/* * Return a `~/foo' like path if the user is under his home directory, * and restart from / if // found, * else the unmodified path. */ astr compact_path(const astr path) { astr buf = astr_new(); struct passwd *pw; size_t i; if ((pw = getpwuid(getuid())) == NULL) { /* User not found in password file. */ astr_cpy(buf, path); return buf; } /* Replace `/userhome/' (if existent) with `~/'. */ i = strlen(pw->pw_dir); if (!strncmp(pw->pw_dir, astr_cstr(path), i)) { astr_cpy_cstr(buf, "~/"); if (!strcmp(pw->pw_dir, "/")) astr_cat_cstr(buf, astr_char(path, 1)); else astr_cat_cstr(buf, astr_char(path, i + 1)); } else astr_cpy(buf, path); return buf; }
static void draw_line(size_t line, size_t startcol, Window *wp, Line *lp, size_t lineno, Region *r, int highlight) { size_t x, i; term_move(line, 0); for (x = 0, i = startcol; i < astr_len(lp->item) && x < wp->ewidth; i++) { if (highlight && in_region(lineno, i, r)) outch(*astr_char(lp->item, (ptrdiff_t)i), FONT_REVERSE, &x); else outch(*astr_char(lp->item, (ptrdiff_t)i), FONT_NORMAL, &x); } draw_end_of_line(line, wp, lineno, r, highlight, x, i); }
/* * Copy a region of text into an allocated buffer. */ char * copy_text_block (size_t startn, size_t starto, size_t size) { char *buf, *dp; size_t max_size, n, i; Line *lp; max_size = 10; dp = buf = (char *) xzalloc (max_size); lp = cur_bp->pt.p; n = cur_bp->pt.n; if (n > startn) do lp = lp->prev; while (--n > startn); else if (n < startn) do lp = lp->next; while (++n < startn); for (i = starto; dp - buf < (int) size;) { if (dp >= buf + max_size) { int save_off = dp - buf; max_size += 10; buf = (char *) xrealloc (buf, max_size); dp = buf + save_off; } if (i < astr_len (lp->text)) *dp++ = *astr_char (lp->text, (ptrdiff_t) (i++)); else { *dp++ = '\n'; lp = lp->next; i = 0; } } return buf; }
/* * Return the current directory. */ static astr get_current_dir(void) { astr buf; int p; if (cur_bp->filename != NULL) /* If the current buffer has a filename, get the current directory name from it. */ buf = astr_new_cstr(cur_bp->filename); else { /* Get the current directory name from the system. */ buf = agetcwd(); if (astr_len(buf) != 0 && *astr_char(buf, -1) != '/') astr_cat_char(buf, '/'); } p = astr_rfind_cstr(buf, "/"); astr_truncate(buf, p + 1); return buf; }
/* * This function calculates the best start column to draw if the line * needs to get truncated. * Called only for the line where is the point. */ static void calculate_start_column(Window *wp) { size_t col = 0, lastcol = 0, t = tab_width(wp->bp); int rpfact, lpfact; char *buf, *rp, *lp, *p; Point pt = window_pt(wp); rp = astr_char(pt.p->item, (ptrdiff_t)pt.o); rpfact = pt.o / (wp->ewidth / 3); for (lp = rp; lp >= astr_cstr(pt.p->item); --lp) { for (col = 0, p = lp; p < rp; ++p) if (*p == '\t') { col |= t - 1; ++col; } else if (isprint(*p)) ++col; else { col += make_char_printable(&buf, (size_t)*p); free(buf); } lpfact = (lp - astr_cstr(pt.p->item)) / (wp->ewidth / 3); if (col >= wp->ewidth - 1 || lpfact < (rpfact - 2)) { wp->start_column = lp + 1 - astr_cstr(pt.p->item); point_screen_column = lastcol; return; } lastcol = col; } wp->start_column = 0; point_screen_column = col; }
/* * This functions does some corrections and expansions to * the passed path: * - expands `~/' and `~name/' expressions; * - replaces `//' with `/' (restarting from the root directory); * - removes `..' and `.' entries. * * If something goes wrong, the string is deleted and NULL returned */ astr expand_path(astr path) { int ret = TRUE; struct passwd *pw; const char *sp = astr_cstr(path); astr epath = astr_new(); if (*sp != '/') { astr_cat_delete(epath, agetcwd()); if (astr_len(epath) == 0 || *astr_char(epath, -1) != '/') astr_cat_char(epath, '/'); } while (*sp != '\0') { if (*sp == '/') { if (*++sp == '/') { /* Got `//'. Restart from this point. */ while (*sp == '/') sp++; astr_truncate(epath, 0); } astr_cat_char(epath, '/'); } else if (*sp == '~') { if (*(sp + 1) == '/') { /* Got `~/'. Restart from this point and insert the user's home directory. */ astr_truncate(epath, 0); if ((pw = getpwuid(getuid())) == NULL) { ret = FALSE; break; } if (strcmp(pw->pw_dir, "/") != 0) astr_cat_cstr(epath, pw->pw_dir); ++sp; } else { /* Got `~something'. Restart from this point and insert that user's home directory. */ astr as = astr_new(); astr_truncate(epath, 0); ++sp; while (*sp != '\0' && *sp != '/') astr_cat_char(as, *sp++); pw = getpwnam(astr_cstr(as)); astr_delete(as); if (pw == NULL) { ret = FALSE; break; } astr_cat_cstr(epath, pw->pw_dir); } } else if (*sp == '.') { if (*(sp + 1) == '/' || *(sp + 1) == '\0') { ++sp; if (*sp == '/' && *(sp + 1) != '/') ++sp; } else if (*(sp + 1) == '.' && (*(sp + 2) == '/' || *(sp + 2) == '\0')) { if (astr_len(epath) >= 1 && *astr_char(epath, -1) == '/') astr_truncate(epath, -1); while (*astr_char(epath, -1) != '/' && astr_len(epath) >= 1) astr_truncate(epath, -1); sp += 2; if (*sp == '/' && *(sp + 1) != '/') ++sp; } else goto got_component; } else { const char *p; got_component: p = sp; while (*p != '\0' && *p != '/') p++; if (*p == '\0') { /* Final filename */ astr_cat_cstr(epath, sp); break; } else { /* Non-final directory */ while (*sp != '/') astr_cat_char(epath, *sp++); } } } astr_cpy(path, epath); astr_delete(epath); if (!ret) { astr_delete(path); return NULL; } return path; }