Introduction
Introduction Statistics Contact Development Disclaimer Help
xtbinit.c - sam - An updated version of the sam text editor.
git clone git://vernunftzentrum.de/sam.git
Log
Files
Refs
LICENSE
---
xtbinit.c (18637B)
---
1 /* Copyright (c) 1998 Lucent Technologies - All rights reserved. */
2 #include <u.h>
3 #include <libg.h>
4 #include <stdio.h>
5 #include <stdlib.h>
6 #include <string.h>
7 #include <sys/types.h>
8 #include <sys/socket.h>
9 #include "libgint.h"
10
11 #define Font xFont
12 #define Event xEvent
13
14 #include <X11/Intrinsic.h>
15 #include <X11/StringDefs.h>
16 #include <X11/Shell.h>
17 #include <X11/XKBlib.h>
18 #include <X11/extensions/XInput.h>
19 #include "Gwin.h"
20
21 #undef Font
22 #undef Event
23
24 /* default colors */
25 #ifndef MAX_BACKGROUNDS
26 #define MAX_BACKGROUNDS 20
27 #endif
28
29 #ifndef DEFAULT_FOREGROUND
30 #define DEFAULT_FOREGROUND "#000000"
31 #endif
32
33 #ifndef DEFAULT_BACKGROUND
34 #define DEFAULT_BACKGROUND "#ffffff"
35 #endif
36
37 #ifndef DEFAULT_BORDER
38 #define DEFAULT_BORDER "#000000"
39 #endif
40
41 /* libg globals */
42 XIM xim;
43 XIC xic;
44 Bitmap screen;
45 XftFont *font;
46 XftColor fontcolor;
47 char fontspec[1024] = {0};
48 char foregroundspec[1024] = {0};
49 char backgroundspec[1024] = {0};
50 char borderspec[1024] = {0};
51
52 /* implementation globals */
53 extern char *machine;
54 Display *_dpy;
55 Widget _toplevel;
56 Window _topwindow;
57 uint64_t _bgpixels[MAX_BACKGROUNDS];
58 int _nbgs;
59 uint64_t _fgpixel, _bgpixel, _borderpixel;
60 XColor _fgcolor, _bgcolor, _bordercolor;
61 int _ld2d[6] = { 1, 2, 4, 8, 16, 24 };
62 uint64_t _ld2dmask[6] = { 0x1, 0x3, 0xF, 0xFF, 0xFFFF, 0x00FFFFFF };
63 Colormap _libg_cmap;
64 int _cmap_installed;
65
66 /* xbinit implementation globals */
67 static XtAppContext app;
68 static Widget widg;
69 static bool exposed = 0;
70 static Atom wm_take_focus;
71 static Mouse lastmouse;
72
73 typedef struct Ebuf {
74 struct Ebuf *next;
75 int n;
76 unsigned char buf[4];
77 } Ebuf;
78
79 typedef struct Esrc {
80 bool issocket;
81 bool inuse;
82 int size;
83 int count;
84 Ebuf *head;
85 Ebuf *tail;
86 } Esrc;
87
88 #define MAXINPUT 1024 /* number of queued input events */
89 #define MAXSRC 10
90
91 static Esrc esrc[MAXSRC];
92 static int nsrc;
93
94
95 static int einitcalled = 0;
96 static int Smouse = -1;
97 static int Skeyboard = -1;
98
99
100 static void reshaped(int, int, int, int);
101 static void gotchar(int, int, int, int, int, const char *);
102 static void gotmouse(Gwinmouse *);
103 static int ilog2(int);
104
105 static Ebuf *ebread(Esrc *);
106 static Ebuf *ebadd(Esrc *, bool);
107 static void focinit(Widget);
108 static void wmproto(Widget, XEvent *, String *, Cardinal *);
109 static void waitevent(void);
110
111 static Errfunc onerr;
112
113 String _fallbacks[] = {
114 "*gwin.width: 400",
115 "*gwin.height: 400",
116 NULL
117 };
118
119 static char *shelltrans =
120 "<ClientMessage> WM_PROTOCOLS : WMProtocolAction()";
121 static XtActionsRec wmpactions[] = {
122 {"WMProtocolAction", wmproto}
123 };
124
125 Bitmap *darkgrey;
126
127 static uint8_t darkgreybits[] = {
128 0xDD, 0xDD, 0x77, 0x77, 0xDD, 0xDD, 0x77, 0x77,
129 0xDD, 0xDD, 0x77, 0x77, 0xDD, 0xDD, 0x77, 0x77,
130 0xDD, 0xDD, 0x77, 0x77, 0xDD, 0xDD, 0x77, 0x77,
131 0xDD, 0xDD, 0x77, 0x77, 0xDD, 0xDD, 0x77, 0x77,
132 };
133
134 void
135 freefont(void)
136 {
137 if (font)
138 XftFontClose(_dpy, font);
139 }
140
141 void
142 xtbinit(Errfunc f, char *class, int *pargc, char **argv, char **fallback…
143 {
144 int n;
145 char *p;
146 int compose;
147
148 if(!class && argv[0]){
149 p = strrchr(argv[0], '/');
150 if(p)
151 class = XtNewString(p+1);
152 else
153 class = XtNewString(argv[0]);
154 if(class[0] >= 'a' && class[0] <= 'z')
155 class[0] += 'A' - 'a';
156 }
157 onerr = f;
158 if (!fallbacks)
159 fallbacks = _fallbacks;
160
161 char name[512] = {0};
162 snprintf(name, sizeof(name) - 1, "samterm on %s", machine);
163 Arg args[] ={
164 {XtNinput, true},
165 {XtNtitle, (XtArgVal)name},
166 {XtNiconName, (XtArgVal)name},
167 };
168 _toplevel = XtAppInitialize(&app, class,
169 NULL, 0,
170 pargc, argv, fallbacks, args, XtNumber(args));
171
172 n = 0;
173 XtSetArg(args[n], XtNreshaped, reshaped); n++;
174 XtSetArg(args[n], XtNgotchar, gotchar); n++;
175 XtSetArg(args[n], XtNgotmouse, gotmouse); n++;
176 widg = XtCreateManagedWidget("gwin", gwinWidgetClass, _toplevel, arg…
177
178 _dpy = XtDisplay(widg);
179 XAllocNamedColor(_dpy, DefaultColormap(_dpy, DefaultScreen(_dpy)),
180 foregroundspec[0] ? foregroundspec : getenv("FOREGR…
181 XAllocNamedColor(_dpy, DefaultColormap(_dpy, DefaultScreen(_dpy)),
182 borderspec[0] ? borderspec : getenv("BORDER") ? get…
183 char bgspec[1024] = {0};
184 strncpy(bgspec, backgroundspec[0] ? backgroundspec : getenv("BACKGRO…
185
186 char *bgc = NULL;
187 for (bgc = strtok(bgspec, ":"); bgc != NULL && _nbgs < MAX_BACKGROUN…
188 XColor xc = {0};
189 if (XAllocNamedColor(_dpy, DefaultColormap(_dpy, DefaultScreen(_…
190 _bgpixels[_nbgs++] = xc.pixel;
191 }
192
193 if (_nbgs == 0)
194 _bgpixels[_nbgs++] = ~_fgcolor.pixel;
195
196 _bgpixel = _bgpixels[0];
197
198 n = 0;
199 XtSetArg(args[n], XtNcomposeMod, &compose); n++;
200 XtGetValues(widg, args, n);
201
202 if (compose < 0 || compose > 5) {
203 n = 0;
204 XtSetArg(args[n], XtNcomposeMod, 0); n++;
205 XtSetValues(widg, args, n);
206 }
207
208 initcursors();
209 atexit(freebindings);
210 atexit(freechords);
211
212 if ((xim = XOpenIM(_dpy, NULL, NULL, NULL)) == NULL) {
213 XSetLocaleModifiers("@im=local");
214 if ((xim = XOpenIM(_dpy, NULL, NULL, NULL)) == NULL) {
215 XSetLocaleModifiers("@im=");
216 if ((xim = XOpenIM(_dpy, NULL, NULL, NULL)) == NULL) {
217 fprintf(stderr, "could not open input method\n");
218 exit(EXIT_FAILURE);
219 }
220 }
221 }
222
223 font = XftFontOpenName(_dpy, DefaultScreen(_dpy), fontspec[0] ? font…
224 screen.id = 0;
225 XtRealizeWidget(_toplevel);
226 _topwindow = XtWindow(_toplevel);
227 atexit(freefont);
228
229 pid_t pid = getpid();
230 XChangeProperty(_dpy, XtWindow(_toplevel), XInternAtom(_dpy, "_NET_W…
231
232 _fgpixel = _fgcolor.pixel;
233 _borderpixel = _bordercolor.pixel;
234
235 XRenderColor xrcolor = {0};
236 xrcolor.red = _fgcolor.red;
237 xrcolor.green = _fgcolor.green;
238 xrcolor.blue = _fgcolor.blue;
239 xrcolor.alpha = 65535;
240 XftColorAllocValue(_dpy, DefaultVisual(_dpy, DefaultScreen(_dpy)), D…
241
242 screen.id = (int) XtWindow(widg);
243 screen.ldepth = ilog2(DefaultDepth(_dpy, DefaultScreen(_dpy)));
244 screen.flag = SCR;
245 if(_fgpixel != 0)
246 screen.flag |= BL1;
247 /* leave screen rect at all zeros until reshaped() sets it */
248 while(!exposed) {
249 XFlush(_dpy);
250 XtAppProcessEvent(app, XtIMXEvent);
251 }
252
253 darkgrey = balloc(Rect(0, 0, 16, 16), 0);
254 wrbitmap(darkgrey, 0, 16, darkgreybits);
255
256 XFlush(_dpy);
257 focinit(_toplevel);
258 }
259
260 static void
261 focinit(Widget w)
262 {
263 XrmValue src, dst;
264
265 src.addr = "WM_TAKE_FOCUS";
266 src.size = strlen((char *)src.addr)+1;
267 dst.addr = (XtPointer) &wm_take_focus;
268 dst.size = sizeof(Atom);
269 XtConvertAndStore(w, XtRString, &src, XtRAtom, &dst);
270 XSetWMProtocols(XtDisplay(w), XtWindow(w), &wm_take_focus, 1);
271 XtAppAddActions(app, wmpactions, XtNumber(wmpactions));
272 XtAugmentTranslations(w, XtParseTranslationTable(shelltrans));
273 }
274
275 static void
276 wmproto(Widget w, XEvent *e , String *p, Cardinal *np)
277 {
278 Time t;
279
280 if(e->type == ClientMessage &&
281 (Atom)(e->xclient.data.l[0]) == wm_take_focus) {
282 t = (Time) e->xclient.data.l[1];
283 XtCallAcceptFocus(widg, &t);
284 }
285 }
286
287 static void
288 reshaped(int minx, int miny, int maxx, int maxy)
289 {
290 Ebuf *eb;
291
292 screen.r = Rect(minx, miny, maxx, maxy);
293 screen.clipr = screen.r;
294 if (screen.id) {
295 exposed = true;
296 ereshaped(screen.r);
297 }
298 if(einitcalled){
299 /*
300 * Cause a mouse event, so programs like sam
301 * will get out of eread and REALLY do the reshape
302 */
303 eb = ebadd(&esrc[Smouse], false);
304 if (eb == 0)
305 berror("eballoc can't malloc");
306 memcpy((void*)eb->buf, (void*)&lastmouse, sizeof lastmouse);
307 esrc[Smouse].count++;
308 }
309 }
310
311 static void
312 gotchar(int c, int kind, int target, int x, int y, const char *arg)
313 {
314 Ebuf *eb;
315 Keystroke k;
316
317 if(!einitcalled || Skeyboard == -1)
318 return;
319 eb = ebadd(&esrc[Skeyboard], false);
320 if (eb == NULL)
321 berror("eballoc can't malloc");
322 k.c = c;
323 k.k = kind;
324 k.t = target;
325 k.p = Pt(x, y);
326 k.a = arg;
327 memcpy(eb->buf, &k, sizeof(Keystroke));
328 esrc[Skeyboard].count++;
329 }
330
331 static void
332 gotmouse(Gwinmouse *gm)
333 {
334 Ebuf *eb;
335 Mouse m;
336
337 if(!einitcalled || Smouse == -1)
338 return;
339 m.buttons = gm->buttons;
340 m.xy.x = gm->xy.x;
341 m.xy.y = gm->xy.y;
342 m.msec = gm->msec;
343 lastmouse = m;
344 eb = ebadd(&esrc[Smouse], false);
345 if (eb == 0)
346 berror("eballoc can't malloc");
347 memcpy((void*)eb->buf, (void*)&m, sizeof m);
348 esrc[Smouse].count++;
349 }
350
351 static void
352 gotinput(XtPointer cldata, int *pfd, XtInputId *id)
353 {
354 Ebuf *eb, *lasttail, *newe;
355 Esrc *es;
356 int n;
357
358 if(!einitcalled)
359 return;
360 es = (Esrc *)cldata;
361 if (es->count >= MAXINPUT)
362 return;
363 lasttail = es->tail;
364 eb = ebadd(es, false);
365 if (eb == 0)
366 return;
367 if(es->size){
368 if (es->issocket){
369 struct sockaddr addr;
370 socklen_t len;
371 int fd = accept(*pfd, &addr, &len);
372 n = read(fd, (char *)eb->buf, es->size);
373 close(fd);
374 } else
375 n = read(*pfd, (char *)eb->buf, es->size);
376 if (n < 0)
377 n = 0;
378 if(n < es->size) {
379 newe = realloc(eb, sizeof(Ebuf)+n);
380 newe->n = n;
381 if (es->head == eb)
382 es->head = newe;
383 else
384 lasttail->next = newe;
385 es->tail = newe;
386 }
387 }
388 es->count++;
389 }
390
391 static int
392 ilog2(int n)
393 {
394 int i, v;
395
396 for(i=0, v=1; i < 6; i++, v<<=1)
397 if(n <= v)
398 break;
399 return i;
400 }
401
402
403 void
404 rdcolmap(Bitmap *b, RGB *map)
405 {
406 XColor cols[256];
407 int i, n, depth;
408 Colormap cmap;
409 Arg args[2];
410
411 if (_cmap_installed) {
412 cmap = _libg_cmap;
413 } else {
414 i = 0;
415 XtSetArg(args[i], XtNcolormap, &cmap); i++;
416 XtGetValues(_toplevel, args, i);
417 }
418
419 depth = _ld2d[screen.ldepth];
420 n = 1 << depth;
421 if (depth == 1) {
422 map[0].red = map[0].green = map[0].blue = ~0;
423 map[1].red = map[1].green = map[1].blue = 0;
424 }
425 else {
426 if (n > 256) {
427 berror("rdcolmap bitmap too deep");
428 return;
429 }
430 for (i = 0; i < n; i++)
431 cols[i].pixel = i;
432 XQueryColors(_dpy, cmap, cols, n);
433 for (i = 0; i < n; i++) {
434 map[i].red = (cols[i].red << 16) | cols[i].red;
435 map[i].green = (cols[i].green << 16) | cols[i].green;
436 map[i].blue = (cols[i].blue << 16) | cols[i].blue;
437 }
438 }
439 }
440
441 void
442 wrcolmap(Bitmap *b, RGB *map)
443 {
444 int i, n, depth;
445 Screen *scr;
446 XColor cols[256];
447 Arg args[2];
448 XVisualInfo vi;
449 Window w;
450
451 scr = XtScreen(_toplevel);
452 depth = _ld2d[screen.ldepth];
453 n = 1 << depth;
454 if (n > 256) {
455 berror("wrcolmap bitmap too deep");
456 return;
457 } else if (depth > 1) {
458 for (i = 0; i < n; i++) {
459 cols[i].red = map[i].red >> 16;
460 cols[i].green = map[i].green >> 16;
461 cols[i].blue = map[i].blue >> 16;
462 cols[i].pixel = i;
463 cols[i].flags = DoRed|DoGreen|DoBlue;
464 }
465 if (!XMatchVisualInfo(_dpy, XScreenNumberOfScreen(scr),
466 depth, PseudoColor, &vi)) {
467 berror("wrcolmap can't get visual");
468 return;
469 }
470 w = XtWindow(_toplevel);
471 _libg_cmap = XCreateColormap(_dpy, w, vi.visual, AllocAll);
472 XStoreColors(_dpy, _libg_cmap, cols, n);
473
474 i = 0;
475 XtSetArg(args[i], XtNcolormap, _libg_cmap); i++;
476 XtSetValues(_toplevel, args, i);
477 _cmap_installed = 1;
478 }
479 }
480
481 void
482 einit(uint64_t keys)
483 {
484 /*
485 * Make sure Smouse = ilog2(Emouse) and Skeyboard == ilog2(Ekeyboard)
486 */
487 nsrc = 0;
488 if(keys&Emouse){
489 Smouse = 0;
490 esrc[Smouse].inuse = true;
491 esrc[Smouse].size = sizeof(Mouse);
492 esrc[Smouse].count = 0;
493 nsrc = Smouse+1;
494 }
495 if(keys&Ekeyboard){
496 Skeyboard = 1;
497 esrc[Skeyboard].inuse = true;
498 esrc[Skeyboard].size = sizeof(Keystroke);
499 esrc[Skeyboard].count = 0;
500 if(Skeyboard >= nsrc)
501 nsrc = Skeyboard+1;
502 }
503 einitcalled = 1;
504 }
505
506 uint64_t
507 estart(uint64_t key, int fd, size_t n, bool issocket)
508 {
509 int i;
510
511 if(fd < 0)
512 berror("bad fd to estart");
513 if(n <= 0 || n > EMAXMSG)
514 n = EMAXMSG;
515 for(i=0; i<MAXSRC; i++)
516 if((key & ~(1<<i)) == 0 && !esrc[i].inuse){
517 if(nsrc <= i)
518 nsrc = i+1;
519 esrc[i].inuse = true;
520 esrc[i].issocket = issocket;
521 esrc[i].size = n;
522 esrc[i].count = 0;
523 XtAppAddInput(app, fd, (XtPointer)XtInputReadMask,
524 gotinput, (XtPointer) &esrc[i]);
525 return 1<<i;
526 }
527 return 0;
528 }
529
530 uint64_t
531 event(Event *e)
532 {
533 return eread(~0L, e);
534 }
535
536 uint64_t
537 eread(uint64_t keys, Event *e)
538 {
539 Ebuf *eb;
540 int i;
541
542 if(keys == 0)
543 return 0;
544 /* Give Priority to X events */
545 if (XtAppPending(app) & XtIMXEvent)
546 XtAppProcessEvent(app, XtIMXEvent);
547
548 for(;;){
549 for(i=0; i<nsrc; i++)
550 if((keys & (1<<i)) && esrc[i].head){
551 if(i == Smouse)
552 e->mouse = emouse();
553 else if(i == Skeyboard)
554 e->keystroke = ekbd();
555 else {
556 eb = ebread(&esrc[i]);
557 e->n = eb->n;
558 if(e->n > 0)
559 memcpy((void*)e->data, (void*)eb->buf, e->n);
560 free(eb);
561 }
562 return 1<<i;
563 }
564 waitevent();
565 }
566 }
567
568 Mouse
569 emouse(void)
570 {
571 Mouse m;
572 Ebuf *eb;
573
574 if(!esrc[Smouse].inuse)
575 berror("mouse events not selected");
576 eb = ebread(&esrc[Smouse]);
577 memcpy((void*)&m, (void*)eb->buf, sizeof(Mouse));
578 free(eb);
579 return m;
580 }
581
582 Keystroke
583 ekbd(void)
584 {
585 Ebuf *eb;
586 Keystroke k;
587
588 if(!esrc[Skeyboard].inuse)
589 berror("keyboard events not selected");
590 eb = ebread(&esrc[Skeyboard]);
591 memcpy(&k, eb->buf, sizeof(Keystroke));
592 free(eb);
593 return k;
594 }
595
596 void
597 pushkbd(int c)
598 {
599 Ebuf *eb;
600 Keystroke k;
601
602 if(!einitcalled || Skeyboard == -1)
603 return;
604 eb = ebadd(&esrc[Skeyboard], true);
605 if (eb == 0)
606 berror("eballoc can't malloc");
607 k.c = c;
608 k.k = Kraw;
609 memcpy(eb->buf, &k, sizeof(Keystroke));
610 esrc[Skeyboard].count++;
611 }
612
613 int
614 ecanread(uint64_t keys)
615 {
616 int i;
617
618 for(;;){
619 for(i=0; i<nsrc; i++){
620 if((keys & (1<<i)) && esrc[i].head)
621 return 1<<i;
622 }
623 if(XtAppPending(app))
624 waitevent();
625 else
626 return 0;
627 }
628 }
629
630 int
631 ecanmouse(void)
632 {
633 if(Smouse == -1)
634 berror("mouse events not selected");
635 return ecanread(Emouse);
636 }
637
638 int
639 ecankbd(void)
640 {
641 if(Skeyboard == -1)
642 berror("keyboard events not selected");
643 return ecanread(Ekeyboard);
644 }
645
646 static Ebuf*
647 ebread(Esrc *s)
648 {
649 Ebuf *eb;
650
651 while(s->head == 0)
652 waitevent();
653 eb = s->head;
654 if(s == &esrc[Smouse]) {
655 while(eb->next) {
656 s->head = eb->next;
657 s->count--;
658 free(eb);
659 eb = s->head;
660 }
661 }
662 s->head = s->head->next;
663 if(s->head == 0) {
664 s->tail = 0;
665 s->count = 0;
666 } else
667 s->count--;
668 return eb;
669 }
670
671 static inline void
672 ebappend(Ebuf *b, Esrc *s)
673 {
674 if (s->tail){
675 s->tail->next = b;
676 s->tail = b;
677 } else
678 s->head = s->tail = b;
679 }
680
681 static inline void
682 ebprepend(Ebuf *b, Esrc *s)
683 {
684 b->next = s->head;
685 s->head = b;
686 }
687
688 static Ebuf*
689 ebadd(Esrc *s, bool prepend)
690 {
691 Ebuf *eb;
692 int m;
693
694 m = sizeof(Ebuf);
695 if(s->size > 1)
696 m += (s->size-1); /* overestimate, because of alignment */
697 eb = (Ebuf *)malloc(m);
698 if(eb) {
699 eb->next = 0;
700 eb->n = s->size;
701 if (prepend)
702 ebprepend(eb, s);
703 else
704 ebappend(eb, s);
705 }
706 return eb;
707 }
708
709 void
710 berror(char *s)
711 {
712 if(onerr)
713 (*onerr)(s);
714 else{
715 fprintf(stderr, "libg error: %s:\n", s);
716 exit(1);
717 }
718 }
719
720 void
721 bflush(void)
722 {
723 while(XtAppPending(app) & XtIMXEvent)
724 waitevent();
725 }
726
727 static void
728 waitevent(void)
729 {
730 XFlush(_dpy);
731 if (XtAppPending(app) & XtIMXEvent)
732 XtAppProcessEvent(app, XtIMXEvent);
733 else
734 XtAppProcessEvent(app, XtIMAll);
735 }
736
737 int
738 snarfswap(char *s, int n, char **t)
739 {
740 *t = GwinSelectionSwap(widg, s);
741 if (*t)
742 return strlen(*t);
743 return 0;
744 }
745
746 int scrpix(int *w, int *h)
747 {
748 if (w)
749 *w = WidthOfScreen(XtScreen(_toplevel));
750 if (h)
751 *h = HeightOfScreen(XtScreen(_toplevel));
752 return 1;
753 }
754
755 #ifdef DEBUG
756 /* for debugging */
757 printgc(char *msg, GC g)
758 {
759 XGCValues v;
760
761 XGetGCValues(_dpy, g, GCFunction|GCForeground|GCBackground|GCFont|
762 GCTile|GCFillStyle|GCStipple, &v);
763 fprintf(stderr, "%s: gc %x\n", msg, g);
764 fprintf(stderr, " fg %d bg %d func %d fillstyle %d font %x tile %x …
765 v.foreground, v.background, v.function, v.fill_style,
766 v.font, v.tile, v.stipple);
767 }
768 #endif
769
770 void
771 raisewindow(void)
772 {
773 XEvent e;
774 Atom a = XInternAtom(_dpy, "_NET_ACTIVE_WINDOW", True);
775
776 XRaiseWindow(_dpy, _topwindow);
777
778 if (a != None){
779 memset(&e, 0, sizeof(XEvent));
780 e.type = ClientMessage;
781 e.xclient.window = _topwindow;
782 e.xclient.message_type = a;
783 e.xclient.format = 32;
784 e.xclient.data.l[0] = 1;
785 e.xclient.data.l[1] = CurrentTime;
786 e.xclient.data.l[2] = None;
787 e.xclient.data.l[3] = 0;
788 e.xclient.data.l[4] = 0;
789
790 XSendEvent(_dpy, DefaultRootWindow(_dpy), False,
791 SubstructureRedirectMask | SubstructureNotifyMask, &e…
792 }
793
794 XFlush(_dpy);
795 }
796
797 uint64_t
798 getbg(void)
799 {
800 static int i = 0;
801
802 if (i >= _nbgs)
803 i = 0;
804
805 return _bgpixels[i++];
806 }
807
You are viewing proxied material from vernunftzentrum.de. The copyright of proxied material belongs to its original authors. Any comments or complaints in relation to proxied material should be directed to the original authors of the content concerned. Please see the disclaimer for more details.