#include <config.h>
#ifdef MSDOS
#include "lisp.h"
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <sys/param.h>
#include <sys/time.h>
#include <dos.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#if __DJGPP__ >= 2
#include <fcntl.h>
#include <io.h>
#include <dpmi.h>
#include <sys/farptr.h>
#include <libc/dosio.h>
#include <conio.h>
#endif
#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"
#include "commands.h"
#include "blockinput.h"
#include "keyboard.h"
#include <go32.h>
#include <pc.h>
#include <ctype.h>
#define P_WAIT 1
#ifndef _USE_LFN
#define _USE_LFN 0
#endif
#ifndef _dos_ds
#define _dos_ds _go32_info_block.selector_for_linear_memory
#endif
#if __DJGPP__ > 1
#include <signal.h>
#include "syssignal.h"
#ifndef SYSTEM_MALLOC
#ifdef GNU_MALLOC
#include <crt0.h>
#ifdef REL_ALLOC
int _crt0_startup_flags = _CRT0_FLAG_UNIX_SBRK;
#else
int _crt0_startup_flags = (_CRT0_FLAG_UNIX_SBRK | _CRT0_FLAG_FILL_SBRK_MEMORY);
#endif
#endif
#endif
#endif
static unsigned long
event_timestamp ()
{
struct time t;
unsigned long s;
gettime (&t);
s = t.ti_min;
s *= 60;
s += t.ti_sec;
s *= 1000;
s += t.ti_hund * 10;
return s;
}
#define NUM_MOUSE_BUTTONS (5)
int have_mouse;
static int mouse_visible;
static int mouse_last_x;
static int mouse_last_y;
static int mouse_button_translate[NUM_MOUSE_BUTTONS];
static int mouse_button_count;
void
mouse_on ()
{
union REGS regs;
if (have_mouse > 0 && !mouse_visible)
{
if (termscript)
fprintf (termscript, "<M_ON>");
regs.x.ax = 0x0001;
int86 (0x33, ®s, ®s);
mouse_visible = 1;
}
}
void
mouse_off ()
{
union REGS regs;
if (have_mouse > 0 && mouse_visible)
{
if (termscript)
fprintf (termscript, "<M_OFF>");
regs.x.ax = 0x0002;
int86 (0x33, ®s, ®s);
mouse_visible = 0;
}
}
static void
mouse_setup_buttons (int n_buttons)
{
if (n_buttons == 3)
{
mouse_button_count = 3;
mouse_button_translate[0] = 0;
mouse_button_translate[1] = 2;
mouse_button_translate[2] = 1;
}
else
{
mouse_button_count = 2;
mouse_button_translate[0] = 0;
mouse_button_translate[1] = 1;
}
}
DEFUN ("msdos-set-mouse-buttons", Fmsdos_set_mouse_buttons, Smsdos_set_mouse_buttons,
1, 1, "NSet number of mouse buttons to: ",
"Set the number of mouse buttons to use by Emacs.\n\
This is useful with mice that report the number of buttons inconsistently,\n\
e.g., if the number of buttons is reported as 3, but Emacs only sees 2 of\n\
them. This happens with wheeled mice on Windows 9X, for example.")
(nbuttons)
Lisp_Object nbuttons;
{
int n;
CHECK_NUMBER (nbuttons, 0);
n = XINT (nbuttons);
if (n < 2 || n > 3)
Fsignal (Qargs_out_of_range,
Fcons (build_string ("only 2 or 3 mouse buttons are supported"),
Fcons (nbuttons, Qnil)));
mouse_setup_buttons (n);
return Qnil;
}
static void
mouse_get_xy (int *x, int *y)
{
union REGS regs;
regs.x.ax = 0x0003;
int86 (0x33, ®s, ®s);
*x = regs.x.cx / 8;
*y = regs.x.dx / 8;
}
void
mouse_moveto (x, y)
int x, y;
{
union REGS regs;
if (termscript)
fprintf (termscript, "<M_XY=%dx%d>", x, y);
regs.x.ax = 0x0004;
mouse_last_x = regs.x.cx = x * 8;
mouse_last_y = regs.x.dx = y * 8;
int86 (0x33, ®s, ®s);
}
static int
mouse_pressed (b, xp, yp)
int b, *xp, *yp;
{
union REGS regs;
if (b >= mouse_button_count)
return 0;
regs.x.ax = 0x0005;
regs.x.bx = mouse_button_translate[b];
int86 (0x33, ®s, ®s);
if (regs.x.bx)
*xp = regs.x.cx / 8, *yp = regs.x.dx / 8;
return (regs.x.bx != 0);
}
static int
mouse_released (b, xp, yp)
int b, *xp, *yp;
{
union REGS regs;
if (b >= mouse_button_count)
return 0;
regs.x.ax = 0x0006;
regs.x.bx = mouse_button_translate[b];
int86 (0x33, ®s, ®s);
if (regs.x.bx)
*xp = regs.x.cx / 8, *yp = regs.x.dx / 8;
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;
int insist;
Lisp_Object *bar_window, *x, *y;
enum scroll_bar_part *part;
unsigned long *time;
{
int ix, iy;
Lisp_Object frame, tail;
FOR_EACH_FRAME (tail, frame)
XFRAME (frame)->mouse_moved = 0;
*f = SELECTED_FRAME();
*bar_window = Qnil;
mouse_get_xy (&ix, &iy);
*time = event_timestamp ();
*x = make_number (mouse_last_x = ix);
*y = make_number (mouse_last_y = iy);
}
static void
mouse_check_moved ()
{
int x, y;
mouse_get_xy (&x, &y);
SELECTED_FRAME()->mouse_moved |= (x != mouse_last_x || y != mouse_last_y);
mouse_last_x = x;
mouse_last_y = y;
}
static void
mouse_clear_clicks (void)
{
int b;
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);
}
}
void
mouse_init ()
{
union REGS regs;
if (termscript)
fprintf (termscript, "<M_INIT>");
regs.x.ax = 0x0021;
int86 (0x33, ®s, ®s);
mouse_clear_clicks ();
regs.x.ax = 0x0007;
regs.x.cx = 0;
regs.x.dx = 8 * (ScreenCols () - 1);
int86 (0x33, ®s, ®s);
regs.x.ax = 0x0008;
regs.x.cx = 0;
regs.x.dx = 8 * (ScreenRows () - 1);
int86 (0x33, ®s, ®s);
mouse_moveto (0, 0);
mouse_visible = 0;
}
static int internal_terminal = 0;
#ifndef HAVE_X_WINDOWS
extern unsigned char ScreenAttrib;
static int screen_face;
static int highlight;
static int screen_size_X;
static int screen_size_Y;
static int screen_size;
static int current_pos_X;
static int current_pos_Y;
static int new_pos_X;
static int new_pos_Y;
static void *startup_screen_buffer;
static int startup_screen_size_X;
static int startup_screen_size_Y;
static int startup_pos_X;
static int startup_pos_Y;
static unsigned char startup_screen_attrib;
static clock_t startup_time;
static int term_setup_done;
static unsigned short outside_cursor;
struct x_output the_only_x_display;
static unsigned long screen_old_address = 0;
static unsigned short screen_virtual_segment = 0;
static unsigned short screen_virtual_offset = 0;
extern int unibyte_display_via_language_environment;
Lisp_Object Qbar;
static int initial_screen_colors[2];
#if __DJGPP__ > 1
static void
dosv_refresh_virtual_screen (int offset, int count)
{
__dpmi_regs regs;
if (offset < 0 || count < 0)
return;
regs.h.ah = 0xff;
regs.x.es = screen_virtual_segment;
regs.x.di = screen_virtual_offset + offset;
regs.x.cx = count;
__dpmi_int (0x10, ®s);
}
#endif
static void
dos_direct_output (y, x, buf, len)
int y;
int x;
char *buf;
int len;
{
int t0 = 2 * (x + y * screen_size_X);
int t = t0 + (int) ScreenPrimary;
int l0 = len;
#if (__DJGPP__ < 2)
while (--len >= 0) {
dosmemput (buf++, 1, t);
t += 2;
}
#else
for (_farsetsel (_dos_ds); --len >= 0; t += 2, buf++)
_farnspokeb (t, *buf);
if (screen_virtual_segment)
dosv_refresh_virtual_screen (t0, l0);
#endif
}
#endif
#if (__DJGPP__ < 2)
static void
do_visible_bell (xorattr)
unsigned char xorattr;
{
asm volatile
(" movb $1,%%dl \n\
visible_bell_0: \n\
movl _ScreenPrimary,%%eax \n\
call dosmemsetup \n\
movl %%eax,%%ebx \n\
movl %1,%%ecx \n\
movb %0,%%al \n\
incl %%ebx \n\
visible_bell_1: \n\
xorb %%al,%%gs:(%%ebx) \n\
addl $2,%%ebx \n\
decl %%ecx \n\
jne visible_bell_1 \n\
decb %%dl \n\
jne visible_bell_3 \n\
visible_bell_2: \n\
movzwl %%ax,%%eax \n\
movzwl %%ax,%%eax \n\
movzwl %%ax,%%eax \n\
movzwl %%ax,%%eax \n\
decw %%cx \n\
jne visible_bell_2 \n\
jmp visible_bell_0 \n\
visible_bell_3:"
:
: "m" (xorattr), "g" (screen_size)
: "%eax", "%ebx", "%ecx", "%edx");
}
static void
ScreenVisualBell (void)
{
do_visible_bell (((the_only_x_display.foreground_pixel
^ the_only_x_display.background_pixel)
* 0x11) & 0x7f);
}
#endif
#ifndef HAVE_X_WINDOWS
static int blink_bit = -1;
static void
bright_bg (void)
{
union REGS regs;
if (blink_bit == -1)
blink_bit = (_farpeekb (_dos_ds, 0x465) & 0x20) == 0x20;
regs.h.bl = 0;
regs.x.ax = 0x1003;
int86 (0x10, ®s, ®s);
}
static void
maybe_enable_blinking (void)
{
if (blink_bit == 1)
{
union REGS regs;
regs.h.bl = 1;
regs.x.ax = 0x1003;
int86 (0x10, ®s, ®s);
}
}
static int
vga_installed (void)
{
union REGS regs;
regs.x.ax = 0x1a00;
int86 (0x10, ®s, ®s);
if (regs.h.al == 0x1a && regs.h.bl > 5 && regs.h.bl < 13)
return 1;
return 0;
}
void
dos_set_window_size (rows, cols)
int *rows, *cols;
{
char video_name[30];
Lisp_Object video_mode;
int video_mode_value;
int have_vga = 0;
union REGS regs;
int current_rows = ScreenRows (), current_cols = ScreenCols ();
if (*rows == current_rows && *cols == current_cols)
return;
mouse_off ();
have_vga = vga_installed ();
sprintf (video_name, "screen-dimensions-%dx%d", *rows, *cols);
video_mode = XSYMBOL (Fintern_soft (build_string (video_name),
Qnil))-> value;
if (INTEGERP (video_mode)
&& (video_mode_value = XINT (video_mode)) > 0)
{
regs.x.ax = video_mode_value;
int86 (0x10, ®s, ®s);
if (have_mouse)
{
regs.x.ax = 0;
int86 (0x33, ®s, ®s);
}
}
#if __DJGPP__ > 1
else
{
static struct {
int rows;
int need_vga;
} std_dimension[] = {
{25, 0},
{28, 1},
{35, 0},
{40, 1},
{43, 0},
{50, 1}
};
int i = 0;
while (i < sizeof (std_dimension) / sizeof (std_dimension[0]))
{
if (std_dimension[i].need_vga <= have_vga
&& std_dimension[i].rows >= *rows)
{
if (std_dimension[i].rows != current_rows
|| *cols != current_cols)
_set_screen_lines (std_dimension[i].rows);
break;
}
i++;
}
}
#else
else if (*rows <= 25)
{
if (current_rows != 25 || current_cols != 80)
{
regs.x.ax = 3;
int86 (0x10, ®s, ®s);
regs.x.ax = 0x1101;
regs.h.bl = 0;
int86 (0x10, ®s, ®s);
regs.x.ax = 0x1200;
regs.h.bl = 32;
int86 (0x10, ®s, ®s);
regs.x.ax = 3;
int86 (0x10, ®s, ®s);
}
}
else if (*rows <= 50)
if (have_vga && (current_rows != 50 || current_cols != 80)
|| *rows <= 43 && (current_rows != 43 || current_cols != 80))
{
regs.x.ax = 3;
int86 (0x10, ®s, ®s);
regs.x.ax = 0x1112;
regs.h.bl = 0;
int86 (0x10, ®s, ®s);
regs.x.ax = 0x1200;
regs.h.bl = 32;
int86 (0x10, ®s, ®s);
regs.x.ax = 0x0100;
regs.x.cx = 7;
int86 (0x10, ®s, ®s);
}
#endif
if (have_mouse)
{
mouse_init ();
mouse_on ();
}
*rows = ScreenRows ();
*cols = ScreenCols ();
screen_size_X = *cols;
screen_size_Y = *rows;
screen_size = *cols * *rows;
#if __DJGPP__ > 1
if (current_rows != *rows || current_cols != *cols)
{
struct frame *f = SELECTED_FRAME();
struct display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
Lisp_Object window = dpyinfo->mouse_face_window;
if (! NILP (window) && XFRAME (XWINDOW (window)->frame) == f)
{
dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
dpyinfo->mouse_face_window = Qnil;
}
}
#endif
bright_bg ();
if (screen_virtual_segment)
dosv_refresh_virtual_screen (0, *cols * *rows);
}
static void
mouse_off_maybe ()
{
int x, y;
if (!mouse_visible)
return;
mouse_get_xy (&x, &y);
if (y != new_pos_Y || x < new_pos_X)
return;
mouse_off ();
}
#define DEFAULT_CURSOR_START (-1)
#define DEFAULT_CURSOR_WIDTH (-1)
#define BOX_CURSOR_WIDTH (-32)
static void
msdos_set_cursor_shape (struct frame *f, int start_line, int width)
{
#if __DJGPP__ > 1
unsigned desired_cursor;
__dpmi_regs regs;
int max_line, top_line, bot_line;
if (f && f != SELECTED_FRAME())
return;
max_line = _farpeekw (_dos_ds, 0x485) - 1;
switch (max_line)
{
default:
case 7:
bot_line = 7;
break;
case 9:
bot_line = 9;
break;
case 13:
bot_line = 12;
break;
case 15:
bot_line = 14;
break;
}
if (width < 0)
{
if (width == BOX_CURSOR_WIDTH)
{
top_line = 0;
bot_line = max_line;
}
else if (start_line != DEFAULT_CURSOR_START)
{
top_line = start_line;
bot_line = top_line - width - 1;
}
else if (width != DEFAULT_CURSOR_WIDTH)
{
top_line = 0;
bot_line = -1 - width;
}
else
top_line = bot_line + 1;
}
else if (width == 0)
{
top_line = 31;
bot_line = 0;
}
else
{
if (start_line != DEFAULT_CURSOR_START)
bot_line = start_line;
top_line = bot_line - (width - 1);
}
desired_cursor = ((top_line & 0x1f) << 8) | (bot_line & 0x1f);
if (desired_cursor == _farpeekw (_dos_ds, 0x460))
return;
regs.h.ah = 1;
regs.x.cx = desired_cursor;
__dpmi_int (0x10, ®s);
#endif
}
static void
IT_set_cursor_type (struct frame *f, Lisp_Object cursor_type)
{
if (EQ (cursor_type, Qbar))
{
msdos_set_cursor_shape (f, DEFAULT_CURSOR_START, DEFAULT_CURSOR_WIDTH);
}
else if (CONSP (cursor_type) && EQ (XCAR (cursor_type), Qbar))
{
Lisp_Object bar_parms = XCDR (cursor_type);
int width;
if (INTEGERP (bar_parms))
{
width = XINT (bar_parms);
msdos_set_cursor_shape (f, width >= 0 ? DEFAULT_CURSOR_START : 0,
width);
}
else if (CONSP (bar_parms)
&& INTEGERP (XCAR (bar_parms))
&& INTEGERP (XCDR (bar_parms)))
{
int start_line = XINT (XCDR (bar_parms));
width = XINT (XCAR (bar_parms));
msdos_set_cursor_shape (f, start_line, width);
}
}
else
msdos_set_cursor_shape (f, 0, BOX_CURSOR_WIDTH);
}
static void
IT_ring_bell (void)
{
if (visible_bell)
{
mouse_off ();
ScreenVisualBell ();
}
else
{
union REGS inregs, outregs;
inregs.h.ah = 2;
inregs.h.dl = 7;
intdos (&inregs, &outregs);
}
}
static void
IT_set_face (int face)
{
struct frame *sf = SELECTED_FRAME();
struct face *fp = FACE_FROM_ID (sf, face);
struct face *dfp = FACE_FROM_ID (sf, DEFAULT_FACE_ID);
unsigned long fg, bg, dflt_fg, dflt_bg;
if (!fp)
{
fp = dfp;
if (!fp)
abort ();
}
screen_face = face;
fg = fp->foreground;
bg = fp->background;
dflt_fg = dfp->foreground;
dflt_bg = dfp->background;
if (fg == FACE_TTY_DEFAULT_COLOR || fg == FACE_TTY_DEFAULT_FG_COLOR)
fg = FRAME_FOREGROUND_PIXEL (sf);
else if (fg == FACE_TTY_DEFAULT_BG_COLOR)
fg = FRAME_BACKGROUND_PIXEL (sf);
if (bg == FACE_TTY_DEFAULT_COLOR || bg == FACE_TTY_DEFAULT_BG_COLOR)
bg = FRAME_BACKGROUND_PIXEL (sf);
else if (bg == FACE_TTY_DEFAULT_FG_COLOR)
bg = FRAME_FOREGROUND_PIXEL (sf);
if ((highlight || fp->tty_reverse_p)
&& (fg == dflt_fg && bg == dflt_bg))
{
unsigned long tem = fg;
fg = bg;
bg = tem;
}
if (inverse_video)
{
unsigned long tem2 = fg;
fg = bg;
bg = tem2;
}
if (termscript)
fprintf (termscript, "<FACE %d%s: %d/%d[FG:%d/BG:%d]>", face,
highlight ? "H" : "", fp->foreground, fp->background, fg, bg);
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 (struct glyph *str, int str_len)
{
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 =
(terminal_coding.common_flags & CODING_REQUIRE_ENCODING_MASK
? &terminal_coding
: &safe_terminal_coding);
struct frame *sf;
int convert_unibyte_characters
= (NILP (current_buffer->enable_multibyte_characters)
&& unibyte_display_via_language_environment);
unsigned char conversion_buffer[256];
int conversion_buffer_size = sizeof conversion_buffer;
if (str_len <= 0) return;
screen_buf = screen_bp = alloca (str_len * 2);
screen_buf_end = screen_buf + str_len * 2;
sf = SELECTED_FRAME();
IT_set_face (DEFAULT_FACE_ID);
terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
while (sl)
{
int cf, chlen, enclen;
unsigned char workbuf[MAX_MULTIBYTE_LENGTH], *buf;
unsigned ch;
if (CHAR_GLYPH_PADDING_P (*str))
{
str++;
sl--;
}
else
{
register GLYPH g = GLYPH_FROM_CHAR_GLYPH (*str);
int glyph_not_in_table = 0;
if (g < 0 || g >= tlen)
{
ch = str->u.ch;
glyph_not_in_table = 1;
}
else
{
GLYPH_FOLLOW_ALIASES (tbase, tlen, g);
ch = FAST_GLYPH_CHAR (g);
}
if (SINGLE_BYTE_CHAR_P (ch) && convert_unibyte_characters
&& (ch >= 0240
|| (ch >= 0200 && !NILP (Vnonascii_translation_table))))
ch = unibyte_char_to_multibyte (ch);
if (! CHAR_VALID_P (ch, 0))
{
g = !NILP (Vdos_unsupported_char_glyph)
? Vdos_unsupported_char_glyph
: MAKE_GLYPH (sf, '\177', GLYPH_FACE (sf, g));
ch = FAST_GLYPH_CHAR (g);
}
cf = str->face_id;
if (cf != screen_face)
IT_set_face (cf);
if (glyph_not_in_table || GLYPH_SIMPLE_P (tbase, tlen, g))
{
chlen = CHAR_STRING (ch, workbuf);
buf = workbuf;
}
else
{
chlen = GLYPH_LENGTH (tbase, g);
buf = GLYPH_STRING (tbase, g);
}
if (chlen == 1)
{
*conversion_buffer = (unsigned char)ch;
chlen = 0;
enclen = 1;
}
else
{
coding->src_multibyte = 1;
encode_coding (coding, buf, conversion_buffer, chlen,
conversion_buffer_size);
chlen -= coding->consumed;
enclen = coding->produced;
if (*conversion_buffer == '?')
{
unsigned 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)
{
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;
screen_bp = screen_buf;
}
else
{
for (bp = conversion_buffer; enclen--; bp++)
{
*screen_bp++ = (unsigned char)*bp;
*screen_bp++ = ScreenAttrib;
if (termscript)
fputc (*bp, termscript);
}
if (chlen > 0)
{
buf += coding->consumed;
while (chlen--)
{
if (termscript)
fputc (*buf, termscript);
*screen_bp++ = (unsigned char)*buf++;
*screen_bp++ = ScreenAttrib;
}
}
str++;
sl--;
}
}
}
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;
if (CODING_REQUIRE_FLUSHING (coding))
{
coding->mode |= CODING_MODE_LAST_BLOCK;
encode_coding (coding, "", conversion_buffer, 0, conversion_buffer_size);
if (coding->produced > 0)
{
screen_buf = alloca (coding->produced * 2);
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;
}
}
}
int disable_mouse_highlight;
static Lisp_Object help_echo;
static Lisp_Object previous_help_echo;
static Lisp_Object help_echo_window;
static Lisp_Object help_echo_object;
static int help_echo_pos;
static int mouse_preempted = 0;
static void
IT_set_mouse_pointer (int mode)
{
}
static void
show_mouse_face (struct display_info *dpyinfo, int hl)
{
struct window *w = XWINDOW (dpyinfo->mouse_face_window);
struct frame *f = XFRAME (WINDOW_FRAME (w));
int i;
struct face *fp;
if (w->current_matrix == NULL)
goto set_cursor_shape;
if (dpyinfo->mouse_face_end_row >= w->current_matrix->nrows)
goto set_cursor_shape;
if (hl > 0)
{
fp = FACE_FROM_ID (SELECTED_FRAME(), dpyinfo->mouse_face_face_id);
if (!fp)
goto set_cursor_shape;
}
for (i = dpyinfo->mouse_face_beg_row;
i <= dpyinfo->mouse_face_end_row;
i++)
{
int start_hpos, end_hpos;
struct glyph_row *row = MATRIX_ROW (w->current_matrix, i);
if (!row->enabled_p)
continue;
if (i == dpyinfo->mouse_face_beg_row)
start_hpos = dpyinfo->mouse_face_beg_col;
else
start_hpos = 0;
if (i == dpyinfo->mouse_face_end_row)
end_hpos = dpyinfo->mouse_face_end_col;
else
end_hpos = row->used[TEXT_AREA];
if (end_hpos <= start_hpos)
continue;
row->mouse_face_p = hl > 0;
if (hl > 0)
{
int vpos = row->y + WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w);
int kstart = start_hpos + WINDOW_DISPLAY_LEFT_EDGE_PIXEL_X (w);
int nglyphs = end_hpos - start_hpos;
int offset = ScreenPrimary + 2*(vpos*screen_size_X + kstart) + 1;
int start_offset = offset;
if (termscript)
fprintf (termscript, "\n<MH+ %d-%d:%d>",
kstart, kstart + nglyphs - 1, vpos);
mouse_off ();
IT_set_face (dpyinfo->mouse_face_face_id);
_farsetsel (_dos_ds);
while (nglyphs--)
{
_farnspokeb (offset, ScreenAttrib);
offset += 2;
}
if (screen_virtual_segment)
dosv_refresh_virtual_screen (start_offset, end_hpos - start_hpos);
mouse_on ();
}
else
{
int nglyphs = end_hpos - start_hpos;
int save_x = new_pos_X, save_y = new_pos_Y;
if (end_hpos >= row->used[TEXT_AREA])
nglyphs = row->used[TEXT_AREA] - start_hpos;
new_pos_X = start_hpos + WINDOW_DISPLAY_LEFT_EDGE_PIXEL_X (w);
new_pos_Y = row->y + WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w);
if (termscript)
fprintf (termscript, "<MH- %d-%d:%d>",
new_pos_X, new_pos_X + nglyphs - 1, new_pos_Y);
IT_write_glyphs (row->glyphs[TEXT_AREA] + start_hpos, nglyphs);
if (termscript)
fputs ("\n", termscript);
new_pos_X = save_x;
new_pos_Y = save_y;
}
}
set_cursor_shape:
IT_set_mouse_pointer (hl);
}
static void
clear_mouse_face (struct display_info *dpyinfo)
{
if (! NILP (dpyinfo->mouse_face_window))
show_mouse_face (dpyinfo, 0);
dpyinfo->mouse_face_beg_row = dpyinfo->mouse_face_beg_col = -1;
dpyinfo->mouse_face_end_row = dpyinfo->mouse_face_end_col = -1;
dpyinfo->mouse_face_window = Qnil;
}
static int
fast_find_position (struct window *w, int pos, int *hpos, int *vpos)
{
int i;
int lastcol;
int maybe_next_line_p = 0;
int line_start_position;
int yb = window_text_bottom_y (w);
struct glyph_row *row = MATRIX_ROW (w->current_matrix, 0);
struct glyph_row *best_row = row;
while (row->y < yb)
{
if (row->used[TEXT_AREA])
line_start_position = row->glyphs[TEXT_AREA]->charpos;
else
line_start_position = 0;
if (line_start_position > pos)
break;
else if (line_start_position == pos
&& pos == BUF_ZV (XBUFFER (w->buffer)))
{
maybe_next_line_p = 1;
break;
}
else if (line_start_position > 0)
best_row = row;
if (row->y + 1 >= yb)
break;
++row;
}
lastcol = 0;
row = best_row;
for (i = 0; i < row->used[TEXT_AREA]; i++)
{
struct glyph *glyph = row->glyphs[TEXT_AREA] + i;
int charpos;
charpos = glyph->charpos;
if (charpos == pos)
{
*hpos = i;
*vpos = row->y;
return 1;
}
else if (charpos > pos)
break;
else if (charpos > 0)
lastcol = i;
}
if (maybe_next_line_p)
{
++row;
lastcol = 0;
}
*vpos = row->y;
*hpos = lastcol + 1;
return 0;
}
static void
IT_note_mode_line_highlight (struct window *w, int x, int mode_line_p)
{
struct frame *f = XFRAME (w->frame);
struct display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
struct glyph_row *row;
if (mode_line_p)
row = MATRIX_MODE_LINE_ROW (w->current_matrix);
else
row = MATRIX_HEADER_LINE_ROW (w->current_matrix);
if (row->enabled_p)
{
extern Lisp_Object Qhelp_echo;
struct glyph *glyph, *end;
Lisp_Object help, map;
glyph = row->glyphs[TEXT_AREA]
+ x - FRAME_LEFT_SCROLL_BAR_WIDTH (f) * CANON_X_UNIT (f);
end = glyph + row->used[TEXT_AREA];
if (glyph < end
&& STRINGP (glyph->object)
&& XSTRING (glyph->object)->intervals
&& glyph->charpos >= 0
&& glyph->charpos < XSTRING (glyph->object)->size)
{
help = Fget_text_property (make_number (glyph->charpos),
Qhelp_echo, glyph->object);
if (!NILP (help))
{
help_echo = help;
XSETWINDOW (help_echo_window, w);
help_echo_object = glyph->object;
help_echo_pos = glyph->charpos;
}
}
}
}
static void
IT_note_mouse_highlight (struct frame *f, int x, int y)
{
struct display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
int portion = -1;
Lisp_Object window;
struct window *w;
if (mouse_preempted)
return;
if (disable_mouse_highlight
|| !f->glyphs_initialized_p)
return;
dpyinfo->mouse_face_mouse_x = x;
dpyinfo->mouse_face_mouse_y = y;
dpyinfo->mouse_face_mouse_frame = f;
if (dpyinfo->mouse_face_defer)
return;
if (gc_in_progress)
{
dpyinfo->mouse_face_deferred_gc = 1;
return;
}
window = window_from_coordinates (f, x, y, &portion, 0);
if (! EQ (window, dpyinfo->mouse_face_window))
clear_mouse_face (dpyinfo);
if (!WINDOWP (window))
return;
w = XWINDOW (window);
x -= WINDOW_DISPLAY_LEFT_EDGE_PIXEL_X (w);
y -= WINDOW_DISPLAY_TOP_EDGE_PIXEL_Y (w);
if (portion == 1 || portion == 3)
{
IT_note_mode_line_highlight (w, x, portion == 1);
return;
}
else
IT_set_mouse_pointer (0);
if (
portion == 0
&& EQ (w->window_end_valid, w->buffer)
&& XFASTINT (w->last_modified) == BUF_MODIFF (XBUFFER (w->buffer))
&& (XFASTINT (w->last_overlay_modified)
== BUF_OVERLAY_MODIFF (XBUFFER (w->buffer))))
{
int pos, i;
struct glyph_row *row;
struct glyph *glyph;
int nrows = w->current_matrix->nrows;
glyph = NULL;
if (y >= 0 && y < nrows)
{
row = MATRIX_ROW (w->current_matrix, y);
for (i = 0; i <= y; i++)
if (!MATRIX_ROW (w->current_matrix, i)->enabled_p)
break;
if (i > y
&& row->displays_text_p
&& x < window_box_width (w, TEXT_AREA))
{
glyph = row->glyphs[TEXT_AREA];
if (x >= row->used[TEXT_AREA])
glyph = NULL;
else
{
glyph += x;
if (!BUFFERP (glyph->object))
glyph = NULL;
}
}
}
if (glyph == NULL)
{
clear_mouse_face (dpyinfo);
return;
}
if (!BUFFERP (glyph->object))
abort ();
pos = glyph->charpos;
{
extern Lisp_Object Qmouse_face;
Lisp_Object mouse_face, overlay, position;
Lisp_Object *overlay_vec;
int len, noverlays;
struct buffer *obuf;
int obegv, ozv;
if (pos > BUF_Z (XBUFFER (w->buffer)))
return;
obuf = current_buffer;
current_buffer = XBUFFER (w->buffer);
obegv = BEGV;
ozv = ZV;
BEGV = BEG;
ZV = Z;
XSETINT (position, pos);
len = 10;
overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
noverlays = overlays_at (pos, 0, &overlay_vec, &len, NULL, NULL, 0);
if (noverlays > len)
{
len = noverlays;
overlay_vec = (Lisp_Object *) alloca (len * sizeof (Lisp_Object));
noverlays = overlays_at (pos,
0, &overlay_vec, &len, NULL, NULL, 0);
}
noverlays = sort_overlays (overlay_vec, noverlays, w);
if (! (EQ (window, dpyinfo->mouse_face_window)
&& y >= dpyinfo->mouse_face_beg_row
&& y <= dpyinfo->mouse_face_end_row
&& (y > dpyinfo->mouse_face_beg_row
|| x >= dpyinfo->mouse_face_beg_col)
&& (y < dpyinfo->mouse_face_end_row
|| x < dpyinfo->mouse_face_end_col
|| dpyinfo->mouse_face_past_end)))
{
clear_mouse_face (dpyinfo);
overlay = Qnil;
for (i = noverlays - 1; i >= 0; --i)
{
mouse_face = Foverlay_get (overlay_vec[i], Qmouse_face);
if (!NILP (mouse_face))
{
overlay = overlay_vec[i];
break;
}
}
if (NILP (overlay))
mouse_face = Fget_text_property (position, Qmouse_face,
w->buffer);
if (! NILP (overlay))
{
Lisp_Object before, after;
int ignore;
before = Foverlay_start (overlay);
after = Foverlay_end (overlay);
fast_find_position (w, XFASTINT (before),
&dpyinfo->mouse_face_beg_col,
&dpyinfo->mouse_face_beg_row);
dpyinfo->mouse_face_past_end
= !fast_find_position (w, XFASTINT (after),
&dpyinfo->mouse_face_end_col,
&dpyinfo->mouse_face_end_row);
dpyinfo->mouse_face_window = window;
dpyinfo->mouse_face_face_id
= face_at_buffer_position (w, pos, 0, 0,
&ignore, pos + 1, 1);
show_mouse_face (dpyinfo, 1);
}
else if (! NILP (mouse_face))
{
Lisp_Object before, after, beginning, end;
int ignore;
beginning = Fmarker_position (w->start);
XSETINT (end, (BUF_Z (XBUFFER (w->buffer))
- XFASTINT (w->window_end_pos)));
before
= Fprevious_single_property_change (make_number (pos + 1),
Qmouse_face,
w->buffer, beginning);
after
= Fnext_single_property_change (position, Qmouse_face,
w->buffer, end);
fast_find_position (w, XFASTINT (before),
&dpyinfo->mouse_face_beg_col,
&dpyinfo->mouse_face_beg_row);
dpyinfo->mouse_face_past_end
= !fast_find_position (w, XFASTINT (after),
&dpyinfo->mouse_face_end_col,
&dpyinfo->mouse_face_end_row);
dpyinfo->mouse_face_window = window;
dpyinfo->mouse_face_face_id
= face_at_buffer_position (w, pos, 0, 0,
&ignore, pos + 1, 1);
show_mouse_face (dpyinfo, 1);
}
}
{
Lisp_Object help;
extern Lisp_Object Qhelp_echo;
help = Qnil;
for (i = noverlays - 1; i >= 0 && NILP (help); --i)
{
overlay = overlay_vec[i];
help = Foverlay_get (overlay, Qhelp_echo);
}
if (!NILP (help))
{
help_echo = help;
help_echo_window = window;
help_echo_object = overlay;
help_echo_pos = pos;
}
else if (NILP (help)
&& ((STRINGP (glyph->object)
&& glyph->charpos >= 0
&& glyph->charpos < XSTRING (glyph->object)->size)
|| (BUFFERP (glyph->object)
&& glyph->charpos >= BEGV
&& glyph->charpos < ZV)))
{
help = Fget_text_property (make_number (glyph->charpos),
Qhelp_echo, glyph->object);
if (!NILP (help))
{
help_echo = help;
help_echo_window = window;
help_echo_object = glyph->object;
help_echo_pos = glyph->charpos;
}
}
}
BEGV = obegv;
ZV = ozv;
current_buffer = obuf;
}
}
}
static void
IT_clear_end_of_line (int first_unused)
{
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 (new_pos_X >= first_unused || fatal_error_in_progress)
return;
IT_set_face (0);
i = (j = first_unused - new_pos_X) * 2;
if (termscript)
fprintf (termscript, "<CLR:EOL[%d..%d)>", new_pos_X, first_unused);
spaces = sp = alloca (i);
while (--j >= 0)
{
*sp++ = ' ';
*sp++ = ScreenAttrib;
}
mouse_off_maybe ();
dosmemput (spaces, i, (int)ScreenPrimary + offset);
if (screen_virtual_segment)
dosv_refresh_virtual_screen (offset, i / 2);
new_pos_X = first_unused;
}
static void
IT_clear_screen (void)
{
if (termscript)
fprintf (termscript, "<CLR:SCR>");
if (FACE_FROM_ID (SELECTED_FRAME (), DEFAULT_FACE_ID) == NULL)
ScreenAttrib = (initial_screen_colors[0] << 4) | initial_screen_colors[1];
else
IT_set_face (0);
mouse_off ();
ScreenClear ();
if (screen_virtual_segment)
dosv_refresh_virtual_screen (0, screen_size);
new_pos_X = new_pos_Y = 0;
}
static void
IT_clear_to_end (void)
{
if (termscript)
fprintf (termscript, "<CLR:EOS>");
while (new_pos_Y < screen_size_Y) {
new_pos_X = 0;
IT_clear_end_of_line (screen_size_X);
new_pos_Y++;
}
}
static void
IT_cursor_to (int y, int x)
{
if (termscript)
fprintf (termscript, "\n<XY=%dx%d>", x, y);
new_pos_X = x;
new_pos_Y = y;
}
static int cursor_cleared;
static void
IT_display_cursor (int on)
{
if (on && cursor_cleared)
{
ScreenSetCursor (current_pos_Y, current_pos_X);
cursor_cleared = 0;
}
else if (!on && !cursor_cleared)
{
ScreenSetCursor (-1, -1);
cursor_cleared = 1;
}
}
static void
IT_cmgoto (FRAME_PTR f)
{
int update_cursor_pos = 1;
#if 0
static int previous_pos_X = -1;
update_cursor_pos = 1;
if (update_cursor_pos && previous_pos_X >= 0)
previous_pos_X = -1;
if (!update_cursor_pos
&& XFASTINT (XWINDOW (FRAME_MINIBUF_WINDOW (f))->top) <= new_pos_Y)
{
int tem_X = current_pos_X, dummy;
if (echo_area_glyphs)
{
tem_X = echo_area_glyphs_length;
if (previous_pos_X == -1)
ScreenGetCursor (&dummy, &previous_pos_X);
}
else if (previous_pos_X >= 0)
{
tem_X = previous_pos_X;
previous_pos_X = -1;
}
if (current_pos_X != tem_X)
{
new_pos_X = tem_X;
update_cursor_pos = 1;
}
}
#endif
if (update_cursor_pos
&& (current_pos_X != new_pos_X || current_pos_Y != new_pos_Y))
{
ScreenSetCursor (current_pos_Y = new_pos_Y, current_pos_X = new_pos_X);
if (termscript)
fprintf (termscript, "\n<CURSOR:%dx%d>", current_pos_X, current_pos_Y);
}
IT_display_cursor (1);
if (!mouse_visible)
mouse_on ();
}
static void
IT_reassert_line_highlight (int new, int vpos)
{
highlight = new;
}
static void
IT_change_line_highlight (int new_highlight, int y, int vpos, int first_unused_hpos)
{
highlight = new_highlight;
IT_cursor_to (vpos, 0);
IT_clear_end_of_line (first_unused_hpos);
}
static void
IT_update_begin (struct frame *f)
{
struct display_info *display_info = FRAME_X_DISPLAY_INFO (f);
struct frame *mouse_face_frame = display_info->mouse_face_mouse_frame;
highlight = 0;
BLOCK_INPUT;
if (f && f == mouse_face_frame)
{
display_info->mouse_face_defer = 1;
if (FRAME_GARBAGED_P (f))
display_info->mouse_face_window = Qnil;
if (!NILP (display_info->mouse_face_window)
&& WINDOWP (display_info->mouse_face_window))
{
struct window *w = XWINDOW (display_info->mouse_face_window);
int i;
if (NILP (w->buffer))
display_info->mouse_face_window = Qnil;
else
{
for (i = 0; i < w->desired_matrix->nrows; ++i)
if (MATRIX_ROW_ENABLED_P (w->desired_matrix, i)
&& MATRIX_ROW (w->current_matrix, i)->mouse_face_p)
break;
}
if (NILP (w->buffer) || i < w->desired_matrix->nrows)
clear_mouse_face (display_info);
}
}
else if (mouse_face_frame && !FRAME_LIVE_P (mouse_face_frame))
{
display_info->mouse_face_beg_row = display_info->mouse_face_beg_col = -1;
display_info->mouse_face_end_row = display_info->mouse_face_end_col = -1;
display_info->mouse_face_window = Qnil;
display_info->mouse_face_deferred_gc = 0;
display_info->mouse_face_mouse_frame = NULL;
}
UNBLOCK_INPUT;
}
static void
IT_update_end (struct frame *f)
{
highlight = 0;
FRAME_X_DISPLAY_INFO (f)->mouse_face_defer = 0;
}
Lisp_Object Qcursor_type;
static void
IT_frame_up_to_date (struct frame *f)
{
struct display_info *dpyinfo = FRAME_X_DISPLAY_INFO (f);
Lisp_Object new_cursor, frame_desired_cursor;
struct window *sw;
if (dpyinfo->mouse_face_deferred_gc
|| (f && f == dpyinfo->mouse_face_mouse_frame))
{
BLOCK_INPUT;
if (dpyinfo->mouse_face_mouse_frame)
IT_note_mouse_highlight (dpyinfo->mouse_face_mouse_frame,
dpyinfo->mouse_face_mouse_x,
dpyinfo->mouse_face_mouse_y);
dpyinfo->mouse_face_deferred_gc = 0;
UNBLOCK_INPUT;
}
sw = XWINDOW (f->selected_window);
frame_desired_cursor = Fcdr (Fassq (Qcursor_type, f->param_alist));
if (cursor_in_echo_area
&& FRAME_HAS_MINIBUF_P (f)
&& EQ (FRAME_MINIBUF_WINDOW (f), echo_area_window)
&& sw == XWINDOW (echo_area_window))
new_cursor = frame_desired_cursor;
else
{
struct buffer *b = XBUFFER (sw->buffer);
if (EQ (b->cursor_type, Qt))
new_cursor = frame_desired_cursor;
else if (NILP (b->cursor_type))
new_cursor = Fcons (Qbar, make_number (0));
else
new_cursor = b->cursor_type;
}
IT_set_cursor_type (f, new_cursor);
IT_cmgoto (f);
}
static void
IT_copy_glyphs (int xfrom, int xto, size_t len, int ypos)
{
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);
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);
}
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);
IT_copy_glyphs (new_pos_X, new_pos_X + len, shift_by_width, new_pos_Y);
IT_write_glyphs (start, len);
}
static void
IT_delete_glyphs (n)
register int n;
{
abort ();
}
void
x_set_menu_bar_lines (f, value, oldval)
struct frame *f;
Lisp_Object value, oldval;
{
set_menu_bar_lines (f, value, oldval);
}
extern Lisp_Object Qbackground_color;
extern Lisp_Object Qforeground_color;
Lisp_Object Qreverse;
extern Lisp_Object Qtitle;
static void
IT_set_terminal_modes (void)
{
if (termscript)
fprintf (termscript, "\n<SET_TERM>");
highlight = 0;
screen_size_X = ScreenCols ();
screen_size_Y = ScreenRows ();
screen_size = screen_size_X * screen_size_Y;
new_pos_X = new_pos_Y = 0;
current_pos_X = current_pos_Y = -1;
if (term_setup_done)
return;
term_setup_done = 1;
startup_screen_size_X = screen_size_X;
startup_screen_size_Y = screen_size_Y;
startup_screen_attrib = ScreenAttrib;
#if __DJGPP__ > 1
{
unsigned short es_value;
__dpmi_regs regs;
regs.h.ah = 0xfe;
if (ScreenPrimary == 0xb0000UL || ScreenPrimary == 0xb8000UL)
regs.x.es = (ScreenPrimary >> 4) & 0xffff;
else if (screen_old_address)
regs.x.es = (screen_old_address >> 4) & 0xffff;
else
regs.x.es = ScreenMode () == 7 ? 0xb000 : 0xb800;
regs.x.di = 0;
es_value = regs.x.es;
__dpmi_int (0x10, ®s);
if (regs.x.es != es_value)
{
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;
}
}
#endif
ScreenGetCursor (&startup_pos_Y, &startup_pos_X);
ScreenRetrieve (startup_screen_buffer = xmalloc (screen_size * 2));
if (termscript)
fprintf (termscript, "<SCREEN SAVED (dimensions=%dx%d)>\n",
screen_size_X, screen_size_Y);
bright_bg ();
}
static void
IT_reset_terminal_modes (void)
{
int display_row_start = (int) ScreenPrimary;
int saved_row_len = startup_screen_size_X * 2;
int update_row_len = ScreenCols () * 2;
int current_rows = ScreenRows ();
int to_next_row = update_row_len;
unsigned char *saved_row = startup_screen_buffer;
int cursor_pos_X = ScreenCols () - 1;
int cursor_pos_Y = ScreenRows () - 1;
if (termscript)
fprintf (termscript, "\n<RESET_TERM>");
highlight = 0;
if (!term_setup_done)
return;
mouse_off ();
maybe_enable_blinking ();
ScreenAttrib = startup_screen_attrib;
if (clock () - startup_time >= 2*CLOCKS_PER_SEC)
{
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--)
{
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;
if (startup_pos_Y < cursor_pos_Y)
cursor_pos_Y = startup_pos_Y;
ScreenSetCursor (cursor_pos_Y, cursor_pos_X);
xfree (startup_screen_buffer);
term_setup_done = 0;
}
static void
IT_set_terminal_window (int foo)
{
}
DEFUN ("msdos-remember-default-colors", Fmsdos_remember_default_colors,
Smsdos_remember_default_colors, 1, 1, 0,
"Remember the screen colors of the current frame.")
(frame)
Lisp_Object frame;
{
struct frame *f;
CHECK_FRAME (frame, 0);
f= XFRAME (frame);
if (EQ (Fcdr (Fassq (Qreverse, f->param_alist)), Qt))
{
initial_screen_colors[0] = FRAME_BACKGROUND_PIXEL (f);
initial_screen_colors[1] = FRAME_FOREGROUND_PIXEL (f);
}
else
{
initial_screen_colors[0] = FRAME_FOREGROUND_PIXEL (f);
initial_screen_colors[1] = FRAME_BACKGROUND_PIXEL (f);
}
}
void
IT_set_frame_parameters (f, alist)
struct frame *f;
Lisp_Object alist;
{
Lisp_Object tail;
int length = XINT (Flength (alist));
int i, j;
Lisp_Object *parms
= (Lisp_Object *) alloca (length * sizeof (Lisp_Object));
Lisp_Object *values
= (Lisp_Object *) alloca (length * sizeof (Lisp_Object));
int reverse = EQ (Fcdr (Fassq (Qreverse, f->param_alist)), Qt);
int was_reverse = reverse;
int redraw = 0, fg_set = 0, bg_set = 0;
int need_to_reverse;
unsigned long orig_fg;
unsigned long orig_bg;
Lisp_Object frame_bg, frame_fg;
extern Lisp_Object Qdefault, QCforeground, QCbackground;
if (alist == Vdefault_frame_alist
&& initial_screen_colors[0] != -1 && initial_screen_colors[1] != -1)
{
FRAME_FOREGROUND_PIXEL (f) = initial_screen_colors[0];
FRAME_BACKGROUND_PIXEL (f) = initial_screen_colors[1];
}
orig_fg = FRAME_FOREGROUND_PIXEL (f);
orig_bg = FRAME_BACKGROUND_PIXEL (f);
frame_fg = Fcdr (Fassq (Qforeground_color, f->param_alist));
frame_bg = Fcdr (Fassq (Qbackground_color, f->param_alist));
if (NILP (frame_fg))
frame_fg = build_string (unspecified_fg);
if (NILP (frame_bg))
frame_bg = build_string (unspecified_bg);
i = 0;
for (tail = alist; CONSP (tail); tail = Fcdr (tail))
{
Lisp_Object elt;
elt = Fcar (tail);
parms[i] = Fcar (elt);
CHECK_SYMBOL (parms[i], 1);
values[i] = Fcdr (elt);
i++;
}
j = i;
for (i = 0; i < j; i++)
{
Lisp_Object prop, val;
prop = parms[i];
val = values[i];
if (EQ (prop, Qreverse))
reverse = EQ (val, Qt);
}
need_to_reverse = reverse && !was_reverse;
if (termscript && need_to_reverse)
fprintf (termscript, "<INVERSE-VIDEO>\n");
for (i--; i >= 0; i--)
{
Lisp_Object prop, val;
Lisp_Object frame;
prop = parms[i];
val = values[i];
if (EQ (prop, Qforeground_color))
{
unsigned long new_color = load_color (f, NULL, val, need_to_reverse
? LFACE_BACKGROUND_INDEX
: LFACE_FOREGROUND_INDEX);
if (new_color != FACE_TTY_DEFAULT_COLOR
&& new_color != FACE_TTY_DEFAULT_FG_COLOR
&& new_color != FACE_TTY_DEFAULT_BG_COLOR)
{
FRAME_FOREGROUND_PIXEL (f) = new_color;
XSETFRAME (frame, f);
if (need_to_reverse)
{
Finternal_set_lisp_face_attribute (Qdefault, QCbackground,
val, frame);
prop = Qbackground_color;
bg_set = 1;
}
else
{
Finternal_set_lisp_face_attribute (Qdefault, QCforeground,
val, frame);
fg_set = 1;
}
redraw = 1;
if (termscript)
fprintf (termscript, "<FGCOLOR %lu>\n", new_color);
}
}
else if (EQ (prop, Qbackground_color))
{
unsigned long new_color = load_color (f, NULL, val, need_to_reverse
? LFACE_FOREGROUND_INDEX
: LFACE_BACKGROUND_INDEX);
if (new_color != FACE_TTY_DEFAULT_COLOR
&& new_color != FACE_TTY_DEFAULT_FG_COLOR
&& new_color != FACE_TTY_DEFAULT_BG_COLOR)
{
FRAME_BACKGROUND_PIXEL (f) = new_color;
XSETFRAME (frame, f);
if (need_to_reverse)
{
Finternal_set_lisp_face_attribute (Qdefault, QCforeground,
val, frame);
prop = Qforeground_color;
fg_set = 1;
}
else
{
Finternal_set_lisp_face_attribute (Qdefault, QCbackground,
val, frame);
bg_set = 1;
}
redraw = 1;
if (termscript)
fprintf (termscript, "<BGCOLOR %lu>\n", new_color);
}
}
else if (EQ (prop, Qtitle))
{
x_set_title (f, val);
if (termscript)
fprintf (termscript, "<TITLE: %s>\n", XSTRING (val)->data);
}
else if (EQ (prop, Qcursor_type))
{
IT_set_cursor_type (f, val);
if (termscript)
fprintf (termscript, "<CTYPE: %s>\n",
EQ (val, Qbar) || CONSP (val) && EQ (XCAR (val), Qbar)
? "bar" : "box");
}
store_frame_param (f, prop, val);
}
if (need_to_reverse)
{
Lisp_Object frame;
if (!fg_set)
{
XSETFRAME (frame, f);
Finternal_set_lisp_face_attribute (Qdefault, QCforeground,
tty_color_name (f, orig_bg),
frame);
redraw = 1;
}
if (!bg_set)
{
XSETFRAME (frame, f);
Finternal_set_lisp_face_attribute (Qdefault, QCbackground,
tty_color_name (f, orig_fg),
frame);
redraw = 1;
}
}
if (redraw)
{
face_change_count++;
if (f == SELECTED_FRAME())
redraw_frame (f);
}
}
extern void init_frame_faces (FRAME_PTR);
#endif
void
internal_terminal_init ()
{
char *term = getenv ("TERM");
char *colors;
struct frame *sf = SELECTED_FRAME();
#ifdef HAVE_X_WINDOWS
if (!inhibit_window_system)
return;
#endif
internal_terminal
= (!noninteractive) && term && !strcmp (term, "internal");
if (getenv ("EMACSTEST"))
termscript = fopen (getenv ("EMACSTEST"), "wt");
#ifndef HAVE_X_WINDOWS
if (!internal_terminal || inhibit_window_system)
{
sf->output_method = output_termcap;
return;
}
Vwindow_system = intern ("pc");
Vwindow_system_version = make_number (1);
sf->output_method = output_msdos_raw;
screen_old_address = 0;
initial_screen_colors[0] = initial_screen_colors[1] = -1;
bzero (&the_only_x_display, sizeof the_only_x_display);
the_only_x_display.background_pixel = 7;
the_only_x_display.foreground_pixel = 0;
bright_bg ();
colors = getenv ("EMACSCOLORS");
if (colors && strlen (colors) >= 2)
{
if (isdigit (colors[0]))
colors[0] -= '0';
else if (isxdigit (colors[0]))
colors[0] -= (isupper (colors[0]) ? 'A' : 'a') - 10;
if (colors[0] >= 0 && colors[0] < 16)
the_only_x_display.foreground_pixel = colors[0];
if (isdigit (colors[1]))
colors[1] -= '0';
else if (isxdigit (colors[1]))
colors[1] -= (isupper (colors[1]) ? 'A' : 'a') - 10;
if (colors[1] >= 0 && colors[1] < 16)
the_only_x_display.background_pixel = colors[1];
}
the_only_x_display.line_height = 1;
the_only_x_display.font = (XFontStruct *)1;
the_only_x_display.display_info.mouse_face_mouse_frame = NULL;
the_only_x_display.display_info.mouse_face_deferred_gc = 0;
the_only_x_display.display_info.mouse_face_beg_row =
the_only_x_display.display_info.mouse_face_beg_col = -1;
the_only_x_display.display_info.mouse_face_end_row =
the_only_x_display.display_info.mouse_face_end_col = -1;
the_only_x_display.display_info.mouse_face_face_id = DEFAULT_FACE_ID;
the_only_x_display.display_info.mouse_face_window = Qnil;
the_only_x_display.display_info.mouse_face_mouse_x =
the_only_x_display.display_info.mouse_face_mouse_y = 0;
the_only_x_display.display_info.mouse_face_defer = 0;
init_frame_faces (sf);
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;
clear_end_of_line_hook = IT_clear_end_of_line;
clear_frame_hook = IT_clear_screen;
change_line_highlight_hook = IT_change_line_highlight;
update_begin_hook = IT_update_begin;
update_end_hook = IT_update_end;
reassert_line_highlight_hook = IT_reassert_line_highlight;
frame_up_to_date_hook = IT_frame_up_to_date;
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
}
dos_get_saved_screen (screen, rows, cols)
char **screen;
int *rows;
int *cols;
{
#ifndef HAVE_X_WINDOWS
*screen = startup_screen_buffer;
*cols = startup_screen_size_X;
*rows = startup_screen_size_Y;
return *screen != (char *)0;
#else
return 0;
#endif
}
#ifndef HAVE_X_WINDOWS
void
check_x (void)
{
if (! FRAME_MSDOS_P (SELECTED_FRAME()))
error ("Not running under a window system");
}
#endif
#define Ignore 0x0000
#define Normal 0x0000
#define FctKey 0x1000
#define Special 0x2000
#define ModFct 0x3000
#define Map 0x4000
#define KeyPad 0x5000
#define Grey 0x6000
#define Alt 0x0100
#define Ctrl 0x0200
#define Shift 0x0400
static int extended_kbd;
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;
};
static struct dos_keyboard_map us_keyboard = {
"`1234567890-= qwertyuiop[] asdfghjkl;'\\ zxcvbnm,./ ",
"~!@#$%^&*()_+ QWERTYUIOP{} ASDFGHJKL:\"| ZXCVBNM<>? ",
0,
0
};
static struct dos_keyboard_map fr_keyboard = {
"ý&‚\",(-Š_€…)= azertyuiop^$ qsdfghjklm—* wxcvbnm;:! ",
" 1234567890ø+ AZERTYUIOPùœ QSDFGHJKLM%æ WXCVBN?./õ ",
" ~#{[|`\\^@]} Ï ",
0
};
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 = {
"\\1234567890'< qwertyuiopŠ+> asdfghjkl•…— zxcvbnm,.- ",
"|!\"œ$%&/()=?^> QWERTYUIOP‚* ASDFGHJKL‡øõ ZXCVBNM;:_ ",
" {}~` [] @# ",
it_kbd_translate_table
};
static struct dos_keyboard_map dk_keyboard = {
"«1234567890+| qwertyuiop†~ asdfghjkl‘›' zxcvbnm,.- ",
"õ!\"#$%&/()=?` QWERTYUIOP^ ASDFGHJKL’* ZXCVBNM;:_ ",
" @œ$ {[]} | ",
0
};
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 = {
"\\1234567890-^\\ qwertyuiop@[ asdfghjkl;:] zxcvbnm,./ ",
"_!\"#$%&'()~=~| QWERTYUIOP`{ ASDFGHJKL+*} ZXCVBNM<>? ",
0,
jp_kbd_translate_table
};
static struct keyboard_layout_list
{
int country_code;
struct dos_keyboard_map *keyboard_map;
} keyboard_layout_list[] =
{
1, &us_keyboard,
33, &fr_keyboard,
39, &it_keyboard,
45, &dk_keyboard,
81, &jp_keyboard
};
static struct dos_keyboard_map *keyboard;
static int keyboard_map_all;
static int international_keyboard;
int
dos_set_keyboard (code, always)
int code;
int always;
{
int i;
_go32_dpmi_registers regs;
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;
keyboard = keyboard_layout_list[0].keyboard_map;
keyboard_map_all = always;
dos_keyboard_layout = 1;
for (i = 0; i < (sizeof (keyboard_layout_list)/sizeof (struct keyboard_layout_list)); i++)
if (code == keyboard_layout_list[i].country_code)
{
keyboard = keyboard_layout_list[i].keyboard_map;
keyboard_map_all = always;
dos_keyboard_layout = code;
return 1;
}
return 0;
}
static struct
{
unsigned char char_code;
unsigned char meta_code;
unsigned char keypad_code;
unsigned char editkey_code;
} keypad_translate_map[] = {
'0', '0', 0xb0, 0x63,
'1', '1', 0xb1, 0x57,
'2', '2', 0xb2, 0x54,
'3', '3', 0xb3, 0x56,
'4', '4', 0xb4, 0x51,
'5', '5', 0xb5, 0xb5,
'6', '6', 0xb6, 0x53,
'7', '7', 0xb7, 0x50,
'8', '8', 0xb8, 0x52,
'9', '9', 0xb9, 0x55,
'.', '-', 0xae, 0xff
};
static struct
{
unsigned char char_code;
unsigned char keypad_code;
} grey_key_translate_map[] = {
'/', 0xaf,
'*', 0xaa,
'-', 0xad,
'+', 0xab,
'\r', 0x8d
};
static unsigned short
ibmpc_translate_map[] =
{
Normal | 0xff,
Alt | ModFct | 0x1b,
Normal | 1,
Normal | 2,
Normal | 3,
Normal | 4,
Normal | 5,
Normal | 6,
Normal | 7,
Normal | 8,
Normal | 9,
Normal | 10,
Normal | 11,
Normal | 12,
Special | 0x08,
ModFct | 0x74,
Map | 15,
Map | 16,
Map | 17,
Map | 18,
Map | 19,
Map | 20,
Map | 21,
Map | 22,
Map | 23,
Map | 24,
Map | 25,
Map | 26,
ModFct | 0x0d,
Ignore,
Map | 30,
Map | 31,
Map | 32,
Map | 33,
Map | 34,
Map | 35,
Map | 36,
Map | 37,
Map | 38,
Map | 39,
Map | 40,
Map | 0,
Ignore,
Map | 41,
Map | 45,
Map | 46,
Map | 47,
Map | 48,
Map | 49,
Map | 50,
Map | 51,
Map | 52,
Map | 53,
Map | 54,
Ignore,
Grey | 1,
Ignore,
Normal | 55,
Ignore,
FctKey | 0xbe,
FctKey | 0xbf,
FctKey | 0xc0,
FctKey | 0xc1,
FctKey | 0xc2,
FctKey | 0xc3,
FctKey | 0xc4,
FctKey | 0xc5,
FctKey | 0xc6,
FctKey | 0xc7,
Ignore,
Ignore,
KeyPad | 7,
KeyPad | 8,
KeyPad | 9,
Grey | 2,
KeyPad | 4,
KeyPad | 5,
KeyPad | 6,
Grey | 3,
KeyPad | 1,
KeyPad | 2,
KeyPad | 3,
KeyPad | 0,
KeyPad | 10,
Shift | FctKey | 0xbe,
Shift | FctKey | 0xbf,
Shift | FctKey | 0xc0,
Shift | FctKey | 0xc1,
Shift | FctKey | 0xc2,
Shift | FctKey | 0xc3,
Shift | FctKey | 0xc4,
Shift | FctKey | 0xc5,
Shift | FctKey | 0xc6,
Shift | FctKey | 0xc7,
Ctrl | FctKey | 0xbe,
Ctrl | FctKey | 0xbf,
Ctrl | FctKey | 0xc0,
Ctrl | FctKey | 0xc1,
Ctrl | FctKey | 0xc2,
Ctrl | FctKey | 0xc3,
Ctrl | FctKey | 0xc4,
Ctrl | FctKey | 0xc5,
Ctrl | FctKey | 0xc6,
Ctrl | FctKey | 0xc7,
Alt | FctKey | 0xbe,
Alt | FctKey | 0xbf,
Alt | FctKey | 0xc0,
Alt | FctKey | 0xc1,
Alt | FctKey | 0xc2,
Alt | FctKey | 0xc3,
Alt | FctKey | 0xc4,
Alt | FctKey | 0xc5,
Alt | FctKey | 0xc6,
Alt | FctKey | 0xc7,
Ctrl | FctKey | 0x6d,
Ctrl | KeyPad | 4,
Ctrl | KeyPad | 6,
Ctrl | KeyPad | 1,
Ctrl | KeyPad | 3,
Ctrl | KeyPad | 7,
Alt | Map | 1,
Alt | Map | 2,
Alt | Map | 3,
Alt | Map | 4,
Alt | Map | 5,
Alt | Map | 6,
Alt | Map | 7,
Alt | Map | 8,
Alt | Map | 9,
Alt | Map | 10,
Alt | Map | 11,
Alt | Map | 12,
Ctrl | KeyPad | 9,
FctKey | 0xc8,
FctKey | 0xc9,
Shift | FctKey | 0xc8,
Shift | FctKey | 0xc9,
Ctrl | FctKey | 0xc8,
Ctrl | FctKey | 0xc9,
Alt | FctKey | 0xc8,
Alt | FctKey | 0xc9,
Ctrl | KeyPad | 8,
Ctrl | Grey | 2,
Ctrl | KeyPad | 5,
Ctrl | Grey | 3,
Ctrl | KeyPad | 2,
Ctrl | KeyPad | 0,
Ctrl | KeyPad | 10,
Ctrl | FctKey | 0x09,
Ctrl | Grey | 0,
Ctrl | Grey | 1,
Alt | FctKey | 0x50,
Alt | FctKey | 0x52,
Alt | FctKey | 0x55,
Ignore,
Alt | FctKey | 0x51,
Ignore,
Alt | FctKey | 0x53,
Ignore,
Alt | FctKey | 0x57,
Alt | KeyPad | 2,
Alt | KeyPad | 3,
Alt | KeyPad | 0,
Alt | KeyPad | 10,
Alt | Grey | 0,
Alt | FctKey | 0x09,
Alt | Grey | 4
};
#define SHIFT_P 0x0003
#define CTRL_P 0x0004
#define ALT_P 0x0008
#define SCRLOCK_P 0x0010
#define NUMLOCK_P 0x0020
#define CAPSLOCK_P 0x0040
#define ALT_GR_P 0x0800
#define SUPER_P 0x4000
#define HYPER_P 0x8000
static int
dos_get_modifiers (keymask)
int *keymask;
{
union REGS regs;
int mask;
int modifiers = 0;
regs.h.ah = extended_kbd ? 0x12 : 0x02;
int86 (0x16, ®s, ®s);
if (!extended_kbd)
{
mask = regs.h.al & (SHIFT_P | CTRL_P | ALT_P |
SCRLOCK_P | NUMLOCK_P | CAPSLOCK_P);
}
else
{
mask = regs.h.al & (SHIFT_P |
SCRLOCK_P | NUMLOCK_P | CAPSLOCK_P);
if (regs.h.ah & 2)
mask |= ALT_P;
if ((regs.h.ah & 8) != 0)
{
mask |= ALT_GR_P;
if (dos_hyper_key == 1)
{
mask |= HYPER_P;
modifiers |= hyper_modifier;
}
else if (dos_super_key == 1)
{
mask |= SUPER_P;
modifiers |= super_modifier;
}
else if (!international_keyboard)
{
mask &= ~ALT_GR_P;
mask |= ALT_P;
}
}
if (regs.h.ah & 1)
mask |= CTRL_P;
if (regs.h.ah & 4)
{
if (dos_hyper_key == 2)
{
mask |= HYPER_P;
modifiers |= hyper_modifier;
}
else if (dos_super_key == 2)
{
mask |= SUPER_P;
modifiers |= super_modifier;
}
else
mask |= CTRL_P;
}
}
if (mask & SHIFT_P)
modifiers |= shift_modifier;
if (mask & CTRL_P)
modifiers |= ctrl_modifier;
if (mask & ALT_P)
modifiers |= meta_modifier;
if (keymask)
*keymask = mask;
return modifiers;
}
#define NUM_RECENT_DOSKEYS (100)
int recent_doskeys_index;
int total_doskeys;
Lisp_Object recent_doskeys;
DEFUN ("recent-doskeys", Frecent_doskeys, Srecent_doskeys, 0, 0, 0,
"Return vector of last 100 keyboard input values seen in dos_rawgetc.\n\
Each input key receives two values in this vector: first the ASCII code,\n\
and then the scan code.")
()
{
Lisp_Object *keys = XVECTOR (recent_doskeys)->contents;
Lisp_Object val;
if (total_doskeys < NUM_RECENT_DOSKEYS)
return Fvector (total_doskeys, keys);
else
{
val = Fvector (NUM_RECENT_DOSKEYS, keys);
bcopy (keys + recent_doskeys_index,
XVECTOR (val)->contents,
(NUM_RECENT_DOSKEYS - recent_doskeys_index) * sizeof (Lisp_Object));
bcopy (keys,
XVECTOR (val)->contents + NUM_RECENT_DOSKEYS - recent_doskeys_index,
recent_doskeys_index * sizeof (Lisp_Object));
return val;
}
}
static int
dos_rawgetc ()
{
struct input_event event;
union REGS regs;
#ifndef HAVE_X_WINDOWS
IT_cmgoto (SELECTED_FRAME());
#endif
while ((regs.h.ah = extended_kbd ? 0x11 : 0x01),
int86 (0x16, ®s, ®s),
(regs.x.flags & 0x40) == 0)
{
union REGS regs;
register unsigned char c;
int sc, code = -1, mask, kp_mode;
int modifiers;
regs.h.ah = extended_kbd ? 0x10 : 0x00;
int86 (0x16, ®s, ®s);
c = regs.h.al;
sc = regs.h.ah;
total_doskeys += 2;
XVECTOR (recent_doskeys)->contents[recent_doskeys_index++]
= make_number (c);
if (recent_doskeys_index == NUM_RECENT_DOSKEYS)
recent_doskeys_index = 0;
XVECTOR (recent_doskeys)->contents[recent_doskeys_index++]
= make_number (sc);
if (recent_doskeys_index == NUM_RECENT_DOSKEYS)
recent_doskeys_index = 0;
modifiers = dos_get_modifiers (&mask);
#ifndef HAVE_X_WINDOWS
if (!NILP (Vdos_display_scancodes))
{
char buf[11];
sprintf (buf, "%02x:%02x*%04x",
(unsigned) (sc&0xff), (unsigned) c, mask);
dos_direct_output (screen_size_Y - 2, screen_size_X - 12, buf, 10);
}
#endif
if (sc == 0xe0)
{
switch (c)
{
case 10:
code = Ctrl | Grey | 4;
break;
case 13:
code = Grey | 4;
break;
case '/':
code = Grey | 0;
break;
default:
continue;
};
c = 0;
}
else
{
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 (code == -1)
{
if (sc >= (sizeof (ibmpc_translate_map) / sizeof (short)))
continue;
if ((code = ibmpc_translate_map[sc]) == Ignore)
continue;
}
}
if (c == 0)
{
if ( (code & Alt)
|| ( (code & 0xf000) == Map && !international_keyboard))
modifiers |= meta_modifier;
if (code & Ctrl)
modifiers |= ctrl_modifier;
if (code & Shift)
modifiers |= shift_modifier;
}
switch (code & 0xf000)
{
case ModFct:
if (c && !(mask & (SHIFT_P | ALT_P | CTRL_P | HYPER_P | SUPER_P)))
return c;
c = 0;
case FctKey:
if (c != 0)
return c;
case Special:
code |= 0xff00;
break;
case Normal:
if (sc == 0)
{
if (c == 0)
continue;
return c;
}
if (!keyboard_map_all)
{
if (c != ' ')
return c;
code = c;
break;
}
case Map:
if (c && !(mask & ALT_P) && !((mask & SHIFT_P) && (mask & CTRL_P)))
if (!keyboard_map_all)
return c;
code &= 0xff;
if (mask & ALT_P && code <= 10 && code > 0 && dos_keypad_mode & 0x200)
mask |= SHIFT_P;
if (mask & SHIFT_P)
{
code = keyboard->shifted[code];
mask -= SHIFT_P;
modifiers &= ~shift_modifier;
}
else
if ((mask & ALT_GR_P) && keyboard->alt_gr && keyboard->alt_gr[code] != ' ')
code = keyboard->alt_gr[code];
else
code = keyboard->unshifted[code];
break;
case KeyPad:
code &= 0xff;
if (c == 0xe0)
kp_mode = 3;
else
if ((mask & (NUMLOCK_P|CTRL_P|SHIFT_P|ALT_P)) == NUMLOCK_P)
kp_mode = dos_keypad_mode & 0x03;
else
kp_mode = (dos_keypad_mode >> 4) & 0x03;
switch (kp_mode)
{
case 0:
if (code == 10 && dos_decimal_point)
return dos_decimal_point;
return keypad_translate_map[code].char_code;
case 1:
code = 0xff00 | keypad_translate_map[code].keypad_code;
break;
case 2:
code = keypad_translate_map[code].meta_code;
modifiers = meta_modifier;
break;
case 3:
code = 0xff00 | keypad_translate_map[code].editkey_code;
break;
}
break;
case Grey:
code &= 0xff;
kp_mode = ((mask & (NUMLOCK_P|CTRL_P|SHIFT_P|ALT_P)) == NUMLOCK_P) ? 0x04 : 0x40;
if (dos_keypad_mode & kp_mode)
code = 0xff00 | grey_key_translate_map[code].keypad_code;
else
code = grey_key_translate_map[code].char_code;
break;
}
make_event:
if (code == 0)
continue;
if (code >= 0x100)
event.kind = non_ascii_keystroke;
else
event.kind = ascii_keystroke;
event.code = code;
event.modifiers = modifiers;
event.frame_or_window = selected_frame;
event.arg = Qnil;
event.timestamp = event_timestamp ();
kbd_buffer_store_event (&event);
}
if (have_mouse > 0 && !mouse_preempted)
{
int but, press, x, y, ok;
int mouse_prev_x = mouse_last_x, mouse_prev_y = mouse_last_y;
mouse_check_moved ();
if (mouse_last_x != mouse_prev_x || mouse_last_y != mouse_prev_y)
{
previous_help_echo = help_echo;
help_echo = help_echo_object = help_echo_window = Qnil;
help_echo_pos = -1;
IT_note_mouse_highlight (SELECTED_FRAME(),
mouse_last_x, mouse_last_y);
if (!NILP (help_echo) || !NILP (previous_help_echo))
{
event.kind = HELP_EVENT;
event.frame_or_window = selected_frame;
event.arg = help_echo_object;
event.x = make_number (help_echo_pos);
event.timestamp = event_timestamp ();
event.code = 0;
kbd_buffer_store_event (&event);
if (WINDOWP (help_echo_window))
event.frame_or_window = help_echo_window;
event.arg = help_echo;
event.code = 1;
kbd_buffer_store_event (&event);
}
}
for (but = 0; but < NUM_MOUSE_BUTTONS; but++)
for (press = 0; press < 2; press++)
{
int button_num = but;
if (press)
ok = mouse_pressed (but, &x, &y);
else
ok = mouse_released (but, &x, &y);
if (ok)
{
if (mouse_button_count == 2 && but < 2)
{
int x2, y2;
if (press && mouse_pressed (1-but, &x2, &y2)
|| !press && mouse_released (1-but, &x2, &y2))
button_num = 2;
else
{
delay (100);
if (press && mouse_pressed (1-but, &x2, &y2)
|| !press && mouse_released (1-but, &x2, &y2))
button_num = 2;
}
}
event.kind = mouse_click;
event.code = button_num;
event.modifiers = dos_get_modifiers (0)
| (press ? down_modifier : up_modifier);
event.x = x;
event.y = y;
event.frame_or_window = selected_frame;
event.arg = Qnil;
event.timestamp = event_timestamp ();
kbd_buffer_store_event (&event);
}
}
}
return -1;
}
static int prev_get_char = -1;
dos_keysns ()
{
if (prev_get_char != -1)
return 1;
else
return ((prev_get_char = dos_rawgetc ()) != -1);
}
dos_keyread ()
{
if (prev_get_char != -1)
{
int c = prev_get_char;
prev_get_char = -1;
return c;
}
else
return dos_rawgetc ();
}
#ifndef HAVE_X_WINDOWS
void
pixel_to_glyph_coords (f, pix_x, pix_y, x, y, bounds, noclip)
FRAME_PTR f;
register int pix_x, pix_y;
register int *x, *y;
XRectangle *bounds;
int noclip;
{
if (bounds) abort ();
*x = pix_x;
*y = pix_y;
}
void
glyph_to_pixel_coords (f, x, y, pix_x, pix_y)
FRAME_PTR f;
register int x, y;
register int *pix_x, *pix_y;
{
*pix_x = x;
*pix_y = y;
}
static char *menu_help_message, *prev_menu_help_message;
static int menu_help_paneno, menu_help_itemno;
static XMenu *
IT_menu_create ()
{
XMenu *menu;
menu = (XMenu *) xmalloc (sizeof (XMenu));
menu->allocated = menu->count = menu->panecount = menu->width = 0;
return menu;
}
static void
IT_menu_make_room (XMenu *menu)
{
if (menu->allocated == 0)
{
int count = menu->allocated = 10;
menu->text = (char **) xmalloc (count * sizeof (char *));
menu->submenu = (XMenu **) xmalloc (count * sizeof (XMenu *));
menu->panenumber = (int *) xmalloc (count * sizeof (int));
menu->help_text = (char **) xmalloc (count * sizeof (char *));
}
else if (menu->allocated == menu->count)
{
int count = menu->allocated = menu->allocated + 10;
menu->text
= (char **) xrealloc (menu->text, count * sizeof (char *));
menu->submenu
= (XMenu **) xrealloc (menu->submenu, count * sizeof (XMenu *));
menu->panenumber
= (int *) xrealloc (menu->panenumber, count * sizeof (int));
menu->help_text
= (char **) xrealloc (menu->help_text, count * sizeof (char *));
}
}
static XMenu *
IT_menu_search_pane (XMenu *menu, int pane)
{
int i;
XMenu *try;
for (i = 0; i < menu->count; i++)
if (menu->submenu[i])
{
if (pane == menu->panenumber[i])
return menu->submenu[i];
if ((try = IT_menu_search_pane (menu->submenu[i], pane)))
return try;
}
return (XMenu *) 0;
}
static void
IT_menu_calc_size (XMenu *menu, int *width, int *height)
{
int i, h2, w2, maxsubwidth, maxheight;
maxsubwidth = 0;
maxheight = menu->count;
for (i = 0; i < menu->count; i++)
{
if (menu->submenu[i])
{
IT_menu_calc_size (menu->submenu[i], &w2, &h2);
if (w2 > maxsubwidth) maxsubwidth = w2;
if (i + h2 > maxheight) maxheight = i + h2;
}
}
*width = menu->width + maxsubwidth;
*height = maxheight;
}
static void
IT_menu_display (XMenu *menu, int y, int x, int pn, int *faces, int disp_help)
{
int i, j, face, width;
struct glyph *text, *p;
char *q;
int mx, my;
int enabled, mousehere;
int row, col;
struct frame *sf = SELECTED_FRAME();
menu_help_message = NULL;
width = menu->width;
text = (struct glyph *) xmalloc ((width + 2) * sizeof (struct glyph));
ScreenGetCursor (&row, &col);
mouse_get_xy (&mx, &my);
IT_update_begin (sf);
for (i = 0; i < menu->count; i++)
{
int max_width = width + 2;
IT_cursor_to (y + i, x);
enabled
= (!menu->submenu[i] && menu->panenumber[i]) || (menu->submenu[i]);
mousehere = (y + i == my && x <= mx && mx < x + width + 2);
face = faces[enabled + mousehere * 2];
if (disp_help && enabled + mousehere * 2 >= 2)
{
menu_help_message = menu->help_text[i];
menu_help_paneno = pn - 1;
menu_help_itemno = i;
}
p = text;
SET_CHAR_GLYPH (*p, ' ', face, 0);
p++;
for (j = 0, q = menu->text[i]; *q; j++)
{
if (*q > 26)
{
SET_CHAR_GLYPH (*p, *q++, face, 0);
p++;
}
else
{
SET_CHAR_GLYPH (*p, '^', face, 0);
p++;
j++;
SET_CHAR_GLYPH (*p, *q++ + 64, face, 0);
p++;
}
}
if (x + max_width > screen_size_X)
{
max_width = screen_size_X - x;
text[max_width - 1].u.ch = '$';
}
for (; j < max_width - 2; j++, p++)
SET_CHAR_GLYPH (*p, ' ', face, 0);
SET_CHAR_GLYPH (*p, menu->submenu[i] ? 16 : ' ', face, 0);
p++;
IT_write_glyphs (text, max_width);
}
IT_update_end (sf);
IT_cursor_to (row, col);
xfree (text);
}
int
have_menus_p ()
{
return 1;
}
XMenu *
XMenuCreate (Display *foo1, Window foo2, char *foo3)
{
return IT_menu_create ();
}
int
XMenuAddPane (Display *foo, XMenu *menu, char *txt, int enable)
{
int len;
char *p;
if (!enable)
abort ();
IT_menu_make_room (menu);
menu->submenu[menu->count] = IT_menu_create ();
menu->text[menu->count] = txt;
menu->panenumber[menu->count] = ++menu->panecount;
menu->help_text[menu->count] = NULL;
menu->count++;
for (len = strlen (txt), p = txt; *p; p++)
if (*p < 27)
len++;
if (len > menu->width)
menu->width = len;
return menu->panecount;
}
int
XMenuAddSelection (Display *bar, XMenu *menu, int pane,
int foo, char *txt, int enable, char *help_text)
{
int len;
char *p;
if (pane)
if (!(menu = IT_menu_search_pane (menu, pane)))
return XM_FAILURE;
IT_menu_make_room (menu);
menu->submenu[menu->count] = (XMenu *) 0;
menu->text[menu->count] = txt;
menu->panenumber[menu->count] = enable;
menu->help_text[menu->count] = help_text;
menu->count++;
for (len = strlen (txt), p = txt; *p; p++)
if (*p < 27)
len++;
if (len > menu->width)
menu->width = len;
return XM_SUCCESS;
}
void
XMenuLocate (Display *foo0, XMenu *menu, int foo1, int foo2, int x, int y,
int *ulx, int *uly, int *width, int *height)
{
IT_menu_calc_size (menu, width, height);
*ulx = x + 1;
*uly = y;
*width += 2;
}
struct IT_menu_state
{
void *screen_behind;
XMenu *menu;
int pane;
int x, y;
};
int
XMenuActivate (Display *foo, XMenu *menu, int *pane, int *selidx,
int x0, int y0, unsigned ButtonMask, char **txt,
void (*help_callback)(char *, int, int))
{
struct IT_menu_state *state;
int statecount;
int x, y, i, b;
int screensize;
int faces[4];
Lisp_Object selectface;
int leave, result, onepane;
int title_faces[4];
int buffers_num_deleted = 0;
struct frame *sf = SELECTED_FRAME();
Lisp_Object saved_echo_area_message;
if (have_mouse <= 0)
return XM_IA_SELECT;
if (x0 <= 0)
x0 = 1;
if (y0 <= 0)
y0 = 1;
mouse_preempted++;
state = alloca (menu->panecount * sizeof (struct IT_menu_state));
screensize = screen_size * 2;
faces[0]
= lookup_derived_face (sf, intern ("msdos-menu-passive-face"),
0, DEFAULT_FACE_ID);
faces[1]
= lookup_derived_face (sf, intern ("msdos-menu-active-face"),
0, DEFAULT_FACE_ID);
selectface = intern ("msdos-menu-select-face");
faces[2] = lookup_derived_face (sf, selectface,
0, faces[0]);
faces[3] = lookup_derived_face (sf, selectface,
0, faces[1]);
for (i = 0; i < 4; i++)
title_faces[i] = faces[3];
statecount = 1;
if (strncmp (menu->text[0], "Buffers 1", 9) == 0)
{
menu->text[0][7] = '\0';
buffers_num_deleted = 1;
}
saved_echo_area_message = Fcurrent_message ();
state[0].menu = menu;
mouse_off ();
ScreenRetrieve (state[0].screen_behind = xmalloc (screensize));
IT_display_cursor (0);
IT_menu_display (menu, y0 - 1, x0 - 1, 1, title_faces, 0);
if (buffers_num_deleted)
menu->text[0][7] = ' ';
if ((onepane = menu->count == 1 && menu->submenu[0]))
{
menu->width = menu->submenu[0]->width;
state[0].menu = menu->submenu[0];
}
else
{
state[0].menu = menu;
}
state[0].x = x0 - 1;
state[0].y = y0;
state[0].pane = onepane;
mouse_last_x = -1;
leave = 0;
while (!leave)
{
if (!mouse_visible) mouse_on ();
mouse_check_moved ();
if (sf->mouse_moved)
{
sf->mouse_moved = 0;
result = XM_IA_SELECT;
mouse_get_xy (&x, &y);
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;
if (0 <= dy && dy < state[i].menu->count)
{
if (!state[i].menu->submenu[dy])
if (state[i].menu->panenumber[dy])
result = XM_SUCCESS;
else
result = XM_IA_SELECT;
*pane = state[i].pane - 1;
*selidx = dy;
if (i != statecount - 2
|| state[i].menu->submenu[dy] != state[i+1].menu)
while (i != statecount - 1)
{
statecount--;
mouse_off ();
ScreenUpdate (state[statecount].screen_behind);
if (screen_virtual_segment)
dosv_refresh_virtual_screen (0, screen_size);
xfree (state[statecount].screen_behind);
}
if (i == statecount - 1 && state[i].menu->submenu[dy])
{
IT_menu_display (state[i].menu,
state[i].y,
state[i].x,
state[i].pane,
faces, 1);
state[statecount].menu = state[i].menu->submenu[dy];
state[statecount].pane = state[i].menu->panenumber[dy];
mouse_off ();
ScreenRetrieve (state[statecount].screen_behind
= xmalloc (screensize));
state[statecount].x
= state[i].x + state[i].menu->width + 2;
state[statecount].y = y;
statecount++;
}
}
}
IT_menu_display (state[statecount - 1].menu,
state[statecount - 1].y,
state[statecount - 1].x,
state[statecount - 1].pane,
faces, 1);
}
else
{
if ((menu_help_message || prev_menu_help_message)
&& menu_help_message != prev_menu_help_message)
{
help_callback (menu_help_message,
menu_help_paneno, menu_help_itemno);
IT_display_cursor (0);
prev_menu_help_message = menu_help_message;
}
__dpmi_yield ();
}
for (b = 0; b < mouse_button_count && !leave; b++)
{
if (mouse_pressed (b, &x, &y))
{
while (mouse_button_depressed (b, &x, &y))
__dpmi_yield ();
leave = 1;
}
(void) mouse_released (b, &x, &y);
}
}
mouse_off ();
ScreenUpdate (state[0].screen_behind);
if (screen_virtual_segment)
dosv_refresh_virtual_screen (0, screen_size);
if (! NILP (saved_echo_area_message))
message_with_string ("%s", saved_echo_area_message, 0);
message (0);
while (statecount--)
xfree (state[statecount].screen_behind);
IT_display_cursor (1);
discard_mouse_events ();
mouse_clear_clicks ();
if (!kbd_buffer_events_waiting (1))
clear_input_pending ();
mouse_preempted--;
return result;
}
void
XMenuDestroy (Display *foo, XMenu *menu)
{
int i;
if (menu->allocated)
{
for (i = 0; i < menu->count; i++)
if (menu->submenu[i])
XMenuDestroy (foo, menu->submenu[i]);
xfree (menu->text);
xfree (menu->submenu);
xfree (menu->panenumber);
xfree (menu->help_text);
}
xfree (menu);
menu_help_message = prev_menu_help_message = NULL;
}
int
x_pixel_width (struct frame *f)
{
return FRAME_WIDTH (f);
}
int
x_pixel_height (struct frame *f)
{
return FRAME_HEIGHT (f);
}
#endif
void msdos_downcase_filename (unsigned char *);
void
dostounix_filename (p)
register char *p;
{
msdos_downcase_filename (p);
while (*p)
{
if (*p == '\\')
*p = '/';
p++;
}
}
void
unixtodos_filename (p)
register char *p;
{
if (p[1] == ':' && *p >= 'A' && *p <= 'Z')
{
*p += 'a' - 'A';
p += 2;
}
while (*p)
{
if (*p == '/')
*p = '\\';
p++;
}
}
int
getdefdir (drive, dst)
int drive;
char *dst;
{
char in_path[4], *p = in_path;
int e = errno;
if (drive != 0)
{
*p++ = drive + 'A' - 1;
*p++ = ':';
}
*p++ = '.';
*p = '\0';
errno = 0;
_fixpath (in_path, dst);
if ((errno && errno != ENOSYS) || *dst == '\0')
return 0;
msdos_downcase_filename (dst);
errno = e;
return 1;
}
int
crlf_to_lf (n, buf)
register int n;
register unsigned char *buf;
{
unsigned char *np = buf;
unsigned char *startp = buf;
unsigned char *endp = buf + n;
if (n == 0)
return n;
while (buf < endp - 1)
{
if (*buf == 0x0d)
{
if (*(++buf) != 0x0a)
*np++ = 0x0d;
}
else
*np++ = *buf++;
}
if (buf < endp)
*np++ = *buf++;
return np - startp;
}
#if defined(__DJGPP__) && __DJGPP__ == 2 && __DJGPP_MINOR__ == 0
#include <io.h>
#include <libc/dosio.h>
static char xbuf[64 * 1024];
#define XBUF_END (xbuf + sizeof (xbuf) - 1)
int
__write (int handle, const void *buffer, size_t count)
{
if (count == 0)
return 0;
if(__file_handle_modes[handle] & O_BINARY)
return _write (handle, buffer, count);
else
{
char *xbp = xbuf;
const char *bp = buffer;
int total_written = 0;
int nmoved = 0, ncr = 0;
while (count)
{
if (xbp < XBUF_END)
{
if (*bp == '\n')
{
ncr++;
*xbp++ = '\r';
}
*xbp++ = *bp++;
nmoved++;
count--;
}
if (xbp >= XBUF_END || !count)
{
size_t to_write = nmoved + ncr;
int written = _write (handle, xbuf, to_write);
if (written == -1)
return -1;
else
total_written += nmoved;
if (written < to_write)
return total_written - (to_write - written) * nmoved/to_write;
nmoved = 0;
ncr = 0;
xbp = xbuf;
}
}
return total_written;
}
}
#include <io.h>
int _rename(const char *old, const char *new)
{
__dpmi_regs r;
int olen = strlen(old) + 1;
int i;
int use_lfn = _USE_LFN;
char tempfile[FILENAME_MAX];
const char *orig = old;
int lfn_fd = -1;
r.x.dx = __tb_offset;
r.x.di = __tb_offset + olen;
r.x.ds = r.x.es = __tb_segment;
if (use_lfn)
{
char *pbase = 0, *p;
static char try_char[] = "abcdefghijklmnopqrstuvwxyz012345789";
int idx = sizeof(try_char) - 1;
strcpy(tempfile, old);
for (p = tempfile; *p; p++)
if (*p == '/' || *p == '\\' || *p == ':')
pbase = p;
if (pbase)
pbase++;
else
pbase = tempfile;
strcpy(pbase, "X$$djren$$.$$temp$$");
do
{
if (idx <= 0)
return -1;
*pbase = try_char[--idx];
} while (_chmod(tempfile, 0) != -1);
r.x.ax = 0x7156;
_put_path2(tempfile, olen);
_put_path(old);
__dpmi_int(0x21, &r);
if (r.x.flags & 1)
{
errno = __doserr_to_errno(r.x.ax);
return -1;
}
lfn_fd = _creat(old, 0);
olen = strlen(tempfile) + 1;
old = tempfile;
r.x.di = __tb_offset + olen;
}
for (i=0; i<2; i++)
{
if(use_lfn)
r.x.ax = 0x7156;
else
r.h.ah = 0x56;
_put_path2(new, olen);
_put_path(old);
__dpmi_int(0x21, &r);
if(r.x.flags & 1)
{
if (r.x.ax == 5 && i == 0)
remove(new);
else
{
errno = __doserr_to_errno(r.x.ax);
if (use_lfn)
{
if (lfn_fd != -1)
{
_close (lfn_fd);
remove (orig);
}
_put_path2(orig, olen);
_put_path(tempfile);
r.x.ax = 0x7156;
__dpmi_int(0x21, &r);
}
return -1;
}
}
else
break;
}
if (lfn_fd != -1)
return (_close (lfn_fd) == 0) ? remove (orig) : -1;
return 0;
}
#endif
DEFUN ("msdos-long-file-names", Fmsdos_long_file_names, Smsdos_long_file_names,
0, 0, 0,
"Return non-nil if long file names are supported on MSDOS.")
()
{
return (_USE_LFN ? Qt : Qnil);
}
void
msdos_downcase_filename (p)
register unsigned char *p;
{
if (p[1] == ':' && *p >= 'A' && *p <= 'Z')
{
*p += 'a' - 'A';
p += 2;
}
if (NILP (Fmsdos_long_file_names ()))
for ( ; *p; p++)
if (*p >= 'A' && *p <= 'Z')
*p += 'a' - 'A';
}
DEFUN ("msdos-downcase-filename", Fmsdos_downcase_filename, Smsdos_downcase_filename,
1, 1, 0,
"Convert alphabetic characters in FILENAME to lower case and return that.\n\
When long filenames are supported, doesn't change FILENAME.\n\
If FILENAME is not a string, returns nil.\n\
The argument object is never altered--the value is a copy.")
(filename)
Lisp_Object filename;
{
Lisp_Object tem;
if (! STRINGP (filename))
return Qnil;
tem = Fcopy_sequence (filename);
msdos_downcase_filename (XSTRING (tem)->data);
return tem;
}
static char emacsroot[MAXPATHLEN];
char *
rootrelativepath (rel)
char *rel;
{
static char result[MAXPATHLEN + 10];
strcpy (result, emacsroot);
strcat (result, "/");
strcat (result, rel);
return result;
}
void
init_environment (argc, argv, skip_args)
int argc;
char **argv;
int skip_args;
{
char *s, *t, *root;
int len;
static const char * const tempdirs[] = {
"$TMPDIR", "$TEMP", "$TMP", "c:/"
};
int i;
const int imax = sizeof (tempdirs) / sizeof (tempdirs[0]);
for (i = 0; i < imax ; i++)
{
const char *tmp = tempdirs[i];
if (*tmp == '$')
tmp = getenv (tmp + 1);
if (tmp && access (tmp, D_OK) == 0)
{
setenv ("TMPDIR", tmp, 1);
break;
}
}
if (i >= imax)
cmd_error_internal
(Fcons (Qerror,
Fcons (build_string ("no usable temporary directories found!!"),
Qnil)),
"While setting TMPDIR: ");
startup_time = clock ();
root = alloca (MAXPATHLEN + 20);
_fixpath (argv[0], root);
msdos_downcase_filename (root);
len = strlen (root);
while (len > 0 && root[len] != '/' && root[len] != ':')
len--;
root[len] = '\0';
if (len > 4
&& (strcmp (root + len - 4, "/bin") == 0
|| strcmp (root + len - 4, "/src") == 0))
root[len - 4] = '\0';
else
strcpy (root, "c:/emacs");
len = strlen (root);
strcpy (emacsroot, root);
setenv ("HOME", root, 0);
strcpy (root + len, "/bin");
setenv ("EMACSPATH", root, 0);
setenv ("TERM", "internal", 0);
#ifdef HAVE_X_WINDOWS
setenv ("DISPLAY", "unix:0.0", 0);
#endif
s = getenv ("COMSPEC");
if (!s) s = "c:/command.com";
t = alloca (strlen (s) + 1);
strcpy (t, s);
dostounix_filename (t);
setenv ("SHELL", t, 0);
s = getenv ("PATH");
if (!s) s = "";
t = alloca (strlen (s) + 3);
strcat (strcpy (t, ".;"), s);
dostounix_filename (t);
setenv ("PATH", t, 1);
setenv ("USER", "root", 0);
setenv ("NAME", getenv ("USER"), 0);
if (!getenv ("TZ"))
switch (dos_country_code)
{
case 31:
case 32:
case 33:
case 34:
case 36:
case 38:
case 39:
case 41:
case 42:
case 45:
case 46:
case 47:
case 48:
case 49:
setenv ("TZ", "MET-01METDST-02,M3.5.0/02:00,M9.5.0/02:00", 0);
break;
case 44:
case 351:
case 354:
setenv ("TZ", "GMT+00", 0);
break;
case 81:
case 82:
setenv ("TZ", "JST-09", 0);
break;
case 90:
case 358:
setenv ("TZ", "EET-02", 0);
break;
case 972:
setenv ("TZ", "IST-02IDT-03,M4.1.6/00:00,M9.5.6/01:00", 0);
break;
}
tzset ();
}
static int break_stat;
static int stdin_stat;
#if __DJGPP__ < 2
static _go32_dpmi_seginfo ctrl_break_vector;
static _go32_dpmi_registers ctrl_break_regs;
static int ctrlbreakinstalled = 0;
void
ctrl_break_func (regs)
_go32_dpmi_registers *regs;
{
Vquit_flag = Qt;
}
void
install_ctrl_break_check ()
{
if (!ctrlbreakinstalled)
{
ctrlbreakinstalled = 1;
ctrl_break_vector.pm_offset = (int) ctrl_break_func;
_go32_dpmi_allocate_real_mode_callback_iret (&ctrl_break_vector,
&ctrl_break_regs);
_go32_dpmi_set_real_mode_interrupt_vector (0x1b, &ctrl_break_vector);
}
}
#endif
int
dos_ttraw ()
{
union REGS inregs, outregs;
static int first_time = 1;
break_stat = getcbrk ();
setcbrk (0);
#if __DJGPP__ < 2
install_ctrl_break_check ();
#endif
if (first_time)
{
inregs.h.ah = 0xc0;
int86 (0x15, &inregs, &outregs);
extended_kbd = (!outregs.x.cflag) && (outregs.h.ah == 0);
have_mouse = 0;
if (internal_terminal
#ifdef HAVE_X_WINDOWS
&& inhibit_window_system
#endif
)
{
inregs.x.ax = 0x0021;
int86 (0x33, &inregs, &outregs);
have_mouse = (outregs.x.ax & 0xffff) == 0xffff;
if (!have_mouse)
{
inregs.x.ax = 0x0000;
int86 (0x33, &inregs, &outregs);
have_mouse = (outregs.x.ax & 0xffff) == 0xffff;
}
if (have_mouse)
{
have_mouse = 1;
mouse_visible = 0;
mouse_setup_buttons (outregs.x.bx);
mouse_position_hook = &mouse_get_pos;
mouse_init ();
}
#ifndef HAVE_X_WINDOWS
#if __DJGPP__ >= 2
outside_cursor = _farpeekw (_dos_ds, 0x460);
#endif
#endif
}
first_time = 0;
#if __DJGPP__ >= 2
stdin_stat = setmode (fileno (stdin), O_BINARY);
return (stdin_stat != -1);
}
else
return (setmode (fileno (stdin), O_BINARY) != -1);
#else
}
inregs.x.ax = 0x4400;
inregs.x.bx = 0x00;
intdos (&inregs, &outregs);
stdin_stat = outregs.h.dl;
inregs.x.dx = stdin_stat | 0x0020;
inregs.x.ax = 0x4401;
intdos (&inregs, &outregs);
return !outregs.x.cflag;
#endif
}
int
dos_ttcooked ()
{
union REGS inregs, outregs;
setcbrk (break_stat);
mouse_off ();
#if __DJGPP__ >= 2
#ifndef HAVE_X_WINDOWS
if (outside_cursor)
{
inregs.h.ah = 1;
inregs.x.cx = outside_cursor;
int86 (0x10, &inregs, &outregs);
}
#endif
return (setmode (fileno (stdin), stdin_stat) != -1);
#else
inregs.x.ax = 0x4401;
inregs.x.bx = 0x00;
inregs.x.dx = stdin_stat;
intdos (&inregs, &outregs);
return !outregs.x.cflag;
#endif
}
int
run_msdos_command (argv, working_dir, tempin, tempout, temperr, envv)
unsigned char **argv;
const char *working_dir;
int tempin, tempout, temperr;
char **envv;
{
char *saveargv1, *saveargv2, *lowcase_argv0, *pa, *pl;
char oldwd[MAXPATHLEN + 1];
int msshell, result = -1;
int inbak, outbak, errbak;
int x, y;
Lisp_Object cmd;
getwd (oldwd);
lowcase_argv0 = alloca (strlen (argv[0]) + 1);
for (pa = argv[0], pl = lowcase_argv0; *pa; pl++)
{
*pl = *pa++;
if (*pl >= 'A' && *pl <= 'Z')
*pl += 'a' - 'A';
}
*pl = '\0';
cmd = Ffile_name_nondirectory (build_string (lowcase_argv0));
msshell = !NILP (Fmember (cmd, Fsymbol_value (intern ("msdos-shells"))))
&& !strcmp ("-c", argv[1]);
if (msshell)
{
saveargv1 = argv[1];
saveargv2 = argv[2];
argv[1] = "/c";
if (argv[2] && argv[3])
{
char *p = alloca (strlen (argv[2]) + 1);
strcpy (argv[2] = p, saveargv2);
while (*p && isspace (*p))
p++;
while (*p)
{
if (*p == '/')
*p++ = '\\';
else
p++;
}
}
}
chdir (working_dir);
inbak = dup (0);
outbak = dup (1);
errbak = dup (2);
if (inbak < 0 || outbak < 0 || errbak < 0)
goto done;
if (have_mouse > 0)
mouse_get_xy (&x, &y);
dos_ttcooked ();
dup2 (tempin, 0);
dup2 (tempout, 1);
dup2 (temperr, 2);
#if __DJGPP__ > 1
if (msshell && !argv[3])
{
const char *cmnd;
for (cmnd = saveargv2; *cmnd && isspace (*cmnd); cmnd++)
;
if (*cmnd)
{
extern char **environ;
char **save_env = environ;
int save_system_flags = __system_flags;
__system_flags = (__system_redirect
| __system_use_shell
| __system_allow_multiple_cmds
| __system_allow_long_cmds
| __system_handle_null_commands
| __system_emulate_chdir);
environ = envv;
result = system (cmnd);
__system_flags = save_system_flags;
environ = save_env;
}
else
result = 0;
}
else
#endif
result = spawnve (P_WAIT, argv[0], argv, envv);
dup2 (inbak, 0);
dup2 (outbak, 1);
dup2 (errbak, 2);
emacs_close (inbak);
emacs_close (outbak);
emacs_close (errbak);
dos_ttraw ();
if (have_mouse > 0)
{
mouse_init ();
mouse_moveto (x, y);
}
bright_bg ();
done:
chdir (oldwd);
if (msshell)
{
argv[1] = saveargv1;
argv[2] = saveargv2;
}
return result;
}
croak (badfunc)
char *badfunc;
{
fprintf (stderr, "%s not yet implemented\r\n", badfunc);
reset_sys_modes ();
exit (1);
}
#if __DJGPP__ < 2
gethostname (p, size)
char *p;
int size;
{
char *q = egetenv ("HOSTNAME");
if (!q) q = "pc";
strcpy (p, q);
return 0;
}
static struct tm time_rec;
int
gettimeofday (struct timeval *tp, struct timezone *tzp)
{
if (tp)
{
struct time t;
struct tm tm;
gettime (&t);
if (t.ti_hour < time_rec.tm_hour)
{
struct date d;
getdate (&d);
time_rec.tm_year = d.da_year - 1900;
time_rec.tm_mon = d.da_mon - 1;
time_rec.tm_mday = d.da_day;
}
time_rec.tm_hour = t.ti_hour;
time_rec.tm_min = t.ti_min;
time_rec.tm_sec = t.ti_sec;
tm = time_rec;
tm.tm_gmtoff = dos_timezone_offset;
tp->tv_sec = mktime (&tm);
tp->tv_usec = t.ti_hund * (1000000 / 100);
}
return 0;
}
#endif
#if __DJGPP__ < 2
unsigned alarm (s) unsigned s; {}
fork () { return 0; }
int kill (x, y) int x, y; { return -1; }
nice (p) int p; {}
void volatile pause () {}
sigsetmask (x) int x; { return 0; }
sigblock (mask) int mask; { return 0; }
#endif
void request_sigio (void) {}
setpgrp () {return 0; }
setpriority (x,y,z) int x,y,z; { return 0; }
void unrequest_sigio (void) {}
#if __DJGPP__ > 1
#ifdef POSIX_SIGNALS
#include <libc/bss.h>
static int sigprocmask_count = -1;
static sigset_t current_mask;
static sigset_t pending_signals;
typedef void (*sighandler_t)(int);
static sighandler_t prev_handlers[320];
static void
sig_suspender (signo)
int signo;
{
sigaddset (&pending_signals, signo);
}
int
sigprocmask (how, new_set, old_set)
int how;
const sigset_t *new_set;
sigset_t *old_set;
{
int signo;
sigset_t new_mask;
if (sigprocmask_count != __bss_count)
{
sigprocmask_count = __bss_count;
sigemptyset (&pending_signals);
sigemptyset (¤t_mask);
for (signo = 0; signo < 320; signo++)
prev_handlers[signo] = SIG_ERR;
}
if (old_set)
*old_set = current_mask;
if (new_set == 0)
return 0;
if (how != SIG_BLOCK && how != SIG_UNBLOCK && how != SIG_SETMASK)
{
errno = EINVAL;
return -1;
}
sigemptyset (&new_mask);
for (signo = 0; signo < 320; signo++)
{
if (sigismember (¤t_mask, signo))
sigaddset (&new_mask, signo);
else if (sigismember (new_set, signo) && how != SIG_UNBLOCK)
{
sigaddset (&new_mask, signo);
if (signo != SIGKILL && prev_handlers[signo] == SIG_ERR)
prev_handlers[signo] = signal (signo, sig_suspender);
}
if (( how == SIG_UNBLOCK
&& sigismember (&new_mask, signo)
&& sigismember (new_set, signo))
|| (how == SIG_SETMASK
&& sigismember (&new_mask, signo)
&& !sigismember (new_set, signo)))
{
sigdelset (&new_mask, signo);
if (prev_handlers[signo] != SIG_ERR)
{
signal (signo, prev_handlers[signo]);
prev_handlers[signo] = SIG_ERR;
}
if (sigismember (&pending_signals, signo))
{
sigdelset (&pending_signals, signo);
raise (signo);
}
}
}
current_mask = new_mask;
return 0;
}
#else
sigsetmask (x) int x; { return 0; }
sigblock (mask) int mask; { return 0; }
#endif
#endif
#ifndef HAVE_SELECT
#include "sysselect.h"
#ifndef EMACS_TIME_ZERO_OR_NEG_P
#define EMACS_TIME_ZERO_OR_NEG_P(time) \
((long)(time).tv_sec < 0 \
|| ((time).tv_sec == 0 \
&& (long)(time).tv_usec <= 0))
#endif
void
dos_yield_time_slice (void)
{
_go32_dpmi_registers r;
r.x.ax = 0x1680;
r.x.ss = r.x.sp = r.x.flags = 0;
_go32_dpmi_simulate_int (0x2f, &r);
if (r.h.al == 0x80)
errno = ENOSYS;
}
int
sys_select (nfds, rfds, wfds, efds, timeout)
int nfds;
SELECT_TYPE *rfds, *wfds, *efds;
EMACS_TIME *timeout;
{
int check_input;
struct time t;
check_input = 0;
if (rfds)
{
check_input = FD_ISSET (0, rfds);
FD_ZERO (rfds);
}
if (wfds)
FD_ZERO (wfds);
if (efds)
FD_ZERO (efds);
if (nfds != 1)
abort ();
if (!timeout)
{
while (!detect_input_pending ())
{
dos_yield_time_slice ();
}
}
else
{
EMACS_TIME clnow, cllast, cldiff;
gettime (&t);
EMACS_SET_SECS_USECS (cllast, t.ti_sec, t.ti_hund * 10000L);
while (!check_input || !detect_input_pending ())
{
gettime (&t);
EMACS_SET_SECS_USECS (clnow, t.ti_sec, t.ti_hund * 10000L);
EMACS_SUB_TIME (cldiff, clnow, cllast);
if (EMACS_TIME_NEG_P (cldiff))
EMACS_SET_SECS (cldiff, EMACS_SECS (cldiff) + 60);
EMACS_SUB_TIME (*timeout, *timeout, cldiff);
if (EMACS_TIME_ZERO_OR_NEG_P (*timeout))
return 0;
cllast = clnow;
dos_yield_time_slice ();
}
}
FD_SET (0, rfds);
return 1;
}
#endif
#ifdef chdir
#undef chdir
extern int chdir ();
int
sys_chdir (path)
const char* path;
{
int len = strlen (path);
char *tmp = (char *)path;
if (*tmp && tmp[1] == ':')
{
if (getdisk () != tolower (tmp[0]) - 'a')
setdisk (tolower (tmp[0]) - 'a');
tmp += 2;
len -= 2;
}
if (len > 1 && (tmp[len - 1] == '/'))
{
char *tmp1 = (char *) alloca (len + 1);
strcpy (tmp1, tmp);
tmp1[len - 1] = 0;
tmp = tmp1;
}
return chdir (tmp);
}
#endif
#ifdef tzset
#undef tzset
extern void tzset (void);
void
init_gettimeofday ()
{
time_t ltm, gtm;
struct tm *lstm;
tzset ();
ltm = gtm = time (NULL);
ltm = mktime (lstm = localtime (<m));
gtm = mktime (gmtime (>m));
time_rec.tm_hour = 99;
time_rec.tm_isdst = lstm->tm_isdst;
dos_timezone_offset = time_rec.tm_gmtoff = (int)(gtm - ltm) / 60;
}
#endif
#ifdef abort
#undef abort
void
dos_abort (file, line)
char *file;
int line;
{
char buffer1[200], buffer2[400];
int i, j;
sprintf (buffer1, "<EMACS FATAL ERROR IN %s LINE %d>", file, line);
for (i = j = 0; buffer1[i]; i++) {
buffer2[j++] = buffer1[i];
buffer2[j++] = 0x70;
}
dosmemput (buffer2, j, (int)ScreenPrimary);
ScreenSetCursor (2, 0);
abort ();
}
#else
void
abort ()
{
dos_ttcooked ();
ScreenSetCursor (10, 0);
cputs ("\r\n\nEmacs aborted!\r\n");
#if __DJGPP__ > 1
#if __DJGPP__ == 2 && __DJGPP_MINOR__ < 2
if (screen_virtual_segment)
dosv_refresh_virtual_screen (2 * 10 * screen_size_X, 4 * screen_size_X);
signal (SIGINT, SIG_DFL);
__asm__ __volatile__ ("movb $0x1b,%al;call ___djgpp_hw_exception");
#else
raise (SIGABRT);
#endif
#endif
exit (2);
}
#endif
#ifndef HAVE_X_WINDOWS
Lisp_Object Vx_bitmap_file_path;
int x_stretch_cursor_p;
#endif
#ifndef subprocesses
static int delete_exited_processes;
#endif
syms_of_msdos ()
{
recent_doskeys = Fmake_vector (make_number (NUM_RECENT_DOSKEYS), Qnil);
staticpro (&recent_doskeys);
#ifndef HAVE_X_WINDOWS
help_echo = Qnil;
staticpro (&help_echo);
help_echo_object = Qnil;
staticpro (&help_echo_object);
help_echo_window = Qnil;
staticpro (&help_echo_window);
previous_help_echo = Qnil;
staticpro (&previous_help_echo);
help_echo_pos = -1;
DEFVAR_LISP ("x-bitmap-file-path", &Vx_bitmap_file_path,
"List of directories to search for bitmap files for X.");
Vx_bitmap_file_path = decode_env_path ((char *) 0, ".");
DEFVAR_BOOL ("x-stretch-cursor", &x_stretch_cursor_p,
"*Non-nil means draw block cursor as wide as the glyph under it.\n\
For example, if a block cursor is over a tab, it will be drawn as\n\
wide as that tab on the display. (No effect on MS-DOS.)");
x_stretch_cursor_p = 0;
Qbar = intern ("bar");
staticpro (&Qbar);
Qcursor_type = intern ("cursor-type");
staticpro (&Qcursor_type);
Qreverse = intern ("reverse");
staticpro (&Qreverse);
DEFVAR_LISP ("dos-unsupported-char-glyph", &Vdos_unsupported_char_glyph,
"*Glyph to display instead of chars not supported by current codepage.\n\
\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,
"*Non-nil means delete processes immediately when they exit.\n\
nil means don't delete them until `list-processes' is run.");
delete_exited_processes = 0;
#endif
defsubr (&Srecent_doskeys);
defsubr (&Smsdos_long_file_names);
defsubr (&Smsdos_downcase_filename);
defsubr (&Smsdos_remember_default_colors);
defsubr (&Smsdos_set_mouse_buttons);
}
#endif