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
29 #include "coollocal.h"
32 #include "../src/mad.h"
35 extern int column_highlighting
;
37 void status_string (WEdit
* edit
, char *s
, int w
, int fill
, int font_width
)
40 char t
[160]; /* 160 just to be sure */
41 /* The field lengths just prevents the status line from shortening to much */
42 sprintf (t
, "[%c%c%c%c] %2ld:%3ld+%2ld=%3ld/%3ld - *%-4ld/%4ldb=%3d",
43 edit
->mark1
!= edit
->mark2
? ( column_highlighting
? 'C' : 'B') : '-',
44 edit
->modified
? 'M' : '-', edit
->macro_i
< 0 ? '-' : 'R',
45 edit
->overwrite
== 0 ? '-' : 'O',
46 edit
->curs_col
/ font_width
, edit
->start_line
+ 1, edit
->curs_row
,
47 edit
->curs_line
+ 1, edit
->total_lines
+ 1, edit
->curs1
,
48 edit
->last_byte
, edit
->curs1
< edit
->last_byte
49 ? edit_get_byte (edit
, edit
->curs1
) : -1);
50 sprintf (s
, "%.*s", w
+ 1, t
);
55 if (strchr (" +-*=/:b", s
[i
])) /* chop off the last word/number */
66 /* how to get as much onto the status line as is numerically possible :) */
67 void edit_status (WEdit
* edit
)
71 w
= edit
->widget
.cols
- (edit
->have_frame
* 2);
76 attrset (SELECTED_COLOR
);
78 widget_move (edit
, edit
->have_frame
, edit
->have_frame
);
79 i
= w
> 24 ? 18 : w
- 6;
81 sprintf (s
, "%s", (char *) name_trunc (edit
->filename
? edit
->filename
: "", i
));
87 status_string (edit
, s
+ 20, t
, ' ', 1);
91 printw ("%.*s", w
, s
);
92 attrset (NORMAL_COLOR
);
99 extern int fixed_font
;
102 void rerender_text (CWidget
* wdt
);
106 void edit_status (WEdit
* edit
)
113 w
= edit
->num_widget_columns
- 1;
120 i
= w
> 24 ? 18 : w
- 6;
122 sprintf (s
, "%s", name_trunc (edit
->filename
? edit
->filename
: "", i
));
129 status_string (edit
, s
+ i
+ 2, t
, 0, FONT_MEAN_WIDTH
);
132 entry
= GTK_ENTRY (edit
->widget
->status
);
133 if (strcmp (s
, gtk_entry_get_text (entry
)))
134 gtk_entry_set_text (entry
, s
);
139 void edit_status (WEdit
* edit
)
141 if ((COptionsOf (edit
->widget
) & EDITOR_NO_TEXT
)) {
148 w
= edit
->num_widget_columns
- 1;
155 i
= w
> 24 ? 18 : w
- 6;
157 sprintf (s
, "%s", name_trunc (edit
->filename
? edit
->filename
: "", i
));
164 status_string (edit
, s
+ i
+ 2, t
, 0, FONT_MEAN_WIDTH
);
167 strcpy (id
, CIdentOf (edit
->widget
));
168 strcat (id
, ".text");
171 wdt
->text
= strdup (s
);
172 CSetWidgetSize (id
, CWidthOf (edit
->widget
), CHeightOf (wdt
));
183 int cursor_in_screen (WEdit
* edit
, long row
)
185 if (row
< 0 || row
>= edit
->num_widget_lines
)
191 /* returns rows from the first displayed line to the cursor */
192 int cursor_from_display_top (WEdit
* edit
)
194 if (edit
->curs1
< edit
->start_display
)
195 return -edit_move_forward (edit
, edit
->curs1
, 0, edit
->start_display
);
197 return edit_move_forward (edit
, edit
->start_display
, 0, edit
->curs1
);
200 /* returns how far the cursor is out of the screen */
201 int cursor_out_of_screen (WEdit
* edit
)
203 int row
= cursor_from_display_top (edit
);
204 if (row
>= edit
->num_widget_lines
)
205 return row
- edit
->num_widget_lines
+ 1;
212 extern unsigned char per_char
[256];
213 int edit_width_of_long_printable (int c
);
216 /* this scrolls the text so that cursor is on the screen */
217 void edit_scroll_screen_over_cursor (WEdit
* edit
)
221 p
= edit_get_col (edit
);
222 edit_update_curs_row (edit
);
224 outby
= p
+ edit
->start_col
- edit
->num_widget_columns
+ 1 + (EDIT_RIGHT_EXTREME
+ edit
->found_len
);
226 outby
= p
+ edit
->start_col
- CWidthOf (edit
->widget
) + 7 + (EDIT_RIGHT_EXTREME
+ edit
->found_len
) * FONT_MEAN_WIDTH
+ edit_width_of_long_printable (edit_get_byte (edit
, edit
->curs1
));
229 edit_scroll_right (edit
, outby
);
231 outby
= EDIT_LEFT_EXTREME
- p
- edit
->start_col
;
233 outby
= EDIT_LEFT_EXTREME
* FONT_MEAN_WIDTH
- p
- edit
->start_col
;
236 edit_scroll_left (edit
, outby
);
239 if (edit
->found_len
!= 0)
240 l
= edit
->num_widget_lines
/ 5;
241 outby
= p
- edit
->num_widget_lines
+ 1 + EDIT_BOTTOM_EXTREME
+ l
;
243 edit_scroll_downward (edit
, outby
);
244 outby
= EDIT_TOP_EXTREME
- p
+ l
;
246 edit_scroll_upward (edit
, outby
);
247 edit_update_curs_row (edit
);
253 #define CACHE_WIDTH 256
254 #define CACHE_HEIGHT 128
256 int EditExposeRedraw
= 0;
259 /* background colors: marked is refers to mouse highlighting, highlighted refers to a found string. */
260 unsigned long edit_abnormal_color
, edit_marked_abnormal_color
;
261 unsigned long edit_highlighted_color
, edit_marked_color
;
262 unsigned long edit_normal_background_color
;
264 /* foreground colors */
265 unsigned long edit_normal_foreground_color
, edit_bold_color
;
266 unsigned long edit_italic_color
;
269 unsigned long edit_cursor_color
;
271 void edit_set_foreground_colors (unsigned long normal
, unsigned long bold
, unsigned long italic
)
273 edit_normal_foreground_color
= normal
;
274 edit_bold_color
= bold
;
275 edit_italic_color
= italic
;
278 void edit_set_background_colors (unsigned long normal
, unsigned long abnormal
, unsigned long marked
, unsigned long marked_abnormal
, unsigned long highlighted
)
280 edit_abnormal_color
= abnormal
;
281 edit_marked_abnormal_color
= marked_abnormal
;
282 edit_marked_color
= marked
;
283 edit_highlighted_color
= highlighted
;
284 edit_normal_background_color
= normal
;
287 void edit_set_cursor_color (unsigned long c
)
289 edit_cursor_color
= c
;
294 #define BOLD_COLOR MARKED_COLOR
295 #define UNDERLINE_COLOR VIEW_UNDERLINED_COLOR
296 #define MARK_COLOR SELECTED_COLOR
297 #define DEF_COLOR NORMAL_COLOR
299 static void set_color (int font
)
304 #define edit_move(x,y) widget_move(edit, y, x);
306 static void print_to_widget (WEdit
* edit
, long row
, int start_col
, float start_col_real
, long end_col
, unsigned int line
[])
308 int x
= (float) start_col_real
+ EDIT_TEXT_HORIZONTAL_OFFSET
;
309 int x1
= start_col
+ EDIT_TEXT_HORIZONTAL_OFFSET
;
310 int y
= row
+ EDIT_TEXT_VERTICAL_OFFSET
;
312 set_color (DEF_COLOR
);
314 hline (' ', end_col
+ 1 - EDIT_TEXT_HORIZONTAL_OFFSET
- x1
);
316 edit_move (x
+ FONT_OFFSET_X
, y
+ FONT_OFFSET_Y
);
318 unsigned int *p
= line
;
324 textchar
= *p
& 0xFF;
326 if (!(style
& (0xFF - MOD_ABNORMAL
- MOD_CURSOR
)))
327 SLsmg_set_color ((*p
& 0x007F0000) >> 16);
329 if (style
& MOD_ABNORMAL
)
331 if (style
& MOD_HIGHLIGHTED
) {
332 set_color (BOLD_COLOR
);
333 } else if (style
& MOD_MARKED
) {
334 set_color (MARK_COLOR
);
336 if (style
& MOD_UNDERLINED
) {
337 set_color (UNDERLINE_COLOR
);
339 if (style
& MOD_BOLD
) {
340 set_color (BOLD_COLOR
);
348 /* b pointer to begining of line */
349 static void edit_draw_this_line (WEdit
* edit
, long b
, long row
, long start_col
, long end_col
)
351 static unsigned int line
[MAX_LINE_LEN
];
352 unsigned int *p
= line
;
353 long m1
= 0, m2
= 0, q
, c1
, c2
;
354 int col
, start_col_real
;
359 edit_get_syntax_color (edit
, b
- 1, &fg
, &bg
);
360 q
= edit_move_forward3 (edit
, b
, start_col
- edit
->start_col
, 0);
361 start_col_real
= (col
= (int) edit_move_forward3 (edit
, b
, 0, q
)) + edit
->start_col
;
362 c1
= min (edit
->column1
, edit
->column2
);
363 c2
= max (edit
->column1
, edit
->column2
);
365 if (col
+ 16 > -edit
->start_col
) {
366 eval_marks (edit
, &m1
, &m2
);
368 if (row
<= edit
->total_lines
- edit
->start_line
) {
369 while (col
<= end_col
- edit
->start_col
) {
371 if (q
== edit
->curs1
)
372 *p
|= MOD_CURSOR
* 256;
373 if (q
>= m1
&& q
< m2
) {
374 if (column_highlighting
) {
376 x
= edit_move_forward3 (edit
, b
, 0, q
);
377 if (x
>= c1
&& x
< c2
)
378 *p
|= MOD_MARKED
* 256;
380 *p
|= MOD_MARKED
* 256;
382 if (q
== edit
->bracket
)
383 *p
|= MOD_BOLD
* 256;
384 if (q
>= edit
->found_start
&& q
< edit
->found_start
+ edit
->found_len
)
385 *p
|= MOD_HIGHLIGHTED
* 256;
386 c
= edit_get_byte (edit
, q
);
387 edit_get_syntax_color (edit
, q
, &fg
, &bg
);
388 /* we don't use bg for mc - fg contains both */
393 col
= end_col
- edit
->start_col
+ 1; /* quit */
397 i
= TAB_SIZE
- ((int) col
% TAB_SIZE
);
399 c
= *(p
++) & (0xFFFFFFFF - MOD_CURSOR
* 256);
407 if (is_printable (c
)) {
411 *p
|= (256 * MOD_ABNORMAL
);
419 start_col_real
= start_col
= 0;
423 print_to_widget (edit
, row
, start_col
, start_col_real
, end_col
, line
);
430 #define key_pending(x) (!is_idle())
434 int edit_mouse_pending (Window win
);
435 #define edit_draw_this_line edit_draw_this_line_proportional
437 static int key_pending (WEdit
* edit
)
442 if (!(edit
->force
& REDRAW_COMPLETELY
) && !EditExposeRedraw
)
443 return CKeyPending ();
451 /* b for pointer to begining of line */
452 static void edit_draw_this_char (WEdit
* edit
, long curs
, long row
)
454 int b
= edit_bol (edit
, curs
);
456 edit_draw_this_line (edit
, b
, row
, 0, edit
->num_widget_columns
- 1);
458 edit_draw_this_line (edit
, b
, row
, 0, CWidthOf (edit
->widget
));
462 /* cursor must be in screen for other than REDRAW_PAGE passed in force */
463 void render_edit_text (WEdit
* edit
, long start_row
, long start_column
, long end_row
, long end_column
)
465 long row
= 0, curs_row
;
466 static int prev_curs_row
= 0;
467 static int prev_start_col
= 0;
468 static long prev_curs
= 0;
471 static unsigned long prev_win
= 0;
473 int force
= edit
->force
;
477 if the position of the page has not moved then we can draw the cursor character only.
478 This will prevent line flicker when using arrow keys.
480 if ((!(force
& REDRAW_CHAR_ONLY
)) || (force
& REDRAW_PAGE
)
483 || prev_win
!= ((GdkWindowPrivate
*) CWindowOf (edit
->widget
)->text_area
)->xwindow
485 || prev_win
!= CWindowOf (edit
->widget
)
489 if (!(force
& REDRAW_IN_BOUNDS
)) { /* !REDRAW_IN_BOUNDS means to ignore bounds and redraw whole rows */
491 end_row
= edit
->num_widget_lines
- 1;
494 end_column
= edit
->num_widget_columns
- 1;
496 end_column
= CWidthOf (edit
->widget
);
499 if (force
& REDRAW_PAGE
) {
501 b
= edit_move_forward (edit
, edit
->start_display
, start_row
, 0);
502 while (row
<= end_row
) {
503 if (key_pending (edit
))
505 edit_draw_this_line (edit
, b
, row
, start_column
, end_column
);
506 b
= edit_move_forward (edit
, b
, 1, 0);
510 curs_row
= edit
->curs_row
;
512 if (force
& REDRAW_BEFORE_CURSOR
) {
513 if (start_row
< curs_row
) {
514 long upto
= curs_row
- 1 <= end_row
? curs_row
- 1 : end_row
;
516 b
= edit
->start_display
;
517 while (row
<= upto
) {
518 if (key_pending (edit
))
520 edit_draw_this_line (edit
, b
, row
, start_column
, end_column
);
521 b
= edit_move_forward (edit
, b
, 1, 0);
525 /* if (force & REDRAW_LINE) { ---> default */
526 b
= edit_bol (edit
, edit
->curs1
);
527 if (curs_row
>= start_row
&& curs_row
<= end_row
) {
528 if (key_pending (edit
))
530 edit_draw_this_line (edit
, b
, curs_row
, start_column
, end_column
);
532 if (force
& REDRAW_AFTER_CURSOR
) {
533 if (end_row
> curs_row
) {
534 row
= curs_row
+ 1 < start_row
? start_row
: curs_row
+ 1;
535 b
= edit_move_forward (edit
, b
, 1, 0);
536 while (row
<= end_row
) {
537 if (key_pending (edit
))
539 edit_draw_this_line (edit
, b
, row
, start_column
, end_column
);
540 b
= edit_move_forward (edit
, b
, 1, 0);
545 if (force
& REDRAW_LINE_ABOVE
&& curs_row
>= 1) {
547 b
= edit_move_backward (edit
, edit_bol (edit
, edit
->curs1
), 1);
548 if (row
>= start_row
&& row
<= end_row
) {
549 if (key_pending (edit
))
551 edit_draw_this_line (edit
, b
, row
, start_column
, end_column
);
554 if (force
& REDRAW_LINE_BELOW
&& row
< edit
->num_widget_lines
- 1) {
556 b
= edit_bol (edit
, edit
->curs1
);
557 b
= edit_move_forward (edit
, b
, 1, 0);
558 if (row
>= start_row
&& row
<= end_row
) {
559 if (key_pending (edit
))
561 edit_draw_this_line (edit
, b
, row
, start_column
, end_column
);
566 if (prev_curs_row
< edit
->curs_row
) { /* with the new text highlighting, we must draw from the top down */
567 edit_draw_this_char (edit
, prev_curs
, prev_curs_row
);
568 edit_draw_this_char (edit
, edit
->curs1
, edit
->curs_row
);
570 edit_draw_this_char (edit
, edit
->curs1
, edit
->curs_row
);
571 edit_draw_this_char (edit
, prev_curs
, prev_curs_row
);
577 prev_curs_row
= edit
->curs_row
;
578 prev_curs
= edit
->curs1
;
579 prev_start_col
= edit
->start_col
;
582 prev_win
= ((GdkWindowPrivate
*) CWindowOf (edit
->widget
)->text_area
)->xwindow
;
584 prev_win
= CWindowOf (edit
->widget
);
594 void edit_convert_expose_to_area (XExposeEvent
* xexpose
, int *row1
, int *col1
, int *row2
, int *col2
)
596 *col1
= xexpose
->x
- EDIT_TEXT_HORIZONTAL_OFFSET
;
597 *row1
= (xexpose
->y
- EDIT_TEXT_VERTICAL_OFFSET
) / FONT_PIX_PER_LINE
;
598 *col2
= xexpose
->x
+ xexpose
->width
+ EDIT_TEXT_HORIZONTAL_OFFSET
+ 3;
599 *row2
= (xexpose
->y
+ xexpose
->height
- EDIT_TEXT_VERTICAL_OFFSET
) / FONT_PIX_PER_LINE
;
604 void edit_render_tidbits (GtkEdit
* edit
)
606 gtk_widget_draw_focus (GTK_WIDGET (edit
));
611 void edit_render_tidbits (CWidget
* wdt
)
614 int w
= wdt
->width
, h
= wdt
->height
;
618 isfocussed
= (win
== CGetFocus ());
620 CSetColor (COLOR_FLAT
);
623 render_bevel (win
, 0, 0, w
- 1, h
- 1, 3, 1); /*most outer border bevel */
625 render_bevel (win
, 2, 2, w
- 3, h
- 3, 1, 1); /*border bevel */
626 render_bevel (win
, 0, 0, w
- 1, h
- 1, 2, 0); /*most outer border bevel */
632 void edit_set_space_width (int s
);
633 extern int option_long_whitespace
;
637 void edit_render (WEdit
* edit
, int page
, int row_start
, int col_start
, int row_end
, int col_end
)
643 if (page
) /* if it was an expose event, 'page' would be set */
644 edit
->force
|= REDRAW_PAGE
| REDRAW_IN_BOUNDS
;
645 f
= edit
->force
& (REDRAW_PAGE
| REDRAW_COMPLETELY
);
648 if (edit
->force
& REDRAW_COMPLETELY
)
649 redraw_labels (edit
->widget
.parent
, (Widget
*) edit
);
651 if (option_long_whitespace
)
652 edit_set_space_width (per_char
[' '] * 2);
654 edit_set_space_width (per_char
[' ']);
656 win
= (GtkEdit
*) edit
->widget
;
658 edit_set_foreground_colors (
659 color_palette (option_editor_fg_normal
),
660 color_palette (option_editor_fg_bold
),
661 color_palette (option_editor_fg_italic
)
663 edit_set_background_colors (
664 color_palette (option_editor_bg_normal
),
665 color_palette (option_editor_bg_abnormal
),
666 color_palette (option_editor_bg_marked
),
667 color_palette (option_editor_bg_marked_abnormal
),
668 color_palette (option_editor_bg_highlighted
)
670 edit_set_cursor_color (
671 color_palette (option_editor_fg_cursor
)
677 if (!EditExposeRedraw
)
678 set_cursor_position (0, 0, 0, 0, 0, 0, 0, 0, 0);
682 render_edit_text (edit
, row_start
, col_start
, row_end
, col_end
);
683 if (edit
->force
) /* edit->force != 0 means a key was pending and the redraw
684 was halted, so next time we must redraw everything in case stuff
685 was left undrawn from a previous key press */
686 edit
->force
|= REDRAW_PAGE
;
689 edit_render_tidbits (edit
->widget
);
691 /* ***************** */
693 CSetColor (edit_normal_background_color
);
694 CLine (CWindowOf (edit
->widget
), 3, 3, 3, CHeightOf (edit
->widget
) - 4);
701 void edit_render_expose (WEdit
* edit
, XExposeEvent
* xexpose
)
703 int row_start
, col_start
, row_end
, col_end
;
704 EditExposeRedraw
= 1;
705 edit
->num_widget_lines
= (CHeightOf (edit
->widget
) - 6) / FONT_PIX_PER_LINE
;
706 edit
->num_widget_columns
= (CWidthOf (edit
->widget
) - 7) / FONT_MEAN_WIDTH
;
707 if (edit
->force
& (REDRAW_PAGE
| REDRAW_COMPLETELY
)) {
708 edit
->force
|= REDRAW_PAGE
| REDRAW_COMPLETELY
;
709 edit_render_keypress (edit
);
711 edit_convert_expose_to_area (xexpose
, &row_start
, &col_start
, &row_end
, &col_end
);
712 edit_render (edit
, 1, row_start
, col_start
, row_end
, col_end
);
714 EditExposeRedraw
= 0;
717 void edit_render_keypress (WEdit
* edit
)
719 edit_render (edit
, 0, 0, 0, 0, 0);
724 void edit_render_keypress (WEdit
* edit
)
726 edit_render (edit
, 0, 0, 0, 0, 0);