home *** CD-ROM | disk | FTP | other *** search
/ Liren Large Software Subsidy 7 / 07.iso / c / c185 / 1.ddi / EXAMPLE.EXE / CSCAPE / EXAMPLE / DEMOFM.C < prev    next >
Encoding:
C/C++ Source or Header  |  1989-09-12  |  14.2 KB  |  587 lines

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