diff -urN cui125/cui.c cui126/cui.c --- cui125/cui.c Mon Apr 21 01:00:00 2014 +++ cui126/cui.c Mon Apr 21 22:00:00 2014 @@ -512,6 +512,12 @@ } int +cui_child_num(cui obj) +{ + return cui_index(obj->children) + 1; +} + +int cui_index(cui obj) { if(obj == NULL) return -1; @@ -601,6 +607,7 @@ { cui term = cui_term_new(obj, 0, 0, cui_x2(obj), cui_y2(obj)+1); cui_hide(term); + cui_draw(obj); cui_puts_add(html_puts, term); cui_draw(obj); diff -urN cui125/cui.h cui126/cui.h --- cui125/cui.h Thu Apr 17 22:00:00 2014 +++ cui126/cui.h Mon Apr 21 22:00:00 2014 @@ -87,6 +87,7 @@ void cui_wh_fit(cui obj); void cui_wh_exp(cui obj); +int cui_child_num(cui obj); int cui_index(cui obj); cui cui_index_to_child(cui obj, int i); diff -urN cui125/cui_srv.c cui126/cui_srv.c --- cui125/cui_srv.c Mon Apr 21 01:00:00 2014 +++ cui126/cui_srv.c Mon Apr 21 22:00:00 2014 @@ -12,9 +12,10 @@ #include "handler.h" #include "button.h" #include "dialog.h" +#include "menu.h" struct conn_prm{ - cui view, conn, close_btn, tab; + cui view, menu_pd, tab; }; static int @@ -40,22 +41,33 @@ } static void -client_add(cui tab, int cfd, void *prm) +close_show_hide(void *prm, int v) { struct conn_prm *p = (struct conn_prm *)prm; - int y = cui_y2(cui_tab_scline(tab)); - cui termin = cui_termin_new(p->view, 0, 0, 0, 0, cfd); + cui menu = cui_menu_pulldown_menu_get(p->menu_pd); + cui item = cui_menu_str_to_item(menu, "close"); + cui_show_hide(item, v); +} + +static void +term_add(int cfd, void *prm) +{ + struct conn_prm *p = (struct conn_prm *)prm; + int y = cui_y2(cui_tab_scline(p->tab)); + cui t = (cfd == -1) ? + cui_terminal_new(p->view, 0, 0, 0, 0): + cui_termin_new(p->view, 0, 0, 0, 0, cfd); static int cnt = 0; char buf[16]; - cui_hide(termin); - cui_xywh_set(termin, 0, y, p->view->w, p->view->h - y); + cui_hide(t); + cui_xywh_set(t, 0, y, p->view->w, p->view->h - y); - sprintf(buf, "%d", cnt++); - cui_tab_add(tab, strdup(buf), termin, FALSE); + sprintf(buf, "%s%d", cfd == -1 ? "sh-" : "", cnt++); + cui_tab_add(p->tab, strdup(buf), t, FALSE); - cui_show(p->close_btn); + close_show_hide(prm, TRUE); } static int @@ -67,7 +79,7 @@ case CUI_EVT_READABLE: sfd = val; if((cfd = cui_srv_accept(sfd)) == -1) return FALSE; - client_add(obj, cfd, prm); + term_add(cfd, prm); break; default: return FALSE; @@ -89,7 +101,7 @@ if(fc == tab || fc == termin) cui_focus_set(NULL); cui_tab_del(tab, termin); cui_termin_del_free(termin); - if(cui_tab_n_get(tab) <= 0) cui_hide(p->close_btn); + if(cui_tab_n_get(tab) <= 0) close_show_hide(prm, FALSE); break; case CUI_EVT_RESIZE: for(tab_btn=tab->children; tab_btn; tab_btn=tab_btn->next){ @@ -112,21 +124,28 @@ switch(evt){ case CUI_EVT_BUTTON: - if(obj == p->conn){ - if(!cui_host_port_dialog(p->view, p->conn->x+1, cui_y2(p->conn), host, &port)) break; - if((cfd = cui_conn_host_port(host, port)) == -1){ - cui_msg_dialog(p->view, "connect failed"); - break; - } - client_add(p->tab, cfd, prm); - }else if(obj == p->close_btn){ - cui_termin termin = (cui_termin)cui_tab_get(p->tab); - if(termin){ - char buf[1024]; - sprintf(buf, "close tab '%s' ?", cui_tab_str_get(p->tab)); - if(cui_confirm_dialog(p->view, buf)) cui_termin_kill((cui)termin); + if(obj == p->menu_pd){ + char *s = cui_menu_pulldown_str_get(p->menu_pd); + if(strcmp(s, "conn") == 0){ + if(!cui_host_port_dialog(p->view, 1, 1, host, &port)) break; + if((cfd = cui_conn_host_port(host, port)) == -1){ + cui_msg_dialog(p->view, "connect failed"); + break; + } + term_add(cfd, prm); + }else if(strcmp(s, "shell") == 0){ + term_add(-1, prm); /* shell */ + }else if(strcmp(s, "close") == 0){ + char buf[1024], *tab_str; + cui t = cui_tab_get(p->tab); + if(t== NULL) break; + tab_str = cui_tab_str_get(p->tab); + sprintf(buf, "close tab '%s' ?", tab_str); + if(!cui_confirm_dialog(p->view, buf)) break; + if(strncmp(tab_str, "sh-", 3) == 0) cui_terminal_kill(t); + else cui_termin_kill(t); } - } + }else return FALSE; break; default: return FALSE; @@ -140,22 +159,21 @@ int init_ret = cui_init(av); cui bs = cui_scpanel_new(NULL, 0, 0, w_get(av), h_get(av), "cui_srv"); cui view = ((cui_scpanel)bs)->view; - cui conn = cui_button_new(view, 0, 0, "conn"); - cui close_btn = cui_button_new(view, cui_x2(conn) + 1, 0, "close"); - cui tab = cui_tab_new(view, cui_x2(close_btn) + 1, 0, 0, NULL, NULL, FALSE); + char *lst[] = { "conn", "shell", "close", NULL }; + cui menu_pd = cui_menu_pulldown_new(view, 0, 0, "menu", lst); + cui tab = cui_tab_new(view, cui_x2(menu_pd) + 1, 0, 0, NULL, NULL, FALSE); char **av2 = av; int port, sfd; - struct conn_prm cprm = {view, conn, close_btn, tab}; + struct conn_prm cprm = { view, menu_pd, tab }; - cui_hide(close_btn); + close_show_hide(&cprm, FALSE); cui_bind(tab, CUI_EVT_READABLE, tab_hdr, &cprm); while((port = cui_arg_int(av2, "-port", -1, &av2)) != -1){ if((sfd = cui_srv_port(port)) == -1) continue; cui_readable_add(tab, sfd); } cui_bind(view, CUI_EVT_DEAD | CUI_EVT_RESIZE, view_hdr, &cprm); - cui_bind(conn, CUI_EVT_BUTTON, conn_hdr, &cprm); - cui_bind(close_btn, CUI_EVT_BUTTON, conn_hdr, &cprm); + cui_bind(menu_pd, CUI_EVT_BUTTON, conn_hdr, &cprm); cui_main(bs, NULL); cui_free(bs); diff -urN cui125/menu.c cui126/menu.c --- cui125/menu.c Fri Apr 11 01:00:00 2014 +++ cui126/menu.c Mon Apr 21 22:00:00 2014 @@ -162,6 +162,18 @@ return NULL; } +int +cui_menu_item_num(cui obj) +{ + return cui_child_num(obj); +} + +cui +cui_menu_item_get(cui obj, int i) +{ + return cui_index_to_child(obj, i); +} + cui cui_menu_popup_new(cui parent, int x, int y, int w, char **lst, int val) { @@ -399,6 +411,98 @@ { cui_menu_int_lst_free(obj); cui_menu_popup_del_free(obj); +} + +cui +cui_menu_pulldown_new(cui parent, int x, int y, char *s, char **lst) +{ + cui obj = cui_alloc(sizeof(struct cui_menu_pulldown)); + cui_menu_pulldown_init(obj, parent, x, y, s, lst); + return obj; +} + +void +cui_menu_pulldown_init(cui obj, cui parent, int x, int y, char *s, char **lst) +{ + cui_menu_pulldown p = (cui_menu_pulldown)obj; + cui_base_init(obj, parent, x, y, 0, 0); + p->btn = cui_menu_btn_new(obj, 0, 0, s); + cui_wh_fit(obj); + p->menu = cui_menu_new(cui_root(obj), 0, 0, lst); + p->v = -1; + p->vp = NULL; + + cui_bind(p->btn, CUI_EVT_BUTTON, cui_menu_pulldown_hdr, obj); + cui_bind(p->menu, CUI_EVT_BUTTON, cui_menu_pulldown_hdr, obj); +} + +int +cui_menu_pulldown_hdr(cui ev_obj, int evt, int val, void *prm) +{ + cui obj = (cui)prm; + cui_menu_pulldown p = (cui_menu_pulldown)obj; + + switch(evt){ + case CUI_EVT_BUTTON: + if(ev_obj == p->btn){ + int bak = p->v; + p->menu->x = cui_lx(cui_root(obj), cui_gx(obj)); + p->menu->y = cui_ly(cui_root(obj), cui_gy(obj)) + 1; + p->menu->flags &= ~CUI_FLG_HIDE; + cui_main(p->menu, cui_index_to_child(p->menu, 0)); + cui_hide(p->menu); + if(p->v < 0) p->v = bak; + else cui_handler_call(obj, CUI_EVT_BUTTON, p->v); + }else if(ev_obj == p->menu){ + p->v = val; + if(p->vp) *p->vp = p->v; + cui_quit(); + } + break; + default: + return FALSE; + } + return TRUE; +} + +int +cui_menu_pulldown_get(cui obj) +{ + cui_menu_pulldown p = (cui_menu_pulldown)obj; + return p->v; +} + +void +cui_menu_pulldown_vp_set(cui obj, int *vp) +{ + cui_menu_pulldown p = (cui_menu_pulldown)obj; + p->vp = vp; +} + +cui +cui_menu_pulldown_menu_get(cui obj) +{ + cui_menu_pulldown p = (cui_menu_pulldown)obj; + return p->menu; +} + +char * +cui_menu_pulldown_str_get(cui obj) +{ + cui_menu_pulldown p = (cui_menu_pulldown)obj; + cui item; + + if(p->v < 0) return ""; + if((item = cui_menu_item_get(p->menu, p->v)) == NULL) return ""; + return cui_menu_item_str_get(item); +} + +void +cui_menu_pulldown_del_free(cui obj) +{ + cui_menu_pulldown p = (cui_menu_pulldown)obj; + cui_del_free(p->menu); + cui_del_free(obj); } /* EOF */ diff -urN cui125/menu.h cui126/menu.h --- cui125/menu.h Fri Apr 11 01:00:00 2014 +++ cui126/menu.h Mon Apr 21 22:00:00 2014 @@ -27,6 +27,12 @@ int v, min_v, max_v, *vp; } *cui_menu_int; +typedef struct cui_menu_pulldown{ + struct cui_base base; + cui btn, menu; + int v, *vp; +} *cui_menu_pulldown; + cui cui_menu_btn_new(cui parent, int x, int y, char *s); void cui_menu_btn_init(cui obj, cui parent, int x, int y, char *s); int cui_menu_btn_hdr(cui obj, int evt, int val, void *prm); @@ -41,6 +47,8 @@ cui cui_menu_new(cui parent, int x, int y, char **lst); cui cui_menu_str_to_item(cui menu, char *s); +int cui_menu_item_num(cui obj); +cui cui_menu_item_get(cui obj, int i); cui cui_menu_popup_new(cui parent, int x, int y, int w, char **lst, int val); void cui_menu_popup_init(cui obj, cui parent, int x, int y, int w, char **lst, int val); @@ -60,5 +68,14 @@ void cui_menu_int_vp_set(cui obj, int *vp); void cui_menu_int_min_max_set(cui obj, int min_v, int max_v); void cui_menu_int_del_free(cui obj); + +cui cui_menu_pulldown_new(cui parent, int x, int y, char *s, char **lst); +void cui_menu_pulldown_init(cui obj, cui parent, int x, int y, char *s, char **lst); +int cui_menu_pulldown_hdr(cui obj, int evt, int val, void *prm); +int cui_menu_pulldown_get(cui obj); +void cui_menu_pulldown_vp_set(cui obj, int *vp); +cui cui_menu_pulldown_menu_get(cui obj); +char *cui_menu_pulldown_str_get(cui obj); +void cui_menu_pulldown_del_free(cui obj); #endif diff -urN cui125/tab.c cui126/tab.c --- cui125/tab.c Mon Apr 21 00:00:00 2014 +++ cui126/tab.c Mon Apr 21 22:00:00 2014 @@ -236,7 +236,7 @@ int cui_tab_n_get(cui obj) { - return obj->children == NULL ? 0 : cui_index(obj->children) + 1; + return cui_child_num(obj); } char * diff -urN cui125/term.c cui126/term.c --- cui125/term.c Mon Apr 21 00:00:00 2014 +++ cui126/term.c Mon Apr 21 22:00:00 2014 @@ -553,8 +553,8 @@ if(t->pid == pid) break; } if(p == NULL) return; - cui_readable_del(obj, t->pipe_r); cui_list_del(&t_list, p->data); + cui_termin_kill(obj); } static void @@ -562,7 +562,12 @@ { cui_terminal p = (cui_terminal)obj; int ret, master; - signal(SIGCHLD, sig_hdr); + static int first = TRUE; + + if(first){ + signal(SIGCHLD, sig_hdr); + first = FALSE; + } #if defined(__FreeBSD__) if((ret = forkpty(&master, NULL, NULL, NULL)) < 0) ERR("forkpy"); #else /* defined(__linux__) */ @@ -573,7 +578,7 @@ if((ret = fork()) < 0) ERR("fork"); #endif if(ret != 0){ /* parent */ - p->pipe_r = p->pipe_w = master; + p->sock = master; p->pid = ret; *(cui *)cui_list_add(&t_list, sizeof(cui)) = obj; return; @@ -608,99 +613,24 @@ cui_terminal_init(cui obj, cui parent, int x, int y, int w, int h) { cui_terminal p = (cui_terminal)obj; - int evts; char *cmd = "stty erase ^H\r"; - cui_base_init(obj, parent, x, y, w, h); - obj->flags |= CUI_FLG_CAN_FOCUS; - - p->term = cui_term_new(obj, 1, 0, w-2, h); - p->in_key_mode = FALSE; - - p->fill_l = cui_fill_new(obj, 0, 0, 1, h, "|", CUI_ATTR_NORMAL); - p->fill_r = cui_fill_new(obj, w-1, 0, 1, h-1, "|", CUI_ATTR_NORMAL); - p->rszbox = cui_rszbox_new(obj); - boot_sh(obj); - if(write(p->pipe_w, cmd, strlen(cmd)) <0) ERR("write"); - - evts = CUI_EVT_DRAW|CUI_EVT_KEY|CUI_EVT_RESIZE|CUI_EVT_TIMER|CUI_EVT_READABLE; - cui_bind(obj, evts, cui_terminal_hdr, NULL); - - cui_readable_add(obj, p->pipe_r); + cui_termin_init(obj, parent, x, y, w, h, p->sock); + if(write(p->sock, cmd, strlen(cmd)) <0) ERR("write"); } void -cui_terminal_in_key_mode_set(cui obj, int in_key_mode) -{ - int attr; - - cui_terminal p = (cui_terminal)obj; - if(p->in_key_mode == in_key_mode) return; - - p->in_key_mode = in_key_mode; - attr = in_key_mode ? CUI_ATTR_REVERSE : CUI_ATTR_NORMAL; - cui_fill_attr_set(p->fill_l, attr); - cui_fill_attr_set(p->fill_r, attr); - - cui_timer_set(obj, TIMEOUT_MSEC, TRUE); -} - -int -cui_terminal_hdr(cui obj, int evt, int val, void *prm) +cui_terminal_kill(cui obj) { cui_terminal p = (cui_terminal)obj; - char *s, buf[1024]; - int n; - - switch(evt){ - case CUI_EVT_DRAW: - s = val == CUI_DRAW_FOCUS ? "/" : "|"; - cui_label_str_set(p->fill_l, s); - cui_label_str_set(p->fill_r, s); - return TRUE; - - case CUI_EVT_KEY: - if(!p->in_key_mode){ - if(val == CUI_KEY_ENTER){ - cui_terminal_in_key_mode_set(obj, TRUE); - return TRUE; - } - return FALSE; - } - /* in_key_mode */ - if(write(p->pipe_w, &val, 1) != 1) ERR("write"); - cui_timer_set(obj, TIMEOUT_MSEC, TRUE); - return TRUE; - - case CUI_EVT_RESIZE: - cui_wh_set(p->term, obj->w-2, obj->h); - cui_wh_set(p->fill_l, 1, obj->h); - cui_xywh_set(p->fill_r, obj->w-1, 0, 1, obj->h-1); - cui_xy_set(p->rszbox, obj->w-1, obj->h-1); - return TRUE; - - case CUI_EVT_TIMER: - cui_terminal_in_key_mode_set(obj, FALSE); - return TRUE; - - case CUI_EVT_READABLE: - if((n = read(p->pipe_r, buf, 1024-1)) < 0){ - return TRUE; - } - buf[n] = '\0'; - cui_term_puts(p->term, buf); - return TRUE; - } - return FALSE; + kill(p->pid, SIGKILL); } void cui_terminal_del_free(cui obj) { - cui_terminal p = (cui_terminal)obj; - cui_term_buf_free(p->term); - cui_del_free(obj); + cui_termin_del_free(obj); } /* EOF */ diff -urN cui125/term.h cui126/term.h --- cui125/term.h Mon Apr 21 00:00:00 2014 +++ cui126/term.h Mon Apr 21 22:00:00 2014 @@ -26,11 +26,8 @@ } *cui_termin; typedef struct cui_terminal{ - struct cui_base base; - cui term, fill_l, fill_r, rszbox; - int in_key_mode; - int pipe_r, pipe_w; - int pid; + struct cui_termin termin; + int sock, pid; } *cui_terminal; cui cui_term_new(cui parent, int x, int y, int w, int h); @@ -67,7 +64,7 @@ cui cui_terminal_new(cui parent, int x, int y, int w, int h); void cui_terminal_init(cui obj, cui parent, int x, int y, int w, int h); int cui_terminal_hdr(cui obj, int evt, int val, void *prm); -void cui_terminal_in_key_mode_set(cui obj, int in_key_mode); +void cui_terminal_kill(cui obj); void cui_terminal_del_free(cui obj); #endif