More debianization
[erwise] / Xl / XlWindow.c
1 /*
2  * XlWindow.c --
3  *
4  * Author: Teemu Rantanen <tvr@cs.hut.fi>
5  * Copyright (c) 1992 Teemu Rantanen
6  *                    All rights reserved
7  *
8  * Created: Tue Mar  3 02:59:10 1992 tvr
9  * Last modified: Tue Apr 21 00:34:09 1992 tvr
10  *
11  */
12
13 #include <stdio.h>
14 #include <sys/types.h>
15
16 #include <X11/Xlib.h>
17
18 #include "HTAnchor.h"
19 #include "HTStyle.h"
20 #include "../HText/HText.h"
21
22 #include "Xl.h"
23 #include "XlStyle.h"
24 #include "XlTypes.h"
25 #include "XlFormatText.h"
26
27 /*
28  * Make cursor positioning more intelligent
29  */
30 #define Y_MULTIPLIER 50
31
32 /*
33  * Is there spaces at the end of data ?
34  */
35 int xl_space_index(data, length)
36 char *data;
37 int length;
38 {
39     int i;
40
41     if (!data)
42         return -1;
43
44     for (i = 0; i < length; i++)
45         if (*data++ == ' ')
46             return i;
47
48     return length;
49 }
50
51
52 /*
53  * Draw one Xl object to screen
54  */
55 void xl_draw_object(htext, object)
56 HText_t *htext;
57 HTextObject_t *object;
58 {
59     /*
60      * If this object is cursor, clear area or else partial updating
61      * does not work correctly
62      */
63
64     if (object == htext->cursor) {
65         XClearArea(htext->xl_global->dpy,
66                    htext->xl_global->window,
67                    object->x - htext->xl_global->x,
68                    object->y - htext->xl_global->y,
69                    object->width,
70                    object->height,
71                    False);
72     }
73     XDrawString(htext->xl_global->dpy,
74                 htext->xl_global->window,
75                 object->xl_data->gc,
76                 object->x - htext->xl_global->x,
77                 object->y - htext->xl_global->y +
78                 object->xl_data->style->fontinfo->ascent,
79                 object->data,
80                 object->length);
81
82     /*
83      * Draw underline for anchors
84      */
85     if (object->anchor) {
86         int y;
87         int x;
88         int width;
89
90         y = object->y + object->xl_data->style->fontinfo->ascent +
91             object->xl_data->style->fontinfo->descent -
92             htext->xl_global->y;
93
94         x = object->x - htext->xl_global->x;
95
96         width = object->width;
97
98         if (object->next && (object->anchor == object->next->anchor) &&
99             (object->y == object->next->y)) {
100             width += xl_wordgap(object);
101         }
102         XDrawLine(htext->xl_global->dpy,
103                   htext->xl_global->window,
104                   object->xl_data->gc,
105                   x, y,
106                   x + width, y);
107     }
108     /*
109      * Is this object cursor ?
110      */
111     if (object == htext->cursor) {
112         int cursorwidth;
113
114         /*
115          * If cursor is on raw mode, get rid of spaces at the end
116          */
117         if (xl_object_mode(object) & STYLE_RAW) {
118             int i = xl_space_index(object->data, object->length);
119
120             if (i >= 0) {
121                 cursorwidth = (int) XTextWidth(object->xl_data->style->fontinfo,
122                                                object->data,
123                                                i);
124             } else {
125                 cursorwidth = object->width;
126             }
127         } else {
128             cursorwidth = object->width;
129         }
130
131         XDrawRectangle(htext->xl_global->dpy,
132                        htext->xl_global->window,
133                        htext->xl_global->xorgc,
134                        object->x - htext->xl_global->x,
135                        object->y - htext->xl_global->y,
136                        cursorwidth - 1,
137                        object->height - 1);
138     }
139 }
140
141
142 /*
143  * Check is object is on wanted region. Return 0 if point is on region.
144  * Otherwise return distance. NOTE. y-distance is multiplied by a big
145  * number because this way cursor positioning works more intelligently than
146  * without it.
147  */
148 int xl_object_on_region(htext, object, x, y, w, h)
149 HText_t *htext;
150 HTextObject_t *object;
151 int x, y;
152 int w, h;
153 {
154     int r = 0;
155
156     /*
157      * Change real coordinates to virtual coordinates
158      */
159     x += htext->xl_global->x;
160     y += htext->xl_global->y;
161
162     if ((object->y + object->height) < y)
163         r += (y - (object->y + object->height)) * Y_MULTIPLIER;
164
165     if (object->y > (y + h))
166         r += (object->y - (y + h)) * Y_MULTIPLIER;
167
168     if ((object->x + object->width) < x)
169         r += x - (object->x + object->width);
170
171     if (object->x > (x + w))
172         r += object->x - (x + w);
173
174     return r;
175 }
176
177
178
179 /*
180  *  Redraw region of the window. Draw all objects (or parts of the objects)
181  *  on redraw region.
182  */
183 void XlRedraw(windowx, windowy, width, height, htext)
184 int windowx, windowy;
185 int width, height;
186 HText_t *htext;
187 {
188     HTextObject_t *p;
189
190     /*
191      * This is stupid. This has to be written again
192      */
193
194     p = htext->first;
195
196     while (p) {
197         if (xl_object_on_region(htext, p, windowx, windowy, width, height) == 0) {
198             xl_draw_object(htext, p);
199         }
200         p = p->next;
201     }
202 }
203
204
205 /*
206  *  Move window to other coordinates. Xl can optimize window moving by using
207  *  regioncopy and updating only parts of display.
208  */
209 void XlMoveWindow(newvx, newvy, htext)
210 int newvx, newvy;
211 HText_t *htext;
212 {
213     XWindowAttributes a;
214
215     long deltax, deltay;
216
217     /*
218      * Need to know window dimensions
219      */
220     XGetWindowAttributes(htext->xl_global->dpy,
221                          htext->xl_global->window,
222                          &a);
223
224     /*
225      * How much to move
226      */
227     deltax = newvx - htext->xl_global->x;
228     deltay = newvy - htext->xl_global->y;
229
230     /*
231      * Can move be optimized ?
232      */
233     if ((abs(deltax) < a.width) && (abs(deltay) < a.height)) {
234         XCopyArea(htext->xl_global->dpy,
235                   htext->xl_global->window,
236                   htext->xl_global->window,
237                   htext->xl_global->gcs[0],     /* dummy GC */
238                   deltax < 0 ? 0 : deltax,
239                   deltay < 0 ? 0 : deltay,
240                   a.width - abs(deltax),
241                   a.height - abs(deltay),
242                   deltax < 0 ? -deltax : 0,
243                   deltay < 0 ? -deltay : 0);
244     }
245     /*
246      * Set new corner coordinates
247      */
248
249     XlSetPageCoordinates(newvx, newvy, htext);
250
251     /*
252      * Clear borders to be updated again
253      */
254     if (deltax != 0) {
255         XClearArea(htext->xl_global->dpy,
256                    htext->xl_global->window,
257                    deltax > 0 ? a.width - deltax : 0,
258                    0,
259                    abs(deltax),
260                    a.height,
261                    True);
262     }
263     if (deltay != 0) {
264         XClearArea(htext->xl_global->dpy,
265                    htext->xl_global->window,
266                    0,
267                    deltay > 0 ? a.height - deltay : 0,
268                    a.width,
269                    abs(deltay),
270                    True);
271     }
272 }
273
274
275
276 /*
277  * Clear window
278  */
279 void XlClearWindow(width, height, htext)
280 int width;
281 int height;
282 HText_t *htext;
283 {
284     XClearArea(htext->xl_global->dpy,
285                htext->xl_global->window,
286                0, 0, width, height, True);
287 }
288
289
290 /*
291  * Setup cursorposition on a page
292  */
293 void XlSetCursor(htext, object)
294 HText_t *htext;
295 HTextObject_t *object;
296 {
297     XWindowAttributes a;
298     HTextObject_t *old_object;
299
300
301     if (!htext || !htext->xl_global ||
302         !htext->xl_global->dpy ||
303         !htext->xl_global->window)
304         return;
305
306     /*
307      * Need to know window dimensions
308      */
309     XGetWindowAttributes(htext->xl_global->dpy,
310                          htext->xl_global->window,
311                          &a);
312
313     /*
314      * Clear old cursor
315      */
316     if (htext->cursor) {
317         if (xl_object_on_region(htext, htext->cursor, 0, 0,
318                                 a.width, a.height) == 0) {
319             XClearArea(htext->xl_global->dpy,
320                        htext->xl_global->window,
321                        htext->cursor->x - htext->xl_global->x,
322                        htext->cursor->y - htext->xl_global->y,
323                        htext->cursor->width,
324                        htext->cursor->height,
325                        False);
326
327             /*
328              * When drawing old area, must clear htext->cursor for a while
329              */
330             old_object = htext->cursor;
331
332             htext->cursor = 0;
333
334             xl_draw_object(htext, old_object);
335         }
336     }
337     old_object = object;
338     htext->cursor = object;
339
340     if (htext->cursor) {
341         if (xl_object_on_region(htext, object, 0, 0, a.width, a.height) == 0) {
342 #if 0
343             /*
344              * This is moved to draw object. partial drawing updating of
345              * cursor causes otherwise problems
346              */
347             XClearArea(htext->xl_global->dpy,
348                        htext->xl_global->window,
349                        htext->cursor->x - htext->xl_global->x,
350                        htext->cursor->y - htext->xl_global->y,
351                        htext->cursor->width,
352                        htext->cursor->height,
353                        False);
354 #endif
355             xl_draw_object(htext, htext->cursor);
356         }
357     }
358 }