home *** CD-ROM | disk | FTP | other *** search
/ Atari FTP / ATARI_FTP_0693.zip / ATARI_FTP_0693 / Mint / toswinsc.zoo / popup.c < prev    next >
C/C++ Source or Header  |  1992-10-27  |  4KB  |  160 lines

  1. /*
  2.  * Copyright 1992 Eric R. Smith. All rights reserved.
  3.  * Redistribution is permitted only if the distribution
  4.  * is not for profit, and only if all documentation
  5.  * (including, in particular, the file "copying")
  6.  * is included in the distribution in unmodified form.
  7.  * THIS PROGRAM COMES WITH ABSOLUTELY NO WARRANTY, NOT
  8.  * EVEN THE IMPLIED WARRANTIES OF MERCHANTIBILITY OR
  9.  * FITNESS FOR A PARTICULAR PURPOSE. USE AT YOUR OWN
  10.  * RISK.
  11.  */
  12. #include <stdlib.h>
  13. #include <stddef.h>
  14. #include <string.h>
  15. #include <osbind.h>
  16. #include "xgem.h"
  17.  
  18. /*
  19.  * pop up a menu at screen location (x, y), and deal with user
  20.  * interactions with it
  21.  */
  22.  
  23. void
  24. popup_menu( m, x, y )
  25.     MENU *m;
  26.     int x,y;
  27. {
  28.     extern int entrylen __PROTO(( ENTRY * ));
  29.     extern char *entrystr __PROTO(( ENTRY *, int ));
  30.     OBJECT *popobj;
  31.     ENTRY *e;
  32.     int numobjects = 1;
  33.     int wide = 0;
  34.     int i;
  35.     int w, h;
  36.     int event, msx, msy, mbutton, mbreturn, keycode, dummy;
  37.     int curobj = -1;
  38.     int newobj;
  39.     int lowbyte;
  40.  
  41.     msx = x; msy = y;
  42.     for (e = m->contents; e; e = e->next) {
  43.         numobjects++;
  44.         if ( (i = entrylen(e)) > wide)
  45.             wide = i;
  46.     }
  47.     popobj = malloc(numobjects * sizeof(OBJECT));
  48.     if (!popobj) return;
  49.  
  50. /* first, create the box around the menu */
  51.     popobj[0].ob_next = -1;
  52.     popobj[0].ob_head = 1;
  53.     popobj[0].ob_tail = numobjects - 1;
  54.     popobj[0].ob_type = G_BOX;
  55.     popobj[0].ob_flags = LASTOB; popobj[0].ob_state = NORMAL;
  56.     popobj[0].ob_spec = 0x00ff1100L;
  57.     popobj[0].ob_x = x/gl_wchar; popobj[0].ob_y = y/gl_hchar;
  58.     popobj[0].ob_width = wide;
  59.     popobj[0].ob_height = numobjects - 1;
  60.     i = 1;
  61.     for (e = m->contents; e; e = e->next) {
  62.         popobj[i].ob_next = (e->next) ? i+1 : 0;
  63.         popobj[i].ob_head = popobj[i].ob_tail = -1;
  64.         popobj[i].ob_type = G_STRING;
  65.         popobj[i].ob_flags = NONE;
  66.         popobj[i].ob_state = e->state;
  67.         popobj[i].ob_spec = (long)entrystr(e, wide);
  68.         if (!popobj[i].ob_spec) return;
  69.         popobj[i].ob_x = 0; popobj[i].ob_y = i - 1;
  70.         popobj[i].ob_width = wide; popobj[i].ob_height = 1;
  71.         i++;
  72.     }
  73.     popobj[i-1].ob_flags = LASTOB;
  74.  
  75. /* now, fix up the object tree */
  76.     for (i = 0; i < numobjects; i++)
  77.         rsrc_obfix(popobj, i);
  78.  
  79. /* find the rectangle the tree will appear in; make sure the whole menu
  80.  * will appear on-screen
  81.  */
  82.     x = popobj[0].ob_x - 1; y = popobj[0].ob_y - 1;
  83.     w = popobj[0].ob_width + 2; h = popobj[0].ob_height + 2;
  84.  
  85.     if (x + w > xdesk + wdesk) x = xdesk + wdesk - w;
  86.     if (y + h > ydesk + hdesk) y = ydesk + hdesk - h;
  87.     if (x < xdesk) x = xdesk;
  88.     if (y < ydesk) y = ydesk;
  89.  
  90.     popobj[0].ob_x = x+1; popobj[0].ob_y = y+1;
  91.  
  92. /* display the tree */
  93.     wind_update(BEG_MCTRL);
  94.     form_dial(0, x, y, w, h, x, y, w, h);
  95.  
  96.     objc_draw(popobj, 0, 1, x, y, w, h);
  97.  
  98. /* interact with it */
  99.  
  100.     for(;;) {
  101.         event = evnt_multi(MU_BUTTON|MU_M1|MU_KEYBD,
  102.             2, 0x0001, 0x0001,
  103.             1, msx, msy, 1, 1,
  104.             0, 0, 0, 0, 0,
  105.             0L, 0L,
  106.             &msx, &msy, &mbutton, &dummy,
  107.             &keycode, &mbreturn);
  108.  
  109.         if (event & MU_M1) {
  110.             if (msx >= x && msx <= x+w && msy >= y && msy <= y+h) {
  111.                 newobj = objc_find(popobj, 0, 1, msx, msy);
  112.             } else newobj = -1;
  113.  
  114.             if (curobj > 0 && curobj != newobj) {
  115.                 objc_change(popobj, curobj, 0, x, y, w, h,
  116.                     NORMAL, 1);
  117.             }
  118.             curobj = newobj;
  119.             if (curobj > 0 && popobj[curobj].ob_state != DISABLED) {
  120.                 objc_change(popobj, curobj, 0,x,y,w,h,
  121.                         SELECTED, 1);
  122.             } else {
  123.                 curobj = -1;
  124.             }
  125.         }
  126.         if (event & MU_KEYBD) {
  127.             lowbyte = keycode & 0x00ff;
  128.             i = 1;
  129.             for (e = m->contents; e; e = e->next) {
  130.                 if ((lowbyte && e->keycode == lowbyte) ||
  131.                      e->keycode == keycode) {
  132.                     curobj = i;
  133.                     event |= MU_BUTTON;
  134.                     break;
  135.                 } else i++;
  136.             }
  137.         }
  138.         if (event & MU_BUTTON) {
  139.             break;
  140.         }
  141.     }
  142.  
  143. /* free memory allocated by `entrystr' */
  144.     for (i = 1; i < numobjects; i++)
  145.         free((void *)popobj[i].ob_spec);
  146.     free(popobj);
  147.     form_dial(3, x, y, w, h, x, y, w, h);
  148.     wind_update(END_MCTRL);
  149.     if (curobj > 0) {
  150.         for (e = m->contents; e; e = e->next) {
  151.             --curobj;
  152.             if (curobj == 0) {
  153.                 (*e->func)(e->arg);
  154.                 break;
  155.             }
  156.         }
  157.     }
  158. }
  159.  
  160.