Mercurial > hg > xemacs-beta
annotate src/redisplay-tty.c @ 4967:0d4c9d0f6a8d
rewrite dynarr code
-------------------- ChangeLog entries follow: --------------------
src/ChangeLog addition:
2010-02-03 Ben Wing <ben@xemacs.org>
* device-x.c (x_get_resource_prefix):
* device-x.c (Fx_get_resource):
* device-x.c (Fx_get_resource_prefix):
* device-x.c (Fx_put_resource):
* dialog-msw.c:
* dialog-msw.c (handle_question_dialog_box):
* dired-msw.c (mswindows_sort_files):
* dired-msw.c (mswindows_get_files):
* extents.c (extent_fragment_sort_by_priority):
* extents.c (Fset_extent_parent):
* file-coding.c (coding_reader):
* file-coding.c (coding_writer):
* file-coding.c (gzip_convert):
* frame.c (generate_title_string):
* gutter.c (calculate_gutter_size_from_display_lines):
* indent.c (vmotion_1):
* lread.c (read_bit_vector):
* mule-coding.c (iso2022_decode):
* rangetab.c:
* rangetab.c (Fcopy_range_table):
* rangetab.c (Fget_range_table):
* rangetab.c (unified_range_table_copy_data):
* redisplay-msw.c (mswindows_output_string):
* redisplay-output.c (output_display_line):
* redisplay-output.c (redisplay_move_cursor):
* redisplay-output.c (redisplay_clear_bottom_of_window):
* redisplay-tty.c (tty_output_ichar_dynarr):
* redisplay-tty.c (set_foreground_to):
* redisplay-tty.c (set_background_to):
* redisplay-xlike-inc.c (XLIKE_output_string):
* redisplay.c (redisplay_window_text_width_string):
* redisplay.c (redisplay_text_width_string):
* redisplay.c (create_text_block):
* redisplay.c (SET_CURRENT_MODE_CHARS_PIXSIZE):
* redisplay.c (generate_fstring_runes):
* redisplay.c (regenerate_modeline):
* redisplay.c (ensure_modeline_generated):
* redisplay.c (real_current_modeline_height):
* redisplay.c (create_string_text_block):
* redisplay.c (regenerate_window):
* redisplay.c (REGEN_INC_FIND_START_END):
* redisplay.c (point_visible):
* redisplay.c (redisplay_window):
* redisplay.c (mark_glyph_block_dynarr):
* redisplay.c (line_start_cache_start):
* redisplay.c (start_with_line_at_pixpos):
* redisplay.c (update_line_start_cache):
* redisplay.c (glyph_to_pixel_translation):
* redisplay.c (pixel_to_glyph_translation):
* sysdep.c (qxe_readdir):
* text.c (dfc_convert_to_external_format):
* text.c (dfc_convert_to_internal_format):
* toolbar-common.c (common_output_toolbar_button):
* window.c (window_modeline_height):
* window.c (Fwindow_last_line_visible_height):
* window.c (window_displayed_height):
* window.c (window_scroll):
* window.c (get_current_pixel_pos):
Use Dynarr_begin() in place of Dynarr_atp (foo, 0).
* dynarr.c (Dynarr_realloc):
* dynarr.c (Dynarr_lisp_realloc):
* dynarr.c (Dynarr_resize):
* dynarr.c (Dynarr_insert_many):
* dynarr.c (Dynarr_delete_many):
* dynarr.c (Dynarr_memory_usage):
* dynarr.c (stack_like_malloc):
* dynarr.c (stack_like_free):
* lisp.h:
* lisp.h (DECLARE_DYNARR_LISP_IMP):
* lisp.h (XD_DYNARR_DESC):
* lisp.h (Dynarr_pop):
* gutter.c (output_gutter):
* redisplay-output.c (sync_rune_structs):
* redisplay-output.c (redisplay_output_window):
Redo the dynarr code, add greater checks.
Rename the `len', `largest' and `max' members to `len_',
`largest_' and `max_' to try and catch existing places that might
directly modify these values. Make new accessors Dynarr_largest()
and Dynarr_max() and make them and existing Dynarr_length() be
non-lvalues by adding '+ 0' to them; fix a couple of places in the
redisplay code that tried to modify the length directly by setting
Dynarr_length(). Use the accessors whenever possible even in the
dynarr code itself. The accessors also verify that 0 <= len <=
largest <= max. Rename settor function Dynarr_set_size() to
Dynarr_set_length() and use it more consistently; also create
lower-level Dynarr_set_length_1(). This latter function should be
the only function that directly modifies the `len_' member of a
Dynarr, and in the process makes sure that the `largest' value is
kept correct.
Consistently use ERROR_CHECK_STRUCTURES instead of
ERROR_CHECK_TYPES for error-checking code. Reintroduce the
temporarily disabled verification code on the positions of
Dynarr_at(), Dynarr_atp() and Dynarr_atp_past_end().
Also create Dynarr_resize_if() in place of a repeated
code fragment. Clean up all the functions that modify Dynarrs to
use the new macros and functions and verify the correctness of the
Dynarr both before and after the change.
Note that there are two kinds of verification -- one for accessing
and one for modifying. The difference is that the modify
verification additionally checks to make sure that the Dynarr
isn't locked. (This is used in redisplay to check for problems
with reentrancy.)
* lrecord.h: Move XD_DYNARR_DESC to lisp.h, grouping with the dynarr code.
author | Ben Wing <ben@xemacs.org> |
---|---|
date | Wed, 03 Feb 2010 20:51:18 -0600 |
parents | 304aebb79cd3 |
children | 5502045ec510 8b2f75cecb89 |
rev | line source |
---|---|
428 | 1 /* Communication module for TTY terminals. |
2 Copyright (C) 1994, 1995 Board of Trustees, University of Illinois. | |
3 Copyright (C) 1995 Sun Microsystems, Inc. | |
793 | 4 Copyright (C) 1995, 1996, 2002 Ben Wing. |
428 | 5 Copyright (C) 1996 Chuck Thompson. |
6 | |
7 This file is part of XEmacs. | |
8 | |
9 XEmacs is free software; you can redistribute it and/or modify it | |
10 under the terms of the GNU General Public License as published by the | |
11 Free Software Foundation; either version 2, or (at your option) any | |
12 later version. | |
13 | |
14 XEmacs is distributed in the hope that it will be useful, but WITHOUT | |
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
16 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
17 for more details. | |
18 | |
19 You should have received a copy of the GNU General Public License | |
20 along with XEmacs; see the file COPYING. If not, write to | |
21 the Free Software Foundation, Inc., 59 Temple Place - Suite 330, | |
22 Boston, MA 02111-1307, USA. */ | |
23 | |
24 /* Synched up with: Not completely synched with FSF. Mostly divergent | |
25 from FSF. */ | |
26 | |
27 /* This file has been Mule-ized. */ | |
28 | |
29 /* Written by Chuck Thompson. */ | |
30 /* Color support added by Ben Wing. */ | |
31 | |
32 #include <config.h> | |
33 #include "lisp.h" | |
34 | |
35 #include "buffer.h" | |
872 | 36 #include "device-impl.h" |
428 | 37 #include "events.h" |
38 #include "faces.h" | |
872 | 39 #include "frame-impl.h" |
428 | 40 #include "glyphs.h" |
41 #include "lstream.h" | |
42 #include "redisplay.h" | |
43 #include "sysdep.h" | |
44 #include "window.h" | |
45 | |
872 | 46 #include "console-tty-impl.h" |
47 #include "objects-tty-impl.h" | |
800 | 48 |
859 | 49 #include "syssignal.h" |
50 | |
428 | 51 /* These headers #define all kinds of common words like "columns"... |
52 What a bunch of losers. If we were to include them, we'd have to | |
53 include them last to prevent them from messing up our own header | |
54 files (struct slot names, etc.). But it turns out that there are | |
55 other conflicts as well on some systems, so screw it: we'll just | |
56 re-declare the routines we use and assume the code in this file is | |
57 invoking them correctly. */ | |
58 /* # include <curses.h> */ | |
59 /* # include <term.h> */ | |
442 | 60 EXTERN_C int tgetent (const char *, const char *); |
61 EXTERN_C int tgetflag (const char *); | |
62 EXTERN_C int tgetnum (const char *); | |
63 EXTERN_C char *tgetstr (const char *, char **); | |
64 EXTERN_C void tputs (const char *, int, void (*)(int)); | |
65 | |
428 | 66 #define FORCE_CURSOR_UPDATE(c) send_string_to_tty_console (c, 0, 0) |
67 #define OUTPUTN(c, a, n) \ | |
68 do { \ | |
69 cmputc_console = c; \ | |
70 FORCE_CURSOR_UPDATE (c); \ | |
71 tputs (a, n, cmputc); \ | |
72 } while (0) | |
73 #define OUTPUT1(c, a) OUTPUTN (c, a, 1) | |
74 #define OUTPUTN_IF(c, a, n) \ | |
75 do { \ | |
76 cmputc_console = c; \ | |
77 FORCE_CURSOR_UPDATE (c); \ | |
78 if (a) \ | |
79 tputs (a, n, cmputc); \ | |
80 } while (0) | |
81 #define OUTPUT1_IF(c, a) OUTPUTN_IF (c, a, 1) | |
82 | |
867 | 83 static void tty_output_ichar_dynarr (struct window *w, |
428 | 84 struct display_line *dl, |
867 | 85 Ichar_dynarr *buf, int xpos, |
428 | 86 face_index findex, |
87 int cursor); | |
867 | 88 static void tty_output_ibyte_string (struct window *w, |
428 | 89 struct display_line *dl, |
867 | 90 Ibyte *str, Bytecount len, |
428 | 91 int xpos, face_index findex, |
92 int cursor); | |
93 static void tty_turn_on_face (struct window *w, face_index findex); | |
94 static void tty_turn_off_face (struct window *w, face_index findex); | |
95 static void tty_turn_on_frame_face (struct frame *f, Lisp_Object face); | |
96 static void tty_turn_off_frame_face (struct frame *f, Lisp_Object face); | |
97 | |
98 static void term_get_fkeys (Lisp_Object keymap, char **address); | |
99 | |
100 /***************************************************************************** | |
101 tty_text_width | |
102 | |
3571 | 103 Non-Mule TTYs don't have fonts (that we use at least), so everything |
428 | 104 is considered to be fixed width -- in other words, we return LEN. |
105 Under Mule, however, a character can still cover more than one | |
867 | 106 column, so we use ichar_string_displayed_columns(). |
428 | 107 ****************************************************************************/ |
108 static int | |
4928
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
3571
diff
changeset
|
109 tty_text_width (struct window *w, struct face_cachel *UNUSED (cachel), |
2286 | 110 const Ichar *str, Charcount len) |
428 | 111 { |
4928
ea701c23ed84
change text_width method to take a window, in preparation for unicode-internal changes
Ben Wing <ben@xemacs.org>
parents:
3571
diff
changeset
|
112 struct console *c = WINDOW_XCONSOLE (w); |
3571 | 113 |
114 if (CONSOLE_TTY_MULTIPLE_WIDTH (c)) | |
115 { | |
116 return ichar_string_displayed_columns (str, len); | |
117 } | |
118 | |
119 return len; | |
428 | 120 } |
121 | |
122 /***************************************************************************** | |
123 tty_divider_height | |
124 | |
125 Return the width of the horizontal divider. This is a function | |
126 because divider_height is a console method. | |
127 ****************************************************************************/ | |
128 static int | |
129 tty_divider_height (void) | |
130 { | |
131 return 1; | |
132 } | |
133 | |
134 /***************************************************************************** | |
135 tty_eol_cursor_width | |
136 | |
137 Return the width of the end-of-line cursor. This is a function | |
138 because eol_cursor_width is a console method. | |
139 ****************************************************************************/ | |
140 static int | |
141 tty_eol_cursor_width (void) | |
142 { | |
143 return 1; | |
144 } | |
145 | |
146 /***************************************************************************** | |
442 | 147 tty_frame_output_begin |
428 | 148 |
149 Perform any necessary initialization prior to an update. | |
150 ****************************************************************************/ | |
2286 | 151 #ifdef HAVE_TERMIOS |
152 #define TERMIOS_MAYBE_UNUSED(decl) UNUSED(decl) | |
153 #else | |
154 #define TERMIOS_MAYBE_UNUSED(decl) decl | |
155 #endif | |
156 | |
428 | 157 #ifdef DEBUG_XEMACS |
2286 | 158 void tty_frame_output_begin (struct frame *TERMIOS_MAYBE_UNUSED(f)); |
428 | 159 void |
160 #else | |
161 static void | |
162 #endif | |
2286 | 163 tty_frame_output_begin (struct frame *TERMIOS_MAYBE_UNUSED(f)) |
428 | 164 { |
165 #ifndef HAVE_TERMIOS | |
166 /* Termcap requires `ospeed' to be a global variable so we have to | |
167 always set it for whatever tty console we are actually currently | |
168 working with. */ | |
442 | 169 ospeed = DEVICE_TTY_DATA (XDEVICE (FRAME_DEVICE (f)))->ospeed; |
428 | 170 #endif |
171 } | |
172 | |
173 /***************************************************************************** | |
442 | 174 tty_frame_output_end |
428 | 175 |
176 Perform any necessary flushing of queues when an update has completed. | |
177 ****************************************************************************/ | |
178 #ifdef DEBUG_XEMACS | |
442 | 179 void tty_frame_output_end (struct frame *f); |
428 | 180 void |
181 #else | |
182 static void | |
183 #endif | |
442 | 184 tty_frame_output_end (struct frame *f) |
428 | 185 { |
442 | 186 struct console *c = XCONSOLE (FRAME_CONSOLE (f)); |
428 | 187 |
188 CONSOLE_TTY_CURSOR_X (c) = CONSOLE_TTY_FINAL_CURSOR_X (c); | |
189 CONSOLE_TTY_CURSOR_Y (c) = CONSOLE_TTY_FINAL_CURSOR_Y (c); | |
190 FORCE_CURSOR_UPDATE (c); | |
191 Lstream_flush (XLSTREAM (CONSOLE_TTY_DATA (c)->outstream)); | |
192 } | |
193 | |
194 static void | |
195 tty_set_final_cursor_coords (struct frame *f, int y, int x) | |
196 { | |
197 struct console *c = XCONSOLE (FRAME_CONSOLE (f)); | |
198 | |
199 CONSOLE_TTY_FINAL_CURSOR_X (c) = x; | |
200 CONSOLE_TTY_FINAL_CURSOR_Y (c) = y; | |
201 } | |
202 | |
203 /***************************************************************************** | |
204 tty_output_display_block | |
205 | |
206 Given a display line, a block number for that start line, output all | |
207 runes between start and end in the specified display block. | |
208 ****************************************************************************/ | |
209 static void | |
210 tty_output_display_block (struct window *w, struct display_line *dl, int block, | |
211 int start, int end, int start_pixpos, | |
2286 | 212 int cursor_start, int UNUSED (cursor_width), |
213 int UNUSED (cursor_height)) | |
428 | 214 { |
215 struct frame *f = XFRAME (w->frame); | |
3479 | 216 Ichar_dynarr *buf; |
428 | 217 |
218 struct display_block *db = Dynarr_atp (dl->display_blocks, block); | |
219 rune_dynarr *rba = db->runes; | |
220 struct rune *rb; | |
221 | |
222 int elt = start; | |
223 face_index findex; | |
224 int xpos; | |
225 | |
226 rb = Dynarr_atp (rba, elt); | |
227 | |
228 if (!rb) | |
229 { | |
230 /* Nothing to do so don't do anything. */ | |
231 return; | |
232 } | |
233 else | |
234 { | |
235 findex = rb->findex; | |
236 xpos = rb->xpos; | |
237 } | |
238 | |
239 if (end < 0) | |
240 end = Dynarr_length (rba); | |
241 | |
3479 | 242 buf = Dynarr_new (Ichar); |
428 | 243 |
244 while (elt < end && Dynarr_atp (rba, elt)->xpos < start_pixpos) | |
245 { | |
246 elt++; | |
247 findex = Dynarr_atp (rba, elt)->findex; | |
248 xpos = Dynarr_atp (rba, elt)->xpos; | |
249 } | |
250 | |
251 while (elt < end) | |
252 { | |
253 rb = Dynarr_atp (rba, elt); | |
254 | |
255 if (rb->findex == findex && rb->type == RUNE_CHAR | |
256 && rb->object.chr.ch != '\n' | |
257 && (rb->cursor_type != CURSOR_ON | |
258 || NILP (w->text_cursor_visible_p))) | |
259 { | |
260 Dynarr_add (buf, rb->object.chr.ch); | |
261 elt++; | |
262 } | |
263 else | |
264 { | |
265 if (Dynarr_length (buf)) | |
266 { | |
867 | 267 tty_output_ichar_dynarr (w, dl, buf, xpos, findex, 0); |
428 | 268 xpos = rb->xpos; |
269 } | |
270 Dynarr_reset (buf); | |
271 | |
272 if (rb->type == RUNE_CHAR) | |
273 { | |
274 findex = rb->findex; | |
275 xpos = rb->xpos; | |
276 | |
277 if (rb->object.chr.ch == '\n') | |
278 { | |
279 /* Clear in case a cursor was formerly here. */ | |
280 | |
281 Dynarr_add (buf, ' '); | |
867 | 282 tty_output_ichar_dynarr (w, dl, buf, rb->xpos, |
428 | 283 DEFAULT_INDEX, 0); |
284 Dynarr_reset (buf); | |
285 | |
286 cmgoto (f, dl->ypos - 1, rb->xpos); | |
287 | |
288 elt++; | |
289 } | |
290 else if (rb->cursor_type == CURSOR_ON) | |
291 { | |
292 /* There is not a distinct eol cursor on tty's. */ | |
293 | |
294 Dynarr_add (buf, rb->object.chr.ch); | |
867 | 295 tty_output_ichar_dynarr (w, dl, buf, xpos, findex, 0); |
428 | 296 Dynarr_reset (buf); |
297 | |
298 cmgoto (f, dl->ypos - 1, xpos); | |
299 | |
300 xpos += rb->width; | |
301 elt++; | |
302 } | |
303 } | |
304 /* #### RUNE_HLINE is actually a little more complicated than this | |
305 but at the moment it is only used to draw a turned off | |
306 modeline and this will suffice for that. */ | |
307 else if (rb->type == RUNE_BLANK || rb->type == RUNE_HLINE) | |
308 { | |
867 | 309 Ichar ch_to_add; |
428 | 310 int size = rb->width; |
311 | |
312 if (rb->type == RUNE_BLANK) | |
313 ch_to_add = ' '; | |
314 else | |
315 ch_to_add = '-'; | |
316 | |
317 while (size--) | |
318 Dynarr_add (buf, ch_to_add); | |
867 | 319 tty_output_ichar_dynarr (w, dl, buf, rb->xpos, findex, 0); |
428 | 320 |
321 if (xpos >= cursor_start | |
322 && cursor_start < xpos + Dynarr_length (buf)) | |
323 { | |
324 cmgoto (f, dl->ypos - 1, cursor_start); | |
325 } | |
326 | |
327 Dynarr_reset (buf); | |
328 | |
329 elt++; | |
330 if (elt < end) | |
331 { | |
332 rb = Dynarr_atp (rba, elt); | |
333 | |
334 findex = rb->findex; | |
335 xpos = rb->xpos; | |
336 } | |
337 } | |
338 else if (rb->type == RUNE_DGLYPH) | |
339 { | |
340 Lisp_Object window; | |
341 Lisp_Object instance; | |
342 | |
793 | 343 window = wrap_window (w); |
428 | 344 instance = glyph_image_instance (rb->object.dglyph.glyph, |
793 | 345 window, ERROR_ME_DEBUG_WARN, 1); |
428 | 346 |
347 if (IMAGE_INSTANCEP (instance)) | |
442 | 348 { |
349 switch (XIMAGE_INSTANCE_TYPE (instance)) | |
428 | 350 { |
442 | 351 case IMAGE_MONO_PIXMAP: |
352 case IMAGE_COLOR_PIXMAP: | |
353 case IMAGE_SUBWINDOW: | |
354 case IMAGE_WIDGET: | |
355 /* just do nothing here */ | |
356 break; | |
428 | 357 |
442 | 358 case IMAGE_NOTHING: |
359 /* nothing is as nothing does */ | |
360 break; | |
428 | 361 |
442 | 362 case IMAGE_TEXT: |
363 case IMAGE_POINTER: | |
364 default: | |
2500 | 365 ABORT (); |
428 | 366 } |
442 | 367 IMAGE_INSTANCE_OPTIMIZE_OUTPUT |
368 (XIMAGE_INSTANCE (instance)) = 0; | |
369 } | |
428 | 370 |
371 xpos += rb->width; | |
372 elt++; | |
373 } | |
374 else | |
2500 | 375 ABORT (); |
428 | 376 } |
377 } | |
378 | |
379 if (Dynarr_length (buf)) | |
867 | 380 tty_output_ichar_dynarr (w, dl, buf, xpos, findex, 0); |
428 | 381 Dynarr_free (buf); |
382 | |
383 } | |
384 | |
385 | |
386 | |
387 /***************************************************************************** | |
388 tty_output_vertical_divider | |
389 | |
390 Draw a vertical divider down the right side of the given window. | |
391 ****************************************************************************/ | |
392 static void | |
2286 | 393 tty_output_vertical_divider (struct window *w, int UNUSED (clear)) |
428 | 394 { |
395 /* Divider width can either be 0 or 1 on TTYs */ | |
396 if (window_divider_width (w)) | |
397 { | |
398 struct frame *f = XFRAME (w->frame); | |
399 struct console *c = XCONSOLE (FRAME_CONSOLE (f)); | |
400 int line; | |
401 int y_top = WINDOW_TEXT_TOP (w); | |
402 int y_bot = WINDOW_TEXT_BOTTOM (w); | |
403 unsigned char divv = '|'; | |
404 | |
405 tty_turn_on_face (w, MODELINE_INDEX); | |
406 for (line = y_top; line < y_bot; line++) | |
407 { | |
408 cmgoto (f, line, WINDOW_TEXT_RIGHT (w)); | |
409 send_string_to_tty_console (c, &divv, 1); | |
410 TTY_INC_CURSOR_X (c, 1); | |
411 } | |
412 | |
413 /* Draw the divider in the modeline. */ | |
414 cmgoto (f, y_bot, WINDOW_TEXT_RIGHT (w)); | |
415 send_string_to_tty_console (c, &divv, 1); | |
416 TTY_INC_CURSOR_X (c, 1); | |
417 tty_turn_off_face (w, MODELINE_INDEX); | |
418 } | |
419 } | |
420 | |
421 /**************************************************************************** | |
422 tty_clear_region | |
423 | |
424 Clear the area in the box defined by the given parameters. | |
425 ****************************************************************************/ | |
426 static void | |
2286 | 427 tty_clear_region (Lisp_Object window, struct device* UNUSED (d), |
428 struct frame * f, face_index findex, int x, int y, | |
429 int width, int height, Lisp_Object UNUSED (fcolor), | |
430 Lisp_Object UNUSED (bcolor), | |
431 Lisp_Object UNUSED (background_pixmap)) | |
428 | 432 { |
433 struct console *c = XCONSOLE (FRAME_CONSOLE (f)); | |
434 int line; | |
435 struct window* w = XWINDOW (window); | |
436 | |
437 tty_turn_on_face (w, findex); | |
438 for (line = y; line < y + height; line++) | |
439 { | |
440 int col; | |
441 | |
442 cmgoto (f, line, x); | |
443 | |
444 if (window_is_leftmost (w) | |
445 && window_is_rightmost (w) | |
446 && TTY_SE (c).clr_to_eol) | |
447 { | |
448 OUTPUT1 (c, TTY_SE (c).clr_to_eol); | |
449 } | |
450 else | |
451 { | |
452 unsigned char sp = ' '; | |
453 /* #### Of course, this is all complete and utter crap. */ | |
454 for (col = x; col < x + width; col++) | |
455 send_string_to_tty_console (c, &sp, 1); | |
456 TTY_INC_CURSOR_X (c, width); | |
457 } | |
458 } | |
459 tty_turn_off_face (w, findex); | |
460 cmgoto (f, y, x); | |
461 } | |
462 | |
463 /***************************************************************************** | |
464 tty_clear_to_window_end | |
465 | |
466 Clear the area between ypos1 and ypos2. Each margin area and the | |
467 text area is handled separately since they may each have their own | |
468 background color. | |
469 ****************************************************************************/ | |
470 static void | |
471 tty_clear_to_window_end (struct window *w, int ypos1, int ypos2) | |
472 { | |
473 struct frame *f = XFRAME (w->frame); | |
474 struct console *c = XCONSOLE (FRAME_CONSOLE (f)); | |
475 int x, width; | |
476 | |
477 x = WINDOW_TEXT_LEFT (w); | |
478 width = WINDOW_TEXT_WIDTH (w); | |
479 | |
480 if (window_is_rightmost (w)) | |
481 { | |
482 /* #### Optimize to use clr_to_eol function of tty if available, if | |
483 the window is the entire width of the frame. */ | |
484 /* #### Is this actually an optimization? */ | |
485 int line; | |
486 tty_turn_on_face (w, DEFAULT_INDEX); | |
487 for (line = ypos1; line < ypos2; line++) | |
488 { | |
489 cmgoto (XFRAME (w->frame), line, x); | |
490 OUTPUT1 (c, TTY_SE (c).clr_to_eol); | |
491 } | |
492 tty_turn_off_face (w, DEFAULT_INDEX); | |
493 } | |
494 else | |
495 { | |
793 | 496 Lisp_Object window = wrap_window (w); |
428 | 497 |
498 redisplay_clear_region (window, DEFAULT_INDEX, x, ypos1, width, ypos2 - ypos1); | |
499 } | |
500 } | |
501 | |
502 /**************************************************************************** | |
503 tty_clear_frame | |
504 | |
505 Clear the entire frame. | |
506 ****************************************************************************/ | |
507 static void | |
508 tty_clear_frame (struct frame *f) | |
509 { | |
510 struct console *c = XCONSOLE (FRAME_CONSOLE (f)); | |
511 | |
512 tty_turn_on_frame_face (f, Vdefault_face); | |
513 if (TTY_SE (c).clr_frame) | |
514 { | |
515 OUTPUT1 (c, TTY_SE (c).clr_frame); | |
516 CONSOLE_TTY_REAL_CURSOR_X (c) = 0; | |
517 CONSOLE_TTY_REAL_CURSOR_Y (c) = 0; | |
518 #ifdef NOT_SURE | |
519 FRAME_CURSOR_X (f) = 0; | |
520 FRAME_CURSOR_Y (f) = 0; | |
521 #endif | |
522 } | |
523 else | |
524 { | |
525 #ifdef NOT_SURE | |
526 internal_cursor_to (f, 0, 0); | |
527 clear_to_end (f); | |
528 #else | |
529 /* #### Not implemented. */ | |
442 | 530 stderr_out ("Not yet.\n"); |
428 | 531 #endif |
532 } | |
533 tty_turn_off_frame_face (f, Vdefault_face); | |
534 } | |
535 | |
536 static void | |
867 | 537 tty_output_ibyte_string (struct window *w, struct display_line *dl, |
2286 | 538 Ibyte *str, Bytecount len, int xpos, |
539 face_index findex, int UNUSED (cursor)) | |
428 | 540 { |
541 struct frame *f = XFRAME (w->frame); | |
542 struct console *c = XCONSOLE (FRAME_CONSOLE (f)); | |
3571 | 543 int incing = CONSOLE_TTY_MULTIPLE_WIDTH (c) ? |
544 ibyte_string_displayed_columns (str, len) : | |
545 bytecount_to_charcount(str, len); | |
428 | 546 |
547 /* First position the cursor. */ | |
548 cmgoto (f, dl->ypos - 1, xpos); | |
549 | |
550 /* Enable any face properties. */ | |
551 tty_turn_on_face (w, findex); | |
552 | |
553 send_string_to_tty_console (c, str, len); | |
3571 | 554 TTY_INC_CURSOR_X (c, incing); |
428 | 555 |
556 /* Turn the face properties back off. */ | |
557 tty_turn_off_face (w, findex); | |
558 } | |
559 | |
867 | 560 static Ibyte_dynarr *tty_output_ichar_dynarr_dynarr; |
428 | 561 |
562 /***************************************************************************** | |
867 | 563 tty_output_ichar_dynarr |
428 | 564 |
565 Given a string and a starting position, output that string in the | |
566 given face. If cursor is true, draw a cursor around the string. | |
567 ****************************************************************************/ | |
568 static void | |
867 | 569 tty_output_ichar_dynarr (struct window *w, struct display_line *dl, |
570 Ichar_dynarr *buf, int xpos, face_index findex, | |
428 | 571 int cursor) |
572 { | |
867 | 573 if (!tty_output_ichar_dynarr_dynarr) |
574 tty_output_ichar_dynarr_dynarr = Dynarr_new (Ibyte); | |
428 | 575 else |
867 | 576 Dynarr_reset (tty_output_ichar_dynarr_dynarr); |
428 | 577 |
4967 | 578 convert_ichar_string_into_ibyte_dynarr (Dynarr_begin (buf), |
428 | 579 Dynarr_length (buf), |
867 | 580 tty_output_ichar_dynarr_dynarr); |
428 | 581 |
867 | 582 tty_output_ibyte_string (w, dl, |
4967 | 583 Dynarr_begin (tty_output_ichar_dynarr_dynarr), |
867 | 584 Dynarr_length (tty_output_ichar_dynarr_dynarr), |
428 | 585 xpos, findex, cursor); |
586 } | |
587 | |
588 #if 0 | |
589 | |
867 | 590 static Ibyte_dynarr *sidcs_dynarr; |
428 | 591 |
592 static void | |
593 substitute_in_dynamic_color_string (Lisp_Object spec, Lisp_Object string) | |
594 { | |
595 int i; | |
867 | 596 Ibyte *specdata = XSTRING_DATA (spec); |
428 | 597 Bytecount speclen = XSTRING_LENGTH (spec); |
598 | |
599 if (!sidcs_dynarr) | |
867 | 600 sidcs_dynarr = Dynarr_new (Ibyte); |
428 | 601 else |
602 Dynarr_reset (sidcs_dynarr); | |
603 | |
604 for (i = 0; i < speclen; i++) | |
605 { | |
606 if (specdata[i] == '%' && specdata[i+1] == '%') | |
607 { | |
608 Dynarr_add (sidcs_dynarr, '%'); | |
609 i++; | |
610 } | |
611 else if (specdata[i] == '%' && specdata[i+1] == 's') | |
612 { | |
613 Dynarr_add_many (sidcs_dynarr, | |
614 XSTRING_DATA (string), | |
615 XSTRING_LENGTH (string)); | |
616 i++; | |
617 } | |
618 else | |
619 Dynarr_add (sidcs_dynarr, specdata[i]); | |
620 } | |
621 } | |
622 | |
623 #endif | |
624 | |
625 static void | |
626 set_foreground_to (struct console *c, Lisp_Object sym) | |
627 { | |
628 Lisp_Object result; | |
867 | 629 Ibyte *escseq = 0; |
428 | 630 Bytecount escseqlen = 0; |
631 | |
632 result = assq_no_quit (sym, Vtty_color_alist); | |
633 if (!NILP (result)) | |
634 { | |
635 Lisp_Object esc_seq = XCAR (XCDR (result)); | |
636 escseq = XSTRING_DATA (esc_seq); | |
637 escseqlen = XSTRING_LENGTH (esc_seq); | |
638 } | |
639 #if 0 | |
640 else if (STRINGP (Vtty_dynamic_color_fg)) | |
641 { | |
642 substitute_in_dynamic_color_string (Vtty_dynamic_color_fg, | |
643 Fsymbol_name (sym)); | |
4967 | 644 escseq = Dynarr_begin (sidcs_dynarr); |
428 | 645 escseqlen = Dynarr_length (sidcs_dynarr); |
646 } | |
647 #endif | |
648 | |
649 if (escseq) | |
650 { | |
651 send_string_to_tty_console (c, escseq, escseqlen); | |
652 } | |
653 } | |
654 | |
655 static void | |
656 set_background_to (struct console *c, Lisp_Object sym) | |
657 { | |
658 Lisp_Object result; | |
867 | 659 Ibyte *escseq = 0; |
428 | 660 Bytecount escseqlen = 0; |
661 | |
662 result = assq_no_quit (sym, Vtty_color_alist); | |
663 if (!NILP (result)) | |
664 { | |
665 Lisp_Object esc_seq = XCDR (XCDR (result)); | |
666 escseq = XSTRING_DATA (esc_seq); | |
667 escseqlen = XSTRING_LENGTH (esc_seq); | |
668 } | |
669 #if 0 | |
670 else if (STRINGP (Vtty_dynamic_color_bg)) | |
671 { | |
672 substitute_in_dynamic_color_string (Vtty_dynamic_color_bg, | |
673 Fsymbol_name (sym)); | |
4967 | 674 escseq = Dynarr_begin (sidcs_dynarr); |
428 | 675 escseqlen = Dynarr_length (sidcs_dynarr); |
676 } | |
677 #endif | |
678 | |
679 if (escseq) | |
680 { | |
681 send_string_to_tty_console (c, escseq, escseqlen); | |
682 } | |
683 } | |
684 | |
685 static void | |
686 tty_turn_on_face_1 (struct console *c, int highlight_p, | |
687 int blinking_p, int dim_p, int underline_p, | |
688 int reverse_p, Lisp_Object cinst_fore, | |
689 Lisp_Object cinst_back) | |
690 { | |
691 if (highlight_p) | |
692 { | |
693 OUTPUT1_IF (c, TTY_SD (c).turn_on_bold); | |
694 } | |
695 | |
696 if (blinking_p) | |
697 { | |
698 OUTPUT1_IF (c, TTY_SD (c).turn_on_blinking); | |
699 } | |
700 | |
701 if (dim_p) | |
702 { | |
703 OUTPUT1_IF (c, TTY_SD (c).turn_on_dim); | |
704 } | |
705 | |
706 if (underline_p) | |
707 { | |
708 /* #### punt for now if underline mode is glitchy */ | |
709 if (!TTY_FLAGS (c).underline_width) | |
710 { | |
711 OUTPUT1_IF (c, TTY_SD (c).begin_underline); | |
712 } | |
713 } | |
714 | |
715 if (reverse_p) | |
716 { | |
717 /* #### punt for now if standout mode is glitchy */ | |
718 if (!TTY_FLAGS (c).standout_width) | |
719 { | |
720 OUTPUT1_IF (c, TTY_SD (c).begin_standout); | |
721 } | |
722 else | |
723 reverse_p = 0; | |
724 } | |
725 | |
726 if (reverse_p) | |
727 { | |
728 Lisp_Object temp = cinst_fore; | |
729 cinst_fore = cinst_back; | |
730 cinst_back = temp; | |
731 } | |
732 | |
733 if (COLOR_INSTANCEP (cinst_fore) | |
734 && !EQ (cinst_fore, Vthe_null_color_instance)) | |
735 set_foreground_to (c, COLOR_INSTANCE_TTY_SYMBOL | |
736 (XCOLOR_INSTANCE (cinst_fore))); | |
737 | |
738 if (COLOR_INSTANCEP (cinst_back) | |
739 && !EQ (cinst_back, Vthe_null_color_instance)) | |
740 set_background_to (c, COLOR_INSTANCE_TTY_SYMBOL | |
741 (XCOLOR_INSTANCE (cinst_back))); | |
742 } | |
743 | |
744 /***************************************************************************** | |
745 tty_turn_on_face | |
746 | |
747 Turn on all set properties of the given face. | |
748 ****************************************************************************/ | |
749 static void | |
750 tty_turn_on_face (struct window *w, face_index findex) | |
751 { | |
752 struct frame *f = XFRAME (w->frame); | |
753 struct console *c = XCONSOLE (FRAME_CONSOLE (f)); | |
754 | |
755 tty_turn_on_face_1 (c, | |
756 WINDOW_FACE_CACHEL_HIGHLIGHT_P (w, findex), | |
757 WINDOW_FACE_CACHEL_BLINKING_P (w, findex), | |
758 WINDOW_FACE_CACHEL_DIM_P (w, findex), | |
759 WINDOW_FACE_CACHEL_UNDERLINE_P (w, findex), | |
760 WINDOW_FACE_CACHEL_REVERSE_P (w, findex), | |
761 WINDOW_FACE_CACHEL_FOREGROUND (w, findex), | |
762 WINDOW_FACE_CACHEL_BACKGROUND (w, findex)); | |
763 } | |
764 | |
765 /***************************************************************************** | |
766 tty_turn_off_face | |
767 | |
768 Turn off all set properties of the given face (revert to default | |
769 face). We assume that tty_turn_on_face has been called for the given | |
770 face so that its properties are actually active. | |
771 ****************************************************************************/ | |
772 static void | |
773 tty_turn_off_face (struct window *w, face_index findex) | |
774 { | |
775 struct frame *f = XFRAME (w->frame); | |
776 struct console *c = XCONSOLE (FRAME_CONSOLE (f)); | |
777 | |
778 if (WINDOW_FACE_CACHEL_REVERSE_P (w, findex)) | |
779 { | |
780 /* #### punt for now if standout mode is glitchy */ | |
781 if (!TTY_FLAGS (c).standout_width) | |
782 { | |
783 OUTPUT1_IF (c, TTY_SD (c).end_standout); | |
784 } | |
785 } | |
786 | |
787 if (WINDOW_FACE_CACHEL_UNDERLINE_P (w, findex)) | |
788 { | |
789 /* #### punt for now if underline mode is glitchy */ | |
790 if (!TTY_FLAGS (c).underline_width) | |
791 { | |
792 OUTPUT1_IF (c, TTY_SD (c).end_underline); | |
793 } | |
794 } | |
795 | |
796 if (WINDOW_FACE_CACHEL_HIGHLIGHT_P (w, findex) || | |
797 WINDOW_FACE_CACHEL_BLINKING_P (w, findex) || | |
798 WINDOW_FACE_CACHEL_DIM_P (w, findex) || | |
799 !EQ (WINDOW_FACE_CACHEL_FOREGROUND (w, findex), | |
800 Vthe_null_color_instance) || | |
801 !EQ (WINDOW_FACE_CACHEL_BACKGROUND (w, findex), | |
802 Vthe_null_color_instance)) | |
803 { | |
804 OUTPUT1_IF (c, TTY_SD (c).turn_off_attributes); | |
805 } | |
806 } | |
807 | |
808 /***************************************************************************** | |
809 tty_turn_on_frame_face | |
810 | |
811 Turn on all set properties of the given face. | |
812 ****************************************************************************/ | |
813 static void | |
814 tty_turn_on_frame_face (struct frame *f, Lisp_Object face) | |
815 { | |
816 Lisp_Object frame; | |
817 struct console *c = XCONSOLE (FRAME_CONSOLE (f)); | |
818 | |
793 | 819 frame = wrap_frame (f); |
428 | 820 tty_turn_on_face_1 (c, |
821 FACE_HIGHLIGHT_P (face, frame), | |
822 FACE_BLINKING_P (face, frame), | |
823 FACE_DIM_P (face, frame), | |
824 FACE_UNDERLINE_P (face, frame), | |
825 FACE_REVERSE_P (face, frame), | |
826 FACE_FOREGROUND (face, frame), | |
827 FACE_BACKGROUND (face, frame)); | |
828 } | |
829 | |
830 /***************************************************************************** | |
831 tty_turn_off_frame_face | |
832 | |
833 Turn off all set properties of the given face (revert to default | |
834 face). We assume that tty_turn_on_face has been called for the given | |
835 face so that its properties are actually active. | |
836 ****************************************************************************/ | |
837 static void | |
838 tty_turn_off_frame_face (struct frame *f, Lisp_Object face) | |
839 { | |
840 Lisp_Object frame; | |
841 struct console *c = XCONSOLE (FRAME_CONSOLE (f)); | |
842 | |
793 | 843 frame = wrap_frame (f); |
428 | 844 |
845 if (FACE_REVERSE_P (face, frame)) | |
846 { | |
847 /* #### punt for now if standout mode is glitchy */ | |
848 if (!TTY_FLAGS (c).standout_width) | |
849 { | |
850 OUTPUT1_IF (c, TTY_SD (c).end_standout); | |
851 } | |
852 } | |
853 | |
854 if (FACE_UNDERLINE_P (face, frame)) | |
855 { | |
856 /* #### punt for now if underline mode is glitchy */ | |
857 if (!TTY_FLAGS (c).underline_width) | |
858 { | |
859 OUTPUT1_IF (c, TTY_SD (c).end_underline); | |
860 } | |
861 } | |
862 | |
863 if (FACE_HIGHLIGHT_P (face, frame) || | |
864 FACE_BLINKING_P (face, frame) || | |
865 FACE_DIM_P (face, frame) || | |
866 !EQ (FACE_FOREGROUND (face, frame), Vthe_null_color_instance) || | |
867 !EQ (FACE_BACKGROUND (face, frame), Vthe_null_color_instance)) | |
868 { | |
869 OUTPUT1_IF (c, TTY_SD (c).turn_off_attributes); | |
870 } | |
871 } | |
872 | |
873 /***************************************************************************** | |
874 set_tty_modes | |
875 | |
876 Sets up various parameters on tty modes. | |
877 ****************************************************************************/ | |
878 void | |
879 set_tty_modes (struct console *c) | |
880 { | |
881 if (!CONSOLE_TTY_P (c)) | |
882 return; | |
883 | |
884 OUTPUT1_IF (c, TTY_SD (c).init_motion); | |
885 OUTPUT1_IF (c, TTY_SD (c).cursor_visible); | |
886 OUTPUT1_IF (c, TTY_SD (c).keypad_on); | |
887 } | |
888 | |
889 /***************************************************************************** | |
890 reset_tty_modes | |
891 | |
892 Restore default state of tty. | |
893 ****************************************************************************/ | |
894 void | |
895 reset_tty_modes (struct console *c) | |
896 { | |
897 if (!CONSOLE_TTY_P (c)) | |
898 return; | |
899 | |
900 OUTPUT1_IF (c, TTY_SD (c).orig_pair); | |
901 OUTPUT1_IF (c, TTY_SD (c).keypad_off); | |
902 OUTPUT1_IF (c, TTY_SD (c).cursor_normal); | |
903 OUTPUT1_IF (c, TTY_SD (c).end_motion); | |
442 | 904 |
905 { | |
906 Lisp_Object frm = CONSOLE_SELECTED_FRAME (c); | |
907 | |
908 if (!NILP (frm)) | |
909 tty_frame_output_end (XFRAME (frm)); | |
910 } | |
428 | 911 } |
912 | |
913 /***************************************************************************** | |
914 tty_redisplay_shutdown | |
915 | |
916 Clear the frame and position the cursor properly for exiting. | |
917 ****************************************************************************/ | |
918 void | |
919 tty_redisplay_shutdown (struct console *c) | |
920 { | |
921 Lisp_Object dev = CONSOLE_SELECTED_DEVICE (c); | |
922 | |
923 if (!NILP (dev)) | |
924 { | |
925 Lisp_Object frm = DEVICE_SELECTED_FRAME (XDEVICE (dev)); | |
926 | |
927 if (!NILP (frm)) | |
928 { | |
929 struct frame *f = XFRAME (frm); | |
930 | |
931 /* Clear the bottom line of the frame. */ | |
932 redisplay_clear_region (FRAME_SELECTED_WINDOW (f), DEFAULT_INDEX, 0, | |
933 f->height, f->width, 1); | |
934 | |
935 /* And then stick the cursor there. */ | |
936 tty_set_final_cursor_coords (f, f->height, 0); | |
442 | 937 tty_frame_output_end (f); |
428 | 938 } |
939 } | |
940 } | |
941 | |
942 | |
943 /* #### Everything below here is old shit. It should either be moved | |
944 up or removed. */ | |
945 | |
946 | |
444 | 947 #ifdef NOT_YET |
428 | 948 /* FLAGS - these don't need to be console local since only one console |
442 | 949 can be being updated at a time. */ |
428 | 950 static int insert_mode_on; /* nonzero if in insert mode */ |
951 static int standout_mode_on; /* nonzero if in standout mode */ | |
952 static int underline_mode_on; /* nonzero if in underline mode */ | |
953 static int alternate_mode_on; /* nonzero if in alternate char set */ | |
954 static int attributes_on; /* nonzero if any attributes on */ | |
955 | |
956 static void | |
957 turn_on_insert (struct frame *f) | |
958 { | |
959 struct console *c = XCONSOLE (FRAME_CONSOLE (f)); | |
960 | |
961 if (!insert_mode_on) | |
962 OUTPUT1_IF (c, TTY_SE (c).begin_ins_mode); | |
963 insert_mode_on = 1; | |
964 } | |
965 | |
966 static void | |
967 turn_off_insert (struct frame *f) | |
968 { | |
969 struct console *c = XCONSOLE (FRAME_CONSOLE (f)); | |
970 | |
971 if (insert_mode_on) | |
972 OUTPUT1 (c, TTY_SE (c).end_ins_mode); | |
973 insert_mode_on = 0; | |
974 } | |
975 | |
976 static void | |
977 internal_cursor_to (struct frame *f, int row, int col) | |
978 { | |
979 struct console *c = XCONSOLE (FRAME_CONSOLE (f)); | |
980 | |
981 if (!TTY_FLAGS (c).insert_mode_motion) | |
982 turn_off_insert (f); | |
983 if (!TTY_FLAGS (c).standout_motion) | |
984 { | |
985 turn_off_standout (f); | |
986 turn_off_underline (f); | |
987 turn_off_alternate (f); | |
988 } | |
989 | |
990 cmgoto (f, row, col); | |
991 } | |
992 | |
993 static void | |
994 clear_to_end (struct frame *f) | |
995 { | |
996 struct console *c = XCONSOLE (FRAME_CONSOLE (f)); | |
997 | |
998 /* assumes cursor is already positioned */ | |
999 if (TTY_SE (c).clr_from_cursor) | |
1000 { | |
1001 OUTPUT1 (c, TTY_SE (c).clr_from_cursor); | |
1002 } | |
1003 else | |
1004 { | |
1005 int line = FRAME_CURSOR_Y (f); | |
1006 | |
1007 while (line < FRAME_HEIGHT (f)) | |
1008 { | |
1009 internal_cursor_to (f, line, 0); | |
1010 OUTPUT1 (c, TTY_SE (c).clr_to_eol); | |
1011 } | |
1012 } | |
1013 } | |
1014 #endif /* 0 */ | |
1015 | |
1016 #if 0 | |
1017 /* | |
1018 * clear from last visible line on window to window end (presumably | |
1019 * the line above window's modeline | |
1020 */ | |
1021 static void | |
1022 tty_clear_window_end (struct window *w, int ystart, int yend) | |
1023 { | |
1024 struct console *c = XCONSOLE (WINDOW_CONSOLE (w)); | |
1025 int line; | |
1026 | |
1027 for (line = ystart; line < yend; line++) | |
1028 { | |
1029 cmgoto (XFRAME (w->frame), line, 0); | |
1030 OUTPUT1 (c, TTY_SE (c).clr_to_eol); | |
1031 } | |
1032 } | |
1033 | |
1034 #endif /* 0 */ | |
1035 | |
1036 static int | |
1037 tty_flash (struct device *d) | |
1038 { | |
1039 struct console *c = XCONSOLE (DEVICE_CONSOLE (d)); | |
1040 if (TTY_SD (c).visual_bell) | |
1041 { | |
1042 OUTPUT1 (c, TTY_SD (c).visual_bell); | |
1043 Lstream_flush (XLSTREAM (CONSOLE_TTY_DATA (c)->outstream)); | |
1044 return 1; | |
1045 } | |
1046 else | |
1047 return 0; | |
1048 } | |
1049 | |
1050 /* | |
1051 * tty_ring_bell - sound an audio beep. | |
1052 */ | |
1053 static void | |
2286 | 1054 tty_ring_bell (struct device *d, int volume, int UNUSED (pitch), |
1055 int UNUSED (duration)) | |
428 | 1056 { |
1057 struct console *c = XCONSOLE (DEVICE_CONSOLE (d)); | |
1058 | |
1059 if (volume) | |
1060 { | |
1061 OUTPUT1 (c, TTY_SD (c).audio_bell); | |
1062 Lstream_flush (XLSTREAM (CONSOLE_TTY_DATA (c)->outstream)); | |
1063 } | |
1064 } | |
1065 | |
1066 | |
1067 int | |
1068 init_tty_for_redisplay (struct device *d, char *terminal_type) | |
1069 { | |
2367 | 1070 /* !!#### Mule-ize this */ |
428 | 1071 int status; |
1072 char entry_buffer[2044]; | |
1073 /* char temp_buffer[2044]; */ | |
1074 char *bufptr; | |
1075 struct console *c = XCONSOLE (DEVICE_CONSOLE (d)); | |
1076 | |
1077 /* What we should really do is allocate just enough space for | |
1078 the actual strings that are stored; but this would require | |
1079 doing this after all the tgetstr()s and adjusting all the | |
1080 pointers. */ | |
1081 CONSOLE_TTY_DATA (c)->term_entry_buffer = (char *) xmalloc (2044); | |
1082 bufptr = CONSOLE_TTY_DATA (c)->term_entry_buffer; | |
1083 | |
442 | 1084 #ifdef SIGTTOU |
428 | 1085 /* SIGTT* don't exist under win32 */ |
1086 EMACS_BLOCK_SIGNAL (SIGTTOU); | |
1087 #endif | |
1088 status = tgetent (entry_buffer, terminal_type); | |
442 | 1089 #ifdef SIGTTOU |
428 | 1090 EMACS_UNBLOCK_SIGNAL (SIGTTOU); |
1091 #endif | |
1092 #if 0 | |
1093 if (status < 0) | |
1094 return TTY_UNABLE_OPEN_DATABASE; | |
1095 else if (status == 0) | |
1096 return TTY_TYPE_UNDEFINED; | |
1097 #endif | |
1098 /* Under Linux at least, <0 is returned for TTY_TYPE_UNDEFINED. --ben */ | |
1099 if (status <= 0) | |
1100 return TTY_TYPE_UNDEFINED; | |
1101 | |
1102 /* | |
1103 * Establish the terminal size. | |
1104 */ | |
1105 /* First try to get the info from the system. If that fails, check | |
1106 the termcap entry. */ | |
1107 get_tty_device_size (d, &CONSOLE_TTY_DATA (c)->width, | |
1108 &CONSOLE_TTY_DATA (c)->height); | |
1109 | |
1110 if (CONSOLE_TTY_DATA (c)->width <= 0) | |
1111 CONSOLE_TTY_DATA (c)->width = tgetnum ("co"); | |
1112 if (CONSOLE_TTY_DATA (c)->height <= 0) | |
1113 CONSOLE_TTY_DATA (c)->height = tgetnum ("li"); | |
1114 | |
1115 if (CONSOLE_TTY_DATA (c)->width <= 0 || CONSOLE_TTY_DATA (c)->height <= 0) | |
1116 return TTY_SIZE_UNSPECIFIED; | |
1117 | |
1118 /* | |
1119 * Initialize cursor motion information. | |
1120 */ | |
1121 | |
1122 /* local cursor movement */ | |
1123 TTY_CM (c).up = tgetstr ("up", &bufptr); | |
1124 TTY_CM (c).down = tgetstr ("do", &bufptr); | |
1125 TTY_CM (c).left = tgetstr ("le", &bufptr); | |
1126 TTY_CM (c).right = tgetstr ("nd", &bufptr); | |
1127 TTY_CM (c).home = tgetstr ("ho", &bufptr); | |
1128 TTY_CM (c).low_left = tgetstr ("ll", &bufptr); | |
1129 TTY_CM (c).car_return = tgetstr ("cr", &bufptr); | |
1130 | |
1131 /* absolute cursor motion */ | |
1132 TTY_CM (c).abs = tgetstr ("cm", &bufptr); | |
1133 TTY_CM (c).hor_abs = tgetstr ("ch", &bufptr); | |
1134 TTY_CM (c).ver_abs = tgetstr ("cv", &bufptr); | |
1135 | |
1136 /* Verify that the terminal is powerful enough to run Emacs */ | |
1137 if (!TTY_CM (c).abs) | |
1138 { | |
1139 if (!TTY_CM (c).up || !TTY_CM (c).down | |
1140 || !TTY_CM (c).left || !TTY_CM (c).right) | |
1141 return TTY_TYPE_INSUFFICIENT; | |
1142 } | |
1143 | |
1144 /* parameterized local cursor movement */ | |
1145 TTY_CM (c).multi_up = tgetstr ("UP", &bufptr); | |
1146 TTY_CM (c).multi_down = tgetstr ("DO", &bufptr); | |
1147 TTY_CM (c).multi_left = tgetstr ("LE", &bufptr); | |
1148 TTY_CM (c).multi_right = tgetstr ("RI", &bufptr); | |
1149 | |
1150 /* scrolling */ | |
1151 TTY_CM (c).scroll_forw = tgetstr ("sf", &bufptr); | |
1152 TTY_CM (c).scroll_back = tgetstr ("sr", &bufptr); | |
1153 TTY_CM (c).multi_scroll_forw = tgetstr ("SF", &bufptr); | |
1154 TTY_CM (c).multi_scroll_back = tgetstr ("SR", &bufptr); | |
1155 TTY_CM (c).set_scroll_region = tgetstr ("cs", &bufptr); | |
1156 | |
1157 | |
1158 /* | |
1159 * Initialize screen editing information. | |
1160 */ | |
1161 | |
1162 /* adding to the screen */ | |
1163 TTY_SE (c).ins_line = tgetstr ("al", &bufptr); | |
1164 TTY_SE (c).multi_ins_line = tgetstr ("AL", &bufptr); | |
1165 TTY_SE (c).repeat = tgetstr ("rp", &bufptr); | |
1166 TTY_SE (c).begin_ins_mode = tgetstr ("im", &bufptr); | |
1167 TTY_SE (c).end_ins_mode = tgetstr ("ei", &bufptr); | |
1168 TTY_SE (c).ins_char = tgetstr ("ic", &bufptr); | |
1169 TTY_SE (c).multi_ins_char = tgetstr ("IC", &bufptr); | |
1170 TTY_SE (c).insert_pad = tgetstr ("ip", &bufptr); | |
1171 | |
1172 /* deleting from the screen */ | |
1173 TTY_SE (c).clr_frame = tgetstr ("cl", &bufptr); | |
1174 TTY_SE (c).clr_from_cursor = tgetstr ("cd", &bufptr); | |
1175 TTY_SE (c).clr_to_eol = tgetstr ("ce", &bufptr); | |
1176 TTY_SE (c).del_line = tgetstr ("dl", &bufptr); | |
1177 TTY_SE (c).multi_del_line = tgetstr ("DL", &bufptr); | |
1178 TTY_SE (c).del_char = tgetstr ("dc", &bufptr); | |
1179 TTY_SE (c).multi_del_char = tgetstr ("DC", &bufptr); | |
1180 TTY_SE (c).begin_del_mode = tgetstr ("dm", &bufptr); | |
1181 TTY_SE (c).end_del_mode = tgetstr ("ed", &bufptr); | |
1182 TTY_SE (c).erase_at_cursor = tgetstr ("ec", &bufptr); | |
1183 | |
1184 | |
1185 /* | |
1186 * Initialize screen display information. | |
1187 */ | |
1188 TTY_SD (c).begin_standout = tgetstr ("so", &bufptr); | |
1189 TTY_SD (c).end_standout = tgetstr ("se", &bufptr); | |
1190 TTY_SD (c).begin_underline = tgetstr ("us", &bufptr); | |
1191 TTY_SD (c).end_underline = tgetstr ("ue", &bufptr); | |
1192 TTY_SD (c).begin_alternate = tgetstr ("as", &bufptr); | |
1193 TTY_SD (c).end_alternate = tgetstr ("ae", &bufptr); | |
1194 TTY_SD (c).turn_on_reverse = tgetstr ("mr", &bufptr); | |
1195 TTY_SD (c).turn_on_blinking = tgetstr ("mb", &bufptr); | |
1196 TTY_SD (c).turn_on_bold = tgetstr ("md", &bufptr); | |
1197 TTY_SD (c).turn_on_dim = tgetstr ("mh", &bufptr); | |
1198 TTY_SD (c).turn_off_attributes = tgetstr ("me", &bufptr); | |
1199 TTY_SD (c).orig_pair = tgetstr ("op", &bufptr); | |
1200 | |
1201 TTY_SD (c).visual_bell = tgetstr ("vb", &bufptr); | |
1202 TTY_SD (c).audio_bell = tgetstr ("bl", &bufptr); | |
1203 if (!TTY_SD (c).audio_bell) | |
1204 { | |
1205 /* If audio_bell doesn't get set, then assume C-g. This is gross and | |
1206 ugly but is what Emacs has done from time immortal. */ | |
1207 TTY_SD (c).audio_bell = "\07"; | |
1208 } | |
1209 | |
1210 TTY_SD (c).cursor_visible = tgetstr ("ve", &bufptr); | |
1211 TTY_SD (c).cursor_normal = tgetstr ("vs", &bufptr); | |
1212 TTY_SD (c).init_motion = tgetstr ("ti", &bufptr); | |
1213 TTY_SD (c).end_motion = tgetstr ("te", &bufptr); | |
1214 TTY_SD (c).keypad_on = tgetstr ("ks", &bufptr); | |
1215 TTY_SD (c).keypad_off = tgetstr ("ke", &bufptr); | |
1216 | |
1217 | |
1218 /* | |
1219 * Initialize additional terminal information. | |
1220 */ | |
1221 TTY_FLAGS (c).must_write_spaces = tgetflag ("in"); | |
1222 TTY_FLAGS (c).insert_mode_motion = tgetflag ("mi"); | |
1223 TTY_FLAGS (c).standout_motion = tgetflag ("ms"); | |
1224 TTY_FLAGS (c).memory_above_frame = tgetflag ("da"); | |
1225 TTY_FLAGS (c).memory_below_frame = tgetflag ("db"); | |
1226 TTY_FLAGS (c).standout_width = tgetnum ("sg"); | |
1227 TTY_FLAGS (c).underline_width = tgetnum ("ug"); | |
1228 | |
1229 if (TTY_FLAGS (c).standout_width == -1) | |
1230 TTY_FLAGS (c).standout_width = 0; | |
1231 if (TTY_FLAGS (c).underline_width == -1) | |
1232 TTY_FLAGS (c).underline_width = 0; | |
1233 | |
1234 TTY_FLAGS (c).meta_key = | |
1235 eight_bit_tty (d) ? tgetflag ("km") || tgetflag ("MT") ? 1 : 2 : 0; | |
1236 | |
1237 | |
1238 /* | |
1239 * Setup the costs tables for this tty console. | |
1240 */ | |
1241 cm_cost_init (c); | |
1242 | |
444 | 1243 #ifdef NOT_YET |
428 | 1244 /* |
1245 * Initialize local flags. | |
1246 */ | |
1247 insert_mode_on = 0; | |
1248 standout_mode_on = 0; | |
1249 underline_mode_on = 0; | |
1250 alternate_mode_on = 0; | |
1251 attributes_on = 0; | |
444 | 1252 #endif |
428 | 1253 |
1254 /* | |
1255 * Attempt to initialize the function_key_map to | |
1256 * some kind of sensible value | |
1257 */ | |
1258 | |
1259 term_get_fkeys (c->function_key_map, &bufptr); | |
1260 | |
1261 { | |
1262 /* check for ANSI set-foreground and set-background strings, | |
1263 and assume color if so. | |
1264 | |
1265 #### we should support the other (non-ANSI) ways of specifying | |
1266 color, too. */ | |
1267 char foobuf[500]; | |
1268 char *fooptr = foobuf; | |
1269 if ((tgetstr ("AB", &fooptr) && tgetstr ("AF", &fooptr)) || | |
1270 (tgetstr ("Sf", &fooptr) && tgetstr ("Sb", &fooptr)) || | |
1271 ((tgetnum ("Co") > 0) && (tgetnum ("pa") > 0))) | |
1272 DEVICE_CLASS (d) = Qcolor; | |
1273 else | |
1274 DEVICE_CLASS (d) = Qmono; | |
1275 } | |
1276 | |
1277 return TTY_INIT_SUCCESS; | |
1278 } | |
1279 | |
1280 struct fkey_table | |
1281 { | |
442 | 1282 const char *cap; |
1283 const char *name; | |
428 | 1284 }; |
1285 | |
1286 /* Termcap capability names that correspond directly to X keysyms. | |
1287 Some of these (marked "terminfo") aren't supplied by old-style | |
1288 (Berkeley) termcap entries. They're listed in X keysym order; | |
1289 except we put the keypad keys first, so that if they clash with | |
1290 other keys (as on the IBM PC keyboard) they get overridden. | |
1291 */ | |
1292 | |
1293 static struct fkey_table keys[] = | |
1294 { | |
1295 {"kh", "home"}, /* termcap */ | |
1296 {"kl", "left"}, /* termcap */ | |
1297 {"ku", "up"}, /* termcap */ | |
1298 {"kr", "right"}, /* termcap */ | |
1299 {"kd", "down"}, /* termcap */ | |
1300 {"%8", "prior"}, /* terminfo */ | |
1301 {"%5", "next"}, /* terminfo */ | |
1302 {"@7", "end"}, /* terminfo */ | |
1303 {"@1", "begin"}, /* terminfo */ | |
1304 {"*6", "select"}, /* terminfo */ | |
1305 {"%9", "print"}, /* terminfo */ | |
1306 {"@4", "execute"}, /* terminfo --- actually the `command' key */ | |
1307 /* | |
1308 * "insert" --- see below | |
1309 */ | |
1310 {"&8", "undo"}, /* terminfo */ | |
1311 {"%0", "redo"}, /* terminfo */ | |
1312 {"%7", "menu"}, /* terminfo --- actually the `options' key */ | |
1313 {"@0", "find"}, /* terminfo */ | |
1314 {"@2", "cancel"}, /* terminfo */ | |
1315 {"%1", "help"}, /* terminfo */ | |
1316 /* | |
1317 * "break" goes here, but can't be reliably intercepted with termcap | |
1318 */ | |
1319 {"&4", "reset"}, /* terminfo --- actually `restart' */ | |
1320 /* | |
1321 * "system" and "user" --- no termcaps | |
1322 */ | |
1323 {"kE", "clearline"}, /* terminfo */ | |
1324 {"kA", "insertline"}, /* terminfo */ | |
1325 {"kL", "deleteline"}, /* terminfo */ | |
1326 {"kI", "insertchar"}, /* terminfo */ | |
1327 {"kD", "delete"}, /* terminfo */ | |
1328 {"kB", "backtab"}, /* terminfo */ | |
1329 /* | |
1330 * "kp-backtab", "kp-space", "kp-tab" --- no termcaps | |
1331 */ | |
1332 {"@8", "kp-enter"}, /* terminfo */ | |
1333 /* | |
1334 * "kp-f1", "kp-f2", "kp-f3" "kp-f4", | |
1335 * "kp-multiply", "kp-add", "kp-separator", | |
1336 * "kp-subtract", "kp-decimal", "kp-divide", "kp-0"; | |
1337 * --- no termcaps for any of these. | |
1338 */ | |
1339 {"K4", "kp-1"}, /* terminfo */ | |
1340 /* | |
1341 * "kp-2" --- no termcap | |
1342 */ | |
1343 {"K5", "kp-3"}, /* terminfo */ | |
1344 /* | |
1345 * "kp-4" --- no termcap | |
1346 */ | |
1347 {"K2", "kp-5"}, /* terminfo */ | |
1348 /* | |
1349 * "kp-6" --- no termcap | |
1350 */ | |
1351 {"K1", "kp-7"}, /* terminfo */ | |
1352 /* | |
1353 * "kp-8" --- no termcap | |
1354 */ | |
1355 {"K3", "kp-9"}, /* terminfo */ | |
1356 /* | |
1357 * "kp-equal" --- no termcap | |
1358 */ | |
1359 {"k1", "f1"}, | |
1360 {"k2", "f2"}, | |
1361 {"k3", "f3"}, | |
1362 {"k4", "f4"}, | |
1363 {"k5", "f5"}, | |
1364 {"k6", "f6"}, | |
1365 {"k7", "f7"}, | |
1366 {"k8", "f8"}, | |
1367 {"k9", "f9"}, | |
1368 }; | |
1369 | |
1370 static char **term_get_fkeys_arg; | |
1371 | |
1372 static Lisp_Object term_get_fkeys_1 (Lisp_Object keymap); | |
1373 static Lisp_Object term_get_fkeys_error (Lisp_Object err, Lisp_Object arg); | |
1374 | |
1375 /* Find the escape codes sent by the function keys for Vfunction_key_map. | |
1376 This function scans the termcap function key sequence entries, and | |
1377 adds entries to Vfunction_key_map for each function key it finds. */ | |
1378 | |
1379 static void | |
1380 term_get_fkeys (Lisp_Object keymap, char **address) | |
1381 { | |
1382 /* We run the body of the function (term_get_fkeys_1) and ignore all Lisp | |
1383 errors during the call. The only errors should be from Fdefine_key | |
1384 when given a key sequence containing an invalid prefix key. If the | |
1385 termcap defines function keys which use a prefix that is already bound | |
1386 to a command by the default bindings, we should silently ignore that | |
1387 function key specification, rather than giving the user an error and | |
1388 refusing to run at all on such a terminal. */ | |
1389 | |
1390 term_get_fkeys_arg = address; | |
1391 | |
1392 condition_case_1 (Qerror, | |
1393 term_get_fkeys_1, keymap, | |
1394 term_get_fkeys_error, Qnil); | |
1395 } | |
1396 | |
1397 static Lisp_Object | |
2286 | 1398 term_get_fkeys_error (Lisp_Object UNUSED (err), Lisp_Object arg) |
428 | 1399 { |
1400 return arg; | |
1401 } | |
1402 | |
1403 static Lisp_Object | |
1404 term_get_fkeys_1 (Lisp_Object function_key_map) | |
1405 { | |
1406 int i; | |
1407 | |
1408 char **address = term_get_fkeys_arg; | |
1409 | |
1410 for (i = 0; i < countof (keys); i++) | |
1411 { | |
1412 char *sequence = tgetstr (keys[i].cap, address); | |
1413 if (sequence) | |
1414 Fdefine_key (function_key_map, | |
4953
304aebb79cd3
function renamings to track names of char typedefs
Ben Wing <ben@xemacs.org>
parents:
4928
diff
changeset
|
1415 build_extstring (sequence, Qbinary), |
428 | 1416 vector1 (intern (keys[i].name))); |
1417 } | |
1418 | |
1419 /* The uses of the "k0" capability are inconsistent; sometimes it | |
1420 describes F10, whereas othertimes it describes F0 and "k;" describes F10. | |
1421 We will attempt to politely accommodate both systems by testing for | |
1422 "k;", and if it is present, assuming that "k0" denotes F0, otherwise F10. | |
1423 */ | |
1424 { | |
442 | 1425 const char *k_semi = tgetstr ("k;", address); |
1426 const char *k0 = tgetstr ("k0", address); | |
428 | 1427 |
1428 if (k_semi) | |
4953
304aebb79cd3
function renamings to track names of char typedefs
Ben Wing <ben@xemacs.org>
parents:
4928
diff
changeset
|
1429 Fdefine_key (function_key_map, build_extstring (k_semi, Qbinary), |
428 | 1430 vector1 (intern ("f10"))); |
1431 | |
1432 if (k0) | |
4953
304aebb79cd3
function renamings to track names of char typedefs
Ben Wing <ben@xemacs.org>
parents:
4928
diff
changeset
|
1433 Fdefine_key (function_key_map, build_extstring (k0, Qbinary), |
428 | 1434 vector1 (intern (k_semi ? "f0" : "f10"))); |
1435 } | |
1436 | |
1437 /* Set up cookies for numbered function keys above f10. */ | |
1438 { | |
1439 char fcap[3], fkey[4]; | |
1440 | |
1441 fcap[0] = 'F'; fcap[2] = '\0'; | |
1442 for (i = 11; i < 64; i++) | |
1443 { | |
1444 if (i <= 19) | |
1445 fcap[1] = '1' + i - 11; | |
1446 else if (i <= 45) | |
1447 fcap[1] = 'A' + i - 20; | |
1448 else | |
1449 fcap[1] = 'a' + i - 46; | |
1450 | |
1451 { | |
1452 char *sequence = tgetstr (fcap, address); | |
1453 if (sequence) | |
1454 { | |
1455 sprintf (fkey, "f%d", i); | |
1456 Fdefine_key (function_key_map, | |
4953
304aebb79cd3
function renamings to track names of char typedefs
Ben Wing <ben@xemacs.org>
parents:
4928
diff
changeset
|
1457 build_extstring (sequence, Qbinary), |
428 | 1458 vector1 (intern (fkey))); |
1459 } | |
1460 } | |
1461 } | |
1462 } | |
1463 | |
1464 /* | |
1465 * Various mappings to try and get a better fit. | |
1466 */ | |
440 | 1467 #define CONDITIONAL_REASSIGN(cap1, cap2, keyname) do { \ |
1468 if (!tgetstr (cap1, address)) \ | |
1469 { \ | |
1470 char *sequence = tgetstr (cap2, address); \ | |
1471 if (sequence) \ | |
1472 Fdefine_key (function_key_map, \ | |
4953
304aebb79cd3
function renamings to track names of char typedefs
Ben Wing <ben@xemacs.org>
parents:
4928
diff
changeset
|
1473 build_extstring (sequence, Qbinary), \ |
440 | 1474 vector1 (intern (keyname))); \ |
1475 } \ | |
1476 } while (0) | |
428 | 1477 |
1478 /* if there's no key_next keycap, map key_npage to `next' keysym */ | |
1479 CONDITIONAL_REASSIGN ("%5", "kN", "next"); | |
1480 /* if there's no key_prev keycap, map key_ppage to `previous' keysym */ | |
1481 CONDITIONAL_REASSIGN ("%8", "kP", "prior"); | |
1482 /* if there's no key_dc keycap, map key_ic to `insert' keysym */ | |
1483 CONDITIONAL_REASSIGN ("kD", "kI", "insert"); | |
1484 | |
1485 /* IBM has their own non-standard dialect of terminfo. | |
1486 If the standard name isn't found, try the IBM name. */ | |
1487 CONDITIONAL_REASSIGN ("kB", "KO", "backtab"); | |
1488 CONDITIONAL_REASSIGN ("@4", "kJ", "execute"); /* actually "action" */ | |
1489 CONDITIONAL_REASSIGN ("@4", "kc", "execute"); /* actually "command" */ | |
1490 CONDITIONAL_REASSIGN ("%7", "ki", "menu"); | |
1491 CONDITIONAL_REASSIGN ("@7", "kw", "end"); | |
1492 CONDITIONAL_REASSIGN ("F1", "k<", "f11"); | |
1493 CONDITIONAL_REASSIGN ("F2", "k>", "f12"); | |
1494 CONDITIONAL_REASSIGN ("%1", "kq", "help"); | |
1495 CONDITIONAL_REASSIGN ("*6", "kU", "select"); | |
1496 #undef CONDITIONAL_REASSIGN | |
1497 | |
1498 return Qnil; | |
1499 } | |
1500 | |
1501 | |
1502 /************************************************************************/ | |
1503 /* initialization */ | |
1504 /************************************************************************/ | |
1505 | |
1506 void | |
1507 console_type_create_redisplay_tty (void) | |
1508 { | |
1509 /* redisplay methods */ | |
1510 CONSOLE_HAS_METHOD (tty, text_width); | |
1511 CONSOLE_HAS_METHOD (tty, output_display_block); | |
1512 CONSOLE_HAS_METHOD (tty, output_vertical_divider); | |
1513 CONSOLE_HAS_METHOD (tty, divider_height); | |
1514 CONSOLE_HAS_METHOD (tty, eol_cursor_width); | |
1515 CONSOLE_HAS_METHOD (tty, clear_to_window_end); | |
1516 CONSOLE_HAS_METHOD (tty, clear_region); | |
1517 CONSOLE_HAS_METHOD (tty, clear_frame); | |
442 | 1518 CONSOLE_HAS_METHOD (tty, frame_output_begin); |
1519 CONSOLE_HAS_METHOD (tty, frame_output_end); | |
428 | 1520 CONSOLE_HAS_METHOD (tty, flash); |
1521 CONSOLE_HAS_METHOD (tty, ring_bell); | |
1522 CONSOLE_HAS_METHOD (tty, set_final_cursor_coords); | |
1523 } |