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
;
 
AAPL
$524.94
Apple Inc.
+5.93
MSFT
$40.01
Microsoft Corpora
-0.39
GOOG
$536.10
Google Inc.
-20.44

MacTech Search:
Community Search:

Software Updates via MacUpdate

VMware Fusion 6.0.3 - Run Windows apps a...
VMware Fusion allows you to create a Virtual Machine on your Mac and run Windows (including Windows 8.1) and Windows software on your Mac. Run your favorite Windows applications alongside Mac... Read more
Tweetbot 1.5.1 - Popular iOS twitter cli...
Tweetbot is a full-featured OS X Twitter client with a lot of personality. Whether it's the meticulously-crafted interface, sounds and animation, or features like multiple timelines and column views... Read more
Mac DVDRipper Pro 4.1.7 - Copy, backup,...
Mac DVDRipper Pro is the DVD backup solution that lets you protect your DVDs from scratches, save your batteries by reading your movies from your hard disk, manage your collection with just a few... Read more
PDFpenPro 6.2 - Advanced PDF toolkit for...
PDFpenPro allows users to edit PDF's easily. Add text, images and signatures. Fill out PDF forms. Merge or split PDF documents. Reorder and delete pages. Even correct text and edit graphics! Create... Read more
PDFpen 6.2 - Edit and annotate PDFs with...
PDFpen allows users to easily edit PDF's. Add text, images and signatures. Fill out PDF forms. Merge or split PDF documents. Reorder and delete pages. Even correct text and edit graphics! Features... Read more
Monolingual 1.5.9 - Remove unwanted OS X...
Monolingual is a program for removing unnecesary language resources from OS X, in order to reclaim several hundred megabytes of disk space. It requires a 64-bit capable Intel-based Mac and at least... Read more
Maya 2015 - Professional 3D modeling and...
Maya is an award-winning software and powerful, integrated 3D modeling, animation, visual effects, and rendering solution. Because Maya is based on an open architecture, all your work can be scripted... Read more
Starcraft II: Wings of Liberty 1.1.1.180...
Download the patch by launching the Starcraft II game and downloading it through the Battle.net connection within the app. Starcraft II: Wings of Liberty is a strategy game played in real-time. You... Read more
Sibelius 7.5.0 - Music notation solution...
Sibelius is the world's best-selling music notation software for Mac. It is as intuitive to use as a pen, yet so powerful that it does most things in less than the blink of an eye. The demo includes... Read more
Typinator 5.9 - Speedy and reliable text...
Typinator turbo-charges your typing productivity. Type a little. Typinator does the rest. We've all faced projects that require repetitive typing tasks. With Typinator, you can store commonly used... Read more

Latest Forum Discussions

See All

Have a Special Dead Trigger 2 Easter Bas...
Have a Special Dead Trigger 2 Easter Basket Full of Goodies, Courtesy of Madfinger Games Posted by Rob Rich on April 18th, 2014 [ permalink ] Dead Trigger 2 | Read more »
Almost All of Playdek’s Library is on Sa...
Almost All of Playdek’s Library is on Sale Right Now, and You Should Check it Out Posted by Rob Rich on April 18th, 2014 [ permalink ] Playdek has released quite a few great iOS ports of board and card games over the years, and now most of them... | Read more »
Zynga Launches Brand New Farmville Exper...
Zynga Launches Brand New Farmville Experience with Farmville 2: Country Escape Posted by Tre Lawrence on April 18th, 2014 [ permalink ] | Read more »
David. Review
David. Review By Cata Modorcea on April 18th, 2014 Our Rating: :: MINIMALISTIC IN A DIFFERENT WAYUniversal App - Designed for iPhone and iPad David is a minimalistic game wrapped inside of a soothing atmosphere in which the hero... | Read more »
Eyefi Unveils New Eyefi Cloud Service Th...
Eyefi Unveils New Eyefi Cloud Service That Allows Users to Share Media Across Personal Devices Posted by Tre Lawrence on April 18th, 2014 [ permalink ] | Read more »
Tales from the Dragon Mountain: The Lair...
Tales from the Dragon Mountain: The Lair Review By Jennifer Allen on April 18th, 2014 Our Rating: :: STEADY ADVENTURINGiPad Only App - Designed for the iPad Treading a safe path, Tales from the Dragon Mountain: The Lair is a... | Read more »
Yahoo Updates Flickr App with Advanced E...
Yahoo Updates Flickr App with Advanced Editing Features and More Posted by Tre Lawrence on April 18th, 2014 [ permalink ] | Read more »
My Incredible Body - A Kid's App to...
My Incredible Body - A Kid's App to Learn about the Human Body 1.1.00 Device: iOS Universal Category: Education Price: $2.99, Version: 1.1.00 (iTunes) Description: Wouldn’t it be cool to look inside yourself and see what was going on... | Read more »
Trials Frontier Review
Trials Frontier Review By Carter Dotson on April 18th, 2014 Our Rating: :: A ROUGH LANDINGUniversal App - Designed for iPhone and iPad Trials Frontier finally brings the famed stunt racing franchise to mobile, but how much does its... | Read more »
Evernote Business Notebook by Moleskin I...
Evernote Business Notebook by Moleskin Introduced – Support Available in Evernote for iOS Posted by Tre Lawrence on April 18th, 2014 [ permalink ] | Read more »

