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;
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)
94 /* get the first needed row */
95 row = text->GetRowNearY(y_text);
96 /* y_text is now the real beginning of the row */
99 /* y1 is now the real beginning of row on the screen */
101 while (row != 0 && y < y2) {
103 text->GetVisibleRow(*this, y, row, y + first);
109 /* maybe we have to clear the screen at the bottom */
111 fillRectangle(gc_lighted,
120 void LyXScreen::DrawOneRow(Row *row, long &y_text)
126 if (y + row->height > 0 && y - row->height <= _height) {
127 /* ok there is something visible */
128 text->GetVisibleRow(*this, y, row, y + first);
134 /* draws the screen, starting with textposition y. uses as much already
135 * printed pixels as possible */
136 void LyXScreen::Draw(long y)
138 if (cursor_visible) HideCursor();
141 long old_first = first;
144 /* is any optimiziation possible? */
145 if ((y - old_first) < _height
146 && (old_first - y) < _height) {
147 if (first < old_first) {
148 DrawFromTo(0, old_first - first);
149 XCopyArea (fl_display,
153 _offset_x, _offset_y,
154 _width , _height - old_first + first,
155 _offset_x, _offset_y + old_first - first);
156 // expose the area drawn
157 expose(0, 0, _width, old_first - first);
159 DrawFromTo(_height + old_first - first, _height);
160 XCopyArea (fl_display,
164 _offset_x, _offset_y + first - old_first,
165 _width , _height + old_first - first,
166 _offset_x, _offset_y);
167 // expose the area drawn
168 expose(0, _height + old_first - first,
169 _width, first - old_first);
172 /* make a dumb new-draw */
173 DrawFromTo(0, _height);
174 expose(0, 0, _width, _height);
179 void LyXScreen::ShowCursor()
185 if (cursor_visible) return;
189 y1 = text->cursor.y - text->real_current_font.maxAscent() - first;
192 y2 = text->cursor.y + text->real_current_font.maxDescent() - first;
193 if (y2 > _height) y2 = _height;
195 // Secure against very strange situations
196 if (y2 < y1) y2 = y1;
198 if (fast_selection || mono_video) {
199 if (y2 > 0 && y1 < _height) {
200 XDrawLine(fl_display,
201 _window, getGC(gc_select),
206 cursor_visible = true;
210 XFreePixmap(fl_display, cursor_pixmap);
214 if (y2 > 0 && y1 < _height) {
216 cursor_pixmap_h = y2 - y1 + 1;
218 cursor_pixmap_y = y1;
220 XCreatePixmap(fl_display,
224 fl_get_visual_depth());
225 XCopyArea(fl_display,
229 _offset_x + cursor_pixmap_x,
230 _offset_y + cursor_pixmap_y,
231 cursor_pixmap_w, cursor_pixmap_h,
233 XDrawLine(fl_display,
234 _window, getGC(gc_copy),
239 cursor_visible = true;
245 /* returns 1 if first has changed, otherwise 0 */
246 int LyXScreen::FitManualCursor(long /*x*/, long y, int asc, int desc)
250 if (y + desc - first >= _height)
251 newtop = y - 3*_height / 4; /* the scroll region must be so big!! */
252 else if (y - asc < first
254 newtop = y - _height / 4;
259 if (newtop != first){
268 void LyXScreen::HideManualCursor(long x, long y, int asc, int desc){
269 if (fast_selection || mono_video)
270 ShowManualCursor(x,y,asc,desc);
276 void LyXScreen::ShowManualCursor(long x, long y, int asc, int desc)
281 y1 = y - first - asc;
284 y2 = y -first + desc;
288 if (fast_selection || mono_video){
289 if (y2 > 0 && y1 < _height) {
290 XDrawLine(fl_display,
291 _window, getGC(gc_select),
299 XFreePixmap(fl_display, cursor_pixmap);
303 if (y2 > 0 && y1 < _height) {
305 cursor_pixmap_h = y2 - y1 + 1;
307 cursor_pixmap_y = y1;
309 XCreatePixmap (fl_display,
313 fl_get_visual_depth());
315 XCopyArea (fl_display,
319 _offset_x + cursor_pixmap_x,
320 _offset_y + cursor_pixmap_y,
324 XDrawLine(fl_display,
325 _window, getGC(gc_copy),
331 cursor_visible = true;
336 void LyXScreen::HideCursor()
338 if (!cursor_visible) return;
340 if (fast_selection || mono_video){
341 cursor_visible = false;
343 cursor_visible = false;
346 XCopyArea (fl_display,
351 cursor_pixmap_w, cursor_pixmap_h,
352 cursor_pixmap_x + _offset_x,
353 cursor_pixmap_y + _offset_y);
355 cursor_visible = false;
360 void LyXScreen::CursorToggle()
369 /* returns a new top so that the cursor is visible */
370 long LyXScreen::TopCursorVisible()
375 - text->cursor.row->baseline
376 + text->cursor.row->height
377 - first >= _height) {
378 if (text->cursor.row->height < _height
379 && text->cursor.row->height > _height/4)
380 newtop = text->cursor.y
381 + text->cursor.row->height
382 - text->cursor.row->baseline - _height;
384 newtop = text->cursor.y
385 - 3*_height / 4; /* the scroll region must be so big!! */
386 } else if (text->cursor.y - text->cursor.row->baseline < first
388 if (text->cursor.row->height < _height
389 && text->cursor.row->height > _height/4)
390 newtop = text->cursor.y - text->cursor.row->baseline;
392 newtop = text->cursor.y - _height / 4;
404 /* scrolls the screen so that the cursor is visible, if necessary.
405 * returns 1 if a change was made, otherwise 0 */
406 int LyXScreen::FitCursor()
408 /* is a change necessary */
409 long newtop = TopCursorVisible();
410 int result = (newtop != first);
417 void LyXScreen::Update()
421 if (text->status == LyXText::NEED_MORE_REFRESH
422 || screen_refresh_y > -1 ) {
423 if (screen_refresh_y > -1
424 && screen_refresh_y < text->refresh_y)
425 y = screen_refresh_y;
429 if (y < first) y = first;
431 DrawFromTo(y - first, _height);
433 text->status = LyXText::UNCHANGED;
434 screen_refresh_y = -1;
435 expose(0, y-first, _width, _height - (y - first));
436 } else if (text->status == LyXText::NEED_VERY_LITTLE_REFRESH) {
437 /* ok I will update the current cursor row */
439 DrawOneRow(text->refresh_row, y);
440 text->status = LyXText::UNCHANGED;
441 expose(0, text->refresh_y-first,
442 _width, text->refresh_row->height);
447 void LyXScreen::SmallUpdate()
453 if (text->status == LyXText::NEED_MORE_REFRESH){
454 /* ok I will update till the current cursor row */
455 row = text->refresh_row;
459 if (y > text->cursor.y) {
464 while (row && row != text->cursor.row && y < first + _height) {
470 screen_refresh_y = y;
471 screen_refresh_row = row->next;
472 text->status = LyXText::UNCHANGED;
473 // Is the right regin exposed?
474 expose(0, y2-first, _width, y-y2);
475 } else if (text->status == LyXText::NEED_VERY_LITTLE_REFRESH) {
476 /* ok I will update the current cursor row */
477 row = text->refresh_row;
480 text->status = LyXText::UNCHANGED;
481 expose(0, text->refresh_y - first,
482 _width, row->height);
487 void LyXScreen::ToggleSelection(bool kill_selection)
492 /* only if there is a selection */
493 if (!text->selection)
496 if (fast_selection || mono_video){
498 /* selection only in one row ?*/
499 if (text->sel_start_cursor.y == text->sel_end_cursor.y) {
501 /* only if something is visible */
502 if (text->sel_start_cursor.y
503 - text->sel_start_cursor.row->baseline
505 && text->sel_start_cursor.y
506 - text->sel_start_cursor.row->baseline +
507 text->sel_start_cursor.row->height - first > 0) {
508 top = text->sel_start_cursor.y
509 - text->sel_start_cursor.row->baseline
512 + text->sel_start_cursor.row->height;
515 if (bottom > _height)
517 XFillRectangle(fl_display,_window,
519 text->sel_start_cursor.x
522 text->sel_end_cursor.x
523 - text->sel_start_cursor.x,
527 /* the sel_start_cursor row first */
528 /* only if anything is visible */
529 if (text->sel_start_cursor.y
530 - text->sel_start_cursor.row->baseline
532 && text->sel_start_cursor.y
533 - text->sel_start_cursor.row->baseline +
534 text->sel_start_cursor.row->height - first > 0) {
535 top = text->sel_start_cursor.y
536 - text->sel_start_cursor.row->baseline
539 + text->sel_start_cursor.row->height;
542 if (bottom > _height)
544 XFillRectangle(fl_display,_window,
546 text->sel_start_cursor.x
550 - text->sel_start_cursor.x,
556 if (text->sel_start_cursor.row->next !=
557 text->sel_end_cursor.row) {
558 top = text->sel_start_cursor.y
559 - text->sel_start_cursor.row->baseline
560 + text->sel_start_cursor.row->height;
561 bottom = text->sel_end_cursor.y
562 - text->sel_end_cursor.row->baseline;
566 if (bottom - first < 0)
569 if (bottom - first > _height)
570 bottom = first + _height;
571 if (top - first > _height)
572 top = first + _height;
575 XFillRectangle(fl_display,
579 top - first+_offset_y,
585 /* the sel_end_cursor row last */
586 if (text->sel_end_cursor.y
587 - text->sel_end_cursor.row->baseline
589 && text->sel_end_cursor.y
590 - text->sel_end_cursor.row->baseline +
591 text->sel_end_cursor.row->height - first > 0) {
592 top = text->sel_end_cursor.y
593 - text->sel_end_cursor.row->baseline
596 + text->sel_end_cursor.row->height;
599 if (bottom > _height)
601 XFillRectangle(fl_display,_window,
605 text->sel_end_cursor.x,
610 top = text->sel_start_cursor.y
611 - text->sel_start_cursor.row->baseline;
612 bottom = text->sel_end_cursor.y
613 - text->sel_end_cursor.row->baseline
614 + text->sel_end_cursor.row->height;
618 if (bottom - first < 0)
621 if (bottom - first > _height)
622 bottom = first + _height;
623 if (top - first > _height)
624 top = first + _height;
628 DrawFromTo(top - first, bottom - first);
629 expose(0, top - first, _width, bottom - first - (top - first));
634 void LyXScreen::ToggleToggle()
639 if (text->toggle_cursor.par == text->toggle_end_cursor.par
640 && text->toggle_cursor.pos == text->toggle_end_cursor.pos)
643 if (fast_selection || mono_video){
645 /* selection only in one row ?*/
646 if (text->toggle_cursor.y == text->toggle_end_cursor.y) {
648 /* only if anything is visible */
649 if (text->toggle_cursor.y - text->toggle_cursor.row->baseline - first < _height
650 && text->toggle_cursor.y - text->toggle_cursor.row->baseline +
651 text->toggle_cursor.row->height - first > 0) {
652 top = text->toggle_cursor.y - text->toggle_cursor.row->baseline - first;
653 bottom = top + text->toggle_cursor.row->height;
654 if (top < 0) top = 0;
655 if (bottom > _height) bottom = _height;
656 XFillRectangle(fl_display,_window,
658 text->toggle_cursor.x+_offset_x,
660 text->toggle_end_cursor.x -
661 text->toggle_cursor.x,
665 /* the toggle_cursor row first */
666 /* only if anything is visible */
667 if (text->toggle_cursor.y - text->toggle_cursor.row->baseline - first < _height
668 && text->toggle_cursor.y - text->toggle_cursor.row->baseline +
669 text->toggle_cursor.row->height - first > 0) {
670 top = text->toggle_cursor.y - text->toggle_cursor.row->baseline - first;
671 bottom = top + text->toggle_cursor.row->height;
674 if (bottom > _height)
676 XFillRectangle(fl_display,_window,
678 text->toggle_cursor.x+_offset_x,
680 _width - text->toggle_cursor.x,
686 if (text->toggle_cursor.row->next !=
687 text->toggle_end_cursor.row) {
688 top = text->toggle_cursor.y
689 - text->toggle_cursor.row->baseline
690 + text->toggle_cursor.row->height;
691 bottom = text->toggle_end_cursor.y
692 - text->toggle_end_cursor.row->baseline;
696 if (bottom - first < 0)
699 if (bottom - first > _height)
700 bottom = first + _height;
701 if (top - first > _height)
702 top = first + _height;
705 XFillRectangle(fl_display,_window,
708 top - first+_offset_y,
714 /* the toggle_end_cursor row last */
715 if (text->toggle_end_cursor.y - text->toggle_end_cursor.row->baseline - first < _height
716 && text->toggle_end_cursor.y - text->toggle_end_cursor.row->baseline +
717 text->toggle_end_cursor.row->height - first > 0) {
718 top = text->toggle_end_cursor.y
719 - text->toggle_end_cursor.row->baseline
722 + text->toggle_end_cursor.row->height;
725 if (bottom > _height)
727 XFillRectangle(fl_display,_window,
731 text->toggle_end_cursor.x,
736 top = text->toggle_cursor.y
737 - text->toggle_cursor.row->baseline;
738 bottom = text->toggle_end_cursor.y
739 - text->toggle_end_cursor.row->baseline
740 + text->toggle_end_cursor.row->height;
744 if (bottom - first < 0)
747 if (bottom - first > _height)
748 bottom = first + _height;
749 if (top - first > _height)
750 top = first + _height;
752 DrawFromTo(top - first, bottom - first);
753 expose(0, top - first, _width, bottom - first - (top - first));
759 void LyXScreen::drawTableLine(int baseline, int x, int length, bool on_off)
763 gc = getGC(gc_thin_on_off_line);
774 void LyXScreen::drawVerticalTableLine(int x, int y1, int y2, bool on_off)
778 gc = getGC(gc_thin_on_off_line);
789 void LyXScreen::drawFrame(int /*ft*/, int x, int y, int w, int h,
790 FL_COLOR /*col*/, int /*b*/)
792 // Implement this using X11 calls, and the repaint problems are gone!
793 // At least, I think that should do it since we only have them after
794 // one of these buttons are displayed now! Lars, it seems you've hit the
796 // fl_winset(foreground);
797 // fl_drw_frame(ft, x, y, w, h, col, b);
798 // This should be changed to draw a button like frame, in the
799 // mean time we'll just use a regular rectangle
801 // I want the buttons back before 0.12. OK, this is very simple,
802 // like what is done in xforms sources. (Ale)
804 // This one is too dirty. Get rid of it.
807 // Please comment this annonymous variable.
810 // I think these calls to fl_color might make xforms sometimes
811 // draw the wrong color on other objects.
812 fl_color(FL_TOP_BCOL);
813 XFillRectangle(fl_display, foreground, fl_gc,x-d,y-d,w+2*d,d);
814 fl_color(FL_BOTTOM_BCOL);
815 XFillRectangle(fl_display, foreground, fl_gc,x-d,y+h,w+2*d,d);
817 // Now a couple of trapezoids
820 pl[0].x = x-d; pl[0].y = y-d;
821 pl[1].x = x-d; pl[1].y = y+h+d;
822 pl[2].x = x; pl[2].y = y+h;
823 pl[3].x = x; pl[3].y = y;
825 pr[0].x = x+w+d; pr[0].y = y-d;
826 pr[1].x = x+w+d; pr[1].y = y+h+d;
827 pr[2].x = x+w; pr[2].y = y+h;
828 pr[3].x = x+w; pr[3].y = y;
830 fl_color(FL_LEFT_BCOL);
831 XFillPolygon(fl_display,
834 Convex, CoordModeOrigin);
835 fl_color(FL_RIGHT_BCOL);
836 XFillPolygon(fl_display,
839 Convex, CoordModeOrigin);