home *** CD-ROM | disk | FTP | other *** search
- \ WFL.SEQ Window file selection. by Tom Zimmer
-
- ONLY FORTH ALSO HIDDEN DEFINITIONS ALSO
-
- create rootdir '.' c, 0 c, \ root is . & null
- handle dirhndl
-
- defer wflbutton ' noop is wflbutton
-
- headerless
-
- create itemstk 10 allot
- itemstk 10 erase
-
- variable item#
- item# off
-
- variable flitem
- flitem off
-
- : setfl ( n1 --- )
- flitem ! ;
-
- \ Item stack used to hold Directory offsets in window while stepping
- \ up and down the directory tree.
-
- : 0istk ( --- ) \ Clear the item stack
- itemstk 10 erase
- item# off ;
-
- : >istk ( n1 --- ) \ put an item on the item stack
- item# @ itemstk + c!
- item# @ 1+ 9 min item# ! ;
-
- : istk> ( --- n1 ) \ get an item from the item stack.
- item# @ 1- 0MAX dup item# !
- itemstk + dup c@ swap off ;
-
- headers
-
- create dirspec$ ," *.*" b/hcb allot
- -1 dirspec$ >hndle !
- dirspec$ count + off
-
- create defdirspec$ ," *.*" 20 allot
-
- 14 constant b/fnam \ bytes per filename
- 300 constant maxdir
-
- b/fnam maxdir * paragraph 4 + \ room for directory entries plus a couple
- constant #dirsegs
- 4 constant forgx
- 3 constant forgy \ top of file window display
- 18 constant dlen \ directory window length
-
- 0 value dirseg
- 0 value dirrow
- 0 value #fls \ number of files present
- 0 value curfl \ current file number
- 0 value foff
-
- headerless
-
- 16 constant dirattrib \ directory file attribute
- variable aletter
-
- headers
-
- : dirinit ( --- ) \ try to initialize the directory
- defers initstuff \ yet initialized.
- off> dirseg
- #dirsegs alloc 8 =
- if 2drop
- ." \n\bNo room for directory buffer!, "
- ." Can't pop up Dir window. Sorry!\n\:10"
- else nip =: dirseg
- then rows forgy - 4 - =: dlen ;
-
- ' dirinit is initstuff
-
- headerless
-
- code foff+ ( n1 --- n2 )
- pop ax
- add ax, ' foff >body
- 1push
- end-code
-
- headers
-
- code >fadr ( name# -- seg name_offset )
- pop ax
- mov bx, # b/fnam
- mul bx \ b/fnam *
- add ax, # 1 \ 1+
- mov dx, ' dirseg >body \ dirseg
- 2push
- end-code
-
- : dir>pad ( seg off --- a1 n1 )
- 2dup c@l >r ?cs: pad r@ 1+ cmovel pad 1+ r> ;
-
- : .nam ( n1 --- )
- >fadr dup>r dir>pad dup>r type
- 12 r> - spaces
- dirseg r> 1- c@l dirattrib and
- if #out @ 1- #line @ at
- ." ∞"
- then ;
-
- : name>buf ( --- ) \ move name from dta to buffer
- #fls >fadr nip >r
- pad 30 + 12 dup 0
- do over i + c@ 0=
- if drop i leave
- then
- loop dup dirseg r@ c!l
- >r ?cs: swap dirseg r> r@ 1+ swap cmovel
- pad 21 + c@ dirseg r> 1- c!l ;
-
- : $getdir ( a1 --- )
- dirhndl $>handle \ get directory spec
- dirhndl pathset drop
- off> curfl
- off> foff
- off> #fls
- pad SET-DTA
- dirhndl >nam findfirst
- begin 255 and 0= #fls maxdir > 0= and
- while name>buf incr> #fls
- findnext
- repeat ;
-
- : getdir ( --- )
- dirspec$ $getdir ;
-
- headerless
-
- : (at.") ( x1 y1 | text --- x1 y1+1 )
- 2dup at
- 2r@ 2dup c@l >r 1+ r@ typeL r> 1+ xeven r> + >r
- 1+ ;
-
- : at." ( x1 y1 | text --- x1 y1+1 )
- compile (at.") x," ; immediate
-
- : showkeys ( --- ) \ show some help
- forgx forgy 17 -1 d+
- at." ┌────────────────┐"
- at." │ Hom │ │ PgUp │"
- at." │ ────┼───┼───── │"
- at." │ End │ │ PgDn │"
- at." ├────────────────┴─────────────────────┐"
- at." │ A-Z = Next file starting with Letter │"
- at." │ ─┘ = Select file or directory │"
- at." │ Esc = Cancel file selection │"
- at." │ Del = Delete selected file │"
- at." │ \ = Type in a new Directory Spec. │"
- at." └──────────────────────────────────────┘" 2drop ;
-
- : pathbox ( --- )
- forgx forgy 17 10 d+ 2dup 52 2 d+ box&fill
- ." Path = " ;
-
- : showpath ( --- )
- pathbox forgx forgy 26 11 d+ at
- dirspec$ dup pathset 0=
- if count type
- else ." Can't read path" drop
- then ;
-
- headers
-
- : showdir ( --- ) \ display directory window
- savecursor
- forgx forgy 1- 2dup 15 dlen 1+ d+ box
- forgx 15 + forgy at ." \r"
- forgx 15 + forgy dlen + at ." \r"
- dlen 0
- do forgx forgy 1 i d+ at i foff+ #fls >=
- if i 0= if ." ...No Files..."
- else ." " then
- else curfl i foff+ =
- if i =: dirrow
- >attrib1 ." ■" i foff+ .nam ." ■"
- >norm
- else ." " i foff+ .nam ." "
- then
- then
- loop restcursor ;
-
- : nfl ( --- ) \ next file
- curfl #fls 1- 0MAX = if exit then
- curfl 1+ #fls 1- min 0MAX dup !> curfl
- dup #fls < swap dlen 1- - foff = and
- if foff 1+ #fls 15 - 0MAX min !> foff
- then ;
-
- : pfl ( --- ) \ previous file
- curfl 1- 0MAX dup !> curfl
- foff =
- if foff 1- 0MAX !> foff
- then ;
-
- headerless
-
- : ?lmatch ( --- f1 )
- curfl >fadr 1+ c@l aletter c@ = ;
-
- : gotofl ( --- )
- flitem @ 0MAX
- curfl over >
- if curfl swap do pfl loop
- else curfl ?do nfl loop
- then ;
-
- : 0fl ( --- ) \ first file
- 0 !> curfl
- 0 !> foff ;
-
- variable foffsave
- variable curflsave
-
- : find_letter ( c1 --- c1 ) \ search for a file starting with c1
- 95 and dup aletter c! curfl >r
- curfl #fls 1- 0MAX =
- if 0fl
- else nfl
- then
- begin ?lmatch curfl #fls 1- 0MAX = or 0=
- while nfl
- repeat ?lmatch 0=
- if 0fl r@ 0
- ?do ?lmatch ?leave nfl
- loop ?lmatch
- if foffsave @
- curflsave @ curfl - 1+ dlen >=
- if curfl
- then =: foff
- then
- else foff foffsave ! curfl curflsave !
- then ?lmatch 0= if beep then
- r>drop ;
-
- : efl ( --- ) \ goto end of file list
- begin nfl curfl #fls 1- 0MAX = until ;
-
- headers
- \ from counted string=a1
- : >pathend" ( a1 --- a2 n1 ) \ return a2 and count=n1 of filename
- count
- begin 2dup '\' scan ?dup
- while 2swap 2drop 1 -1 d+
- repeat drop ;
-
- \ a1 = counted string address
- : >pathend ( a1 --- a2 ) \ a2 = the address of the char beyond last \
- >pathend" drop ;
-
- : >pathend-1 ( a1 --- a2 )
- dup c@ >r \ save old length
- dup>r >pathend \ find last backslash
- r@ - 2- 0MAX r@ c! \ adjust to new count
- r@ >pathend \ find previous backslash
- r> r> swap c! ; \ restore old length
-
- headerless
-
- : delfl ( --- ) \ delete the current file
- curfl >fadr dup>r 1- c@l dirattrib and
- forgx forgy 19 11 d+ 2dup at 50 spaces at
- if ." Can't delete directory !\b\:10"
- else ." Delete \`" dirseg r@ dir>pad type ." \` <- Y/N [N] "
- cursor-on key cursor-off bl or 'y' =
- if dirspec$ >pathend dirspec$ 1+ - dup dirhndl c!
- dirspec$ 1+ dirhndl 1+ rot cmove
- dirseg r@ dir>pad >r dirhndl count + r@ cmove
- r> dirhndl c+!
- dirhndl count + off
- dirhndl hdelete 5 =
- if ." Access denied !\b\:10"
- then
- then curfl foff
- getdir
- !> foff !> curfl
- then r>drop showpath ;
-
- : ndir ( --- ) \ Enter a NEW directory spec
- forgx forgy 17 14 d+ at
- ." Edit the Directory Spec, and press Enter. ESC=Cancel"
- cursor-on pathbox
- on> autoclear
- >attrib1
- forgx forgy 26 11 d+ dirspec$ 41 lineeditor drop
- >norm
- forgx forgy 17 14 d+ at 52 spaces
- dirspec$ count + 1- c@ dup '\' = swap ':' = or
- if defdirspec$ count >r dirspec$ count + r@ cmove
- r> dirspec$ c+!
- then dirspec$ c@ 0=
- if defdirspec$ dirspec$ over c@ 1+ cmove
- then 0 dirspec$ count + c!
- dirspec$ pathset drop
- cursor-off getdir showpath 0fl ;
-
- : keytests ( n1 --- )
- dup false = if ( do nothing ) else
- ( up arrow ) dup 200 = over 56 = or if pfl else
- ( down arrow ) dup 208 = over 50 = or if nfl else
- ( PgUp ) dup 201 = over 57 = or if dlen 2/ 0 ?do pfl loop else
- ( PgDn ) dup 209 = over 51 = or if dlen 2/ 0 ?do nfl loop else
- ( \ ) dup 92 = if ndir else
- ( 0 to 9) dup '0' '9' between over bl or
- ( A to Z) 'a' 'z' between or if find_letter else
- ( Del ) dup 211 = over 46 = or if delfl else
- ( Home ) dup 199 = over 55 = or if 0fl else
- ( End ) dup 207 = over 49 = or if efl else beep
- then then then then then then then then then then
- drop ;
-
- : ?setdir ( c1 --- c2 f1 ) \ return bool false if new dir
- curfl >fadr dup>r 1- c@l dirattrib and \ are we on a DIR
- if drop
- dirseg r@ dir>pad + off \ move DIR to PAD, nul term
- pad 1+ @ rootdir @ = \ is DIR the ROOT?
- if dirspec$ 2+ c@ ':' = \ include drive?
- if '\' dirspec$ 3 + c! 3 dirspec$ c!
- defdirspec$ count >r
- dirspec$ count + r@ cmove r> dirspec$ c+!
- else defdirspec$ dirspec$ over c@ 1+ cmove
- then dirspec$ count + off \ nul term
- begin item# @ 1 > \ Clear DIR stack
- while istk> drop
- repeat istk> setfl \ set to ROOT
- else pad 1+ @ " .." drop @ = \ pop one level?
- if \ Now we need to remove a Dir from DIRSPEC$.
- \ so step through DIRSPEC to next to the last
- \ directory.
- dirspec$ >pathend-1 dirspec$ 1+ - dirspec$ c!
- \ Append *.* to current directory specification
- defdirspec$ count >r dirspec$ count + r@ cmove
- r> dirspec$ c+!
- dirspec$ count + off \ nul terminate
- istk> setfl \ pop DIR stack
-
- else \ Must be on a directory name other than
- \ "." or ".." so step down to that directory
-
- dirspec$ >pathend dup \ set dirspec length
- dirspec$ 1+ - dirspec$ c!
- \ append DIR from PAD
- \ to dirspec
- pad count >r swap r@ cmove
- r> dirspec$ c+! \ set length
- " \" >r dirspec$ count + r@ cmove \ append "\"
- r> dirspec$ c+!
- defdirspec$ count >r dirspec$ count + r@ cmove
- r> dirspec$ c+! \ append *.*
- dirspec$ count + off \ null terinate
- curfl >istk \ save directory offset
- 0 setfl \ reset offset to zero
- then
- then \ get new directory, and show the path
- cursor-off getdir showpath gotofl
- false false
- else true
- then r>drop ;
-
- headers
-
- FORTH DEFINITIONS
-
- : <getfile> ( --- <a1> f1 ) \ return a1 filename addr and boolean
- dirseg 0= if false exit then \ if it didn't work, then leave
- ['] wflbutton save!> dobutton \ init mouse support
- savecursor
- savescr \ save cursor and screen
- forgx 2- forgy 2- over 74 + rows 3 - box&fill
- forgx forgy 36 1 d+ at \ then my message
- ." \r Tom's Window File Selection Tool "
- forgx forgy 20 7 d+ at
- ." \2 Reading Directory Files... "
- cursor-off getdir \ clear screen, and get dir
- 0fl showkeys showpath \ show the keys and dir path
- forgx forgy 17 16 d+ at \ and som help information
- ." Use to pick a file, or press the first letter of"
- forgx forgy 17 17 d+ at
- ." the file you want, then press Return to select it."
- begin showdir 0 0 at \ show the directory
- key dup 13 = dup \ wait for a key, if Enter
- if drop ?setdir ( c1 --- c2 f1 ) \ try to set dir
- then over 27 = or 0= \ else check for escape or null
- while keytests \ if neither then try to find a file
- repeat 13 = dup \ if it was Enter, then get the file name
- \ we are on and move it to PAD. Prepend
- \ the DIR spec.
- if dirspec$ >pathend dirspec$ 1+ - >r
- dirspec$ pad r@ 1+ cmove r> pad c!
- curfl >fadr 2dup c@l >r 1+
- ?cs: pad count + r@ cmovel r> pad c+!
- pad handle>ext c@ '.' <> \ append '.' if no extension
- if '.' pad count + c!
- 1 pad c+!
- then pad swap
- then
- restscr \ restore screen
- restcursor \ restore cursor position
- restore> dobutton
- #fls 0<> and ; \ return boolean for file selected
-
- ' <getfile> is getfile \ patch in window get file.
-
- behead
-
-
-