From 3ecdbb0c879ebcf6d011211d14d89392993fd503 Mon Sep 17 00:00:00 2001 From: root Date: Thu, 2 Dec 2010 23:53:41 +0200 Subject: [PATCH] tabs for console --- src/dispextern.h | 3 + src/frame.c | 224 ++++++++++++++++++++++++++++++++++++++++++++++++++++-- src/frame.h | 25 +++++- src/window.c | 5 + src/xdisp.c | 76 ++++++++++++++++++ src/xfaces.c | 10 +++ 6 files changed, 333 insertions(+), 10 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..a012066 100644 --- a/src/frame.c +++ b/src/frame.c @@ -118,16 +118,19 @@ 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_code_init, Qtab_code_activate, Qtab_code_deactivate; 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 +200,146 @@ 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, tab, dummy; + + if (FRAME_MINIBUF_ONLY_P (f)) + return; + + XSETFRAME(frame, f); + + if (INTEGERP (value)) + nlines = XINT (value); + else + nlines = 0; + + maxlines = FRAME_LINES (f) - 3 - /* editline + modeline + minibuf line = 3 */ + FRAME_MENU_BAR_LINES (f) - + FRAME_TOOL_BAR_LINES (f); + + (nlines > maxlines) && (nlines = maxlines); + + 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) = tab_index; + + tab = XCDR (AREF ( f->tab_bar_items, f->current_tab ) ) ; + + activatecode = Fassq (Qtab_activate, tab); + + if (! EQ (Qnil, activatecode)) + { + activatecode = XCDR (activatecode); + return (void) Ffuncall (1, &activatecode); + } + +} + +void +deactivate_tab (struct frame *f) +{ + Lisp_Object deactivatecode, tab; + + tab = XCDR (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 (ASIZE (FRAME_TAB_BAR_ITEMS (f)) <= tab) + 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, tab); + adjust_glyphs (f); + } + +} + + Lisp_Object Vframe_list; @@ -348,6 +491,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 +717,6 @@ make_initial_frame (void) return f; } - struct frame * make_terminal_frame (struct terminal *terminal) { @@ -650,6 +796,44 @@ get_future_frame_param (Lisp_Object parameter, return result; } +Lisp_Object +add_tab (Lisp_Object parms) +{ + Lisp_Object tab, initcode, activatecode, deactivatecode; + + Lisp_Object tab_object[4]; + + + struct frame *sf = SELECTED_FRAME (); + if (sf->last_tab == 1000) + return; + char tab_name[]=" tab"; + + if (NILP (sf->tab_bar_items)) + sf->tab_bar_items = Fmake_vector (make_number (1000), Qnil); + + activatecode = Fassq (Qtab_activate, parms); + deactivatecode = Fassq (Qtab_deactivate, parms); + + //tab = Fcons (make_string (tab_name, sizeof (tab_name)-1), Qnil); + tab_object[0] = make_string (tab_name, sizeof (tab_name)-1); + tab_object[1] = activatecode; + tab_object[2] = deactivatecode; + tab = Flist ( 3, tab_object ); + + ASET (sf->tab_bar_items, sf->last_tab++, tab); + + initcode = Fassq (Qtab_init, parms); + + if (! EQ (Qnil, initcode)) + { + initcode = XCDR (initcode); + return Ffuncall (1, &initcode); + } + + return Qnil; +} + DEFUN ("make-terminal-frame", Fmake_terminal_frame, Smake_terminal_frame, 1, 1, 0, doc: /* Create an additional terminal frame, possibly on another terminal. @@ -674,10 +858,17 @@ 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) - abort (); + abort (); #else /* not MSDOS */ #ifdef WINDOWSNT /* This should work now! */ @@ -2286,9 +2477,13 @@ 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); } if (EQ (prop, Qminibuffer) && WINDOWP (val)) @@ -2394,11 +2589,14 @@ 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, items; 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); } - UNGCPRO; return alist; } @@ -2822,6 +3020,8 @@ 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}, {"mouse-color", &Qmouse_color}, {"name", &Qname}, {"scroll-bar-width", &Qscroll_bar_width}, @@ -4443,6 +4643,16 @@ 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_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..b9084a2 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. */ @@ -835,10 +855,9 @@ typedef struct frame *FRAME_PTR; #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..1865eb0 100644 --- a/src/xdisp.c +++ b/src/xdisp.c @@ -1059,6 +1059,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 +14577,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 +14592,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 +18184,74 @@ 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, s; + while (!NILP (tab = AREF (fr->tab_bar_items, ii))) + { + 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 (XCAR(tab)) > tab_length ? tab_length: SCHARS (XCAR (tab)); + s = Fsubstring (XCAR (tab), 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