home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / ME22-OS2.ZIP / MACROS.ZIP / MENUBAR.M < prev    next >
Text File  |  1988-07-09  |  12KB  |  518 lines

  1. /*
  2.   MENUBAR
  3.     Macro to implement a simple menubar system for interacting with
  4.     ME. You can change this so that the menu items invoke any editor
  5.     primitive or any user-defined macro. This macro package relies
  6.     on ME's feature of calling internal C functions in order to
  7.     display the menubar and submenus.
  8.  
  9.     The menubar definiton should be in a file with an .MNU extension.
  10.     In this macro, the CTRL-B key is used to bring up the menubar; you
  11.     can change this key by altering the assign_key() call in the init()
  12.     function here.
  13.     
  14.     The menubar definition must be in the following format :
  15.  
  16.     [optional comment lines]
  17.     .....
  18.     MENUBAR menu-name [COLOR color]
  19.     {
  20.       text-of-menubar-item-1
  21.      [MENU
  22.       {
  23.         subpopup1-text     [->function-to-call]
  24.       ......
  25.       }]
  26.     }
  27.     
  28.     Please note that items enclosed by square brackets are optional. In this
  29.     case, the subpopup definition after a menubar item is optional. Also,
  30.     the function to invoke after an item is chosed is optional. Look at the
  31.     accompanying file MENUBAR.MNU for an actual menubar definition. The
  32.     menubar definition starts with first line with the word MENUBAR starting 
  33.     at column 1. 
  34.     
  35.     (C) Copyright 1988   Marc Adler/Magma Systems    All Rights Reserved
  36. */
  37.  
  38. #define HORIZ 1
  39. #define VERT  2
  40. #define TOP_LEFT  3
  41. #define TOP_RIGHT 4
  42. #define BOT_LEFT  5
  43. #define BOT_RIGHT 6
  44.  
  45. #define DOWN    208
  46. #define UP      200
  47. #define LEFT    203
  48. #define RIGHT   205
  49.  
  50. #define MAXMENUBARITEMS 16
  51.  
  52. string BoxChars[10];
  53.  
  54. int    MenuRow1, MenuCol1, MenuRow2, MenuCol2;
  55. int    MenuColor;
  56. string MenuName;
  57. int    MenubarBuf;
  58. int    MenubarItemBufID;
  59.  
  60. int debug;
  61. int MenubarWindow;
  62. int    MenuBuf[MAXMENUBARITEMS];
  63. string MenuNames[MAXMENUBARITEMS];
  64. int    PopupWindow[MAXMENUBARITEMS];
  65. int NumMenus;
  66. string MenubarText;
  67. int CurrMenuItem;
  68.  
  69. int    OriginalFileBufID;
  70.  
  71.  
  72. /*
  73.   Init() - initialization function - done once when the macro is loaded
  74. */
  75. init()
  76. {
  77.   /* Set up the values for box-drawing characters */
  78.   BoxChars[HORIZ]     = "═";
  79.   BoxChars[VERT]      = "║";
  80.   BoxChars[TOP_LEFT]  = "╔";
  81.   BoxChars[TOP_RIGHT] = "╗";
  82.   BoxChars[BOT_LEFT]  = "╚";
  83.   BoxChars[BOT_RIGHT] = "╝";
  84.   
  85.   /* Set the dimensions of the menubar */
  86.   MenuRow1 = 1;
  87.   MenuCol1 = 0;
  88.   MenuRow2 = 3;
  89.   MenuCol2 = 79;
  90.  
  91.   /* CTRL-B will invoke the default menubar macro */
  92.   assign_key("do_default_menu", 2);
  93. }
  94.  
  95. do_default_menu()
  96. {
  97.   do_menu("menubar");
  98. }
  99.  
  100.  
  101. /*
  102.   Do_Menu() - driver for reading, parsing, and displaying a menubar. The
  103.               passed argument is the root part of the menubar file name.
  104. */
  105. do_menu(menuname)
  106.   string menuname;
  107. {
  108.   debug = 0;
  109.   menubar_already_here = 0;
  110.  
  111.   OriginalFileBufID = old_buf = currbuf();
  112.  
  113.   /* Open the Menubar definition file if it doesn't exist already. */
  114.   if (!index(menuname, ".mnu"))
  115.     menuname = strcat(menuname, ".mnu");
  116.  
  117.   if ((MenubarBuf = find_buffer(menuname)) <= 0)
  118.     MenubarBuf = create_buffer(menuname);
  119.   else
  120.     menubar_already_here = 1;
  121.   new_buf = setcurrbuf(MenubarBuf);
  122.   setcol(1);
  123.   vidsetcursor(32, 0);
  124.  
  125.   /* Parse the defn. If there's an error, abort. */
  126.   if (!menubar_already_here)
  127.   {
  128.     if (MenuParse() < 0)
  129.     {
  130.       delete_buffer(new_buf);
  131.       show_buffer(old_buf);
  132.       return;
  133.     }
  134.   }
  135.   
  136.   /* Create a window for the menubar and attach the menubar buffer to it. */
  137.   /* This is the ME paradigm for creating popup windows.                  */
  138.   MenubarWindow = create_window(MenuRow1+1,MenuCol1+1,MenuRow2-1,MenuCol2-1,MenuColor);
  139.   attach_window(MenubarWindow, new_buf);
  140.   gobof();
  141.   DrawBox(0, 0, 2, 79, MenuColor);
  142.  
  143.   /* Everything is displayed --- get the user input */
  144.   MenubarProcess();
  145.  
  146.   /* After we're done, get rid of the menubar's window, */
  147.   /* and go back to the file we were editing.           */
  148.   remove_window(MenubarWindow);
  149.   show_buffer(old_buf);
  150.   refresh();
  151. }
  152.  
  153.  
  154. /*
  155.   MenuParse() - parse the menubar defn which is in the menubar buffer.
  156.                 Returns 1 if everything went OK, -1 if there was an error.
  157. */
  158. MenuParse()
  159. {
  160.   int old_buf, new_buf;
  161.  
  162.   /* Span all initial comment lines */
  163.   while (index(currline(), "MENUBAR") != 1)
  164.     if (!down())
  165.       return -1;
  166.  
  167.   /* The first token should be the word "MENUBAR" */
  168.   if (get_token() != "MENUBAR")
  169.   {
  170.     get_tty_str("The file is not a menubar definition file");
  171.     return -1;
  172.   }
  173.  
  174.   /* The next token is the name of the menubar */
  175.   MenuName = get_token();
  176.   
  177.   /*
  178.     The cursor is either at the COLOR or the name of the first item
  179.   */
  180.   if ((s = get_token()) == "COLOR")
  181.     MenuColor = get_int_token();
  182.   else
  183.     MenuColor = 07;
  184.  
  185.   old_buf = currbuf();
  186.   NumMenus = 1;
  187.  
  188.   while (1)
  189.   {
  190.     /* The token should be the name of the popup */
  191.     go_past_func = index(currline(), "->");
  192.  
  193.     if ((mname = get_token()) == "" || mname == "}")
  194.       break;
  195.     /* After this, the token ptr should be at the first item of the popup */
  196.     MenuNames[NumMenus] = mname;
  197.  
  198.     if (go_past_func)
  199.     {
  200.       down();
  201.       gobol();
  202.     }
  203.  
  204.     if (index(currline(), "MENU") > 0)
  205.     {
  206.       MenuBuf[NumMenus] = new_buf = create_buffer(strcat(mname, ".men"));
  207.       down();
  208.       if (index(ltrim(currline()), "{"))
  209.       {
  210.         down();
  211.         gobol();
  212.       }
  213.     }
  214.     else
  215.       MenuBuf[NumMenus] = new_buf = 0;
  216.     NumMenus++;
  217.  
  218.     if (debug)
  219.       get_tty_str("The name of the popup is [%s]", mname);
  220.  
  221.     itemcnt = 1;
  222.  
  223.     if (new_buf)        /* We have a submenu */
  224.     {
  225.       /* Get each line until we encounter a line with a right curly brace. */
  226.       /* Insert the entire line into the buffer which holds the submenu.   */
  227.       while (index(cl = ltrim(currline()), "}") == 0)
  228.       {
  229.         if (debug)
  230.           get_tty_str("Inserting item [%s]", cl);
  231.         oldcol = currcol();
  232.         setcurrbuf(new_buf);
  233.         if (itemcnt > 1)
  234.         {
  235.           goeol();
  236.           insert("\n");
  237.         }
  238.         gobol();
  239.         insert(ltrim(cl));
  240.         itemcnt++;
  241.  
  242.         setcurrbuf(old_buf);
  243.         setcol(oldcol);
  244.         if (!down())
  245.           break;
  246.         gobol();
  247.       } /* end while */
  248.       
  249.       /* Move to the next line after the right curly brace */
  250.       if (!down() || currline() == "")
  251.         break;
  252.       gobol();
  253.     } /* end if submenu */
  254.   } /* end while */
  255.   
  256.   /* We form the menubar's text line by concatinating the menubar items. */
  257.   /* We then stick this line on top of the menubar buffer. Since the     */
  258.   /* menubar window only shows 1 line, this is the line that we'll see.  */
  259.   MenubarText = MenuNames[1];
  260.   for (i = 2;  i <= NumMenus;  i++)
  261.     MenubarText = sprintf("%s   %s", MenubarText, MenuNames[i]);
  262.   gobof();
  263.   insert(MenubarText);  insert("\n");
  264.   gobol();
  265.     
  266.   /* Success!!! */
  267.   return 1;
  268. }
  269.  
  270.  
  271. get_token()
  272. {
  273.   string s;
  274.  
  275.   if (is_eol() || currchar() == ' ')
  276.     if (!nextword())
  277.       return "";
  278.  
  279.   if (is_eof())
  280.     return "";
  281.  
  282.   start = currcol();
  283.   while (!is_eol() && currchar() != ' ')
  284.     right();
  285.   s = substr(currline(), start, currcol() - start);
  286.   nextword();
  287.   if (debug)
  288.     get_tty_str(sprintf("GET_TOKEN returns [%s]", s));
  289.   return s;
  290. }
  291.  
  292. get_int_token()
  293. {
  294.   n = atoi(get_token());
  295.   if (debug)
  296.     get_tty_str(sprintf("GET_INT_TOKEN - n is %d", n));
  297.   return n;
  298. }
  299.  
  300. /* ------------------------- MENU PROCESSING ------------------------- */
  301.  
  302. #define ESC   27
  303. #define UP    200
  304. #define DOWN  208
  305.  
  306. MenubarProcess()
  307. {
  308.   CurrMenuItem = 1;
  309.  
  310. do_it:
  311.   highlite_word(1);
  312.   if (MenuBuf[CurrMenuItem])
  313.   {
  314.     DrawPopup(currcol());
  315.     c = MenuProcess();
  316.     clear_mark();
  317.     if (PopupWindow[CurrMenuItem])
  318.       remove_window(PopupWindow[CurrMenuItem]);
  319.     if (c == '\r' || c == ESC)
  320.       return;
  321.     show_buffer(setcurrbuf(MenubarBuf));
  322.     DrawBox(0, 0, 2, 79, MenuColor);
  323.   }
  324.   else
  325.     c = get_tty_char();
  326.  
  327.   if (c != '\r' && c != ESC)
  328.   {
  329.     switch (c)
  330.     {
  331.       case LEFT :
  332.         MenuLeft();
  333.         break;
  334.       case RIGHT :
  335.         MenuRight();
  336.         break;
  337.       default   :
  338.         bell();
  339.         break;
  340.     }
  341.   }
  342.   goto do_it;
  343. }
  344.  
  345.  
  346. MenuProcess()
  347. {
  348.   markline();
  349.  
  350. do_it:
  351.   while ((c = get_tty_char()) != '\r' && c != ESC)
  352.   {
  353.     switch (c)
  354.     {
  355.       case UP   :
  356.         MenuUp();
  357.         break;
  358.       case DOWN :
  359.         MenuDown();
  360.         break;
  361.       case LEFT :
  362.         return(LEFT);
  363.       case RIGHT :
  364.         return(RIGHT);
  365.       default   :
  366.         bell();
  367.         break;
  368.     }
  369.   }
  370.   
  371.   if (c == '\r')
  372.   {
  373.     cln = currlinenum();
  374.  
  375.     if ((i = index(currline(), "->")) > 0)
  376.     {
  377.       macname = substr(currline(), i+2, 100);
  378.       /*
  379.         If we want to perform the macro on the original file we
  380.         were editing, then we must switch back to the old buffer.
  381.       */
  382.       menubuf = currbuf();
  383.       show_buffer(OriginalFileBufID);
  384.       setprompt(2);
  385.       domacro(macname);
  386.       setprompt(0);
  387.       setcurrbuf(menubuf);
  388.     }
  389.  
  390.     if (debug)
  391.       get_tty_str("After indirect call - before DrawBox");
  392.     DrawBox(MenuRow1-1, MenuCol1, MenuRow2-1, MenuCol2, MenuColor);
  393. /*
  394.     goto do_it;
  395. */
  396.   }
  397.   
  398.   return c;
  399. }
  400.  
  401.  
  402.  
  403. /*
  404.   DrawPopup() - displays a submenu
  405. */
  406. DrawPopup(startcol)
  407. {
  408. /*
  409.  BUGS - figure out how wide the submenu should be
  410. */
  411.   setcurrbuf(MenuBuf[CurrMenuItem]);
  412.   x1 = startcol - 1;
  413.   x2 = x1 + 16;
  414.   wid = create_window(4, x1+1, lastlinenum()+3, x2-1, 7);
  415.   attach_window(wid, MenuBuf[CurrMenuItem]);
  416.   PopupWindow[CurrMenuItem] = wid;
  417.   gobof();
  418.   DrawBox(2, x1, lastlinenum()+3, x2, MenuColor);
  419. }
  420.  
  421. /*
  422.   HighliteWord() - draws the current word with highliting (if rev is 1)
  423. */
  424. highlite_word(rev)
  425. {
  426.   /* Determine the proper attribute to draw the word with */
  427.   if (rev)
  428.     rev = (MenuColor % 16) * 16 + (MenuColor / 16);
  429.   else
  430.     rev = MenuColor;
  431.  
  432.   /* Get the starting & ending columns of the word */
  433.   col = currcol();
  434.   endpos = index(substr(currline(), col, 100), " ") + col - 1;
  435.   word = substr(currline(), col, endpos - col);
  436.  
  437.   /* Redraw the word with the specified attribute */
  438.   display(1, col, endpos-1, rev, word);
  439. }
  440.  
  441.  
  442. /*
  443.   MenuLeft() - move left one item in the menubar
  444. */
  445. MenuLeft()
  446. {
  447.   highlite_word(0);
  448.   if (!is_bol())
  449.     CurrMenuItem--;
  450.   prevword();
  451.   highlite_word(1);
  452. }
  453.  
  454. /*
  455.   MenuRight() - move right one item in the menubar
  456. */
  457. MenuRight()
  458. {
  459.   if (index(substr(currline(), currcol(), 100), " ") > 0)
  460.   {
  461.     highlite_word(0);           /* remove highliting */
  462.     if (!is_eol())
  463.       CurrMenuItem++;
  464.     nextword();                 /* move to the next item */
  465.     highlite_word(1);           /* highlite the new item */
  466.   }
  467. }
  468.  
  469. /*
  470.   MenuUp() - move up one line in the submenu
  471. */
  472. MenuUp()
  473. {
  474.   if (currlinenum() > 1)
  475.   {
  476.     clear_mark();       /* remove highlite from the old line */
  477.     up();
  478.     markline();         /* highlight the new line */
  479.   }
  480. }
  481.  
  482. /*
  483.   MenuDown() - move down one line in the submenu
  484. */
  485. MenuDown()
  486. {
  487.   if (currlinenum() < lastlinenum())
  488.   {
  489.     clear_mark();       /* remove highlite from the old line */
  490.     down();
  491.     markline();         /* highlight the new line */
  492.   }
  493. }
  494.  
  495.  
  496. /*
  497.   DrawBox() - draws a box using the passed coordinates and attribute.
  498. */
  499. DrawBox(row1, col1, row2, col2, color)
  500. {
  501.   width = col2 - col1 + 1;
  502.   horiz_line = repstr(BoxChars[HORIZ], width - 2);
  503.   blank_line = repstr(" ", width - 2);
  504.  
  505.   display(row1, col1 + 1, col1 + width - 1,  color, horiz_line);
  506.   display(row2, col1 + 1, col1 + width - 1,  color, horiz_line);
  507.   for (r = row1+1;  r < row2;  r++)
  508.   {
  509.     display(r, col1, col1, color, BoxChars[VERT]);
  510.     display(r, col2, col2, color, BoxChars[VERT]);
  511.   }
  512.   display(row1, col1, col1,  color, BoxChars[TOP_LEFT]);
  513.   display(row1, col2, col2,  color, BoxChars[TOP_RIGHT]);
  514.   display(row2, col1, col1,  color, BoxChars[BOT_LEFT]);
  515.   display(row2, col2, col2,  color, BoxChars[BOT_RIGHT]);
  516. }
  517.  
  518.