From e369ad3fc8c95e81e0d84758896297cf970b324a Mon Sep 17 00:00:00 2001 From: root Date: Thu, 2 Dec 2010 23:53:41 +0200 Subject: [PATCH] tabs for console - tabs as window configuration --- src/dispextern.h | 3 + src/frame.c | 240 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- src/frame.h | 31 ++++++- src/window.c | 5 + src/xdisp.c | 79 ++++++++++++++++++ src/xfaces.c | 10 ++ 6 files changed, 359 insertions(+), 9 deletions(-) diff --git a/src/dispextern.h b/src/dispextern.h index 7426c03..2a87044 100644 --- a/src/dispextern.h +++ b/src/dispextern.h @@ -1697,6 +1697,9 @@ enum face_id MOUSE_FACE_ID, MENU_FACE_ID, VERTICAL_BORDER_FACE_ID, + CURRENT_TAB_FACE_ID, + ODD_TAB_FACE_ID, + EVEN_TAB_FACE_ID, BASIC_FACE_ID_SENTINEL }; diff --git a/src/frame.c b/src/frame.c index ba675be..b90bff3 100644 --- a/src/frame.c +++ b/src/frame.c @@ -118,16 +118,20 @@ Lisp_Object Qwindow_id; Lisp_Object Qouter_window_id; #endif Lisp_Object Qparent_id; -Lisp_Object Qtitle, Qname; +Lisp_Object Qtitle, Qname, Qtab_name, Qtab, Qcurrent_tab; +Lisp_Object Qtab_env; +Lisp_Object Qtab_list; Lisp_Object Qexplicit_name; Lisp_Object Qunsplittable; -Lisp_Object Qmenu_bar_lines, Qtool_bar_lines, Qtool_bar_position; +Lisp_Object Qmenu_bar_lines, Qtool_bar_lines, Qtool_bar_position, Qtab_bar_lines; Lisp_Object Vmenu_bar_mode, Vtool_bar_mode; Lisp_Object Qleft_fringe, Qright_fringe; Lisp_Object Qbuffer_predicate, Qbuffer_list, Qburied_buffer_list; Lisp_Object Qtty_color_mode; Lisp_Object Qtty, Qtty_type; +Lisp_Object Qtab_activate, Qtab_deactivate, Qtab_init; + Lisp_Object Qfullscreen, Qfullwidth, Qfullheight, Qfullboth, Qmaximized; Lisp_Object Qsticky; Lisp_Object Qfont_backend; @@ -197,6 +201,149 @@ set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval) adjust_glyphs (f); } } + +/* this is identical to set_menu_bar_lines_1 */ +static void +set_tab_bar_lines_1 ( Lisp_Object window, int n) +{ + struct window *w = XWINDOW (window); + + XSETFASTINT (w->last_modified, 0); + XSETFASTINT (w->top_line, XFASTINT (w->top_line) + n); + XSETFASTINT (w->total_lines, XFASTINT (w->total_lines) - n); + + if (INTEGERP (w->orig_top_line)) + XSETFASTINT (w->orig_top_line, XFASTINT (w->orig_top_line) + n); + if (INTEGERP (w->orig_total_lines)) + XSETFASTINT (w->orig_total_lines, XFASTINT (w->orig_total_lines) - n); + + /* Handle just the top child in a vertical split. */ + if (!NILP (w->vchild)) + set_tab_bar_lines_1 (w->vchild, n); + + /* Adjust all children in a horizontal split. */ + for (window = w->hchild; !NILP (window); window = w->next) + { + w = XWINDOW (window); + set_tab_bar_lines_1 (window, n); + } +} + +static void +set_tab_bar_lines (struct frame *f, Lisp_Object value) +{ + int nlines, olines, maxlines; + Lisp_Object frame; + + if (FRAME_MINIBUF_ONLY_P (f)) + return; + + XSETFRAME(frame, f); + + if (INTEGERP (value)) + nlines = XINT (value); + else + nlines = 0; + + struct frame *this; + this = XFRAME(frame); + olines = FRAME_TAB_BAR_LINES (this); + if (nlines != olines) + { + if (EQ (frame, selected_frame)) + /* redisplay is required only when one changes the + selected tab */ + windows_or_buffers_changed++; + FRAME_WINDOW_SIZES_CHANGED (this) = 1; + FRAME_TAB_BAR_LINES (this) = nlines; + set_tab_bar_lines_1 (this->root_window, nlines - olines); + adjust_glyphs (this); + } + +} + +void +activate_tab (struct frame *f, int tab_index) +{ + Lisp_Object activatecode, tab; + FRAME_CURRENT_TAB (f) = XINT (tab_index); + tab = Fnth ( tab_index, f -> tab_bar_items ) ; + activatecode = Fassq (Qtab_activate, tab); + if (! EQ (Qnil, activatecode)) + { + activatecode = XCDR (activatecode); + return (void) Ffuncall (1, &activatecode); + } +} + +void +deactivate_tab (struct frame *f) +{ + return; + Lisp_Object deactivatecode, tab; + tab = AREF ( f->tab_bar_items, f->current_tab ) ; + deactivatecode = Fassq (Qtab_deactivate, tab); + if (! EQ (Qnil, deactivatecode)) + { + deactivatecode = XCDR (deactivatecode); + return (void) Ffuncall (1, &deactivatecode); + } +} + +void +set_current_tab (struct frame *f, Lisp_Object value) +{ + int otab, tab; + + if (FRAME_MINIBUF_ONLY_P (f)) + return; + + Lisp_Object frame; + XSETFRAME(frame, f); + + if (INTEGERP (value)) + tab = XINT (value); + else + return (void) deactivate_tab (f); + + otab = FRAME_CURRENT_TAB (f); + + /* no tag is active */ + if (Flength (FRAME_TAB_BAR_ITEMS (f)) <= value) + return (void) deactivate_tab (f); + + if (tab != otab) + { + if (EQ (frame, selected_frame)) + /* redisplay is required only when one changes the + selected tab */ + windows_or_buffers_changed++; + FRAME_WINDOW_SIZES_CHANGED (f) = 1; + deactivate_tab (f); + activate_tab (f, value); + adjust_glyphs (f); + } + +} + +void +add_tab_environment (struct frame *f, + Lisp_Object prop) +{ + Lisp_Object env, l; + l = Fnth (make_number (f->current_tab), f->tab_bar_items); + if (NILP(prop)) + return; + return; + env = Fcons (prop, + XCDR (Fassq (Qtab_env, + XCDR ( AREF (f->tab_bar_items, f->current_tab))))); +// env = Fcons (Qtab_env, Fcons ( prop, XCDR (env) ) ); + store_in_alist (&l, Qtab_env, env); + +} + + Lisp_Object Vframe_list; @@ -348,6 +495,10 @@ make_frame (int mini_p) f->font_driver_list = NULL; f->font_data_list = NULL; + f->tab_bar_items = Qnil; + f->current_tab = 0; + f->last_tab = 0; + root_window = make_window (); if (mini_p) { @@ -570,7 +721,6 @@ make_initial_frame (void) return f; } - struct frame * make_terminal_frame (struct terminal *terminal) { @@ -650,6 +800,44 @@ get_future_frame_param (Lisp_Object parameter, return result; } +Lisp_Object +add_tab (Lisp_Object parms) +{ + Lisp_Object tab_name, initcode, activatecode, deactivatecode, tab, env, name; + + Lisp_Object tab_object[4]; + + struct frame *sf = SELECTED_FRAME (); + if (sf->last_tab == 1000) + return Qnil; + + activatecode = Fassq (Qtab_activate, parms); + deactivatecode = Fassq (Qtab_deactivate, parms); + env = Fassq (Qtab_env, parms); + name = Fassq (Qtab_name, parms); + + name = NILP (name) ? make_string (" tab", 4) : XCDR (name); + + tab_name = Fcons (Qtab_name, name); + tab_object[0] = NILP (tab_name) ? Qnil:Fcons (tab_name, Qnil); + tab_object[1] = NILP (activatecode) ? Qnil: Fcons (activatecode, Qnil); + tab_object[2] = NILP (deactivatecode) ? Qnil:Fcons (deactivatecode, Qnil); + tab_object[3] = NILP (env) ? Qnil:Fcons (env, Qnil); + tab = Fappend ( 4, tab_object ); + + /* ASET (sf->tab_bar_items, sf->last_tab++, tab); */ + Lisp_Object new[2]; + new[0] = sf->tab_bar_items; + new[1] = Fcons (tab, Qnil); + + sf->tab_bar_items = Fappend ( 2, new); + + initcode = Fassq (Qtab_init, parms); + + /* sf->last_tab++; */ + return make_number (sf->last_tab++); +} + DEFUN ("make-terminal-frame", Fmake_terminal_frame, Smake_terminal_frame, 1, 1, 0, doc: /* Create an additional terminal frame, possibly on another terminal. @@ -674,6 +862,13 @@ affects all frames on the same terminal device. */) Lisp_Object frame, tem; struct frame *sf = SELECTED_FRAME (); + Lisp_Object tab; + + tab = Fassq (Qtab, parms); + if (! EQ (Qnil, tab)) + return add_tab (parms); + + #ifdef MSDOS if (sf->output_method != output_msdos_raw && sf->output_method != output_termcap) @@ -2286,9 +2481,15 @@ store_frame_param (struct frame *f, Lisp_Object prop, Lisp_Object val) if (! FRAME_WINDOW_P (f)) { if (EQ (prop, Qmenu_bar_lines)) - set_menu_bar_lines (f, val, make_number (FRAME_MENU_BAR_LINES (f))); + set_menu_bar_lines (f, val, make_number (FRAME_MENU_BAR_LINES (f))); + else if (EQ (prop, Qtab_bar_lines)) + set_tab_bar_lines (f, val); else if (EQ (prop, Qname)) set_term_frame_name (f, val); + else if (EQ (prop, Qcurrent_tab)) + set_current_tab (f, val); + else if (EQ (prop, Qtab_env)) + add_tab_environment (f, val); } if (EQ (prop, Qminibuffer) && WINDOWP (val)) @@ -2394,11 +2595,19 @@ If FRAME is omitted, return information on the currently selected frame. */) #endif { /* This ought to be correct in f->param_alist for an X frame. */ - Lisp_Object lines; + Lisp_Object lines, tabenv; XSETFASTINT (lines, FRAME_MENU_BAR_LINES (f)); store_in_alist (&alist, Qmenu_bar_lines, lines); + XSETFASTINT (lines, FRAME_TAB_BAR_LINES (f)); + store_in_alist (&alist, Qtab_bar_lines, lines); + XSETFASTINT (lines, FRAME_CURRENT_TAB (f)); + store_in_alist (&alist, Qcurrent_tab, lines); + tabenv= Fcdr ( Fassq (Qtab_env, + Fnth (make_number (f->current_tab), f->tab_bar_items))); + store_in_alist (&alist, Qtab_env, tabenv); + /* provide an informal reference to tabs. */ + store_in_alist (&alist, Qtab_list, f->tab_bar_items); } - UNGCPRO; return alist; } @@ -2822,6 +3031,9 @@ static const struct frame_parm_table frame_parms[] = {"icon-type", &Qicon_type}, {"internal-border-width", &Qinternal_border_width}, {"menu-bar-lines", &Qmenu_bar_lines}, + {"tab-bar-lines", &Qtab_bar_lines}, + {"current-tab", &Qcurrent_tab}, + {"tab-list", &Qtab_list}, {"mouse-color", &Qmouse_color}, {"name", &Qname}, {"scroll-bar-width", &Qscroll_bar_width}, @@ -4443,6 +4655,22 @@ syms_of_frame (void) Qterminal_live_p = intern_c_string ("terminal-live-p"); staticpro (&Qterminal_live_p); + Qtab = intern_c_string ("tab"); + staticpro (&Qtab); + + Qtab_env = intern_c_string ("tab:env"); + staticpro (&Qtab_env); + + Qtab_name = intern_c_string ("tab:name"); + staticpro (&Qtab_name); + + Qtab_activate = intern_c_string ("tab:activate"); + staticpro (&Qtab_activate); + Qtab_deactivate = intern_c_string ("tab:deactivate"); + staticpro (&Qtab_deactivate); + Qtab_init = intern_c_string ("tab:init"); + staticpro (&Qtab_init); + #ifdef HAVE_NS Qns_parse_geometry = intern_c_string ("ns-parse-geometry"); staticpro (&Qns_parse_geometry); diff --git a/src/frame.h b/src/frame.h index 31f6017..3110fd4 100644 --- a/src/frame.h +++ b/src/frame.h @@ -171,6 +171,12 @@ struct frame Only the X toolkit version uses this. */ Lisp_Object menu_bar_vector; + /* + * a list with conses of the form ("string_tab_name" . (alist_tab_parameters)) + */ + Lisp_Object tab_bar_items; + + /* Predicate for selecting buffers for other-buffer. */ Lisp_Object buffer_predicate; @@ -203,6 +209,13 @@ struct frame /* Cache of realized faces. */ struct face_cache *face_cache; + /* + the index of the last activated tab. + */ + int current_tab; + + int last_tab; + /* Number of elements in `menu_bar_vector' that have meaningful data. */ EMACS_INT menu_bar_items_used; @@ -360,6 +373,8 @@ struct frame /* Number of lines of menu bar. */ int menu_bar_lines; + int tab_bar_lines; + #if defined (USE_X_TOOLKIT) || defined (HAVE_NTGUI) \ || defined (HAVE_NS) || defined (USE_GTK) /* Nonzero means using a menu bar that comes from the X toolkit. */ @@ -590,6 +605,11 @@ typedef struct frame *FRAME_PTR; These lines are counted in FRAME_LINES. */ #define FRAME_MENU_BAR_LINES(f) (f)->menu_bar_lines +#define FRAME_CURRENT_TAB(f) f -> current_tab +#define FRAME_TAB_BAR_ITEMS(f) f -> tab_bar_items +#define FRAME_TAB_BAR_LINES(f) f -> tab_bar_lines + + /* Nonzero if this frame should display a tool bar in a way that does not use any text lines. */ #if defined (USE_GTK) || defined (HAVE_NS) @@ -606,7 +626,7 @@ typedef struct frame *FRAME_PTR; /* Lines above the top-most window in frame F. */ #define FRAME_TOP_MARGIN(F) \ - (FRAME_MENU_BAR_LINES (F) + FRAME_TOOL_BAR_LINES (F)) + (FRAME_MENU_BAR_LINES (F) + FRAME_TOOL_BAR_LINES (F) + FRAME_TAB_BAR_LINES(F)) /* Pixel height of the top margin above. */ @@ -832,13 +852,18 @@ typedef struct frame *FRAME_PTR; supported. An alternate definition of the macro would expand to something which executes the statement once. */ +#define FOR_EACH_TAB(frame, list_var, tab_var) \ + for ((list_var) = frame->tab_bar_items; \ + (CONSP (list_var) \ + && (tab_var = XCAR (list_var), 1)); \ + list_var = XCDR (list_var)) + #define FOR_EACH_FRAME(list_var, frame_var) \ for ((list_var) = Vframe_list; \ (CONSP (list_var) \ - && (frame_var = XCAR (list_var), 1)); \ + && (frame_var = XCAR (list_var), 1)); \ list_var = XCDR (list_var)) - extern Lisp_Object Qframep, Qframe_live_p; extern Lisp_Object Qtty, Qtty_type; extern Lisp_Object Qtty_color_mode; diff --git a/src/window.c b/src/window.c index a2a0c79..7096488 100644 --- a/src/window.c +++ b/src/window.c @@ -5832,6 +5832,7 @@ struct save_window_data int frame_cols, frame_lines, frame_menu_bar_lines; int frame_tool_bar_lines; + int frame_tab_bar_lines; }; /* This is saved as a Lisp_Vector */ @@ -5963,6 +5964,7 @@ the return value is nil. Otherwise the value is t. */) int previous_frame_cols = FRAME_COLS (f); int previous_frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f); int previous_frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f); + int previous_frame_tab_bar_lines = FRAME_TAB_BAR_LINES (f); /* The mouse highlighting code could get screwed up if it runs during this. */ @@ -6414,6 +6416,7 @@ redirection (see `redirect-frame-focus'). */) data->frame_lines = FRAME_LINES (f); data->frame_menu_bar_lines = FRAME_MENU_BAR_LINES (f); data->frame_tool_bar_lines = FRAME_TOOL_BAR_LINES (f); + data->frame_tab_bar_lines = FRAME_TAB_BAR_LINES (f); data->selected_frame = selected_frame; data->current_window = FRAME_SELECTED_WINDOW (f); XSETBUFFER (data->current_buffer, current_buffer); @@ -6910,6 +6913,8 @@ compare_window_configurations (Lisp_Object c1, Lisp_Object c2, int ignore_positi return 0; if (d1->frame_menu_bar_lines != d2->frame_menu_bar_lines) return 0; + if (d1->frame_tab_bar_lines != d2->frame_tab_bar_lines) + return 0; if (! EQ (d1->selected_frame, d2->selected_frame)) return 0; /* Don't compare the current_window field directly. diff --git a/src/xdisp.c b/src/xdisp.c index 77e9db2..bbd8bd3 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -330,6 +330,8 @@ Lisp_Object Qinhibit_eval_during_redisplay; Lisp_Object Qbuffer_position, Qposition, Qobject; Lisp_Object Qright_to_left, Qleft_to_right; +Lisp_Object Qtab_name; + /* Cursor shapes */ Lisp_Object Qbar, Qhbar, Qbox, Qhollow; @@ -1059,6 +1061,8 @@ static int store_mode_line_string (const char *, Lisp_Object, int, int, int, Lis static const char *decode_mode_spec (struct window *, int, int, int, Lisp_Object *); static void display_menu_bar (struct window *); +static void display_tab_bar (struct window *w); + static int display_count_lines (EMACS_INT, EMACS_INT, EMACS_INT, int, EMACS_INT *); static int display_string (const unsigned char *, Lisp_Object, Lisp_Object, @@ -14575,6 +14579,7 @@ redisplay_window (Lisp_Object window, int just_this_one_p) && EQ (FRAME_SELECTED_WINDOW (f), window)) { int redisplay_menu_p = 0; + int redisplay_tab_p = 0; int redisplay_tool_bar_p = 0; if (FRAME_WINDOW_P (f)) @@ -14589,9 +14594,14 @@ redisplay_window (Lisp_Object window, int just_this_one_p) else redisplay_menu_p = FRAME_MENU_BAR_LINES (f) > 0; + redisplay_tab_p = FRAME_TAB_BAR_LINES (f) > 0; + if (redisplay_menu_p) display_menu_bar (w); + if (redisplay_tab_p) + display_tab_bar (w); + #ifdef HAVE_WINDOW_SYSTEM if (FRAME_WINDOW_P (f)) { @@ -18176,6 +18186,75 @@ See also `bidi-paragraph-direction'. */) } } +void +display_tab_bar (struct window *w) +{ + const int tab_length = 10; + + struct frame *fr = XFRAME (WINDOW_FRAME (w)); + + struct it it; + int index; + init_iterator (&it, w, -1, -1, + fr->desired_matrix->rows + FRAME_MENU_BAR_LINES (fr), + DEFAULT_FACE_ID); + it.first_visible_x = 0; + it.last_visible_x = FRAME_COLS (fr); + + /* Clear all rows of the menu bar. */ + for (index = 0; + index < FRAME_TAB_BAR_LINES (fr); + ++index) + { + struct glyph_row *row = it.glyph_row + index; + clear_glyph_row (row); + row->enabled_p = 1; + row->full_width_p = 1; + } + + int ii=0, oddrow=0, oddcol=0; + Lisp_Object tab, tab_list, s; + FOR_EACH_TAB (fr, tab_list, tab) + { + Lisp_Object tabname = Fcdr (Fassq (Qtab_name, tab)); + if (it. hpos + tab_length > FRAME_COLS (fr)) + { + /* Fill out the line with spaces. */ + it.base_face_id = DEFAULT_FACE_ID; + while (it.current_x < it.last_visible_x) + display_string (" ", Qnil, Qnil, 0, 0, &it, 1, 0, 0, -1); + + if (unix == (it.current_y + 1)) + oddcol = ii % 2; + + oddrow = (oddcol)? (ii%2) : !oddrow; + + it.hpos = it.current_x = 0; + it.current_y ++; + ++it.vpos; + it.glyph_row++; + if (it.current_y > FRAME_TAB_BAR_LINES (fr)) + break; + } + + it.base_face_id = (ii == FRAME_CURRENT_TAB (fr)) ? CURRENT_TAB_FACE_ID : + oddrow ? ODD_TAB_FACE_ID : + EVEN_TAB_FACE_ID; + + int len = SCHARS (tabname) > tab_length ? tab_length: SCHARS (tabname); + s = Fsubstring (tabname, make_number(0), make_number (len)); + display_string (NULL, s, Qnil, 0, 0, &it, tab_length, 0, 0, -1); + + oddrow = ! oddrow; + ii++; + } + + + /* Compute the total height of the lines. */ + compute_line_metrics (&it); + +} + /*********************************************************************** diff --git a/src/xfaces.c b/src/xfaces.c index 5c7cfe6..3e14a64 100644 --- a/src/xfaces.c +++ b/src/xfaces.c @@ -348,6 +348,7 @@ Lisp_Object Qframe_set_background_mode; Lisp_Object Qdefault, Qtool_bar, Qregion, Qfringe; Lisp_Object Qheader_line, Qscroll_bar, Qcursor, Qborder, Qmouse, Qmenu; Lisp_Object Qmode_line_inactive, Qvertical_border; +Lisp_Object Qodd_tab_face, Qeven_tab_face, Qcurrent_tab_face; /* The symbol `face-alias'. A symbols having that property is an alias for another face. Value of the property is the name of @@ -5389,6 +5390,9 @@ realize_basic_faces (struct frame *f) realize_named_face (f, Qmouse, MOUSE_FACE_ID); realize_named_face (f, Qmenu, MENU_FACE_ID); realize_named_face (f, Qvertical_border, VERTICAL_BORDER_FACE_ID); + realize_named_face (f, Qcurrent_tab_face, CURRENT_TAB_FACE_ID); + realize_named_face (f, Qodd_tab_face, ODD_TAB_FACE_ID); + realize_named_face (f, Qeven_tab_face, EVEN_TAB_FACE_ID); /* Reflect changes in the `menu' face in menu bars. */ if (FRAME_FACE_CACHE (f)->menu_face_changed_p) @@ -6659,6 +6663,12 @@ syms_of_xfaces (void) staticpro (&Qmode_line_inactive); Qvertical_border = intern_c_string ("vertical-border"); staticpro (&Qvertical_border); + Qcurrent_tab_face = intern ("current-tab-face"); + staticpro (&Qcurrent_tab_face); + Qodd_tab_face = intern ("odd-tab-face"); + staticpro (&Qodd_tab_face); + Qeven_tab_face = intern ("even-tab-face"); + staticpro (&Qeven_tab_face); Qtty_color_desc = intern_c_string ("tty-color-desc"); staticpro (&Qtty_color_desc); Qtty_color_standard_values = intern_c_string ("tty-color-standard-values"); -- 1.7.1