/*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() { }