/* * Input an escaped token. Possible escape chars are single-quote, * double-quote and backslash. Only the first is a valid escape for * rc; the others are just inserted into the receiving buffer. */ int escapetoken(Biobuf *bp, Bufblock *buf, int preserve, int esc) { int c, line; if(esc != '\'') return 1; line = mkinline; while((c = nextrune(bp, 0)) > 0){ if(c == '\''){ if(preserve) rinsert(buf, c); c = Bgetrune(bp); if (c < 0) break; if(c != '\''){ Bungetrune(bp); return 1; } } rinsert(buf, c); } SYNERR(line); fprint(2, "missing closing %c\n", esc); return 0; }
void copy_first() { if (valid) { strcpy(text, valid->text); while (text[cursor] != '\0' && cursor < MAX_LEN - 1) cursor = nextrune(+1); update_valid_options(); } }
static int lex(struct cstate *g) { int quoted = nextrune(g); if (quoted) { switch (g->yychar) { case 'b': return L_WORD; case 'B': return L_NWORD; case 'd': newcclass(g); addranges_d(g); return L_CCLASS; case 's': newcclass(g); addranges_s(g); return L_CCLASS; case 'w': newcclass(g); addranges_w(g); return L_CCLASS; case 'D': newcclass(g); addranges_d(g); return L_NCCLASS; case 'S': newcclass(g); addranges_s(g); return L_NCCLASS; case 'W': newcclass(g); addranges_w(g); return L_NCCLASS; case '0': g->yychar = 0; return L_CHAR; } if (g->yychar >= '0' && g->yychar <= '9') { g->yychar -= '0'; if (*g->source >= '0' && *g->source <= '9') g->yychar = g->yychar * 10 + *g->source++ - '0'; return L_REF; } return L_CHAR; } switch (g->yychar) { case 0: case '$': case ')': case '*': case '+': case '.': case '?': case '^': case '|': return g->yychar; } if (g->yychar == '{') return lexcount(g); if (g->yychar == '[') return lexclass(g); if (g->yychar == '(') { if (g->source[0] == '?') { if (g->source[1] == ':') { g->source += 2; return L_NC; } if (g->source[1] == '=') { g->source += 2; return L_PLA; } if (g->source[1] == '!') { g->source += 2; return L_NLA; } } return '('; } return L_CHAR; }
/* * Assemble a line skipping blank lines, comments, and eliding * escaped newlines */ int assline(Biobuf *bp, Bufblock *buf) { int c; int lastc; buf->current=buf->start; while ((c = nextrune(bp, 1)) >= 0){ switch(c) { case '\r': /* consumes CRs for Win95 */ continue; case '\n': if (buf->current != buf->start) { insert(buf, 0); return 1; } break; /* skip empty lines */ case '\\': case '\'': case '"': rinsert(buf, c); if (escapetoken(bp, buf, 1, c) == 0) Exit(); break; case '`': if (bquote(bp, buf) == 0) Exit(); break; case '#': lastc = '#'; while ((c = Bgetc(bp)) != '\n') { if (c < 0) goto eof; if(c != '\r') lastc = c; } mkinline++; if (lastc == '\\') break; /* propagate escaped newlines??*/ if (buf->current != buf->start) { insert(buf, 0); return 1; } break; default: rinsert(buf, c); break; } } eof: insert(buf, 0); return *buf->start != 0; }
/* * assemble a back-quoted shell command into a buffer */ static int bquote(Biobuf *bp, Bufblock *buf) { int c, line, term, depth; int start; line = mkinline; while((c = Bgetrune(bp)) == ' ' || c == '\t') ; if(c == '{'){ term = '}'; /* rc style */ while((c = Bgetrune(bp)) == ' ' || c == '\t') ; } else term = '`'; /* sh style */ depth = 1; start = buf->current-buf->start; for(;c > 0; c = nextrune(bp, 0)){ if(c == '{' && term == '}') depth++; if(c == term && --depth == 0){ insert(buf, '\n'); insert(buf,0); buf->current = buf->start+start; execinit(); execsh(0, buf->current, buf, envy); return 1; } if(c == '\n') break; if(c == '\'' || c == '"' || c == '\\'){ insert(buf, c); if(!escapetoken(bp, buf, 1, c)) return 0; continue; } rinsert(buf, c); } SYNERR(line); fprint(2, "missing closing %c after `\n", term); return 0; }
/* * Input an escaped token. Possible escape chars are single-quote, * double-quote and backslash. */ static int shescapetoken(Biobuf *bp, Bufblock *buf, int preserve, int esc) { int c, line; if(esc == '\\') { c = Bgetrune(bp); if(c == '\r') c = Bgetrune(bp); if (c == '\n') mkinline++; rinsert(buf, c); return 1; } line = mkinline; while((c = nextrune(bp, 0)) >= 0){ if(c == esc){ if(preserve) rinsert(buf, c); return 1; } if(c == '\\') { rinsert(buf, c); c = Bgetrune(bp); if(c == '\r') c = Bgetrune(bp); if (c < 0) break; if (c == '\n') mkinline++; } rinsert(buf, c); } SYNERR(line); fprint(2, "missing closing %c\n", esc); return 0; }
void keypress(XKeyEvent *ev) { char buf[32]; int len; KeySym ksym = NoSymbol; Status status; len = XmbLookupString(xic, ev, buf, sizeof buf, &ksym, &status); if(status == XBufferOverflow) return; if(ev->state & ControlMask) switch(ksym) { case XK_a: ksym = XK_Home; break; case XK_b: ksym = XK_Left; break; case XK_c: ksym = XK_Escape; break; case XK_d: ksym = XK_Delete; break; case XK_e: ksym = XK_End; break; case XK_f: ksym = XK_Right; break; case XK_g: ksym = XK_Escape; break; case XK_h: ksym = XK_BackSpace; break; case XK_i: ksym = XK_Tab; break; case XK_j: /* fallthrough */ case XK_J: ksym = XK_Return; break; case XK_m: /* fallthrough */ case XK_M: ksym = XK_Return; break; case XK_n: ksym = XK_Down; break; case XK_p: ksym = XK_Up; break; case XK_k: /* delete right */ text[cursor] = '\0'; match(); break; case XK_u: /* delete left */ insert(NULL, 0 - cursor); break; case XK_w: /* delete word */ while(cursor > 0 && text[nextrune(-1)] == ' ') insert(NULL, nextrune(-1) - cursor); while(cursor > 0 && text[nextrune(-1)] != ' ' && text[nextrune(-1)] != '/') insert(NULL, nextrune(-1) - cursor); break; case XK_y: /* paste selection */ XConvertSelection(dc->dpy, (ev->state & ShiftMask) ? clip : XA_PRIMARY, utf8, utf8, win, CurrentTime); return; default: return; } else if(ev->state & Mod1Mask) switch(ksym) { case XK_g: ksym = XK_Home; break; case XK_G: ksym = XK_End; break; case XK_h: ksym = XK_Up; break; case XK_j: ksym = XK_Next; break; case XK_k: ksym = XK_Prior; break; case XK_l: ksym = XK_Down; break; default: return; } switch(ksym) { default: if(!iscntrl(*buf)) insert(buf, len); break; case XK_Delete: if(text[cursor] == '\0') return; cursor = nextrune(+1); /* fallthrough */ case XK_BackSpace: if(cursor == 0) return; insert(NULL, nextrune(-1) - cursor); break; case XK_End: if(text[cursor] != '\0') { cursor = strlen(text); break; } if(next) { /* jump to end of list and position items in reverse */ curr = matchend; calcoffsets(); curr = prev; calcoffsets(); while(next && (curr = curr->right)) calcoffsets(); } sel = matchend; break; case XK_Escape: ret = EXIT_FAILURE; running = False; case XK_Home: if(sel == matches) { cursor = 0; break; } sel = curr = matches; calcoffsets(); break; case XK_Left: if(cursor > 0 && (!sel || !sel->left || lines > 0)) { cursor = nextrune(-1); break; } if(lines > 0) return; /* fallthrough */ case XK_Up: if(sel && sel->left && (sel = sel->left)->right == curr) { curr = prev; calcoffsets(); } break; case XK_Next: if(!next) return; sel = curr = next; calcoffsets(); break; case XK_Prior: if(!prev) return; sel = curr = prev; calcoffsets(); break; case XK_Return: case XK_KP_Enter: puts((sel && !(ev->state & ShiftMask)) ? sel->text : text); ret = EXIT_SUCCESS; running = False; case XK_Right: if(text[cursor] != '\0') { cursor = nextrune(+1); break; } if(lines > 0) return; /* fallthrough */ case XK_Down: if(sel && sel->right && (sel = sel->right) == next) { curr = next; calcoffsets(); } break; case XK_Tab: if(!sel) return; strncpy(text, sel->text, sizeof text); cursor = strlen(text); match(); break; } drawmenu(); }
void handle_key(XKeyEvent ke) { FcChar8 buf[32]; int len, n; KeySym keysym = NoSymbol; Status status; option *o; len = XmbLookupString(xic, &ke, buf, sizeof(buf), &keysym, &status); if (status == XBufferOverflow) return; if (ke.state & ControlMask) { switch(keysym) { case XK_a: keysym = XK_Home; break; case XK_e: keysym = XK_End; break; case XK_p: keysym = XK_Up; break; case XK_n: keysym = XK_Down; break; case XK_f: keysym = XK_Right; break; case XK_b: keysym = XK_Left; break; case XK_d: keysym = XK_Delete; break; case XK_bracketleft: keysym = XK_Escape; break; case XK_k: text[cursor] = '\0'; break; case XK_u: for (n = cursor; cursor < MAX_LEN; cursor++) text[cursor - n] = text[cursor]; cursor = 0; update_valid_options(); return; } } if (text_input) { switch(keysym) { default: if (!iscntrl(*buf)) { insert(buf, len); update_valid_options(); } break; case XK_Delete: if (text[cursor] == '\0') break; cursor = nextrune(+1); /* Fall through to backspace */ case XK_BackSpace: if (cursor == 0) exit(0); insert(NULL, nextrune(-1) - cursor); update_valid_options(); break; case XK_Tab: copy_first(); break; case XK_Left: if (cursor != 0) cursor = nextrune(-1); break; case XK_Right: if (text[cursor] != '\0') cursor = nextrune(+1); break; case XK_Home: cursor = 0; break; case XK_End: while (text[cursor] != '\0') cursor = nextrune(+1); } } switch(keysym) { case XK_Up: if (valid->prev) valid = valid->prev; else for (; valid && valid->next; valid = valid->next); break; case XK_Down: if (valid->next) valid = valid->next; else for (; valid && valid->prev; valid = valid->prev); break; case XK_Return: finish(); break; case XK_Escape: exit(1); break; } if (exit_on_one) { for (n = 0, o = valid; o; o = o->next) n++; if (n == 1) finish(); } }
static int lexclass(struct cstate *g) { int type = L_CCLASS; int quoted, havesave, havedash; Rune save; newcclass(g); quoted = nextrune(g); if (!quoted && g->yychar == '^') { type = L_NCCLASS; quoted = nextrune(g); } havesave = havedash = 0; for (;;) { if (g->yychar == 0) die(g, "unterminated character class"); if (!quoted && g->yychar == ']') break; if (!quoted && g->yychar == '-') { if (havesave) { if (havedash) { addrange(g, save, '-'); havesave = havedash = 0; } else { havedash = 1; } } else { save = '-'; havesave = 1; } } else if (quoted && strchr("DSWdsw", g->yychar)) { if (havesave) { addrange(g, save, save); if (havedash) addrange(g, '-', '-'); } switch (g->yychar) { case 'd': addranges_d(g); break; case 's': addranges_s(g); break; case 'w': addranges_w(g); break; case 'D': addranges_D(g); break; case 'S': addranges_S(g); break; case 'W': addranges_W(g); break; } havesave = havedash = 0; } else { if (quoted) { if (g->yychar == 'b') g->yychar = '\b'; else if (g->yychar == '0') g->yychar = 0; /* else identity escape */ } if (havesave) { if (havedash) { addrange(g, save, g->yychar); havesave = havedash = 0; } else { addrange(g, save, save); save = g->yychar; } } else { save = g->yychar; havesave = 1; } } quoted = nextrune(g); } if (havesave) { addrange(g, save, save); if (havedash) addrange(g, '-', '-'); } return type; }
void keypress(Input *i, XKeyEvent *ev) { char buf[32]; int len; KeySym ksym = NoSymbol; Status status; len = XmbLookupString(ic, ev, buf, sizeof(buf), &ksym, &status); if (status == XBufferOverflow) return; if (ev->state & ControlMask) switch (ksym) { case XK_a: ksym = XK_Home; break; case XK_b: ksym = XK_Left; break; case XK_d: ksym = XK_Delete; break; case XK_e: ksym = XK_End; break; case XK_f: ksym = XK_Right; break; case XK_h: ksym = XK_BackSpace; break; case XK_i: ksym = XK_Tab; break; case XK_j: case XK_m: ksym = XK_Return; break; default: return; } else if (ev->state & Mod1Mask) switch (ksym) { case XK_g: ksym = XK_Home; break; case XK_G: ksym = XK_End; break; default: return; } switch (ksym) { default: if (!iscntrl(*buf)) insert(i, buf, len); break; case XK_Delete: if (i->text[i->cursor] == 0) return; i->cursor = nextrune(i, +1); /* fallthrough */ case XK_BackSpace: if (i->cursor == 0) return; insert(i, NULL, nextrune(i, -1) - i->cursor); break; case XK_Home: if (i->cursor == 0) return; i->cursor = 0; break; case XK_End: if (i->text[i->cursor] == 0) return; i->cursor = strlen(i->text); break; case XK_Left: if (i->cursor == 0) return; i->cursor = nextrune(i, -1); break; case XK_Right: if (i->text[i->cursor] == 0) return; i->cursor = nextrune(i, +1); break; case XK_Return: case XK_KP_Enter: if (!i->next) { running = False; return; } /* fallthrough */ case XK_Tab: XSetInputFocus(dpy, i->next ? i->next->win : inputs->win, RevertToPointerRoot, CurrentTime); return; } drawinput(i); }
static int run(void) { char buf[32]; char c; for (;;) { xread(0, &c, 1); memset(buf, '\0', sizeof buf); buf[0] = c; switch_top: switch(c) { case CONTROL('['): xread(0, &c, 1); esc_switch_top: switch(c) { case CONTROL('['): /* ESC, need to press twice due to console limitations */ c = CONTROL('C'); goto switch_top; case '[': xread(0, &c, 1); switch(c) { case '1': /* Home */ case '7': case 'H': if (c != 'H') xread(0, &c, 1); /* Remove trailing '~' from stdin */ c = CONTROL('A'); goto switch_top; case '2': /* Insert */ xread(0, &c, 1); /* Remove trailing '~' from stdin */ c = CONTROL('Y'); goto switch_top; case '3': /* Delete */ xread(0, &c, 1); /* Remove trailing '~' from stdin */ c = CONTROL('D'); goto switch_top; case '4': /* End */ case '8': case 'F': if (c != 'F') xread(0, &c, 1); /* Remove trailing '~' from stdin */ c = CONTROL('E'); goto switch_top; case '5': /* PageUp */ xread(0, &c, 1); /* Remove trailing '~' from stdin */ c = CONTROL('V'); goto switch_top; case '6': /* PageDown */ xread(0, &c, 1); /* Remove trailing '~' from stdin */ c = 'v'; goto esc_switch_top; case 'A': /* Up arrow */ c = CONTROL('P'); goto switch_top; case 'B': /* Down arrow */ c = CONTROL('N'); goto switch_top; case 'C': /* Right arrow */ c = CONTROL('F'); goto switch_top; case 'D': /* Left arrow */ c = CONTROL('B'); goto switch_top; } break; case 'b': while (cursor > 0 && text[nextrune(-1)] == ' ') cursor = nextrune(-1); while (cursor > 0 && text[nextrune(-1)] != ' ') cursor = nextrune(-1); break; case 'f': while (text[cursor] != '\0' && text[nextrune(+1)] == ' ') cursor = nextrune(+1); if (text[cursor] != '\0') { do { cursor = nextrune(+1); } while (text[cursor] != '\0' && text[cursor] != ' '); } break; case 'd': while (text[cursor] != '\0' && text[nextrune(+1)] == ' ') { cursor = nextrune(+1); insert(NULL, nextrune(-1) - cursor); } if (text[cursor] != '\0') { do { cursor = nextrune(+1); insert(NULL, nextrune(-1) - cursor); } while (text[cursor] != '\0' && text[cursor] != ' '); } break; case 'v': if (!next) break; sel = curr = next; calcoffsets(); break; default: break; } break; case CONTROL('C'): return EXIT_FAILURE; case CONTROL('M'): /* Return */ case CONTROL('J'): if (sel) strncpy(text, sel->text, sizeof(text)-1); /* Complete the input first, when hitting return */ cursor = strlen(text); match(); drawmenu(); /* fallthrough */ case CONTROL(']'): case CONTROL('\\'): /* These are usually close enough to RET to replace Shift+RET, again due to console limitations */ puts(text); return EXIT_SUCCESS; case CONTROL('A'): if (sel == matches) { cursor = 0; break; } sel = curr = matches; calcoffsets(); break; case CONTROL('E'): if (text[cursor] != '\0') { cursor = strlen(text); break; } if (next) { curr = matchend; calcoffsets(); curr = prev; calcoffsets(); while(next && (curr = curr->right)) calcoffsets(); } sel = matchend; break; case CONTROL('B'): if (cursor > 0 && (!sel || !sel->left || lines > 0)) { cursor = nextrune(-1); break; } /* fallthrough */ case CONTROL('P'): if (sel && sel->left && (sel = sel->left)->right == curr) { curr = prev; calcoffsets(); } break; case CONTROL('F'): if (text[cursor] != '\0') { cursor = nextrune(+1); break; } /* fallthrough */ case CONTROL('N'): if (sel && sel->right && (sel = sel->right) == next) { curr = next; calcoffsets(); } break; case CONTROL('D'): if (text[cursor] == '\0') break; cursor = nextrune(+1); /* fallthrough */ case CONTROL('H'): case CONTROL('?'): /* Backspace */ if (cursor == 0) break; insert(NULL, nextrune(-1) - cursor); break; case CONTROL('I'): /* TAB */ if (!sel) break; strncpy(text, sel->text, sizeof text); cursor = strlen(text); match(); break; case CONTROL('K'): text[cursor] = '\0'; match(); break; case CONTROL('U'): insert(NULL, 0 - cursor); break; case CONTROL('W'): while (cursor > 0 && text[nextrune(-1)] == ' ') insert(NULL, nextrune(-1) - cursor); while (cursor > 0 && text[nextrune(-1)] != ' ') insert(NULL, nextrune(-1) - cursor); break; case CONTROL('V'): if (!prev) break; sel = curr = prev; calcoffsets(); break; default: if (!iscntrl(*buf)) insert(buf, strlen(buf)); break; } drawmenu(); } }
void keypress(XKeyEvent *ev) { char buf[32]; size_t len; KeySym ksym; len = strlen(text); XLookupString(ev, buf, sizeof buf, &ksym, NULL); if(ev->state & ControlMask) { switch(tolower(ksym)) { default: return; case XK_a: ksym = XK_Home; break; case XK_b: ksym = XK_Left; break; case XK_c: ksym = XK_Escape; break; case XK_d: ksym = XK_Delete; break; case XK_e: ksym = XK_End; break; case XK_f: ksym = XK_Right; break; case XK_h: ksym = XK_BackSpace; break; case XK_i: ksym = XK_Tab; break; case XK_j: ksym = XK_Return; break; case XK_k: /* delete right */ text[cursor] = '\0'; match(); break; case XK_n: ksym = XK_Down; break; case XK_p: ksym = XK_Up; break; case XK_u: /* delete left */ insert(NULL, 0 - cursor); break; case XK_w: /* delete word */ while(cursor > 0 && text[nextrune(-1)] == ' ') insert(NULL, nextrune(-1) - cursor); while(cursor > 0 && text[nextrune(-1)] != ' ') insert(NULL, nextrune(-1) - cursor); break; case XK_y: /* paste selection */ XConvertSelection(dc->dpy, XA_PRIMARY, utf8, utf8, win, CurrentTime); return; } } switch(ksym) { default: if(!iscntrl(*buf)) insert(buf, strlen(buf)); break; case XK_Delete: if(cursor == len) return; cursor = nextrune(+1); case XK_BackSpace: if(cursor > 0) insert(NULL, nextrune(-1) - cursor); break; case XK_End: if(cursor < len) { cursor = len; break; } while(next) { sel = curr = next; calcoffsets(); } while(sel && sel->right) sel = sel->right; break; case XK_Escape: exit(EXIT_FAILURE); case XK_Home: if(sel == matches) { cursor = 0; break; } sel = curr = matches; calcoffsets(); break; case XK_Left: if(cursor > 0 && (!sel || !sel->left || lines > 0)) { cursor = nextrune(-1); break; } else if(lines > 0) return; case XK_Up: if(sel && sel->left && (sel = sel->left)->right == curr) { curr = prev; calcoffsets(); } break; case XK_Next: if(!next) return; sel = curr = next; calcoffsets(); break; case XK_Prior: if(!prev) return; sel = curr = prev; calcoffsets(); break; case XK_Return: case XK_KP_Enter: handle_return((sel && !(ev->state & ShiftMask)) ? sel->text : text); case XK_Right: if(cursor < len) { cursor = nextrune(+1); break; } else if(lines > 0) return; case XK_Down: if(sel && sel->right && (sel = sel->right) == next) { curr = next; calcoffsets(); } break; case XK_Tab: if(!sel) return; strncpy(text, sel->text, sizeof text); cursor = strlen(text); match(); break; } drawmenu(); }