-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathTaskMaster3.p
2799 lines (2622 loc) · 96 KB
/
TaskMaster3.p
1
UNIT TaskMaster3;{ Creata da MisterAkko. }(*Basato su TaskMaster 2.6.2, 22-24 agosto 1996TaskMaster 3 gestisce finestre di testo per conto dell'utente.Revisione beta del 2/4/97. Introduce TMLogicalToPhysical e TMPhysicalToLogicalRevisione beta del 19/4/97. Pubblica TMDoUpdateStuff a beneficio di DialogLord 4.1TaskMaster 3.5 del 13 ago 97. Supporto di Appearance Supporto delle floating windows (solo con Mac OS 8) Introduce TMFrontWindow Introduce TMSelectWindow Introduce TMBeginDirectDraw Introduce TMEndDirectDraw Introduce una defproc per disegnare i controlli*)INTERFACEUSES { List 1 - always include these } Types, QuickDraw, { List 2 - only require List 1 types } Controls, Events, Files, TextEdit;CONST (* TaskMask equates *) tmMenuKey = $00000001; {Task Mask - Handle menu key events } tmUpdate = $00000002; {Task Mask - Handle update events } tmFindW = $00000004; {Task Mask - May call FindWindow } tmMenuSel = $00000008; {Task Mask - May call MenuSelect } tmOpenNDA = $00000010; {Task Mask - May call OpenNDA } tmSysClick = $00000020; {Task Mask - May call SysClick } tmDragW = $00000040; {Task Mask - May call DragWindow } tmContent = $00000080; {Task Mask - Activate inactive window on click in content Region } tmClose = $00000100; {Task Mask - May call TrackGoAway} tmZoom = $00000200; {Task Mask - May call TrackZoom} tmGrow = $00000400; {Task Mask - May call GrowWindow} tmScroll = $00000800; {Task Mask - Enable scrolling and activate window on click in scroll bar } tmSpecial = $00001000; {Task Mask - Handle events in Edit menu} tmCRedraw = $00002000; {Task Mask - redraw controls when necessary} tmInactive = $00004000; {Task Mask - Allow selection of inactive menu items} tmInfo = $00008000; {Task Mask - Don't activate inactive window on click in info bar } tmContentControls=$00020000; { TaskMask - Allow calling FindControl and TrackControl when FindWindow returns wInContent and window is already selected } tmControlKey = $00040000; { TaskMask - Passes keys to controls. } tmControlMenu= $00080000; { TaskMask - Passes menu events to popup menus in windows - NOT IMPLEMENTED } tmMultiClick = $00100000; { TaskMask - handles double, triple... clicks } tmIdleEvents = $00200000; { TaskMask - passes idle events to controls } tmAllowEditing = $20000000; { TaskMask - User may edit in TEHandle } tmDoDiskMount= $40000000; { TaskMask - may call DIBadMount } tmMultiFinder= $80000000; { TaskMask - May pass back suspend & resume pseudo-events } tmEverything = $FFFFFFFF; { TaskMast - do everything } (* TaskMaster return codes *) inNull = $0000; {TaskMaster codes - retained for back compatibility } nullEvt = inNull; inButtDwn = $0001; {TaskMaster codes - retained for back compatibility } inKey = $0003; {TaskMaster codes - retained for back compatibility } inUpdate = $0006; {TaskMaster codes - retained for back compatibility } wInDesk = $0010; {TaskMaster codes - On Desktop } wInMenuBar = $0011; {TaskMaster codes - On system menu bar } wClickCalled = $0012; {TaskMaster codes - system click called } wInContentRgn = $0013; {TaskMaster codes - in content Region } wInDragRgn = $0014; {TaskMaster codes - in drag Region } wInGrowRgn = $0015; {TaskMaster codes - in grow Region, active window only } wInGoAwayRgn = $0016; {TaskMaster codes - in go-away Region, active window only } wInZoom = $7FFC; {TaskMaster codes - in zoom Region, active window only } wInInfo = $0018; {TaskMaster codes - in information bar } wInSpecial = $0019; {TaskMaster codes - item id selected was 250 - 255 } wInDeskItem = $001A; {TaskMaster codes - item id selected was 1 - 249 } wInFrame = $001B; {TaskMaster codes - in frame, but not on anything else } wInactMenu = $001C; {TaskMaster codes - "selection" of inactive menu item } wClosedNDA = $001D; {TaskMaster codes - desk accessory closed } wCalledSysEdit = $001E; {TaskMaster codes - inactive menu item selected } wTrackZoom = $001F; {TaskMaster codes - tracked zoom Control} wHitFrame = $0020; {TaskMaster codes - window frame hit} wInControl = $0021; {TaskMaster codes - Button down in Control } wInControlMenu = $0022; {TaskMaster codes - Control-handled menu item } wTextEditChange = $7FFB; { TaskMaster codes - TextEdit handled the event. TaskData4 contains the window affected } wDiskMount = $7FFD; { TaskMaster codes - disk event handled } wMouseMoved = $7FFC; { mouseMovedMessage } wResume = $7FFE; {TaskMaster codes - Application is going foreground } wSuspend = $7FFF; {TaskMaster codes - Application is going background } wInSysWindow = $8000; {TaskMaster codes - hi bit set for system windows } { Window frame constants. } fGrow = $8000; { TaskMaster - draw grow box } fRScroll = $4000; { TaskMaster - draw a vertical scroll bar } fBScroll = $2000; { TaskMaster - draw a horizontal scroll bar } fInfoBar = $1000; { TaskMaster - window has in information bar } fContainsTextEdit = $0800; { TaskMaster - Insert a TEHandle in content } fIsWindoid = $0400; { TaskMaster - consider me a windoid } fIsVisible = $0001; { RESERVED FOR INTERNAL USE - latent windoid. It's currently invisible, because we are in the background. It must return visible } { Costanti predefinite per la prioritˆ dell'applicazione quando in foreground sui task in background. Usare high priority se l'applicazione CPU intensive e sfrutta gli idle time; usare middle prioprity se l'applicazione sfrutta in qualche modo gli idle time. Usare low priority se l'applicazione non sfrutta gli idle: TaskMaster otterrˆ il controllo solo quando c' un evento per la nostra applicazione. A proposito della scelta dei parametri numerici, si veda technote 188 } taskLowPriority = 50; taskMiddlePriority = 25; taskHighPriority = 0; { Number of refcons TaskMaster will handle for you } kNumOfRefCons = 4;TYPE {this defines the procedure pointer} TaskMasterDefProc = procedure (finestra: WindowPtr); wmTaskRec = PACKED RECORD CASE boolean OF false: (wmWhat: integer; wmMessage: longint; wmWhen: longint; wmWhere: Point; wmModifiers: integer; wmTaskData, {TaskMaster return data} wmTaskMask, {TaskMaster feature mask } wmTaskData2, wmTaskData3, wmTaskData4: longint; wmLastClickTick: longint; { Tick count of last click } wmClickCount: integer; { Click count (single, doubleÉ)} wmLastClickPt: Point; { point where click happened (global) } ); true: (EventRecord: EventRecord); END; wmTaskRecPtr = ^wmTaskRec; tmAuxRecordHandle = ^tmAuxRecordPtr; tmAuxRecordPtr = ^tmAuxRecord; tmAuxRecord = RECORD tmSignature: OSType; { sempre 'TskM'. Usato per distinguere le finestre di TM } wFrameBits: integer; { frame definition bits. Vedi le costanti relative } wRefCon: ARRAY [1..kNumOfRefCons] OF longint; { refCon per l'uso dell'applicazione } wXOrigin, { vertical offset of content region from data area. This is the horiz. value passed to SetOrigin. Set to 0 if not using the vertical scroll bar } wYOrigin, { horizontal offset of content region from data area } wDataH, { height of entire data area. If set to 0, window will take the whole desktop space. Set to 0 if not using the vertical scroll bar. } wDataW, { width of entire data area } wMaxH, { Maximum content height allowed when growing the window } wMaxW, { Maximum content width allowed when growing the window } wMinH, { Minimum content height } wMinW, { Minimum content width } wScrollVer, { Number of pixels to scroll the content region when the up or down scroll arrow are clicked. Used only if the vertical scroll bar is part of the window. Set to 0 otherwise. } wScrollHor, { Number of pixels to scroll horizontally for arrow clicks} wPageVer, { Number of pixels to scroll the content region when the up or down page region are clicked. Used only if the vertical scroll bar is part of the window. Set to 0 for a defaut value: current height of content region minus 10. } wPageHor, { Number of pixels to scroll horizontally for page clicks} wInfoHeight: integer; { Window information bar height in pixels } wControlsDefProc, { New for v3.5. Controls drawing procedure } wInfoDefProc, { Window information bar definition procedure } wContDefProc: TaskMasterDefProc; { Window contents definition procedure } { Fields below this point are the exclusive domain of Taskmaster, mustn't be manipulated by user and can be changed at any time } wHSBH, wVSBH: ControlHandle; { Handle for scrollbars } wInfoBarSpace: Rect; wContentSpace, wScrollBarsSpace: RgnHandle; wTextEdit: TEHandle; { New for v3,0 } END;{ Initialize TaskMaster routines and global data }PROCEDURE InitTaskMaster(standardPriority: integer);FUNCTION TaskMaster(taskMask: Integer; sleepRegion: RgnHandle; VAR taskRec: wmTaskRec): integer;{ Set - reset this task priority }PROCEDURE TaskPriority(newPriority: integer);FUNCTION GetPriority: integer;{ Window creation, definition, deletion }PROCEDURE TMNewWindow(theWindow: WindowPtr; FrameBits: integer; RefCon: longint; { This is the refCon number 1. Use TMSetWRefCon for the others } DataH, DataW, MaxH, MaxW, MinH, MinW, ScrollVer, ScrollHor, PageVer, PageHor, InfoHeight: integer; infoDefProc, contDefProc, ctlDefProc: TaskMasterDefProc);{ WARNING: questa procedura pu˜ di sua testa chiamate TMSizeWindow e ridimensionare lafinestra se le dimensioni attuali non sono comprese tra min e max }PROCEDURE TMDisposeWindow(theWindow: WindowPtr);{ Handling of refCon values. These procedures work on both TaskMaster and non-TaskMaster windows }PROCEDURE TMSetWRefCon(theWindow: WindowPtr; whichOne: Integer; theNewValue: longint);FUNCTION TMGetWRefCon(theWindow: WindowPtr; whichOne: Integer): longint;{ Handling of invalid region. For use with TaskMaster windows that have scrollbars }PROCEDURE TMInvalRect (r: Rect);PROCEDURE TMInvalRgn (r: RgnHandle);PROCEDURE TMSizeWindow (theWin: WindowPtr; newW, newH: Integer; dataOnly: Boolean); { Variante per la versione 3. Se dataOnly true, TaskMaster suppone che le dimensioni passate siano riferite allo spazio dati dentro la finestra. Per esempio, se io ho una finestra che mostra una icona di 32x32 pixel, ma la finestra ha una info bar alta 20 pixel, le due chiamate sono equivalenti: TMSizeWindow (win, 32, 32, TRUE) TMSizeWindow (win, 32, 32+20+3, FALSE) (*3 per le righe orizzontali, 20 per la info bar*) } PROCEDURE TMBeginDirectDraw (finestra: WindowPtr);PROCEDURE TMEndDirectDraw (finestra: WindowPtr);{ Se il programma deve proprio disegnare nella content region della finestrafuori dal ciclo di update, chiami queste procedure prima e dopo.PER RAGIONI DI VELOCITA, TM NON CONTROLLA CHE LA FINESTRA SIA UNA TMWINDOWE' RESPONSABILITA' DEL CHIAMANTE ACCERCARSENE }FUNCTION TMDoUpdateStuff(finestra: WindowPtr; myTaskMask: longint): boolean;{ Internal use - exported for usage inside modal dialog filters. Restituisce true se riuscito a trattare l'evento }PROCEDURE TMDoActivateStuff (activatedWindow: WindowPtr; myTaskMask: Longint; deactivate: Boolean);{ Internal use - exported for usage inside modal dialog filters. Pu˜ essere utilizzato safely per disattivare i dialog box che vanno in secondo piano quando esiste Appearance manager: in questo caso AppMgr gestisce la latenza dei controlli (abilitati e disabilitati resteranno tali quando il dialog box torna in primo piano). Chiamato in caso di activate, suspend e resume }PROCEDURE TMLogicalToPhysical (VAR p: Point);PROCEDURE TMPhysicalToLogical (VAR p: Point);{ Si comporta come LocalToGlobal. Trasforma una coordinata TaskMaster di un puntoall'interno della content region della finestra corrente nella coordinata "local",nel senso QuickTime. Per esempio, in una finestra che ha una info bar alta 97 punti,trasforma (10, 10) in (10, 110) (aggiungendo l'altezza della info bar e i tre pixeldelle linee di separazione) }{ handling of textedit windows - new for v3,0 }PROCEDURE TMLoadTextFromRes (theWin: WindowPtr; theResID: Integer);{ Carica testo da una coppia di risorse TEXT+styl dentro la finestra }PROCEDURE TMLoadTextFromFile (theWin: WindowPtr; fromWhere: FSSpec);{ Carica testo da un file stile SimpleText (tipo 'TEXT' con opzionalmenteuna risorsa 'styl' 128)dentro la finestra }PROCEDURE TMLoadText (theWin: WindowPtr; textHandle: Handle; stylInTheWindow: {StScrap}Handle);{ Ficca il contenuto delle due handle dentro la finestra. Entrambe possonolegittimamente essere NIL }PROCEDURE TEAppendTextRun (theWin: WindowPtr; theTextRun: Str255);{ AGGIUNGE la stringa data in calce al textedit }PROCEDURE TESetTextStyle (theWin: WindowPtr; whatToChange, theFont, theSize: Integer; theStyle: Style; theColor: RGBColor);{ CAMBIA lo stile della selezione. Per "whatToChange" usare le costantidefinite dentro TextEdit (doAll, doSizeÉ) }FUNCTION TEGetTextStyle (theWin: WindowPtr; VAR theFont, theSize: Integer; VAR theStyle: Style; VAR theColor: RGBColor): Boolean;{ RESTITUISCE lo stile della selezione. In caso di stile disomogeneo, ai parametri viene assegnato -1. [GOTCHA: tranne che per il colore...] In caso di fallimento (per esempio se la selezione nulla e non c' stile di default) restituisce FALSE, altrimenti restituisce TRUE }PROCEDURE TMSaveTextToRes (theWin: WindowPtr; theResID: Integer; theResName: Str255);{ Salva testo (e stile) delle finestra indicata nel file risorsecorrentemente aperto - l'ultimo della catena dei file }PROCEDURE TMSaveTextToFile (theWin: WindowPtr; where: FSSpec);{ Salva testo (e stile) in un file. Se il file specificato esiste,viene sovrascritto. Il file assume tipo e creatore di SimpleText }{ Le due procedure che seguono sono efficaci solo sotto Mac OS 8. Neglialtri casi si comportano come le chiamate del toolbox }FUNCTION TMFrontWindow: WindowPtr;{ Come FrontWindow, ma non considera le floating windows. }PROCEDURE TMSelectWindow (theWindow:WindowPtr);{ Come SelectWindow, ma lascia la finestra dietro alle floating window.Nel caso di finestra che viene creata, chiamare TMSelectWindow DOPO ShowWindow }IMPLEMENTATIONUSES Appearance, Devices, DiskInit, EPPC, FixMath, GestaltEqu, LowMem, Memory, Menus, MixedMode, OSUtils, Processes, Resources, Script, Windows, BinIO; { Per le routine che salvano il testo }CONST kAppleMenu = 128; kFirstNDA = 3; kEditMenu = 130; kUndo = 1; kCut = 3; kCopy = 4; kPaste = 5; kClear = 6; kTaskMasterSignature = 'TskM';VAR gNumberOfWindoids, { Se ci sono windoid, non posso fare affidamento sugli eventi activate del toolbox e devo generarmeli da me } gMyPriority: integer; { Current multitasking priority } gTMCanUseThemes: Boolean; { Can use Appearance Manager } thisWindData: tmAuxRecordHandle; { Global temporary storage for handle to data describing a window. Set by IsTMWindow } gScrollTextProc, gScrollBarProc: ControlActionUPP; { Global UPP for the scrollbar procs }{$S UtilMain}FUNCTION IsTMWindow(whichWindow: WindowPtr): boolean;{ Internal use. Takes a look and determines if this window has the auxiliary TaskMaster record. SIDE EFFECT: sets the global variable thisWindData to a copy of the handle to the window characteristics. }BEGIN IF whichWindow = NIL THEN IsTMWindow := FALSE ELSE BEGIN thisWindData := tmAuxRecordHandle(GetWRefCon(whichWindow)); { the check on the "oddness" of the refCon value is made so that we don't get a nasty bus error dereferencing something that is not an address. The short circuit boolean evaluation capability of Pascal is employed so that we only dereference the handle if the previous checks were successful } IsTMWindow := (Longint (thisWindData) > $100) & (Longint (thisWindData) = BSL (BSR(Longint(thisWindData), 2), 2)) & (Longint (thisWindData^) = BSL (BSR(Longint(thisWindData^), 2), 2)) & (thisWindData^^.tmSignature = kTaskMasterSignature); ENDEND;{$S UtilMain}PROCEDURE SendMyselfAnActivateEvent (theWindow: WindowPtr; activate: Boolean);VAR myEvent: EventRecord; err: OSErr; myself: ProcessSerialNumber;BEGIN IF WindowPeek (theWindow)^.visible THEN BEGIN myself.highLongOfPSN := 0; myself.lowlongOfPSN := kCurrentProcess; WITH myEvent DO BEGIN what := kHighLevelEvent; message := Longint (kTaskMasterSignature); { activate event } where := Point (Longint (theWindow)); END; err := PostHighLevelEvent (myEvent, @myself, ord (activate), { refcon field } NIL, 0, receiverIDisPSN) ENDEND;{$S UtilMain}PROCEDURE HandlePseudoActivateEvent (VAR e: wmTaskRec);{ La parte opposta del filo rispetto al precedente }VAR activateIt, dummyLength: Longint; myWindow: WindowPtr; myself: TargetID; err: OSErr;BEGIN WITH e DO BEGIN err := AcceptHighLevelEvent (myself, activateIt, NIL, dummyLength); myWindow := WindowPtr (wmWhere); { Modifica l'evento di modo che sembri al chiamante un evento activate TaskMaster } wmMessage := Longint (myWindow); wmTaskData := Longint (myWindow); wmTaskData2 := activateIt; wmModifiers := BOr (wmModifiers, wmTaskData2); { Gestiscilo internamente } TMDoActivateStuff (myWindow, wmTaskMask, activateIt=0); ENDEND;{$S UtilMain}PROCEDURE TMBeginDirectDraw (finestra: WindowPtr);{ Uso interno. Una volta era parte integrante di TMDoUpdateStuff. Poiho aggiunto la gestione di textEdit, e per questo motivo diventato necessariogestire il disegno nella content region anche fuori dalla gestione degli update.Per esempio, prima di chiamata TEClick o TEScroll. Quando necessario disegnarenella content region della finestra, chiamare prima questa procedura.Side effect garantito: lock di thisWindData}VAR paneRgn: RgnHandle; handleState: SignedByte; pt: Point;BEGIN pt := finestra^.portRect.topLeft; IF Longint (pt) <> 0 THEN debugStr ('Coordinate system set twice'); thisWindData := tmAuxRecordHandle (GetWRefCon(finestra)); handleState := HGetState (Handle (thisWindData)); HLock (Handle (thisWindData)); WITH thisWindData^^ DO BEGIN { Don't let the user draw over the info bar and the scroll bars } paneRgn := NewRgn; CloseRgn (paneRgn); CopyRgn (wContentSpace, paneRgn); { Non c' bisogno di offsettare anche per info bar - lavoriamo in coordinate locali } OffsetRgn (paneRgn, wXOrigin, wYOrigin); SetClip (paneRgn); DisposeRgn (paneRgn); { Set del sistema di coordinate } IF BAnd(wFrameBits, fInfoBar) = 0 THEN SetOrigin(wXOrigin, wYOrigin) ELSE SetOrigin(wXOrigin, wYOrigin-wInfoHeight-3); END; HSetState (Handle (thisWindData), handleState)END;{$S UtilMain}PROCEDURE TMEndDirectDraw (finestra: WindowPtr);{ Simmetrica alla precedente }BEGIN SetOrigin (0, 0); ClipRect (finestra^.portRect); { No clipping }END;{$S UtilMain}PROCEDURE TaskMasterDefProcForTextEdit (w: WindowPtr);{ defproc per le finestre che contengono spazio textedit nel content }BEGIN IF IsTMWindow (w) THEN BEGIN HLock (Handle (thisWindData)); WITH thisWindData^^ DO BEGIN EraseRgn (wContentSpace); TEUpdate (wContentSpace^^.rgnBBox, wTextEdit) END; HUnLock (Handle (thisWindData)); END;END;{$S UtilMain}PROCEDURE TrackTEPosn (theControl: ControlHandle; theHTE: TEHandle);{ Ensures that the scrollbar value matches the position of the text edit record.}VAR shouldBe: Integer; controlRect: rect; savedOrigin: Point; myPort: GrafPtr;BEGIN shouldBe := theHTE^^.viewRect.top - theHTE^^.destRect.top; if GetControlValue(theControl) <> shouldBe THEN BEGIN SetControlValue(theControl, shouldBe); { Ora devo invalidare il controlrect di modo che venga ridisegnato, e non banale, perchŽ non so se il chiamante abbia modificato l'origine del sistema di coordinate... } GetPort (myPort); savedOrigin.h := -myPort^.portRect.left; savedOrigin.v := -myPort^.portRect.top; SetOrigin (0, 0); controlRect := theControl^^.contrlRect; InvalRect (controlRect); SetOrigin (savedOrigin.h, savedOrigin.v); ENDEND;{$S UtilMain}PROCEDURE ScrollTEActionProc(control: ControlHandle; part: Integer);{ For scrolling TextEdit. Rivisto per fornire live scrolling sotto Mac OS 8 }VAR delta, initialValue: Integer; handleState: SignedByte;BEGIN handleState := HGetState (Handle (thisWindData)); HLock (Handle (thisWindData)); delta := 0; IF part = kControlIndicatorPart THEN { In questo caso il valore del control giˆ quel che dobbiamo raggiungere. Il vecchio valore quello che TextEdit memorizza ancora } initialValue := thisWindData^^.wTextEdit^^.viewRect.top - thisWindData^^.wTextEdit^^.destRect.top ELSE initialValue := GetControlValue(control); IF part <> 0 THEN BEGIN CASE part OF kControlUpButtonPart, kControlDownButtonPart : delta := 24; kControlPageUpPart, kControlPageDownPart : delta := control^^.contrlRect.bottom - control^^.contrlRect.top; kControlIndicatorPart: delta := GetControlValue(control)-initialValue; END; { case } IF (part = kControlUpButtonPart) OR (part = kControlPageUpPart) THEN delta := -delta; { reverse direction } IF delta <> 0 THEN SetControlValue(control, initialValue+delta); { Pinned within Min/Max automatically } { Ricalcolo il delta, per beneficiare del pinning } delta := GetControlValue(control)-initialValue; IF delta <> 0 THEN WITH thisWindData^^ DO BEGIN TMBeginDirectDraw (control^^.contrlOwner); IF control = thisWindData^^.wVSBH THEN TEScroll(0, -delta, wTextEdit) ELSE TEScroll(-delta, 0, wTextEdit); TMEndDirectDraw (control^^.contrlOwner); END; { if then with do } END; { if } HSetState (Handle (thisWindData), handleState)END; { ScrollVActionProc }{$S UtilMain}PROCEDURE SetScrollLimit;{ reset scrollbar so it is consistent with the TextEdit field (after modifying text). GOTCHA: thisWindData must be valid and locked }VAR newScroll: ControlHandle; theHTE: TEHandle; teLimit: Point; lineHeight, fontAscent, currentMax, currentValue: INTEGER; theStyle: TextStyle;BEGIN newScroll := thisWindData^^.wVSBH; theHTE := thisWindData^^.wTextEdit; currentMax := GetControlMaximum(newScroll); (* Scroll max should be position of bottom of bottom line when unscrolled This is equal to The position of the bottom line relative to current position + The amount currently scrolled - The height of the visible part *) teLimit := TEGetPoint(theHTE^^.teLength, theHTE); { Position of bottom relative to current posn } TEGetStyle(theHTE^^.teLength, theStyle, lineHeight, fontAscent,theHTE); teLimit.v := teLimit.v + lineHeight - fontAscent; { Add in for descent - TEGetPoint is posn of baseline not bottom of chars } { Also inform hi level code of new size } thisWindData^^.wDataW := (theHTE^^.viewRect.right - theHTE^^.viewRect.left); thisWindData^^.wDataH := teLimit.v; { Scrollbar handling } teLimit.v := teLimit.v + (theHTE^^.viewRect.top -theHTE^^.destRect.top) { Amount already scrolled } - (theHTE^^.viewRect.bottom - theHTE^^.viewRect.top); { Height of page } if teLimit.v < 0 THEN { Cannot be negative } teLimit.v := 0; if currentMax <> teLimit.v THEN BEGIN currentValue := GetControlValue(newScroll); if currentValue > teLimit.v THEN BEGIN TEScroll (0, teLimit.v - currentValue, theHTE); SetControlValue (newScroll, teLimit.v); END; SetControlMaximum (newScroll, teLimit.v); END; { Also check thumb position } TrackTEPosn (newScroll, theHTE);END;{$S UtilMain}PROCEDURE TaskPriority(newPriority: integer);BEGIN IF (newPriority > - 1) AND (newPriority < 601) THEN gMyPriority := newPriority ELSE gMyPriority := taskHighPriorityEND;{$S UtilMain}PROCEDURE MyScrollRect (w: WindowPtr; r: rect; dx, dy: Integer);{ Port settato, ThisWinData settato }VAR myUpdateRgn: RgnHandle;BEGIN { Trick to save time } IF (dx = dy) AND (dx = 0) THEN Exit (MyScrollRect); IF TMDoUpdateStuff (w, tmEverything) THEN BEGIN { Crea una regione vuota } myUpdateRgn := NewRgn; CloseRgn (myUpdateRgn); { Lo spazio dove si troveranno le scrollbar dopo lo scroll va ridisegnato, perchŽ le scrollbar spariscano } CopyRgn (thisWindData^^.wScrollBarsSpace, myUpdateRgn); OffsetRgn (myUpdateRgn, dx, dy); {PaintRgn (myUpdateRgn); { debug } InvalRgn (myUpdateRgn); { OK, non chiedetemi perchŽ questo vada qui e non sopra. So solo che cos“ funziona. E l'ho scoperto nel modo pi doloroso } IF BAnd (thisWindData^^.wFrameBits, fInfoBar) <> 0 THEN SetOrigin(0, -thisWindData^^.wInfoHeight-3); { Esegui lo scroll, e chiedi il ridisegno delle zone vuote che appaiono } ScrollRect(r,dx,dy,myUpdateRgn); {PaintRgn (myUpdateRgn); { debug } InvalRgn (myUpdateRgn); DisposeRgn (myUpdateRgn); SetOrigin (0, 0) END;END;{$S UtilMain}PROCEDURE TMAction(theControl: ControlHandle; partCode: integer);{ Action procedure for TaskMaster windows, when tmScroll is set (that is, we handle scrolling of content region) WARNING: this action procedure takes for granted that the global variable thisWindData contains a handle to the current window's TaskMaster specifics (it might access it via theControl^^.ctlOwner, but it would be a waste of time). It also supposes that the current GrafPort is the window GrafPort, as common for TaskMaster routines. }VAR newXOrigin, newYOrigin, scrollAmountH, scrollAmountV: integer; r: rect; handleState: SignedByte; FUNCTION CommonAction (VAR amount: INTEGER): integer;{ Clips the scrolling amount to a reasonable value. Gives back the new position }VAR max, currvalue, newValue: integer;BEGIN { Now clip the scrolling to the maximum allowed } currValue := GetControlValue (theControl); newValue := currValue + amount; IF newValue < 0 then newValue := 0; max := GetControlMaximum (theControl); IF newValue > max then newValue := max; SetControlValue (theControl, newValue); { Give back the actual amount of the scroll } amount := newValue - currValue; { Give back the absolute value of the control } CommonAction := newValueEND;BEGIN scrollAmountH := 0; scrollAmountV := 0; { The Common Action proc calls SetControlValue, which may move memory } handleState := HGetState (Handle (thisWindData)); HLock (Handle (thisWindData)); WITH thisWindData^^ DO BEGIN newXOrigin := wXOrigin; newYOrigin := wYOrigin; IF theControl = wHSBH THEN BEGIN case partCode of kControlUpButtonPart: scrollAmountH := -wScrollHor; kControlDownButtonPart: scrollAmountH := wScrollHor; kControlPageUpPart: if wPageHor > 0 THEN scrollAmountH := -wPageHor ELSE WITH wContentSpace^^.rgnBBox DO scrollAmountH := left - right + 10; kControlPageDownPart: if wPageHor > 0 THEN scrollAmountH := wPageHor ELSE WITH wContentSpace^^.rgnBBox DO scrollAmountH := right - left - 10; { otherwise don't do anything } END; { case } newXOrigin := CommonAction (scrollAmountH); END { horizontal scrolling } ELSE BEGIN case partCode of kControlUpButtonPart: scrollAmountV := -wScrollVer; kControlDownButtonPart: scrollAmountV := wScrollVer; kControlPageUpPart: if wPageVer > 0 THEN scrollAmountV := -wPageVer ELSE WITH wContentSpace^^.rgnBBox DO scrollAmountV := top - bottom + 10; kControlPageDownPart: if wPageVer > 0 THEN scrollAmountV := wPageVer ELSE WITH wContentSpace^^.rgnBBox DO scrollAmountV := bottom - top - 10; { otherwise don't do anything } END; { case } newYOrigin := CommonAction (scrollAmountV); END; { horizontal scrolling } { Now do the window content scrolling } r := wContentSpace^^.rgnBBox; { rect with the window contents } MyScrollRect (WindowPtr(theControl^^.contrlOwner), r, -scrollAmountH, -scrollAmountV); wXOrigin := newXOrigin; wYOrigin := newYOrigin; END; { with } HSetState (Handle (thisWindData), handleState)END;{$S UtilInit}PROCEDURE InitTaskMaster(standardPriority: integer);VAR gestaltResult: Longint;BEGIN TaskPriority(standardPriority); gScrollBarProc := NewControlActionProc (@TMAction); { Necessary to handle PowerPC } gScrollTextProc := NewControlActionProc (@ScrollTEActionProc); gTMCanUseThemes := (Gestalt (gestaltAppearanceAttr, gestaltResult) = noErr); gNumberOfWindoids := 0END;{$S UtilMain}FUNCTION GetPriority: integer;BEGIN GetPriority := gMyPriorityEND;{$S UtilMain}FUNCTION CalcScrollBarThickness (wFrameBits: Integer): Integer;{ scrollBarThickness normalmente 16; - standard Mac scrollbar Lo spazio occupato a video normalmente 16 - 1, because external pixel is superimposed with window edge }BEGIN IF gTMCanUseThemes AND (BAnd (wFrameBits, fIsWindoid) <> 0) THEN CalcScrollBarThickness := 11 { Dall'Appearance sample code } ELSE CalcScrollBarThickness := 16END;{$S UtilMain}Function CalcBottomSBZone (whose: WindowPtr; where: tmAuxRecordHandle): Rect;{ Ad uso di CalcZones e di quanti disegnano le scrollbar }VAR result: rect; scrollBarSpace: Integer;BEGIN WITH whose^, where^^ DO BEGIN scrollBarSpace := CalcScrollbarThickness (wFrameBits) - 1; IF BAnd(wFrameBits, fBScroll) = 0 THEN SetRect (result, 0 , 0, -1, -1) ELSE IF BAnd(wFrameBits, fGrow) = 0 THEN { SB should occupy all the space } SetRect (result, portRect.left - 1, portRect.bottom - scrollBarSpace, portRect.right + 1, portRect.bottom + 1) ELSE { SB should leave space for grow box } SetRect(result, portRect.left - 1, portRect.bottom - scrollBarSpace, portRect.right - scrollBarSpace + 1, portRect.bottom + 1) END; CalcBottomSBZone := resultEND;{$S UtilMain}Function CalcRightSBZone (whose: WindowPtr; where: tmAuxRecordHandle): Rect;{ Ad uso di CalcZones e di quanti disegnano le scrollbar }VAR result: rect; scrollBarSpace: Integer;BEGIN WITH whose^, where^^ DO BEGIN scrollBarSpace := CalcScrollBarThickness (wFrameBits) - 1; IF BAnd(wFrameBits, fRScroll) = 0 THEN SetRect (result, 0 , 0, -1, -1) ELSE BEGIN { Insert right scrollbar zone } result.left := portRect.right - scrollBarSpace; result.right := portRect.right + 1; IF BAnd(wFrameBits, fInfoBar) = 0 THEN result.top := -1 ELSE result.top := wInfoHeight + 2; IF BAnd(wFrameBits, fGrow) = 0 THEN result.bottom := portRect.bottom + 1 ELSE result.bottom := portRect.bottom - scrollBarSpace + 1 END END; CalcRightSBZone := resultEND;{$S UtilMain}FUNCTION CalcBSBMax (where: tmAuxRecordHandle): integer;var t: integer;{ Given a TM window, this function calculates a correct value for thebottom scrollbar's "max value" fieldSuch value is the data height in pixel minus the height of the window content regionin pixel.Use the content region, not the control, to calculate: thus, thisfunction can be used in creating the control itself }BEGIN WITH where^^ DO t := wDataW - wContentSpace^^.rgnBBox.right + wContentSpace^^.rgnBBox.left; if t <= 0 then CalcBSBMax := 0 {GetControlMinimum (where^^.wHSBH)} else CalcBSBMax := t;END;{$S UtilMain}FUNCTION CalcRSBMax (where: tmAuxRecordHandle): integer;{ Given a TM window, this function calculates a correct value for theright scrollbar's "max value" field.Such value is the data height in pixel minus the height of the window content regionin pixel.Use the content region, not the control, to calculate: thus, thisfunction can be used in creating the control itself }var t: integer;BEGIN WITH where^^ DO t := wDataH { Data height in pixel } - wContentSpace^^.rgnBBox.bottom + wContentSpace^^.rgnBBox.top; IF t <= 0 THEN CalcRSBMax := 0 {GetControlMinimum (where^^.wVSBH)} ELSE CalcRSBMax := tEND;{$S UtilMain}FUNCTION CalcTERect (theWindow: WindowPtr): Rect;{ Calcola lo spazio per TextEdit. Suppone che thisWindData sia settato e loccato }VAR workRect: Rect;BEGIN workRect := thisWindData^^.wContentSpace^^.rgnBBox; { Esclusi sempre il growbox } IF BAnd(thisWindData^^.wFrameBits, fGrow+fRScroll) = fGrow THEN { grow, but not right scrollbar } workRect.right := workrect.right - CalcScrollBarThickness (thisWindData^^.wFrameBits); InsetRect(workRect, 5, 1); CalcTERect := workRectEND;{$S UtilMain}PROCEDURE CalcZones(whose: WindowPtr; where: tmAuxRecordHandle);{ Internal use: keeps current the value of the private fields }VAR tempRgn: RgnHandle; handleState: SignedByte; bottomOfContent, rightOfContent: Integer;BEGIN handleState := HGetState (Handle(where)); HLock(Handle(where)); { Manipulating regions can move memory around, so... } WITH whose^, where^^ DO BEGIN IF gTMCanUseThemes THEN SetRect (wInfoBarSpace, 0, 0, portRect.right, wInfoHeight + 2) { Appearance: Niente double line } ELSE SetRect(wInfoBarSpace, 0, 0, portRect.right, wInfoHeight - 1); bottomOfContent := portRect.bottom; IF BAnd(wFrameBits, fInfoBar) <> 0 THEN { remove info bar zone } bottomOfContent := bottomOfContent - wInfoHeight - 3; IF BAnd(wFrameBits, fBScroll) <> 0 THEN { remove bottom scrollbar zone } bottomOfContent := bottomOfContent - 15; rightOfContent := portRect.right; IF BAnd(wFrameBits, fRScroll) <> 0 THEN { remove right scrollbar zone } rightOfContent := rightOfContent - 15; SetRectRgn(wContentSpace, 0, 0, rightOfContent, bottomOfContent); SetEmptyRgn(wScrollBarsSpace); tempRgn := NewRgn; CloseRgn (tempRgn); IF BAnd(wFrameBits, fBScroll) <> 0 THEN { Calculate the space for the bottom scroll bar, if any } RectRgn (wScrollBarsSpace, CalcBottomSBZone (whose, where)); IF BAnd(wFrameBits, fRScroll) <> 0 THEN BEGIN { Add right side scroll bar, if any } RectRgn (tempRgn, CalcRightSBZone (whose, where)); UnionRgn(wScrollBarsSpace, tempRgn, wScrollBarsSpace); END; { Add grow box space } IF BAnd(wFrameBits, fGrow) <> 0 THEN BEGIN { Add grow box zone } SetRectRgn(tempRgn, portRect.right - CalcScrollbarThickness (wFrameBits) + 1, portRect.bottom - CalcScrollbarThickness (wFrameBits) + 1, portRect.right, portRect.bottom); UnionRgn(wScrollBarsSpace, tempRgn, wScrollBarsSpace) END; { Now calculate correct content region subtracting scrollbar space } DiffRgn(wContentSpace, wScrollBarsSpace, wContentSpace); DisposeRgn(tempRgn) END; { with } { Unlock handle only if unlocked at start } HSetState (Handle (where), handleState);END;{$S UtilMain}PROCEDURE ResizeNShowSB (theWin: WindowPtr);{ The window was zoomed or grown. If there are scrollbars, handle them }{ Se l'utente ha scrollato sino in fondo, e poi ingrandisce la finestra versoil basso, necessario resettare wXOrigin e wYOrigin di modo che non venga mostratoci˜ che si trova "dopo la fine"}CONST {kControlInvisible is used to 'turn off' controls (i.e., cause the control not to be redrawn as a result of some Control Manager call such as SetControlValue) by being put into the contrlVis field of the record. kControlVisible is used the same way to 'turn on' the control.} kControlInvisible = 0; kControlVisible = $FF;VAR scrollbarSpace, teSpace: Rect; newWidth, newHeight: Integer;BEGIN { MoveControl may move or purge memory, soÉÊ} HLock (Handle (thisWindData)); { Calcola nuove dimensioni finestra } WITH theWin^.portRect DO BEGIN newWidth := right - left; newHeight := bottom - top; END; WITH thisWindData^^ DO BEGIN { Redraw area of former scroll bars } InvalRgn (wScrollBarsSpace); { Must be done when thisWindData is locked } { Also redraw area of former info bar - required by appearance } InvalRect (wInfoBarSpace); { Make record fields up-to-date } CalcZones (theWin, thisWindData); { Move scroll bars to the new position } IF BAnd(wFrameBits, fRScroll) <> 0 THEN BEGIN scrollbarSpace := CalcRightSBZone (theWin, thisWindData); wVSBH^^.contrlVis := kControlInvisible; { See sample code TESample } MoveControl (wVSBH, scrollbarSpace.left, scrollbarSpace.top); SizeControl (wVSBH, CalcScrollBarThickness (wFrameBits), scrollbarSpace.bottom-scrollbarSpace.top); { We must change the max value, so that we don't scroll past the data end } SetControlMaximum (wVSBH, CalcRSBMax (thisWindData)); wVSBH^^.contrlVis := kControlVisible; { Check growth beyond lower bound } IF newHeight + wYOrigin > wDataH THEN BEGIN wYOrigin := wDataH - newHeight; IF wYOrigin < 0 THEN wYOrigin := 0; { Non dovrebbe servire, maÉÊ} InvalRgn (wContentSpace); END; END; { if it has a right scrollbar } IF BAnd(wFrameBits, fBScroll) <> 0 THEN BEGIN scrollbarSpace := CalcBottomSBZone (theWin, thisWindData); wHSBH^^.contrlVis := kControlInvisible; MoveControl (wHSBH, scrollbarSpace.left, scrollbarSpace.top); SizeControl (wHSBH, scrollbarSpace.right-scrollbarSpace.left, CalcScrollBarThickness (wFrameBits)); SetControlMaximum (wHSBH, CalcBSBMax (thisWindData)); wHSBH^^.contrlVis := kControlVisible; { Check growth beyond rightmost bound } IF newWidth + wXOrigin > wDataw THEN BEGIN wXOrigin := wDataw - newWidth; IF wXOrigin < 0 THEN wXOrigin := 0; { Non dovrebbe servire, maÉÊ} InvalRgn (wContentSpace); END; END; { control move } { Reset TextEdit rect, if any - new for v3.0 } IF BAnd(wFrameBits, fContainsTextEdit) <> 0 THEN BEGIN teSpace := CalcTERect (theWin); wTextEdit^^.viewRect := teSpace; wTextEdit^^.destRect := teSpace; TECalText (wTextEdit); { Il rect cambiato = la lunghezza dei dati cambiata = ci vuole SetScrollLimit } TMBeginDirectDraw (theWin); SetScrollLimit; InvalRect (teSpace); { Equivale a TMInvalrect chiamato da fuori TMBeginDirectDraw } TMEndDirectDraw (theWin); { Redraw } END ELSE { Just have the newly moved scrollbars reappear } InvalRgn (wScrollBarsSpace); { Must be done when thisWindData is locked } END; { with } HUnlock (Handle (thisWindData));END;(************* For DoGrow and DoZoom ***************){$S UtilMain}FUNCTION CalcMaxScreenWidth(dataOnly: Boolean): integer;{ calculate maximum real screen size for the window whose data is in thisWindData.}VAR result: integer;BEGIN WITH thisWindData^^ do begin IF dataOnly THEN result := wDataW ELSE result := wMaxW; IF BAnd(wFrameBits, fRScroll) <> 0 THEN CalcMaxScreenWidth := result + CalcScrollBarThickness (wFrameBits) - 1 ELSE CalcMaxScreenWidth := result END { with }END;{$S UtilMain}FUNCTION CalcMaxScreenHeight (dataOnly: Boolean): integer;{ calculate maximum real screen size for the window whose data is in thisWindData.If "dataOnly" is true, consider only the data currently inside the window,and not the maximum allowable growth }VAR result: integer;BEGIN WITH thisWindData^^ do begin IF dataOnly THEN result := wDataH ELSE result := wMaxH; IF BAnd(wFrameBits, fBScroll) <> 0 THEN result := result + CalcScrollBarThickness (wFrameBits) - 1; IF BAnd(wFrameBits, fInfoBar) <> 0 THEN result := result + 3 + wInfoHeight; CalcMaxScreenHeight := result ENDEND;{$S UtilMain}FUNCTION CalcMinScreenWidth: integer;{ calculate minimum real screen size for window. }VAR result: integer;BEGIN result := thisWindData^^.wMinW; IF BAnd(thisWindData^^.wFrameBits, fRScroll) <> 0 THEN result := result + CalcScrollBarThickness (thisWindData^^.wFrameBits) - 1; { Add space for bottom scrollbar } CalcMinScreenWidth := resultEND;{$S UtilMain}FUNCTION CalcMinScreenHeight: integer;{ calculate minimum real screen size for window. }VAR result: integer;BEGIN result := thisWindData^^.wMinH; IF result > 0 THEN BEGIN { Se la finestra deve sempre mostrare un po' di content, allora l'altezza minima tiene in conto anche i tre pixel della barra di separazione orizzontale tra info bar e content } IF BAnd(thisWindData^^.wFrameBits, fInfoBar) <> 0 THEN result := result + thisWindData^^.wInfoHeight + 3 END ELSE IF BAnd(thisWindData^^.wFrameBits, fInfoBar) <> 0 THEN result := result + thisWindData^^.wInfoHeight; IF BAnd(thisWindData^^.wFrameBits, fBScroll) <> 0 THEN result := result + CalcScrollBarThickness (thisWindData^^.wFrameBits) - 1; { Add space for bottom scrollbar } CalcMinScreenHeight := resultEND;{$S UtilMain}PROCEDURE TMDrawGrowIcon (theWindow: windowPtr; wFrameBits: Integer);{ The window manager's DrawGrowIcon call also draws a frame for two scrollbars.This is unseemely in quite a few cases: among those the existance of an info bar.So we clip off those extra lines, to get only the grow box.GOTCHA: this procedure requires that the current port is set to the window }VAR hostClip: RgnHandle; scrollBarSpace: Integer;BEGIN IF NOT gTMCanUseThemes THEN BEGIN { Se c' appearance mgr ci pensa lui } hostClip := NewRgn; CloseRgn (hostClip); GetClip(hostClip); scrollBarSpace := CalcScrollbarThickness (wFrameBits) - 1; WITH theWindow^.portRect DO SetRectRgn (theWindow^.clipRgn, right - scrollBarSpace, bottom - scrollBarSpace, right, bottom); DrawGrowIcon (theWindow); SetClip (hostClip); DisposeRgn (hostClip) END;END;(***************** End slave routines ************){$S UtilMain}FUNCTION TMDoUpdateStuff(finestra: WindowPtr; myTaskMask: longint): boolean;{ Restituisce true se riuscito a trattare l'evento }VAR portOspite: GrafPtr; { Host port for saving, just in case } err: OSErr; paneRect: Rect; { portRect of my panes (infobar, contentspace) while drawing }BEGIN IF IsTMWindow(finestra) THEN BEGIN GetPort (portOspite); SetPort (finestra); HLock(Handle(thisWindData)); { BeginUpdate may move memory } WITH thisWindData^^ DO BEGIN { We are supposing there's no need to call CalcZones here } { If there's a grow region, do it } IF BAnd(wFrameBits, fGrow) <> 0 THEN TMDrawGrowIcon(finestra, wFrameBits); BeginUpdate(finestra); { Call the user procedures to do their part } { Draw information bar, if any } IF wInfoDefProc <> NIL THEN BEGIN ClipRect (finestra^.portRect); { No clipping } IF gTMCanUseThemes THEN err := DrawThemeWindowHeader (wInfoBarSpace, ord(WindowPeek(finestra)^.hilited=TRUE)) { cos“ son certo di passare solo 0 o 1 - hilited pu˜ valere altro } ELSE BEGIN { Disegna la doppia linea che separa info bar da content region } PenNormal; ForeColor (blackColor); MoveTo (0, wInfoHeight); LineTo (wInfoBarSpace.right, wInfoHeight); END; MoveTo (0, wInfoHeight + 2); LineTo (wInfoBarSpace.right, wInfoHeight + 2); { Disegna la info bar usando la user proc } SetRect (paneRect, 0, 0, wInfoBarSpace.right, wInfoHeight); ClipRect(paneRect); wInfoDefProc (finestra); ClipRect (finestra^.portRect); { No clipping } END; { Se abbiamo chiamato BeginUpdate, posso usare UpdateControls per uno update pi veloce di quello consentito da DrawControls. Devo farlo ora, perchŽ altrimenti i controlli nella info bar potrebbero venire sovrascritti dal blocco precedente se lo facessi prima } IF (BAnd(myTaskMask, tmCRedraw) <> 0) AND (wControlsDefProc = NIL) THEN BEGIN PenNormal; UpdateControls (finestra, finestra^.visRgn); END; { Draw content using content procedure, if any } IF wContDefProc <> NIL THEN BEGIN TMBeginDirectDraw (finestra); wContDefProc (finestra); IF wControlsDefProc <> NIL THEN wControlsDefProc (finestra); { New for v3.5 } TMEndDirectDraw (finestra) END; { Do some housekeeping and give back a result code } EndUpdate(finestra); TMDoUpdateStuff := true; END; { with } HUnlock(Handle(thisWindData)); { BeginUpdate may move memory } SetPort (portOspite) END { if it is a TaskMaster window } ELSE TMDoUpdateStuff := falseEND; { proc }{$S UtilMain}PROCEDURE TMInvalRect (r: Rect);VAR invalWhat: GrafPtr;BEGIN GetPort (invalWhat); IF IsTMWindow (invalWhat) THEN WITH thisWindData^^ DO BEGIN OffsetRect (r, -wXOrigin, -wYOrigin); { E c' anche la info bar! -- bug fix 3.0 } IF BAnd(wFrameBits, fInfoBar) <> 0 THEN OffsetRect (r, 0, 3 + wInfoHeight); END; InvalRect (r);END;{$S UtilMain}PROCEDURE TMInvalRgn (r: RgnHandle);VAR invalWhat: GrafPtr;BEGIN GetPort (invalWhat); IF IsTMWindow (invalWhat) THEN WITH thisWindData^^ DO BEGIN OffsetRgn (r, -wXOrigin, -wYOrigin); { E c' anche la info bar! -- bug fix 3.0 } IF BAnd(wFrameBits, fInfoBar) <> 0 THEN OffsetRgn (r, 0, 3 + wInfoHeight); END; InvalRgn (r);END;{$S UtilMain}PROCEDURE TMLogicalToPhysical (VAR p: Point);VAR invalWhat: GrafPtr;BEGIN GetPort (invalWhat); IF IsTMWindow (invalWhat) THEN WITH thisWindData^^, p DO BEGIN h := h - wXOrigin; v := v - wYOrigin; IF BAnd(wFrameBits, fInfoBar) <> 0 THEN v := v + 3 + wInfoHeight; END;END;{$S UtilMain}PROCEDURE TMPhysicalToLogical (VAR p: Point);VAR invalWhat: GrafPtr;BEGIN GetPort (invalWhat); IF IsTMWindow (invalWhat) THEN WITH thisWindData^^, p DO BEGIN h := h + wXOrigin; v := v + wYOrigin; IF BAnd(wFrameBits, fInfoBar) <> 0 THEN v := v - 3 - wInfoHeight; END;END;{$S UtilMain}FUNCTION TMFrontWindow: WindowPtr;VAR result: WindowPtr; BEGIN result := FrontWindow; IF gTMCanUseThemes THEN BEGIN WHILE (result <> NIL) & IsTMWindow (result) & (BAnd(thisWindData^^.wFrameBits, fIsWindoid) <> 0) DO { é un windoid, trascuralo } result := WindowPtr (WindowPeek(result)^.nextWindow) END; TMFrontWindow := resultEND;{$S UtilMain}FUNCTION AllWindowsLoop (callMeWithVisibleWindoids, callMeWithInvisibleWindoids, callMeWithTheFirstWindow, callMeWithOtherWindows: TaskMasterdefProc): WindowPtr;{ Uso interno. Passa in rassegna tutte le finestre, le riordina, e strada facendochiama procedure di callback a uso del chiamante.Restituisce l'ultimo windoid, oppure NIL se non ci sono windoid.Usato da TMSelectWindow e da SuspendOrResumeTasks.Garantisce che thisWindData sia settato correttamente SOLO per callMeWithWindoids }TYPE TWindowInfoPtr = ^TWindowInfo; TWindowInfo = RECORD aWindow: WindowPtr; nextInfo: TWindowInfoPtr END;VAR rootInfoWindows, loopInfoWindows: TWindowInfoPtr; windowsLoop, firstWindow, lastWindoid, nextOne: WindowPtr; peek: WindowPeek; windoidIsVisible: Boolean;BEGIN windowsLoop := LMGetWindowList; rootInfoWindows := NIL; WHILE windowsLoop <> NIL DO BEGIN peek := WindowPeek (windowsLoop); IF rootInfoWindows = NIL THEN BEGIN rootInfoWindows := TWindowInfoPtr (NewPtr (SizeOf (TWindowInfo))); rootInfoWindows^.aWindow := windowsLoop; rootInfoWindows^.nextInfo := NIL; loopInfoWindows := rootInfoWindows END ELSE BEGIN loopInfoWindows^.nextInfo := TWindowInfoPtr (NewPtr (SizeOf (TWindowInfo))); loopInfoWindows := loopInfoWindows^.nextInfo; loopInfoWindows^.aWindow := windowsLoop; loopInfoWindows^.nextInfo := NIL; END; windowsLoop := WindowPtr (WindowPeek (windowsLoop)^.nextWindow); END; firstWindow := NIL; lastWindoid := NIL; nextOne := NIL; loopInfoWindows := rootInfoWindows; WHILE loopInfoWindows <> NIL DO BEGIN windowsLoop := loopInfoWindows^.aWindow; IF IsTMWindow (windowsLoop) & (BAnd(thisWindData^^.wFrameBits, fIsWindoid) <> 0) THEN BEGIN { é un windoid } windoidIsVisible := WindowPeek (windowsLoop)^.visible; { Dagli la possibilitˆ di diventare visibile PRIMA dei test } IF NOT windoidIsVisible THEN callMeWithInvisibleWindoids (windowsLoop); { Se ho giˆ trovato una finestra normale prima di questo windoid, sono guai: le finestre devono sempre stare sotto ai windoid! } IF (firstWindow <> NIL) AND WindowPeek (windowsLoop)^.visible THEN BEGIN { Sposto questo windoid al posto giusto } IF lastWindoid = NIL THEN SelectWindow (windowsLoop) { Mettilo al primo posto } ELSE SendBehind (windowsLoop, lastWindoid); END; { Giˆ che ci sei, assicurati che i windoid visibili siano hilited } IF NOT WindowPeek (windowsLoop)^.hilited AND WindowPeek (windowsLoop)^.visible THEN HiliteWindow (windowsLoop, TRUE); { Infine, dagli la possibilitˆ di diventare invisibile se questo che vuole il caller } IF windoidIsVisible THEN callMeWithVisibleWindoids (windowsLoop); { Tieni traccia di quale sia ora l'ultimo windoid della catena } IF WindowPeek (windowsLoop)^.visible THEN lastWindoid := windowsLoop; END ELSE BEGIN { é una window } IF firstWindow = NIL THEN BEGIN { Qui non so se debba essere hilited o no: normalmente lo sarˆ, ma se siamo in background la finestra dev'essere disattiva. Che ci pensi il mio chiamante. } firstWindow := windowsLoop; callMeWithTheFirstWindow (firstWindow); END ELSE BEGIN { Giˆ che ci sei, assicurati che le finestre oltre la prima non siano hilited } IF WindowPeek (windowsLoop)^.hilited AND WindowPeek (windowsLoop)^.visible THEN HiliteWindow (windowsLoop, FALSE); { Chiama il callback } callMeWithOtherWindows (windowsLoop) END; END; loopInfoWindows := loopInfoWindows^.nextInfo END; AllWindowsLoop := lastWindoid; WHILE rootInfoWindows <> NIL DO BEGIN loopInfoWindows := rootInfoWindows^.nextInfo; DisposePtr (Ptr (rootInfoWindows)); rootInfoWindows := loopInfoWindows END;END;{$S UtilMain}PROCEDURE CallbackDoNothing (theWin: WindowPtr);{ Callback per AllWindowsLoop che non fa nulla }BEGIN {$UNUSED theWin}END;{$S UtilMain}PROCEDURE CallbackGiveIdle (theWin: WindowPtr);{ Callback per AllWindowsLoop che passa idle alla finestra indicata }BEGIN IF gTMCanUseThemes THEN IdleControls (theWin);END;{$S UtilMain}PROCEDURE CallbackGiveIdleIncludingTextEdit (theWin: WindowPtr);{ Callback per AllWindowsLoop che passa idle alla finestra indicata }VAR theMouse: Point;BEGIN IF WindowPeek (theWin)^.visible THEN BEGIN IF NOT WindowPeek (theWin)^.hilited THEN HiliteWindow (theWin, TRUE); IF IsTMWindow (theWin) THEN WITH thisWindData^^ DO BEGIN HLock (Handle(thisWindData)); IF gTMCanUseThemes THEN IdleControls (theWin); IF BAnd(wFrameBits, fContainsTextEdit) <> 0 THEN BEGIN SetPort (theWin); TMBeginDirectDraw (theWin); TEIdle (wTextEdit); { Cursore } GetMouse (theMouse); IF PtInRgn (theMouse, wContentSpace) THEN SetCursor(GetCursor(iBeamCursor)^^) ELSE SetCursor(qd.arrow); { GOTCHA - se l'utente aveva customizzatoÉÊ} TMEndDirectDraw (theWin) END; HUnLock (Handle (thisWindData)); END ENDEND;{$S UtilMain}PROCEDURE CallbackHideWindoid (theWin: WindowPtr);{ Callback per AllWindowsLoop che nasconde un windoid (suspend) }BEGIN { Se il windoid era visibileÉÊ} IF WindowPeek (theWin)^.visible THEN BEGIN { Étieni nota del fatto che lo stiamo nascondendo noi (diventa latente) e non l'applicativo cliente } thisWindData^^.wFrameBits := BOr (thisWindData^^.wFrameBits, fIsVisible); HideWindow (theWin); END;END;{$S UtilMain}PROCEDURE CallbackShowWindoid (theWin: WindowPtr);{ Callback per AllWindowsLoop che mostra un windoid (resume) }BEGIN { Se latente, e cio se l'abbiamo nascosto noi (al suspend) e non l'applicativo cliente (per i cazzi suoi)ÉÊ} IF NOT WindowPeek (theWin)^.visible AND (BAnd(thisWindData^^.wFrameBits, fIsVisible) <> 0) THEN BEGIN { Ésegnati che non pi latenteÉÊ} thisWindData^^.wFrameBits := BAnd (thisWindData^^.wFrameBits, BNot(fIsVisible)); { Ée fallo apparire. } ShowWindow (theWin); ENDEND;{$S UtilMain}PROCEDURE CallbackHiliteWindow (theWin: WindowPtr);{ Callback per AllWindowsLoop che seleziona la finestra }BEGIN IF WindowPeek (theWin)^.visible AND NOT WindowPeek (theWin)^.hilited THEN HiliteWindow (theWin, TRUE);END;{$S UtilMain}PROCEDURE CallbackUnhiliteWindow (theWin: WindowPtr);{ Callback per AllWindowsLoop che deseleziona la finestra }BEGIN IF WindowPeek (theWin)^.hilited THEN HiliteWindow (theWin, FALSE);END;{$S UtilMain}PROCEDURE TMSelectWindow (theWindow: WindowPtr);VAR lastWindoid, oldFirstWindow: WindowPtr;BEGIN IF gNumberOfWindoids > 0 THEN BEGIN oldFirstWindow := TMFrontWindow; lastWindoid := AllWindowsLoop (CallbackDoNothing, CallbackDoNothing, CallbackUnhiliteWindow, CallbackDoNothing); { Se ci sono windoid, metti la nostra finestra subito dopo il primo di essi } IF (lastWindoid <> theWindow) AND (lastWindoid <> NIL) THEN SendBehind (theWindow, lastWindoid); { Attiva la nostra finestra se del caso } IF NOT WindowPeek (theWindow)^.hilited THEN HiliteWindow (theWindow, TRUE); { Gli eventi activate devono venire trascurati, perchŽ altrimenti mi incasinano i windoid. Dunque, devo gestire io la attivazione della finestra } IF (oldFirstWindow <> theWindow) THEN { Invia uno pseudo-evento deactivate alla vecchia finestra di primo piano } SendMyselfAnActivateEvent (oldFirstWindow, FALSE); { Invia uno pseudo-evento activate alla mia finestra } SendMyselfAnActivateEvent (theWindow, TRUE); END ELSE SelectWindow (theWindow)END;{$S UtilMain}PROCEDURE SuspendOrResumeVisualTasks (resume: Boolean);VAR lastWindoid, firstWindow: WindowPtr;BEGIN IF resume THEN lastWindoid := AllWindowsLoop (CallbackDoNothing, CallbackShowWindoid, CallbackHiliteWindow, CallbackDoNothing) ELSE lastWindoid := AllWindowsLoop (CallbackHideWindoid, CallbackDoNothing, CallbackUnhiliteWindow, CallbackDoNothing); firstWindow := TMFrontWindow; IF firstWindow <> NIL THEN TMDoActivateStuff (firstWindow, tmEverything, NOT resume);END;{$S UtilMain}PROCEDURE TMSizeWindow (theWin: WindowPtr; newW, newH: Integer; dataOnly: Boolean);VAR oldPort: GrafPtr; scrollBarSpace: Integer; requiredMinW, requiredMaxW, requiredMinH, requiredMaxH: Integer;BEGIN IF IsTMWindow (theWin) THEN WITH thisWindData^^ DO BEGIN { Gestione delle dimensioni "logiche", relative alla sola parte dati } IF dataOnly THEN BEGIN scrollBarSpace := CalcScrollBarThickness (wFrameBits) - 1; IF BAnd(wFrameBits, fRScroll) <> 0 THEN newW := newW + scrollBarSpace; IF BAnd(wFrameBits, fBScroll) <> 0 THEN newH := newH + scrollBarSpace; IF BAnd(wFrameBits, fInfoBar) <> 0 THEN newH := newH + 3 + wInfoHeight; END; { data only } { Gestione delle dimensioni min-max garantite } requiredMinW := CalcMinScreenWidth; requiredMaxW := CalcMaxScreenWidth (FALSE); requiredMinH := CalcMinScreenHeight; requiredMaxH := CalcMaxScreenHeight (FALSE); IF newW < requiredMinW THEN newW := requiredMinW ELSE IF newW > requiredMaxW THEN newW := requiredMaxW; IF newH < requiredMinH THEN newH := requiredMinH ELSE IF newH > requiredMaxH THEN newH := requiredMaxH; END; { with } { Esecuzione } SizeWindow (theWin, newW, newH, TRUE); { If we are handling scrollbars, move and then draw them immediately } IF IsTMWindow (theWin) THEN BEGIN GetPort (oldPort); SetPort (theWin); ResizeNShowSB (theWin); SetPort (oldPort) ENDEND;{$S UtilMain}PROCEDURE DoWZoom(theWindow: WindowPtr; zoomDir: integer);{ From snippet DTS code. Modified so that the window will take only asmuch space as needed to show all contents. Am I not a nice guy? }VAR globalPortRect, theSect, zoomRect: Rect; nthDevice, dominantGDevice: GDHandle; sectArea, greatestArea: longint; bias, minX, minY: integer; sectFlag, fixClip: boolean; iWasBehindThisOne, windowsLoop: WindowPtr; { ZoomWindow mi mette in primo piano. Ma io non voglio }BEGIN fixClip := FALSE; { Se la finestra sta rimpicciolendo e non c'e un grow box, accertati che assuma le dimensioni minime fissate dall'utente } IF (zoomDir = inZoomIn) & IsTMWindow (theWindow) & (BAnd(thisWindData^^.wFrameBits, fGrow) = 0) THEN BEGIN zoomRect := WStateDataHandle(WindowPeek(theWindow)^.dataHandle)^^.userState; minX := CalcMinScreenWidth; { Bug fix 3.0 - it used to forfeit the info bar } minY := CalcMinScreenHeight; WITH zoomRect DO BEGIN IF (right - left) < minX THEN right := left + minX; IF (bottom - top) < minY THEN bottom := top + minY; END; WStateDataHandle(WindowPeek(theWindow)^.dataHandle)^^.userState := zoomRect; fixClip := TRUE; END; { If there is the possibility of multiple gDevices, then we } { must check them to make sure we are zooming onto the right } { display device when zooming out. } IF zoomDir = inZoomOut THEN BEGIN { window's portRect must be converted to global coordinates } globalPortRect := theWindow^.portRect; LocalToGlobal(globalPortRect.topLeft); LocalToGlobal(globalPortRect.botRight); { must calculate height of window's title bar } bias := globalPortRect.top - 1 - WindowPeek(theWindow)^.strucRgn^^.rgnBBox.top; nthDevice := GetDeviceList; greatestArea := 0; { This loop checks the window against all the gdRects in the } { gDevice list and remembers which gdRect contains the largest } { portion of the window being zoomed. } WHILE nthDevice <> NIL DO BEGIN sectFlag := SectRect(globalPortRect, nthDevice^^.gdRect, theSect); WITH theSect DO sectArea := longint(right - left) * (bottom - top); IF sectArea > greatestArea THEN BEGIN greatestArea := sectArea; dominantGDevice := nthDevice; END; nthDevice := GetNextDevice(nthDevice); END; {of WHILE} { We must create a zoom rectangle manually in this case. } { account for menu bar height as well, if on main device } IF dominantGDevice = GetMainDevice THEN bias := bias + GetMBarHeight; WITH dominantGDevice^^.gdRect DO SetRect(zoomRect, left + 3, top + bias + 3, right - 3, bottom - 3); { OK this way for non-TM windows. NowÉ } IF IsTMWindow(theWindow) THEN BEGIN { La finestra zoomata starˆ per intero sullo schermo se non la sposto? } globalPortRect.right := globalPortRect.left + CalcMaxScreenWidth(TRUE); globalPortRect.bottom := globalPortRect.top + CalcMaxScreenHeight(TRUE); IF PtInRect (globalPortRect.botRight, dominantGDevice^^.gdRect) THEN { Si, allora lascia la finestra dov' } zoomRect := globalPortRect ELSE WITH zoomrect DO BEGIN { No, it won't fit. Use the zoomrect calculated via SetRect before } { BUT if window content is smaller than full screen, make window smaller, AND keep it positioned at the upper left corner of screen, just like the Finder 7.0 does! } right := left + CalcMaxScreenWidth(TRUE); IF right > dominantGDevice^^.gdRect.right THEN right := dominantGDevice^^.gdRect.right-3; bottom := top + CalcMaxScreenHeight(TRUE); IF bottom > dominantGDevice^^.gdRect.bottom THEN bottom := dominantGDevice^^.gdRect.bottom-3; END; { ramo ELSE } WITH thisWindData^^ DO BEGIN { Reset the coordinates, so that we show full contents } wXOrigin := 0; wYOrigin := 0 END; END; { if is TM Window } { Set up the WStateData record for this window. } fixClip := TRUE; WStateDataHandle(WindowPeek(theWindow)^.dataHandle)^^.stdState := zoomRect; END; {of Color QuickDraw conditional stuff} { New for v3.5, e necessario per i windoid. Trovo la mia posizione nella windows list } iWasBehindThisOne := NIL; windowsLoop := LMGetWindowList; REPEAT IF WindowPeek (windowsLoop)^.nextWindow = WindowPeek (theWindow) THEN iWasBehindThisOne := windowsLoop; IF windowsLoop <> NIL THEN windowsLoop := WindowPtr (WindowPeek (windowsLoop)^.nextWindow) UNTIL (windowsLoop = NIL) OR (iWasBehindThisOne <> NIL); ZoomWindow(theWindow, zoomDir, true); { Rimettila nella posizione giusta nella windows list } IF iWasBehindThisOne <> NIL THEN SendBehind (theWindow, iWasBehindThisOne); IF Ord(WindowPeek(theWindow)^.hilited) = 0 { IM I-277} THEN HiliteWindow (theWindow, TRUE); EraseRect (theWindow^.portRect); { recommended for cosmetic reasons } InvalRect (theWindow^.portRect); IF IsTMWindow (theWindow) THEN { Resize the scrollbars, redraw them, and recalculate the window zones } ResizeNShowSB (theWindow); IF fixClip THEN ClipRect(theWindow^.portRect);END;{$S UtilMain}PROCEDURE TMNewWindow(theWindow: WindowPtr; FrameBits: integer; RefCon: longint; { This is the refCon number 1. Use TMSetWRefCon for the others } DataH, DataW, MaxH, MaxW, MinH, MinW, ScrollVer, ScrollHor, PageVer, PageHor, InfoHeight: integer; infoDefProc, contDefProc, ctlDefProc: TaskMasterDefProc);VAR windowAlreadyKnown: Boolean; { Set if caller asks us to work on a Window we already created aux data for } i, newWidth, newHeight: Integer; workrect: Rect; savedPort: grafPtr;BEGIN IF IsTMWindow (theWindow) THEN windowAlreadyKnown := TRUE ELSE BEGIN thisWindData := tmAuxRecordHandle(NewHandle(SizeOf(tmAuxRecord))); IF thisWindData = NIL THEN exit (TMNewWindow); WITH thisWindData^^ DO BEGIN { Init refcons } FOR i := 2 TO kNumOfRefCons DO wRefCon[i] := 0; wVSBH := NIL; wHSBH := NIL; wTextEdit := NIL; END; windowAlreadyKnown := FALSE END; HLock (Handle (thisWindData)); { We may be shuffling memory while initializing, soÉ } WITH thisWindData^^ DO BEGIN { Fill in the fields of the window record } tmSignature := kTaskMasterSignature; wFrameBits := FrameBits; wRefCon[1] := RefCon; wXOrigin := 0; wYOrigin := 0; wDataH := DataH; wDataW := DataW; wMaxH := MaxH; wMaxW := MaxW; wMinH := MinH; wMinW := MinW; wScrollVer := ScrollVer; wScrollHor := ScrollHor; wPageVer := PageVer; wPageHor := PageHor; wInfoHeight := InfoHeight; { definition procedures (drawing info bar and content} wInfoDefProc := InfoDefProc; IF BAnd(wFrameBits, fContainsTextEdit) = 0 THEN wContDefProc := contDefProc ELSE wContDefProc := TaskMasterDefProcForTextEdit; { New for 3.0 } wControlsDefProc := ctlDefProc; { Create regions for window zones } IF NOT windowAlreadyKnown THEN BEGIN wContentSpace := NewRgn; CloseRgn (wContentSpace); wScrollBarsSpace := NewRgn; CloseRgn (wScrollBarsSpace); END; { Fill in the maintainance fields } CalcZones (theWindow, thisWindData); { Create scroll bars if needed; Reset them if not } IF (BAnd(wFrameBits, fRScroll) <> 0) AND (wVSBH = NIL) THEN IF gTMCanUseThemes THEN wVSBH := NewControl (theWindow, CalcRightSBZone (theWindow, thisWindData), '', true, 0, 0, CalcRSBMax (thisWindData), kControlScrollBarLiveProc, 0) ELSE wVSBH := NewControl (theWindow, CalcRightSBZone (theWindow, thisWindData), '', true, 0, 0, CalcRSBMax (thisWindData), scrollBarProc, 0); IF (BAnd(wFrameBits, fRScroll) = 0) AND (wVSBH <> NIL) THEN BEGIN DisposeControl (wVSBH); wVSBH := NIL END; IF (BAnd(wFrameBits, fBScroll) <> 0) AND (wHSBH = NIL) THEN IF gTMCanUseThemes THEN wHSBH := NewControl (theWindow, CalcBottomSBZone (theWindow, thisWindData), '', true, 0, 0, CalcBSBMax (thisWindData), kControlScrollBarProc, 0) ELSE wHSBH := NewControl (theWindow, CalcBottomSBZone (theWindow, thisWindData), '', true, 0, 0, CalcBSBMax (thisWindData), scrollBarProc, 0); IF (BAnd(wFrameBits, fBScroll) = 0) AND (wHSBH <> NIL) THEN BEGIN DisposeControl (wHSBH); wHSBH := NIL END; { Init TextEdit field if needed } IF (BAnd(wFrameBits, fContainsTextEdit) <> 0) AND (wTextEdit = NIL) THEN BEGIN workRect := CalcTERect (theWindow); GetPort (savedPort); SetPort (theWindow); wTextEdit := TEStyleNew(workRect, workRect); { TEDeactivate (wTextEdit); NIM Text, TEFeatureFlag paragraph } { Init TextEdit as we like it } TEAutoView(true, wTextEdit); i := TEFeatureFlag (teFAutoScr, teBitSet, wTextEdit); {i := TEFeatureFlag (teFOutlineHilite, teBitSet, wTextEdit);} SetPort (savedPort); END; IF (BAnd(wFrameBits, fContainsTextEdit) = 0) AND (wTextEdit <> NIL) THEN BEGIN TEDispose (wTextEdit); wTextEdit := NIL END; IF windowAlreadyKnown THEN BEGIN IF (BAnd(wFrameBits, fRScroll) <> 0) THEN SetControlMaximum (wVSBH, CalcRSBMax (thisWindData)); IF (BAnd(wFrameBits, fBScroll) <> 0) THEN SetControlMaximum (wHSBH, CalcBSBMax (thisWindData)) END ELSE IF (BAnd(wFrameBits, fIsWindoid) = 0) THEN gNumberOfWindoids := succ (gNumberOfWindoids); END; { with } HUnlock (Handle (thisWindData)); { Put a reference to this record in the window record } SetWRefCon(theWindow, longint(thisWindData)); { Sanity check on sizes, new for v3. I resize the window on the current size. This allows TMSizeWindow to check if the current size is acceptable (between min and max as stated by the user), and resize it if necessary } newWidth := theWindow^.portRect.right; newHeight := theWindow^.portRect.bottom; TMSizeWindow (theWindow, newWidth, newHeight, FALSE); END;{$S UtilMain}PROCEDURE TMDisposeWindow(theWindow: WindowPtr);VAR doActivationCheck: Boolean; { Should we activate the second-tier window? } theFrontWindow: WindowPtr;BEGIN doActivationCheck := TRUE; IF IsTMWindow(theWindow) THEN BEGIN HLock(Handle(thisWindData)); WITH thisWindData^^ DO BEGIN IF wHSBH <> NIL THEN { Bug fix in v3.0 } DisposeControl (wHSBH); IF wVSBH <> NIL THEN DisposeControl (wVSBH); DisposeRgn(wContentSpace); DisposeRgn(wScrollBarsSpace); { New in v.3.0 } IF wTextEdit <> NIL THEN TEDispose (wTextEdit); { New in v 3.5 } IF BAnd (wFrameBits, fIsWindoid) <> 0 THEN BEGIN doActivationCheck := FALSE; gNumberOfWindoids := pred (gNumberOfWindoids); END END; DisposeHandle(Handle(thisWindData)) END; theFrontWindow := TMFrontWindow; DisposeWindow(theWindow); IF doActivationCheck AND (gNumberOfWindoids > 0) AND (theFrontWindow = theWindow) THEN BEGIN { Ha chiuso la finestra di primo piano. Ci sono windoid. DisposeWindow ha generato un evento di activate che io devo trascurare, perchŽ altrimenti mi incasina i windoid. Dunque, devo gestire io la attivazione della seconda finestra } theFrontWindow := WindowPtr (WindowPeek (theFrontWindow)^.nextWindow); IF theFrontWindow <> NIL THEN BEGIN HiliteWindow (theFrontWindow, TRUE); { Invia uno pseudo-evento activate } SendMyselfAnActivateEvent (theFrontWindow, TRUE); END; END;END;{$S UtilMain}PROCEDURE TMSetWRefCon(theWindow: WindowPtr; whichOne: Integer; theNewValue: longint);BEGIN IF IsTMWindow(theWindow) THEN thisWindData^^.wRefCon[whichOne] := theNewValue ELSE SetWRefCon(theWindow, theNewValue);END;{$S UtilMain}FUNCTION TMGetWRefCon(theWindow: WindowPtr; whichOne: Integer): longint;BEGIN IF IsTMWindow(theWindow) THEN TMGetWRefCon := tmAuxRecordHandle(thisWindData)^^.wRefCon[whichOne] ELSE TMGetWRefCon := GetWRefCon(theWindow)END;{$S UtilMain}FUNCTION WasMenuEditAndIHandledIt (menu, voce: Integer; finestra: WindowPtr): Boolean;{ Chiamato internamente da TMMenuSelected (per i menu) e TMKey (per mela-lettera).restituisce TRUE se handled }BEGIN IF (menu = kEditMenu) & (voce <= kClear) & IsTMWindow (finestra) & (thisWindData^^.wTextEdit <> NIL) THEN BEGIN SetPort (finestra); TMBeginDirectDraw (finestra); CASE voce OF kUndo:; kCut: TECut (thisWindData^^.wTextEdit); kCopy: TECopy (thisWindData^^.wTextEdit); kPaste: TEPaste (thisWindData^^.wTextEdit); kClear: TEDelete (thisWindData^^.wTextEdit); END; SetScrollLimit; TMEndDirectDraw (finestra); HiliteMenu(0); { Spegni il menu edit } WasMenuEditAndIHandledIt := TRUE END ELSE WasMenuEditAndIHandledIt := FALSEEND;{$S UtilMain}FUNCTION TMMenuSelected(VAR taskRec: wmTaskRec): integer;(************* C' un modo di trattare close? ***************){ Chiamata internamente quando stato selezionato un menu. Gestisce, se l'utente lo ha richiesto, menu Composizione e menu mela } (* Convenzione Gs: gli NDA sono gli id 1-249, e poi abbiamo 250=undo, 251=Cut, 252=copy, 253=Paste, 254=clear, 255=close. Convenzione Mac: i DA sono id 3-.. del primo menu; nel terzo menu 1=undo, 3=cut, 4=copy, 5=paste, 6=clear. {Inside Mac I-441} (NON corrisponde ai messaggi ricevuti da un cdev, vedi technote 215) Per semplificare le cose, qui imponiamo che i menu abbiano numeri consecutivi a partire dal numero 128. *)VAR menu, voce: integer; theName: Str255; { Nome del DA } dummy: integer; { Risultato di OpenDeskAcc } savedPort: GrafPtr; {vedi Inside Mac I-440} topWindow: WindowPtr;BEGIN WITH taskRec DO BEGIN voce := LoWrd(wmTaskData); menu := HiWrd(wmTaskData); IF (menu = kAppleMenu) & (voce >= kFirstNDA) THEN BEGIN { menu mela } IF BAnd(wmTaskMask, tmOpenNDA) = 0 THEN TMMenuSelected := wInDeskItem { wmTaskData contiene menu e voce } ELSE BEGIN GetPort(savedPort); GetMenuItemText(GetMenuHandle(menu), voce, theName); dummy := OpenDeskAcc(theName); SetPort(savedPort); HiliteMenu(0); {"Spegne" il menu mela} wmTaskData := wInDeskItem; TMMenuSelected := nullEvt END; Exit(TMMenuSelected) END; { if menu mela } topWindow := TMFrontWindow; IF menu = kEditMenu THEN IF (BAnd(wmTaskMask, tmSpecial) <> 0) & (BAnd (wmTaskMask, tmAllowEditing) <> 0) & WasMenuEditAndIHandledIt (menu, voce, topWindow) THEN BEGIN TMMenuSelected := nullEvent; wmTaskData := wTextEditChange; wmTaskData4 := Longint (topWindow) { Bug fix 3.5 } END ELSE TMMenuSelected := wInSpecial ELSE { Se siamo arrivati sin qui, un normale menu } TMMenuSelected := wInMenuBar END { with }END;{$S UtilMain}FUNCTION DoGrowStuff (theWin: WindowPtr; theClick: Point): Longint;VAR growWindowResult: longint; growSpace: Rect;BEGIN { Lascia ridimensionare la finestra } IF IsTMWindow (theWin) THEN BEGIN growWindowResult := 0; { Apparente compiler bug woraround, 14nov96 } SetRect(growSpace, CalcMinScreenWidth, CalcMinScreenHeight, CalcMaxScreenWidth(FALSE)+1, CalcMaxScreenHeight(FALSE)+1); { Se non restituisco 1 in pi lui mi limita a 1 in meno! } END ELSE { Let's not be screen fascists: let user take advantage of all screens } WITH GetGrayRgn^^.rgnBBox DO SetRect(growSpace, 64, 48, right-left, bottom-top); growWindowResult := GrowWindow(theWin, theClick, growSpace); { Restituisci le nuove dimensioni all'esterno. Potrebbero servire } DoGrowStuff := growWindowResult; { Ridimensiona la finestra. Questo genera un evento di update. } IF growWindowResult <> 0 THEN { zero sta per "non cambiare" - IM I WMgr } TMSizeWindow (theWin, LoWrd(growWindowResult), HiWrd(growWindowResult), FALSE)END; { procedure }{$S UtilMain}PROCEDURE TMDoActivateStuff (activatedWindow: WindowPtr; myTaskMask: Longint; deactivate: Boolean);{ Chiamato in caso di activate, suspend e resume }LABEL 100;VAR unControllo, ilRootControl: ControlHandle; stato: integer; hostPort: GrafPtr; err: OSErr;BEGIN IF activatedWindow <> NIL THEN BEGIN GetPort (hostPort); SetPort (activatedWindow); IF BAnd(myTaskMask, tmCRedraw) <> 0 THEN BEGIN IF gTMCanUseThemes THEN BEGIN (* HiliteWindow (activatedWindow, NOT deactivate); *) err := GetRootControl (activatedWindow, ilRootControl); IF (err = noErr) AND (ilRootControl <> NIL) THEN IF deactivate THEN err := DeactivateControl (ilRootControl) ELSE err := ActivateControl (ilRootControl) ELSE { Ricadi nel codice per System 7 } Goto 100; END ELSE BEGIN100: PenNormal; { Senn˜ DrawControls pu˜ fallire } unControllo := WindowPeek(activatedWindow)^.controlList; IF deactivate THEN stato := 255 ELSE stato := 0; WHILE unControllo <> NIL DO BEGIN HiliteControl(unControllo, stato); unControllo := unControllo^^.nextControl END; { while } IF IsTMWindow (activatedWindow) & { Bug fix 3.0 } (BAnd (thisWindData^^.wFrameBits, fGrow) <> 0) THEN TMDrawGrowIcon (activatedWindow, thisWindData^^.wFrameBits); END { if it has no Appearance mgr } END; { if CRedraw } { Text Edit handling - new for v3,0 } IF IsTMWindow (activatedWindow) & (BAnd (thisWindData^^.wFrameBits, fContainsTextEdit) <> 0) THEN WITH thisWindData^^ DO BEGIN { HLock (Handle (thisWindData)); Lo fa directdraw } TMBeginDirectDraw (activatedWindow); IF deactivate THEN TEDeactivate (wTextEdit) ELSE IF (BAnd (myTaskMask, tmAllowEditing) <> 0) THEN { window being activated } TEActivate (wTextEdit); TMEndDirectDraw (activatedWindow); END; SetPort (hostPort) END { if }END; { proc }{$S UtilMain}PROCEDURE MyDragWindow (w: WindowPtr; p: Point);{ Analogo a DragWindow, ma non attiva la finestra - sarebbe sbagliato se esistono windoid }VAR err: OSErr; winRgn, originalVisRgn: RgnHandle; everywhere: rect; resultPoint: longint; windowPosOnScreen, finalResult: Point; guestPort: GrafPtr; totalPort: GrafPort;begin Longint (windowPosOnScreen) := 0; LocalToGlobal (windowPosOnScreen); { trovo la pos globale della finestra } GetPort (guestPort); { Crea una regione con l'aspetto della finestra } winRgn := NewRgn; CloseRgn (winRgn); err := GetWindowRegion (w, kWindowStructureRgn, winRgn); { Crea un nuovo GrafPort nel quale disegnare } OpenPort(@totalPort); originalVisRgn := totalPort.visRgn; totalPort.visRgn := GetGrayRgn; everywhere := totalPort.visRgn^^.rgnBBox; totalPort.portRect := everywhere; { Usual grafPort gimmick } SetPort (@totalPort); { Chiedi al toolbox di fare il lavoro } resultPoint := DragGrayRgn (winRgn, p, everywhere, everywhere, noConstraint, NIL); { Il risultato il delta, quindiÉÊ} finalResult.v := HiWrd (resultPoint) + windowPosOnScreen.v; finalResult.h := LoWrd (resultPoint) + windowPosOnScreen.h; { GrafPrt again } SetPort (guestPort); totalPort.visRgn := originalVisRgn; ClosePort(@totalPort); SetPort (guestPort); { Lo so che non dovrebbe servire, maÉÊ} { Esegui lo spostamento } MoveWindow (w, finalResult.h, finalResult.v, FALSE); TMSelectWindow (w); { Liberati della memoria allocata } DisposeRgn (winRgn)END;{$S UtilMain}FUNCTION TaskMaster(taskMask: Integer; sleepRegion: RgnHandle; VAR taskRec: wmTaskRec): integer;VAR theHostPort: GrafPtr; finestra: WindowPtr; wKind, findWindowResult: integer; spazioScrivania: Rect; aPoint: Point; gotEvent: boolean; err: OSErr; theHostPen: PenState; { To save the user pen state before calling PenNormal } PROCEDURE TaskMasterContent; { Riferimenti: vol III, pag. 52-46, dell'Apple IIgs toolbox ref } VAR thePoint: Point; theControl: ControlHandle; r: Rect; startValue: Integer; PROCEDURE HandleThumb; BEGIN HLock (Handle (thisWindData)); WITH taskRec, thisWindData^^ DO BEGIN startValue := GetControlValue (theControl); wmTaskData3 := TrackControl(theControl, thePoint, nil); if LoWrd (wmTaskData3) <> 0 THEN BEGIN { Thumb was dragged, find the delta } startValue := startValue - GetControlValue (theControl); r := wContentSpace^^.rgnBBox; IF theControl = wHSBH THEN BEGIN { horiz } wXOrigin := GetControlValue (theControl); IF wTextEdit <> NIL THEN BEGIN TMBeginDirectDraw (finestra); TEScroll(startValue, 0, wTextEdit); TMEndDirectDraw (finestra) END ELSE MyScrollRect (finestra, r, startValue, 0); END { do horizontal scroll } ELSE BEGIN { vertical } wYOrigin := GetControlValue (theControl); IF wTextEdit <> NIL THEN BEGIN TMBeginDirectDraw (finestra); TEScroll(0, startValue, wTextEdit); TMEndDirectDraw (finestra) END ELSE MyScrollRect (finestra, r, 0, startValue); END { vertical scroll } END; { if thumb was dragged } HUnlock (Handle (thisWindData)) END { with } END; { if click was in thumb } PROCEDURE HandleMyScrollbar; BEGIN WITH taskRec, thisWindData^^ DO BEGIN IF BAnd (wmTaskMask, tmScroll) <> 0 THEN BEGIN IF (LoWrd(wmTaskData3) = kControlIndicatorPart) AND (wTextEdit = NIL) { new v3.5: live scrolling of textedit } THEN HandleThumb ELSE { click was not on thumb } IF wTextEdit <> NIL THEN { Special TextEdit handling case } wmTaskData3 := TrackControl(theControl, thePoint, gScrollTextProc) ELSE wmTaskData3 := TrackControl(theControl, thePoint, gScrollBarProc); TaskMaster := nullEvt; wmTaskdata := wHitFrame; END { ifÉ tmScroll } ELSE { I'm not allowed to track my own controls } TaskMaster := wInFrame; END; { with } exit (TaskMasterContent) END; { proc } PROCEDURE HandleTextEdit (theWin: WindowPtr); VAR extend: Boolean; BEGIN WITH taskRec, thisWindData^^ DO BEGIN IF BAnd (wmTaskMask, tmAllowEditing) <> 0 THEN BEGIN SetPort (theWin); extend := BAnd(wmModifiers, shiftKey) <> 0; TMPhysicalToLogical (thePoint); if PtInRect (thePoint, wTextEdit^^.viewRect) THEN BEGIN TMBeginDirectDraw (theWin); TEClick (thePoint, extend, wTextEdit); TrackTEPosn (wVSBH, wTextEdit); TMEndDirectDraw (theWin); END; TaskMaster := nullEvent; wmTaskData := wTextEditChange; wmTaskData4 := Longint (theWin) END ELSE { We are not allowed to handle the click } TaskMaster := wInContentRgn; END; { with } END; BEGIN WITH taskRec DO BEGIN wmTaskData := longint(finestra); IF (BAnd(wmTaskMask, tmContent) <> 0) & (Ord(WindowPeek(finestra)^.hilited) = 0) { IM I-277} THEN TMSelectWindow(finestra); thePoint := wmWhere; GlobalToLocal(thePoint); wmTaskData3 := FindControl(thePoint, finestra, theControl); wmTaskData2 := longint(theControl); { Passa la Control Handle } { é un mio controllo? } IF (LoWrd(wmTaskData3) >= 20) & IsTMWindow (finestra) & ((theControl = thisWindData^^.wHSBH) | (theControl = thisWindData^^.wVSBH)) THEN HandleMyScrollBar; { E da qui esce direttamente } { No, ma E' un controllo? } IF theControl <> NIL THEN BEGIN { E' un controllo non mio. é un controllo suo che devo gestire? } IF (LoWrd(wmTaskData3) > 0) & (BAnd(wmTaskMask, tmContentControls) <> 0) THEN IF gTMCanUseThemes THEN { Appearance: posso passargli anche i modifiers } wmTaskData3 := HandleControlClick (theControl, thePoint, wmModifiers, pointer (-1)) ELSE wmTaskData3 := TrackControl(theControl, thePoint, pointer( - 1)); { Vabbeh, in qualche modo abbiamo fatto. Mouse out? } IF LoWrd(wmTaskData3) = 0 THEN BEGIN { Moused out of control } TaskMaster := nullEvt; wmTaskdata := wInControl; END { if moused out of user control } ELSE { Yes, user control was clicked } TaskMaster := wInControl END { un controllo} ELSE BEGIN { User clicked in window, but not in a control } IF IsTMWindow(finestra) THEN WITH thisWindData^^ DO { Hmmm.. maybe a click in an inactive scrollbar? } IF PtInRgn(thePoint,wScrollBarsSpace) THEN TaskMaster := wInFrame ELSE { Nope, go ahead: it's the real content } IF (BAnd(wFrameBits, fInfoBar) <> 0) & (thePoint.v < wInfoHeight) THEN TaskMaster := wInInfo ELSE IF BAnd(wFrameBits, fContainsTextEdit) <> 0 THEN HandleTextEdit (finestra) ELSE BEGIN TaskMaster := wInContentRgn; { Give user the coordinates, both absoluteÉ } Point (wmTaskData2) := thePoint; { É and relative } WITH wmWhere DO BEGIN v := thePoint.v + wYOrigin; IF BAnd(wFrameBits, fInfoBar) <> 0 THEN v := v - wInfoHeight - 2; h := thePoint.h + wXOrigin END; { Va restituito in coordinate globali, quindiÉÊ} LocalToGlobal(wmWhere); END { if click in real content region } ELSE TaskMaster := wInContentRgn END { clicked in window, not control } END { with } END; { Procedure } PROCEDURE TaskMasterKeydown; VAR menu, voce: Integer; BEGIN finestra := TMFrontWindow; WITH taskRec DO BEGIN { Se non scorciatoria di tastieraÉ } IF (BAnd(wmModifiers, cmdKey) = 0) | { Éo se non trattiamo scorc. di tastiera } (BAnd(wmTaskMask, tmMenuKey) = 0) THEN { Banale tasto premuto. Devo passarlo a TextEdit? } IF IsTmWindow (finestra) & { Si, se questa finestra contiene un TextEditÉ } (BAnd (thisWindData^^.wFrameBits, fContainsTextEdit) <> 0) & { Ée se l'utente mi ha chiesto di farlo } (BAnd(wmTaskMask, tmAllowEditing) <> 0) THEN BEGIN HLock (Handle (thisWindData)); GetPort (theHostPort); SetPort (finestra); WITH thisWindData^^ DO BEGIN TMBeginDirectDraw (finestra); TEKey(Chr(BAnd (wmMessage, charCodeMask)), wTextEdit); SetScrollLimit; TMEndDirectDraw (finestra); END; { with } SetPort (theHostPort); HUnLock (Handle (thisWindData)); TaskMaster := nullEvent; wmTaskData := wTextEditChange; wmTaskData4 := Longint (finestra) END ELSE TaskMaster := keyDown ELSE BEGIN IF gTMCanUseThemes THEN wmTaskData := MenuEvent (taskRec.eventRecord) { New for appearance } ELSE wmTaskData := MenuKey(chr(BAnd(wmTaskData, charCodeMask))); menu := HiWrd (wmTaskData); voce := LoWrd (wmTaskData); IF WasMenuEditAndIHandledIt (menu, voce, finestra) THEN BEGIN TaskMaster := nullEvent; wmTaskData := wTextEditChange; wmTaskData4 := Longint (finestra); END ELSE TaskMaster := TMMenuSelected(taskRec) END; END { with } END; { Keydown }BEGIN { TaskMaster itself } { Chiama lo Event manager e scopri se ci sono eventi in coda } gotEvent := WaitNextEvent(taskMask, taskRec.EventRecord, gMyPriority, sleepRegion);{ IF gotEvent THEN } WITH taskRec DO BEGIN { Fa una copia dello event message } wmTaskData := wmMessage; CASE wmWhat OF nullEvent: BEGIN { Handling of tmIdleEvents } IF BAnd(wmTaskMask, tmIdleEvents) <> 0 THEN finestra := AllWindowsLoop (CallbackGiveIdle, CallbackDoNothing, CallbackGiveIdleIncludingTextEdit, CallbackGiveIdle); wmTaskData := 0; TaskMaster := nullEvent END; mouseDown: BEGIN IF BAnd(wmTaskMask, tmMultiClick) <> 0 THEN IF TickCount - wmLastClickTick < GetDblTime THEN BEGIN { Double click } aPoint := wmWhere; SubPt(wmLastClickPt, aPoint); IF ABS(aPoint.v) + ABS(aPoint.h) < 4 THEN { Clicked same general area } wmClickCount := succ(wmClickCount) ELSE wmClickCount := 1 END { IF double click } ELSE wmClickCount := 1; wmLastClickTick := wmWhen; wmLastClickPt := wmWhere; IF BAnd(wmTaskMask, tmFindW) <> 0 THEN BEGIN findWindowResult := FindWindow(wmWhere, finestra); GetPort (theHostPort); GetPenState (theHostPen); PenNormal; { So that we can draw controls and info bar frame } SetPort (finestra); { So that update & others may work } CASE findWindowResult OF inMenuBar: IF BAnd(wmTaskMask, tmMenuSel) = 0 THEN BEGIN { L'applicazione tratta i click in menu bar } wmTaskData := 0; TaskMaster := inMenuBar END ELSE BEGIN wmTaskData := MenuSelect(wmWhere); IF HiWrd(wmTaskData) = 0 THEN { no selection was made } IF BAnd(wmTaskMask, tmInactive) <> 0 THEN BEGIN wmTaskData := menuChoice; TaskMaster := wInactMenu END ELSE BEGIN wmTaskData := wInMenuBar; TaskMaster := nullEvent END ELSE { selection was made } TaskMaster := TMMenuSelected(taskRec) END; { inMenuBar } inSysWindow: IF BAnd(wmTaskMask, tmSysClick) = 0 THEN BEGIN wmTaskData := longint(finestra); { La convenzione del Gs pi furba di quella Mac. Quando si clicca nella finestra di un DA, Mac restituisce inSysWindow, e il DA si deve arrangiare. Il Gs, invece, restituisce le stesse costanti usate per le normali finestra (come inGrow) e somma wInSysWindow, cio $8000, lo rende negativo. Qui adottiamo la convenzione Gs } { Fingi che sia una finestra dell'applicazione } wKind := WindowPeek(finestra)^.WindowKind; WindowPeek(finestra)^.WindowKind := userKind; { Chiama di nuovo FindWindow } TaskMaster := FindWindow(wmWhere, finestra) + wInSysWindow; { restituisci la finestra al proprietario } WindowPeek(finestra)^.WindowKind := wKind END ELSE BEGIN SystemClick(taskRec.EventRecord, finestra); wmTaskData := wClickCalled; TaskMaster := nullEvt END; inDrag: IF BAnd(wmTaskMask, tmDragW) = 0 THEN BEGIN wmTaskData := longint(finestra); TaskMaster := inDrag END ELSE BEGIN { Lascia spostare la finestra, poi attivala } IF IsTMWindow(finestra) & gTMCanUseThemes & (BAnd(thisWindData^^.wFrameBits, fIsWindoid) = 0) THEN { Se abbiamo appearance, supportiamo i windoid. In questo caso, se questa finestra non un windoid, spostala mantenendola sullo stesso piano in cui si trova giˆ } MyDragWindow (finestra, wmWhere) ELSE BEGIN { Se invece siamo in System 7, o se questa finestra un windoid, spostala e dopo averla spostata mettila in primo piano } spazioScrivania := GetGrayRgn^^.rgnBBox; {Technote 79 pg.2} DragWindow(finestra, wmWhere, spazioScrivania); END; wmTaskData := wInDragRgn; wmTaskData2 := Longint (finestra); { bug fix 3.0 } TaskMaster := nullEvent END; inContent: TaskMasterContent; inGoAway: IF BAnd(wmTaskMask, tmClose) = 0 THEN BEGIN wmTaskData := longint(finestra); TaskMaster := wInGoAwayRgn; END ELSE IF TrackGoAway(finestra, wmWhere) THEN BEGIN wmTaskData := longint(finestra); TaskMaster := wInGoAwayRgn; END ELSE BEGIN wmTaskData := wInGoAwayRgn; TaskMaster := nullEvt END; inZoomIn, inZoomOut: IF BAnd(wmTaskMask, tmZoom) = 0 THEN BEGIN wmTaskData := longint(finestra); TaskMaster := wInZoom END ELSE BEGIN wmTaskData2 := Longint (finestra); { bug fix 3.0 } IF TrackBox(finestra, wmWhere, findWindowResult) THEN BEGIN DoWZoom(finestra, findWindowResult); wmTaskData := wInZoom; END ELSE wmTaskData := wTrackZoom; TaskMaster := nullEvt END; inGrow: IF BAnd(wmTaskMask, tmGrow) = 0 THEN BEGIN wmTaskData := longint(finestra); TaskMaster := wInGrowRgn; END ELSE BEGIN wmTaskData4 := DoGrowStuff (finestra, wmWhere); wmTaskData2 := longint(finestra); wmTaskData := wInGrowRgn; TaskMaster := nullEvt END; OTHERWISE BEGIN { ogni altra cosa, come inDesk } wmTaskData := findWindowResult; TaskMaster := findWindowResult END END; { FindWindow } { Ripristina lo stato della macchina prima di uscire } SetPort (theHostPort); SetPenState (theHostPen); END ELSE TaskMaster := mouseDown; END; { case mouseDown } keyDown, autoKey: TaskMasterKeydown; updateEvt: { Dobbiamo trattare noi gli update event? } IF (BAnd(wmTaskMask, tmUpdate) <> 0) & TMDoUpdateStuff(WindowPtr(wmTaskData), wmTaskMask) THEN BEGIN TaskMaster := nullEvent; { Bug patch. Accade che dopo TMDoUpdateStuff l'accesso ai campi dell'event record dereferenziato con WITH generi un bus error. Sospetto che qualcosa nello stack vada a soqquadro e venga rimesso a posto solo in uscita dalla procedura. Come workaround, evito di usare il dereferencing } taskRec.wmTaskData := updateEvt END ELSE {wmTaskData contiene il puntatore alla window che vuole update} TaskMaster := updateEvt; activateEvt: BEGIN { wmLastClickTick all'inizio indeterminato, e questo pu˜ provocare qualche effetto collaterale. Per˜, siccome il primo evento che arriva a una applicazione activate...} wmLastClickTick := 0; IF gNumberOfWindoids > 0 THEN BEGIN { Non accettare gli activate del toolbox, incasinano i windoid } wmTaskData := 0; TaskMaster := nullEvent END ELSE BEGIN wmTaskData2 := BAnd(wmModifiers, activeFlag); TMDoActivateStuff (WindowPtr (wmTaskData), wmTaskMask, wmTaskData2 = 0); TaskMaster := activateEvt END END; { activate } osEvt: { Mouse moved? (le equates di Events.p contengono $00FA, non $FA00) } IF BAnd (wmMessage, $FF000000) = $FA000000 THEN TaskMaster := wMouseMoved ELSE BEGIN { Suspend o resume } IF BAnd(wmTaskMask, tmMultiFinder) <> 0 THEN BEGIN wmTaskData := longint(TMFrontWindow); wmTaskData2 := BAnd(wmModifiers, activeFlag); { Distingui il tipo di osEvt } wmTaskData2 := BAnd(wmMessage, 1); { Hide or show windoids, as appropriate } { Also, check that all windows look inactive when in background, and that the front window is highlighted when we're back in foreground } SuspendOrResumeVisualTasks (LoWrd(wmTaskData2) = 1); IF LoWrd(wmTaskData2) = 1 THEN BEGIN InitCursor; { Il cursore pu˜ cambiare in major switch } TaskMaster := wResume; END ELSE TaskMaster := wSuspend; END { if tmMultifinder bit is set } ELSE TaskMaster := osEvt END; { suspend o resume } diskEvt: IF (BAnd(wmTaskMask, tmDoDiskMount) <> 0) & (HiWrd(wmMessage) <> noErr) THEN BEGIN WITH qd.screenBits.bounds DO { find appropriate position in main screen } SetPt(aPoint, (right - left - 200) DIV 2, (bottom - top - 100) DIV 3); err := DIBadMount (aPoint, wmMessage); TaskMaster := nullEvent; wmTaskData := wDiskMount; wmTaskData2 := err END ELSE TaskMaster := diskEvt; kHighLevelEvent: { Pu˜ essere uno pseuso-evento activate, e allora lo tratto come un activate. Oppure un altra cosa, tipicamente un AppleEvent, e allora lo passo al chiamante } IF wmMessage = Longint (kTaskMasterSignature) THEN BEGIN HandlePseudoActivateEvent (taskRec); TaskMaster := activateEvt END ELSE TaskMaster := kHighLevelEvent; OTHERWISE TaskMaster := wmWhat END { case Event of } END { with, dereferenziante il record }END; {TaskMaster}{$S UtilMain}PROCEDURE TMLoadText (theWin: WindowPtr; textHandle: Handle; stylInTheWindow: {StScrap}Handle);BEGIN { sanity check } IF IsTMWindow (theWin) & (BAnd(thisWindData^^.wFrameBits, fContainsTextEdit) <> 0) THEN BEGIN Hlock (Handle (thisWindData)); WITH thisWindData^^ DO BEGIN SetPort (theWin); TMBeginDirectDraw (theWin); { Cancella qualsiasi cosa si trovasse in precedenza nel TextEdit field } TESetSelect (0, MAXINT, wTextEdit); TEDelete (wTextEdit); { Metti il tutto nel TextEdit record } TEStyleInsert (textHandle^, GetHandleSize (textHandle), STScrpHandle(stylInTheWindow), wTextEdit); SetScrollLimit; TMEndDirectDraw (theWin); END; { with } HUnlock (Handle (thisWindData)) END { if }END;{$S UtilMain}PROCEDURE TEAppendTextRun (theWin: WindowPtr; theTextRun: Str255);VAR lastCharPos: Integer;BEGIN IF IsTMWindow (theWin) THEN BEGIN Hlock (Handle(thisWindData)); WITH thisWindData^^ DO BEGIN lastCharPos := wTextEdit^^.teLength; TMBeginDirectDraw (theWin); { Sostanzialmente a beneficio di Dream } IF lastCharPos > 32000 THEN BEGIN TESetSelect(1, 10000, wTextEdit); TEDelete (wTextEdit); END; TESetSelect (lastCharPos, lastCharPos, wTextEdit); TEInsert (@theTextRun[1], length(theTextRun), wTextEdit); TESelView (wTextEdit); { garantisce che il nuovo testo appaia alla vista } SetScrollLimit; TMEndDirectDraw (theWin); END; { with } HUnlock (Handle(thisWindData)); END; { if }END;PROCEDURE TESetTextStyle (theWin: WindowPtr; whatToChange, theFont, theSize: Integer; theStyle: Style; theColor: RGBColor);VAR myStyleRec: TextStyle;BEGIN IF IsTMWindow (theWin) THEN BEGIN Hlock (Handle(thisWindData)); WITH thisWindData^^, myStyleRec DO BEGIN tsFont := theFont; tsFace := theStyle; tsSize := theSize; tsColor := theColor; TMBeginDirectDraw (theWin); TESetStyle(whatToChange, myStyleRec, TRUE, wTextEdit); TMEndDirectDraw (theWin); END; { with } HUnlock (Handle(thisWindData)); END; { if }END;{$S UtilMain}FUNCTION TEGetTextStyle (theWin: WindowPtr; VAR theFont, theSize: Integer; VAR theStyle: Style; VAR theColor: RGBColor): Boolean;VAR riuscito: Boolean; gliStili: STScrpHandle; loop: Integer; stdFont: Longint;BEGIN riuscito := FALSE; IF IsTMWindow (theWin) & (thisWindData^^.wTextEdit <> NIL) THEN BEGIN gliStili := TEGetStyleScrapHandle (thisWindData^^.wTextEdit); IF (gliStili <> NIL) & (gliStili^^.scrpNStyles > 0) THEN BEGIN HLock (Handle (gliStili)); WITH gliStili^^ DO BEGIN theFont := scrpStyleTab [0].scrpFont; theSize := scrpStyleTab [0].scrpSize; theColor := scrpStyleTab [0].scrpColor; theStyle := scrpStyleTab [0].scrpFace; FOR loop := 2 TO scrpNStyles DO BEGIN { Same font? } IF scrpStyleTab [loop-1].scrpFont <> theFont THEN theFont := -1; { Same... etc } IF scrpStyleTab [loop-1].scrpSize <> theSize THEN theSize := -1; IF scrpStyleTab [loop-1].scrpFace <> theStyle THEN theStyle := Style(-1); (*** IF scrpStyleTab [loop-1].scrpColor <> theColor THEN theColor := ??? ***) END; END; { with } DisposeHandle (Handle (gliStili)); { Restituisci valori significativi al posto di quelli "standard" di TE } IF (theSize = 0) OR (theFont = 1) THEN BEGIN stdFont := GetScriptVariable (smSystemScript, smScriptAppFondSize); IF theSize = 0 THEN theSize := LoWrd (stdFont); IF theFont = 1 THEN theFont := HiWrd (stdFont); END; riuscito := TRUE END END; TEGetTextStyle := riuscitoEND;{$S UtilMain}PROCEDURE TMKernelGrabTextFromWindow (theWin: WindowPtr; VAR theText, theStyle: Handle);(*** WARNING: Le handle restituite sono proprietˆ di TextEdit E NON NE VA FATTO UN DISPOSE ***)VAR savedSelStart, savedSelEnd: Integer;BEGIN IF IsTMWindow (theWin) & (thisWindData^^.wTextEdit <> NIL) THEN BEGIN theText := Handle (TEGetText (thisWindData^^.wTextEdit)); { TEGetStyleScrapHandle si occupa solo della selezione corrente, dunqueÉÊ} savedSelStart := thisWindData^^.wTextEdit^^.selStart; savedSelEnd := thisWindData^^.wTextEdit^^.selEnd; TESetSelect (1, maxint, thisWindData^^.wTextEdit); theStyle := Handle (TEGetStyleScrapHandle (thisWindData^^.wTextEdit)); TESetSelect (savedSelStart, savedSelEnd, thisWindData^^.wTextEdit); END ELSE BEGIN theText := NIL; theStyle := NIL ENDEND;CONST resTestoPuro = 'TEXT'; resStileDelTesto = 'styl'; kSimpleTextCreator = 'ttxt'; kSimpleTextFileType = 'TEXT'; rSimpleTextStylID = 128;{$S UtilMain}PROCEDURE TMSaveTextToRes (theWin: WindowPtr; theResID: Integer; theResName: Str255);VAR theText, theStyle: Handle; theFile: MyFile;BEGIN TMKernelGrabTextFromWindow (theWin, theText, theStyle); { Salva lo "styl" } theFile.resFork := CurResFile; WriteRes (theFile, theResID, resStileDelTesto, '', theStyle); DetachResource (theStyle); { Salva il testo } WriteRes (theFile, theResID, resTestoPuro, theResName, theText); DetachResource (theText);END;{$S UtilMain}PROCEDURE TMSaveTextToFile (theWin: WindowPtr; where: FSSpec);VAR theFile: MyFile; theText, theStyle: Handle;BEGIN TMKernelGrabTextFromWindow (theWin, theText, theStyle); RewriteRByFSS (theFile, where, kSimpleTextFileType, kSimpleTextCreator); { Salva lo "styl" } WriteRes (theFile, rSimpleTextStylID, resStileDelTesto, '', theStyle); DetachResource (theStyle); { Salva il testo } HandleWrite (theFile, GetHandleSize (theText), theText); Close (theFile)END;{$S UtilMain}PROCEDURE TMLoadTextFromRes (theWin: WindowPtr; theResID: Integer);VAR textHandle: Handle; { Handle alla risorsa TEXT } stylInTheWindow: {StScrp}Handle; { Handle alla risorsa styl }BEGIN { Leggi dalle risorse il testo } textHandle := GetResource (resTestoPuro, theResID); { Leggi dalle risorse lo stile } stylInTheWindow := GetResource (resStileDelTesto, theResID); { Metti il tutto nel TextEdit record } TMLoadText (theWin, textHandle, stylInTheWindow); { Liberati delle risorse } IF textHandle <> NIL THEN ReleaseResource (textHandle); IF stylInTheWindow <> NIL THEN ReleaseResource (stylInTheWindow);END;{$S UtilMain}PROCEDURE TMLoadTextFromFile (theWin: WindowPtr; fromWhere: FSSpec);VAR theFile: MyFile; textHandle: Handle; { Handle alla risorsa TEXT } stylInTheWindow: {StScrp}Handle; { Handle alla risorsa styl } howMuchToRead: Longint;BEGIN ResetRByFss (theFile, fromWhere); IF theFile.errore = noErr THEN BEGIN { Testo } howMuchToRead := MAXINT; { Massimo ammesso da TextEdit } textHandle := NewHandle (howMuchToRead); IF textHandle <> NIL THEN BEGIN HandleRead (theFile, howMuchToRead, textHandle); SetHandleSize (textHandle, howMuchToRead) { In seguito si farˆ GetHandleSizeÉ} END; { Stile } stylInTheWindow := Get1Resource (resStiledelTesto, rSimpleTextStylID); { Metti il tutto nel TextEdit record } TMLoadText (theWin, textHandle, stylInTheWindow); { Shutdown } IF stylInTheWindow <> NIL THEN ReleaseResource (stylInTheWindow); IF textHandle <> NIL THEN DisposeHandle (textHandle) END; { Chiudi il file } Close (theFile)END;END. {Unit}