190 lines
6.3 KiB
C++
190 lines
6.3 KiB
C++
#include <stdio.h>
|
||
#include <disp.h>
|
||
#include <sedit.hpp>
|
||
|
||
typedef void (* PFC)(int,char *);
|
||
extern void default_error(int,char *);
|
||
PFC sedit_handler = default_error;
|
||
|
||
enum { BS = 0x0e08, ESC = 0x011b, DEL = 0x5300, INS = 0x5200, LCUR = 0x4b00,
|
||
RCUR = 0x4d00, WLEFT = 0x7300, WRIGHT = 0x7400, HOME = 0x4700,
|
||
END = 0x4f00, RET = 0x1c0d, UCUR = 0x4800, DCUR = 0x5000,
|
||
CTRLEND = 0x7500, CTRLHOME = 0x7700 };
|
||
|
||
string_editor::string_editor(int ml, int insmode)
|
||
{
|
||
maxlength = ml; insert = insmode;
|
||
howlong = where = -1;
|
||
local = new char[ml+1];
|
||
if (!local)
|
||
sedit_handler(ENOMEM,"line editor - not enough memory");
|
||
}
|
||
|
||
int string_editor::edit(int arow, int acol, char *s, int fillin, int sc, int dc)
|
||
{
|
||
char c, *p, *q, *r;
|
||
int fv, i, kc, cc = acol+sc;
|
||
|
||
if (fillin) { // string not visible
|
||
disp_move(arow,acol);
|
||
if (*s)
|
||
disp_printf("%s",s);
|
||
else // or not relevant
|
||
disp_printf("%*c",maxlength,' ');
|
||
}
|
||
p = s+sc;
|
||
howlong = strlen(s);
|
||
strcpy(local,s); // in case edit abandoned
|
||
q = s+howlong; // q points beyond end of string
|
||
disp_move(arow,acol+sc);
|
||
disp_flush();
|
||
for (;;) {
|
||
kc = dc? dc: command_source();
|
||
c = kc = convertor(kc,s,p-s);
|
||
if (!insert && kc == DEL) // it not insert mode
|
||
c = kc = 0x3920; // treat DEL as space
|
||
if (kc == BS) {
|
||
if (p > s) {
|
||
--p;
|
||
disp_putc('\b'); // backspace
|
||
if (insert) {
|
||
howlong--; // adjust length
|
||
q--; // and tail pointer
|
||
r = p;
|
||
while ((*r = *(r+1)) != '\0') {
|
||
disp_putc(*r);
|
||
r++; // move tail down one
|
||
}
|
||
} else
|
||
*p = ' '; // otherwise just blank the position
|
||
cc--;
|
||
disp_putc(' '); // blank position or old last char
|
||
disp_move(arow,cc);
|
||
disp_flush();
|
||
}
|
||
} else if (kc == DEL) {
|
||
if (p == q) // at end - nothing to delete
|
||
continue;
|
||
r = p;
|
||
while ((*r = *(r+1)) != '\0') {
|
||
disp_putc(*r); // move tail down one
|
||
r++;
|
||
}
|
||
disp_putc(' '); // blank last char
|
||
disp_move(arow,cc);
|
||
disp_flush();
|
||
*--q = '\0';
|
||
howlong--;
|
||
} else if (kc == CTRLHOME) {
|
||
strcpy(s,p);
|
||
i = strlen(s);
|
||
disp_move(arow,acol);
|
||
disp_printf("%s%*c",s,howlong-i,' ');
|
||
disp_move(arow,acol);
|
||
disp_flush();
|
||
p = s;
|
||
q = s+i;
|
||
howlong = i;
|
||
cc = acol;
|
||
} else if (kc == CTRLEND) {
|
||
q = p;
|
||
*p = '\0';
|
||
i = strlen(s);
|
||
disp_printf("%*c",howlong-i,' ');
|
||
disp_move(arow,cc);
|
||
disp_flush();
|
||
howlong = i;
|
||
} else if (kc == INS) {
|
||
insert = !insert; // toggle insert mode
|
||
} else if (kc == LCUR && p > s) {
|
||
p--;
|
||
cc--;
|
||
disp_move(arow,cc); // left one char
|
||
disp_flush();
|
||
} else if (kc == RCUR && p < q) {
|
||
p++;
|
||
cc++;
|
||
disp_move(arow,cc); // right one char
|
||
disp_flush();
|
||
} else if (kc == WLEFT && p > s) {
|
||
do {
|
||
p--;
|
||
cc--;
|
||
} while (p > s && !(*(p-1) == ' ' && *p != ' '));
|
||
disp_move(arow,cc); // word left
|
||
disp_flush();
|
||
} else if (kc == WRIGHT && p < q) {
|
||
do {
|
||
p++;
|
||
cc++;
|
||
} while (p < q && !(*(p-1) == ' ' && *p != ' '));
|
||
disp_move(arow,cc); // word right
|
||
disp_flush();
|
||
} else if (kc == HOME) {
|
||
p = s;
|
||
cc = acol;
|
||
disp_move(arow,cc); // left hand end
|
||
disp_flush();
|
||
} else if (kc == END) {
|
||
p = q;
|
||
cc = acol+howlong;
|
||
disp_move(arow,cc); // right hand end
|
||
disp_flush();
|
||
} else if (kc == RET || kc == UCUR || kc == DCUR) {
|
||
for (--q; *q == ' '; --q) ; // strip trailing blanks
|
||
*++q = '\0'; // terminate
|
||
where = p-s;
|
||
return(kc ==RET? 1:(kc == UCUR? 2: 3));
|
||
} else if (kc == ESC) {
|
||
strcpy(s,local); // restore original
|
||
where = p-s;
|
||
return(0);
|
||
} else if ((fv = filter(c,s,p-s)) != 0) {
|
||
// is the character acceptable?
|
||
if (insert) {
|
||
if (howlong < maxlength) {
|
||
r = q+1;
|
||
while (r > p) {
|
||
*r = *(r-1);
|
||
r--; // move tail along
|
||
}
|
||
disp_printf(" %s",r+1);
|
||
*r = c;
|
||
howlong++;
|
||
q++;
|
||
p++;
|
||
goto update;
|
||
} else putchar(7); // already at max length - beep
|
||
} else if (p == q) {
|
||
if (howlong < maxlength) {
|
||
howlong++;
|
||
*++q = '\0';
|
||
*p++ = c;
|
||
goto update;
|
||
} else putchar(7);
|
||
} else {
|
||
*p++ = c; // overwrite existing character
|
||
update:
|
||
disp_move(arow,cc);
|
||
disp_flush();
|
||
disp_putc(c); // display the character
|
||
disp_flush();
|
||
cc++;
|
||
}
|
||
} else if (fv == 0) // bad char beep it
|
||
putchar(7);
|
||
// else just ignore it
|
||
if (dc) {
|
||
where = p-s;
|
||
return 4; // single command mode
|
||
}
|
||
}
|
||
}
|
||
|
||
PFC set_sedit_handler(PFC handler)
|
||
{
|
||
PFC local = sedit_handler;
|
||
sedit_handler = handler;
|
||
return local;
|
||
}
|
||
|