home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / mesa5.zip / mesa5src.zip / MesaDLL / os2_menu.cpp < prev    next >
Text File  |  2002-12-26  |  13KB  |  533 lines

  1.  
  2. /* Copyright (c) Mark J. Kilgard, 1994, 1997, 1998. */
  3. /* Copyright (c) Nate Robins, 1997. */
  4.  
  5. /* This program is freely distributable without licensing fees
  6.    and is provided without guarantee or warrantee expressed or
  7.    implied. This program is -not- in the public domain. */
  8.  
  9. /* This file completely re-implements glut_menu.c and glut_menu2.c
  10.    for Win32.  Note that neither glut_menu.c nor glut_menu2.c are
  11.    compiled into Win32 GLUT. */
  12.  
  13. #include <stdlib.h>
  14. #include <string.h>
  15. #include <stdio.h>
  16. #include <errno.h>
  17. #include <assert.h>
  18.  
  19. #include "glutint.h"
  20.  
  21. void (GLUTCALLBACK *__glutMenuStatusFunc) (int, int, int);
  22. //GLUTmenu *__glutMappedMenu;
  23. //GLUTwindow *__glutMenuWindow;
  24. GLUTmenuItem *__glutItemSelected;
  25. unsigned __glutMenuButton;
  26.  
  27. static GLUTmenu **menuList = NULL;
  28. static int menuListSize = 0;
  29. static UINT uniqueMenuHandler = 1;
  30.  
  31. /* DEPRICATED, use glutMenuStatusFunc instead. */
  32. void GLUTAPIENTRY
  33. glutMenuStateFunc(GLUTmenuStateCB menuStateFunc)
  34. {
  35.   __glutMenuStatusFunc = (GLUTmenuStatusCB) menuStateFunc;
  36. }
  37.  
  38. void GLUTAPIENTRY
  39. glutMenuStatusFunc(GLUTmenuStatusCB menuStatusFunc)
  40. {
  41.   __glutMenuStatusFunc = menuStatusFunc;
  42. }
  43.  
  44. void
  45. __glutSetMenu(GLUTmenu * menu)
  46. {
  47.   __glutCurrentMenu = menu;
  48. }
  49.  
  50. static void
  51. unmapMenu(GLUTmenu * menu)
  52. {
  53.   if (menu->cascade) {
  54.     unmapMenu(menu->cascade);
  55.     menu->cascade = NULL;
  56.   }
  57.   menu->anchor = NULL;
  58.   menu->highlighted = NULL;
  59. }
  60.  
  61. void
  62. __glutFinishMenu(Window win, int x, int y)
  63. {
  64.  
  65.   unmapMenu(__glutMappedMenu);
  66.  
  67.   /* XXX Put in a GdiFlush just in case.  Probably unnecessary. -mjk  */
  68. //  GdiFlush();
  69.  
  70.   if (__glutMenuStatusFunc) {
  71.     __glutSetWindow(__glutMenuWindow);
  72.     __glutSetMenu(__glutMappedMenu);
  73.  
  74.     /* Setting __glutMappedMenu to NULL permits operations that
  75.        change menus or destroy the menu window again. */
  76.     __glutMappedMenu = NULL;
  77.  
  78.     __glutMenuStatusFunc(GLUT_MENU_NOT_IN_USE, x, y);
  79.   }
  80.   /* Setting __glutMappedMenu to NULL permits operations that
  81.      change menus or destroy the menu window again. */
  82.   __glutMappedMenu = NULL;
  83.  
  84.   /* If an item is selected and it is not a submenu trigger,
  85.      generate menu callback. */
  86.   if (__glutItemSelected && !__glutItemSelected->isTrigger) {
  87.     __glutSetWindow(__glutMenuWindow);
  88.     /* When menu callback is triggered, current menu should be
  89.        set to the callback menu. */
  90.     __glutSetMenu(__glutItemSelected->menu);
  91.     __glutItemSelected->menu->select(__glutItemSelected->value);
  92.   }
  93.   __glutMenuWindow = NULL;
  94. }
  95.  
  96. static void
  97. mapMenu(GLUTmenu * menu, int x, int y)
  98. {
  99. //todo
  100. //  TrackPopupMenu((HMENU) menu->win, TPM_LEFTALIGN |
  101. //    (__glutMenuButton == TPM_RIGHTBUTTON) ? TPM_RIGHTBUTTON : TPM_LEFTBUTTON,
  102. //    x, y, 0, __glutCurrentWindow->win, NULL);
  103. }
  104.  
  105. void
  106. __glutStartMenu(GLUTmenu * menu, GLUTwindow * window,
  107.                int x, int y, int x_win, int y_win)
  108. {
  109.   assert(__glutMappedMenu == NULL);
  110.   __glutMappedMenu = menu;
  111.   __glutMenuWindow = window;
  112.   __glutItemSelected = NULL;
  113.   if (__glutMenuStatusFunc) {
  114.     __glutSetMenu(menu);
  115.     __glutSetWindow(window);
  116.     __glutMenuStatusFunc(GLUT_MENU_IN_USE, x_win, y_win);
  117.   }
  118.   mapMenu(menu, x, y);
  119. }
  120.  
  121. GLUTmenuItem *
  122. __glutGetUniqueMenuItem(GLUTmenu * menu, UINT unique)
  123. {
  124.   GLUTmenuItem *item;
  125.   int i;
  126.  
  127.   i = menu->num;
  128.   item = menu->list;
  129.   while (item) {
  130.     if (item->unique == unique) {
  131.       return item;
  132.     }
  133.     if (item->isTrigger) {
  134.       GLUTmenuItem *subitem;
  135.       subitem = __glutGetUniqueMenuItem(menuList[item->value], unique);
  136.       if (subitem) {
  137.         return subitem;
  138.       }
  139.     }
  140.     i--;
  141.     item = item->next;
  142.   }
  143.   return NULL;
  144. }
  145.  
  146. GLUTmenuItem *
  147. __glutGetMenuItem(GLUTmenu * menu, Window win, int *which)
  148. {
  149.   GLUTmenuItem *item;
  150.   int i;
  151.  
  152.   i = menu->num;
  153.   item = menu->list;
  154.   while (item) {
  155.     if (item->win == win) {
  156.       *which = i;
  157.       return item;
  158.     }
  159.     if (item->isTrigger) {
  160.       GLUTmenuItem *subitem;
  161.  
  162.       subitem = __glutGetMenuItem(menuList[item->value],
  163.         win, which);
  164.       if (subitem) {
  165.         return subitem;
  166.       }
  167.     }
  168.     i--;
  169.     item = item->next;
  170.   }
  171.   return NULL;
  172. }
  173.  
  174. GLUTmenu *
  175. __glutGetMenu(Window win)
  176. {
  177.   GLUTmenu *menu;
  178.  
  179.   menu = __glutMappedMenu;
  180.   while (menu) {
  181.     if (win == menu->win) {
  182.       return menu;
  183.     }
  184.     menu = menu->cascade;
  185.   }
  186.   return NULL;
  187. }
  188.  
  189. GLUTmenu *
  190. __glutGetMenuByNum(int menunum)
  191. {
  192.   if (menunum < 1 || menunum > menuListSize) {
  193.     return NULL;
  194.   }
  195.   return menuList[menunum - 1];
  196. }
  197.  
  198. static int
  199. getUnusedMenuSlot(void)
  200. {
  201.   int i;
  202.  
  203.   /* Look for allocated, unused slot. */
  204.   for (i = 0; i < menuListSize; i++) {
  205.     if (!menuList[i]) {
  206.       return i;
  207.     }
  208.   }
  209.   /* Allocate a new slot. */
  210.   menuListSize++;
  211.   if (menuList) {
  212.     menuList = (GLUTmenu **)
  213.       realloc(menuList, menuListSize * sizeof(GLUTmenu *));
  214.   } else {
  215.     /* XXX Some realloc's do not correctly perform a malloc
  216.        when asked to perform a realloc on a NULL pointer,
  217.        though the ANSI C library spec requires this. */
  218.     menuList = (GLUTmenu **) malloc(sizeof(GLUTmenu *));
  219.   }
  220.   if (!menuList) {
  221.     __glutFatalError("out of memory.");
  222.   }
  223.   menuList[menuListSize - 1] = NULL;
  224.   return menuListSize - 1;
  225. }
  226.  
  227. static void
  228. menuModificationError(void)
  229. {
  230.   /* XXX Remove the warning after GLUT 3.0. */
  231.   __glutWarning("The following is a new check for GLUT 3.0; update your code.");
  232.   __glutFatalError("menu manipulation not allowed while menus in use.");
  233. }
  234.  
  235. int GLUTAPIENTRY
  236. glutCreateMenu(GLUTselectCB selectFunc)
  237. {
  238.   GLUTmenu *menu;
  239.   int menuid;
  240.  
  241.   if (__glutMappedMenu) {
  242.     menuModificationError();
  243.   }
  244.   menuid = getUnusedMenuSlot();
  245.   menu = (GLUTmenu *) malloc(sizeof(GLUTmenu));
  246.   if (!menu) {
  247.     __glutFatalError("out of memory.");
  248.   }
  249.   menu->id = menuid;
  250.   menu->num = 0;
  251.   menu->submenus = 0;
  252.   menu->select = selectFunc;
  253.   menu->list = NULL;
  254.   menu->cascade = NULL;
  255.   menu->highlighted = NULL;
  256.   menu->anchor = NULL;
  257. //todo
  258. //  menu->win = (HWND) CreatePopupMenu();
  259.   menuList[menuid] = menu;
  260.   __glutSetMenu(menu);
  261.   return menuid + 1;
  262. }
  263.  
  264.  
  265. void GLUTAPIENTRY
  266. glutDestroyMenu(int menunum)
  267. {
  268.   GLUTmenu *menu = __glutGetMenuByNum(menunum);
  269.   GLUTmenuItem *item, *next;
  270.  
  271.   if (__glutMappedMenu) {
  272.     menuModificationError();
  273.   }
  274.   assert(menu->id == menunum - 1);
  275. //todo  DestroyMenu( (HMENU) menu->win);
  276.   menuList[menunum - 1] = NULL;
  277.   /* free all menu entries */
  278.   item = menu->list;
  279.   while (item) {
  280.     assert(item->menu == menu);
  281.     next = item->next;
  282.     free(item->label);
  283.     free(item);
  284.     item = next;
  285.   }
  286.   if (__glutCurrentMenu == menu) {
  287.     __glutCurrentMenu = NULL;
  288.   }
  289.   free(menu);
  290. }
  291.  
  292. int GLUTAPIENTRY
  293. glutGetMenu(void)
  294. {
  295.   if (__glutCurrentMenu) {
  296.     return __glutCurrentMenu->id + 1;
  297.   } else {
  298.     return 0;
  299.   }
  300. }
  301.  
  302. void GLUTAPIENTRY
  303. glutSetMenu(int menuid)
  304. {
  305.   GLUTmenu *menu;
  306.  
  307.   if (menuid < 1 || menuid > menuListSize) {
  308.     __glutWarning("glutSetMenu attempted on bogus menu.");
  309.     return;
  310.   }
  311.   menu = menuList[menuid - 1];
  312.   if (!menu) {
  313.     __glutWarning("glutSetMenu attempted on bogus menu.");
  314.     return;
  315.   }
  316.   __glutSetMenu(menu);
  317. }
  318.  
  319. static void
  320. setMenuItem(GLUTmenuItem * item, const char *label,
  321.            int value, Bool isTrigger)
  322. {
  323.   GLUTmenu *menu;
  324.  
  325.   menu = item->menu;
  326.   item->label = __glutStrdup(label);
  327.   if (!item->label) {
  328.     __glutFatalError("out of memory.");
  329.   }
  330.   item->isTrigger = isTrigger;
  331.   item->len = (int) strlen(label);
  332.   item->value = value;
  333.   item->unique = uniqueMenuHandler++;
  334. //todo
  335. //  if (isTrigger) {
  336. //    AppendMenu((HMENU) menu->win, MF_POPUP, (UINT)item->win, label);
  337. //  } else {
  338. //    AppendMenu((HMENU) menu->win, MF_STRING, item->unique, label);
  339. //  }
  340. }
  341.  
  342. void GLUTAPIENTRY
  343. glutAddMenuEntry(const char *label, int value)
  344. {
  345.   GLUTmenuItem *entry;
  346.  
  347.   if (__glutMappedMenu) {
  348.     menuModificationError();
  349.   }
  350.   entry = (GLUTmenuItem *) malloc(sizeof(GLUTmenuItem));
  351.   if (!entry) {
  352.     __glutFatalError("out of memory.");
  353.   }
  354.   entry->menu = __glutCurrentMenu;
  355.   setMenuItem(entry, label, value, FALSE);
  356.   __glutCurrentMenu->num++;
  357.   entry->next = __glutCurrentMenu->list;
  358.   __glutCurrentMenu->list = entry;
  359. }
  360.  
  361. void GLUTAPIENTRY
  362. glutAddSubMenu(const char *label, int menu)
  363. {
  364.   GLUTmenuItem *submenu;
  365.   GLUTmenu     *popupmenu;
  366.  
  367.   if (__glutMappedMenu) {
  368.     menuModificationError();
  369.   }
  370.   submenu = (GLUTmenuItem *) malloc(sizeof(GLUTmenuItem));
  371.   if (!submenu) {
  372.     __glutFatalError("out of memory.");
  373.   }
  374.   __glutCurrentMenu->submenus++;
  375.   submenu->menu = __glutCurrentMenu;
  376.   popupmenu = __glutGetMenuByNum(menu);
  377.   if (popupmenu) {
  378.     submenu->win = popupmenu->win;
  379.   }
  380.   setMenuItem(submenu, label, /* base 0 */ menu - 1, TRUE);
  381.   __glutCurrentMenu->num++;
  382.   submenu->next = __glutCurrentMenu->list;
  383.   __glutCurrentMenu->list = submenu;
  384. }
  385.  
  386. void GLUTAPIENTRY
  387. glutChangeToMenuEntry(int num, const char *label, int value)
  388. {
  389.   GLUTmenuItem *item;
  390.   int i;
  391.  
  392.   if (__glutMappedMenu) {
  393.     menuModificationError();
  394.   }
  395.   i = __glutCurrentMenu->num;
  396.   item = __glutCurrentMenu->list;
  397.   while (item) {
  398.     if (i == num) {
  399.       if (item->isTrigger) {
  400.         /* If changing a submenu trigger to a menu entry, we
  401.            need to account for submenus.  */
  402.         item->menu->submenus--;
  403.        /* Nuke the Win32 menu. */
  404. //todo
  405. //       DestroyMenu((HMENU) item->win);
  406.       }
  407.       free(item->label);
  408.  
  409.       item->label = strdup(label);
  410.       if (!item->label)
  411.        __glutFatalError("out of memory");
  412.       item->isTrigger = FALSE;
  413.       item->len = (int) strlen(label);
  414.       item->value = value;
  415.       item->unique = uniqueMenuHandler++;
  416. //todo
  417. //      ModifyMenu((HMENU) __glutCurrentMenu->win, (UINT) i - 1,
  418. //        MF_BYPOSITION | MFT_STRING, item->unique, label);
  419.  
  420.       return;
  421.     }
  422.     i--;
  423.     item = item->next;
  424.   }
  425.   __glutWarning("Current menu has no %d item.", num);
  426. }
  427.  
  428. void GLUTAPIENTRY
  429. glutChangeToSubMenu(int num, const char *label, int menu)
  430. {
  431.   GLUTmenu *popupmenu;
  432.   GLUTmenuItem *item;
  433.   int i;
  434.  
  435.   if (__glutMappedMenu) {
  436.     menuModificationError();
  437.   }
  438.   i = __glutCurrentMenu->num;
  439.   item = __glutCurrentMenu->list;
  440.   while (item) {
  441.     if (i == num) {
  442.       if (!item->isTrigger) {
  443.         /* If changing a menu entry to as submenu trigger, we
  444.            need to account for submenus.  */
  445.         item->menu->submenus++;
  446. //todo
  447. //       item->win = (HWND) CreatePopupMenu();
  448.       }
  449.       free(item->label);
  450.  
  451.       item->label = strdup(label);
  452.       if (!item->label)
  453.        __glutFatalError("out of memory");
  454.       item->isTrigger = TRUE;
  455.       item->len = (int) strlen(label);
  456.       item->value = menu - 1;
  457.       item->unique = uniqueMenuHandler++;
  458.       popupmenu = __glutGetMenuByNum(menu);
  459.       if (popupmenu)
  460.        item->win = popupmenu->win;
  461. //todo
  462. //      ModifyMenu((HMENU) __glutCurrentMenu->win, (UINT) i - 1,
  463. //        MF_BYPOSITION | MF_POPUP, (UINT) item->win, label);
  464.       return;
  465.     }
  466.     i--;
  467.     item = item->next;
  468.   }
  469.   __glutWarning("Current menu has no %d item.", num);
  470. }
  471.  
  472. void GLUTAPIENTRY
  473. glutRemoveMenuItem(int num)
  474. {
  475.   GLUTmenuItem *item, **prev;
  476.   int i;
  477.  
  478.   if (__glutMappedMenu) {
  479.     menuModificationError();
  480.   }
  481.   i = __glutCurrentMenu->num;
  482.   prev = &__glutCurrentMenu->list;
  483.   item = __glutCurrentMenu->list;
  484.   while (item) {
  485.     if (i == num) {
  486.       /* Found the menu item in list to remove. */
  487.       __glutCurrentMenu->num--;
  488.  
  489.       /* Patch up menu's item list. */
  490.       *prev = item->next;
  491. //todo
  492. //      RemoveMenu((HMENU) __glutCurrentMenu->win, (UINT) i - 1, MF_BYPOSITION);
  493.  
  494.       free(item->label);
  495.       free(item);
  496.       return;
  497.     }
  498.     i--;
  499.     prev = &item->next;
  500.     item = item->next;
  501.   }
  502.   __glutWarning("Current menu has no %d item.", num);
  503. }
  504.  
  505. void GLUTAPIENTRY
  506. glutAttachMenu(int button)
  507. {
  508.   if (__glutCurrentWindow == __glutGameModeWindow) {
  509.     __glutWarning("cannot attach menus in game mode.");
  510.     return;
  511.   }
  512.   if (__glutMappedMenu) {
  513.     menuModificationError();
  514.   }
  515.   if (__glutCurrentWindow->menu[button] < 1) {
  516.     __glutCurrentWindow->buttonUses++;
  517.   }
  518.   __glutCurrentWindow->menu[button] = __glutCurrentMenu->id + 1;
  519. }
  520.  
  521. void GLUTAPIENTRY
  522. glutDetachMenu(int button)
  523. {
  524.   if (__glutMappedMenu) {
  525.     menuModificationError();
  526.   }
  527.   if (__glutCurrentWindow->menu[button] > 0) {
  528.     __glutCurrentWindow->buttonUses--;
  529.     __glutCurrentWindow->menu[button] = 0;
  530.   }
  531. }
  532.  
  533.