📄 slrline.c
字号:
/* SLang_read_line interface --- uses SLang tty stuff *//* Copyright (c) 1992, 1999, 2001, 2002, 2003 John E. Davis * This file is part of the S-Lang library. * * You may distribute under the terms of either the GNU General Public * License or the Perl Artistic License. */#include "slinclud.h"#include "slang.h"#include "_slang.h"#ifdef REAL_UNIX_SYSTEMint SLang_RL_EOF_Char = 4;#elseint SLang_RL_EOF_Char = 26;#endifint SLang_Rline_Quit;static SLang_RLine_Info_Type *This_RLI;static unsigned char Char_Widths[256];static void position_cursor (int);static void rl_beep (void){ putc(7, stdout); fflush (stdout);}/* editing functions */static int rl_bol (void){ if (This_RLI->point == 0) return 0; This_RLI->point = 0; return 1;}static int rl_eol (void){ if (This_RLI->point == This_RLI->len) return 0; This_RLI->point = This_RLI->len; return 1;}static int rl_right (void){ if (This_RLI->point == This_RLI->len) return 0; This_RLI->point++; return 1;}static int rl_left (void){ if (This_RLI->point == 0) return 0; This_RLI->point--; return 1;}static int rl_self_insert (void){ unsigned char *pmin, *p; if (This_RLI->len == This_RLI->buf_len) { rl_beep (); return 0; } pmin = This_RLI->buf + This_RLI->point; p = This_RLI->buf + This_RLI->len; while (p > pmin) { *p = *(p - 1); p--; } *pmin = SLang_Last_Key_Char; This_RLI->len++; This_RLI->point++; if ((This_RLI->curs_pos + 2 >= This_RLI->edit_width) || (This_RLI->tt_insert == NULL) || (Char_Widths[SLang_Last_Key_Char] != 1)) return 1; (*This_RLI->tt_insert)((char) SLang_Last_Key_Char); /* update screen buf */ p = This_RLI->old_upd + (This_RLI->len - 1); pmin = This_RLI->old_upd + (This_RLI->point - 1); while (p > pmin) { *p = *(p - 1); p--; } *pmin = SLang_Last_Key_Char; return 0;}int SLang_rline_insert (char *s){ unsigned char *pmin, *p; int n; n = strlen (s); if (n > This_RLI->buf_len - This_RLI->len) n = This_RLI->buf_len - This_RLI->len; if (n == 0) return 0; pmin = This_RLI->buf + This_RLI->point; p = This_RLI->buf + (This_RLI->len - 1); while (p >= pmin) { *(p + n) = *p; p--; } SLMEMCPY ((char *) pmin, s, n); This_RLI->len += n; This_RLI->point += n; return n;}static int rl_deln (int n){ unsigned char *pmax, *p; p = This_RLI->buf + This_RLI->point; pmax = This_RLI->buf + This_RLI->len; if (p + n > pmax) n = (int) (pmax - p); while (p < pmax) { *p = *(p + n); p++; } This_RLI->len -= n; return n;}static int rl_del (void){ return rl_deln(1);}static int rl_quote_insert (void){ int err = SLang_Error; SLang_Error = 0; SLang_Last_Key_Char = (*This_RLI->getkey)(); rl_self_insert (); if (SLang_Error == SL_USER_BREAK) SLang_Error = 0; else SLang_Error = err; return 1;}static int rl_trim (void){ unsigned char *p, *pmax, *p1; p = This_RLI->buf + This_RLI->point; pmax = This_RLI->buf + This_RLI->len; if (p == pmax) { if (p == This_RLI->buf) return 0; p--; } if ((*p != ' ') && (*p != '\t')) return 0; p1 = p; while ((p1 < pmax) && ((*p1 == ' ') || (*p1 == '\t'))) p1++; pmax = p1; p1 = This_RLI->buf; while ((p >= p1) && ((*p == ' ') || (*p == '\t'))) p--; if (p == pmax) return 0; p++; This_RLI->point = (int) (p - p1); return rl_deln ((int) (pmax - p));}static int rl_bdel (void){ if (rl_left()) return rl_del(); return 0;}static int rl_deleol (void){ if (This_RLI->point == This_RLI->len) return 0; *(This_RLI->buf + This_RLI->point) = 0; This_RLI->len = This_RLI->point; return 1;}static int rl_delete_line (void){ This_RLI->point = 0; *(This_RLI->buf + This_RLI->point) = 0; This_RLI->len = 0; return 1;}static int rl_enter (void){ *(This_RLI->buf + This_RLI->len) = 0; SLang_Rline_Quit = 1; return 1;}static SLKeyMap_List_Type *RL_Keymap;/* This update is designed for dumb terminals. It assumes only that the * terminal can backspace via ^H, and move cursor to start of line via ^M. * There is a hook so the user can provide a more sophisticated update if * necessary. */static void position_cursor (int col){ unsigned char *p, *pmax; int dc; if (col == This_RLI->curs_pos) { fflush (stdout); return; } if (This_RLI->tt_goto_column != NULL) { (*This_RLI->tt_goto_column)(col); This_RLI->curs_pos = col; fflush (stdout); return; } dc = This_RLI->curs_pos - col; if (dc < 0) { p = This_RLI->new_upd + This_RLI->curs_pos; pmax = This_RLI->new_upd + col; while (p < pmax) putc((char) *p++, stdout); } else { if (dc < col) { while (dc--) putc(8, stdout); } else { putc('\r', stdout); p = This_RLI->new_upd; pmax = This_RLI->new_upd + col; while (p < pmax) putc((char) *p++, stdout); } } This_RLI->curs_pos = col; fflush (stdout);}static void erase_eol (SLang_RLine_Info_Type *rli){ unsigned char *p, *pmax; p = rli->old_upd + rli->curs_pos; pmax = rli->old_upd + rli->old_upd_len; while (p++ < pmax) putc(' ', stdout); rli->curs_pos = rli->old_upd_len;}static unsigned char *spit_out(SLang_RLine_Info_Type *rli, unsigned char *p){ unsigned char *pmax; position_cursor ((int) (p - rli->new_upd)); pmax = rli->new_upd + rli->new_upd_len; while (p < pmax) putc((char) *p++, stdout); rli->curs_pos = rli->new_upd_len; return pmax;}static void really_update (SLang_RLine_Info_Type *rli, int new_curs_position){ unsigned char *b = rli->old_upd, *p = rli->new_upd, chb, chp; unsigned char *pmax; if (rli->update_hook != NULL) { (*rli->update_hook)(p, rli->edit_width, new_curs_position); } else { pmax = p + rli->edit_width; while (p < pmax) { chb = *b++; chp = *p++; if (chb == chp) continue; if (rli->old_upd_len <= rli->new_upd_len) { /* easy one */ (void) spit_out (rli, p - 1); break; } spit_out(rli, p - 1); erase_eol (rli); break; } position_cursor (new_curs_position); } /* update finished, so swap */ rli->old_upd_len = rli->new_upd_len; p = rli->old_upd; rli->old_upd = rli->new_upd; rli->new_upd = p;}static void RLupdate (SLang_RLine_Info_Type *rli){ int len, dlen, start_len, prompt_len = 0, tw = 0, count; int want_cursor_pos; unsigned char *b, chb, *b_point, *p; int no_echo; no_echo = rli->flags & SL_RLINE_NO_ECHO; b_point = (unsigned char *) (rli->buf + rli->point); *(rli->buf + rli->len) = 0; /* expand characters for output buffer --- handle prompt first. * Do two passes --- first to find out where to begin upon horiz * scroll and the second to actually fill the buffer. */ len = 0; count = 2; /* once for prompt and once for buf */ b = (unsigned char *) rli->prompt; while (count--) { if ((count == 0) && no_echo) break; /* The prompt could be NULL */ if (b != NULL) while ((chb = *b) != 0) { /* This will ensure that the screen is scrolled a third of the edit * width each time */ if (b_point == b) break; dlen = Char_Widths[chb]; if ((chb == '\t') && tw) { dlen = tw * ((len - prompt_len) / tw + 1) - (len - prompt_len); } len += dlen; b++; } tw = rli->tab; b = (unsigned char *) rli->buf; if (count == 1) prompt_len = len; } if (len < rli->edit_width - rli->dhscroll) start_len = 0; else if ((rli->start_column > len) || (rli->start_column + rli->edit_width <= len)) { start_len = len - (rli->edit_width - rli->dhscroll); if (start_len < 0) start_len = 0; } else start_len = rli->start_column; rli->start_column = start_len; want_cursor_pos = len - start_len; /* second pass */ p = rli->new_upd; len = 0; count = 2; b = (unsigned char *) rli->prompt; if (b == NULL) b = (unsigned char *) ""; while ((len < start_len) && (*b)) { len += Char_Widths[*b++]; } tw = 0; if (*b == 0) { b = (unsigned char *) rli->buf; while (len < start_len) { len += Char_Widths[*b++]; } tw = rli->tab; count--; } len = 0; while (count--) { if ((count == 0) && (no_echo)) break; while ((len < rli->edit_width) && ((chb = *b++) != 0)) { dlen = Char_Widths[chb]; if (dlen == 1) *p++ = chb; else { if ((chb == '\t') && tw) { dlen = tw * ((len + start_len - prompt_len) / tw + 1) - (len + start_len - prompt_len);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -