/* New redisplay, TTY faces by Gerd Moellmann <gerd@gnu.org>. */
#include <config.h>
-#include <stdio.h>
#include <errno.h>
+#include <fcntl.h>
+#include <stdio.h>
#include <sys/file.h>
#include <sys/time.h>
#include <unistd.h>
#include "xterm.h"
#endif
-#ifndef O_RDWR
-#define O_RDWR 2
-#endif
-
-#ifndef O_NOCTTY
-#define O_NOCTTY 0
-#endif
-
/* The name of the default console device. */
#ifdef WINDOWSNT
#define DEV_TTY "CONOUT$"
static void tty_show_cursor (struct tty_display_info *);
static void tty_hide_cursor (struct tty_display_info *);
static void tty_background_highlight (struct tty_display_info *tty);
-static struct terminal *get_tty_terminal (Lisp_Object, int);
+static struct terminal *get_tty_terminal (Lisp_Object, bool);
static void clear_tty_hooks (struct terminal *terminal);
static void set_tty_hooks (struct terminal *terminal);
static void dissociate_if_controlling_tty (int fd);
static void delete_tty (struct terminal *);
-static _Noreturn void maybe_fatal (int must_succeed, struct terminal *terminal,
- const char *str1, const char *str2, ...)
+static _Noreturn void maybe_fatal (bool, struct terminal *,
+ const char *, const char *, ...)
ATTRIBUTE_FORMAT_PRINTF (3, 5) ATTRIBUTE_FORMAT_PRINTF (4, 5);
static _Noreturn void vfatal (const char *str, va_list ap)
ATTRIBUTE_FORMAT_PRINTF (1, 0);
#define OUTPUT(tty, a) \
emacs_tputs ((tty), a, \
- (int) (FRAME_LINES (XFRAME (selected_frame)) \
- - curY (tty)), \
+ FRAME_LINES (XFRAME (selected_frame)) - curY (tty), \
cmputc)
#define OUTPUT1(tty, a) emacs_tputs ((tty), a, 1, cmputc)
static int max_frame_cols;
-/* Non-zero if we have dropped our controlling tty and therefore
- should not open a frame on stdout. */
-static int no_controlling_tty;
-
\f
#ifdef HAVE_GPM
{
unsigned char *conversion_buffer;
struct coding_system *coding;
- size_t n, stringlen;
+ int n, stringlen;
struct tty_display_info *tty = FRAME_TTY (f);
const char *single = n > 0 ? tty->TS_ins_line : tty->TS_del_line;
const char *scroll = n > 0 ? tty->TS_rev_scroll : tty->TS_fwd_scroll;
- register int i = n > 0 ? n : -n;
- register char *buf;
+ int i = eabs (n);
+ char *buf;
/* If the lines below the insertion are being pushed
into the end of the window, this is the same as clearing;
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 < (sizeof (keys) / sizeof (keys[0])); i++)
{
char *sequence = tgetstr (keys[i].cap, address);
if (sequence)
static void append_composite_glyph (struct it *);
static void produce_composite_glyph (struct it *);
static void append_glyphless_glyph (struct it *, int, const char *);
-static void produce_glyphless_glyph (struct it *, int, Lisp_Object);
+static void produce_glyphless_glyph (struct it *, Lisp_Object);
/* Append glyphs to IT's glyph_row. Called from produce_glyphs for
terminal frames if IT->glyph_row != NULL. IT->char_to_display is
if (it->what == IT_GLYPHLESS)
{
- produce_glyphless_glyph (it, 0, Qnil);
+ produce_glyphless_glyph (it, Qnil);
goto done;
}
Lisp_Object acronym = lookup_glyphless_char_display (-1, it);
eassert (it->what == IT_GLYPHLESS);
- produce_glyphless_glyph (it, 1, acronym);
+ produce_glyphless_glyph (it, acronym);
}
}
the character. See the description of enum
glyphless_display_method in dispextern.h for the details.
- FOR_NO_FONT is nonzero if and only if this is for a character that
- is not supported by the coding system of the terminal. ACRONYM, if
- non-nil, is an acronym string for the character.
+ ACRONYM, if non-nil, is an acronym string for the character.
The glyphs actually produced are of type CHAR_GLYPH. */
static void
-produce_glyphless_glyph (struct it *it, int for_no_font, Lisp_Object acronym)
+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
ts = tty->standout_mode ? tty->TS_set_background : tty->TS_set_foreground;
if (fg >= 0 && ts)
{
- p = tparam (ts, NULL, 0, (int) fg, 0, 0, 0);
+ p = tparam (ts, NULL, 0, fg, 0, 0, 0);
OUTPUT (tty, p);
xfree (p);
}
ts = tty->standout_mode ? tty->TS_set_foreground : tty->TS_set_background;
if (bg >= 0 && ts)
{
- p = tparam (ts, NULL, 0, (int) bg, 0, 0, 0);
+ p = tparam (ts, NULL, 0, bg, 0, 0, 0);
OUTPUT (tty, p);
xfree (p);
}
}
-/* Return non-zero if the terminal on frame F supports all of the
+/* Return true if the terminal on frame F supports all of the
capabilities in CAPS simultaneously, with foreground and background
colors FG and BG. */
-int
+bool
tty_capable_p (struct tty_display_info *tty, unsigned int caps,
unsigned long fg, unsigned long bg)
{
/* Save or restore the default color-related capabilities of this
terminal. */
static void
-tty_default_color_capabilities (struct tty_display_info *tty, int save)
+tty_default_color_capabilities (struct tty_display_info *tty, bool save)
{
if (save)
/* Return the tty display object specified by TERMINAL. */
static struct terminal *
-get_tty_terminal (Lisp_Object terminal, int throw)
+get_tty_terminal (Lisp_Object terminal, bool throw)
{
struct terminal *t = get_terminal (terminal, throw);
{
struct terminal *t;
- if (!name)
- emacs_abort ();
+ eassert (name);
for (t = terminal_list; t; t = t->next_terminal)
{
t->display_info.tty->output = 0;
if (FRAMEP (t->display_info.tty->top_frame))
- FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 0);
+ SET_FRAME_VISIBLE (XFRAME (t->display_info.tty->top_frame), 0);
}
t->display_info.tty->input = stdin;
#else /* !MSDOS */
fd = emacs_open (t->display_info.tty->name, O_RDWR | O_NOCTTY, 0);
+ t->display_info.tty->input = t->display_info.tty->output
+ = fd < 0 ? 0 : fdopen (fd, "w+");
- if (fd == -1)
- error ("Can not reopen tty device %s: %s", t->display_info.tty->name, strerror (errno));
+ if (! t->display_info.tty->input)
+ {
+ int open_errno = errno;
+ emacs_close (fd);
+ report_file_errno ("Cannot reopen tty device",
+ build_string (t->display_info.tty->name),
+ open_errno);
+ }
- if (strcmp (t->display_info.tty->name, DEV_TTY))
+ if (!O_IGNORE_CTTY && strcmp (t->display_info.tty->name, DEV_TTY) != 0)
dissociate_if_controlling_tty (fd);
-
- t->display_info.tty->output = fdopen (fd, "w+");
- t->display_info.tty->input = t->display_info.tty->output;
#endif
add_keyboard_wait_descriptor (fd);
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);
- FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1);
+ SET_FRAME_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1);
}
set_tty_hooks (t);
const char *name;
int fd;
name = (const char *) ttyname (0);
- fd = open (name, O_WRONLY);
+ fd = emacs_open (name, O_WRONLY, 0);
SOME_FUNCTION (x, y, fd);
- close (fd);
+ emacs_close (fd);
last_mouse_x = x;
last_mouse_y = y; */
}
cursor_to (f, save_y, save_x);
}
-static int
-term_mouse_movement (FRAME_PTR frame, Gpm_Event *event)
+static bool
+term_mouse_movement (struct frame *frame, Gpm_Event *event)
{
/* Has the mouse moved off the glyph it was on at the last sighting? */
if (event->x != last_mouse_x || event->y != last_mouse_y)
This clears mouse_moved until the next motion
event arrives. */
static void
-term_mouse_position (FRAME_PTR *fp, int insist, Lisp_Object *bar_window,
+term_mouse_position (struct frame **fp, int insist, Lisp_Object *bar_window,
enum scroll_bar_part *part, Lisp_Object *x,
Lisp_Object *y, Time *timeptr)
{
{
struct frame *f = XFRAME (tty->top_frame);
struct input_event ie;
- int do_help = 0;
+ bool do_help = 0;
int count = 0;
EVENT_INIT (ie);
{
struct tty_output *t = xzalloc (sizeof *t);
- if (! FRAME_TERMCAP_P (f))
- emacs_abort ();
+ eassert (FRAME_TERMCAP_P (f));
t->display_info = FRAME_TERMINAL (f)->display_info.tty;
static void
tty_free_frame_resources (struct frame *f)
{
- if (! FRAME_TERMCAP_P (f))
- emacs_abort ();
+ eassert (FRAME_TERMCAP_P (f));
if (FRAME_FACE_CACHE (f))
free_frame_faces (f);
static void
tty_free_frame_resources (struct frame *f)
{
- if (! FRAME_TERMCAP_P (f) && ! FRAME_MSDOS_P (f))
- emacs_abort ();
+ eassert (FRAME_TERMCAP_P (f) || FRAME_MSDOS_P (f));
if (FRAME_FACE_CACHE (f))
free_frame_faces (f);
terminal->delete_terminal_hook = &delete_tty;
}
-/* Drop the controlling terminal if fd is the same device. */
+/* If FD is the controlling terminal, drop it. */
static void
dissociate_if_controlling_tty (int fd)
{
-#ifndef DOS_NT
- pid_t pgid = tcgetpgrp (fd); /* If tcgetpgrp succeeds, fd is the ctty. */
- if (pgid != -1)
- {
-#if defined (USG5)
- setpgrp ();
- no_controlling_tty = 1;
-#elif defined (CYGWIN)
- setsid ();
- no_controlling_tty = 1;
-#else
-#ifdef TIOCNOTTY /* Try BSD ioctls. */
- sigset_t blocked;
- sigemptyset (&blocked);
- sigaddset (&blocked, SIGTTOU);
- pthread_sigmask (SIG_BLOCK, &blocked, 0);
- fd = emacs_open (DEV_TTY, O_RDWR, 0);
- if (fd != -1 && ioctl (fd, TIOCNOTTY, 0) != -1)
- {
- no_controlling_tty = 1;
- }
- if (fd != -1)
- emacs_close (fd);
- pthread_sigmask (SIG_UNBLOCK, &blocked, 0);
-#else
-# error "Unknown system."
-#endif /* ! TIOCNOTTY */
-#endif /* ! USG */
+ /* If tcgetpgrp succeeds, fd is the controlling terminal,
+ so dissociate it by invoking setsid. */
+ if (tcgetpgrp (fd) >= 0 && setsid () < 0)
+ {
+#ifdef TIOCNOTTY
+ /* 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 ();
+ ioctl (fd, TIOCNOTTY, 0);
+ unblock_tty_out_signal ();
+#endif
}
-#endif /* !DOS_NT */
}
/* Create a termcap display on the tty device with the given name and
TERMINAL_TYPE is the termcap type of the device, e.g. "vt100".
- If MUST_SUCCEED is true, then all errors are fatal. */
+ If MUST_SUCCEED is true, then all errors are fatal. */
struct terminal *
-init_tty (const char *name, const char *terminal_type, int must_succeed)
+init_tty (const char *name, const char *terminal_type, bool must_succeed)
{
- char *area = NULL;
+ char *area;
char **address = &area;
- int buffer_size = 4096;
int status;
struct tty_display_info *tty = NULL;
struct terminal *terminal = NULL;
- int ctty = 0; /* 1 if asked to open controlling tty. */
+ bool ctty = false; /* True if asked to open controlling tty. */
if (!terminal_type)
maybe_fatal (must_succeed, 0,
set_tty_hooks (terminal);
{
- int fd;
- FILE *file;
-
-#ifdef O_IGNORE_CTTY
- if (!ctty)
- /* Open the terminal device. Don't recognize it as our
- controlling terminal, and don't make it the controlling tty
- if we don't have one at the moment. */
- fd = emacs_open (name, O_RDWR | O_IGNORE_CTTY | O_NOCTTY, 0);
- else
-#endif /* O_IGNORE_CTTY */
- /* Alas, O_IGNORE_CTTY is a GNU extension that seems to be only
- defined on Hurd. On other systems, we need to explicitly
- dissociate ourselves from the controlling tty when we want to
- open a frame on the same terminal. */
- fd = emacs_open (name, O_RDWR | O_NOCTTY, 0);
+ /* Open the terminal device. */
- tty->name = xstrdup (name);
- terminal->name = xstrdup (name);
+ /* If !ctty, don't recognize it as our controlling terminal, and
+ don't make it the controlling tty if we don't have one now.
- if (fd < 0)
- maybe_fatal (must_succeed, terminal,
- "Could not open file: %s",
- "Could not open file: %s",
- name);
- if (!isatty (fd))
+ Alas, O_IGNORE_CTTY is a GNU extension that seems to be only
+ defined on Hurd. On other systems, we need to explicitly
+ dissociate ourselves from the controlling tty when we want to
+ 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+");
+
+ if (! tty->input)
{
- close (fd);
- maybe_fatal (must_succeed, terminal,
- "Not a tty device: %s",
- "Not a tty device: %s",
- name);
+ char const *diagnostic
+ = tty->input ? "Not a tty device: %s" : "Could not open file: %s";
+ emacs_close (fd);
+ maybe_fatal (must_succeed, terminal, diagnostic, diagnostic, name);
}
-#ifndef O_IGNORE_CTTY
- if (!ctty)
- dissociate_if_controlling_tty (fd);
-#endif
+ tty->name = xstrdup (name);
+ terminal->name = xstrdup (name);
- file = fdopen (fd, "w+");
- tty->input = file;
- tty->output = file;
+ if (!O_IGNORE_CTTY && !ctty)
+ dissociate_if_controlling_tty (fd);
}
tty->type = xstrdup (terminal_type);
Wcm_clear (tty);
- tty->termcap_term_buffer = xmalloc (buffer_size);
-
/* On some systems, tgetent tries to access the controlling
- terminal. */
- {
- sigset_t blocked;
- sigemptyset (&blocked);
- sigaddset (&blocked, SIGTTOU);
- pthread_sigmask (SIG_BLOCK, &blocked, 0);
- status = tgetent (tty->termcap_term_buffer, terminal_type);
- pthread_sigmask (SIG_UNBLOCK, &blocked, 0);
- }
+ terminal. */
+ block_tty_out_signal ();
+ status = tgetent (tty->termcap_term_buffer, terminal_type);
+ if (tty->termcap_term_buffer[TERMCAP_BUFFER_SIZE - 1])
+ emacs_abort ();
+ unblock_tty_out_signal ();
if (status < 0)
{
terminal_type);
}
-#ifndef TERMINFO
- if (strlen (tty->termcap_term_buffer) >= buffer_size)
- emacs_abort ();
- buffer_size = strlen (tty->termcap_term_buffer);
-#endif
- tty->termcap_strings_buffer = area = xmalloc (buffer_size);
+ area = tty->termcap_strings_buffer;
tty->TS_ins_line = tgetstr ("al", address);
tty->TS_ins_multi_lines = tgetstr ("AL", address);
tty->TS_bell = tgetstr ("bl", address);
Right (tty) = tgetstr ("nd", address);
Down (tty) = tgetstr ("do", address);
if (!Down (tty))
- Down (tty) = tgetstr ("nl", address); /* Obsolete name for "do" */
+ Down (tty) = tgetstr ("nl", address); /* Obsolete name for "do". */
if (tgetflag ("bs"))
- Left (tty) = "\b"; /* can't possibly be longer! */
- else /* (Actually, "bs" is obsolete...) */
+ Left (tty) = "\b"; /* Can't possibly be longer! */
+ else /* (Actually, "bs" is obsolete...) */
Left (tty) = tgetstr ("le", address);
if (!Left (tty))
- Left (tty) = tgetstr ("bc", address); /* Obsolete name for "le" */
+ Left (tty) = tgetstr ("bc", address); /* Obsolete name for "le". */
tty->TS_pad_char = tgetstr ("pc", address);
tty->TS_repeat = tgetstr ("rp", address);
tty->TS_end_standout_mode = tgetstr ("se", address);
#ifdef WINDOWSNT
{
struct frame *f = XFRAME (selected_frame);
+ int height, width;
- initialize_w32_display (terminal);
+ initialize_w32_display (terminal, &width, &height);
- FrameRows (tty) = FRAME_LINES (f);
- FrameCols (tty) = FRAME_COLS (f);
- tty->specified_window = FRAME_LINES (f);
+ FrameRows (tty) = height;
+ FrameCols (tty) = width;
+ tty->specified_window = height;
- FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
terminal->char_ins_del_ok = 1;
baud_rate = 19200;
don't think we're losing anything by turning it off. */
terminal->line_ins_del_ok = 0;
- tty->TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */
+ tty->TN_max_colors = 16; /* Must be non-zero for tty-display-color-p. */
#endif /* DOS_NT */
#ifdef HAVE_GPM
tty->Wcm->cm_tab = 0;
/* We can't support standout mode, because it uses magic cookies. */
tty->TS_standout_mode = 0;
- /* But that means we cannot rely on ^M to go to column zero! */
+ /* But that means we cannot rely on ^M to go to column zero! */
CR (tty) = 0;
- /* LF can't be trusted either -- can alter hpos */
- /* if move at column 0 thru a line with TS_standout_mode */
+ /* LF can't be trusted either -- can alter hpos. */
+ /* If move at column 0 thru a line with TS_standout_mode. */
Down (tty) = 0;
}
tty->specified_window = FrameRows (tty);
- if (Wcm_init (tty) == -1) /* can't do cursor motion */
+ if (Wcm_init (tty) == -1) /* Can't do cursor motion. */
{
maybe_fatal (must_succeed, terminal,
"Terminal type \"%s\" is not powerful enough to run Emacs",
= tty->TS_delete_mode && tty->TS_insert_mode
&& !strcmp (tty->TS_delete_mode, tty->TS_insert_mode);
- tty->se_is_so = (tty->TS_standout_mode
- && tty->TS_end_standout_mode
- && !strcmp (tty->TS_standout_mode, tty->TS_end_standout_mode));
-
UseTabs (tty) = tabs_safe_p (fileno (tty->input)) && TabWidth (tty) == 8;
terminal->scroll_region_ok
/* Auxiliary error-handling function for init_tty.
Delete TERMINAL, then call error or fatal with str1 or str2,
- respectively, according to whether MUST_SUCCEED is zero or not. */
+ respectively, according to whether MUST_SUCCEED is true. */
static void
-maybe_fatal (int must_succeed, struct terminal *terminal,
+maybe_fatal (bool must_succeed, struct terminal *terminal,
const char *str1, const char *str2, ...)
{
va_list ap;
vfatal (str2, ap);
else
verror (str1, ap);
-
- va_end (ap);
- emacs_abort ();
}
void
va_list ap;
va_start (ap, str);
vfatal (str, ap);
- va_end (ap);
}
\f
if (!terminal->name)
return;
- if (terminal->type != output_termcap)
- emacs_abort ();
+ eassert (terminal->type == output_termcap);
tty = terminal->display_info.tty;
xfree (tty->old_tty);
xfree (tty->Wcm);
- xfree (tty->termcap_strings_buffer);
- xfree (tty->termcap_term_buffer);
-
xfree (tty);
}