home *** CD-ROM | disk | FTP | other *** search
/ SPACE 2 / SPACE - Library 2 - Volume 1.iso / program / 331 / gemfxm14 / windxmpl.c < prev    next >
Encoding:
C/C++ Source or Header  |  1990-07-20  |  11.6 KB  |  426 lines

  1. /* tab expansion/compression should be set to 4 in your editor */
  2. /**************************************************************************
  3.  *
  4.  * WINDXMPL.C - Demo of handling an object tree in a window, with minimal
  5.  *                emulation of form_do processing. (And with a special demo
  6.  *                of editing a text field based on either a mouse click or
  7.  *                a menu selection; a strange feature someone asked for.)
  8.  *
  9.  *                This file demos many of the alternate AES bindings 
  10.  *                routines such as frmx_center and evnx_multi.
  11.  *************************************************************************/
  12.  
  13. #include <osbind.h>
  14. #include <gemfast.h> 
  15. #include "windxmpl.h"
  16.  
  17. #define WI_KIND     (SIZER+MOVER+CLOSER+NAME)
  18. #define NO_WINDOW    -1
  19.  
  20. #define TRUE  1
  21. #define FALSE 0
  22.  
  23. OBJECT    *menutree;
  24. OBJECT    *windtree;
  25.  
  26. int     wchar;
  27. int     hchar;
  28. int     wi_handle = NO_WINDOW;
  29. char    wi_name[] = " Window Demo ";
  30.  
  31. extern int    gl_apid;
  32.  
  33. /**************************************************************************
  34.  *
  35.  * prg_init - Standard GEM startup.
  36.  *
  37.  *************************************************************************/
  38.  
  39. prg_init()
  40. {
  41.     int  dmy;
  42.     
  43.     appl_init();
  44.     
  45.     if (!rsrc_load("WINDXMPL.RSC")) {
  46.         form_alert(1,"[1][ | Can't load RSC! | ][ Fatal ]");
  47.         appl_exit();
  48.         Pterm(1);
  49.     }
  50.  
  51.     graf_handle(&wchar, &hchar, &dmy, &dmy);    /* For window min sizes */
  52.  
  53.     rsrc_gaddr(R_TREE, MENUTREE, &menutree);
  54.     rsrc_gaddr(R_TREE, WINDTREE, &windtree);
  55.  
  56.     menu_bar(menutree, TRUE);
  57.  
  58.     graf_mouse(ARROW, 0L);      
  59. }
  60.  
  61. /**************************************************************************
  62.  *
  63.  * prg_exit - Standard GEM exit.
  64.  *
  65.  *************************************************************************/
  66.  
  67. prg_exit()
  68. {
  69.     w_close();
  70.     menu_bar(menutree, FALSE);
  71.     rsrc_free();
  72.     appl_exit();
  73.     Pterm(0);
  74. }
  75.  
  76. /**************************************************************************
  77.  *
  78.  * w_open - Create and open a window.
  79.  *    The display tree is centered, then the window is sized to hold it.
  80.  *
  81.  *************************************************************************/
  82.  
  83. w_open()
  84. {
  85.     GRECT    wrect;
  86.     GRECT    treerect;
  87.     
  88.     if (wi_handle != NO_WINDOW) {        /* if window is already open,      */
  89.         return wi_handle;                /* just return the handle.          */
  90.     }
  91.  
  92.     frmx_center(windtree, &treerect);    /* center tree, sizes in treerect */
  93.  
  94.     winx_calc(WC_BORDER, WI_KIND, treerect, &wrect); /* calc window fullsize */
  95.  
  96.     wi_handle = wind_create(WI_KIND, wrect);         /* create window      */
  97.  
  98.     if (wi_handle < 0) {
  99.         form_error(4);                        /* can't open another window  */
  100.         wi_handle = NO_WINDOW;
  101.     } else {
  102.         wind_set(wi_handle, WF_NAME, wi_name, 0L);    /* set window title   */
  103.         wind_open(wi_handle, wrect);                /* open window          */
  104.     }
  105.     
  106.     return wi_handle;
  107.  
  108. }
  109.  
  110. /**************************************************************************
  111.  *
  112.  * w_close - Close and delete a window.
  113.  *
  114.  *************************************************************************/
  115.  
  116. w_close()
  117. {
  118.     if (wi_handle != NO_WINDOW) {    /* only do close processing */
  119.         wind_close(wi_handle);        /* if the window is open!    */
  120.         wind_delete(wi_handle);
  121.         wi_handle = NO_WINDOW;
  122.     }
  123. }
  124.  
  125. /**************************************************************************
  126.  *
  127.  * do_redraw - Standard AES redraw handler for trees in windows.
  128.  *
  129.  *************************************************************************/
  130.  
  131. do_redraw(window, ptree, predrawrect)
  132.     register int      window;
  133.     register OBJECT   *ptree;
  134.     register GRECT      *predrawrect;
  135. {
  136.     register int      calltype;
  137.     register int      doneflag;
  138.     GRECT              t1;
  139.     GRECT              t2;
  140.  
  141. /*
  142.  * process the rectangle list for the window.  for each intersection of
  143.  * the area to be redrawn with a visible window rectangle, call objc_draw
  144.  * to draw that portion of the menu.
  145.  */
  146.  
  147.     wind_update(BEG_UPDATE);
  148.     
  149.     calltype = WF_FIRSTXYWH;
  150.     doneflag = FALSE;
  151.  
  152.     do    {
  153.         winx_get(window, calltype, &t1);
  154.         if (t1.g_w && t1.g_h) {
  155.             if (rc_intersect(predrawrect, &t1) && t1.g_w && t1.g_h) {
  156.                 objc_draw(ptree, R_TREE, MAX_DEPTH, t1);
  157.             }
  158.         } else {
  159.             doneflag = TRUE;
  160.         }
  161.         calltype = WF_NEXTXYWH;
  162.     } while (doneflag == FALSE);
  163.  
  164.     wind_update(END_UPDATE);
  165. }
  166.  
  167. /**************************************************************************
  168.  *
  169.  * send_edmsg - Send a message to ourselves to edit the window field.
  170.  *    The message looks exactly like a normal MN_SELECTED.
  171.  *    This allows us to re-schedule the edit function after topping our 
  172.  *    window, in case the user picks the EDIT menu item while an ACC
  173.  *    window is topped.
  174.  *
  175.  *************************************************************************/
  176.  
  177. send_edmsg()
  178. {
  179.     static int    edmsg[8] = {MN_SELECTED, 0, 0, MENUFILE, MENUEDFN};
  180.     
  181.     edmsg[1] = gl_apid;
  182.     appl_write(gl_apid, 16, edmsg);
  183. }
  184.  
  185. /**************************************************************************
  186.  *
  187.  * hndl_message - Standard message handling code.
  188.  *
  189.  *************************************************************************/
  190.  
  191. hndl_message(msgbuf)
  192.     register int    *msgbuf;
  193. {
  194.     int             dmy;
  195.     int             top_window;
  196.     register OBJECT *ptree = windtree;
  197.     GRECT            t1, t2;
  198.  
  199.     switch (msgbuf[0]) {
  200.             
  201.     case MN_SELECTED:
  202.  
  203.         switch (msgbuf[4]) {
  204.         case MENUQUIT:
  205.  
  206.             prg_exit();
  207.             break;
  208.  
  209.         case MENUEDFN:
  210.  
  211. /*-------------------------------------------------------------------------
  212.  * Handling the EDIT FILENAME menu item...
  213.  *
  214.  * For a request to edit the field in the window, we must first ensure
  215.  * that our window is topped (an ACC could be topped).    If not, we do
  216.  * a wind_set() call to top it, because allowing editing in a background
  217.  * window goes against all GEM concepts.  After forcing the window to the
  218.  * top, we send an edit request back to ourselves, because our window
  219.  * doesn't really become topped until we receive back the corresponding
  220.  * redraw messages.
  221.  *
  222.  * We call menu_tnormal() to visually highlight the FILE title; if we're
  223.  * here because of a message we sent ourselves, the title won't already
  224.  * be highlighted.    If we're here because of a genuine menu selection
  225.  * by the user, it doesn't hurt to do the call anyway.
  226.  *
  227.  * If our window is topped, we call form_do() to handle the editing.  A
  228.  * nasty side effect of form_do() is that it will visually SELECT the
  229.  * edit field when the user hits return, so we immediately de-select it.
  230.  *
  231.  * Before starting the edit dialog, we set the ob_flags value for the
  232.  * filename edit field to EDITABLE, EXIT, and DEFAULT.    This allows the
  233.  * user to type in text and hit <CR> (a natural action), and the <CR>
  234.  * causes an exit from form_do() processing because of the DEFAULT flag
  235.  * on the edit field.  (What, you thought only buttons could be DEFAULT?)
  236.  * When the edit is done, we reset the ob_flags for the edit field.
  237.  *-----------------------------------------------------------------------*/
  238.  
  239.             menu_tnormal(menutree, MENUFILE, FALSE);
  240.             wind_get(0, WF_TOP, &top_window, &dmy, &dmy, &dmy);
  241.             if (wi_handle != top_window) {
  242.                 wind_set(wi_handle, WF_TOP, 0L, 0L);
  243.                 send_edmsg();
  244.             } else {
  245.                 wind_update(BEG_UPDATE);
  246.                 ptree[WINDTEFN].ob_flags |=  (EDITABLE|EXIT|DEFAULT);
  247.                 form_do(ptree, WINDTEFN);
  248.                 winx_get(wi_handle, WF_WORKXYWH, &t1);
  249.                 objc_change(ptree, WINDTEFN, 0, t1, NORMAL, TRUE);
  250.                 ptree[WINDTEFN].ob_flags &= ~(EDITABLE|EXIT|DEFAULT);
  251.                 wind_update(END_UPDATE);
  252.             }
  253.             break;
  254.         }
  255.         menu_tnormal(menutree, msgbuf[3], TRUE);
  256.         break;
  257.  
  258.     case WM_CLOSED:
  259.  
  260.         prg_exit();
  261.         break;
  262.  
  263.     case WM_TOPPED:
  264.     case WM_NEWTOP:
  265.  
  266.         wind_set(msgbuf[3], WF_TOP, 0L, 0L);
  267.         break;
  268.         
  269.     case WM_REDRAW:
  270.  
  271.         do_redraw(msgbuf[3], ptree, &msgbuf[4]);
  272.         break;
  273.  
  274.     case WM_MOVED:
  275.     case WM_SIZED:
  276.  
  277. /*-------------------------------------------------------------------------
  278.  * Handling SIZED and MOVED window requests...
  279.  *
  280.  * AES has given us the window outside dimensions of the user's mouse
  281.  * activity with the window controls, convert to workarea dimensions.
  282.  *
  283.  * Reposition the object tree at the proper x/y to match the window.
  284.  * Use rc_intersect() to ensure that a re-size operation does not exceed
  285.  * the w/h dimensions of the object tree.  Also, insure the window doesn't
  286.  * get shrunk to an impossibly small size.
  287.  *
  288.  * Based on the workarea rectangle (possibly adjusted by rc_intersect),
  289.  * calc the new outer dimensions, then call wind_set() to set them.
  290.  * The wind_set() call will cause the AES to send us (and everyone else)
  291.  * the appropriate redraw messages, which we'll get on the next iteration
  292.  * of the event loop.
  293.  *-----------------------------------------------------------------------*/
  294.  
  295.         t1 = *(GRECT *)(&msgbuf[4]);
  296.         winx_calc(WC_WORK, WI_KIND, t1, &t2);
  297.  
  298.         ptree->ob_x = t2.g_x;
  299.         ptree->ob_y = t2.g_y;
  300.  
  301.         rc_intersect(&ptree->ob_x, &t2);
  302.         if (t2.g_w < wchar)
  303.             t2.g_w = wchar;
  304.         if (t2.g_h < hchar)
  305.             t2.g_h = hchar;
  306.  
  307.         winx_calc(WC_BORDER, WI_KIND, t2, &t1);
  308.         wind_set(msgbuf[3], WF_CURRXYWH, t1);
  309.  
  310.         break;
  311.                 
  312.     } /* END switch (msgbuf[0]) */
  313.  
  314. }
  315.  
  316. /**************************************************************************
  317.  *
  318.  * hndl_button - Handle a button click in our window.
  319.  *
  320.  *    This routine handles radio button clicks, and clicks on SELECTABLE
  321.  *    objects that are not DISABLED.    It basically mimics the actions of
  322.  *    the form_do() click handler...radio button clicks are processed
  323.  *    immediately, then the mouse is ignored until the button is released.
  324.  *    Clicks on non-radio objects will track the mouse, and will handle
  325.  *    the object based on where the mouse is when the button is released.
  326.  *
  327.  *    There is also a special-case handling for a click on the text edit
  328.  *    (filename) field:  we send ourselves an edit-requested message, and
  329.  *    the edit dialog will get processed on the next iteration through the
  330.  *    main eventmulti loop. 
  331.  *************************************************************************/
  332.  
  333. hndl_button(mx, my, mb)
  334.     int mx, my, mb;
  335. {
  336.     int             dmy;
  337.     register int    oldobj;
  338.     register int    selobj;
  339.     register int    in_obj;
  340.     register OBJECT *ptree = windtree;
  341.     register OBJECT *pobj;
  342.     GRECT            windrect;
  343.     
  344.     selobj = objc_find(ptree, R_TREE, MAX_DEPTH, mx, my);
  345.     pobj   = &ptree[selobj];
  346.     
  347.     if (selobj <= R_TREE || (pobj->ob_state & DISABLED) ) {
  348.         return NO_OBJECT;
  349.     }
  350.  
  351.     if (selobj == WINDTEFN) {
  352.         send_edmsg();
  353.         evnt_button(1,1,0, &dmy, &dmy, &dmy, &dmy);
  354.         return 0;
  355.     }
  356.  
  357.     wind_update(BEG_UPDATE);
  358.     
  359.     if (pobj->ob_flags & RBUTTON) { /* handle radio buttons */
  360.     
  361.         oldobj = obj_rbselect(ptree, selobj, SELECTED);
  362.         winx_get(wi_handle, WF_WORKXYWH, &windrect);
  363.         objc_draw(ptree, selobj, MAX_DEPTH, windrect);
  364.         if (oldobj > R_TREE) {
  365.             objc_draw(ptree, oldobj, MAX_DEPTH, windrect);
  366.         }
  367.         
  368.         evnt_button(1,1,0, &dmy, &dmy, &dmy, &dmy);
  369.         in_obj = TRUE;
  370.  
  371.     } else {                        /* handle on/off buttons */
  372.  
  373.         if (pobj->ob_flags & SELECTABLE) {
  374.             in_obj = graf_watchbox(ptree, selobj, 
  375.                                 (pobj->ob_state ^ SELECTED),
  376.                                  pobj->ob_state);
  377.         } 
  378.     }
  379.     
  380.     wind_update(END_UPDATE);
  381.  
  382.     if (in_obj == FALSE) {
  383.         selobj = NO_OBJECT;             /* Nothing changed            */
  384.     } else {
  385.         if (!(pobj->ob_flags & EXIT)) {
  386.             selobj = 0;                 /* Click on non-EXIT object */
  387.         }
  388.     }
  389.  
  390.     return selobj;
  391. }
  392.  
  393. /**************************************************************************
  394.  *
  395.  * main driver.
  396.  *
  397.  *************************************************************************/
  398.  
  399. main()
  400. {
  401.     int     event;
  402.     XMULTI    xm;
  403.  
  404.     prg_init();
  405.     
  406.     if (NO_WINDOW == w_open()) {
  407.         prg_exit();
  408.     }
  409.  
  410.     xm.mflags    = MU_MESAG | MU_BUTTON;
  411.     xm.mbmask    = 1;
  412.     xm.mbclicks = 1;
  413.     xm.mbstate    = 1;
  414.     
  415.     while (1) {
  416.         event = evnx_multi(&xm);
  417.  
  418.         if (event & MU_MESAG) {
  419.             hndl_message(xm.msgbuf);
  420.         }
  421.         if (event & MU_BUTTON) {
  422.             hndl_button(xm.mmox, xm.mmoy, xm.mmobutton);
  423.         }
  424.     }
  425. }
  426.