mirror of
https://github.com/elliotnunn/supermario.git
synced 2024-11-29 20:49:19 +00:00
1686 lines
61 KiB
Plaintext
1686 lines
61 KiB
Plaintext
;______________________________________________________________________________
|
||
;
|
||
; File: TSMExtension.a
|
||
;
|
||
; Contains: Text Services Manager trap dispatcher.
|
||
;
|
||
; Written by: Kenny SC. Tung
|
||
;
|
||
; Copyright: © 1991-1992 by Apple Computer, Inc., all rights reserved.
|
||
;
|
||
; Change History (most recent first):
|
||
;
|
||
; <SM5> 8/26/92 kc Fix compiler warning.
|
||
; <SM4> 7/7/92 CSS Update from Reality:
|
||
; <49> 7/3/92 KST <JH>: Correct a type error: kIMJustSetCursorBit should really be
|
||
; kSWMJustSetCursorBit.
|
||
; <48> 6/26/92 KST #1031142 <JH>: When the application claims not TSM aware any
|
||
; more, we need to clear all UseInputWindow flags so it will not
|
||
; be reused when another TSM aware app is launched.
|
||
; <47> 6/26/92 KST #1033450,1033456,1031316 <JH>: When XCLOSETSMAWAREAPPLICATION()
|
||
; is called, we better inform Process Manager about it.
|
||
; <46> 6/22/92 KST #1033280,1033495 <JH>: When part code <= inSysWindow, return not
|
||
; over a floating window. (I used to only check inDesk).
|
||
; <45> 6/19/92 KST #1032492 <JH>: When TSM tries to open the resource file using
|
||
; the refcon in the floating window, need to verify its
|
||
; windowkind.
|
||
; <44> 6/17/92 KST #1030843 <JH>: If we click in a popup menu inside of a floating
|
||
; window, HMGetBalloon needs to return true so that balloon will
|
||
; be removed. Also changed the function name from
|
||
; utaIsApplicationTSMAware to utaIsAppTSMAwareAndNotUsingIW to be
|
||
; more precise and descriptive.
|
||
; <43> 6/14/92 KST Changed utaRemoveDocumentID to return the number of TSM
|
||
; documents remained open by the application.
|
||
|
||
; <SM3> 6/11/92 CSS Roll-in Reality Changes. I don't know where Fred left off so here
|
||
; are all the comments:
|
||
; <42> 6/10/92 YK Oops, don’t do last minutes change.
|
||
; <41> 6/10/92 YK #1031298 <JH>: Add OldJapaneseInputMethodExists. It returns
|
||
; True if the specified old-input method exists.
|
||
; <40> 6/10/92 KST #1031142,1030881 <JH>: Since we removed the docID param from
|
||
; TSMEvent, UseInputWindow has been broken because keydown event
|
||
; is routed to SWM recursively. Fix it with a TSM global keeping
|
||
; track of which doc is using the input window. And added a new
|
||
; private call for SWM -- TSMEventFromSWM. The TSM boot code has
|
||
; been modified so that it can handle multiple TSMinit files.
|
||
; (Global will not be re-allocated).
|
||
; <39> 6/4/92 JH #1031574 <KST>: _HMGetBalloonPatch leaves bits behind when a
|
||
; help window is drawn over the menubar. Checking to see if we are
|
||
; over the menubar or over a systemwindow before we return false.
|
||
; <38> 6/2/92 KST <JH>, Should not check for inContent in HMGetBalloon.
|
||
; <37> 6/2/92 KST <JH>,The previous change has a minor mistake in HMGetBalloon
|
||
; patch.
|
||
; <36> 6/2/92 JH #1028635,1030481,1030631,1030634,1030647 <KST>: Added SystemMenu
|
||
; patch to support system menus for input methods.
|
||
; <35> 5/20/92 KST #1030447 <JH>: Fixed a bug. UseInputWindow did not work if we
|
||
; want to have global effect for the application.
|
||
; <34> 5/14/92 KST #1025797,<JH>: Added one new message selector 'kMsgHelpHELPMgr'
|
||
; to InformTSM. This call is used by __HMScanHWinResource in
|
||
; BalloonPACK.a. Also patched __HMGetBalloonPatch so that Help
|
||
; balloon will not flash in the Finder.
|
||
; <33> 5/4/92 KST #1025252,<JH>: Patched _PaintBehind so that floating windows
|
||
; will be updated correctly when the whole screen is redrawn.
|
||
; <32> 5/2/92 YK Flush the parameter on the stack before return to a caller.
|
||
; <31> 5/1/92 KST #1027482,<JH>: If input method changed cursor in a floating
|
||
; layer, then don't let other application to change the cursor
|
||
; again.
|
||
; <30> 5/1/92 KST #1028301,<JH>: SetTSMDialogState, RestoreTSMDialogState,
|
||
; TSMChangeCursor, TSMRestoreCursor calls are no longer needed and
|
||
; should be removed from the source code.
|
||
; <29> 4/9/92 KST JH,modifying InitTSMApplication to support the fact that SWM is
|
||
; no longer an application but a driver. Adding 2 new messages in
|
||
; InformTSM. Will remove SetDialogState in the next release.
|
||
; <28> 3/27/92 KST Documentation changes.
|
||
; <27> 3/23/92 KST Changes due to the code review.
|
||
; <26> 3/12/92 KST Added a new call "utaGetTSMAwareDocTable".
|
||
; <25> 3/6/92 KST Removed debugger code. Will grow internal table when overflow.
|
||
; <24> 3/4/92 KST Get trap address of SetCursor at INIT time.
|
||
; <23> 3/3/92 KST Added 2 new calls: "TSMChangeCursor", and "TSMRestoreCursor".
|
||
; <22> 3/2/92 KST Added a private TSM call "NewTSMDocument4SWM".
|
||
; <21> 2/28/92 KST Added 2 new calls "SetTSMDialogState", and
|
||
; "RestoreTSMDialogState".
|
||
; <20> 2/27/92 KST In utKillTSMAwareApplication, if the app is not TSM aware, we'll
|
||
; send an AE to SWM ask it to close its input window. If it is TSM
|
||
; aware, we'll set tsmKillApplicationP flag to true.
|
||
; <19> 2/11/92 DCL Changed the name of TSMEqu.[aph] to TextServices.[aph] for
|
||
; better read-ability.
|
||
; <18> 2/10/92 KST InformTSM's msgChangeToOldJIM now takes a parameter -- FEPID.
|
||
; <SM2> 4/22/92 FM Bring up to date with Reality…
|
||
; <17> 2/1/92 KST We don't have a global flag in TSM globals to indicate using
|
||
; bottom-line window.
|
||
; <16> 1/31/92 YK Added FindServiceWindow.
|
||
; <15> 1/29/92 KST Removed "xIsApplicationTSMAware" call. Also inform Process
|
||
; Manager whether it should start sending events to SWM when SWM
|
||
; informTSM with its PSN.
|
||
; <14> 1/16/92 KST Add a new message to InformTSM: kMsgChangeToOldJIM.
|
||
; <13> 1/11/92 KST TSM globals are initially cleared.
|
||
; <12> 1/10/92 KST Inform Process Manager if the application is TSM aware.
|
||
; <11> 1/9/92 KST Changed SetDefaultInputMethod selector back to 13 so that we can
|
||
; build TSM INIT with d13.
|
||
; <10> 1/8/92 KST Removed CleanUpTSMAwareApp routine. CleanUpTSMApp is now a
|
||
; message to InformTSM.
|
||
; <9> 1/4/92 KST Add a new routine "CloseTextService". Also "OpenTextService" now
|
||
; returns component instance to the caller.
|
||
; <8> 12/31/91 KST Added "CleanUpTSMAwareApplication" and "InformTSM" new calls.
|
||
; Check saved resource for "Use Input Window" global flag at boot
|
||
; time.
|
||
; <7> 12/20/91 KST Making progress toward Alpha. Changed "inline" to "TSM", and
|
||
; added new calls.
|
||
; <6> 12/10/91 KST Adding a new "InlineAwareRegister" call.
|
||
; <5> 12/10/91 KST Disable the Gestalt call for now.
|
||
; <4> 12/10/91 KST Added boot time initialization code, and to use "TSMPrivate.a".
|
||
; <3> 11/26/91 KST Low level TSM routines are now dispatched directly to the
|
||
; Component Manager.
|
||
; <2> 11/23/91 KST Check in the first time for Cube-E.
|
||
;
|
||
;
|
||
;______________________________________________________________________________
|
||
|
||
|
||
|
||
|
||
;______________________________________________________________________________
|
||
;
|
||
; File: "TSMDispatch.a"
|
||
;
|
||
; Written by Kenny SC. Tung
|
||
;
|
||
; Modification History:
|
||
; 21Nov91 KSCT New today.
|
||
;______________________________________________________________________________
|
||
|
||
|
||
|
||
|
||
PRINT OFF
|
||
|
||
LOAD 'StandardEqu.d'
|
||
INCLUDE 'Processes.a'
|
||
INCLUDE 'MFPrivate.a'
|
||
INCLUDE 'LinkedPatchMacros.a'
|
||
INCLUDE 'GestaltEqu.a'
|
||
INCLUDE 'LayerEqu.a'
|
||
|
||
INCLUDE 'TextServices.a'
|
||
INCLUDE 'TSMPrivate.a'
|
||
|
||
INCLUDE 'Balloons.a'
|
||
INCLUDE 'BalloonsPriv.a'
|
||
INCLUDE 'ScriptPriv.a'
|
||
|
||
PRINT ON
|
||
|
||
CASE OBJ
|
||
|
||
IF &type('TSMDebug') = 'UNDEFINED' THEN
|
||
TSMDebug EQU 0
|
||
ENDIF
|
||
|
||
|
||
IF &type('BuildTSMInit') = 'UNDEFINED' THEN
|
||
BuildTSMInit EQU 0 ; this is only defined when building INIT
|
||
ENDIF
|
||
|
||
|
||
;______________________________________________________________________________
|
||
; Input: D0.W low byte = trap index,
|
||
; high byte = # of parameters in words.
|
||
; Note:
|
||
;______________________________________________________________________________
|
||
TSMDISPATCH Proc export ; dispatch code
|
||
|
||
MOVEQ #0,D1
|
||
MOVE.W D0,D1 ; D1 = trap index
|
||
TST.W D1 ; Check the trap dispatch
|
||
BLT.S @1 ; Negative traps are trouble
|
||
CMP.W #kMaxTSMSelector,D1 ; Compare against our known limits
|
||
BLS.S @2 ; Continue if all seems well
|
||
|
||
@1 MOVEQ #0,D1
|
||
MOVE.W D0,D1
|
||
LSR.W #8,D1 ; D1 = # of parameters in words
|
||
LSL.W #1,D1 ; convert to bytes
|
||
MOVEQ #ParamErr,D0 ; Indicate parameter error
|
||
MOVEA.L (SP)+,A0 ; get return address
|
||
LEA (A7,D1),SP ; pop param
|
||
MOVE.W D0,(SP) ; function result
|
||
JMP (A0) ; Terminate this call
|
||
|
||
@2 ;; D1 = trap index.
|
||
EXT.W D1 ;
|
||
ASL.W #1,D1 ; each entry is 4 bytes
|
||
MOVE.W TSMTrapTable(D1.W),d0 ; get the address of the entry point
|
||
JMP TSMTrapTable(D0.W) ;jump to it
|
||
|
||
MACRO
|
||
JT &entry
|
||
IMPORT &entry
|
||
DC.W &entry - TSMTrapTable
|
||
ENDM
|
||
TSMTrapTable
|
||
|
||
JT XNEWTSMDOCUMENT ; 0 initialize TSM aware document
|
||
JT XDELETETSMDOCUMENT ; 1
|
||
JT XACTIVATETSMDOCUMENT ; 2
|
||
JT XDEACTIVATETSMDOCUMENT ; 3
|
||
JT XTSMEVENT ; 4
|
||
JT XTSMMENUSELECT ; 5
|
||
JT XSETTSMCURSOR ; 6
|
||
JT XFIXTSMDOCUMENT ; 7
|
||
JT XGETSERVICELIST ; 8
|
||
JT XOPENTEXTSERVICE ; 9
|
||
JT XCLOSETEXTSERVICE ; 10 <04Jan91 #9>
|
||
JT XSENDAETOCLIENT ; 11
|
||
|
||
|
||
JT XSETDEFAULTINPUTMETHOD ; 12
|
||
JT XGETDEFAULTINPUTMETHOD ; 13 (D)
|
||
JT XSETTEXTSERVICELANGUAGE ; 14 (E)
|
||
JT XGETTEXTSERVICELANGUAGE ; 15
|
||
JT XUSEINPUTWINDOW ; 16
|
||
JT XNEWSERVICEWINDOW ; 17
|
||
JT XCLOSESERVICEWINDOW ; 18
|
||
JT XGETFRONTSERVICEWINDOW ; 19
|
||
|
||
JT XINITTSMAWAREAPPLICATION ; 20
|
||
JT XCLOSETSMAWAREAPPLICATION ; 21
|
||
JT XINFORMTSM ; 22
|
||
|
||
JT XFINDSERVICEWINDOW ; 23
|
||
JT XNEWTSMDOCUMENT4SWM ; 24 <02Mar92 #22>
|
||
JT XTSMEVENTFROMSWM ; 25 <03Jun92 #39>
|
||
|
||
ENDP
|
||
|
||
|
||
|
||
|
||
; __________________________________________________________________________
|
||
; Function: xInitTSMAwareApplication()
|
||
; Application registers itself as TSM aware.
|
||
; Input: none.
|
||
; Output: D0.W = error code (memFullErr, tsmNotAnAppErr, tsmAlreadyRegisteredErr)
|
||
; Register usage: Use D0,D1,A0,A1
|
||
;
|
||
; Side Effect: If application registers itself the first time, a table to
|
||
; record open document IDs is allocated if it is not allocated.
|
||
; ___________________________________________________________________________
|
||
XINITTSMAWAREAPPLICATION PROC EXPORT
|
||
Import utaTSMAwareApplicationP
|
||
Export xInitTSMAwareDriver
|
||
WITH PSNRecord
|
||
|
||
SUBA.W #10, sp ; allocate storage for PSN (8 bytes) and result
|
||
PEA 2(sp) ; push address of PSN storage
|
||
_GetSystemClientProcess ; get PSN with which to associate the file
|
||
TST.W (sp)+ ; on error, PSN == kNoProcess
|
||
BNE.S noProcess
|
||
|
||
xInitTSMAwareDriver
|
||
;; Verify if we have registered this app already ...
|
||
MOVE.L highLongOfPSN(SP),D0 ; get high half of PSN
|
||
MOVE.L lowLongOfPSN(SP),D1 ; get low half of PSN
|
||
BSR utaTSMAwareApplicationP ; is it already registered?
|
||
BNE.S registered ; yes, punt =>
|
||
;; PSN on top of stack. Locate a free entry and store.
|
||
BSR getFreePSNEntry ; get a free entry in A1
|
||
BNE.S cleanSPExit ; punt on error (D0 set)
|
||
;; Record this application in the PSN table (A1) ...
|
||
|
||
IF TSMDebug THEN ; debug begin
|
||
CMP.W #kPSNTableSignature,psnTableSignature(A1) ; valid table?
|
||
BEQ.S TableOK ; yes
|
||
_debugger
|
||
TableOK
|
||
ENDIF ; end
|
||
|
||
MOVE.L (sp)+,psnHighID(A1) ; pop and save high half of PSN
|
||
MOVE.L (sp)+,psnLowID(A1) ; pop and save low half of PSN
|
||
CLR.W psnDoWeReallyUseIW(A1) ; don't use float input window
|
||
MOVEA.L psnDocsTablePtr(A1),A0 ; get the addr
|
||
MOVE.L A0,D0 ; is there a table?
|
||
BNE.S hasTable ; if yes, recycle it (clear counter)
|
||
MOVE.L #kDocTableDefSize,D0 ; doc ID table size
|
||
_NewPtr ,sys ,clear ; from system heap
|
||
BEQ.S newTable ; OK ->
|
||
MOVE.W #memFullErr,D0 ; set error code
|
||
BRA.S cleanSPExit ; no memory, sorry
|
||
|
||
newTable
|
||
MOVE.W #kDefTableEntryN,docTableEntryN(A0) ; total entry number of the table
|
||
MOVE.L A0,psnDocsTablePtr(A1) ; save the table in PSN record
|
||
hasTable
|
||
CLR.W docIDCount(A0) ; clear counter
|
||
|
||
;; Inform Process Manager that this application is TSM aware ...
|
||
LEA psnHighID(A1),A0 ; PSN addr
|
||
CLR.W -(SP) ; room for result
|
||
MOVE.L A0,-(SP) ; PSN
|
||
MOVE.W #$FFFF,-(SP) ; flag = true
|
||
_InlineAware
|
||
ADDA.W #2,SP ; ignore error
|
||
|
||
MOVEQ #0,D0 ; return no error
|
||
|
||
ret
|
||
MOVE.W D0,4(SP) ; return error in Pascal style
|
||
RTS
|
||
|
||
noProcess
|
||
MOVE.W #tsmNotAnAppErr,D0
|
||
cleanSPExit
|
||
LEA 8(SP),SP ; reset sp (for PSN record)
|
||
BRA.S ret
|
||
registered
|
||
MOVE.W #tsmAlreadyRegisteredErr,D0
|
||
BRA.S cleanSPExit
|
||
|
||
|
||
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
; Function: getFreePSNEntry
|
||
; Internal routine called by xInitTSMAwareApplication only.
|
||
; Output: A1.L = pointer to PSN record if D0 = 0,
|
||
; D0.W = noErr if found one free slot
|
||
; ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
||
|
||
getFreePSNEntry ; private routine
|
||
|
||
MOVEA.L ExpandMem,A0
|
||
MOVEA.L ExpandMemRec.emTSMGlobals(A0),A0 ; get TSM global in A0
|
||
MOVEA.L TSMVarsRec.tsmIAPSNTablePtr(A0),A0 ; get PSN table
|
||
MOVE.W iaAppCount(A0),D0 ; D0.W = total apps registered
|
||
MOVE.W iaTotalPSNEntryN(A0),D1 ; D1.W = total entries
|
||
CMP.W D1,D0 ; any free slot?
|
||
BHS.S @full ; no
|
||
@again
|
||
LEA iaPSNStart(A0),A1 ; A1 = first PSN record
|
||
|
||
@tryNext
|
||
TST.L psnHighID(A1) ; is this free?
|
||
BNE.S @4 ; No
|
||
TST.L psnLowID(A1) ; is this free?
|
||
BEQ.S @foundOne ; yes, both slots are zero
|
||
@4
|
||
ADDA.W #kPSNEntrySize,A1 ; points to the next one
|
||
BRA.S @tryNext
|
||
|
||
@foundOne ADD.W #1,iaAppCount(A0) ; bump app counter
|
||
MOVEQ #0,D0 ; no error
|
||
RTS
|
||
|
||
@full ;; all full, need to grow the array
|
||
|
||
;; PSN table is full, (too many TSM aware application? Good !!!), need to grow the table ...
|
||
|
||
MOVEA.L A0,A1 ; A1 = old PSN table
|
||
ADDQ #kDefTableEntryN,D1 ; increment total entry
|
||
MOVE.L D1,D0
|
||
LSL.L #kLog2PSNEntrySize,D0 ; total bytes
|
||
ADD.L #iaPSNStart,D0 ; plus header = new size to allocate
|
||
_NewPtr ,sys ,clear ; allocate a larger table from system heap
|
||
BNE.S @noMem ; no memory, we are in trouble
|
||
|
||
;; A0 = new PSN table, A1 = old PSN table, D1 = new total entry.
|
||
MOVE.W iaTotalPSNEntryN(A1),D0 ; D0.W = original total entries
|
||
LSL.L #kLog2PSNEntrySize,D0 ; convert to bytes
|
||
ADD.L #iaPSNStart,D0 ; plus header = old size to copy
|
||
EXG A1,A0 ; A0 is the source
|
||
_BlockMove ; copy A0 => A1
|
||
|
||
;; A0 is the old table, we can release it now ...
|
||
_DisposePtr ; free mem
|
||
|
||
MOVEA.L ExpandMem,A0 ; we come here when buffer is full
|
||
MOVEA.L ExpandMemRec.emTSMGlobals(A0),A0 ; get TSM global in A0
|
||
MOVE.L A1,TSMVarsRec.tsmIAPSNTablePtr(A0) ; save new table in TSM global
|
||
MOVE.W D1,iaTotalPSNEntryN(A1) ; update (NEW) total entries
|
||
EXG A1,A0 ; A0 is now the new PSN table
|
||
BRA.S @again ; try again
|
||
@noMem
|
||
MOVE.W #memFullErr,D0 ; return error
|
||
RTS
|
||
|
||
ENDWITH
|
||
ENDP ; xInitTSMAwareApplication END
|
||
|
||
|
||
|
||
; _________________________________________________________________________
|
||
; Function: OSErr utaRecordDocumentID(aHandle, &PSNRecord)
|
||
; Internal C routine --
|
||
; Record the document ID in PSN table for the application.
|
||
; Each application keeps track of all open document IDs.
|
||
; Called by 'xNewTSMDocument'.
|
||
; Output: noErr = no error
|
||
; Register usage: Use D0,D1,A0,A1
|
||
;
|
||
; Side effect:
|
||
; Grow the document table if it is full.
|
||
; _________________________________________________________________________
|
||
|
||
utaRecordDocumentID PROC EXPORT
|
||
IMPORT utaTSMAwareApplicationP
|
||
WITH PSNRecord
|
||
; 0(SP) -> return addr
|
||
docIDParam equ 4 ; 4(SP) -> aHandle = valid document ID
|
||
psnParam equ 8 ; 8(SP) -> ptr(PSNRecord)
|
||
|
||
|
||
MOVEA.L psnParam(SP),A0 ; A0 = ptr(PSNRecord)
|
||
MOVE.L highLongOfPSN(A0),D0 ; get high half of PSN
|
||
MOVE.L lowLongOfPSN(A0),D1 ; get low half of PSN
|
||
BSR utaTSMAwareApplicationP ; is it already registered?
|
||
BEQ.S @notAwareReturn ; no, it is not TSM aware? !!
|
||
@1
|
||
;; It is registered, A1 = ptr(PSNRecord) ...
|
||
MOVE.L psnDocsTablePtr(A1),D0 ; D0 = ptr(doc ID table)
|
||
BEQ.S @notAwareReturn ; if no table
|
||
MOVEA.L D0,A0
|
||
MOVE.W docIDCount(A0),D0 ; D0.W = total ID recorded
|
||
MOVE.W docTableEntryN(A0),D1 ; D1.W = total entries
|
||
CMP.W D1,D0 ; any free slot?
|
||
BHS.S @full ; no
|
||
LEA docIDStart(A0),A1 ; A1 = first ID
|
||
@loop
|
||
TST.L (A1)+ ; is this slot free?
|
||
BNE.S @loop ; no
|
||
|
||
MOVE.L docIDParam(SP),-(A1) ; save the ID in the free slot
|
||
ADD.W #1,docIDCount(A0) ; increment count
|
||
MOVEQ #0,D0 ; OK
|
||
@Exit
|
||
RTS
|
||
|
||
@notAwareReturn
|
||
MOVE.W #tsmNeverRegisteredErr,D0 ; return error
|
||
BRA.S @Exit
|
||
|
||
|
||
|
||
@full ; all full, need to grow the array
|
||
;; document table is full, need to grow the table ...
|
||
|
||
ADDQ #kDefTableEntryN,D1 ; increment total entry
|
||
MOVE.L D1,D0
|
||
LSL.L #kLog2DocEntrySize,D0 ; entry * 4
|
||
ADD.L #docIDStart,D0 ; plus header
|
||
_NewPtr ,sys ,clear ; allocate a larger table from system heap
|
||
BNE.S @noMem ; no memory, it's OK
|
||
;; A0 = new doc table, A1 = ptr(PSNRecord), D0.L = new table size, D1 = new total entry.
|
||
MOVE.L A2,-(SP) ; free A2
|
||
MOVEA.L A1,A2 ; A2 = ptr(PSNRecord)
|
||
MOVE.L psnDocsTablePtr(A2),A1 ; A1 = ptr(old table)
|
||
MOVE.L A0,psnDocsTablePtr(A2) ; save the new table
|
||
|
||
;; A0 = new doc table, A1 = old doc table,
|
||
MOVE.W docTableEntryN(A1),D0 ; D0.W = original total entries
|
||
LSL.L #kLog2DocEntrySize,D0 ; entry * 4
|
||
ADD.L #docIDStart,D0 ; plus header
|
||
EXG A1,A0 ; A0 is the source
|
||
_BlockMove ; copy A0 => A1
|
||
|
||
;; A0 is the old table, we can release it now ...
|
||
_DisposePtr ; free mem
|
||
|
||
MOVE.W D1,docTableEntryN(A1) ; update (NEW) total entries
|
||
MOVEA.L A2,A1 ; A1 = ptr(PSNRecord)
|
||
MOVEA.L (SP)+,A2 ; restore A2
|
||
BRA.S @1 ; try again
|
||
@noMem
|
||
MOVE.W #memFullErr,D0 ; return error
|
||
RTS
|
||
|
||
ENDWITH
|
||
ENDP ; utaRecordDocumentID END
|
||
|
||
|
||
; _________________________________________________________________________
|
||
; Function: OSErr utaRemoveDocumentID(handle, countPtr, psnRecordPtr);
|
||
; Internal routine -- Remove the document ID in process's doc ID table.
|
||
; Called by 'xDeleteTSMDocument' only.
|
||
; The caller of this routine should close all open text services!
|
||
; Input: Handle is a valid document ID
|
||
; Output: count = number of TSM documents remained
|
||
; psnRecordPtr = psn Record Ptr (meaningful only if count = 0)
|
||
; Register usage: Use D0,D1,A0,A1
|
||
; C calling convention .....
|
||
; _________________________________________________________________________
|
||
|
||
; 0(SP) -> return addr
|
||
; 4(SP) -> handle (ID)
|
||
; 8(SP) -> ptr(short) ; count
|
||
;12(SP) -> ptr(psn record) ; meaningful only if count = 0 !!!!!!!!!!!!!
|
||
|
||
utaRemoveDocumentID PROC EXPORT
|
||
IMPORT utaTSMAwareApplicationP
|
||
WITH PSNRecord, TSMDocumentRecord
|
||
|
||
MOVEA.L 4(SP),A0 ; A0 = handle
|
||
MOVEA.L (A0),A0 ; A0 = doc ID pointer
|
||
MOVE.L iDocPSNID1(A0),D0 ; get high half of PSN
|
||
MOVE.L iDocPSNID2(A0),D1 ; get low half of PSN
|
||
BSR utaTSMAwareApplicationP ; is it already registered?
|
||
BEQ.S @err ; no, it is not TSM aware? !!
|
||
|
||
;; It is registered, A1 = ptr(PSNRecord) ...
|
||
MOVE.L psnDocsTablePtr(A1),D0 ; D0 = ptr(doc ID table)
|
||
BEQ.S @err ; if no table
|
||
MOVEA.L D0,A0 ; A0 = ptr(doc ID table)
|
||
MOVE.W docIDCount(A0),D0 ; D0.W = total ID recorded
|
||
BEQ.S @stackOK ; br if empty (A1 = ptr(PSNRecord))
|
||
|
||
MOVE.L A1,-(SP) ; save ptr
|
||
MOVE.W docTableEntryN(A0),D0 ; D0.W = total entry
|
||
LEA docIDStart(A0),A1 ; A1 = first ID
|
||
MOVE.L 8(SP),D1 ; D1 = document ID to delete
|
||
@loop
|
||
TST.W D0 ; more to search?
|
||
BLE.S @notFound ; no (should never happen)
|
||
SUBQ #1,D0 ; one less to search
|
||
CMP.L (A1)+,D1 ; is this the one?
|
||
BNE.S @loop ; no
|
||
|
||
CLR.L -(A1) ; found, clear it
|
||
SUB.W #1,docIDCount(A0) ; decrement count
|
||
MOVEA.L (SP)+,A1 ; A1 = ptr(PSNRecord)
|
||
|
||
@stackOK
|
||
MOVE.W docIDCount(A0),D0 ; D0.W = total ID recorded
|
||
MOVEA.L 8(SP),A0 ; A0 = ptr to short
|
||
MOVE.W D0,(A0) ; return count remaining
|
||
MOVEA.L 12(SP),A0 ; A0 = ptr to psn record
|
||
MOVE.L A1,(A0) ; return psn record ptr
|
||
MOVEQ #0,D0 ; perfect
|
||
RTS
|
||
|
||
@notFound
|
||
ADDQ.W #4,SP ; pop ptr
|
||
@err
|
||
MOVE.W #tsmNeverRegisteredErr,D0 ; not TSM aware
|
||
RTS
|
||
|
||
ENDWITH
|
||
ENDP ; utaRemoveDocumentID END
|
||
|
||
|
||
; _____________________________________________________________________________________
|
||
; Function: OSErr utaUpdateAppFlagInPSNTable(&PSNRecord, useFloatWindowP);
|
||
; Internal routine -- update the 'psnAppUseInputWindowP' flag in the PSN table.
|
||
; Called by 'xActivateTSMDocument', and 'xUseInputWindow'.
|
||
; Input: Handle is a valid document ID
|
||
; Output: none
|
||
; Register usage: Use D0,D1,D2,A0,A1
|
||
; Modification history:
|
||
; 20May92 KST A boolean passed in by C compiler is 4 bytes !! When xUseInputWindow
|
||
; calls this routine and pass us the Boolean flag, I used MOVE.B to get
|
||
; the flag, which got garbage from the stack. <#35>
|
||
; _____________________________________________________________________________________
|
||
|
||
utaUpdateAppFlagInPSNTable PROC EXPORT
|
||
IMPORT utaTSMAwareApplicationP
|
||
WITH PSNRecord
|
||
|
||
; 0(SP) -> return addr
|
||
psnParam equ 4 ; 4(SP) -> ptr(PSNRecord)
|
||
useFWParam equ 8 ; 8(SP) -> useFloatWindow flag
|
||
|
||
|
||
MOVEA.L psnParam(SP),A0 ; A0 = ptr(PSNRecord)
|
||
MOVE.L highLongOfPSN(A0),D0 ; get high half of PSN
|
||
MOVE.L lowLongOfPSN(A0),D1 ; get low half of PSN
|
||
|
||
BSR utaTSMAwareApplicationP ; is it already registered?
|
||
BEQ.S @neverRegister ; no, it is not TSM aware? !!
|
||
|
||
;; It is registered, A1 = ptr(PSNRecord) ...
|
||
MOVE.L useFWParam(SP),D2 ; get flag with .L <#35>
|
||
MOVE.B D2,psnAppUseInputWindowP(A1); change the APP. flag in PSN record
|
||
|
||
MOVE.W #$FFFF,D0 ; true (inline aware)
|
||
TST.W psnDoWeReallyUseIW(A1) ; is the document using input window?
|
||
BEQ.S @3 ; no (inline aware)
|
||
MOVEQ #0,D0 ; D0 = false (not inline aware)
|
||
|
||
@3
|
||
;; Inform Process Manager that this application is TSM aware or not...
|
||
MOVEA.L psnParam(SP),A0 ; A0 = ptr(PSNRecord)
|
||
CLR.W -(SP) ; room for result
|
||
MOVE.L A0,-(SP) ; PSN
|
||
MOVE.B D0,-(SP) ; Boolean flag
|
||
_InlineAware
|
||
ADDA.W #2,SP
|
||
MOVEQ #0,D0 ; no error
|
||
@5
|
||
RTS
|
||
@neverRegister
|
||
MOVE.W #tsmNeverRegisteredErr,D0 ; not TSM aware
|
||
BRA.S @5
|
||
|
||
ENDWITH
|
||
ENDP ; utaUpdateAppFlagInPSNTable END
|
||
|
||
|
||
|
||
; _________________________________________________________________________
|
||
; Function: void utaUpdateDocFlagInPSNTable(idocID);
|
||
; Internal routine -- update the 'psnDocUseInputWindowP' flag in the PSN table.
|
||
; Called by 'xActivateTSMDocument', and 'xUseInputWindow'.
|
||
; Input: Handle is a valid document ID
|
||
; Output: none
|
||
; Register usage: Use D0,D1,D2,A0,A1
|
||
; _________________________________________________________________________
|
||
|
||
; 0(SP) -> return addr
|
||
; 4(SP) -> handle (ID)
|
||
|
||
utaUpdateDocFlagInPSNTable PROC EXPORT
|
||
IMPORT utaTSMAwareApplicationP
|
||
WITH PSNRecord, TSMDocumentRecord
|
||
|
||
MOVEA.L 4(SP),A0 ; A0 = handle
|
||
MOVEA.L (A0),A0 ; A0 = doc ID pointer
|
||
MOVE.L iDocPSNID1(A0),D0 ; get high half of PSN
|
||
MOVE.L iDocPSNID2(A0),D1 ; get low half of PSN
|
||
MOVE.B iDocUseInputWindowP(A0),D2 ; get flag when we dereferenced the handle
|
||
|
||
BSR utaTSMAwareApplicationP ; is it already registered ? (D2 preserved)
|
||
BEQ.S @8 ; no, it is not TSM aware? !!
|
||
|
||
;; It is registered, A1 = ptr(PSNRecord), D2.B = flag ...
|
||
MOVE.B D2,psnDocUseInputWindowP(A1); change the doc falg in PSN record
|
||
|
||
MOVE.W #$FFFF,D0 ; true (inline aware)
|
||
TST.W psnDoWeReallyUseIW(A1) ; is the document using input window?
|
||
BEQ.S @3 ; no (inline aware)
|
||
MOVEQ #0,D0 ; D0 = false (not inline aware)
|
||
|
||
@3
|
||
;; Inform Process Manager that this application is TSM aware or not...
|
||
LEA psnHighID(A1),A0 ; PSN addr
|
||
CLR.W -(SP) ; room for result
|
||
MOVE.L A0,-(SP) ; PSN
|
||
MOVE.B D0,-(SP) ; Boolean flag
|
||
_InlineAware
|
||
ADDA.W #2,SP
|
||
MOVEQ #0,D0 ; no error
|
||
|
||
@8 RTS
|
||
|
||
ENDWITH
|
||
ENDP ; utaUpdateDocFlagInPSNTable END
|
||
|
||
|
||
|
||
; _________________________________________________________________________
|
||
; Function: utaTSMAwareApplicationP
|
||
; Internal routine -- Verify if the application is TSM aware.
|
||
; Input: D0.L = high half of PSN. (I don't believe we've designed PSN as 8 bytes !!!)
|
||
; D1.L = low half of PSN
|
||
; Output: D0.W = true (non-zero) if the app is TSM aware, A1 = ptr(PSNRecord)
|
||
; D0.W = false (zero) if the app is not TSM aware.
|
||
; and condition code set.
|
||
; Register usage: Use D0,D1,A0,A1. D2 must be preserved.
|
||
;
|
||
; Side Effect: If D0 = true, return pointer to my internal PSN record in A1
|
||
; _________________________________________________________________________
|
||
utaTSMAwareApplicationP PROC EXPORT
|
||
WITH PSNRecord
|
||
|
||
|
||
MOVE.L D3,-(SP) ; free D3
|
||
|
||
;; make sure PSN is not 0 ...
|
||
MOVE.L D0,D3
|
||
OR.L D1,D3 ; valid PSN
|
||
BEQ.S @tsmAwareExit ; no, both id are 0
|
||
|
||
MOVEA.L ExpandMem,A0
|
||
MOVEA.L ExpandMemRec.emTSMGlobals(A0),A0 ; get TSM global in A0
|
||
MOVEA.L TSMVarsRec.tsmIAPSNTablePtr(A0),A0 ; get PSN table
|
||
MOVEQ #0,D3
|
||
MOVE.W iaAppCount(A0),D3 ; D3.W = total apps registered
|
||
BEQ.S @notFound ; none
|
||
MOVE.W iaTotalPSNEntryN(A0),D3 ; D3.L = total entries
|
||
BEQ.S @notFound ; should not happen, just in case
|
||
LEA iaPSNStart(A0),A1 ; A1 = first PSN record
|
||
SUBQ #1,D3
|
||
@loop
|
||
CMP.L psnHighID(A1),D0 ; same id?
|
||
BNE.S @5 ; no
|
||
CMP.L psnLowID(A1),D1 ; same id?
|
||
BEQ.S @found ; yes
|
||
|
||
@5
|
||
ADDA.W #kPSNEntrySize,A1 ; points to the next one
|
||
DBRA D3,@loop ; no array overflow check
|
||
@notFound
|
||
MOVEQ #0,D0 ; not TSM aware
|
||
@tsmAwareExit
|
||
MOVE.L (SP)+,D3 ; restore D3
|
||
TST.W D0 ; set CCR
|
||
RTS
|
||
|
||
@found
|
||
MOVEQ #1,D0 ; TSM aware
|
||
|
||
IF TSMDebug THEN
|
||
CMP.W #kPSNTableSignature,psnTableSignature(A1) ; valid table?
|
||
BEQ.S @20 ; yes
|
||
_debugger
|
||
@20
|
||
ENDIF
|
||
|
||
BRA.S @tsmAwareExit
|
||
ENDWITH
|
||
|
||
ENDP ; utaTSMAwareApplicationP
|
||
|
||
|
||
|
||
; _____________________________________________________________________________________________
|
||
; Function: xCloseTSMAwareApplication()
|
||
; Application deregisters itself when quit.
|
||
; Input: ProcessSerialNumberPtr.
|
||
; Output: D0.W = error code (memFullErr, tsmNotAnAppErr, openDocumentsErr)
|
||
; Register usage: Use D0,D1,A0,A1
|
||
;
|
||
; •• Note: xCloseTSMAwareApplication can't close the application if there is any document open.
|
||
; utKillTSMAwareApplication will close the document and then close the application.
|
||
;
|
||
; •• utCloseAppCommon code is shared by InformTSM's @KillTSMApp.
|
||
; Do not change the calling convention without changing @KillTSMApp !!
|
||
; _____________________________________________________________________________________________
|
||
XCLOSETSMAWAREAPPLICATION PROC EXPORT
|
||
IMPORT utaTSMAwareApplicationP, utDeleteCleanUpTSMDocument
|
||
EXPORT utCloseAppCommon
|
||
WITH PSNRecord
|
||
|
||
;; Verify if we have registered this application ...
|
||
SUBA.W #10,SP ; allocate storage for PSN (8 bytes) and result
|
||
PEA 2(SP) ; push address of PSN storage
|
||
_GetSystemClientProcess ; get PSN with which to associate the file
|
||
MOVE.W (SP)+,D0 ; on error, PSN == kNoProcess
|
||
BNE.W closeRet ; punt
|
||
MOVEQ #0,D2 ; clear flag (no force close)
|
||
|
||
utCloseAppCommon ; shared by utKillTSMAwareApplication
|
||
;; If you change the stack frame for this code, be sure to change utKillTSMAwareApplication
|
||
;; If D2 <> 0, then force to close all documents and exit. (called from InformTSM).
|
||
;; If D2 == 0 and there is open document, then return error.
|
||
;; Verify if we have registered this app already ...
|
||
|
||
MOVE.L 0(SP),D0 ; get high half of PSN
|
||
MOVE.L 4(SP),D1 ; get low half of PSN
|
||
BSR utaTSMAwareApplicationP ; is it already registered?
|
||
BEQ.S @notTSMaware ; no, it is not TSM aware
|
||
|
||
;; It is registered, A1 = ptr(PSNRecord) ...
|
||
|
||
MOVE.L psnDocsTablePtr(A1),D0 ; get document ID table
|
||
BEQ.S @docsClosed ; stop if nil
|
||
MOVEA.L D0,A0 ; A0 = document ID table
|
||
MOVE.W docIDCount(A0),D0 ; any open document?
|
||
BEQ.S @docsClosed ; no, OK =>
|
||
TST.W D2 ; is this a force close?
|
||
BEQ.S docsOpenErr ; no, can't continue
|
||
|
||
;; This is a force close but there is open document, so let's close the documents for the app.
|
||
;; D2 is free register now ...
|
||
MOVE.L A1,-(SP) ; save PSNRecord pointer
|
||
MOVEQ #0,D0 ; clear 32 bits
|
||
MOVE.W docTableEntryN(A0),D0 ; total number of entry
|
||
SUBQ #1,D0 ; for DBRAing
|
||
LEA docIDStart(A0),A0 ; A0 = points to the first ID
|
||
|
||
@loop ;; need to preserve A0/D0
|
||
MOVE.L (A0)+,D1 ; D1 = doc ID
|
||
BEQ.S @1 ; empty
|
||
|
||
CLR.L -4(A0) ; clear the table entry too
|
||
MOVEM.L D0/A0,-(SP) ; save D0/A0 across the call
|
||
|
||
MOVE.L D1,-(SP) ; push parameter -> ID
|
||
JSR utDeleteCleanUpTSMDocument ; delete and clean up the document <#47>
|
||
ADDA.W #4,SP ; pop param
|
||
|
||
MOVEM.L (SP)+,D0/A0 ; restore D0/A0
|
||
@1 DBRA D0,@loop
|
||
|
||
MOVEA.L (SP)+,A1 ; restore PSNRecord pointer
|
||
MOVEA.L psnDocsTablePtr(A1),A0 ; A0 = document ID table
|
||
;; the document ID table is not released, we just clear the counter for re-use
|
||
MOVE.W #0,docIDCount(A0) ; clear counter, all closed
|
||
@docsClosed
|
||
|
||
CLR.L psnHighID(A1) ; mark this PSN slot to be free
|
||
CLR.L psnLowID(A1)
|
||
CLR.L psnAppUseInputWindowP(A1) ; clear UseInputWindow flags so it will not be reused <#48>
|
||
|
||
MOVEA.L ExpandMem,A0
|
||
MOVEA.L ExpandMemRec.emTSMGlobals(A0),A0 ; get TSM global in A0
|
||
MOVEA.L TSMVarsRec.tsmIAPSNTablePtr(A0),A0 ; get PSN table
|
||
SUB.W #1,iaAppCount(A0) ; decrease app counter
|
||
|
||
;; now, inform Process Manager that this process is not TSM aware any more ....
|
||
|
||
CLR.W -(SP) ; room for result
|
||
PEA 2(SP) ; PSN
|
||
CLR.W -(SP) ; flag = flase
|
||
_InlineAware ; not aware
|
||
ADDA.W #2,SP ; ignore error
|
||
|
||
MOVEQ #0,D0 ; return no error
|
||
BRA.S closeRet
|
||
|
||
@notTSMaware
|
||
MOVE.W #tsmNeverRegisteredErr,D0 ; return error
|
||
BRA.S closeRet
|
||
|
||
docsOpenErr ; can't close because there is open documents
|
||
MOVE.W #tsmDocumentOpenErr,D0 ; return error
|
||
closeRet
|
||
LEA 8(SP),SP ; restore sp
|
||
MOVE.W D0,4(SP) ; return error in Pascal style
|
||
RTS
|
||
ENDWITH
|
||
|
||
ENDP ; XCLOSETSMAWAREAPPLICATION END
|
||
|
||
|
||
; _______________________________________________________________________________
|
||
; Function: pascal OSErr utaGetTSMAwareDocTable(ProcessSerialNumberPtr, docTablePtr)
|
||
; Verify if the application is TSM aware.
|
||
; If the USEINPUTWINDOW flag is set, we treat the app as non-TSM aware!
|
||
; If the app is TSM aware, then return its document table pointer in docTablePtr.
|
||
; If error, then docTablePtr has undefined value.
|
||
; Input: ProcessSerialNumberPtr.
|
||
; docTablePtr = pointer to docTable.
|
||
; Output: D0.W = error code (memFullErr, temNeverRegisteredErr, tsmUseInputWindowErr),
|
||
; D0.W = noErr if it is TSM aware.
|
||
; Register usage: Use D0,D1,A0,A1
|
||
; _______________________________________________________________________________
|
||
UTAGETTSMAWAREDOCTABLE PROC EXPORT
|
||
Import UTAISAPPTSMAWAREANDNOTUSINGIW
|
||
WITH PSNRecord
|
||
|
||
MOVEA.L 8(SP),A1 ; get ProcessSerialNumberPtr
|
||
CLR.W -(SP)
|
||
MOVE.L A1,-(SP) ; push ProcessSerialNumberPtr
|
||
JSR UTAISAPPTSMAWAREANDNOTUSINGIW ; get doc table ptr
|
||
MOVE.W (SP)+,D0 ; is it TSM aware or use input window?
|
||
BNE.S @5 ; no
|
||
MOVEA.L 4(SP),A0 ; get pointer to docTable
|
||
MOVE.L psnDocsTablePtr(A1),(A0) ; return docTable
|
||
|
||
@5
|
||
MOVEA.L (SP)+,A0 ; get return address
|
||
LEA 8(SP),SP ; restore sp
|
||
MOVE.W D0,(SP) ; return error in Pascal style
|
||
JMP (A0)
|
||
|
||
ENDWITH
|
||
ENDP
|
||
|
||
|
||
|
||
|
||
; _______________________________________________________________________________
|
||
; Function: utaGetTSMAppRecordPtr(ProcessSerialNumber *PSNRecord, TSMAppsRecord **appRecordPtr);
|
||
; Verify if the application is TSM aware.
|
||
; If the USEINPUTWINDOW flag is set, we treat the app as non-TSM aware!
|
||
; If the app is TSM aware, then return its document table pointer in docTablePtr.
|
||
; If error, then docTablePtr has undefined value.
|
||
; Input: ProcessSerialNumberPtr.
|
||
; docTablePtr = pointer to docTable.
|
||
; Output: D0.W = error code (memFullErr, temNeverRegisteredErr, tsmUseInputWindowErr),
|
||
; D0.W = noErr if it is TSM aware.
|
||
; Register usage: Use D0,D1,A0,A1
|
||
; _______________________________________________________________________________
|
||
UTAGETTSMAPPRECORDPTR PROC EXPORT
|
||
Import utaTSMAwareApplicationP
|
||
WITH PSNRecord
|
||
|
||
MOVEA.L 8(SP),A1 ; get ProcessSerialNumberPtr
|
||
MOVE.L highLongOfPSN(A1),D0 ; get high half of PSN
|
||
MOVE.L lowLongOfPSN(A1),D1 ; get low half of PSN
|
||
BSR utaTSMAwareApplicationP ; is it already registered?
|
||
BEQ.S @5 ; no, it is not TSM aware
|
||
|
||
MOVEA.L 4(SP),A0 ; get pointer to psn record
|
||
MOVE.L A1,(A0) ; return record
|
||
MOVEQ #0,D0 ; return noErr
|
||
@return
|
||
MOVEA.L (SP)+,A0 ; get return address
|
||
LEA 8(SP),SP ; restore sp
|
||
MOVE.W D0,(SP) ; return error in Pascal style
|
||
JMP (A0)
|
||
|
||
|
||
@5
|
||
MOVE.W #tsmNeverRegisteredErr,D0 ; return error
|
||
BRA.S @return
|
||
|
||
ENDWITH
|
||
ENDP
|
||
|
||
|
||
|
||
|
||
; _______________________________________________________________________________
|
||
; Function: pascal OSErr utaGetAppsUseInputWindowFlag(ProcessSerialNumberPtr, booleanPtr)
|
||
; Verify if the application is TSM aware.
|
||
; If the USEINPUTWINDOW flag is set, we treat the app as non-TSM aware!
|
||
; Input: ProcessSerialNumberPtr.
|
||
; Output: D0.W = error code (memFullErr, temNeverRegisteredErr, tsmUseInputWindowErr),
|
||
; D0.W = noErr if it is TSM aware and not using input window.
|
||
; A1.L = ptr(PSNRecord table entry)
|
||
; Register usage: Use D0,D1,A0,A1
|
||
; _______________________________________________________________________________
|
||
UTAGETAPPSUSEINPUTWINDOWFLAG PROC EXPORT
|
||
Import utaTSMAwareApplicationP
|
||
|
||
retaddr equ 0
|
||
booleanPtr equ 4
|
||
psnPtr equ 8
|
||
|
||
|
||
MOVEA.L psnPtr(SP),A1 ; get ProcessSerialNumberPtr
|
||
MOVE.L highLongOfPSN(A1),D0 ; get high half of PSN
|
||
MOVE.L lowLongOfPSN(A1),D1 ; get low half of PSN
|
||
BSR utaTSMAwareApplicationP ; is it already registered?
|
||
BEQ.S @5 ; no, it is not TSM aware
|
||
MOVE.B PSNRecord.psnAppUseInputWindowP(A1),D1; get the byte
|
||
@3
|
||
MOVEQ #0,D0 ; return noErr
|
||
MOVEA.L (SP)+,A0 ; get return address
|
||
MOVEA.L (SP)+,A1 ; get boolean address
|
||
MOVE.B D1,(A1) ; return flag
|
||
MOVE.L A0,(SP) ; remove parameter
|
||
MOVE.W D0,4(SP) ; return error in Pascal style
|
||
RTS
|
||
|
||
@5
|
||
MOVE.W #tsmNeverRegisteredErr,D0 ; return error
|
||
BRA.S @3
|
||
|
||
ENDP
|
||
|
||
|
||
; _______________________________________________________________________________
|
||
; Function: pascal OSErr utaIsAppTSMAwareAndNotUsingIW(ProcessSerialNumberPtr)
|
||
; Verify if the application is TSM aware and use input window or not.
|
||
; If the USEINPUTWINDOW flag is set, we treat the app as non-TSM aware!
|
||
; Input: ProcessSerialNumberPtr.
|
||
; Output: D0.W = error code (memFullErr, temNeverRegisteredErr, tsmUseInputWindowErr),
|
||
; D0.W = tsmUseInputWindowErr means the app is TSM aware !!!!
|
||
; D0.W = noErr if it is TSM aware and not using input window.
|
||
; A1.L = ptr(PSNRecord table entry)
|
||
; Register usage: Use D0,D1,A0,A1
|
||
; _______________________________________________________________________________
|
||
UTAISAPPTSMAWAREANDNOTUSINGIW PROC EXPORT
|
||
Import utaTSMAwareApplicationP
|
||
|
||
;; Verify if we have registered this application ...
|
||
MOVEA.L 4(SP),A1 ; get ProcessSerialNumberPtr
|
||
MOVE.L highLongOfPSN(A1),D0 ; get high half of PSN
|
||
MOVE.L lowLongOfPSN(A1),D1 ; get low half of PSN
|
||
BSR utaTSMAwareApplicationP ; is it already registered?
|
||
BEQ.S @5 ; no, it is not TSM aware
|
||
|
||
;; It is registered, A1 = ptr(PSNRecord)
|
||
TST.W psnDoWeReallyUseIW(A1) ; is the document using input window?
|
||
BNE.S @7 ; yes, if any of the 2 flags is set, return error
|
||
MOVEQ #noErr,D0 ; no error
|
||
@3
|
||
MOVEA.L (SP)+,A0 ; get return address
|
||
MOVE.L A0,(SP) ; remove parameter
|
||
MOVE.W D0,4(SP) ; return error in Pascal style
|
||
RTS
|
||
|
||
@5
|
||
MOVE.W #tsmNeverRegisteredErr,D0 ; return error
|
||
BRA.S @3
|
||
|
||
@7
|
||
MOVE.W #tsmUseInputWindowErr,D0 ; return error
|
||
BRA.S @3
|
||
|
||
|
||
ENDP ; xIsApplicationTSMAware END
|
||
|
||
|
||
; _______________________________________________________________________________
|
||
; Function: pascal OSErr xInformTSM(msgNumber, msgParamPtr)
|
||
; Inform TSM with some messages
|
||
; Input:
|
||
; Output: noErr if all OK
|
||
; Register usage: Use D0,D1,D2,A0,A1
|
||
; Stack frame:
|
||
; SP => 00(SP).L -> return addr
|
||
; 04(SP).L -> msgParamPtr
|
||
; 08(SP).W -> msgSelector
|
||
; 10(SP).W -> msgResult
|
||
; _______________________________________________________________________________
|
||
XINFORMTSM PROC EXPORT
|
||
Import utCloseAppCommon, utChangeToOldJIM, utInformPMgr, utSuspendResumeApp
|
||
|
||
msgParamPtr equ 4
|
||
msgSelector equ 8
|
||
msgResult equ 10
|
||
|
||
|
||
MOVE.W msgSelector(SP),D0 ; get selector
|
||
BEQ @noopExit ; no op
|
||
MOVEA.L msgParamPtr(SP),A1 ; get param ptr(script/id) <06Feb92 #18>
|
||
|
||
CMP.W #kMsgBkgAppsPSN,D0 ; is SWM passing me the PSN?
|
||
BEQ.S @getSWMsPSN ; yes
|
||
CMP.W #kMsgKillTSMApp,D0 ; kill the application?
|
||
BEQ.S @KillTSMApp ; yes
|
||
|
||
CMP.W #kMsgSuspendApp,D0 ; suspend the non-TSM aware application?
|
||
BEQ.S @SuspendApp ; yes
|
||
|
||
CMP.W #kMsgResumeApp,D0 ; resume the non-TSM aware application?
|
||
BEQ.S @ResumeApp ; yes
|
||
|
||
CMP.W #kMsgHelpHELPMgr,D0 ; kMsgHelpHELPMgr?
|
||
BEQ.W @tsmHelpMgrPatch ; yes
|
||
|
||
CMP.W #kMsgChangeToOldJIM,D0 ; change to old JIM
|
||
BNE.W @bad ; no
|
||
|
||
|
||
|
||
; _______________________________________________________________
|
||
; Function: void utChangeToOldJIM()
|
||
; User wants to switch to old input method (for Japanese script only)
|
||
; Input: none
|
||
; A1 = param record pointer
|
||
; Output: noErr if all OK
|
||
; tsmTSNotOpenErr = JIM is not open.
|
||
; _______________________________________________________________
|
||
|
||
MOVE.L A1,-(SP) ; pass the parameter <06Feb92 #18>
|
||
JSR utChangeToOldJIM ; for Japanese script only
|
||
TST.L (SP)+ ; pop param <06Feb92 #18>
|
||
BRA.S @noopExit ; and exit
|
||
|
||
|
||
; _______________________________________________________________
|
||
; Function: void SuspendApp()
|
||
; User wants to switch to old input method (for Japanese script only)
|
||
; Input: none
|
||
; A1 = param record pointer
|
||
; Output: noErr if all OK
|
||
; tsmTSNotOpenErr = JIM is not open.
|
||
; _______________________________________________________________
|
||
@SuspendApp
|
||
MOVE.L #kTSMSuspend,-(SP) ; pass the parameter
|
||
|
||
@SuspendResume
|
||
JSR utSuspendResumeApp ; suspend/resume
|
||
TST.L (SP)+ ; pop param
|
||
BRA.S @noopExit ; and exit
|
||
|
||
@ResumeApp
|
||
MOVE.L #kTSMResume,-(SP) ; pass the parameter
|
||
BRA.S @SuspendResume
|
||
|
||
|
||
|
||
; _______________________________________________________________
|
||
; Function: utKillTSMAwareApplication(ProcessSerialNumberPtr)
|
||
; Called from Patches:MiscPatches.a
|
||
; Input: ProcessSerialNumberPtr.
|
||
; A1 = param record pointer
|
||
; Output: noErr if all OK
|
||
;
|
||
; Modification history:
|
||
; 25Feb92 KST If the app is not TSM aware, we'll send an AE to SWM
|
||
; ask it to close its input window.
|
||
; 27Feb92 KST Set tsmKillApplicationP flag to signal we're killing the
|
||
; TSM aware application, and the menu is already killed !!
|
||
; 27Mar92 KST If the app is not TSM aware, we'll not be called.
|
||
; _______________________________________________________________
|
||
@KillTSMApp
|
||
|
||
;; When 'utCloseAppCommon' is called, it expects D2 is used as a flag,
|
||
;; and the stack frame looks like this:
|
||
;
|
||
; SP --> highLongOfPSN (long)
|
||
; lowLongOfPSN (long)
|
||
; return address (long)
|
||
; (high addr) result (word)
|
||
;
|
||
; •• Do not change this without changing XCLOSETSMAWAREAPPLICATION !!
|
||
|
||
MOVEA.L ExpandMem,A0
|
||
MOVEA.L ExpandMemRec.emTSMGlobals(A0),A0; get TSM global in A0
|
||
ST.B TSMVarsRec.tsmKillApplicationP(A0) ; set flag <#20>
|
||
|
||
MOVEQ #1,D2 ; set flag, force close the app
|
||
SUBA.W #2,SP ; room for result
|
||
PEA @return2Here ; return address
|
||
MOVE.L lowLongOfPSN(A1),D1 ; get low half of PSN
|
||
MOVE.L D1,-(SP) ; push low PSN
|
||
MOVE.L highLongOfPSN(A1),D1 ; get high half of PSN
|
||
MOVE.L D1,-(SP) ; push hign PSN
|
||
JMP utCloseAppCommon ; use common code, D2 is the flag
|
||
@return2Here
|
||
ADDA.W #2,SP ; ignore error
|
||
MOVEA.L ExpandMem,A0
|
||
MOVEA.L ExpandMemRec.emTSMGlobals(A0),A0; get TSM global in A0
|
||
CLR.B TSMVarsRec.tsmKillApplicationP(A0) ; clear flag <#20>
|
||
|
||
MOVEQ #0,D0 ; always success
|
||
BRA.S @noopExit ; and exit
|
||
|
||
; _______________________________________________________________
|
||
; Function: getSWMsPSN(SWM's ProcessSerialNumberPtr)
|
||
; Input: ProcessSerialNumberPtr.
|
||
; A1 = param record pointer
|
||
; Output: noErr if all OK
|
||
; _______________________________________________________________
|
||
@getSWMsPSN
|
||
Import xInitTSMAwareDriver
|
||
|
||
MOVEA.L ExpandMem,A0
|
||
MOVEA.L ExpandMemRec.emTSMGlobals(A0),A0; get TSM global in A0
|
||
MOVE.L highLongOfPSN(A1),D1 ; get high ID
|
||
MOVE.L D1,TSMVarsRec.tsmSWMHighPSN(A0) ; save in TSM global
|
||
MOVE.L lowLongOfPSN(A1),D1 ; get low ID
|
||
MOVE.L D1,TSMVarsRec.tsmSWMLowPSN(A0) ; save in TSM global
|
||
|
||
|
||
JSR utInformPMgr ; set up flag
|
||
|
||
MOVEA.L msgParamPtr(SP),A0 ; get param ptr which points at the PSN
|
||
MOVEA.L (SP),A1 ; get return addr
|
||
SUBQ #2,SP ; get 2 more bytes on the
|
||
MOVE.L highLongOfPSN(A0),highLongOfPSN(SP)
|
||
MOVE.L lowLongOfPSN(A0),lowLongOfPSN(SP)
|
||
MOVE.L A1,8(SP) ; move the return address
|
||
JMP xInitTSMAwareDriver ; return through InitTSMAware
|
||
|
||
|
||
@noopExit ; exit point shared by all InformTSM subfunctions
|
||
|
||
MOVEA.L (SP),A1 ; get return addr
|
||
LEA 10(SP),SP ; pop off params
|
||
MOVE.W D0,(SP) ; result
|
||
JMP (A1) ; return to caller
|
||
|
||
MOVEQ #0,D0 ; always success
|
||
BRA.S @noopExit ; and exit
|
||
|
||
@bad ; bad selector
|
||
MOVE.W #paramErr,D0 ; return error
|
||
BRA.S @noopExit
|
||
|
||
|
||
|
||
|
||
; _______________________________________________________________
|
||
; Function: tsmHelpMgrPatch
|
||
; Input:
|
||
; A1 = param record pointer
|
||
; Output: 1. return noErr if the mouse is over a floating window and,
|
||
; 2. also return that windowptr in tsmHelpWindowPtr, and
|
||
; 3. if the mouse is over content region, we'll try to open the
|
||
; resource file and return the refnum in tsmHelpRefnum.
|
||
; (If the window is a system floating window and refcon <> nil).
|
||
; Side effect:
|
||
; If we return noErr, then tsmHelpWindowPtr must contains a floating window,
|
||
; because Help Manager will later swap the layer to floating layer.
|
||
;
|
||
; (6) parameter for kMsgHelpHELPMgr -- record of 10 bytes:
|
||
; tsmHelpRefnum EQU 0 ; > 0 if we opened IM's resource file
|
||
; tsmHelpWindowPtr EQU 2 ; nil if no floating window
|
||
; tsmHelpSavedLayer EQU 6 ; temp. storage for Help Manager to swap the layer
|
||
; tsmHelpRecSize EQU tsmHelpSavedLayer+4
|
||
; _______________________________________________________________
|
||
@tsmHelpMgrPatch
|
||
MOVEM.L A2/A3,-(SP) ; save A2/A3
|
||
CLR.W tsmHelpRefnum(A1) ; clear Refnum
|
||
CLR.L tsmHelpWindowPtr(A1) ; clear WindowPtr
|
||
MOVEA.L A1,A2 ; A2 = param ptr
|
||
|
||
|
||
SUBQ #2,-(SP) ; room for result
|
||
MOVE.L Mouse,-(SP) ; pass the global mouse on stack
|
||
PEA tsmHelpWindowPtr(A2) ; pass WindowPtr
|
||
_FindServiceWindow
|
||
MOVE.W (SP)+,D0 ; over our window?
|
||
BEQ.S @helpErrReturn ; no
|
||
|
||
CMP.W #inSysWindow,D0 ; in system item, menubar <#46>
|
||
BLE.S @helpErrReturn ; exit if yes, not over a floater <#46>
|
||
|
||
CMP.W #inContent,D0 ; in content?
|
||
BNE.S @windowHasNoInstance ; no, just swap the layer
|
||
|
||
MOVEA.L tsmHelpWindowPtr(A2),A3 ; save the window ptr in A3
|
||
|
||
;; OK, the mouse is over a floating window so open the resource file so that
|
||
;; Help Manager can dig out the Balloon resource ...
|
||
;; But first, let's check if the window is a system floating window and refcon <> nil. <#45>
|
||
;; from here on, we return noErr to indicate the mouse is over a floater ...
|
||
|
||
CMP.W #systemFloatKind,WindowRecord.windowKind(A3) ; is this floater belonging to a text service <#45>
|
||
BNE.S @windowHasNoInstance ; if not, don't try to open its resource file <#45>
|
||
|
||
MOVE.L WindowRecord.refcon(A3),D0 ; is there an Instance?
|
||
BEQ.S @windowHasNoInstance ; if not, then don't try to open anything
|
||
|
||
SUBQ #2,-(SP) ; room for result
|
||
MOVE.L D0,-(SP) ; the Component instance
|
||
;; need special case for SWM
|
||
|
||
_OpenComponentResFile
|
||
MOVE.W (SP)+,D0 ; is it open?
|
||
BLE.S @helpErrReturn ; no
|
||
MOVE.W D0,tsmHelpRefnum(A2) ; return the RefNum
|
||
|
||
@windowHasNoInstance
|
||
MOVEQ #0,D0 ; OK
|
||
BRA.S @helpPopStack
|
||
|
||
@helpErrReturn
|
||
CLR.W tsmHelpRefnum(A2) ; clear Refnum
|
||
CLR.L tsmHelpWindowPtr(A2) ; clear WindowPtr
|
||
MOVE.W #paramErr,D0 ; return error
|
||
|
||
@helpPopStack
|
||
MOVEM.L (SP)+,A2/A3 ; restore A2/A3
|
||
BRA.S @noopExit
|
||
|
||
|
||
|
||
ENDP ; XINFORMTSM END
|
||
|
||
; END InformTSM
|
||
|
||
|
||
|
||
|
||
;; Begin patches ...
|
||
|
||
IF not BuildTSMInit THEN
|
||
|
||
; _______________________________________________________________________________
|
||
; SetCursor Patch
|
||
;
|
||
; Applications such as Finder periodically set the cursor. This is a problem
|
||
; if IM changes the cursor over floating window. The cursor will now flash
|
||
; because 2 parties compete changing the cursor. This patch will temporarily
|
||
; disable the SetCursor call if IM or SWM changed the cursor.
|
||
; _______________________________________________________________________________
|
||
|
||
__SetCursorPatch PatchProc _SetCursor,(Plus,SE,II,Portable,IIci)
|
||
|
||
move.l ExpandMem,a0 ; good old ExpandMem again
|
||
move.l ExpandMemRec.emTSMGlobals(a0),a0 ; our global ptr into a0
|
||
|
||
btst #kIMJustSetCursorBit,TSMVarsRec.tsmPatchFlags(a0) ; should we let SetCursor calls through?
|
||
bne.s @JustRTS ; flag is on nobody can set the cursor until it clears
|
||
|
||
;; kSWMJustSetCursorBit is set in SWM driver ....
|
||
btst #kSWMJustSetCursorBit,TSMVarsRec.tsmPatchFlags(a0) ; should we let SetCursor calls through?
|
||
bne.s @JustRTS ; flag is on nobody can set the cursor until it clears
|
||
|
||
jmpOld ; flag is clear go ahead and set the cursor
|
||
nop ; <sm5>
|
||
@JustRTS
|
||
move.l (sp)+,a0 ; pop return address <32>
|
||
addq #4,sp ; flush the parameter on the stack <32>
|
||
jmp (a0) ; return to the caller. <32>
|
||
|
||
ENDPROC
|
||
|
||
|
||
|
||
|
||
; _______________________________________________________________________________
|
||
; PaintBehind Patch
|
||
; AfterDark redraws the screen with FrontWindow(), and grayrgn. This however,
|
||
; does not draw the floating windows. This patch will paint from IM layer if
|
||
; theWindow = frontwindow, and theRegion = GrayRgn.
|
||
; _______________________________________________________________________________
|
||
|
||
__PaintBehindPatch PatchProc _PaintBehind,(Plus,SE,II,Portable,IIci)
|
||
|
||
theRetAddr EQU 0 ; satck frame for this call
|
||
theRegion EQU 4
|
||
theWindow EQU 8
|
||
|
||
|
||
SUBA.W #4,SP
|
||
_FrontWindow
|
||
MOVE.L (SP)+,D0
|
||
CMP.L theWindow(SP),D0 ; draw from the front window?
|
||
BNE.S @NeverMind ; no
|
||
|
||
MOVEA.L GrayRgn,A0 ; get the GRAY region handle
|
||
MOVEA.L (A0),A0 ; dereference it
|
||
LEA rgnBBox+bottom(A0),A0 ; A0 points to bottom
|
||
MOVEA.L theRegion(SP),A1 ; get the region
|
||
MOVEA.L (A1),A1 ; dereference it
|
||
LEA rgnBBox+top(A1),A1 ; A1 points to top
|
||
|
||
;; Note: Pyro always pass the region with -1, -1, bottom+1, right+1,
|
||
;; and this is why I don't branch with BNE or BEQ ...
|
||
|
||
TST.W (A1)+ ; top should be 0
|
||
BGT.S @NeverMind ; if > 0, then don't do anything special
|
||
TST.W (A1)+ ; left should be 0
|
||
BGT.S @NeverMind ; if > 0, then don't do anything special
|
||
|
||
;; A1 points to bottom of rect
|
||
|
||
MOVE.W (A1)+,D0
|
||
CMP.W (A0)+,D0 ; paint the whole desktop?
|
||
BLT.S @NeverMind ; no
|
||
MOVE.W (A1),D0
|
||
CMP.W (A0),D0 ; paint the whole desktop?
|
||
BLT.S @NeverMind ; no
|
||
|
||
;; Here, we assume the guy is trying to paint the whole screen, let's paint the floating windows too.
|
||
;; Dean said: "Just paint from input method's floating layer". -- (04May92)
|
||
;; I tried paint from the root layer, Balloon window's contents doesn't get redraw anyway.
|
||
|
||
SUBA.W #6,SP
|
||
PEA 2(SP)
|
||
_GetFrontServiceWindow
|
||
MOVE.W (SP)+,D0 ; any error?
|
||
BNE.S @NeverMind ; br if error
|
||
MOVE.L (SP)+,D0 ; get the front floating window
|
||
BEQ.S @NeverMind ; br if no floating window
|
||
MOVE.L D0,theWindow(SP) ; paint from the root
|
||
|
||
@NeverMind
|
||
jmpOld ; flag is clear go ahead and set the cursor
|
||
|
||
|
||
|
||
ENDPROC
|
||
|
||
__SystemMenuPatch PatchProc _SystemMenu,(Plus,SE,II,Portable,IIci)
|
||
import CHANGEMENURESULTFORINPUTMETHOD
|
||
|
||
move.l 4(sp),d0 ;get menuresult
|
||
swap d0 ;make the high word low
|
||
cmp.w #-kTSMSystemMenuID,d0 ;is this us?
|
||
bne.s @NotTSMMenu ;
|
||
swap d0 ;put the high word back
|
||
move.l d0,-(sp) ;move it onto the stack
|
||
pea (sp) ;push the address
|
||
jsr CHANGEMENURESULTFORINPUTMETHOD ;and send it to the input method
|
||
addq #4,sp ;get rid of space for menuresult
|
||
rts ;return to caller
|
||
@NotTSMMenu
|
||
jmpOld ;not ours so forget about it
|
||
|
||
ENDPROC
|
||
|
||
|
||
|
||
; ____________________________________________________________________________________
|
||
; __HMGetBalloonPatch Patch
|
||
; Again, applications such as Finder periodically redraw the Help balloon. This is
|
||
; a problem if there is a help balloon over the floating window. The balloon window
|
||
; will flash because app tries to remove the Balloon and paint one of its own.
|
||
; Trashes D0/A0/A1 -- these are free registers, right?
|
||
; ____________________________________________________________________________________
|
||
|
||
__HMGetBalloonPatch PatchProc _Pack14,(Plus,SE,II,Portable,IIci)
|
||
|
||
cmp.w #kHMGetBalloons,d0 ; is this IsBalloon?
|
||
beq.s @DoGetBalloonPatch ; yes so do it
|
||
nop ; <sm5>
|
||
jmpOld ; it wasn't kHMIsBalloon so call the real Pack14
|
||
|
||
@DoGetBalloonPatch
|
||
|
||
subq #2,sp ; room on the stack
|
||
jsrOld ; and jump to the old one
|
||
move.b (sp)+,d0 ; get resut
|
||
move.b d0,4(sp) ; and put in on the stack
|
||
beq.s @returnOldResult ; no balloon, so return the result to original caller
|
||
|
||
;
|
||
; OK so a ballon is up see if the last window we helped was a floating window
|
||
; we do that by getting the parent of the last window helped
|
||
; and seeing if that parent equals the IMlayer. This patch is for Finder because
|
||
; Finder does not know/care the floating window and draw its own Balloon.
|
||
;
|
||
|
||
; Now check if we are clicked inside of a floating window ... <#44>
|
||
|
||
SUBQ #6,SP ; room for result
|
||
MOVE.L Mouse,-(SP) ; pass the global mouse on stack
|
||
PEA 6(SP) ; pass WindowPtr
|
||
_FindServiceWindow
|
||
MOVE.W (SP)+,D0 ; over our window?
|
||
ADDQ.W #4,SP ; restore the stack
|
||
BEQ.S @returnOldResult ; no
|
||
|
||
CMP.W #inSysWindow,D0 ; in system item, menubar? <#39>
|
||
BLE.S @returnOldResult ; exit if yes, return the original result <#39>
|
||
|
||
MOVEA.L ExpandMem,A1 ; A1 = ExpandMem <#44>
|
||
MOVE.L ExpandMemRec.emTSMGlobals(A1),D0 ; get TSM global <#44>
|
||
BEQ.S @noTSM ; br if no TSM <#44>
|
||
MOVEA.L D0,A0 ; A0 = TSM global <#44>
|
||
|
||
;; If we are inside of PopUpMenuSelect, then say the balloon is on so that a previous balloon will be removed correctly.
|
||
BTST #kInTSMPopUpMenuSelectCall,TSMVarsRec.tsmPatchFlags(A0) ; are we in PopUpMenuSelect? <#44>
|
||
BNE.S @returnOldResult ; flag is on so return the original result <#44>
|
||
|
||
@noTSM
|
||
;; If we are inside of MenuSelect, then say the balloon is on so that a previous balloon will be removed correctly.
|
||
;; Note Help Manager already patched out __MenuSelect and set a flag in emHelpGlobals, so we'll just use that one !!
|
||
MOVE.L ExpandMemRec.emHelpGlobals(A1),A0 ; A0 = HelpMgr global ptr <#47>
|
||
TST.B hmgInMenuSelectFlag(A0) ; are we in MenuSelect? <#47>
|
||
BNE.S @returnOldResult ; yes so return the original result <#47>
|
||
|
||
;; end change of #44, #47
|
||
|
||
|
||
MOVE.B #0,4(sp) ; pretend no help windows are up by slamming the result to 0
|
||
|
||
@returnOldResult
|
||
RTS ; and return
|
||
|
||
ENDPROC
|
||
|
||
|
||
|
||
|
||
; ____________________________________________________________________________________
|
||
; __PopUpMenuSelect Patch <#44>
|
||
; If there is a popup menu in the floating window and with HelpMgr on, need to
|
||
; return the original result from HMGetBalloon so that balloon will be removed.
|
||
; ____________________________________________________________________________________
|
||
|
||
__PopUpMenuSelect PatchProc _PopUpMenuSelect,(Plus,SE,II,Portable,IIci)
|
||
|
||
retAddr EQU 8 ; saved 2 registers
|
||
|
||
MOVEM.L A0-A1,-(SP) ; free A0/A1
|
||
MOVEA.L ExpandMem,A1
|
||
MOVE.L ExpandMemRec.emTSMGlobals(A1),D1 ; get TSM global
|
||
BEQ.S @noEntry ; br if no TSM
|
||
MOVEA.L D1,A1 ; A1 = TSM global
|
||
BSET #kInTSMPopUpMenuSelectCall,TSMVarsRec.tsmPatchFlags(A1) ; say we're in PopupMenuSelect
|
||
MOVE.L retAddr(SP),D1 ; return address
|
||
MOVE.L D1,TSMVarsRec.tsmPopUpReturnAddr(A1) ; save the return address
|
||
LEA @return2Here,A0 ; return to here
|
||
MOVE.L A0,retAddr(SP)
|
||
|
||
;; OK, now to prevent from text services to receive an update event from SWM driver,
|
||
;; we need to tell SWM not to route events to TSM/text services ...
|
||
MOVE.W TSMVarsRec.tsmSWMDrvrRefNum(A1),D1 ; get refnum
|
||
BEQ.S @noEntry ; br if no SWM
|
||
NOT.W D1 ; unit entry := -1 * (refNum + 1)
|
||
cmp.w UnitNtryCnt,D1 ; is there an entry of this number?
|
||
bhs.s @noEntry ; no, so return NIL
|
||
LSL.W #2,D1 ; index := entry * 4
|
||
MOVE.L UTableBase,A1 ; unit I/O table [pointer]
|
||
MOVEA.L 0(A1,D1.W),A1 ; return DCtlHandle
|
||
MOVEA.L (A1),A1 ; dereference the handle
|
||
MOVEA.L dCtlStorage(A1),A1 ; get storage handle
|
||
MOVEA.L (A1),A1 ; dereference the handle
|
||
|
||
ST swmdrvrRecordMenuIsDown(A1) ; set the byte to true
|
||
@noEntry
|
||
MOVEM.L (SP)+,A0-A1 ; restore A0/A1
|
||
|
||
jmpOld ; and jump to the old one
|
||
|
||
@return2Here
|
||
|
||
MOVEA.L ExpandMem,A1
|
||
MOVE.L ExpandMemRec.emTSMGlobals(A1),A1 ; get TSM global
|
||
BCLR #kInTSMPopUpMenuSelectCall,TSMVarsRec.tsmPatchFlags(A1) ; we're not in PopupMenuSelect
|
||
MOVE.L TSMVarsRec.tsmPopUpReturnAddr(A1),D1 ; get the return address
|
||
MOVE.L D1,-(SP) ; return to caller
|
||
|
||
|
||
MOVE.W TSMVarsRec.tsmSWMDrvrRefNum(A1),D1 ; get refnum
|
||
BEQ.S @exit ; br if no SWM
|
||
NOT.W D1 ; unit entry := -1 * (refNum + 1)
|
||
cmp.w UnitNtryCnt,d1 ; is there an entry of this number?
|
||
bhs.s @exit ; no, so return NIL
|
||
LSL.W #2,D1 ; index := entry * 4
|
||
MOVE.L UTableBase,A1 ; unit I/O table [pointer]
|
||
MOVEA.L 0(A1,D1.W),A1 ; return DCtlHandle
|
||
MOVEA.L (A1),A1 ; dereference the handle
|
||
MOVEA.L dCtlStorage(A1),A1 ; get storage handle
|
||
MOVEA.L (A1),A1 ; dereference the handle
|
||
CLR.B swmdrvrRecordMenuIsDown(A1) ; clear the byte
|
||
|
||
@exit
|
||
|
||
RTS
|
||
|
||
ENDPROC
|
||
|
||
|
||
ENDIF ; end if building INIT
|
||
|
||
|
||
|
||
; _______________________________________________________________________________
|
||
; pascal short Gestalt(OSType selector, long responsePtr)
|
||
; Define a new Gestalt call to return TSM's version.
|
||
; _______________________________________________________________________________
|
||
|
||
TSMGestalt PROC EXPORT
|
||
|
||
MOVE.L 4(A7),A0 ; Return result to caller (responsePtr)
|
||
MOVE.L #TSMVersion,(A0) ; get version number
|
||
MOVE.L (SP)+,A0 ; Get return address
|
||
ADDQ #8,A7 ; Nuke some parameters
|
||
CLR.W (A7) ; no error
|
||
JMP (A0) ; return
|
||
|
||
ENDPROC
|
||
|
||
|
||
|
||
|
||
|
||
;============================================================================================
|
||
;
|
||
; InstallProc for the Text Services Manager -- allocate memory for globals.
|
||
;
|
||
;============================================================================================
|
||
|
||
TSMGRINSTALL proc export
|
||
WITH PSNRecord
|
||
|
||
|
||
|
||
MOVEA.L ExpandMem,A1
|
||
MOVE.L ExpandMemRec.emTSMGlobals(A1),D0 ; get TSM global
|
||
MOVEA.L D0,A1 ; clear A1 flag
|
||
BEQ.S @noGlobal ; not initialized
|
||
MOVE.W TSMVarsRec.tsmRecSize(A1),D0 ; record size
|
||
CMP.W #TSMVarsRec.TSMVarsRecSize,D0 ; are they the same size?
|
||
BEQ.W @return ; yes, reuse it
|
||
|
||
|
||
@noGlobal
|
||
;; allocate TSM global, and save it in ExpandMem ...
|
||
;; A1 <> nil if we have allocated the globals already.
|
||
;; all fields are initially cleared (0 or flase) !
|
||
MOVE.L #TSMVarsRec.TSMVarsRecSize,D0
|
||
_NewPtr ,Sys ,Clear ; allocate global from system heap
|
||
BNE.W @cantboot ; fatal error
|
||
|
||
;; A0 = new record, A1 = old record, copy A1 => A0,
|
||
MOVE.L A1,D0 ; do we have an old one?
|
||
BEQ.S @noOldRecord ; no
|
||
MOVEQ #0,D0
|
||
MOVE.W TSMVarsRec.tsmRecSize(A1),D0 ; old record size
|
||
EXG A0,A1 ; A0 = old record
|
||
_BlockMove ; A0 => A1 (preserved)
|
||
_DisposePtr ; free the old one
|
||
MOVEA.L ExpandMem,A0
|
||
MOVE.W #TSMVarsRec.TSMVarsRecSize,TSMVarsRec.tsmRecSize(A1) ; new record size
|
||
MOVE.L A1,ExpandMemRec.emTSMGlobals(A0) ; save the new TSM global in ExpandMem
|
||
BRA.S @return ; OK
|
||
|
||
@noOldRecord
|
||
MOVE.W #TSMVarsRec.TSMVarsRecSize,TSMVarsRec.tsmRecSize(A0)
|
||
MOVE.B #0, TSMVarsRec.tsmMajorVersion(A0) ; 0.1
|
||
MOVE.B #kTSMVersion, TSMVarsRec.tsmMinorVersion(A0) ; not released yet
|
||
MOVE.W #kUnknownScript,TSMVarsRec.tsmCurrentSLRec.fScript(A0) ; current script = unknown
|
||
MOVE.W #kUnknownLanguage,TSMVarsRec.tsmCurrentSLRec.fLanguage(A0) ; current language = unknown
|
||
|
||
MOVE.L #$4B534354,TSMVarsRec.tsmDebugSignature(A0)
|
||
|
||
MOVEA.L ExpandMem,A1
|
||
MOVE.L A0,ExpandMemRec.emTSMGlobals(A1) ; save TSM global in ExpandMem
|
||
MOVE.L A0,A1 ; save global in A1
|
||
|
||
;; allocate TSM aware PSN table, and save it in TSM global ...
|
||
MOVE.L #kPSNTableDefSize,D0 ; allocate TSM aware PSN table
|
||
_NewPtr ,Sys ,Clear ; from system heap
|
||
BNE.S @cantboot2 ; fatal error
|
||
|
||
MOVE.L A0,TSMVarsRec.tsmIAPSNTablePtr(A1) ; save the table addr in global too
|
||
MOVE.W #kDefTableEntryN,D0
|
||
MOVE.W D0,iaTotalPSNEntryN(A0) ; total entry number of the table
|
||
; LEA iaPSNStart(A0),A0 ; A0 points to the start of the array
|
||
; SUBQ.W #1,D0 ; for dbra
|
||
@loop1
|
||
; MOVE.W #kPSNTableSignature,psnTableSignature(A0) ; valid table signature
|
||
; ADDA.W #kPSNEntrySize,A0 ; next record
|
||
; DBRA D0,@loop1
|
||
; can't update default IM in TSM globals because we can't save the component, just description. too bad.
|
||
|
||
MOVE.L #gestaltTSMgrVersion,D0 ; selector to d0
|
||
import TSMGestalt
|
||
lea TSMGestalt,A0 ; get our function pointer into A0
|
||
_NewGestalt ; install it
|
||
|
||
MOVEQ #0,D0 ; all done
|
||
@return
|
||
RTS
|
||
|
||
@cantboot2
|
||
MOVE.L A1,A0
|
||
_DisposePtr ; free global
|
||
MOVEA.L ExpandMem,A0
|
||
CLR.L ExpandMemRec.emTSMGlobals(A0) ; clear TSM global
|
||
|
||
@cantboot
|
||
MOVEQ #dsMemFullErr,D0 ; no mem error
|
||
_SysError
|
||
BRA.S @return
|
||
|
||
ENDWITH
|
||
ENDPROC ; TSMgrInstall END
|
||
|
||
|
||
|
||
;============================================================================================
|
||
;
|
||
; old input method support.
|
||
;
|
||
;============================================================================================
|
||
|
||
|
||
; _______________________________________________________________________________
|
||
; pascal Boolean OldJapaneseInputMethodExists( short fepID);
|
||
;
|
||
; return true if the old Input Method which has the given id is installed.
|
||
; _______________________________________________________________________________
|
||
|
||
|
||
ojimRecord RECORD {a6link},decr
|
||
boolResult ds.w 1 ; activate result.
|
||
fepID ds.w 1 ; interface routine ID number.
|
||
return ds.l 1 ; return address.
|
||
a6link ds.l 1 ; old a6 register.
|
||
ojimRecord equ * ; size of local variables.
|
||
ENDR
|
||
|
||
OLDJAPANESEINPUTMETHODEXISTS PROC EXPORT
|
||
WITH ojimRecord,intfRecord,ScriptSystemGlobals,SMgrRecord
|
||
|
||
link a6,#ojimRecord
|
||
clr.w boolResult(a6) ; assume not found.
|
||
GetSmgrCore a0 ; load script manager core.
|
||
move.l smgrEntry+(smJapanese*4)(a0),d0 ; load doubleTalkRecord for Japanese.
|
||
beq.s @exit ; not installed. (something wrong)
|
||
move.l d0,a0
|
||
|
||
move.l intfArray(a0),d0 ; get the array handle.
|
||
ble.s @exit ; nil or negative -> something wrong.
|
||
move.l d0,a1 ; Load table handle.
|
||
move.l (a1),a1 ; Load table pointer.
|
||
move.l (a1)+,d0 ; Load table length.
|
||
move.w fepID(a6),d1 ; Load search id number.
|
||
bra.s @1 ; enter loop at bottom
|
||
@0
|
||
move.l (a1)+,a0 ; load table entry.
|
||
cmp.w (a0),d1 ; same id number?
|
||
beq.s @foundID ; yes -> we found it!
|
||
@1 dbra d0,@0 ; do the next entry.
|
||
bra.s @exit
|
||
@foundID
|
||
move.w #$0100,boolResult(a6) ; return (Pascal) true.
|
||
@exit
|
||
unlk a6
|
||
move.l (sp)+,a0 ; pop the return address.
|
||
addq #2,sp ; pop the Integer arguments.
|
||
jmp (a0) ; return to the caller.
|
||
|
||
ENDWITH
|
||
ENDPROC
|
||
|
||
END
|