1 /* editor text drawing.
3 Copyright (C) 1996, 1997 the Free Software Foundation
5 Authors: 1996, 1997 Paul Sheer
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 2 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program; if not, write to the Free Software
21 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
28 #define MAX_LINE_LEN 1024
31 #include "src/charsets.h"
34 static void status_string (WEdit
* edit
, char *s
, int w
, int fill
, int font_width
)
39 * If we are at the end of file, print <EOF>,
40 * otherwise print the current character as is (if printable),
41 * as decimal and as hex.
43 if (edit
->curs1
< edit
->last_byte
) {
44 unsigned char cur_byte
= edit_get_byte (edit
, edit
->curs1
);
45 g_snprintf (byte_str
, sizeof(byte_str
), "%c %3d 0x%02X",
46 is_printable(cur_byte
) ? cur_byte
: '.',
50 strcpy(byte_str
, "<EOF>");
53 /* The field lengths just prevent the status line from shortening too much */
55 "[%c%c%c%c] %2ld L:[%3ld+%2ld %3ld/%3ld] *(%-4ld/%4ldb)= %s",
56 edit
->mark1
!= edit
->mark2
? ( column_highlighting
? 'C' : 'B') : '-',
57 edit
->modified
? 'M' : '-',
58 edit
->macro_i
< 0 ? '-' : 'R',
59 edit
->overwrite
== 0 ? '-' : 'O',
60 edit
->curs_col
/ font_width
,
65 edit
->total_lines
+ 1,
72 /* how to get as much onto the status line as is numerically possible :) */
73 void edit_status (WEdit
* edit
)
77 w
= edit
->widget
.cols
- (edit
->have_frame
* 2);
82 attrset (SELECTED_COLOR
);
84 widget_move (edit
, edit
->have_frame
, edit
->have_frame
);
85 i
= w
> 24 ? 18 : w
- 6;
87 strcpy (s
, (char *) name_trunc (edit
->filename
? edit
->filename
: "", i
));
93 status_string (edit
, s
+ 20, t
, ' ', 1);
97 printw ("%-*s", w
, s
);
98 attrset (EDITOR_NORMAL_COLOR
);
102 /* result is boolean */
103 int cursor_in_screen (WEdit
* edit
, long row
)
105 if (row
< 0 || row
>= edit
->num_widget_lines
)
111 /* returns rows from the first displayed line to the cursor */
112 int cursor_from_display_top (WEdit
* edit
)
114 if (edit
->curs1
< edit
->start_display
)
115 return -edit_move_forward (edit
, edit
->curs1
, 0, edit
->start_display
);
117 return edit_move_forward (edit
, edit
->start_display
, 0, edit
->curs1
);
120 /* returns how far the cursor is out of the screen */
121 int cursor_out_of_screen (WEdit
* edit
)
123 int row
= cursor_from_display_top (edit
);
124 if (row
>= edit
->num_widget_lines
)
125 return row
- edit
->num_widget_lines
+ 1;
131 /* this scrolls the text so that cursor is on the screen */
132 void edit_scroll_screen_over_cursor (WEdit
* edit
)
136 int b_extreme
, t_extreme
, l_extreme
, r_extreme
;
138 if (edit
->num_widget_lines
<= 0 || edit
->num_widget_columns
<= 0)
141 r_extreme
= EDIT_RIGHT_EXTREME
;
142 l_extreme
= EDIT_LEFT_EXTREME
;
143 b_extreme
= EDIT_BOTTOM_EXTREME
;
144 t_extreme
= EDIT_TOP_EXTREME
;
145 if (edit
->found_len
) {
146 b_extreme
= max (edit
->num_widget_lines
/ 4, b_extreme
);
147 t_extreme
= max (edit
->num_widget_lines
/ 4, t_extreme
);
149 if (b_extreme
+ t_extreme
+ 1 > edit
->num_widget_lines
) {
151 n
= b_extreme
+ t_extreme
;
152 b_extreme
= (b_extreme
* (edit
->num_widget_lines
- 1)) / n
;
153 t_extreme
= (t_extreme
* (edit
->num_widget_lines
- 1)) / n
;
155 if (l_extreme
+ r_extreme
+ 1 > edit
->num_widget_columns
) {
157 n
= l_extreme
+ t_extreme
;
158 l_extreme
= (l_extreme
* (edit
->num_widget_columns
- 1)) / n
;
159 r_extreme
= (r_extreme
* (edit
->num_widget_columns
- 1)) / n
;
161 p
= edit_get_col (edit
);
162 edit_update_curs_row (edit
);
163 outby
= p
+ edit
->start_col
- edit
->num_widget_columns
+ 1 + (r_extreme
+ edit
->found_len
);
165 edit_scroll_right (edit
, outby
);
166 outby
= l_extreme
- p
- edit
->start_col
;
168 edit_scroll_left (edit
, outby
);
170 outby
= p
- edit
->num_widget_lines
+ 1 + b_extreme
;
172 edit_scroll_downward (edit
, outby
);
173 outby
= t_extreme
- p
;
175 edit_scroll_upward (edit
, outby
);
176 edit_update_curs_row (edit
);
179 #define set_color(font) attrset (font)
181 #define edit_move(x,y) widget_move(edit, y, x);
183 /* Set colorpair by index, don't interpret S-Lang "emulated attributes" */
185 #define lowlevel_set_color(x) SLsmg_set_color(x & 0x7F)
187 #define lowlevel_set_color(x) attrset(MY_COLOR_PAIR(color))
190 static void print_to_widget (WEdit
* edit
, long row
, int start_col
, float start_col_real
, long end_col
, unsigned int line
[])
192 int x
= (float) start_col_real
+ EDIT_TEXT_HORIZONTAL_OFFSET
;
193 int x1
= start_col
+ EDIT_TEXT_HORIZONTAL_OFFSET
;
194 int y
= row
+ EDIT_TEXT_VERTICAL_OFFSET
;
196 set_color (EDITOR_NORMAL_COLOR
);
198 hline (' ', end_col
+ 1 - EDIT_TEXT_HORIZONTAL_OFFSET
- x1
);
200 edit_move (x
+ FONT_OFFSET_X
, y
+ FONT_OFFSET_Y
);
202 unsigned int *p
= line
;
209 textchar
= *p
& 0xFF;
212 if (style
& MOD_ABNORMAL
) {
213 /* Non-printable - show as a dot on black background */
217 if (!(style
& (0xFF - MOD_ABNORMAL
- MOD_CURSOR
)))
218 lowlevel_set_color (color
);
219 if (style
& MOD_HIGHLIGHTED
) {
220 set_color (EDITOR_BOLD_COLOR
);
221 } else if (style
& MOD_MARKED
) {
222 set_color (EDITOR_MARKED_COLOR
);
224 if (style
& MOD_UNDERLINED
) {
225 set_color (EDITOR_UNDERLINED_COLOR
);
227 if (style
& MOD_BOLD
) {
228 set_color (EDITOR_BOLD_COLOR
);
236 /* b is a pointer to the beginning of the line */
237 static void edit_draw_this_line (WEdit
* edit
, long b
, long row
, long start_col
, long end_col
)
239 static unsigned int line
[MAX_LINE_LEN
];
240 unsigned int *p
= line
;
241 long m1
= 0, m2
= 0, q
, c1
, c2
;
242 int col
, start_col_real
;
245 int i
, book_mark
= -1;
248 if (!book_mark_query (edit
, edit
->start_line
+ row
, &book_mark
))
252 edit_get_syntax_color (edit
, b
- 1, &color
);
253 q
= edit_move_forward3 (edit
, b
, start_col
- edit
->start_col
, 0);
254 start_col_real
= (col
= (int) edit_move_forward3 (edit
, b
, 0, q
)) + edit
->start_col
;
255 c1
= min (edit
->column1
, edit
->column2
);
256 c2
= max (edit
->column1
, edit
->column2
);
258 if (col
+ 16 > -edit
->start_col
) {
259 eval_marks (edit
, &m1
, &m2
);
261 if (row
<= edit
->total_lines
- edit
->start_line
) {
262 while (col
<= end_col
- edit
->start_col
) {
264 if (q
== edit
->curs1
)
265 *p
|= MOD_CURSOR
* 256;
266 if (q
>= m1
&& q
< m2
) {
267 if (column_highlighting
) {
269 x
= edit_move_forward3 (edit
, b
, 0, q
);
270 if (x
>= c1
&& x
< c2
)
271 *p
|= MOD_MARKED
* 256;
273 *p
|= MOD_MARKED
* 256;
275 if (q
== edit
->bracket
)
276 *p
|= MOD_BOLD
* 256;
277 if (q
>= edit
->found_start
&& q
< edit
->found_start
+ edit
->found_len
)
278 *p
|= MOD_HIGHLIGHTED
* 256;
279 c
= edit_get_byte (edit
, q
);
280 /* we don't use bg for mc - fg contains both */
281 if (book_mark
== -1) {
282 edit_get_syntax_color (edit
, q
, &color
);
285 *p
|= book_mark
<< 16;
290 col
= end_col
- edit
->start_col
+ 1; /* quit */
294 i
= TAB_SIZE
- ((int) col
% TAB_SIZE
);
296 c
= *(p
++) & (0xFFFFFFFF - MOD_CURSOR
* 256);
305 if (c
>= 0 && c
<= 255)
308 if (is_printable (c
)) {
311 *(p
++) |= (256 * MOD_ABNORMAL
);
319 start_col_real
= start_col
= 0;
323 print_to_widget (edit
, row
, start_col
, start_col_real
, end_col
, line
);
326 #define key_pending(x) (!is_idle())
328 static void edit_draw_this_char (WEdit
* edit
, long curs
, long row
)
330 int b
= edit_bol (edit
, curs
);
331 edit_draw_this_line (edit
, b
, row
, 0, edit
->num_widget_columns
- 1);
334 /* cursor must be in screen for other than REDRAW_PAGE passed in force */
335 void render_edit_text (WEdit
* edit
, long start_row
, long start_column
, long end_row
,
338 long row
= 0, curs_row
;
339 static int prev_curs_row
= 0;
340 static int prev_start_col
= 0;
341 static long prev_curs
= 0;
342 static long prev_start
= -1;
344 int force
= edit
->force
;
347 CPushFont ("editor", 0);
350 * If the position of the page has not moved then we can draw the cursor
351 * character only. This will prevent line flicker when using arrow keys.
353 if ((!(force
& REDRAW_CHAR_ONLY
)) || (force
& REDRAW_PAGE
)) {
354 if (!(force
& REDRAW_IN_BOUNDS
)) { /* !REDRAW_IN_BOUNDS means to ignore bounds and redraw whole rows */
356 end_row
= edit
->num_widget_lines
- 1;
358 end_column
= edit
->num_widget_columns
- 1;
360 if (force
& REDRAW_PAGE
) {
362 b
= edit_move_forward (edit
, edit
->start_display
, start_row
, 0);
363 while (row
<= end_row
) {
364 if (key_pending (edit
))
366 edit_draw_this_line (edit
, b
, row
, start_column
, end_column
);
367 b
= edit_move_forward (edit
, b
, 1, 0);
371 curs_row
= edit
->curs_row
;
373 if (force
& REDRAW_BEFORE_CURSOR
) {
374 if (start_row
< curs_row
) {
375 long upto
= curs_row
- 1 <= end_row
? curs_row
- 1 : end_row
;
377 b
= edit
->start_display
;
378 while (row
<= upto
) {
379 if (key_pending (edit
))
381 edit_draw_this_line (edit
, b
, row
, start_column
, end_column
);
382 b
= edit_move_forward (edit
, b
, 1, 0);
386 /* if (force & REDRAW_LINE) ---> default */
387 b
= edit_bol (edit
, edit
->curs1
);
388 if (curs_row
>= start_row
&& curs_row
<= end_row
) {
389 if (key_pending (edit
))
391 edit_draw_this_line (edit
, b
, curs_row
, start_column
, end_column
);
393 if (force
& REDRAW_AFTER_CURSOR
) {
394 if (end_row
> curs_row
) {
395 row
= curs_row
+ 1 < start_row
? start_row
: curs_row
+ 1;
396 b
= edit_move_forward (edit
, b
, 1, 0);
397 while (row
<= end_row
) {
398 if (key_pending (edit
))
400 edit_draw_this_line (edit
, b
, row
, start_column
, end_column
);
401 b
= edit_move_forward (edit
, b
, 1, 0);
406 if (force
& REDRAW_LINE_ABOVE
&& curs_row
>= 1) {
408 b
= edit_move_backward (edit
, edit_bol (edit
, edit
->curs1
), 1);
409 if (row
>= start_row
&& row
<= end_row
) {
410 if (key_pending (edit
))
412 edit_draw_this_line (edit
, b
, row
, start_column
, end_column
);
415 if (force
& REDRAW_LINE_BELOW
&& row
< edit
->num_widget_lines
- 1) {
417 b
= edit_bol (edit
, edit
->curs1
);
418 b
= edit_move_forward (edit
, b
, 1, 0);
419 if (row
>= start_row
&& row
<= end_row
) {
420 if (key_pending (edit
))
422 edit_draw_this_line (edit
, b
, row
, start_column
, end_column
);
427 if (prev_curs_row
< edit
->curs_row
) { /* with the new text highlighting, we must draw from the top down */
428 edit_draw_this_char (edit
, prev_curs
, prev_curs_row
);
429 edit_draw_this_char (edit
, edit
->curs1
, edit
->curs_row
);
431 edit_draw_this_char (edit
, edit
->curs1
, edit
->curs_row
);
432 edit_draw_this_char (edit
, prev_curs
, prev_curs_row
);
438 prev_curs_row
= edit
->curs_row
;
439 prev_curs
= edit
->curs1
;
440 prev_start_col
= edit
->start_col
;
442 edit
->screen_modified
= 0;
443 prev_start
= edit
->start_line
;
448 void edit_render (WEdit
* edit
, int page
, int row_start
, int col_start
, int row_end
, int col_end
)
450 if (page
) /* if it was an expose event, 'page' would be set */
451 edit
->force
|= REDRAW_PAGE
| REDRAW_IN_BOUNDS
;
453 if (edit
->force
& REDRAW_COMPLETELY
)
454 redraw_labels (edit
->widget
.parent
, (Widget
*) edit
);
455 render_edit_text (edit
, row_start
, col_start
, row_end
, col_end
);
457 * edit->force != 0 means a key was pending and the redraw
458 * was halted, so next time we must redraw everything in case stuff
459 * was left undrawn from a previous key press.
462 edit
->force
|= REDRAW_PAGE
;
465 void edit_render_keypress (WEdit
* edit
)
467 edit_render (edit
, 0, 0, 0, 0, 0);