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"
34 val.foreground = BlackPixel(fl_display,
35 DefaultScreen(fl_display));
38 val.graphics_exposures = false;
39 val.line_style = LineSolid;
41 return XCreateGC(fl_display, RootWindow(fl_display, 0),
42 GCForeground | GCFunction | GCGraphicsExposures
43 | GCLineWidth | GCLineStyle , &val);
48 LyXScreen::LyXScreen(WorkArea & o, LyXText * text_ptr)
49 : owner(o), text(text_ptr)
53 /* the cursor isnt yet visible */
54 cursor_visible = false;
55 screen_refresh_y = -1;
68 void LyXScreen::Redraw()
70 DrawFromTo(0, owner.height());
71 screen_refresh_y = -1;
72 expose(0, 0, owner.workWidth(), owner.height());
74 cursor_visible = false;
80 void LyXScreen::expose(int x, int y, int exp_width, int exp_height)
87 exp_width, exp_height,
93 void LyXScreen::DrawFromTo(int y1, int y2)
95 long y_text = first + y1;
97 /* get the first needed row */
98 Row * row = text->GetRowNearY(y_text);
99 /* y_text is now the real beginning of the row */
101 long y = y_text - first;
102 /* y1 is now the real beginning of row on the screen */
104 while (row != 0 && y < y2) {
105 text->GetVisibleRow(y, row, y + first);
110 /* maybe we have to clear the screen at the bottom */
112 owner.getPainter().fillRectangle(0, y,
120 void LyXScreen::DrawOneRow(Row * row, long & y_text)
122 long y = y_text - first;
124 if (y + row->height > 0 && y - row->height <= owner.height()) {
125 /* ok there is something visible */
126 text->GetVisibleRow(y, row, y + first);
128 y_text += row->height;
132 /* draws the screen, starting with textposition y. uses as much already
133 * printed pixels as possible */
134 void LyXScreen::Draw(long y)
136 if (cursor_visible) HideCursor();
139 long old_first = first;
142 /* is any optimiziation possible? */
143 if ((y - old_first) < owner.height()
144 && (old_first - y) < owner.height()) {
145 if (first < old_first) {
146 DrawFromTo(0, old_first - first);
147 XCopyArea (fl_display,
154 owner.height() - old_first + first,
156 owner.ypos() + old_first - first
158 // expose the area drawn
164 owner.height() + old_first - first,
166 XCopyArea (fl_display,
171 owner.ypos() + first - old_first,
173 owner.height() + old_first - first,
176 // expose the area drawn
177 expose(0, owner.height() + old_first - first,
178 owner.workWidth(), first - old_first);
181 /* make a dumb new-draw */
182 DrawFromTo(0, owner.height());
183 expose(0, 0, owner.workWidth(), owner.height());
188 void LyXScreen::ShowCursor()
190 if (!cursor_visible) {
191 Cursor_Shape shape = BAR_SHAPE;
192 if (text->real_current_font.language() !=
193 text->bparams->language_info
194 || text->real_current_font.isVisibleRightToLeft()
195 != text->bparams->language_info->RightToLeft)
196 shape = (text->real_current_font.isVisibleRightToLeft())
197 ? REVERSED_L_SHAPE : L_SHAPE;
198 ShowManualCursor(text->cursor.x, text->cursor.y,
199 lyxfont::maxAscent(text->real_current_font),
200 lyxfont::maxDescent(text->real_current_font),
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));