📄 getline.c
字号:
len = strlen(gl_killbuf); if (len > 0) { if (gl_overwrite == 0) { if (gl_cnt + len >= BUF_SIZE - 1) gl_error("\n*** Error: getline(): input buffer overflow\n"); for (i=gl_cnt; i >= gl_pos; i--) gl_buf[i+len] = gl_buf[i]; for (i=0; i < len; i++) gl_buf[gl_pos+i] = gl_killbuf[i]; gl_fixup(gl_prompt, gl_pos, gl_pos+len); } else { if (gl_pos + len > gl_cnt) { if (gl_pos + len >= BUF_SIZE - 1) gl_error("\n*** Error: getline(): input buffer overflow\n"); gl_buf[gl_pos + len] = 0; } for (i=0; i < len; i++) gl_buf[gl_pos+i] = gl_killbuf[i]; gl_extent = len; gl_fixup(gl_prompt, gl_pos, gl_pos+len); } } else gl_putc('\007');}static voidgl_transpose()/* switch character under cursor and to left of cursor */{ int c; if (gl_pos > 0 && gl_cnt > gl_pos) { c = gl_buf[gl_pos-1]; gl_buf[gl_pos-1] = gl_buf[gl_pos]; gl_buf[gl_pos] = c; gl_extent = 2; gl_fixup(gl_prompt, gl_pos-1, gl_pos); } else gl_putc('\007');}static voidgl_newline()/* * Cleans up entire line before returning to caller. A \n is appended. * If line longer than screen, we redraw starting at beginning */{ int change = gl_cnt; int len = gl_cnt; int loc = gl_width - 5; /* shifts line back to start position */ if (gl_cnt >= BUF_SIZE - 1) gl_error("\n*** Error: getline(): input buffer overflow\n"); if (gl_out_hook) { change = gl_out_hook(gl_buf); len = strlen(gl_buf); } if (loc > len) loc = len; gl_fixup(gl_prompt, change, loc); /* must do this before appending \n */ gl_buf[len] = '\n'; gl_buf[len+1] = '\0'; gl_putc('\n');}static voidgl_del(loc)int loc;/* * Delete a character. The loc variable can be: * -1 : delete character to left of cursor * 0 : delete character under cursor */{ int i; if ((loc == -1 && gl_pos > 0) || (loc == 0 && gl_pos < gl_cnt)) { for (i=gl_pos+loc; i < gl_cnt; i++) gl_buf[i] = gl_buf[i+1]; gl_fixup(gl_prompt, gl_pos+loc, gl_pos+loc); } else gl_putc('\007');}static voidgl_kill(pos)int pos;/* delete from pos to the end of line */{ if (pos < gl_cnt) { strcpy(gl_killbuf, gl_buf + pos); gl_buf[pos] = '\0'; gl_fixup(gl_prompt, pos, pos); } else gl_putc('\007');}static voidgl_word(direction)int direction;/* move forward or backword one word */{ int pos = gl_pos; if (direction > 0) { /* forward */ while (!isspace(gl_buf[pos]) && pos < gl_cnt) pos++; while (isspace(gl_buf[pos]) && pos < gl_cnt) pos++; } else { /* backword */ if (pos > 0) pos--; while (isspace(gl_buf[pos]) && pos > 0) pos--; while (!isspace(gl_buf[pos]) && pos > 0) pos--; if (pos < gl_cnt && isspace(gl_buf[pos])) /* move onto word */ pos++; } gl_fixup(gl_prompt, -1, pos);}static voidgl_redraw()/* emit a newline, reset and redraw prompt and current input line */{ if (gl_init_done > 0) { gl_putc('\n'); gl_fixup(gl_prompt, -2, gl_pos); }}voidgl_redraw_r()/* emit a newline, reset and redraw prompt and current input line */{ if (gl_init_done > 0) { gl_putc('\r'); gl_fixup(gl_prompt, -2, gl_pos); }}static voidgl_fixup(prompt, change, cursor)char *prompt;int change, cursor;/* * This function is used both for redrawing when input changes or for * moving within the input line. The parameters are: * prompt: compared to last_prompt[] for changes; * change : the index of the start of changes in the input buffer, * with -1 indicating no changes, -2 indicating we're on * a new line, redraw everything. * cursor : the desired location of the cursor after the call. * A value of BUF_SIZE can be used to indicate the cursor should * move just past the end of the input line. */{ static int gl_shift; /* index of first on screen character */ static int off_right; /* true if more text right of screen */ static int off_left; /* true if more text left of screen */ static char last_prompt[80] = ""; int left = 0, right = -1; /* bounds for redraw */ int pad; /* how much to erase at end of line */ int backup; /* how far to backup before fixing */ int new_shift; /* value of shift based on cursor */ int extra; /* adjusts when shift (scroll) happens */ int i; int new_right = -1; /* alternate right bound, using gl_extent */ int l1, l2; if (change == -2) { /* reset */ gl_pos = gl_cnt = gl_shift = off_right = off_left = 0; gl_putc('\r'); gl_puts(prompt); strcpy(last_prompt, prompt); change = 0; gl_width = gl_termw - gl_strlen(prompt); } else if (strcmp(prompt, last_prompt) != 0) { l1 = gl_strlen(last_prompt); l2 = gl_strlen(prompt); gl_cnt = gl_cnt + l1 - l2; strcpy(last_prompt, prompt); gl_putc('\r'); gl_puts(prompt); gl_pos = gl_shift; gl_width = gl_termw - l2; change = 0; } pad = (off_right)? gl_width - 1 : gl_cnt - gl_shift; /* old length */ backup = gl_pos - gl_shift; if (change >= 0) { gl_cnt = strlen(gl_buf); if (change > gl_cnt) change = gl_cnt; } if (cursor > gl_cnt) { if (cursor != BUF_SIZE) /* BUF_SIZE means end of line */ gl_putc('\007'); cursor = gl_cnt; } if (cursor < 0) { gl_putc('\007'); cursor = 0; } if (off_right || (off_left && cursor < gl_shift + gl_width - gl_scroll / 2)) extra = 2; /* shift the scrolling boundary */ else extra = 0; new_shift = cursor + extra + gl_scroll - gl_width; if (new_shift > 0) { new_shift /= gl_scroll; new_shift *= gl_scroll; } else new_shift = 0; if (new_shift != gl_shift) { /* scroll occurs */ gl_shift = new_shift; off_left = (gl_shift)? 1 : 0; off_right = (gl_cnt > gl_shift + gl_width - 1)? 1 : 0; left = gl_shift; new_right = right = (off_right)? gl_shift + gl_width - 2 : gl_cnt; } else if (change >= 0) { /* no scroll, but text changed */ if (change < gl_shift + off_left) { left = gl_shift; } else { left = change; backup = gl_pos - change; } off_right = (gl_cnt > gl_shift + gl_width - 1)? 1 : 0; right = (off_right)? gl_shift + gl_width - 2 : gl_cnt; new_right = (gl_extent && (right > left + gl_extent))? left + gl_extent : right; } pad -= (off_right)? gl_width - 1 : gl_cnt - gl_shift; pad = (pad < 0)? 0 : pad; if (left <= right) { /* clean up screen */ for (i=0; i < backup; i++) gl_putc('\b'); if (left == gl_shift && off_left) { gl_putc('$'); left++; } for (i=left; i < new_right; i++) gl_putc(gl_buf[i]); gl_pos = new_right; if (off_right && new_right == right) { gl_putc('$'); gl_pos++; } else { for (i=0; i < pad; i++) /* erase remains of prev line */ gl_putc(' '); gl_pos += pad; } } i = gl_pos - cursor; /* move to final cursor location */ if (i > 0) { while (i--) gl_putc('\b'); } else { for (i=gl_pos; i < cursor; i++) gl_putc(gl_buf[i]); } gl_pos = cursor;}static intgl_tab(buf, offset, loc)char *buf;int offset;int *loc;/* default tab handler, acts like tabstops every 8 cols */{ int i, count, len; len = strlen(buf); count = 8 - (offset + *loc) % 8; for (i=len; i >= *loc; i--) buf[i+count] = buf[i]; for (i=0; i < count; i++) buf[*loc+i] = ' '; i = *loc; *loc = i + count; return i;}/******************* strlen stuff **************************************/void gl_strwidth(func)size_t (*func)();{ if (func != 0) { gl_strlen = func; }}/******************* History stuff **************************************/#ifndef HIST_SIZE#define HIST_SIZE 100#endifstatic int hist_pos = 0, hist_last = 0;static char *hist_buf[HIST_SIZE];static voidhist_init(){ int i; hist_buf[0] = ""; for (i=1; i < HIST_SIZE; i++) hist_buf[i] = (char *)0;}voidgl_histadd(buf)char *buf;{ static char *prev = 0; char *p = buf; int len; /* in case we call gl_histadd() before we call getline() */ if (gl_init_done < 0) { /* -1 only on startup */ hist_init(); gl_init_done = 0; } while (*p == ' ' || *p == '\t' || *p == '\n') p++; if (*p) { len = strlen(buf); if (strchr(p, '\n')) /* previously line already has NL stripped */ len--; if (prev == 0 || strlen(prev) != len || strncmp(prev, buf, len) != 0) { hist_buf[hist_last] = hist_save(buf); prev = hist_buf[hist_last]; hist_last = (hist_last + 1) % HIST_SIZE; if (hist_buf[hist_last] && *hist_buf[hist_last]) { free(hist_buf[hist_last]); } hist_buf[hist_last] = ""; } } hist_pos = hist_last;}static char *hist_prev()/* loads previous hist entry into input buffer, sticks on first */{ char *p = 0; int next = (hist_pos - 1 + HIST_SIZE) % HIST_SIZE; if (hist_buf[hist_pos] != 0 && next != hist_last) { hist_pos = next; p = hist_buf[hist_pos]; } if (p == 0) { p = ""; gl_putc('\007'); } return p;}static char *hist_next()/* loads next hist entry into input buffer, clears on last */{ char *p = 0; if (hist_pos != hist_last) { hist_pos = (hist_pos+1) % HIST_SIZE; p = hist_buf[hist_pos]; } if (p == 0) { p = ""; gl_putc('\007'); } return p;}static char *hist_save(p)char *p;/* makes a copy of the string */{ char *s = 0; int len = strlen(p); char *nl = strchr(p, '\n'); if (nl) { if ((s = malloc(len)) != 0) { strncpy(s, p, len-1); s[len-1] = 0; } } else { if ((s = malloc(len+1)) != 0) { strcpy(s, p); } } if (s == 0) gl_error("\n*** Error: hist_save() failed on malloc\n"); return s;}/******************* Search stuff **************************************/static char search_prompt[101]; /* prompt includes search string */static char search_string[100];static int search_pos = 0; /* current location in search_string */static int search_forw_flg = 0; /* search direction flag */static int search_last = 0; /* last match found */static void search_update(c)int c;{ if (c == 0) { search_pos = 0; search_string[0] = 0; search_prompt[0] = '?'; search_prompt[1] = ' '; search_prompt[2] = 0; } else if (c > 0) { search_string[search_pos] = c; search_string[search_pos+1] = 0; search_prompt[search_pos] = c; search_prompt[search_pos+1] = '?'; search_prompt[search_pos+2] = ' '; search_prompt[search_pos+3] = 0; search_pos++; } else { if (search_pos > 0) { search_pos--; search_string[search_pos] = 0; search_prompt[search_pos] = '?'; search_prompt[search_pos+1] = ' '; search_prompt[search_pos+2] = 0; } else { gl_putc('\007'); hist_pos = hist_last; } }}static void search_addchar(c)int c;{ char *loc; search_update(c); if (c < 0) { if (search_pos > 0) { hist_pos = search_last; } else { gl_buf[0] = 0; hist_pos = hist_last; } strcpy(gl_buf, hist_buf[hist_pos]); } if ((loc = strstr(gl_buf, search_string)) != 0) { gl_fixup(search_prompt, 0, loc - gl_buf); } else if (search_pos > 0) { if (search_forw_flg) { search_forw(0); } else { search_back(0); } } else { gl_fixup(search_prompt, 0, 0); }}static void search_term(){ gl_search_mode = 0; if (gl_buf[0] == 0) /* not found, reset hist list */ hist_pos = hist_last; if (gl_in_hook) gl_in_hook(gl_buf); gl_fixup(gl_prompt, 0, gl_pos);}static void search_back(new_search)int new_search;{ int found = 0; char *p, *loc; search_forw_flg = 0; if (gl_search_mode == 0) { search_last = hist_pos = hist_last; search_update(0); gl_search_mode = 1; gl_buf[0] = 0; gl_fixup(search_prompt, 0, 0); } else if (search_pos > 0) { while (!found) { p = hist_prev(); if (*p == 0) { /* not found, done looking */ gl_buf[0] = 0; gl_fixup(search_prompt, 0, 0); found = 1; } else if ((loc = strstr(p, search_string)) != 0) { strcpy(gl_buf, p); gl_fixup(search_prompt, 0, loc - p); if (new_search) search_last = hist_pos; found = 1; } } } else { gl_putc('\007'); }}static void search_forw(new_search)int new_search;{ int found = 0; char *p, *loc; search_forw_flg = 1; if (gl_search_mode == 0) { search_last = hist_pos = hist_last; search_update(0); gl_search_mode = 1; gl_buf[0] = 0; gl_fixup(search_prompt, 0, 0); } else if (search_pos > 0) { while (!found) { p = hist_next(); if (*p == 0) { /* not found, done looking */ gl_buf[0] = 0; gl_fixup(search_prompt, 0, 0); found = 1; } else if ((loc = strstr(p, search_string)) != 0) { strcpy(gl_buf, p); gl_fixup(search_prompt, 0, loc - p); if (new_search) search_last = hist_pos; found = 1; } } } else { gl_putc('\007'); }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -