aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEli Zaretskii2012-06-02 17:57:51 +0300
committerEli Zaretskii2012-06-02 17:57:51 +0300
commitb5e9cbb6fdce4b7e8c5cd6ad1addf6e4af35da67 (patch)
treec6a1b2060e5d56677f6785c2241311527fa917fa
parentf51b6486fc8b0e3fa7fd08cbf83b27ef0d5efe1a (diff)
downloademacs-b5e9cbb6fdce4b7e8c5cd6ad1addf6e4af35da67.tar.gz
emacs-b5e9cbb6fdce4b7e8c5cd6ad1addf6e4af35da67.zip
Initial incomplete version of tty menus. tty_menu_activate not done yet.
-rw-r--r--src/dispextern.h55
-rw-r--r--src/dispnew.c33
-rw-r--r--src/menu.c29
-rw-r--r--src/menu.h2
-rw-r--r--src/msdos.c7
-rw-r--r--src/term.c801
-rw-r--r--src/termhooks.h6
-rw-r--r--src/w32console.c15
-rw-r--r--src/window.c29
-rw-r--r--src/xdisp.c71
10 files changed, 998 insertions, 50 deletions
diff --git a/src/dispextern.h b/src/dispextern.h
index 979ade70bfc..65df553c831 100644
--- a/src/dispextern.h
+++ b/src/dispextern.h
@@ -3115,6 +3115,7 @@ extern int clear_mouse_face (Mouse_HLInfo *);
3115extern int cursor_in_mouse_face_p (struct window *w); 3115extern int cursor_in_mouse_face_p (struct window *w);
3116extern void tty_draw_row_with_mouse_face (struct window *, struct glyph_row *, 3116extern void tty_draw_row_with_mouse_face (struct window *, struct glyph_row *,
3117 int, int, enum draw_glyphs_face); 3117 int, int, enum draw_glyphs_face);
3118extern void display_tty_menu_item (const char *, int, int, int, int);
3118 3119
3119/* Flags passed to try_window. */ 3120/* Flags passed to try_window. */
3120#define TRY_WINDOW_CHECK_MARGINS (1 << 0) 3121#define TRY_WINDOW_CHECK_MARGINS (1 << 0)
@@ -3278,6 +3279,8 @@ extern void hide_hourglass (void);
3278 3279
3279int popup_activated (void); 3280int popup_activated (void);
3280 3281
3282/* Defined in dispnew.c */
3283
3281extern Lisp_Object buffer_posn_from_coords (struct window *, 3284extern Lisp_Object buffer_posn_from_coords (struct window *,
3282 int *, int *, 3285 int *, int *,
3283 struct display_pos *, 3286 struct display_pos *,
@@ -3292,35 +3295,35 @@ extern Lisp_Object marginal_area_string (struct window *, enum window_part,
3292 Lisp_Object *, 3295 Lisp_Object *,
3293 int *, int *, int *, int *); 3296 int *, int *, int *, int *);
3294extern void redraw_frame (struct frame *); 3297extern void redraw_frame (struct frame *);
3295extern void cancel_line (int, struct frame *);
3296extern void init_desired_glyphs (struct frame *);
3297extern int update_frame (struct frame *, int, int); 3298extern int update_frame (struct frame *, int, int);
3299extern void update_frame_with_menu (struct frame *);
3298extern void bitch_at_user (void); 3300extern void bitch_at_user (void);
3299void adjust_glyphs (struct frame *); 3301extern void adjust_glyphs (struct frame *);
3300void free_glyphs (struct frame *); 3302extern void free_glyphs (struct frame *);
3301void free_window_matrices (struct window *); 3303extern void free_window_matrices (struct window *);
3302void check_glyph_memory (void); 3304extern void check_glyph_memory (void);
3303void mirrored_line_dance (struct glyph_matrix *, int, int, int *, char *); 3305extern void mirrored_line_dance (struct glyph_matrix *, int, int, int *,
3304void clear_glyph_matrix (struct glyph_matrix *); 3306 char *);
3305void clear_current_matrices (struct frame *f); 3307extern void clear_glyph_matrix (struct glyph_matrix *);
3306void clear_desired_matrices (struct frame *); 3308extern void clear_current_matrices (struct frame *f);
3307void shift_glyph_matrix (struct window *, struct glyph_matrix *, 3309extern void clear_desired_matrices (struct frame *);
3308 int, int, int); 3310extern void shift_glyph_matrix (struct window *, struct glyph_matrix *,
3309void rotate_matrix (struct glyph_matrix *, int, int, int); 3311 int, int, int);
3310void increment_matrix_positions (struct glyph_matrix *, 3312extern void rotate_matrix (struct glyph_matrix *, int, int, int);
3311 int, int, ptrdiff_t, ptrdiff_t); 3313extern void increment_matrix_positions (struct glyph_matrix *,
3312void blank_row (struct window *, struct glyph_row *, int); 3314 int, int, ptrdiff_t, ptrdiff_t);
3313void enable_glyph_matrix_rows (struct glyph_matrix *, int, int, int); 3315extern void blank_row (struct window *, struct glyph_row *, int);
3314void clear_glyph_row (struct glyph_row *); 3316extern void enable_glyph_matrix_rows (struct glyph_matrix *, int, int, int);
3315void prepare_desired_row (struct glyph_row *); 3317extern void clear_glyph_row (struct glyph_row *);
3316void set_window_update_flags (struct window *, int); 3318extern void prepare_desired_row (struct glyph_row *);
3317void update_single_window (struct window *, int); 3319extern void set_window_update_flags (struct window *, int);
3318void do_pending_window_change (int); 3320extern void update_single_window (struct window *, int);
3319void change_frame_size (struct frame *, int, int, int, int, int); 3321extern void do_pending_window_change (int);
3320void init_display (void); 3322extern void change_frame_size (struct frame *, int, int, int, int, int);
3321void syms_of_display (void); 3323extern void init_display (void);
3324extern void syms_of_display (void);
3322extern Lisp_Object Qredisplay_dont_pause; 3325extern Lisp_Object Qredisplay_dont_pause;
3323void spec_glyph_lookup_face (struct window *, GLYPH *); 3326extern void spec_glyph_lookup_face (struct window *, GLYPH *);
3324 3327
3325/* Defined in terminal.c */ 3328/* Defined in terminal.c */
3326 3329
diff --git a/src/dispnew.c b/src/dispnew.c
index a23f2b9a959..0c975124479 100644
--- a/src/dispnew.c
+++ b/src/dispnew.c
@@ -3337,6 +3337,39 @@ update_frame (struct frame *f, int force_p, int inhibit_hairy_id_p)
3337 return paused_p; 3337 return paused_p;
3338} 3338}
3339 3339
3340/* Update a TTY frame F that has a menu dropped down over some of its
3341 glyphs. This is like the second part of update_frame, but it
3342 doesn't call build_frame_matrix, because we already have the
3343 desired matrix prepared, and don't want it to be overwritten by the
3344 text of the normal display. */
3345void
3346update_frame_with_menu (struct frame *f)
3347{
3348 struct window *root_window = XWINDOW (f->root_window);
3349
3350 xassert (FRAME_TERMCAP_P (f));
3351
3352 /* We are working on frame matrix basis. Set the frame on whose
3353 frame matrix we operate. */
3354 set_frame_matrix_frame (f);
3355
3356 /* Update the display */
3357 update_begin (f);
3358 paused_p = update_frame_1 (f, 1, 1);
3359 update_end (f);
3360
3361 if (FRAME_TTY (f)->termscript)
3362 fflush (FRAME_TTY (f)->termscript);
3363 fflush (FRAME_TTY (f)->output);
3364 /* Check window matrices for lost pointers. */
3365#if GLYPH_DEBUG
3366 check_window_matrix_pointers (root_window);
3367 add_frame_display_history (f, paused_p);
3368#endif
3369
3370 /* Reset flags indicating that a window should be updated. */
3371 set_window_update_flags (root_window, 0);
3372}
3340 3373
3341 3374
3342/************************************************************************ 3375/************************************************************************
diff --git a/src/menu.c b/src/menu.c
index 9ccfffd768c..7a7db9f07ff 100644
--- a/src/menu.c
+++ b/src/menu.c
@@ -1323,20 +1323,31 @@ no quit occurs and `x-popup-menu' returns nil. */)
1323 1323
1324 /* FIXME: Use a terminal hook! */ 1324 /* FIXME: Use a terminal hook! */
1325#if defined HAVE_NTGUI 1325#if defined HAVE_NTGUI
1326 selection = w32_menu_show (f, xpos, ypos, for_click, 1326 if (FRAME_W32_P (f))
1327 keymaps, title, &error_name); 1327 selection = w32_menu_show (f, xpos, ypos, for_click,
1328#elif defined HAVE_NS 1328 keymaps, title, &error_name);
1329 selection = ns_menu_show (f, xpos, ypos, for_click, 1329 else
1330 keymaps, title, &error_name); 1330#endif
1331#else /* MSDOS and X11 */ 1331#if defined HAVE_NS
1332 if (FRAME_NS_P (f))
1333 selection = ns_menu_show (f, xpos, ypos, for_click,
1334 keymaps, title, &error_name);
1335 else
1336#endif
1337#if (defined (HAVE_X_WINDOWS) || defined (MSDOS))
1332 /* Assume last_event_timestamp is the timestamp of the button event. 1338 /* Assume last_event_timestamp is the timestamp of the button event.
1333 Is this assumption ever violated? We can't use the timestamp 1339 Is this assumption ever violated? We can't use the timestamp
1334 stored within POSITION because there the top bits from the actual 1340 stored within POSITION because there the top bits from the actual
1335 timestamp may be truncated away (Bug#4930). */ 1341 timestamp may be truncated away (Bug#4930). */
1336 selection = xmenu_show (f, xpos, ypos, for_click, 1342 if (FRAME_X_P (f) || FRAME_MSDOS_P (f))
1337 keymaps, title, &error_name, 1343 selection = xmenu_show (f, xpos, ypos, for_click,
1338 last_event_timestamp); 1344 keymaps, title, &error_name,
1345 last_event_timestamp);
1346 else
1339#endif 1347#endif
1348 if (FRAME_TERMCAP_P (f))
1349 selection = tty_menu_show (f, xpos, ypos, for_click,
1350 keymaps, title, &error_name);
1340 1351
1341 UNBLOCK_INPUT; 1352 UNBLOCK_INPUT;
1342 1353
diff --git a/src/menu.h b/src/menu.h
index cb22a5255d6..12b2fcc6a7d 100644
--- a/src/menu.h
+++ b/src/menu.h
@@ -51,4 +51,6 @@ extern Lisp_Object ns_menu_show (FRAME_PTR, int, int, int, int,
51 Lisp_Object, const char **); 51 Lisp_Object, const char **);
52extern Lisp_Object xmenu_show (FRAME_PTR, int, int, int, int, 52extern Lisp_Object xmenu_show (FRAME_PTR, int, int, int, int,
53 Lisp_Object, const char **, Time); 53 Lisp_Object, const char **, Time);
54extern Lisp_Object tty_menu_show (FRAME_PTR, int, int, int, int,
55 Lisp_Object, const char **);
54#endif /* MENU_H */ 56#endif /* MENU_H */
diff --git a/src/msdos.c b/src/msdos.c
index c6213b566b8..95d16438005 100644
--- a/src/msdos.c
+++ b/src/msdos.c
@@ -1389,13 +1389,6 @@ IT_delete_glyphs (struct frame *f, int n)
1389 abort (); 1389 abort ();
1390} 1390}
1391 1391
1392/* set-window-configuration on window.c needs this. */
1393void
1394x_set_menu_bar_lines (struct frame *f, Lisp_Object value, Lisp_Object oldval)
1395{
1396 set_menu_bar_lines (f, value, oldval);
1397}
1398
1399/* This was copied from xfaces.c */ 1392/* This was copied from xfaces.c */
1400 1393
1401extern Lisp_Object Qbackground_color; 1394extern Lisp_Object Qbackground_color;
diff --git a/src/term.c b/src/term.c
index 3d7a677374c..188c476961b 100644
--- a/src/term.c
+++ b/src/term.c
@@ -58,6 +58,10 @@ static int been_here = -1;
58#include "xterm.h" 58#include "xterm.h"
59#endif 59#endif
60 60
61#ifdef HAVE_MENUS
62#include "menu.h"
63#endif
64
61#ifndef O_RDWR 65#ifndef O_RDWR
62#define O_RDWR 2 66#define O_RDWR 2
63#endif 67#endif
@@ -2834,6 +2838,803 @@ DEFUN ("gpm-mouse-stop", Fgpm_mouse_stop, Sgpm_mouse_stop,
2834#endif /* HAVE_GPM */ 2838#endif /* HAVE_GPM */
2835 2839
2836 2840
2841/***********************************************************************
2842 Menus
2843 ***********************************************************************/
2844
2845#if defined (HAVE_MENUS) && !defined (MSDOS)
2846
2847/* TTY menu implementation and main ideas are borrowed from msdos.c.
2848
2849 However, unlike on MSDOS, where the menu text is drawn directly to
2850 the screen, on a TTY we use display_string (see xdisp.c) to put the
2851 glyphs produced from the menu items into the desired_matrix glyph
2852 matrix, and then call update_frame to deliver the results to the
2853 glass. The previous contents of the screen, in the form of the
2854 current_matrix, is stashed away, and used to restore screen
2855 contents when the menu selection changes or when the final
2856 selection is made and the menu should be popped down.
2857
2858 The idea of this implementation was suggested by Gerd Moellmann. */
2859
2860#define TTYM_FAILURE -1
2861#define TTYM_SUCCESS 1
2862#define TTYM_NO_SELECT 2
2863#define TTYM_IA_SELECT 3
2864
2865/* These hold text of the current and the previous menu help messages. */
2866static const char *menu_help_message, *prev_menu_help_message;
2867/* Pane number and item number of the menu item which generated the
2868 last menu help message. */
2869static int menu_help_paneno, menu_help_itemno;
2870
2871typedef struct tty_menu_struct
2872{
2873 int count;
2874 char **text;
2875 struct tty_menu_struct **submenu;
2876 int *panenumber; /* Also used as enable. */
2877 int allocated;
2878 int panecount;
2879 int width;
2880 const char **help_text;
2881} tty_menu;
2882
2883/* Create a brand new menu structure. */
2884
2885static tty_menu *
2886tty_menu_create (void)
2887{
2888 tty_menu *menu;
2889
2890 menu = (tty_menu *) xmalloc (sizeof (tty_menu));
2891 menu->allocated = menu->count = menu->panecount = menu->width = 0;
2892 return menu;
2893}
2894
2895/* Allocate some (more) memory for MENU ensuring that there is room for one
2896 for item. */
2897
2898static void
2899tty_menu_make_room (tty_menu *menu)
2900{
2901 if (menu->allocated == 0)
2902 {
2903 int count = menu->allocated = 10;
2904 menu->text = (char **) xmalloc (count * sizeof (char *));
2905 menu->submenu = (tty_menu **) xmalloc (count * sizeof (tty_menu *));
2906 menu->panenumber = (int *) xmalloc (count * sizeof (int));
2907 menu->help_text = (const char **) xmalloc (count * sizeof (char *));
2908 }
2909 else if (menu->allocated == menu->count)
2910 {
2911 int count = menu->allocated = menu->allocated + 10;
2912 menu->text
2913 = (char **) xrealloc (menu->text, count * sizeof (char *));
2914 menu->submenu
2915 = (tty_menu **) xrealloc (menu->submenu, count * sizeof (tty_menu *));
2916 menu->panenumber
2917 = (int *) xrealloc (menu->panenumber, count * sizeof (int));
2918 menu->help_text
2919 = (const char **) xrealloc (menu->help_text, count * sizeof (char *));
2920 }
2921}
2922
2923/* Search the given menu structure for a given pane number. */
2924
2925static tty_menu *
2926tty_menu_search_pane (tty_menu *menu, int pane)
2927{
2928 int i;
2929 tty_menu *try;
2930
2931 for (i = 0; i < menu->count; i++)
2932 if (menu->submenu[i])
2933 {
2934 if (pane == menu->panenumber[i])
2935 return menu->submenu[i];
2936 if ((try = tty_menu_search_pane (menu->submenu[i], pane)))
2937 return try;
2938 }
2939 return (tty_menu *) 0;
2940}
2941
2942/* Determine how much screen space a given menu needs. */
2943
2944static void
2945tty_menu_calc_size (tty_menu *menu, int *width, int *height)
2946{
2947 int i, h2, w2, maxsubwidth, maxheight;
2948
2949 maxsubwidth = 0;
2950 maxheight = menu->count;
2951 for (i = 0; i < menu->count; i++)
2952 {
2953 if (menu->submenu[i])
2954 {
2955 tty_menu_calc_size (menu->submenu[i], &w2, &h2);
2956 if (w2 > maxsubwidth) maxsubwidth = w2;
2957 if (i + h2 > maxheight) maxheight = i + h2;
2958 }
2959 }
2960 *width = menu->width + maxsubwidth;
2961 *height = maxheight;
2962}
2963
2964/* Display MENU at (X,Y) using FACES. */
2965
2966#define BUILD_CHAR_GLYPH(GLYPH, CODE, FACE_ID, PADDING_P) \
2967 do \
2968 { \
2969 (GLYPH).type = CHAR_GLYPH; \
2970 SET_CHAR_GLYPH ((GLYPH), CODE, FACE_ID, PADDING_P); \
2971 (GLYPH).charpos = -1; \
2972 } \
2973 while (0)
2974
2975static void
2976tty_menu_display (tty_menu *menu, int y, int x, int pn, int *faces,
2977 int disp_help)
2978{
2979 int i, face, width, mx = -1, my = -1, enabled, mousehere, row, col;
2980 struct frame *sf = SELECTED_FRAME ();
2981 struct tty_display_info *tty = FRAME_TTY (sf);
2982#if defined (HAVE_MOUSE) || defined (HAVE_GPM)
2983 Lisp_Object lmx, lmy, lisp_dummy;
2984 enum scroll_bar_part part_dummy;
2985 Time time_dummy;
2986
2987 if (FRAME_TERMINAL (sf)->mouse_position_hook)
2988 (*FRAME_TERMINAL (sf)->mouse_position_hook) (&sf, -1,
2989 &lispy_dummy, &party_dummy,
2990 &lmx, &lmy,
2991 &time_dummy);
2992 if (!NILP (lmx))
2993 {
2994 mx = XINT (lmx);
2995 my = XINT (lmy);
2996 }
2997 else
2998 {
2999 mx = x;
3000 my = y;
3001 }
3002#else
3003 /* FIXME: need to set mx and my from cursor movement commands. */
3004 mx = x;
3005 my = y;
3006#endif
3007
3008 menu_help_message = NULL;
3009
3010 width = menu->width;
3011 col = curX (tty);
3012 row = curY (tty);
3013#if 0
3014 IT_update_begin (sf); /* FIXME: do we need an update_begin_hook? */
3015#endif
3016 for (i = 0; i < menu->count; i++)
3017 {
3018 int max_width = width + 2;
3019
3020 cursor_to (sf, y + i, x);
3021 enabled
3022 = (!menu->submenu[i] && menu->panenumber[i]) || (menu->submenu[i]);
3023 mousehere = (y + i == my && x <= mx && mx < x + max_width);
3024 face = faces[enabled + mousehere * 2];
3025 /* Display the menu help string for the i-th menu item even if
3026 the menu item is currently disabled. That's what the GUI
3027 code does. */
3028 if (disp_help && enabled + mousehere * 2 >= 2)
3029 {
3030 menu_help_message = menu->help_text[i];
3031 menu_help_paneno = pn - 1;
3032 menu_help_itemno = i;
3033 }
3034 display_tty_menu_item (menu->text[i], face, y + i, x,
3035 menu->submenu[i] != NULL);
3036 }
3037 update_frame_with_menu (sf);
3038 cursor_to (sf, row, col);
3039}
3040
3041/* --------------------------- X Menu emulation ---------------------- */
3042
3043/* Report availability of menus. */
3044
3045int
3046have_menus_p (void) { return 1; }
3047
3048/* Create a new pane and place it on the outer-most level. */
3049
3050int
3051tty_menu_add_pane (Display *foo, tty_menu *menu, const char *txt)
3052{
3053 int len;
3054 const char *p;
3055
3056 tty_menu_make_room (menu);
3057 menu->submenu[menu->count] = tty_menu_create ();
3058 menu->text[menu->count] = (char *)txt;
3059 menu->panenumber[menu->count] = ++menu->panecount;
3060 menu->help_text[menu->count] = NULL;
3061 menu->count++;
3062
3063 /* Update the menu width, if necessary. */
3064 for (len = 0, p = txt; *p; )
3065 {
3066 int ch_len;
3067 int ch = STRING_CHAR_AND_LENGTH (p, ch_len);
3068
3069 len += CHAR_WIDTH (ch);
3070 p += ch_len;
3071 }
3072
3073 if (len > menu->width)
3074 menu->width = len;
3075
3076 return menu->panecount;
3077}
3078
3079/* Create a new item in a menu pane. */
3080
3081int
3082tty_menu_add_selection (tty_menu *menu, int pane,
3083 char *txt, int enable, char const *help_text)
3084{
3085 int len;
3086 char *p;
3087
3088 if (pane)
3089 if (!(menu = tty_menu_search_pane (menu, pane)))
3090 return TTYM_FAILURE;
3091 tty_menu_make_room (menu);
3092 menu->submenu[menu->count] = (tty_menu *) 0;
3093 menu->text[menu->count] = txt;
3094 menu->panenumber[menu->count] = enable;
3095 menu->help_text[menu->count] = help_text;
3096 menu->count++;
3097
3098 /* Update the menu width, if necessary. */
3099 for (len = 0, p = txt; *p; )
3100 {
3101 int ch_len;
3102 int ch = STRING_CHAR_AND_LENGTH (p, ch_len);
3103
3104 len += CHAR_WIDTH (ch);
3105 p += ch_len;
3106 }
3107
3108 if (len > menu->width)
3109 menu->width = len;
3110
3111 return TTYM_SUCCESS;
3112}
3113
3114/* Decide where the menu would be placed if requested at (X,Y). */
3115
3116void
3117tty_menu_locate (tty_menu *menu, int x, int y,
3118 int *ulx, int *uly, int *width, int *height)
3119{
3120 tty_menu_calc_size (menu, width, height);
3121 *ulx = x + 1;
3122 *uly = y;
3123 *width += 2;
3124}
3125
3126struct tty_menu_state
3127{
3128 void *screen_behind;
3129 tty_menu *menu;
3130 int pane;
3131 int x, y;
3132};
3133
3134
3135/* Display menu, wait for user's response, and return that response. */
3136
3137int
3138tty_menu_activate (tty_menu *menu, int *pane, int *selidx,
3139 int x0, int y0, char **txt,
3140 void (*help_callback)(char const *, int, int))
3141{
3142 struct tty_menu_state *state;
3143 int statecount, x, y, i, b, screensize, leave, result, onepane;
3144 int title_faces[4]; /* face to display the menu title */
3145 int faces[4], buffers_num_deleted = 0;
3146 struct frame *sf = SELECTED_FRAME ();
3147 Lisp_Object saved_echo_area_message, selectface;
3148
3149 /* Don't allow non-positive x0 and y0, lest the menu will wrap
3150 around the display. */
3151 if (x0 <= 0)
3152 x0 = 1;
3153 if (y0 <= 0)
3154 y0 = 1;
3155
3156 /* We will process all the mouse events directly, so we had
3157 better prevent dos_rawgetc from stealing them from us. */
3158 mouse_preempted++;
3159
3160 state = alloca (menu->panecount * sizeof (struct tty_menu_state));
3161 screensize = screen_size * 2;
3162 faces[0]
3163 = lookup_derived_face (sf, intern ("tty-menu-disabled-face"),
3164 DEFAULT_FACE_ID, 1);
3165 faces[1]
3166 = lookup_derived_face (sf, intern ("tty-menu-enabled-face"),
3167 DEFAULT_FACE_ID, 1);
3168 selectface = intern ("tty-menu-selected-face");
3169 faces[2] = lookup_derived_face (sf, selectface,
3170 faces[0], 1);
3171 faces[3] = lookup_derived_face (sf, selectface,
3172 faces[1], 1);
3173
3174 /* Make sure the menu title is always displayed with
3175 `msdos-menu-active-face', no matter where the mouse pointer is. */
3176 for (i = 0; i < 4; i++)
3177 title_faces[i] = faces[3];
3178
3179 statecount = 1;
3180
3181 /* Don't let the title for the "Buffers" popup menu include a
3182 digit (which is ugly).
3183
3184 This is a terrible kludge, but I think the "Buffers" case is
3185 the only one where the title includes a number, so it doesn't
3186 seem to be necessary to make this more general. */
3187 if (strncmp (menu->text[0], "Buffers 1", 9) == 0)
3188 {
3189 menu->text[0][7] = '\0';
3190 buffers_num_deleted = 1;
3191 }
3192
3193#if 0
3194 /* We need to save the current echo area message, so that we could
3195 restore it below, before we exit. See the commentary below,
3196 before the call to message_with_string. */
3197 saved_echo_area_message = Fcurrent_message ();
3198#endif
3199 state[0].menu = menu;
3200 mouse_off (); /* FIXME */
3201 ScreenRetrieve (state[0].screen_behind = xmalloc (screensize)); /* FIXME */
3202
3203 /* Turn off the cursor. Otherwise it shows through the menu
3204 panes, which is ugly. */
3205 show_cursor (0); /* FIXME: need a new hook. */
3206
3207 /* Display the menu title. */
3208 tty_menu_display (menu, y0 - 1, x0 - 1, 1, title_faces, 0);
3209 if (buffers_num_deleted)
3210 menu->text[0][7] = ' ';
3211 if ((onepane = menu->count == 1 && menu->submenu[0]))
3212 {
3213 menu->width = menu->submenu[0]->width;
3214 state[0].menu = menu->submenu[0];
3215 }
3216 else
3217 {
3218 state[0].menu = menu;
3219 }
3220 state[0].x = x0 - 1;
3221 state[0].y = y0;
3222 state[0].pane = onepane;
3223
3224 mouse_last_x = -1; /* A hack that forces display. */
3225 leave = 0;
3226 while (!leave)
3227 {
3228 if (!mouse_visible) mouse_on ();
3229 mouse_check_moved ();
3230 if (sf->mouse_moved)
3231 {
3232 sf->mouse_moved = 0;
3233 result = TTYM_IA_SELECT;
3234 mouse_get_xy (&x, &y);
3235 for (i = 0; i < statecount; i++)
3236 if (state[i].x <= x && x < state[i].x + state[i].menu->width + 2)
3237 {
3238 int dy = y - state[i].y;
3239 if (0 <= dy && dy < state[i].menu->count)
3240 {
3241 if (!state[i].menu->submenu[dy])
3242 {
3243 if (state[i].menu->panenumber[dy])
3244 result = TTYM_SUCCESS;
3245 else
3246 result = TTYM_IA_SELECT;
3247 }
3248 *pane = state[i].pane - 1;
3249 *selidx = dy;
3250 /* We hit some part of a menu, so drop extra menus that
3251 have been opened. That does not include an open and
3252 active submenu. */
3253 if (i != statecount - 2
3254 || state[i].menu->submenu[dy] != state[i+1].menu)
3255 while (i != statecount - 1)
3256 {
3257 statecount--;
3258 mouse_off ();
3259 ScreenUpdate (state[statecount].screen_behind);
3260 xfree (state[statecount].screen_behind);
3261 }
3262 if (i == statecount - 1 && state[i].menu->submenu[dy])
3263 {
3264 tty_menu_display (state[i].menu,
3265 state[i].y,
3266 state[i].x,
3267 state[i].pane,
3268 faces, 1);
3269 state[statecount].menu = state[i].menu->submenu[dy];
3270 state[statecount].pane = state[i].menu->panenumber[dy];
3271 mouse_off ();
3272 ScreenRetrieve (state[statecount].screen_behind
3273 = xmalloc (screensize));
3274 state[statecount].x
3275 = state[i].x + state[i].menu->width + 2;
3276 state[statecount].y = y;
3277 statecount++;
3278 }
3279 }
3280 }
3281 tty_menu_display (state[statecount - 1].menu,
3282 state[statecount - 1].y,
3283 state[statecount - 1].x,
3284 state[statecount - 1].pane,
3285 faces, 1);
3286 }
3287 else
3288 {
3289 if ((menu_help_message || prev_menu_help_message)
3290 && menu_help_message != prev_menu_help_message)
3291 {
3292 help_callback (menu_help_message,
3293 menu_help_paneno, menu_help_itemno);
3294 show_cursor (0);
3295 prev_menu_help_message = menu_help_message;
3296 }
3297 /* We are busy-waiting for the mouse to move, so let's be nice
3298 to other Windows applications by releasing our time slice. */
3299 __dpmi_yield ();
3300 }
3301 for (b = 0; b < mouse_button_count && !leave; b++)
3302 {
3303 /* Only leave if user both pressed and released the mouse, and in
3304 that order. This avoids popping down the menu pane unless
3305 the user is really done with it. */
3306 if (mouse_pressed (b, &x, &y))
3307 {
3308 while (mouse_button_depressed (b, &x, &y))
3309 __dpmi_yield ();
3310 leave = 1;
3311 }
3312 (void) mouse_released (b, &x, &y);
3313 }
3314 }
3315
3316 mouse_off ();
3317 ScreenUpdate (state[0].screen_behind);
3318
3319#if 0
3320 /* We have a situation here. ScreenUpdate has just restored the
3321 screen contents as it was before we started drawing this menu.
3322 That includes any echo area message that could have been
3323 displayed back then. (In reality, that echo area message will
3324 almost always be the ``keystroke echo'' that echoes the sequence
3325 of menu items chosen by the user.) However, if the menu had some
3326 help messages, then displaying those messages caused Emacs to
3327 forget about the original echo area message. So when
3328 ScreenUpdate restored it, it created a discrepancy between the
3329 actual screen contents and what Emacs internal data structures
3330 know about it.
3331
3332 To avoid this conflict, we force Emacs to restore the original
3333 echo area message as we found it when we entered this function.
3334 The irony of this is that we then erase the restored message
3335 right away, so the only purpose of restoring it is so that
3336 erasing it works correctly... */
3337 if (! NILP (saved_echo_area_message))
3338 message_with_string ("%s", saved_echo_area_message, 0);
3339 message (0);
3340#endif
3341 while (statecount--)
3342 xfree (state[statecount].screen_behind);
3343 show_cursor (1); /* turn cursor back on */
3344 /* Clean up any mouse events that are waiting inside Emacs event queue.
3345 These events are likely to be generated before the menu was even
3346 displayed, probably because the user pressed and released the button
3347 (which invoked the menu) too quickly. If we don't remove these events,
3348 Emacs will process them after we return and surprise the user. */
3349 discard_mouse_events ();
3350 mouse_clear_clicks ();
3351 if (!kbd_buffer_events_waiting (1))
3352 clear_input_pending ();
3353 /* Allow mouse events generation by dos_rawgetc. */
3354 mouse_preempted--;
3355 return result;
3356}
3357
3358/* Dispose of a menu. */
3359
3360void
3361tty_menu_destroy (tty_menu *menu)
3362{
3363 int i;
3364 if (menu->allocated)
3365 {
3366 for (i = 0; i < menu->count; i++)
3367 if (menu->submenu[i])
3368 tty_menu_destroy (menu->submenu[i]);
3369 xfree (menu->text);
3370 xfree (menu->submenu);
3371 xfree (menu->panenumber);
3372 xfree (menu->help_text);
3373 }
3374 xfree (menu);
3375 menu_help_message = prev_menu_help_message = NULL;
3376}
3377
3378Lisp_Object
3379tty_menu_show (FRAME_PTR f, int x, int y, int for_click, int keymaps,
3380 Lisp_Object title, const char **error_name)
3381{
3382 tty_menu *menu;
3383 int pane, selidx, lpane, status;
3384 Lisp_Object entry, pane_prefix;
3385 char *datap;
3386 int ulx, uly, width, height;
3387 int dispwidth, dispheight;
3388 int i, j, lines, maxlines;
3389 int maxwidth;
3390 int dummy_int;
3391 unsigned int dummy_uint;
3392 ptrdiff_t specpdl_count = SPECPDL_INDEX ();
3393
3394 if (! FRAME_TERMCAP_P (f))
3395 abort ();
3396
3397 *error_name = 0;
3398 if (menu_items_n_panes == 0)
3399 return Qnil;
3400
3401 if (menu_items_used <= MENU_ITEMS_PANE_LENGTH)
3402 {
3403 *error_name = "Empty menu";
3404 return Qnil;
3405 }
3406
3407 /* Make the menu on that window. */
3408 menu = tty_menu_create ();
3409 if (menu == NULL)
3410 {
3411 *error_name = "Can't create menu";
3412 return Qnil;
3413 }
3414
3415 /* Don't GC while we prepare and show the menu, because we give the
3416 menu functions pointers to the contents of strings. */
3417 inhibit_garbage_collection ();
3418
3419 /* Adjust coordinates to be root-window-relative. */
3420 x += f->left_pos;
3421 y += f->top_pos;
3422
3423 /* Create all the necessary panes and their items. */
3424 maxwidth = maxlines = lines = i = 0;
3425 lpane = TTYM_FAILURE;
3426 while (i < menu_items_used)
3427 {
3428 if (EQ (XVECTOR (menu_items)->contents[i], Qt))
3429 {
3430 /* Create a new pane. */
3431 Lisp_Object pane_name, prefix;
3432 const char *pane_string;
3433
3434 maxlines = max (maxlines, lines);
3435 lines = 0;
3436 pane_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_NAME];
3437 prefix = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
3438 pane_string = (NILP (pane_name)
3439 ? "" : SSDATA (pane_name));
3440 if (keymaps && !NILP (prefix))
3441 pane_string++;
3442
3443 lpane = tty_menu_add_pane (menu, pane_string);
3444 if (lpane == TTYM_FAILURE)
3445 {
3446 tty_menu_destroy (menu);
3447 *error_name = "Can't create pane";
3448 return Qnil;
3449 }
3450 i += MENU_ITEMS_PANE_LENGTH;
3451
3452 /* Find the width of the widest item in this pane. */
3453 j = i;
3454 while (j < menu_items_used)
3455 {
3456 Lisp_Object item;
3457 item = XVECTOR (menu_items)->contents[j];
3458 if (EQ (item, Qt))
3459 break;
3460 if (NILP (item))
3461 {
3462 j++;
3463 continue;
3464 }
3465 width = SBYTES (item);
3466 if (width > maxwidth)
3467 maxwidth = width;
3468
3469 j += MENU_ITEMS_ITEM_LENGTH;
3470 }
3471 }
3472 /* Ignore a nil in the item list.
3473 It's meaningful only for dialog boxes. */
3474 else if (EQ (XVECTOR (menu_items)->contents[i], Qquote))
3475 i += 1;
3476 else
3477 {
3478 /* Create a new item within current pane. */
3479 Lisp_Object item_name, enable, descrip, help;
3480 char *item_data;
3481 char const *help_string;
3482
3483 item_name = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_NAME];
3484 enable = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_ENABLE];
3485 descrip
3486 = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_EQUIV_KEY];
3487 help = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_HELP];
3488 help_string = STRINGP (help) ? SSDATA (help) : NULL;
3489
3490 if (!NILP (descrip))
3491 {
3492 /* if alloca is fast, use that to make the space,
3493 to reduce gc needs. */
3494 item_data = (char *) alloca (maxwidth + SBYTES (descrip) + 1);
3495 memcpy (item_data, SSDATA (item_name), SBYTES (item_name));
3496 for (j = SCHARS (item_name); j < maxwidth; j++)
3497 item_data[j] = ' ';
3498 memcpy (item_data + j, SSDATA (descrip), SBYTES (descrip));
3499 item_data[j + SBYTES (descrip)] = 0;
3500 }
3501 else
3502 item_data = SSDATA (item_name);
3503
3504 if (lpane == TTYM_FAILURE
3505 || (tty_menu_add_selection (menu, lpane, item_data,
3506 !NILP (enable), help_string)
3507 == TTYM_FAILURE))
3508 {
3509 tty_menu_destroy (menu);
3510 *error_name = "Can't add selection to menu";
3511 return Qnil;
3512 }
3513 i += MENU_ITEMS_ITEM_LENGTH;
3514 lines++;
3515 }
3516 }
3517
3518 maxlines = max (maxlines, lines);
3519
3520 /* All set and ready to fly. */
3521 dispwidth = f->text_cols;
3522 dispheight = f->text_lines;
3523 x = min (x, dispwidth);
3524 y = min (y, dispheight);
3525 x = max (x, 1);
3526 y = max (y, 1);
3527 tty_menu_locate (menu, x, y, &ulx, &uly, &width, &height);
3528 if (ulx+width > dispwidth)
3529 {
3530 x -= (ulx + width) - dispwidth;
3531 ulx = dispwidth - width;
3532 }
3533 if (uly+height > dispheight)
3534 {
3535 y -= (uly + height) - dispheight;
3536 uly = dispheight - height;
3537 }
3538
3539 if (FRAME_HAS_MINIBUF_P (f) && uly+height > dispheight - 1)
3540 {
3541 /* Move the menu away of the echo area, to avoid overwriting the
3542 menu with help echo messages or vice versa. */
3543 if (BUFFERP (echo_area_buffer[0]) && WINDOWP (echo_area_window))
3544 {
3545 y -= WINDOW_TOTAL_LINES (XWINDOW (echo_area_window));
3546 uly -= WINDOW_TOTAL_LINES (XWINDOW (echo_area_window));
3547 }
3548 else
3549 {
3550 y--;
3551 uly--;
3552 }
3553 }
3554
3555 if (ulx < 0) x -= ulx;
3556 if (uly < 0) y -= uly;
3557
3558 if (! for_click)
3559 {
3560 /* If position was not given by a mouse click, adjust so upper left
3561 corner of the menu as a whole ends up at given coordinates. This
3562 is what x-popup-menu says in its documentation. */
3563 x += width/2;
3564 y += 1.5*height/(maxlines+2);
3565 }
3566
3567 pane = selidx = 0;
3568
3569 record_unwind_protect (pop_down_menu,
3570 Fcons (make_save_value (f, 0),
3571 make_save_value (menu, 0)));
3572
3573 /* Help display under X won't work because XMenuActivate contains
3574 a loop that doesn't give Emacs a chance to process it. */
3575 menu_help_frame = f;
3576 status = tty_menu_activate (menu, &pane, &selidx, x, y, &datap,
3577 menu_help_callback);
3578 entry = pane_prefix = Qnil;
3579
3580 switch (status)
3581 {
3582 case TTYM_SUCCESS:
3583 /* Find the item number SELIDX in pane number PANE. */
3584 i = 0;
3585 while (i < menu_items_used)
3586 {
3587 if (EQ (XVECTOR (menu_items)->contents[i], Qt))
3588 {
3589 if (pane == 0)
3590 pane_prefix
3591 = XVECTOR (menu_items)->contents[i + MENU_ITEMS_PANE_PREFIX];
3592 pane--;
3593 i += MENU_ITEMS_PANE_LENGTH;
3594 }
3595 else
3596 {
3597 if (pane == -1)
3598 {
3599 if (selidx == 0)
3600 {
3601 entry
3602 = XVECTOR (menu_items)->contents[i + MENU_ITEMS_ITEM_VALUE];
3603 if (keymaps != 0)
3604 {
3605 entry = Fcons (entry, Qnil);
3606 if (!NILP (pane_prefix))
3607 entry = Fcons (pane_prefix, entry);
3608 }
3609 break;
3610 }
3611 selidx--;
3612 }
3613 i += MENU_ITEMS_ITEM_LENGTH;
3614 }
3615 }
3616 break;
3617
3618 case TTYM_FAILURE:
3619 *error_name = "Can't activate menu";
3620 case TTYM_IA_SELECT:
3621 break;
3622 case TTYM_NO_SELECT:
3623 /* Make "Cancel" equivalent to C-g unless FOR_CLICK (which means
3624 the menu was invoked with a mouse event as POSITION). */
3625 if (! for_click)
3626 Fsignal (Qquit, Qnil);
3627 break;
3628 }
3629
3630 unbind_to (specpdl_count, Qnil);
3631
3632 return entry;
3633}
3634
3635#endif /* HAVE_MENUS && !MSDOS */
3636
3637
2837#ifndef MSDOS 3638#ifndef MSDOS
2838/*********************************************************************** 3639/***********************************************************************
2839 Initialization 3640 Initialization
diff --git a/src/termhooks.h b/src/termhooks.h
index 4cad4825cdd..a15f829288a 100644
--- a/src/termhooks.h
+++ b/src/termhooks.h
@@ -665,3 +665,9 @@ extern unsigned char *encode_terminal_code (struct glyph *, int,
665#ifdef HAVE_GPM 665#ifdef HAVE_GPM
666extern void close_gpm (int gpm_fd); 666extern void close_gpm (int gpm_fd);
667#endif 667#endif
668
669#ifdef WINDOWSNT
670extern int curX (struct tty_display_info *);
671extern int curY (struct tty_display_info *);
672#endif
673
diff --git a/src/w32console.c b/src/w32console.c
index 22f329e239d..1f90f872d49 100644
--- a/src/w32console.c
+++ b/src/w32console.c
@@ -603,6 +603,21 @@ Wcm_clear (struct tty_display_info *tty)
603} 603}
604 604
605 605
606/* Report the current cursor position. The following two functions
607 mirror cm.h macros and are used in term.c's tty menu code, so they
608 are not really "stubs". */
609int
610curX (struct tty_display_info *tty)
611{
612 return cursor_coords.X;
613}
614
615int
616curY (struct tty_display_info *tty)
617{
618 return cursor_coords.Y;
619}
620
606/*********************************************************************** 621/***********************************************************************
607 Faces 622 Faces
608 ***********************************************************************/ 623 ***********************************************************************/
diff --git a/src/window.c b/src/window.c
index 54ad0af4c3f..563b52a0ca4 100644
--- a/src/window.c
+++ b/src/window.c
@@ -5464,18 +5464,24 @@ the return value is nil. Otherwise the value is t. */)
5464 || data->frame_cols != previous_frame_cols) 5464 || data->frame_cols != previous_frame_cols)
5465 change_frame_size (f, data->frame_lines, 5465 change_frame_size (f, data->frame_lines,
5466 data->frame_cols, 0, 0, 0); 5466 data->frame_cols, 0, 0, 0);
5467#if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS) 5467#ifdef HAVE_MENUS
5468 if (data->frame_menu_bar_lines 5468 if (data->frame_menu_bar_lines
5469 != previous_frame_menu_bar_lines) 5469 != previous_frame_menu_bar_lines)
5470 x_set_menu_bar_lines (f, make_number (data->frame_menu_bar_lines), 5470 {
5471 make_number (0)); 5471 if (FRAME_WINDOW_P (f))
5472 x_set_menu_bar_lines (f, make_number (data->frame_menu_bar_lines),
5473 make_number (0));
5474 else /* TTY or MSDOS */
5475 set_menu_bar_lines (f, make_number (data->frame_menu_bar_lines),
5476 make_number (0));
5477 }
5478#endif
5472#ifdef HAVE_WINDOW_SYSTEM 5479#ifdef HAVE_WINDOW_SYSTEM
5473 if (data->frame_tool_bar_lines 5480 if (data->frame_tool_bar_lines
5474 != previous_frame_tool_bar_lines) 5481 != previous_frame_tool_bar_lines)
5475 x_set_tool_bar_lines (f, make_number (data->frame_tool_bar_lines), 5482 x_set_tool_bar_lines (f, make_number (data->frame_tool_bar_lines),
5476 make_number (0)); 5483 make_number (0));
5477#endif 5484#endif
5478#endif
5479 5485
5480 /* "Swap out" point from the selected window's buffer 5486 /* "Swap out" point from the selected window's buffer
5481 into the window itself. (Normally the pointm of the selected 5487 into the window itself. (Normally the pointm of the selected
@@ -5688,16 +5694,23 @@ the return value is nil. Otherwise the value is t. */)
5688 || previous_frame_cols != FRAME_COLS (f)) 5694 || previous_frame_cols != FRAME_COLS (f))
5689 change_frame_size (f, previous_frame_lines, previous_frame_cols, 5695 change_frame_size (f, previous_frame_lines, previous_frame_cols,
5690 0, 0, 0); 5696 0, 0, 0);
5691#if defined (HAVE_WINDOW_SYSTEM) || defined (MSDOS) 5697#ifdef HAVE_MENUS
5692 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f)) 5698 if (previous_frame_menu_bar_lines != FRAME_MENU_BAR_LINES (f))
5693 x_set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines), 5699 {
5694 make_number (0)); 5700 if (FRAME_WINDOW_P (f))
5701 x_set_menu_bar_lines (f,
5702 make_number (previous_frame_menu_bar_lines),
5703 make_number (0));
5704 else /* TTY or MSDOS */
5705 set_menu_bar_lines (f, make_number (previous_frame_menu_bar_lines),
5706 make_number (0));
5707 }
5708#endif
5695#ifdef HAVE_WINDOW_SYSTEM 5709#ifdef HAVE_WINDOW_SYSTEM
5696 if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f)) 5710 if (previous_frame_tool_bar_lines != FRAME_TOOL_BAR_LINES (f))
5697 x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines), 5711 x_set_tool_bar_lines (f, make_number (previous_frame_tool_bar_lines),
5698 make_number (0)); 5712 make_number (0));
5699#endif 5713#endif
5700#endif
5701 5714
5702 /* Now, free glyph matrices in windows that were not reused. */ 5715 /* Now, free glyph matrices in windows that were not reused. */
5703 for (i = n = 0; i < n_leaf_windows; ++i) 5716 for (i = n = 0; i < n_leaf_windows; ++i)
diff --git a/src/xdisp.c b/src/xdisp.c
index 0763fc19c73..52163db7456 100644
--- a/src/xdisp.c
+++ b/src/xdisp.c
@@ -19961,7 +19961,78 @@ display_menu_bar (struct window *w)
19961 compute_line_metrics (&it); 19961 compute_line_metrics (&it);
19962} 19962}
19963 19963
19964#ifdef HAVE_MENUS
19965/* Display one menu item on a TTY, by overwriting the glyphs in the
19966 desired glyph matrix with glyphs produced from the menu item text.
19967 Called from term.c to display TTY drop-down menus one item at a
19968 time.
19964 19969
19970 ITEM_TEXT is the menu item text as a C string.
19971
19972 FACE_ID is the face ID to be used for this menu item. FACE_ID
19973 could specify one of 3 faces: a face for an enabled item, a face
19974 for a disabled item, or a face for a selected item.
19975
19976 X and Y are coordinates of the first glyph in the desired matrix to
19977 be overwritten by the menu item. Since this is a TTY, Y is the
19978 glyph row and X is the glyph number in the row, where to start
19979 displaying the item.
19980
19981 SUBMENU non-zero means this menu item drops down a submenu, which
19982 should be indicated by displaying a proper visual cue after the
19983 item text. */
19984
19985void
19986display_tty_menu_item (const char *item_text, int face_id, int x, int y,
19987 int submenu)
19988{
19989 struct it it;
19990 struct frame *f = SELECTED_FRAME ();
19991 int saved_used, saved_truncated;
19992 struct glyph_row *row;
19993
19994 xassert (FRAME_TERMCAP_P (f));
19995
19996 init_iterator (&it, w, -1, -1, f->desired_matrix->rows + y, MENU_FACE_ID);
19997 it.first_visible_x = 0;
19998 it.last_visible_x = FRAME_COLS (f);
19999 row = it.glyph_row;
20000 row->full_width_p = 1;
20001
20002 /* Arrange for the menu item glyphs to start at X and have the
20003 desired face. */
20004 it.current_x = it.hpos = x;
20005 saved_used = row->used[TEXT_AREA];
20006 saved_truncated = row->truncated_on_right_p;
20007 row->used[TEXT_AREA] = x - row->used[LEFT_MARGIN_AREA];
20008 it.face_id = face_id;
20009
20010 /* FIXME: This should be controlled by a user option. See the
20011 comments in redisplay_tool_bar and display_mode_line about this.
20012 Also, if paragraph_embedding could ever be R2L, changes will be
20013 needed to avoid shifting to the right the row characters in
20014 term.c:append_glyph. */
20015 it.paragraph_embedding = L2R;
20016
20017 if (submenu)
20018 {
20019 /* Indicate with ">" that there's a submenu. */
20020 display_string (item_text, Qnil, Qnil, 0, 0, &it,
20021 strlen (item_text), 0, FRAME_COLS (f) - 2, -1);
20022 display_string (">", Qnil, Qnil, 0, 0, &it, 1, 0, 0, -1);
20023 }
20024 else
20025 {
20026 /* Display the menu item, pad with one space. */
20027 display_string (item_text, Qnil, Qnil, 0, 0, &it,
20028 strlen (item_text) + 1, 0, 0, -1);
20029 }
20030
20031 row->used[TEXT_AREA] = saved_used;
20032 row->truncated_on_right_p = saved_truncated;
20033 row->hash - row_hash (row);
20034}
20035#endif /* HAVE_MENUS */
19965 20036
19966/*********************************************************************** 20037/***********************************************************************
19967 Mode Line 20038 Mode Line