diff options
author | Marc Horowitz <marc@mit.edu> | 1989-11-01 20:02:01 +0000 |
---|---|---|
committer | Marc Horowitz <marc@mit.edu> | 1989-11-01 20:02:01 +0000 |
commit | d13d8a046838ce3d0e2643bb5b49f2ff77d679ca (patch) | |
tree | 05737bc11e3461836ce817939b9129ed58545ac7 /zwgc/xmark.c | |
parent | fd994e4099ad66fb3bf26cd636ca5d5cae72da68 (diff) |
Initial revision
Diffstat (limited to 'zwgc/xmark.c')
-rw-r--r-- | zwgc/xmark.c | 357 |
1 files changed, 357 insertions, 0 deletions
diff --git a/zwgc/xmark.c b/zwgc/xmark.c new file mode 100644 index 0000000..15d4be4 --- /dev/null +++ b/zwgc/xmark.c @@ -0,0 +1,357 @@ +#include <X11/X.h> +#include <X11/Xlib.h> +#include "X_gram.h" +#include "X_fonts.h" +#include "xmark.h" +#include "new_string.h" +#include <stdio.h> + +int markblock[3] = { -1 , -1 , -1 }; +int markchar[3] = { -1 , -1 , -1 }; +int markpixel[3] = { -1 , -1 , -1 }; +x_gram *markgram = NULL; + +int oldblock[2] = { -1 , -1 }; +int oldpixel[2] = { -1 , -1 }; +x_gram *oldgram = NULL; + +#define xmarkValid() \ + ((markgram) && \ + (STARTBLOCK != -1) && (ENDBLOCK != -1) && \ + (STARTCHAR != -1) && (ENDCHAR != -1) && \ + (STARTPIXEL != -1) && (ENDPIXEL != -1)) + +void xmarkSetBound(gram,x,y,which) + x_gram *gram; + int x,y; + int which; +{ + int i,xofs,yofs; + XFontStruct *font; + xblock *xb; + char *s; + +#ifdef MARK_DEBUG +#define RETURN \ + if ((oldblock[which] != markblock[which]) || \ + (oldpixel[which] != markpixel[which])) { \ + printf("----- SetBound:\noldblock[%d]=%d, oldpixel[%d]=%d\nmarkblock[%d]=%d, markpixel[%d]=%d\n-----", \ + which,oldblock[which],which,oldpixel[which], \ + which,markblock[which],which,markpixel[which]); \ + } \ + return +#else +#define RETURN return +#endif + + if (markgram != gram) { + xmarkClear(); + markgram = gram; + } else if (which < XMARK_TEMP_BOUND) { + oldblock[which]=markblock[which]; + oldpixel[which]=markpixel[which]; + } + + /* Start at the top, fastforward to first span not too high. */ + for (i=0,xb=gram->blocks ; + (i<gram->numblocks) && (xb->y2 < y) ; + i++,xb++) ; + + /* the point is after the end */ + if (i==gram->numblocks) { + markblock[which]=i; + markchar[which]=0; + markpixel[which]=0; + RETURN; + } + + /* is the point before the beginning of the line? */ + if (x <= xb->x1) { + markblock[which]=i; + markchar[which]=0; + markpixel[which]=0; + RETURN; + } + + /* is the point in the nether space between this line and the last? */ + if (y < xb->y1) { + markblock[which]=i; + markchar[which]=0; + markpixel[which]=0; + RETURN; + } + + for (yofs=xb->y1;(i<gram->numblocks) && (xb->y1 == yofs);i++,xb++) { + + if (x <= xb->x2) { + markblock[which]=i; + + xofs=xb->x1; + if ((x < xofs) || (y < xb->y1)) { + markchar[which]=0; + RETURN; + } + font=get_fontst_from_fid(xb->fid); + for (i=0,s=((gram->text)+(xb->strindex)); + xofs<x && i<xb->strlen; + i++,s++) + if (x<=(xofs+=font->per_char[*s - font->min_char_or_byte2].width)) { + markchar[which]=i; + markpixel[which]=xofs-xb->x1- + font->per_char[*s - font->min_char_or_byte2].width; + RETURN; + } + } + } + + /* The endpoint is after the end of the block if the loop ends */ + markblock[which]=i; + markchar[which]=0; + markpixel[which]=0; + RETURN; +} + +/* needs both bounds to be valid (!= -1) */ +static int xmarkNearest(x,y) + int x,y; +{ + int middle; + + xmarkSetBound(markgram,x,y,XMARK_TEMP_BOUND); + middle=(ENDBLOCK+STARTBLOCK)/2; + + if (markblock[XMARK_TEMP_BOUND] < middle) + return(XMARK_START_BOUND); + else if (markblock[XMARK_TEMP_BOUND] > middle) + return(XMARK_END_BOUND); + else { + middle=(ENDCHAR+STARTCHAR)/2; + if (markchar[XMARK_TEMP_BOUND] < middle) + return(XMARK_START_BOUND); + else + return(XMARK_END_BOUND); + } +} + +void xmarkExpose(dpy,w,gram,b1,p1,b2,p2) + Display *dpy; + Window w; + x_gram *gram; + unsigned int b1,p1,b2,p2; +{ +#define swap(x,y) temp=(x); (x)=(y); (y)=temp + int i,temp; + XEvent event; +#define expose (event.xexpose) + + if ((b1==-1) || (p1==-1) || (b2==-1) || (p2==-1)) return; + + if ((b1 > b2) || ((b1 == b2) && (p1 > p2))) { + swap(b1,b2); + swap(p1,p2); + } + + expose.type=Expose; + expose.display=dpy; + expose.window=w; + + for (i=b1;i<=b2;i++) { + if (b1==b2) { + expose.x=gram->blocks[i].x1+p1; + expose.y=gram->blocks[i].y1; + expose.width=p2-p1; + expose.height=gram->blocks[i].y2-gram->blocks[i].y1; + expose.count=0; + } else if (i==b1) { + expose.x=gram->blocks[i].x1+p1; + expose.y=gram->blocks[i].y1; + expose.width=gram->blocks[i].x2-p1; + expose.height=gram->blocks[i].y2-gram->blocks[i].y1; + expose.count=b2-i; + } else if (i==b2) { + expose.x=gram->blocks[i].x1; + expose.y=gram->blocks[i].y1; + expose.width=p2; + expose.height=gram->blocks[i].y2-gram->blocks[i].y1; + expose.count=b2-i; + } else { + expose.x=gram->blocks[i].x1; + expose.y=gram->blocks[i].y1; + expose.width=gram->blocks[i].x2-gram->blocks[i].x1; + expose.height=gram->blocks[i].y2-gram->blocks[i].y1; + expose.count=b2-i; + } + +#ifdef MARK_DEBUG + if (expose.width && expose.height) { + printf("---- markExpose:\nb1=%d p1=%d b2=%d p2=%d\n",b1,p1,b2,p2); + printf("x=%d y=%d w=%d h=%d\n-----", + expose.x,expose.y,expose.width,expose.height); + } +#endif + if ((expose.width && expose.height) || (expose.count == 0)) + XSendEvent(dpy,w,True,ExposureMask,&event); + } +} + +/* Public functions: */ + +void xmarkRedraw(dpy,w,gram,range) + Display *dpy; + Window w; + x_gram *gram; + int range; +{ +#define ob1 (oldblock[XMARK_START_BOUND]) +#define ob2 (oldblock[XMARK_END_BOUND]) +#define nb1 (markblock[XMARK_START_BOUND]) +#define nb2 (markblock[XMARK_END_BOUND]) +#define op1 (oldpixel[XMARK_START_BOUND]) +#define op2 (oldpixel[XMARK_END_BOUND]) +#define np1 (markpixel[XMARK_START_BOUND]) +#define np2 (markpixel[XMARK_END_BOUND]) + + if (range==XMARK_REDRAW_CURRENT) { + if (!markgram) return; + xmarkExpose(dpy,w,gram,nb1,np1,nb2,np2); + } else if (range==XMARK_REDRAW_OLD) { + if (!oldgram) return; + xmarkExpose(dpy,w,gram,ob1,op1,ob2,op2); + } else if (range==XMARK_REDRAW_START) { + if (!markgram) return; + xmarkExpose(dpy,w,gram,ob1,op1,nb1,np1); + } else if (range==XMARK_REDRAW_END) { + if (!markgram) return; + xmarkExpose(dpy,w,gram,ob2,op2,nb2,np2); + } +#ifdef DEBUG + else { + printf("xmarkRedraw: This shouldn't happen!\n"); + } +#endif +} + +/* needs both bounds to be valid (!= -1) */ +int xmarkSecond() +{ + if (STARTBLOCK > ENDBLOCK) + return(XMARK_START_BOUND); + else if (STARTBLOCK < ENDBLOCK) + return(XMARK_END_BOUND); + else { + if (STARTCHAR > ENDCHAR) + return(XMARK_START_BOUND); + else if (STARTCHAR < ENDCHAR) + return(XMARK_END_BOUND); + else + return(XMARK_END_BOUND); + } +} + +void xmarkClear() +{ + oldblock[0]=markblock[0]; + oldblock[1]=markblock[1]; + oldpixel[0]=markpixel[0]; + oldpixel[1]=markpixel[1]; + oldgram=markgram; + + markblock[0]=-1; + markblock[1]=-1; + markchar[0]=-1; + markchar[1]=-1; + markpixel[0]=-1; + markpixel[1]=-1; + markgram=NULL; +} + +int xmarkExtendFromFirst(gram,x,y) + x_gram *gram; + int x,y; +{ + if (markgram != gram) { + xmarkClear(); + markgram = gram; + } + + if (STARTBLOCK == -1) { + xmarkStart(gram,x,y); + xmarkEnd(gram,x,y); + return(XMARK_REDRAW_CURRENT); + } else if (ENDBLOCK == -1) { + xmarkEnd(gram,x,y); + return(XMARK_REDRAW_CURRENT); + } else { + xmarkSetBound(gram,x,y,XMARK_END_BOUND); + return(XMARK_REDRAW_END); + } +} + +int xmarkExtendFromNearest(gram,x,y) + x_gram *gram; + int x,y; +{ + int bound; + + if (markgram != gram) { + xmarkClear(); + markgram = gram; + } + + if (STARTBLOCK == -1) { + xmarkStart(gram,x,y); + xmarkEnd(gram,x,y); + return(XMARK_REDRAW_CURRENT); + } else if (ENDBLOCK == -1) { + xmarkEnd(gram,x,y); + return(XMARK_REDRAW_CURRENT); + } else { + xmarkSetBound(gram,x,y,bound=xmarkNearest(x,y)); + return(bound==XMARK_START_BOUND?XMARK_REDRAW_START:XMARK_REDRAW_END); + } +} + +char *xmarkGetText() +{ + int i, index, len; + int last_y = -1; + string temp; + string text_so_far = string_Copy(""); + char *text = markgram->text; + int startblock,endblock,startchar,endchar; + + if (xmarkValid()) { + if (xmarkSecond() == XMARK_END_BOUND) { + startblock=STARTBLOCK; + endblock=ENDBLOCK; + startchar=STARTCHAR; + endchar=ENDCHAR; + } else { + startblock=ENDBLOCK; + endblock=STARTBLOCK; + startchar=ENDCHAR; + endchar=STARTCHAR; + } + + for (i=startblock; i<=endblock; i++) { + if (last_y != -1 && last_y != markgram->blocks[i].y) + text_so_far = string_Concat2(text_so_far, "\n"); + index = markgram->blocks[i].strindex; + len = markgram->blocks[i].strlen; + if (startblock == endblock) + temp = string_CreateFromData(text+index+startchar, + endchar-startchar); + else if (i==startblock) + temp = string_CreateFromData(text+index+startchar,len-startchar); + else if (i==endblock) + temp = string_CreateFromData(text+index,endchar); + else + temp = string_CreateFromData(text+index,len); + text_so_far = string_Concat2(text_so_far, temp); + free(temp); + last_y = markgram->blocks[i].y; + } + } + + return(text_so_far); +} |