home *** CD-ROM | disk | FTP | other *** search
/ Hall of Fame / HallofFameCDROM.cdr / window / mewel12.lzh / MENUGEN.C < prev    next >
C/C++ Source or Header  |  1989-07-21  |  33KB  |  1,183 lines

  1. /*===========================================================================*/
  2. /*                                                                           */
  3. /* File    : MENUGEN.C                                                       */
  4. /*                                                                           */
  5. /* Purpose : A simple menu editor designed for demo purposes.                */
  6. /*           Menugen lets you design a pulldown menu system for your         */
  7. /*           application. You can append, insert, change, and delete menubar */
  8. /*           or pulldown menu entries, and then save them in a .RC file.     */
  9. /*                                                                           */
  10. /* History : Created by Marc Adler 7/20/89                                   */
  11. /*                                                                           */
  12. /* (C) Copyright 1989 Marc Adler/Magma Systems     All Rights Reserved       */
  13. /*===========================================================================*/
  14.  
  15. #include <stdio.h>
  16. #include <string.h>
  17. #include "window.h"
  18. #include "keys.h"
  19. #include "rc.h"
  20. #include "menugen.h"
  21.  
  22. /*
  23.   External functions
  24. */
  25. extern int  pascal MainWndProc();
  26. extern int  pascal MenuWindowWndProc();
  27. extern BOOL pascal MenuItemDlgProc();
  28. extern HWND pascal DialogCreateIndirect();
  29. extern HMENU MenuList();
  30.  
  31. /*
  32.   Globals
  33. */
  34. HWND  hMain;          /* handle of main window */
  35. HWND  hStatus;        /* handle of status window */
  36. HWND  hWndMenu;       /* handle to the window which holds the test menubar */
  37. HDLG  hItemDlg;       /* handle to the menu editing dialog box */
  38. HMENU hMenuBar = NULLHWND; /* handle of the test menubar */
  39. char  CurrFileName[65] = { '\0' };
  40. #define MODE_MENUBAR  1
  41. #define MODE_POPUP    2
  42. WORD CurrMode = MODE_MENUBAR;
  43.  
  44. #define ID_ITEM 900
  45. WORD idLastItem = ID_ITEM;  /* keeps track of the last identifier given out */
  46.  
  47. /*
  48.   A structure to hold the current menu item status 
  49. */
  50. typedef struct menuitem
  51. {
  52.   char szItemText[80];
  53.   WORD idItem;
  54.   WORD fMask;
  55.   HMENU hMenu;
  56. } MENUITEM;
  57. MENUITEM CurrItem;
  58.  
  59. /*
  60.   Menu attribute-to-string mapping table
  61. */
  62. typedef struct attrinfo
  63. {
  64.   WORD fBitMask;
  65.   char *szAttr;
  66. } ATTRINFO;
  67. ATTRINFO AttrInfo[] =
  68. {
  69.   MF_CHECKED,   "CHECKED",
  70.   MF_DISABLED,  "DISABLED",
  71.   MF_SEPARATOR, "SEPARATOR",
  72.   MF_SHADOW,    "SHADOW",
  73.   MF_HELP,      "HELP",
  74. };
  75.  
  76.  
  77. main(argc, argv)
  78.   int  argc;
  79.   char **argv;
  80. {
  81.   WORD   hRes;
  82.   HMENU  hBar;
  83.   EVENT  event;
  84.   HACCEL hAccel;
  85.  
  86.  
  87.   /*
  88.     Process any command line arguments
  89.   */
  90.   if (argc >= 2)
  91.   {
  92.     int i;
  93.     for (i = 1;  i < argc;  i++)
  94.     {
  95.       char *arg = argv[i];
  96.       if (*arg == '-' || *arg == '/')
  97.         switch (*++arg)
  98.         {
  99.           case 'm' :               /* -m => use mono attributes */
  100.             WinUseMonoMap(TRUE);
  101.             break;
  102.         }
  103.       else
  104.         break;
  105.     }
  106.   }
  107.  
  108.   /*
  109.     Initialize the window system - this *must* be done once in every appl
  110.   */
  111.   WinInit();
  112.  
  113.   /*
  114.     Create the main window and set the main window procedure
  115.   */
  116.   hMain = CreateWindow("Normal",            /* class name */
  117.                        "Menu Generator",    /* window title */
  118.                        WIN_HAS_BORDER,      /* window flags */
  119.                        0,0, 80,24,          /* dimensions */
  120.                        0x17,                /* color */
  121.                        1,                   /* id */
  122.                        NULLHWND,            /* hParent */
  123.                        (HMENU) NULLHWND,    /* menu */
  124.                        0,                   /* HINST */
  125.                        (DWORD) NULL);       /* creation params */
  126.   WinSetWinProc(hMain, MainWndProc);
  127.  
  128.   /*
  129.     Create the menu test window...
  130.   */
  131.   hWndMenu = CreateWindow("Normal",         /* class name */
  132.                          "Current Menu",    /* window title */
  133.                          WIN_HAS_BORDER,    /* window flags */
  134.                          1,3, 78,5,         /* dimensions */
  135.                          0x57,              /* color */
  136.                          0,                 /* id */
  137.                          hMain,             /* hParent */
  138.                          (HMENU) NULLHWND,  /* menu */
  139.                          0,                 /* HINST */
  140.                          (DWORD) NULL);     /* creation params */
  141.   WinSetWinProc(hWndMenu, MenuWindowWndProc);
  142.  
  143.   /*
  144.     Create the status window...
  145.   */
  146.   hStatus = CreateWindow("Normal",          /* class name */
  147.                          NULL,              /* window title */
  148.                          0x0000L,           /* window flags */
  149.                          0,24, 80,1,        /* dimensions */
  150.                          0x31,              /* color */
  151.                          0,                 /* id */
  152.                          hMain,             /* hParent */
  153.                          (HMENU) NULLHWND,  /* menu */
  154.                          0,                 /* HINST */
  155.                          (DWORD) NULL);     /* creation params */
  156.                                             
  157.  
  158.   /*
  159.     Load the main menubar in from the external resource file MENUGEN.RES.
  160.     Alternatively, we can also do a bunch of CreateMenu()'s, but using
  161.     a resource file lets us modify our menus more easily.
  162.   */
  163.   hRes = OpenResourceFile("menugen");
  164.   if (!hRes)
  165.   {
  166.     printf("Can't open menugen.res\n");
  167.     exit(1);
  168.   }
  169.   hBar = LoadMenu(hRes, ID_MENUBAR, hMain);
  170.   SetMenu(hMain, hBar);
  171.   CheckMenuItem(hBar, ID_MODE_BAR, MF_BYCOMMAND | MF_CHECKED);
  172.   CloseResourceFile(hRes);
  173.  
  174.   /*
  175.     Set up the accelerator table and keys.
  176.     F1 invokes help and ALT-X exits.
  177.   */
  178.   hAccel = AcceleratorCreate();
  179.   AcceleratorSetFocus(hAccel);
  180.   AcceleratorSetKey(ID_EXIT, VK_ALT_X);
  181.   AcceleratorSetKey(ID_HELP, VK_F1);
  182.   AcceleratorSetKey(ID_OPEN, VK_ALT_O);
  183.   AcceleratorSetWnd(hMain);
  184.  
  185.   /*
  186.     Set the input focus to the main window. This will also draw the window.
  187.   */
  188.   SetFocus(hMain);
  189.  
  190.   /*
  191.     Read in the initial dialog box
  192.   */
  193.   if (argc > 1)
  194.   {
  195.     char fname[80];
  196.     /*
  197.       Append a .RES extension
  198.     */
  199.     strcpy(fname, argv[1]);
  200.     ChangeExtension(fname, ".res");
  201.     if ((hMenuBar = MenuList(fname)))
  202.     {
  203.       ChangeExtension(fname, ".rc");
  204.       strcpy(CurrFileName, fname);
  205.       SetMenu(hWndMenu, hMenuBar);
  206.     }
  207.   }
  208.  
  209.   /*
  210.     If we have no initial menubar to work with, create a dummy one
  211.     with one menubar item and one associated pulldown item.
  212.   */
  213.   if (hMenuBar == NULLHWND)
  214.   {
  215.     HMENU hPop;
  216.     hMenuBar = CreateMenu(hWndMenu);
  217.     hPop = CreateMenu(hMenuBar);
  218.     CreateDefaultPopup(hPop, 0x0000);
  219.     ChangeMenu(hMenuBar, 0, "~Dummy", hPop, MF_POPUP | MF_APPEND);
  220.   }
  221.  
  222.   /*
  223.     Set the new menu bar and refresh the window
  224.   */
  225.   SetMenu(hWndMenu, hMenuBar);
  226.   DrawMenuBar(hMenuBar);
  227.  
  228.   /*
  229.     Main message loop
  230.   */
  231.   for (;;)
  232.   {
  233.     GetMessage(&event);
  234.     TranslateAccelerator(&event);
  235.     /*
  236.       We trap the right-button-down messages before they get swallowed
  237.       up by the default menu window proc.
  238.     */
  239.     if (event.message == WM_RBUTTONDOWN)
  240.       MenuWindowWndProc(event.hWnd, event.message, event.wParam, event.lParam);
  241.     else
  242.       DispatchMessage(&event);
  243.   }
  244. }
  245.  
  246.  
  247. /*
  248.   MainWndProc - window procedure for the main window
  249. */
  250. pascal MainWndProc(hWnd, message, wParam, lParam)
  251.   HWND hWnd;
  252.   WORD message;
  253.   WORD wParam;
  254.   DWORD lParam;
  255. {
  256.   switch (message)
  257.   {
  258.     case WM_COMMAND    :
  259.       switch (wParam)
  260.       {
  261.         case ID_OPEN   :
  262.           if (DlgOpenFile(NULLHWND, "*.res", CurrFileName))
  263.           {
  264.             if ((hMenuBar = MenuList(CurrFileName)))
  265.             {
  266.               ChangeExtension(CurrFileName, ".rc");
  267.               SetMenu(hWndMenu, hMenuBar);
  268.               DrawMenuBar(hMenuBar);
  269.             }
  270.           }
  271.           break;
  272.  
  273.         case ID_SAVE   :
  274.           if (CurrFileName[0])
  275.           {
  276.             GenerateRCCode(hMenuBar, CurrFileName);
  277.             break;
  278.           }    
  279.           /* fall into ... */
  280.  
  281.         case ID_SAVEAS :
  282.           SaveFileDlg();
  283.           break;
  284.  
  285.         case ID_GENERATE    :
  286.           GenerateRCCode(hMenuBar, "foo.c");
  287.           break;
  288.  
  289.         case ID_HELP :
  290.           HelpDialog();
  291.           break;
  292.  
  293.         case ID_EXIT :
  294.           exit(0);
  295.       }
  296.       break;
  297.  
  298.     case WM_HELP       :
  299.       HelpDialog();
  300.       break;
  301.  
  302.     case WM_QUIT       :
  303.       /* End the menu editor */
  304.       exit(0);
  305.  
  306.     default :
  307.       /* Call the default window procedure for the main window */
  308.       return DefWinProc(hWnd, message, wParam, lParam);
  309.   }
  310.  
  311.   return FALSE;
  312. }
  313.  
  314.  
  315. /*
  316.   MenuWindowWndProc - window procedure for the window which contains the
  317.     menubar we are building. The main purpose of this function is to receive
  318.     WM_COMMAND messages when we click on a menu item, and to receive
  319.     right button down messages in order to edit a menubar item.
  320. */
  321. pascal MenuWindowWndProc(hWnd, message, wParam, lParam)
  322.   HWND hWnd;
  323.   WORD message;
  324.   WORD wParam;
  325.   DWORD lParam;
  326. {
  327.   switch (message)
  328.   {
  329.     case WM_COMMAND    :
  330.     {
  331.       WORD iSaveMode = CurrMode;
  332.       CurrMode = MODE_POPUP;
  333.       EditChangeItem(wParam);
  334.       CurrMode = iSaveMode;
  335.       break;
  336.     }
  337.  
  338.     case WM_RBUTTONDOWN:
  339.     {
  340.       int  mouserow = HIWORD(lParam);
  341.       int  mousecol = LOWORD(lParam);
  342.       RECT rMenuBar;
  343.  
  344.       /*
  345.         See if we clicked in the menubar
  346.       */
  347.       rMenuBar = WinGetRect(hMenuBar);
  348.       if (RectContainsPoint(rMenuBar, mouserow, mousecol))
  349.       {
  350.         int  iPos;
  351.         WORD iSaveMode = CurrMode;
  352.  
  353.         CurrMode = MODE_MENUBAR;
  354.         if ((iPos = ColToItem(hMenuBar, mousecol)) >= 0)
  355.         {
  356.           /*
  357.             Determine which menubar item we clicked on, and fill the
  358.             CurrItem structure with that info.
  359.           */
  360.           GetMenuString(hMenuBar, iPos, CurrItem.szItemText, 
  361.                                  sizeof(CurrItem.szItemText), MF_BYPOSITION);
  362.           CurrItem.idItem = iPos;
  363.           CurrItem.fMask  = GetMenuState(hMenuBar, iPos, MF_BYPOSITION);
  364.           EditDispatch();
  365.         }
  366.         CurrMode = iSaveMode;
  367.       }
  368.       SetFocus(hMain);
  369.       return TRUE;
  370.     }
  371.  
  372.     case WM_HELP       :
  373.       HelpDialog();
  374.       break;
  375.  
  376.     case WM_QUIT       :
  377.       /* End the dialog editor */
  378.       exit(0);
  379.  
  380.     default :
  381.       /* Call the default window procedure for the main window */
  382.       return DefWinProc(hWnd, message, wParam, lParam);
  383.   }
  384.  
  385.   return FALSE;
  386. }
  387.  
  388.  
  389. EditDispatch()
  390. {
  391.   int rc;
  392.  
  393.   /*
  394.     Put up the menu item dialog box and get the user's choice of action
  395.   */
  396.   LoadMenugenDialog();
  397.   if ((rc = DialogBox(hItemDlg)) == IDCANCEL)
  398.     return TRUE;
  399.  
  400.   if (rc == ID_EDIT_ADD || rc == ID_EDIT_INSERT || rc == ID_EDIT_CHANGE)
  401.   {
  402.     if (CurrMode == MODE_MENUBAR)
  403.     {
  404.       HMENU hPop;
  405.  
  406.       if (rc == ID_EDIT_ADD || rc == ID_EDIT_INSERT)
  407.       {
  408.         WORD cmdmask = (rc == ID_EDIT_INSERT) ? MF_INSERT : MF_APPEND;
  409.         WORD idChgItem = (rc == ID_EDIT_INSERT) ? 0 : 0;
  410.  
  411.         if (CurrItem.fMask & MF_POPUP)
  412.           CurrItem.idItem = hPop = CreateMenu(hMenuBar);
  413.         ChangeMenu(hMenuBar,
  414.                    idChgItem,
  415.                    CurrItem.szItemText,
  416.                    CurrItem.idItem,
  417.                    cmdmask | MF_STRING | (CurrItem.fMask & ~MF_SHADOW));
  418.         if (CurrItem.fMask & MF_POPUP)
  419.           CreateDefaultPopup(hPop, CurrItem.fMask & MF_SHADOW);
  420.       }
  421.       else  /* rc == ID_EDIT_CHANGE */
  422.       {
  423.         ChangeMenu(hMenuBar, CurrItem.idItem, CurrItem.szItemText, 0,
  424.                    MF_BYPOSITION | MF_CHANGE | MF_STRING |
  425.                     (CurrItem.fMask & ~(MF_SHADOW|MF_POPUP)));
  426.       }
  427.  
  428.       DrawMenuBar(hMenuBar);
  429.     }
  430.     else   /* CurrMode == MF_POPUP */
  431.     {
  432.       if (rc == ID_EDIT_ADD || rc == ID_EDIT_INSERT)
  433.       {
  434.         WORD cmdmask = (rc == ID_EDIT_INSERT) ? MF_INSERT : MF_APPEND;
  435.         WORD idChgItem = (rc == ID_EDIT_INSERT) ? 0 : 0;
  436.  
  437.         ChangeMenu(CurrItem.hMenu,
  438.                    idChgItem,
  439.                    CurrItem.szItemText,
  440.                    CurrItem.idItem,
  441.                    cmdmask | MF_STRING | CurrItem.fMask);
  442.       }
  443.       else /* rc == ID_EDIT_CHANGE */
  444.       {
  445.         ChangeMenu(CurrItem.hMenu, CurrItem.idItem, CurrItem.szItemText, 0,
  446.                  MF_BYCOMMAND | MF_CHANGE | MF_STRING | CurrItem.fMask);
  447.       }
  448.     }
  449.   }
  450.  
  451.   else if (rc == ID_EDIT_DELETE)
  452.   {
  453.     EditDeleteItem(CurrItem.idItem);
  454.   }
  455. }
  456.  
  457.  
  458. EditChangeItem(idItem)
  459. {
  460.   int rc;
  461.   int pos;
  462.   HMENU hPop;
  463.  
  464.   memset(&CurrItem, 0, sizeof(CurrItem));
  465.   CurrItem.idItem = idItem;
  466.  
  467.   for (pos = 0;  (hPop = GetSubMenu(hMenuBar, pos));  pos++)
  468.   {
  469.     if (GetMenuString(hPop, idItem, CurrItem.szItemText, 
  470.                               sizeof(CurrItem.szItemText), MF_BYCOMMAND) > 0)
  471.     {
  472.       CurrItem.fMask = GetMenuState(hPop, idItem, MF_BYCOMMAND);
  473.       break; 
  474.     }
  475.   }
  476.  
  477.   if ((CurrItem.hMenu = hPop) == NULLHWND)
  478.   {
  479.     MessageBox("Can't locate the item", NULL, NULL, "Error", MB_OK);
  480.     return FALSE;
  481.   }
  482.  
  483.   EditDispatch();
  484. }
  485.  
  486.  
  487. EditDeleteItem(idItem)
  488. {
  489.   int rc;
  490.   int pos;
  491.   HMENU hPop;
  492.  
  493.   memset(&CurrItem, 0, sizeof(CurrItem));
  494.   CurrItem.idItem = idItem;
  495.  
  496.   if (CurrMode == MODE_MENUBAR)
  497.   {
  498.     hPop = hMenuBar;
  499.   }
  500.   else
  501.   {
  502.     for (pos = 0;  (hPop = GetSubMenu(hMenuBar, pos));  pos++)
  503.       if (GetMenuString(hPop, idItem, CurrItem.szItemText, 
  504.                                 sizeof(CurrItem.szItemText), MF_BYCOMMAND) > 0)
  505.       {
  506.         CurrItem.fMask = GetMenuState(hPop, idItem, MF_BYCOMMAND);
  507.         break; 
  508.       }
  509.   }
  510.  
  511.   if ((CurrItem.hMenu = hPop) == NULLHWND)
  512.   {
  513.     MessageBox("Can't locate the item", NULL, NULL, "Error", MB_OK);
  514.     return FALSE;
  515.   }
  516.  
  517.   if (MessageBox("Are you sure that you",
  518.                  "want to delete the item",
  519.                   CurrItem.szItemText, "Warning!", MB_YESNO) == IDNO)
  520.     return FALSE;
  521.  
  522.   ChangeMenu(hPop, idItem, NULL, 0, 
  523.              (CurrMode == MODE_MENUBAR) ? (MF_DELETE | MF_BYPOSITION)
  524.                                         : (MF_DELETE | MF_BYCOMMAND));
  525.   DrawMenuBar(hMenuBar);
  526.   return TRUE;
  527. }
  528.  
  529.  
  530. /***************************************************************************/
  531. /*                                                                         */
  532. /* ColToItem() - given a menubar and an absolute column, return the        */
  533. /*        index of the menubar item clicked on.                            */
  534. /*                                                                         */
  535. /***************************************************************************/
  536. ColToItem(hBar, mousecol)
  537.   HMENU hBar;
  538.   int   mousecol;
  539. {
  540.   RECT  rBar;
  541.   int   totalLen = 0;
  542.   int   itemLen;
  543.   int   iPos;
  544.   char  szItem[80];
  545.  
  546.   /*
  547.     Convert screen to window coordinates
  548.   */
  549.   rBar = WinGetRect(hBar);
  550.   mousecol -= rBar.left;
  551.  
  552.   /*
  553.     Go through all of the items in the menubar, totalling up the lengths
  554.     of the strings. When we find an item that intersects the column,
  555.     the return the index of the string.
  556.   */
  557.   for (iPos = 0;
  558.       (itemLen = GetMenuString(hBar,iPos,szItem,sizeof(szItem),MF_BYPOSITION));
  559.       iPos++)
  560.   {
  561.     if (mousecol >= totalLen + 1 && mousecol < totalLen + itemLen + 1)
  562.       return iPos;
  563.     else
  564.       totalLen += itemLen + 2;
  565.   }
  566.  
  567.   return -1;
  568. }
  569.  
  570.  
  571.  
  572. /**************************************************************************/
  573. /*                                                                        */
  574. /* CheckBox-to-mask mapping                                               */
  575. /*                                                                        */
  576. /**************************************************************************/
  577. typedef struct checkbox_to_mask
  578. {
  579.   WORD idCheckBox;
  580.   WORD fMaskBits;
  581. } CHECKBOX_TO_MASK;
  582.  
  583. CHECKBOX_TO_MASK CheckBoxToMask[] =
  584. {
  585.   ID_SEPARATOR,  MF_SEPARATOR,
  586.   ID_SHADOW,     MF_SHADOW,
  587.   ID_HAS_POPUP,  MF_POPUP,
  588.   ID_WMHELP,     MF_HELP,
  589.   ID_DISABLED,   MF_DISABLED,
  590.   ID_CHECKED,    MF_CHECKED
  591. };
  592.  
  593. /**************************************************************************/
  594. /*                                                                        */
  595. /* MenuItemDlgProc()                                                      */
  596. /*   Processes the mneu item information dialog box.                      */
  597. /*                                                                        */
  598. /**************************************************************************/
  599. BOOL pascal MenuItemDlgProc(hDlg, msg, wParam, lParam)
  600.   HWND hDlg;
  601.   WORD msg;
  602.   WORD wParam;
  603.   DWORD lParam;
  604. {
  605.   int i;
  606.  
  607.   switch (msg)
  608.   {
  609.     case WM_INITDIALOG :
  610.       /*
  611.         Transfer the data from CurrItem into the dialog controls
  612.       */
  613.       SetDialogText(hDlg, ID_ITEMTEXT, CurrItem.szItemText);
  614.       SetDialogInt(hDlg, ID_ITEMID, CurrItem.idItem);
  615.       for (i = 0; i < sizeof(CheckBoxToMask)/sizeof(CheckBoxToMask[0]); i++)
  616.         CheckDialogItem(hDlg, CheckBoxToMask[i].idCheckBox,
  617.                 (CurrItem.fMask & CheckBoxToMask[i].fMaskBits) ? TRUE : FALSE);
  618.       return TRUE;
  619.  
  620.     case WM_QUIT :
  621.       EndDialog(hDlg, IDCANCEL);
  622.       break;
  623.  
  624.     case WM_COMMAND :
  625.       if (wParam == IDCANCEL)
  626.         EndDialog(hDlg, IDCANCEL);
  627.       else if (wParam==ID_EDIT_ADD || wParam==ID_EDIT_INSERT || wParam==ID_EDIT_CHANGE)
  628.       {
  629.         /*
  630.           Transfer the data from the dialog controls into the CurrItem struct
  631.         */
  632.         GetDlgItemText(hDlg, ID_ITEMTEXT, 
  633.                            CurrItem.szItemText, sizeof(CurrItem.szItemText));
  634.         GetDialogInt(hDlg, ID_ITEMID, &CurrItem.idItem);
  635.  
  636.         /*
  637.           Build the attribute mask from the checkbox states
  638.         */
  639.         CurrItem.fMask = 0x0000;
  640.         for (i = 0; i < sizeof(CheckBoxToMask)/sizeof(CheckBoxToMask[0]); i++)
  641.           if (IsDialogButtonChecked(hDlg, CheckBoxToMask[i].idCheckBox))
  642.             CurrItem.fMask |= CheckBoxToMask[i].fMaskBits;
  643.         EndDialog(hDlg, wParam);
  644.       }
  645.       else if (wParam == ID_EDIT_DELETE)
  646.       {
  647.         GetDialogInt(hDlg, ID_ITEMID, &CurrItem.idItem);
  648.         EndDialog(hDlg, ID_EDIT_DELETE);
  649.       }
  650.       return TRUE;
  651.  
  652.     case WM_CHAR :
  653.       if (wParam == VK_ESC)
  654.         EndDialog(hDlg, IDCANCEL);
  655.       return FALSE;
  656.  
  657.     default :
  658.       return FALSE;
  659.   }
  660. }
  661.  
  662.  
  663. /**************************************************************************/
  664. /*                                                                        */
  665. /* CreateDefaultPopup()                                                   */
  666. /*   Attaches NUM_DEFAULT_ITEMS popup items to a menubar entry.           */
  667. /*                                                                        */
  668. /**************************************************************************/
  669. #define NUM_DEFAULT_ITEMS   1
  670.  
  671. CreateDefaultPopup(hPop, hasShadow)
  672.   HMENU hPop;
  673.   WORD  hasShadow;
  674. {
  675.   int  i;
  676.   char buf[32];
  677.  
  678.   for (i = 0;  i < NUM_DEFAULT_ITEMS;  i++)
  679.   {
  680.     sprintf(buf, "Item%d", idLastItem);
  681.     ChangeMenu(hPop, 0, buf, idLastItem++, MF_APPEND | hasShadow);
  682.   }
  683. }
  684.  
  685.  
  686. LoadMenugenDialog()
  687. {
  688.   WORD  hRes = OpenResourceFile("menugen");
  689.  
  690.   if (!hRes)
  691.   {
  692.     printf("Can't open menugen.res\n");
  693.     exit(1);
  694.   }
  695.   hItemDlg = LoadDialog(hRes, DLG_MENUITEM, hMain, MenuItemDlgProc);
  696.   CloseResourceFile(hRes);
  697. }
  698.  
  699.  
  700. /****************************************************************************/
  701. /*                                                                          */
  702. /*       CODE GENERATION FOR THE MENUS...                                   */
  703. /*                                                                          */
  704. /****************************************************************************/
  705.  
  706. #define ID_MENU  256
  707.  
  708. GenerateRCCode(hMenuBar, szFileName)
  709.   HMENU hMenuBar;         /* handle to menubar */
  710.   char  *szFileName;      /* name of file to write the description to */
  711. {
  712.   int   indent = 0;
  713.   int   nBarItems, nPopupItems;
  714.   int   iBar, iItem;
  715.   WORD  fFlags;
  716.   WORD  id;
  717.   char  szText[80];
  718.   HMENU hPop;
  719.   FILE  *RCfp;
  720.  
  721.   if ((nBarItems = GetMenuItemCount(hMenuBar)) <= 0)
  722.     return FALSE;
  723.  
  724.   /*
  725.     Open the RC file
  726.   */
  727.   if ((RCfp = fopen(szFileName, "w")) == NULL)
  728.   {
  729.     MessageBox("Cannot open the file", szFileName, NULL, "Error", MB_OK);
  730.     return FALSE;
  731.   }
  732.  
  733.   /*
  734.     Print the menu header
  735.   */
  736.   fprintf(RCfp, "%d MENU\nBEGIN\n", ID_MENU);
  737.   indent++;
  738.  
  739.   for (iBar = 0;  iBar < nBarItems;  iBar++)
  740.   {
  741.     if ((hPop = GetSubMenu(hMenuBar, iBar)) != NULLHWND)
  742.     {
  743.       /*
  744.         Print a popup item
  745.       */
  746.       GetMenuString(hMenuBar, iBar, szText, sizeof(szText), MF_BYPOSITION);
  747.       print_indent(RCfp, indent);
  748.       fprintf(RCfp, "POPUP \"%s\"\nBEGIN\n", szText);
  749.       indent++;
  750.  
  751.       if ((nPopupItems = GetMenuItemCount(hPop)) > 0)
  752.         for (iItem = 0;  iItem < nPopupItems;  iItem++)
  753.         {
  754.           fFlags = GetMenuState(hPop, iItem, MF_BYPOSITION);
  755.           if (fFlags & MF_SEPARATOR)
  756.           {
  757.             print_indent(RCfp, indent);
  758.             fprintf(RCfp, "MENUITEM SEPARATOR\n");
  759.             continue;
  760.           }
  761.  
  762.           id = GetMenuItemID(hPop, iItem);
  763.           GetMenuString(hPop, iItem, szText, sizeof(szText), MF_BYPOSITION);
  764.           print_indent(RCfp, indent);
  765.           fprintf(RCfp, "MENUITEM \"%s\", %d", szText, id);
  766.           print_flags(RCfp, fFlags);
  767.           fprintf(RCfp, "\n");
  768.         }
  769.  
  770.       indent--;
  771.       print_indent(RCfp, indent);
  772.       fprintf(RCfp, "END\n");
  773.     }
  774.     else
  775.     {
  776.       /*
  777.         Print a menubar item
  778.       */
  779.       fFlags = GetMenuState(hMenuBar, iBar, MF_BYPOSITION);
  780.       id = GetMenuItemID(hMenuBar, iBar);
  781.       GetMenuString(hMenuBar, iBar, szText, sizeof(szText), MF_BYPOSITION);
  782.       print_indent(RCfp, indent);
  783.       fprintf(RCfp, "MENUITEM \"%s\", %d");
  784.       print_flags(RCfp, fFlags);
  785.       fprintf(RCfp, "\n");
  786.     }
  787.   }
  788.  
  789.   indent--;
  790.   fprintf(RCfp, "END\n\n");
  791.   fclose(RCfp);
  792.   return TRUE;
  793. }
  794.  
  795.  
  796. /****************************************************************************/
  797. /*                                                                          */
  798. /* print_flags() - converts attr bitmask to English description for .RC     */
  799. /*                                                                          */
  800. /****************************************************************************/
  801. print_flags(fp, flags)
  802.   FILE *fp;
  803.   WORD flags;
  804. {
  805.   BOOL bNeedComma = FALSE;
  806.   ATTRINFO *a;
  807.  
  808.   if (!flags)
  809.     return FALSE;
  810.   fprintf(fp, ", ");
  811.  
  812.   for (a=AttrInfo;  a < AttrInfo + sizeof(AttrInfo)/sizeof(AttrInfo[0]);  a++)
  813.     if (flags & a->fBitMask)
  814.     {
  815.       if (bNeedComma)
  816.         fprintf(fp, ", ");
  817.       fprintf(fp, a->szAttr);
  818.       bNeedComma = TRUE;
  819.     }
  820.   return TRUE;
  821. }
  822.  
  823. /****************************************************************************/
  824. /*                                                                          */
  825. /* print_indent() - prints out the proper number of leading blanks          */
  826. /*                                                                          */
  827. /****************************************************************************/
  828. #define INDENT_VAL   2
  829.  
  830. print_indent(fp, indent)
  831.   FILE *fp;
  832.   int  indent;
  833. {
  834.   for (indent *= INDENT_VAL;  indent;  indent--)
  835.     fprintf(fp, " ");
  836. }
  837.  
  838.  
  839. /****************************************************************************/
  840. /*                                                                          */
  841. /*       SAVING A MENU TO AN RC FILE.....                                   */
  842. /*                                                                          */
  843. /****************************************************************************/
  844.  
  845. SaveFileDlg()
  846. {
  847.   HWND hDlg;
  848.   WORD hRes;
  849.   extern BOOL pascal DlgFnSave();
  850.  
  851.   hRes = OpenResourceFile("menugen");
  852.   if (!hRes)
  853.     return FALSE;
  854.   hDlg = LoadDialog(hRes, DLG_MENUSAVE, hMain, DlgFnSave);
  855.   CloseResourceFile(hRes);
  856.  
  857.   return (hDlg) ? DialogBox(hDlg) : FALSE;
  858. }
  859.  
  860.  
  861. BOOL pascal DlgFnSave(hDlg, msg, wParam, lParam)
  862.   HWND hDlg;
  863.   WORD msg;
  864.   WORD wParam;
  865.   DWORD lParam;
  866. {
  867.   char szFileName[80];
  868.  
  869.   switch (msg)
  870.   {
  871.     case WM_INITDIALOG :
  872.       return TRUE;
  873.  
  874.     case WM_COMMAND :
  875.       if (wParam == IDCANCEL)
  876.         EndDialog(hDlg, IDCANCEL);
  877.       else if (wParam == IDOK)
  878.       {
  879.         GetDialogText(hDlg, ID_ITEMTEXT, (char far *) szFileName, 65);
  880.         if (access(szFileName, 0x0000))
  881.         {
  882.           if (MessageBox("The file", szFileName, "exists. Overwrite?", "Warning", 
  883.                      MB_YESNO) == IDNO)
  884.             return TRUE;
  885.         }
  886.         if (GenerateRCCode(hMenuBar, szFileName))
  887.         {
  888.           strcpy(CurrFileName, szFileName);
  889.           EndDialog(hDlg, IDOK);
  890.         }
  891.       }
  892.       return TRUE;
  893.  
  894.     case WM_CHAR :
  895.       if (wParam == VK_ESC)
  896.       {
  897.         EndDialog(hDlg, VK_ESC);
  898.       }
  899.       return FALSE;
  900.  
  901.     default :
  902.       return FALSE;
  903.   }
  904. }
  905.  
  906.  
  907. /***************************************************************************/
  908. /*                                                                         */
  909. /* MenuList() - puts up a dialog box which shows a list of the menus       */
  910. /*                in the given .RES file.                                  */
  911. /*                                                                         */
  912. /***************************************************************************/
  913.  
  914. WORD hModule;
  915.  
  916. HMENU MenuList(char *szFileName)
  917. {
  918.   HDLG  hDlg;
  919.   HMENU hMenu;
  920.   WORD  hRes;
  921.   extern BOOL pascal DlgListDialogProc();
  922.  
  923.   hRes = OpenResourceFile("menugen");
  924.   if (!hRes)
  925.   {
  926.     printf("Can't open menugen.res\n");
  927.     exit(1);
  928.   }
  929.   hDlg = LoadDialog(hRes, DLG_MENULIST, hMain, DlgListDialogProc);
  930.   CloseResourceFile(hRes);
  931.  
  932.   if ((hModule = OpenResourceFile(szFileName)) == FALSE)
  933.     return NULLHWND;
  934.   hMenu = (HMENU) DialogBox(hDlg);
  935.   CloseResourceFile(hModule);
  936.   return hMenu;
  937. }
  938.  
  939. BOOL pascal DlgListDialogProc(hDlg, msg, wParam, lParam)
  940.   HWND hDlg;
  941.   WORD msg;
  942.   WORD wParam;
  943.   DWORD lParam;
  944. {
  945.   RESOURCE res;
  946.   HMENU    hNewMenu;
  947.   WORD     iSel;
  948.   char     buf[33];
  949.  
  950.   switch (msg)
  951.   {
  952.     case WM_INITDIALOG :
  953.       lseek(hModule, 0L, 0);
  954.       /*
  955.         Gather the names of all menu resources
  956.       */
  957.       for (;;)
  958.       {
  959.         if (read(hModule, &res, sizeof(res)) <= 0)
  960.           break;
  961.  
  962.         if (res.iResType == RT_MENU)
  963.         {
  964.           /*
  965.             Add it to the listbox
  966.           */
  967.           sprintf(buf, "%u", res.iResID);
  968.           SendDlgItemMessage(hDlg, ID_MENULIST_LISTBOX, LB_ADDSTRING, 0, 
  969.                                                        (DWORD) (char far *) buf);
  970.         }
  971.  
  972.         if (lseek(hModule, (long) res.nResBytes, 1) == -1)
  973.           break;
  974.       }
  975.       return TRUE;
  976.  
  977.     case WM_COMMAND :
  978.       switch (wParam)
  979.       {
  980.         case IDOK     :
  981.           /*
  982.             Did we choose a menu? If so, find out which one.
  983.           */
  984.           iSel = SendDlgItemMessage(hDlg, ID_MENULIST_LISTBOX, LB_GETCURSEL, 0, 0L);
  985.           if (iSel == LB_ERR)
  986.             return TRUE;
  987.  
  988.           /*
  989.             Get the id of the menu to load
  990.           */
  991.           SendDlgItemMessage(hDlg, ID_MENULIST_LISTBOX, LB_GETTEXT, iSel,
  992.                              (DWORD) (char far *) buf);
  993.           iSel = atoi(buf);
  994.  
  995.           /*
  996.             Load the chosen menu and return the menu handle to the caller.
  997.           */
  998.           if ((hNewMenu = LoadMenu(hModule, iSel, hWndMenu)))
  999.             EndDialog(hDlg, hNewMenu);
  1000.           else
  1001.             MessageBox("This menu could not be loaded", NULL, NULL, "ERROR", MB_OK);
  1002.           return TRUE;
  1003.         case IDCANCEL :
  1004.           EndDialog(hDlg, FALSE);
  1005.           return TRUE;
  1006.       }
  1007.  
  1008.   } /* switch */
  1009.  
  1010.   return FALSE;
  1011. }
  1012.  
  1013.  
  1014. /***************************************************************************/
  1015. /*                                                                         */
  1016. /* ChangeExtension() - changes a filename's extension to szExt             */
  1017. /*                                                                         */
  1018. /***************************************************************************/
  1019. ChangeExtension(fname, szExt)
  1020.   char *fname, *szExt;
  1021. {
  1022.   char *pExt = strchr(fname, '.');
  1023.   if (pExt)
  1024.     strcpy(pExt, szExt);
  1025.   else
  1026.     strcat(fname, szExt);
  1027. }
  1028.  
  1029.  
  1030. /***************************************************************************/
  1031. /*                                                                         */
  1032. /* CtrlDisplayStatus() - displays the status message                       */
  1033. /*                                                                         */
  1034. /***************************************************************************/
  1035. CtrlDisplayStatus(str)
  1036.   char *str;
  1037. {
  1038.   WinClear(hStatus);
  1039.   WinPuts(hStatus, 0, 0, str, WinGetAttr(hStatus));
  1040. }
  1041.  
  1042.  
  1043. /***************************************************************************/
  1044. /*                                                                         */
  1045. /*                       HELP ROUTINES                                     */
  1046. /*                                                                         */
  1047. /***************************************************************************/
  1048.  
  1049. HelpDialog()
  1050. {
  1051.   HDLG hDlg;
  1052.   WORD hRes;
  1053.   extern BOOL pascal HelpDialogProc();
  1054.  
  1055.   hRes = OpenResourceFile("menugen");
  1056.   if (!hRes)
  1057.   {
  1058.     printf("Can't open menugen.res\n");
  1059.     exit(1);
  1060.   }
  1061.   hDlg = LoadDialog(hRes, DLG_HELP, hMain, HelpDialogProc);
  1062.   CloseResourceFile(hRes);
  1063.   return (hDlg) ? DialogBox(hDlg) : FALSE;
  1064. }
  1065.  
  1066.  
  1067. BOOL pascal HelpDialogProc(hDlg, msg, wParam, lParam)
  1068.   HWND hDlg;
  1069.   WORD msg;
  1070.   WORD wParam;
  1071.   DWORD lParam;
  1072. {
  1073.   char szBuf[80];
  1074.   static FILE *fHelp;
  1075.   HWND   hLB;
  1076.   HWND   hTopics;
  1077.   int    iTopic;
  1078.   static int bShowingTopics;
  1079.  
  1080.   switch (msg)
  1081.   {
  1082.     case WM_INITDIALOG :
  1083.       if ((fHelp = fopen("MENUGEN.HLP", "r")) == NULL)
  1084.       {
  1085.         MessageBox("Can't open MENUGEN.HLP", NULL, NULL, "Error", MB_OK);
  1086.         EndDialog(hDlg, IDCANCEL);
  1087.         return TRUE;
  1088.       }
  1089. get_topics:
  1090.       hLB = GetDlgItem(hDlg, ID_HELP_LB);
  1091.       SendMessage(hLB, LB_RESETCONTENT, 0, 0L);
  1092.       ListBoxSetRedraw(hLB, FALSE);
  1093.  
  1094.       while (fgets(szBuf, sizeof(szBuf), fHelp) != NULL && *szBuf != '\f')
  1095.       {
  1096.         char *szEnd = szBuf + strlen(szBuf) - 1;
  1097.         if (*szEnd == '\n')
  1098.           *szEnd = '\0';
  1099.         SendMessage(hLB, LB_ADDSTRING, 0, (DWORD) (char far *) szBuf);
  1100.       }
  1101.  
  1102.       ListBoxSetRedraw(hLB, TRUE);
  1103.       SetFocus(hLB);
  1104.  
  1105.       hTopics = GetDlgItem(hDlg, ID_TOPICS);
  1106.       EnableWindow(hTopics, FALSE);
  1107.       WinSetAttr(hTopics, 0x37);
  1108.  
  1109.       bShowingTopics = TRUE;
  1110.       return TRUE;
  1111.  
  1112.  
  1113.     case WM_QUIT :
  1114.       EndDialog(hDlg, IDCANCEL);
  1115.       break;
  1116.  
  1117.     case WM_COMMAND :
  1118.       switch (wParam)
  1119.       {
  1120.         case IDCANCEL :
  1121.           fclose(fHelp);
  1122.           EndDialog(hDlg, IDCANCEL);
  1123.           break;
  1124.         case IDOK     :
  1125.           if (bShowingTopics)
  1126.           {
  1127.             /* Show a help item */
  1128.             hLB = GetDlgItem(hDlg, ID_HELP_LB);
  1129.             iTopic = SendMessage(hLB, LB_GETCURSEL, 0, 0L);
  1130.  
  1131.             while (iTopic)
  1132.             {
  1133.               if (fgets(szBuf, sizeof(szBuf), fHelp) == NULL)
  1134.                 break;
  1135.               if (*szBuf == '\f')
  1136.                 iTopic--;
  1137.             }
  1138.  
  1139.             hLB = GetDlgItem(hDlg, ID_HELP_LB);
  1140.             SendMessage(hLB, LB_RESETCONTENT, 0, 0L);
  1141.             ListBoxSetRedraw(hLB, FALSE);
  1142.  
  1143.             while (fgets(szBuf, sizeof(szBuf), fHelp) != NULL && *szBuf != '\f')
  1144.             {
  1145.               char *szEnd = szBuf + strlen(szBuf) - 1;
  1146.               if (*szEnd == '\n')
  1147.                 *szEnd = '\0';
  1148.               SendMessage(hLB, LB_ADDSTRING, 0, (DWORD) (char far *) szBuf);
  1149.             }
  1150.  
  1151.             ListBoxSetRedraw(hLB, TRUE);
  1152.             SetFocus(hLB);
  1153.             bShowingTopics = FALSE;
  1154.  
  1155.             hTopics = GetDlgItem(hDlg, ID_TOPICS);
  1156.             EnableWindow(hTopics, TRUE);
  1157.             WinSetAttr(hTopics, 0x31);
  1158.           }
  1159.           else
  1160.           {
  1161.             rewind(fHelp);
  1162.             goto get_topics;
  1163.           }
  1164.           break;
  1165.         case ID_TOPICS:
  1166.           rewind(fHelp);
  1167.           goto get_topics;
  1168.       }
  1169.       return TRUE;
  1170.  
  1171.     case WM_CHAR :
  1172.       if (wParam == VK_ESC)
  1173.       {
  1174.         fclose(fHelp);
  1175.         EndDialog(hDlg, IDCANCEL);
  1176.       }
  1177.       return FALSE;
  1178.  
  1179.     default :
  1180.       return FALSE;
  1181.   }
  1182. }
  1183.