; ----- COM-AND Edit transation tables
;
;	This script opens a window and allows the editing of translation
;	tables.  COM-AND supports two transations: incoming and outgoing.
;	The first 128 bytes of the incoming table are displayed on entry.
;
;	The incoming table is 256 entries.  The outgoing table is the same
;	size.  The 'n'th position represents the translation value for the
;	character with value 'n'.
;
;	Translation may be enabled here in this script - and in COM-AND's
;	Alt-V emulations.
;
;	R.McG, commenced 1/89
; ----- Usages -----------------
;	S19 -----> COM-AND.XLT file name to be used
;	S10-S17 -> The file loaded into memory
;	N99 -----> Display page (0,1,2,3)
;	FLAG(9) -> Hex/decimal switch
;	FLAG(8) -> Modification to file
; ------------------------------
;	Initialization
;
;* TRACE ON
   ON ESCAPE GOSUB Exit 		; SAVE is performed in Window
   LEGEND " Edit translations"
   SET TTHRU OFF			; Disallow typeahead
   N99 = 0				; Base of current window
   SET FLAG(9) OFF			; Hex/decimal flag (true = hex)
   SET FLAG(8) OFF			; Modification flag
;
;	Initialize, and paint an initial window
;
   GOSUB Set_Fname			; S19 -> target file
   UPPER S19				; .. make nice
   GOSUB Load				; Load values
   GOSUB Window 			; Open the window
;
;	Main-loop - look for keyentry
;
Main_Loop:
   ATSAY  22,11 (default) "          "
   LOCATE 22,11
   KEYGET S0				; Get a keystroke
;
;	Act upon the keystroke
;
   SWITCH S0
      CASE "4900"                       ; Pgup
	 GOTO PgUp
      ENDCASE
      CASE "5100"                       ; PgDn
	 GOTO PgDn
      ENDCASE
      CASE "4700"                       ; Home
	 GOTO Home
      ENDCASE
      CASE "4F00"                       ; End
	 GOTO End
      ENDCASE
      CASE "H"                          ; H)ex
	 SET FLAG(9) ON
	 GOSUB DISPPAGE
	 GOTO Main_Loop
      ENDCASE
      CASE "D"                          ; D)ecimal
	 SET FLAG(9) OFF
	 GOSUB DISPPAGE
	 GOTO Main_Loop
      ENDCASE
      CASE "S"                          ; S)ave
	 GOSUB Store
	 GOTO Main_Loop
      ENDCASE
      CASE "N"                          ; S)ave
	 IF FLAG(8)
	    GOSUB Store 		; Save on disk
	    SET FLAG(8) OFF
	    ENDIF
	 SET TRAN ON
	 GOTO Main_Loop
      ENDCASE
      CASE "F"                          ; S)ave
	 SET TRAN OFF
	 GOTO Main_Loop
      ENDCASE
   ENDSWITCH
;
;     Begin numeric entry
;
   IF NOT NULL S0(1:3)			; Disallow other special keys
      SOUND 100,100
      GOTO Main_Loop
      ENDIF
   GOSUB Enter				; Enter #
   GOTO Main_Loop			; And continue
;
; ----- Page up (cycle backwards through possible values)
;
PgUp:
   DEC N99
   IF LT N99 0
      N99 = 3
      ENDIF
   GOSUB DispPage
   GOTO Main_Loop
;
; ----- Page down (cycle forwards through possible values)
;
PgDn:
   INC N99
   IF GT N99 3
      N99 = 0
      ENDIF
   GOSUB DispPage
   GOTO Main_Loop
;
; ----- Home (move to first line)
;
Home:
   N99 = 0
   GOSUB DispPage
   GOTO Main_Loop
;
; ----- End (Move to last line)
;
End:
   N99 = 3
   GOSUB DispPage
   GOTO Main_Loop
