Category : BASIC Source Code
Archive   : PBWRITE.ZIP
Filename : PBWRITE.BAS
'³ PBWRITE.BAS ³
'³ This subroutine must be included in your program. See PBWDEMO1 - 3 for ³
'³ examples of how to call the PBWRITE text editor subroutine. ³
'ÀÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÄÙ
' *** IBM SPEED DRAFT I ' *** HIGH ASCII GRAF t16
$IF 0
CHANGES TO THIS SUBROUTINE 08/24/93
Vastly improved speed of video writes through an improved inline
assembler video routine. This routine uses a parameter for video
ram address so it does not need to check each time.
Added ^Q-S Search and Replace facility
Added ^G Change Margins facility with margin reformat options
Added ^D Clear all text with save document protection
Added background processing subroutine facility for background
printing or any other background operation the programmer needs.
See the very last support subroutine in PBWRITE.BAS for more
notes on how to implement background processing.
Added TAB key handling, TAB jumps to tab point every 8 spaces.
At startup, a document passed to the routine will be checked for
tabs. If tabs are present, tabs will be expanded. This can take
a few seconds for large documents.
Added Keyboard macro support. Press ^K and then M for MACRO.
The editor will ask you to enter a hot key (ALT+something). Every
keystroke entered from this point is recorded. Press ALT+M to
end recording. Press the hot key (ALT+something) to playback.
CHANGES TO THIS SUBROUTINE 06/12/93
Fixed a major crippling word-wrap error that trashed the document
if word-wrap occured along with windowed scroll.
CHANGES TO THIS SUBROUTINE 04/30/93
Added CTRL-Y Line Delete
Added CTRL-T Word Right Delete
Added CTRL-U Line/Word undelete (up to 32K of deleted history)
Added ^K-B Block Begin, ^K-K Block End (does not highlight, though)
Added ^K-C Block Copy, ^K-Y Block Delete, ^K-V Block Move
Added ^K-R File Insert
Note: File Insert Loads a file into the clipboard. You must
use ^K-C to copy it into the current cursor position.
Added ^K-P will print block if defined, else print entire doc
CHANGES TO THIS SUBROUTINE 03/20/93
Added inline ASM routine VPRINT for direct video writes. Eliminates
need for external OBJ file
CHANGES TO THIS SUBROUTINE 12/18/92
Added Bishop's EXPANDTABS routine to correctly tab docs
Modified ExitCode%: If this var=chr$(13) upon entry, then
chr$(13) becomes an exit key, like ESCAPE, unless the doc
is ZOOMed, in which case it acts like it should. This is
so we can use PBWrite for data field entry, like FrameWork.
CHANGES TO THIS SUBROUTINE - 12/08/93
Activated internal error trap
Backspace was acting like Delete key in first position.
CHANGES TO THIS SUBROUTINE - 11/24/92
Added wordwrap and Margin% parameter
Added ExitCode% to return the scan code of key used to exit
the subroutine - ALT-X, ALT-Q, ESC, F6-F10 or F1
Fixed END key, actually goes to the end of the line, not just
the edge of the window
F3 to load a file - just press enter for a list of files
Added local error handler
F4 or ^K-P will print (that was easy)
THIS FILE: PBWRITE.BAS
AUTHOR: Erik Olson
DESCRIPTION: A collection of subroutines which center around PBWRITE(), which
is a fully functional "word-star" compatible editor subroutine.
PBWRITE edits the contents of a single string, so the largest
size document it can hold is 32K, however, the routine is
completely self-contained and can be called recursively, thus
providing you with a tool for producing multi-window and multi-
document editing. This sub only opens one window for editing,
but as many windows as RAM allows can be opened and maintained
by simply preserving the screen (if desired) and saving the
contents of the string. See the SUBROUTINE header remarks for
more details.
$ENDIF
' *** LINE FEED
DECLARE SUB GETSTRLOC ()
$IF 0
ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
ÛßÛ Û Û ÛßÝ ÛßÛ ÛßÛ Û Û ßÛß Û ÛÝÞ Ûßß
ßþÜ Û Û ÛßÛ ÛßÝ Û Û Û Û Û Û ÛÛÛ Ûß
ÛÜÛ ÛÜÛ ÛÜÛ Û Û ÛÜÛ ÛÜÛ Û Û ÝÞÛ ÛÜÜ
ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
PBWRITE() - Open a window and edit
ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
Parameters: ED$
A string which contains the entire document being edited. This
document must be an ASCII file with each line ending in a Carriage-
return, Line-feed pair. To get a file from disk, open it as binary
and read the entire file into ED$, like this:
OPEN F$ FOR BINARY AS #1 : GET$ #1, LOF(1), ED$ : CLOSE #1
ED$ cannot be any more than 32K in size. If the file is larger,
you must read it into multiple variables, and perhaps split it
into separate windows, or just load the part being edited, like
some sort of bridge.
TopView%, LeftView%, BottomView%, RightView%
These four integers contain the screen coordinates for the window.
The size of the window can be changed while editing by pressing
the SCROLL-LOCK key. When SCLK is active, the arrows ENLARGE the
window, while SHIFT-ARROW (numbers) shrink the window. If the
size of the window is changed by the user, the new coordinates
are returned in these parameters.
CursorRow%, CursorCol%
These parameters may (or should) start out as 0, unless you are
returning to a document that has been previously loaded and edited.
These integers contain the current cursor position within the
window (not within the document itself) and may be saved on exit
in order to restore the cursor when the user re-enters the document.
Ptr%
This integer should start out as 0 as well, but can be stored and
passed again when returning to a document. Ptr% holds the current
"top of window" position of the document.
Offset%
This integer, like the others, starts as 0 and stores the current
horizontal scroll offset of the window. If a person editing has
arrowed far to the right, causing the window contents to scroll
horizontally, Offset% contains the horizontal "left of window"
position of the document.
Title$
TextAttr%
This is a number from 0-255 which contains the color attribute
(foreground and background) of the text within the window.
BorderAttr%
This is a number from 0-255 which contains the color attribute
(foreground and background) of the window border, title, and
some of the pop-up windows and prompts.
Margin%
This is any reasonable number which represents the right margin
of the document. Set this to 0 to disable wordwrap
ExitCode%
This contains the scan code of the key used to exit the routine
ALT + anything, F5-F12. If ExitCode% = 256 going into this
routine, PBWRITE will draw the window and the text in it, but
immediately exit with an exit code of 256. This is so you
can call all of your windows the first time around just to
get them onto the screen. From that point on, calling PBWRITE
with exitcode%=0 will actually allow you to edit it.
STATUS ON EXIT
ED$ will contain the current document and the remaining parameters
will retain the current status if editing. If you call PBWRITE
with these parameters again, the user will find himself right
where he left off in the document. If you call PBWRITE with
another set of parameters, alternate documents can be edited
without disturbing eachother. In this fashion, you could write
a multiple-window editor very easily. PBWRITE can also be called
recursively, that is, from within itself, to temporarily edit
another document, or even temporarily edit another PART of the
current document.
THROW AWAY VARIABLES
VideoRAM&............long integer which stores the screen segment
O$...................saved screen
I%, C%, N%, S%.......Keyboard shift states (INS CAPS NUM SCLK)
FL$() ...............Array to contain the file list
Zoom% ...............True if window is currently zoomed.
Exit13% .............Exits on
Character% ..........Current character offset from start
$ENDIF
%PBWFALSE=0
%PBWTRUE=NOT %PBWFALSE
SUB PBWRITE(ED$,TopView%,LeftView%,BottomView%,RightView%,CursorRow%,CursorCol%,_
Ptr%,Offset%,Title$, TextAttr%, BorderAttr%, Margin%, ExitCode%)
SHARED Macro%,KBuffer$,Macro$
ON LOCAL ERROR GOTO PBWriteError
IF ED$="" THEN ED$=" " + chr$(13)+chr$(10)
IF INSTR(ED$, CHR$(9)) THEN ExpandTabs ED$ ' expand tabs if they exist
REG 1, 15*256
CALL INTERRUPT &H10
IF Reg(1) - (Reg(1)\256) * 256 = 7 THEN VideoRAM&=&HB000 else VideoRAM&=&HB800
DIM Fl$(500) ' for loading the directory
IF CursorRow% < TopView% THEN CursorRow% = TopView%
IF CursorRow% > BottomView% THEN CursorRow% = BottomView%
'Make sure the cursor is within the effective window
IF CursorCol% < LeftView% THEN CursorCol% = LeftView%
IF CursorCol% > RightView% THEN CursorCol% = RightView%
' establish keyboard shift states
REG 1,&h1200
CALL INTERRUPT &h16
b=ABS(REG(1))
IF (b AND 16) = 16 THEN S1% = 1 ELSE S1% = 0
IF (b and 32) = 32 THEN N1% = 1 ELSE N1%= 0
IF (b and 64) = 64 THEN C1% = 1 ELSE C1%= 0
IF (b and 128)=128 THEN I1% = 1 ELSE I1%= 0
' Setting an exitcode on entry will cause the window and text to draw,
' but immediately exit. This way, we can pop the window onto the screen
' without having to go into it.
' save the screen before drawing the frame so we can 'lift' the frame
' or move it around, or re-size it using the scroll lock key
O$=SaveScreen$
OrgTopView%=TopView%
OrgLeftView%=LeftView%
OrgRightView%=RightView%
OrgBottomView%=BottomView%
RedrawAndExit:
WideNess%=RightView%-LeftView%
Call PBWriteBox(TopView%-1, LeftView%-1, BottomView%+1, RightView%, BorderAttr%,VideoRAM&)
IF WideNess% > 20 THEN
IF Zoom% THEN a%= 25:b%=1 ELSE a%=BottomView%+1: b%=LeftView%+3
IF I1% THEN Stat$= "(Ins)" ELSE Stat$= "(Ovr)"
IF C1% THEN Stat$=Stat$+ "(Caps)" ELSE Stat$=Stat$+ "(Norm)"
IF N1% THEN Stat$=Stat$+ "(Num)" ELSE Stat$=Stat$+ "(Pad)"
IF S1% THEN Stat$=Stat$+ "(ScLk)" ELSE Stat$=Stat$+"(Edit)"
CALL VPRINT(a%,b%,Stat$,BorderAttr%,VideoRAM&)
END IF
If len(Title$) THEN CALL VPRINT(TopView%-1, LeftView%+1,"["+Title$+"]",BorderAttr%,VideoRAM&)
' starting byte for view (1 is top of file)
If Ptr%=0 then Ptr%=1
' Draw the screen
DO
TempPtr% = Ptr% : Temp% = TopView% : LastLine%=0
IF Right$(ED$,2)<>CHR$(13)+CHR$(10) THEN ED$=ED$+CHR$(13)+CHR$(10)
DO
eol% = Instr(Mid$(ED$,TempPtr%),Chr$(13))
if eol%=0 then
eol%=LEN(ED$)
if LastLine%=0 THEN LastLine%=Temp%-1
If CursorCol% > LeftView%+LenEditLine% THEN CursorCol%=LeftView%+LenEditLine%
If CursorRow% > LastLine% THEN CursorRow%=LastLine%
ELSE
DECR eol% ' DECR: do not show the CR
END IF
Curr$ = Mid$(ED$, TempPtr%,eol%):if Curr$=chr$(10) then Curr$=""
IF Temp%=CursorRow% THEN LenEditLine%=LEN(Curr$):EditPtr%=TempPtr%:EditEol%=TempPtr% + eol%
CALL VPRINT(Temp%, LeftView%, Mid$(Curr$+Space$(WideNess%+Offset%), 1+Offset%,WideNess%), TextAttr%,VideoRAM&)
TempPtr% = Instr(TempPtr%, ED$, Chr$(13)) + 2 ' +2 for CRLF pair
If TempPtr%=2 Then TempPtr%=LEN(ED$)
INCR Temp%
if Temp% > BottomView% THEN Exit LOOP
LOOP
IF RedrawPatch% THEN EXIT LOOP ' If redrawing on exit after forced UNZOOM
IF ExitCode% = 256 THEN EXIT LOOP ' if touch and go drawing
IF ExitCode% = 13 THEN Exit13%=%PBWTRUE:ExitCode%=0 ' exit on
'....................make sure the cursor is not beyond the end of a line
'If CursorCol% > LeftView%+LenEditLine% THEN CursorCol%=LeftView%+LenEditLine%
'If CursorRow% > LastLine% THEN CursorRow%=LastLine%
LOCATE CursorRow%,CursorCol%, 1 ' keep a visible cursor always
KB$ = "" ' KB$ will contain the next keystroke
WHILE KB$ = ""
' Call a possible multitasker
CALL TASK.MANAGER
' check for change in keyboard shift states
REG 1,&h1200
CALL INTERRUPT &h16
b=ABS(REG(1))
IF (b AND 16) = 16 THEN S2% = 1 ELSE S2% = 0
IF (b and 32) = 32 THEN N2% = 1 ELSE N2%= 0
IF (b and 64) = 64 THEN C2% = 1 ELSE C2%= 0
IF (b and 128)=128 THEN I2% = 1 ELSE I2%= 0
' if shift states have changed then update the status indicators
IF C2% <> C1% or N2% <> N1% or I2% <> I1% or S2% <> S1% THEN
REG 1,&h1200
CALL INTERRUPT &h16
b=ABS(REG(1))
IF (b AND 16) = 16 THEN S1% = 1 ELSE S1% = 0
IF (b and 32) = 32 THEN N1% = 1 ELSE N1%= 0
IF (b and 64) = 64 THEN C1% = 1 ELSE C1%= 0
IF (b and 128)=128 THEN I1% = 1 ELSE I1%= 0
IF WideNess% > 20 THEN
IF Zoom% THEN a%= 25:b%=1 ELSE a%=BottomView%+1: b%=LeftView%+3
IF I1% THEN Stat$= "(Ins)" ELSE Stat$= "(Ovr)"
IF C1% THEN Stat$=Stat$+ "(Caps)" ELSE Stat$=Stat$+ "(Norm)"
IF N1% THEN Stat$=Stat$+ "(Num)" ELSE Stat$=Stat$+ "(Pad)"
IF S1% THEN Stat$=Stat$+ "(ScLk)" ELSE Stat$=Stat$+"(Edit)"
CALL VPRINT(a%,b%,Stat$,BorderAttr%,VideoRAM&)
END IF
If len(Title$) THEN CALL VPRINT(TopView%-1, LeftView%+1,"["+Title$+"]",BorderAttr%,VideoRAM&)
LOCATE CursorRow%,CursorCol%, 1
END IF
KB$ = IN.KEY$ : WEND
SELECT CASE KB$
CASE CHR$(9)
Tabs%=8-(Offset%+(CursorCol%-LeftView%) MOD 8)
Keyin SPACE$(Tabs%)
CASE CHR$(32) TO CHR$(126) ' normal allowable document keys
NoSave%=-1 ' not saved
'........................the position of the char within ED$
Character%=EditPtr%+Offset%+(CursorCol%-LeftView%)
'........................add extra spaces if beyond endofline
If Offset%+(CursorCol%-LeftView%)>LENEditLine% THEN_
ED$=LEFT$(ED$,Character%-1)+SPACE$((Offset%+(CursorCol%-LeftView%))-LENEditLine%)+MID$(ED$,Character%)
'........................add extra spaces is beyond endoffile
'IF Character%>LEN(ED$) THEN ED$=ED$+SPACE$(LEN(ED$)-Character%)
' INSERT OR OVERTYPE THE CHARACTER
IF I1% THEN ' Insert mode inserts character
ED$=LEFT$(ED$,Character%-1) + KB$ + MID$(ED$,Character%)
ELSE
' If we are at the end of a line, we must
' pretend the insert is on
if MID$(ED$,Character%,1)=CHR$(13) THEN
ED$=LEFT$(ED$,Character%-1) + KB$ + MID$(ED$,Character%)
ELSE
MID$(ED$,Character%,1)=KB$ ' overtype mode changes char
END IF ' if it's a carriage return or not
END IF ' if insert is on or not
' ..............WRAP TEXT IF NECESSARY ' ** WORDWRAP
IF (CursorCol%-LeftView%)+Offset% > Margin% and Margin% > 0 THEN
n% = Character% ' ** WORDWRAP
newcursorcol% = 0 ' ** WORDWRAP
DO ' ** WORDWRAP
Check$ = MID$(ED$,n%,1) ' ** WORDWRAP
if CHECK$ = CHR$(10) OR n% = 1 THEN ' ** WORDWRAP
' abort wrap, just go to the next line
CursorCol%=LeftView% ' ** WORDWRAP
Offset%=0 ' ** WORDWRAP
INCR CursorRow% ' ** WORDWRAP
EXIT LOOP ' ** WORDWRAP
END IF
' ** WORDWRAP
IF Check$ = " " THEN ' ** WORDWRAP
'WRAP HERE! ' ** WORDWRAP
ED$=LEFT$(ED$,n%-1)+CHR$(13)+CHR$(10)+MID$(ED$,n%+1)
Cursorcol% = NewCursorCol%+LeftView%
Offset% = 0
''''' bug fix 6/12/93
CursorCol%=LeftView%
IF Offset%>0 THEN GOSUB GOHOME
Offset%=0
CursorCol%=NewCursorCol%+LeftView%
IF CursorRow% < BottomView% THEN
INCR CursorRow%
ELSE
GOSUB GODOWN
END IF
''''' end bug fix -- also iterate loop instead of gosub redraw below
EXIT LOOP ' ** WORDWRAP
END IF ' ** WORDWRAP
DECR n% ' ** WORDWRAP
INCR NewCursorCol% ' ** WORDWRAP
LOOP ' ** WORDWRAP
ITERATE LOOP
'GOSUB REDRAW ' ** WORDWRAP
END IF ' time to wrap ' ** WORDWRAP
'................NOW ADJUST THE CURSOR POSITION
IF CursorCol% < RightView%-1 THEN
INCR CursorCol%
ELSE
GOSUB GORIGHT
END IF
CASE CHR$(13)
IF Exit13% AND NOT Zoom% THEN ExitCode%=13:EXIT SELECT
''IF I1% THEN ' insert mode inserts carriage return + line feed
Character%=EditPtr%+Offset%+(CursorCol%-LeftView%)
ED$=LEFT$(ED$,Character%-1) + CHR$(13)+CHR$(10) + MID$(ED$,Character%)
''END IF
CursorCol%=LeftView%
IF Offset%>0 THEN GOSUB GOHOME
Offset%=0
IF CursorRow% < BottomView% THEN
INCR CursorRow%
ELSE
GOSUB GODOWN
END IF
CASE CHR$(8)
IF Character% > 2 and Offset% = 0 AND CursorCol%=LeftView% THEN BFlag%=%PBWTRUE
IF CursorCol% > LeftView% THEN
DECR CursorCol%
ELSE
GOSUB GOLEFT
END IF
Character%=EditPtr%+Offset%+(CursorCol%-LeftView%)
IF Bflag% THEN
BFlag% = %PBWFALSE
' This is where we want to delete and join up
' with the line above. Hmmmm....
'ED$=LEFT$(ED$,Character%-2)+Mid$(ED$,Character%+1)
ELSE
IF LEN(ED$) AND MID$(ED$,Character%,1)<>CHR$(13) AND _
Mid$(ED$,Character%,1)<>CHR$(10) THEN_
ED$=LEFT$(ED$,Character%-1)+Mid$(ED$,Character%+1)
END IF
CASE CHR$(0,&H53) ' del
Character%=EditPtr%+Offset%+(CursorCol%-LeftView%)
IF LEN(ED$) THEN
IF MID$(ED$,Character%,1)=CHR$(13) THEN
ED$=LEFT$(ED$,Character%-1)+MID$(ED$,Character%+2)
ELSE
ED$=LEFT$(ED$,Character%-1)+MID$(ED$,Character%+1)
END IF
END IF
CASE CHR$(11) ' Control - K
Temp$=SaveScreen$
IF WideNess% > 30 THEN CALL VPRINT(TopView%-1, RightView%-14, "^K-BCDKNPQRSWM", BorderAttr%,VideoRAM&)
Sound 1500,.5:Sound 2000,.5:Sound 2500,.5
DO : KK$ = IN.KEY$ : LOOP WHILE KK$=""
CALL RestoreScreen(Temp$)
KK$=UCASE$(KK$) ' **WORDSTAR**
SELECT CASE KK$
CASE "B" ' mark block begin ' **WORDSTAR**
BlockStart%=EditPtr%+Offset%+(CursorCol%-LeftView%)
IF BlockEnd%>BlockStart% THEN
SOUND 2500,.5:SOUND 3000,.5:SOUND 3500,.5
BLOCK$=MID$(ED$,BlockStart%,BlockEnd%-BlockStart%)
END IF
CASE "K" ' mark block end ' **WORDSTAR**
BlockEnd%=EditPtr%+Offset%+(CursorCol%-LeftView%)
IF BlockEnd%>BlockStart% THEN
SOUND 2500,.5:SOUND 3000,.5:SOUND 3500,.5
BLOCK$=MID$(ED$,BlockStart%,BlockEnd%-BlockStart%)
END IF
CASE "T" ' mark single word ' **WORDSTAR**
CASE "C" ' copy block ' **WORDSTAR**
IF LEN(BLOCK$) THEN
Character%=EditPtr%+Offset%+(CursorCol%-LeftView%)
ED$=LEFT$(ED$,Character%-1) + BLOCK$ + MID$(ED$,Character%)
BlockStart%=Character%:BlockEnd%=Character%+LEN(Block$)
END IF
CASE "V" ' move block ' **WORDSTAR**
IF LEN(BLOCK$) THEN
Character%=EditPtr%+Offset%+(CursorCol%-LeftView%)
' if cursor is before block then delete block first,
' then insert
IF Character% < BlockStart% THEN
ED$=LEFT$(ED$,BlockStart%-1) + MID$(ED$,BlockEnd%)
ED$=LEFT$(ED$,Character%-1) + BLOCK$ + MID$(ED$,Character%)
BlockStart%=Character%:BlockEnd%=Character%+LEN(Block$)
' otherwise if character is after block then insert
' block first then delete it.
ELSEIF Character% > BlockEnd% THEN
ED$=LEFT$(ED$,Character%-1) + BLOCK$ + MID$(ED$,Character%)
ED$=LEFT$(ED$,BlockStart%-1) + MID$(ED$,BlockEnd%)
BlockStart%=Character%:BlockEnd%=Character%+LEN(Block$)
END IF
END IF
CASE "Y" ' delete block ' **WORDSTAR**
ED$=LEFT$(ED$,BlockStart%-1) + MID$(ED$,BlockEnd%)
IF ED$="" THEN ED$=CHR$(13)+CHR$(10)
CASE "R" ' read block from file ' **WORDSTAR**
INF%=1
GOSUB INSERTFILE
CASE "W" ' write block to disk ' **WORDSTAR**
GOSUB SAVEAS
CASE "H" ' hide/display block ' **WORDSTAR**
CASE "P" ' print block ' **WORDSTAR**
IF BLOCK$="" THEN GOSUB PRINTALL ELSE _
LPRINT BLOCK$
CASE "D" ' save and exit ' **WORDSTAR**
GOSUB QUITSAVE
CASE "S" ' save ' **WORDSTAR**
GOSUB SAVE
CASE "Q" ' quit without saving ' **WORDSTAR**
ExitCode% = 27
CASE "N" ' set place marker ' **WORDSTAR**
CASE "M" ' Start Macro
LOCATE ,,0
IF Macro% THEN
Sound 3000,1:SOUND 2000,1:SOUND 1000,1
MESSAGE "PRESS ALT-M TO STOP RECORDING"
DELAY 1
RESTORESCREEN Temp$
ELSE
MESSAGE "Press ALT+key for Macro Record"
DO:M$=INKEY$:LOOP WHILE M$=""
RESTORESCREEN TEMP$
IF M$=CHR$(27) THEN EXIT SELECT
IF LEN(M$)=2 AND M$<>CHR$(0,50) THEN
Macro$=Macro$+CHR$(13,10)+"MACRO:"+M$
Macro%=-1
MESSAGE "BEGIN RECORDING. PRESS ALT-M TO FINISH"
Sound 1000,1:SOUND 2000,1:SOUND 3000,1
DELAY 2
ELSE
SOUND 50,1
MESSAGE "CANNOT USE THAT KEY"
DELAY 2
END IF
RESTORESCREEN TEMP$
END IF
CASE ELSE
END SELECT
Temp$=""
CASE CHR$(17) ' Control - Q
Temp$=SaveScreen$
IF Wideness% > 30 THEN CALL VPRINT(TopView%-1, RightView%-18, "^Q-SDEXRCBKPWLFAV", BorderAttr%,VideoRAM&)
Sound 1500,.5:Sound 2000,.5:Sound 2500,.5
DO : QQ$ = IN.KEY$ : LOOP WHILE QQ$=""
CALL RestoreScreen(Temp$)
SELECT CASE UCASE$(QQ$)
' Some of these we are going to ignore because
' they are pretty much useless.
'''CASE "S" 'move to beginning of line
' Use HOME and END instead
'''CASE "D" 'end of line ' **WORDSTAR**
'''CASE "E" 'top of window ' **WORDSTAR**
'''CASE "X" 'bottom of window ' **WORDSTAR**
'''CASE "R" 'top of file ' **WORDSTAR**
'''CASE "C" 'end of file ' **WORDSTAR**
CASE "B" 'beginning of block ' **WORDSTAR**
CASE "K" 'end of block ' **WORDSTAR**
CASE "P" 'last cursor position ' **WORDSTAR**
CASE "W" 'restore error message ' **WORDSTAR**
CASE "L" 'restore line ' **WORDSTAR**
CASE "F" 'search ' **WORDSTAR**
CASE "A" 'search and replace ' **WORDSTAR**
MESSAGE "SEARCH FOR ..."
SRCH$=PBWRITEEDITBOX$(SRCH$+SPACE$(25-LEN(SRCH$)),TextAttr%,BorderAttr%,VideoRAM&)
IF SRCH$="" THEN EXIT SELECT
MESSAGE "REPLACE WITH ..."
RPLC$=PBWRITEEDITBOX$(RPLC$+SPACE$(25-LEN(RPLC$)),TextAttr%,BorderAttr%,VideoRAM&)
IF RPLC$="" THEN EXIT SELECT
REPLACE SRCH$ WITH RPLC$ IN ED$
CASE "V" 'last cursor position ' **WORDSTAR**
CASE ELSE
END SELECT
RESTORESCREEN Temp$:Temp$=""
CASE CHR$(20) ' CTRL-T ' ** WORDSTAR**
' get current line, add to a string /1/2/3/4
Character%=EditPtr%+Offset%+(CursorCol%-LeftView%)
Temp%=(INSTR(Character%+1,ED$,ANY CHR$(32,10))+1)-Character%
SAVELINE$=MID$(ED$,Character%,temp%)+CHR$(1)+SAVELINE$
ED$=LEFT$(ED$,Character%-1) + MID$(ED$,Character%+Temp%)
IF ED$="" THEN ED$=CHR$(13)+CHR$(10)
CASE CHR$(25) ' CTRL-Y ' **WORDSTAR**
' get current line, add to a string /1/2/3/4
SAVELINE$=MID$(ED$,EditPtr%,EditEol%-EditPtr%)+CHR$(13)+CHR$(10)+CHR$(1)+SAVELINE$
ED$=LEFT$(ED$,EditPtr%-1) + MID$(ED$,EditEol%+2)
IF ED$="" THEN ED$=CHR$(13)+CHR$(10)
CASE CHR$(21) ' CTRL-U ' **WORDSTAR**
' restore leftmost line in /1/2/3/4
IF LEN(SAVELINE$) THEN
TEMP$=EXTRACT$(SAVELINE$,CHR$(1))
IF SAVELINE$=TEMP$+CHR$(1) THEN SAVELINE$="" ELSE _
SAVELINE$=MID$(SAVELINE$,INSTR(SAVELINE$,CHR$(1))+1)
Character%=EditPtr%+Offset%+(CursorCol%-LeftView%)
ED$=LEFT$(ED$,Character%-1) + TEMP$ + MID$(ED$,Character%)
END IF
CASE CHR$(4) ' CTRL-D ... Erase document in memory
GOSUB CLEARALL
CASE CHR$(7) ' CTRL-G ... Change Margin%
Temp$=SAVESCREEN$
ChangeMargin:
MESSAGE "CHANGE MARGIN TO ..."
Margin$=STR$(Margin%)+" "
Margin$=PBWRITEEDITBOX$(Margin$,TextAttr%,BorderAttr%,VideoRAM&)
IF VAL(Margin$)<15 and VAL(Margin$) > 4096 THEN
SOUND 50,2
MESSAGE "BE REASONABLE"
DELAY 2
Restorescreen Temp$
GOTO ChangeMargin
END IF
IF Margin$<>"" THEN
Margin%=VAL(Margin$)
REDIM Temp$(5)
Temp$(1)="reformat on double carriage return"
Temp$(2)="reformat, preserve carriage returns"
Temp$(3)="continue with new margin, no change"
SELECT CASE POPMENU(Temp$())
CASE 1
REPLACE CHR$(13,10,13,10) WITH CHR$(13,13) IN ED$
REPLACE CHR$(32,13,10) WITH " " IN ED$
REPLACE CHR$(13,10) WITH " " IN ED$
KEYIN ED$
ED$=CrLf$
Ptr%=1:Offset%=0:CursorRow%=0:CursorCol%=0
IF CursorRow% < TopView% THEN CursorRow% = TopView%
IF CursorRow% > BottomView% THEN CursorRow% = BottomView%
IF CursorCol% < LeftView% THEN CursorCol% = LeftView%
IF CursorCol% > RightView% THEN CursorCol% = RightView%
CASE 2
REPLACE CHR$(13,10) WITH CHR$(13) IN ED$
KEYIN ED$
ED$=CrLf$
Ptr%=1:Offset%=0:CursorRow%=0:CursorCol%=0
IF CursorRow% < TopView% THEN CursorRow% = TopView%
IF CursorRow% > BottomView% THEN CursorRow% = BottomView%
IF CursorCol% < LeftView% THEN CursorCol% = LeftView%
IF CursorCol% > RightView% THEN CursorCol% = RightView%
CASE 3
END SELECT
END IF
RESTORESCREEN Temp$:Temp$=""
CASE CHR$(0,59) ' F1
ExitCode%=59 ' exit for help? <--------------+
CASE CHR$(0,60) ' F2 |
GOSUB SAVE ' F2 = save |
CASE CHR$(0,61) ' F3 |
GOSUB LOADNEW ' F3 = load new |
CASE CHR$(0,62) ' F4 |
GOSUB PRINTALL ' F4 = Print |
' F5 - zoom (handled elsewhere) |
CASE CHR$(0,64) ' F6 '\ |
ExitCode% = 64 ' \ |
CASE CHR$(0,65) ' F7 ' \ |
ExitCode% = 65 ' \ |
CASE CHR$(0,66) ' F8 ' \ V
ExitCode% = 66 ' \
CASE CHR$(0,67) ' F9 ' \
ExitCode% = 67 ' \
CASE CHR$(0,68) ' F10 ' Keys that make you exit
ExitCode% = 68 ' /
' /
CASE CHR$(27) ' ESC exit ' /
ExitCode%=27 ' /
' /
CASE CHR$(0,16) ' ALT-Q ' /
ExitCode%=16 ' /
'
CASE CHR$(0,45) ' ALT-X '
ExitCode%=45 '
CASE CHR$(0,&H50) 'dn arrow ' ** NAVIGATION **
IF CursorRow% < BottomView% THEN
INCR CursorRow%
ELSE
GOSUB GODOWN
END IF
CASE CHR$(0,&H48) 'up arrow ' ** NAVIGATION **
IF CursorRow% > TopView% THEN
DECR CursorRow%
ELSE
GOSUB GOUP
END IF
CASE CHR$(0,&H4F) ' end ' ** NAVIGATION **
CursorCol% = LeftView%+LenEditLine%+1
IF CursorCol% > RightView% THEN CursorCol% = RightView%-1:_
Offset%=(LenEditLine%-RightView%)+LeftView%+1
CASE CHR$(0,&H47) 'home ' ** NAVIGATION **
IF CursorCol% > LeftView% or Offset% THEN
Offset% = 0
CursorCol%=LeftView%
ELSE
CursorCol%=LeftView%
CursorRow%=TopView%
Ptr% = 1
END IF
CASE CHR$(0, &H4D) ' right arrow ' ** NAVIGATION **
IF CursorCol% < RightView%-1 THEN
INCR CursorCol%
ELSE
GOSUB GORIGHT
END IF
CASE CHR$(0,&H4B) ' left arrow ' ** NAVIGATION **
IF CursorCol% > LeftView% THEN
DECR CursorCol%
ELSE
GOSUB GOLEFT
END IF
CASE CHR$(0,&H51) ' page down ' ** NAVIGATION **
if LastLine%=0 THEN GOSUB PAGEDOWN
CASE CHR$(0, &H49) ' page up ' ** NAVIGATION **
GOSUB PAGEUP
CASE CHR$(0,63) ' F5 Zoom ' ** ZOOM/UNZOOM **
If Zoom% THEN
Zoom%=0
TopView% = OldTopView%
LeftView% = OldLeftView%
BottomView% = OldBottomView% ' ** ZOOM/UNZOOM **
RightView% = OldRightView%
WideNess%=RightView%-LeftView%
CursorRow% =CursorRow% + (Topview%-2)
CursorCol% =CursorCol% + (LeftView%-1)
IF CursorCol% > RightView% THEN _ ' ** ZOOM/UNZOOM **
OffSet%= CursorCol%-RightView%:_
CursorCol%=RightView%
CALL RestoreScreen(Z$)
DO
IF CursorRow%>BottomView% THEN
GOSUB GODOWN ' ** ZOOM/UNZOOM **
DECR CursorRow%
ELSE
EXIT LOOP
END IF
LOOP
ELSE ' ** ZOOM/UNZOOM **
Zoom%=-1
CursorRow% =CursorRow% - (Topview%-3)
CursorCol% =CursorCol% - (LeftView%-2)
OldTopView%=TopView%
OldLeftView%=LeftView%
OldRightView%=RightView% ' ** ZOOM/UNZOOM **
OldBottomView%=BottomView%
TopView%=2
LeftView%=1
BottomView%=24
RightView%=81 ' ** ZOOM/UNZOOM **
WideNess%=RightView%-LeftView%
CursorRow% =CursorRow% - (Topview%-1)
CursorCol% =CursorCol% - LeftView%
Z$=SaveScreen$
LOCATE 2,1
PRINT Space$(80*23); ' ** ZOOM/UNZOOM **
END IF
CASE ELSE ' ** ZOOM/UNZOOM **
END SELECT
LOOP WHILE ExitCode%=0 ' ** END MAIN CODE
IF RedrawPatch% THEN EXIT SUB
If Zoom% THEN ' ** FORCE UNZOOM ON EXIT
Zoom%=0
TopView% = OldTopView%
LeftView% = OldLeftView%
BottomView% = OldBottomView%
RightView% = OldRightView%
WideNess%=RightView%-LeftView%
CursorRow% =CursorRow% + (Topview%-2)
CursorCol% =CursorCol% + (LeftView%-1)
IF CursorCol% > RightView% THEN _
OffSet%= CursorCol%-RightView%:_
CursorCol%=RightView%
CALL RestoreScreen(Z$)
DO
IF CursorRow%>BottomView% THEN
GOSUB GODOWN
DECR CursorRow%
ELSE
EXIT LOOP
END IF
LOOP
RedrawPatch%=-1:RedrawExit%=-1 ' redraw on UNZOOM/flags exit correctly
GOTO RedrawAndExit
END IF
EXIT SUB
' document animation routines ' ** ANIMATE
GODOWN: 'CASE CHR$(0,&H50) 'dn arrow
IF TempPtr% < LEN(ED$) THEN
Ptr%=Instr(Ptr%, ED$, Chr$(13) ) + 2
ELSE
Sound 100,.1 ' we are at the end
END IF
RETURN
GOUP: 'CASE CHR$(0,&H48) 'up arrow ' ** ANIMATE
IF Ptr% > 1 THEN
' search backwards for a CR or 1
DECR Ptr%:IF Ptr%>1 then DECR Ptr%
DO:DECR Ptr%:LOOP UNTIL Mid$(ED$, Ptr%, 1)=CHR$(13) OR Ptr%=1
IF Ptr%>1 THEN INCR Ptr%:INCR Ptr%
ELSE
Sound 100,.1 ' we are at the beginning
END IF
RETURN ' ** ANIMATE
GOHOME: 'CASE CHR$(0,&H47) 'home
If Offset% THEN Offset% = 0 ELSE Ptr%=1
RETURN
GORIGHT: 'CASE CHR$(0, &H4D) ' right arrow ' ** ANIMATE
INCR Offset%
RETURN
GOLEFT: 'CASE CHR$(0,&H4B) ' left arrow
If Offset% THEN DECR Offset% ' ** ANIMATE
RETURN
PAGEDOWN: 'CASE CHR$(0,&H51) ' page down
FOR pd = TopView% to BottomView%-1 ' ** ANIMATE
OldPtr%=Ptr%
Ptr%=Instr(Ptr%, ED$, Chr$(13) ) + 2
if Ptr%=2 then Ptr%=OldPtr%:Exit FOR
Next Pd
RETURN
PAGEUP: 'CASE CHR$(0, &H49) ' page up ' ** ANIMATE
FOR pd = TopView% to BottomView% -1
IF Ptr% > 1 THEN
' search backwards for a CR or 1
DECR Ptr%:IF Ptr%>1 then DECR Ptr%
DO:DECR Ptr%:LOOP UNTIL Mid$(ED$, Ptr%, 1)=CHR$(13) OR Ptr%=1
IF Ptr%>1 THEN INCR Ptr%:INCR Ptr%
ELSE
EXIT FOR
END IF
NEXT Pd
RETURN
REDRAW:
IF NOT Zoom% THEN Call PBWriteBox(TopView%-1, LeftView%-1, BottomView%+1, RightView%, BorderAttr%,VideoRAM&)
IF CursorRow% < TopView% THEN CursorRow% = TopView%
IF CursorRow% > BottomView% THEN CursorRow% = BottomView%
'Make sure the cursor is within the effective window
IF CursorCol% < LeftView% THEN CursorCol% = LeftView%
IF CursorCol% > RightView% THEN CursorCol% = RightView%
IF WideNess% > 20 THEN
IF Zoom% THEN a%= 25:b%=1 ELSE a%=BottomView%+1: b%=LeftView%+3
IF I1% THEN Stat$= "(Ins)" ELSE Stat$= "(Ovr)"
IF C1% THEN Stat$=Stat$+ "(Caps)" ELSE Stat$=Stat$+ "(Norm)"
IF N1% THEN Stat$=Stat$+ "(Num)" ELSE Stat$=Stat$+ "(Pad)"
IF S1% THEN Stat$=Stat$+ "(ScLk)" ELSE Stat$=Stat$+"(Edit)"
CALL VPRINT(a%,b%,Stat$,BorderAttr%,VideoRAM&)
END IF
If len(Title$) THEN CALL VPRINT(TopView%-1, LeftView%+1,"["+Title$+"]",BorderAttr%,VideoRAM&)
' starting byte for view (1 is top of file)
If Ptr%=0 then Ptr%=1
' Draw the screen
TempPtr% = Ptr% : Temp% = TopView%
DO
eol% = Instr(Mid$(ED$,TempPtr%),Chr$(13))
if eol%=0 then eol%=LEN(ED$) ELSE DECR eol% ' DECR: do not show the CR
IF Eol%=TempPtr% THEN Curr$="" ELSE Curr$ = Mid$(ED$, TempPtr%,eol%)
IF Temp%=CursorRow% THEN EditLine$=Curr$:EditPtr%=TempPtr%
Locate Temp%, LeftView%
CALL VPRINT(Temp%,LeftView%, Mid$(Curr$+Space$(WideNess%+Offset%), 1+Offset%,WideNess%),TextAttr%,VideoRAM&)
TempPtr% = Instr(TempPtr%, ED$, Chr$(13)) + 2 ' +2 for CRLF pair
If TempPtr%=2 Then TempPtr%=LEN(ED$)
INCR Temp%
if Temp% > BottomView% THEN Exit LOOP
LOOP
RETURN
SAVE:
GOSUB SAVEAS
RETURN
SAVEAS:
Temp$=SaveScreen$
d$=Title$+SPACE$(40):d$=LEFT$(d$,40)
Fi$=PBWriteEditBox$(d$,TextAttr%,BorderAttr%,VideoRAM&)
CALL RestoreScreen(Temp$)
Temp$=""
if len(Fi$) and Fi$<> CHR$(27) THEN
fi%=FREEFILE
OPEN Fi$ FOR OUTPUT AS #fi%
PRINT #fi%,ED$;
CLOSE #Fi%
NoSave%=0
Title$=Fi$
END IF
RETURN ' saveas
QUITSAVE:
GOSUB SAVEAS
IF Fi$<>CHR$(27) THEN ExitCode%=1
RETURN ' quitsave
PRINTALL:
O2$=SAVESCREEN$
redim temp$(4)
temp$(1)="LPT1:"
temp$(2)="LPT2:"
temp$(3)="LPT3:"
LPT%=POPMENU(temp$()):IF LPT%=0 THEN GOTO DonePrinting
' You can define one of the exit keys, say F7, as a "mail merge"
' key in which ED$ can be copied to a temporary string and
' then using the REPLACE .. WITH statement mailmerge fields
' can be replaced with memory variables or database fields.
RESTORESCREEN O2$
for i%=1 to len(ED$)
a%=val(mid$(ch$,i%,1))
reg 1, &h00+a
reg 4,LPT%
call Interrupt &h17
pstat%=REG(1)
if (pstat% and 32)= 32 then ERROR 27:EXIT FOR ' "Out of Paper"
if (pstat% and 8)= 8 then ERROR 57:EXIT FOR ' "I/O Error"
if (pstat% and 1)= 1 then ERROR 24:EXIT FOR ' "Printer Time Out"
next i%
DonePrinting:
RESTORESCREEN O2$
SOUND 5000,.5:SOUND 1000,.5
RETURN ' printall
CLEARALL:
IF NoSave% THEN
O2$=SAVESCREEN$
a% = YesOrNo("Save " + Title$, TextAttr%, BorderAttr%, VideoRAM&)
RESTORESCREEN O2$
if A%=1 THEN
GOSUB SAVEAS
IF Fi$=CHR$(27) THEN RETURN
END IF
END IF
if a%<>27 THEN
Title$="NONAME.TXT"
ED$=CrLf$
Ptr%=1:Offset%=0:CursorRow%=0:CursorCol%=0
IF CursorRow% < TopView% THEN CursorRow% = TopView%
IF CursorRow% > BottomView% THEN CursorRow% = BottomView%
'Make sure the cursor is within the effective window
IF CursorCol% < LeftView% THEN CursorCol% = LeftView%
IF CursorCol% > RightView% THEN CursorCol% = RightView%
END IF
Call VPrint (TopView%-1, LeftView%+1,String$(RightView%-LeftView%-1,205),BorderAttr%,VideoRAM&)
CALL VPRINT(TopView%-1, LeftView%+1,"["+Title$+"]",BorderAttr%,VideoRAM&)
RETURN ' Clear all
LOADNEW:
IF NoSave% THEN
O2$=SAVESCREEN$
a% = YesOrNo("Save " + Title$, TextAttr%, BorderAttr%, VideoRAM&)
RESTORESCREEN O2$
if A%=1 THEN
GOSUB SAVEAS
IF Fi$=CHR$(27) THEN RETURN
END IF
END IF
INSERTFILE:
if a%<>27 or INF%=1 THEN
d$=Left$(CurDir$+"\"+Space$(40),40)
'Temp2$=SaveScreen$
O2$=SAVESCREEN$
Fi$=PBWriteEditBox$(D$, TextAttr%,BorderAttr%, VideoRAM&)
RESTORESCREEN O2$
IF Fi$="" or Fi$=chr$(27) THEN RETURN
DO
IF RIGHT$(Fi$,1)="\" OR INSTR(Fi$,"?") OR INSTR(Fi$,"*") OR INSTR(Fi$,"..") THEN
CD$ = Fi$
' get the specified directory
DO UNTIL RIGHT$(CD$,1)="\" OR RIGHT$(CD$,1)=":" OR CD$=""
CD$=LEFT$(CD$,LEN(CD$)-1)
LOOP
REDIM FL$(500)
i% = 1
fl$(i%) = DIR$(Fi$) '............... get directory into an array
DO
INCR i%
FL$(i%) = DIR$
IF i%=499 THEN EXIT LOOP
LOOP WHILE FL$(i%) <> ""
ARRAY SORT fl$() FOR i%
Fi$=FileBox$( Fl$() )
IF INF%=0 THEN Title$=Fi$
ELSE
EXIT LOOP
END IF
LOOP
IF Fi$ <> "" THEN
Fi%=FREEFILE
IF INSTR(Fi$,"\")=0 THEN Fi$=CD$+Fi$
OPEN Fi$ FOR BINARY AS #fi%
IF LOF(Fi%) > 32700 THEN
CLOSE #Fi%
ERROR 700 ' file to big
ELSE
O2$=SAVESCREEN$
MESSAGE "GETTING..."
IF INF%=1 THEN
GET$ Fi%, LOF(Fi%),BLOCK$
INF%=0
CALL ExpandTabs(BLOCK$)
ELSE
GET$ Fi%, LOF(Fi%), ED$
CALL ExpandTabs(ED$)
IF ED$="" THEN ED$=" "+CHR$(13) + CHR$(10)
END IF
RESTORESCREEN O2$
CLOSE #fi%
END IF
END IF
Ptr%=1:Offset%=0:CursorRow%=0:CursorCol%=0
IF CursorRow% < TopView% THEN CursorRow% = TopView%
IF CursorRow% > BottomView% THEN CursorRow% = BottomView%
'Make sure the cursor is within the effective window
IF CursorCol% < LeftView% THEN CursorCol% = LeftView%
IF CursorCol% > RightView% THEN CursorCol% = RightView%
END IF
'Title$ = Fl$(i%)
Call VPrint (TopView%-1, LeftView%+1,String$(RightView%-LeftView%-1,205),BorderAttr%,VideoRAM&)
CALL VPRINT(TopView%-1, LeftView%+1,"["+Title$+"]",BorderAttr%,VideoRAM&)
RETURN ' loadnew
PBWriteError:
O3$=SAVESCREEN$
SELECT CASE ERR
CASE 6
MESSAGE "OVERFLOW"
CASE 7
MESSAGE "OUT OF MEMORY"
CASE 9
MESSAGE "SEGMENT OR STACK EXPIRED"
CASE 11
MESSAGE "DIVIDE BY 0"
CASE 14
MESSAGE "OUT OF VARIABLE SPACE"
CASE 24
MESSAGE "DEVICE TIMEOUT"
CASE 25
MESSAGE "DEVICE FAULT"
CASE 27
MESSAGE "NO PAPER"
CASE 52
MESSAGE "IMPROPER FILE LOGIC"
CASE 53
MESSAGE "FILE NOT ACCESSABLE"
CASE 54
MESSAGE "BAD FILE MODE"
CASE 55
MESSAGE "FILE IS OPEN"
CASE 57
MESSAGE "DEVICE I/O"
CASE 61
MESSAGE "DISK IS FULL"
CASE 62
MESSAGE "UNEXPECTED END OF FILE"
CASE 64
MESSAGE "BAD FILE NAME"
CASE 68
MESSAGE "DEVICE UNNAVAILABLE"
CASE 70
MESSAGE "FILE LOCK"
CASE 71
MESSAGE "DISK IS NOT READY"
CASE 72
MESSAGE "DISK MEDIA ERROR"
CASE 75
MESSAGE "BAD PATH/FILE"
CASE 76
MESSAGE "PATH NOT FOUND"
CASE 5
MESSAGE "ILLEGAL FUNCTION CALL"
CASE 58
MESSAGE "FILE EXISTS"
CASE 67
MESSAGE "TOO MANY FILES OPEN"
CASE 73
MESSAGE "ADVANCED FEATURE UNNAVAILABLE"
CASE 74
MESSAGE "RENAME ACROSS DISKS"
CASE 700
MESSAGE "FILE EXCEEDS 32K"
CASE ELSE
MESSAGE "ERROR"+STR$(ERR)+" AT PGM-CTR"+STR$(ERADR)
END SELECT
SOUND 50,5
DO:LOOP WHILE INKEY$=""
''''STOP '*****************************************************************
RESTORESCREEN O3$
RESUME NEXT
END SUB
' *** LINE FEED
SUB SingleBox (Wa%, Wb%, Wc%, Wd%)
REG 1, 15*256
CALL INTERRUPT &H10
IF Reg(1) - (Reg(1)\256) * 256 = 7 THEN Address&=&HB000 else Address&=&HB800
DEF SEG = ADDRESS&
LOCATE Wa%, Wb%: PRINT CHR$(213) + STRING$((Wd% - Wb%) - 1, 205) + CHR$(184)
LOCATE Wc%, Wb%: PRINT CHR$(212) + STRING$((Wd% - Wb%) - 1, 205) + CHR$(190)
FOR zxy% = 1 TO Wc% - Wa% - 1
LOCATE Wa% + zxy%, Wb%
PRINT CHR$(179) + SPACE$((Wd% - Wb%) - 1) + CHR$(179)
' right side of the box is Wa+zxy *80 + Wd + 1
' stuff an attribute into there
POKE ( (Wa%+Zxy%) * 160 ) + (Wd%*2) + 1,8
NEXT zxy%
for i%=(Wc% * 160) + ((wb%+2)*2)-1 TO (Wc%*160) + ((Wd%*2)+2)-1 STEP 2
' What this does is calculate the memory locations of the characters
' in video ram
POKE i%, 8
Next i%
DEF SEG
END SUB
FUNCTION PopMenu(item$())
' Center a scrolling menu on the screen containing options in Item$()
' This function returns the number of the selected item, or 0 if ESC pressed.
MenWid=0:MenHi=0
DO:MenHi=MenHi+1:IF LEN(Item$(MenHi))>MenWid then MenWid=LEN(Item$(MenHi))
LOOP WHILE LEN(Item$(MenHi))
MenHi=MenHi:MenWid=MenWid+4
' Menu box is MenHi x MenWid
wa% = 12 - (MenHi\2)
wb% = 40 - (MenWid\2)
wc% = wa% + MenHi
wd% = wb% + MenWid
COLOR 0,7
CALL SingleBox(Wa%,Wb%,Wc%,Wd%)
For y=1 to MenHi-1
Locate 12 - (MenHi\2) + y, 42 - (MenWid\2):Print Item$(y)
Next y
PopMe=1
DO
Locate 12 - (MenHi\2) + PopMe,42-(MenWid\2)
Color 7,0 : Print Item$(PopMe) : Color 0,7
do:a$ = IN.KEY$:loop while a$=""
If Len(a$) = 2 THEN a=asc(right$(a$,1)) else a=asc(a$)
SELECT CASE a
CASE &H48 ' up arrow
Locate 12 - (MenHi\2) + PopMe,42-(MenWid\2)
Print Item$(PopMe)
PopMe=PopMe-1
If PopMe = 0 then PopMe = 1
CASE &H50 ' dn arrow
Locate 12 - (MenHi\2) + PopMe,42-(MenWid\2)
Print Item$(PopMe)
PopMe=PopMe+1
If PopMe = MenHi then PopMe = MenHi - 1
CASE &H47 ' home
Locate 12 - (MenHi\2) + PopMe,42-(MenWid\2)
Print Item$(PopMe)
PopMe=1
CASE &H4D ' right arrow ........ it could happen
CASE &H4B ' left arrow
' these keys might indicate that the
' user wants to move horizontally to
' another menu. See CASEKEYS.BAS for
' a generic keyboard polling CASE struct
CASE &H51, &H4F ' page down or END
Locate 12 - (MenHi\2) + PopMe,42-(MenWid\2)
Print Item$(PopMe)
PopMe=MenHi-1
CASE &H49 ' page up
Locate 12 - (MenHi\2) + PopMe,42-(MenWid\2)
Print Item$(PopMe)
PopMe=1
CASE 27 ' escape
PopMenu=0 : Exit Loop
CASE 13
PopMenu=PopMe : Exit Loop
CASE ELSE
END SELECT
loop
END FUNCTION
FUNCTION SaveScreen$
REG 1, 15*256
CALL INTERRUPT &H10
IF Reg(1) - (Reg(1)\256) * 256 = 7 THEN Address=&HB000 else Address=&HB800
DEF SEG = ADDRESS
SaveScreen$=PEEK$(0,4000)
DEF SEG
END FUNCTION
SUB RestoreScreen(S$)
REG 1, 15*256
CALL INTERRUPT &H10
IF Reg(1) - (Reg(1)\256) * 256 = 7 THEN Address=&HB000 else Address=&HB800
DEF SEG = Address
POKE$ 0, S$
DEF SEG
END SUB
$IF 0
ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
ÛßÛ Û Û ÛßÝ ÛßÛ ÛßÛ Û Û ßÛß Û ÛÝÞ Ûßß
ßþÜ Û Û ÛßÛ ÛßÝ Û Û Û Û Û Û ÛÛÛ Ûß
ÛÜÛ ÛÜÛ ÛÜÛ Û Û ÛÜÛ ÛÜÛ Û Û ÝÞÛ ÛÜÜ
ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
VPRINT - writes directly to video
ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
$ENDIF
SUB VPrint(BYVAL Row%,BYVAL Col%,BYVAL St$, BYVAL Att%, Byval VideoRAM&)
! push si ; Save em
! push di ;
! push ds ;
! mov ax,St$ ; get the handle
! push ax ; push it
! call getstrloc ; Get String info
! mov ds,dx ; Set the string seg
! mov si,ax ; set string ptr
! cmp cx,0 ; Quit if string = 0
! je Done ;
! xor ax,ax ;
! mov ax,Row% ; get the row
! dec al ; convert row to zero base
! mov bl,80 ; get the number of cols
! mul bl ; multiply # of cols * rows
! add ax,Col% ; add the column
! dec al ; convert column to zero base
! mov di,ax ; offset within video page
! shl di,1 ; account for color/attribute
! mov ax,VideoRAM& ; ' default to mono card segment
Display:
! mov es,ax ; point ES to video
! mov ax,Att% ; color/attribute
! mov ah,al
Printit:
! lodsb ; get a char into al
! stosw ; write char and attr to screen
! loop Printit ; go for entire string
Done: ' (len\counter already in cx)
! pop ds ; pop em
! pop di ;
! pop si ;
END SUB
' *** LINE FEED
$IF 0
ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
ÛßÛ Û Û ÛßÝ ÛßÛ ÛßÛ Û Û ßÛß Û ÛÝÞ Ûßß
ßþÜ Û Û ÛßÛ ÛßÝ Û Û Û Û Û Û ÛÛÛ Ûß
ÛÜÛ ÛÜÛ ÛÜÛ Û Û ÛÜÛ ÛÜÛ Û Û ÝÞÛ ÛÜÜ
ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
EXPANDTABS - remove TABS from doc
ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
Special thanks to Mel Bishop for this routine!
$ENDIF
SUB ExpandTabs(Msg$)
REM *******************************************************
REM * Might as well convert Word-Star extended characters *
REM * into normal ASCII characters here as well. *
REM *******************************************************
crlf$=chr$(13)+chr$(10)
' We want to leave high ascii graf chars the same. It saves time too.
' for x=128 to 255 'Might as well convert
' replace chr$(x) with chr$(x-128) in Msg$ 'Word Star extended
' next x 'characters.
msg$=remove$(msg$,chr$(10)) 'Temporary remove line feeds from
temp$="" 'string. Leave C/R's for INSTR.
do 'Set the master loop
if msg$="" then exit loop 'If no more string to process,
'perform a grand exit
p=instr(msg$,chr$(13)) 'Find a C/R in the string.
if p=0 then 'If no C/R in string, reassign entire
te$=msg$ 'remaining string to be processed
msg$="" 'and null out the main string
else
te$=left$(msg$,p) 'Other wise, strip off the left hand
tm$=right$(msg$,len(msg$)-p) 'portion of the string for processing
msg$=tm$ 'and rid it from the main string.
tm$=""
end if
te$=remove$(te$,chr$(13)) 'Remove the C/R from string.
do
t1$="":t2$=""
p=instr(te$,chr$(9)) 'Find a TAB in the sub-string
if p=0 then exit loop 'If none present, whole line done.
t1$=left$(te$,p-1) 'Split the process string into 2
t2$=right$(te$,len(te$)-p) 'sub-strings with TAB as delimiter.
'NOTE: (p) points to the TAB character
'in t1$ so use p-1 to avoid it.
t1$ = t1$ + " " 'Add a space to replace the lost TAB
do until len(t1$)/8=int(len(t1$)/8) 'Lengthen to a multiple of 8
t1$ = t1$ + " "
loop
te$ = t1$ + t2$ 'Concanotate original string with the
loop 'added spaces & loop for more TAB's
temp$=temp$+te$+crlf$ 'Build temporary holding string
loop 'and loop back for next line.
msg$=temp$ 'Reassign the temporary hold string to
'the string being called
temp$="" 'and null out temp strings for memory
t1$="" 'management.
t2$=""
te$="" 'fini
END SUB
' *** LINE FEED
$IF 0
ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
ÛßÛ Û Û ÛßÝ ÛßÛ ÛßÛ Û Û ßÛß Û ÛÝÞ Ûßß
ßþÜ Û Û ÛßÛ ÛßÝ Û Û Û Û Û Û ÛÛÛ Ûß
ÛÜÛ ÛÜÛ ÛÜÛ Û Û ÛÜÛ ÛÜÛ Û Û ÝÞÛ ÛÜÜ
ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
SINGLEBOX - draws a box on the screen
ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
$ENDIF
SUB PBWriteBox (Wa%, Wb%, Wc%, Wd%,Attr%,VideoRAM&)
DEF SEG=VideoRAM&
CALL VPRINT(Wa%,Wb%,CHR$(213) + STRING$((Wd% - Wb%) - 1, 205) + CHR$(184),Attr%,VideoRAM&)
CALL VPRINT(Wc%,Wb%,CHR$(212) + STRING$((Wd% - Wb%) - 1, 205) + CHR$(190),Attr%,VideoRAM&)
FOR zxy% = 1 TO Wc% - Wa% - 1
CALL VPRINT(Wa%+Zxy%,Wb%,CHR$(179),Attr%,VideoRAM&)
CALL VPRINT(Wa%+Zxy%,Wd%,CHR$(179),Attr%,VideoRAM&)
' right side of the box is Wa+zxy *80 + Wd + 1
' stuff an attribute into there
POKE ( (Wa%+Zxy%) * 160 ) + (Wd%*2) + 1,8
NEXT zxy%
for i%=(Wc% * 160) + ((wb%+2)*2)-1 TO (Wc%*160) + ((Wd%*2)+2)-1 STEP 2
POKE i%, 8
Next i%
DEF SEG
END SUB
' *** LINE FEED
$IF 0
ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
Ûßß Û Û ÛÝÞ Ûßß ßÛß Û ÛßÛ ÛÝÞ Û Û
Ûß Û Û ÛÛÛ Û Û Û Û Û ÛÛÛ ÞÝ ÞÝ
Û ÛÜÛ ÝÞÛ ÛÜÜ Û Û ÛÜÛ ÝÞÛ Û Û
ÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜÜ
PBWRITEEDITBOX - pop up input box
ßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßßß
$ENDIF
FUNCTION PBWriteEditBox$(Default$, TAttr%, BAttr%, VideoRAM&)
COLOR 0,7
CALL PBWriteBox(9, 28-(LEN(Default$)\2), 11, 32+(LEN(Default$)\2), Battr%, VideoRAM&)
y% = 30 - (LEN(Default$) \ 2) : YY%=0
yy%=LEN(RTRIM$(default$))
DO
CALL VPRINT(10, y%-1, " " + Default$+" ", Tattr%,VideoRAM&)
LOCATE 10,Y%+yy%,1
DO:Scratch$=IN.KEY$:LOOP WHILE LEN(Scratch$)=0
IF LEN(Scratch$) THEN
SELECT CASE(Scratch$)
CASE CHR$(27), CHR$(13)
EXIT SELECT
CASE CHR$(8)
IF YY% THEN
YY%=YY%-1
IF YY% THEN
Default$=LEFT$(Default$,yy%)+MID$(Default$,yy%+2) + " "
ELSE
Default$=MID$(Default$,yy%+2) + " "
END IF
END IF
CASE CHR$(0)+CHR$(83)
IF YY% THEN
Default$=LEFT$(Default$,yy%)+MID$(Default$,yy%+2) + " "
ELSE
Default$=MID$(Default$,yy%+2) + " "
END IF
CASE CHR$(0)+CHR$(&H4D)
IF YY% < LEN(Default$) THEN INCR YY%
CASE CHR$(0)+CHR$(&H4B)
IF YY% THEN DECR YY%
CASE CHR$(0)+CHR$(79) 'end
yy%=LEN(RTRIM$(default$))
CASE CHR$(0)+CHR$(71)
yy%=0
CASE ELSE
IF LEN(Scratch$)=1 and YY%=0 THEN Default$=SPACE$(LEN(default$))
IF LEN(Scratch$)=1 and YY% < LEN(Default$) THEN_
MID$(Default$,YY%+1,1) = Scratch$ : YY%=YY%+1
END SELECT
IF Scratch$=CHR$(27) THEN PBWriteEditBox$=CHR$(27):EXIT LOOP
IF Scratch$=CHR$(13) THEN PBWriteEditBox$=RTRIM$(Default$):EXIT LOOP
END IF
LOOP
END FUNCTION
FUNCTION FileBox$( ListArray$() )
O$=SAVESCREEN$
' The last element of the list in the array has to be blank.
' calculate how wide to make the window
Yy%=0
DO
INCR Yy%
IF LEN(ListArray$(Yy%)) > MaxLen% THEN MaxLen%=LEN(ListArray$(Yy%))
IF LEN(ListArray$(Yy%)) = 0 THEN ListLen%=Yy%: EXIT LOOP
LOOP
WinTop%=5:WinLeft%=38-(MaxLen%\2):WinRight%=43+(MaxLen%\2)
WinBot% = (WinTop% + Yy%)-1:If WinBot% > 20 THEN WinBot% = 20
COLOR 0,7
Call SingleBox(WinTop%, WinLeft%, WinBot%, WinRight%)
TopLine% = 0 ' the first element to appear inside the box
PickLine% = 1 ' the offset box line you are pointing at
DO ' Main loop start
For Yy% = WinTop% + 1 TO WinBot%-1
Locate Yy%, WinLeft%+1
IF Yy% = WinTop% + PickLine% THEN COLOR 7,0 ELSE COLOR 0,7
PRINT " " + ListArray$(Yy%-WinTop%+TopLine%) + SPACE$(MaxLen%-LEN(ListArray$(Yy%-WinTop%+TopLine%))+2)
Next Yy%
DO:A$=IN.KEY$:LOOP WHILE A$=""
Pick:
SELECT CASE A$
CASE CHR$(0,&H48) 'up arrow
DECR PickLine%
CASE CHR$(0,&H50) 'dn arrow
INCR PickLine%
CASE CHR$(0,&H4B) 'rt arrow
CASE CHR$(0,&H4D) 'lf arrow
CASE CHR$(0,&H47) 'home
PickLine%=1
CASE CHR$(0,&H4F) 'end
PickLine%=WinBot%-WinTop%-1
CASE CHR$(0,&H49) 'page up
if PickLine%=1 then_
TopLine%=TopLine%-(WinBot%-winTop%)+2 else_
PickLine%=1
CASE CHR$(0,&H51) 'page dn
If PickLine%=WinBot%-WinTop%-1 THEN_
TopLine%=TopLine%+(WinBot%-WinTop%)-2 else_
PickLine%=WinBot%-WinTop%-1
CASE CHR$(0,82) ' insert
CASE CHR$(0,119) 'ctrl home
CASE CHR$(0,117) 'ctrl end
CASE CHR$(0,132) 'ctrl pgup
CASE CHR$(0,118) 'ctrl pgdn
CASE CHR$(27) ' Escape ESC
CASE ELSE
END SELECT
if A$=CHR$(27) then FileBox$="":RESTORESCREEN O$:EXIT FUNCTION
if A$=CHR$(13) then FileBox$=ListArray$(TopLine%+PickLine%):RESTORESCREEN O$:EXIT FUNCTION
if PickLine%<1 then PickLine%=1:DECR TopLine%
if topLine%<0 then TopLine%=0:PickLine%=1:sound 1500,.1
if PickLine%=>WinBot%-WinTop% then PickLine%=WinBot%-WinTop%-1:INCR TopLine%
if TopLine% > ListLen% - (Winbot%-WinTop%) then TopLine%=ListLen%-(Winbot%-WinTop%):PickLine%=WinBot%-WinTop%-1:sound 500,.1
LOOP
END FUNCTION
FUNCTION YesOrNo (Prompt$, TAttr%, BAttr%, VideoRAM&)
Temp$=SaveScreen$
IF LEN(Prompt$) < 15 THEN Prompt$ = SPACE$(8 - LEN(Prompt$) \ 2) + Prompt$ + SPACE$(8 - LEN(Prompt$) \ 2)
Wb% = 38 - LEN(Prompt$) \ 2
Wd% = 42 + LEN(Prompt$) \ 2
Wa% = CSRLIN
Wc% = Wa% + 3
CALL PBWriteBox(Wa%, Wb%, Wc%, Wd%, BAttr%, VideoRAM&)
CALL VPRINT(Wa%+1, Wb%+1, SPACE$(Wd%-Wb%-1), TAttr%,VideoRAM&)
CALL VPRINT(Wa%+2, Wb%+1, SPACE$(Wd%-Wb%-1), TAttr%,VideoRAM&)
CALL VPRINT(Wa%+1, 40-LEN(Prompt$) \ 2, Prompt$, TAttr%,VideoRAM&)
YorN = -1
LET YorN$ = "
DO
CALL VPRINT(Wa% + 2, 34, YorN$, TAttr%,VideoRAM&)
DO: A$ = IN.KEY$: LOOP WHILE A$ = ""
IF UCASE$(A$) = "Y" THEN YorN = -1
IF UCASE$(A$) = "N" THEN YorN = 0
IF A$ = CHR$(0) + CHR$(&H4D) THEN YorN = 0
IF A$ = CHR$(0) + CHR$(&H4B) THEN YorN = 1
IF A$=CHR$(27) THEN YorN = 27:EXIT LOOP
IF A$ = CHR$(13) THEN EXIT LOOP
IF YorN THEN LET YorN$ = "
LOOP
YesOrNo = YorN
CALL RestoreScreen(Temp$)
END FUNCTION
' *** LINE FEED
SUB Message (E$)
CALL SingleBox(14, 20, 16, 60)
LOCATE 15, 40 - (LEN(E$) \ 2)
PRINT E$;
END SUB
FUNCTION IN.KEY$
SHARED Macro%,KBuffer$,Macro$
IF LEN(KBuffer$) THEN
IK$=LEFT$(KBuffer$,1)
IF IK$=CHR$(0) THEN IK$=LEFT$(KBuffer$,2)
KBuffer$=MID$(KBuffer$,1+LEN(IK$))
ELSE
IK$=INKEY$
END IF
IF IK$=CHR$(0,50) THEN IF Macro% THEN Macro%=0:SOUND 3000,1:SOUND 2000,1:SOUND 1000,1
IF Macro% THEN MACRO$=MACRO$+IK$
IF LEN(IK$)=2 THEN
IF LEN(MACRO$) THEN
IF INSTR(MACRO$,"MACRO:"+IK$) THEN
M$=MID$(MACRO$,INSTR(MACRO$,CHR$(13,10)+"MACRO:"+IK$)+9)
IF INSTR(M$,"MACRO") THEN
M$=LEFT$(M$,INSTR(M$,CHR$(13,10)+"MACRO")-1)
END IF
KEYIN M$
IK$=""
END IF
END IF
END IF
IN.KEY$=IK$
END FUNCTION
SUB KEYIN(instring$)
SHARED Macro%,KBuffer$
KBuffer$=instring$+KBuffer$
END SUB
SUB TASK.MANAGER
' This sub does not do anything right now, however it will be
' called many times a second while PBWRITE is running. In here
' you can be running background processes like running a print
' job or printing several copies of ED$ as they are merged with
' fields and records from a large database, thus allowing the
' user to keep on working while the printing is taking place.
' be sure that the events which take place here or the other
' subs and functions called by this sub are extremely brief
' and repetetive in order to not interfere with the smooth
' operation of PBWRITE. Also, if something goes wrong and you
' need to interact with the user (such as an error message) you
' must save and restore the screen. TASK.MANAGER can also be
' monitoring for network messages, performing an Xmodem download,
' or even writing video ram to a ram disk file every few seconds
' in order to allow another network workstation to monitor what
' the user is doing. There are a great many neat possibilities.
END SUB
Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!
This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.
But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/