Price Scanner via MacPrices.net

Deal Alert! 13-inch MacBook Pro on sale for $...
Best Buy has the 13″ 2.5GHz MacBook Pro on sale for $999.99 on their online store. Choose free shipping or free instant local store pickup (if available). Their price is $200 off MSRP. Price is valid... Read more
Free HopTo 2.2 Helps Enhance Your Productivit...
The HopTo app helps you do more on your iPad by providing more and easier adaccess to files and documents. Version 2.2 adds Egnyte and HopTo’s Mac OSX File Connector. If you already have the hopTo... Read more
National Distracted Driving Awareness Month:...
As the country recognizes National Distracted Driving Awareness Month, Sprint is reminding wireless consumers to focus on driving while behind the wheel, to not text or email while driving, and to... Read more
13-inch 2.4GHz Retina MacBook Pro available f...
Abt has the 13″ 2.4GHz 128GB Retina MacBook Pro available for $1229 including free shipping. Their price is $70 off MSRP. Read more
iMacs on sale for up to $160 off MSRP this we...
Best Buy has iMacs on sale for up to $160 off MSRP for a limited time. Choose free home shipping or free instant local store pickup (if available). Prices are valid for online orders only, in-store... Read more
iPad Airs on sale this weekend for up to $100...
Best Buy has WiFi iPad Airs on sale for $50 off MSRP and WiFi + Cellular iPad Airs on sale for $100 off MSRP on their online store for a limited time, with prices now starting at $449. Choose free... Read more
Apple restocks refurbished Mac minis starting...
The Apple Store has restocked Apple Certified Refurbished Mac minis for up to $150 off the cost of new models. Apple’s one-year warranty is included with each mini, and shipping is free: - 2.5GHz Mac... Read more
Hyundai Brings Apple CarPlay To The 2015 Sona...
Hyundai Motor America has announced it will bring Apple CarPlay functionality to the 2015 Sonata. CarPlay is pitched as a smarter, safer and easier way to use iPhone in the car and gives iPhone users... Read more
Updated iPads Coming Sooner Than We Had Thoug...
MacRumors, cites KGI securities analyst Ming Chi Kuo, well-respected as an Apple product prognisticator, saying that Apple will introduce an upgraded iPad Air and iPad mini in 2014/Q3, meaning the... Read more
Toshiba Unveils New High And Low End Laptop M...
Toshiba has announced new laptop models covering both the high-end and low-end of the notebook computer spectrum. Toshiba 4K Ultra HD Laptop Toshiba’s new Satellite P55t features one of the world’s... Read more

Jobs Board

*Apple* Solutions Consultant (ASC) - Apple (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
*Apple* Inc. Research Data Specialist - Appl...
…of Worldwide Market Research & Intelligence. The team is responsible for conducting Apple branded consumer market research. It is also responsible for analyzing data Read more
*Apple* Automotive Parts Department position...
Apple Automotive is one of the fastest growing dealer…and it shows. Consider making the switch to the Apple Automotive Group today! At Apple Automotive, we Read more
*Apple* Solutions Consultant (ASC) - Apple (...
**Job Summary** The ASC is an Apple employee who serves as an Apple brand ambassador and influencer in a Reseller's store. The ASC's role is to grow Apple Read more
*Apple* Retail - Manager - Holyoke - Apple I...
Job Summary Keeping an Apple Store thriving requires a diverse set of leadership skills, and as a Manager, you’re a master of them all. In the store’s fast-paced, Read more
All contents are Copyright 1984-2011 by Xplain Corporation. All rights reserved. Theme designed by Icreon.