]> git.lyx.org Git - lyx.git/blob - src/frontends/xforms/xscreen.C
fix tooltips in toolbar
[lyx.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 #include "debug.h"
33
34 using std::endl;
35 using std::max;
36 using std::min;
37
38 namespace {
39
40 GC createGC()
41 {
42         XGCValues val;
43         val.foreground = BlackPixel(fl_get_display(),
44                                     DefaultScreen(fl_get_display()));
45
46         val.function = GXcopy;
47         val.graphics_exposures = false;
48         val.line_style = LineSolid;
49         val.line_width = 0;
50         return XCreateGC(fl_get_display(), RootWindow(fl_get_display(), 0),
51                          GCForeground | GCFunction | GCGraphicsExposures
52                          | GCLineWidth | GCLineStyle , &val);
53 }
54
55 } // namespace anon
56
57
58 // Constructor
59 XScreen::XScreen(XWorkArea & o)
60         : LyXScreen(), owner_(o)
61 {
62         // the cursor isnt yet visible
63         cursor_pixmap = 0;
64         cursor_pixmap_x = 0;
65         cursor_pixmap_y = 0;
66         cursor_pixmap_w = 0;
67         cursor_pixmap_h = 0;
68
69         // We need this GC
70         gc_copy = createGC();
71 }
72
73
74 XScreen::~XScreen()
75 {
76         XFreeGC(fl_get_display(), gc_copy);
77 }
78
79
80 void XScreen::setCursorColor()
81 {
82         if (!lyxColorHandler.get()) return;
83
84         GC gc = lyxColorHandler->getGCForeground(LColor::cursor);
85
86         XGCValues val;
87         XGetGCValues(fl_get_display(),
88                      gc, GCForeground, &val);
89         XChangeGC(fl_get_display(), gc_copy, GCForeground, &val);
90 }
91
92
93 void XScreen::showManualCursor(LyXText const * text, int x, int y,
94                                  int asc, int desc, Cursor_Shape shape)
95 {
96         // Update the cursor color.
97         setCursorColor();
98
99         int const y1 = max(y - text->first_y - asc, 0);
100         int const y_tmp = min(y - text->first_y + desc,
101                               static_cast<int>(owner_.workHeight()));
102
103         // Secure against very strange situations
104         int const y2 = max(y_tmp, y1);
105
106         if (cursor_pixmap) {
107                 XFreePixmap(fl_get_display(), cursor_pixmap);
108                 cursor_pixmap = 0;
109         }
110
111         if (y2 > 0 && y1 < int(owner_.workHeight())) {
112                 cursor_pixmap_h = y2 - y1 + 1;
113                 cursor_pixmap_y = y1;
114
115                 switch (shape) {
116                 case BAR_SHAPE:
117                         cursor_pixmap_w = 1;
118                         cursor_pixmap_x = x;
119                         break;
120                 case L_SHAPE:
121                         cursor_pixmap_w = cursor_pixmap_h/3;
122                         cursor_pixmap_x = x;
123                         break;
124                 case REVERSED_L_SHAPE:
125                         cursor_pixmap_w = cursor_pixmap_h/3;
126                         cursor_pixmap_x = x - cursor_pixmap_w + 1;
127                         break;
128                 }
129
130                 cursor_pixmap =
131                         XCreatePixmap (fl_get_display(),
132                                        fl_root,
133                                        cursor_pixmap_w,
134                                        cursor_pixmap_h,
135                                        fl_get_visual_depth());
136                 XCopyArea (fl_get_display(),
137                            owner_.getWin(),
138                            cursor_pixmap,
139                            gc_copy,
140                            owner_.xpos() + cursor_pixmap_x,
141                            owner_.ypos() + cursor_pixmap_y,
142                            cursor_pixmap_w,
143                            cursor_pixmap_h,
144                            0, 0);
145                 XDrawLine(fl_get_display(),
146                           owner_.getWin(),
147                           gc_copy,
148                           x + owner_.xpos(),
149                           y1 + owner_.ypos(),
150                           x + owner_.xpos(),
151                           y2 + owner_.ypos());
152                 switch (shape) {
153                 case BAR_SHAPE:
154                         break;
155                 case L_SHAPE:
156                 case REVERSED_L_SHAPE:
157                         int const rectangle_h = (cursor_pixmap_h + 10) / 20;
158                         XFillRectangle(fl_get_display(),
159                                        owner_.getWin(),
160                                        gc_copy,
161                                        cursor_pixmap_x + owner_.xpos(),
162                                        y2 - rectangle_h + 1 + owner_.ypos(),
163                                        cursor_pixmap_w - 1, rectangle_h);
164                         break;
165                 }
166
167         }
168         cursor_visible_ = true;
169 }
170
171
172 void XScreen::hideCursor()
173 {
174         if (!cursor_visible_) return;
175
176         if (cursor_pixmap) {
177                 XCopyArea (fl_get_display(),
178                            cursor_pixmap,
179                            owner_.getWin(),
180                            gc_copy,
181                            0, 0,
182                            cursor_pixmap_w, cursor_pixmap_h,
183                            cursor_pixmap_x + owner_.xpos(),
184                            cursor_pixmap_y + owner_.ypos());
185         }
186         cursor_visible_ = false;
187 }
188
189
190 void XScreen::expose(int x, int y, int w, int h)
191 {
192         lyxerr[Debug::GUI] << "expose " << w << "x" << h
193                 << "+" << x << "+" << y << endl;
194         XCopyArea(fl_get_display(),
195                   owner_.getPixmap(),
196                   owner_.getWin(),
197                   gc_copy,
198                   x, y, w, h,
199                   x + owner_.xpos(),
200                   y + owner_.ypos());
201 }
202
203
204 void XScreen::draw(LyXText * text, BufferView * bv, unsigned int y)
205 {
206         if (cursor_visible_) hideCursor();
207
208         int const old_first = text->first_y;
209         bool const internal = (text == bv->text);
210         text->first_y = y;
211
212         // is any optimization possible?
213         if ((y - old_first) < owner_.workHeight()
214             && (old_first - y) < owner_.workHeight())
215         {
216                 if (text->first_y < old_first) {
217                         drawFromTo(text, bv, 0,
218                                    old_first - text->first_y, 0, 0, internal);
219                         XCopyArea (fl_get_display(),
220                                    owner_.getWin(),
221                                    owner_.getWin(),
222                                    gc_copy,
223                                    owner_.xpos(),
224                                    owner_.ypos(),
225                                    owner_.workWidth(),
226                                    owner_.workHeight() - old_first + text->first_y,
227                                    owner_.xpos(),
228                                    owner_.ypos() + old_first - text->first_y
229                                 );
230                         // expose the area drawn
231                         expose(0, 0,
232                                owner_.workWidth(),
233                                old_first - text->first_y);
234                 } else  {
235                         drawFromTo(text, bv,
236                                    owner_.workHeight() + old_first - text->first_y,
237                                    owner_.workHeight(), 0, 0, internal);
238                         XCopyArea (fl_get_display(),
239                                    owner_.getWin(),
240                                    owner_.getWin(),
241                                    gc_copy,
242                                    owner_.xpos(),
243                                    owner_.ypos() + text->first_y - old_first,
244                                    owner_.workWidth(),
245                                    owner_.workHeight() + old_first - text->first_y,
246                                    owner_.xpos(),
247                                    owner_.ypos());
248                         // expose the area drawn
249                         expose(0, owner_.workHeight() + old_first - text->first_y,
250                                owner_.workWidth(), text->first_y - old_first);
251                 }
252         } else {
253                 // make a dumb new-draw
254                 drawFromTo(text, bv, 0, owner_.workHeight(), 0, 0, internal);
255                 expose(0, 0, owner_.workWidth(), owner_.workHeight());
256         }
257
258         XSync(fl_get_display(), 0);
259 }