/* Terminal control module for terminals described by TERMCAP
- Copyright (C) 1985-1987, 1993-1995, 1998, 2000-2013 Free Software
+ Copyright (C) 1985-1987, 1993-1995, 1998, 2000-2014 Free Software
Foundation, Inc.
This file is part of GNU Emacs.
static int been_here = -1;
#endif
+#ifdef USE_X_TOOLKIT
+#include "../lwlib/lwlib.h"
+#endif
+
#include "cm.h"
#ifdef HAVE_X_WINDOWS
#include "xterm.h"
static int max_frame_cols;
+static Lisp_Object Qtty_mode_set_strings;
+static Lisp_Object Qtty_mode_reset_strings;
+
\f
#ifdef HAVE_GPM
/* Set up termcap modes for Emacs. */
+static void
+tty_send_additional_strings (struct terminal *terminal, Lisp_Object sym)
+{
+ Lisp_Object lisp_terminal;
+ Lisp_Object extra_codes;
+ struct tty_display_info *tty = terminal->display_info.tty;
+
+ XSETTERMINAL (lisp_terminal, terminal);
+ for (extra_codes = Fterminal_parameter (lisp_terminal, sym);
+ CONSP (extra_codes);
+ extra_codes = XCDR (extra_codes))
+ {
+ Lisp_Object string = XCAR (extra_codes);
+ if (STRINGP (string))
+ {
+ fwrite (SDATA (string), 1, SBYTES (string), tty->output);
+ if (tty->termscript)
+ fwrite (SDATA (string), 1, SBYTES (string), tty->termscript);
+ }
+ }
+}
+
static void
tty_set_terminal_modes (struct terminal *terminal)
{
OUTPUT_IF (tty, visible_cursor ? tty->TS_cursor_visible : tty->TS_cursor_normal);
OUTPUT_IF (tty, tty->TS_keypad_mode);
losecursor (tty);
+ tty_send_additional_strings (terminal, Qtty_mode_set_strings);
fflush (tty->output);
}
}
if (tty->output)
{
+ tty_send_additional_strings (terminal, Qtty_mode_reset_strings);
tty_turn_off_highlight (tty);
tty_turn_off_insert (tty);
OUTPUT_IF (tty, tty->TS_end_keypad_mode);
tty_show_cursor (tty);
tty_turn_off_insert (tty);
tty_background_highlight (tty);
+ fflush (tty->output);
}
/* The implementation of set_terminal_window for termcap frames. */
sequence, and return a pointer to that byte sequence. */
unsigned char *
-encode_terminal_code (struct glyph *src, int src_len, struct coding_system *coding)
+encode_terminal_code (struct glyph *src, int src_len,
+ struct coding_system *coding)
{
struct glyph *src_end = src + src_len;
unsigned char *buf;
if (!KEYMAPP (KVAR (kboard, Vinput_decode_map)))
kset_input_decode_map (kboard, Fmake_sparse_keymap (Qnil));
- for (i = 0; i < (sizeof (keys) / sizeof (keys[0])); i++)
+ for (i = 0; i < ARRAYELTS (keys); i++)
{
char *sequence = tgetstr (keys[i].cap, address);
if (sequence)
CONDITIONAL_REASSIGN ("kD", "kI", "insert");
/* if there's no key_end keycap, map key_ll to 'end' keysym */
CONDITIONAL_REASSIGN ("@7", "kH", "end");
-
- /* IBM has their own non-standard dialect of terminfo.
- If the standard name isn't found, try the IBM name. */
- CONDITIONAL_REASSIGN ("kB", "KO", "backtab");
- CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */
- CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */
- CONDITIONAL_REASSIGN ("%7", "ki", "menu");
- CONDITIONAL_REASSIGN ("@7", "kw", "end");
- CONDITIONAL_REASSIGN ("F1", "k<", "f11");
- CONDITIONAL_REASSIGN ("F2", "k>", "f12");
- CONDITIONAL_REASSIGN ("%1", "kq", "help");
- CONDITIONAL_REASSIGN ("*6", "kU", "select");
#undef CONDITIONAL_REASSIGN
}
static void
produce_glyphless_glyph (struct it *it, Lisp_Object acronym)
{
- int face_id;
- int len;
+ int len, face_id = merge_glyphless_glyph_face (it);
char buf[sizeof "\\x" + max (6, (sizeof it->c * CHAR_BIT + 3) / 4)];
char const *str = " ";
- /* Get a face ID for the glyph by utilizing a cache (the same way as
- done for `escape-glyph' in get_next_display_element). */
- if (it->f == last_glyphless_glyph_frame
- && it->face_id == last_glyphless_glyph_face_id)
- {
- face_id = last_glyphless_glyph_merged_face_id;
- }
- else
- {
- /* Merge the `glyphless-char' face into the current face. */
- face_id = merge_faces (it->f, Qglyphless_char, 0, it->face_id);
- last_glyphless_glyph_frame = it->f;
- last_glyphless_glyph_face_id = it->face_id;
- last_glyphless_glyph_merged_face_id = face_id;
- }
-
if (it->glyphless_method == GLYPHLESS_DISPLAY_THIN_SPACE)
{
/* As there's no way to produce a thin space, we produce a space
acronym = XCDR (acronym);
buf[0] = '[';
str = STRINGP (acronym) ? SSDATA (acronym) : "";
- for (len = 0; len < 6 && str[len] && ASCII_BYTE_P (str[len]); len++)
+ for (len = 0; len < 6 && str[len] && ASCII_CHAR_P (str[len]); len++)
buf[1 + len] = str[len];
buf[1 + len] = ']';
len += 2;
turn_on_face (struct frame *f, int face_id)
{
struct face *face = FACE_FROM_ID (f, face_id);
- long fg = face->foreground;
- long bg = face->background;
+ unsigned long fg = face->foreground;
+ unsigned long bg = face->background;
struct tty_display_info *tty = FRAME_TTY (f);
- /* Do this first because TS_end_standout_mode may be the same
+ /* Use reverse video if the face specifies that.
+ Do this first because TS_end_standout_mode may be the same
as TS_exit_attribute_mode, which turns all appearances off. */
- if (MAY_USE_WITH_COLORS_P (tty, NC_REVERSE))
- {
- if (tty->TN_max_colors > 0)
- {
- if (fg >= 0 && bg >= 0)
- {
- /* If the terminal supports colors, we can set them
- below without using reverse video. The face's fg
- and bg colors are set as they should appear on
- the screen, i.e. they take the inverse-video'ness
- of the face already into account. */
- }
- else if (inverse_video)
- {
- if (fg == FACE_TTY_DEFAULT_FG_COLOR
- || bg == FACE_TTY_DEFAULT_BG_COLOR)
- tty_toggle_highlight (tty);
- }
- else
- {
- if (fg == FACE_TTY_DEFAULT_BG_COLOR
- || bg == FACE_TTY_DEFAULT_FG_COLOR)
- tty_toggle_highlight (tty);
- }
- }
- else
- {
- /* If we can't display colors, use reverse video
- if the face specifies that. */
- if (inverse_video)
- {
- if (fg == FACE_TTY_DEFAULT_FG_COLOR
- || bg == FACE_TTY_DEFAULT_BG_COLOR)
- tty_toggle_highlight (tty);
- }
- else
- {
- if (fg == FACE_TTY_DEFAULT_BG_COLOR
- || bg == FACE_TTY_DEFAULT_FG_COLOR)
- tty_toggle_highlight (tty);
- }
- }
- }
+ if (MAY_USE_WITH_COLORS_P (tty, NC_REVERSE)
+ && (inverse_video
+ ? fg == FACE_TTY_DEFAULT_FG_COLOR || bg == FACE_TTY_DEFAULT_BG_COLOR
+ : fg == FACE_TTY_DEFAULT_BG_COLOR || bg == FACE_TTY_DEFAULT_FG_COLOR))
+ tty_toggle_highlight (tty);
if (face->tty_bold_p && MAY_USE_WITH_COLORS_P (tty, NC_BOLD))
OUTPUT1_IF (tty, tty->TS_enter_bold_mode);
char *p;
ts = tty->standout_mode ? tty->TS_set_background : tty->TS_set_foreground;
- if (fg >= 0 && ts)
+ if (face_tty_specified_color (fg) && ts)
{
p = tparam (ts, NULL, 0, fg, 0, 0, 0);
OUTPUT (tty, p);
}
ts = tty->standout_mode ? tty->TS_set_foreground : tty->TS_set_background;
- if (bg >= 0 && ts)
+ if (face_tty_specified_color (bg) && ts)
{
p = tparam (ts, NULL, 0, bg, 0, 0, 0);
OUTPUT (tty, p);
/* Return true if the terminal on frame F supports all of the
- capabilities in CAPS simultaneously, with foreground and background
- colors FG and BG. */
+ capabilities in CAPS simultaneously. */
bool
-tty_capable_p (struct tty_display_info *tty, unsigned int caps,
- unsigned long fg, unsigned long bg)
+tty_capable_p (struct tty_display_info *tty, unsigned int caps)
{
#define TTY_CAPABLE_P_TRY(tty, cap, TS, NC_bit) \
if ((caps & (cap)) && (!(TS) || !MAY_USE_WITH_COLORS_P(tty, NC_bit))) \
if (save)
{
- xfree (default_orig_pair);
- default_orig_pair = tty->TS_orig_pair ? xstrdup (tty->TS_orig_pair) : NULL;
-
- xfree (default_set_foreground);
- default_set_foreground = tty->TS_set_foreground ? xstrdup (tty->TS_set_foreground)
- : NULL;
-
- xfree (default_set_background);
- default_set_background = tty->TS_set_background ? xstrdup (tty->TS_set_background)
- : NULL;
-
+ dupstring (&default_orig_pair, tty->TS_orig_pair);
+ dupstring (&default_set_foreground, tty->TS_set_foreground);
+ dupstring (&default_set_background, tty->TS_set_background);
default_max_colors = tty->TN_max_colors;
default_max_pairs = tty->TN_max_pairs;
default_no_color_video = tty->TN_no_color_video;
was suspended. */
get_tty_size (fileno (t->display_info.tty->input), &width, &height);
if (width != old_width || height != old_height)
- change_frame_size (f, height, width, 0, 0, 0);
+ change_frame_size (f, width, height, 0, 0, 0, 0);
SET_FRAME_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1);
}
Menus
***********************************************************************/
-#if defined (HAVE_MENUS) && !defined (MSDOS)
+#if !defined (MSDOS)
/* TTY menu implementation and main ideas are borrowed from msdos.c.
However, unlike on MSDOS, where the menu text is drawn directly to
the display video memory, on a TTY we use display_string (see
display_tty_menu_item in xdisp.c) to put the glyphs produced from
- the menu items directly into the frame's 'desired_matrix' glyph
- matrix, and then call update_frame_with_menu to deliver the results
- to the glass. The previous contents of the screen, in the form of
- the current_matrix, is stashed away, and used to restore screen
+ the menu items into the frame's 'desired_matrix' glyph matrix, and
+ then call update_frame_with_menu to deliver the results to the
+ glass. The previous contents of the screen, in the form of the
+ current_matrix, is stashed away, and used to restore screen
contents when the menu selection changes or when the final
selection is made and the menu should be popped down.
#define TTYM_SUCCESS 1
#define TTYM_NO_SELECT 2
#define TTYM_IA_SELECT 3
+#define TTYM_NEXT 4
+#define TTYM_PREV 5
/* These hold text of the current and the previous menu help messages. */
static const char *menu_help_message, *prev_menu_help_message;
last menu help message. */
static int menu_help_paneno, menu_help_itemno;
-static int menu_x, menu_y;
-
static Lisp_Object Qtty_menu_navigation_map, Qtty_menu_exit;
static Lisp_Object Qtty_menu_prev_item, Qtty_menu_next_item;
static Lisp_Object Qtty_menu_next_menu, Qtty_menu_prev_menu;
static Lisp_Object Qtty_menu_select, Qtty_menu_ignore;
+static Lisp_Object Qtty_menu_mouse_movement;
typedef struct tty_menu_struct
{
int count;
char **text;
struct tty_menu_struct **submenu;
- int *panenumber; /* Also used as enable. */
- int allocated;
+ int *panenumber; /* Also used as enabled flag. */
+ ptrdiff_t allocated;
int panecount;
int width;
const char **help_text;
static tty_menu *
tty_menu_create (void)
{
- tty_menu *menu;
-
- menu = (tty_menu *) xmalloc (sizeof (tty_menu));
- menu->allocated = menu->count = menu->panecount = menu->width = 0;
- return menu;
+ return xzalloc (sizeof *tty_menu_create ());
}
/* Allocate some (more) memory for MENU ensuring that there is room for one
- for item. */
+ more item. */
static void
tty_menu_make_room (tty_menu *menu)
{
- if (menu->allocated == 0)
- {
- int count = menu->allocated = 10;
- menu->text = (char **) xmalloc (count * sizeof (char *));
- menu->submenu = (tty_menu **) xmalloc (count * sizeof (tty_menu *));
- menu->panenumber = (int *) xmalloc (count * sizeof (int));
- menu->help_text = (const char **) xmalloc (count * sizeof (char *));
- }
- else if (menu->allocated == menu->count)
+ if (menu->allocated == menu->count)
{
- int count = menu->allocated = menu->allocated + 10;
- menu->text
- = (char **) xrealloc (menu->text, count * sizeof (char *));
- menu->submenu
- = (tty_menu **) xrealloc (menu->submenu, count * sizeof (tty_menu *));
- menu->panenumber
- = (int *) xrealloc (menu->panenumber, count * sizeof (int));
- menu->help_text
- = (const char **) xrealloc (menu->help_text, count * sizeof (char *));
+ ptrdiff_t allocated = menu->allocated;
+ menu->text = xpalloc (menu->text, &allocated, 1, -1, sizeof *menu->text);
+ menu->text = xrealloc (menu->text, allocated * sizeof *menu->text);
+ menu->submenu = xrealloc (menu->submenu,
+ allocated * sizeof *menu->submenu);
+ menu->panenumber = xrealloc (menu->panenumber,
+ allocated * sizeof *menu->panenumber);
+ menu->help_text = xrealloc (menu->help_text,
+ allocated * sizeof *menu->help_text);
+ menu->allocated = allocated;
}
}
{
if (pane == menu->panenumber[i])
return menu->submenu[i];
- if ((try = tty_menu_search_pane (menu->submenu[i], pane)))
+ try = tty_menu_search_pane (menu->submenu[i], pane);
+ if (try)
return try;
}
return (tty_menu *) 0;
*height = maxheight;
}
-/* Display MENU at (X,Y) using FACES. */
-
static void
-tty_menu_display (tty_menu *menu, int x, int y, int pn, int *faces,
- int disp_help)
+mouse_get_xy (int *x, int *y)
{
- int i, face, width, mx = -1, my = -1, enabled, mousehere, row, col;
struct frame *sf = SELECTED_FRAME ();
- struct tty_display_info *tty = FRAME_TTY (sf);
-#if defined (HAVE_MOUSE) || defined (HAVE_GPM)
- Lisp_Object lmx, lmy, lisp_dummy;
+ Lisp_Object lmx = Qnil, lmy = Qnil, lisp_dummy;
enum scroll_bar_part part_dummy;
Time time_dummy;
if (FRAME_TERMINAL (sf)->mouse_position_hook)
(*FRAME_TERMINAL (sf)->mouse_position_hook) (&sf, -1,
- &lispy_dummy, &party_dummy,
+ &lisp_dummy, &part_dummy,
&lmx, &lmy,
&time_dummy);
if (!NILP (lmx))
{
- mx = XINT (lmx);
- my = XINT (lmy);
- }
- else
- {
- mx = menu_x;
- my = menu_y;
+ *x = XINT (lmx);
+ *y = XINT (lmy);
}
-#else
- mx = menu_x;
- my = menu_y;
-#endif
+}
+
+/* Display MENU at (X,Y) using FACES, starting with FIRST_ITEM
+ (zero-based). */
+
+static void
+tty_menu_display (tty_menu *menu, int x, int y, int pn, int *faces,
+ int mx, int my, int first_item, bool disp_help)
+{
+ int i, face, width, enabled, mousehere, row, col;
+ struct frame *sf = SELECTED_FRAME ();
+ struct tty_display_info *tty = FRAME_TTY (sf);
+ /* Don't try to display more menu items than the console can display
+ using the available screen lines. Exclude the echo area line, as
+ it will be overwritten by the help-echo anyway. */
+ int max_items = min (menu->count - first_item, FRAME_LINES (sf) - 1 - y);
menu_help_message = NULL;
width = menu->width;
col = cursorX (tty);
row = cursorY (tty);
-#if 0
- IT_update_begin (sf); /* FIXME: do we need an update_begin_hook? */
-#endif
- for (i = 0; i < menu->count; i++)
+ for (i = 0; i < max_items; i++)
{
int max_width = width + 2; /* +2 for padding blanks on each side */
+ int j = i + first_item;
- cursor_to (sf, y + i, x);
- if (menu->submenu[i])
+ if (menu->submenu[j])
max_width += 2; /* for displaying " >" after the item */
enabled
- = (!menu->submenu[i] && menu->panenumber[i]) || (menu->submenu[i]);
+ = (!menu->submenu[j] && menu->panenumber[j]) || (menu->submenu[j]);
mousehere = (y + i == my && x <= mx && mx < x + max_width);
face = faces[enabled + mousehere * 2];
/* Display the menu help string for the i-th menu item even if
code does. */
if (disp_help && enabled + mousehere * 2 >= 2)
{
- menu_help_message = menu->help_text[i];
+ menu_help_message = menu->help_text[j];
menu_help_paneno = pn - 1;
- menu_help_itemno = i;
+ menu_help_itemno = j;
}
- display_tty_menu_item (menu->text[i], max_width, face, x, y + i,
- menu->submenu[i] != NULL);
+ /* Take note of the coordinates of the active menu item, to
+ display the cursor there. */
+ if (mousehere)
+ {
+ row = y + i;
+ col = x;
+ }
+ display_tty_menu_item (menu->text[j], max_width, face, x, y + i,
+ menu->submenu[j] != NULL);
}
- update_frame_with_menu (sf);
- cursor_to (sf, row, col);
+ update_frame_with_menu (sf, row, col);
}
/* --------------------------- X Menu emulation ---------------------- */
-/* Report availability of menus. */
-
-int
-have_menus_p (void) { return 1; }
-
/* Create a new pane and place it on the outer-most level. */
static int
tty_menu_add_pane (tty_menu *menu, const char *txt)
{
int len;
- const char *p;
+ const unsigned char *p;
tty_menu_make_room (menu);
menu->submenu[menu->count] = tty_menu_create ();
menu->count++;
/* Update the menu width, if necessary. */
- for (len = 0, p = txt; *p; )
+ for (len = 0, p = (unsigned char *) txt; *p; )
{
int ch_len;
int ch = STRING_CHAR_AND_LENGTH (p, ch_len);
/* Create a new item in a menu pane. */
-int
+static bool
tty_menu_add_selection (tty_menu *menu, int pane,
- char *txt, int enable, char const *help_text)
+ char *txt, bool enable, char const *help_text)
{
int len;
- char *p;
+ unsigned char *p;
if (pane)
- if (!(menu = tty_menu_search_pane (menu, pane)))
- return TTYM_FAILURE;
+ {
+ menu = tty_menu_search_pane (menu, pane);
+ if (! menu)
+ return 0;
+ }
tty_menu_make_room (menu);
menu->submenu[menu->count] = (tty_menu *) 0;
menu->text[menu->count] = txt;
menu->count++;
/* Update the menu width, if necessary. */
- for (len = 0, p = txt; *p; )
+ for (len = 0, p = (unsigned char *) txt; *p; )
{
int ch_len;
int ch = STRING_CHAR_AND_LENGTH (p, ch_len);
if (len > menu->width)
menu->width = len;
- return TTYM_SUCCESS;
+ return 1;
}
/* Decide where the menu would be placed if requested at (X,Y). */
-void
+static void
tty_menu_locate (tty_menu *menu, int x, int y,
int *ulx, int *uly, int *width, int *height)
{
int x, y;
};
+/* Save away the contents of frame F's current frame matrix, and
+ enable all its rows. Value is a glyph matrix holding the contents
+ of F's current frame matrix with all its glyph rows enabled. */
+
+static struct glyph_matrix *
+save_and_enable_current_matrix (struct frame *f)
+{
+ int i;
+ struct glyph_matrix *saved = xzalloc (sizeof *saved);
+ saved->nrows = f->current_matrix->nrows;
+ saved->rows = xzalloc (saved->nrows * sizeof *saved->rows);
+
+ for (i = 0; i < saved->nrows; ++i)
+ {
+ struct glyph_row *from = f->current_matrix->rows + i;
+ struct glyph_row *to = saved->rows + i;
+ ptrdiff_t nbytes = from->used[TEXT_AREA] * sizeof (struct glyph);
+
+ to->glyphs[TEXT_AREA] = xmalloc (nbytes);
+ memcpy (to->glyphs[TEXT_AREA], from->glyphs[TEXT_AREA], nbytes);
+ to->used[TEXT_AREA] = from->used[TEXT_AREA];
+ /* Make sure every row is enabled, or else update_frame will not
+ redraw them. (Rows that are identical to what is already on
+ screen will not be redrawn anyway.) */
+ to->enabled_p = true;
+ to->hash = from->hash;
+ }
+
+ return saved;
+}
+
/* Restore the contents of frame F's desired frame matrix from SAVED,
and free memory associated with SAVED. */
to->used[TEXT_AREA] = from->used[TEXT_AREA];
to->enabled_p = from->enabled_p;
to->hash = from->hash;
- xfree (from->glyphs[TEXT_AREA]);
- nbytes = from->used[LEFT_MARGIN_AREA] * sizeof (struct glyph);
- if (nbytes)
- {
- eassert (to->glyphs[LEFT_MARGIN_AREA] != from->glyphs[LEFT_MARGIN_AREA]);
- memcpy (to->glyphs[LEFT_MARGIN_AREA],
- from->glyphs[LEFT_MARGIN_AREA], nbytes);
- to->used[LEFT_MARGIN_AREA] = from->used[LEFT_MARGIN_AREA];
- xfree (from->glyphs[LEFT_MARGIN_AREA]);
- }
- else
- to->used[LEFT_MARGIN_AREA] = 0;
- nbytes = from->used[RIGHT_MARGIN_AREA] * sizeof (struct glyph);
- if (nbytes)
- {
- eassert (to->glyphs[RIGHT_MARGIN_AREA] != from->glyphs[RIGHT_MARGIN_AREA]);
- memcpy (to->glyphs[RIGHT_MARGIN_AREA],
- from->glyphs[RIGHT_MARGIN_AREA], nbytes);
- to->used[RIGHT_MARGIN_AREA] = from->used[RIGHT_MARGIN_AREA];
- xfree (from->glyphs[RIGHT_MARGIN_AREA]);
- }
- else
- to->used[RIGHT_MARGIN_AREA] = 0;
}
-
- xfree (saved->rows);
- xfree (saved);
}
static void
int i;
if (!saved)
- return; /* already freed */
+ return; /* Already freed! */
for (i = 0; i < saved->nrows; ++i)
{
struct glyph_row *from = saved->rows + i;
xfree (from->glyphs[TEXT_AREA]);
- if (from->used[LEFT_MARGIN_AREA])
- xfree (from->glyphs[LEFT_MARGIN_AREA]);
- if (from->used[RIGHT_MARGIN_AREA])
- xfree (from->glyphs[RIGHT_MARGIN_AREA]);
}
xfree (saved->rows);
screen_update (struct frame *f, struct glyph_matrix *mtx)
{
restore_desired_matrix (f, mtx);
- update_frame_with_menu (f);
+ update_frame_with_menu (f, -1, -1);
}
-/* Read user input and return X and Y coordinates where that input
- puts us. We only consider mouse movement and click events and
- keyboard movement commands; the rest are ignored.
+typedef enum {
+ MI_QUIT_MENU = -1,
+ MI_CONTINUE = 0,
+ MI_ITEM_SELECTED = 1,
+ MI_NEXT_ITEM = 2,
+ MI_PREV_ITEM = 3,
+ MI_SCROLL_FORWARD = 4,
+ MI_SCROLL_BACK = 5
+} mi_result;
- Value is -1 if C-g was pressed, zero otherwise. */
-static int
+/* Read user input and return X and Y coordinates where that input
+ puts us. We only consider mouse movement and click events, and
+ keyboard movement commands; the rest are ignored. */
+static mi_result
read_menu_input (struct frame *sf, int *x, int *y, int min_y, int max_y,
bool *first_time)
{
- Lisp_Object c;
-
if (*first_time)
{
*first_time = false;
- /* FIXME: Following 2 or 3 lines are temporary! */
- menu_x = *x;
- menu_y = *y;
sf->mouse_moved = 1;
- return 0;
}
-
- while (1)
+ else
{
-#if 1
- extern Lisp_Object read_menu_command (void);
Lisp_Object cmd;
- int usable_input = 1;
- int st = 0;
-
+ bool usable_input = 1;
+ mi_result st = MI_CONTINUE;
+ struct tty_display_info *tty = FRAME_TTY (sf);
+ Lisp_Object saved_mouse_tracking = do_mouse_tracking;
+
+ /* Signal the keyboard reading routines we are displaying a menu
+ on this terminal. */
+ tty->showing_menu = 1;
+ /* We want mouse movements be reported by read_menu_command. */
+ do_mouse_tracking = Qt;
do {
cmd = read_menu_command ();
- } while NILP (cmd);
-
- if (EQ (cmd, Qt) || EQ (cmd, Qtty_menu_exit))
- return -1;
- if (EQ (cmd, Qtty_menu_next_menu))
- *x += 1;
+ } while (NILP (cmd));
+ tty->showing_menu = 0;
+ do_mouse_tracking = saved_mouse_tracking;
+
+ if (EQ (cmd, Qt) || EQ (cmd, Qtty_menu_exit)
+ /* If some input switched frames under our feet, exit the
+ menu, since the menu faces are no longer valid, and the
+ menu is no longer relevant anyway. */
+ || sf != SELECTED_FRAME ())
+ return MI_QUIT_MENU;
+ if (EQ (cmd, Qtty_menu_mouse_movement))
+ mouse_get_xy (x, y);
+ else if (EQ (cmd, Qtty_menu_next_menu))
+ {
+ usable_input = 0;
+ st = MI_NEXT_ITEM;
+ }
else if (EQ (cmd, Qtty_menu_prev_menu))
- *x -= 1;
+ {
+ usable_input = 0;
+ st = MI_PREV_ITEM;
+ }
else if (EQ (cmd, Qtty_menu_next_item))
{
if (*y < max_y)
*y += 1;
+ else
+ st = MI_SCROLL_FORWARD;
}
else if (EQ (cmd, Qtty_menu_prev_item))
{
if (*y > min_y)
*y -= 1;
+ else
+ st = MI_SCROLL_BACK;
}
else if (EQ (cmd, Qtty_menu_select))
- st = 1;
+ st = MI_ITEM_SELECTED;
else if (!EQ (cmd, Qtty_menu_ignore))
- {
- usable_input = 0;
- st = -1;
- }
+ usable_input = 0;
if (usable_input)
sf->mouse_moved = 1;
-#else
- int volatile dx = 0;
- int volatile dy = 0;
- int volatile st = 0;
-
- *x += dx;
- *y += dy;
- if (dx != 0 || dy != 0)
- sf->mouse_moved = 1;
- Sleep (300);
-#endif
- menu_x = *x;
- menu_y = *y;
return st;
}
- return 0;
-}
-
-/* FIXME */
-static bool mouse_visible;
-static void
-mouse_off (void)
-{
- mouse_visible = false;
-}
-
-static void
-mouse_on (void)
-{
- mouse_visible = true;
-}
-
-static bool
-mouse_pressed (int b, int *x, int *y)
-{
- return false;
-}
-
-static bool
-mouse_button_depressed (int b, int *x, int *y)
-{
- return false;
-}
-
-static bool
-mouse_released (int b, int *x, int *y)
-{
- return true;
+ return MI_CONTINUE;
}
/* Display menu, wait for user's response, and return that response. */
-int
+static int
tty_menu_activate (tty_menu *menu, int *pane, int *selidx,
int x0, int y0, char **txt,
- void (*help_callback)(char const *, int, int))
+ void (*help_callback)(char const *, int, int),
+ bool kbd_navigation)
{
struct tty_menu_state *state;
- int statecount, x, y, i, b, leave, result, onepane;
- int title_faces[4]; /* face to display the menu title */
+ int statecount, x, y, i;
+ bool leave, onepane;
+ int result IF_LINT (= 0);
+ int title_faces[4]; /* Face to display the menu title. */
int faces[4], buffers_num_deleted = 0;
struct frame *sf = SELECTED_FRAME ();
struct tty_display_info *tty = FRAME_TTY (sf);
bool first_time;
- Lisp_Object saved_echo_area_message, selectface;
+ Lisp_Object selectface;
+ int first_item = 0;
+ int col, row;
/* Don't allow non-positive x0 and y0, lest the menu will wrap
around the display. */
if (y0 <= 0)
y0 = 1;
-#if 0
- /* We will process all the mouse events directly. */
- mouse_preempted++;
-#endif
-
state = alloca (menu->panecount * sizeof (struct tty_menu_state));
memset (state, 0, sizeof (*state));
faces[0]
buffers_num_deleted = 1;
}
-#if 0
- /* We need to save the current echo area message, so that we could
- restore it below, before we exit. See the commentary below,
- before the call to message_with_string. */
- saved_echo_area_message = Fcurrent_message ();
-#endif
/* Force update of the current frame, so that the desired and the
current matrices are identical. */
- update_frame_with_menu (sf);
+ update_frame_with_menu (sf, -1, -1);
state[0].menu = menu;
- mouse_off (); /* FIXME */
- state[0].screen_behind = save_current_matrix (sf);
-
- /* Turn off the cursor. Otherwise it shows through the menu
- panes, which is ugly. */
- tty_hide_cursor (tty);
+ state[0].screen_behind = save_and_enable_current_matrix (sf);
/* Display the menu title. We subtract 1 from x0 and y0 because we
want to interpret them as zero-based column and row coordinates,
and also because we want the first item of the menu, not its
title, to appear at x0,y0. */
- tty_menu_display (menu, x0 - 1, y0 - 1, 1, title_faces, 0);
+ tty_menu_display (menu, x0 - 1, y0 - 1, 1, title_faces, x0 - 1, y0 - 1, 0, 0);
+
+ /* Turn off the cursor. Otherwise it shows through the menu
+ panes, which is ugly. */
+ col = cursorX (tty);
+ row = cursorY (tty);
+ tty_hide_cursor (tty);
+
if (buffers_num_deleted)
menu->text[0][7] = ' ';
- if ((onepane = menu->count == 1 && menu->submenu[0]))
+ onepane = menu->count == 1 && menu->submenu[0];
+ if (onepane)
{
menu->width = menu->submenu[0]->width;
state[0].menu = menu->submenu[0];
leave = 0;
while (!leave)
{
- int mouse_button_count = 3; /* FIXME */
- int input_status;
- int min_y = state[0].y, max_y = min_y + state[0].menu->count - 1;
+ mi_result input_status;
+ int min_y = state[0].y;
+ int max_y = min (min_y + state[0].menu->count, FRAME_LINES (sf) - 1) - 1;
- if (!mouse_visible) mouse_on ();
input_status = read_menu_input (sf, &x, &y, min_y, max_y, &first_time);
if (input_status)
{
- if (input_status == -1)
+ leave = 1;
+ switch (input_status)
{
+ case MI_QUIT_MENU:
/* Remove the last help-echo, so that it doesn't
re-appear after "Quit". */
show_help_echo (Qnil, Qnil, Qnil, Qnil);
result = TTYM_NO_SELECT;
+ break;
+ case MI_NEXT_ITEM:
+ if (kbd_navigation)
+ result = TTYM_NEXT;
+ else
+ leave = 0;
+ break;
+ case MI_PREV_ITEM:
+ if (kbd_navigation)
+ result = TTYM_PREV;
+ else
+ leave = 0;
+ break;
+ case MI_SCROLL_FORWARD:
+ if (y - min_y == state[0].menu->count - 1 - first_item)
+ {
+ y = min_y;
+ first_item = 0;
+ }
+ else
+ first_item++;
+ leave = 0;
+ break;
+ case MI_SCROLL_BACK:
+ if (first_item == 0)
+ {
+ y = max_y;
+ first_item = state[0].menu->count - 1 - (y - min_y);
+ }
+ else
+ first_item--;
+ leave = 0;
+ break;
+ default:
+ /* MI_ITEM_SELECTED is handled below, so nothing to do. */
+ break;
}
- leave = 1;
}
- else if (sf->mouse_moved)
+ if (sf->mouse_moved && input_status != MI_QUIT_MENU)
{
sf->mouse_moved = 0;
result = TTYM_IA_SELECT;
for (i = 0; i < statecount; i++)
if (state[i].x <= x && x < state[i].x + state[i].menu->width + 2)
{
- int dy = y - state[i].y;
+ int dy = y - state[i].y + first_item;
if (0 <= dy && dy < state[i].menu->count)
{
if (!state[i].menu->submenu[dy])
have been opened. That does not include an open and
active submenu. */
if (i != statecount - 2
- || state[i].menu->submenu[dy] != state[i+1].menu)
+ || state[i].menu->submenu[dy] != state[i + 1].menu)
while (i != statecount - 1)
{
statecount--;
- mouse_off (); /* FIXME */
screen_update (sf, state[statecount].screen_behind);
state[statecount].screen_behind = NULL;
}
state[i].x,
state[i].y,
state[i].pane,
- faces, 1);
+ faces, x, y, first_item, 1);
state[statecount].menu = state[i].menu->submenu[dy];
state[statecount].pane = state[i].menu->panenumber[dy];
- mouse_off (); /* FIXME */
state[statecount].screen_behind
- = save_current_matrix (sf);
+ = save_and_enable_current_matrix (sf);
state[statecount].x
= state[i].x + state[i].menu->width + 2;
state[statecount].y = y;
state[statecount - 1].x,
state[statecount - 1].y,
state[statecount - 1].pane,
- faces, 1);
+ faces, x, y, first_item, 1);
+ /* The call to display help-echo below will move the cursor,
+ so remember its current position as computed by
+ tty_menu_display. */
+ col = cursorX (tty);
+ row = cursorY (tty);
}
/* Display the help-echo message for the currently-selected menu
{
help_callback (menu_help_message,
menu_help_paneno, menu_help_itemno);
- tty_hide_cursor (tty);
+ /* Move the cursor to the beginning of the current menu
+ item, so that screen readers and other accessibility aids
+ know where the active region is. */
+ cursor_to (sf, row, col);
prev_menu_help_message = menu_help_message;
}
-#if 0
- /* We are busy-waiting for the mouse to move, so let's be nice
- to other Windows applications by releasing our time slice. */
- Sleep (20); /* FIXME */
-
- for (b = 0; b < mouse_button_count && !leave; b++)
- {
- /* Only leave if user both pressed and released the mouse, and in
- that order. This avoids popping down the menu pane unless
- the user is really done with it. */
- if (mouse_pressed (b, &x, &y))
- {
- while (mouse_button_depressed (b, &x, &y))
- Sleep (20); /* FIXME */
- leave = 1;
- }
- (void) mouse_released (b, &x, &y);
- }
-#endif
+ /* Both tty_menu_display and help_callback invoke update_end,
+ which calls tty_show_cursor. Re-hide it, so it doesn't show
+ through the menus. */
+ tty_hide_cursor (tty);
+ fflush (tty->output);
}
- mouse_off (); /* FIXME */
sf->mouse_moved = 0;
- /* FIXME: Since we set the fram's garbaged flag, do we need this
- call to screen_update? */
screen_update (sf, state[0].screen_behind);
- state[0].screen_behind = NULL;
-#if 0
- /* We have a situation here. ScreenUpdate has just restored the
- screen contents as it was before we started drawing this menu.
- That includes any echo area message that could have been
- displayed back then. (In reality, that echo area message will
- almost always be the ``keystroke echo'' that echoes the sequence
- of menu items chosen by the user.) However, if the menu had some
- help messages, then displaying those messages caused Emacs to
- forget about the original echo area message. So when
- ScreenUpdate restored it, it created a discrepancy between the
- actual screen contents and what Emacs internal data structures
- know about it.
-
- To avoid this conflict, we force Emacs to restore the original
- echo area message as we found it when we entered this function.
- The irony of this is that we then erase the restored message
- right away, so the only purpose of restoring it is so that
- erasing it works correctly... */
- if (! NILP (saved_echo_area_message))
- message_with_string ("%s", saved_echo_area_message, 0);
- message (0);
-#endif
while (statecount--)
free_saved_screen (state[statecount].screen_behind);
- tty_show_cursor (tty); /* turn cursor back on */
+ tty_show_cursor (tty); /* Turn cursor back on. */
+ fflush (tty->output);
/* Clean up any mouse events that are waiting inside Emacs event queue.
These events are likely to be generated before the menu was even
(which invoked the menu) too quickly. If we don't remove these events,
Emacs will process them after we return and surprise the user. */
discard_mouse_events ();
-#if 0
- mouse_clear_clicks ();
-#endif
if (!kbd_buffer_events_waiting ())
clear_input_pending ();
-#if 0
- /* Allow mouse events generation by dos_rawgetc. */
- mouse_preempted--;
-#endif
- SET_FRAME_GARBAGED (sf);
return result;
}
/* Dispose of a menu. */
-void
+static void
tty_menu_destroy (tty_menu *menu)
{
int i;
menu_help_message = prev_menu_help_message = NULL;
}
-static struct frame *tty_menu_help_frame;
-
/* Show help HELP_STRING, or clear help if HELP_STRING is null.
PANE is the pane number, and ITEM is the menu item number in
- the menu (currently not used).
-
- This cannot be done with generating a HELP_EVENT because
- XMenuActivate contains a loop that doesn't let Emacs process
- keyboard events.
-
- FIXME: Do we need this in TTY menus? */
+ the menu (currently not used). */
static void
tty_menu_help_callback (char const *help_string, int pane, int item)
unblock_input ();
}
+/* Return the zero-based index of the last menu-bar item on frame F. */
+static int
+tty_menu_last_menubar_item (struct frame *f)
+{
+ int i = 0;
+
+ eassert (FRAME_TERMCAP_P (f) && FRAME_LIVE_P (f));
+ if (FRAME_TERMCAP_P (f) && FRAME_LIVE_P (f))
+ {
+ Lisp_Object items = FRAME_MENU_BAR_ITEMS (f);
+
+ while (i < ASIZE (items))
+ {
+ Lisp_Object str;
+
+ str = AREF (items, i + 1);
+ if (NILP (str))
+ break;
+ i += 4;
+ }
+ i -= 4; /* Went one too far! */
+ }
+ return i;
+}
+
+/* Find in frame F's menu bar the menu item that is next or previous
+ to the item at X/Y, and return that item's position in X/Y. WHICH
+ says which one--next or previous--item to look for. X and Y are
+ measured in character cells. This should only be called on TTY
+ frames. */
+static void
+tty_menu_new_item_coords (struct frame *f, int which, int *x, int *y)
+{
+ eassert (FRAME_TERMCAP_P (f) && FRAME_LIVE_P (f));
+ if (FRAME_TERMCAP_P (f) && FRAME_LIVE_P (f))
+ {
+ Lisp_Object items = FRAME_MENU_BAR_ITEMS (f);
+ int last_i = tty_menu_last_menubar_item (f);
+ int i, prev_x;
+
+ /* This loop assumes a single menu-bar line, and will fail to
+ find an item if it is not in the first line. Note that
+ make_lispy_event in keyboard.c makes the same assumption. */
+ for (i = 0, prev_x = -1; i < ASIZE (items); i += 4)
+ {
+ Lisp_Object pos, str;
+ int ix;
+
+ str = AREF (items, i + 1);
+ pos = AREF (items, i + 3);
+ if (NILP (str))
+ return;
+ ix = XINT (pos);
+ if (ix <= *x
+ /* We use <= so the blank between 2 items on a TTY is
+ considered part of the previous item. */
+ && *x <= ix + menu_item_width (SDATA (str)))
+ {
+ /* Found current item. Now compute the X coordinate of
+ the previous or next item. */
+ if (which == TTYM_NEXT)
+ {
+ if (i < last_i)
+ *x = XINT (AREF (items, i + 4 + 3));
+ else
+ *x = 0; /* Wrap around to the first item. */
+ }
+ else if (prev_x < 0)
+ {
+ /* Wrap around to the last item. */
+ *x = XINT (AREF (items, last_i + 3));
+ }
+ else
+ *x = prev_x;
+ return;
+ }
+ prev_x = ix;
+ }
+ }
+}
+
+/* WINDOWSNT uses this as menu_show_hook, see w32console.c. */
Lisp_Object
-tty_menu_show (struct frame *f, int x, int y, int for_click, int keymaps,
+tty_menu_show (struct frame *f, int x, int y, int menuflags,
Lisp_Object title, const char **error_name)
{
tty_menu *menu;
Lisp_Object entry, pane_prefix;
char *datap;
int ulx, uly, width, height;
+ int item_x, item_y;
int dispwidth, dispheight;
int i, j, lines, maxlines;
int maxwidth;
- int dummy_int;
- unsigned int dummy_uint;
- ptrdiff_t specpdl_count = SPECPDL_INDEX ();
+ ptrdiff_t specpdl_count;
- if (! FRAME_TERMCAP_P (f))
- emacs_abort ();
+ eassert (FRAME_TERMCAP_P (f));
*error_name = 0;
if (menu_items_n_panes == 0)
return Qnil;
}
- /* Don't GC while we prepare and show the menu, because we give the
- menu functions pointers to the contents of strings. */
- inhibit_garbage_collection ();
+ dynwind_begin ();
+
+ /* Avoid crashes if, e.g., another client will connect while we
+ are in a menu. */
+ temporarily_switch_to_single_kboard (f);
/* Adjust coordinates to be root-window-relative. */
- x += f->left_pos;
- y += f->top_pos;
+ item_x = x += f->left_pos;
+ item_y = y += f->top_pos;
/* Create all the necessary panes and their items. */
maxwidth = maxlines = lines = i = 0;
prefix = AREF (menu_items, i + MENU_ITEMS_PANE_PREFIX);
pane_string = (NILP (pane_name)
? "" : SSDATA (pane_name));
- if (keymaps && !NILP (prefix))
+ if ((menuflags & MENU_KEYMAPS) && !NILP (prefix))
pane_string++;
lpane = tty_menu_add_pane (menu, pane_string);
{
tty_menu_destroy (menu);
*error_name = "Can't create pane";
- return Qnil;
+ entry = Qnil;
+ goto tty_menu_end;
}
i += MENU_ITEMS_PANE_LENGTH;
if (!NILP (descrip))
{
- /* if alloca is fast, use that to make the space,
+ /* If alloca is fast, use that to make the space,
to reduce gc needs. */
item_data = (char *) alloca (maxwidth + SBYTES (descrip) + 1);
memcpy (item_data, SSDATA (item_name), SBYTES (item_name));
item_data = SSDATA (item_name);
if (lpane == TTYM_FAILURE
- || (tty_menu_add_selection (menu, lpane, item_data,
- !NILP (enable), help_string)
- == TTYM_FAILURE))
+ || (! tty_menu_add_selection (menu, lpane, item_data,
+ !NILP (enable), help_string)))
{
tty_menu_destroy (menu);
*error_name = "Can't add selection to menu";
- return Qnil;
+ entry = Qnil;
+ goto tty_menu_end;
}
i += MENU_ITEMS_ITEM_LENGTH;
lines++;
x = max (x, 1);
y = max (y, 1);
tty_menu_locate (menu, x, y, &ulx, &uly, &width, &height);
- if (ulx+width > dispwidth)
+ if (ulx + width > dispwidth)
{
x -= (ulx + width) - dispwidth;
ulx = dispwidth - width;
}
- if (uly+height > dispheight)
+ if (uly + height > dispheight)
{
y -= (uly + height) - dispheight;
uly = dispheight - height;
}
- if (FRAME_HAS_MINIBUF_P (f) && uly+height > dispheight - 2)
+ if (FRAME_HAS_MINIBUF_P (f) && uly + height > dispheight - 2)
{
/* Move the menu away of the echo area, to avoid overwriting the
menu with help echo messages or vice versa. */
#if 0
/* This code doesn't make sense on a TTY, since it can easily annul
the adjustments above that carefully avoid truncation of the menu
- items. */
+ items. I think it was written to fix some problem that only
+ happens on X11. */
if (! for_click)
{
/* If position was not given by a mouse click, adjust so upper left
corner of the menu as a whole ends up at given coordinates. This
is what x-popup-menu says in its documentation. */
- x += width/2;
- y += 1.5*height/(maxlines+2);
+ x += width / 2;
+ y += 1.5 * height / (maxlines + 2);
}
#endif
record_unwind_protect (tty_pop_down_menu, make_save_ptr (menu));
- tty_menu_help_frame = f; /* FIXME: This seems unused. */
specbind (Qoverriding_terminal_local_map,
Fsymbol_value (Qtty_menu_navigation_map));
status = tty_menu_activate (menu, &pane, &selidx, x, y, &datap,
- tty_menu_help_callback);
+ tty_menu_help_callback,
+ menuflags & MENU_KBD_NAVIGATION);
entry = pane_prefix = Qnil;
switch (status)
{
entry
= AREF (menu_items, i + MENU_ITEMS_ITEM_VALUE);
- if (keymaps != 0)
+ if (menuflags & MENU_KEYMAPS)
{
entry = Fcons (entry, Qnil);
if (!NILP (pane_prefix))
}
break;
+ case TTYM_NEXT:
+ case TTYM_PREV:
+ tty_menu_new_item_coords (f, status, &item_x, &item_y);
+ entry = Fcons (make_number (item_x), make_number (item_y));
+ break;
+
case TTYM_FAILURE:
*error_name = "Can't activate menu";
case TTYM_IA_SELECT:
break;
case TTYM_NO_SELECT:
+ /* If the selected frame was changed while we displayed a menu,
+ throw to top level in order to undo any temporary settings
+ made by TTY menu code. */
+ if (f != SELECTED_FRAME ())
+ Ftop_level ();
/* Make "Cancel" equivalent to C-g unless FOR_CLICK (which means
the menu was invoked with a mouse event as POSITION). */
- if (! for_click)
+ if (!(menuflags & MENU_FOR_CLICK))
Fsignal (Qquit, Qnil);
break;
}
- unbind_to (specpdl_count, Qnil);
+ tty_menu_end:
+ dynwind_end ();
return entry;
}
-#endif /* HAVE_MENUS && !MSDOS */
+#endif /* !MSDOS */
\f
#ifndef MSDOS
***********************************************************************/
/* Initialize the tty-dependent part of frame F. The frame must
- already have its device initialized. */
+ already have its device initialized. */
void
create_tty_output (struct frame *f)
f->output_data.tty = t;
}
-/* Delete frame F's face cache, and its tty-dependent part. */
+/* Delete frame F's face cache, and its tty-dependent part. */
static void
tty_free_frame_resources (struct frame *f)
{
eassert (FRAME_TERMCAP_P (f));
-
- if (FRAME_FACE_CACHE (f))
- free_frame_faces (f);
-
+ free_frame_faces (f);
xfree (f->output_data.tty);
}
#else /* MSDOS */
-/* Delete frame F's face cache. */
+/* Delete frame F's face cache. */
static void
tty_free_frame_resources (struct frame *f)
{
eassert (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f));
-
- if (FRAME_FACE_CACHE (f))
- free_frame_faces (f);
+ free_frame_faces (f);
}
#endif /* MSDOS */
\f
terminal->frame_rehighlight_hook = 0;
terminal->frame_raise_lower_hook = 0;
terminal->fullscreen_hook = 0;
+ terminal->menu_show_hook = 0;
terminal->set_vertical_scroll_bar_hook = 0;
terminal->condemn_scroll_bars_hook = 0;
terminal->redeem_scroll_bar_hook = 0;
static void
set_tty_hooks (struct terminal *terminal)
{
- terminal->rif = 0; /* ttys don't support window-based redisplay. */
-
terminal->cursor_to_hook = &tty_cursor_to;
terminal->raw_cursor_to_hook = &tty_raw_cursor_to;
-
terminal->clear_to_end_hook = &tty_clear_to_end;
terminal->clear_frame_hook = &tty_clear_frame;
terminal->clear_end_of_line_hook = &tty_clear_end_of_line;
-
terminal->ins_del_lines_hook = &tty_ins_del_lines;
-
terminal->insert_glyphs_hook = &tty_insert_glyphs;
terminal->write_glyphs_hook = &tty_write_glyphs;
terminal->delete_glyphs_hook = &tty_delete_glyphs;
-
terminal->ring_bell_hook = &tty_ring_bell;
-
terminal->reset_terminal_modes_hook = &tty_reset_terminal_modes;
terminal->set_terminal_modes_hook = &tty_set_terminal_modes;
- terminal->update_begin_hook = 0; /* Not needed. */
terminal->update_end_hook = &tty_update_end;
+ terminal->menu_show_hook = &tty_menu_show;
terminal->set_terminal_window_hook = &tty_set_terminal_window;
-
- terminal->mouse_position_hook = 0; /* Not needed. */
- terminal->frame_rehighlight_hook = 0; /* Not needed. */
- terminal->frame_raise_lower_hook = 0; /* Not needed. */
-
- terminal->set_vertical_scroll_bar_hook = 0; /* Not needed. */
- terminal->condemn_scroll_bars_hook = 0; /* Not needed. */
- terminal->redeem_scroll_bar_hook = 0; /* Not needed. */
- terminal->judge_scroll_bars_hook = 0; /* Not needed. */
-
terminal->read_socket_hook = &tty_read_avail_input; /* keyboard.c */
- terminal->frame_up_to_date_hook = 0; /* Not needed. */
-
terminal->delete_frame_hook = &tty_free_frame_resources;
terminal->delete_terminal_hook = &delete_tty;
+ /* Other hooks are NULL by default. */
}
/* If FD is the controlling terminal, drop it. */
/* setsid failed, presumably because Emacs is already a process
group leader. Fall back on the obsolescent way to dissociate
a controlling tty. */
- block_tty_out_signal ();
+ sigset_t oldset;
+ block_tty_out_signal (&oldset);
ioctl (fd, TIOCNOTTY, 0);
- unblock_tty_out_signal ();
+ unblock_tty_out_signal (&oldset);
#endif
}
}
struct terminal *
init_tty (const char *name, const char *terminal_type, bool must_succeed)
{
-#ifdef TERMINFO
- char **address = 0;
-#else
char *area;
char **address = &area;
-#endif
int status;
struct tty_display_info *tty = NULL;
struct terminal *terminal = NULL;
+ sigset_t oldset;
bool ctty = false; /* True if asked to open controlling tty. */
if (!terminal_type)
if (terminal)
return terminal;
- terminal = create_terminal ();
+ terminal = create_terminal (output_termcap, NULL);
#ifdef MSDOS
if (been_here > 0)
maybe_fatal (0, 0, "Attempt to create another terminal %s", "",
tty->next = tty_list;
tty_list = tty;
- terminal->type = output_termcap;
terminal->display_info.tty = tty;
tty->terminal = terminal;
open a frame on the same terminal. */
int flags = O_RDWR | O_NOCTTY | (ctty ? 0 : O_IGNORE_CTTY);
int fd = emacs_open (name, flags, 0);
- tty->input = tty->output = fd < 0 || ! isatty (fd) ? 0 : fdopen (fd, "w+");
+ tty->input = tty->output =
+ ((fd < 0 || ! isatty (fd))
+ ? NULL
+ : fdopen (fd, "w+"));
if (! tty->input)
{
char const *diagnostic
- = tty->input ? "Not a tty device: %s" : "Could not open file: %s";
+ = (fd < 0) ? "Could not open file: %s" : "Not a tty device: %s";
emacs_close (fd);
maybe_fatal (must_succeed, terminal, diagnostic, diagnostic, name);
}
/* On some systems, tgetent tries to access the controlling
terminal. */
- block_tty_out_signal ();
-#ifdef TERMINFO
- status = tgetent (0, terminal_type);
-#else
+ block_tty_out_signal (&oldset);
status = tgetent (tty->termcap_term_buffer, terminal_type);
if (tty->termcap_term_buffer[TERMCAP_BUFFER_SIZE - 1])
emacs_abort ();
-#endif
- unblock_tty_out_signal ();
+ unblock_tty_out_signal (&oldset);
if (status < 0)
{
terminal_type);
}
-#ifndef TERMINFO
area = tty->termcap_strings_buffer;
-#endif
tty->TS_ins_line = tgetstr ("al", address);
tty->TS_ins_multi_lines = tgetstr ("AL", address);
tty->TS_bell = tgetstr ("bl", address);
/* Since we make MagicWrap terminals look like AutoWrap, we need to have
the former flag imply the latter. */
AutoWrap (tty) = MagicWrap (tty) || tgetflag ("am");
- terminal->memory_below_frame = tgetflag ("db");
+ tty->memory_below_frame = tgetflag ("db");
tty->TF_hazeltine = tgetflag ("hz");
- terminal->must_write_spaces = tgetflag ("in");
+ tty->must_write_spaces = tgetflag ("in");
tty->meta_key = tgetflag ("km") || tgetflag ("MT");
tty->TF_insmode_motion = tgetflag ("mi");
tty->TF_standout_motion = tgetflag ("ms");
tty->specified_window = height;
FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
- terminal->char_ins_del_ok = 1;
+ tty->char_ins_del_ok = 1;
baud_rate = 19200;
}
#else /* MSDOS */
get_tty_size (fileno (tty->input), &width, &height);
FrameCols (tty) = width;
FrameRows (tty) = height;
- terminal->char_ins_del_ok = 0;
+ tty->char_ins_del_ok = 0;
init_baud_rate (fileno (tty->input));
}
#endif /* MSDOS */
tty->delete_in_insert_mode = 1;
UseTabs (tty) = 0;
- terminal->scroll_region_ok = 0;
+ tty->scroll_region_ok = 0;
/* Seems to insert lines when it's not supposed to, messing up the
display. In doing a trace, it didn't seem to be called much, so I
don't think we're losing anything by turning it off. */
- terminal->line_ins_del_ok = 0;
+ tty->line_ins_del_ok = 0;
tty->TN_max_colors = 16; /* Must be non-zero for tty-display-color-p. */
#endif /* DOS_NT */
tty->mouse_highlight.mouse_face_window = Qnil;
#endif
- terminal->kboard = xmalloc (sizeof *terminal->kboard);
- init_kboard (terminal->kboard);
- kset_window_system (terminal->kboard, Qnil);
- terminal->kboard->next_kboard = all_kboards;
- all_kboards = terminal->kboard;
+ terminal->kboard = allocate_kboard (Qnil);
terminal->kboard->reference_count++;
/* Don't let the initial kboard remain current longer than necessary.
That would cause problems if a file loaded on startup tries to
UseTabs (tty) = tabs_safe_p (fileno (tty->input)) && TabWidth (tty) == 8;
- terminal->scroll_region_ok
+ tty->scroll_region_ok
= (tty->Wcm->cm_abs
&& (tty->TS_set_window || tty->TS_set_scroll_region || tty->TS_set_scroll_region_1));
- terminal->line_ins_del_ok
+ tty->line_ins_del_ok
= (((tty->TS_ins_line || tty->TS_ins_multi_lines)
&& (tty->TS_del_line || tty->TS_del_multi_lines))
- || (terminal->scroll_region_ok
+ || (tty->scroll_region_ok
&& tty->TS_fwd_scroll && tty->TS_rev_scroll));
- terminal->char_ins_del_ok
+ tty->char_ins_del_ok
= ((tty->TS_ins_char || tty->TS_insert_mode
|| tty->TS_pad_inserted_char || tty->TS_ins_multi_chars)
&& (tty->TS_del_char || tty->TS_del_multi_chars));
- terminal->fast_clear_end_of_line = tty->TS_clr_line != 0;
-
init_baud_rate (fileno (tty->input));
#endif /* not DOS_NT */
void
syms_of_term (void)
{
+#include "term.x"
+
DEFVAR_BOOL ("system-uses-terminfo", system_uses_terminfo,
doc: /* Non-nil means the system uses terminfo rather than termcap.
This variable can be used by terminal emulator packages. */);
bigger, or it may make it blink, or it may do nothing at all. */);
visible_cursor = 1;
- defsubr (&Stty_display_color_p);
- defsubr (&Stty_display_color_cells);
- defsubr (&Stty_no_underline);
- defsubr (&Stty_type);
- defsubr (&Scontrolling_tty_p);
- defsubr (&Stty_top_frame);
- defsubr (&Ssuspend_tty);
- defsubr (&Sresume_tty);
-#ifdef HAVE_GPM
- defsubr (&Sgpm_mouse_start);
- defsubr (&Sgpm_mouse_stop);
-#endif /* HAVE_GPM */
-
#ifndef DOS_NT
default_orig_pair = NULL;
default_set_foreground = NULL;
encode_terminal_src = NULL;
encode_terminal_dst = NULL;
+ DEFSYM (Qtty_mode_set_strings, "tty-mode-set-strings");
+ DEFSYM (Qtty_mode_reset_strings, "tty-mode-reset-strings");
+
+#ifndef MSDOS
DEFSYM (Qtty_menu_next_item, "tty-menu-next-item");
DEFSYM (Qtty_menu_prev_item, "tty-menu-prev-item");
DEFSYM (Qtty_menu_next_menu, "tty-menu-next-menu");
DEFSYM (Qtty_menu_select, "tty-menu-select");
DEFSYM (Qtty_menu_ignore, "tty-menu-ignore");
DEFSYM (Qtty_menu_exit, "tty-menu-exit");
+ DEFSYM (Qtty_menu_mouse_movement, "tty-menu-mouse-movement");
DEFSYM (Qtty_menu_navigation_map, "tty-menu-navigation-map");
+#endif
}