;
; ----- Subroutine Exit - terminate the process
;
Exit:
   IF FLAG(8)				; If table modified
      GOSUB Ask_Save			; Ask if to save
      ENDIF
   DO					; CLose any open windows
     WCLOSE
     UNTIL FAILURE
   EXIT
;
; ----- Subroutine: Enter a value
;	.. on entry S0 -> The first keystroke
;	.. S9 within this subroutine the field being constructed
;	.. N6 within this subroutine is an index to field being constructed
;
Enter:
   N6 = 0				; Index to field being built
   S9 = ""                              ; Clear field
   UPPER S0				; Make upper case
   CTOI S0 N0				; Easier comparison
   IF NOT ((GE N0 48 and LE N0 57) or EQ N0 88) ; Allow 0-9 and 'x'
      SOUND 100,100
      RETURN
      ENDIF
   CURSOR N0,N1
   INC N1
   LOCATE N0,N1
   GOTO Keyin
;
;	Accept another keypress
;
Keypress:
   KEYGET S0				; Get more from keybd
;
;	Catch backspace (and equivalent cursor left) here
;
Keyin:
   IF STRCMP S0 "08" or STRCMP S0 "4B00"; Backspace or cursor left
      IF GT N6 0
	 CURSOR N0,N1
	 ATSAY N0,N1 (default) "^H"
	 DEC N6
	 ENDIF
      IF EQ N6 0
	 RETURN 			; Nop at this pt
	 ENDIF
      GOTO Keypress
      ENDIF
;
;	Catch carriage return (and equivalent space/tab) here
;
   IF STRCMP S0 "0D" or STRCMP S0 " " or STRCMP S0 "09" ; cr, space, tab
      IF EQ N6 0			; Look for nothing done
	 RETURN 			; Empty field
	 ENDIF
      GOTO End_Entry			; Done - try to convert it
      ENDIF
;
;	Other control keys abort entry
;
   IF NOT NULL S0(1:3)			; If a special key
      GOTO Abort_Entry			; Exit on special key
      ENDIF
;
;	Filter only 0-9, a-f, and 'x' here
;
   UPPER S0				; Make upper case
   CTOI S0 N0				; Easier comparison
   IF NOT ((GE N0 48 and LE N0 57) or (GE N0 65 and LE N0 70) or EQ N0 88)
      SOUND 100,100
      GOTO Keypress
      ENDIF
;
;	Add the character to the string being constructed
;
   CURSOR N0,N1
   ATSAY N0,N1 (default) S0
   INC N1
   LOCATE N0,N1
   S9(N6:N6) = S0			; Add the key
   INC N6				; Add to index
   GOTO Keypress			; And continue
;
;	Abort entry and return to main
;
Abort_Entry:
   RETURN
;
;	Error in entry
;
Entry_Error:
   SOUND 400,100
   RETURN
;
;	End of entry - catch empty field
;
End_Entry:
      IF EQ N6 0			; EMpty field
	 RETURN
	 ENDIF
;
;	Convert a leading 'x' into '0x'
;
      IF STRCMP S9(0:0) "X"             ; 'x' in col 0
	 S9 = "0"&S9                    ; Add an initial 0
	 ENDIF
;
;	Try to convert the char
;
      ATOI S9 N0			; Convert
      IF ERROR or (LT N0 0 or GT N0 255)
	 GOTO Entry_Error		; .. indicate error
	 ENDIF
;
;	Lookup the value obtained
;
   GOSUB Get_Value			; Using N0, get its translation into N1
   S0 = "Char %03d (x%02x) currently translates to %03d (x%02x)"
   STRFMT S1 S0 N0,N0 N1,N1		; Construct prompt
;
;	Open a window for the entry of the translation
;
   WOPEN 19,0, 22,78 (default) TenterXIT
   ATSAY 20,2, (default) S1		; D
   ATSAY 21,2  (default) "New translation: "
   ATSAY 22,28 (default) " Press ESC to cancel "
;
;	Ask for the translation
;
Tenter:
   ATGET 21,19 (default) 4 S0		; Get new translation
