File indexing completed on 2025-05-11 08:24:19
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016
0017
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 #include <signal.h>
0035 #include <limits.h>
0036 #include <stdlib.h>
0037 #include <stdio.h>
0038 #include <stdarg.h>
0039 #include <string.h>
0040 #include <errno.h>
0041 #include <fcntl.h>
0042 #include <unistd.h>
0043 #include <sys/stat.h>
0044
0045 #ifdef SANOS
0046 #include <os.h>
0047 #endif
0048
0049 #ifdef __rtems__
0050 #include <assert.h>
0051 #include <rtems.h>
0052 #include <rtems/shell.h>
0053 #endif
0054
0055 #if defined(__linux__) || defined(__rtems__)
0056 #include <sys/ioctl.h>
0057 #include <termios.h>
0058 #ifndef O_BINARY
0059 #define O_BINARY 0
0060 #endif
0061 static int linux_console;
0062 #endif
0063
0064 #define MINEXTEND 32768
0065 #define LINEBUF_EXTRA 32
0066
0067 #ifndef TABSIZE
0068 #define TABSIZE 8
0069 #endif
0070
0071 #ifndef INDENT
0072 #define INDENT " "
0073 #endif
0074
0075 #define CLRSCR "\033[0J\x1b[H\x1b[J"
0076 #define CLREOL "\033[K"
0077 #define GOTOXY "\033[%d;%dH"
0078 #define RESET_COLOR "\033[0m"
0079
0080 #ifdef COLOR
0081 #define TEXT_COLOR "\033[44m\033[37m\033[1m"
0082 #define SELECT_COLOR "\033[47m\033[37m\033[1m"
0083 #define STATUS_COLOR "\033[0m\033[47m\033[30m"
0084 #else
0085 #define TEXT_COLOR "\033[0m"
0086 #define SELECT_COLOR "\033[7m\033[1m"
0087 #define STATUS_COLOR "\033[1m\033[7m"
0088 #endif
0089
0090
0091
0092
0093
0094 #define KEY_BACKSPACE 0x101
0095 #define KEY_ESC 0x102
0096 #define KEY_INS 0x103
0097 #define KEY_DEL 0x104
0098 #define KEY_LEFT 0x105
0099 #define KEY_RIGHT 0x106
0100 #define KEY_UP 0x107
0101 #define KEY_DOWN 0x108
0102 #define KEY_HOME 0x109
0103 #define KEY_END 0x10A
0104 #define KEY_ENTER 0x10B
0105 #define KEY_TAB 0x10C
0106 #define KEY_PGUP 0x10D
0107 #define KEY_PGDN 0x10E
0108
0109 #define KEY_CTRL_LEFT 0x10F
0110 #define KEY_CTRL_RIGHT 0x110
0111 #define KEY_CTRL_UP 0x111
0112 #define KEY_CTRL_DOWN 0x112
0113 #define KEY_CTRL_HOME 0x113
0114 #define KEY_CTRL_END 0x114
0115 #define KEY_CTRL_TAB 0x115
0116
0117 #define KEY_SHIFT_LEFT 0x116
0118 #define KEY_SHIFT_RIGHT 0x117
0119 #define KEY_SHIFT_UP 0x118
0120 #define KEY_SHIFT_DOWN 0x119
0121 #define KEY_SHIFT_PGUP 0x11A
0122 #define KEY_SHIFT_PGDN 0x11B
0123 #define KEY_SHIFT_HOME 0x11C
0124 #define KEY_SHIFT_END 0x11D
0125 #define KEY_SHIFT_TAB 0x11E
0126
0127 #define KEY_SHIFT_CTRL_LEFT 0x11F
0128 #define KEY_SHIFT_CTRL_RIGHT 0x120
0129 #define KEY_SHIFT_CTRL_UP 0x121
0130 #define KEY_SHIFT_CTRL_DOWN 0x122
0131 #define KEY_SHIFT_CTRL_HOME 0x123
0132 #define KEY_SHIFT_CTRL_END 0x124
0133
0134 #define KEY_F1 0x125
0135 #define KEY_F2 0x126
0136 #define KEY_F3 0x127
0137 #define KEY_F4 0x128
0138 #define KEY_F5 0x129
0139 #define KEY_F6 0x12a
0140 #define KEY_F7 0x12b
0141 #define KEY_F8 0x12c
0142 #define KEY_F9 0x12d
0143 #define KEY_F10 0x12e
0144
0145 #define KEY_UNKNOWN 0xFFF
0146
0147 #define ctrl(c) ((c) - 0x60)
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162 struct env;
0163
0164 struct undo {
0165 int pos;
0166 int erased;
0167 int inserted;
0168 unsigned char *undobuf;
0169 unsigned char *redobuf;
0170 struct undo *next;
0171 struct undo *prev;
0172 };
0173
0174 struct editor {
0175 unsigned char *start;
0176 unsigned char *gap;
0177 unsigned char *rest;
0178 unsigned char *end;
0179
0180 int toppos;
0181 int topline;
0182 int margin;
0183
0184 int linepos;
0185 int line;
0186 int col;
0187 int lastcol;
0188 int anchor;
0189
0190 struct undo *undohead;
0191 struct undo *undotail;
0192 struct undo *undo;
0193
0194 int refresh;
0195 int lineupdate;
0196 int dirty;
0197
0198 int newfile;
0199 int permissions;
0200
0201 int selecting;
0202
0203 struct env *env;
0204 struct editor *next;
0205 struct editor *prev;
0206
0207 char filename[FILENAME_MAX];
0208 };
0209
0210 struct env {
0211 struct editor *current;
0212
0213 unsigned char *clipboard;
0214 int clipsize;
0215
0216 unsigned char *search;
0217 unsigned char *linebuf;
0218
0219 int cols;
0220 int lines;
0221
0222 int untitled;
0223 };
0224
0225
0226
0227
0228
0229 static void clear_undo(struct editor *ed) {
0230 struct undo *undo = ed->undohead;
0231 while (undo) {
0232 struct undo *next = undo->next;
0233 free(undo->undobuf);
0234 free(undo->redobuf);
0235 free(undo);
0236 undo = next;
0237 }
0238 ed->undohead = ed->undotail = ed->undo = NULL;
0239 }
0240
0241 static void reset_undo(struct editor *ed) {
0242 while (ed->undotail != ed->undo) {
0243 struct undo *undo = ed->undotail;
0244 if (!undo) {
0245 ed->undohead = NULL;
0246 ed->undotail = NULL;
0247 break;
0248 }
0249 ed->undotail = undo->prev;
0250 if (undo->prev) undo->prev->next = NULL;
0251 free(undo->undobuf);
0252 free(undo->redobuf);
0253 free(undo);
0254 }
0255 ed->undo = ed->undotail;
0256 }
0257
0258 static struct editor *create_editor(struct env *env) {
0259 struct editor *ed = (struct editor *) malloc(sizeof(struct editor));
0260 memset(ed, 0, sizeof(struct editor));
0261 if (env->current) {
0262 ed->next = env->current->next;
0263 ed->prev = env->current;
0264 env->current->next->prev = ed;
0265 env->current->next = ed;
0266 } else {
0267 ed->next = ed->prev = ed;
0268 }
0269 ed->env = env;
0270 env->current = ed;
0271 return ed;
0272 }
0273
0274 static void delete_editor(struct editor *ed) {
0275 if (ed->next == ed) {
0276 ed->env->current = NULL;
0277 } else {
0278 ed->env->current = ed->prev;
0279 }
0280 ed->next->prev = ed->prev;
0281 ed->prev->next = ed->next;
0282 if (ed->start) free(ed->start);
0283 clear_undo(ed);
0284 free(ed);
0285 }
0286
0287 static struct editor *find_editor(struct env *env, char *filename) {
0288 char fnbuf[PATH_MAX];
0289 char *fn = fnbuf;
0290 struct editor *ed = env->current;
0291 struct editor *start = ed;
0292
0293
0294 if (!realpath(filename, fn)) { fn = filename; }
0295
0296 do {
0297 if (strcmp(fn, ed->filename) == 0) return ed;
0298 ed = ed->next;
0299 } while (ed != start);
0300 return NULL;
0301 }
0302
0303 static int new_file(struct editor *ed, char *filename) {
0304 if (*filename) {
0305 strlcpy(ed->filename, filename, sizeof(ed->filename));
0306 } else {
0307 sprintf(ed->filename, "Untitled-%d", ++ed->env->untitled);
0308 ed->newfile = 1;
0309 }
0310 ed->permissions = 0644;
0311
0312 ed->start = (unsigned char *) malloc(MINEXTEND);
0313 if (!ed->start) return -1;
0314 #ifdef DEBUG
0315 memset(ed->start, 0, MINEXTEND);
0316 #endif
0317
0318 ed->gap = ed->start;
0319 ed->rest = ed->end = ed->gap + MINEXTEND;
0320 ed->anchor = -1;
0321
0322 return 0;
0323 }
0324
0325 static int load_file(struct editor *ed, char *filename) {
0326 struct stat statbuf;
0327 int length;
0328 int f;
0329
0330 if (!realpath(filename, ed->filename)) return -1;
0331 f = open(ed->filename, O_RDONLY | O_BINARY);
0332 if (f < 0) return -1;
0333
0334 if (fstat(f, &statbuf) < 0) goto err;
0335 length = statbuf.st_size;
0336 ed->permissions = statbuf.st_mode & 0777;
0337
0338 ed->start = (unsigned char *) malloc(length + MINEXTEND);
0339 if (!ed->start) goto err;
0340 #ifdef DEBUG
0341 memset(ed->start, 0, length + MINEXTEND);
0342 #endif
0343 if (read(f, ed->start, length) != length) goto err;
0344
0345 ed->gap = ed->start + length;
0346 ed->rest = ed->end = ed->gap + MINEXTEND;
0347 ed->anchor = -1;
0348
0349 close(f);
0350 return 0;
0351
0352 err:
0353 close(f);
0354 if (ed->start) {
0355 free(ed->start);
0356 ed->start = NULL;
0357 }
0358 return -1;
0359 }
0360
0361 static int save_file(struct editor *ed) {
0362 int f;
0363
0364 f = open(ed->filename, O_CREAT | O_TRUNC | O_WRONLY, ed->permissions);
0365 if (f < 0) return -1;
0366
0367 if (write(f, ed->start, ed->gap - ed->start) != ed->gap - ed->start) goto err;
0368 if (write(f, ed->rest, ed->end - ed->rest) != ed->end - ed->rest) goto err;
0369
0370 close(f);
0371 ed->dirty = 0;
0372 clear_undo(ed);
0373 return 0;
0374
0375 err:
0376 close(f);
0377 return -1;
0378 }
0379
0380 static int text_length(struct editor *ed) {
0381 return (ed->gap - ed->start) + (ed->end - ed->rest);
0382 }
0383
0384 static unsigned char *text_ptr(struct editor *ed, int pos) {
0385 unsigned char *p = ed->start + pos;
0386 if (p >= ed->gap) p += (ed->rest - ed->gap);
0387 return p;
0388 }
0389
0390 static void move_gap(struct editor *ed, int pos, int minsize) {
0391 int gapsize = ed->rest - ed->gap;
0392 unsigned char *p = text_ptr(ed, pos);
0393 if (minsize < 0) minsize = 0;
0394
0395 if (minsize <= gapsize) {
0396 if (p != ed->rest) {
0397 if (p < ed->gap) {
0398 memmove(p + gapsize, p, ed->gap - p);
0399 } else {
0400 memmove(ed->gap, ed->rest, p - ed->rest);
0401 }
0402 ed->gap = ed->start + pos;
0403 ed->rest = ed->gap + gapsize;
0404 }
0405 } else {
0406 int newsize;
0407 unsigned char *start;
0408 unsigned char *gap;
0409 unsigned char *rest;
0410 unsigned char *end;
0411
0412 if (gapsize + MINEXTEND > minsize) minsize = gapsize + MINEXTEND;
0413 newsize = (ed->end - ed->start) - gapsize + minsize;
0414 start = (unsigned char *) malloc(newsize);
0415 if (start == NULL) {
0416 return;
0417 }
0418 gap = start + pos;
0419 rest = gap + minsize;
0420 end = start + newsize;
0421
0422 if (p < ed->gap) {
0423 memcpy(start, ed->start, pos);
0424 memcpy(rest, p, ed->gap - p);
0425 memcpy(end - (ed->end - ed->rest), ed->rest, ed->end - ed->rest);
0426 } else {
0427 memcpy(start, ed->start, ed->gap - ed->start);
0428 memcpy(start + (ed->gap - ed->start), ed->rest, p - ed->rest);
0429 memcpy(rest, p, ed->end - p);
0430 }
0431
0432 free(ed->start);
0433 ed->start = start;
0434 ed->gap = gap;
0435 ed->rest = rest;
0436 ed->end = end;
0437 }
0438
0439 #ifdef DEBUG
0440 memset(ed->gap, 0, ed->rest - ed->gap);
0441 #endif
0442 }
0443
0444 static void close_gap(struct editor *ed) {
0445 int len = text_length(ed);
0446 move_gap(ed, len, 1);
0447 ed->start[len] = 0;
0448 }
0449
0450 static int get(struct editor *ed, int pos) {
0451 unsigned char *p = text_ptr(ed, pos);
0452 if (p >= ed->end) return -1;
0453 return *p;
0454 }
0455
0456 static int compare(struct editor *ed, unsigned char *buf, int pos, int len) {
0457 unsigned char *bufptr = buf;
0458 unsigned char *p = ed->start + pos;
0459 if (p >= ed->gap) p += (ed->rest - ed->gap);
0460
0461 while (len > 0) {
0462 if (p == ed->end) return 0;
0463 if (*bufptr++ != *p) return 0;
0464 len--;
0465 if (++p == ed->gap) p = ed->rest;
0466 }
0467
0468 return 1;
0469 }
0470
0471 static int copy(struct editor *ed, unsigned char *buf, int pos, int len) {
0472 unsigned char *bufptr = buf;
0473 unsigned char *p = ed->start + pos;
0474 if (p >= ed->gap) p += (ed->rest - ed->gap);
0475
0476 while (len > 0) {
0477 if (p == ed->end) break;
0478 *bufptr++ = *p;
0479 len--;
0480 if (++p == ed->gap) p = ed->rest;
0481 }
0482
0483 return bufptr - buf;
0484 }
0485
0486 static void replace(struct editor *ed, int pos, int len, unsigned char *buf, int bufsize, int doundo) {
0487 unsigned char *p;
0488 struct undo *undo;
0489
0490
0491 if (doundo) {
0492 reset_undo(ed);
0493 undo = ed->undotail;
0494 if (undo && len == 0 && bufsize == 1 && undo->erased == 0 && pos == undo->pos + undo->inserted) {
0495
0496 undo->redobuf = realloc(undo->redobuf, undo->inserted + 1);
0497 undo->redobuf[undo->inserted] = *buf;
0498 undo->inserted++;
0499 } else if (undo && len == 1 && bufsize == 0 && undo->inserted == 0 && pos == undo->pos) {
0500
0501 undo->undobuf = realloc(undo->undobuf, undo->erased + 1);
0502 undo->undobuf[undo->erased] = get(ed, pos);
0503 undo->erased++;
0504 } else if (undo && len == 1 && bufsize == 0 && undo->inserted == 0 && pos == undo->pos - 1) {
0505
0506 undo->pos--;
0507 undo->undobuf = realloc(undo->undobuf, undo->erased + 1);
0508 memmove(undo->undobuf + 1, undo->undobuf, undo->erased);
0509 undo->undobuf[0] = get(ed, pos);
0510 undo->erased++;
0511 } else {
0512
0513 undo = (struct undo *) malloc(sizeof(struct undo));
0514 if (ed->undotail) ed->undotail->next = undo;
0515 undo->prev = ed->undotail;
0516 undo->next = NULL;
0517 ed->undotail = ed->undo = undo;
0518 if (!ed->undohead) ed->undohead = undo;
0519
0520 undo->pos = pos;
0521 undo->erased = len;
0522 undo->inserted = bufsize;
0523 undo->undobuf = undo->redobuf = NULL;
0524 if (len > 0) {
0525 undo->undobuf = malloc(len);
0526 copy(ed, undo->undobuf, pos, len);
0527 }
0528 if (bufsize > 0) {
0529 undo->redobuf = malloc(bufsize);
0530 memcpy(undo->redobuf, buf, bufsize);
0531 }
0532 }
0533 }
0534
0535 p = ed->start + pos;
0536 if (bufsize == 0 && p <= ed->gap && p + len >= ed->gap) {
0537
0538 ed->rest += len - (ed->gap - p);
0539 ed->gap = p;
0540 } else {
0541
0542 move_gap(ed, pos + len, bufsize - len);
0543
0544
0545 memcpy(ed->start + pos, buf, bufsize);
0546 ed->gap = ed->start + pos + bufsize;
0547 }
0548
0549
0550 ed->dirty = 1;
0551 }
0552
0553 static void insert(struct editor *ed, int pos, unsigned char *buf, int bufsize) {
0554 replace(ed, pos, 0, buf, bufsize, 1);
0555 }
0556
0557 static void erase(struct editor *ed, int pos, int len) {
0558 replace(ed, pos, len, NULL, 0, 1);
0559 }
0560
0561
0562
0563
0564
0565 static int line_length(struct editor *ed, int linepos) {
0566 int pos = linepos;
0567 while (1) {
0568 int ch = get(ed, pos);
0569 if (ch < 0 || ch == '\n' || ch == '\r') break;
0570 pos++;
0571 }
0572
0573 return pos - linepos;
0574 }
0575
0576 static int line_start(struct editor *ed, int pos) {
0577 while (1) {
0578 if (pos == 0) break;
0579 if (get(ed, pos - 1) == '\n') break;
0580 pos--;
0581 }
0582
0583 return pos;
0584 }
0585
0586 static int next_line(struct editor *ed, int pos) {
0587 while (1) {
0588 int ch = get(ed, pos);
0589 if (ch < 0) return -1;
0590 pos++;
0591 if (ch == '\n') return pos;
0592 }
0593 }
0594
0595 static int prev_line(struct editor *ed, int pos) {
0596 if (pos == 0) return -1;
0597
0598 while (pos > 0) {
0599 int ch = get(ed, --pos);
0600 if (ch == '\n') break;
0601 }
0602
0603 while (pos > 0) {
0604 int ch = get(ed, --pos);
0605 if (ch == '\n') return pos + 1;
0606 }
0607
0608 return 0;
0609 }
0610
0611 static int column(struct editor *ed, int linepos, int col) {
0612 unsigned char *p = text_ptr(ed, linepos);
0613 int c = 0;
0614 while (col > 0) {
0615 if (p == ed->end) break;
0616 if (*p == '\t') {
0617 int spaces = TABSIZE - c % TABSIZE;
0618 c += spaces;
0619 } else {
0620 c++;
0621 }
0622 col--;
0623 if (++p == ed->gap) p = ed->rest;
0624 }
0625 return c;
0626 }
0627
0628 static void moveto(struct editor *ed, int pos, int center) {
0629 int scroll = 0;
0630 for (;;) {
0631 int cur = ed->linepos + ed->col;
0632 if (pos < cur) {
0633 if (pos >= ed->linepos) {
0634 ed->col = pos - ed->linepos;
0635 } else {
0636 ed->col = 0;
0637 ed->linepos = prev_line(ed, ed->linepos);
0638 ed->line--;
0639
0640 if (ed->topline > ed->line) {
0641 ed->toppos = ed->linepos;
0642 ed->topline--;
0643 ed->refresh = 1;
0644 scroll = 1;
0645 }
0646 }
0647 } else if (pos > cur) {
0648 int next = next_line(ed, ed->linepos);
0649 if (next == -1) {
0650 ed->col = line_length(ed, ed->linepos);
0651 break;
0652 } else if (pos < next) {
0653 ed->col = pos - ed->linepos;
0654 } else {
0655 ed->col = 0;
0656 ed->linepos = next;
0657 ed->line++;
0658
0659 if (ed->line >= ed->topline + ed->env->lines) {
0660 ed->toppos = next_line(ed, ed->toppos);
0661 ed->topline++;
0662 ed->refresh = 1;
0663 scroll = 1;
0664 }
0665 }
0666 } else {
0667 break;
0668 }
0669 }
0670
0671 if (scroll && center) {
0672 int tl = ed->line - ed->env->lines / 2;
0673 if (tl < 0) tl = 0;
0674 for (;;) {
0675 if (ed->topline > tl) {
0676 ed->toppos = prev_line(ed, ed->toppos);
0677 ed->topline--;
0678 } else if (ed->topline < tl) {
0679 ed->toppos = next_line(ed, ed->toppos);
0680 ed->topline++;
0681 } else {
0682 break;
0683 }
0684 }
0685 }
0686 }
0687
0688
0689
0690
0691
0692 static int get_selection(struct editor *ed, size_t *start, size_t *end) {
0693 if (ed->anchor == -1) {
0694 *start = *end = -1;
0695 return 0;
0696 } else {
0697 int pos = ed->linepos + ed->col;
0698 if (pos == ed->anchor) {
0699 *start = *end = -1;
0700 return 0;
0701 } else if (pos < ed->anchor) {
0702 *start = pos;
0703 *end = ed->anchor;
0704 } else {
0705 *start = ed->anchor;
0706 *end = pos;
0707 }
0708 }
0709 return 1;
0710 }
0711
0712 static int get_selected_text(struct editor *ed, char *buffer, int size) {
0713 size_t selstart, selend, len;
0714
0715 if (!get_selection(ed, &selstart, &selend)) return 0;
0716 len = selend - selstart;
0717 if (len >= size) return 0;
0718 copy(ed, (unsigned char*) buffer, selstart, len);
0719 buffer[len] = 0;
0720 return len;
0721 }
0722
0723 static void update_selection(struct editor *ed, int select) {
0724 if (select) {
0725 if (ed->anchor == -1) ed->anchor = ed->linepos + ed->col;
0726 ed->refresh = 1;
0727 } else {
0728 if (ed->anchor != -1) ed->refresh = 1;
0729 ed->anchor = -1;
0730 }
0731 }
0732
0733 static int erase_selection(struct editor *ed) {
0734 size_t selstart, selend;
0735
0736 if (!get_selection(ed, &selstart, &selend)) return 0;
0737 moveto(ed, selstart, 0);
0738 erase(ed, selstart, selend - selstart);
0739 ed->anchor = -1;
0740 ed->refresh = 1;
0741 return 1;
0742 }
0743
0744 static void select_all(struct editor *ed) {
0745 ed->anchor = 0;
0746 ed->refresh = 1;
0747 moveto(ed, text_length(ed), 0);
0748 }
0749
0750
0751
0752
0753
0754 static void get_console_size(struct env *env) {
0755 #ifdef __linux__
0756 struct winsize ws;
0757 ioctl(0, TIOCGWINSZ, &ws);
0758 env->cols = ws.ws_col;
0759 env->lines = ws.ws_row - 1;
0760 #elif defined(__rtems__)
0761 char* e;
0762 env->lines = 25;
0763 env->cols = 80;
0764 e = getenv("LINES");
0765 if (e != NULL) {
0766 int lines = strtol(e, 0, 10);
0767 if (lines > 0) {
0768 env->lines = lines - 1;
0769 }
0770 }
0771 e = getenv("COLUMNS");
0772 if (e != NULL) {
0773 int cols = strtol(e, 0, 10);
0774 if (cols > 0) {
0775 env->cols = cols;
0776 }
0777 }
0778 #else
0779 struct term *term = gettib()->proc->term;
0780 env->cols = term->cols;
0781 env->lines = term->lines - 1;
0782 #endif
0783 env->linebuf = realloc(env->linebuf, env->cols + LINEBUF_EXTRA);
0784 }
0785
0786 static void outch(char c) {
0787 putchar(c);
0788 }
0789
0790 static void outbuf(unsigned char *buf, int len) {
0791 fwrite(buf, 1, len, stdout);
0792 }
0793
0794 static void outstr(char *str) {
0795 fputs(str, stdout);
0796 }
0797
0798 static void clear_screen(void) {
0799 outstr(CLRSCR);
0800 }
0801
0802 static void gotoxy(int col, int line) {
0803 char buf[32];
0804
0805 sprintf(buf, GOTOXY, line + 1, col + 1);
0806 outstr(buf);
0807 }
0808
0809
0810
0811
0812
0813 static void get_modifier_keys(int *shift, int *ctrl) {
0814 *shift = *ctrl = 0;
0815 #ifdef __linux__
0816 if (linux_console) {
0817 char modifiers = 6;
0818 if (ioctl(0, TIOCLINUX, &modifiers) >= 0) {
0819 if (modifiers & 1) *shift = 1;
0820 if (modifiers & 4) *ctrl = 1;
0821 }
0822 }
0823 #endif
0824 }
0825
0826 static int getachar(void)
0827 {
0828 int ch = getchar();
0829 return ch;
0830 }
0831
0832 static int getkey(void) {
0833 int ch, shift, ctrl;
0834
0835 ch = getachar();
0836 if (ch < 0) return ch;
0837
0838 switch (ch) {
0839 case 0x08: return KEY_BACKSPACE;
0840 case 0x09:
0841 get_modifier_keys(&shift, &ctrl);
0842 if (shift) return KEY_SHIFT_TAB;
0843 if (ctrl) return KEY_CTRL_TAB;
0844 return KEY_TAB;
0845 #ifdef SANOS
0846 case 0x0D: return gettib()->proc->term->type == TERM_CONSOLE ? KEY_ENTER : KEY_UNKNOWN;
0847 case 0x0A: return gettib()->proc->term->type != TERM_CONSOLE ? KEY_ENTER : KEY_UNKNOWN;
0848 #else
0849 case 0x0D: return KEY_ENTER;
0850 case 0x0A: return KEY_ENTER;
0851 #endif
0852 case 0x1B:
0853 ch = getachar();
0854 switch (ch) {
0855 case 0x1B: return KEY_ESC;
0856 case 0x4F:
0857 ch = getachar();
0858 switch (ch) {
0859 case 0x46: return KEY_END;
0860 case 0x48: return KEY_HOME;
0861 case 0x50: return KEY_F1;
0862 case 0x51: return KEY_F2;
0863 case 0x52: return KEY_F3;
0864 case 0x53: return KEY_F4;
0865 case 0x54: return KEY_F5;
0866 default: return KEY_UNKNOWN;
0867 }
0868 break;
0869
0870 case 0x5B:
0871 get_modifier_keys(&shift, &ctrl);
0872 ch = getachar();
0873 if (ch == 0x31) {
0874 ch = getachar();
0875 switch (ch) {
0876 case 0x35:
0877 return getachar() == 0x7E ? KEY_F5 : KEY_UNKNOWN;
0878 case 0x37:
0879 return getachar() == 0x7E ? KEY_F6 : KEY_UNKNOWN;
0880 case 0x3B:
0881 ch = getachar();
0882 if (ch == 0x7E) return KEY_F7;
0883 if (ch == 0x32) shift = 1;
0884 if (ch == 0x35) ctrl = 1;
0885 if (ch == 0x36) shift = ctrl = 1;
0886 ch = getachar();
0887 break;
0888 case 0x39:
0889 return getachar() == 0x7E ? KEY_F8 : KEY_UNKNOWN;
0890 case 0x7E:
0891 if (shift && ctrl) return KEY_SHIFT_CTRL_HOME;
0892 if (shift) return KEY_SHIFT_HOME;
0893 if (ctrl) return KEY_CTRL_HOME;
0894 return KEY_HOME;
0895 default:
0896 return KEY_UNKNOWN;
0897 }
0898 }
0899
0900 switch (ch) {
0901 case 0x31:
0902 ch = getachar();
0903 if (ch != 0x7E) return KEY_UNKNOWN;
0904 if (shift && ctrl) return KEY_SHIFT_CTRL_HOME;
0905 if (shift) return KEY_SHIFT_HOME;
0906 if (ctrl) return KEY_CTRL_HOME;
0907 return KEY_HOME;
0908 case 0x32:
0909 ch = getachar();
0910 switch (ch) {
0911 case 0x30: ch = getachar(); return KEY_F9;
0912 case 0x31: ch = getachar(); return KEY_F10;
0913 case 0x7E: return KEY_INS;
0914 default: break;
0915 }
0916 return KEY_UNKNOWN;
0917 case 0x33: return getachar() == 0x7E ? KEY_DEL : KEY_UNKNOWN;
0918 case 0x34:
0919 if (getachar() != 0x7E) return KEY_UNKNOWN;
0920 if (shift && ctrl) return KEY_SHIFT_CTRL_END;
0921 if (shift) return KEY_SHIFT_END;
0922 if (ctrl) return KEY_CTRL_END;
0923 return KEY_END;
0924 case 0x35:
0925 if (getachar() != 0x7E) return KEY_UNKNOWN;
0926 if (shift) return KEY_SHIFT_PGUP;
0927 return KEY_PGUP;
0928 case 0x36:
0929 if (getachar() != 0x7E) return KEY_UNKNOWN;
0930 if (shift) return KEY_SHIFT_PGDN;
0931 return KEY_PGDN;
0932 case 0x41:
0933 if (shift && ctrl) return KEY_SHIFT_CTRL_UP;
0934 if (shift) return KEY_SHIFT_UP;
0935 if (ctrl) return KEY_CTRL_UP;
0936 return KEY_UP;
0937 case 0x42:
0938 if (shift && ctrl) return KEY_SHIFT_CTRL_DOWN;
0939 if (shift) return KEY_SHIFT_DOWN;
0940 if (ctrl) return KEY_CTRL_DOWN;
0941 return KEY_DOWN;
0942 case 0x43:
0943 if (shift && ctrl) return KEY_SHIFT_CTRL_RIGHT;
0944 if (shift) return KEY_SHIFT_RIGHT;
0945 if (ctrl) return KEY_CTRL_RIGHT;
0946 return KEY_RIGHT;
0947 case 0x44:
0948 if (shift && ctrl) return KEY_SHIFT_CTRL_LEFT;
0949 if (shift) return KEY_SHIFT_LEFT;
0950 if (ctrl) return KEY_CTRL_LEFT;
0951 return KEY_LEFT;
0952 case 0x46:
0953 if (shift && ctrl) return KEY_SHIFT_CTRL_END;
0954 if (shift) return KEY_SHIFT_END;
0955 if (ctrl) return KEY_CTRL_END;
0956 return KEY_END;
0957 case 0x48:
0958 if (shift && ctrl) return KEY_SHIFT_CTRL_HOME;
0959 if (shift) return KEY_SHIFT_HOME;
0960 if (ctrl) return KEY_CTRL_HOME;
0961 return KEY_HOME;
0962 case 0x5A:
0963 return KEY_SHIFT_TAB;
0964 case 0x5B:
0965 ch = getachar();
0966 switch (ch) {
0967 case 0x41: return KEY_F1;
0968 case 0x43: return KEY_F3;
0969 case 0x45: return KEY_F5;
0970 }
0971 return KEY_UNKNOWN;
0972
0973 default: return KEY_UNKNOWN;
0974 }
0975 break;
0976
0977 default: return KEY_UNKNOWN;
0978 }
0979 break;
0980
0981 case 0x00:
0982 case 0xE0:
0983 ch = getachar();
0984 switch (ch) {
0985 case 0x0F: return KEY_SHIFT_TAB;
0986 case 0x3B: return KEY_F1;
0987 case 0x3D: return KEY_F3;
0988 case 0x3F: return KEY_F5;
0989 case 0x47: return KEY_HOME;
0990 case 0x48: return KEY_UP;
0991 case 0x49: return KEY_PGUP;
0992 case 0x4B: return KEY_LEFT;
0993 case 0x4D: return KEY_RIGHT;
0994 case 0x4F: return KEY_END;
0995 case 0x50: return KEY_DOWN;
0996 case 0x51: return KEY_PGDN;
0997 case 0x52: return KEY_INS;
0998 case 0x53: return KEY_DEL;
0999 case 0x73: return KEY_CTRL_LEFT;
1000 case 0x74: return KEY_CTRL_RIGHT;
1001 case 0x75: return KEY_CTRL_END;
1002 case 0x77: return KEY_CTRL_HOME;
1003 case 0x8D: return KEY_CTRL_UP;
1004 case 0x91: return KEY_CTRL_DOWN;
1005 case 0x94: return KEY_CTRL_TAB;
1006 case 0xB8: return KEY_SHIFT_UP;
1007 case 0xB7: return KEY_SHIFT_HOME;
1008 case 0xBF: return KEY_SHIFT_END;
1009 case 0xB9: return KEY_SHIFT_PGUP;
1010 case 0xBB: return KEY_SHIFT_LEFT;
1011 case 0xBD: return KEY_SHIFT_RIGHT;
1012 case 0xC0: return KEY_SHIFT_DOWN;
1013 case 0xC1: return KEY_SHIFT_PGDN;
1014 case 0xDB: return KEY_SHIFT_CTRL_LEFT;
1015 case 0xDD: return KEY_SHIFT_CTRL_RIGHT;
1016 case 0xD8: return KEY_SHIFT_CTRL_UP;
1017 case 0xE0: return KEY_SHIFT_CTRL_DOWN;
1018 case 0xD7: return KEY_SHIFT_CTRL_HOME;
1019 case 0xDF: return KEY_SHIFT_CTRL_END;
1020
1021 default: return KEY_UNKNOWN;
1022 }
1023 break;
1024
1025 case 0x7F: return KEY_BACKSPACE;
1026
1027 default: return ch;
1028 }
1029 }
1030
1031 static int prompt(struct editor *ed, char *msg, int selection) {
1032 int maxlen, len, ch;
1033 char *buf = (char*) ed->env->linebuf;
1034
1035 gotoxy(0, ed->env->lines);
1036 outstr(STATUS_COLOR);
1037 outstr(msg);
1038 outstr(CLREOL);
1039
1040 len = 0;
1041 maxlen = ed->env->cols - strlen(msg) - 1;
1042 if (selection) {
1043 len = get_selected_text(ed, buf, maxlen);
1044 outbuf((unsigned char*) buf, len);
1045 }
1046
1047 for (;;) {
1048 fflush(stdout);
1049 ch = getkey();
1050 if (ch == KEY_ESC) {
1051 return 0;
1052 } else if (ch == KEY_ENTER) {
1053 buf[len] = 0;
1054 return len > 0;
1055 } else if (ch == KEY_BACKSPACE) {
1056 if (len > 0) {
1057 outstr("\b \b");
1058 len--;
1059 }
1060 } else if (ch >= ' ' && ch < 0x100 && len < maxlen) {
1061 outch(ch);
1062 buf[len++] = ch;
1063 }
1064 }
1065 }
1066
1067 static int ask(void) {
1068 int ch = getachar();
1069 return ch == 'y' || ch == 'Y';
1070 }
1071
1072
1073
1074
1075
1076 static void display_message(struct editor *ed, char *fmt, ...) {
1077 va_list args;
1078
1079 va_start(args, fmt);
1080 gotoxy(0, ed->env->lines);
1081 outstr(STATUS_COLOR);
1082 vprintf(fmt, args);
1083 outstr(CLREOL TEXT_COLOR);
1084 fflush(stdout);
1085 va_end(args);
1086 }
1087
1088 static void draw_full_statusline(struct editor *ed) {
1089 struct env *env = ed->env;
1090 int namewidth = env->cols - 29;
1091 gotoxy(0, env->lines);
1092 sprintf((char*) env->linebuf, STATUS_COLOR "%*.*sF1=Help %c%c Ln %-6dCol %-4d" CLREOL TEXT_COLOR, -namewidth, namewidth, ed->filename, ed->selecting ? '+' : ' ', ed->dirty ? '*' : ' ', ed->line + 1, column(ed, ed->linepos, ed->col) + 1);
1093 outstr((char*) env->linebuf);
1094 }
1095
1096 static void draw_statusline(struct editor *ed) {
1097 gotoxy(ed->env->cols - 20, ed->env->lines);
1098 sprintf((char*) ed->env->linebuf, STATUS_COLOR "%c Ln %-6dCol %-4d" CLREOL TEXT_COLOR, ed->dirty ? '*' : ' ', ed->line + 1, column(ed, ed->linepos, ed->col) + 1);
1099 outstr((char*) ed->env->linebuf);
1100 }
1101
1102 static void display_line(struct editor *ed, int pos, int fullline) {
1103 int hilite = 0;
1104 int col = 0;
1105 int margin = ed->margin;
1106 int maxcol = ed->env->cols + margin;
1107 unsigned char *bufptr = ed->env->linebuf;
1108 unsigned char *p = text_ptr(ed, pos);
1109 size_t selstart, selend, ch;
1110 char *s;
1111
1112 (void) get_selection(ed, &selstart, &selend);
1113 while (col < maxcol) {
1114 if (margin == 0) {
1115 if (!hilite && pos >= selstart && pos < selend) {
1116 for (s = SELECT_COLOR; *s; s++) *bufptr++ = *s;
1117 hilite = 1;
1118 } else if (hilite && pos >= selend) {
1119 for (s = TEXT_COLOR; *s; s++) *bufptr++ = *s;
1120 hilite = 0;
1121 }
1122 }
1123
1124 if (p == ed->end) break;
1125 ch = *p;
1126 if (ch == '\r' || ch == '\n') break;
1127
1128 if (ch == '\t') {
1129 int spaces = TABSIZE - col % TABSIZE;
1130 while (spaces > 0 && col < maxcol) {
1131 if (margin > 0) {
1132 margin--;
1133 } else {
1134 *bufptr++ = ' ';
1135 }
1136 col++;
1137 spaces--;
1138 }
1139 } else {
1140 if (margin > 0) {
1141 margin--;
1142 } else {
1143 *bufptr++ = ch;
1144 }
1145 col++;
1146 }
1147
1148 if (++p == ed->gap) p = ed->rest;
1149 pos++;
1150 }
1151
1152 #if defined(__linux__)
1153 if (hilite) {
1154 while (col < maxcol) {
1155 *bufptr++ = ' ';
1156 col++;
1157 }
1158 } else {
1159 if (col == margin) *bufptr++ = ' ';
1160 }
1161 #endif
1162
1163 if (col < maxcol) {
1164 for (s = CLREOL; *s; s++) *bufptr++ = *s;
1165 if (fullline) {
1166 memcpy(bufptr, "\r\n", 2);
1167 bufptr += 2;
1168 }
1169 }
1170
1171 if (hilite) {
1172 for (s = TEXT_COLOR; *s; s++) *bufptr++ = *s;
1173 }
1174
1175 outbuf(ed->env->linebuf, bufptr - ed->env->linebuf);
1176 }
1177
1178 static void update_line(struct editor *ed) {
1179 gotoxy(0, ed->line - ed->topline);
1180 display_line(ed, ed->linepos, 0);
1181 }
1182
1183 static void draw_screen(struct editor *ed) {
1184 int pos;
1185 int i;
1186
1187 gotoxy(0, 0);
1188 outstr(TEXT_COLOR);
1189 pos = ed->toppos;
1190 for (i = 0; i < ed->env->lines; i++) {
1191 if (pos < 0) {
1192 outstr(CLREOL "\r\n");
1193 } else {
1194 display_line(ed, pos, 1);
1195 pos = next_line(ed, pos);
1196 }
1197 }
1198 }
1199
1200 static void position_cursor(struct editor *ed) {
1201 int col = column(ed, ed->linepos, ed->col);
1202 gotoxy(col - ed->margin, ed->line - ed->topline);
1203 }
1204
1205
1206
1207
1208
1209 static void adjust(struct editor *ed) {
1210 int col;
1211 int ll = line_length(ed, ed->linepos);
1212 ed->col = ed->lastcol;
1213 if (ed->col > ll) ed->col = ll;
1214
1215 col = column(ed, ed->linepos, ed->col);
1216 while (col < ed->margin) {
1217 ed->margin -= 4;
1218 if (ed->margin < 0) ed->margin = 0;
1219 ed->refresh = 1;
1220 }
1221
1222 while (col - ed->margin >= ed->env->cols) {
1223 ed->margin += 4;
1224 ed->refresh = 1;
1225 }
1226 }
1227
1228 static void select_toggle(struct editor *ed) {
1229 ed->selecting = ed->selecting ? 0 : 1;
1230 update_selection(ed, ed->selecting);
1231 adjust(ed);
1232 }
1233
1234 static void up(struct editor *ed, int select) {
1235 int newpos;
1236
1237 update_selection(ed, select);
1238
1239 newpos = prev_line(ed, ed->linepos);
1240 if (newpos < 0) return;
1241
1242 ed->linepos = newpos;
1243 ed->line--;
1244 if (ed->line < ed->topline) {
1245 ed->toppos = ed->linepos;
1246 ed->topline = ed->line;
1247 ed->refresh = 1;
1248 }
1249
1250 adjust(ed);
1251 }
1252
1253 static void down(struct editor *ed, int select) {
1254 int newpos;
1255
1256 update_selection(ed, select);
1257
1258 newpos = next_line(ed, ed->linepos);
1259 if (newpos < 0) return;
1260
1261 ed->linepos = newpos;
1262 ed->line++;
1263
1264 if (ed->line >= ed->topline + ed->env->lines) {
1265 ed->toppos = next_line(ed, ed->toppos);
1266 ed->topline++;
1267 ed->refresh = 1;
1268 }
1269
1270 adjust(ed);
1271 }
1272
1273 static void left(struct editor *ed, int select) {
1274 update_selection(ed, select);
1275 if (ed->col > 0) {
1276 ed->col--;
1277 } else {
1278 int newpos = prev_line(ed, ed->linepos);
1279 if (newpos < 0) return;
1280
1281 ed->col = line_length(ed, newpos);
1282 ed->linepos = newpos;
1283 ed->line--;
1284 if (ed->line < ed->topline) {
1285 ed->toppos = ed->linepos;
1286 ed->topline = ed->line;
1287 ed->refresh = 1;
1288 }
1289 }
1290
1291 ed->lastcol = ed->col;
1292 adjust(ed);
1293 }
1294
1295 static void right(struct editor *ed, int select) {
1296 update_selection(ed, select);
1297 if (ed->col < line_length(ed, ed->linepos)) {
1298 ed->col++;
1299 } else {
1300 int newpos = next_line(ed, ed->linepos);
1301 if (newpos < 0) return;
1302
1303 ed->col = 0;
1304 ed->linepos = newpos;
1305 ed->line++;
1306
1307 if (ed->line >= ed->topline + ed->env->lines) {
1308 ed->toppos = next_line(ed, ed->toppos);
1309 ed->topline++;
1310 ed->refresh = 1;
1311 }
1312 }
1313
1314 ed->lastcol = ed->col;
1315 adjust(ed);
1316 }
1317
1318 static int wordchar(int ch) {
1319 return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9');
1320 }
1321
1322 static void wordleft(struct editor *ed, int select) {
1323 int pos, phase;
1324
1325 update_selection(ed, select);
1326 pos = ed->linepos + ed->col;
1327 phase = 0;
1328 while (pos > 0) {
1329 int ch = get(ed, pos - 1);
1330 if (phase == 0) {
1331 if (wordchar(ch)) phase = 1;
1332 } else {
1333 if (!wordchar(ch)) break;
1334 }
1335
1336 pos--;
1337 if (pos < ed->linepos) {
1338 ed->linepos = prev_line(ed, ed->linepos);
1339 ed->line--;
1340 ed->refresh = 1;
1341 }
1342 }
1343 ed->col = pos - ed->linepos;
1344 if (ed->line < ed->topline) {
1345 ed->toppos = ed->linepos;
1346 ed->topline = ed->line;
1347 }
1348
1349 ed->lastcol = ed->col;
1350 adjust(ed);
1351 }
1352
1353 static void wordright(struct editor *ed, int select) {
1354 int pos, end, phase, next;
1355
1356 update_selection(ed, select);
1357 pos = ed->linepos + ed->col;
1358 end = text_length(ed);
1359 next = next_line(ed, ed->linepos);
1360 phase = 0;
1361 while (pos < end) {
1362 int ch = get(ed, pos);
1363 if (phase == 0) {
1364 if (wordchar(ch)) phase = 1;
1365 } else {
1366 if (!wordchar(ch)) break;
1367 }
1368
1369 pos++;
1370 if (pos == next) {
1371 ed->linepos = next;
1372 next = next_line(ed, ed->linepos);
1373 ed->line++;
1374 ed->refresh = 1;
1375 }
1376 }
1377 ed->col = pos - ed->linepos;
1378 if (ed->line >= ed->topline + ed->env->lines) {
1379 ed->toppos = next_line(ed, ed->toppos);
1380 ed->topline++;
1381 }
1382
1383 ed->lastcol = ed->col;
1384 adjust(ed);
1385 }
1386
1387 static void home(struct editor *ed, int select) {
1388 update_selection(ed, select);
1389 ed->col = ed->lastcol = 0;
1390 adjust(ed);
1391 }
1392
1393 static void end(struct editor *ed, int select) {
1394 update_selection(ed, select);
1395 ed->col = ed->lastcol = line_length(ed, ed->linepos);
1396 adjust(ed);
1397 }
1398
1399 static void top(struct editor *ed, int select) {
1400 update_selection(ed, select);
1401 ed->toppos = ed->topline = ed->margin = 0;
1402 ed->linepos = ed->line = ed->col = ed->lastcol = 0;
1403 ed->refresh = 1;
1404 }
1405
1406 static void bottom(struct editor *ed, int select) {
1407 update_selection(ed, select);
1408 for (;;) {
1409 int newpos = next_line(ed, ed->linepos);
1410 if (newpos < 0) break;
1411
1412 ed->linepos = newpos;
1413 ed->line++;
1414
1415 if (ed->line >= ed->topline + ed->env->lines) {
1416 ed->toppos = next_line(ed, ed->toppos);
1417 ed->topline++;
1418 ed->refresh = 1;
1419 }
1420 }
1421 ed->col = ed->lastcol = line_length(ed, ed->linepos);
1422 adjust(ed);
1423 }
1424
1425 static void pageup(struct editor *ed, int select) {
1426 int i;
1427
1428 update_selection(ed, select);
1429 if (ed->line < ed->env->lines) {
1430 ed->linepos = ed->toppos = 0;
1431 ed->line = ed->topline = 0;
1432 } else {
1433 for (i = 0; i < ed->env->lines; i++) {
1434 int newpos = prev_line(ed, ed->linepos);
1435 if (newpos < 0) return;
1436
1437 ed->linepos = newpos;
1438 ed->line--;
1439
1440 if (ed->topline > 0) {
1441 ed->toppos = prev_line(ed, ed->toppos);
1442 ed->topline--;
1443 }
1444 }
1445 }
1446
1447 ed->refresh = 1;
1448 adjust(ed);
1449 }
1450
1451 static void pagedown(struct editor *ed, int select) {
1452 int i;
1453
1454 update_selection(ed, select);
1455 for (i = 0; i < ed->env->lines; i++) {
1456 int newpos = next_line(ed, ed->linepos);
1457 if (newpos < 0) break;
1458
1459 ed->linepos = newpos;
1460 ed->line++;
1461
1462 ed->toppos = next_line(ed, ed->toppos);
1463 ed->topline++;
1464 }
1465
1466 ed->refresh = 1;
1467 adjust(ed);
1468 }
1469
1470
1471
1472
1473
1474 static void insert_char(struct editor *ed, unsigned char ch) {
1475 erase_selection(ed);
1476 insert(ed, ed->linepos + ed->col, &ch, 1);
1477 ed->col++;
1478 ed->lastcol = ed->col;
1479 adjust(ed);
1480 if (!ed->refresh) ed->lineupdate = 1;
1481 }
1482
1483 static void newline(struct editor *ed) {
1484 int p;
1485 unsigned char ch;
1486
1487 erase_selection(ed);
1488 #if defined(__linux__) || defined(__rtems__)
1489 insert(ed, ed->linepos + ed->col, (unsigned char*) "\n", 1);
1490 #else
1491 insert(ed, ed->linepos + ed->col, "\r\n", 2);
1492 #endif
1493 ed->col = ed->lastcol = 0;
1494 ed->line++;
1495 p = ed->linepos;
1496 ed->linepos = next_line(ed, ed->linepos);
1497 for (;;) {
1498 ch = get(ed, p++);
1499 if (ch == ' ' || ch == '\t') {
1500 insert(ed, ed->linepos + ed->col, &ch, 1);
1501 ed->col++;
1502 } else {
1503 break;
1504 }
1505 }
1506 ed->lastcol = ed->col;
1507
1508 ed->refresh = 1;
1509
1510 if (ed->line >= ed->topline + ed->env->lines) {
1511 ed->toppos = next_line(ed, ed->toppos);
1512 ed->topline++;
1513 ed->refresh = 1;
1514 }
1515
1516 adjust(ed);
1517 }
1518
1519 static void backspace(struct editor *ed) {
1520 if (erase_selection(ed)) return;
1521 if (ed->linepos + ed->col == 0) return;
1522 if (ed->col == 0) {
1523 int pos = ed->linepos;
1524 erase(ed, --pos, 1);
1525 if (get(ed, pos - 1) == '\r') erase(ed, --pos, 1);
1526
1527 ed->line--;
1528 ed->linepos = line_start(ed, pos);
1529 ed->col = pos - ed->linepos;
1530 ed->refresh = 1;
1531
1532 if (ed->line < ed->topline) {
1533 ed->toppos = ed->linepos;
1534 ed->topline = ed->line;
1535 }
1536 } else {
1537 ed->col--;
1538 erase(ed, ed->linepos + ed->col, 1);
1539 ed->lineupdate = 1;
1540 }
1541
1542 ed->lastcol = ed->col;
1543 adjust(ed);
1544 }
1545
1546 static void del(struct editor *ed) {
1547 int pos, ch;
1548
1549 if (erase_selection(ed)) return;
1550 pos = ed->linepos + ed->col;
1551 ch = get(ed, pos);
1552 if (ch < 0) return;
1553
1554 erase(ed, pos, 1);
1555 if (ch == '\r') {
1556 ch = get(ed, pos);
1557 if (ch == '\n') erase(ed, pos, 1);
1558 }
1559
1560 if (ch == '\n') {
1561 ed->refresh = 1;
1562 } else {
1563 ed->lineupdate = 1;
1564 }
1565 }
1566
1567 static void indent(struct editor *ed, unsigned char *indentation) {
1568 size_t start, end, i, lines, toplines, newline, ch;
1569 unsigned char *buffer, *p;
1570 size_t buflen;
1571 int width = strlen((const char*) indentation);
1572 int pos = ed->linepos + ed->col;
1573
1574 if (!get_selection(ed, &start, &end)) {
1575 insert_char(ed, '\t');
1576 return;
1577 }
1578
1579 lines = 0;
1580 toplines = 0;
1581 newline = 1;
1582 for (i = start; i < end; i++) {
1583 if (i == ed->toppos) toplines = lines;
1584 if (newline) {
1585 lines++;
1586 newline = 0;
1587 }
1588 if (get(ed, i) == '\n') newline = 1;
1589 }
1590 buflen = end - start + lines * width;
1591 buffer = malloc(buflen);
1592 if (!buffer) return;
1593
1594 newline = 1;
1595 p = buffer;
1596 for (i = start; i < end; i++) {
1597 if (newline) {
1598 memcpy(p, indentation, width);
1599 p += width;
1600 newline = 0;
1601 }
1602 ch = get(ed, i);
1603 *p++ = ch;
1604 if (ch == '\n') newline = 1;
1605 }
1606
1607 replace(ed, start, end - start, buffer, buflen, 1);
1608 free(buffer);
1609
1610 if (ed->anchor < pos) {
1611 pos += width * lines;
1612 } else {
1613 ed->anchor += width * lines;
1614 }
1615
1616 ed->toppos += width * toplines;
1617 ed->linepos = line_start(ed, pos);
1618 ed->col = ed->lastcol = pos - ed->linepos;
1619
1620 adjust(ed);
1621 ed->refresh = 1;
1622 }
1623
1624 static void unindent(struct editor *ed, unsigned char *indentation) {
1625 size_t start, end, i, newline, ch, shrinkage, topofs;
1626 unsigned char *buffer, *p;
1627 int width = strlen((const char*) indentation);
1628 int pos = ed->linepos + ed->col;
1629
1630 if (!get_selection(ed, &start, &end)) return;
1631
1632 buffer = malloc(end - start);
1633 if (!buffer) return;
1634
1635 newline = 1;
1636 p = buffer;
1637 i = start;
1638 shrinkage = 0;
1639 topofs = 0;
1640 while (i < end) {
1641 if (newline) {
1642 newline = 0;
1643 if (compare(ed, indentation, i, width)) {
1644 i += width;
1645 shrinkage += width;
1646 if (i < ed->toppos) topofs -= width;
1647 continue;
1648 }
1649 }
1650 ch = get(ed, i++);
1651 *p++ = ch;
1652 if (ch == '\n') newline = 1;
1653 }
1654
1655 if (!shrinkage) {
1656 free(buffer);
1657 return;
1658 }
1659
1660 replace(ed, start, end - start, buffer, p - buffer, 1);
1661 free(buffer);
1662
1663 if (ed->anchor < pos) {
1664 pos -= shrinkage;
1665 } else {
1666 ed->anchor -= shrinkage;
1667 }
1668
1669 ed->toppos += topofs;
1670 ed->linepos = line_start(ed, pos);
1671 ed->col = ed->lastcol = pos - ed->linepos;
1672
1673 ed->refresh = 1;
1674 adjust(ed);
1675 }
1676
1677 static void undo(struct editor *ed) {
1678 if (!ed->undo) return;
1679 moveto(ed, ed->undo->pos, 0);
1680 replace(ed, ed->undo->pos, ed->undo->inserted, ed->undo->undobuf, ed->undo->erased, 0);
1681 ed->undo = ed->undo->prev;
1682 if (!ed->undo) ed->dirty = 0;
1683 ed->anchor = -1;
1684 ed->lastcol = ed->col;
1685 ed->refresh = 1;
1686 }
1687
1688 static void redo(struct editor *ed) {
1689 if (ed->undo) {
1690 if (!ed->undo->next) return;
1691 ed->undo = ed->undo->next;
1692 } else {
1693 if (!ed->undohead) return;
1694 ed->undo = ed->undohead;
1695 }
1696 replace(ed, ed->undo->pos, ed->undo->erased, ed->undo->redobuf, ed->undo->inserted, 0);
1697 moveto(ed, ed->undo->pos, 0);
1698 ed->dirty = 1;
1699 ed->anchor = -1;
1700 ed->lastcol = ed->col;
1701 ed->refresh = 1;
1702 }
1703
1704
1705
1706
1707
1708 static void copy_selection(struct editor *ed) {
1709 size_t selstart, selend;
1710
1711 if (!get_selection(ed, &selstart, &selend)) return;
1712 ed->env->clipsize = selend - selstart;
1713 ed->env->clipboard = (unsigned char *) realloc(ed->env->clipboard, ed->env->clipsize);
1714 if (!ed->env->clipboard) return;
1715 copy(ed, ed->env->clipboard, selstart, ed->env->clipsize);
1716 }
1717
1718 static void cut_selection(struct editor *ed) {
1719 copy_selection(ed);
1720 erase_selection(ed);
1721 select_toggle(ed);
1722 }
1723
1724 static void paste_selection(struct editor *ed) {
1725 erase_selection(ed);
1726 insert(ed, ed->linepos + ed->col, ed->env->clipboard, ed->env->clipsize);
1727 moveto(ed, ed->linepos + ed->col + ed->env->clipsize, 0);
1728 ed->refresh = 1;
1729 }
1730
1731
1732
1733
1734
1735 static void open_editor(struct editor *ed) {
1736 int rc;
1737 char *filename;
1738 struct env *env = ed->env;
1739
1740 if (!prompt(ed, "Open file: ", 1)) {
1741 ed->refresh = 1;
1742 return;
1743 }
1744 filename = (char*) ed->env->linebuf;
1745
1746 ed = find_editor(ed->env, filename);
1747 if (ed) {
1748 env->current = ed;
1749 } else {
1750 ed = create_editor(env);
1751 rc = load_file(ed, filename);
1752 if (rc < 0) {
1753 display_message(ed, "Error %d opening %s (%s)", errno, filename, strerror(errno));
1754 sleep(5);
1755 delete_editor(ed);
1756 ed = env->current;
1757 }
1758 }
1759 ed->refresh = 1;
1760 }
1761
1762 static void new_editor(struct editor *ed) {
1763 ed = create_editor(ed->env);
1764 new_file(ed, "");
1765 ed->refresh = 1;
1766 }
1767
1768 static void read_from_stdin(struct editor *ed) {
1769 char buffer[512];
1770 int n, pos;
1771
1772 pos = 0;
1773 while ((n = fread(buffer, 1, sizeof(buffer), stdin)) > 0) {
1774 insert(ed, pos, (unsigned char*) buffer, n);
1775 pos += n;
1776 }
1777 strncpy(ed->filename, "<stdin>", FILENAME_MAX);
1778 ed->newfile = 1;
1779 ed->dirty = 0;
1780 }
1781
1782 static void save_editor(struct editor *ed) {
1783 int rc;
1784
1785 if (!ed->dirty && !ed->newfile) return;
1786
1787 if (ed->newfile) {
1788 if (!prompt(ed, "Save as: ", 1)) {
1789 ed->refresh = 1;
1790 return;
1791 }
1792
1793 if (access((const char*) ed->env->linebuf, F_OK) == 0) {
1794 display_message(ed, "Overwrite %s (y/n)? ", ed->env->linebuf);
1795 if (!ask()) {
1796 ed->refresh = 1;
1797 return;
1798 }
1799 }
1800 strlcpy(
1801 ed->filename, (const char*) ed->env->linebuf, sizeof(ed->filename));
1802 ed->newfile = 0;
1803 }
1804
1805 rc = save_file(ed);
1806 if (rc < 0) {
1807 display_message(ed, "Error %d saving document (%s)", errno, strerror(errno));
1808 sleep(5);
1809 }
1810
1811 ed->refresh = 1;
1812 }
1813
1814 static struct editor* close_editor(struct editor *ed) {
1815 struct env *env = ed->env;
1816
1817 if (ed->dirty) {
1818 display_message(ed, "Close %s without saving changes (y/n)? ", ed->filename);
1819 if (!ask()) {
1820 ed->refresh = 1;
1821 return ed;
1822 }
1823 }
1824
1825 delete_editor(ed);
1826
1827 ed = env->current;
1828 if (!ed) {
1829 ed = create_editor(env);
1830 new_file(ed, "");
1831 }
1832 ed->refresh = 1;
1833 return ed;
1834 }
1835
1836 static void pipe_command(struct editor *ed) {
1837 #ifdef __rtems__
1838 display_message(ed, "Not supported");
1839 sleep(3);
1840 #else
1841 FILE *f;
1842 char buffer[512];
1843 int n;
1844 int pos;
1845
1846 if (!prompt(ed, "Command: ", 1)) {
1847 ed->refresh = 1;
1848 return;
1849 }
1850
1851 #ifdef SANOS
1852 f = popen(ed->env->linebuf, "r2");
1853 #else
1854 f = popen(ed->env->linebuf, "r");
1855 #endif
1856 if (!f) {
1857 display_message(ed, "Error %d running command (%s)", errno, strerror(errno));
1858 sleep(5);
1859 } else {
1860 erase_selection(ed);
1861 pos = ed->linepos + ed->col;
1862 while ((n = fread(buffer, 1, sizeof(buffer), f)) > 0) {
1863 insert(ed, pos, buffer, n);
1864 pos += n;
1865 }
1866 moveto(ed, pos, 0);
1867 pclose(f);
1868 }
1869 ed->refresh = 1;
1870 #endif
1871 }
1872
1873 static void find_text(struct editor *ed, int next) {
1874 int slen;
1875
1876 if (!next) {
1877 if (!prompt(ed, "Find: ", 1)) {
1878 ed->refresh = 1;
1879 return;
1880 }
1881 if (ed->env->search) free(ed->env->search);
1882 ed->env->search = (unsigned char*) strdup((const char*) ed->env->linebuf);
1883 }
1884
1885 if (!ed->env->search) return;
1886 slen = strlen((const char*) ed->env->search);
1887 if (slen > 0) {
1888 unsigned char *match;
1889
1890 close_gap(ed);
1891 match = (unsigned char*) strstr((char*) ed->start + ed->linepos + ed->col, (char*) ed->env->search);
1892 if (match != NULL) {
1893 int pos = match - ed->start;
1894 ed->anchor = pos;
1895 moveto(ed, pos + slen, 1);
1896 } else {
1897 outch('\007');
1898 }
1899 }
1900 ed->refresh = 1;
1901 }
1902
1903 static void goto_line(struct editor *ed) {
1904 int lineno, l, pos;
1905
1906 ed->anchor = -1;
1907 if (prompt(ed, "Goto line: ", 1)) {
1908 lineno = atoi((char*) ed->env->linebuf);
1909 if (lineno > 0) {
1910 pos = 0;
1911 for (l = 0; l < lineno - 1; l++) {
1912 pos = next_line(ed, pos);
1913 if (pos < 0) break;
1914 }
1915 } else {
1916 pos = -1;
1917 }
1918
1919 if (pos >= 0) {
1920 moveto(ed, pos, 1);
1921 } else {
1922 outch('\007');
1923 }
1924 }
1925 ed->refresh = 1;
1926 }
1927
1928 static struct editor *next_file(struct editor *ed) {
1929 ed = ed->env->current = ed->next;
1930 ed->refresh = 1;
1931 return ed;
1932 }
1933
1934 static void jump_to_editor(struct editor *ed) {
1935 struct env *env = ed->env;
1936 char filename[FILENAME_MAX];
1937 int lineno = 0;
1938
1939 if (!get_selected_text(ed, filename, FILENAME_MAX)) {
1940 int pos = ed->linepos + ed->col;
1941 char *p = filename;
1942 int left = FILENAME_MAX - 1;
1943 while (left > 0) {
1944 int ch = get(ed, pos);
1945 if (ch < 0) break;
1946 if (strchr("!@\"'#%&()[]{}*?+:;\r\n\t ", ch)) break;
1947 *p++ = ch;
1948 left--;
1949 pos++;
1950 }
1951 *p = 0;
1952
1953 if (get(ed, pos) == ':') {
1954 pos++;
1955 for (;;) {
1956 int ch = get(ed, pos);
1957 if (ch < 0) break;
1958 if (ch >= '0' && ch <= '9') {
1959 lineno = lineno * 10 + (ch - '0');
1960 } else {
1961 break;
1962 }
1963 pos++;
1964 }
1965 }
1966 }
1967 if (!*filename) return;
1968
1969 ed = find_editor(env, filename);
1970 if (ed) {
1971 env->current = ed;
1972 } else {
1973 ed = create_editor(env);
1974 if (load_file(ed, filename) < 0) {
1975 outch('\007');
1976 delete_editor(ed);
1977 ed = env->current;
1978 }
1979 }
1980
1981 if (lineno > 0) {
1982 int pos = 0;
1983 while (--lineno > 0) {
1984 pos = next_line(ed, pos);
1985 if (pos < 0) break;
1986 }
1987 if (pos >= 0) moveto(ed, pos, 1);
1988 }
1989
1990 ed->refresh = 1;
1991 }
1992
1993 static void redraw_screen(struct editor *ed) {
1994 get_console_size(ed->env);
1995 draw_screen(ed);
1996 }
1997
1998 static int quit(struct env *env) {
1999 struct editor *ed = env->current;
2000 struct editor *start = ed;
2001
2002 do {
2003 if (ed->dirty) {
2004 display_message(ed, "Close %s without saving changes (y/n)? ", ed->filename);
2005 if (!ask()) return 0;
2006 }
2007 ed = ed->next;
2008 } while (ed != start);
2009
2010 return 1;
2011 }
2012
2013 static void help(struct editor *ed) {
2014 gotoxy(0, 0);
2015 clear_screen();
2016 outstr("Editor Command Summary\r\n");
2017 outstr("======================\r\n\r\n");
2018 outstr("<up> Move one line up (*) Ctrl+N New editor\r\n");
2019 outstr("<down> Move one line down (*) Ctrl+O Open file\r\n");
2020 outstr("<left> Move one character left (*) Ctrl+S Save file\r\n");
2021 outstr("<right> Move one character right (*) Ctrl+W Close file\r\n");
2022 outstr("<pgup> Move one page up (*) Ctrl+Q Quit\r\n");
2023 outstr("<pgdn> Move one page down (*) Ctrl+P Pipe command\r\n");
2024 outstr("Ctrl+<left> Move to previous word (*) Ctrl+A Select all\r\n");
2025 outstr("Ctrl+<right> Move to next word (*) Ctrl+C Copy selection to clipboard\r\n");
2026 outstr("<home> Move to start of line (*) Ctrl+X Cut selection to clipboard\r\n");
2027 outstr("<end> Move to end of line (*) Ctrl+V Paste from clipboard\r\n");
2028 outstr("Ctrl+<home> Move to start of file (*) Ctrl+Z Undo\r\n");
2029 outstr("Ctrl+<end> Move to end of file (*) Ctrl+R Redo\r\n");
2030 outstr("<backspace> Delete previous character Ctrl+F Find text\r\n");
2031 outstr("<delete> Delete current character Ctrl+G Find next\r\n");
2032 outstr("Ctrl+<tab> Next editor Ctrl+L Goto line\r\n");
2033 outstr("<tab> Indent selection F1 Help\r\n");
2034 outstr("Shift+<tab> Unindent selection F2 Select toggle\r\n");
2035 outstr(" (*) Extends selection, F2 toggles. F3 Navigate to file\r\n");
2036 outstr(" F4 Copy selection to clipboard\r\n");
2037 outstr(" Ctrl-Q/S may not work over F5 Redraw screen\r\n");
2038 outstr(" serial links, use funcions keys F9 Save file\r\n");
2039 outstr(" F10 Quit\r\n");
2040 outstr("Press any key to continue...");
2041 fflush(stdout);
2042
2043 getkey();
2044 draw_screen(ed);
2045 draw_full_statusline(ed);
2046 }
2047
2048
2049
2050
2051
2052 static void edit(struct editor *ed) {
2053 int done = 0;
2054 int key;
2055
2056 ed->refresh = 1;
2057 while (!done) {
2058 if (ed->refresh) {
2059 draw_screen(ed);
2060 draw_full_statusline(ed);
2061 ed->refresh = 0;
2062 ed->lineupdate = 0;
2063 } else if (ed->lineupdate) {
2064 update_line(ed);
2065 ed->lineupdate = 0;
2066 draw_statusline(ed);
2067 } else {
2068 draw_statusline(ed);
2069 }
2070
2071 position_cursor(ed);
2072 fflush(stdout);
2073 key = getkey();
2074
2075 if (key >= ' ' && key <= 0x7F) {
2076 #ifdef LESS
2077 switch (key) {
2078 case 'q': done = 1; break;
2079 case '/': find_text(ed, 0); break;
2080 }
2081 #else
2082 insert_char(ed, (unsigned char) key);
2083 #endif
2084 } else {
2085 switch (key) {
2086 case KEY_F1: help(ed); break;
2087 case KEY_F2: select_toggle(ed); break;
2088 case KEY_F3: jump_to_editor(ed); ed = ed->env->current; break;
2089 case KEY_F4: copy_selection(ed); break;
2090 case KEY_F5: redraw_screen(ed); break;
2091 case KEY_F9: save_editor(ed); break;
2092 case KEY_F10: done = 1; break;
2093
2094 #if defined(__linux__) || defined(__rtems__)
2095 case ctrl('y'): help(ed); break;
2096 case ctrl('t'): top(ed, 0); break;
2097 case ctrl('b'): bottom(ed, 0); break;
2098 #endif
2099
2100 case KEY_UP: up(ed, ed->selecting); break;
2101 case KEY_DOWN: down(ed, ed->selecting); break;
2102 case KEY_LEFT: left(ed, ed->selecting); break;
2103 case KEY_RIGHT: right(ed, ed->selecting); break;
2104 case KEY_HOME: home(ed, ed->selecting); break;
2105 case KEY_END: end(ed, ed->selecting); break;
2106 case KEY_PGUP: pageup(ed, ed->selecting); break;
2107 case KEY_PGDN: pagedown(ed, ed->selecting); break;
2108
2109 case KEY_CTRL_RIGHT: wordright(ed, ed->selecting); break;
2110 case KEY_CTRL_LEFT: wordleft(ed, ed->selecting); break;
2111 case KEY_CTRL_HOME: top(ed, ed->selecting); break;
2112 case KEY_CTRL_END: bottom(ed, ed->selecting); break;
2113
2114 #if SHIFT_SELECT
2115 case KEY_SHIFT_UP: up(ed, 1); break;
2116 case KEY_SHIFT_DOWN: down(ed, 1); break;
2117 case KEY_SHIFT_LEFT: left(ed, 1); break;
2118 case KEY_SHIFT_RIGHT: right(ed, 1); break;
2119 case KEY_SHIFT_PGUP: pageup(ed, 1); break;
2120 case KEY_SHIFT_PGDN: pagedown(ed, 1); break;
2121 case KEY_SHIFT_HOME: home(ed, 1); break;
2122 case KEY_SHIFT_END: end(ed, 1); break;
2123
2124 case KEY_SHIFT_CTRL_RIGHT: wordright(ed, 1); break;
2125 case KEY_SHIFT_CTRL_LEFT: wordleft(ed, 1); break;
2126 case KEY_SHIFT_CTRL_HOME: top(ed, 1); break;
2127 case KEY_SHIFT_CTRL_END: bottom(ed, 1); break;
2128 #endif
2129
2130 case KEY_CTRL_TAB: ed = next_file(ed); break;
2131
2132 case ctrl('e'): select_toggle(ed); break;
2133 case ctrl('a'): select_all(ed); break;
2134 case ctrl('c'): copy_selection(ed);select_toggle(ed); break;
2135 case ctrl('f'): find_text(ed, 0); break;
2136 case ctrl('l'): goto_line(ed); break;
2137 case ctrl('g'): find_text(ed, 1); break;
2138 case ctrl('q'): done = 1; break;
2139 #ifdef LESS
2140 case KEY_ESC: done = 1; break;
2141 #else
2142 case KEY_TAB: indent(ed, (unsigned char*) INDENT); break;
2143 case KEY_SHIFT_TAB: unindent(ed, (unsigned char*) INDENT); break;
2144
2145 case KEY_ENTER: newline(ed); break;
2146 case KEY_BACKSPACE: backspace(ed); break;
2147 case KEY_DEL: del(ed); break;
2148 case ctrl('x'): cut_selection(ed); break;
2149 case ctrl('z'): undo(ed); break;
2150 case ctrl('r'): redo(ed); break;
2151 case ctrl('v'): paste_selection(ed); break;
2152 case ctrl('o'): open_editor(ed); ed = ed->env->current; break;
2153 case ctrl('n'): new_editor(ed); ed = ed->env->current; break;
2154 case ctrl('s'): save_editor(ed); break;
2155 case ctrl('p'): pipe_command(ed); break;
2156 #endif
2157 case ctrl('w'): ed = close_editor(ed); break;
2158 }
2159 }
2160 }
2161 }
2162
2163
2164
2165
2166 static int rtems_shell_main_edit(int argc, char *argv[])
2167 {
2168 struct env env;
2169 int rc;
2170 int i;
2171 sigset_t blocked_sigmask, orig_sigmask;
2172 #if defined(__linux__)
2173 struct termios tio;
2174 #endif
2175 #if defined(__linux__) || defined(__rtems__)
2176 struct termios orig_tio;
2177 #endif
2178 #ifdef SANOS
2179 struct term *term;
2180 #endif
2181
2182 memset(&env, 0, sizeof(env));
2183 for (i = 1; i < argc; i++) {
2184 struct editor *ed = create_editor(&env);
2185 rc = load_file(ed, argv[i]);
2186 if (rc < 0 && errno == ENOENT) rc = new_file(ed, argv[i]);
2187 if (rc < 0) {
2188 perror(argv[i]);
2189 return 0;
2190 }
2191 }
2192 if (env.current == NULL) {
2193 struct editor *ed = create_editor(&env);
2194 if (isatty(fileno(stdin))) {
2195 new_file(ed, "");
2196 } else {
2197 read_from_stdin(ed);
2198 }
2199 }
2200 env.current = env.current->next;
2201
2202 #ifdef SANOS
2203 term = gettib()->proc->term;
2204 if (fdin != term->ttyin) dup2(term->ttyin, fdin);
2205 if (fdout != term->ttyout) dup2(term->ttyout, fdout);
2206 #elif !defined(__rtems__)
2207 if (!isatty(fileno(stdin))) {
2208 if (!freopen("/dev/tty", "r", stdin)) perror("/dev/tty");
2209 }
2210 #endif
2211
2212 setvbuf(stdout, NULL, 0, 8192);
2213
2214 #if defined(__linux__) || defined(__rtems__)
2215 (void) tcgetattr(0, &orig_tio);
2216 #if !defined(__rtems__)
2217 cfmakeraw(&tio);
2218 tcsetattr(0, TCSANOW, &tio);
2219 #endif
2220 if (getenv("TERM") && strcmp(getenv("TERM"), "linux") == 0) {
2221 linux_console = 1;
2222 } else {
2223 outstr(CLRSCR);
2224 outstr("\033[3 q");
2225 outstr("\033]50;CursorShape=2\a");
2226 }
2227 #endif
2228
2229 get_console_size(&env);
2230
2231 sigemptyset(&blocked_sigmask);
2232 sigaddset(&blocked_sigmask, SIGINT);
2233 sigaddset(&blocked_sigmask, SIGTSTP);
2234 sigaddset(&blocked_sigmask, SIGABRT);
2235 sigprocmask(SIG_BLOCK, &blocked_sigmask, &orig_sigmask);
2236
2237 for (;;) {
2238 if (!env.current) break;
2239 edit(env.current);
2240 if (quit(&env)) break;
2241 }
2242
2243 gotoxy(0, env.lines + 1);
2244 outstr(RESET_COLOR CLREOL);
2245 #if defined(__linux__) || defined(__rtems__)
2246 tcsetattr(0, TCSANOW, &orig_tio);
2247 #endif
2248
2249 while (env.current) delete_editor(env.current);
2250
2251 if (env.clipboard) free(env.clipboard);
2252 if (env.search) free(env.search);
2253 if (env.linebuf) free(env.linebuf);
2254
2255 setbuf(stdout, NULL);
2256 sigprocmask(SIG_SETMASK, &orig_sigmask, NULL);
2257
2258 return 0;
2259 }
2260
2261 rtems_shell_cmd_t rtems_shell_EDIT_Command = {
2262 "edit",
2263 "edit [file ...]",
2264 "files",
2265 rtems_shell_main_edit,
2266 NULL,
2267 NULL
2268 };