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