home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / World_Of_Computer_Software-02-385-Vol-1of3.iso / x / xcu16.zip / clients / xcell / Cell.c next >
C/C++ Source or Header  |  1991-10-03  |  57KB  |  2,354 lines

  1. /*
  2.  * Copyright 1991 Cornell University
  3.  *
  4.  * Permission to use, copy, modify, and distribute this software and its
  5.  * documentation for any purpose and without fee is hereby granted, provided
  6.  * that the above copyright notice appear in all copies and that both that
  7.  * copyright notice and this permission notice appear in supporting
  8.  * documentation, and that the name of Cornell U. not be used in advertising
  9.  * or publicity pertaining to distribution of the software without specific,
  10.  * written prior permission.  Cornell U. makes no representations about the
  11.  * suitability of this software for any purpose.  It is provided "as is"
  12.  * without express or implied warranty.
  13.  *
  14.  * CORNELL UNIVERSITY DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
  15.  * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
  16.  * EVENT SHALL CORNELL UNIVERSITY BE LIABLE FOR ANY SPECIAL, INDIRECT OR
  17.  * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
  18.  * USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
  19.  * OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
  20.  * PERFORMANCE OF THIS SOFTWARE.
  21.  *
  22.  * Author:  Gene W. Dykes, Program of Computer Graphics
  23.  *          580 Theory Center, Cornell University, Ithaca, NY 14853
  24.  *          (607) 255-6713   gwd@graphics.cornell.edu
  25.  */
  26.  
  27. /*
  28.  * XcuCell.c - XcuCell widget
  29.  */
  30.  
  31. #define XtStrlen(s)        ((s) ? strlen(s) : 0)
  32. #define IsSensitive(w) ((w)->core.sensitive && (w)->core.ancestor_sensitive)
  33.  
  34. #define    rand2()        (rand() & 1)
  35. #define    rand3()        (rand() % 3)
  36. #define    rand4()        (rand() & 3)
  37. #define    rand5()        (rand() % 5)
  38. #define    rand6()        (rand() % 6)
  39. #define    rand7()        (rand() & 7)
  40.  
  41. #define MAX_COLORS_ALLOWED 8
  42.  
  43. #include <ctype.h>
  44. #include <X11/IntrinsicP.h>
  45. #include <X11/Xos.h>
  46. #include <X11/StringDefs.h>
  47. #include "CellP.h"
  48. #include "CellI.h"
  49. #include <X11/Xcu/SimpleP.h>
  50.  
  51. void Xcu_copy_ds () ;
  52.  
  53. /*
  54.  * Full class record constant
  55.  */
  56.  
  57. /* Private Data */
  58.  
  59. /*
  60.  * XtResource :
  61.  *    name, class, type, size,
  62.  *    offset, default_type, default_address
  63.  *
  64.  * These are the resources needed in addition to core resources
  65.  */
  66.  
  67. #define offset(field) XtOffset(XcuCellWidget, field)
  68.  
  69. static Dimension def_zero = 0 ;
  70. static Boolean def_false = False ;
  71. static Boolean def_true = True ;
  72. static int def_one = 1 ;
  73. static int def_minus1 = -1 ;
  74. static int def_seed = 317317317 ;
  75.  
  76. #ifdef DEFFILE
  77. #undef DEFFILE
  78. #endif
  79. #define DEFFILE "."
  80.  
  81. static XtResource resources[] =
  82.     {
  83.      {XtNcolors, XtCCellColors, XtRString, sizeof(String),
  84.     offset(cell.color_string), XtRString,
  85.     "Black,White,Blue,Green,Red,Yellow,Cyan,Magenta"}
  86.     ,{XtNcolor0, XtCCellColor, XtRString, sizeof(String),
  87.     offset(cell.color0), XtRString, (XPointer) NULL}
  88.     ,{XtNcolor1, XtCCellColor, XtRString, sizeof(String),
  89.     offset(cell.color1), XtRString, (XPointer) NULL}
  90.     ,{XtNcolor2, XtCCellColor, XtRString, sizeof(String),
  91.     offset(cell.color2), XtRString, (XPointer) NULL}
  92.     ,{XtNcolor3, XtCCellColor, XtRString, sizeof(String),
  93.     offset(cell.color3), XtRString, (XPointer) NULL}
  94.     ,{XtNcolor4, XtCCellColor, XtRString, sizeof(String),
  95.     offset(cell.color4), XtRString, (XPointer) NULL}
  96.     ,{XtNcolor5, XtCCellColor, XtRString, sizeof(String),
  97.     offset(cell.color5), XtRString, (XPointer) NULL}
  98.     ,{XtNcolor6, XtCCellColor, XtRString, sizeof(String),
  99.     offset(cell.color6), XtRString, (XPointer) NULL}
  100.     ,{XtNcolor7, XtCCellColor, XtRString, sizeof(String),
  101.     offset(cell.color7), XtRString, (XPointer) NULL}
  102.     ,{XtNdirectory, XtCCellDirectory, XtRString, sizeof(String),
  103.     offset(cell.directory), XtRString, (XPointer) DEFFILE}
  104.     ,{XtNignoreColors, XtCCellIgnoreColors, XtRString, sizeof(String),
  105.     offset(cell.ignore_colors), XtRString, (XPointer)NULL}
  106.     /***
  107.     ,{XtNcolorsFile, XtCCellColorsFile, XtRString, sizeof(String),
  108.     offset(cell.colors_file), XtRString, (XPointer)NULL}
  109.     ***/
  110.     ,{XtNrulesFile, XtCCellRulesFile, XtRString, sizeof(String),
  111.     offset(cell.rules_file), XtRString, (XPointer)""}
  112.     ,{XtNalternating, XtCCellAlternating, XtRBoolean, sizeof(Boolean),
  113.     offset(cell.alternating), XtRBoolean, (XPointer)&def_false}
  114.     ,{XtNperturb, XtCCellPerturb, XtRBoolean, sizeof(Boolean),
  115.     offset(cell.masks_active), XtRBoolean, (XPointer)&def_false}
  116.     ,{XtNpickFile, XtCCellPickFile, XtRString, sizeof(String),
  117.     offset(cell.pick_file), XtRString, (XPointer)""}
  118.     ,{XtNruleIndex, XtCCellRuleIndex, XtRInt, sizeof(int),
  119.     offset(cell.rule_index_), XtRInt, (XPointer)&def_minus1}
  120.     ,{XtNnColors, XtCCellNColors, XtRInt, sizeof(int),
  121.     offset(cell.n_colors), XtRString, (XPointer)"6"}
  122.     ,{XtNseed, XtCCellSeed, XtRInt, sizeof(int),
  123.     offset(cell.seed_), XtRInt, (XPointer)&def_seed}
  124.     ,{XtNcellType, XtCCellType, XtRString, sizeof(String),
  125.     offset(cell.type_), XtRString, (XPointer)"lcr4"}
  126.     ,{XtNperRow, XtCCellPerRow, XtRInt, sizeof(int),
  127.     offset(cell.per_row_), XtRInt, (XPointer)&def_one}
  128.     ,{XtNperCol, XtCCellPerCol, XtRInt, sizeof(int),
  129.     offset(cell.per_col_), XtRInt, (XPointer)&def_one}
  130.     ,{XtNsequence, XtCCellSequence, XtRXcuCellSequence,
  131.     sizeof(XcuCellSequenceType),
  132.     offset(cell.sequence), XtRString, (XPointer)"OrderedPermute"}
  133.     ,{XtNfrequency, XtCCellFrequency, XtRXcuCellFrequency,
  134.     sizeof(XcuCellFrequencyType),
  135.     offset(cell.frequency), XtRString, (XPointer)"Fixed_frequency"}
  136.     ,{XtNorderedRules, XtCCellOrderedRules, XtRBoolean, sizeof(Boolean),
  137.     offset(cell.order_), XtRBoolean, (XPointer)&def_false}
  138.     ,{XtNverticalMerge, XtCCellVerticalMerge, XtRBoolean, sizeof(Boolean),
  139.     offset(cell.vertical_merge_), XtRBoolean, (XPointer)&def_false}
  140.     ,{XtNhorizontalMerge, XtCCellHorizontalMerge, XtRBoolean, sizeof(Boolean),
  141.     offset(cell.horizontal_merge_), XtRBoolean, (XPointer)&def_false}
  142.     ,{XtNinternalWidth, XtCWidth, XtRDimension,  sizeof(Dimension),
  143.     offset(cell.internal_width), XtRDimension, (XPointer)&def_zero}
  144.     ,{XtNinternalHeight, XtCHeight, XtRDimension, sizeof(Dimension),
  145.     offset(cell.internal_height), XtRDimension, (XPointer)&def_zero}
  146.     ,{XtNfacetWidth, XtCFacetWidth, XtRDimension, sizeof(Dimension),
  147.     offset(simple.facet_width), XtRDimension, (XPointer)&def_zero}
  148.     ,{XtNmutate, XtCMutate, XtRBoolean, sizeof(Boolean),
  149.     offset(cell.mutate), XtRBoolean, (XPointer)&def_false}
  150.     ,{XtNbeep, XtCBeep, XtRBoolean, sizeof(Boolean),
  151.     offset(cell.beep), XtRBoolean, (XPointer)&def_true}
  152.     /*** intentionally undocumented ! Probably used only by XcuWlm ***/
  153.     ,{XtNprocedureList, XtCProcedureList,
  154.       XtRProcedureList, sizeof(XtProcedureList *),
  155.       offset(cell.procedure_list), XtRProcedureList, (XPointer)NULL}
  156.     } ;
  157.  
  158. static void Pick () ;
  159.  
  160. static char defaultTranslations[] =
  161.     "<Btn1Down>:    pick()" ;
  162.  
  163. static XtActionsRec actionsList[] =
  164. {
  165.   {"pick",        Pick},
  166. };
  167.  
  168. static void ClassInitialize() ;
  169. static void ClassPartInitialize();
  170. static void Initialize() ;
  171. static void Resize() ;
  172. static void Redisplay() ;
  173. static void Destroy() ;
  174. static Boolean SetValues() ;
  175. static Dimension PreferredWidth() ;
  176. static Dimension PreferredHeight() ;
  177. static XtGeometryResult QueryGeometry() ;
  178. static void GetCellGC () ;
  179. static void GetBackgroundGC () ;
  180. static void XcuCvtStringToColors();
  181. static void XcuCvtWordToColor();
  182. static void XcuConvertStringToWords ();
  183. static void CvtStringToFrequency() ;
  184. static void CvtStringToSequence() ;
  185.  
  186. static void get_rule_type () ;
  187. static void get_save_rule () ;
  188. static void get_order_number () ;
  189. static void get_pick_file () ;
  190. static void get_mod_file () ;
  191. static void get_size_arrays () ;
  192. static void get_seed () ;
  193. static void get_rules () ;
  194. static void get_wraps () ;
  195. static void get_counts () ;
  196. static void get_initial_row () ;
  197. static void get_rule () ;
  198. static void get_ignores () ;
  199. static void get_colors () ;
  200. static void get_permutations () ;
  201. static void get_rcells () ;
  202. static void p_rule () ;
  203. static void put_row () ;
  204. static void do_gets () ;
  205. static void set_changed_false () ;
  206. static void set_changed_true () ;
  207. static void permute_colormap () ;
  208. static long rndm() ;
  209.  
  210. static void permute (/* int, int, int, int*, int**, int *, int * */) ;
  211. static int  **permutations (/* int, int, int *, int * */) ;
  212. static int  n_by_m_perm (/* int, int */) ;
  213. static int  factorial (/* int */) ;
  214.  
  215. extern XrmQuark XcuSimplifyArg () ;
  216.  
  217. #define superclass (&xcuSimpleClassRec)
  218.  
  219. XcuCellClassRec xcuCellClassRec =
  220. {
  221.   {
  222.   /* core_class fields */    
  223.     /* superclass          */    (WidgetClass) &xcuSimpleClassRec,
  224.     /* class_name          */    "Cell",
  225.     /* widget_size          */    sizeof(XcuCellRec),
  226.     /* class_initialize       */    ClassInitialize,
  227.     /* class_part_initialize    */    ClassPartInitialize,
  228.     /* class_inited           */    FALSE,
  229.     /* initialize          */    Initialize,
  230.     /* initialize_hook        */    NULL,
  231.     /* realize              */    XtInheritRealize,
  232.     /* actions              */    actionsList,
  233.     /* num_actions          */    XtNumber(actionsList),
  234.     /* resources          */    resources,
  235.     /* num_resources          */    XtNumber(resources),
  236.     /* xrm_class          */    NULLQUARK,
  237.     /* compress_motion          */    TRUE,
  238.     /* compress_exposure      */    TRUE,
  239.     /* compress_enterleave    */    TRUE,
  240.     /* visible_interest          */    FALSE,
  241.     /* destroy              */    Destroy,
  242.     /* resize              */    Resize,
  243.     /* expose              */    Redisplay,
  244.     /* set_values          */    SetValues,
  245.     /* set_values_hook        */    NULL,
  246.     /* set_values_almost    */    XtInheritSetValuesAlmost,
  247.     /* get_values_hook        */    NULL,
  248.     /* accept_focus         */    NULL,
  249.     /* version            */    XtVersion,
  250.     /* callback_private       */    NULL,
  251.     /* tm_table               */    defaultTranslations,
  252.     /* query_geometry        */    QueryGeometry,
  253.     /* display_accelerator    */    XtInheritDisplayAccelerator,
  254.     /* extension        */    NULL,
  255.   },
  256.   {
  257.     XtInheritChangeSensitive, /* Simple Class fields */
  258.     XtInheritDrawFacets,
  259.     XtInheritDrawHighlight
  260.   },
  261.   {
  262.     NULL,                        /* XcuCell Class fields  */
  263.   },
  264. } ;
  265.  
  266. /* For use by clients... */
  267. WidgetClass xcuCellWidgetClass = (WidgetClass) &xcuCellClassRec ;
  268.  
  269. /**
  270.  ***
  271.  **** Toolkit Procedures
  272.  ***
  273.  **/
  274.  
  275. /***** **** *** ** * ClassInitialize * ** *** **** *****/
  276.  
  277. static XrmQuark    XrmQEfixed, XrmQEpage, XrmQErule, XrmQEline ;
  278. static XrmQuark    XrmQEordered, XrmQErandomp, XrmQErandomc ;
  279.  
  280. static void
  281. ClassInitialize()
  282. {
  283. XrmQEfixed   = XrmStringToQuark("fixedfrequency") ;
  284. XrmQEpage = XrmStringToQuark("pagefrequency") ;
  285. XrmQErule  = XrmStringToQuark("rulefrequency") ;
  286. XrmQEline  = XrmStringToQuark("linefrequency") ;
  287. XtAddConverter( XtRString, XtRXcuCellFrequency, CvtStringToFrequency,
  288.         NULL, 0 ) ;
  289. XrmQEordered   = XrmStringToQuark("orderedpermute") ;
  290. XrmQErandomp = XrmStringToQuark("randompermute") ;
  291. XrmQErandomc  = XrmStringToQuark("randomcolor") ;
  292. XtAddConverter( XtRString, XtRXcuCellSequence, CvtStringToSequence,
  293.         NULL, 0 ) ;
  294. return ;
  295. }
  296.  
  297. /***** **** *** ** * ClassPartInitialize * ** *** **** *****/
  298.  
  299. static void
  300. ClassPartInitialize(class)
  301.     WidgetClass class;
  302. {
  303. #ifdef XXX
  304. register XcuCellWidgetClass c = (XcuCellWidgetClass)class;
  305.  
  306. /*****
  307. if (c->cell_class.redisplay_text == XtInheritRedisplayText)
  308.     c->cell_class.redisplay_text = RedisplayText;
  309. *****/
  310.  
  311. #endif
  312. return ;
  313. }
  314.  
  315. /***** **** *** ** * Initialize * ** *** **** *****/
  316.  
  317. static void
  318. Initialize (request, new)
  319.     Widget request, new ;
  320. {
  321. XcuCellWidget lw = (XcuCellWidget) new ;
  322. Dimension facet_add = (lw->simple.shadow ? 1 : 2) * lw->simple.facet_width ;
  323.  
  324. static String XcuCellNextText = "XcuCellNextMap" ;
  325. static String XcuCellFirstText = "XcuCellFirstMap" ;
  326.  
  327. lw->cell.procedure_list = (XtProcedureList *)
  328.                XtMalloc (3 * sizeof (XtProcedureList)) ;
  329. lw->cell.procedure_list[0].name = XcuCellNextText ;
  330. lw->cell.procedure_list[0].procedure = XcuCellNextMap ;
  331. lw->cell.procedure_list[1].name = XcuCellFirstText ;
  332. lw->cell.procedure_list[1].procedure = XcuCellFirstMap ;
  333. lw->cell.procedure_list[2].name = NULL ;
  334. lw->cell.procedure_list[2].procedure = NULL ;
  335.  
  336.  
  337. if (lw->cell.rules_file) Xcu_copy_ds(&lw->cell.rules_file, lw->cell.rules_file);
  338. if (lw->cell.pick_file) Xcu_copy_ds(&lw->cell.pick_file, lw->cell.pick_file);
  339. if (lw->cell.directory) Xcu_copy_ds(&lw->cell.directory, lw->cell.directory);
  340.  
  341. XcuCvtStringToColors (lw) ;
  342.  
  343. GetCellGC (lw) ;
  344.  
  345. if (lw->simple.shadow)
  346.     GetBackgroundGC (lw, lw->simple.background_pixel) ;
  347. else
  348.     GetBackgroundGC (lw, lw->core.background_pixel) ;
  349.  
  350. lw->simple.exposing = True ;
  351.  
  352. if (lw->core.width == 0)
  353.     {
  354.     if (lw->core.height == 0)
  355.     lw->core.width = lw->core.height = 256 ;
  356.     else
  357.     lw->core.width = lw->core.height ;
  358.     }
  359.  
  360. if (lw->core.height == 0)
  361.     lw->core.height = lw->core.width ;
  362.  
  363. lw->cell.width = lw->core.width - 2*lw->cell.internal_width - facet_add ;
  364. lw->cell.height = lw->core.height - 2*lw->cell.internal_height - facet_add ;
  365.  
  366. lw->cell.image = XCreateImage
  367.     (
  368.     XtDisplay(new),
  369.     XDefaultVisualOfScreen(XtScreen(new)),
  370.     XDefaultDepthOfScreen(XtScreen(new)),
  371.     ZPixmap,
  372.     0,
  373.     (char *) NULL,
  374.     lw->cell.width,
  375.     1,
  376.     8,
  377.     0
  378.     );
  379.  
  380.  
  381. save_rule = (int ***) NULL ;
  382. asave_rule = (int ***) NULL ;
  383. irule = (int *) NULL ;
  384. arule = (int *) NULL ;
  385. fpick = (FILE *) NULL ;
  386. mask = (int **) NULL ;
  387. rule = (int **) NULL ;
  388. lw->cell.image->data = NULL ;
  389. row0 = NULL ;
  390. row1 = NULL ;
  391. lw->cell.first_initial_row = True ;
  392. mask_iter = 0 ;
  393. row = 0 ;
  394. lw->cell.ignore_count = 0 ;
  395. lw->cell.ignore_array = NULL ;
  396. lw->cell.is_exposed = False ;
  397. lw->cell.cells = NULL ;
  398. lw->cell.rcells = NULL ;
  399. lw->cell.permute_array = NULL ;
  400. lw->cell.permutation_index = -1 ;
  401.  
  402. set_changed_true (lw) ;
  403. lw->cell.mod_changed = lw->cell.masks_active ;
  404. lw->cell.alt_changed = lw->cell.alternating ;
  405. do_gets (lw) ;
  406.  
  407. (*XtClass(new)->core_class.resize) (new) ;
  408.  
  409. return ;
  410. }
  411.  
  412. /***** **** *** ** * Resize * ** *** **** *****/
  413.  
  414. static void
  415. Resize (w)
  416.     Widget w ;
  417. {
  418. XcuCellWidget lw = (XcuCellWidget) w ;
  419. Dimension facet_add = (lw->simple.shadow ? 1 : 2) * lw->simple.facet_width ;
  420.  
  421. lw->cell.width = lw->core.width - facet_add - 2 * lw->cell.internal_width ;
  422. lw->cell.height = lw->core.height - facet_add - 2 * lw->cell.internal_height ;
  423. lw->cell.width &= (~3) ;
  424. lw->cell.internal_width = (lw->core.width - lw->cell.width - facet_add) / 2 ;
  425. lw->cell.internal_height = (lw->core.height - lw->cell.height - facet_add)/2 ;
  426.  
  427. lw->cell.width_changed = True ;
  428. lw->cell.height_changed = True ;
  429. do_gets (lw) ;
  430.  
  431. /* for invocation of callbacks */
  432. (*superclass->core_class.resize)( w ) ;
  433.  
  434. return ;
  435. }
  436.  
  437. /***** **** *** ** * SetValues * ** *** **** *****/
  438.  
  439. /*
  440.  * Set specified arguments into widget
  441.  */
  442.  
  443. /* ARGSUSED */
  444. static Boolean
  445. SetValues (current, request, new)
  446.     Widget current, request, new ;
  447. {
  448. XcuCellWidget curlw = (XcuCellWidget) current ;
  449. XcuCellWidget newlw = (XcuCellWidget) new ;
  450. Boolean need_to_redisplay = False ;
  451. Boolean was_resized = False ;
  452.  
  453. if (curlw->cell.color0 != newlw->cell.color0)
  454.     {
  455.     Xcu_copy_ds (&newlw->cell.color0, newlw->cell.color0) ;
  456.     XcuCvtWordToColor (newlw, newlw->cell.color0, newlw->cell.colors, 0) ;
  457.     newlw->cell.colors_changed = True ;
  458.     }
  459.  
  460. if (curlw->cell.color1 != newlw->cell.color1)
  461.     {
  462.     Xcu_copy_ds (&newlw->cell.color1, newlw->cell.color1) ;
  463.     XcuCvtWordToColor (newlw, newlw->cell.color1, newlw->cell.colors, 1) ;
  464.     newlw->cell.colors_changed = True ;
  465.     }
  466.  
  467. if (curlw->cell.color2 != newlw->cell.color2)
  468.     {
  469.     Xcu_copy_ds (&newlw->cell.color2, newlw->cell.color2) ;
  470.     XcuCvtWordToColor (newlw, newlw->cell.color2, newlw->cell.colors, 2) ;
  471.     newlw->cell.colors_changed = True ;
  472.     }
  473.  
  474. if (curlw->cell.color3 != newlw->cell.color3)
  475.     {
  476.     Xcu_copy_ds (&newlw->cell.color3, newlw->cell.color3) ;
  477.     XcuCvtWordToColor (newlw, newlw->cell.color3, newlw->cell.colors, 3) ;
  478.     newlw->cell.colors_changed = True ;
  479.     }
  480.  
  481. if (curlw->cell.color4 != newlw->cell.color4)
  482.     {
  483.     Xcu_copy_ds (&newlw->cell.color4, newlw->cell.color4) ;
  484.     XcuCvtWordToColor (newlw, newlw->cell.color4, newlw->cell.colors, 4) ;
  485.     newlw->cell.colors_changed = True ;
  486.     }
  487.  
  488. if (curlw->cell.color5 != newlw->cell.color5)
  489.     {
  490.     Xcu_copy_ds (&newlw->cell.color5, newlw->cell.color5) ;
  491.     XcuCvtWordToColor (newlw, newlw->cell.color5, newlw->cell.colors, 5) ;
  492.     newlw->cell.colors_changed = True ;
  493.     }
  494.  
  495. if (curlw->cell.color6 != newlw->cell.color6)
  496.     {
  497.     Xcu_copy_ds (&newlw->cell.color6, newlw->cell.color6) ;
  498.     XcuCvtWordToColor (newlw, newlw->cell.color6, newlw->cell.colors, 6) ;
  499.     newlw->cell.colors_changed = True ;
  500.     }
  501.  
  502. if (curlw->cell.color7 != newlw->cell.color7)
  503.     {
  504.     Xcu_copy_ds (&newlw->cell.color7, newlw->cell.color7) ;
  505.     XcuCvtWordToColor (newlw, newlw->cell.color7, newlw->cell.colors, 7) ;
  506.     newlw->cell.colors_changed = True ;
  507.     }
  508.  
  509. if (curlw->cell.rules_file != newlw->cell.rules_file)
  510.     {
  511.     Xcu_copy_ds (&newlw->cell.rules_file, newlw->cell.rules_file) ;
  512.     newlw->cell.rules_changed = True ;
  513.     }
  514.  
  515. if (curlw->cell.ignore_colors != newlw->cell.ignore_colors)
  516.     {
  517.     Xcu_copy_ds (&newlw->cell.ignore_colors, newlw->cell.ignore_colors) ;
  518.     newlw->cell.ignore_colors_changed = True ;
  519.     }
  520.  
  521. if (curlw->cell.directory != newlw->cell.directory)
  522.     {
  523.     Xcu_copy_ds (&newlw->cell.directory, newlw->cell.directory) ;
  524.     }
  525.  
  526. if (curlw->cell.masks_active != newlw->cell.masks_active)
  527.     {
  528.     if (newlw->cell.masks_active && newlw->cell.all_random_)
  529.     {
  530.     fprintf (stderr,
  531.          "Warning. Perturbation of random automatoms not allowed.\n") ;
  532.     newlw->cell.masks_active = False ;
  533.     }
  534.     else
  535.     {
  536.     newlw->cell.mod_changed = True ;
  537.     }
  538.     }
  539.  
  540. if (curlw->cell.pick_file != newlw->cell.pick_file)
  541.     {
  542.     Xcu_copy_ds (&newlw->cell.pick_file, newlw->cell.pick_file) ;
  543.     newlw->cell.pick_changed = True ;
  544.     }
  545.  
  546. if (curlw->cell.rule_index_ != newlw->cell.rule_index_)
  547.     {
  548.     newlw->cell.rrule_changed = True ;
  549.     }
  550.  
  551. if (curlw->cell.seed_ != newlw->cell.seed_)
  552.     {
  553.     newlw->cell.seed_changed = True ;
  554.     }
  555.  
  556. if (newlw->cell.type_ &&
  557.     (!curlw->cell.type_ || strcmp(newlw->cell.type_, curlw->cell.type_) != 0))
  558.     {
  559.     newlw->cell.type_changed = True ;
  560.     }
  561.  
  562. if (curlw->cell.per_row_ != newlw->cell.per_row_)
  563.     {
  564.     newlw->cell.hmany_changed = True ;
  565.     }
  566.  
  567. if (curlw->cell.per_col_ != newlw->cell.per_col_)
  568.     {
  569.     newlw->cell.many_changed = True ;
  570.     }
  571.  
  572. if (curlw->cell.horizontal_merge_ != newlw->cell.horizontal_merge_)
  573.     {
  574.     newlw->cell.hmerge_changed = True ;
  575.     }
  576.  
  577. if (curlw->cell.colors != newlw->cell.colors)
  578.     {
  579.     newlw->cell.colors_changed = True ;
  580.     }
  581.  
  582. if (curlw->cell.n_colors != newlw->cell.n_colors)
  583.     {
  584.     newlw->cell.n_colors_changed = True ;
  585.     }
  586.  
  587. if (curlw->cell.alternating != newlw->cell.alternating)
  588.     {
  589.     newlw->cell.alt_changed = True ;
  590.     }
  591.  
  592. if (
  593.    was_resized
  594.    || curlw->simple.facet_width != newlw->simple.facet_width
  595.    || curlw->cell.internal_width != newlw->cell.internal_width
  596.    || curlw->cell.internal_height != newlw->cell.internal_height
  597.    )
  598.     {
  599.     (*XtClass(newlw)->core_class.resize) (new) ;
  600.     need_to_redisplay = True ;
  601.     }
  602. else
  603.     {
  604.     do_gets (newlw) ;
  605.     }
  606.  
  607. if (curlw->core.background_pixel != newlw->core.background_pixel)
  608.     {
  609.     if (newlw->simple.shadow)
  610.     GetBackgroundGC (newlw, newlw->simple.background_pixel) ;
  611.     else
  612.     GetBackgroundGC (newlw, newlw->core.background_pixel) ;
  613.     need_to_redisplay = True ;
  614.     }
  615.  
  616. if (newlw->cell.frequency != curlw->cell.frequency)
  617.     {
  618.     if (newlw->cell.frequency == XcuPAGE_FREQUENCY)
  619.     {
  620.     newlw->cell.permutation_index++ ;
  621.     if (newlw->cell.permutation_index == newlw->cell.n_permutations)
  622.         newlw->cell.permutation_index = 0 ;
  623.     }
  624.     }
  625. return need_to_redisplay ;
  626. }
  627.  
  628. /***** **** *** ** * QueryGeometry * ** *** **** *****/
  629.  
  630. static XtGeometryResult
  631. QueryGeometry (widget, requested, preferred)
  632.     Widget widget ;
  633.     XtWidgetGeometry *requested ;
  634.     XtWidgetGeometry *preferred ;
  635. {
  636. /*
  637.  * Examine bits in requested->request_mode
  638.  * Evaluate preferred geometry of the widget
  639.  * Store the result in preferred, setting bits cared about in request_mode
  640.  *  (CWX, CWY,  CWWidth, CWHeight,  CWBorderWidth,  CWSibling,  CWStackMode)
  641.  *
  642.  * acceptable without modification                XtGeometryYes
  643.  *
  644.  * one field in requested != one field in preferred ||
  645.  * one bit set in preferred that is not set in requested    XtGeometryAlmost
  646.  *
  647.  * if preferred == current                    XtGeometryNo
  648.  */
  649.  
  650. XtGeometryResult return_mode ;
  651. XcuCellWidget lw = (XcuCellWidget) widget ;
  652.  
  653. preferred->width = PreferredWidth (lw) ;
  654. preferred->height = PreferredHeight (lw); 
  655. preferred->request_mode = (CWWidth | CWHeight) ;
  656.  
  657. if ((requested->request_mode & (CWWidth | CWHeight)) == 0)
  658.     {
  659.     /* parent isn't interested in anything we're interested in */
  660.     return XtGeometryNo ;
  661.     }
  662.  
  663. if (
  664.     (
  665.      ((requested->request_mode & CWWidth) != 0 &&
  666.       preferred->width == requested->width)
  667.             ||
  668.      ((requested->request_mode & CWWidth) == 0)
  669.     )
  670.             &&
  671.     (
  672.      ((requested->request_mode & CWHeight) != 0 &&
  673.       preferred->height == requested->height)
  674.             ||
  675.      ((requested->request_mode & CWHeight) == 0)
  676.     )
  677.    )
  678.     {
  679.     /* Our values already identical to those the parent is interested in */
  680.     return XtGeometryNo ;
  681.     }
  682.  
  683. /*
  684.  * That takes care of the simple cases, now we have to take a closer look...
  685.  * I don't mind getting bigger than the smallest possible size.
  686.  */
  687.  
  688. return_mode = XtGeometryYes ;
  689.  
  690. if (
  691.     (requested->request_mode & CWHeight) &&
  692.     (requested->height < preferred->height)
  693.    )
  694.     {
  695.     return_mode = XtGeometryAlmost ;
  696.     }
  697. if (
  698.     (requested->request_mode & CWWidth) &&
  699.     (requested->width < preferred->width)
  700.    )
  701.     {
  702.     return_mode = XtGeometryAlmost ;
  703.     }
  704.  
  705. return return_mode ;
  706. }
  707.  
  708. /***** **** *** ** * Destroy * ** *** **** *****/
  709.  
  710. static void
  711. Destroy (widget)
  712.     Widget widget ;
  713. {
  714. /*
  715.  * free dynamically allocated data
  716.  */
  717.  
  718. if (!XtIsRealized (widget))
  719.     return ;
  720.  
  721. return ;
  722. }
  723.  
  724. /***** **** *** ** * Redisplay * ** *** **** *****/
  725.  
  726. static void Redisplay(w, event, region)
  727.     Widget w;
  728.     XEvent *event;        /* unused */
  729.     Region region;        /* unused */
  730. {
  731. XcuCellWidget lw = (XcuCellWidget) w;
  732.  
  733. /*
  734.  * Repaint the background if need be
  735.  * Redisplay the text
  736.  * Allow superclass to handle facets and highlights
  737.  */
  738.  
  739. lw->cell.is_exposed = True ;
  740. (*superclass->core_class.expose)( w, event, region ) ;
  741.  
  742.     if (lw->simple.shadow)
  743.         {
  744.         XFillRectangle(XtDisplay(w),XtWindow(w), lw->cell.background_GC,
  745.             0, 0,
  746.             lw->core.width - lw->simple.facet_width,
  747.             lw->core.height - lw->simple.facet_width);
  748.         }
  749.     else
  750.         {
  751.         XFillRectangle(XtDisplay(w),XtWindow(w), lw->cell.background_GC,
  752.             lw->simple.facet_width, lw->simple.facet_width,
  753.             lw->core.width - 2*lw->simple.facet_width,
  754.             lw->core.height - 2*lw->simple.facet_width);
  755.         }
  756.  
  757. return ;
  758. }
  759.  
  760. /**
  761.  ***
  762.  **** Private Procedures
  763.  ***
  764.  **/
  765.  
  766.  
  767. /***** **** *** ** * GetBackgroundGC * ** *** **** *****/
  768.  
  769. static void
  770. GetBackgroundGC (lw, background_color)
  771.     XcuCellWidget lw ;
  772.     Pixel background_color ;
  773. {
  774. XGCValues    values ;
  775.  
  776. values.foreground    = background_color ;
  777.  
  778. lw->cell.background_GC = XtGetGC(
  779.     (Widget)lw,
  780.     (unsigned) GCForeground,
  781.     &values) ;
  782. return ;
  783. }
  784.  
  785. /***** **** *** ** * GetCellGC * ** *** **** *****/
  786.  
  787. static void
  788. GetCellGC (lw)
  789.     XcuCellWidget lw ;
  790. {
  791. XGCValues    values ;
  792.  
  793.  
  794. values.function    = GXcopy ;
  795. lw->cell.cell_GC = XtGetGC(
  796.     (Widget)lw,
  797.     (unsigned) GCFunction,
  798.     &values) ;
  799. return ;
  800. }
  801.  
  802.  
  803. static Dimension
  804. PreferredHeight (lw)
  805.     XcuCellWidget lw ;
  806. {
  807. Dimension facet_add = (lw->simple.shadow ? 1 : 2) * lw->simple.facet_width ;
  808. Dimension smallest_height = lw->cell.height +
  809.              2*lw->cell.internal_height +
  810.              facet_add ;
  811.  
  812. return smallest_height ;
  813. }
  814.  
  815. static Dimension
  816. PreferredWidth (lw)
  817.     XcuCellWidget lw ;
  818. {
  819. Dimension facet_add = (lw->simple.shadow ? 1 : 2) * lw->simple.facet_width ;
  820. Dimension smallest_width = lw->cell.width +
  821.              2*lw->cell.internal_width +
  822.              facet_add ;
  823. return smallest_width ;
  824. }
  825.  
  826. /*
  827.  * Convert String To Colors
  828.  */
  829.  
  830. static void
  831. XcuCvtStringToColors(lw)
  832.     XcuCellWidget lw ;
  833. {
  834. Cardinal    i ;
  835. String        *words ;
  836. Display        *display = XtDisplay(lw) ;
  837. XColor        visual_def_return ;
  838.  
  839. if (lw->cell.color_string == NULL) return ;
  840.  
  841. XcuConvertStringToWords (lw->cell.color_string, &words, &lw->cell.n_colors) ;
  842.  
  843. lw->cell.colors = (XColor *) XtMalloc (lw->cell.n_colors * sizeof(XColor)) ;
  844.  
  845. for (i=0;  i < lw->cell.n_colors;  i++)
  846.     {
  847.     if (XLookupColor(display,
  848.              DefaultColormap(display,DefaultScreen(display)),
  849.              words[i], &visual_def_return, &lw->cell.colors[i])
  850.     == True)
  851.     {
  852.     }
  853.     else
  854.     {
  855.     fprintf (stderr, "Error converting (%s) to Pixel\n", words[i]) ;
  856.     fprintf (stderr, "Setting it to Black\n") ;
  857.     lw->cell.colors[i].pixel = BlackPixel(display,DefaultScreen(display)) ;
  858.     lw->cell.colors[i].red = 0 ;
  859.     lw->cell.colors[i].green = 0 ;
  860.     lw->cell.colors[i].blue = 0 ;
  861.     }
  862.     }
  863.  
  864. return ;
  865. }
  866.  
  867. static void
  868. XcuCvtWordToColor(cw, word, colors, index)
  869.     XcuCellWidget cw ;
  870.     String word ;
  871.     XColor *colors ;
  872.     int index ;
  873. {
  874. Display *display = XtDisplay(cw) ;
  875. XColor visual_def_return ;
  876.  
  877. if (word == NULL) return ;
  878. if (index >= cw->cell.max_colors) return ;
  879.  
  880.     if (XLookupColor(display,
  881.              DefaultColormap(display,DefaultScreen(display)),
  882.              word, &visual_def_return, &colors[index])
  883.     == True)
  884.     {
  885.     cw->cell.cells[index] = colors[index].pixel ;
  886.     if (index < cw->cell.max_rw_cells)
  887.         {
  888.         XStoreColor  (XtDisplay(cw),
  889.           DefaultColormap(XtDisplay(cw),DefaultScreen(XtDisplay(cw))),
  890.           &colors[index]) ;
  891.         }
  892.     else
  893.         {
  894.         int h ;
  895.         h=XFreeColors (XtDisplay(cw),
  896.           DefaultColormap(XtDisplay(cw),DefaultScreen(XtDisplay(cw))),
  897.           &cw->cell.cells[index], 1, NULL) ;
  898.         h=XAllocColor (XtDisplay(cw),
  899.           DefaultColormap(XtDisplay(cw),DefaultScreen(XtDisplay(cw))),
  900.           &colors[index]) ;
  901.         cw->cell.cells[index] = colors[index].pixel ;
  902.         for (h=0;  h < cw->cell.per_row_;  h++)
  903.         {
  904.         if (index < cw->cell.reduct_)
  905.             cw->cell.rcells[h][index] = cw->cell.cells[index] ;
  906.         }
  907.         }
  908.     }
  909.     else
  910.     {
  911.     fprintf (stderr, "Error converting (%s) to Pixel\n", word) ;
  912.     fprintf (stderr, "Leaving it unchanged\n") ;
  913.     }
  914.  
  915. return ;
  916. }
  917.  
  918. static void
  919. XcuConvertStringToWords (s, words, n_words)
  920.     String s ;
  921.     String **words ;
  922.     int *n_words ;
  923. {
  924. int n_commas = 0 ;
  925. int i ;
  926. String p ;
  927.  
  928. /*
  929.  * First, find the number of words in the string.
  930.  * It is the number of commas, plus one.
  931.  */
  932. for (p=s;  *p;  p++)
  933.     {
  934.     if (*p == ',')
  935.     n_commas++ ;
  936.     }
  937.  
  938. *n_words = n_commas + 1 ;
  939. *words = (String *) XtMalloc (*n_words * sizeof (String)) ;
  940.  
  941. /*
  942.  * Copy each word into the output array
  943.  */
  944.  
  945. for (i=0;  i < *n_words;  i++)
  946.     {
  947.     char *comma = strchr (s, ',') ;
  948.     if (comma) *comma = '\0' ;
  949.     (*words)[i] = (String) XtMalloc (strlen(s) + 1) ;
  950.     strcpy ((*words)[i], s) ;
  951.     if (!comma)
  952.     break ;
  953.     s = comma + 1 ;
  954.     }
  955. return ;
  956. }
  957.  
  958. static void
  959. get_rule_type (lw)
  960.     XcuCellWidget lw ;
  961. {
  962.      if (strcmp(lw->cell.type_, "klcrt3") == 0)
  963.     { mix = KLCRT3 ; spread = 11 ; reduct = 3 ; windo = 5 ; }
  964. else if (strcmp(lw->cell.type_, "klcrt4") == 0)
  965.     { mix = KLCRT4 ; spread = 16 ; reduct = 4 ; windo = 5 ; }
  966. else if (strcmp(lw->cell.type_, "klcrt5") == 0)
  967.     { mix = KLCRT5 ; spread = 21 ; reduct = 5 ; windo = 5 ; }
  968. else if (strcmp(lw->cell.type_, "lccrrr4") == 0)
  969.     { mix = LCCRRR4 ; spread = 19 ; reduct = 4 ; windo = 3 ; }
  970. else if (strcmp(lw->cell.type_, "lccr4") == 0)
  971.     { mix = LCCR4 ; spread = 16 ; reduct = 4 ; windo = 3 ; }
  972. else if (strcmp(lw->cell.type_, "lcr3") == 0)
  973.     { mix = LCR3 ; spread = 7 ; reduct = 3 ; windo = 3 ; }
  974. else if (strcmp(lw->cell.type_, "lcr4") == 0)
  975.     { mix = LCR4 ; spread = 10 ; reduct = 4 ; windo = 3 ; }
  976. else if (strcmp(lw->cell.type_, "lcr5") == 0)
  977.     { mix = LCR5 ; spread = 13 ; reduct = 5 ; windo = 3 ; }
  978. else if (strcmp(lw->cell.type_, "lcr6") == 0)
  979.     { mix = LCR6 ; spread = 16 ; reduct = 6 ; windo = 3 ; }
  980. else
  981.     {
  982.     fprintf (stderr, "Unknown rule: (%s)\n", lw->cell.type_) ;
  983.     exit (1) ;
  984.     }
  985. get_mod_file (lw) ;
  986. return ;
  987. }
  988.  
  989. static void
  990. get_save_rule (lw)
  991.     XcuCellWidget lw ;
  992. {
  993. int is, it ;
  994.  
  995. if (save_rule)
  996.     {
  997.     for (is=0;  is < lw->cell.old_many_per_page;  is++)
  998.     {
  999.     for (it=0;  it < lw->cell.old_hmany_per_page;  it++)
  1000.         {
  1001.         XtFree (save_rule[is][it]) ;
  1002.         XtFree (asave_rule[is][it]) ;
  1003.         }
  1004.     XtFree (save_rule[is]) ;
  1005.     XtFree (asave_rule[is]) ;
  1006.     }
  1007.     XtFree (save_rule) ;
  1008.     XtFree (asave_rule) ;
  1009.     XtFree (irule) ;
  1010.     XtFree (arule) ;
  1011.     XtFree (lw->cell.mutation) ;
  1012.     }
  1013.  
  1014. save_rule = (int ***) XtMalloc (many_per_page * sizeof (int **)) ;
  1015. asave_rule = (int ***) XtMalloc (many_per_page * sizeof (int **)) ;
  1016. for (is=0;  is < many_per_page;  is++)
  1017.     {
  1018.     save_rule[is] = (int **) XtMalloc (hmany_per_page * sizeof (int *)) ;
  1019.     asave_rule[is] = (int **) XtMalloc (hmany_per_page * sizeof (int *)) ;
  1020.     for (it=0;  it < hmany_per_page;  it++)
  1021.     {
  1022.     save_rule[is][it] = (int *) XtMalloc (spread * sizeof (int)) ;
  1023.     asave_rule[is][it] = (int *) XtMalloc (spread * sizeof (int)) ;
  1024.     }
  1025.     }
  1026.  
  1027. irule = (int *) XtMalloc (hmany_per_page * sizeof (int)) ;
  1028. arule = (int *) XtMalloc (hmany_per_page * sizeof (int)) ;
  1029. for (it=0;  it < hmany_per_page;  it++)
  1030.     {
  1031.     irule[it] = -1 ;
  1032.     arule[it] = -1 ;
  1033.     }
  1034.  
  1035. lw->cell.mutation = (int *) XtCalloc (spread, sizeof (int)) ;
  1036. lw->cell.old_many_per_page = many_per_page ;
  1037. lw->cell.old_hmany_per_page = hmany_per_page ;
  1038.  
  1039. return ;
  1040. }
  1041.  
  1042. static void
  1043. get_order_number (lw)
  1044.     XcuCellWidget lw ;
  1045. {
  1046. if (rrule == -1)
  1047.     order_number = -1 ; /* NOP ? */
  1048. else
  1049. if (rrule == 0)
  1050.     order_number = -1 ;
  1051. else
  1052.     order_number = rrule - 2 ;
  1053.  
  1054. return ;
  1055. }
  1056.  
  1057. static void
  1058. get_pick_file (lw)
  1059.     XcuCellWidget lw ;
  1060. {
  1061. if (fpick)
  1062.     fclose (fpick) ;
  1063.  
  1064. if (*lw->cell.pick_file == '/' || *lw->cell.pick_file == '.')
  1065.     fpick = fopen (lw->cell.pick_file, "a") ;
  1066. else
  1067.     {
  1068.     char temp[200] ;
  1069.     sprintf (temp, "%s/%s", lw->cell.directory, lw->cell.pick_file) ;
  1070.     fpick = fopen (temp, "a") ;
  1071.     }
  1072.  
  1073. return ;
  1074. }
  1075.  
  1076. static void
  1077. get_mod_file (lw)
  1078.     XcuCellWidget lw ;
  1079. {
  1080. int i, sp ;
  1081. FILE *fd ;
  1082. char temp[100] ;
  1083.  
  1084. sprintf (temp, "%s/Mods/%d_%d", lw->cell.directory, reduct, spread) ;
  1085. fd = fopen (temp, "r") ;
  1086. if (fd == 0)
  1087.     {
  1088.     fprintf (stderr, "Trouble Opening Mod File (%s)\n", temp) ;
  1089.     exit (1) ;
  1090.     }
  1091.  
  1092. if (mask)
  1093.     {
  1094.     for (i=0;  i < masks;  i++)
  1095.     XtFree (mask[i]) ;
  1096.     XtFree (mask) ;
  1097.     }
  1098.  
  1099. fscanf (fd, "%d%d%d", &masks, &lw->cell.mod_hmany_per_page,
  1100.                   &lw->cell.mod_many_per_page) ;
  1101. mask = (int **) XtMalloc (masks * sizeof (int *)) ;
  1102. for (i=0;  i < masks;  i++)
  1103.     {
  1104.     mask[i] = (int *) XtMalloc (spread * sizeof (int)) ;
  1105.     for (sp=0;  sp < spread;  sp++)
  1106.         {
  1107.         int num = fscanf (fd, "%d", &mask[i][sp]) ;
  1108.         if (num < 1)
  1109.             break ;
  1110.         }
  1111.     if (sp < spread)
  1112.         break ;
  1113.     }
  1114. if (i < masks)
  1115.     {
  1116.     fprintf (stderr, "Insufficient mask data found\n") ;
  1117.     exit (1) ;
  1118.     }
  1119. fclose (fd) ;
  1120. return ;
  1121. }
  1122.  
  1123. static void
  1124. get_seed (lw)
  1125.     XcuCellWidget lw ;
  1126. {
  1127. if (lw->cell.seed_ != 317317317)
  1128.     srand (lw->cell.seed_) ;
  1129. else
  1130.     {
  1131.     struct timeval tp_, *tp = &tp_ ;
  1132.     struct timezone tzp_, *tzp = &tzp_ ;
  1133.     gettimeofday (tp, tzp) ;
  1134.     srand (tp->tv_sec) ;
  1135.     }
  1136. return ;
  1137. }
  1138.  
  1139. static void
  1140. get_rules (lw)
  1141.     XcuCellWidget lw ;
  1142. {
  1143. FILE *fd ;
  1144. int i, sp ;
  1145.  
  1146. if (rule && lw->cell.rules_file)
  1147.     {
  1148.     for (i=0;  i < lw->cell.rule_count;  i++)
  1149.     XtFree (rule[i]) ;
  1150.     XtFree (rule) ;
  1151.     }
  1152.  
  1153. if (lw->cell.rules_file &&
  1154.     *lw->cell.rules_file &&
  1155.     strcmp(lw->cell.rules_file, "random"))
  1156.     {
  1157.     char temp[200] ;
  1158.     fd = fopen (lw->cell.rules_file, "r") ;
  1159.     if (!fd)
  1160.     {
  1161.     if (*lw->cell.rules_file != '.' &&
  1162.         *lw->cell.rules_file != '/')
  1163.         {
  1164.         sprintf (temp, "%s/%s", lw->cell.directory, lw->cell.rules_file) ;
  1165.         }
  1166.  
  1167.     fd = fopen (temp, "r") ;
  1168.     if (!fd)
  1169.         {
  1170.         fprintf (stderr, "Trouble opening rule file: (%s)\n",
  1171.              lw->cell.rules_file) ;
  1172.         exit (1) ;
  1173.         }
  1174.     }
  1175.     /*
  1176.      * Once through the file to find the number of rules...
  1177.      */
  1178.  
  1179.     for (nrule=0; ; )
  1180.     {
  1181.     for (sp=0;  sp < spread;  sp++)
  1182.         {
  1183.         int dummy ;
  1184.         int num = fscanf (fd, "%d", &dummy) ;
  1185.         if (num < 1)
  1186.             break ;
  1187.         }
  1188.     if (sp < spread)
  1189.         break ;
  1190.     nrule++ ;
  1191.     }
  1192.  
  1193.     lw->cell.rule_count = nrule + (lw->cell.masks_active ? hmany_per_page : 0);
  1194.     rule = (int **) XtMalloc (lw->cell.rule_count * sizeof (int *)) ;
  1195.     fseek (fd, 0l, 0) ;
  1196.  
  1197.     for (i=0; i < nrule;  i++)
  1198.     {
  1199.     rule[i] = (int *) XtMalloc (spread * sizeof (int)) ;
  1200.     for (sp=0;  sp < spread;  sp++)
  1201.         {
  1202.         fscanf (fd, "%d", &rule[i][sp]) ;
  1203.         }
  1204.     }
  1205.     if (lw->cell.masks_active)
  1206.     {
  1207.     int h ;
  1208.     for (h=0;  h < hmany_per_page;  h++)
  1209.         {
  1210.         rule[nrule+h] = (int *) XtMalloc (spread * sizeof (int)) ;
  1211.         }
  1212.     }
  1213.  
  1214.     allrandom = False ;
  1215.     }
  1216. else
  1217. if (lw->cell.rules_file)
  1218.     {
  1219.     /* Null String implies random rules (also "random") */
  1220.     rule = (int **) XtMalloc (hmany_per_page * sizeof (int *)) ;
  1221.     for (i=0;  i < hmany_per_page;  i++)
  1222.     rule[i] = (int *) XtMalloc (spread * sizeof (int)) ;
  1223.     allrandom = True ;
  1224.     lw->cell.rule_count = hmany_per_page ;
  1225.     lw->cell.masks_active = False ;
  1226.     }
  1227. return ;
  1228. }
  1229.  
  1230. static void
  1231. get_counts (lw)
  1232.     XcuCellWidget lw ;
  1233. {
  1234. many_count = lw->cell.height / many_per_page ;
  1235. hmany_count = lw->cell.width / hmany_per_page ;
  1236.  
  1237. return ;
  1238. }
  1239.  
  1240. static void
  1241. get_wraps (lw)
  1242.     XcuCellWidget lw ;
  1243. {
  1244. int i, h, w ;
  1245. wrap_left = (unsigned char **)
  1246.         XtMalloc (hmany_per_page * sizeof (unsigned char *)) ;
  1247. for (i=0;  i < hmany_per_page;  i++)
  1248.     wrap_left[i] = (unsigned char *)
  1249.            XtMalloc (windo/2 * sizeof (unsigned char)) ;
  1250.  
  1251. wrap_right = (unsigned char **)
  1252.         XtMalloc (hmany_per_page * sizeof (unsigned char *)) ;
  1253. for (i=0;  i < hmany_per_page;  i++)
  1254.     wrap_right[i] = (unsigned char *)
  1255.            XtMalloc (windo/2 * sizeof (unsigned char)) ;
  1256.  
  1257. for (h=0;  h < hmany_per_page;  h++)
  1258.     {
  1259.     for (w=0; w < windo/2;  w++)
  1260.     {
  1261.     if (!hmerge)
  1262.         {
  1263.         wrap_left[h][w] = (h+1) * hmany_count - w - 1 ;
  1264.         wrap_right[h][w] = h * hmany_count + w ;
  1265.         }
  1266.     else
  1267.         {
  1268.         if (h == 0)
  1269.         wrap_left[h][w] = h * hmany_count - w - 1 ;
  1270.         else
  1271.         wrap_left[h][w] = hmany_per_page * hmany_count - w - 1 ;
  1272.         if (h == hmany_per_page-1)
  1273.         wrap_right[h][w] = w ;
  1274.         else
  1275.         wrap_right[h][w] = (h+1) * hmany_count + w ;
  1276.         }
  1277.     }
  1278.     }
  1279. return ;
  1280. }
  1281.  
  1282. static void
  1283. get_ignores (lw)
  1284.     XcuCellWidget lw ;
  1285. {
  1286. /*
  1287.  * Convert String To Ignores
  1288.  */
  1289. Cardinal    i ;
  1290. String    *words ;
  1291.  
  1292. if (lw->cell.ignore_array)
  1293.     {
  1294.     }
  1295.  
  1296. if (lw->cell.ignore_colors)
  1297.     {
  1298.     if (*lw->cell.ignore_colors)
  1299.     {
  1300.     XcuConvertStringToWords (lw->cell.ignore_colors,
  1301.                  &words, &lw->cell.ignore_count) ;
  1302.     lw->cell.ignore_array = (int *) XtMalloc (lw->cell.ignore_count *
  1303.                             sizeof(int)) ;
  1304.     for (i=0;  i < lw->cell.ignore_count;  i++)
  1305.         {
  1306.         lw->cell.ignore_array[i] = atoi(words[i]) ;
  1307.         }
  1308.     lw->cell.ignore_colors = (String) NULL ;
  1309.     }
  1310.     else
  1311.     lw->cell.ignore_count = 0 ;
  1312.     }
  1313.  
  1314. return ;
  1315. }
  1316.  
  1317. static void
  1318. get_size_arrays (lw)
  1319.     XcuCellWidget lw ;
  1320. {
  1321. if (lw->cell.image->data)
  1322.     {
  1323.     XtFree(lw->cell.image->data) ;
  1324.     }
  1325. if (row0)
  1326.     {
  1327.     XtFree(row0) ;
  1328.     }
  1329.  
  1330. if (row1)
  1331.     {
  1332.     XtFree(row1) ;
  1333.     }
  1334.  
  1335. lw->cell.image->data = XtMalloc((unsigned) lw->cell.width * sizeof(char)) ;
  1336. row0 = (unsigned char *) XtMalloc((unsigned) lw->cell.width * sizeof(char)) ;
  1337. row1 = (unsigned char *) XtMalloc((unsigned) lw->cell.width * sizeof(char)) ;
  1338.  
  1339. lw->cell.image->width = lw->cell.width ;
  1340. lw->cell.image->bytes_per_line = lw->cell.width ;
  1341.  
  1342. return ;
  1343. }
  1344.  
  1345. static
  1346. void get_rcells (lw)
  1347.     XcuCellWidget lw ;
  1348. {
  1349. int i, h ;
  1350. if (lw->cell.rcells)
  1351.     {
  1352.     for (i=0;  i < lw->cell.old_rcell_hmany;  i++)
  1353.     XtFree (lw->cell.rcells[i]) ;
  1354.     XtFree (lw->cell.rcells) ;
  1355.     }
  1356. lw->cell.old_rcell_hmany = hmany_per_page ;
  1357. lw->cell.rcells = (Pixel **) XtMalloc (hmany_per_page * sizeof (Pixel *)) ;
  1358. for (h=0;  h < hmany_per_page;  h++)
  1359.     {
  1360.     lw->cell.rcells[h] = (Pixel *) XtMalloc (reduct * sizeof (Pixel)) ;
  1361.     for (i=0;  i < reduct;  i++)
  1362.     {
  1363.     lw->cell.rcells[h][i] = lw->cell.cells[i] ;
  1364.     }
  1365.     }
  1366.  
  1367. return ;
  1368. }
  1369.  
  1370. static
  1371. void get_colors (lw)
  1372.     XcuCellWidget lw ;
  1373. {
  1374. int i, h ;
  1375.  
  1376.     if (lw->cell.cells)
  1377.     {
  1378.     XtFree (lw->cell.cells) ;
  1379.     XFreeColors (XtDisplay(lw),
  1380.             DefaultColormap(XtDisplay(lw),DefaultScreen(XtDisplay(lw))),
  1381.             lw->cell.cells,
  1382.             lw->cell.old_n_colors,
  1383.             NULL) ;
  1384.     }
  1385.  
  1386.     lw->cell.old_n_colors = lw->cell.n_colors ;
  1387.     lw->cell.cells = (Pixel *) XtMalloc (lw->cell.n_colors * sizeof (Pixel)) ;
  1388.  
  1389.     /*
  1390.      * First allocate as many writable colormap entries as we can get.
  1391.      */
  1392.  
  1393.     for (lw->cell.max_rw_cells=0;
  1394.      lw->cell.max_rw_cells < lw->cell.n_colors;
  1395.      lw->cell.max_rw_cells++)
  1396.     {
  1397.     if (!XAllocColorCells (XtDisplay(lw),
  1398.            DefaultColormap(XtDisplay(lw),DefaultScreen(XtDisplay(lw))),
  1399.            True,
  1400.            NULL, 0,
  1401.            &lw->cell.cells[lw->cell.max_rw_cells], 1))
  1402.         break ;
  1403.     }
  1404.  
  1405. for (i=0;  i < lw->cell.max_rw_cells;  i++)
  1406.     {
  1407.     lw->cell.colors[i].pixel = lw->cell.cells[i] ;
  1408.     lw->cell.colors[i].flags = DoRed | DoGreen | DoBlue ;
  1409.     }
  1410.  
  1411. if (lw->cell.max_rw_cells)
  1412. XStoreColors  (XtDisplay(lw),
  1413.           DefaultColormap(XtDisplay(lw),DefaultScreen(XtDisplay(lw))),
  1414.           lw->cell.colors, lw->cell.max_rw_cells) ;
  1415. /*
  1416.  * Now get the remainder as read-only colormap entries
  1417.  */
  1418.  
  1419. for (i=lw->cell.max_rw_cells;  i < lw->cell.n_colors;  i++)
  1420.     {
  1421.     if (!XAllocColor (XtDisplay(lw),
  1422.           DefaultColormap(XtDisplay(lw),DefaultScreen(XtDisplay(lw))),
  1423.           &lw->cell.colors[i]))
  1424.     break ;
  1425.     lw->cell.cells[i] = lw->cell.colors[i].pixel ;
  1426.     }
  1427.  
  1428.  
  1429. if (i < lw->cell.n_colors)
  1430.     {
  1431.     fprintf (stderr, "Warning: Unable to allocate enough colormap cells!\n") ;
  1432.     }
  1433.  
  1434. lw->cell.max_colors = i ;
  1435.  
  1436. return ;
  1437. }
  1438.  
  1439. static
  1440. void get_permutations (lw)
  1441.     XcuCellWidget lw ;
  1442. {
  1443. int i ;
  1444. int m_taken = reduct ;
  1445. Pixel arr[MAX_COLORS_ALLOWED] ;
  1446.  
  1447. lw->cell.permutation_index = 0 ;
  1448.  
  1449. if (lw->cell.permute_array)
  1450.     {
  1451.     for (i=0;  i < lw->cell.n_permutations;  i++)
  1452.     XtFree (lw->cell.permute_array[i]) ;
  1453.     XtFree (lw->cell.permute_array) ;
  1454.     }
  1455.  
  1456. for (i=0;  i < lw->cell.n_colors;  i++)
  1457.     arr[i] = i ;
  1458.  
  1459. lw->cell.permute_array = permutations (lw->cell.n_colors,
  1460.                        m_taken,
  1461.                        arr,
  1462.                        &lw->cell.n_permutations) ;
  1463. return ;
  1464. }
  1465.  
  1466. void
  1467. XcuCellStep (lw)
  1468.     XcuCellWidget lw ;
  1469. {
  1470. int h ;
  1471. unsigned char *temp ;
  1472. int *iarule ;
  1473.  
  1474. if (!lw->cell.is_exposed)
  1475.     return ;
  1476.  
  1477. if (row == lw->cell.height)
  1478.     {
  1479.     row = 0 ;
  1480.     mask_iter = 0 ;
  1481.     }
  1482.  
  1483. if (row == 0)
  1484.     {
  1485.     if (lw->cell.frequency == XcuPAGE_FREQUENCY)
  1486.     XcuCellNextMap (lw, 1) ;
  1487.     rule_number = 0 ;
  1488.     get_rule (lw, irule, save_rule, NULL) ;
  1489.     if (lw->cell.alternating)
  1490.     get_rule (lw, arule, asave_rule, irule) ;
  1491.     rule_number++ ;
  1492.     get_initial_row (lw) ;
  1493.     put_row (lw, lw->cell.image) ;
  1494.     row_count = 1 ;
  1495.     row++ ;
  1496.     return ;
  1497.     }
  1498.  
  1499. row_count++ ;
  1500. iarule = (!lw->cell.alternating || !(row_count & 1)) ? irule : arule ;
  1501.  
  1502. for (h=0;  h < hmany_per_page;  h++)
  1503.     {
  1504.     if (lw->cell.frequency == XcuLINE_FREQUENCY)
  1505.     {
  1506.     lw->cell.current_h = h ;
  1507.     XcuCellNextMap (lw, 1) ;
  1508.     }
  1509.     switch (mix)
  1510.       {
  1511.       case LCR3 :
  1512.       case LCR4 :
  1513.       case LCR5 :
  1514.       case LCR6 :
  1515.     {
  1516.     lcr (h, hmany_count, lw->cell.masks_active, row0, row1,
  1517.           rule, nrule, wrap_left, wrap_right,
  1518.           iarule, lw->cell.rcells[h], lw->cell.image->data) ;
  1519.     break ;
  1520.     }
  1521.       case LCCR4 :
  1522.     {
  1523.     lccr (h, hmany_count, lw->cell.masks_active, row0, row1, rule, nrule,
  1524.           wrap_left, wrap_right, iarule, lw->cell.rcells[h],
  1525.           lw->cell.image->data) ;
  1526.     break ;
  1527.     }
  1528.       case LCCRRR4 :
  1529.     {
  1530.     lccrrr (h, hmany_count, lw->cell.masks_active, row0, row1, rule, nrule,
  1531.           wrap_left, wrap_right, iarule, lw->cell.rcells[h],
  1532.           lw->cell.image->data) ;
  1533.     break ;
  1534.     }
  1535.       case KLCRT3 :
  1536.       case KLCRT4 :
  1537.       case KLCRT5 :
  1538.     {
  1539.     klcrt (h, hmany_count, lw->cell.masks_active, row0, row1, rule, nrule,
  1540.           wrap_left, wrap_right, iarule, lw->cell.rcells[h],
  1541.           lw->cell.image->data) ;
  1542.     break ;
  1543.     }
  1544.       }
  1545.     }
  1546. put_row (lw, lw->cell.image) ;
  1547.  
  1548. temp = row0 ;
  1549. row0 = row1 ;
  1550. row1 = temp ;
  1551.  
  1552. if (row > 1 && many_per_page > 1)
  1553.     {
  1554.     if (row_count > many_count && row < lw->cell.height - many_count/2)
  1555.     {
  1556.     row_count = 1 ;
  1557.     get_initial_row (lw) ;
  1558.     get_rule (lw, irule, save_rule, 0) ;
  1559.     if (lw->cell.alternating)
  1560.         get_rule (lw, arule, asave_rule, irule) ;
  1561.     rule_number++ ;
  1562.     }
  1563.     }
  1564.  
  1565. row++; 
  1566. /*** FUTURE RESOURCE
  1567. if (row == lw->cell.height)
  1568.     {
  1569.     if (sleep_seconds)
  1570.     sleep (sleep_seconds) ;
  1571.     }
  1572. ***/
  1573. return ;
  1574. }
  1575.  
  1576. static void
  1577. Pick (w,event,params,num_params)
  1578.      Widget w;
  1579.      XButtonEvent *event;
  1580.      String *params;        /* unused */
  1581.      Cardinal *num_params;    /* unused */
  1582. {
  1583. XcuCellWidget lw = (XcuCellWidget) w ;
  1584. Dimension facet_sub = (lw->simple.shadow ? 0 : 1) * lw->simple.facet_width ;
  1585. int dcx, dcy ;
  1586. int picked_rule ;
  1587. int hpicked_rule ;
  1588.  
  1589. dcx = event->x - lw->cell.internal_width - facet_sub ;
  1590. dcy = event->y - lw->cell.internal_height - facet_sub ;
  1591. picked_rule = dcy / many_count ;
  1592. hpicked_rule = dcx / hmany_count ;
  1593.  
  1594. /* TODO: Some sort of acknowledging flash? */
  1595. if (lw->cell.beep)
  1596.     fprintf (stderr, "\007") ;
  1597.  
  1598. if (!fpick)
  1599.     {
  1600.     char tmp[20] ;
  1601.     sprintf (tmp, "/tmp/cell%d", getpid()) ;
  1602.     fprintf (stderr, "No pick file specified! Opening %s for output.\n", tmp) ;
  1603.     fpick = fopen (tmp, "a") ;
  1604.     }
  1605. p_rule (fpick, "", save_rule[picked_rule][hpicked_rule], spread) ;
  1606. if (lw->cell.alternating)
  1607.     p_rule (fpick, " ", asave_rule[picked_rule][hpicked_rule], spread) ;
  1608. fflush (fpick) ;
  1609. return ;
  1610. }
  1611.  
  1612. static void
  1613. get_initial_row (lw)
  1614.     XcuCellWidget lw ;
  1615. {
  1616. int i, h ;
  1617. /* for now only random or merge initialization */
  1618. /* (We may want to add initialization by a defined pattern) */
  1619.  
  1620. if (
  1621.     lw->cell.first_initial_row || !vmerge
  1622.    )
  1623.     {
  1624.     for (i=0;  i < lw->cell.width;  i++)
  1625.     {
  1626.     switch (reduct)
  1627.         {
  1628.         case 3 : { row0[i] = rand3() ; break ; }
  1629.         case 4 : { row0[i] = rand4() ; break ; }
  1630.         case 5 : { row0[i] = rand5() ; break ; }
  1631.         case 6 : { row0[i] = rand6() ; break ; }
  1632.         }
  1633.     }
  1634.     lw->cell.first_initial_row = False ;
  1635.     }
  1636. else
  1637.     {
  1638.     /* we may reinitialize if the row has come out all equal */
  1639.     for (h=0;  h < hmany_per_page;  h++)
  1640.     {
  1641.     int c = h*hmany_count ;
  1642.     for (i=1;  i < hmany_count;  i++)
  1643.         {
  1644.         if (row0[c+i] != row0[c])
  1645.         {
  1646.         break ;
  1647.         }
  1648.         }
  1649.     if (i == hmany_count)
  1650.         {
  1651.         for (i=0;  i < hmany_count;  i++)
  1652.         {
  1653.         switch (reduct)
  1654.             {
  1655.             case 3 : { row0[c+i] = rand3() ; break ; }
  1656.             case 4 : { row0[c+i] = rand4() ; break ; }
  1657.             case 5 : { row0[c+i] = rand5() ; break ; }
  1658.             case 6 : { row0[c+i] = rand6() ; break ; }
  1659.             }
  1660.         }
  1661.         }
  1662.     }
  1663.     }
  1664. return ;
  1665. }
  1666.  
  1667. static void
  1668. get_rule (lw, iarule, iasave_rule, real_irule)
  1669.     XcuCellWidget lw ;
  1670.     int *iarule ;
  1671.     int ***iasave_rule ;
  1672.     int *real_irule ;
  1673. {
  1674. int i, h, rule_cnt ;
  1675.  
  1676. for (h=0;  h < hmany_per_page;  h++)
  1677.   {
  1678.   do
  1679.     {
  1680.     if (mask_iter >= masks)
  1681.     mask_iter -= masks ;
  1682.     if (lw->cell.mutate)
  1683.     {
  1684.     int mutate_location = rand() % spread ;
  1685.     int mutate_value = rand3() + 1 ;
  1686.     lw->cell.mutation[mutate_location] += mutate_value ;
  1687.     lw->cell.mutation[mutate_location] %= 4 ;
  1688.     iarule[h] = h ;
  1689.     for (i=0;  i < spread;  i++)
  1690.         rule[h][i] = lw->cell.mutation[i] ;
  1691.     }
  1692.     else
  1693.     if (allrandom)
  1694.     {
  1695.     iarule[h] = h ;
  1696.     for (i=0;  i < spread;  i++)
  1697.         {
  1698.         int val ;
  1699.         for (;;)
  1700.         {
  1701.         switch (reduct)
  1702.             {
  1703.             case 3 : { val = rand3() ; break ; }
  1704.             case 4 : { val = rand4() ; break ; }
  1705.             case 5 : { val = rand5() ; break ; }
  1706.             case 6 : { val = rand6() ; break ; }
  1707.             }
  1708.         if (lw->cell.ignore_count)
  1709.             {
  1710.             int j ;
  1711.             for (j=0;  j < lw->cell.ignore_count;  j++)
  1712.             if (lw->cell.ignore_array[j] == val)
  1713.                 break ;
  1714.             if (j == lw->cell.ignore_count)
  1715.             break ;
  1716.             }
  1717.         else
  1718.             break ;
  1719.         }
  1720.         rule[h][i] = val ;
  1721.         }
  1722.     }
  1723.     else
  1724.     if (order || lw->cell.masks_active)
  1725.     {
  1726.     if (!lw->cell.masks_active || mask_iter == 0)
  1727.         {
  1728.         order_number++ ;
  1729.         if (order_number == nrule)
  1730.         order_number = 0 ;
  1731.         iarule[h] = order_number ;
  1732.         }
  1733.     if (lw->cell.masks_active)
  1734.         {
  1735.         int r ;
  1736.         for (r=0;  r < spread;  r++)
  1737.         rule[nrule+h][r] = rule[iarule[0]][r] ;
  1738.         }
  1739.     }
  1740.     else
  1741.     if (rrule == -1) /* random rule number */
  1742.     {
  1743.     iarule[h] = (rand() % nrule) ; 
  1744.     if (iarule[h] == nrule) iarule[h] = 0 ;
  1745.     }
  1746.     else  /* use the specified rule */
  1747.     {
  1748.     iarule[h] = rrule - 1 ;
  1749.     }
  1750.  
  1751.     if (lw->cell.masks_active)
  1752.     {
  1753.     for (i=0;  i < spread;  i++)
  1754.         {
  1755.         rule[nrule+h][i] += mask[mask_iter][i] ;
  1756.         if (rule[nrule+h][i] >= reduct)
  1757.         rule[nrule+h][i] -= reduct ;
  1758.         }
  1759.  
  1760.     mask_iter++ ;
  1761.     if (mask_iter > masks)
  1762.         mask_iter = 0 ;
  1763.     }
  1764.  
  1765.     for (rule_cnt=0;  rule_cnt < spread;  rule_cnt++)
  1766.     {
  1767.     if (lw->cell.masks_active)
  1768.         iasave_rule[rule_number][h][rule_cnt] = rule[nrule+h][rule_cnt] ;
  1769.     else
  1770.         {
  1771.         iasave_rule[rule_number][h][rule_cnt] = rule[iarule[h]][rule_cnt] ;
  1772.         }
  1773.     }
  1774.     if (lw->cell.frequency == XcuRULE_FREQUENCY)
  1775.     {
  1776.     lw->cell.current_h = h ;
  1777.     XcuCellNextMap (lw, 1) ;
  1778.     }
  1779.     } while (hmany_per_page > 1 && real_irule && iarule[h] == real_irule[h]) ;
  1780.       /* This avoids getting the same rule for both rules when alternating */
  1781.   }
  1782.  
  1783. return ;
  1784. }
  1785.  
  1786. static void
  1787. p_rule (fd, pre_text, _rule, _spread)
  1788.     FILE *fd ;
  1789.     char *pre_text ;
  1790.     int *_rule ;
  1791.     int _spread ;
  1792. {
  1793. int i, j ;
  1794. int m3 = _spread/3*3 ;
  1795. int orphans = _spread - m3 ;
  1796. int groups, ptr ;
  1797.  
  1798. fprintf (fd, "%s", pre_text) ;
  1799. for (i=0;  i < orphans;  i++)
  1800.     fprintf (fd, "%d ", _rule[i]) ;
  1801.  
  1802. groups = m3 / 3 ;
  1803. ptr = orphans ;
  1804. for (i=0;  i < groups;  i++)
  1805.     {
  1806.     fprintf (fd, " ") ;
  1807.     for (j=0;  j < 3;  j++)
  1808.         {
  1809.         fprintf (fd, "%d ", _rule[ptr]) ;
  1810.         ptr++ ;
  1811.         }
  1812.     }
  1813. fprintf (fd, "\n") ;
  1814. return ;
  1815. }
  1816.  
  1817. static void
  1818. put_row (lw, image)
  1819.     XcuCellWidget lw ;
  1820.     XImage *image ;
  1821. {
  1822. Dimension facet_left = (lw->simple.shadow) ?
  1823.             0 : lw->simple.facet_width ;
  1824. XPutImage (XtDisplay(lw), XtWindow(lw), lw->cell.cell_GC,
  1825.        image, 0, 0,
  1826.        facet_left + lw->cell.internal_width,
  1827.        facet_left + lw->cell.internal_height + row,
  1828.        lw->cell.width, 1) ;
  1829. return ;
  1830. }
  1831.  
  1832. static void
  1833. do_gets (lw)
  1834.     XcuCellWidget lw ;
  1835. {
  1836. if (lw->cell.alt_changed)
  1837.     {
  1838.     lw->cell.first_initial_row = True ;
  1839.     row = 0 ;
  1840.     }
  1841.  
  1842. if (lw->cell.type_changed)
  1843.     {
  1844.     int old_spread = spread ;
  1845.     int old_windo = windo ;
  1846.     int old_reduct = reduct ;
  1847.     get_rule_type    (lw) ;
  1848.     if (spread != old_spread)
  1849.     lw->cell.spread_changed = True ;
  1850.     if (windo != old_windo)
  1851.     lw->cell.windo_changed = True ;
  1852.     if (reduct != old_reduct)
  1853.     lw->cell.reduct_changed = True ;
  1854.     row = 0 ;
  1855.     lw->cell.first_initial_row = True ;
  1856.     mask_iter = 0 ;
  1857.     }
  1858.  
  1859. if (lw->cell.mod_changed)
  1860.     {
  1861.     int temp ;
  1862.  
  1863.     temp = hmany_per_page ;
  1864.     hmany_per_page = lw->cell.mod_hmany_per_page ;
  1865.     lw->cell.mod_hmany_per_page = temp ;
  1866.  
  1867.     temp = many_per_page ;
  1868.     many_per_page = lw->cell.mod_many_per_page ;
  1869.     lw->cell.mod_many_per_page = temp ;
  1870.  
  1871.     lw->cell.many_changed = True ;
  1872.     lw->cell.hmany_changed = True ;
  1873.  
  1874.     row = 0 ;
  1875.     lw->cell.first_initial_row = True ;
  1876.     mask_iter = 0 ;
  1877.     }
  1878.  
  1879. if (lw->cell.hmany_changed || lw->cell.many_changed || lw->cell.spread_changed)
  1880.     {
  1881.     get_save_rule    (lw) ;
  1882.     }
  1883.  
  1884. if (lw->cell.rrule_changed)
  1885.     {
  1886.     get_order_number(lw) ;
  1887.     row = 0 ;
  1888.     lw->cell.first_initial_row = True ;
  1889.     mask_iter = 0 ;
  1890.     }
  1891.  
  1892. if (lw->cell.pick_changed)
  1893.     {
  1894.     get_pick_file    (lw) ;
  1895.     }
  1896.  
  1897. if (lw->cell.seed_changed)
  1898.     {
  1899.     get_seed    (lw) ;
  1900.     row = 0 ;
  1901.     lw->cell.first_initial_row = True ;
  1902.     mask_iter = 0 ;
  1903.     }
  1904.  
  1905. if (lw->cell.rules_changed || lw->cell.mod_changed ||
  1906.     lw->cell.spread_changed || lw->cell.hmany_changed)
  1907.     {
  1908.     get_rules    (lw) ;
  1909.     row = 0 ;
  1910.     lw->cell.first_initial_row = True ;
  1911.     mask_iter = 0 ;
  1912.     }
  1913.  
  1914. if (lw->cell.width_changed || lw->cell.height_changed ||
  1915.     lw->cell.many_changed  || lw->cell.hmany_changed)
  1916.     {
  1917.     get_counts    (lw) ;
  1918.     lw->cell.hmany_changed = True ;
  1919.     row = 0 ;
  1920.     lw->cell.first_initial_row = True ;
  1921.     mask_iter = 0 ;
  1922.     }
  1923.  
  1924. if (lw->cell.windo_changed || lw->cell.hmerge_changed ||
  1925.     lw->cell.hmany_changed)
  1926.     {
  1927.     get_wraps    (lw) ;
  1928.     row = 0 ;
  1929.     lw->cell.first_initial_row = True ;
  1930.     mask_iter = 0 ;
  1931.     }
  1932.  
  1933. if (lw->cell.ignore_colors_changed)
  1934.     {
  1935.     get_ignores    (lw) ;
  1936.     }
  1937.  
  1938. if (lw->cell.width_changed || lw->cell.height_changed)
  1939.     {
  1940.     get_size_arrays    (lw) ;
  1941.     row = 0 ;
  1942.     lw->cell.first_initial_row = True ;
  1943.     mask_iter = 0 ;
  1944.     }
  1945.  
  1946. if (lw->cell.colors_changed || lw->cell.n_colors_changed)
  1947.     {
  1948.     get_colors    (lw) ;
  1949.     lw->cell.hmany_changed = True ; /* Hack to get get_rcells() called */
  1950.     }
  1951.  
  1952. if (lw->cell.reduct_changed || lw->cell.hmany_changed)
  1953.     {
  1954.     get_rcells    (lw) ;
  1955.     }
  1956.  
  1957. if (lw->cell.reduct_changed || lw->cell.n_colors_changed)
  1958.     {
  1959.     get_permutations (lw) ;
  1960.     }
  1961.  
  1962. set_changed_false (lw) ;
  1963. return ;
  1964. }
  1965.  
  1966. static void
  1967. set_changed_false (lw)
  1968.     XcuCellWidget lw ;
  1969. {
  1970. lw->cell.height_changed = False ;
  1971. lw->cell.hmerge_changed = False ;
  1972. lw->cell.hmany_changed = False ;
  1973. lw->cell.ignore_colors_changed = False ;
  1974. lw->cell.many_changed = False ;
  1975. lw->cell.mod_changed = False ;
  1976. lw->cell.pick_changed = False ;
  1977. lw->cell.rrule_changed = False ;
  1978. lw->cell.rules_changed = False ;
  1979. lw->cell.seed_changed = False ;
  1980. lw->cell.spread_changed = False ;
  1981. lw->cell.type_changed = False ;
  1982. lw->cell.width_changed = False ;
  1983. lw->cell.windo_changed = False ;
  1984. lw->cell.colors_changed = False ;
  1985. lw->cell.n_colors_changed = False ;
  1986. lw->cell.reduct_changed = False ;
  1987. lw->cell.alt_changed = False ;
  1988. return ;
  1989. }
  1990.  
  1991. static void
  1992. set_changed_true (lw)
  1993.     XcuCellWidget lw ;
  1994. {
  1995. lw->cell.height_changed = True ;
  1996. lw->cell.hmerge_changed = True ;
  1997. lw->cell.hmany_changed = True ;
  1998. lw->cell.ignore_colors_changed = True ;
  1999. lw->cell.many_changed = True ;
  2000. lw->cell.pick_changed = True ;
  2001. lw->cell.rrule_changed = True ;
  2002. lw->cell.rules_changed = True ;
  2003. lw->cell.seed_changed = True ;
  2004. lw->cell.spread_changed = True ;
  2005. lw->cell.type_changed = True ;
  2006. lw->cell.width_changed = True ;
  2007. lw->cell.windo_changed = True ;
  2008. lw->cell.colors_changed = True ;
  2009. lw->cell.n_colors_changed = True ;
  2010. lw->cell.reduct_changed = True ;
  2011. lw->cell.alt_changed = True ;
  2012. return ;
  2013. }
  2014.  
  2015. void
  2016. XcuCellFirstMap (lw)
  2017.     XcuCellWidget lw ;
  2018. {
  2019. lw->cell.permutation_index = 0 ;
  2020. permute_colormap (lw) ;
  2021. return ;
  2022. }
  2023.  
  2024. void
  2025. XcuCellNextMap (lw, direction)
  2026.     XcuCellWidget lw ;
  2027.     int direction ;
  2028. {
  2029. switch (lw->cell.sequence)
  2030.   {
  2031.   case XcuORDERED_PERMUTE :
  2032.     {
  2033.     if (direction >= 0)
  2034.     {
  2035.     lw->cell.permutation_index++ ;
  2036.     if (lw->cell.permutation_index == lw->cell.n_permutations)
  2037.         lw->cell.permutation_index = 0 ;
  2038.     }
  2039.     else
  2040.     {
  2041.     lw->cell.permutation_index-- ;
  2042.     if (lw->cell.permutation_index < 0)
  2043.         lw->cell.permutation_index = lw->cell.n_permutations - 1 ;
  2044.     }
  2045.     permute_colormap (lw) ;
  2046.     break ;
  2047.     }
  2048.   case XcuRANDOM_PERMUTE :
  2049.     {
  2050.     lw->cell.permutation_index = (rand() % lw->cell.n_permutations) ;
  2051.     permute_colormap (lw) ;
  2052.     break ;
  2053.     }
  2054.   case XcuRANDOM_COLOR :
  2055.     {
  2056.     int i ;
  2057.     XColor color[MAX_COLORS_ALLOWED] ;
  2058.     if (lw->cell.max_rw_cells >= reduct &&
  2059.     lw->cell.frequency != XcuLINE_FREQUENCY &&
  2060.     (lw->cell.frequency != XcuRULE_FREQUENCY || hmany_per_page == 1))
  2061.     {
  2062.     /*
  2063.      * Alter the colors by modifying the colormap
  2064.      */
  2065.     for (i=0;  i < reduct;  i++)
  2066.         {
  2067.         color[i].flags = DoRed|DoGreen|DoBlue ;
  2068.         color[i].pixel = lw->cell.colors[i].pixel ;
  2069.         color[i].red = rndm(65535L,-1) ;
  2070.         color[i].green = rndm(65535L,-1) ;
  2071.         color[i].blue = rndm(65535L,-1) ;
  2072.         }
  2073.  
  2074.     XStoreColors  (XtDisplay(lw),
  2075.           DefaultColormap(XtDisplay(lw),DefaultScreen(XtDisplay(lw))),
  2076.           color, reduct) ;
  2077.     }
  2078.     else
  2079.     {
  2080.     /*
  2081.      * Can't do it!
  2082.      */
  2083.     }
  2084.     break ;
  2085.     }
  2086.   }
  2087. return ;
  2088. }
  2089.  
  2090. static void
  2091. permute_colormap (lw)
  2092.     XcuCellWidget lw ;
  2093. {
  2094. static XColor *temp = NULL ;
  2095. static int max_temp = 0 ;
  2096. int i ;
  2097. if (reduct > max_temp)
  2098.     {
  2099.     if (temp)
  2100.     XtFree (temp) ;
  2101.     temp = (XColor *) XtMalloc (reduct * sizeof (XColor)) ;
  2102.     }
  2103. /*
  2104.  * We'll change the colormap if we have enough writable cells,
  2105.  * o.w., we can only change future colors by altering the pixels written
  2106.  * But we have to alter pixels written if the coloration is by rule or line
  2107.  * (unless there is only one rule per row and then we can change the colormap)
  2108.  */
  2109. if (lw->cell.max_rw_cells >= reduct &&
  2110.     lw->cell.frequency != XcuLINE_FREQUENCY &&
  2111.     (lw->cell.frequency != XcuRULE_FREQUENCY || hmany_per_page == 1))
  2112.     {
  2113.     /*
  2114.      * Alter the colors by modifying the colormap
  2115.      */
  2116.     for (i=0;  i < reduct;  i++)
  2117.     {
  2118.     int index = lw->cell.permute_array[lw->cell.permutation_index][i] ;
  2119.     temp[i].flags = lw->cell.colors[i].flags ;
  2120.     temp[i].pixel = lw->cell.colors[i].pixel ;
  2121.     temp[i].red = lw->cell.colors[index].red ;
  2122.     temp[i].green = lw->cell.colors[index].green ;
  2123.     temp[i].blue = lw->cell.colors[index].blue ;
  2124.     }
  2125.  
  2126.     XStoreColors  (XtDisplay(lw),
  2127.           DefaultColormap(XtDisplay(lw),DefaultScreen(XtDisplay(lw))),
  2128.           temp, reduct) ;
  2129.     }
  2130. else
  2131.     {
  2132.     /*
  2133.      * Alter the colors by modifying the pixels written instead of modifying
  2134.      * the colormap
  2135.      */
  2136.     for (i=0;  i < reduct;  i++)
  2137.     {
  2138.     int index = lw->cell.permute_array[lw->cell.permutation_index][i] ;
  2139.     lw->cell.rcells[lw->cell.current_h][i] = lw->cell.cells[index] ;
  2140.     }
  2141.     }
  2142. return ;
  2143. }
  2144.  
  2145. static int **
  2146. permutations (n_items, m_taken, items, n_permutations)
  2147.     int n_items ;
  2148.     int m_taken ;
  2149.     Pixel *items ;
  2150.     int *n_permutations ;
  2151. {
  2152. int i ;
  2153. int n_found ;
  2154. static Pixel **array ;
  2155. Pixel *temp ;
  2156. /*
  2157.  * given n items, taken m at a time, this function...
  2158.  * computes the number of permutations,
  2159.  * allocates an array of pointers to the permutations,
  2160.  * and computes the permutations.
  2161.  */
  2162.  
  2163. if (n_items < m_taken)
  2164.     {
  2165.     int n=1 ;
  2166.  
  2167.     for (i=0;  i < m_taken;  i++)
  2168.     n *= n_items ;
  2169.     n -= n_items ; /* skip cases where all the same color */
  2170.     *n_permutations = n ;
  2171.  
  2172.     array = (Pixel **) XtMalloc (*n_permutations * sizeof (Pixel *)) ;
  2173.     for (i=0;  i < n;  i++)
  2174.     array[i] = (Pixel *) XtMalloc (m_taken * sizeof(Pixel)) ;
  2175.     for (i=0,n=0;  n < *n_permutations;  i++)
  2176.     {
  2177.     int index = i ;
  2178.     int k ;
  2179.     for (k=0;  k < m_taken;  k++)
  2180.         {
  2181.         array[n][k] = index%n_items ;
  2182.         index /= n_items ;
  2183.         }
  2184.     for (k=1;  k < m_taken;  k++)
  2185.         if (array[n][k] != array[n][0])
  2186.         break ;
  2187.     if (k != m_taken)
  2188.         {
  2189.         n++ ;
  2190.         }
  2191.     }
  2192.  
  2193.     return array ;
  2194.     }
  2195. *n_permutations = n_by_m_perm (n_items, m_taken) ;
  2196.  
  2197. array = (Pixel **) XtMalloc (*n_permutations * sizeof (Pixel *)) ;
  2198. for (i=0;  i < *n_permutations;  i++)
  2199.     {
  2200.     array[i] = (Pixel *) XtMalloc (m_taken * sizeof (Pixel)) ;
  2201.     }
  2202.  
  2203. temp = (Pixel *) XtMalloc (m_taken * sizeof(Pixel)) ;
  2204. n_found = 0 ;
  2205. permute (m_taken, 0, n_items, items, array, temp, &n_found) ;
  2206. XtFree (temp) ;
  2207.  
  2208. return array ;
  2209. }
  2210.  
  2211. static void
  2212. permute (n_levels, i_level, n_elements, elements,
  2213.      perm_array, temp_array, n_found)
  2214.     int n_levels ;
  2215.     int i_level ;
  2216.     int n_elements ;
  2217.     Pixel *elements ;
  2218.     Pixel **perm_array ;
  2219.     int *temp_array ;
  2220.     int *n_found ;
  2221. {
  2222. int    i, j ;
  2223.  
  2224. for (i=0;  i < n_elements;  i++)
  2225.     {
  2226.     temp_array[i_level] = elements[i] ;
  2227.     if (i_level == n_levels - 1)
  2228.     {
  2229.     for (j=0;  j < n_levels;  j++)
  2230.         {
  2231.         perm_array[*n_found][j] = temp_array[j] ;
  2232.         }
  2233.     *n_found += 1 ;
  2234.     }
  2235.     else
  2236.     {
  2237.     Pixel *pass_array = (Pixel *) XtMalloc((n_elements-1) * sizeof(Pixel));
  2238.     for (j=0;  j < i;  j++)
  2239.         {
  2240.         pass_array[j] = elements[j] ;
  2241.         }
  2242.     for (j=i+1;  j < n_elements;  j++)
  2243.         {
  2244.         pass_array[j-1] = elements[j] ;
  2245.         }
  2246.     permute (n_levels, i_level+1, n_elements-1,
  2247.          pass_array, perm_array, temp_array, n_found) ;
  2248.     XtFree ((char *)pass_array) ;
  2249.     }
  2250.     }
  2251. return ;
  2252. }
  2253.  
  2254. static int
  2255. n_by_m_perm (n, m)
  2256.     int n ;
  2257.     int m ;
  2258. {
  2259. return factorial (n) / factorial (n-m) ;
  2260. }
  2261.  
  2262. static int
  2263. factorial (n)
  2264.     int n ;
  2265. {
  2266. if (n == 0)
  2267.     return 1 ;
  2268. else
  2269.     return n * factorial (n-1) ;
  2270. }
  2271.  
  2272. /**
  2273.  *** Resource Converter Routine
  2274.  **/
  2275.  
  2276. /*
  2277.  * Convert String To Frequency
  2278.  */
  2279.  
  2280. static void
  2281. CvtStringToFrequency(args, num_args, fromVal, toVal)
  2282.     XrmValuePtr *args ;        /* unused */
  2283.     Cardinal    *num_args ;    /* unused */
  2284.     XrmValuePtr fromVal ;
  2285.     XrmValuePtr toVal ;
  2286. {
  2287. static XcuCellFrequencyType    e ; /* must be static! */
  2288. XrmQuark    q ;
  2289. char    *s = (char *) fromVal->addr ;
  2290.  
  2291. if (s == NULL) return ;
  2292.  
  2293. q = XcuSimplifyArg (s, "xcu") ;
  2294.  
  2295. toVal->size = sizeof(XcuCellFrequencyType) ;
  2296. toVal->addr = (XPointer) &e ;
  2297.  
  2298. if (q == XrmQEfixed)   { e = XcuFIXED_FREQUENCY;   return; }
  2299. if (q == XrmQEpage) { e = XcuPAGE_FREQUENCY; return; }
  2300. if (q == XrmQErule)  { e = XcuRULE_FREQUENCY;  return; }
  2301. if (q == XrmQEline)  { e = XcuLINE_FREQUENCY;  return; }
  2302.  
  2303. toVal->size = 0 ;
  2304. toVal->addr = NULL ;
  2305. return ;
  2306. }
  2307.  
  2308. /*
  2309.  * Convert String To Sequence
  2310.  */
  2311.  
  2312. static void
  2313. CvtStringToSequence(args, num_args, fromVal, toVal)
  2314.     XrmValuePtr *args ;        /* unused */
  2315.     Cardinal    *num_args ;    /* unused */
  2316.     XrmValuePtr fromVal ;
  2317.     XrmValuePtr toVal ;
  2318. {
  2319. static XcuCellSequenceType    e ; /* must be static! */
  2320. XrmQuark    q ;
  2321. char    *s = (char *) fromVal->addr ;
  2322.  
  2323. if (s == NULL) return ;
  2324.  
  2325. q = XcuSimplifyArg (s, "xcu") ;
  2326.  
  2327. toVal->size = sizeof(XcuCellSequenceType) ;
  2328. toVal->addr = (XPointer) &e ;
  2329.  
  2330. if (q == XrmQEordered)   { e = XcuORDERED_PERMUTE;   return; }
  2331. if (q == XrmQErandomp) { e = XcuRANDOM_PERMUTE; return; }
  2332. if (q == XrmQErandomc)  { e = XcuRANDOM_COLOR;  return; }
  2333.  
  2334. toVal->size = 0 ;
  2335. toVal->addr = NULL ;
  2336. return ;
  2337. }
  2338.  
  2339. static long
  2340. rndm(maxval)
  2341.     long maxval;
  2342. {
  2343.   long lrand48();
  2344.   int sr1=15, sr2=16;
  2345.   long mv=maxval;
  2346.   while (mv > 0x8000L) {
  2347.     sr1++;
  2348.     sr2--;
  2349.     mv >>= 1;
  2350.   }
  2351. return ((lrand48() >> sr1) * maxval) >> sr2;
  2352. }
  2353.  
  2354.