452 lines
11 KiB
Forth
452 lines
11 KiB
Forth
\ TED.F
|
|
\
|
|
\ TED - A Tiny Text Editor for DX-Forth
|
|
\
|
|
\ Based on the HT-68K editor by J.Bartel
|
|
\
|
|
\ The HELP screen is only compiled for the
|
|
\ turnkey version
|
|
\
|
|
\ ^E Up cursor ^R Prev page
|
|
\ ^X Down cursor ^C Next page
|
|
\ ^D Right cursor ^G Del next char
|
|
\ ^S Left cursor ^H Del prev char
|
|
\ ^L Restore line ^M New line
|
|
\ ^T Erase to EOL ^Y Delete line
|
|
\ ^U Exit editor ^Z Function
|
|
\ ^ZC Clear text ^ZH Help
|
|
\ ^ZR Read file ^ZW Write file
|
|
\
|
|
\ Revision
|
|
\ 2016-09-25 es updated for DX-Forth
|
|
\ 2015-06-03 es specify a filename
|
|
\ 2015-12-09 es join lines with ^G or DEL
|
|
\ 2017-01-25 es replace EXIT THEN with END
|
|
|
|
forth definitions decimal
|
|
|
|
0 \ true for turnkey
|
|
|
|
( *) dup [if] application [then]
|
|
|
|
cr .( loading TED Text Editor )
|
|
|
|
\ Running DX-Forth for CP/M or DOS ?
|
|
: CPM? ( -- f ) $111 @ $4683 = ;
|
|
|
|
[undefined] ZCOUNT [if]
|
|
: ZCOUNT ( a -- a u ) dup -1 0 scan drop over - ;
|
|
[then]
|
|
|
|
[undefined] ZPLACE [if]
|
|
: ZPLACE ( a -- a u ) 2dup + >r swap cmove 0 r> c! ;
|
|
[then]
|
|
|
|
[undefined] PACK [if]
|
|
: PACK ( a u a2 -- a2 ) dup >r place r> ;
|
|
[then]
|
|
|
|
[undefined] TOKEN [if]
|
|
: TOKEN ( "name" -- c-addr u ) bl word count ;
|
|
[then]
|
|
|
|
\ Video terminal specific
|
|
|
|
79 value XMAX \ #columns - 1
|
|
24 value YMAX \ #rows - 1
|
|
|
|
\ INSERT-LINE ( -- ) insert blank line at cursor;
|
|
\ remaining rows scroll down
|
|
\ DELETE-LINE ( -- ) delete line at cursor;
|
|
\ remaining rows scroll up
|
|
\ CLEAR-LINE ( -- ) blank from cursor to end of line
|
|
|
|
\ pointer operations
|
|
: 1+! ( a -- ) 1 swap +! ;
|
|
: 1-! ( a -- ) -1 swap +! ;
|
|
: C@+ ( a -- c ) dup @ c@ swap 1+! ;
|
|
: C!+ ( c a -- ) tuck @ c! 1+! ;
|
|
: -C@ ( a -- c ) dup 1-! @ c@ ;
|
|
: -C! ( c a -- ) dup 1-! @ c! ;
|
|
|
|
\ max line length
|
|
132 constant COLS
|
|
|
|
0 value YBOT \ edit bottom row
|
|
0 value BUF \ edit buffer addr
|
|
0 value BUFE \ edit buffer end + 1
|
|
0 value TBUF \ text buffer addr
|
|
0 value LINES \ line count
|
|
0 value MEM \ top of memory
|
|
0 value FNAM \ filename buffer addr
|
|
0 value FID \ file handle
|
|
|
|
variable COL \ current column#
|
|
variable LIN \ current line#
|
|
variable LADR \ current line addr
|
|
variable LTOP \ absolute line# at top of screen
|
|
variable LPOS \ current line# relative to top of screen
|
|
variable BPOS \ address of char in edit buffer
|
|
variable NXT \ next free addr in text (contains 0)
|
|
variable UPD \ edit buffer change flag
|
|
variable XF \ quit flag
|
|
|
|
: UKEY ( -- c ) key upcase ;
|
|
: LMAX ( -- n ) lines 1- 0 max ;
|
|
: GOXY ( x y -- ) 1+ at-xy ;
|
|
: CXY ( -- ) col @ XMAX min lpos @ goxy ;
|
|
: MSG ( -- ) 0 0 at-xy clear-line ;
|
|
: CHGD ( -- ) upd on ;
|
|
|
|
: CONT ( -- ) xf off
|
|
." Press a key to continue " key drop ;
|
|
|
|
: .FIL ( -- ) fnam count 20 min type ;
|
|
|
|
: .POS ( -- )
|
|
13 0 at-xy lin @ 1+ u.
|
|
22 0 at-xy col @ 1+ u. cxy ;
|
|
|
|
: .HD ( -- ) msg 10 0 at-xy
|
|
[ dup ] [if]
|
|
." Ln Cl ^ZH Help File "
|
|
[else]
|
|
." Ln Cl File "
|
|
[then]
|
|
.fil .pos ;
|
|
|
|
: .ERR ( a u -- ) msg .fil space space type cont .hd ;
|
|
|
|
: SURE? ( a u -- f )
|
|
msg type ." Are you sure? " ukey [char] Y = ;
|
|
|
|
: LINE ( -- a u ) ladr @ zcount ;
|
|
|
|
: .LINE ( -- ) line XMAX 1+ min type ;
|
|
|
|
: .RT ( -- ) \ display string right of cursor
|
|
bpos @ bufe over - XMAX 1+ bpos @ buf - - min type ;
|
|
|
|
: ROOM? ( -- f ) bufe 1- c@ bl = ;
|
|
|
|
: LINE@ ( -- lin adr ) lin @ ladr @ ;
|
|
: LINE! ( lin adr -- ) ladr ! lin ! ;
|
|
|
|
: GOTOP ( -- ) tbuf ladr ! lin off ;
|
|
|
|
: CURTOP ( -- )
|
|
gotop ltop off col off lpos off ;
|
|
|
|
\ clear text, filename, reset cursor
|
|
: -TXT ( -- ) tbuf dup 1- 3 erase ( nulls )
|
|
1+ nxt ! 1 to lines 0 fnam c! curtop ;
|
|
|
|
: SETUP ( -- )
|
|
[ cpm? ] [if]
|
|
$168 c@ 1- to XMAX
|
|
$169 c@ 1- dup to YMAX 2- to YBOT
|
|
[else]
|
|
get-window ( x1 y1 x2 y2 )
|
|
rot - dup to YMAX 2- to YBOT
|
|
swap - to XMAX
|
|
[then]
|
|
application here unused + to mem pad 80 +
|
|
dup to fnam 80 + dup to buf COLS + dup to bufe
|
|
2+ dup to tbuf mem u> abort" no space" -txt ;
|
|
|
|
: INSC ( c -- ) \ insert char in buf
|
|
bpos @ dup 1+ bufe over - 1+ cmove>
|
|
bpos c!+ ;
|
|
|
|
: LU ( -- ) \ go up one line in text
|
|
lin 1-!
|
|
ladr dup 1-! begin dup -c@ 0= until 1+! ;
|
|
|
|
: LD ( -- ) \ go down one line in text
|
|
lin 1+! ladr begin dup c@+ 0= until drop ;
|
|
|
|
: SETLIN ( n -- ) \ setup for line n
|
|
tbuf over 0 ?do zcount + 1+ loop
|
|
ladr ! lin ! ;
|
|
|
|
: LINES+ ( -- ) lines 1+ to lines ;
|
|
: LINES- ( -- ) lines 1- to lines ;
|
|
|
|
: ?MEM ( -- )
|
|
nxt @ mem u< not if s" no space" .err then ;
|
|
|
|
: REPL ( a u -- ) \ replace line in text
|
|
>r line r@ over - >r
|
|
over + dup r@ + nxt @ 1+ dup >r
|
|
2 pick - move 2r> + dup off nxt !
|
|
r> cmove ?mem ;
|
|
|
|
: BSTR ( -- a u ) \ string in buffer
|
|
buf bufe over - -trailing ;
|
|
|
|
: LEAV ( -- ) \ leave the line we are on
|
|
upd @ if bstr repl then upd off ;
|
|
|
|
: ENTER ( -- ) \ start changes on this line
|
|
line buf dup COLS blank swap cmove
|
|
buf col @ + bpos ! upd off ;
|
|
|
|
: .ALL ( -- ) \ update screen
|
|
leav enter
|
|
page line@
|
|
ltop @ dup setlin
|
|
lmax swap - YBOT min
|
|
1+ 0 ?do 0 i goxy .line ld loop
|
|
line! .hd cxy ;
|
|
|
|
: SLN ( ltop lin -- )
|
|
>r 0 max lmax min dup r> max lmax min
|
|
dup setlin over - lpos ! ltop ! .all ;
|
|
|
|
: PU ( -- ) \ ^R page up
|
|
lin @ if
|
|
leav ltop @ YBOT - lin @ YBOT - sln
|
|
then ;
|
|
|
|
: PD ( -- ) \ ^C page dn
|
|
lin @ lines < if
|
|
leav ltop @ YBOT + lin @ YBOT + sln
|
|
then ;
|
|
|
|
: SU ( -- ) \ scroll up, new line at bottom
|
|
0 0 goxy delete-line 0 YBOT dup lpos ! goxy ;
|
|
|
|
: SD ( -- ) \ scroll down, new line at top
|
|
0 0 goxy insert-line lpos off ;
|
|
|
|
-? : UP ( -- ) \ ^E line up
|
|
lin @ if
|
|
leav lu
|
|
lin @ ltop @ 1- = if
|
|
sd .line ltop 1-!
|
|
else
|
|
lpos 1-!
|
|
then
|
|
enter .pos
|
|
then ;
|
|
|
|
: DN ( -- ) \ ^X line dn
|
|
lin @ lines < if
|
|
leav ld
|
|
lin @ ltop @ YBOT 1+ + = if
|
|
su .line ltop 1+!
|
|
else
|
|
lpos 1+!
|
|
then
|
|
enter .pos
|
|
then ;
|
|
|
|
: RT ( -- ) \ ^D right
|
|
col @ XMAX < if
|
|
col 1+! bpos 1+! .pos
|
|
then ;
|
|
|
|
: LFT ( -- ) \ ^S left
|
|
col @ if
|
|
bpos 1-! col 1-! .pos
|
|
then ;
|
|
|
|
: TAB ( -- ) \ ^I tab
|
|
4 col @ over mod - 0 do rt loop ;
|
|
|
|
: NLN ( -- ) \ ^M new line
|
|
room? if
|
|
13 insc chgd leav
|
|
ladr begin dup c@+ 13 = until 0 over -c! 1+!
|
|
lines+ lin 1+!
|
|
clear-line col off enter
|
|
lpos @ YBOT = if
|
|
su ltop 1+!
|
|
else
|
|
lpos 1+! insert-line cxy
|
|
then
|
|
.all
|
|
then ;
|
|
|
|
: DEL ( -- ) \ ^G del next
|
|
bpos @ bstr + < if ( del char)
|
|
bpos @ dup 1+ swap bufe bl over c! over - 1+ cmove
|
|
.rt cxy chgd
|
|
else ( join line)
|
|
chgd leav line COLS over - >r
|
|
+ dup 1+ zcount r> min rot zplace .all
|
|
then ;
|
|
|
|
: BS ( -- ) \ ^H del prev
|
|
col @ if lft del then ;
|
|
|
|
: DLN ( -- ) \ ^Y del line
|
|
lin @ lines < if
|
|
ladr @
|
|
ld enter 13 ladr -c!
|
|
ladr !
|
|
chgd leav enter
|
|
lines- lin 1-!
|
|
delete-line
|
|
ltop @ YBOT + lines < if
|
|
line@
|
|
ltop @ YBOT + setlin 0 YBOT goxy .line
|
|
line!
|
|
then
|
|
.pos
|
|
then ;
|
|
|
|
: RST ( -- ) \ ^L restore line
|
|
0 lpos @ goxy clear-line .line cxy
|
|
enter ;
|
|
|
|
: DEOL ( -- ) \ ^T delete to EOL
|
|
bufe bpos @ - blank
|
|
clear-line cxy chgd ;
|
|
|
|
: CHAROK ( c -- )
|
|
dup bl 126 between room? and if
|
|
dup insc dup emit col 1+! .rt
|
|
.pos chgd
|
|
then drop ;
|
|
|
|
: CLR ( -- ) \ ^ZC
|
|
s" *** Clear text: " sure? if leav -txt then
|
|
.all ;
|
|
|
|
: GETN ( -- a u ) msg ." Filename: "
|
|
pad dup XMAX 10 - accept ;
|
|
|
|
: STNAM ( a u -- a u )
|
|
2dup fnam pack count upper 0 to fid ;
|
|
|
|
: CLOSF ( -- ) fid ?dup if close-file drop then ;
|
|
|
|
: CLN ( a u -- ) \ ctl chars to spaces
|
|
over + swap ?do i c@ bl max i c! loop ;
|
|
|
|
: (RD) ( a u -- )
|
|
stnam r/w open-file throw to fid
|
|
0 to lines tbuf dup off dup 1+ nxt !
|
|
( a) begin
|
|
dup COLS 2dup + mem u> throw
|
|
fid read-line throw ( a u' f )
|
|
while
|
|
2dup cln + 0 over c! ( null)
|
|
1+ dup nxt ! lines+
|
|
repeat 2drop nxt @ off ;
|
|
|
|
: RD ( a u -- )
|
|
s" F" +ext ( append .F extension if none )
|
|
leav ['] (rd) catch if
|
|
2drop s" load/size error" .err -txt
|
|
then closf curtop .all ;
|
|
|
|
: (WR) ( a u -- )
|
|
stnam r/w create-file throw to fid
|
|
tbuf begin ( a)
|
|
dup nxt @ u<
|
|
while
|
|
zcount 2dup fid write-line drop + 1+
|
|
repeat drop ;
|
|
|
|
: WR ( a u -- )
|
|
leav ['] (wr) catch if
|
|
2drop s" save error" .err
|
|
then closf .all ;
|
|
|
|
: ZRD ( -- ) \ ^ZR read file into text buffer
|
|
getn rd .hd ;
|
|
|
|
: ZWR ( -- ) \ ^ZW write text to file
|
|
getn wr .hd ;
|
|
|
|
: SAV ( -- )
|
|
fnam count dup 0= if 2drop getn then wr ;
|
|
|
|
dup [if]
|
|
: HLP ( -- ) \ ^ZH help
|
|
leav page 14 spaces ." Help Menu"
|
|
cr ." ^E Up cursor ^R Prev page"
|
|
cr ." ^X Down cursor ^C Next page"
|
|
cr ." ^D Right cursor ^G Del next char"
|
|
cr ." ^S Left cursor ^H Del prev char"
|
|
cr ." ^L Restore line ^M New line"
|
|
cr ." ^T Erase to EOL ^Y Delete line"
|
|
cr ." ^U Exit editor ^Z Function"
|
|
cr ." ^ZC Clear text ^ZH Help"
|
|
cr ." ^ZR Read file ^ZW Write file"
|
|
cr cr cont .all ;
|
|
[then]
|
|
|
|
: FN ( -- ) \ ^Z function
|
|
[ dup ] [if]
|
|
msg ." *** (R)ead, (W)rite, (C)lear, (H)elp ? " ukey
|
|
[char] H of hlp end \ ^ZH help
|
|
[else]
|
|
msg ." *** (R)ead, (W)rite, (C)lear ? " ukey
|
|
[then]
|
|
[char] C of clr end \ ^ZC clear
|
|
[char] R of zrd end \ ^ZR read
|
|
[char] W of zwr end \ ^ZW write
|
|
drop .hd ;
|
|
|
|
: DONE ( -- ) \ ^U Quit editor
|
|
msg ." *** Exit: (S)ave, (Q)uit ? " ukey
|
|
[char] Q of xf on end
|
|
[char] S of sav xf on end
|
|
drop .hd ;
|
|
|
|
: KMAP ( c1 -- c2 ) \ map in arrow keys etc
|
|
[ cpm? ] [if]
|
|
$14F c@ of 5 end $150 c@ of 24 end
|
|
$151 c@ of 4 end $152 c@ of 19 end
|
|
127 of 7 end
|
|
[else]
|
|
200 of 5 end 208 of 24 end
|
|
205 of 4 end 203 of 19 end
|
|
211 of 7 end
|
|
210 of 22 end 201 of 18 end
|
|
209 of 3 end 199 of 17 end
|
|
[then] ;
|
|
|
|
: CMD ( -- ) key kmap
|
|
3 of pd ( ^C) end 4 of rt ( ^D) end
|
|
5 of up ( ^E) end 7 of del ( ^G) end
|
|
8 of bs ( ^H) end 9 of tab ( ^I) end
|
|
12 of rst ( ^L) end 13 of nln ( ^M) end
|
|
18 of pu ( ^R) end 19 of lft ( ^S) end
|
|
20 of deol ( ^T) end 21 of done ( ^U) end
|
|
24 of dn ( ^X) end 25 of dln ( ^Y) end
|
|
26 of fn ( ^Z) end
|
|
charok ;
|
|
|
|
\ Load & edit textfile addr len. If len=0 don't load.
|
|
: (TED) ( line addr len -- )
|
|
setup page .hd
|
|
?dup if
|
|
rd ( line ) 1- dup 7 - swap sln
|
|
else 2drop then
|
|
enter xf off begin cmd xf @ until
|
|
0 YMAX at-xy cr cr ;
|
|
|
|
( *) [if]
|
|
|
|
\ Turnkey version
|
|
-? : TED ( -- ) 1 cmdtail (ted) ; turnkey ted ted bye
|
|
|
|
[else]
|
|
|
|
\ Resident version
|
|
-? : TED ( "filename[.F]" -- ) token dup if 1 -rot
|
|
else 2drop loadline @ lastfile then (ted) ;
|
|
|
|
\ aka TED EDIT
|
|
|
|
behead cpm? cmd
|
|
|
|
[then]
|
|
|
|
forth definitions application
|
|
|