1 /* editor text drawing.
3 Copyright (C) 1996, 1997 the Free Software Foundation
5 Authors: 1996, 1997 Paul Sheer
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */
24 #define MAX_LINE_LEN 1024
28 #include "coollocal.h"
30 #include "../src/mad.h"
34 static void status_string (WEdit
* edit
, char *s
, int w
, int fill
, int font_width
)
37 char t
[160]; /* 160 just to be sure */
38 /* The field lengths just prevents the status line from shortening to much */
39 sprintf (t
, "[%c%c%c%c] %2ld:%3ld+%2ld=%3ld/%3ld - *%-4ld/%4ldb=%3d",
40 edit
->mark1
!= edit
->mark2
? 'B' : '-',
41 edit
->modified
? 'M' : '-', edit
->macro_i
< 0 ? '-' : 'R',
42 edit
->overwrite
== 0 ? '-' : 'O',
43 edit
->curs_col
/ font_width
, edit
->start_line
+ 1, edit
->curs_row
,
44 edit
->curs_line
+ 1, edit
->total_lines
+ 1, edit
->curs1
,
45 edit
->last_byte
, edit
->curs1
< edit
->last_byte
46 ? edit_get_byte (edit
, edit
->curs1
) : -1);
47 sprintf (s
, "%.*s", w
+ 1, t
);
52 if (strchr (" +-*=/:b", s
[i
])) /* chop off the last word/number */
63 /* how to get as much onto the status line as is numerically possible :) */
64 void edit_status (WEdit
* edit
)
68 w
= edit
->widget
.cols
- (edit
->have_frame
* 2);
73 attrset (SELECTED_COLOR
);
75 widget_move (edit
, edit
->have_frame
, edit
->have_frame
);
76 i
= w
> 24 ? 18 : w
- 6;
78 sprintf (s
, "%s", name_trunc (edit
->filename
? edit
->filename
: "", i
));
84 status_string (edit
, s
+ 20, t
, ' ', 1);
88 printw ("%.*s", w
, s
);
90 attrset (NORMAL_COLOR
);
96 extern int fixed_font
;
98 void rerender_text (CWidget
* wdt
);
100 void edit_status (WEdit
* edit
)
102 if ((edit
->widget
->options
& EDITOR_NO_TEXT
)) {
109 w
= edit
->num_widget_columns
- 1;
116 i
= w
> 24 ? 18 : w
- 6;
118 sprintf (s
, "%s", name_trunc (edit
->filename
? edit
->filename
: "", i
));
125 status_string (edit
, s
+ i
+ 2, t
, 0, FONT_MEAN_WIDTH
);
128 strcpy (id
, edit
->widget
->ident
);
129 strcat (id
, ".text");
132 wdt
->text
= strdup (s
);
133 CSetWidgetSize (id
, edit
->widget
->width
, wdt
->height
);
143 int cursor_in_screen (WEdit
* edit
, long row
)
145 if (row
< 0 || row
>= edit
->num_widget_lines
)
151 /* returns rows from the first displayed line to the cursor */
152 int cursor_from_display_top (WEdit
* edit
)
154 if (edit
->curs1
< edit
->start_display
)
155 return -edit_move_forward (edit
, edit
->curs1
, 0, edit
->start_display
);
157 return edit_move_forward (edit
, edit
->start_display
, 0, edit
->curs1
);
160 /* returns how far the cursor is out of the screen */
161 int cursor_out_of_screen (WEdit
* edit
)
163 int row
= cursor_from_display_top (edit
);
164 if (row
>= edit
->num_widget_lines
)
165 return row
- edit
->num_widget_lines
+ 1;
172 extern unsigned char per_char
[256];
173 int edit_width_of_long_printable (int c
);
176 /* this scrolls the text so that cursor is on the screen */
177 void edit_scroll_screen_over_cursor (WEdit
* edit
)
181 p
= edit_get_col (edit
);
182 edit_update_curs_row (edit
);
184 outby
= p
+ edit
->start_col
- edit
->num_widget_columns
+ 1 + (EDIT_RIGHT_EXTREME
+ edit
->found_len
);
186 outby
= p
+ edit
->start_col
- edit
->widget
->width
+ 7 + (EDIT_RIGHT_EXTREME
+ edit
->found_len
) * FONT_MEAN_WIDTH
+ edit_width_of_long_printable (edit_get_byte (edit
, edit
->curs1
));
189 edit_scroll_right (edit
, outby
);
191 outby
= EDIT_LEFT_EXTREME
- p
- edit
->start_col
;
193 outby
= EDIT_LEFT_EXTREME
* FONT_MEAN_WIDTH
- p
- edit
->start_col
;
196 edit_scroll_left (edit
, outby
);
199 if (edit
->found_len
!= 0)
200 l
= edit
->num_widget_lines
/ 5;
201 outby
= p
- edit
->num_widget_lines
+ 1 + EDIT_BOTTOM_EXTREME
+ l
;
203 edit_scroll_downward (edit
, outby
);
204 outby
= EDIT_TOP_EXTREME
- p
+ l
;
206 edit_scroll_upward (edit
, outby
);
207 edit_update_curs_row (edit
);
213 #define CACHE_WIDTH 256
214 #define CACHE_HEIGHT 128
216 int EditExposeRedraw
= 0;
219 /* background colors: marked is refers to mouse highlighting, highlighted refers to a found string. */
220 unsigned long edit_abnormal_color
, edit_marked_abnormal_color
;
221 unsigned long edit_highlighted_color
, edit_marked_color
;
222 unsigned long edit_normal_background_color
;
224 /* foreground colors */
225 unsigned long edit_normal_foreground_color
, edit_bold_color
;
226 unsigned long edit_italic_color
;
229 unsigned long edit_cursor_color
;
231 void edit_set_foreground_colors (unsigned long normal
, unsigned long bold
, unsigned long italic
)
233 edit_normal_foreground_color
= normal
;
234 edit_bold_color
= bold
;
235 edit_italic_color
= italic
;
238 void edit_set_background_colors (unsigned long normal
, unsigned long abnormal
, unsigned long marked
, unsigned long marked_abnormal
, unsigned long highlighted
)
240 edit_abnormal_color
= abnormal
;
241 edit_marked_abnormal_color
= marked_abnormal
;
242 edit_marked_color
= marked
;
243 edit_highlighted_color
= highlighted
;
244 edit_normal_background_color
= normal
;
247 void edit_set_cursor_color (unsigned long c
)
249 edit_cursor_color
= c
;
254 #define BOLD_COLOR MARKED_COLOR
255 #define UNDERLINE_COLOR VIEW_UNDERLINED_COLOR
256 #define MARK_COLOR SELECTED_COLOR
257 #define DEF_COLOR NORMAL_COLOR
259 static void set_color (int font
)
264 #define edit_move(x,y) widget_move(edit, y, x);
266 static void print_to_widget (WEdit
* edit
, long row
, int start_col
, float start_col_real
, long end_col
, unsigned int line
[])
268 int x
= (float) start_col_real
+ EDIT_TEXT_HORIZONTAL_OFFSET
;
269 int x1
= start_col
+ EDIT_TEXT_HORIZONTAL_OFFSET
;
270 int y
= row
+ EDIT_TEXT_VERTICAL_OFFSET
;
272 set_color (DEF_COLOR
);
274 hline (' ', end_col
+ 1 - EDIT_TEXT_HORIZONTAL_OFFSET
- x1
);
276 edit_move (x
+ FONT_OFFSET_X
, y
+ FONT_OFFSET_Y
);
278 unsigned int *p
= line
;
284 textchar
= *p
& 0xFF;
286 if (!(style
& (0xFF - MOD_ABNORMAL
- MOD_CURSOR
)))
287 SLsmg_set_color ((*p
& 0x007F0000) >> 16);
289 if (style
& MOD_ABNORMAL
)
291 if (style
& MOD_HIGHLIGHTED
) {
292 set_color (BOLD_COLOR
);
293 } else if (style
& MOD_MARKED
) {
294 set_color (MARK_COLOR
);
296 if (style
& MOD_UNDERLINED
) {
297 set_color (UNDERLINE_COLOR
);
299 if (style
& MOD_BOLD
) {
300 set_color (BOLD_COLOR
);
308 /* b pointer to begining of line */
309 static void edit_draw_this_line (WEdit
* edit
, long b
, long row
, long start_col
, long end_col
)
311 static unsigned int line
[MAX_LINE_LEN
];
312 unsigned int *p
= line
;
313 long m1
= 0, m2
= 0, q
;
314 int col
, start_col_real
;
319 edit_get_syntax_color (edit
, b
- 1, &fg
, &bg
);
320 q
= edit_move_forward3 (edit
, b
, start_col
- edit
->start_col
, 0);
321 start_col_real
= (col
= (int) edit_move_forward3 (edit
, b
, 0, q
)) + edit
->start_col
;
323 if (col
+ 16 > -edit
->start_col
) {
324 eval_marks (edit
, &m1
, &m2
);
326 if (row
<= edit
->total_lines
- edit
->start_line
) {
327 while (col
<= end_col
- edit
->start_col
) {
329 if (q
== edit
->curs1
)
330 *p
|= MOD_CURSOR
* 256;
331 if (q
>= m1
&& q
< m2
)
332 *p
|= MOD_MARKED
* 256;
333 if (q
== edit
->bracket
)
334 *p
|= MOD_BOLD
* 256;
335 if (q
>= edit
->found_start
&& q
< edit
->found_start
+ edit
->found_len
)
336 *p
|= MOD_HIGHLIGHTED
* 256;
337 c
= edit_get_byte (edit
, q
);
338 edit_get_syntax_color (edit
, q
, &fg
, &bg
);
339 /* we don't use bg for mc - fg contains both */
344 col
= end_col
- edit
->start_col
+ 1; /* quit */
348 i
= TAB_SIZE
- ((int) col
% TAB_SIZE
);
350 c
= *(p
++) & (0xFFFFFFFF - MOD_CURSOR
* 256);
358 if (is_printable (c
)) {
362 *p
|= (256 * MOD_ABNORMAL
);
370 start_col_real
= start_col
= 0;
374 print_to_widget (edit
, row
, start_col
, start_col_real
, end_col
, line
);
381 #define key_pending(x) (!is_idle())
385 int edit_mouse_pending (Window win
);
386 #define edit_draw_this_line edit_draw_this_line_proportional
388 static int key_pending (WEdit
* edit
)
390 if (!(edit
->force
& REDRAW_COMPLETELY
) && !EditExposeRedraw
)
391 return CKeyPending ();
398 /* b for pointer to begining of line */
399 static void edit_draw_this_char (WEdit
* edit
, long curs
, long row
)
401 int b
= edit_bol (edit
, curs
);
403 edit_draw_this_line (edit
, b
, row
, 0, edit
->num_widget_columns
- 1);
405 edit_draw_this_line (edit
, b
, row
, 0, edit
->widget
->width
);
409 /* cursor must be in screen for other than REDRAW_PAGE passed in force */
410 void render_edit_text (WEdit
* edit
, long start_row
, long start_column
, long end_row
, long end_column
)
412 long row
= 0, curs_row
;
413 static int prev_curs_row
= 0;
414 static long prev_start_display
= 0;
415 static int prev_start_col
= 0;
416 static long prev_curs
= 0;
419 static Window prev_win
= 0;
423 int force
= edit
->force
;
427 if the position of the page has not moved then we can draw the cursor character only.
428 This will prevent line flicker when using arrow keys.
430 if ((!(force
& REDRAW_CHAR_ONLY
)) || (force
& REDRAW_PAGE
)
432 || prev_win
!= edit
->widget
->winid
435 if (!(force
& REDRAW_IN_BOUNDS
)) { /* !REDRAW_IN_BOUNDS means to ignore bounds and redraw whole rows */
437 end_row
= edit
->num_widget_lines
- 1;
440 end_column
= edit
->num_widget_columns
- 1;
442 end_column
= edit
->widget
->width
;
445 if (force
& REDRAW_PAGE
) {
447 b
= edit_move_forward (edit
, edit
->start_display
, start_row
, 0);
448 while (row
<= end_row
) {
449 if (key_pending (edit
))
451 edit_draw_this_line (edit
, b
, row
, start_column
, end_column
);
452 b
= edit_move_forward (edit
, b
, 1, 0);
456 curs_row
= edit
->curs_row
;
458 if (force
& REDRAW_BEFORE_CURSOR
) {
459 if (start_row
< curs_row
) {
460 long upto
= curs_row
- 1 <= end_row
? curs_row
- 1 : end_row
;
462 b
= edit
->start_display
;
463 while (row
<= upto
) {
464 if (key_pending (edit
))
466 edit_draw_this_line (edit
, b
, row
, start_column
, end_column
);
467 b
= edit_move_forward (edit
, b
, 1, 0);
471 /* if (force & REDRAW_LINE) { ---> default */
472 b
= edit_bol (edit
, edit
->curs1
);
473 if (curs_row
>= start_row
&& curs_row
<= end_row
) {
474 if (key_pending (edit
))
476 edit_draw_this_line (edit
, b
, curs_row
, start_column
, end_column
);
478 if (force
& REDRAW_AFTER_CURSOR
) {
479 if (end_row
> curs_row
) {
480 row
= curs_row
+ 1 < start_row
? start_row
: curs_row
+ 1;
481 b
= edit_move_forward (edit
, b
, 1, 0);
482 while (row
<= end_row
) {
483 if (key_pending (edit
))
485 edit_draw_this_line (edit
, b
, row
, start_column
, end_column
);
486 b
= edit_move_forward (edit
, b
, 1, 0);
491 if (force
& REDRAW_LINE_ABOVE
&& curs_row
>= 1) {
493 b
= edit_move_backward (edit
, edit_bol (edit
, edit
->curs1
), 1);
494 if (row
>= start_row
&& row
<= end_row
) {
495 if (key_pending (edit
))
497 edit_draw_this_line (edit
, b
, row
, start_column
, end_column
);
500 if (force
& REDRAW_LINE_BELOW
&& row
< edit
->num_widget_lines
- 1) {
502 b
= edit_bol (edit
, edit
->curs1
);
503 b
= edit_move_forward (edit
, b
, 1, 0);
504 if (row
>= start_row
&& row
<= end_row
) {
505 if (key_pending (edit
))
507 edit_draw_this_line (edit
, b
, row
, start_column
, end_column
);
512 if (prev_curs_row
< edit
->curs_row
) { /* with the new text highlighting, we must draw from the top down */
513 edit_draw_this_char (edit
, prev_curs
, prev_curs_row
);
514 edit_draw_this_char (edit
, edit
->curs1
, edit
->curs_row
);
516 edit_draw_this_char (edit
, edit
->curs1
, edit
->curs_row
);
517 edit_draw_this_char (edit
, prev_curs
, prev_curs_row
);
523 prev_curs_row
= edit
->curs_row
;
524 prev_curs
= edit
->curs1
;
525 prev_start_display
= edit
->start_display
;
526 prev_start_col
= edit
->start_col
;
528 prev_win
= edit
->widget
->winid
;
531 edit_get_syntax_color (edit
, edit
->start_display
- 1, &fg
, &bg
);
538 void edit_convert_expose_to_area (XExposeEvent
* xexpose
, int *row1
, int *col1
, int *row2
, int *col2
)
540 *col1
= xexpose
->x
- EDIT_TEXT_HORIZONTAL_OFFSET
;
541 *row1
= (xexpose
->y
- EDIT_TEXT_VERTICAL_OFFSET
) / FONT_PIX_PER_LINE
;
542 *col2
= xexpose
->x
+ xexpose
->width
+ EDIT_TEXT_HORIZONTAL_OFFSET
+ 3;
543 *row2
= (xexpose
->y
+ xexpose
->height
- EDIT_TEXT_VERTICAL_OFFSET
) / FONT_PIX_PER_LINE
;
546 void edit_render_tidbits (CWidget
* wdt
)
549 int w
= wdt
->width
, h
= wdt
->height
;
553 isfocussed
= (win
== CGetFocus ());
555 CSetColor (COLOR_FLAT
);
558 render_bevel (win
, 0, 0, w
- 1, h
- 1, 3, 1); /*most outer border bevel */
560 render_bevel (win
, 2, 2, w
- 3, h
- 3, 1, 1); /*border bevel */
561 render_bevel (win
, 0, 0, w
- 1, h
- 1, 2, 0); /*most outer border bevel */
565 void edit_set_space_width (int s
);
566 extern int option_long_whitespace
;
570 void edit_render (WEdit
* edit
, int page
, int row_start
, int col_start
, int row_end
, int col_end
)
573 if (page
) /* if it was an expose event, 'page' would be set */
574 edit
->force
|= REDRAW_PAGE
| REDRAW_IN_BOUNDS
;
575 f
= edit
->force
& (REDRAW_PAGE
| REDRAW_COMPLETELY
);
578 if (edit
->force
& REDRAW_COMPLETELY
)
579 redraw_labels (edit
->widget
.parent
, (Widget
*) edit
);
581 if (option_long_whitespace
)
582 edit_set_space_width (per_char
[' '] * 2);
584 edit_set_space_width (per_char
[' ']);
585 edit_set_foreground_colors (
586 color_palette (option_editor_fg_normal
),
587 color_palette (option_editor_fg_bold
),
588 color_palette (option_editor_fg_italic
)
590 edit_set_background_colors (
591 color_palette (option_editor_bg_normal
),
592 color_palette (option_editor_bg_abnormal
),
593 color_palette (option_editor_bg_marked
),
594 color_palette (option_editor_bg_marked_abnormal
),
595 color_palette (option_editor_bg_highlighted
)
597 edit_set_cursor_color (
598 color_palette (option_editor_fg_cursor
)
601 if (!EditExposeRedraw
)
602 set_cursor_position (0, 0, 0, 0, 0, 0, 0, 0, 0);
605 render_edit_text (edit
, row_start
, col_start
, row_end
, col_end
);
606 if (edit
->force
) /* edit->force != 0 means a key was pending and the redraw
607 was halted, so next time we must redraw everything in case stuff
608 was left undrawn from a previous key press */
609 edit
->force
|= REDRAW_PAGE
;
612 edit_render_tidbits (edit
->widget
);
613 CSetColor (edit_normal_background_color
);
614 CLine (edit
->widget
->winid
, 3, 3, 3, edit
->widget
->height
- 4);
620 void edit_render_expose (WEdit
* edit
, XExposeEvent
* xexpose
)
622 int row_start
, col_start
, row_end
, col_end
;
623 EditExposeRedraw
= 1;
624 edit
->num_widget_lines
= (edit
->widget
->height
- 6) / FONT_PIX_PER_LINE
;
625 edit
->num_widget_columns
= (edit
->widget
->width
- 7) / FONT_MEAN_WIDTH
;
626 if (edit
->force
& (REDRAW_PAGE
| REDRAW_COMPLETELY
)) {
627 edit
->force
|= REDRAW_PAGE
| REDRAW_COMPLETELY
;
628 edit_render_keypress (edit
);
630 edit_convert_expose_to_area (xexpose
, &row_start
, &col_start
, &row_end
, &col_end
);
631 edit_render (edit
, 1, row_start
, col_start
, row_end
, col_end
);
633 EditExposeRedraw
= 0;
636 void edit_render_keypress (WEdit
* edit
)
638 edit_render (edit
, 0, 0, 0, 0, 0);
643 void edit_render_keypress (WEdit
* edit
)
645 edit_render (edit
, 0, 0, 0, 0, 0);