1 /* This file is part of
2 * ======================================================
4 * LyX, The Document Processor
6 * Copyright 1995 Matthias Ettrich
7 * Copyright 1995-1998 The LyX Team
9 * ====================================================== */
14 #pragma implementation "lyxscreen.h"
17 #include "lyxscreen.h"
21 extern int mono_video;
22 extern int fast_selection;
25 LyXScreen::LyXScreen(Window window,
31 : text(text_ptr), _window(window),
32 _width(width), _height(height),
33 _offset_x(offset_x), _offset_y(offset_y)
37 /* the cursor isnt yet visible */
38 cursor_visible = false;
39 screen_refresh_y = -1;
41 /* create the foreground pixmap */
42 foreground = XCreatePixmap (fl_display,
45 fl_get_visual_depth());
55 LyXScreen::~LyXScreen()
57 XFreePixmap(fl_display, foreground);
61 void LyXScreen::Redraw()
63 DrawFromTo(0, _height);
64 screen_refresh_y = -1;
65 expose(0, 0, _width, _height);
67 cursor_visible = false;
73 void LyXScreen::expose(int x, int y, int exp_width, int exp_height)
80 exp_width, exp_height,
81 x+_offset_x, y+_offset_y);
85 void LyXScreen::DrawFromTo(int y1, int y2)
87 long y_text = first + y1;
89 /* get the first needed row */
90 Row * row = text->GetRowNearY(y_text);
91 /* y_text is now the real beginning of the row */
93 long y = y_text - first;
94 /* y1 is now the real beginning of row on the screen */
96 while (row != 0 && y < y2) {
98 text->GetVisibleRow(*this, y, row, y + first);
104 /* maybe we have to clear the screen at the bottom */
106 fillRectangle(gc_lighted,
115 void LyXScreen::DrawOneRow(Row * row, long & y_text)
117 long y = y_text - first;
119 if (y + row->height > 0 && y - row->height <= _height) {
120 /* ok there is something visible */
121 text->GetVisibleRow(*this, y, row, y + first);
123 y_text+= row->height;
127 /* draws the screen, starting with textposition y. uses as much already
128 * printed pixels as possible */
129 void LyXScreen::Draw(long y)
131 if (cursor_visible) HideCursor();
134 long old_first = first;
137 /* is any optimiziation possible? */
138 if ((y - old_first) < _height
139 && (old_first - y) < _height) {
140 if (first < old_first) {
141 DrawFromTo(0, old_first - first);
142 XCopyArea (fl_display,
146 _offset_x, _offset_y,
147 _width , _height - old_first + first,
148 _offset_x, _offset_y + old_first - first);
149 // expose the area drawn
150 expose(0, 0, _width, old_first - first);
152 DrawFromTo(_height + old_first - first, _height);
153 XCopyArea (fl_display,
157 _offset_x, _offset_y + first - old_first,
158 _width , _height + old_first - first,
159 _offset_x, _offset_y);
160 // expose the area drawn
161 expose(0, _height + old_first - first,
162 _width, first - old_first);
165 /* make a dumb new-draw */
166 DrawFromTo(0, _height);
167 expose(0, 0, _width, _height);
172 void LyXScreen::ShowCursor()
178 if (cursor_visible) return;
182 y1 = text->cursor.y - text->real_current_font.maxAscent() - first;
185 y2 = text->cursor.y + text->real_current_font.maxDescent() - first;
186 if (y2 > _height) y2 = _height;
188 // Secure against very strange situations
189 if (y2 < y1) y2 = y1;
191 if (fast_selection || mono_video) {
192 if (y2 > 0 && y1 < _height) {
193 XDrawLine(fl_display,
194 _window, getGC(gc_select),
199 cursor_visible = true;
203 XFreePixmap(fl_display, cursor_pixmap);
207 if (y2 > 0 && y1 < _height) {
209 cursor_pixmap_h = y2 - y1 + 1;
211 cursor_pixmap_y = y1;
213 XCreatePixmap(fl_display,
217 fl_get_visual_depth());
218 XCopyArea(fl_display,
222 _offset_x + cursor_pixmap_x,
223 _offset_y + cursor_pixmap_y,
224 cursor_pixmap_w, cursor_pixmap_h,
226 XDrawLine(fl_display,
227 _window, getGC(gc_copy),
232 cursor_visible = true;
238 /* returns 1 if first has changed, otherwise 0 */
239 int LyXScreen::FitManualCursor(long /*x*/, long y, int asc, int desc)
243 if (y + desc - first >= _height)
244 newtop = y - 3*_height / 4; /* the scroll region must be so big!! */
245 else if (y - asc < first
247 newtop = y - _height / 4;
252 if (newtop != first){
261 void LyXScreen::HideManualCursor(long x, long y, int asc, int desc)
263 if (fast_selection || mono_video)
264 ShowManualCursor(x, y, asc, desc);
270 void LyXScreen::ShowManualCursor(long x, long y, int asc, int desc)
275 y1 = y - first - asc;
278 y2 = y -first + desc;
282 if (fast_selection || mono_video) {
283 if (y2 > 0 && y1 < _height) {
284 XDrawLine(fl_display,
285 _window, getGC(gc_select),
293 XFreePixmap(fl_display, cursor_pixmap);
297 if (y2 > 0 && y1 < _height) {
299 cursor_pixmap_h = y2 - y1 + 1;
301 cursor_pixmap_y = y1;
303 XCreatePixmap (fl_display,
307 fl_get_visual_depth());
309 XCopyArea (fl_display,
313 _offset_x + cursor_pixmap_x,
314 _offset_y + cursor_pixmap_y,
318 XDrawLine(fl_display,
319 _window, getGC(gc_copy),
325 cursor_visible = true;
330 void LyXScreen::HideCursor()
332 if (!cursor_visible) return;
334 if (fast_selection || mono_video) {
335 cursor_visible = false;
337 cursor_visible = false;
340 XCopyArea (fl_display,
345 cursor_pixmap_w, cursor_pixmap_h,
346 cursor_pixmap_x + _offset_x,
347 cursor_pixmap_y + _offset_y);
349 cursor_visible = false;
354 void LyXScreen::CursorToggle()
363 /* returns a new top so that the cursor is visible */
364 long LyXScreen::TopCursorVisible()
369 - text->cursor.row->baseline
370 + text->cursor.row->height
371 - first >= _height) {
372 if (text->cursor.row->height < _height
373 && text->cursor.row->height > _height/4)
374 newtop = text->cursor.y
375 + text->cursor.row->height
376 - text->cursor.row->baseline - _height;
378 newtop = text->cursor.y
379 - 3*_height / 4; /* the scroll region must be so big!! */
380 } else if (text->cursor.y - text->cursor.row->baseline < first
382 if (text->cursor.row->height < _height
383 && text->cursor.row->height > _height/4)
384 newtop = text->cursor.y - text->cursor.row->baseline;
386 newtop = text->cursor.y - _height / 4;
398 /* scrolls the screen so that the cursor is visible, if necessary.
399 * returns 1 if a change was made, otherwise 0 */
400 int LyXScreen::FitCursor()
402 /* is a change necessary */
403 long newtop = TopCursorVisible();
404 int result = (newtop != first);
411 void LyXScreen::Update()
415 if (text->status == LyXText::NEED_MORE_REFRESH
416 || screen_refresh_y > -1 ) {
417 if (screen_refresh_y > -1
418 && screen_refresh_y < text->refresh_y)
419 y = screen_refresh_y;
423 if (y < first) y = first;
425 DrawFromTo(y - first, _height);
427 text->status = LyXText::UNCHANGED;
428 screen_refresh_y = -1;
429 expose(0, y-first, _width, _height - (y - first));
430 } else if (text->status == LyXText::NEED_VERY_LITTLE_REFRESH) {
431 /* ok I will update the current cursor row */
433 DrawOneRow(text->refresh_row, y);
434 text->status = LyXText::UNCHANGED;
435 expose(0, text->refresh_y-first,
436 _width, text->refresh_row->height);
441 void LyXScreen::SmallUpdate()
447 if (text->status == LyXText::NEED_MORE_REFRESH){
448 /* ok I will update till the current cursor row */
449 row = text->refresh_row;
453 if (y > text->cursor.y) {
458 while (row && row != text->cursor.row && y < first + _height) {
464 screen_refresh_y = y;
465 screen_refresh_row = row->next;
466 text->status = LyXText::UNCHANGED;
467 // Is the right regin exposed?
468 expose(0, y2-first, _width, y-y2);
469 } else if (text->status == LyXText::NEED_VERY_LITTLE_REFRESH) {
470 /* ok I will update the current cursor row */
471 row = text->refresh_row;
474 text->status = LyXText::UNCHANGED;
475 expose(0, text->refresh_y - first,
476 _width, row->height);
481 void LyXScreen::ToggleSelection(bool kill_selection)
483 /* only if there is a selection */
484 if (!text->selection)
491 if (fast_selection || mono_video) {
493 /* selection only in one row ?*/
494 if (text->sel_start_cursor.y == text->sel_end_cursor.y) {
496 /* only if something is visible */
497 if (text->sel_start_cursor.y
498 - text->sel_start_cursor.row->baseline
500 && text->sel_start_cursor.y
501 - text->sel_start_cursor.row->baseline +
502 text->sel_start_cursor.row->height - first > 0) {
503 top = text->sel_start_cursor.y
504 - text->sel_start_cursor.row->baseline
507 + text->sel_start_cursor.row->height;
510 if (bottom > _height)
512 XFillRectangle(fl_display, _window,
514 text->sel_start_cursor.x
517 text->sel_end_cursor.x
518 - text->sel_start_cursor.x,
522 /* the sel_start_cursor row first */
523 /* only if anything is visible */
524 if (text->sel_start_cursor.y
525 - text->sel_start_cursor.row->baseline
527 && text->sel_start_cursor.y
528 - text->sel_start_cursor.row->baseline +
529 text->sel_start_cursor.row->height - first > 0) {
530 top = text->sel_start_cursor.y
531 - text->sel_start_cursor.row->baseline
534 + text->sel_start_cursor.row->height;
537 if (bottom > _height)
539 XFillRectangle(fl_display, _window,
541 text->sel_start_cursor.x
545 - text->sel_start_cursor.x,
551 if (text->sel_start_cursor.row->next !=
552 text->sel_end_cursor.row) {
553 top = text->sel_start_cursor.y
554 - text->sel_start_cursor.row->baseline
555 + text->sel_start_cursor.row->height;
556 bottom = text->sel_end_cursor.y
557 - text->sel_end_cursor.row->baseline;
561 if (bottom - first < 0)
564 if (bottom - first > _height)
565 bottom = first + _height;
566 if (top - first > _height)
567 top = first + _height;
570 XFillRectangle(fl_display,
574 top - first+_offset_y,
580 /* the sel_end_cursor row last */
581 if (text->sel_end_cursor.y
582 - text->sel_end_cursor.row->baseline
584 && text->sel_end_cursor.y
585 - text->sel_end_cursor.row->baseline +
586 text->sel_end_cursor.row->height - first > 0) {
587 top = text->sel_end_cursor.y
588 - text->sel_end_cursor.row->baseline
591 + text->sel_end_cursor.row->height;
594 if (bottom > _height)
596 XFillRectangle(fl_display, _window,
600 text->sel_end_cursor.x,
605 top = text->sel_start_cursor.y
606 - text->sel_start_cursor.row->baseline;
607 bottom = text->sel_end_cursor.y
608 - text->sel_end_cursor.row->baseline
609 + text->sel_end_cursor.row->height;
613 if (bottom - first < 0)
616 if (bottom - first > _height)
617 bottom = first + _height;
618 if (top - first > _height)
619 top = first + _height;
623 DrawFromTo(top - first, bottom - first);
624 expose(0, top - first, _width, bottom - first - (top - first));
629 void LyXScreen::ToggleToggle()
634 if (text->toggle_cursor.par == text->toggle_end_cursor.par
635 && text->toggle_cursor.pos == text->toggle_end_cursor.pos)
638 if (fast_selection || mono_video) {
640 /* selection only in one row ?*/
641 if (text->toggle_cursor.y == text->toggle_end_cursor.y) {
643 /* only if anything is visible */
644 if (text->toggle_cursor.y - text->toggle_cursor.row->baseline - first < _height
645 && text->toggle_cursor.y - text->toggle_cursor.row->baseline +
646 text->toggle_cursor.row->height - first > 0) {
647 top = text->toggle_cursor.y - text->toggle_cursor.row->baseline - first;
648 bottom = top + text->toggle_cursor.row->height;
649 if (top < 0) top = 0;
650 if (bottom > _height) bottom = _height;
651 XFillRectangle(fl_display, _window,
653 text->toggle_cursor.x+_offset_x,
655 text->toggle_end_cursor.x -
656 text->toggle_cursor.x,
660 /* the toggle_cursor row first */
661 /* only if anything is visible */
662 if (text->toggle_cursor.y - text->toggle_cursor.row->baseline - first < _height
663 && text->toggle_cursor.y - text->toggle_cursor.row->baseline +
664 text->toggle_cursor.row->height - first > 0) {
665 top = text->toggle_cursor.y - text->toggle_cursor.row->baseline - first;
666 bottom = top + text->toggle_cursor.row->height;
669 if (bottom > _height)
671 XFillRectangle(fl_display, _window,
673 text->toggle_cursor.x+_offset_x,
675 _width - text->toggle_cursor.x,
681 if (text->toggle_cursor.row->next !=
682 text->toggle_end_cursor.row) {
683 top = text->toggle_cursor.y
684 - text->toggle_cursor.row->baseline
685 + text->toggle_cursor.row->height;
686 bottom = text->toggle_end_cursor.y
687 - text->toggle_end_cursor.row->baseline;
691 if (bottom - first < 0)
694 if (bottom - first > _height)
695 bottom = first + _height;
696 if (top - first > _height)
697 top = first + _height;
700 XFillRectangle(fl_display, _window,
703 top - first+_offset_y,
709 /* the toggle_end_cursor row last */
710 if (text->toggle_end_cursor.y - text->toggle_end_cursor.row->baseline - first < _height
711 && text->toggle_end_cursor.y - text->toggle_end_cursor.row->baseline +
712 text->toggle_end_cursor.row->height - first > 0) {
713 top = text->toggle_end_cursor.y
714 - text->toggle_end_cursor.row->baseline
717 + text->toggle_end_cursor.row->height;
720 if (bottom > _height)
722 XFillRectangle(fl_display, _window,
726 text->toggle_end_cursor.x,
731 top = text->toggle_cursor.y
732 - text->toggle_cursor.row->baseline;
733 bottom = text->toggle_end_cursor.y
734 - text->toggle_end_cursor.row->baseline
735 + text->toggle_end_cursor.row->height;
739 if (bottom - first < 0)
742 if (bottom - first > _height)
743 bottom = first + _height;
744 if (top - first > _height)
745 top = first + _height;
747 DrawFromTo(top - first, bottom - first);
748 expose(0, top - first, _width, bottom - first - (top - first));
754 void LyXScreen::drawTableLine(int baseline, int x, int length, bool on_off)
758 gc = getGC(gc_thin_on_off_line);
769 void LyXScreen::drawVerticalTableLine(int x, int y1, int y2, bool on_off)
773 gc = getGC(gc_thin_on_off_line);
784 void LyXScreen::drawFrame(int /*ft*/, int x, int y, int w, int h,
785 FL_COLOR /*col*/, int /*b*/)
787 // Implement this using X11 calls, and the repaint problems are gone!
788 // At least, I think that should do it since we only have them after
789 // one of these buttons are displayed now! Lars, it seems you've hit the
791 // fl_winset(foreground);
792 // fl_drw_frame(ft, x, y, w, h, col, b);
793 // This should be changed to draw a button like frame, in the
794 // mean time we'll just use a regular rectangle
796 // I want the buttons back before 0.12. OK, this is very simple,
797 // like what is done in xforms sources. (Ale)
799 // This one is too dirty. Get rid of it.
802 // Please comment this annonymous variable.
805 // I think these calls to fl_color might make xforms sometimes
806 // draw the wrong color on other objects.
807 fl_color(FL_TOP_BCOL);
808 XFillRectangle(fl_display, foreground, fl_gc,
809 x - d, y - d, w + 2 * d, d);
810 fl_color(FL_BOTTOM_BCOL);
811 XFillRectangle(fl_display, foreground, fl_gc,
812 x - d, y + h, w + 2 * d, d);
814 // Now a couple of trapezoids
817 pl[0].x = x - d; pl[0].y = y - d;
818 pl[1].x = x - d; pl[1].y = y + h + d;
819 pl[2].x = x; pl[2].y = y + h;
820 pl[3].x = x; pl[3].y = y;
822 pr[0].x = x + w + d; pr[0].y = y - d;
823 pr[1].x = x + w + d; pr[1].y = y + h + d;
824 pr[2].x = x + w; pr[2].y = y + h;
825 pr[3].x = x + w; pr[3].y = y;
827 fl_color(FL_LEFT_BCOL);
828 XFillPolygon(fl_display,
831 Convex, CoordModeOrigin);
832 fl_color(FL_RIGHT_BCOL);
833 XFillPolygon(fl_display,
836 Convex, CoordModeOrigin);