;
;	Catch empty response (Tenter_ESC also clears S0)
;
   IF NULL S0				; EMpty field
      WCLOSE				; Drop window
      RETURN
      ENDIF
;
;    Convert a leading 'x' into '0x'
;
   IF STRCMP S0(0:0) "X"                ; 'x' in col 0
      S0 = "0"&S0                       ; Add an initial 0
      ENDIF
;
;    Try to convert the char
;
   ATOI S0 N1				; Convert
   IF ERROR or (LT N1 0 or GT N1 255)
      SOUND 400,100
      GOTO Tenter			; .. Try again
      ENDIF
;
;    We have a value (N0 translating into N1)
;
   WCLOSE
   SET FLAG(8) ON			; Mark updated
   GOSUB Set_Value
;
;    Redisplay the line or page modified
;
   N3 = N0/128				; N3  -> page #
   IF GE N99 2				; N99 -> incoming/outgoing
      N3 = N3+2
      ENDIF
   IF NE N3 N99
      N99 = N3				; Set new page no
      GOSUB DispPage			; Display the new page
   ELSE
      N98 = N0 & 15			; Make N98 = 0-15
      GOSUB DispLine			; Just redo the line (n98 = lineno)
      ENDIF
   RETURN
;
; ----- Escape during entry routine
;
TenterXit:
      S0 = ""                           ; Null input field
      RETURN
;
; ----- Get a translation value
;	On entry N0 -> the char being translated
;	On exit  N1 <- the translation
;
Get_Value:
	N3 = N0/64		; Mask string # (0-3)
	IF GE N99 2		; Decide incoming/outgoing
	   N3 = N3+4		; Sel within incoming/outgoing tables
	   ENDIF
	SWITCH N3		; Switch on string # (0-7)
	  CASE 0
	    S0 = S10
	  ENDCASE
	  CASE 1
	    S0 = S11
	  ENDCASE
	  CASE 2
	    S0 = S12
	  ENDCASE
	  CASE 3
	    S0 = S13
	  ENDCASE
	  CASE 4
	    S0 = S14
	  ENDCASE
	  CASE 5
	    S0 = S15
	  ENDCASE
	  CASE 6
	    S0 = S16
	  ENDCASE
	  CASE 7
	    S0 = S17
	  ENDCASE
	ENDSWITCH
	CTOI S0(N0&63) N1
	RETURN
;
; ----- Store a translation value
;	On entry N0 -> the char being translated
;		 N1 -> the translation
;
Set_Value:
	N3 = N0/64		; Mask string # (0-3)
	IF GE N99 2		; Decide incoming/outgoing
	   N3 = N3+4		; Sel within incoming/outgoing tables
	   ENDIF
	SWITCH N3		; Switch on string # (0-7)
	  CASE 0
	    ITOC N1 S10(N0&63)
	  ENDCASE
	  CASE 1
	    ITOC N1 S11(N0&63)
	  ENDCASE
	  CASE 2
	    ITOC N1 S12(N0&63)
	  ENDCASE
	  CASE 3
	    ITOC N1 S13(N0&63)
	  ENDCASE
	  CASE 4
	    ITOC N1 S14(N0&63)
	  ENDCASE
	  CASE 5
	    ITOC N1 S15(N0&63)
	  ENDCASE
	  CASE 6
	    ITOC N1 S16(N0&63)
	  ENDCASE
	  CASE 7
	    ITOC N1 S17(N0&63)
	  ENDCASE
	ENDSWITCH
	RETURN
;
; ----- Construct the file name we'll use for COM-AND.XLT
;
Set_Fname:
	S19 = "COM-AND.XLT"     ; Default to current subdir
	IF ISFILE S19		; Look for file on default subdir
	   RETURN		; Exit here
	   ENDIF
