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.getFontDirection()
192 != text->parameters->getDocumentDirection())
193 if (text->real_current_font.getFontDirection()
194 == LYX_DIR_LEFT_TO_RIGHT)
197 shape = REVERSED_L_SHAPE;
198 ShowManualCursor(text->cursor.x, text->cursor.y,
199 text->real_current_font.maxAscent(),
200 text->real_current_font.maxDescent(),
206 /* returns 1 if first has changed, otherwise 0 */
207 int LyXScreen::FitManualCursor(long /*x*/, long y, int asc, int desc)
211 if (y + desc - first >= owner.height())
212 newtop = y - 3 * owner.height() / 4; /* the scroll region must be so big!! */
213 else if (y - asc < first
215 newtop = y - owner.height() / 4;
220 if (newtop != first){
229 void LyXScreen::ShowManualCursor(long x, long y, int asc, int desc,
232 long y1 = max(y - first - asc, 0L);
233 long y2 = min(y - first + desc, long(owner.height()));
235 // Secure against very strange situations
236 if (y2 < y1) y2 = y1;
239 XFreePixmap(fl_display, cursor_pixmap);
245 cursor_pixmap_h = y2 - y1 + 1;
246 cursor_pixmap_y = y1;
254 cursor_pixmap_w = cursor_pixmap_h/3;
257 case REVERSED_L_SHAPE:
258 cursor_pixmap_w = cursor_pixmap_h/3;
259 cursor_pixmap_x = x - cursor_pixmap_w + 1;
264 XCreatePixmap (fl_display,
268 fl_get_visual_depth());
269 XCopyArea (fl_display,
273 owner.xpos() + cursor_pixmap_x,
274 owner.ypos() + cursor_pixmap_y,
278 XDrawLine(fl_display,
289 case REVERSED_L_SHAPE:
290 int rectangle_h = (cursor_pixmap_h+10)/20;
291 XFillRectangle(fl_display,
294 cursor_pixmap_x + owner.xpos(),
295 y2 - rectangle_h + 1 + owner.ypos(),
296 cursor_pixmap_w - 1, rectangle_h);
301 cursor_visible = true;
305 void LyXScreen::HideCursor()
307 if (!cursor_visible) return;
310 XCopyArea (fl_display,
315 cursor_pixmap_w, cursor_pixmap_h,
316 cursor_pixmap_x + owner.xpos(),
317 cursor_pixmap_y + owner.ypos());
319 cursor_visible = false;
323 void LyXScreen::CursorToggle()
332 /* returns a new top so that the cursor is visible */
333 long LyXScreen::TopCursorVisible()
338 - text->cursor.row->baseline
339 + text->cursor.row->height
340 - first >= owner.height()) {
341 if (text->cursor.row->height < owner.height()
342 && text->cursor.row->height > owner.height() / 4)
343 newtop = text->cursor.y
344 + text->cursor.row->height
345 - text->cursor.row->baseline - owner.height();
347 newtop = text->cursor.y
348 - 3 * owner.height() / 4; /* the scroll region must be so big!! */
349 } else if (text->cursor.y - text->cursor.row->baseline < first
351 if (text->cursor.row->height < owner.height()
352 && text->cursor.row->height > owner.height() / 4)
353 newtop = text->cursor.y - text->cursor.row->baseline;
355 newtop = text->cursor.y - owner.height() / 4;
367 /* scrolls the screen so that the cursor is visible, if necessary.
368 * returns 1 if a change was made, otherwise 0 */
369 int LyXScreen::FitCursor()
371 /* is a change necessary */
372 long newtop = TopCursorVisible();
373 int result = (newtop != first);
380 void LyXScreen::Update()
382 if (text->status == LyXText::NEED_MORE_REFRESH
383 || screen_refresh_y > -1 ) {
385 if (screen_refresh_y > -1
386 && screen_refresh_y < text->refresh_y)
387 y = screen_refresh_y;
391 if (y < first) y = first;
393 DrawFromTo(y - first, owner.height());
395 text->status = LyXText::UNCHANGED;
396 screen_refresh_y = -1;
398 owner.workWidth(), owner.height() - (y - first));
399 } else if (text->status == LyXText::NEED_VERY_LITTLE_REFRESH) {
400 /* ok I will update the current cursor row */
401 long y = text->refresh_y;
402 DrawOneRow(text->refresh_row, y);
403 text->status = LyXText::UNCHANGED;
404 expose(0, text->refresh_y - first,
405 owner.workWidth(), text->refresh_row->height);
410 void LyXScreen::SmallUpdate()
412 if (text->status == LyXText::NEED_MORE_REFRESH) {
413 /* ok I will update till the current cursor row */
414 Row * row = text->refresh_row;
415 long y = text->refresh_y;
418 if (y > text->cursor.y) {
424 && row != text->cursor.row
425 && y < first + owner.height()) {
431 screen_refresh_y = y;
432 screen_refresh_row = row->next;
433 text->status = LyXText::UNCHANGED;
434 // Is the right regin exposed?
435 expose(0, y2 - first,
436 owner.workWidth(), y - y2);
437 } else if (text->status == LyXText::NEED_VERY_LITTLE_REFRESH) {
438 /* ok I will update the current cursor row */
439 long y = text->refresh_y;
440 DrawOneRow(text->refresh_row, y);
441 text->status = LyXText::UNCHANGED;
442 expose(0, text->refresh_y - first,
443 owner.workWidth(), text->refresh_row->height);
448 void LyXScreen::ToggleSelection(bool kill_selection)
450 /* only if there is a selection */
451 if (!text->selection) return;
453 long top = text->sel_start_cursor.y
454 - text->sel_start_cursor.row->baseline;
455 long bottom = text->sel_end_cursor.y
456 - text->sel_end_cursor.row->baseline
457 + text->sel_end_cursor.row->height;
460 top = max(top, first);
462 bottom = max(bottom, first);
464 if (bottom > first + owner.height())
465 bottom = first + owner.height();
466 if (top > first + owner.height())
467 top = first + owner.height();
471 DrawFromTo(top - first, bottom - first);
472 expose(0, top - first,
474 bottom - first - (top - first));
478 void LyXScreen::ToggleToggle()
480 if (text->toggle_cursor.par == text->toggle_end_cursor.par
481 && text->toggle_cursor.pos == text->toggle_end_cursor.pos)
484 long top = text->toggle_cursor.y
485 - text->toggle_cursor.row->baseline;
486 long bottom = text->toggle_end_cursor.y
487 - text->toggle_end_cursor.row->baseline
488 + text->toggle_end_cursor.row->height;
492 if (bottom - first < 0)
495 if (bottom - first > owner.height())
496 bottom = first + owner.height();
497 if (top - first > owner.height())
498 top = first + owner.height();
500 DrawFromTo(top - first, bottom - first);
501 expose(0, top - first, owner.workWidth(),
502 bottom - first - (top - first));