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"
22 extern int mono_video;
23 extern int fast_selection;
26 LyXScreen::LyXScreen(Window window,
32 : text(text_ptr), _window(window),
33 _width(width), _height(height),
34 _offset_x(offset_x), _offset_y(offset_y)
38 /* the cursor isnt yet visible */
39 cursor_visible = false;
40 screen_refresh_y = -1;
42 /* create the foreground pixmap */
43 foreground = XCreatePixmap (fl_display,
46 fl_get_visual_depth());
56 LyXScreen::~LyXScreen()
58 XFreePixmap(fl_display, foreground);
62 void LyXScreen::Redraw()
64 DrawFromTo(0, _height);
65 screen_refresh_y = -1;
66 expose(0, 0, _width, _height);
68 cursor_visible = false;
74 void LyXScreen::expose(int x, int y, int exp_width, int exp_height)
81 exp_width, exp_height,
82 x+_offset_x, y+_offset_y);
86 void LyXScreen::DrawFromTo(int y1, int y2)
88 long y_text = first + y1;
90 /* get the first needed row */
91 Row * row = text->GetRowNearY(y_text);
92 /* y_text is now the real beginning of the row */
94 long y = y_text - first;
95 /* y1 is now the real beginning of row on the screen */
97 while (row != 0 && y < y2) {
99 text->GetVisibleRow(*this, y, row, y + first);
105 /* maybe we have to clear the screen at the bottom */
107 fillRectangle(gc_lighted,
116 void LyXScreen::DrawOneRow(Row * row, long & y_text)
118 long y = y_text - first;
120 if (y + row->height > 0 && y - row->height <= _height) {
121 /* ok there is something visible */
122 text->GetVisibleRow(*this, y, row, y + first);
124 y_text+= row->height;
128 /* draws the screen, starting with textposition y. uses as much already
129 * printed pixels as possible */
130 void LyXScreen::Draw(long y)
132 if (cursor_visible) HideCursor();
135 long old_first = first;
138 /* is any optimiziation possible? */
139 if ((y - old_first) < _height
140 && (old_first - y) < _height) {
141 if (first < old_first) {
142 DrawFromTo(0, old_first - first);
143 XCopyArea (fl_display,
147 _offset_x, _offset_y,
148 _width , _height - old_first + first,
149 _offset_x, _offset_y + old_first - first);
150 // expose the area drawn
151 expose(0, 0, _width, old_first - first);
153 DrawFromTo(_height + old_first - first, _height);
154 XCopyArea (fl_display,
158 _offset_x, _offset_y + first - old_first,
159 _width , _height + old_first - first,
160 _offset_x, _offset_y);
161 // expose the area drawn
162 expose(0, _height + old_first - first,
163 _width, first - old_first);
166 /* make a dumb new-draw */
167 DrawFromTo(0, _height);
168 expose(0, 0, _width, _height);
173 void LyXScreen::ShowCursor()
179 if (cursor_visible) return;
183 y1 = text->cursor.y - text->real_current_font.maxAscent() - first;
186 y2 = text->cursor.y + text->real_current_font.maxDescent() - first;
187 if (y2 > _height) y2 = _height;
189 // Secure against very strange situations
190 if (y2 < y1) y2 = y1;
192 if (fast_selection || mono_video) {
193 if (y2 > 0 && y1 < _height) {
194 XDrawLine(fl_display,
195 _window, getGC(gc_select),
200 cursor_visible = true;
204 XFreePixmap(fl_display, cursor_pixmap);
208 if (y2 > 0 && y1 < _height) {
210 cursor_pixmap_h = y2 - y1 + 1;
212 cursor_pixmap_y = y1;
214 XCreatePixmap(fl_display,
218 fl_get_visual_depth());
219 XCopyArea(fl_display,
223 _offset_x + cursor_pixmap_x,
224 _offset_y + cursor_pixmap_y,
225 cursor_pixmap_w, cursor_pixmap_h,
227 XDrawLine(fl_display,
228 _window, getGC(gc_copy),
233 cursor_visible = true;
239 /* returns 1 if first has changed, otherwise 0 */
240 int LyXScreen::FitManualCursor(long /*x*/, long y, int asc, int desc)
244 if (y + desc - first >= _height)
245 newtop = y - 3*_height / 4; /* the scroll region must be so big!! */
246 else if (y - asc < first
248 newtop = y - _height / 4;
253 if (newtop != first){
262 void LyXScreen::HideManualCursor(long x, long y, int asc, int desc)
264 if (fast_selection || mono_video)
265 ShowManualCursor(x, y, asc, desc);
271 void LyXScreen::ShowManualCursor(long x, long y, int asc, int desc)
276 y1 = y - first - asc;
279 y2 = y -first + desc;
283 if (fast_selection || mono_video) {
284 if (y2 > 0 && y1 < _height) {
285 XDrawLine(fl_display,
286 _window, getGC(gc_select),
294 XFreePixmap(fl_display, cursor_pixmap);
298 if (y2 > 0 && y1 < _height) {
300 cursor_pixmap_h = y2 - y1 + 1;
302 cursor_pixmap_y = y1;
304 XCreatePixmap (fl_display,
308 fl_get_visual_depth());
310 XCopyArea (fl_display,
314 _offset_x + cursor_pixmap_x,
315 _offset_y + cursor_pixmap_y,
319 XDrawLine(fl_display,
320 _window, getGC(gc_copy),
326 cursor_visible = true;
331 void LyXScreen::HideCursor()
333 if (!cursor_visible) return;
335 if (fast_selection || mono_video) {
336 cursor_visible = false;
338 cursor_visible = false;
341 XCopyArea (fl_display,
346 cursor_pixmap_w, cursor_pixmap_h,
347 cursor_pixmap_x + _offset_x,
348 cursor_pixmap_y + _offset_y);
350 cursor_visible = false;
355 void LyXScreen::CursorToggle()
364 /* returns a new top so that the cursor is visible */
365 long LyXScreen::TopCursorVisible()
370 - text->cursor.row->baseline
371 + text->cursor.row->height
372 - first >= _height) {
373 if (text->cursor.row->height < _height
374 && text->cursor.row->height > _height/4)
375 newtop = text->cursor.y
376 + text->cursor.row->height
377 - text->cursor.row->baseline - _height;
379 newtop = text->cursor.y
380 - 3*_height / 4; /* the scroll region must be so big!! */
381 } else if (text->cursor.y - text->cursor.row->baseline < first
383 if (text->cursor.row->height < _height
384 && text->cursor.row->height > _height/4)
385 newtop = text->cursor.y - text->cursor.row->baseline;
387 newtop = text->cursor.y - _height / 4;
399 /* scrolls the screen so that the cursor is visible, if necessary.
400 * returns 1 if a change was made, otherwise 0 */
401 int LyXScreen::FitCursor()
403 /* is a change necessary */
404 long newtop = TopCursorVisible();
405 int result = (newtop != first);
412 void LyXScreen::Update()
416 if (text->status == LyXText::NEED_MORE_REFRESH
417 || screen_refresh_y > -1 ) {
418 if (screen_refresh_y > -1
419 && screen_refresh_y < text->refresh_y)
420 y = screen_refresh_y;
424 if (y < first) y = first;
426 DrawFromTo(y - first, _height);
428 text->status = LyXText::UNCHANGED;
429 screen_refresh_y = -1;
430 expose(0, y-first, _width, _height - (y - first));
431 } else if (text->status == LyXText::NEED_VERY_LITTLE_REFRESH) {
432 /* ok I will update the current cursor row */
434 DrawOneRow(text->refresh_row, y);
435 text->status = LyXText::UNCHANGED;
436 expose(0, text->refresh_y-first,
437 _width, text->refresh_row->height);
442 void LyXScreen::SmallUpdate()
448 if (text->status == LyXText::NEED_MORE_REFRESH){
449 /* ok I will update till the current cursor row */
450 row = text->refresh_row;
454 if (y > text->cursor.y) {
459 while (row && row != text->cursor.row && y < first + _height) {
465 screen_refresh_y = y;
466 screen_refresh_row = row->next;
467 text->status = LyXText::UNCHANGED;
468 // Is the right regin exposed?
469 expose(0, y2-first, _width, y-y2);
470 } else if (text->status == LyXText::NEED_VERY_LITTLE_REFRESH) {
471 /* ok I will update the current cursor row */
472 row = text->refresh_row;
475 text->status = LyXText::UNCHANGED;
476 expose(0, text->refresh_y - first,
477 _width, row->height);
482 void LyXScreen::ToggleSelection(bool kill_selection)
484 /* only if there is a selection */
485 if (!text->selection)
492 if (fast_selection || mono_video) {
494 /* selection only in one row ?*/
495 if (text->sel_start_cursor.y == text->sel_end_cursor.y) {
497 /* only if something is visible */
498 if (text->sel_start_cursor.y
499 - text->sel_start_cursor.row->baseline
501 && text->sel_start_cursor.y
502 - text->sel_start_cursor.row->baseline +
503 text->sel_start_cursor.row->height - first > 0) {
504 top = text->sel_start_cursor.y
505 - text->sel_start_cursor.row->baseline
508 + text->sel_start_cursor.row->height;
511 if (bottom > _height)
513 XFillRectangle(fl_display, _window,
515 text->sel_start_cursor.x
518 text->sel_end_cursor.x
519 - text->sel_start_cursor.x,
523 /* the sel_start_cursor row first */
524 /* only if anything is visible */
525 if (text->sel_start_cursor.y
526 - text->sel_start_cursor.row->baseline
528 && text->sel_start_cursor.y
529 - text->sel_start_cursor.row->baseline +
530 text->sel_start_cursor.row->height - first > 0) {
531 top = text->sel_start_cursor.y
532 - text->sel_start_cursor.row->baseline
535 + text->sel_start_cursor.row->height;
538 if (bottom > _height)
540 XFillRectangle(fl_display, _window,
542 text->sel_start_cursor.x
546 - text->sel_start_cursor.x,
552 if (text->sel_start_cursor.row->next !=
553 text->sel_end_cursor.row) {
554 top = text->sel_start_cursor.y
555 - text->sel_start_cursor.row->baseline
556 + text->sel_start_cursor.row->height;
557 bottom = text->sel_end_cursor.y
558 - text->sel_end_cursor.row->baseline;
562 if (bottom - first < 0)
565 if (bottom - first > _height)
566 bottom = first + _height;
567 if (top - first > _height)
568 top = first + _height;
571 XFillRectangle(fl_display,
575 top - first+_offset_y,
581 /* the sel_end_cursor row last */
582 if (text->sel_end_cursor.y
583 - text->sel_end_cursor.row->baseline
585 && text->sel_end_cursor.y
586 - text->sel_end_cursor.row->baseline +
587 text->sel_end_cursor.row->height - first > 0) {
588 top = text->sel_end_cursor.y
589 - text->sel_end_cursor.row->baseline
592 + text->sel_end_cursor.row->height;
595 if (bottom > _height)
597 XFillRectangle(fl_display, _window,
601 text->sel_end_cursor.x,
606 top = text->sel_start_cursor.y
607 - text->sel_start_cursor.row->baseline;
608 bottom = text->sel_end_cursor.y
609 - text->sel_end_cursor.row->baseline
610 + text->sel_end_cursor.row->height;
614 if (bottom - first < 0)
617 if (bottom - first > _height)
618 bottom = first + _height;
619 if (top - first > _height)
620 top = first + _height;
624 DrawFromTo(top - first, bottom - first);
625 expose(0, top - first, _width, bottom - first - (top - first));
630 void LyXScreen::ToggleToggle()
635 if (text->toggle_cursor.par == text->toggle_end_cursor.par
636 && text->toggle_cursor.pos == text->toggle_end_cursor.pos)
639 if (fast_selection || mono_video) {
641 /* selection only in one row ?*/
642 if (text->toggle_cursor.y == text->toggle_end_cursor.y) {
644 /* only if anything is visible */
645 if (text->toggle_cursor.y - text->toggle_cursor.row->baseline - first < _height
646 && text->toggle_cursor.y - text->toggle_cursor.row->baseline +
647 text->toggle_cursor.row->height - first > 0) {
648 top = text->toggle_cursor.y - text->toggle_cursor.row->baseline - first;
649 bottom = top + text->toggle_cursor.row->height;
650 if (top < 0) top = 0;
651 if (bottom > _height) bottom = _height;
652 XFillRectangle(fl_display, _window,
654 text->toggle_cursor.x+_offset_x,
656 text->toggle_end_cursor.x -
657 text->toggle_cursor.x,
661 /* the toggle_cursor row first */
662 /* only if anything is visible */
663 if (text->toggle_cursor.y - text->toggle_cursor.row->baseline - first < _height
664 && text->toggle_cursor.y - text->toggle_cursor.row->baseline +
665 text->toggle_cursor.row->height - first > 0) {
666 top = text->toggle_cursor.y - text->toggle_cursor.row->baseline - first;
667 bottom = top + text->toggle_cursor.row->height;
670 if (bottom > _height)
672 XFillRectangle(fl_display, _window,
674 text->toggle_cursor.x+_offset_x,
676 _width - text->toggle_cursor.x,
682 if (text->toggle_cursor.row->next !=
683 text->toggle_end_cursor.row) {
684 top = text->toggle_cursor.y
685 - text->toggle_cursor.row->baseline
686 + text->toggle_cursor.row->height;
687 bottom = text->toggle_end_cursor.y
688 - text->toggle_end_cursor.row->baseline;
692 if (bottom - first < 0)
695 if (bottom - first > _height)
696 bottom = first + _height;
697 if (top - first > _height)
698 top = first + _height;
701 XFillRectangle(fl_display, _window,
704 top - first+_offset_y,
710 /* the toggle_end_cursor row last */
711 if (text->toggle_end_cursor.y - text->toggle_end_cursor.row->baseline - first < _height
712 && text->toggle_end_cursor.y - text->toggle_end_cursor.row->baseline +
713 text->toggle_end_cursor.row->height - first > 0) {
714 top = text->toggle_end_cursor.y
715 - text->toggle_end_cursor.row->baseline
718 + text->toggle_end_cursor.row->height;
721 if (bottom > _height)
723 XFillRectangle(fl_display, _window,
727 text->toggle_end_cursor.x,
732 top = text->toggle_cursor.y
733 - text->toggle_cursor.row->baseline;
734 bottom = text->toggle_end_cursor.y
735 - text->toggle_end_cursor.row->baseline
736 + text->toggle_end_cursor.row->height;
740 if (bottom - first < 0)
743 if (bottom - first > _height)
744 bottom = first + _height;
745 if (top - first > _height)
746 top = first + _height;
748 DrawFromTo(top - first, bottom - first);
749 expose(0, top - first, _width, bottom - first - (top - first));
755 void LyXScreen::drawTableLine(int baseline, int x, int length, bool on_off)
759 gc = getGC(gc_thin_on_off_line);
770 void LyXScreen::drawVerticalTableLine(int x, int y1, int y2, bool on_off)
774 gc = getGC(gc_thin_on_off_line);
785 void LyXScreen::drawFrame(int /*ft*/, int x, int y, int w, int h,
786 FL_COLOR /*col*/, int /*b*/)
788 // Implement this using X11 calls, and the repaint problems are gone!
789 // At least, I think that should do it since we only have them after
790 // one of these buttons are displayed now! Lars, it seems you've hit the
792 // fl_winset(foreground);
793 // fl_drw_frame(ft, x, y, w, h, col, b);
794 // This should be changed to draw a button like frame, in the
795 // mean time we'll just use a regular rectangle
797 // I want the buttons back before 0.12. OK, this is very simple,
798 // like what is done in xforms sources. (Ale)
800 // This one is too dirty. Get rid of it.
803 // Please comment this annonymous variable.
806 // I think these calls to fl_color might make xforms sometimes
807 // draw the wrong color on other objects.
808 fl_color(FL_TOP_BCOL);
809 XFillRectangle(fl_display, foreground, fl_gc,
810 x - d, y - d, w + 2 * d, d);
811 fl_color(FL_BOTTOM_BCOL);
812 XFillRectangle(fl_display, foreground, fl_gc,
813 x - d, y + h, w + 2 * d, d);
815 // Now a couple of trapezoids
818 pl[0].x = x - d; pl[0].y = y - d;
819 pl[1].x = x - d; pl[1].y = y + h + d;
820 pl[2].x = x; pl[2].y = y + h;
821 pl[3].x = x; pl[3].y = y;
823 pr[0].x = x + w + d; pr[0].y = y - d;
824 pr[1].x = x + w + d; pr[1].y = y + h + d;
825 pr[2].x = x + w; pr[2].y = y + h;
826 pr[3].x = x + w; pr[3].y = y;
828 fl_color(FL_LEFT_BCOL);
829 XFillPolygon(fl_display,
832 Convex, CoordModeOrigin);
833 fl_color(FL_RIGHT_BCOL);
834 XFillPolygon(fl_display,
837 Convex, CoordModeOrigin);