/* Edit line management file Copyright (c) Tudor Hulubei & Andrei Pitis, May 1994 This file is part of UIT (UNIX Interactive Tools) UIT 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. UIT 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 UIT; see the file COPYING. If not, write to the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA. */ #include #include #include #include "tty.h" #include "window.h" #include "edit.h" extern int LinuxConsole; extern int ColorMonitor; extern char cSection[]; extern char bwSection[]; static char etemp[256]; #define EDIT_FIELDS 3 static char EditFields[EDIT_FIELDS][40] = { "CommandLineForeground", "CommandLineBackground", "CommandLineBrightness" }; #ifdef HAVE_LINUX static int EditColors[EDIT_FIELDS] = { WHITE, BLACK, ON }; #else static int EditColors[EDIT_FIELDS] = { WHITE, BLACK, ON }; #endif #define CommandLineForeground EditColors[0] #define CommandLineBackground EditColors[1] #define CommandLineBrightness EditColors[2] edit *edit_init(int _columns, int _begin_y, configuration *config) { char *data, *section; int sectionptr, index, i; edit *this = (edit *)malloc(sizeof(edit)); this->columns = _columns; this->records = this->current_record = 0; this->buf = (char *)malloc(EDIT_BUFLEN); this->history_buf = (char *)malloc(EDIT_HISTBUFLEN); memset(this->history_buf, 0, EDIT_HISTBUFLEN); edit_reset(this); this->win = window_init(0, _begin_y, 1, _columns); if (configuration_getstatus(config) == STATUS_OK) { section = (LinuxConsole && ColorMonitor) ? cSection : bwSection; sectionptr = configuration_getsectionptr(config, section); if (sectionptr != -1) for (i = 0; i < EDIT_FIELDS; i++) { configuration_getfielddata(config, sectionptr, EditFields[i], &data, 1, DO_SEEK); if (!data || (index = tty_getcolorindex(data)) == -1) fprintf(stderr, "Invalid %s (%s).\n", EditFields[i], data); else EditColors[i] = index; } } return this; } void edit_end(edit *this) { free(this->buf); free(this->history_buf); free(this->win); } char *edit_gettext(edit *this, char *dest) { return strcpy(dest, this->buf + this->static_size); } void edit_reset(edit *this) { this->buf[this->index = this->static_size = 0] = 0; } void edit_putch(edit *this, int key) { tty_status status; if (key == KEY_BACKSPACE && this->index == this->static_size) return; if (key != KEY_BACKSPACE && this->index == EDIT_BUFLEN - 1) { tty_beep(); return; } if (key == KEY_BACKSPACE) this->index--; else { if (!is_print(key)) return; this->buf[this->index++] = key; } this->buf[this->index] = 0; if (this->index < this->columns - 1) { tty_save(&status); tty_bright(CommandLineBrightness); tty_foreground(CommandLineForeground); tty_background(CommandLineBackground); if (key == KEY_BACKSPACE) { window_cursormove(this->win, 0, this->index); window_write(" ", 1); window_cursormove(this->win, 0, this->index); } else window_write((char *)&key, 1); tty_restore(&status); } else edit_update(this); } void edit_update(edit *this) { unsigned len; tty_status status; tty_save(&status); tty_bright(CommandLineBrightness); tty_foreground(CommandLineForeground); tty_background(CommandLineBackground); memset(etemp, ' ', this->columns); len = (this->index >= this->columns) ? this->index - this->columns + 1 : 0; memcpy(etemp, this->buf + this->static_size + len, this->index - this->static_size - len); window_cursormove(this->win, 0, 0); window_write(this->buf, this->static_size); window_write(etemp, this->columns - this->static_size); tty_restore(&status); } void edit_eos(edit *this) { this->static_size = this->index; } void edit_setcursor(edit *this) { tty_bright(CommandLineBrightness); tty_foreground(CommandLineForeground); tty_background(CommandLineBackground); window_cursormove(this->win, 0, strlen(this->buf)); } void edit_del(edit *this) { this->buf[this->index = this->static_size] = 0; edit_update(this); } void edit_puts(edit *this, char *str) { strncpy(this->buf + this->index, str, EDIT_BUFLEN - this->static_size - 1); this->index = strlen(this->buf); } char *edit_gets(edit *this, char *static_text, char *dest, char *default_str) { char key; struct key_struct *ks; int oldindex = this->index, oldstatic_size = this->static_size; char oldbuf[EDIT_BUFLEN]; strcpy(oldbuf, this->buf); edit_reset(this); edit_puts(this, static_text); edit_eos(this); if (default_str) edit_puts(this, default_str); edit_update(this); edit_setcursor(this); for (;;) { ks = tty_getkey(NULL); key = ks->key_seq[0]; if (ks->aux_data == NULL && (is_print(key) || key == KEY_BACKSPACE)) edit_putch(this, key); else break; } edit_gettext(this, dest); strcpy(this->buf, oldbuf); this->index = oldindex; this->static_size = oldstatic_size; edit_update(this); edit_setcursor(this); return (key == KEY_ENTER) ? dest : NULL; } void edit_history(edit *this, int dir) { switch (dir) { case EDIT_PREVIOUS: if (this->current_record) this->current_record--; strncpy(this->buf + this->static_size, this->history_buf + this->current_record * EDIT_RECLEN, EDIT_BUFLEN - this->static_size - 1); this->index = strlen(this->buf); edit_update(this); break; case EDIT_NEXT: if (this->current_record < this->records) { strncpy(this->buf + this->static_size, this->history_buf + ++this->current_record * EDIT_RECLEN, EDIT_BUFLEN - this->static_size - 1); this->index = strlen(this->buf); edit_update(this); } else edit_del(this); break; case EDIT_RECORD: if ((this->records && strcmp(&this->history_buf[(this->records - 1) * EDIT_RECLEN], this->buf + this->static_size) == 0) || this->buf[this->static_size] == 0) { this->current_record = this->records; break; } if (this->records == EDIT_HISTRECS) { memcpy(this->history_buf, this->history_buf + EDIT_RECLEN, EDIT_HISTBUFLEN - EDIT_RECLEN); this->records--; } strcpy(this->history_buf + this->records * EDIT_RECLEN, this->buf + this->static_size); this->current_record = ++this->records; break; default: break; } }