static void check_last_key_function (FVOID_STAR f) { /* For syntax highlighting */ if (Last_Key_Function != f) touch_window (); #if 0 && ((Last_Key_Function == (FVOID_STAR) ins_char_cmd) || (Last_Key_Function == (FVOID_STAR) eol_cmd) || (Last_Key_Function == (FVOID_STAR) delete_char_cmd) || (Last_Key_Function == (FVOID_STAR) backward_delete_char_cmd) || (Last_Key_Function == (FVOID_STAR) backward_delete_char_untabify))) register_change(0); #endif }
/* Let "|" denote the window edges, * "." denote text, "*" denotes the current location * * .........|....*..........|.... * <---- col ---> * <-- wc -><-------sw------> * The contraints are: wc >= 0, col >= 0, sw > 0. * Let whs be the value of abs(Wants_HScroll). We want to wc to satisfy * wc+1 <= col <= wc + sw - 1 * ==> col-sw+1 <= wc <= col-1 * However, if wc does not satisfy this, then set wc such that: * * wc + whs <= col <= wc + sw - whs * col+whs-sw <= wc <= col-whs * Evidently, this requires: * col+whs-sw < col-whs * whs-sw < -whs * 2whs < sw ==> whs < sw/2 * * As a special case, if col < sw, then set wc=0. */ static void set_hscroll(int col) { int whs = abs(Wants_HScroll), wc = JWindow->hscroll_column - 1; int sw = Jed_Num_Screen_Cols-1; static Line *last; Line *tmp; int wc_min, wc_max; #if JED_HAS_DISPLAY_LINE_NUMBERS sw -= CBuf->line_num_display_size; #endif if (sw < 2) sw = 2; if (Wants_HScroll > 0) wc += HScroll; /* only this line scrolled */ /* take care of last effect of horizontal scroll */ if (last != NULL) { tmp = CLine; CLine = last; register_change(0); CLine = tmp; if (last != CLine) HScroll = 0; last = NULL; } col--; /* use 0 origin */ if (2*whs > sw) whs = sw/2; wc_min = col - sw + 1; if (wc_min < 0) wc_min = 0; wc_max = col - 1; if (wc < wc_min) wc = wc_min + whs; if (wc > wc_max) wc = wc_max - whs; if (col < sw) { if ((CBuf->modes & WRAP_MODE) || (col <= sw - whs)) wc = 0; } if (Wants_HScroll < 0) { /* Scroll whole window */ if (wc + 1 != JWindow->hscroll_column) { JWindow->hscroll_column = wc + 1; touch_window(); } HScroll = 0; } else { /* Scroll just this line -- do not change hscroll_column */ register_change(0); last = HScroll_Line = CLine; HScroll = wc - (JWindow->hscroll_column-1); } }
static void set_hscroll(int col) { int hdiff, whs = abs(Wants_HScroll), wc = JWindow->hscroll_column - 1; int sw = Jed_Num_Screen_Cols - 1; static Line *last; Line *tmp; #if JED_HAS_DISPLAY_LINE_NUMBERS sw -= CBuf->line_num_display_size; #endif if (sw < 1) sw = 1; /* take care of last effect of horizontal scroll */ if (last != NULL) { tmp = CLine; CLine = last; register_change(0); CLine = tmp; if (last != CLine) { #if 0 /* I need to think about this more */ if (Wants_HScroll < 0) { if (wc != 0) { JWindow->column = 1; wc = 0; touch_window (); } } #endif HScroll = 0; } last = NULL; } col--; /* use 0 origin */ hdiff = col - wc; if ((HScroll >= hdiff) || (HScroll <= hdiff - sw)) { if (hdiff >= sw) { HScroll = hdiff - sw + whs; } else if ((hdiff == 0) && (wc == 0)) HScroll = 0; else if (hdiff <= 1) { HScroll = hdiff - whs - 1; } else HScroll = 0; } if (HScroll) { if (wc + HScroll < 0) HScroll = -wc; if (Wants_HScroll < 0) { JWindow->hscroll_column += HScroll; touch_window(); HScroll = 0; } else { register_change(0); last = HScroll_Line = CLine; } } }
bool fs::file_changes::load(const char* filename) { // If the file doesn't exist or is not a regular file... struct stat sbuf; if ((stat(filename, &sbuf) < 0) || (!S_ISREG(sbuf.st_mode))) { return false; } // If the file is empty... if (sbuf.st_size == 0) { return false; } // Open file for reading. int fd; if ((fd = open(filename, O_RDONLY)) < 0) { return false; } // Map file into memory. void* buf; if ((buf = mmap(NULL, sbuf.st_size, PROT_READ, MAP_SHARED, fd, 0)) == MAP_FAILED) { close(fd); return false; } const uint8_t* begin = reinterpret_cast<const uint8_t*>(buf); const uint8_t* end = begin + sbuf.st_size; size_t nline = 0; size_t nchanges = 0; do { nline++; // Search end of line. const uint8_t* eol; if ((eol = reinterpret_cast<const uint8_t*>( memchr(begin, '\n', end - begin) )) == NULL) { munmap(buf, sbuf.st_size); close(fd); return false; } // If the line is too short... size_t linelen; if ((linelen = eol - begin) < 20) { munmap(buf, sbuf.st_size); close(fd); return false; } // First line? if (nline == 1) { if (memcmp(begin, "Number of changes: ", 19) != 0) { munmap(buf, sbuf.st_size); close(fd); return false; } // Parse number of changes. begin += 19; size_t l = 0; while (begin < eol) { if ((*begin >= '0') && (*begin <= '9')) { uint64_t tmp; if ((tmp = (nchanges * 10) + (*begin - '0')) < nchanges) { munmap(buf, sbuf.st_size); close(fd); return false; } nchanges = tmp; l++; } else if ((l > 0) && (*begin == '.') && (begin + 1 == eol)) { break; } else { munmap(buf, sbuf.st_size); close(fd); return false; } begin++; } begin = eol + 1; continue; } fs::file_change::type t; // Get type of the file change. size_t skip; if (memcmp(begin, "Modify: ", 8) == 0) { t = fs::file_change::type::kModify; skip = 8; } else if (memcmp(begin, "Add: ", 5) == 0) { t = fs::file_change::type::kAdd; skip = 5; } else if (memcmp(begin, "Remove: ", 8) == 0) { t = fs::file_change::type::kRemove; skip = 8; } else { munmap(buf, sbuf.st_size); close(fd); return false; } begin += skip; // Parse offset. if (memcmp(begin, "offset: ", 8) != 0) { munmap(buf, sbuf.st_size); close(fd); return false; } begin += 8; uint64_t off = 0; size_t l = 0; while (begin < eol) { if ((*begin >= '0') && (*begin <= '9')) { uint64_t tmp; if ((tmp = (off * 10) + (*begin - '0')) < off) { munmap(buf, sbuf.st_size); close(fd); return false; } off = tmp; l++; } else if ((l > 0) && (*begin == ',')) { break; } else { munmap(buf, sbuf.st_size); close(fd); return false; } begin++; } // Parse length. if ((begin + 10 >= eol) || (memcmp(begin, ", length: ", 10) != 0)) { munmap(buf, sbuf.st_size); close(fd); return false; } begin += 10; uint64_t len = 0; l = 0; while (begin < eol) { if ((*begin >= '0') && (*begin <= '9')) { uint64_t tmp; if ((tmp = (len * 10) + (*begin - '0')) < len) { munmap(buf, sbuf.st_size); close(fd); return false; } len = tmp; l++; } else if ((l > 0) && (*begin == '.') && (begin + 1 == eol) && (len > 0)) { break; } else { munmap(buf, sbuf.st_size); close(fd); return false; } begin++; } begin = eol + 1; if (t == file_change::type::kRemove) { if (!remove(off, NULL, len)) { munmap(buf, sbuf.st_size); close(fd); return false; } } else { if ((eol = reinterpret_cast<const uint8_t*>( memchr(begin, '\n', end - begin) )) == NULL) { munmap(buf, sbuf.st_size); close(fd); return false; } if ((linelen = eol - begin) != 2 * len) { munmap(buf, sbuf.st_size); close(fd); return false; } uint8_t* line; if ((line = reinterpret_cast<uint8_t*>(malloc(len))) == NULL) { munmap(buf, sbuf.st_size); close(fd); return false; } l = 0; for (size_t i = 0; i < linelen; i += 2) { uint8_t c; if ((begin[i] >= '0') && (begin[i] <= '9')) { c = begin[i] - '0'; } else if ((begin[i] >= 'a') && (begin[i] <= 'f')) { c = begin[i] - 'a' + 10; } else if ((begin[i] >= 'A') && (begin[i] <= 'F')) { c = begin[i] - 'A' + 10; } else { free(line); munmap(buf, sbuf.st_size); close(fd); return false; } if ((begin[i + 1] >= '0') && (begin[i + 1] <= '9')) { c = (c * 16) + (begin[i + 1] - '0'); } else if ((begin[i + 1] >= 'a') && (begin[i + 1] <= 'f')) { c = (c * 16) + (begin[i + 1] - 'a' + 10); } else if ((begin[i + 1] >= 'A') && (begin[i + 1] <= 'F')) { c = (c * 16) + (begin[i + 1] - 'A' + 10); } else { free(line); munmap(buf, sbuf.st_size); close(fd); return false; } line[l++] = c; } if (!register_change(t, off, NULL, line, len)) { free(line); munmap(buf, sbuf.st_size); close(fd); return false; } free(line); begin = eol + 1; } } while (begin < end); munmap(buf, sbuf.st_size); close(fd); return (nchanges == _M_used); }