2 * usage: .../gui-plan [<windowid>]
5 * off <segname>[/[<movfeat>]
6 * [t|f][i]on <segname>[[/<movfeat>] <movpos>]
7 * [t|f][i]det <segname>[[/<movfeat>] <movpos>]
16 #include <sys/types.h>
17 #include <sys/socket.h>
23 typedef int ErrorCode;
27 #include "../layout/plan-data-format.h"
28 #include "../layout/layout-data.h"
34 #define NSEGMENTS (ui_plan_data.n_segments)
36 typedef struct MaskState MaskState;
38 int x, y, width, height;
42 typedef struct PosnState PosnState;
44 int x, y, width, height;
50 unsigned on:1, inv:1, det:1, trainown:2, updated_tmp:1,
51 resolution_problem:1; /* for multiplexer client only */
54 typedef struct SegmovfeatState SegmovfeatState;
55 struct SegmovfeatState {
56 SegmovfeatState *next;
58 unsigned redraw_needed:1;
61 PosnState (*posns)[2/*i*/][2/*det*/];
62 /* posns[n_posns]=unknown if n_posns>1 */
66 const char *progname= "gui-plan";
68 typedef struct TrainState TrainState;
72 SegFlags flags; /* used by multiplexer client */
77 static SegState *state;
78 static SegmovfeatState *states_head;
79 static StartupState stastate;
81 static oop_source_sys *sys_events;
83 static int redraw_needed_count, expose_count;
84 static Pixmap bg_pixmap;
85 static unsigned long train_pixel, owned_pixel;
87 static const char *stastate_names[]= DEFINE_STASTATE_DATA;
89 static const char *badcmdreport_data;
90 static size_t badcmdreport_recsz;
92 void die_hook(void) { }
93 void die_vprintf_hook(const char *fmt, va_list al) { }
95 static void xlib_process(void);
97 static void diex(const char *fn, const char *w) __attribute__((noreturn));
98 static void diex(const char *fn, const char *w) {
99 die("Xlib call failed: %s%s%s%s", fn,
100 (w)?" (":"", (w), (w)?")":"");
103 #define XCALL(f,w,al) do{ \
108 static void diexpm(const char *fn, const char *w, int xpmst)
109 __attribute__((noreturn));
110 static void diexpm(const char *fn, const char *w, int xpmst) {
111 die("Xpm call failed: %s%s%s%s: %s", fn,
112 (w)?" (":"", (w), (w)?")":"", XpmGetErrorString(xpmst));
115 #define XPMCALL(f,w,al) do{ \
117 xpmcall_xpmst= ((f) al); \
118 if (xpmcall_xpmst != XpmSuccess) \
119 diexpm(#f, (w), xpmcall_xpmst); \
122 /*---------- input handling ----------*/
126 void (*on_eof)(void);
127 void (*on_input_line)(ParseState *ps);
128 int (*on_badcmd)(void);
131 static const InputStream *instream;
133 static void *input_iferr(oop_source *evts, oop_read *stdin_read,
134 oop_rd_event evt, const char *errmsg, int errnoval,
135 const char *data, size_t recsz, void *u_v) {
137 emsg= oop_rd_errmsg(stdin_read, evt, errnoval, OOP_RD_STYLE_GETLINE);
138 die("%s: %s", instream->name, emsg);
141 static void *input_ifok(oop_source *evts, oop_read *cl_read,
142 oop_rd_event evt, const char *errmsg, int errnoval,
143 const char *data, size_t recsz, void *u_v) {
146 if (evt == OOP_RD_EOF) {
150 if (evt != OOP_RD_OK) {
151 input_iferr(evts,cl_read,evt,errmsg,errnoval,data,recsz,0);
155 badcmdreport_data= data;
156 badcmdreport_recsz= recsz;
159 instream->on_input_line(&ps);
164 static void *some_exception(oop_source *evts, int fd,
165 oop_event evt, void *name_v) {
166 const char *name= name_v;
167 die("poll exception on %s (fd %d)",name,fd);
170 int vbadcmd(ParseState *ps, const char *fmt, va_list al) {
171 fprintf(stderr,"gui-plan: incorrect input: `%.*s': ",
172 (int)badcmdreport_recsz, badcmdreport_data);
173 vfprintf(stderr,fmt,al);
175 return instream->on_badcmd();
178 static int lstrpdbsearch(const char *str, int l,
180 const void *items, int n_items,
182 int min, maxe, try, cmp;
183 const void *try_item;
184 const char *try_name;
189 if (min >= maxe) { badcmd(0,"unknown %s `%.*s'",what,l,str); return -1; }
190 try= min + (maxe - min) / 2;
191 try_item= (const char*)items + itemsz * try;
192 try_name= *(const char *const *)try_item;
193 cmp= lstrstrcmp(str, l, try_name ? try_name : "");
194 if (!cmp) return try;
195 if (cmp < 0) maxe= try;
200 static int lstrpdbsearch_movfeat(const char *str, int l,
201 const PlanSegmentData *sd) {
202 return lstrpdbsearch(str, l, "movfeat", sd->movfeats, sd->n_movfeats,
203 sizeof(*sd->movfeats));
205 static int lstrpdbsearch_segment(const char *str, int l) {
206 return lstrpdbsearch(str, l, "segment",
207 ui_plan_data.segments, ui_plan_data.n_segments,
208 sizeof(*ui_plan_data.segments));
211 /*---------- drawing etc. ----------*/
213 static int range_overlap(int x1, int width1, int x2, int width2) {
214 /* works for y's and heights too, obviously. */
218 if (rhs1 <= x2 || rhs2 <= x1) return 0;
222 static void redraw_mark(SegmovfeatState *fs) {
223 if (fs->redraw_needed) return;
224 fs->redraw_needed= 1;
225 redraw_needed_count++;
228 static void xlib_expose(XExposeEvent *ev) {
231 expose_count= ev->count;
232 if (!ev->width || !ev->height) return;
234 for (fs= states_head;
237 if (!range_overlap(fs->whole.x, fs->whole.width,
238 ev->x, ev->width)) continue;
239 if (!range_overlap(fs->whole.y, fs->whole.height,
240 ev->y, ev->height)) continue;
245 static void redraw(SegmovfeatState *fs) {
249 if (fs->redraw_needed) {
250 fs->redraw_needed= 0;
251 redraw_needed_count--;
254 XCALL( XCopyArea, "redraw",
255 (d, bg_pixmap, w, fs->whole.gc,
256 fs->whole.x, fs->whole.y,
257 fs->whole.width, fs->whole.height,
258 fs->whole.x, fs->whole.y) );
260 src= &fs->posns[fs->posn][fs->flags.inv][fs->flags.det];
261 XCALL( XCopyArea, "redraw",
262 (d, src->pm, w, fs->whole.gc,
263 0,0, src->width, src->height,
266 if (fs->flags.trainown && src && src->edge.x >= 0) {
267 gcv.foreground= fs->flags.trainown>1 ? train_pixel : owned_pixel;
268 XCALL( XChangeGC, "train/own",
269 (d, src->edge.gc, GCForeground, &gcv) );
270 XCALL( XFillRectangle, "train/own",
272 src->edge.x, src->edge.y,
273 src->edge.width, src->edge.height) );
277 static void redraw_as_needed(void) {
280 for (fs= states_head;
283 if (fs->redraw_needed)
285 assert(!redraw_needed_count);
288 static Bool evpredicate_always(Display *d, XEvent *ev, XPointer a) {
292 static void xlib_process(void) {
297 xst= XCheckIfEvent(d,&ev,evpredicate_always,0);
299 if (!redraw_needed_count || expose_count)
306 case Expose: xlib_expose(&ev.xexpose); break;
307 case NoExpose: break;
308 default: die("unrequested event type %d\n",ev.type);
313 static void *xlib_readable(oop_source *evts, int fd,
314 oop_event evt, void *cl_v) {
319 static int thiswordeatonechar(ParseState *ps, int c) {
320 if (ps->thisword[0] == c) {
321 ps->thisword++; ps->lthisword--;
327 static void loadmask(MaskState *out, const PlanPixmapDataRef *ppd,
328 XGCValues *gcv, long gcv_mask) {
329 static XpmColorSymbol coloursymbols[2]= {
330 { (char*)"space", 0, 0 },
331 { (char*)"mark", 0, 1 }
334 XpmAttributes mattribs;
339 mattribs.valuemask= XpmDepth | XpmColorSymbols;
341 mattribs.colorsymbols= coloursymbols;
342 mattribs.numsymbols= sizeof(coloursymbols) / sizeof(*coloursymbols);
343 XPMCALL( XpmCreatePixmapFromData, "mask",
344 (d,w, (char**)ppd->d, &pm,0, &mattribs) );
345 out->width= mattribs.width;
346 out->height= mattribs.height;
348 gcv->clip_x_origin= out->x;
349 gcv->clip_y_origin= out->y;
351 out->gc= XCreateGC(d,w,
352 gcv_mask | GCClipXOrigin | GCClipYOrigin | GCClipMask,
354 XCALL( XFreePixmap, "mask", (d,pm) );
357 /*---------- stdin input handling ----------*/
359 static void stdin_eof(void) { exit(0); }
360 static int stdin_badcmd(void) { exit(8); }
362 static void stdin_input_line(ParseState *ps) {
363 const char *slash, *movfeatname;
364 int invert, det, trainown, segment_ix, movfeat_ix, lmovfeatname;
366 const PlanSegmentData *segment_d;
367 const PlanSegmovfeatData *movfeat_d;
372 if (!thiswordstrcmp(ps,"off")) {
378 thiswordeatonechar(ps,'t') ? 2 :
379 thiswordeatonechar(ps,'f') ? 1 : 0;
380 invert= thiswordeatonechar(ps,'i');
381 det= (!thiswordstrcmp(ps,"on") ? 0 :
382 !thiswordstrcmp(ps,"det") ? 1 :
383 (badcmd(ps,"unknown command"),-1));
386 slash= memchr(ps->thisword, '/', ps->lthisword);
388 movfeatname= slash + 1;
389 lmovfeatname= (ps->thisword + ps->lthisword) - movfeatname;
390 ps->lthisword= slash - ps->thisword;
395 segment_ix= lstrpdbsearch_segment(ps->thisword,ps->lthisword);
396 segment_d= &ui_plan_data.segments[segment_ix];
398 movfeat_ix= lstrpdbsearch_movfeat(movfeatname, lmovfeatname, segment_d);
399 movfeat_d= &segment_d->movfeats[movfeat_ix];
402 if (invert<0) badcmd(0,"off may not take movfeatpos");
403 ps_neednumber(ps, &posn, 0, movfeat_d->n_posns-1, "movfeatpos");
405 if (invert>=0 && movfeat_d->n_posns > 1) {
406 posn= movfeat_d->n_posns;
414 fs= &state[segment_ix].mfs[movfeat_ix];
417 fs->flags.inv= invert;
423 fs->flags.trainown= trainown;
429 static const InputStream stdin_is= {
430 "stdin", stdin_eof, stdin_input_line, stdin_badcmd
433 /*---------- multiplexer client ----------*/
435 static OutBufferChain sock= { (char*)"multiplexer socket", -1 };
437 static void sockvprintf(const char *fmt, va_list al)
438 __attribute__((format(printf,1,0)));
439 static void sockprintf(const char *fmt, ...)
440 __attribute__((format(printf,1,2)));
442 static void sockvprintf(const char *fmt, va_list al) {
443 ovprintf(&sock,fmt,al);
445 static void sockprintf(const char *fmt, ...) {
452 static int sock_clientconnect(const char *node, const char *service) {
453 struct addrinfo *aires, *try, hints;
454 char niaddrbuf[256], niportbuf[64];
457 memset(&hints,0,sizeof(hints));
458 hints.ai_family= PF_UNSPEC;
459 hints.ai_socktype= SOCK_STREAM;
460 r= getaddrinfo(node,service,&hints,&aires);
461 if (r) die("getaddrinfo node `%s' service `%s' failed: %s\n",
462 node,service,gai_strerror(r));
464 for (try=aires; try; try=try->ai_next) {
465 assert(try->ai_socktype == SOCK_STREAM);
467 r= getnameinfo(try->ai_addr, try->ai_addrlen,
468 niaddrbuf, sizeof(niaddrbuf),
469 niportbuf, sizeof(niportbuf),
470 NI_NUMERICHOST|NI_NUMERICSERV);
473 printf("trying %s,%s... ",niaddrbuf,niportbuf);
476 sock= socket(try->ai_family, SOCK_STREAM, try->ai_protocol);
478 printf("couldn't create socket: %s\n",strerror(errno));
482 r= connect(sock, try->ai_addr, try->ai_addrlen);
484 printf("connected\n");
488 printf("connect failed: %s\n",strerror(errno));
495 static void sock_eof(void) { die("EOF on multiplexer connection"); }
496 static int sock_badcmd(void) { return -1; }
498 /*---------- multiplexer protocol ----------*/
501 struct { struct TrainState *next, *back; } others;
506 static struct { TrainState *head, *tail; } trains;
508 #define FOR_S for (s=0; s<NSEGMENTS; s++)
510 static void mx_clear_updated(void) {
513 state[s].flags.updated_tmp= 0;
516 static void mx_redraw_feat(int s, int f) {
517 SegState *ss= &state[s];
518 SegmovfeatState *fs= &ss->mfs[f];
519 fs->flags= ss->flags;
520 fs->flags.on= stastate > Sta_Off && poweron;
521 if (stastate==Sta_Resolving)
522 fs->flags.trainown= ss->flags.resolution_problem ? 2 : 0;
526 static void mx_redraw_seg(int s) {
528 assert(!!state[s].flags.trainown == !!state[s].owner);
529 for (f=0; f < ui_plan_data.segments[s].n_movfeats; f++)
533 static void mx_redraw_all(void) {
539 static int ps_needsegment(ParseState *ps) {
540 int r= ps_needword(ps); if (r) return -1;
541 return lstrpdbsearch_segment(ps->thisword,ps->lthisword);
544 static void si_detect(ParseState *ps) {
548 s= ps_needsegment(ps); if (s<0) return;
549 r= ps_neednumber(ps,&dl,0,1,"detection flag"); if (r) return;
550 state[s].flags.det= dl;
554 static void si_polarity(ParseState *ps) {
559 if (*ps->remain++ != '<') { badcmd(ps,"missing <"); return; }
561 end= strchr(ps->remain,'>');
562 if (!end) { badcmd(ps,"missing >"); return; }
564 while (ps->remain < end) {
565 delim= memchr(ps->remain, ',', end - ps->remain);
566 if (!delim) delim= end;
568 ps->thisword= ps->remain;
569 ps->lthisword= delim - ps->remain;
572 s= lstrpdbsearch_segment(ps->thisword,ps->lthisword); if (s<0) continue;
573 state[s].flags.updated_tmp= 1;
576 if (state[s].flags.inv == state[s].flags.updated_tmp)
578 state[s].flags.inv= state[s].flags.updated_tmp;
583 static void si_movpos(ParseState *ps) {
586 s= ps_needsegment(ps); if (s<0) return;
587 r= ps_needword(ps); if (r) return;
588 if (thiswordstrcmp(ps,"feat")) { badcmd(ps,"weird movpos"); return; }
590 r= ps_needword(ps); if (r) return;
591 f= lstrpdbsearch_movfeat(ps->thisword, ps->lthisword,
592 &ui_plan_data.segments[s]); if (f<0) return;
594 n_posns= ui_plan_data.segments[s].movfeats[f].n_posns;
595 if (ps->remain[0]=='?') goto unknown;
596 r= ps_neednumber(ps,&pl,0,n_posns-1,"movfeat posn"); if (r) goto unknown;
597 state[s].mfs[f].posn= pl;
602 state[s].mfs[f].posn= n_posns;
606 static void si_on(ParseState *ps) {
611 static void si_off(ParseState *ps) {
616 static void si_train(ParseState *ps) {
623 r= ps_needword(ps); /* <train> */ if (r) return;
625 /* atomise the train name */
626 for (train=trains.head;
628 train= train->others.next)
629 if (!thiswordstrcmp(ps,train->name))
632 train= mmalloc(sizeof(*train));
633 train->name= mmalloc(ps->lthisword+1);
634 memcpy(train->name,ps->thisword,ps->lthisword);
635 train->name[ps->lthisword]= 0;
636 DLIST2_APPEND(trains,train,others);
639 r= ps_needword(ps); if (r) return;
640 if (thiswordstrcmp(ps,"has")) { badcmd(ps,"weird train"); return; }
641 while (ps_word(ps) >= 0) {
642 sl= strcspn(ps->thisword, "/.!*~#+");
643 if (sl > ps->lthisword) sl= ps->lthisword;
645 if (*seg=='-') { seg++; sl--; }
646 s= lstrpdbsearch_segment(seg,sl); if (s<0) continue;
647 lastchar= ps->thisword[ps->lthisword-1];
648 state[s].owner= train;
649 state[s].flags.updated_tmp= 1;
650 state[s].flags.trainown= 1 + (lastchar=='!' || lastchar=='*');
653 if (state[s].flags.updated_tmp) {
655 } else if (state[s].owner==train) {
657 state[s].flags.trainown= 0;
663 typedef struct MuxEventInfo MuxEventInfo;
664 typedef void MuxEventFn(ParseState *ps);
666 struct MuxEventInfo {
667 const char *prefix; /* 0: sentinel */
668 const char *remainpat; /* 0: no pattern in select needed */
669 MuxEventFn *fn; /* 0: just ignore matching messages */
671 static const MuxEventInfo muxeventinfos[];
673 static void si_stastate(ParseState *ps) {
675 const char *const *new_stastate;
677 new_stastate= some_needword_lookup(ps, stastate_names, "stastate");
678 stastate= new_stastate ? new_stastate - stastate_names : 0;
681 state[s].flags.resolution_problem= 0;
683 if (stastate <= Sta_Resolving) {
685 state[s].flags.det= 0;
686 state[s].flags.trainown= 0;
693 static void mx_resolution_problem(int s) {
694 state[s].flags.resolution_problem= 1;
697 static void si_resolution_inexplicable(ParseState *ps) {
699 s= ps_needsegment(ps); if (s<0) return;
700 mx_resolution_problem(s);
702 static void si_resolution_mispositioned(ParseState *ps) {
704 r= ps_needword(ps); /* head|tail */ if (r) return;
705 r= ps_needword(ps); /* <train> */ if (r) return;
706 s= ps_needsegment(ps); if (s<0) return;
707 mx_resolution_problem(s);
710 static void si_connected(ParseState *ps) {
711 const MuxEventInfo *mxi;
715 sockprintf("select-replay");
716 for (mxi=muxeventinfos; mxi->prefix; mxi++) {
720 for (p=mxi->prefix; (c=*p); p++) {
726 sockprintf("%s",mxi->remainpat);
728 sockprintf(" ~|*\n");
730 /* set the fixed moveable features */
731 const SegmentInfo *segi;
732 const MovFeatInfo *mfi;
733 const PlanSegmentData *planseg;
734 const PlanSegmovfeatData *planfeat;
737 for (segn=0; segn<info_nsegments; segn++) {
738 segi= &info_segments[segn];
739 if (!segi->n_fixedmovfeats) continue;
740 for (s=0; s<NSEGMENTS; s++)
741 if (!strcmp(segi->pname, (planseg=&ui_plan_data.segments[s])->segname))
743 die("layout data segment %s not found\n",segi->pname);
745 for (mfn=0, mfi= segi->movfeats + segi->n_movfeats;
746 mfn < segi->n_fixedmovfeats;
748 for (f=1; f<planseg->n_movfeats; f++)
749 if (!strcmp(mfi->pname, (planfeat=&planseg->movfeats[f])->movfeatname))
751 die("layout data movfeat %s/%s not found\n",segi->pname,mfi->pname);
753 state[s].mfs[f].posn= mfi->posns;
754 if (debug) fprintf(debug,"fixed %s/%s=%d\n",
755 segi->pname,mfi->pname,mfi->posns);
760 static void si_fatal(ParseState *ps) {
761 die("multiplexer reports problem: %.*s\n",
762 (int)badcmdreport_recsz, badcmdreport_data);
764 static void si_ack(ParseState *ps) {
765 ps_needword(ps); /* command */
766 ps_needword(ps); /* status */
767 if (thiswordstrcmp(ps,"ok")) si_fatal(0);
770 static const MuxEventInfo muxeventinfos[]= {
771 { "?detect", "", si_detect },
772 { "?picio out polarity", "", si_polarity },
773 { "?movpos", "_*_feat", si_movpos },
774 { "?picio out on", "", si_on },
775 { "?picio out off", "", si_off },
776 { "?train", "_*_has", si_train },
778 { "?stastate", "", si_stastate },
780 { "?resolution inexplicable", "", si_resolution_inexplicable },
781 { "?resolution mispositioned", "", si_resolution_mispositioned },
783 { "=connected", "", si_connected },
784 { "=permission", "", 0 },
786 { "+executing", 0, 0 },
787 { "+ack", 0, si_ack },
788 { "+nak", 0, si_fatal },
789 { "=failed", 0, si_fatal },
790 { "=denied", 0, si_fatal },
794 static void sock_input_line(ParseState *ps) {
795 const MuxEventInfo *mxi;
796 const char *got, *expected;
798 if (!ps->remain || !ps->remain[0])
800 ps->thisword= ps->remain;
801 for (mxi=muxeventinfos; mxi->prefix; mxi++) {
803 expected= mxi->prefix;
804 l= ps->lthisword= strlen(expected);
805 if (*expected=='?') { got++; expected++; l--; }
806 if (memcmp(got, expected, l)) continue;
807 if (!got[l] || got[l]==' ') goto found;
811 if (!mxi->fn) return;
813 if ((c= *ps->remain)) { assert(c==' '); ps->remain++; }
814 if (debug) fprintf(debug,"calling <%s> with <%.*s|%s>\n",
815 mxi->prefix, ps->lthisword,ps->thisword, ps->remain);
819 static const InputStream sock_is= {
820 "multiplexer connection",
826 /*---------- main program including much of the initialisation ----------*/
828 int main(int argc, const char *const *argv) {
831 XpmAttributes mattribs;
832 XWindowAttributes wattribs;
833 int segment_ix, movfeat_ix, posn, invert, det, oor, infd;
838 const PlanSegmentData *segment_d;
839 const PlanSegmovfeatData *movfeat_d;
842 sys_events= oop_sys_new(); if (!sys_events) diee("oop_sys_new");
843 events= oop_sys_source(sys_events); assert(events);
845 while ((arg= *++argv)) {
846 if (!strcmp(arg,"--sizes")) {
847 printf("%d\n%d\n", ui_plan_data.xsz, ui_plan_data.ysz);
848 if (ferror(stdout) || fflush(stdout)) diee("print stdout");
850 } else if (!strcmp(arg,"--debug")) {
852 } else if (arg[0]=='@') {
856 comma= strchr(node,',');
861 service= STR(TRAINMX_PORT);
863 sock.fd= sock_clientconnect(node,service);
864 if (sock.fd<0) die("unable to connect to multiplexer");
866 if (comma) *comma= ',';
867 } else if (arg[0]=='-') {
868 die("invalid option(s)");
870 errno=0; wspec= strtoul(arg,&ep,0);
871 if (errno || ep==arg || *ep || wspec==None) die("bad windowid");
875 d= XOpenDisplay(0); if (!d) die("XOpenDisplay failed");
878 w= XCreateSimpleWindow(d, DefaultRootWindow(d),
879 0,0, ui_plan_data.xsz, ui_plan_data.ysz,
881 if (w == None) diex("XCreateSimpleWindow", "initial");
886 XCALL( XGetWindowAttributes, 0, (d,w,&wattribs) );
888 XPMCALL( XpmCreatePixmapFromData, "background",
889 (d,w, (char**)ui_plan_data.background, &bg_pixmap,0,0) );
891 XCALL( XSetWindowBackgroundPixmap, 0, (d,w,bg_pixmap) );
893 XCALL( XAllocNamedColor, "white",
894 (d, wattribs.colormap, "#ffffff",
896 train_pixel= colour.pixel;
898 XCALL( XAllocNamedColor, "owned",
899 (d, wattribs.colormap, "#a0a0a0",
901 owned_pixel= colour.pixel;
903 state= mmalloc(sizeof(*state) * NSEGMENTS);
904 for (segment_ix= 0, segment_d= ui_plan_data.segments;
905 segment_ix < ui_plan_data.n_segments;
906 segment_ix++, segment_d++) {
907 state[segment_ix].flags.on= 0;
908 state[segment_ix].flags.inv= 0;
909 state[segment_ix].flags.det= 0;
910 state[segment_ix].flags.trainown= 0;
911 state[segment_ix].flags.updated_tmp= 0;
912 state[segment_ix].mfs= fs=
913 mmalloc(sizeof(*state[segment_ix].mfs) * segment_d->n_movfeats);
914 for (movfeat_ix= 0, movfeat_d= segment_d->movfeats;
915 movfeat_ix < segment_d->n_movfeats;
916 movfeat_ix++, movfeat_d++, fs++) {
917 fs->next= states_head; states_head= fs;
918 fs->flags= state[segment_ix].flags;
919 fs->posn= movfeat_d->n_posns;
920 if (fs->posn==1) fs->posn= 0;
921 fs->redraw_needed= 0;
923 loadmask(&fs->whole, &movfeat_d->mask, &gcv, 0);
925 fs->posns= mmalloc(sizeof(*fs->posns)*(fs->posn+1));
926 for (posn= 0; posn <= fs->posn; posn++)
927 for (invert=0; invert<2; invert++)
928 for (det=0; det<2; det++) {
929 PosnState *ps= &fs->posns[posn][invert][det];
930 const PlanPixmapOnData *ppod=
931 posn < movfeat_d->n_posns
932 ? &movfeat_d->posns[posn] : 0;
933 const PlanPixmapDataRef *ppdr= ppod
934 ? &ppod->on[invert][det]
935 : &movfeat_d->unknown[invert][det];
938 mattribs.valuemask= 0;
939 XPMCALL( XpmCreatePixmapFromData, "main",
944 ps->width= mattribs.width;
945 ps->height= mattribs.height;
947 loadmask(&ps->edge, &ppod->pedge, &gcv, 0);
964 events->on_fd(events, infd, OOP_EXCEPTION, some_exception,
965 (void*)instream->name);
967 rd= oop_rd_new_fd(events, infd, 0,0);
968 if (!rd) diee("oop_rd_new_fd");
970 oor= oop_rd_read(rd, OOP_RD_STYLE_GETLINE, 1024,
971 input_ifok,0, input_iferr,0);
972 if (oor) diee("oop_rd_read");
974 events->on_fd(events, ConnectionNumber(d), OOP_READ, xlib_readable, 0);
975 events->on_fd(events, ConnectionNumber(d), OOP_EXCEPTION, some_exception,
976 (void*)"xserver connection");
978 XCALL( XSelectInput, 0, (d,w, ExposureMask) );
981 XCALL( XClearArea, "initial", (d,w, 0,0,0,0, True) );
983 XCALL( XMapWindow, 0, (d,w) );
988 oop_sys_run(sys_events);