home *** CD-ROM | disk | FTP | other *** search
- /*
- demofm.c
-
- jmd 6/89
-
- C-scape 3.2 Example Program
- Copyright (c) 1989, 1990 by Oakland Group, Inc.
- ALL RIGHTS RESERVED.
-
- OVERVIEW:
- ---------
- This program demonstrates how to use a mouse with C-scape.
- In particular it shows how to use a mouse along with a
- framer (pulldown) menu.
-
- The program starts by creating three seds: a background sed
- that covers the display, the framer menu bar located along the
- top of the display, and a small data entry window.
-
- Press F10 or click the framer menu bar with the
- mouse to use the framer. You can use the framer menu to select
- actions to be performed. For example, you can choose to create
- a new window or delete an extant one. Some of the
- menu choices can also be performed by using function keys.
-
- You can move betwwen windows by moving the mouse over the desired
- window.
-
- When you are finished you can quit by pressing ESC or by
- selecting the Quit option from the menu.
-
- All the windows have mouse support enabled (via sed_SetBorderFeatures).
- You can move any of the windows by dragging on their borders with
- the mouse.
-
- A CLOSER LOOK:
- --------------
- This program does the following:
- First, it initializes the display interface and the mouse.
- Then it creates a background sed and the pulldown menu. A global pointer
- `menubar' points to the pulldown menu.
-
- Next it calls the function main_loop. In here we create a small data
- entry sed with fun_MakeSed (below). This routines creates a sed
- and returns a pointer to it. A global pointer, `currsed' points to this
- sed. `currsed' is used to keep track of the "current sed".
-
- All the seds created with fun_MakeSed are placed into a linked list of
- seds. The top of this list is pointed to by `headsed' and the links are
- maintained with the sed generic data pointer; every sed points to
- the next sed in the list, the last to NULL.
-
- When seds are deleted (with fun_DeleteSed) they are removed from the
- linked list.
-
- The seds created with fun_MakeSed use the special function
- spc_FunCommand (below) to intercept the Function Key commands.
-
- main_loop sits in a loop and calls sed_Go on `currsed'. sed_Go returns
- a command value (one the FUN_ values defines below). main_loop
- switches on this command value and performs various operations.
- When the command FUN_QUIT is returned, main_loop exits and the program
- is terminated.
-
- sed_Go returns a command value in one of two ways. If a function key
- is pressed, the special function, spc_FunCommand, intercepts and returns
- a command code via the sed's baton. If the user selects the menubar
- with the mouse or presses F10 control is passed (via sed_SetNextWin)
- to the menubar. After a choice is made, the menubar returns the command
- code (via its baton). Note that although sed_Go is called on currsed
- you can never tell which sed is actually returning a value through
- because of the nextwin mechanism.
-
- Also, note that frame_Open automatically attaches a mouse handler
- especially intended for the framer.
-
- MISCELLANY:
- -----------
- "A squid eating dough in a polyethylene bag is fast and bulbous! Got me?"
-
- -- Capt. Beefheart
-
- The use of a couple of items in this program are of further note:
-
- + the sedmou_GreedClick handler on a pop up
-
- + mouse-sensitive OK and CANCEL fields in a pop up (all fields
- are now sensitive to the sed's mousecode - see library source)
-
- + detection of which mouse buttons (1, 2, or 3) are down (see
- spc_FunCommand, CASE: MOU_CLICK)
-
- + detection of a double mouse click (see spc_FunCommand,
- CASE: MOU_CLICK)
-
- + sed_SetBorderFeature to mouse-sensitize borders
-
- + window shadows
-
- + sed_SetNextWin to pass control among windows
-
- + sed_Alloc as an alternative field variable allocation method
-
- + Bulbous, also tapered.
-
- Revision History:
- -----------------
- 4/01/90 jmd ansi-fied
- 4/08/90 jmd added FNULLs for PHARLAP, added aux function
- 6/06/90 jmd changed main to return an int
- 9/14/90 bkd changed to use exit(0) instead of return(0).
- 10/19/90 pmcm included ostdlib.h for exit(), added return(1)
- 12/7/90 pmcm fixed positioning so windows don't appear over menu.
- 12/7/90 bkd merged in ted's changes: prototyped main, except if
- Turbo C++. (12/01/90 ted) and restored "" includes
- for C-scape headers (not <> includes). (12/04/90 ted)
-
- */
-
- #include <stdio.h>
-
- #include "cscape.h"
- #include "ostdlib.h" /* for exit() */
- #include "framer.h"
- #include "scancode.h"
-
- /*** Function Prototypes ***/
-
- /* Turbo C++ complains if main is prototyped */
- #ifndef TCP
- int main(void);
- #endif
-
- sed_type background(void);
- void main_loop(void);
- sed_type fun_MakeSed(sed_type *headsed, int id);
- sed_type fun_DeleteSed(sed_type *headsed, sed_type sed);
-
- boolean spc_FunCommand(sed_type sed, int scancode);
-
- /*** Commands ***/
-
- #define FUN_QUIT 1
- #define FUN_NEW 2
- #define FUN_DELETE 3
- #define FUN_RESET 4
- #define FUN_NEXTWIN 5
- #define FUN_INVERT 6
-
- #define MAX_WINS 25 /* limit number of windows */
-
-
- /*** menubar definition ***/
-
- static struct frame_def menu_bar[] = { /* note: values must be positive */
-
- { "Window", FNULL, 0 },
- { "New (F2)", FNULL, FUN_NEW },
- { "Delete (F3)", FNULL, FUN_DELETE },
- { "Invert (F6)", FNULL, FUN_INVERT },
- { FRAME_END },
- { "Data", FNULL, 0 },
- { "Reset (F4)", FNULL, FUN_RESET },
- { "Next Window (F5)", FNULL, FUN_NEXTWIN },
- { FRAME_END },
- { "Quit (Esc)", FNULL, FUN_QUIT },
- { FRAME_END },
- { FRAME_END }
- };
-
-
- /*** global data ***/
- sed_type currsed = NULL; /* this is the current sed */
- sed_type menubar = NULL; /* the menu bar */
-
- int main(void)
- {
- sed_type back;
-
- /* Initialize device interface */
- disp_Init(def_ModeText, FNULL);
-
- /* Turn on the mouse */
- hard_InitMouse();
-
- /* Turn on sedwin mouse */
- sedwin_ClassInit();
-
- /* create background window and menu */
- back = background();
-
- /* do everything */
- main_loop();
-
- /* close down the menu and background seds */
- sed_Close(menubar);
- sed_Close(back);
-
- /* close down the display interface */
- disp_Close();
-
- exit(0);
- return(0);
- }
-
- sed_type background()
- /*
- This routine creates the background sed
- and the menu bar. (the menubar is pointed to by a global variable)
- */
- {
- register int i;
-
- menu_type menu;
- sed_type sed;
-
- /* create background screen */
- menu = menu_Open();
-
- /* fill up the background screen
- (with extended ASCII character \260 (alas, octal is most portable))
- */
- for (i = 0; i < disp_GetHeight(); i++) {
- menu_Printf(menu, "@[%d,\260]\n", disp_GetWidth());
- }
-
- menu_Flush(menu);
-
- sed = sed_Open(menu);
- sed_SetShadowAttr(sed, 0x08);
- sed_Repaint(sed);
-
- /*** create menu bar ***/
- menubar = frame_Open(menu_bar, bd_1, 0x07, 0x70, 0x07);
- frame_Repaint(menubar);
-
- return(sed);
- }
-
- void main_loop()
- /*
- This is the central part of the program.
- Here we create a window and sit in a loop processing events
- until we're finished.
- */
- {
- sed_type headsed = NULL;
- sed_type next;
- int win_id = 0;
- int win_count = 1; /* keep track of how many windows there are */
- int fldno;
- byte reg, sel, bck;
-
- /* create the first sed */
- currsed = fun_MakeSed(&headsed, win_id++);
-
- while(currsed != NULL) {
- /* Activate the current sed, see what command it returns */
- /* Note that even though we call sed_Go on currsed, it may actually
- return from another sed, such as the menubar */
- switch(sed_Go(currsed)) {
-
- case FUN_QUIT:
- /* we're done, quit */
- currsed = NULL;
- break;
-
- case FUN_NEW:
- /* create a new window, add it to the list */
- if (win_count < MAX_WINS) {
- if ((currsed = fun_MakeSed(&headsed, win_id++)) != NULL) {
- win_count++;
- }
- }
- else {
- tone();
- }
- break;
-
- case FUN_DELETE:
- /* delete the current window */
- if (win_count > 1) {
- currsed = fun_DeleteSed(&headsed, currsed);
- win_count--;
- }
- else {
- tone();
- }
- break;
-
- case FUN_RESET:
- /* reset the window's field contents */
- for (fldno = 0; fldno < sed_GetFieldCount(currsed); fldno++) {
- sed_SetRecord(currsed, "", fldno);
- }
- sed_UpdateFields(currsed);
- break;
-
- case FUN_NEXTWIN:
- /* pass control to the next window in the list */
- currsed = (sed_type) sed_GetData(currsed);
- if (currsed == NULL) {
- /* if we're at the end of the list, wrap around */
- currsed = headsed;
- }
- break;
-
- case FUN_INVERT:
- /* invert the colors of currsed */
- sed_GetColors(currsed, ®, &bck, &sel);
- sed_SetColors(currsed, sel, sel, reg);
- sed_SetBorderColor(currsed, sel);
- sed_Update(currsed);
- break;
- }
- }
-
- /* close all the seds in the list */
- for (next = headsed; next != NULL; next = (sed_type) sed_GetData(next)) {
- sed_Close(next);
- }
- }
-
- sed_type fun_MakeSed(sed_type *headsed, int id)
- /*
- Create a new sed and employ it.
- The new sed is placed at the end of the linked list of seds.
- headsed is a pointer to the first sed in the list,
- the links are maintained via the sed data pointers.
-
- id is number of the window.
- It is used in the border title (for cosmetic reasons)
-
- The sed created by this routine uses the special function
- spc_FunCommand (below) to intercept the Function Key commands.
- */
- {
- menu_type menu;
- sed_type sed, next, last;
- char title[22];
-
- if ((menu = menu_Open()) == NULL) {
- return(NULL);
- }
-
- /* Note: NULL field vars are OK becuse we're going to use sed_Alloc */
- menu_Printf(menu, " Name: @f[############]\n\n", NULL, &string_funcs);
- menu_Printf(menu, " City: @f[############]\n", NULL, &string_funcs);
-
- if ((sed = sed_Open(menu)) == NULL) {
- menu_Destroy(menu);
- return(NULL);
- }
-
- if (!sed_Alloc(sed)) {
- sed_Close(sed);
- return(NULL);
- }
-
- sed_SetHeight(sed, 4);
- sed_SetWidth(sed, 22);
-
- sed_SetAux(sed, aux_Top);
- sed_SetSpecial(sed, spc_FunCommand);
- sed_SetLabel(sed, id);
-
- if (!sed_SetBorder(sed, bd_box)) {
- sed_Close(sed);
- return(NULL);
- }
- sprintf(title, "Window %d", id);
- sed_SetBorderTitle(sed, title);
- sed_SetBorderFeature(sed, BD_MOVE | BD_RESIZE);
-
- /* set a random position, within bounds (don't place over top menubar).
- bounds are dependent on display size, window-with-border size, and
- the shadow width.
- bord_GetHeight/Width returns the dimensions of the border, if
- present; of the sed, if not.
- */
- sed_SetPosition(sed, (rand() % (disp_GetHeight() - bord_GetHeight(sed) - 2)) + 1,
- (rand() % (disp_GetWidth() - bord_GetWidth(sed) - 2)));
-
- sed_SetShadow(sed, 1);
- sed_SetShadowAttr(sed, 0x08);
-
- sed_SetMouse(sed, sedmou_Track);
-
- /* put the sed in the sedlist */
- if (*headsed == NULL) {
- /* this is the first sed in the list */
- *headsed = sed;
- }
- else {
- /* add to the end of the list */
- for (last = next = *headsed; next != NULL; next = (sed_type) sed_GetData(next)) {
- last = next;
- }
- sed_SetData(last, (VOID *) sed);
- }
-
- sed_Repaint(sed);
-
- return(sed);
- }
-
- sed_type fun_DeleteSed(sed_type *headsed, sed_type sed)
- /*
- Close a sed, remove it from the sed list.
- Returns a new current sed.
- */
- {
- sed_type curr = NULL;
- sed_type last, next;
-
- /* find sed in the list */
- for (last = next = *headsed; next != NULL; next = (sed_type) sed_GetData(next)) {
- if (sed == next) {
- /* close up the gap in the list */
-
- if (sed == *headsed) {
- *headsed = (sed_type) sed_GetData(sed);
- curr = *headsed;
- }
- else {
- sed_SetData(last, sed_GetData(sed));
- /* set curr to next window in chain */
- if ((curr = (sed_type) sed_GetData(sed)) == NULL) {
- /* we were the last in the list chain, set curr to head */
- curr = *headsed;
- }
- }
-
- sed_Close(sed);
- break;
- }
-
- last = next;
- }
-
- return(curr);
- }
-
-
- char *rand_string[] = {
- "Wow",
- "Gee",
- "Yikes",
- "Neat",
- "Cool",
- "Nifty",
- "Yow",
- "Zowie",
- "Far Out",
- "Excellent",
- "Rad",
- "Groovy",
- "Holy Smoke",
- "Gadzooks"
- };
-
- #define RAND_LIST (sizeof(rand_string) / sizeof(char *))
-
- boolean spc_FunCommand(sed_type sed, int scancode)
- /*
- Special function for fun seds.
- Traps for command keys or menu.
- When a command key is intercepted, its value is returned via the baton.
- */
- {
- menu_type menu;
- sed_type popsed;
- int row, col;
- mev_struct mev; /* a mouse event structure */
-
- boolean btn1 = FALSE; /* mouse info */
- boolean btn2 = FALSE;
- boolean btn3 = FALSE;
- int click = GREYPLUS;
-
- /* set current sed to our sed */
- currsed = sed;
-
- switch(scancode) {
- case ESC:
- sed_SetBaton(sed, FUN_QUIT);
- sed_ToggleExit(sed);
- return(TRUE);
-
- case FN2:
- /* create new window command */
- sed_SetBaton(sed, FUN_NEW);
- sed_ToggleExit(sed);
- return(TRUE);
-
- case FN3:
- /* delete window command */
- sed_SetBaton(sed, FUN_DELETE);
- sed_ToggleExit(sed);
- return(TRUE);
-
- case FN4:
- /* reset window command */
- sed_SetBaton(sed, FUN_RESET);
- sed_ToggleExit(sed);
- return(TRUE);
-
- case FN5:
- /* next window command */
- sed_SetBaton(sed, FUN_NEXTWIN);
- sed_ToggleExit(sed);
- return(TRUE);
-
- case FN6:
- /* invert window attributes command */
- sed_SetBaton(sed, FUN_INVERT);
- sed_ToggleExit(sed);
- return(TRUE);
-
- case FN10:
- /* pass control to menu bar */
- sed_SetNextWin(sed, menubar);
- sed_ToggleExit(sed);
- return(TRUE);
-
- case MOU_CLICK:
- /* a mouse click: test for double clicks */
-
- /* Get the current mouse event in a mev_struct */
- win_MouseCurrEvent(&mev);
-
- /* Check which buttons were pressed before Dbl messes with mev */
- btn1 = mev_IsButton1Down(&mev);
- btn2 = mev_IsButton2Down(&mev);
- btn3 = mev_IsButton3Down(&mev);
-
- /* test for double click */
- if (win_MouseDblClick(sed, &mev) == MOU_DCLICK) {
- click = MOU_DCLICK;
- }
- else {
- /* a single click */
- click = MOU_CLICK;
- }
-
- /* fall through to GREYPLUS case: */
-
- case GREYPLUS:
- /* make a popup dialogue window
- (use data pointer feature of gmenu_funcs) */
- menu = menu_Open();
- menu_Printf(menu, "\n This is a popup window\n");
-
- switch (click) {
- case GREYPLUS:
- menu_Printf(menu, "\n Keyboard");
- break;
- case MOU_CLICK:
- menu_Printf(menu, "\n Single Mouse Click");
- break;
- case MOU_DCLICK:
- menu_Printf(menu, "\n Double Mouse Click");
- break;
- }
-
- menu_Printf(menu, "\n Mouse Buttons %s %s %s",
- (btn1) ? "1" : "",
- (btn2) ? "2" : "",
- (btn3) ? "3" : "");
-
- menu_Printf(menu, "\n\n @fd2[ OK ] ", NULL, &gmenu_funcs, NULL, "1");
- menu_Printf(menu, " @fd2[ Cancel ] ", NULL, &gmenu_funcs, NULL, "0");
-
- popsed = sed_Open(menu);
- sed_SetHeight(popsed, 5);
- sed_SetWidth(popsed, 25);
-
- sed_GetPosition(sed, &row, &col);
- sed_SetPosition(popsed, row + 3, col + 4);
-
- sed_SetBorder(popsed, bd_2);
-
- sed_SetBorderFeature(popsed, BD_MOVE | BD_RESIZE);
-
- sed_SetShadow(popsed, 1);
- sed_SetShadowAttr(popsed, 0x08);
-
- sed_SetMouse(popsed, sedmou_GreedyClick);
- sed_Repaint(popsed);
-
- if (sed_Go(popsed) == 1) {
- /* they chose OK, fill in the current record randomly */
- sed_SetCurrRecord(sed, rand_string[rand() % RAND_LIST]);
- sed_UpdateCurrField(sed);
- }
- else {
- tone();
- }
-
- sed_Close(popsed);
- return(TRUE);
-
- case ENTER:
- return(TRUE);
- }
-
- return(FALSE);
- }
-