TED - A Tiny Text Editor

\ 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


Top    Home    Forth

em.gif (457 bytes)


web analytics

Page updated: 2017-01-25