1 /* This file is part of
2 * ======================================================
4 * LyX, The Document Processor
6 * Copyright (C) 1995 Matthias Ettrich
7 * Copyright (C) 1995-1998 The LyX Team
9 *======================================================*/
14 #pragma implementation "lyxscreen.h"
17 #include "lyxscreen.h"
21 // $Id: screen.C,v 1.1 1999/09/27 18:44:38 larsbj Exp $
23 #if !defined(lint) && !defined(WITH_WARNINGS)
24 static char vcid[] = "$Id: screen.C,v 1.1 1999/09/27 18:44:38 larsbj Exp $";
27 extern int mono_video;
28 extern int fast_selection;
32 LyXScreen::LyXScreen(Window window,
38 : text(text_ptr),_window(window),
39 _width(width),_height(height),
40 _offset_x(offset_x), _offset_y(offset_y)
44 /* the cursor isnt yet visible */
45 cursor_visible = false;
46 screen_refresh_y = -1;
48 /* create the foreground pixmap */
49 foreground = XCreatePixmap (fl_display,
52 fl_get_visual_depth());
62 LyXScreen::~LyXScreen()
64 XFreePixmap(fl_display, foreground);
68 void LyXScreen::Redraw()
70 DrawFromTo(0, _height);
71 screen_refresh_y = -1;
72 expose(0, 0, _width, _height);
74 cursor_visible = false;
80 void LyXScreen::expose(int x, int y, int exp_width, int exp_height)
87 exp_width, exp_height,
88 x+_offset_x, y+_offset_y);
92 void LyXScreen::DrawFromTo(int y1, int y2)
100 /* get the first needed row */
101 row = text->GetRowNearY(y_text);
102 /* y_text is now the real beginning of the row */
105 /* y1 is now the real beginning of row on the screen */
107 while (row != NULL && y < y2) {
109 text->GetVisibleRow(*this, y, row, y + first);
115 /* maybe we have to clear the screen at the bottom */
117 fillRectangle(gc_lighted,
126 void LyXScreen::DrawOneRow(Row *row, long &y_text)
132 if (y + row->height > 0 && y - row->height <= _height) {
133 /* ok there is something visible */
134 text->GetVisibleRow(*this, y, row, y + first);
140 /* draws the screen, starting with textposition y. uses as much already
141 * printed pixels as possible */
142 void LyXScreen::Draw(long y)
144 if (cursor_visible) HideCursor();
147 long old_first = first;
150 /* is any optimiziation possible? */
151 if ((y - old_first) < _height
152 && (old_first - y) < _height) {
153 if (first < old_first) {
154 DrawFromTo(0, old_first - first);
155 XCopyArea (fl_display,
159 _offset_x, _offset_y,
160 _width , _height - old_first + first,
161 _offset_x, _offset_y + old_first - first);
162 // expose the area drawn
163 expose(0, 0, _width, old_first - first);
165 DrawFromTo(_height + old_first - first, _height);
166 XCopyArea (fl_display,
170 _offset_x, _offset_y + first - old_first,
171 _width , _height + old_first - first,
172 _offset_x, _offset_y);
173 // expose the area drawn
174 expose(0, _height + old_first - first,
175 _width, first - old_first);
178 /* make a dumb new-draw */
179 DrawFromTo(0, _height);
180 expose(0, 0, _width, _height);
185 void LyXScreen::ShowCursor()
191 if (cursor_visible) return;
195 y1 = text->cursor.y - text->real_current_font.maxAscent() - first;
198 y2 = text->cursor.y + text->real_current_font.maxDescent() - first;
199 if (y2 > _height) y2 = _height;
201 // Secure against very strange situations
202 if (y2 < y1) y2 = y1;
204 if (fast_selection || mono_video) {
205 if (y2 > 0 && y1 < _height) {
206 XDrawLine(fl_display,
207 _window, getGC(gc_select),
212 cursor_visible = true;
216 XFreePixmap(fl_display, cursor_pixmap);
220 if (y2 > 0 && y1 < _height) {
222 cursor_pixmap_h = y2 - y1 + 1;
224 cursor_pixmap_y = y1;
226 XCreatePixmap(fl_display,
230 fl_get_visual_depth());
231 XCopyArea(fl_display,
235 _offset_x + cursor_pixmap_x,
236 _offset_y + cursor_pixmap_y,
237 cursor_pixmap_w, cursor_pixmap_h,
239 XDrawLine(fl_display,
240 _window, getGC(gc_copy),
245 cursor_visible = true;
251 /* returns 1 if first has changed, otherwise 0 */
252 int LyXScreen::FitManualCursor(long /*x*/, long y, int asc, int desc)
256 if (y + desc - first >= _height)
257 newtop = y - 3*_height / 4; /* the scroll region must be so big!! */
258 else if (y - asc < first
260 newtop = y - _height / 4;
265 if (newtop != first){
274 void LyXScreen::HideManualCursor(long x, long y, int asc, int desc){
275 if (fast_selection || mono_video)
276 ShowManualCursor(x,y,asc,desc);
282 void LyXScreen::ShowManualCursor(long x, long y, int asc, int desc)
287 y1 = y - first - asc;
290 y2 = y -first + desc;
294 if (fast_selection || mono_video){
295 if (y2 > 0 && y1 < _height) {
296 XDrawLine(fl_display,
297 _window, getGC(gc_select),
305 XFreePixmap(fl_display, cursor_pixmap);
309 if (y2 > 0 && y1 < _height) {
311 cursor_pixmap_h = y2 - y1 + 1;
313 cursor_pixmap_y = y1;
315 XCreatePixmap (fl_display,
319 fl_get_visual_depth());
321 XCopyArea (fl_display,
325 _offset_x + cursor_pixmap_x,
326 _offset_y + cursor_pixmap_y,
330 XDrawLine(fl_display,
331 _window, getGC(gc_copy),
337 cursor_visible = true;
342 void LyXScreen::HideCursor()
344 if (!cursor_visible) return;
346 if (fast_selection || mono_video){
347 cursor_visible = false;
349 cursor_visible = false;
352 XCopyArea (fl_display,
357 cursor_pixmap_w, cursor_pixmap_h,
358 cursor_pixmap_x + _offset_x,
359 cursor_pixmap_y + _offset_y);
361 cursor_visible = false;
366 void LyXScreen::CursorToggle()
375 /* returns a new top so that the cursor is visible */
376 long LyXScreen::TopCursorVisible()
381 - text->cursor.row->baseline
382 + text->cursor.row->height
383 - first >= _height) {
384 if (text->cursor.row->height < _height
385 && text->cursor.row->height > _height/4)
386 newtop = text->cursor.y
387 + text->cursor.row->height
388 - text->cursor.row->baseline - _height;
390 newtop = text->cursor.y
391 - 3*_height / 4; /* the scroll region must be so big!! */
392 } else if (text->cursor.y - text->cursor.row->baseline < first
394 if (text->cursor.row->height < _height
395 && text->cursor.row->height > _height/4)
396 newtop = text->cursor.y - text->cursor.row->baseline;
398 newtop = text->cursor.y - _height / 4;
410 /* scrolls the screen so that the cursor is visible, if necessary.
411 * returns 1 if a change was made, otherwise 0 */
412 int LyXScreen::FitCursor()
414 /* is a change necessary */
415 long newtop = TopCursorVisible();
416 int result = (newtop != first);
423 void LyXScreen::Update()
427 if (text->status == LyXText::NEED_MORE_REFRESH
428 || screen_refresh_y > -1 ) {
429 if (screen_refresh_y > -1
430 && screen_refresh_y < text->refresh_y)
431 y = screen_refresh_y;
435 if (y < first) y = first;
437 DrawFromTo(y - first, _height);
439 text->status = LyXText::UNCHANGED;
440 screen_refresh_y = -1;
441 expose(0, y-first, _width, _height - (y - first));
442 } else if (text->status == LyXText::NEED_VERY_LITTLE_REFRESH) {
443 /* ok I will update the current cursor row */
445 DrawOneRow(text->refresh_row, y);
446 text->status = LyXText::UNCHANGED;
447 expose(0, text->refresh_y-first,
448 _width, text->refresh_row->height);
453 void LyXScreen::SmallUpdate()
459 if (text->status == LyXText::NEED_MORE_REFRESH){
460 /* ok I will update till the current cursor row */
461 row = text->refresh_row;
465 if (y > text->cursor.y) {
470 while (row && row != text->cursor.row && y < first + _height) {
476 screen_refresh_y = y;
477 screen_refresh_row = row->next;
478 text->status = LyXText::UNCHANGED;
479 // Is the right regin exposed?
480 expose(0, y2-first, _width, y-y2);
481 } else if (text->status == LyXText::NEED_VERY_LITTLE_REFRESH) {
482 /* ok I will update the current cursor row */
483 row = text->refresh_row;
486 text->status = LyXText::UNCHANGED;
487 expose(0, text->refresh_y - first,
488 _width, row->height);
493 void LyXScreen::ToggleSelection(bool kill_selection)
498 /* only if there is a selection */
499 if (!text->selection)
502 if (fast_selection || mono_video){
504 /* selection only in one row ?*/
505 if (text->sel_start_cursor.y == text->sel_end_cursor.y) {
507 /* only if something is visible */
508 if (text->sel_start_cursor.y
509 - text->sel_start_cursor.row->baseline
511 && text->sel_start_cursor.y
512 - text->sel_start_cursor.row->baseline +
513 text->sel_start_cursor.row->height - first > 0) {
514 top = text->sel_start_cursor.y
515 - text->sel_start_cursor.row->baseline
518 + text->sel_start_cursor.row->height;
521 if (bottom > _height)
523 XFillRectangle(fl_display,_window,
525 text->sel_start_cursor.x
528 text->sel_end_cursor.x
529 - text->sel_start_cursor.x,
533 /* the sel_start_cursor row first */
534 /* only if anything is visible */
535 if (text->sel_start_cursor.y
536 - text->sel_start_cursor.row->baseline
538 && text->sel_start_cursor.y
539 - text->sel_start_cursor.row->baseline +
540 text->sel_start_cursor.row->height - first > 0) {
541 top = text->sel_start_cursor.y
542 - text->sel_start_cursor.row->baseline
545 + text->sel_start_cursor.row->height;
548 if (bottom > _height)
550 XFillRectangle(fl_display,_window,
552 text->sel_start_cursor.x
556 - text->sel_start_cursor.x,
562 if (text->sel_start_cursor.row->next !=
563 text->sel_end_cursor.row) {
564 top = text->sel_start_cursor.y
565 - text->sel_start_cursor.row->baseline
566 + text->sel_start_cursor.row->height;
567 bottom = text->sel_end_cursor.y
568 - text->sel_end_cursor.row->baseline;
572 if (bottom - first < 0)
575 if (bottom - first > _height)
576 bottom = first + _height;
577 if (top - first > _height)
578 top = first + _height;
581 XFillRectangle(fl_display,
585 top - first+_offset_y,
591 /* the sel_end_cursor row last */
592 if (text->sel_end_cursor.y
593 - text->sel_end_cursor.row->baseline
595 && text->sel_end_cursor.y
596 - text->sel_end_cursor.row->baseline +
597 text->sel_end_cursor.row->height - first > 0) {
598 top = text->sel_end_cursor.y
599 - text->sel_end_cursor.row->baseline
602 + text->sel_end_cursor.row->height;
605 if (bottom > _height)
607 XFillRectangle(fl_display,_window,
611 text->sel_end_cursor.x,
616 top = text->sel_start_cursor.y
617 - text->sel_start_cursor.row->baseline;
618 bottom = text->sel_end_cursor.y
619 - text->sel_end_cursor.row->baseline
620 + text->sel_end_cursor.row->height;
624 if (bottom - first < 0)
627 if (bottom - first > _height)
628 bottom = first + _height;
629 if (top - first > _height)
630 top = first + _height;
634 DrawFromTo(top - first, bottom - first);
635 expose(0, top - first, _width, bottom - first - (top - first));
640 void LyXScreen::ToggleToggle()
645 if (text->toggle_cursor.par == text->toggle_end_cursor.par
646 && text->toggle_cursor.pos == text->toggle_end_cursor.pos)
649 if (fast_selection || mono_video){
651 /* selection only in one row ?*/
652 if (text->toggle_cursor.y == text->toggle_end_cursor.y) {
654 /* only if anything is visible */
655 if (text->toggle_cursor.y - text->toggle_cursor.row->baseline - first < _height
656 && text->toggle_cursor.y - text->toggle_cursor.row->baseline +
657 text->toggle_cursor.row->height - first > 0) {
658 top = text->toggle_cursor.y - text->toggle_cursor.row->baseline - first;
659 bottom = top + text->toggle_cursor.row->height;
660 if (top < 0) top = 0;
661 if (bottom > _height) bottom = _height;
662 XFillRectangle(fl_display,_window,
664 text->toggle_cursor.x+_offset_x,
666 text->toggle_end_cursor.x -
667 text->toggle_cursor.x,
671 /* the toggle_cursor row first */
672 /* only if anything is visible */
673 if (text->toggle_cursor.y - text->toggle_cursor.row->baseline - first < _height
674 && text->toggle_cursor.y - text->toggle_cursor.row->baseline +
675 text->toggle_cursor.row->height - first > 0) {
676 top = text->toggle_cursor.y - text->toggle_cursor.row->baseline - first;
677 bottom = top + text->toggle_cursor.row->height;
680 if (bottom > _height)
682 XFillRectangle(fl_display,_window,
684 text->toggle_cursor.x+_offset_x,
686 _width - text->toggle_cursor.x,
692 if (text->toggle_cursor.row->next !=
693 text->toggle_end_cursor.row) {
694 top = text->toggle_cursor.y
695 - text->toggle_cursor.row->baseline
696 + text->toggle_cursor.row->height;
697 bottom = text->toggle_end_cursor.y
698 - text->toggle_end_cursor.row->baseline;
702 if (bottom - first < 0)
705 if (bottom - first > _height)
706 bottom = first + _height;
707 if (top - first > _height)
708 top = first + _height;
711 XFillRectangle(fl_display,_window,
714 top - first+_offset_y,
720 /* the toggle_end_cursor row last */
721 if (text->toggle_end_cursor.y - text->toggle_end_cursor.row->baseline - first < _height
722 && text->toggle_end_cursor.y - text->toggle_end_cursor.row->baseline +
723 text->toggle_end_cursor.row->height - first > 0) {
724 top = text->toggle_end_cursor.y
725 - text->toggle_end_cursor.row->baseline
728 + text->toggle_end_cursor.row->height;
731 if (bottom > _height)
733 XFillRectangle(fl_display,_window,
737 text->toggle_end_cursor.x,
742 top = text->toggle_cursor.y
743 - text->toggle_cursor.row->baseline;
744 bottom = text->toggle_end_cursor.y
745 - text->toggle_end_cursor.row->baseline
746 + text->toggle_end_cursor.row->height;
750 if (bottom - first < 0)
753 if (bottom - first > _height)
754 bottom = first + _height;
755 if (top - first > _height)
756 top = first + _height;
758 DrawFromTo(top - first, bottom - first);
759 expose(0, top - first, _width, bottom - first - (top - first));
765 void LyXScreen::drawTableLine(int baseline, int x, int length, bool on_off)
769 gc = getGC(gc_thin_on_off_line);
780 void LyXScreen::drawVerticalTableLine(int x, int y1, int y2, bool on_off)
784 gc = getGC(gc_thin_on_off_line);
795 void LyXScreen::drawFrame(int /*ft*/, int x, int y, int w, int h,
796 FL_COLOR /*col*/, int /*b*/)
799 #warning Implement this using X11 calls, and the repaint problems are gone!
801 // At least, I think that should do it since we only have them after
802 // one of these buttons are displayed now! Lars, it seems you've hit the
804 // fl_winset(foreground);
805 // fl_drw_frame(ft, x, y, w, h, col, b);
806 // This should be changed to draw a button like frame, in the
807 // mean time we'll just use a regular rectangle
809 // I want the buttons back before 0.12. OK, this is very simple,
810 // like what is done in xforms sources. (Ale)
812 // This one is too dirty. Get rid of it.
815 // Please comment this annonymous variable.
818 // I think these calls to fl_color might make xforms sometimes
819 // draw the wrong color on other objects.
820 fl_color(FL_TOP_BCOL);
821 XFillRectangle(fl_display, foreground, fl_gc,x-d,y-d,w+2*d,d);
822 fl_color(FL_BOTTOM_BCOL);
823 XFillRectangle(fl_display, foreground, fl_gc,x-d,y+h,w+2*d,d);
825 // Now a couple of trapezoids
828 pl[0].x = x-d; pl[0].y = y-d;
829 pl[1].x = x-d; pl[1].y = y+h+d;
830 pl[2].x = x; pl[2].y = y+h;
831 pl[3].x = x; pl[3].y = y;
833 pr[0].x = x+w+d; pr[0].y = y-d;
834 pr[1].x = x+w+d; pr[1].y = y+h+d;
835 pr[2].x = x+w; pr[2].y = y+h;
836 pr[3].x = x+w; pr[3].y = y;
838 fl_color(FL_LEFT_BCOL);
839 XFillPolygon(fl_display,
842 Convex, CoordModeOrigin);
843 fl_color(FL_RIGHT_BCOL);
844 XFillPolygon(fl_display,
847 Convex, CoordModeOrigin);