|
|
1.1 root 1: #include "xjerq.h"
2: #include <errno.h>
3: #ifdef BSD
4: #include <sys/ioctl.h>
5: #else
6: #include <sys/filio.h>
7: #endif
8:
9: Rectangle Drect;
10: Bitmap display;
11: struct Mouse mouse;
12: static struct JProc sP;
13: struct JProc *P;
14: GC gcs[4];
15: Display *dpy;
16: unsigned long fgpix;
17: unsigned long bgpix;
18: Colormap colormap;
19: XColor fgcolor, bgcolor;
20: Font defont;
21:
22: static short arrow_bits[]={
23: 0x0004, 0x000E, 0x001F, 0x003E,
24: 0x007C, 0x00F8, 0x01F0, 0x83E0,
25: 0x87C0, 0xCF80, 0xDF00, 0xFE00,
26: 0xFC00, 0xF800, 0xFE00, 0xFF80,
27: };
28: Cursor normalcursor;
29:
30: /*
31: * Buffer for keyboard input
32: */
33: #define KBDBUFSIZE 128
34: static unsigned char kbdbuffer[KBDBUFSIZE];
35:
36: static struct {
37: unsigned char *buf;
38: unsigned char *in;
39: unsigned char *out;
40: int cnt;
41: int size;
42: } kbdbuf = {kbdbuffer, kbdbuffer, kbdbuffer, 0, KBDBUFSIZE};
43:
44: initdisplay(argc, argv)
45: int argc;
46: char *argv[];
47: {
48: int i;
49: Window win;
50: XSetWindowAttributes xswa;
51: XSizeHints sizehints;
52: Font *df;
53: char *font;
54: char *geom = 0;
55: int flags;
56: int width, height, x, y;
57: char **ap;
58:
59: if (!(dpy= XOpenDisplay(NULL))) {
60: perror("Cannot open display\n");
61: exit(-1);
62: }
63:
64: if ((font = XGetDefault(dpy, argv[0], "JerqFont")) == NULL)
65: font = "fixed";
66: bzero(&sizehints, sizeof(sizehints));
67: ap = argv; i = argc;
68: while (i-- > 0) {
69: if (!strcmp("-fn", ap[0])) {
70: font = ap[1];
71: i--; ap++;
72: }
73: else if (ap[0][0] == '=') {
74: geom = ap[0];
75: flags = XParseGeometry(ap[0], &x, &y, &width, &height);
76: if(WidthValue & flags) {
77: sizehints.flags |= USSize;
78: sizehints.width = width;
79: }
80: if(HeightValue & flags) {
81: sizehints.flags |= USSize;
82: sizehints.height = height;
83: }
84: if(XValue & flags) {
85: if(XNegative & flags)
86: x = DisplayWidth(dpy, DefaultScreen(dpy)) + x
87: - sizehints.width;
88: sizehints.flags |= USPosition;
89: sizehints.x = x;
90: }
91: if(YValue & flags) {
92: if(YNegative & flags)
93: y = DisplayHeight(dpy, DefaultScreen(dpy)) + y
94: -sizehints.height;
95: sizehints.flags |= USPosition;
96: sizehints.y = y;
97: }
98: }
99: ap++;
100: }
101:
102: df = XLoadQueryFont(dpy, font);
103: defont = *df;
104: P = &sP;
105:
106: sizehints.width_inc = sizehints.height_inc = 1;
107: sizehints.min_width = sizehints.min_height = 20;
108: sizehints.flags |= PResizeInc|PMinSize;
109: if (!geom) {
110: sizehints.width = defont.max_bounds.width * 80;
111: sizehints.height = (defont.max_bounds.ascent +
112: defont.max_bounds.descent) * 24;
113: sizehints.flags |= PSize;
114: }
115:
116: xswa.event_mask = 0;
117: bgpix = xswa.background_pixel = WhitePixel(dpy, 0);
118: fgpix = xswa.border_pixel = BlackPixel(dpy, 0);
119: win = XCreateWindow(dpy, RootWindow(dpy, DefaultScreen(dpy)),
120: sizehints.x, sizehints.y, sizehints.width, sizehints.height,
121: 2, 0,
122: InputOutput, DefaultVisual(dpy, DefaultScreen(dpy)),
123: CWEventMask | CWBackPixel | CWBorderPixel, &xswa);
124:
125: XSetStandardProperties(dpy, win, argv[0], argv[0],
126: None, argv, argc, &sizehints);
127:
128: XSelectInput(dpy, win,
129: ButtonPressMask|ButtonReleaseMask|ButtonMotionMask|
130: StructureNotifyMask|ExposureMask|KeyPressMask);
131: XMapWindow(dpy, win);
132:
133: colormap = XDefaultColormap(dpy, 0);
134: fgcolor.pixel = fgpix;
135: bgcolor.pixel = bgpix;
136: XQueryColor(dpy, colormap, &fgcolor);
137: XQueryColor(dpy, colormap, &bgcolor);
138:
139: gcs[F_STORE] = XCreateGC(dpy, win, 0, NULL);
140: XSetForeground(dpy, gcs[F_STORE], fgpix);
141: XSetBackground(dpy, gcs[F_STORE], bgpix);
142: XSetFont(dpy, gcs[F_STORE], defont.fid);
143: gcs[F_OR] = XCreateGC(dpy, win, 0, NULL);
144: XCopyGC(dpy, gcs[F_STORE], GCForeground|GCBackground|GCFont, gcs[F_OR]);
145: gcs[F_CLR] = XCreateGC(dpy, win, 0, NULL);
146: XCopyGC(dpy, gcs[F_STORE], GCBackground|GCFont, gcs[F_CLR]);
147: XSetForeground(dpy, gcs[F_CLR], bgpix);
148: gcs[F_XOR] = XCreateGC(dpy, win, 0, NULL);
149: XCopyGC(dpy, gcs[F_STORE], GCBackground|GCFont, gcs[F_XOR]);
150: XSetForeground(dpy, gcs[F_XOR], AllPlanes);
151: XSetFunction(dpy, gcs[F_XOR], GXxor);
152:
153: display.dr = win;
154: Drect.origin.x = 0;
155: Drect.origin.y = 0;
156: Drect.corner.x = sizehints.width;
157: Drect.corner.y = sizehints.height;
158: display.rect = Drect;
159: while (! P->state & RESHAPED)
160: handleinput(); /* wait for exposure */
161: P->state &= ~RESHAPED;
162: normalcursor = ToCursor(arrow_bits, arrow_bits, 0, 15);
163: cursswitch(&normalcursor);
164:
165:
166: }
167:
168: Bitmap *
169: balloc(r)
170: Rectangle r;
171: {
172: Bitmap *b;
173: Pixmap pm;
174: b=(Bitmap *)malloc(sizeof (struct Bitmap));
175: pm = XCreatePixmap(dpy, display.dr, r.corner.x-r.origin.x,
176: r.corner.y-r.origin.y, DefaultDepth(dpy, 0));
177: b->dr=pm;
178: b->rect=r;
179: b->flag = BI_PIXMAP;
180: return b;
181: }
182:
183: void
184: bfree(b)
185: Bitmap *b;
186: {
187: if(b){
188: XFreePixmap(dpy, b->dr);
189: free((char *)b);
190: }
191: }
192:
193: #define brx(b) (b->rect.origin.x)
194: #define bry(b) (b->rect.origin.y)
195:
196: void
197: rectf(b,r,f)
198: Bitmap *b;
199: Rectangle r;
200: Code f;
201: {
202: register wd=r.corner.x-r.origin.x;
203: register ht=r.corner.y-r.origin.y;
204:
205: if (b->flag & BI_PIXMAP)
206: r.origin = sub(r.origin, b->rect.origin);
207: XFillRectangle(dpy, b->dr, gcs[f], r.origin.x, r.origin.y, wd, ht);
208: }
209:
210: void
211: bitblt(sb,r,db,p,f)
212: Bitmap *sb, *db;
213: Rectangle r; /* in source bitmap */
214: Point p; /* in dest bitmap */
215: Code f;
216: {
217: int wd=r.corner.x-r.origin.x;
218: int ht=r.corner.y-r.origin.y;
219:
220: if (sb->flag & BI_PIXMAP)
221: r.origin = sub(r.origin, sb->rect.origin);
222: if (db->flag & BI_PIXMAP)
223: p = sub(p, db->rect.origin);
224: XCopyArea(dpy, sb->dr, db->dr, gcs[f], r.origin.x, r.origin.y,
225: wd, ht, p.x, p.y);
226: }
227:
228: Point
229: string(ft, s, b, p, f)
230: XFontStruct *ft;
231: char *s;
232: Bitmap *b;
233: Point p;
234: Code f;
235: {
236: Point p1;
237: int i;
238:
239: i = strlen(s);
240: p1 = p;
241: p.y += ft->max_bounds.ascent;
242: if (b->flag & BI_PIXMAP)
243: p = sub(p, b->rect.origin);
244: XDrawString(dpy, b->dr, gcs[f], p.x, p.y, s, i);
245: p1.x += XTextWidth(ft, s, i);
246: return p1;
247: }
248:
249: strwidth(ft,s)
250: XFontStruct *ft;
251: char *s;
252: {
253: return XTextWidth(ft, s, strlen(s));
254: }
255:
256: #ifdef safe
257: Point
258: Pt(x, y)
259: short x, y;
260: {
261: Point p;
262: p.x = x;
263: p.y = y;
264: return p;
265: }
266: Rectangle
267: SRect(x1, y1, x2, y2)
268: short x1, y1, x2, y2;
269: {
270: Rectangle r;
271: r.origin.x = x1;
272: r.origin.y = y1;
273: r.corner.x = x2;
274: r.corner.y = y2;
275: return r;
276: }
277: Rectangle
278: Rpt(p1, p2)
279: Point p1, p2;
280: {
281: Rectangle r;
282: r.origin = p1;
283: r.corner = p2;
284: return r;
285: }
286: #endif safe
287:
288: Point
289: add(a, b)
290: Point a, b;
291: {
292: register short *ap= &a.x, *bp= &b.x;
293: *ap++ += *bp++;
294: *ap += *bp;
295: return a;
296: }
297: Point
298: sub(a, b)
299: Point a, b;
300: {
301: register short *ap= &a.x, *bp= &b.x;
302: *ap++ -= *bp++;
303: *ap -= *bp;
304: return a;
305: }
306: Rectangle
307: inset(r,n)
308: Rectangle r;
309: register n;
310: {
311: register short *rp= &r.origin.x;
312: *rp++ += n;
313: *rp++ += n;
314: *rp++ -= n;
315: *rp -= n;
316: return r;
317: }
318: Rectangle
319: raddp(r, p)
320: Rectangle r;
321: Point p;
322: {
323: register short *rp= &r.origin.x, *pp= &p.x;
324: *rp++ += *pp++;
325: *rp++ += *pp--;
326: *rp++ += *pp++;
327: *rp += *pp;
328: return r;
329: }
330: eqpt(p, q)
331: Point p, q;
332: {
333: register long *pp=(long *)&p, *qq=(long *)&q;
334: return *pp==*qq;
335: }
336: ptinrect(p, r)
337: Point p;
338: Rectangle r;
339: {
340: return(p.x>=r.origin.x && p.x<r.corner.x
341: && p.y>=r.origin.y && p.y<r.corner.y);
342: }
343:
344: /*
345: * Convert a blit style texture to a pixmap which can be used in tiling
346: * or cursor operations.
347: */
348: Pixmap ToPixmap(bits)
349: short bits[];
350: {
351: static XImage *im;
352: Pixmap pm;
353:
354: if (!im)
355: im = XCreateImage(dpy, XDefaultVisual(dpy, 0), 1,
356: XYBitmap, 0, (char *)bits, 16, 16, 8, 2);
357: else
358: im->data = (char *)bits;
359: pm = XCreatePixmap(dpy, display.dr, 16, 16, 1);
360: XPutImage(dpy, pm, gcs[F_STORE], im, 0, 0, 0, 0, 16, 16);
361: return pm;
362: }
363:
364: Cursor ToCursor(source, mask, hotx, hoty)
365: short source[], mask[];
366: {
367: Pixmap sp, mp;
368: Cursor c;
369:
370: sp = ToPixmap(source);
371: mp = ToPixmap(mask);
372: c = XCreatePixmapCursor(dpy, sp, mp, &fgcolor, &bgcolor, hotx, hoty);
373: XFreePixmap(dpy, sp);
374: XFreePixmap(dpy, mp);
375: return(c);
376: }
377:
378: cursset(p)
379: Point p;
380: {
381: XWarpPointer(dpy, display.dr, display.dr, mouse.xy.x, mouse.xy.y,
382: display.rect.corner.x, display.rect.corner.y, p.x, p.y);
383: mouse.xy.x = p.x;
384: mouse.xy.y = p.y;
385: }
386:
387: jnap(i)
388: {
389: handleinput();
390: }
391:
392: kbdchar()
393: {
394: int i;
395:
396: if (!kbdbuf.cnt)
397: return -1;
398: i = *kbdbuf.out++;
399: if (kbdbuf.out == &kbdbuf.buf[kbdbuf.size])
400: kbdbuf.out = kbdbuf.buf;
401: if (--kbdbuf.cnt == 0)
402: P->state &= ~KBD;
403: return(i);
404: }
405:
406: #undef button
407: handleinput()
408: {
409: XEvent ev;
410: unsigned char s[16], *cp;
411: int n;
412:
413: XNextEvent(dpy, &ev);
414: switch (ev.type) {
415: case ButtonPress:
416: mouse.buttons |= (8 >> ev.xbutton.button);
417: mouse.xy.x = ev.xbutton.x;
418: mouse.xy.y = ev.xbutton.y;
419: mouse.time = ev.xbutton.time;
420: break;
421: case ButtonRelease:
422: mouse.buttons &= ~(8 >> ev.xbutton.button);
423: mouse.xy.x = ev.xbutton.x;
424: mouse.xy.y = ev.xbutton.y;
425: mouse.time = ev.xbutton.time;
426: break;
427: case MotionNotify:
428: mouse.xy.x = ev.xmotion.x;
429: mouse.xy.y = ev.xmotion.y;
430: break;
431: case MapNotify:
432: case NoExpose:
433: break;
434: case ConfigureNotify:
435: if (display.rect.corner.x != ev.xconfigure.width ||
436: display.rect.corner.y != ev.xconfigure.height) {
437: display.rect.corner.x = ev.xconfigure.width;
438: display.rect.corner.y = ev.xconfigure.height;
439: Drect = display.rect;
440: }
441: break;
442: case Expose:
443: if (ev.xexpose.count == 0) {
444: rectf(&display, Drect, F_CLR);
445: P->state |= RESHAPED;
446: }
447: break;
448: case KeyPress:
449: mouse.xy.x = ev.xkey.x;
450: mouse.xy.y = ev.xkey.y;
451: mouse.time = ev.xkey.time;
452: n = XLookupString(&ev, s, sizeof(s), NULL, NULL);
453: if (n > 0) {
454: cp = s;
455: P->state |= KBD;
456: do {
457: if (kbdbuf.cnt == kbdbuf.size)
458: break;
459: *kbdbuf.in++ = *cp++;
460: kbdbuf.cnt++;
461: if (kbdbuf.in == &kbdbuf.buf[kbdbuf.size])
462: kbdbuf.in = kbdbuf.buf;
463: } while (--n);
464: }
465: break;
466: default:
467: break;
468: }
469: }
470: #define button(i) (mouse.buttons&(8>>i))
471:
472: char *
473: gcalloc(nbytes, where)
474: unsigned long nbytes;
475: char **where;
476: {
477: *where=(char *)alloc(nbytes);
478: return *where;
479: }
480: void
481: gcfree(s)
482: char *s;
483: {
484: free(s);
485: }
486:
487: min(a,b)
488: {
489: return (a<b? a: b);
490: }
491: max(a,b)
492: {
493: return (a>b? a: b);
494: }
495:
496: /* Form a circle of radius r centered at x1,y1
497: */
498: circle(b,p,r,f)
499: Bitmap *b;
500: Point p;
501: {
502: unsigned int diam = 2*r;
503: if (b->flag & BI_PIXMAP)
504: p = sub(p, b->rect.origin);
505: p = sub(p, Pt(r,r));
506: XDrawArc(dpy, b->dr, gcs[f], p.x, p.y, diam, diam, 0, 23040/* 360 deg */);
507: }
508:
509: Cursor *
510: cursswitch(cp)
511: Cursor *cp;
512: {
513: static Cursor *prev = &normalcursor;
514: Cursor *ret = prev;
515: if (!cp)
516: cp = &normalcursor;
517: XDefineCursor(dpy, display.dr, *cp);
518: prev = cp;
519: return ret;
520: }
521: /* Fill a disc of radius r centered at x1,y1
522: */
523: disc(b, p, r, f)
524: Bitmap *b;
525: Point p;
526: int r;
527: Code f;
528: {
529: unsigned int diam = 2*r;
530: if (b->flag & BI_PIXMAP)
531: p = sub(p, b->rect.origin);
532: p = sub(p, Pt(r,r));
533: XFillArc(dpy, b->dr, gcs[f], p.x, p.y, diam, diam, 0, 23040/* 360 deg */);
534: }
535:
536: typedef struct String{
537: char *s; /* pointer to string */
538: short n; /* number used, no terminal null */
539: short size; /* size of allocated area */
540: } String;
541:
542: getmuxbuf(pmb)
543: String *pmb;
544: {
545: char *ans;
546: int n;
547: ans=XFetchBytes(dpy, &n);
548: pmb->size=pmb->n=n;
549: gcalloc(pmb->size, &(pmb->s));
550: strncpy(pmb->s, ans, n);
551: free(ans);
552: }
553:
554: #define UP 0
555: #define DOWN 1
556:
557: static short boxcurs_bits[] = {
558: 0x43FF, 0xE001, 0x7001, 0x3801, 0x1D01, 0x0F01, 0x8701, 0x8F01,
559: 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0x8001, 0xFFFF,
560: };
561: static Cursor boxcurs;
562:
563: buttons(updown)
564: {
565: while((button123()!=0) != updown)
566: jnap(2);
567: }
568:
569: Rectangle
570: canon(p1, p2)
571: Point p1, p2;
572: {
573: Rectangle r;
574: r.origin.x = min(p1.x, p2.x);
575: r.origin.y = min(p1.y, p2.y);
576: r.corner.x = max(p1.x, p2.x);
577: r.corner.y = max(p1.y, p2.y);
578: return(r);
579: }
580:
581: static outline(r)
582: Rectangle r;
583: {
584: XPoint p[5], *pp;
585:
586: pp = p;
587: pp->x = r.corner.x; pp->y = r.origin.y; pp++;
588: pp->x = r.corner.x; pp->y = r.corner.y; pp++;
589: pp->x = r.origin.x; pp->y = r.corner.y; pp++;
590: pp->x = r.origin.x; pp->y = r.origin.y; pp++;
591: pp->x = r.corner.x; pp->y = r.origin.y; pp++;
592: XDrawLines(dpy, display.dr, gcs[F_XOR], p, 5, CoordModeOrigin);
593: }
594:
595: Rectangle
596: getrectb(n)
597: int n;
598: {
599: Rectangle r;
600: Point p1, p2;
601:
602: if (!boxcurs)
603: boxcurs = ToCursor(boxcurs_bits, boxcurs_bits, 8, 8);
604: cursswitch(&boxcurs);
605: buttons(UP);
606: buttons(DOWN);
607: if(!(mouse.buttons&n)){
608: r.origin.x=r.origin.y=r.corner.x=r.corner.y=0;
609: buttons(UP);
610: goto Return;
611: }
612: p1=mouse.xy;
613: p2=p1;
614: r=canon(p1, p2);
615: outline(r);
616: for(; mouse.buttons&n; jnap(2)){
617: outline(r);
618: p2=mouse.xy;
619: r=canon(p1, p2);
620: outline(r);
621: }
622: outline(r); /* undraw for the last time */
623: Return:
624: cursswitch(0);
625: return r;
626: }
627:
628: Rectangle
629: getrect(n)
630: {
631: return getrectb(8>>n);
632: }
633:
634: #define scale(x, inmin, inmax, outmin, outmax)\
635: (outmin + muldiv(x-inmin,outmax-outmin,inmax-inmin))
636:
637: #define bound(x, low, high) min(high, max( low, x ))
638:
639: #define DISPLAY 16
640: #define DELTA 6
641: #define BARWIDTH 18
642:
643: static char **table;
644: static char *
645: tablegen(i)
646: {
647: return table[i];
648: }
649:
650: menuhit(m, but)
651: register Menu *m;
652: {
653: register int width, i, j, top, newtop, hit, newhit, items, lines, length;
654: Point p, q, savep, baro, barc;
655: Rectangle sr, tr, mr; /* scroll, text, menu */
656: register Bitmap *b;
657: register char *s, *(*generator)(), *from, *to;
658: char fill[64];
659: Font *font = &defont;
660: int spacing = font->max_bounds.ascent + font->max_bounds.descent;
661:
662: #define sro sr.origin
663: #define src sr.corner
664: #define tro tr.origin
665: #define trc tr.corner
666: #define mro mr.origin
667: #define mrc mr.corner
668:
669: generator = (table=m->item) ? tablegen : m->generator;
670: p = mouse.xy;
671: length = width = items = 0;
672: for( ; s=(*generator)(items); ++items) {
673: length = max(length, strlen(s));
674: width = max(width, strwidth(font,s));
675: }
676: if(items == 0){
677: while(button(but));
678: return -1;
679: }
680: width += 10;
681: sro.x = sro.y = src.x = tro.x = mro.x = mro.y = 0;
682: if(items <= DISPLAY)
683: lines = items;
684: else{
685: lines = DISPLAY;
686: tro.x = src.x = BARWIDTH;
687: sro.x = sro.y = 1;
688: }
689: tro.y = 1;
690: mrc = trc = add(Pt(tro.x, mro.y), Pt(width, min(items, lines)*spacing+2));
691: trc.y = src.y = mrc.y-1;
692: newtop = bound(m->prevtop, 0, items-lines);
693: p.y -= bound(m->prevhit, 0, lines-1)*spacing+spacing/2;
694: p.x = bound(p.x-(src.x+width/2), 0, display.rect.corner.x-mrc.x);
695: p.y = bound(p.y, 0, display.rect.corner.y-mrc.y);
696: sr = raddp(sr, p);
697: tr = raddp(tr, p);
698: mr = raddp(mr, p);
699: b = balloc(mr);
700: if(b)
701: bitblt(&display, mr, b, mro, F_STORE);
702: rectf(&display, mr, F_OR);
703: PaintMenu:
704: rectf(&display, inset(mr, 1), F_CLR);
705: top = newtop;
706: if(items > DISPLAY){
707: baro.y = scale(top, 0, items, sro.y, src.y);
708: baro.x = sr.origin.x;
709: barc.y = scale(top+DISPLAY, 0, items, sro.y, src.y);
710: barc.x = sr.corner.x;
711: rectf(&display, Rpt(baro,barc), F_XOR);
712: }
713: for(p=tro, i=top; i < min(top+lines, items); ++i){
714: q = p;
715: from = generator(i);
716: for(to = &fill[0]; *from; ++from)
717: if(*from & 0x80)
718: for(j=length-(strlen(from+1)+(to-&fill[0])); j-->0;)
719: *to++ = *from & 0x7F;
720: else
721: *to++ = *from;
722: *to = '\0';
723: q.x += (width-strwidth(font,fill))/2;
724: string(font, fill, &display, q, F_XOR);
725: p.y += spacing;
726: }
727: savep = mouse.xy;
728: for(newhit = hit = -1; button(but); jnap(2)){
729: if(ptinrect(p = mouse.xy, sr)){
730: if(ptinrect(savep,tr)){
731: p.y = (baro.y+barc.y)/2;
732: cursset(p);
733: }
734: newtop = scale(p.y, sro.y, src.y, 0, items);
735: newtop = bound(newtop-DISPLAY/2, 0, items-DISPLAY);
736: if(newtop != top)
737: goto PaintMenu;
738: }else if(ptinrect(savep,sr)){
739: register dx, dy;
740: if(abs(dx = p.x-savep.x) < DELTA)
741: dx = 0;
742: if(abs(dy = p.y-savep.y) < DELTA)
743: dy = 0;
744: if(abs(dy) >= abs(dx))
745: dx = 0;
746: else
747: dy = 0;
748: cursset(p = add(savep, Pt(dx,dy)));
749: }
750: savep = p;
751: newhit = -1;
752: if(ptinrect(p, tr)){
753: newhit = bound((p.y-tro.y)/spacing, 0, lines-1);
754: if(newhit!=hit && hit>=0
755: && abs(tro.y+spacing*newhit+spacing/2-p.y) > spacing/3)
756: newhit = hit;
757: }
758: if(newhit != hit){
759: flip(tr, hit, spacing);
760: flip(tr, hit = newhit, spacing);
761: }
762: if(newhit==0 && top>0){
763: newtop = top-1;
764: p.y += spacing;
765: cursset(p);
766: goto PaintMenu;
767: }
768: if(newhit==DISPLAY-1 && top<items-lines){
769: newtop = top+1;
770: p.y -= spacing;
771: cursset(p);
772: goto PaintMenu;
773: }
774: }
775: if(b){
776: bitblt(b, b->rect, &display, b->rect.origin, F_STORE);
777: bfree(b);
778: }
779: if(hit>=0){
780: m->prevhit = hit;
781: m->prevtop = top;
782: return hit+top;
783: }else
784: return -1;
785: }
786:
787: static
788: flip(r,n,spacing)
789: Rectangle r;
790: {
791: if(n<0)
792: return;
793: ++r.origin.x;
794: r.corner.y = (r.origin.y += spacing*n) + spacing;
795: --r.corner.x;
796: rectf(&display, r, F_XOR);
797: }
798:
799: void
800: point(b,p,f)
801: Bitmap *b;
802: Point p;
803: Code f;
804: {
805: if (b->flag & BI_PIXMAP)
806: p = sub(p, b->rect.origin);
807: XDrawPoint(dpy, b->dr, gcs[f], p.x, p.y);
808: }
809:
810: #define PBSIZE 100
811:
812: static XPoint xp[PBSIZE];
813: static xpcnt;
814: static Code fc;
815: static ispixmap;
816: static Bitmap *bitm;
817:
818: #define flushpt() if (xpcnt) flushpoints();
819:
820: points(p)
821: Point p;
822: {
823: register XPoint *x;
824:
825: if (ispixmap)
826: p = sub(p, bitm->rect.origin);
827: x = &xp[xpcnt];
828: x->x = p.x;
829: x->y = p.y;
830: if (++xpcnt == PBSIZE)
831: flushpoints();
832: }
833:
834: initpoints(b, f)
835: Bitmap *b;
836: Code f;
837: {
838: if (b->flag & BI_PIXMAP)
839: ispixmap = 1;
840: else
841: ispixmap = 0;
842: bitm = b;
843: fc = f;
844: }
845:
846: endpoints()
847: {
848: flushpt();
849: XSync(dpy, 0);
850: }
851:
852: flushpoints()
853: {
854: if (xpcnt) {
855: XDrawPoints(dpy, bitm->dr, gcs[fc], xp, xpcnt, CoordModeOrigin);
856: xpcnt = 0;
857: }
858: }
859:
860: /*
861: * Buffer for keyboard input
862: */
863: #define RCVBUFSIZE 1024
864:
865: static unsigned char rcvbuffer[RCVBUFSIZE];
866:
867: static struct {
868: unsigned char *buf;
869: unsigned char *in;
870: unsigned char *out;
871: int cnt;
872: int size;
873: }rcvbuf = { rcvbuffer, rcvbuffer, rcvbuffer, 0, RCVBUFSIZE };
874:
875:
876: rcvchar()
877: {
878: int i;
879:
880: if (!rcvbuf.cnt)
881: return -1;
882: i = *rcvbuf.out++;
883: if (rcvbuf.out == &rcvbuf.buf[rcvbuf.size])
884: rcvbuf.out = rcvbuf.buf;
885: if (--rcvbuf.cnt == 0)
886: P->state &= ~RCV;
887: return(i);
888: }
889:
890: rcvfill()
891: {
892: register i;
893:
894: if (rcvbuf.cnt == rcvbuf.size)
895: return;
896: if (rcvbuf.in < rcvbuf.out)
897: i = rcvbuf.out - rcvbuf.in;
898: else
899: i = &rcvbuf.buf[rcvbuf.size] - rcvbuf.in;
900: i = read(0, rcvbuf.in, i);
901: if (i <= 0)
902: return;
903: P->state |= RCV;
904: rcvbuf.cnt += i;
905: rcvbuf.in += i;
906: if (rcvbuf.in == &rcvbuf.buf[rcvbuf.size])
907: rcvbuf.in = rcvbuf.buf;
908: }
909:
910: void
911: request(r)
912: int r;
913: {
914: int i=1;
915: if (r & RCV) {
916: /* need non-blocking I/O on stdout */
917: #ifdef BSD
918: ioctl(1, FIONBIO, &i);
919: #else
920: ioctl(1, FIOWNBLK, 0);
921: #endif
922: }
923: /* for now, assume MOUSE|KBD requested */
924: }
925:
926: void
927: segment(b,p,q,f)
928: Bitmap *b;
929: Point p, q;
930: Code f;
931: {
932: if (b->flag & BI_PIXMAP) {
933: p = sub(p, b->rect.origin);
934: q = sub(q, b->rect.origin);
935: }
936: XDrawLine(dpy, b->dr, gcs[f], p.x, p.y, q.x, q.y);
937: }
938:
939: #ifndef BSD
940: #define EWOULDBLOCK EBUSY
941: #endif
942:
943: sendnchars(n,p)
944: char *p;
945: int n;
946: {
947: int i;
948: int maxfd, rmask, wmask;
949:
950: while (n) {
951: i = write(1, p, n);
952: if (i > 0) {
953: n -= i;
954: p += i;
955: continue;
956: }
957: if (i < 0 && errno == EWOULDBLOCK) {
958: maxfd = dpy->fd + 1;
959: do {
960: while (XPending(dpy))
961: handleinput();
962: rmask = (1 << dpy->fd) | 1;
963: wmask = 2;
964: #ifdef BSD
965: select(maxfd, &rmask, &wmask, 0, 0);
966: #else
967: select(maxfd, &rmask, &wmask, 0x6fffffff);
968: #endif
969: if (rmask & 1)
970: rcvfill();
971: if (rmask & (1 << dpy->fd))
972: handleinput();
973: } while (!wmask);
974: }
975: else
976: exit(1);
977: }
978: }
979: #define MAXROOT 0xb504
980: sqrt(x)
981: register long x;
982: {
983: register long high=MAXROOT;
984: register long low=0;
985: register long current=MAXROOT/2;
986: if(x<=0)
987: return 0;
988: if(x>=MAXROOT*MAXROOT)
989: return(MAXROOT);
990: while(high>low+1){
991: if(current*current==x)
992: return (current);
993: if(current*current>x)
994: high=current;
995: else
996: low=current;
997: current=(high+low)>>1;
998: }
999: return(current);
1000: }
1001:
1002: wait(resource)
1003: {
1004: int maxfd, smask, i;
1005:
1006: maxfd = dpy->fd + 1;
1007: for(;;) {
1008: if (P->state & resource)
1009: break;
1010: if (XPending(dpy))
1011: goto xin;
1012: if (resource & CPU)
1013: break;
1014: smask = (1 << dpy->fd) | 1;
1015: #ifdef BSD
1016: select(maxfd, &smask, 0, 0, 0);
1017: #else
1018: select(maxfd, &smask, 0, 0x6fffffff);
1019: #endif
1020: if (smask & 1)
1021: rcvfill();
1022: if (smask & (1 << dpy->fd)) {
1023: xin:
1024: handleinput();
1025: /* We always have the mouse and cpu */
1026: if (resource & (MOUSE|CPU))
1027: break;
1028: }
1029: }
1030: return P->state;
1031: }
1032:
1033: int
1034: own()
1035: {
1036: return P->state|MOUSE;
1037: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.