home *** CD-ROM | disk | FTP | other *** search
/ Photo CD Demo 1 / Demo.bin / cellsim / v2_5 / src / cell.c next >
Encoding:
C/C++ Source or Header  |  1990-04-08  |  75.7 KB  |  3,896 lines

  1. /*****
  2.  *
  3.  * File: cell.c
  4.  *
  5.  * Cellsim, cellular automata simulator
  6.  *
  7.  * General routines.
  8.  *
  9.  *****/
  10.  
  11.  
  12. #include "cell.h"
  13.  
  14. /*
  15.  *
  16.  * Cellsim copyright 1989, 1990 by Chris Langton and Dave Hiebeler
  17.  * (cgl@lanl.gov, hiebeler@heretic.lanl.gov)
  18.  *
  19.  * This package may be freely distributed, as long as you don't:
  20.  * - remove this notice
  21.  * - try to make money by doing so
  22.  * - prevent others from copying it freely
  23.  * - distribute modified versions without clearly documenting your changes
  24.  *   and notifying us
  25.  *
  26.  * Please contact either of the authors listed above if you have questions
  27.  * or feel an exception to any of the above restrictions is in order.
  28.  *
  29.  * If you make changes to the code, or have suggestions for changes,
  30.  * let us know!  If we use your suggestion, you will receive full credit
  31.  * of course.
  32.  */
  33.  
  34. /*****
  35.  * Cellsim history:
  36.  *
  37.  * Cellsim was originally written on Apollo workstations by Chris Langton.
  38.  *
  39.  * Sun versions:
  40.  *
  41.  * - version 1.0
  42.  *   by C. Ferenbaugh and C. Langton
  43.  *   released 09/02/88
  44.  *
  45.  * - version 1.5
  46.  *   by Dave Hiebeler and C. Langton  May - June 1989
  47.  *   released 07/03/89
  48.  *
  49.  * - version 2.0
  50.  *   by Dave Hiebeler and C. Langton  July - August 1989
  51.  *   never officially released (unofficially released 09/08/89)
  52.  *
  53.  * - version 2.5
  54.  *   by Dave Hiebeler and C. Langton  September '89 - February 1990
  55.  *   released 02/26/90
  56.  *****/
  57.  
  58.  
  59.  
  60. main(argc, argv)
  61. int argc;
  62. char **argv;
  63. {
  64.     struct timeval tp;
  65.     struct timezone *tzp;
  66.  
  67.     emergency_LT_save_ptr = emergency_LT_save;
  68.     default_segv_func = (void_func_ptr) signal(SIGSEGV, emergency_LT_save_ptr);
  69.     /* Seed the random-# generator based on current time in microseconds */
  70.     tzp = NULL;
  71.     gettimeofday(&tp, tzp);
  72.     srandom((int) tp.tv_usec);
  73.     
  74.     remove_frame_args(&argc, argv);
  75.     which(argv[0],argv0);    /* look up full pathname of Cellsim */
  76.     init_vars();        /* init various variables */
  77.     set_params(argc, argv);
  78.     switch (B) {
  79.       case 64:
  80.       case 128:
  81.     CM_zoom = 6;
  82.     break;
  83.       case 256:
  84.     CM_zoom = 3;
  85.     break;
  86.       case 512:
  87.     CM_zoom = 1;
  88.     break;
  89.     }
  90.     CM_panx = B/2;
  91.     CM_pany = B/2;
  92.     init_scr();                /* initialize screen and graphics */
  93.     init_data();            /* initialize automaton data */
  94.     clear_data();            /* clear out data */
  95.     tclear();                /* clear the LT */
  96.  
  97.     statecount = (int *) malloc(S * sizeof(int));
  98.                     /* storage for state counters */
  99.  
  100.     display_image();            /* display (cleared) image */
  101.     
  102.     show_msg("Cellsim 2.5");
  103.     command_loop();
  104.     
  105.     /* On termination, sockets are automatically closed,
  106.      * pixrects destroyed, etc. */
  107.     exit(0);
  108.  
  109. } /* main */
  110.  
  111.  
  112.  
  113. /*
  114.  * Initialize misc. variables
  115.  */
  116. init_vars()
  117. {
  118.     char *tmp_str;
  119.     
  120.     parm1 = 0;
  121.     parm2 = 0;
  122.     use_FB = 0;
  123.     use_Sun_disp = 1;
  124.     auto_nhood_change = 1;
  125.     auto_image_change = 1;
  126.     blackwhite = 0;
  127.     if ((tmp_str = getenv("IMAGE_DIR")) == NULL)
  128.     sprintf(Image_dir, "%s", IMAGE_DIR);
  129.     else
  130.     sprintf(Image_dir, "%s", tmp_str);
  131.     if ((tmp_str = getenv("TABLE_DIR")) == NULL)
  132.     sprintf(Table_dir, "%s", TABLE_DIR);
  133.     else
  134.     sprintf(Table_dir, "%s", tmp_str);
  135.     if ((tmp_str = getenv("FCN_DIR")) == NULL)
  136.     sprintf(Fcn_dir, "%s", FCN_DIR);
  137.     else
  138.     sprintf(Fcn_dir, "%s", tmp_str);
  139.     if ((tmp_str = getenv("CMAP_DIR")) == NULL)
  140.     sprintf(Cmap_dir, "%s", CMAP_DIR);
  141.     else
  142.     sprintf(Cmap_dir, "%s", tmp_str);
  143.     expand_fname(Image_dir, Image_dir);
  144.     expand_fname(Table_dir, Table_dir);
  145.     expand_fname(Fcn_dir, Fcn_dir);
  146.     expand_fname(Cmap_dir, Cmap_dir);
  147.     sprintf(CM_hostname, "%s", DEFAULT_CM_HOST);
  148.     CM_port = CELLSIM_PORT;
  149. }
  150.  
  151.  
  152. /*
  153.  * Set up the configuration (neighborhood, image-size, etc) based
  154.  * on the command-line arguments.
  155.  */
  156. set_params(argc, argv)
  157.     int     argc;
  158.     char  **argv;
  159. {
  160.     int     i, err, n, tmp;
  161.     char *tmp_str, tmp_str2[80];
  162.  
  163.     for (i = 1; i < argc; i++) {
  164.     switch (argv[i][0]) {
  165.       case 'b':
  166.         err = sscanf(&argv[i][1], "%d", &n);
  167.         if (err != 1 || (n != 64 && n != 128 && n != 256 && n != 512))
  168.         printf("Illegal value %s for b ignored\n", &argv[i][1]);
  169.         else
  170.         B = n;
  171.         break;
  172.       case 'B':    /* run in black&white */
  173.         blackwhite = 1;
  174.         break;
  175.       case 'm':
  176.         NHOOD = NH_MOORE;
  177.         set_states(&argv[i][1]);
  178.         break;
  179.       case 'M':
  180.         NHOOD = NH_MARG;
  181.         set_states(&argv[i][1]);
  182.         break;
  183.       case 'v':
  184.         NHOOD = NH_VONN;
  185.         set_states(&argv[i][1]);
  186.         break;
  187.       case 'l':
  188.         NHOOD = NH_LIN;
  189.         set_states(&argv[i][1]);
  190.         break;
  191.       case 'r':
  192.         err = sscanf(&argv[i][1], "%d", &n);
  193.         if (err != 1 || n <= 0 || n > 3)
  194.         printf("Illegal value %s for R ignored\n", &argv[i][1]);
  195.         else
  196.         R = n;
  197.         break;
  198.       case 'H':
  199.         strcpy(hostname, &argv[i][1]);
  200.         break;
  201.       case 'P':
  202.         err = sscanf(&argv[i][1], "%d", &n);
  203.         if (err != 1)
  204.         printf("Illegal port number %s ignored\n", &argv[i][1]);
  205.         else {
  206.         portnum = n;
  207.         SOCKET_INUSE = TRUE;
  208.         }
  209.         break;
  210.       case 'p':    /* Set CM port */
  211.         err = sscanf(&argv[i][1], "%d", &n);
  212.         if (err != 1)
  213.         printf("Illegal port number %s ignored\n", &argv[i][1]);
  214.         else
  215.         CM_port = n;
  216.         break;
  217.       case 'C':    /* Attach to the Connection Machine */
  218.         if (argv[i][1] != '\0') {
  219.         err = sscanf(&argv[i][1], "%s", tmp_str2);
  220.         if (err == 1)
  221.             strcpy(CM_hostname, tmp_str2);
  222.         }
  223.         break;
  224.       default:
  225.         printf("Unknown option '%s' (#%d) ignored\n", argv[i],i);
  226.         break;
  227.     } /* switch */
  228.     } /* for i */
  229.     if (S != 256) {
  230.     if ((NHOOD == NH_MOORE || (NHOOD == NH_LIN && R == 3)) && S > 4) {
  231.         printf("Maximum of 4 states allowed in given nhood\n");
  232.         S = 4;
  233.     }
  234.     }
  235.     BM1 = B - 1;
  236.     BPL1 = B + 1;
  237.     TBM1 = 2 * B - 1;
  238.     BSQR = B * B;
  239.     BBUF = BSQR + B;
  240.     ASIZE = BBUF + B;
  241.     ABASE = B;
  242.     RCOUNT = B;
  243.  
  244.     if (NHOOD == NH_LIN) {
  245.     ICBASE = BSQR;
  246.     ICSIZE = B;
  247.     DIM = 1;
  248.     } else {
  249.     ICBASE = B;
  250.     ICSIZE = BSQR;
  251.     DIM = 2;
  252.     }
  253.  
  254.     L = (short) (log((double) S) / log((double) 2.0));
  255.     AMASK = S - 1;
  256.  
  257.     switch (NHOOD) {
  258.     case NH_VONN:
  259.     set_params_v();
  260.     break;
  261.     case NH_MOORE:
  262.     set_params_m();
  263.     break;
  264.     case NH_LIN:
  265.     set_params_l();
  266.     break;
  267.     case NH_MARG:
  268.     set_params_marg();
  269.     break;
  270.     }
  271.  
  272.     if (!function) {
  273.     TSIZE = 1 << (L * N);
  274.     ta = (State *)malloc(TSIZE);
  275.     }
  276.  
  277.     if (SOCKET_INUSE)
  278.     init_sock(hostname, portnum);
  279.  
  280.     saved_sx = B;
  281.     saved_sy = B;
  282.     saved_min_val = 0;
  283.     saved_max_val = S-1;
  284.  
  285. } /* set_params */
  286.  
  287.  
  288. /*
  289.  * Set # of states
  290.  */
  291. set_states(str)
  292.     char   *str;
  293. {
  294.     int     n, err;
  295.     if (str[0] == 0)
  296.     return;
  297.     err = sscanf(str, "%d", &n);
  298.     if (err != 1 || (n != 2 && n != 4 && n != 8 && n != 16 && n != 256)) {
  299.     printf("Illegal value %s for S ignored\n", str);
  300.     exit(1);
  301.     }
  302.     else
  303.     S = n;
  304.     if (n == 256)
  305.     function = 1;
  306.     else
  307.     function = 0;
  308. }
  309.  
  310.  
  311. /********************************** USER PROCEDURES ************************/
  312. /*
  313.  * Many of the procedures that may be called up from the control panel
  314.  * are here.  Exceptions are some SunView-specific routines in "cellscr.c",
  315.  * and some Connection-Machine related routines in "cm_cellsim.c" (some
  316.  * of the CM-routines are farther on in this file, as well).
  317.  */
  318.  
  319.  
  320.  
  321. set_proc()
  322. {
  323.     if (invalid_set_pressed())
  324.     return;
  325.     if (setting_sequence)
  326.     add_sequence(set_proc);
  327.     set_just_pressed = 1;
  328. }
  329.  
  330.  
  331. step_proc( /* ARGS UNUSED */ )
  332. {
  333.     int     p, quit = FALSE;
  334.  
  335.     if (invalid_set_pressed())
  336.     return;
  337.     if (setting_sequence)
  338.     add_sequence(step_proc);
  339.     if (function && (!use_CM)) {
  340.     if (update_function == NULL) {
  341.         clear_msg();
  342.         show_msg("No update-function loaded");
  343.         return;
  344.     }
  345.     }
  346.     p = 0;
  347.     while (!quit) {
  348.     if (use_CM) {
  349.         CM_auto_step(1);
  350.         CM_display_image();
  351.         stime++;
  352.         show_time(stime);
  353.     }
  354.     else {
  355.         p = auto_step(1);
  356.         display_image();
  357.     }
  358.     quit = !p;
  359.     if (p)
  360.         quit = undef(p);
  361.     }
  362. }
  363.  
  364.  
  365. skip_proc()
  366. {
  367.     int     p, step;
  368.  
  369.     if (setting_sequence)
  370.     add_sequence(skip_proc);
  371.     if (function && (!use_CM)) {
  372.     if (update_function == NULL) {
  373.         clear_msg();
  374.         show_msg("You have not loaded an update-function");
  375.         return;
  376.     }
  377.     }
  378.     clear_msg();
  379.     if (set_pressed()) {
  380.     if (get_num("Number of steps:", &step, 1, MAXINT, saved_skip))
  381.         return;
  382.     saved_skip = step;
  383.     return;
  384.     }
  385.     else {
  386.     if (saved_skip == INTUNDEF) {
  387.         clear_msg();
  388.         show_msg("Number of steps never set");
  389.         return;
  390.     }
  391.     }
  392.     p = 0;
  393.     if (use_CM) {
  394.     CM_auto_step(saved_skip);
  395.     CM_display_image();
  396.     stime += saved_skip;
  397.     show_time(stime);
  398.     }
  399.     else {
  400.     p = auto_step(saved_skip);
  401.     display_image();
  402.     }
  403.     if (p) {
  404.     clear_msg();
  405.     show_msg("Undefined neighborhood");
  406.     }
  407. }
  408.  
  409.  
  410. screenful_proc()
  411. {
  412.     int     p;
  413.  
  414.     clear_msg();
  415.     if (invalid_set_pressed())
  416.     return;
  417.     if (NHOOD != NH_LIN) {
  418.     show_msg("Not linear nhood");
  419.     return;
  420.     }
  421.     if (setting_sequence)
  422.     add_sequence(screenful_proc);
  423.     if (use_CM) {
  424.     CM_disp_interval = 1;
  425.     CM_auto_screen(B);
  426.     CM_display_image();
  427.     stime += B;
  428.     show_time(stime);
  429.     return;
  430.     }
  431.     else
  432.     p = auto_screen(1);
  433.     display_image();
  434.     if (p) {
  435.     clear_msg();
  436.     show_msg("Undefined neighborhood");
  437.     }
  438. }
  439.  
  440.  
  441. zero_proc()
  442. {
  443.     clear_msg();
  444.     if (invalid_set_pressed())
  445.     return;
  446.     if (setting_sequence)
  447.     add_sequence(zero_proc);
  448.     stime = 0;
  449.     show_time(stime);
  450. }
  451.  
  452.  
  453. clear_proc()
  454. {
  455.     clear_msg();
  456.     if (invalid_set_pressed())
  457.     return;
  458.     if (setting_sequence)
  459.     add_sequence(clear_proc);
  460.     iclear();
  461. }
  462.  
  463.  
  464. learn_proc()
  465. {
  466.     clear_msg();
  467.     if (invalid_set_pressed())
  468.     return;
  469.     if (setting_sequence)
  470.     add_sequence(learn_proc);
  471.     if (function) {
  472.     clear_msg();
  473.     show_msg("Learn is not available with");
  474.     show_msg("256-state rules");
  475.     return;
  476.     }
  477.     learn();
  478. }
  479.  
  480.  
  481.  
  482. run_proc()
  483. {
  484.     int go=TRUE;
  485.  
  486.     if (invalid_set_pressed())
  487.     return;
  488.     if (setting_sequence)
  489.     add_sequence(run_proc);
  490.     if (!use_CM) {
  491.     generic_auto_run(MAXINT, 1);
  492.     return;
  493.     }
  494.     def_CM_get_settings();
  495.     CM_disp_interval = 1;
  496.     CM_run_forever_proc();
  497. }
  498.  
  499.  
  500. run_local_proc()
  501. {
  502.     if (invalid_set_pressed())
  503.     return;
  504.     if (setting_sequence)
  505.     add_sequence(run_local_proc);
  506.     local_run = 1;
  507.     generic_auto_run(MAXINT, 1);
  508.     local_run = 0;
  509. }
  510.  
  511.  
  512. step_local_proc()
  513. {
  514.     if (invalid_set_pressed())
  515.     return;
  516.     if (setting_sequence)
  517.     add_sequence(step_local_proc);
  518.     local_run = 1;
  519.     generic_auto_run(1, 1);
  520.     local_run = 0;
  521. }
  522.  
  523.  
  524. skip_run_proc()
  525. {
  526.     int     d;
  527.  
  528.     clear_msg();
  529.     if (setting_sequence)
  530.     add_sequence(skip_run_proc);
  531.     if (set_pressed()) {
  532.     if (get_num("Display interval:", &d, 0, MAXINT,
  533.             saved_display_interval))
  534.         return;
  535.     saved_display_interval = d;
  536.     return;
  537.     }
  538.     if (saved_display_interval == INTUNDEF) {
  539.     clear_msg();
  540.     show_msg("display interval not set");
  541.     return;
  542.     }
  543.     if (use_CM && (!use_Sun_disp)) {
  544.     def_CM_get_settings();
  545.     CM_disp_interval = saved_display_interval;
  546.     CM_run_forever_proc();
  547.     }
  548.     else
  549.     generic_auto_run(MAXINT, saved_display_interval);
  550. }
  551.  
  552.  
  553.  
  554. bound_run_proc()
  555. {
  556.     int     b;
  557.     clear_msg();
  558.     if (setting_sequence)
  559.     add_sequence(bound_run_proc);
  560.     if (set_pressed()) {
  561.     if (get_num("Number of steps:", &b, 1, MAXINT, saved_num_steps))
  562.         return;
  563.     saved_num_steps = b;
  564.     return;
  565.     }
  566.     if (saved_num_steps == INTUNDEF) {
  567.     clear_msg();
  568.     show_msg("number of steps default");
  569.     show_msg("was never set");
  570.     return;
  571.     }
  572.     def_CM_get_settings();
  573.     if (use_CM && (!use_Sun_disp)) {
  574.     CM_disp_interval = 1;
  575.     CM_auto_screen(saved_num_steps);
  576.     stime += saved_num_steps;
  577.     show_time(stime);
  578.     }
  579.     else
  580.     generic_auto_run(saved_num_steps, 1);
  581. }
  582.  
  583.  
  584. sb_run_proc()
  585. {
  586.     int     d, b;
  587.     clear_msg();
  588.     if (setting_sequence)
  589.     add_sequence(sb_run_proc);
  590.     if (set_pressed()) {
  591.     if (get_num("Display interval:", &d, 0, MAXINT,
  592.             saved_display_interval))
  593.         return;
  594.     saved_display_interval = d;
  595.     if (get_num("Number of steps:", &b, 1, MAXINT, saved_num_steps))
  596.         return;
  597.     saved_num_steps = b;
  598.     return;
  599.     }
  600.     if (saved_num_steps == INTUNDEF) {
  601.     clear_msg();
  602.     show_msg("number of steps default");
  603.     show_msg("was never set");
  604.     return;
  605.     }
  606.     if (saved_display_interval == INTUNDEF) {
  607.     clear_msg();
  608.     show_msg("display interval not set");
  609.     return;
  610.     }
  611.     def_CM_get_settings();
  612.     if (use_CM && (!use_Sun_disp)) {
  613.     CM_disp_interval = saved_display_interval;
  614.     CM_auto_screen(saved_num_steps);
  615.     CM_display_image();
  616.     stime += saved_num_steps;
  617.     show_time(stime);
  618.     }
  619.     else
  620.     generic_auto_run(saved_num_steps, saved_display_interval);
  621. }
  622.  
  623.  
  624. generic_auto_run(bound, disp_int)
  625.     int     bound, disp_int;
  626. {
  627.     int     k, go = TRUE;
  628.     int     stoptime = stime + bound, step = (disp_int ? disp_int : 1);
  629.  
  630.     if ((NHOOD == NH_LIN) && (bound != MAXINT))
  631.     stoptime = stime + bound*(B-1);
  632.     if (function && (!use_CM)) {
  633.     if (update_function == NULL) {
  634.         clear_msg();
  635.         show_msg("No update-function loaded");
  636.         return;
  637.     }
  638.     }
  639.     set_run_mode();
  640.     k = 0;
  641.     if (use_CM && (!local_run)) {
  642.     while (go && stime < stoptime) {
  643.         CM_auto_screen(step);
  644.         stime += step;
  645.         show_time(stime);
  646.         if (disp_int)
  647.         CM_display_image();
  648.         go = !check_button();
  649.     }
  650.     }
  651.     else {
  652.     while (go && stime < stoptime) {
  653.         k = auto_screen(step);
  654.         if (disp_int)
  655.         display_image();
  656.         go = !check_button();
  657.         if (k) {
  658.         clear_msg();
  659.         show_msg("Undefined neighborhood");
  660.         unset_run_mode();
  661.         break;
  662.         }
  663.         switch (stop_on_mode) {
  664.           case NEVER:
  665.         break;
  666.           case NO_CHANGE:
  667.         if (!compare_images()) {
  668.             unset_run_mode();
  669.             return;
  670.         }
  671.         break;
  672.           case ALL_ZERO:
  673.         if (array_is_empty()) {
  674.             unset_run_mode();
  675.             return;
  676.         }
  677.         break;
  678.         }
  679.     }
  680.     }
  681.     if (!disp_int) {
  682.     if (use_CM)
  683.         CM_display_image();
  684.     else
  685.         display_image();
  686.     }
  687.     unset_run_mode();
  688. }
  689.  
  690.  
  691. quick_random_proc()
  692. {
  693.     int i;
  694.     
  695.     /* percentage is set so that all states (including 0) will
  696.      * appear with equal probability */
  697.     clear_msg();
  698.     if (invalid_set_pressed())
  699.     return;
  700.     if (setting_sequence)
  701.     add_sequence(quick_random_proc);
  702.     for (i=0; i<B*B; i++)
  703.     ca[i + ABASE] = random()%S;
  704.     display_image();
  705. }
  706.  
  707.  
  708. general_random_proc()
  709. {
  710.     if (setting_sequence)
  711.     add_sequence(general_random_proc);
  712.     if (set_pressed())
  713.     general_random_set_proc();
  714.     else
  715.     general_random_generate_proc();
  716. }
  717.  
  718.  
  719. general_random_set_proc()
  720. {
  721.     int ox, oy, sx, sy, percent, min_val, max_val, err, org, x, y, index;
  722.     char tmp_str[80];
  723.  
  724.     clear_msg();
  725.     if (get_2num("Origin of area: ", &ox, &oy, 0, B, 0, B, saved_ox, saved_oy))
  726.     return;
  727.     if (get_2num("Size of area: ", &sx, &sy, 0, B-ox, 0, B-oy,
  728.          saved_sx, saved_sy))
  729.     return;
  730.     err = get_num("% of cells to change:", &percent, 0, 100, saved_density);
  731.     if (err)
  732.     return;
  733.     if (get_2num("Min and max vals:", &min_val, &max_val, 0, S-1, 0, S-1,
  734.          saved_min_val, saved_max_val))
  735.     return;
  736.     saved_ox = ox;
  737.     saved_oy = oy;
  738.     saved_sx = sx;
  739.     saved_sy = sy;
  740.     saved_density = percent;
  741.     saved_min_val = min_val;
  742.     saved_max_val = max_val;
  743. }
  744.  
  745.  
  746. general_random_generate_proc()
  747. {
  748.     int ox, oy, sx, sy, percent, min_val, max_val, err, org, x, y, index;
  749.  
  750.     clear_msg();
  751.     if ((saved_max_val == INTUNDEF) || (saved_ox == INTUNDEF)) {
  752.     show_msg("Defaults never set, or cleared");
  753.     show_msg("when configuration changed");
  754.     return;
  755.     }
  756.     if (non_local)
  757.     return;
  758.     show_msg("Generating random image...");
  759.     ox = saved_ox;
  760.     oy = saved_oy;
  761.     sx = saved_sx;
  762.     sy = saved_sy;
  763.     percent = saved_density;
  764.     min_val = saved_min_val;
  765.     max_val = saved_max_val;
  766.     for (y=oy; y < oy+sy; y++)
  767.     for (x=ox; x < ox+sx; x++) {
  768.         if ((random()%100) < percent) {
  769.         index = y*B + x + ABASE;
  770.         ca[index] = (random()%(max_val - min_val + 1)) + min_val;
  771.         }
  772.     }
  773.     show_msg("Done.");
  774.     display_image();
  775. }
  776.  
  777.  
  778. sequence1_proc()
  779. {
  780.     if (set_pressed())
  781.     sequence_set_proc(1);
  782.     else
  783.     sequence_generate_proc(1);
  784. }
  785.  
  786.  
  787. sequence2_proc()
  788. {
  789.     if (set_pressed())
  790.     sequence_set_proc(2);
  791.     else
  792.     sequence_generate_proc(2);
  793. }
  794.  
  795.  
  796. sequence3_proc()
  797. {
  798.     if (set_pressed())
  799.     sequence_set_proc(3);
  800.     else
  801.     sequence_generate_proc(3);
  802. }
  803.  
  804.  
  805. sequence4_proc()
  806. {
  807.     if (set_pressed())
  808.     sequence_set_proc(4);
  809.     else
  810.     sequence_generate_proc(4);
  811. }
  812.  
  813.  
  814. sequence5_proc()
  815. {
  816.     if (set_pressed())
  817.     sequence_set_proc(5);
  818.     else
  819.     sequence_generate_proc(5);
  820. }
  821.  
  822.  
  823. sequence_set_proc(n)
  824. short n;
  825. {
  826.     clear_msg();
  827.     clear_sequence(n);
  828.     if (setting_sequence) {
  829.     show_msg("Invalid -- can't call set sequence");
  830.     show_msg("within itself.  Exiting sequence setting.");
  831.     setting_sequence = 0;
  832.     return;
  833.     }
  834.     setting_sequence = n;
  835.     show_msg("Setting sequence.  Click 'sequence'");
  836.     show_msg("again when done");
  837. }
  838.  
  839.  
  840. sequence_generate_proc(n)
  841. short n;
  842. {
  843.     int i;
  844.     
  845.     clear_msg();
  846.     if (setting_sequence == n) {
  847.     setting_sequence = 0;
  848.     if (sequence_length[n-1] == 0) {
  849.         show_msg("Sequence is empty, not saved");
  850.         return;
  851.     }
  852.     show_msg("Sequence saved.  Hit 'sequence'");
  853.     show_msg("to activate your sequence");
  854.     return;
  855.     }
  856.     if (sequence_length[n-1] == 0) {
  857.     sprintf(buf1, "Sequence %d is empty", n);
  858.     show_msg(buf1);
  859.     return;
  860.     }
  861.     for (i=0; i < sequence_length[n-1]; i++)
  862.     (*(sequence_array[n-1][i]))();
  863.     clear_msg();
  864.     sprintf(buf1,"Done executing sequence #%d",n);
  865.     show_msg(buf1);
  866.     sprintf(buf1, "of length %d", sequence_length[n-1]);
  867.     show_msg(buf1);
  868. }
  869.  
  870.  
  871. horiz_line_proc()
  872. {
  873.     if (invalid_set_pressed())
  874.     return;
  875.     if (setting_sequence)
  876.     add_sequence(horiz_line_proc);
  877.     drawing = HORIZ_LINE;
  878.     clear_msg();
  879.     show_msg("Click left button at one end");
  880. }
  881.  
  882.  
  883. vert_line_proc()
  884. {
  885.     if (invalid_set_pressed())
  886.     return;
  887.     if (setting_sequence)
  888.     add_sequence(vert_line_proc);
  889.     drawing = VERT_LINE;
  890.     clear_msg();
  891.     show_msg("Click left button at one end");
  892. }
  893.  
  894.  
  895. arb_line_proc()
  896. {
  897.     if (invalid_set_pressed())
  898.     return;
  899.     if (setting_sequence)
  900.     add_sequence(arb_line_proc);
  901.     drawing = ARB_LINE;
  902.     clear_msg();
  903.     show_msg("Click left button at start");
  904.     show_msg("of line");
  905. }
  906.  
  907.  
  908. hollow_circ_proc()
  909. {
  910.     if (invalid_set_pressed())
  911.     return;
  912.     if (setting_sequence)
  913.     add_sequence(hollow_circ_proc);
  914.     drawing = HOLLOW_CIRC;
  915.     clear_msg();
  916.     show_msg("Click left button at center");
  917.     show_msg("of circle");
  918. }
  919.  
  920.  
  921. shaded_circ_proc()
  922. {
  923.     int xinc, yinc;
  924.     
  925.     if (setting_sequence)
  926.     add_sequence(shaded_circ_proc);
  927.     if (set_pressed()) {
  928.     clear_msg();
  929.     if (get_2num("X and Y increment: ", &xinc, &yinc, 0, B-1, 0, B-1,
  930.              saved_xinc, saved_yinc))
  931.         return;
  932.     saved_xinc = xinc;
  933.     saved_yinc = yinc;
  934.     return;
  935.     }
  936.     else {
  937.     if ((saved_xinc == INTUNDEF) || (saved_yinc == INTUNDEF)) {
  938.         clear_msg();
  939.         show_msg("Parameters never set for");
  940.         show_msg("shaded circle. Use 'set'.");
  941.         return;
  942.     }
  943.     }
  944.     drawing = SHADED_CIRC;
  945.     clear_msg();
  946.     show_msg("Click left button at center");
  947.     show_msg("of circle");
  948. }
  949.  
  950.  
  951. chdir_proc()
  952. {
  953.     char pathname[MAXPATHLEN];
  954.     
  955.     clear_msg();
  956.     if (!getwd(pathname)) {
  957.     show_msg("Unable to find current");
  958.     show_msg("working directory");
  959.     return;
  960.     }
  961.     get_msg("New directory:", buf1, BUFLEN, pathname);
  962.     if (expand_fname(buf1, buf1))
  963.     return;
  964.     if (stat(buf1, &statbuf)) {
  965.     clear_msg();
  966.     show_msg("Error trying to set directory");
  967.     return;
  968.     }
  969.     if (!((statbuf.st_mode) & S_IFDIR)) {
  970.     clear_msg();
  971.     show_msg("Not a directory");
  972.     return;
  973.     }
  974.     chdir(buf1);
  975.     strcpy(current_working_dir,buf1);
  976.     show_msg("Current working directory is now");
  977.     show_msg(buf1);
  978. }
  979.  
  980. /**************** magnify routines *******************/
  981.  
  982.  
  983. magnify_proc()
  984. {
  985.     int     m, err;
  986.     char    str[BUFLEN];
  987.     
  988.     clear_msg();
  989.     if (invalid_set_pressed())
  990.     return;
  991.     if (setting_sequence)
  992.     add_sequence(magnify_proc);
  993.     if (closeup) {
  994.     show_msg("Not allowed in closeup mode");
  995.     return;
  996.     }
  997.     sprintf(str, "Zoom factor (currently %d):", mag);
  998.     err = get_num(str, &m, 1, (int) MAXSIZE / side, mag);
  999.     if (err)
  1000.     return;
  1001.     set_mag(m);
  1002. }
  1003.  
  1004.  
  1005. zoom_in_proc()
  1006. {
  1007.     int m = (int) MAXSIZE / side;    /* maximum magnification */
  1008.  
  1009.     clear_msg();
  1010.     if (invalid_set_pressed())
  1011.     return;
  1012.     if (setting_sequence)
  1013.     add_sequence(zoom_in_proc);
  1014.     if (closeup) {
  1015.     clear_msg();
  1016.     show_msg("Can't use zoom in closeup");
  1017.     return;
  1018.     }
  1019.     if (mag < m) {
  1020.     mag++;
  1021.     set_mag(mag);
  1022.     }
  1023. }
  1024.  
  1025.  
  1026. zoom_out_proc()
  1027. {
  1028.     clear_msg();
  1029.     if (invalid_set_pressed())
  1030.     return;
  1031.     if (setting_sequence)
  1032.     add_sequence(zoom_out_proc);
  1033.     if (closeup) {
  1034.     clear_msg();
  1035.     show_msg("Can't use zoom in closeup");
  1036.     return;
  1037.     }
  1038.     if (mag > 1) {
  1039.     mag--;
  1040.     set_mag(mag);
  1041.     }
  1042. }
  1043.  
  1044.  
  1045. zoom_proc()
  1046. {
  1047.     int     m = (int) MAXSIZE / side;    /* maximum magnification */
  1048.  
  1049.     clear_msg();
  1050.     if (invalid_set_pressed())
  1051.     return;
  1052.     if (setting_sequence)
  1053.     add_sequence(zoom_proc);
  1054.     if (closeup) {
  1055.     clear_msg();
  1056.     show_msg("Can't use zoom in closeup");
  1057.     return;
  1058.     }
  1059.     if (mag < m)
  1060.     set_mag(m);
  1061.     else
  1062.     set_mag(1);
  1063. }
  1064.  
  1065.  
  1066. closeup_proc()
  1067. {
  1068.     clear_msg();
  1069.     if (invalid_set_pressed())
  1070.     return;
  1071.     if (setting_sequence)
  1072.     add_sequence(closeup_proc);
  1073.     if (closeup = !closeup) {
  1074.     side = 32;
  1075.     saved_mag_factor = mag;
  1076.     mag = MAXSIZE / 32;
  1077.     if (NHOOD == NH_LIN) {
  1078.         xstart = (B - 32) / 2;
  1079.         ystart = B - 32;
  1080.     }
  1081.     else
  1082.         xstart = ystart = (B - 32) / 2;
  1083.     display_image();
  1084.     } else {
  1085.     side = B;
  1086.     mag = saved_mag_factor;
  1087.     xstart = ystart = 0;
  1088.     set_mag(mag);
  1089.     }
  1090. }
  1091.  
  1092.  
  1093. /********************** display routines ************************/
  1094.  
  1095. shift_proc()
  1096. {
  1097.     int     n;
  1098.     char    str[BUFLEN];
  1099.     clear_msg();
  1100.     sprintf(str, "Distance (currently %d):", shift_dist);
  1101.     if (get_num(str, &n, 1, B / 2, shift_dist))
  1102.     return;
  1103.     shift_dist = n;
  1104. }
  1105.  
  1106.  
  1107. right_proc()
  1108. {
  1109.     hshift_data(shift_dist);
  1110.     display_image();
  1111. }
  1112.  
  1113.  
  1114. left_proc()
  1115. {
  1116.     hshift_data(-shift_dist);
  1117.     display_image();
  1118. }
  1119.  
  1120.  
  1121. up_proc()
  1122. {
  1123.     vshift_data(-shift_dist);
  1124.     display_image();
  1125. }
  1126.  
  1127.  
  1128. down_proc()
  1129. {
  1130.     vshift_data(shift_dist);
  1131.     display_image();
  1132. }
  1133.  
  1134.  
  1135. /*********************** IMAGE ROUTINES ********************/
  1136.  
  1137. isave_proc()
  1138. {
  1139.     if (save_images_compressed == TRUE)
  1140.     isave_compressed();
  1141.     else
  1142.     isave();
  1143. }
  1144.  
  1145.  
  1146. isave()
  1147. {                    /* save current image */
  1148.     State  *ap;
  1149.     int dumpsize;
  1150.     
  1151.     clear_msg();
  1152.     if (invalid_set_pressed())
  1153.     return;
  1154.     if (setting_sequence)
  1155.     add_sequence(isave);
  1156.     get_msg("Save image file:", buf1, BUFLEN, saved_image_file);
  1157.     if (buf1[0] == NULL)
  1158.     return;
  1159.     if ((buf1[0] == '/') || (!strncmp(buf1, "./", 2)) || (!strncmp(buf1, "../", 3)) || (!save_in_image_dir))
  1160.     ;
  1161.     else {
  1162.     strcpy(buf2, buf1);
  1163.     sprintf(buf1, "%s/%s", Image_dir, buf2);
  1164.     }
  1165.     if (expand_fname(buf1, buf1))
  1166.     return;
  1167.     strcpy(saved_image_file,buf1);
  1168.     if ((fp = fopen(buf1, "r")) != NULL) {
  1169.     if (!confirm_overwrite()) {
  1170.         fclose(fp);
  1171.         return;
  1172.     }
  1173.     fclose(fp);
  1174.     }
  1175.     fp = fopen(saved_image_file, "w");
  1176.     if (fp == NULL) {
  1177.     clear_msg();
  1178.     show_msg("Unable to open file");
  1179.     show_msg(sys_errlist[errno]);
  1180.     return;
  1181.     }
  1182.     if (use_2D_always) {
  1183.     ap = ca + B;
  1184.     dumpsize = BSQR;
  1185.     }
  1186.     else {
  1187.     ap = ca + ICBASE;
  1188.     dumpsize = ICSIZE;
  1189.     }
  1190.     fwrite(ap, sizeof(*ap), dumpsize, fp);
  1191.     fclose(fp);
  1192.     sprintf(buf1, "%s saved",saved_image_file);
  1193.     show_msg(buf1);
  1194. }
  1195.  
  1196.  
  1197.  
  1198. isave_CAM6()
  1199. {                    /* save image in CAM6 format */
  1200.     State *ap, *save_ap;
  1201.     unsigned char byteval;
  1202.     int i, j, plane;
  1203.  
  1204.     clear_msg();
  1205.     if (invalid_set_pressed())
  1206.     return;
  1207.     if (setting_sequence)
  1208.     add_sequence(isave_CAM6);
  1209.     if (B == 512) {
  1210.     clear_msg();
  1211.     show_msg("Can't save 512-size image");
  1212.     show_msg("in CAM format yet");
  1213.     return;
  1214.     }
  1215.     ap = ca + ICBASE;
  1216.     save_ap = ap;
  1217.     get_msg("Save CAM6 file:", buf1, BUFLEN, saved_image_file);
  1218.     if (buf1[0] == NULL)
  1219.     return;
  1220.     if ((buf1[0] == '/') || (!strncmp(buf1, "./", 2)) || (!strncmp(buf1, "../", 3)) || (!save_in_image_dir))
  1221.     ;
  1222.     else {
  1223.     strcpy(buf2, buf1);
  1224.     sprintf(buf1, "%s/%s", Image_dir, buf2);
  1225.     }
  1226.     if (expand_fname(buf1, buf1))
  1227.     return;
  1228.     strcpy(saved_image_file,buf1);
  1229.     if ((fp = fopen(buf1, "r")) != NULL) {
  1230.     if (!confirm_overwrite()) {
  1231.         fclose(fp);
  1232.         return;
  1233.     }
  1234.     }
  1235.     if (save_images_compressed == TRUE) {
  1236.     show_msg("Saving uncompressed -- can't");
  1237.     show_msg("save compressed CAM6 images yet");
  1238.     }
  1239.     fp = fopen(saved_image_file, "w");
  1240.     for (plane = 0; plane < L; plane++) {
  1241.     for (i=0; i < 65536; ) {
  1242.         byteval = 0;
  1243.         if (((i%256) >= B) || ((i / 256) >= B)) {
  1244.         putc(0, fp);
  1245.         i += 8;
  1246.         }
  1247.         else {
  1248.         for (j=0; j < 8; j++) {
  1249.             byteval = (byteval << 1) | ((ap[7-j] & (1<<plane)) >> plane);
  1250.             i++;
  1251.         }
  1252.         putc(byteval,fp);
  1253.         ap += 8;
  1254.         }
  1255.     }
  1256.     ap = save_ap;
  1257.     }
  1258.     fclose(fp);
  1259.     sprintf(buf1, "%s saved",saved_image_file);
  1260.     show_msg(buf1);
  1261. }
  1262.         
  1263.     
  1264. isave_compressed()
  1265. {                    /* save current image */
  1266.     State  *ap;
  1267.     int err;
  1268.     FILE *fp;
  1269.     int dumpsize;
  1270.  
  1271.     clear_msg();
  1272.     if (invalid_set_pressed())
  1273.     return;
  1274.     if (setting_sequence)
  1275.     add_sequence(isave_compressed);
  1276.     get_msg("Save image file:", buf1, BUFLEN, saved_image_file);
  1277.     if (buf1[0] == NULL)
  1278.     return;
  1279.     if ((buf1[0] == '/') || (!strncmp(buf1, "./", 2)) || (!strncmp(buf1, "../", 3)) || (!save_in_image_dir))
  1280.     ;
  1281.     else {
  1282.     strcpy(buf2, buf1);
  1283.     sprintf(buf1, "%s/%s", Image_dir, buf2);
  1284.     }
  1285.     if (expand_fname(buf1, buf1))
  1286.     return;
  1287.     if (strcmp(&buf1[strlen(buf1)-2],".Z"))
  1288.     strcat(buf1, ".Z");
  1289.     strcpy(saved_image_file,buf1);
  1290.     if ((fp = fopen(buf1, "r")) != NULL) {
  1291.     if (!confirm_overwrite()) {
  1292.         fclose(fp);
  1293.         return;
  1294.     }
  1295.     }
  1296.     sprintf(buf2,"compress > %s",saved_image_file);
  1297.     if ((fp = popen(buf2, "w")) == NULL) {
  1298.     show_msg("Error opening pipe");
  1299.     return;
  1300.     }
  1301.     if (use_2D_always) {
  1302.     ap = ca + B;
  1303.     dumpsize = BSQR;
  1304.     }
  1305.     else {
  1306.     ap = ca + ICBASE;
  1307.     dumpsize = ICSIZE;
  1308.     }
  1309.     fwrite(ap, sizeof(*ap), dumpsize, fp);
  1310.     err = pclose(fp);
  1311.     if (err) {
  1312.     sprintf(buf1,"pclose returned %d",err);
  1313.     show_msg(buf1);
  1314.     return;
  1315.     }
  1316.     sprintf(buf1, "%s saved",saved_image_file);
  1317.     show_msg(buf1);
  1318. }
  1319.  
  1320.  
  1321. isave_resize()
  1322. {                /* save image into file of different size */
  1323.     int     s, dx, dy, err;
  1324.  
  1325.     clear_msg();
  1326.     if (invalid_set_pressed())
  1327.     return;
  1328.     if (setting_sequence)
  1329.     add_sequence(isave_resize);
  1330.     get_msg("Save image file:", buf1, BUFLEN, saved_image_file);
  1331.     if (buf1[0] == NULL)
  1332.     return;
  1333.     if ((buf1[0] == '/') || (!strncmp(buf1, "./", 2)) ||
  1334.     (!strncmp(buf1, "../", 3)) || (!save_in_image_dir))
  1335.     ;
  1336.     else {
  1337.     strcpy(buf2, buf1);
  1338.     sprintf(buf1, "%s/%s", Image_dir, buf2);
  1339.     }
  1340.     if (expand_fname(buf1, buf1))
  1341.     return;
  1342.     strcpy(saved_image_file,buf1);
  1343.     if ((fp = fopen(buf1, "r")) != NULL) {
  1344.     if (!confirm_overwrite()) {
  1345.         fclose(fp);
  1346.         return;
  1347.     }
  1348.     }
  1349.     if (save_images_compressed == TRUE) {
  1350.     show_msg("Saving uncompressed -- can't");
  1351.     show_msg("save/reside compressed yet");
  1352.     }
  1353.     fp = fopen(saved_image_file, "w");
  1354.     if (get_num("Side length:", &s, 1, 512, saved_side_length))
  1355.     return;
  1356.     saved_side_length = s;
  1357.     if (DIM == 1) {
  1358.     get_msg("X offset:", buf1, BUFLEN, saved_x_offset);
  1359.     strcpy(saved_x_offset,buf1);
  1360.     err = sscanf(buf1, "%d", &dx);
  1361.     } else {
  1362.     get_msg("X, Y offsets:", buf1, BUFLEN, saved_y_offset);
  1363.     strcpy(saved_y_offset,buf1);
  1364.     err = sscanf(buf1, "%d%d", &dx, &dy);
  1365.     }
  1366.     if (err != DIM && buf1[0] != NULL) {
  1367.     show_msg("Invalid entry");
  1368.     return;
  1369.     }
  1370.     if (buf1[0] == NULL)
  1371.     dx = dy = abs((B - s) / 2);
  1372.     save_resize_data(fp, s, dx, dy);
  1373.     fclose(fp);
  1374.     display_image();
  1375.  
  1376. }
  1377.  
  1378.  
  1379. iload()
  1380. {                    /* load an image into ca */
  1381.     clear_msg();
  1382.     if (invalid_set_pressed())
  1383.     return;
  1384.     if (setting_sequence)
  1385.     add_sequence(iload);
  1386.     get_msg("Load image file:", buf1, BUFLEN, saved_image_file);
  1387.     if (buf1[0] == NULL)
  1388.     return;
  1389.     if (expand_fname(buf1, buf1))
  1390.     return;
  1391.     strcpy(saved_image_file,buf1);
  1392.     if (!strcmp(&buf1[strlen(buf1)-2],".Z")) {
  1393.     iload_compressed(buf1);
  1394.     return;
  1395.     }
  1396.     if (!(fp = fopen(buf1, "r"))) {
  1397.     sprintf(buf2,"%s/%s",Image_dir,buf1);
  1398.     if (!(fp = fopen(buf2, "r"))) {
  1399.         /* see if a compressed version is around */
  1400.         iload_compressed(buf1);
  1401.         return;
  1402.     }
  1403.     }
  1404.     if (auto_image_change)
  1405.     change_image_size_file(buf1);
  1406.     load_data(fp);
  1407.     fclose(fp);
  1408.     display_image();
  1409.  
  1410. }
  1411.  
  1412.  
  1413. iload_CAM6()
  1414. {                    /* load image in CAM6 format */
  1415.     State *ap, *save_ap;
  1416.     unsigned char byteval;
  1417.     int i, j, plane;
  1418.  
  1419.     clear_msg();
  1420.     if (invalid_set_pressed())
  1421.     return;
  1422.     if (setting_sequence)
  1423.     add_sequence(iload_CAM6);
  1424.     ap = ca + ICBASE;
  1425.     save_ap = ap;
  1426.     for (i=0; i<BSQR; i++)
  1427.     ap[i] = 0;
  1428.     get_msg("Load CAM6 image file:", buf1, BUFLEN, saved_image_file);
  1429.     if (buf1[0] == NULL)
  1430.     return;
  1431.     if (expand_fname(buf1, buf1))
  1432.     return;
  1433.     strcpy(saved_image_file,buf1);
  1434.     if (!(fp = fopen(buf1, "r"))) {
  1435.     sprintf(buf2, "%s/%s", Image_dir, buf1);
  1436.     if (!(fp = fopen(buf2, "r"))) {
  1437.         /* see if a compressed version is around */
  1438.         iload_CAM6_compressed(buf1);
  1439.         return;
  1440.     }
  1441.     }
  1442.     if (auto_image_change)
  1443.     change_image_size_file(buf1);
  1444.     for (plane = 0; plane < L; plane++) {
  1445.     for (i=0; i < 65536; ) {
  1446.         byteval = 0;
  1447.         if (((i%256) >= B) || ((i / 256) >= B)) {
  1448.         (void) getc(fp);
  1449.         i += 8;
  1450.         }
  1451.         else {
  1452.         byteval = getc(fp);
  1453.         for (j=0; j < 8; j++) {
  1454.             ap[0] |= (byteval & 1) << plane;
  1455.             byteval >>= 1;
  1456.             i++;
  1457.             ap++;
  1458.         }
  1459.         }
  1460.     }
  1461.     ap = save_ap;
  1462.     }
  1463.     fclose(fp);
  1464.     display_image();
  1465. }
  1466.  
  1467.  
  1468. iload_CAM6_compressed(name)
  1469. char *name;
  1470. {
  1471.     clear_msg();
  1472.     show_msg("Couldn't find uncompressed CAM6 image,");
  1473.     show_msg("and can't load compressed CAM6 images yet");
  1474.     return;
  1475. }
  1476.  
  1477.  
  1478. iload_compressed(name)
  1479. char *name;
  1480. {                    /* load a compressed image into ca */
  1481.     int err;
  1482.     
  1483.     strcpy(buf1,name);
  1484.     if (buf1[0] == NULL)
  1485.     return;
  1486.     if (strcmp(&buf1[strlen(buf1)-2],".Z"))
  1487.     strcat(buf1,".Z");
  1488.     if (!stat(buf1,&statbuf)) {
  1489.     sprintf(buf2,"uncompress -c %s",buf1);
  1490.     if (!(fp = popen(buf2, "r"))) {
  1491.         show_msg("Error trying to open pipe");
  1492.         return;
  1493.     }
  1494.     }
  1495.     else {
  1496.     sprintf(buf2,"%s/%s",Image_dir,buf1);
  1497.     if (stat(buf2,&statbuf)) {
  1498.         show_msg("No such image file");
  1499.         return;
  1500.     }
  1501.     sprintf(buf2,"uncompress -c %s/%s",Image_dir,buf1);
  1502.     if (!(fp = popen(buf2,"r"))) {
  1503.         show_msg("Error trying to open pipe");
  1504.         return;
  1505.     }
  1506.     }
  1507.     if (auto_image_change)
  1508.     change_image_size_file(buf1);
  1509.     load_data(fp);
  1510.     err = pclose(fp);
  1511.     if (err) {
  1512.     sprintf(buf1,"pclose returned %d",err);
  1513.     show_msg(buf1);
  1514.     return;
  1515.     }
  1516.     display_image();
  1517.  
  1518. }
  1519.  
  1520.  
  1521. iload_resize()
  1522. {                    /* load an image of different size */
  1523.     int     s, dx, dy, err;
  1524.     char fname[80];
  1525.  
  1526.     clear_msg();
  1527.     if (invalid_set_pressed())
  1528.     return;
  1529.     if (setting_sequence)
  1530.     add_sequence(iload_resize);
  1531.     get_msg("Load image file:", buf1, BUFLEN, saved_image_file);
  1532.     if (buf1[0] == NULL)
  1533.     return;
  1534.     if (expand_fname(buf1, buf1))
  1535.     return;
  1536.     strcpy(fname,buf1);
  1537.     strcpy(saved_image_file,buf1);
  1538.     if (!(fp = fopen(buf1, "r"))) {
  1539.     sprintf(buf2,"%s/%s",Image_dir,buf1);
  1540.     if (!(fp = fopen(buf2,"r"))) {
  1541.         iload_resize_compressed(buf1);
  1542.         return;
  1543.     }
  1544.     }
  1545.     if (get_num("Side length:", &s, 1, 512, saved_side_length))
  1546.     return;
  1547.     saved_side_length = s;
  1548.     if (DIM == 1) {
  1549.     get_msg("X offset:", buf1, BUFLEN, saved_x_offset);
  1550.     strcpy(saved_x_offset,buf1);
  1551.     err = sscanf(buf1, "%d", &dx);
  1552.     } else {
  1553.     get_msg("X, Y offsets:", buf1, BUFLEN, saved_y_offset);
  1554.     strcpy(saved_y_offset,buf1);
  1555.     err = sscanf(buf1, "%d%d", &dx, &dy);
  1556.     }
  1557.     if (err != DIM && buf1[0] != NULL) {
  1558.     show_msg("Invalid entry");
  1559.     return;
  1560.     }
  1561.     if (buf1[0] == NULL)
  1562.     dx = dy = abs((B - s) / 2);
  1563.     load_resize_data(fp, s, dx, dy);
  1564.     fclose(fp);
  1565.     display_image();
  1566.  
  1567. }
  1568.  
  1569.  
  1570. iload_resize_compressed(name)
  1571. char *name;
  1572. {                    /* load an image of different size */
  1573.     int     s, dx, dy, err;
  1574.     char fname[80];
  1575.  
  1576.     clear_msg();
  1577.     strcpy(buf1,name);
  1578.     if (buf1[0] == NULL)
  1579.     return;
  1580.     strcpy(fname,buf1);
  1581.     if (strcmp(&buf1[strlen(buf1)-2],".Z"))
  1582.     strcat(buf1,".Z");
  1583.     if (!stat(buf1,&statbuf)) {
  1584.     sprintf(buf2,"uncompress -c %s",buf1);
  1585.     if (!(fp = popen(buf2,"r"))) {
  1586.         show_msg("Error trying to open pipe");
  1587.         return;
  1588.     }
  1589.     }
  1590.     else {
  1591.     sprintf(buf2,"%s/%s",Image_dir,buf1);
  1592.     if (stat(buf2,&statbuf)) {
  1593.         show_msg("No such image file");
  1594.         return;
  1595.     }
  1596.     sprintf(buf2,"uncompress -c %s/%s",Image_dir,buf1);
  1597.     if (!(fp = popen(buf2,"r"))) {
  1598.         show_msg("Error trying to open pipe");
  1599.         return;
  1600.     }
  1601.     }
  1602.     if (get_num("Side length:", &s, 1, 512, saved_side_length))
  1603.     return;
  1604.     saved_side_length = s;
  1605.     if (DIM == 1) {
  1606.     get_msg("X offset:", buf1, BUFLEN, saved_x_offset);
  1607.     strcpy(saved_x_offset,buf1);
  1608.     err = sscanf(buf1, "%d", &dx);
  1609.     } else {
  1610.     get_msg("X, Y offsets:", buf1, BUFLEN, saved_y_offset);
  1611.     strcpy(saved_y_offset,buf1);
  1612.     err = sscanf(buf1, "%d%d", &dx, &dy);
  1613.     }
  1614.     if (err != DIM && buf1[0] != NULL) {
  1615.     show_msg("Invalid entry");
  1616.     return;
  1617.     }
  1618.     if (buf1[0] == NULL)
  1619.     dx = dy = abs((B - s) / 2);
  1620.     load_resize_data(fp, s, dx, dy);
  1621.     err = pclose(fp);
  1622.     if (err) {
  1623.     sprintf(buf1,"pclose returned %d",err);
  1624.     show_msg(buf1);
  1625.     }
  1626.     display_image();
  1627.  
  1628. }
  1629.  
  1630.  
  1631. ienter()
  1632. {                /* enter initial config. from keyboard */
  1633.     int     i, l, base;
  1634.     
  1635.     clear_msg();
  1636.     if (setting_sequence)
  1637.     add_sequence(ienter);
  1638.     if (set_pressed()) {
  1639.     get_msg("Enter string:", buf1, BUFLEN, saved_ienter_str);
  1640.     strcpy(saved_ienter_str, buf1);
  1641.     return;
  1642.     }
  1643.     strcpy(buf1, saved_ienter_str);
  1644.     l = strlen(buf1);
  1645.     for (i = 0; i < l; i++)
  1646.     if (!is_state(buf1[i])) {
  1647.         show_msg("Invalid entry");
  1648.         return;
  1649.     }
  1650.     clear_data();
  1651.     base = ICBASE + (ICSIZE - l) / 2;
  1652.     if (DIM == 2)
  1653.     base -= B / 2;
  1654.     for (i = 0; i < l; i++)
  1655.     ca[base + i] = to_state(buf1[i]);
  1656.     display_image();
  1657. }
  1658.  
  1659.  
  1660. iclear()
  1661. {                    /* clear current array ca */
  1662.     clear_msg();
  1663.     if (invalid_set_pressed())
  1664.     return;
  1665.     if (setting_sequence)
  1666.     add_sequence(iclear);
  1667.     clear_data();
  1668.     display_image();
  1669. }
  1670.  
  1671.  
  1672. iswap()
  1673. {                    /* swap current and image arrays */
  1674.     clear_msg();
  1675.     if (invalid_set_pressed())
  1676.     return;
  1677.     if (setting_sequence)
  1678.     add_sequence(iswap);
  1679.     swap_data();
  1680.     display_image();
  1681. }
  1682.  
  1683.  
  1684. icopy()
  1685. {                    /* copy current array to image array */
  1686.     clear_msg();
  1687.     if (invalid_set_pressed())
  1688.     return;
  1689.     if (setting_sequence)
  1690.     add_sequence(icopy);
  1691.     copy_data();
  1692.     clear_msg();
  1693.     show_msg("Image copied");
  1694. }
  1695.  
  1696.  
  1697. iinvert()
  1698. {                    /* bitwise invert of current array */
  1699.     clear_msg();
  1700.     if (invalid_set_pressed())
  1701.     return;
  1702.     if (setting_sequence)
  1703.     add_sequence(iinvert);
  1704.     invert_data();
  1705.     display_image();
  1706. }
  1707.  
  1708.  
  1709. CM_load_image_proc()
  1710. {
  1711.     char fname[128];
  1712.     
  1713.     clear_msg();
  1714.     if (invalid_set_pressed())
  1715.     return;
  1716.     if (setting_sequence)
  1717.     add_sequence(CM_load_image_proc);
  1718.     get_msg("Filename:", buf1, 128, saved_image_file);
  1719.     if (buf1[0] == 0)
  1720.     return;
  1721.     strcpy(saved_image_file, buf1);
  1722.     strcpy(fname, buf1);
  1723.     CM_load_image(fname);
  1724. }
  1725.  
  1726.  
  1727. CM_change_delay_proc()
  1728. {
  1729.     int new_delay;
  1730.  
  1731.     clear_msg();
  1732.     if (invalid_set_pressed())
  1733.     return;
  1734.     if (setting_sequence)
  1735.     add_sequence(CM_change_delay_proc);
  1736.     if (get_num("New delay: ", &new_delay, 0, 1000000, CM_delay))
  1737.     return;
  1738.     CM_delay = new_delay;
  1739.     CM_send_delay();
  1740. }
  1741.  
  1742.  
  1743. CM_quick_random_proc()
  1744. {
  1745.     clear_msg();
  1746.     if (invalid_set_pressed())
  1747.     return;
  1748.     if (setting_sequence)
  1749.     add_sequence(CM_quick_random_proc);
  1750.     CM_quick_random();
  1751. }
  1752.  
  1753.  
  1754. CM_general_random_proc()
  1755. {
  1756.     clear_msg();
  1757.     if (set_pressed())
  1758.     CM_general_random_set_proc();
  1759.     else
  1760.     CM_general_random_generate_proc();
  1761. }
  1762.  
  1763.  
  1764. CM_general_random_set_proc()
  1765. {
  1766.     if (setting_sequence)
  1767.     add_sequence(CM_general_random_set_proc);
  1768.     general_random_set_proc();
  1769. }
  1770.  
  1771.  
  1772. CM_general_random_generate_proc()
  1773. {
  1774.     clear_msg();
  1775.     if (setting_sequence)
  1776.     add_sequence(CM_general_random_generate_proc);
  1777.     if ((saved_max_val == INTUNDEF) || (saved_ox == INTUNDEF)) {
  1778.     show_msg("Defaults never set, or cleared");
  1779.     show_msg("when configuration changed");
  1780.     return;
  1781.     }
  1782.     CM_general_random();
  1783. }
  1784.  
  1785.  
  1786.     
  1787.     
  1788.  
  1789. /***************** LOOKUP TABLE (LT) ROUTINES ********************/
  1790.  
  1791.  
  1792.  
  1793. tsave_proc()
  1794. {
  1795.     if (save_LT_compressed)
  1796.     tsave_compressed();
  1797.     else
  1798.     tsave();
  1799. }
  1800.  
  1801.  
  1802. tsave()
  1803. {                    /* save a t-table */
  1804.     clear_msg();
  1805.     if (invalid_set_pressed())
  1806.     return;
  1807.     if (function) {
  1808.     show_msg("Can't save when using");
  1809.     show_msg("256 states.");
  1810.     return;
  1811.     }
  1812.     if (setting_sequence)
  1813.     add_sequence(tsave);
  1814.     get_msg("Save LT file:", buf1, BUFLEN, saved_rule_file);
  1815.     if (buf1[0] == NULL) {
  1816.     show_msg("");
  1817.     return;
  1818.     }
  1819.     if ((buf1[0] == '/') || (!strncmp(buf1, "./", 2)) || (!strncmp(buf1, "../", 3)) || (!save_in_LT_dir))
  1820.     ;
  1821.     else {
  1822.     strcpy(buf2, buf1);
  1823.     sprintf(buf1, "%s/%s", Table_dir, buf2);
  1824.     }
  1825.     if (expand_fname(buf1, buf1))
  1826.     return;
  1827.     strcpy(saved_rule_file, buf1);
  1828.     if ((fp = fopen(buf1, "r")) != NULL) {
  1829.     if (!confirm_overwrite()) {
  1830.         fclose(fp);
  1831.         return;
  1832.     }
  1833.     }
  1834.     fp = fopen(saved_rule_file, "w");
  1835.     if (fp == NULL) {
  1836.     clear_msg();
  1837.     show_msg("Unable to open file");
  1838.     show_msg(sys_errlist[errno]);
  1839.     return;
  1840.     }
  1841.     fwrite(ta, sizeof(*ta), TSIZE, fp);
  1842.     fclose(fp);
  1843.     show_rule(buf1);
  1844.     sprintf(buf1, "%s saved",saved_rule_file);
  1845.     show_msg(buf1);
  1846. }
  1847.  
  1848.  
  1849.  
  1850. tsave_compressed()
  1851. {                    /* save a t-table compressed */
  1852.     int err;
  1853.     
  1854.     clear_msg();
  1855.     if (invalid_set_pressed())
  1856.     return;
  1857.     if (setting_sequence)
  1858.     add_sequence(tsave_compressed);
  1859.     get_msg("Save LT file:", buf1, BUFLEN, saved_rule_file);
  1860.     if (buf1[0] == NULL) {
  1861.     show_msg("");
  1862.     return;
  1863.     }
  1864.     if ((buf1[0] == '/') || (!strncmp(buf1, "./", 2)) || (!strncmp(buf1, "../", 3)) || (!save_in_LT_dir))
  1865.     ;
  1866.     else {
  1867.     strcpy(buf2, buf1);
  1868.     sprintf(buf1, "%s/%s", Table_dir, buf2);
  1869.     }
  1870.     if (expand_fname(buf1, buf1))
  1871.     return;
  1872.     if (strcmp(&buf1[strlen(buf1)-2],".Z"))
  1873.     strcat(buf1,".Z");
  1874.     strcpy(saved_rule_file, buf1);
  1875.     if ((fp = fopen(buf1, "r")) != NULL) {
  1876.     if (!confirm_overwrite()) {
  1877.         fclose(fp);
  1878.         return;
  1879.     }
  1880.     }
  1881.     fclose(fp);
  1882.     sprintf(buf2,"compress > %s",saved_rule_file);
  1883.     fp = popen(buf2, "w");
  1884.     fwrite(ta, sizeof(*ta), TSIZE, fp);
  1885.     err = pclose(fp);
  1886.     if (err) {
  1887.     sprintf(buf1,"pclose returned %d",err);
  1888.     show_msg(buf1);
  1889.     return;
  1890.     }
  1891.     show_rule(saved_rule_file);
  1892.     sprintf(buf1, "%s saved",saved_rule_file);
  1893.     show_msg(buf1);
  1894. }
  1895.  
  1896.  
  1897. edit_parm1()
  1898. {
  1899.     int tmp_int;
  1900.     
  1901.     clear_msg();
  1902.     if (invalid_set_pressed())
  1903.     return;
  1904.     if (setting_sequence)
  1905.     add_sequence(edit_parm1);
  1906.     if (get_num("Parm1 value:", &tmp_int, 0, 255, parm1))
  1907.     return;
  1908.     parm1 = tmp_int;
  1909. }
  1910.  
  1911.  
  1912.  
  1913. edit_parm2()
  1914. {
  1915.     int tmp_int;
  1916.     
  1917.     clear_msg();
  1918.     if (invalid_set_pressed())
  1919.     return;
  1920.     if (setting_sequence)
  1921.     add_sequence(edit_parm2);
  1922.     if (get_num("Parm2 value:", &tmp_int, 0, 255, parm2))
  1923.     return;
  1924.     parm2 = tmp_int;
  1925. }
  1926.  
  1927.  
  1928.  
  1929. load_rule()    /* Load a rule (an LT or obj-code file) */
  1930. {
  1931.     char objname[80], fname[128];
  1932.     
  1933.     
  1934.     clear_msg();
  1935.     if (invalid_set_pressed())
  1936.     return;
  1937.     if (setting_sequence)
  1938.     add_sequence(load_rule);
  1939.     get_msg("Load rule:", buf1, BUFLEN, saved_rule_file);
  1940.     if (buf1[0] == NULL)
  1941.     return;
  1942.     if (expand_fname(buf1, buf1))
  1943.     return;
  1944.     strcpy(saved_rule_file, buf1);
  1945.     if (!strcmp(&buf1[strlen(buf1)-2],".Z")) {
  1946.     tload_compressed(buf1);
  1947.     return;
  1948.     }
  1949.     strcpy(fname,buf1);
  1950.     if (auto_nhood_change)
  1951.     change_stuff_file(buf1);
  1952.     strcpy(buf1,fname);
  1953.     if (!(fp = fopen(buf1, "r"))) {
  1954.     if (function)
  1955.         sprintf(buf2, "%s/%s", Fcn_dir, buf1);
  1956.     else
  1957.         sprintf(buf2,"%s/%s",Table_dir,buf1);
  1958.     if (!(fp = fopen(buf2, "r"))) {
  1959.         /* try compressed version */
  1960.         tload_compressed(buf1);
  1961.         return;
  1962.     }
  1963.     }
  1964.     if (function) {
  1965.     sprintf(objname, "%s", buf1);
  1966.     if (stat(buf1,&statbuf)) {
  1967.         if (stat(buf2, &statbuf)) {
  1968.         show_msg("Could not open file");
  1969.         return;
  1970.         }
  1971.         sprintf(objname, "%s", buf2);
  1972.     }
  1973.     show_msg("Loading/linking file...");
  1974.     update_function = NULL;
  1975.     before_function = NULL;
  1976.     after_function = NULL;
  1977.     initialization_function = (void_func_ptr) dynamic_load(argv0, objname);
  1978.     initialization_function();
  1979.     }
  1980.     else {
  1981.     update_function = NULL;
  1982.     before_function = NULL;
  1983.     after_function = NULL;
  1984.     fread(ta, sizeof(*ta), TSIZE, fp);
  1985.     }
  1986.     fclose(fp);
  1987.     show_rule(buf1);
  1988.     strcat(buf1, " loaded");
  1989.     show_msg(buf1);
  1990. }
  1991.  
  1992.  
  1993. tload_compressed(name)
  1994. char *name;
  1995. {                    /* load a compressed t-table */
  1996.     int err;
  1997.     
  1998.     strcpy(buf1,name);
  1999.     if (buf1[0] == NULL)
  2000.     return;
  2001.     if (strcmp(&buf1[strlen(buf1)-2],".Z"))
  2002.     strcat(buf1,".Z");
  2003.     if (auto_nhood_change)
  2004.     change_stuff_file(name);
  2005.     if (!stat(buf1,&statbuf)) {
  2006.     if (function) {
  2007.         show_msg("Can't load compressed .o files yet");
  2008.         return;
  2009.     }
  2010.     sprintf(buf2,"uncompress -c %s",buf1);
  2011.     if (!(fp = popen(buf2, "r"))) {
  2012.         show_msg("Error trying to open pipe");
  2013.         return;
  2014.     }
  2015.     }
  2016.     else {
  2017.     if (function)
  2018.         sprintf(buf2, "%s/%s", Fcn_dir, buf1);
  2019.     else
  2020.         sprintf(buf2,"%s/%s",Table_dir,buf1);
  2021.     if (stat(buf2,&statbuf)) {
  2022.         show_msg("no such t-file");
  2023.         return;
  2024.     }
  2025.     if (function) {
  2026.         show_msg("Can't load compressed .o files yet");
  2027.         return;
  2028.     }
  2029.     sprintf(buf2,"uncompress -c %s/%s",Table_dir,buf1);
  2030.     if (!(fp = popen(buf2, "r"))) {
  2031.         show_msg("Error trying to open pipe");
  2032.         return;
  2033.     }
  2034.     }
  2035.     fread(ta, sizeof(*ta), TSIZE, fp);
  2036.     err = pclose(fp);
  2037.     if (err) {
  2038.     sprintf(buf1,"pclose returned %d",err);
  2039.     show_msg(err);
  2040.     return;
  2041.     }
  2042.     show_rule(buf1);
  2043.     strcat(buf1, " loaded");
  2044.     show_msg(buf1);
  2045. }
  2046.  
  2047.  
  2048. tclear_proc()
  2049. {                    /* set all t-table entries to UNDEF */
  2050.     int     i;
  2051.  
  2052.     if (invalid_set_pressed())
  2053.     return;
  2054.     if (function) {
  2055.     clear_msg();
  2056.     show_msg("no lookup table when");
  2057.     show_msg("using 256 states");
  2058.     }
  2059.     if (setting_sequence)
  2060.     add_sequence(tclear);
  2061.     for (i = 0; i < TSIZE; i++)
  2062.     ta[i] = UNDEF;
  2063.     clear_rule();
  2064. }
  2065.  
  2066. talter()
  2067. {                    /* select and alter a t-table entry */
  2068.     State   image;
  2069.     int     aa;
  2070.     char    nhood[BUFLEN];
  2071.  
  2072.     clear_msg();
  2073.     if (invalid_set_pressed())
  2074.     return;
  2075.     if (function) {
  2076.     clear_msg();
  2077.     show_msg("no lookup table when");
  2078.     show_msg("using 256 states");
  2079.     }
  2080.     if (setting_sequence)
  2081.     add_sequence(talter);
  2082.     get_msg("Neighborhood:", nhood, BUFLEN, saved_nhood);
  2083.     if (nhood[0] == 0)
  2084.     return;
  2085.     strcpy(saved_nhood, buf1);
  2086.     if (strlen(nhood) != N) {
  2087.     show_msg("Illegal neighhborhood");
  2088.     return;
  2089.     }
  2090.     alter_nhood(nhood);
  2091.  
  2092. } /* talter */
  2093.  
  2094.  
  2095.  
  2096. tgenerate()
  2097. {                    /* generate Wolfram's basic rules */
  2098.     int     rule, i;
  2099.     
  2100.     clear_msg();
  2101.     if (invalid_set_pressed())
  2102.     return;
  2103.     if (function) {
  2104.     clear_msg();
  2105.     show_msg("no lookup table when");
  2106.     show_msg("using 256 states");
  2107.     }
  2108.     if (setting_sequence)
  2109.     add_sequence(tgenerate);
  2110.     if (get_num("Rule number:", &rule, 0, 255, saved_rule_number))
  2111.     return;
  2112.     saved_rule_number = rule;
  2113.     for (i = 0; i < 8; i++) {
  2114.     ta[i] = rule & 1;
  2115.     rule >>= 1;
  2116.     }
  2117. }
  2118.  
  2119.  
  2120. lambda_proc()
  2121. {
  2122.     if (function) {
  2123.     clear_msg();
  2124.     show_msg("Lambda invalid when using");
  2125.     show_msg("256 states");
  2126.     return;
  2127.     }
  2128.     if (set_pressed())
  2129.     tlambda_set();
  2130.     else
  2131.     tlambda_generate();
  2132. }
  2133.  
  2134.  
  2135. tlambda_set()
  2136. {
  2137.     int i, percent;
  2138.  
  2139.     clear_msg();
  2140.     if (setting_sequence)
  2141.     add_sequence(tlambda_set);
  2142.     if (get_num("Enter percentage: ", &percent, 0, 100, saved_lambda_percent))
  2143.     return;
  2144.     saved_lambda_percent = percent;
  2145. }
  2146.  
  2147.  
  2148. tlambda_generate()
  2149. {
  2150.     int i, j;
  2151.     char nhood_str[10];
  2152.  
  2153.     if (setting_sequence)
  2154.     add_sequence(tlambda_generate);
  2155.     if (saved_lambda_percent == INTUNDEF) {
  2156.     clear_msg();
  2157.     show_msg("Lambda value never set");
  2158.     return;
  2159.     }
  2160.     clear_msg();
  2161.     sprintf(buf1, "Generating tbl with lambda=%d",saved_lambda_percent);
  2162.     show_msg(buf1);
  2163.     tclear();
  2164.     ta[0] = 0;
  2165.     
  2166.     for (i=0; i < S; i++) {    /* set transition for homogeneous nborhoods */
  2167.     for (j=0; j<N; j++)
  2168.         nhood_str[j] = '0'+i;
  2169.     nhood_str[N] = '\0';
  2170.     tstore(nhood_str, i);
  2171.     }
  2172.     for (i=0; i<TSIZE; i++) {
  2173.     if (ta[i] == UNDEF) {
  2174.         to_nhood(i, nhood_str);
  2175.         if ((random()%100) < saved_lambda_percent)
  2176.         tstore(nhood_str, (random()%(S-1))+1);
  2177.         else
  2178.         tstore(nhood_str, 0);
  2179.     }
  2180.     }
  2181.     clear_msg();
  2182.     sprintf(buf1, "Lambda = %1.2f", compute_lambda());
  2183. }
  2184.  
  2185.  
  2186. lambda_step_proc()
  2187. {
  2188.     if (function) {
  2189.     clear_msg();
  2190.     show_msg("lambda-step invalid when");
  2191.     show_msg("using 256 states");
  2192.     return;
  2193.     }
  2194.     if (set_pressed())
  2195.     tlambda_step_set();
  2196.     else
  2197.     tlambda_step_generate();
  2198. }
  2199.  
  2200.  
  2201. tlambda_step_set()
  2202. {
  2203.     int i, stepval;
  2204.  
  2205.     clear_msg();
  2206.     if (setting_sequence)
  2207.     add_sequence(tlambda_step_set);
  2208.     if (get_num("Enter step-value: ", &stepval, -TSIZE, TSIZE, saved_lambda_increment))
  2209.     return;
  2210.     saved_lambda_increment = stepval;
  2211.     saved_lambda_inc_set = 1;
  2212. }
  2213.  
  2214.  
  2215. tlambda_step_generate()
  2216. {
  2217.     int i, j, k;
  2218.     char nhood_str[10];
  2219.  
  2220.     if (setting_sequence)
  2221.     add_sequence(tlambda_step_generate);
  2222.     if (!saved_lambda_inc_set) {
  2223.     clear_msg();
  2224.     show_msg("Lambda increment never set");
  2225.     return;
  2226.     }
  2227.     clear_msg();
  2228.     if (saved_lambda_increment == 0) {
  2229.     show_msg("Increment is 0 - no change");
  2230.     return;
  2231.     }
  2232.     if (saved_lambda_increment > 0)
  2233.     sprintf(buf1, "Adding %d transitions to tbl",saved_lambda_increment);
  2234.     else
  2235.     sprintf(buf1, "Clearing %d transitions in tbl", -1 * saved_lambda_increment);
  2236.     show_msg(buf1);
  2237.  
  2238.     if (saved_lambda_increment > 0) {
  2239.     for (i=0; i < saved_lambda_increment; i++) {
  2240.         j = random()%TSIZE;
  2241.         for (k=0; (k < TSIZE) && (ta[j] != 0); k++, j=(j+1)%TSIZE)  ;
  2242.         if (k < TSIZE) {
  2243.         /* printf("setting tbl entry # %d (k=%d)\n",j,k); */
  2244.         to_nhood(j, nhood_str);
  2245.         tstore(nhood_str, (random()%(S-1))+1);
  2246.         }
  2247.     }
  2248.     }
  2249.     else {
  2250.     for (i=0; i < -1 * saved_lambda_increment; i++) {
  2251.         j = random()%TSIZE;
  2252.         for (k=0; (k < TSIZE) && (ta[j] == 0); k++, j=(j+1)%TSIZE)  ;
  2253.         if (k < TSIZE) {
  2254.         /* printf("clearing tbl entry # %d (k=%d)\n",j,k); */
  2255.         to_nhood(j, nhood_str);
  2256.         tstore(nhood_str, 0);
  2257.         }
  2258.     }
  2259.     }
  2260.     sprintf(buf1, "Lambda = %1.2f", compute_lambda());
  2261.     show_msg(buf1);
  2262. }
  2263.  
  2264.  
  2265. rho_proc()
  2266. {
  2267.     if (function) {
  2268.     clear_msg();
  2269.     show_msg("Rho invalid when using");
  2270.     show_msg("256 states");
  2271.     return;
  2272.     }
  2273.     if (set_pressed())
  2274.     trho_set();
  2275.     else
  2276.     trho_generate();
  2277. }
  2278.  
  2279.  
  2280. trho_set()
  2281. {
  2282.     int done, sum, r, j, err, tmp_int;
  2283.     int i, percent[16];
  2284.  
  2285.     if (setting_sequence)
  2286.     add_sequence(trho_set);
  2287.     clear_msg();
  2288.     sum = 0;
  2289.     switch (S) {
  2290.       case 2:
  2291.     clear_msg();
  2292.     sprintf(buf1, "percentage of 1");
  2293.     if (get_num(buf1, &percent[1], 0, 100, 0))
  2294.         return;
  2295.     break;
  2296.       case 4:
  2297.       case 8:
  2298.     clear_msg();
  2299.     sprintf(buf1, "percentages of 1-%d", S-1);
  2300.     get_msg(buf1, buf2, BUFLEN, "");
  2301.     err = sscanf(buf2, "%d %d %d %d %d %d %d %d",&percent[1],
  2302.              &percent[2],&percent[3],&percent[4],&percent[5],
  2303.              &percent[6],&percent[7],&tmp_int);
  2304.         if (err != S-1) {
  2305.         sprintf(buf1, "wrong # of percentages entered");
  2306.         show_msg(buf1);
  2307.         return;
  2308.         }
  2309.         break;
  2310.       case 16:
  2311.         clear_msg();
  2312.         sprintf(buf1, "percentages of 1-7");
  2313.         get_msg(buf1, buf2, BUFLEN, "");
  2314.         err = sscanf(buf2, "%d %d %d %d %d %d %d %d",&percent[1],
  2315.              &percent[2],&percent[3],&percent[4],&percent[5],
  2316.              &percent[6],&percent[7],&tmp_int);
  2317.         if (err != 7) {
  2318.         sprintf(buf1, "wrong # of percentages entered");
  2319.         show_msg(buf1);
  2320.         return;
  2321.         }
  2322.         clear_msg();
  2323.         sprintf(buf1, "percentages of 8-15");
  2324.         get_msg(buf1, buf2, BUFLEN, "");
  2325.         err = sscanf(buf2, "%d %d %d %d %d %d %d %d %d",&percent[8],
  2326.              &percent[9],&percent[10],&percent[11],&percent[12],
  2327.              &percent[13],&percent[14],&percent[15],&tmp_int);
  2328.         if (err != 8) {
  2329.         sprintf(buf1, "wrong # of percentages entered");
  2330.         show_msg(buf1);
  2331.         return;
  2332.         }
  2333.         break;
  2334.     }
  2335.     for (i=1; i<S; i++)
  2336.     sum += percent[i];
  2337.     if (sum > 100) {
  2338.     show_msg("Sum was greater than 100%");
  2339.     return;
  2340.     }
  2341.     for (i=1; i < S; i++)
  2342.     saved_rho_percent[i] = percent[i];
  2343. }
  2344.  
  2345.  
  2346. trho_generate()
  2347. {
  2348.     int done, sum, r, j;
  2349.     int i, percent[16], p[16];
  2350.     char nhood_str[10];
  2351.  
  2352.     clear_msg();
  2353.     if (setting_sequence)
  2354.     add_sequence(trho_generate);
  2355.     if (saved_rho_percent[0] == INTUNDEF) {
  2356.     show_msg("default never set, or cleared");
  2357.     show_msg("when configuration changed");
  2358.     return;
  2359.     }
  2360.     show_msg("Setting percentage rho");
  2361.     switch (S) {
  2362.       case 2:
  2363.       case 4:
  2364.       case 8:
  2365.     sprintf(buf1, "%d", saved_rho_percent[1]);
  2366.     for (i=2; i<S; i++) {
  2367.         sprintf(buf2, " %d", saved_rho_percent[i]);
  2368.         strcat(buf1, buf2);
  2369.     }
  2370.     show_msg(buf1);
  2371.     break;
  2372.       case 16:
  2373.     sprintf(buf1, "%d", saved_rho_percent[1]);
  2374.     for (i=2; i<= 8; i++) {
  2375.         sprintf(buf2, " %d", saved_rho_percent[i]);
  2376.         strcat(buf1, buf2);
  2377.     }
  2378.     show_msg(buf1);
  2379.     sprintf(buf1, "%d", saved_rho_percent[8]);
  2380.     for (i=9; i<16; i++) {
  2381.         sprintf(buf2, " %d", saved_rho_percent[i]);
  2382.         strcat(buf1, buf2);
  2383.     }
  2384.     show_msg(buf1);
  2385.     break;
  2386.     }
  2387.     show_msg("generating table...");
  2388.     p[0] = 0;
  2389.     for (i=1; i < S; i++)
  2390.     p[i] = p[i-1] + saved_rho_percent[i];
  2391.     tclear();
  2392.     for (i=0; i < S; i++) {    /* set transition for homogeneous nborhoods */
  2393.     for (j=0; j<N; j++)
  2394.         nhood_str[j] = '0'+i;
  2395.     nhood_str[N] = '\0';
  2396.     tstore(nhood_str, i);
  2397.     }
  2398.     for (i=0; i < TSIZE; i++) {
  2399.     if (ta[i] == UNDEF) {
  2400.         to_nhood(i, nhood_str);
  2401.         done = 0;
  2402.         r = random()%100;
  2403.         for (j=1; j < S; j++) {
  2404.         if ((!done) && (r < p[j])) {
  2405.             done = 1;
  2406.             tstore(nhood_str, j);
  2407.         }
  2408.         }
  2409.         if (!done)
  2410.         tstore(nhood_str, 0);
  2411.     }
  2412.     }
  2413.     show_msg("done");
  2414. }
  2415.  
  2416.  
  2417. alter_nhood(nhood)            /* alter a given t-table entry */
  2418.     char   *nhood;
  2419. {
  2420.     State   image;
  2421.     int     aa;
  2422.     char    tstr[BUFLEN], saved_nhood[20];
  2423.  
  2424.     strcpy(buf2, nhood);
  2425.     strcpy(saved_nhood, nhood);
  2426.     aa = to_index(buf2);        /* convert string to index */
  2427.  
  2428.     if (aa == TABLE_ERR)
  2429.     show_msg("Illegal neighborhood");
  2430.     else {
  2431.     sprintf(tstr, "%s => %c; new image?", buf2, to_char(ta[aa]));
  2432.     clear_msg();
  2433.     get_msg(tstr, buf1, BUFLEN, "");
  2434.     if (buf1[0] == NULL)
  2435.         show_msg("");
  2436.     else if (!is_state(buf1[0]))
  2437.         show_msg("Illegal image");
  2438.     else {
  2439.         image = to_state(buf1[0]);
  2440.         sprintf(tstr, "%s => %c ok? ", saved_nhood, buf1[0]);
  2441.         get_msg(tstr, buf1, BUFLEN, "");
  2442.         if (buf1[0] == 'y')
  2443.         tstore(saved_nhood, image);
  2444.     }
  2445.     } /* else */
  2446.  
  2447. } /* alter_nhood */
  2448.  
  2449.  
  2450. tstore(nhood, image)        /* encode t-table index of ascii nhood */
  2451.     char    nhood[];
  2452. State   image;
  2453.  
  2454. {
  2455.     int     aa, ab, ac, ad;        /* vars for four nhood rotations */
  2456.  
  2457.     aa = to_index(nhood);
  2458.     if (!table_symmetry) {
  2459.     ta[aa] = image;
  2460.     return;
  2461.     }
  2462.     rotate(nhood);
  2463.     ab = to_index(nhood);
  2464.     rotate(nhood);
  2465.     ac = to_index(nhood);
  2466.     rotate(nhood);
  2467.     ad = to_index(nhood);
  2468.  
  2469.     /* now save image */
  2470.  
  2471.     ta[aa] = ta[ab] = ta[ac] = ta[ad] = image;
  2472.  
  2473. } /* tstore */
  2474.  
  2475.  
  2476.  
  2477. /********************* BUFFER ROUTINES *********************/
  2478.  
  2479. bload()
  2480. {
  2481.     clear_msg();
  2482.     if (invalid_set_pressed())
  2483.     return;
  2484.     if (setting_sequence)
  2485.     add_sequence(bload);
  2486.     bbufop(BUFOP_LOAD, "Load from");
  2487. }
  2488.  
  2489. bsave()
  2490. {
  2491.     clear_msg();
  2492.     if (invalid_set_pressed())
  2493.     return;
  2494.     if (setting_sequence)
  2495.     add_sequence(bsave);
  2496.     bbufop(BUFOP_SAVE, "Save to");
  2497. }
  2498.  
  2499. bswap()
  2500. {
  2501.     clear_msg();
  2502.     if (invalid_set_pressed())
  2503.     return;
  2504.     if (setting_sequence)
  2505.     add_sequence(bswap);
  2506.     bbufop(BUFOP_SWAP, "Swap to");
  2507. }
  2508.  
  2509. bxor()
  2510. {
  2511.     clear_msg();
  2512.     if (invalid_set_pressed())
  2513.     return;
  2514.     if (setting_sequence)
  2515.     add_sequence(bxor);
  2516.     bbufop(BUFOP_XOR, "Xor with");
  2517. }
  2518.  
  2519. bor()
  2520. {
  2521.     clear_msg();
  2522.     if (invalid_set_pressed())
  2523.     return;
  2524.     if (setting_sequence)
  2525.     add_sequence(bor);
  2526.     bbufop(BUFOP_OR, "Or with");
  2527. }
  2528.  
  2529. band()
  2530. {
  2531.     clear_msg();
  2532.     if (invalid_set_pressed())
  2533.     return;
  2534.     if (setting_sequence)
  2535.     add_sequence(band);
  2536.     bbufop(BUFOP_AND, "And with");
  2537. }
  2538.  
  2539.  
  2540. bbufop(op, name)            /* do bit-operation with buffer */
  2541.     int     op;
  2542.     char   *name;
  2543. {
  2544.     int     n, err;
  2545.     char    str[BUFLEN];
  2546.     clear_msg();
  2547.     sprintf(str, "%s buffer #:", name);
  2548.     err = get_num(str, &n, 0, NBUFFERS - 1, saved_buffer);
  2549.     if (err)
  2550.     return;
  2551.     else {
  2552.     saved_buffer = n;
  2553.     switch (op) {
  2554.     case BUFOP_XOR:
  2555.         xor_with_buffer(n);
  2556.         break;
  2557.     case BUFOP_OR:
  2558.         or_with_buffer(n);
  2559.         break;
  2560.     case BUFOP_AND:
  2561.         and_with_buffer(n);
  2562.         break;
  2563.     case BUFOP_LOAD:
  2564.         load_from_buffer(n);
  2565.         break;
  2566.     case BUFOP_SAVE:
  2567.         copy_to_buffer(n);
  2568.         show_msg("Image copied");
  2569.         break;
  2570.     case BUFOP_SWAP:
  2571.         swap_to_buffer(n);
  2572.         break;
  2573.     } /* switch */
  2574.     display_image();
  2575.     } /* else */
  2576. } /* bbufop */
  2577.  
  2578.  
  2579.  
  2580. /*********************** PLANE ROUTINES ***********************/
  2581.  
  2582. pclear()
  2583. {                    /* clear given bitplanes */
  2584.     int     mask;
  2585.     
  2586.     clear_msg();
  2587.     if (invalid_set_pressed())
  2588.     return;
  2589.     if (setting_sequence)
  2590.     add_sequence(pclear);
  2591.     if (get_num("Plane mask:", &mask, 1, AMASK, saved_plane_mask))
  2592.     return;
  2593.     saved_plane_mask = mask;
  2594.     clear_planes(mask);
  2595.     display_image();
  2596. }
  2597.  
  2598.  
  2599. pinvert()
  2600. {                    /* invert given bitplanes */
  2601.     int     mask;
  2602.     
  2603.     clear_msg();
  2604.     if (invalid_set_pressed())
  2605.     return;
  2606.     if (setting_sequence)
  2607.     add_sequence(pinvert);
  2608.     if (get_num("Plane mask:", &mask, 1, AMASK, saved_plane_mask))
  2609.     return;
  2610.     saved_plane_mask = mask;
  2611.     invert_planes(mask);
  2612.     display_image();
  2613. }
  2614.  
  2615. /******************** DRAWING ROUTINES ***********************/
  2616.  
  2617. plot(x,y,val)
  2618. int x,y,val;
  2619. {
  2620.     if ((x < 0) || (x >= B) || (y < 0) || (y >= B))
  2621.     return;
  2622.     ca[y*B + x + ABASE] = val;
  2623. }
  2624.  
  2625.  
  2626. draw_horizontal_line(row, start_col, end_col, val)
  2627. int row, start_col, end_col, val;
  2628. {
  2629.     int index, x, tmp;
  2630.  
  2631.     if (start_col > end_col) {
  2632.     tmp = start_col;
  2633.     start_col = end_col;
  2634.     end_col = tmp;
  2635.     }
  2636.     index = row*B + start_col + ABASE;
  2637.     for (x=start_col; x <= end_col; x++)
  2638.     ca[index++] = val;
  2639.     display_image();
  2640. }
  2641.  
  2642.  
  2643. draw_vertical_line(col, start_row, end_row, val)
  2644. int col, start_row, end_row, val;
  2645. {
  2646.     int index, y, tmp;
  2647.  
  2648.     if (start_row > end_row) {
  2649.     tmp = start_row;
  2650.     start_row = end_row;
  2651.     end_row = tmp;
  2652.     }
  2653.     index = start_row*B + col + ABASE;
  2654.     for (y=start_row; y <= end_row; y++) {
  2655.     ca[index] = val;
  2656.     index += B;
  2657.     }
  2658.     display_image();
  2659. }
  2660.  
  2661.  
  2662. draw_arbitrary_line(start_x, start_y, end_x, end_y, val)
  2663. int start_x, start_y, end_x, end_y, val;
  2664. {
  2665.     int index;
  2666.     int dx, dy, count, error, x, y, tmp;
  2667.  
  2668.     dx = end_x - start_x;
  2669.     dy = end_y - start_y;
  2670.     error = 0;
  2671.  
  2672.     if (dy < 0) {
  2673.     tmp = start_x;
  2674.     start_x = end_x;
  2675.     end_x = tmp;
  2676.     tmp = start_y;
  2677.     start_y = end_y;
  2678.     end_y = tmp;
  2679.     dx = -dx;
  2680.     dy = -dy;
  2681.     }
  2682.     plot(start_x,start_y,val);
  2683.     x = start_x;
  2684.     y = start_y;
  2685.     if (dx >= 0) {
  2686.     if (dx == dy) {
  2687.         for (count = 1; count <= dx-1; count++)
  2688.         plot(x++, y++, val);
  2689.     }
  2690.     else if (dx >= dy) {
  2691.         for (count = 1; count <= dx-1; count++) {
  2692.         if (error < 0) {
  2693.             x++;
  2694.             plot(x,y,val);
  2695.             error = error+dy;
  2696.         }
  2697.         else {
  2698.             x++;
  2699.             y++;
  2700.             plot(x,y,val);
  2701.             error = error + dy - dx;
  2702.         }
  2703.         }
  2704.     }
  2705.     else {
  2706.         for (count = 1; count <= dy-1; count++) {
  2707.         if (error < 0) {
  2708.             x++;
  2709.             y++;
  2710.             plot(x,y,val);
  2711.             error = error + dy - dx;
  2712.         }
  2713.         else {
  2714.             y++;
  2715.             plot(x,y,val);
  2716.             error = error-dx;
  2717.         }
  2718.         }
  2719.     }
  2720.     }
  2721.     else {
  2722.     dx = -dx;
  2723.     /* if (dx == dy) {
  2724.         for (count = 1; count <= dx-1; count++)
  2725.         plot(x--, y++, val);
  2726.       }
  2727.       else */ if (dx >= dy) {
  2728.         for (count = 1; count <= dx-1; count++) {
  2729.         if (error < 0) {
  2730.             x--;
  2731.             plot(x,y,val);
  2732.             error = error+dy;
  2733.         }
  2734.         else {
  2735.             x--;
  2736.             y++;
  2737.             plot(x,y,val);
  2738.             error = error-dx+dy;
  2739.         }
  2740.         }
  2741.     }
  2742.     else {
  2743.         for (count=1; count <= dy-1; count++) {
  2744.         if (error < 0) {
  2745.             x--;
  2746.             y++;
  2747.             plot(x,y,val);
  2748.             error = error-dx+dy;
  2749.         }
  2750.         else {
  2751.             y++;
  2752.             plot(x,y,val);
  2753.             error = error-dx;
  2754.         }
  2755.         }
  2756.     }
  2757.     }
  2758.     plot(end_x,end_y,val);
  2759.     display_image();
  2760. }
  2761.  
  2762.  
  2763. draw_hollow_circ(center_x, center_y, x1, y1, val)
  2764. int center_x, center_y, x1, y1, val;
  2765. {
  2766.     double radius, dx, dy;
  2767.     double dtheta, ct, st, x, y, xtemp, xc, yc;
  2768.  
  2769.     xc = (double) center_x;
  2770.     yc = (double) center_y;
  2771.     dx = (double) abs(x1-center_x);
  2772.     dy = (double) abs(y1-center_y);
  2773.     radius = sqrt((dx*dx) + (dy*dy));
  2774.     if (radius == 0)
  2775.     return;
  2776.     dtheta = 1/radius;
  2777.     ct = cos(dtheta);
  2778.     st = sin(dtheta);
  2779.     x = 0.0;
  2780.     y = radius;
  2781.     while (y >= x) {
  2782.     plot((int)(xc+x),(int)(yc+y),val);
  2783.     plot((int)(xc-x),(int)(yc+y),val);
  2784.     plot((int)(xc+x),(int)(yc-y),val);
  2785.     plot((int)(xc-x),(int)(yc-y),val);
  2786.     plot((int)(xc+y),(int)(yc+x),val);
  2787.     plot((int)(xc-y),(int)(yc+x),val);
  2788.     plot((int)(xc+y),(int)(yc-x),val);
  2789.     plot((int)(xc-y),(int)(yc-x),val);
  2790.     xtemp = x;
  2791.     x = (x*ct - y*st);
  2792.     y = (y*ct + xtemp*st);
  2793.     }
  2794.     display_image();
  2795. }
  2796.  
  2797.  
  2798. draw_shaded_circ(center_x, center_y, x1, y1, xii, yii, val)
  2799. int center_x, center_y, x1, y1, xii, yii, val;
  2800. {
  2801.     double dx, dy, radius;
  2802.     double xc, yc, xi, yi, xl, xr, x, y, radical;
  2803.  
  2804.     xc = (double) center_x;
  2805.     yc = (double) center_y;
  2806.     dx = (double) abs(x1-center_x);
  2807.     dy = (double) abs(y1-center_y);
  2808.     radius = sqrt((dx*dx) + (dy*dy));
  2809.     xi = (double) xii;
  2810.     yi = (double) yii;
  2811.     if (radius == 0)
  2812.     return;
  2813.     y = yc+radius;
  2814.     plot((int)xc, (int)y, val);
  2815.     if (yi)
  2816.     y = y-yi;
  2817.     else
  2818.     y--;
  2819.     while (y > (yc-radius)) {
  2820.     radical = sqrt(radius*radius - (y-yc)*(y-yc));
  2821.     xl = xc - radical;
  2822.     xr = xc + radical;
  2823.     x = xl;
  2824.     if (xi && yi) {
  2825.         while (x < xr) {
  2826.         plot((int)x, (int)y, val);
  2827.         x = x + xi;
  2828.         }
  2829.         plot((int)xr, (int)y, val);
  2830.         y = y - yi;
  2831.     }
  2832.     else {
  2833.         plot((int)xl, (int)y, val);
  2834.         plot((int)xr, (int)y, val);
  2835.         y--;
  2836.     }
  2837.     }
  2838.     y = yc - radius;
  2839.     plot((int)xc, (int)y, val);
  2840.     display_image();
  2841. }
  2842.  
  2843. /********************* UTILITIES AND GENERAL ROUTINES********************/
  2844.  
  2845.  
  2846.  
  2847. /*
  2848.  * See if the "set" button was just pressed... if so, return 1, else
  2849.  * return 0.  In either case, unset the "set_just_pressed" variable
  2850.  */
  2851. set_pressed()
  2852. {
  2853.     if (set_just_pressed) {
  2854.     set_just_pressed = 0;
  2855.     return 1;
  2856.     }
  2857.     else
  2858.     return 0;
  2859. }
  2860.  
  2861.  
  2862. /*
  2863.  * If set was just pressed, then complain that set has no meaning for this
  2864.  * routine, and clear the flag and return 1.  If set was not pressed, return 0.
  2865.  */
  2866. invalid_set_pressed()
  2867. {
  2868.     if (set_just_pressed) {
  2869.     clear_msg();
  2870.     show_msg("'Set' invalid for this function");
  2871.     set_just_pressed = 0;
  2872.     return 1;
  2873.     }
  2874.     else
  2875.     return 0;
  2876. }
  2877.  
  2878.  
  2879. /*
  2880.  * Find the full pathname of cellsim that is being executed,
  2881.  * so we can do dynamic linking if we need to.
  2882.  */
  2883. void
  2884. which(a0, result)
  2885. char *a0, *result;
  2886. {
  2887.     char *path, directory[256];
  2888.     int i, j;
  2889.  
  2890.     if ((!strncmp(a0, "./", 2)) || (!strncmp(a0, "../", 3)) || (a0[0] == '/')) {
  2891.     strcpy(result, a0);
  2892.     return;
  2893.     }
  2894.     if ((path = getenv("PATH")) == NULL)
  2895.      quit("Couldn't look up PATH from the environment!");
  2896.     i = 0;
  2897.     while (i < strlen(path)) {
  2898.     j = 0;
  2899.     while ((path[i] != ':') && (path[i] != '\0'))
  2900.         directory[j++] = path[i++];
  2901.     i++;
  2902.     directory[j++] = '/';
  2903.     directory[j++] = '\0';
  2904.     strcat(directory, a0);
  2905.     /* Now "directory" contains the next try */
  2906.     if (!stat(directory, &statbuf)) {
  2907.         strcpy(result, directory);
  2908.         return;
  2909.     }
  2910.     }
  2911. }
  2912.  
  2913.  
  2914. /*
  2915.  * Expand a "tilde" filename or filename with wildcards in it.
  2916.  */
  2917. int
  2918. expand_fname(src, dest)
  2919. char *src, *dest;
  2920. {
  2921.     FILE *fp;
  2922.     char command_str[256];
  2923.     int err, i;
  2924.  
  2925.     if (!strlen(src))
  2926.     return;
  2927.     sprintf(command_str, "/bin/sh -c \"/bin/csh -f -c '/bin/echo %s' 2>&1\"",src);
  2928.     if ((fp = popen(command_str, "r")) == NULL) {
  2929.     clear_msg();
  2930.     show_msg("error trying to expand filename");
  2931.     return 1;
  2932.     }
  2933.     fgets(dest, BUFLEN, fp);
  2934.     if ((dest[strlen(dest)-1] == '\n') || (dest[strlen(dest)-1] == '\r'))
  2935.     dest[strlen(dest)-1] = '\0';
  2936.     if ((!strncmp(dest,"Unknown user",12))||(!strncmp(dest,"No match.",9))) {
  2937.     clear_msg();
  2938.     show_msg(dest);
  2939.     pclose(fp);
  2940.     return 1;
  2941.     }
  2942.     for (i=0; i<strlen(dest); i++)
  2943.     if (dest[i] == ' ') {    /* multiple matches */
  2944.         clear_msg();
  2945.         show_msg("Multiple filenames matched.");
  2946.         return 1;
  2947.     }
  2948.     if (strlen(dest) == 0) {
  2949.     clear_msg();
  2950.     show_msg("error trying to expand filename");
  2951.     return 1;
  2952.     }
  2953.     err = pclose(fp);
  2954.     if (err) {
  2955.     clear_msg();
  2956.     show_msg("Error trying to expand filename");
  2957.     return 1;
  2958.     }
  2959.     return 0;
  2960. }
  2961.     
  2962.  
  2963.  
  2964. /*
  2965.  * Two routines to print an error message and exit.  (One that takes
  2966.  * one parameter, another that takes 2).
  2967.  */
  2968. void
  2969. quit(s)
  2970. char *s;
  2971. {
  2972.     fprintf(stderr, "%s\n", s);
  2973.     exit(1);
  2974. }
  2975.  
  2976.  
  2977. void
  2978. quit2(s1,s2)
  2979. char *s1, *s2;
  2980. {
  2981.     fprintf(stderr, s1, s2);
  2982.     fprintf(stderr, "\n");
  2983.     exit(1);
  2984. }
  2985.  
  2986.  
  2987. int
  2988. confirm_overwrite()
  2989. {
  2990.     get_msg("Overwrite file?", buf1, 80, "");
  2991.     if (buf1[0] != 'y') {
  2992.     show_msg("Save cancelled.");
  2993.     return 0;
  2994.     }
  2995.     return 1;
  2996. }
  2997.     
  2998.  
  2999. /*
  3000.  * This is needed because tclear_proc adds itself to the current sequence
  3001.  * if one is being created.  We need a tclear routine that won't do that.
  3002.  */
  3003. tclear()
  3004. {                    /* set all t-table entries to UNDEF */
  3005.     int     i;
  3006.  
  3007.     if (invalid_set_pressed())
  3008.     return;
  3009.     for (i = 0; i < TSIZE; i++)
  3010.     ta[i] = UNDEF;
  3011.     clear_rule();
  3012. }
  3013.  
  3014.     
  3015. int
  3016. is_state(c)                /* is given character a valid state? */
  3017.     char    c;
  3018. {
  3019.     if (S >= 16)
  3020.     return ((c >= ASCZ && c < ASCZ + 10) || (c >= 'a' && c <= 'f')
  3021.         || (c >= 'A' && c <= 'F'));
  3022.     else
  3023.     return (c >= ASCZ && c < ASCZ + S);
  3024. }
  3025.  
  3026.  
  3027. show_next_state(x, y)        /* at given point, show nhood and next state */
  3028.     unsigned short x, y;
  3029. {
  3030.     int     a, i;
  3031.     char    state;
  3032.  
  3033.     /* initialize top and bottom buffers */
  3034.  
  3035.     for (i = 0; i < B; i++) {
  3036.     ca[i] = ca[BSQR + i];
  3037.     ca[BBUF + i] = ca[ABASE + i];
  3038.     }
  3039.  
  3040.     a = get_address(x, y);
  3041.  
  3042.     if (use_CM) {
  3043.     if (function) {
  3044.         clear_msg();
  3045.         show_msg("Probe not implement with");
  3046.         show_msg("256 states on CM yet");
  3047.         return;
  3048.     }
  3049.     i = CM_probe(x,y,a);
  3050.     to_nhood(a, buf2);
  3051.     state = to_char(i);
  3052.     sprintf(buf1, "%s -> %d", buf2, i);
  3053.     clear_msg();
  3054.     show_msg(buf1);
  3055.     return;
  3056.     }
  3057.     state = to_char(ta[a]);        /* image state in t-table */
  3058.     to_nhood(a, buf2);
  3059.  
  3060.     sprintf(buf1, "%s => %c", buf2, state);
  3061.     clear_msg();
  3062.     show_msg(buf1);
  3063.  
  3064. } /* show_next_state() */
  3065.  
  3066.  
  3067. clear_sequence(n)
  3068. short n;
  3069. {
  3070.     sequence_length[n-1] = 0;
  3071. }
  3072.  
  3073.  
  3074. add_sequence(fptr)
  3075. int_func_ptr fptr;
  3076. {
  3077.     sequence_array[setting_sequence-1][sequence_length[setting_sequence-1]++] = fptr;
  3078. }
  3079.  
  3080.  
  3081.  
  3082. /*
  3083.  * Compare the current image with the previous image.
  3084.  * Returns 1 if they differ, 0 if the same.
  3085.  */
  3086. compare_images()
  3087. {
  3088.     unsigned char *ptr1, *ptr2;
  3089.     int i;
  3090.  
  3091.     ptr1 = ca+ICBASE;
  3092.     ptr2 = ia+ICBASE;
  3093.     i = 0;
  3094.     while (i < ICSIZE) {
  3095.     if (*ptr1 != *ptr2)
  3096.         i = ICSIZE+1;
  3097.     else
  3098.         i++;
  3099.     ptr1++;
  3100.     ptr2++;
  3101.     }
  3102.     if (i == ICSIZE+1)    /* images are different */
  3103.     return 1;
  3104.     else
  3105.     return 0;
  3106. }
  3107.  
  3108.  
  3109. /*
  3110.  * See if the current array is empty.  If so, return 1, else
  3111.  * return 0.
  3112.  */
  3113. array_is_empty()
  3114. {
  3115.     unsigned char *ptr;
  3116.     int i;
  3117.  
  3118.     ptr = ca + ICBASE;
  3119.     i = 0;
  3120.     while (i < ICSIZE) {
  3121.     if (*ptr)
  3122.         i = ICSIZE+1;
  3123.     else
  3124.         i++;
  3125.     ptr++;
  3126.     }
  3127.     if (i == ICSIZE+1) {
  3128.     /* fprintf(stderr,"array_is_empty() returning 0\n"); */
  3129.     return 0;
  3130.     }
  3131.     else {
  3132.     /* fprintf(stderr,"array_is_empty() returning 1\n"); */
  3133.     return 1;
  3134.     }
  3135. }
  3136.  
  3137.  
  3138. double
  3139. compute_lambda()
  3140. {
  3141.     int i, sum;
  3142.  
  3143.     sum = 0;
  3144.     for (i=0; i<TSIZE; i++)
  3145.     if (ta[i] && (ta[i] != UNDEF))
  3146.         sum++;
  3147.     return (((double)sum)/((double)TSIZE) * (double)100);
  3148. }
  3149.  
  3150.  
  3151. int
  3152. valid_state(nborhood, nstates, radius)
  3153. int nborhood, nstates, radius;
  3154. {
  3155.     if ((nstates != 2) && (nstates != 4) && (nstates != 8) &&
  3156.     (nstates != 16) && (nstates != 256))
  3157.     return 0;
  3158.     if (nstates != 256) {
  3159.     if ((nborhood == NH_MOORE ||
  3160.          (nborhood == NH_LIN && radius == 3)) && nstates > 4)
  3161.         return 0;
  3162.     }
  3163.     if (radius > 3)
  3164.     return 0;
  3165.     return 1;
  3166. }    
  3167.  
  3168.  
  3169. /* Do an emergency save of the LT (if there is currently one)
  3170.  * when a segmentation fault occurs
  3171.  */
  3172. static void
  3173. emergency_LT_save()
  3174. {
  3175.     FILE *fp;
  3176.  
  3177.     unlink("/tmp/cellsim.LT");
  3178.     if ((fp=fopen("/tmp/cellsim.LT"))==NULL)
  3179.     quit("Couldn't perform emergency LT save");
  3180.     fwrite(ta, sizeof(*ta), TSIZE, fp);
  3181.     fclose(fp);
  3182.     default_segv_func();
  3183.     exit(1);
  3184. }
  3185.  
  3186.  
  3187. /*** DERIVE -- Derive t-functions by comparing two images *****/
  3188.  
  3189. derive(x, y, nhood, iptr)
  3190.     int     x, y, nhood;
  3191.     State  *iptr;
  3192.  
  3193. {
  3194.     unsigned int table_state, image_state;
  3195.     char    str[BUFLEN];
  3196.     int     aptr;
  3197.  
  3198.  
  3199.     image_state = *iptr;
  3200.     table_state = ta[nhood];
  3201.  
  3202.     to_nhood(nhood, str);
  3203.  
  3204.     if (table_state == UNDEF)
  3205.     tstore(str, image_state);
  3206.  
  3207.     else if (table_state != image_state) {
  3208.     mark_site(x, y);        /* display cell marker */
  3209.  
  3210.     clear_msg();
  3211.     show_msg("conflict");
  3212.     sprintf(buf1, "current rule: %s => %c", str, to_char(table_state));
  3213.     show_msg(buf1);
  3214.     sprintf(buf1, "proposed:  %s => %c", str, to_char(image_state));
  3215.     show_msg(buf1);
  3216.     get_msg("change? (y,n,q)", buf1, BUFLEN, "");
  3217.  
  3218.     switch (buf1[0]) {
  3219.  
  3220.     case 'y':
  3221.         tstore(str, image_state);
  3222.         display_site(x, y, image_state);
  3223.         break;
  3224.  
  3225.     case 'q':
  3226.         display_site(x, y, table_state);
  3227.         *iptr = table_state;
  3228.         return (0);
  3229.  
  3230.     default:
  3231.         display_site(x, y, table_state);
  3232.         *iptr = table_state;
  3233.         break;
  3234.  
  3235.     } /* switch */
  3236.  
  3237.     } /* else if */
  3238.     return (1);
  3239.  
  3240. } /* derive() */
  3241.  
  3242.  
  3243. undef(ptr)                /* handle an undefined neighborhood */
  3244.     int     ptr;
  3245. {
  3246.     State   image;
  3247.     int     x, y, a, i, flag = TRUE;
  3248.     State   save_state;
  3249.     char saved_nhood[BUFLEN];
  3250.  
  3251.     i = ptr - ABASE;
  3252.     x = i % B;
  3253.     y = i / B;
  3254.  
  3255.     a = get_address(x, y);
  3256.  
  3257.     to_nhood(a, buf2);        /* get nhood in ascii c-clockwise format */
  3258.     strcpy(saved_nhood, buf2);
  3259.  
  3260.     mark_site(x, y);
  3261.  
  3262.     save_state = ca[ptr];
  3263.  
  3264.     clear_msg();
  3265.     sprintf(buf1, "Undefined nhood %s", buf2);
  3266.     show_msg(buf1);
  3267.     get_msg("Image ('q' to quit):", buf1, BUFLEN, "");
  3268.     if (buf1[0] != NULL && buf1[0] != 'q') {
  3269.     flag = FALSE;
  3270.     if (!is_state(buf1[0])) {
  3271.         show_msg("ILLEGAL IMAGE, try again:", buf1, BUFLEN);
  3272.     } else {
  3273.         image = to_state(buf1[0]);
  3274.         tstore(saved_nhood, image);
  3275.     }
  3276.  
  3277.     } /* if (buf1[0]...) */
  3278.     display_site(x, y, save_state);
  3279.  
  3280.     return (flag);
  3281.  
  3282. } /* undef */
  3283.  
  3284.  
  3285.  
  3286. random_image(side, percent)        /* generate a random configuration */
  3287.     int     side, percent;
  3288. {
  3289.     int     i, org, xcoord, ycoord, index, state;
  3290.     int     grid_size, bucket_size, numcells;
  3291.     float   density;
  3292.  
  3293.     org = (B - side) / 2;
  3294.     density = percent / 100.0;
  3295.  
  3296.     numcells = density * side * side;
  3297.     bucket_size = RSIZE / S;
  3298.     grid_size = RSIZE / side;
  3299.  
  3300.     clear_data();
  3301.     for (i = 0; i < numcells; ) {
  3302.     xcoord = (random() & RMASK) / grid_size;
  3303.     ycoord = (random() & RMASK) / grid_size;
  3304.     state = (random() & RMASK) / bucket_size;
  3305.  
  3306.     index = (ycoord + org) * B + xcoord + org + ABASE;
  3307.     if (ca[index] == 0) {
  3308.         ca[index] = state;
  3309.         i++;
  3310.     }
  3311.     }
  3312.  
  3313.     display_image();
  3314.  
  3315. } /* random_image */
  3316.  
  3317.  
  3318.  
  3319.  
  3320. set_image_dir()
  3321. {
  3322.     clear_msg();
  3323.     if (invalid_set_pressed())
  3324.     return;
  3325.     if (setting_sequence)
  3326.     add_sequence(set_image_dir);
  3327.     get_msg("Enter new Image_dir:", buf1, BUFLEN, Image_dir);
  3328.     if (expand_fname(buf1, buf1))
  3329.     return;
  3330.     if (buf1[0] != '\0')
  3331.     sprintf(Image_dir, "%s", buf1);
  3332.     return;
  3333. }
  3334.  
  3335.  
  3336. set_fcn_dir()
  3337. {
  3338.     clear_msg();
  3339.     if (invalid_set_pressed())
  3340.     return;
  3341.     if (setting_sequence)
  3342.     add_sequence(set_fcn_dir);
  3343.     get_msg("Enter new Fcn_dir:", buf1, BUFLEN, Fcn_dir);
  3344.     if (expand_fname(buf1, buf1))
  3345.     return;
  3346.     if (buf1[0] != '\0')
  3347.     sprintf(Fcn_dir, "%s", buf1);
  3348.     return;
  3349. }
  3350.  
  3351.  
  3352. set_table_dir()
  3353. {
  3354.     clear_msg();
  3355.     if (invalid_set_pressed())
  3356.     return;
  3357.     if (setting_sequence)
  3358.     add_sequence(set_table_dir);
  3359.     get_msg("Enter new Table_dir:", buf1, BUFLEN, Table_dir);
  3360.     if (expand_fname(buf1, buf1))
  3361.     return;
  3362.     if (buf1[0] != '\0')
  3363.     sprintf(Table_dir, "%s", buf1);
  3364.     return;
  3365. }
  3366.  
  3367.  
  3368. set_cmap_dir()
  3369. {
  3370.     clear_msg();
  3371.     if (invalid_set_pressed())
  3372.     return;
  3373.     if (setting_sequence)
  3374.     add_sequence(set_cmap_dir);
  3375.     get_msg("Enter new Cmap_dir:", buf1, BUFLEN, Cmap_dir);
  3376.     if (expand_fname(buf1, buf1))
  3377.     return;
  3378.     if (buf1[0] != '\0')
  3379.     sprintf(Cmap_dir, "%s", buf1);
  3380.     return;
  3381. }
  3382.  
  3383.     
  3384.  
  3385. /******************************** CHANGE ROUTINES ***********************/
  3386. /* These are the routines used to change the neighborhood and number */
  3387. /* of states, or the image size. */
  3388.  
  3389.  
  3390.  
  3391. /* This routine is callable from the "rules" menu, and allows the
  3392.  * user to switch to a specified neighorhood and number of states
  3393.  */
  3394. change_stuff_proc()
  3395. {
  3396.     clear_msg();
  3397.     if (invalid_set_pressed())
  3398.     return;
  3399.     if (setting_sequence)
  3400.     add_sequence(change_stuff_proc);
  3401.     get_msg("Enter string:", buf1, BUFLEN, "");
  3402.     if (buf1[0] != '\0')
  3403.     change_stuff(buf1);
  3404. }
  3405.  
  3406.  
  3407.  
  3408. /*
  3409.  * This routine will be called by the various rule-loading routines
  3410.  * to automatically switch to the proper neighborhood and number of
  3411.  * states based on the file name.
  3412.  */
  3413. change_stuff_file(name)
  3414. char *name;
  3415. {
  3416.     char fname[80];
  3417.     int i, j, radius;
  3418.     char *ptr, tmp_str[80];
  3419.  
  3420.     strcpy(fname, name);
  3421.     if (!strcmp(&fname[strlen(fname)-2], ".Z"))
  3422.     fname[strlen(fname)-2] = '\0';
  3423.     j = -1;
  3424.     if (!strcmp(&fname[strlen(fname)-2], ".o")) {
  3425.     for (i=1; i < strlen(fname); i++)
  3426.         if ((!strncmp(&fname[i], "256", 3)) && (fname[i-2] == '.'))
  3427.         j = i-1;
  3428.     switch (fname[j]) {
  3429.       case 'm':
  3430.         change_stuff("m256");
  3431.         break;
  3432.       case 'M':
  3433.         change_stuff("M256");
  3434.         break;
  3435.       case 'v':
  3436.         change_stuff("v256");
  3437.         break;
  3438.       case 'l':
  3439.         radius = 1;
  3440.         if (fname[j+4] == 'r')
  3441.         sprintf(tmp_str, "l256r%c", fname[j+5]);
  3442.         else
  3443.         sprintf(tmp_str, "l256");
  3444.         change_stuff(tmp_str);
  3445.         break;
  3446.       default:
  3447.         sprintf(tmp_str, "Illegal nborhood char '%c'", fname[j]);
  3448.         show_msg(tmp_str);
  3449.         return;
  3450.         break;
  3451.     }
  3452.     return;
  3453.     }
  3454.     /* If we reach here, then it was not a ".o" file */
  3455.     ptr = &fname[strlen(fname)-1];
  3456.     while ((*ptr != '.') && (ptr != fname))
  3457.     ptr--;
  3458.     if (ptr == fname)
  3459.     return;
  3460.     ptr++;
  3461.     change_stuff(ptr);
  3462. }
  3463.  
  3464.  
  3465. /*
  3466.  * This is the routine that gets called by the previous 2, to actually
  3467.  * perform the neighborhood change
  3468.  */
  3469. change_stuff(str)
  3470. char *str;
  3471. {
  3472.     int nborhood, nstates, radius, i, j;
  3473.     char tmp_str[80], tmp2_str[80], save_str[80];
  3474.  
  3475.     strcpy(save_str, str);
  3476.     clear_msg();
  3477.     switch (str[0]) {
  3478.       case 'm':
  3479.     nborhood = NH_MOORE;
  3480.     break;
  3481.       case 'v':
  3482.     nborhood = NH_VONN;
  3483.     break;
  3484.       case 'M':
  3485.     nborhood = NH_MARG;
  3486.     break;
  3487.       case 'l':
  3488.     nborhood = NH_LIN;
  3489.     break;
  3490.       default:
  3491.     show_msg("Illegal nborhood");
  3492.     break;
  3493.     }
  3494.     i = 1;
  3495.     j = 0;
  3496.     while ((str[i] != '\0') && (str[i] != 'r'))
  3497.     tmp_str[j++] = str[i++];
  3498.     tmp_str[j] = '\0';
  3499.     sscanf(tmp_str, "%d", &nstates);
  3500.     radius = 1;
  3501.     if (str[i] == 'r')
  3502.     sscanf(&(str[i+1]), "%d", &radius);
  3503.     if (!valid_state(nborhood, nstates, radius)) {
  3504.     show_msg("Invalid neighborhood config");
  3505.     return;
  3506.     }
  3507.     if (use_CM) {
  3508.     if (!valid_CM_state(nborhood, nstates, radius)) {
  3509.         show_msg("Invalid nhood for CM");
  3510.         return;
  3511.     }
  3512.     }
  3513.     if (nborhood == NH_LIN) {
  3514.     if ((nborhood == NHOOD) && (nstates == S) && (radius == R))
  3515.         return;
  3516.     }
  3517.     else {
  3518.     if ((nborhood == NHOOD) && (nstates == S))
  3519.         return;
  3520.     }
  3521.     if (change_params(nborhood, nstates, radius)) {
  3522.     clear_msg();
  3523.     show_msg("Error in change_params()");
  3524.     return 1;
  3525.     }
  3526.     change_canvas_menus();
  3527.     and_states();
  3528.     and_color(AMASK);
  3529.     and_planemask(AMASK);
  3530.     clear_saved_nhood_defaults();
  3531.     if (ta) free(ta);
  3532.     if (function)
  3533.     ta = NULL;
  3534.     else
  3535.     if ((ta = (State *)malloc(TSIZE)) == NULL) {
  3536.         clear_msg();
  3537.         show_msg("Couldn't allocate memory for lookup-table");
  3538.         return 1;
  3539.     }
  3540.     tclear();
  3541.     free(statecount);
  3542.     statecount = (int *) malloc(S * sizeof(int));
  3543.     display_image();
  3544.     clear_msg();
  3545.     switch (nborhood) {
  3546.       case NH_MOORE:
  3547.     sprintf(tmp_str,"moore ");
  3548.     break;
  3549.       case NH_MARG:
  3550.     sprintf(tmp_str,"marg ");
  3551.     break;
  3552.       case NH_LIN:
  3553.     sprintf(tmp_str,"lin ");
  3554.     break;
  3555.       case NH_VONN:
  3556.     sprintf(tmp_str,"vonn ");
  3557.     break;
  3558.     }
  3559.     sprintf(tmp2_str,"%d", nstates);
  3560.     strcat(tmp_str, tmp2_str);
  3561.     if (nborhood == NH_LIN) {
  3562.     sprintf(tmp2_str," r %d",radius);
  3563.     strcat(tmp_str, tmp2_str);
  3564.     }
  3565.     show_msg(tmp_str);
  3566.     if (use_CM)
  3567.     CM_change_stuff(save_str);
  3568. }
  3569.  
  3570.  
  3571. /* This is a routine to change the image-size which is callable
  3572.  * from the "image" menu.
  3573.  */
  3574. change_image_size_proc()
  3575. {
  3576.     int newsize;
  3577.     
  3578.     clear_msg();
  3579.     if (invalid_set_pressed())
  3580.     return;
  3581.     if (setting_sequence)
  3582.     add_sequence(change_image_size_proc);
  3583.     get_msg("New size:", buf1, BUFLEN, "");
  3584.     if (buf1[0] != '\0') {
  3585.     sscanf(buf1,"%d",&newsize);
  3586.     change_image_size(newsize);
  3587.     }
  3588. }
  3589.  
  3590.  
  3591. /* This routine is called by the image-load routines, to change
  3592.  * the image-size if that is necessary to accomodate the new image,
  3593.  * based on the filename.
  3594.  */
  3595. change_image_size_file(fname)
  3596. char *fname;
  3597. {
  3598.     char tmp_str[80], *ptr, *ptr2;
  3599.     int i, newsize;
  3600.     
  3601.     if (!strcmp(&fname[strlen(fname)-2], ".Z"))
  3602.     ptr = &fname[strlen(fname)-3];
  3603.     else ptr = &fname[strlen(fname)-1];
  3604.     ptr2 = ptr;
  3605.     while ((*ptr != '.') && (ptr != fname))
  3606.     ptr--;
  3607.     if (ptr == fname) return;
  3608.     ptr++;
  3609.     i = 0;
  3610.     while (ptr != ptr2)
  3611.     tmp_str[i++] = *ptr++;
  3612.     tmp_str[i++] = *ptr++;
  3613.     tmp_str[i] = '\0';
  3614.     if (tmp_str[i-1] == 'x')
  3615.     tmp_str[i-1] = '\0';
  3616.     sscanf(tmp_str,"%d",&newsize);
  3617.     change_image_size(newsize);
  3618. }
  3619.     
  3620.  
  3621. /*
  3622.  * This one does the actual work of changing the image size.
  3623.  */
  3624. change_image_size(newsize)
  3625. int newsize;
  3626. {
  3627.     if (newsize == B)
  3628.     return;
  3629.     /* if ((newsize != 64) && (newsize != 128) && (newsize != 256) &&
  3630.     (newsize != 512)) {
  3631.     clear_msg();
  3632.     show_msg("Invalid image size");
  3633.     return;
  3634.     }
  3635.     */
  3636.     if (newsize < 4) {
  3637.     clear_msg();
  3638.     show_msg("Image size must be at least 4");
  3639.     return;
  3640.     }
  3641.     if (newsize > 512) {
  3642.     clear_msg();
  3643.     show_msg("Image size must be no greater");
  3644.     show_msg("than 512");
  3645.     return;
  3646.     }
  3647.     if (newsize%4) {
  3648.     clear_msg();
  3649.     show_msg("Image size must be multiple of 4");
  3650.     return;
  3651.     }
  3652.     if (use_CM) {
  3653.     if (!valid_CM_image(newsize)) {
  3654.         clear_msg();
  3655.         show_msg("Invalid size for CM.");
  3656.         show_msg("Must be 128, 256, or 512.");
  3657.         return;
  3658.     }
  3659.     }
  3660.     if (closeup)
  3661.     closeup_proc();
  3662.     B = newsize;
  3663.     BM1 = B - 1;
  3664.     BPL1 = B + 1;
  3665.     TBM1 = 2 * B - 1;
  3666.     BSQR = B * B;
  3667.     BBUF = BSQR + B;
  3668.     ASIZE = BBUF + B;
  3669.     ABASE = B;
  3670.     RCOUNT = B;
  3671.     if (NHOOD == NH_LIN) {
  3672.     ICBASE = BSQR;
  3673.     ICSIZE = B;
  3674.     change_image_size_l();    /* linear neighborhood uses its own private
  3675.                  * array for some updates, so we have to tell
  3676.                  * that array to change */
  3677.     }
  3678.     else {
  3679.     ICBASE = B;
  3680.     ICSIZE = BSQR;
  3681.     }
  3682.     if (use_CM)
  3683.     CM_change_image_size();
  3684.     change_scr();
  3685.     change_data();
  3686.     clear_saved_image_defaults();
  3687.     clear_data();
  3688.     display_image();
  3689.     sprintf(buf1,"Size is now %d",B);
  3690.     show_msg(buf1);
  3691. }
  3692.  
  3693.  
  3694. /*
  3695.  * This is almost the same as set_params; there a few differences, since
  3696.  * this one gets called only to switch neighborhood, where set_params
  3697.  * gets called to initialize things when cellsim is first started up.
  3698.  */
  3699. change_params(nhood, nstates, radius)  /* change the nborhood or # of states */
  3700. int nhood, nstates;
  3701. {
  3702.     /* if (SOCKET_INUSE) {
  3703.     clear_msg();
  3704.     show_msg("Can't change nhood using sockets");
  3705.     return 1;
  3706.     } */
  3707.     NHOOD = nhood;
  3708.     if (nstates == 256)
  3709.     function = 1;
  3710.     else
  3711.     function = 0;
  3712.     switch (nhood) {
  3713.       case NH_MOORE:
  3714.     change_states(nstates, 0);
  3715.     break;
  3716.       case NH_MARG:
  3717.     change_states(nstates, 0);
  3718.     break;
  3719.       case NH_VONN:
  3720.     change_states(nstates, 0);
  3721.     break;
  3722.       case NH_LIN:
  3723.     change_states(nstates, radius);
  3724.     break;
  3725.       default:
  3726.     clear_msg();
  3727.     show_msg("Illegal neighborhood");
  3728.     return 1;
  3729.     break;
  3730.     }
  3731.     if (NHOOD == NH_LIN) {
  3732.     ICBASE = BSQR;
  3733.     ICSIZE = B;
  3734.     DIM = 1;
  3735.     }
  3736.     else {
  3737.     ICBASE = B;
  3738.     ICSIZE = BSQR;
  3739.     DIM = 2;
  3740.     }
  3741.  
  3742.     L = (short) (log((double) S) / log((double) 2.0));
  3743.     AMASK = S-1;
  3744.     switch (NHOOD) {
  3745.       case NH_VONN:
  3746.     set_params_v();
  3747.     break;
  3748.       case NH_MOORE:
  3749.     set_params_m();
  3750.     break;
  3751.       case NH_LIN:
  3752.     set_params_l();
  3753.     break;
  3754.       case NH_MARG:
  3755.     set_params_marg();
  3756.     break;
  3757.     }
  3758.  
  3759.     if (!function)
  3760.     TSIZE = 1 << (L * N);
  3761.     else
  3762.     TSIZE = 0;
  3763.     return 0;
  3764. }
  3765.  
  3766.  
  3767. /*
  3768.  * Similar to set_states
  3769.  */
  3770. change_states(nstates, radius)
  3771. int nstates, radius;
  3772. {
  3773.     S = nstates;
  3774.     R = radius;
  3775. }
  3776.  
  3777.  
  3778. /*
  3779.  * Unset any saved defaults which are no longer valid as a result of
  3780.  * the neighborhood being changed
  3781.  */
  3782. clear_saved_nhood_defaults()
  3783. {
  3784.     saved_max_val = INTUNDEF;        /* for general random proc */
  3785.     saved_rho_percent[0] = INTUNDEF;    /* rho array */
  3786. }
  3787.     
  3788.  
  3789. /*
  3790.  * Unset any saved defaults which are no longer valid as a result of
  3791.  * the image-size being changed
  3792.  */
  3793. clear_saved_image_defaults()
  3794. {
  3795.     saved_ox = INTUNDEF;    /* size for general random proc */
  3796. }
  3797.  
  3798.  
  3799. /***************** Connection Machine (CM) Routines *****************/
  3800. void
  3801. CM_change_host()
  3802. {
  3803.     clear_msg();
  3804.     if (invalid_set_pressed())
  3805.     return;
  3806.     if (setting_sequence)
  3807.     add_sequence(CM_change_host);
  3808.     get_msg("Hostname:", buf1, BUFLEN, CM_hostname);
  3809.     if (buf1[0] == NULL)
  3810.     return;
  3811.     strcpy(CM_hostname, buf1);
  3812. }
  3813.  
  3814.  
  3815. void
  3816. CM_change_port()
  3817. {
  3818.     int num;
  3819.     
  3820.     clear_msg();
  3821.     if (invalid_set_pressed())
  3822.     return;
  3823.     if (setting_sequence)
  3824.     add_sequence(CM_change_port);
  3825.     if (get_num("Port:", &num, 0, 50000, CM_port))
  3826.     return;
  3827.     CM_port = num;
  3828. }
  3829.  
  3830.  
  3831.  
  3832. int
  3833. valid_CM_state(nborhood, nstates, radius)
  3834. int nborhood, nstates, radius;
  3835. {
  3836.     /* if (nborhood == NH_LIN)
  3837.     return 0; */
  3838.     if (nstates == 256)
  3839.     return 1;
  3840.     if ((nborhood == NH_MOORE) && (nstates > 2))
  3841.     return 0;
  3842.     if (((nborhood == NH_VONN) || (nborhood == NH_MARG) ||
  3843.      (nborhood == NH_LIN)) && (nstates > 8))
  3844.     return 0;
  3845.     return 1;
  3846. }
  3847.  
  3848.  
  3849. int
  3850. valid_CM_image(size)
  3851. int size;
  3852. {
  3853.     if ((size==128) || (size==256) || (size==512))
  3854.     return 1;
  3855.     else
  3856.     return 0;
  3857. }
  3858.  
  3859.  
  3860.     
  3861. CM_run_forever_proc()
  3862. {
  3863.     int go=TRUE;
  3864.     
  3865.     set_run_mode();
  3866.     if (use_CM && (!local_run) && (!SOCKET_INUSE)) {
  3867.     CM_auto_run();
  3868.     while (go) {
  3869.         go = !check_button();
  3870.         usleep(100000);
  3871.     }
  3872.     CM_stop_run();
  3873.     unset_run_mode();
  3874.     show_time(stime);
  3875.     }
  3876.     else {
  3877.     clear_msg();
  3878.     if (use_Sun_disp) {
  3879.         show_msg("You must disable local display to");
  3880.         show_msg("use 'run' on CM");
  3881.     }
  3882.     if (SOCKET_INUSE) {
  3883.         show_msg("Can't yet use 'run' on CM");
  3884.         show_msg("when using sockets");
  3885.     }
  3886.     unset_run_mode();
  3887.     return;
  3888.     }
  3889.     if (use_Sun_disp)
  3890.     CM_display_image();
  3891. }
  3892.  
  3893.     
  3894.  
  3895. /************************************* EOF **********************************/
  3896.