home *** CD-ROM | disk | FTP | other *** search
/ Computer Club Elmshorn Atari PD / CCE_PD.iso / pc / 0600 / CCE_0678.ZIP / CCE_0678.PD / E_GEM135 / SOURCE / POPUP.C < prev    next >
C/C++ Source or Header  |  1993-10-17  |  9KB  |  428 lines

  1.  
  2. #include "proto.h"
  3.  
  4. static int        ob_next(OBJECT *,int);
  5. static void     ob_change(OBJECT *,int,int);
  6. static int         ob_find(OBJECT *,int,int);
  7. static int        do_popup(OBJECT *,boolean,int,int *);
  8.  
  9. static int ob_next(OBJECT *tree,int start)
  10. {
  11.     reg OBJECT *obj;
  12.     reg int i = start;
  13.  
  14.     if (start<tree->ob_head)
  15.         start=tree->ob_head;
  16.     do
  17.     {
  18.         obj = tree + i;
  19.         if ((obj->ob_state & DISABLED)==0 && (obj->ob_flags & (SELECTABLE|HIDETREE))==SELECTABLE)
  20.             return(i);
  21.         i = obj->ob_next;
  22.     }
  23.     while (i>=0);
  24.     return(FAIL);
  25. }
  26.  
  27. static void ob_change(OBJECT *tree,int obj,int newstate)
  28. {
  29.     reg OBJECT *ob = tree + obj;
  30.     int x,y;
  31.  
  32.     objc_offset(tree,obj,&x,&y);
  33.     objc_change(tree,obj,0,x,y,ob->ob_width,ob->ob_height,newstate,1);
  34. }
  35.  
  36. static int ob_find(OBJECT *tree,int x,int y)
  37. {
  38.     reg int pos = objc_find(tree,ROOT,1,x,y);
  39.  
  40.     if (pos>0 && ob_next(tree,pos)==pos)
  41.         return(pos);
  42.     else
  43.         return(FAIL);
  44. }
  45.  
  46. static int do_popup(OBJECT *menu,boolean wrap,int last,int *dc)
  47. {
  48.     reg int current,old = FAIL,ret = FAIL;
  49.  
  50.     EVENT events =
  51.     {
  52.         MU_BUTTON | MU_M1 | MU_M2 | MU_KEYBD,
  53.         1,1,1,0,0,0,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,0,
  54.         {0,0,0,0,0,0,0,0}
  55.     };
  56.  
  57.     _mouse_pos(&events.ev_mmox,&events.ev_mmoy);
  58.     if ((current = ob_find(menu,events.ev_mmox,events.ev_mmoy))<=0)
  59.         current = last;
  60.  
  61.     for (;;)
  62.     {
  63.         reg int mpos;
  64.  
  65.         if (current!=old)
  66.         {
  67.             if (old>0)
  68.                 ob_change(menu,old,menu[old].ob_state & (~SELECTED));
  69.             
  70.             if (current>0)
  71.                 ob_change(menu,current,menu[current].ob_state | SELECTED);
  72.  
  73.             old = current;
  74.         }
  75.  
  76.         if ((mpos = objc_find(menu,ROOT,1,events.ev_mmox,events.ev_mmoy)) < 0)
  77.         {
  78.             events.ev_mm1flags    = 0;
  79.             events.ev_mm1x        = menu->ob_x;
  80.             events.ev_mm1y        = menu->ob_y;
  81.             events.ev_mm1width    = menu->ob_width;
  82.             events.ev_mm1height    = menu->ob_height;
  83.             events.ev_mflags    &= ~MU_M2;
  84.         }
  85.         else
  86.         {
  87.             events.ev_mm1flags    = 1;
  88.             objc_offset(menu,mpos,&events.ev_mm1x,&events.ev_mm1y);
  89.             events.ev_mm1width    = menu[mpos].ob_width;
  90.             events.ev_mm1height    = menu[mpos].ob_height;
  91.             events.ev_mm2x        = events.ev_mmox;
  92.             events.ev_mm2y        = events.ev_mmoy;
  93.             events.ev_mflags    |= MU_M2;
  94.         }
  95.         
  96.         events.ev_mwich = Event_Multi(&events,0);
  97.         if (events.ev_mwich & MU_BUTTON)
  98.         {
  99.             if (!(events.ev_mmobutton & 1))
  100.             {
  101.                 ret = ob_find(menu,events.ev_mmox,events.ev_mmoy);
  102.                 break;
  103.             }
  104.             else
  105.                 events.ev_mbstate = 0;
  106.         }
  107.  
  108.         if (events.ev_mwich & (MU_M1|MU_M2))
  109.         {
  110.             current = ob_find(menu,events.ev_mmox,events.ev_mmoy);
  111.             
  112.             if (events.ev_mwich & MU_M2)
  113.             {
  114.                 events.ev_mm2x = events.ev_mmox;
  115.                 events.ev_mm2y = events.ev_mmoy;
  116.             }
  117.         }
  118.         
  119.         if (events.ev_mwich & MU_KEYBD)
  120.         {
  121.             int exitmode = FALSE;
  122.  
  123.             switch (events.ev_mkreturn & 0x00ff)
  124.             {
  125.             case 13:
  126.             case 32:
  127.                 ret = current;
  128.                 exitmode = TRUE;
  129.                 break;
  130.             case 27:
  131.                 ret = FAIL;
  132.                 exitmode = TRUE;
  133.             }
  134.  
  135.             if (exitmode==FALSE)
  136.             {
  137.                 switch (events.ev_mkreturn>>8)
  138.                 {
  139.                 case 97:
  140.                     ret = FAIL;
  141.                     exitmode = TRUE;
  142.                     break;
  143.                 case 71:
  144.                     if (events.ev_mmokstate & 3)
  145.                     {
  146.                         reg int j;
  147.     
  148.                         for (j=menu->ob_head;j<=menu->ob_tail;j++)
  149.                             if ((menu[j].ob_state & DISABLED)==0 && (menu[j].ob_flags & (SELECTABLE|HIDETREE))==SELECTABLE)
  150.                                  current = j;
  151.                     }
  152.                     else
  153.                         current = ob_next(menu,menu->ob_head);
  154.                     break;
  155.                 case 75:
  156.                 case 72:
  157.                     {
  158.                         reg int j,temp = FAIL;
  159.  
  160.                         if (current>menu->ob_head)
  161.                         {
  162.                             for (j=menu->ob_head;j<current;j++)
  163.                                 if ((menu[j].ob_state & DISABLED)==0 && (menu[j].ob_flags & (SELECTABLE|HIDETREE))==SELECTABLE)
  164.                                      temp = j;
  165.                         }
  166.  
  167.                         if (temp<0 && (wrap || current<0))
  168.                         {
  169.                             for (j=menu->ob_head;j<=menu->ob_tail;j++)
  170.                                 if ((menu[j].ob_state & DISABLED)==0 && (menu[j].ob_flags & (SELECTABLE|HIDETREE))==SELECTABLE)
  171.                                      temp = j;
  172.                         }
  173.  
  174.                         if (temp>0)
  175.                             current = temp;
  176.                     }
  177.                     break;
  178.                 case 77:
  179.                 case 80:
  180.                     if (current<menu->ob_tail)
  181.                     {
  182.                         if (current<0)
  183.                             current = ob_next(menu,menu->ob_head);
  184.                         else
  185.                         {
  186.                             int temp = ob_next(menu,menu[current].ob_next);
  187.                             if (temp>0 && temp!=current)
  188.                                 current = temp;
  189.                             else
  190.                                 current = ob_next(menu,menu->ob_head);
  191.                         }
  192.                     }
  193.                     else if (wrap)
  194.                         current = ob_next(menu,menu->ob_head);
  195.                     break;
  196.                 default:
  197.                     {
  198.                         int obj;
  199.     
  200.                         if ((obj=_is_hotkey(menu,events.ev_mkreturn,events.ev_mmokstate))>0)
  201.                         {
  202.                             if ((menu[obj].ob_state & DISABLED)==0 && (menu[obj].ob_flags & (SELECTABLE|HIDETREE))==SELECTABLE)
  203.                             {
  204.                                 if (old>0)
  205.                                     ob_change(menu,old,menu[old].ob_state & (~SELECTED));
  206.                                 ob_change(menu,obj,menu[obj].ob_state | SELECTED);
  207.                                 evnt_timer(150,0);
  208.     
  209.                                 exitmode = TRUE;
  210.                                 ret = obj;
  211.                             }
  212.                         }
  213.                     }
  214.                 }
  215.             }
  216.  
  217.             if (exitmode)
  218.                 break;
  219.         }
  220.     }
  221.  
  222.     if (ret>0)
  223.         *dc = (events.ev_mbreturn>=2 || (events.ev_mmokstate & 3));
  224.     return (ret);
  225. }
  226.  
  227. int Popup(POPUP *popup,int mode,int center,int x,int y,int *index,int select)
  228. {
  229.     reg DIAINFO *info = popup->p_info;
  230.     reg OBJECT    *menu = popup->p_menu,*tree = info->di_tree;
  231.     reg int current = FAIL,exit = FAIL,object;
  232.     int dc = FALSE;
  233.  
  234.     graf_mouse(ARROW,NULL);
  235.  
  236.     if (info)
  237.     {
  238.         object = (mode & POPUP_CYCLE) ? popup->p_cycle : popup->p_parent;
  239.         if (object>0)
  240.             ob_draw_chg(info,object,NULL,tree[object].ob_state|SELECTED,FALSE);
  241.     }
  242.  
  243.     {
  244.         reg int i;
  245.  
  246.         for (i=menu->ob_head;i<=menu->ob_tail;i++)
  247.         {
  248.             if (menu[i].ob_flags & SELECTABLE)
  249.                 menu[i].ob_state &= ~SELECTED;
  250.  
  251.             if (!(menu[i].ob_flags & HIDETREE))
  252.             {
  253.                 if (i==select)
  254.                 {
  255.                     if (mode & POPUP_CHECK)
  256.                         menu[i].ob_state |= CHECKED;
  257.                     if (current>=0)
  258.                         menu[current].ob_state &= ~CHECKED;
  259.                     current=i;
  260.                 }
  261.                 else if (menu[i].ob_state & CHECKED)
  262.                 {
  263.                     if (!(mode & POPUP_CHECK) || current>=0)
  264.                         menu[i].ob_state &= ~CHECKED;
  265.                     else
  266.                         current = i;
  267.                 }
  268.             }
  269.         }
  270.     }
  271.  
  272.     if (!(mode & POPUP_CYCLE))
  273.     {
  274.         int sx,sy,sw = menu->ob_width>>1,sh = menu->ob_height>>1,dummy;
  275.         long mem = 0l;
  276.         MFDB dial;
  277.  
  278.         _mouse_pos(&sx,&sy);
  279.         if (info && popup->p_button>0)
  280.         {
  281.             int bx,by;
  282.             objc_offset(tree,popup->p_button,&bx,&by);
  283.             if (x<=0)
  284.                 x = bx;
  285.             if (y<=0)
  286.                 y = by;
  287.         }
  288.  
  289.         switch (center)
  290.         {
  291.         case CENTER:
  292.             {
  293.                 INFOVSCR *vscr;
  294.  
  295.                 form_center(menu,&dummy,&dummy,&dummy,&dummy);
  296.                 if (get_cookie(COOKIE_VSCR,(long *) &vscr) && (vscr->cookie==COOKIE_XBRA))
  297.                 {
  298.                     menu->ob_x = vscr->x + (vscr->w>>1) - sw;
  299.                     menu->ob_y = vscr->y + (vscr->h>>1) - sh;
  300.                 }
  301.             }
  302.             break;
  303.         case XYPOS:
  304.             menu->ob_x = x;
  305.             menu->ob_y = y;
  306.             break;
  307.         case MOUSEPOS:
  308.             menu->ob_x = sx - sw;
  309.             menu->ob_y = sy - sh;
  310.             break;
  311.         case XPOS:
  312.             menu->ob_x = x;
  313.             menu->ob_y = sy - sh;
  314.             break;
  315.         case YPOS:
  316.             menu->ob_x = sx - sw;
  317.             menu->ob_y = y;
  318.             break;
  319.         case OBJPOS:
  320.             menu->ob_x = x;
  321.             menu->ob_y = y;
  322.             if (current>=0)
  323.             {
  324.                 menu->ob_x -= menu[current].ob_x;
  325.                 menu->ob_y -= menu[current].ob_y;
  326.             }
  327.         }
  328.  
  329.         Min(&menu->ob_x,clip.v_x2 - menu->ob_width - 3);
  330.         Max(&menu->ob_x,clip.v_x1 + 3);
  331.         Min(&menu->ob_y,clip.v_y2 - menu->ob_height - 3);
  332.         Max(&menu->ob_y,clip.v_y1 + 3);
  333.  
  334.         sx = menu->ob_x - 3;
  335.         sy = menu->ob_y - 3;
  336.         sw = menu->ob_width + 6;
  337.         sh = menu->ob_height + 6;
  338.  
  339.         _beg_ctrl();
  340.         mfdb(&dial,NULL,sw,sh,0,planes);
  341.         
  342.         {
  343.             reg long len = mfdb_size(&dial);
  344.  
  345.             if ((long) Malloc(-1l)>(len+4096l))
  346.             {
  347.                 if ((mem = (long) Malloc(len+256l))>0l)
  348.                 {
  349.                     dial.fd_addr    = (int *) ((mem & 0xfffffffel) + 2);
  350.                     _bitblt(menu,&dial,TRUE);
  351.                     goto draw_popup;
  352.                 }
  353.             }
  354.         }
  355.  
  356.         form_dial(FMD_START,sx,sy,sw,sh,sx,sy,sw,sh);
  357.         
  358.         draw_popup:
  359.         objc_draw(menu,ROOT,MAX_DEPTH,sx,sy,sw,sh);
  360.         exit = do_popup(menu,popup->p_wrap,current,&dc);
  361.  
  362.         if (mem)
  363.         {
  364.             _bitblt(menu,&dial,FALSE);
  365.             Mfree((void *) mem);
  366.         }
  367.         else
  368.             form_dial(FMD_FINISH,sx,sy,sw,sh,sx,sy,sw,sh);
  369.         _end_ctrl();
  370.     }
  371.     else
  372.     {
  373.         if (current<0 || current>=menu->ob_tail)
  374.             exit = ob_next(menu,menu->ob_head);
  375.         else
  376.         {
  377.             int temp = ob_next(menu,menu[current].ob_next);
  378.             exit = (temp>0) ? temp : ob_next(menu,menu->ob_head);
  379.         }
  380.         evnt_timer(50,0);
  381.     }
  382.  
  383.     if (info && object>0)
  384.         ob_draw_chg(info,object,NULL,tree[object].ob_state & (~SELECTED),FALSE);
  385.  
  386.     if (exit>0)
  387.     {
  388.         if (mode & POPUP_CHECK)
  389.         {
  390.             if (current>=0)
  391.                 menu[current].ob_state &= ~CHECKED;
  392.             menu[exit].ob_state |= CHECKED;
  393.         }
  394.  
  395.         if (info && popup->p_set && popup->p_button>0)
  396.         {
  397.             ob_set_text(tree,popup->p_button,ob_get_text(menu,exit,0));
  398.             ob_draw_chg(info,popup->p_button,NULL,FAIL,FALSE);
  399.             if (popup->p_cycle>0)
  400.                 ob_draw_chg(info,popup->p_cycle,NULL,FAIL,FALSE);
  401.         }
  402.  
  403.         if (index)
  404.         {
  405.             reg int i = 1,radio = 0;
  406.  
  407.             do
  408.             {
  409.                 if ((menu[i].ob_flags & (SELECTABLE|HIDETREE))==SELECTABLE)
  410.                 {
  411.                     if (i==exit)
  412.                     {
  413.                         *index = radio;
  414.                         break;
  415.                     }
  416.                     radio++;
  417.                 }
  418.                 i = menu[i].ob_next;
  419.             } while (i>=0);
  420.         }
  421.     }
  422.  
  423.     if (exit<=0)
  424.         return(0);
  425.     else
  426.         return ((dc) ? (exit|0x8000) : exit);
  427. }
  428.