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"
20 #include "BufferView.h"
27 extern int mono_video;
28 extern int fast_selection;
36 val.foreground = BlackPixel(fl_display,
37 DefaultScreen(fl_display));
40 val.graphics_exposures = false;
41 val.line_style = LineSolid;
43 return XCreateGC(fl_display, RootWindow(fl_display, 0),
44 GCForeground | GCFunction | GCGraphicsExposures
45 | GCLineWidth | GCLineStyle , &val);
51 LyXScreen::LyXScreen(BufferView * o, Window window,
58 : owner(o), text(text_ptr), _window(window),
59 _width(width), _height(height),
60 _offset_x(offset_x), _offset_y(offset_y)
64 /* the cursor isnt yet visible */
65 cursor_visible = false;
66 screen_refresh_y = -1;
68 /* create the foreground pixmap */
85 LyXScreen::~LyXScreen() {}
88 void LyXScreen::Redraw()
90 DrawFromTo(0, _height);
91 screen_refresh_y = -1;
92 expose(0, 0, _width, _height);
94 cursor_visible = false;
101 void LyXScreen::expose(int x, int y, int exp_width, int exp_height)
103 XCopyArea(fl_display,
108 exp_width, exp_height,
109 x+_offset_x, y+_offset_y);
112 void LyXScreen::expose(int x, int y, int exp_width, int exp_height)
114 XCopyArea(fl_display,
119 exp_width, exp_height,
120 x+_offset_x, y+_offset_y);
126 void LyXScreen::DrawFromTo(int y1, int y2)
128 long y_text = first + y1;
130 /* get the first needed row */
131 Row * row = text->GetRowNearY(y_text);
132 /* y_text is now the real beginning of the row */
134 long y = y_text - first;
135 /* y1 is now the real beginning of row on the screen */
137 while (row != 0 && y < y2) {
139 text->GetVisibleRow(y, row, y + first);
145 /* maybe we have to clear the screen at the bottom */
147 owner->painter().fillRectangle(0, y, _width, y2 - y,
152 void LyXScreen::DrawFromTo(int y1, int y2)
154 long y_text = first + y1;
156 /* get the first needed row */
157 Row * row = text->GetRowNearY(y_text);
158 /* y_text is now the real beginning of the row */
160 long y = y_text - first;
161 /* y1 is now the real beginning of row on the screen */
163 while (row != 0 && y < y2) {
165 text->GetVisibleRow(*this, y, row, y + first);
171 /* maybe we have to clear the screen at the bottom */
173 fillRectangle(gc_lighted,
183 void LyXScreen::DrawOneRow(Row * row, long & y_text)
185 long y = y_text - first;
187 if (y + row->height > 0 && y - row->height <= _height) {
188 /* ok there is something visible */
190 text->GetVisibleRow(y, row, y + first);
192 text->GetVisibleRow(*this, y, row, y + first);
195 y_text+= row->height;
199 /* draws the screen, starting with textposition y. uses as much already
200 * printed pixels as possible */
202 void LyXScreen::Draw(long y)
204 if (cursor_visible) HideCursor();
207 long old_first = first;
210 /* is any optimiziation possible? */
211 if ((y - old_first) < _height
212 && (old_first - y) < _height) {
213 if (first < old_first) {
214 DrawFromTo(0, old_first - first);
215 XCopyArea (fl_display,
219 _offset_x, _offset_y,
220 _width , _height - old_first + first,
221 _offset_x, _offset_y + old_first - first);
222 // expose the area drawn
223 expose(0, 0, _width, old_first - first);
225 DrawFromTo(_height + old_first - first, _height);
226 XCopyArea (fl_display,
230 _offset_x, _offset_y + first - old_first,
231 _width , _height + old_first - first,
232 _offset_x, _offset_y);
233 // expose the area drawn
234 expose(0, _height + old_first - first,
235 _width, first - old_first);
238 /* make a dumb new-draw */
239 DrawFromTo(0, _height);
240 expose(0, 0, _width, _height);
244 void LyXScreen::Draw(long y)
246 if (cursor_visible) HideCursor();
249 long old_first = first;
252 /* is any optimiziation possible? */
253 if ((y - old_first) < _height
254 && (old_first - y) < _height) {
255 if (first < old_first) {
256 DrawFromTo(0, old_first - first);
257 XCopyArea (fl_display,
261 _offset_x, _offset_y,
262 _width , _height - old_first + first,
263 _offset_x, _offset_y + old_first - first);
264 // expose the area drawn
265 expose(0, 0, _width, old_first - first);
267 DrawFromTo(_height + old_first - first, _height);
268 XCopyArea (fl_display,
272 _offset_x, _offset_y + first - old_first,
273 _width , _height + old_first - first,
274 _offset_x, _offset_y);
275 // expose the area drawn
276 expose(0, _height + old_first - first,
277 _width, first - old_first);
280 /* make a dumb new-draw */
281 DrawFromTo(0, _height);
282 expose(0, 0, _width, _height);
288 void LyXScreen::ShowCursor()
294 if (cursor_visible) return;
298 y1 = text->cursor.y - text->real_current_font.maxAscent() - first;
301 y2 = text->cursor.y + text->real_current_font.maxDescent() - first;
302 if (y2 > _height) y2 = _height;
304 // Secure against very strange situations
305 if (y2 < y1) y2 = y1;
308 if (fast_selection || mono_video) {
309 if (y2 > 0 && y1 < _height) {
310 XDrawLine(fl_display,
311 _window, getGC(gc_select),
316 cursor_visible = true;
321 XFreePixmap(fl_display, cursor_pixmap);
325 if (y2 > 0 && y1 < _height) {
327 cursor_pixmap_h = y2 - y1 + 1;
329 cursor_pixmap_y = y1;
331 XCreatePixmap(fl_display,
335 fl_get_visual_depth());
337 XCopyArea(fl_display,
341 _offset_x + cursor_pixmap_x,
342 _offset_y + cursor_pixmap_y,
343 cursor_pixmap_w, cursor_pixmap_h,
345 XDrawLine(fl_display,
352 XCopyArea(fl_display,
356 _offset_x + cursor_pixmap_x,
357 _offset_y + cursor_pixmap_y,
358 cursor_pixmap_w, cursor_pixmap_h,
360 XDrawLine(fl_display,
368 cursor_visible = true;
376 /* returns 1 if first has changed, otherwise 0 */
377 int LyXScreen::FitManualCursor(long /*x*/, long y, int asc, int desc)
381 if (y + desc - first >= _height)
382 newtop = y - 3*_height / 4; /* the scroll region must be so big!! */
383 else if (y - asc < first
385 newtop = y - _height / 4;
390 if (newtop != first){
399 void LyXScreen::HideManualCursor(long x, long y, int asc, int desc)
402 if (fast_selection || mono_video)
403 ShowManualCursor(x, y, asc, desc);
410 void LyXScreen::ShowManualCursor(long x, long y, int asc, int desc)
415 y1 = y - first - asc;
418 y2 = y -first + desc;
423 if (fast_selection || mono_video) {
424 if (y2 > 0 && y1 < _height) {
425 XDrawLine(fl_display,
426 _window, getGC(gc_select),
435 XFreePixmap(fl_display, cursor_pixmap);
439 if (y2 > 0 && y1 < _height) {
441 cursor_pixmap_h = y2 - y1 + 1;
443 cursor_pixmap_y = y1;
445 XCreatePixmap (fl_display,
449 fl_get_visual_depth());
451 XCopyArea (fl_display,
455 _offset_x + cursor_pixmap_x,
456 _offset_y + cursor_pixmap_y,
460 XDrawLine(fl_display,
467 XCopyArea (fl_display,
471 _offset_x + cursor_pixmap_x,
472 _offset_y + cursor_pixmap_y,
476 XDrawLine(fl_display,
485 cursor_visible = true;
492 void LyXScreen::HideCursor()
494 if (!cursor_visible) return;
497 if (fast_selection || mono_video) {
498 cursor_visible = false;
500 cursor_visible = false;
505 XCopyArea (fl_display,
510 cursor_pixmap_w, cursor_pixmap_h,
511 cursor_pixmap_x + _offset_x,
512 cursor_pixmap_y + _offset_y);
514 XCopyArea (fl_display,
519 cursor_pixmap_w, cursor_pixmap_h,
520 cursor_pixmap_x + _offset_x,
521 cursor_pixmap_y + _offset_y);
524 cursor_visible = false;
531 void LyXScreen::CursorToggle()
540 /* returns a new top so that the cursor is visible */
541 long LyXScreen::TopCursorVisible()
546 - text->cursor.row->baseline
547 + text->cursor.row->height
548 - first >= _height) {
549 if (text->cursor.row->height < _height
550 && text->cursor.row->height > _height/4)
551 newtop = text->cursor.y
552 + text->cursor.row->height
553 - text->cursor.row->baseline - _height;
555 newtop = text->cursor.y
556 - 3*_height / 4; /* the scroll region must be so big!! */
557 } else if (text->cursor.y - text->cursor.row->baseline < first
559 if (text->cursor.row->height < _height
560 && text->cursor.row->height > _height/4)
561 newtop = text->cursor.y - text->cursor.row->baseline;
563 newtop = text->cursor.y - _height / 4;
575 /* scrolls the screen so that the cursor is visible, if necessary.
576 * returns 1 if a change was made, otherwise 0 */
577 int LyXScreen::FitCursor()
579 /* is a change necessary */
580 long newtop = TopCursorVisible();
581 int result = (newtop != first);
588 void LyXScreen::Update()
592 if (text->status == LyXText::NEED_MORE_REFRESH
593 || screen_refresh_y > -1 ) {
594 if (screen_refresh_y > -1
595 && screen_refresh_y < text->refresh_y)
596 y = screen_refresh_y;
600 if (y < first) y = first;
602 DrawFromTo(y - first, _height);
604 text->status = LyXText::UNCHANGED;
605 screen_refresh_y = -1;
606 expose(0, y-first, _width, _height - (y - first));
607 } else if (text->status == LyXText::NEED_VERY_LITTLE_REFRESH) {
608 /* ok I will update the current cursor row */
610 DrawOneRow(text->refresh_row, y);
611 text->status = LyXText::UNCHANGED;
612 expose(0, text->refresh_y-first,
613 _width, text->refresh_row->height);
618 void LyXScreen::SmallUpdate()
624 if (text->status == LyXText::NEED_MORE_REFRESH){
625 /* ok I will update till the current cursor row */
626 row = text->refresh_row;
630 if (y > text->cursor.y) {
635 while (row && row != text->cursor.row && y < first + _height) {
641 screen_refresh_y = y;
642 screen_refresh_row = row->next;
643 text->status = LyXText::UNCHANGED;
644 // Is the right regin exposed?
645 expose(0, y2-first, _width, y-y2);
646 } else if (text->status == LyXText::NEED_VERY_LITTLE_REFRESH) {
647 /* ok I will update the current cursor row */
648 row = text->refresh_row;
651 text->status = LyXText::UNCHANGED;
652 expose(0, text->refresh_y - first,
653 _width, row->height);
658 void LyXScreen::ToggleSelection(bool kill_selection)
660 /* only if there is a selection */
661 if (!text->selection)
668 if (fast_selection || mono_video) {
670 /* selection only in one row ?*/
671 if (text->sel_start_cursor.y == text->sel_end_cursor.y) {
673 /* only if something is visible */
674 if (text->sel_start_cursor.y
675 - text->sel_start_cursor.row->baseline
677 && text->sel_start_cursor.y
678 - text->sel_start_cursor.row->baseline +
679 text->sel_start_cursor.row->height - first > 0) {
680 top = text->sel_start_cursor.y
681 - text->sel_start_cursor.row->baseline
684 + text->sel_start_cursor.row->height;
687 if (bottom > _height)
689 XFillRectangle(fl_display, _window,
691 text->sel_start_cursor.x
694 text->sel_end_cursor.x
695 - text->sel_start_cursor.x,
699 /* the sel_start_cursor row first */
700 /* only if anything is visible */
701 if (text->sel_start_cursor.y
702 - text->sel_start_cursor.row->baseline
704 && text->sel_start_cursor.y
705 - text->sel_start_cursor.row->baseline +
706 text->sel_start_cursor.row->height - first > 0) {
707 top = text->sel_start_cursor.y
708 - text->sel_start_cursor.row->baseline
711 + text->sel_start_cursor.row->height;
714 if (bottom > _height)
716 XFillRectangle(fl_display, _window,
718 text->sel_start_cursor.x
722 - text->sel_start_cursor.x,
728 if (text->sel_start_cursor.row->next !=
729 text->sel_end_cursor.row) {
730 top = text->sel_start_cursor.y
731 - text->sel_start_cursor.row->baseline
732 + text->sel_start_cursor.row->height;
733 bottom = text->sel_end_cursor.y
734 - text->sel_end_cursor.row->baseline;
738 if (bottom - first < 0)
741 if (bottom - first > _height)
742 bottom = first + _height;
743 if (top - first > _height)
744 top = first + _height;
747 XFillRectangle(fl_display,
751 top - first+_offset_y,
757 /* the sel_end_cursor row last */
758 if (text->sel_end_cursor.y
759 - text->sel_end_cursor.row->baseline
761 && text->sel_end_cursor.y
762 - text->sel_end_cursor.row->baseline +
763 text->sel_end_cursor.row->height - first > 0) {
764 top = text->sel_end_cursor.y
765 - text->sel_end_cursor.row->baseline
768 + text->sel_end_cursor.row->height;
771 if (bottom > _height)
773 XFillRectangle(fl_display, _window,
777 text->sel_end_cursor.x,
783 top = text->sel_start_cursor.y
784 - text->sel_start_cursor.row->baseline;
785 bottom = text->sel_end_cursor.y
786 - text->sel_end_cursor.row->baseline
787 + text->sel_end_cursor.row->height;
791 if (bottom - first < 0)
794 if (bottom - first > _height)
795 bottom = first + _height;
796 if (top - first > _height)
797 top = first + _height;
801 DrawFromTo(top - first, bottom - first);
802 expose(0, top - first, _width, bottom - first - (top - first));
809 void LyXScreen::ToggleToggle()
814 if (text->toggle_cursor.par == text->toggle_end_cursor.par
815 && text->toggle_cursor.pos == text->toggle_end_cursor.pos)
819 if (fast_selection || mono_video) {
821 /* selection only in one row ?*/
822 if (text->toggle_cursor.y == text->toggle_end_cursor.y) {
824 /* only if anything is visible */
825 if (text->toggle_cursor.y - text->toggle_cursor.row->baseline - first < _height
826 && text->toggle_cursor.y - text->toggle_cursor.row->baseline +
827 text->toggle_cursor.row->height - first > 0) {
828 top = text->toggle_cursor.y - text->toggle_cursor.row->baseline - first;
829 bottom = top + text->toggle_cursor.row->height;
830 if (top < 0) top = 0;
831 if (bottom > _height) bottom = _height;
832 XFillRectangle(fl_display, _window,
834 text->toggle_cursor.x+_offset_x,
836 text->toggle_end_cursor.x -
837 text->toggle_cursor.x,
841 /* the toggle_cursor row first */
842 /* only if anything is visible */
843 if (text->toggle_cursor.y - text->toggle_cursor.row->baseline - first < _height
844 && text->toggle_cursor.y - text->toggle_cursor.row->baseline +
845 text->toggle_cursor.row->height - first > 0) {
846 top = text->toggle_cursor.y - text->toggle_cursor.row->baseline - first;
847 bottom = top + text->toggle_cursor.row->height;
850 if (bottom > _height)
852 XFillRectangle(fl_display, _window,
854 text->toggle_cursor.x+_offset_x,
856 _width - text->toggle_cursor.x,
862 if (text->toggle_cursor.row->next !=
863 text->toggle_end_cursor.row) {
864 top = text->toggle_cursor.y
865 - text->toggle_cursor.row->baseline
866 + text->toggle_cursor.row->height;
867 bottom = text->toggle_end_cursor.y
868 - text->toggle_end_cursor.row->baseline;
872 if (bottom - first < 0)
875 if (bottom - first > _height)
876 bottom = first + _height;
877 if (top - first > _height)
878 top = first + _height;
881 XFillRectangle(fl_display, _window,
884 top - first+_offset_y,
890 /* the toggle_end_cursor row last */
891 if (text->toggle_end_cursor.y - text->toggle_end_cursor.row->baseline - first < _height
892 && text->toggle_end_cursor.y - text->toggle_end_cursor.row->baseline +
893 text->toggle_end_cursor.row->height - first > 0) {
894 top = text->toggle_end_cursor.y
895 - text->toggle_end_cursor.row->baseline
898 + text->toggle_end_cursor.row->height;
901 if (bottom > _height)
903 XFillRectangle(fl_display, _window,
907 text->toggle_end_cursor.x,
913 top = text->toggle_cursor.y
914 - text->toggle_cursor.row->baseline;
915 bottom = text->toggle_end_cursor.y
916 - text->toggle_end_cursor.row->baseline
917 + text->toggle_end_cursor.row->height;
921 if (bottom - first < 0)
924 if (bottom - first > _height)
925 bottom = first + _height;
926 if (top - first > _height)
927 top = first + _height;
929 DrawFromTo(top - first, bottom - first);
930 expose(0, top - first, _width, bottom - first - (top - first));
938 void LyXScreen::drawTableLine(int baseline, int x, int length, bool on_off)
942 gc = getGC(gc_thin_on_off_line);
955 void LyXScreen::drawVerticalTableLine(int x, int y1, int y2, bool on_off)
959 gc = getGC(gc_thin_on_off_line);
972 void LyXScreen::drawFrame(int /*ft*/, int x, int y, int w, int h,
973 FL_COLOR /*col*/, int /*b*/)
975 // Implement this using X11 calls, and the repaint problems are gone!
976 // At least, I think that should do it since we only have them after
977 // one of these buttons are displayed now! Lars, it seems you've hit the
979 // fl_winset(foreground);
980 // fl_drw_frame(ft, x, y, w, h, col, b);
981 // This should be changed to draw a button like frame, in the
982 // mean time we'll just use a regular rectangle
984 // I want the buttons back before 0.12. OK, this is very simple,
985 // like what is done in xforms sources. (Ale)
987 // This one is too dirty. Get rid of it.
990 // Please comment this annonymous variable.
993 // I think these calls to fl_color might make xforms sometimes
994 // draw the wrong color on other objects.
995 fl_color(FL_TOP_BCOL);
996 XFillRectangle(fl_display, foreground, fl_gc,
997 x - d, y - d, w + 2 * d, d);
998 fl_color(FL_BOTTOM_BCOL);
999 XFillRectangle(fl_display, foreground, fl_gc,
1000 x - d, y + h, w + 2 * d, d);
1002 // Now a couple of trapezoids
1003 XPoint pl[4], pr[4];
1005 pl[0].x = x - d; pl[0].y = y - d;
1006 pl[1].x = x - d; pl[1].y = y + h + d;
1007 pl[2].x = x; pl[2].y = y + h;
1008 pl[3].x = x; pl[3].y = y;
1010 pr[0].x = x + w + d; pr[0].y = y - d;
1011 pr[1].x = x + w + d; pr[1].y = y + h + d;
1012 pr[2].x = x + w; pr[2].y = y + h;
1013 pr[3].x = x + w; pr[3].y = y;
1015 fl_color(FL_LEFT_BCOL);
1016 XFillPolygon(fl_display,
1019 Convex, CoordModeOrigin);
1020 fl_color(FL_RIGHT_BCOL);
1021 XFillPolygon(fl_display,
1024 Convex, CoordModeOrigin);