static void scrollback_push(uchar *line) { if (term.sblines == term.sblen) { // Need to make space for the new line. if (term.sblen < cfg.scrollback_lines) { // Expand buffer assert(term.sbpos == 0); int new_sblen = min(cfg.scrollback_lines, term.sblen * 3 + 1024); term.scrollback = renewn(term.scrollback, new_sblen); term.sbpos = term.sblen; term.sblen = new_sblen; } else if (term.sblines) { // Throw away the oldest line free(term.scrollback[term.sbpos]); term.sblines--; } else return; } assert(term.sblines < term.sblen); assert(term.sbpos < term.sblen); term.scrollback[term.sbpos++] = line; if (term.sbpos == term.sblen) term.sbpos = 0; term.sblines++; if (term.tempsblines < term.sblines) term.tempsblines++; }
int in_results(pos scrpos) { if (term.results.length == 0) { return 0; } pos abspos = { .x = scrpos.x, .y = scrpos.y + term.sblines }; int match = in_results_recurse(abspos, 0, term.results.length); match += in_result(abspos, term.results.results[term.results.current]); return match; } void results_add(result abspos) { assert(term.results.capacity > 0); if (term.results.length == term.results.capacity) { term.results.capacity *= 2; term.results.results = renewn(term.results.results, term.results.capacity); } term.results.results[term.results.length] = abspos; ++term.results.length; }
static DWORD WINAPI shell_exec_thread(void *data) { wchar *wpath = data; #ifdef __CYGWIN__ /* Need to sync the Windows environment */ cygwin_internal(CW_SYNC_WINENV); #endif if ((INT_PTR)ShellExecuteW(wnd, 0, wpath, 0, 0, SW_SHOWNORMAL) <= 32) { uint error = GetLastError(); if (error != ERROR_CANCELLED) { int msglen = 1024; wchar * msg = newn(wchar, msglen); FormatMessageW( FORMAT_MESSAGE_FROM_SYSTEM | 64, 0, error, 0, msg, msglen, 0 ); wchar sep[] = W("\n"); msg = renewn(msg, wcslen(msg) + wcslen(sep) + wcslen(wpath) + 1); wcscat(msg, sep); wcscat(msg, wpath); message_box_w(0, msg, null, MB_ICONERROR, null); } } free(wpath); return 0; }
void term_clear_results(void) { term.results.results = renewn(term.results.results, 16); term.results.current = 0; term.results.length = 0; term.results.capacity = 16; }
static void insert_controlset(controlbox *b, int index, controlset *s) { if (b->nctrlsets >= b->ctrlsetsize) { b->ctrlsetsize = b->nctrlsets + 32; b->ctrlsets = renewn(b->ctrlsets, b->ctrlsetsize); } if (index < b->nctrlsets) memmove(&b->ctrlsets[index + 1], &b->ctrlsets[index], (b->nctrlsets - index) * sizeof(*b->ctrlsets)); b->ctrlsets[index] = s; b->nctrlsets++; }
/* Allocate some private data in a controlbox. */ void * ctrl_alloc(controlbox * b, size_t size) { void *p; /* * This is an internal allocation routine, so it's allowed to * use malloc directly. */ p = malloc(size); if (b->nfrees >= b->freesize) { b->freesize = b->nfrees + 32; b->frees = renewn(b->frees, b->freesize); } b->frees[b->nfrees++] = p; return p; }
static control * ctrl_new(controlset *s, int type, handler_fn handler, void *context) { control *c = new(control); if (s->ncontrols >= s->ctrlsize) { s->ctrlsize = s->ncontrols + 32; s->ctrls = renewn(s->ctrls, s->ctrlsize); } s->ctrls[s->ncontrols++] = c; /* * Fill in the standard fields. */ c->type = type; c->column = COLUMN_FIELD(0, s->ncolumns); c->handler = handler; c->context = context; c->label = null; c->plat_ctrl = null; return c; }
/* * 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); }