/*ScianObjWindows.c Object window stuff Eric Pepke March 28, 1990 */ #include "Scian.h" #include "ScianTypes.h" #include "ScianLists.h" #include "ScianWindows.h" #include "ScianColors.h" #include "ScianIDs.h" #include "ScianObjWindows.h" #include "ScianErrors.h" #include "ScianDraw.h" #include "ScianControls.h" #include "ScianArrays.h" #include "ScianScripts.h" #include "ScianVisWindows.h" #include "ScianDialogs.h" #include "ScianIcons.h" #include "ScianEvents.h" #include "ScianStyle.h" #include "ScianObjFunctions.h" #include "ScianPictures.h" #include "ScianButtons.h" #include "ScianTitleBoxes.h" #include "ScianTextBoxes.h" #include "ScianSliders.h" #ifdef PROTO void ReshapeList(ThingListPtr, int, int, int, int, int, int, int, int); #else void ReshapeList(); #endif int pauseDrawing = 0; char tempStr[TEMPSTRSIZE + 1]; ObjPtr objWindowClass; /*Object window class*/ ObjPtr dragBuffer = NULLOBJ; /*Objects held*/ Bool showWindows = true; /*Show new opened windows*/ ObjPtr NewControlWindow(object) ObjPtr object; /*Opens a new control window for object*/ { FuncTyp newCtlWindow; ObjPtr retVal; ObjPtr repObj, name, repName = NULLOBJ; char windowName[255]; if (IsIcon(object)) { /*It's an icon, use its REPOBJ. Do nothing if it has none.*/ object = GetVar(object, REPOBJ); if (!object) { return ObjFalse; } } strcpy(windowName, ""); MakeVar(object, NAME); name = GetVar(object, NAME); if (name) { if (repName) { strcat(windowName, " "); } strcat(windowName, GetString(name)); } newCtlWindow = GetMethod(object, NEWCTLWINDOW); if (newCtlWindow) { PauseDrawing(true); showWindows = showControlPanels; retVal = (*newCtlWindow)(object, windowName); showWindows = true; PauseDrawing(false); } else { retVal = NULLOBJ; } return retVal; } void SetEndpoints(object, x1, y1, x2, y2) ObjPtr object; int x1, y1, x2, y2; /*Sets the endpoints of an object*/ { int l, r, b, t; ObjPtr var; real loc[2]; l = MIN(x1, x2) - HANDLESIZE / 2; r = MAX(x1, x2) + HANDLESIZE / 2; b = MIN(y1, y2) - HANDLESIZE / 2; t = MAX(y1, y2) + HANDLESIZE / 2; Set2DIntBounds(object, l, r, b, t); var = NewRealArray(1, 2L); loc[0] = x1; loc[1] = y1; CArray2Array(var, loc); SetVar(object, STARTPOINT, var); var = NewRealArray(1, 2L); loc[0] = x2; loc[1] = y2; CArray2Array(var, loc); SetVar(object, ENDPOINT, var); } Bool Get2DIntBounds(object, l, r, b, t) ObjPtr object; int *l, *r, *b, *t; /*Gets the 2D integer bounds of a screen object*/ { ObjPtr boundsArray; boundsArray = GetFixedArrayVar("Get2DIntBounds", object, BOUNDS, 1, 4L); if (boundsArray) { real temp[4]; Array2CArray(temp, boundsArray); *l = temp[0]; *r = temp[1]; *b = temp[2]; *t = temp[3]; return true; } else { return false; } } Bool Set2DIntBounds(object, l, r, b, t) ObjPtr object; int l, r, b, t; /*Sets the 2D integer bounds of a screen object to l, r, b, t*/ { ObjPtr boundsArray; boundsArray = NewRealArray(1, 4L); if (boundsArray) { real temp[4]; temp[0] = l; temp[1] = r; temp[2] = b; temp[3] = t; CArray2Array(boundsArray, temp); SetVar(object, BOUNDS, boundsArray); return true; } else { return false; } } void ForAllObjects(obj, routine) ObjPtr obj; FuncTyp routine; /*Performs routine on all selected objects in win*/ { ObjPtr contents; FuncTyp method; method = GetMethod(obj, FORALLOBJECTS); if (method) { (*method)(obj, routine); } } static ObjPtr CloseObjWindow(theInfo) WinInfoPtr theInfo; /*Closes obj window theInfo*/ { return ObjTrue; } #ifdef GODLIKE static ObjPtr DrawBounds(stuff) ObjPtr stuff; /*Draws the bounds of stuff*/ { ThingListPtr runner; ObjPtr bounds, contents; if (IsList(stuff)) { runner = LISTOF(stuff); while (runner) { DrawBounds(runner -> thing); runner = runner -> next; } } else { contents = GetVar(stuff, CONTENTS); if (contents) { DrawBounds(contents); } bounds = GetVar(stuff, BOUNDS); if (bounds) { int l, r, b, t; Get2DIntBounds(stuff, &l, &r, &b, &t); FrameUIRect(l, r, b, t, UIWHITE); } } } static ObjPtr DrawSoftBounds(stuff) ObjPtr stuff; /*Draws the soft bounds of stuff*/ { ThingListPtr runner; ObjPtr bounds, contents; if (IsList(stuff)) { runner = LISTOF(stuff); while (runner) { DrawSoftBounds(runner -> thing); runner = runner -> next; } } else { contents = GetVar(stuff, CONTENTS); if (contents) { DrawSoftBounds(contents); } bounds = GetVar(stuff, BOUNDS); if (bounds) { int l, r, b, t; ObjPtr softBounds; Get2DIntBounds(stuff, &l, &r, &b, &t); softBounds = GetVar(stuff, INNERSOFTMARGIN); if (!softBounds) { FrameUIRect(l + MINORBORDER, r - MINORBORDER, b + MINORBORDER, t - MINORBORDER, UIRED); } softBounds = GetVar(stuff, OUTERSOFTMARGIN); if (!softBounds) { FrameUIRect(l - MINORBORDER, r + MINORBORDER, b - MINORBORDER, t + MINORBORDER, UIRED); } } } } static void SaveSubTemplate(stuff, file) ObjPtr stuff; FILE *file; /*Saves a subtemplate for stuff and its contents into file*/ { ThingListPtr runner; ObjPtr bounds, contents, name; if (IsList(stuff)) { runner = LISTOF(stuff); while (runner) { SaveSubTemplate(runner -> thing, file); runner = runner -> next; } } else { contents = GetVar(stuff, CONTENTS); if (contents) { SaveSubTemplate(contents, file); } bounds = GetVar(stuff, BOUNDS); if (bounds) { int l, r, b, t; Get2DIntBounds(stuff, &l, &r, &b, &t); name = GetVar(stuff, NAME); if (name) { fprintf(file, "\t{\"%s\", %d, %d, %d, %d},\n", GetString(name), l, r, b, t); } } } } static ObjPtr SaveTemplateReally(owner, reply) ObjPtr owner; char *reply; /*Really saves a template named reply*/ { FILE *file; char fileName[200]; ObjPtr contents; contents = GetVar(GetVar(owner, OWNERWINDOW), CONTENTS); sprintf(fileName, "%s.tpl", reply); file = fopen(fileName, "w"); if (file) { fprintf(file, "Template %sTemplate[] =\n {\n", reply); SaveSubTemplate(contents, file); fprintf(file, "\t{\"\", 0, 0, 0, 0}\n"); fprintf(file, " };\n\n"); fclose(file); } } void DoSaveTemplate() /*Saves a template for the current window*/ { if (selWinInfo) { char *s; WinInfoPtr curWindow, alertWindow; /*Figure out the name for the template*/ strcpy(tempStr, selWinInfo -> winTitle); s = tempStr; while (*s) { if (*s == ' ') *s = '_'; ++s; } curWindow = selWinInfo; alertWindow = AskUser((WinInfoPtr) selWinInfo, "Enter template name:", (FuncTyp) SaveTemplateReally, tempStr); SetVar((ObjPtr) alertWindow, OWNERWINDOW, (ObjPtr) curWindow); } } static ObjPtr AddObjToWindow(object, dialog) ObjPtr object; ObjPtr dialog; { ObjPtr contents, panel; contents = GetVar(GetVar(dialog, OWNERWINDOW), CONTENTS); panel = LISTOF(contents) -> thing; if (panel) { contents = GetVar(panel, CONTENTS); PrefixList(contents, object); SetVar(object, PARENT, panel); ImInvalid(object); } } static ObjPtr NewScreenSlider(dialog, name) ObjPtr dialog; char *name; /*Makes a new slider*/ { ObjPtr object; object = NewSlider(10, 10 + SLIDERWIDTH, 10, 100, PLAIN, name); AddObjToWindow(object, dialog); } static ObjPtr NewScreenScaleSlider(dialog, name) ObjPtr dialog; char *name; /*Makes a new slider*/ { ObjPtr object; object = NewSlider(10, 10 + SLIDERWIDTH, 10, 100, SCALE, name); AddObjToWindow(object, dialog); } static ObjPtr NewScreenTitleBox(dialog, name) ObjPtr dialog; char *name; /*Makes a new title box*/ { ObjPtr object; object = NewTitleBox(10, 100, 10, 70, name); AddObjToWindow(object, dialog); } static ObjPtr NewScreenRadioButton(dialog, name) ObjPtr dialog; char *name; /*Makes a new radio button*/ { ObjPtr object; object = NewRadioButton(10, 100, 10, 10 + CHECKBOXHEIGHT, name); AddObjToWindow(object, dialog); } static ObjPtr NewScreenPlainButton(dialog, name) ObjPtr dialog; char *name; /*Makes a new plain button*/ { ObjPtr object; object = NewButton(10, 100, 10, 10 + BUTTONHEIGHT, name); AddObjToWindow(object, dialog); } static ObjPtr NewScreenShortButton(dialog, name) ObjPtr dialog; char *name; /*Makes a new plain button*/ { ObjPtr object; object = NewButton(10, 100, 10, 10 + SHORTBUTTONHEIGHT, name); AddObjToWindow(object, dialog); } static ObjPtr NewScreenCheckBox(dialog, name) ObjPtr dialog; char *name; /*Makes a new check box*/ { ObjPtr object; object = NewCheckBox(10, 100, 10, 10 + CHECKBOXHEIGHT, name, false); AddObjToWindow(object, dialog); } static ObjPtr NewScreenTextBox(dialog, name) ObjPtr dialog; char *name; /*Makes a new text box*/ { ObjPtr object; object = NewTextBox(10, 100, 10, 10 + TEXTBOXHEIGHT, 0, name, name); AddObjToWindow(object, dialog); } static ObjPtr NewScreenEditableTextBox(dialog, name) ObjPtr dialog; char *name; /*Makes a new text box*/ { ObjPtr object; object = NewTextBox(10, 100, 10, 10 + EDITBOXHEIGHT, EDITABLE + WITH_PIT + ONE_LINE, name, name); AddObjToWindow(object, dialog); } void DoNewScreenSlider() /*Makes a new slider in the current window*/ { if (selWinInfo) { WinInfoPtr curWindow, alertWindow; curWindow = selWinInfo; alertWindow = AskUser((WinInfoPtr) selWinInfo, "Please name the new object:", (FuncTyp) NewScreenSlider, ""); SetVar((ObjPtr) alertWindow, OWNERWINDOW, (ObjPtr) curWindow); } } void DoNewScreenScaleSlider() /*Makes a new scale slider in the current window*/ { if (selWinInfo) { WinInfoPtr curWindow, alertWindow; curWindow = selWinInfo; alertWindow = AskUser((WinInfoPtr) selWinInfo, "Please name the new object:", (FuncTyp) NewScreenScaleSlider, ""); SetVar((ObjPtr) alertWindow, OWNERWINDOW, (ObjPtr) curWindow); } } void DoNewScreenTitleBox() /*Makes a new title box in the current window*/ { if (selWinInfo) { WinInfoPtr curWindow, alertWindow; curWindow = selWinInfo; alertWindow = AskUser((WinInfoPtr) selWinInfo, "Please name the new object:", (FuncTyp) NewScreenTitleBox, ""); SetVar((ObjPtr) alertWindow, OWNERWINDOW, (ObjPtr) curWindow); } } void DoNewScreenRadioButton() /*Makes a new radio button in the current window*/ { if (selWinInfo) { WinInfoPtr curWindow, alertWindow; curWindow = selWinInfo; alertWindow = AskUser((WinInfoPtr) selWinInfo, "Please name the new object:", (FuncTyp) NewScreenRadioButton, ""); SetVar((ObjPtr) alertWindow, OWNERWINDOW, (ObjPtr) curWindow); } } void DoNewScreenPlainButton() /*Makes a new plain button in the current window*/ { if (selWinInfo) { WinInfoPtr curWindow, alertWindow; curWindow = selWinInfo; alertWindow = AskUser((WinInfoPtr) selWinInfo, "Please name the new object:", (FuncTyp) NewScreenPlainButton, ""); SetVar((ObjPtr) alertWindow, OWNERWINDOW, (ObjPtr) curWindow); } } void DoNewScreenShortButton() /*Makes a new plain button in the current window*/ { if (selWinInfo) { WinInfoPtr curWindow, alertWindow; curWindow = selWinInfo; alertWindow = AskUser((WinInfoPtr) selWinInfo, "Please name the new object:", (FuncTyp) NewScreenShortButton, ""); SetVar((ObjPtr) alertWindow, OWNERWINDOW, (ObjPtr) curWindow); } } void DoNewScreenCheckBox() /*Makes a new check box in the current window*/ { if (selWinInfo) { WinInfoPtr curWindow, alertWindow; curWindow = selWinInfo; alertWindow = AskUser((WinInfoPtr) selWinInfo, "Please name the new object:", (FuncTyp) NewScreenCheckBox, ""); SetVar((ObjPtr) alertWindow, OWNERWINDOW, (ObjPtr) curWindow); } } void DoNewScreenTextBox() /*Makes a new text box in the current window*/ { if (selWinInfo) { WinInfoPtr curWindow, alertWindow; curWindow = selWinInfo; alertWindow = AskUser((WinInfoPtr) selWinInfo, "Please name the new object:", (FuncTyp) NewScreenTextBox, ""); SetVar((ObjPtr) alertWindow, OWNERWINDOW, (ObjPtr) curWindow); } } void DoNewScreenEditableTextBox() /*Makes a new text box in the current window*/ { if (selWinInfo) { WinInfoPtr curWindow, alertWindow; curWindow = selWinInfo; alertWindow = AskUser((WinInfoPtr) selWinInfo, "Please name the new object:", (FuncTyp) NewScreenEditableTextBox, ""); SetVar((ObjPtr) alertWindow, OWNERWINDOW, (ObjPtr) curWindow); } } #endif static ObjPtr DrawObjWindow(theInfo) WinInfoPtr theInfo; /*Draws the obj window theInfo*/ { #ifdef GRAPHICS ObjPtr contents; /*Draw the objects within the window*/ contents = GetVar((ObjPtr) theInfo, CONTENTS); if (contents) { if (IsList(contents)) { DrawList(contents); } } #ifdef GODLIKE if (GetPredicate((ObjPtr) theInfo, SHOWBOUNDS)) { DrawBounds(contents); } #endif #endif return ObjTrue; } #define BIP(r, o) #ifdef PROTO ObjPtr BoundsInvalid(ObjPtr object, unsigned long changeCount) #else ObjPtr BoundsInvalid(object, changeCount) ObjPtr object; unsigned long changeCount; #endif /*For an object, tests to see if it needs drawing. Returns NULLOBJ if it does not array[4] giving bounds if it does ObjTrue it it needs to be redrawn but does not know where In order for an object to be declared invalid, its changed bounds must have been changed more recently than changeCount */ { ObjPtr contents; ObjPtr myBounds; FuncTyp method; method = GetMethod(object, BOUNDSINVALID); if (method) { ObjPtr retVal; retVal = (*method)(object, changeCount); BIP(retVal, object); return retVal; } MakeVar(object, APPEARANCE); MakeVar(object, CHANGEDBOUNDS); if (GetVarChangeCount(object, CHANGEDBOUNDS) > changeCount) { /*Object is not good, so return the bounds*/ myBounds = GetVar(object, CHANGEDBOUNDS); if (myBounds && IsArray(myBounds) && RANK(myBounds) == 1 && DIMS(myBounds)[0] == 4) { BIP(myBounds, object); return myBounds; } else { BIP(ObjTrue, object); return ObjTrue; } } MakeVar(object, CONTENTS); contents = GetVar(object, CONTENTS); if (contents && IsList(contents)) { /*Still, maybe some of the contents need to be drawn*/ Bool firstTime; real boundsElements[4]; real testElements[4]; ObjPtr test; ThingListPtr runner; Bool doubleNoBounds = false; MakeVar(object, BOUNDS); myBounds = GetVar(object, BOUNDS); firstTime = true; runner = LISTOF(contents); while (runner) { test = BoundsInvalid(runner -> thing, changeCount); if (test) { /*Hey, the kid needs redrawing*/ if (IsRealArray(test)) { /*It has a bounds*/ if (firstTime) { Array2CArray(boundsElements, test); } else { Array2CArray(testElements, test); if (testElements[0] < boundsElements[0]) boundsElements[0] = testElements[0]; if (testElements[1] > boundsElements[1]) boundsElements[1] = testElements[1]; if (testElements[2] < boundsElements[2]) boundsElements[2] = testElements[2]; if (testElements[3] > boundsElements[3]) boundsElements[3] = testElements[3]; } } else { /*It doesn't have a bounds*/ if (firstTime) { /*Try to use my bounds*/ if (myBounds && IsArray(myBounds) && RANK(myBounds) == 1 && DIMS(myBounds)[0] == 4) { Array2CArray(boundsElements, myBounds); } else { doubleNoBounds = true; } } } firstTime = false; } runner = runner -> next; } /*Now return the bounds*/ if (firstTime != true) { if (doubleNoBounds) { BIP(ObjTrue, object); return ObjTrue; } else { ObjPtr retVal; retVal = NewRealArray(1, 4L); CArray2Array(retVal, boundsElements); BIP(retVal, object); return retVal; } } } return NULLOBJ; } ObjPtr MakeObjWindowDrawn(curWindow) WinInfoPtr curWindow; /*Method to make an obj window drawn. Returns true iff drawing done*/ { ObjPtr boundsInvalid; int l, r, b, t; int whichBuffer; if (IsDoubleBuf(curWindow)) { /*Double buffer, determine which buffer we're drawing*/ ObjPtr var; var = GetVar((ObjPtr) curWindow, WHICHBUFFER); if (var) { whichBuffer = GetInt(var); } else { whichBuffer = 0; } /*Set to other buffer*/ SetVar((ObjPtr) curWindow, WHICHBUFFER, NewInt(whichBuffer ? 0 : 1)); } else { /*Single buffer, just one buffer*/ whichBuffer = 0; } boundsInvalid = BoundsInvalid((ObjPtr) curWindow, GetVarChangeCount((ObjPtr) curWindow, whichBuffer ? BUFFER1 : BUFFER0)); if (boundsInvalid) { SetVar((ObjPtr) curWindow, whichBuffer ? BUFFER1 : BUFFER0, ObjTrue); #ifndef DONTCLIP if ((IsArray(boundsInvalid) && !GetPredicate((ObjPtr) curWindow, SHOWBOUNDS))) { real elements[4]; Array2CArray(elements, boundsInvalid); SetClipRect((int) elements[0], (int) elements[1], (int) elements[2], (int) elements[3]); DrawWindowInfo(curWindow); RestoreClipRect(); } else #endif { DrawWindowInfo(curWindow); } return ObjTrue; } return ObjFalse; } ObjPtr PressObjWindow(theInfo, x, y, flags) WinInfoPtr theInfo; int x, y; long flags; /*Does a press in object window theInfo*/ { ObjPtr contents, retVal = ObjFalse; #ifdef INTERACTIVE SetDrawingWindow(theInfo); /*Press in the objects within the window*/ contents = GetVar((ObjPtr) theInfo, CONTENTS); if (contents) { if (IsList(contents)) { retVal = PressObject(contents, x, y, flags); } } RestoreDrawingWindow(); #endif return retVal; } ObjPtr TurnDialObjWindow(theInfo, whichDial, delta, flags) WinInfoPtr theInfo; int whichDial; real delta; long flags; /*Does a turn of a dial whichDial by amount delta in object window theInfo*/ { ObjPtr contents, retVal = ObjFalse; #ifdef INTERACTIVE SetDrawingWindow(theInfo); /*Press in the objects within the window*/ contents = GetVar((ObjPtr) theInfo, CONTENTS); if (contents) { if (IsList(contents)) { retVal = TurnDialObject(contents, whichDial, delta, flags); } } RestoreDrawingWindow(); #endif return retVal; } #ifdef INTERACTIVE #ifdef PROTO ObjPtr TurnDialObject(ObjPtr obj, int whichDial, real delta, long flags) #else ObjPtr TurnDialObject(obj, whichDial, delta, flags) ObjPtr obj; int whichDial; real delta; long flags; #endif /*Turns dial whichDial amount delta in obj*/ { FuncTyp method; method = GetMethod(obj, TURNDIAL); if (method) { return (*method)(obj, whichDial, delta, flags); } else { return ObjFalse; } } #endif static ObjPtr DropObjWindow(window, object, x, y) ObjPtr window, object; int x, y; /*Does a drop in object window theInfo*/ { ObjPtr contents, retVal = ObjFalse; /*Drop in the objects within the window*/ contents = GetVar(window, CONTENTS); if (contents) { if (IsList(contents)) { retVal = DropList(contents, object, x, y); } } return retVal; } static ObjPtr KeyDownObjWindow(theInfo, theKey, flags) WinInfoPtr theInfo; int theKey; long flags; /*Does a key down in object window theInfo*/ { ObjPtr contents; /*Press in the objects within the window*/ contents = GetVar((ObjPtr) theInfo, CONTENTS); if (contents) { if (IsList(contents)) { KeyDownList(contents, theKey, flags); } } return ObjTrue; } void ReshapeObject(object, ol, or, ob, ot, left, right, bottom, top) ObjPtr object; int ol, or, ob, ot; int left, right, bottom, top; /*Reshapes object, which used to exist within owner with edges ol, or, ob, ot to one which exists within owner with edges left, right, bottom, top.*/ { FuncTyp method; method = GetMethod(object, RESHAPE); if (method) { (*method)(object, ol, or, ob, ot, left, right, bottom, top); } else { ObjPtr boundsArray, locArray; ObjPtr stickyInt; real bounds[4]; real oldWidth, oldHeight; /*Old width and height*/ Bool sideLocked[4]; /*True iff side is locked*/ Bool xStretch, yStretch; /*Stretchiness in x and y*/ int stickiness; /*Side stickiness of the object*/ real oldBounds[4]; /*Old bounds of the object*/ ObjPtr contents; /*Contents of the object, if any*/ real wr, hr; /*Width and height ratios*/ Bool isIcon = false; /*Is an icon?*/ wr = ((real) (right - left)) / ((real) (or - ol)); hr = ((real) (top - bottom)) / ((real) (ot - ob)); boundsArray = GetVar(object, BOUNDS); if (!boundsArray || !IsRealArray(boundsArray) || RANK(boundsArray) != 1 || DIMS(boundsArray)[0] != 4) { /*It might be an icon*/ locArray = GetVar(object, ICONLOC); if (!locArray && !IsRealArray(locArray) || RANK(locArray) != 1 || DIMS(locArray)[0] != 2) { return; } isIcon = true; Array2CArray(bounds, locArray); bounds[3] = bounds[2] = bounds[1]; bounds[1] = bounds[0]; } else { Array2CArray(bounds, boundsArray); } oldBounds[0] = bounds[0]; oldBounds[1] = bounds[1]; oldBounds[2] = bounds[2]; oldBounds[3] = bounds[3]; oldWidth = bounds[1] - bounds[0]; oldHeight = bounds[3] - bounds[2]; /*Get the object's stickiness*/ stickyInt = GetVar(object, STICKINESS); if (stickyInt && IsInt(stickyInt)) { stickiness = GetInt(stickyInt); } else { stickiness = 0; } if ((stickiness & STICKYLEFT) || (stickiness & FLOATINGLEFT)) { if (stickiness & FLOATINGLEFT) { bounds[0] = (bounds[0] - ol) * wr + left; } else { bounds[0] += left - ol; } if (!((stickiness & STICKYRIGHT) || (stickiness & FLOATINGRIGHT))) { bounds[1] = bounds[0] + oldWidth; } } if ((stickiness & STICKYRIGHT) || (stickiness & FLOATINGRIGHT)) { if (stickiness & FLOATINGRIGHT) { bounds[1] = (bounds[1] - ol) * wr + left; } else { bounds[1] += right - or; } if (!((stickiness & STICKYLEFT) || (stickiness & FLOATINGLEFT))) { bounds[0] = bounds[1] - oldWidth; } } if ((stickiness & STICKYBOTTOM) || (stickiness & FLOATINGBOTTOM)) { if (stickiness & FLOATINGBOTTOM) { bounds[2] = (bounds[2] - ob) * hr + bottom; } else { bounds[2] += bottom - ob; } if (!((stickiness & STICKYTOP) || (stickiness & FLOATINGTOP))) { bounds[3] = bounds[2] + oldHeight; } } if ((stickiness & STICKYTOP) || (stickiness & FLOATINGTOP)) { if (stickiness & FLOATINGTOP) { bounds[3] = (bounds[3] - ob) * hr + bottom; } else { bounds[3] += top - ot; } if (!((stickiness & STICKYBOTTOM) || (stickiness & FLOATINGBOTTOM))) { bounds[2] = bounds[3] - oldHeight; } } /*We've got a new bounds, put it back*/ if (isIcon) { locArray = NewRealArray(1, 2L); ((real *) ELEMENTS(locArray))[0] = bounds[0]; ((real *) ELEMENTS(locArray))[1] = bounds[2]; SetVar(object, ICONLOC, locArray); } else { boundsArray = NewRealArray(1, 4L); CArray2Array(boundsArray, bounds); SetVar(object, BOUNDS, boundsArray); } /*If there are some contents to this, do the reshape recursively*/ contents = GetVar(object, CONTENTS); if (contents && IsList(contents)) { ReshapeList(LISTOF(contents), 0, (int) (oldBounds[1] - oldBounds[0]), 0, (int) (oldBounds[3] - oldBounds[2]), 0, (int) (bounds[1] - bounds[0]), 0, (int) (bounds[3] - bounds[2])); } } } void ReshapeList(contents, ol, or, ob, ot, left, right, bottom, top) ThingListPtr contents; int ol, or, ob, ot; int left, right, bottom, top; /*Reshapes a list of objects using ReshapeObject*/ { while (contents) { ObjPtr object; object = contents -> thing; ReshapeObject(object, ol, or, ob, ot, left, right, bottom, top); contents = contents -> next; } } ObjPtr ReshapeObjWindow(window, ol, or, ob, ot, nl, nr, nb, nt) ObjPtr window; int ol, or, ob, ot; int nl, nr, nb, nt; /*Reshapes object window given that ol, or, ob, and ot was the old viewport. Does not redraw anything.*/ { ObjPtr contents; contents = GetVar(window, CONTENTS); if (contents && IsList(contents)) { ReshapeList(LISTOF(contents), 0, or - ol, 0, ot - ob, 0, nr - nl, 0, nt - nb); } return ObjTrue; } void ImInvalid(object) ObjPtr object; /*Alerts the window system that an object is no longer valid*/ { FuncTyp method; method = GetMethod(object, IMINVALID); if (method) { (*method)(object); } else { ObjPtr bounds; bounds = GetVar(object, BOUNDS); if (bounds && IsArray(bounds) && RANK(bounds) == 1 && DIMS(bounds)[0] == 4) { real elements[4]; Array2CArray(elements, bounds); /*Kludge because most objects draw one bigger*/ elements[1] += 1.0; elements[3] += 1.0; bounds = NewRealArray(1, 4L); CArray2Array(bounds, elements); SetVar(object, CHANGEDBOUNDS, bounds); } else { SetVar(object, CHANGEDBOUNDS, ObjTrue); } } } void ExpandInvalid(object) ObjPtr object; /*Expands the invalid bounds*/ { ObjPtr bounds, changedBounds; real biggerBounds[4]; real *elements; changedBounds = GetVar(object, CHANGEDBOUNDS); if (changedBounds && IsArray(changedBounds) && RANK(changedBounds) == 1 && DIMS(changedBounds)[0] == 4) { /*Have to expand these bounds*/ Array2CArray(biggerBounds, changedBounds); bounds = GetVar(object, BOUNDS); if (bounds && IsArray(bounds) && RANK(bounds) == 1 && DIMS(bounds)[0] == 4) { elements = ELEMENTS(bounds); biggerBounds[0] = MIN(elements[0], biggerBounds[0]); biggerBounds[1] = MAX(elements[1] + 1.0, biggerBounds[1]); biggerBounds[2] = MIN(elements[2], biggerBounds[2]); biggerBounds[3] = MAX(elements[3] + 1.0, biggerBounds[3]); changedBounds = NewRealArray(1, 4L); CArray2Array(changedBounds, biggerBounds); SetVar(object, CHANGEDBOUNDS, changedBounds); } else { SetVar(object, CHANGEDBOUNDS, ObjTrue); } return; } /*Fall through, just do ImInvalid*/ ImInvalid(object); } #ifdef PROTO void ImInvalidBounds(ObjPtr object, int l, int r, int b, int t) #else void ImInvalidBounds(object, l, r, b, t) ObjPtr object; int l, r, b, t; #endif /*Alerts the window system that an object is no longer valid within bounds*/ { ObjPtr bounds; real *elements; bounds = NewRealArray(1, 4L); elements = ELEMENTS(bounds); elements[0] = l; elements[1] = r; elements[2] = b; elements[3] = t; SetVar(object, CHANGEDBOUNDS, bounds); } #ifdef PROTO void PauseDrawing(Bool whether) #else void PauseDrawing(whether) Bool whether; #endif /*Pauses drawing for a while*/ { if (whether) { ++pauseDrawing; } else { --pauseDrawing; } } #ifdef PROTO void DrawSkeleton(Bool whether) #else void DrawSkeleton(whether) Bool whether; #endif /*Does subsequent DrawMe's in skeleton mode or not*/ { if (!whether) { EraseAll(); } OverDraw(whether); } void DrawMe(object) ObjPtr object; /*Redraws object in the current window undergoing interaction*/ { #ifdef GRAPHICS ExpandInvalid(object); if (overDraw) { EraseAll(); DrawObject(object); } else { if (!pauseDrawing) { drawMouse = true; } } #endif } #ifdef PROTO void DrawMeInBounds(ObjPtr object, int l, int r, int b, int t) #else void DrawMeInBounds(object, l, r, b, t) int l, r, b, t; ObjPtr object; #endif /*Redraws object in the current window undergoing interaction*/ { #ifdef GRAPHICS ImInvalidBounds(object, l, r, b, t); if (overDraw) { EraseAll(); DrawObject(object); } else { if (!pauseDrawing) { drawMouse = true; } } #endif } void InitPickUp() /*Initializes picking up objects*/ { if (dragBuffer) { DeleteThing(dragBuffer); dragBuffer = NULLOBJ; } } ObjPtr PickUpObject(object) ObjPtr object; /*Picks up an object*/ { object = ObjectWhichRepresents(selWinInfo, object); if (object && IsIcon(object)) { if (!dragBuffer) { iconXOff = iconYOff = 0; dragBuffer = NewList(); AddToReferenceList(dragBuffer); if (!runningScript) { MySetCursor(ICONCURSOR); } } PostfixList(dragBuffer, object); return ObjTrue; } else { return ObjFalse; } } void DoPickUpObjects() /*Picks up the objects in the icon in the selected window*/ { DoObjFunction(OF_PICK_UP); } void ToggleShowBounds() /*Toggles the show bounds in the current window*/ { if (selWinInfo) { Bool lastState; lastState = GetPredicate((ObjPtr) selWinInfo, SHOWBOUNDS); SetVar((ObjPtr) selWinInfo, SHOWBOUNDS, lastState ? ObjFalse : ObjTrue); #ifdef GRAPHICS #ifdef WINDOWS4D if (lastState) { int l, r, b, t; GetWindowBounds(&l, &r, &b, &t); minsize(r - l + 1, t - b + 1); maxsize(r - l + 1, t - b + 1); winconstraints(); } else { minsize(40, 30); maxsize(1280, 1024); winconstraints(); } #endif #endif ImInvalid((ObjPtr) selWinInfo); } } #ifdef PROTO WinInfoPtr NewObjWindow(ObjPtr superClass, char *title, long flags, int minWidth, int minHeight, int maxWidth, int maxHeight) #else WinInfoPtr NewObjWindow(superClass, title, flags, minWidth, minHeight, maxWidth, maxHeight) ObjPtr superClass; char *title; long flags; int minWidth, minHeight, maxWidth, maxHeight; #endif /*Creates a new object window for repObj with title title and flags flags. repObj can be null. If it isn't, the title will be updated according to the repObj's NAME. superClass is the class of the window, if NULLOBJ objWindowClass will be used*/ { WinInfoPtr retVal; WindowID theWindow; /*Edit flags*/ if (!hasRGB && (flags & WINRGB)) { flags &= ~WINRGB; } if (!hasCmap) flags |= WINRGB; if (showWindows) { theWindow = NewOpenedWindow(title, minWidth, minHeight, maxWidth, maxHeight,flags); } else { theWindow = 0; } retVal = NewWinInfo(superClass ? superClass : objWindowClass, theWindow, flags, title, minWidth, minHeight, maxWidth, maxHeight); SetVar((ObjPtr) retVal, CONTENTS, NewList()); /*Contents*/ if (showWindows) { CEWS(retVal, minWidth, minHeight); } #ifdef SELNEWWINDOWS inputWindow = retVal; #endif return retVal; } static ObjPtr FindObjectObjClass(object, name) ObjPtr object; char *name; /*Searches an object and its contents for an object with name*/ { ObjPtr retVal = NULLOBJ; ObjPtr objName, contents; /*First check to see if I am the object*/ objName = GetVar(object, NAME); if (objName && IsString(objName) && ObjectNameMatches(name, GetString(objName))) { if (!retVal) { retVal = NewList(); } PostfixList(retVal, object); } /*Now check my CONTENTS*/ contents = GetVar(object, CONTENTS); if (contents) { ObjPtr foundObjects; foundObjects = FindNamedObject(contents, name); if (foundObjects) { if (!retVal) { retVal = NewList(); } AppendList(retVal, foundObjects); } } return retVal; } static ObjPtr FindObjectObjWindow(object, name) ObjPtr object; char *name; /*Searches an object window and its subwindows for object name*/ { ObjPtr subWindows; ObjPtr retVal; ObjPtr foundObjects; retVal = NULLOBJ; foundObjects = FindObjectObjClass(object, name); if (foundObjects) { if (!retVal) { retVal = NewList(); } AppendList(retVal, foundObjects); } subWindows = GetVar(object, SUBWINDOWS); if (subWindows) { foundObjects = FindNamedObject(subWindows, name); if (foundObjects) { if (!retVal) { retVal = NewList(); } AppendList(retVal, foundObjects); } } return retVal; } static ObjPtr ForAllObjectsObjClass(object, routine) ObjPtr object; FuncTyp routine; /*Does routine on all objects within object*/ { ObjPtr contents; (*routine)(object); /*Now check my CONTENTS*/ contents = GetVar(object, CONTENTS); if (contents) { ForAllObjects(contents, routine); } return ObjTrue; } extern ObjPtr objClass; ObjPtr ShowObjWindowFrame(curWindow) WinInfoPtr curWindow; /*Shows the window frame*/ { #ifdef GRAPHICS #ifdef WINDOWS4D #ifndef NOHIDEFRAME if (!(selWinInfo -> id)) { return ObjFalse; } SelWindow(curWindow); if (logging) { Log("show frame\n"); } wintitle(selWinInfo -> winTitle); minsize(selWinInfo -> minWidth, selWinInfo -> minHeight); maxsize(selWinInfo -> maxWidth, selWinInfo -> maxHeight); winconstraints(); selWinInfo -> flags &= ~WINNOFRAME; #endif #endif #endif return ObjTrue; } ObjPtr HideObjWindowFrame(curWindow) WinInfoPtr curWindow; /*Hides the window frame*/ { #ifdef WINDOWS4D #ifdef GRAPHICS #ifndef NOHIDEFRAME if (logging) { Log("hide frame\n"); } SelWindow(curWindow); if (!(selWinInfo -> id)) { return ObjFalse; } noborder(); minsize(selWinInfo -> minWidth, selWinInfo -> minHeight); maxsize(selWinInfo -> maxWidth, selWinInfo -> maxHeight); winconstraints(); selWinInfo -> flags |= WINNOFRAME; #endif #endif #endif return ObjTrue; } void InitObjWindows() /*Initializes the obj window system*/ { objWindowClass = NewObject(windowClass, 0); AddToReferenceList(objWindowClass); SetMethod(objWindowClass, CLOSE, CloseObjWindow); SetMethod(objWindowClass, DRAW, DrawObjWindow); SetMethod(objWindowClass, PRESS, PressObjWindow); SetMethod(objWindowClass, TURNDIAL, TurnDialObjWindow); SetMethod(objWindowClass, DROPOBJECTS, DropObjWindow); SetMethod(objWindowClass, KEYDOWN, KeyDownObjWindow); SetMethod(objWindowClass, RESHAPE, ReshapeObjWindow); SetMethod(objWindowClass, MAKEDRAWN, MakeObjWindowDrawn); SetMethod(objWindowClass, SHOWFRAME, ShowObjWindowFrame); SetMethod(objWindowClass, HIDEFRAME, HideObjWindowFrame); SetMethod(objWindowClass, FINDOBJECT, FindObjectObjWindow); /*KLUDGE*/ SetMethod(objClass, FINDOBJECT, FindObjectObjClass); SetMethod(objClass, FORALLOBJECTS, ForAllObjectsObjClass); } static Bool repped; static ObjPtr testObject; static ObjPtr objectWhichRepresents; static ObjPtr CheckRepObj(object) ObjPtr object; /*Checks if an object matches testObject*/ { if (IsIcon(object) && (GetVar(object, REPOBJ) == testObject)) { objectWhichRepresents = object; repped = true; return ObjTrue; } else if ((object == testObject) && !repped) { objectWhichRepresents = object; return ObjTrue; } else { return ObjFalse; } } ObjPtr ObjectWhichRepresents(window, object) WinInfoPtr window; ObjPtr object; /*Returns the object in window that represents object, or NULLOBJ*/ { if (object == (ObjPtr) window) return (ObjPtr) window; repped = false; objectWhichRepresents = NULLOBJ; testObject = object; if (object) { ForAllObjects((ObjPtr) window, CheckRepObj); } else { return NULLOBJ; } if (!objectWhichRepresents) { ObjPtr var; var = GetVar(object, NAME); if (var) { ObjPtr list; list = FindNamedObject((ObjPtr) window, GetString(var)); if (list && LISTOF(list)) { objectWhichRepresents = LISTOF(list) -> thing; } } } return objectWhichRepresents; } ObjPtr DeleteObject(object) ObjPtr object; /*Deletes an object from the current window.*/ { ObjPtr deleteObject; if (!selWinInfo || !object) return ObjFalse; deleteObject = ObjectWhichRepresents(selWinInfo, object); Select(object, false); if (deleteObject) { FuncTyp method; object = deleteObject; method = GetMethod(object, DELETEICON); if (method) { if (IsTrue((*method)(object))) { ObjPtr contentsList; contentsList = GetVar(object, PARENT); if (!contentsList || !IsList(contentsList)) { contentsList = GetVar(contentsList, CONTENTS); } if (contentsList && IsList(contentsList)) { ObjPtr parent; parent = GetVar(contentsList, PARENT); if (parent) { ImInvalid(parent); } DeleteFromList(contentsList, object); return ObjTrue; } else { ReportError("DeleteObject","Internal error: cannot find contents list"); } } } } return ObjFalse; } void DoDelete() /*Deletes objects*/ { ObjPtr corral; Bool didit = false; if (logging) { InhibitLogging(true); } if (selWinInfo) { ForAllSelectedObjects(DeleteObject); } if (logging) { InhibitLogging(false); if (didit) { Log("delete\n"); } } } void KillObjWindows() /*Kills the obj window system*/ { DeleteThing(objWindowClass); } ObjPtr FindNamedObject(object, name) ObjPtr object; char *name; /*Finds object with name within object. Returns a list of matching objects*/ { FuncTyp method; ObjPtr retVal; method = GetMethod(object, FINDOBJECT); if (method) { retVal = (*method)(object, name); { ThingListPtr runner; if (retVal) { ObjPtr test, temp; ObjPtr repObj = NULLOBJ; Bool hasExact, hasInexact; ObjPtr exactList; /*See if there are both exact and inexact matches*/ hasExact = false; hasInexact = false; runner = LISTOF(retVal); exactList = NULLOBJ; while (runner) { test = runner -> thing; temp = GetVar(test, NAME); if (0 == strcmp2(GetString(temp), name)) { if (!hasExact) { exactList = NewList(); } PrefixList(exactList, test); hasExact = true; } else { hasInexact = true; } runner = runner -> next; } if (hasExact && hasInexact) { /*Only use the exact matches*/ retVal = exactList; } /*See if multiple objects are really the same object*/ runner = LISTOF(retVal); while (runner) { test = runner -> thing; if (IsIcon(test) && (temp = GetVar(test, REPOBJ))) { test = temp; } if (repObj) { /*There's already a repobj*/ if (test != repObj) break; } else { /*There isn't a repobj yet*/ repObj = test; } runner = runner -> next; } if (!runner) { /*They are all the same object*/ retVal = NewList(); PrefixList(retVal, repObj); } } return retVal; } } else { return NULLOBJ; } } void MakeMeCurrent(object) ObjPtr object; /*Makes object the current object in the local window*/ { if (runningScript && !scriptSelectP) { return; } if (selWinInfo) { ObjPtr oldCurrent; oldCurrent = GetVar((ObjPtr) selWinInfo, CURRENT); if (oldCurrent == object) return; FlushKeystrokes(); SetVar((ObjPtr) selWinInfo, CURRENT, object); if (oldCurrent) { ImInvalid(oldCurrent); DeferMessage(oldCurrent, YOURENOTCURRENT); } if (object) ImInvalid(object); } } Bool AmICurrent(object) ObjPtr object; /*Returns true iff object is the current object in the current window*/ { if (selWinInfo) { return GetVar((ObjPtr) selWinInfo, CURRENT) == object ? true : false; } else { return false; } }