cppcheck: reduce variable scope.
[midnight-commander.git] / src / editor / editdraw.c
blobdb7ad2480840475d49e78ff30fb6838f1d3ad5fb
1 /*
2 Editor text drawing.
4 Copyright (C) 1996, 1997, 1998, 2001, 2002, 2003, 2004, 2005, 2006,
5 2007, 2011, 2012, 2013
6 The Free Software Foundation, Inc.
8 Written by:
9 Paul Sheer, 1996, 1997
10 Andrew Borodin <aborodin@vmail.ru> 2012, 2013
11 Slava Zanko <slavazanko@gmail.com>, 2013
13 This file is part of the Midnight Commander.
15 The Midnight Commander is free software: you can redistribute it
16 and/or modify it under the terms of the GNU General Public License as
17 published by the Free Software Foundation, either version 3 of the License,
18 or (at your option) any later version.
20 The Midnight Commander is distributed in the hope that it will be useful,
21 but WITHOUT ANY WARRANTY; without even the implied warranty of
22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
23 GNU General Public License for more details.
25 You should have received a copy of the GNU General Public License
26 along with this program. If not, see <http://www.gnu.org/licenses/>.
29 /** \file
30 * \brief Source: editor text drawing
31 * \author Paul Sheer
32 * \date 1996, 1997
35 #include <config.h>
36 #include <stdlib.h>
37 #include <stdio.h>
38 #include <stdarg.h>
39 #include <sys/types.h>
40 #include <unistd.h>
41 #include <string.h>
42 #include <ctype.h>
43 #include <errno.h>
44 #include <sys/stat.h>
46 #include "lib/global.h"
47 #include "lib/tty/tty.h" /* tty_printf() */
48 #include "lib/tty/key.h" /* is_idle() */
49 #include "lib/skin.h"
50 #include "lib/strutil.h" /* utf string functions */
51 #include "lib/util.h" /* is_printable() */
52 #include "lib/widget.h"
53 #ifdef HAVE_CHARSET
54 #include "lib/charsets.h"
55 #endif
57 #include "src/setup.h" /* edit_tab_spacing */
59 #include "edit-impl.h"
60 #include "editwidget.h"
62 /*** global variables ****************************************************************************/
64 /* Toggles statusbar draw style */
65 int simple_statusbar = 0;
67 int visible_tabs = 1, visible_tws = 1;
69 /*** file scope macro definitions ****************************************************************/
71 #define MAX_LINE_LEN 1024
73 /* Text styles */
74 #define MOD_ABNORMAL (1 << 8)
75 #define MOD_BOLD (1 << 9)
76 #define MOD_MARKED (1 << 10)
77 #define MOD_CURSOR (1 << 11)
78 #define MOD_WHITESPACE (1 << 12)
80 #define edit_move(x,y) widget_move(edit, y, x);
82 #define key_pending(x) (!is_idle())
84 #define EDITOR_MINIMUM_TERMINAL_WIDTH 30
86 /*** file scope type declarations ****************************************************************/
88 struct line_s
90 unsigned int ch;
91 unsigned int style;
94 /*** file scope variables ************************************************************************/
96 /*** file scope functions ************************************************************************/
98 static inline void
99 printwstr (const char *s, int len)
101 if (len > 0)
102 tty_printf ("%-*.*s", len, len, s);
105 /* --------------------------------------------------------------------------------------------- */
107 static inline void
108 status_string (WEdit * edit, char *s, int w)
110 char byte_str[16];
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->buffer.curs1 < edit->buffer.size)
119 #ifdef HAVE_CHARSET
120 if (edit->utf8)
122 unsigned int cur_utf = 0;
123 int cw = 1;
125 cur_utf = edit_buffer_get_utf (&edit->buffer, edit->buffer.curs1, &cw);
126 if (cw > 0)
128 g_snprintf (byte_str, sizeof (byte_str), "%04d 0x%03X",
129 (unsigned) cur_utf, (unsigned) cur_utf);
131 else
133 cur_utf = edit_buffer_get_current_byte (&edit->buffer);
134 g_snprintf (byte_str, sizeof (byte_str), "%04d 0x%03X",
135 (int) cur_utf, (unsigned) cur_utf);
138 else
139 #endif
141 unsigned char cur_byte = 0;
143 cur_byte = edit_buffer_get_current_byte (&edit->buffer);
144 g_snprintf (byte_str, sizeof (byte_str), "%4d 0x%03X",
145 (int) cur_byte, (unsigned) cur_byte);
148 else
150 strcpy (byte_str, "<EOF> ");
153 /* The field lengths just prevent the status line from shortening too much */
154 if (simple_statusbar)
155 g_snprintf (s, w,
156 "%c%c%c%c %3ld %5ld/%ld %6ld/%ld %s %s",
157 edit->mark1 != edit->mark2 ? (edit->column_highlight ? 'C' : 'B') : '-',
158 edit->modified ? 'M' : '-',
159 macro_index < 0 ? '-' : 'R',
160 edit->overwrite == 0 ? '-' : 'O',
161 edit->curs_col + edit->over_col,
162 edit->buffer.curs_line + 1,
163 edit->buffer.lines + 1, (long) edit->buffer.curs1, (long) edit->buffer.size,
164 byte_str,
165 #ifdef HAVE_CHARSET
166 mc_global.source_codepage >= 0 ? get_codepage_id (mc_global.source_codepage) :
167 #endif
168 "");
169 else
170 g_snprintf (s, w,
171 "[%c%c%c%c] %2ld L:[%3ld+%2ld %3ld/%3ld] *(%-4ld/%4ldb) %s %s",
172 edit->mark1 != edit->mark2 ? (edit->column_highlight ? 'C' : 'B') : '-',
173 edit->modified ? 'M' : '-',
174 macro_index < 0 ? '-' : 'R',
175 edit->overwrite == 0 ? '-' : 'O',
176 edit->curs_col + edit->over_col,
177 edit->start_line + 1,
178 edit->curs_row,
179 edit->buffer.curs_line + 1,
180 edit->buffer.lines + 1, (long) edit->buffer.curs1, (long) edit->buffer.size,
181 byte_str,
182 #ifdef HAVE_CHARSET
183 mc_global.source_codepage >= 0 ? get_codepage_id (mc_global.source_codepage) :
184 #endif
185 "");
188 /* --------------------------------------------------------------------------------------------- */
190 * Draw the status line at the top of the screen for fullscreen editor window.
192 * @param edit editor object
193 * @param color color pair
196 static inline void
197 edit_status_fullscreen (WEdit * edit, int color)
199 Widget *h = WIDGET (WIDGET (edit)->owner);
200 const int w = h->cols;
201 const size_t status_size = w + 1;
202 char *const status = g_malloc (status_size);
203 int status_len;
204 const char *fname = "";
205 int fname_len;
206 const int gap = 3; /* between the filename and the status */
207 const int right_gap = 5; /* at the right end of the screen */
208 const int preferred_fname_len = 16;
210 status_string (edit, status, status_size);
211 status_len = (int) str_term_width1 (status);
213 if (edit->filename_vpath != NULL)
214 fname = x_basename (vfs_path_get_last_path_str (edit->filename_vpath));
216 fname_len = str_term_width1 (fname);
217 if (fname_len < preferred_fname_len)
218 fname_len = preferred_fname_len;
220 if (fname_len + gap + status_len + right_gap >= w)
222 if (preferred_fname_len + gap + status_len + right_gap >= w)
223 fname_len = preferred_fname_len;
224 else
225 fname_len = w - (gap + status_len + right_gap);
226 fname = str_trunc (fname, fname_len);
229 widget_move (h, 0, 0);
230 tty_setcolor (color);
231 printwstr (fname, fname_len + gap);
232 printwstr (status, w - (fname_len + gap));
234 if (simple_statusbar && w > EDITOR_MINIMUM_TERMINAL_WIDTH)
236 size_t percent = 100;
238 if (edit->buffer.lines + 1 != 0)
239 percent = (edit->buffer.curs_line + 1) * 100 / (edit->buffer.lines + 1);
240 widget_move (h, 0, w - 6 - 6);
241 tty_printf (" %3d%%", percent);
244 g_free (status);
247 /* --------------------------------------------------------------------------------------------- */
249 * Draw status line for editor window if window is not in fullscreen mode.
251 * @param edit editor object
254 static inline void
255 edit_status_window (WEdit * edit)
257 Widget *w = WIDGET (edit);
258 int y, x;
259 int cols = w->cols;
261 tty_setcolor (STATUSBAR_COLOR);
263 if (cols > 5)
265 const char *fname = N_("NoName");
267 if (edit->filename_vpath != NULL)
269 fname = x_basename (vfs_path_as_str (edit->filename_vpath));
271 #ifdef ENABLE_NLS
272 else
273 fname = _(fname);
274 #endif
276 edit_move (2, 0);
277 tty_printf ("[%s]", str_term_trim (fname, w->cols - 8 - 6));
280 tty_getyx (&y, &x);
281 x -= w->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, w->lines - 1);
295 tty_printf ("%3ld %5ld/%ld %6ld/%ld",
296 edit->curs_col + edit->over_col,
297 edit->buffer.curs_line + 1, edit->buffer.lines + 1, (long) edit->buffer.curs1,
298 (long) edit->buffer.size);
302 * If we are at the end of file, print <EOF>,
303 * otherwise print the current character as is (if printable),
304 * as decimal and as hex.
306 if (cols > 46)
308 edit_move (32, w->lines - 1);
309 if (edit->buffer.curs1 >= edit->buffer.size)
310 tty_print_string ("[<EOF> ]");
311 #ifdef HAVE_CHARSET
312 else if (edit->utf8)
314 unsigned int cur_utf;
315 int cw = 1;
317 cur_utf = edit_buffer_get_utf (&edit->buffer, edit->buffer.curs1, &cw);
318 if (cw <= 0)
319 cur_utf = edit_buffer_get_current_byte (&edit->buffer);
320 tty_printf ("[%05d 0x%04X]", cur_utf, cur_utf);
322 #endif
323 else
325 unsigned char cur_byte;
327 cur_byte = edit_buffer_get_current_byte (&edit->buffer);
328 tty_printf ("[%05d 0x%04X]", (unsigned int) cur_byte, (unsigned int) cur_byte);
333 /* --------------------------------------------------------------------------------------------- */
335 * Draw a frame around edit area.
337 * @param edit editor object
338 * @param color color pair
339 * @param active TRUE if editor object is focused
342 static inline void
343 edit_draw_frame (const WEdit * edit, int color, gboolean active)
345 const Widget *w = (const Widget *) edit;
347 /* draw a frame around edit area */
348 tty_setcolor (color);
349 /* draw double frame for active window if skin supports that */
350 tty_draw_box (w->y, w->x, w->lines, w->cols, !active);
351 /* draw a drag marker */
352 if (edit->drag_state == MCEDIT_DRAG_NORMAL)
354 tty_setcolor (EDITOR_FRAME_DRAG);
355 widget_move (w, w->lines - 1, w->cols - 1);
356 tty_print_alt_char (ACS_LRCORNER, TRUE);
360 /* --------------------------------------------------------------------------------------------- */
362 * Draw a window control buttons.
364 * @param edit editor object
365 * @param color color pair
368 static inline void
369 edit_draw_window_icons (const WEdit * edit, int color)
371 const Widget *w = WIDGET (edit);
372 char tmp[17];
374 tty_setcolor (color);
375 if (edit->fullscreen)
376 widget_move (w->owner, 0, WIDGET (w->owner)->cols - 6);
377 else
378 widget_move (w, 0, w->cols - 8);
379 g_snprintf (tmp, sizeof (tmp), "[%s][%s]", edit_window_state_char, edit_window_close_char);
380 tty_print_string (tmp);
383 /* --------------------------------------------------------------------------------------------- */
385 static inline void
386 print_to_widget (WEdit * edit, long row, int start_col, int start_col_real,
387 long end_col, struct line_s line[], char *status, int bookmarked)
389 Widget *w = WIDGET (edit);
391 struct line_s *p;
393 int x = start_col_real;
394 int x1 = start_col + EDIT_TEXT_HORIZONTAL_OFFSET + option_line_state_width;
395 int y = row + EDIT_TEXT_VERTICAL_OFFSET;
396 int cols_to_skip = abs (x);
397 int i;
398 int wrap_start;
399 int len;
401 if (!edit->fullscreen)
403 x1++;
404 y++;
407 tty_setcolor (EDITOR_NORMAL_COLOR);
408 if (bookmarked != 0)
409 tty_setcolor (bookmarked);
411 len = end_col + 1 - start_col;
412 wrap_start = option_word_wrap_line_length + edit->start_col;
414 if (len > 0 && w->y + y >= 0)
416 if (!show_right_margin || wrap_start > end_col)
417 tty_draw_hline (w->y + y, w->x + x1, ' ', len);
418 else if (wrap_start < 0)
420 tty_setcolor (EDITOR_RIGHT_MARGIN_COLOR);
421 tty_draw_hline (w->y + y, w->x + x1, ' ', len);
423 else
425 if (wrap_start > 0)
426 tty_draw_hline (w->y + y, w->x + x1, ' ', wrap_start);
428 len -= wrap_start;
429 if (len > 0)
431 tty_setcolor (EDITOR_RIGHT_MARGIN_COLOR);
432 tty_draw_hline (w->y + y, w->x + x1 + wrap_start, ' ', len);
437 if (option_line_state)
439 tty_setcolor (LINE_STATE_COLOR);
440 for (i = 0; i < LINE_STATE_WIDTH; i++)
442 edit_move (x1 + i - option_line_state_width, y);
443 if (status[i] == '\0')
444 status[i] = ' ';
445 tty_print_char (status[i]);
449 edit_move (x1, y);
450 i = 1;
451 for (p = line; p->ch != 0; p++)
453 int style;
454 unsigned int textchar;
455 int color;
457 if (cols_to_skip != 0)
459 cols_to_skip--;
460 continue;
463 style = p->style & 0xFF00;
464 textchar = p->ch;
465 color = p->style >> 16;
467 if (style & MOD_ABNORMAL)
469 /* Non-printable - use black background */
470 color = 0;
473 if (style & MOD_WHITESPACE)
475 if (style & MOD_MARKED)
477 textchar = ' ';
478 tty_setcolor (EDITOR_MARKED_COLOR);
480 else
481 tty_setcolor (EDITOR_WHITESPACE_COLOR);
483 else if (style & MOD_BOLD)
484 tty_setcolor (EDITOR_BOLD_COLOR);
485 else if (style & MOD_MARKED)
486 tty_setcolor (EDITOR_MARKED_COLOR);
487 else
488 tty_lowlevel_setcolor (color);
490 if (show_right_margin)
492 if (i > option_word_wrap_line_length + edit->start_col)
493 tty_setcolor (EDITOR_RIGHT_MARGIN_COLOR);
494 i++;
497 tty_print_anychar (textchar);
501 /* --------------------------------------------------------------------------------------------- */
502 /** b is a pointer to the beginning of the line */
504 static void
505 edit_draw_this_line (WEdit * edit, off_t b, long row, long start_col, long end_col)
507 Widget *w = WIDGET (edit);
509 struct line_s line[MAX_LINE_LEN];
510 struct line_s *p = line;
512 off_t m1 = 0, m2 = 0, q;
513 int col, start_col_real;
514 int color;
515 int abn_style;
516 int book_mark = 0;
517 char line_stat[LINE_STATE_WIDTH + 1] = "\0";
519 if (row > w->lines - 1 - EDIT_TEXT_VERTICAL_OFFSET - 2 * (edit->fullscreen ? 0 : 1))
520 return;
522 if (book_mark_query_color (edit, edit->start_line + row, BOOK_MARK_COLOR))
523 book_mark = BOOK_MARK_COLOR;
524 else if (book_mark_query_color (edit, edit->start_line + row, BOOK_MARK_FOUND_COLOR))
525 book_mark = BOOK_MARK_FOUND_COLOR;
527 if (book_mark)
528 abn_style = book_mark << 16;
529 else
530 abn_style = MOD_ABNORMAL;
532 end_col -= EDIT_TEXT_HORIZONTAL_OFFSET + option_line_state_width;
533 if (!edit->fullscreen)
535 end_col--;
536 if (w->x + w->cols <= WIDGET (w->owner)->cols)
537 end_col--;
540 color = edit_get_syntax_color (edit, b - 1);
541 q = edit_move_forward3 (edit, b, start_col - edit->start_col, 0);
542 start_col_real = (col = (int) edit_move_forward3 (edit, b, 0, q)) + edit->start_col;
544 if (option_line_state)
546 unsigned int cur_line;
548 cur_line = edit->start_line + row;
549 if (cur_line <= (unsigned int) edit->buffer.lines)
551 g_snprintf (line_stat, LINE_STATE_WIDTH + 1, "%7i ", cur_line + 1);
553 else
555 memset (line_stat, ' ', LINE_STATE_WIDTH);
556 line_stat[LINE_STATE_WIDTH] = '\0';
558 if (book_mark_query_color (edit, cur_line, BOOK_MARK_COLOR))
560 g_snprintf (line_stat, 2, "*");
564 if (col + 16 > -edit->start_col)
566 eval_marks (edit, &m1, &m2);
568 if (row <= edit->buffer.lines - edit->start_line)
570 off_t tws = 0;
571 if (tty_use_colors () && visible_tws)
573 unsigned int c;
575 tws = edit_buffer_get_eol (&edit->buffer, b);
576 while (tws > b
577 && ((c = edit_buffer_get_byte (&edit->buffer, tws - 1)) == ' ' || c == '\t'))
578 tws--;
581 while (col <= end_col - edit->start_col)
583 int cw = 1;
584 unsigned int c;
585 gboolean wide_width_char = FALSE;
586 gboolean control_char = FALSE;
588 p->ch = 0;
589 p->style = 0;
590 if (q == edit->buffer.curs1)
591 p->style |= MOD_CURSOR;
592 if (q >= m1 && q < m2)
594 if (edit->column_highlight)
596 long x;
597 long c1, c2;
599 x = (long) edit_move_forward3 (edit, b, 0, q);
600 c1 = min (edit->column1, edit->column2);
601 c2 = max (edit->column1, edit->column2);
602 if (x >= c1 && x < c2)
603 p->style |= MOD_MARKED;
605 else
606 p->style |= MOD_MARKED;
608 if (q == edit->bracket)
609 p->style |= MOD_BOLD;
610 if (q >= edit->found_start && q < (off_t) (edit->found_start + edit->found_len))
611 p->style |= MOD_BOLD;
613 #ifdef HAVE_CHARSET
614 if (edit->utf8)
615 c = edit_buffer_get_utf (&edit->buffer, q, &cw);
616 else
617 #endif
618 c = edit_buffer_get_byte (&edit->buffer, q);
620 /* we don't use bg for mc - fg contains both */
621 if (book_mark)
623 p->style |= book_mark << 16;
625 else
627 color = edit_get_syntax_color (edit, q);
628 p->style |= color << 16;
630 switch (c)
632 case '\n':
633 col = end_col - edit->start_col + 1; /* quit */
634 break;
635 case '\t':
637 int tab_over;
638 int i;
640 i = TAB_SIZE - ((int) col % TAB_SIZE);
641 tab_over = (end_col - edit->start_col) - (col + i - 1);
642 if (tab_over < 0)
643 i += tab_over;
644 col += i;
645 if (tty_use_colors () &&
646 ((visible_tabs || (visible_tws && q >= tws)) && enable_show_tabs_tws))
648 if (p->style & MOD_MARKED)
649 c = p->style;
650 else if (book_mark)
651 c |= book_mark << 16;
652 else
653 c = p->style | MOD_WHITESPACE;
654 if (i > 2)
656 p->ch = '<';
657 p->style = c;
658 p++;
659 while (--i > 1)
661 p->ch = '-';
662 p->style = c;
663 p++;
665 p->ch = '>';
666 p->style = c;
667 p++;
669 else if (i > 1)
671 p->ch = '<';
672 p->style = c;
673 p++;
674 p->ch = '>';
675 p->style = c;
676 p++;
678 else
680 p->ch = '>';
681 p->style = c;
682 p++;
685 else if (tty_use_colors () && visible_tws && q >= tws
686 && enable_show_tabs_tws)
688 p->ch = '.';
689 p->style |= MOD_WHITESPACE;
690 c = p->style & ~MOD_CURSOR;
691 p++;
692 while (--i)
694 p->ch = ' ';
695 p->style = c;
696 p++;
699 else
701 p->ch |= ' ';
702 c = p->style & ~MOD_CURSOR;
703 p++;
704 while (--i)
706 p->ch = ' ';
707 p->style = c;
708 p++;
712 break;
713 case ' ':
714 if (tty_use_colors () && visible_tws && q >= tws && enable_show_tabs_tws)
716 p->ch = '.';
717 p->style |= MOD_WHITESPACE;
718 p++;
719 col++;
720 break;
722 /* fallthrough */
723 default:
724 #ifdef HAVE_CHARSET
725 if (mc_global.utf8_display)
727 if (!edit->utf8)
729 c = convert_from_8bit_to_utf_c ((unsigned char) c, edit->converter);
731 else
733 if (g_unichar_iswide (c))
735 wide_width_char = TRUE;
736 col++;
740 else if (edit->utf8)
741 c = convert_from_utf_to_current_c (c, edit->converter);
742 else
743 c = convert_to_display_c (c);
744 #endif
746 /* Caret notation for control characters */
747 if (c < 32)
749 p->ch = '^';
750 p->style = abn_style;
751 p++;
752 p->ch = c + 0x40;
753 p->style = abn_style;
754 p++;
755 col += 2;
756 control_char = TRUE;
757 break;
759 if (c == 127)
761 p->ch = '^';
762 p->style = abn_style;
763 p++;
764 p->ch = '?';
765 p->style = abn_style;
766 p++;
767 col += 2;
768 control_char = TRUE;
769 break;
771 #ifdef HAVE_CHARSET
772 if (edit->utf8)
774 if (g_unichar_isprint (c))
775 p->ch = c;
776 else
778 p->ch = '.';
779 p->style = abn_style;
781 p++;
783 else
784 #endif
786 if ((mc_global.utf8_display && g_unichar_isprint (c)) ||
787 (!mc_global.utf8_display && is_printable (c)))
789 p->ch = c;
790 p++;
792 else
794 p->ch = '.';
795 p->style = abn_style;
796 p++;
799 col++;
800 break;
801 } /* case */
803 q++;
804 if (cw > 1)
806 q += cw - 1;
809 if (col > (end_col - edit->start_col + 1))
811 if (wide_width_char)
813 p--;
814 break;
816 if (control_char)
818 p -= 2;
819 break;
825 else
827 start_col_real = start_col = 0;
830 p->ch = 0;
832 print_to_widget (edit, row, start_col, start_col_real, end_col, line, line_stat, book_mark);
835 /* --------------------------------------------------------------------------------------------- */
837 static inline void
838 edit_draw_this_char (WEdit * edit, off_t curs, long row, long start_column, long end_column)
840 off_t b = edit_buffer_get_bol (&edit->buffer, curs);
842 edit_draw_this_line (edit, b, row, start_column, end_column);
845 /* --------------------------------------------------------------------------------------------- */
846 /** cursor must be in screen for other than REDRAW_PAGE passed in force */
848 static inline void
849 render_edit_text (WEdit * edit, long start_row, long start_column, long end_row, long end_column)
851 static long prev_curs_row = 0;
852 static off_t prev_curs = 0;
854 Widget *w = WIDGET (edit);
855 Widget *wh = WIDGET (w->owner);
857 int force = edit->force;
858 int y1, x1, y2, x2;
860 int last_line;
861 int last_column;
863 /* draw only visible region */
865 last_line = wh->y + wh->lines - 1;
867 y1 = w->y;
868 if (y1 > last_line - 1 /* buttonbar */ )
869 return;
871 last_column = wh->x + wh->cols - 1;
873 x1 = w->x;
874 if (x1 > last_column)
875 return;
877 y2 = w->y + w->lines - 1;
878 if (y2 < wh->y + 1 /* menubar */ )
879 return;
881 x2 = w->x + w->cols - 1;
882 if (x2 < wh->x)
883 return;
885 if ((force & REDRAW_IN_BOUNDS) == 0)
887 /* !REDRAW_IN_BOUNDS means to ignore bounds and redraw whole rows */
888 /* draw only visible region */
890 if (y2 <= last_line - 1 /* buttonbar */ )
891 end_row = w->lines - 1;
892 else if (y1 >= wh->y + 1 /* menubar */ )
893 end_row = wh->lines - 1 - y1 - 1;
894 else
895 end_row = start_row + wh->lines - 1 - 1;
897 if (x2 <= last_column)
898 end_column = w->cols - 1;
899 else if (x1 >= wh->x)
900 end_column = wh->cols - 1 - x1;
901 else
902 end_column = start_column + wh->cols - 1;
906 * If the position of the page has not moved then we can draw the cursor
907 * character only. This will prevent line flicker when using arrow keys.
909 if ((force & REDRAW_CHAR_ONLY) == 0 || (force & REDRAW_PAGE) != 0)
911 long row, b;
913 if ((force & REDRAW_PAGE) != 0)
915 row = start_row;
916 b = edit_buffer_move_forward (&edit->buffer, edit->start_display, start_row, 0);
917 while (row <= end_row)
919 if (key_pending (edit))
920 return;
921 edit_draw_this_line (edit, b, row, start_column, end_column);
922 b = edit_buffer_move_forward (&edit->buffer, b, 1, 0);
923 row++;
926 else
928 long curs_row = edit->curs_row;
930 if ((force & REDRAW_BEFORE_CURSOR) != 0 && start_row < curs_row)
932 long upto = curs_row - 1 <= end_row ? curs_row - 1 : end_row;
934 row = start_row;
935 b = edit->start_display;
936 while (row <= upto)
938 if (key_pending (edit))
939 return;
940 edit_draw_this_line (edit, b, row, start_column, end_column);
941 b = edit_buffer_move_forward (&edit->buffer, b, 1, 0);
945 /* if (force & REDRAW_LINE) ---> default */
946 b = edit_buffer_get_current_bol (&edit->buffer);
947 if (curs_row >= start_row && curs_row <= end_row)
949 if (key_pending (edit))
950 return;
951 edit_draw_this_line (edit, b, curs_row, start_column, end_column);
954 if ((force & REDRAW_AFTER_CURSOR) != 0 && end_row > curs_row)
956 row = curs_row + 1 < start_row ? start_row : curs_row + 1;
957 b = edit_buffer_move_forward (&edit->buffer, b, 1, 0);
958 while (row <= end_row)
960 if (key_pending (edit))
961 return;
962 edit_draw_this_line (edit, b, row, start_column, end_column);
963 b = edit_buffer_move_forward (&edit->buffer, b, 1, 0);
964 row++;
968 if ((force & REDRAW_LINE_ABOVE) != 0 && curs_row >= 1)
970 row = curs_row - 1;
971 b = edit_buffer_move_backward (&edit->buffer,
972 edit_buffer_get_current_bol (&edit->buffer), 1);
973 if (row >= start_row && row <= end_row)
975 if (key_pending (edit))
976 return;
977 edit_draw_this_line (edit, b, row, start_column, end_column);
981 if ((force & REDRAW_LINE_BELOW) != 0 && row < w->lines - 1)
983 row = curs_row + 1;
984 b = edit_buffer_get_current_bol (&edit->buffer);
985 b = edit_buffer_move_forward (&edit->buffer, b, 1, 0);
986 if (row >= start_row && row <= end_row)
988 if (key_pending (edit))
989 return;
990 edit_draw_this_line (edit, b, row, start_column, end_column);
995 else if (prev_curs_row < edit->curs_row)
997 /* with the new text highlighting, we must draw from the top down */
998 edit_draw_this_char (edit, prev_curs, prev_curs_row, start_column, end_column);
999 edit_draw_this_char (edit, edit->buffer.curs1, edit->curs_row, start_column, end_column);
1001 else
1003 edit_draw_this_char (edit, edit->buffer.curs1, edit->curs_row, start_column, end_column);
1004 edit_draw_this_char (edit, prev_curs, prev_curs_row, start_column, end_column);
1007 edit->force = 0;
1009 prev_curs_row = edit->curs_row;
1010 prev_curs = edit->buffer.curs1;
1013 /* --------------------------------------------------------------------------------------------- */
1015 static inline void
1016 edit_render (WEdit * edit, int page, int row_start, int col_start, int row_end, int col_end)
1018 if (page) /* if it was an expose event, 'page' would be set */
1019 edit->force |= REDRAW_PAGE | REDRAW_IN_BOUNDS;
1021 render_edit_text (edit, row_start, col_start, row_end, col_end);
1024 * edit->force != 0 means a key was pending and the redraw
1025 * was halted, so next time we must redraw everything in case stuff
1026 * was left undrawn from a previous key press.
1028 if (edit->force)
1029 edit->force |= REDRAW_PAGE;
1032 /* --------------------------------------------------------------------------------------------- */
1033 /*** public functions ****************************************************************************/
1034 /* --------------------------------------------------------------------------------------------- */
1036 void
1037 edit_status (WEdit * edit, gboolean active)
1039 int color;
1041 if (edit->fullscreen)
1043 color = STATUSBAR_COLOR;
1044 edit_status_fullscreen (edit, color);
1046 else
1048 color = edit->drag_state != MCEDIT_DRAG_NORMAL ? EDITOR_FRAME_DRAG : active ?
1049 EDITOR_FRAME_ACTIVE : EDITOR_FRAME;
1050 edit_draw_frame (edit, color, active);
1051 edit_status_window (edit);
1054 edit_draw_window_icons (edit, color);
1057 /* --------------------------------------------------------------------------------------------- */
1059 /** this scrolls the text so that cursor is on the screen */
1060 void
1061 edit_scroll_screen_over_cursor (WEdit * edit)
1063 Widget *w = WIDGET (edit);
1065 long p;
1066 long outby;
1067 int b_extreme, t_extreme, l_extreme, r_extreme;
1069 if (w->lines <= 0 || w->cols <= 0)
1070 return;
1072 w->lines -= EDIT_TEXT_VERTICAL_OFFSET;
1073 w->cols -= EDIT_TEXT_HORIZONTAL_OFFSET + option_line_state_width;
1075 if (!edit->fullscreen)
1077 w->x++;
1078 w->cols -= 2;
1079 w->y++;
1080 w->lines -= 2;
1083 r_extreme = EDIT_RIGHT_EXTREME;
1084 l_extreme = EDIT_LEFT_EXTREME;
1085 b_extreme = EDIT_BOTTOM_EXTREME;
1086 t_extreme = EDIT_TOP_EXTREME;
1087 if (edit->found_len != 0)
1089 b_extreme = max (w->lines / 4, b_extreme);
1090 t_extreme = max (w->lines / 4, t_extreme);
1092 if (b_extreme + t_extreme + 1 > w->lines)
1094 int n;
1096 n = b_extreme + t_extreme;
1097 if (n == 0)
1098 n = 1;
1099 b_extreme = (b_extreme * (w->lines - 1)) / n;
1100 t_extreme = (t_extreme * (w->lines - 1)) / n;
1102 if (l_extreme + r_extreme + 1 > w->cols)
1104 int n;
1106 n = l_extreme + t_extreme;
1107 if (n == 0)
1108 n = 1;
1109 l_extreme = (l_extreme * (w->cols - 1)) / n;
1110 r_extreme = (r_extreme * (w->cols - 1)) / n;
1112 p = edit_get_col (edit) + edit->over_col;
1113 edit_update_curs_row (edit);
1114 outby = p + edit->start_col - w->cols + 1 + (r_extreme + edit->found_len);
1115 if (outby > 0)
1116 edit_scroll_right (edit, outby);
1117 outby = l_extreme - p - edit->start_col;
1118 if (outby > 0)
1119 edit_scroll_left (edit, outby);
1120 p = edit->curs_row;
1121 outby = p - w->lines + 1 + b_extreme;
1122 if (outby > 0)
1123 edit_scroll_downward (edit, outby);
1124 outby = t_extreme - p;
1125 if (outby > 0)
1126 edit_scroll_upward (edit, outby);
1127 edit_update_curs_row (edit);
1129 w->lines += EDIT_TEXT_VERTICAL_OFFSET;
1130 w->cols += EDIT_TEXT_HORIZONTAL_OFFSET + option_line_state_width;
1131 if (!edit->fullscreen)
1133 w->x--;
1134 w->cols += 2;
1135 w->y--;
1136 w->lines += 2;
1140 /* --------------------------------------------------------------------------------------------- */
1142 void
1143 edit_render_keypress (WEdit * edit)
1145 edit_render (edit, 0, 0, 0, 0, 0);
1148 /* --------------------------------------------------------------------------------------------- */