/
edit.rrbasic
384 lines (343 loc) · 8.09 KB
/
edit.rrbasic
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
REM globals
max = 100
lines = 0
top = 0
currentx = 0
currenty = 0
dirty = FALSE
DIM content$, max
REM load file, draw UI, start editor input loop
PROCload(ARGS$)
IF ARGS$ = "" THEN lines = 1
CLS
PROCtext
PROCedit
END
REM clear line from cursor to right
DEF PROCclearLineFromCursor
PRINT CHR$(27) + "[0K";
RETPROC
REM draw UI around editor window
DEF PROCdraw
BACKGROUND 4
COLOUR 15
CURSOR 1, TERMHEIGHT
PROCclearLineFromCursor
CURSOR 2, TERMHEIGHT
PRINT "ESC EXIT"; CHR$(9); "^S SAVE"; CHR$(9); CHR$(9); "^W WHEREIS"; CHR$(9); "^R REPLACE";
CURSOR TERMWIDTH - 15, TERMHEIGHT
PRINT currentx; ","; top + currenty;
CURSOR 1, 0
PROCclearLineFromCursor
CURSOR TERMWIDTH / 2 - 2, 0
PRINT "EDIT"
COLOUR 7
BACKGROUND 0
CURSOR 1, 2
RETPROC
REM Display prompt in bottom section of screen
DEF PROCprompt(prompt$)
PROCdraw
BACKGROUND 4
COLOUR 15
CURSOR 1, TERMHEIGHT
PROCclearLineFromCursor
CURSOR 2, TERMHEIGHT
PRINT prompt$; ": ";
RETPROC
REM clear prompt
DEF PROCendPrompt
CLS
PROCtext
RETPROC
REM hide text cursor
DEF PROChideCursor
PRINT CHR$(27);"[?25l";
RETPROC
REM show text cursor
DEF PROCshowCursor
PRINT CHR$(27);"[?25h";
RETPROC
REM display text to editor window
DEF PROCtext
PROChideCursor
PROCdraw
CURSOR 1, 2
FOR l = top TO top + TERMHEIGHT - 2
PROCclearLineFromCursor
IF l < max THEN PRINT LEFT$(content$(l), TERMWIDTH)
NEXT
PROCshowCursor
RETPROC
REM load a file into the array, translating TAB to four spaces
DEF PROCload(file$)
IF file$ = "" THEN RETPROC
FH = OPENIN(file$)
IF FH < 0 THEN PROCfail
lines = 0
REPEAT
rawLine$ = READ$(FH)
processed$ = ""
FOR N = 0 TO LEN(rawLine$)
char$ = MID$(rawLine$, N, N+1)
IF char$ = CHR$(9) THEN processed$ = processed$ + " "
IF char$ > CHR$(9) THEN processed$ = processed$ + char$
NEXT
content$(lines) = processed$
lines = lines + 1
IF lines = max THEN PROCgrow
UNTIL EOF(FH) = 1
CLOSE FH
RETPROC
REM increase array used to store text
DEF PROCgrow
max = max + 100
REDIM content$, max
RETPROC
REM error handler
DEF PROCfail
PRINT "Could not open file: "; ARGS$
END
RETPROC
REM handle editor input loop
DEF PROCedit
REPEAT
CURSOR currentx + 1, currenty + 2
key$ = INKEY$
IF key$ > "" THEN PROCprocessKey(ASC(key$))
UNTIL FALSE
RETPROC
REM handle keypress
DEF PROCprocessKey(in)
incopy = in
ctrl = CTRLKEY
IF ctrl = TRUE THEN PROCctrl(CHR$(incopy))
IF ctrl = TRUE THEN RETPROC
IF in = 27 THEN PROCquit
IF in = 13 THEN PROCenter
IF in = 250 THEN PROCup
IF in = 251 THEN PROCdown
IF in = 252 THEN PROCleft
IF in = 253 THEN PROCright
IF in = 249 THEN PROCend
IF in = 254 THEN PROChome
IF in = 245 THEN PROCpageUp
IF in = 246 THEN PROCpageDown
IF in = 247 THEN PROCdelete
IF in = 8 THEN PROCbackSpace
IF (in < 128) AND (in > 31) THEN PROCinsertChar(incopy)
cx = LEN(content$(top + currenty))
IF currentx > cx THEN currentx = cx
IF (currenty + top) > (lines - 1) THEN currenty = lines - top - 1
RETPROC
REM insert character at current position and advance right
DEF PROCinsertChar(i)
start$ = MID$(content$(top + currenty), 0, currentx)
end$ = MID$(content$(top + currenty), currentx, LEN(content$(top + currenty)))
content$(top + currenty) = start$ + CHR$(i) + end$
currentx = currentx + 1
dirty = TRUE
PROCtext
RETPROC
REM handle CTRL+key
DEF PROCctrl(ctrlkey$)
IF UPPER$(ctrlkey$) = "S" THEN PROCsave
IF UPPER$(ctrlkey$) = "W" THEN PROCsearch
IF UPPER$(ctrlkey$) = "R" THEN PROCreplace
PROCtext
RETPROC
REM handle save
DEF PROCsave
IF ARGS$ = "" THEN PROCsaveNew
IF ARGS$ = "" THEN RETPROC
PROCsaveAs
RETPROC
REM handle save over existing file
DEF PROCsaveAs
PROCprompt("Save as [" + ARGS$ + "]")
INPUT file$
IF file$ = "" THEN file$ = ARGS$
PROCdoSave(file$)
RETPROC
REM handle save to new file
DEF PROCsaveNew
PROCprompt("Save as")
INPUT file$
PROCdoSave(file$)
RETPROC
REM save file
DEF PROCdoSave(saveFileName$)
FH = OPENOUT(saveFileName$)
IF FH < 0 THEN PROCsaveError(saveFileName$)
IF FH < 0 THEN RETPROC
REM write file line by line
FOR X = 0 TO lines
WRITE FH, content$(X)
NEXT
CLOSE FH
dirty = FALSE
RETPROC
REM display save error
DEF PROCsaveError
PROCprompt("Unable to save file! Press any key to continue")
REPEAT
UNTIL INKEY$ > ""
RETPROC
REM text search
DEF PROCsearch
PROCprompt("Search text")
INPUT find$
RETPROC
REM search and replace
DEF PROCreplace
PROCprompt("Search text")
INPUT find$
PROCprompt("Replace text")
INPUT replace$
dirty = TRUE
RETPROC
REM handle escape key
DEF PROCquit
IF dirty = TRUE THEN PROCconfirm
IF dirty = TRUE THEN RETPROC
CLS
END
RETPROC
REM confirm exit if file contents changed
DEF PROCconfirm
PROCprompt("Contents changed. Are you sure?")
REPEAT
input$ = INKEY$
UNTIL input$ > ""
PROCtext
IF UPPER$(input$) = "N" THEN RETPROC
CLS
END
RETPROC
REM handle cursor left key
DEF PROCleft
currentx = currentx - 1
IF currentx < 0 THEN currentx = 0
PROCtext
RETPROC
REM handle cursor up key
DEF PROCup
currenty = currenty - 1
IF currenty < 0 THEN PROCscrollUp
PROCtext
RETPROC
REM handle cursor down key
DEF PROCdown
currenty = currenty + 1
IF currenty > (TERMHEIGHT - 3) THEN PROCscrollDown
PROCtext
RETPROC
REM scroll screen down one line
DEF PROCscrollDown
currenty = TERMHEIGHT - 3
top = top + 1
IF top > (TERMHEIGHT - 2 + lines) THEN top = TERMHEIGHT - 2 + lines
PROCtext
RETPROC
REM Scroll screen up one line
DEF PROCscrollUp
currenty = 0
top = top - 1
IF top < 0 THEN top = 0
RETPROC
REM handle cursor right key
DEF PROCright
currentx = currentx + 1
IF currentx > (TERMWIDTH - 1) THEN currentx = TERMWIDTH - 1
PROCtext
RETPROC
REM handle end key
DEF PROCend
currentx = LEN(content$(top + currenty))
IF currentx > (TERMWIDTH - 1) THEN currentx = TERMWIDTH - 1
PROCtext
RETPROC
REM handle home key
DEF PROChome
currentx = 0
PROCtext
RETPROC
REM handle page up key
DEF PROCpageUp
top = top - TERMHEIGHT - 2
IF top < 0 THEN top = 0
PROCtext
RETPROC
REM handle page down key
DEF PROCpageDown
IF (top + currenty + TERMHEIGHT - 2) > (lines - 1) THEN RETPROC
top = top + TERMHEIGHT - 2
IF top > (TERMHEIGHT - 2 + lines) THEN top = TERMHEIGHT - 2 + lines
PROCtext
RETPROC
REM handle enter key, split line if neccessary
DEF PROCenter
currentLine$ = content$(top + currenty)
start$ = MID$(currentLine$, 0, currentx)
end$ = MID$(currentLine$, currentx, LEN(currentLine$))
REM push lines below down
PUSH content$, top + currenty
content$(top + currenty) = start$
content$(top + currenty + 1) = end$
currentx = 0
currenty = currenty + 1
lines = lines + 1
IF lines = max THEN PROCgrow
IF currenty > (TERMHEIGHT - 3) THEN PROCscrollDown
dirty = TRUE
PROCtext
RETPROC
REM handle delete key, join line if neccessary
DEF PROCdelete
currentLine$ = content$(top + currenty)
len = LEN(currentLine$)
IF currentx > (len - 1) THEN PROCjoin
IF currentx < len THEN PROCdeleteRight
dirty = TRUE
PROCtext
RETPROC
REM handle backspace
DEF PROCbackSpace
cx = currentx
IF cx = 0 THEN PROCjoinAbove
IF cx > 0 THEN PROCdeleteLeft
dirty = TRUE
PROCtext
RETPROC
REM delete character to left of cursor, advance left
DEF PROCdeleteLeft
start$ = MID$(content$(top + currenty), 0, currentx - 1)
end$ = MID$(content$(top + currenty), currentx, LEN(content$(top + currenty)))
content$(top + currenty) = start$ + end$
currentx = currentx - 1
RETPROC
REM delete one character to the right
DEF PROCdeleteRight
start$ = MID$(content$(top + currenty), 0, currentx)
end$ = MID$(content$(top + currenty), currentx + 1, LEN(content$(top + currenty)))
content$(top + currenty) = start$ + end$
RETPROC
REM join the end of the current line to the line below, moving lines up
DEF PROCjoin
IF currenty = (lines - 1) THEN RETPROC
content$(top + currenty) = content$(top + currenty) + content$(top + currenty + 1)
POP content$, top + currenty + 1
content$(lines - 1) = ""
lines = lines - 1
RETPROC
REM join the start of the current line to the line above, moving lines up
DEF PROCjoinAbove
IF currenty = 0 THEN RETPROC
newcurrentx = LEN(content$(top + currenty - 1))
content$(top + currenty - 1) = content$(top + currenty - 1) + content$(top + currenty)
POP content$, top + currenty
content$(lines - 1) = ""
currentx = newcurrentx
currenty = currenty - 1
lines = lines - 1
RETPROC