📄 tio.c
字号:
redraw(cursor, !(when & WHEN_VICMD)); pfetch(markline(cursor)); sprintf(buf, "%7ld,%-4d", markline(cursor), 1 + idx2col(cursor, ptext, when & (WHEN_VIINP|WHEN_VIREP))); move(LINES - 1, COLS - 22); addstr(buf); }#endif /* redraw, so the cursor is in the right place */ if (when & WHENMASK) { redraw(cursor, !(when & (WHENMASK & ~(WHEN_VIREP|WHEN_VIINP)))); } /* Okay, now we can finally read the rawin keystrokes */ refresh(); nkeys = ttyread(keybuf + cend, sizeof keybuf - cend, timeout); /* if nkeys == 0 then we've reached EOF of an ex script. */ if (nkeys == 0 && timeout == 0) { tmpabort(TRUE); move(LINES - 1, 0); clrtoeol(); refresh(); endwin(); exit(1); } cend += nkeys; user += nkeys; return nkeys;}/* This function counts the number of maps that could match the characters * between &keybuf[next] and &keybuf[cend], including incomplete matches. * The longest comlete match is remembered via the "match" variable. */static int countmatch(when) int when; /* mixture of WHEN_XXX flags */{ MAP *map; int count; /* clear the "match" variable */ match = (MAP *)0; /* check every map */ for (count = 0, map = maps; map; map = map->next) { /* can't match if wrong mode */ if ((map->flags & when) == 0) { continue; } /* would this be a complete match? */ if (map->len <= cend - next) { /* Yes, it would be. Now does it really match? */ if (!strncmp(map->rawin, &keybuf[next], map->len)) { count++; /* if this is the longest complete match, * then remember it. */ if (!match || match->len < map->len) { match = map; } } } else { /* No, it wouldn't. But check for partial match */ if (!strncmp(map->rawin, &keybuf[next], cend - next)) { count++; } } } return count;}#ifndef NO_ABBR/* This function checks to see whether a word is an abbreviation. If it is, * then an appropriate number of backspoace characters is inserted into the * type-ahead buffer, followed by the expanded form of the abbreviation. */static void expandabbr(word, wlen) char *word; int wlen;{ MAP *abbr; /* if the next character wouldn't end the word, then don't expand */ if (isalnum(keybuf[next]) || keybuf[next] == ctrl('V')) { return; } /* find the abbreviation, if any */ for (abbr = abbrs; abbr && (abbr->len != wlen || strncmp(abbr->rawin, word, wlen)); abbr = abbr->next) { } /* If an abbreviation was found, then expand it by inserting the long * version into the type-ahead buffer, and then inserting (in front of * the long version) enough backspaces to erase to the short version. */ if (abbr) { execmap(0, abbr->cooked, FALSE); while (wlen > 15) { execmap(0, "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b", FALSE); wlen -= 15; } if (wlen > 0) { execmap(0, "\b\b\b\b\b\b\b\b\b\b\b\b\b\b\b" + 15 - wlen, FALSE); } }}#endif/* This function calls getabkey() without attempting to expand abbreviations */int getkey(when) int when; /* mixture of WHEN_XXX flags */{ return getabkey(when, "", 0);}/* This is it. This function returns keystrokes one-at-a-time, after mapping * and abbreviations have been taken into account. */int getabkey(when, word, wlen) int when; /* mixture of WHEN_XXX flags */ char *word; /* a word that may need to be expanded as an abbr */ int wlen; /* length of "word" -- since "word" might not have \0 */{ int matches; /* if this key is needed for delay between multiple error messages, * then reset the manymsgs flag and abort any mapped key sequence. */ if (showmsg()) { if (when == WHEN_MSG) {#ifndef CRUNCH if (!*o_more) { refresh(); return ' '; }#endif qaddstr("[More...]"); refresh(); execmap(user, "", FALSE); } }#ifdef DEBUG /* periodically check for screwed up internal tables */ watch();#endif /* if buffer empty, read some characters without timeout */ if (next >= cend) { next = user = cend = 0; fillkeybuf(when, 0); } /* try to map the key, unless already mapped and not ":set noremap" */ if (next >= user || *o_remap) { do { do { matches = countmatch(when); } while (matches > 1 && fillkeybuf(when, *o_keytime) > 0); if (matches == 1) { execmap(match->len, match->cooked, (match->flags & WHEN_INMV) != 0 && (when & (WHEN_VIINP|WHEN_VIREP)) != 0); } } while (*o_remap && matches == 1); }#ifndef NO_ABBR /* try to expand an abbreviation, except in visual command mode */ if (wlen > 0 && (mode & (WHEN_EX|WHEN_VIINP|WHEN_VIREP)) != 0) { expandabbr(word, wlen); }#endif /* ERASEKEY should always be mapped to '\b'. */ if (keybuf[next] == ERASEKEY) { keybuf[next] = '\b'; } /* return the next key */ return keybuf[next++];}/* This function maps or unmaps a key */void mapkey(rawin, cooked, when, name) char *rawin; /* the input key sequence, before mapping */ char *cooked;/* after mapping -- or NULL to remove map */ short when; /* bitmap of when mapping should happen */ char *name; /* name of the key, NULL for no name, "abbr" for abbr */{ MAP **head; /* head of list of maps or abbreviations */ MAP *scan; /* used for scanning through the list */ MAP *prev; /* used during deletions */ /* Is this a map or an abbreviation? Choose the right list. */#ifndef NO_ABBR head = ((!name || strcmp(name, "abbr")) ? &maps : &abbrs);#else head = &maps;#endif /* try to find the map in the list */ for (scan = *head, prev = (MAP *)0; scan && (strcmp(rawin, scan->rawin) || !(scan->flags & when & (WHEN_EX|WHEN_VICMD|WHEN_VIINP|WHEN_VIREP))); prev = scan, scan = scan->next) { } /* trying to map? (not unmap) */ if (cooked && *cooked) { /* if map starts with "visual ", then mark it as a visual map */ if (head == &maps && !strncmp(cooked, "visual ", 7)) { cooked += 7; when |= WHEN_INMV; } /* "visual" maps always work in input mode */ if (when & WHEN_INMV) { when |= WHEN_VIINP|WHEN_VIREP|WHEN_POPUP; } /* if not already in the list, then allocate a new structure */ if (!scan) { scan = (MAP *)malloc(sizeof(MAP)); scan->len = strlen(rawin); scan->rawin = malloc(scan->len + 1); strcpy(scan->rawin, rawin); scan->flags = when; scan->label = name; if (*head) { prev->next = scan; } else { *head = scan; } scan->next = (MAP *)0; } else /* recycle old structure */ { free(scan->cooked); } scan->cooked = malloc(strlen(cooked) + 1); strcpy(scan->cooked, cooked); } else /* unmapping */ { /* if nothing to unmap, then exit silently */ if (!scan) { return; } /* unlink the structure from the list */ if (prev) { prev->next = scan->next; } else { *head = scan->next; } /* free it, and the strings that it refers to */ free(scan->rawin); free(scan->cooked); free(scan); }}/* This function returns a printable version of a string. It uses tmpblk.c */char *printable(str) char *str; /* the string to convert */{ char *build; /* used for building the string */ for (build = tmpblk.c; *str; str++) {#if AMIGA if (*str == '\233') { *build++ = '<'; *build++ = 'C'; *build++ = 'S'; *build++ = 'I'; *build++ = '>'; } else #endif if (UCHAR(*str) < ' ' || *str == '\177') { *build++ = '^'; *build++ = *str ^ '@'; } else { *build++ = *str; } } *build = '\0'; return tmpblk.c;}/* This function displays the contents of either the map table or the * abbreviation table. User commands call this function as follows: * :map dumpkey(WHEN_VICMD, FALSE); * :map! dumpkey(WHEN_VIREP|WHEN_VIINP, FALSE); * :abbr dumpkey(WHEN_VIINP|WHEN_VIREP, TRUE); * :abbr! dumpkey(WHEN_EX|WHEN_VIINP|WHEN_VIREP, TRUE); */void dumpkey(when, abbr) int when; /* WHEN_XXXX of mappings to be dumped */ int abbr; /* boolean: dump abbreviations instead of maps? */{ MAP *scan; char *str; int len;#ifndef NO_ABBR for (scan = (abbr ? abbrs : maps); scan; scan = scan->next)#else for (scan = maps; scan; scan = scan->next)#endif { /* skip entries that don't match "when" */ if ((scan->flags & when) == 0) { continue; } /* dump the key label, if any */ if (!abbr) { len = 8; if (scan->label) { qaddstr(scan->label); len -= strlen(scan->label); } do { qaddch(' '); } while (len-- > 0); } /* dump the rawin version */ str = printable(scan->rawin); qaddstr(str); len = strlen(str); do { qaddch(' '); } while (len++ < 8); /* dump the mapped version */#ifndef NO_EXTENSIONS if ((scan->flags & WHEN_INMV) && (when & (WHEN_VIINP|WHEN_VIREP))) { qaddstr("visual "); }#endif str = printable(scan->cooked); qaddstr(str); addch('\n'); exrefresh(); }}#ifndef NO_MKEXRCstatic safequote(str) char *str;{ char *build; build = tmpblk.c + strlen(tmpblk.c); while (*str) { if (*str <= ' ' && *str >= 1 || *str == '|') { *build++ = ctrl('V'); } *build++ = *str++; } *build = '\0';}/* This function saves the contents of either the map table or the * abbreviation table into a file. Both the "bang" and "no bang" versions * are saved. * :map dumpkey(WHEN_VICMD, FALSE); * :map! dumpkey(WHEN_VIREP|WHEN_VIINP, FALSE); * :abbr dumpkey(WHEN_VIINP|WHEN_VIREP, TRUE); * :abbr! dumpkey(WHEN_EX|WHEN_VIINP|WHEN_VIREP, TRUE); */savemaps(fd, abbr) int fd; /* file descriptor of an open file to write to */ int abbr; /* boolean: do abbr table? (else do map table) */{ MAP *scan; char *str; int bang; int when; int len;# ifndef NO_ABBR for (scan = (abbr ? abbrs : maps); scan; scan = scan->next)# else for (scan = maps; scan; scan = scan->next)# endif { /* skip maps that have labels, except for function keys */ if (scan->label && *scan->label != '#') { continue; } for (bang = 0; bang < 2; bang++) { /* decide which "when" flags we want */# ifndef NO_ABBR if (abbr) when = (bang ? WHEN_EX|WHEN_VIINP|WHEN_VIREP : WHEN_VIINP|WHEN_VIREP); else# endif when = (bang ? WHEN_VIREP|WHEN_VIINP : WHEN_VICMD); /* skip entries that don't match "when" */ if ((scan->flags & when) == 0) { continue; } /* write a "map" or "abbr" command name */# ifndef NO_ABBR if (abbr) strcpy(tmpblk.c, "abbr"); else# endif strcpy(tmpblk.c, "map"); /* maybe write a bang. Definitely write a space */ if (bang) strcat(tmpblk.c, "! "); else strcat(tmpblk.c, " "); /* write the rawin version */# ifndef NO_FKEY if (scan->label) strcat(tmpblk.c, scan->label); else# endif safequote(scan->rawin); strcat(tmpblk.c, " "); /* dump the mapped version */# ifndef NO_EXTENSIONS if ((scan->flags & WHEN_INMV) && (when & (WHEN_VIINP|WHEN_VIREP))) { strcat(tmpblk.c, "visual "); }# endif safequote(scan->cooked); strcat(tmpblk.c, "\n"); twrite(fd, tmpblk.c, strlen(tmpblk.c)); } }}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -