mirror of
https://github.com/dschmenk/PLASMA.git
synced 2026-04-27 03:18:02 +00:00
1605 lines
42 KiB
Plaintext
Executable File
1605 lines
42 KiB
Plaintext
Executable File
//=====================================
|
|
//
|
|
// Text Editor
|
|
//
|
|
//=====================================
|
|
|
|
include "inc/cmdsys.plh"
|
|
include "inc/args.plh"
|
|
include "inc/fileio.plh"
|
|
include "inc/conio.plh"
|
|
include "inc/vblank.plh"
|
|
sysflags restxt1|resxtxt1|nojitc // Keep JITC from compiling and pausing while editing
|
|
const CSW = $36
|
|
//
|
|
// Data and text buffer constants
|
|
//
|
|
const MAXLINES = 999
|
|
const MAXLINESSIZE = MAXLINES+24
|
|
const MAXCLIPLINES = 256
|
|
const MAXLNLEN = 127
|
|
const pgjmp = 16
|
|
const changed = 1
|
|
const insmode = 2
|
|
const gutter = 4 // This has to be 4 to match on-screen width
|
|
const selection = 8
|
|
const exit = 16
|
|
const numlock = 128
|
|
//
|
|
// Text screen dimensions
|
|
//
|
|
byte[] UltraTermWidth = 80, 96, 160, 80, 80, 80, 132, 128
|
|
byte[] UltraTermHeight = 24, 24, 24, 24, 32, 48, 24, 32
|
|
word scrnheight = 24
|
|
byte scrnwidth = 80
|
|
byte viewwidth
|
|
byte viewleft
|
|
word viewtop
|
|
//
|
|
// Editor variables
|
|
//
|
|
byte nullstr = ""
|
|
byte[80] findstr = ""
|
|
byte[64] filename = "UNTITLED"
|
|
byte flags = 0
|
|
word numlines = 0
|
|
word numcliplines = 0
|
|
word arg
|
|
word strpool, strplmapsize, strpoolmap
|
|
word txtlinbuf, cliplinbuf
|
|
word cursx, cursy, cursrow, curscol, selrow
|
|
word cursflash = 500 // default cursor flash delay
|
|
//
|
|
// Predeclared functions
|
|
//
|
|
predef cmdmode#0
|
|
//
|
|
// Utility functions
|
|
//
|
|
// Defines for ASM routines
|
|
//
|
|
asm equates
|
|
!SOURCE "vmsrc/plvmzp.inc"
|
|
end
|
|
asm lnupcpy(dststr, srcstr)#0
|
|
LDA ESTKL,X
|
|
STA SRCL
|
|
LDA ESTKH,X
|
|
STA SRCH
|
|
INX
|
|
LDA ESTKL,X
|
|
STA DSTL
|
|
LDA ESTKH,X
|
|
STA DSTH
|
|
INX
|
|
LDY #$00
|
|
LDA (SRC),Y
|
|
CMP #80
|
|
BCC +
|
|
LDA #79
|
|
+ STA (DST),Y
|
|
TAY
|
|
BEQ +++
|
|
CPUPLP LDA (SRC),Y
|
|
CMP #$20
|
|
BCS +
|
|
ADC #$60
|
|
+ AND #$7F
|
|
CMP #$7B
|
|
BCS ++
|
|
CMP #$61
|
|
BCC ++
|
|
SEC
|
|
SBC #$20
|
|
++ STA (DST),Y
|
|
DEY
|
|
BNE CPUPLP
|
|
+++ RTS
|
|
end
|
|
//def sizemask(size)
|
|
// if size <= 80
|
|
// return sizetomask[(size - 1) >> 4]
|
|
// fin
|
|
// if size <= 16
|
|
// return $01
|
|
// elsif size <= 32
|
|
// return $03
|
|
// elsif size <= 48
|
|
// return $07
|
|
// elsif size <= 64
|
|
// return $0F
|
|
// elsif size <= 80
|
|
// return $1F
|
|
// fin
|
|
// return 0
|
|
//end
|
|
asm sizemask(size)#1
|
|
LDA ESTKL,X
|
|
CMP #129 ; 81
|
|
BCS ++
|
|
ADC #$0F
|
|
LSR
|
|
LSR
|
|
LSR
|
|
LSR
|
|
TAY
|
|
LDA #$FF
|
|
- ASL
|
|
DEY
|
|
BNE -
|
|
EOR #$FF
|
|
STA ESTKL,X
|
|
LDA #$00
|
|
STA ESTKH,X
|
|
RTS
|
|
-- DEY ; THIS IS NEXT MAP BYTE FROM BELOW
|
|
CPY #$FF
|
|
BNE +
|
|
DEC DSTH
|
|
DEC ESTKH+1,X
|
|
LDA ESTKH+1,X
|
|
CMP #$FF
|
|
BNE +
|
|
INX
|
|
INX
|
|
INX
|
|
++ LDA #$00
|
|
STA ESTKL,X
|
|
STA ESTKH,X
|
|
RTS
|
|
end
|
|
//def strpoolalloc(size)
|
|
// szmask = sizemask(size)
|
|
// for i = strplmapsize - 1 downto 0
|
|
// if ^(strpoolmap + i) <> $FF
|
|
// mapmask = szmask
|
|
// ofst = 0
|
|
// repeat // Look for memory hole to fit
|
|
// if ^(strpoolmap + i) & mapmask // Nope, shift over
|
|
// mapmask = mapmask << 1
|
|
// ofst++
|
|
// else // Yep, take it
|
|
// ^(strpoolmap + i) = ^(strpoolmap + i) | mapmask
|
|
// return (ofst << 4) + (i << 7) + strpool
|
|
// fin
|
|
// until mapmask & $100 // No fit
|
|
// fin
|
|
// next
|
|
// return 0
|
|
//end
|
|
asm poolalloc(poolbase, mapbase, idx, mask)#1
|
|
LDA ESTKL+2,X ; MAPBASEL
|
|
STA DSTL
|
|
LDA ESTKH+2,X ; MAPBASEH
|
|
CLC
|
|
ADC ESTKH+1,X ; IDXH
|
|
STA DSTH
|
|
LDY ESTKL+1,X ; IDXL
|
|
+ LDA (DST),Y
|
|
CMP #$FF
|
|
BEQ -- ; MAP BYTE FULL, TRY NEXT
|
|
LDA #$00
|
|
STA TMP ; OFST
|
|
LDA ESTKL,X
|
|
STA ESTKH,X
|
|
- AND (DST),Y
|
|
BEQ ++
|
|
INC TMP ; OFST++
|
|
ASL ESTKH,X ; MASK <<= 1
|
|
BCS -- ; NO FIT, TRY NEXT MAP BYTE
|
|
LDA ESTKH,X
|
|
BCC -
|
|
++ LDA ESTKH,X ; UPDATE MAPMASK
|
|
ORA (DST),Y
|
|
STA (DST),Y
|
|
LDA TMP ; OFST
|
|
ASL
|
|
ASL
|
|
ASL
|
|
ASL
|
|
;CLC
|
|
ADC ESTKL+3,X ; + OFST << 4
|
|
STA ESTKL+3,X
|
|
BCC +
|
|
INC ESTKH+3,X
|
|
+ TYA
|
|
LSR ESTKH+1,X
|
|
ROR
|
|
TAY
|
|
LDA #$00
|
|
ROR
|
|
;CLC
|
|
ADC ESTKL+3,X ; + IDX << 7
|
|
STA ESTKL+3,X
|
|
TYA
|
|
ADC ESTKH+3,X
|
|
STA ESTKH+3,X
|
|
INX
|
|
INX
|
|
INX
|
|
RTS
|
|
end
|
|
def bell#0
|
|
putc($07)
|
|
end
|
|
//
|
|
// Memory management routines
|
|
//
|
|
def striplead(strptr, chr)#0
|
|
byte striplen
|
|
|
|
for striplen = 1 to ^strptr
|
|
if ^(strptr + striplen) <> chr
|
|
break
|
|
fin
|
|
next
|
|
if striplen > 1
|
|
^strptr = ^strptr - (striplen - 1)
|
|
memcpy(strptr + 1, strptr + striplen, ^strptr)
|
|
fin
|
|
end
|
|
def strstripcpy(dststr, srcstr)#0
|
|
byte strlen
|
|
|
|
memcpy(dststr, srcstr, ^srcstr + 1)
|
|
for strlen = ^dststr downto 1
|
|
if ^(dststr + strlen) > keyspace
|
|
break
|
|
fin
|
|
next
|
|
^dststr = strlen
|
|
end
|
|
def delstr(strptr)#0
|
|
word ofst, mask
|
|
|
|
if strptr <> @nullstr
|
|
ofst = (strptr - strpool) >> 4
|
|
mask = sizemask(^strptr + 1) << (ofst & $07)
|
|
ofst = ofst >> 3
|
|
^(strpoolmap + ofst) = ^(strpoolmap + ofst) & ~mask
|
|
fin
|
|
end
|
|
def newstr(strptr)
|
|
byte strlen
|
|
word newptr
|
|
|
|
for strlen = ^strptr downto 1
|
|
if ^(strptr + strlen) > keyspace
|
|
break
|
|
fin
|
|
next
|
|
if strlen == 0
|
|
return @nullstr
|
|
fin
|
|
newptr = poolalloc(strpool, \
|
|
strpoolmap, \
|
|
strplmapsize - 1, \
|
|
sizemask(strlen + 1))
|
|
if newptr
|
|
memcpy(newptr + 1, strptr + 1, strlen)
|
|
^newptr = strlen
|
|
else
|
|
puts("Out of memory!\n")
|
|
newptr = @nullstr
|
|
fin
|
|
return newptr
|
|
end
|
|
def inittxtbuf#0
|
|
word i
|
|
|
|
if not strpool
|
|
txtlinbuf = heapalloc(MAXLINESSIZE*2)
|
|
cliplinbuf = heapalloc(MAXCLIPLINES*2)
|
|
strplmapsize = (heapavail - 1024) / 128
|
|
strpoolmap = heapalloc(strplmapsize)
|
|
strpool = heapalloc(strplmapsize * 128)
|
|
memset(txtlinbuf, @nullstr, MAXLINESSIZE*2)
|
|
memset(cliplinbuf, @nullstr, MAXCLIPLINES*2)
|
|
memset(strpoolmap, 0, strplmapsize)
|
|
else
|
|
for i = 0 to MAXLINESSIZE-1
|
|
if txtlinbuf=>[i] <> @nullstr
|
|
delstr(txtlinbuf=>[i])
|
|
txtlinbuf=>[i] = @nullstr
|
|
fin
|
|
next
|
|
fin
|
|
numlines = 1
|
|
cursrow = 0
|
|
curscol = 0
|
|
cursx = flags & gutter
|
|
cursy = 0
|
|
viewleft = 0
|
|
viewtop = 0
|
|
viewwidth = scrnwidth - (flags & gutter) - 2
|
|
flags = flags & ~selection
|
|
end
|
|
//
|
|
// String routines
|
|
//
|
|
def fillnum(huns, tens, ones, chrptr)#3
|
|
if huns
|
|
chrptr->[0] = '0' + huns
|
|
chrptr->[1] = '0' + tens
|
|
chrptr->[2] = '0' + ones
|
|
ones++
|
|
if ones > 9
|
|
ones = 0
|
|
tens++
|
|
if tens > 9
|
|
tens = 0
|
|
huns++
|
|
fin
|
|
fin
|
|
elsif tens
|
|
chrptr->[0] = ' '
|
|
chrptr->[1] = '0' + tens
|
|
chrptr->[2] = '0' + ones
|
|
ones++
|
|
if ones > 9
|
|
ones = 0
|
|
tens++
|
|
if tens > 9
|
|
tens = 0
|
|
huns = 1
|
|
fin
|
|
fin
|
|
elsif ones
|
|
chrptr->[0] = ' '
|
|
chrptr->[1] = ' '
|
|
chrptr->[2] = '0' + ones
|
|
ones++
|
|
if ones > 9
|
|
ones = 0
|
|
tens = 1
|
|
fin
|
|
fin
|
|
return huns, tens, ones
|
|
end
|
|
def strtonum(strptr)
|
|
word num, i
|
|
byte c
|
|
|
|
num = 0
|
|
for i = 1 to ^strptr
|
|
c = ^(strptr + i) & $7F
|
|
if c < '0' and c > '9'
|
|
break
|
|
fin
|
|
num = num * 10 + c - '0'
|
|
next
|
|
return num
|
|
end
|
|
def nametostr(namestr, len, strptr)#0
|
|
^strptr = len
|
|
memcpy(strptr + 1, namestr, len)
|
|
end
|
|
//
|
|
// File routines
|
|
//
|
|
def readtxt(filename, startline)#0
|
|
byte refnum, i, j, txtbuf[MAXLNLEN+2]
|
|
|
|
refnum = fileio:open(filename)
|
|
if refnum
|
|
fileio:newline(refnum, $7F, $0D)
|
|
numlines = startline
|
|
repeat
|
|
txtbuf = fileio:read(refnum, @txtbuf + 1, MAXLNLEN)
|
|
if txtbuf
|
|
txtlinbuf=>[numlines] = newstr(@txtbuf)
|
|
numlines++
|
|
fin
|
|
if !(numlines & $0F); putc('.'); fin
|
|
until txtbuf == 0 or numlines == MAXLINES
|
|
fileio:close(refnum)
|
|
//
|
|
// Make sure there is a blank line at the end of the buffer
|
|
//
|
|
if numlines < MAXLINES and txtlinbuf=>[numlines - 1] <> @nullstr
|
|
txtlinbuf=>[numlines] = @nullstr
|
|
numlines++
|
|
fin
|
|
fin
|
|
putln
|
|
end
|
|
def writetxt(filename)#0
|
|
word i
|
|
byte refnum, txtbuf[MAXLNLEN+2], txtlen
|
|
|
|
//
|
|
// Remove blank lines at end of text.
|
|
//
|
|
while numlines > 1 and txtlinbuf=>[numlines - 1] == @nullstr; numlines--; loop
|
|
//
|
|
// Delete old file and re-create
|
|
//
|
|
fileio:destroy(filename)
|
|
fileio:create(filename, $04, $00) // full access, TXT file
|
|
refnum = fileio:open(filename)
|
|
if refnum == 0
|
|
puts("\nError $"); puth(perr); puts(" opening: "); puts(filename); putln
|
|
return
|
|
fin
|
|
//
|
|
// Write all the text lines to the file.
|
|
//
|
|
for i = 0 to numlines - 1
|
|
txtlen = ^(txtlinbuf=>[i])
|
|
memcpy(@txtbuf, txtlinbuf=>[i] + 1, txtlen)
|
|
txtbuf[txtlen] = keyenter
|
|
txtlen++
|
|
if fileio:write(refnum, @txtbuf, txtlen) <> txtlen
|
|
puts("\nError $"); puth(perr); puts(" writing: "); puts(filename); putln
|
|
fileio:close(refnum)
|
|
return
|
|
fin
|
|
if !(i & $0F); putc('.'); fin
|
|
next
|
|
if fileio:close(refnum) <> FILE_ERR_OK
|
|
puts("\nError $"); puth(perr); puts(" closing: "); puts(filename)
|
|
fin
|
|
putln
|
|
end
|
|
//
|
|
// Screen routines
|
|
//
|
|
def drawstr(row, strptr)#0
|
|
word numchars
|
|
|
|
conio:gotoxy(flags & gutter, row)
|
|
numchars = ^strptr - viewleft
|
|
if numchars >= viewwidth
|
|
conio:putchars(viewwidth, strptr + viewleft + 1)
|
|
else
|
|
conio:putchars(numchars, strptr + viewleft + 1)
|
|
conio:clear(cleol)
|
|
fin
|
|
end
|
|
def drawgutterrow(row)#0
|
|
byte seperator, huns, tens, ones
|
|
word scrnrow
|
|
char gutterchars[3]
|
|
|
|
//
|
|
// Draw line numbers and gutter hilites
|
|
//
|
|
if flags & gutter
|
|
scrnrow = row + viewtop
|
|
huns, tens = divmod(scrnrow + 1, 100)
|
|
tens, ones = divmod(tens, 10)
|
|
if scrnrow < numlines
|
|
seperator = viewleft ?? '<' :: ' '
|
|
if flags & selection
|
|
if (scrnrow >= selrow and scrnrow <= cursrow) or (scrnrow >= cursrow and scrnrow <= selrow)
|
|
seperator = '['
|
|
conio:textctrl(ctrlattr, INVERSE)
|
|
fin
|
|
fin
|
|
if scrnrow == cursrow
|
|
conio:textctrl(ctrlattr, INVERSE)
|
|
fin
|
|
huns, tens, ones = fillnum(huns, tens, ones, @gutterchars)
|
|
conio:gotoxy(0, row)
|
|
conio:putchars(3, @gutterchars)
|
|
conio:textctrl(ctrlattr, INVERSE)
|
|
putc(seperator)
|
|
conio:textctrl(ctrlattr, NORMAL)
|
|
fin
|
|
fin
|
|
end
|
|
def drawgutter#0
|
|
byte row, seperator, huns, tens, ones
|
|
word scrnrow
|
|
char gutterchars[3]
|
|
|
|
//
|
|
// Draw line numbers and gutter hilites
|
|
//
|
|
if flags & gutter
|
|
seperator = viewleft ?? '<' :: ' '
|
|
huns, tens = divmod(viewtop + 1, 100)
|
|
tens, ones = divmod(tens, 10)
|
|
for row = 0 to scrnheight-1
|
|
scrnrow = row + viewtop
|
|
if scrnrow < numlines
|
|
seperator = viewleft ?? '<' :: ' '
|
|
if flags & selection
|
|
if (scrnrow >= selrow and scrnrow <= cursrow) or (scrnrow >= cursrow and scrnrow <= selrow)
|
|
seperator = '['
|
|
conio:textctrl(ctrlattr, INVERSE)
|
|
fin
|
|
fin
|
|
if scrnrow == cursrow
|
|
conio:textctrl(ctrlattr, INVERSE)
|
|
fin
|
|
huns, tens, ones = fillnum(huns, tens, ones, @gutterchars)
|
|
conio:gotoxy(0, row)
|
|
conio:putchars(3, @gutterchars)
|
|
conio:textctrl(ctrlattr, INVERSE)
|
|
putc(seperator)
|
|
conio:textctrl(ctrlattr, NORMAL)
|
|
fin
|
|
next
|
|
fin
|
|
end
|
|
def drawrows(toprow, bottomrow)#0
|
|
byte row, seperator, huns, tens, ones
|
|
word scrnrow, strptr, numchars
|
|
char gutterchars[3]
|
|
|
|
//
|
|
// Draw gutter and text
|
|
//
|
|
huns, tens = divmod(viewtop + toprow + 1, 100)
|
|
tens, ones = divmod(tens, 10)
|
|
for row = toprow to bottomrow
|
|
conio:gotoxy(0, row)
|
|
scrnrow = row + viewtop
|
|
if scrnrow < numlines
|
|
if flags & gutter
|
|
seperator = viewleft ?? '<' :: ' '
|
|
if flags & selection
|
|
if (scrnrow >= selrow and scrnrow <= cursrow) or (scrnrow >= cursrow and scrnrow <= selrow)
|
|
seperator = '['
|
|
conio:textctrl(ctrlattr, INVERSE)
|
|
fin
|
|
fin
|
|
if scrnrow == cursrow
|
|
conio:textctrl(ctrlattr, INVERSE)
|
|
fin
|
|
huns, tens, ones = fillnum(huns, tens, ones, @gutterchars)
|
|
conio:putchars(3, @gutterchars)
|
|
conio:textctrl(ctrlattr, INVERSE)
|
|
putc(seperator)
|
|
conio:textctrl(ctrlattr, NORMAL)
|
|
fin
|
|
strptr = txtlinbuf=>[scrnrow]
|
|
numchars = ^strptr - viewleft
|
|
if numchars >= viewwidth
|
|
numchars = viewwidth
|
|
fin
|
|
conio:putchars(numchars, strptr + viewleft + 1)
|
|
fin
|
|
conio:clear(cleol)
|
|
next
|
|
end
|
|
def drawscrn#0
|
|
drawrows(0, scrnheight - 1)
|
|
end
|
|
def curshpos(hpos)#1
|
|
byte needredraw, scrnleft, scrnright
|
|
|
|
needredraw = TRUE
|
|
if hpos < 0; hpos = 0; fin
|
|
if hpos > MAXLNLEN; hpos = MAXLNLEN; fin
|
|
scrnleft = flags & gutter
|
|
scrnright = scrnwidth - 2
|
|
curscol = hpos
|
|
cursx = curscol - viewleft + scrnleft
|
|
if cursx > scrnright
|
|
cursx = scrnright
|
|
viewleft = curscol - viewwidth
|
|
elsif cursx < scrnleft
|
|
cursx = scrnleft
|
|
viewleft = curscol
|
|
else
|
|
needredraw = FALSE
|
|
fin
|
|
return needredraw
|
|
end
|
|
def cursvpos(vpos)#1
|
|
byte needredraw
|
|
|
|
needredraw = TRUE
|
|
if vpos < 0; vpos = 0; fin
|
|
if vpos > numlines - 1; vpos = numlines - 1; fin
|
|
cursrow = vpos
|
|
cursy = cursrow - viewtop
|
|
if cursy > scrnheight - 1
|
|
cursy = scrnheight - 1
|
|
viewtop = cursrow - (scrnheight - 1)
|
|
elsif cursy < 0
|
|
cursy = 0
|
|
viewtop = cursrow
|
|
else
|
|
needredraw = FALSE
|
|
fin
|
|
return needredraw
|
|
end
|
|
def curshome#0
|
|
cursrow = 0
|
|
curscol = 0
|
|
cursx = flags & gutter
|
|
cursy = 0
|
|
viewleft = 0
|
|
viewtop = 0
|
|
drawscrn
|
|
end
|
|
def cursend#0
|
|
if numlines > scrnheight - 1
|
|
cursrow = numlines - 1
|
|
cursy = scrnheight - 1
|
|
viewtop = cursrow - (scrnheight - 1)
|
|
else
|
|
cursrow = numlines - 1
|
|
cursy = numlines - 1
|
|
viewtop = 0
|
|
fin
|
|
curscol = 0
|
|
cursx = flags & gutter
|
|
viewleft = 0
|
|
drawscrn
|
|
end
|
|
def cursup#0
|
|
if cursrow > 0
|
|
cursrow--
|
|
drawgutterrow(cursy)
|
|
if cursy > 0
|
|
cursy--
|
|
drawgutterrow(cursy)
|
|
else
|
|
viewtop = cursrow
|
|
if conio:textctrl(ctrlscroll, DOWN)
|
|
drawrows(0, 0)
|
|
else
|
|
drawscrn
|
|
fin
|
|
fin
|
|
fin
|
|
end
|
|
def pgup#0
|
|
word scroll
|
|
|
|
scroll = viewtop
|
|
if cursvpos(cursrow - pgjmp)
|
|
scroll = viewtop - scroll
|
|
if scroll
|
|
if conio:textctrl(ctrlscroll, scroll)
|
|
drawrows(0, -scroll - 1)
|
|
drawgutter
|
|
else
|
|
drawscrn
|
|
fin
|
|
fin
|
|
else
|
|
drawgutter
|
|
fin
|
|
end
|
|
def cursdown#0
|
|
if cursrow < numlines - 1
|
|
cursrow++
|
|
drawgutterrow(cursy)
|
|
if cursy < scrnheight - 1
|
|
cursy++
|
|
drawgutterrow(cursy)
|
|
else
|
|
viewtop = cursrow - (scrnheight - 1)
|
|
if conio:textctrl(ctrlscroll, UP)
|
|
drawrows(scrnheight - 1, scrnheight - 1)
|
|
else
|
|
drawscrn
|
|
fin
|
|
fin
|
|
fin
|
|
end
|
|
def pgdown#0
|
|
word scroll
|
|
|
|
scroll = viewtop
|
|
if cursvpos(cursrow + pgjmp)
|
|
scroll = viewtop - scroll
|
|
if scroll
|
|
if conio:textctrl(ctrlscroll, scroll)
|
|
drawrows(scrnheight - scroll, scrnheight - 1)
|
|
drawgutter
|
|
else
|
|
drawscrn
|
|
fin
|
|
fin
|
|
else
|
|
drawgutter
|
|
fin
|
|
end
|
|
def cursleft#0
|
|
if curshpos(curscol - 1); drawscrn; fin
|
|
end
|
|
def pgleft#0
|
|
word i, strptr
|
|
|
|
strptr = txtlinbuf=>[cursrow]
|
|
if curscol > ^strptr
|
|
i = ^strptr
|
|
else
|
|
for i = 1 to ^strptr
|
|
if ^(strptr + i) <> keyspace
|
|
break
|
|
fin
|
|
next
|
|
i--
|
|
if i >= curscol
|
|
i = 0
|
|
fin
|
|
fin
|
|
if curshpos(i)
|
|
drawscrn
|
|
else
|
|
drawgutter
|
|
fin
|
|
end
|
|
def cursright#0
|
|
if curshpos(curscol + 1); drawscrn; fin
|
|
end
|
|
def pgright#0
|
|
word i, strptr
|
|
|
|
strptr = txtlinbuf=>[cursrow]
|
|
if curscol >= ^strptr
|
|
i = curscol + 8
|
|
else
|
|
for i = 1 to ^strptr
|
|
if ^(strptr + i) <> keyspace
|
|
break
|
|
fin
|
|
next
|
|
i--
|
|
if curscol >= i
|
|
i = ^strptr
|
|
fin
|
|
fin
|
|
if curshpos(i)
|
|
drawscrn
|
|
else
|
|
drawgutter
|
|
fin
|
|
end
|
|
//
|
|
// Find string in text
|
|
//
|
|
def findline(strptr, start)#1
|
|
byte scan, i, upstr[MAXLNLEN+1]
|
|
|
|
if ^strptr >= findstr
|
|
lnupcpy(@upstr, strptr)
|
|
for scan = start to upstr - findstr + 1
|
|
if upstr[scan] == findstr[1]
|
|
for i = 2 to findstr
|
|
if upstr[scan + i - 1] <> findstr[i]
|
|
break
|
|
fin
|
|
next
|
|
if i > findstr
|
|
curshpos(scan - 1)
|
|
return TRUE
|
|
fin
|
|
fin
|
|
next
|
|
fin
|
|
return FALSE
|
|
end
|
|
def findtxt#0
|
|
word f
|
|
|
|
//
|
|
// Search from current pos to end
|
|
//
|
|
if findline(txtlinbuf=>[cursrow], curscol + 2)
|
|
return
|
|
fin
|
|
for f = cursrow + 1 to numlines - 1
|
|
if findline(txtlinbuf=>[f], 1)
|
|
cursvpos(f)
|
|
return
|
|
fin
|
|
next
|
|
//
|
|
// Search from beginning to current pos
|
|
//
|
|
for f = 0 to cursrow
|
|
if findline(txtlinbuf=>[f], 1)
|
|
cursvpos(f)
|
|
return
|
|
fin
|
|
next
|
|
bell
|
|
end
|
|
//
|
|
// Printer routines
|
|
//
|
|
def printtxt(slot)#0
|
|
word i, scrncsw
|
|
|
|
scrncsw = *CSW
|
|
*CSW = $C000 | (slot << 8)
|
|
for i = 0 to numlines - 1
|
|
puts(txtlinbuf=>[i]); putln
|
|
next
|
|
*CSW = scrncsw
|
|
end
|
|
def freesel#0
|
|
word i
|
|
|
|
if numcliplines
|
|
for i = 0 to numcliplines - 1
|
|
if cliplinbuf=>[i] <> @nullstr
|
|
delstr(cliplinbuf=>[i])
|
|
cliplinbuf=>[i] = @nullstr
|
|
fin
|
|
next
|
|
numcliplines = 0
|
|
fin
|
|
end
|
|
def selrange#2
|
|
word first, last
|
|
|
|
if flags & selection
|
|
if cursrow > selrow
|
|
first, last = selrow, cursrow
|
|
else
|
|
first, last = cursrow, selrow
|
|
fin
|
|
else
|
|
first = cursrow
|
|
last = first
|
|
fin
|
|
return first, last
|
|
end
|
|
def beginsel#0
|
|
flags = flags ^ selection
|
|
selrow = cursrow
|
|
drawgutter
|
|
end
|
|
def copysel#0
|
|
word firstsel, lastsel
|
|
|
|
freesel
|
|
firstsel, lastsel = selrange
|
|
if lastsel - firstsel < MAXCLIPLINES
|
|
for numcliplines = 0 to lastsel - firstsel
|
|
cliplinbuf=>[numcliplines] = newstr(txtlinbuf=>[firstsel + numcliplines])
|
|
next
|
|
flags = flags & ~selection
|
|
drawgutter
|
|
else
|
|
bell
|
|
fin
|
|
end
|
|
def cutsel#0
|
|
word firstsel, lastsel
|
|
|
|
freesel
|
|
firstsel, lastsel = selrange
|
|
if lastsel - firstsel < MAXCLIPLINES
|
|
for numcliplines = 0 to lastsel - firstsel
|
|
cliplinbuf=>[numcliplines] = txtlinbuf=>[firstsel + numcliplines]
|
|
next
|
|
memcpy(@txtlinbuf=>[firstsel], \
|
|
@txtlinbuf=>[lastsel + 1], \
|
|
(numlines - lastsel + 1) * 2)
|
|
numlines = numlines - numcliplines
|
|
for lastsel = numlines to numlines + numcliplines
|
|
txtlinbuf=>[lastsel] = @nullstr
|
|
next
|
|
cursrow = firstsel
|
|
if cursrow >= numlines
|
|
cursrow = numlines - 1
|
|
fin
|
|
if cursrow < viewtop
|
|
viewtop = cursrow
|
|
fin
|
|
cursy = cursrow - viewtop
|
|
flags = flags | changed
|
|
flags = flags & ~selection
|
|
drawscrn
|
|
else
|
|
bell
|
|
fin
|
|
end
|
|
def pastesel#0
|
|
word p
|
|
|
|
if numcliplines and numcliplines + numlines < MAXLINES
|
|
memcpy(@txtlinbuf=>[cursrow + numcliplines], \
|
|
@txtlinbuf=>[cursrow], \
|
|
(numlines - cursrow) * 2)
|
|
for p = 0 to numcliplines - 1
|
|
txtlinbuf=>[cursrow + p] = newstr(cliplinbuf=>[p])
|
|
next
|
|
numlines = numlines + numcliplines
|
|
flags = flags | changed
|
|
drawscrn
|
|
else
|
|
bell
|
|
fin
|
|
end
|
|
def indentsel#0
|
|
byte indentstr[MAXLNLEN+1], j, l
|
|
word firstsel, lastsel, i
|
|
|
|
freesel
|
|
firstsel, lastsel = selrange
|
|
for i = firstsel to lastsel
|
|
l = ^(txtlinbuf=>[i])
|
|
if l and l < MAXLNLEN - 2
|
|
memcpy(@indentstr + 3, txtlinbuf=>[i] + 1, l)
|
|
indentstr[0] = l + 2
|
|
indentstr[1] = keyspace
|
|
indentstr[2] = keyspace
|
|
//
|
|
// Align indent
|
|
//
|
|
for j = 3 to indentstr[0]
|
|
if indentstr[j] <> keyspace
|
|
if j & 1 == 0
|
|
indentstr[0]--
|
|
memcpy(@indentstr + 1, @indentstr + 2, indentstr[0])
|
|
fin
|
|
break
|
|
fin
|
|
next
|
|
delstr(txtlinbuf=>[i])
|
|
txtlinbuf=>[i] = newstr(@indentstr)
|
|
flags = flags | changed
|
|
fin
|
|
next
|
|
drawscrn
|
|
end
|
|
def undentsel#0
|
|
byte undentstr[MAXLNLEN+1], l
|
|
word firstsel, lastsel, i
|
|
|
|
freesel
|
|
firstsel, lastsel = selrange
|
|
for i = firstsel to lastsel
|
|
l = ^(txtlinbuf=>[i])
|
|
if l
|
|
memcpy(@undentstr + 1, txtlinbuf=>[i] + 1, l)
|
|
if undentstr[1] == keyspace
|
|
memcpy(@undentstr + 1, @undentstr + 2, l - 1)
|
|
l--
|
|
if l and undentstr[1] == keyspace
|
|
memcpy(@undentstr + 1, @undentstr + 2, l - 1)
|
|
l--
|
|
fin
|
|
undentstr[0] = l
|
|
delstr(txtlinbuf=>[i])
|
|
txtlinbuf=>[i] = newstr(@undentstr)
|
|
flags = flags | changed
|
|
fin
|
|
fin
|
|
next
|
|
drawscrn
|
|
end
|
|
def autoindent(strptr)#0
|
|
byte i
|
|
|
|
for i = 1 to ^strptr
|
|
if ^(strptr + i) <> keyspace
|
|
break
|
|
fin
|
|
next
|
|
curshpos(i - 1)
|
|
end
|
|
def openline(row)
|
|
if numlines < MAXLINES
|
|
memcpy(@txtlinbuf=>[row + 1], @txtlinbuf=>[row], (numlines - row) * 2)
|
|
txtlinbuf=>[row] = @nullstr
|
|
numlines++
|
|
flags = flags | changed
|
|
return TRUE
|
|
fin
|
|
bell
|
|
return FALSE
|
|
end
|
|
def joinline#0
|
|
word joinlen, joinstr, stripjoin
|
|
|
|
if cursrow < numlines - 1
|
|
joinstr = heapalloc(MAXLNLEN+1)
|
|
stripjoin = heapalloc(MAXLNLEN+1)
|
|
strstripcpy(joinstr, txtlinbuf=>[cursrow])
|
|
memcpy(stripjoin, txtlinbuf=>[cursrow + 1], ^(txtlinbuf=>[cursrow + 1]) + 1)
|
|
striplead(stripjoin, keyspace);
|
|
joinlen = ^joinstr + ^stripjoin
|
|
if joinlen <= MAXLNLEN
|
|
curshpos(^joinstr)
|
|
memcpy(joinstr + ^joinstr + 1, stripjoin + 1, ^stripjoin)
|
|
^joinstr = joinlen
|
|
delstr(txtlinbuf=>[cursrow])
|
|
txtlinbuf=>[cursrow] = newstr(joinstr)
|
|
delstr(txtlinbuf=>[cursrow + 1])
|
|
numlines--
|
|
memcpy(@txtlinbuf=>[cursrow + 1], @txtlinbuf=>[cursrow + 2], (numlines - cursrow) * 2)
|
|
flags = flags | changed
|
|
heaprelease(joinstr)
|
|
return
|
|
fin
|
|
heaprelease(joinstr)
|
|
fin
|
|
bell
|
|
end
|
|
def splitline#0
|
|
byte splitstr[MAXLNLEN+1], splitlen, i
|
|
|
|
if openline(cursrow + 1)
|
|
if curscol
|
|
splitlen = ^(txtlinbuf=>[cursrow])
|
|
if curscol < splitlen - 1
|
|
splitstr = splitlen - curscol
|
|
memcpy(@splitstr + 1, txtlinbuf=>[cursrow] + curscol + 1, splitstr)
|
|
striplead(@splitstr, keyspace)
|
|
for i = 1 to curscol
|
|
if ^(txtlinbuf=>[cursrow] + i) <> keyspace
|
|
break
|
|
fin
|
|
memcpy(@splitstr + 2, @splitstr + 1, splitstr)
|
|
splitstr[1] = keyspace
|
|
splitstr++
|
|
next
|
|
txtlinbuf=>[cursrow + 1] = newstr(@splitstr)
|
|
splitstr = curscol
|
|
memcpy(@splitstr + 1, txtlinbuf=>[cursrow] + 1, splitstr)
|
|
delstr(txtlinbuf=>[cursrow])
|
|
txtlinbuf=>[cursrow] = newstr(@splitstr)
|
|
curshpos(i - 1)
|
|
else
|
|
if splitlen > 0
|
|
for curscol = 1 to splitlen - 1
|
|
if ^(txtlinbuf=>[cursrow] + curscol) <> keyspace
|
|
break
|
|
fin
|
|
next
|
|
curshpos(curscol - 1)
|
|
fin
|
|
fin
|
|
else
|
|
txtlinbuf=>[cursrow + 1] = txtlinbuf=>[cursrow]
|
|
txtlinbuf=>[cursrow] = @nullstr
|
|
fin
|
|
fin
|
|
end
|
|
//
|
|
// Keyboard routines
|
|
//
|
|
def waitkey#1
|
|
word delay
|
|
|
|
for delay = 0 to cursflash
|
|
if conio:keypressed()
|
|
return conio:getkey()
|
|
fin
|
|
next
|
|
return 0
|
|
end
|
|
def keyin
|
|
byte key, underchr, curschr
|
|
|
|
underchr = curscol >= ^(txtlinbuf=>[cursrow]) ?? ' ' :: txtlinbuf=>[cursrow]->[curscol + 1]
|
|
curschr = flags & insmode ?? '+' :: '_'
|
|
if conio:keypressed()
|
|
key = conio:getkey()
|
|
conio:gotoxy(cursx, cursy)
|
|
else
|
|
conio:gotoxy(cursx, cursy)
|
|
repeat
|
|
conio:textctrl(ctrlattr, INVERSE)
|
|
conio:putchars(1, curschr)
|
|
conio:gotoxy(cursx, cursy)
|
|
key = waitkey
|
|
conio:textctrl(ctrlattr, NORMAL)
|
|
if not key
|
|
conio:putchars(1, underchr)
|
|
conio:gotoxy(cursx, cursy)
|
|
key = waitkey
|
|
fin
|
|
until key
|
|
fin
|
|
conio:putchars(1, underchr)
|
|
if (key & ~keyoptmod) >= '0' and (key & ~keyoptmod) <= '9'
|
|
key = key ^ (flags & numlock) // numlock == keyoptmod
|
|
fin
|
|
if key & keyoptmod // Closed-Apple/Option pressed
|
|
when key
|
|
is keyarrowleft | keyoptmod
|
|
key = keyctrla; break
|
|
is keyarrowright | keyoptmod
|
|
key = keyctrls; break
|
|
is keyarrowup | keyoptmod
|
|
key = keyctrlw; break
|
|
is keyarrowdown | keyoptmod
|
|
key = keyctrlz; break
|
|
is keyenter | keyoptmod
|
|
key = keyctrlf; break
|
|
is keytab | keyoptmod
|
|
key = keydetab; break
|
|
is '\\' | keyoptmod
|
|
key = keydelete; break // Delete
|
|
//
|
|
// Map option+keypad on Platinum //e
|
|
//
|
|
is '4' | keyoptmod
|
|
key = keyarrowleft; break
|
|
is '6' | keyoptmod
|
|
key = keyarrowright; break
|
|
is '8' | keyoptmod
|
|
key = keyarrowup; break
|
|
is '2' | keyoptmod
|
|
key = keyarrowdown; break
|
|
is '7' | keyoptmod
|
|
key = keyctrlq; break // Top
|
|
is '1' | keyoptmod
|
|
key = keyctrle; break // Bottom
|
|
is '9' | keyoptmod
|
|
key = keyctrlw; break // Pg Up
|
|
is '3' | keyoptmod
|
|
key = keyctrlz; break // Pg Dn
|
|
is '5' | keyoptmod
|
|
key = keyctrlb; break // Selection start/end
|
|
is '0' | keyoptmod
|
|
key = keyctrld; break // Del
|
|
is '.' | keyoptmod
|
|
key = keyctrlv; break // Paste
|
|
is '-' | keyoptmod
|
|
key = keyctrlx; break // Cut
|
|
is '+' | keyoptmod
|
|
key = keyctrlc; break // Copy
|
|
is '*' | keyoptmod
|
|
key = keyctrlo; break // Open line
|
|
is '/' | keyoptmod
|
|
key = keyctrlt; break // Insert/Overwrite
|
|
is '=' | keyoptmod
|
|
flags = flags ^ numlock
|
|
if flags & numlock
|
|
bell
|
|
fin
|
|
bell
|
|
key = 0
|
|
break
|
|
otherwise
|
|
key = key & ~keyoptmod
|
|
wend
|
|
fin
|
|
return key
|
|
end
|
|
def editkey(key)
|
|
if key >= keyspace or key == keyctrld or key == keyctrlr
|
|
return TRUE
|
|
fin
|
|
return FALSE
|
|
end
|
|
def editline(key)
|
|
word undoline
|
|
byte undopos, localchange, editstr[], editlen, editchars[MAXLNLEN+1]
|
|
|
|
if (editkey(key))
|
|
localchange = FALSE
|
|
undopos = curscol
|
|
undoline = txtlinbuf=>[cursrow]
|
|
editlen = MAXLNLEN
|
|
memcpy(@editchars, undoline + 1, ^undoline)
|
|
memset(@editchars + ^undoline, keyspace | (keyspace << 8), MAXLNLEN - ^undoline)
|
|
txtlinbuf=>[cursrow] = @editstr
|
|
repeat
|
|
when key
|
|
is keyctrld
|
|
memcpy(@editchars[curscol], @editchars[curscol + 1], MAXLNLEN - 1 - curscol)
|
|
editchars[MAXLNLEN - 1] = keyspace
|
|
drawstr(cursy, @editstr)
|
|
localchange = TRUE
|
|
break
|
|
is keyctrlr
|
|
memset(@editchars, $A0A0, MAXLNLEN)
|
|
memcpy(@editchars, undoline + 1, ^undoline)
|
|
if curshpos(undopos)
|
|
drawscrn
|
|
else
|
|
drawstr(cursy, @editstr)
|
|
fin
|
|
localchange = FALSE
|
|
break
|
|
is keydelete
|
|
if curscol > 0
|
|
memcpy(@editchars[curscol - 1], @editchars[curscol], MAXLNLEN - curscol)
|
|
editchars[MAXLNLEN - 1] = keyspace
|
|
if curshpos(curscol - 1)
|
|
drawscrn
|
|
else
|
|
drawstr(cursy, @editstr)
|
|
fin
|
|
localchange = TRUE
|
|
fin
|
|
break
|
|
otherwise
|
|
if flags & insmode
|
|
if editchars[MAXLNLEN - 1] == keyspace
|
|
memcpy(@editchars[curscol+1], @editchars[curscol], MAXLNLEN - 1 - curscol)
|
|
else
|
|
bell
|
|
break
|
|
fin
|
|
fin
|
|
editchars[curscol] = key
|
|
if curshpos(curscol + 1)
|
|
drawscrn
|
|
else
|
|
drawstr(cursy, @editstr)
|
|
fin
|
|
localchange = TRUE
|
|
break
|
|
wend
|
|
key = keyin
|
|
until not editkey(key)
|
|
if localchange
|
|
flags = flags | changed
|
|
delstr(undoline)
|
|
txtlinbuf=>[cursrow] = newstr(@editstr)
|
|
else
|
|
txtlinbuf=>[cursrow] = undoline
|
|
fin
|
|
fin
|
|
return key
|
|
end
|
|
def editmode#0
|
|
conio:textctrl(ctrlecho, OFF)
|
|
conio:textctrl(ctrlcursor, OFF)
|
|
repeat
|
|
when editline(keyin)
|
|
is keyarrowup
|
|
cursup; break
|
|
is keyarrowdown
|
|
cursdown; break
|
|
is keyarrowleft
|
|
cursleft; break
|
|
is keyarrowright
|
|
cursright; break
|
|
is keyctrlw
|
|
pgup; break
|
|
is keyctrlz
|
|
pgdown; break
|
|
is keyctrla
|
|
pgleft; break
|
|
is keyctrls
|
|
pgright; break
|
|
is keyctrlq
|
|
curshome; break
|
|
is keyctrle
|
|
cursend; break
|
|
is keyctrlb
|
|
beginsel; break
|
|
is keyctrlc
|
|
copysel; break
|
|
is keyctrlx
|
|
cutsel; break
|
|
is keyctrlv
|
|
pastesel; break
|
|
is keyctrlf
|
|
if cursrow == (numlines - 1)
|
|
if numlines < MAXLINES
|
|
numlines++
|
|
cursdown
|
|
flags = flags | changed
|
|
drawgutter
|
|
else
|
|
bell
|
|
fin
|
|
break
|
|
fin
|
|
cursdown
|
|
is keyctrlo
|
|
openline(cursrow)
|
|
if cursrow
|
|
autoindent(txtlinbuf=>[cursrow - 1])
|
|
else
|
|
curshpos(0)
|
|
fin
|
|
drawscrn
|
|
break
|
|
is keyenter
|
|
if flags & insmode
|
|
splitline
|
|
else
|
|
openline(cursrow + 1)
|
|
fin
|
|
autoindent(txtlinbuf=>[cursrow])
|
|
cursvpos(cursrow + 1)
|
|
drawscrn
|
|
break
|
|
is keyctrly
|
|
joinline
|
|
drawscrn
|
|
break
|
|
is keytab
|
|
if flags & insmode
|
|
indentsel
|
|
if not ^(txtlinbuf=>[cursrow])
|
|
curshpos((curscol + 2) & $FE)
|
|
else
|
|
autoindent(txtlinbuf=>[cursrow])
|
|
fin
|
|
break
|
|
fin
|
|
is keydetab
|
|
undentsel
|
|
if not ^(txtlinbuf=>[cursrow])
|
|
curshpos((curscol - 2) & $FFFE)
|
|
else
|
|
autoindent(txtlinbuf=>[cursrow])
|
|
fin
|
|
break
|
|
is keyctrlt
|
|
flags = flags ^ insmode
|
|
break
|
|
is keyescape
|
|
cmdmode
|
|
if not (flags & exit)
|
|
conio:clear(cls)
|
|
conio:textctrl(ctrlecho, OFF)
|
|
conio:textctrl(ctrlcursor, OFF)
|
|
drawscrn
|
|
fin
|
|
wend
|
|
until flags & exit
|
|
end
|
|
//
|
|
// Command mode
|
|
//
|
|
def prfiles(optpath)
|
|
byte path[64]
|
|
byte refnum
|
|
byte firstblk
|
|
byte entrylen, entriesblk
|
|
byte i, type, len
|
|
word databuff, entry
|
|
|
|
if ^optpath
|
|
strstripcpy(@path, optpath)
|
|
else
|
|
fileio:getpfx(@path)
|
|
puts(@path)
|
|
putln
|
|
fin
|
|
databuff = heapalloc(512)
|
|
refnum = fileio:open(@path)
|
|
if perr
|
|
return perr
|
|
fin
|
|
firstblk = 1
|
|
while fileio:read(refnum, databuff, 512) == 512
|
|
entry = databuff + 4
|
|
if firstblk
|
|
entrylen = databuff->$23
|
|
entriesblk = databuff->$24
|
|
entry = entry + entrylen
|
|
fin
|
|
for i = firstblk to entriesblk
|
|
type = ^entry
|
|
if type <> 0
|
|
len = type & $0F
|
|
^entry = len
|
|
puts(entry)
|
|
if type & $F0 == $D0 // Is it a directory?
|
|
putc('/')
|
|
len++
|
|
fin
|
|
for len = 20 - len downto 1
|
|
putc(' ')
|
|
next
|
|
fin
|
|
entry = entry + entrylen
|
|
next
|
|
firstblk = 0
|
|
loop
|
|
fileio:close(refnum)
|
|
heaprelease(databuff)
|
|
putln
|
|
return 0
|
|
end
|
|
def parsecmd(strptr)
|
|
byte cmd
|
|
|
|
cmd = 0
|
|
striplead(strptr, ' ')
|
|
if ^strptr
|
|
cmd = ^(strptr + 1)
|
|
memcpy(strptr + 1, strptr + 2, ^strptr)
|
|
^strptr--
|
|
fin
|
|
if ^strptr
|
|
striplead(strptr, ' ')
|
|
fin
|
|
return cmd
|
|
end
|
|
def chkchng
|
|
if flags & changed
|
|
puts("LOSE CHANGES TO FILE (Y/N)?")
|
|
if toupper(getc) == 'N'
|
|
putln
|
|
return FALSE
|
|
fin
|
|
putln
|
|
fin
|
|
return TRUE
|
|
end
|
|
def cmdmode#0
|
|
byte slot, b
|
|
word cmdptr, line
|
|
var i, freepool
|
|
|
|
conio:gotoxy(0, scrnheight - 1)
|
|
conio:clear(cleol)
|
|
conio:textctrl(ctrlecho, ON)
|
|
conio:textctrl(ctrlcursor, ON)
|
|
perr = 0 // Reset perr
|
|
line = 0
|
|
while not (flags & exit)
|
|
puts(@filename)
|
|
cmdptr = gets($BA)
|
|
when toupper(parsecmd(cmdptr))
|
|
is 'F' // Find string
|
|
if ^cmdptr
|
|
lnupcpy(@findstr, cmdptr)
|
|
fin
|
|
findtxt
|
|
return
|
|
is 'T' // Toggle upper/lower case display
|
|
if ^cmdptr
|
|
when toupper(^(cmdptr + 1))
|
|
is 'G' // Gutter view
|
|
flags = flags ^ gutter
|
|
viewwidth = scrnwidth - (flags & gutter) - 1
|
|
curshpos(curscol)
|
|
break
|
|
is 'C' // Lower case chip (Apple ][/][+ only)
|
|
conio:textctrl(ctrlcase, 0)
|
|
break
|
|
wend
|
|
fin
|
|
return
|
|
is '9' // Goto line #
|
|
line++
|
|
is '8'
|
|
line++
|
|
is '7'
|
|
line++
|
|
is '6'
|
|
line++
|
|
is '5'
|
|
line++
|
|
is '4'
|
|
line++
|
|
is '3'
|
|
line++
|
|
is '2'
|
|
line++
|
|
is '1'
|
|
line++
|
|
is '0'
|
|
memcpy(cmdptr + 2, cmdptr + 1, ^cmdptr)
|
|
^(cmdptr + 1) = line + '0' // Push number back on cmdptr
|
|
^cmdptr++
|
|
line = strtonum(cmdptr)
|
|
if line
|
|
curshpos(0)
|
|
cursvpos(line - 1)
|
|
fin
|
|
is 'E' // Edit mode
|
|
is 0
|
|
return
|
|
is 'A' // Append file
|
|
readtxt(cmdptr, numlines)
|
|
flags = flags | changed
|
|
break
|
|
is 'R' // Read file
|
|
if chkchng
|
|
inittxtbuf
|
|
strstripcpy(@filename, cmdptr)
|
|
readtxt(@filename, 0)
|
|
flags = flags & ~changed
|
|
fin
|
|
break
|
|
is 'W' // Write file
|
|
if ^cmdptr
|
|
strstripcpy(@filename, cmdptr)
|
|
fin
|
|
writetxt(@filename)
|
|
//if flags & changed; fin
|
|
flags = flags & ~changed
|
|
break
|
|
is 'C' // Catalog
|
|
prfiles(cmdptr); break
|
|
is 'P' // Prefix
|
|
fileio:setpfx(cmdptr); break
|
|
is 'H' // Hardcopy
|
|
if ^cmdptr
|
|
slot = cmdptr.1 - '0'
|
|
else
|
|
slot = 1
|
|
fin
|
|
printtxt(slot)
|
|
break
|
|
is 'Q' // Quit
|
|
flags = flags | (chkchng ?? exit :: 0)
|
|
if not (flags & exit)
|
|
return
|
|
fin
|
|
break
|
|
is 'N'
|
|
if chkchng
|
|
inittxtbuf
|
|
strstripcpy(@filename, "UNTITLED")
|
|
fin
|
|
break
|
|
is 'D' // Dump stats
|
|
freepool = 0
|
|
for i = strplmapsize - 1 downto 0
|
|
slot = ^(strpoolmap + i)
|
|
if slot <> $FF
|
|
for b = 0 to 7
|
|
if not ((1 << b) & slot)
|
|
freepool++
|
|
fin
|
|
next
|
|
fin
|
|
next
|
|
puts("Pool size: "); puti(strplmapsize*128); putln
|
|
puts("Pool free: "); puti(freepool*16); putln
|
|
puts("Num lines: "); puti(numlines); putln
|
|
puts("Clip lines: "); puti(numcliplines); putln
|
|
break
|
|
otherwise
|
|
bell
|
|
putc('?')
|
|
putln
|
|
wend
|
|
if perr
|
|
puts("ERROR: $")
|
|
putb(perr)
|
|
putln
|
|
fin
|
|
loop
|
|
end
|
|
//
|
|
// Init editor
|
|
//
|
|
arg = argNext(argFirst)
|
|
if ^arg
|
|
while ^(arg+1) == '-'
|
|
when ^(arg+2)
|
|
is '4' // Force 40 columns
|
|
scrnwidth = 40
|
|
break
|
|
is 'U' // Use extended VIDEX UltraTerm mode
|
|
scrnwidth = 80 + ^(arg+3) - '0'
|
|
break
|
|
wend
|
|
arg = argNext(arg)
|
|
loop
|
|
strcpy(@filename, arg)
|
|
arg = argNext(arg)
|
|
if ^arg
|
|
cursrow = strtonum(arg)
|
|
fin
|
|
fin
|
|
if waitVBL
|
|
cursflash = waitVBL
|
|
fin
|
|
flags = flags | insmode | gutter
|
|
scrnwidth = conio:textmode(scrnwidth)
|
|
if scrnwidth > 80 // Lookup UltraTerm screen dimensions
|
|
scrnheight = UltraTermHeight[scrnwidth - 81]
|
|
scrnwidth = UltraTermWidth[scrnwidth - 81]
|
|
fin
|
|
puts("PLEIADES 2.20 Editor\n")
|
|
inittxtbuf
|
|
puts(@filename)
|
|
readtxt(@filename, 0)
|
|
if cursrow
|
|
curshpos(0)
|
|
cursvpos(cursrow - 1)
|
|
fin
|
|
conio:clear(cls)
|
|
drawscrn
|
|
editmode
|
|
conio:textmode(0) // Set default mode
|
|
done
|