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 extern int column_highlighting
;
36 static void status_string (WEdit
* edit
, char *s
, int w
, int fill
, int font_width
)
41 * If we are at the end of file, print <EOF>,
42 * otherwise print the current character as is (if printable),
43 * as decimal and as hex.
45 if (edit
->curs1
< edit
->last_byte
) {
46 unsigned char cur_byte
= edit_get_byte (edit
, edit
->curs1
);
47 g_snprintf (byte_str
, sizeof(byte_str
), "%c %3d 0x%02X",
48 is_printable(cur_byte
) ? cur_byte
: '.',
52 strcpy(byte_str
, "<EOF>");
55 /* The field lengths just prevent the status line from shortening too much */
57 "[%c%c%c%c] %2ld L:[%3ld+%2ld %3ld/%3ld] *(%-4ld/%4ldb)= %s",
58 edit
->mark1
!= edit
->mark2
? ( column_highlighting
? 'C' : 'B') : '-',
59 edit
->modified
? 'M' : '-',
60 edit
->macro_i
< 0 ? '-' : 'R',
61 edit
->overwrite
== 0 ? '-' : 'O',
62 edit
->curs_col
/ font_width
,
67 edit
->total_lines
+ 1,
74 /* how to get as much onto the status line as is numerically possible :) */
75 void edit_status (WEdit
* edit
)
79 w
= edit
->widget
.cols
- (edit
->have_frame
* 2);
84 attrset (SELECTED_COLOR
);
86 widget_move (edit
, edit
->have_frame
, edit
->have_frame
);
87 i
= w
> 24 ? 18 : w
- 6;
89 strcpy (s
, (char *) name_trunc (edit
->filename
? edit
->filename
: "", i
));
95 status_string (edit
, s
+ 20, t
, ' ', 1);
99 printw ("%-*s", w
, s
);
100 attrset (NORMAL_COLOR
);
104 /* result is boolean */
105 int cursor_in_screen (WEdit
* edit
, long row
)
107 if (row
< 0 || row
>= edit
->num_widget_lines
)
113 /* returns rows from the first displayed line to the cursor */
114 int cursor_from_display_top (WEdit
* edit
)
116 if (edit
->curs1
< edit
->start_display
)
117 return -edit_move_forward (edit
, edit
->curs1
, 0, edit
->start_display
);
119 return edit_move_forward (edit
, edit
->start_display
, 0, edit
->curs1
);
122 /* returns how far the cursor is out of the screen */
123 int cursor_out_of_screen (WEdit
* edit
)
125 int row
= cursor_from_display_top (edit
);
126 if (row
>= edit
->num_widget_lines
)
127 return row
- edit
->num_widget_lines
+ 1;
133 /* this scrolls the text so that cursor is on the screen */
134 void edit_scroll_screen_over_cursor (WEdit
* edit
)
138 int b_extreme
, t_extreme
, l_extreme
, r_extreme
;
139 r_extreme
= EDIT_RIGHT_EXTREME
;
140 l_extreme
= EDIT_LEFT_EXTREME
;
141 b_extreme
= EDIT_BOTTOM_EXTREME
;
142 t_extreme
= EDIT_TOP_EXTREME
;
143 if (edit
->found_len
) {
144 b_extreme
= max (edit
->num_widget_lines
/ 4, b_extreme
);
145 t_extreme
= max (edit
->num_widget_lines
/ 4, t_extreme
);
147 if (b_extreme
+ t_extreme
+ 1 > edit
->num_widget_lines
) {
149 n
= b_extreme
+ t_extreme
;
150 b_extreme
= (b_extreme
* (edit
->num_widget_lines
- 1)) / n
;
151 t_extreme
= (t_extreme
* (edit
->num_widget_lines
- 1)) / n
;
153 if (l_extreme
+ r_extreme
+ 1 > edit
->num_widget_columns
) {
155 n
= l_extreme
+ t_extreme
;
156 l_extreme
= (l_extreme
* (edit
->num_widget_columns
- 1)) / n
;
157 r_extreme
= (r_extreme
* (edit
->num_widget_columns
- 1)) / n
;
159 p
= edit_get_col (edit
);
160 edit_update_curs_row (edit
);
161 outby
= p
+ edit
->start_col
- edit
->num_widget_columns
+ 1 + (r_extreme
+ edit
->found_len
);
163 edit_scroll_right (edit
, outby
);
164 outby
= l_extreme
- p
- edit
->start_col
;
166 edit_scroll_left (edit
, outby
);
168 outby
= p
- edit
->num_widget_lines
+ 1 + b_extreme
;
170 edit_scroll_downward (edit
, outby
);
171 outby
= t_extreme
- p
;
173 edit_scroll_upward (edit
, outby
);
174 edit_update_curs_row (edit
);
177 #define set_color(font) attrset (font)
179 #define edit_move(x,y) widget_move(edit, y, x);
181 static void print_to_widget (WEdit
* edit
, long row
, int start_col
, float start_col_real
, long end_col
, unsigned int line
[])
183 int x
= (float) start_col_real
+ EDIT_TEXT_HORIZONTAL_OFFSET
;
184 int x1
= start_col
+ EDIT_TEXT_HORIZONTAL_OFFSET
;
185 int y
= row
+ EDIT_TEXT_VERTICAL_OFFSET
;
187 set_color (EDITOR_NORMAL_COLOR
);
189 hline (' ', end_col
+ 1 - EDIT_TEXT_HORIZONTAL_OFFSET
- x1
);
191 edit_move (x
+ FONT_OFFSET_X
, y
+ FONT_OFFSET_Y
);
193 unsigned int *p
= line
;
199 textchar
= *p
& 0xFF;
201 if (!(style
& (0xFF - MOD_ABNORMAL
- MOD_CURSOR
)))
202 SLsmg_set_color ((*p
& 0x007F0000) >> 16);
204 if (style
& MOD_ABNORMAL
)
206 if (style
& MOD_HIGHLIGHTED
) {
207 set_color (EDITOR_BOLD_COLOR
);
208 } else if (style
& MOD_MARKED
) {
209 set_color (EDITOR_MARKED_COLOR
);
211 if (style
& MOD_UNDERLINED
) {
212 set_color (EDITOR_UNDERLINED_COLOR
);
214 if (style
& MOD_BOLD
) {
215 set_color (EDITOR_BOLD_COLOR
);
223 /* b is a pointer to the beginning of the line */
224 static void edit_draw_this_line (WEdit
* edit
, long b
, long row
, long start_col
, long end_col
)
226 static unsigned int line
[MAX_LINE_LEN
];
227 unsigned int *p
= line
;
228 long m1
= 0, m2
= 0, q
, c1
, c2
;
229 int col
, start_col_real
;
232 int i
, book_mark
= -1;
235 if (!book_mark_query (edit
, edit
->start_line
+ row
, &book_mark
))
239 edit_get_syntax_color (edit
, b
- 1, &fg
, &bg
);
240 q
= edit_move_forward3 (edit
, b
, start_col
- edit
->start_col
, 0);
241 start_col_real
= (col
= (int) edit_move_forward3 (edit
, b
, 0, q
)) + edit
->start_col
;
242 c1
= min (edit
->column1
, edit
->column2
);
243 c2
= max (edit
->column1
, edit
->column2
);
245 if (col
+ 16 > -edit
->start_col
) {
246 eval_marks (edit
, &m1
, &m2
);
248 if (row
<= edit
->total_lines
- edit
->start_line
) {
249 while (col
<= end_col
- edit
->start_col
) {
251 if (q
== edit
->curs1
)
252 *p
|= MOD_CURSOR
* 256;
253 if (q
>= m1
&& q
< m2
) {
254 if (column_highlighting
) {
256 x
= edit_move_forward3 (edit
, b
, 0, q
);
257 if (x
>= c1
&& x
< c2
)
258 *p
|= MOD_MARKED
* 256;
260 *p
|= MOD_MARKED
* 256;
262 if (q
== edit
->bracket
)
263 *p
|= MOD_BOLD
* 256;
264 if (q
>= edit
->found_start
&& q
< edit
->found_start
+ edit
->found_len
)
265 *p
|= MOD_HIGHLIGHTED
* 256;
266 c
= edit_get_byte (edit
, q
);
267 /* we don't use bg for mc - fg contains both */
268 if (book_mark
== -1) {
269 edit_get_syntax_color (edit
, q
, &fg
, &bg
);
272 *p
|= book_mark
<< 16;
277 col
= end_col
- edit
->start_col
+ 1; /* quit */
281 i
= TAB_SIZE
- ((int) col
% TAB_SIZE
);
283 c
= *(p
++) & (0xFFFFFFFF - MOD_CURSOR
* 256);
292 if (c
>= 0 && c
<= 255)
295 if (is_printable (c
)) {
299 *p
|= (256 * MOD_ABNORMAL
);
307 start_col_real
= start_col
= 0;
311 print_to_widget (edit
, row
, start_col
, start_col_real
, end_col
, line
);
314 #define key_pending(x) (!is_idle())
316 static void edit_draw_this_char (WEdit
* edit
, long curs
, long row
)
318 int b
= edit_bol (edit
, curs
);
319 edit_draw_this_line (edit
, b
, row
, 0, edit
->num_widget_columns
- 1);
322 /* cursor must be in screen for other than REDRAW_PAGE passed in force */
323 void render_edit_text (WEdit
* edit
, long start_row
, long start_column
, long end_row
,
326 long row
= 0, curs_row
;
327 static int prev_curs_row
= 0;
328 static int prev_start_col
= 0;
329 static long prev_curs
= 0;
330 static long prev_start
= -1;
332 int force
= edit
->force
;
335 CPushFont ("editor", 0);
338 * If the position of the page has not moved then we can draw the cursor
339 * character only. This will prevent line flicker when using arrow keys.
341 if ((!(force
& REDRAW_CHAR_ONLY
)) || (force
& REDRAW_PAGE
)) {
342 if (!(force
& REDRAW_IN_BOUNDS
)) { /* !REDRAW_IN_BOUNDS means to ignore bounds and redraw whole rows */
344 end_row
= edit
->num_widget_lines
- 1;
346 end_column
= edit
->num_widget_columns
- 1;
348 if (force
& REDRAW_PAGE
) {
350 b
= edit_move_forward (edit
, edit
->start_display
, start_row
, 0);
351 while (row
<= end_row
) {
352 if (key_pending (edit
))
354 edit_draw_this_line (edit
, b
, row
, start_column
, end_column
);
355 b
= edit_move_forward (edit
, b
, 1, 0);
359 curs_row
= edit
->curs_row
;
361 if (force
& REDRAW_BEFORE_CURSOR
) {
362 if (start_row
< curs_row
) {
363 long upto
= curs_row
- 1 <= end_row
? curs_row
- 1 : end_row
;
365 b
= edit
->start_display
;
366 while (row
<= upto
) {
367 if (key_pending (edit
))
369 edit_draw_this_line (edit
, b
, row
, start_column
, end_column
);
370 b
= edit_move_forward (edit
, b
, 1, 0);
374 /* if (force & REDRAW_LINE) ---> default */
375 b
= edit_bol (edit
, edit
->curs1
);
376 if (curs_row
>= start_row
&& curs_row
<= end_row
) {
377 if (key_pending (edit
))
379 edit_draw_this_line (edit
, b
, curs_row
, start_column
, end_column
);
381 if (force
& REDRAW_AFTER_CURSOR
) {
382 if (end_row
> curs_row
) {
383 row
= curs_row
+ 1 < start_row
? start_row
: curs_row
+ 1;
384 b
= edit_move_forward (edit
, b
, 1, 0);
385 while (row
<= end_row
) {
386 if (key_pending (edit
))
388 edit_draw_this_line (edit
, b
, row
, start_column
, end_column
);
389 b
= edit_move_forward (edit
, b
, 1, 0);
394 if (force
& REDRAW_LINE_ABOVE
&& curs_row
>= 1) {
396 b
= edit_move_backward (edit
, edit_bol (edit
, edit
->curs1
), 1);
397 if (row
>= start_row
&& row
<= end_row
) {
398 if (key_pending (edit
))
400 edit_draw_this_line (edit
, b
, row
, start_column
, end_column
);
403 if (force
& REDRAW_LINE_BELOW
&& row
< edit
->num_widget_lines
- 1) {
405 b
= edit_bol (edit
, edit
->curs1
);
406 b
= edit_move_forward (edit
, b
, 1, 0);
407 if (row
>= start_row
&& row
<= end_row
) {
408 if (key_pending (edit
))
410 edit_draw_this_line (edit
, b
, row
, start_column
, end_column
);
415 if (prev_curs_row
< edit
->curs_row
) { /* with the new text highlighting, we must draw from the top down */
416 edit_draw_this_char (edit
, prev_curs
, prev_curs_row
);
417 edit_draw_this_char (edit
, edit
->curs1
, edit
->curs_row
);
419 edit_draw_this_char (edit
, edit
->curs1
, edit
->curs_row
);
420 edit_draw_this_char (edit
, prev_curs
, prev_curs_row
);
426 prev_curs_row
= edit
->curs_row
;
427 prev_curs
= edit
->curs1
;
428 prev_start_col
= edit
->start_col
;
430 edit
->screen_modified
= 0;
431 prev_start
= edit
->start_line
;
436 void edit_set_space_width (int s
);
437 extern int option_long_whitespace
;
439 void edit_render (WEdit
* edit
, int page
, int row_start
, int col_start
, int row_end
, int col_end
)
442 if (page
) /* if it was an expose event, 'page' would be set */
443 edit
->force
|= REDRAW_PAGE
| REDRAW_IN_BOUNDS
;
444 f
= edit
->force
& (REDRAW_PAGE
| REDRAW_COMPLETELY
);
446 if (edit
->force
& REDRAW_COMPLETELY
)
447 redraw_labels (edit
->widget
.parent
, (Widget
*) edit
);
448 render_edit_text (edit
, row_start
, col_start
, row_end
, col_end
);
450 * edit->force != 0 means a key was pending and the redraw
451 * was halted, so next time we must redraw everything in case stuff
452 * was left undrawn from a previous key press.
455 edit
->force
|= REDRAW_PAGE
;
458 void edit_render_keypress (WEdit
* edit
)
460 edit_render (edit
, 0, 0, 0, 0, 0);