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"
19 #include "lyxscreen.h"
32 val.foreground = BlackPixel(fl_display,
33 DefaultScreen(fl_display));
36 val.graphics_exposures = false;
37 val.line_style = LineSolid;
39 return XCreateGC(fl_display, RootWindow(fl_display, 0),
40 GCForeground | GCFunction | GCGraphicsExposures
41 | GCLineWidth | GCLineStyle , &val);
46 LyXScreen::LyXScreen(WorkArea & o, LyXText * text_ptr)
47 : owner(o), text(text_ptr)
51 /* the cursor isnt yet visible */
52 cursor_visible = false;
53 screen_refresh_y = -1;
66 void LyXScreen::Redraw()
68 DrawFromTo(0, owner.height());
69 screen_refresh_y = -1;
70 expose(0, 0, owner.workWidth(), owner.height());
72 cursor_visible = false;
78 void LyXScreen::expose(int x, int y, int exp_width, int exp_height)
85 exp_width, exp_height,
91 void LyXScreen::DrawFromTo(int y1, int y2)
93 long y_text = first + y1;
95 /* get the first needed row */
96 Row * row = text->GetRowNearY(y_text);
97 /* y_text is now the real beginning of the row */
99 long y = y_text - first;
100 /* y1 is now the real beginning of row on the screen */
102 while (row != 0 && y < y2) {
103 text->GetVisibleRow(y, row, y + first);
108 /* maybe we have to clear the screen at the bottom */
110 owner.getPainter().fillRectangle(0, y,
118 void LyXScreen::DrawOneRow(Row * row, long & y_text)
120 long y = y_text - first;
122 if (y + row->height > 0 && y - row->height <= owner.height()) {
123 /* ok there is something visible */
124 text->GetVisibleRow(y, row, y + first);
126 y_text += row->height;
130 /* draws the screen, starting with textposition y. uses as much already
131 * printed pixels as possible */
132 void LyXScreen::Draw(long y)
134 if (cursor_visible) HideCursor();
137 long old_first = first;
140 /* is any optimiziation possible? */
141 if ((y - old_first) < owner.height()
142 && (old_first - y) < owner.height()) {
143 if (first < old_first) {
144 DrawFromTo(0, old_first - first);
145 XCopyArea (fl_display,
152 owner.height() - old_first + first,
154 owner.ypos() + old_first - first
156 // expose the area drawn
162 owner.height() + old_first - first,
164 XCopyArea (fl_display,
169 owner.ypos() + first - old_first,
171 owner.height() + old_first - first,
174 // expose the area drawn
175 expose(0, owner.height() + old_first - first,
176 owner.workWidth(), first - old_first);
179 /* make a dumb new-draw */
180 DrawFromTo(0, owner.height());
181 expose(0, 0, owner.workWidth(), owner.height());
186 void LyXScreen::ShowCursor()
188 if (cursor_visible) return;
190 long x = text->cursor.x;
192 long y1 = max(text->cursor.y -
193 text->real_current_font.maxAscent() - first, 0L);
195 long y2 = min(text->cursor.y +
196 text->real_current_font.maxDescent() - first,
197 long(owner.height()));
199 // Secure against very strange situations
200 if (y2 < y1) y2 = y1;
203 XFreePixmap(fl_display, cursor_pixmap);
207 if (y2 > 0 && y1 < owner.height()) {
209 cursor_pixmap_h = y2 - y1 + 1;
211 cursor_pixmap_y = y1;
213 XCreatePixmap(fl_display,
217 fl_get_visual_depth());
218 XCopyArea(fl_display,
222 owner.xpos() + cursor_pixmap_x,
223 owner.ypos() + cursor_pixmap_y,
224 cursor_pixmap_w, cursor_pixmap_h,
226 XDrawLine(fl_display,
233 cursor_visible = true;
238 /* returns 1 if first has changed, otherwise 0 */
239 int LyXScreen::FitManualCursor(long /*x*/, long y, int asc, int desc)
243 if (y + desc - first >= owner.height())
244 newtop = y - 3 * owner.height() / 4; /* the scroll region must be so big!! */
245 else if (y - asc < first
247 newtop = y - owner.height() / 4;
252 if (newtop != first){
261 void LyXScreen::ShowManualCursor(long x, long y, int asc, int desc)
263 long y1 = max(y - first - asc, 0L);
264 long y2 = min(y - first + desc, long(owner.height()));
267 XFreePixmap(fl_display, cursor_pixmap);
274 cursor_pixmap_h = y2 - y1 + 1;
276 cursor_pixmap_y = y1;
278 XCreatePixmap (fl_display,
282 fl_get_visual_depth());
283 XCopyArea (fl_display,
287 owner.xpos() + cursor_pixmap_x,
288 owner.ypos() + cursor_pixmap_y,
292 XDrawLine(fl_display,
300 cursor_visible = true;
304 void LyXScreen::HideCursor()
306 if (!cursor_visible) return;
309 XCopyArea (fl_display,
314 cursor_pixmap_w, cursor_pixmap_h,
315 cursor_pixmap_x + owner.xpos(),
316 cursor_pixmap_y + owner.ypos());
318 cursor_visible = false;
322 void LyXScreen::CursorToggle()
331 /* returns a new top so that the cursor is visible */
332 long LyXScreen::TopCursorVisible()
337 - text->cursor.row->baseline
338 + text->cursor.row->height
339 - first >= owner.height()) {
340 if (text->cursor.row->height < owner.height()
341 && text->cursor.row->height > owner.height() / 4)
342 newtop = text->cursor.y
343 + text->cursor.row->height
344 - text->cursor.row->baseline - owner.height();
346 newtop = text->cursor.y
347 - 3 * owner.height() / 4; /* the scroll region must be so big!! */
348 } else if (text->cursor.y - text->cursor.row->baseline < first
350 if (text->cursor.row->height < owner.height()
351 && text->cursor.row->height > owner.height() / 4)
352 newtop = text->cursor.y - text->cursor.row->baseline;
354 newtop = text->cursor.y - owner.height() / 4;
366 /* scrolls the screen so that the cursor is visible, if necessary.
367 * returns 1 if a change was made, otherwise 0 */
368 int LyXScreen::FitCursor()
370 /* is a change necessary */
371 long newtop = TopCursorVisible();
372 int result = (newtop != first);
379 void LyXScreen::Update()
381 if (text->status == LyXText::NEED_MORE_REFRESH
382 || screen_refresh_y > -1 ) {
384 if (screen_refresh_y > -1
385 && screen_refresh_y < text->refresh_y)
386 y = screen_refresh_y;
390 if (y < first) y = first;
392 DrawFromTo(y - first, owner.height());
394 text->status = LyXText::UNCHANGED;
395 screen_refresh_y = -1;
397 owner.workWidth(), owner.height() - (y - first));
398 } else if (text->status == LyXText::NEED_VERY_LITTLE_REFRESH) {
399 /* ok I will update the current cursor row */
400 long y = text->refresh_y;
401 DrawOneRow(text->refresh_row, y);
402 text->status = LyXText::UNCHANGED;
403 expose(0, text->refresh_y - first,
404 owner.workWidth(), text->refresh_row->height);
409 void LyXScreen::SmallUpdate()
411 if (text->status == LyXText::NEED_MORE_REFRESH) {
412 /* ok I will update till the current cursor row */
413 Row * row = text->refresh_row;
414 long y = text->refresh_y;
417 if (y > text->cursor.y) {
423 && row != text->cursor.row
424 && y < first + owner.height()) {
430 screen_refresh_y = y;
431 screen_refresh_row = row->next;
432 text->status = LyXText::UNCHANGED;
433 // Is the right regin exposed?
434 expose(0, y2 - first,
435 owner.workWidth(), y - y2);
436 } else if (text->status == LyXText::NEED_VERY_LITTLE_REFRESH) {
437 /* ok I will update the current cursor row */
438 long y = text->refresh_y;
439 DrawOneRow(text->refresh_row, y);
440 text->status = LyXText::UNCHANGED;
441 expose(0, text->refresh_y - first,
442 owner.workWidth(), text->refresh_row->height);
447 void LyXScreen::ToggleSelection(bool kill_selection)
449 /* only if there is a selection */
450 if (!text->selection) return;
452 long top = text->sel_start_cursor.y
453 - text->sel_start_cursor.row->baseline;
454 long bottom = text->sel_end_cursor.y
455 - text->sel_end_cursor.row->baseline
456 + text->sel_end_cursor.row->height;
459 top = max(top, first);
461 bottom = max(bottom, first);
463 if (bottom > first + owner.height())
464 bottom = first + owner.height();
465 if (top > first + owner.height())
466 top = first + owner.height();
470 DrawFromTo(top - first, bottom - first);
471 expose(0, top - first,
473 bottom - first - (top - first));
477 void LyXScreen::ToggleToggle()
479 if (text->toggle_cursor.par == text->toggle_end_cursor.par
480 && text->toggle_cursor.pos == text->toggle_end_cursor.pos)
483 long top = text->toggle_cursor.y
484 - text->toggle_cursor.row->baseline;
485 long bottom = text->toggle_end_cursor.y
486 - text->toggle_end_cursor.row->baseline
487 + text->toggle_end_cursor.row->height;
491 if (bottom - first < 0)
494 if (bottom - first > owner.height())
495 bottom = first + owner.height();
496 if (top - first > owner.height())
497 top = first + owner.height();
499 DrawFromTo(top - first, bottom - first);
500 expose(0, top - first, owner.workWidth(),
501 bottom - first - (top - first));