]> asedeno.scripts.mit.edu Git - 1ts-debian.git/blob - zephyr/zwgc/xmark.c
r4275@bucket (orig r265): kcr | 2008-01-21 02:57:32 -0500
[1ts-debian.git] / zephyr / zwgc / xmark.c
1 /* This file is part of the Project Athena Zephyr Notification System.
2  * It is one of the source files comprising zwgc, the Zephyr WindowGram
3  * client.
4  *
5  *      Created by:     Marc Horowitz <marc@athena.mit.edu>
6  *
7  *      $Id$
8  *
9  *      Copyright (c) 1989 by the Massachusetts Institute of Technology.
10  *      For copying and distribution information, see the file
11  *      "mit-copyright.h".
12  */
13
14 #if (!defined(lint) && !defined(SABER))
15 static const char rcsid_xmark_c[] = "$Id$";
16 #endif
17
18 #include <zephyr/mit-copyright.h>
19
20 #include <sysdep.h>
21
22 #ifndef X_DISPLAY_MISSING
23
24 #include <X11/X.h>
25 #include <X11/Xlib.h>
26 #include "X_gram.h"
27 #include "X_fonts.h"
28 #include "xmark.h"
29 #include "new_string.h"
30
31 int markblock[3] = { -1 , -1 , -1 };
32 int markchar[3] = { -1 , -1 , -1 };
33 int markpixel[3] = { -1 , -1 , -1 };
34 x_gram *markgram = NULL;
35
36 int oldblock[2] = { -1 , -1 };
37 int oldpixel[2] = { -1 , -1 };
38 x_gram *oldgram = NULL;
39
40 #define xmarkValid() \
41    ((markgram) && \
42    (STARTBLOCK != -1) && (ENDBLOCK != -1) && \
43    (STARTCHAR != -1) && (ENDCHAR != -1) && \
44    (STARTPIXEL != -1) && (ENDPIXEL != -1))
45
46 void
47 xmarkSetBound(x_gram *gram,
48               int x,
49               int y,
50               int which)
51 {
52    int i,xofs,yofs;
53    XFontStruct *font;
54    xblock *xb;
55    unsigned char *s;
56
57 #ifdef MARK_DEBUG
58 #define RETURN \
59    if ((oldblock[which] != markblock[which]) || \
60        (oldpixel[which] != markpixel[which])) { \
61       printf("----- SetBound:\noldblock[%d]=%d,   oldpixel[%d]=%d\nmarkblock[%d]=%d, markpixel[%d]=%d\n-----", \
62              which,oldblock[which],which,oldpixel[which], \
63              which,markblock[which],which,markpixel[which]); \
64    } \
65    return
66 #else
67 #define RETURN return
68 #endif
69
70    if (markgram != gram) {
71       xmarkClear();
72       markgram = gram;
73    } else if (which < XMARK_TEMP_BOUND) {
74       oldblock[which]=markblock[which];
75       oldpixel[which]=markpixel[which];
76    }
77
78    /* Start at the top, fastforward to first span not too high. */
79    for (i=0,xb=gram->blocks ;
80         (i<gram->numblocks) && (xb->y2 < y) ;
81         i++,xb++) ;
82
83    /* the point is after the end */
84    if (i==gram->numblocks) {
85       markblock[which]=i;
86       markchar[which]=0;
87       markpixel[which]=0;
88       RETURN;
89    }
90
91    /* is the point before the beginning of the line? */
92    if (x <= xb->x1) {
93       markblock[which]=i;
94       markchar[which]=0;
95       markpixel[which]=0;
96       RETURN;
97    }
98
99    /* is the point in the nether space between this line and the last? */
100    if (y < xb->y1) {
101       markblock[which]=i;
102       markchar[which]=0;
103       markpixel[which]=0;
104       RETURN;
105    }
106
107    for (yofs=xb->y1;(i<gram->numblocks) && (xb->y1 == yofs);i++,xb++) {
108
109       if (x <= xb->x2) {
110          markblock[which]=i;
111
112          xofs=xb->x1;
113          if ((x < xofs) || (y < xb->y1)) {
114             markchar[which]=0;
115             RETURN;
116          }
117          font=get_fontst_from_fid(xb->fid);
118          for (i=0,s=(unsigned char *)((gram->text)+(xb->strindex));
119               xofs<x && i<xb->strlen;
120               i++,s++) {
121              /* if font->per_char is NULL, then we should use min_bounds */
122              short usewidth = font->per_char ? font->per_char[*s - font->min_char_or_byte2].width : font->min_bounds.width;
123            if (x <= (xofs+=usewidth)) {
124               markchar[which]=i;
125               markpixel[which]=xofs - xb->x1 - usewidth;
126               RETURN;
127            }
128          }
129       }
130    }
131
132    /* The endpoint is after the end of the block if the loop ends */
133    markblock[which]=i;
134    markchar[which]=0;
135    markpixel[which]=0;
136    RETURN;
137 }
138
139 /* needs both bounds to be valid (!= -1) */
140 static int
141 xmarkNearest(int x,
142              int y)
143 {
144    int middle;
145
146    xmarkSetBound(markgram,x,y,XMARK_TEMP_BOUND);
147    middle=(ENDBLOCK+STARTBLOCK)/2;
148
149    if (markblock[XMARK_TEMP_BOUND] < middle)
150      return(XMARK_START_BOUND);
151    else if (markblock[XMARK_TEMP_BOUND] > middle)
152      return(XMARK_END_BOUND);
153    else {
154       middle=(ENDCHAR+STARTCHAR)/2;
155       if (markchar[XMARK_TEMP_BOUND] < middle)
156         return(XMARK_START_BOUND);
157       else
158         return(XMARK_END_BOUND);
159    }
160 }
161
162 void
163 xmarkExpose(Display *dpy,
164             Window w,
165             x_gram *gram,
166             unsigned int b1,
167             unsigned int p1,
168             unsigned int b2,
169             unsigned int p2)
170 {
171 #define swap(x,y) temp=(x); (x)=(y); (y)=temp
172    int i,temp;
173    XEvent event;
174 #define expose (event.xexpose)
175
176    if ((b1==-1) || (p1==-1) || (b2==-1) || (p2==-1)) return;
177
178    if ((b1 > b2) || ((b1 == b2) && (p1 > p2))) {
179       swap(b1,b2);
180       swap(p1,p2);
181    }
182
183 #if defined(_IBMR2) && !defined(__GNUC__) && defined(RS6000_OPT_BUG)
184    /* A version of the AIX 3.1 RS/6000 C compiler needs this to prevent
185       a core dump in the loop below. */
186    &b1;
187 #endif
188
189    expose.type=Expose;
190    expose.display=dpy;
191    expose.window=w;
192
193    for (i=b1;i<=b2;i++) {
194       if (b1==b2) {
195          expose.x=gram->blocks[i].x1+p1;
196          expose.y=gram->blocks[i].y1;
197          expose.width=p2-p1;
198          expose.height=gram->blocks[i].y2-gram->blocks[i].y1;
199          expose.count=0;
200       } else if (i==b1) {
201          expose.x=gram->blocks[i].x1+p1;
202          expose.y=gram->blocks[i].y1;
203          expose.width=gram->blocks[i].x2-p1;
204          expose.height=gram->blocks[i].y2-gram->blocks[i].y1;
205          expose.count=b2-i;
206       } else if (i==b2) {
207          expose.x=gram->blocks[i].x1;
208          expose.y=gram->blocks[i].y1;
209          expose.width=p2;
210          expose.height=gram->blocks[i].y2-gram->blocks[i].y1;
211          expose.count=b2-i;
212       } else {
213          expose.x=gram->blocks[i].x1;
214          expose.y=gram->blocks[i].y1;
215          expose.width=gram->blocks[i].x2-gram->blocks[i].x1;
216          expose.height=gram->blocks[i].y2-gram->blocks[i].y1;
217          expose.count=b2-i;
218       }
219
220 #ifdef MARK_DEBUG
221    if (expose.width && expose.height) {
222       printf("---- markExpose:\nb1=%d p1=%d b2=%d p2=%d\n",b1,p1,b2,p2);
223       printf("x=%d y=%d w=%d h=%d\n-----",
224              expose.x,expose.y,expose.width,expose.height);
225    }
226 #endif
227       if ((expose.width && expose.height) || (expose.count == 0))
228         XSendEvent(dpy,w,True,ExposureMask,&event);
229    }
230 }
231
232 /* Public functions: */
233
234 void
235 xmarkRedraw(Display *dpy,
236             Window w,
237             x_gram *gram,
238             int range)
239 {
240 #define ob1 ((unsigned int) oldblock[XMARK_START_BOUND])
241 #define ob2 ((unsigned int) oldblock[XMARK_END_BOUND])
242 #define nb1 ((unsigned int) markblock[XMARK_START_BOUND])
243 #define nb2 ((unsigned int) markblock[XMARK_END_BOUND])
244 #define op1 ((unsigned int) oldpixel[XMARK_START_BOUND])
245 #define op2 ((unsigned int) oldpixel[XMARK_END_BOUND])
246 #define np1 ((unsigned int) markpixel[XMARK_START_BOUND])
247 #define np2 ((unsigned int) markpixel[XMARK_END_BOUND])
248
249    if (range==XMARK_REDRAW_CURRENT) {
250       if (!markgram) return;
251       xmarkExpose(dpy,w,gram,nb1,np1,nb2,np2);
252    } else if (range==XMARK_REDRAW_OLD) {
253       if (!oldgram) return;
254       xmarkExpose(dpy,w,gram,ob1,op1,ob2,op2);
255    } else if (range==XMARK_REDRAW_START) {
256       if (!markgram) return;
257       xmarkExpose(dpy,w,gram,ob1,op1,nb1,np1);
258    } else if (range==XMARK_REDRAW_END) {
259       if (!markgram) return;
260       xmarkExpose(dpy,w,gram,ob2,op2,nb2,np2);
261    }
262 #ifdef DEBUG
263      else {
264         printf("xmarkRedraw:  This shouldn't happen!\n");
265      }
266 #endif
267 }
268
269 /* needs both bounds to be valid (!= -1) */
270 int
271 xmarkSecond(void)
272 {
273    if (STARTBLOCK > ENDBLOCK)
274      return(XMARK_START_BOUND);
275    else if (STARTBLOCK < ENDBLOCK)
276      return(XMARK_END_BOUND);
277    else {
278       if (STARTCHAR > ENDCHAR)
279         return(XMARK_START_BOUND);
280       else if (STARTCHAR < ENDCHAR)
281         return(XMARK_END_BOUND);
282       else
283         return(XMARK_END_BOUND);
284    }
285 }
286
287 void
288 xmarkClear(void)
289 {
290    oldblock[0]=markblock[0];
291    oldblock[1]=markblock[1];
292    oldpixel[0]=markpixel[0];
293    oldpixel[1]=markpixel[1];
294    oldgram=markgram;
295
296    markblock[0] = -1;
297    markblock[1] = -1;
298    markchar[0] = -1;
299    markchar[1] = -1;
300    markpixel[0] = -1;
301    markpixel[1] = -1;
302    markgram=NULL;
303 }
304
305 int
306 xmarkExtendFromFirst(x_gram *gram,
307                      int x,
308                      int y)
309 {
310    if (markgram != gram) {
311       xmarkClear();
312       markgram = gram;
313    }
314
315    if (STARTBLOCK == -1) {
316       xmarkStart(gram,x,y);
317       xmarkEnd(gram,x,y);
318       return(XMARK_REDRAW_CURRENT);
319    } else if (ENDBLOCK == -1) {
320       xmarkEnd(gram,x,y);
321       return(XMARK_REDRAW_CURRENT);
322    } else {
323       xmarkSetBound(gram,x,y,XMARK_END_BOUND);
324       return(XMARK_REDRAW_END);
325    }
326 }
327
328 int
329 xmarkExtendFromNearest(x_gram *gram,
330                        int x,
331                        int y)
332 {
333    int bound;
334
335    if (markgram != gram) {
336       xmarkClear();
337       markgram = gram;
338    }
339
340    if (STARTBLOCK == -1) {
341       xmarkStart(gram,x,y);
342       xmarkEnd(gram,x,y);
343       return(XMARK_REDRAW_CURRENT);
344    } else if (ENDBLOCK == -1) {
345       xmarkEnd(gram,x,y);
346       return(XMARK_REDRAW_CURRENT);
347    } else {
348       xmarkSetBound(gram,x,y,bound=xmarkNearest(x,y));
349       return(bound==XMARK_START_BOUND?XMARK_REDRAW_START:XMARK_REDRAW_END);
350    }
351 }
352
353 char *
354 xmarkGetText(void)
355 {
356     int i, index, len;
357     int last_y = -1;
358     string temp;
359     string text_so_far = string_Copy("");
360     char *text = markgram->text;
361     int startblock,endblock,startchar,endchar;
362
363     if (xmarkValid()) {
364        if (xmarkSecond() == XMARK_END_BOUND) {
365           startblock=STARTBLOCK;
366           endblock=ENDBLOCK;
367           startchar=STARTCHAR;
368           endchar=ENDCHAR;
369        } else {
370           startblock=ENDBLOCK;
371           endblock=STARTBLOCK;
372           startchar=ENDCHAR;
373           endchar=STARTCHAR;
374        }
375
376        for (i=startblock; i<=endblock; i++) {
377           if (last_y != -1 && last_y != markgram->blocks[i].y)
378             text_so_far = string_Concat2(text_so_far, "\n");
379           index = markgram->blocks[i].strindex;
380           len = markgram->blocks[i].strlen;
381           if (startblock == endblock)
382             temp = string_CreateFromData(text+index+startchar,
383                                          endchar-startchar);
384           else if (i==startblock)
385             temp = string_CreateFromData(text+index+startchar,len-startchar);
386           else if (i==endblock)
387             temp = string_CreateFromData(text+index,endchar);
388           else
389             temp = string_CreateFromData(text+index,len);
390           text_so_far = string_Concat2(text_so_far, temp);
391           free(temp);
392           last_y = markgram->blocks[i].y;
393        }
394     }
395
396     return(text_so_far);
397 }
398
399 #endif /* X_DISPLAY_MISSING */
400