termline* newline(const char* chars) { static termline* line = 0; if (line) freeline(line); line = alloc_newline(chars); return line; }
const char* syntax(const char *chars) { size_t sz = strlen(chars); termline* line = alloc_newline(chars); int jed_prefix_length = t24_is_jed_line(line->chars, sz); t24_basic_highlight(line->chars, sz, jed_prefix_length); const char* result = decode_colors(line->chars, sz); freeline(line); return result; }
/* * Set up the terminal for a given size. */ void term_resize(int newrows, int newcols) { bool on_alt_screen = term.on_alt_screen; term_switch_screen(0, false); term.selected = false; term.marg_top = 0; term.marg_bot = newrows - 1; /* * Resize the screen and scrollback. We only need to shift * lines around within our data structures, because lineptr() * will take care of resizing each individual line if * necessary. So: * * - If the new screen is longer, we shunt lines in from temporary * scrollback if possible, otherwise we add new blank lines at * the bottom. * * - If the new screen is shorter, we remove any blank lines at * the bottom if possible, otherwise shunt lines above the cursor * to scrollback if possible, otherwise delete lines below the * cursor. * * - Then, if the new scrollback length is less than the * amount of scrollback we actually have, we must throw some * away. */ termlines *lines = term.lines; term_cursor *curs = &term.curs; term_cursor *saved_curs = &term.saved_cursors[term.on_alt_screen]; // Shrink the screen if newrows < rows if (newrows < term.rows) { int removed = term.rows - newrows; int destroy = min(removed, term.rows - (curs->y + 1)); int store = removed - destroy; // Push removed lines into scrollback for (int i = 0; i < store; i++) { termline *line = lines[i]; scrollback_push(compressline(line)); freeline(line); } // Move up remaining lines memmove(lines, lines + store, newrows * sizeof(termline *)); // Destroy removed lines below the cursor for (int i = term.rows - destroy; i < term.rows; i++) freeline(lines[i]); // Adjust cursor position curs->y = max(0, curs->y - store); saved_curs->y = max(0, saved_curs->y - store); } term.lines = lines = renewn(lines, newrows); // Expand the screen if newrows > rows if (newrows > term.rows) { int added = newrows - term.rows; int restore = min(added, term.tempsblines); int create = added - restore; // Fill bottom of screen with blank lines for (int i = newrows - create; i < newrows; i++) lines[i] = newline(newcols, false); // Move existing lines down memmove(lines + restore, lines, term.rows * sizeof(termline *)); // Restore lines from scrollback for (int i = restore; i--;) { uchar *cline = scrollback_pop(); termline *line = decompressline(cline, null); free(cline); line->temporary = false; /* reconstituted line is now real */ lines[i] = line; } // Adjust cursor position curs->y += restore; saved_curs->y += restore; } // Resize lines for (int i = 0; i < newrows; i++) resizeline(lines[i], newcols); // Make a new displayed text buffer. if (term.displines) { for (int i = 0; i < term.rows; i++) freeline(term.displines[i]); } term.displines = renewn(term.displines, newrows); for (int i = 0; i < newrows; i++) { termline *line = newline(newcols, false); term.displines[i] = line; for (int j = 0; j < newcols; j++) line->chars[j].attr = ATTR_INVALID; } // Make a new alternate screen. lines = term.other_lines; if (lines) { for (int i = 0; i < term.rows; i++) freeline(lines[i]); } term.other_lines = lines = renewn(lines, newrows); for (int i = 0; i < newrows; i++) lines[i] = newline(newcols, true); // Reset tab stops term.tabs = renewn(term.tabs, newcols); for (int i = (term.cols > 0 ? term.cols : 0); i < newcols; i++) term.tabs[i] = (i % 8 == 0); // Check that the cursor positions are still valid. assert(0 <= curs->y && curs->y < newrows); assert(0 <= saved_curs->y && saved_curs->y < newrows); curs->x = min(curs->x, newcols - 1); curs->wrapnext = false; term.disptop = 0; term.rows = newrows; term.cols = newcols; term_switch_screen(on_alt_screen, false); }
static void join ( FILE *fp1, FILE *fp2 ) { struct seq seq1, seq2; struct line line; int diff, i, j, eof1, eof2; /* Read the first line of each file. */ initseq (&seq1); getseq (fp1, &seq1); initseq (&seq2); getseq (fp2, &seq2); while (seq1.count && seq2.count) { diff = keycmp (&seq1.lines[0], &seq2.lines[0]); if (diff < 0) { if (print_unpairables_1) prline (&seq1.lines[0]); freeline (&seq1.lines[0]); seq1.count = 0; getseq (fp1, &seq1); continue; } if (diff > 0) { if (print_unpairables_2) prline (&seq2.lines[0]); freeline (&seq2.lines[0]); seq2.count = 0; getseq (fp2, &seq2); continue; } /* Keep reading lines from file1 as long as they continue to match the current line from file2. */ eof1 = 0; do if (!getseq (fp1, &seq1)) { eof1 = 1; ++seq1.count; break; } while (!keycmp (&seq1.lines[seq1.count - 1], &seq2.lines[0])); /* Keep reading lines from file2 as long as they continue to match the current line from file1. */ eof2 = 0; do if (!getseq (fp2, &seq2)) { eof2 = 1; ++seq2.count; break; } while (!keycmp (&seq1.lines[0], &seq2.lines[seq2.count - 1])); if (print_pairables) { for (i = 0; i < seq1.count - 1; ++i) for (j = 0; j < seq2.count - 1; ++j) prjoin (&seq1.lines[i], &seq2.lines[j]); } for (i = 0; i < seq1.count - 1; ++i) freeline (&seq1.lines[i]); if (!eof1) { seq1.lines[0] = seq1.lines[seq1.count - 1]; seq1.count = 1; } else seq1.count = 0; for (i = 0; i < seq2.count - 1; ++i) freeline (&seq2.lines[i]); if (!eof2) { seq2.lines[0] = seq2.lines[seq2.count - 1]; seq2.count = 1; } else seq2.count = 0; } if (print_unpairables_1 && seq1.count) { prline (&seq1.lines[0]); freeline (&seq1.lines[0]); while (getline (fp1, &line)) { prline (&line); freeline (&line); } } if (print_unpairables_2 && seq2.count) { prline (&seq2.lines[0]); freeline (&seq2.lines[0]); while (getline (fp2, &line)) { prline (&line); freeline (&line); } } delseq (&seq1); delseq (&seq2); }
/* * Process the library command. * This command (sadly) requires a rather * detailed knowledge of the file system of * the operating system. */ void library(void) { char *p; int c; int d; char *sctp; struct line *lp1; struct line *lp2; FILE *fp; c = getnb(); if (c!='c' && c!='s' && c!='l' && c!='d') diag("Bad library command"); while (isalpha(*ctp)) ++ctp; while ((d = *ctp)==' ' || d=='\t') ++ctp; if (c!='l' && d==0) diag("Missing file name"); p = ctp; while (*ctp != 0) ++ctp; switch (c) { case 'c': if ((fp=fopen(p, "r")) == NULL) diag("Cannot open"); lp1 = line; while (lp1 != NULL) { lp2 = lp1->l_fp; freeline(lp1); lp1 = lp2; } line = NULL; sctp = ctp; while (focal_getline(abuf, fp) != 0) { ctp = abuf; if ((c=getnb()) != 0) { if (isdigit(c) == 0) diag("Direct line in call"); inject(c); } } fclose(fp); ctp = sctp; break; case 'd': if (remove(p) < 0) diag("Cannot delete"); break; case 'l': #ifndef DIR_SUPPORT diag("Library list not implemented"); #else { #ifdef DOS int attr = _A_RDONLY | _A_ARCH; int rc; static struct find_t de; static char fname[FILENAME_MAX]; char *s; if (d == 0) strcpy(fname, "*.*"); else { strcpy(fname, p); s = fname + strlen(fname) - 1; if (*s == '\\') strcat(fname, "*.*"); else if (*s == '.') strcat(fname, "\\*.*"); } rc = _dos_findfirst(fname, attr, &de); while (!rc) { if ((de.attrib & _A_SUBDIR) == 0 && strcmp(de.name, ".") != 0 && strcmp(de.name, "..") != 0) printf("%-13s\n", de.name); rc = _dos_findnext(&de); } #else #ifdef DIRENT struct dirent *de; DIR *dp; if (d == 0) p = "."; if ((dp = opendir(p)) == NULL) { perror("focal"); diag("Bad directory"); } while ((de = readdir(dp)) != NULL) { if (de->d_ino == 0 || strcmp(de->d_name, ".") == 0 || strcmp(de->d_name, "..") == 0) continue; printf("%s\n", de->d_name); } closedir(dp); #else int fd = 0; if (d == 0) p = "."; if (stat(p, &sb) < 0 || (sb.st_mode&S_IFMT) != S_IFDIR || (fd = open(p, 0)) < 0) diag("Bad directory"); while (read(fd, &db, sizeof(db)) == sizeof(db)) { if (db.d_ino == 0 || strncmp(db.d_name, ".", DIRSIZ) == 0 || strncmp(db.d_name, "..", DIRSIZ) == 0) continue; printf("%.*s\n", DIRSIZ, db.d_name); } close(fd); #endif #endif } #endif break; case 's': if ((fp=fopen(p, "w")) == NULL) diag("Cannot create"); save(NULL, fp); fclose(fp); break; } }