#include #include #include #include #include #include #include #include //#include #include //#include //#include #include #include extern const char *__progname; static XrmDatabase db; static const char *defaults = "\ *Foreground: white\n\ *Background: black\n\ *BorderColor: white\n\ *BorderWidth: 1\n\ *BorderMargin: 1\n\ *MenuMargin: 25\n\ *Name: xie\n\ *IconName: xie\n\ *MagFactor: 16\n\ "; static char *displayname; static char *geometryspec; static char *foreground; static char *background; static char *bordercstr; static char *borderwstr; static char *bordermstr; static char *menumstr; static char *magfacstr; static char *name; static char *iconname; static char *fontname; static int synch; static int argc; static char **argv; static Display *disp; static Screen *scr; static int width; static int height; static int depth; static Window rootwin; static Colormap defcmap; static Visual *visual; static int (*preverr)(Display *, XErrorEvent *); static int (*prevIOerr)(Display *); static const char *filename; typedef enum { FF_PBM = 1, FF_RPBM, FF_PGM, FF_RPGM, FF_PPM, FF_RPPM, FF_PAM, FF_RPAM, } FILEFMT; typedef struct loadstate LOADSTATE; typedef struct imgdesc IMGDESC; typedef struct pixel PIXEL; typedef struct gcw GCW; struct gcw { XGCValues shadow; unsigned long int dirty; GC gc; } ; struct pixel { unsigned char r; unsigned char g; unsigned char b; unsigned char a; } ; struct loadstate { int fd; FILE *f; const char *fn; int rfill; int rptr; IMGDESC *img; unsigned char pbmbuf; unsigned char pbmbit; char rbuf[8192]; } ; struct imgdesc { FILEFMT fmt; int w; int h; int maxval; int maxval2; PIXEL *data; } ; static IMGDESC image; static int margin; static int menu_margin; static int borderwidth; static int magfactor; static XFontStruct *font; static int deffont; static int baselineskip; static Colormap wincmap; static XColor fgcolour; static XColor bgcolour; static XColor bdcolour; static Cursor arrowcurs; static Cursor xhaircurs; static Cursor boxgrabcurs[3][3]; static GCW wgc; static GCW bgc; static void bugcheck_(int, const char *, ...) __attribute__((__format__(__printf__,2,3))); #ifdef __GNUC__ #if __GNUC__ < 3 #define bugcheck(args...) bugcheck_(__LINE__,args) #else #define bugcheck(...) bugcheck_(__LINE__,__VA_ARGS__) #endif #else // Hope it's at least C99... #define bugcheck(...) bugcheck_(__LINE__,__VA_ARGS__) #endif static void bugcheck_(int line, const char *fmt, ...) { va_list ap; char *s; va_start(ap,fmt); vasprintf(&s,fmt,ap); va_end(ap); fprintf(stderr,"%s: bugcheck (line %d): %s\n",__progname,line,s); free(s); abort(); fprintf(stderr,"%s: abort() returned!\n",__progname); exit(1); } static void saveargv(int ac, char **av) { int i; int nc; char *abuf; argc = ac; argv = (char **) malloc((ac+1)*sizeof(char *)); nc = 1; for (i=0;i 0) { skip --; continue; } if (**av != '-') { errs += specify_file(av[skip]); continue; } if (0) { needarg:; fprintf(stderr,"%s: %s needs a following argument\n",__progname,*av); errs ++; continue; } #define WANTARG() do { if (++skip >= ac) goto needarg; } while (0) if (!strcmp(*av,"-display")) { WANTARG(); displayname = av[skip]; continue; } if (!strcmp(*av,"-geometry")) { WANTARG(); geometryspec = av[skip]; continue; } if (!strcmp(*av,"-foreground") || !strcmp(*av,"-fg")) { WANTARG(); foreground = av[skip]; continue; } if (!strcmp(*av,"-background") || !strcmp(*av,"-bg")) { WANTARG(); background = av[skip]; continue; } if (!strcmp(*av,"-bordercolor") || !strcmp(*av,"-bd")) { WANTARG(); bordercstr = av[skip]; continue; } if (!strcmp(*av,"-borderwidth") || !strcmp(*av,"-bw")) { WANTARG(); borderwstr = av[skip]; continue; } if (!strcmp(*av,"-bordermargin") || !strcmp(*av,"-bm")) { WANTARG(); bordermstr = av[skip]; continue; } if (!strcmp(*av,"-menumargin") || !strcmp(*av,"-mm")) { WANTARG(); menumstr = av[skip]; continue; } if (!strcmp(*av,"-magfactor") || !strcmp(*av,"-magf") || !strcmp(*av,"-mf")) { WANTARG(); magfacstr = av[skip]; continue; } if (!strcmp(*av,"-name")) { WANTARG(); name = av[skip]; continue; } if (!strcmp(*av,"-iconname")) { WANTARG(); iconname = av[skip]; continue; } if (!strcmp(*av,"-font") || !strcmp(*av,"-fn")) { WANTARG(); fontname = av[skip]; continue; } if (!strcmp(*av,"-sync")) { synch = 1; continue; } if (!strcmp(*av,"-file")) { WANTARG(); errs += specify_file(av[skip]); continue; } #undef WANTARG fprintf(stderr,"%s: unrecognized option `%s'\n",__progname,*av); errs ++; } if (errs) exit(1); } static int load_r(void *sv, char *data, int len) { return(read(((LOADSTATE *)sv)->fd,data,len)); } static int load_get(LOADSTATE *s) { int c; c = getc(s->f); if (c != EOF) return(c); if (feof(s->f)) { fprintf(stderr,"%s: %s: unexpected EOF\n",__progname,s->fn); } else if (ferror(s->f)) { fprintf(stderr,"%s: %s: read error\n",__progname,s->fn); } else { fprintf(stderr,"%s: %s: got EOF but neither feof nor ferror(?""?)\n",__progname,s->fn); } return(EOF); } static int pnmget(LOADSTATE *s) { int c; c = load_get(s); if (c == EOF) return(EOF); if (c == '#') { while (1) { c = load_get(s); if (c == EOF) return(EOF); if (c == '\n') break; } } return(c); } static int digitval(char c) { switch (c) { case '0': return(0); break; case '1': return(1); break; case '2': return(2); break; case '3': return(3); break; case '4': return(4); break; case '5': return(5); break; case '6': return(6); break; case '7': return(7); break; case '8': return(8); break; case '9': return(9); break; } return(-1); } static int pnmgetnum(LOADSTATE *s, const char *what) { int v; int c; int dv; do c = pnmget(s); while (isspace(c)); if (c == EOF) { fprintf(stderr,"%s: %s: not a PNM file (EOF reading %s)\n",__progname,s->fn,what); return(-1); } v = digitval(c); if ((v < 0) || (v >= 10)) { fprintf(stderr,"%s: %s: not a PNM file (non-digit in %s)\n",__progname,s->fn,what); return(-1); } while (1) { c = pnmget(s); if (c == EOF) { fprintf(stderr,"%s: %s: not a PNM file (EOF reading %s)\n",__progname,s->fn,what); return(-1); } dv = digitval(c); if ((dv < 0) || (dv >= 10)) break; v = (10 * v) + dv; } if (! isspace(c)) { fprintf(stderr,"%s: %s: not a PNM file (non-digit in %s)\n",__progname,s->fn,what); return(-1); } return(v); } static int filefmt_raw(FILEFMT ff) { switch (ff) { case FF_RPBM: case FF_RPGM: case FF_RPPM: case FF_RPAM: return(1); break; default: return(0); break; } } static void skip1white(LOADSTATE *s) { int c; c = load_get(s); if (! isspace(c)) ungetc(c,s->f); // ungetc(EOF,) is a silent no-op } static int load_header(LOADSTATE *s) { int p; int n; int v; p = load_get(s); if (p == EOF) return(1); if (p != 0x50) // ASCII 'P' { fprintf(stderr,"%s: %s: bad magic number (0x%02x)\n",__progname,s->fn,p); return(1); } n = load_get(s); if (n == EOF) return(1); switch (n) { case 0x31: // ASCII '1' s->img->fmt = FF_PBM; break; case 0x32: // ASCII '2' s->img->fmt = FF_PGM; break; case 0x33: // ASCII '3' s->img->fmt = FF_PPM; break; case 0x34: // ASCII '4' s->img->fmt = FF_RPBM; break; case 0x35: // ASCII '5' s->img->fmt = FF_RPGM; break; case 0x36: // ASCII '6' s->img->fmt = FF_RPPM; break; case 0x37: // ASCII '7' s->img->fmt = FF_PAM; break; case 0x38: // ASCII '8' s->img->fmt = FF_RPAM; break; default: fprintf(stderr,"%s: %s: bad magic number (0x%02x 0x%02x)\n",__progname,s->fn,p,n); return(1); break; } v = pnmgetnum(s,"width"); if (v < 0) return(1); s->img->w = v; v = pnmgetnum(s,"height"); if (v < 0) return(1); s->img->h = v; s->img->maxval2 = 255; switch (s->img->fmt) { default: bugcheck("impossible image format %d",(int)s->img->fmt); break; case FF_PBM: case FF_RPBM: s->img->maxval = 1; break; case FF_PGM: case FF_PPM: v = pnmgetnum(s,"maxval"); if (v < 0) return(1); s->img->maxval = v; break; case FF_RPGM: case FF_RPPM: v = pnmgetnum(s,"maxval"); if (v < 0) return(1); if (v > 255) { fprintf(stderr,"%s: %s: raw maxval %d is out of range\n",__progname,s->fn,v); return(1); } s->img->maxval = v; break; case FF_PAM: v = pnmgetnum(s,"maxval"); if (v < 0) return(1); s->img->maxval = v; v = pnmgetnum(s,"maxval2"); if (v < 0) return(1); s->img->maxval2 = v; break; case FF_RPAM: v = pnmgetnum(s,"maxval"); if (v < 0) return(1); if (v > 255) { fprintf(stderr,"%s: %s: raw maxval %d is out of range\n",__progname,s->fn,v); return(1); } s->img->maxval = v; v = pnmgetnum(s,"maxval2"); if (v < 0) return(1); if (v > 255) { fprintf(stderr,"%s: %s: raw maxval2 %d is out of range\n",__progname,s->fn,v); return(1); } s->img->maxval2 = v; break; } if (filefmt_raw(s->img->fmt)) skip1white(s); return(0); } static void pnmget_init(LOADSTATE *s) { switch (s->img->fmt) { case FF_PBM: case FF_RPBM: s->pbmbit = 0; break; default: break; } } static int pnmgetcomponent(LOADSTATE *s, int maxval, const char *what) { int v; v = pnmgetnum(s,"pixel"); if (v < 0) return(-1); if (v > maxval) { fprintf(stderr,"%s: %s: %s value %d is above maxval %d\n",__progname,s->fn,what,v,maxval); return(-1); } return((v*(maxval+1))/256); } static int pnmgetraw(LOADSTATE *s, int maxval, const char *what) { int v; v = load_get(s); if (v == EOF) return(1); if (v > maxval) { fprintf(stderr,"%s: %s: %s value %d is above maxval %d\n",__progname,s->fn,what,v,maxval); return(-1); } return((v*(maxval+1))/256); } static int pnmget_pixel(LOADSTATE *s, PIXEL *pp) { int v; switch (s->img->fmt) { default: bugcheck("impossible image format %d",(int)s->img->fmt); break; case FF_PBM: v = pnmgetnum(s,"pixel"); if (v < 0) return(1); v = v ? 0 : 255; pp->r = v; pp->g = v; pp->b = v; pp->a = 0; break; case FF_RPBM: if (! s->pbmbit) { v = load_get(s); if (v == EOF) return(1); s->pbmbuf = v; s->pbmbit = 0x80; } v = (s->pbmbuf & s->pbmbit) ? 0 : 255; s->pbmbit >>= 1; pp->r = v; pp->g = v; pp->b = v; pp->a = 0; break; case FF_PGM: v = pnmgetcomponent(s,s->img->maxval,"PGM pixel"); if (v < 0) return(1); pp->r = v; pp->g = v; pp->b = v; pp->a = 0; break; case FF_RPGM: v = pnmgetraw(s,s->img->maxval,"raw-PGM pixel"); if (v < 0) return(1); pp->r = v; pp->g = v; pp->b = v; pp->a = 0; break; case FF_PPM: v = pnmgetcomponent(s,s->img->maxval,"PPM R channel"); if (v < 0) return(1); pp->r = v; v = pnmgetcomponent(s,s->img->maxval,"PPM G channel"); if (v < 0) return(1); pp->g = v; v = pnmgetcomponent(s,s->img->maxval,"PPM B channel"); if (v < 0) return(1); pp->b = v; pp->a = 0; break; case FF_RPPM: v = pnmgetraw(s,s->img->maxval,"raw-PPM R channel"); if (v < 0) return(1); pp->r = v; v = pnmgetraw(s,s->img->maxval,"raw-PPM G channel"); if (v < 0) return(1); pp->g = v; v = pnmgetraw(s,s->img->maxval,"raw-PPM B channel"); if (v < 0) return(1); pp->b = v; pp->a = 0; break; case FF_PAM: v = pnmgetcomponent(s,s->img->maxval,"PAM R channel"); if (v < 0) return(1); pp->r = v; v = pnmgetcomponent(s,s->img->maxval,"PAM G channel"); if (v < 0) return(1); pp->g = v; v = pnmgetcomponent(s,s->img->maxval,"PAM B channel"); if (v < 0) return(1); pp->b = v; v = pnmgetcomponent(s,s->img->maxval2,"PAM alpha channel"); if (v < 0) return(1); pp->a = v; break; case FF_RPAM: v = pnmgetraw(s,s->img->maxval,"raw-PAM R channel"); if (v < 0) return(1); pp->r = v; v = pnmgetraw(s,s->img->maxval,"raw-PAM G channel"); if (v < 0) return(1); pp->g = v; v = pnmgetraw(s,s->img->maxval,"raw-PAM B channel"); if (v < 0) return(1); pp->b = v; v = pnmgetraw(s,s->img->maxval2,"raw-PAM alpha channel"); if (v < 0) return(1); pp->a = v; break; } return(0); } static void pnmget_endrow(LOADSTATE *s) { switch (s->img->fmt) { case FF_PBM: case FF_RPBM: s->pbmbit = 0; break; default: break; } } static void load_image(void) { LOADSTATE s; int x; int y; PIXEL *pp; if (! filename) { fprintf(stderr,"%s: must specify a filename\n",__progname); exit(1); } s.fd = open(filename,O_RDONLY,0); if (s.fd < 0) { fprintf(stderr,"%s: can't open %s: %s\n",__progname,filename,strerror(errno)); exit(1); } s.fn = filename; s.rfill = 0; s.rptr = 0; s.f = funopen(&s,&load_r,0,0,0); if (! s.f) { fprintf(stderr,"%s: can't fdopen %s: %s\n",__progname,filename,strerror(errno)); exit(1); } s.img = ℑ if (load_header(&s)) { fclose(s.f); close(s.fd); return; } image.data = malloc(image.w*image.h*sizeof(PIXEL)); if (image.data == 0) { fprintf(stderr,"%s: %s: can't allocate space for %dx%d image\n",__progname,filename,image.w,image.h); exit(1); } pnmget_init(&s); pp = image.data; for (y=0;y (1) { k = va_arg(ap,int); switch (k) { case GCWC_END: break <"args">; case GCWC_DEFAULT: if (g->shadow.foreground != 0) { g->shadow.foreground = 0; g->dirty |= GCForeground; } break; case GCWC_FOREGROUND: v_uli = va_arg(ap,unsigned long int); if (g->shadow.foreground != v_uli) { g->shadow.foreground = v_uli; g->dirty |= GCForeground; } break; default: abort(); break; } } va_end(ap); if (g->dirty) XChangeGC(disp,g->gc,g->dirty,&g->shadow); } static Display *open_display(char *disp) { Display *rv; rv = XOpenDisplay(disp); if (rv == 0) { fprintf(stderr,"%s: can't open display %s\n",__progname,XDisplayName(disp)); exit(1); } return(rv); } static int err(Display *d, XErrorEvent *ee) { return((*preverr)(d,ee)); } static int ioerr(Display *d) { return((*prevIOerr)(d)); } static void setup_db(void) { char *str; char *home; XrmDatabase db2; db = XrmGetStringDatabase(defaults); str = XResourceManagerString(disp); if (str) { db2 = XrmGetStringDatabase(str); XrmMergeDatabases(db2,&db); } else { home = getenv("HOME"); if (home) { str = malloc(strlen(home)+1+10+1); sprintf(str,"%s/.Xdefaults",home); db2 = XrmGetFileDatabase(str); if (db2) { XrmMergeDatabases(db2,&db); } free(str); } } } static void maybeset(char **strp, char *str) { if (str && !*strp) *strp = str; } static char *get_default_value(const char *name, const char *class) { char *type; XrmValue value; if (XrmGetResource(db,name,class,&type,&value) == False) return(0); return(value.addr); } static void setup_font(void) { deffont = 0; font = fontname ? XLoadQueryFont(disp,fontname) : 0; if (! font) { if (fontname) fprintf(stderr,"%s: can't load font %s, using server default\n",__progname,fontname); font = XQueryFont(disp,XGContextFromGC(XDefaultGCOfScreen(scr))); deffont = 1; } baselineskip = font->ascent + font->descent; } static void setup_colour(char *str, XColor *col) { if (XParseColor(disp,wincmap,str,col) == 0) { fprintf(stderr,"%s: bad color `%s'\n",__progname,str); exit(1); } while (1) { if (XAllocColor(disp,wincmap,col) == 0) { if (wincmap != defcmap) { fprintf(stderr,"%s: can't allocate colormap cell for color `%s'\n",__progname,str); exit(1); } wincmap = XCopyColormapAndFree(disp,wincmap); continue; } break; } } static void setup_colours(void) { wincmap = defcmap; setup_colour(foreground,&fgcolour); setup_colour(background,&bgcolour); setup_colour(bordercstr,&bdcolour); } static void setup_numbers(void) { if (bordermstr) margin = atoi(bordermstr); if (menumstr) menu_margin = atoi(menumstr); if (borderwstr) borderwidth = atoi(borderwstr); if (magfacstr) magfactor = atoi(magfacstr); } static void setup_cursors(void) { Pixmap pic; Pixmap mask; unsigned int siz; unsigned int h; int x; int y; /* Unfortunately writing the shapes[][] initializer naturally here means subscripting it as [y][x] instead of [x][y] below.... */ static unsigned int shapes[3][3] = { { XC_top_left_corner , XC_top_side , XC_top_right_corner }, { XC_left_side , 0 , XC_right_side }, { XC_bottom_left_corner, XC_bottom_side, XC_bottom_right_corner } }; for (y=0;y<3;y++) { for (x=0;x<3;x++) { if ((x == 1) && (y == 1)) { boxgrabcurs[1][1] = None; } else { Cursor c; c = XCreateFontCursor(disp,shapes[y][x]); XRecolorCursor(disp,c,&fgcolour,&bgcolour); boxgrabcurs[x][y] = c; } } } arrowcurs = XCreateFontCursor(disp,XC_left_ptr); XRecolorCursor(disp,arrowcurs,&fgcolour,&bgcolour); /* wish we could count on XC_crosshair to have a decent mask! */ XQueryBestSize(disp,CursorShape,rootwin,width,height,&siz,&h); if (h < siz) siz = h; if (width/40 < siz) siz = width / 40; if (height/40 < siz) siz = height / 40; if (! (siz & 1)) siz --; pic = XCreatePixmap(disp,rootwin,siz,siz,1); mask = XCreatePixmap(disp,rootwin,siz,siz,1); gcw_config(&bgc,GCWC_DEFAULT,GCWC_FOREGROUND,0L,GCWC_END); XFillRectangle(disp,mask,bgc.gc,0,0,siz,siz); gcw_config(&bgc,GCWC_FOREGROUND,1L,GCWC_END); #ifdef DIAGONAL_XHAIR XDrawLine(disp,mask,bgc.gc,0,0,siz-1,siz-1); XDrawLine(disp,mask,bgc.gc,0,1,siz-2,siz-1); XDrawLine(disp,mask,bgc.gc,1,0,siz-1,siz-2); XDrawLine(disp,mask,bgc.gc,0,siz-1,siz-1,0); XDrawLine(disp,mask,bgc.gc,0,siz-2,siz-2,0); XDrawLine(disp,mask,bgc.gc,1,siz-1,siz-1,1); #else XFillRectangle(disp,mask,bgc.gc,0,(siz/2)-1,siz,3); XFillRectangle(disp,mask,bgc.gc,(siz/2)-1,0,3,siz); #endif XFillRectangle(disp,mask,bgc.gc,(siz/2)-4,(siz/2)-4,9,9); gcw_config(&bgc,GCWC_FOREGROUND,0L,GCWC_END); XFillRectangle(disp,pic,bgc.gc,0,0,siz,siz); XFillRectangle(disp,mask,bgc.gc,(siz/2)-1,(siz/2)-1,3,3); gcw_config(&bgc,GCWC_FOREGROUND,1L,GCWC_END); #ifdef DIAGONAL_XHAIR XDrawLine(disp,pic,bgc.gc,1,1,siz-2,siz-2); XDrawLine(disp,pic,bgc.gc,1,siz-2,siz-2,1); #else XDrawLine(disp,pic,bgc.gc,1,siz/2,siz-2,siz/2); XDrawLine(disp,pic,bgc.gc,siz/2,1,siz/2,siz-2); #endif XDrawRectangle(disp,pic,bgc.gc,(siz/2)-3,(siz/2)-3,6,6); gcw_config(&bgc,GCWC_FOREGROUND,0L,GCWC_END); XFillRectangle(disp,pic,bgc.gc,(siz/2)-2,(siz/2)-2,5,5); xhaircurs = XCreatePixmapCursor(disp,pic,mask,&fgcolour,&bgcolour,siz/2,siz/2); XFreePixmap(disp,pic); XFreePixmap(disp,mask); } static void setup_gcw(GCW *g, Drawable d) { g->shadow.function = GXcopy; g->shadow.plane_mask = ~0UL; g->shadow.foreground = 0; g->shadow.background = 1; g->shadow.line_width = 0; g->shadow.line_style = LineSolid; g->shadow.cap_style = CapButt; g->shadow.join_style = JoinMiter; g->shadow.fill_style = FillSolid; g->shadow.fill_rule = EvenOddRule; g->shadow.arc_mode = ArcPieSlice; g->shadow.tile = None; g->shadow.stipple = None; g->shadow.ts_x_origin = 0; g->shadow.ts_y_origin = 0; g->shadow.font = 0; g->shadow.subwindow_mode = ClipByChildren; g->shadow.graphics_exposures = True; g->shadow.clip_x_origin = 0; g->shadow.clip_y_origin = 0; g->shadow.clip_mask = None; g->shadow.dash_offset = 0; g->shadow.dashes = 4; g->dirty = 0; if (! deffont) { g->shadow.font = font->fid; g->dirty |= GCFont; } g->gc = XCreateGC(disp,d,g->dirty,&g->shadow); g->dirty = 0; } static void setup_gcs(void) { Pixmap pm; setup_gcw(&wgc,(Drawable)rootwin); pm = XCreatePixmap(disp,rootwin,1,1,1); setup_gcw(&bgc,(Drawable)pm); XFreePixmap(disp,pm); } int main(int, char **); int main(int ac, char **av) { saveargv(ac,av); handleargs(ac,av); load_image(); disp = open_display(displayname); if (synch) XSynchronize(disp,True); preverr = XSetErrorHandler(err); prevIOerr = XSetIOErrorHandler(ioerr); scr = XDefaultScreenOfDisplay(disp); width = XWidthOfScreen(scr); height = XHeightOfScreen(scr); depth = XDefaultDepthOfScreen(scr); rootwin = XRootWindowOfScreen(scr); defcmap = XDefaultColormapOfScreen(scr); visual = XDefaultVisualOfScreen(scr); setup_db(); maybeset(&geometryspec,get_default_value("xbme.geometry","Editor.Geometry")); maybeset(&fontname,get_default_value("xbme.font","Editor.Font")); maybeset(&foreground,get_default_value("xbme.foreground","Editor.Foreground")); maybeset(&background,get_default_value("xbme.background","Editor.Background")); maybeset(&bordercstr,get_default_value("xbme.borderColor","Editor.BorderColor")); maybeset(&borderwstr,get_default_value("xbme.borderWidth","Editor.BorderWidth")); maybeset(&bordermstr,get_default_value("xbme.borderMargin","Editor.BorderMargin")); maybeset(&magfacstr,get_default_value("xbme.magFactor","Editor.MagFactor")); maybeset(&menumstr,get_default_value("xbme.menuMargin","Editor.MenuMargin")); maybeset(&name,get_default_value("xbme.name","Editor.Name")); maybeset(&iconname,get_default_value("xbme.iconName","Editor.IconName")); setup_font(); setup_colours(); setup_numbers(); setup_gcs(); setup_cursors(); // setup_windows(); // setup_fat_pix(); return(0); }