From aff01dd96f651db009a0d318a14477ff1f91e1c8 Mon Sep 17 00:00:00 2001 From: Eli Zaretskii Date: Sat, 14 Feb 2009 10:50:29 +0000 Subject: [PATCH] (MAX_SCREEN_BUF): New macro. (IT_write_glyphs): Make screen_buf[] always be MAX_SCREEN_BUF-long. Encode the entire run of glyphs sharing the same face, instead of doing that one glyph at a time (fixes a bug with displaying double-size characters). --- src/ChangeLog | 8 ++++ src/msdos.c | 100 +++++++++++++++++++------------------------------- 2 files changed, 46 insertions(+), 62 deletions(-) diff --git a/src/ChangeLog b/src/ChangeLog index f9c24996500..fae28300ffc 100644 --- a/src/ChangeLog +++ b/src/ChangeLog @@ -1,3 +1,11 @@ +2009-02-14 Eli Zaretskii + + * msdos.c (MAX_SCREEN_BUF): New macro. + (IT_write_glyphs): Make screen_buf[] always be MAX_SCREEN_BUF-long. + Encode the entire run of glyphs sharing the same face, instead of + doing that one glyph at a time (fixes a bug with displaying + double-size characters). + 2009-02-13 Adrian Robert * nsfns.m (ns-read-file-name): BLOCK_INPUT while showing dialog. diff --git a/src/msdos.c b/src/msdos.c index e4e57646991..6397539574e 100644 --- a/src/msdos.c +++ b/src/msdos.c @@ -957,19 +957,20 @@ IT_set_face (int face) } } +/* According to RBIL (INTERRUP.A, V-1000), 160 is the maximum possible + width of a DOS display in any known text mode. We multiply by 2 to + accomodate the screen attribute byte. */ +#define MAX_SCREEN_BUF 160*2 + Lisp_Object Vdos_unsupported_char_glyph; extern unsigned char *encode_terminal_code (struct glyph *, int, struct coding_system *); static void IT_write_glyphs (struct frame *f, struct glyph *str, int str_len) { - unsigned char *screen_buf, *screen_bp, *screen_buf_end, *bp; - int unsupported_face = 0; - unsigned unsupported_char = '\177'; + unsigned char screen_buf[MAX_SCREEN_BUF], *screen_bp, *bp; 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 tty_display_info *tty = FRAME_TTY (f); struct frame *sf; unsigned char *conversion_buffer; @@ -990,8 +991,6 @@ IT_write_glyphs (struct frame *f, struct glyph *str, int str_len) if (str_len <= 0) return; - screen_buf = screen_bp = alloca (str_len * 2); - screen_buf_end = screen_buf + str_len * 2; sf = SELECTED_FRAME(); /* Since faces get cached and uncached behind our back, we can't @@ -1004,73 +1003,50 @@ IT_write_glyphs (struct frame *f, struct glyph *str, int str_len) /* The mode bit CODING_MODE_LAST_BLOCK should be set to 1 only at the tail. */ coding->mode &= ~CODING_MODE_LAST_BLOCK; + screen_bp = &screen_buf[0]; while (sl > 0) { int cf; + int n; - /* Glyphs with GLYPH_MASK_PADDING bit set are actually there - only for the redisplay code to know how many columns does - this character occupy on the screen. Skip padding glyphs. */ - if (CHAR_GLYPH_PADDING_P (*str)) - { - str++; - sl--; - } - else + /* If the face of this glyph is different from the current + screen face, update the screen attribute byte. */ + cf = str->face_id; + if (cf != screen_face) + IT_set_face (cf); /* handles invalid faces gracefully */ + + /* Identify a run of glyphs with the same face. */ + for (n = 1; n < sl; ++n) + if (str[n].face_id != cf) + break; + + if (n >= sl) + /* This is the last glyph. */ + coding->mode |= CODING_MODE_LAST_BLOCK; + + conversion_buffer = encode_terminal_code (str, n, coding); + if (coding->produced > 0) { - /* If the face of this glyph is different from the current - screen face, update the screen attribute byte. */ - cf = str->face_id; - if (cf != screen_face) - IT_set_face (cf); /* handles invalid faces gracefully */ - - if (sl <= 1) - /* This is the last glyph. */ - coding->mode |= CODING_MODE_LAST_BLOCK; - - conversion_buffer = encode_terminal_code (str, 1, coding); - if (coding->produced > 0) + /* Copy the encoded bytes to the screen buffer. */ + for (bp = conversion_buffer; coding->produced--; bp++) { - if (2*coding->produced > screen_buf_end - screen_bp) + /* Paranoia: discard bytes that would overrun the end of + the screen buffer. */ + if (screen_bp - screen_buf <= MAX_SCREEN_BUF - 2) { - /* The allocated buffer for screen writes is too small. - Flush it and loop again without incrementing STR, so - that the next loop will begin with the same glyph. */ - int nbytes = screen_bp - screen_buf; - - mouse_off_maybe (); - dosmemput (screen_buf, nbytes, (int)ScreenPrimary + offset); - if (screen_virtual_segment) - dosv_refresh_virtual_screen (offset, nbytes / 2); - new_pos_X += nbytes / 2; - offset += nbytes; - - /* Prepare to reuse the same buffer again. */ - screen_bp = screen_buf; - continue; - } - else - { - /* There's enough place in the allocated buffer to add - the encoding of this glyph. */ - - /* Copy the encoded bytes to the allocated buffer. */ - for (bp = conversion_buffer; coding->produced--; bp++) - { - *screen_bp++ = (unsigned char)*bp; - *screen_bp++ = ScreenAttrib; - if (tty->termscript) - fputc (*bp, tty->termscript); - } + *screen_bp++ = (unsigned char)*bp; + *screen_bp++ = ScreenAttrib; } + if (tty->termscript) + fputc (*bp, tty->termscript); } - /* Update STR and its remaining length. */ - str++; - sl--; } + /* Update STR and its remaining length. */ + str += n; + sl -= n; } - /* Dump whatever is left in the screen buffer. */ + /* Dump whatever we have in the screen buffer. */ mouse_off_maybe (); dosmemput (screen_buf, screen_bp - screen_buf, (int)ScreenPrimary + offset); if (screen_virtual_segment) -- 2.39.5