/* MS-DOS specific C utilities. -*- coding: raw-text -*-
- Copyright (C) 1993, 1994, 1995, 1996, 1997 Free Software Foundation, Inc.
+ Copyright (C) 1993, 94, 95, 96, 97, 1999 Free Software Foundation, Inc.
This file is part of GNU Emacs.
#include "lisp.h"
#include <stdio.h>
#include <stdlib.h>
+#include <time.h>
#include <sys/param.h>
#include <sys/time.h>
#include <dos.h>
#include <conio.h> /* for cputs */
#endif
-#include "dosfns.h"
#include "msdos.h"
#include "systime.h"
#include "termhooks.h"
+#include "termchar.h"
#include "dispextern.h"
+#include "dosfns.h"
#include "termopts.h"
+#include "charset.h"
+#include "coding.h"
+#include "disptab.h"
#include "frame.h"
#include "window.h"
#include "buffer.h"
return (regs.x.bx != 0);
}
+static int
+mouse_button_depressed (b, xp, yp)
+ int b, *xp, *yp;
+{
+ union REGS regs;
+
+ if (b >= mouse_button_count)
+ return 0;
+ regs.x.ax = 0x0003;
+ int86 (0x33, ®s, ®s);
+ if ((regs.x.bx & (1 << mouse_button_translate[b])) != 0)
+ {
+ *xp = regs.x.cx / 8;
+ *yp = regs.x.dx / 8;
+ return 1;
+ }
+ return 0;
+}
+
void
mouse_get_pos (f, insist, bar_window, part, x, y, time)
FRAME_PTR *f;
mouse_init ()
{
union REGS regs;
+ int b;
if (termscript)
fprintf (termscript, "<M_INIT>");
regs.x.ax = 0x0021;
int86 (0x33, ®s, ®s);
+ /* Reset the mouse last press/release info. It seems that Windows
+ doesn't do that automatically when function 21h is called, which
+ causes Emacs to ``remember'' the click that switched focus to the
+ window just before Emacs was started from that window. */
+ for (b = 0; b < mouse_button_count; b++)
+ {
+ int dummy_x, dummy_y;
+
+ (void) mouse_pressed (b, &dummy_x, &dummy_y);
+ (void) mouse_released (b, &dummy_x, &dummy_y);
+ }
+
regs.x.ax = 0x0007;
regs.x.cx = 0;
regs.x.dx = 8 * (ScreenCols () - 1);
static int startup_pos_Y;
static unsigned char startup_screen_attrib;
+static clock_t startup_time;
+
static int term_setup_done;
/* Similar to the_only_frame. */
/* Segment and offset of the virtual screen. If 0, DOS/V is NOT loaded. */
static unsigned short screen_virtual_segment = 0;
static unsigned short screen_virtual_offset = 0;
+/* A flag to control how to display unibyte 8-bit characters. */
+extern int unibyte_display_via_language_environment;
#if __DJGPP__ > 1
/* Update the screen from a part of relocated DOS/V screen buffer which
}
#endif
-static
+static void
dos_direct_output (y, x, buf, len)
int y;
int x;
}
}
+/* Given a face id FACE, extract the face parameters to be used for
+ display until the face changes. The face parameters (actually, its
+ color) are used to construct the video attribute byte for each
+ glyph during the construction of the buffer that is then blitted to
+ the video RAM. */
static void
IT_set_face (int face)
{
- struct face *fp;
- extern struct face *intern_face (/* FRAME_PTR, struct face * */);
+ struct face *fp = FACE_FROM_ID (selected_frame, face);
+ unsigned long fg, bg;
- if (face == 1 || (face == 0 && highlight))
- fp = FRAME_MODE_LINE_FACE (foo);
- else if (face <= 0 || face >= FRAME_N_COMPUTED_FACES (foo))
- fp = FRAME_DEFAULT_FACE (foo);
- else
- fp = intern_face (selected_frame, FRAME_COMPUTED_FACES (foo)[face]);
- if (termscript)
- fprintf (termscript, "<FACE %d: %d/%d>",
- face, FACE_FOREGROUND (fp), FACE_BACKGROUND (fp));
+ if (!fp)
+ {
+ fp = FACE_FROM_ID (selected_frame, DEFAULT_FACE_ID);
+ /* The default face for the frame should always be realized and
+ cached. */
+ if (!fp)
+ abort ();
+ }
screen_face = face;
- ScreenAttrib = (FACE_BACKGROUND (fp) << 4) | FACE_FOREGROUND (fp);
+ fg = fp->foreground;
+ bg = fp->background;
+
+ /* Don't use invalid colors. In particular, a color of -1 means use
+ the colors of the default face, except that if highlight is on,
+ invert the foreground and the background. Note that we assume
+ all 16 colors to be available for the background, since Emacs
+ switches on this mode (and loses the blinking attribute) at
+ startup. */
+ if (fg == (unsigned long)-1)
+ fg = highlight ? FRAME_BACKGROUND_PIXEL (selected_frame)
+ : FRAME_FOREGROUND_PIXEL (selected_frame);
+ if (bg == (unsigned long)-1)
+ bg = highlight ? FRAME_FOREGROUND_PIXEL (selected_frame)
+ : FRAME_BACKGROUND_PIXEL (selected_frame);
+ if (termscript)
+ fprintf (termscript, "<FACE %d%s: %d/%d>",
+ face, highlight ? "H" : "", fp->foreground, fp->background);
+ if (fg >= 0 && fg < 16)
+ {
+ ScreenAttrib &= 0xf0;
+ ScreenAttrib |= fg;
+ }
+ if (bg >= 0 && bg < 16)
+ {
+ ScreenAttrib &= 0x0f;
+ ScreenAttrib |= ((bg & 0x0f) << 4);
+ }
}
+Lisp_Object Vdos_unsupported_char_glyph;
+
static void
-IT_write_glyphs (GLYPH *str, int len)
+IT_write_glyphs (struct glyph *str, int str_len)
{
- int newface;
- int ch, l = len;
- unsigned char *buf, *bp;
+ unsigned char *screen_buf, *screen_bp, *screen_buf_end, *bp;
+ int unsupported_face = FAST_GLYPH_FACE (Vdos_unsupported_char_glyph);
+ unsigned unsupported_char= FAST_GLYPH_CHAR (Vdos_unsupported_char_glyph);
int offset = 2 * (new_pos_X + screen_size_X * new_pos_Y);
+ register int sl = str_len;
+ register int tlen = GLYPH_TABLE_LENGTH;
+ register Lisp_Object *tbase = GLYPH_TABLE_BASE;
+
+ struct coding_system *coding = (CODING_REQUIRE_ENCODING (&terminal_coding)
+ ? &terminal_coding
+ : &safe_terminal_coding);
+
+ /* Do we need to consider conversion of unibyte characters to
+ multibyte? */
+ int convert_unibyte_characters
+ = (NILP (current_buffer->enable_multibyte_characters)
+ && unibyte_display_via_language_environment);
- if (len == 0) return;
+ if (str_len == 0) return;
- buf = bp = alloca (len * 2);
+ screen_buf = screen_bp = alloca (str_len * 2);
+ screen_buf_end = screen_buf + str_len * 2;
+
+ /* Since faces get cached and uncached behind our back, we can't
+ rely on their indices in the cache being consistent across
+ invocations. So always reset the screen face to the default
+ face of the frame, before writing glyphs, and let the glyphs
+ set the right face if it's different from the default. */
+ IT_set_face (DEFAULT_FACE_ID);
- while (--l >= 0)
- {
- newface = FAST_GLYPH_FACE (*str);
- if (newface != screen_face)
- IT_set_face (newface);
- ch = FAST_GLYPH_CHAR (*str);
- *bp++ = (unsigned char)ch;
- *bp++ = ScreenAttrib;
-
- if (termscript)
- fputc (ch, termscript);
- str++;
+ /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
+ the tail. */
+ terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
+ while (sl)
+ {
+ int cf, chlen, enclen;
+ unsigned char workbuf[4], *buf;
+ unsigned ch;
+ register GLYPH g = GLYPH_FROM_CHAR_GLYPH (*str);
+
+ /* Find the actual glyph to display by traversing the entire
+ aliases chain for this glyph. */
+ GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
+
+ /* Glyphs with GLYPH_MASK_PADDING bit set are actually there
+ only for the redisplay code to know how many columns does
+ this character occupy on the screen. Skip padding glyphs. */
+ if (CHAR_GLYPH_PADDING_P (*str))
+ {
+ str++;
+ sl--;
+ }
+ else
+ {
+ /* Convert the character code to multibyte, if they
+ requested display via language environment. */
+ ch = FAST_GLYPH_CHAR (g);
+ /* We only want to convert unibyte characters to multibyte
+ in unibyte buffers! Otherwise, the 8-bit code might come
+ from the display table set up to display foreign characters. */
+ if (SINGLE_BYTE_CHAR_P (ch) && convert_unibyte_characters
+ && (ch >= 0240
+ || (ch >= 0200 && !NILP (Vnonascii_translation_table))))
+ ch = unibyte_char_to_multibyte (ch);
+
+ /* Invalid characters are displayed with a special glyph. */
+ if (! GLYPH_CHAR_VALID_P (ch))
+ {
+ g = !NILP (Vdos_unsupported_char_glyph)
+ ? Vdos_unsupported_char_glyph
+ : MAKE_GLYPH (selected_frame, '\177',
+ GLYPH_FACE (selected_frame, g));
+ ch = FAST_GLYPH_CHAR (g);
+ }
+ if (COMPOSITE_CHAR_P (ch))
+ {
+ /* If CH is a composite character, we can display
+ only the first component. */
+ g = cmpchar_table[COMPOSITE_CHAR_ID (ch)]->glyph[0],
+ ch = GLYPH_CHAR (selected_frame, g);
+ cf = FAST_GLYPH_FACE (g);
+ }
+
+ /* If the face of this glyph is different from the current
+ screen face, update the screen attribute byte. */
+ cf = FAST_GLYPH_FACE (g);
+ if (cf != screen_face)
+ IT_set_face (cf); /* handles invalid faces gracefully */
+
+ if (GLYPH_SIMPLE_P (tbase, tlen, g))
+ /* We generate the multi-byte form of CH in BUF. */
+ chlen = CHAR_STRING (ch, workbuf, buf);
+ else
+ {
+ /* We have a string in Vglyph_table. */
+ chlen = GLYPH_LENGTH (tbase, g);
+ buf = GLYPH_STRING (tbase, g);
+ }
+
+ /* If the character is not multibyte, don't bother converting it. */
+ if (chlen == 1)
+ {
+ *conversion_buffer = (unsigned char)ch;
+ chlen = 0;
+ enclen = 1;
+ }
+ else
+ {
+ encode_coding (coding, buf, conversion_buffer, chlen,
+ conversion_buffer_size);
+ chlen -= coding->consumed;
+ enclen = coding->produced;
+
+ /* Replace glyph codes that cannot be converted by
+ terminal_coding with Vdos_unsupported_char_glyph. */
+ if (*conversion_buffer == '?')
+ {
+ char *cbp = conversion_buffer;
+
+ while (cbp < conversion_buffer + enclen && *cbp == '?')
+ *cbp++ = unsupported_char;
+ if (unsupported_face != screen_face)
+ IT_set_face (unsupported_face);
+ }
+ }
+
+ if (enclen + chlen > screen_buf_end - screen_bp)
+ {
+ /* The allocated buffer for screen writes is too small.
+ Flush it and loop again without incrementing STR, so
+ that the next loop will begin with the same glyph. */
+ int nbytes = screen_bp - screen_buf;
+
+ mouse_off_maybe ();
+ dosmemput (screen_buf, nbytes, (int)ScreenPrimary + offset);
+ if (screen_virtual_segment)
+ dosv_refresh_virtual_screen (offset, nbytes / 2);
+ new_pos_X += nbytes / 2;
+ offset += nbytes;
+
+ /* Prepare to reuse the same buffer again. */
+ screen_bp = screen_buf;
+ }
+ else
+ {
+ /* There's enough place in the allocated buffer to add
+ the encoding of this glyph. */
+
+ /* First, copy the encoded bytes. */
+ for (bp = conversion_buffer; enclen--; bp++)
+ {
+ *screen_bp++ = (unsigned char)*bp;
+ *screen_bp++ = ScreenAttrib;
+ if (termscript)
+ fputc (*bp, termscript);
+ }
+
+ /* Now copy the bytes not consumed by the encoding. */
+ if (chlen > 0)
+ {
+ buf += coding->consumed;
+ while (chlen--)
+ {
+ if (termscript)
+ fputc (*buf, termscript);
+ *screen_bp++ = (unsigned char)*buf++;
+ *screen_bp++ = ScreenAttrib;
+ }
+ }
+
+ /* Update STR and its remaining length. */
+ str++;
+ sl--;
+ }
+ }
}
+ /* Dump whatever is left in the screen buffer. */
mouse_off_maybe ();
- dosmemput (buf, 2 * len, (int)ScreenPrimary + offset);
+ dosmemput (screen_buf, screen_bp - screen_buf, (int)ScreenPrimary + offset);
if (screen_virtual_segment)
- dosv_refresh_virtual_screen (offset, len);
- new_pos_X += len;
+ dosv_refresh_virtual_screen (offset, (screen_bp - screen_buf) / 2);
+ new_pos_X += (screen_bp - screen_buf) / 2;
+
+ /* We may have to output some codes to terminate the writing. */
+ if (CODING_REQUIRE_FLUSHING (coding))
+ {
+ coding->mode |= CODING_MODE_LAST_BLOCK;
+ encode_coding (coding, "", conversion_buffer, 0, conversion_buffer_size);
+ if (coding->produced > 0)
+ {
+ for (screen_bp = screen_buf, bp = conversion_buffer;
+ coding->produced--; bp++)
+ {
+ *screen_bp++ = (unsigned char)*bp;
+ *screen_bp++ = ScreenAttrib;
+ if (termscript)
+ fputc (*bp, termscript);
+ }
+ offset += screen_bp - screen_buf;
+ mouse_off_maybe ();
+ dosmemput (screen_buf, screen_bp - screen_buf,
+ (int)ScreenPrimary + offset);
+ if (screen_virtual_segment)
+ dosv_refresh_virtual_screen (offset, (screen_bp - screen_buf) / 2);
+ new_pos_X += (screen_bp - screen_buf) / 2;
+ }
+ }
}
static void
char *spaces, *sp;
int i, j;
int offset = 2 * (new_pos_X + screen_size_X * new_pos_Y);
+ extern int fatal_error_in_progress;
+
+ if (fatal_error_in_progress)
+ return;
IT_set_face (0);
if (termscript)
static int cursor_cleared;
-static
+static void
IT_display_cursor (int on)
{
if (on && cursor_cleared)
/* Only set the cursor to where it should be if the display is
already in sync with the window contents. */
int update_cursor_pos = MODIFF == unchanged_modified;
-
- /* If we are in the echo area, and the cursor is beyond the end of
- the text, put the cursor at the end of text. */
+ static int previous_pos_X = -1;
+
+ /* If the display is in sync, forget any previous knowledge about
+ cursor position. This is primarily for unexpected events like
+ C-g in the minibuffer. */
+ if (update_cursor_pos && previous_pos_X >= 0)
+ previous_pos_X = -1;
+ /* If we are in the echo area, put the cursor at the
+ end of the echo area message. */
if (!update_cursor_pos
&& XFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (f))->top) <= new_pos_Y)
{
- int tem_X = FRAME_DESIRED_GLYPHS (f)->used[new_pos_Y];
+ int tem_X = current_pos_X, dummy;
+
+ if (echo_area_glyphs)
+ {
+ tem_X = echo_area_glyphs_length;
+ /* Save current cursor position, to be restored after the
+ echo area message is erased. Only remember one level
+ of previous cursor position. */
+ if (previous_pos_X == -1)
+ ScreenGetCursor (&dummy, &previous_pos_X);
+ }
+ else if (previous_pos_X >= 0)
+ {
+ /* We wind up here after the echo area message is erased.
+ Restore the cursor position we remembered above. */
+ tem_X = previous_pos_X;
+ previous_pos_X = -1;
+ }
- if (current_pos_X > tem_X)
+ if (current_pos_X != tem_X)
{
new_pos_X = tem_X;
update_cursor_pos = 1;
}
static void
-IT_change_line_highlight (int new_highlight, int vpos, int first_unused_hpos)
+IT_change_line_highlight (int new_highlight, int y, int vpos, int first_unused_hpos)
{
highlight = new_highlight;
IT_set_face (0); /* To possibly clear the highlighting. */
{
}
+/* Copy LEN glyphs displayed on a single line whose vertical position
+ is YPOS, beginning at horizontal position XFROM to horizontal
+ position XTO, by moving blocks in the video memory. Used by
+ functions that insert and delete glyphs. */
+static void
+IT_copy_glyphs (int xfrom, int xto, size_t len, int ypos)
+{
+ /* The offsets of source and destination relative to the
+ conventional memorty selector. */
+ int from = 2 * (xfrom + screen_size_X * ypos) + ScreenPrimary;
+ int to = 2 * (xto + screen_size_X * ypos) + ScreenPrimary;
+
+ if (from == to || len <= 0)
+ return;
+
+ _farsetsel (_dos_ds);
+
+ /* The source and destination might overlap, so we need to move
+ glyphs non-destructively. */
+ if (from > to)
+ {
+ for ( ; len; from += 2, to += 2, len--)
+ _farnspokew (to, _farnspeekw (from));
+ }
+ else
+ {
+ from += (len - 1) * 2;
+ to += (len - 1) * 2;
+ for ( ; len; from -= 2, to -= 2, len--)
+ _farnspokew (to, _farnspeekw (from));
+ }
+ if (screen_virtual_segment)
+ dosv_refresh_virtual_screen (ypos * screen_size_X * 2, screen_size_X);
+}
+
+/* Insert and delete glyphs. */
+static void
+IT_insert_glyphs (start, len)
+ register struct glyph *start;
+ register int len;
+{
+ int shift_by_width = screen_size_X - (new_pos_X + len);
+
+ /* Shift right the glyphs from the nominal cursor position to the
+ end of this line. */
+ IT_copy_glyphs (new_pos_X, new_pos_X + len, shift_by_width, new_pos_Y);
+
+ /* Now write the glyphs to be inserted. */
+ IT_write_glyphs (start, len);
+}
+
+static void
+IT_delete_glyphs (n)
+ register int n;
+{
+ abort ();
+}
+
/* set-window-configuration on window.c needs this. */
void
x_set_menu_bar_lines (f, value, oldval)
es_value = regs.x.es;
__dpmi_int (0x10, ®s);
- if (regs.x.es != es_value && regs.x.es != (ScreenPrimary >> 4) & 0xffff)
+ if (regs.x.es != es_value)
{
- screen_old_address = ScreenPrimary;
+ /* screen_old_address is only set if ScreenPrimary does NOT
+ already point to the relocated buffer address returned by
+ the Int 10h/AX=FEh call above. DJGPP v2.02 and later sets
+ ScreenPrimary to that address at startup under DOS/V. */
+ if (regs.x.es != (ScreenPrimary >> 4) & 0xffff)
+ screen_old_address = ScreenPrimary;
screen_virtual_segment = regs.x.es;
screen_virtual_offset = regs.x.di;
ScreenPrimary = (screen_virtual_segment << 4) + screen_virtual_offset;
/* Leave the video system in the same state as we found it,
as far as the blink/bright-background bit is concerned. */
maybe_enable_blinking ();
-
+
/* We have a situation here.
We cannot just do ScreenUpdate(startup_screen_buffer) because
the luser could have changed screen dimensions inside Emacs
is also restored within the visible dimensions. */
ScreenAttrib = startup_screen_attrib;
- ScreenClear ();
- if (screen_virtual_segment)
- dosv_refresh_virtual_screen (0, screen_size);
- if (update_row_len > saved_row_len)
- update_row_len = saved_row_len;
- if (current_rows > startup_screen_size_Y)
- current_rows = startup_screen_size_Y;
-
- if (termscript)
- fprintf (termscript, "<SCREEN RESTORED (dimensions=%dx%d)>\n",
- update_row_len / 2, current_rows);
-
- while (current_rows--)
+ /* Don't restore the screen if we are exiting less than 2 seconds
+ after startup: we might be crashing, and the screen might show
+ some vital clues to what's wrong. */
+ if (clock () - startup_time >= 2*CLOCKS_PER_SEC)
{
- dosmemput (saved_row, update_row_len, display_row_start);
+ ScreenClear ();
if (screen_virtual_segment)
- dosv_refresh_virtual_screen (display_row_start - ScreenPrimary,
- update_row_len / 2);
- saved_row += saved_row_len;
- display_row_start += to_next_row;
+ dosv_refresh_virtual_screen (0, screen_size);
+
+ if (update_row_len > saved_row_len)
+ update_row_len = saved_row_len;
+ if (current_rows > startup_screen_size_Y)
+ current_rows = startup_screen_size_Y;
+
+ if (termscript)
+ fprintf (termscript, "<SCREEN RESTORED (dimensions=%dx%d)>\n",
+ update_row_len / 2, current_rows);
+
+ while (current_rows--)
+ {
+ dosmemput (saved_row, update_row_len, display_row_start);
+ if (screen_virtual_segment)
+ dosv_refresh_virtual_screen (display_row_start - ScreenPrimary,
+ update_row_len / 2);
+ saved_row += saved_row_len;
+ display_row_start += to_next_row;
+ }
}
if (startup_pos_X < cursor_pos_X)
cursor_pos_X = startup_pos_X;
void
IT_set_frame_parameters (f, alist)
- FRAME_PTR f;
+ struct frame *f;
Lisp_Object alist;
{
Lisp_Object tail;
Lisp_Object *values
= (Lisp_Object *) alloca (length * sizeof (Lisp_Object));
int redraw;
- extern unsigned long load_color ();
+ struct face *dflt = NULL;
+
+ if (FRAME_FACE_CACHE (f))
+ dflt = FACE_FROM_ID (f, DEFAULT_FACE_ID);
redraw = 0;
if (EQ (prop, Qforeground_color))
{
- unsigned long new_color = load_color (f, val);
+ unsigned long new_color = load_color (f, NULL, val,
+ LFACE_FOREGROUND_INDEX);
if (new_color != ~0)
{
+ if (!dflt)
+ abort ();
FRAME_FOREGROUND_PIXEL (f) = new_color;
+ dflt->foreground = new_color;
redraw = 1;
if (termscript)
fprintf (termscript, "<FGCOLOR %lu>\n", new_color);
}
else if (EQ (prop, Qbackground_color))
{
- unsigned long new_color = load_color (f, val);
+ unsigned long new_color = load_color (f, NULL, val,
+ LFACE_BACKGROUND_INDEX);
if (new_color != ~0)
{
+ if (!dflt)
+ abort ();
FRAME_BACKGROUND_PIXEL (f) = new_color;
+ dflt->background = new_color;
redraw = 1;
if (termscript)
fprintf (termscript, "<BGCOLOR %lu>\n", new_color);
{
unsigned long fg = FRAME_FOREGROUND_PIXEL (f);
- FRAME_FOREGROUND_PIXEL (f) = FRAME_BACKGROUND_PIXEL (f);
+ if (!dflt)
+ abort ();
+ FRAME_FOREGROUND_PIXEL (f) = FRAME_BACKGROUND_PIXEL (f); /* FIXME! */
FRAME_BACKGROUND_PIXEL (f) = fg;
+ dflt->foreground = FRAME_FOREGROUND_PIXEL (f);
+ dflt->foreground = fg;
if (termscript)
fprintf (termscript, "<INVERSE-VIDEO>\n");
}
if (redraw)
{
- extern void recompute_basic_faces (FRAME_PTR);
- extern void redraw_frame (FRAME_PTR);
-
recompute_basic_faces (f);
if (f == selected_frame)
redraw_frame (f);
init_frame_faces (selected_frame);
ring_bell_hook = IT_ring_bell;
+ insert_glyphs_hook = IT_insert_glyphs;
+ delete_glyphs_hook = IT_delete_glyphs;
write_glyphs_hook = IT_write_glyphs;
cursor_to_hook = raw_cursor_to_hook = IT_cursor_to;
clear_to_end_hook = IT_clear_to_end;
set_terminal_modes_hook = IT_set_terminal_modes;
reset_terminal_modes_hook = IT_reset_terminal_modes;
set_terminal_window_hook = IT_set_terminal_window;
+ char_ins_del_ok = 0;
#endif
}
* SPACE
*/
+#define Ignore 0x0000
+#define Normal 0x0000 /* normal key - alt changes scan-code */
+#define FctKey 0x1000 /* func key if c == 0, else c */
+#define Special 0x2000 /* func key even if c != 0 */
+#define ModFct 0x3000 /* special if mod-keys, else 'c' */
+#define Map 0x4000 /* alt scan-code, map to unshift/shift key */
+#define KeyPad 0x5000 /* map to insert/kp-0 depending on c == 0xe0 */
+#define Grey 0x6000 /* Grey keypad key */
+
+#define Alt 0x0100 /* alt scan-code */
+#define Ctrl 0x0200 /* ctrl scan-code */
+#define Shift 0x0400 /* shift scan-code */
+
static int extended_kbd; /* 101 (102) keyboard present. */
+struct kbd_translate {
+ unsigned char sc;
+ unsigned char ch;
+ unsigned short code;
+};
+
struct dos_keyboard_map
{
char *unshifted;
char *shifted;
char *alt_gr;
+ struct kbd_translate *translate_table;
};
"`1234567890-= qwertyuiop[] asdfghjkl;'\\ zxcvbnm,./ ",
/* 0123456789012345678901234567890123456789 012345678901234 */
"~!@#$%^&*()_+ QWERTYUIOP{} ASDFGHJKL:\"| ZXCVBNM<>? ",
- 0 /* no Alt-Gr key */
+ 0, /* no Alt-Gr key */
+ 0 /* no translate table */
};
static struct dos_keyboard_map fr_keyboard = {
/* 0123456789012345678901234567890123456789012345678901234 */
" 1234567890ø+ AZERTYUIOPù\9c QSDFGHJKLM%æ WXCVBN?./õ ",
/* 01234567 89012345678901234567890123456789012345678901234 */
- " ~#{[|`\\^@]} Ï "
+ " ~#{[|`\\^@]} Ï ",
+ 0 /* no translate table */
};
/*
* added also {,},` as, respectively, AltGr-8, AltGr-9, AltGr-'
* Donated by Stefano Brozzi <brozzis@mag00.cedi.unipr.it>
*/
+
+static struct kbd_translate it_kbd_translate_table[] = {
+ { 0x56, 0x3c, Normal | 13 },
+ { 0x56, 0x3e, Normal | 27 },
+ { 0, 0, 0 }
+};
static struct dos_keyboard_map it_keyboard = {
/* 0 1 2 3 4 5 */
/* 0 123456789012345678901234567890123456789012345678901234 */
- "\\1234567890'\8d qwertyuiop\8a+ asdfghjkl\95\85\97 zxcvbnm,.- ",
+ "\\1234567890'\8d< qwertyuiop\8a+> asdfghjkl\95\85\97 zxcvbnm,.- ",
/* 01 23456789012345678901234567890123456789012345678901234 */
- "|!\"\9c$%&/()=?^ QWERTYUIOP\82* ASDFGHJKL\87øõ ZXCVBNM;:_ ",
+ "|!\"\9c$%&/()=?^> QWERTYUIOP\82* ASDFGHJKL\87øõ ZXCVBNM;:_ ",
/* 0123456789012345678901234567890123456789012345678901234 */
- " {}~` [] @# "
+ " {}~` [] @# ",
+ it_kbd_translate_table
};
static struct dos_keyboard_map dk_keyboard = {
/* 01 23456789012345678901234567890123456789012345678901234 */
"õ!\"#$%&/()=?` QWERTYUIOP\8f^ ASDFGHJKL\92\9d* ZXCVBNM;:_ ",
/* 0123456789012345678901234567890123456789012345678901234 */
- " @\9c$ {[]} | "
+ " @\9c$ {[]} | ",
+ 0 /* no translate table */
+};
+
+static struct kbd_translate jp_kbd_translate_table[] = {
+ { 0x73, 0x5c, Normal | 0 },
+ { 0x73, 0x5f, Normal | 0 },
+ { 0x73, 0x1c, Map | 0 },
+ { 0x7d, 0x5c, Normal | 13 },
+ { 0x7d, 0x7c, Normal | 13 },
+ { 0x7d, 0x1c, Map | 13 },
+ { 0, 0, 0 }
+};
+static struct dos_keyboard_map jp_keyboard = {
+/* 0 1 2 3 4 5 */
+/* 0123456789012 345678901234567890123456789012345678901234 */
+ "\\1234567890-^\\ qwertyuiop@[ asdfghjkl;:] zxcvbnm,./ ",
+/* 01 23456789012345678901234567890123456789012345678901234 */
+ "_!\"#$%&'()~=~| QWERTYUIOP`{ ASDFGHJKL+*} ZXCVBNM<>? ",
+ 0, /* no Alt-Gr key */
+ jp_kbd_translate_table
};
static struct keyboard_layout_list
1, &us_keyboard,
33, &fr_keyboard,
39, &it_keyboard,
- 45, &dk_keyboard
+ 45, &dk_keyboard,
+ 81, &jp_keyboard
};
static struct dos_keyboard_map *keyboard;
Note: calling Int 2Fh via int86 wedges the DOS box on some versions
of Windows 9X! So don't do that! */
regs.x.ax = 0xad80;
+ regs.x.ss = regs.x.sp = regs.x.flags = 0;
_go32_dpmi_simulate_int (0x2f, ®s);
if (regs.h.al == 0xff)
international_keyboard = 1;
return 0;
}
\f
-#define Ignore 0x0000
-#define Normal 0x0000 /* normal key - alt changes scan-code */
-#define FctKey 0x1000 /* func key if c == 0, else c */
-#define Special 0x2000 /* func key even if c != 0 */
-#define ModFct 0x3000 /* special if mod-keys, else 'c' */
-#define Map 0x4000 /* alt scan-code, map to unshift/shift key */
-#define KeyPad 0x5000 /* map to insert/kp-0 depending on c == 0xe0 */
-#define Grey 0x6000 /* Grey keypad key */
-
-#define Alt 0x0100 /* alt scan-code */
-#define Ctrl 0x0200 /* ctrl scan-code */
-#define Shift 0x0400 /* shift scan-code */
-
static struct
{
unsigned char char_code; /* normal code */
Ignore, /* Right shift */
Grey | 1, /* Grey * */
Ignore, /* Alt */
- Normal | ' ', /* ' ' */
+ Normal | 55, /* ' ' */
Ignore, /* Caps Lock */
FctKey | 0xbe, /* F1 */
FctKey | 0xbf, /* F2 */
/* Get a char from keyboard. Function keys are put into the event queue. */
extern void kbd_buffer_store_event (struct input_event *);
+static int mouse_preempted = 0; /* non-zero when XMenu gobbles mouse events */
static int
dos_rawgetc ()
{
union REGS regs;
register unsigned char c;
- int sc, code, mask, kp_mode;
+ int sc, code = -1, mask, kp_mode;
int modifiers;
regs.h.ah = extended_kbd ? 0x10 : 0x00;
}
else
{
- if (sc >= (sizeof (ibmpc_translate_map) / sizeof (short)))
- continue;
- if ((code = ibmpc_translate_map[sc]) == Ignore)
- continue;
+ /* Try the keyboard-private translation table first. */
+ if (keyboard->translate_table)
+ {
+ struct kbd_translate *p = keyboard->translate_table;
+
+ while (p->sc)
+ {
+ if (p->sc == sc && p->ch == c)
+ {
+ code = p->code;
+ break;
+ }
+ p++;
+ }
+ }
+ /* If the private table didn't translate it, use the general
+ one. */
+ if (code == -1)
+ {
+ if (sc >= (sizeof (ibmpc_translate_map) / sizeof (short)))
+ continue;
+ if ((code = ibmpc_translate_map[sc]) == Ignore)
+ continue;
+ }
}
if (c == 0)
kbd_buffer_store_event (&event);
}
- if (have_mouse > 0)
+ if (have_mouse > 0 && !mouse_preempted)
{
int but, press, x, y, ok;
IT_menu_display (XMenu *menu, int y, int x, int *faces)
{
int i, j, face, width;
- GLYPH *text, *p;
+ struct glyph *text, *p;
char *q;
int mx, my;
int enabled, mousehere;
int row, col;
width = menu->width;
- text = (GLYPH *) xmalloc ((width + 2) * sizeof (GLYPH));
+ text = (struct glyph *) xmalloc ((width + 2) * sizeof (struct glyph));
ScreenGetCursor (&row, &col);
mouse_get_xy (&mx, &my);
IT_update_begin (selected_frame);
mousehere = (y + i == my && x <= mx && mx < x + width + 2);
face = faces[enabled + mousehere * 2];
p = text;
- *p++ = FAST_MAKE_GLYPH (' ', face);
+ SET_CHAR_GLYPH (*p, ' ', face, 0);
+ p++;
for (j = 0, q = menu->text[i]; *q; j++)
{
if (*q > 26)
- *p++ = FAST_MAKE_GLYPH (*q++, face);
+ {
+ SET_CHAR_GLYPH (*p, *q++, face, 0);
+ p++;
+ }
else /* make '^x' */
{
- *p++ = FAST_MAKE_GLYPH ('^', face);
+ SET_CHAR_GLYPH (*p, '^', face, 0);
+ p++;
j++;
- *p++ = FAST_MAKE_GLYPH (*q++ + 64, face);
+ SET_CHAR_GLYPH (*p, *q++ + 64, face, 0);
+ p++;
}
}
- for (; j < width; j++)
- *p++ = FAST_MAKE_GLYPH (' ', face);
- *p++ = FAST_MAKE_GLYPH (menu->submenu[i] ? 16 : ' ', face);
+ for (; j < width; j++, p++)
+ SET_CHAR_GLYPH (*p, ' ', face, 0);
+
+ SET_CHAR_GLYPH (*p, menu->submenu[i] ? 16 : ' ', face, 0);
+ p++;
IT_write_glyphs (text, width + 2);
}
IT_update_end (selected_frame);
int statecount;
int x, y, i, b;
int screensize;
- int faces[4], selectface;
+ int faces[4];
+ Lisp_Object selectface;
int leave, result, onepane;
int title_faces[4]; /* face to display the menu title */
int buffers_num_deleted = 0;
if (y0 <= 0)
y0 = 1;
+ /* We will process all the mouse events directly, so we had
+ better prevented dos_rawgetc from stealing them from us. */
+ mouse_preempted++;
+
state = alloca (menu->panecount * sizeof (struct IT_menu_state));
screensize = screen_size * 2;
faces[0]
- = compute_glyph_face (selected_frame,
- face_name_id_number
- (selected_frame,
- intern ("msdos-menu-passive-face")),
- 0);
+ = lookup_derived_face (selected_frame, intern ("msdos-menu-passive-face"),
+ CHARSET_ASCII, DEFAULT_FACE_ID);
faces[1]
- = compute_glyph_face (selected_frame,
- face_name_id_number
- (selected_frame,
- intern ("msdos-menu-active-face")),
- 0);
- selectface
- = face_name_id_number (selected_frame, intern ("msdos-menu-select-face"));
- faces[2] = compute_glyph_face (selected_frame, selectface, faces[0]);
- faces[3] = compute_glyph_face (selected_frame, selectface, faces[1]);
+ = lookup_derived_face (selected_frame, intern ("msdos-menu-active-face"),
+ CHARSET_ASCII, DEFAULT_FACE_ID);
+ selectface = intern ("msdos-menu-select-face");
+ faces[2] = lookup_derived_face (selected_frame, selectface,
+ CHARSET_ASCII, faces[0]);
+ faces[3] = lookup_derived_face (selected_frame, selectface,
+ CHARSET_ASCII, faces[1]);
/* Make sure the menu title is always displayed with
`msdos-menu-active-face', no matter where the mouse pointer is. */
state[statecount - 1].x,
faces);
}
- for (b = 0; b < mouse_button_count; b++)
+ else
+ /* We are busy-waiting for the mouse to move, so let's be nice
+ to other Windows applications by releasing our time slice. */
+ __dpmi_yield ();
+ for (b = 0; b < mouse_button_count && !leave; b++)
{
- (void) mouse_pressed (b, &x, &y);
- if (mouse_released (b, &x, &y))
- leave = 1;
+ /* 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))
+ __dpmi_yield ();
+ leave = 1;
+ }
+ (void) mouse_released (b, &x, &y);
}
}
while (statecount--)
xfree (state[statecount].screen_behind);
IT_display_cursor (1); /* turn cursor back on */
+ /* Clean up any mouse events that are waiting inside Emacs event queue.
+ These events are likely to be generated before the menu was even
+ displayed, probably because the user pressed and released the button
+ (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 ();
+ /* Allow mouse events generation by dos_rawgetc. */
+ mouse_preempted--;
return result;
}
*p = '\0';
errno = 0;
_fixpath (in_path, dst);
- if (errno)
+ /* _fixpath can set errno to ENOSYS on non-LFN systems because
+ it queries the LFN support, so ignore that error. */
+ if ((errno && errno != ENOSYS) || *dst == '\0')
return 0;
msdos_downcase_filename (dst);
Qnil)),
"While setting TMPDIR: ");
+ /* Note the startup time, so we know not to clear the screen if we
+ exit immediately; see IT_reset_terminal_modes.
+ (Yes, I know `clock' returns zero the first time it's called, but
+ I do this anyway, in case some wiseguy changes that at some point.) */
+ startup_time = clock ();
+
/* Find our root from argv[0]. Assuming argv[0] is, say,
"c:/emacs/bin/emacs.exe" our root will be "c:/emacs". */
root = alloca (MAXPATHLEN + 20);
dup2 (inbak, 0);
dup2 (outbak, 1);
dup2 (errbak, 2);
- close (inbak);
- close (outbak);
- close (errbak);
+ emacs_close (inbak);
+ emacs_close (outbak);
+ emacs_close (errbak);
dos_ttraw ();
if (have_mouse > 0)
#if __DJGPP__ == 2 && __DJGPP_MINOR__ < 2
if (screen_virtual_segment)
dosv_refresh_virtual_screen (2 * 10 * screen_size_X, 4 * screen_size_X);
-#endif /* __DJGPP_MINOR__ < 2 */
/* Generate traceback, so we could tell whodunit. */
signal (SIGINT, SIG_DFL);
__asm__ __volatile__ ("movb $0x1b,%al;call ___djgpp_hw_exception");
+#else /* __DJGPP_MINOR__ >= 2 */
+ raise (SIGABRT);
+#endif /* __DJGPP_MINOR__ >= 2 */
#endif
exit (2);
}
"List of directories to search for bitmap files for X.");
Vx_bitmap_file_path = decode_env_path ((char *) 0, ".");
- /* The following two are from xfns.c: */
+ /* The following three are from xfns.c: */
Qbackground_color = intern ("background-color");
staticpro (&Qbackground_color);
Qforeground_color = intern ("foreground-color");
staticpro (&Qforeground_color);
+
+ DEFVAR_LISP ("dos-unsupported-char-glyph", &Vdos_unsupported_char_glyph,
+ "*Glyph to display instead of chars not supported by current codepage.\n\
+
+This variable is used only by MSDOS terminals.");
+ Vdos_unsupported_char_glyph = '\177';
#endif
#ifndef subprocesses
DEFVAR_BOOL ("delete-exited-processes", &delete_exited_processes,