; ; File: StyledTextEdit.a (formerly te68k_style.a) ; ; Contains: TextEdit for ROM or (when included in TextEditPatch.a) 'ptch' 0 ; ; Written by: S Capps, M Kaptanoglu, R Wetmore, Sue Bartalo (most recently) ; ; Copyright: © 1982-1989, 1991 by Apple Computer, Inc., all rights reserved. ; ; Change History (most recent first): ; ; <4> 1/17/92 DCL Backed out the previous change because this file is not supposed ; to be touched. Holy File. ; <3> 12/12/91 DCL #1009157: Changed a Tst to Tst.b so as not to test the potential ; garbage in the other byte. Changed procedure noClickProc in ; TextEdit.a, StyledTextEdit.a, and TextEditPatchIIciROM.a ; <2> 1/16/90 SMB Included TextEditPriv.a ; <1> 12/18/89 CCH Adding for the first time into BBS. ; BBS versions above: ;___________________________________________________________________________________________________ ;EASE READ ONLY COPY of file ÒStyledTextEdit.aÓ ; 1.7 SMB 08/25/1989 Removed load of nEqu.d. ; 1.6 smb 05/20/1989 Had to reset A2 to selStart(a3) in TECopy after a NewHandle call, which may ; have invalidated the pointer to the teRecord (upon which A2 was based!). See bug #46036. ; Fix for bug 39276: changed add operation in TECustomHook from a long op to a word op. ; Must lock the StScrpHandle for SetStylScrap to work correctly: see bug #36986. ; 1.5 smb 03/02/1989 Added Script Manager patch for setting up teSysJust from the system script ; for Harpo. ; 1.4 SMB 02/22/1989 Replaced hardware casms with feature casms, and changed ; routine names so they would not conflict with mpw includes. Also ; removed additional equates that are in ToolEqu.a. Also renamed this ; file from te68k_patch.a to StyledTextEdit.a to be used for Harpo Rom and ; 6.0.4 System builds. ; 1.3 SMB 02/22/1989 Test ; ¥1.2 CCH 02/15/1989 Submitting REAL 6.0.3 te68k source until BigBang sources ; get rolled in. ; FILE: TE68K.TEXT ; '/[ÂNO]/' ; © Apple Computer, Inc. 1982-1988 ; All Rights Reserved ; ;find /<<>>/ "{active}" # Execute to find the next available change number. ; ---------------------------------------------------------------------- ; ; Text Edit ; ; Modification history: ; ; 23-Jul-83 New Today ; 2-Aug-83 Code review changes: ; added std2Offset constant ; stdEntry points to param via A2 ; changed #7 to #Lock ; moved epilog4 ; flags trick in lock/unlock in stdentry/exit ; cleaned up selection safety chk in stdentry ; used grafGlobals(A5) instead of 0(A5) ; cleaned up(Ha!) TEClick ; Changed DoFind to handle top and pin H to DestRect ; switched end checks for teFind in DoText ; Changed and commented selsort- now returns A2^ to selStart ; callers of selSort now use A2 ; Shortened rect stuff in RecalDraw ; CallBreak uses reg arguments instead of stack ; 3-Aug-83 Cleaned up TEKey a bit ; Cleaned up refresh a bit ; Changed all indices to unsigned (BGE's) ; Added idle proc for scroll and key ; Addes TEInsert ; Fixed the Bryan Stearns memorial 1-char bug in RecalDraw ; Added hilite hook for MicroSoft and other bizarre things ; Added caret hook too ; SetSelect uses longs ; Added TESetJust, TEGetText ; 5-Aug-83 Fixed a bug in FindLine ; Fixed bug in Recaline (now waits for whole text to finish) ; Optimized dobackgnd to always stop at end ; 6-Aug-83 Dropped total dobackgnd from recal(I guess addition IS communitive) ; 7-Aug-83 Reinstated total dobackgnd from recal(FUCK!) ; 8-Aug-83 Dropped pinrects and used extended rects in DoText to save code ; 17-Aug-83 Fixed Rony bug in RecalDraw ; 19-Aug-83 Added system double/caret times ; 21-Aug-83 Added DoText and recal hooks ; 25-Aug-83 Fixed unwind bug in stdexit ; 25-Aug-83 Fixed Insert D7 bug ; 4-Sep-83 Fixed First char select bug in DoText ; 9-Sep-83 Fixed caret activate problem w/ inactive records ; Dropped background stuff(Finally gave up) ; Added global word break for Europe. ; 12-Sep-83 Made InvertHook push the rectangle ; ----------------------------------------------------------------------- ; 23 Jan 85 LAK Adapted for new equate files. ; 24-Jan-85 EHB Added patch in RecalDraw ; 25-Jan-85 EHB Fixed Refresh to only hilight visible part of selection ; 25-Jan-85 EHB Added Capp's TextBox fix ; 16-Jan-85 EHB Fixed center/right justify in TextBox fix ; 03-May-85 SC Fixed the -in-1st-char bug with word select. FindWord ; would abort if the left char scan got to the beginning, but ; it wouldn't check if the 0th char was a break character or not ; 03-May-85 SC Dropped forROM and for44T compile switches for readability ; 03-May-85 SC New version of FindLine, cleaner and fixes bugs. Still ; inefficient because it measures whole line repeatedly, but ; faster quickdraw fixes this. ; 03-May-85 SC Made trim measure skip wordBreak code and only trim chars ; <= space. This should truly measure only the black characters ; And not the word break chars now. ; 04-May-85 SC Changed D2 usage in TEClick to D5 long sign bit ; 04-May-85 SC SkipLoop in TrimMeasure could go negative ; 04-May-85 SC Dropped DelGuts and InsGuts call from PasteGuts and made a ; combined inline call for munger speed. Could make DelGuts and ; InsGuts inline since only 1 caller, but left that for another day ; 05-May-85 SC Made StdEntry/Exit use LINK instructions not SP based ; 05-May-85 SC TESetSelect trashed teSelPoint, cleaned up code a bit ; 05-May-85 SC Dropped teSelPoint usage, get off stack frame instead of TeHandle ; 05-May-85 SC Tricks played with A0 and teCarOn, teCarAct in DrawCaret, cleaned ; up for readability. ; 05-May-85 SC Longized all the 0(A0,DX.L) and call to _TextWidth and _DrawText ; 05-May-85 SC Fixed up recalLines to reduce flashiness ; 06-May-85 SC DoFormat had an extra measure for left justify that was not needed ; 06-May-85 SC DoText used tempRect, use stack frame instead ; 07-May-85 SC Undo refresh hilite stuff, moved similar stuff to Hilite ; 08-May-85 SC Added default click proc for auto scrolling ; 08-May-85 SC Added TEPinScroll which does a pinned scroll (Not upward ; compatible so I couldn't include in real scroll, but it is ; used by the default click proc and TEScrollView ; 08-May-85 SC Added TEScrollView which insures selection is visible before ; doing something. Called from TEKey, TEPaste, TECut, TEIdle, etc. ; 09-May-85 SC StdEntry/Exit save restore teTextH flags ; 09-May-85 SC teLftClick not a byte, now the tefLeftClk bit in teFlags ; 09-May-85 SC Made SelView local proc ; 09-May-85 SC Dropped trim measure black stuff ; 09-May-85 SC Made a local CalText proc to avoid StdEntry ; 11-May-85 SC Completely trashed DoText, OffsetStuff, DoFormat and ; replaced them with a clean versions of DoFind, DoHilite, ; DoDraw, DoCaret. This was to clean up the scaled fonts ; problem, the direct pen adjustment and general mayhem ; With the old DoText. ; 11-May-85 SC Local proc Scroll broken out for use by TEScroll and TEPinScroll ; 11-May-85 SC Reinstated teSelPoint, it's in documentation ; 11-May-85 SC Added TEAutoView trap to enable/disable the auto scrolling ; 11-May-85 SC Use _XMunger instead of _Munger ; 12-May-85 SC New local proc MungeSetup to do common munger stuff ; 12-May-85 SC Use D5 in recallines to hold telength ; 13-May-85 SC Save/Restore text stuff in std entry/exit and made setlinarray ; avoid calling _GethandleSize(done once in stdEntry) ; 13-May-85 SC Added preflight routine to check memory. Called from ; pasteguts, insertGuts, and TextBox. Did similar to TENew ; 15-May-85 SC Multiple standard entries with stack peel amount in D1. Does ; a preflight and then escapes if the preflight fails ; 18-May-85 SC Put back DoText funnel for compatibility ; 18-May-85 SC Dropped printable trim in FindLine @ end ; 18-May-85 SC LineWidth didn't handle the line past teLength correctly ; 18-May-85 SC Merged LineWidth and TrimMeasure ; 18-May-85 SC Made trim measure skip wordBreak code and only trim chars ; <= space. This should truly measure only the black characters ; And not the word break chars now. (Deja Vu - did this on 3 May ; but a bug in FindLine made it LOOK as though it didn't work ; so I undid it on 9-May) ; 18-May-85 SC New routine PinDisplay replaces pin code in Hilite and Refresh ; 18-May-85 SC Made DefClikProc obey autoScroll bit ; 20-May-85 SC DoSearch longize D3-D4 (Thanks Bill and Larry) ; 20-May-85 SC CleanupSel saved teTextH flags twice!! ; 20-May-85 SC Fast TextBox didn't catch zero string length case (oops) ; 20-May-85 SC SelView called before caret view in DelGuts and PasteGuts; ; should be after (leaves carets behind in Dialogs) ; 21-May-85 SC Added negative length to Fast TextBox ; 23-May-85 SC Dropped port save/restore font ; 7-Jun-85 EHB Fast TextBox shouldn't catch zero strings else no EraseRect(oops) ; 10-Jun-85 SC CharbyChar had a BLT that should've been a BLE (It gets there ; by a BGE so it should stay in loop if BLE). ; 10-Jun-85 SC DoText links a stack frame/DoBye and findDone UNLK ; 10-Jun-85 SC In rangeRect, stuff the rect.left in tempRect and set pen to ; right for compatibility with old DoText ; 10-Jun-85 SC DoSearch returns in D0 as before ; 15-Jun-85 SC Undid "teLftClick not a byte, now the tefLeftClk bit in teFlags" ; had to drop back to old one for compatibility. TERecback is ; now the TEFlags ; 15-Jun-85 SC DoText must return ThePort in A0 for compatibility ; 16-July-85 SC PinDisplay has new entry point for TEUpdate compatability ; Refresh changed to take A0 pointing to an update rect not ; D0/D1, calls PinA0Rect. ; 26-Jul-85 EHB Added ShowCaret to end of TEPinScroll (needed for null scroll) ; 01-Oct-85 EHB Set up D2 for all calls to CallBreak (identifies caller) ; 01-Oct-85 EHB Added hooks for TrimMeasure, FindWord, and FindLine. ; 30-Oct-85 EHB In DoFind, set up D3/D4 with selStart/selEnd before calling DoText ; 31-Oct-85 EHB In RecalDraw, draw whole words if WordRedraw (new lowMem) is TRUE ; 31-Oct-85 EHB Fast TextBox was scanning 0 len strings for CR's ; 01-Nov-85 EHB If WordRedraw=0->draw normal, if >0 -> draw word, if <0 -> draw line ; 03-Nov-85 SC Fixed special case D3=0 in DoCaret ; 05-Nov-85 EHB Moved label to make WordRedraw fix work right ; --------------------------------- Lonely Heifer ROMs ---------------------------- ; 14-Jan-85 EHB In PasteGuts, call SelSort and get sel length for preflight ; Fix longize bug in the beginning of DoSearch ; Added cursor key support to TEKey ; <19feb86> BBM Made some modifications to work under MPW ; --------------------------------- ROM 76 ---------------------------- ; MBK removed equates to an external file; added four new ; traps (TEStylNew, iTEStylPaste, iTESetStyle, iTEGetStyle); ; added the following new routines: SetOneStyle, GetDefStyle, ; ScanMeasure, GetLineHites, GetHite, CopyStyle, DeleteStyle, ; DecStyleCount, StylMeasure, SetLineHite, PasteStyle, MakeRoom, ; DupStyle, FindStyle, CompareStyles, AddStyle, ExtendStyle, ; FindLineHite, GetCurStyle, GetNumStyles, GetStyle, ; RecalstStarts, SetHiteAscent, SetStyle, ConcatStyles, ; ChangeStyle, and FindFeature; modified the following routines: ; TESetText, LineRect, PinDisplay, StdEntry, TECopy, DelGuts, ; RecalDraw, FindLine, RecalLines, SetLineArray, TEPaste, ; InsGuts, TEKey, TEPinScroll and TESelView. ; MBK Added 3 more traps (iTEReplaceStyle, TEGetOffset, TEFindStyle); ; renamed iTEGetStyle to TEFindStyle (iTEGetStyle now returns the ; style handle); fixed selection bug, the problem was in ; ScanMeasure and DoSearch. Fixed bug in CharByChar. Started ; fixing recalibration problem. ; MBK Fixed the scrolling problem in SelView; Modified ; Recallines to take into account changes in point size. ; MBK Renamed iTEGetStyle to iGetStylHandle and TEFindStyle to ; iTEGetStyle. Added iSetStylHandle. Added TEDispatch to handle ; All style traps (except TEStylNew) with only 1 real trap for ; them all. Made the following changes for International: ; added the Pixel2Char, Char2Pixel, and HiliteText hooks; ; modified doSearch and doDraw to test teSysJust and perform ; their functions backwards if it's set; totally rewrote ; DoHilite. Added NextLineRect to speed up DoDraw. Rewrote ; stages 2 and 3 of Recal for speed. Added new feature of ; Not resetting the line heights in Recallines if the high bit ; of the line height already stored is set. Changed the ; iTESetStyle and iTEReplaceStyle input modes to be OR'able. ; Also combined the body of these 2 routines for efficiency. ; Added stuff to compute distance to be auto-scrolled for ; TERecs with style, in DefClikProc. Changed BSET and BCLR ; of handles to _HLock and _HUnlock. ; MBK Fixed iTEGetStyle to return the grafport settings for ; records without style. Made addSize OR'able in StyleGuts. ; Fixed "index expected in D0" bug in DoSearch. Added ; DoMeasure, ChkBounds, and made FindLine call Pixel2Char ; for International. Fixed word-wrapping with spaces. Put ; local equates back in this file and put the rest of the ; equates in nToolEqu.a. Got rid of scrp equates, since they ; were the same as the st- equates. ; MBK Changed colorBit to clrBit since colorBit is a Quickdraw ; Trap already. Modified DoHilite to always measure from start ; of line, to fix highlighting problem with scaled fonts. Got ; rid of special code in PasteStyle to prevent style duplication, ; And just call ConcatStyles at the end. Added DoErase to fix ; italics erase problem. Removed code to shrink style runs array ; in ConcatStyles. Fixed problem of not clearing flag bits in ; ptrs before doing operations on an address. Changed color from ; LONGINT to RGBColor, and added Ernie's RGBForeColor and ; GetForeColor to handle this for the Alladin world. ; MBK Fixed problem in which CR at bottom of ViewRect did not cause ; scrolling (cleaned up DefClikProc, which fixed the problem seen ; in the Poke program). Changed Pixel2Char not to expect a buffer ; ptr as input, and to allocate the space itself on the stack. ; Added StylTextBox. Changed scrpStartChar to a LONGINT. Changed ; TECopy and TEPaste not to touch the desk scrap if the TERec is ; an old one (since David G. mentioned a lot of old applications ; may need to preserve the desk scrap for Undo). Changed DoHilite ; back to what it was (except with middle lines being highlighted ; as a block for speed) because the International version was ; just too slow; this means I also removed the HiliteText hook. ; Modified RecalDraw to adjust the redraw selection according to ; changes in line height. ; MBK Fixed 2 register preservation problems. Fixed InsertRecal ; memory overload problem. Redesigned method of updating line heights. ; MBK Made all changes resulting from code review. ; MBK Fixed CopyStyle and InsertRecal to reset ptr values after a ; memory allocation call (the ptrs were pointing to trash). ; --------------------------------- ROM 77 ---------------------------- ; MBK Fixed SetLineHite to take the line height from the only style ; when text length is 0 (instead of using the system font as a default). ; Fixed RecalLines to consider the next character the start of the ; next line if the width of the viewRect is less than the width of ; a single character. Fixed styleGuts to access FmDefaultSize as ; a byte, not a word. Fixed RecalLines bug in which lines are not ; recalibrated when text is typed over a single CR. ; MBK Fixed bug in RangeRect that caused selection to be off in MultiPlan. ; Fixed special case in which line redraw did not work, in RecalLines. ; MBK Set the high bit of the pnMode before highlighting, to use the new ; background color highlighting method. ; MBK Set the error code in D0 before calling SysError. Fixed bug in which ; carets left on the screen were not getting erased (in Mac3D). ; MBK Changed to clear bit in HiliteMode instead of setting bit in pnMode ; for color hilighting. Fixed selection bug in Pixel2Char. ; MBK Fixed SetStyle to save D2 on the stack because _RGBForeColor destroys it. ; Fixed Pixel2Char to restore D0 from D1 if NewPtr has to be called. ; MBK Restore A3 ptr after RGBForeColor call in StdExit, in case TERec gets moved. ; MBK Changed to clear the color highlight bit only if a highlight ; hook has not been installed (this was a problem with highlighting ; in the hex editor of ResEdit). Modified DoErase to erase the previous ; character if the mode is XOR, otherwise redrawing it will wipe it out ; (this was a problem in NetTrek). Modified StylMeasure to lock the style ; Record so that dereferenced pointer doesn't end up pointing to garbage. ; Also fixed Pixel2Char to do a signed comparison on the stack space. ; This bug was discovered by tEx, when the RAM cache was set high. ; ** BETA 3 ** ; MBK Added iGetStylScrap, PutStylScrap, iTEGetPoint, and iTEGetHeight. ; ** BETA 4 ** ; MBK Made changes in GetDefStyle, DoDraw, MeasureIt, ; StylMeasure, SetHiteAscent, and SetStyle to protect unlocked ; pointers from memory reallocation. Added startLine and ; endLine input to iTEGetHeight. Added RecalDraw to PutStylScrap. ; MBK I removed the C717 change to SetHiteAscent. The ptr there ; was not an offset from styleTab, it was an addr on the stack. ; ** BETA 5 ** ; MBK I changed PutStylScrap to iTEStylInsert, which unlike ; PutStylScrap will insert the text as well as the style info. ; Fixed StyleGuts to check for point sizes <= 0 when an addSize ; is done. It now converts such values to 1. Modified iTEGetHeight ; to subtract 1 from startLine because GetLineHites wants it ; 0-based. iSetStylHandle fixed to dispose of old style handle ; before setting new one. ; ** BETA 6 ** ; MBK Fixed CopyStyle to lock my style handle before calling ; PutScrap. Fixed DelGuts to relock text handle after munging. ; Removed call to StdEntry from iTEStylInsert because TEDispatch ; does it. ; MBK Fixed iTEStylInsert to get the input parameters in the ; correct order. ; MBK Fixed StdEntry to set the Grafport's txMode from TERec.teMode. ; Fixed RangeRect to set pnLoc correctly for compatibility with ; old applications. Fixed FindLine to check for a CR at the end ; of a string of unwrapped blanks. ; ** BETA 8 ** ; MBK Miscellaneous bug fixes (search on 851 to get more detailed ; descriptions); added code to handle setting styles on null ; selections. ; MBK Changed TECalText delta to 8001, fixed Pixel2Char disposhandle ; problem, fixed find style problem in PstStylScrap, fixed GetLineHites ; to work with fixed height, fixed recal deletion problem, restored input ; parameter order of iTEGetHeight. ; MBK Fixed problems of iTEStylInsert destroying the StScrpHandle, style ; duplication problem in PstStylGuts, and iTEGetPoint returning incorrect ; offset when text ends in CR. Removed conditionals around bug fixes. ; MSH Port to HcMac (Laguna). No color on this machine ; rwh Port to Modern Victorian ; ------------------------------ System 6.0 ---------------------------- ; Did some personal cleanup. Added new equates for new structures. ; Changed Bcc's and Bcs's to more logical forms. ; Began comparing various patches against this source to resolve differences. ; Fixed 0 length bug in iTEStylInsert ; Added conditional equates to make RAM-based testing easier ; Patched ReCalLines to properly shrink lineStarts array ; Broke out some common code, trying not to reinvent the wheel: ; AnyNullStyle, GetTrueStyle, GetOneStyle ; Changed iGetStylScrap to return a proper scrap record, even if ; there is no selection range. Prevents apps from having ; to special case insertion points ; Rewrote most of iTEGetHeight to properly sort and pin start/end ; Added conditional inclusion of TEDispatch'ed routine addresses ; so I can find them without a Cray ; InitRsrved had some strangeness in it ; Added TESetEraseFlag and iTEContinuousStyle. Added in code to check ; for erase flag before performing _EraseRect's ; Changed references to faces to be byte instead of word length ; Changed branches to optimal form. Those patches marked "NO" ; are for new ROMs and total replacement patches only. ; (There were an awful lot of word branches where shorts would do!) ; Added SetStyleScrap ; Changed fail test in SetGuts to masking uninteresting bits ; Added doToggle functionality to SetGuts, StyleGuts, SetRsrved, CheckMatch ; Added some hysteresis to lineStarts hack, to try to prevent some ; heap thrashing from constant SetHandleSize calls ; Added new internal dispatch table to (quasi-) support tabs. We won't ; officially support tabs, but these hooks will make the job a lot ; simpler for those who need it. (It used to be a lot easier to hook ; in tab support than it is now that styles have to be reckoned with.) ; Yanked SetEraseFlag and associated logic. Only bought us about 10% - not ; enough to get excited over. Added iTECustomHook to give a high end ; way to stuff new internal dispatch table addresses ; Took out some redundancies and moved autoscroll flag from its position in ; "teFlags" (nŽe teRecBack) to the new dispatch record. Ooops. It acted as ; a high bit set in the new handle to the TEDispatchRec ; Fixed bug in TEDispose where dispatch vector was not getting released for ; unstyled TE records. ; Fixed bug in iTEContinuousStyle and changed the way it handles face ; attributes ; Revisiting of S508, installed on Altair only by mistake. ; Fixes problem of TEHandle being dereferenced across a call to ; InstallIntDispatch in TEStylNew, which could thrash the heap. ; <19Feb89smb> Replaced hardware casms with feature casms, and changed routine names ; so they would not conflict with mpw includes. Also removed additional ; equates that are in ToolEqu.a. ; <28Feb89smb> Added Script Manager patch for setting up teSysJust from the system script ; for Harpo. ; <16May89smb> Had to reset A2 to selStart(a3) in TECopy after a NewHandle call, which may ; have invalidated the pointer to the teRecord (upon which A2 was based!). ; See bug #46036. Fix for bug 39276: changed add operation in TECustomHook ; from a long op to a word op. ; <17May89smb> Must lock the StScrpHandle for SetStylScrap to work correctly: see bug #36986. ; _______________________________________________________________________ ;<<>> <- This is to make the end of these comments easy to find with MPW. Blanks On String AsIs If &TYPE('&RWWDebug') = 'UNDEFINED' Then If &TYPE('InsideTEPatch') = 'UNDEFINED' Then ; LOAD 'StandardEqu.d' INCLUDE 'ScriptPriv.a' ; <28Feb89smb> INCLUDE 'TextEditPriv.a' ; <1/9/90smb> EndIf ; EndIf ; ************************************************************************************************* ; ************************************************************************************************* ; ************************************************************************************************* TextEdit Proc Export Export TextBox Export TEActivate Export TEClick Export TECopy Export TECut Export TEDeactivate Export TEDelete Export TEInit Export TENew Export TEDispose Export TEKey Export TEPaste Export TEIdle Export TEUpdate Export TEInsert Export TESetText Export TECalText Export TESetSelect Export TEScroll Export TESetJust Export TEGetText Export TEAutoView Export TEPinScroll Export TESelView Export TEStylNew Export TEGetOffset Export TEDispatch ; hooks to be stored in the trap table Export XTrimMeasure Export XFindWord Export XFindLine Export vPixel2Char Export vChar2Pixel ;----------------------- teStylSize Equ 28 ; initial size of teStylesRec with 2 entries stBaseSize Equ 20 ; added to fix MakeRoom bug ; iTESetStyle/iTEContinuousStyle modes doAll2 Equ $1F ; all of the above + add size doAll3 Equ $3F ; all of the above + toggle faces ;----------------------- teFind Equ 0 teMark Equ 1 teDraw Equ -1 teLoc Equ -2 teLFlush Equ 0 ; default teRFlush Equ -1 teCenter Equ 1 ; constants for identifying the routine that called callbreak teWordSelect Equ 4 ; clickExpand to select word teWordDrag Equ 8 ; clickExpand to drag new word teFromFind Equ 12 ; FindLine called it teFromRecal Equ 16 ; RecalLines called it inHandle Equ 8 ; TE handle offset saveHandle Equ -2 ; incoming handle flags savePort Equ saveHandle-4 ; incoming graf port saveClip Equ savePort-4 ; incoming clip in TE port saveTH Equ saveClip-2 ; saved text handle flags saveFont Equ saveTH-2 ; Grafport's font saveFace Equ saveFont-2 ; Grafport's face saveSize Equ saveFace-2 ; Grafport's size saveColor Equ saveSize-6 ; Grafport's color stdLink Equ saveColor ; standard frame for doText saveLeft Equ -2 ; true left saveJust Equ saveLeft-2 ; left setting after justification txtLink Equ saveJust ; frame for recallines savedD4 Equ -2 savedD2 Equ savedD4-2 startHndl Equ savedD2-4 savePtr Equ startHndl-4 oldNLines Equ savePtr-2 RecalLink Equ oldNLines AddrTable DC.W iTEStylPaste-AddrTable ; 0 DC.W iTESetStyle-AddrTable ; 1 DC.W iTEReplaceStyle-AddrTable ; 2 DC.W iTEGetStyle-AddrTable ; 3 DC.W iGetStylHandle-AddrTable ; 4 DC.W iSetStylHandle-AddrTable ; 5 DC.W iGetStylScrap-AddrTable ; 6 DC.W iTEStylInsert-AddrTable ; 7 DC.W iTEGetPoint-AddrTable ; 8 DC.W iTEGetHeight-AddrTable ; 9 ; ** New entry points DC.W iTEContinuousStyle-AddrTable ; 10 DC.W iSetStylScrap-AddrTable ; 11 DC.W iTECustomHook-AddrTable ; 12 DC.W iTENumStyles-AddrTable ; 13 ; ---------------------------------------------------------------------- ; FUNCTION TEGetText( h: TEHandle ): Handle; ; Returns the text handle ; ---------------------------------------------------------------------- TEGetText Bsr StdEntry Move.L teTextH(A3),(A2) ; return the text handle Bra epilog4 ; ---------------------------------------------------------------------- ; PROCEDURE TEInit ; ---------------------------------------------------------------------- TEInit MoveQ #0,D0 Move D0,TEScrpLength ; save in global space _NewHandle Move.L A0,TEScrpHandle ; Save in global space Lea XDoText,A0 ; set up doText hook Move.L A0,teDoText Lea XRecalLines,A0 ; set up recal hook Move.L A0,teRecal Lea DefWordBrk,A0 ; get default word break Move.L A0,teWdBreak ; <28Feb89smb> If onHcMac then WITH SMgrRecord,ScriptRecord GetSMgrCore a0 ; load SMgr globals pointer. tst.b smgrEnabled(a0) ; script manager disabled? beq @bail ; yes -> bail out. move.w smgrSysScript(a0),d0 ; get system script code. lsl.w #2,d0 ; script code is long offset. move.l smgrEntry(a0,d0.w),a0 ; load system script entry. move.b scriptJust(a0),d0 ; load script just. ext.w d0 ; sign extend just. move.w d0,TESysJust ; set global just. endWith @bail endif Rts ; ---------------------------------------------------------------------- ; PROCEDURE TEDispose( h: TEHandle ) ; ** ** Added code to dispose of style ; related handles if this TERec has style. ; ---------------------------------------------------------------------- TEDispose Link A6,#0 MoveM.L D2-D7/A2-A4,-(SP) ; save stdregs Move.L 8(A6),A4 ; Pop handle into A4 Move.L (A4),A3 ; Dereference into A3 Move.L teTextH(A3),A0 ; get rid of text _DisposHandle ; Following lines moved here from within "styled" section below. Move.L teDispatchH(A3),A0 ; Added to (quasi-) support tabs _DisposHandle ; Tst.W teSize(A3) ; record with style? Bpl.S @0 ; more to dispose if so Move.L teStylesH(A3),A2 ; get style handle Move.L (A2),A2 ; dereference Move.L styleTab(A2),A0 ; handle to distinct styles _DisposHandle Move.L lhTab(A2),A0 ; handle to line heights _DisposHandle Bsr.S DisposRsrved ; dispose of reserved handle Move.L teStylesH(A3),A0 ; get rid of itself _DisposHandle @0 Move.L A4,A0 ; get rid of itself _DisposHandle MoveQ #4,D0 Bra Std2Exit ; ---------------------------------------------------------------------- ; PROCEDURE DisposRsrved; ; ** ** ; I changed teReserved to a handle to the following structure: ; Record ; newReserved : LONGINT; ; nullScrap : stScrpHandle; ; End; ; nullScrap is used to store a style which is set when the ; selection is NIL in iTESetStyle. I store it in the scrap ; format so that it can easily be inserted using PstStylGuts. ; This procedure is called to dispose of the nullStyle handle. ; ---------------------------------------------------------------------- DisposRsrved Move.L teStylesH(A3),A0 ; get style handle Move.L (A0),A0 ; deref Move.L nullStyle(A0),A0 ; get reserved handle Move.L A0,-(SP) ; save this handle Move.L (A0),A0 ; deref Move.L nullScrap(A0),A0 ; get handle to scrap for null selection _DisposHandle ; get rid of null scrap handle Move.L (SP)+,A0 ; get back nullStyle handle _DisposHandle ; get rid of nullStyle handle Rts ; ---------------------------------------------------------------------- ; PROCEDURE TextBox( Text: Ptr; Length: LONGINT; r: Rect; style: INTEGER ); ; 18 14 10 8 TBJust Equ 8 TBBox Equ 10 TBLength Equ 14 TBText Equ 18 ; ---------------------------------------------------------------------- TextBox Link A6,#0 MoveM.L D2-D7/A2-A4,-(SP) ; save StdRegs on stack Tst.W TBJust(A6) ; ÒleftÓ justified? Bne.S @05 ; no => skip this Move.W teSysJust,TBJust(A6) ; he meant, Òdefault justificationÓ @05 Cmp.W #teForceLeft,TBJust(A6) ; _real_ left justification? Bne.S @08 ; no => skip this Clr.W TBJust(A6) ; clear justification @08 ; ; here's Capp's code to make TextBox fast for drawing single lines ; Added EHB 25-Jan-85. Move.L TBText(A6),A0 ; see if any CR's in text Move.L TBLength(A6),D0 ; get length Blt.S tbExit ; escape if illegal string NO Beq.S NoZeroScan ; => don't scan NIL strings @0 Cmp.B #$0D,(A0)+ Beq.S useRealOne SubQ.L #1,D0 Bne.S @0 ; no carriage returns, try in rect NoZeroScan SubQ #2,SP ; see how big it is? Move.L TBText(A6),-(SP) ; pass text Clr.W -(SP) Move TBLength+2(A6),-(SP) ; pass length (low word) _TextWidth Move.W (SP)+,D3 ; save it Move.L TBBox(A6),A0 ; point to rect Move right(A0),D0 Sub left(A0),D0 SubQ #2,D0 Cmp D3,D0 Ble.S useRealOne Move.L A0,-(SP) ; erase the rect _EraseRect SubQ #8,SP Move.L SP,-(SP) _GetFontInfo Move (SP)+,D0 ; get ascent AddQ #6,SP ; skip rest Move.L TBBox(A6),A0 ; point to rect Move.L (A0),-(SP) ; push topleft Add D0,(SP) ; go down ascent AddQ #1,2(SP) ; indent 1 for TE compatibility _MoveTo Tst.W TBJust(A6) ; look at justification ; leave high byte for others Beq.S @2 ; if left go do it ; assume centered Move.L TBBox(A6),A0 ; point to rect Move right(A0),D0 ; calc width Sub left(A0),D0 Sub D3,D0 ; subtract text width SubQ #1,D0 ; caret space TE compatibility Tst.W TBJust(A6) ; look at justification Bmi.S @1 ; if right skip right shift AsR #1,D0 ; divide by two @1 Move D0,-(SP) ; move over Clr -(SP) ; dv = 0 _Move @2 Move.L TBText(A6),-(SP) ; pass text Clr -(SP) Move TBLength+2(A6),-(SP) ; pass length (low word) _DrawText tbExit Bra.S Go14Exit ; go to standard exit ; end of TextBox patch UseRealOne ; watch out for wierd (SP) offsets SubQ #4,SP ; make room for return handle Move.L TBBox(A6),-(SP) ; pass rect to init code Move.L (SP),-(SP) ; pass rect twice Move.L (SP),-(SP) ; pass rect twice _EraseRect _TENew Move.L (SP)+,A4 ; save handle Move.L (A4),A0 ; dereference Move.W TBJust(A6),teJust(A0) ; and set style Move.L TBLength(A6),D0 ; get length Beq.S noTextBox Move.L TBText(A6),-(SP) ; pass text pointer Move.L D0,-(SP) ; pass text length Move.L A4,-(SP) ; pass tehandle _TESetText Move.L TBBox(A6),-(SP) ; pass rect to update Move.L A4,-(SP) ; pass tehandle _TEUpdate ; and draw it noTextBox Move.L A4,-(SP) ; pass tehandle _TEDispose ; and dispose it Go14Exit MoveQ #14,D0 Bra Std2Exit ; ---------------------------------------------------------------------- ; PROCEDURE TESetText( text: Ptr; l: Length; h: TEHandle ); ; ** Modified 6/18/86 by MBK ** ; Makes the text passed in the current text to edit ; ---------------------------------------------------------------------- TESetText Bsr StdEntry Move.L (A2)+,D0 ; get length passed Move D0,teSelStart(A3) ; save as selection Move D0,teSelEnd(A3) Move D0,teLength(A3) ; save as length Move.L teTextH(A3),A0 ; handle to stuff into Move.L D0,-(SP) _HUnlock ; and unlock it Move.L (SP)+,D0 Move.L (A2)+,A0 ; set up ptr Move.L teTextH(A3),A1 ; handle to stuff into _PtrToXHand Move.L teTextH(A3),A0 ; handle to stuff into _HLock ; relock it Bsr.S SetOneStyle ; set GrafPort's style NO Bsr CalText ; go do it noText go12 Bra epilog12 ; ---------------------------------------------------------------------- ; PROCEDURE SetOneStyle ; ** Added 6/2/83 by MBK ** ; Called by TESetText to set the entire body of the new text ; to a single style, which is taken from the GrafPort by ; default. ; ---------------------------------------------------------------------- SetOneStyle Tst.W teSize(A3) ; check style flag Bpl.S @0 ; quit if no style ; Set style handle to minimum size (i.e., 1 style for entire text) Move.L teStylesH(A3),A0 ; get style handle MoveQ #teStylSize,D0 ; size of record with 1 style Bsr.S MySetHandleSize ; reset handle size NO Move.L (A0),A0 ; dereference ; Reset StyleRec's handle size to just 1 StyleRec Move.L styleTab(A0),A0 ; handle to StyleRec's MoveQ #stRecSize,D0 ; size of 1 style record Bsr.S MySetHandleSize ; reset handle size NO Move.L teStylesH(A3),A0 ; get style handle Move.L (A0),A0 ; dereference to A0 Move.W teLength(A3),D0 ; get length of text Bsr.S GetDefStyle ; store default style in StyleRec NO @0 Rts ; ---------------------------------------------------------------------- ; PROCEDURE MySetHandleSize ; ** ** ; MySetHandleSize unlocks the TEHandle and the text handle, attempts ; to set the input handle size, calls system error if there is one, ; And otherwise relocks TEHandle and the text handle. ; Entry: ; D0: requested handle size ; A0: a handle ; A3: Ptr to TERec ; A4: Handle to TERec ; Exit: ; A3: Could have a different value if memory was shifted ; ---------------------------------------------------------------------- MySetHandleSize MoveM.L D0/A0,-(SP) ; save input Move.L teTextH(A3),A0 ; text handle _HUnLock ; unlock it MoveM.L (SP)+,D0/A0 ; restore input _SetHandleSize ; do it Bne.S badExit ; fly away if system error MoveM.L D0/A0,-(SP) ; save input Move.L teTextH(A3),A0 ; text handle _HLock ; lock that too MoveM.L (SP)+,D0/A0 ; restore input Rts badExit Move.W #dsMemFullErr,D0 ; memory full error ** ** _SysError ; go away and never come back ; ---------------------------------------------------------------------- ; PROCEDURE GetDefStyle ; ** Added 6/2/86 by MBK ** ; GetDefStyle gets the default style for this TERec (taken ; from its GrafPort) and stores it in the styleRec pointed ; to by A0. ; Entry: ; D0: length of text ; A0: dereferenced TEStylesH ; A3: Ptr to TERec ; ---------------------------------------------------------------------- GetDefStyle Move.W #1,nRuns(A0) ; always 1 style to start Move.W #1,nStyles(A0) ; # of styleRec's Lea runs(A0),A1 ; point to start of style array Clr.L (A1)+ ; start offset and index Move.W D0,(A1)+ ; 1 beyond the end Move.W #$FFFF,(A1) ; make it no style Move.L styleTab(A0),A0 ; handle to StyleRec's Move.L (A0),A0 ; dereference Move.W #1,stCount(A0) ; so set count to 1 Bsr.S GetSize ; get ascent & hite NO ; Dereference the handle again. GetSize calls GetFontInfo, which could ; move memory around. Move.L teStylesH(A3),A0 ; style handle Move.L (A0),A0 ; dereference Move.L styleTab(A0),A0 ; handle to StyleRec's Move.L (A0),A0 ; dereference Move.W D0,stAscent(A0) ; save in ascent ** ** Move.W D1,stHeight(A0) ; save in line height ** ** ; Get the font, face, size and color and save away Move.L teGrafPort(A3),A1 ; get this port Move.W txFont(A1),stFont(A0) ; save the font Move.W txFace(A1),stFace(A0) ; save the face Move.W txSize(A1),stSize(A0) ; save the size Pea stColor(A0) ; place to store color ** ** ;; If forRAM THEN If (Not forROM) THEN ; <19Feb89smb> BTst #14,ROM85 ; are we on a color system? (as per Jerome) Bnz.S @1 ; Nope _GetForeColor ; Bra.S @2 ; @1 Bsr GetForeColor ; @2 ;; ElseIf onNuMac|onMvMac THEN ; rwh ElseIf hasCQD THEN ; <19Feb89smb> _GetForeColor ; for Ikki ** ** Else Bsr GetForeColor ; for Alladin ** ** EndIf Rts ; ---------------------------------------------------------------------- ; PROCEDURE GetSize ; ** ** ; Get ascent and line height from current font. ; Exit: ; D0: ascent ; D1: line height (= descent + leading!) ; ---------------------------------------------------------------------- GetSize Move.L A0,-(SP) ; calling routines need this ; Get line height, etc. for font SubQ #8,SP ; make room for font info stuff Move.L SP,-(SP) ; push address _GetFontInfo Move (SP)+,D0 ; get ascent Move D0,D1 Add (SP)+,D1 ; add descent AddQ #2,SP ; skip max wid Add (SP)+,D1 ; add leading Move.L (SP)+,A0 Rts ; ---------------------------------------------------------------------- ; PROCEDURE TECalText{ ( h: TEHandle ) }; ; When the user installs his own text handle/rectangle in the record, ; this routine should be called to calibrate the line array to it ; ---------------------------------------------------------------------- CalText Move.L teSelStart(A3),-(SP) ; save selStart/End Clr teSelStart(A3) ; recall from beginning ; The delta must be 32,767 for the recalibration to work correctly when the insert length ; is 32,767 and the text length is 0. (an arbitrarily large negative number won't do). Move #$8001,D7 ; fake delta(large - number) Clr.L teLines(A3) ; insure total recal Bsr ReCalLines ; redo the line stuff Move.L (SP)+,teSelStart(A3) ; restore selStart/End Rts TECalText Bsr StdEntry Bsr.S CalText ; NO epilog4 MoveQ #4,D0 ; fall into std exit ; ---------------------------------------------------------------------- ; Std Exit assumes original argument is good StdExit Move.L inHandle(A6),A4 ; Place handle into A4 Bra.S RealExit ; ** ** For style routines, which also have a routine ; selector on the top of the stack StdExit2 Move.L inHandle+2(A6),A4 ; Place handle into A4 RealExit Move.L (A4),A3 ; re-dereference it Move D0,D4 ; save strip amount Move.L teTextH(A3),A0 ; get text handle Move.B saveTH(A6),D0 ; get the text handle flags _HSetState ; set up the handle Move.L saveClip(A6),-(SP) Move.L (SP),-(SP) _SetClip ; restore caller's clip _DisposRgn ; and dispose of our copy Move.L A4,A0 ; get the handle Move.B saveHandle(A6),D0 ; get the handle's flags _HSetState ; restore the handle Pea saveColor(A6) ; set foreground color ** ** ;; If forRAM THEN If (not forROM) THEN ; <19Feb89smb> BTst #14,ROM85 ; are we on a color system? (as per Jerome) Bnz.S @1 ; Nope _RGBForeColor ; Move.L (A4),A3 ; Bra.S @2 ; @1 Bsr RGBForeColor ; @2 ;; ElseIf onNuMac|onMvMac THEN ; rwh ElseIf hasCQD THEN ; <19Feb89smb> _RGBForeColor ; for Ikki ** ** Move.L (A4),A3 ; restore ptr just in case ** ** Else Bsr RGBForeColor ; for Alladin ** ** EndIf Move.L teGrafPort(A3),A0 ; restore GrafPort stuff Move.W saveSize(A6),txSize(A0) ; restore Grafport's size Move.W saveFace(A6),txFace(A0) ; restore Grafport's face Move.W saveFont(A6),txFont(A0) ; restore Grafport's font Move.L savePort(A6),-(SP) ; restore port to user's passed _SetPort Move D4,D0 ; restore strip amount Std2Exit MoveM.L (SP)+,D2-D7/A2-A4 ; restore regs Unlk A6 Move.L (SP)+,A0 ; remove return add Add D0,SP ; strip parameters Jmp (A0) ; ---------------------------------------------------------------------- ; PROCEDURE TESetSelect{ ( selStart, selEnd: LONGINT; h: TEHandle ) }; ; Sets the current select range ; ---------------------------------------------------------------------- TESetSelect Bsr StdEntry Bsr ClearRsrved ; clear out reserved style Bsr HideCaret Bsr HiLite Move 14(A6),teSelEnd(A3) ; Jam the selection end Move 18(A6),teSelStart(A3) ; jam selStart Bsr CleanUpSel ; sort and clean up selection Bsr ShowCaret Bsr HiLite Bsr SelView ; insure selection is visible Bra go12 ; ---------------------------------------------------------------------- ; FUNCTION TENew{ ( destRect, viewRect: Rect ): TEHandle }; ; ---------------------------------------------------------------------- TENew Link A6,#0 MoveM.L D2-D7/A2-A4,-(SP) ; Save regs Clr.L 16(A6) ; return NIL MoveQ #TERecSize,D0 ; Allocate a record _NewHandle ,CLEAR Bne badExit ; escape if error NO Move.L A0,A4 ; save handle _HLock ; get object handle and lock it Move.L (A4),A3 ; dereference it MoveQ #0,D0 ; get text handle _NewHandle Bne badExit ; escape if error NO Move.L A0,teTextH(A3) ; Dest and view rect must be together in record Lea teDestRect(A3),A0 ; point to rects in beginning Move.L 12(A6),A2 ; Get dest rectangle arg Move.L (A2)+,(A0)+ ; save away in record Move.L (A2)+,(A0)+ Move.L 8(A6),A2 ; Get view rectangle arg Move.L (A2)+,(A0)+ ; save away in record Move.L (A2)+,(A0)+ ; Get line height, etc. for font Bsr GetSize ; get ascent & hite ** ** Move.W D0,teAscent(A3) ; save in ascent ** ** Move.W D1,teLineHite(A3) ; save in line height ** ** ; Get the font and face and save away Move.L grafGlobals(A5),A2 ; get lisagraf globals and then Move.L thePort(A2),A2 ; thePort Move.L A2,teGrafPort(A3) ; save this port Move.L txFont(A2),teFontStuff(A3) ; save the font/face Move.L txFont+4(A2),teFontStuff+4(A3) ; save the mode/size Move.L teWdBreak,teWordBreak(A3) ; Set global word breaker Lea DefClikProc,A0 ; setup default click proc Move.L A0,TEClikProc(A3) Bsr.S InstallIntDispatch ; install new internal dispatch tbl Move.L teTextH(A3),A0 ; need to unlock text handle _HUnlock ; MyNewHandle locked it Move.L A4,A0 ; set up for HUnlock _HUnlock Move.L A4,16(A6) ; return handle @0 MoveQ #8,D0 Bra Std2Exit ; NO ; ---------------------------------------------------------------------- ; PROCEDURE ClearRsrved; ; ** ** ; I changed teReserved to a handle to the following structure: ; Record ; newReserved : LONGINT; ; nullScrap : stScrpHandle; ; End; ; nullScrap is used to store a style which is set when the ; selection is NIL in iTESetStyle. I store it in the scrap ; format so that it can easily be inserted using PstStylGuts. ; This procedure is called to set the style count to 0 whenever ; the selection is changed. ; ---------------------------------------------------------------------- ClearRsrved Tst.W teSize(A3) ; record with style? Bpl.S @0 ; this hdl isn't there if not Move.L teStylesH(A3),A0 ; get style handle Move.L (A0),A0 ; deref Move.L nullStyle(A0),A0 ; get reserved handle Move.L (A0),A0 ; deref Move.L nullScrap(A0),A0 ; get handle to scrap for null selection Move.L (A0),A0 ; deref Move.W #0,scrpNStyles(A0) ; indicate no style @0 Rts ; ---------------------------------------------------------------------- ; InstallIntDispatch ; ; Added this code to (quasi-) support tabs ; ---------------------------------------------------------------------- InstallIntDispatch MoveQ #intDispSize,D0 Bsr MyNewHandle ; Replaces next two lines ; _NewHandle ; ; Bne badExit ; Move.L A0,teDispatchH(A3) ; install it in the record Move.L (A0),A0 Lea xEOLHook,A1 Move.L A1,EOLHook(A0) Lea xDRAWHook,A1 Move.L A1,DRAWHook(A0) Lea Char2Pixel,A1 Move.L A1,WIDTHHook(A0) Lea Pixel2Char,A1 ; Move.L A1,HITTESTHook(A0) ; Clr.L newTEFlags(A0) ; Rts ; ---------------------------------------------------------------------- ; FUNCTION TEStylNew{ ( destRect, viewRect: Rect ): TEHandle }; ; ** Added 5/23/86 by MBK ** ; TEStyleNew sets txSize to -1 and stores a handle to the ; style information in txFont, txFace. The LineHeight and ; FontAscent fields are set to -1. ; ---------------------------------------------------------------------- TEStylNew Link A6,#0 MoveM.L D2-D7/A2-A4,-(SP) ; Save regs Clr.L 16(A6) ; return NIL MoveQ #TERecSize,D0 ; Allocate a record _NewHandle ,CLEAR Bne badExit ; escape if error NO Move.L A0,A4 ; save handle _HLock ; get object handle and lock it Move.L (A4),A3 ; dereference it MoveQ #0,D0 ; get text handle _NewHandle Bne badExit ; escape if error NO Move.L A0,teTextH(A3) ; Dest and view rect must be together in record Lea teDestRect(A3),A0 ; point to rects in beginning Move.L 12(A6),A2 ; Get dest rectangle arg Move.L (A2)+,(A0)+ ; save away in record Move.L (A2)+,(A0)+ Move.L 8(A6),A2 ; Get view rectangle arg Move.L (A2)+,(A0)+ ; save away in record Move.L (A2)+,(A0)+ ; Set size to -1 to indicate this is a stylish record & allocate handle to style Move.W #-1,teSize(A3) ; set style flag (Go style) MoveQ #teStylSize,D0 ; min size is for 1 style descriptor Bsr MyNewHandle ; get handle to style info ** ** Move.L A0,teStylesH(A3) ; former txFont location ; Get Style Handle for storing font, face, size, and color MoveQ #stRecSize,D0 ; size of style descriptor Bsr MyNewHandle ; get StyleHandle NO Move.L teStylesH(A3),A2 ; handle to style info Move.L (A2),A2 ; dereference Move.L A0,styleTab(A2) ; store handle to styles array ; Get handle to array of largest line height on each line MoveQ #4,D0 ; Make room for one entry in line height array Bsr MyNewHandle ; allocate handle to line hites NO Move.L A0,A1 ; save handle Move.L teStylesH(A3),A0 ; handle to style info Move.L (A0),A0 ; dereference Move.L A1,lhTab(A0) ; store line hites handle ; Save the GrafPort and save default style from GrafPort Move.L grafGlobals(A5),A1 ; get lisagraf globals and then Move.L thePort(A1),A1 ; thePort Move.L A1,teGrafPort(A3) ; save this port Move.W txMode(A1),teMode(A3) ; save the mode MoveQ #1,D0 ; length of text + 1 Bsr GetDefStyle ; save default style in StyleRec ; Store one entry in line height array Move.L teStylesH(A3),A0 ; style handle Move.L (A0),A0 ; dereference Move.L lhTab(A0),A1 ; handle to line height table Move.L (A1),A1 ; dereference Move.L styleTab(A0),A0 ; handle to StyleRec's Move.L (A0),A0 ; dereference Move.W stAscent(A0),2(A1) ; save ascent Move.W stHeight(A0),(A1) ; save line height Move.W #$FFFF,teAscent(A3) ; won't be used unless somebody Move.W #$FFFF,teLineHite(A3) ; sets the ascent and line height Move.L teWdBreak,teWordBreak(A3) ; Set global word breaker Lea DefClikProc,A0 ; setup default click proc Move.L A0,TEClikProc(A3) Bsr.S InitRsrved ; init reserved handle Bsr InstallIntDispatch ; install new internal dispatch tbl Move.L teTextH(A3),A0 ; need to unlock text handle ** ** _HUnlock ; MyNewHandle locked it ** ** Move.L A4,A0 ; set up for HUnlock _HUnlock Move.L A4,16(A6) ; return handle @0 MoveQ #8,D0 Bra Std2Exit ; NO ; ---------------------------------------------------------------------- ; PROCEDURE InitRsrved; ; ** ** ; I changed teReserved to a handle to the following structure: ; Record ; newReserved : LONGINT; ; nullScrap : stScrpHandle; ; End; ; nullScrap is used to store a style which is set when the ; selection is NIL in iTESetStyle. I store it in the scrap ; format so that it can easily be inserted using PstStylGuts. ; This procedure is called to create the nullStyle handle. ; ---------------------------------------------------------------------- InitRsrved Move.L A2,-(SP) ; save reg MoveQ #nullStSize,D0 ; size of reserved handle Bsr.S MyNewHandle ; NewHandle with error checking Move.L teStylesH(A3),A2 ; get style handle Move.L (A2),A2 ; deref Move.L A0,nullStyle(A2) ; store new handle ; MyNewHandle could thrash the heap. Gotta save this handle for later. Move.L A0,-(SP) ; Save off the handle MoveQ #scrpRecSize+2,D0 ; size of scrap handle ; what? AddQ #2,D0 ; include room for # of styles Bsr.S MyNewHandle ; NewHandle with error checking ; This pulls off the nullStyle handle we saved a few lines ago. ; not needed. Move.L nullStyle(A2),A2 ; get reserved handle Move.L (SP)+,A2 ; Retrieve nullStyle handle Move.L (A2),A2 ; deref Move.L A0,nullScrap(A2) ; store new scrap handle ; what? Move.L nullScrap(A2),A0 ; get handle to scrap for null selection Move.L (A0),A0 ; deref Move.W #0,scrpNStyles(A0) ; indicate no style Move.L (SP)+,A2 ; restore reg Rts ; ---------------------------------------------------------------------- ; PROCEDURE MyNewHandle ; ** ** ; MyNewHandle unlocks the TEHandle and the text handle, attempts ; to allocate memory for a handle, calls system error if there is one, ; And otherwise relocks TEHandle and the text handle. ; Entry: ; D0: requested handle size ; A3: Ptr to TERec ; A4: Handle to TERec ; Exit: ; A0: the handle ; A3: Could have a different value if memory was shifted ; ---------------------------------------------------------------------- MyNewHandle Move.L D0,-(SP) ; save input Move.L teTextH(A3),A0 ; text handle _HUnlock ; make it easy to get memory Move.L A4,A0 ; TEHandle _HUnlock ; make it easy to get memory Move.L (SP)+,D0 ; get the input _NewHandle ; do it Bne badExit ; fly away if system error Move.L A0,-(SP) ; save handle Move.L A4,A0 ; get TEHandle _HLock ; relock it Move.L (A4),A3 ; reset TEPtr Move.L teTextH(A3),A0 ; text handle _HLock ; lock that too Move.L (SP)+,A0 ; restore handle Rts ; ---------------------------------------------------------------------- ; PROCEDURE TEUpdate( r: Rect; h: TEHandle ) ; Redraws the entire object sected by r ; ---------------------------------------------------------------------- TEUpdate Bsr StdEntry Move.L (A2)+,A0 ; get rect Bsr Refresh Bra epilog8 ; ---------------------------------------------------------------------- ; A local cover for do find called from TEClick ; This takes a character index in D6 and expands it into D0,D1 ; For character select mode, it simply copies it into D0,D1, but ; for word select, it locates the surrounding word and returns ; D0,D1 pointing to the word start and end(Respectively) ; Long at D5 negative if word select ; ---------------------------------------------------------------------- ClickExpand Move D6,D0 ; default for no-word select Move D6,D1 Tst.L D5 ; see if word select (if negative) Bpl.S byebye Bsr FindWord ; find word @D0 byebye Rts ; ---------------------------------------------------------------------- ; PROCEDURE HiLite; ; A3 is dereferenced object ; Now this pins the selStart and selEnd to the viewRect lines ; ---------------------------------------------------------------------- HiLite Tst.B teActive(A3) ; don't do if not active Beq.S byebye MoveM teSelStart(A3),D3-D4 ; disp start is D3, disp end is D4 MoveQ #teMark,D7 ; set mark mode Bra DoText ; Remove old selection ; ---------------------------------------------------------------------- ; PROCEDURE TEClick( pt: Point; extend: BOOLEAN; h: TEHandle ); ; Uses: ; D6 as a character index corresponding to the current mouse point ; D5 a copy of the previous D6 ; D5 long sign minus if word select ; A2 anchor left point for hilighting selection ; A4 anchor right for hilighting selection ; D0 for left of word at click spot ; D1 for right of word at click spot ; D3 split dispStarts for left and right piece of highlight ; D4 split dispEnds for left and right piece of highlight ; ---------------------------------------------------------------------- TEClick Bsr StdEntry Bsr ClearRsrved ; clear out reserved style ; Find the new point and get index of it in D6 Move.L 14(A6),teSelPoint(A3) ; pass selPoint Bsr DoFind ; juggle dispStart/End and do find Bsr HideCaret ; Remove caret SubQ #4,SP ; make room for the tickCount _TickCount Move.L (SP)+,D0 ; Ticks in D0 Sub.L teClikTime(A3),D0 ; see if double click Cmp.L doubleTime,D0 ; 1/2 second click time Sle D5 ; D5 = 0 if single click Cmp teClikLoc(A3),D6 ; see if same location Seq D1 And.B D1,D5 ; D5 ST if double click RoR.L #8,D5 ; get switch in high D5 Move D6,teClikLoc(A3) ; double click only if not moved ; D6 now contains the character location at which to look ; Find out if we want an extended selection or a normal one ; For an extended selection, fake out the loop below by fooling it into thinking ; we've already entered it "normally" but with the old selection already ; hilighted, etc. Tst.B 12(A6) ; see if extend flag is on Beq.S notExtended MoveM teSelStart(A3),D0-D1 ; get old selection Cmp D6,D0 ; chk side of new loc Bhs.S useRight Move D0,A2 ; save anchor left Move D0,A4 ; and anchor right Bra.S goToIt useRight Move D1,A2 ; save anchor left Move D1,A4 ; and anchor right goToIt Move D6,D5 Bra.S goSelect notExtended Bsr.S HiLite ; Remove old selection MoveQ #teWordSelect,D2 ; say "ClickExpand, word selection" Bsr.S ClickExpand ; NO ; D0/D1 now contain the "bounds" of this click MoveM D0-D1,teSelStart(A3) Move D0,A2 ; save anchor left Move D1,A4 ; and anchor right Move D6,D5 ; save "old" D6 ; remember whether initial click was to left or right of character Move.B teLftClick(A3),teLftCaret(A3) Bsr ShowCaret ; feedback to user Bsr HiLite waitLoop Move.L teClikProc(A3),D0 ; call the click proc Beq.S noClikProc Move.L D0,A0 Jsr (A0) Beq.S done1 ; if returns zero abort drag noClikProc Clr -(SP) ; make room for result _WaitMouseUp ; see if button still down Tst (SP)+ ; pop result, check only the significant byte <3> - <4> Beq.S done1 Pea teSelPoint(A3) ; pass address for point _GetMouse Bsr.S DoFind ; juggle dispStart/End and do find Cmp D6,D5 ; see if change Beq.S waitLoop Bsr HideCaret ; There was a change so highlight only the new part. This is a really tricky part... ; The thing we're trying to do is is highlight only the part that changes of the ; selection which is being dragged out in this loop goSelect MoveQ #teWordDrag,D2 ; say "ClickExpand, word dragging" Bsr ClickExpand ; Get new points Lea teSelEnd(A3),A0 ; point between selStart/End Cmp D6,A4 ; see if less than anchor right Blo.S notToLeft ; skip if not to left of anchor Move -(A0),D3 ; save previous left Move D0,(A0)+ ; save new left Move D0,D4 ; save dispEnd too Swap D3 Swap D4 Move A4,D3 ; save other dispStart Move (A0)+,D4 ; save other dispEnd Move A4,-(A0) Bra.S hiliteIt notToLeft Cmp D6,A2 ; see if greater than anchor left Bhi.S keepWaiting ; skip if not to right of anchor Move (A0)+,D3 ; save previous right Move D1,-(A0) ; save new right Move D1,D4 ; save dispEnd too Swap D3 Swap D4 Move -(A0),D3 ; save other dispEnd Move A2,D4 ; save other dispStart Move A2,(A0)+ hiliteIt MoveQ #teMark,D7 ; set mark mode Bsr DoText ; do one half Swap D3 ; get other dispStart/End Swap D4 ; and hilight too Bsr DoText ; and other half keepWaiting Move D6,D5 ; save new end Bra.S waitLoop ; continue on done1 Bsr ShowCaret ; redisplay caret ; ** ** Save tick count at the end of TEClick so that ; extra TextEdit computing time will not be counted between clicks SubQ #4,SP ; make room for the tickCount _TickCount Move.L (SP)+,teClikTime(A3) ; remember click time epilog10 MoveQ #10,D0 Bra StdExit ; ---------------------------------------------------------------------- ; DoFind ; Take the teSelPoint(A3) and return D6 w/corresponding char index ; Exit ; D6 contains the selection index returned from DoText ; ---------------------------------------------------------------------- DoFind ; find out which text line it's on Move teSelPoint+v(A3),D0 ; i:=(selPoint.v-destRect.top) Bsr PtToLine ; line index in D0 Bge.S southPole ; below the last line Add D0,D0 ; double D0 Bpl.S noPole ; default if i < 0 is D6 = 0 northPole MoveQ #0,D6 ; if above point to beginning Rts southPole Move teLength(A3),D6 ; return index(t):=length Rts noPole MoveM teLines(A3,D0),D3-D4 ; dispStart := lines[i] MoveQ #teFind,D7 ; set find mode Bsr DoText ; return index(t) in D0 Move D0,D6 ; return in D6 Rts ; ---------------------------------------------------------------------- ; Pixel2Char ; ** Added 6/18/86 MBK ** ; Entry: ; D0.W: length of block ; D1.W: pixel width relative to start of block ; D2.W: slop ; A0: ptr to start of block ; Exit: ; D0 (low word) pixel width to last offset ; (high word) boolean = TRUE if offset corresponding to ; the given pixel width was found ; D1.W: character offset ; D2.W: flagged if hit on left of char ; ---------------------------------------------------------------------- Pixel2Char Move.L jPixel2Char,-(SP) ; call the Pixel2Char Routine Rts vPixel2Char ; here's our Pixel2Char MoveM.L D3-D4/A4,-(SP) Move.W D1,D3 ; save pixel width MoveQ #0,D4 ; clear whole register ** ** Move.W D0,D4 ; save count AddQ #1,D0 ; plus 1 for measure Ext.L D0 ; should be long Add.L D0,D0 ; double for words Move.L D0,D1 ; save in D1 ** ** ; ** ** try to get room on the stack; if not available, ; make a last ditch effort with NewPtr _StackSpace ; get stack size ** ** Sub.l d1,d0 ; stack, use newPtr ** ** Cmp.l #1024,d0 ; ** ** Blt.s tryHeap Sub.l d1,sp ; push the array. ** ** Move.l sp,a4 ; save the array pointer Bra.S onStack tryHeap Move.L D1,D0 ; RESTORE size ** ** Move.L A0,-(SP) ; save text ptr ** ** _NewPtr ; for array of char widths Move.L A0,A4 ; save ptr to array Move.L (SP)+,A0 ; restore text ptr ** ** ; Must save ptr for the dispose, because A4 will be modified. Move.L A4,-(SP) ; save ptr for dispose MoveQ #0,D1 ; to say newPtr was used ** ** Tst.W D0 ; check result code ** ** Beq.S onStack ; continue if no error ** ** Move.W #dsMemFullErr,D0 ; memory full error ** ** _SysError ; else call _SysError ** ** onStack Move.L D1,-(SP) ; save buffer size ** ** Move.W D4,-(SP) ; length of block Move.L A0,-(SP) ; ptr to text Move.L A4,-(SP) ; ptr to charLocs _MeasureText ; measure all at once Move.W D4,D1 ; get count Add.L D4,D4 ; mult count by 2 Add.L D4,A4 ; pt to 1 beyond last entry ** ** Cmp.W (A4),D3 ; pt within width? ; This is to fix the following bug: if you clicked the mouse EXACTLY at ; the end of a line (ended by a CR), the selection was set to the character ; following the CR, instead of preceding it. Bge.S @2 ; quit if not @0 Cmp.W -(A4),D3 ; pt within width? Bge.S @1 ; quit if so SubQ #1,D1 ; dec the count Bne.S @0 ; keep trying AddQ #1,D1 ; adjust for later decrement @1 Move.W 2(A4),D2 ; width to right of offset Move.W (A4),D4 ; width to left of offset Sub.W D4,D2 ; get difference AsR.W #1,D2 ; divide by 2 Add.W D2,D4 ; width to middle of last char MoveQ #1,D0 ; point was found Swap D0 ; store flag in high byte MoveQ #0,D2 ; assume right Cmp.W D4,D3 ; compare to pixel width Bge.S @3 ; left if pixel width is less MoveQ #1,D2 ; else it's to the left Bra.S @3 @2 MoveQ #0,D0 ; found flag is false MoveQ #0,D2 ; right of offset @3 Move.W (A4),D0 ; return pixel width Move.L (SP)+,D3 ; stack or heap? Beq.S @4 ; 0 means heap Add.L D3,SP ; else fix the stack Bra.S @5 @4 Move.L (SP)+,A4 ; restore ptr for dispose MoveM.L D0-D2,-(SP) ; save stuff Move.L A4,A0 _DisposPtr ; dispose of char widths array MoveM.L (SP)+,D0-D2 ; restore stuff @5 MoveM.L (SP)+,D3-D4/A4 Rts ; ---------------------------------------------------------------------- ; DoSearch ; ** Rewritten 6/18/86 MBK ** ; ---------------------------------------------------------------------- DoSearch ; ** ** Modified to call Preamble to get A2; the index ; is in D0, but don't use it since it's not ; documented in Inside Mac Bsr Preamble ; get A2 from D3 Move (A2),D3 ; set left anchor <14Jan86> Move D3,D4 ; init char counter Bsr LineRect ; set rLine to A2 line Move (A2),D7 ; set left anchor Move.W teSelPoint+h(A3),D5 ; get h coord Sub.W teSelRect+left(A3),D5 ; subtract justification Move teSelRect+left(A3),teSelRect+right(A3) ; init right side to left Move.W #$8002,teSelRect+left(A3) ; bogus left Move.W 2(A2),D6 ; end of line Tst.W teSize(A3) ; check style flag Bmi.S @0 MoveQ #1,D2 ; just 1 style Move.W D3,D1 ; start of line Move.W D6,D0 ; whole line Bra.S @3 @0 Move.W D3,D0 ; get selection start!!! Move.W D6,D1 ; end of line Bsr Get1stStyle ; get 1st style (depending on teSysJust) Move.L A0,A2 ; preserve ptr to current style Move.W D0,D2 ; preserve # of styles Move.L teStylesH(A3),A0 ; handle to style info ** ** _HLock ; lock it up ** ** Move.L A2,A0 ; restore style ptr ** ** @1 Move.L A0,A2 ; save ptr to style start Bsr SetStyle ; set the style Move.W startChar(A0),D1 ; get start of style AddQ.L #stStartSize,A0 ; pt to next style Move.W startChar(A0),D0 ; start of next style Cmp.W D3,D1 Bhs.S @2 ; made this unsigned ** ** Move.W D3,D1 ; reset if needed @2 Move.W D1,D7 Cmp.W D0,D6 ; compare to end of line Bhs.S @3 ; made this unsigned ** ** Move.W D6,D0 ; set end of style to end of line @3 Move.W D2,-(SP) Sub.W D1,D0 ; length Move.L teTextH(A3),A0 ; handle to text Move.L (A0),A0 ; dereference AddA.W D1,A0 ; add offset to start of line Move.W D5,D1 ; get pixel offset MoveQ #0,D2 ; slop ** ** ; Bsr Pixel2Char ; measure all at once Bsr.S TEHitTestHook ; call our hook instead Add.W D0,teSelRect+right(A3) ; update selRect Sub.W D0,D5 ; update pixel offset Add.W D1,D7 ; update char offset Swap D0 ; get flag Tst.W D0 ; pixel to left of offset? Bne.S HitIt ; point was found Add.W D1,D4 ; current position Cmp.W D4,D6 ; reached end of line? Bls.S @4 ; made this unsigned ** ** Move.L A2,A0 ; ptr to current style Move.W (SP)+,D2 ; restore style count Bsr GetNextStyle ; get next one based on teSysJust SubQ #1,D2 ; dec # of styles Bne.S @1 ; keep looping if more NO MoveQ #1,D7 ; decremented below Bra.S findLeft ; force to loc 0 on left @4 Move.W #$7FFE,teSelRect+right(A3) ; else store bogus right MoveQ #0,D2 ; assume right Move.L teTextH(A3),A0 ; get text handle Move.L (A0),A0 ; dereference ; ** Added this code to support tabs ; Cmp.B #$0D,-1(A0,D7) ; get the last charleft Move.B -1(A0,D7),D0 ; THESE TWO LINES REPLACE PREVIOUS Bsr.S TEEolHook ; Bne.S hitIt ; must be right MoveQ #1,D2 ; else set left if CR hitIt AddQ.L #2,SP ; remove count from stack SF teLftClick(A3) ; assume to right Tst.W D2 ; left or right? Beq.S findDone findLeft SubQ #1,D7 ; adjust result to left half ST teLftClick(A3) ; mark it to left findDone Tst.W teSize(A3) ; check style flag Bpl.S @5 Move.L teStylesH(A3),A0 ; handle to style info _HUnlock ; unlock it @5 Move D7,D0 ; return in D0 Bra doBye ; ---------------------------------------------------------------------- ; TEEolHook ; ; This vectored routine was added to make life simpler for those who ; wanted to add tabs to TextEdit. We won't officially support it, ; but it's here for people who need it. ; ---------------------------------------------------------------------- TEEolHook Move.L teDispatchH(A3),A0 Move.L (A0),A0 ; get at table Move.L EOLHook(A0),A0 Jmp (A0) ; ---------------------------------------------------------------------- ; xEOLHook ; ; Actual routine that tests character as end-of-line character. Stock ; version only checks for CR. To support tabs you'd add a ; test for TAB here as well, and then determine if the TAB puts ; you over the length for Òend of lineÓ. ; ENTRY: D0.B = character to check ; ---------------------------------------------------------------------- XEOLHook Cmp.B #$0D,D0 ; is it a CR? Rts ; return with telltale CCR ; ---------------------------------------------------------------------- ; TEWidthHook ; ; Added hook for those needing to intercept the measurement of a line ; Stock version only calls Char2Pixel. To support tabs, you'd check ; the selection to be measured for tabs and add in the appropriate ; tab widths. ; ENTRY: A0.L => Text to measure ; D0.W = Length of text to be measured ; D1.W = Offset into text ; D2.L = Slop (low word) ; Hilite flag (high word) ; EXIT: D1.W = Width of measured text ; ---------------------------------------------------------------------- TEWidthHook Move.L teDispatchH(A3),A1 Move.L (A1),A1 Move.L WIDTHHook(A1),A1 Jmp (A1) ; ---------------------------------------------------------------------- ; TEHitTestHook ; ; Added hook for those needing to intercept hit testing on a line ; Stock version only calls Pixel2Char. To support tabs, you'd check ; the selection to be tested and add in the appropriate tab widths. ; ENTRY: A0.L => ptr to start of block ; D0.W = Length of block ; D1.W = Pixel width relative to start of block ; D2.L = Slop ; EXIT: D0.L = Pixel width to last offset (low word) ; BOOLEAN = TRUE if offset corresponding to ; the given pixel width was found (high word) ; D1.W = Character offset ; D2.W = Flagged if hit on left of char ; ---------------------------------------------------------------------- TEHitTestHook Move.L teDispatchH(A3),A1 Move.L (A1),A1 Move.L HITTESTHook(A1),A1 Jmp (A1) ; ---------------------------------------------------------------------- ; TEDrawHook ; ; Added hook for those needing to intercept the drawing of a line ; ---------------------------------------------------------------------- TEDrawHook Move.L teDispatchH(A3),A1 Move.L (A1),A1 ; get at table Move.L DRAWHook(A1),A1 Jmp (A1) ; ---------------------------------------------------------------------- ; xDRAWHook ; ; Actual routine that does drawing. Stock version only does _DrawText. ; To support tabs, you'd check the selection to be drawn for tabs, ; and take appropriate action on the intervening pieces. ; ENTRY: A0.L => text to draw ; D0.W = starting character ; D1.W = length to draw ; ---------------------------------------------------------------------- xDRAWHook Move.L A0,-(SP) Move.W D0,-(SP) Move.W D1,-(SP) _DrawText Rts ; ---------------------------------------------------------------------- ; DoDraw ; ** Rewritten 6/18/86 by MBK ** ; Given display start and end in [D3..D4], this draws the text ; ---------------------------------------------------------------------- DoDraw Bsr PinDisplay Bsr Preamble ; set rLine to A2 line ; ** Only call LineRect at start to avoid height search ** Bsr LineRect @0 Bsr PrepLine ; pin D4 at line end Bls doBye ; done... Bsr ChkBounds ; extend bounds if necessary Tst.W teSysJust ; reverse order? Beq.S @05 ; no, normal Move.W #$8002,teSelRect+left(A3) ; else, set unbound left @05 Move.W D4,D6 ; selEnd Bsr DoErase ; to fix italics problem** ** Move.W saveLeft(A6),-(SP) ; saved true left value ** Got rid of rTrue ** Move.W teSelRect+top(A3),-(SP) ; position pen Move teAscent(A3),D0 Tst.W teSize(A3) ; check style flag Bmi.S @1 ; record has no style, so draw all at once (the old way) Add D0,(SP) ; drop pen to baseline _MoveTo Move.L teTextH(A3),A0 ; get text handle Move.L (A0),A0 ; dereference Add.L D3,A0 ; offset pointer ; ** Added code to support tabs ; Move.L A0,-(SP) ; pass pointer ; Clr -(SP) ; no offset ; Move D4,-(SP) ; range ; Sub D3,(SP) ; draw amt := range-i ; _DrawText ; draw it Clr.W D0 ; D0-D1 aren't a concern, sinceÉ Move.W D4,D1 ; Éone would expect _DrawTextÉ Sub.W D3,D1 ; Éto blow them away anyways Bsr.S TEDrawHook ; go draw it Bra.S @6 ; NO ; record has style, so draw one style at a time @1 Tst.W D0 ; check default ascent Bpl.S @2 ; use it if set Bsr PtrToLine ; get line # Ext.L D0 ; make it long just in case ** ** LsL.L #2,D0 ; mult by 4 ** ** Move.L teStylesH(A3),A0 ; handle to style info Move.L (A0),A0 ; deref Move.L lhTab(A0),A0 ; array of max hite indeces Move.L (A0),A0 ; deref Move.W 2(A0,D0.L),D0 ; max ascent @2 Add D0,(SP) ; drop pen to baseline _MoveTo Move.W D3,D0 ; start offset Move.W D4,D1 ; end of selection ; ** Changed to Get1stStyle for International ** Bsr Get1stStyle ; get its style Move.W D0,D2 ; save style count @3 Move.L A0,A4 ; ptr to style Bsr SetStyle ; set style Move.W startChar(A0),D0 ; get start of style AddQ #stStartSize,A0 ; ptr to next style Move.W D6,D4 ; init to end of line Cmp.W startChar(A0),D6 ; compare to end of line Blo.S @4 Move.W startChar(A0),D4 ; set to end of style @4 Move.W D2,-(SP) ; save the count Move.L teTextH(A3),A0 ; get text handle Move.L (A0),A0 ; dereference Cmp.W D3,D0 Bhs.S @5 ; made this unsigned ** ** Move.W D3,D0 ; reset if needed @5 AddA.W D0,A0 ; offset pointer ; ** Added code to support tabs ; Move.L A0,-(SP) ; pass pointer ; Clr -(SP) ; no offset ; Move D4,-(SP) ; range ; Sub D0,(SP) ; draw amt := range-i Move.L teStylesH(A3),A1 ; get style handle Move.L (A1),A1 Sub.L A1,A4 ; save as an offset ; _DrawText ; draw it Move.W D4,D1 ; amount := range - i Sub.W D0,D1 ; Clr.W D0 ; no offset Bsr TEDrawHook ; go draw it ; Unlock the style handle when through with pointer. Move.L teStylesH(A3),A1 ; get style handle Move.L (A1),A1 Add.L A1,A4 ; restore as pointer Move.L A4,A0 ; ptr to style Move.W (SP)+,D2 ; restore the count Bsr GetNextStyle ; get next based on teSysJust SubQ #1,D2 ; dec the style counter Bne.S @3 ; must be more than 1 line ; ** NextLineRect will not search for height from start ** @6 Bsr PtrToLine ; convert A2 to line # AddQ #1,D0 ; next line Bsr NextLineRect ; set next line's rect Move (A2),D3 ; get start Bra @0 ; keep going doBye MoveM.L (SP)+,D2-D7/A2-A4 ; restore regs Unlk A6 ; unlink DoText frame Move.L grafGlobals(A5),A0 ; get the port in A0 for Move.L thePort(A0),A0 ; compatibility Rts ; ---------------------------------------------------------------------- ; DoErase ; ** ** ; DoErase was added to solve the problem of half the previous ; character getting erased when an EraseRect is done before ; drawing the current character. (This is a problem for Italics ; And certain special fonts). In DoErase, if the offset is the ; same as the line start, I still erase the whole line, in case ; of a change in line height (and the offset must be the same as ; a line start if the line height has changed); otherwise, I ; don't erase the previous character since it's going to be ; drawn over anyway. ; Entry: ; D3: start offset ; A2: line start ; ------------------------------------------------------------------------ DoErase Move.W teSelRect+left(A3),-(SP) ; save left side for draw Cmp.W (A2),D3 ; at start of line? Beq.S @2 ; don't worry if so ; If the mode is XOR, we must erase the previous character as well as redrawing it. ; Redrawing the character in XOR without erasing it first just erases it. This means ; the italics problem will not be fixed in this mode. Cmp.W #srcXor,teMode(A3) ; is drawing mode XOR? Beq.S @2 ; do it the old way if so Tst.W teSize(A3) ; TERec with style? Bpl.S @1 ; skip style setup if not Move.W D3,D0 ; selection start Move.W D0,D1 ; don't care about end Bsr.S Get1stStyle ; 1st style on line NO Bsr SetStyle ; set the port @1 SubQ.L #2,SP ; room for result Move.L teTextH(A3),A0 ; text handle Move.L (A0),-(SP) ; ptr on stack Move.W D3,-(SP) ; offset to current char Move.W #1,-(SP) ; just one char _TextWidth ; how wide is it? Move.W (SP)+,D0 ; this wide ; Don't want to erase the prev character because that destroys part of the character ; before it (if it's italics or a kerned font). However, the last pixel should be erased ; in case the application leaves a caret drawn there (like Mac3D does). Tst.W D0 ; nothing to do if no width ** ** Beq.S @0 ; else subtract one from char width ** ** SubQ.W #1,D0 ; to fix caret erase problem ** ** @0 Add.W D0,teSelRect+Left(A3) ; adjust left @2 Pea teSelRect(A3) ; erase the expanded rect _EraseRect Move.W (SP)+,teSelRect+left(A3) ; restore left side for draw Rts ; ---------------------------------------------------------------------- ; Get1stStyle ; ** Added for International ** ; This returns the 1st style block found on a line of text ; If teSysJust = 0, and the last style block on the line ; otherwise. ; Entry: ; D0: start offset ; D1: End offset ; Exit: ; A0: ptr to style block to be processed 1st ; D0: number of styles between the 2 offsets ; ---------------------------------------------------------------------- Get1stStyle Bsr GetCurStyle ; get style at start offset Bsr GetNumStyles ; get # of styles in string Tst.W teSysJust ; is text left to right? Beq.S @0 ; if so, that's it MoveQ #0,D1 ; clear whole register ** ** Move.W D0,D1 ; else, get # of styles SubQ.W #1,D1 LsL.L #2,D1 ; * stStartSize ** ** Add.L D1,A0 ; to pt to last style block ** ** @0 Rts ; ---------------------------------------------------------------------- ; GetNextStyle ; ** Added for International ** ; This returns the next style block found on a line of text. ; If teSysJust = 0, this is the following style block; ; If teSysJust <> 0, this is the preceding style block. ; Entry: ; A0: ptr to current style block ; Exit: ; A0: ptr to next style block ; ---------------------------------------------------------------------- GetNextStyle Tst.W teSysJust ; is text left to right? Beq.S @0 SubQ.L #stStartSize,A0 ; no, get preceding style Bra.S @1 @0 AddQ.L #stStartSize,A0 ; yes, get following style @1 Rts ; ---------------------------------------------------------------------- ; PrepLine ; Given display start and end in [D3..D4], and a line start in ; (A2), this gets the line's rectangle in rLine(A6). Then pins ; D4 at the lineStart of the next line. Then gets the range's ; rectangle in rTrue. And, the expanded rect in teSelRect(A3). ; (It calls range rect to do this). Finally exits with CC's ; Set according to D3 and D5(the length). ; Exit: ; CC's set to relationship of D3 to dispEnd in D5 ; ---------------------------------------------------------------------- PrepLine Move D5,D4 ; get right Cmp 2(A2),D4 ; pin to right Blo.S @0 Move 2(A2),D4 ; set to line end @0 Bsr RangeRect ; get rect from D3 to D4 in teSelRect Cmp D3,D5 ; finished? Rts ; ---------------------------------------------------------------------- ; Preamble ; Given display start and end in [D3..D4], this first sorts the ; two, and copies D4 into D5. Then, it skips to the lineStart ; entry containing D3. It sets up A2 to point to that line. ; Exit: ; CC's set to relationship of D3 to the next line's start, 2(A2) ; D5 a copy of incoming D4 ; ---------------------------------------------------------------------- Preamble Move.L (SP)+,A0 ; get local RTS MoveM.L D2-D7/A2-A4,-(SP) Move.L A0,-(SP) ; replace RTS Cmp D3,D4 ; sort range Bhs.S @0 Exg D4,D3 ; swap regs @0 Cmp teLength(A3),D4 ; pin disp end Blo.S @1 Move teLength(A3),D4 ; pin disp end @1 Lea teLines(A3),A2 ; point to line starts And.L lo16,D4 ; longize D4 Move D4,D5 ; save D5 as limit And.L lo16,D3 ; longize D3 Beq.S @2 ; skip out if 1st line(for empty rec.) Move.W D3,D0 Bsr.S GetLine ; get its line ptr NO @2 Rts ; ---------------------------------------------------------------------- ; GetLine ; Given an offset, find the ptr to the line it's on. ; Entry: D0: offset ; A2: ptr to line from which to start search ; Exit: A2: ptr to line on which offset is found ; ---------------------------------------------------------------------- GetLine @0 Cmp 2(A2),D0 ; D0 past or at next linestart? Bls.S @1 ; if at next line start AddQ #2,A2 ; next lineStart Bra.S @0 @1 Bne.S @2 ; if AT next line start AddQ #2,A2 ; next lineStart @2 Rts ; ---------------------------------------------------------------------- ; DoText funnel proc for compatibility DoText Move.L teDoText,-(SP) Rts XDoText Link A6,#txtLink ; link frame for DoText procs Tst D7 ; check dispatch code Beq DoSearch Bgt.S DoHilite Cmp #-1,D7 Beq DoDraw ; fall into doCaret ; ---------------------------------------------------------------------- ; DoCaret ; Given display start sets up the caret rect in teSelRect. Note ; all the weird shit it has to do because of caret positioning ; around the end of a line and at the end of the text. ; ---------------------------------------------------------------------- DoCaret Bsr.S Preamble ; set rLine to A2 line Tst D3 ; special case @ 1st character <03Nov85> SC Beq.S @2 ; if so skip all these checks <03Nov85> SC Cmp (A2),D3 ; right at line start? Bne.S @2 ; skip if not next-line start Move teLength(A3),D0 ; are we past last char? Beq.S @2 ; (and is there a last char?) Cmp D0,D3 ; are we past last char? Blo.S @0 ; if not, skip special case Move.L teTextH(A3),A0 ; get text handle Move.L (A0),A0 ; dereference ; ** Added this code to support tabs ; Cmp.B #$0D,-1(A0,D3) ; if last char <> CR then... Move.B -1(A0,D3),D0 ; THESE TWO LINES REPLACE PREVIOUS Bsr TEEolHook ; Beq.S @2 ; skip the line Bra.S @1 @0 Tst.B teLftCaret(A3) ; to left? Bne.S @2 ; skip line pull back if so @1 SubQ #2,A2 ; skip to previous line @2 Bsr LineRect ; removed from Prep ** ** Bsr PrepLine ; get selRect from D3..D4 NO Move saveLeft(A6),D0 ; get caret loc Move D0,teSelRect+right(A3) ; and set in teSelRect SubQ #1,D0 Move D0,teSelRect+left(A3) Bra doBye ; ---------------------------------------------------------------------- ; DoHilite ; ---------------------------------------------------------------------- DoHilite Bsr PinDisplay Bsr Preamble ; set rLine to A2 line Bsr LineRect ; get top, bottom and just Bsr PrepLine ; pin D4 at line end Bls.S @1 ; done... NO Bsr.S ChkBounds ; check far left and right NO Move.L teHiHook(A3),D0 ; do the inversion via hook if Bsr InvertHook ; there Cmp.W 2(A2),D5 ; only 1 line? Bls.S @1 ; made this unsigned ** ** Bsr PtrToLine ; get current line # Move.W D0,D1 ; save it Move.W D5,D0 ; offset to look for Bsr GetLine ; get D5 line ptr Bsr PtrToLine ; convert A2 ptr to line # AddQ #1,D1 Cmp.W D0,D1 ; get the difference Beq.S @0 ; no lines inbetween Move.W D0,-(SP) ; save line # Exg D0,D1 Move.W teSelRect+bottom(A3),teSelRect+top(A3) Bsr GetLineHites ; hites from 2nd to last lines Add.W D0,teSelRect+bottom(A3) ; hite to last line Move.W #$8002,teSelRect+left(A3) ; far left Move.W #$7FFE,teSelRect+right(A3) ; far right Move.L teHiHook(A3),D0 Bsr InvertHook ; hilite it Move.W (SP)+,D0 ; restore line # ; hilite last line @0 Bsr.S NextLineRect ; get rectangle for last line NO Move.W (A2),D3 ; for chkBounds Bsr PrepLine ; get left and right Bls.S @1 ; done... Bsr.S ChkBounds ; check far left and right NO Move.L teHiHook(A3),D0 ; do the inversion via hook if Bsr InvertHook ; there @1 Bra doBye ; ---------------------------------------------------------------------- ; ChkBounds ; ** Added for International ** ; The left and right sides of the selection rectangle are ; extended if the line start = the selection start and the ; line end = the selection end, respectively. ; Entry: ; A2 : Ptr to the current line ; ---------------------------------------------------------------------- ChkBounds Move.W (A2),D0 ; start of line Move.W 2(A2),D1 ; end of line Tst.W teSize(A3) ; record with style? Bpl.S @2 ; skip ahead if not Tst.W teSysJust ; reverse order? Beq.S @2 ; this is easy if not Bsr Get1stStyle ; get actual 1st style SubQ #1,D0 ; look for end of last style Bne.S @0 ; Reset start and end of line if only 1 style Move.W (A2),D0 ; reset start of line Move.W 2(A2),D1 ; end of line Bra.S @2 ; more than 1 style, so find actual start and end line offsets @0 SubQ #1,D0 ; dec style count LsL.W #2,D0 ; * stStartSize ** ** Neg D0 ; negative for subtraction Move.W startChar(A0,D0),D1 ; start of next-to-last style Move.W (A2),D0 ; get start of line again Cmp.W startChar(A0),D0 ; compare to start of style Bhs.S @2 ; made this unsigned ** ** Move.W startChar(A0),D0 ; else set to style start ; if block begins at start of line, make left a large negative number @2 Cmp.W D0,D3 Bne.S @3 Move.W #$8002,teSelRect+left(A3) ; if block ends at end of line, make right a large positive number @3 Cmp.W D1,D4 Bne.S @4 Move.W #$7FFE,teSelRect+right(A3) @4 Rts ; ---------------------------------------------------------------------- ; NextLineRect ; ** Added to speed things up ** ; LineRect was being called from the line drawing loop in ; DoDraw, and adding up line heights from the 1st line to the ; current one. That was fine for fixed line heights, but too ; slow for variable ones. Now I call NextLineRect from the ; loop to simply set the top of this line from the bottom of ; the previous one, and get the height of this line only to ; Set the bottom. NextLineRect also calls DoJust to set ; the justification. ; Entry: ; D0: Current line # ; Exit: ; A2: Ptr to current line # ; ---------------------------------------------------------------------- NextLineRect Move.W teSelRect+bottom(A3),teSelRect+top(A3) Bsr GetHite ; get height of this line Add.W D1,teSelRect+bottom(A3) ; adjust bottom ; ** ** Replaced call to LineToPtr with these 2 lines ; since noone else called it Add.W D0,D0 ; double for word entries ** ** Lea teLines(A3,D0),A2 ; pt to line starts array ** ** Move.W teDestRect+left(A3),teSelRect+left(A3) Bsr.S DoJust ; set the justification NO Rts ; ---------------------------------------------------------------------- ; PtrToLine ; ** ** ; Get the line # from the A2 value. ; Entry: ; A2: Ptr to current line # ; Exit: ; D0: Current line # ; ---------------------------------------------------------------------- PtrToLine Lea teLines(A3),A0 ; pt to line starts array Move.L A2,D0 ; current line ptr Sub.L A0,D0 ; current line offset AsR.L #1,D0 ; current line number Rts ; ---------------------------------------------------------------------- ; LineRect ; ** Modified 6/18/86 by MBK ** ; Given the line start array in A2, this fills in the rLine(A6) ; With the rectangle for that line except that right = left. ; It adjusts the rect for the current format. ; ---------------------------------------------------------------------- LineRect Bsr.S PtrToLine ; get line # from A2 NO Move.W D0,D1 MoveQ #0,D0 ; from 0 to this line ** MBK 6/18/86 ** Bsr.S GetLineHites ; get height NO Lea teDestRect+8(A3),A0 ; point past destRect Lea teSelRect+8(A3),A1 ; and past stack rect Move.L -(A0),-(A1) Move.L -(A0),-(A1) Add D0,(A1) ; add to top Move top(A1),bottom(A1) Move.W D1,D0 ; current line ** MBK 6/18/86 ** Bsr GetHite ; height of this line ** MBK 6/18/86 ** Add D1,bottom(A1) ; add line height to bottom ; now offset to right according to the format ; ** ** Added the DoJust label for just doing justification DoJust ; ** ** Changed to save justification on stack instead of in D2 Move.W teJust(A3),-(SP) ; get justification ** ** Bne.S @0 ; go process if not left** ** Move.W teSysJust,(SP) ; check text direction ** ** Beq.S @2 ; do nothing if left @0 Cmp.W #teForceLeft,(SP) Beq.S @2 Bsr LineWidth ; get width of (A2) line in D0 Move teDestRect+right(A3),D1 Sub teDestRect+left(A3),D1 Sub D0,D1 SubQ #1,D1 ; subtract one for caret Tst.W (SP) ; see what format Bmi.S @1 AsR #1,D1 ; div by 2 for centering @1 Add D1,teSelRect+left(A3) ; bump rect over @2 AddQ #1,teSelRect+left(A3) ; indent for caret Move teSelRect+left(A3),teSelRect+right(A3) Move.W teSelRect+left(A3),saveJust(A6) ; left just ** ** AddQ.L #2,SP ; restore it ** ** Rts ; ---------------------------------------------------------------------- ; PROCEDURE GetLineHites ; ** Added 6/3/86 by MBK ** ; Gets the line height of each line from start to end line and ; returns the total of all the line heights. If teLineHite ; has a non-zero value, a fixed line height is used ; for each line. Otherwise, GetLineHites gets the line height ; for each line from the MaxHites array. ; Entry: ; D0 starting line # ; D1 ending line # (Preserved) ; Exit: ; D0 total distance in pixels from top of start line to top of ; End line ; ---------------------------------------------------------------------- GetLineHites MoveM.L D1-D2,-(SP) ; save stuff ; If this TERec has no style, just use the old teLineHite Sub.W D0,D1 ; get # of lines Beq.S @0 ; if none, skip this Move.W teLineHite(A3),D2 ; get default line hite ; If lineHite is positive, use it no matter what type of TERec. Bpl.S @0 Tst.W teSize(A3) ; check style flag Bmi.S @1 ; if not, use TERec value ; somebody set the default, so use fixed line height for all lines @0 MulU D1,D2 ; * fixed line height Bra.S @3 ; that was easy! NO ; Get maximum height on this line from the array @1 Move.L teStylesH(A3),A0 ; handle to style info Move.L (A0),A0 ; dereference Move.L lhTab(A0),A0 ; handle to max hites Move.L (A0),A0 ; dereference LsL.W #2,D0 ; multiply by 4 AddA.W D0,A0 ; starting line MoveQ #0,D2 ; line height accumulator @2 Move.W (A0),D0 ; get line height ** ** And.W #$7FFF,D0 ; mask out high bit ** ** Add.W D0,D2 ; accumulate heights AddQ #4,A0 ; point to next SubQ #1,D1 ; dec the counter Bne.S @2 ; keep accumulating @3 Move.L D2,D0 ; answer in D0 MoveM.L (SP)+,D1-D2 ; restore stuff Rts ; ---------------------------------------------------------------------- ; PROCEDURE GetHite ; ** Added 6/16/86 by MBK ** ; Gets the line height of the given line. ; Entry: ; D0 line number ; Exit: ; D1 height of this line ; ---------------------------------------------------------------------- GetHite ; If this TERec has no style, just use the old teLineHite Move.W teLineHite(A3),D1 ; get default line height Bpl.S @0 ; use it if set ** ** Tst.W teSize(A3) ; check style flag Bpl.S @0 ; if not, use TERec value ; Get maximum height on this line from the array Move.L teStylesH(A3),A0 ; handle to style info ** ** Move.L (A0),A0 ; dereference ** ** Move.L lhTab(A0),A0 ; handle to max hites ** ** Move.L (A0),A0 ; dereference Move.W D0,D1 ; preserve D0 ** ** LsL.W #2,D1 ; for 2 word entries ** ** Move.W 0(A0,D1),D1 ; get height ** ** And.W #$7FFF,D1 ; mask out high bit ** ** @0 Rts ; ---------------------------------------------------------------------- ; LineWidth ; Measures the width of the line at (A2)..2(A2). Trims break chars ; from the right side ; Entry ; A3 = dereferenced handle to TE object ; Exit ; leaves the width in D0 ; ---------------------------------------------------------------------- LineWidth Move (A2),D6 ; get left anchor Move 2(A2),D7 ; get right part MeasD6D7 Move.L teTrimMeasure,-(SP) ; push trimMeasure routine Rts ; and call it XTrimMeasure Cmp teLength(A3),D6 ; are we past last char? Beq.S zeroExit ; escape quick NO Cmp D6,D7 ; is line empty? Bls.S zeroExit ; if so, skip trimming(fast exit)NO Move.L teTextH(A3),A0 ; get text handle Move.L (A0),A0 ; dereference @0 SubQ #1,D7 ; look to left Cmp D6,D7 Beq.S @1 ; assume done if = to left Cmp.B #$20,0(A0,D7) ; if last char <= space then... Bls.S @0 ; it's a break @1 AddQ #1,D7 ; use next char ; fall into MeasureIt ; get width in [D6 to D7) ; ---------------------------------------------------------------------- ; MeasureIt ; ** Rewritten 6/20/86 by MBK ** ; Entry ; A3 = dereferenced handle to TE object ; Does a TextWidth for teTextH(A3), [D6 to D7] ; Exit ; leaves the width in D0 ; ---------------------------------------------------------------------- MeasureIt Cmp D6,D7 ; nothing to measure? Bls.S zeroExit ; NO MoveM.L D2/D4/D6,-(SP) ; save stuff And.L lo16,D6 ; longize it ; Skip all the new stuff if style is not set Tst.W teSize(A3) ; record with style? Bmi.S @0 ; if not, go do it the old way Move.W D7,D0 ; end offset Bsr.S GetWidth ; get string width NO Move.W D1,D0 ; return width in D0 Bra.S @3 ; Record does have style; get # of styles within selection @0 MoveQ #0,D4 ; clear accumulator Move.W D6,D0 ; start of selection Bsr GetCurStyle ; get current style Move.W D7,D1 ; end of selection Bsr GetNumStyles ; # of styles in selection Move.W D0,D2 ; save # of styles ; Set the GrafPort to the current style @1 Bsr SetStyle ; set current style AddQ #stStartSize,A0 ; pt to next style Move.W startChar(A0),D0 ; start of next style Cmp.W D0,D7 ; compare to end of selection Bhs.S @2 ; ok if less Move.W D7,D0 ; else set to end of selection ; Get the width of this selection @2 Move.W D2,-(SP) ; save the count Bsr.S GetWidth ; get string width NO ; Accumulate total width of the selection Add.W D1,D4 ; accumulate width Move.W (SP)+,D2 ; restore the count Move.W startChar(A0),D6 ; start of next style SubQ #1,D2 ; dec the style counter Bne.S @1 ; more styles Move.W D4,D0 ; return width in D0 @3 MoveM.L (SP)+,D2/D4/D6 ; restore stuff Rts zeroExit MoveQ #0,D0 ; nothing to measure Rts GetWidth Tst.W teSize(A3) ; record with style? Bpl.S @0 ; if not, A0 is nothing Move.L teStylesH(A3),A1 ; get style handle Move.L (A1),A1 ; dereference Sub.L A1,A0 ; save as offset @0 Move.L A0,-(SP) ; save A0 Move.L teTextH(A3),A0 ; get text handle Move.L (A0),A0 ; dereference Move.W D6,D1 ; offset into text Sub.W D1,D0 ; length MoveQ #0,D2 ; slop, hilite flag ** ** ; Bsr.S Char2Pixel ; get width NO Bsr TEWidthHook ; THIS LINE REPLACES PREVIOUS Move.L (SP)+,A0 ; restore A0 Tst.W teSize(A3) ; record with style? Bpl.S @1 ; if not, A0 is nothing Move.L teStylesH(A3),A1 ; get style handle Move.L (A1),A1 ; dereference Add.L A1,A0 ; restore as pointer @1 Rts ; ---------------------------------------------------------------------- ; Char2Pixel ; ** ** ; Entry: A0: ptr to text ; D0.W length of text to be measured ; D1.W offset into text ; D2 slop (low word) ; hilite flag (high word) ; Exit: D1.W width of measured text ; ---------------------------------------------------------------------- Char2Pixel Move.L jChar2Pixel,-(SP) ; call the Char2Pixel Routine Rts vChar2Pixel ; here's our Char2Pixel SubQ #2,SP ; room for result Move.L A0,-(SP) ; pass pointer Move.W D1,-(SP) ; offset Move D0,-(SP) ; length _TextWidth ; get width Move.W (SP)+,D1 ; resulting width Rts ; ---------------------------------------------------------------------- ; RangeRect ; Given the line rect in rLine(A6), this sets teSelRect to the ; line rect with the left side at the given loc in D3 and the ; right side at D4. If D3 is the first char on the line, it ; ---------------------------------------------------------------------- RangeRect Cmp.W (A2),D3 ; same as line start? Bhi.S @0 ; made this unsigned ** ** Cmp.W 2(A2),D4 ; same as line end? Blo.S @0 ; made this unsigned ** ** ; Must set D6 in this case (DoMeasure sets it but MeasureIt doesn't) Move.W (A2),D6 ; set D6 to beg of line ** ** Move.W D4,D7 ; just need 2nd measure Bsr MeasureIt ; measure whole line Add.W D0,teSelRect+right(A3) ; save right side Bra.S @1 ; done with measuring @0 Move D3,D7 ; get measure right Bsr.S DoMeasure ; measure from [D6..D7) NO Add D0,teSelRect+left(A3) ; set left Move D4,D7 ; get 2nd measure right Bsr.S DoMeasure ; measure from [D6..D7) NO Add D0,teSelRect+right(A3) ; save right side @1 Lea teSelRect(A3),A1 Move.W left(A1),saveLeft(A6) ; just need to save left Move left(A1),tempRect ; compatibility shit Move.L botRight(A1),-(SP) ; push pen loc for compatibility ; In the pre-Mac+ version Capps used pnLoc throughout DoText. He added the ; MoveTo here to maintain compatibility with that, but unfortunately in the ; pre-Mac+ version the pnloc is less by line height minus ascent. ; This fixes bug LM-RM-107. Don't worry about new style records since this ; is only for maintaining compatibility with old apps. ;; If forRAM THEN If (not forROM) THEN ; <19Feb89smb> BTst #14,ROM85 ; are we on a color system? (as per Jerome) Bnz.S @2 ; Nope EndIf ;; <19Feb89smb> If onNuMac|onMvMac|forRAM THEN ; rwh Tst.W teSize(A3) ; if it's a new style record Bmi.S @2 ; don't have to worry about it Move.W teLineHite(A3),D0 ; else, get hite - ascent Sub.W teAscent(A3),D0 Sub.W D0,(SP) ; subtract from pnloc.v @2 ;; <19Feb89smb> EndIf _MoveTo ; compatibility shit Rts ; ---------------------------------------------------------------------- ; DoMeasure ; ** MBK ** ; DoMeasure was added to handle reverse justification. ; DoMeasure measures from the actual start of the line ; to the given offset. MeasureIt is still called directly ; when the distance between 2 offsets is desired. ; ---------------------------------------------------------------------- DoMeasure MoveM.L D3/D5-D6,-(SP) MoveQ #0,D5 ; width accumulator Move.W (A2),D6 ; line start Cmp D6,D7 ; nothing to measure? Blo.S @4 ; made this unsigned ** ** Tst.W teSize(A3) ; style record? Bpl.S @3 ; just do normal measure if not Tst.W teSysJust ; reverse order? Beq.S @3 ; just do normal measure if not Move.W D6,D3 ; start offset Move.W (A2),D0 ; start of line Move.W 2(A2),D1 ; end of line Bsr Get1stStyle ; get actual 1st style on line Move.W D7,D0 ; end offset @0 Move.W startChar(A0),D6 ; store actual start of line Cmp.W D6,D3 ; should not be less than Bls.S @1 ; made this unsigned ** ** Move.W D3,D6 ; the selection start @1 Cmp.W D6,D7 ; if greater than selection end Blo.S @2 ; then end is not in this style Move.W D7,D0 ; selection end Cmp.W stStartSize(A0),D7 ; if less than next style start Bls.S @3 ; made this unsigned ** ** @2 Move.W stStartSize(A0),D0 ; else set end as next Cmp.W 2(A2),D0 ; style start Bls.S @25 ; made this unsigned ** ** Move.W 2(A2),D0 ; line's end @25 Move.W D0,-(SP) ; SetStyle destroys this ** ** Bsr SetStyle ; set the style Move.W (SP)+,D0 ; restore length to measure ** ** Bsr GetWidth ; get string width Add.W D1,D5 ; accumulate width SubQ.L #stStartSize,A0 ; pt to prev style Bra.S @0 ; keep measuring @3 Bsr MeasureIt ; last measurement Add.W D0,D5 ; final width @4 Move.W D5,D0 ; return width in D0 MoveM.L (SP)+,D3/D5-D6 Rts ; ---------------------------------------------------------------------- ; PinDisplay ; Pins D3 and D4 to the viewRect ; Expects A3 the usual TE record ; Alternate entry with rect already in A0 ; Trashes D0, A0 PinDisplay Lea teViewRect(A3),A0 ; use viewRect PinA0Rect Move top(A0),D0 ; load D0 w/top Bsr.S PtToLine ; turn into a lineStart Bge.S @4 ; escape if top gone Add D0,D0 ; double for array ref. Blt.S @1 Cmp teLines(A3,D0),D3 ; pin D3 to viewRect.top Bhs.S @0 Move teLines(A3,D0),D3 ; dispStart = lines[i] @0 Cmp teLines(A3,D0),D4 ; pin D4 to viewRect.top Bhs.S @1 Move teLines(A3,D0),D4 ; dispEnd = lines[i] @1 Move bottom(A0),D0 ; get bottom in D0 SubQ #1,D0 Bsr.S PtToLine AddQ #1,D0 ; inc line # ** MBK 6/18/86 ** Cmp teNLines(A3),D0 ; compare to max ** MBK 6/18/86 ** Bhi.S @3 ; made this unsigned ** ** Add D0,D0 Cmp teLines(A3,D0),D3 ; pin D3 to viewRect.bottom Blo.S @2 Move teLines(A3,D0),D3 ; dispStart = lines[i] @2 Cmp teLines(A3,D0),D4 ; pin D4 to viewRect.bottom Blo.S @3 Move teLines(A3,D0),D4 ; dispEnd = lines[i] @3 Rts @4 Move D3,D4 ; nothing in range Rts ; ---------------------------------------------------------------------- ; PtToLine ; ** Rewritten 6/13/86 by MBK ** ; Entry: ; D0 contains a V coordinate of a point of which we want to find the ; corresponding line index into lineStart array ; Exit: ; D0 contains line index(May be negative) ; CC's set according to D0 vs teNLines ; ---------------------------------------------------------------------- PtToLine MoveM.L D2/D6-D7/A0,-(SP) Sub teDestRect+top(A3),D0 ; origin to destRect Ext.L D0 ; extend to long Move.W teNLines(A3),D7 ; save total # of lines Beq.S @4 ; if none, quit now Move.W teLineHite(A3),D1 ; get default line height Tst.W teSize(A3) ; check style flag Bpl.S @0 ; if not, do it the old way Tst.W D1 ; was line height set? Bmi.S @1 ; wasn't set, so use array @0 DivS D1,D0 ; else divide by line height Bra.S @4 ; you're done @1 Move.L teStylesH(A3),A0 ; handle to style info Move.L (A0),A0 ; dereference Move.L lhTab(A0),A0 ; max heights per line Move.L (A0),A0 ; dereference MoveQ #0,D1 ; init line hite accumulator Move.W D7,D2 ; get # of lines @2 Move.W (A0),D6 And.W #$7FFF,D6 ; mask out high bit ** ** Add.W D6,D1 ; get the height AddQ.W #4,A0 Cmp.W D1,D0 ; compare to point Blt.S @3 ; found it SubQ.W #1,D2 ; dec counter Bne.S @2 ; more lines to point @3 Move.W D7,D0 ; total # of lines Sub.W D2,D0 ; get line index @4 Cmp D7,D0 ; compare the max # lines MoveM.L (SP)+,D2/D6-D7/A0 Rts ; ---------------------------------------------------------------------- ; Invert Hook ; This calls the passed hook if there, but otherwise uses _InverRect ; Used for carets and selection. The hook passed must remove the ; rect from the stack ; Entry: ; D0 the hook proc in question ; selRect(A3) set up for rectangle in question ; ---------------------------------------------------------------------- InvertHook ; Clear HiliteMode bit to tell QuickDraw to use color highlighting. ; Only do this if a hook is not installed. Pea teSelRect(A3) ; default selection method ;; If forRAM THEN If (Not forROM) THEN ; <19Feb89smb> ; we have to do this test, so we have to explicitly check D0.L again rather ; than count on the SR flags coming in being right as in the ROM versions BTst #14,ROM85 ; on a color system? Bnz.S @1 ; Tst.L D0 ; does a hook exist? Bne.S @2 ; yes, go do it Lea HiliteMode,A0 ; BClr #7,(A0) ; Bra.S defHilite ; @1 Tst.L D0 ; does a hook exist? Beq.S defHilite ; no @2 ;; ElseIf onNuMac|onMvMac THEN ; rwh ElseIf hasCQD THEN ; <19Feb89smb> Bne.S @0 Lea HiliteMode,A0 ; new memory location for hiliting BClr #7,(A0) ; tell them we want color hiliting Bra.S defHilite ; do the inversion @0 Else Beq.S defHilite ; there, otherwise just invert EndIf Move.L D0,A0 Jmp (A0) defHilite _InverRect Rts ; Color highlighting is not to be used on the caret, so I created this separate ; procedure just for caret highlighting. ;; If onNuMac|onMvMac|forRAM THEN ; rwh If hasCQD|(Not forROM) THEN ; <19Feb89smb> CaretHook Pea teSelRect(A3) ; default selection method Tst.L D0 ; make absolutely sure! Beq.S defHilite ; there, otherwise just invert Move.L D0,A0 Jmp (A0) EndIf ; ---------------------------------------------------------------------- ; Standard Entry for procs, saves registers and pops handle arg into ; A4 and dereferences it into A3. Points A2 to first parameter ; AFTER the handle. StdEntry MoveQ #0,D0 ; not a style trap ** ** @1 Move.L A4,A0 ; set up for GetState _HGetState ; get handle flags Move.B D0,saveHandle(A6) ; save handle flags Pea savePort(A6) ; save incoming port _GetPort Move.L A4,A0 ; get the TEHandle _HLock Move.L (A4),A3 ; Dereference into A3 ** ** ;; If forRAM THEN If (Not ForROM) THEN ; <19Feb89smb> BTst #14,ROM85 ; color QD around? Bnz.S @1 ; nope Move.W teMode(A3),txMode(A0) ; _GetForeColor ; Bra.S @2 ; @1 Bsr GetForeColor ; @2 ;; ElseIf onNuMac|onMvMac THEN ; rwh ElseIf hasCQD THEN ; <19Feb89smb> Move.W teMode(A3),txMode(A0) ; do set the mode ** ** Else Bsr GetForeColor ; for Alladin ** ** EndIf Move.L teTextH(A3),A0 ; get handle size _HGetState ; get the text handle's tag Move.B D0,saveTH(A6) ; and save the flags _HLock ; and lock it _GetHandleSize ; get its size Move D0,teLength(A3) ; stuff its length ; Clean up the selection (This must be the last guy because of alternate entry) CleanUpSel Move teLength(A3),D0 ; get the text length Move teSelEnd(A3),D1 ; make sure selEnd is cool Sub D0,D1 ; selEnd-length Bls.S okSelEnd ; if >0 then bad selend Move D0,teSelEnd(A3) ; set to length if > length okSelEnd Move teSelStart(A3),D1 ; make sure selStart is cool Sub teSelEnd(A3),D1 ; selStart-selend Bls.S okSelStart ; if >0 then bad selStart Sub D1,teSelStart(A3) ; set to selend if > selend okSelStart Bsr SelSort ; I wish i could fall into it Tst.L D3 ; addr of style trap? ** ** ; All style procedure and function traps come here (except ; TEStylNew) due to a shortage of traps. ; ** ** ; Added special dispatch to StylTextBox. Have to special case ; it since it doesn't go through StdEntry. ; ---------------------------------------------------------------------- TEDispatch MoveQ #1,D0 ; tells stdEntry it's a style trap Bsr StdEntry2 ; get addr of procedure Jmp (A0) ; go and never come back! ; *************************************************************************** ; ** So I can find routines more easily... If &TYPE('&RWWDebug') <> 'UNDEFINED' Then Macro FindEntry &rout DC.B '&SUBSTR(&CONCAT(&rout,'............'),1,12)' DC.L &rout-DispLocTable EndM Export DispLocTable DispLocTable FindEntry vChar2Pixel FindEntry vPixel2Char FindEntry XTrimMeasure FindEntry XFindWord FindEntry XFindLine FindEntry XEOLHook FindEntry XDRAWHook FindEntry iTEStylPaste FindEntry iTESetStyle FindEntry iTEReplaceStyle FindEntry iTEGetStyle FindEntry iGetStylHandle FindEntry iSetStylHandle FindEntry iGetStylScrap FindEntry iTEStylInsert FindEntry iTEGetPoint FindEntry iTEGetHeight FindEntry iSetStylScrap FindEntry iTECustomHook FindEntry iTEContinuousStyle FindEntry iSetStylScrap FindEntry iTENumStyles DC.L -1 EndIf ; *************************************************************************** ; ---------------------------------------------------------------------- ; Sorts the selStart and selEnd ; Entry: ; A3 must contain a dereferenced TE object ; Exit: ; D0 contains a sorted selStart/End as a long ; A2 contains a pointer to teSelStart ; ---------------------------------------------------------------------- SelSort Lea teSelStart(A3),A2 ; Point to selstart Move.L (A2),D0 ; load start and end Cmp (A2),D0 ; see which is bigger Bhs.S @0 Swap D0 Move.L D0,(A2) ; swap and store back @0 Rts ; ---------------------------------------------------------------------- ; PROCEDURE TECopy( h: TEHandle ); ; ** Modified 6/20/86 by MBK ** ; ---------------------------------------------------------------------- TECopy Bsr StdEntry ; NO Bsr.S SelSort ; D0 contains both (end in low order) Sub (A2),D0 ; A2 points to selStart(A3) Move D0,teScrpLength ; scraplength=selEnd-selStart Move.L teTextH(A3),A0 ; source = text; already locked Move.L (A0),A0 ; dereference MoveQ #0,D0 ; clear whole long Move (A2),D0 Add.L D0,A0 ; offset to selection(see above) Move.L teScrpHandle,A1 ; destination Move teScrpLength,D0 ; nBytes = scrapLength _PtrToXHand ; ** ** Don't wipe out desk scrap for old TERecs in case applications ; use it for Undo Tst.W teSize(A3) ; check style flag Bpl.S goEpilog4 ; no style, don't wipe out scrap ; Now copy directly to the desk scrap anyway SubQ #4,SP ; room for result ** MBK 6/20/86 ** _ZeroScrap ; clear the scrap ** MBK 6/20/86 ** AddQ.L #4,SP ; ignore result ** MBK 6/20/86 ** Bsr.S SelSort ; D0 contains both (end in low order) Bsr.S CopyStyle ; copy style info NO Move.L teTextH(A3),A0 ; text handle ** MBK 6/20/86 ** Move.L (A0),A0 ; deref ** MBK 6/20/86 ** MoveQ #0,D0 ; clear long word ** MBK 6/20/86 ** ; <16May89smb> Must set up A2 to point to selStart(a3) again, since it may be invalid if the ; teRecord moved during a MyNewHandle call in CopyGuts. Lea teSelStart(A3),A2 ; <16May89smb> point to selStart Move (A2),D0 ; start of selection ** MBK 6/20/86 ** AddA.W D0,A0 ; offset to selection ** MBK 6/20/86 ** SubQ #4,SP ; room for result ** MBK 6/20/86 ** Move.W teScrpLength,D0 ; length of selection ** MBK 6/20/86 ** Move.L D0,-(SP) ; push length ** MBK 6/20/86 ** Move.L #'TEXT',-(SP) ; type 'TEXT' ** ** Move.L A0,-(SP) ; ptr to selection ** MBK 6/20/86 ** _PutScrap ; copy to desk scrap ** MBK 6/20/86 ** AddQ.L #4,SP ; ignore result ** MBK 6/20/86 ** goEpilog4 Bra epilog4 ; ---------------------------------------------------------------------- ; PROCEDURE CopyStyle ; ** Added 5/28/86 by MBK ** ; CopyStyle saves the styles corresponding to the current text ; selection to the desk scrap. ; Entry: ; A3: Pointer to TERec ; D0: selStart, selEnd ; ---------------------------------------------------------------------- CopyStyle MoveM.L D0/D2-D5/A2/A5,-(SP) ; save stuff ; get ptr to 1st style and # of styles Move.W D0,D1 ; save end Swap D0 ; selStart in low word Cmp.W D0,D1 ; is it an insertion pt? Beq.S @2 ; if so, no style to copy Bsr.S CopyGuts ; do the copy ; Lock my scrap handle 'cause PutScrap might try to move it! Move.L A4,A0 ; my scrap handle _HLock ; lock it ; copy the styles to the desk scrap now SubQ.L #4,SP ; room for result Move.L D4,-(SP) ; size of scrap Move.L #'styl',-(SP) ; scrap type ** ** Move.L (A4),-(SP) ; scrap ptr _PutScrap ; copy to desk scrap AddQ.L #4,SP ; remove result code ; don't need this handle anymore Move.L A4,A0 ; scrap handle _DisposHandle ; get rid of it @2 MoveM.L (SP)+,D0/D2-D5/A2/A5 ; save stuff Rts ; ---------------------------------------------------------------------- ; PROCEDURE CopyGuts ; ** Separated out from CopyStyle 1/22/87 by MBK ** ; CopyGuts is called by CopyStyle and iGetStylScrap to save the ; styles corresponding to the current text selection. ; Entry: ; A3: Pointer to TERec ; D0: selStart ; D1: selEnd ; ---------------------------------------------------------------------- CopyGuts Move.W D0,D5 ; save 1st offset Bsr GetCurStyle ; get style at current selection Bsr GetNumStyles ; find # of styles in selection Move.W D0,D2 ; save # of styles ; get a temp handle to store the styles in before copying to desk scrap MulU #scrpRecSize,D0 ; * size of a scrap style rec AddQ.L #2,D0 ; total scrap size Move.L D0,D4 ; preserve scrap size Bsr MyNewHandle ; temp handle for style scrap ** ** Move.L A0,A4 ; save scrap handle Move.L (A0),A0 ; deref Move.W D2,scrpNStyles(A0) ; store # of styles in scrap Lea scrpStyleTab(A0),A1 ; pt to array of styles ; ** ** style ptr may no longer be valid after memory allocation Move.W D5,D0 ; get 1st offset ** ** Bsr GetCurStyle ; get style at current selection** ** Move.L A0,A2 ; store ptr to current style ** ** ; loop over styles in the selection, copying to temp location @0 AddQ.L #4,A1 ; skip 1st entry ** ** Move.W styleIndex(A2),D0 ; style index Bsr GetStyle ; get the style ptr AddQ.L #2,A0 ; skip 1st entry ** ** MoveQ #stRecSize-2,D0 ; size of a style rec-2 ** ** _BlockMove ; copy style to scrap MoveQ #0,D0 ; it's a long word ** ** Move.W startChar(A2),D0 ; get start offset of this style Sub.W D5,D0 ; offset from start of text scrap Bhs.S @1 ; made this unsigned ** ** MoveQ #0,D0 @1 Move.L D0,-(A1) ; store scrap offset Add.L #scrpRecSize,A1 ; next position in style array AddQ.L #stStartSize,A2 ; next style SubQ #1,D2 ; dec the style counter Bne.S @0 ; loop if more styles Rts ; ---------------------------------------------------------------------- ; PROCEDURE TECut( h: TEHandle ); ; ---------------------------------------------------------------------- TECut Bsr StdEntry ; NO Move.L A4,-(SP) ; duplicate handle twice _TECopy ; copy it Move.L A4,-(SP) _TEDelete ; delete it (A3 no good after) Bra goEpilog4 ; see you later NO ; ---------------------------------------------------------------------- ; PROCEDURE TEDelete( h: TEHandle ); ; ---------------------------------------------------------------------- TEDelete Bsr StdEntry ; NO Bsr HideCaret Bsr.S DelGuts ; delete the selection Bsr RecalDraw ; recalibrate line starts Bsr ShowCaret Bsr SelView ; insure selection is visible Bra goEpilog4 ; NO ; ---------------------------------------------------------------------- ; PROCEDURE DelGuts ; ** Modified 6/18/86 by MBK ** ; Entry: ; A3 contains dereferenced handle ; Exit ; Selstart and selEnd will be fixed up to point to the old selStart ; D7 contains delta amount for delete portion ; ---------------------------------------------------------------------- DelGuts Bsr SelSort ; sort selection NO Move D0,D7 ; calc delta amount(selEnd in D0) Sub (A2),D7 ; ...for ReCalLines (A2 ^selStart) Beq.S outGuts ; skip if null selection ; ** Inserted test to change the way backspacing/deleting works. ; If you backspace to the beginning of a style, that style is saved to the null scrap. ; This allows you to type a selection, backspace over it, and retype without ; TextEdit reverting to the previous style. Tst.W teSize(A3) ; is this a styled record? Bpl.S @1 ; oops, never mind MoveM.L D0/D7/A2,-(SP) ; we need D0 and A2 temporarily Move.W teSelStart(A3),D0 ; find start of block to be yanked Bsr GetCurStyle ; find the associated style run Move.W teSelStart(A3),D0 ; get start of block again Cmp.W startChar(A0),D0 ; is it the beginning of a style? Beq.S @2 ; yes, so continue Bsr ClearRsrved ; no null selection! Bra.S @3 ; @2 Move.W styleIndex(A0),D0 ; fetch index into style table Bsr GetStyle ; find associated style table entry Move.W #doAll,-(SP) ; build fake frame for SetRsrved Pea stFont(A0) ; point at embedded textstyle Clr.B -(SP) ; need another word, can't hurt Move.L SP,A2 ; point A2 at stacked parameters Bsr AltSetRsrved ; set null scrap style AddQ.W #8,SP ; fix up stack @3 MoveM.L (SP)+,D0/D7/A2 ; retrieve saved registers @1 ; Move.W D0,D1 ; selEnd ** MBK 6/18/86 ** Swap D0 ; selStart ** MBK 6/18/86 ** Bsr.S DeleteStyle ; del associated styles NO Bsr MungeSetup ; set up params for delete Move D7,-(SP) ; length for delete Clr -(SP) ; fake long length Clr.L -(SP) ; fake p2 Clr.L -(SP) ; fake l2 _Munger ; sloppy munger AddQ.L #4,SP ; pop result Move.L teTextH(A3),A0 ; RecalDraw expects text to be locked _Hlock ; and relock it Sub D7,teLength(A3) ; length:=length -(selEnd-selStart) Move (A2)+,(A2) ; selEnd:=selStart outGuts Rts ; ---------------------------------------------------------------------- ; PROCEDURE DeleteStyle ; ** Added 6/2/86 by MBK ** ; DeleteStyle checks to see if the TERec has style (txSize = -1), ; And if so deletes the style(s) corresponding to the current text ; selection. ; Entry: ; A3: Ptr to TERec ; D0: selStart ; D1: selEnd ; ---------------------------------------------------------------------- DeleteStyle MoveM.L D0/D2-D6/A2,-(SP) ; save stuff Tst.W teSize(A3) ; check style flag Bpl.S @2 ; no style so nothing to delete Move.W D0,D5 ; store selStart Sub.W D1,D5 ; neg length for delete Beq.S @2 ; quit if nothing to delete Move.W D0,D3 ; save selStart SubQ #1,D0 ; pre-decrement Bsr GetCurStyle ; get style at current selection Move.L A0,A2 ; store ptr to current style Move.W D0,D6 ; save index AddQ #1,D1 ; include following style Bsr GetNumStyles ; find # of styles in selection SubQ #1,D0 ; don't delete current style Move.W D0,D2 ; # of styles Add.W D6,D0 ; add index Move.W D0,D6 ; save index MoveQ #0,D4 ; clear long word ** ** Move.W D2,D4 LsL.L #2,D4 ; * stStartSize (4) ** ** Add.L D4,A0 ; pt to last style to be deleted Tst.W D2 ; see if any styles to delete Bne.S @0 ; if nothing to delete Bsr RecalStStarts ; reset following style starts Bra.S @2 ; and go @0 Move.W D3,startChar(A0) ; selStart is new start of last style Bsr RecalStStarts ; reset following style starts Cmp.W startChar(A2),D3 ; special case Beq.S @1 Add.L #stStartSize,A2 ; point to next style SubQ #stStartSize,D4 ; 1 less to delete SubQ #1,D2 ; don't delete last style Beq.S @2 ; nothing to delete @1 Move.L A2,A0 ; ptr Move.W D2,D0 ; count Bsr.S DecStylCount ; decrement style count NO ; Delete the runs corresponding to deleted text Move.L teStylesH(A3),A0 ; handle to style info Move.L (A0),A0 ; dereference MoveQ #0,D0 ; clear long word ** ** Move.W nRuns(A0),D0 ; current # of styles AddQ #1,D0 ; plus 1 Sub D6,D0 ; minus index LsL.L #2,D0 ; * stStartSize (4) ** ** Sub.W D2,nRuns(A0) ; dec the # of styles Move.L A2,A1 ; destination of move Move.L A2,A0 Add.L D4,A0 ; source of move _BlockMove @2 MoveM.L (SP)+,D0/D2-D6/A2 ; restore stuff Rts ; ---------------------------------------------------------------------- ; PROCEDURE DecStylCount ; ** Added 6/2/86 by MBK ** ; DecStylCount decrements the style count by one after an instance ; of the style has been deleted. ; Entry: ; D0: # of styles to check ; A0: Pointer to style from which to start ; A3: Ptr to TERec ; ---------------------------------------------------------------------- DecStylCount Move.L A0,A1 ; save ptr to style start Move.W D0,D1 ; store # styles to check ; get the styleRec corresponding to the index @0 Move.W styleIndex(A1),D0 ; get index to style Bsr GetStyle ; get pointer to that style Tst.W stCount(A0) ; is the count already 0? Beq.S @1 SubQ #1,stCount(A0) ; if not, decrement the count ; see if there are more styles to delete @1 Add.L #stStartSize,A1 ; point to next style SubQ #1,D1 ; dec the counter Bne.S @0 ; more to decrement Rts ; ---------------------------------------------------------------------- ; PROCEDURE RecalDraw ; ** Modified 6/18/86 by MBK ** ; Calls ReCalLines to recalibrates the line start array and then draws ; the "new" part according to selStart ; Entry ; A4 points to handle ; A3 points to dereferenced TE object ; D7 contains delta change = oldLength-newLength ; ** ** Added code to reset redraw boundaries if the ; line height has changed on any line. ; ** ** Moved code to decide where redraw must occur ; to the routine SetLineHite. ; ---------------------------------------------------------------------- RecalDraw MoveQ #0,D0 ; 1st line ** MBK 6/18/86 ** Move.W teNLines(A3),D1 ; last line ** MBK 6/18/86 ** Bsr GetLineHites ; get total height ** MBK 6/18/86 ** Move.W D0,-(SP) ; save it ** MBK 6/18/86 ** Bsr ReCalLines ; D2/D4 returned w/dispStart Move D2,D3 ; record dispStart MoveQ #0,D0 ; 1st line ** MBK 6/18/86 ** Move.W teNLines(A3),D1 ; last line ** MBK 6/18/86 ** Bsr GetLineHites ; get new height ** MBK 6/18/86 ** Move.W (SP)+,D1 ; get old height Cmp.W D0,D1 ; don't erase if same Blo.S noErase ; nothing to erase Lea teSelRect(A3),A0 ; pt to selection rect Add teDestRect+top(A3),D1 ; new bottom Move.W D1,bottom(A0) Add teDestRect+top(A3),D0 ; new top Move.W D0,top(A0) Move.W #$8002,left(A0) ; large negative left Move #$7FF0,right(A0) ; VERY large right(Erase to end) Move.L A0,-(SP) ; point to rect _EraseRect noErase MoveQ #teDraw,D7 ; Redraw changed part Bra DoText ; see you later NO ; ---------------------------------------------------------------------- ; PROCEDURE FindWord ; Finds a word @ D0 and returns its start and end+1 index in D0,D1 ; respectively. Note cannot return selStart itself - must look to left ; Entry ; A3 - dereferenced handle ; D0 - current position (i.e. selStart) ; D2 - identifier of routine that called FindWord ; Exit ; D0 - word start ; D1 - word end+1 ; ---------------------------------------------------------------------- FindWord Move.L teFindWord,-(SP) ; call the FindWord Routine Rts XFindWord ; here's our FindWord Swap D2 ; get constant into high word Move.W D0,D2 ; save position in low word Move.W D0,D1 Beq.S RightScan Bsr.S LeftScan ; do left scan 1st ; Right scan, given a char code in D1, this returns the next word break >= D1 RightScan BClr #17,D2 ; clear bit 17 (right) RS1 Cmp teLength(A3),D1 ; see if @ right edge Bhs.S @0 ; assume found if at right edge Move D1,A1 ; pass index Bsr.S CallBreak Bne.S @0 AddQ #1,D1 ; try next char Bra.S RS1 ; @0 Rts ; Given a char location in D0, this routine returns a new word break to left of D0 LeftScan BSet #17,D2 ; set bit 1 (left) LS1 SubQ #1,D0 ; pre decrement Move D0,A1 ; pass index Bsr.S CallBreak ; was it a break? Bne.S @0 ; if so, skip town Tst D0 ; are we done? Beq.S @1 ; if so, skip town Bra.S LS1 ; keep looking @0 AddQ #1,D0 ; try next char @1 Rts CallBreak MoveM.L D0/A0-A1,-(SP) ; save regs Move A1,D0 ; pass index in D0 Move.L teTextH(A3),A0 ; get handle Move.L (A0),A0 Move.L teWordBreak(A3),A1 ; get routine Jsr (A1) ; call routine which sets CC's MoveM.L (SP)+,D0/A0-A1 ; restore regs Rts DefWordBrk ; lo16 is used by TE as a constant for clearing the high word of registers lo16 Equ *+2 And.L #$0000FFFF,D0 ; longize it Cmp.B #$20,0(A0,D0.L) ; see if <= $20 Sls D0 ; return if word break(SP) Tst.B D0 Rts ; Measures the trimmed string in [D6..D7) TrimMeasure MoveM.L D6-D7,-(SP) ; save regs Bsr MeasD6D7 MoveM.L (SP)+,D6-D7 ; restore regs Rts ; ---------------------------------------------------------------------- ; PROCEDURE StylMeasure ; ** Added 6/18/86 by MBK ** ; Measures the word at offset D6-D7, taking the style into account ; If this record has style. ; Entry: ; D6 Start of word to be measured ; D7 End of word to be measured ; A3 dereferenced handle ; Exit: ; D0 Width of selection ; ---------------------------------------------------------------------- StylMeasure MoveM.L D2-D3/D5/A2,-(SP) ; does this record have style? Tst.W teSize(A3) ; check style flag Bmi.S @2 ; No, just measure the whole thing at once Move.W D7,D0 ; end offset Move.W D6,D1 ; start offset Bsr.S SetUp ; measure whole word NO Add.W D6,D1 ; offset at end of word Bra.S @6 ; that's it NO ; Yes, so measure word 1 style at a time @2 Move.W D6,D5 ; start offset Move.W D6,D3 ; start offset Move.W D3,D0 ; start Bsr GetCurStyle ; get current style Move.L A0,A2 ; save style start ptr Move.W D7,D1 ; end Bsr GetNumStyles ; # of styles in selection Move.W D0,D2 ; save it @3 Move.L A2,A0 ; style ptr Bsr SetStyle ; set the style Add.L #stStartSize,A2 ; pt to next style Move.L A2,A0 ; style ptr Move.W startChar(A0),D0 ; end of style Cmp.W D0,D7 ; compare to end of selection Bhs.S @4 ; okay if greater Move.W D7,D0 ; else set to end of selection @4 Move.W D3,D1 ; start offset Move.W D0,D3 ; next time end becomes start Move.L teStylesH(A3),A0 ; get handle to style record Move.L (A0),A0 ; deref Sub.L A0,A2 ; save as an offset Bsr.S SetUp ; measure it NO Move.L teStylesH(A3),A0 ; get handle to style record Move.L (A0),A0 ; deref Add.L A0,A2 ; restore style pointer Add.W D1,D5 ; accumulate offset Tst.W D0 ; pixel width found? Bne.S @5 ; quit if so SubQ #1,D2 ; dec the style counter Bne.S @3 ; keep looping if more styles NO @5 Move.W D5,D1 ; offset @6 MoveM.L (SP)+,D2-D3/D5/A2 Rts SetUp Move.W D2,-(SP) ; save style count Sub.W D1,D0 ; text length Move.L teTextH(A3),A0 ; text handle Move.L (A0),A0 ; deref AddA.W D1,A0 ; text ptr Move.W D4,D1 ; pixel width MoveQ #0,D2 ; slop ; Bsr Pixel2Char ; measure it Bsr TEHitTestHook ; measure it Sub.W D0,D4 ; update width Swap D0 ; get flag in low byte Move.W (SP)+,D2 ; restore count Rts ; ---------------------------------------------------------------------- ; PROCEDURE FindLine ; ** Modified 6/18/86 by MBK ** ; Finds a line starting at char location in D6. ; This first tries to measure the line in word chunks to save time, ; but if that fails it will do it character by character. IF teCROnly ; is set it won't measure anything(Assuming dest rect is huge to right) ; And just scans for the CR. ; Entry ; D6 start of line search assumed to be at 1st word? ; A3 - dereferenced handle ; Exits ; D0 with line end after D6 ; ---------------------------------------------------------------------- FindLine Move.L teFindLine,-(SP) ; push current FindLine routine Rts ; and call it XFindLine ; our default FindLine routine MoveM.L D1-D7/A1-A2,-(SP) ; protect working registers ; Keep going until line width in D4 is used up Move teDestRect+right(A3),D4 ; get right edge Sub teDestRect+left(A3),D4 ; get extent SubQ #1,D4 ; reduce for caret indent Sub.L A2,A2 ; flag not found Move D6,D7 ; use D7 for tail, D6 for head MoveQ #0,D3 ; clear accumulator ** MBK 6/17/86 ** MoveQ #0,D5 ; init D5 wordLoop Move D7,D0 ; set up start posn MoveQ #teFromFind,D2 ; say findLine is calling Bsr FindWord ; get word end in D1 NO Move D1,D7 ; save end Tst.B teCROnly(A3) ; see if only scan to CR Bne.S @0 ; if so, skip the measure Bsr StylMeasure ; measure with style ** MBK 6/17/86 ** Tst.W D0 ; end of line reached? Bne.S Spilled ; It has yet to spill off the right, so continue on unless char = CR @0 Move D7,D5 ; save lastBlank location AddQ #1,A2 ; flag as found Cmp teLength(A3),D7 ; see if < length for right Beq.S foundLine Move.L teTextH(A3),A0 ; see if char was a CR Move.L (A0),A0 And.L lo16,D7 ; longize it ; ** Added this code to support tabs ; Cmp.B #$0D,0(A0,D7.L) ; well, is it? Move.B 0(A0,D7.L),D0 ; THESE FOUR LINES REPLACE PREVIOUS MoveM.L D1,-(SP) ; we need D1 intact Bsr TEEolHook ; MoveM.L (SP)+,D1 ; (MoveM doesn't affect CCR!!) Bne.S @1 ; keep trying if not ** ** AddQ #1,D5 ; point after break char ** ** Bra.S foundLine ; and exit ** ** @1 Move.W D7,D6 AddQ #1,D7 ; start with next word Bra.S wordLoop ; get next one NO ; D5 contains the last break location so point to next character since break char ; is included on the line. ; If A2 = 0, then it never found a break char spilled Move A2,D0 ; did we find something Beq.S @1 Move.L teTextH(A3),A0 ; get text handle ** ** Move.L (A0),A0 ; dereference ** ** @0 AddQ #1,D5 ; use next char ** ** Cmp.W teLength(A3),D5 ; check text length ** ** Bhs.S foundLine ; exit if end of text ** ** ; A CR following non-wrapped blanks should be considered the line break. ; If not, the CR will go on the next line, and we'll get an empty line ; in-between. This fixes bug LM-RM-98. ; ** Added this code to support tabs ; Cmp.B #$0D,0(A0,D5) ; if last char = CR then... Move.B 0(A0,D5),D0 ; THESE FOUR LINES REPLACE PREVIOUS MoveM.L D1/A0,-(SP) ; (we need D1 AND A0) Bsr TEEolHook ; MoveM.L (SP)+,D1/A0 ; (MoveM doesn't affect CCR!!) Bne.S @2 ; if CR, we actually want next char AddQ #1,D5 ; use next char Bra.S foundLine @2 Cmp.B #$20,0(A0,D5) ; if last char = space then... ** ** Beq.S @0 ; it's a break ** ** Bra.S foundLine @1 SubQ #1,D1 ; end of rect intersects this char Move.W D1,D5 foundLine Move D5,D0 ; return in D0 MoveM.L (SP)+,D1-D7/A1-A2 ; restore working registers Rts ; ---------------------------------------------------------------------- ; PROCEDURE ReCalLines ; ** Modified 6/18/86 by MBK ** ; Recalibrates the line start array and sets dispStart/dispEnd to ; correct redraw spot. Starting with the selection, it figures out ; which line the selection is on. Then it recalibrates the line starts ; from there until the delta in D7 is consumed (the word wrap has ; petered out). It returns D2 and D4 to the redraw start and end. ; (It should return D3 instead of D2, but for compatibility it uses ; D2). ; Entry ; A4 points to handle ; A3 points to dereferenced TE object ; D7 contains delta in change = oldLength-newLength ; Exit ; dispStart(D2) now set to redraw start ; dispEnd(D4) set to redraw end ; Uses ; D5 for handle size (changed by setlinearray) ; ---------------------------------------------------------------------- ; ** ** Stages 2 and 3 of Recal were totally rewritten for ; speed. I decided the insert and delete cases were ; different enough to justify handling them separately. ReCalLines Move.L teRecal,-(SP) Rts XReCalLines Link A6,#RecalLink MoveM.L D3/D5-D6/A2,-(SP) ; save regs (SEE .EQU ABOVE) Move.W teNLines(A3),oldNLines(A6) ; save old # of lines ** ** Clr.W teNLines(A3) ; prime nLines:=0 Clr.W savedD2(A6) ; default redraw beginning Move teLength(A3),savedD4(A6) ; default redraw end Tst.W teLength(A3) ; any text? Beq.S RecalDone ; if not, nothing to recal NO ; D3 contains the start point to recal from, so find the line containing D3 Lea teLines(A3),A2 ; point to line starts MoveQ #teFromRecal,D2 ; say ReCalLines is calling Move teSelStart(A3),D0 ; put start position in D0 Bsr FindWord ; get word around selstart for...NO Move D0,D3 ; comparison stage1 Move (A2)+,D6 ; i(start):=lineStarts[line] Move D6,savedD2(A6) ; save away as default redraw start Cmp (A2),D3 ; while selWordNO Cmp D0,D3 ; did the line break change? Bhs.S stageBad ; if so, must redraw whole thing stageGood ; Tst.B WordRedraw ; should we redraw the whole word? Bgt.S stageBad ; => yes, app wants whole word Blt.S stage2A ; => app wants whole line Move teSelStart(A3),D3 ; return selStart stageBad Tst.W teJust(A3) ; see what format, for right or Bne.S stage2A ; centered, must use linestart Tst.W teSysJust ; check text direction ** ** Bne.S stage2A ; not left ** ** ; Special case: redraw line didn't work because stage2x jumped here w/o checking the redraw flag. Tst.B WordRedraw ; should we redraw the whole word? ** ** Blt.S stage2A ; => app wants whole line ** ** Move D3,savedD2(A6) ; return word start-1 Beq.S stage2A SubQ #1,savedD2(A6) Bra.S stage2A stage2y Bsr FindLine ; get line after D6 NO Cmp D0,D3 ; did the line break change? Bne.S stageBad ; if so, must redraw whole thingNO Move D3,savedD2(A6) ; "next" line OK if at beginning Bra.S stageGood ; NO ; 2 new routines for handling stages 2 and 3 of Recal stage2A Move.W D0,D3 ; save line start in D3 If &TYPE('&RWWDebug') <> 'UNDEFINED' Then Tst.W D7 ; insertion or deletion? Ble.S @0 ; If some characters on a line are replaced by (a fewer number of) CRs ; the deletion algorithm does not work correctly because it is not ; prepared to add new lines. So now I just call the insertion algorithm ; except for this special case, when character(s) at the beginning of ; the line are being deleted (the insertion algoritm doesn't work ; in this case). Maybe someday this whole recalibration thing will ; get rewritten! ; Changed this once again. Selstart will equal selEnd whenever TEDelete was called. ; Only call InsertRecal if this was an insertion that was shorter than the selection. Move.W teSelStart(A3),D0 Cmp.W teSelEnd(A3),D0 Bne.S @0 Bsr.S DeleteRecal ; recal for deletions Bra.S reCalDone EndIf ; @0 Bsr InsertRecal ; recal for insertions reCalDone Bsr SetLineHite ; reset line heights ** ** Move.W savedD4(A6),D4 ; return start and end ** MBK 6/18/86 ** Move.W savedD2(A6),D2 ; ** MBK 6/18/86 ** ; ** Rudy D. memorial lineStarts hack. ; Force TERecord to be proper length. cutBackSlop Equ 8 Move.L A4,A0 ; How fat is TERecord now? _GetHandleSize ; Tst.L D0 ; check for error Bpl.S @2 _SysError ; fly away if system error @2 Sub.L #teRecSize,D0 ; lose header LsR.L #1,D0 ; account for word sized table And.L #$7FFF,D0 ; gotta be fewer than 32K lines Sub.W teNLines(A3),D0 ; blow off cutback Bz.S @1 ; didn't change at all Bmi.S @1 ; got larger. Munger handled it Cmp.W #cutBackSlop,D0 ; is difference less than slop Blo.S @1 ; Yes, so don't bother memory mgr MoveQ #0,D0 ; Gotta talk longs, here Move.W teNLines(A3),D0 ; Fetch number of lines LsL.L #1,D0 ; account for word offset Add.L #teRecSize,D0 ; Add in rest of record Move.L A4,A0 ; TEHandle is what we're resizing Bsr MySetHandleSize ; Go do it @1 ; MoveM.L (SP)+,D3/D5-D6/A2 ; restore regs Unlk A6 Rts ; see you later If &TYPE('&RWWDebug') <> 'UNDEFINED' Then ; ** ** Stages 2 and 3 for deletion only DeleteRecal Move.L teTextH(A3),A0 ; text handle Move.L (A0),A1 ; deref into A1 dStage2 ; If the width of a single character > the width of the window, Recal keeps ; finding the same line (line 1) forever. If this happens, don't keep trying ; to wrap, just advance to the next character. Cmp.W D6,D3 ; same as old value? ** ** Bne.S @0 ; ok if not ** ** AddQ #1,D3 ; else advance to next char ** ** @0 Cmp teSelEnd(A3),D3 ; not ready for stage 3 if not yet Bls.S dSkip3 ; past selEnd Move.L A2,savePtr(A6) ; save ptr for move up Move.W (A2),D0 ; old line start Sub D3,D0 ; oldStart - newStart Cmp D0,D7 ; compare to delta Beq.S dStage3 ; ** Added this code to support tabs ; Cmp.B #$0D,-1(A1,D3) ; get the last char Move.B -1(A1,D3),D0 ; THESE TWO LINES REPLACE PREVIOUS Bsr TEEolHook ; Bne.S dSkip3 ; if CR stage 2 is over ; look for the old value of this line Move.L A2,A0 Move.W D3,D0 ; line start + delta Add.W D7,D0 @1 Cmp.W (A0)+,D0 ; must be a match Bhi.S @1 ; made this unsigned ** ** SubQ #2,A0 ; got over-incremented Move.L A0,savePtr(A6) ; save ptr for move up Bra.S dStage3 dSkip3 ; update the table with new start AddQ #1,teNLines(A3) ; inc # of lines Move D3,(A2)+ ; lines[nLines]:=i Move D3,D6 ; now start with the next line Cmp teLength(A3),D6 ; while i < length do Bhs.S endDRecal Bsr FindLine ; get line after D6 NO Move D0,D3 ; findline returns in D0 Bra.S dStage2 ; if so, never do background ; Fill out following line offsets with delta and return in D4 the redraw end dStage3 Move.L A2,A0 Move.L savePtr(A6),A0 ; source ptr Cmp.L A2,A0 ; same as dest ptr? Beq.S @3 ; if so, no lines deleted Move.W teLength(A3),D3 ; else, redraw everything @3 Move D3,savedD4(A6) ; found it, record in dispEnd dStage3A ; update the table with new start AddQ #1,teNLines(A3) ; increment # lines Move.W (A0)+,D0 Sub D7,D0 ; lines[nLines]:=lines[nLines]-delta Move.W D0,(A2) Move (A2)+,D6 ; see if done Cmp teLength(A3),D6 ; while i < length do Blo.S dStage3A endDRecal Rts EndIf ; ; ** ** Stages 2 and 3 for insertion only defBufSize Equ 256 ; initial size of temp line start buffer InsertRecal MoveM.L D2/D4,-(SP) ; save stuff MoveQ #0,D5 ; line start counter Move.W teSelEnd(A3),D4 If &TYPE('&RWWDebug') = 'UNDEFINED' Then Tst.W D7 ; Only do "subtraction" if negative Bpl.S @05 ; EndIf Sub.W D7,D4 ; selEnd + delta @05 ; ** ** MyNewHandle unlocks the TEHandle for memory allocation and resets ; the A3 ptr, so the A2 ptr must also be reset Sub.L A3,A2 ; save A2 as an offset ** ** Move.L #defBufSize,D0 ; don't want to reset too often ** ** Move.L D0,D2 ; save initial handle size Bsr MyNewHandle ; temp handle for line starts ** ** _HLock ; play it safe Move.L (A0),A1 ; save ptr Move.L A0,startHndl(A6) ; save handle Add.L A3,A2 ; restore A2 as a ptr ** ** Move.L A2,savePtr(A6) ; current line start ptr iStage2 ; If the width of a single character > the width of the window, Recal keeps ; finding the same line (line 1) forever. If this happens, don't keep trying ; to wrap, just advance to the next character. Cmp.W D6,D3 ; same as old value? ** ** Bne.S @0 ; ok if not ** ** AddQ #1,D3 ; else advance to next char ** ** @0 Cmp D4,D3 ; not ready for stage 3 if not yet Bls.S iSkip3 ; past selEnd Move.L teTextH(A3),A0 ; get text handle Move.L (A0),A0 ; deref ; ** Added code to support tabs ; Cmp.B #$0D,-1(A0,D3) ; get the last char Move.B -1(A0,D3),D0 ; THESE TWO LINES REPLACE PREVIOUS Bsr TEEolHook ; Bne.S @3 ; keep going if not CR Move.L A2,A0 ; set current ptr Move.W D3,D0 ; get line start Add.W D7,D0 ; minus delta (D7 is neg) ; find the old value of this line start for moving down remaining line starts @1 Cmp.W (A0)+,D0 Bhi.S @1 ; made this unsigned ** ** SubQ #2,A0 ; got over-incremented Move.L A0,savePtr(A6) ; save it Bra.S iStage3 ; on to stage 3 @3 ; D5 may be greater than the old number of lines, so skip the ; delta check if so. This was a really obscure bug which only ; hurt us when D0 happened to be equal to D7. MoveQ #0,D0 ; clear entire register Move.W oldNLines(A6),D0 ; get old # of lines Add.W D0,D0 ; double for word entries Cmp.L D0,D5 ; have we exceeded the length of the array? Bhs.S iSkip3 ; skip delta check if so Move.W 0(A2,D5.L),D0 ; get old start Sub D3,D0 ; oldStart - newStart Cmp D0,D7 ; compare to delta Bne.S iSkip3 ; keep trying if not same Add.L D5,savePtr(A6) ; set old start for move down Bra.S iStage3 iSkip3 ; increase sizes of temporary arrays if needed Cmp.L D5,D2 ; time to increase sizes? Bgt.S @0 Move.L startHndl(A6),A0 ; temp line starts handle _HUnlock Add.L #defBufSize,D2 ; inc size for line starts ** ** Move.L D2,D0 Sub.L (A0),A1 ; make ptr an offset Bsr MySetHandleSize ; reset handle size ** ** _HLock Add.L (A0),A1 ; make the offset a ptr again @0 Move D3,(A1)+ ; lines[nLines]:=i Move D3,D6 ; now start with the next line AddQ #1,teNLines(A3) ; increment # lines AddQ.L #2,D5 Cmp teLength(A3),D6 ; while i < length do Blo.S @1 ; keep finding lines ** ** Move.W oldNLines(A6),D0 ; get old # of lines ** ** AddQ.W #1,D0 ; plus 1 to pt to end ** ** Add.W D0,D0 ; double for word entries ** ** Lea teLines(A3,D0),A0 ; plus base address ** ** Move.L A0,savePtr(A6) ; save it for replace ** ** Bra.S iStage3A ; go munge ** ** @1 Bsr FindLine ; get line after D6 NO Move D0,D3 ; findline returns in D0 Bra iStage2 ; if so, never do background NO ; Fill out following line offsets with delta and return in D4 the redraw end iStage3 Move D3,savedD4(A6) ; found it, record in dispEnd ; Still need to munge if D5 is 0, in case something was inserted over a CR. ; Line which skipped munging if D5 = 0 was deleted. Move.L savePtr(A6),D0 Sub.L A2,D0 ; change in # of lines? Sub.L D5,D0 Beq.S iStage3A Move.W teLength(A3),D3 ; if so, must display all iStage3A Move D3,savedD4(A6) ; found it, record in dispEnd Move.L A4,A0 _HUnLock ; unlock TEHandle SubQ.L #4,SP ; room for ret value Move.L A4,-(SP) ; TEHandle Move.L A2,D0 Sub.L A3,D0 ; offset to line preceding insert Move.L D0,-(SP) Move.L #0,-(SP) ; Nil ptr Move.L savePtr(A6),D0 ; end of insertion Sub.L A2,D0 ; - beg of insertion Move.L D0,-(SP) Move.L startHndl(A6),A0 Move.L (A0),-(SP) ; ptr to new line starts Move.L D5,-(SP) ; length of insertion Sub.L A3,A2 ; save as offset _Munger ; (TEHandle, preInsertPoint, NIL, selectionLen, newLineStarts, insertLen); AddQ.L #4,SP ; don't care Move.L A4,A0 _HLock ; relock TEHandle Move.L (A4),A3 ; deref Add.L A3,A2 ; restore as ptr Add.L D5,A2 ; adjust ptr for move down sameLine Move.L startHndl(A6),A0 ; get rid of line starts handle _DisposHandle Cmp teLength(A3),D6 ; if i >= length quit Bhs.S endIRecal iStage3B ; update the table with new start AddQ #1,teNLines(A3) ; increment # lines Sub D7,(A2) ; lines[nLines]:=lines[nLines]-delta Move (A2)+,D6 ; see if done Cmp teLength(A3),D6 ; while i < length do Blo.S iStage3B endIRecal MoveM.L (SP)+,D2/D4 ; other stuff Rts ; ---------------------------------------------------------------------- ; PROCEDURE SetLineHite ; ** Added 6/18/86 by MBK ** ; SetLineHite takes the maximum height for the current line ; (which was determined in FindLine) and stores it in the ; array of maximum line heights. ; ** ** Changed to reset all heights at end of recal ; Entry: ; A4 is pointing into array in which to insert line heights and ; ascents ; ---------------------------------------------------------------------- SetLineHite MoveM.L D2-D5/A2/A4,-(SP) ; save registers Tst.W teSize(A3) ; record with style? Bpl endSetLH ; quit if not Move.L teStylesH(A3),A0 ; handle to style info Move.L (A0),A0 ; deref Move.L lhTab(A0),A0 ; line heights array _GetHandleSize ; get current size Move.W D0,D3 ; save size in D3 AsR.W #2,D3 ; get # of lines MoveQ #0,D0 ; clear whole reg Move.W teNLines(A3),D0 ; get # of lines AddQ.L #1,D0 ; + 1 for last entry LsL.L #2,D0 ; for 2 integers Bsr MySetHandleSize ; reset handle size ** ** Move.L teStylesH(A3),A1 ; handle to style info ** ** Move.L (A1),A1 ; deref ** ** Move.L lhTab(A1),A4 ; line heights array Move.L (A4),A4 ; deref Tst.W teLength(A3) ; any text? Bne.S @0 ; no default needed if so ** ** ; If all text was deleted, set line height according to only remaining style. Move.W runs+2(A1),D0 ; index to 1st style ** ** Bsr GetStyle ; get ptr to 1st style ** ** Move.W stHeight(A0),(A4)+ ; store line height ** ** Move.W stAscent(A0),(A4) ; store the ascent ** ** Bra endSetLH ; and quit ** ** @0 Move.L styleTab(A1),A0 ; styles array Move.L (A0),A0 ; deref Lea runs(A1),A1 ; pt to style runs Lea teLines(A3),A2 ; pt to line starts MoveQ #0,D1 ; set max MoveQ #0,D2 ; set starting line # Move.L #-1,D4 ; starting redraw line ** ** Move.W (A4),D5 ; save old value ** ** setLoop Move.W styleIndex(A1),D0 ; index to current style MulU #stRecSize,D0 ; multiply index by size of record Cmp.W stHeight(A0,D0.L),D1 ; compare to current max ** ** made D0 long Bge.S @1 ; already have max Move.W stHeight(A0,D0.L),D1 ; else save as new max ** ** made D0 long Cmp.W D2,D3 ; is this a new entry? Ble.S @0 ; just set it if so Tst.W (A4) ; else, see if it should be set Bmi.S @1 ; if neg don't reset @0 Move.W D1,(A4) ; else set height Move.W stAscent(A0,D0.L),2(A4) ; set ascent ** ** made D0 long @1 Move.W 2(A2),D0 ; get next line start Cmp.W stStartSize(A1),D0 ; cmp to style start Blo.S @3 ; made this unsigned ** ** Beq.S @2 ; next style AddQ.L #stStartSize,A1 ; pt to next style Bra.S setLoop ; keep checking this line @2 AddQ.L #stStartSize,A1 ; pt to next style @3 AddQ.L #2,A2 ; pt to next line Tst.L D4 ; line to start redraw from ** ** Bpl.S @4 ; don't reset it ** ** Cmp.W (A4),D5 ; compare to old max ** ** Beq.S @4 ; ok if same ** ** MoveQ #0,D4 ; clear neg value in hi word ** ** Move.W D2,D4 ; store line # for redraw ** ** @4 AddQ.L #4,A4 ; next line height entry Move.W (A4),D5 ; save old value ** ** MoveQ #0,D1 ; reset max AddQ #1,D2 ; inc counter Cmp.W teNLines(A3),D2 ; check counter Blo.S setLoop ; loop if more lines ** ** changed BNE to BCS Move.L -4(A4),(A4) ; last dummy entry Tst.L D4 ; change in heights? ** ** Bmi.S endSetLH ; quit if not ** ** Move.W teLength(A3),savedD4(A6) ; must redraw to bottom ** ** Add.W D4,D4 ; double the line # ** ** Move.W teLines(A3,D4),D0 ; get start of line ** ** Cmp.W savedD2(A6),D0 ; don't reset if new start ** ** Bhs.S endSetLH ; is greater than old start ** ** Move.W D0,savedD2(A6) ; store as new display start ** ** endSetLH MoveM.L (SP)+,D2-D5/A2/A4 ; restore registers Rts ; ---------------------------------------------------------------------- ; PROCEDURE ShowCaret ; PROCEDURE HideCaret ; PROCEDURE DrawCaret ; PROCEDURE EraseCaret ; Entry: ; A3 contains dereferenced handle ; ---------------------------------------------------------------------- ShowCaret Tst.B teActive(A3) ; do nothing if not active Beq.S noDrawIt ; NO Move teSelStart(A3),D0 ; see if should be turned on Cmp teSelEnd(A3),D0 Bne.S noDrawIt ; if selection <> 0 then escape ST teCarAct(A3) ; activate caret DrawCaret Tst.B teCarOn(A3) ; see if caret is on Bne.S noDrawIt ; don't draw it if so ST teCarOn(A3) ; caret marked on ForceCaret Bra.S DrawIt ; force a redraw HideCaret Tst.B teActive(A3) ; do nothing if not active Beq.S noDrawIt ; NO SF teCarAct(A3) ; deactivate caret EraseCaret Tst.B teCarOn(A3) ; see if caret is on Beq.S noDrawIt ; don't draw it if so SF teCarOn(A3) ; caret marked on ; Must be called with sorted selStart and selEnd DrawIt MoveM.L D0-D7,-(SP) Move teSelStart(A3),D3 ; dispStart:=selStart Move D3,D4 ; dispEnd:=same MoveQ #teLoc,D7 ; does nothing except moves pen Bsr DoText ; draw the caret Move.L teCarHook(A3),D0 ; do the inversion via hook if there ; Call new procedure for caret highlighting, so that color highlighting ; won't be used. ;; If forRAM THEN If (NOT ForROM) THEN ; <19Feb89smb> BTst #14,ROM85 ; color QD around? Bnz.S @1 ; nope Bsr CaretHook ; Bra.S @2 ; @1 Bsr InvertHook ; @2 ;; ElseIf onNuMac|onMvMac THEN ; rwh ElseIf hasCQD THEN ; <19Feb89smb> Bsr CaretHook ; NO Else Bsr InvertHook ; NO EndIf MoveM.L (SP)+,D0-D7 noDrawIt Rts ; ---------------------------------------------------------------------- ; PROCEDURE TEActivate( h: TEHandle ) ; PROCEDURE TEDeActivate( h: TEHandle ) ; ---------------------------------------------------------------------- TEActivate Bsr StdEntry ; NO Tst.B teActive(A3) ; see if already active Bne.S goGoHome Move teSelStart(A3),D0 ; Only enable the caret Cmp teSelEnd(A3),D0 Bne.S @1 ST teCarAct(A3) ; activate caret/don't show yet @1 ST teActive(A3) ; flag as active Bsr Hilite goGoHome Bra.S goHome TEDeactivate Bsr StdEntry ; NO Tst.B teActive(A3) ; see if already inactive Beq.S goHome Bsr.S HideCaret ; hide the caret Bsr HiLite ; Remove old selection SF teActive(A3) ; flag as inactive Bra.S goHome ; ---------------------------------------------------------------------- ; PROCEDURE TEIdle( h: TEHandle ) ; ---------------------------------------------------------------------- TEIdle Bsr StdEntry ; NO Tst.B teCarAct(A3) ; see if active Beq.S goHome SubQ #4,SP ; make room for result _TickCount ; Get current time Move.L (SP)+,A0 ; use A0 for auto extend Cmp.L teCarTime(A3),A0 ; see if done Blo.S goHome Add.L caretTime,A0 ; next time Move.L A0,teCarTime(A3) If &TYPE('&RWWDebug') <> 'UNDEFINED' Then Bsr DrawIt ; flip the caret Else Bsr.S DrawIt ; flip the caret EndIf Not.B teCarOn(A3) ; flip the flag goHome Bra epilog4 ; ---------------------------------------------------------------------- ; PROCEDURE TEPaste( h: TEHandle ); ; ---------------------------------------------------------------------- TEPaste Bsr StdEntry MoveQ #0,D7 ; flag says normal paste Bsr.S DoPaste ; NO Bra.S goHome ; {epilog4} NO DoPaste ; ** ** Don't wipe out desk scrap for old TERecs in case applications ; use it for Undo Tst.W teSize(A3) ; record with style? Bpl.S @2 ; paste from TEscrap if not ; allocate a new handle for the text scrap contents MoveQ #0,D0 ; min size ** MBK 6/20/86 ** Bsr MyNewHandle ; get a temp handle ** ** Move.L A0,D6 ; save the handle ** MBK 6/20/86 ** Move.L A0,-(SP) ; push it ** MBK 6/20/86 ** ; copy desk scrap to my temp scrap SubQ.L #4,SP ; room for VAR ** MBK 6/20/86 ** Move.L SP,A1 ; save this address ** MBK 6/20/86 ** SubQ.L #4,SP ; make room for result ** MBK 6/20/86 ** Move.L A0,-(SP) ; push new handle ** MBK 6/20/86 ** Move.L #'TEXT',-(SP) ; scrap type ** ** Move.L A1,-(SP) ; push address ** MBK 6/20/86 ** _GetScrap ; get desk scrap ** MBK 6/20/86 ** Move.L (SP)+,D0 ; error code ** MBK 6/20/86 ** AddQ.L #4,SP ; don't care ** MBK 6/20/86 ** Tst.L D0 ; error? ** MBK 6/20/86 ** Ble.S @1 ; no text scrap ** MBK 6/20/86 ** Move.L D0,D5 ; length of scrap ** MBK 6/20/86 ** Move.L D6,A0 ; ** MBK 6/20/86 ** _HLock ; lock text scrap ** MBK 6/20/86 ** Move.L (A0),D6 ; ptr to scrap ** MBK 6/20/86 ** Bsr.S PasteGuts ; go paste the scrap NO @1 Move.L (SP)+,A0 ; temp scrap handle ** MBK 6/20/86 ** _DisposHandle ; get rid of it ** MBK 6/20/86 ** Bra.S @3 ; ** ** paste from old TEScrp, for old TERecs only @2 Move.L teScrpHandle,A0 ; insertion = scrap _HLock ; lock it Move.L (A0),D6 ; now dereference MoveQ #0,D5 ; clear whole reg Move teScrpLength,D5 ; insertion length Bsr.S PasteGuts ; go paste the scrap Move.L teScrpHandle,A0 ; insertion = scrap _HUnLock ; unlock it @3 Rts ; ---------------------------------------------------------------------- ; PROCEDURE iTEStylPaste( h: TEHandle ); ; ** Added 6/20/86 by MBK ** ; TEStylePaste pastes the 'styl' scrap as well as the 'TEXT' ; scrap. TEPaste, on the other hand, simply extends the current ; style in the text to include the pasted text. Both work ; the old way for records without style. ; ---------------------------------------------------------------------- iTEStylPaste MoveQ #1,D7 ; flag says normal paste Bsr.S DoPaste ; NO MoveQ #6,D0 Bra StdExit2 ; ---------------------------------------------------------------------- ; PROCEDURE PstRsrved; ; ** ** ; I changed teReserved to a handle to the following structure: ; Record ; newReserved : LONGINT; ; nullScrap : stScrpHandle; ; End; ; nullScrap is used to store a style which is set when the ; selection is NIL in iTESetStyle. I store it in the scrap ; format so that it can easily be inserted using PstStylGuts. ; This procedure is called to paste the reserved style if there ; is one, and otherwise just to extend the current style. ; ---------------------------------------------------------------------- PstRsrved Move.L teStylesH(A3),A0 ; get style handle Move.L (A0),A0 ; deref Move.L nullStyle(A0),A0 ; get reserved handle Move.L (A0),A0 ; deref Move.L nullScrap(A0),A1 ; get handle to scrap for null selection Move.L A1,-(SP) ; save for unlocking later Move.L (A1),A0 ; deref Tst.W scrpNStyles(A0) ; is there a style? Beq.S @0 ; do extend if not MoveM.L D3/A4,-(SP) Move.L A1,A4 ; put scrap handle in A4 ; Gotta lock down null scrap! Move.L A1,A0 _HLock MoveQ #0,D3 ; clear whole register Move.W teSelStart(A3),D3 ; PstStylGuts wants this Bsr PstStylGuts ; go paste it MoveM.L (SP)+,D3/A4 Bra.S @1 @0 Bsr ExtendStyle ; just extend @1 ; Unlock previously locked null scrap Move.L (SP)+,A0 _HUnlock Rts ; ---------------------------------------------------------------------- ; PROCEDURE PasteGuts ; Entry: ; D7 = 0, if ExtendStyle should be used to update style table ; 1, if PasteStyle should be used to update style table ; D5 = insert length after the delete ; D6 = pointer to text to insert ; ---------------------------------------------------------------------- PasteGuts ; The following routines cannot trash D5/D6 Move.W D7,-(SP) ; save flag Bsr HideCaret ; NO Bsr HiLite ; remove selection NO Tst.W teSize(A3) ; check style flag Bpl.S @1 ; no, skip style paste Tst.W (SP) ; paste or extend? Beq.S @0 Bsr.S PasteStyle ; paste associated style NO Bra.S @1 ; no, skip style paste @0 Bsr.S PstRsrved ; get the style NO @1 Bsr SelSort ; sort select (A2 ^selStart/End)NO Move D0,D7 ; calc delta amount(selEnd in D0) Sub (A2),D7 ; ...for ReCalLines (A2 ^selStart) Bsr MungeSetup ; setup for the paste replace Move D7,-(SP) ; length for delete Clr -(SP) ; fake long length Move.L D6,-(SP) ; pointer to insert = p2 Move.L D5,-(SP) ; length to insert = l2 _Munger ; use sloppy munger AddQ.L #4,SP ; pop result Move.L teTextH(A3),A0 ; get text handle _Hlock ; and relock it Sub D7,teLength(A3) ; length:=length -(selEnd-selStart) Add D5,teLength(A3) ; adjust length by insert amount Sub D5,D7 ; adjust delta amount for ReCalLines Bsr RecalDraw ; redo the line stuff Lea teSelStart(A3),A0 ; point to selStart Add D5,(A0) ; selStart:=selstart + insert amount Move (A0)+,(A0) ; selEnd:=selStart Bsr ShowCaret ; NO Bsr SelView ; insure selection is visible AddQ.L #2,SP ; remove flag from stack Rts ; ---------------------------------------------------------------------- ; PROCEDURE PasteStyle ; ** Added 5/28/86 by MBK ** ; PasteStyle inserts the style scrap into the TERec style array ; If txSize is set to -1 (otherwise this is considered a record ; without style). ; Entry: ; D5: length of pasted text ; A3: ptr to TERec ; ---------------------------------------------------------------------- PasteStyle Tst.W teSize(A3) ; check style flag Bpl.S EndPStyl ; only like stylish records NO MoveM.L D2-D6/A2/A4,-(SP) ; save stuff Bsr SelSort ; get selStart, selEnd Move.W D0,D4 ; selEnd Swap D0 MoveQ #0,D3 ; make sure all clear ** ** Move.W D0,D3 ; selStart ; allocate a new handle for the styl scrap contents MoveQ #0,D0 ; min size Bsr MyNewHandle ; get a temp handle ** ** Move.L A0,A4 ; store the handle Move.L A0,-(SP) ; save the handle ; copy desk scrap to my temp scrap SubQ.L #4,SP ; room for VAR Move.L SP,A1 ; save this address SubQ.L #4,SP ; make room for result Move.L A0,-(SP) ; push new handle Move.L #'styl',-(SP) ; scrap type ** ** Move.L A1,-(SP) ; don't care what this is _GetScrap ; get desk scrap Move.L (SP)+,D0 ; error code AddQ.L #4,SP ; don't care Tst.L D0 ; style found? Bpl.S @0 ; there was a style in scrap! Bsr PstRsrved ; get the style Bra.S @4 ; extend current style NO ; 'styl' scrap was found, delete styles formerly associated with the selection @0 Move.L A4,A0 _HLock ; lock scrap handle while deleting Move.W D3,D0 ; selStart Move.W D4,D1 ; selEnd Bsr DeleteStyle ; delete associated styles Bsr.S PstStylGuts ; do the paste ; get rid of temp scrap handle @4 Move.L (SP)+,A0 ; temp scrap handle _DisposHandle ; get rid of it MoveM.L (SP)+,D2-D6/A2/A4 ; restore stuff EndPStyl Rts ; ---------------------------------------------------------------------- ; PROCEDURE PstStylGuts ; ** Separated out from PasteStyle 23jan87 by MBK ** ; PstStylGuts inserts the style info pointed at by the A4 ; handle into the TERec style array. ; Entry: ; D3: selStart (high word must be clear!) ; D5: length of pasted text ; A3: ptr to TERec ; A4: handle to style info ; ---------------------------------------------------------------------- PstStylGuts ; set up ptr to where new styles will be inserted Move.W D3,D0 ; get selStart SubQ #1,D0 ; pre-decrement Bsr GetCurStyle ; get current style Move.W D0,D4 ; index to current style Move.L (A4),A4 ; dereference Move.W scrpNStyles(A4),D2 ; get # of styles in scrap Lea scrpStyleTab(A4),A4 ; ptr to style array Move.W D3,D0 ; selStart Bne.S @0 ; dup if not 0 Tst.W D2 ; make sure num styles <> 0 Beq.S @05 SubQ #1,D4 ; adjust index for this style Bra.S @05 @0 Bsr DupStyle ; make copy of style if needed Add.L #stStartSize,A0 ; pt to next style @05 Add.W D2,D4 ; save index to last style Bsr.S MakeRoom ; make room in array NO Move.L A0,A2 ; updated ptr Move.L teStylesH(A3),A0 ; lock handle because _HLock ; you'll be munging ; loop over styles in scrap, adding them to styles array if not there already @1 Move.L scrpStartChar(A4),D1 ; get scrap start offset ** ** Add.L D3,D1 ; plus current offset ** ** Cmp.L #$FFFF,D1 ; offset cannot be > 64K ** ** Bhi.S @3 ; if it is don't add it ** ** Move.W D1,-(SP) ; save offset ** ** Move.L A4,A0 ; ptr to stuff that counts ; The count is a longint in the scrap style table, so I should be adding ; 2 to point to where a regular style record would be pointing. Otherwise, ; FindStyle will not find this style in the table. AddQ.L #2,A0 Bsr FindStyle ; look for it Tst.L D0 ; do we have it already? Bne.S @2 ; yes Move.L A4,A0 AddQ.L #2,A0 ; skip high word ** ** Bsr AddStyle ; else, add it Move.W #1,stCount(A1) ; A1 is still pointing to style entry ; in either case insert new style descriptor in runs array @2 Move.W (SP)+,D1 ; restore offset Move.W D1,(A2)+ ; store style start Move.W D0,(A2)+ ; store style index @3 Add.L #scrpRecSize,A4 ; pt to next scrap style SubQ.W #1,D2 ; dec style counter (make word len!) Bne.S @1 ; keep looping if more SubQ #stStartSize,A2 ; add size of pasted text to all following style starts Move.L teStylesH(A3),A0 ; handle to style info _HUnlock ; ok to unlock it now Move.L A2,A0 ; ptr to last style Move.W D4,D0 ; index to last style Bsr RecalStStarts ; inc following style starts Bsr ConcatStyles ; allow no duplications ** ** Bsr ClearRsrved ; clear reserved handle Rts ; ---------------------------------------------------------------------- ; PROCEDURE MakeRoom ; ** Added 6/19/86 by MBK ** ; MakeRoom moves down the contents of the runs array ; to make room for new entries. ; Entry: ; D2: # of new entries ; A0: ptr from which to move ; Exit: ; A0: new ptr value (after resizing) ; ---------------------------------------------------------------------- MakeRoom MoveM.L D2-D3/A2,-(SP) Move.L A0,A2 ; ptr from which to move Move.L teStylesH(A3),A0 ; style runs _HUnlock ; do this before setting D0 Move.L (A0),A1 MoveQ #1,D0 ; + 1 for dummy end ** ** Add.W nRuns(A1),D0 ; current # of style runs ** ** Add.W D2,nRuns(A1) ; new # of styles LsL.L #2,D0 ; * stStartSize ** ** Move.L D0,D3 ; preserve size for block move Add.L #stBaseSize,D0 ; add rest of handle size ** ** Lea runs(A1),A1 ; pt to start of style runs Sub.L A1,A2 ; preserve ptr as an offset ** ** Sub.L A2,D3 ; amount to be moved down Ext.L D2 ; make it a long ** ** LsL.L #2,D2 ; * stStartSize ** ** Add.L D2,D0 ; new size of block Bsr MySetHandleSize ; reset handle size ** ** Move.L (A0),A1 ; dereference Lea runs(A1),A1 ; pt to start of style runs Add.L A2,A1 ; source ** ** _HLock ; assume locked state ** ** Move.L A1,A0 Add.L D2,A1 ; destination Move.L D3,D0 ; length _BlockMove ; make room MoveM.L (SP)+,D2-D3/A2 Rts ; ---------------------------------------------------------------------- ; PROCEDURE DupStyle ; ** Added 6/11/86 by MBK ** ; DupStyle makes a duplicate copy of the current style ptr ; If no new style starts at the current cursor position. ; This is used when the style is about to be broken up by ; newly inserted styles (such as from TEStylePaste). ; Entry: ; D0: selStart ; A0: ptr to current style ; ---------------------------------------------------------------------- DupStyle Move.L D2,-(SP) Move.L A0,A1 Add.L #stStartSize,A0 ; pt to next Cmp.W startChar(A0),D0 ; does a new style start here? Beq.S @0 ; if so, no need to dup Move.W D0,-(SP) MoveQ #1,D2 ; one style to insert Bsr.S MakeRoom ; make room for it NO Move.L A0,A1 ; copy it SubQ #stStartSize,A1 ; point to prev style Move.W (SP)+,startChar(A0) ; get style start Move.W styleIndex(A1),D0 ; get style's index ** ** Move.W D0,styleIndex(A0) ; copy style index ** ** ; ** ** obscure bug found by Andy H.; DupStyle should inc the stCount Bsr GetStyle ; get the style ** ** AddQ #1,stCount(A0) ; and inc the count @0 Move.L (SP)+,D2 Move.L A1,A0 Rts ; ---------------------------------------------------------------------- ; PROCEDURE FindStyle ; ** Added 5/29/86 by MBK ** ; FindStyle looks for a style in the style array matching the ; style pointed at by A0. ; Entry: ; A0: ptr to style being sought ; A3: TEHandle ; Exit: ; D0(High): 1 if style was found, 0 otherwise ; D0(Low): style index if style is found, 0 otherwise ; A0: ptr to entry in style array if style is found, ; No change otherwise ; ---------------------------------------------------------------------- FindStyle Move.L D2,-(SP) ; save stuff ; get ptr to 1st style in text Move.L teStylesH(A3),A1 ; get style handle Move.L (A1),A1 ; dereference Move.W nStyles(A1),D2 ; get # of styles in text Move.L styleTab(A1),A1 ; handle to styles array Move.L (A1),A1 ; dereference Lea stFont(A0),A0 ; set ptr to relevent data Move.W D2,D1 ; init to # of styles ; loop over styles comparing to the one being sought @0 Tst.W stCount(A1) ; is this style being used? Beq.S @1 ; doesn't count if not Bsr.S CompareStyles ; do the styles match? NO ; Tst.W D0 ; REDUNDANT! Beq.S @2 ; go if you have a match @1 Add.L #stRecSize,A1 ; point to next style SubQ #1,D1 ; dec counter Bne.S @0 ; keep trying MoveQ #0,D0 ; clear flag to indicate not found Bra.S @3 ; a matching style was found, set flag and style index @2 MoveQ #1,D0 ; indicates style found ** ** Swap D0 ; faster than MOVE.L #$10000,D0 ** ** Sub.W D1,D2 ; get the difference Move.W D2,D0 ; return index in D0(Low) AddQ.W #1,stCount(A1) ; inc the count Move.L A1,A0 ; return ptr in A0 @3 Move.L (SP)+,D2 ; restore stuff Rts ; ---------------------------------------------------------------------- ; PROCEDURE CompareStyles ; ** Added 5/29/86 by MBK ** ; CompareStyles compares two styles byte by byte. ; Entry: ; A0: ptr to one style ; A1: ptr to another style ; Exit: ; D0: non-zero if styles don't match, 0 if they do ; ---------------------------------------------------------------------- CompareStyles MoveM.L A0-A1,-(SP) ; save ptrs Lea stFont(A1),A1 ; set ptr to relevent data Move.L #styleSize,D0 ; get size of style descriptor @0 CmpM.B (A0)+,(A1)+ ; compare a byte Bne.S @1 ; quit if not equal SubQ #1,D0 ; else dec the counter Bne.S @0 ; keep comparing if not 0 @1 MoveM.L (SP)+,A0-A1 ; restore ptrs Rts ; ---------------------------------------------------------------------- ; PROCEDURE AddStyle ; ** Added 5/30/86 by MBK ** ; AddStyle adds a new style to the styles array. ; Entry: ; A0: ptr to style to be added ; A3: TEHandle ; Exit: ; D0: style index ; ---------------------------------------------------------------------- AddStyle MoveM.L D2-D3/A2,-(SP) ; Get # of styles and handle to them Move.L teStylesH(A3),A1 ; get handle to style info Move.L (A1),A2 ; dereference Move.W nStyles(A2),D0 ; get # of styleRecs Move.W D0,D3 ; save it Move.L styleTab(A2),A1 ; handle to styleRecs Move.L (A1),A1 ; dereference ; If a style has a count of 0, its location may be reused by the new style @0 Tst.W stCount(A1) ; style being used? Beq.S @1 ; if not, it can be reused Add.L #stRecSize,A1 ; else, pt to next style rec SubQ #1,D0 ; dec the counter Bne.S @0 ; keep trying ; No empty slots found, so create room at the end Move.L A0,-(SP) ; save ptr to new style AddQ #1,nStyles(A2) ; inc # of styleRecs Move.L styleTab(A2),A0 ; handle to styleRecs _GetHandleSize ; how big is it? Move.L D0,D2 ; save size Add.L #stRecSize,D0 ; inc size by 1 record ; ** ** didn't need to reset A0 again since GetHandleSize doesn't trash it Move.L A0,A2 ; handle to styleRecs ** ** Bsr MySetHandleSize ; reset handle size ** ** Move.L (SP)+,A0 ; restore ptr to new style Move.L (A2),A1 ; dereference Add.L D2,A1 ; add record at end MoveQ #0,D0 ; will be using last slot @1 Sub.W D0,D3 ; get the index Move.L #stRecSize,D0 ; size of record _BlockMove ; copy it to styleRec array Move.W D3,D0 ; return the index MoveM.L (SP)+,D2-D3/A2 Rts ; A3 the standard record w/selstart for the offset ; trashes A1 ; leaves stack setup to l1 MungeSetup Move.L (SP)+,A1 ; get local RTS Move.L teTextH(A3),A0 ; get text handle _HUnlock SubQ.L #4,SP ; room for result Move.L A0,-(SP) ; push handle Move teSelstart(A3),-(SP) ; start index for insert Clr -(SP) ; fake long for index Clr.L -(SP) ; fake p1 Jmp (A1) ; ---------------------------------------------------------------------- ; PROCEDURE InsRsrved; ; ** ** ; I changed teReserved to a handle to the following structure: ; Record ; newReserved : LONGINT; ; nullScrap : stScrpHandle; ; End; ; nullScrap is used to store a style which is set when the ; selection is NIL in iTESetStyle. I store it in the scrap ; format so that it can easily be inserted using PstStylGuts. ; This procedure is called to insert the reserved style if there ; is one, and otherwise just to extend the current style. ; ---------------------------------------------------------------------- InsRsrved Tst.W D5 ; anything being inserted? Beq.S @1 ; quit if not Move.L teStylesH(A3),A0 ; get style handle Move.L (A0),A0 ; deref Move.L nullStyle(A0),A0 ; get reserved handle Move.L (A0),A0 ; deref Move.L nullScrap(A0),A1 ; get handle to scrap for null selection Move.L (A1),A0 ; deref Tst.W scrpNStyles(A0) ; is there a style? Beq.S @0 ; do extend if not MoveM.L D3/A4,-(SP) Move.L A1,A4 ; put scrap handle in A4 MoveQ #0,D3 ; clear whole register Move.W teSelStart(A3),D3 ; PstStylGuts wants this Bsr PstStylGuts ; go paste it MoveM.L (SP)+,D3/A4 Bsr ClearRsrved ; selection is different now Bra.S @1 @0 Move.W teSelStart(A3),D0 ; get selStart SubQ #1,D0 ; pre-decrement Bsr GetCurStyle ; get current style Bsr RecalStStarts ; adjust start points @1 Rts ; ---------------------------------------------------------------------- ; PROCEDURE InsGuts ; ** Modified 6/18/86 by MBK ** ; Takes the text pointed to by D6 of length D5 and inserts it ; at selStart. It then adjusts teLength by the inserted length. ; It also adjusts D7, the delta accumulator for RecalLines. ; Entry: ; D5 length of text ; D6 pointer to text ; D7 pending delta amount for recalLines ; Exit: ; D7 Adjusted by insert amount ; ---------------------------------------------------------------------- InsGuts Bsr.S MungeSetup ; setup for the insert NO Clr.L -(SP) ; fake l1 Move.L D6,-(SP) ; pointer to insert = p2 Move.L D5,-(SP) ; length to insert = l2 _Munger ; use sloppy munger AddQ.L #4,SP ; pop result Move.L teTextH(A3),A0 ; get text handle _Hlock ; and relock it Add D5,teLength(A3) ; adjust length by insert amount Sub D5,D7 ; adjust delta amount for ReCalLines Tst.W teSize(A3) ; check style flag Bpl.S @0 ; no, you're done ** MBK 6/18/86 ** Bsr.S InsRsrved ; insert the style NO @0 Rts ; ---------------------------------------------------------------------- ; PROCEDURE TEInsert( pText: PTR; l: LONGINT; h: TEHandle ); ; This inserts the passed text/length just before the selection ; but doesn't touch the scrap. The selection too is "untouched" ; because it is offset by the inserted amount to point to the same ; range. Just after a TENew this can be used as a replacement for ; the old TESetText because the slection and length are all zero. ; ---------------------------------------------------------------------- TEInsert Bsr StdEntry Bsr HideCaret ; NO Bsr HiLite ; remove selection NO MoveQ #0,D7 ; delta = 0(No deletion) MoveM.L (A2)+,D5-D6 ; A2 points to l param Bsr.S insGuts ; go insert the scrap Bsr RecalDraw ; redo the line stuff Add D5,teSelStart(A3) ; selStart:=selstart + insert amount Add D5,teSelEnd(A3) ; selEnd:=selEnd + insert amount Bsr ShowCaret Bsr HiLite ; restore selection NO epilog12 MoveQ #12,D0 Bra StdExit ; ---------------------------------------------------------------------- ; PROCEDURE TEKey( key: CHAR; h: TEHandle ); ; ** Modified 6/18/86 by MBK ** ; ---------------------------------------------------------------------- TEKey Bsr StdEntry ; NO ST teLftCaret(A3) ; jam caret to left _ObscureCursor ; nice knowing you cursor Move.W (A2),D1 ; store char away Cmp.B #$08,D1 ; is it a backspace? Beq.S backSpace ; Cursor Key support - Added from 'Lonely Hearts' patch 14Jan86 ; left: If selStart isn't 0 it decrements it and places the caret there ; right: Increments selEnd and places caret there ; up: simulates a click one line above current selStart point ; down: simulates a click one line below current selStart point MoveQ #1,D2 ; assume going down MoveQ #$1F,D0 ; range $1C-$1F Sub.B D1,D0 ; get key code Blt.S @0 Beq.S downArrow ; is it a cursor key? SubQ.B #1,D0 Beq.S upArrow SubQ.B #1,D0 Beq.S rightArrow SubQ.B #1,D0 Beq.S leftArrow @0 Bra.S PasteChar ; => go paste in the character upArrow MoveQ #-1,D2 ; going up downArrow Move D2,-(SP) ; save D2 Move teSelStart(A3),D3 ; pass selStart=selEnd Move D3,D4 MoveQ #-2,D7 ; position pen to caret Bsr DoText ; the port ret. in A0 Move (SP)+,D2 ; restore D2 Bsr FindLineHite ; get current line hite ** MBK 6/18/86 ** MulS D1,D2 ; get delta -- a SIGNED 16-bit value<09Dec85 JTC> Move.L teSelRect(A3),teSelPoint(A3) ; pass caret point Add D2,teSelPoint(A3) ; adjust v value Bsr DoFind ; the port ret. in A0 ST teLftCaret(A3) ; force clean clicks Bra.S leftRight ; setselect'll force autoscroll rightArrow Move teSelEnd(A3),D6 ; get start AddQ #1,D6 ; going down Bra.S leftRight leftArrow Move teSelStart(A3),D6 ; get start Beq.S leftRight SubQ #1,D6 ; going to left leftRight Ext.L D6 ; D6 comes back char loc Move.L D6,-(SP) ; pass start Move.L D6,-(SP) Move.L A4,-(SP) _TESetSelect Bsr DrawCaret ; force caret ON Bra.S Epilog6 PasteChar ; Go paste the character Move.L A2,D6 ; point to the character AddQ #1,D6 ; character in lower half MoveQ #1,D5 ; one long MoveQ #0,D7 ; want to call ExtendStyle Bsr PasteGuts Bra.S epilog6 backSpace Move teSelStart(A3),D0 ; see if null selection Cmp teSelEnd(A3),D0 Bne.S cutit ; since there's no selection eat characters to the left. Tst D0 ; see if at extreme left Beq.S epilog6 ; skip if so Bsr HideCaret ; remove the caret SubQ #1,teSelStart(A3) ; adjust selection cutit Move.L A4,-(SP) ; pass the handle _TEDelete ; and cut it (A3 no good after) epilog6 MoveQ #6,D0 Bra StdExit ; ---------------------------------------------------------------------- ; PROCEDURE ExtendStyle ; ** Added 6/6/86 by MBK ** ; Handles deletion or extension of styles. ; Entry: ; D5 length of text being inserted (preserved) ; ---------------------------------------------------------------------- ExtendStyle Move.W D5,-(SP) ; save length Tst.W teSize(A3) ; check style flag Bpl.S @1 ; quit if not ; get selStart, selEnd and see if it's an insertion pt Bsr SelSort ; sorts selStart, selEnd Move.W D0,D1 ; selEnd Swap D0 ; selStart in low byte now Cmp.W D0,D1 ; is it an insertion pt? Beq.S @0 ; no styles to delete if so ; If insertion is replacing a selection, you want to use the style of the ; first character of the selection (whereas if it's an insertion pt, you ; use the previous character's style). SubQ #1,D5 ; dec insertion length AddQ #1,D0 ; pt to next char Bsr DeleteStyle ; else, delete excess styles @0 Tst.W D5 ; anything to insert? Beq.S @1 ; you're done if not SubQ #1,D0 ; pre-decrement Bsr GetCurStyle ; else get current style Bsr RecalStStarts ; update style starts @1 Move.W (SP)+,D5 ; restore length Rts ; ---------------------------------------------------------------------- ; PROCEDURE FindLineHite ; ** Added 6/16/86 by MBK ** ; Finds the given line and returns its line height. ; Entry: ; D3 selStart ; Exit: ; D1 height of this line ; ---------------------------------------------------------------------- FindLineHite Move.L A2,-(SP) ; save A2 Lea teLines(A3),A2 ; pt to start of linestarts Move.W D3,D0 ; offset Bsr GetLine ; get line that it's on Bsr PtrToLine ; get line # from A2 ; Get maximum height on this line from the array Bsr GetHite ; get height of this line Move.L (SP)+,A2 ; restore A2 Rts ; ---------------------------------------------------------------------- ; PROCEDURE TESetJust( just: INTEGER; h: TEHandle ); ; Sets the justify mode. DOESN'T redraw. Lovely code... ; ---------------------------------------------------------------------- TESetJust Bsr StdEntry Move (A2),teJust(A3) ; set the style Bra.S epilog6 ; NO ; ---------------------------------------------------------------------- ; PROCEDURE Refresh ; Redraws the lines intersected verticals top in D0, bottom in D1 ; ---------------------------------------------------------------------- Refresh MoveQ #0,D3 ; min/max redraw pins in DoDraw MoveQ #-1,D4 Bsr PinA0Rect ; pass A0 rect to Pin code MoveQ #teDraw,D7 ; drawit Bsr DoText Bsr HiLite ; reshow selection Tst.B teCarOn(A3) ; force a redraw if caret is on Beq.S handyReturn ; if off skip it Bra ForceCaret ; implied return ; ---------------------------------------------------------------------- ; PROCEDURE TEScroll( dh, dv: INTEGER; h: TEHandle ) ; Scrolls the dest rect "under" the view rect to give the caller ; scrolling ability. A call of ( 0, -lineheight, h) would scroll up ; one line, because dest rect is offset by the passed (dh,dv). The ; resultant update region is redrawn ; ---------------------------------------------------------------------- TEScroll Bsr StdEntry Bsr HideCaret Move.L (A2)+,D3 ; get dv,dh pair Bsr.S Scroll epilog8 MoveQ #8,D0 Bra StdExit ; Amount to scroll in D3 Scroll Tst.L D3 ; escape if nothing there Beq.S ActCaret ; fix errant HideCaret (and RtsÉ) Pea teDestRect(A3) ; pass the dest rectangle Move.L D3,-(SP) ; pass dh, dv _OffsetRect SubQ #4,SP ; make room for temp region _NewRgn ; get it Move.L (SP)+,A2 ; save its handle Pea teViewRect(A3) ; pass rect to scroll Move.L D3,-(SP) ; pass dh, dv Move.L A2,-(SP) ; pass the temp region _ScrollRect Bsr.S ActCaret ; just activate, don't draw NO Move.L A2,-(SP) ; clip to it update rgn _SetClip Move.L (A2),A0 ; point to region Lea rgnBBox(A0),A0 Bsr.S Refresh ; and redraw those lines Move.L A2,-(SP) ; get rid of temp region _DisposRgn @0 handyReturn Rts ; ** ** Don't draw caret yet, just activate it ActCaret Tst.B teActive(A3) ; do nothing if not active Beq.S @0 ; NO Move teSelStart(A3),D0 ; see if should be turned on Cmp teSelEnd(A3),D0 Bne.S @0 ; if selection <> 0 then escape ST teCarAct(A3) ; replaced ShowCaret @0 Rts ; ---------------------------------------------------------------------- ; PROCEDURE TEPinScroll( dh, dv: INTEGER; h: TEHandle ) ; ** Modified 6/18/86 by MBK ** ; Scrolls the dest rect "under" the view rect to give the caller ; scrolling ability. A call of ( 0, -lineheight, h) would scroll up ; one line, because dest rect is offset by the passed (dh,dv). The ; resultant update region is redrawn. This version pins the scroll ; amount to the destRect/nLines ; ---------------------------------------------------------------------- TEPinScroll Bsr StdEntry Bsr HideCaret Move (A2),D0 ; get dV Bpl.S @1 ; pin top Move.W teNLines(A3),D1 ; last line ** MBK 6/18/86 ** Move.W teLength(A3),D0 ; last char ** ** Tst.W D0 ; anything in file? ** ** Beq.S @0 ; skip test if not ** ** Move.L teTextH(A3),A0 ; text handle ** ** Move.L (A0),A0 ; dereference ** ** Cmp.B #$0D,-1(A0,D0) ; file end with CR? ** ** Bne.S @0 ; end of file if not ** ** AddQ #1,D1 ; else 1 more line ** ** @0 MoveQ #0,D0 ; 1st line ** MBK 6/18/86 ** Bsr GetLineHites ; compile max hites ** MBK 6/18/86 ** Move.W D0,D1 ; hite from 1st to last ** MBK 6/18/86 ** Move.W (A2),D0 ; restore D0 ** MBK 6/18/86 ** Add teDestRect+top(A3),D1 ; get destRect.top Sub teViewRect+bottom(A3),D1 ; a diff. viewRect.bottom Ble.S @2 ; dest already gone... Add D1,D0 ; see what delta does Bpl.S pinH Bra.S @2 ; should be subtracted because it's negative @1 Move teDestRect+top(A3),D1 ; add destRect.top Sub teViewRect+top(A3),D1 ; diff. viewRect.top Bpl.S @2 ; already bad Add D1,D0 Bmi.S pinH @2 Sub D0,(A2) ; adjust scroll pinH Move 2(A2),D0 ; get dH Bpl.S @1 ; pin top Move teDestRect+right(A3),D1 ; add destrect.right Sub teViewRect+right(A3),D1 ; a diff. viewRect.right Ble.S @2 ; already past, cancel scroll Add D1,D0 Bpl.S pinDone Add D0,2(A2) ; adjust scroll Bra.S pinDone @1 Move teDestRect+left(A3),D1 ; add destRect.left Sub teViewRect+left(A3),D1 ; diff. viewRect.left Bpl.S @2 ; already past, cancel scroll Add D1,D0 Bmi.S pinDone @2 Sub D0,2(A2) ; adjust scroll pinDone Move.L (A2)+,D3 ; get dv,dh pair Bsr Scroll ; and go scroll it Bsr ActCaret ; just activate, don't draw ** ** Bra epilog8 ; ---------------------------------------------------------------------- ; PROCEDURE TESelView( hTe: TEHandle ); ; ** Modified 6/18/86 by MBK ** ; Insures the selection is in view rect. SelView is a local ; copy of it ; ---------------------------------------------------------------------- TESelView Bsr StdEntry ; doo dah... Bsr.S SelView ; go do it Bra epilog4 ; local cover (A4/A3 pointing to usual record) SelView ; ; Changed from teFlags to new whizzy position in TEDispatchRec ; BTst #tefAutoPos,teFlags(A3) ; scrolling allowed? Move.L teDispatchH(A3),A0 Move.L (A0),A0 Move.L newTEFlags(A0),D0 BTst #0,D0 Beq.S @0 ; if not, must skip Bsr SelSort ; sort selection Move teSelStart(A3),D3 ; dispStart:=selStart Move D3,D4 ; dispEnd:=same MoveQ #teLoc,D7 ; does nothing except moves pen Bsr DoText ; position for the caret Move.L teSelRect+topLeft(A3),D7 ; save penloc in D7 Lea tempRect+8,A2 ; place for working rect Lea teViewRect+8(A3),A0 ; source Move.L -(A0),-(A2) Move.L -(A0),-(A2) Move teSelStart(A3),D3 ; dispStart:=selStart ** ** Bsr FindLineHite ; get height of line ** ** Sub D1,bottom(A2) SubQ #1,right(A2) ; room for caret SubQ #2,SP Move.L D7,-(SP) ; pass selStart location Move.L A2,-(SP) ; pass adjust viewRect _PtInRect Tst.B (SP)+ Bne.S @0 ; if visible, then OK Move.L (A2)+,-(SP) ; get adjusted viewRect.topLeft Move.L (A2),-(SP) ; get adjusted viewRect.botRight Move.L -(A2),-(SP) ; subtract adjusted topLeft Pea 4(SP) _SubPt Pea 4(SP) ; add top to delta _AddPt Move.L D7,-(SP) ; subtract penloc Pea 4(SP) ; to "center" pen if possible _SubPt Move.L A4,-(SP) _TEPinScroll ; s/b a trap ** ** @0 Rts ; adios ; ---------------------------------------------------------------------- ; PROCEDURE TEAutoView( auto: BOOLEAN; hTe: TEHandle ); ; Sets the autoview bit according to the boolean ; ---------------------------------------------------------------------- TEAutoView Bsr StdEntry ; doo dah... Move.L teDispatchH(A3),A0 ; Move.L (A0),A0 ; Move.L newTEFlags(A0),D0 ; Tst.B (A2)+ ; was it true Beq.S @0 ; BSet #tefAutoPos,teFlags(A3) ; allow scrolling BSet #0,D0 ; Bra.S @1 @0 ; BClr #tefAutoPos,teFlags(A3) ; allow scrolling BClr #0,D0 @1 Move.L D0,newTEFlags(A0) Bra epilog6 ; ---------------------------------------------------------------------- ; PROCEDURE DefClikProc ; Default click proc for scrolling - does a pinned autoscroll of ; the destRect to match the viewrect. ; Entry: ; A3 pointing to the dereferenced text edit record ; A6 pointing to the standard stack frame ; thePort set, etc. ; Exits: ; CC's set <> 0 ; ---------------------------------------------------------------------- DefClikProc MoveM.L D0-D7/A0-A4,-(SP) ; save ALL regs ; BTst #tefAutoPos,teFlags(A3) ; scrolling allowed? Move.L teDispatchH(A3),A0 ; Move.L (A0),A0 ; Move.L newTEFlags(A0),D0 ; BTst #0,D0 ; Beq.S doneAuto ; if not, must skip Lea teViewRect+8(A3),A0 ; point to view rect Lea tempRect+8,A2 ; copy into tempRect Move.L -(A0),-(A2) Move.L -(A0),-(A2) SubQ #4,SP ; room for pt Move.L SP,-(SP) _GetMouse Move (SP)+,D6 ; get V coordinate Move (SP)+,D7 ; get H coordinate MoveQ #0,D4 ; horz scroll amt Move teLineHite(A3),D1 ; vert scroll amt Bpl.S @1 ; use if not negative ** ** Move.W D6,D0 ; find D6 line ** ** Cmp.W teDestRect+bottom(A3),D0 ; pt below the rect? ** ** Ble.S @0 ; okay if less or same ** ** Move.W teDestRect+bottom(A3),D0 ; else reset to bottom ** ** @0 Bsr PtToLine ; try to find its line # ** ** Bge.S doneAuto ; no scroll if line doesn't exist ** ** Bsr GetHite ; else get its height @1 Cmp (A2)+,D6 ; subtract top of viewRect Blt.S scrollUp ; scroll up Cmp (A2)+,D7 ; subtract left of viewRect Blt.S scrollLeft ; scroll left Cmp (A2)+,D6 ; subtract bottom of viewRect Bgt.S scrollDown ; scroll down Cmp (A2)+,D7 ; subtract right of viewRect Bgt.S scrollRight ; scroll right doneAuto MoveQ #1,D0 ; cc's <> 0 MoveM.L (SP)+,D0-D7/A0-A4 ; restore ALL regs Rts scrollDown Neg D1 ; flip direction scrollUp Bra.S scrollEm scrollRight Neg D1 ; flip direction scrollLeft Exg D4,D1 ; switch axes scrollEm ; Finally do the scroll Move D4,-(SP) ; pass dh Move D1,-(SP) ; pass dv Move.L 8(A6),-(SP) ; tehandle _TEPinScroll ; _TEPinScroll ** ** Bra.S doneAuto ; NO ; ---------------------------------------------------------------------- ; PROCEDURE GetCurStyle ; ** Added 6/5/86 by MBK ** ; Gets the current style; in other words, it finds the 1st style ; descriptor preceding the current selection. ; Entry: ; D0 selection start (whose style we wish to find) ; Exit: ; D0 index into runs array of current style ; A0 ptr into runs array to current style ; ---------------------------------------------------------------------- GetCurStyle MoveM.L D1-D4,-(SP) ; get low and high indeces, and ptr to array for binary search AddQ #1,D0 ; don't get preceding style Move.W D0,D2 ; save the key (sel start) Move.L teStylesH(A3),A0 ; handle to style info Move.L (A0),A0 ; deref Move.W nRuns(A0),D1 ; high index Lea runs(A0),A0 ; pt to runs array MoveQ #0,D0 ; low index ; start of binary search loop @0 Cmp.W D0,D1 ; are indeces the same? Beq.S @3 ; we're done if so Move.W D1,D3 Add.W D0,D3 ; low + high LsR.W #1,D3 ; divide by 2 MoveQ #0,D4 ; clear the long word ** ** Move.W D3,D4 ; middle LsL.L #2,D4 ; mult by stStartSize ** ** Cmp.W 0(A0,D4),D2 ; do we have a match? Beq.S @2 ; we're done if so Bls.S @1 ; range is low to mid ; no change in high; low gets middle + 1 Move.W D3,D0 ; low := middle + 1 AddQ #1,D0 Bra.S @0 ; try again ; no change in low; high gets middle @1 Move.W D3,D1 ; else high := middle Bra.S @0 ; try again @2 Move.W D3,D0 ; store answer in D0 ; return ptr into runs array and index to the styleRec @3 Tst.W D0 Beq.S @4 ; special case of 1st style SubQ #1,D0 ; point to prev style @4 MoveQ #0,D1 ; clear the long word ** ** Move.W D0,D1 LsL.L #2,D1 ; mult by stStartSize ** ** Add.L D1,A0 ; ptr to style start MoveM.L (SP)+,D1-D4 Rts ; ---------------------------------------------------------------------- ; PROCEDURE GetNumStyles ; ** Added 5/28/86 by MBK ** ; GetNumStyles counts the number of styles in the current ; selection range in the text. ; Entry: ; D1: selEnd ; A0: ptr to current style in runs array ; Exit: ; D0: # of styles within current selection ; ---------------------------------------------------------------------- GetNumStyles Move.L A0,-(SP) ; save ptr Move.L teStylesH(A3),A1 ; handle to style info Move.L (A1),A1 ; dereference MoveQ #0,D0 ; clear whole register ** ** Move.W nRuns(A1),D0 ; # of style starts Lea runs(A1),A1 ; pt to style starts LsL.L #2,D0 ; * stStartSize ** ** Add.L D0,A1 ; pt to last style start MoveQ #0,D0 ; init the counter ; keep checking style starts till one is >= selEnd (eventually it MUST be) @0 Add.L #stStartSize,A0 ; point to next style record AddQ #1,D0 ; at least 1 style Cmp.L A0,A1 ; reached the end? Beq.S @1 ; quit if so Cmp.W startChar(A0),D1 ; is style within selection? Bhi.S @0 ; made this unsigned ** ** @1 Move.L (SP)+,A0 Rts ; ---------------------------------------------------------------------- ; PROCEDURE GetStyle ; ** Added 5/29/86 by MBK ** ; GetStyle returns a pointer to the style found at the given ; index into the style array. ; Entry: ; D0: style index ; A3: Ptr to TERec ; Exit: ; A0: style pointer ; ---------------------------------------------------------------------- GetStyle MulU #stRecSize,D0 ; multiply index by size of record Move.L teStylesH(A3),A0 ; get style handle Move.L (A0),A0 ; dereference Move.L styleTab(A0),A0 ; handle to styles array Move.L (A0),A0 ; dereference Add.L D0,A0 ; point to style descriptor Rts ; ---------------------------------------------------------------------- ; PROCEDURE RecalStStarts ; ** Added 5/23/86 by MBK ** ; Recomputes the starting offsets of each style in the text ; following the current one. It adds the length of the newly ; inserted text to each offset following the insertion point. ; Entry: ; D0 index to current style in runs array ; D5 length of inserted text ; A0 pointer to the current style in runs array ; ---------------------------------------------------------------------- RecalStStarts Move.L teStylesH(A3),A1 ; get handle to style info Move.L (A1),A1 ; deref Move.W nRuns(A1),D1 ; get # of style starts Sub.W D0,D1 ; subtract current index Bls.S @1 ; made this unsigned ** ** ; add length of inserted text to all following style starts @0 Add.L #stStartSize,A0 ; point to next style record Add.W D5,startChar(A0) ; add length to starting offset SubQ #1,D1 ; dec the counter Bne.S @0 @1 Rts ; ---------------------------------------------------------------------- ; PROCEDURE SetRsrved; ; ** ** ; I changed teReserved to a handle to the following structure: ; Record ; newReserved : LONGINT; ; nullScrap : stScrpHandle; ; End; ; nullScrap is used to store a style which is set when the ; selection is NIL in iTESetStyle. I store it in the scrap ; format so that it can easily be inserted using PstStylGuts. ; This procedure is called to set the style to whatever the user ; has input to iTESetStyle. ; On entry, SetRsrved expects A2 to be pointing to something ; that looks like this: ; flag.B TextStylePtr.L mode.W ; The flag is not accessed and can just be a hole if desired. ; ---------------------------------------------------------------------- SetRsrved Move.W teSelStart(A3),D0 ; get selection start Cmp.W teSelEnd(A3),D0 ; same as selEnd? Bne lvSetRsrved ; quit if not AltSetRsrved ; Move.L teStylesH(A3),A1 ; get style handle Move.L (A1),A1 ; deref Move.L nullStyle(A1),A1 ; get reserved handle Move.L (A1),A1 ; deref Move.L nullScrap(A1),A1 ; get handle to scrap for null selection Move.L A1,-(SP) ; save handle for later Move.L (A1),A1 ; deref Tst.W scrpNStyles(A1) ; stored already? Beq.S @0 ; reset if not Lea scrpStyleTab(A1),A1 ; point to start of tableev style if so Bra.S @1 ; go use new settings ; First get current style settings @0 SubQ #1,D0 ; in case sel is on a run boundary Bsr GetCurStyle ; get current style run Move.W styleIndex(A0),D0 ; get style index Bsr.S GetStyle ; get the style in A0 NO Move.W #1,scrpNStyles(A1) ; indicate 1 style Lea scrpStyleTab(A1),A1 ; point to start of table Move.L #0,scrpStartChar(A1) ; store start offset Lea stFont(A0),A0 Move.L (A0)+,scrpFont(A1) ; font, face Move.L (A0)+,scrpSize(A1) ; size, color Move.L (A0)+,scrpColor+2(A1) ; color ; now adjust according to new settings @1 Move.W 6(A2),D2 ; get the mode Move.L 2(A2),A0 ; get style ptr BTst #fontBit,D2 ; set font? Beq.S @2 ; no Move.W tsFont(A0),scrpFont(A1) ; else, set it @2 BTst #faceBit,D2 ; set face? Beq.S @4 ; no ; ** Added code to support doToggle mode. ; An insertion point is by definition continuous, so all we have to do is ; calculate unique set elements Move.B tsFace(A0),D0 ; fetch given face BTst #toglBit,D2 ; toggling? Bz.S @3 ; no, go set Eor.B D0,scrpFace(A1) ; Bra.S @4 ; @3 Tst.B D0 ; if new face is plainÉ Bnz.S @35 ; Clr.B scrpFace(A1) ; Éwipe out old attributes @35 Or.B D0,scrpFace(A1) ; union in new attributes @4 BTst #sizeBit,D2 ; set size only? Beq.S @5 ; no BTst #addSizeBit,D2 ; is addSize also set? Bne.S @5 ; it has precedence Move.W tsSize(A0),scrpSize(A1) ; else, get size @5 BTst #clrBit,D2 ; set color only? Beq.S @6 ; no Move.L tsColor(A0),scrpColor(A1) ; store the new value there Move.W tsColor+4(A0),scrpColor+4(A1) ; store color ,hi @6 BTst #addSizeBit,D2 ; is it addSize? Beq.S @9 Move.W scrpSize(A1),D0 ; get current size Bne.S @7 ; => not 0 Move.B FmDefaultSize,D0 ; get default size as byte value** ** @7 Add.W tsSize(A0),D0 ; add increment to size Bgt.S @8 ; size <-1 if it's 0 or negative Move.W #1,D0 ; minimum allowable @8 Move.W D0,scrpSize(A1) ; now store it @9 Move.L teGrafPort(A3),A0 ; the port Move.W scrpFont(A1),txFont(A0) ; set font Move.W scrpFace(A1),txFace(A0) ; set face Move.W scrpSize(A1),txSize(A0) ; set size Bsr GetSize ; get ascent & hite Move.L (SP)+,A0 ; get back scrap handle Move.L (A0),A0 ; deref Lea scrpStyleTab(A0),A0 ; pt to start of scrap table Move.W D0,scrpAscent(A0) ; save in ascent Move.W D1,scrpHeight(A0) ; save in line height lvSetRsrved Rts ; ---------------------------------------------------------------------- ; PROCEDURE iTESetStyle( SetMode: INTEGER; Styl: StylPtr; redraw: BOOLEAN; ; hTE: TEHandle ); ; Sets the style of the selected text (replacing all other styles). ; Supports the following modes: ; 1 doFont: Set Font only ; 2 doFace: Set Face only ; 4 doSize: Set Size only ; 8 doColor: Set Color only ; 15 doAll: Set all modes ; 16 addSize: Add Size integer to each size in selection ; 32 doToggle: Set each face attribute if not continuous, reset otherwise ; ---------------------------------------------------------------------- iTESetStyle Tst.W teSize(A3) ; check style flag Bpl.S @1 ; if not, sorry, can't set it Bsr SetRsrved ; save the style ; ** ** boolean value is in bit 1 of high byte Move.W (A2)+,D0 ; get redraw value ** ** And #$FF00,D0 ; check redraw value ** ** Bne.S @0 ; must redraw if set Bsr.S SetGuts ; else just add styles Bra.S @1 @0 Move.L A2,-(SP) ; save ptr to parameters Bsr HideCaret Bsr HiLite ; remove selection Move.L (SP)+,A2 ; restore ptr to parameters Bsr.S SetGuts ; do style munging MoveQ #0,D7 ; length is 0 Bsr RecalDraw ; redo the line stuff Bsr ShowCaret Bsr Hilite ; restore selection Bsr SelView ; ensure selection is visible @1 MoveQ #14,D0 Bra stdExit2 ; ---------------------------------------------------------------------- SetGuts MoveM.L D2-D7/A2/A4/A6,-(SP) ; save registers Move.L (A2)+,A4 ; style ptr Move.W (A2)+,D7 ; save mode here Sub.L A6,A6 ; not used by SetStyle ; ** Added code to support doToggle. ; I changed the next statement to a mask from the original, which punted if ; it saw bits it didn't like. And.W #doAll3,D7 ; only lower 6 bits make sense Move.W D7,D0 ; And.W #doFace+doToggle,D0 ; are we toggling? Cmp.W #doFace+doToggle,D0 ; (both bits have to be on, dummy!) Bne.S @05 ; SubQ.W #1,A6 ; -1 to signal toggle mode Move.W #doFace,-(SP) ; prepare fake frame for call ; SP => doFace/2 Sub.W #styleSize+2,SP ; make room for result & TextStyle ; SP => VAR/2 VAR/styleSize doFace/2 Pea styleSize+2(SP) ; push pointer to doFace ; SP => ^doFace/4 VAR/2 VAR/styleSize doFace/2 Pea 4+2(SP) ; push pointer to TextStyle hole ; SP => ^VAR/4 ^doFace/4 VAR/2 VAR/styleSize doFace/2 Move.L SP,A2 ; point A2 at stacked parameters Bsr ContGuts ; coalesce continuous styles Add.W #10,SP ; pop stack back to TextStyle Move.B tsFace(SP),D5 ; save continuous face attributes Swap D5 ; we'll need low word later Add.W #styleSize+2,SP ; now remove TextStyle & doFace @05 ; Bsr.S StyleGuts ; do style munging @0 MoveM.L (SP)+,D2-D7/A2/A4/A6 ; restore registers Rts ; ---------------------------------------------------------------------- StyleGuts Tst.W D7 ; check mode Beq EndStyle ; 0 is invalid mode Bsr SelSort ; sort selStart, selEnd Move.W D0,D1 ; save selEnd Move.W D0,D4 Swap D0 Move.W D0,D3 ; save selStart Sub.W D3,D1 ; save selection length Beq EndStyle ; if len = 0, nothing to do ; store the input style information temporarily Sub.L #stRecSize,SP ; make room on stack Move.L SP,A2 ; save ptr in A2 ; Move.W D3,D0 ; selStart REDUNDANT! Bsr GetCurStyle ; get current style Move.W D4,D1 ; selEnd Bsr GetNumStyles ; get # of styles within selection Move.W D0,D2 ; preserve # of styles Swap D3 ; selStart in upper word Move.W D4,D3 ; selEnd in lower word ; ** Faces are byte lengthÉ Move.B tsFace(A4),D4 ; save face Swap D4 ; put face in upper word Move.W tsFont(A4),D4 ; font in lower word Move.W tsSize(A4),D5 ; save size Move.L tsColor(A4),D6 ; save color Swap D7 ; running out of reg's ** ** Move.W tsColor+4(A4),D7 ; store color in D7,hi ** ** Swap D7 ; keep mode in D7,low ** ** Move.L A2,A4 ; temp style handle Move.L A0,A2 ; preserve ptr Move.L teStylesH(A3),A0 ; handle to style info ** ** _HLock ; keep it locked ** ** ; By this point, the world looks like this: ; D2.W = number of styles in current selection (used as counter) ; D3.L = selStart/selEnd (high word/low word) ; D4.L = Face/Font ; D5.L = Toggle face info/Size ; D6.L = Color Red/Green ; D7.L = Color Blue/set mode ; A2.L => StyleRun array, first associated element ; A4.L => working STElement on stack styleLoop Move.W styleIndex(A2),D0 ; else, index to style Bsr GetStyle ; find it Bsr CheckMatch ; must match for replacement Tst.W D0 ; check return flag Beq noMatch ; if false, don't replace Move.L #stRecSize,D0 ; length of a styleRec Move.L A4,A1 ; ptr to temp storage _BlockMove ; copy to temp location for mod Move.L A2,A0 ; current style Move.L D3,D0 ; selStart, selEnd Swap D0 ; selStart in low word Cmp.W startChar(A2),D0 ; compare to style start Bls.S @0 ; made this unsigned ** ** Bsr DupStyle ; else dup it AddQ #stStartSize,A0 ; new style replaces this Move.L A0,A2 @0 Cmp.W #1,D2 ; last style? Bne.S @1 ; not yet AddQ #stStartSize,A0 Cmp.W startChar(A0),D3 ; compare to style end Beq.S @1 ; ok if same as selEnd Move.W D3,D0 ; selEnd Move.L A2,A0 ; current style Bsr DupStyle ; dup it Move.L A0,A2 ; ptr updated in A0 ; ** ** dupstyle was fixed to inc the style count, so it's ; ok to dec it in all cases now @1 MoveQ #1,D0 ; # of styles to (possibly) delete Move.L A2,A0 ; ptr to style start Bsr DecStylCount ; style used 1 less time BTst #fontBit,D7 ; set font? Beq.S @3 ; no Move.W D4,stFont(A4) ; else, put in temp rec @3 BTst #faceBit,D7 ; set face? Beq.S @5 ; no ; ** This new code supports the doToggle mode Move.L D4,D0 ; fetch face information Swap D0 ; move face to low byte Move.L A6,D1 ; are we just setting? Bz.S @41 ; AddQ.L #1,D1 ; are we toggling? (was it just -1?) Beq.S @42 ; yes, go handle ; ReplacingÉ Move.B D0,stFace(A4) ; we must be replacing, then Bra.S @5 ; ; TogglingÉ (algorithm also works for plain, so we don't have to special case) @42 Move.L D5,D1 ; fetch toggle info Swap D1 ; move continuous face to low byte And.B D0,D1 ; intersect faces for XOR mask Eor.B D1,D0 ; difference from desired is OR mask Or.B D0,stFace(A4) ; union in new style attributes Eor.B D1,stFace(A4) ; remove already set attributes Bra.S @5 ; ; MergingÉ @41 Tst.B D0 ; is it plain? Bnz.S @43 ; no, merge in attributes Clr.B stFace(A4) ; remove all styles if plain @43 Or.B D0,stFace(A4) ; union sets @5 BTst #sizeBit,D7 ; set size only? Beq.S @6 ; no BTst #addSizeBit,D7 ; is addSize also set? ** ** Bne.S @6 ; it has precedence ** ** Move.W D5,stSize(A4) ; else, get size @6 BTst #clrBit,D7 ; set color only? Beq.S @7 ; no Move.L D6,stColor(A4) ; store the new value there Swap D7 ; running out of reg's ** ** Move.W D7,stColor+4(A4) ; store color in D7,hi ** ** Swap D7 ; keep mode in D7,low ** ** @7 BTst #addSizeBit,D7 ; is it addSize? ** ** Beq.S @9 Move.W stSize(A4),D0 ; get current size Bne.S @8 ; => not 0 ; I assumed FmDefaultSize was a word constant, but actually it points to a byte value. Move.B FmDefaultSize,D0 ; get default size as byte value** ** Move.W D0,stSize(A4) ; store as word value ** ** @8 ; Don't allow the size to become 0 or be negative. Add.W D5,D0 ; add increment to size Bgt.S @81 ; size <-1 if it's 0 or negative Move.W #1,D0 ; minimum allowable @81 Move.W D0,stSize(A4) ; now store it @9 Move.L A4,A0 ; point to relevent stuff Bsr FindStyle ; look for this style Tst.L D0 ; do we have it already? Bne.S @10 ; guess so Move.L A4,A0 ; get ptr to new style Bsr.S SetHiteAscent ; set line height and font ascentNO Move.W #1,stCount(A0) ; will be used once to start Bsr AddStyle ; and add it @10 Move.W D0,styleIndex(A2) ; store new style index NoMatch AddQ #stStartSize,A2 ; point to next style SubQ.W #1,D2 ; dec style counter Bne styleLoop ; keep looping if not 0 Move.L teStylesH(A3),A0 ; handle to style info _HUnlock Bsr ConcatStyles ; watch out for adjoining styles Add.L #stRecSize,SP ; restore stack EndStyle Rts ; ---------------------------------------------------------------------- ; PROCEDURE SetHiteAscent ; Added 5/30/86 by MBK ; SetHiteAscent sets the line height and the font ascent based ; On the given style. ; Entry: ; A0: ptr to style (preserved) ; A3: TEHandle ; ---------------------------------------------------------------------- SetHiteAscent Move.L D2,-(SP) ; save registers ; set my style just to get the info I need Move.L teGrafPort(A3),A1 ; the port Move.W stFont(A0),txFont(A1) ; set font Move.W stFace(A0),txFace(A1) ; set face Move.W stSize(A0),txSize(A1) ; set size ; get the line height and font ascent Bsr GetSize ; get ascent & hite ** ** Move.W D0,stAscent(A0) ; save in ascent ** ** Move.W D1,stHeight(A0) ; save in line height ** ** Move.L (SP)+,D2 ; restore registers Rts ; ---------------------------------------------------------------------- ; AnyNullStyle ; ; Returns TRUE if a null style exists ; ENTRY: ; A3.L = TEPtr ; EXIT: ; A0.L => null scrap record (hTE^^.nullStyle^^.nullScrap^) ; USES: ; A0.L ; ---------------------------------------------------------------------- AnyNullStyle Move.L teStylesH(A3),A0 ; => style record Move.L (A0),A0 Move.L nullStyle(A0),A0 ; => null style record Move.L (A0),A0 Move.L nullScrap(A0),A0 ; => null scrap record Move.L (A0),A0 Tst.W scrpNStyles(A0) ; Assure null style exists Rts ; ---------------------------------------------------------------------- ; GetTrueStyle ; ; Returns the style at the specified offset, whether from null style or ; inferred from current style. Made subroutine because I needed ; similar result for iGetStylScrap. ; ENTRY: ; D0.W = offset into text record ; A3.L = TEPtr ; EXIT: ; A0.L => STElement representing style ; USES: ; D0.W, A0.L ; ---------------------------------------------------------------------- GetTrueStyle Cmp.W teSelStart(A3),D0 ; start = offset, andÉ Bne.S GetOneStyle Cmp.W teSelEnd(A3),D0 ; end = start? Bne.S GetOneStyle Bsr.S AnyNullStyle Bz.S GetOneStyle ; None exists. Punt. ; Yeah, this looks strange. ScrpSTElements and STElements are _almost_ ; the same, except that the first field of ScrpSTElement is a long instead ; of a word. Fake it as though A0 => STElement Lea scrpStyleTab+2(A0),A0 Rts ; ---------------------------------------------------------------------- ; GetOneStyle ; ; Returns the style at the specified offset ; ---------------------------------------------------------------------- GetOneStyle Bsr GetCurStyle ; get current style Move.W styleIndex(A0),D0 ; get style index Bsr GetStyle ; now you have it Rts ; ---------------------------------------------------------------------- ; PROCEDURE iTEGetStyle( offset: INTEGER; VAR Styl: StylePtr; ; VAR lineHite:INTEGER; VAR fontAscent:INTEGER; ; hTE: TEHandle ); ; Returns the style _OF_THE_CHARACTER_ at the specified offset ; ---------------------------------------------------------------------- iTEGetStyle Tst.W teSize(A3) ; check style flag Bpl.S @0 ; if not, sorry, can't get it Move.L (A2)+,-(SP) ; save ptr to font ascent Move.L (A2)+,-(SP) ; save ptr to line height Move.L (A2)+,-(SP) ; save style ptr Move.W (A2),D0 ; offset Bsr.S GetOneStyle ; fetch inferred style Move.L (SP)+,A1 ; point to styleRec Move.W stFont(A0),(A1)+ ; copy font Move.W stFace(A0),(A1)+ ; copy face Move.W stSize(A0),(A1)+ ; copy size Move.L A0,A2 ; save ptr ** ** Lea stColor(A0),A0 ; pt to color ** ** Move.W (A0)+,(A1)+ ; copy red ** ** Move.W (A0)+,(A1)+ ; copy green ** ** Move.W (A0),(A1) ; copy blue ** ** Move.L (SP)+,A1 ; ptr to line height Move.W stHeight(A2),(A1) ; store line height Move.L (SP)+,A1 ; ptr to font ascent Move.W stAscent(A2),(A1) ; store font ascent Bra.S @1 ; ** ** Added this code to return GrafPort info for records without style. @0 Bsr GetSize ; get ascent & hite ** ** Move.L (A2)+,A0 ; ptr to ascent ** ** Move D0,(A0) ; save in ascent ** ** Move.L (A2)+,A0 ; ptr to line height ** ** Move D1,(A0) ; save in line height ** ** Move.L (A2),A0 ; ptr to style record Move.L teGrafPort(A3),A1 Move.W txFont(A1),(A0)+ ; copy font Move.W txFace(A1),(A0)+ Move.W txSize(A1),(A0)+ ; copy size Pea 0(A0) ; ptr to forecolor ;; If forRAM THEN If (Not forROM) THEN ; <19Feb89smb> BTst #14,ROM85 ; color QD around? Bnz.S @05 ; nope _GetForeColor ; Bra.S @07 ; @05 Bsr GetForeColor ; @07 ;; ElseIf onNuMac|onMvMac THEN ; rwh ElseIf hasCQD THEN ; <19Feb89smb> _GetForeColor ; for Ikki Else Bsr GetForeColor ; for Alladin EndIf @1 MoveQ #20,D0 Bra StdExit2 ; ------------------------------------------------ ; SetStyle - sets the style pointed to by A0 ; Entry: A0 Pointer to styleStart (Preserved) ; ------------------------------------------------ SetStyle Move.L A0,-(SP) Move.W styleIndex(A0),D0 ; get index to styleRec Bsr GetStyle ; get the styleRec Move.L teGrafPort(A3),A1 ; get the Port Move.W stFont(A0),txFont(A1) ; set font Move.W stFace(A0),txFace(A1) ; set face Move.W stSize(A0),txSize(A1) ; set size ;; If forRAM THEN If (Not forROM) THEN ; <19Feb89smb> BTst #14,ROM85 ; Becks or better? Bnz.S @1 ; nope EndIf ;; If onNuMac|onMvMac|forRAM THEN ; rwh If hasCQD|(Not forROM) THEN ; <19Feb89smb> ; Save D2 because the RGBForeColor trap destroys it. ; Save the style ptr as an offset, since _RGBForeColor may shift memory. Move.L teStylesH(A3),A1 ; style handle ** ** Move.L (A1),D0 ; dereference ** ** Sub.L D0,(SP) ; save as offset ** ** Move.W D2,-(SP) ; save D2 for everybody ** ** EndIf @1 Pea stColor(A0) ; point to fgColor ** ** ;; If forRAM THEN If (Not forROM) THEN ; <19Feb89smb> BTst #14,ROM85 ; Becks or better? Bnz.S @2 ; nope _RGBForeColor ; Move.W (SP)+,D2 ; Move.L teStylesH(A3),A1 ; Move.L (A1),D0 ; Add.L D0,(SP) ; Bra.S @3 ; @2 Bsr RGBForeColor ; @3 ;; ElseIf onNuMac|onMvMac THEN ; rwh ElseIf hasCQD THEN ; <19Feb89smb> _RGBForeColor ; for Ikki ** ** Move.W (SP)+,D2 ; restore D2 ** ** Move.L teStylesH(A3),A1 ; style handle ** ** Move.L (A1),D0 ; dereference ** ** Add.L D0,(SP) ; restore as ptr ** ** Else Bsr RGBForeColor ; for Alladin ** ** EndIf Move.L (SP)+,A0 Rts ; ---------------------------------------------------------------------- ; PROCEDURE ConcatStyles ; Added 6/12/86 by MBK ; ConcatStyles checks the entire runs array for adjoining ; identical styles, and concatenates any it finds. ; ---------------------------------------------------------------------- ConcatStyles MoveM.L D2/A2,-(SP) ; save registers ** ** Move.L teStylesH(A3),A0 ; handle to style info Move.L (A0),A0 ; dereference Move.L styleTab(A0),A2 ; handle to distinct styles ** ** Move.L (A2),A2 ; dereference ** ** Move.W nRuns(A0),D0 ; get # of style starts AddQ #1,D0 ; + dummy end index Lea runs(A0),A0 ; ptr to stStarts array Move.L A0,A1 ; copy it MoveQ #0,D2 ; repetition counter ** ** Move.W styleIndex(A0),D1 ; current index ** ** ; loop thru styles removing repetitious ones @0 SubQ.W #1,D0 ; dec the count Beq.S @2 ; done, get out AddQ #1,D2 ; inc repetition counter ** ** AddQ.L #stStartSize,A1 ; point to next style Cmp.W styleIndex(A1),D1 ; are they the same? Beq.S @0 ; don't change ptrs if so SubQ #1,D2 ; dec repetition counter ** ** Beq.S @1 ; no repetitions ** ** ; ** ** if any runs are merged, the stCount for that style must also be adjusted MulU #stRecSize,D1 ; * size of record ** ** Sub.W D2,stCount(A2,D1.L) ; dec count ** ** MoveQ #0,D2 ; repetition counter ** ** @1 AddQ.L #stStartSize,A0 ; now pt to next Move.L startChar(A1),startChar(A0) ; move start and index Move.W styleIndex(A0),D1 ; current index ** ** Bra.S @0 ; shrink the handle to the style info @2 Sub.L A0,A1 ; get amount that's redundant Move.L A1,D0 Move.L teStylesH(A3),A0 ; handle to style info Move.L (A0),A1 ; dereference AsR.L #2,D0 ; divide diff by 4 Sub.W D0,nRuns(A1) ; store new # of style starts MoveM.L (SP)+,D2/A2 ; restore registers ** ** Rts ; bye ; ---------------------------------------------------------------------- ; PROCEDURE CheckMatch ; ** Added 7/19/86 by MBK ** ; CheckMatch checks to see if the input style record matches ; the style being sought by iTEReplaceStyle. If so, a True flag ; is returned. If the call was from iTESetStyle, True is auto- ; matically returned since the record does not have to match ; anything. ; Entry: ; A0: ptr to style record ; A6: ptr to style being searched for (0 if from iTESetStyle) ; D7: replace mode ; Exit: ; D0: flag = 1 if this style may be replaced ; ---------------------------------------------------------------------- CheckMatch MoveQ #1,D0 ; assume okay Cmp.L #0,A6 ; call from iTESetStyle? Beq.S @5 ; quit with true if so ; ** Added code to support doToggle mode ; Specifically, A6 = -1 is used as a flag in iTESetStyle Cmp.L #-1,A6 ; ignore toggle mode, too Beq.S @5 ; BTst #fontBit,D7 ; find font? Beq.S @1 Move.W tsFont(A6),D1 Cmp.W stFont(A0),D1 ; same as this style? Bne.S @4 ; stop comparing if not @1 BTst #faceBit,D7 ; find face? Beq.S @2 ; ** Faces are byte lengthÉ Move.B tsFace(A6),D1 ; Cmp.B stFace(A0),D1 ; same as this style? Bne.S @4 ; stop comparing if not @2 BTst #sizeBit,D7 ; find size? Beq.S @3 Move.W tsSize(A6),D1 Cmp.W stSize(A0),D1 ; same as this style? Bne.S @4 ; stop comparing if not @3 BTst #clrBit,D7 ; find color? Beq.S @5 ; must have a match if still here Move.L tsColor(A6),D1 Cmp.L stColor(A0),D1 ; same as this style? Bne.S @4 ; red and green not same ** ** Move.W tsColor+4(A6),D1 ; get blue ** ** Cmp.W stColor+4(A0),D1 ; blues the same? ** ** Beq.S @5 @4 MoveQ #0,D0 ; not a match @5 Rts ; ---------------------------------------------------------------------- ; PROCEDURE iTEReplaceStyle( ReplaceMode: INTEGER; Style1: STHandle; ; Style2: STHandle; redraw: BOOLEAN; ; hTE: TEHandle ); ; ** ** ; Replaces Style1 by Style2. If the mode is not doAll, the given ; characteristic will be replaced within all styles in which it's found. ; Supports the following modes: ; 1 doFace: replace Face only ; 2 doSize: replace Size only ; 4 doFont: replace Font only ; 8 doColor: replace Color only ; 15 doAll: replace all modes ; ---------------------------------------------------------------------- iTEReplaceStyle Tst.W teSize(A3) ; check style flag Bpl.S @1 ; if not, sorry, can't set it ; ** ** boolean value is in bit 1 of high byte Move.W (A2)+,D0 ; get redraw value ** ** And #$FF00,D0 ; check redraw value ** ** Bne.S @0 ; must redraw if set Bsr.S ReplaceGuts ; else just add styles Bra.S @1 @0 Move.L A2,-(SP) ; save ptr to parameters Bsr HideCaret Bsr HiLite ; remove selection Move.L (SP)+,A2 ; restore ptr to parameters Bsr.S ReplaceGuts ; do style munging MoveQ #0,D7 ; length is 0 Bsr RecalDraw ; redo the line stuff Bsr ShowCaret Bsr Hilite ; restore selection Bsr SelView ; ensure selection is visible @1 MoveQ #18,D0 Bra stdExit2 ; ---------------------------------------------------------------------- ReplaceGuts MoveM.L D2-D7/A2/A4/A6,-(SP) ; save registers Move.L (A2)+,A4 ; replace style ptr Move.L (A2)+,A6 ; find style ptr Move.W (A2)+,D7 ; save mode here And.W #doAll2,D7 ; only the lower 5 bits make sense Bsr StyleGuts ; do style munging NO @0 MoveM.L (SP)+,D2-D7/A2/A4/A6 ; restore registers Rts ; ---------------------------------------------------------------------- ; FUNCTION TEGetOffset( pt: Point; hTE: TEHandle): INTEGER; ; ** ** ; Returns the offset into the text corresponding to the given point. ; ---------------------------------------------------------------------- TEGetOffset Bsr StdEntry Move.L teSelPoint(A3),-(SP) ; save selPoint ; Find the point and get char index of it in D6 Move.L (A2)+,teSelPoint(A3) ; pass selPoint Bsr DoFind ; juggle dispStart/End and do find Move.W D6,(A2) ; dispStart Move.L (SP)+,teSelPoint(A3) ; restore selPoint Bra Epilog8 ; ---------------------------------------------------------------------- ; FUNCTION iGetStylHandle( hTE: TEHandle ): TEStylHandle; ; ** ** ; Returns the style handle. ; ---------------------------------------------------------------------- iGetStylHandle Clr.L (A2) ; init value to Nil Tst.W teSize(A3) ; check style flag Bpl.S @0 ; if not, sorry, can't set it Move.L teStylesH(A3),(A2) ; return the style handle @0 MoveQ #6,D0 Bra StdExit2 ; ---------------------------------------------------------------------- ; PROCEDURE iSetStylHandle (hST: TEStylHandle; hTE: TEHandle); ; ** ** ; Sets the style handle. ; ---------------------------------------------------------------------- iSetStylHandle Tst.W teSize(A3) ; check style flag Bpl.S @0 ; if not, sorry, can't set it ; Dispose of old handle before replacing. Move.L teStylesH(A3),A0 ; get old handle _DisposHandle ; get rid of it Move.L (A2),teStylesH(A3) ; set the style handle @0 MoveQ #10,D0 Bra StdExit2 ;; If onMacPP|onHcMac|forRAM THEN ; If (Not hasCQD)|(Not forROM) THEN ; <19Feb89smb> ; procedure RGBForeColor (Color : RGBColor); ; This routine takes an RGB triple and sets the current Graf- or CGrafPort ; fields so that drawing will take place with the best match of the ; requested color, using the current GDevice's color matching rules. The ; appropriate fields are set depending on portType RGBForeColor Move.L 4(SP),A1 ; point at the RGB color ; convert RGB to old-style index value ; use high bit of each component to select RGB off (0) or on (1) MoveQ #0,D1 ; clear out D1 Move (A1)+,D1 ; get red LsL.L #1,D1 ; get high bit Move (A1)+,D1 ; get green LsL.L #1,D1 ; get high bit Move (A1)+,D1 ; get blue LsL.L #1,D1 ; get high bit Swap D1 ; get RGB index Lea MapTbl,A0 ; get translate table MoveQ #0,D0 ; clear out high word LsL.W #1,D1 ; word index Move 0(A0,D1),D0 ; convert to planar value Move.L GrafGlobals(A5),A0 ; get the QuickDraw globals pointer Move.L thePort(A0),A0 ; point at the port Move.L D0,fgColor(A0) ; and set the index field Move.L (SP)+,A0 ; get the return address AddQ #4,SP ; get rid of the parameter Jmp (A0) ; and return ; TABLE TO MAP FROM 3 BIT RGB TO OLD-STYLE COLOR INDICES MapTBL DC.W $21 ; RBG = 0,0,0 -> black DC.W $199 ; RBG = 0,0,1 -> blue DC.W $155 ; RBG = 0,1,0 -> green DC.W $111 ; RBG = 0,1,1 -> cyan DC.W $CD ; RBG = 1,0,0 -> red DC.W $89 ; RBG = 1,0,1 -> magenta DC.W $45 ; RBG = 1,1,0 -> yellow DC.W $1E ; RBG = 1,1,1 -> white ; PROCEDURE GetForeColor (VAR Color: RGBColor); ; Return the RGB components of the current foreground color ; Works for old and new ports. GetForeColor Move.L 4(SP),A1 ; point at the RGB color Move.L GrafGlobals(A5),A0 ; get the QuickDraw globals pointer Move.L thePort(A0),A0 ; point at the port ; Use CMYB bits in color to derive proper RGB components Move.L fgColor(A0),D0 ; get planar color from port BTst #5,D0 ; test black bit Beq.S notBlack ; => color isn't not black Or.W #$01C0,D0 ; else set CMY = 111 for black notBlack LsR.W #1,D0 ; xxxC MYBR GBwb -> CMYx xxxx MoveQ #2,D1 ; process 3 bits nxtBit Clr.W (A1) ; assume component is 0 LsL.B #1,D0 ; check next component Blo.S cmpOK ; => if bit set, component clear Not.W (A1) ; else component = $FFFF cmpOK AddQ #2,A1 ; advance to next component DBra D1,nxtBit ; repeat for all components Move.L (SP)+,A0 ; get the return address AddQ #4,SP ; get rid of the parameter Jmp (A0) ; and return EndIf ; ---------------------------------------------------------------------- ; FUNCTION iTEGetPoint( offset: INTEGER; hTE: TEHandle): Point; ; ** <23jan87/MBK> ** ; Returns the point corresponding to the given offset into the text. ; ---------------------------------------------------------------------- iTEGetPoint Move.W (A2)+,D0 ; get the offset Move.L A2,-(SP) ; preserve parameter ptr Move.W D0,-(SP) ; preserve offset Cmp.W teLength(A3),D0 ; pin it to the length Blo.S @0 ; ok if less or same Move.W teLength(A3),D0 ; else pin to end Move.W D0,(SP) ; replace offset SubQ #1,D0 ; just for GetLine @0 Lea teLines(A3),A2 ; pt to start of array Bsr GetLine ; get ptr to line it's on ; LineRect expects to be called from RecalLines, which has its own frame. It saves ; a value off of A6, which in this case destroys the savePort value on the stdEntry frame. ; So save and restore the value that will be overwritten. Move.W saveJust(A6),-(SP) ; LineRect will write something here Bsr LineRect ; sets up selRect from destRect and justification Move.W (SP)+,saveJust(A6) ; restore port Move.W (A2),D6 ; start of line Move.W (SP)+,D7 ; offset to measure to ; If the last char is a CR, the h coord should be at the beginning of the next line after the CR ; (the v coord was correct, but the h was at the point preceding the CR on the previous line). Cmp.W teLength(A3),D7 ; is offset = text length? Bne.S @2 ; skip CR test if not Move.L teTextH(A3),A0 Move.L (A0),A0 Cmp.B #$0D,-1(A0,D7) ; if last char = CR then... Bne.S @2 ; assume left justification Move.W teSelRect+left(A3),D0 Move.W teJust(A3),D1 Bne.S @1 Move.W teSysJust,D1 Beq.S @3 Cmp.W #teForceLeft,D1 Beq.S @3 @1 ; right or center justification Move.W teDestRect+right(A3),D0 SubQ #1,D0 Tst.W D1 Bmi.S @3 ; center justification (divide width by 2) Sub.W teDestRect+left(A3),D0 AsR #1,D0 Add.W teDestRect+left(A3),D0 Bra.S @3 @2 Bsr MeasureIt ; measure with style Add.W teSelRect+left(A3),D0 ; add in justification @3 Move.L (SP)+,A2 ; restore parameter ptr Move.W teSelRect+bottom(A3),(A2)+ ; return v coord Move.W D0,(A2) ; return h coord MoveQ #8,D0 Bra StdExit2 ; ---------------------------------------------------------------------- ; FUNCTION iGetStylScrap( hTE: TEHandle): StScrpHandle; ; ** <23jan87/MBK> ** ; Gets the style information corresponding to the current selection and ; returns a handle to it, stored in the same format as the 'styl' block. ; ---------------------------------------------------------------------- iGetStylScrap Clr.L (A2) ; init value to Nil Tst.W teSize(A3) ; is it a new TERec? Bpl.S EndGet ; quit if not Move.W teSelStart(A3),D0 ; get selstart, selEnd Move.W teSelEnd(A3),D1 ; selEnd in D1 Cmp.W D0,D1 ; compare start to end ; Return true style at selection, whether inferred or stated in NullStRec Bne.S @05 ; selection - get it Move.L #scrpRecSize+2,D0 ; size of total scrap style rec Bsr MyNewHandle ; temp handle for style scrap Move.L A0,(A2) ; report back with scrap handle Move.L (A0),A1 ; save as destptr Move.W #1,(A1)+ ; one style total Clr.L (A1)+ ; scrpStartChar := 0 Move.W teSelStart(A3),D0 ; get offset Bsr GetTrueStyle ; Get style record Lea 2(A0),A0 ; skip over stCount to stHeight Move.L #scrpRecSize-4,D0 ; amount to copy _BlockMove ; from NullStRec to StScrpRec Bra.S EndGet ; we're outta here @05 ; Bhs.S @0 ; ok if end >= start Exg D0,D1 ; else swap start and end @0 MoveM.L D2-D5/A2/A5,-(SP) ; save stuff Bsr CopyGuts ; go to create 'styl' handle MoveM.L (SP)+,D2-D5/A2/A5 ; restore stuff Move.L A4,(A2) ; return 'styl' handle EndGet MoveQ #6,D0 Bra StdExit2 ; ---------------------------------------------------------------------- ; PROCEDURE iSetStylScrap(rangeStart, rangeEnd: LONGINT; newStyles: StScrpHandle; ; redraw: BOOLEAN; hTE: TEHandle); ; ** ** ; This procedure is the logical opposite of iGetStylScrap. It ; takes a handle to a style scrap record and applies it ; over the given range. iSetStylScrap does not affect the ; range of the current selection. If newStyles is NIL or ; if the edit record was not created with TEStylNew, this ; procedure has no effect. ; It is easily possible for the range to be out of sync with ; with the scrap record. In either case, as soon as a ; boundary is reached, this procedure is terminated without ; a specific error condition. ; ---------------------------------------------------------------------- iSetStylScrap Tst.W teSize(A3) ; don't do anything if not styled Bpl @xit Move.W (A2)+,D5 ; get redraw byte And.W #$FF00,D5 ; boolean is bit 1 of high byte Sne D5 ; D5 non-zero if we want to redraw Beq.S @03 ; we don't, so skip hiliting Bsr HideCaret ; remove hiliting Bsr Hilite @03 Move.L (A2)+,A1 ; fetch scrap handle ; <17May89smb> must lock the handle before using it move.l a1,-(sp) ; save for restoring flags <17May89smb> Move.l a1,a0 ; handle to style scrap <17May89smb> _HGetState move.b d0,-(sp) ; save state flags for handle <17May89smb> move.l a1,a0 ; get handle again for lock <17May89smb> _HLock ; <17May89smb> Move.L (A1),A1 ; point at scrap record proper Move.L (A2)+,D7 ; fetch end Move.L (A2),D6 ; fetch start Cmp.L D6,D7 ; sort start/end Bhs.S @05 ; end is higher or same, so okay Exg D6,D7 ; we want start in D6 @05 MoveQ #0,D0 ; make long for comparisons Move.W teLength(A3),D0 Cmp.L D0,D6 ; pin start to end of record Bls.S @07 Move.L D0,D6 @07 Cmp.L D0,D7 ; pin end to end of record Bls.S @09 Move.L D0,D7 @09 Move.L D6,D3 ; make a working copy Move.L teSelStart(A3),-(SP) ; save original start/end Move.W (A1)+,D4 ; number of styles to do Bra.S @loop @1 Cmp.L D3,D7 ; break out if start >= range end Bls.S @done Move.W D3,teSelStart(A3) ; save end as new start Tst.W D4 ; is this the last scrap entry? Bnz.S @2 ; no, calc end from table Move.L D7,D0 ; ran off end of table, so force end Bra.S @3 @2 Move.L D6,D0 ; calc end of selection Add.L scrpRecSize+scrpStartChar(A1),D0 Cmp.L D7,D0 ; pin end to range end Bls.S @4 @3 Move.L D7,D0 @4 Move.W D0,teSelEnd(A3) ; and save as new end Move.L D0,D3 ; (save end as next new start) MoveM.L D3-D7/A1/A4/A6,-(SP) ; Move.W teSelStart(A3),D0 ; fetch start of style Bsr GetOneStyle ; point at style to copy over Lea stFont(A0),A6 ; iTEReplaceStyle expects it in A6 Lea scrpFont(A1),A4 ; point at style to set Move.W #doAll,D7 ; replace everything Bsr StyleGuts ; go replace it MoveM.L (SP)+,D3-D7/A1/A4/A6 ; Add #scrpRecSize,A1 ; bump pointer to next scrap entry @loop DBra D4,@1 @done Move.L (SP)+,teSelStart(A3) ; restore previous select/end move.b (sp)+,d0 ; state flags for style scrap handle <17May89smb> move.l (sp)+,a0 ; handle to reset <17May89smb> _HSetState ; <17May89smb> Tst.B D5 ; are we redrawing? Beq.S @xit ; nope, dump out MoveQ #0,D7 ; no change in lineStarts array Bsr RecalDraw Bsr ShowCaret Bsr Hilite Bsr SelView ; ensure selection is visible @xit MoveQ #20,D0 Bra StdExit2 ; ---------------------------------------------------------------------- ; PROCEDURE iTEStylInsert( pText: Ptr; l: LONGINT; hST: StScrpHandle; ; hTE: TEHandle ); ; This inserts the passed text/length and the associated styles ; specified in the StScrpHandle just before the selection ; but doesn't touch the scrap. The selection too is "untouched" ; because it is offset by the inserted amount to point to the same ; range. Just after a TEStylNew this can be used as a replacement ; for the old TESetText because the selection and length are all zero. ; ** ** Replaced PutStylScrap by iTEStylInsert. ; iTEStylInsert is exactly the same as TEInsert if the TERec is not ; a style record, or if a NIL style handle is passed in. Otherwise, ; iTEStylInsert inserts the input style information along with the ; text. ; ** ** A2 points to the style handle when we ; 1st enter here. Before I was getting it after the text and length. ; ---------------------------------------------------------------------- iTEStylInsert ; ** ** Removed call to StdEntry because TEDispatch does it. Bsr HideCaret ; NO Bsr HiLite ; remove selection NO Move.L (A2)+,D0 ; get style handle ** ** MoveQ #0,D7 ; delta = 0(No deletion) MoveM.L (A2)+,D5-D6 ; A2 points to l param ; ** If length is 0, punt Tst.L D5 ; length? Bz.S @15 ; Nope, so leave Tst.L D0 ; check if handle is NIL ** ** Beq.S @0 ; can't insert styles if NIL Move.L D0,A2 ; save style handle in A2 ** ** Tst.W teSize(A3) ; check style flag Bpl.S @0 ; just insert text if not a style record Bsr MungeSetup ; setup for the insert Clr.L -(SP) ; fake l1 Move.L D6,-(SP) ; pointer to insert = p2 Move.L D5,-(SP) ; length to insert = l2 _Munger ; use sloppy munger AddQ.L #4,SP ; pop result Add D5,teLength(A3) ; adjust length by insert amount Move.L teTextH(A3),A0 ; get text handle _Hlock ; and relock it Move.L A2,A0 ; get style handle ** ** _HGetState ; get the style handle's tag Move.B D0,-(SP) ; and save the flags _HLock ; and lock it MoveM.L D2-D6/A2/A4,-(SP) ; save stuff Move.L A2,A4 ; style handle in A4 ** ** ; ** ** High word of D3 must be clear for PstStylGuts MoveQ #0,D3 ; clear whole register Move.W teSelStart(A3),D3 ; selection start Bsr PstStylGuts ; go do the style paste MoveM.L (SP)+,D2-D6/A2/A4 ; restore stuff Move.B (SP)+,D0 ; get the flags Move.L A2,A0 ; get style handle ** ** _HSetState ; set the style handle's tag Sub D5,D7 ; adjust delta amount for ReCalLines Bra.S @1 ; go recal @0 Bsr insGuts ; go insert the text NO @1 Bsr RecalDraw ; redo the line stuff Add D5,teSelStart(A3) ; selStart:=selstart + insert amount Add D5,teSelEnd(A3) ; selEnd:=selEnd + insert amount @15 ; Bsr ShowCaret Bsr HiLite ; restore selection NO MoveQ #18,D0 ; # of bytes on stack Bra StdExit2 ; to be removed before exit ; ---------------------------------------------------------------------- ; FUNCTION iTEGetHeight (endLine, startLine : LONGINT; hTE: TEHandle): LONGINT; ; ** Rewritten ** ; Gets the total line height of the document. ; Now properly sorts endLine and startLine so doesn't need special glue. ; ---------------------------------------------------------------------- iTEGetHeight MoveM.L (A2)+,D0-D1 ; 1st line Cmp.L D0,D1 ; Which is larger? Bhs.S @05 ; D1 is, so okay Exg.L D0,D1 ; Assure endLine in D1 @05 Tst.L D0 ; is it 0? Bnz.S @0 MoveQ #1,D0 ; minimum line # @0 SubQ.L #1,D0 ; make it 0-based Tst.L D1 ; is it 0? Bnz.S @1 MoveQ #1,D1 ; minimum line # @1 MoveQ #0,D2 ; clear D2 long Move.W teNLines(A3),D2 ; last line Bne.S @15 ; At least one line! MoveQ #1,D2 ; @15 ; Cmp.L D2,D0 ; pin to last line Bls.S @2 ; okay if less or same Move.L D2,D0 ; else set to max line @2 Cmp.L D2,D1 ; pin to last line Bls.S @3 ; okay if less or same Move.L D2,D1 ; else set to max line @3 Bsr GetLineHites ; get total height Move.L D0,(A2) ; return total height MoveQ #14,D0 ; # of bytes on stack Bra StdExit2 ; to be removed before exit ; ---------------------------------------------------------------------- ; PROCEDURE iTECustomHook(which: TEHook; VAR addr: ProcPtr; ; hTE: TEHandle); ; ** ** ; This procedure sets the various internal dispatch table ; addresses, returning the previous contents in addr. ; ---------------------------------------------------------------------- iTECustomHook Move.L (A2)+,A1 ; fetch pointer to new address Move.W (A2),D0 ; fetch selector LsL.W #2,D0 ; * 4 for long offset Move.L teDispatchH(A3),A0 ; get handle to hooks Move.L (A0),A0 ; point at table ;; Add.L D0,A0 ; add in offset <16May89smb> Add.w D0,A0 ; add in offset <16May89smb>: changed to word op. Move.L (A0),D0 ; fetch old vector Move.L (A1),(A0) ; and store away the new one Move.L D0,(A1) @xit MoveQ #12,D0 ; # of bytes on stack Bra StdExit2 ; to be removed before exit ; ---------------------------------------------------------------------- ; FUNCTION iTENumStyles(rangeStart, rangeEnd: LONGINT; ; hTE: TEHandle): LONGINT; ; ** ** ; This function returns the number of style changes across ; a given range. ; ---------------------------------------------------------------------- iTENumStyles Move.L (A2)+,D1 ; get end of range Move.L (A2)+,D0 ; get start of range Cmp.L D0,D1 ; Which is larger? Bhi.S @1 ; D1 is, so okay Beq.S @3 ; (special case when both same) Exg.L D0,D1 ; Assure endLine in D1 @1 Tst.W teSize(A3) ; if it is an old TERec Bmi.S @2 @3 MoveQ #1,D0 ; signify one style exists Bra.S @xit @2 Clr.L D2 ; pin rangeEnd to selEnd Move.W teSelEnd(A3),D2 ; Cmp.L D2,D1 ; Bls.S @4 ; Move.L D2,D1 ; rangeEnd was larger, force selEnd @4 Bsr GetCurStyle Bsr GetNumStyles @xit Move.L D0,(A2) ; store away result MoveQ #14,D0 Bra StdExit2 ; ---------------------------------------------------------------------- ; FUNCTION iTEContinuousStyle(VAR mode: INTEGER; VAR aStyle: TextStyle; ; hTE: TEHandle): BOOLEAN; ; ** ** ; This function gives you information about the continuity of ; various aspects of the current selection. The result ; returned is TRUE if the given style exists across the ; entire selection range. The style attributes to check ; are specified by the mode parameter, which takes the ; same values as in iTESetStyle. Attributes which are ; continuous across the current selection range are ; returned in aStyle, with the appropriate bits set in ; mode. If the selection range is an insertion point, ; this call duplicates iTEGetStyle, except that the returned ; style reflects the style of the _next_character_typed_. ; The attribute bits of aStyle.tsFace are individually ; checked across the selection range, and are returned set ; to 1 if that attribute is indeed continuous. ; ---------------------------------------------------------------------- iTEContinuousStyle Tst.W teSize(A3) ; is it a new TERec? Bmi.S @1 ; yes it is, continue Move.L (A2),A0 Move.L teGrafPort(A3),A1 Move.L txFont(A1),(A0)+ ; copy font/face Move.W txSize(A1),(A0)+ ; copy size Pea 0(A0) ; ptr to forecolor ;; If forRAM THEN If (Not forROM) THEN ; 19Feb89smb> BTst #14,ROM85 ; Becks or better? Bnz.S @2 ; nope _GetForeColor ; Bra.S @3 ; @2 Bsr GetForeColor ; @3 ;; ElseIf onNuMac|onMvMac THEN ; rwh ElseIf hasCQD THEN ; 19Feb89smb> _GetForeColor ; for Mac II Else Bsr GetForeColor ; for all others EndIf ST 8(A2) ; only one style, so everything's continuous Bra.S @xit @1 Bsr.S ContGuts @xit MoveQ #14,D0 Bra StdExit2 ; ---------------------------------------------------------------------- ; ContGuts ; ; Rewrote according to suggestions from DTS. Now no face information ; needs to be passed in. If ANY face information is continuous across ; the selection, doFace is returned TRUE if it was requested. ; Seems this is a more required case than the original allowed for, ; (and besides, it is a helluva lot easier case to code for) ; Does actual work of iTEContinuousStyle ; ---------------------------------------------------------------------- contArgs Record 0 contStyle Ds.L 1 contMode Ds.L 1 contResult Ds.B 1 EndR ContGuts With contArgs MoveM.L D3-D7/A4,-(SP) ; save working registers Move.W teSelStart(A3),D0 ; insertion point gets handled differently Cmp.W teSelEnd(A3),D0 Seq D5 ; show as an insertion point Bne.S @1 Bsr AnyNullStyle ; use null style if available Bnz.S @1 Tst.W D0 ; otherwise, we want style of characterÉ Bz.S @1 ; Éjust _before_ insert point SubQ.W #1,D0 ; (exception is top of record, obviously) @1 Bsr GetTrueStyle Move.L contStyle(A2),A1 ; point at receiving record Move.L stFont(A0),tsFont(A1) ; move TextStyle Move.L stSize(A0),tsSize(A1) Move.L stColor+2(A0),tsColor+2(A1) ; aStyle is primed with the style of the selection start. Find the StyleRun that ; determines the selection start and walk through the style changes, noting differences Move.B stFace(A0),D7 ; save start face for compare later Move.B D7,D6 ; make a working copy Move.L contMode(A2),A0 ; point at mode Move.W (A0),D0 ; save mode for comparison later And.W #$000F,D0 ; only low 4 bits make any sense Move.W D0,D4 ; D4 = working register Move.W D0,D3 ; D3 = original request Tst.B D5 ; insertion point? Bnz @goodxit ; yes, so no need to consult style entries Move.W teSelStart(A3),D0 ; get selection start Bsr GetCurStyle ; get the current StyleRun Move.L A0,A4 ; (we don't need the TEHandleÉ) @loop AddQ #stStartSize,A4 ; actually, we want the next one Tst.W D4 ; if we've reset all bitsÉ Bz.S @2 ; Éit's senseless to go on Move.W startChar(A4),D0 ; if negative, we're off end of table Bmi.S @2 Cmp.W teSelEnd(A3),D0 ; if past end of selection, we're done Bhs.S @2 Move.W styleIndex(A4),D0 ; get index into style table Bsr GetStyle ; go get it ; In order for this to work, neither GetCurStyle nor GetStyle can mess with A1!!!!!É BTst #fontBit,D4 ; check font? Bz.S @3 Move.W tsFont(A1),D0 Cmp.W stFont(A0),D0 ; do fonts match? Beq.S @3 ; yes, go on BClr #fontBit,D4 ; don't need to check it anymore @3 BTst #sizeBit,D4 ; check size? Bz.S @4 Move.W tsSize(A1),D0 Cmp.W stSize(A0),D0 ; do sizes match? Beq.S @4 ; yes, go on BClr #sizeBit,D4 ; don't need to check it anymore @4 BTst #clrBit,D4 ; check color? Bz.S @5 Move.L tsColor(A1),D0 Cmp.L stColor(A0),D0 ; do red/green match? Bne.S @6 ; no, reset bit Move.W tsColor+4(A1),D0 Cmp.W stColor+4(A0),D0 ; does blue match? Beq.S @5 @6 BClr #clrBit,D4 ; don't need to check it anymore ; Comparing faces is a bit tricky. If we started out plain, merge in style bits. ; Otherwise, calculate intersection of bit sets @5 BTst #faceBit,D4 ; check face? Bz.S @loop Tst.B D7 ; did we start out with plain style? Bnz.S @8 Or.B stFace(A0),D6 ; Don't fall through anymore Bra.S @loop ; @8 And.B stFace(A0),D6 Bra.S @loop ; We come here when we're done perusing the selection range. ; Now, we have to resolve the doFace bit. This is all complicated by the fact that ; ÒplainÓ isn't a style attribute, but rather a lack of other styles. @2 BTst #faceBit,D4 ; check face? Bz.S @xit ; nope, skip resolution ; All this is new, for new handling of face information Tst.B D7 ; did we start out with plain? Bnz.S @notPlain ; nope, go on Tst.B D6 ; if ended with plain, hunky dory Bz.S @goodxit ; save result and exit @badxit BClr #faceBit,D4 ; no good. reset bit Bra.S @xit ; Éand leave @notPlain Tst.B D6 ; end with any intersection? Bz.S @badxit ; nope, so nothing was continuous @goodxit Move.B D6,tsFace(A1) ; save intersection to aStyle @xit Move.L contMode(A2),A0 ; Point at mode Move.W D4,(A0) ; save intersection back to mode Cmp.W D4,D3 ; Was everything continuous? Seq D0 ; TRUE if everything was equal Neg.B D0 ; Blaise wants false=0 and true=1 Move.B D0,contResult(A2) ; Blaise wants false=0 and true=1 MoveM.L (SP)+,D3-D7/A4 ; Retrieve working registers Rts EndWith ; contArgs ; ************************************************************************************************* ; ************************************************************************************************* ; ************************************************************************************************* ; TextEdit end