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