TweetFollow Us on Twitter

Text with Style
Volume Number:4
Issue Number:5
Column Tag:Forth Forum

Formatted Text with Style

By Jörg Langowski, MacTutor Editorial Board

TextEdit with Style(s)

TextEdit has always been one of the major conveniences of the Macintosh. Life (as far as programming is concerned) is so much simpler with a standard editing package that takes care of line break, word wrap, text insertion, justification etc. for you, instead of having to write it yourself.

One major reason why TextEdit was inadequate for e.g. word processing had always been that the text style was fixed for one text edit record, i.e. for one piece of edited text. Changing fonts, boldfacing, or changing the size of only one word or one phrase in the text was not possible.

The new implementation of TextEdit that is described in IM Vol.V finally introduces this possibility. TextEdit now recognizes two types of TE records: the old one, having the same text style all over the text, and a new format where style information is associated and displayed with the text. Although contained in IM V, the new TextEdit traps are available (System 4.2 and later) on the Mac Plus as well as on the SE and MacII.

A second inconvenience has been resolved: When working on new type TE records, TECopy and TEPaste now uses the desk scrap (i.e. the general clipboard) for cutting/pasting directly. It is no more necessary to convert between the internal TE scrap and the desk scrap on activate/deactivate events. For old TE records, TECopy and TEPaste still only use the internal scrap (for compatibility).

The new text edit is not yet used very widely, but it is worth it. Therefore I thought it might be a good idea to show its function on a practical example in Mach2 Forth. It is based on the ‘skeleton editor’ on the Mach2 demo disk, but contains a lot of enhancements, such as horizontal scrolling and scroll thumbs that work, and of course the text style support.

The new TE record

How does the system distinguish between the new and the old type TE record?

Mostly, the structure of the new record is the same as the old one, with a couple of exceptions: The txSize field of a new TE record contains -1 (word, offset $50 from beginning of record). In that case, the fields txFont and txFace (offset $4A and $4C) are combined to hold the handle of what is called a style record, a structure that contains the style information associated with the text. Of course, the information previously contained in the txFont, txFace and txSize fields - font, text face, and font size - is not meaningful anymore, since it may change over the length of the text.

Furthermore, the fields lineHeight and fontAscent (offset $18 and $1A) may now also contain -1, in which case the line height and ascent will be calculated individually for each line; if they contain positive numbers, the TErecord has fixed line height and ascent as before.

The style record

This structure contains the style information that belongs to the TErecord. Its layout is give in IM V-261 and I’ll repeat it here (Pascal style):

TYPE
TEStyleHandle = ^TEStylePtr;
TEStylePtr = ^TEStyleRec;
TEStyleRec = RECORD
 nRuns: INTEGER;
 nStyles: INTEGER;
 styleTab:STHandle;
 lhTab: LHHandle;
 teRefCon:LONGINT;
 nullStyle: nullSTHandle;
 runs:  ARRAY [0..0] OF StyleRun
 END;

StyleRun = RECORD
 startChar: INTEGER;
 styleIndex:INTEGER
 END;

The text is characterized by a succession of style runs, characters of the same style in the TE record. The system knows where they start (startChar) and the index styleIndex of the corresponding style in a style table. Each style record contains information about how many style runs and how many different styles there are in the text (nruns, nStyles), and handles to the style and line height tables (styleTab, lhTab). teRefCon can be used freely by the application, and nullStyle contains a handle to the style table that is used when the selection is empty.

The style table contains an entry for each different style encountered in the text:

TYPE
STHandle = ^STPtr;
StPtr = ^TEStyleTable;
TEStyleTable = ARRAY [0..0] OF STElement;

STElement = RECORD
 stCount: INTEGER;
 stHeight:INTEGER;
 stAscent:INTEGER;
 stFont:INTEGER;
 stFace:Style;
 stSize:INTEGER;
 stColor: RGBColor;
 END;

stCount indicates how often this style occurs in the text; the remaining fields indicate the text style.

Since the line height now may differ from line to line, there is another table, the line-height table, which contains an entry for each line in the lineStarts array of the TE record.

TYPE
LHHandle = ^LHPtr;
LHPtr = ^LHTable;
LHTable = ARRAY [0..0] OF LHElement;

LHElement = RECORD
 lhHeight:INTEGER;
 lhAscent:INTEGER;
 END;

For each line, lhHeight and lhAscent contain the maximum height and ascent present in that line.

Fortunately, you don’t have to remember any of this information when using the new Text Edit. For straightforward text editing, all we need to know is that the TECopy, TECut, TEKey and TEDelete routines work as before, but Copy and Cut store a second type of scrap, ‘styl’, in the desk scrap. When you do a TEPaste, this information is not used and only the text is pasted into the edit record using the style that was present at the insertion point. For pasting ‘with style’, a new routine exists, TEStylPaste. This is one of 10 routines that are called through the new trap TEDispatch. This trap will look at a selector (integer) on top of stack and call the new text edit routines accordingly.