;
; ----- Construct the file with the COM-AND= pathing (if provided)
;
	ENVIRON S1 "COM-AND="   ; Look for COM-AND= environment var
	IF FOUND		; If environment variable found
	   LENGTH S1 N0 	; Get its length
	   N0 = N0-1		; Point to last char in string
	   IF not STRCMP S1(n0:n0) "\"
	      N0 = N0+1
	      CONCAT S1(n0) "\"
	      ENDIF
	   ENDIF
	S19 = S1&"COM-AND.XLT"  ; Concatenate path and name
	RETURN
;
; ----- Subroutine: error
;	.. Open a window, display, and and await keypress
;	S0,S1 pass the message(s) to display
;
Error:
	WOPEN 10,1, 13,77 (contrast) ErrEsc
	ATSAY 11, 3 (contrast) S0(0:73)
	ATSAY 12, 3 (contrast) S1(0:73)
	ATSAY 13,26 (contrast) " Press any key to continue "
	SOUND 880,100

	KEYGET S0		; Wait for any key
	WCLOSE			; Restore screen under
	RETURN			; And return to caller
;
;	Escape during "Error" window
;
ErrEsc:
	RETURN			; And return to KEYGET above
;
; ----- Load the current table
;	.. first, dummy values
;
Load:
	FOR N0=0,31
	    ITOC  N0	  S10(N0:N0)
	    ITOC (N0+64)  S11(N0:N0)
	    ITOC (N0+128) S12(N0:N0)
	    ITOC (N0+192) S13(N0:N0)
	    ITOC  N0+32   S10(N0+32)
	    ITOC (N0+96)  S11(N0+32)
	    ITOC (N0+160) S12(N0+32)
	    ITOC (N0+224) S13(N0+32)
	    ENDFOR
	S14 = S10
	S15 = S11
	S16 = S12
	S17 = S13
;
;	If the file doesn't exist, no error
;
	IF NOT ISFILE S19
	   GOTO LOADXIT
	   ENDIF
;
;	Open the file
;
	FOPENI S19 BINARY	; Open as a binary file
	IF FAILED		; If error openeing it...
	   S0 = "Error opening file for loading"
	   S1 = S19
	   GOSUB Error		 ; Display error message
	   RETURN
	   ENDIF
;
;	Read the file into 8 string variables
;	.. File is opened binary!
;
	READ S10 64 N0		; Read 64 bytes
	READ S11 64 N0		; Read 64 bytes
	READ S12 64 N0		; Read 64 bytes
	READ S13 64 N0		; Read 64 bytes
	READ S14 64 N0		; Read 64 bytes
	READ S15 64 N0		; Read 64 bytes
	READ S16 64 N0		; Read 64 bytes
	READ S17 64 N0		; Read 64 bytes
	FCLOSEI 		; Close the file
LoadXit:
	RETURN			; And we're done
;
; ----- Subroutine: Ask if modifications are to be saved
;	.. Open a window, display, and and await keypress
;	S0,S1 pass the message(s) to display
;
Ask_Save:
	WOPEN 10,1, 12,77 (contrast) AskEsc
	ATSAY 11, 3 (contrast) "Do you wish to save changes? (y/n): "
	ATSAY 12,29 (contrast) " Press ESC to exit "
	SOUND 880,100
Ask_Again:
	ATGET 11,40 (contrast) 1 S0
	SWITCH S0
	  CASE "Y"
	    GOSUB Store 	; Save current values
	  ENDCASE
	  CASE "N"
	  ENDCASE
	  DEFAULT
	    SOUND 100,100
	    GOTO Ask_Again	; None of the above
	  ENDCASE
	ENDSWITCH

	WCLOSE			; Restore screen under
	RETURN			; And return to caller
;
;	Escape during "Ask" window
;
AskEsc:
	S0 = "N"                ; Fake a 'n'
	RETURN			; And return to KEYGET above
;
; ----- Store the table as composed.
;	.. First, Open the file
;
Store:
	FOPENO S19 BINARY	; Open the file name so constructed
	IF FAILED		; If error openeing it...
	   S0 = "Error opening file for update"
	   S1 = S19
	   GOSUB Error		 ; Display error message
	   RETURN
	   ENDIF
