/* Terminal control module for terminals described by TERMCAP
Copyright (C) 1985, 1986, 1987, 1993, 1994, 1995, 1998, 2000, 2001,
- 2002, 2003, 2004, 2005, 2006, 2007 Free Software Foundation, Inc.
+ 2002, 2003, 2004, 2005, 2006, 2007, 2008
+ Free Software Foundation, Inc.
This file is part of GNU Emacs.
#endif
#include <signal.h>
+#include <stdarg.h>
#include "lisp.h"
#include "termchar.h"
#define O_NOCTTY 0
#endif
+/* The name of the default console device. */
+#ifdef WINDOWSNT
+#define DEV_TTY "CONOUT$"
+#else
+#define DEV_TTY "/dev/tty"
+#endif
+
static void tty_set_scroll_region P_ ((struct frame *f, int start, int stop));
static void turn_on_face P_ ((struct frame *, int face_id));
static void turn_off_face P_ ((struct frame *, int face_id));
char *tparam ();
extern char *tgetstr ();
-
-static void term_clear_mouse_face ();
-static void term_mouse_highlight (struct frame *f, int x, int y);
\f
-#ifdef WINDOWSNT
-/* We aren't X windows, but we aren't termcap either. This makes me
- uncertain as to what value to use for frame.output_method. For
- this file, we'll define FRAME_TERMCAP_P to be zero so that our
- output hooks get called instead of the termcap functions. Probably
- the best long-term solution is to define an output_windows_nt... */
-
-#undef FRAME_TERMCAP_P
-#define FRAME_TERMCAP_P(_f_) 0
-#endif /* WINDOWSNT */
-
#ifdef HAVE_GPM
#include <sys/fcntl.h>
#include "buffer.h"
-/* Nonzero means mouse is enabled on Linux console. */
-int term_gpm = 0;
+static void term_clear_mouse_face ();
+static void term_mouse_highlight (struct frame *f, int x, int y);
-/* The id of the terminal device for which we have gpm support. */
-int gpm_tty;
+/* The device for which we have enabled gpm support (or NULL). */
+struct tty_display_info *gpm_tty = NULL;
/* These variables describe the range of text currently shown in its
mouse-face, together with the window they apply to. As long as
static int mouse_face_beg_row, mouse_face_beg_col;
static int mouse_face_end_row, mouse_face_end_col;
static int mouse_face_past_end;
-static Lisp_Object Qmouse_face_window;
+static Lisp_Object mouse_face_window;
static int mouse_face_face_id;
static int pos_x, pos_y;
cmcheckmagic (tty);
}
+#ifdef HAVE_GPM /* Only used by GPM code. */
+
static void
tty_write_glyphs_with_face (f, string, len, face_id)
register struct frame *f;
cmcheckmagic (tty);
}
-
+#endif
/* An implementation of insert_glyphs for termcap frames. */
static KBOARD *term_get_fkeys_kboard;
static Lisp_Object term_get_fkeys_1 ();
-/* Find the escape codes sent by the function keys for Vfunction_key_map.
+/* Find the escape codes sent by the function keys for Vinput_decode_map.
This function scans the termcap function key sequence entries, and
- adds entries to Vfunction_key_map for each function key it finds. */
+ adds entries to Vinput_decode_map for each function key it finds. */
static void
term_get_fkeys (address, kboard)
KBOARD *kboard = term_get_fkeys_kboard;
/* This can happen if CANNOT_DUMP or with strange options. */
- if (!initialized)
- kboard->Vlocal_function_key_map = Fmake_sparse_keymap (Qnil);
+ if (!KEYMAPP (kboard->Vinput_decode_map))
+ kboard->Vinput_decode_map = Fmake_sparse_keymap (Qnil);
for (i = 0; i < (sizeof (keys)/sizeof (keys[0])); i++)
{
char *sequence = tgetstr (keys[i].cap, address);
if (sequence)
- Fdefine_key (kboard->Vlocal_function_key_map, build_string (sequence),
+ Fdefine_key (kboard->Vinput_decode_map, build_string (sequence),
Fmake_vector (make_number (1),
intern (keys[i].name)));
}
if (k0)
/* Define f0 first, so that f10 takes precedence in case the
key sequences happens to be the same. */
- Fdefine_key (kboard->Vlocal_function_key_map, build_string (k0),
+ Fdefine_key (kboard->Vinput_decode_map, build_string (k0),
Fmake_vector (make_number (1), intern ("f0")));
- Fdefine_key (kboard->Vlocal_function_key_map, build_string (k_semi),
+ Fdefine_key (kboard->Vinput_decode_map, build_string (k_semi),
Fmake_vector (make_number (1), intern ("f10")));
}
else if (k0)
- Fdefine_key (kboard->Vlocal_function_key_map, build_string (k0),
+ Fdefine_key (kboard->Vinput_decode_map, build_string (k0),
Fmake_vector (make_number (1), intern (k0_name)));
}
if (sequence)
{
sprintf (fkey, "f%d", i);
- Fdefine_key (kboard->Vlocal_function_key_map, build_string (sequence),
+ Fdefine_key (kboard->Vinput_decode_map, build_string (sequence),
Fmake_vector (make_number (1),
intern (fkey)));
}
{ \
char *sequence = tgetstr (cap2, address); \
if (sequence) \
- Fdefine_key (kboard->Vlocal_function_key_map, build_string (sequence), \
+ Fdefine_key (kboard->Vinput_decode_map, build_string (sequence), \
Fmake_vector (make_number (1), \
intern (sym))); \
}
{
struct terminal *t = get_terminal (terminal, throw);
- if (t && t->type == output_initial)
- return NULL;
-
if (t && t->type != output_termcap)
{
if (throw)
{
struct terminal *t = get_terminal (terminal, 1);
- if (t->type != output_termcap || strcmp (t->display_info.tty->name, "/dev/tty"))
+ if (t->type != output_termcap || strcmp (t->display_info.tty->name, DEV_TTY))
return Qnil;
else
return Qt;
if (f)
{
+ /* First run `suspend-tty-functions' and then clean up the tty
+ state because `suspend-tty-functions' might need to change
+ the tty state. */
+ if (!NILP (Vrun_hooks))
+ {
+ Lisp_Object args[2];
+ args[0] = intern ("suspend-tty-functions");
+ XSETTERMINAL (args[1], t);
+ Frun_hook_with_args (2, args);
+ }
+
reset_sys_modes (t->display_info.tty);
delete_keyboard_wait_descriptor (fileno (f));
if (FRAMEP (t->display_info.tty->top_frame))
FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 0);
- /* Run `suspend-tty-functions'. */
- if (!NILP (Vrun_hooks))
- {
- Lisp_Object args[2];
- args[0] = intern ("suspend-tty-functions");
- args[1] = make_number (t->id);
- Frun_hook_with_args (2, args);
- }
}
/* Clear display hooks to prevent further output. */
if (fd == -1)
error ("Can not reopen tty device %s: %s", t->display_info.tty->name, strerror (errno));
- if (strcmp (t->display_info.tty->name, "/dev/tty"))
+ if (strcmp (t->display_info.tty->name, DEV_TTY))
dissociate_if_controlling_tty (fd);
-
+
t->display_info.tty->output = fdopen (fd, "w+");
t->display_info.tty->input = t->display_info.tty->output;
-
+
add_keyboard_wait_descriptor (fd);
if (FRAMEP (t->display_info.tty->top_frame))
init_sys_modes (t->display_info.tty);
- /* Run `suspend-tty-functions'. */
+ /* Run `resume-tty-functions'. */
if (!NILP (Vrun_hooks))
{
Lisp_Object args[2];
args[0] = intern ("resume-tty-functions");
- args[1] = make_number (t->id);
+ XSETTERMINAL (args[1], t);
Frun_hook_with_args (2, args);
}
}
static void
term_show_mouse_face (enum draw_glyphs_face draw)
{
- struct window *w = XWINDOW (Qmouse_face_window);
+ struct window *w = XWINDOW (mouse_face_window);
int save_x, save_y;
int i;
static void
term_clear_mouse_face ()
{
- if (!NILP (Qmouse_face_window))
+ if (!NILP (mouse_face_window))
term_show_mouse_face (DRAW_NORMAL_TEXT);
mouse_face_beg_row = mouse_face_beg_col = -1;
mouse_face_end_row = mouse_face_end_col = -1;
- Qmouse_face_window = Qnil;
+ mouse_face_window = Qnil;
}
/* Find the glyph matrix position of buffer position POS in window W.
if (!WINDOWP (window))
return;
- if (!EQ (window, Qmouse_face_window))
+ if (!EQ (window, mouse_face_window))
term_clear_mouse_face ();
w = XWINDOW (window);
noverlays = sort_overlays (overlay_vec, noverlays, w);
/* Check mouse-face highlighting. */
- if (!(EQ (window, Qmouse_face_window)
+ if (!(EQ (window, mouse_face_window)
&& y >= mouse_face_beg_row
&& y <= mouse_face_end_row
&& (y > mouse_face_beg_row
= !fast_find_position (w, XFASTINT (after),
&mouse_face_end_col,
&mouse_face_end_row);
- Qmouse_face_window = window;
+ mouse_face_window = window;
mouse_face_face_id
= face_at_buffer_position (w, pos, 0, 0,
= !fast_find_position (w, XFASTINT (after),
&mouse_face_end_col,
&mouse_face_end_row);
- Qmouse_face_window = window;
+ mouse_face_window = window;
mouse_face_face_id
= face_at_buffer_position (w, pos, 0, 0,
handle_one_term_event (struct tty_display_info *tty, Gpm_Event *event, struct input_event* hold_quit)
{
struct frame *f = XFRAME (tty->top_frame);
- int fd;
struct input_event ie;
int do_help = 0;
int count = 0;
ie.arg = Qnil;
if (event->type & (GPM_MOVE | GPM_DRAG)) {
- unsigned char buf[6 * sizeof (short)];
- unsigned short *arg = (unsigned short *) buf + 1;
- const char *name;
-
previous_help_echo_string = help_echo_string;
help_echo_string = Qnil;
- /* Display mouse pointer */
- buf[sizeof(short) - 1] = 2; /* set selection */
-
- arg[0] = arg[2] = (unsigned short) event->x + gpm_zerobased;
- arg[1] = arg[3] = (unsigned short) event->y + gpm_zerobased;
- arg[4] = (unsigned short) 3;
-
- name = ttyname (0);
- fd = open (name, O_WRONLY);
- ioctl (fd, TIOCLINUX, buf + sizeof (short) - 1);
- close (fd);
+ Gpm_DrawPointer (event->x, event->y, fileno (tty->output));
if (!term_mouse_movement (f, event))
help_echo_string = previous_help_echo_string;
return count;
}
-DEFUN ("term-open-connection", Fterm_open_connection, Sterm_open_connection,
+DEFUN ("gpm-mouse-start", Fgpm_mouse_start, Sgpm_mouse_start,
0, 0, 0,
- doc: /* Open a connection to Gpm. */)
+ doc: /* Open a connection to Gpm.
+Gpm-mouse can only be activated for one tty at a time. */)
()
{
- struct tty_display_info *tty = FRAME_TTY (SELECTED_FRAME ());
+ struct frame *f = SELECTED_FRAME ();
+ struct tty_display_info *tty
+ = ((f)->output_method == output_termcap
+ ? (f)->terminal->display_info.tty : NULL);
Gpm_Connect connection;
+ if (!tty)
+ error ("Gpm-mouse only works in the GNU/Linux console");
+ if (gpm_tty == tty)
+ return Qnil; /* Already activated, nothing to do. */
+ if (gpm_tty)
+ error ("Gpm-mouse can only be activated for one tty at a time");
+
connection.eventMask = ~0;
connection.defaultMask = ~GPM_HARD;
connection.maxMod = ~0;
connection.minMod = 0;
gpm_zerobased = 1;
- /* We only support GPM on the controlling tty. */
- if (term_gpm || tty->terminal->id > 1
- || Gpm_Open (&connection, 0) < 0)
- return Qnil;
+ if (Gpm_Open (&connection, 0) < 0)
+ error ("Gpm-mouse failed to connect to the gpm daemon");
else
{
- term_gpm = 1;
- gpm_tty = tty->terminal->id;
+ gpm_tty = tty;
+ /* `init_sys_modes' arranges for mouse movements sent through gpm_fd
+ to generate SIGIOs. Apparently we need to call reset_sys_modes
+ before calling init_sys_modes. */
reset_sys_modes (tty);
init_sys_modes (tty);
add_gpm_wait_descriptor (gpm_fd);
- return Qt;
+ return Qnil;
}
}
-DEFUN ("term-close-connection", Fterm_close_connection, Sterm_close_connection,
+DEFUN ("gpm-mouse-stop", Fgpm_mouse_stop, Sgpm_mouse_stop,
0, 0, 0,
doc: /* Close a connection to Gpm. */)
()
{
- delete_gpm_wait_descriptor (gpm_fd);
- while (Gpm_Close()); /* close all the stack */
- term_gpm = 0;
- return Qnil;
+ struct frame *f = SELECTED_FRAME ();
+ struct tty_display_info *tty
+ = ((f)->output_method == output_termcap
+ ? (f)->terminal->display_info.tty : NULL);
+
+ if (!tty || gpm_tty != tty)
+ return Qnil; /* Not activated on this terminal, nothing to do. */
+
+ if (gpm_fd >= 0)
+ delete_gpm_wait_descriptor (gpm_fd);
+ while (Gpm_Close()); /* close all the stack */
+ gpm_tty = NULL;
+ return Qnil;
}
#endif /* HAVE_GPM */
}
\f
+/* Reset the hooks in TERMINAL. */
static void
clear_tty_hooks (struct terminal *terminal)
terminal->delete_terminal_hook = &delete_tty;
}
+/* Initialize hooks in TERMINAL with the values needed for a tty. */
+
static void
set_tty_hooks (struct terminal *terminal)
{
#if defined (USG) && !defined (BSD_PGRPS)
setpgrp ();
no_controlling_tty = 1;
+#elif defined (CYGWIN)
+ setsid ();
+ no_controlling_tty = 1;
#else
#ifdef TIOCNOTTY /* Try BSD ioctls. */
sigblock (sigmask (SIGTTOU));
- fd = emacs_open ("/dev/tty", O_RDWR, 0);
+ fd = emacs_open (DEV_TTY, O_RDWR, 0);
if (fd != -1 && ioctl (fd, TIOCNOTTY, 0) != -1)
{
no_controlling_tty = 1;
#endif /* ! TIOCNOTTY */
#endif /* ! USG */
}
-#endif
+#endif /* !WINDOWSNT */
}
static void maybe_fatal();
"Unknown terminal type",
"Unknown terminal type");
-#ifndef WINDOWSNT
if (name == NULL)
- name = "/dev/tty";
- if (!strcmp (name, "/dev/tty"))
+ name = DEV_TTY;
+ if (!strcmp (name, DEV_TTY))
ctty = 1;
/* If we already have a terminal on the given device, use that. If
terminal = get_named_tty (name);
if (terminal)
return terminal;
-#endif
-
+
terminal = create_terminal ();
tty = (struct tty_display_info *) xmalloc (sizeof (struct tty_display_info));
bzero (tty, sizeof (struct tty_display_info));
#ifndef WINDOWSNT
set_tty_hooks (terminal);
-
+
{
int fd;
FILE *file;
tty->input = file;
tty->output = file;
}
-
+
tty->type = xstrdup (terminal_type);
add_keyboard_wait_descriptor (fileno (tty->input));
#ifdef HAVE_GPM
terminal->mouse_position_hook = term_mouse_position;
- Qmouse_face_window = Qnil;
+ mouse_face_window = Qnil;
#endif
#ifdef WINDOWSNT
- initialize_w32_display ();
+ initialize_w32_display (terminal);
+ /* The following two are inaccessible from w32console.c. */
+ terminal->delete_frame_hook = &delete_tty_output;
+ terminal->delete_terminal_hook = &delete_tty;
- /* XXX Can this be non-null? */
- if (name)
- {
- tty->name = xstrdup (name);
- terminal->name = xstrdup (name);
- }
- tty->type = xstrdup (terminal_type);
+ tty->name = xstrdup (name);
+ terminal->name = xstrdup (name);
+ tty->type = xstrdup (terminal_type);
- /* XXX not sure if this line is correct. If it is not set then we
- crash in update_display_1. */
tty->output = stdout;
-
- Wcm_clear (tty);
+ tty->input = stdin;
+ add_keyboard_wait_descriptor (0);
- area = (char *) xmalloc (2044); /* XXX this seems unused. */
+ Wcm_clear (tty);
{
struct frame *f = XFRAME (selected_frame);
- FrameRows (tty) = FRAME_LINES (f); /* XXX */
- FrameCols (tty) = FRAME_COLS (f); /* XXX */
- tty->specified_window = FRAME_LINES (f); /* XXX */
+ FrameRows (tty) = FRAME_LINES (f);
+ FrameCols (tty) = FRAME_COLS (f);
+ tty->specified_window = FRAME_LINES (f);
- FRAME_CAN_HAVE_SCROLL_BARS (f) = 0; /* XXX */
- FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none; /* XXX */
+ FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
+ FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
}
tty->delete_in_insert_mode = 1;
tty->TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */
- return terminal;
#else /* not WINDOWSNT */
Wcm_clear (tty);
buffer = (char *) xmalloc (buffer_size);
-
+
/* On some systems, tgetent tries to access the controlling
terminal. */
sigblock (sigmask (SIGTTOU));
status = tgetent (buffer, terminal_type);
sigunblock (sigmask (SIGTTOU));
-
+
if (status < 0)
{
#ifdef TERMINFO
tty->TF_underscore = tgetflag ("ul");
tty->TF_teleray = tgetflag ("xt");
+#endif /* !WINDOWSNT */
#ifdef MULTI_KBOARD
terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
init_kboard (terminal->kboard);
+ terminal->kboard->Vwindow_system = Qnil;
terminal->kboard->next_kboard = all_kboards;
all_kboards = terminal->kboard;
terminal->kboard->reference_count++;
prompt in the mini-buffer. */
if (current_kboard == initial_kboard)
current_kboard = terminal->kboard;
+#ifndef WINDOWSNT
term_get_fkeys (address, terminal->kboard);
#endif
+#endif
+#ifndef WINDOWSNT
/* Get frame size from system, or else from termcap. */
{
int height, width;
/* Don't do this. I think termcap may still need the buffer. */
/* xfree (buffer); */
+#endif /* not WINDOWSNT */
+
/* Init system terminal modes (RAW or CBREAK, etc.). */
init_sys_modes (tty);
return terminal;
-#endif /* not WINDOWSNT */
}
/* Auxiliary error-handling function for init_tty.
abort ();
}
-/* VARARGS 1 */
void
-fatal (str, arg1, arg2)
- char *str, *arg1, *arg2;
+fatal (const char *str, ...)
{
+ va_list ap;
+ va_start (ap, str);
fprintf (stderr, "emacs: ");
- fprintf (stderr, str, arg1, arg2);
- fprintf (stderr, "\n");
+ vfprintf (stderr, str, ap);
+ va_end (ap);
fflush (stderr);
exit (1);
}
/* Protect against recursive calls. Fdelete_frame in
delete_terminal calls us back when it deletes our last frame. */
- if (terminal->deleted)
+ if (!terminal->name)
return;
if (terminal->type != output_termcap)
defsubr (&Ssuspend_tty);
defsubr (&Sresume_tty);
#ifdef HAVE_GPM
- defsubr (&Sterm_open_connection);
- defsubr (&Sterm_close_connection);
+ defsubr (&Sgpm_mouse_start);
+ defsubr (&Sgpm_mouse_stop);
- staticpro (&Qmouse_face_window);
+ staticpro (&mouse_face_window);
#endif /* HAVE_GPM */
}