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"
24 #include "bufferparams.h"
33 val.foreground = BlackPixel(fl_display,
34 DefaultScreen(fl_display));
37 val.graphics_exposures = false;
38 val.line_style = LineSolid;
40 return XCreateGC(fl_display, RootWindow(fl_display, 0),
41 GCForeground | GCFunction | GCGraphicsExposures
42 | GCLineWidth | GCLineStyle , &val);
47 LyXScreen::LyXScreen(WorkArea & o, LyXText * text_ptr)
48 : owner(o), text(text_ptr)
52 /* the cursor isnt yet visible */
53 cursor_visible = false;
54 screen_refresh_y = -1;
67 void LyXScreen::Redraw()
69 DrawFromTo(0, owner.height());
70 screen_refresh_y = -1;
71 expose(0, 0, owner.workWidth(), owner.height());
73 cursor_visible = false;
79 void LyXScreen::expose(int x, int y, int exp_width, int exp_height)
86 exp_width, exp_height,
92 void LyXScreen::DrawFromTo(int y1, int y2)
94 long y_text = first + y1;
96 /* get the first needed row */
97 Row * row = text->GetRowNearY(y_text);
98 /* y_text is now the real beginning of the row */
100 long y = y_text - first;
101 /* y1 is now the real beginning of row on the screen */
103 while (row != 0 && y < y2) {
104 text->GetVisibleRow(y, row, y + first);
109 /* maybe we have to clear the screen at the bottom */
111 owner.getPainter().fillRectangle(0, y,
119 void LyXScreen::DrawOneRow(Row * row, long & y_text)
121 long y = y_text - first;
123 if (y + row->height > 0 && y - row->height <= owner.height()) {
124 /* ok there is something visible */
125 text->GetVisibleRow(y, row, y + first);
127 y_text += row->height;
131 /* draws the screen, starting with textposition y. uses as much already
132 * printed pixels as possible */
133 void LyXScreen::Draw(long y)
135 if (cursor_visible) HideCursor();
138 long old_first = first;
141 /* is any optimiziation possible? */
142 if ((y - old_first) < owner.height()
143 && (old_first - y) < owner.height()) {
144 if (first < old_first) {
145 DrawFromTo(0, old_first - first);
146 XCopyArea (fl_display,
153 owner.height() - old_first + first,
155 owner.ypos() + old_first - first
157 // expose the area drawn
163 owner.height() + old_first - first,
165 XCopyArea (fl_display,
170 owner.ypos() + first - old_first,
172 owner.height() + old_first - first,
175 // expose the area drawn
176 expose(0, owner.height() + old_first - first,
177 owner.workWidth(), first - old_first);
180 /* make a dumb new-draw */
181 DrawFromTo(0, owner.height());
182 expose(0, 0, owner.workWidth(), owner.height());
187 void LyXScreen::ShowCursor()
189 if (!cursor_visible) {
190 Cursor_Shape shape = BAR_SHAPE;
191 if (text->real_current_font.language() !=
192 text->parameters->language_info
193 || text->real_current_font.isVisibleRightToLeft()
194 != text->parameters->language_info->RightToLeft)
195 shape = (text->real_current_font.isVisibleRightToLeft())
196 ? REVERSED_L_SHAPE : L_SHAPE;
197 ShowManualCursor(text->cursor.x, text->cursor.y,
198 text->real_current_font.maxAscent(),
199 text->real_current_font.maxDescent(),
205 /* returns 1 if first has changed, otherwise 0 */
206 int LyXScreen::FitManualCursor(long /*x*/, long y, int asc, int desc)
210 if (y + desc - first >= owner.height())
211 newtop = y - 3 * owner.height() / 4; /* the scroll region must be so big!! */
212 else if (y - asc < first
214 newtop = y - owner.height() / 4;
219 if (newtop != first){
228 void LyXScreen::ShowManualCursor(long x, long y, int asc, int desc,
231 long y1 = max(y - first - asc, 0L);
232 long y2 = min(y - first + desc, long(owner.height()));
234 // Secure against very strange situations
235 if (y2 < y1) y2 = y1;
238 XFreePixmap(fl_display, cursor_pixmap);
244 cursor_pixmap_h = y2 - y1 + 1;
245 cursor_pixmap_y = y1;
253 cursor_pixmap_w = cursor_pixmap_h/3;
256 case REVERSED_L_SHAPE:
257 cursor_pixmap_w = cursor_pixmap_h/3;
258 cursor_pixmap_x = x - cursor_pixmap_w + 1;
263 XCreatePixmap (fl_display,
267 fl_get_visual_depth());
268 XCopyArea (fl_display,
272 owner.xpos() + cursor_pixmap_x,
273 owner.ypos() + cursor_pixmap_y,
277 XDrawLine(fl_display,
288 case REVERSED_L_SHAPE:
289 int rectangle_h = (cursor_pixmap_h+10)/20;
290 XFillRectangle(fl_display,
293 cursor_pixmap_x + owner.xpos(),
294 y2 - rectangle_h + 1 + owner.ypos(),
295 cursor_pixmap_w - 1, rectangle_h);
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));