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., 59 Temple Place, Suite 330, Boston, MA
26 #define MAX_LINE_LEN 1024
28 #if ! defined (MIDNIGHT) && ! defined (GTK)
30 #include "coollocal.h"
34 extern int column_highlighting
;
36 #if defined (MIDNIGHT) || defined (GTK)
38 void status_string (WEdit
* edit
, char *s
, int w
, int fill
, int font_width
)
43 char t
[160]; /* 160 just to be sure */
44 /* The field lengths just prevents the status line from shortening to much */
45 sprintf (t
, "[%c%c%c%c] %2ld:%3ld+%2ld=%3ld/%3ld - *%-4ld/%4ldb=%3d",
46 edit
->mark1
!= edit
->mark2
? ( column_highlighting
? 'C' : 'B') : '-',
47 edit
->modified
? 'M' : '-', edit
->macro_i
< 0 ? '-' : 'R',
48 edit
->overwrite
== 0 ? '-' : 'O',
49 edit
->curs_col
/ font_width
, edit
->start_line
+ 1, edit
->curs_row
,
50 edit
->curs_line
+ 1, edit
->total_lines
+ 1, edit
->curs1
,
51 edit
->last_byte
, edit
->curs1
< edit
->last_byte
52 ? edit_get_byte (edit
, edit
->curs1
) : -1);
54 sprintf (s
, "%.*s", w
+ 1, t
);
59 if (strchr ("+-*=/:b", s
[i
])) /* chop off the last word/number */
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 sprintf (s
, "%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
);
107 extern int fixed_font
;
110 void render_status (CWidget
* wdt
, int expose
);
114 void edit_status (WEdit
*edit
)
119 w
= edit
->num_widget_columns
- 1;
126 i
= w
> 24 ? 18 : w
- 6;
128 sprintf (s
, "%s", (char *) name_trunc (edit
->filename
? edit
->filename
: "", i
));
135 status_string (edit
, s
+ i
+ 2, t
, 0, FONT_MEAN_WIDTH
);
138 entry
= GTK_ENTRY (edit
->widget
->status
);
139 if (strcmp (s
, gtk_entry_get_text (entry
)))
140 gtk_entry_set_text (entry
, s
);
145 void edit_status (WEdit
* edit
)
147 long start_mark
, end_mark
;
153 if (eval_marks (edit
, &start_mark
, &end_mark
))
154 end_mark
= start_mark
= 0;
155 if ((COptionsOf (edit
->widget
) & EDITOR_NO_TEXT
))
157 m
= edit
->stat
.st_mode
;
158 p
= edit
->filename
? edit
->filename
: "";
159 sprintf (s
, "\034%c%s\033\035 \034-%c%c%c%c%c%c%c%c%c\035 \034%s%s%s%c\035 \034\030%02ld\033\035 \034%-4ld+%2ld=\030%4ld\033/%3ld\035 \034*%-5ld/%5ldb=%c%3d\035%c \034\001%ld\033\035",
160 *p
? '\033' : '\003', *p
? (char *) name_trunc (p
, max (edit
->num_widget_lines
/ 3, 16)) : _ ("<unnamed>"),
161 m
& S_IRUSR
? 'r' : '-',
162 m
& S_IWUSR
? 'w' : '-',
163 m
& S_IXUSR
? 'x' : '-',
164 m
& S_IRGRP
? 'r' : '-',
165 m
& S_IWGRP
? 'w' : '-',
166 m
& S_IXGRP
? 'x' : '-',
167 m
& S_IROTH
? 'r' : '-',
168 m
& S_IWOTH
? 'w' : '-',
169 m
& S_IXOTH
? 'x' : '-',
170 end_mark
- start_mark
|| (edit
->mark2
== -1 && !edit
->highlight
) ? (column_highlighting
? "\032C\033" : "\001B\033") : "-",
171 edit
->modified
? "\012M\033" : "-", edit
->macro_i
< 0 ? "-" : "\023R\033",
172 edit
->overwrite
== 0 ? '-' : 'O',
173 edit
->curs_col
/ FONT_MEAN_WIDTH
, edit
->start_line
+ 1, edit
->curs_row
,
174 edit
->curs_line
+ 1, edit
->total_lines
+ 1, edit
->curs1
,
175 edit
->last_byte
, edit
->curs1
== edit
->last_byte
? '\014' : '\033', edit
->curs1
< edit
->last_byte
176 ? edit_get_byte (edit
, edit
->curs1
) : -1,
177 end_mark
- start_mark
&& !column_highlighting
? ' ' : '\0',
178 end_mark
- start_mark
);
179 strcpy (id
, CIdentOf (edit
->widget
));
180 strcat (id
, ".text");
183 wdt
->text
= (char *) strdup (s
);
184 CSetWidgetSize (id
, CWidthOf (edit
->widget
), CHeightOf (wdt
));
185 render_status (wdt
, 0);
194 int cursor_in_screen (WEdit
* edit
, long row
)
196 if (row
< 0 || row
>= edit
->num_widget_lines
)
202 /* returns rows from the first displayed line to the cursor */
203 int cursor_from_display_top (WEdit
* edit
)
205 if (edit
->curs1
< edit
->start_display
)
206 return -edit_move_forward (edit
, edit
->curs1
, 0, edit
->start_display
);
208 return edit_move_forward (edit
, edit
->start_display
, 0, edit
->curs1
);
211 /* returns how far the cursor is out of the screen */
212 int cursor_out_of_screen (WEdit
* edit
)
214 int row
= cursor_from_display_top (edit
);
215 if (row
>= edit
->num_widget_lines
)
216 return row
- edit
->num_widget_lines
+ 1;
223 extern unsigned char per_char
[256];
224 int edit_width_of_long_printable (int c
);
227 /* this scrolls the text so that cursor is on the screen */
228 void edit_scroll_screen_over_cursor (WEdit
* edit
)
232 int b_extreme
, t_extreme
, l_extreme
, r_extreme
;
233 r_extreme
= EDIT_RIGHT_EXTREME
;
234 l_extreme
= EDIT_LEFT_EXTREME
;
235 b_extreme
= EDIT_BOTTOM_EXTREME
;
236 t_extreme
= EDIT_TOP_EXTREME
;
237 if (edit
->found_len
) {
238 b_extreme
= max (edit
->num_widget_lines
/ 4, b_extreme
);
239 t_extreme
= max (edit
->num_widget_lines
/ 4, t_extreme
);
241 if (b_extreme
+ t_extreme
+ 1 > edit
->num_widget_lines
) {
243 n
= b_extreme
+ t_extreme
;
244 b_extreme
= (b_extreme
* (edit
->num_widget_lines
- 1)) / n
;
245 t_extreme
= (t_extreme
* (edit
->num_widget_lines
- 1)) / n
;
247 if (l_extreme
+ r_extreme
+ 1 > edit
->num_widget_columns
) {
249 n
= l_extreme
+ t_extreme
;
250 l_extreme
= (l_extreme
* (edit
->num_widget_columns
- 1)) / n
;
251 r_extreme
= (r_extreme
* (edit
->num_widget_columns
- 1)) / n
;
253 p
= edit_get_col (edit
);
254 edit_update_curs_row (edit
);
256 outby
= p
+ edit
->start_col
- edit
->num_widget_columns
+ 1 + (r_extreme
+ edit
->found_len
);
258 outby
= p
+ edit
->start_col
- CWidthOf (edit
->widget
) + 7 + (r_extreme
+ edit
->found_len
) * FONT_MEAN_WIDTH
+ edit_width_of_long_printable (edit_get_byte (edit
, edit
->curs1
));
261 edit_scroll_right (edit
, outby
);
263 outby
= l_extreme
- p
- edit
->start_col
;
265 outby
= l_extreme
* FONT_MEAN_WIDTH
- p
- edit
->start_col
;
268 edit_scroll_left (edit
, outby
);
270 outby
= p
- edit
->num_widget_lines
+ 1 + b_extreme
;
272 edit_scroll_downward (edit
, outby
);
273 outby
= t_extreme
- p
;
275 edit_scroll_upward (edit
, outby
);
276 edit_update_curs_row (edit
);
282 #define CACHE_WIDTH 256
283 #define CACHE_HEIGHT 128
285 int EditExposeRedraw
= 0;
288 /* background colors: marked is refers to mouse highlighting, highlighted refers to a found string. */
289 unsigned long edit_abnormal_color
, edit_marked_abnormal_color
;
290 unsigned long edit_highlighted_color
, edit_marked_color
;
291 unsigned long edit_normal_background_color
;
293 /* foreground colors */
294 unsigned long edit_normal_foreground_color
, edit_bold_color
;
295 unsigned long edit_italic_color
;
298 unsigned long edit_cursor_color
;
300 void edit_set_foreground_colors (unsigned long normal
, unsigned long bold
, unsigned long italic
)
302 edit_normal_foreground_color
= normal
;
303 edit_bold_color
= bold
;
304 edit_italic_color
= italic
;
307 void edit_set_background_colors (unsigned long normal
, unsigned long abnormal
, unsigned long marked
, unsigned long marked_abnormal
, unsigned long highlighted
)
309 edit_abnormal_color
= abnormal
;
310 edit_marked_abnormal_color
= marked_abnormal
;
311 edit_marked_color
= marked
;
312 edit_highlighted_color
= highlighted
;
313 edit_normal_background_color
= normal
;
316 void edit_set_cursor_color (unsigned long c
)
318 edit_cursor_color
= c
;
323 static void set_color (int font
)
328 #define edit_move(x,y) widget_move(edit, y, x);
330 static void print_to_widget (WEdit
* edit
, long row
, int start_col
, float start_col_real
, long end_col
, unsigned int line
[])
332 int x
= (float) start_col_real
+ EDIT_TEXT_HORIZONTAL_OFFSET
;
333 int x1
= start_col
+ EDIT_TEXT_HORIZONTAL_OFFSET
;
334 int y
= row
+ EDIT_TEXT_VERTICAL_OFFSET
;
336 set_color (EDITOR_NORMAL_COLOR
);
338 hline (' ', end_col
+ 1 - EDIT_TEXT_HORIZONTAL_OFFSET
- x1
);
340 edit_move (x
+ FONT_OFFSET_X
, y
+ FONT_OFFSET_Y
);
342 unsigned int *p
= line
;
348 textchar
= *p
& 0xFF;
350 if (!(style
& (0xFF - MOD_ABNORMAL
- MOD_CURSOR
)))
351 SLsmg_set_color ((*p
& 0x007F0000) >> 16);
353 if (style
& MOD_ABNORMAL
)
355 if (style
& MOD_HIGHLIGHTED
) {
356 set_color (EDITOR_BOLD_COLOR
);
357 } else if (style
& MOD_MARKED
) {
358 set_color (EDITOR_MARKED_COLOR
);
360 if (style
& MOD_UNDERLINED
) {
361 set_color (EDITOR_UNDERLINED_COLOR
);
363 if (style
& MOD_BOLD
) {
364 set_color (EDITOR_BOLD_COLOR
);
372 /* b pointer to begining of line */
373 static void edit_draw_this_line (WEdit
* edit
, long b
, long row
, long start_col
, long end_col
)
375 static unsigned int line
[MAX_LINE_LEN
];
376 unsigned int *p
= line
;
377 long m1
= 0, m2
= 0, q
, c1
, c2
;
378 int col
, start_col_real
;
381 int i
, book_mark
= -1;
384 if (!book_mark_query (edit
, edit
->start_line
+ row
, &book_mark
))
388 edit_get_syntax_color (edit
, b
- 1, &fg
, &bg
);
389 q
= edit_move_forward3 (edit
, b
, start_col
- edit
->start_col
, 0);
390 start_col_real
= (col
= (int) edit_move_forward3 (edit
, b
, 0, q
)) + edit
->start_col
;
391 c1
= min (edit
->column1
, edit
->column2
);
392 c2
= max (edit
->column1
, edit
->column2
);
394 if (col
+ 16 > -edit
->start_col
) {
395 eval_marks (edit
, &m1
, &m2
);
397 if (row
<= edit
->total_lines
- edit
->start_line
) {
398 while (col
<= end_col
- edit
->start_col
) {
400 if (q
== edit
->curs1
)
401 *p
|= MOD_CURSOR
* 256;
402 if (q
>= m1
&& q
< m2
) {
403 if (column_highlighting
) {
405 x
= edit_move_forward3 (edit
, b
, 0, q
);
406 if (x
>= c1
&& x
< c2
)
407 *p
|= MOD_MARKED
* 256;
409 *p
|= MOD_MARKED
* 256;
411 if (q
== edit
->bracket
)
412 *p
|= MOD_BOLD
* 256;
413 if (q
>= edit
->found_start
&& q
< edit
->found_start
+ edit
->found_len
)
414 *p
|= MOD_HIGHLIGHTED
* 256;
415 c
= edit_get_byte (edit
, q
);
416 /* we don't use bg for mc - fg contains both */
417 if (book_mark
== -1) {
418 edit_get_syntax_color (edit
, q
, &fg
, &bg
);
421 *p
|= book_mark
<< 16;
426 col
= end_col
- edit
->start_col
+ 1; /* quit */
430 i
= TAB_SIZE
- ((int) col
% TAB_SIZE
);
432 c
= *(p
++) & (0xFFFFFFFF - MOD_CURSOR
* 256);
440 if (is_printable (c
)) {
444 *p
|= (256 * MOD_ABNORMAL
);
452 start_col_real
= start_col
= 0;
456 print_to_widget (edit
, row
, start_col
, start_col_real
, end_col
, line
);
463 #define key_pending(x) (!is_idle())
467 int edit_mouse_pending (Window win
);
468 #define edit_draw_this_line edit_draw_this_line_proportional
470 static int key_pending (WEdit
* edit
)
472 static int flush
= 0, line
= 0;
478 } else if (!(edit
->force
& REDRAW_COMPLETELY
) && !EditExposeRedraw
) {
479 /* this flushes the display in logarithmic intervals - so both fast and
480 slow machines will get good performance vs nice-refreshing */
481 if ((1 << flush
) == ++line
) {
483 return CKeyPending ();
493 /* b for pointer to begining of line */
494 static void edit_draw_this_char (WEdit
* edit
, long curs
, long row
)
496 int b
= edit_bol (edit
, curs
);
498 edit_draw_this_line (edit
, b
, row
, 0, edit
->num_widget_columns
- 1);
500 edit_draw_this_line (edit
, b
, row
, 0, CWidthOf (edit
->widget
));
504 /* cursor must be in screen for other than REDRAW_PAGE passed in force */
505 void render_edit_text (WEdit
* edit
, long start_row
, long start_column
, long end_row
, long end_column
)
507 long row
= 0, curs_row
;
508 static int prev_curs_row
= 0;
509 static int prev_start_col
= 0;
510 static long prev_curs
= 0;
513 static unsigned long prev_win
= 0;
516 int force
= edit
->force
;
524 if the position of the page has not moved then we can draw the cursor character only.
525 This will prevent line flicker when using arrow keys.
527 if ((!(force
& REDRAW_CHAR_ONLY
)) || (force
& REDRAW_PAGE
)
530 || prev_win
!= ((GdkWindowPrivate
*) CWindowOf (edit
->widget
)->text_area
)->xwindow
532 || prev_win
!= CWindowOf (edit
->widget
)
536 if (!(force
& REDRAW_IN_BOUNDS
)) { /* !REDRAW_IN_BOUNDS means to ignore bounds and redraw whole rows */
538 end_row
= edit
->num_widget_lines
- 1;
541 end_column
= edit
->num_widget_columns
- 1;
543 end_column
= CWidthOf (edit
->widget
);
546 if (force
& REDRAW_PAGE
) {
548 b
= edit_move_forward (edit
, edit
->start_display
, start_row
, 0);
549 while (row
<= end_row
) {
550 if (key_pending (edit
))
552 edit_draw_this_line (edit
, b
, row
, start_column
, end_column
);
553 b
= edit_move_forward (edit
, b
, 1, 0);
557 curs_row
= edit
->curs_row
;
559 if (force
& REDRAW_BEFORE_CURSOR
) {
560 if (start_row
< curs_row
) {
561 long upto
= curs_row
- 1 <= end_row
? curs_row
- 1 : end_row
;
563 b
= edit
->start_display
;
564 while (row
<= upto
) {
565 if (key_pending (edit
))
567 edit_draw_this_line (edit
, b
, row
, start_column
, end_column
);
568 b
= edit_move_forward (edit
, b
, 1, 0);
572 /* if (force & REDRAW_LINE) { ---> default */
573 b
= edit_bol (edit
, edit
->curs1
);
574 if (curs_row
>= start_row
&& curs_row
<= end_row
) {
575 if (key_pending (edit
))
577 edit_draw_this_line (edit
, b
, curs_row
, start_column
, end_column
);
579 if (force
& REDRAW_AFTER_CURSOR
) {
580 if (end_row
> curs_row
) {
581 row
= curs_row
+ 1 < start_row
? start_row
: curs_row
+ 1;
582 b
= edit_move_forward (edit
, b
, 1, 0);
583 while (row
<= end_row
) {
584 if (key_pending (edit
))
586 edit_draw_this_line (edit
, b
, row
, start_column
, end_column
);
587 b
= edit_move_forward (edit
, b
, 1, 0);
592 if (force
& REDRAW_LINE_ABOVE
&& curs_row
>= 1) {
594 b
= edit_move_backward (edit
, edit_bol (edit
, edit
->curs1
), 1);
595 if (row
>= start_row
&& row
<= end_row
) {
596 if (key_pending (edit
))
598 edit_draw_this_line (edit
, b
, row
, start_column
, end_column
);
601 if (force
& REDRAW_LINE_BELOW
&& row
< edit
->num_widget_lines
- 1) {
603 b
= edit_bol (edit
, edit
->curs1
);
604 b
= edit_move_forward (edit
, b
, 1, 0);
605 if (row
>= start_row
&& row
<= end_row
) {
606 if (key_pending (edit
))
608 edit_draw_this_line (edit
, b
, row
, start_column
, end_column
);
613 if (prev_curs_row
< edit
->curs_row
) { /* with the new text highlighting, we must draw from the top down */
614 edit_draw_this_char (edit
, prev_curs
, prev_curs_row
);
615 edit_draw_this_char (edit
, edit
->curs1
, edit
->curs_row
);
617 edit_draw_this_char (edit
, edit
->curs1
, edit
->curs_row
);
618 edit_draw_this_char (edit
, prev_curs
, prev_curs_row
);
624 prev_curs_row
= edit
->curs_row
;
625 prev_curs
= edit
->curs1
;
626 prev_start_col
= edit
->start_col
;
629 prev_win
= ((GdkWindowPrivate
*) CWindowOf (edit
->widget
)->text_area
)->xwindow
;
631 prev_win
= CWindowOf (edit
->widget
);
642 void edit_convert_expose_to_area (XExposeEvent
* xexpose
, int *row1
, int *col1
, int *row2
, int *col2
)
644 *col1
= xexpose
->x
- EDIT_TEXT_HORIZONTAL_OFFSET
;
645 *row1
= (xexpose
->y
- EDIT_TEXT_VERTICAL_OFFSET
) / FONT_PIX_PER_LINE
;
646 *col2
= xexpose
->x
+ xexpose
->width
+ EDIT_TEXT_HORIZONTAL_OFFSET
+ 3;
647 *row2
= (xexpose
->y
+ xexpose
->height
- EDIT_TEXT_VERTICAL_OFFSET
) / FONT_PIX_PER_LINE
;
652 void edit_render_tidbits (GtkEdit
* edit
)
654 gtk_widget_draw_focus (GTK_WIDGET (edit
));
659 void edit_render_tidbits (CWidget
* wdt
)
662 int w
= wdt
->width
, h
= wdt
->height
;
666 isfocussed
= (win
== CGetFocus ());
668 CSetColor (COLOR_FLAT
);
671 render_bevel (win
, 0, 0, w
- 1, h
- 1, 3, 1); /*most outer border bevel */
673 render_bevel (win
, 2, 2, w
- 3, h
- 3, 1, 1); /*border bevel */
674 render_bevel (win
, 0, 0, w
- 1, h
- 1, 2, 0); /*most outer border bevel */
680 void edit_set_space_width (int s
);
681 extern int option_long_whitespace
;
685 void edit_render (WEdit
* edit
, int page
, int row_start
, int col_start
, int row_end
, int col_end
)
691 if (page
) /* if it was an expose event, 'page' would be set */
692 edit
->force
|= REDRAW_PAGE
| REDRAW_IN_BOUNDS
;
693 f
= edit
->force
& (REDRAW_PAGE
| REDRAW_COMPLETELY
);
696 if (edit
->force
& REDRAW_COMPLETELY
)
697 redraw_labels (edit
->widget
.parent
, (Widget
*) edit
);
699 if (option_long_whitespace
)
700 edit_set_space_width (per_char
[' '] * 2);
702 edit_set_space_width (per_char
[' ']);
704 win
= (GtkEdit
*) edit
->widget
;
706 edit_set_foreground_colors (
707 color_palette (option_editor_fg_normal
),
708 color_palette (option_editor_fg_bold
),
709 color_palette (option_editor_fg_italic
)
711 edit_set_background_colors (
712 color_palette (option_editor_bg_normal
),
713 color_palette (option_editor_bg_abnormal
),
714 color_palette (option_editor_bg_marked
),
715 color_palette (option_editor_bg_marked_abnormal
),
716 color_palette (option_editor_bg_highlighted
)
718 edit_set_cursor_color (
719 color_palette (option_editor_fg_cursor
)
725 if (!EditExposeRedraw
)
726 set_cursor_position (0, 0, 0, 0, 0, 0, 0, 0, 0);
730 render_edit_text (edit
, row_start
, col_start
, row_end
, col_end
);
731 if (edit
->force
) /* edit->force != 0 means a key was pending and the redraw
732 was halted, so next time we must redraw everything in case stuff
733 was left undrawn from a previous key press */
734 edit
->force
|= REDRAW_PAGE
;
737 edit_render_tidbits (edit
->widget
);
739 /* ***************** */
741 CSetColor (edit_normal_background_color
);
742 CLine (CWindowOf (edit
->widget
), 3, 3, 3, CHeightOf (edit
->widget
) - 4);
749 void edit_render_expose (WEdit
* edit
, XExposeEvent
* xexpose
)
751 int row_start
, col_start
, row_end
, col_end
;
752 EditExposeRedraw
= 1;
753 edit
->num_widget_lines
= (CHeightOf (edit
->widget
) - EDIT_FRAME_H
) / FONT_PIX_PER_LINE
;
754 edit
->num_widget_columns
= (CWidthOf (edit
->widget
) - EDIT_FRAME_W
) / FONT_MEAN_WIDTH
;
755 if (edit
->force
& (REDRAW_PAGE
| REDRAW_COMPLETELY
)) {
756 edit
->force
|= REDRAW_PAGE
| REDRAW_COMPLETELY
;
757 edit_render_keypress (edit
);
759 edit_convert_expose_to_area (xexpose
, &row_start
, &col_start
, &row_end
, &col_end
);
760 edit_render (edit
, 1, row_start
, col_start
, row_end
, col_end
);
762 EditExposeRedraw
= 0;
765 void edit_render_keypress (WEdit
* edit
)
767 edit_render (edit
, 0, 0, 0, 0, 0);
772 void edit_render_keypress (WEdit
* edit
)
774 edit_render (edit
, 0, 0, 0, 0, 0);