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
;
140 if (edit
->num_widget_lines
<= 0 || edit
->num_widget_columns
<= 0)
143 r_extreme
= EDIT_RIGHT_EXTREME
;
144 l_extreme
= EDIT_LEFT_EXTREME
;
145 b_extreme
= EDIT_BOTTOM_EXTREME
;
146 t_extreme
= EDIT_TOP_EXTREME
;
147 if (edit
->found_len
) {
148 b_extreme
= max (edit
->num_widget_lines
/ 4, b_extreme
);
149 t_extreme
= max (edit
->num_widget_lines
/ 4, t_extreme
);
151 if (b_extreme
+ t_extreme
+ 1 > edit
->num_widget_lines
) {
153 n
= b_extreme
+ t_extreme
;
154 b_extreme
= (b_extreme
* (edit
->num_widget_lines
- 1)) / n
;
155 t_extreme
= (t_extreme
* (edit
->num_widget_lines
- 1)) / n
;
157 if (l_extreme
+ r_extreme
+ 1 > edit
->num_widget_columns
) {
159 n
= l_extreme
+ t_extreme
;
160 l_extreme
= (l_extreme
* (edit
->num_widget_columns
- 1)) / n
;
161 r_extreme
= (r_extreme
* (edit
->num_widget_columns
- 1)) / n
;
163 p
= edit_get_col (edit
);
164 edit_update_curs_row (edit
);
165 outby
= p
+ edit
->start_col
- edit
->num_widget_columns
+ 1 + (r_extreme
+ edit
->found_len
);
167 edit_scroll_right (edit
, outby
);
168 outby
= l_extreme
- p
- edit
->start_col
;
170 edit_scroll_left (edit
, outby
);
172 outby
= p
- edit
->num_widget_lines
+ 1 + b_extreme
;
174 edit_scroll_downward (edit
, outby
);
175 outby
= t_extreme
- p
;
177 edit_scroll_upward (edit
, outby
);
178 edit_update_curs_row (edit
);
181 #define set_color(font) attrset (font)
183 #define edit_move(x,y) widget_move(edit, y, x);
185 static void print_to_widget (WEdit
* edit
, long row
, int start_col
, float start_col_real
, long end_col
, unsigned int line
[])
187 int x
= (float) start_col_real
+ EDIT_TEXT_HORIZONTAL_OFFSET
;
188 int x1
= start_col
+ EDIT_TEXT_HORIZONTAL_OFFSET
;
189 int y
= row
+ EDIT_TEXT_VERTICAL_OFFSET
;
191 set_color (EDITOR_NORMAL_COLOR
);
193 hline (' ', end_col
+ 1 - EDIT_TEXT_HORIZONTAL_OFFSET
- x1
);
195 edit_move (x
+ FONT_OFFSET_X
, y
+ FONT_OFFSET_Y
);
197 unsigned int *p
= line
;
203 textchar
= *p
& 0xFF;
205 if (!(style
& (0xFF - MOD_ABNORMAL
- MOD_CURSOR
)))
206 SLsmg_set_color ((*p
& 0x007F0000) >> 16);
208 if (style
& MOD_ABNORMAL
)
210 if (style
& MOD_HIGHLIGHTED
) {
211 set_color (EDITOR_BOLD_COLOR
);
212 } else if (style
& MOD_MARKED
) {
213 set_color (EDITOR_MARKED_COLOR
);
215 if (style
& MOD_UNDERLINED
) {
216 set_color (EDITOR_UNDERLINED_COLOR
);
218 if (style
& MOD_BOLD
) {
219 set_color (EDITOR_BOLD_COLOR
);
227 /* b is a pointer to the beginning of the line */
228 static void edit_draw_this_line (WEdit
* edit
, long b
, long row
, long start_col
, long end_col
)
230 static unsigned int line
[MAX_LINE_LEN
];
231 unsigned int *p
= line
;
232 long m1
= 0, m2
= 0, q
, c1
, c2
;
233 int col
, start_col_real
;
236 int i
, book_mark
= -1;
239 if (!book_mark_query (edit
, edit
->start_line
+ row
, &book_mark
))
243 edit_get_syntax_color (edit
, b
- 1, &fg
, &bg
);
244 q
= edit_move_forward3 (edit
, b
, start_col
- edit
->start_col
, 0);
245 start_col_real
= (col
= (int) edit_move_forward3 (edit
, b
, 0, q
)) + edit
->start_col
;
246 c1
= min (edit
->column1
, edit
->column2
);
247 c2
= max (edit
->column1
, edit
->column2
);
249 if (col
+ 16 > -edit
->start_col
) {
250 eval_marks (edit
, &m1
, &m2
);
252 if (row
<= edit
->total_lines
- edit
->start_line
) {
253 while (col
<= end_col
- edit
->start_col
) {
255 if (q
== edit
->curs1
)
256 *p
|= MOD_CURSOR
* 256;
257 if (q
>= m1
&& q
< m2
) {
258 if (column_highlighting
) {
260 x
= edit_move_forward3 (edit
, b
, 0, q
);
261 if (x
>= c1
&& x
< c2
)
262 *p
|= MOD_MARKED
* 256;
264 *p
|= MOD_MARKED
* 256;
266 if (q
== edit
->bracket
)
267 *p
|= MOD_BOLD
* 256;
268 if (q
>= edit
->found_start
&& q
< edit
->found_start
+ edit
->found_len
)
269 *p
|= MOD_HIGHLIGHTED
* 256;
270 c
= edit_get_byte (edit
, q
);
271 /* we don't use bg for mc - fg contains both */
272 if (book_mark
== -1) {
273 edit_get_syntax_color (edit
, q
, &fg
, &bg
);
276 *p
|= book_mark
<< 16;
281 col
= end_col
- edit
->start_col
+ 1; /* quit */
285 i
= TAB_SIZE
- ((int) col
% TAB_SIZE
);
287 c
= *(p
++) & (0xFFFFFFFF - MOD_CURSOR
* 256);
296 if (c
>= 0 && c
<= 255)
299 if (is_printable (c
)) {
303 *p
|= (256 * MOD_ABNORMAL
);
311 start_col_real
= start_col
= 0;
315 print_to_widget (edit
, row
, start_col
, start_col_real
, end_col
, line
);
318 #define key_pending(x) (!is_idle())
320 static void edit_draw_this_char (WEdit
* edit
, long curs
, long row
)
322 int b
= edit_bol (edit
, curs
);
323 edit_draw_this_line (edit
, b
, row
, 0, edit
->num_widget_columns
- 1);
326 /* cursor must be in screen for other than REDRAW_PAGE passed in force */
327 void render_edit_text (WEdit
* edit
, long start_row
, long start_column
, long end_row
,
330 long row
= 0, curs_row
;
331 static int prev_curs_row
= 0;
332 static int prev_start_col
= 0;
333 static long prev_curs
= 0;
334 static long prev_start
= -1;
336 int force
= edit
->force
;
339 CPushFont ("editor", 0);
342 * If the position of the page has not moved then we can draw the cursor
343 * character only. This will prevent line flicker when using arrow keys.
345 if ((!(force
& REDRAW_CHAR_ONLY
)) || (force
& REDRAW_PAGE
)) {
346 if (!(force
& REDRAW_IN_BOUNDS
)) { /* !REDRAW_IN_BOUNDS means to ignore bounds and redraw whole rows */
348 end_row
= edit
->num_widget_lines
- 1;
350 end_column
= edit
->num_widget_columns
- 1;
352 if (force
& REDRAW_PAGE
) {
354 b
= edit_move_forward (edit
, edit
->start_display
, start_row
, 0);
355 while (row
<= end_row
) {
356 if (key_pending (edit
))
358 edit_draw_this_line (edit
, b
, row
, start_column
, end_column
);
359 b
= edit_move_forward (edit
, b
, 1, 0);
363 curs_row
= edit
->curs_row
;
365 if (force
& REDRAW_BEFORE_CURSOR
) {
366 if (start_row
< curs_row
) {
367 long upto
= curs_row
- 1 <= end_row
? curs_row
- 1 : end_row
;
369 b
= edit
->start_display
;
370 while (row
<= upto
) {
371 if (key_pending (edit
))
373 edit_draw_this_line (edit
, b
, row
, start_column
, end_column
);
374 b
= edit_move_forward (edit
, b
, 1, 0);
378 /* if (force & REDRAW_LINE) ---> default */
379 b
= edit_bol (edit
, edit
->curs1
);
380 if (curs_row
>= start_row
&& curs_row
<= end_row
) {
381 if (key_pending (edit
))
383 edit_draw_this_line (edit
, b
, curs_row
, start_column
, end_column
);
385 if (force
& REDRAW_AFTER_CURSOR
) {
386 if (end_row
> curs_row
) {
387 row
= curs_row
+ 1 < start_row
? start_row
: curs_row
+ 1;
388 b
= edit_move_forward (edit
, b
, 1, 0);
389 while (row
<= end_row
) {
390 if (key_pending (edit
))
392 edit_draw_this_line (edit
, b
, row
, start_column
, end_column
);
393 b
= edit_move_forward (edit
, b
, 1, 0);
398 if (force
& REDRAW_LINE_ABOVE
&& curs_row
>= 1) {
400 b
= edit_move_backward (edit
, edit_bol (edit
, edit
->curs1
), 1);
401 if (row
>= start_row
&& row
<= end_row
) {
402 if (key_pending (edit
))
404 edit_draw_this_line (edit
, b
, row
, start_column
, end_column
);
407 if (force
& REDRAW_LINE_BELOW
&& row
< edit
->num_widget_lines
- 1) {
409 b
= edit_bol (edit
, edit
->curs1
);
410 b
= edit_move_forward (edit
, b
, 1, 0);
411 if (row
>= start_row
&& row
<= end_row
) {
412 if (key_pending (edit
))
414 edit_draw_this_line (edit
, b
, row
, start_column
, end_column
);
419 if (prev_curs_row
< edit
->curs_row
) { /* with the new text highlighting, we must draw from the top down */
420 edit_draw_this_char (edit
, prev_curs
, prev_curs_row
);
421 edit_draw_this_char (edit
, edit
->curs1
, edit
->curs_row
);
423 edit_draw_this_char (edit
, edit
->curs1
, edit
->curs_row
);
424 edit_draw_this_char (edit
, prev_curs
, prev_curs_row
);
430 prev_curs_row
= edit
->curs_row
;
431 prev_curs
= edit
->curs1
;
432 prev_start_col
= edit
->start_col
;
434 edit
->screen_modified
= 0;
435 prev_start
= edit
->start_line
;
440 void edit_set_space_width (int s
);
441 extern int option_long_whitespace
;
443 void edit_render (WEdit
* edit
, int page
, int row_start
, int col_start
, int row_end
, int col_end
)
445 if (page
) /* if it was an expose event, 'page' would be set */
446 edit
->force
|= REDRAW_PAGE
| REDRAW_IN_BOUNDS
;
448 if (edit
->force
& REDRAW_COMPLETELY
)
449 redraw_labels (edit
->widget
.parent
, (Widget
*) edit
);
450 render_edit_text (edit
, row_start
, col_start
, row_end
, col_end
);
452 * edit->force != 0 means a key was pending and the redraw
453 * was halted, so next time we must redraw everything in case stuff
454 * was left undrawn from a previous key press.
457 edit
->force
|= REDRAW_PAGE
;
460 void edit_render_keypress (WEdit
* edit
)
462 edit_render (edit
, 0, 0, 0, 0, 0);