/* 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, 2008
+ 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009
Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include "syssignal.h"
#include "systty.h"
#include "intervals.h"
+#ifdef MSDOS
+#include "msdos.h"
+static int been_here = -1;
+#endif
/* For now, don't try to include termcap.h. On some systems,
configure finds a non-standard termcap.h that the main build
#ifdef HAVE_X_WINDOWS
#include "xterm.h"
#endif
-#ifdef MAC_OS
-#include "macterm.h"
-#endif
#ifndef O_RDWR
#define O_RDWR 2
required = MAX_MULTIBYTE_LENGTH * src_len;
if (encode_terminal_src_size < required)
{
- if (encode_terminal_src_size == 0)
- encode_terminal_src = xmalloc (required);
- else
+ if (encode_terminal_src)
encode_terminal_src = xrealloc (encode_terminal_src, required);
+ else
+ encode_terminal_src = xmalloc (required);
encode_terminal_src_size = required;
}
{
if (src->type == COMPOSITE_GLYPH)
{
- struct composition *cmp = composition_table[src->u.cmp_id];
+ struct composition *cmp;
+ Lisp_Object gstring;
int i;
nbytes = buf - encode_terminal_src;
- required = MAX_MULTIBYTE_LENGTH * cmp->glyph_len;
+ if (src->u.cmp.automatic)
+ {
+ gstring = composition_gstring_from_id (src->u.cmp.id);
+ required = src->u.cmp.to - src->u.cmp.from;
+ }
+ else
+ {
+ cmp = composition_table[src->u.cmp.id];
+ required = MAX_MULTIBYTE_LENGTH * cmp->glyph_len;
+ }
if (encode_terminal_src_size < nbytes + required)
{
buf = encode_terminal_src + nbytes;
}
- for (i = 0; i < cmp->glyph_len; i++)
- {
- int c = COMPOSITION_GLYPH (cmp, i);
+ if (src->u.cmp.automatic)
+ for (i = src->u.cmp.from; i < src->u.cmp.to; i++)
+ {
+ Lisp_Object g = LGSTRING_GLYPH (gstring, i);
+ int c = LGLYPH_CHAR (g);
- if (! char_charset (c, charset_list, NULL))
- break;
- buf += CHAR_STRING (c, buf);
- nchars++;
- }
- if (i == 0)
- {
- /* The first character of the composition is not encodable. */
- *buf++ = '?';
- nchars++;
- }
+ if (! char_charset (c, charset_list, NULL))
+ c = '?';
+ buf += CHAR_STRING (c, buf);
+ nchars++;
+ }
+ else
+ for (i = 0; i < cmp->glyph_len; i++)
+ {
+ int c = COMPOSITION_GLYPH (cmp, i);
+
+ if (c == '\t')
+ continue;
+ if (char_charset (c, charset_list, NULL))
+ {
+ if (CHAR_WIDTH (c) == 0
+ && i > 0 && COMPOSITION_GLYPH (cmp, i - 1) == '\t')
+ /* Should be left-padded */
+ {
+ buf += CHAR_STRING (' ', buf);
+ nchars++;
+ }
+ }
+ else
+ c = '?';
+ buf += CHAR_STRING (c, buf);
+ nchars++;
+ }
}
/* We must skip glyphs to be padded for a wide character. */
else if (! CHAR_GLYPH_PADDING_P (*src))
if (GLYPH_INVALID_P (g) || GLYPH_SIMPLE_P (tbase, tlen, g))
{
- /* This glyph doesn't has an entry in Vglyph_table. */
+ /* This glyph doesn't have an entry in Vglyph_table. */
c = src->u.ch;
}
else
if (encode_terminal_dst_size == 0)
{
encode_terminal_dst_size = encode_terminal_src_size;
- encode_terminal_dst = xmalloc (encode_terminal_dst_size);
+ if (encode_terminal_dst)
+ encode_terminal_dst = xrealloc (encode_terminal_dst,
+ encode_terminal_dst_size);
+ else
+ encode_terminal_dst = xmalloc (encode_terminal_dst_size);
}
coding->destination = encode_terminal_dst;
coding->dst_bytes = encode_terminal_dst_size;
{
glyph->type = COMPOSITE_GLYPH;
glyph->pixel_width = it->pixel_width;
- glyph->u.cmp_id = it->cmp_id;
+ glyph->u.cmp.id = it->cmp_it.id;
+ if (it->cmp_it.ch < 0)
+ {
+ glyph->u.cmp.automatic = 0;
+ glyph->u.cmp.id = it->cmp_it.id;
+ }
+ else
+ {
+ glyph->u.cmp.automatic = 1;
+ glyph->u.cmp.id = it->cmp_it.id;
+ glyph->u.cmp.from = it->cmp_it.from;
+ glyph->u.cmp.to = it->cmp_it.to;
+ }
+
glyph->face_id = it->face_id;
glyph->padding_p = 0;
glyph->charpos = CHARPOS (it->position);
produce_composite_glyph (it)
struct it *it;
{
- struct composition *cmp = composition_table[it->cmp_id];
int c;
- xassert (cmp->glyph_len > 0);
- c = COMPOSITION_GLYPH (cmp, 0);
- it->pixel_width = CHAR_WIDTH (it->c);
- it->nglyphs = 1;
+ if (it->cmp_it.ch < 0)
+ {
+ struct composition *cmp = composition_table[it->cmp_it.id];
+
+ it->pixel_width = cmp->width;
+ }
+ else
+ {
+ Lisp_Object gstring = composition_gstring_from_id (it->cmp_it.id);
+ it->pixel_width = composition_gstring_width (gstring, it->cmp_it.from,
+ it->cmp_it.to, NULL);
+ }
+ it->nglyphs = 1;
if (it->glyph_row)
append_composite_glyph (it);
}
return make_number (t->display_info.tty->TN_max_colors);
}
-#ifndef WINDOWSNT
+#ifndef DOS_NT
/* Declare here rather than in the function, as in the rest of Emacs,
to work around an HPUX compiler bug (?). See
}
}
-#endif /* !WINDOWSNT */
+#endif /* !DOS_NT */
\f
{
struct terminal *t = get_terminal (terminal, throw);
- if (t && t->type != output_termcap)
+ if (t && t->type != output_termcap && t->type != output_msdos_raw)
{
if (throw)
error ("Device %d is not a termcap terminal device", t->id);
for (t = terminal_list; t; t = t->next_terminal)
{
- if (t->type == output_termcap
+ if ((t->type == output_termcap || t->type == output_msdos_raw)
&& !strcmp (t->display_info.tty->name, name)
&& TERMINAL_ACTIVE_P (t))
return t;
{
struct terminal *t = get_terminal (terminal, 1);
- if (t->type != output_termcap)
+ if (t->type != output_termcap && t->type != output_msdos_raw)
return Qnil;
if (t->display_info.tty->type)
}
DEFUN ("controlling-tty-p", Fcontrolling_tty_p, Scontrolling_tty_p, 0, 1, 0,
- doc: /* Return non-nil if TERMINAL is on the controlling tty of the Emacs process.
+ doc: /* Return non-nil if TERMINAL is the controlling tty of the Emacs process.
TERMINAL can be a terminal id, a frame or nil (meaning the selected
frame's terminal). This function always returns nil if TERMINAL
{
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 && t->type != output_msdos_raw)
+ || strcmp (t->display_info.tty->name, DEV_TTY) != 0)
return Qnil;
else
return Qt;
reset_sys_modes (t->display_info.tty);
+#ifdef subprocesses
delete_keyboard_wait_descriptor (fileno (f));
+#endif
+#ifndef MSDOS
fclose (f);
if (f != t->display_info.tty->output)
fclose (t->display_info.tty->output);
+#endif
t->display_info.tty->input = 0;
t->display_info.tty->output = 0;
if (get_named_tty (t->display_info.tty->name))
error ("Cannot resume display while another display is active on the same device");
+#ifdef MSDOS
+ t->display_info.tty->output = stdout;
+ t->display_info.tty->input = stdin;
+#else /* !MSDOS */
fd = emacs_open (t->display_info.tty->name, O_RDWR | O_NOCTTY, 0);
if (fd == -1)
t->display_info.tty->output = fdopen (fd, "w+");
t->display_info.tty->input = t->display_info.tty->output;
+#endif
+#ifdef subprocesses
add_keyboard_wait_descriptor (fd);
+#endif
if (FRAMEP (t->display_info.tty->top_frame))
- FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1);
+ {
+ struct frame *f = XFRAME (t->display_info.tty->top_frame);
+ int width, height;
+ int old_height = FRAME_COLS (f);
+ int old_width = FRAME_LINES (f);
+
+ /* Check if terminal/window size has changed while the frame
+ 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);
+ FRAME_SET_VISIBLE (XFRAME (t->display_info.tty->top_frame), 1);
+ }
init_sys_modes (t->display_info.tty);
}
}
+void
+close_gpm ()
+{
+ if (gpm_fd >= 0)
+ delete_gpm_wait_descriptor (gpm_fd);
+ while (Gpm_Close()); /* close all the stack */
+ gpm_tty = NULL;
+}
+
DEFUN ("gpm-mouse-stop", Fgpm_mouse_stop, Sgpm_mouse_stop,
0, 0, 0,
doc: /* Close a connection to Gpm. */)
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;
+ close_gpm ();
return Qnil;
}
#endif /* HAVE_GPM */
f->output_data.tty = t;
}
-/* Delete the tty-dependent part of frame F. */
+/* Delete frame F's face cache, and its tty-dependent part. */
static void
-delete_tty_output (struct frame *f)
+tty_free_frame_resources (struct frame *f)
{
if (! FRAME_TERMCAP_P (f))
abort ();
+ if (FRAME_FACE_CACHE (f))
+ free_frame_faces (f);
+
xfree (f->output_data.tty);
}
/* Leave these two set, or suspended frames are not deleted
correctly. */
- terminal->delete_frame_hook = &delete_tty_output;
+ terminal->delete_frame_hook = &tty_free_frame_resources;
terminal->delete_terminal_hook = &delete_tty;
}
terminal->read_socket_hook = &tty_read_avail_input; /* keyboard.c */
terminal->frame_up_to_date_hook = 0; /* Not needed. */
- terminal->delete_frame_hook = &delete_tty_output;
+ terminal->delete_frame_hook = &tty_free_frame_resources;
terminal->delete_terminal_hook = &delete_tty;
}
static void
dissociate_if_controlling_tty (int fd)
{
-#ifndef WINDOWSNT
+#ifndef DOS_NT
int pgid;
EMACS_GET_TTY_PGRP (fd, &pgid); /* If tcgetpgrp succeeds, fd is the ctty. */
if (pgid != -1)
#endif /* ! TIOCNOTTY */
#endif /* ! USG */
}
-#endif /* !WINDOWSNT */
+#endif /* !DOS_NT */
}
static void maybe_fatal();
{
char *area = NULL;
char **address = &area;
- char *buffer = NULL;
int buffer_size = 4096;
register char *p = NULL;
int status;
int ctty = 0; /* 1 if asked to open controlling tty. */
if (!terminal_type)
- maybe_fatal (must_succeed, 0, 0,
+ maybe_fatal (must_succeed, 0,
"Unknown terminal type",
"Unknown terminal type");
return terminal;
terminal = create_terminal ();
+#ifdef MSDOS
+ if (been_here > 0)
+ maybe_fatal (1, 0, "Attempt to create another terminal %s", "",
+ name, "");
+ been_here = 1;
+ tty = &the_only_display_info;
+#else
tty = (struct tty_display_info *) xmalloc (sizeof (struct tty_display_info));
+#endif
bzero (tty, sizeof (struct tty_display_info));
tty->next = tty_list;
tty_list = tty;
tty->Wcm = (struct cm *) xmalloc (sizeof (struct cm));
Wcm_clear (tty);
-#ifndef WINDOWSNT
+#ifndef DOS_NT
set_tty_hooks (terminal);
{
fd = emacs_open (name, O_RDWR | O_NOCTTY, 0);
#endif /* O_IGNORE_CTTY */
+ tty->name = xstrdup (name);
+ terminal->name = xstrdup (name);
+
if (fd < 0)
- maybe_fatal (must_succeed, buffer, terminal,
+ maybe_fatal (must_succeed, terminal,
"Could not open file: %s",
"Could not open file: %s",
name);
if (!isatty (fd))
{
close (fd);
- maybe_fatal (must_succeed, buffer, terminal,
+ maybe_fatal (must_succeed, terminal,
"Not a tty device: %s",
"Not a tty device: %s",
name);
#endif
file = fdopen (fd, "w+");
- tty->name = xstrdup (name);
- terminal->name = xstrdup (name);
tty->input = file;
tty->output = file;
}
tty->type = xstrdup (terminal_type);
+#ifdef subprocesses
add_keyboard_wait_descriptor (fileno (tty->input));
-
#endif
+#endif /* !DOS_NT */
+
encode_terminal_src_size = 0;
encode_terminal_dst_size = 0;
mouse_face_window = Qnil;
#endif
+#ifdef DOS_NT
#ifdef WINDOWSNT
initialize_w32_display (terminal);
+#else /* MSDOS */
+ if (strcmp (terminal_type, "internal") == 0)
+ terminal->type = output_msdos_raw;
+ initialize_msdos_display (terminal);
+#endif /* MSDOS */
+ tty->output = stdout;
+ tty->input = stdin;
/* The following two are inaccessible from w32console.c. */
- terminal->delete_frame_hook = &delete_tty_output;
+ terminal->delete_frame_hook = &tty_free_frame_resources;
terminal->delete_terminal_hook = &delete_tty;
tty->name = xstrdup (name);
terminal->name = xstrdup (name);
tty->type = xstrdup (terminal_type);
- tty->output = stdout;
- tty->input = stdin;
+#ifdef subprocesses
add_keyboard_wait_descriptor (0);
+#endif
Wcm_clear (tty);
+#ifdef WINDOWSNT
{
struct frame *f = XFRAME (selected_frame);
FRAME_CAN_HAVE_SCROLL_BARS (f) = 0;
FRAME_VERTICAL_SCROLL_BAR_TYPE (f) = vertical_scroll_bar_none;
}
+#else /* MSDOS */
+ {
+ int height, width;
+ get_tty_size (fileno (tty->input), &width, &height);
+ FrameCols (tty) = width;
+ FrameRows (tty) = height;
+ }
+#endif /* MSDOS */
tty->delete_in_insert_mode = 1;
UseTabs (tty) = 0;
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;
+#ifdef WINDOWSNT
terminal->char_ins_del_ok = 1;
-
baud_rate = 19200;
+#else /* MSDOS */
+ terminal->char_ins_del_ok = 0;
+ init_baud_rate (fileno (tty->input));
+#endif /* MSDOS */
tty->TN_max_colors = 16; /* Required to be non-zero for tty-display-color-p */
-#else /* not WINDOWSNT */
+#else /* not DOS_NT */
Wcm_clear (tty);
- buffer = (char *) xmalloc (buffer_size);
+ tty->termcap_term_buffer = (char *) xmalloc (buffer_size);
/* On some systems, tgetent tries to access the controlling
terminal. */
sigblock (sigmask (SIGTTOU));
- status = tgetent (buffer, terminal_type);
+ status = tgetent (tty->termcap_term_buffer, terminal_type);
sigunblock (sigmask (SIGTTOU));
if (status < 0)
{
#ifdef TERMINFO
- maybe_fatal (must_succeed, buffer, terminal,
+ maybe_fatal (must_succeed, terminal,
"Cannot open terminfo database file",
"Cannot open terminfo database file");
#else
- maybe_fatal (must_succeed, buffer, terminal,
+ maybe_fatal (must_succeed, terminal,
"Cannot open termcap database file",
"Cannot open termcap database file");
#endif
if (status == 0)
{
#ifdef TERMINFO
- maybe_fatal (must_succeed, buffer, terminal,
+ maybe_fatal (must_succeed, terminal,
"Terminal type %s is not defined",
"Terminal type %s is not defined.\n\
If that is not the actual type of terminal you have,\n\
to do `unset TERMINFO' (C-shell: `unsetenv TERMINFO') as well.",
terminal_type);
#else
- maybe_fatal (must_succeed, buffer, terminal,
+ maybe_fatal (must_succeed, terminal,
"Terminal type %s is not defined",
"Terminal type %s is not defined.\n\
If that is not the actual type of terminal you have,\n\
}
#ifndef TERMINFO
- if (strlen (buffer) >= buffer_size)
+ if (strlen (tty->termcap_term_buffer) >= buffer_size)
abort ();
- buffer_size = strlen (buffer);
+ buffer_size = strlen (tty->termcap_term_buffer);
#endif
- area = (char *) xmalloc (buffer_size);
-
+ tty->termcap_strings_buffer = area = (char *) xmalloc (buffer_size);
tty->TS_ins_line = tgetstr ("al", address);
tty->TS_ins_multi_lines = tgetstr ("AL", address);
tty->TS_bell = tgetstr ("bl", address);
Down (tty) = tgetstr ("do", address);
if (!Down (tty))
Down (tty) = tgetstr ("nl", address); /* Obsolete name for "do" */
-#ifdef VMS
- /* VMS puts a carriage return before each linefeed,
- so it is not safe to use linefeeds. */
- if (Down (tty) && Down (tty)[0] == '\n' && Down (tty)[1] == '\0')
- Down (tty) = 0;
-#endif /* VMS */
if (tgetflag ("bs"))
Left (tty) = "\b"; /* can't possibly be longer! */
else /* (Actually, "bs" is obsolete...) */
tty->TF_underscore = tgetflag ("ul");
tty->TF_teleray = tgetflag ("xt");
-#endif /* !WINDOWSNT */
-#ifdef MULTI_KBOARD
+#endif /* !DOS_NT */
terminal->kboard = (KBOARD *) xmalloc (sizeof (KBOARD));
init_kboard (terminal->kboard);
terminal->kboard->Vwindow_system = Qnil;
prompt in the mini-buffer. */
if (current_kboard == initial_kboard)
current_kboard = terminal->kboard;
-#ifndef WINDOWSNT
+#ifndef DOS_NT
term_get_fkeys (address, terminal->kboard);
-#endif
-#endif
-#ifndef WINDOWSNT
/* Get frame size from system, or else from termcap. */
{
int height, width;
FrameRows (tty) = tgetnum ("li");
if (FrameRows (tty) < 3 || FrameCols (tty) < 3)
- maybe_fatal (must_succeed, NULL, terminal,
+ maybe_fatal (must_succeed, terminal,
"Screen size %dx%d is too small"
"Screen size %dx%d is too small",
FrameCols (tty), FrameRows (tty));
TabWidth (tty) = tgetnum ("tw");
-#ifdef VMS
- /* These capabilities commonly use ^J.
- I don't know why, but sending them on VMS does not work;
- it causes following spaces to be lost, sometimes.
- For now, the simplest fix is to avoid using these capabilities ever. */
- if (Down (tty) && Down (tty)[0] == '\n')
- Down (tty) = 0;
-#endif /* VMS */
-
if (!tty->TS_bell)
tty->TS_bell = "\07";
if (Wcm_init (tty) == -1) /* can't do cursor motion */
{
- maybe_fatal (must_succeed, NULL, terminal,
+ maybe_fatal (must_succeed, terminal,
"Terminal type \"%s\" is not powerful enough to run Emacs",
-#ifdef VMS
- "Terminal type \"%s\" is not powerful enough to run Emacs.\n\
-It lacks the ability to position the cursor.\n\
-If that is not the actual type of terminal you have, use either the\n\
-DCL command `SET TERMINAL/DEVICE= ...' for DEC-compatible terminals,\n\
-or `define EMACS_TERM \"terminal type\"' for non-DEC terminals.",
-#else /* not VMS */
# ifdef TERMINFO
"Terminal type \"%s\" is not powerful enough to run Emacs.\n\
It lacks the ability to position the cursor.\n\
`setenv TERM ...') to specify the correct type. It may be necessary\n\
to do `unset TERMCAP' (C-shell: `unsetenv TERMCAP') as well.",
# endif /* TERMINFO */
-#endif /*VMS */
terminal_type);
}
if (FrameRows (tty) <= 0 || FrameCols (tty) <= 0)
- maybe_fatal (must_succeed, NULL, terminal,
+ maybe_fatal (must_succeed, terminal,
"Could not determine the frame size",
"Could not determine the frame size");
init_baud_rate (fileno (tty->input));
-#ifdef AIXHFT
- /* The HFT system on AIX doesn't optimize for scrolling, so it's
- really ugly at times. */
- terminal->line_ins_del_ok = 0;
- terminal->char_ins_del_ok = 0;
-#endif
-
- /* Don't do this. I think termcap may still need the buffer. */
- /* xfree (buffer); */
-
-#endif /* not WINDOWSNT */
+#endif /* not DOS_NT */
/* Init system terminal modes (RAW or CBREAK, etc.). */
init_sys_modes (tty);
}
/* Auxiliary error-handling function for init_tty.
- Free BUFFER and delete TERMINAL, then call error or fatal
- with str1 or str2, respectively, according to MUST_SUCCEED. */
+ Delete TERMINAL, then call error or fatal with str1 or str2,
+ respectively, according to MUST_SUCCEED. */
static void
-maybe_fatal (must_succeed, buffer, terminal, str1, str2, arg1, arg2)
+maybe_fatal (must_succeed, terminal, str1, str2, arg1, arg2)
int must_succeed;
- char *buffer;
struct terminal *terminal;
char *str1, *str2, *arg1, *arg2;
{
- xfree (buffer);
-
if (terminal)
delete_tty (terminal);
Lisp_Object tail, frame;
int last_terminal;
- /* Protect against recursive calls. Fdelete_frame in
+ /* Protect against recursive calls. delete_frame in
delete_terminal calls us back when it deletes our last frame. */
if (!terminal->name)
return;
if (tty->input)
{
+#ifdef subprocesses
delete_keyboard_wait_descriptor (fileno (tty->input));
+#endif
if (tty->input != stdin)
fclose (tty->input);
}
xfree (tty->old_tty);
xfree (tty->Wcm);
+ if (tty->termcap_strings_buffer)
+ xfree (tty->termcap_strings_buffer);
+ if (tty->termcap_term_buffer)
+ xfree (tty->termcap_term_buffer);
bzero (tty, sizeof (struct tty_display_info));
xfree (tty);
staticpro (&mouse_face_window);
#endif /* HAVE_GPM */
+
+#ifndef DOS_NT
+ default_orig_pair = NULL;
+ default_set_foreground = NULL;
+ default_set_background = NULL;
+#endif /* !DOS_NT */
+
+ encode_terminal_src = NULL;
+ encode_terminal_dst = NULL;
}