home *** CD-ROM | disk | FTP | other *** search
Text File | 1995-06-25 | 22.3 KB | 773 lines | [TEXT/KAHL] |
- /*
- Little Smalltalk, version 3
- Written by Tim Budd, Oregon State University, June 1988
-
- Symantec Think Class Library interface code
- ©Julian Barkway, April 1994, all rights reserved.
-
- glue2.cp
- --------
-
- This is the interface between Little Smalltalk and the Symantec Think
- Class Library (v1.1.3). Where possible, I have retained the StdWin
- function names and parameters used in the original Little Smalltalk (v3)
- (although certain structures now refer to TCL objects) in order to assist
- porting.
-
- Glue1.cp contains functions relating to windows, menus, graphics and dialogues.
- Glue2.cp contains text, event handling and general purpose functions.
- */
-
- #include <stdio.h>
- #include <string.h>
- #include "env.h"
- #include "memory.h"
- #include "macio.h"
- #include "tclprim.proto.h"
-
- #undef class
- #include "Constants.h"
- #include "CDataFile.h"
- #include "CGraphicsPane.h"
- #include "CTextPane.h"
- #include "CSelectPane.h"
- #include "CLStWindow.h"
- #include "CLStApp.h"
- #include "CLStSwitchboard.h"
- #include "CLStScrollPane.h"
- #include "LStResources.h"
- #include "glue.h"
-
- extern short gClicks;
- extern CLStApp *gSmalltalk;
-
- #define uchar unsigned char // Just laziness :-)
-
-
- //===================================================================================
- // Set the font in the given TextEdit to the font specified in fontName.
- //===================================================================================
- void setFont (TEXTEDIT *tp, char *fontName)
- {
- Str255 str;
- Rect margin = {0, 0, 0, 0};
-
- strcpy ((char *)str, fontName);
- CtoPstr ((char *)str);
- ((CTextPane *)tp)->SetFontName (str);
- // Force a dummy re-size which will re-calculate number
- // of complete lines available, thereby ensuring that
- // the last line doesn't get clipped vertically.
- ((CTextPane *)tp)->ResizeFrame (&margin);
- ((CTextPane *)tp)->AdjustBounds ();
- }
-
-
- //===================================================================================
- // Set the font size in the given TextEdit to that specified by fontSize.
- //===================================================================================
- void setFontSize (TEXTEDIT *tp, short fontSize)
- {
- Rect margin = {0, 0, 0, 0};
-
- ((CTextPane *)tp)->SetFontSize (fontSize);
- ((CTextPane *)tp)->ResizeFrame (&margin);
- ((CTextPane *)tp)->AdjustBounds ();
- }
-
-
- //===================================================================================
- // Set the type face in the given TextEdit to that specified by typeFace.
- //
- // Note that in Smalltalk the following faces are available:
- // 1 - plain,
- // 2 - bold,
- // 3 - italic,
- // 4 - underline
- //
- // and are specified by the numbers given NOT the Mac system constants.
- //
- //===================================================================================
- void setTypeFace (TEXTEDIT *tp, short typeFace)
- {
- Rect margin = {0, 0, 0, 0};
-
- switch (typeFace) {
- case 1:
- typeFace = normal;
- break;
- case 2:
- typeFace = bold;
- break;
- case 3:
- typeFace = italic;
- break;
- case 4:
- typeFace = underline;
- break;
- default:
- typeFace = normal;
- }
- ((CTextPane *)tp)->SetFontStyle (typeFace);
- ((CTextPane *)tp)->ResizeFrame (&margin);
- ((CTextPane *)tp)->AdjustBounds ();
- }
-
-
- //===================================================================================
- // Replace the currently selected text in the given TextEdit by the text specified.
- //===================================================================================
- void tereplace (TEXTEDIT *tp, char *str)
- {
- short i;
- long selStart, selEnd;
- TEHandle teh = ((CTextPane *)tp)->macTE;
-
- for (i = 0; i < strlen (str); i++) // Convert all LFs to CRs
- if (str [i] == '\n') // -- probably unnecessary in majority of cases.
- str [i] = '\r';
-
- ((CTextPane *)tp)->GetSelection (&selStart, &selEnd);
-
- if (selEnd > selStart) {
- ((CTextPane *)tp)->SetSelection (selEnd, selEnd, FALSE);
- }
-
- ((CTextPane *)tp)->InsertTextPtr ((Ptr)str, (long)strlen (str), TRUE);
- ((CTextPane *)tp)->AdjustBounds ();
- }
-
-
- //===================================================================================
- // Replace all the text in a text pane with the given text.
- //===================================================================================
- void replaceAllText (TEXTEDIT *tp, char *str)
- {
- short i;
-
- for (i = 0; i < strlen (str); i++) // Convert all LFs to CRs
- if (str [i] == '\n')
- str [i] = '\r';
-
- ((CTextPane *)tp)->ReplaceContents (str);
- ((CTextPane *)tp)->AdjustBounds ();
- }
-
-
- //===================================================================================
- // Delete all the text in a text pane.
- //===================================================================================
- void deleteAllText (TEXTEDIT *tp)
- {
- ((CTextPane *)tp)->DeleteContents ();
- ((CTextPane *)tp)->AdjustBounds ();
- }
-
-
- //===================================================================================
- // Return current size of pane.
- //===================================================================================
- void getPaneSize (TEXTEDIT *tp, short *width, short *height)
- {
- long w, h;
-
- ((CPane *)tp)->GetPixelExtent (&w, &h);
- *width = (short)w;
- *height = (short)h;
- }
-
-
- #define getSizingOptions(x,y,x1,y1) if (x) \
- x1 = sizELASTIC; \
- else \
- x1 = sizFIXEDLEFT; \
- if (y) \
- y1 = sizELASTIC; \
- else \
- y1 = sizFIXEDLEFT
-
- //===================================================================================
- // Add a basic pane to a window.
- //===================================================================================
- TEXTEDIT *addScrollPane (WINDOW *win, short left, short top, short right, short bottom,
- short horizOption, short vertOption)
- {
- CLStScrollPane *scrollPane;
- short w = right - left,
- h = bottom - top;
-
- scrollPane = new (CLStScrollPane);
- scrollPane->IScrollPane ((CLStWindow *)win->window, (CDocument *)(win->document),
- w, h, left, top,
- (SizingOption)horizOption, (SizingOption)vertOption,
- TRUE, TRUE, TRUE);
- return (char *)scrollPane;
- }
-
-
- //===================================================================================
- // Add a selection pane to a window.
- //===================================================================================
- TEXTEDIT *addSelPane (WINDOW *win, short left, short top, short right, short bottom,
- short horizElastic, short vertElastic, short lineLength)
- {
- CSelectPane *selPane;
- CLStScrollPane *scrollPane;
- LongPt origin = {0L, 0L};
- SizingOption horizOption, vertOption;
-
- getSizingOptions (horizElastic, vertElastic, horizOption, vertOption);
- scrollPane = (CLStScrollPane *)addScrollPane (win, left, top, right, bottom,
- horizOption, vertOption);
- selPane = new (CSelectPane);
- selPane->ISelectPane (scrollPane, (CDocument *)(win->document),
- horizOption, vertOption, lineLength);
- ((CDocument *)(win->document))->itsMainPane = selPane;
- ((CDocument *)(win->document))->itsGopher = selPane;
-
- scrollPane->InstallPanorama (selPane);
- selPane->ScrollTo (&origin, TRUE); // Ensure everything is visible
-
- return (char *)selPane;
- }
-
-
- //===================================================================================
- // Add a text pane to a window
- //===================================================================================
- TEXTEDIT *addTextPane (WINDOW *win, short left, short top, short right, short bottom,
- short horizElastic, short vertElastic, short lineLength)
- {
- CTextPane *textPane;
- CLStScrollPane *scrollPane;
- LongPt origin = {0L, 0L};
- SizingOption horizOption, vertOption;
-
- getSizingOptions (horizElastic, vertElastic, horizOption, vertOption);
- scrollPane = (CLStScrollPane *)addScrollPane (win, left, top, right, bottom,
- horizOption, vertOption);
- textPane = new (CTextPane);
- textPane->ITextPane (scrollPane, (CDocument *)(win->document),
- horizOption, vertOption, lineLength);
- ((CDocument *)(win->document))->itsMainPane = textPane;
- ((CDocument *)(win->document))->itsGopher = textPane;
-
- scrollPane->InstallPanorama (textPane);
- textPane->ScrollTo (&origin, TRUE); // Ensure everything is visible
-
- return (char *)textPane;
- }
-
-
- //===================================================================================
- // Stub function provided for StdWin compatibility.
- //===================================================================================
- TEXTEDIT *tecreate (WINDOW *win, int left, int top, int right, int bottom)
- {
- return addTextPane (win, left, top, right, bottom, TRUE, TRUE, 2000);
- }
-
-
- //===================================================================================
- // Add a graphics pane to a window
- //===================================================================================
- TEXTEDIT *addGraphicsPane (WINDOW *win, short left, short top, short right, short bottom,
- short horizElastic, short vertElastic)
- {
- CGraphicsPane *gPane;
- CLStScrollPane *scrollPane;
- LongPt origin = {0L, 0L};
- SizingOption horizOption, vertOption;
-
- getSizingOptions (horizElastic, vertElastic, horizOption, vertOption);
- scrollPane = (CLStScrollPane *)addScrollPane (win, left, top, right, bottom,
- horizOption, vertOption);
- gPane = new (CGraphicsPane);
- gPane->IGraphicsPane (scrollPane, (CDocument *)(win->document),
- horizOption, vertOption);
- ((CDocument *)(win->document))->itsMainPane = gPane;
- ((CDocument *)(win->document))->itsGopher = gPane;
-
- scrollPane->InstallPanorama (gPane);
- gPane->ScrollTo (&origin, TRUE); // Ensure everything is visible
-
- return (char *)gPane;
- }
-
-
- //===================================================================================
- // Stub function provided for StdWin compatibility.
- //===================================================================================
- Boolean teevent (TEXTEDIT *tp, EVENT *e)
- {
- return FALSE;
- }
-
-
- //===================================================================================
- // Scroll the text, if necessary, to ensure that the selected area is visible in the
- // text pane.
- //===================================================================================
- void scrollToSelection (TEXTEDIT *tp)
- {
- ((CTextPane *)tp)->ScrollToSelection ();
- }
-
-
- //===================================================================================
- // Set the text selection to the given character positions.
- //===================================================================================
- void setTextSelection (TEXTEDIT *tp, long startPos, long endPos)
- {
- ((CTextPane *)tp)->SetSelection (startPos, endPos, TRUE);
- }
-
-
- //===================================================================================
- // Return the start and end character positions of the current text selection.
- //===================================================================================
- void getTextSelection (TEXTEDIT *tp, long *startPos, long *endPos)
- {
- ((CTextPane *)tp)->GetSelection (startPos, endPos);
- }
-
-
- //===================================================================================
- // tegettext - return all the text associated with the current TE.
- //===================================================================================
-
- #define MAXBUF 8 * 1024
- uchar buf [MAXBUF];
-
- char *tegettext (TEXTEDIT *tp)
- {
- Handle th;
- short i, j;
- long maxText;
-
- maxText = ((CTextPane *)tp)->GetLength ();
-
- th = ((CTextPane *)tp)->GetTextHandle ();
- if (maxText > MAXBUF - 1)
- maxText = MAXBUF - 1;
-
- BlockMove (*th, buf, maxText);
- buf [maxText] = '\0';
-
- return (char *)buf;
- }
-
-
- //===================================================================================
- // Return the text inside the selected area (if there is any)
- //===================================================================================
- char *teGetSelectedText (TEXTEDIT *tp)
- {
- long selStart, selEnd;
- short i;
- char *cp;
-
- cp = (char *)*(((CTextPane *)tp)->GetTextHandle ());
- ((CTextPane *)tp)->GetSelection (&selStart, &selEnd);
-
- if (selEnd <= selStart) {
- buf [0] = '\0';
- return (char *)buf;
- }
-
- for (i = 0; i < MAXBUF; i++) {
- if (selStart == selEnd)
- break;
- buf [i] = cp [selStart++];
- }
- buf [i] = '\0';
- return (char *)buf;
- }
-
-
- //===================================================================================
- // Draw the contents of the given TextEdit.
- //===================================================================================
- void tedraw (register TEXTEDIT *tp)
- {
- Rect area;
- LongRect lr, margin = {0, 0, 0, 0};
-
- ((CTextPane *)tp)->GetAperture (&lr);
- ((CTextPane *)tp)->FrameToQDR (&lr, &area);
- ((CTextPane *)tp)->Draw (&area);
- }
-
-
- //===================================================================================
- // Save the text of a TextEdit to the given file.
- //===================================================================================
- void saveTE (TEXTEDIT *tp, short fileNum)
- {
- CDataFile *fil;
- FILE *fd;
- CharsHandle teh;
-
- teh = TEGetText (((CTextPane *)tp)->macTE);
-
- fil = new (CDataFile);
- fil->IDataFile ();
- fd = getFilePointer (fileNum);
- fil->refNum = fd->fileRef;
- fil->WriteAll ((Handle)teh);
- }
-
-
- //===================================================================================
- // Load the text of a TextEdit from the given file.
- //===================================================================================
- void loadTE (TEXTEDIT *tp, short fileNum)
- {
- CDataFile *fil;
- FILE *fd;
- Handle hndl, h;
-
- fil = new (CDataFile);
- fil->IDataFile ();
- fd = getFilePointer (fileNum);
- fil->refNum = fd->fileRef;
- hndl = fil->ReadAll ();
- ((CTextPane *)tp)->ReplaceContents (hndl); // Parameter type changed to handle - v3.1.5
- ((CTextPane *)tp)->AdjustBounds ();
- h = *hndl; // Safe handle disposal added for v3.1.5
- if (h) {
- DisposHandle (hndl);
- }
- }
-
-
- //===================================================================================
- // Send an Open Document AppleEvent to the specified app using the specified file.
- //===================================================================================
- OSErr sendOpenDocEvent (long theAppSig, SFReply *theSFReply)
- {
- AppleEvent aEvent;
- FSSpec theFile;
- WDPBRec wdInfo;
- OSErr err;
- AEDescList docList;
- AEDesc docDesc, sigDesc;
- AERecord aeRec;
- Boolean disposeCheck [4] = {FALSE, FALSE, FALSE, FALSE};
-
- err = AECreateDesc (typeApplSignature, &theAppSig, (Size)sizeof(long),
- &sigDesc);
- if (err)
- goto sendOpenDocEvent_exit;
-
- disposeCheck [0] = TRUE;
- err = AECreateAppleEvent (kCoreEventClass, kAEOpenDocuments, &sigDesc,
- kAutoGenerateReturnID, kAnyTransactionID, &aEvent);
- if (err)
- goto sendOpenDocEvent_exit;
-
- disposeCheck [1] = TRUE;
- wdInfo.ioNamePtr = NULL; // Convert SFReply to FSSpec
- wdInfo.ioVRefNum = theSFReply->vRefNum;
- wdInfo.ioWDIndex = 0;
- wdInfo.ioWDProcID = 0;
- err = PBGetWDInfo (&wdInfo, FALSE);
- if (err)
- goto sendOpenDocEvent_exit;
-
- theFile.vRefNum = wdInfo.ioWDVRefNum;
- theFile.parID = wdInfo.ioWDDirID;
- BlockMove (theSFReply->fName, theFile.name, (long)theSFReply->fName [0] + 1);
-
- err = AECreateList (NULL, 0, FALSE, &docList);
- if (err)
- goto sendOpenDocEvent_exit;
-
- disposeCheck [2] = TRUE;
- err = AECreateDesc (typeFSS, &theFile, (Size)sizeof (FSSpec), &docDesc);
- if (err)
- goto sendOpenDocEvent_exit;
-
- disposeCheck [3] = TRUE;
- err = AEPutDesc (&docList, 0L, &docDesc);
- if (err)
- goto sendOpenDocEvent_exit;
-
- err = AEPutParamDesc (&aEvent, keyDirectObject, &docList);
- if (err)
- goto sendOpenDocEvent_exit;
-
- err = AESend (&aEvent, NULL, kAENoReply + kAEAlwaysInteract + kAECanSwitchLayer,
- kAENormalPriority, kAEDefaultTimeout, NULL, NULL);
-
- sendOpenDocEvent_exit:
- if (disposeCheck [1])
- AEDisposeDesc (&aEvent);
- if (disposeCheck [2])
- AEDisposeDesc (&docList);
- if (disposeCheck [3])
- AEDisposeDesc (&docDesc);
- if (err)
- return err;
-
- return 0L;
- }
-
-
- //===================================================================================
- // Translate the info provided after an Open Document event has been received into
- // the full path and file type that Smalltalk currently likes. (I really will have
- // to get Smalltalk used to dealing with directory IDs one of these days...) Return
- // FALSE if info not present.
- //===================================================================================
- Boolean getFileInfo (char *fullPath, long *fType)
- {
- if (gSmalltalk->theFile.fType == 0L)
- return FALSE;
-
- *fType = (long)gSmalltalk->theFile.fType;
- getPathNameFromWD ((long)gSmalltalk->theFile.vRefNum, fullPath);
- PtoCstr (gSmalltalk->theFile.fName);
- strcat (fullPath, (char *)gSmalltalk->theFile.fName);
- CtoPstr ((char *)gSmalltalk->theFile.fName);
- return TRUE;
- }
-
-
- //===================================================================================
- // Process any AppleEvents sent by the Finder when the application is first launched.
- // I handle these separately from other events so I can load a system image before
- // Smalltalk itself is started.
- //
- // Only HighLevelEvents are processed; anything else is ignored.
- //===================================================================================
- Boolean processStartUpEvent (char *buf)
- {
- EventRecord event;
- long fType;
- short i = 255;
- OSErr err;
-
- while (i) {
- if (WaitNextEvent (highLevelEventMask, &event, 0, NULL) ) {
- if (AEProcessAppleEvent (&event))
- return FALSE; // Error case.
-
- if (getFileInfo (buf, &fType)) {
- if (fType == kSysImageType)
- return TRUE;
- else { // Not a sys. image so requeue Event for handling later
- err = sendOpenDocEvent (kCreator, &gSmalltalk->theFile);
- return FALSE;
- }
- }
- }
- i--;
- }
- }
-
- void printLog (char *msg);
- //===================================================================================
- // Get a user event from the system and translate it into StdWin format.
- //===================================================================================
- Point lastMouse = {-32767, -32767};
-
- void wgetevent (EVENT *ep)
- {
- EventRecord *macEvent;
- Point wp;
- char theChar;
- Byte keyCode;
- WindowPtr w;
-
- gSmalltalk->lastEvent.what = 0;
- gSmalltalk->theFile.fType = 0L;
-
- gSmalltalk->Process1Event ();
- if (gSmalltalk->menuID == 0xffff) {
- ep->type = WE_QUIT;
- return;
- }
- if (gSmalltalk->lastEvent.what == 0) {
- ep->type = WE_NULL;
- return;
- }
-
- macEvent = &(gSmalltalk->lastEvent);
-
- wp = macEvent->where;
- GlobalToLocal (&wp);
- if (lastMouse.h == -32767 && lastMouse.v == -32767)
- lastMouse = wp;
-
-
- w = FrontWindow ();
- if (w)
- ep->window = ((CLStWindow *)GetWRefCon (w))->theLStWindow;
- else
- ep->window = NULL;
-
- switch (macEvent->what) {
- case mouseDown:
- processMouseDown (macEvent, ep);
- break;
- case mouseUp:
- ep->type = WE_MOUSE_UP;
- ep->u.where.h = wp.h;
- ep->u.where.v = wp.v;
- ep->u.where.clicks = 1;
- ep->u.where.button = 1;
- ep->u.where.mask = 0;
- break;
- case keyDown:
- case autoKey:
- theChar = macEvent->message & charCodeMask;
- keyCode = (macEvent->message & keyCodeMask) >> 8;
- if (macEvent->modifiers & cmdKey)
- break;
- switch (keyCode) {
- case kEscapeOrClear:
- case kLeftCursor:
- case kRightCursor:
- case kUpCursor:
- case kDownCursor:
- case KeyHome:
- case KeyEnd:
- case KeyPageUp:
- case KeyPageDown:
- case KeyEscape:
- case KeyClear:
- case KeyHelp:
- case KeyFwdDelete:
- case KeyF1:
- case KeyF2:
- case KeyF3:
- case KeyF4:
- case KeyF5:
- case KeyF6:
- case KeyF7:
- case KeyF8:
- case KeyF9:
- case KeyF10:
- case KeyF11:
- case KeyF12:
- case KeyF13:
- case KeyF14:
- case KeyF15:
- ep->type = WE_KEY;
- ep->u.key.code = keyCode;
- ep->u.key.mask = WM_META;
- break;
- case KeyLeftCursor:
- case KeyRightCursor:
- case KeyUpCursor:
- case KeyDownCursor:
- ep->type = WE_COMMAND;
- ep->u.command = WC_LEFT;
- break;
- case kEnterKey:
- ep->type = WE_COMMAND;
- ep->u.command = WC_RETURN;
- break;
- default:
- ep->type = WE_CHAR;
- ep->u.character = theChar;
- }
- break;
- case updateEvt:
- {
- WindowPtr w = FrontWindow ();
- Rect r = (**(((WindowRecord *)w)->updateRgn)).rgnBBox;
-
- ep->type = WE_DRAW;
- ep->u.area.left = r.left;
- ep->u.area.top = r.top;
- ep->u.area.right = r.right;
- ep->u.area.bottom = r.bottom;
- break;
- }
- case activateEvt:
- ep->type = WE_ACTIVATE;
- break;
- case kHighLevelEvent: /* Process AppleEvent */
- ep->type = WE_EXTERN;
- break;
- default:
- if ( (wp.h != lastMouse.h)
- || (wp.v != lastMouse.v) ) {
- ep->type = WE_MOUSE_MOVE;
- ep->u.where.h = wp.h;
- ep->u.where.v = wp.v;
- lastMouse = wp;
- ep->u.where.clicks = gClicks;
- ep->u.where.button = 1;
- ep->u.where.mask = 0;
- }
- else
- ep->type = WE_NULL;
- }
- lastMouse = wp;
- }
-
-
- //===================================================================================
- // Special processing for mouseDown events.
- //===================================================================================
- void processMouseDown (EventRecord *macEvent, EVENT *ep)
- {
- if (gSmalltalk->winPart != inContent && gSmalltalk->winPart == inSysWindow)
- return;
-
- switch (gSmalltalk->winPart) {
- case inMenuBar:
- ep->type = WE_MENU;
- if (gSmalltalk->menuID > kSTMenuBase) {
- ep->u.m.id = gSmalltalk->menuID - kSTMenuBase;
- ep->u.m.item = gSmalltalk->menuItem; // Was: ' = gSmalltalk->menuItem - 1;'
- // - changed for v3.1.5
- }
- else {
- ep->type = WE_NULL;
- ep->u.m.id = 0;
- ep->u.m.item = 0;
- }
- break;
- case inDrag:
- ep->type = WE_MOVE;
- break;
- case inGrow:
- ep->type = WE_SIZE;
- break;
- case inGoAway:
- ep->type = WE_CLOSE;
- break;
- default:
- {
- WINDOW *w;
- GrafPtr aPort;
-
- ep->type = WE_MOUSE_DOWN;
- if (ep->window != NULL)
- ((CLStWindow *)(ep->window->window))->Prepare ();
- GlobalToLocal (&(macEvent->where)); // Return point in _window_ co-ords.
- ep->u.where.h = macEvent->where.h;
- ep->u.where.v = macEvent->where.v;
- ep->u.where.clicks = gClicks;
- if (macEvent->modifiers & optionKey)
- ep->u.where.button = 2; // Simulate a 2 button mouse with help of 'option' key
- else
- ep->u.where.button = 1;
- ep->u.where.mask = 0;
- }
- }
- }
-
-
- //===================================================================================
- // Stub function provided for StdWin compatibility.
- //===================================================================================
- void wsettimer (WINDOW *win, int deciseconds)
- {
- return;
- }
-