home *** CD-ROM | disk | FTP | other *** search
/ QBasic & Borland Pascal & C / Delphi5.iso / C / Samples / CSAPE32.ARJ / EXAMPLES / DEMOFM.C < prev    next >
C/C++ Source or Header  |  1991-03-09  |  16KB  |  609 lines

  1. /*
  2.     demofm.c
  3.  
  4.     jmd 6/89
  5.  
  6.     C-scape 3.2    Example Program
  7.     Copyright (c) 1989, 1990 by Oakland Group, Inc.
  8.     ALL RIGHTS RESERVED.
  9.  
  10.     OVERVIEW:
  11.     ---------
  12.     This program demonstrates how to use a mouse with C-scape.
  13.     In particular it shows how to use a mouse along with a 
  14.     framer (pulldown) menu.
  15.  
  16.     The program starts by creating three seds:  a background sed
  17.     that covers the display, the framer menu bar located along the
  18.     top of the display, and a small data entry window.
  19.  
  20.     Press F10 or click the framer menu bar with the
  21.     mouse to use the framer.  You can use the framer menu to select 
  22.     actions to be performed.  For example, you can choose to create 
  23.     a new window or delete an extant one.  Some of the
  24.     menu choices can also be performed by using function keys.
  25.  
  26.     You can move betwwen windows by moving the mouse over the desired 
  27.     window.
  28.  
  29.     When you are finished you can quit by pressing ESC or by 
  30.     selecting the Quit option from the menu.
  31.  
  32.     All the windows have mouse support enabled (via sed_SetBorderFeatures).
  33.     You can move any of the windows by dragging on their borders with 
  34.     the mouse.
  35.  
  36.     A CLOSER LOOK:
  37.     --------------
  38.     This program does the following:
  39.     First, it initializes the display interface and the mouse.
  40.     Then it creates a background sed and the pulldown menu.  A global pointer
  41.     `menubar' points to the pulldown menu.
  42.  
  43.     Next it calls the function main_loop.  In here we create a small data
  44.     entry sed with fun_MakeSed (below).  This routines creates a sed 
  45.     and returns a pointer to it.  A global pointer, `currsed' points to this 
  46.     sed.  `currsed' is used to keep track of the "current sed".
  47.  
  48.     All the seds created with fun_MakeSed are placed into a linked list of
  49.     seds.  The top of this list is pointed to by `headsed' and the links are 
  50.     maintained with the sed generic data pointer; every sed points to 
  51.     the next sed in the list, the last to NULL.
  52.  
  53.     When seds are deleted (with fun_DeleteSed) they are removed from the
  54.     linked list.
  55.  
  56.     The seds created with fun_MakeSed use the special function
  57.     spc_FunCommand (below) to intercept the Function Key commands.
  58.  
  59.     main_loop sits in a loop and calls sed_Go on `currsed'.  sed_Go returns
  60.     a command value (one the FUN_ values defines below).  main_loop
  61.     switches on this command value and performs various operations.
  62.     When the command FUN_QUIT is returned, main_loop exits and the program
  63.     is terminated.
  64.  
  65.     sed_Go returns a command value in one of two ways.  If a function key
  66.     is pressed, the special function, spc_FunCommand, intercepts and returns
  67.     a command code via the sed's baton.  If the user selects the menubar
  68.     with the mouse or presses F10 control is passed (via sed_SetNextWin)
  69.     to the menubar.  After a choice is made, the menubar returns the command
  70.     code (via its baton).  Note that although sed_Go is called on currsed
  71.     you can never tell which sed is actually returning a value through
  72.     because of the nextwin mechanism.
  73.  
  74.     Also, note that frame_Open automatically attaches a mouse handler
  75.     especially intended for the framer.
  76.  
  77.     MISCELLANY:
  78.     -----------
  79.     "A squid eating dough in a polyethylene bag is fast and bulbous! Got me?"
  80.  
  81.         -- Capt. Beefheart
  82.  
  83.     The use of a couple of items in this program are of further note:
  84.     
  85.         +    the sedmou_GreedClick handler on a pop up
  86.  
  87.         +    mouse-sensitive OK and CANCEL fields in a pop up (all fields 
  88.             are now sensitive to the sed's mousecode - see library source)
  89.  
  90.         +    detection of which mouse buttons (1, 2, or 3) are down (see 
  91.             spc_FunCommand, CASE: MOU_CLICK)
  92.  
  93.         +    detection of a double mouse click (see spc_FunCommand, 
  94.             CASE: MOU_CLICK)
  95.  
  96.         +    sed_SetBorderFeature to mouse-sensitize borders
  97.  
  98.         +     window shadows
  99.  
  100.         +    sed_SetNextWin to pass control among windows
  101.  
  102.         +    sed_Alloc as an alternative field variable allocation method
  103.         
  104.         +    Bulbous, also tapered.
  105.     
  106.     Revision History:
  107.     -----------------
  108.      4/01/90 jmd    ansi-fied
  109.      4/08/90 jmd    added FNULLs for PHARLAP, added aux function
  110.      6/06/90 jmd    changed main to return an int
  111.      9/14/90 bkd    changed to use exit(0) instead of return(0).
  112.     10/19/90 pmcm    included ostdlib.h for exit(), added return(1)
  113.      12/7/90 pmcm    fixed positioning so windows don't appear over menu.
  114.      12/7/90 bkd    merged in ted's changes: prototyped main, except if
  115.                      Turbo C++. (12/01/90 ted) and restored "" includes
  116.                     for C-scape headers (not <> includes). (12/04/90 ted)
  117.  
  118. */
  119.  
  120. #include <stdio.h>
  121.  
  122. #include "cscape.h"
  123. #include "ostdlib.h"    /*    for exit() */
  124. #include "framer.h"
  125. #include "scancode.h"
  126.  
  127. /*** Function Prototypes ***/
  128.  
  129. /* Turbo C++ complains if main is prototyped */
  130. #ifndef TCP
  131. int main(void);
  132. #endif
  133.  
  134. sed_type     background(void);
  135. void         main_loop(void);
  136. sed_type     fun_MakeSed(sed_type *headsed, int id);
  137. sed_type     fun_DeleteSed(sed_type *headsed, sed_type sed);
  138.  
  139. boolean     spc_FunCommand(sed_type sed, int scancode);
  140.  
  141. /*** Commands ***/
  142.  
  143. #define FUN_QUIT      1
  144. #define FUN_NEW          2
  145. #define FUN_DELETE      3
  146. #define FUN_RESET      4
  147. #define FUN_NEXTWIN      5
  148. #define FUN_INVERT      6
  149.  
  150. #define MAX_WINS      25        /* limit number of windows */
  151.  
  152.  
  153. /*** menubar definition ***/
  154.  
  155. static struct frame_def menu_bar[] = {   /* note: values must be positive */
  156.  
  157.     { "Window",              FNULL,  0    },
  158.     { "New (F2)",              FNULL,  FUN_NEW    },
  159.     { "Delete (F3)",         FNULL,  FUN_DELETE },
  160.     { "Invert (F6)",         FNULL,  FUN_INVERT },
  161.     { FRAME_END },
  162.     { "Data",                FNULL,  0 },
  163.     { "Reset (F4)",         FNULL,  FUN_RESET },
  164.     { "Next Window (F5)",     FNULL,    FUN_NEXTWIN },
  165.     { FRAME_END },
  166.     { "Quit (Esc)",            FNULL,  FUN_QUIT    },
  167.     { FRAME_END },
  168.     { FRAME_END }
  169. };
  170.  
  171.  
  172. /*** global data ***/
  173. sed_type currsed = NULL;    /* this is the current sed */
  174. sed_type menubar = NULL;    /* the menu bar */
  175.  
  176. int main(void)
  177. {
  178.     sed_type back;
  179.  
  180.     /* Initialize device interface */
  181.     disp_Init(def_ModeText, FNULL);
  182.  
  183.     /* Turn on the mouse */
  184.     hard_InitMouse();
  185.  
  186.     /* Turn on sedwin mouse */
  187.     sedwin_ClassInit();
  188.  
  189.     /* create background window and menu */
  190.     back = background();
  191.  
  192.     /* do everything */
  193.     main_loop();
  194.  
  195.     /* close down the menu and background seds */
  196.     sed_Close(menubar);
  197.     sed_Close(back);
  198.  
  199.     /* close down the display interface */
  200.     disp_Close();
  201.  
  202.     exit(0);
  203.     return(0);
  204. }
  205.  
  206. sed_type background()
  207. /*
  208.     This routine creates the background sed
  209.     and the menu bar.  (the menubar is pointed to by a global variable)
  210. */
  211. {
  212.     register int i;
  213.  
  214.     menu_type menu;
  215.     sed_type sed;
  216.  
  217.     /* create background screen */
  218.     menu = menu_Open();
  219.  
  220.     /* fill up the background screen 
  221.        (with extended ASCII character \260 (alas, octal is most portable))
  222.     */
  223.     for (i = 0; i < disp_GetHeight(); i++) {
  224.         menu_Printf(menu, "@[%d,\260]\n", disp_GetWidth());
  225.     }
  226.  
  227.     menu_Flush(menu);
  228.  
  229.     sed = sed_Open(menu);
  230.     sed_SetShadowAttr(sed, 0x08);
  231.     sed_Repaint(sed);
  232.  
  233.     /*** create menu bar ***/
  234.     menubar = frame_Open(menu_bar, bd_1, 0x07, 0x70, 0x07);
  235.     frame_Repaint(menubar);
  236.  
  237.     return(sed);
  238. }
  239.  
  240. void main_loop()
  241. /*
  242.     This is the central part of the program.
  243.     Here we create a window and sit in a loop processing events
  244.     until we're finished.
  245. */
  246. {
  247.     sed_type headsed = NULL;
  248.     sed_type next;
  249.     int      win_id = 0;
  250.     int      win_count = 1;        /* keep track of how many windows there are */
  251.     int      fldno;
  252.     byte     reg, sel, bck;
  253.  
  254.     /* create the first sed */
  255.     currsed = fun_MakeSed(&headsed, win_id++);
  256.  
  257.     while(currsed != NULL) {
  258.         /* Activate the current sed, see what command it returns */
  259.         /* Note that even though we call sed_Go on currsed, it may actually
  260.              return from another sed, such as the menubar */
  261.         switch(sed_Go(currsed)) {
  262.  
  263.         case FUN_QUIT:
  264.             /* we're done, quit */
  265.             currsed = NULL;
  266.             break;
  267.  
  268.         case FUN_NEW:
  269.             /* create a new window, add it to the list */
  270.             if (win_count < MAX_WINS) {
  271.                 if ((currsed = fun_MakeSed(&headsed, win_id++)) != NULL) {
  272.                     win_count++;
  273.                 }    
  274.             }
  275.             else {
  276.                 tone();
  277.             }
  278.             break;
  279.  
  280.         case FUN_DELETE:
  281.             /* delete the current window */
  282.             if (win_count > 1) {
  283.                 currsed = fun_DeleteSed(&headsed, currsed);
  284.                 win_count--;
  285.             }
  286.             else {
  287.                 tone();
  288.             }
  289.             break;
  290.  
  291.         case FUN_RESET:
  292.             /* reset the window's field contents */
  293.             for (fldno = 0; fldno < sed_GetFieldCount(currsed); fldno++) {
  294.                 sed_SetRecord(currsed, "", fldno);
  295.             }
  296.             sed_UpdateFields(currsed);
  297.             break;
  298.  
  299.         case FUN_NEXTWIN:
  300.             /* pass control to the next window in the list */
  301.             currsed = (sed_type) sed_GetData(currsed);
  302.             if (currsed == NULL) {
  303.                 /* if we're at the end of the list, wrap around */
  304.                 currsed = headsed;
  305.             }
  306.             break;
  307.  
  308.         case FUN_INVERT:
  309.             /* invert the colors of currsed */
  310.             sed_GetColors(currsed, ®, &bck, &sel);
  311.             sed_SetColors(currsed, sel, sel, reg);
  312.             sed_SetBorderColor(currsed, sel);
  313.             sed_Update(currsed);
  314.             break;
  315.         }
  316.     }
  317.  
  318.     /* close all the seds in the list */
  319.     for (next = headsed; next != NULL; next = (sed_type) sed_GetData(next)) {
  320.         sed_Close(next);
  321.     }
  322. }
  323.  
  324. sed_type fun_MakeSed(sed_type *headsed, int id)
  325. /*
  326.     Create a new sed and employ it.
  327.     The new sed is placed at the end of the linked list of seds.
  328.     headsed is a pointer to the first sed in the list,
  329.     the links are maintained via the sed data pointers.
  330.  
  331.     id is number of the window.  
  332.     It is used in the border title (for cosmetic reasons)
  333.  
  334.     The sed created by this routine uses the special function
  335.     spc_FunCommand (below) to intercept the Function Key commands.
  336. */
  337. {
  338.     menu_type menu;
  339.     sed_type  sed, next, last;
  340.     char       title[22];
  341.  
  342.     if ((menu = menu_Open()) == NULL) {
  343.         return(NULL);
  344.     }
  345.  
  346.     /* Note: NULL field vars are OK becuse we're going to use sed_Alloc */
  347.     menu_Printf(menu, " Name: @f[############]\n\n", NULL, &string_funcs);
  348.     menu_Printf(menu, " City: @f[############]\n", NULL, &string_funcs);
  349.  
  350.     if ((sed = sed_Open(menu)) == NULL) {
  351.         menu_Destroy(menu);
  352.         return(NULL);
  353.     }
  354.  
  355.     if (!sed_Alloc(sed)) {
  356.         sed_Close(sed);
  357.         return(NULL);
  358.     }
  359.     
  360.     sed_SetHeight(sed, 4);
  361.     sed_SetWidth(sed, 22);
  362.  
  363.     sed_SetAux(sed, aux_Top);
  364.     sed_SetSpecial(sed, spc_FunCommand);
  365.     sed_SetLabel(sed, id);
  366.  
  367.     if (!sed_SetBorder(sed, bd_box)) {
  368.         sed_Close(sed);
  369.         return(NULL);
  370.     }
  371.     sprintf(title, "Window %d", id);
  372.     sed_SetBorderTitle(sed, title);
  373.     sed_SetBorderFeature(sed, BD_MOVE | BD_RESIZE);
  374.  
  375.     /*    set a random position, within bounds (don't place over top menubar).
  376.         bounds are dependent on display size, window-with-border size, and
  377.         the shadow width.
  378.         bord_GetHeight/Width returns the dimensions of the border, if
  379.         present; of the sed, if not.
  380.      */
  381.     sed_SetPosition(sed, (rand() % (disp_GetHeight() - bord_GetHeight(sed) - 2)) + 1, 
  382.                          (rand() % (disp_GetWidth() - bord_GetWidth(sed) - 2)));
  383.  
  384.     sed_SetShadow(sed, 1);
  385.     sed_SetShadowAttr(sed, 0x08);
  386.  
  387.     sed_SetMouse(sed, sedmou_Track);
  388.  
  389.     /* put the sed in the sedlist */
  390.     if (*headsed == NULL) {
  391.         /* this is the first sed in the list */
  392.         *headsed = sed;
  393.     }
  394.     else {
  395.         /* add to the end of the list */
  396.         for (last = next = *headsed; next != NULL; next = (sed_type) sed_GetData(next)) {
  397.             last = next;
  398.         }
  399.         sed_SetData(last, (VOID *) sed);
  400.     }
  401.  
  402.     sed_Repaint(sed);
  403.  
  404.     return(sed);
  405. }
  406.  
  407. sed_type fun_DeleteSed(sed_type *headsed, sed_type sed)
  408. /*
  409.     Close a sed, remove it from the sed list.
  410.     Returns a new current sed.
  411. */
  412. {
  413.     sed_type curr = NULL;
  414.     sed_type last, next;
  415.  
  416.     /* find sed in the list */
  417.     for (last = next = *headsed; next != NULL; next = (sed_type) sed_GetData(next)) {
  418.         if (sed == next) {
  419.             /* close up the gap in the list */
  420.  
  421.             if (sed == *headsed) {
  422.                 *headsed = (sed_type) sed_GetData(sed);
  423.                 curr = *headsed;
  424.             }
  425.             else {
  426.                 sed_SetData(last, sed_GetData(sed));
  427.                 /* set curr to next window in chain */
  428.                 if ((curr = (sed_type) sed_GetData(sed)) == NULL) {
  429.                     /* we were the last in the list chain, set curr to head */
  430.                     curr = *headsed;
  431.                 }
  432.             }
  433.  
  434.             sed_Close(sed);
  435.             break;
  436.         }
  437.  
  438.         last = next;
  439.     }
  440.  
  441.     return(curr);    
  442. }
  443.  
  444.  
  445. char *rand_string[] = {
  446.     "Wow",
  447.     "Gee",
  448.     "Yikes",
  449.     "Neat",
  450.     "Cool",
  451.     "Nifty",
  452.     "Yow",
  453.     "Zowie",
  454.     "Far Out",
  455.     "Excellent",
  456.     "Rad",
  457.     "Groovy",
  458.     "Holy Smoke",
  459.     "Gadzooks"
  460. };
  461.  
  462. #define RAND_LIST  (sizeof(rand_string) / sizeof(char *))
  463.  
  464. boolean spc_FunCommand(sed_type sed, int scancode)
  465. /*
  466.     Special function for fun seds.
  467.     Traps for command keys or menu.
  468.     When a command key is intercepted, its value is returned via the baton.
  469. */
  470. {
  471.     menu_type menu;
  472.     sed_type popsed;
  473.     int row, col;
  474.     mev_struct mev;            /* a mouse event structure */
  475.     
  476.     boolean    btn1 = FALSE;    /* mouse info */
  477.     boolean    btn2 = FALSE;
  478.     boolean    btn3 = FALSE;
  479.     int     click = GREYPLUS;
  480.  
  481.     /* set current sed to our sed */
  482.     currsed = sed;
  483.  
  484.     switch(scancode) {
  485.     case ESC:
  486.         sed_SetBaton(sed, FUN_QUIT);
  487.         sed_ToggleExit(sed);
  488.         return(TRUE);
  489.  
  490.     case FN2:
  491.         /* create new window command */
  492.         sed_SetBaton(sed, FUN_NEW);
  493.         sed_ToggleExit(sed);
  494.         return(TRUE);
  495.  
  496.     case FN3:
  497.         /* delete window command */
  498.         sed_SetBaton(sed, FUN_DELETE);
  499.         sed_ToggleExit(sed);
  500.         return(TRUE);
  501.  
  502.     case FN4:
  503.         /* reset window command */
  504.         sed_SetBaton(sed, FUN_RESET);
  505.         sed_ToggleExit(sed);
  506.         return(TRUE);
  507.  
  508.     case FN5:
  509.         /* next window command */
  510.         sed_SetBaton(sed, FUN_NEXTWIN);
  511.         sed_ToggleExit(sed);
  512.         return(TRUE);
  513.  
  514.     case FN6:
  515.         /* invert window attributes command */
  516.         sed_SetBaton(sed, FUN_INVERT);
  517.         sed_ToggleExit(sed);
  518.         return(TRUE);
  519.  
  520.     case FN10:
  521.         /* pass control to menu bar */
  522.         sed_SetNextWin(sed, menubar);
  523.         sed_ToggleExit(sed);
  524.         return(TRUE);
  525.  
  526.     case MOU_CLICK:
  527.         /* a mouse click: test for double clicks */
  528.  
  529.         /* Get the current mouse event in a mev_struct */
  530.         win_MouseCurrEvent(&mev);
  531.  
  532.          /* Check which buttons were pressed before Dbl messes with mev */
  533.         btn1 = mev_IsButton1Down(&mev);
  534.         btn2 = mev_IsButton2Down(&mev);
  535.         btn3 = mev_IsButton3Down(&mev);
  536.  
  537.         /* test for double click */
  538.         if (win_MouseDblClick(sed, &mev) == MOU_DCLICK) {
  539.             click = MOU_DCLICK;
  540.         }
  541.         else {
  542.             /* a single click */
  543.             click = MOU_CLICK;
  544.         }
  545.  
  546.         /* fall through to GREYPLUS case: */
  547.  
  548.     case GREYPLUS:
  549.         /* make a popup dialogue window 
  550.             (use data pointer feature of gmenu_funcs) */
  551.         menu = menu_Open();
  552.         menu_Printf(menu, "\n This is a popup window\n");
  553.  
  554.         switch (click) {
  555.         case GREYPLUS:
  556.             menu_Printf(menu, "\n  Keyboard");
  557.             break;
  558.         case MOU_CLICK:
  559.             menu_Printf(menu, "\n  Single Mouse Click");
  560.             break;
  561.         case MOU_DCLICK:
  562.             menu_Printf(menu, "\n  Double Mouse Click");
  563.             break;
  564.         }
  565.  
  566.         menu_Printf(menu, "\n   Mouse Buttons  %s %s %s", 
  567.             (btn1) ? "1" : "", 
  568.             (btn2) ? "2" : "", 
  569.             (btn3) ? "3" : "");
  570.  
  571.         menu_Printf(menu, "\n\n    @fd2[ OK ]  ", NULL, &gmenu_funcs, NULL, "1");
  572.         menu_Printf(menu, "  @fd2[ Cancel ]  ", NULL, &gmenu_funcs, NULL, "0");
  573.  
  574.         popsed = sed_Open(menu);
  575.         sed_SetHeight(popsed, 5);
  576.         sed_SetWidth(popsed, 25);
  577.  
  578.         sed_GetPosition(sed, &row, &col);
  579.         sed_SetPosition(popsed, row + 3, col + 4);
  580.  
  581.         sed_SetBorder(popsed, bd_2);
  582.  
  583.         sed_SetBorderFeature(popsed, BD_MOVE | BD_RESIZE);
  584.  
  585.         sed_SetShadow(popsed, 1);
  586.         sed_SetShadowAttr(popsed, 0x08);
  587.  
  588.         sed_SetMouse(popsed, sedmou_GreedyClick);
  589.         sed_Repaint(popsed);
  590.  
  591.         if (sed_Go(popsed) == 1) {
  592.             /* they chose OK, fill in the current record randomly */
  593.             sed_SetCurrRecord(sed, rand_string[rand() % RAND_LIST]);
  594.             sed_UpdateCurrField(sed);
  595.         }
  596.         else {
  597.             tone();
  598.         }
  599.  
  600.         sed_Close(popsed);
  601.         return(TRUE);
  602.  
  603.     case ENTER:
  604.         return(TRUE);
  605.     }
  606.  
  607.     return(FALSE);
  608. }
  609.