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
5 * Created by: Marc Horowitz <marc@athena.mit.edu>
9 * Copyright (c) 1989 by the Massachusetts Institute of Technology.
10 * For copying and distribution information, see the file
14 #if (!defined(lint) && !defined(SABER))
15 static const char rcsid_xmark_c[] = "$Id$";
18 #include <zephyr/mit-copyright.h>
22 #ifndef X_DISPLAY_MISSING
26 #include <zephyr/zephyr.h>
30 #include "new_string.h"
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;
37 int oldblock[2] = { -1 , -1 };
38 int oldpixel[2] = { -1 , -1 };
39 x_gram *oldgram = NULL;
41 #define xmarkValid() \
43 (STARTBLOCK != -1) && (ENDBLOCK != -1) && \
44 (STARTCHAR != -1) && (ENDCHAR != -1) && \
45 (STARTPIXEL != -1) && (ENDPIXEL != -1))
48 xmarkSetBound(x_gram *gram,
57 XRectangle *ink, *logical;
61 if ((oldblock[which] != markblock[which]) || \
62 (oldpixel[which] != markpixel[which])) { \
63 printf("----- SetBound:\noldblock[%d]=%d, oldpixel[%d]=%d\nmarkblock[%d]=%d, markpixel[%d]=%d\n-----", \
64 which,oldblock[which],which,oldpixel[which], \
65 which,markblock[which],which,markpixel[which]); \
72 if (markgram != gram) {
75 } else if (which < XMARK_TEMP_BOUND) {
76 oldblock[which]=markblock[which];
77 oldpixel[which]=markpixel[which];
80 /* Start at the top, fastforward to first span not too high. */
81 for (i=0,xb=gram->blocks ;
82 (i<gram->numblocks) && (xb->y2 < y) ;
85 /* the point is after the end */
86 if (i==gram->numblocks) {
93 /* is the point before the beginning of the line? */
101 /* is the point in the nether space between this line and the last? */
109 for (yofs=xb->y1;(i<gram->numblocks) && (xb->y1 == yofs);i++,xb++) {
115 if ((x < xofs) || (y < xb->y1)) {
120 #ifdef X_HAVE_UTF8_STRING
121 Xutf8TextPerCharExtents(font, xb->wstr, xb->wlen,
122 NULL, NULL, -1, &num_chars, NULL, NULL);
124 XwcTextPerCharExtents(font, (XChar2b *)xb->wstr, xb->wlen,
125 NULL, NULL, -1, &num_chars, NULL, NULL);
127 ink = malloc(num_chars * sizeof(XRectangle));
128 logical = malloc(num_chars * sizeof(XRectangle));
129 #ifdef X_HAVE_UTF8_STRING
130 Xutf8TextPerCharExtents(font, xb->wstr, xb->wlen,
131 ink, logical, num_chars, &num_chars, NULL, NULL);
133 XwcTextPerCharExtents(font, (XChar2b *)xb->wstr, xb->wlen,
134 ink, logical, num_chars, &num_chars, NULL, NULL);
136 for (i=0;i<num_chars;i++) {
137 if (x <= xofs + logical[i].x + logical[i].width) {
139 markpixel[which]=xofs + logical[i].x - xb->x1;
150 /* The endpoint is after the end of the block if the loop ends */
157 /* needs both bounds to be valid (!= -1) */
164 xmarkSetBound(markgram,x,y,XMARK_TEMP_BOUND);
165 middle=(ENDBLOCK+STARTBLOCK)/2;
167 if (markblock[XMARK_TEMP_BOUND] < middle)
168 return(XMARK_START_BOUND);
169 else if (markblock[XMARK_TEMP_BOUND] > middle)
170 return(XMARK_END_BOUND);
172 middle=(ENDCHAR+STARTCHAR)/2;
173 if (markchar[XMARK_TEMP_BOUND] < middle)
174 return(XMARK_START_BOUND);
176 return(XMARK_END_BOUND);
181 xmarkExpose(Display *dpy,
189 #define swap(x,y) temp=(x); (x)=(y); (y)=temp
192 #define expose (event.xexpose)
194 if ((b1==-1) || (p1==-1) || (b2==-1) || (p2==-1)) return;
196 if ((b1 > b2) || ((b1 == b2) && (p1 > p2))) {
201 #if defined(_IBMR2) && !defined(__GNUC__) && defined(RS6000_OPT_BUG)
202 /* A version of the AIX 3.1 RS/6000 C compiler needs this to prevent
203 a core dump in the loop below. */
211 for (i=b1;i<=b2;i++) {
213 expose.x=gram->blocks[i].x1+p1;
214 expose.y=gram->blocks[i].y1;
216 expose.height=gram->blocks[i].y2-gram->blocks[i].y1;
219 expose.x=gram->blocks[i].x1+p1;
220 expose.y=gram->blocks[i].y1;
221 expose.width=gram->blocks[i].x2-p1;
222 expose.height=gram->blocks[i].y2-gram->blocks[i].y1;
225 expose.x=gram->blocks[i].x1;
226 expose.y=gram->blocks[i].y1;
228 expose.height=gram->blocks[i].y2-gram->blocks[i].y1;
231 expose.x=gram->blocks[i].x1;
232 expose.y=gram->blocks[i].y1;
233 expose.width=gram->blocks[i].x2-gram->blocks[i].x1;
234 expose.height=gram->blocks[i].y2-gram->blocks[i].y1;
239 if (expose.width && expose.height) {
240 printf("---- markExpose:\nb1=%d p1=%d b2=%d p2=%d\n",b1,p1,b2,p2);
241 printf("x=%d y=%d w=%d h=%d\n-----",
242 expose.x,expose.y,expose.width,expose.height);
245 if ((expose.width && expose.height) || (expose.count == 0))
246 XSendEvent(dpy,w,True,ExposureMask,&event);
250 /* Public functions: */
253 xmarkRedraw(Display *dpy,
258 #define ob1 ((unsigned int) oldblock[XMARK_START_BOUND])
259 #define ob2 ((unsigned int) oldblock[XMARK_END_BOUND])
260 #define nb1 ((unsigned int) markblock[XMARK_START_BOUND])
261 #define nb2 ((unsigned int) markblock[XMARK_END_BOUND])
262 #define op1 ((unsigned int) oldpixel[XMARK_START_BOUND])
263 #define op2 ((unsigned int) oldpixel[XMARK_END_BOUND])
264 #define np1 ((unsigned int) markpixel[XMARK_START_BOUND])
265 #define np2 ((unsigned int) markpixel[XMARK_END_BOUND])
267 if (range==XMARK_REDRAW_CURRENT) {
268 if (!markgram) return;
269 xmarkExpose(dpy,w,gram,nb1,np1,nb2,np2);
270 } else if (range==XMARK_REDRAW_OLD) {
271 if (!oldgram) return;
272 xmarkExpose(dpy,w,gram,ob1,op1,ob2,op2);
273 } else if (range==XMARK_REDRAW_START) {
274 if (!markgram) return;
275 xmarkExpose(dpy,w,gram,ob1,op1,nb1,np1);
276 } else if (range==XMARK_REDRAW_END) {
277 if (!markgram) return;
278 xmarkExpose(dpy,w,gram,ob2,op2,nb2,np2);
282 printf("xmarkRedraw: This shouldn't happen!\n");
287 /* needs both bounds to be valid (!= -1) */
291 if (STARTBLOCK > ENDBLOCK)
292 return(XMARK_START_BOUND);
293 else if (STARTBLOCK < ENDBLOCK)
294 return(XMARK_END_BOUND);
296 if (STARTCHAR > ENDCHAR)
297 return(XMARK_START_BOUND);
298 else if (STARTCHAR < ENDCHAR)
299 return(XMARK_END_BOUND);
301 return(XMARK_END_BOUND);
308 oldblock[0]=markblock[0];
309 oldblock[1]=markblock[1];
310 oldpixel[0]=markpixel[0];
311 oldpixel[1]=markpixel[1];
324 xmarkExtendFromFirst(x_gram *gram,
328 if (markgram != gram) {
333 if (STARTBLOCK == -1) {
334 xmarkStart(gram,x,y);
336 return(XMARK_REDRAW_CURRENT);
337 } else if (ENDBLOCK == -1) {
339 return(XMARK_REDRAW_CURRENT);
341 xmarkSetBound(gram,x,y,XMARK_END_BOUND);
342 return(XMARK_REDRAW_END);
347 xmarkExtendFromNearest(x_gram *gram,
353 if (markgram != gram) {
358 if (STARTBLOCK == -1) {
359 xmarkStart(gram,x,y);
361 return(XMARK_REDRAW_CURRENT);
362 } else if (ENDBLOCK == -1) {
364 return(XMARK_REDRAW_CURRENT);
366 xmarkSetBound(gram,x,y,bound=xmarkNearest(x,y));
367 return(bound==XMARK_START_BOUND?XMARK_REDRAW_START:XMARK_REDRAW_END);
377 string text_so_far = string_Copy("");
378 char *text = markgram->text;
379 int startblock,endblock,startchar,endchar;
382 if (xmarkSecond() == XMARK_END_BOUND) {
383 startblock=STARTBLOCK;
394 for (i=startblock; i<=endblock; i++) {
395 if (last_y != -1 && last_y != markgram->blocks[i].y)
396 text_so_far = string_Concat2(text_so_far, "\n");
397 index = markgram->blocks[i].strindex;
398 len = markgram->blocks[i].strlen;
399 if (startblock == endblock)
400 temp = string_CreateFromData(text+index+startchar,
402 else if (i==startblock)
403 temp = string_CreateFromData(text+index+startchar,len-startchar);
404 else if (i==endblock)
405 temp = string_CreateFromData(text+index,endchar);
407 temp = string_CreateFromData(text+index,len);
408 text_so_far = string_Concat2(text_so_far, temp);
410 last_y = markgram->blocks[i].y;
417 #endif /* X_DISPLAY_MISSING */