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

Default Folder X 5.1.6 - Enhances Open a...
Default Folder X attaches a toolbar to the right side of the Open and Save dialogs in any OS X-native application. The toolbar gives you fast access to various folders and commands. You just click on... Read more
Geekbench 4.1.2 - Measure processor and...
Geekbench provides a comprehensive set of benchmarks engineered to quickly and accurately measure processor and memory performance. Designed to make benchmarks easy to run and easy to understand,... Read more
GraphicConverter 10.5 - $39.95
GraphicConverter is an all-purpose image-editing program that can import 200 different graphic-based formats, edit the image, and export it to any of 80 available file formats. The high-end editing... Read more
Dropbox 35.4.20 - Cloud backup and synch...
Dropbox is an application that creates a special Finder folder that automatically syncs online and between your computers. It allows you to both backup files and keep them up-to-date between systems... Read more
XMind 8 Update 4 - Popular mind mapping...
XMind is the most popular mind mapping tool. Millions of people use XMind to clarify thinking, manage complex information, run brainstorming and get work organized. It couldn't be easier to get... Read more
Safari Technology Preview 11.1 - The new...
Safari Technology Preview contains the most recent additions and improvements to WebKit and the latest advances in Safari web technologies. And once installed, you will receive notifications of... Read more
Chromium 61.0.3163.91 - Fast and stable...
Chromium is an open-source browser project that aims to build a safer, faster, and more stable way for all Internet users to experience the web. Version 61.0.3163.91: Release notes were unavailable... Read more
RapidWeaver 7.5.1 - Create template-base...
RapidWeaver is a next-generation Web design application to help you easily create professional-looking Web sites in minutes. No knowledge of complex code is required, RapidWeaver will take care of... Read more
Google Chrome 61.0.3163.91 - Modern and...
Google Chrome is a Web browser by Google, created to be a modern platform for Web pages and applications. It utilizes very fast loading of Web pages and has a V8 engine, which is a custom built... Read more
Quicken 4.6.3 - Complete personal financ...
Quicken makes managing your money easier than ever. Whether paying bills, upgrading from Windows, enjoying more reliable downloads, or getting expert product help, Quicken's new and improved features... Read more

