This is x11_stuff.c in view mode; [Download] [Up]
/*
* This software is copyrighted as noted below. It may be freely copied,
* modified, and redistributed, provided that the copyright notices are
* preserved on all copies.
*
* There is no warranty or other guarantee of fitness for this software,
* it is provided solely "as is". Bug reports or fixes may be sent
* to the author, who may or may not act on them as he desires.
*
* You may not include this software in a program or other software product
* without supplying the source, or without informing the end-user that the
* source is available for no extra charge.
*
* If you modify this software, you should include a notice giving the
* name of the person performing the modification, the date of modification,
* and the reason for such modification.
*/
/*
* x11_stuff.c - Do colormaps, visuals, pix_info window...
*
* Author: Spencer W. Thomas (x10)
* Computer Science Dept.
* University of Utah
* Date: Thu Feb 20 1986
* Copyright (c) 1986, University of Utah
*
* Modified: Andrew F. Vesper (x 11)
* High Performance Workstations
* Digital Equipment Corp
* Date: Fri, Aug 7, 1987
* Thu, Jan 14, 1988
* Copyright (c) 1987,1988, Digital Equipment Corporation
*
* Modified: Martin R. Friedmann (better X11, flipbook, mag, pix_info)
* Dept of Electrical Engineering and Computer Science
* University of Michigan
* Date: Tue, Nov 14, 1989
* Copyright (c) 1989, University of Michigan
*/
#include "getx11.h"
#include "circle.bitmap"
#include "circle_mask.bitmap"
static Boolean init_separate_color_rw(), init_color_rw(),
init_separate_color_ro(), init_color_ro(), init_mono_rw(), init_mono_ro();
static CONST_DECL char *visual_class_to_string();
extern int get_dither_arrays(), shift_match_left(), shift_match_right();
Cursor circle_cursor = NULL;
Cursor left_ptr_cursor = NULL;
Cursor watch_cursor = NULL;
static image_information *wait_img = NULL;
void set_watch_cursor( window )
Window window;
{
XDefineCursor( dpy, window, watch_cursor );
XFlush(dpy);
}
void set_circle_cursor( window )
Window window;
{
XDefineCursor( dpy, window, circle_cursor );
XFlush(dpy);
}
void set_left_ptr_cursor( window )
Window window;
{
XDefineCursor( dpy, window, left_ptr_cursor );
XFlush(dpy);
}
void get_cursors( window )
Window window;
{
if (circle_cursor == NULL)
circle_cursor = XCreateFontCursor (dpy, XC_circle);
if (watch_cursor == NULL)
watch_cursor = XCreateFontCursor (dpy, XC_watch);
if (left_ptr_cursor == NULL)
left_ptr_cursor = XCreateFontCursor (dpy, XC_left_ptr);
if (circle_cursor == NULL) {
Pixmap source;
Pixmap mask;
XColor color_1;
XColor color_2;
source = XCreateBitmapFromData(dpy, window, circle_bits,
circle_width, circle_height);
mask = XCreateBitmapFromData(dpy, window, circle_mask_bits,
circle_width, circle_height);
color_1.pixel = WhitePixel (dpy, screen);
color_1.red = 0xffff;
color_1.green = 0xffff;
color_1.blue = 0xffff;
color_1.flags = DoRed | DoGreen | DoBlue;
color_1.pixel = BlackPixel (dpy, screen);
color_2.red = 0;
color_2.green = 0;
color_2.blue = 0;
color_2.flags = DoRed | DoGreen | DoBlue;
circle_cursor = XCreatePixmapCursor (dpy, source, mask,
&color_1, &color_2,
circle_x_hot, circle_y_hot);
XFreePixmap (dpy, source);
XFreePixmap (dpy, mask);
}
if (watch_cursor == NULL)
watch_cursor = circle_cursor;
if (left_ptr_cursor == NULL)
left_ptr_cursor = circle_cursor;
}
XImage *get_X_image( img, width, height )
image_information *img;
int width, height;
{
XImage *image;
image = XCreateImage (dpy, img->dpy_visual,
(img->binary_img ? 1 : img->dpy_depth),
(img->binary_img ? XYBitmap : ZPixmap),
0, NULL, width, height, 32, 0);
if (image != NULL) {
image->data = (char *)malloc ( image->bytes_per_line * height );
if ( image->data == NULL) {
perror ( "malloc image->data" );
XDestroyImage (image);
image = NULL;
}
}
return (image);
}
void
determine_icon_size(image_width, image_height,
icon_width, icon_height, icon_factor )
int image_width, image_height;
int *icon_width, *icon_height, *icon_factor;
{
XIconSize *icon_sizes;
int icon_size_count;
int width, height, factor;
int i;
/*
* We want the Icon to be about DESIRED_ICON_WIDTH x DESIRED_ICON_HEIGHT.
* First, make sure that is OK with the window manager.
* Then figure out the icon scaling factor.
*/
#define DESIRED_ICON_WIDTH 48
#define DESIRED_ICON_HEIGHT 48
width = DESIRED_ICON_WIDTH;
height = DESIRED_ICON_HEIGHT;
if (XGetIconSizes (dpy, root_window, &icon_sizes, &icon_size_count)
&& icon_size_count >= 1) {
for (i = 0; i < icon_size_count; i++) {
if (icon_sizes[i].min_width <= DESIRED_ICON_WIDTH
&& icon_sizes[i].max_width >= DESIRED_ICON_WIDTH
&& icon_sizes[i].min_height <= DESIRED_ICON_HEIGHT
&& icon_sizes[i].max_height >= DESIRED_ICON_HEIGHT) {
break;
}
}
if (i >= icon_size_count) {
width = icon_sizes[0].max_width;
height = icon_sizes[0].max_height;
}
}
factor = image_width / width;
if (factor < image_height / height)
factor = image_height / height;
if ( factor == 0 )
factor = 1;
*icon_width = 1 + (image_width / factor);
*icon_height = 1 + (image_height / factor);
*icon_factor = factor;
}
static void handle_x_errors( dpy, event)
Display *dpy;
XErrorEvent *event;
{
XID xid = event->resourceid;
image_information *img = wait_img;
switch ( event->error_code ) {
case BadAlloc:
if ( img ) {
if ( xid == img->pixmap ){
img->pixmap = NULL;
img->pixmap_failed = True;
} else
if ( xid == img->icn_pixmap ){
img->icn_pixmap = NULL;
img->pixmap_failed = True;
} else
if (xid == img->mag_pixmap ){
img->mag_pixmap = NULL;
img->pixmap_failed = True;
} else
_XDefaultError (dpy, event);
break;
}
case BadWindow:
case BadDrawable:
case BadMatch:
_XDefaultError( dpy, event );
break;
default:
_XDefaultError( dpy, event );
break;
}
}
void get_x_colormap( img )
image_information *img;
{
img->colormap = XCreateColormap (dpy, root_window,
img->dpy_visual, AllocNone );
if (img->colormap == NULL)
fprintf(stderr, "Could not create color map for visual\n");
VPRINTF(stderr, "created colormap for visual type %s\n",
visual_class_to_string(img->visual_class));
}
void check_pixmap_allocation( img )
image_information *img;
{
wait_img = img;
XSetErrorHandler( handle_x_errors );
XSync( dpy, False );
}
/*
* Create a window with no help from user.
*/
void
create_windows( img, window_geometry )
char *window_geometry;
register image_information *img;
{
static XClassHint class_hint = {"getx11", "Getx11"};
char default_geometry[30];
int width, height, x, y;
XSizeHints size_hints;
unsigned int mask;
unsigned long gc_mask;
XGCValues gc_values;
XWMHints wm_hints;
XSetWindowAttributes xswa;
unsigned long xswa_mask;
Boolean new_window;
int icn_alloc = False;
Boolean new_pixmaps;
/*
* Now, make the window.
*/
new_window = (img->window == NULL && img->icn_window == NULL);
new_pixmaps = ((img->pixmap == NULL || img->icn_pixmap == NULL ||
img->mag_pixmap == NULL) && !img->pixmap_failed &&
!stingy_flag);
if ( !img->window )
{
sprintf( default_geometry, "=%dx%d", img->w, img->h );
mask = XGeometry(dpy, screen, window_geometry, default_geometry,
IMAGE_BORDERWIDTH, 1, 1, 0, 0,
&x, &y, &width, &height );
size_hints.flags = 0;
if ( mask & (XValue | YValue) ) {
size_hints.flags |= USPosition;
size_hints.x = x;
size_hints.y = y;
} else {
size_hints.flags |= PPosition;
size_hints.x = x = (DisplayWidth(dpy, screen) - width)/2;
size_hints.y = y = (DisplayHeight(dpy, screen) - height)/2;
}
if ( mask & (WidthValue | HeightValue) ) {
size_hints.flags |= USSize;
size_hints.width = width;
size_hints.height = height;
}
wm_hints.flags = InputHint;
wm_hints.input = True;
VPRINTF (stderr, "window at (%d, %d) %dx%d\n",
x, y, width, height);
xswa_mask = CWBackPixel | CWEventMask | CWBorderPixel;
xswa.background_pixel = BlackPixel (dpy, screen);
xswa.border_pixel = WhitePixel (dpy, screen);
xswa.event_mask = ButtonPressMask | ExposureMask | KeyPressMask;
if (img->colormap) {
xswa.colormap = img->colormap;
xswa_mask |= CWColormap;
}
img->window = XCreateWindow ( dpy, root_window, x, y,
width, height,
IMAGE_BORDERWIDTH, img->dpy_depth,
InputOutput, img->dpy_visual,
xswa_mask, &xswa);
XSetNormalHints (dpy, img->window, &size_hints);
XSetClassHint(dpy, img->window, &class_hint);
XSetWMHints(dpy, img->window, &wm_hints);
XSetIconName (dpy, img->window, img->title);
}
XStoreName(dpy, img->window, img->title);
if ( !img->pixmap && new_pixmaps )
img->pixmap = XCreatePixmap(dpy, img->window, img->w, img->h,
img->dpy_depth );
img->refresh_pixmap = img->pixmap;
if ( !img->icn_window )
{
xswa_mask = NULL;
if (img->colormap) {
xswa.colormap = img->colormap;
xswa_mask = CWColormap;
}
img->icn_window = XCreateWindow (dpy, root_window, 0, 0,
img->icn_w, img->icn_h,
0, img->dpy_depth,
InputOutput, img->dpy_visual,
xswa_mask, &xswa);
size_hints.flags = PMinSize | PMaxSize;
size_hints.min_width = img->icn_w;
size_hints.max_width = img->icn_w;
size_hints.min_height = img->icn_h;
size_hints.max_height = img->icn_h;
XSetNormalHints(dpy, img->icn_window, &size_hints);
XStoreName(dpy, img->icn_window, img->title);
}
if ( !img->gc )
{
gc_mask = 0;
gc_values.function = GXcopy; gc_mask |= GCFunction;
gc_values.plane_mask = AllPlanes; gc_mask |= GCPlaneMask;
gc_values.foreground = white_pixel; gc_mask |= GCForeground;
gc_values.background = black_pixel; gc_mask |= GCBackground;
img->gc = XCreateGC (dpy, img->window, gc_mask, &gc_values);
}
if ( !img->icn_pixmap )
{
img->icn_pixmap = XCreatePixmap(dpy, img->icn_window, img->icn_w,
img->icn_h, img->dpy_depth );
img->icn_gc = XCreateGC(dpy, img->icn_window, gc_mask, &gc_values);
icn_alloc = True;
}
if ( new_pixmaps || icn_alloc )
check_pixmap_allocation( img );
if ( new_window )
{
if ( img->icn_pixmap && img->icn_window ) {
wm_hints.flags = ( StateHint | IconPixmapHint | IconMaskHint |
IconWindowHint );
wm_hints.initial_state = NormalState;
wm_hints.icon_pixmap = img->icn_pixmap;
wm_hints.icon_window = img->icn_window;
wm_hints.icon_mask = img->icn_pixmap;
XSetWMHints (dpy, img->window, &wm_hints);
}
XSetWindowBackgroundPixmap(dpy, img->icn_window, img->icn_pixmap);
XMapWindow( dpy, img->window );
XClearWindow( dpy, img->window );
get_cursors( img->window );
}
XFlush( dpy );
}
/* this is a relic */
static int log2_levels;
/*
* This routine builds the color map (for X window system, details may
* differ in your system. Note particularly the two level color
* mapping: X will give back 216 color map entries, but there is no
* guarantee they are sequential. The dithering code above wants to
* compute a number in 0 - 215, so we must map from this to the X color
* map entry id.
*/
/*
* Initialize the 8 bit color map. Use gamma corrected map.
*/
#define IS_BINARY 1
#define IS_MONO 2
#define WANT_READ_WRITE 4
#define NOT_BINARY 0
#define NOT_MONO 0
#define WANT_READ_ONLY 0
void init_color( img )
register image_information *img;
{
register int type;
Boolean done = False, try_ro = True;
while ( ! done ) {
DPRINTF (stderr, "Cmap type: binary %d, mono %d, read/write %d\n",
img->binary_img, img->mono_img, img->rw_cmap );
type = ((( img->binary_img ) ? IS_BINARY : NOT_BINARY ) |
(( img->mono_img ) ? IS_MONO : NOT_MONO ) |
((( img->rw_cmap && img->sep_colors ) ||
( img->rw_cmap && !try_ro)) ?
WANT_READ_WRITE : WANT_READ_ONLY ));
switch ( type ) {
case NOT_BINARY | NOT_MONO | WANT_READ_WRITE:
done = (( img->sep_colors ) ?
init_separate_color_rw( img ) :
init_color_rw( img ));
if ( !done && !try_ro) {
fprintf( stderr,
"%s: not enough cmap entries available, trying b/w.\n",
progname );
img->mono_img = True;
img->dpy_channels = 1;
}
break;
case NOT_BINARY | NOT_MONO | WANT_READ_ONLY:
done = (( img->sep_colors ) ?
init_separate_color_ro( img, try_ro ) :
init_color_ro( img, try_ro ));
if ( !done && !try_ro ) {
fprintf( stderr,
"%s: not enough cmap entries available, trying b/w.\n",
progname );
img->mono_img = True;
img->dpy_channels = 1;
}
break;
case NOT_BINARY | IS_MONO | WANT_READ_WRITE:
done = (img->sep_colors ?
init_separate_color_rw( img ) : init_mono_rw( img ));
if ( !done & !try_ro ) img->binary_img = True;
break;
case NOT_BINARY | IS_MONO | WANT_READ_ONLY:
done = ( img->sep_colors ?
init_separate_color_ro( img, try_ro ) :
init_mono_ro( img, try_ro ));
if ( !done & !try_ro ) img->binary_img = True;
break;
case IS_BINARY | IS_MONO | WANT_READ_ONLY:
/* make the magic square */
get_dither_arrays( img );
make_square( 255.0, img->divN, img->modN, img->dm16 );
if ( img->pixel_table == NULL )
img->pixel_table = (Pixel *) malloc (2 * sizeof (Pixel));
if (img->pixel_table == NULL) {
perror ("malloc pixel_table (2)");
exit (1);
}
do {
Pixel wp = WhitePixel (dpy, screen);
Pixel bp = BlackPixel (dpy, screen);
if (bp < 2 && wp < 2) {
img->pixel_table[bp] = bp;
img->pixel_table[wp] = wp;
}
else {
img->pixel_table[0] = bp;
img->pixel_table[1] = wp;
}
} while (0);
img->lvls = 2;
img->lvls_squared = 4;
done = True;
break;
default:
fprintf (stderr, "Unknown type in init_colors: %d\n", type);
exit (1);
}
if (! done) {
try_ro = False;
if ( img->rw_cmap == True ) {
get_x_colormap( img );
}
}
}
VPRINTF (stderr, "Created color map with %d entries", img->lvls);
if (! img->mono_img ) {
VPRINTF (stderr, " per color, %d total\n", img->lvls * img->lvls * img->lvls);}
else VPRINTF (stderr, "\n");
if ( img->binary_img )
{
black_pixel = BlackPixel (dpy, screen);
white_pixel = WhitePixel (dpy, screen);
}
else if ( img->pixel_table != NULL ) {
black_pixel = img->pixel_table[0];
white_pixel = img->pixel_table[(img->mono_img) ? img->lvls - 1 :
img->lvls * img->lvls * img->lvls - 1];
}
else {
black_pixel = 0;
white_pixel = SHIFT_MASK_PIXEL(img->lvls - 1,img->lvls - 1,img->lvls - 1);
}
}
static
Boolean
init_separate_color_rw ( img )
image_information *img;
{
/*
* use XAllocColorPlanes to allocate all the cells we need --
* this makes it simple for me.
*/
#ifdef THIS_CODE_IS_NEVER_CALLED
pixel_table = NULL;
map = NULL;
color_defs = NULL;
DPRINTF (stderr, "In init_separate_color_rw \n");
for (log2_num_lvls = log2_levels;
log2_num_lvls >= 1;
log2_num_lvls-- ) {
num_lvls = 1 << log2_num_lvls;
total_levels = 1 << (log2_num_lvls * 3);
if (map == NULL) {
map = (int *) malloc (num_lvls * sizeof (int) );
if (map == NULL) continue;
}
if (color_defs == NULL) {
color_defs = (XColor *) malloc (num_lvls * sizeof (XColor) );
if (color_defs == NULL)
continue;
}
if ( XAllocColorPlanes (dpy, img->colormap, 1, &pixel_base, 1,
log2_num_lvls, log2_num_lvls,
log2_num_lvls,
&red_mask, &green_mask, &blue_mask) == 0)
continue;
if (log2_num_lvls == 8) img->dither_img = False;
bwdithermap ( num_lvls, display_gamma, map, divN, modN, dm16 );
red_shift = shift_match_right(red_mask);
green_shift = shift_match_right(green_mask);
blue_shift = shift_match_right(blue_mask);
/*
* Set up the color map entries.
*/
for (i = 0; i < num_lvls; i++) {
color_defs[i].pixel = SHIFT_MASK_PIXEL(i, i, i);
color_defs[i].red = map[i] << 8;
color_defs[i].green = map[i] << 8;
color_defs[i].blue = map[i] << 8;
color_defs[i].flags = DoRed | DoGreen | DoBlue;
}
XStoreColors (dpy, img->colormap, color_defs, num_lvls);
if (img->lvls > num_lvls) {
img->lvls = num_lvls;
img->lvls_squared = num_lvls * num_lvls;
log2_levels = log2_num_lvls;
}
free (map);
free (color_defs);
return (True);
}
#endif /* THIS_CODE_IS_NEVER_CALLED */
return (False);
}
/*
* Used for allocating the colormap in a PsuedoColor visual or other color
* type. Used for the standard 8 bit display
*/
static
Boolean
init_color_rw ( img )
image_information *img;
{
int num_lvls;
int *map;
XColor *color_defs, *color;
int total_levels;
int red_index;
int green_index;
int blue_index;
int i, j;
int free_pixels = 0, shift, cmap_size;
Pixel *pixels;
DPRINTF(stderr, "In init_color_rw\n");
/* get free pixels from the default colormap */
cmap_size = (1 << img->dpy_depth);
/* get all free cells in the colormap in <depth> calls to AllocColor */
pixels = (Pixel *) malloc (cmap_size * sizeof (Pixel) );
color_defs = (XColor *) malloc (cmap_size * sizeof (XColor) );
if ( pixels && color_defs )
{
DPRINTF(stderr, "Allocating colors: success/failure ");
for (shift = img->dpy_depth; shift >= 0; shift--)
if (XAllocColorCells (dpy, img->colormap, False, 0, 0,
&pixels[free_pixels],
(int)1 << shift))
{
DPRINTF(stderr, "1");
free_pixels += (unsigned int)1 << shift;
}
else DPRINTF(stderr, "0");
DPRINTF(stderr, " got %d\n", free_pixels);
}
for (num_lvls = img->lvls;
num_lvls > 1;
num_lvls-- )
{
total_levels = num_lvls * num_lvls * num_lvls;
if ( total_levels <= free_pixels )
break;
}
if ( !num_lvls )
return (False);
if (img->lvls > num_lvls) {
img->lvls = num_lvls;
img->lvls_squared = num_lvls * num_lvls;
for (log2_levels = 1, i = 2; i < img->lvls; i <<= 1, log2_levels++) {
/* do nothing */
}
}
if ( num_lvls == 256 )
img->dither_img = False;
if (! img->pixel_table )
img->pixel_table = (Pixel *) malloc (total_levels * sizeof (Pixel) );
map = (int *) malloc (num_lvls * sizeof (int) );
if ( get_dither_arrays( img ) )
bwdithermap ( num_lvls, display_gamma, map,
img->divN, img->modN, img->dm16 );
/*
* Use the top free_pixels NOT the bottom ones. This makes it right for
* 99% of the DISPLAYs out there which begin using colors at the bottom.
* We take the top color cells, and copy the bottom ones into the extra
* spaces, *some* other windows won't be clobbered by our colormap.
*/
shift = free_pixels - total_levels;
for (j = 0, i = shift; j < total_levels; i++, j++)
img->pixel_table[j] = pixels[i];
for (i = 0; i < shift; i++)
color_defs[i].pixel = pixels[i];
XQueryColors( dpy, DefaultColormap(dpy, screen),
color_defs, shift );
/*
* Set up the color map entries.
*/
color = &color_defs[shift];
red_index = 0;
green_index = 0;
blue_index = 0;
for (i = 0; i < total_levels; i++) {
color->pixel = img->pixel_table[i];
color->red = map[red_index] << 8;
color->green = map[green_index] << 8;
color->blue = map[blue_index] << 8;
color->flags = DoRed | DoGreen | DoBlue;
color++;
if (++red_index >= num_lvls) {
if (++green_index >= num_lvls) {
++blue_index;
green_index = 0;
}
red_index = 0;
}
}
XStoreColors (dpy, img->colormap, color_defs, free_pixels);
free (map);
free (color_defs);
free (pixels);
return (True);
}
static
Boolean
init_separate_color_ro ( img, try_ro )
image_information *img;
int try_ro;
{
register int num_lvls;
register int log2_num_lvls;
register int *map = NULL;
register int i;
DPRINTF(stderr, "In init_separate_color_ro\n");
for (log2_num_lvls = log2_levels;
log2_num_lvls >= 1;
log2_num_lvls-- ) {
num_lvls = 1 << log2_num_lvls;
if (map == NULL) {
map = (int *) malloc (num_lvls * sizeof (int) );
if (map == NULL) continue;
}
if (num_lvls == 256) img->dither_img = False;
get_dither_arrays( img );
bwdithermap( num_lvls, display_gamma, map,
img->divN, img->modN, img->dm16 );
red_mask = img->dpy_visual->red_mask;
green_mask = img->dpy_visual->green_mask;
blue_mask = img->dpy_visual->blue_mask;
red_shift = shift_match_left (red_mask, log2_num_lvls);
green_shift = shift_match_left (green_mask, log2_num_lvls);
blue_shift = shift_match_left (blue_mask, log2_num_lvls);
if (img->lvls > num_lvls) {
img->lvls = num_lvls;
img->lvls_squared = num_lvls * num_lvls;
log2_levels = log2_num_lvls;
}
/* pack into a pixel the pre shifted and maksed pixel values */
if ( img->mono_color ) {
img->pixel_table = (Pixel *)malloc(img->cmlen * sizeof (Pixel));
if (!img->pixel_table) continue;
for ( i = 0; i < img->cmlen; i++ )
img->pixel_table[i] =
SHIFT_MASK_PIXEL(img->in_cmap[RLE_RED][i],
img->in_cmap[RLE_GREEN][i],
img->in_cmap[RLE_BLUE][i]);
}
if ( map )
free (map);
return (True);
}
return (False);
}
static int pixcompare(pixel1, pixel2 )
Pixel *pixel1, *pixel2;
{
return( *pixel1 - *pixel2 );
}
void free_unique_colors( img, pixels, npixels )
image_information *img;
Pixel *pixels;
int npixels;
{
Pixel last, *p;
int i, nunique;
if ( no_color_ref_counts )
{
qsort(pixels, npixels, sizeof(Pixel), pixcompare);
p = pixels;
for (i=1; i<npixels; i++ ) {
if ( pixels[i] != *p ) {
p += 1;
*p = pixels[i];
}
}
nunique = (p - pixels) + 1;
DPRINTF(stderr, "In free_unique_pixels \n\nPixels: ");
for (i=0;i<nunique;i++) DPRINTF(stderr, " %d ",pixels[i]);
DPRINTF(stderr, "\n");
}
else
nunique = npixels;
XFreeColors(dpy, img->colormap, pixels, nunique, 0);
}
static
Boolean
init_color_ro ( img, try_ro )
image_information *img;
int try_ro;
{
register int num_lvls;
register int total_levels;
XColor color_def;
register XColor *color_defs = NULL;
register Status *status = NULL;
register int red_index;
register int green_index;
register int blue_index;
register int *map = NULL;
register int i,j;
int first = True;
DPRINTF(stderr, "In init_color_ro\n");
for (num_lvls = img->lvls; num_lvls >= 2; num_lvls -- ) {
if (try_ro && !first && specified_levels) break;
else first = False;
total_levels = num_lvls * num_lvls * num_lvls;
if ( !img->pixel_table ) {
img->pixel_table = (Pixel *)malloc(total_levels * sizeof (Pixel) );
if ( !img->pixel_table ) continue;
}
if ( map == NULL ) {
map = (int *) malloc (num_lvls * sizeof (int) );
if (map == NULL) continue;
}
if (num_lvls == 256) img->dither_img = False;
get_dither_arrays( img );
bwdithermap( num_lvls, display_gamma, map,
img->divN, img->modN, img->dm16 );
/* try to get a color map entry for each color. */
red_index = green_index = blue_index = 0;
#ifdef XLIBINT_H_NOT_AVAILABLE
for ( i = 0; i < total_levels; i++ ) {
color_def.red = map[red_index] << 8;
color_def.green = map[green_index] << 8;
color_def.blue = map[blue_index] << 8;
if ( XAllocColor (dpy, img->colormap, &color_def ) == 0 ) {
break;
}
if (++red_index >= num_lvls) {
if (++green_index >= num_lvls) {
++blue_index; green_index = 0;
}
red_index = 0;
}
img->pixel_table[i] = color_def.pixel;
}
/* Check if the colors are available */
if ( i < total_levels ) { /* Free the colors already obtained */
free_unique_colors (img, img->pixel_table, i );
continue;
}
#else
if (!color_defs)
color_defs = (XColor *) malloc(total_levels * sizeof (XColor));
if (!status)
status = (Status *) malloc(total_levels * sizeof (Status));
if ( !status || !color_defs ) continue;
for ( i = 0; i < total_levels; i++ ) {
color_defs[i].red = map[red_index] << 8;
color_defs[i].green = map[green_index] << 8;
color_defs[i].blue = map[blue_index] << 8;
if (++red_index >= num_lvls) {
if (++green_index >= num_lvls) {
++blue_index; green_index = 0;
}
red_index = 0;
}
}
if (XAllocColors(dpy, img->colormap, color_defs, total_levels, status)== 0)
{
for ( i = 0, j = 0; i < total_levels; i++ )
if (status[i])
img->pixel_table[j++] = color_defs[i].pixel;
free_unique_colors (img, img->pixel_table, j );
continue;
} else
for ( i = 0; i < total_levels; i++ )
img->pixel_table[i] = color_defs[i].pixel;
#endif
img->lvls = num_lvls;
img->lvls_squared = num_lvls * num_lvls;
for (log2_levels = 1, i = 2; i < img->lvls; i <<= 1, log2_levels++) {
/* do nothing */
}
if (map) free (map);
if (status) free (status);
if (color_defs) free (color_defs);
return (True);
}
if (map) free (map);
if (status) free (status);
if (color_defs) free (color_defs);
return (False);
}
static
Boolean
init_mono_rw ( img )
image_information *img;
{
int num_lvls;
int *map;
XColor *color_defs, *color;
int i, j;
int free_pixels = 0, shift, cmap_size;
Pixel *pixels;
DPRINTF(stderr, "In init_mono_rw\n");
/* get free pixels from the default colormap */
cmap_size = (1 << img->dpy_depth);
/* get all free cells in the colormap in <depth> calls to AllocColor */
pixels = (Pixel *) malloc (cmap_size * sizeof (Pixel) );
color_defs = (XColor *) malloc (cmap_size * sizeof (XColor) );
if ( pixels && color_defs ) {
DPRINTF(stderr, "Allocating colors: success/failure ");
for (shift = img->dpy_depth; shift >= 0; shift--)
if (XAllocColorCells (dpy, img->colormap, False, 0, 0,
&pixels[free_pixels],
(int)1 << shift))
{
DPRINTF(stderr, "1");
free_pixels += (unsigned int)1 << shift;
}
else DPRINTF(stderr, "0");
DPRINTF(stderr, " got %d\n", free_pixels);
}
if ( img->mono_color ) {
img->lvls = img->cmlen;
if ( img->cmlen > free_pixels )
fprintf(stderr, "%s: Warning: Not enough cells for input cmap\n",
progname);
}
if ( free_pixels == 0 ) return False;
num_lvls = img->lvls;
while ( num_lvls > free_pixels && num_lvls >= 2 )
num_lvls = ((num_lvls > 16) ? num_lvls / 2 : num_lvls - 1);
img->lvls = num_lvls;
img->lvls_squared = num_lvls * num_lvls;
for (log2_levels = 1, i = 2; i < img->lvls; i <<= 1, log2_levels++) {
/* do nothing */
}
if ( num_lvls == 256 && img->mono_color )
img->dither_img = False;
if ( !img->pixel_table )
img->pixel_table = (Pixel *)
malloc ((img->mono_color? img->cmlen : num_lvls) * sizeof(Pixel) );
map = (int *) malloc ( num_lvls * sizeof(int) );
if (!map || !img->pixel_table) {
fprintf(stderr, "malloc problems in init_mono_rw\n");
return False;
}
get_dither_arrays( img );
bwdithermap(num_lvls, display_gamma, map,
img->divN, img->modN, img->dm16 );
/*
* Use the top free_pixels NOT the bottom ones. This makes it right for
* 99% of the DISPLAYs out there which begin using colors at the bottom.
* We take the top color cells, and copy the bottom ones into the extra
* spaces, *some* other windows won't be clobbered by our colormap.
*/
shift = free_pixels - num_lvls;
for (j = 0, i = shift; j < num_lvls; i++, j++)
img->pixel_table[j] = pixels[i];
for (i = 0; i < shift; i++)
color_defs[i].pixel = pixels[i];
XQueryColors( dpy, DefaultColormap(dpy, screen), color_defs, shift );
/*
* Set up the color map entries.
*/
color = &color_defs[shift];
if (img->mono_color)
for ( i = 0; i < num_lvls; i++ ) {
color->pixel = img->pixel_table[i];
color->red = img->in_cmap[RLE_RED][i] << 8;
color->green = img->in_cmap[RLE_GREEN][i] << 8;
color->blue = img->in_cmap[RLE_BLUE][i] << 8;
color->flags = DoRed | DoGreen | DoBlue;
color++;
}
else
for ( i = 0; i < num_lvls; i++ ) {
color->pixel = img->pixel_table[i];
color->red = map[i] << 8;
color->green = map[i] << 8;
color->blue = map[i] << 8;
color->flags = DoRed | DoGreen | DoBlue;
color++;
}
XStoreColors (dpy, img->colormap, color_defs, free_pixels);
free (map);
free (color_defs);
free (pixels);
return (True);
}
static
Boolean
init_mono_ro ( img, try_ro )
image_information *img;
int try_ro;
{
register int num_lvls;
XColor color_def;
register XColor *color_defs = NULL;
register Status *status = NULL;
register int * map = NULL;
register int i,j;
int first = True;
DPRINTF(stderr, "In init_mono_ro");
if ( try_ro ) {
DPRINTF(stderr, " trying read/only\n");
} else {
DPRINTF(stderr, "\n");
}
if ( img->mono_color )
img->lvls = img->cmlen;
for (num_lvls = img->lvls; num_lvls >= 2;
num_lvls = (num_lvls > 16) ? num_lvls / 2 : num_lvls - 1 ) {
if ( try_ro && !first && specified_levels ) break;
else if ( !first && img->mono_color ) break;
else first = False;
if (img->pixel_table == NULL) {
img->pixel_table = (Pixel *) malloc (num_lvls * sizeof (Pixel) );
if (img->pixel_table == NULL) continue;
}
if (map == NULL) {
map = (int *) malloc (num_lvls * sizeof (int) );
if (map == NULL) continue;
}
if (num_lvls == 256 || img->mono_color)
img->dither_img = False;
get_dither_arrays( img );
bwdithermap(num_lvls, display_gamma, map,
img->divN, img->modN, img->dm16 );
/* try to get a color map entry for each color. */
#ifdef XLIBINT_H_NOT_AVAILABLE
for ( i = 0; i < num_lvls; i++ ) {
if ( img->mono_color ) {
color_def.red = img->in_cmap[RLE_RED][i] << 8;
color_def.green = img->in_cmap[RLE_GREEN][i] << 8;
color_def.blue = img->in_cmap[RLE_BLUE][i] << 8;
} else {
color_def.red = map[i] << 8;
color_def.green = map[i] << 8;
color_def.blue = map[i] << 8;
}
if ( XAllocColor (dpy, img->colormap, &color_def ) == 0 ){
break;
}
img->pixel_table[i] = color_def.pixel;
}
/* Check if the colors are available */
if ( i < num_lvls) {
/* Free the colors already obtained */
free_unique_colors (img, img->pixel_table, i );
continue; /* adjust level & repeat */
}
#else
if (!color_defs)
color_defs = (XColor *) malloc(num_lvls * sizeof (XColor));
if (!status)
status = (Status *) malloc(num_lvls * sizeof (Status));
if ( !status || !color_defs ) continue;
for ( i = 0; i < num_lvls; i++ ) {
color_defs[i].pixel = 0;
if ( img->mono_color ) {
color_defs[i].red = img->in_cmap[RLE_RED][i] << 8;
color_defs[i].green = img->in_cmap[RLE_GREEN][i] << 8;
color_defs[i].blue = img->in_cmap[RLE_BLUE][i] << 8;
} else {
color_defs[i].red = map[i] << 8;
color_defs[i].green = map[i] << 8;
color_defs[i].blue = map[i] << 8;
}
}
if (XAllocColors(dpy, img->colormap, color_defs, num_lvls, status)== 0)
{
for ( i = 0, j = 0; i < num_lvls; i++ )
if (status[i])
img->pixel_table[j++] = color_defs[i].pixel;
free_unique_colors (img, img->pixel_table, j );
continue;
} else
for ( i = 0; i < num_lvls; i++ )
img->pixel_table[i] = color_defs[i].pixel;
#endif
img->lvls = num_lvls;
img->lvls_squared = num_lvls * num_lvls;
for (log2_levels = 1, i = 2; i < img->lvls; i <<= 1, log2_levels++);
/* do nothing */
free (map);
if (status) free (status);
if (color_defs) free (color_defs);
return (True);
}
if (img->pixel_table)
free (img->pixel_table);
img->pixel_table = NULL;
if (map) free (map);
if (status) free (status);
if (color_defs) free (color_defs);
return (False);
}
static CONST_DECL char *visual_class_to_string(visual_type)
int visual_type;
{
CONST_DECL char *type_string;
switch (visual_type) {
case DirectColor: type_string = "DirectColor"; break;
case PseudoColor: type_string = "PseudoColor"; break;
case TrueColor: type_string = "TrueColor"; break;
case StaticColor: type_string = "StaticColor"; break;
case GrayScale: type_string = "GrayScale"; break;
case StaticGray: type_string = "StaticGray"; break;
default: type_string = "any/unknown"; break;
}
return type_string;
}
#define BINARY_TABLE_INDEX 0
#define MONOCHROME_TABLE_INDEX 1
#define COLOR_TABLE_INDEX 2
/* Here we ALWAYS want to take a PseudoColor over the next best visual... */
/* in Monochrome, we can do just as much with a pseudo color visual, and */
/* we may be able to preserve some of the default colors from other windows*/
/* In color mode, some eight bit displays offer a Direct and TrueColor */
/* visual.. This is quite confusing, Have you ever seen a 24bit display */
/* offer a 24-bit PseudoColor visual? They offer 8 bit PC visuals usually */
static int desired_class_table [][6] = {
{ PseudoColor, StaticGray, GrayScale, DirectColor, TrueColor, StaticColor},
{ PseudoColor, GrayScale, StaticGray, DirectColor, TrueColor, StaticColor},
{ PseudoColor, DirectColor, TrueColor, StaticColor, GrayScale, StaticGray}
};
void
find_appropriate_visual( img )
register image_information *img;
{
static int num_visuals = 0;
static XVisualInfo *visual_info = NULL;
register XVisualInfo *vi, *found_vi;
XVisualInfo *XGetVisualInfo ();
VisualID def_visual_id;
int def_visual_index;
int def_scrn = DefaultScreen(dpy);
int desired_class;
int desired_depth;
int deepest_visual;
int depth_delta;
register int i;
DPRINTF(stderr, "In find_appropriate_visual(%d)\n", img->img_channels);
if (visual_info == NULL) {
visual_info = XGetVisualInfo (dpy, VisualNoMask, NULL, &num_visuals);
if (visual_info == NULL || num_visuals == 0) {
fprintf (stderr, "XGetVisualInfo failed\n");
exit (1);
}
}
desired_depth = 1;
for (i = 2; i < img->lvls; i <<= 1) {
desired_depth++;
}
if ( img->mono_img && img->lvls == 2 )
img->binary_img = True;
if ( img->binary_img ) {
desired_class = BINARY_TABLE_INDEX;
desired_depth = 1;
depth_delta = 1;
}
else if ( img->mono_img ) {
desired_class = MONOCHROME_TABLE_INDEX;
depth_delta = 1;
}
else {
desired_class = COLOR_TABLE_INDEX;
desired_depth *= 3; /* needed if separate colors */
depth_delta = 3;
}
VPRINTF (stderr, "Searching for %s visual with desired depth >= %d\n",
visual_class_to_string(img->visual_class), desired_depth);
/*
* find visual such that:
*
* 1. depth is as large as possible (up to true desired depth)
* 2. visual depth is the smallest of those supported >= depth
* 3. visual class is the `most desired' for the image type
* Meaning! that if it is the DefaultVisual it IS the
* most desired. We can't choose one visual class over
* another for all displays! If the depth of the DefaultVisual
* is large enough for the image, or as large as all others, we
* use it! This minimizes screw ups on our part.
*/
found_vi = NULL;
def_visual_id = DefaultVisual(dpy, def_scrn)->visualid ;
deepest_visual = 0;
for (i = 0; i < num_visuals; i++)
{
if ( deepest_visual < visual_info[i].depth )
deepest_visual = visual_info[i].depth;
if ( def_visual_id == visual_info[i].visualid )
def_visual_index = i;
}
/* Take the Default Visual if it's cool enough... */
if ( visual_info[def_visual_index].depth >= desired_depth ||
visual_info[def_visual_index].depth == deepest_visual )
found_vi = &visual_info[def_visual_index];
/* if we were told to look for a specific type first, do it */
if ( img->visual_class >= 0 ) {
int depth;
for (depth = desired_depth; depth >= 1; depth -= depth_delta) {
for (vi = visual_info; vi < visual_info + num_visuals; vi++)
if (vi->class == img->visual_class && vi->depth >= depth &&
vi->screen == def_scrn ) {
found_vi = vi;
if (found_vi->depth == depth) break;
}
if (found_vi != NULL && found_vi->class == img->visual_class)
break;
}
}
/* Werent told to get any type of Visual, or didn't find one, wingit */
if ( img->visual_class < 0 ) {
int depth;
for (depth = desired_depth; depth >= 0; depth -= depth_delta) {
if (found_vi != NULL)
break;
for (i = 0; i < 6; i++) {
int vt;
/* search for class and depth */
vt = desired_class_table[desired_class][i];
for (vi = visual_info; vi < visual_info+num_visuals; vi++)
if (vi->class == vt && vi->depth >= depth &&
vi->screen == def_scrn ) {
if (found_vi==NULL || found_vi->depth > vi->depth)
found_vi = vi;
if (vi->depth == depth)
break;
}
}
}
}
if (found_vi == NULL) {
fprintf (stderr, "%s: Could not find appropriate visual type - %s\n",
progname, visual_class_to_string(img->visual_class));
exit (1);
}
/* set program the_hdr */
screen = found_vi->screen;
root_window = RootWindow (dpy, screen);
/* set img variables */
img->dpy_depth = found_vi->depth;
img->dpy_visual = found_vi->visual;
img->visual_class = found_vi->class;
/* We want to give the DefaultColormap a shot first */
if ( found_vi->visualid == def_visual_id )
img->colormap = DefaultColormap( dpy, screen );
else
get_x_colormap( img );
if ( img->dpy_depth == 1 || img->binary_img ) {
img->binary_img = True;
img->mono_img = True;
img->color_dpy = False;
img->dpy_channels = 1;
img->sep_colors = False;
img->rw_cmap = False;
img->lvls = 2;
img->lvls_squared = 4;
log2_levels = 1;
}
else {
int class = img->visual_class;
if ( class == GrayScale || class == StaticGray ) {
img->mono_img = True;
img->color_dpy = False;
img->dpy_channels = 1;
depth_delta = 1;
}
img->rw_cmap = (class == PseudoColor || class == GrayScale);
if ( img->dpy_visual != DefaultVisual( dpy, screen ) )
img->colormap = XCreateColormap( dpy, root_window,
img->dpy_visual, AllocNone );
if ( class == StaticColor || class == DirectColor || class == TrueColor ) {
img->sep_colors = True;
i = 1 << (img->dpy_depth / depth_delta);
if ( img->lvls > i) {
img->lvls = i;
img->lvls_squared = i * i;
}
} else {
img->sep_colors = False;
/* Image is monochrome??? */
if (depth_delta == 1) {
i = found_vi->colormap_size;
}
else { /* color */
for (i = 1; i * i * i < found_vi->colormap_size; i++) {}
i--;
}
if (img->lvls > i) {
img->lvls = i;
img->lvls_squared = i * i;
}
}
for (log2_levels = 1, i = 2; i < img->lvls; i <<= 1, log2_levels++);
/* do nothing */
}
VPRINTF(stderr, "Visual type %s, depth %d, screen %d\n",
visual_class_to_string(img->visual_class), img->dpy_depth, screen);
VPRINTF(stderr, "levels: %d, log(2) levels: %d\n", img->lvls, log2_levels);
}
static XFontStruct *pixel_font_info = NULL;
void
MapPixWindow ( img, use_top )
image_information *img;
int use_top;
{
Window hukairz;
int x, y;
unsigned int w, h, hunoz, huwanz, font_height;
XGetGeometry (dpy, img->window, &hukairz, &x, &y, &w, &h, &hunoz, &huwanz);
if (!pixel_font_info) {
pixel_font_info = XLoadQueryFont (dpy, "fixed");
if (!pixel_font_info) {
fprintf (stderr, "%s: unable to load font '%s'\n",
progname, "fixed");
exit (1);
}
}
font_height = pixel_font_info->ascent + pixel_font_info->descent + 4;
y = (use_top ? 0 : (h - font_height));
if ( img->pix_info_window == NULL ) {
XSetFont (dpy, img->gc, pixel_font_info->fid );
img->pix_info_window = XCreateSimpleWindow
(dpy, img->window, 0, y, w, font_height, 0, None, black_pixel );
}
else
XMoveResizeWindow ( dpy, img->pix_info_window, 0, y, w, font_height );
XMapWindow ( dpy, img->pix_info_window );
}
void
DrawPixWindow ( img, x, y )
image_information *img;
int x, y;
{
char str[256];
unsigned char *r, *g, *b;
r = SAVED_RLE_ROW( img, y ) + x;
switch ( img->dpy_channels ) {
case 1:
if ( img->mag_fact > 1 )
sprintf (str, "(%4d,%4d): ( %3d ) (Mag %2d)",
x + img->x, img->h - y - 1 + img->y,
*r, img->mag_fact);
else
sprintf (str, "(%4d,%4d): ( %3d )",
x + img->x, img->h - y - 1 + img->y, *r);
break;
case 2:
g = r + img->w;
if ( img->mag_fact > 1 )
sprintf (str, "(%4d,%4d): ( %3d, %3d ) (Mag %2d)",
x + img->x, img->h - y - 1 + img->y,
*r, *g, img->mag_fact);
else
sprintf (str, "(%4d,%4d): ( %3d, %3d )",
x + img->x, img->h - y - 1 + img->y,
*r, *g);
break;
case 3:
g = r + img->w;
b = g + img->w;
if ( img->mag_fact > 1 )
sprintf (str,
"(%4d,%4d): 0x%02x%02x%02x ( %3d, %3d, %3d ) (Mag %2d)",
x + img->x, img->h - y - 1 + img->y,
*r, *g, *b, *r, *g, *b, img->mag_fact);
else
sprintf (str, "(%4d,%4d): 0x%02x%02x%02x ( %3d, %3d, %3d )",
x + img->x, img->h - y - 1 + img->y,
*r, *g, *b, *r, *g, *b);
break;
}
XClearWindow ( dpy, img->pix_info_window );
XDrawString ( dpy, img->pix_info_window, img->gc,
4, 2 + pixel_font_info->ascent, str, strlen (str) );
}
void
DrawSpeedWindow ( img, s )
image_information *img;
int s;
{
char str[256];
if ( s > 0 )
sprintf( str, "%s%d Frames/Second", (s > 0) ? "": "1/", (s>0)?s:-s );
else
sprintf( str, "As fast as possible" );
XClearWindow ( dpy, img->pix_info_window );
XDrawString ( dpy, img->pix_info_window, img->gc,
4, 2 + pixel_font_info->ascent, str, strlen (str) );
}
void
UnmapPixWindow( img )
image_information *img;
{
XUnmapWindow ( dpy, img->pix_info_window );
}
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.