/* * 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_status_line(size_t line, Window *wp) { size_t i; char *buf, *eol_type; Point pt = window_pt(wp); astr as, bs; term_attrset(1, FONT_REVERSE); term_move(line, 0); for (i = 0; i < wp->ewidth; ++i) term_addch('-'); if (cur_bp->eol == coding_eol_cr) eol_type = "(Mac)"; else if (cur_bp->eol == coding_eol_crlf) eol_type = "(DOS)"; else eol_type = ":"; term_move(line, 0); bs = astr_afmt(astr_new(), "(%d,%d)", pt.n+1, get_goalc_wp(wp)); as = astr_afmt(astr_new(), "--%s%2s %-15s %s %-9s (Text", eol_type, make_mode_line_flags(wp), wp->bp->name, make_screen_pos(wp, &buf), astr_cstr(bs)); free(buf); astr_delete(bs); if (wp->bp->flags & BFLAG_AUTOFILL) astr_cat_cstr(as, " Fill"); if (wp->bp->flags & BFLAG_OVERWRITE) astr_cat_cstr(as, " Ovwrt"); if (thisflag & FLAG_DEFINING_MACRO) astr_cat_cstr(as, " Def"); if (wp->bp->flags & BFLAG_ISEARCH) astr_cat_cstr(as, " Isearch"); astr_cat_char(as, ')'); term_addnstr(astr_cstr(as), min(term_width(), astr_len(as))); astr_delete(as); term_attrset(1, FONT_NORMAL); }
static void draw_status_line (size_t line, Window wp) { term_attrset (FONT_REVERSE); term_move (line, 0); for (size_t i = 0; i < get_window_ewidth (wp); ++i) term_addstr ("-"); const char *eol_type; if (get_buffer_eol (cur_bp) == coding_eol_cr) eol_type = "(Mac)"; else if (get_buffer_eol (cur_bp) == coding_eol_crlf) eol_type = "(DOS)"; else eol_type = ":"; term_move (line, 0); size_t n = offset_to_line (get_window_bp (wp), window_o (wp)); astr as = astr_fmt ("--%s%2s %-15s %s %-9s (Fundamental", eol_type, make_mode_line_flags (wp), get_buffer_name (get_window_bp (wp)), make_screen_pos (wp), astr_cstr (astr_fmt ("(%zu,%zu)", n + 1, get_goalc_bp (get_window_bp (wp), window_o (wp))))); if (get_buffer_autofill (get_window_bp (wp))) astr_cat_cstr (as, " Fill"); if (thisflag & FLAG_DEFINING_MACRO) astr_cat_cstr (as, " Def"); if (get_buffer_isearch (get_window_bp (wp))) astr_cat_cstr (as, " Isearch"); astr_cat_char (as, ')'); term_addstr (astr_cstr (as)); term_attrset (FONT_NORMAL); }
/* * Return a string of maximum length `maxlen' beginning with a `...' * sequence if a cut is need. */ astr shorten_string (char *s, int maxlen) { astr as = astr_new (); int len = strlen (s); if (len <= maxlen) astr_cpy_cstr (as, s); else { astr_cpy_cstr (as, "..."); astr_cat_cstr (as, s + len - maxlen + 3); } return as; }
/* * Return a `~/foo' like path if the user is under his home directory, * else the unmodified path. */ astr compact_path (astr path) { struct passwd *pw = getpwuid (getuid ()); if (pw != NULL) { /* Replace `/userhome/' (if found) with `~/'. */ size_t homelen = strlen (pw->pw_dir); if (homelen > 0 && pw->pw_dir[homelen - 1] == '/') homelen--; if (astr_len (path) > homelen && !strncmp (pw->pw_dir, astr_cstr (path), homelen) && astr_get (path, homelen) == '/') astr_cpy (path, astr_cat_cstr (astr_new_cstr ("~/"), astr_cstr (path) + homelen + 1)); } return path; }
/* * 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. * * The return value indicates success or failure. */ bool expand_path (astr path) { int ok = true; const char *sp = astr_cstr (path); astr epath = astr_new (); if (*sp != '/' && *sp != '~') { astr_cat (epath, agetcwd ()); if (astr_len (epath) == 0 || astr_get (epath, astr_len (epath) - 1) != '/') astr_cat_char (epath, '/'); } for (const char *p = sp; *p != '\0';) { if (*p == '/') { if (*++p == '/') { /* Got `//'. Restart from this point. */ while (*p == '/') p++; astr_truncate (epath, 0); } if (astr_len (epath) == 0 || astr_get (epath, astr_len (epath) - 1) != '/') astr_cat_char (epath, '/'); } else if (*p == '~' && (p == sp || p[-1] == '/')) { /* Got `/~' or leading `~'. Restart from this point. */ struct passwd *pw; astr_truncate (epath, 0); ++p; if (*p == '/') { /* Got `~/'. Insert the user's home directory. */ pw = getpwuid (getuid ()); if (pw == NULL) { ok = false; break; } if (!STREQ (pw->pw_dir, "/")) astr_cat_cstr (epath, pw->pw_dir); } else { /* Got `~something'. Insert that user's home directory. */ astr as = astr_new (); while (*p != '\0' && *p != '/') astr_cat_char (as, *p++); pw = getpwnam (astr_cstr (as)); if (pw == NULL) { ok = false; break; } astr_cat_cstr (epath, pw->pw_dir); } } else if (*p == '.' && (p[1] == '/' || p[1] == '\0')) { /* Got `.'. */ ++p; } else if (*p == '.' && p[1] == '.' && (p[2] == '/' || p[2] == '\0')) { /* Got `..'. */ if (astr_len (epath) >= 1 && astr_get (epath, astr_len (epath) - 1) == '/') astr_truncate (epath, astr_len (epath) - 1); while (astr_get (epath, astr_len (epath) - 1) != '/' && astr_len (epath) >= 1) astr_truncate (epath, astr_len (epath) - 1); p += 2; } if (*p != '~') while (*p != '\0' && *p != '/') astr_cat_char (epath, *p++); } astr_cpy (path, epath); return ok; }
/* * Convert a key chord into its ASCII representation */ astr chordtostr(size_t key) { astr as = astr_new(); if (key & KBD_CTRL) astr_cat_cstr(as, "C-"); if (key & KBD_META) astr_cat_cstr(as, "M-"); key &= ~(KBD_CTRL | KBD_META); switch (key) { case KBD_PGUP: astr_cat_cstr(as, "<prior>"); break; case KBD_PGDN: astr_cat_cstr(as, "<next>"); break; case KBD_HOME: astr_cat_cstr(as, "<home>"); break; case KBD_END: astr_cat_cstr(as, "<end>"); break; case KBD_DEL: astr_cat_cstr(as, "<delete>"); break; case KBD_BS: astr_cat_cstr(as, "<backspace>"); break; case KBD_INS: astr_cat_cstr(as, "<insert>"); break; case KBD_LEFT: astr_cat_cstr(as, "<left>"); break; case KBD_RIGHT: astr_cat_cstr(as, "<right>"); break; case KBD_UP: astr_cat_cstr(as, "<up>"); break; case KBD_DOWN: astr_cat_cstr(as, "<down>"); break; case KBD_RET: astr_cat_cstr(as, "<RET>"); break; case KBD_TAB: astr_cat_cstr(as, "<TAB>"); break; case KBD_F1: astr_cat_cstr(as, "<f1>"); break; case KBD_F2: astr_cat_cstr(as, "<f2>"); break; case KBD_F3: astr_cat_cstr(as, "<f3>"); break; case KBD_F4: astr_cat_cstr(as, "<f4>"); break; case KBD_F5: astr_cat_cstr(as, "<f5>"); break; case KBD_F6: astr_cat_cstr(as, "<f6>"); break; case KBD_F7: astr_cat_cstr(as, "<f7>"); break; case KBD_F8: astr_cat_cstr(as, "<f8>"); break; case KBD_F9: astr_cat_cstr(as, "<f9>"); break; case KBD_F10: astr_cat_cstr(as, "<f10>"); break; case KBD_F11: astr_cat_cstr(as, "<f11>"); break; case KBD_F12: astr_cat_cstr(as, "<f12>"); break; case ' ': astr_cat_cstr(as, "SPC"); break; default: if (isgraph(key)) astr_cat_char(as, (int)(key & 0xff)); else astr_afmt(as, "<%x>", key); } return as; }
/* * 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; }