]> git.lyx.org Git - features.git/blob - src/frontends/xforms/xscreen.C
Really dull and boring header shit
[features.git] / src / frontends / xforms / xscreen.C
1 /**
2  * \file xscreen.C
3  * Read the file COPYING
4  *
5  * \author unknown
6  * \author John Levon 
7  *
8  * Full author contact details are available in file CREDITS
9  */
10
11 #include <config.h>
12
13 #ifdef __GNUG__
14 #pragma implementation
15 #endif
16
17 #include <algorithm>
18 #include <X11/Xlib.h>
19
20 #include "frontends/screen.h"
21 #include "frontends/font_metrics.h"
22 #include "XWorkArea.h"
23 #include "xscreen.h"
24 #include "lyxtext.h"
25 #include "lyxrow.h"
26 #include "Painter.h"
27 #include "WorkArea.h"
28 #include "buffer.h"
29 #include "BufferView.h"
30 #include "insets/insettext.h"
31 #include "ColorHandler.h"
32 #include "language.h"
33 #include "debug.h"
34
35 using std::endl;
36 using std::max;
37 using std::min;
38
39 namespace {
40
41 GC createGC()
42 {
43         XGCValues val;
44         val.foreground = BlackPixel(fl_get_display(),
45                                     DefaultScreen(fl_get_display()));
46
47         val.function = GXcopy;
48         val.graphics_exposures = false;
49         val.line_style = LineSolid;
50         val.line_width = 0;
51         return XCreateGC(fl_get_display(), RootWindow(fl_get_display(), 0),
52                          GCForeground | GCFunction | GCGraphicsExposures
53                          | GCLineWidth | GCLineStyle, &val);
54 }
55
56 } // namespace anon
57
58
59 // Constructor
60 XScreen::XScreen(XWorkArea & o)
61         : LyXScreen(), owner_(o)
62 {
63         // the cursor isnt yet visible
64         cursor_pixmap = 0;
65         cursor_pixmap_x = 0;
66         cursor_pixmap_y = 0;
67         cursor_pixmap_w = 0;
68         cursor_pixmap_h = 0;
69
70         // We need this GC
71         gc_copy = createGC();
72 }
73
74
75 XScreen::~XScreen()
76 {
77         XFreeGC(fl_get_display(), gc_copy);
78 }
79
80
81 void XScreen::setCursorColor()
82 {
83         if (!lyxColorHandler.get()) return;
84
85         GC gc = lyxColorHandler->getGCForeground(LColor::cursor);
86
87         XGCValues val;
88         XGetGCValues(fl_get_display(),
89                      gc, GCForeground, &val);
90         XChangeGC(fl_get_display(), gc_copy, GCForeground, &val);
91 }
92
93
94 void XScreen::showManualCursor(LyXText const * text, int x, int y,
95                                  int asc, int desc, Cursor_Shape shape)
96 {
97         // Update the cursor color.
98         setCursorColor();
99
100         int const y1 = max(y - text->first_y - asc, 0);
101         int const y_tmp = min(y - text->first_y + desc,
102                               static_cast<int>(owner_.workHeight()));
103
104         // Secure against very strange situations
105         int const y2 = max(y_tmp, y1);
106
107         if (cursor_pixmap) {
108                 XFreePixmap(fl_get_display(), cursor_pixmap);
109                 cursor_pixmap = 0;
110         }
111
112         if (y2 > 0 && y1 < int(owner_.workHeight())) {
113                 cursor_pixmap_h = y2 - y1 + 1;
114                 cursor_pixmap_y = y1;
115
116                 switch (shape) {
117                 case BAR_SHAPE:
118                         cursor_pixmap_w = 1;
119                         cursor_pixmap_x = x;
120                         break;
121                 case L_SHAPE:
122                         cursor_pixmap_w = cursor_pixmap_h/3;
123                         cursor_pixmap_x = x;
124                         break;
125                 case REVERSED_L_SHAPE:
126                         cursor_pixmap_w = cursor_pixmap_h/3;
127                         cursor_pixmap_x = x - cursor_pixmap_w + 1;
128                         break;
129                 }
130
131                 cursor_pixmap =
132                         XCreatePixmap (fl_get_display(),
133                                        fl_root,
134                                        cursor_pixmap_w,
135                                        cursor_pixmap_h,
136                                        fl_get_visual_depth());
137                 XCopyArea (fl_get_display(),
138                            owner_.getWin(),
139                            cursor_pixmap,
140                            gc_copy,
141                            owner_.xpos() + cursor_pixmap_x,
142                            owner_.ypos() + cursor_pixmap_y,
143                            cursor_pixmap_w,
144                            cursor_pixmap_h,
145                            0, 0);
146                 XDrawLine(fl_get_display(),
147                           owner_.getWin(),
148                           gc_copy,
149                           x + owner_.xpos(),
150                           y1 + owner_.ypos(),
151                           x + owner_.xpos(),
152                           y2 + owner_.ypos());
153                 switch (shape) {
154                 case BAR_SHAPE:
155                         break;
156                 case L_SHAPE:
157                 case REVERSED_L_SHAPE:
158                         int const rectangle_h = (cursor_pixmap_h + 10) / 20;
159                         XFillRectangle(fl_get_display(),
160                                        owner_.getWin(),
161                                        gc_copy,
162                                        cursor_pixmap_x + owner_.xpos(),
163                                        y2 - rectangle_h + 1 + owner_.ypos(),
164                                        cursor_pixmap_w - 1, rectangle_h);
165                         break;
166                 }
167
168         }
169         cursor_visible_ = true;
170 }
171
172
173 void XScreen::hideCursor()
174 {
175         if (!cursor_visible_) return;
176
177         if (cursor_pixmap) {
178                 XCopyArea (fl_get_display(),
179                            cursor_pixmap,
180                            owner_.getWin(),
181                            gc_copy,
182                            0, 0,
183                            cursor_pixmap_w, cursor_pixmap_h,
184                            cursor_pixmap_x + owner_.xpos(),
185                            cursor_pixmap_y + owner_.ypos());
186         }
187         cursor_visible_ = false;
188 }
189
190
191 void XScreen::expose(int x, int y, int w, int h)
192 {
193         lyxerr[Debug::GUI] << "expose " << w << "x" << h
194                 << "+" << x << "+" << y << endl;
195         XCopyArea(fl_get_display(),
196                   owner_.getPixmap(),
197                   owner_.getWin(),
198                   gc_copy,
199                   x, y, w, h,
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 const 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 }