-
Notifications
You must be signed in to change notification settings - Fork 10
/
Copy pathte_edit.c
490 lines (403 loc) · 9.89 KB
/
te_edit.c
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
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
/* te_edit.c
Text editor.
Edit line.
Copyright (c) 2015-2021 Miguel Garcia / FloppySoftware
This program is free software; you can redistribute it and/or modify it
under the terms of the GNU General Public License as published by the
Free Software Foundation; either version 2, or (at your option) any
later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
Changes:
30 Jan 2018 : Extracted from te.c.
04 Feb 2018 : Support for macros. Go to line #.
22 Feb 2018 : Check for buffer changes.
26 Dec 2018 : Use TAB_COLS instead of 8.
06 Jan 2019 : Speed improvements. Now cut deletes the line. Now paste inserts a new line before the current one.
08 Jan 2019 : BfEdit() now uses ModifyLine().
13 Jan 2019 : Minor optimizations.
18 Jan 2019 : Unselect block if needed.
18 Jan 2018 : Added K_DELETE.
27 Jan 2019 : Added support for macros.
29 Jan 2019 : Added K_CLRCLP.
24 Dec 2019 : Added support for line numbers.
26 Dec 2019 : Now K_INTRO is K_CR.
01 Mar 2020 : Added CLANG support. Set fe_forced flag in ForceGetCh().
04 Jan 2021 : Use configuration variables.
25 Sep 2021 : Ignore '\0' characters comming from macro comments. Use editln variable.
*/
/* Edit current line
-----------------
Returns last character entered.
*/
BfEdit()
{
int i, ch, len, run, upd_lin, upd_col, upd_now, upd_cur, spc, old_len;
char *buf;
/* Tell we are editing */
editln = 1;
/* Get current line contents */
strcpy(ln_dat, lp_arr[lp_cur]);
/* Setup some things */
len = old_len = strlen(ln_dat);
run = upd_col = upd_now = upd_cur = 1; upd_lin = spc = 0;
/* Adjust column position */
if(box_shc > len)
box_shc = len;
/* Loop */
while(run)
{
/* Print line? */
if(upd_lin)
{
upd_lin = 0;
putstr(ln_dat + box_shc);
/* Print a space? */
if(spc)
{
putchr(' '); spc = 0;
}
}
/* Print length? */
if(upd_now)
{
upd_now = 0;
CrtLocate(PS_ROW, PS_COL_NOW); putint("%02d", len);
}
/* Print column #? */
if(upd_col)
{
upd_col = 0;
CrtLocate(PS_ROW, PS_COL_CUR); putint("%02d", box_shc + 1);
}
/* Locate cursor? */
if(upd_cur)
{
upd_cur = 0;
CrtLocate(BOX_ROW + box_shr, box_shc + cf_num);
}
/* Get character and do action */
#if OPT_MACRO
while((ch = ForceGetCh()) == 0)
;
#else
ch = ForceGetCh();
#endif
#if OPT_BLOCK
/* Unselect block if needed: don't check blk_count, we want to unselect start and / or end block selection */
if(blk_start != -1 || blk_end != -1) {
if(ch < 1000) {
upd_cur = 1;
}
else {
switch(ch)
{
case K_CR :
case K_TAB :
case K_LDEL :
case K_RDEL :
case K_PASTE :
case K_MACRO :
upd_cur = 1;
break;
}
}
if(upd_cur) {
LoopBlkUnset();
CrtLocate(BOX_ROW + box_shr, box_shc + cf_num);
upd_cur = 0;
}
}
#endif
if(ch < 1000)
{
if(len < ln_max)
{
putchr(ch);
for(i = len; i > box_shc; --i)
{
ln_dat[i] = ln_dat[i - 1];
}
ln_dat[box_shc++] = ch; ln_dat[++len] = 0;
++upd_lin; ++upd_now; ++upd_col;
if(cf_clang) {
#if OPT_MACRO
if(!MacroRunning())
{
#endif
switch(ch)
{
case '[' : ForceChLeft(len, ']'); break;
case '{' : ForceChLeft(len, '}'); break;
case '(' : ForceChLeft(len, ')'); break;
case '"' : ForceChLeft(len, '"'); break;
case '\'' : ForceChLeft(len, '\''); break;
case '*' : if(box_shc > 1 && ln_dat[box_shc - 2] == '/' && len + 1 < ln_max) { ForceStr("*/"); ForceCh(K_LEFT); ForceCh(K_LEFT);} break;
}
#if OPT_MACRO
}
#endif
}
}
++upd_cur;
}
else
{
/* Note: This function does preliminary checks in some
keys for Loop(), to avoid wasted time. */
switch(ch)
{
case K_LEFT : /* Move one character to the left -------- */
if(box_shc)
{
--box_shc; ++upd_col;
}
else if(lp_cur)
{
box_shc = 9999 /* strlen(lp_arr[lp_cur - 1]) */ ;
ch = K_UP;
run = 0;
}
++upd_cur;
break;
case K_RIGHT : /* Move one character to the right ------- */
if(box_shc < len)
{
++box_shc; ++upd_col;
}
else if(lp_cur < lp_now - 1)
{
ch = K_DOWN;
box_shc = run = 0;
}
++upd_cur;
break;
case K_LDEL : /* Delete one character to the left ------- */
if(box_shc)
{
strcpy(ln_dat + box_shc - 1, ln_dat + box_shc);
--box_shc; --len; ++upd_now; ++upd_lin; ++spc; ++upd_col;
putchr('\b');
}
else if(lp_cur)
run = 0;
++upd_cur;
break;
case K_RDEL : /* Delete one character to the right ----- */
if(box_shc < len)
{
strcpy(ln_dat + box_shc, ln_dat + box_shc + 1);
--len; ++upd_now; ++upd_lin; ++spc;
}
else if(lp_cur < lp_now -1)
run = 0;
++upd_cur;
break;
case K_UP : /* Up one line --------------------------- */
if(lp_cur)
run = 0;
++upd_cur;
break;
case K_DOWN : /* One line down ------------------------- */
if(lp_cur < lp_now - 1)
run = 0;
++upd_cur;
break;
#if OPT_BLOCK
case K_BLK_START : /* Set block start -------------------- */
case K_BLK_END : /* Set block end ---------------------- */
case K_BLK_UNSET : /* Unset block ----------------------- */
#endif
#if OPT_GOTO
case K_GOTO : /* Go to line # -------------------------- */
#endif
#if OPT_MACRO
case K_MACRO : /* Execute macro from file -------------- */
#endif
case K_COPY : /* Copy block/line to the clipboard ------ */
case K_CUT : /* Copy and delete block/line ------------ */
case K_PASTE : /* Paste clipboard before the current line */
case K_DELETE : /* Delete block/line --------------------- */
case K_CLRCLP : /* Clear the clipboard ------------------- */
case K_ESC : /* Escape: Show the menu ----------------- */
case K_CR : /* Insert CR (split the line) ------------ */
run = 0;
break;
case K_PGUP : /* Page up ------------------------------- */
case K_TOP : /* Document top -------------------------- */
if(lp_cur || box_shc)
run = 0;
++upd_cur;
break;
case K_PGDOWN : /* Page down ----------------------------- */
case K_BOTTOM : /* Document bottom ----------------------- */
if(lp_cur < lp_now - 1 || box_shc != len)
run = 0;
++upd_cur;
break;
case K_BEGIN : /* Begin of line ------------------------- */
if(box_shc)
{
box_shc = 0; ++upd_col;
}
++upd_cur;
break;
case K_END : /* End of line --------------------------- */
if(box_shc != len)
{
box_shc = len; ++upd_col;
}
++upd_cur;
break;
case K_TAB : /* Insert TAB (spaces) ------------------- */
i = cf_tab_cols - box_shc % cf_tab_cols;
while(i--)
{
if(ForceCh(' '))
break;
}
break;
#if OPT_LWORD
case K_LWORD : /* Move one word to the left ------------ */
if(box_shc)
{
/* Skip the current word if we are at its begining */
if(ln_dat[box_shc] != ' ' && ln_dat[box_shc - 1] == ' ')
--box_shc;
/* Skip spaces */
while(box_shc && ln_dat[box_shc] == ' ')
--box_shc;
/* Find the beginning of the word */
while(box_shc && ln_dat[box_shc] != ' ')
{
/* Go to the beginning of the word */
if(ln_dat[--box_shc] == ' ')
{
++box_shc; break;
}
}
++upd_col;
}
++upd_cur;
break;
#endif
#if OPT_RWORD
case K_RWORD : /* Move one word to the right ----------- */
/* Skip current word */
while(ln_dat[box_shc] && ln_dat[box_shc] != ' ')
++box_shc;
/* Skip spaces */
while(ln_dat[box_shc] == ' ')
++box_shc;
++upd_col; ++upd_cur;
break;
#endif
#if OPT_FIND
case K_FIND : /* Find string -------------------------- */
run = 0;
break;
case K_NEXT : /* Find next string --------------------- */
if(find_str[0])
run = 0;
break;
#endif
}
}
}
/* Update changes if any */
if(len == old_len)
{
/* Check for changes */
if(memcmp(lp_arr[lp_cur], ln_dat, len))
{
/* Update the changes */
strcpy(lp_arr[lp_cur], ln_dat);
/* Changes are not saved */
lp_chg = 1;
}
}
else {
ModifyLine(lp_cur, ln_dat); /* FIX-ME: Re-print the line with old contents in case of error? */
/* Changes are not saved */
lp_chg = 1;
}
/* Tell we are not editing */
editln = 0;
/* Return last character entered */
return ch;
}
/* Add a character to forced entry buffer
--------------------------------------
Return Z on success, NZ on failure.
*/
ForceCh(ch)
int ch;
{
if(fe_now < FORCED_MAX)
{
++fe_now;
if(fe_set == FORCED_MAX)
fe_set = 0;
fe_dat[fe_set++] = ch;
return 0;
}
return -1;
}
/* Add a string to forced entry buffer
-----------------------------------
Return Z on success, NZ on failure.
*/
ForceStr(s)
char *s;
{
while(*s)
{
if(ForceCh(*s++))
return -1;
}
return 0;
}
/* Return character from forced entry buffer, or keyboard
------------------------------------------------------
*/
ForceGetCh()
{
if(fe_now)
{
--fe_now;
if(fe_get == FORCED_MAX)
fe_get = 0;
fe_forced = 1;
return fe_dat[fe_get++];
}
#if OPT_MACRO
if(MacroRunning()) {
MacroGet();
if(fe_now) {
return ForceGetCh();
}
}
#endif
fe_forced = 0;
return getchr();
}
/* Single character completion for C language, etc.
------------------------------------------------
*/
ForceChLeft(len, ch)
int len, ch;
{
if(!fe_forced)
{
if(len < ln_max)
{
ForceCh(ch); ForceCh(K_LEFT);
}
}
}