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"
28 val.foreground = BlackPixel(fl_display,
29 DefaultScreen(fl_display));
32 val.graphics_exposures = false;
33 val.line_style = LineSolid;
35 return XCreateGC(fl_display, RootWindow(fl_display, 0),
36 GCForeground | GCFunction | GCGraphicsExposures
37 | GCLineWidth | GCLineStyle , &val);
42 LyXScreen::LyXScreen(BufferView * o, Window window,
49 : owner(o), text(text_ptr), _window(window),
50 _width(width), _height(height),
51 _offset_x(offset_x), _offset_y(offset_y)
55 /* the cursor isnt yet visible */
56 cursor_visible = false;
57 screen_refresh_y = -1;
59 /* create the foreground pixmap */
74 LyXScreen::~LyXScreen() {}
77 void LyXScreen::Redraw()
79 DrawFromTo(0, _height);
80 screen_refresh_y = -1;
81 expose(0, 0, _width, _height);
83 cursor_visible = false;
89 void LyXScreen::expose(int x, int y, int exp_width, int exp_height)
96 exp_width, exp_height,
97 x+_offset_x, y+_offset_y);
101 void LyXScreen::DrawFromTo(int y1, int y2)
103 long y_text = first + y1;
105 /* get the first needed row */
106 Row * row = text->GetRowNearY(y_text);
107 /* y_text is now the real beginning of the row */
109 long y = y_text - first;
110 /* y1 is now the real beginning of row on the screen */
112 while (row != 0 && y < y2) {
114 text->GetVisibleRow(y, row, y + first);
120 /* maybe we have to clear the screen at the bottom */
122 owner->painter().fillRectangle(0, y, _width, y2 - y,
128 void LyXScreen::DrawOneRow(Row * row, long & y_text)
130 long y = y_text - first;
132 if (y + row->height > 0 && y - row->height <= _height) {
133 /* ok there is something visible */
134 text->GetVisibleRow(y, row, y + first);
136 y_text+= row->height;
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;
205 XFreePixmap(fl_display, cursor_pixmap);
209 if (y2 > 0 && y1 < _height) {
211 cursor_pixmap_h = y2 - y1 + 1;
213 cursor_pixmap_y = y1;
215 XCreatePixmap(fl_display,
219 fl_get_visual_depth());
220 XCopyArea(fl_display,
224 _offset_x + cursor_pixmap_x,
225 _offset_y + cursor_pixmap_y,
226 cursor_pixmap_w, cursor_pixmap_h,
228 XDrawLine(fl_display,
234 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()
268 void LyXScreen::ShowManualCursor(long x, long y, int asc, int desc)
273 y1 = y - first - asc;
276 y2 = y -first + desc;
281 XFreePixmap(fl_display, cursor_pixmap);
285 if (y2 > 0 && y1 < _height) {
287 cursor_pixmap_h = y2 - y1 + 1;
289 cursor_pixmap_y = y1;
291 XCreatePixmap (fl_display,
295 fl_get_visual_depth());
296 XCopyArea (fl_display,
300 _offset_x + cursor_pixmap_x,
301 _offset_y + cursor_pixmap_y,
305 XDrawLine(fl_display,
312 cursor_visible = true;
316 void LyXScreen::HideCursor()
318 if (!cursor_visible) return;
321 XCopyArea (fl_display,
326 cursor_pixmap_w, cursor_pixmap_h,
327 cursor_pixmap_x + _offset_x,
328 cursor_pixmap_y + _offset_y);
330 cursor_visible = false;
334 void LyXScreen::CursorToggle()
343 /* returns a new top so that the cursor is visible */
344 long LyXScreen::TopCursorVisible()
349 - text->cursor.row->baseline
350 + text->cursor.row->height
351 - first >= _height) {
352 if (text->cursor.row->height < _height
353 && text->cursor.row->height > _height/4)
354 newtop = text->cursor.y
355 + text->cursor.row->height
356 - text->cursor.row->baseline - _height;
358 newtop = text->cursor.y
359 - 3*_height / 4; /* the scroll region must be so big!! */
360 } else if (text->cursor.y - text->cursor.row->baseline < first
362 if (text->cursor.row->height < _height
363 && text->cursor.row->height > _height/4)
364 newtop = text->cursor.y - text->cursor.row->baseline;
366 newtop = text->cursor.y - _height / 4;
378 /* scrolls the screen so that the cursor is visible, if necessary.
379 * returns 1 if a change was made, otherwise 0 */
380 int LyXScreen::FitCursor()
382 /* is a change necessary */
383 long newtop = TopCursorVisible();
384 int result = (newtop != first);
391 void LyXScreen::Update()
395 if (text->status == LyXText::NEED_MORE_REFRESH
396 || screen_refresh_y > -1 ) {
397 if (screen_refresh_y > -1
398 && screen_refresh_y < text->refresh_y)
399 y = screen_refresh_y;
403 if (y < first) y = first;
405 DrawFromTo(y - first, _height);
407 text->status = LyXText::UNCHANGED;
408 screen_refresh_y = -1;
409 expose(0, y-first, _width, _height - (y - first));
410 } else if (text->status == LyXText::NEED_VERY_LITTLE_REFRESH) {
411 /* ok I will update the current cursor row */
413 DrawOneRow(text->refresh_row, y);
414 text->status = LyXText::UNCHANGED;
415 expose(0, text->refresh_y-first,
416 _width, text->refresh_row->height);
421 void LyXScreen::SmallUpdate()
427 if (text->status == LyXText::NEED_MORE_REFRESH){
428 /* ok I will update till the current cursor row */
429 row = text->refresh_row;
433 if (y > text->cursor.y) {
438 while (row && row != text->cursor.row && y < first + _height) {
444 screen_refresh_y = y;
445 screen_refresh_row = row->next;
446 text->status = LyXText::UNCHANGED;
447 // Is the right regin exposed?
448 expose(0, y2-first, _width, y-y2);
449 } else if (text->status == LyXText::NEED_VERY_LITTLE_REFRESH) {
450 /* ok I will update the current cursor row */
451 row = text->refresh_row;
454 text->status = LyXText::UNCHANGED;
455 expose(0, text->refresh_y - first,
456 _width, row->height);
461 void LyXScreen::ToggleSelection(bool kill_selection)
463 /* only if there is a selection */
464 if (!text->selection)
467 long top = text->sel_start_cursor.y
468 - text->sel_start_cursor.row->baseline;
469 long bottom = text->sel_end_cursor.y
470 - text->sel_end_cursor.row->baseline
471 + text->sel_end_cursor.row->height;
475 if (bottom - first < 0)
478 if (bottom - first > _height)
479 bottom = first + _height;
480 if (top - first > _height)
481 top = first + _height;
485 DrawFromTo(top - first, bottom - first);
486 expose(0, top - first, _width, bottom - first - (top - first));
490 void LyXScreen::ToggleToggle()
492 if (text->toggle_cursor.par == text->toggle_end_cursor.par
493 && text->toggle_cursor.pos == text->toggle_end_cursor.pos)
496 long top = text->toggle_cursor.y
497 - text->toggle_cursor.row->baseline;
498 long bottom = text->toggle_end_cursor.y
499 - text->toggle_end_cursor.row->baseline
500 + text->toggle_end_cursor.row->height;
504 if (bottom - first < 0)
507 if (bottom - first > _height)
508 bottom = first + _height;
509 if (top - first > _height)
510 top = first + _height;
512 DrawFromTo(top - first, bottom - first);
513 expose(0, top - first, _width, bottom - first - (top - first));