all: $(TARGETS)
-CONVERT_OBJS= convert.o ocr.o pages.o structure.o
+CONVERT_OBJS= convert.o ocr.o pages.o structure.o common.o
convert: $(CONVERT_OBJS) -lnetpbm -lXtst -lX11
$(CONVERT_OBJS): ocr.h convert.h structure.h
--- /dev/null
+
+#ifndef COMMON_H
+#define COMMON_H
+
+#define _GNU_SOURCE
+
+#include <stdarg.h>
+
+#include <sys/types.h>
+
+typedef struct {
+ int w,h;
+ char d[];
+} CanonImage;
+
+
+/*----- debugging arrangements, rather contingent -----*/
+
+typedef struct {
+ int x, y;
+} Point;
+
+typedef struct { /* both inclusive */
+ Point tl;
+ Point br;
+} Rect;
+
+
+
+#define DEBUG_FLAG_LIST \
+ DF(findypp) \
+ DF(pages) \
+ DF(rect) \
+ DF(ocr) \
+ DF(callout)
+
+enum {
+#define DF(f) dbg__shift_##f,
+ DEBUG_FLAG_LIST
+#undef DF
+};
+enum {
+#define DF(f) dbg_##f = 1 << dbg__shift_##f,
+ DEBUG_FLAG_LIST
+#undef DF
+};
+
+unsigned debug_flags;
+
+#define DEBUGP(f) (!!(debug_flags & dbg_##f))
+
+void debug_flush(void);
+#define debug stderr
+
+const char *get_vardir(void);
+
+#define FMT(f,a) __attribute__((format(printf,f,a)))
+#define NORET __attribute__((noreturn))
+
+#define DEFINE_VWRAPPERF(decls, funcf, otherattribs) \
+ decls void funcf(const char *fmt, ...) FMT(1,2) otherattribs; \
+ decls void funcf(const char *fmt, ...) { \
+ va_list al; va_start(al,fmt); v##funcf(fmt,al); va_end(al); \
+ }
+
+#define DEBUG_DEFINE_SOME_DEBUGF(fl,funcf) \
+ static void v##funcf(const char *fmt, va_list al) { \
+ if (DEBUGP(fl)) \
+ vfprintf(debug,fmt,al); \
+ } \
+ DEFINE_VWRAPPERF(static, funcf, )
+
+#define DEBUG_DEFINE_DEBUGF(fl) DEBUG_DEFINE_SOME_DEBUGF(fl,debugf)
+
+
+/*---------- error handling ----------*/
+
+void vfatal(const char *fmt, va_list) FMT(1,0) NORET;
+void fatal(const char *fmt, ...) FMT(1,2) NORET;
+
+#define sysassert(what) \
+ ((what) ? (void)0 : sysassert_fail(__FILE__, __LINE__, #what))
+
+void sysassert_fail(const char *file, int line, const char *what)
+ __attribute__((noreturn));
+
+
+void *mmalloc(size_t sz);
+void *mrealloc(void *p, size_t sz);
+
+
+#endif /*COMMON_H*/
#include "convert.h"
-
void debug_flush(void) {
- eassert(!fflush(debug));
- eassert(!ferror(debug));
+ sysassert(!ferror(debug));
+ sysassert(!fflush(debug));
}
-
const char *get_vardir(void) { return "."; }
static enum {
- mf_findwindow= 01,
- mf_screenshot= 02,
- mf_analyse= 04,
+ mf_findwindow= 0001,
+ mf_screenshot= 0010,
+ mf_readscreenshot= 0020,
+ mf_analyse= 0100,
- mode_findwindow= 01,
- mode_screenshot= 03,
- mode_analyse= 04,
+ mode_findwindow= 0001,
+ mode_screenshot= 0011,
+ mode_analyse= 0120,
- mode_all= 07,
+ mode_all= 0111,
} o_mode= mode_all;
static char *o_screenshots_fn;
FILE *screenshots_file;
+
+static void badusage(const char *fmt, ...)
+ __attribute__((format(printf,1,2),noreturn));
+static void badusage(const char *fmt, ...) {
+ va_list al;
+ va_start(al,fmt);
+ exit(12);
+}
+
+static void open_screenshots_file(const char *mode) {
+ screenshots_file= fopen(o_screenshots_fn, mode);
+ if (!screenshots_file)
+ fatal("could not open screenshots file `%s': %s",
+ o_screenshots_fn, strerror(errno));
+}
+
int main(int argc, char **argv) {
const char *arg;
int r;
+#define ARGVAL ((*++argv) ? *argv : \
+ badusage("missing value for option %s",arg),(char*)0)
+
while ((arg=*++argv)) {
if (!strcmp(arg,"--find-window-only"))
o_mode= mode_findwindow;
else if (!strcmp(arg,"--quiet"))
o_quiet= 1;
else if (!strcmp(arg,"--screenshots-file"))
- eassert( o_screenshots_fn= *++argv );
+ o_screenshots_fn= ARGVAL;
#define DF(f) \
else if (!strcmp(arg,"-D" #f)) \
debug_flags |= dbg_##f;
#undef DF
else if (!strcmp(arg,"--window-id")) {
char *ep;
- eassert((arg=*++argv));
- unsigned long windowid= strtoul(arg,&ep,0);
- eassert(!*ep);
+ unsigned long windowid= strtoul(ARGVAL,&ep,0);
+ if (*ep) badusage("invalid window id");
set_yppclient_window(windowid);
} else
- eassert(!"bad option");
+ badusage("unknown option `%s'",arg);
}
if (!o_screenshots_fn) {
r= asprintf(&o_screenshots_fn,"%s/#pages#.ppm",get_vardir());
- eassert(r>=0); eassert(o_screenshots_fn);
+ sysassert(r>=0);
}
if (o_mode & mf_findwindow) {
find_yppclient_window();
}
if (o_mode & mf_screenshot) {
- screenshots_file= fopen(o_screenshots_fn, "w"); eassert(screenshots_file);
+ open_screenshots_file("w");
if (o_single_page) take_one_screenshot();
else take_screenshots();
- } else {
- screenshots_file= fopen(o_screenshots_fn, "r"); eassert(screenshots_file);
+ }
+ if (o_mode & mf_readscreenshot) {
+ open_screenshots_file("r");
if (o_single_page) read_one_screenshot();
else read_screenshots();
}
-DEFINE_VWRAPPERF(, progress)
-DEFINE_VWRAPPERF(, progress_log)
-DEFINE_VWRAPPERF(, progress_spinner)
-DEFINE_VWRAPPERF(, warning)
+DEFINE_VWRAPPERF(, progress, )
+DEFINE_VWRAPPERF(, progress_log, )
+DEFINE_VWRAPPERF(, progress_spinner, )
+DEFINE_VWRAPPERF(, warning, )
+DEFINE_VWRAPPERF(, fatal, NORET)
static int last_progress_len;
putc('\r',stderr);
r= vfprintf(stderr,fmt,al);
- eassert(r>=0);
if (spinner) {
putc(spinner,stderr);
else while (last_progress_len-- > r) putc('\b',stderr);
}
last_progress_len= r;
- fflush(stderr);
+
+ if (ferror(stderr) || fflush(stderr)) _exit(16);
}
void vprogress(const char *fmt, va_list al) { vprogress_core(0,fmt,al); }
void vwarning(const char *fmt, va_list al) {
progress("");
- fputs("warning: ",stderr);
+ fputs("Warning: ",stderr);
vfprintf(stderr,fmt,al);
+ fputs("\n",stderr);
fflush(stderr);
}
+
+void vfatal(const char *fmt, va_list al) {
+ progress("");
+ fputs("\n\nFatal error: ",stderr);
+ vfprintf(stderr,fmt,al);
+ fflush(stderr);
+ fputs("\n\n",stderr);
+ _exit(4);
+}
+
+void sysassert_fail(const char *file, int line, const char *what) {
+ int e= errno;
+ progress("");
+ fprintf(stderr,
+ "\nfatal operational error:\n"
+ " unsuccessful execution of: %s\n"
+ " %s:%d: %s\n\n",
+ what, file,line, strerror(e));
+ _exit(16);
+}
+
+void *mmalloc(size_t sz) {
+ void *r;
+ if (!sz) return 0;
+ sysassert( r= malloc(sz) );
+ return r;
+}
+void *mrealloc(void *p, size_t sz) {
+ assert(sz);
+ void *r;
+ sysassert( r= realloc(p,sz) );
+ return r;
+}
#ifndef CONVERT_H
#define CONVERT_H
-
+#include "common.h"
#include "ocr.h"
#include <pam.h>
extern FILE *screenshots_file;
-#define FMT(f,a) __attribute__((format(printf,f,a)))
-
void vwarning(const char *fmt, va_list) FMT(1,0);
void warning(const char *fmt, ...) FMT(1,2);
DEBUG_DEFINE_DEBUGF(ocr)
+#define dbassert(x) \
+ ((x) ? (void)0 : \
+ fatal("Error in character set database.\n" \
+ " Requirement not met: %s:%d: %s", __FILE__,__LINE__, #x))
+
static void fgetsline(FILE *f, char *lbuf, size_t lbufsz) {
+ errno=0;
char *s= fgets(lbuf,lbufsz,f);
- eassert(s);
+ sysassert(!ferror(f));
+ dbassert(!feof(f));
+ assert(s);
int l= strlen(lbuf);
- eassert(l>0); eassert(lbuf[--l]='\n');
+ dbassert(l>0); dbassert(lbuf[--l]='\n');
lbuf[l]= 0;
}
#define FGETSLINE(f,buf) (fgetsline(f,buf,sizeof(buf)))
char *dbfname=0;
asprintf(&dbfname,"%s/charset-%d.txt",get_vardir(),rd->h);
- eassert(dbfname);
+ sysassert(dbfname);
db= fopen(dbfname,"r");
free(dbfname);
if (!db) {
- eassert(errno==ENOENT);
+ sysassert(errno==ENOENT);
return;
}
FGETSLINE(db,lbuf);
- eassert(!strcmp(lbuf,"# ypp-sc-tools pctb font v1"));
+ dbassert(!strcmp(lbuf,"# ypp-sc-tools pctb font v1"));
r= fscanf(db, "%d", &h);
- eassert(r==1);
- eassert(h==rd->h);
+ dbassert(r==1);
+ dbassert(h==rd->h);
for (;;) {
FGETSLINE(db,lbuf);
found_ctx:
for (nchrs=0;;) {
- int c= fgetc(db); eassert(c!=EOF);
- if (c=='\n') { eassert(nchrs); break; }
- eassert(nchrs<MAXGLYPHCHRS);
+ int c= fgetc(db); sysassert(!ferror(db)); dbassert(c!=EOF);
+ if (c=='\n') { dbassert(nchrs); break; }
+ dbassert(nchrs<MAXGLYPHCHRS);
if (c=='\\') {
unsigned cr;
- c= fgetc(db); eassert(c=='x');
- r= fscanf(db, "%2x", &cr); eassert(r==1);
+ c= fgetc(db); sysassert(!ferror(db)); dbassert(c=='x');
+ r= fscanf(db, "%2x", &cr); sysassert(!ferror(db)); dbassert(r==1);
assert(cr>0 && cr<=255);
c= cr;
}
current= &rd->contexts[ctxi];
for (;;) {
FGETSLINE(db,lbuf);
- if (!lbuf[0]) { eassert(current != &rd->contexts[ctxi]); break; }
+ if (!lbuf[0]) { dbassert(current != &rd->contexts[ctxi]); break; }
char *ep;
- cv= strtoul(lbuf,&ep,16); eassert(!*ep);
- eassert(!(cv & ~((1UL << rd->h)-1)));
+ cv= strtoul(lbuf,&ep,16); dbassert(!*ep);
+ dbassert(!(cv & ~((1UL << rd->h)-1)));
for (j=0; j<current->nlinks; j++)
if (current->links[j].col == cv) {
goto found_link;
}
- additional= malloc(sizeof(*additional)); eassert(additional);
+ additional= mmalloc(sizeof(*additional));
additional->s[0]= 0;
additional->nlinks= additional->alinks= 0;
additional->links= 0;
if (current->nlinks==current->alinks) {
current->alinks++;
current->alinks<<=1;
- current->links= realloc(current->links,
- sizeof(*current->links) * current->alinks);
- eassert(current->links);
+ current->links= mrealloc(current->links,
+ sizeof(*current->links) * current->alinks);
}
current->links[current->nlinks].col= cv;
current->links[current->nlinks].then= additional;
found_link:;
}
- eassert(!current->s[0]);
+ dbassert(!current->s[0]);
strcpy(current->s, chrs);
current->endsword= endsword;
}
- eassert(!ferror(db));
- eassert(!fclose(db));
+ sysassert(!ferror(db));
+ sysassert(!fclose(db));
}
static void cu_pr_ctxmap(unsigned ctxmap) {
static void callout_unknown(OcrReader *rd, int w, Pixcol cols[],
int unk_l, int unk_r, unsigned unk_ctxmap) {
- int jobpipe[2],donepipe[2], c, r,i, x,y;
+ int jobpipe[2],donepipe[2], c,i, x,y;
const OcrResultGlyph *s;
const char *p;
char cb;
Pixcol pv;
if (!resolver) {
- r= pipe(jobpipe); eassert(!r);
- r= pipe(donepipe); eassert(!r);
+ sysassert(! pipe(jobpipe) );
+ sysassert(! pipe(donepipe) );
resolver_pid= fork();
- eassert(resolver_pid!=-1);
+ sysassert(resolver_pid!=-1);
if (!resolver_pid) {
- r= dup2(jobpipe[0],0); eassert(r==0);
- r= close(jobpipe[1]); eassert(!r);
- r= close(donepipe[0]); eassert(!r);
+ sysassert( dup2(jobpipe[0],0) ==0 );
+ sysassert(! close(jobpipe[1]) );
+ sysassert(! close(donepipe[0]) );
/* we know donepipe[1] is >= 4 and we have dealt with all the others
* so we aren't in any danger of overwriting some other fd 4: */
- r= dup2(donepipe[1],4); eassert(r==4);
+ sysassert( dup2(donepipe[1],4) ==4 );
execlp("./show-thing.tcl", "./show-thing.tcl",
DEBUGP(callout) ? "--debug" : "--noop-arg",
"--automatic-1",
(char*)0);
- eassert(!"execlp failed");
+ sysassert(!"execlp failed");
}
- r= close(jobpipe[0]); eassert(!r);
- r= close(donepipe[1]); eassert(!r);
- resolver= fdopen(jobpipe[1],"w"); eassert(resolver);
+ sysassert(! close(jobpipe[0]) );
+ sysassert(! close(donepipe[1]) );
+ resolver= fdopen(jobpipe[1],"w"); sysassert(resolver);
resolver_done= donepipe[0];
}
fprintf(resolver,"%d %d ",unk_l,unk_r);
fputs("\",\n",resolver);
}
fputs("};\n",resolver);
- eassert(!ferror(resolver));
- eassert(!fflush(resolver));
+ sysassert(!ferror(resolver));
+ sysassert(!fflush(resolver));
- eassert(resolver);
+ sysassert(resolver);
+ int r;
for (;;) {
r= read(resolver_done,&cb,1);
- if (r==-1) { eassert(errno==EINTR); continue; }
+ if (r==-1) { sysassert(errno==EINTR); continue; }
break;
}
if (r==0) {
pid_t pid;
+ int st;
for (;;) {
- pid= waitpid(resolver_pid, &r, 0);
- if (pid==-1) { eassert(errno==EINTR); continue; }
+ pid= waitpid(resolver_pid, &st, 0);
+ if (pid==-1) { sysassert(errno==EINTR); continue; }
break;
}
- eassert(pid==resolver_pid);
- if (WIFEXITED(r)) {
- eassert(!WEXITSTATUS(r));
+ sysassert(pid==resolver_pid);
+ if (WIFEXITED(st)) {
+ if (WEXITSTATUS(st))
+ fatal("character resolver failed with nonzero exit status %d",
+ WEXITSTATUS(st));
fclose(resolver);
close(resolver_done);
resolver= 0;
- } else if (WIFSIGNALED(r)) {
- eassert(!"resolver child died due to signal");
+ } else if (WIFSIGNALED(st)) {
+ fatal("character resolver died due to signal %s%s",
+ strsignal(WTERMSIG(st)), WCOREDUMP(st)?" (core dumped)":"");
} else {
- eassert(!"weird wait status");
+ fatal("character resolver gave strange wait status %d",st);
}
} else {
- eassert(r==1);
- eassert(cb==0);
+ assert(r==1);
+ sysassert(cb==0);
}
readdb(rd);
unsigned ctxmap) {
if (rd->nresults >= rd->aresults) {
rd->aresults++; rd->aresults<<=1;
- rd->results= realloc(rd->results,sizeof(*rd->results)*rd->aresults);
- eassert(rd->results);
+ rd->results= mrealloc(rd->results, sizeof(*rd->results)*rd->aresults);
}
rd->results[rd->nresults].s= s;
rd->results[rd->nresults].l= l;
struct OcrCellTypeInfo {
unsigned initial, nextword, midword;
+ const char *name;
};
const struct OcrCellTypeInfo ocr_celltype_number= {
- 4,4,4
+ 4,4,4,
+ .name= "number"
};
const struct OcrCellTypeInfo ocr_celltype_text= {
- .initial=2 /* Uppercase */,
- .nextword=3 /* Either */,
- .midword=1 /* Lower only */
+ .initial=2, /* Uppercase */
+ .nextword=3, /* Either */
+ .midword=1, /* Lower only */
+ .name= "text"
};
+const char *ocr_celltype_name(OcrCellType ct) { return ct->name; }
+
OcrResultGlyph *ocr(OcrReader *rd, OcrCellType ct, int w, Pixcol cols[]) {
int nspaces;
unsigned ctxmap;
OcrReader *ocr_init(int h) {
OcrReader *rd;
- rd= malloc(sizeof(*rd)); eassert(rd);
+ rd= mmalloc(sizeof(*rd));
memset(rd,0,sizeof(*rd));
rd->h= h;
readdb(rd);
#ifndef OCR_H
#define OCR_H
-
-#define _GNU_SOURCE
+#include "common.h"
#include <string.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
-#include <stdarg.h>
#include <inttypes.h>
-#include <sys/types.h>
#include <sys/wait.h>
-typedef struct {
- int w,h;
- char d[];
-} CanonImage;
-
typedef uint32_t Pixcol;
#define PSPIXCOL(priscan) priscan##32
typedef const struct OcrCellTypeInfo *OcrCellType;
extern const struct OcrCellTypeInfo ocr_celltype_text;
extern const struct OcrCellTypeInfo ocr_celltype_number;
+const char *ocr_celltype_name(OcrCellType ct);
typedef struct OcrReader OcrReader;
*/
-/*----- debugging arrangements, rather contingent -----*/
-
-#define DEBUG_FLAG_LIST \
- DF(findypp) \
- DF(pages) \
- DF(rect) \
- DF(ocr) \
- DF(callout)
-
-enum {
-#define DF(f) dbg__shift_##f,
- DEBUG_FLAG_LIST
-#undef DF
-};
-enum {
-#define DF(f) dbg_##f = 1 << dbg__shift_##f,
- DEBUG_FLAG_LIST
-#undef DF
-};
-
-unsigned debug_flags;
-
-#define DEBUGP(f) (!!(debug_flags & dbg_##f))
-
-void debug_flush(void);
-
-#define eassert assert
-#define debug stderr
-
-const char *get_vardir(void);
-
-#define DEFINE_VWRAPPERF(decls, funcf) \
- decls void funcf(const char *fmt, ...) { \
- va_list al; va_start(al,fmt); v##funcf(fmt,al); va_end(al); \
- }
-
-#define DEBUG_DEFINE_SOME_DEBUGF(fl,funcf) \
- static void v##funcf(const char *fmt, va_list al) { \
- if (DEBUGP(fl)) \
- vfprintf(debug,fmt,al); \
- } \
- DEFINE_VWRAPPERF(static, funcf)
-
-#define DEBUG_DEFINE_DEBUGF(fl) DEBUG_DEFINE_SOME_DEBUGF(fl,debugf)
-
#endif /*OCR_H*/
DEBUG_DEFINE_DEBUGF(pages)
+#define xassert(what) \
+ ((what) ? (void)0 : \
+ fatal("X11 operation unexpectedly failed." \
+ " %s:%d: %s\n", __FILE__,__LINE__,#what))
+
static KeyCode keycode(KeySym sym) {
return XKeysymToKeycode(disp,sym);
}
void screenshot_startup(void) {
- int r;
progress("starting...");
- disp= XOpenDisplay(0); eassert(disp);
- r= gettimeofday(&tv_startup,0); eassert(!r);
+ disp= XOpenDisplay(0);
+ if (!disp) fatal("Unable to open X11 display.");
+ sysassert(! gettimeofday(&tv_startup,0) );
}
/*---------- pager ----------*/
static double timestamp(void) {
struct timeval tv;
- int r;
- r= gettimeofday(&tv,0); eassert(!r);
+ sysassert(! gettimeofday(&tv,0) );
double t= (tv.tv_sec - tv_startup.tv_sec) +
(tv.tv_usec - tv_startup.tv_usec) * 1e-6;
debugf("PAGING %f\n",t);
return t;
}
static void delay(double need_sleep) {
- int r;
debugf("PAGING delay %f\n",need_sleep);
- r= usleep(need_sleep * 1e6); eassert(!r);
+ sysassert(! usleep(need_sleep * 1e6) );
}
static void sync_after_input(void) {
- int r;
- r= XSync(disp, False); eassert(r);
+ xassert( XSync(disp, False) );
last_input= timestamp();
}
static void translate_coords_toroot(int wx, int wy, int *rx, int *ry) {
- int r;
Window dummy;
- r= XTranslateCoordinates(disp, id,attr.root, wx,wy, rx,ry, &dummy);
- eassert(r);
+ xassert( XTranslateCoordinates(disp, id,attr.root, wx,wy, rx,ry, &dummy) );
}
static void check_client_window_all_on_screen(void) {
- int r;
- int rxpos, rypos;
+ Rect onroot;
unsigned rwidth, rheight;
Window dummy;
unsigned bd, depth;
+ int rxpos, rypos;
- r= XGetGeometry(disp,attr.root, &dummy, &rxpos,&rypos,
- &rwidth, &rheight,
- &bd,&depth);
+ xassert( XGetGeometry(disp,attr.root, &dummy, &rxpos,&rypos,
+ &rwidth, &rheight,
+ &bd,&depth) );
- translate_coords_toroot(0,0, &rxpos,&rypos);
- eassert(rxpos>=0 && rypos>=0);
-
- translate_coords_toroot(wwidth-1,wheight-1, &rxpos,&rypos);
- eassert(rxpos<rwidth && rypos<rheight);
+ translate_coords_toroot(0,0, &onroot.tl.x,&onroot.tl.y);
+ translate_coords_toroot(wwidth-1,wheight-1, &onroot.br.x,&onroot.br.y);
+ if (!(onroot.tl.x >= 0 &&
+ onroot.tl.y >= 0 &&
+ onroot.br.x < rwidth &&
+ onroot.br.y < rheight))
+ fatal("YPP client window is not entirely on the screen.");
}
static void check_not_disturbed(void) {
switch (ev.type) {
case VisibilityNotify:
- eassert(ev.xvisibility.state == VisibilityUnobscured);
+ if (ev.xvisibility.state != VisibilityUnobscured)
+ fatal("YPP client window has become obscured.");
break;
case ConfigureNotify:
check_client_window_all_on_screen();
break;
case FocusOut:
- eassert(!"focus left YPP client window");
+ fatal("Focus left YPP client window.");
break;
case FocusIn:
warning("focus entered YPP client window ?!");
break;
default:
- eassert(!"unexpected X11 event");
+ fatal("Received unexpected X11 event (type code %d)!", ev.type);
}
}
}
va_start(al,fmt);
Snapshot *last=0;
- int r;
/* waits longer if we're going to return an image identical to previously
* if previously==0, all images are considered identical to it */
last_input, previously);
char *doing;
- r= vasprintf(&doing,fmt,al); eassert(r>=0);
+ sysassert( vasprintf(&doing,fmt,al) >=0);
progress("%s",doing);
}
static void raise_and_get_details(void) {
- int r;
int evbase,errbase,majver,minver;
int wxpos, wypos;
unsigned bd,depth;
debugf("PAGING raise_and_get_details\n");
- r= XTestQueryExtension(disp, &evbase,&errbase,&majver,&minver);
- eassert(r==True);
+ int xtest= XTestQueryExtension(disp, &evbase,&errbase,&majver,&minver);
+ if (!xtest) fatal("X server does not support the XTEST extension.");
- r= XRaiseWindow(disp, id); eassert(r);
+ xassert( XRaiseWindow(disp, id) );
/* in case VisibilityNotify triggers right away before we have had a
* change to raise; to avoid falsely detecting lowering in that case */
- r= XSelectInput(disp, id,
- StructureNotifyMask|
- VisibilityChangeMask
- ); eassert(r);
+ xassert( XSelectInput(disp, id,
+ StructureNotifyMask|
+ VisibilityChangeMask
+ ) );
- r= XRaiseWindow(disp, id); eassert(r);
+ xassert( XRaiseWindow(disp, id) );
/* in case the window was lowered between our Raise and our SelectInput;
* to avoid failing to detect that lowering */
- r= XGetWindowAttributes(disp, id, &attr); eassert(r);
- r= XGetGeometry(disp,id, &attr.root,
- &wxpos,&wypos, &wwidth,&wheight,
- &bd,&depth);
+ xassert( XGetWindowAttributes(disp, id, &attr) );
+ xassert( XGetGeometry(disp,id, &attr.root,
+ &wxpos,&wypos, &wwidth,&wheight,
+ &bd,&depth) );
- eassert(wwidth >= 320 && wheight >= 320);
+ if (!(wwidth >= 320 && wheight >= 320))
+ fatal("YPP client window is implausibly small?");
check_client_window_all_on_screen();
}
static void set_focus(void) {
- int r;
int screen= XScreenNumberOfScreen(attr.screen);
progress("taking control of YPP client window...");
sync_after_input();
delay(0.5);
- r= XSelectInput(disp, id,
- StructureNotifyMask|
- VisibilityChangeMask|
- FocusChangeMask
- ); eassert(r);
+ xassert( XSelectInput(disp, id,
+ StructureNotifyMask|
+ VisibilityChangeMask|
+ FocusChangeMask
+ ) );
translate_coords_toroot(10,10, &xpos,&ypos);
XTestFakeMotionEvent(disp,screen, xpos,ypos, 0);
}
});
- eassert(!fflush(screenshots_file));
+ sysassert(!ferror(screenshots_file));
+ sysassert(!fflush(screenshots_file));
return im;
}
for (;;) {
debugf("paging page %d\n",npages);
- eassert(npages < MAX_PAGES);
+ if (!(npages < MAX_PAGES))
+ fatal("Paging down seems to generate too many pages - max is %d.",
+ MAX_PAGES);
+
page_images[npages]= convert_page(current);
free_snapshot(&last); last=current; current=0;
void find_yppclient_window(void) {
Window root, gotroot, gotparent;
- int screen, r;
+ int screen;
int nfound=0;
if (id) return;
#define S(x) (sizeof((x))-1)
Atom wm_name= XInternAtom(disp,"WM_NAME",True);
- eassert(wm_name != None);
+ xassert(wm_name != None);
for (screen=0; screen<ScreenCount(disp); screen++) {
debugfind("FINDYPP screen %d\n", screen);
unsigned int nchildren1;
Window *children1=0;
- r= XQueryTree(disp,root,
+ xassert( XQueryTree(disp,root,
&gotroot,&gotparent,
- &children1,&nchildren1);
- eassert(r);
+ &children1,&nchildren1) );
debugfind("FINDYPP screen %d nchildren1=%d\n", screen, nchildren1);
int i;
unsigned int nchildren2;
Window *children2=0;
- r= XQueryTree(disp,w1,
- &gotroot,&gotparent,
- &children2,&nchildren2);
- eassert(r);
+ xassert( XQueryTree(disp,w1,
+ &gotroot,&gotparent,
+ &children2,&nchildren2) );
debugfind("FINDYPP screen %d c1[%2d]=0x%08lx nchildren2=%d\n",
screen, i, (unsigned long)w1, nchildren2);
unsigned long len, gotbytesafter;
char *title;
unsigned char *gottitle=0;
- r= XGetWindowProperty(disp,w2, wm_name,0,512, False,
- AnyPropertyType,&gottype, &gotfmt, &len,
- &gotbytesafter, &gottitle);
- eassert(!r);
+ xassert( !XGetWindowProperty(disp,w2, wm_name,0,512, False,
+ AnyPropertyType,&gottype, &gotfmt, &len,
+ &gotbytesafter, &gottitle) );
title= (char*)gottitle;
if (DEBUGP(findypp)) {
REQUIRE( !memcmp(title + len - S(suffix), suffix, S(suffix)) );
REQUIRE( !memcmp(spc1, onthe, S(onthe)) );
-#define ASSIGN(what, start, end) do { \
- r= asprintf(&what, "%.*s", (end)-(start), start); eassert(r>0); \
+#define ASSIGN(what, start, end) do { \
+ sysassert( asprintf(&what, "%.*s", (end)-(start), start) >0 ); \
}while(0)
ASSIGN(pirate, title + S(prefix), spc1);
ASSIGN(ocean, spc1 + S(onthe), (title + len) - S(suffix));
debugfind(" YES!\n");
id= w2;
nfound++;
- progress_log("found YPP client [--window-id 0x%lx]:"
+ progress_log("found YPP client (0x%lx):"
" %s ocean - %s.",
(unsigned long)id, ocean, pirate);
}
}
if (children1) XFree(children1);
}
- eassert(nfound==1);
+ if (nfound>1)
+ fatal("Found several YPP clients."
+ " Close one, or specify the windowid with --window-id.\n");
+ if (nfound<1)
+ fatal("Did not find YPP client."
+ " Use --window-id and/or report this as a fault.\n");
}
#include "structure.h"
-
-typedef struct {
- int x, y;
-} Point;
-
-typedef struct { /* both inclusive */
- Point tl;
- Point br;
-} Rect;
-
static CanonImage *cim;
static inline char get(int x, int y) { return cim->d[y * cim->w + x]; }
{ 0,0 }
};
+
+static void mustfail1(const char *file, int line, const char *what) {
+ fprintf(stderr,
+ "\n\n"
+ "Unable to figure out contents YPP client display.\n"
+ " Check that your client is logged in has the correct display.\n"
+ " If that isn't the problem, please report this as a fault.\n\n"
+ "Technical details:"
+ " %s:%d: requirement failed: %s\n",
+ file, line, what);
+}
+static void mustfail2(void) NORET;
+static void mustfail2(void) {
+ fprintf(stderr, "\n\nGiving up.\n");
+ exit(8);
+}
+
+#define MUST(x, ifnot) do{ \
+ if (!(x)) { \
+ mustfail1(__FILE__,__LINE__,#x); \
+ ifnot; \
+ mustfail2(); \
+ } \
+ }while(0)
+
+#define MP(v) fprintf(stderr," %s=%d,%d",#v,(v).x,(v).y)
+#define MI(v) fprintf(stderr," %s=%d", #v,(v))
+#define MC(v) fprintf(stderr," %s='%c'", #v,(v))
+#define MS(v) fprintf(stderr," %s=\"%s\"", #v,(v))
+#define MSB(v) fprintf(stderr," %s", (v))
+#define MR(v) fprintf(stderr," %s=%d,%d..%d,%d",\
+ #v,(v).tl.x,(v).tl.y,(v).br.x,(v).br.y)
+
+
static void require_rectangle(int tlx, int tly, int brx, int bry,
const char *ok) {
- int x,y;
- for (x=tlx; x<=brx; x++)
- for (y=tly; y<=bry; y++) {
- int c= get(x,y);
- assert(strchr(ok,c));
+ Point p;
+ for (p.x=tlx; p.x<=brx; p.x++)
+ for (p.y=tly; p.y<=bry; p.y++) {
+ int c= get_p(p);
+ MUST( strchr(ok,c), ({
+ Rect rm={{tlx,tly},{brx,bry}};
+ MR(rm);MP(p);MS(ok);
+ }));
}
}
static void require_rectangle_r(Rect rr, const char *ok) {
static void debug_rect(const char *what, int whati, Rect rr) {
if (!DEBUGP(rect)) return;
- int y,r,w;
+ int y,w;
fprintf(debug, "%s %d: %d,%d..%d,%d:\n", what, whati,
rr.tl.x,rr.tl.y, rr.br.x,rr.br.y);
w= rr.br.x - rr.tl.x + 1;
for (y=rr.tl.y; y<=rr.br.y; y++) {
fprintf(debug, "%4d%*s|", y, rr.tl.x,"");
- r= fwrite(cim->d + y*cim->w + rr.tl.x, 1, w, debug);
- eassert(r==w);
+ fwrite(cim->d + y*cim->w + rr.tl.x, 1, w, debug);
fputc('|',debug);
fputc('\n',debug);
}
#define WALK_UNTIL_MUST(point,coord,increm,last,edge) \
do { \
WALK_UNTIL(point,coord,increm,last,edge); \
- eassert((point).coord != (last)+(increm)); \
- } while(0)
+ MUST( (point).coord != (last)+(increm), \
+ MP(point); MI(increm); MI(last); MC(edge); \
+ ); \
+ }while(0)
void find_structure(CanonImage *im) {
cim= im;
Point across= { mainr.tl.x, commbasey };
int colno=0;
for (;;) {
- eassert(get_p(across) != '+');
+ MUST( get_p(across) != '+', MI(colno);MP(across);MR(mainr);MI(commbasey) );
WALK_UNTIL(across, x,+1, mainr.br.x, '+');
- eassert(colno < MAX_COLUMNS);
+ MUST( colno < MAX_COLUMNS, MP(across);MR(mainr);MI(commbasey); );
int colrx= across.x;
if (colrx > mainr.br.x) colrx= mainr.br.x;
if (colno < INTERESTING_COLUMNS)
require_rectangle(across.x,mainr.tl.y, across.x,mainr.br.y, "+");
across.x++;
}
- eassert(colno >= MIN_COLUMNS);
+ MUST( colno >= MIN_COLUMNS, MI(colno);MR(mainr);MP(across); );
-#define SET_ONCE(var,val) do{ \
- int v= (val); \
- if ((var)==-1) (var)= v; \
- else eassert((var) == v); \
+#define SET_ONCE(var,val) do{ \
+ int v= (val); \
+ if ((var)==-1) (var)= v; \
+ else MUST( (var) == v, MSB(#var);MI((var));MI(v);MR(mainr); ); \
}while(0)
SET_ONCE(columns, colno);
}
CanonImage *alloc_canon_image(int w, int h) {
- CanonImage *im= malloc(sizeof(CanonImage) + w*h);
- eassert(im);
+ CanonImage *im= mmalloc(sizeof(CanonImage) + w*h);
im->w= w;
im->h= h;
memset(im->d,'?',w*h);
CanonImage *im;
pnm_readpaminit(f, &inpam, sizeof(inpam));
- eassert(inpam.maxval == 255);
- eassert(inpam.bytes_per_sample == 1);
+ if (!(inpam.maxval == 255 &&
+ inpam.bytes_per_sample == 1 &&
+ inpam.format == RPPM_FORMAT))
+ fatal("PNM screenshot(s) file must be 8bpp 1 byte per sample RGB");
CANONICALISE_IMAGE(im, inpam.width, inpam.height, {
- int r= fread(&rgb_buf,1,3,f); eassert(r==3);
+ int r= fread(&rgb_buf,1,3,f);
+ sysassert(!ferror(f));
+ if (r!=3) fatal("PNM screenshot(s) file ends unexpectedly");
rgb=
((unsigned long)rgb_buf[0]<<16) |
(rgb_buf[2]);
});
- eassert(!ferror(screenshots_file));
- eassert(!feof(screenshots_file));
+ sysassert(!ferror(screenshots_file));
+
+ if (!(npages < MAX_PAGES))
+ fatal("Too many images in screenshots file; max is %d.\n", MAX_PAGES);
- eassert(npages < MAX_PAGES);
page_images[npages++]= im;
}
void read_screenshots(void) {
struct stat stab;
- int r;
- r= fstat(fileno(screenshots_file), &stab); eassert(!r);
+ sysassert(! fstat(fileno(screenshots_file), &stab) );
for (;;) {
if (S_ISREG(stab.st_mode)) {
progress("reading screenshot %d...",npages);
file_read_image_ppm(screenshots_file);
}
- eassert(!ferror(screenshots_file));
+ sysassert(!ferror(screenshots_file));
progress_log("read %d screenshots.",npages);
}
for (x=0; x<w; x++) {
Pixcol cx, rv;
for (y=0, cx=0, rv=1; y<text_h; y++, rv<<=1) {
- switch (get(x+r.tl.x, y+r.tl.y)) {
+ Point here= { x+r.tl.x, y+r.tl.y };
+ int pixel= get_p(here);
+ switch (pixel) {
case ' ': break;
case 'o': cx |= rv; break;
- default: eassert(!"wrong pixel");
+ default:
+ MUST(!"wrong pixel",
+ MC(pixel);MP(here);MSB(ocr_celltype_name(ct));MR(r); );
}
}
cols[x]= cx;
tab= "\t";
}
fputs("\n", stdout);
- eassert(!ferror(stdout));
- eassert(!fflush(stdout));
+ sysassert(!ferror(stdout));
+ sysassert(!fflush(stdout));
}
}
}
} \
if (DEBUGP(rect)) { \
fprintf(debug, "%4d ",y); \
- int r= fwrite(im->d + y*w, 1,w, debug); \
- eassert(r==w); \
+ fwrite(im->d + y*w, 1,w, debug); \
fputc('\n',debug); \
} \
} \
+++ /dev/null
-/**/
-
-#include <assert.h>
-#include <stdlib.h>
-#include <string.h>
-
-#include <X11/Xlib.h>
-#include <X11/extensions/XTest.h>
-
-#define eassert assert
-
-static Display *disp;
-static long id;
-
-static KeyCode keycode(const char *s) {
- KeySym sym= XStringToKeysym(s);
- return XKeysymToKeycode(disp,sym);
-}
-
-int main(int argc, const char *const *argv) {
- char *ep;
- XWindowAttributes attr;
- int xpos,ypos;
- unsigned width,height,bd,depth;
- int r;
-
- id= strtoul(*++argv,&ep,0);
- disp= XOpenDisplay(0); eassert(disp);
-
- r= XRaiseWindow(disp, id); eassert(r);
-
- r= XGetWindowAttributes(disp, id, &attr); eassert(r);
- r= XGetGeometry(disp,id, &attr.root,&xpos,&ypos,&width,&height, &bd,&depth);
- eassert(r);
-
- Window dummy;
- r= XTranslateCoordinates(disp, id,attr.root, 160,160, &xpos,&ypos,
- &dummy);
- eassert(r);
-
- int screen= XScreenNumberOfScreen(attr.screen);
- XTestFakeMotionEvent(disp,screen, xpos, ypos, 0);
- XTestFakeButtonEvent(disp,1,1, 0);
- XTestFakeButtonEvent(disp,1,0, 100);
-
- XTestFakeKeyEvent(disp, keycode("Next"),1, 100);
- XTestFakeKeyEvent(disp, keycode("Next"),0, 100);
-
-#if 0
-
- while (*++argv) {
-
- memset(&ev,0,sizeof(ev));
-#define KE ev.xkey
-#define ME ev.xbutton
-
- switch (**argv) {
- case 'r':
- break;
-
-#define KMEVENT(e,t) \
- e.type= t; \
- e.window= id; \
- e.root= attr.root; \
- e.x= atoi(*++argv); \
- e.y= atoi(*++argv); \
- e.x_root= e.x; \
- e.y_root= e.y; \
- e.same_screen= True; \
- kmevent(&ev); \
- break;
-
- case 'K': KE.keycode= ; KMEVENT(KE,KeyPress);
- case 'k': KE.keycode= keycode(*++argv); KMEVENT(KE,KeyRelease);
- case 'M': ME.button=1; KMEVENT(ME,ButtonPress);
- case 'm': ME.button=1; ME.state=Button1Mask; KMEVENT(ME,ButtonRelease);
- default:
- abort();
- }
- }
-
-#endif
- r= XSync(disp, False); eassert(r);
- exit(0);
-}
file convert
set confirm off
set args --screenshot-only
-
-break pages.c:510
+#break pages.c:510
run