/* visual.c */

#include <stdio.h>

#include "visual.h"

#include <X11/Xmu/StdCmap.h>
#include "error.h"

/* stolen from the PEX utilities */
static void ora_find_best_visual(Display *dpy, XVisualInfo *chosen_vis)
/* book_utils.c 1.4 */
/*
    Copyright 1992, 1993 O'Reilly and Associates, Inc.  Permission to
    use, copy, and modify this program is hereby granted, as long as
    this copyright notice appears in each copy of the program source
    code.
*/
{
    int			i, size, num_vis, cmap_size;
    XVisualInfo		vis_templ, *vis_list;
    
    /* Get all the visuals for the screen. */
    vis_templ.screen = DefaultScreen( dpy );
    vis_list = XGetVisualInfo( dpy, VisualScreenMask, &vis_templ,
			      &num_vis );
    
    /* Determine the best visual available.  The best one is the */
    /* one with the most colors and highest capabilities. */
    cmap_size = 0;
    chosen_vis->class = -1;
    for ( i = 0; i < num_vis; i++ ) {
	/* Determine the number of colors available. */
	switch ( vis_list[i].class ) {
	case TrueColor:
	case DirectColor:
	    size = (vis_list[i].red_mask | vis_list[i].green_mask
		| vis_list[i].blue_mask) + 1;
	    break;
	default:
	    size = vis_list[i].colormap_size;
	}
	
	/* Choose this one if it supports more colors or is a higher */
	/* class, but favor TrueColor over DirectColor. */
	if ( size >= cmap_size ) {
	    switch ( vis_list[i].class ) {
	    case TrueColor:
		/* Choose TrueColor over anything else. */
		*chosen_vis = vis_list[i];
		cmap_size = size;
		break;
	    case DirectColor:
		/* Don't choose DirectColor over TrueColor. */
	        if ( chosen_vis->class != TrueColor ) {
		    *chosen_vis = vis_list[i];
		    cmap_size = size;
		}
		break;
	    default:
	        /* Choose the highest class. */
		if ( vis_list[i].class >= chosen_vis->class ) {
		    *chosen_vis = vis_list[i];
		    cmap_size = size;
		}
		break;
	    }
	}
    }
}

static int ora_get_standard_colormap(Display *dpy, 
				     XVisualInfo *vis_info, 
				     XStandardColormap *cmap_info)
/* book_utils.c 1.4 */
/*
    Copyright 1992, 1993 O'Reilly and Associates, Inc.  Permission to
    use, copy, and modify this program is hereby granted, as long as
    this copyright notice appears in each copy of the program source
    code.
*/
{
    XStandardColormap	*std_cmaps;
    Atom		property;
    int			i, num_cmaps;
    
    switch ( vis_info->class ) {
    case TrueColor:
    case StaticColor:
	property = XA_RGB_BEST_MAP;
	break;
    case PseudoColor:
    case DirectColor:
    default:
	property = XA_RGB_DEFAULT_MAP;
	break;
    case StaticGray:
    case GrayScale:
	property = XA_RGB_GRAY_MAP;
	break;
    }

    /* Ensure that the property is defined. */
    if ( XmuLookupStandardColormap( dpy, vis_info->screen,
	vis_info->visualid, vis_info->depth, property,
	False, True ) ) {
	
	/* Get the standard colormap properties. */
	if ( XGetRGBColormaps( dpy,
	      RootWindow( dpy, DefaultScreen( dpy ) ),
	      &std_cmaps, &num_cmaps, property ) ) {
	
	    /* Find the properties for the specified visual. */
	    for ( i = 0; i < num_cmaps; i++ ) {
		if ( vis_info->visualid == std_cmaps[i].visualid ) {
		    *cmap_info = std_cmaps[i];
		    return 1;
		}
	    }
	    XFree( (char *)std_cmaps );
	}
    }
    
    return 0;
}

void find_best_visual_and_colormap(Display *dpy, 
				   XVisualInfo *best_visual, 
				   XStandardColormap *std_cmap)
{
/* Determine the best visual to use. */
	ora_find_best_visual( dpy, best_visual );
    
/* Get a standard colormap for the visual. */
	if ( !ora_get_standard_colormap( dpy, best_visual, std_cmap ) ) 
		Fatal(2, NULL, "Cannot find a standard colormap\n");
}

