fix include file case
[reactos.git] / rosapps / mc / edit / editdraw.c
1 /* editor text drawing.
2
3 Copyright (C) 1996, 1997 the Free Software Foundation
4
5 Authors: 1996, 1997 Paul Sheer
6
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.
11
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.
16
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. */
20
21 #include <config.h>
22 #include "edit.h"
23
24 #define MAX_LINE_LEN 1024
25
26 #ifndef MIDNIGHT
27 #include "app_glob.c"
28 #include "coollocal.h"
29 #else
30 #include "../src/mad.h"
31 #endif
32
33
34 static void status_string (WEdit * edit, char *s, int w, int fill, int font_width)
35 {
36 int i;
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);
48 i = strlen (s);
49 s[i] = ' ';
50 i = w;
51 do {
52 if (strchr (" +-*=/:b", s[i])) /* chop off the last word/number */
53 break;
54 s[i] = fill;
55 } while (i--);
56 s[i] = fill;
57 s[w] = 0;
58 }
59
60
61 #ifdef MIDNIGHT
62
63 /* how to get as much onto the status line as is numerically possible :) */
64 void edit_status (WEdit * edit)
65 {
66 int w, i, t;
67 char *s;
68 w = edit->widget.cols - (edit->have_frame * 2);
69 s = malloc (w + 15);
70 if (w < 4)
71 w = 4;
72 memset (s, ' ', w);
73 attrset (SELECTED_COLOR);
74 if (w > 4) {
75 widget_move (edit, edit->have_frame, edit->have_frame);
76 i = w > 24 ? 18 : w - 6;
77 i = i < 13 ? 13 : i;
78 sprintf (s, "%s", name_trunc (edit->filename ? edit->filename : "", i));
79 i += strlen (s);
80 s[strlen (s)] = ' ';
81 t = w - 20;
82 if (t < 0)
83 t = 0;
84 status_string (edit, s + 20, t, ' ', 1);
85 } else {
86 s[w] = 0;
87 }
88 printw ("%.*s", w, s);
89
90 attrset (NORMAL_COLOR);
91 free (s);
92 }
93
94 #else
95
96 extern int fixed_font;
97
98 void rerender_text (CWidget * wdt);
99
100 void edit_status (WEdit * edit)
101 {
102 if ((edit->widget->options & EDITOR_NO_TEXT)) {
103 return;
104 } else {
105 int w, i, t;
106 CWidget *wdt;
107 char id[33];
108 char s[160];
109 w = edit->num_widget_columns - 1;
110 if (w > 150)
111 w = 150;
112 if (w < 0)
113 w = 0;
114 memset (s, 0, w);
115 if (w > 1) {
116 i = w > 24 ? 18 : w - 6;
117 i = i < 13 ? 13 : i;
118 sprintf (s, "%s", name_trunc (edit->filename ? edit->filename : "", i));
119 i = strlen (s);
120 s[i] = ' ';
121 s[i+1] = ' ';
122 t = w - i - 2;
123 if (t < 0)
124 t = 0;
125 status_string (edit, s + i + 2, t, 0, FONT_MEAN_WIDTH);
126 }
127 s[w] = 0;
128 strcpy (id, edit->widget->ident);
129 strcat (id, ".text");
130 wdt = CIdent (id);
131 free (wdt->text);
132 wdt->text = strdup (s);
133 CSetWidgetSize (id, edit->widget->width, wdt->height);
134 rerender_text (wdt);
135 }
136 }
137
138
139 #endif
140
141
142 /* boolean */
143 int cursor_in_screen (WEdit * edit, long row)
144 {
145 if (row < 0 || row >= edit->num_widget_lines)
146 return 0;
147 else
148 return 1;
149 }
150
151 /* returns rows from the first displayed line to the cursor */
152 int cursor_from_display_top (WEdit * edit)
153 {
154 if (edit->curs1 < edit->start_display)
155 return -edit_move_forward (edit, edit->curs1, 0, edit->start_display);
156 else
157 return edit_move_forward (edit, edit->start_display, 0, edit->curs1);
158 }
159
160 /* returns how far the cursor is out of the screen */
161 int cursor_out_of_screen (WEdit * edit)
162 {
163 int row = cursor_from_display_top (edit);
164 if (row >= edit->num_widget_lines)
165 return row - edit->num_widget_lines + 1;
166 if (row < 0)
167 return row;
168 return 0;
169 }
170
171 #ifndef MIDNIGHT
172 extern unsigned char per_char[256];
173 int edit_width_of_long_printable (int c);
174 #endif
175
176 /* this scrolls the text so that cursor is on the screen */
177 void edit_scroll_screen_over_cursor (WEdit * edit)
178 {
179 int p, l;
180 int outby;
181 p = edit_get_col (edit);
182 edit_update_curs_row (edit);
183 #ifdef MIDNIGHT
184 outby = p + edit->start_col - edit->num_widget_columns + 1 + (EDIT_RIGHT_EXTREME + edit->found_len);
185 #else
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));
187 #endif
188 if (outby > 0)
189 edit_scroll_right (edit, outby);
190 #ifdef MIDNIGHT
191 outby = EDIT_LEFT_EXTREME - p - edit->start_col;
192 #else
193 outby = EDIT_LEFT_EXTREME * FONT_MEAN_WIDTH - p - edit->start_col;
194 #endif
195 if (outby > 0)
196 edit_scroll_left (edit, outby);
197 p = edit->curs_row;
198 l = 0;
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;
202 if (outby > 0)
203 edit_scroll_downward (edit, outby);
204 outby = EDIT_TOP_EXTREME - p + l;
205 if (outby > 0)
206 edit_scroll_upward (edit, outby);
207 edit_update_curs_row (edit);
208 }
209
210
211 #ifndef MIDNIGHT
212
213 #define CACHE_WIDTH 256
214 #define CACHE_HEIGHT 128
215
216 int EditExposeRedraw = 0;
217 int EditClear = 0;
218
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;
223
224 /* foreground colors */
225 unsigned long edit_normal_foreground_color, edit_bold_color;
226 unsigned long edit_italic_color;
227
228 /* cursor color */
229 unsigned long edit_cursor_color;
230
231 void edit_set_foreground_colors (unsigned long normal, unsigned long bold, unsigned long italic)
232 {
233 edit_normal_foreground_color = normal;
234 edit_bold_color = bold;
235 edit_italic_color = italic;
236 }
237
238 void edit_set_background_colors (unsigned long normal, unsigned long abnormal, unsigned long marked, unsigned long marked_abnormal, unsigned long highlighted)
239 {
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;
245 }
246
247 void edit_set_cursor_color (unsigned long c)
248 {
249 edit_cursor_color = c;
250 }
251
252 #else
253
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
258
259 static void set_color (int font)
260 {
261 attrset (font);
262 }
263
264 #define edit_move(x,y) widget_move(edit, y, x);
265
266 static void print_to_widget (WEdit * edit, long row, int start_col, float start_col_real, long end_col, unsigned int line[])
267 {
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;
271
272 set_color (DEF_COLOR);
273 edit_move (x1, y);
274 hline (' ', end_col + 1 - EDIT_TEXT_HORIZONTAL_OFFSET - x1);
275
276 edit_move (x + FONT_OFFSET_X, y + FONT_OFFSET_Y);
277 {
278 unsigned int *p = line;
279 int textchar = ' ';
280 long style;
281
282 while (*p) {
283 style = *p >> 8;
284 textchar = *p & 0xFF;
285 #ifdef HAVE_SYNTAXH
286 if (!(style & (0xFF - MOD_ABNORMAL - MOD_CURSOR)))
287 SLsmg_set_color ((*p & 0x007F0000) >> 16);
288 #endif
289 if (style & MOD_ABNORMAL)
290 textchar = '.';
291 if (style & MOD_HIGHLIGHTED) {
292 set_color (BOLD_COLOR);
293 } else if (style & MOD_MARKED) {
294 set_color (MARK_COLOR);
295 }
296 if (style & MOD_UNDERLINED) {
297 set_color (UNDERLINE_COLOR);
298 }
299 if (style & MOD_BOLD) {
300 set_color (BOLD_COLOR);
301 }
302 addch (textchar);
303 p++;
304 }
305 }
306 }
307
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)
310 {
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;
315 unsigned int c;
316 int fg, bg;
317 int i;
318
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;
322
323 if (col + 16 > -edit->start_col) {
324 eval_marks (edit, &m1, &m2);
325
326 if (row <= edit->total_lines - edit->start_line) {
327 while (col <= end_col - edit->start_col) {
328 *p = 0;
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 */
340 *p |= fg << 16;
341 q++;
342 switch (c) {
343 case '\n':
344 col = end_col - edit->start_col + 1; /* quit */
345 *(p++) |= ' ';
346 break;
347 case '\t':
348 i = TAB_SIZE - ((int) col % TAB_SIZE);
349 *p |= ' ';
350 c = *(p++) & (0xFFFFFFFF - MOD_CURSOR * 256);
351 col += i;
352 while (--i)
353 *(p++) = c;
354 break;
355 case '\r':
356 break;
357 default:
358 if (is_printable (c)) {
359 *(p++) |= c;
360 } else {
361 *(p++) = '.';
362 *p |= (256 * MOD_ABNORMAL);
363 }
364 col++;
365 break;
366 }
367 }
368 }
369 } else {
370 start_col_real = start_col = 0;
371 }
372 *p = 0;
373
374 print_to_widget (edit, row, start_col, start_col_real, end_col, line);
375 }
376
377 #endif
378
379 #ifdef MIDNIGHT
380
381 #define key_pending(x) (!is_idle())
382
383 #else
384
385 int edit_mouse_pending (Window win);
386 #define edit_draw_this_line edit_draw_this_line_proportional
387
388 static int key_pending (WEdit * edit)
389 {
390 if (!(edit->force & REDRAW_COMPLETELY) && !EditExposeRedraw)
391 return CKeyPending ();
392 return 0;
393 }
394
395 #endif
396
397
398 /* b for pointer to begining of line */
399 static void edit_draw_this_char (WEdit * edit, long curs, long row)
400 {
401 int b = edit_bol (edit, curs);
402 #ifdef MIDNIGHT
403 edit_draw_this_line (edit, b, row, 0, edit->num_widget_columns - 1);
404 #else
405 edit_draw_this_line (edit, b, row, 0, edit->widget->width);
406 #endif
407 }
408
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)
411 {
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;
417
418 #ifndef MIDNIGHT
419 static Window prev_win = 0;
420 #endif
421 int fg, bg;
422
423 int force = edit->force;
424 long b;
425
426 /*
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.
429 */
430 if ((!(force & REDRAW_CHAR_ONLY)) || (force & REDRAW_PAGE)
431 #ifndef MIDNIGHT
432 || prev_win != edit->widget->winid
433 #endif
434 ) {
435 if (!(force & REDRAW_IN_BOUNDS)) { /* !REDRAW_IN_BOUNDS means to ignore bounds and redraw whole rows */
436 start_row = 0;
437 end_row = edit->num_widget_lines - 1;
438 start_column = 0;
439 #ifdef MIDNIGHT
440 end_column = edit->num_widget_columns - 1;
441 #else
442 end_column = edit->widget->width;
443 #endif
444 }
445 if (force & REDRAW_PAGE) {
446 row = start_row;
447 b = edit_move_forward (edit, edit->start_display, start_row, 0);
448 while (row <= end_row) {
449 if (key_pending (edit))
450 goto exit_render;
451 edit_draw_this_line (edit, b, row, start_column, end_column);
452 b = edit_move_forward (edit, b, 1, 0);
453 row++;
454 }
455 } else {
456 curs_row = edit->curs_row;
457
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;
461 row = start_row;
462 b = edit->start_display;
463 while (row <= upto) {
464 if (key_pending (edit))
465 goto exit_render;
466 edit_draw_this_line (edit, b, row, start_column, end_column);
467 b = edit_move_forward (edit, b, 1, 0);
468 }
469 }
470 }
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))
475 goto exit_render;
476 edit_draw_this_line (edit, b, curs_row, start_column, end_column);
477 }
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))
484 goto exit_render;
485 edit_draw_this_line (edit, b, row, start_column, end_column);
486 b = edit_move_forward (edit, b, 1, 0);
487 row++;
488 }
489 }
490 }
491 if (force & REDRAW_LINE_ABOVE && curs_row >= 1) {
492 row = 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))
496 goto exit_render;
497 edit_draw_this_line (edit, b, row, start_column, end_column);
498 }
499 }
500 if (force & REDRAW_LINE_BELOW && row < edit->num_widget_lines - 1) {
501 row = curs_row + 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))
506 goto exit_render;
507 edit_draw_this_line (edit, b, row, start_column, end_column);
508 }
509 }
510 }
511 } else {
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);
515 } else {
516 edit_draw_this_char (edit, edit->curs1, edit->curs_row);
517 edit_draw_this_char (edit, prev_curs, prev_curs_row);
518 }
519 }
520
521 edit->force = 0;
522
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;
527 #ifndef MIDNIGHT
528 prev_win = edit->widget->winid;
529 #endif
530 exit_render:
531 edit_get_syntax_color (edit, edit->start_display - 1, &fg, &bg);
532 }
533
534
535
536 #ifndef MIDNIGHT
537
538 void edit_convert_expose_to_area (XExposeEvent * xexpose, int *row1, int *col1, int *row2, int *col2)
539 {
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;
544 }
545
546 void edit_render_tidbits (CWidget * wdt)
547 {
548 int isfocussed;
549 int w = wdt->width, h = wdt->height;
550 Window win;
551
552 win = wdt->winid;
553 isfocussed = (win == CGetFocus ());
554
555 CSetColor (COLOR_FLAT);
556
557 if (isfocussed) {
558 render_bevel (win, 0, 0, w - 1, h - 1, 3, 1); /*most outer border bevel */
559 } else {
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 */
562 }
563 }
564
565 void edit_set_space_width (int s);
566 extern int option_long_whitespace;
567
568 #endif
569
570 void edit_render (WEdit * edit, int page, int row_start, int col_start, int row_end, int col_end)
571 {
572 int f = 0;
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);
576
577 #ifdef MIDNIGHT
578 if (edit->force & REDRAW_COMPLETELY)
579 redraw_labels (edit->widget.parent, (Widget *) edit);
580 #else
581 if (option_long_whitespace)
582 edit_set_space_width (per_char[' '] * 2);
583 else
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)
589 );
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)
596 );
597 edit_set_cursor_color (
598 color_palette (option_editor_fg_cursor)
599 );
600
601 if (!EditExposeRedraw)
602 set_cursor_position (0, 0, 0, 0, 0, 0, 0, 0, 0);
603 #endif
604
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;
610 #ifndef MIDNIGHT
611 if (f) {
612 edit_render_tidbits (edit->widget);
613 CSetColor (edit_normal_background_color);
614 CLine (edit->widget->winid, 3, 3, 3, edit->widget->height - 4);
615 }
616 #endif
617 }
618
619 #ifndef MIDNIGHT
620 void edit_render_expose (WEdit * edit, XExposeEvent * xexpose)
621 {
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);
629 } else {
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);
632 }
633 EditExposeRedraw = 0;
634 }
635
636 void edit_render_keypress (WEdit * edit)
637 {
638 edit_render (edit, 0, 0, 0, 0, 0);
639 }
640
641 #else
642
643 void edit_render_keypress (WEdit * edit)
644 {
645 edit_render (edit, 0, 0, 0, 0, 0);
646 }
647
648 #endif