/* grX11su2.c - * * ********************************************************************* * * Copyright (C) 1985, 1990 Regents of the University of California. * * * Permission to use, copy, modify, and distribute this * * * software and its documentation for any purpose and without * * * fee is hereby granted, provided that the above copyright * * * notice appear in all copies. The University of California * * * makes no representations about the suitability of this * * * software for any purpose. It is provided "as is" without * * * express or implied warranty. Export of this software outside * * * of the United States of America may require an export license. * * ********************************************************************* * * This file contains additional functions to manipulate an X * color display. Included here are rectangle drawing and color map * loading. */ #define HIRES /* There is NO reason to turn this off. With HIRES defined the code tests if 8bit pseudocolor is available and uses it if it is. Therefore, if the old code (assume 8bit pseudocolor) would work at all the new code will work the same way. */ /* debugging only */ /* #define HIRESDB */ #include #ifdef OS2 #include /* Current Linux has conflict with wchar_t, but OS2 needs stdlib.h */ #else char *getenv(); #endif #include #ifdef HIRES #include #endif #include "misc/magic.h" #include "textio/textio.h" #include "utils/geometry.h" #ifdef HIRES #include "graphics/glyphs.h" #endif #include "graphics/graphics.h" #include "windows/windows.h" #include "graphics/graphicsInt.h" #include "grX11Int.h" #ifdef HIRES extern char *DBWStyleType; unsigned long grPixels[256]; unsigned long grPlanes[256]; XColor colors[256*3]; /* Unique colors used by Magic */ #else unsigned long grPixels[128]; unsigned long grPlanes[128]; XColor colors[256]; /* Unique colors used by Magic */ #endif Visual *grVisual; int grClass; unsigned long grCompleteMask; Colormap grXcmap; /* disgusting machine-dependent constants - see below */ #ifdef macII #define X_COLORMAP_BASE 128 #define X_COLORMAP_RESERVED 4 #else #if defined(OS2) || defined(CYGWIN) #define X_COLORMAP_BASE 128 #define X_COLORMAP_RESERVED 0 #else #define X_COLORMAP_BASE 0 #define X_COLORMAP_RESERVED 2 #endif #endif /*--------------------------------------------------------- * GrXSetCMap: I've seen about 6 versions of this procedure now, all of them flawed in some way or another. I expect this one to be no different... Anyway, the idea here is to first try allocating the required planes out of the default colormap. This is the kindest, gentlest thing to do because it doesn't cause all the other windows to go technicolor when the cursor is in a magic window. If this fails, we go ahead and allocate a colormap specifically for magic. The problem now is using this colormap in such a way that the other windows' colors get mangled the least. Unfortunately, doing this is X-server dependent. This is where the constants above come in. X_COLORMAP_BASE indicates which part of the colormap (assuming the number of planes required is less than the number of planes in the display) to fill in the colors magic requires. X_COLORMAP_RESERVED tells how many high-end colors the server won't let us touch; if we even try to query these colors, we get an X error. If, starting at X_COLORMAP_BASE, the number of colors required would push us into the top X_COLORMAP_RESERVED colors, then we won't be able to set all the colors the user wanted us to set. The top colors will remain identical to those in the default colormap. There are clearly some shortcomings in this approach. For example, a server might reserve colors at the bottom of the colormap. Since I haven't seen such a server yet and I'm really sick of X11, this eventuality is not supported. The best way to use Magic under X is to pick a number of planes small enough to fix in the default colormap, and not to waste random colors on things like xterms, xclocks and xbiffs. Do you really need a yellow and black xterm and a red xclock? Think about it. * * * Results: None. * * Side Effects: * The values in the color map are set from the array indicated * by pmap. X color cells are allocated if this display has * more than 1 plane. * * Errors: None. * *--------------------------------------------------------- */ Void GrX11SetCMap (pmap) char *pmap; /* A pointer to 256*3 bytes containing the * new values for the color map. The first * three values are red, green, and blue * intensities for color 0, and so on. */ { char *p; int i,j; #ifdef HIRES static unsigned long planes[32]; XVisualInfo grvisual_info, *grvisual_get, grtemplate; VisualID defpsvid; int defpsindex = -1; int gritems, gritems_list, grcolorCount; int red_size, green_size, blue_size, red_shift, green_shift, blue_shift; int red_mask, green_mask, blue_mask; char *visual_type[7]; #define visual_table_len 7 int visual_table[visual_table_len]; char *log_color, *env_str; int color_base, color_reserved; #else static unsigned long planes[8]; #endif int status; unsigned long basepixel; static int firstCall = 1; static int planeCount; /* how many planes we want to allocate */ static int colorCount; /* how many colors we want to allocate */ static int realColors; /* how many colors we actually do allocate */ if (firstCall) { firstCall = 0; #ifdef HIRES visual_type[0] = "StaticGrey"; visual_type[1] = "GreyScale"; visual_type[2] = "StaticColor"; visual_type[3] = "PseudoColor"; visual_type[4] = "TrueColor"; visual_type[5] = "DirectColor"; visual_type[6] = "UNKNOWN"; #else /* Cannot hold the total set of colors in an array for grCurrent.depth > 8 */ colorCount = 1 << grCurrent.depth; realColors = colorCount; #endif grXcmap = XDefaultColormap(grXdpy,grXscrn); #ifdef HIRES /* Discover properties of Server. */ grVisual = XDefaultVisual(grXdpy, grXscrn); defpsvid = XVisualIDFromVisual(grVisual); grtemplate.screen = grXscrn; grtemplate.depth = 0; grvisual_get = XGetVisualInfo(grXdpy, VisualScreenMask, &grtemplate, &gritems); if(grvisual_get == NULL) { TxPrintf("Could not obtain Visual Info from Server %s. Will attempt default.\n", getenv("DISPLAY"));} else { #ifdef HIRESDB TxPrintf("Server Vendor: %s\n", ServerVendor(grXdpy)); TxPrintf("Vendor Release: %d\n", VendorRelease(grXdpy)); TxPrintf("Protocol Version: %d\n", ProtocolVersion(grXdpy)); TxPrintf("Protocol Revision: %d\n", ProtocolRevision(grXdpy)); #ifdef OS2 TxPrintf("HOSTTYPE: i386-OS/2\n"); #else TxPrintf("HOSTTYPE: %s\n", getenv("HOSTTYPE")); #endif TxPrintf("XGetVisualInfo returned visuals list of length %d:\n", gritems); TxPrintf("Default VisualID 0x%x\n", defpsvid); #endif gritems_list = gritems; for(gritems = 0; gritems < gritems_list; gritems++) { j = grvisual_get[gritems].class; if( j < 0 || j > 5) { TxPrintf("Unknown visual class index: %d\n", j); j = 6; } #ifdef HIRESDB TxPrintf("Found Visual Class %s, ID 0x%x with:\n depth %d, colormap_size %d, bits_per_rgb %d.\n", visual_type[j], grvisual_get[gritems].visualid, grvisual_get[gritems].depth, grvisual_get[gritems].colormap_size, grvisual_get[gritems].bits_per_rgb); if(grvisual_get[gritems].class == 4) { TxPrintf(" TrueColor masks: red %06x, green %06x, blue %06x\n", grvisual_get[gritems].red_mask, grvisual_get[gritems].green_mask, grvisual_get[gritems].blue_mask); } #endif if ((grvisual_get[gritems].class == 3) && (grvisual_get[gritems].visualid == defpsvid)) { defpsindex = gritems;} } /* Unfortunately, the list returned by Xservers has classes in random order. Therefore, a search is needed to find a good choice. The only currently supported classes are PseudoColor at depth 8 and TrueColor at depth 15, 16, and 24. It is likely that TrueColor depths 8 through 32 will work, but these have not been tested. In addition, it has been discovered that some SUN systems "offer" more than one Pseudocolor at depth 8, but with differing colormap sizes. There is nothing about how to handle this in the X11 documentation, so the search below chooses the "first" class. The class with 256 colors seems preferable and works at present. The second Pseudocolor in the list gives a BatMatch reject from the server, so it is useless. Basing the selection on 256 colors might be effective, but might conflict in other cases... As usual X11 is just guesswork. At present the preferred order is: PseudoColor at 8, then TrueColor at 24, then TrueColor at 16, ... Unless this is overridden by the MAGIC_COLOR environment variable, which can be: bw, 8, 16, 24 */ for(j = 0; j < visual_table_len; j++) { visual_table[j] = -1; } for(j = 0; j < gritems_list; j++) { if((grvisual_get[j].class == 0) && (grvisual_get[j].depth == 8) && (visual_table[1] == -1)) visual_table[1] = j; /* StaticGrey */ if((grvisual_get[j].class == 1) && (grvisual_get[j].depth == 8) && (visual_table[2] == -1)) visual_table[2] = j; /* GreyScale */ if((grvisual_get[j].class == 3) && (grvisual_get[j].depth == 8) && (visual_table[3] == -1)) visual_table[3] = j; /* Psuedocolor */ if((grvisual_get[j].class == 4) && (grvisual_get[j].depth == 15) && (visual_table[4] == -1)) visual_table[4] = j; /* TrueColor */ if((grvisual_get[j].class == 4) && (grvisual_get[j].depth == 16) && (visual_table[5] == -1)) visual_table[5] = j; /* TrueColor */ if((grvisual_get[j].class == 4) && (grvisual_get[j].depth == 24) && (visual_table[6] == -1)) visual_table[6] = j; /* TrueColor */ } if(defpsindex != -1) { visual_table[3] = defpsindex; } log_color = getenv("MAGIC_COLOR"); /* Allow environment variables to override the colormap base and */ /* number of reserved colors, as these depend on the terminal X */ /* server, NOT on the machine running magic. */ /* Note: ought to use something that checks for errors in place */ /* of atoi(). */ env_str = getenv("X_COLORMAP_BASE"); if (env_str != NULL) color_base = (int)atoi(env_str); else color_base = X_COLORMAP_BASE; env_str = getenv("X_COLORMAP_RESERVED"); if (env_str != NULL) color_reserved = (int)atoi(env_str); else color_reserved = X_COLORMAP_RESERVED; gritems = -1; if(log_color != NULL) { if(strncmp(log_color, "8bit", 4) == 0) gritems = visual_table[3]; if(strncmp(log_color, "15bit", 5) == 0) gritems = visual_table[4]; if(strncmp(log_color, "16bit", 5) == 0) gritems = visual_table[5]; if(strncmp(log_color, "24bit", 5) == 0) gritems = visual_table[6]; if(gritems == -1) { printf("The visual mode %s is not available. Sorry.\n", log_color); XFree(grvisual_get); MainExit(1); } } else { if(visual_table[3] != -1) gritems = visual_table[3]; else if(visual_table[6] != -1) gritems = visual_table[6]; else if(visual_table[5] != -1) gritems = visual_table[5]; else if(visual_table[4] != -1) gritems = visual_table[4]; } if(gritems == -1) { TxPrintf("Neither TrueColor 15, 16 nor 24, nor PseudoColor 8 found. "); TxPrintf("Cannot initialize DISPLAY %s\n", getenv("DISPLAY")); XFree(grvisual_get); MainExit(1); } else { TxPrintf("Using %s, VisualID 0x%x depth %d\n", visual_type[grvisual_get[gritems].class], grvisual_get[gritems].visualid, grvisual_get[gritems].depth); } grClass = grvisual_get[gritems].class; grVisual = grvisual_get[gritems].visual; grcolorCount = grvisual_get[gritems].colormap_size; grCurrent.depth = grvisual_get[gritems].depth; red_mask = grvisual_get[gritems].red_mask; green_mask = grvisual_get[gritems].green_mask; blue_mask = grvisual_get[gritems].blue_mask; } XFree(grvisual_get); planeCount = grCurrent.depth; colorCount = grcolorCount; realColors = colorCount; if(planeCount > 8) { /* must load appropriate Dstyle file. */ grDStyleType = "24bit"; if(GrLoadStyles(DBWStyleType, ".", SysLibPath)) MainExit(); } if(planeCount == 8) { grCurrent.depth = 7; planeCount = 7; /* This resets to old 7-plane mode */ colorCount = 1 << (planeCount); realColors = colorCount; } #endif if(grCurrent.depth) { #ifdef HIRES status = 0; if(grClass != 4) #endif status= XAllocColorCells(grXdpy,grXcmap,True,planes,planeCount, &basepixel,1); if (status == 0) /* ok, we tried to be nice; now lets whack the default colormap and put in one of our own. */ { #ifdef HIRES int actualColors = grcolorCount; #else int actualColors = 1 << XDefaultDepth(grXdpy,grXscrn); #endif int usableColors = actualColors - color_reserved; #ifdef HIRES if(usableColors > 256) usableColors = 256; if(grClass != 4) #endif TxPrintf("Unable to allocate %d planes in default colormap; making a new one.\n",planeCount); if(planeCount <= 8) { #ifdef HIRES grXcmap = XCreateColormap(grXdpy,grCurrent.window, grVisual, AllocAll); #else grXcmap = XCreateColormap(grXdpy,grCurrent.window, XDefaultVisual(grXdpy, grXscrn), AllocAll); #endif #ifdef HIRESDB TxPrintf("actualColors %d, usableColors %d, planeCount %d\n", actualColors, usableColors, planeCount); #endif basepixel = color_base; } else { #ifdef HIRES grXcmap = XCreateColormap(grXdpy,grCurrent.window, grVisual, AllocNone); #else grXcmap = XCreateColormap(grXdpy,grCurrent.window, XDefaultVisual(grXdpy, grXscrn), AllocNone); #endif basepixel = 0; } for (j=0; j < planeCount; j++) planes[j] = 1< usableColors)? usableColors-basepixel: colorCount; #ifdef HIRES if ((realColors != colorCount) && (planeCount <= 8)) #else if (realColors != colorCount) #endif { TxPrintf("Only %d contiguous colors were available.\n",realColors); colorCount=realColors; } } if (grXcmap == 0 || status ==0) { TxError( "X11 setup: Unable to allocate %d planes\n",planeCount); MainExit(1); } /* grCompleteMask is a mask of all the planes not used by this technology. It is OR'd in with the mask that magic supplies to ensure that unused bits of the pixel are cleared. grNumBitPlanes is set when the dstyles file is read in; for the following to work, the dstyles file must be read before the colormap. I changed main.c so that this was the case. If you aren't getting mutually exclusive colors, this may be why. -dcs */ #ifdef HIRES #ifdef HIRESDB TxPrintf("planeCount %d, realColors %d\n", planeCount, realColors); #endif if(planeCount > 8) { p = pmap; if(planeCount == 16) { red_size = 5; green_size = 6; blue_size = 5; } else if(planeCount == 15) { red_size = 5; green_size = 5; blue_size = 5; } else { red_size = 8; green_size = 8; blue_size = 8; } red_shift = green_size + blue_size; green_shift = blue_size; if((planeCount == 24) & (red_mask == 0xff)) { /* this is SUN Solaris doing it backwards: BGR */ red_shift = 0; green_shift = red_size; blue_shift = green_size + red_size; } /* DANGER! Modify the code below with care: gcc 2.7.2 generates bad code if the masks are not used as below. */ for (i=0;i != colorCount;i++) { if((planeCount == 16) || (planeCount ==15)) { grPixels[i] = (long)(((*p++) >> (8 - red_size)) << (green_size + blue_size)) & red_mask; /* red */ grPixels[i] |= (long)(((*p++) >> (8 - green_size)) << blue_size) & green_mask; /* green */ grPixels[i] |= (long)((*p++) >> (8 - blue_size)) & blue_mask; /* blue */ } else if((planeCount == 24) & (red_mask == 0xff)) { /* this is SUN Solaris doing it backwards: BGR */ grPixels[i] = (long)((*p++) & red_mask); /* here is where gcc really goes wrong (sign extends) */ grPixels[i] |= (long)(((*p++) << green_shift) & green_mask); grPixels[i] |= (long)(((*p++) << blue_shift) & blue_mask); } else { grPixels[i] = (long)(((*p++)<< red_shift) & red_mask); grPixels[i] |= (long)(((*p++)<< green_shift) & green_mask); grPixels[i] |= (long)((*p++) & blue_mask); } } #ifdef HIRESDB TxPrintf("grPixels: %6x %6x %6x %6x\n", grPixels[0], grPixels[1], grPixels[2], grPixels[3]); #endif for(i=0; i < planeCount; i++) { planes[i] = 1 << i; grPlanes[i] = 0; for(j=0;j != planeCount;j++) if(i & (1< 7 || grNumBitPlanes <1) { TxError("display_styles must be 0 < p < 8 under X11"); GrX11Close(); MainExit(1); } if (grNumBitPlanes > planeCount) { TxError("Your display_styles uses %d planes but you only have %d\n",grNumBitPlanes,planeCount); GrX11Close(); MainExit(1); } for (i=0;i != grNumBitPlanes;i++) { grCompleteMask |= planes[i]; } grCompleteMask = AllPlanes & ~grCompleteMask; for (i=0;i != colorCount;i++) { grPixels[i] = basepixel; grPlanes[i] = grCompleteMask; for (j=0;j != planeCount;j++) if ( i & (1 <r_xbot; grx11Rects[grx11NbRects].y = grMagicToX(r->r_ytop); grx11Rects[grx11NbRects].width = r->r_xtop - r->r_xbot + 1; grx11Rects[grx11NbRects].height = r->r_ytop - r->r_ybot + 1; grx11NbRects++; } #ifdef NONMANHATTAN /*--------------------------------------------------------- * grx11FillPolygon: * This routine draws a solid polygon * * Results: None. * * Side Effects: * Drawing. *--------------------------------------------------------- */ Void grx11FillPolygon(tp, np) Point *tp; int np; { XPoint xp[5]; int i; for (i = 0; i < np; i++) { xp[i].x = tp[i].p_x; xp[i].y = grMagicToX(tp[i].p_y); } XFillPolygon(grXdpy, grCurrent.window, grGCFill, xp, np, Convex, CoordModeOrigin); } #endif