./configure: cleanup '--enable-background' option description
[midnight-commander.git] / src / editor / editdraw.c
blob6b11171eebaaf5589ed10bf8bdc4035455c1eba3
1 /*
2 Editor text drawing.
4 Copyright (C) 1996, 1997, 1998, 2001, 2002, 2003, 2004, 2005, 2006,
5 2007, 2011, 2012
6 The Free Software Foundation, Inc.
8 Written by:
9 Paul Sheer, 1996, 1997
10 Andrew Borodin <aborodin@vmail.ru> 2012
12 This file is part of the Midnight Commander.
14 The Midnight Commander is free software: you can redistribute it
15 and/or modify it under the terms of the GNU General Public License as
16 published by the Free Software Foundation, either version 3 of the License,
17 or (at your option) any later version.
19 The Midnight Commander is distributed in the hope that it will be useful,
20 but WITHOUT ANY WARRANTY; without even the implied warranty of
21 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 GNU General Public License for more details.
24 You should have received a copy of the GNU General Public License
25 along with this program. If not, see <http://www.gnu.org/licenses/>.
28 /** \file
29 * \brief Source: editor text drawing
30 * \author Paul Sheer
31 * \date 1996, 1997
34 #include <config.h>
35 #include <stdlib.h>
36 #include <stdio.h>
37 #include <stdarg.h>
38 #include <sys/types.h>
39 #include <unistd.h>
40 #include <string.h>
41 #include <ctype.h>
42 #include <errno.h>
43 #include <sys/stat.h>
45 #include "lib/global.h"
46 #include "lib/tty/tty.h" /* tty_printf() */
47 #include "lib/tty/key.h" /* is_idle() */
48 #include "lib/skin.h"
49 #include "lib/strutil.h" /* utf string functions */
50 #include "lib/util.h" /* is_printable() */
51 #include "lib/charsets.h"
53 #include "src/setup.h" /* edit_tab_spacing */
54 #include "src/main.h" /* macro_index */
56 #include "edit-impl.h"
57 #include "editwidget.h"
59 /*** global variables ****************************************************************************/
61 /* Toggles statusbar draw style */
62 int simple_statusbar = 0;
64 int visible_tabs = 1, visible_tws = 1;
66 /*** file scope macro definitions ****************************************************************/
68 #define MAX_LINE_LEN 1024
70 /* Text styles */
71 #define MOD_ABNORMAL (1 << 8)
72 #define MOD_BOLD (1 << 9)
73 #define MOD_MARKED (1 << 10)
74 #define MOD_CURSOR (1 << 11)
75 #define MOD_WHITESPACE (1 << 12)
77 #define edit_move(x,y) widget_move(edit, y, x);
79 #define key_pending(x) (!is_idle())
81 #define EDITOR_MINIMUM_TERMINAL_WIDTH 30
83 /*** file scope type declarations ****************************************************************/
85 struct line_s
87 unsigned int ch;
88 unsigned int style;
91 /*** file scope variables ************************************************************************/
93 /*** file scope functions ************************************************************************/
95 static inline void
96 printwstr (const char *s, int len)
98 if (len > 0)
99 tty_printf ("%-*.*s", len, len, s);
102 /* --------------------------------------------------------------------------------------------- */
104 static inline void
105 status_string (WEdit * edit, char *s, int w)
107 char byte_str[16];
108 unsigned char cur_byte = 0;
109 unsigned int cur_utf = 0;
110 int cw = 1;
113 * If we are at the end of file, print <EOF>,
114 * otherwise print the current character as is (if printable),
115 * as decimal and as hex.
117 if (edit->curs1 < edit->last_byte)
119 if (!edit->utf8)
121 cur_byte = edit_get_byte (edit, edit->curs1);
123 g_snprintf (byte_str, sizeof (byte_str), "%4d 0x%03X",
124 (int) cur_byte, (unsigned) cur_byte);
126 else
128 cur_utf = edit_get_utf (edit, edit->curs1, &cw);
129 if (cw > 0)
131 g_snprintf (byte_str, sizeof (byte_str), "%04d 0x%03X",
132 (unsigned) cur_utf, (unsigned) cur_utf);
134 else
136 cur_utf = edit_get_byte (edit, edit->curs1);
137 g_snprintf (byte_str, sizeof (byte_str), "%04d 0x%03X",
138 (int) cur_utf, (unsigned) cur_utf);
143 else
145 strcpy (byte_str, "<EOF> ");
148 /* The field lengths just prevent the status line from shortening too much */
149 if (simple_statusbar)
150 g_snprintf (s, w,
151 "%c%c%c%c %3ld %5ld/%ld %6ld/%ld %s %s",
152 edit->mark1 != edit->mark2 ? (edit->column_highlight ? 'C' : 'B') : '-',
153 edit->modified ? 'M' : '-',
154 macro_index < 0 ? '-' : 'R',
155 edit->overwrite == 0 ? '-' : 'O',
156 edit->curs_col + edit->over_col,
157 edit->curs_line + 1,
158 edit->total_lines + 1, edit->curs1, edit->last_byte, byte_str,
159 #ifdef HAVE_CHARSET
160 mc_global.source_codepage >=
161 0 ? get_codepage_id (mc_global.source_codepage) : ""
162 #else
164 #endif
166 else
167 g_snprintf (s, w,
168 "[%c%c%c%c] %2ld L:[%3ld+%2ld %3ld/%3ld] *(%-4ld/%4ldb) %s %s",
169 edit->mark1 != edit->mark2 ? (edit->column_highlight ? 'C' : 'B') : '-',
170 edit->modified ? 'M' : '-',
171 macro_index < 0 ? '-' : 'R',
172 edit->overwrite == 0 ? '-' : 'O',
173 edit->curs_col + edit->over_col,
174 edit->start_line + 1,
175 edit->curs_row,
176 edit->curs_line + 1,
177 edit->total_lines + 1, edit->curs1, edit->last_byte, byte_str,
178 #ifdef HAVE_CHARSET
179 mc_global.source_codepage >=
180 0 ? get_codepage_id (mc_global.source_codepage) : ""
181 #else
183 #endif
187 /* --------------------------------------------------------------------------------------------- */
189 * Draw the status line at the top of the screen for fullscreen editor window.
191 * @param edit editor object
192 * @param color color pair
195 static inline void
196 edit_status_fullscreen (WEdit * edit, int color)
198 const int w = edit->widget.owner->cols;
199 const size_t status_size = w + 1;
200 char *const status = g_malloc (status_size);
201 int status_len;
202 const char *fname = "";
203 int fname_len;
204 const int gap = 3; /* between the filename and the status */
205 const int right_gap = 5; /* at the right end of the screen */
206 const int preferred_fname_len = 16;
208 status_string (edit, status, status_size);
209 status_len = (int) str_term_width1 (status);
211 if (edit->filename_vpath != NULL)
212 fname = x_basename (vfs_path_get_last_path_str (edit->filename_vpath));
214 fname_len = str_term_width1 (fname);
215 if (fname_len < preferred_fname_len)
216 fname_len = preferred_fname_len;
218 if (fname_len + gap + status_len + right_gap >= w)
220 if (preferred_fname_len + gap + status_len + right_gap >= w)
221 fname_len = preferred_fname_len;
222 else
223 fname_len = w - (gap + status_len + right_gap);
224 fname = str_trunc (fname, fname_len);
227 dlg_move (edit->widget.owner, 0, 0);
228 tty_setcolor (color);
229 printwstr (fname, fname_len + gap);
230 printwstr (status, w - (fname_len + gap));
232 if (simple_statusbar && w > EDITOR_MINIMUM_TERMINAL_WIDTH)
234 size_t percent = 100;
236 if (edit->total_lines + 1 != 0)
237 percent = (edit->curs_line + 1) * 100 / (edit->total_lines + 1);
238 dlg_move (edit->widget.owner, 0, w - 6 - 6);
239 tty_printf (" %3d%%", percent);
242 g_free (status);
245 /* --------------------------------------------------------------------------------------------- */
247 * Draw status line for editor window if window is not in fullscreen mode.
249 * @param edit editor object
252 static inline void
253 edit_status_window (WEdit * edit)
255 int y, x;
256 int cols = edit->widget.cols;
258 tty_setcolor (STATUSBAR_COLOR);
260 if (cols > 5)
262 const char *fname = N_("NoName");
263 char *full_fname = NULL;
265 if (edit->filename_vpath != NULL)
267 full_fname = vfs_path_to_str (edit->filename_vpath);
268 fname = x_basename (full_fname);
270 #ifdef ENABLE_NLS
271 else
272 fname = _(fname);
273 #endif
275 edit_move (2, 0);
276 tty_printf ("[%s]", str_term_trim (fname, edit->widget.cols - 8 - 6));
277 g_free (full_fname);
280 tty_getyx (&y, &x);
281 x -= edit->widget.x;
282 x += 4;
283 if (x + 6 <= cols - 2 - 6)
285 edit_move (x, 0);
286 tty_printf ("[%c%c%c%c]",
287 edit->mark1 != edit->mark2 ? (edit->column_highlight ? 'C' : 'B') : '-',
288 edit->modified ? 'M' : '-',
289 macro_index < 0 ? '-' : 'R', edit->overwrite == 0 ? '-' : 'O');
292 if (cols > 30)
294 edit_move (2, edit->widget.lines - 1);
295 tty_printf ("%3ld %5ld/%ld %6ld/%ld",
296 edit->curs_col + edit->over_col,
297 edit->curs_line + 1, edit->total_lines + 1, edit->curs1, edit->last_byte);
301 * If we are at the end of file, print <EOF>,
302 * otherwise print the current character as is (if printable),
303 * as decimal and as hex.
305 if (cols > 46)
307 edit_move (32, edit->widget.lines - 1);
308 if (edit->curs1 >= edit->last_byte)
309 tty_print_string ("[<EOF> ]");
310 #ifdef HAVE_CHARSET
311 else if (edit->utf8)
313 unsigned int cur_utf;
314 int cw = 1;
316 cur_utf = edit_get_utf (edit, edit->curs1, &cw);
317 if (cw <= 0)
318 cur_utf = edit_get_byte (edit, edit->curs1);
319 tty_printf ("[%05d 0x%04X]", cur_utf, cur_utf);
321 #endif
322 else
324 unsigned char cur_byte;
326 cur_byte = edit_get_byte (edit, edit->curs1);
327 tty_printf ("[%05d 0x%04X]", (unsigned int) cur_byte, (unsigned int) cur_byte);
332 /* --------------------------------------------------------------------------------------------- */
334 * Draw a frame around edit area.
336 * @param edit editor object
337 * @param color color pair
338 * @param active TRUE if editor object is focused
341 static inline void
342 edit_draw_frame (const WEdit * edit, int color, gboolean active)
344 const Widget *w = (const Widget *) edit;
346 /* draw a frame around edit area */
347 tty_setcolor (color);
348 /* draw double frame for active window if skin supports that */
349 tty_draw_box (w->y, w->x, w->lines, w->cols, !active);
350 /* draw a drag marker */
351 if (edit->drag_state == MCEDIT_DRAG_NORMAL)
353 tty_setcolor (EDITOR_FRAME_DRAG);
354 widget_move (w, w->lines - 1, w->cols - 1);
355 tty_print_alt_char (ACS_LRCORNER, TRUE);
359 /* --------------------------------------------------------------------------------------------- */
361 * Draw a window control buttons.
363 * @param edit editor object
364 * @param color color pair
367 static inline void
368 edit_draw_window_icons (const WEdit * edit, int color)
370 const Widget *w = (const Widget *) edit;
371 char tmp[17];
373 tty_setcolor (color);
374 if (edit->fullscreen)
375 dlg_move (w->owner, 0, w->owner->cols - 6);
376 else
377 widget_move (w, 0, edit->widget.cols - 8);
378 g_snprintf (tmp, sizeof (tmp), "[%s][%s]", edit_window_state_char, edit_window_close_char);
379 tty_print_string (tmp);
382 /* --------------------------------------------------------------------------------------------- */
384 static inline void
385 print_to_widget (WEdit * edit, long row, int start_col, int start_col_real,
386 long end_col, struct line_s line[], char *status, int bookmarked)
388 struct line_s *p;
390 int x = start_col_real;
391 int x1 = start_col + EDIT_TEXT_HORIZONTAL_OFFSET + option_line_state_width;
392 int y = row + EDIT_TEXT_VERTICAL_OFFSET;
393 int cols_to_skip = abs (x);
394 int i;
395 int wrap_start;
396 int len;
398 if (!edit->fullscreen)
400 x1++;
401 y++;
404 tty_setcolor (EDITOR_NORMAL_COLOR);
405 if (bookmarked != 0)
406 tty_setcolor (bookmarked);
408 len = end_col + 1 - start_col;
409 wrap_start = option_word_wrap_line_length + edit->start_col;
411 if (len > 0 && edit->widget.y + y >= 0)
413 if (!show_right_margin || wrap_start > end_col)
414 tty_draw_hline (edit->widget.y + y, edit->widget.x + x1, ' ', len);
415 else if (wrap_start < 0)
417 tty_setcolor (EDITOR_RIGHT_MARGIN_COLOR);
418 tty_draw_hline (edit->widget.y + y, edit->widget.x + x1, ' ', len);
420 else
422 if (wrap_start > 0)
423 tty_draw_hline (edit->widget.y + y, edit->widget.x + x1, ' ', wrap_start);
425 len -= wrap_start;
426 if (len > 0)
428 tty_setcolor (EDITOR_RIGHT_MARGIN_COLOR);
429 tty_draw_hline (edit->widget.y + y, edit->widget.x + x1 + wrap_start, ' ', len);
434 if (option_line_state)
436 tty_setcolor (LINE_STATE_COLOR);
437 for (i = 0; i < LINE_STATE_WIDTH; i++)
439 edit_move (x1 + i - option_line_state_width, y);
440 if (status[i] == '\0')
441 status[i] = ' ';
442 tty_print_char (status[i]);
446 edit_move (x1, y);
447 i = 1;
448 for (p = line; p->ch != 0; p++)
450 int style;
451 unsigned int textchar;
452 int color;
454 if (cols_to_skip != 0)
456 cols_to_skip--;
457 continue;
460 style = p->style & 0xFF00;
461 textchar = p->ch;
462 color = p->style >> 16;
464 if (style & MOD_ABNORMAL)
466 /* Non-printable - use black background */
467 color = 0;
470 if (style & MOD_WHITESPACE)
472 if (style & MOD_MARKED)
474 textchar = ' ';
475 tty_setcolor (EDITOR_MARKED_COLOR);
477 else
478 tty_setcolor (EDITOR_WHITESPACE_COLOR);
480 else if (style & MOD_BOLD)
481 tty_setcolor (EDITOR_BOLD_COLOR);
482 else if (style & MOD_MARKED)
483 tty_setcolor (EDITOR_MARKED_COLOR);
484 else
485 tty_lowlevel_setcolor (color);
487 if (show_right_margin)
489 if (i > option_word_wrap_line_length + edit->start_col)
490 tty_setcolor (EDITOR_RIGHT_MARGIN_COLOR);
491 i++;
494 tty_print_anychar (textchar);
498 /* --------------------------------------------------------------------------------------------- */
499 /** b is a pointer to the beginning of the line */
501 static void
502 edit_draw_this_line (WEdit * edit, long b, long row, long start_col, long end_col)
504 struct line_s line[MAX_LINE_LEN];
505 struct line_s *p = line;
507 long m1 = 0, m2 = 0, q, c1, c2;
508 int col, start_col_real;
509 unsigned int c;
510 int color;
511 int abn_style;
512 int i;
513 int utf8lag = 0;
514 unsigned int cur_line = 0;
515 int book_mark = 0;
516 char line_stat[LINE_STATE_WIDTH + 1] = "\0";
518 if (row > edit->widget.lines - 1 - EDIT_TEXT_VERTICAL_OFFSET - 2 * (edit->fullscreen ? 0 : 1))
519 return;
521 if (book_mark_query_color (edit, edit->start_line + row, BOOK_MARK_COLOR))
522 book_mark = BOOK_MARK_COLOR;
523 else if (book_mark_query_color (edit, edit->start_line + row, BOOK_MARK_FOUND_COLOR))
524 book_mark = BOOK_MARK_FOUND_COLOR;
526 if (book_mark)
527 abn_style = book_mark << 16;
528 else
529 abn_style = MOD_ABNORMAL;
531 end_col -= EDIT_TEXT_HORIZONTAL_OFFSET + option_line_state_width;
532 if (!edit->fullscreen)
534 const Widget *w = (const Widget *) edit;
536 end_col--;
537 if (w->x + w->cols <= w->owner->cols)
538 end_col--;
541 edit_get_syntax_color (edit, b - 1, &color);
542 q = edit_move_forward3 (edit, b, start_col - edit->start_col, 0);
543 start_col_real = (col = (int) edit_move_forward3 (edit, b, 0, q)) + edit->start_col;
545 if (option_line_state)
547 cur_line = edit->start_line + row;
548 if (cur_line <= (unsigned int) edit->total_lines)
550 g_snprintf (line_stat, LINE_STATE_WIDTH + 1, "%7i ", cur_line + 1);
552 else
554 memset (line_stat, ' ', LINE_STATE_WIDTH);
555 line_stat[LINE_STATE_WIDTH] = '\0';
557 if (book_mark_query_color (edit, cur_line, BOOK_MARK_COLOR))
559 g_snprintf (line_stat, 2, "*");
563 if (col + 16 > -edit->start_col)
565 eval_marks (edit, &m1, &m2);
567 if (row <= edit->total_lines - edit->start_line)
569 long tws = 0;
570 if (tty_use_colors () && visible_tws)
572 tws = edit_eol (edit, b);
573 while (tws > b && ((c = edit_get_byte (edit, tws - 1)) == ' ' || c == '\t'))
574 tws--;
577 while (col <= end_col - edit->start_col)
579 int cw = 1;
580 int tab_over = 0;
581 gboolean wide_width_char = FALSE;
582 gboolean control_char = FALSE;
584 p->ch = 0;
585 p->style = 0;
586 if (q == edit->curs1)
587 p->style |= MOD_CURSOR;
588 if (q >= m1 && q < m2)
590 if (edit->column_highlight)
592 int x;
593 x = edit_move_forward3 (edit, b, 0, q);
594 c1 = min (edit->column1, edit->column2);
595 c2 = max (edit->column1, edit->column2);
596 if (x >= c1 && x < c2)
597 p->style |= MOD_MARKED;
599 else
600 p->style |= MOD_MARKED;
602 if (q == edit->bracket)
603 p->style |= MOD_BOLD;
604 if (q >= edit->found_start && q < edit->found_start + edit->found_len)
605 p->style |= MOD_BOLD;
607 if (!edit->utf8)
609 c = edit_get_byte (edit, q);
611 else
613 c = edit_get_utf (edit, q, &cw);
615 /* we don't use bg for mc - fg contains both */
616 if (book_mark)
618 p->style |= book_mark << 16;
620 else
622 edit_get_syntax_color (edit, q, &color);
623 p->style |= color << 16;
625 switch (c)
627 case '\n':
628 col = (end_col + utf8lag) - edit->start_col + 1; /* quit */
629 break;
630 case '\t':
631 i = TAB_SIZE - ((int) col % TAB_SIZE);
632 tab_over = (end_col - edit->start_col) - (col + i - 1);
633 if (tab_over < 0)
634 i += tab_over;
635 col += i;
636 if (tty_use_colors () &&
637 ((visible_tabs || (visible_tws && q >= tws)) && enable_show_tabs_tws))
639 if (p->style & MOD_MARKED)
640 c = p->style;
641 else if (book_mark)
642 c |= book_mark << 16;
643 else
644 c = p->style | MOD_WHITESPACE;
645 if (i > 2)
647 p->ch = '<';
648 p->style = c;
649 p++;
650 while (--i > 1)
652 p->ch = '-';
653 p->style = c;
654 p++;
656 p->ch = '>';
657 p->style = c;
658 p++;
660 else if (i > 1)
662 p->ch = '<';
663 p->style = c;
664 p++;
665 p->ch = '>';
666 p->style = c;
667 p++;
669 else
671 p->ch = '>';
672 p->style = c;
673 p++;
676 else if (tty_use_colors () && visible_tws && q >= tws && enable_show_tabs_tws)
678 p->ch = '.';
679 p->style |= MOD_WHITESPACE;
680 c = p->style & ~MOD_CURSOR;
681 p++;
682 while (--i)
684 p->ch = ' ';
685 p->style = c;
686 p++;
689 else
691 p->ch |= ' ';
692 c = p->style & ~MOD_CURSOR;
693 p++;
694 while (--i)
696 p->ch = ' ';
697 p->style = c;
698 p++;
701 break;
702 case ' ':
703 if (tty_use_colors () && visible_tws && q >= tws && enable_show_tabs_tws)
705 p->ch = '.';
706 p->style |= MOD_WHITESPACE;
707 p++;
708 col++;
709 break;
711 /* fallthrough */
712 default:
713 #ifdef HAVE_CHARSET
714 if (mc_global.utf8_display)
716 if (!edit->utf8)
718 c = convert_from_8bit_to_utf_c ((unsigned char) c, edit->converter);
720 else
722 if (g_unichar_iswide (c))
724 wide_width_char = TRUE;
725 col++;
729 else if (edit->utf8)
730 c = convert_from_utf_to_current_c (c, edit->converter);
731 else
732 #endif
733 c = convert_to_display_c (c);
735 /* Caret notation for control characters */
736 if (c < 32)
738 p->ch = '^';
739 p->style = abn_style;
740 p++;
741 p->ch = c + 0x40;
742 p->style = abn_style;
743 p++;
744 col += 2;
745 control_char = TRUE;
746 break;
748 if (c == 127)
750 p->ch = '^';
751 p->style = abn_style;
752 p++;
753 p->ch = '?';
754 p->style = abn_style;
755 p++;
756 col += 2;
757 control_char = TRUE;
758 break;
760 if (!edit->utf8)
762 if ((mc_global.utf8_display && g_unichar_isprint (c)) ||
763 (!mc_global.utf8_display && is_printable (c)))
765 p->ch = c;
766 p++;
768 else
770 p->ch = '.';
771 p->style = abn_style;
772 p++;
775 else
777 if (g_unichar_isprint (c))
779 p->ch = c;
780 p++;
782 else
784 p->ch = '.';
785 p->style = abn_style;
786 p++;
789 col++;
790 break;
791 } /* case */
793 q++;
794 if (cw > 1)
796 q += cw - 1;
799 if (col > (end_col - edit->start_col + 1))
801 if (wide_width_char)
803 p--;
804 break;
806 if (control_char)
808 p -= 2;
809 break;
815 else
817 start_col_real = start_col = 0;
820 p->ch = 0;
822 print_to_widget (edit, row, start_col, start_col_real, end_col, line, line_stat, book_mark);
825 /* --------------------------------------------------------------------------------------------- */
827 static inline void
828 edit_draw_this_char (WEdit * edit, long curs, long row, long start_column, long end_column)
830 int b = edit_bol (edit, curs);
831 edit_draw_this_line (edit, b, row, start_column, end_column);
834 /* --------------------------------------------------------------------------------------------- */
835 /** cursor must be in screen for other than REDRAW_PAGE passed in force */
837 static inline void
838 render_edit_text (WEdit * edit, long start_row, long start_column, long end_row, long end_column)
840 static long prev_curs_row = 0;
841 static long prev_curs = 0;
843 Widget *w = (Widget *) edit;
844 Dlg_head *h = w->owner;
846 long row = 0, curs_row;
847 int force = edit->force;
848 long b;
849 int y1, x1, y2, x2;
851 int last_line;
852 int last_column;
854 /* draw only visible region */
856 last_line = h->y + h->lines - 1;
858 y1 = w->y;
859 if (y1 > last_line - 1 /* buttonbar */ )
860 return;
862 last_column = h->x + h->cols - 1;
864 x1 = w->x;
865 if (x1 > last_column)
866 return;
868 y2 = w->y + w->lines - 1;
869 if (y2 < h->y + 1 /* menubar */ )
870 return;
872 x2 = w->x + w->cols - 1;
873 if (x2 < h->x)
874 return;
876 if ((force & REDRAW_IN_BOUNDS) == 0)
878 /* !REDRAW_IN_BOUNDS means to ignore bounds and redraw whole rows */
879 /* draw only visible region */
881 if (y2 <= last_line - 1 /* buttonbar */ )
882 end_row = w->lines - 1;
883 else if (y1 >= h->y + 1 /* menubar */ )
884 end_row = h->lines - 1 - y1 - 1;
885 else
886 end_row = start_row + h->lines - 1 - 1;
888 if (x2 <= last_column)
889 end_column = w->cols - 1;
890 else if (x1 >= h->x)
891 end_column = h->cols - 1 - x1;
892 else
893 end_column = start_column + h->cols - 1;
897 * If the position of the page has not moved then we can draw the cursor
898 * character only. This will prevent line flicker when using arrow keys.
900 if ((force & REDRAW_CHAR_ONLY) == 0 || (force & REDRAW_PAGE) != 0)
902 if ((force & REDRAW_PAGE) != 0)
904 row = start_row;
905 b = edit_move_forward (edit, edit->start_display, start_row, 0);
906 while (row <= end_row)
908 if (key_pending (edit))
909 return;
910 edit_draw_this_line (edit, b, row, start_column, end_column);
911 b = edit_move_forward (edit, b, 1, 0);
912 row++;
915 else
917 curs_row = edit->curs_row;
919 if ((force & REDRAW_BEFORE_CURSOR) != 0 && start_row < curs_row)
921 long upto = curs_row - 1 <= end_row ? curs_row - 1 : end_row;
923 row = start_row;
924 b = edit->start_display;
925 while (row <= upto)
927 if (key_pending (edit))
928 return;
929 edit_draw_this_line (edit, b, row, start_column, end_column);
930 b = edit_move_forward (edit, b, 1, 0);
934 /* if (force & REDRAW_LINE) ---> default */
935 b = edit_bol (edit, edit->curs1);
936 if (curs_row >= start_row && curs_row <= end_row)
938 if (key_pending (edit))
939 return;
940 edit_draw_this_line (edit, b, curs_row, start_column, end_column);
943 if ((force & REDRAW_AFTER_CURSOR) != 0 && end_row > curs_row)
945 row = curs_row + 1 < start_row ? start_row : curs_row + 1;
946 b = edit_move_forward (edit, b, 1, 0);
947 while (row <= end_row)
949 if (key_pending (edit))
950 return;
951 edit_draw_this_line (edit, b, row, start_column, end_column);
952 b = edit_move_forward (edit, b, 1, 0);
953 row++;
957 if ((force & REDRAW_LINE_ABOVE) != 0 && curs_row >= 1)
959 row = curs_row - 1;
960 b = edit_move_backward (edit, edit_bol (edit, edit->curs1), 1);
961 if (row >= start_row && row <= end_row)
963 if (key_pending (edit))
964 return;
965 edit_draw_this_line (edit, b, row, start_column, end_column);
969 if ((force & REDRAW_LINE_BELOW) != 0 && row < edit->widget.lines - 1)
971 row = curs_row + 1;
972 b = edit_bol (edit, edit->curs1);
973 b = edit_move_forward (edit, b, 1, 0);
974 if (row >= start_row && row <= end_row)
976 if (key_pending (edit))
977 return;
978 edit_draw_this_line (edit, b, row, start_column, end_column);
983 else if (prev_curs_row < edit->curs_row)
985 /* with the new text highlighting, we must draw from the top down */
986 edit_draw_this_char (edit, prev_curs, prev_curs_row, start_column, end_column);
987 edit_draw_this_char (edit, edit->curs1, edit->curs_row, start_column, end_column);
989 else
991 edit_draw_this_char (edit, edit->curs1, edit->curs_row, start_column, end_column);
992 edit_draw_this_char (edit, prev_curs, prev_curs_row, start_column, end_column);
995 edit->force = 0;
997 prev_curs_row = edit->curs_row;
998 prev_curs = edit->curs1;
1001 /* --------------------------------------------------------------------------------------------- */
1003 static inline void
1004 edit_render (WEdit * edit, int page, int row_start, int col_start, int row_end, int col_end)
1006 if (page) /* if it was an expose event, 'page' would be set */
1007 edit->force |= REDRAW_PAGE | REDRAW_IN_BOUNDS;
1009 render_edit_text (edit, row_start, col_start, row_end, col_end);
1012 * edit->force != 0 means a key was pending and the redraw
1013 * was halted, so next time we must redraw everything in case stuff
1014 * was left undrawn from a previous key press.
1016 if (edit->force)
1017 edit->force |= REDRAW_PAGE;
1020 /* --------------------------------------------------------------------------------------------- */
1021 /*** public functions ****************************************************************************/
1022 /* --------------------------------------------------------------------------------------------- */
1024 void
1025 edit_status (WEdit * edit, gboolean active)
1027 int color;
1029 if (edit->fullscreen)
1031 color = STATUSBAR_COLOR;
1032 edit_status_fullscreen (edit, color);
1034 else
1036 color = edit->drag_state != MCEDIT_DRAG_NORMAL ? EDITOR_FRAME_DRAG : active ?
1037 EDITOR_FRAME_ACTIVE : EDITOR_FRAME;
1038 edit_draw_frame (edit, color, active);
1039 edit_status_window (edit);
1042 edit_draw_window_icons (edit, color);
1045 /* --------------------------------------------------------------------------------------------- */
1047 /** this scrolls the text so that cursor is on the screen */
1048 void
1049 edit_scroll_screen_over_cursor (WEdit * edit)
1051 int p;
1052 int outby;
1053 int b_extreme, t_extreme, l_extreme, r_extreme;
1055 if (edit->widget.lines <= 0 || edit->widget.cols <= 0)
1056 return;
1058 edit->widget.lines -= EDIT_TEXT_VERTICAL_OFFSET;
1059 edit->widget.cols -= EDIT_TEXT_HORIZONTAL_OFFSET + option_line_state_width;
1061 if (!edit->fullscreen)
1063 edit->widget.x++;
1064 edit->widget.cols -= 2;
1065 edit->widget.y++;
1066 edit->widget.lines -= 2;
1069 r_extreme = EDIT_RIGHT_EXTREME;
1070 l_extreme = EDIT_LEFT_EXTREME;
1071 b_extreme = EDIT_BOTTOM_EXTREME;
1072 t_extreme = EDIT_TOP_EXTREME;
1073 if (edit->found_len)
1075 b_extreme = max (edit->widget.lines / 4, b_extreme);
1076 t_extreme = max (edit->widget.lines / 4, t_extreme);
1078 if (b_extreme + t_extreme + 1 > edit->widget.lines)
1080 int n;
1082 n = b_extreme + t_extreme;
1083 if (n == 0)
1084 n = 1;
1085 b_extreme = (b_extreme * (edit->widget.lines - 1)) / n;
1086 t_extreme = (t_extreme * (edit->widget.lines - 1)) / n;
1088 if (l_extreme + r_extreme + 1 > edit->widget.cols)
1090 int n;
1092 n = l_extreme + t_extreme;
1093 if (n == 0)
1094 n = 1;
1095 l_extreme = (l_extreme * (edit->widget.cols - 1)) / n;
1096 r_extreme = (r_extreme * (edit->widget.cols - 1)) / n;
1098 p = edit_get_col (edit) + edit->over_col;
1099 edit_update_curs_row (edit);
1100 outby = p + edit->start_col - edit->widget.cols + 1 + (r_extreme + edit->found_len);
1101 if (outby > 0)
1102 edit_scroll_right (edit, outby);
1103 outby = l_extreme - p - edit->start_col;
1104 if (outby > 0)
1105 edit_scroll_left (edit, outby);
1106 p = edit->curs_row;
1107 outby = p - edit->widget.lines + 1 + b_extreme;
1108 if (outby > 0)
1109 edit_scroll_downward (edit, outby);
1110 outby = t_extreme - p;
1111 if (outby > 0)
1112 edit_scroll_upward (edit, outby);
1113 edit_update_curs_row (edit);
1115 edit->widget.lines += EDIT_TEXT_VERTICAL_OFFSET;
1116 edit->widget.cols += EDIT_TEXT_HORIZONTAL_OFFSET + option_line_state_width;
1117 if (!edit->fullscreen)
1119 edit->widget.x--;
1120 edit->widget.cols += 2;
1121 edit->widget.y--;
1122 edit->widget.lines += 2;
1126 /* --------------------------------------------------------------------------------------------- */
1128 void
1129 edit_render_keypress (WEdit * edit)
1131 edit_render (edit, 0, 0, 0, 0, 0);
1134 /* --------------------------------------------------------------------------------------------- */