# include "Ximage.h"
# define NPIXELS 64

/* DirectColor doesn't seem to work, even though it is available:
   I cannot use XAllocColorCells to get pixels under DirectColor
*/

/* static int try_visual[] = {5, 3, 1, 4, 2, 0}; */

void CheckVisual (Graphic *graphic, int *argc, char **argv) {

  int i, Nfound, N;
  int col, def, dyn;
  XVisualInfo *visual_list, visual_temp;
  unsigned long planes[3];
  XPixmapFormatValues *pixmaps;
  int Npixmaps;

  if (DEBUG) {
    fprintf (stderr, "DirectColor: %d\n", DirectColor);
    fprintf (stderr, "PseudoColor: %d\n", PseudoColor);
    fprintf (stderr, "TrueColor: %d\n", TrueColor);
    fprintf (stderr, "GrayScale: %d\n", GrayScale);
    fprintf (stderr, "StaticColor: %d\n", StaticColor);
    fprintf (stderr, "StaticGray: %d\n", StaticGray);
  }

  visual_temp.screen = graphic[0].screen;
  
  /* find available visuals */
  visual_list = XGetVisualInfo (graphic[0].display, VisualScreenMask, &visual_temp, &Nfound);
  if (Nfound == 0) {
    fprintf (stderr, "error finding useful visual\n");
    exit (0);
  }
  
  /* check default visual first */ 
  for (i = 0; (i < Nfound) && (graphic[0].visual != visual_list[i].visual); i++);
  if (i == Nfound) {
    fprintf (stderr, "default visual not found??\n");
    exit (0);
  }

  col = def = dyn = FALSE;
  if (DEBUG) fprintf (stderr, "default visual class is %d\n", visual_list[i].class);
  switch (visual_list[i].class) {
  case PseudoColor:
    col = def = dyn = TRUE;
    graphic[0].visual = visual_list[i].visual;
    graphic[0].visualclass = TRUE;
    goto test_pixels;
    break;
  default:
    break;
  }

  for (i = 0; i < Nfound; i++) {
    switch (visual_list[i].class) {
    case PseudoColor:
      if (DEBUG) fprintf (stderr, "selected visual class is %d\n", visual_list[i].class);
      col = dyn = TRUE;
      if (graphic[0].visual == visual_list[i].visual) {
	def = TRUE;
      } else {
	graphic[0].visual = visual_list[i].visual;
      }
      graphic[0].visualclass = TRUE;
      goto test_pixels;
      break;
    default:
      break;
    }
  }

  for (i = 0; i < Nfound; i++) {
    switch (visual_list[i].class) {
    case GrayScale:
      if (DEBUG) fprintf (stderr, "selected visual class is %d\n", visual_list[i].class);
      dyn = TRUE;
      if (graphic[0].visual == visual_list[i].visual) {
	def = TRUE;
      } else {
	graphic[0].visual = visual_list[i].visual;
      }
      graphic[0].visualclass = TRUE;
      goto test_pixels;
      break;
    default:
      break;
    }
  }

  for (i = 0; (i < Nfound) && (visual_list[i].class != TrueColor); i++);
  if (i != Nfound) {
    col = TRUE;
    if (DEBUG) fprintf (stderr, "visual class is %d\n", visual_list[i].class);
    if (graphic[0].visual == visual_list[i].visual) {
      def = TRUE;
    } else {
      graphic[0].visual = visual_list[i].visual;
    }
    graphic[0].visualclass = FALSE;
    goto test_pixels;
  }

  for (i = 0; (i < Nfound) && (visual_list[i].class != StaticColor); i++);
  if (i != Nfound) {
    if (DEBUG) fprintf (stderr, "visual class is %d\n", visual_list[i].class);
    if (graphic[0].visual == visual_list[i].visual) {
      def = TRUE;
    } else {
      graphic[0].visual = visual_list[i].visual;
    }
    graphic[0].visualclass = FALSE;
    goto test_pixels;
  }

  for (i = 0; (i < Nfound) && (visual_list[i].class != StaticGray); i++);
  if (i != Nfound) {
    if (DEBUG) fprintf (stderr, "visual class is %d\n", visual_list[i].class);
    if (graphic[0].visual == visual_list[i].visual) {
      def = TRUE;
    } else {
      graphic[0].visual = visual_list[i].visual;
    }
    graphic[0].visualclass = FALSE;
    goto test_pixels;
  }

  test_pixels:

  /* need to make a colormap if 
     1) the selected visual is not the default 
     2) there are not enough colors available */

  /* NEED TO ADD A COUPLE LINES DEFINING THE VARIOUS HARD COLORS (BLACK, WHITE, AND THE OVERLAYS) */

  if ((N = get_argument (*argc, argv, "-private"))) {
    remove_argument(N, argc, argv);
    def = FALSE;
  } 

  if (!def) {
    if (DEBUG) fprintf (stderr, "allocated private colormap\n");
    graphic[0].colormap = XCreateColormap (graphic[0].display, RootWindow (graphic[0].display, graphic[0].screen), graphic[0].visual, AllocNone);
  }

  if (dyn) {
    /* allocate color cells  */
    for (graphic[0].Npixels = NPIXELS;
	 ((graphic[0].Npixels >= 16) && 
	  !XAllocColorCells (graphic[0].display, graphic[0].colormap, FALSE, planes, 1, graphic[0].pixels, graphic[0].Npixels));
	 graphic[0].Npixels -= 4) {
      if (DEBUG) fprintf (stderr, "trying %d colors\n", (int) graphic[0].Npixels);
    }


    /* make private colormap  */
    if (graphic[0].Npixels < 16) {
      // fprintf (stderr, "can't allocate enough cells, using private colormap\n");
      graphic[0].colormap = XCreateColormap (graphic[0].display, RootWindow (graphic[0].display, graphic[0].screen), graphic[0].visual, AllocNone);
      for (graphic[0].Npixels = NPIXELS;
	   ((graphic[0].Npixels >= 16) && 
	    !XAllocColorCells (graphic[0].display, graphic[0].colormap, FALSE, planes, 1, graphic[0].pixels, graphic[0].Npixels));
	   graphic[0].Npixels -= 4);

      if ((N = get_argument (*argc, argv, "-colorcount"))) {
	fprintf (stderr, "kii can grab %d colors\n", (int) graphic[0].Npixels);
	exit (0);
      } 
      if (graphic[0].Npixels < 16) {
	fprintf (stderr, "can't even allocate enough cells in private colormap\n");
	exit (0);
      }
    }
  }

  if (!dyn) {
    graphic[0].Npixels = 256;
    // fprintf (stderr, "can't use dynamic colors, color scrollbar inactive\n");
    // fprintf (stderr, " this can be avoided by using a dynamic visual class\n");
    // fprintf (stderr, " (see Kii help page for details)\n");
  }

  if ((N = get_argument (*argc, argv, "-colorcount"))) {
    fprintf (stderr, "kii can grab %d colors\n", (int) graphic[0].Npixels);
    exit (0);
  } 
  
  pixmaps = XListPixmapFormats (graphic[0].display, &Npixmaps);
  for (i = 0; i < Npixmaps; i++) {
    if (pixmaps[i].depth == graphic[0].depth) {
      graphic[0].Nbits = pixmaps[i].bits_per_pixel;
    }
  }
}