Mach2 implements the new TE routines using their names and compiling the glue code for the dispatch routine automatically. One routine, TEStylInsert, has been left out accidentally, and is redefined in the example listing. Two more new traps exist: TEStylNew and TEGetOffset. Mach2 spells the former ‘TEStyleNew’, so watch out for that.

For simple use as in the example, the most important new routines that you have to remember are TEStylNew, TEStylPaste, TEGetOffset, TEGetStyle, and TESetStyle.

TEStylNew is just like TENew, except that it creates a new type TE record. TEStylPaste will use the ‘styl’ information in the scrap, if present, for the text to be pasted.

TEGetOffset works with both old and new type TE records and finds the character offset in the text corresponding to a certain point in the window (local coordinates). This is necessary for updating the font, size and style menu information after a change of the insertion point by a mouse click.

TEGetStyle and TESetStyleare used to get and set style information at the selection of insertion point in the text. They work with another data structure, the TextStyle:

TYPE TextStyle = RECORD
 tsFont:INTEGER;
 tsFace:Style;
 tsSize:INTEGER;
 tsColor: RGBColor
 END;

This record contains the text style information that is passed to/from the TE record.

All these routines are, of course, documented in IM Vol. V. Examples on how to call them can be found in the program listing. Feel free to experiment with the other new TE routines.

The example will create an editor window with vertical and horizontal scroll bars and read the first 1024 characters from a text file. You can use this text for playing around with different style settings (using the menus I provided). Doing this, you will notice that the Style menu doesn’t seem to have any effect on the text. Fonts and font sizes may be changed, but underlining, boldfacing etc. seems to be impossible. However, when you set those text attributes for a certain selection and then click at different positions in the text, you will see that the Style menu changes appropriately, checkmarks appear and disappear in the right positions. Therefore I believe that the style changes are well recorded in the style record/style table; only the text display doesn’t seem to function. Is this a bug still present in the new TextEdit, or have I overlooked something obvious (question to you, the readers)?

You see that editing multi-style text is not too difficult with the new TE routines, since they take care of almost everything. For saving and loading files, you would have to provide code that reads/writes the style record information together with the text, this also seems pretty straightforward. Printing a new style text edit record is a completely different ballgame, since no printing support exists (yet?) that is quite as extensive as the new TextEdit. You would have to extract the style information for each line, using the style record, style and line height tables, and write the printing code from scratch. More difficult, but probably a good ‘exercise for the reader’.

Bugs in the SCSI driver?

Some remarks have been received that the SCSI code published in V4#1/2 was buggy, and someone seems to have crashed his hard disk using it. I feel sorry if application of that example (which was however marked ‘experimental’) should have caused trouble to anyone. The only excuse I have is that it was said that the code had been shown to work only for two types of disk, the Q280 and the ST225N, the only ones available to me for testing at that time.

Let me point out here that we can only do our best to give examples of Macintosh programming, but never guarantee that everything works 100% and bug-free. Feel free to publish your comments, preferably with corrections, in MacTutor, that’s what we’re here for. But for any example that is printed here or published on the source code disks, be prepared that something might go wrong, and especially DON’T run it from the disk that has your only copy of that 40-page report on it that is due in two days! Play it safe and use floppies that have nothing valuable on them. I learned my lesson when I crashed my own hard disk while writing the Forth example for the February article.

I wish you good luck with this month’s example. The source code disk contains two compiled versions, one for Mac Plus/SE/II, and one for Mac II only (contains 68020 code). As far as I have checked them, they don’t crash and work under MultiFinder. But you never know...

Till next month, happy threading.

Listing 1: Text Edit Example with Style
\ New Text Edit example
\ J. Langowski for Mac Tutor March 1988
\ derived from
\ Editor Shell Example Program on Mach 2 demo disk

\ found two ‘features’ of the new text edit while 
\ experimenting:
\ a. when the insertion point is at a boundary between
\    two different styles, the text typed will be TEKeyed 
\    according to the style BEFORE the insertion point,
\    while TEGetStyle will return style information from 
\    AFTER the insertion point.
\ b. Although the text face seems to be set inside the style \    record 
and properly associated with the text 
\    (TEGetStyle returns the correct information after the 
\    text face has been changed), the text is always drawn 
\    plain text style. The font and size changes work OK.
\

only forth definitions
also assembler also mac

\ ***** constants

300 CONSTANT APPLEID 
310 CONSTANT FILEID
320 CONSTANT EDITID
330 CONSTANT SIZEID
340 CONSTANT FontID
350 CONSTANT StyleID

