*.d
proto-expanded
auproto-*
+gui-plan
include ../common.make
include ../cprogs.make
-TARGETS= hostside hostside-old
+TARGETS= hostside hostside-old gui-plan
all: $(TARGETS)
-hostside-old: serialio.o nmra.o main.o encode.o
+hostside-old: serialio.o nmra.o main.o encode.o utils.o
$(LINK)
-hostside: hostside.o serialio.o client.o obc.o commands.o \
+hostside: hostside.o serialio.o client.o obc.o commands.o utils.o \
nmra.o encode.o retransmit.o output.o auproto-pic.o \
+ parseutils.o \
-loop
$(LINK)
proto-expanded: ../cebpic/README.protocol
expand <$< $o
+gui-plan: gui-plan.o utils.o parseutils.o ../layout/ui-plan-bot.o \
+ __oop-read-copy.o -loop
+ $(LINK) -L/usr/X11R6/lib -lXpm -lX11
+
commands.o auproto-pic.o: auproto-pic.h
auproto-%: parse-proto-spec proto-expanded skelproto-%
%.c: layoutinfo.h
-safety: safety.o utils.o ../layout/ours.layout-data.o
+safety: safety.o utils.o trackloc.o ../layout/ours.layout-data.o
$(LINK)
clean:
--- /dev/null
+/* read.c, liboop, copyright 2000 Ian jackson
+
+ This is free software; you can redistribute it and/or modify it under the
+ terms of the GNU Lesser General Public License, version 2.1 or later.
+ See the file COPYING for details. */
+
+#include "oop.h"
+#include "oop-read.h"
+
+#include <string.h>
+#include <errno.h>
+#include <assert.h>
+#include <limits.h>
+
+#undef MIN /* for systems that define it */
+#define MIN(a,b) ((a)<(b) ? (a) : (b))
+
+static void *on_time(oop_source*, struct timeval, void*);
+static void *on_readable(oop_source*, oop_readable*, void*);
+static void *on_process(oop_source*, oop_read*, int try_read);
+
+static int set_time_ifbuf(oop_source *oop, oop_read *rd);
+static void cancel_time(oop_source *oop, oop_read *rd);
+
+const oop_rd_style OOP_RD_STYLE_GETLINE[]= {{
+ OOP_RD_DELIM_STRIP,'\n', OOP_RD_NUL_FORBID, OOP_RD_SHORTREC_EOF,
+}};
+const oop_rd_style OOP_RD_STYLE_BLOCK[]= {{
+ OOP_RD_DELIM_NONE, 0, OOP_RD_NUL_PERMIT, OOP_RD_SHORTREC_EOF,
+}};
+const oop_rd_style OOP_RD_STYLE_IMMED[]= {{
+ OOP_RD_DELIM_NONE, 0, OOP_RD_NUL_PERMIT, OOP_RD_SHORTREC_SOONEST,
+}};
+
+struct oop_read {
+ /* set at creation time: */
+ oop_source *oop;
+ oop_readable *ra;
+ char *userbuf;
+ /* persistent state */
+ oop_rd_bufctl_op readahead; /* _ENABLE or _DISABLE */
+ char *allocbuf;
+ size_t alloc, used, discard;
+ size_t neednotcheck; /* data we've already searched for delimiter */
+ int displacedchar; /* >=0, first unused */
+ /* arguments to oop_rd_read */
+ oop_rd_style style;
+ size_t maxrecsz;
+ oop_rd_call *call_ok, *call_err;
+ void *data_ok, *data_err;
+};
+
+/* Buffer is structured like this if displacedchar>=0 and delim found:
+ *
+ * done stuff, displaced readahead - read unused
+ * we've called delimiter| but not yet buffer
+ * back for || returned space
+ * ddddddddddddddddddddddDOaaaaaaaaaaaaaaaaaaa____________
+ * <------- discard ----->
+ * <----------------------- used ------------>
+ * <------------------------------------- alloc --------->
+ *
+ * If displacedchar>=0 then the the first character of readahead has
+ * been displaced by a nul byte and is stored in displacedchar. If
+ * _DELIM_STRIP and the delimiter is found then the nul overwrites the
+ * delimiter.
+ *
+ * Buffer when full {this,max} may need
+ * DELIM found? <-recval-> recdata buffer required readahead
+ * NONE n/a ddddddddddOaaa_ recsz recdata+1 == recsz+1 maxrecsz
+ * KEEP Yes dddddddddDOaaa_ recsz recdata+1 == recsz+1 maxrecsz
+ * KEEP No ddddddddddOaaa_ recsz recdata+1 == recsz+1 maxrecsz
+ * STRIP Yes dddddddddd0aaaa recsz+1 recdata == recsz+1 maxrecsz+1
+ * STRIP No ddddddddddOaaaa recsz recdata+1 == recsz+1 maxrecsz+1
+ *
+ * Key: d = data to be returned
+ * D = delimiter, being returned
+ * a = readahead, not to be returned
+ * O = readahead character displaced by a nul
+ * 0 = delimiter replaced by a nul
+ * _ = unused
+ */
+
+static const char *const eventstrings_nl[]= {
+ "INTERNAL ERROR (_nl _OK) please report",
+ "End of file",
+ "Missing newline at end of file",
+ "Line too long",
+ "Nul byte",
+ "Nul byte, in line which is also too long",
+ "INTERNAL ERROR (_nl _SYSTEM) please report"
+};
+
+static const char *const eventstrings_other[]= {
+ "Record read successfully",
+ "End of file",
+ "Incomplete record at end of file",
+ "Record too long",
+ "Nul byte",
+ "Nul byte in record which is also too long",
+ "System error"
+};
+
+oop_read *oop_rd_new(oop_source *oop, oop_readable *ra, char *buf, size_t bufsz) {
+ oop_read *rd= 0;
+
+ assert(buf ? bufsz>=2 : !bufsz);
+
+ rd= oop_malloc(sizeof(*rd)); if (!rd) goto x_fail;
+ rd->oop= oop;
+ rd->ra= ra;
+ rd->userbuf= buf;
+ rd->readahead= OOP_RD_BUFCTL_ENABLE;
+ rd->allocbuf= 0;
+ rd->used= 0;
+ rd->alloc= buf ? bufsz : 0;
+ rd->discard= 0;
+ rd->neednotcheck= 0;
+ rd->displacedchar= -1;
+ rd->style= *OOP_RD_STYLE_IMMED;
+
+ return rd;
+
+x_fail:
+ oop_free(rd);
+ return 0;
+}
+
+static int set_time_ifbuf(oop_source *oop, oop_read *rd) {
+ if (rd->used > rd->discard)
+ return oop->on_time(oop,OOP_TIME_NOW,on_time,rd), 0; /* fixme */
+ return 0;
+}
+static void cancel_time(oop_source *oop, oop_read *rd) {
+ oop->cancel_time(oop,OOP_TIME_NOW,on_time,rd);
+}
+static int set_read(oop_source *oop, oop_read *rd) {
+ return rd->ra->on_readable(rd->ra,on_readable,rd), 0; /* fixme */
+}
+static void cancel_read(oop_source *oop, oop_read *rd) {
+ rd->ra->on_cancel(rd->ra);
+}
+
+int oop_rd_read(oop_read *rd, const oop_rd_style *style, size_t maxrecsz,
+ oop_rd_call *ifok, void *data_ok,
+ oop_rd_call *iferr, void *data_err) {
+ oop_source *oop= rd->oop;
+ int er;
+
+ cancel_time(oop,rd);
+ cancel_read(oop,rd);
+
+ if (style->delim_mode == OOP_RD_DELIM_NONE ||
+ rd->style.delim_mode == OOP_RD_DELIM_NONE ||
+ style->delim != rd->style.delim)
+ rd->neednotcheck= 0;
+
+ rd->style= *style;
+ rd->maxrecsz= maxrecsz;
+ rd->call_ok= ifok; rd->data_ok= data_ok;
+ rd->call_err= iferr; rd->data_err= data_err;
+
+ er= set_read(oop,rd); if (er) return er;
+ er= set_time_ifbuf(oop,rd); if (er) return er;
+ return 0;
+}
+
+void oop_rd_delete(oop_read *rd) {
+ rd->ra->on_cancel(rd->ra);
+ oop_free(rd->allocbuf);
+ oop_free(rd);
+}
+
+void oop_rd_cancel(oop_read *rd) {
+ cancel_time(rd->oop,rd);
+ cancel_read(rd->oop,rd);
+}
+
+const char *oop_rd_errmsg(oop_read *rd, oop_rd_event event, int errnoval,
+ const oop_rd_style *style) {
+ if (event == OOP_RD_SYSTEM)
+ return strerror(errnoval);
+ else if (style && style->delim_mode != OOP_RD_DELIM_NONE
+ && style->delim == '\n')
+ return eventstrings_nl[event];
+ else
+ return eventstrings_other[event];
+}
+
+static void *on_readable(oop_source *oop, oop_readable *ra, void *rd_void) {
+ oop_read *rd= rd_void;
+
+ assert(oop == rd->oop);
+ assert(ra == rd->ra);
+ return on_process(oop,rd,1);
+}
+
+static void *on_time(oop_source *oop, struct timeval when, void *rd_void) {
+ oop_read *rd= rd_void;
+
+ assert(oop == rd->oop);
+ return on_process(oop,rd,0);
+}
+
+static size_t calc_dataspace(oop_read *rd) {
+ if (rd->style.delim_mode == OOP_RD_DELIM_STRIP) {
+ return rd->alloc;
+ } else {
+ return rd->alloc ? rd->alloc-1 : 0;
+ }
+}
+
+static void *on_process(oop_source *oop, oop_read *rd, int try_read) {
+ oop_rd_event event;
+ int evkind; /* 0=none, -1=error, 1=something */
+ int errnoval, nread, cancelnow;
+ oop_rd_call *call;
+ char *buf, *delimp;
+ const char *errmsg;
+ size_t maxrecsz; /* like in arg to oop_rd_read, but 0 -> large val */
+ size_t maxbufreqd; /* maximum buffer we might possibly want to alloc */
+ size_t readahead; /* max amount of data we might want to readahead */
+ size_t want; /* amount we want to allocate or data we want to read */
+ size_t dataspace; /* amount of buffer we can usefully fill with data */
+ size_t thisrecsz; /* length of the record we've found */
+ size_t thisrecdata; /* length of data representing the record */
+ void *call_data;
+
+ cancel_time(oop,rd);
+
+ if (rd->userbuf) {
+ buf= rd->userbuf;
+ } else {
+ buf= rd->allocbuf;
+ }
+
+ if (rd->discard) {
+ rd->used -= rd->discard;
+ rd->neednotcheck -= rd->discard;
+ memmove(buf, buf + rd->discard, rd->used);
+ rd->discard= 0;
+ }
+ if (rd->displacedchar >= 0) {
+ assert(rd->used > 0);
+ buf[0]= rd->displacedchar;
+ rd->displacedchar= -1;
+ }
+
+ maxrecsz= rd->maxrecsz ? rd->maxrecsz : INT_MAX / 5 /* allows +20 and *4 */;
+ maxbufreqd= maxrecsz+1;
+
+ if (rd->userbuf && maxbufreqd > rd->alloc) {
+ maxrecsz -= (maxbufreqd - rd->alloc);
+ maxbufreqd= rd->alloc;
+ }
+
+ if (rd->style.delim_mode == OOP_RD_DELIM_STRIP) {
+ readahead= maxrecsz+1;
+ } else {
+ readahead= maxrecsz;
+ }
+
+ for (;;) {
+ evkind= 0;
+ event= -1;
+ thisrecdata= thisrecsz= 0;
+ errnoval= 0;
+
+ assert(rd->used <= rd->alloc);
+ dataspace= calc_dataspace(rd);
+
+ if (/* delimiter already in buffer, within max record data ? */
+ rd->style.delim_mode != OOP_RD_DELIM_NONE &&
+ (delimp= memchr(buf + rd->neednotcheck, rd->style.delim,
+ MIN(rd->used, readahead) - rd->neednotcheck))) {
+
+ thisrecsz= (delimp - buf);
+ thisrecdata= thisrecsz+1;
+ if (rd->style.delim_mode == OOP_RD_DELIM_KEEP)
+ thisrecsz= thisrecdata;
+ event= OOP_RD_OK;
+ evkind= +1;
+
+ } else if (rd->used >= readahead) {
+
+ thisrecsz= thisrecdata= maxrecsz;
+ evkind= +1;
+
+ if (rd->style.delim_mode == OOP_RD_DELIM_NONE) {
+ event= OOP_RD_OK;
+ } else {
+ event= OOP_RD_LONG;
+ if (rd->style.shortrec_mode < OOP_RD_SHORTREC_LONG) {
+ evkind= -1;
+ thisrecsz= thisrecdata= 0;
+ }
+ }
+
+ } else if (/* want to return ASAP, and we have something ? */
+ rd->style.shortrec_mode == OOP_RD_SHORTREC_SOONEST &&
+ rd->used > 0 && rd->alloc >= 2) {
+
+ thisrecdata= rd->used;
+ if (thisrecdata == rd->alloc) thisrecdata--;
+ thisrecsz= thisrecdata;
+ event= OOP_RD_OK;
+ evkind= +1;
+
+ }
+
+ want= 0;
+ if (evkind && thisrecdata && thisrecsz >= rd->alloc) {
+ /* Need to make space for the trailing nul */
+ want= rd->alloc+1;
+ } else if (!evkind && !rd->userbuf &&
+ rd->used >= dataspace && rd->alloc < maxbufreqd) {
+ /* Need to make space to read more data */
+ want= rd->alloc + 20;
+ want <<= 2;
+ want= MIN(want, maxbufreqd);
+ }
+
+ if (want) {
+ assert(!rd->userbuf);
+ assert(want <= maxbufreqd);
+
+ buf= oop_realloc(rd->allocbuf,want);
+ if (!buf) {
+ event= OOP_RD_SYSTEM;
+ evkind= -1;
+ errnoval= ENOMEM;
+ thisrecsz= thisrecdata= 0;
+ break;
+ }
+ rd->allocbuf= buf;
+ rd->alloc= want;
+ }
+
+ if (evkind) break; /* OK, process it then */
+
+ if (!try_read) return OOP_CONTINUE; /* But we weren't told it was ready. */
+
+ dataspace= calc_dataspace(rd);
+ want= MIN(dataspace, readahead);
+ assert(rd->used < want);
+
+ errno= 0;
+ nread= rd->ra->try_read(rd->ra, buf+rd->used, want-rd->used);
+ if (errno == EAGAIN) return OOP_CONTINUE;
+
+ if (nread > 0) {
+ rd->neednotcheck= rd->used;
+ rd->used += nread;
+ continue;
+ }
+
+ if (nread < 0) { /* read error */
+
+ event= OOP_RD_SYSTEM;
+ evkind= -1;
+ errnoval= errno;
+ thisrecsz= thisrecdata= rd->used;
+ break;
+
+ } else {
+
+ if (rd->used) {
+ event= OOP_RD_PARTREC;
+ evkind= (rd->style.shortrec_mode == OOP_RD_SHORTREC_FORBID) ? -1 : +1;
+ thisrecsz= thisrecdata= rd->used;
+ } else {
+ event= OOP_RD_EOF;
+ evkind= +1;
+ }
+ break;
+
+ }
+ }
+
+ /* OK, we have an event of some kind */
+
+ /* Nul byte handling */
+ if (thisrecsz > 0 && rd->style.nul_mode != OOP_RD_NUL_PERMIT) {
+ size_t checked;
+ char *nul, *notnul;
+
+ for (checked=0;
+ (nul= memchr(buf+checked,0,thisrecsz-checked));
+ ) {
+ if (rd->style.nul_mode == OOP_RD_NUL_FORBID) {
+ event= OOP_RD_NUL;
+ evkind= -1;
+ thisrecdata= thisrecsz= 0;
+ break;
+ }
+ assert(rd->style.nul_mode == OOP_RD_NUL_DISCARD);
+ for (notnul= nul+1;
+ notnul < buf+thisrecsz && notnul == '\0';
+ notnul++);
+ thisrecsz-= (notnul-nul);
+ checked= nul-buf;
+ memmove(nul,notnul,thisrecsz-checked);
+ }
+ }
+
+ /* Checks that all is well */
+
+ assert(evkind);
+ assert(thisrecsz <= thisrecdata);
+ assert(!rd->maxrecsz || thisrecsz <= rd->maxrecsz);
+ assert(thisrecdata <= rd->used);
+
+ rd->discard= thisrecdata;
+
+ cancelnow= (evkind < 0) || (event == OOP_RD_EOF);
+
+ if (!cancelnow) {
+ errnoval= set_time_ifbuf(oop,rd);
+ if (errnoval) {
+ event= OOP_RD_SYSTEM;
+ evkind= -1;
+ cancelnow= 1;
+ thisrecsz= thisrecdata= 0;
+ rd->discard= 0;
+ }
+ }
+
+ if (evkind < 0) {
+ call= rd->call_err;
+ call_data= rd->data_err;
+ errmsg= oop_rd_errmsg(rd,event,errnoval,&rd->style);
+ } else {
+ call= rd->call_ok;
+ call_data= rd->data_ok;
+ errmsg= 0;
+ }
+
+ if (thisrecdata) {
+ /* We have to fill in a nul byte. */
+ assert(thisrecsz < rd->alloc);
+ if (thisrecsz == thisrecdata && thisrecsz < rd->used)
+ rd->displacedchar= (unsigned char)buf[thisrecdata];
+ buf[thisrecsz]= 0;
+ }
+
+ if (cancelnow)
+ oop_rd_cancel(rd);
+
+ return
+ call(oop,rd, event,errmsg,errnoval,
+ (thisrecdata ? buf : 0), thisrecsz, call_data);
+}
+
+oop_read *oop_rd_new_fd(oop_source *oop, int fd, char *buf, size_t bufsz) {
+ oop_readable *ra;
+ oop_read *rd;
+
+ ra= oop_readable_fd(oop,fd);
+ if (!ra) return 0;
+
+ rd= oop_rd_new(oop,ra,buf,bufsz);
+ if (!rd) { ra->delete_tidy(ra); return 0; }
+
+ return rd;
+}
+
+int oop_rd_delete_tidy(oop_read *rd) {
+ oop_readable *ra= rd->ra;
+ oop_rd_delete(rd);
+ return ra->delete_tidy(ra);
+}
+
+void oop_rd_delete_kill(oop_read *rd) {
+ oop_readable *ra= rd->ra;
+ oop_rd_delete(rd);
+ ra->delete_kill(ra);
+}
owrite(&ps->cl->ch,"\n",1);
}
-void badcmd(ParseState *ps, const char *fmt, ...) {
- va_list al;
- va_start(al,fmt);
- vbadcmd(ps,fmt,al);
- va_end(al);
-}
-
-int ps_word(ParseState *ps) {
- const char *space;
- if (!ps->remain) return 0;
- space= strchr(ps->remain, ' ');
- ps->thisword= ps->remain;
- if (space) {
- ps->lthisword= space - ps->thisword;
- ps->remain= space + 1;
- } else {
- ps->lthisword= strlen(ps->remain);
- ps->remain= 0;
- }
- return 1;
-}
-
-int ps_needword(ParseState *ps) {
- if (!ps_word(ps)) { badcmd(ps,"too few args"); return 0; }
- return 1;
-}
-
-int ps_neednumber(ParseState *ps, long *r, long mi, long mx, const char *wh) {
- char *ep;
- long v;
-
- if (!ps_needword(ps)) return 0;
- errno= 0; v= strtol(ps->thisword,&ep,0);
- if (errno || ep != ps->thisword + ps->lthisword) {
- badcmd(ps,"invalid number for %s",wh);
- return 0;
- }
- if (v < mi || v > mx) {
- badcmd(ps,"%s %ld out of range %ld..%ld",wh,v,mi,mx);
- return 0;
- }
- *r= v;
- return 1;
-}
-
-int ps_neednoargs(ParseState *ps) {
- if (ps->remain) {
- badcmd(ps,"too many arguments");
- return 0;
- }
- return 1;
-}
-
-int ps_needhextoend(ParseState *ps, Byte *d, int *remain_io) {
- Byte *d_end;
- char buf[3], *ep;
-
- d_end= d + *remain_io;
- buf[2]= 0;
-
- if (!ps->remain) { badcmd(ps,"need hex data block"); return 0; }
- for (;;) {
- if (!ps_word(ps)) return 0;
- while (ps->lthisword > 0) {
- if (ps->lthisword & 1) {
- badcmd(ps,"hex data block with odd number of digits in part");
- return 0;
- }
- buf[0]= ps->thisword[0];
- buf[1]= ps->thisword[1];
- if (d >= d_end) { badcmd(ps,"hex data block too long"); return 0; }
- *d++= strtoul(buf,&ep,16);
- if (*ep) { badcmd(ps,"invalid digit in hex data block"); return 0; }
- ps->lthisword -= 2;
- ps->thisword += 2;
- }
- }
-
- *remain_io= d_end - d;
- return 1;
-}
-
-int lstrstrcmp(const char *a, int la, const char *b) {
- int lb= strlen(b);
- if (la != lb) return 1;
- return memcmp(a,b,la);
-}
-
-int thiswordstrcmp(ParseState *ps, const char *b) {
- return lstrstrcmp(ps->thisword, ps->lthisword, b);
-}
-
const void *any_lookup(ParseState *ps, const void *inf, size_t sz) {
const char *tname;
/*
- * usage: gui-plan <windowid>
+ * usage: .../gui-plan [<windowid>]
* protocol on stdin:
- * series of uint32_t's in network byte order
- * top byte is opcode
- * 0x00 off
- * 0x01 on
- * 0x01 detect
- * next byte is movposcomb
- * remaining bytes are segment number
+ * series of lines
+ * off <segname>[/[<movfeat>]
+ * [i]on <segname>[[/<movfeat>] <movpos>]
+ * [i]det <segname>[[/<movfeat>] <movpos>]
*/
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
+#include <errno.h>
+
+#include <X11/Xlib.h>
+#include <X11/xpm.h>
+
+#include "hostside.h"
+#include "../layout/plan-data-format.h"
+
+#include <oop.h>
+#include <oop-read.h>
+
+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*/];
+};
+
+oop_source *events;
+
+static SegmovfeatState **state, *states_head;
+static Display *d;
+static oop_source_sys *sys_events;
+static Window w;
+static int redraw_needed_count, expose_count;
+
+static void diex(const char *fn, const char *w) __attribute__((noreturn));
+static void diex(const char *fn, const char *w) {
+ die("Xlib call failed: %s%s%s%s", fn,
+ (w)?" (":"", (w), (w)?")":"");
+}
+
+#define XCALL(f,w,al) do{ \
+ if (!( (f) al )) \
+ diex(#f, (w)); \
+ }while(0)
+
+static void diexpm(const char *fn, const char *w, int xpmst)
+ __attribute__((noreturn));
+static void diexpm(const char *fn, const char *w, int xpmst) {
+ die("Xpm call failed: %s%s%s%s: %s", fn,
+ (w)?" (":"", (w), (w)?")":"", XpmGetErrorString(xpmst));
+}
+
+#define XPMCALL(f,w,al) do{ \
+ int xpmcall_xpmst; \
+ xpmcall_xpmst= ((f) al); \
+ if (xpmcall_xpmst != XpmSuccess) \
+ diexpm(#f, (w), xpmcall_xpmst); \
+ }while(0)
+
+void vbadcmd(ParseState *ps, const char *fmt, va_list al) {
+ fprintf(stderr,"gui-plan: incorrect input: ");
+ vfprintf(stderr,fmt,al);
+ putc('\n',stderr);
+ exit(8);
+}
+
+static void *stdin_iferr(oop_source *evts, oop_read *stdin_read,
+ oop_rd_event evt, const char *errmsg, int errnoval,
+ const char *data, size_t recsz, void *cl_v) {
+ die("read stdin: %s", oop_rd_errmsg(stdin_read, evt,
+ errnoval, OOP_RD_STYLE_GETLINE));
+ return OOP_CONTINUE;
+}
+
+static int lstrpdbsearch(const char *str, int l,
+ const char *what,
+ const void *items, int n_items,
+ int itemsz) {
+ int min, maxe, try, cmp;
+ const void *try_item;
+ const char *try_name;
+
+ min= 0;
+ maxe= n_items;
+ for (;;) {
+ if (min >= maxe) badcmd(0,"unknown %s",what);
+ try= min + (maxe - min) / 2;
+ try_item= (const char*)items + itemsz * try;
+ try_name= *(const char *const *)try_item;
+ cmp= lstrstrcmp(str, l, try_name ? try_name : "");
+ if (!cmp) return try;
+ if (cmp < 0) maxe= try;
+ else min= try + 1;
+ }
+}
+
+static void *some_exception(oop_source *evts, int fd,
+ oop_event evt, void *cl_v) {
+ die("poll exception on fd %d",fd);
+}
+
+static int range_overlap(int x1, int width1, int x2, int width2) {
+ /* works for y's and heights too, obviously. */
+ int rhs1, rhs2;
+ rhs1= x1 + width1;
+ rhs2= x2 + width2;
+ if (rhs1 <= x2 || rhs2 <= x1) return 0;
+ return 1;
+}
+
+static void xlib_expose(XExposeEvent *ev) {
+ SegmovfeatState *fs;
+
+ expose_count= ev->count;
+ if (!ev->width || !ev->height) return;
+
+ for (fs= states_head;
+ fs;
+ fs= fs->next) {
+ if (fs->redraw_needed)
+ continue;
+ if (!range_overlap(fs->x, fs->width,
+ ev->x, ev->width)) continue;
+ if (!range_overlap(fs->y, fs->height,
+ ev->y, ev->height)) continue;
+ fs->redraw_needed= 1;
+ redraw_needed_count++;
+ }
+}
+
+static void redraw(SegmovfeatState *fs) {
+ Pixmap src;
+
+ 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];
+ XCALL( XCopyArea, "redraw",
+ (d, src, w, fs->gc,
+ 0,0, fs->width, fs->height,
+ fs->x, fs->y) );
+ }
+}
+
+static void redraw_as_needed(void) {
+ SegmovfeatState *fs;
+
+ for (fs= states_head;
+ fs;
+ fs= fs->next)
+ if (fs->redraw_needed)
+ redraw(fs);
+ assert(!redraw_needed_count);
+}
+
+static Bool evpredicate_always(Display *d, XEvent *ev, XPointer a) {
+ return True;
+}
+
+static void xlib_process(void) {
+ XEvent ev;
+ Status xst;
+
+ for (;;) {
+ xst= XCheckIfEvent(d,&ev,evpredicate_always,0);
+ if (!xst) {
+ if (!redraw_needed_count || expose_count)
+ return;
+ redraw_as_needed();
+ continue;
+ }
+
+ switch (ev.type) {
+ case Expose: xlib_expose(&ev.xexpose); break;
+ case NoExpose: break;
+ default: die("unrequested event type %d\n",ev.type);
+ }
+ }
+}
+
+static void *xlib_readable(oop_source *evts, int fd,
+ oop_event evt, void *cl_v) {
+ xlib_process();
+ return OOP_CONTINUE;
+}
+
+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;
+ long posn;
+ const PlanSegmentData *segment_d;
+ const PlanSegmovfeatData *movfeat_d;
+ SegmovfeatState *fs;
+
+ if (evt == OOP_RD_EOF)
+ exit(0);
+
+ if (evt != OOP_RD_OK)
+ return stdin_iferr(evts,cl_read,evt,errmsg,errnoval,data,recsz,cl_v);
+
+ ps.cl= 0;
+ ps.remain= data;
+ ps_needword(&ps);
+
+ if (!thiswordstrcmp(&ps,"off")) {
+ invert= -1;
+ det= 0;
+ } else {
+ invert= (ps.thisword[0]=='i');
+ if (invert) { ps.thisword++; ps.lthisword--; }
+ det= (!thiswordstrcmp(&ps,"on") ? 0 :
+ !thiswordstrcmp(&ps,"det") ? 1 :
+ (badcmd(&ps,"unknown command"),-1));
+ }
+ ps_needword(&ps);
+ slash= memchr(ps.thisword, '/', ps.lthisword);
+ if (slash) {
+ movfeatname= slash + 1;
+ lmovfeatname= (ps.thisword + ps.lthisword) - movfeatname;
+ ps.lthisword= slash - ps.thisword;
+ } else {
+ movfeatname= 0;
+ lmovfeatname= 0;
+ }
+ segment_ix= lstrpdbsearch(ps.thisword, ps.lthisword,
+ "segment", ui_plan_data.segments,
+ ui_plan_data.n_segments, sizeof(*segment_d));
+ segment_d= &ui_plan_data.segments[segment_ix];
+
+ movfeat_ix= lstrpdbsearch(movfeatname, lmovfeatname,
+ "movfeat", segment_d->movfeats,
+ segment_d->n_movfeats, sizeof(*movfeat_d));
+ movfeat_d= &segment_d->movfeats[movfeat_ix];
+
+ if (ps.remain) {
+ 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;
+ }
+
+ ps_neednoargs(&ps);
+
+ fs= &state[segment_ix][movfeat_ix];
+ fs->invert= invert;
+ fs->det= det;
+ fs->posn= posn;
+
+ redraw(fs);
+ xlib_process();
+
+ return OOP_CONTINUE;
+}
+
+int main(int argc, const char *const *argv) {
+ static XpmColorSymbol coloursymbols[2]= {
+ { (char*)"space", 0, 0 },
+ { (char*)"mark", 0, 1 }
+ };
+
+ 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;
+ 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");
+
+ errno=0; w= strtoul(arg,&ep,0);
+ if (errno || ep==arg || *ep) die("bad windowid");
+ } else {
+ w= XCreateSimpleWindow(d, DefaultRootWindow(d),
+ 0,0, ui_plan_data.xsz, ui_plan_data.ysz,
+ 0,0, 0);
+ if (w == None) diex("XCreateSimpleWindow", "initial");
+ }
+
+ XCALL( XGetWindowAttributes, 0, (d,w,&wattribs) );
+
+ XPMCALL( XpmCreatePixmapFromData, "background",
+ (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) );
+
+ state= mmalloc(sizeof(*state) * ui_plan_data.n_segments);
+ for (segment_ix= 0, segment_d= ui_plan_data.segments;
+ segment_ix < ui_plan_data.n_segments;
+ segment_ix++, segment_d++) {
+ state[segment_ix]= fs=
+ mmalloc(sizeof(**state) * segment_d->n_movfeats);
+ for (movfeat_ix= 0, movfeat_d= segment_d->movfeats;
+ movfeat_ix < segment_d->n_movfeats;
+ 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->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++)
+ for (invert=0; invert<2; invert++)
+ for (det=0; det<2; det++) {
+ XPMCALL( XpmCreatePixmapFromData, "main",
+ (d,w,
+ (char**)(movfeat_d->posns[posn].a[invert][det]),
+ &fs->posns[posn][invert][det],
+ 0,0) );
+ }
+ }
+ }
+
+ sys_events= oop_sys_new(); if (!sys_events) diee("oop_sys_new");
+ events= oop_sys_source(sys_events); assert(events);
+
+ rd= oop_rd_new_fd(events, 0, 0,0);
+ if (!rd) diee("oop_rd_new_fd");
+ oor= oop_rd_read(rd, OOP_RD_STYLE_GETLINE, 1024,
+ stdin_ifok, 0,
+ stdin_iferr, 0);
+ if (oor) diee("oop_rd_read");
+
+ events->on_fd(events, 0, OOP_EXCEPTION, some_exception, 0);
+ events->on_fd(events, ConnectionNumber(d), OOP_READ, xlib_readable, 0);
+ events->on_fd(events, ConnectionNumber(d), OOP_EXCEPTION, some_exception, 0);
+
+ XCALL( XSelectInput, 0, (d,w, ExposureMask) );
+
+ if (arg) {
+ XCALL( XClearArea, "initial", (d,w, 0,0,0,0, True) );
+ } else {
+ XCALL( XMapWindow, 0, (d,w) );
+ }
+
+ xlib_process();
+
+ oop_sys_run(sys_events);
+ abort();
+}
--- /dev/null
+/**/
+
+#include <stdarg.h>
+#include <errno.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include "hostside.h"
+
+void badcmd(ParseState *ps, const char *fmt, ...) {
+ va_list al;
+ va_start(al,fmt);
+ vbadcmd(ps,fmt,al);
+ va_end(al);
+}
+
+int ps_word(ParseState *ps) {
+ const char *space;
+ if (!ps->remain) return 0;
+ space= strchr(ps->remain, ' ');
+ ps->thisword= ps->remain;
+ if (space) {
+ ps->lthisword= space - ps->thisword;
+ ps->remain= space + 1;
+ } else {
+ ps->lthisword= strlen(ps->remain);
+ ps->remain= 0;
+ }
+ return 1;
+}
+
+int ps_needword(ParseState *ps) {
+ if (!ps_word(ps)) { badcmd(ps,"too few args"); return 0; }
+ return 1;
+}
+
+int ps_neednumber(ParseState *ps, long *r, long mi, long mx, const char *wh) {
+ char *ep;
+ long v;
+
+ if (!ps_needword(ps)) return 0;
+ errno= 0; v= strtol(ps->thisword,&ep,0);
+ if (errno || ep != ps->thisword + ps->lthisword) {
+ badcmd(ps,"invalid number for %s",wh);
+ return 0;
+ }
+ if (v < mi || v > mx) {
+ badcmd(ps,"%s %ld out of range %ld..%ld",wh,v,mi,mx);
+ return 0;
+ }
+ *r= v;
+ return 1;
+}
+
+int ps_neednoargs(ParseState *ps) {
+ if (ps->remain) {
+ badcmd(ps,"too many arguments");
+ return 0;
+ }
+ return 1;
+}
+
+int ps_needhextoend(ParseState *ps, Byte *d, int *remain_io) {
+ Byte *d_end;
+ char buf[3], *ep;
+
+ d_end= d + *remain_io;
+ buf[2]= 0;
+
+ if (!ps->remain) { badcmd(ps,"need hex data block"); return 0; }
+ for (;;) {
+ if (!ps_word(ps)) return 0;
+ while (ps->lthisword > 0) {
+ if (ps->lthisword & 1) {
+ badcmd(ps,"hex data block with odd number of digits in part");
+ return 0;
+ }
+ buf[0]= ps->thisword[0];
+ buf[1]= ps->thisword[1];
+ if (d >= d_end) { badcmd(ps,"hex data block too long"); return 0; }
+ *d++= strtoul(buf,&ep,16);
+ if (*ep) { badcmd(ps,"invalid digit in hex data block"); return 0; }
+ ps->lthisword -= 2;
+ ps->thisword += 2;
+ }
+ }
+
+ *remain_io= d_end - d;
+ return 1;
+}
+
+int lstrstrcmp(const char *a, int la, const char *b) {
+ int lb, minl, r;
+
+ lb= strlen(b);
+ minl= la < lb ? la : lb;
+ r= memcmp(a,b,minl);
+ if (r) return r;
+
+ return (la < lb ? -1 :
+ la > lb ? 1 : 0);
+}
+
+int thiswordstrcmp(ParseState *ps, const char *b) {
+ return lstrstrcmp(ps->thisword, ps->lthisword, b);
+}
+
*/
#include <unistd.h>
-#include <stdio.h>
-#include <stdlib.h>
#include <assert.h>
-#include <string.h>
#include <errno.h>
-#include <stdarg.h>
-#include <unistd.h>
#include <fcntl.h>
#include "common.h"
int serial_fudge_delay= 0;
int serial_fd= -1;
-void vdie(const char *fmt, int ev, va_list al) {
- vfprintf(stderr,fmt,al);
- if (ev) fprintf(stderr,": %s",strerror(ev));
- fputc('\n',stderr);
- exit(12);
-}
-
-void die(const char *fmt, ...)
- { va_list al; va_start(al,fmt); vdie(fmt,0,al); }
-void diee(const char *fmt, ...)
- { va_list al; va_start(al,fmt); vdie(fmt,errno,al); }
-void diem(void)
- { diee("malloc failed"); }
-
-void *mmalloc(size_t sz) {
- void *p;
- if (!sz) return 0;
- p= malloc(sz);
- if (!p) diem();
- return p;
-}
-
-char *mstrdupl(const char *s, int l) {
- char *p;
- p= mmalloc(l+1);
- memcpy(p,s,l);
- p[l]= 0;
- return p;
-}
-
-char *mstrdup(const char *s) { return mstrdupl(s,strlen(s)); }
-
void serial_open(const char *device) {
assert(serial_fd==-1);
--- /dev/null
+/*
+ */
+
+#include <assert.h>
+
+#include "safety.h"
+
+const SegPosCombInfo *trackloc_segposcomb(const TrackLocation *tloc) {
+ State *s= &safety_state;
+ SegmentState *seg= &s->segments[tloc->segn];
+ const SegmentInfo *segi= &info_segments[tloc->segn];
+
+ assert(seg->movposcomb < segi->n_poscombs);
+ return &segi->poscombs[seg->movposcomb];
+}
+
+const SegmentLinkInfo *trackloc_segmentlink(const TrackLocation *tloc,
+ const SegPosCombInfo *pci,
+ unsigned far) {
+ return (tloc->backwards ^ far) ? &pci->backwards : &pci->forwards;
+}
+
+long trackloc_remaininseg(const TrackLocation *tloc) {
+ const SegPosCombInfo *pci;
+ long segment_len;
+
+ pci= trackloc_segposcomb(tloc);
+ segment_len= pci->dist;
+ assert(tloc->into <= segment_len);
+ return segment_len - tloc->into;
+}
+
+void trackloc_further(TrackLocation *tloc, long *remain_io) {
+ const SegPosCombInfo *pci;
+ const SegmentLinkInfo *lnki_far;
+ long segment_remain;
+
+ segment_remain= trackloc_remaininseg(tloc);
+
+ if (*remain_io <= segment_remain) {
+ tloc->into += *remain_io;
+ *remain_io= 0;
+ } else {
+ pci= trackloc_segposcomb(tloc);
+ lnki_far= trackloc_segmentlink(tloc, pci, 1);
+ *remain_io -= segment_remain;
+ tloc->segn= lnki_far->next;
+ tloc->into= 0;
+ tloc->backwards ^= lnki_far->next_backwards;
+ }
+}
+
+void trackloc_reverse(TrackLocation *tloc) {
+ tloc->into= trackloc_remaininseg(tloc);
+ tloc->backwards ^= 1;
+}
+
-/*
- */
+/**/
-#include <assert.h>
+#include <stdarg.h>
+#include <errno.h>
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
-#include "safety.h"
+#include "hostside.h"
-const SegPosCombInfo *trackloc_segposcomb(const TrackLocation *tloc) {
- State *s= &safety_state;
- SegmentState *seg= &s->segments[tloc->segn];
- const SegmentInfo *segi= &info_segments[tloc->segn];
-
- assert(seg->movposcomb < segi->n_poscombs);
- return &segi->poscombs[seg->movposcomb];
-}
-
-const SegmentLinkInfo *trackloc_segmentlink(const TrackLocation *tloc,
- const SegPosCombInfo *pci,
- unsigned far) {
- return (tloc->backwards ^ far) ? &pci->backwards : &pci->forwards;
+void vdie(const char *fmt, int ev, va_list al) {
+ vfprintf(stderr,fmt,al);
+ if (ev) fprintf(stderr,": %s",strerror(ev));
+ fputc('\n',stderr);
+ exit(12);
}
-
-long trackloc_remaininseg(const TrackLocation *tloc) {
- const SegPosCombInfo *pci;
- long segment_len;
-
- pci= trackloc_segposcomb(tloc);
- segment_len= pci->dist;
- assert(tloc->into <= segment_len);
- return segment_len - tloc->into;
-}
-void trackloc_further(TrackLocation *tloc, long *remain_io) {
- const SegPosCombInfo *pci;
- const SegmentLinkInfo *lnki_far;
- long segment_remain;
-
- segment_remain= trackloc_remaininseg(tloc);
-
- if (*remain_io <= segment_remain) {
- tloc->into += *remain_io;
- *remain_io= 0;
- } else {
- pci= trackloc_segposcomb(tloc);
- lnki_far= trackloc_segmentlink(tloc, pci, 1);
- *remain_io -= segment_remain;
- tloc->segn= lnki_far->next;
- tloc->into= 0;
- tloc->backwards ^= lnki_far->next_backwards;
- }
+void die(const char *fmt, ...)
+ { va_list al; va_start(al,fmt); vdie(fmt,0,al); }
+void diee(const char *fmt, ...)
+ { va_list al; va_start(al,fmt); vdie(fmt,errno,al); }
+void diem(void)
+ { diee("malloc failed"); }
+
+void *mmalloc(size_t sz) {
+ void *p;
+ if (!sz) return 0;
+ p= malloc(sz);
+ if (!p) diem();
+ return p;
}
-
-void trackloc_reverse(TrackLocation *tloc) {
- tloc->into= trackloc_remaininseg(tloc);
- tloc->backwards ^= 1;
+
+char *mstrdupl(const char *s, int l) {
+ char *p;
+ p= mmalloc(l+1);
+ memcpy(p,s,l);
+ p[l]= 0;
+ return p;
}
-
+
+char *mstrdup(const char *s) { return mstrdupl(s,strlen(s)); }
all: default lpages layers extras
for-test-ui: ours.graph.c ours.redactgraph ours.raw.neato.ps \
ours.redacted.neato.ps ours.layout-data.o \
- ours.dgram-bot.segcmap subseg2display ui-plan-bot.ppm
+ ours.dgram-bot.segcmap subseg2display ui-plan-bot.ppm \
+ ui-plan-bot.o
layers: $(LAYERS)
lpages: $(LPAGES)
} PlanPixmapOnData;
typedef struct {
- unsigned long code;
+ const char *movfeatname;
+ int x, y;
PlanPixmapDataRef off;
int n_posns;
const PlanPixmapOnData *posns;
} PlanSegmovfeatData;
typedef struct {
+ const char *segname;
int n_movfeats;
const PlanSegmovfeatData *movfeats;
} PlanSegmentData;
typedef struct {
+ int xsz, ysz;
PlanPixmapDataRef background;
int n_segments;
const PlanSegmentData *segments;
} PlanData;
+extern const PlanData ui_plan_data;
+extern const char ui_plan_colour_off[];
+
#endif /*PLAN_DATA_FORMAT_H*/
}
die "$pp $t{Movfeatpos}"
unless defined $found;
+ $xpmname= $segname.'_'.$found;
for ($bitno=0; $bitno < $movfeat_configbits{$xpmname}; $bitno++) {
xpmdata_pixel("on","_${xpmname}_${bitno}",
((1<<$bitno) & $t{Movfeatpos}) ? $angstr : '-');
# $cmap{$cmapname}{$pixchars}= $xpm_data_string_rhs
# $cmap{$cmapname}{''}= [ string names for including in xpm ]
# (after cmapdata_output_all)
+$cmap{''}= {}; # fixed colours
sub xpm_cmap ($$) {
my ($style,$cmapname) = @_;
sub xpm_cmap_entry ($$$) {
my ($cmapname,$pixchars,$rhs) = @_;
+ die unless exists $cmap{$cmapname};
die if exists $cmap{$cmapname}{$pixchars};
$cmap{$cmapname}{$pixchars}= $rhs;
}
sub cmaps_define () {
my ($inv,$ondet);
-
+
xpm_cmap("background","background");
+ xpm_cmap_rgbpermil('',qw(off 0 0 0));
xpm_cmap_rgbpermil("background",qw(- 100 100 100
- + 999 0 999
+ + 999 0 990
: 75 75 75
- ! 999 0 999));
+ ! 999 0 980));
xpm_cmap("off","off");
xpm_cmap_fixedbitmap("off",'*');
foreach $inv (('','i')) {
foreach $ondet (qw(on det)) {
xpm_cmap("on","${inv}${ondet}");
- xpm_cmap_rgbpermil("${inv}${ondet}",qw(- 300 300 300));
+ xpm_cmap_rgbpermil("${inv}${ondet}",
+ ' ', qw(999 0 970),
+ qw(- 50 50 50));
}
xpm_cmap_angular("${inv}on", !!$inv, 600, qw(0 0 0));
xpm_cmap_angular("${inv}det",!!$inv, 330, qw(1000 1000 1000));
sub cmapdata_output_all () {
my ($cmapname, $stuff, $cmap, $sname, $pixchars);
+
foreach $cmapname (sort keys %cmap) {
+ next unless length $cmapname;
$stuff= [ ];
$cmap= $cmap{$cmapname};
foreach $pixchars (sort keys %$cmap) {
}
$cmap->{''}= $stuff;
}
+
+ my ($colour, $rhs);
+ $cmap= $cmap{''};
+ foreach $colour (sort keys %$cmap) {
+ $rhs= $cmap->{$colour};
+ $rhs =~ s/^c // or die "$colour $rhs ?";
+ printf("const char ui_plan_colour_%s[]= \"%s\";\n",
+ $colour, $rhs)
+ or die $!;
+ }
}
sub xpmdata_output_all () {
sub plandata_output_all () {
my ($i, @segnames, $segname);
my (@movfeats, $movfeat, $dname, $xpmname, $n_posns, $code, $posn, $mfd);
+ my ($n_movfeats, $xpmd);
for ($i=1; $i<@segnum_name; $i++) {
next unless defined $segnum_name[$i];
push @segnames, $segnum_name[$i];
if (!length $movfeat) {
$xpmname= $segname;
$n_posns= 1;
- $code= 0;
+ $code= '0';
} else {
$xpmname= "${segname}_${movfeat}";
$n_posns= $movfeat_configbits{$xpmname};
- $code= $movfeat_prefix{$xpmname};
+ $code= "\"$movfeat\"";
}
printf("static const PlanPixmapOnData pon_%s[]= {\n",
$xpmname)
}
printf("};\n")
or die $!;
- $mfd .= sprintf(" { 0x%x, p_off_%s, %d, pon_%s },\n",
- $code, $xpmname, $n_posns, $xpmname);
+ $xpmd= $xpmdata{'off'}{"_$xpmname"};
+ $mfd .= sprintf(" { %s, %d,%d, p_off_%s, %d, pon_%s },\n",
+ $code,
+ $xpmd->{X}{Min}, $xpmd->{Y}{Min},
+ $xpmname, $n_posns, $xpmname);
}
printf("static const PlanSegmovfeatData mf_%s[]= {\n".
"%s".
or die $!;
for $segname (@segnames) {
if (exists $movfeats{$segname}) {
- printf(" { %d, mf_%s },\n",
- scalar(@{ $movfeats{$segname} })+1,
- $segname)
- or die $!;
+ $n_movfeats= scalar(@{ $movfeats{$segname} })+1;
} else {
- printf(" { 1, mf_%s },\n",
- $segname)
- or die $!;
+ $n_movfeats= 1;
}
+ printf(" { \"%s\", %d, mf_%s },\n",
+ $segname,
+ $n_movfeats,
+ $segname)
+ or die $!;
}
printf("};\n")
or die $!;
printf("const PlanData ui_plan_data= {\n".
+ " $sz{X}, $sz{Y},\n".
" p_background,\n".
" %d, segments\n".
"};\n",