#include "tcb.h" #include #include #include #include #include #include static struct { struct { u_int winch : 1; u_int term : 1; u_int ctrl : 1; } f; } Key; typedef int (*GETCH)(int); static int is_esc(char *ks[], char esc[]) { int i; for (i = 0; ks[i] && (ks[i][0] != esc[0] || ks[i][2] != esc[2]); i++) ; return (ks[i]) ? i : 0; } static void set_name(STR *sp0, char name[]) { STR *sp; int i, c, len; if (!sp0) return; for (len = strlen(name), i = 0; ; len++) { if (!(c = sp0->name[len])) break; for (sp = sp0->next; sp && sp->name[len] == c; sp = sp->next) ; if (sp) break; } if ((len -= (i = strlen(name)))) { memcpy(&name[i], &sp0->name[i], len); name[i + len] = '\0'; } } static int key_getch(int f_key, u_char cva[]) { static u_char *cvp, cvp0[N_line]; int i; if (f_key == 2 || f_key == 3) { if ((i = strlen(cva)) >= N_line) { memcpy(cvp0, cva, N_line - 1); cvp0[N_line-1] = '\0'; i = N_line - 1; } else strcpy(cvp0, cva); cvp = cvp0; if (f_key == 2) vt_mode(-'d'); return 0; } else if (!(i = *cvp++)) return -1; else if (load_intr() == S_err0) while ((i = *cvp)) cvp++; if (!*cvp) vt_mode('d'); return i; } static int set_km(int m, int **p_kmp, int f_M) { /* keyboard macro */ static int f_me, n_km, a_km[N_macro]; switch(f_M) { case M_ms: f_me = n_km = 0; break; case 0: a_km[n_km++] = m; a_km[n_km] = 0; if (n_km < N_macro-1) break; case M_me: f_me = 1; n_km = -1; break; case M_mm: if (!f_me) { a_km[n_km++] = f_M; /* endless loop */ a_km[n_km] = 0; f_me = 1; } *p_kmp = a_km; break; } return n_km + 1; } static void key_ttou(int dummy) { signal(SIGTTOU, key_ttou); if (s_S(S_error)) kill(getpid(), SIGTSTP); else killpg(getpgrp(), SIGTSTP); } static void key_cont(int dummy) { signal(SIGCONT, key_cont); if (s_S(S_pid)) print_pid(getpid()); vt_init(-9); /* check SIGTTOU */ } void key_winch(int spid0)/*tcb*/ { static int spid; if (spid0 < 0) { spid = -spid0; return; } signal(SIGWINCH, key_winch); vt_winsize(); if (spid && !kill(spid, 0)) vt_mode('v'); Key.f.winch = 1; } static void key_segv(int dummy) { save_stderr("%s: %s.\n", s_S(S_tcb), s_S(S_err8)); exit_tcb(0); print_stderr(NULL); exit(1); } void key_term(int dummy)/*tcb*/ { get_hup(1); unlink_file(); Key.f.term = 1; } static void key_pipe(int dummy) { signal(SIGPIPE, key_pipe); } static void stand_str(RV *rvp0, int f_M) { static RV *rvp; static PP p; int i, f_enter, n_attr, f_stand, f_grep, f_file; static ATTR pp_attr[N_attr]; /* display control-code (^?) */ if (!vt_mode('D') || rvp0 == EOB || f_M == M_shell || f_M == T_arc3 || f_M == T_input) return; if (is_comm(f_M, 0)) f_enter = f_M; else if ((i = is_comm(f_M, 1))) f_enter = i; else f_enter = 0; f_file = is_file(f_M); if (rvp0) { rvp = rvp0; vt_stand(); f_stand = 1; } else { vt_endstand(); f_stand = -1; } vt_move(rvp->row, rvp->col); p.attr = NULL; f_grep = f_M == M_egrep || f_M == M_cut || f_M == T_hfgrep || f_M == T_hegrep; n_attr = set_attr(pp_attr, rvp->str, f_stand, f_grep, f_file); p.cs = rvp->str; p.f.len = strlen(p.cs); i = p.f.len + rvp->col; if (f_file) ; /* M_du || T_du */ else if (i > vt_col(0) - 1) p.f.len--; p.split = (f_M == T_grep && f_stand > 0) ? -f_M : 0; if (n_attr) { pp_attr[n_attr++].n = -1; p.attr = pp_attr; } put_str(&p, 0); vt_endstand(); } static int kton(int k, int key_c[]) { int i, i_tab; for (i_tab = 0; key_c[i_tab]; i_tab++) ; for (i = 0; i < i_tab && key_c[i] != k; i++) ; return (i < i_tab) ? i : 0; } static int input_key(int f_M, u_char mess[], u_char *cs, int col0, char *cname, LIST **listp, STR *cmd, u_char iname[], char dir[], char old[]) { int i, j, k, m, len, row, col, cole, shift, f_list, ti; struct stat st; u_char *cp, buff[N_line], str[N_line]; static int ilen; static u_char buffb[N_line]; row = vt_row(0) - 1; k = vt_col(0) / 4; switch(f_M) { case M_man2: case M_cut2: case M_locate: case T_locate: case M_fgrep: k = vt_col(0) / 2; case M_prog2: case T_rm: case T_cp: case T_mv: case T_arc: case T_arc3: case M_lfile2: case M_ldir2: *buff = '\0'; break; case M_exit: strcpy(buff, "y"); break; case M_man: k = vt_col(0) / 2; default: if (!cs || cs == EO9) *buff = '\0'; else strcpy(buff, cs); if (cname) sprintf(strchr(buff, '\0'), " %s", cname); break; } if ((i = *iname)) { if (i == K_a0 && !*buffb) { m = 0; *iname = '\0'; } else { strcpy(buff, buffb); if (i == K_a0) buff[ilen] = *buffb = '\0'; else strcpy(&buff[ilen], iname); *iname = '\0'; col = cole = strlen(buff) + col0; m = -K_e; } } else m = 0; col = cole = col0 + strlen(buff); len = vt_col(0) - col0 - k - 1; col = (col > col0 + len) ? col0 + len : col; shift = f_list = 0; key_eeol(row, col0, len); vt_move(row, col0); if ((i = *buff)) if (i == K_a0) *buff = '\0'; else if ((i = cole - col0 - len) > 0) { shift = i; print_buff(&buff[shift]); } else print_buff(buff); vt_flush(); for (m = 0; ; m = (m > 0) ? 0 : m , f_list = (f_list != 1) ? 0 : f_list) { m = edit_line(m, T_input, buff, len, row, col0, &col, &cole, &shift); switch(m) { case 0: case N_char: break; case M_hist: switch(f_M) { case T_hist: case T_hfile: case T_hdir: case T_hman: case T_hlocate: case T_hfgrep: case T_hegrep: echo_mess(S_errv); continue; } case M_cmd: if (f_M == T_cmd) continue; case M_list: if (m == M_cmd || m == M_hist) { if (f_M != M_fgrep && f_M != M_egrep) ilen = 0; } else if (f_M == T_list || f_M == M_locate || f_M == T_locate || f_M == M_fgrep || f_M == M_egrep) continue; if (m == M_list) { *listp = free_list(*listp); if ((ti = col + shift - col0)) buff[ti] = '\0'; do { if (strchr(buff, '\0')[-1] == '~') strcpy(&strchr(buff, '\0')[-1], s_S(S_home)); else if (strstr(buff, "~/")) { strcpy(str, &strstr(buff, "~/")[2]); sprintf(buff, "%s%s", s_S(S_home), str); } } while (0); strcpy(str, buff); if (*str != '/') strcpy(str, dir); else if (!stat(str, &st) && S_ISDIR(st.st_mode) && strchr(str, '\0')[-1] != '/') { strcat(str, "/"); strcat(buff, "/"); } else get_dir(str); i = make_list(str, buff, &ilen, listp, f_M); } else i = -m; switch(i) { case 0: break; case 1: col = cole = strlen(buff) + col0; m = -K_e; continue; default: if (i < 0) ; else if (!f_list) { f_list = 1; col = cole = strlen(buff) + col0; m = -K_e; vt_putchar(K_g); continue; } else f_list = 0; strcpy(mess, &buff[ilen]); if (i < 0) { m = (i == -M_cmd) ? -T_cmd : -T_hist; strcat(buffb, buff); } else { m = -T_list; strcpy(buffb, buff); } goto jump; } break; case M_susp: vt_init(2); killpg(getpgrp(), SIGTSTP); vt_winsize(); vt_init(1); m = -M_clear; goto jump; break; default: if (m < N_char || m >= N_num) goto jump; else switch((m - N_char)) { case '\r': i = M_cr; if (!*buff) if (f_M == T_locate) if (!cs || cs == EO9) *buff = '\0'; else strcpy(buff, cs); else { vt_putchar(K_g); i = 0; } else { j = 0; switch(f_M) { case T_locate: i = T_cr; break; case T_hfile: case M_lfile: if ((cp = strstr(buff, " (")) || (cp = strstr(buff, " \042"))) { j = cp - buff; *cp = '\0'; } else j = 0; case T_hdir: case M_ldir: case M_lfile2: case M_ldir2: if ((cp = strstr(buff, "//"))) strcpy(buff, &cp[1]); else if (strchr(buff, '\0')[-1] == '~') strcpy(buff, s_S(S_home)); else if ((cp = strstr(buff, "~/"))) { strcpy(str, &cp[2]); sprintf(buff, "%s%s", s_S(S_home), str); } while (*(cp = &strchr(buff, '\0')[-1]) == ' ' || *cp == '\t') *cp = '\0'; if (access(buff, F_OK) < 0) { *buff = '\0'; vt_putchar(K_g); if ((i = f_M == M_lfile || f_M == M_ldir || f_M == T_hfile || f_M == T_hdir)) { m = -M_clear; goto jump; } } else if ((f_M == M_lfile || f_M == T_hfile) && j) buff[j] = ' '; break; default: break; } } if (shift) shift = 0; col = cole = col0; strcpy(mess, buff); if (f_M != M_cut && f_M != M_cut2 && f_M != M_fgrep && f_M != M_egrep) { for (j = strlen(mess) - 1; j >= 0 && mess[j] == ' '; j--) ; if (mess[j+1]) mess[j+1] = '\0'; } *buff = '\0'; m = i; goto jump; break; case K_s: m = M_fgrep; goto jump; break; case K_w: if (f_M == T_cp || f_M == T_mv || f_M == T_arc || f_M == T_arc3) { char *p = alloca(1 + 1 + strlen(old) + 1); sprintf(p, "%c%c%s", K_u, K_k, old); read_m(NULL, 3, 0, p, NULL, NULL, NULL, NULL, NULL, NULL, 0); } else vt_putchar(K_g); break; default: m = -m; break; } break; } } jump: return m; } int read_m(RV *rvp, int f_M, int klen, u_char *cva, char *cname, LIST **listp, STR *cmd, u_char *iname, char *dir, char *old, int f_move)/*tcb*/ { static char ex[] = "Exit ? (y/n) "; static char del[] = "Delete ? (y/n) "; static char dest[] = "Destination ? "; static int key_k[32], key_r[8], key_g[14], key_y[6]; static int n_bm, n_km, *p_km; static u_char *p_bm; static int *key_m, *key_c, k_wait, pid; static char *ks[7], esc[8] = {K_ec, }; static GETCH getch = vt_getch; u_char *cp; int i, c, k, f_enter, f_list, rowb, colb; if (f_M == T_key2) { key_m = (int*)cva; key_c = (int*)cname; k_wait = conf_wait(NULL, NULL); vt_ks(ks); /* copy buffer key */ key_y[0] = -1; key_y[1] = K_a; key_y[2] = K_e; key_y[3] = K_b; key_y[4] = K_f; key_y[5] = 0; /* invalid command-line key */ for (i = 0; i < 29; i++) switch(i) { case 0: key_k[i] = -1; /* return value 0 from ktoc() */ break; case K_j: /* ^J */ case K_o: /* ^O */ case K_t: /* ^T */ case K_x: /* ^X */ case K_ec: /* ^[ */ key_k[i] = -1; /* can be used for `F-?' in tcbrc */ break; case 28: key_k[i] = 0; break; default: key_k[i] = i; break; } /* cursor key */ key_r[0] = -1; key_r[1] = key_c[M_kup]; key_r[2] = key_c[M_kdn]; key_r[3] = key_c[M_knext]; key_r[4] = key_c[M_kprev]; key_r[5] = key_c[M_kback]; key_r[6] = key_c[M_kforw]; key_r[7] = 0; /* invalid key in T_input */ key_g[0] = -1; key_g[1] = M_up; key_g[2] = M_dn; key_g[3] = M_fgrep; key_g[4] = M_egrep; key_g[5] = M_kforw; key_g[6] = M_kback; key_g[7] = M_head; key_g[8] = M_tail; key_g[9] = M_prev; key_g[10] = M_next; key_g[11] = M_kprev; key_g[12] = M_knext; key_g[13] = 0; return 0; } if (cva) { key_getch(f_M, cva); getch = (GETCH)key_getch; return 0; } if (is_comm(f_M, 1) || f_M == M_exit) f_enter = 2; else if (is_comm(f_M, 0)) f_enter = 1; else f_enter = 0; f_list = 1; switch(f_M) { case M_fgrep: case M_locate: case M_man2: case M_cut2: case M_prog2: case M_lfile2: case M_ldir2: f_list = 0; case M_egrep: case M_cut: case M_man: case M_lfile: case M_ldir: case M_prog: case M_hist: case T_hist: case T_hfile: case T_hdir: case T_hman: case T_hlocate: case T_hfgrep: case T_hegrep: case M_cmd: case T_cmd: case M_list: case T_list: case T_locate: c = 1; break; case M_shell: case T_input: f_move = 1; default: c = f_enter == 2; break; } if (f_enter == 2) { vt_endstand(); vt_move(vt_row(0) - 1, klen); switch(f_M) { case T_rm: vt_printf("%s", del); klen += strlen(del); break; case M_exit: vt_printf("%s", ex); klen += strlen(ex); break; default: vt_printf("%s", dest); klen += strlen(dest); break; } } if (c) { u_char *p = (rvp->pp && rvp->pp->tell != (u_int)EOE) ? rvp->pp->cs : NULL; if (*iname || !p) *rvp->str = '\0'; if (f_list) stand_str(rvp, f_M); while (1) { c = input_key(f_M, rvp->str, p, klen, (*cname) ? cname : NULL , listp, cmd, iname, dir, old); if (!f_list && strint(key_g, c)) vt_putchar(K_g); else break; } if (f_list && c != M_cr && c != T_cr) stand_str(NULL, f_M); return c; } stand_str(rvp, f_M); k = c = 0; do { if (Key.f.winch) { Key.f.winch = 0; return T_winch; } else if (Key.f.term) { Key.f.term = 0; return T_exit; } else if (!c) { if (p_bm) { c = p_bm[n_bm++]; if (!p_bm[n_bm]) { if (getch == vt_getch) vt_mode('d'); free(p_bm); p_bm = NULL; n_bm = 0; } usleep(k_wait); } else if (p_km) { if ((c = p_km[n_km++]) == M_mm) { set_km(0, &p_km, c); n_km = 0; c = p_km[n_km++]; } if (load_intr() == S_errb || !p_km[n_km]) { if (getch == vt_getch) vt_mode('d'); if (!kill(pid, 0)) kill(pid, SIGKILL); unlink(s_S(S_intr)); p_km = NULL; n_km = pid = 0; } usleep(k_wait); stand_str(NULL, f_M); return c; } else if (getch != vt_getch) { if ((c = getch(0)) < 0) { getch = vt_getch; c = 0; continue; } } else c = getch(0); if (((c > 0 && c < ' ') || c == K_at) && Key.f.ctrl) return c; switch(c) { case K_at: if (f_M == M_shell || f_M == T_input) { vt_putchar(K_g); c = 0; } break; default: if (c >= 'A' && c <= 'D' && (f_M != M_shell && f_M != T_input)) c += 'a'-'A'; break; } } if (c == K_ec) if (k >> 8 == K_ec) { c = M_exit; continue; } else { if (getch != vt_getch) esc[1] = '\0'; else { i = strlen(ks[0]) - 1; vt_init(30); for (cp = &esc[1]; i && (*cp = getch(0)); i--, cp++) ; } if (esc[1]) { i = is_esc(ks, esc); esc[1] = '\0'; if (ks[i]) { if (i >= 4) getch(1); vt_init(10); stand_str(NULL, f_M); return kton(key_r[i+1], key_c); } else { c = 0; vt_init(10); continue; } } else { k = K_ec << 8; c = 0; vt_init(10); continue; } } else if (c == K_v) { c = M_kforw; continue; } else if (c == 'v' && k >> 8 == K_ec) { c = M_kback; continue; } else if (c == K_z) { c = M_susp; continue; } else if (c >= '0' && c <= '9') if (c >= '1' && k >> 8 == key_c[M_num]) { disp_window(rvp->ps, rvp->pp, f_M, NULL, NULL, NULL, &k); if (!(c = print_line(NULL, EOD, (f_M == M_shell) ? -c : c, NULL))) return M_clear; else return c + N_num; } else if (k >> 8 == key_c[M_cd]) return c - '0' + T_0; if (c) { if (Key.f.winch || Key.f.term) { c = 0; continue; } do { if (k) { k |= c; if (strint(key_m, k)) { k <<= 8; c = 0; continue; } else if (!(c = kton(k, key_c))) { k = c = 0; continue; } else if (f_M == M_shell || f_M == T_input) continue; } else if (strint(key_m, c) && (((f_M == M_shell || f_M == T_input) && !strint(key_k, c) && c < ' ') || (f_M != M_shell && f_M != T_input))) { k = c << 8; c = 0; continue; } else k = c; if (f_M == M_shell || f_M == T_input) if ((!strint(key_k, k) && k < ' ') || (f_M == M_shell && k == K_s) /* ^S */ || (f_M == T_input && k == K_c)) { /* ^C */ vt_putchar(K_g); k = c = 0; } else { switch(k) { case K_l: /* ^L */ c = M_clear; break; case K_i: /* ^I */ c = M_list; break; case K_s: /* ^S */ c = M_fgrep; break; case K_r: /* ^R */ c = M_hist; break; case K_n: /* ^N */ c = M_dn; break; case K_p: /* ^P */ c = M_up; break; case K_g: /* ^G */ c = M_bl; break; case K_z: /* ^Z */ c = M_susp; break; case K_w: /* ^W */ if (f_M != T_input) { c = T_w; break; } default: c = k + N_char; break; } k = 0; } else if (!(c = kton(k, key_c)) || strchr(print_key(NULL), c) || c == M_list) k = c = 0; else switch(c) { case M_cmd: c = T_cmd3; break; case M_hist: c = T_hist2; break; case M_ms: echo_mess(S_errp); n_km = set_km(0, NULL, c); if (p_km) p_km = NULL; c = k = 0; continue; case M_me: if (n_km) { k = S_errq; set_km(0, NULL, c); } else k = S_errr; echo_mess(k); n_km = c = k = 0; continue; case M_mm: if (!(pid = fork())) while (1) { /* unlink(s_S(S_intr)) <== (?) */ while (!vt_getch(1)) ; save_intr(S_errb); /* stop keyboard macro */ } set_km(0, &p_km, c); n_km = 0; c = p_km[n_km++]; if (load_intr() == S_errb || !p_km[n_km]) { if (!kill(pid, 0)) kill(pid, SIGKILL); unlink(s_S(S_intr)); p_km = NULL; n_km = pid = 0; } break; default: if (c >= M__0 && c <= M__19) { if (!(cp = s_S(S_macro + c - M__0))) { char *p = alloca(strlen(s_S(S_tcb)) + 10); sprintf(p, "tcbrc: M-%d", c - M__0); save_intr(S_errs); print_intr(p, NULL); } else p_bm = strdup(cp); c = k = n_bm = 0; } break; } } while (0); stand_str(rvp, f_M); } else if (f_M == M_shell && !k) /* check access() ==> shell.c(2) */ return 0; if (!access(s_S(S_mess), F_OK)) { c = T_du2; vt_move(vt_row(0) - 1, 0); vt_putchar(K_g); vt_printf(" (%s%s%s) ", vt_geta(A_md), s_S(S_errh), vt_geta(A_me)); vt_move(vt_row(0) - 1, 2 + strlen(s_S(S_errh)) + 2); vt_flush(); while (vt_getch(0) != K_m) ; f_M = T_input; } } while (!c); stand_str(NULL, f_M); if (f_M != M_shell) if (c == M_susp) { rowb = vt_row(0); colb = vt_col(0); vt_move(vt_row(0) - 1, 0); if (is_fm()) { vt_init(-2); kill(getpid(), SIGTSTP); vt_init(-1); } else { vt_init(-2); killpg(getpgrp(), SIGTSTP); killpg(getpgrp(), SIGCONT); vt_init(-1); } vt_winsize(); if (rowb != vt_row(0) || colb != vt_col(0)) key_winch(0); c = M_clear; } switch(c) { case M_ascii: if (vt_charset(0) == C_ascii) vt_charset(C_none); else vt_charset(C_ascii); c = M_sel; break; default: break; } if (n_km && !p_km) n_km = set_km(c, NULL, 0); return c; } void save_signal(int f_tcb)/*tcb*/ { int i; for (i = 1; i < NSIG; i++) switch(i) { case SIGWINCH: signal(i, key_winch); break; case SIGPIPE: signal(i, key_pipe); break; case SIGTERM: case SIGHUP: signal(i, key_term); break; case SIGSEGV: signal(i, key_segv); break; case SIGTTIN: signal(i, SIG_DFL); break; case SIGTTOU: signal(i, key_ttou); break; case SIGCONT: signal(i, key_cont); break; case SIGTSTP: case SIGCHLD: break; default: signal(i, SIG_IGN); break; } } int find_name(int n_name, STR **spp, LIST **listp, char name[], char str[], char bak[], int f_find) { DIR *dirp; struct direct *dp; struct stat st; STR *sp; PN pn; int i; char tmp[N_line]; sp = *spp; if (!(dirp = opendir(str))) return n_name; while ((dp = readdir(dirp))) if ((dp->d_ino || !strcmp(dp->d_name, "..")) && (!*name || (*name && !strncmp(dp->d_name, name, strlen(name))))) { if (f_find) { strcpy(tmp, str); strcat(tmp, dp->d_name); stat(tmp, &st); if ((((i = S_ISDIR(st.st_mode)) || !(st.st_mode & S_IXUSR)) && f_find == 1) || (!i && f_find == 2)) continue; } else { strcpy(tmp, str); strcat(tmp, dp->d_name); stat(tmp, &st); i = S_ISDIR(st.st_mode); } if (i && strchr(dp->d_name, '\0')[-1] != '/') strcat(dp->d_name, "/"); strcpy(bak, dp->d_name); if (*name) sp = save_str(sp, dp->d_name, &pn); *listp = save_list(*listp, dp->d_name, &pn); n_name++; } *spp = sp; closedir(dirp); return n_name; } void make_cmd(STR *sp, LIST **listp)/*tcb*/ { static PN pn; for (; sp; sp = sp->next) if (sp->name) *listp = save_list(*listp, sp->name, &pn); } int make_list(u_char dir0[], u_char buff[], int *lenp, LIST **listp, int f_M)/*tcb*/ { int c, i, n_name, f_prog, f_dir = 0; char *cp, *dir, name[N_line], bak[N_line]; STR *sp; if ((f_prog = (*buff != '.' && !strchr(buff, '/') && !strchr(buff, ' ') && (f_M == M_prog || f_M == M_prog2 || f_M == M_man || f_M == M_man2 || f_M == M_shell)))) { strcpy(name, buff); dir = malloc(strlen(s_S(S_path)) + 1); } else { f_dir = (f_M == M_ldir || f_M == M_ldir2 || f_M == T_arc || f_M == T_arc3) ? 2 : 0; if ((i = ichrstr(buff, 0, "//"))) i--; else for (i = strlen(buff); i && (c = buff[i]) != ' ' && c != '<' && c != '>' && c != '|' && c != ';'; i--) ; if (i) i++; if (buff[i]) { if (buff[i] == '/') { dir = malloc(strlen(&buff[i]) + 1 + 1); strcpy(dir, &buff[i]); } else { u_char *p = alloca(strlen(&buff[i]) + 1); strcpy(p, &buff[i]); dir = malloc(strlen(dir0) + strlen(p) + 1 + 1); strcpy(dir, dir0); strcat(dir, p); } strcpy(name, dir); get_dir(dir); if (strchr(dir, '\0')[-1] != '/') strcat(dir, "/"); get_name(name); } else { dir = malloc(strlen(dir0) + 1); strcpy(dir, dir0); *name = '\0'; } } sp = NULL; if (f_prog) { char *path = malloc(strlen(s_S(S_path)) + 1); char *str = malloc(strlen(s_S(S_path)) + 1); n_name = 0; strcpy(path, s_S(S_path)); cp = path; while (1) { strcpy(dir, cp); if ((cp = strchr(dir, ':'))) { *cp = '\0'; strcpy(str, dir); strcat(str, "/"); n_name = find_name(n_name, &sp, listp, name, str, bak, f_prog); *cp++ = ':'; } else { strcat(dir, "/"); n_name = find_name(n_name, &sp, listp, name, dir, bak, f_prog); break; } } free(path); free(str); } else n_name = find_name(0, &sp, listp, name, dir, bak, f_dir); if (f_prog) i = 0; else { for (i = strlen(buff); (c = buff[i]) != ' ' && c != '<' && c != '>' && c != '|' && c != ';' && c != '/' && i; i--) ; if ((!i && c == '/') || i) i++; } if (!*name) { if (!f_prog && n_name == 1) strcpy(&buff[i], bak); } else if (n_name) { set_name(sp, name); strcpy(&buff[i], name); } if (n_name == 1) if (f_M == M_shell) if (strchr(bak, '\0')[-1] == '/') { if (strchr(buff, '\0')[-1] != '/') strcat(buff, "/"); } else strcat(buff, " "); else if (!f_prog && f_dir && strchr(buff, '\0')[-1] != '/') strcat(buff, "/"); free_str(sp); *lenp = i; free(dir); return n_name; } void key_eeol(int row, int col0, int len)/*tcb*/ { vt_move(row, col0); while (len--) vt_putchar(' '); vt_move(row, col0); } static void add_buff(int m, int *shiftp, int row, int *colp, int col0, int len, int *colep, u_char back[], u_char buff[]) { int i; if (strlen(buff) > N_line - 2) { vt_putchar(K_g); return; } if (*colp < col0 + len && (*shiftp || (!*shiftp && *colp < *colep))) { i = *shiftp + *colp - col0; strcpy(back, &buff[i]); strcpy(&buff[i+1], back); buff[i] = m; strcpy(back, &buff[*shiftp]); back[len] = '\0'; vt_move(row, col0); print_buff(back); (*colp)++; (*colep)++; vt_move(row, *colp); } else { i = 0; if (*colp == col0 + len) { (*shiftp)++; vt_move(row, col0); if ((i = buff[*colp - col0 + *shiftp - 1])) { strcpy(back, &buff[*colp - col0 + *shiftp - 1]); buff[*colp-col0 + *shiftp - 1] = '\0'; } print_buff(&buff[*shiftp]); } if ((m > 0 && m < ' ') || m == K_at) { vt_stand(); vt_putchar(((m == K_at) ? 0 : m) + '@'); vt_endstand(); } else vt_putchar(m); vt_flush(); sprintf(&buff[*colp-col0 + ((*shiftp) ? *shiftp - 1 : 0)], "%c", m); (*colep)++; if (i) strcat(buff, back); if (!*shiftp) *colp = *colep; else strcpy(back, &buff[*shiftp]); vt_move(row, *colp); } } int edit_line(int m, int mb, u_char buff[], int len, int row, int col0, int *colp, int *colep, int *shiftp)/*tcb*/ { int i, col, cole, shift; static u_char back[N_line+1], yank[N_line+1]; col = *colp; cole = *colep; shift = *shiftp; for (; ; m = (m > 0) ? 0 : m) { if (!m) m = read_m(EOB, mb, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL,0); if (Key.f.ctrl) { Key.f.ctrl = 0; if (((m > 0 && m < ' ') || m == K_dl || m == K_at)) { vt_move(row, col); add_buff(m, &shift, row, &col, col0, len, &cole, back, buff); vt_flush(); continue; } } if ((m >= 0 && m <= N_char) || m >= N_num) break; else { switch(((m > 0) ? m - N_char : m)) { case 0: continue; case K_q: Key.f.ctrl = 1; break; case K_u: /* ^U */ i = shift + col - col0; cole -= i; memcpy(yank, buff, i); yank[i] = '\0'; strcpy(buff, &buff[i]); shift = ((i = cole - col0 - len) > 0) ? i : 0; strcpy(back, &buff[shift]); col = col0; key_eeol(row, col0, len); print_buff(back); vt_move(row, col); vt_flush(); break; case K_k: /* ^K */ if (shift) { cole = shift + col; strcpy(yank, &buff[cole - col0]); buff[cole - col0] = '\0'; if ((i = cole - col0 - len) > 0) { shift = i; col = col0 + len; } else { shift = 0; col = cole; } strcpy(back, &buff[shift]); key_eeol(row, col0, len); print_buff(back); } else { strcpy(yank, &buff[col - col0]); buff[col - col0] = '\0'; key_eeol(row, col, len - (col - col0)); cole = col; } break; case K_y: /* ^Y */ vt_move(row, col0); if ((i = strlen(buff) + strlen(yank) + 1 - N_line) > 0) { vt_putchar(K_g); strchr(yank, '\0')[-i] = '\0'; } if (col == cole) strcat(buff, yank); else { i = col - col0 + shift; memmove(&buff[i + strlen(yank)], &buff[i], strlen(&buff[i]) + 1); memcpy(&buff[i], yank, strlen(yank)); } cole = strlen(buff) + col0; if ((i = cole - col0 - len) > 0) { shift = i; strcpy(back, &buff[shift]); print_buff(back); col = col0 + len; } else { key_eeol(row, col0, len); print_buff(buff); col = cole; } break; case K_dl: case K_h: /* ^H */ if (col <= col0) { vt_putchar(K_g); continue; } else { if (shift) { strcpy(&buff[col - col0 + shift - 1] , &buff[col - col0 + shift]); if (shift) shift--; strcpy(back, &buff[shift]); } else { if (col == cole) buff[cole - col0 - 1] = '\0'; else strcpy(&buff[col - col0 - 1], &buff[col - col0]); col--; strcpy(back, buff); } cole--; back[len] = '\0'; key_eeol(row, col0, len); print_buff(back); vt_move(row, col); } break; case K_d: /* ^D */ if ((shift && col >= col0 + len) || (!shift && (cole == col0 || cole == col))) { vt_putchar(K_g); continue; } if (shift) { strcpy(&buff[col - col0 + shift], &buff[col - col0 + shift + 1]); if (shift) shift--; strcpy(back, &buff[shift]); col++; } else { strcpy(&buff[col - col0], &buff[col - col0 + 1]); strcpy(back, buff); } back[len] = '\0'; cole--; key_eeol(row, col0, len); print_buff(back); vt_move(row, col); break; case K_a: /* ^A */ vt_move(row, (col = col0)); if (shift) { strcpy(back, buff); back[len] = '\0'; print_buff(back); vt_move(row, col); vt_flush(); shift = 0; } break; case -K_e: m -= m; case K_e: /* ^E */ vt_move(row, col0); if ((i = cole - col0 - len) > 0) { shift = i; strcpy(back, &buff[shift]); print_buff(back); col = col0 + len; } else { key_eeol(row, col0, len); print_buff(buff); col = cole; } break; case K_b: /* ^B */ if (!*buff) { vt_putchar(K_g); continue; } if (col <= col0) { if (shift) { strcpy(back, &buff[--shift]); back[len] = '\0'; vt_move(row, col0); print_buff(back); vt_move(row, col0); vt_flush(); } else { vt_putchar(K_g); continue; } } else vt_move(row, --col); break; case K_f: /* ^F */ if (col >= cole) { vt_putchar(K_g); continue; } if (col < col0 + len - 1) vt_move(row, ++col); else { if (shift+len >= cole - col0) { vt_putchar(K_g); continue; } strcpy(back, &buff[++shift]); back[len] = '\0'; vt_move(row, col0); print_buff(back); vt_flush(); } break; case K_c: /* ^C */ case '\r': goto jump; default: if (m > 0) goto jump; else m = -m - N_char; vt_move(row, col); add_buff(m, &shift, row, &col, col0, len, &cole, back, buff); break; } vt_flush(); } } jump: *colp = col; *colep = cole; *shiftp = shift; return m; }