20  CONSTANT InUpArrow   
21  CONSTANT InDownArrow 
22  CONSTANT InPageUp 
23  CONSTANT InPageDown
129 CONSTANT InThumb

$44525652 Constant “drvr
$464F4E54 Constant “font

%000001000000000 CONSTANT ShiftMask 
    
$10 CONSTANTportRect \ Grafport rectangle
$6E CONSTANTwVisible \ visible flag [byte]

\ text edit equates
0  CONSTANT teDestRect  
8  CONSTANT teViewRect  
$C  CONSTANTselRect
$18 CONSTANT   teLineHite 
$1A CONSTANTteFontAscent
$1C CONSTANTteSelPoint  
$20 CONSTANT   teSelStart 
$22 CONSTANT   teSelEnd
$38 CONSTANT   teCarOn  
$39 CONSTANT   teCarAct
$3C CONSTANTteLength
$3E CONSTANTteTextH
$48 CONSTANTteCROnly
$4A CONSTANTteFont
$4C CONSTANTteFace
$4A CONSTANTteStylHandle  
 \ handle to style record for new
 \ text edit. Never accessed directly
$4E CONSTANTteMode \ text mode [word] 
$50 CONSTANT   teSize\ font size [word] 
 \ teFont, teFace, teMode, teSize are only 
 \ meaningful for old style TE records.
 \ for a new style record, teSize contains -1.
 \ in that case, teFont and teFace together contain
 \ the handle to the style record.
$5E CONSTANTteNLines
$60 CONSTANTteLines

$AB0 CONSTANT  TEScrpLength
$AB4 CONSTANT  TEScrpHandle

\ Event Record Equates
$0 CONSTANT What ( event code [word] )
$2 CONSTANT Message( event message [long] )  
$6 CONSTANT When ( ticks since start-up  [long] )
$A CONSTANT Where( mouse loc. pt. global [long] )
$E CONSTANT Modifiers( modifier flags  [word] )

$0A CONSTANT LF  ( ascii ‘linefeed’ )
$20 CONSTANT SP  ( ascii ‘space’ )

create applestring 01 C, $14 C, \ Apple symbol

\ ***** variables

VARIABLE TEHandle( handle for text edit record )
VARIABLE TERect   4 VALLOT
 ( Text Edit view rectangle )
