]> git.lyx.org Git - features.git/blob - src/frontends/xforms/xscreen.C
*duck*
[features.git] / src / frontends / xforms / xscreen.C
1 /**
2  * \file xscreen.C
3  * Copyright 1995-2002 the LyX Team
4  * Read the file COPYING
5  *
6  * \author unknown
7  * \author John Levon <moz@compsoc.man.ac.uk>
8  */
9
10 #include <config.h>
11
12 #ifdef __GNUG__
13 #pragma implementation
14 #endif
15
16 #include <algorithm>
17 #include <X11/Xlib.h>
18
19 #include "frontends/screen.h"
20 #include "frontends/font_metrics.h"
21 #include "XWorkArea.h"
22 #include "xscreen.h"
23 #include "lyxtext.h"
24 #include "lyxrow.h"
25 #include "Painter.h"
26 #include "WorkArea.h"
27 #include "buffer.h"
28 #include "BufferView.h"
29 #include "insets/insettext.h"
30 #include "ColorHandler.h"
31 #include "language.h"
32
33 using std::max;
34 using std::min;
35
36 namespace {
37
38 GC createGC()
39 {
40         XGCValues val;
41         val.foreground = BlackPixel(fl_get_display(), 
42                                     DefaultScreen(fl_get_display()));
43         
44         val.function = GXcopy;
45         val.graphics_exposures = false;
46         val.line_style = LineSolid;
47         val.line_width = 0;
48         return XCreateGC(fl_get_display(), RootWindow(fl_get_display(), 0), 
49                          GCForeground | GCFunction | GCGraphicsExposures
50                          | GCLineWidth | GCLineStyle , &val);
51 }
52
53 } // namespace anon
54
55
56 // Constructor
57 XScreen::XScreen(XWorkArea & o)
58         : LyXScreen(), owner_(o)
59 {
60         // the cursor isnt yet visible
61         cursor_pixmap = 0;
62         cursor_pixmap_x = 0;
63         cursor_pixmap_y = 0;
64         cursor_pixmap_w = 0;
65         cursor_pixmap_h = 0;
66
67         // We need this GC
68         gc_copy = createGC();
69 }
70
71
72 XScreen::~XScreen()
73 {
74         XFreeGC(fl_get_display(), gc_copy);
75 }
76
77  
78 void XScreen::setCursorColor() 
79 {
80         if (!lyxColorHandler.get()) return;
81
82         GC gc = lyxColorHandler->getGCForeground(LColor::cursor);
83         
84         XGCValues val;
85         XGetGCValues(fl_get_display(),
86                      gc, GCForeground, &val);
87         XChangeGC(fl_get_display(), gc_copy, GCForeground, &val);
88 }
89
90
91 void XScreen::showManualCursor(LyXText const * text, int x, int y,
92                                  int asc, int desc, Cursor_Shape shape)
93 {
94         // Update the cursor color.
95         setCursorColor();
96         
97         int const y1 = max(y - text->first_y - asc, 0);
98         int const y_tmp = min(y - text->first_y + desc,
99                               static_cast<int>(owner_.workHeight()));
100
101         // Secure against very strange situations
102         int const y2 = max(y_tmp, y1);
103         
104         if (cursor_pixmap) {
105                 XFreePixmap(fl_get_display(), cursor_pixmap);
106                 cursor_pixmap = 0;
107         }
108
109         if (y2 > 0 && y1 < int(owner_.workHeight())) {
110                 cursor_pixmap_h = y2 - y1 + 1;
111                 cursor_pixmap_y = y1;
112
113                 switch (shape) {
114                 case BAR_SHAPE:
115                         cursor_pixmap_w = 1;
116                         cursor_pixmap_x = x;
117                         break;
118                 case L_SHAPE:
119                         cursor_pixmap_w = cursor_pixmap_h/3;
120                         cursor_pixmap_x = x;
121                         break;
122                 case REVERSED_L_SHAPE:
123                         cursor_pixmap_w = cursor_pixmap_h/3;
124                         cursor_pixmap_x = x - cursor_pixmap_w + 1;
125                         break;
126                 }
127
128                 cursor_pixmap = 
129                         XCreatePixmap (fl_get_display(),
130                                        fl_root,
131                                        cursor_pixmap_w,
132                                        cursor_pixmap_h,
133                                        fl_get_visual_depth());
134                 XCopyArea (fl_get_display(),
135                            owner_.getWin(),
136                            cursor_pixmap,
137                            gc_copy,
138                            owner_.xpos() + cursor_pixmap_x,
139                            owner_.ypos() + cursor_pixmap_y,
140                            cursor_pixmap_w,
141                            cursor_pixmap_h,
142                            0, 0);
143                 XDrawLine(fl_get_display(),
144                           owner_.getWin(),
145                           gc_copy,
146                           x + owner_.xpos(),
147                           y1 + owner_.ypos(),
148                           x + owner_.xpos(),
149                           y2 + owner_.ypos());
150                 switch (shape) {
151                 case BAR_SHAPE:
152                         break;
153                 case L_SHAPE:
154                 case REVERSED_L_SHAPE:
155                         int const rectangle_h = (cursor_pixmap_h + 10) / 20;
156                         XFillRectangle(fl_get_display(),
157                                        owner_.getWin(),
158                                        gc_copy,
159                                        cursor_pixmap_x + owner_.xpos(),
160                                        y2 - rectangle_h + 1 + owner_.ypos(),
161                                        cursor_pixmap_w - 1, rectangle_h);
162                         break;
163                 }
164
165         }
166         cursor_visible_ = true;
167 }
168
169
170 void XScreen::hideCursor()
171 {
172         if (!cursor_visible_) return;
173
174         if (cursor_pixmap) {
175                 XCopyArea (fl_get_display(), 
176                            cursor_pixmap,
177                            owner_.getWin(),
178                            gc_copy,
179                            0, 0, 
180                            cursor_pixmap_w, cursor_pixmap_h,
181                            cursor_pixmap_x + owner_.xpos(),
182                            cursor_pixmap_y + owner_.ypos());
183         }
184         cursor_visible_ = false;
185 }
186
187  
188 void XScreen::expose(int x, int y, int exp_width, int exp_height)
189 {
190         // FIXME: here we should definitely NOT do this.
191         // we need to generate an expose event for the workarea
192         // and then copy from the pixmap to the screen. This
193         // is the Sane Way (tm) 
194         XCopyArea(fl_get_display(),
195                   owner_.getPixmap(),
196                   owner_.getWin(),
197                   gc_copy,
198                   x, y,
199                   exp_width, exp_height,
200                   x + owner_.xpos(),
201                   y + owner_.ypos());
202 }
203
204
205 void XScreen::draw(LyXText * text, BufferView * bv, unsigned int y)
206 {
207         if (cursor_visible_) hideCursor();
208
209         int const old_first = text->first_y;
210         bool internal = (text == bv->text);
211         text->first_y = y;
212
213         // is any optimization possible?
214         if ((y - old_first) < owner_.workHeight()
215             && (old_first - y) < owner_.workHeight())
216         {
217                 if (text->first_y < old_first) {
218                         drawFromTo(text, bv, 0,
219                                    old_first - text->first_y, 0, 0, internal);
220                         XCopyArea (fl_get_display(),
221                                    owner_.getWin(),
222                                    owner_.getWin(),
223                                    gc_copy,
224                                    owner_.xpos(),
225                                    owner_.ypos(),
226                                    owner_.workWidth(),
227                                    owner_.workHeight() - old_first + text->first_y,
228                                    owner_.xpos(),
229                                    owner_.ypos() + old_first - text->first_y
230                                 );
231                         // expose the area drawn
232                         expose(0, 0,
233                                owner_.workWidth(),
234                                old_first - text->first_y);
235                 } else  {
236                         drawFromTo(text, bv,
237                                    owner_.workHeight() + old_first - text->first_y,
238                                    owner_.workHeight(), 0, 0, internal);
239                         XCopyArea (fl_get_display(),
240                                    owner_.getWin(),
241                                    owner_.getWin(),
242                                    gc_copy,
243                                    owner_.xpos(),
244                                    owner_.ypos() + text->first_y - old_first,
245                                    owner_.workWidth(),
246                                    owner_.workHeight() + old_first - text->first_y,
247                                    owner_.xpos(),
248                                    owner_.ypos());
249                         // expose the area drawn
250                         expose(0, owner_.workHeight() + old_first - text->first_y,
251                                owner_.workWidth(), text->first_y - old_first);
252                 }
253         } else {
254                 // make a dumb new-draw 
255                 drawFromTo(text, bv, 0, owner_.workHeight(), 0, 0, internal);
256                 expose(0, 0, owner_.workWidth(), owner_.workHeight());
257         }
258
259         XSync(fl_get_display(), 0);
260 }