Ce programme reprend en grande partie la méthode utilisé dans Xspect. Cette-à-dire qu'il essaie d'allouer les couleurs dans la palette courante, et en cas d'échec il crée une palette virtuelle. Pour tester, les résultats, nous affichons une mire des couleurs.
/* INCLUDES */ /* -------- */ /* standard */ #include <stdio.h> #include <stdlib.h> /* XLib */ #include <X11/Xlib.h> #include <X11/Xutil.h> #include <X11/Xos.h> /* MOTIF */ #include <Xm/FileSB.h> #include <Xm/DrawingA.h> #include <Xm/PushBG.h> #include <Xm/RowColumn.h> /* DEFINES */ /* ------- */ #define charset XmSTRING_DEFAULT_CHARSET #define MAX_PLANE 2 #define MAX_CELL ((MAX_COLOR) * (1 << (MAX_PLANE))) #define MAX_COLOR 16 #define CANNOT_OVERLAY 0 #define CAN_OVERLAY 1 #define MAX_CHAR 256 #define UNDEFINED -1 #define WIDTH 400 #define HEIGHT 300 /* TYPES */ /* ----- */ typedef char STRING[MAX_CHAR]; /* Constantes de couleurs */ /* ---------------------- */ static short valStd8[][3] = { 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0xFF, 0x00, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00 }; /* Variables globales */ /* ------------------ */ Display *display; int screen_num; Window window; unsigned long planeMasks[MAX_PLANE]; unsigned long pixels[MAX_COLOR]; XColor exactDefs[MAX_CELL]; Colormap colormap, mycolormap; int iwhite = UNDEFINED; int iblack = UNDEFINED; int ifg = UNDEFINED; int ibg = UNDEFINED; Pixmap pixmap; void blkToZero(str) char *str; { int i; char *ptr = str; for (i = 0; i < strlen(str); i++, ptr++) { if (*ptr == ' ') *ptr = '0'; } } void fin() { /* Restore the old colormap */ if (mycolormap!=colormap) { printf("Restore the old colormap\n"); XFreeColormap(display,mycolormap); } exit(); } /* Programme Principal */ /* ------------------- */ main(argc,argv) int argc; char *argv[]; { Widget topLevel,text_w, dialog,drawing_a, pb; XtAppContext app; XGCValues gcv; GC gc; extern void exit(), echo_file(); void DessinePalette(); void initColors(); void drawing_area_callback(); topLevel=XtVaAppInitialize(&app, "Demos", NULL, 0, &argc, argv, NULL, XmNwidth, WIDTH, XmNheight, HEIGHT, NULL); display = XtDisplay(topLevel); screen_num = DefaultScreen(display); window=XtWindow(topLevel); initColors(8); XtVaSetValues(topLevel,XmNcolormap,mycolormap,NULL); /* Create a drawing area widget */ drawing_a=XtVaCreateWidget("drawing_a", xmDrawingAreaWidgetClass, topLevel, NULL); XtAddCallback(drawing_a,XmNexposeCallback,drawing_area_callback,NULL); gc = XCreateGC(XtDisplay(drawing_a), RootWindowOfScreen(XtScreen(drawing_a)), 0, NULL); XtVaSetValues(drawing_a,XmNuserData,gc,NULL); /* Create a pixmap the same size as the drawing area */ pixmap=XCreatePixmap(XtDisplay(drawing_a), RootWindowOfScreen(XtScreen(drawing_a)),WIDTH,HEIGHT, DefaultDepthOfScreen(XtScreen(drawing_a))); /* Clear pixmap with white */ XSetForeground(XtDisplay(drawing_a), gc, WhitePixelOfScreen(XtScreen(drawing_a))); XFillRectangle(XtDisplay(drawing_a), pixmap,gc,0,0,WIDTH,HEIGHT); DessinePalette(drawing_a); /* Add a pushbutton the user can use to close */ pb = XtVaCreateManagedWidget("Close", xmPushButtonGadgetClass, drawing_a, NULL); /* if activated call the callback */ XtAddCallback(pb,XmNactivateCallback, fin,NULL); /* create a file selection dialog */ dialog=XmCreateFileSelectionDialog(topLevel,"filesb",NULL,0); XtAddCallback(dialog,XmNcancelCallback,exit,NULL); XtAddCallback(dialog,XmNokCallback,echo_file,NULL); XtManageChild(dialog); /* main loop */ XtManageChild(drawing_a); XtRealizeWidget(topLevel); XtAppMainLoop(app); } /* Fonction Callback appelee lors de l'activation de la fenetre */ /* ou de sa re-exposition */ /* ------------------------------------------------------------ */ void drawing_area_callback(widget,data,cbs) Widget widget; XtPointer data; XmDrawingAreaCallbackStruct *cbs; { XEvent *event=cbs->event; Display *dpy=event->xany.display; if (cbs->reason == XmCR_EXPOSE || cbs->reason == XmCR_ACTIVATE) { GC gc; XtVaGetValues(widget,XmNuserData,&gc,NULL); XCopyArea(dpy,pixmap, event->xany.window,gc,0,0,WIDTH,HEIGHT,0,0); } } /* Write the name of the selected file on the screen */ /* ------------------------------------------------- */ void echo_file(fs,client_data,cbs) Widget fs; /* file selection box */ XtPointer client_data; XmFileSelectionBoxCallbackStruct *cbs; { char *filename; if (!XmStringGetLtoR(cbs->value,charset,&filename)) return; if (!*filename) { printf("No file selected."); XtFree(filename); return; } printf("Filename given : %s \n",filename); XtFree(filename); } /* Draw the colormap in a window */ /* ----------------------------- */ void DessinePalette(widget) Widget widget; { int i; int step = (4 * WIDTH / 5) / MAX_COLOR; GC gc; XtVaGetValues(widget,XmNuserData,&gc,NULL); for (i=0;i<MAX_COLOR;i++) { XSetForeground(XtDisplay(widget), gc, exactDefs[i].pixel); XFillRectangle(XtDisplay(widget),pixmap,gc,i*step,0,step,HEIGHT); } } /* colormap initialisation */ /* ----------------------- */ void initColors(ncolor) int ncolor; { XVisualInfo visualInfo; int defaultDepth=DefaultDepth(display,screen_num); int nplane, ncell; colormap = DefaultColormap(display,screen_num); mycolormap=colormap; nplane = 2; ncell = ncolor * (1 << nplane); if (defaultDepth == 1) { /* must be StaticGray, use black and white */ printf("The screen can only have 2 colors."); ncolor = 0; nplane = 2; ncell = 2; } if (!XMatchVisualInfo(display, screen_num, defaultDepth, PseudoColor, &visualInfo)) { if (!XMatchVisualInfo(display, screen_num, defaultDepth, DirectColor, &visualInfo)) { /* No PseudoColor or TrueColor visual available at defaultDepth. * Some applications might try for a GrayScale visual * here if they can use gray to advantage, before * giving up and using black and white. */ printf("initColors: TODO HERE: try for a GrayScale... \n"); } } if ( getColors(ncolor, nplane, ncell, &planeMasks[0], &pixels[0], &exactDefs[0]) == CANNOT_OVERLAY ) printf("We can't allocate enough colors for overlay.\n"); } int getColors(maxColors, maxPlanes, maxCells, planeMasks, pixels, exactDefs) int maxColors; int maxPlanes; int maxCells; unsigned long planeMasks[MAX_PLANE]; unsigned long pixels[MAX_COLOR]; XColor exactDefs[MAX_CELL]; { STRING name[MAX_CELL]; XColor *pExDef; Colormap defaultCmap = colormap; int nbCells = maxCells; int power2maxPlanes; int i, j, k; int class; void createPrivateMap(); /* compute our private color map */ createPrivateMap(&valStd8[0][0], name, maxColors, maxPlanes, maxCells, planeMasks, pixels, exactDefs); iwhite = 0; ibg = 1; /* cyan */ iblack = 7; ifg = 3; /* blue */ if (XAllocColorCells(display, defaultCmap, False, planeMasks, maxPlanes, pixels, maxColors) == 0) { fprintf(stderr,"Can't alloc enough colors in the current color map. Creation of a new one. \n"); if ((defaultCmap=XCopyColormapAndFree(display,colormap)) == BadAlloc) fprintf(stderr, "\nCan't Create new colormap\n"); if (XAllocColorCells(display, defaultCmap, False, planeMasks, maxPlanes, pixels, maxColors) == 0) { fprintf(stderr,"\nCan't allocate %d colors after created the new color map\n\ This is a big problem !\n",maxColors); exit(0); } } /* allocated colorcells succesfully, * now set their colors */ for (i = 0; i < maxCells; i++) { exactDefs[i].flags = DoRed | DoGreen | DoBlue; if (! XParseColor(display, defaultCmap, name[i], &exactDefs[i])) fprintf(stderr,"basic: color name %s not in database", name[i]); printf("%s\n",name[i]); } /* set pixel value in struct to the allocated ones */ for (i = 0; i < (1 << maxPlanes); i++) for (j = 0; j < maxColors; j++) { unsigned long msk = 0; for (k = 0; k < maxPlanes; k++) { int bool = ((1 << k) & i) >> k; msk |= bool * planeMasks[k]; } exactDefs[i * maxColors + j].pixel = pixels[j] | msk; } /* this sets the color of the read/write cells */ XStoreColors(display, defaultCmap, exactDefs, nbCells); if (defaultCmap!=colormap) { mycolormap=defaultCmap; XInstallColormap(display,mycolormap); } if (nbCells >= 4) return (CAN_OVERLAY); else return (CANNOT_OVERLAY); } void createPrivateMap(val, name, maxColors, maxPlanes, maxCells, planeMasks, pixels, exactDefs) short val[][3]; STRING name[MAX_CELL]; int maxColors; int maxPlanes; int maxCells; unsigned long planeMasks[MAX_PLANE]; unsigned long pixels[MAX_COLOR]; XColor exactDefs[MAX_CELL]; { int i, j; int fr1, fg1, fb1; int fr2, fg2, fb2; int fr3, fg3, fb3; double coeff = 1.5; printf("createPrivateMap..\n"); /* plan 1 */ fr1 = 0; fg1 = 255; fb1 = 0; /* plan 2 */ fr2 = 255; fg2 = 0; fb2 = 0; /* plan 1 & 2 */ fr3 = 255; fg3 = 255; fb3 = 0; i = 0; for (j = 0; j < maxColors; j++) { sprintf(name[i * maxColors + j], "#%2X%2X%2X\0", val[j][0], val[j][1], val[j][2]); blkToZero(name[i * maxColors + j]); } i = 1; for (j = 0; j < maxColors; j++) { double cr, cg, cb; cr = (coeff * val[j][0] + fr1) / (coeff + 1.); cg = (coeff * val[j][1] + fg1) / (coeff + 1.); cb = (coeff * val[j][2] + fb1) / (coeff + 1.); if (cr > 255.) cr = 255.; if (cg > 255.) cg = 255.; if (cb > 255.) cb = 255.; sprintf(name[i * maxColors + j], "#%2X%2X%2X\0", (int) cr, (int) cg, (int) cb); blkToZero(name[i * maxColors + j]); } i = 2; for (j = 0; j < maxColors; j++) { double cr, cg, cb; cr = (coeff * val[j][0] + fr2) / (coeff + 1.); cg = (coeff * val[j][1] + fg2) / (coeff + 1.); cb = (coeff * val[j][2] + fb2) / (coeff + 1.); if (cr > 255.) cr = 255.; if (cg > 255.) cg = 255.; if (cb > 255.) cb = 255.; sprintf(name[i * maxColors + j], "#%2X%2X%2X\0", (int) cr, (int) cg, (int) cb); blkToZero(name[i * maxColors + j]); } i = 3; for (j = 0; j < maxColors; j++) { double cr, cg, cb; cr = (coeff * val[j][0] + fr3) / (coeff + 1.); cg = (coeff * val[j][1] + fg3) / (coeff + 1.); cb = (coeff * val[j][2] + fb3) / (coeff + 1.); if (cr > 255.) cr = 255.; if (cg > 255.) cg = 255.; if (cb > 255.) cb = 255.; sprintf(name[i * maxColors + j], "#%2X%2X%2X\0", (int) cr, (int) cg, (int) cb); blkToZero(name[i * maxColors + j]); } }