VARIABLE SIZE    ( item# of current textsize )
VARIABLE DESKNAME 252 VALLOT\ holds name of desk accessory
VARIABLE FONTNAME 252 VALLOT\ holds font name selected
VARIABLE ITEMNAME 60 VALLOT 
 \ receives menu item name
VARIABLE MyStyle 8 VALLOT 
 \ text style record for our private use
 \ fields of MyStyle:
 0 CONSTANT tsFont
 2 CONSTANT tsFace
 4 CONSTANT tsSize
 6 CONSTANT RGBColor
VARIABLE currentFont \ menu ID of font in use
VARIABLE #fonts      \ # of currently installed fonts
VARIABLE currentSize  \ menu ID of size in use

76  USER AbortHook
152 USER ContentHook
160 USER GrowHook
164 USER CloseBoxHook
168 USER UpdateHook
172 USER ActivateHook
202 USER CAction \ control action routine vector

\ ***** glue routines for new text edit
\
\ TEStylNew ( destRect viewRect -- TEHandle )
\ is misspelled ‘TEStyleNew’ in the Mach2 trap definitions,
\ but implemented. So are TEGetOffset and most of the 
\ other new text edit routines that are called through 
\ TEDispatch.
\ One exception is TEStylInsert, which we are defining 
\ here:

CODE TEStylInsert ( text length hST hTE -- )
 EXG D4,A7
 MOVE.L $C(A6),-(A7) \ pointer to text
 MOVE.L $8(A6),-(A7) \ length of text
 MOVE.L $4(A6),-(A7) \ style record handle
 MOVE.L (A6),-(A7) \ TE record handle
 ADDA.W #$10,A6
 MOVE.W #$7,-(A7)
 _TEDispatch
 EXG  D4,A7
 RTS
END-CODE

\ ***** windows, menus, controls, tasks etc. *****

NEW.WINDOW Editor
“ Editor” Editor TITLE
42 4 330 507 Editor BOUNDS
DOCUMENT INVISIBLE CLOSEBOX GROWBOX 
 Editor ITEMS

200 1000 TERMINAL EditTask

NEW.MBAR EditBar 

NEW.MENU AppleMenu
APPLESTRING AppleMenu TITLE
0 APPLEID AppleMenu BOUNDS
“ About Editor ...;(-” AppleMenu ITEMS

NEW.MENU FileMenu
“ File” FileMenu TITLE
0 FileID FileMenu BOUNDS
“ New/N;Open.../O;Close;Save;Save as...;Revert to Original;(Print”
 FileMenu ITEMS

NEW.MENU EditMenu
“ Edit” EditMenu TITLE
0 EDITID EditMenu BOUNDS
“ (Undo/Z;(-;Cut/K;Copy/C;Paste/V;Clear” 
 EditMenu ITEMS

NEW.MENU FontMenu
“ Font” FontMenu TITLE
0 FontID FontMenu BOUNDS
“  (Fonts<I;(-” FontMenu ITEMS

NEW.MENU SizeMenu
“ Size” SizeMenu TITLE
0 SizeID SizeMenu BOUNDS
“  9 Point; 10 Point; 12 Point; 14 Point; 18 Point; 20 Point; 24 Point” 

 SizeMenu ITEMS

CREATE SizeIDTable
0 , 0 , 0 c, \ no menu IDs for sizes 0 thru 8
1 c, 2 c, 0 c, 3 c, \  9,10,--,12
0 c, 4 c, 0 c, 0 c, \ --,14,--,--
0 c, 5 c, 0 c, 6 c, \ --,18,--,20
0 c, 0 c, 0 c, 7 c, \ --,--,--,24

CREATE SizeTable
0 c, 9 c, 10 c, 12 c, 14 c, 18 c, 20 c, 24 c,


NEW.MENU StyleMenu
“ Style” StyleMenu TITLE
0 StyleID StyleMenu BOUNDS
“  Plain/P; Bold/B<B; Italic/I<I; Underline/U<U; Outline<O; Shadow<S; 
Condense; Extend” 
 StyleMenu ITEMS

NEW.CONTROL Scroll
VSCROLLBAR VISIBLE 100 0 Scroll ITEMS
VARIABLE lastVs
400 CONSTANT maxVs

NEW.CONTROL hScroll
HSCROLLBAR VISIBLE 100 0 hScroll ITEMS
VARIABLE lastHs
100 CONSTANT maxHs

: CHECK  ( menuhandle item# flag -- )( checking a menu item )
 CALL CheckItem ;
 
: =string { aStr bStr | -- flag }
 aStr count 65536 * bStr count rot + swap
 call CmpString 0=
;

CODE @TEHandle
 MOVE.L TEHandle,-(A6)    RTS
END-CODE

: Shift?   (   -  f )   \ checks the event record to see if the
 \ shift key was pressed. 
 EVENT-RECORD Modifiers + W@ ShiftMask AND
 IF -1 ELSE 0 THEN  
;
 

: adjustFontMenu
\ adjust font menu and currentFont variable
 myStyle w@ ( font ID ) fontName call getFname
 #fonts @ 0 DO
 fontMenu @ i itemName call GetItem
 itemName fontName =string 
 IF  FontMenu @ currentFont @ 0 check 
 \ uncheck previous font selection 
     FontMenu @ i -1 check
     i currentFont !
     leave
 THEN
 LOOP
;

: adjustStyleMenu { | face - }
 myStyle tsFace + w@ -> face
 8 0 DO 
   1 i scale face and ( get style bit )
   if -1 else 0 then
   styleMenu @ i 2+ rot check 
 LOOP 
;
 
: adjustSizeMenu
 SizeMenu @ currentSize @ 0 check 
 myStyle tsSize + w@ ( size )
 SizeIDTable + c@ ( sizeID )
 dup currentSize !
 SizeMenu @ swap -1 check 
;

: getCurrentStyle { | LHite FAsc -- }
 ( updates variable currentFont )
 ( size and Face kept in myStyle )
 ( LHite and FAsc are currently not used )

 @TEHandle @ teselStart + w@ 
 \ get start of selection (or insertion point)
 ( offset ) myStyle ^ LHite ^ FAsc @TEHandle
 call TEGetStyle
 
 adjustFontMenu
 adjustStyleMenu
 adjustSizeMenu
;

: AdjustTERect
 \ adjust terect size for the presence of scrollbars
 portRect Editor + 4 + W@ ( get bottom coord )
 16 -   ( subtract 16 for height of scrollbar )
 teViewRect @TEHandle @ + 4 + W! \ store new coord back in text edit 
record 
   
 portRect Editor + 6 + W@ ( get right coord )
 16 -   ( subtract 16 for width of scrollbar )
 teViewRect @TEHandle @ + 6 + W!
;
 
: Visible? (   -  f  ) \ checks visible flag in window record
 Editor wVisible + C@  
;

\ ***** event handlers *****

: ACTIVATE-HANDLER
 RUN-ACTIVATE
 EVENT-RECORD Modifiers + W@( get modifiers word )
 1 AND IF 
 @TEHandle CALL TEActivate
 getCurrentStyle
 ELSE   
 @TEHandle CALL TEDeactivate
 THEN 
;

 
: UPDATE-HANDLER
 Editor CALL SetPort
 AdjustTERect
 Editor CALL BeginUpdate
    Editor CALL DrawControls
    Editor CALL DrawGrowIcon
    Editor portRect + @TEHandle CALL TEUpdate
 Editor CALL EndUpdate
;

: CONTENT-HANDLER { | theMouse -- }
 RUN-CONTENT
 Editor CALL SetPort

 ^ theMouse CALL GetMouse
 theMouse @TEHandle @ TEViewRect + 
 call PtInRect
 IF
 theMouse Shift? @TEHandle CALL TEClick
 getCurrentStyle 
 THEN
;

: CLOSEBOX-HANDLER
 Editor \ windowpointer 
 EVENT-RECORD Where + @ call TrackGoAway     IF Editor CALL HideWindow 
THEN
;


\ **** main editor example code *****

: POP-UP
 Editor CALL ShowWindow
 Editor CALL SelectWindow
 EditBar @ CALL SetMenuBar
 CALL DrawMenuBar 
;
 
: ShutDown
 Editor CALL HideWindow
 PAUSE  ( PAUSE so that the i/o task can 
 have a turn and handle the
 deactivate event generated by
  the closing of the window )
 MACH.MBAR( MACH menubar back on screen )
 @TEHandle CALL TEDispose   
;

: SetScrollLimits
 Scroll @ 0 CALL SetMinCtl
 Scroll @ maxVs CALL SetMaxCtl   
 Scroll @ 0 CALL SetCtlValue 
 0 lastVs !  
 hScroll @ 0 CALL SetMinCtl
 hScroll @ maxHs CALL SetMaxCtl   
 hScroll @ 0 CALL SetCtlValue 
 0 lastHs !  
;


: EditFile   {   | char exitflag --   }
 BEGIN
     Visible?
     IF
      ?TERMINAL IF
 KEY -> char( get the character )
      char 14 = IF
        0 -> exitflag ( if cmd ‘.’ exit )
 ELSE
 char @TEHandle CALL TEKey
 ( else insert )
 1 -> exitflag   ( char )
 THEN
 ELSE
        1 -> exitflag
 ( if no key pressed, keep looping )
      THEN
 
     ELSE
      0 -> exitflag
 ( if window’s been closed, exit )
     THEN
 exitflag ( check exit condition )
 WHILE
     @TEHandle CALL TEIdle
 REPEAT
;
 
 
: Open 
 Pop-Up
 Editor CALL SetPort
    
 TERect TERect CALL TEStyleNew TEHandle ! 
 \ get new style TE record 
 -1 teCROnly @TEHANDLE @ + W! ( no word wrap )
 -1 teCarAct @TEHandle @ + C! ( activate caret )
 -1 @TEHandle call TEAutoView
 \ enable auto scroll

 ( get the first 1K of text )
 0 VIRTUAL 1024 0 @TEHandle TEStylinsert
 0 0 @TEHandle CALL TESetSelect
 15 ( doAll ) myStyle -1 ( redraw) @TEHandle
 call TESetStyle 
 adjustFontMenu
 adjustStyleMenu
 adjustSizeMenu
    
 AdjustTERect  ( initialize the text )
 PortRect Editor + @TEHandle CALL TEUpdate 
 @TEHandle CALL TEDeactivate
 @TEHandle CALL TEActivate

 SetScrollLimits
 Editor CALL DrawControls Editor CALL DrawGrowIcon

 [‘] UPDATE-HANDLER UpdateHook !
 [‘] CONTENT-HANDLER ContentHook !
 [‘] ACTIVATE-HANDLER ActivateHook !    
 [‘] CLOSEBOX-HANDLER CloseBoxHook !  
;
    
 
\ ***** menu handlers *****

: HandleDeskAcc ( item# -  )
 APPLEMENU @ SWAP DESKNAME CALL GETITEM
 DESKNAME CALL OPENDESKACC
 DROP 
;

: DO-APPLE ( item# -  )
 dup 1 = IF
     ( AboutEdit ) ( About Editor ... )
     drop
 ELSE  HandleDeskAcc
 THEN 
;

: NewFile ;
: OpenFile ;
: CloseFile ;
: SaveFile ;
: SaveAs ;
: Revert ;

: DO-FILE ( item# -  )
 CASE
 1 OF NewFile    ENDOF
 2 OF   OpenFile ENDOF
 3 OF   CloseFileENDOF
 4 OF SaveFile   ENDOF
 5 OF SaveAsENDOF
 6 OF RevertENDOF
 ENDCASE 
;

: DO-EDIT ( item# - )
 CASE
 1 OF   ( TEUndo )   ENDOF
 3 OF   @TEHandle CALL TECut  ENDOF
 4 OF @TEHandle CALL TECopy ENDOF
 5 OF @TEHandle CALL TEStylPaste   ENDOF
 6 OF @TEHandle CALL TEDelete ENDOF
 ENDCASE  
;

: DO-Font { item# | fontID - }
 FontMenu @ item# Fontname call getitem
 Fontname ^ fontID call getFNum
 ^ fontID w@ myStyle w! 
 \ put into tsFont field of style record
 1 ( doFont) myStyle -1 ( redraw) @TEHandle
 call TESetStyle
 FontMenu @ currentFont @ 0 check 
 FontMenu @ item# -1 check
 item# currentFont !
;

: Do-Style { item# | facefield -- }
 myStyle tsFace + -> facefield
 item# CASE
 1 OF ( plain text ) 
   0 facefield w!
 ENDOF  

 facefield w@ 
 1 item# 2- scale xor 
 facefield w! \ flip bit
 ENDCASE

 2 ( doFace) myStyle -1 ( redraw) @TEHandle
 call TESetStyle
 adjustStyleMenu
;

 
: Do-Size  ( item# - ) 
 SizeTable + c@
 myStyle tsSize + w!
 4 ( doSize) myStyle -1 ( redraw) @TEHandle
 call TESetStyle
 adjustSizeMenu
;
 
: MBAR-HANDLER  ( item# menuID -  )
 CASE
 APPLEID OF DO-APPLE    ENDOF
 FILEID OF DO-FILE   ENDOF
 EDITID OF DO-EDIT ENDOF
 FontID OF DO-Font ENDOF
 SIZEID OF DO-Size ENDOF
 STYLEIDOF DO-StyleENDOF
 ENDCASE  
 0 CALL HILITEMENU  
;


\ ***** control action routines *****

\ A control action routine specifies what action should take 
\ place WHILE a control is being held down.

: ScrollText  { dv  dh  --   }
 dh dv @TEHandle CALL TEScroll   
;
 
: DO-Scroll { part-code  | ctlvalue  -  }
   part-code
   CASE
      inuparrow OF  Scroll @ CALL GetCtlValue  -> ctlvalue
        ctlvalue 0= NOT 
     IF
        Scroll @ ctlvalue 1- call SetCtlValue
 5 0  ScrollText
     THEN
 ENDOF
 
      indownarrow OF  Scroll @ call GetCtlValue  -> ctlvalue
 ctlvalue maxVs = NOT
     IF
 Scroll @ ctlvalue 1+ call SetCtlValue
 -5 0 ScrollText
     THEN
 ENDOF
 
      inpageup  OF  Scroll @ call GetCtlValue  -> ctlvalue
 ctlvalue 0= NOT 
     IF
 Scroll @ ctlvalue 5 - call SetCtlValue
 25 0  ScrollText
     THEN
 ENDOF
 
      inpagedown OF  Scroll @ call GetCtlValue   -> ctlvalue
 ctlvalue maxVs = NOT
      IF
        Scroll @ ctlvalue 5 + call SetCtlValue
 -25 0  ScrollText   
      THEN
 ENDOF
   ENDCASE  
   Scroll @ call GetCtlValue lastVs ! 
;

: DO-hScroll { part-code  | ctlvalue  -  }
   part-code
   CASE
      inuparrow OF hScroll @ call GetCtlValue  -> ctlvalue
        ctlvalue 0= NOT 
     IF
        hScroll @ ctlvalue 1- call SetCtlValue
 0 5 ScrollText
     THEN
 ENDOF
 
      indownarrow OF hScroll @ call GetCtlValue  -> ctlvalue
 ctlvalue maxHs = NOT
     IF
 hScroll @ ctlvalue 1+ call SetCtlValue
 0 -5 ScrollText
     THEN
 ENDOF
 
      inpageup  OF hScroll @ call GetCtlValue  -> ctlvalue
 ctlvalue 0= NOT 
     IF
 hScroll @ ctlvalue 5 - call SetCtlValue
 0 25 ScrollText
     THEN
 ENDOF
 
      inpagedown OF hScroll @ call GetCtlValue  -> ctlvalue
 ctlvalue maxHs = NOT
      IF
        hScroll @ ctlvalue 5 + call SetCtlValue
 0 -25 ScrollText   
      THEN
 ENDOF
   ENDCASE    
   hScroll @ call GetCtlValue lastHs ! 
;

: ControlAction  ( part-code  control-handle -  )
 CASE
  Scroll @ OF DO-Scroll   ENDOF
 hScroll @ OF DO-hScroll ENDOF
 swap drop
 ENDCASE
;


\ ***** scrollbar thumb control handler *****

: DO-vThumb { | ctlV }
 inThumb = IF
 scroll @ call getCtlValue -> ctlV
 lastVs @ ctlV - 5 * 0 scrollText
 ctlV lastVs !
 THEN
;

: DO-hThumb { | ctlV }
 inThumb = IF
 hscroll @ call getCtlValue -> ctlV
 0 lastHs @ ctlV - 5 * scrollText
 ctlV lastHs !
 THEN 
;
  
: ControlHandler  ( part-code  control-handle -  )
 CASE
  Scroll @ OF DO-vThumb   ENDOF
 hScroll @ OF DO-hThumb  ENDOF
 swap drop
 ENDCASE
;


\ ***** initialization *****

: INIT-MBAR
 EditBar ADD
 EditBar APPLEMENU ADD    
 APPLEMENU @ “drvr call addresmenu
 EditBar FileMenu  ADD
 EditBar EditMenu  ADD
 EditBar FontMenu  ADD  
 Fontmenu @ “font call addresmenu
 Fontmenu @ call countMItems #fonts !
 EditBar SizeMenu  ADD 
 EditBar StyleMenu ADD
;
 
: INIT-TASK
 Editor ADD ( make the Editor window )
 Editor Scroll ADD ( add vertical scroll bar )
 Editor hScroll ADD( add horizontal scroll bar )
 Editor EditTask BUILD 
;
 
: START-TASK
 ACTIVATE 
 [‘] ControlAction CAction !
 [‘] ControlHandler Control-Vector !
 [‘] MBAR-HANDLER MENU-VECTOR !  
 BEGIN
     STANDARD-GETFILE
     IF
 Open
 EditFile
 ShutDown
     THEN
     [‘] RUN-UPDATE UpdateHook !
     [‘] RUN-CONTENT ContentHook !
     [‘] RUN-ACTIVATE ActivateHook !
     [‘] RUN-CLOSEBOX CloseBoxHook !
     SLEEP STATUS W! ( put Editor task to sleep )
     PAUSE( exit this task )
 AGAIN 
;

: INIT-EDIT
 INIT-TASK
 INIT-MBAR
 EditBar EditTask MBAR>TASK 4 myStyle w!     \ default font, Monaco
 0 myStyle 2+ w! \ default face, plain text
 9 myStyle 4 + w! \ default size, 9 point
 0 myStyle 6 + ! \ RGBcolor = ...
 0 myStyle 10 + w! \ ...black 
 4   TERect     W! ( define the text edit rectangle )
 4   TERect 2+  W!
 288 TERect 4 + W!
 503 TERect 6 + W!
 EditTask START-TASK  
;


: EDIT  ( wakes up Editor task )
 EDITTASK @ 
 IFWAKE STATUS TASK-> EditTask W!
 ELSE INIT-EDIT
 THEN
;
 

Community Search:
MacTech Search:

Software Updates via MacUpdate

Latest Forum Discussions

See All

Whitethorn Games combines two completely...
If you have ever gone fishing then you know that it is a lesson in patience, sitting around waiting for a bite that may never come. Well, that's because you have been doing it wrong, since as Whitehorn Games now demonstrates in new release Skate... | Read more »
Call of Duty Warzone is a Waiting Simula...
It's always fun when a splashy multiplayer game comes to mobile because they are few and far between, so I was excited to see the notification about Call of Duty: Warzone Mobile (finally) launching last week and wanted to try it out. As someone who... | Read more »
Albion Online introduces some massive ne...
Sandbox Interactive has announced an upcoming update to its flagship MMORPG Albion Online, containing massive updates to its existing guild Vs guild systems. Someone clearly rewatched the Helms Deep battle in Lord of the Rings and spent the next... | Read more »
Chucklefish announces launch date of the...
Chucklefish, the indie London-based team we probably all know from developing Terraria or their stint publishing Stardew Valley, has revealed the mobile release date for roguelike deck-builder Wildfrost. Developed by Gaziter and Deadpan Games, the... | Read more »
Netmarble opens pre-registration for act...
It has been close to three years since Netmarble announced they would be adapting the smash series Solo Leveling into a video game, and at last, they have announced the opening of pre-orders for Solo Leveling: Arise. [Read more] | Read more »
PUBG Mobile celebrates sixth anniversary...
For the past six years, PUBG Mobile has been one of the most popular shooters you can play in the palm of your hand, and Krafton is celebrating this milestone and many years of ups by teaming up with hit music man JVKE to create a special song for... | Read more »
ASTRA: Knights of Veda refuse to pump th...
In perhaps the most recent example of being incredibly eager, ASTRA: Knights of Veda has dropped its second collaboration with South Korean boyband Seventeen, named so as it consists of exactly thirteen members and a video collaboration with Lee... | Read more »
Collect all your cats and caterpillars a...
If you are growing tired of trying to build a town with your phone by using it as a tiny, ineffectual shover then fear no longer, as Independent Arts Software has announced the upcoming release of Construction Simulator 4, from the critically... | Read more »
Backbone complete its lineup of 2nd Gene...
With all the ports of big AAA games that have been coming to mobile, it is becoming more convenient than ever to own a good controller, and to help with this Backbone has announced the completion of their 2nd generation product lineup with their... | Read more »
Zenless Zone Zero opens entries for its...
miHoYo, aka HoYoverse, has become such a big name in mobile gaming that it's hard to believe that arguably their flagship title, Genshin Impact, is only three and a half years old. Now, they continue the road to the next title in their world, with... | Read more »

Price Scanner via MacPrices.net

B&H has Apple’s 13-inch M2 MacBook Airs o...
B&H Photo has 13″ MacBook Airs with M2 CPUs and 256GB of storage in stock and on sale for up to $150 off Apple’s new MSRP, starting at only $849. Free 1-2 day delivery is available to most US... Read more
M2 Mac minis on sale for $100-$200 off MSRP,...
B&H Photo has Apple’s M2-powered Mac minis back in stock and on sale today for $100-$200 off MSRP. Free 1-2 day shipping is available for most US addresses: – Mac mini M2/256GB SSD: $499, save $... Read more
Mac Studios with M2 Max and M2 Ultra CPUs on...
B&H Photo has standard-configuration Mac Studios with Apple’s M2 Max & Ultra CPUs in stock today and on Easter sale for $200 off MSRP. Their prices are the lowest available for these models... Read more
Deal Alert! B&H Photo has Apple’s 14-inch...
B&H Photo has new Gray and Black 14″ M3, M3 Pro, and M3 Max MacBook Pros on sale for $200-$300 off MSRP, starting at only $1399. B&H offers free 1-2 day delivery to most US addresses: – 14″ 8... Read more
Department Of Justice Sets Sights On Apple In...
NEWS – The ball has finally dropped on the big Apple. The ball (metaphorically speaking) — an antitrust lawsuit filed in the U.S. on March 21 by the Department of Justice (DOJ) — came down following... Read more
New 13-inch M3 MacBook Air on sale for $999,...
Amazon has Apple’s new 13″ M3 MacBook Air on sale for $100 off MSRP for the first time, now just $999 shipped. Shipping is free: – 13″ MacBook Air (8GB RAM/256GB SSD/Space Gray): $999 $100 off MSRP... Read more
Amazon has Apple’s 9th-generation WiFi iPads...
Amazon has Apple’s 9th generation 10.2″ WiFi iPads on sale for $80-$100 off MSRP, starting only $249. Their prices are the lowest available for new iPads anywhere: – 10″ 64GB WiFi iPad (Space Gray or... Read more
Discounted 14-inch M3 MacBook Pros with 16GB...
Apple retailer Expercom has 14″ MacBook Pros with M3 CPUs and 16GB of standard memory discounted by up to $120 off Apple’s MSRP: – 14″ M3 MacBook Pro (16GB RAM/256GB SSD): $1691.06 $108 off MSRP – 14... Read more
Clearance 15-inch M2 MacBook Airs on sale for...
B&H Photo has Apple’s 15″ MacBook Airs with M2 CPUs (8GB RAM/256GB SSD) in stock today and on clearance sale for $999 in all four colors. Free 1-2 delivery is available to most US addresses.... Read more
Clearance 13-inch M1 MacBook Airs drop to onl...
B&H has Apple’s base 13″ M1 MacBook Air (Space Gray, Silver, & Gold) in stock and on clearance sale today for $300 off MSRP, only $699. Free 1-2 day shipping is available to most addresses in... Read more

Jobs Board

Medical Assistant - Surgical Oncology- *Apple...
Medical Assistant - Surgical Oncology- Apple Hill Location: WellSpan Medical Group, York, PA Schedule: Full Time Sign-On Bonus Eligible Remote/Hybrid Regular Apply Read more
Omnichannel Associate - *Apple* Blossom Mal...
Omnichannel Associate - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Read more
Cashier - *Apple* Blossom Mall - JCPenney (...
Cashier - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Blossom Mall Read more
Operations Associate - *Apple* Blossom Mall...
Operations Associate - Apple Blossom Mall Location:Winchester, VA, United States (https://jobs.jcp.com/jobs/location/191170/winchester-va-united-states) - Apple Read more
Business Analyst | *Apple* Pay - Banco Popu...
Business Analyst | Apple PayApply now " Apply now + Apply Now + Start applying with LinkedIn Start + Please wait Date:Mar 19, 2024 Location: San Juan-Cupey, PR Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.