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