|
/*ScianEvents.c
Eric Pepke
March 8, 1990
Event stuff for scian
*/
#include "Scian.h"
#include "ScianTypes.h"
#include "ScianWindows.h"
#include "ScianEvents.h"
#include "ScianGarbageMan.h"
#include "ScianSockets.h"
#include "ScianScripts.h"
#include "ScianColors.h"
#include "ScianIDs.h"
#include "ScianTimers.h"
#include "ScianMainWindow.h"
#include "ScianObjWindows.h"
#include "ScianVisWindows.h"
#include "ScianPreferences.h"
#include "ScianObjFunctions.h"
#include "ScianDialogs.h"
#include "ScianDraw.h"
#include "ScianStyle.h"
#include "ScianLists.h"
#include "ScianObjWindows.h"
#include "ScianFontMappings.h"
int settleEvents = 0; /*Events to settle*/
ObjPtr dropObject = NULLOBJ; /*Object to drop in window*/
int dropX, dropY; /*Global coordinates of place to drop*/
#ifdef INTERACTIVE
int curMouse = LEFTMOUSE; /*Current mouse button down*/
Bool interactiveMoving = false; /*True iff moving interactively*/
Bool contextHelp = false; /*Context sensitive help*/
#endif
#ifdef IRISNTSC
Bool NTSCOn = 0; /*True iff NTSC is on*/
#endif
Bool stereoOn = 0;
long lastGC = 0; /*Time of last garbage collection*/
#define GCEVERY ((HEARTBEAT) * 10) /*One garbage collection per ten seconds*/
long defaultMonitor; /*Default monitor*/
Event events[MAXNEVENTS];
int curEvent = 0; /*Current and last events for queue*/
int lastEvent = 0; /*Queue empty when they're the same*/
Bool knownUserEvent; /*There is a user event known*/
#define MAXNTASKS 100 /*Maximum # of tasks*/
TaskType doTasks[MAXNTASKS]; /*Tasks to do*/
int tasksLeft = 0; /*Number of tasks left*/
#define MAXNDEFMES 100 /*Maximum # of deferred messages*/
int curDef = 0; /*Current deferred message set*/
WinInfoPtr lastCursorWindow = 0; /*Last cursor window*/
struct
{
ObjPtr object; /*The object to send the message*/
int message; /*The message to send*/
} defMessages[2][MAXNDEFMES];
int defMesLeft = 0;
#ifdef INTERACTIVE
long lastClickTime = 0; /*The time the last click was done*/
long lastKeyTime = 0; /*The last time of a keypress*/
int lastClickX, lastClickY; /*The last click X and Y*/
int sentKey = 0; /*Last key that has been sent*/
WinInfoPtr keyWindow = 0; /*Window the last key was sent to*/
#endif
int running = 1; /*True iff running*/
#ifdef INTERACTIVE
/*Values for mouse switchboard*/
#define MOUSEPRESS 1 /*Select, drag, etc. with mouse*/
#define MOUSEMENU 2 /*Bring up mouse menu*/
#define MOUSEROTATE 3 /*Rotate with the mouse*/
/*Mouse switchboard*/
int mouseSwitchboard[3] =
{
MOUSEMENU,
MOUSEROTATE,
MOUSEPRESS
};
#endif
void DoTask(task)
TaskType task;
/*Asks the system to do task at its earliest possible convenience*/
{
doTasks[tasksLeft++] = task;
}
void DeferMessage(object, message)
ObjPtr object;
int message;
/*Asks the system to do task at its earliest possible convenience*/
{
defMessages[curDef][defMesLeft] . object = object;
defMessages[curDef][defMesLeft] . message = message;
++defMesLeft;
}
void DeferUniqueMessage(object, message)
ObjPtr object;
int message;
/*Asks the system to do task at its earliest possible convenience*/
{
int k;
for (k = 0; k < defMesLeft; ++k)
{
if ((defMessages[curDef][k] . object == object) &&
(defMessages[curDef][k] . message == message))
{
return;
}
}
defMessages[curDef][defMesLeft] . object = object;
defMessages[curDef][defMesLeft] . message = message;
++defMesLeft;
}
void DoUniqueTask(task)
TaskType task;
/*Asks the system to do task at its earliest possible convenience,
but only if it hasn't already been requested*/
{
int k;
for (k = 0; k < tasksLeft; ++k)
{
if (doTasks[k] == task)
{
return;
}
}
doTasks[tasksLeft++] = task;
}
void DoQuit()
/*Asks to quit on the next loop*/
{
running = 0;
}
ObjPtr QuitReply(window, button)
WinInfoPtr window;
int button;
{
if (button == 0)
{
DoQuit();
}
}
void MaybeQuit()
/*Maybe quits on the next loop*/
{
if (OptionDown())
{
DoQuit();
}
else
{
WinInfoPtr alertWindow;
alertWindow = AlertUser(UIERRORALERT, (WinInfoPtr) 0, "Do you really want to quit SciAn?",
QuitReply, 2, "Quit", "Cancel");
SetVar((ObjPtr) alertWindow, INHIBITLOGGING, ObjTrue);
}
}
#ifdef INTERACTIVE
void QueueDevices()
/*Queues up all the devices that will be used by Scian*/
{
qdevice(KEYBD);
qdevice(PADPF1);
qdevice(F1KEY);
qdevice(PADPF2);
qdevice(F2KEY);
qdevice(PADPF3);
qdevice(F3KEY);
qdevice(PADPF4);
qdevice(F4KEY);
qdevice(F5KEY);
qdevice(F6KEY);
qdevice(F7KEY);
qdevice(F8KEY);
qdevice(F9KEY);
qdevice(F10KEY);
qdevice(F11KEY);
qdevice(F12KEY);
qdevice(MOUSE1);
qdevice(MOUSE2);
qdevice(MOUSE3);
qdevice(UPARROWKEY);
qdevice(DOWNARROWKEY);
qdevice(LEFTARROWKEY);
qdevice(RIGHTARROWKEY);
qdevice(WINFREEZE);
qdevice(WINTHAW);
#ifdef DEPTHCHANGE
qdevice(DEPTHCHANGE);
#endif
#ifdef IRIS
#ifdef WINQUIT
qdevice(WINQUIT);
#endif
qdevice(WINSHUT);
qdevice(BUT157);
#endif
}
void UnqueueDevices()
/*Unqueues all the devices*/
{
#ifdef DEPTHCHANGE
unqdevice(DEPTHCHANGE);
#endif
unqdevice(WINFREEZE);
unqdevice(WINTHAW);
unqdevice(KEYBD);
unqdevice(PADPF1);
unqdevice(F1KEY);
unqdevice(PADPF2);
unqdevice(F2KEY);
unqdevice(PADPF3);
unqdevice(F3KEY);
unqdevice(PADPF4);
unqdevice(F4KEY);
unqdevice(F5KEY);
unqdevice(F6KEY);
unqdevice(F7KEY);
unqdevice(F8KEY);
unqdevice(F9KEY);
unqdevice(F10KEY);
unqdevice(F11KEY);
unqdevice(F12KEY);
unqdevice(MOUSE1);
unqdevice(MOUSE2);
unqdevice(MOUSE3);
unqdevice(UPARROWKEY);
unqdevice(DOWNARROWKEY);
unqdevice(LEFTARROWKEY);
unqdevice(RIGHTARROWKEY);
#ifdef IRIS
#ifdef WINQUIT
qdevice(WINQUIT);
#endif
unqdevice(WINSHUT);
unqdevice(BUT157);
#endif
}
#endif
void LongOperation()
/*Signals the user that a long operation is about to occur
This version sets to the watchcursor*/
{
MySetCursor(WATCHCURSOR);
}
void EndLongOperation()
/*Ends a long operation*/
{
if (curCursor == WATCHCURSOR)
{
MySetCursor(0);
}
}
#ifdef INTERACTIVE
void SetContextSensitiveHelp()
/*Sets up the system so that the next press click is a help*/
{
MySetCursor(QUESTIONCURSOR);
contextHelp = true;
}
#endif
#ifdef INTERACTIVE
#ifdef PROTO
void KeyDown(int theKey, long flags)
#else
void KeyDown(theKey, flags)
int theKey;
long flags;
#endif
/*Does a keyDown for theKey with flags.*/
{
WinInfoPtr window;
window = inputWindow;
if (!inputWindow)
{
/*No focus; return*/
return;
}
SelWindow(inputWindow);
if (!selWinInfo)
{
/*Pathological case. Return.*/
return;
}
/*See if it's one of the funny characters*/
switch (theKey)
{
case CONTROL('C'):
#ifdef CH_COPYRIGHT
theKey = CH_COPYRIGHT;
#endif
break;
case CONTROL('X'):
#ifdef CH_CROSS
theKey = CH_CROSS;
#endif
break;
case CONTROL('D'):
#ifdef CH_DOT
theKey = CH_DOT;
#endif
break;
case CONTROL('R'):
#ifdef CH_REGISTERED
theKey = CH_REGISTERED;
#endif
break;
}
{
FuncTyp actionMethod; /*The method to call for the action*/
actionMethod = GetMethod((ObjPtr) selWinInfo, KEYDOWN);
if (actionMethod)
{
/*There's a key down routine. Call it.*/
if (theKey == '\r')
{
/*Kludge to get it to flush stuff before enter key*/
FlushKeystrokes();
}
(*actionMethod)(selWinInfo, theKey, flags);
}
}
}
#endif
void FlushKeystrokes()
/*Flushes the keystrokes to an object that takes keystrokes*/
{
#ifdef INTERACTIVE
if (sentKey && IsValidWindow(keyWindow))
{
WinInfoPtr tempInput;
Screencoord l, r, b, t;
WinInfoPtr oldWindow;
oldWindow = selWinInfo;
tempInput = inputWindow;
inputWindow = keyWindow;
sentKey = 0;
KeyDown(0, 0);
inputWindow = tempInput;
if (oldWindow)
{
SelWindow(oldWindow);
}
}
#endif
}
Bool Mouse(x, y)
int *x, *y;
/*Returns in x and y the current mouse position in local coordinates*/
{
#ifdef INTERACTIVE
int ox, oy;
UD();
CurOffset(&ox, &oy);
*x = getvaluator(MOUSEX) - ox;
*y = getvaluator(MOUSEY) - oy;
switch (curMouse)
{
case MB_LEFT:
return getbutton(MOUSE1);
case MB_MIDDLE:
return getbutton(MOUSE2);
case MB_RIGHT:
return getbutton(MOUSE3);
}
#else
return false;
#endif
}
#ifdef INTERACTIVE
static ObjPtr AbortScript(owner, button)
ObjPtr owner;
int button;
/*Callback routine to abort a script*/
{
if (button)
{
/*Continue*/
runningScript = true;
}
else
{
/*Real abort*/
EndScript();
}
}
void AbortScriptAlert()
/*Puts up an alert to abort the script*/
{
WinInfoPtr errWindow;
MySetCursor(0);
runningScript = false;
errWindow = AlertUser(UICAUTIONALERT, (WinInfoPtr) 0,
"SciAn is currently running a script. Would you like to abort the \
script or continue running it?",
AbortScript, 2, "Abort", "Continue");
SetVar((ObjPtr) errWindow, HELPSTRING,
NewString("SciAn expects no user interaction while running a script. \
This is because changing the state of the windows of SciAn while running a \
script can cause the script to generate an error. It is best either to \
abort the script or continue and not interfere with it. However, if you are really \
sure you know what you are doing, you can interact with SciAn now and press the \
Continue button later. This is not recommended for the inexperienced."));
SetVar((ObjPtr) errWindow, INHIBITLOGGING, ObjTrue);
}
#ifdef PROTO
void MouseDown(int whichButton, int x, int y, long flags)
#else
void MouseDown(whichButton, x, y, flags)
int whichButton;
int x, y;
long flags;
#endif
/*Does a mouseDown.
whichButton should be MB_LEFT, MB_MIDDLE, or MB_RIGHT.
x and y are in global coordinates.*/
{
int action; /*The action to do*/
FuncTyp actionMethod; /*The method to call for the action*/
long ox, oy;
WinInfoPtr mouseWindow;
curMouse = whichButton;
mouseWindow = WhichWindow(x, y);
if (!mouseWindow && !(IsValidWindow(mouseWindow)))
{
/*No focus; return*/
return;
}
SelWindow(mouseWindow);
if (!selWinInfo)
{
/*Pathological case. Return.*/
return;
}
getorigin(&ox, &oy);
x = x - ox;
y = y - oy;
interactiveMoving = true;
/*Determine the action based on the mouse switchboard*/
switch(whichButton)
{
case MB_LEFT:
action = mouseSwitchboard[0];
break;
case MB_MIDDLE:
action = mouseSwitchboard[1];
break;
case MB_RIGHT:
action = mouseSwitchboard[2];
break;
}
/*Do the action*/
switch(action)
{
case MOUSEROTATE:
actionMethod = GetMethod((ObjPtr) selWinInfo, PRESS);
if (actionMethod)
{
/*There's a press routine. Call it.*/
if (contextHelp)
{
(*actionMethod)(selWinInfo, x, y, T_HELP | flags);
contextHelp = false;
MySetCursor(0);
}
else
{
(*actionMethod)(selWinInfo, x, y, T_ROTATE | flags);
}
}
break;
case MOUSEPRESS:
if (dragBuffer)
{
dropX = getvaluator(MOUSEX);
dropY = getvaluator(MOUSEY);
MySetCursor(0);
}
actionMethod = GetMethod((ObjPtr) selWinInfo, PRESS);
if (actionMethod)
{
/*There's a press routine. Call it.*/
if (contextHelp)
{
(*actionMethod)(selWinInfo, x, y, T_HELP | flags);
contextHelp = false;
MySetCursor(0);
}
else
{
(*actionMethod)(selWinInfo, x, y, T_PRESS | flags);
}
}
if (dragBuffer)
{
DeleteThing(dragBuffer);
dragBuffer = 0;
}
break;
case MOUSEMENU:
/*See if there are super menus*/
while (mouseWindow = (WinInfoPtr) GetVar((ObjPtr) mouseWindow, SUPERWINDOW))
{
SelWindow(mouseWindow);
}
if (0 || !selWinInfo -> mainMenu)
{
/*There's no menu. Try to build one.*/
BuildMenu(selWinInfo);
}
if (contextHelp)
{
EnableFunctionMenus(selWinInfo);
}
else
{
AdjustFunctionMenus(selWinInfo);
}
if (selWinInfo -> mainMenu)
{
/*There's a menu. Do it.*/
dopup(selWinInfo -> mainMenu);
}
break;
}
interactiveMoving = false;
}
#endif
#ifdef IRISNTSC
void SetNTSC()
/*Sets to NTSC mode*/
{
NTSCOn = true;
#ifdef GRAPHICS
setmonitor(NTSC);
#ifdef GL4D
setvideo(CG_MODE, CG2_M_MODE2);
setvideo(DE_R1, DER1_G_170);
#endif
#endif
}
void SetStereo()
/*Sets to stereo*/
{
stereoOn = true;
#ifdef STR_RECT
setmonitor(STR_RECT);
#endif
}
void Set60()
/*Sets to 60 Hz mode*/
{
NTSCOn = false;
stereoOn = false;
#ifdef GRAPHICS
setmonitor(defaultMonitor);
#endif
}
void ToggleNTSC()
/*Toggles in and out of NTSC mode*/
{
NTSCOn = NTSCOn ? false : true;
#ifdef GRAPHICS
setmonitor(NTSCOn ? NTSC : defaultMonitor);
#ifdef GL4D
if (NTSCOn)
{
setvideo(CG_MODE, CG2_M_MODE2);
setvideo(DE_R1, DER1_G_170);
}
#endif
#endif
}
void ToggleStereo()
/*Toggles in and out of stereo mode*/
{
stereoOn = stereoOn ? false : true;
#ifdef GRAPHICS
#ifdef STR_RECT
setmonitor(stereoOn ? STR_RECT : defaultMonitor);
#endif
#endif
}
#endif
Bool AltDown()
/*Returns true iff the alt key is down*/
{
#ifdef INTERACTIVE
return (getbutton(LEFTALTKEY) || getbutton(RIGHTALTKEY)) ? true : false;
#else
return false;
#endif
}
Bool ShiftDown()
/*Returns true iff the shift key is down*/
{
#ifdef INTERACTIVE
return (getbutton(LEFTSHIFTKEY) || getbutton(RIGHTSHIFTKEY)) ? true : false;
#else
return false;
#endif
}
Bool OptionDown()
/*Returns true iff the option key is down*/
{
#ifdef INTERACTIVE
return (getbutton(LEFTCTRLKEY) || getbutton(RIGHTCTRLKEY) ||
getbutton(CAPSLOCKKEY)) ? true : false;
#else
return false;
#endif
}
Bool UserEvent()
/*Determine if there is a user event (mouse down or key down or close
window) in the queue*/
{
int k;
if (knownUserEvent)
{
return true;
}
#ifndef SIGNALS
NewEvents();
#endif
k = curEvent;
while (k != lastEvent)
{
k = (k + 1) % MAXNEVENTS;
if (ISUSEREVENT(events[k] . type))
{
knownUserEvent = true;
return true;
}
}
return false;
}
#ifdef PROTO
void PostEvent(Event *event)
#else
void PostEvent(event)
Event *event;
#endif
/*Posts an event just like event, except for time*/
{
int k;
char *a, *b;
struct tms buffer;
lastEvent = (lastEvent + 1) % MAXNEVENTS;
a = (char *) event;
b = (char *) &(events[lastEvent]);
for (k = 0; k < sizeof(Event); ++k)
{
b[k] = a[k];
}
events[lastEvent] . time = times(&buffer);
if (ISUSEREVENT(event -> type))
{
knownUserEvent = true;
}
}
void NewEvents()
/*Get all new events and deposit them in the event queue. Do this every once
in a while.*/
{
#ifdef INTERACTIVE
/*Look for an event*/
while (qtest())
{
long whichDevice;
short theData;
WinInfoPtr window;
struct tms buffer;
whichDevice = qread(&theData);
lastEvent = (lastEvent + 1) % MAXNEVENTS;
events[lastEvent] . type = ET_UNKNOWN;
events[lastEvent] . time = times(&buffer);
events[lastEvent] . flags = 0;
/*Determine if the modifier keys are held down*/
if (getbutton(LEFTSHIFTKEY) || getbutton(RIGHTSHIFTKEY))
{
events[lastEvent] . flags |= F_SHIFTDOWN;
}
if (getbutton(LEFTCTRLKEY) || getbutton(RIGHTCTRLKEY) || getbutton(CAPSLOCKKEY))
{
events[lastEvent] . flags |= F_OPTIONDOWN;
}
if (getbutton(LEFTALTKEY) || getbutton(RIGHTALTKEY))
{
events[lastEvent] . flags |= F_OPTIONDOWN;
}
switch (whichDevice)
{
case INPUTCHANGE:
if (theData && (window = GetWinInfo(theData)))
{
events[lastEvent] . type = ET_SET_WINDOW;
events[lastEvent] . data . window = window;
}
break;
#ifdef DEPTHCHANGE
case DEPTHCHANGE:
if (theData && (window = GetWinInfo(theData)))
{
events[lastEvent] . type = ET_DEPTHCHANGE_WINDOW;
events[lastEvent] . data . window = window;
}
break;
#endif
case WINFREEZE:
if (theData && (window = GetWinInfo(theData)))
{
events[lastEvent] . type = ET_ICONIFY_WINDOW;
events[lastEvent] . data . window = window;
}
break;
case WINTHAW:
if (theData && (window = GetWinInfo(theData)))
{
events[lastEvent] . type = ET_DEICONIFY_WINDOW;
events[lastEvent] . data . window = window;
}
break;
case KEYBD:
if (events[lastEvent] . time - lastKeyTime < CLICK2TIME)
{
events[lastEvent] . flags |= F_DOUBLECLICK;
lastKeyTime = events[lastEvent] . time;
}
events[lastEvent] . type = ET_KEY_DOWN;
events[lastEvent] . data . key = theData;
break;
case MOUSE1:
if (theData)
{
int newX, newY;
/*Determine if this is potentially a double click*/
newX = getvaluator(MOUSEX);
newY = getvaluator(MOUSEY);
if (events[lastEvent] . time - lastClickTime < CLICK2TIME &&
ABS(newX - lastClickX) < CLICK2DIST &&
ABS(newY - lastClickY) < CLICK2DIST)
{
events[lastEvent] . flags |= F_DOUBLECLICK;
}
lastClickX = newX;
lastClickY = newY;
events[lastEvent] . type = ET_MOUSE_DOWN;
}
else
{
events[lastEvent] . type = ET_MOUSE_UP;
lastClickTime = events[lastEvent] . time;
}
events[lastEvent] . data . mouse . x = getvaluator(MOUSEX);
events[lastEvent] . data . mouse . y = getvaluator(MOUSEY);
events[lastEvent] . data . mouse . mouseButton = MB_LEFT;
break;
case MOUSE2:
if (theData)
{
int newX, newY;
/*Determine if this is potentially a double click*/
newX = getvaluator(MOUSEX);
newY = getvaluator(MOUSEY);
if (events[lastEvent] . time - lastClickTime < CLICK2TIME &&
ABS(newX - lastClickX) < CLICK2DIST &&
ABS(newY - lastClickY) < CLICK2DIST)
{
events[lastEvent] . flags |= F_DOUBLECLICK;
}
lastClickX = newX;
lastClickY = newY;
events[lastEvent] . type = ET_MOUSE_DOWN;
}
else
{
events[lastEvent] . type = ET_MOUSE_UP;
lastClickTime = events[lastEvent] . time;
}
events[lastEvent] . data . mouse . x = getvaluator(MOUSEX);
events[lastEvent] . data . mouse . y = getvaluator(MOUSEY);
events[lastEvent] . data . mouse . mouseButton = MB_MIDDLE;
break;
case MOUSE3:
if (theData)
{
int newX, newY;
/*Determine if this is potentially a double click*/
newX = getvaluator(MOUSEX);
newY = getvaluator(MOUSEY);
if (events[lastEvent] . time - lastClickTime < CLICK2TIME &&
ABS(newX - lastClickX) < CLICK2DIST &&
ABS(newY - lastClickY) < CLICK2DIST)
{
events[lastEvent] . flags |= F_DOUBLECLICK;
}
lastClickX = newX;
lastClickY = newY;
events[lastEvent] . type = ET_MOUSE_DOWN;
}
else
{
events[lastEvent] . type = ET_MOUSE_UP;
lastClickTime = events[lastEvent] . time;
}
events[lastEvent] . data . mouse . x = getvaluator(MOUSEX);
events[lastEvent] . data . mouse . y = getvaluator(MOUSEY);
events[lastEvent] . data . mouse . mouseButton = MB_RIGHT;
break;
case REDRAW:
if (theData && (window = GetWinInfo(theData)))
{
events[lastEvent] . type = ET_RESHAPE_WINDOW;
events[lastEvent] . data . window = window;
}
break;
case PIECECHANGE:
if (theData && (window = GetWinInfo(theData)))
{
events[lastEvent] . type = ET_RESHAPE_WINDOW;
events[lastEvent] . data . window = window;
}
break;
case UPARROWKEY:
if (theData)
{
events[lastEvent] . type = ET_KEY_DOWN;
events[lastEvent] . data . key = FK_UP_ARROW;
}
break;
case DOWNARROWKEY:
if (theData)
{
events[lastEvent] . type = ET_KEY_DOWN;
events[lastEvent] . data . key = FK_DOWN_ARROW;
}
break;
case LEFTARROWKEY:
if (theData)
{
events[lastEvent] . type = ET_KEY_DOWN;
events[lastEvent] . data . key = FK_LEFT_ARROW;
}
break;
case RIGHTARROWKEY:
if (theData)
{
events[lastEvent] . type = ET_KEY_DOWN;
events[lastEvent] . data . key = FK_RIGHT_ARROW;
}
break;
#ifdef GL4D
case BUT157:
if (theData)
{
events[lastEvent] . type = ET_KEY_DOWN;
events[lastEvent] . data . key = FK_PRINT_SCREEN;
}
break;
#endif
case PADPF1:
case F1KEY:
if (theData)
{
events[lastEvent] . type = ET_KEY_DOWN;
events[lastEvent] . data . key = FK_1;
}
break;
case PADPF2:
case F2KEY:
if (theData)
{
events[lastEvent] . type = ET_KEY_DOWN;
events[lastEvent] . data . key = FK_2;
}
break;
case PADPF3:
case F3KEY:
if (theData)
{
events[lastEvent] . type = ET_KEY_DOWN;
events[lastEvent] . data . key = FK_3;
}
break;
case PADPF4:
case F4KEY:
if (theData)
{
events[lastEvent] . type = ET_KEY_DOWN;
events[lastEvent] . data . key = FK_4;
}
break;
case F5KEY:
if (theData)
{
events[lastEvent] . type = ET_KEY_DOWN;
events[lastEvent] . data . key = FK_5;
}
break;
case F6KEY:
if (theData)
{
events[lastEvent] . type = ET_KEY_DOWN;
events[lastEvent] . data . key = FK_6;
}
break;
case F7KEY:
if (theData)
{
events[lastEvent] . type = ET_KEY_DOWN;
events[lastEvent] . data . key = FK_7;
}
break;
case F8KEY:
if (theData)
{
events[lastEvent] . type = ET_KEY_DOWN;
events[lastEvent] . data . key = FK_8;
}
break;
case F9KEY:
if (theData)
{
events[lastEvent] . type = ET_KEY_DOWN;
events[lastEvent] . data . key = FK_9;
}
break;
case F10KEY:
if (theData)
{
events[lastEvent] . type = ET_KEY_DOWN;
events[lastEvent] . data . key = FK_10;
}
break;
case F11KEY:
if (theData)
{
events[lastEvent] . type = ET_KEY_DOWN;
events[lastEvent] . data . key = FK_11;
}
break;
case F12KEY:
if (theData)
{
events[lastEvent] . type = ET_KEY_DOWN;
events[lastEvent] . data . key = FK_12;
}
break;
#ifdef IRIS
case WINSHUT:
if (theData && (window = GetWinInfo(theData)))
{
events[lastEvent] . type = ET_CLOSE_WINDOW;
events[lastEvent] . data . window = window;
}
break;
#ifdef WINQUIT
case WINQUIT:
if (theData)
{
events[lastEvent] . type = ET_QUIT;
events[lastEvent] . data . window = 0;
}
break;
#endif
#endif
}
}
#endif
}
#ifdef PROTO
Bool OneEvent(Bool processInput)
#else
Bool OneEvent(processInput)
Bool processInput;
#endif
/*Gets and processes one event. if processInput is true, process input*/
{
Bool readFromScript = true;
int k;
if (logging)
{
InhibitLogging(true);
}
/*Do the messages remaining*/
if (defMesLeft)
{
int which, defLeft;
defLeft = defMesLeft;
which = curDef;
curDef = curDef ? 0 : 1;
defMesLeft = 0;
for (k = 0; k < defLeft; ++k)
{
FuncTyp method;
method = GetMethod(defMessages[which][k] . object, defMessages[which][k] . message);
if (method)
{
(*method)(defMessages[which][k] . object);
}
}
}
if (logging)
{
InhibitLogging(false);
}
/*Do tasks that are waiting*/
if (tasksLeft)
{
for (k = 0; k < tasksLeft; ++k)
{
(*(doTasks[k]))();
}
tasksLeft = 0;
}
#ifdef INTERACTIVE
#ifndef SIGNALS
NewEvents();
#endif
/*Look for an event*/
if (curEvent != lastEvent)
{
/*There is an event*/
curEvent = (curEvent + 1) % MAXNEVENTS;
readFromScript = false;
knownUserEvent = false;
switch (events[curEvent] . type)
{
case ET_SET_WINDOW:
/*Changed windows, reset the moving quality to highest*/
if (IsValidWindow(events[curEvent] . data . window))
{
inputWindow = events[curEvent] . data . window;
}
else
{
inputWindow = 0;
}
break;
case ET_ICONIFY_WINDOW:
/*Window has been iconified*/
if (IsValidWindow(events[curEvent] . data . window))
{
events[curEvent] . data . window -> flags |= WINICONIFIED;
}
break;
case ET_DEICONIFY_WINDOW:
/*Window has been iconified*/
if (IsValidWindow(events[curEvent] . data . window))
{
events[curEvent] . data . window -> flags &= ~WINICONIFIED;
}
break;
case ET_DEPTHCHANGE_WINDOW:
/*Window's depth has changed. See if we need to
change any subwindow*/
if (IsValidWindow(events[curEvent] . data . window))
{
WinInfoPtr superWindow;
ObjPtr subWindows;
/*See if it has subwindows and needs to be popped*/
superWindow = (WinInfoPtr) GetVar((ObjPtr) events[curEvent] . data . window, SUPERWINDOW);
subWindows = GetVar((ObjPtr) superWindow, SUBWINDOWS);
if (subWindows && !superWindow)
{
/*Window has sub windows*/
if (TopWindow() == events[curEvent] . data . window)
{
/*Pop the subwindows*/
ThingListPtr runner;
runner = LISTOF(subWindows);
while (runner)
{
PopWindow((WinInfoPtr) runner -> thing);
runner = runner -> next;
}
}
else if (BottomWindow() == events[curEvent] . data . window)
{
ThingListPtr runner;
/*This window has just been pushed*/
/*This may be a superwindow which has been pushed.
Check to see if all the subwindows are OK*/
superWindow = events[curEvent] . data . window;
subWindows = GetVar((ObjPtr) superWindow, SUBWINDOWS);
runner = LISTOF(subWindows);
while (runner)
{
if (!BelowAllBut((WinInfoPtr) runner -> thing, superWindow))
{
/*Window out of place*/
break;
}
runner = runner -> next;
}
if (runner)
{
/*One window is out of place. Push subwindows*/
runner = LISTOF(subWindows);
while (runner)
{
PushWindow((WinInfoPtr) runner -> thing);
runner = runner -> next;
}
/*Push super window*/
PushWindow(superWindow);
}
}
}
}
break;
case ET_KEY_DOWN:
if (runningScript)
{
AbortScriptAlert();
return;
}
if (events[curEvent] . data . key < FK_BASE)
{
sentKey = events[curEvent] . data . key;
keyWindow = inputWindow;
KeyDown(events[curEvent] . data . key,
events[curEvent] . flags);
}
else
{
switch(events[curEvent] . data . key)
{
case FK_PRINT_SCREEN:
if (inputWindow)
{
SelWindow(inputWindow);
SaveScreen(inputWindow, events[curEvent] . flags);
}
break;
case FK_1:
#ifndef RELEASE
Undo();
#endif
break;
case FK_2:
CutText();
break;
case FK_3:
CopyText();
break;
case FK_4:
PasteText();
break;
case FK_5:
DoShowControls();
break;
case FK_6:
#ifndef RELEASE
TestObserver();
#endif
break;
case FK_7:
DoObjFunction(OF_PUSHTOBOTTOM);
break;
case FK_8:
DoObjFunction(OF_BRINGTOTOP);
break;
case FK_9:
DoPickUpObjects();
break;
case FK_10:
#ifdef IRISNTSC
ToggleNTSC();
#endif
break;
case FK_11:
#ifdef IRISNTSC
ToggleStereo();
#endif
break;
case FK_12:
SetContextSensitiveHelp();
break;
}
}
break;
case ET_MOUSE_DOWN:
if (runningScript)
{
AbortScriptAlert();
return;
}
MouseDown(events[curEvent] . data . mouse . mouseButton,
events[curEvent] . data . mouse . x,
events[curEvent] . data . mouse . y,
events[curEvent] . flags);
break;
case ET_RESHAPE_WINDOW:
if (IsValidWindow(events[curEvent] . data . window))
{
ObjPtr subWindows;
long ol, or, ob, ot, nl, nr, nb, nt;
long sx, sy, ox, oy;
SelWindow(events[curEvent] . data . window);
if (!selWinInfo)
{
break;
}
reshapeviewport();
/*Stuff ol, or, ob, ot*/
getorigin(&ox, &oy);
getsize(&sx, &sy);
ol = ((WinInfoPtr) selWinInfo) -> nl;
or = ((WinInfoPtr) selWinInfo) -> nr;
ob = ((WinInfoPtr) selWinInfo) -> nb;
ot = ((WinInfoPtr) selWinInfo) -> nt;
nl = ox;
nr = ox + sx;
nb = oy;
nt = oy + sy;
if (nl != ol || nr != or || nb != ob || nt != ot)
{
/*Change this window*/
((WinInfoPtr) selWinInfo) -> ol = ol;
((WinInfoPtr) selWinInfo) -> or = or;
((WinInfoPtr) selWinInfo) -> ob = ob;
((WinInfoPtr) selWinInfo) -> ot = ot;
((WinInfoPtr) selWinInfo) -> nl = nl;
((WinInfoPtr) selWinInfo) -> nr = nr;
((WinInfoPtr) selWinInfo) -> nb = nb;
((WinInfoPtr) selWinInfo) -> nt = nt;
if (logging && !GetVar((ObjPtr) selWinInfo, SUPERWINDOW) &&
!GetPredicate((ObjPtr) selWinInfo, INHIBITLOGGING))
{
char cmd[400];
sprintf(cmd, "locate %d %d %d %d\n",
nl, nr, nb, nt);
Log(cmd);
}
ReshapeWindow((ObjPtr) selWinInfo);
}
/*The window has been moved. Both buffers are bad*/
ImInvalid((ObjPtr) selWinInfo);
/*Now, see if any of the subwindows need moving*/
subWindows = GetVar((ObjPtr) selWinInfo, SUBWINDOWS);
if (subWindows)
{
long sox, soy, ssx, ssy;
long l, r, b, t;
ObjPtr var;
real margin[4];
ThingListPtr runner;
runner = LISTOF(subWindows);
while (runner)
{
SelWindow((WinInfoPtr) runner -> thing);
/*Get the window position within superwindow*/
getorigin(&sox, &soy);
getsize(&ssx, &ssy);
var = GetVar(runner -> thing, SUBWINDOWMARGIN);
if (var)
{
Array2CArray(margin, var);
}
else
{
margin[0] = 0.0;
margin[1] = 0.0;
margin[2] = 0.0;
margin[3] = 0.0;
}
/*Adjust*/
l = nl + (int) margin[0];
r = nr - (int) margin[1];
b = nb + (int) margin[2];
t = nt - (int) margin[3];
if (l != sox || b != soy ||
r != sox + ssx - 1 || t != soy + ssy - 1)
{
winposition(l, r, b, t);
ImInvalid(runner -> thing);
}
runner = runner -> next;
}
}
}
break;
case ET_DRAW_WINDOW:
if (IsValidWindow(events[curEvent] . data . window))
{
SelWindow(events[curEvent] . data . window);
reshapeviewport();
if (selWinInfo)
{
/*Both buffers are bad*/
ImInvalid((ObjPtr) selWinInfo);
}
}
break;
case ET_CLOSE_WINDOW:
if (IsValidWindow(events[curEvent] . data . window))
{
CloseWindow(events[curEvent] . data . window);
}
break;
case ET_QUIT:
MaybeQuit();
break;
}
}
else
#endif
if (settleEvents > 0)
{
--settleEvents;
}
else
{
/*If there's an object to drop, drop it.*/
if (dropObject)
{
WinInfoPtr dropWindow;
dropWindow = WhichWindow(dropX, dropY);
if (dropWindow)
{
int left, right, bottom, top;
int ox, oy;
SelWindow(dropWindow);
GetWindowBounds(&left, &right, &bottom, &top);
GetWindowOrigin(&ox, &oy);
dropX -= ox;
dropY -= oy;
if (dropX >= left && dropX <= right &&
dropY >= bottom && dropY <= top)
{
FuncTyp method;
/*Drop*/
method = GetMethod((ObjPtr) selWinInfo, DROPOBJECTS);
if (method)
{
if (logging)
{
char cmd[256];
sprintf(cmd, "drop %d %d\n", dropX, dropY);
Log(cmd);
InhibitLogging(true);
}
(*method)(selWinInfo, dropObject, dropX, dropY);
if (logging)
{
InhibitLogging(false);
}
}
}
}
DeleteThing(dropObject);
dropObject = NULLOBJ;
}
#ifdef CHANGECURSOR
#ifdef INTERACTIVE
#ifdef GRAPHICS
{
WinInfoPtr cursorWindow;
FuncTyp method;
int x, y;
x = getvaluator(MOUSEX);
y = getvaluator(MOUSEY);
cursorWindow = WhichWindow(x, y);
if (cursorWindow != lastCursorWindow)
{
/*Enter and leave messages*/
if (lastCursorWindow)
{
method = GetMethod((ObjPtr) lastCursorWindow, LEAVECURSOR);
if (method)
{
(*method)(lastCursorWindow);
}
}
if (cursorWindow)
{
method = GetMethod((ObjPtr) cursorWindow, ENTERCURSOR);
if (method)
{
SelWindow(cursorWindow);
(*method)(cursorWindow);
}
}
lastCursorWindow = cursorWindow;
}
if (cursorWindow)
{
method = GetMethod((ObjPtr) cursorWindow, IDLECURSOR);
if (method)
{
SelWindow(cursorWindow);
(*method)((ObjPtr) cursorWindow, x, y);
}
}
}
#endif
#endif
#endif
/*Idle the windows if appropriate*/
if (settingUp && runningScript)
{
readFromScript = true;
}
else
{
readFromScript = IdleAllWindows() ? false : true;
}
if (readFromScript)
{
if (runningScript)
{
ReadScriptLine();
}
else
{
#ifdef SOCKETS
/*Idle all connections*/
IdleAllConnections();
#endif
}
}
IdleTimers();
#ifdef RELEASE
TrashDay();
#else
if (GetPrefTruth(PREF_RECKLESSGC))
{
struct tms buffer;
long curTime;
curTime = times(&buffer);
if (curTime - lastGC > GCEVERY)
{
TrashDay();
lastGC = curTime;
}
}
else
{
TrashDay();
}
#endif
}
}
void MainLoop()
/*Main loop for scian*/
{
SetSystemClock(0.0);
while (running)
{
EndLongOperation();
OneEvent(true);
}
EndScript();
if (stereoOn)
{
#ifdef IRISNTSC
Set60();
#endif
}
}
void InitEvents()
{
}
void KillEvents()
{
}
|