Commit 8c2ac482 authored by Jason Rumney's avatar Jason Rumney
Browse files

(turn_on_face, turn_off_face): New functions.

(change_line_highlight): New prototype for new redisplay.
(write_glyphs): Support multibyte text. Support faces.
parent 2e7aef9d
/* Terminal hooks for GNU Emacs on the Microsoft W32 API.
Copyright (C) 1992 Free Software Foundation, Inc.
Copyright (C) 1992, 1999 Free Software Foundation, Inc.
This file is part of GNU Emacs.
......@@ -29,12 +29,18 @@ Boston, MA 02111-1307, USA.
#include <stdio.h>
#include <windows.h>
/* Disable features in headers that require a Window System for
console mode. */
#undef HAVE_WINDOW_SYSTEM
#include "lisp.h"
#include "charset.h"
#include "coding.h"
#include "frame.h"
#include "disptab.h"
#include "termhooks.h"
#include "w32inevt.h"
#include "dispextern.h"
/* from window.c */
extern Lisp_Object Frecenter ();
......@@ -45,7 +51,7 @@ extern int detect_input_pending ();
/* from sysdep.c */
extern int read_input_pending ();
extern FRAME_PTR updating_frame;
extern struct frame * updating_frame;
extern int meta_key;
static void move_cursor (int row, int col);
......@@ -53,18 +59,20 @@ static void clear_to_end (void);
static void clear_frame (void);
static void clear_end_of_line (int);
static void ins_del_lines (int vpos, int n);
static void change_line_highlight (int, int, int);
static void change_line_highlight (int, int, int, int);
static void reassert_line_highlight (int, int);
static void insert_glyphs (GLYPH *start, int len);
static void write_glyphs (GLYPH *string, int len);
static void insert_glyphs (struct glyph *start, int len);
static void write_glyphs (struct glyph *string, int len);
static void delete_glyphs (int n);
void w32_sys_ring_bell (void);
static void reset_terminal_modes (void);
static void set_terminal_modes (void);
static void set_terminal_window (int size);
static void update_begin (FRAME_PTR f);
static void update_end (FRAME_PTR f);
static void update_begin (struct frame * f);
static void update_end (struct frame * f);
static int hl_mode (int new_highlight);
static void turn_on_face P_ ((struct frame *, int face_id));
static void turn_off_face P_ ((struct frame *, int face_id));
COORD cursor_coords;
HANDLE prev_screen, cur_screen;
......@@ -97,7 +105,7 @@ ctrl_c_handler (unsigned long type)
/* If we're updating a frame, use it as the current frame
Otherwise, use the selected frame. */
#define PICK_FRAME() (updating_frame ? updating_frame : selected_frame)
#define PICK_FRAME() (updating_frame ? updating_frame : SELECTED_FRAME ())
/* Move the cursor to (row, col). */
void
......@@ -106,7 +114,7 @@ move_cursor (int row, int col)
cursor_coords.X = col;
cursor_coords.Y = row;
if (updating_frame == (FRAME_PTR) NULL)
if (updating_frame == (struct frame *) NULL)
{
SetConsoleCursorPosition (cur_screen, cursor_coords);
}
......@@ -116,7 +124,7 @@ move_cursor (int row, int col)
void
clear_to_end (void)
{
FRAME_PTR f = PICK_FRAME ();
struct frame * f = PICK_FRAME ();
clear_end_of_line (FRAME_WIDTH (f) - 1);
ins_del_lines (cursor_coords.Y, FRAME_HEIGHT (f) - cursor_coords.Y - 1);
......@@ -126,7 +134,7 @@ clear_to_end (void)
void
clear_frame (void)
{
FRAME_PTR f = PICK_FRAME ();
struct frame * f = PICK_FRAME ();
COORD dest;
int n, r;
CONSOLE_SCREEN_BUFFER_INFO info;
......@@ -146,7 +154,7 @@ clear_frame (void)
}
static GLYPH glyph_base[256];
static struct glyph glyph_base[256];
static BOOL ceol_initialized = FALSE;
/* Clear from Cursor to end (what's "standout marker"?). */
......@@ -158,7 +166,7 @@ clear_end_of_line (int end)
int i;
for (i = 0; i < 256; i++)
{
glyph_base[i] = SPACEGLYPH; /* empty space */
memcpy (&glyph_base[i], &space_glyph, sizeof (struct glyph));
}
ceol_initialized = TRUE;
}
......@@ -173,7 +181,7 @@ ins_del_lines (int vpos, int n)
SMALL_RECT scroll;
COORD dest;
CHAR_INFO fill;
FRAME_PTR f = PICK_FRAME ();
struct frame * f = PICK_FRAME ();
if (n < 0)
{
......@@ -260,7 +268,8 @@ hl_mode (int new_highlight)
/* Call this when about to modify line at position VPOS and change whether it
is highlighted. */
void
change_line_highlight (int new_highlight, int vpos, int first_unused_hpos)
change_line_highlight (int new_highlight, int vpos, int y,
int first_unused_hpos)
{
hl_mode (new_highlight);
move_cursor (vpos, 0);
......@@ -289,7 +298,7 @@ scroll_line (int dist, int direction)
SMALL_RECT scroll;
COORD dest;
CHAR_INFO fill;
FRAME_PTR f = PICK_FRAME ();
struct frame * f = PICK_FRAME ();
scroll.Top = cursor_coords.Y;
scroll.Bottom = cursor_coords.Y;
......@@ -317,7 +326,7 @@ scroll_line (int dist, int direction)
/* If start is zero insert blanks instead of a string at start ?. */
void
insert_glyphs (register GLYPH *start, register int len)
insert_glyphs (register struct glyph *start, register int len)
{
scroll_line (len, RIGHT);
......@@ -336,75 +345,98 @@ insert_glyphs (register GLYPH *start, register int len)
}
void
write_glyphs (register GLYPH *string, register int len)
write_glyphs (register struct glyph *string, register int len)
{
register unsigned int glyph_len = GLYPH_TABLE_LENGTH;
Lisp_Object *glyph_table = GLYPH_TABLE_BASE;
FRAME_PTR f = PICK_FRAME ();
register char *ptr;
GLYPH glyph;
char *chars;
int i;
if (len <= 0)
return;
int produced, consumed, i;
struct frame * f = PICK_FRAME ();
chars = alloca (len * sizeof (*chars));
if (chars == NULL)
{
printf ("alloca failed in write_glyphs\n");
return;
}
/* We have to deal with the glyph indirection...go over the glyph
buffer and extract the characters. */
ptr = chars;
while (--len >= 0)
{
glyph = *string++;
/* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at
the tail. */
terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK;
if (glyph > glyph_len)
{
*ptr++ = glyph & 0xFF;
continue;
}
GLYPH_FOLLOW_ALIASES (glyph_table, glyph_len, glyph);
#ifndef HAVE_NTGUI
if (GLYPH_FACE (fixfix, glyph) != 0)
printf ("Glyph face is %d\n", GLYPH_FACE (fixfix, glyph));
#endif /* !HAVE_NTGUI */
if (GLYPH_SIMPLE_P (glyph_table, glyph_len, glyph))
{
*ptr++ = glyph & 0xFF;
continue;
}
for (i = 0; i < GLYPH_LENGTH (glyph_table, glyph); i++)
{
*ptr++ = (GLYPH_STRING (glyph_table, glyph))[i];
}
}
/* Number of characters we have in the buffer. */
len = ptr-chars;
/* Set the attribute for these characters. */
if (!FillConsoleOutputAttribute (cur_screen, char_attr, len, cursor_coords, &i))
while (len > 0)
{
printf ("Failed writing console attributes: %d\n", GetLastError ());
fflush (stdout);
/* Identify a run of glyphs with the same face. */
int face_id = string->face_id;
int n;
for (n = 1; n < len; ++n)
if (string[n].face_id != face_id)
break;
/* Turn appearance modes of the face of the run on. */
turn_on_face (f, face_id);
while (n > 0)
{
/* We use a shared conversion buffer of the current size
(1024 bytes at least). Usually it is sufficient, but if
not, we just repeat the loop. */
produced = encode_terminal_code (string, conversion_buffer,
n, conversion_buffer_size,
&consumed);
if (produced > 0)
{
/* Set the attribute for these characters. */
if (!FillConsoleOutputAttribute (cur_screen, char_attr,
produced, cursor_coords, &i))
{
printf ("Failed writing console attributes: %d\n",
GetLastError ());
fflush (stdout);
}
/* Write the characters. */
if (!WriteConsoleOutputCharacter (cur_screen, conversion_buffer,
produced, cursor_coords, &i))
{
printf ("Failed writing console characters: %d\n",
GetLastError ());
fflush (stdout);
}
cursor_coords.X += produced;
move_cursor (cursor_coords.Y, cursor_coords.X);
}
len -= consumed;
n -= consumed;
string += consumed;
}
/* Turn appearance modes off. */
turn_off_face (f, face_id);
}
/* Write the characters. */
if (!WriteConsoleOutputCharacter (cur_screen, chars, len, cursor_coords, &i))
/* We may have to output some codes to terminate the writing. */
if (CODING_REQUIRE_FLUSHING (&terminal_coding))
{
printf ("Failed writing console characters: %d\n", GetLastError ());
fflush (stdout);
terminal_coding.mode |= CODING_MODE_LAST_BLOCK;
encode_coding (&terminal_coding, "", conversion_buffer,
0, conversion_buffer_size);
if (terminal_coding.produced > 0)
{
if (!FillConsoleOutputAttribute (cur_screen, char_attr,
terminal_coding.produced,
cursor_coords, &i))
{
printf ("Failed writing console attributes: %d\n",
GetLastError ());
fflush (stdout);
}
/* Write the characters. */
if (!WriteConsoleOutputCharacter (cur_screen, conversion_buffer,
produced, cursor_coords, &i))
{
printf ("Failed writing console characters: %d\n",
GetLastError ());
fflush (stdout);
}
}
}
cursor_coords.X += len;
move_cursor (cursor_coords.Y, cursor_coords.X);
}
void
delete_glyphs (int n)
{
......@@ -499,12 +531,12 @@ set_terminal_modes (void)
we'll start with not moving the cursor while an update is in progress. */
void
update_begin (FRAME_PTR f)
update_begin (struct frame * f)
{
}
void
update_end (FRAME_PTR f)
update_end (struct frame * f)
{
SetConsoleCursorPosition (cur_screen, cursor_coords);
}
......@@ -514,6 +546,50 @@ set_terminal_window (int size)
{
}
/***********************************************************************
Faces
***********************************************************************/
/* Turn appearances of face FACE_ID on tty frame F on. */
static void
turn_on_face (f, face_id)
struct frame *f;
int face_id;
{
struct face *face = FACE_FROM_ID (f, face_id);
xassert (face != NULL);
char_attr = char_attr_normal;
if (face->foreground != FACE_TTY_DEFAULT_COLOR)
char_attr = (char_attr & 0xf0) + face->foreground;
if (face->background != FACE_TTY_DEFAULT_COLOR)
char_attr = (face->background << 4) + char_attr & 0x0f;
if (face->tty_reverse_p)
char_attr = ((char_attr & 0x0f) << 4) + ((char_attr & 0xf0) >> 4);
/* Ensure readability */
if (((char_attr & 0xf0) >> 4) == (char_attr * 0x0f))
char_attr ^= 0x0f;
}
/* Turn off appearances of face FACE_ID on tty frame F. */
static void
turn_off_face (f, face_id)
struct frame *f;
int face_id;
{
if (hl_mode (0))
hl_mode (1);
}
typedef int (*term_hook) ();
void
......@@ -541,6 +617,7 @@ initialize_w32_display (void)
read_socket_hook = w32_console_read_socket;
mouse_position_hook = w32_console_mouse_position;
estimate_mode_line_height_hook = 0;
/* Initialize interrupt_handle. */
init_crit ();
......@@ -612,16 +689,16 @@ initialize_w32_display (void)
if (w32_use_full_screen_buffer)
{
FRAME_HEIGHT (selected_frame) = info.dwSize.Y; /* lines per page */
SET_FRAME_WIDTH (selected_frame, info.dwSize.X); /* characters per line */
FRAME_HEIGHT (SELECTED_FRAME ()) = info.dwSize.Y; /* lines per page */
SET_FRAME_WIDTH (SELECTED_FRAME (), info.dwSize.X); /* characters per line */
}
else
{
/* Lines per page. Use buffer coords instead of buffer size. */
FRAME_HEIGHT (selected_frame) = 1 + info.srWindow.Bottom -
FRAME_HEIGHT (SELECTED_FRAME ()) = 1 + info.srWindow.Bottom -
info.srWindow.Top;
/* Characters per line. Use buffer coords instead of buffer size. */
SET_FRAME_WIDTH (selected_frame, 1 + info.srWindow.Right -
SET_FRAME_WIDTH (SELECTED_FRAME (), 1 + info.srWindow.Right -
info.srWindow.Left);
}
}
......@@ -654,7 +731,7 @@ DEFUN ("set-cursor-size", Fset_cursor_size, Sset_cursor_size, 1, 1, 0,
#ifndef HAVE_NTGUI
void
pixel_to_glyph_coords (FRAME_PTR f, int pix_x, int pix_y, int *x, int *y,
pixel_to_glyph_coords (struct frame * f, int pix_x, int pix_y, int *x, int *y,
void *bounds, int noclip)
{
*x = pix_x;
......@@ -662,7 +739,7 @@ pixel_to_glyph_coords (FRAME_PTR f, int pix_x, int pix_y, int *x, int *y,
}
void
glyph_to_pixel_coords (FRAME_PTR f, int x, int y, int *pix_x, int *pix_y)
glyph_to_pixel_coords (struct frame * f, int x, int y, int *pix_x, int *pix_y)
{
*pix_x = x;
*pix_y = y;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment