Forth source kept in blocks (called screens) is usually formatted as 16 lines of 64 characters. I've heard of one Forth system which showed a screen as 25 lines of 40 characters. To the interpreter, a screen is just a text stream of 1024 bytes.
The Commodore 64's 40 column screen makes it tempting to go with the 25 line by 40 character option (even with the inability to edit those last 24 bytes) but source from such a system would not display properly on a system displaying a screen as 16 lines of 64 characters and vice versa.
I posted the following about five years ago.
JimBoyd wrote:
Garth suggested an editing keyhole into the source.
I should be able to modify the editor to show a 36 column window into the block so I can see and edit just part of a source block without line wrapping on the C64 screen. Since it will be easier to add comments, there won't be so much wasted space.
I kept putting it off, until now. Here is my initial attempt.
First, I should mention that Fleet Forth's EXPECT uses the Commodore 64's screen editor. This means that I can cursor up to a line of text on the screen and press the return key. The line of text will be received by EXPECT just as if it had been typed. SCR is a variable in the EDITOR vocabulary. It is set by LIST and used by all the editor words for the current block to edit.
The words 0: through F: in the EDITOR vocabulary are the child words of XED . 0: reads the entire text input buffer and copies the first 64 bytes (after 0: and a space) to line zero of the current block.
There are some new versions of LIST in the FORTH vocabulary and L in the EDITOR vocabulary. LIST and L display the entire screen. <LIST and <L display the first 36 characters of each line. LIST> and L> display the last 36 characters of each line.
Each version of L fetches the current screen (for editing) from the variable SCR and calls its respective version of LIST .
0 FH LIST
SCR# 2056 1 8
0: // SYSTEM CONSTANTS
1:
2: $85 CONSTANT N $8D CONSTANT XSAVE // THESE CONSTANTS WERE
3: $8E CONSTANT UP $FB CONSTANT IP // SET BY DESIGN
4: $FE CONSTANT W //
5: ' NOOP @ CONSTANT NEXT // THESE CONSTANTS DEPENDED
6: ' FILL @ 3 + @ CONSTANT SETUP // ON THE LOCATIONS OF
7: ' 2DROP @ CONSTANT POPTWO // VARIOUS PRIMITIVES
8: POPTWO 2+ CONSTANT POP // IN THE SYSTEM
9: ' 1 @ 2+ CONSTANT APUSH //
A: APUSH 2+ CONSTANT AYPUSH //
B: AYPUSH 2+ CONSTANT AYPUT //
C:
D:
E:
F:
OK
<L
SCR# 2056 1 8
0[ // SYSTEM CONSTANTS
1[
2[ $85 CONSTANT N $8D CONSTANT XSAVE
3[ $8E CONSTANT UP $FB CONSTANT IP
4[ $FE CONSTANT W
5[ ' NOOP @ CONSTANT NEXT
6[ ' FILL @ 3 + @ CONSTANT SETUP
7[ ' 2DROP @ CONSTANT POPTWO
8[ POPTWO 2+ CONSTANT POP
9[ ' 1 @ 2+ CONSTANT APUSH
A[ APUSH 2+ CONSTANT AYPUSH
B[ AYPUSH 2+ CONSTANT AYPUT
C[
D[
E[
F[
OK
L>
SCR# 2056 1 8
0]
1]
2] T XSAVE // THESE CONSTANTS WERE
3] T IP // SET BY DESIGN
4] //
5] // THESE CONSTANTS DEPENDED
6] P // ON THE LOCATIONS OF
7] WO // VARIOUS PRIMITIVES
8] // IN THE SYSTEM
9] H //
A] SH //
B] T //
C]
D]
E]
F]
OK
This is what it looks like on the Commodore 64.
Notice each version of LIST appends a different character to the line number. This is to support the new screen editing words.
The words 0[ through F[ only alter the first 36 characters of a line and the words 0] through F] only alter the last 36 characters of a line.
The original version of LIST which shows everything on each line is acceptable and the version which shows the first 36 characters of each line is acceptable. The version which shows the last 36 characters on a line doesn't show enough of the beginning of each line. It's almost like editing the end of the line blind. The block could initially be displayed with the original LIST and the source typed in using the screen editing words 0: through F: . The other versions of LIST and the screen editing words 0[ through F[ and 0] through F] could be used to edit the existing source.
I'm not satisfied with the editor extension I mentioned in my last post.
My current screen editor, one I've used for years, uses a modified LIST which displays all the line numbers as hexadecimal numbers, regardless of base, with a colon appended to the number. These are editor words which parse the rest of the line where they occur and copy that text to the corresponding line of the current screen, the block number stored in SCR .
SCR# 2056 1 8
0: // SYSTEM CONSTANTS
1:
2: $85 CONSTANT N $8D CONSTANT XSAVE
3: $8E CONSTANT UP $FB CONSTANT IP
4: $FE CONSTANT W
5: ' NOOP @ CONSTANT NEXT
6: ' FILL @ 3 + @ CONSTANT SETUP
7: ' 2DROP @ CONSTANT POPTWO
8: POPTWO 2+ CONSTANT POP
9: ' 1 @ 2+ CONSTANT APUSH
A: APUSH 2+ CONSTANT AYPUSH
B: AYPUSH 2+ CONSTANT AYPUT
C:
D:
E:
F:
Fleet Forth's EXPECT uses the Commodore 64's screen editor. I can scroll up to a line, alter that line or not and press the return key. That line will be what EXPECT returns.
A very plain and simple screen editor. It does have it's limitations. This is what it looks like if a line (including line number, colon and space) is longer than (or even equal to) 40 characters.
SCR# 2083 1 35
0: // S DISPLAYS ALL OCCURRENCES OF TEX
T FROM SCR TO BLK#-1
1: : S ( BLK# -- )
2: >FBUF SCR @ OVER U< IF
3: SCR @ TUCK
4: DO
5: I SCR ! R# OFF
6: BEGIN
7: SEEK
8: WHILE
9: POINT SCR @ U.
A: REPEAT
B: LOOP
C: THEN
D: SCR ! ;
E:
F:
Sure, the editor words will still work because the Commodore 64 links the two physical lines for the comment line into one logical line. If there are too many long lines the top of the listing will scroll off the screen. LIST includes ?DONE so the listing can be stopped before all the lines are displayed. This makes it possible to edit the top lines if there are many long lines.
There is another problem with long lines. If the long lines are in a definition, they make the source more difficult to follow. That line wrapping makes it harder to notice the source indentation at a glance.
As I said, my current screen editor is the one I've been using for years. I remember one forum member mentioning although my source is in blocks, it has a very vertical format with a great deal of white space to the right. The Commodore 64's 40 column screen is the reason.
In spite of my dissatisfaction with my latest editor extension mentioned in the previous post, I like the idea of a secondary set of screen editor words which use an edit window into the text; however, I would like an edit window which can scroll. I'd also like to keep the editor extension simple. I do not at this time want to duplicate the functionality of 64Forth's screen editor.
I did find a solution which seems satisfying. Only time and use will tell. A modification to EXPECT enhances it further.
9.5.2 EXPECT
Control characters may be processed to allow system dependent
editing of the characters prior to receipt. Therefore, a
Standard Program may not anticipated that control characters can
be received.
It doesn't seem to say anything about intercepting function keys; however, I thought such a capability would be useful. In Fleet Forth, EXPECT is a DEFERred word. It is normally set to (EXPECT) .
The high level portion of (EXPECT) reads the keyboard and echoes the characters back to the screen. If a carriage return is detected in the keyboard buffer, it is not read. Control flow passes to the low level portion of (EXPECT) which uses the Commodore 64's screen editor, kernal routine CHRIN , $FFCF.
The word which echoes keys to the screen is DEMIT . It is a primitive which uses the same C64 kernal routines as (EMIT) . As the leading 'D' in the name implies, it is normally used to send a character to a disk drive, but can also send a character to the screen. The difference with (EMIT) , the vector for EMIT , is DEMIT does not update the variables CHARS and LINES . These variables are used for 'print formatting'. They keep track of the number of characters emitted since the last carriage return or page and the number of lines since the last page. DEMIT was replaced with the following:
7 OVER #133 - U< \ is this not a function key?
IF \ if it is not
DEMIT \ echo to the screen as usual
ELSE \ else
#63 + 4 /MOD SWAP 2* + \ convert PETSCII code
" F0" TUCK 2+ C! \ insert digit character into string
CONTEXT @ (FIND) \ and search CONTEXT vocabulary
IF DUP EXECUTE THEN \ if found, execute
DROP
THEN
The search of the CONTEXT vocabulary will include the parent vocabularies.
The Commodore 64's function keys are a little different. There are only four actual function keys: F1, F3, F5 and F7. F2 is obtained with shift-F1, F4 with shift-F3 and so on.
The PETSCII codes are as follows:
An eight byte look-up table could have been used, but this was smaller.
If function key F1 is pressed and there is no word by that name, it's the same as if the function key was not pressed. If the name exists, it is executed.
I've notice the function key names could be confused with hexadecimal numbers. I've gotten too used to using $F1 for a hexadecimal number. I could change this line:
I've only used code page 437, which clearly the C64 doesn't use. I haven't thought about how I'd use the C64 character set (including function keys), but CP437 is sure nice for the special characters, drawing boxes, and the Greek letters we use all the time in engineering (since that's what I'm always using Forth for). The Epson dot-matrix impact printers, which Epson is still making about nine models of, use the same character set, so I use it with the workbench computer too, although they don't display correctly in its small LCD unless I make custom characters in the LCD, which I've done before but is kind of a lot of overhead. My exception to the 437-only use is my HP-71B hand-held computer which defaults to the ROMAN8 set which is kind of similar but has different byte values for the special characters; but after the HP Thinkjet printer I was using with it went down and I started using the Epson printer, I loaded the CP437 character set into the HP71 computer so things would display correctly in its LCD. Here are a couple of examples of my uses of the box-drawing characters:
(although that last one was for a PIC16 project, not 6502). CP437 also lets me have Forth word names like ±½°C or 10KΩ or put Φ2 in the comments.
I've only used code page 437, which clearly the C64 doesn't use. I haven't thought about how I'd use the C64 character set (including function keys), but CP437 is sure nice for the special characters, drawing boxes, and the Greek letters we use all the time in engineering (since that's what I'm always using Forth for).
I remember code page 437. I haven't seen it since my days of using DOS.
The visual appearance of text windows can be created on the C64 using reverse video. Ctrl-R on the C64 selects reverse video and Ctrl-0 ( control zero) selects normal video.
Here is were I selected a black background and white text and played around on the screen by selecting and deselecting reverse video. I typed the text with spaces to achieve the look of windows.
I normally use reverse video on the C64 to highlight important information.
Fleet Forth has the words RON to switch reverse video on and ROFF to switch to normal video. A carriage return also switches reverse video off.
I've removed the words <LIST <L LIST> L> and their editor words 0[ through F[ and 0] through F] because they were unsatisfactory.
I also mentioned a solution which seems satisfactory.
A new LIST word which use an editing window VALUE for a displacement to the right, EW , and a corresponding set of editing words 0[ through F[ which also use EW.
I would like to mention that the word // is Fleet Forth's word to comment to the end of a line. It will also skip the rest of the line when used at the command line or in an EVALUATEed string.
The comments in the listing which have a backslash were added to this post for clarity.
0 VALUE EW
: LISTW ( SCR -- )
EW #28 UMIN (IS) EW \ be certain EW is from 0 - 28
\ inclusive.
PAGE EDITOR R# OFF DUP SCR ! \ clear the screen, select EDITOR
\ vocabulary & misc. housekeeping.
." SCR# " DUP U. SPACE BLK> . . \ show screen number.
\ BLK> breaks that number down
\ to a screen number relative to
\ the drive it is from and the
\ drive number.
10 SPACES EW . \ show displacement to the right
#16 0 CR
DO
I 0 H.R ." [ "
I LINE EW /STRING #36 UMIN \ only show 36 columns
QTYPE CR \ type in 'quote mode'
DONE? ?LEAVE
LOOP ;
EDITOR DEFINITIONS
: XED2 ( N -- )
CREATE ( N -- )
C,
DOES> ( -- )
C@ LINE 0 TEXT PAD 1+ -ROT
EW #28 UMIN /STRING #36 UMIN
MOVE UPDATE
3 RC ! QUIT -;
: LW ( -- )
SCR @ LISTW ;
0 XED2 0[ 1 XED2 1[ 2 XED2 2[
3 XED2 3[ 4 XED2 4[ 5 XED2 5[
6 XED2 6[ 7 XED2 7[ 8 XED2 8[
9 XED2 9[ $A XED2 A[ $B XED2 B[
$C XED2 C[ $D XED2 D[ $E XED2 E[
$F XED2 F[
FORTH DEFINITIONS
LINE takes an number from 0 to 15 and returns the address, in the block buffer, of that line for the current screen, the one which has its block number stored in SCR . 0 TEXT reads the rest of the line in the text input buffer and stores it at PAD . After -ROT the stack has the following three parameters on top.
The address of the text to copy.
The address of the line of the current screen for this child word.
A count of 64.
The line
increments the destination address by EW bytes and clips the length of the transfer to 36 bytes, the length of the edit window.
The string is MOVEd to the block buffer and the buffer updated.
Fleet Forth's EXPECT starts at the beginning of a line on the view screen and will perform a carriage return if necessary. Setting the variable RC to 3 will cause EXPECT to move the cursor right by three.
That reversed video colon after 2[ is a snapshot of the blinking cursor. It was placed there after pressing the return key anywhere on the previous line.
Fleet Forth's EXPECT was modified to test for function keys. The function key words can be executed without the need to scroll down from the text being edited.
Some sample function key words I was trying. This is how the screen appears when listing with LISTW and EW is zero. The listings are sent to a printer, or in my case, a print.dump file.
SCR# 4719 2 623 14
0[ S
1[ IONS
2[ ) // MOVE EDIT WINDOW
3[ HERE >A ]
4[ MIN LW AT-XY ;
5[ ) // MOVE WINDOW LEFT
6[ X TO EW
7[ , ] -;
8[ ) // MOVE WINDOW RIGHT
9[ MIN TO EW
A[ , ] -;
B[ ) #28 TO EW // MOVE EDIT WINDOW
C[ , ] -;
D[ ) // MOVE CURSOR TO BE
E[ ;
F[ ONS
SCR# 623
// EDITOR FKEYS
EDITOR DEFINITIONS
: F1KEY ( -- ) // MOVE EDIT WINDOW TO BEGINNING
0 TO EW [ HERE >A ]
XY 1 MAX 16 MIN LW AT-XY ;
: F3KEY ( -- ) // MOVE WINDOW LEFT 7 COLUMNS
EW 7 - 0 MAX TO EW
BRANCH [ A@ , ] -;
: F5KEY ( -- ) // MOVE WINDOW RIGHT 7 COLUMNS
EW 7 + #28 MIN TO EW
BRANCH [ A@ , ] -;
: F7KEY ( -- ) #28 TO EW // MOVE EDIT WINDOW TO END
BRANCH [ A> , ] -;
: F2KEY ( -- ) // MOVE CURSOR TO BELOW EDIT AREA
0 18 AT-XY ;
FORTH DEFINITIONS
Although with the last two, there will be a line wrap on the Commodore 64's video screen.
F1KEY moves the editing window all the way to the left by setting EW to zero. XY returns the X (from left to right) and Y (from top to bottom) coordinates of the text cursor. AT-XY sets the coordinates, which places the cursor at those coordinates.
Suppose I wish to add a comment for the definition of F1KEY . While in the editor vocabulary, I press the F1 key and scroll up to the line with the name F1KEY . I press the F7 key and the listing is updated to show the last 36 columns of the screen, but the cursor is on the same line as it was before pressing the F7 key. I can now add a comment knowing it is on the correct line.
In the Fleet Forth kernel there are eighteen headerless words. Words like the one formerly named TRAVERSE or some of the words used by the sector read/write word, SR/W . These headerless words have no use outside the kernel, which is why they are headerless. There is another group of words which are not directly used outside the kernel, the run-time words of other words.
Here are some of the compiling words and associated run-time words
DO (DO)
?DO (?DO)
LOOP (LOOP)
+LOOP (+LOOP)
" (")
." (.")
ABORT" (ABORT")
IS (IS)
TO (IS)
I may change the names of some of these run-time words but these words will not be made headerless. The few dozen bytes saved would not justify the increased complexity in the design of the decompiler, SEE .
I've mentioned Fleet Forth's TRACE and the ability to change what information is displayed by setting the DEFERred word .STEP to a step display word more appropriate for the trace.
Here is yet another example of how TRACE's step display can be customized. I recently made a modification to Fleet Forth's metacompiler. One of the words copies a string to HERE and modifies it, if necessary. The reason PAD isn't used is because Fleet Forth has the word >HERE in the kernel.
I wanted to see what was happening at HERE when tracing that word.
: .STMETA
(.ST1) CR HERE $10 DUMP ;
' .STMETA IS .STEP
(.ST1) is the default step display word. .STMETA calls (.ST1) for the usual display for the current step and then dumps the first sixteen bytes at HERE .
9.5.2 EXPECT
Control characters may be processed to allow system dependent
editing of the characters prior to receipt. Therefore, a
Standard Program may not anticipated that control characters can
be received.
It doesn't seem to say anything about intercepting function keys; however, I thought such a capability would be useful.
I have found nothing in the Forth-83 Standard for or against this extra functionality in EXPECT .
The closest I've seen is this excerpt for the Forth 2012 Standard's ACCEPT .
forth-standard.org wrote:
It is recommended that all non-graphic characters be reserved for editing or control functions and not be stored in the input string.
Fleet Forth is a Forth-83 Standard Forth for the most part; however, when there is something not covered in the Forth-83 Standard I will check the other standards for the least objectionable approach to minimizing divergent behavior in my Forth when adding new functionality to the kernel. One such example is renaming Fleet Forth's UNDO to UNLOOP . ACCEPT is the Forth 2012 Standard version of EXPECT with slightly different behavior. As such, where the Forth-83 Standard is quiet concerning the use of function keys in EXPECT , I'll accept the Forth 2012 Standard's recommendations for ACCEPT . The relevant phrase describing ACCEPT is "or control functions" which would indicate that it is acceptable for ACCEPT , and therefore EXPECT , to intercept function keys and use them for control purposes.
FSAVE is Fleet Forth's word to save the Forth system as a Commodore program file. FSAVE would prompt for a file name and use EXPECT to read in the file name to use; however, I have found that I would occasionally type a file name right after FSAVE when I already had a file name in mind and I was in a hurry. This made me wonder if having the file name inline was a more natural way to do things. The file name used by FSAVE now follows it in the text stream. FSAVE uses 0 WORD so file names with spaces can be used.
9.5.2 EXPECT
Control characters may be processed to allow system dependent
editing of the characters prior to receipt. Therefore, a
Standard Program may not anticipated that control characters can
be received.
It doesn't seem to say anything about intercepting function keys; however, I thought such a capability would be useful.
I have found nothing in the Forth-83 Standard for or against this extra functionality in EXPECT .
The closest I've seen is this excerpt for the Forth 2012 Standard's ACCEPT .
forth-standard.org wrote:
It is recommended that all non-graphic characters be reserved for editing or control functions and not be stored in the input string.
Forth-94 slightly generalized the Forth-83 EXPECT specification by specifying that author of Forth-94 source could not depend on being able to receive non-graphical characters, which is more explicit about setting aside what is returned by a function key unless it returns one or more graphical characters.
However, function keys themselves do not come into scope until Forth-2012, which is also when "a source cannot depend on non-graphical characters being stored" was strengthened to "it is recommended that a system refrain from storing non-graphical characters".
Quote:
Fleet Forth is a Forth-83 Standard Forth for the most part; however, when there is something not covered in the Forth-83 Standard I will check the other standards for the least objectionable approach to minimizing divergent behavior in my Forth when adding new functionality to the kernel. One such example is renaming Fleet Forth's UNDO to UNLOOP . ACCEPT is the Forth 2012 Standard version of EXPECT with slightly different behavior. As such, where the Forth-83 Standard is quiet concerning the use of function keys in EXPECT , I'll accept the Forth 2012 Standard's recommendations for ACCEPT . The relevant phrase describing ACCEPT is "or control functions" which would indicate that it is acceptable for ACCEPT , and therefore EXPECT , to intercept function keys and use them for control purposes.
I'd say it is good for sanity if EXPECT is implemented in a way that allows a set of Forth-94 / Forth-2012 portability screens to define ACCEPT as "EXPECT SPAN @".
One feature of VICE I have used in moderation is the ability to paste text into the simulator. Fleet Forth behaves as though the text is typed in. This does introduce a problem. When loading source from screens on blocks or even from a Commodore sequential file, an ABORT stops the load and returns control to Forth's QUIT loop. When text is pasted into the simulator the QUIT loop still has control. an ABORT stops interpreting text which has already been EXPECTed, or ACCEPTed; however, the simulator continues to fill the keyboard buffer until all pasted text has been inserted into the keyboard buffer. The behavior is exactly as if a programmer typing in source ignores errors and continues typing.
Fleet Forth's ABORT , which is called by ABORT" , is extensible.
SINGLE switches off multitasking. SP! and AP! clear the data and auxiliary stacks. ERR is a deferred word which normally executes NOOP a Forth no-op.
I set ERR to the word PURGE when I wish to paste Forth source from a Linux text file.
: PURGE // EMPTY KEYBOARD
BEGIN // BUFFER
BEGIN
KEY? // ANY KEYSTROKES?
WHILE
KEY DROP
REPEAT
1 JIFFIES // WAIT 1/60 SEC
KEY? 0= // BUFFER EMPTY?
UNTIL ;
KEY? is an AnsiForth word which returns TRUE if a character is available.
The 1 jiffy delay is to give VICE time to refill the keyboard buffer. The inner loop empties the keyboard buffer fast enough that without the delay, PURGE returns before VICE is finished adding pasted text to the buffer.
I should have mentioned that keyboard input in Fleet Forth causes the cursor to blink while waiting for input. When PURGE is used to purge the pasted text after an error occurs, I know it is done when the cursor resumes blinking at a steady rate.
In the Fleet Forth kernel there are eighteen headerless words. Words like the one formerly named TRAVERSE or some of the words used by the sector read/write word, SR/W . These headerless words have no use outside the kernel, which is why they are headerless. There is another group of words which are not directly used outside the kernel, the run-time words of other words.
Some of the run-time words now have the same name as the associated compiling word.
DO DO
?DO ?DO
LOOP LOOP
+LOOP +LOOP
" "
." ."
ABORT" ABORT"
(IS) is still the run-time for IS and TO .
The run-time words are defined before the word FORTH-83 and the compiling words are defined after. This made updating the source for SEE easier.
To find the run-time words, the FORTH vocabulary is set as both the CONTEXT and CURRENT vocabularies. Create a false vocabulary on the auxiliary stack with FORTH-83 as the latest word with the following:
The false vocabulary, the portion of the FORTH vocabulary from FORTH-83 to the beginning is searched. If the sought word is not found in this false CONTEXT vocabulary, the CURRENT vocabulary, which is all of the FORTH vocabulary, is searched.