# HG changeset patch # User Jason Rumney # Date 948597362 0 # Node ID fe54558f20d883549e44a2cf6bb0d5f3a11a84d0 # Parent 06b36e62c2b8a398fe08c94aeb513165641d02c4 (turn_on_face, turn_off_face): New functions. (change_line_highlight): New prototype for new redisplay. (write_glyphs): Support multibyte text. Support faces. diff -r 06b36e62c2b8 -r fe54558f20d8 src/w32console.c --- a/src/w32console.c Sun Jan 23 03:14:51 2000 +0000 +++ b/src/w32console.c Sun Jan 23 03:16:02 2000 +0000 @@ -1,5 +1,5 @@ /* 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 @@ #include #include +/* 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 @@ /* 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_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 @@ /* 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 @@ 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 @@ 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 @@ 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 @@ } -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 @@ 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 @@ 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 @@ /* 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 @@ 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 @@ /* 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 @@ } 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 (); + + /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at + the tail. */ + terminal_coding.mode &= ~CODING_MODE_LAST_BLOCK; - chars = alloca (len * sizeof (*chars)); - if (chars == NULL) + while (len > 0) { - 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++; + /* 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); - 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)) + while (n > 0) { - *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)) - { - printf ("Failed writing console attributes: %d\n", GetLastError ()); - fflush (stdout); + /* 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 @@ 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 @@ { } +/*********************************************************************** + 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 @@ 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 @@ 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 @@ #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 @@ } 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;