+static CanonImage *convert_page(Snapshot *sn) {
+ ShMask shiftmasks[3];
+ CanonImage *im;
+
+ fprintf(screenshot_file,
+ "P6\n"
+ "%d %d\n"
+ "255\n", sn->width, sn->height);
+
+#define COMPUTE_SHIFT_MASK(ix, rgb) \
+ compute_shift_mask(&shiftmasks[ix], sn->rgb##_mask)
+ COMPUTE_SHIFT_MASK(0, red);
+ COMPUTE_SHIFT_MASK(1, green);
+ COMPUTE_SHIFT_MASK(2, blue);
+
+ CANONICALISE_IMAGE(im, sn->width, sn->height, {
+ long xrgb= XGetPixel(sn, x, y);
+ int i;
+ rgb= 0;
+ for (i=0; i<3; i++) {
+ rgb <<= 8;
+ unsigned long sample=
+ ((xrgb << shiftmasks[i].lshift)
+ >> shiftmasks[i].rshift) & SAMPLEMASK;
+ rgb |= sample;
+ fputc(sample, screenshot_file);
+ }
+ });
+
+ sysassert(!ferror(screenshot_file));
+ sysassert(!fflush(screenshot_file));
+
+ return im;
+}
+
+void take_screenshots(void) {
+ Snapshot *current=0, *last=0;
+ CanonImage *test;
+
+ /* find the window and check it's on the right kind of screen */
+ raise_and_get_details();
+ wait_for_stability(¤t,0,0, "checking current YPP client screen...");
+ test= convert_page(current);
+ find_structure(test, &max_relevant_y);
+ check_correct_commodities();
+ free(test);
+
+ /* page to the top - keep pressing page up until the image stops changing */
+ set_focus();
+ wait_for_stability(¤t,0, send_pgup_many,
+ "paging up to top of commodity list...");
+
+ /* now to actually page down */
+ for (;;) {
+ debugf("paging page %d\n",npages);
+
+ 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;
+
+ debugf("PAGING page %d converted\n",npages);
+
+ wait_for_stability(¤t,last, 0,
+ "collecting screenshot of page %d...",
+ npages+1);
+
+ if (npages && /* first pagedown doesn't do much */
+ identical(current,last)) {
+ free_snapshot(¤t);
+ break;
+ }
+
+ send_pgdown();
+ npages++;
+ }
+ progress("finishing with the YPP client...");
+ send_pgdown_torestore();
+
+ debugf("PAGING all done.\n");
+ progress_log("collected %d screenshots.",npages);
+}
+
+void take_one_screenshot(void) {
+ Snapshot *current=0;
+
+ raise_and_get_details();
+ sync_after_input();
+ wait_for_stability(¤t,0,0, "taking screenshot...");
+ page_images[0]= convert_page(current);
+ npages= 1;
+ progress_log("collected single screenshot.");
+}
+
+void set_yppclient_window(unsigned long wul) {
+ id= wul;
+}
+
+DEBUG_DEFINE_SOME_DEBUGF(findypp,debugfind)
+
+void find_yppclient_window(void) {
+ Window root, gotroot, gotparent;
+ int screen;
+ int nfound=0;
+
+ if (id) return;
+
+ progress("looking for YPP client window...");
+
+ static const char prefix[]= "Puzzle Pirates - ";
+ static const char onthe[]= " on the ";
+ static const char suffix[]= " ocean";
+#define S(x) (sizeof((x))-1)
+
+ Atom wm_name= XInternAtom(disp,"WM_NAME",True);
+ xassert(wm_name != None);
+
+ for (screen=0; screen<ScreenCount(disp); screen++) {
+ debugfind("FINDYPP screen %d\n", screen);
+ root= RootWindow(disp,screen);
+ unsigned int nchildren1;
+ Window *children1=0;
+
+ xassert( XQueryTree(disp,root,
+ &gotroot,&gotparent,
+ &children1,&nchildren1) );
+ debugfind("FINDYPP screen %d nchildren1=%d\n", screen, nchildren1);
+
+ int i;
+ for (i=0; i<nchildren1; i++) {
+ Window w1= children1[i];
+ unsigned int nchildren2;
+ Window *children2=0;
+
+ 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);
+
+ int j;
+ for (j=-1; j<(int)nchildren2; j++) {
+ Window w2= j<0 ? w1 : children2[j];
+ debugfind("FINDYPP screen %d c1[%2d]=0x%08lx c2[%2d]=0x%08lx",
+ screen, i, (unsigned long)w1, j, (unsigned long)w2);
+
+ int gotfmt;
+ Atom gottype;
+ unsigned long len, gotbytesafter;
+ char *title;
+ unsigned char *gottitle=0;
+ xassert( !XGetWindowProperty(disp,w2, wm_name,0,512, False,
+ AnyPropertyType,&gottype, &gotfmt, &len,
+ &gotbytesafter, &gottitle) );
+ title= (char*)gottitle;
+
+ if (DEBUGP(findypp)) {
+ debugfind(" gf=%d len=%lu gba=%lu \"", gotfmt,len,gotbytesafter);
+ char *p;
+ for (p=title; p < title+len; p++) {
+ char c= *p;
+ if (c>=' ' && c<=126) fputc(c,debug);
+ else fprintf(debug,"\\x%02x",c & 0xff);
+ }
+ fputs("\": ",debug);
+ }
+
+#define REQUIRE(pred) \
+ if (!(pred)) { debugfind(" failed test %s\n", #pred); continue; } \
+ else
+
+ REQUIRE( gottype!=None );
+ REQUIRE( len );
+ REQUIRE( gotfmt==8 );
+
+ REQUIRE( len >= S(prefix) + 1 + S(onthe) + 1 + S(suffix) );
+
+ char *spc1= strchr( title + S(prefix), ' '); REQUIRE(spc1);
+ char *spc2= strrchr((title + len) - S(suffix), ' '); REQUIRE(spc2);
+
+ REQUIRE( (title + len) - spc1 >= S(onthe) + S(suffix) );
+ REQUIRE( spc2 - title >= S(prefix) + S(onthe) );
+
+ REQUIRE( !memcmp(title, prefix, S(prefix)) );
+ REQUIRE( !memcmp(title + len - S(suffix), suffix, S(suffix)) );
+ REQUIRE( !memcmp(spc1, onthe, S(onthe)) );
+
+#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));