home *** CD-ROM | disk | FTP | other *** search
/ Power-Programmierung / CD1.mdf / magazine / drdobbs / 1991 / 08 / dflat5 / menubar.c < prev    next >
Text File  |  1991-06-27  |  9KB  |  363 lines

  1. /* ---------------- menubar.c -------------- */
  2.  
  3. #include <stdio.h>
  4. #include <stdlib.h>
  5. #include <string.h>
  6. #include <ctype.h>
  7. #include <dos.h>
  8. #include "dflat.h"
  9.  
  10. static void reset_menubar(WINDOW);
  11. static int TestGlobalKeys(WINDOW, PARAM, PARAM);
  12. static void SkipSystemWindows(void);
  13.  
  14. static struct {
  15.     int x1, x2;        /* position in menu bar */
  16.     char sc;        /* shortcut key value   */
  17. } menu[10];
  18. static int mctr;
  19.  
  20. MENU *ActiveMenu = NULL;
  21. int ActiveSelection = -1;
  22. WINDOW MenuBar = NULLWND;
  23.  
  24. static WINDOW mwnd = NULL;
  25. static int Selecting = FALSE;
  26.  
  27. int MenuBarProc(WINDOW wnd, MESSAGE msg, PARAM p1, PARAM p2)
  28. {
  29.     int offset = 3, wd, offset1, i, j;
  30.     MENU *mnu;
  31.     int rtn;
  32.     static AltDown = FALSE;
  33.  
  34.     switch (msg)    {
  35.         case CREATE_WINDOW:
  36.             MenuBar = wnd;
  37.             reset_menubar(wnd);
  38.             break;
  39.         case SETFOCUS:
  40.             rtn = BaseWndProc(MENUBAR, wnd, msg, p1, p2);
  41.             if ((int) p1)    {
  42.                 if (ActiveSelection == -1)
  43.                     ActiveSelection = 0;
  44.                 if (inFocus == wnd)
  45.                     SendMessage(wnd, PAINT, 0, 0);
  46.             }
  47.             else    {
  48.                 SendMessage(wnd, PAINT, 0, 0);
  49. #ifdef INCLUDE_STATUSBAR
  50.                 SendMessage(GetParent(wnd), ADDSTATUS, 0, 0);
  51. #endif
  52.             }
  53.             return rtn;
  54.         case COMMAND:
  55.             ActiveSelection = -1;
  56.             SetPrevFocus(wnd);
  57.             PostMessage(GetParent(wnd), msg, p1, p2);
  58.             return TRUE;
  59.         case BUILDMENU:
  60.             reset_menubar(wnd);
  61.             mctr = 0;
  62.             ActiveMenu = (MENU *) p1;
  63.             while (ActiveMenu->Title != NULL)    {
  64.                 char *cp;
  65.                 GetText(wnd) = realloc(GetText(wnd), strlen(GetText(wnd))+5);
  66.                 memmove(GetText(wnd) + offset+4, GetText(wnd) + offset, strlen(GetText(wnd))-offset+1);
  67.                 CopyCommand(GetText(wnd)+offset, ActiveMenu->Title, FALSE,
  68.                     cfg.clr [MENUBAR] [STD_COLOR] [BG]);
  69.                 menu[mctr].x1 = offset;
  70.                 offset += strlen(ActiveMenu->Title) + (3+MSPACE);
  71.                 menu[mctr].x2 = offset-MSPACE;
  72.                 cp = strchr(ActiveMenu->Title, SHORTCUTCHAR);
  73.                 if (cp)
  74.                     menu[mctr].sc = tolower(*(cp+1));
  75.                 ActiveMenu++;
  76.                 mctr++;
  77.             }
  78.             ActiveMenu = (MENU *) p1;
  79.             break;
  80.         case PAINT:    
  81.             if (!isVisible(wnd))
  82.                 break;
  83.  
  84. #ifdef INCLUDE_STATUSBAR
  85.             if (wnd == inFocus)
  86.                 SendMessage(GetParent(wnd), ADDSTATUS, 0, 0);
  87. #endif
  88.             SetStandardColor(wnd);
  89.             ClearAttribute(wnd, NOCLIP);
  90.  
  91.             clipline(wnd, 0, GetText(wnd));
  92.             wputs(wnd, GetText(wnd), 0, 0);
  93.  
  94.             AddAttribute(wnd, NOCLIP);
  95.             if (ActiveSelection != -1 &&
  96.                     (wnd == inFocus || mwnd != NULLWND))    {
  97.                 char sel[80], *cp;
  98.                 offset = menu[ActiveSelection].x1;
  99.                 offset1 = menu[ActiveSelection].x2;
  100.                 GetText(wnd)[offset1] = '\0';
  101.                 SetReverseColor(wnd);
  102.                 memset(sel, '\0', sizeof sel);
  103.                 strcpy(sel, GetText(wnd)+offset);
  104.                 cp = strchr(sel, CHANGECOLOR);
  105.                 if (cp != NULL)
  106.                     *(cp + 2) = background | 0x80;
  107.                 wputs(wnd, sel, offset-ActiveSelection*4, 0);
  108.                 GetText(wnd)[offset1] = ' ';
  109. #ifdef INCLUDE_STATUSBAR
  110.                 if (!Selecting && mwnd == NULLWND && wnd == inFocus)    {
  111.                     char *st = ActiveMenu[ActiveSelection].StatusText;
  112.                     if (st != NULL)
  113.                         SendMessage(GetParent(wnd), ADDSTATUS, (PARAM)st, 0);
  114.                 }
  115. #endif
  116.             }
  117.             return FALSE;
  118.         case SHIFT_CHANGED:
  119.             if (mwnd == NULLWND)    {
  120.                 if ((int)p1 & ALTKEY)
  121.                     AltDown = TRUE;
  122.                 else if (AltDown)
  123.                     SendMessage(wnd, KEYBOARD,
  124.                         wnd == inFocus ? ESC : F10, 0);
  125.             }
  126.             return TRUE;
  127.         case KEYBOARD:
  128.             AltDown = FALSE;
  129.             if (mwnd == NULLWND)    {
  130.                 /* ----- search for menu bar shortcut keys ---- */
  131.                 int c = tolower((int)p1);
  132.                 int a = AltConvert((int)p1);
  133.                 for (j = 0; j < mctr; j++)    {
  134.                     if ((inFocus == wnd && menu[j].sc == c) ||
  135.                             (a && menu[j].sc == a))    {
  136.                         if (inFocus != wnd)
  137.                             SendMessage(wnd, SETFOCUS, TRUE, 0);
  138.                         SendMessage(wnd, SELECTION, j, 0);
  139.                         return FALSE;
  140.                     }
  141.                 }
  142.             }
  143.             /* -------- search for accelerator keys -------- */
  144.             mnu = ActiveMenu;
  145.             while (mnu->Title != NULL)    {
  146.                 struct PopDown *pd = mnu->Selections;
  147.                 if (mnu->PrepMenu)
  148.                     (*(mnu->PrepMenu))(GetParent(wnd), mnu);
  149.                 while (pd->SelectionTitle != NULL)    {
  150.                     if (pd->Accelerator == (int) p1)    {
  151.                         if (pd->Attrib & INACTIVE)
  152.                             beep();
  153.                         else    {
  154.                             if (GetClass(inFocus) == MENUBAR)
  155.                                 SetPrevFocus(inFocus);
  156.                             PostMessage(GetParent(wnd),
  157.                                 COMMAND, pd->ActionId, 0);
  158.                         }
  159.                         return TRUE;
  160.                     }
  161.                     pd++;
  162.                 }
  163.                 mnu++;
  164.             }
  165.             if (TestGlobalKeys(wnd, p1, p2))
  166.                 return TRUE;
  167.  
  168.             switch ((int)p1)    {
  169. #ifdef INCLUDE_HELP
  170.                 case F1:
  171.                   if (ActiveMenu != NULL &&
  172.                       (mwnd == NULLWND ||
  173.                         (ActiveMenu+ActiveSelection)->
  174.                             Selections[0].SelectionTitle == NULL)) {
  175.                         DisplayHelp(wnd, (ActiveMenu+ActiveSelection)->Title+1);
  176.                         return TRUE;
  177.                     }
  178.                     break;
  179. #endif
  180.                 case '\r':
  181.                     if (mwnd == NULLWND && ActiveSelection != -1)
  182.                         SendMessage(wnd, SELECTION, ActiveSelection, 0);
  183.                     break;
  184.                 case ESC:
  185.                     if (inFocus == wnd)    {
  186.                         ActiveSelection = -1;
  187.                         SetPrevFocus(wnd);
  188.                         SendMessage(wnd, PAINT, 0, 0);
  189.                     }
  190.                     break;
  191.                 case FWD:
  192.                     ActiveSelection++;
  193.                     if (ActiveSelection == mctr)
  194.                         ActiveSelection = 0;
  195.                     if (mwnd != NULLWND)
  196.                         SendMessage(wnd, SELECTION, ActiveSelection, 0);
  197.                     else 
  198.                         SendMessage(wnd, PAINT, 0, 0);
  199.                     break;
  200.                 case BS:
  201.                     if (ActiveSelection == 0)
  202.                         ActiveSelection = mctr;
  203.                     --ActiveSelection;
  204.                     if (mwnd != NULLWND)
  205.                         SendMessage(wnd, SELECTION, ActiveSelection, 0);
  206.                     else 
  207.                         SendMessage(wnd, PAINT, 0, 0);
  208.                     break;
  209.                 default:
  210.                     break;
  211.             }
  212.             return FALSE;
  213.         case LEFT_BUTTON:
  214.             i = BarSelection((int) p1 - GetLeft(wnd));
  215.             if (i < mctr)
  216.                 if (i != ActiveSelection || mwnd == NULLWND)
  217.                     SendMessage(wnd, SELECTION, i, 0);
  218.             return TRUE;
  219.         case SELECTION:
  220.             Selecting = TRUE;
  221.             if (mwnd != NULLWND)
  222.                 SendMessage(mwnd, CLOSE_WINDOW, 0, 0);
  223.             mwnd = NULLWND;
  224.             ActiveSelection = (int) p1;
  225.             offset = menu[ActiveSelection].x1 -
  226.                         4 * ActiveSelection;
  227.             mnu = ActiveMenu+ActiveSelection;
  228.             if (mnu->PrepMenu != NULL)
  229.                 (*(mnu->PrepMenu))(GetParent(wnd), mnu);
  230.             wd = MenuWidth(mnu->Selections);
  231.             if (offset > WindowWidth(wnd)-wd)
  232.                 offset = WindowWidth(wnd)-wd;
  233.             mwnd = CreateWindow(POPDOWNMENU, NULL,
  234.                         GetLeft(wnd)+offset, GetTop(wnd)+1,
  235.                         MenuHeight(mnu->Selections),
  236.                         wd,
  237.                         NULL,
  238.                         wnd,
  239.                         NULL,
  240.                         0);
  241. #ifdef INCLUDE_SHADOWS
  242.             AddAttribute(mwnd, SHADOW);
  243. #endif
  244.             if (mnu->Selections[0].SelectionTitle != NULL)    {
  245.                 SendMessage(mwnd, BUILD_SELECTIONS, (PARAM) mnu, 0);
  246.                 SendMessage(mwnd, SETFOCUS, TRUE, 0);
  247.             }
  248.             else
  249.                 SendMessage(wnd, PAINT, 0, 0);
  250.             Selecting = FALSE;
  251.             break;
  252.         case BORDER:
  253.             return TRUE;
  254.         case INSIDE_WINDOW:
  255.             return InsideRect(p1, p2, WindowRect(wnd));
  256.         case CLOSE_POPDOWN:
  257.             if ((int)p1)
  258.                 PostMessage(wnd, KEYBOARD, ESC, 0);
  259.             mwnd = NULLWND;
  260.             break;
  261.         case CLOSE_WINDOW:
  262.             rtn = BaseWndProc(MENUBAR, wnd, msg, p1, p2);
  263.             if (GetText(wnd) != NULL)    {
  264.                 free(GetText(wnd));
  265.                 GetText(wnd) = NULL;
  266.             }
  267.             mctr = 0;
  268.             ActiveSelection = -1;
  269.             MenuBar = NULL;
  270.             ActiveMenu = NULL;
  271.             return rtn;
  272.         default:
  273.             break;
  274.     }
  275.     return BaseWndProc(MENUBAR, wnd, msg, p1, p2);
  276. }
  277.  
  278. static void reset_menubar(WINDOW wnd)
  279. {
  280.     GetText(wnd) = realloc(GetText(wnd), SCREENWIDTH+5);
  281.     memset(GetText(wnd), ' ', SCREENWIDTH);
  282.     *(GetText(wnd)+SCREENWIDTH-
  283.         (TestAttribute(GetParent(wnd), HASBORDER) ? 2 : 0)) = '\0';
  284. }
  285.  
  286. static int TestGlobalKeys(WINDOW wnd, PARAM p1, PARAM p2)
  287. {
  288.     switch ((int)p1)    {
  289.         case F10:
  290.             if (MenuBar != NULLWND)
  291.                 SendMessage(MenuBar, SETFOCUS, TRUE, 0);
  292.             return TRUE;
  293.         case ALT_F6:
  294.             if (GetClass(inFocus) == POPDOWNMENU)
  295.                 return TRUE;
  296.             SetNextFocus(inFocus);
  297.             SkipSystemWindows();
  298.             return TRUE;
  299. #ifdef INCLUDE_SYSTEM_MENUS
  300.         case ALT_HYPHEN:
  301.             if (GetClass(inFocus) == POPDOWNMENU)
  302.                 SendMessage(inFocus, CLOSE_WINDOW, 0, 0);
  303.             if (GetClass(GetParent(inFocus)) == APPLICATION)
  304.                 BuildSystemMenu(GetParent(inFocus));
  305.             return TRUE;
  306.         case ' ':
  307.             if ((int)p2 & ALTKEY)    {
  308.                 if (GetClass(inFocus) == POPDOWNMENU)
  309.                     SendMessage(inFocus, CLOSE_WINDOW, 0, 0);
  310.                 if (GetClass(inFocus) != MENUBAR &&
  311.                         TestAttribute(inFocus, HASTITLEBAR) &&
  312.                             TestAttribute(inFocus, CONTROLBOX))
  313.                     BuildSystemMenu(inFocus);
  314.                 return TRUE;
  315.             }
  316.             break;
  317. #endif
  318.         case CTRL_F4:
  319.             if (GetClass(inFocus) != MENUBAR)
  320. #ifdef INCLUDE_STATUSBAR
  321.                 if (GetClass(inFocus) != STATUSBAR)
  322. #endif
  323.                     if (GetClass(inFocus) != APPLICATION)    {
  324.                         SendMessage(inFocus, CLOSE_WINDOW, 0, 0);
  325.                         SkipSystemWindows();
  326.                     }
  327.             break;
  328.         case ALT_F4:
  329.             PostMessage(GetParent(wnd), CLOSE_WINDOW, 0, 0);
  330.             break;
  331.         default:
  332.             break;
  333.     }
  334.     return FALSE;
  335. }
  336.  
  337. static void SkipSystemWindows(void)
  338. {
  339.     int cl, ct = 0;
  340.     while ((cl = GetClass(inFocus)) == MENUBAR ||
  341.             cl == APPLICATION
  342. #ifdef INCLUDE_STATUSBAR
  343.          || cl == STATUSBAR
  344. #endif
  345.                                 )    {
  346.         SetNextFocus(inFocus);
  347.         if (++ct == 3)
  348.             break;
  349.     }
  350. }
  351.  
  352. int BarSelection(int mx)
  353. {
  354.     int i;
  355.     for (i = 0; i < mctr; i++)
  356.         if (mx >= menu[i].x1-4*i &&
  357.                 mx <= menu[i].x2-4*i-5)
  358.             break;
  359.     return i;
  360. }
  361.  
  362.  
  363.