win32_menu.c
上传用户:xk288cn
上传日期:2007-05-28
资源大小:4876k
文件大小:12k
源码类别:

GIS编程

开发平台:

Visual C++

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