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