home *** CD-ROM | disk | FTP | other *** search
- /* tab expansion/compression should be set to 4 in your editor */
- /**************************************************************************
- *
- * WINDXMPL.C - Demo of handling an object tree in a window, with minimal
- * emulation of form_do processing. (And with a special demo
- * of editing a text field based on either a mouse click or
- * a menu selection; a strange feature someone asked for.)
- *
- * This file demos many of the alternate AES bindings
- * routines such as frmx_center and evnx_multi.
- *************************************************************************/
-
- #include <osbind.h>
- #include <gemfast.h>
- #include "windxmpl.h"
-
- #define WI_KIND (SIZER+MOVER+CLOSER+NAME)
- #define NO_WINDOW -1
-
- #define TRUE 1
- #define FALSE 0
-
- OBJECT *menutree;
- OBJECT *windtree;
-
- int wchar;
- int hchar;
- int wi_handle = NO_WINDOW;
- char wi_name[] = " Window Demo ";
-
- extern int gl_apid;
-
- /**************************************************************************
- *
- * prg_init - Standard GEM startup.
- *
- *************************************************************************/
-
- prg_init()
- {
- int dmy;
-
- appl_init();
-
- if (!rsrc_load("WINDXMPL.RSC")) {
- form_alert(1,"[1][ | Can't load RSC! | ][ Fatal ]");
- appl_exit();
- Pterm(1);
- }
-
- graf_handle(&wchar, &hchar, &dmy, &dmy); /* For window min sizes */
-
- rsrc_gaddr(R_TREE, MENUTREE, &menutree);
- rsrc_gaddr(R_TREE, WINDTREE, &windtree);
-
- menu_bar(menutree, TRUE);
-
- graf_mouse(ARROW, 0L);
- }
-
- /**************************************************************************
- *
- * prg_exit - Standard GEM exit.
- *
- *************************************************************************/
-
- prg_exit()
- {
- w_close();
- menu_bar(menutree, FALSE);
- rsrc_free();
- appl_exit();
- Pterm(0);
- }
-
- /**************************************************************************
- *
- * w_open - Create and open a window.
- * The display tree is centered, then the window is sized to hold it.
- *
- *************************************************************************/
-
- w_open()
- {
- GRECT wrect;
- GRECT treerect;
-
- if (wi_handle != NO_WINDOW) { /* if window is already open, */
- return wi_handle; /* just return the handle. */
- }
-
- frmx_center(windtree, &treerect); /* center tree, sizes in treerect */
-
- winx_calc(WC_BORDER, WI_KIND, treerect, &wrect); /* calc window fullsize */
-
- wi_handle = wind_create(WI_KIND, wrect); /* create window */
-
- if (wi_handle < 0) {
- form_error(4); /* can't open another window */
- wi_handle = NO_WINDOW;
- } else {
- wind_set(wi_handle, WF_NAME, wi_name, 0L); /* set window title */
- wind_open(wi_handle, wrect); /* open window */
- }
-
- return wi_handle;
-
- }
-
- /**************************************************************************
- *
- * w_close - Close and delete a window.
- *
- *************************************************************************/
-
- w_close()
- {
- if (wi_handle != NO_WINDOW) { /* only do close processing */
- wind_close(wi_handle); /* if the window is open! */
- wind_delete(wi_handle);
- wi_handle = NO_WINDOW;
- }
- }
-
- /**************************************************************************
- *
- * do_redraw - Standard AES redraw handler for trees in windows.
- *
- *************************************************************************/
-
- do_redraw(window, ptree, predrawrect)
- register int window;
- register OBJECT *ptree;
- register GRECT *predrawrect;
- {
- register int calltype;
- register int doneflag;
- GRECT t1;
- GRECT t2;
-
- /*
- * process the rectangle list for the window. for each intersection of
- * the area to be redrawn with a visible window rectangle, call objc_draw
- * to draw that portion of the menu.
- */
-
- wind_update(BEG_UPDATE);
-
- calltype = WF_FIRSTXYWH;
- doneflag = FALSE;
-
- do {
- winx_get(window, calltype, &t1);
- if (t1.g_w && t1.g_h) {
- if (rc_intersect(predrawrect, &t1) && t1.g_w && t1.g_h) {
- objc_draw(ptree, R_TREE, MAX_DEPTH, t1);
- }
- } else {
- doneflag = TRUE;
- }
- calltype = WF_NEXTXYWH;
- } while (doneflag == FALSE);
-
- wind_update(END_UPDATE);
- }
-
- /**************************************************************************
- *
- * send_edmsg - Send a message to ourselves to edit the window field.
- * The message looks exactly like a normal MN_SELECTED.
- * This allows us to re-schedule the edit function after topping our
- * window, in case the user picks the EDIT menu item while an ACC
- * window is topped.
- *
- *************************************************************************/
-
- send_edmsg()
- {
- static int edmsg[8] = {MN_SELECTED, 0, 0, MENUFILE, MENUEDFN};
-
- edmsg[1] = gl_apid;
- appl_write(gl_apid, 16, edmsg);
- }
-
- /**************************************************************************
- *
- * hndl_message - Standard message handling code.
- *
- *************************************************************************/
-
- hndl_message(msgbuf)
- register int *msgbuf;
- {
- int dmy;
- int top_window;
- register OBJECT *ptree = windtree;
- GRECT t1, t2;
-
- switch (msgbuf[0]) {
-
- case MN_SELECTED:
-
- switch (msgbuf[4]) {
- case MENUQUIT:
-
- prg_exit();
- break;
-
- case MENUEDFN:
-
- /*-------------------------------------------------------------------------
- * Handling the EDIT FILENAME menu item...
- *
- * For a request to edit the field in the window, we must first ensure
- * that our window is topped (an ACC could be topped). If not, we do
- * a wind_set() call to top it, because allowing editing in a background
- * window goes against all GEM concepts. After forcing the window to the
- * top, we send an edit request back to ourselves, because our window
- * doesn't really become topped until we receive back the corresponding
- * redraw messages.
- *
- * We call menu_tnormal() to visually highlight the FILE title; if we're
- * here because of a message we sent ourselves, the title won't already
- * be highlighted. If we're here because of a genuine menu selection
- * by the user, it doesn't hurt to do the call anyway.
- *
- * If our window is topped, we call form_do() to handle the editing. A
- * nasty side effect of form_do() is that it will visually SELECT the
- * edit field when the user hits return, so we immediately de-select it.
- *
- * Before starting the edit dialog, we set the ob_flags value for the
- * filename edit field to EDITABLE, EXIT, and DEFAULT. This allows the
- * user to type in text and hit <CR> (a natural action), and the <CR>
- * causes an exit from form_do() processing because of the DEFAULT flag
- * on the edit field. (What, you thought only buttons could be DEFAULT?)
- * When the edit is done, we reset the ob_flags for the edit field.
- *-----------------------------------------------------------------------*/
-
- menu_tnormal(menutree, MENUFILE, FALSE);
- wind_get(0, WF_TOP, &top_window, &dmy, &dmy, &dmy);
- if (wi_handle != top_window) {
- wind_set(wi_handle, WF_TOP, 0L, 0L);
- send_edmsg();
- } else {
- wind_update(BEG_UPDATE);
- ptree[WINDTEFN].ob_flags |= (EDITABLE|EXIT|DEFAULT);
- form_do(ptree, WINDTEFN);
- winx_get(wi_handle, WF_WORKXYWH, &t1);
- objc_change(ptree, WINDTEFN, 0, t1, NORMAL, TRUE);
- ptree[WINDTEFN].ob_flags &= ~(EDITABLE|EXIT|DEFAULT);
- wind_update(END_UPDATE);
- }
- break;
- }
- menu_tnormal(menutree, msgbuf[3], TRUE);
- break;
-
- case WM_CLOSED:
-
- prg_exit();
- break;
-
- case WM_TOPPED:
- case WM_NEWTOP:
-
- wind_set(msgbuf[3], WF_TOP, 0L, 0L);
- break;
-
- case WM_REDRAW:
-
- do_redraw(msgbuf[3], ptree, &msgbuf[4]);
- break;
-
- case WM_MOVED:
- case WM_SIZED:
-
- /*-------------------------------------------------------------------------
- * Handling SIZED and MOVED window requests...
- *
- * AES has given us the window outside dimensions of the user's mouse
- * activity with the window controls, convert to workarea dimensions.
- *
- * Reposition the object tree at the proper x/y to match the window.
- * Use rc_intersect() to ensure that a re-size operation does not exceed
- * the w/h dimensions of the object tree. Also, insure the window doesn't
- * get shrunk to an impossibly small size.
- *
- * Based on the workarea rectangle (possibly adjusted by rc_intersect),
- * calc the new outer dimensions, then call wind_set() to set them.
- * The wind_set() call will cause the AES to send us (and everyone else)
- * the appropriate redraw messages, which we'll get on the next iteration
- * of the event loop.
- *-----------------------------------------------------------------------*/
-
- t1 = *(GRECT *)(&msgbuf[4]);
- winx_calc(WC_WORK, WI_KIND, t1, &t2);
-
- ptree->ob_x = t2.g_x;
- ptree->ob_y = t2.g_y;
-
- rc_intersect(&ptree->ob_x, &t2);
- if (t2.g_w < wchar)
- t2.g_w = wchar;
- if (t2.g_h < hchar)
- t2.g_h = hchar;
-
- winx_calc(WC_BORDER, WI_KIND, t2, &t1);
- wind_set(msgbuf[3], WF_CURRXYWH, t1);
-
- break;
-
- } /* END switch (msgbuf[0]) */
-
- }
-
- /**************************************************************************
- *
- * hndl_button - Handle a button click in our window.
- *
- * This routine handles radio button clicks, and clicks on SELECTABLE
- * objects that are not DISABLED. It basically mimics the actions of
- * the form_do() click handler...radio button clicks are processed
- * immediately, then the mouse is ignored until the button is released.
- * Clicks on non-radio objects will track the mouse, and will handle
- * the object based on where the mouse is when the button is released.
- *
- * There is also a special-case handling for a click on the text edit
- * (filename) field: we send ourselves an edit-requested message, and
- * the edit dialog will get processed on the next iteration through the
- * main eventmulti loop.
- *************************************************************************/
-
- hndl_button(mx, my, mb)
- int mx, my, mb;
- {
- int dmy;
- register int oldobj;
- register int selobj;
- register int in_obj;
- register OBJECT *ptree = windtree;
- register OBJECT *pobj;
- GRECT windrect;
-
- selobj = objc_find(ptree, R_TREE, MAX_DEPTH, mx, my);
- pobj = &ptree[selobj];
-
- if (selobj <= R_TREE || (pobj->ob_state & DISABLED) ) {
- return NO_OBJECT;
- }
-
- if (selobj == WINDTEFN) {
- send_edmsg();
- evnt_button(1,1,0, &dmy, &dmy, &dmy, &dmy);
- return 0;
- }
-
- wind_update(BEG_UPDATE);
-
- if (pobj->ob_flags & RBUTTON) { /* handle radio buttons */
-
- oldobj = obj_rbselect(ptree, selobj, SELECTED);
- winx_get(wi_handle, WF_WORKXYWH, &windrect);
- objc_draw(ptree, selobj, MAX_DEPTH, windrect);
- if (oldobj > R_TREE) {
- objc_draw(ptree, oldobj, MAX_DEPTH, windrect);
- }
-
- evnt_button(1,1,0, &dmy, &dmy, &dmy, &dmy);
- in_obj = TRUE;
-
- } else { /* handle on/off buttons */
-
- if (pobj->ob_flags & SELECTABLE) {
- in_obj = graf_watchbox(ptree, selobj,
- (pobj->ob_state ^ SELECTED),
- pobj->ob_state);
- }
- }
-
- wind_update(END_UPDATE);
-
- if (in_obj == FALSE) {
- selobj = NO_OBJECT; /* Nothing changed */
- } else {
- if (!(pobj->ob_flags & EXIT)) {
- selobj = 0; /* Click on non-EXIT object */
- }
- }
-
- return selobj;
- }
-
- /**************************************************************************
- *
- * main driver.
- *
- *************************************************************************/
-
- main()
- {
- int event;
- XMULTI xm;
-
- prg_init();
-
- if (NO_WINDOW == w_open()) {
- prg_exit();
- }
-
- xm.mflags = MU_MESAG | MU_BUTTON;
- xm.mbmask = 1;
- xm.mbclicks = 1;
- xm.mbstate = 1;
-
- while (1) {
- event = evnx_multi(&xm);
-
- if (event & MU_MESAG) {
- hndl_message(xm.msgbuf);
- }
- if (event & MU_BUTTON) {
- hndl_button(xm.mmox, xm.mmoy, xm.mmobutton);
- }
- }
- }
-