* protocol on stdin:
* series of lines
* off <segname>[/[<movfeat>]
- * [i]on <segname>[[/<movfeat>] <movpos>]
- * [i]det <segname>[[/<movfeat>] <movpos>]
+ * [t|f][i]on <segname>[[/<movfeat>] <movpos>]
+ * [t|f][i]det <segname>[[/<movfeat>] <movpos>]
*/
#include <stdlib.h>
#include <oop.h>
#include <oop-read.h>
+typedef struct MaskState MaskState;
+struct MaskState {
+ int x, y, width, height;
+ GC gc;
+};
+
+typedef struct PosnState PosnState;
+struct PosnState {
+ int x, y, width, height;
+ Pixmap pm;
+ MaskState edge;
+};
+
typedef struct SegmovfeatState SegmovfeatState;
struct SegmovfeatState {
SegmovfeatState *next;
- int invert, det, posn, x, y, width, height, redraw_needed;
- GC gc;
- Pixmap (*posns)[2/*i*/][2/*det*/];
+ int invert, det, trainown, posn, redraw_needed;
+ MaskState whole;
+ PosnState (*posns)[2/*i*/][2/*det*/];
+ /* posns[n_posns]=unknown if n_posns>1 */
};
oop_source *events;
static oop_source_sys *sys_events;
static Window w;
static int redraw_needed_count, expose_count;
+static Pixmap bg_pixmap;
+static unsigned long train_pixel, owned_pixel;
static void diex(const char *fn, const char *w) __attribute__((noreturn));
static void diex(const char *fn, const char *w) {
min= 0;
maxe= n_items;
for (;;) {
- if (min >= maxe) badcmd(0,"unknown %s",what);
+ if (min >= maxe) badcmd(0,"unknown %s `%.*s'",what,l,str);
try= min + (maxe - min) / 2;
try_item= (const char*)items + itemsz * try;
try_name= *(const char *const *)try_item;
fs= fs->next) {
if (fs->redraw_needed)
continue;
- if (!range_overlap(fs->x, fs->width,
+ if (!range_overlap(fs->whole.x, fs->whole.width,
ev->x, ev->width)) continue;
- if (!range_overlap(fs->y, fs->height,
+ if (!range_overlap(fs->whole.y, fs->whole.height,
ev->y, ev->height)) continue;
fs->redraw_needed= 1;
redraw_needed_count++;
}
static void redraw(SegmovfeatState *fs) {
- Pixmap src;
+ PosnState *src;
+ XGCValues gcv;
if (fs->redraw_needed) {
fs->redraw_needed= 0;
redraw_needed_count--;
}
- if (fs->invert < 0) {
- XCALL( XFillRectangle, "redraw",
- (d,w, fs->gc,
- fs->x, fs->y,
- fs->width, fs->height) );
- } else {
- src= fs->posns[fs->posn][fs->invert][fs->det];
+ src= 0;
+ XCALL( XCopyArea, "redraw",
+ (d, bg_pixmap, w, fs->whole.gc,
+ fs->whole.x, fs->whole.y,
+ fs->whole.width, fs->whole.height,
+ fs->whole.x, fs->whole.y) );
+ if (fs->invert >= 0) {
+ src= &fs->posns[fs->posn][fs->invert][fs->det];
XCALL( XCopyArea, "redraw",
- (d, src, w, fs->gc,
- 0,0, fs->width, fs->height,
- fs->x, fs->y) );
+ (d, src->pm, w, fs->whole.gc,
+ 0,0, src->width, src->height,
+ src->x, src->y) );
+ }
+ if (fs->trainown && src && src->edge.x >= 0) {
+ gcv.foreground= fs->trainown>1 ? train_pixel : owned_pixel;
+ XCALL( XChangeGC, "train/own",
+ (d, src->edge.gc, GCForeground, &gcv) );
+ XCALL( XFillRectangle, "train/own",
+ (d,w, src->edge.gc,
+ src->edge.x, src->edge.y,
+ src->edge.width, src->edge.height) );
}
}
xlib_process();
return OOP_CONTINUE;
}
-
+
+static int thiswordeatonechar(ParseState *ps, int c) {
+ if (ps->thisword[0] == c) {
+ ps->thisword++; ps->lthisword--;
+ return 1;
+ }
+ return 0;
+}
+
static void *stdin_ifok(oop_source *evts, oop_read *cl_read,
oop_rd_event evt, const char *errmsg, int errnoval,
const char *data, size_t recsz, void *cl_v) {
const char *slash, *movfeatname;
ParseState ps;
- int invert, det, segment_ix, movfeat_ix, lmovfeatname;
+ int invert, det, trainown, segment_ix, movfeat_ix, lmovfeatname;
long posn;
const PlanSegmentData *segment_d;
const PlanSegmovfeatData *movfeat_d;
if (evt != OOP_RD_OK)
return stdin_iferr(evts,cl_read,evt,errmsg,errnoval,data,recsz,cl_v);
+fprintf(stderr,"gui-plan>%.*s<\n",(int)recsz,data);
+
ps.cl= 0;
ps.remain= data;
ps_needword(&ps);
if (!thiswordstrcmp(&ps,"off")) {
invert= -1;
+ trainown= 0;
det= 0;
} else {
- invert= (ps.thisword[0]=='i');
- if (invert) { ps.thisword++; ps.lthisword--; }
+ trainown=
+ thiswordeatonechar(&ps,'t') ? 2 :
+ thiswordeatonechar(&ps,'f') ? 1 : 0;
+ invert= thiswordeatonechar(&ps,'i');
det= (!thiswordstrcmp(&ps,"on") ? 0 :
!thiswordstrcmp(&ps,"det") ? 1 :
(badcmd(&ps,"unknown command"),-1));
if (invert<0) badcmd(0,"off may not take movfeatpos");
ps_neednumber(&ps, &posn, 0, movfeat_d->n_posns-1, "movfeatpos");
} else {
- if (invert>=0 && movfeat_d->n_posns > 1) badcmd(0,"movfeatpos needed");
- posn= 0;
+ if (invert>=0 && movfeat_d->n_posns > 1) {
+ posn= movfeat_d->n_posns;
+ } else {
+ posn= 0;
+ }
}
ps_neednoargs(&ps);
fs= &state[segment_ix][movfeat_ix];
fs->invert= invert;
fs->det= det;
+ fs->trainown= trainown;
fs->posn= posn;
redraw(fs);
return OOP_CONTINUE;
}
-int main(int argc, const char *const *argv) {
+static void loadmask(MaskState *out, const PlanPixmapDataRef *ppd,
+ XGCValues *gcv, long gcv_mask) {
static XpmColorSymbol coloursymbols[2]= {
{ (char*)"space", 0, 0 },
{ (char*)"mark", 0, 1 }
};
+ XpmAttributes mattribs;
+ Pixmap pm;
+
+ out->x= ppd->x;
+ out->y= ppd->y;
+ mattribs.valuemask= XpmDepth | XpmColorSymbols;
+ mattribs.depth= 1;
+ mattribs.colorsymbols= coloursymbols;
+ mattribs.numsymbols= sizeof(coloursymbols) / sizeof(*coloursymbols);
+ XPMCALL( XpmCreatePixmapFromData, "mask",
+ (d,w, (char**)ppd->d, &pm,0, &mattribs) );
+ out->width= mattribs.width;
+ out->height= mattribs.height;
+
+ gcv->clip_x_origin= out->x;
+ gcv->clip_y_origin= out->y;
+ gcv->clip_mask= pm;
+ out->gc= XCreateGC(d,w,
+ gcv_mask | GCClipXOrigin | GCClipYOrigin | GCClipMask,
+ gcv);
+ XCALL( XFreePixmap, "mask", (d,pm) );
+}
+
+int main(int argc, const char *const *argv) {
oop_read *rd;
const char *arg;
- Pixmap bg_pixmap;
- Pixmap mask;
XpmAttributes mattribs;
XWindowAttributes wattribs;
- XColor background_colour;
int segment_ix, movfeat_ix, posn, invert, det, oor;
+ XGCValues gcv;
+ XColor colour;
SegmovfeatState *fs;
const PlanSegmentData *segment_d;
const PlanSegmovfeatData *movfeat_d;
- XGCValues gcv;
d= XOpenDisplay(0); if (!d) die("XOpenDisplay failed");
if ((arg= *++argv)) {
char *ep;
- if (arg[0]=='-') die("no options understood");
+
+ if (!strcmp(arg,"--sizes")) {
+ printf("%d\n%d\n", ui_plan_data.xsz, ui_plan_data.ysz);
+ if (ferror(stdout) || fflush(stdout)) diee("print stdout");
+ exit(0);
+ }
+
+ if (arg[0]=='-') die("invalid option(s)");
errno=0; w= strtoul(arg,&ep,0);
if (errno || ep==arg || *ep) die("bad windowid");
(d,w, (char**)ui_plan_data.background, &bg_pixmap,0,0) );
XCALL( XSetWindowBackgroundPixmap, 0, (d,w,bg_pixmap) );
- XCALL( XFreePixmap, "background", (d,bg_pixmap) );
- XCALL( XAllocNamedColor, "background",
- (d, wattribs.colormap, ui_plan_colour_off,
- &background_colour, &background_colour) );
+ XCALL( XAllocNamedColor, "white",
+ (d, wattribs.colormap, "#ffffff",
+ &colour, &colour) );
+ train_pixel= colour.pixel;
+
+ XCALL( XAllocNamedColor, "owned",
+ (d, wattribs.colormap, "#a0a0a0",
+ &colour, &colour) );
+ owned_pixel= colour.pixel;
state= mmalloc(sizeof(*state) * ui_plan_data.n_segments);
for (segment_ix= 0, segment_d= ui_plan_data.segments;
movfeat_ix++, movfeat_d++, fs++) {
fs->next= states_head; states_head= fs;
fs->invert= -1;
- fs->det= fs->posn= 0;
- fs->x= movfeat_d->x;
- fs->y= movfeat_d->y;
+ fs->det= 0;
+ fs->trainown= 0;
+ fs->posn= movfeat_d->n_posns;
+ if (fs->posn==1) fs->posn= 0;
fs->redraw_needed= 0;
- mattribs.valuemask= XpmDepth | XpmColorSymbols;
- mattribs.depth= 1;
- mattribs.colorsymbols= coloursymbols;
- mattribs.numsymbols= sizeof(coloursymbols) / sizeof(*coloursymbols);
- XPMCALL( XpmCreatePixmapFromData, "mask",
- (d,w, (char**)movfeat_d->off, &mask,0, &mattribs) );
- fs->width= mattribs.width;
- fs->height= mattribs.height;
-
- gcv.clip_x_origin= fs->x;
- gcv.clip_y_origin= fs->y;
- gcv.clip_mask= mask;
- gcv.foreground= background_colour.pixel;
- fs->gc= XCreateGC(d,w,
- GCClipXOrigin | GCClipYOrigin
- | GCClipMask | GCForeground,
- &gcv);
- XCALL( XFreePixmap, "mask", (d,mask) );
-
- fs->posns= mmalloc(sizeof(*fs->posns)*movfeat_d->n_posns);
- for (posn= 0; posn < movfeat_d->n_posns; posn++)
+
+ loadmask(&fs->whole, &movfeat_d->mask, &gcv, 0);
+
+ fs->posns= mmalloc(sizeof(*fs->posns)*(fs->posn+1));
+ for (posn= 0; posn <= fs->posn; posn++)
for (invert=0; invert<2; invert++)
for (det=0; det<2; det++) {
+ PosnState *ps= &fs->posns[posn][invert][det];
+ const PlanPixmapOnData *ppod=
+ posn < movfeat_d->n_posns
+ ? &movfeat_d->posns[posn] : 0;
+ const PlanPixmapDataRef *ppdr= ppod
+ ? &ppod->on[invert][det]
+ : &movfeat_d->unknown[invert][det];
+ ps->x= ppdr->x;
+ ps->y= ppdr->y;
+ mattribs.valuemask= 0;
XPMCALL( XpmCreatePixmapFromData, "main",
(d,w,
- (char**)(movfeat_d->posns[posn].a[invert][det]),
- &fs->posns[posn][invert][det],
- 0,0) );
+ (char**)ppdr->d,
+ &ps->pm,
+ 0, &mattribs) );
+ ps->width= mattribs.width;
+ ps->height= mattribs.height;
+ if (ppod) {
+ loadmask(&ps->edge, &ppod->pedge, &gcv, 0);
+ } else {
+ ps->edge.x= -1;
+ ps->edge.gc= None;
+ }
}
}
}