g_error document_save(struct textbox_document *doc, const struct pgstring *format, struct pgstring **str) { struct txtformat *f = text_formats; while (f->name && pgstring_cmp(pgstring_tmpwrap(f->name),format)) f++; if (!f->save) return mkerror(PG_ERRT_BADPARAM,51); /* Unsupported text format */ return (*f->save)(doc,str); }
g_error debug_bitmaps(const void **pobj, void *extra) { struct debug_bitmaps_data *data = (struct debug_bitmaps_data *) extra; hwrbitmap bmp = (hwrbitmap) *pobj; s16 w,h; int has_alpha, i; struct font_descriptor *df=NULL; struct pgquad screenclip; struct font_metrics m; hwrbitmap debugwin; s16 lxres,lyres; VID(bitmap_getsize)(VID(window_debug)(), &lxres, &lyres); screenclip.x1 = screenclip.y1 = 0; screenclip.x2 = lxres-1; screenclip.y2 = lyres-1; rdhandle((void**)&df,PG_TYPE_FONTDESC,-1,res[PGRES_DEFAULT_FONT]); df->lib->getmetrics(df,&m); VID(bitmap_getsize) (bmp,&w,&h); if (data->db_x+10+w>lxres) { data->db_x = 0; data->db_y += data->db_h+8; data->db_h = 0; } if (h>data->db_h) data->db_h = h; if (data->db_y+45+h>lyres) { df->lib->draw_string(df,VID(window_debug)(),xy_to_pair(10,lyres-m.charcell.h*3), VID(color_pgtohwr) (0xFFFF00), pgstring_tmpwrap("Too many bitmaps for this screen.\n" "Change video mode and try again"), &screenclip,PG_LGOP_NONE,0); return mkerror(PG_ERRT_INTERNAL,0); /* Dummy error to get us to abort */ } VID(rect) (VID(window_debug)(),data->db_x+3,data->db_y+38,w+4,h+4, VID(color_pgtohwr)(0xFFFFFF),PG_LGOP_NONE); VID(rect) (VID(window_debug)(),data->db_x+4,data->db_y+39,w+2,h+2, VID(color_pgtohwr)(0x000000),PG_LGOP_NONE); has_alpha = w && h && (VID(getpixel)(bmp,0,0) & PGCF_ALPHA); /* If we have an alpha channel, draw a interlacy background so we can see the alpha */ if (has_alpha) { for (i=0;i<h;i++) VID(slab) (VID(window_debug)(), data->db_x+5, data->db_y+40+i, w, VID(color_pgtohwr)(i&1 ? 0xFFFFFF : 0xCCCCCC), PG_LGOP_NONE); df->lib->draw_string(df,VID(window_debug)(),xy_to_pair(data->db_x+5,data->db_y+40), VID(color_pgtohwr)(0x000000), pgstring_tmpwrap("Alpha"), &screenclip, PG_LGOP_NONE,0); } VID(blit) (VID(window_debug)(),data->db_x+5,data->db_y+40,w,h,bmp,0,0, has_alpha ? PG_LGOP_ALPHA : PG_LGOP_NONE); data->db_x += w+8; return success; }
void guru(const char *fmt, ...) { struct font_descriptor *df=NULL; char msgbuf[512]; /* Cruftee! */ char *p,*pline; char c; va_list ap; struct pgquad screenclip; static int semaphore = 0; if (!vid) return; if (semaphore) { fprintf(stderr, "GURU re-entered!\n"); return; } semaphore++; /* Format and print message */ va_start(ap,fmt); vsnprintf(msgbuf,512,fmt,ap); va_end(ap); if (!disable_output) { /* Setup */ VID(rect) (VID(window_debug)(),0,0,vid->lxres,vid->lyres,VID(color_pgtohwr)(0), PG_LGOP_NONE); rdhandle((void**)&df,PG_TYPE_FONTDESC,-1,res[PGRES_DEFAULT_FONT]); screenclip.x1 = screenclip.y1 = 0; screenclip.x2 = vid->lxres-1; screenclip.y2 = vid->lyres-1; #ifdef CONFIG_FORMAT_XBM /* Icon (if this fails, no big deal) */ { hwrbitmap icon; if (!iserror(VID(bitmap_loadxbm) (&icon,deadcomp_bits, deadcomp_width,deadcomp_height, VID(color_pgtohwr) (0xFFFF80), VID(color_pgtohwr) (0x000000)))) { VID(blit) (VID(window_debug)(),5,5,deadcomp_width,deadcomp_height, icon,0,0,PG_LGOP_NONE); VID(bitmap_free) (icon); } } #else /* To appease the below code */ # define deadcomp_width 0 #endif df->lib->draw_string(df,VID(window_debug)(),xy_to_pair(10+deadcomp_width,5), VID(color_pgtohwr)(0xFFFFFF),pgstring_tmpwrap(msgbuf), &screenclip,PG_LGOP_NONE,0); VID(update) (VID(window_debug)(),0,0,vid->lxres,vid->lyres); } #ifdef CONFIG_STDERR_GURU /* Mirror the message on stderr, prefix each line with "GURU: " */ for (c=1,pline=msgbuf;c;pline=p+1) { for (p=pline;*p && *p!='\n';p++); c=*p; *p=0; fprintf(stderr,"GURU: %s\n",pline); } #endif semaphore--; }
void magic_button(s16 key) { switch (key) { case PGKEY_SLASH: /* CTRL-ALT-SLASH exits */ pgserver_mainloop_stop(); return; #ifdef DEBUG_KEYS /* The rest only work in debug mode */ case PGKEY_d: /* CTRL-ALT-d lists all debugging commands */ guru("Someone set up us the bomb!\n" "All your divnode are belong to us!\n" "\n" "Debugging keys:\n" " CTRL-ALT-H: [H]andle tree dump to stdout\n" " CTRL-ALT-S: [S]tring dump to stdout\n" " CTRL-ALT-T: Div[t]ree dump to stdout\n" " CTRL-ALT-M: [M]emory use profile\n" " CTRL-ALT-B: [B]lack screen\n" " CTRL-ALT-Y: Uns[y]nchronize screen buffers\n" " CTRL-ALT-U: Bl[u]e screen\n" " CTRL-ALT-P: Bitma[p] dump to video display\n" " CTRL-ALT-O: Divn[o]de outline\n" " CTRL-ALT-A: [A]pplication dump to stdout\n" " CTRL-ALT-R: Hotspot g[r]aph\n" " CTRL-ALT-I: Mode [I]nfo\n" ); return; case PGKEY_h: /* CTRL-ALT-h dumps the handle tree */ handle_dump(); return; case PGKEY_s: /* CTRL-ALT-s dumps all strings */ string_dump(); return; case PGKEY_n: /* CTRL-ALT-n dumps all gropnodes */ grop_dump(); return; case PGKEY_t: /* CTRL-ALT-t dumps all divnodes */ div_dump(); return; case PGKEY_g: /* Just for fun :) */ guru("GURU MEDITATION #3263827\n\nCongratulations!\n" " Either you have read the source code or\n" " you have very persistently banged your\n" " head on the keyboard ;-)"); return; case PGKEY_m: /* CTRL-ALT-m displays a memory profile */ guru("Memory Profile\n\n" "Total memory use: %d bytes in %d allocations\n\n" "%d bytes in %d gropnodes\n" "%d bytes in %d zombie gropnodes\n" "%d bytes in %d divnodes\n" "%d bytes in %d widgets\n" "%d bytes in %d handle nodes", memamt,memref, num_grops*sizeof(struct gropnode),num_grops, grop_zombie_count*sizeof(struct gropnode),grop_zombie_count, num_divs*sizeof(struct divnode),num_divs, num_widgets*sizeof(struct widget),num_widgets, num_handles*sizeof(struct handlenode),num_handles); return; case PGKEY_b: /* CTRL-ALT-b blanks the screen */ { s16 lxres,lyres; VID(bitmap_getsize)(magic_cursor_display(), &lxres, &lyres); VID(rect) (magic_cursor_display(), 0,0,lxres,lyres, VID(color_pgtohwr) (0),PG_LGOP_NONE); VID(update) (magic_cursor_display(),0,0,lxres,lyres); } return; case PGKEY_y: /* CTRL-ALT-y unsynchronizes the screen buffers */ { /* The buffers in PicoGUI normally like to be synchronized. * Data flows from the divtree to the backbuffer to the screen. * The purpose of this debugging key is to put a different * image on the screen (a black rectangle) than is in the rest * of the pipeline, so that by watching the data ooze out one * can tell if the correct update regions are being used and * in general prod at the video driver. * This would be very simple if not for the fact that only the video * driver has access to the screen's buffer. The procedure here is * to pump the black screen all the way through, then reinitializing * the backbuffer while being very carefull not to update right away * or mess up the sprites. */ struct divtree *p; s16 lxres,lyres; VID(bitmap_getsize)(magic_cursor_display(), &lxres, &lyres); /* Push through the black screen */ VID(rect) (magic_cursor_display(), 0,0,lxres,lyres, VID(color_pgtohwr) (0),PG_LGOP_NONE); VID(update) (magic_cursor_display(),0,0,lxres,lyres); /* Force redrawing everything to the backbuffer */ for (p=dts->top;p;p=p->next) p->flags |= DIVTREE_ALL_REDRAW; update(NULL,0); /* Note the zero flag! */ /* Clear the update rectangle, breaking the pipeline that usually works so well :) */ for (p=dts->top;p;p=p->next) p->update_rect.w = 0; /* The above zero flag left sprites off. With sprites off it's tough to use the mouse! */ VID(sprite_showall) (); } return; case PGKEY_u: /* CTRL-ALT-u makes a blue screen */ { s16 lxres,lyres; VID(bitmap_getsize)(magic_cursor_display(), &lxres, &lyres); VID(rect) (magic_cursor_display(),0,0,lxres,lyres, VID(color_pgtohwr) (0x0000FF), PG_LGOP_NONE); VID(update) (magic_cursor_display(),0,0,lxres,lyres); } return; case PGKEY_p: /* CTRL-ALT-p shows all loaded bitmaps */ { struct debug_bitmaps_data data; s16 lxres,lyres; VID(bitmap_getsize)(VID(window_debug)(), &lxres, &lyres); memset(&data,0,sizeof(data)); guru("Table of loaded bitmaps:"); handle_iterate(PG_TYPE_BITMAP,&debug_bitmaps,&data); VID(update) (VID(window_debug)(),0,0,lxres,lyres); } return; case PGKEY_o: /* CTRL-ALT-o traces all divnodes */ { s16 lxres,lyres; VID(bitmap_getsize)(magic_cursor_display(), &lxres, &lyres); r_divnode_trace(dts->top->head); VID(update) (magic_cursor_display(),0,0,lxres,lyres); } return; case PGKEY_a: /* CTRL-ALT-a shows application info */ { struct app_info *a; const struct pgstring *name; for (a=applist;a;a=a->next) { if (iserror(rdhandle((void**)&name,PG_TYPE_PGSTRING,-1,a->name))) name = pgstring_tmpwrap("(error reading handle)"); printf("app: '"); pgstring_print(name); printf("' type=%d owner=%d\n",a->type,a->owner); } } return; case PGKEY_r: /* CTRL-ALT-r draws the hotspot graph */ { struct hotspot *p; s16 lxres,lyres; VID(bitmap_getsize)(magic_cursor_display(), &lxres, &lyres); for (p=hotspotlist;p;p=p->next) hotspot_draw(p); VID(update) (magic_cursor_display(),0,0,lxres,lyres); } return; case PGKEY_i: /* CTRL-ALT-i gets video mode info */ { int x,y,celw,celh, pixelx,pixely; hwrcolor i, white, black, numcolors; s16 lxres,lyres; VID(bitmap_getsize)(VID(window_debug)(), &lxres, &lyres); guru("Video mode:\n" "Logical %dx%d, physical %dx%d, %d-bit color\n" "\n" "Color palette:\n", vid->lxres, vid->lyres, vid->xres, vid->yres, vid->bpp); if (vid->bpp <= 8) { /* Actual palette display */ i = 0; celw = (lxres-20) >> 4; celh = (lyres-70) >> 4; if (celw < celh) celh = celw; else celw = celh; white = VID(color_pgtohwr)(PGC_WHITE); black = VID(color_pgtohwr)(PGC_BLACK); numcolors = 1 << vid->bpp; for (y=0;y<16;y++) for (x=0;x<16 && i<numcolors;x++,i++) { pixelx = x*celw+10; pixely = y*celh+60; /* Display a rectangle of the color with black and white borders. * This is a lot like what the scribble app does, but we don't have * the convenience of a "frame" gropnode at this low level. */ VID(slab)(VID(window_debug)(),pixelx,pixely,celw,white,PG_LGOP_NONE); VID(slab)(VID(window_debug)(),pixelx,pixely+celh,celw,white,PG_LGOP_NONE); VID(bar)(VID(window_debug)(),pixelx,pixely,celh,white,PG_LGOP_NONE); VID(bar)(VID(window_debug)(),pixelx+celw,pixely,celh,white,PG_LGOP_NONE); VID(slab)(VID(window_debug)(),pixelx+1,pixely+1,celw-2, black, PG_LGOP_NONE); VID(slab)(VID(window_debug)(),pixelx+1,pixely-1+celh,celw-2, black, PG_LGOP_NONE); VID(bar)(VID(window_debug)(),pixelx+1,pixely+1,celh-2, black, PG_LGOP_NONE); VID(bar)(VID(window_debug)(),pixelx-1+celh,pixely+1,celh-2, black, PG_LGOP_NONE); VID(rect)(VID(window_debug)(),pixelx+2,pixely+2,celw-3,celh-3, i , PG_LGOP_NONE); } } else { /* Just some RGB gradients */ y = 60; VID(gradient)(VID(window_debug)(),10,y,lxres-20,20,0, 0x000000,0xFFFFFF, PG_LGOP_NONE); y += 30; VID(gradient)(VID(window_debug)(),10,y,lxres-20,20,0, 0x000000,0xFF0000, PG_LGOP_NONE); y += 30; VID(gradient)(VID(window_debug)(),10,y,lxres-20,20,0, 0x000000,0x00FF00, PG_LGOP_NONE); y += 30; VID(gradient)(VID(window_debug)(),10,y,lxres-20,20,0, 0x000000,0x0000FF, PG_LGOP_NONE); y += 30; } VID(update) (VID(window_debug)(),0,0,lxres,lyres); }