;
;	Write the file from the 8 string variables
;	.. File is opened binary!
;
	WRITE S10 64
	WRITE S11 64
	WRITE S12 64
	WRITE S13 64
	WRITE S14 64
	WRITE S15 64
	WRITE S16 64
	WRITE S17 64
	FCLOSEO 		; Close the file
	RETURN			; And we're done
;
; ----- Format the current page for display
;	.. First, Display the Incoming/outgoing legend
;
DispPage:
	SWITCH N99		; Switch on current page
	  CASE 0
	    S0 = "Incoming translations"
	  ENDCASE
	  CASE 1
	    S0 = "Incoming translations"
	  ENDCASE
	  CASE 2
	    S0 = "Outgoing translations"
	  ENDCASE
	  CASE 3
	    S0 = "Outgoing translations"
	  ENDCASE
	  DEFAULT		; N99 buggerred
	    RETURN		; Leave display blank
	  ENDCASE
	ENDSWITCH
	ATSAY 1,2 (default) S0 & ", from file "*S19
;
;	Now, build lines and display 'em
;
	FOR N98 = 0,15		; 16 rows of 8 columns
	    GOSUB  DispLine
	    ENDFOR
	RETURN			; And we're done
;
; ----- Display a single line
;	N99 -> 0,1,2,3 display page
;	N98 -> The line number (0-15)
;
DispLine:
	SWITCH N99		; Switch on current page
	  CASE 0
	    S0 = S10
	    S1 = S11
	  ENDCASE
	  CASE 1
	    S0 = S12
	    S1 = S13
	  ENDCASE
	  CASE 2
	    S0 = S14
	    S1 = S15
	  ENDCASE
	  CASE 3
	    S0 = S16
	    S1 = S17
	  ENDCASE
	  DEFAULT		; N99 buggerred
	    RETURN		; Leave display blank
	  ENDCASE
	ENDSWITCH
;
;	Now, build a line and display it
;
	N10 = N98		; Even page # 1st lnno
	IF NOT ZERO (N99&1)	; Odd/even base page #
	   N10 = N98+128	; Odd page # 1st line #
	   ENDIF
	FOR N9=1,8
	    N10[N9] = N10[N9-1]+16 ; N11-N17
	    ENDFOR
	CTOI S0(N98)	N0
	CTOI S0(N98+16) N1
	CTOI S0(N98+32) N2
	CTOI S0(N98+48) N3
	CTOI S1(N98)	N4
	CTOI S1(N98+16) N5
	CTOI S1(N98+32) N6
	CTOI S1(N98+48) N7
	IF FLAG(9)		; T -> Hex
	   S2 = "x%02x:x%02x  x%02x:x%02x  x%02x:x%02x  x%02x:x%02x"
	ELSE
	   S2 = "%03d:%03d  %03d:%03d  %03d:%03d  %03d:%03d"
	   ENDIF
	STRFMT S3 S2 N10,N0, N11,N1, N12,N2, N13,N3
	ATSAY N98+2,3 (default) S3
	STRFMT S3 S2 N14,N4, N15,N5, N16,N6, N17,N7
	ATSAY N98+2,3+37 (default) S3
	RETURN			; And we're done
;
; ----- Open a window with blank fields
;
Window:
   WOPEN  0,0  23,78 (Default)
   ATSAY  0,2  (default)   " COM-AND Translates "

   ATSAY 18,0  (default) "ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´"
   ATSAY 19,3  (default)    "PgUp, PgDn, Home, End through table(s);  H)ex, D)ecimal, S)ave, oN), oF)f;"
   ATSAY 20,3  (default)    "Or enter a value (decimal or hex) to modify."
   ATSAY 21,0  (default) "ÃÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄ´"
   ATSAY 22,3  (default) "Select: "
   ATSAY 23,30 (default)			" Press ESC to exit "

   GOSUB  DispPage
   RETURN