Stormbound: Kingdom Wars guide - how to...
Stormbound: Kingdom Wars is an excellent new RTS turned card battler out now on iOS and Android. Lovers of strategy will get a lot of enjoyment out of Stormbound's chess-like mechanics, and it's cardbased units are perfect for anyone who loves the... | Read more »
The best AR apps and games on iOS right...
iOS 11 has officially launched, and with it comes Apple's ARKit, a helpful framework that makes it easier than ever for developers to create mobile AR experiences. To celebrate the occassion, we're featuring some of the best AR apps and games on... | Read more »
Phoenix Wright: Ace Attorney - Spirit of...
Phoenix Wright: Ace Attorney - Spirit of Justice 1.00.00 Device: iOS Universal Category: Games Price: $.99, Version: 1.00.00 (iTunes) Description: ************************************************※IMPORTANT※・Please read the “When... | Read more »
Kpressor (Utilities)
Kpressor 1.0.0 Device: iOS Universal Category: Utilities Price: $4.99, Version: 1.0.0 (iTunes) Description: The ultimate ZIP compression application for iPhone and iPad. - Full integration of iOS 11 with support for multitasking.-... | Read more »
Find out how you can save £35 and win a...
Nothing raises excitement like a good competition, and we’re thrilled to announce our latest contest. We’ll be sending one lucky reader and a friend to the Summoners War World Arena Championship at Le Comedia in Paris on October 7th. It’s the... | Read more »
Another Lost Phone: Laura's Story...
Another Lost Phone: Laura's Story 1.0 Device: iOS Universal Category: Games Price: $2.99, Version: 1.0 (iTunes) Description: Another Lost Phone is a game about exploring the social life of a young woman whose phone you have just... | Read more »
The Witness (Games)
The Witness 1.0 Device: iOS Universal Category: Games Price: $9.99, Version: 1.0 (iTunes) Description: You wake up, alone, on a strange island full of puzzles that will challenge and surprise you. You don't remember who you are, and... | Read more »
Egg, Inc. guide - how to build your gold...
Egg, Inc.'s been around for some time now, but don't you believe for one second that this quirky clicker game has gone out of style. The game keeps popping up on Reddit and other community forums thanks to the outlandish gameplay (plus, the... | Read more »
The best deals on the App Store this wee...
Good news, everyone! Your favorite day of the week has arrived at last -- it's discount roundup day! This fine Wednesday evening we're gathering up the hottest deals on the App Store. We've got action platformers, we've got puzzle games, we've got... | Read more »
Morphite (Games)
Morphite 1.08 Device: iOS Universal Category: Games Price: $7.99, Version: 1.08 (iTunes) Description: | Read more »

Price Scanner via MacPrices.net

Apple Refurbished 2017 13-inch MacBook Pros a...
Apple has Certified Refurbished 2017 13″ Touch Bar MacBook Pros in stock today and available for $200-$300 off MSRP. A standard Apple one-year warranty is included with each MacBook, and shipping is... Read more
OWC USB-C Travel Dock with 5 Ports Connectivi...
OWC have announced the new OWC USB-C Travel Dock, the latest addition to their line of connectivity solutions. The USB-C Travel Dock lets you connect its integrated USB-C cable to a Mac or PC laptop... Read more
Pelican Products, Inc. Unveils Cases For All...
Pelican Products, Inc. has announced the launch of its full line of cases including Voyager, Adventurer, Protector, Ambassador, Interceptor (for the Apple iPhone 8 and 8 Plus backwards compatible... Read more
$100 off new 2017 13-inch MacBook Airs
B&H Photo has 2017 13″ MacBook Airs on sale today for $100 off MSRP including free shipping. B&H charges NY & NJ sales tax only: – 13″ 1.8GHz/128GB MacBook Air (MQD32LL/A): $899, $100 off... Read more
Apple restocks Certified Refurbished 13-inch...
Apple has Certified Refurbished 2015 13″ MacBook Airs available starting at $719 and 2016 models available starting at $809. An Apple one-year warranty is included with each MacBook, and shipping is... Read more
Is iPhone X Really The Future Of The Smartpho...
Should iPhone X even be called a telephone? It does of course support telephony and texting, but its main feature set is oriented to other things. It is also debatable whether it makes any rational... Read more
OtterBox Announces Full Case Lineup for iPhon...
Apple revolutionized the smartphone industry 10 years ago with the original iPhone, and OtterBox has set the standard of protection from the very beginning by protecting every generation of iPhone.... Read more
LifeProof Introduces What’s NEXT Cases for iP...
LifeProof built its reputation on sleek, ultra-protective iPhone cases. From 360-degree coverage to the first screenless waterproof case, the protection pioneer has always pushed the limits.... Read more
Apple Refurbished 2016 15-inch MacBook Pros a...
Apple has Certified Refurbished 2016 15″ Touch Bar MacBook Pros available starting at $1949. An Apple one-year warranty is included with each model, and shipping is free: – 15″ 2.7GHz Touch Bar Space... Read more
Wednesday deal: 15-inch MacBook Pros for up t...
B&H Photo has 2017 15″ MacBook Pros on sale for $150-$200 off MSRP. Shipping is free, and B&H charges sales tax in NY & NJ only: – 15″ 2.8GHz MacBook Pro Space Gray: $2199, $200 off MSRP... Read more

Jobs Board

Development Operations and Site Reliability E...
Development Operations and Site Reliability Engineer, Apple Payment Gateway Job Number: 57572631 Santa Clara Valley, California, United States Posted: Jul. 27, 2017 Read more
Full time *Apple* Hardware Tech needed - ma...
…high level of attention to detail Ethics, integrity and trust Be a geek & Previous Apple experience a must. Previous Apple Retail or other Apple Specialist Read more
Development Operations and Site Reliability E...
Development Operations and Site Reliability Engineer, Apple Payment Gateway Job Number: 57572631 Santa Clara Valley, California, United States Posted: Jul. 27, 2017 Read more
*Apple* Store - Technical Specialist - Apple...
…customers purchase our products, you're the one who helps them get more out of their new Apple technology. Your day in the Apple Store is filled with a range of Read more
*Apple* Retail - Multiple Positions - Apple,...
Job Description: Sales Specialist - Retail Customer Service and Sales Transform Apple Store visitors into loyal Apple customers. When customers enter the store, Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.