home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Mac Game Programming Gurus / TricksOfTheMacGameProgrammingGurus.iso / More Source / C⁄C++ / Xconq 7.0d37 / source / x11 / xinit.c < prev    next >
Encoding:
C/C++ Source or Header  |  1995-05-02  |  50.1 KB  |  1,864 lines  |  [TEXT/KAHL]

  1. /* Initialization for the X11 interface to Xconq.
  2.    Copyright (C) 1987, 1988, 1989, 1991, 1992, 1993, 1994, 1995
  3.    Stanley T. Shebs.
  4.  
  5. Xconq is free software; you can redistribute it and/or modify
  6. it under the terms of the GNU General Public License as published by
  7. the Free Software Foundation; either version 2, or (at your option)
  8. any later version.  See the file COPYING.  */
  9.  
  10. #include "conq.h"
  11. #include "xconq.h"
  12. extern int smallest_image PROTO ((ImageFamily *imf, int *wp, int *hp));
  13.  
  14. extern XrmOptionDescRec xoptions[];
  15. extern int xoptions_count;
  16.  
  17. #ifndef __STDC__
  18. void abort ();
  19. #endif
  20.  
  21. static void init_gcs PROTO ((Side *side));
  22. static void init_fonts PROTO ((Side *side));
  23. static void init_bitmaps PROTO ((Side *side));
  24. static void init_cursors PROTO ((Side *side));
  25.  
  26. static void init_unit_images PROTO ((Side *side));
  27. static void init_terrain_images PROTO ((Side *side));
  28. static void init_emblem_images PROTO ((Side *side));
  29. static void init_emblem PROTO ((Side *side, Side *side2));
  30. static void get_default_terrain_image PROTO ((Side *side, ImageFamily *imf,
  31.                           int t));
  32. static void get_default_emblem PROTO ((Side *side, ImageFamily *imf,
  33.                        Side *side2));
  34. static void describe_imf PROTO ((Side *side, char *classname, char *typename,
  35.                  ImageFamily *imf));
  36.  
  37. static void x11_interp_fn PROTO ((ImageFamily *imf));
  38. static void x11_load_fn PROTO ((ImageFamily *imf));
  39.  
  40. char *imflib = IMFLIB;
  41.  
  42. /* Display and window globals used in callbacks from generic imf
  43.    handling code. */
  44.  
  45. Display *tmp_display;
  46.  
  47. Window tmp_root_window;
  48.  
  49. /* How much space to leave for a unit image, if all images should get
  50.    the same amount (such as for a list of unit types). */
  51.  
  52. int min_w_for_unit_image = 16;
  53. int min_h_for_unit_image = 16;
  54.  
  55. /* various bitmap definitions. */
  56.  
  57. #include "bitmaps/snowy.b"
  58.  
  59. #include "bitmaps/question.b"
  60. #include "bitmaps/lookglass.b"
  61. #include "bitmaps/lookmask.b"
  62. #include "bitmaps/movecurs.b"
  63. #include "bitmaps/movemask.b"
  64. #include "bitmaps/shootcurs.b"
  65. #include "bitmaps/shootmask.b"
  66. #include "bitmaps/buildcurs.b"
  67. #include "bitmaps/buildmask.b"
  68. /* need masks for these too */
  69. #include "bitmaps/hexcurs.b"
  70. #include "bitmaps/hexcursmask.b"
  71. #include "bitmaps/bordcurs.b"
  72. #include "bitmaps/conncurs.b"
  73. #include "bitmaps/addunits.b"
  74.  
  75. #include "bitmaps/boxcurs.b"
  76. #include "bitmaps/boxmask.b"
  77.  
  78. #include "bitmaps/bomb1.b"
  79. #include "bitmaps/bomb2.b"
  80. #include "bitmaps/bomb3.b"
  81. #include "bitmaps/bomb4.b"
  82.  
  83. #include "bitmaps/miss.b"
  84. #include "bitmaps/hit.b"
  85. #include "bitmaps/kill.b"
  86.  
  87. #include "bitmaps/hex8.b"
  88. #include "bitmaps/hex8b.b"
  89. #include "bitmaps/hex16.b"
  90. #include "bitmaps/hex16b.b"
  91. #include "bitmaps/hex32.b"
  92. #include "bitmaps/hex32b.b"
  93.  
  94. #include "bitmaps/closer.b"
  95. #include "bitmaps/farther.b"
  96. #include "bitmaps/terr.b"
  97. #include "bitmaps/elev.b"
  98. #include "bitmaps/therm.b"
  99. #include "bitmaps/units.b"
  100. #include "bitmaps/names.b"
  101. #include "bitmaps/people.b"
  102. #include "bitmaps/resource.b"
  103. #include "bitmaps/feature.b"
  104. #include "bitmaps/featuremask.b"
  105.  
  106. #include "bitmaps/gray.b"
  107. #include "bitmaps/darkgray.b"
  108.  
  109. /* (add arrays of info about various drawing styles and allowable options) */
  110.  
  111. enum whattouse terrstyles[] = {
  112.     useblocks,
  113.     useblocks,
  114.     useblocks,
  115.     useblocks,
  116.     usepictures,
  117.     usepictures,
  118.     usepolygons,
  119.     usepolygons
  120. };
  121.  
  122. /* The set of X11 resources that Xconq knows about. */
  123.  
  124. static XtResource resources[] = {
  125.     { XtNforeground, XtCForeground, XtRPixel, sizeof (Pixel),
  126.       XtOffsetOf(UI, foreground), XtRString, XtDefaultForeground },
  127.     { XtNbackground, XtCBackground, XtRPixel, sizeof (Pixel),
  128.       XtOffsetOf(UI, background), XtRString, XtDefaultBackground },
  129.     { XtNgeometry, XtCGeometry, XtRString, sizeof (String),
  130.       XtOffsetOf(UI, geospec), XtRString, NULL },
  131. };
  132.  
  133. /* Do a precheck of the intended displays.  This happens just after
  134.    player spec reading so that any losing displays can be found before
  135.    game startup gets in too deep. */
  136.  
  137. void
  138. check_player_displays()
  139. {
  140.     int numfailures = 0;
  141.     char *dpyname;
  142.     Player *player;
  143.     Display *dpy;
  144.  
  145.     /* (should be a for_all_ macro) */
  146.     for (player = playerlist ; player != NULL; player = player->next) {
  147.     /* Try to open the display. */
  148.     dpyname = player->displayname;
  149.     if (dpyname != NULL) {
  150.         if (strcmp("here", dpyname) == 0)
  151.           dpyname = getenv("DISPLAY");
  152.         dpy = XOpenDisplay(dpyname);
  153.         if (dpy == NULL) {
  154.         fprintf(stderr, "Cannot open display \"%s\"!\n", dpyname);
  155.         ++numfailures;
  156.         } else {
  157.         XCloseDisplay(dpy);
  158.         }
  159.     }
  160.     }
  161.     if (numfailures > 0) {
  162.     init_error("can't open all the required displays");
  163.     exit(1);
  164.     }
  165. }
  166.  
  167. /* Set up the basic user interface for a side.  This is called from the
  168.    kernel while doing the final assignment of players to sides, and
  169.    does not cause any display activity. */
  170.  
  171. void
  172. init_ui(side)
  173. Side *side;
  174. {
  175.     if (side_wants_display(side)) {
  176.         side->ui = (UI *) xmalloc(sizeof(UI));
  177.     Dprintf("One UI is %d bytes.\n", sizeof(UI));
  178.     } else {
  179.     side->ui = NULL;
  180.     }
  181. }
  182.  
  183. /* Set up all sides' displays all at once. */
  184.  
  185. void
  186. init_all_displays()
  187. {
  188.     int numdisplays = 0;
  189.     Side *side;
  190.     int SideMpTime = 0;
  191.     extern unsigned long EffectiveMpTime;
  192.  
  193.     for_all_sides(side) {
  194.     if (side_has_display(side)) {
  195.         init_display(side);
  196.         SideMpTime += side->ui->mpTime;
  197.         ++numdisplays;
  198.     }
  199.     }
  200.     if (numdisplays == 0) {
  201.     fprintf(stderr, "Must have at least one display to start.\n");
  202.     exit(0);
  203.     }
  204. /*    EffectiveMpTime = SideMpTime / numdisplays; */
  205.     DGprintf("Effective Mp Time is %d milliseconds.\n", EffectiveMpTime);
  206. }
  207.  
  208. /* Do a full redraw on each display. */
  209.  
  210. void
  211. init_redraws()
  212. {
  213.     Side *side;
  214.  
  215.     for_all_sides(side) {
  216.     if (side->ui != NULL) {
  217.         /* The moment of truth - up to now output has been suppressed. */
  218.         side->ui->active = TRUE;
  219.         draw_all_maps(side);
  220.     }
  221.     }
  222. }
  223.  
  224. /* Open display, create all the windows we'll need, do misc setup things,
  225.    and initialize some globals to out-of-range values for recognition later. */
  226.  
  227. void
  228. init_display(side)
  229. Side *side;
  230. {
  231.     int argc = 0;
  232.     int p, u, t, s, depth;
  233.     char *name, *dpyname;
  234.     Display *dpy;
  235.  
  236.     dpyname = side->player->displayname;
  237.  
  238.     Dprintf("Will try to open %s display `%s'...\n",
  239.         side_desig(side), dpyname);
  240.  
  241.     /* A hack. */
  242.     if (strcmp("here", dpyname) == 0)
  243.       dpyname = getenv("DISPLAY");
  244.  
  245.     if (side->id != 1 /* yuck, should test actual display open-ness */) {
  246.     dpy = XtOpenDisplay(thisapp, dpyname, PROGRAMNAME, PROGRAMCLASSNAME,
  247.                 xoptions, xoptions_count, &argc, NULL);
  248.     nargs = 0;
  249.     side->ui->shell = XtAppCreateShell(PROGRAMNAME, PROGRAMCLASSNAME,
  250.                       topLevelShellWidgetClass, dpy,
  251.                       tmpargs, nargs);
  252.     } else {
  253.     /* Just collect the display that's already been opened. */
  254.     dpy = XtDisplay(thistoplevel);
  255.     side->ui->shell = thistoplevel;
  256.     }
  257.     side->ui->dpy = dpy;
  258.  
  259.     if (DebugG)
  260.       XSynchronize(side->ui->dpy, True);
  261.  
  262.     XtGetApplicationResources(side->ui->shell, side->ui,
  263.                   resources, XtNumber(resources), NULL, 0);
  264.  
  265.     side->ui->kill_atom = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
  266.     /* Cache some generally useful values. */
  267.     side->ui->screen = DefaultScreen(dpy);
  268.     side->ui->rootwin = DefaultRootWindow(dpy);
  269.  
  270.     /* Set up things shared by all the windows. */
  271.     side->ui->dflt_color_terr_images = TRUE;
  272.     side->ui->dflt_color_unit_images = TRUE;
  273.     side->ui->dflt_color_embl_images = TRUE;
  274.     side->ui->bonw = BLACKONWHITE;
  275.     side->ui->mayseeall = (g_see_all() || endofgame);
  276.     depth = XDisplayCells(dpy, side->ui->screen);
  277.     DGprintf("%d different colors available ...\n", depth);
  278.     side->ui->monochrome = (depth <= 2);
  279.     for (p = 0; p < NUMPOWERS; ++p) {
  280.     for_all_terrain_types(t) {
  281.         /* Decide what display technique to use at each power. */
  282.         side->ui->usewhat[p][t] = terrstyles[p];
  283.         side->ui->terrpics[p][t] = None;
  284.         side->ui->terrchars[p][t] = '\0';
  285.         side->ui->terrfonts[p][t] = NULL;
  286.     }
  287.     for_all_unit_types(u) {
  288.         side->ui->unitpics[p][u] = None;
  289.         side->ui->unitmasks[p][u] = None;
  290.         side->ui->unitchars[p][u] = '\0';
  291.         side->ui->unitfonts[p][u] = NULL;
  292.         side->ui->ulegendfonts[p][u] = NULL;
  293.         /* (these values really should be filled in better) */
  294.         side->ui->unitw[p][u] = 1;  side->ui->unith[p][u] = 1;
  295.     }
  296.     }
  297.     for (s = 0; s < MAXSIDES; ++s) {
  298.     side->ui->emblempics[s] = None;
  299.     side->ui->emblemmasks[s] = None;
  300.     }
  301.     set_colors(side);
  302.     init_fonts(side);
  303.     init_unit_images(side);
  304.     init_terrain_images(side);
  305.     init_emblem_images(side);
  306.     init_bitmaps(side);
  307.     init_gcs(side);
  308.     init_cursors(side);
  309.     /* Create the generic windows. */
  310.     side->ui->maps = NULL;
  311.  
  312.     create_map(side, 5, side->ui->geospec);
  313.  
  314.     /* At this point, the toplevel widget has been realized, so we can */
  315.     /* start doing things to it...  So, first things first: */
  316.     XSetWMProtocols(dpy, XtWindow(side->ui->shell),
  317.             &side->ui->kill_atom, 1);
  318.     XtOverrideTranslations(side->ui->shell,
  319.     XtParseTranslationTable("<Message>WM_PROTOCOLS: wm-quit()"));
  320.  
  321. #ifdef DESIGNERS
  322.     /* If this side is already a designer (perhaps via command-line option)
  323.        popup the design controls now. */
  324.     if (side->designer)
  325.       popup_design(side);
  326. #endif /* DESIGNERS */
  327.  
  328.     Dprintf("Successfully initialized `%s'!\n", dpyname);
  329. }
  330.  
  331. /* This will set up the correct set of colors at any point in the game.
  332.    Colors are all specified by name; if any are not available, it is up to
  333.    the graphics interface to supply a substitute. */
  334.  
  335. void
  336. set_colors(side)
  337. Side *side;
  338. {
  339.     int    t;
  340.     char *colorname, substname[BUFSIZE];
  341.     char *unseencolorname = "black";
  342.     char *gridcolorname = "black";
  343.  
  344.     side->ui->fgcolor = side->ui->foreground;
  345.     side->ui->bgcolor = side->ui->background;
  346.     side->ui->whitecolor = request_color(side, "white");
  347.     side->ui->blackcolor = request_color(side, "black");
  348.     side->ui->diffcolor = side->ui->blackcolor;
  349.     side->ui->graycolor = side->ui->whitecolor;
  350.     side->ui->enemycolor = side->ui->whitecolor;
  351.     side->ui->neutcolor = side->ui->whitecolor;
  352.     side->ui->goodcolor = side->ui->badcolor = side->ui->whitecolor;
  353.     if (!empty_string(g_grid_color()))
  354.       gridcolorname = g_grid_color();
  355.     side->ui->gridcolor =
  356.       (strcmp(gridcolorname, "white") == 0 ? side->ui->whitecolor : side->ui->blackcolor);
  357.     if (!empty_string(g_unseen_color()))
  358.       unseencolorname = g_unseen_color();
  359.     side->ui->unseencolor =
  360.       (strcmp(unseencolorname, "white") == 0 ? side->ui->whitecolor : side->ui->blackcolor);
  361.     for_all_terrain_types(t) {
  362.     if (side->ui->monochrome) {
  363.         side->ui->cellcolor[t] = side->ui->blackcolor;
  364.     } else {
  365.         colorname = t_color(t);
  366.         /* Warn if we have to substitute a valid color name. */
  367.         if (empty_string(colorname)) {
  368.         /* Substitute grays 33 to 99 only. */
  369.         sprintf(substname, "gray%d", ((t * 66) / numttypes) + 33);
  370.         init_warning("no color for terrain type \"%s\", using \"%s\"",
  371.                  t_type_name(t), substname);
  372.         colorname = substname;
  373.         }
  374.         side->ui->cellcolor[t] = request_color(side, colorname);
  375.     }
  376.     }
  377.     /* Get special-purpose colors. */
  378.     if (!side->ui->monochrome) {
  379.     side->ui->diffcolor = request_color(side, "maroon");
  380.     side->ui->graycolor = request_color(side, "light gray");
  381.     side->ui->enemycolor = request_color(side, "red");
  382.     side->ui->neutcolor = request_color(side, "gray");
  383.     side->ui->goodcolor = request_color(side, "green");
  384.     side->ui->badcolor = request_color(side, "red");
  385.     side->ui->gridcolor = request_color(side, gridcolorname);
  386.     side->ui->unseencolor = request_color(side, unseencolorname);
  387.     }
  388. }
  389.  
  390. /* A predicate that tests whether our display can safely be written to. */
  391. /* (should have a macro version for internal-to-interface use?) */
  392.  
  393. int
  394. active_display(side)
  395. Side *side;
  396. {
  397.     return (side && side->ui && side->ui->active);
  398. }
  399.  
  400. /* Set up all the GCs. */
  401.  
  402. static void
  403. init_gcs(side)
  404. Side *side;
  405. {
  406.     unsigned long mask;
  407.     XGCValues values;
  408.     GC gc;
  409.     Display *dpy = side->ui->dpy;
  410.     Window rootwin = side->ui->rootwin;
  411.  
  412.     gc = DefaultGCOfScreen(DefaultScreenOfDisplay(dpy));
  413.  
  414.     side->ui->gc = XCreateGC(dpy, rootwin, 0L, NULL);
  415.     side->ui->textgc = XCreateGC(dpy, rootwin, 0L, NULL);
  416.     side->ui->ltextgc = XCreateGC(dpy, rootwin, 0L, NULL);
  417.     side->ui->terrgc = XCreateGC(dpy, rootwin, 0L, NULL);
  418.     side->ui->unitgc = XCreateGC(dpy, rootwin, 0L, NULL);
  419.     side->ui->emblgc = XCreateGC(dpy, rootwin, 0L, NULL);
  420.  
  421.     /* Set the fonts associated with each GC. */
  422.     XSetFont(dpy, side->ui->gc, side->ui->textfont->fid);
  423.     XSetFont(dpy, side->ui->textgc, side->ui->textfont->fid);
  424.     XSetFont(dpy, side->ui->ltextgc, side->ui->textfont->fid);
  425.     if (side->ui->unitfont != NULL)
  426.       XSetFont(dpy, side->ui->unitgc, side->ui->unitfont->fid);
  427.  
  428.     /* Set misc properties of each GC. */
  429.     mask = GCFillStyle | GCGraphicsExposures;
  430.     values.fill_style = FillSolid;
  431.     values.graphics_exposures = FALSE;
  432.     XChangeGC(dpy, side->ui->terrgc, mask, &values);
  433.     XChangeGC(dpy, side->ui->unitgc, mask, &values);
  434.     XChangeGC(dpy, side->ui->emblgc, mask, &values);
  435.  
  436.     DGprintf("GCs stored ...\n");
  437. }
  438.  
  439. /* Set up all the fonts. */
  440.  
  441. static void
  442. init_fonts(side)
  443. Side *side;
  444. {
  445.     int p, u;
  446.     XFontStruct *font;
  447.  
  448.     side->ui->textfont =
  449.       open_font(side, TEXTFONT, "TextFont", NULL, "", NULL);
  450.     side->ui->fw = font_width(side->ui->textfont);
  451.     side->ui->fh = font_height(side->ui->textfont);
  452.     font =
  453.       open_font(side, "*-bold-r-*-10-*", "LegendFont",
  454.         side->ui->textfont, "text", NULL);
  455.     for (p = 0; p < NUMPOWERS; ++p) {
  456.     for_all_unit_types(u) {
  457.         side->ui->ulegendfonts[p][u] = font;
  458.     }
  459.     }
  460.     side->ui->flegendfonts[0] =
  461.       open_font(side, "-*-helvetica-medium-r-*-*-8-*-*-*-*-*-*-*",
  462.         "LegendFont0", side->ui->textfont, "text",
  463.         &side->ui->flegendfids[0]);
  464.     side->ui->flegendfonts[1] =
  465.       open_font(side, "-*-helvetica-medium-r-*-*-10-*-*-*-*-*-*-*",
  466.         "LegendFont1", side->ui->textfont, "text",
  467.         &side->ui->flegendfids[1]);
  468.     side->ui->flegendfonts[2] =
  469.       open_font(side, "-*-helvetica-medium-r-*-*-14-*-*-*-*-*-*-*",
  470.         "LegendFont2", side->ui->textfont, "text",
  471.         &side->ui->flegendfids[2]);
  472.     side->ui->flegendfonts[3] =
  473.       open_font(side, "-*-helvetica-medium-r-*-*-18-*-*-*-*-*-*-*",
  474.         "LegendFont3", side->ui->textfont, "text",
  475.         &side->ui->flegendfids[3]);
  476.     side->ui->flegendfonts[4] =
  477.       open_font(side, "-*-helvetica-medium-r-*-*-24-*-*-*-*-*-*-*",
  478.         "LegendFont4", side->ui->textfont, "text",
  479.         &side->ui->flegendfids[4]);
  480.     DGprintf("Fonts opened ...\n");
  481. }
  482.  
  483. /* Get a color set up and warn if not getting what was asked for.  We can */
  484. /* tolerate being off somewhat.  (Note X rgb value range is 0-65535.) */
  485.  
  486. #define CLOSE_ENOUGH(X,Y) (ABS(((int) X) - ((int) Y)) < 2000)
  487.  
  488. long
  489. request_color(side, name)
  490. Side *side;
  491. char *name;
  492. {
  493.     XColor c, avail;
  494.  
  495.     DGprintf("Requesting color %s\n", (name ? name : "<null>"));
  496.     /* This might be called to get user-specified colors, even on a mono
  497.        display, so deal with it. */
  498.     if (empty_string(name)) {
  499.     init_warning(
  500.           "Requesting anonymous color on display \"%s\", substituting white",
  501.              side->player->displayname);
  502.     return WhitePixel(side->ui->dpy, side->ui->screen);
  503.     } else if (side->ui->monochrome) {
  504.     if (strcmp("white", name) == 0) {
  505.         return WhitePixel(side->ui->dpy, side->ui->screen);
  506.     } else if (strcmp("black", name) == 0) {
  507.         return BlackPixel(side->ui->dpy, side->ui->screen);
  508.     } else {
  509.         init_warning(
  510.               "No color \"%s\" on the mono display \"%s\", substituting white",
  511.              name, side->player->displayname);
  512.         return WhitePixel(side->ui->dpy, side->ui->screen);
  513.     }
  514.     } else {
  515.     XAllocNamedColor(side->ui->dpy,
  516.              DefaultColormap(side->ui->dpy, side->ui->screen),
  517.              name, &avail, &c);
  518.     if (!(CLOSE_ENOUGH(c.red, avail.red)
  519.           && CLOSE_ENOUGH(c.green, avail.green)
  520.           && CLOSE_ENOUGH(c.blue, avail.blue))) {
  521.         init_warning("%s color is way off on display \"%s\"!",
  522.              name, side->player->displayname);
  523.         init_warning("(%d %d %d instead of %d %d %d), but using it anyway",
  524.              avail.red, avail.green, avail.blue,
  525.              c.red, c.green, c.blue);
  526.     }
  527.     return avail.pixel;
  528.     }
  529. }
  530.  
  531. static void
  532. init_bitmaps(side)
  533. Side *side;
  534. {
  535.     int i;
  536.     Display *dpy = side->ui->dpy;
  537.     Window win = side->ui->rootwin;
  538.  
  539.     /* Get the solid hex outlines. */
  540.     side->ui->hexpics[3] =
  541.       XCreateBitmapFromData(dpy, win, hex8_bits, hex8_width, hex8_height);
  542.     side->ui->bhexpics[3] =
  543.       XCreateBitmapFromData(dpy, win, hex8b_bits, hex8b_width, hex8b_height);
  544.     side->ui->hexpics[4] =
  545.       XCreateBitmapFromData(dpy, win, hex16_bits, hex16_width, hex16_height);
  546.     side->ui->bhexpics[4] =
  547.       XCreateBitmapFromData(dpy, win, hex16b_bits, hex16b_width, hex16b_height);
  548.     side->ui->hexpics[5] =
  549.       XCreateBitmapFromData(dpy, win, hex32_bits, hex32_width, hex32_height);
  550.     side->ui->bhexpics[5] =
  551.       XCreateBitmapFromData(dpy, win, hex32b_bits, hex32b_width, hex32b_height);
  552.     /* Get pictures of mushroom clouds. */
  553.     side->ui->bombpics[0] =
  554.       XCreateBitmapFromData(dpy, win, bomb1_bits, bomb1_width, bomb1_height);
  555.     side->ui->bombpics[1] =
  556.       XCreateBitmapFromData(dpy, win, bomb2_bits, bomb2_width, bomb2_height);
  557.     side->ui->bombpics[2] =
  558.       XCreateBitmapFromData(dpy, win, bomb3_bits, bomb3_width, bomb3_height);
  559.     side->ui->bombpics[3] =
  560.       XCreateBitmapFromData(dpy, win, bomb4_bits, bomb4_width, bomb4_height);
  561.     side->ui->hitpics[0] =
  562.       XCreateBitmapFromData(dpy, win, miss_bits, miss_width, miss_height);
  563.     side->ui->hitpics[1] =
  564.       XCreateBitmapFromData(dpy, win, hit_bits, hit_width, hit_height);
  565.     side->ui->hitpics[2] =
  566.       XCreateBitmapFromData(dpy, win, kill_bits, kill_width, kill_height);
  567.     side->ui->boxcurs =
  568.       XCreateBitmapFromData(dpy, win, boxcurs_bits, boxcurs_width, boxcurs_height);
  569.     side->ui->boxmask =
  570.       XCreateBitmapFromData(dpy, win, boxmask_bits, boxmask_width, boxmask_height);
  571.     side->ui->grays[gray] =
  572.       XCreateBitmapFromData(dpy, win, gray_bits, gray_width, gray_height);
  573.     side->ui->grays[darkgray] =
  574.       XCreateBitmapFromData(dpy, win, darkgray_bits, darkgray_width, darkgray_height);
  575.     /* Collect pictures that will be used with map controls. */
  576.     for (i = 0; i < numcontrols; ++i)
  577.       side->ui->controlpics[i] = None;
  578.     side->ui->controlpics[LOOK] =
  579.       XCreateBitmapFromData(dpy, win, lookglass_bits, 16, 16);
  580.     side->ui->controlpics[MOVE] =
  581.       XCreateBitmapFromData(dpy, win, shootcursor_bits, 16, 16);
  582.     side->ui->controlpics[UNIT_MOVE] =
  583.       XCreateBitmapFromData(dpy, win, movecursor_bits, 16, 16);
  584.     side->ui->controlpics[UNIT_SHOOT] =
  585.       XCreateBitmapFromData(dpy, win, shootcursor_bits, 16, 16);
  586.     side->ui->controlpics[UNIT_BUILD] =
  587.       XCreateBitmapFromData(dpy, win, buildcursor_bits, 16, 16);
  588.     side->ui->controlpics[ZOOM_OUT] =
  589.       XCreateBitmapFromData(dpy, win, farther_bits, 16, 16);
  590.     side->ui->controlpics[ZOOM_IN] =
  591.       XCreateBitmapFromData(dpy, win, closer_bits, 16, 16);
  592.     DGprintf("Bitmaps stored ...\n");
  593. }
  594.  
  595. /* Make all the different kinds of cursors we intend to use.  Should be
  596.    one for each kind of mode or tool.  Cursors should always be 16x16. */
  597.  
  598. static void
  599. init_cursors(side)
  600. Side *side;
  601. {
  602.     int i;
  603.     Display *dpy = side->ui->dpy;
  604.     Window win = side->ui->rootwin;
  605.     int fg = side->ui->fgcolor, bg = side->ui->bgcolor;
  606.  
  607.     for (i = 0; i < numtools; ++i)
  608.       side->ui->toolcursors[i] = None;
  609.     side->ui->toolcursors[looktool] =
  610.       make_cursor(dpy, win, lookglass_bits, lookmask_bits,
  611.           fg, bg, lookglass_x_hot, lookglass_y_hot);
  612.     side->ui->toolcursors[movetool] =
  613.       make_cursor(dpy, win, shootcursor_bits, shootmask_bits,
  614.           fg, bg, shootcursor_x_hot, shootcursor_y_hot);
  615.     side->ui->toolcursors[unitmovetool] =
  616.       make_cursor(dpy, win, movecursor_bits, movemask_bits,
  617.           fg, bg, movecursor_x_hot, movecursor_y_hot);
  618.     side->ui->toolcursors[unitshoottool] =
  619.       make_cursor(dpy, win, shootcursor_bits, shootmask_bits,
  620.           fg, bg, shootcursor_x_hot, shootcursor_y_hot);
  621.     side->ui->toolcursors[unitbuildtool] =
  622.       make_cursor(dpy, win, buildcursor_bits, buildmask_bits,
  623.           fg, bg, buildcursor_x_hot, buildcursor_y_hot);
  624. #ifdef DESIGNERS
  625.     side->ui->toolcursors[terrainpainttool] =
  626.       make_cursor(dpy, win, hexcursor_bits, hexcursormask_bits,
  627.           fg, bg, hexcursor_x_hot, hexcursor_y_hot);
  628.     side->ui->toolcursors[unitaddtool] =
  629.       make_cursor(dpy, win, addunits_bits, addunits_bits,
  630.           fg, bg, addunits_x_hot, addunits_y_hot);
  631.     side->ui->toolcursors[peoplepainttool] =
  632.       make_cursor(dpy, win, people_bits, people_bits,
  633.           fg, bg, people_x_hot, people_y_hot);
  634.     side->ui->toolcursors[featurepainttool] =
  635.       make_cursor(dpy, win, feature_bits, featuremask_bits,
  636.           fg, bg, feature_x_hot, feature_y_hot);
  637. #endif /* DESIGNERS */
  638.     DGprintf("Cursors stored ...\n");
  639. }
  640.  
  641. /* Since XCreatePixmapCursor() takes XColors and not pixel values we
  642.    have to look up the colors associated with the foreground and
  643.    background pixel values in the color table and pass them to
  644.    XCreatePixmapCursor(). */
  645.    
  646. Cursor
  647. make_cursor(dpy, win, cursbits, maskbits, fg, bg, x, y)
  648. Display *dpy;
  649. Window win;
  650. char *cursbits, *maskbits;
  651. unsigned long fg, bg;
  652. unsigned int x, y;
  653. {
  654.     Pixmap curs, mask;
  655.     XColor fgcolor, bgcolor;
  656.     Cursor rslt;
  657.  
  658.     mask = XCreateBitmapFromData(dpy, win, maskbits, 16, 16);
  659.     curs = XCreateBitmapFromData(dpy, win, cursbits, 16, 16);
  660.     fgcolor.pixel = fg;
  661.     XQueryColor(dpy, DefaultColormap(dpy, DefaultScreen(dpy)), &fgcolor);
  662.     bgcolor.pixel = bg;
  663.     XQueryColor(dpy, DefaultColormap(dpy, DefaultScreen(dpy)), &bgcolor);
  664.     rslt = XCreatePixmapCursor(dpy, curs, mask, &fgcolor, &bgcolor, x, y);
  665.     XFreePixmap(dpy, mask);
  666.     XFreePixmap(dpy, curs);
  667.     return rslt;
  668. }
  669.  
  670. /* Open a font, possibly substituting another font if our desired one is
  671.    missing for some reason. */
  672.  
  673. XFontStruct *
  674. open_font(side, name, xdefault, altfont, alttype, fid)
  675. Side *side;
  676. char *name, *xdefault, *alttype;
  677. XFontStruct *altfont;
  678. Font *fid;
  679. {
  680.     XFontStruct *font;
  681.  
  682.     if (fid) {
  683.     *fid = XLoadFont(side->ui->dpy, name);
  684.     font = XQueryFont(side->ui->dpy, *fid);
  685.     } else {
  686.     font = XLoadQueryFont(side->ui->dpy, name);
  687.     }
  688.     if (font == NULL) {
  689.     init_warning("Can't open font \"%s\" on \"%s\"",
  690.              name, side->player->displayname);
  691.     if (altfont != NULL) {
  692.         init_warning("Substituting the %s font, hope it works!", alttype);
  693.         return altfont;
  694.     } else {
  695.         return NULL;
  696.     }
  697.     }
  698.     DGprintf("Opened font \"%s\" ...\n", name);
  699.     return font;
  700. }
  701.  
  702. /* Get a total bounding box on the font. */
  703.  
  704. int
  705. font_width(font)
  706. XFontStruct *font;
  707. {
  708.     return font->max_bounds.width;
  709. }
  710.  
  711. int
  712. font_height(font)
  713. XFontStruct *font;
  714. {
  715.     return font->max_bounds.ascent + font->max_bounds.descent;
  716. }
  717.  
  718. static void
  719. x11_interp_fn(imf)
  720. ImageFamily *imf;
  721. {
  722.     x11_interp_imf(tmp_display, tmp_root_window, imf, FALSE);
  723. }
  724.  
  725. static void
  726. x11_load_fn(imf)
  727. ImageFamily *imf;
  728. {
  729.     x11_load_imf(tmp_display, tmp_root_window, imf);
  730. }
  731.  
  732. static void
  733. init_unit_images(side)
  734. Side *side;
  735. {
  736.     int u, w, h;
  737.     ImageFamily *imf;
  738.  
  739.     side->ui->uimages =
  740.       (ImageFamily **) xmalloc(numutypes * sizeof(ImageFamily *));
  741.     tmp_display = side->ui->dpy;
  742.     tmp_root_window = side->ui->rootwin;
  743.     for_all_unit_types(u) {
  744.     imf = get_unit_type_images(side, u, x11_interp_fn, x11_load_fn, NULL);
  745.     /* (should fabricate something as a substitute) */
  746.     if (DebugG)
  747.       describe_imf(side, "unit type", u_type_name(u), imf);
  748.     side->ui->uimages[u] = imf;
  749.     if (smallest_image(imf, &w, &h)) {
  750.         if (w > min_w_for_unit_image)
  751.           min_w_for_unit_image = w;
  752.         if (h > min_h_for_unit_image)
  753.           min_h_for_unit_image = h;
  754.     }
  755.     }
  756. }
  757.  
  758. /* Collect images for all the terrain types. */
  759.  
  760. static void
  761. init_terrain_images(side)
  762. Side *side;
  763. {
  764.     int t, p;
  765.     ImageFamily *imf;
  766.     Image *timg;
  767.     X11Image *ximg;
  768.  
  769.     side->ui->timages =
  770.       (ImageFamily **) xmalloc(numttypes * sizeof(ImageFamily *));
  771.     tmp_display = side->ui->dpy;
  772.     tmp_root_window = side->ui->rootwin;
  773.     for_all_terrain_types(t) {
  774.     imf = get_terrain_type_images(side, t, x11_interp_fn, x11_load_fn, NULL);
  775.     if (imf != NULL && imf->numsizes == 0)
  776.       get_default_terrain_image(side, imf, t);
  777.     if (DebugG)
  778.       describe_imf(side, "terrain type", t_type_name(t), imf);
  779.     side->ui->timages[t] = imf;
  780.     /* Precalculate which images to use at which magnifications. */
  781.     for (p = 0; p < NUMPOWERS; ++p) {
  782.         if (1) {
  783.         timg = best_image(side->ui->timages[t], hws[p], hhs[p]);
  784.         if (timg != NULL) {
  785.             ximg = (X11Image *) timg->hook;
  786.             if (ximg != NULL) {
  787.             if (!side->ui->monochrome
  788. /* if somebody changes their mind about using the color images, this will lose */
  789.                  && side->ui->dflt_color_terr_images
  790.                  && ximg->colr != None)
  791.               side->ui->terrpics[p][t] = ximg->colr;
  792.             else
  793.               side->ui->terrpics[p][t] = ximg->mono;
  794.             }
  795.         }
  796.         }
  797.     }
  798.     }
  799. }
  800.  
  801. static void
  802. get_default_terrain_image(side, imf, t)
  803. Side *side;
  804. ImageFamily *imf;
  805. int t;
  806. {
  807.     Image *img;
  808.     X11Image *ximg;
  809.  
  810.     img = get_img(imf, 20, 22);
  811.     img->minw = 1;  img->minh = 1;
  812.     img->maxw = 999;  img->maxh = 999;
  813.     ximg = get_x11_image(img);
  814.     ximg->mono = 
  815.       XCreateBitmapFromData(side->ui->dpy, side->ui->rootwin,
  816.                 hex16b_bits, hex16b_width, hex16b_height);
  817. }
  818.  
  819. /* Set up a side's view of everybody else's colors and emblems. */
  820.  
  821. static void
  822. init_emblem_images(side)
  823. Side *side;
  824. {
  825.     Side *side2;
  826.     
  827.     side->ui->eimages =
  828.       (ImageFamily **) xmalloc((numsides + 1) * sizeof(ImageFamily *));
  829.     /* Independent units may have a distinguishing emblem, so the
  830.        indepside is included here. */
  831.     for_all_sides_plus_indep(side2) {
  832.     init_emblem(side, side2);
  833.     }
  834. }
  835.  
  836. /* Compute the distinctive emblem by which one side will recognize units
  837.    of another side.  This does both our view of ourselves and others
  838.    orthogonally.  Note that sides without displays can still have emblems
  839.    and colors that the sides with displays will see, but that sides
  840.    without displays don't need to do any emblem init. */
  841.  
  842. static void
  843. init_emblem(side, side2)
  844. Side *side, *side2;
  845. {
  846.     char cbuf[BUFSIZ], *s, *c;
  847.     int s2 = side_number(side2), i;
  848.     ImageFamily *imf;
  849.  
  850.     /* Collect the color names of the other side and try to request
  851.        them for our own display. */
  852.     if (!side->ui->monochrome && !empty_string(side2->colorscheme)) {
  853.     /* take spec apart and iterate for multiple colors */
  854.     for (s = side2->colorscheme, c = cbuf, i = 0; i < 3; ++s) {
  855.         if (*s == ',' || *s == '\0') {
  856.         *c = '\0';
  857.         c = cbuf;
  858.         side->ui->colors[s2][i++] = request_color(side, cbuf);
  859.         } else {
  860.         *c++ = *s;
  861.         }
  862.         if (*s == '\0')
  863.           break;
  864.     }
  865.     side->ui->numcolors[s2] = i;
  866.     } else {
  867.     side->ui->numcolors[s2] = 0;
  868.     }
  869.     tmp_display = side->ui->dpy;
  870.     tmp_root_window = side->ui->rootwin;
  871.     imf = get_emblem_images(side, side2, x11_interp_fn, x11_load_fn, NULL);
  872.     if (imf != NULL
  873.     && imf->numsizes == 0
  874.     && !(imf->name != NULL && strcmp(imf->name, "none") == 0)) {
  875.     get_default_emblem(side, imf, side2);
  876.     }
  877.     if (DebugG)
  878.       describe_imf(side, "emblem", side_desig(side2), imf);
  879.     side->ui->eimages[s2] = imf;
  880. }
  881.  
  882. static void
  883. get_default_emblem(side, imf, side2)
  884. Side *side, *side2;
  885. ImageFamily *imf;
  886. {
  887.     Image *img;
  888.     X11Image *ximg;
  889.  
  890.     img = get_img(imf, 8, 8);
  891.     img->minw = 8;  img->minh = 8;
  892.     img->maxw = 128;  img->maxh = 128;
  893.     ximg = get_x11_image(img);
  894.     /* (should make something for this image) */
  895. }
  896.  
  897. /* Output a general description of an image family. */
  898.  
  899. static void
  900. describe_imf(side, classname, typename, imf)
  901. Side *side;
  902. char *classname, *typename;
  903. ImageFamily *imf;
  904. {
  905.     Image *img;
  906.     X11Image *ximg;
  907.  
  908.     if (imf == NULL) {
  909.     DGprintf("No image family for %s %s for %s",
  910.          classname, typename, side_desig(side));
  911.     return;
  912.     }
  913.     DGprintf("%s %s family for %s has %d images",
  914.          classname, typename, side_desig(side), imf->numsizes);
  915.     if (imf->location)
  916.       DGprintf(" and is in %s", imf->location->name);
  917.     DGprintf("\n");
  918.     for (img = imf->images; img != NULL; img = img->next) {
  919.     DGprintf("    %dx%d", img->w, img->h);
  920.     ximg = (X11Image *) img->hook;
  921.     if (ximg)
  922.       DGprintf(" (x11 mono %d color %d mask %d)", ximg->mono, ximg->colr, ximg->mask);
  923.     DGprintf("\n");
  924.     }
  925. }
  926.  
  927. /* Shut the side's display down. */
  928.  
  929. void
  930. close_display(side)
  931. Side *side;
  932. {
  933.     Display *dpy = side->ui->dpy;
  934.  
  935.     XSync(dpy, True);
  936.     /* Mark it as inactive. */
  937.     side->ui->active = FALSE;
  938.     /* Clean up after ourselves. */
  939.     XFreeGC(dpy, side->ui->gc);
  940.     XFreeGC(dpy, side->ui->textgc);
  941.     XFreeGC(dpy, side->ui->ltextgc);
  942.     XFreeGC(dpy, side->ui->terrgc);
  943.     XFreeGC(dpy, side->ui->unitgc);
  944.     XFreeGC(dpy, side->ui->emblgc);
  945.     XCloseDisplay(dpy);
  946. }
  947.  
  948. /* (try to flush?) */
  949. #include "cmdline.h"
  950.  
  951. typedef struct s_varw {
  952.   Widget dialog;
  953.   char *value;
  954.   char *mess;
  955. } Varw;
  956.  
  957. typedef struct s_assignw {
  958.   Widget side, pname, pid;
  959.   char *vname, *vid, *messname, *messid;
  960.   int vflag;
  961. } Assignw;
  962.  
  963. typedef struct s_gamepop {
  964.   Widget shell;
  965.   Widget form;
  966.   Widget name;
  967.   Widget basemodule;
  968.   Widget version;
  969.   Widget title;
  970.   Widget blurb;
  971.   Widget instructions;
  972.   Widget notes;
  973.   Widget ok;
  974.   Widget add;
  975.   Widget verify;
  976.   Widget cancel;
  977.   Varw *variants;
  978.   int numvariants;
  979.   Assignw *assign;
  980. } GamePop;
  981.  
  982. typedef struct s_gamew {
  983.   Widget form;
  984.   Widget name;
  985.   Widget title;
  986.   Widget blurb;
  987.   GamePop *pop;
  988. } Gamew;
  989.  
  990. void popup_game_dialog PROTO ((void));
  991. void popup_game PROTO ((int g, int flag));
  992. extern void quit_dialog PROTO ((Widget w, XtPointer client_data,
  993.                 XtPointer call_data));
  994. extern void game_callback PROTO ((Widget w, XtPointer client_data,
  995.                   XtPointer call_data));
  996. extern void cancel_dialog PROTO ((Widget w, XtPointer client_data,
  997.                      XtPointer call_data));
  998. extern void ok_dialog PROTO ((Widget w, XtPointer client_data,
  999.                      XtPointer call_data));
  1000. extern void go_dialog PROTO ((Widget w, XtPointer client_data,
  1001.                      XtPointer call_data));
  1002. extern void verify_dialog PROTO ((Widget w, XtPointer client_data,
  1003.                      XtPointer call_data));
  1004. extern void add_player_dialog PROTO ((Widget w, XtPointer client_data,
  1005.                      XtPointer call_data));
  1006. int valid_gamepop PROTO ((void));
  1007. void splat_obj_in_textw PROTO ((Widget w, Obj *obj));
  1008. Widget createTextWidget PROTO ((char *name, Widget parent,
  1009.                 Widget up, Obj *obj));
  1010. char *variant_default PROTO ((Variant *var));
  1011. char *variant_name PROTO ((Variant *var));
  1012. void horizontalDialog PROTO ((Widget w));
  1013. void reverseVideoDialog PROTO ((Widget w));
  1014. void implement_variant PROTO ((char *value, Variant *var));
  1015. int valid_variant PROTO ((char *value, Variant *var));
  1016. int type_player  PROTO ((char *value));
  1017. void init_assignw_player PROTO ((Assignw *assignw, Player *player));
  1018. int can_open_display PROTO ((char *dpyname));
  1019. int boolean_lisp PROTO ((char *value));
  1020.  
  1021.  
  1022. static int loop, chosen_game;
  1023.  
  1024. static Widget gameShell;
  1025.  
  1026. static Gamew *games;
  1027.  
  1028. /* we could share this buffers with other modules */
  1029. char buf1[BUFSIZE], buf2[BUFSIZE], buf3[BUFSIZE], errormess[BUFSIZE];
  1030.  
  1031. Obj *variants;
  1032.  
  1033. void 
  1034. popup_game_dialog ()
  1035. {
  1036.   int i;
  1037.   Widget outform, label, quit, viewp, inform;
  1038.   Module *module;
  1039.  
  1040.   games = (Gamew *) xmalloc(numgames*sizeof(Gamew));
  1041.  
  1042.   gameShell = XtVaCreatePopupShell(
  1043.         "gameDialog", topLevelShellWidgetClass, thistoplevel,  NULL);
  1044.   outform = XtVaCreateManagedWidget(
  1045.         "outForm", formWidgetClass, gameShell,  NULL);
  1046.   label = XtVaCreateManagedWidget(
  1047.         "label", labelWidgetClass, outform,  NULL);
  1048.   quit = XtVaCreateManagedWidget("quit", commandWidgetClass, outform,
  1049.                  XtNfromHoriz, label,  NULL);
  1050.   XtAddCallback (quit, XtNcallback, quit_dialog, NULL);
  1051.   viewp = XtVaCreateManagedWidget(
  1052.         "viewport", viewportWidgetClass,  outform,
  1053.         XtNfromVert,  label,
  1054.         XtNallowVert, True,  NULL);
  1055.   inform = XtVaCreateManagedWidget(
  1056.         "inForm", formWidgetClass, viewp,  NULL);
  1057.   
  1058.   for (i = 0; i < numgames; ++i) {
  1059.     module = possible_games[i];
  1060.     games[i].form = XtVaCreateManagedWidget(
  1061.         module->name, formWidgetClass, inform, 
  1062.         XtNfromVert, i ? games[i-1].form : NULL,  NULL);
  1063.     games[i].name = XtVaCreateManagedWidget(
  1064.         "name", commandWidgetClass, games[i].form,
  1065.         XtNlabel, module->name,  NULL);
  1066.     XtAddCallback (games[i].name, XtNcallback, game_callback, NULL);
  1067.     if (module->title && module->title[0]) {
  1068.       games[i].title = XtVaCreateManagedWidget(
  1069.         "title", labelWidgetClass, games[i].form,
  1070.         XtNlabel, module->title,
  1071.         XtNfromHoriz, games[i].name,  NULL);
  1072.     } else {
  1073.       games[i].title = NULL;
  1074.     }
  1075.     if (module->blurb && module->blurb[0]) {
  1076.       games[i].blurb = XtVaCreateManagedWidget(
  1077.         "blurb", labelWidgetClass, games[i].form,
  1078.         XtNlabel, module->blurb,
  1079.         XtNfromHoriz, games[i].title ? games[i].title : 
  1080.                            games[i].name,  NULL);
  1081.     } else {
  1082.       games[i].blurb = NULL;
  1083.     }
  1084.     games[i].pop = NULL;
  1085.   }
  1086.  
  1087.   XtPopup(gameShell, XtGrabNone);
  1088.  
  1089. /* replacement for XtAppMainLoop(thisapp): */
  1090.   loop = 1;
  1091.   while (loop) {
  1092.     XEvent event;
  1093.     XtAppNextEvent(thisapp, &event);
  1094.     XtDispatchEvent(&event);
  1095.   }
  1096. }
  1097.  
  1098. void
  1099. popup_game(g, flag)
  1100. int g, flag;
  1101. {
  1102.     char *vartypename = NULL, *def;
  1103.     GamePop *pop = games[g].pop;
  1104.     Module *module = possible_games[g];
  1105.     Widget up, left, save;
  1106.     Variant *var;
  1107.     Varw *varw;
  1108.     int i;
  1109.     Side *side;
  1110.     Player *player;
  1111.     static char *player_type[] = { "none", "human", "machine" };
  1112.  
  1113.     if (!pop || flag) {
  1114.     if (!pop) {
  1115.         games[g].pop = pop = (GamePop *) xmalloc(sizeof(GamePop));
  1116.         pop->variants = NULL;
  1117.     }
  1118.     sprintf(buf1, "xconq game: %s", module->name);
  1119.     pop->shell =
  1120.       XtVaCreatePopupShell(module->name, topLevelShellWidgetClass,
  1121.                    thistoplevel, 
  1122.                    XtNtitle, buf1,
  1123.                    NULL);
  1124.     pop->form =
  1125.       XtVaCreateManagedWidget("gameForm", formWidgetClass, pop->shell,
  1126.                   NULL);
  1127.     up = left = pop->name =
  1128.       XtVaCreateManagedWidget("name", labelWidgetClass, pop->form,
  1129.                   XtNlabel, module->name,
  1130.                   NULL);
  1131.     if (module->basemodulename && module->basemodulename[0]) {
  1132.         sprintf(buf1, "base module: %s", module->basemodulename);
  1133.     } else {
  1134.         strcpy(buf1, "no base module");
  1135.     }
  1136.     left = pop->basemodule =
  1137.       XtVaCreateManagedWidget("basemodule", labelWidgetClass, pop->form,
  1138.                   XtNlabel, buf1,
  1139.                   XtNfromHoriz, left,
  1140.                   NULL);
  1141.     if (module->version && module->version[0]) {
  1142.         sprintf(buf1, "version: %s", module->version);
  1143.         left = pop->version =
  1144.           XtVaCreateManagedWidget("version", labelWidgetClass, pop->form,
  1145.                       XtNlabel, module->version,
  1146.                       XtNfromHoriz, left,
  1147.                       NULL);
  1148.     }
  1149.     if (module->title && module->title[0]) {
  1150.         up = pop->title =
  1151.           XtVaCreateManagedWidget("title", labelWidgetClass, pop->form,
  1152.                       XtNlabel, module->title,
  1153.                       XtNfromVert, pop->name,
  1154.                       NULL);
  1155.     }
  1156.     if (module->blurb && module->blurb[0]) {
  1157.         up = pop->blurb =
  1158.           XtVaCreateManagedWidget("blurb", labelWidgetClass, pop->form,
  1159.                       XtNlabel, module->blurb,
  1160.                       XtNfromHoriz, pop->title,
  1161.                       XtNfromVert, pop->name,
  1162.                       NULL);
  1163.     }
  1164.  
  1165.     if (module->variants) {
  1166.         for (i = 0; module->variants[i].id != lispnil; ++i) { }
  1167.         pop->numvariants = i;
  1168.     } else {
  1169.         pop->numvariants = 0;
  1170.     }
  1171.     if (flag && pop->numvariants) {
  1172.         if (flag == 1) {
  1173.         pop->variants =
  1174.           (Varw *) xmalloc(pop->numvariants*sizeof(Varw));
  1175.         }
  1176.         up =
  1177.           XtVaCreateManagedWidget("variant", labelWidgetClass, pop->form,
  1178.                       XtNlabel, "Variants:",
  1179.                       XtNfromVert, up,
  1180.                       NULL);
  1181.  
  1182.         for (i = 0; i < pop->numvariants; ++i) {
  1183.         var = &(module->variants[i]);
  1184.         varw = &(pop->variants[i]);
  1185.         vartypename = c_string(var->id);
  1186.  
  1187.         if (flag == 1)
  1188.           varw->value = variant_default(var); 
  1189.         sprintf(buf1, "variant%d", i);
  1190.         up = varw->dialog =
  1191.           XtVaCreateManagedWidget(buf1, dialogWidgetClass, pop->form,
  1192.                       XtNlabel, variant_name(var),
  1193.                       XtNvalue, varw->value,
  1194.                       XtNfromVert, up,
  1195.                       NULL);
  1196.         horizontalDialog(varw->dialog);
  1197.         if (varw->mess && varw->mess[0]) {
  1198.             reverseVideoDialog(varw->dialog);
  1199.             up =
  1200.               XtVaCreateManagedWidget("varMessage", labelWidgetClass,
  1201.                           pop->form,
  1202.                           XtNlabel, varw->mess,
  1203.                           XtNfromVert, up,
  1204.                           NULL);
  1205.         }
  1206.         }
  1207.     }
  1208.  
  1209.     pop->instructions = createTextWidget("instructions", pop->form,
  1210.                          up, module->instructions);
  1211.     if (pop->instructions)
  1212.       up = pop->instructions;
  1213.     pop->notes = createTextWidget("notes", pop->form, up, module->notes);
  1214.     if (pop->notes)
  1215.       up = pop->notes;
  1216.  
  1217.     if (flag) {
  1218.         up = XtVaCreateManagedWidget("assign", labelWidgetClass, pop->form,
  1219.                      XtNlabel, "Assignments:",
  1220.                      XtNfromVert, up,
  1221.                      NULL);
  1222.         if (flag == 1) {
  1223.         pop->assign = (Assignw *) xmalloc(MAXSIDES*sizeof(Assignw));
  1224.         }
  1225.         for (i = 0; i < numsides; ++i) {
  1226.         side   = assignments[i].side;
  1227.         player = assignments[i].player;
  1228.         if (flag == 1) { 
  1229.             init_assignw_player(&(pop->assign[i]), player);
  1230.         }
  1231.         if (side->sideclass && side->sideclass[0]) {
  1232.             sprintf(buf1, "%s (%s)", short_side_title(side),
  1233.                 side->sideclass);
  1234.         } else {
  1235.             strcpy(buf1, short_side_title(side));
  1236.         }
  1237.         save = left = pop->assign[i].side =
  1238.           XtVaCreateManagedWidget("side", labelWidgetClass, pop->form,
  1239.                       XtNlabel, buf1,
  1240.                       XtNfromVert, up,
  1241.                       NULL);
  1242.         left = pop->assign[i].pname =
  1243.           XtVaCreateManagedWidget("pname", dialogWidgetClass,
  1244.                       pop->form,
  1245.                       XtNlabel, "name",
  1246.                       XtNvalue, pop->assign[i].vname,
  1247.                       XtNfromHoriz, left,
  1248.                       XtNfromVert, up,
  1249.                       NULL);
  1250.         horizontalDialog(pop->assign[i].pname);
  1251.         up = pop->assign[i].pid =
  1252.           XtVaCreateManagedWidget("pid", dialogWidgetClass, pop->form,
  1253.                       XtNlabel, player_type[pop->assign[i].vflag],
  1254.                       XtNvalue, pop->assign[i].vid,
  1255.                       XtNfromHoriz, left,
  1256.                       XtNfromVert, up,
  1257.                       NULL);
  1258.         horizontalDialog(pop->assign[i].pid);
  1259.         if (pop->assign[i].messname && pop->assign[i].messname[0]) {
  1260.             reverseVideoDialog(pop->assign[i].pname);
  1261.             up = XtVaCreateManagedWidget("nameMessage",
  1262.                          labelWidgetClass, pop->form,
  1263.                          XtNlabel, pop->assign[i].messname,
  1264.                          XtNfromHoriz, save,
  1265.                          XtNfromVert, up,
  1266.                          NULL);
  1267.         }
  1268.         if (pop->assign[i].messid && pop->assign[i].messid[0]) {
  1269.             reverseVideoDialog(pop->assign[i].pid);
  1270.             up = XtVaCreateManagedWidget("idMessage",
  1271.                          labelWidgetClass, pop->form,
  1272.                          XtNlabel, pop->assign[i].messid,
  1273.                          XtNfromHoriz, save,
  1274.                          XtNfromVert, up,
  1275.                          NULL);
  1276.         }
  1277.         }
  1278.         left = pop->add =
  1279.           XtVaCreateManagedWidget("add", commandWidgetClass, pop->form,
  1280.                       XtNfromVert, up,
  1281.                       NULL);
  1282.         XtAddCallback (pop->add, XtNcallback, add_player_dialog, NULL);
  1283.         left = pop->verify =
  1284.           XtVaCreateManagedWidget("verify", commandWidgetClass, pop->form,
  1285.                       XtNfromVert, up,
  1286.                       XtNfromHoriz, left,
  1287.                       NULL);
  1288.         XtAddCallback (pop->verify, XtNcallback, verify_dialog, NULL);
  1289.         left = pop->ok =
  1290.           XtVaCreateManagedWidget("go", commandWidgetClass, pop->form,
  1291.                       XtNfromVert, up,
  1292.                       XtNfromHoriz, left,
  1293.                       NULL);
  1294.         XtAddCallback (pop->ok, XtNcallback, go_dialog, NULL);
  1295.         pop->cancel =
  1296.           XtVaCreateManagedWidget("quit", commandWidgetClass, pop->form,
  1297.                       XtNfromVert, up,
  1298.                       XtNfromHoriz, left,
  1299.                       NULL);
  1300.         XtAddCallback (pop->cancel, XtNcallback, quit_dialog, NULL);
  1301.     } else {
  1302.         left = pop->ok =
  1303.           XtVaCreateManagedWidget("ok", commandWidgetClass, pop->form,
  1304.                       XtNfromVert, up,
  1305.                       NULL);
  1306.         XtAddCallback (pop->ok, XtNcallback, ok_dialog, NULL);
  1307.         pop->cancel =
  1308.           XtVaCreateManagedWidget("cancel", commandWidgetClass, pop->form,
  1309.                       XtNfromVert, up,
  1310.                       XtNfromHoriz, left,  NULL);
  1311.         XtAddCallback (pop->cancel, XtNcallback, cancel_dialog, NULL);
  1312.     }
  1313.     }
  1314.     XtPopup (pop->shell, XtGrabNone);
  1315.     XMapRaised(XtDisplay(pop->shell), XtWindow(pop->shell));
  1316. }
  1317.  
  1318. Widget
  1319. createTextWidget(name, parent, up, obj)
  1320. char *name;
  1321. Widget parent, up;
  1322. Obj *obj;
  1323. {
  1324.     Widget w;
  1325.  
  1326.     if (obj == lispnil)
  1327.       return NULL;
  1328.  
  1329.     sprintf(buf1, "%s_label", name);
  1330.     w =
  1331.       XtVaCreateManagedWidget(buf1, labelWidgetClass, parent,
  1332.                   XtNlabel, name,
  1333.                   XtNfromVert, up,
  1334.                   NULL);
  1335.     w =
  1336.       XtVaCreateManagedWidget(name, asciiTextWidgetClass, parent,
  1337.                   XtNfromVert, w,
  1338.                   XtNvertDistance, -1,
  1339.                   NULL);
  1340.     splat_obj_in_textw(w, obj);
  1341.     return w;
  1342. }
  1343.  
  1344. void
  1345. splat_obj_in_textw(w, obj)
  1346. Widget w;
  1347. Obj *obj;
  1348. {
  1349.     Obj *rest;
  1350.  
  1351.     if (!obj || obj == lispnil)
  1352.       return;
  1353.  
  1354.     if (stringp(obj)) {
  1355.     textw_printf(w, "%s\n", c_string(obj));
  1356.     return;
  1357.     }
  1358.  
  1359.     if (!consp(obj))
  1360.       return;
  1361.  
  1362.     for (rest = obj; rest != lispnil; rest = cdr(rest)) {
  1363.     if (stringp(car(rest))) {
  1364.         textw_printf(w, "%s\n", c_string(car(rest)));
  1365.     }
  1366.     }
  1367. }
  1368.  
  1369. void
  1370. quit_dialog (w, client_data, call_data)
  1371. Widget w;
  1372. XtPointer client_data;
  1373. XtPointer call_data;
  1374. {
  1375.    exit(0);
  1376. }
  1377.  
  1378.  
  1379. void
  1380. game_callback (w, client_data, call_data)
  1381. Widget w;
  1382. XtPointer client_data;
  1383. XtPointer call_data;
  1384. {
  1385.     int i;
  1386.  
  1387.     for (i = 0; i < numgames; ++i) {
  1388.     if (w == games[i].name) {
  1389.         popup_game(i, 0);
  1390.         return;
  1391.     }
  1392.     }
  1393. }
  1394.  
  1395. void
  1396. cancel_dialog (w, client_data, call_data)
  1397. Widget w;
  1398. XtPointer client_data;
  1399. XtPointer call_data;
  1400. {
  1401.     int i;
  1402.     Widget form = XtParent(w);
  1403.  
  1404.     for (i = 0; i < numgames; ++i) {
  1405.     if (games[i].pop && form == games[i].pop->form) {
  1406.         XtPopdown(games[i].pop->shell);
  1407.     }
  1408.     }
  1409. }
  1410.  
  1411. void
  1412. ok_dialog (w, client_data, call_data)
  1413. Widget w;
  1414. XtPointer client_data;
  1415. XtPointer call_data;
  1416. {
  1417.     int i;
  1418.     Widget form = XtParent(w);
  1419.  
  1420.     for (i = 0; i < numgames; ++i) {
  1421.     if (games[i].pop && form == games[i].pop->form) {
  1422.         break;
  1423.     }
  1424.     }
  1425.     chosen_game = i;
  1426.   
  1427.     /* clean up */
  1428.     for (i = 0; i < numgames; ++i) {
  1429.     if (games[i].pop) {
  1430.         XtPopdown(games[i].pop->shell);
  1431.         XtDestroyWidget(games[i].pop->shell);
  1432.         if (i != chosen_game) {
  1433.         if (games[i].pop->variants)
  1434.           free(games[i].pop->variants);
  1435.         free(games[i].pop);
  1436.         games[i].pop = NULL;
  1437.         }
  1438.     }
  1439.     }
  1440.     XtPopdown(gameShell);
  1441.     XtDestroyWidget(gameShell);
  1442.  
  1443.     /* initialize game and sides */
  1444.     mainmodule = possible_games[chosen_game];
  1445.     load_game_module(mainmodule, TRUE);
  1446.     check_game_validity();
  1447.     make_trial_assignments();
  1448.  
  1449.     popup_game(chosen_game, 1);
  1450. }
  1451.  
  1452. void
  1453. go_dialog (w, client_data, call_data)
  1454. Widget w;
  1455. XtPointer client_data;
  1456. XtPointer call_data;
  1457. {
  1458.     GamePop *pop = games[chosen_game].pop;
  1459.     char *value;
  1460.     int i, flag;
  1461.  
  1462.     if (!valid_gamepop()) {
  1463.     verify_dialog(w, NULL, NULL);
  1464.     XBell(XtDisplay(pop->shell),50);
  1465.     return;
  1466.     }
  1467.  
  1468.     variants = lispnil;
  1469.     /* setup variants */
  1470.     for (i = 0; i < pop->numvariants; ++i) {
  1471.     value = XawDialogGetValueString(pop->variants[i].dialog);
  1472.     implement_variant(value, &(mainmodule->variants[i]));
  1473.     if (pop->variants[i].mess)
  1474.       free(pop->variants[i].mess);
  1475.     }
  1476.     /* get side values */
  1477.     for (i = 0; i < numsides; ++i) {
  1478.     if (pop->assign[i].pname) {
  1479.         value = XawDialogGetValueString(pop->assign[i].pname);
  1480.         if (value && value[0]) {
  1481.         assignments[i].player->name = copy_string(value);
  1482.         } else {
  1483.         assignments[i].player->name = NULL;
  1484.         }
  1485.         if (pop->assign[i].messname)
  1486.           free(pop->assign[i].messname);
  1487.     }
  1488.     if (pop->assign[i].pid) {
  1489.         value = XawDialogGetValueString(pop->assign[i].pid);
  1490.         flag = type_player(value);
  1491.         if (ABS(flag) == 1) {
  1492.         assignments[i].player->displayname = copy_string(value);
  1493.         assignments[i].player->aitypename  = NULL;
  1494.         } else {
  1495.         assignments[i].player->displayname = NULL;
  1496.         assignments[i].player->aitypename  = copy_string(value);
  1497.         }
  1498.         if (pop->assign[i].messid)
  1499.           free(pop->assign[i].messid);
  1500.     }
  1501.     }
  1502.  
  1503.     XtPopdown(pop->shell);
  1504.     XtDestroyWidget(pop->shell);
  1505.     if (pop->variants)
  1506.       free(pop->variants);
  1507.     if (pop->assign)
  1508.       free(pop->assign);
  1509.     free(pop);
  1510.     free(games);
  1511.     games = NULL;
  1512.  
  1513.     do_module_variants(mainmodule, variants);
  1514.     check_game_validity();
  1515.  
  1516.     loop = 0;
  1517. }
  1518.  
  1519. int
  1520. valid_gamepop ()
  1521. {
  1522.     GamePop *pop = games[chosen_game].pop;
  1523.     char *value;
  1524.     int i, flag, res = 1;
  1525.  
  1526.     /* check variants */
  1527.     for (i = 0; i < pop->numvariants; ++i) {
  1528.     value = XawDialogGetValueString(pop->variants[i].dialog);
  1529.     res = res && valid_variant(value, &(mainmodule->variants[i]));
  1530.     }
  1531.     /* check sides */
  1532.     for (i = 0; i < numsides; ++i) {
  1533.     if (pop->assign[i].pid) {
  1534.         value = XawDialogGetValueString(pop->assign[i].pid);
  1535.         res = res && type_player(value)>0;
  1536.     }
  1537.     }
  1538.  
  1539.     return res;
  1540. }
  1541.  
  1542. void
  1543. verify_dialog(w, client_data, call_data)
  1544. Widget w;
  1545. XtPointer client_data;
  1546. XtPointer call_data;
  1547. {
  1548.     GamePop *pop = games[chosen_game].pop;
  1549.     char *value;
  1550.     int i, flag;
  1551.  
  1552.     /* save variant values */
  1553.     for (i = 0; i < pop->numvariants; ++i) {
  1554.     value = XawDialogGetValueString(pop->variants[i].dialog);
  1555.     pop->variants[i].value = copy_string(value);
  1556.     if (valid_variant(value, &(mainmodule->variants[i]))) {
  1557.         if (pop->variants[i].mess)  free(pop->variants[i].mess);
  1558.         pop->variants[i].mess = NULL;
  1559.     } else {
  1560.         pop->variants[i].mess = copy_string(errormess);
  1561.     }
  1562.     }
  1563.     /* save side values */
  1564.     for (i = 0; i < numsides; ++i) {
  1565.     if (pop->assign[i].pname) {
  1566.         value = XawDialogGetValueString(pop->assign[i].pname);
  1567.         pop->assign[i].vname = copy_string(value);
  1568.         pop->assign[i].messname = 0;  /* names always OK? */
  1569.     }
  1570.     if (pop->assign[i].pid) {
  1571.         value = XawDialogGetValueString(pop->assign[i].pid);
  1572.         pop->assign[i].vid = copy_string(value);
  1573.         flag = type_player(value);
  1574.         if (flag > 0) {
  1575.         if (pop->assign[i].messid)
  1576.           free(pop->assign[i].messid);
  1577.         pop->assign[i].messid = NULL;
  1578.         } else {
  1579.         pop->assign[i].messid = copy_string(errormess);
  1580.         }
  1581.     }
  1582.     pop->assign[i].vflag = ABS(flag);
  1583.     }
  1584.  
  1585.     XtPopdown(pop->shell);
  1586.     XtDestroyWidget(pop->shell);
  1587.  
  1588.     popup_game(chosen_game, 2);
  1589. }
  1590.  
  1591. char *
  1592. variant_default(var)
  1593. Variant *var;
  1594. {
  1595.     int i1, i2, i3, i4, i5, n;
  1596.     char *p;
  1597.  
  1598.     switch (keyword_code(c_string(var->id))) {
  1599.       case K_WORLD_SEEN:
  1600.       case K_SEE_ALL:
  1601.       case K_SEQUENTIAL:
  1602.     if (var->dflt == lispnil)  return "true";
  1603.     return c_number(eval(var->dflt)) ? " true" : "false";
  1604.       case K_WORLD_SIZE:
  1605.     sprintlisp(buf3, var->dflt);
  1606.     for (p = buf3; *p; ++p) {
  1607.         if (!isdigit(*p))
  1608.           *p = ' ';
  1609.     }
  1610.     n = sscanf(buf3, "%d%d%d%d%d", &i1, &i2, &i3, &i4, &i5);
  1611.     sprintf(buf3, "(%d %d %d)",
  1612.         (n>0) ? i1 : DEFAULTWIDTH,
  1613.         (n>1) ? i2 : DEFAULTHEIGHT,
  1614.         (n>2) ? i3 : DEFAULTCIRCUMFERENCE);
  1615.     if (n == 4) {
  1616.         sprintf(buf3, "(%d %d %d %d)", i1, i2, i3, i4);
  1617.     }
  1618.     if (n == 5) {
  1619.         sprintf(buf3, "(%d %d %d %d %d)", i1, i2, i3, i4, i5);
  1620.     }
  1621.     return buf3;
  1622.       default:
  1623.     sprintlisp(buf3, var->dflt);
  1624.     return buf3;
  1625.     }
  1626. }
  1627.  
  1628. char *
  1629. variant_name(var)
  1630. Variant *var;
  1631. {
  1632.     switch (keyword_code(c_string(var->id))) {
  1633.       case K_WORLD_SEEN:
  1634.     sprintf(buf2, "%s: make the world be seen already", var->name);
  1635.     return buf2;
  1636.       case K_SEE_ALL:
  1637.     sprintf(buf2, "%s: make everything be always seen", var->name);
  1638.     return buf2;
  1639.       case K_SEQUENTIAL:
  1640.     sprintf(buf2, "%s: move sequentially", var->name);
  1641.     return buf2;
  1642.       case K_WORLD_SIZE:
  1643.     sprintf(buf2, 
  1644.     "%s: set world size (width height circumference [longitude [latitude]])",
  1645.         var->name);
  1646.     return buf2;
  1647.       default:
  1648.     return var->name;
  1649.     }
  1650. }
  1651.  
  1652. void
  1653. horizontalDialog(w)
  1654. Widget w;
  1655. {
  1656.     Widget label, value;
  1657.     int a;
  1658.  
  1659.     label = XtNameToWidget(w, "label");
  1660.     value = XtNameToWidget(w, "value");
  1661.     if (label && value) {
  1662.     XtVaSetValues(value,
  1663.               XtNfromVert,  NULL,
  1664.               XtNfromHoriz, label,
  1665.               NULL);
  1666.     }
  1667. }
  1668.  
  1669. void
  1670. reverseVideoDialog(w)
  1671. Widget w;
  1672. {
  1673.     Pixel fg, bg;
  1674.     Widget label = XtNameToWidget(w, "label");
  1675.  
  1676.     if (!label)
  1677.       return;
  1678.     XtVaGetValues(label, XtNbackground, &bg, XtNforeground, &fg, NULL);
  1679.     XtVaSetValues(w, XtNbackground, fg, NULL);
  1680.     XtVaSetValues(label, XtNbackground, fg, XtNforeground, bg, NULL);
  1681. }
  1682.  
  1683. int
  1684. boolean_lisp(value)
  1685. char *value;
  1686. {
  1687.     char c, *p;
  1688.  
  1689.     if (!value || !value[0])
  1690.       return 0;
  1691.  
  1692.     for (p = value; *p; ++p) {
  1693.     if (isalnum(*p)){
  1694.         c = tolower(value[0]);
  1695.         return (c != '0' && c != 'n' && c != 'f');
  1696.     }
  1697.     }
  1698. }
  1699.  
  1700. void
  1701. implement_variant(value, var)
  1702. char *value;
  1703. Variant *var;
  1704. {
  1705.     int key = keyword_code(c_string(var->id)), i1, i2, i3, i4, i5, n;
  1706.     char *p;
  1707.  
  1708.     switch (key) {
  1709.       case K_WORLD_SEEN:
  1710.       case K_SEE_ALL:
  1711.       case K_SEQUENTIAL:
  1712.     push_key_int_binding(&variants, key, boolean_lisp(value));
  1713.     break;
  1714.       case K_WORLD_SIZE:
  1715.     for (p=value; *p; p++) {
  1716.         if (!isdigit(*p))  *p = ' ';
  1717.     }
  1718.     n = sscanf(value, "%d%d%d%d%d", &i1, &i2, &i3, &i4, &i5);
  1719.     if (n < 4)
  1720.       i4 = 0;
  1721.     if (n < 5)
  1722.       i5 = 0;
  1723.     push_key_cdr_binding(&variants, key,
  1724.                  cons(new_number(i1),
  1725.                   cons(new_number(i2),
  1726.                        cons(new_number(i3),
  1727.                         cons(new_number(i4),
  1728.                          cons(new_number(i5),
  1729.                               lispnil))))));
  1730.     break;
  1731.  
  1732.       default:
  1733.     /* what to do here? */
  1734.     break;
  1735.     }
  1736. }
  1737.  
  1738. int
  1739. valid_variant(value, var)
  1740. char *value;
  1741. Variant *var;
  1742. {
  1743.     int key = keyword_code(c_string(var->id)), i1, i2, i3, i4, i5, n;
  1744.     char *p;
  1745.  
  1746.     errormess[0] = '\0';
  1747.  
  1748.     switch (key) {
  1749.       case K_WORLD_SEEN:
  1750.       case K_SEE_ALL:
  1751.       case K_SEQUENTIAL:
  1752.     return (value && value[0]);
  1753.  
  1754.       case K_WORLD_SIZE:
  1755.     for (p = value; *p; p++) {
  1756.         if (!isdigit(*p))
  1757.           *p = ' ';
  1758.     }
  1759.     n = sscanf(value, "%d%d%d%d%d", &i1, &i2, &i3, &i4, &i5);
  1760.     return (n > 2 && n < 6);
  1761.  
  1762.       default:
  1763.     /* what to do here? */
  1764.     return (value && value[0]);
  1765.     }
  1766. }
  1767.  
  1768. /* return codes:
  1769.    0 = none
  1770.    1 =   valid display
  1771.    2 =   valid machine player
  1772.   -1 = invalid display 
  1773.   -2 = invalid machine player */
  1774.  
  1775. int
  1776. type_player(value)
  1777. char *value;
  1778. {
  1779.     errormess[0] = '\0';
  1780.     if (!value[0]) {
  1781.     strcpy(errormess, "no player specification");
  1782.     return 0;
  1783.     } else if (strchr(value,':') || !strcmp(value,"here")) {
  1784.     if (can_open_display(value)) {
  1785.         return 1;
  1786.     } else {
  1787.         sprintf(errormess, "cannot open display \"%s\"", value);
  1788.         return -1;
  1789.     }
  1790.     } else {
  1791.     if (strcmp(value,"mplayer")) {
  1792.         sprintf(errormess,
  1793.             "invalid or unkonwn AI \"%s\", try \"mplayer\"", value);
  1794.         return -2;
  1795.     } else {
  1796.         return 2;
  1797.     }
  1798.     }
  1799. }
  1800.  
  1801. void 
  1802. add_player_dialog(w, client_data, call_data)
  1803. Widget w;
  1804. XtPointer client_data;
  1805. XtPointer call_data;
  1806. {
  1807.     int i, oldnumsides = numsides;
  1808.     GamePop *pop = games[chosen_game].pop;
  1809.  
  1810.     if (numsides >= g_sides_max()) {
  1811.     XBell(XtDisplay(pop->shell),50);
  1812.     return;
  1813.     }
  1814.  
  1815.     add_side_and_player();
  1816.  
  1817.     for (i = oldnumsides; i < numsides; ++i) {
  1818.     init_assignw_player(&(pop->assign[i]), assignments[i].player);
  1819.     pop->assign[i].messid =
  1820.       copy_string("enter display name or \"mplayer\"");
  1821.     }
  1822.  
  1823.     verify_dialog(w, NULL, NULL);
  1824. }
  1825.  
  1826. void
  1827. init_assignw_player(assignw, player)
  1828. Assignw *assignw;
  1829. Player *player;
  1830. {
  1831.     assignw->vname = (player->name ? player->name : "");
  1832.     if (player->displayname) {
  1833.     assignw->vid = player->displayname;
  1834.     assignw->vflag = 1;
  1835.     } else if (player->aitypename) {
  1836.     assignw->vid = player->aitypename;
  1837.     assignw->vflag = 2;
  1838.     } else {
  1839.     assignw->vid = "";
  1840.     assignw->vflag = 0;
  1841.     }
  1842. }
  1843.  
  1844. int
  1845. can_open_display(dpyname)
  1846. char *dpyname;
  1847. {
  1848.     Display *dpy;
  1849.  
  1850.     if (dpyname == NULL)
  1851.       return FALSE;
  1852.  
  1853.     if (strcmp("here", dpyname) == 0)
  1854.       dpyname = getenv("DISPLAY");
  1855.  
  1856.     dpy = XOpenDisplay(dpyname);
  1857.     if (dpy) {
  1858.     XCloseDisplay(dpy);
  1859.     return TRUE;
  1860.     } else {
  1861.     return FALSE;
  1862.     }
  1863. }
  1864.