home *** CD-ROM | disk | FTP | other *** search
/ Usenet 1994 January / usenetsourcesnewsgroupsinfomagicjanuary1994.iso / sources / x / volume18 / xmandel / part03 < prev    next >
Internet Message Format  |  1992-07-13  |  50KB

  1. Path: uunet!elroy.jpl.nasa.gov!swrinde!mips!msi!dcmartin
  2. From: tony@ajfcal.cuc.ab.ca (Tony Field)
  3. Newsgroups: comp.sources.x
  4. Subject: v18i017: Xmandelbrot, Part03/03
  5. Message-ID: <1992Jul13.155107.6740@msi.com>
  6. Date: 13 Jul 92 15:51:07 GMT
  7. References: <csx-18i015-xmandel@uunet.UU.NET>
  8. Sender: dcmartin@msi.com (David C. Martin - Moderator)
  9. Organization: Molecular Simulations, Inc.
  10. Lines: 1759
  11. Approved: dcmartin@msi.com
  12. Originator: dcmartin@fascet
  13.  
  14. Submitted-by: tony@ajfcal.cuc.ab.ca (Tony Field)
  15. Posting-number: Volume 18, Issue 17
  16. Archive-name: xmandel/part03
  17.  
  18. #!/bin/sh
  19. # this is part.03 (part 3 of a multipart archive)
  20. # do not concatenate these parts, unpack them in order with /bin/sh
  21. # file mandel.c continued
  22. #
  23. if test ! -r _shar_seq_.tmp; then
  24.     echo 'Please unpack part 1 first!'
  25.     exit 1
  26. fi
  27. (read Scheck
  28.  if test "$Scheck" != 3; then
  29.     echo Please unpack part "$Scheck" next!
  30.     exit 1
  31.  else
  32.     exit 0
  33.  fi
  34. ) < _shar_seq_.tmp || exit 1
  35. if test ! -f _shar_wnt_.tmp; then
  36.     echo 'x - still skipping mandel.c'
  37. else
  38. echo 'x - continuing file mandel.c'
  39. sed 's/^X//' << 'SHAR_EOF' >> 'mandel.c' &&
  40. X
  41. void start_mandel()
  42. {
  43. X    if (manparm.window == 0)
  44. X        return;
  45. X    if (manparm.zoom) 
  46. X    {    /* reset to beginning by popping zps off stack if not already there */
  47. X        while (zoomtmp = manparm.zoom->zp) 
  48. X        {    free(manparm.zoom);
  49. X            manparm.zoom = zoomtmp;
  50. X        }
  51. X    } 
  52. X    else 
  53. X    {    manparm.zoom = (struct zoomd *) malloc(sizeof (struct zoomd));
  54. X        manparm.zoom->zp = NULL;    /* NULL means last in stack - don't pop */
  55. X    }
  56. X    manparm.zoom->lx = START_LX; manparm.zoom->ux = START_UX;
  57. X    manparm.zoom->ly = START_LY; manparm.zoom->uy = START_UY;
  58. X
  59. X    mandel ();
  60. }
  61. X
  62. /************************************************************************
  63. *    redo_mandel()        button: recalc        recalc current mandelbrot    *
  64. ************************************************************************/
  65. X
  66. void redo_mandel ()
  67. {    if (manparm.window == 0)
  68. X        return;
  69. X    mandel ();
  70. }
  71. X
  72. X
  73. /************************************************************************
  74. *    mandel()            do the mandelbrot calculations and send to video*
  75. ************************************************************************/
  76. X
  77. static void mandel ()
  78. {
  79. X    double wx, wy, oldwx;
  80. X    double x, y;
  81. X    double incrx, incry;
  82. X    int ix, iy;
  83. X    int        shift;
  84. X    XEvent event;
  85. X    XWindowAttributes draw_wattr;
  86. X    GC draw_gc;
  87. X    Visual *draw_v;
  88. X    long    save_event_mask;
  89. X
  90. X    if (manparm.window == 0)
  91. X        return;
  92. X    manparm.lx = manparm.zoom->lx;
  93. X    manparm.ly = manparm.zoom->ly;
  94. X    manparm.ux = manparm.zoom->ux;
  95. X    manparm.uy = manparm.zoom->uy;
  96. X    update_coordinates (&manparm, 1);
  97. X
  98. X    XGetWindowAttributes (display, manparm.window, &draw_wattr);
  99. X    draw_gc = screen->default_gc;
  100. X    draw_v = screen->root_visual;
  101. X    save_event_mask = draw_wattr.your_event_mask;
  102. X    if (manparm.pixwidth != draw_wattr.width  ||  manparm.pixheight != draw_wattr.height)
  103. X    {
  104. X        /*    screen dimension changed.  rebuild image line information */
  105. X
  106. X        manparm.pixheight = draw_wattr.height;
  107. X        manparm.pixwidth  = draw_wattr.width;
  108. X        manparm.bytewidth = (manparm.pixwidth + dots_per_byte - 1) / dots_per_byte;
  109. X        scanline = -1;
  110. X
  111. X        if (ximage)
  112. X             XDestroyImage (ximage);        /* also deallocates image_data automagically */
  113. X        if (manparm.pix)
  114. X            free (manparm.pix);
  115. X
  116. X        image_data = malloc (manparm.bytewidth + 1);    /* Really! bug in ISC X11?? */
  117. X        manparm.pix = (unsigned char *) malloc (manparm.bytewidth * manparm.pixheight);
  118. X        if (image_data == NULL  ||  manparm.pix == NULL)
  119. X        {    printf ("malloc failed\n"); 
  120. X            return; 
  121. X        }
  122. X        ximage = XCreateImage (display, draw_v, depth, ZPixmap, 0, image_data, manparm.pixwidth, 1, 8, 0);
  123. X        ximage->byte_order = MSBFirst;
  124. X        ximage->bitmap_bit_order = MSBFirst;
  125. X    }
  126. X
  127. X    /*    incremental x/y values for pixel coordinates */
  128. X
  129. X    incrx = (manparm.zoom->ux - manparm.zoom->lx) / manparm.pixwidth;
  130. X    incry = (manparm.zoom->uy - manparm.zoom->ly) / manparm.pixheight;
  131. X    y = manparm.zoom->uy;
  132. X
  133. X    XClearWindow (display, manparm.window);
  134. X    XSelectInput (display, manparm.window, ButtonPressMask | ButtonReleaseMask | ExposureMask);
  135. X
  136. X    for (iy = 0; iy < draw_wattr.height; iy++, y-= incry) 
  137. X    {    int i;
  138. X        if (depth < 8)
  139. X            for (i = 0; i < manparm.bytewidth; i++) 
  140. X                *(image_data + i) = 0;
  141. X        x = manparm.zoom->lx;
  142. X
  143. X        /*    compute colour values for each pixel in a single scan line */
  144. X        
  145. X        for (ix = 0; ix < manparm.pixwidth; ix++, x+= incrx) 
  146. X        {
  147. X            /*    compute set value for current point */
  148. X
  149. X            wx = x; wy = y;
  150. X            for (i = 0; i < ITERATION_DEPTH; i++) 
  151. X            {    oldwx = wx;
  152. X                wx = wx * wx - wy * wy + x;
  153. X                wy = 2 * oldwx * wy + y;
  154. X                if (wx * wx + wy * wy > 4) 
  155. X                    goto useit;
  156. X            }
  157. X            if (depth == 8)
  158. X            {    if (INFINITY_COLOR >= 0)
  159. X                    i = INFINITY_COLOR - COLOR_BIAS;
  160. X            }
  161. X            else
  162. X            {    if (INFINITY_COLOR >= 0)
  163. X                    i = INFINITY_COLOR;
  164. X            }
  165. X
  166. useit:        /*    assign colour to pixel    */
  167. X
  168. X            switch (depth)
  169. X            {
  170. X            case 8:
  171. X                image_data[ix] = i + COLOR_BIAS;
  172. X                break;
  173. X
  174. X            case 4:
  175. X                if (ix % 2)
  176. X                    image_data[ix >> 1] |= (i % 16);
  177. X                else
  178. X                    image_data[ix >> 1] |= ((i % 16) << 4);
  179. X                break;
  180. X
  181. X            case 2:
  182. X                switch (ix % 4)
  183. X                {
  184. X                case 0:        shift = 6;    break;
  185. X                case 1:        shift = 4;    break;
  186. X                case 2:        shift = 2;    break;
  187. X                case 3:        shift = 0;    break;
  188. X                }
  189. X                image_data[ix >> 2] |= (i % 4) << shift;
  190. X                break;
  191. X
  192. X            case 1:
  193. X                if (i % 2)
  194. X                    image_data[ix >> 3] |= 1 << (7 - ix%8);
  195. X            }
  196. X        }
  197. X
  198. X        /*    save scan line for exposure events or gif output */
  199. X        
  200. X        memcpy (manparm.pix + iy * manparm.bytewidth, image_data, manparm.bytewidth);
  201. X        scanline = iy;
  202. X
  203. X        /*    send image line to screen */
  204. X
  205. X        XPutImage (display, manparm.window, draw_gc, ximage, 0,0, 0, iy, manparm.pixwidth, 1);
  206. X
  207. X        /*    check for exposure or buttons after a few lines have been drawn.
  208. X            This keeps server queries do a reasonable level while still
  209. X            allowing exposures without too much delay.
  210. X        */
  211. X        if (iy % EXPOSURE_TEST == 0)
  212. X        {    /*    XSync to ensure exposure or button is honoured "fast" */
  213. X
  214. X            XSync (display, False);
  215. X
  216. X            /*    first cleanup any pending exposures */
  217. X
  218. X            while (XCheckTypedEvent (display, Expose, &event) == True)
  219. X                XtDispatchEvent (&event);
  220. X
  221. X            /*    then check for abort if a button is pressed */
  222. X
  223. X            while (XCheckWindowEvent (display, manparm.window, ButtonPressMask | ButtonReleaseMask, &event) == True)
  224. X            {    if (event.type == ButtonRelease)
  225. X                    goto escape;
  226. X            }
  227. X        }
  228. X    }
  229. escape:
  230. X    XSelectInput (display, manparm.window, save_event_mask);
  231. }
  232. X
  233. /************************************************************************
  234. *    expose_mandel()            handle mandel exposure event                *
  235. ************************************************************************/
  236. X
  237. void expose_mandel (w, unused, event)
  238. Widget w;
  239. caddr_t unused;
  240. XXExposeEvent *event;
  241. {
  242. X    if (manparm.window == 0)
  243. X        return;
  244. X    if (event  &&  manparm.pix  &&  scanline >= 0)
  245. X        redraw_mandel (event);
  246. }
  247. X
  248. /************************************************************************
  249. *    redraw_mandel()            reshow mandelbrot from backup image.        *
  250. ************************************************************************/
  251. X
  252. void redraw_mandel (event)
  253. XXExposeEvent *event;
  254. {
  255. X    int  iy;
  256. X    XWindowAttributes draw_wattr;
  257. X    GC draw_gc;
  258. X    Visual *draw_v;
  259. X    int    maxy;
  260. X
  261. X    if (manparm.window == 0)
  262. X        return;
  263. X    XGetWindowAttributes (display, manparm.window, &draw_wattr);
  264. X    draw_gc = screen->default_gc;
  265. X    draw_v = screen->root_visual;
  266. X    if (event == NULL)
  267. X    {
  268. X        /*    refresh entire window */
  269. X
  270. X        maxy = MIN (scanline, manparm.pixheight-1);
  271. X        for (iy = 0; iy <= maxy; iy++) 
  272. X        {    memcpy (image_data, manparm.pix + iy * manparm.bytewidth, manparm.bytewidth);
  273. X            XPutImage (display, manparm.window, draw_gc, ximage, 0,0, 0, iy, manparm.pixwidth, 1);
  274. X        }
  275. X    }
  276. X    else if (event->x < manparm.pixwidth)
  277. X    {
  278. X        /*    refresh only exposed area */
  279. X
  280. X        int    first_byte, last_byte, nbytes, first_dot, last_dot, ndots;
  281. X
  282. X        if (event->x < manparm.pixwidth)
  283. X        {    first_byte = event->x / dots_per_byte;
  284. X            first_dot  = first_byte * dots_per_byte;
  285. X            last_dot   = MIN (manparm.pixwidth - 1, event->x + event->width - 1);
  286. X            last_byte  = (last_dot + dots_per_byte - 1) / dots_per_byte;
  287. X            nbytes     = last_byte - first_byte + 1;
  288. X            ndots      = last_dot - first_dot + 1;
  289. X            maxy       = MIN (event->y + event->height, manparm.pixheight);
  290. X            for (iy = event->y; iy < maxy  &&  iy <= scanline; iy++) 
  291. X            {    memcpy (image_data, manparm.pix + iy * manparm.bytewidth + first_byte, nbytes);
  292. X                XPutImage (display, manparm.window, draw_gc, ximage, 0,0, event->x, iy, ndots, 1);
  293. X            }                
  294. X        }
  295. X    }
  296. X
  297. X    XFlush(display);
  298. }
  299. X
  300. /************************************************************************
  301. *    do_zoom ()        button: zomm        zoom into mandelbrot            *
  302. *                    The rubber band preserves preserves the current        *
  303. *                    window aspect ration.                                *
  304. ************************************************************************/
  305. X
  306. void do_zoom (w, client_data, call_data)
  307. Widget w;
  308. caddr_t client_data;
  309. caddr_t call_data;
  310. {
  311. X    XWindowAttributes draw_wattr;
  312. X    GC draw_gc;
  313. X    Window Root;
  314. X    int S;
  315. X    int    hh, ww, delta;
  316. X    double scaley, xa, ya, xb, yb;
  317. X    long    save_event_mask;
  318. X    int        have_press;
  319. X
  320. X    Window    root, child;
  321. X    int        pos_x, pos_y;
  322. X    unsigned int keys_buttons;
  323. X    int        root_x, root_y;
  324. X
  325. X    if (activeimage->window == 0)
  326. X        return;
  327. X    if (activeimage->zoom == NULL) return;
  328. X
  329. X    draw_gc = screen->default_gc;
  330. X    S = DefaultScreen (display);
  331. X    Root = RootWindow (display, S);
  332. X
  333. X    XSetForeground (display, draw_gc, 255);
  334. X    XSetSubwindowMode (display, draw_gc, IncludeInferiors);
  335. X    XSetFunction (display, draw_gc, GXxor);
  336. X
  337. X    XGetWindowAttributes (display, activeimage->window, &draw_wattr);
  338. X
  339. X    save_event_mask = draw_wattr.your_event_mask;
  340. X    XSelectInput (display, activeimage->window, ButtonPressMask | ButtonReleaseMask 
  341. X            | PointerMotionHintMask | PointerMotionMask);
  342. X
  343. X    have_press = 0;        /* Motif translation override may cause a     */
  344. X                        /* button release BEFORE a button press        */
  345. X    while (1) 
  346. X    {    static int rubberband = 1;
  347. X        XEvent report;
  348. X
  349. X        XNextEvent (display, &report);
  350. X        if (report.xbutton.window != activeimage->window)
  351. X            continue;
  352. X        switch(report.type) 
  353. X        {
  354. X            int winx0,winy0,winx1,winy1,width,height;
  355. X            int x0, y0, x1, y1;
  356. X            double tw, th;
  357. X
  358. X        case ButtonPress:
  359. X            if (report.xbutton.button != Button1)
  360. X                break;
  361. X            x0 = winx0 = report.xbutton.x;
  362. X            y0 = winy0 = report.xbutton.y;
  363. X            rubberband = 0;
  364. X            width = height = 0;
  365. X            have_press = 1;
  366. X            break;
  367. X
  368. X        case ButtonRelease:
  369. X            if (have_press == 0)
  370. X                break;
  371. X            winx1 = report.xbutton.x;
  372. X            winy1 = report.xbutton.y;
  373. X            x0 = MIN (winx0, winx1);
  374. X            x1 = MAX (winx0, winx1);
  375. X            y0 = MIN (winy0, winy1);
  376. X            y1 = MAX (winy0, winy1);
  377. X            width  = x1 - x0; 
  378. X            height = y1 - y0;
  379. X
  380. X            /*    ensure rubber band preserves the proportions of the
  381. X                current window.
  382. X            */
  383. X            ww = width;
  384. X            hh = height;
  385. X            delta = MAX (ww, hh);
  386. X            scaley = (double) (draw_wattr.height) / (double) (draw_wattr.width);
  387. X            x1 = x0 + delta;
  388. X            y1 = y0 + delta * scaley;
  389. X            height = y1 - y0;
  390. X            width  = x1 - x0;
  391. X
  392. X            XDrawRectangle (display,activeimage->window, draw_gc, x0, y0, width, height);
  393. X            rubberband = 1;
  394. X            XSetFunction (display, draw_gc, GXcopy);
  395. X            XFlush (display);
  396. X            if (delta > 5  &&  report.xbutton.button == 1)
  397. X            {    tw = activeimage->zoom->ux - activeimage->zoom->lx;
  398. X                th = activeimage->zoom->uy - activeimage->zoom->ly;
  399. X                zoomtmp = (struct zoomd *) malloc (sizeof (struct zoomd));
  400. X                zoomtmp->zp = activeimage->zoom;        /* push onto stack */
  401. X                zoomtmp->ux = activeimage->zoom->lx + ((double) x1 / (double) activeimage->pixwidth) * tw;
  402. X                zoomtmp->lx = activeimage->zoom->lx + ((double) x0 / (double) activeimage->pixwidth) * tw;
  403. X                zoomtmp->ly = activeimage->zoom->uy - ((double) y1 / (double) activeimage->pixheight) * th;
  404. X                zoomtmp->uy = activeimage->zoom->uy - ((double) y0 / (double) activeimage->pixheight) * th;
  405. X                activeimage->zoom = zoomtmp;            /* activeimage->zoom is current pointer */
  406. X                XSelectInput (display, activeimage->window, save_event_mask);
  407. X                if (activeimage == &manparm)
  408. X                    mandel ();
  409. X                else
  410. X                    julia (0, 0);
  411. X            }
  412. X            else
  413. X            {    /*    too small image or pressing button 2/3 quits zoom */
  414. X
  415. X                activeimage->lx = activeimage->zoom->lx;
  416. X                activeimage->ly = activeimage->zoom->ly;
  417. X                activeimage->ux = activeimage->zoom->ux;
  418. X                activeimage->uy = activeimage->zoom->uy;
  419. #ifndef MOTIF
  420. X                printf ("\n");
  421. #else
  422. X                update_coordinates (activeimage, 0);
  423. #endif
  424. X                XSelectInput (display, activeimage->window, save_event_mask);
  425. X            }
  426. X            return;
  427. X
  428. X        case MotionNotify:
  429. X            if (!XQueryPointer (display, report.xmotion.window,
  430. X                    &root, &child, &root_x, &root_y,
  431. X                    &pos_x, &pos_y, &keys_buttons))
  432. X                break;
  433. X            winx1 = pos_x;
  434. X            winy1 = pos_y;
  435. X            if (rubberband == 0)
  436. X            {    XDrawRectangle (display,activeimage->window, draw_gc, x0, y0, width, height);
  437. X                x0 = MIN(winx0, winx1);
  438. X                x1 = MAX(winx0, winx1);
  439. X                y0 = MIN(winy0, winy1);
  440. X                y1 = MAX(winy0, winy1);
  441. X                width  = x1 - x0; 
  442. X                height = y1 - y0;
  443. X
  444. X                /*    ensure rubber band preserves the proportions of the
  445. X                    current window.
  446. X                */
  447. X                ww = width;
  448. X                hh = height;
  449. X                delta = MAX (ww, hh);
  450. X                scaley = (double) (draw_wattr.height) / (double) (draw_wattr.width);
  451. X                x1 = x0 + delta;
  452. X                y1 = y0 + delta * scaley;
  453. X                height = y1 - y0;
  454. X                width  = x1 - x0;
  455. X
  456. X                XDrawRectangle (display,activeimage->window, draw_gc, x0, y0, width, height);
  457. X
  458. X                tw = activeimage->zoom->ux - activeimage->zoom->lx;
  459. X                th = activeimage->zoom->uy - activeimage->zoom->ly;
  460. X                xa = activeimage->zoom->lx + ((double) x0 / (double) activeimage->pixwidth) * tw;
  461. X                ya = activeimage->zoom->uy - ((double) y0 / (double) activeimage->pixheight) * th;
  462. X                xb = activeimage->zoom->lx + ((double) x1 / (double) activeimage->pixwidth) * tw;
  463. X                yb = activeimage->zoom->uy - ((double) y1 / (double) activeimage->pixheight) * th;
  464. X
  465. X                activeimage->lx = MIN (xa, xb);
  466. X                activeimage->ly = MIN (ya, yb);
  467. X                activeimage->ux = MAX (xa, xb);
  468. X                activeimage->uy = MAX (ya, yb);
  469. X                update_coordinates (activeimage, 0);
  470. X            }
  471. X            else
  472. X            {
  473. X                tw = activeimage->zoom->ux - activeimage->zoom->lx;
  474. X                th = activeimage->zoom->uy - activeimage->zoom->ly;
  475. X                xa = activeimage->zoom->lx + ((double) winx1 / (double) activeimage->pixwidth) * tw;
  476. X                ya = activeimage->zoom->uy - ((double) winy1 / (double) activeimage->pixheight) * th;
  477. X
  478. X                activeimage->pcolour = pixel_colour (activeimage, winx1, winy1);
  479. X                activeimage->px = xa;
  480. X                activeimage->py = ya;
  481. X                update_point (activeimage);
  482. X            }
  483. X            fflush (stdout);
  484. X            XFlush (display);
  485. X            break;
  486. X
  487. X        default:
  488. X            break;
  489. X        }
  490. X    }
  491. }
  492. X
  493. /************************************************************************
  494. *    do_unzoom()            button: unzoom        recalc previous zoom level.    *
  495. ************************************************************************/
  496. X
  497. void do_unzoom (w, client_data, call_data)
  498. Widget w;
  499. caddr_t client_data;
  500. caddr_t call_data;
  501. {
  502. X    if (activeimage->window == 0)
  503. X        return;
  504. X    if (activeimage->zoom) 
  505. X    {    /* selecting mooz before mandel invalid */
  506. X        if (zoomtmp = activeimage->zoom->zp) 
  507. X        {    /* last on stack */
  508. X            free(activeimage->zoom);
  509. X            activeimage->zoom = zoomtmp;
  510. X        }
  511. X        else
  512. X            return;
  513. X        if (activeimage == &manparm)
  514. X            mandel ();
  515. X        else
  516. X            julia (0, 0);
  517. X    }
  518. }
  519. X
  520. /************************************************************************
  521. *    pixel_colour()        return the colour of a pixel                    *
  522. ************************************************************************/
  523. X
  524. int pixel_colour (p, ix, iy)
  525. struct imageparm *p;
  526. int        ix, iy;
  527. {    int        colour, shift;
  528. X    unsigned char *imageline;
  529. X
  530. X    imageline = p->pix + iy * p->bytewidth;
  531. X    switch (depth)
  532. X    {
  533. X    case 8:
  534. X        colour = imageline[ix] & 0x0ff;
  535. X        break;
  536. X
  537. X    case 4:
  538. X        if (ix % 2)
  539. X            shift = 0;
  540. X        else
  541. X            shift = 4;
  542. X        colour = (imageline[ix >> 1] >> shift) & 0x0f;
  543. X        break;
  544. X
  545. X    case 2:
  546. X        switch (ix % 4)
  547. X        {
  548. X        case 0:        shift = 6;    break;
  549. X        case 1:        shift = 4;    break;
  550. X        case 2:        shift = 2;    break;
  551. X        case 3:        shift = 0;    break;
  552. X        }
  553. X        colour  = (imageline[ix >> 2] >> shift) & 0x03;
  554. X        break;
  555. X
  556. X    case 1:
  557. X        colour = (imageline[ix >> 3]  >> (7 - ix % 8)) & 0x01;
  558. X    }
  559. X    return (colour);
  560. }
  561. SHAR_EOF
  562. echo 'File mandel.c is complete' &&
  563. chmod 0644 mandel.c ||
  564. echo 'restore of mandel.c failed'
  565. Wc_c="`wc -c < 'mandel.c'`"
  566. test 15435 -eq "$Wc_c" ||
  567.     echo 'mandel.c: original size 15435, current size' "$Wc_c"
  568. rm -f _shar_wnt_.tmp
  569. fi
  570. # ============= mandel.h ==============
  571. if test -f 'mandel.h' -a X"$1" != X"-c"; then
  572.     echo 'x - skipping mandel.h (File already exists)'
  573.     rm -f _shar_wnt_.tmp
  574. else
  575. > _shar_wnt_.tmp
  576. echo 'x - extracting mandel.h (Text)'
  577. sed 's/^X//' << 'SHAR_EOF' > 'mandel.h' &&
  578. /* ta=4 */
  579. /*  xmandel.h  */
  580. X
  581. /* ---- some changes you may wish to make ------- */
  582. X
  583. /*  memcpy(dest,src,nbytes) is used in various routines.  If memcpy()
  584. X    is not available, use the #define for bcopy().  If  bcopy() is not
  585. X    available then enable "NEEDMEMCPY" to use a very inefficient
  586. X    memory copy.
  587. */
  588. X
  589. #ifdef HAVEBCOPY
  590. #define memcpy(a,b,c)    bcopy(b,a,c)    /* bsd type */
  591. #endif
  592. X
  593. /* #define NEEDMEMCPY                /* for systems with neither */
  594. X
  595. X
  596. /* set maximum depth of iteration for mandelbrot and julia sets. */
  597. X
  598. #define ITERATION_DEPTH        256
  599. X
  600. /* Check for exposure events after this many scan lines have been drawn
  601. X   by the Mandelbrot or Julia generator.  If you have a very large
  602. X   ITERATION_DEPTH (e.g. > 400) an EXPOSURE_TEST of 1 or 2 is reasonable  */
  603. X
  604. #define EXPOSURE_TEST        4
  605. X
  606. /* If a 256 colour display is used, Set a "color bias" to offset into 
  607. X   the colour table for colour value 0.  Iterations arc coloured
  608. X   as "iteration_count + COLOR_BIAS".
  609. */
  610. X
  611. #define COLOR_BIAS        16
  612. X
  613. /* Set a color value for INFINITY.  A value >= 0 assigns the specified
  614. X   colour number.  A value < 0 uses the "default" colour.
  615. */
  616. X
  617. #define INFINITY_COLOR        -1
  618. X
  619. /*  Initial starting coordinates for mandelbrot set */
  620. X
  621. #define START_LX -2.25
  622. #define START_UX  1.0
  623. #define START_LY -1.5
  624. #define START_UY  1.5
  625. X
  626. X
  627. /* ----- end configuration ------- */
  628. X
  629. #define MIN(a,b)((a) < (b) ? (a) : (b))
  630. #define MAX(a,b)((a) < (b) ? (b) : (a))
  631. #define ABS(a) ((a) < 0 ? (-a) : (a))
  632. X
  633. /*    for those places where I forgot to make the change... */
  634. X
  635. #define malloc(x)    XtMalloc(x)
  636. #define calloc(x,y)    XtCalloc(x,y)
  637. #define free(x)        XtFree(x)
  638. X
  639. typedef unsigned char    byte;
  640. X
  641. struct zoomd 
  642. {    struct zoomd *zp;        /*    previous zoom pointer        */
  643. X    double lx, ux;            /*    bounds for zoom                */
  644. X    double ly, uy;
  645. };
  646. X
  647. #define SAVESIZE 25
  648. X
  649. struct imageparm
  650. {    Window    window;            /* image in this window            */
  651. X    double    lx, ly, ux, uy;    /* image corner coordinates.    */
  652. X    double    px, py;            /* point location (for julia)    */
  653. X    int        rotation;        /* current colour rotation        */
  654. X    int        totrot;            /*    total rotation count        */
  655. X    int        pcolour;        /*    pixel colour                */
  656. X    long    pixheight;        /* image height in pixels        */
  657. X    long    pixwidth;        /* impage width in pixels        */
  658. X    long    bytewidth;        /* width of image line in bytes    */
  659. X    unsigned char *pix;        /* copy of generated image         */
  660. X    struct    zoomd *zoom;    /* zoom stack pointer            */
  661. X    char     sux[SAVESIZE];    /* text ux, uy etc. to detect    */
  662. X    char     suy[SAVESIZE];    /* if user changed values.        */
  663. X    char    slx[SAVESIZE];
  664. X    char    sly[SAVESIZE];
  665. } ;
  666. X
  667. struct enter_buttons
  668. {    char    *button;        /*    label text                    */
  669. X    int        bx;                /*    lable x                        */
  670. X    int        by;                /*    label y                        */
  671. X    char    *field;            /*    data field name                */
  672. X    int        fsize;            /*    data field size chars        */
  673. } ;
  674. X
  675. X
  676. struct button_list
  677. {    char    *ident;                /*    widget name                */
  678. X    void    (*bcall)();            /*    callback function        */
  679. X    int        x;                    /*    x column location        */
  680. X    int        y;                    /*    y row location            */
  681. } ;
  682. X
  683. X
  684. #ifdef __STDC__
  685. /* main.c */
  686. int main(int argc, char **argv);
  687. void update_coordinates(struct imageparm *image, int lf);
  688. void update_point(struct imageparm *image);
  689. /* mandel.c */
  690. void start_mandel(void);
  691. void redo_mandel(void);
  692. void expose_mandel(Widget w, caddr_t unused, XExposeEvent *event);
  693. void redraw_mandel(XExposeEvent *event);
  694. void do_zoom(Widget w, caddr_t client_data, caddr_t call_data);
  695. void do_unzoom(Widget w, caddr_t client_data, caddr_t call_data);
  696. int pixel_colour(struct imageparm *p, int ix, int iy);
  697. /* julia.c */
  698. void start_julia(int destroy_pixmap, int newimage);
  699. void julia(int destroy_pixmap, int newimage);
  700. void expose_julia(Widget w, caddr_t unused, XExposeEvent *event);
  701. void redraw_julia(XExposeEvent *event);
  702. /* writegif.c */
  703. void ws1te_gif_image(char *fname, struct imageparm *imageinfo);
  704. #else
  705. /* main.c */
  706. int main();
  707. void update_coordinates();
  708. void update_point();
  709. /* mandel.c */
  710. void start_mandel();
  711. void redo_mandel();
  712. void expose_mandel();
  713. void redraw_mandel();
  714. void do_zoom();
  715. void do_unzoom();
  716. int pixel_colour();
  717. /* julia.c */
  718. void start_julia();
  719. void julia();
  720. void expose_julia();
  721. void redraw_julia();
  722. /* writegif.c */
  723. void write_gif_image();
  724. #endif
  725. SHAR_EOF
  726. chmod 0644 mandel.h ||
  727. echo 'restore of mandel.h failed'
  728. Wc_c="`wc -c < 'mandel.h'`"
  729. test 4079 -eq "$Wc_c" ||
  730.     echo 'mandel.h: original size 4079, current size' "$Wc_c"
  731. rm -f _shar_wnt_.tmp
  732. fi
  733. # ============= writegif.c ==============
  734. if test -f 'writegif.c' -a X"$1" != X"-c"; then
  735.     echo 'x - skipping writegif.c (File already exists)'
  736.     rm -f _shar_wnt_.tmp
  737. else
  738. > _shar_wnt_.tmp
  739. echo 'x - extracting writegif.c (Text)'
  740. sed 's/^X//' << 'SHAR_EOF' > 'writegif.c' &&
  741. /* ta=4 */
  742. #include <stdio.h>
  743. #include <X11/Intrinsic.h>
  744. #include <X11/Xlib.h>
  745. #include <X11/Xutil.h>
  746. #include <X11/Xos.h>
  747. #include <X11/Shell.h>
  748. #include "mandel.h"
  749. X
  750. #define MAX_COLORS 3
  751. X
  752. unsigned char    rmap[256], gmap[256], bmap[256];
  753. static struct imageparm    *image;
  754. extern Display *display;
  755. X
  756. extern int depth;
  757. typedef long int        count_int;
  758. X
  759. #ifdef __STDC__
  760. static int getcolors(void);
  761. static int writegif(FILE *fp, byte *pic, int w, int h, byte *rmap, byte *gmap, byte *bmap, int numcols, int colorstyle);
  762. static void putword(int w, FILE *fp);
  763. static void compress(int init_bits, FILE *outfile, byte *data, int len);
  764. static void output(int code);
  765. static void cl_block(void);
  766. static void cl_hash(register count_int hsize);
  767. static void char_init(void);
  768. static void char_out(int c);
  769. static void flush_char(void);
  770. #else
  771. static int getcolors();
  772. static int writegif();
  773. static void putword();
  774. static void compress();
  775. static void output();
  776. static void cl_block();
  777. static void cl_hash();
  778. static void char_init();
  779. static void char_out();
  780. static void flush_char();
  781. #endif
  782. X
  783. /************************************************************************
  784. *    write_gif ()                                                        *
  785. *    X11 image data recorded in *image->pix has pixel colors comressed     *
  786. *    to     adjacent bits.  If there are less than 8 bits per pixel, unpack    *
  787. *    the bytes - GIF format must have one pixel per output byte.            *
  788. *    After compression, the wasted space is obviously removed.            *
  789. ************************************************************************/
  790. X
  791. void write_gif_image (fname, imageinfo)
  792. char     *fname;
  793. struct imageparm *imageinfo;
  794. {    FILE    *fp;
  795. X    int        i;
  796. X    int        ncolors;
  797. X    int        ix, iy, shift;
  798. X    byte    *bytes, *these_bits, *input, *output;
  799. X
  800. X    image = imageinfo;
  801. X    if (image->pix == NULL)
  802. X        return;
  803. X
  804. X    for (i = 0;  i < 256;  i++)
  805. X        rmap[i] = gmap[i] = bmap[i] = 0;
  806. X
  807. X    fp = fopen (fname, "w");
  808. X    if (fp == NULL)
  809. X    {    printf ("Cannot open gif output file\n");
  810. X        exit (0);
  811. X    }
  812. X    ncolors = getcolors();
  813. X    if (depth != 8)
  814. X    {    bytes = (byte *) malloc (image->pixheight *  image->pixwidth);
  815. X        for (iy = 0; iy < image->pixheight;  iy++)
  816. X        {
  817. X            output = bytes + iy * image->pixwidth;
  818. X            input = image->pix  + iy * image->bytewidth;
  819. X            switch (depth)
  820. X            {
  821. X            case 4:
  822. X                for (ix = 0; ix < image->pixwidth; ix++)
  823. X                {    if (ix % 2)
  824. X                        shift = 0;
  825. X                    else
  826. X                        shift = 4;
  827. X                    output[ix] = (input[ix >> 1] >> shift) & 0x0f;
  828. X                }
  829. X                break;
  830. X
  831. X            case 2:
  832. X                for (ix = 0; ix < image->pixwidth; ix++)
  833. X                {    switch (ix % 4)
  834. X                    {
  835. X                    case 0:        shift = 6;    break;
  836. X                    case 1:        shift = 4;    break;
  837. X                    case 2:        shift = 2;    break;
  838. X                    case 3:        shift = 0;    break;
  839. X                    }
  840. X                    output[ix] = (input[ix >> 2] >> shift) & 0x03;
  841. X                }
  842. X                break;
  843. X
  844. X            case 1:
  845. X                for (ix = 0; ix < image->pixwidth; ix++)
  846. X                    output[ix] = (input[ix >> 3]  >> (7 - ix % 8)) & 0x01;
  847. X            }
  848. X        }
  849. X        these_bits = bytes;
  850. X    }
  851. X    else
  852. X    {    these_bits = image->pix;
  853. X        bytes = NULL;
  854. X    }
  855. X    writegif (fp, these_bits, image->pixwidth, image->pixheight, rmap, gmap, bmap, ncolors, 0);
  856. X    if (bytes)
  857. X        free (bytes);
  858. X    fclose (fp);
  859. }
  860. X
  861. /************************************************************************
  862. *    getcolors ()        get current colour map in rgb for gif output    *
  863. ************************************************************************/
  864. X
  865. static int getcolors ()
  866. {
  867. X    Colormap default_cmap;
  868. X    int    ncolors, i;
  869. X    XColor    my_colors[256];
  870. X
  871. X    ncolors = DisplayCells (display, DefaultScreen (display));
  872. X    default_cmap = DefaultColormap (display, DefaultScreen (display));
  873. X    for (i = 0;  i < DisplayCells (display, 0);  i++)
  874. X    {    my_colors[i].pixel = i;
  875. X        my_colors[i].flags = DoRed | DoGreen | DoBlue;
  876. X    }
  877. X
  878. X    XQueryColors (display, default_cmap, my_colors, ncolors);
  879. X
  880. X    /*    scale the colours to a 0..255 range as expected by GIF
  881. X        X11 always gives RGB values as a 16 bit number.
  882. X    */
  883. X    for (i = 0;  i < ncolors;  i++)
  884. X    {    rmap[i] = (double) my_colors[i].red / 256.0;
  885. X        gmap[i] = (double) my_colors[i].green / 256.0;
  886. X        bmap[i] = (double) my_colors[i].blue / 256.0;
  887. X    }
  888. X    return (ncolors);
  889. }
  890. X
  891. X
  892. /*    Extracted for the XV.2.11 source distribution....
  893. X *
  894. X * xvgifwr.c  -  handles writing of GIF files.  based on flgife.c and
  895. X *               flgifc.c from the FBM Library, by Michael Maudlin
  896. X *
  897. X * Contains: 
  898. X *   WriteGIF(fp, pic, w, h, rmap, gmap, bmap, numcols, colorstyle)
  899. X *
  900. X * Note: slightly brain-damaged, in that it'll only write non-interlaced 
  901. X *       GIF files (in the interests of speed, or something)
  902. X *
  903. X */
  904. X
  905. X
  906. X
  907. /*****************************************************************
  908. X * Portions of this code Copyright (C) 1989 by Michael Mauldin.
  909. X * Permission is granted to use this file in whole or in part provided
  910. X * that you do not sell it for profit and that this copyright notice
  911. X * and the names of all authors are retained unchanged.
  912. X *
  913. X * Authors:  Michael Mauldin (mlm@cs.cmu.edu)
  914. X *           David Rowley (mgardi@watdcsu.waterloo.edu)
  915. X *
  916. X * Based on: compress.c - File compression ala IEEE Computer, June 1984.
  917. X *
  918. X *    Spencer W. Thomas       (decvax!harpo!utah-cs!utah-gr!thomas)
  919. X *    Jim McKie               (decvax!mcvax!jim)
  920. X *    Steve Davies            (decvax!vax135!petsd!peora!srd)
  921. X *    Ken Turkowski           (decvax!decwrl!turtlevax!ken)
  922. X *    James A. Woods          (decvax!ihnp4!ames!jaw)
  923. X *    Joe Orost               (decvax!vax135!petsd!joe)
  924. X *****************************************************************/
  925. /*
  926. X * Copyright 1989, 1990 by the University of Pennsylvania
  927. X *
  928. X * Permission to use, copy, and distribute for non-commercial purposes,
  929. X * is hereby granted without fee, providing that the above copyright
  930. X * notice appear in all copies and that both the copyright notice and this
  931. X * permission notice appear in supporting documentation.
  932. X *
  933. X * The software may be modified for your own purposes, but modified versions
  934. X * may not be distributed.
  935. X *
  936. X * This software is provided "as is" without any express or implied warranty.
  937. X */
  938. X
  939. X
  940. /* MONO returns total intensity of r,g,b components */
  941. X
  942. #define MONO(rd,gn,bl) (((rd)*11 + (gn)*16 + (bl)*5) >> 5)  /*.33R+ .5G+ .17B*/
  943. X
  944. int DEBUG = 0;
  945. X
  946. static int  Width, Height;
  947. static int  curx, cury;
  948. static long CountDown;
  949. static int  Interlace;
  950. static byte bw[2] = {0, 0xff};
  951. X
  952. /*************************************************************/
  953. static int writegif (fp, pic, w, h, rmap, gmap, bmap, numcols, colorstyle)
  954. FILE *fp;
  955. byte *pic;
  956. int   w,h;
  957. byte *rmap, *gmap, *bmap;
  958. int   numcols, colorstyle;
  959. {
  960. X  int RWidth, RHeight;
  961. X  int LeftOfs, TopOfs;
  962. X  int Resolution, ColorMapSize, InitCodeSize, Background, BitsPerPixel;
  963. X  int i,j;
  964. X
  965. X
  966. X  /* if writing B/W stipple... */
  967. X  if (colorstyle==2) {
  968. X    rmap = gmap = bmap = bw;
  969. X    numcols = 2;
  970. X  }
  971. X
  972. X  Interlace = 0;
  973. X  Background = 0;
  974. X
  975. X  /* figure out 'BitsPerPixel' */
  976. X  for (i=1; i<8; i++)
  977. X    if ( (1<<i) >= numcols) break;
  978. X  
  979. X  BitsPerPixel = i;
  980. X
  981. X  ColorMapSize = 1 << BitsPerPixel;
  982. X    
  983. X  RWidth  = Width  = w;
  984. X  RHeight = Height = h;
  985. X  LeftOfs = TopOfs = 0;
  986. X    
  987. X  Resolution = BitsPerPixel;
  988. X
  989. X  CountDown = w * h;    /* # of pixels we'll be doing */
  990. X
  991. X  if (BitsPerPixel <= 1) InitCodeSize = 2;
  992. X                    else InitCodeSize = BitsPerPixel;
  993. X
  994. X  curx = cury = 0;
  995. X
  996. X  if (!fp) {
  997. X    fprintf(stderr,  "WriteGIF: file not open for writing\n" );
  998. X    return (1);
  999. X  }
  1000. X
  1001. X  if (DEBUG) 
  1002. X    fprintf(stderr,"WrGIF: pic=%lx, w,h=%dx%d, numcols=%d, Bits%d,Cmap=%d\n",
  1003. X        pic, w,h,numcols,BitsPerPixel,ColorMapSize);
  1004. X
  1005. X  fwrite("GIF87a", 1, 6, fp);    /* the GIF magic number */
  1006. X
  1007. X  putword(RWidth, fp);           /* screen descriptor */
  1008. X  putword(RHeight, fp);
  1009. X
  1010. X  i = 0x80;                     /* Yes, there is a color map */
  1011. X  i |= (8-1)<<4;                 /* OR in the color resolution (hardwired 8) */
  1012. X  i |= (BitsPerPixel - 1);       /* OR in the # of bits per pixel */
  1013. X  fputc(i,fp);          
  1014. X
  1015. X  fputc(Background, fp);         /* background color */
  1016. X
  1017. X  fputc(0, fp);                  /* future expansion byte */
  1018. X
  1019. X
  1020. X  if (colorstyle == 1) {         /* greyscale */
  1021. X    for (i=0; i<ColorMapSize; i++) {
  1022. X      j = MONO(rmap[i], gmap[i], bmap[i]);
  1023. X      fputc(j, fp);
  1024. X      fputc(j, fp);
  1025. X      fputc(j, fp);
  1026. X    }
  1027. X  }
  1028. X  else {
  1029. X    for (i=0; i<ColorMapSize; i++) {       /* write out Global colormap */
  1030. X      fputc(rmap[i], fp);
  1031. X      fputc(gmap[i], fp);
  1032. X      fputc(bmap[i], fp);
  1033. X    }
  1034. X  }
  1035. X
  1036. X  fputc( ',', fp );              /* image separator */
  1037. X
  1038. X  /* Write the Image header */
  1039. X  putword(LeftOfs, fp);
  1040. X  putword(TopOfs,  fp);
  1041. X  putword(Width,   fp);
  1042. X  putword(Height,  fp);
  1043. X  if (Interlace) fputc(0x40, fp);   /* Use Global Colormap, maybe Interlace */
  1044. X            else fputc(0x00, fp);
  1045. X
  1046. X  fputc(InitCodeSize, fp);
  1047. X  compress(InitCodeSize+1, fp, pic, w*h);
  1048. X
  1049. X  fputc(0,fp);                      /* Write out a Zero-length packet (EOF) */
  1050. X  fputc(';',fp);                    /* Write GIF file terminator */
  1051. X
  1052. X  return (0);
  1053. }
  1054. X
  1055. X
  1056. X
  1057. X
  1058. /******************************/
  1059. static void putword(w, fp)
  1060. int w;
  1061. FILE *fp;
  1062. {
  1063. X  /* writes a 16-bit integer in GIF order (LSB first) */
  1064. X  fputc(w & 0xff, fp);
  1065. X  fputc((w>>8)&0xff, fp);
  1066. }
  1067. X
  1068. X
  1069. X
  1070. X
  1071. /***********************************************************************/
  1072. X
  1073. X
  1074. static unsigned long cur_accum = 0;
  1075. static int           cur_bits = 0;
  1076. X
  1077. X
  1078. X
  1079. X
  1080. #define min(a,b)        ((a>b) ? b : a)
  1081. X
  1082. #define BITS    12
  1083. #define MSDOS    1
  1084. X
  1085. #define HSIZE  5003            /* 80% occupancy */
  1086. X
  1087. typedef unsigned char   char_type;
  1088. X
  1089. X
  1090. static int n_bits;                   /* number of bits/code */
  1091. static int maxbits = BITS;           /* user settable max # bits/code */
  1092. static int maxcode;                  /* maximum code, given n_bits */
  1093. static int maxmaxcode = 1 << BITS;   /* NEVER generate this */
  1094. X
  1095. #define MAXCODE(n_bits)     ( (1 << (n_bits)) - 1)
  1096. X
  1097. static  count_int      htab [HSIZE];
  1098. static  unsigned short codetab [HSIZE];
  1099. #define HashTabOf(i)   htab[i]
  1100. #define CodeTabOf(i)   codetab[i]
  1101. X
  1102. static int hsize = HSIZE;            /* for dynamic table sizing */
  1103. X
  1104. /*
  1105. X * To save much memory, we overlay the table used by compress() with those
  1106. X * used by decompress().  The tab_prefix table is the same size and type
  1107. X * as the codetab.  The tab_suffix table needs 2**BITS characters.  We
  1108. X * get this from the beginning of htab.  The output stack uses the rest
  1109. X * of htab, and contains characters.  There is plenty of room for any
  1110. X * possible stack (stack used to be 8000 characters).
  1111. X */
  1112. X
  1113. #define tab_prefixof(i) CodeTabOf(i)
  1114. #define tab_suffixof(i)        ((char_type *)(htab))[i]
  1115. #define de_stack               ((char_type *)&tab_suffixof(1<<BITS))
  1116. X
  1117. static int free_ent = 0;                  /* first unused entry */
  1118. X
  1119. /*
  1120. X * block compression parameters -- after all codes are used up,
  1121. X * and compression rate changes, start over.
  1122. X */
  1123. static int clear_flg = 0;
  1124. X
  1125. static long int in_count = 1;            /* length of input */
  1126. static long int out_count = 0;           /* # of codes output (for debugging) */
  1127. X
  1128. /*
  1129. X * compress stdin to stdout
  1130. X *
  1131. X * Algorithm:  use open addressing double hashing (no chaining) on the 
  1132. X * prefix code / next character combination.  We do a variant of Knuth's
  1133. X * algorithm D (vol. 3, sec. 6.4) along with G. Knott's relatively-prime
  1134. X * secondary probe.  Here, the modular division first probe is gives way
  1135. X * to a faster exclusive-or manipulation.  Also do block compression with
  1136. X * an adaptive reset, whereby the code table is cleared when the compression
  1137. X * ratio decreases, but after the table fills.  The variable-length output
  1138. X * codes are re-sized at this point, and a special CLEAR code is generated
  1139. X * for the decompressor.  Late addition:  construct the table according to
  1140. X * file size for noticeable speed improvement on small files.  Please direct
  1141. X * questions about this implementation to ames!jaw.
  1142. X */
  1143. X
  1144. static int g_init_bits;
  1145. static FILE *g_outfile;
  1146. X
  1147. static int ClearCode;
  1148. static int EOFCode;
  1149. X
  1150. X
  1151. /********************************************************/
  1152. static void compress(init_bits, outfile, data, len)
  1153. int   init_bits;
  1154. FILE *outfile;
  1155. byte *data;
  1156. int   len;
  1157. {
  1158. X  register long fcode;
  1159. X  register int i = 0;
  1160. X  register int c;
  1161. X  register int ent;
  1162. X  register int disp;
  1163. X  register int hsize_reg;
  1164. X  register int hshift;
  1165. X
  1166. X  /*
  1167. X   * Set up the globals:  g_init_bits - initial number of bits
  1168. X   *                      g_outfile   - pointer to output file
  1169. X   */
  1170. X  g_init_bits = init_bits;
  1171. X  g_outfile   = outfile;
  1172. X
  1173. X  /* initialize 'compress' globals */
  1174. X  maxbits = BITS;
  1175. X  maxmaxcode = 1<<BITS;
  1176. X  memset((char *) htab, 0, sizeof(htab));
  1177. X  memset((char *) codetab, 0, sizeof(codetab));
  1178. X  hsize = HSIZE;
  1179. X  free_ent = 0;
  1180. X  clear_flg = 0;
  1181. X  in_count = 1;
  1182. X  out_count = 0;
  1183. X  cur_accum = 0;
  1184. X  cur_bits = 0;
  1185. X
  1186. X
  1187. X  /*
  1188. X   * Set up the necessary values
  1189. X   */
  1190. X  out_count = 0;
  1191. X  clear_flg = 0;
  1192. X  in_count = 1;
  1193. X  maxcode = MAXCODE(n_bits = g_init_bits);
  1194. X
  1195. X  ClearCode = (1 << (init_bits - 1));
  1196. X  EOFCode = ClearCode + 1;
  1197. X  free_ent = ClearCode + 2;
  1198. X
  1199. X  char_init();
  1200. X  ent = *data++;  len--;
  1201. X
  1202. X  hshift = 0;
  1203. X  for ( fcode = (long) hsize;  fcode < 65536L; fcode *= 2L )
  1204. X    hshift++;
  1205. X  hshift = 8 - hshift;                /* set hash code range bound */
  1206. X
  1207. X  hsize_reg = hsize;
  1208. X  cl_hash( (count_int) hsize_reg);            /* clear hash table */
  1209. X
  1210. X  output(ClearCode);
  1211. X    
  1212. X  while (len) {
  1213. X    c = *data++;  len--;
  1214. X    in_count++;
  1215. X
  1216. X    fcode = (long) ( ( (long) c << maxbits) + ent);
  1217. X    i = (((int) c << hshift) ^ ent);    /* xor hashing */
  1218. X
  1219. X    if ( HashTabOf (i) == fcode ) {
  1220. X      ent = CodeTabOf (i);
  1221. X      continue;
  1222. X    }
  1223. X
  1224. X    else if ( (long)HashTabOf (i) < 0 )      /* empty slot */
  1225. X      goto nomatch;
  1226. X
  1227. X    disp = hsize_reg - i;           /* secondary hash (after G. Knott) */
  1228. X    if ( i == 0 )
  1229. X      disp = 1;
  1230. X
  1231. probe:
  1232. X    if ( (i -= disp) < 0 )
  1233. X      i += hsize_reg;
  1234. X
  1235. X    if ( HashTabOf (i) == fcode ) {
  1236. X      ent = CodeTabOf (i);
  1237. X      continue;
  1238. X    }
  1239. X
  1240. X    if ( (long)HashTabOf (i) > 0 ) 
  1241. X      goto probe;
  1242. X
  1243. nomatch:
  1244. X    output(ent);
  1245. X    out_count++;
  1246. X    ent = c;
  1247. X
  1248. X    if ( free_ent < maxmaxcode ) {
  1249. X      CodeTabOf (i) = free_ent++; /* code -> hashtable */
  1250. X      HashTabOf (i) = fcode;
  1251. X    }
  1252. X    else
  1253. X      cl_block();
  1254. X  }
  1255. X
  1256. X  /* Put out the final code */
  1257. X  output(ent);
  1258. X  out_count++;
  1259. X  output(EOFCode);
  1260. }
  1261. X
  1262. X
  1263. /*****************************************************************
  1264. X * TAG( output )
  1265. X *
  1266. X * Output the given code.
  1267. X * Inputs:
  1268. X *      code:   A n_bits-bit integer.  If == -1, then EOF.  This assumes
  1269. X *              that n_bits =< (long)wordsize - 1.
  1270. X * Outputs:
  1271. X *      Outputs code to the file.
  1272. X * Assumptions:
  1273. X *      Chars are 8 bits long.
  1274. X * Algorithm:
  1275. X *      Maintain a BITS character long buffer (so that 8 codes will
  1276. X * fit in it exactly).  Use the VAX insv instruction to insert each
  1277. X * code in turn.  When the buffer fills up empty it and start over.
  1278. X */
  1279. X
  1280. static
  1281. unsigned long masks[] = { 0x0000, 0x0001, 0x0003, 0x0007, 0x000F,
  1282. X                                  0x001F, 0x003F, 0x007F, 0x00FF,
  1283. X                                  0x01FF, 0x03FF, 0x07FF, 0x0FFF,
  1284. X                                  0x1FFF, 0x3FFF, 0x7FFF, 0xFFFF };
  1285. X
  1286. static void output(code)
  1287. int code;
  1288. {
  1289. X  cur_accum &= masks[cur_bits];
  1290. X
  1291. X  if (cur_bits > 0)
  1292. X    cur_accum |= ((long)code << cur_bits);
  1293. X  else
  1294. X    cur_accum = code;
  1295. X    
  1296. X  cur_bits += n_bits;
  1297. X
  1298. X  while( cur_bits >= 8 ) {
  1299. X    char_out( (unsigned int) (cur_accum & 0xff) );
  1300. X    cur_accum >>= 8;
  1301. X    cur_bits -= 8;
  1302. X  }
  1303. X
  1304. X  /*
  1305. X   * If the next entry is going to be too big for the code size,
  1306. X   * then increase it, if possible.
  1307. X   */
  1308. X
  1309. X  if (free_ent > maxcode || clear_flg) {
  1310. X
  1311. X    if( clear_flg ) {
  1312. X      maxcode = MAXCODE (n_bits = g_init_bits);
  1313. X      clear_flg = 0;
  1314. X    }
  1315. X    else {
  1316. X      n_bits++;
  1317. X      if ( n_bits == maxbits )
  1318. X    maxcode = maxmaxcode;
  1319. X      else
  1320. X    maxcode = MAXCODE(n_bits);
  1321. X    }
  1322. X  }
  1323. X    
  1324. X  if( code == EOFCode ) {
  1325. X    /* At EOF, write the rest of the buffer */
  1326. X    while( cur_bits > 0 ) {
  1327. X      char_out( (unsigned int)(cur_accum & 0xff) );
  1328. X      cur_accum >>= 8;
  1329. X      cur_bits -= 8;
  1330. X    }
  1331. X
  1332. X    flush_char();
  1333. X    
  1334. X    fflush( g_outfile );
  1335. X
  1336. X    if( ferror( g_outfile ) )
  1337. X    {    printf ("unable to write GIF file\n");
  1338. X        exit (1);
  1339. X    }
  1340. X  }
  1341. }
  1342. X
  1343. X
  1344. /********************************/
  1345. static void cl_block ()             /* table clear for block compress */
  1346. {
  1347. X  /* Clear out the hash table */
  1348. X
  1349. X  cl_hash ( (count_int) hsize );
  1350. X  free_ent = ClearCode + 2;
  1351. X  clear_flg = 1;
  1352. X
  1353. X  output(ClearCode);
  1354. }
  1355. X
  1356. X
  1357. /********************************/
  1358. static void cl_hash(hsize)          /* reset code table */
  1359. register count_int hsize;
  1360. {
  1361. X  register count_int *htab_p = htab+hsize;
  1362. X  register long i;
  1363. X  register long m1 = -1;
  1364. X
  1365. X  i = hsize - 16;
  1366. X  do {                            /* might use Sys V memset(3) here */
  1367. X    *(htab_p-16) = m1;
  1368. X    *(htab_p-15) = m1;
  1369. X    *(htab_p-14) = m1;
  1370. X    *(htab_p-13) = m1;
  1371. X    *(htab_p-12) = m1;
  1372. X    *(htab_p-11) = m1;
  1373. X    *(htab_p-10) = m1;
  1374. X    *(htab_p-9) = m1;
  1375. X    *(htab_p-8) = m1;
  1376. X    *(htab_p-7) = m1;
  1377. X    *(htab_p-6) = m1;
  1378. X    *(htab_p-5) = m1;
  1379. X    *(htab_p-4) = m1;
  1380. X    *(htab_p-3) = m1;
  1381. X    *(htab_p-2) = m1;
  1382. X    *(htab_p-1) = m1;
  1383. X    htab_p -= 16;
  1384. X  } while ((i -= 16) >= 0);
  1385. X
  1386. X  for ( i += 16; i > 0; i-- )
  1387. X    *--htab_p = m1;
  1388. }
  1389. X
  1390. X
  1391. /******************************************************************************
  1392. X *
  1393. X * GIF Specific routines
  1394. X *
  1395. X ******************************************************************************/
  1396. X
  1397. /*
  1398. X * Number of characters so far in this 'packet'
  1399. X */
  1400. static int a_count;
  1401. X
  1402. /*
  1403. X * Set up the 'byte output' routine
  1404. X */
  1405. static void char_init()
  1406. {
  1407. X    a_count = 0;
  1408. }
  1409. X
  1410. /*
  1411. X * Define the storage for the packet accumulator
  1412. X */
  1413. static char accum[ 256 ];
  1414. X
  1415. /*
  1416. X * Add a character to the end of the current packet, and if it is 254
  1417. X * characters, flush the packet to disk.
  1418. X */
  1419. static void char_out(c)
  1420. int c;
  1421. {
  1422. X  accum[ a_count++ ] = c;
  1423. X  if( a_count >= 254 ) 
  1424. X    flush_char();
  1425. }
  1426. X
  1427. /*
  1428. X * Flush the packet to disk, and reset the accumulator
  1429. X */
  1430. static void flush_char()
  1431. {
  1432. X  if( a_count > 0 ) {
  1433. X    fputc( a_count, g_outfile );
  1434. X    fwrite( accum, 1, a_count, g_outfile );
  1435. X    a_count = 0;
  1436. X  }
  1437. }    
  1438. SHAR_EOF
  1439. chmod 0644 writegif.c ||
  1440. echo 'restore of writegif.c failed'
  1441. Wc_c="`wc -c < 'writegif.c'`"
  1442. test 17660 -eq "$Wc_c" ||
  1443.     echo 'writegif.c: original size 17660, current size' "$Wc_c"
  1444. rm -f _shar_wnt_.tmp
  1445. fi
  1446. # ============= xmandel.man ==============
  1447. if test -f 'xmandel.man' -a X"$1" != X"-c"; then
  1448.     echo 'x - skipping xmandel.man (File already exists)'
  1449.     rm -f _shar_wnt_.tmp
  1450. else
  1451. > _shar_wnt_.tmp
  1452. echo 'x - extracting xmandel.man (Text)'
  1453. sed 's/^X//' << 'SHAR_EOF' > 'xmandel.man' &&
  1454. .TH XMANDEL X " 25 April 1992" "X Version 11"
  1455. .UC 4
  1456. .SH NAME
  1457. xmandel \- X11 interface to the Mandelbrot and Julia sets
  1458. .SH SYNOPSIS
  1459. xmandel [-display display]
  1460. .SH DESCRIPTION
  1461. .PP
  1462. .IR Xmandel
  1463. is a user friendly interface for generating and colouring Mandelbrot and Julia sets.
  1464. It initially comes up with with eleven or so command buttons,
  1465. which are described below, for controlling the execution.
  1466. A Mandelbrot set is drawn in the window of the initial form
  1467. when the \fImandel\fP button is selected.
  1468. A separate window is created for drawing the Julia sets.
  1469. .SH THEORY
  1470. Let z0 be a number in the complex plane (x + yi). 
  1471. Choose a complex constant C.  
  1472. Calculate z1 = z0 ** 2 + C.
  1473. Repeat this recursively, so that z2 = z1 ** 2 + C,
  1474. z3 = z2 ** 2 + C and so on.
  1475. z[n] will either tend to infinity or zero, depending
  1476. on its initial value and the constant C.
  1477. Specifically if the absolute value of z[n], 
  1478. expressed as |z| = sqrt(x**2 + y**2) is greater than 2,
  1479. then the recursive formula will diverge.
  1480. .PP
  1481. So, to calculate a Julia set, take each point near (0,0i),
  1482. and use the formula z = z**2 + C recursively.
  1483. The Julia set is the set of points for which
  1484. z = z**2 + C would iterate indefinitely for the constant C.
  1485. Pixels, which represent numbers in the complex plane,
  1486. are set to the number of iterations before |z| exceeds 2.
  1487. This then becomes an index into the hardware colormap.
  1488. Each color then represents the number of iterations before
  1489. divergence is detected.
  1490. .PP
  1491. To calculate a Mandelbrot set, again take each point near (0,0i),
  1492. use the same formula z = z**2 + C recursively.
  1493. This time let C be the initial value of the point itself (C = z0).
  1494. Rather than having the same C for every point in the complex plane
  1495. as in Julia set calculations,
  1496. C is different for each point in the plane.
  1497. Again let the pixel value be the number of iterations
  1498. before |z| exceeds 2.
  1499. .PP
  1500. On monochrome displays, the pixel value is set to 1
  1501. if the iteration count is 64, otherwise 0.
  1502. .PP
  1503. Mandelbrot sets and Julia sets are obviously closely
  1504. related as can be seen from the similarity of their
  1505. respective formulas.
  1506. If the constant C is chosen from the interior of the
  1507. Mandelbrot set, then the Julia set calculated from that
  1508. constant C will be connected, that is have no gaps or discontinuities.
  1509. If the constant C is chosen from outside the Mandelbrot set,
  1510. the Julia set will be disconnected, more like grains of dust (Fatou clouds).
  1511. If the constant C is chosen from the border of the Mandelbrot set, 
  1512. then the Julia set will be more convoluted.
  1513. Given this relationship between points in the Mandelbrot set
  1514. and the Julia set generated, 
  1515. XXmandel provides user selection of the constant C
  1516. by mouse selection in the Mandelbrot window.
  1517. .SH BUTTONS
  1518. To control execution of the calculations, various buttons
  1519. are provided.  The buttons are somewhat different between
  1520. the Athena Widget and Motif Widget implementations.
  1521. The buttons are:
  1522. .TP
  1523. .B mandel
  1524. Calculates a Mandelbrot set from (-2.25, -1.5) to (1.0, 1.5)
  1525. and display it in the window provided.  
  1526. X
  1527. Pressing a mouse button with the cursor in
  1528. the drawing window terminates the calculations.
  1529. .TP
  1530. .B julia
  1531. Calculates a Julia set.
  1532. The user is required to select a point inside the Mandelbrot window using 
  1533. the left mouse button as the constant C for the Julia set calculation.
  1534. It will open a new window if needed.
  1535. The Julia set is centered around (0,0),
  1536. going from (-1.5, -1.5) to (1.5, 1.5).
  1537. Julia set points can be selected from zoomed in Mandelbrot windows as well.
  1538. Beware of selecting points outside the Mandelbrot window.
  1539. X
  1540. Pressing a mouse button in the drawing window terminates the calculations.
  1541. .TP
  1542. .B Image
  1543. After the Mandelbrot or Julia set is generated, the
  1544. .I Image
  1545. button identifies which set is to be used for various manipluations
  1546. such as
  1547. .I zoom
  1548. or 
  1549. .I +colour.
  1550. If this button is pressed, the active image toggles between "Mandel"
  1551. and "Julia" to identify the set that is to be manipulated.
  1552. X
  1553. The Motif implementation uses radio buttons for this toggle.
  1554. .TP
  1555. .B zoom
  1556. In order to zoom in on a given area in the Mandelbrot or Julia set,
  1557. a zoom button is provided.
  1558. The area to be zoomed in on is selected with the left mouse button.
  1559. Left button down begins the selection,
  1560. dragging with left button down draws a rubber banded box to show the zoom area,
  1561. and left button up begins the calculation.
  1562. You can zoom in on a zoomed in area until you reach
  1563. the limits of the precision of your hardware.
  1564. Selecting a zoom area that crosses a window border doesn't work.
  1565. X
  1566. To a certain degree, the zoom rubber banded box may be moved, enlarged
  1567. and otherwise resized by careful use of the mouse.
  1568. X
  1569. Zoom requests less than 5 pixels wide are ignored.  The zoom
  1570. request may be terminated by pressing button 2 or 3 while creating
  1571. the rubber band.
  1572. X
  1573. If the Motif version is used, the zoom coordinates may be specified
  1574. in the
  1575. .I ZOOM COORDINATES
  1576. dialogue boxes.  After the desired coodinates are enterd, pressing the
  1577. .I zoom
  1578. button activates the drawing.
  1579. .TP
  1580. .B unzoom
  1581. Return to previous zoom.  
  1582. Note that you can zoom all the way out by selecting the \fImandel\fP button.
  1583. .TP
  1584. .B recalc
  1585. Recompute the set at the current coordinates.  This is useful
  1586. to redisplay the current image after the set's window has been
  1587. resized.
  1588. X
  1589. If the Motif version is used, the coordinates for recalculation may be
  1590. modified in the
  1591. .I ZOOM COORDINATES
  1592. dialogue boxes.
  1593. .TP
  1594. .B colour
  1595. The
  1596. .I colour
  1597. button selects colour rotation value to be applied when the
  1598. .I +colour
  1599. or
  1600. .I -colour
  1601. buttons are used.
  1602. X
  1603. The "colour step" value is added to each pixel colour before redisplay.
  1604. The effectively rotates the image through the available colour map.
  1605. By default, the rotation value is set to the number of bit planes: for
  1606. an 8 bit display, the rotation value is 8; for a 2 bit display, the rotation
  1607. value is 2; etc.
  1608. X
  1609. The selected set and rotation value is "remembered" for use with the
  1610. .I \+colour
  1611. and
  1612. .I \-colour
  1613. buttons.
  1614. X
  1615. The "rotate" dialogue box in the Motif edition is used to set
  1616. the colour rotation value.
  1617. .TP
  1618. .B \+colour
  1619. The default set
  1620. is rotated in a positive sense by adding the previously 
  1621. specified colour rotation value to all pixels. 
  1622. X
  1623. An interesting "colour zoom" effect can be achieved by first setting the
  1624. colour rotation value to 1 and rapidly pressing the
  1625. .I \+colour
  1626. or
  1627. .I \-colour
  1628. button.
  1629. .TP
  1630. .B \-colour
  1631. The default set
  1632. is rotated in a negative sense by subtracting the previously 
  1633. specified colour rotation value.  In effect,
  1634. .I \-colour
  1635. undoes the effect of
  1636. .I \+colour.
  1637. .TP
  1638. .B gif
  1639. Either the Mandelbrot or Julia image may be captured to a GIF file.
  1640. The Mandelbrot image is saved in the specified file name if the 
  1641. .I Mandelbrot
  1642. radio button is pressed, the Julia image is saved if the 
  1643. .I Julia
  1644. radio button is pressed.
  1645. X
  1646. For the Motif implementation, the desired file name is entered
  1647. into the
  1648. .I Gif file
  1649. dialogue box.  Pressing the
  1650. .I Save
  1651. button saves the default image (set by the radio buttons)
  1652. as a gif file.
  1653. .TP
  1654. .B remove
  1655. Remove the Julia set window.  It will be recreated if another
  1656. Julia display is requested.
  1657. X
  1658. This button is not used in the Motif edition: the Julia set
  1659. may be removed by closing the Julia window.
  1660. .TP
  1661. .B quit
  1662. This causes \fIxmandel\fP to exit.
  1663. .SH MOTIF NOTES
  1664. The
  1665. .I default
  1666. set is selected by the radio buttons
  1667. .I mandel
  1668. or
  1669. .I julia.
  1670. The default set selection is used when the
  1671. .I recalc, \+colour,
  1672. .I \-colour,
  1673. or other buttons are pressed.  For example, if the
  1674. .I julia
  1675. radio button is selected, the
  1676. .I recalc
  1677. button will recompute the Julia set.  The Mandelbrot set is
  1678. unaffected.
  1679. X
  1680. The additional dialog boxes allow you to manually provide the
  1681. Mandelbrot zoom coordinates. Changes to the
  1682. .I POINT COORDINATES
  1683. are not allowed.
  1684. .SH BUGS
  1685. The system works only with 1, 2, 4, or 8 bit displays: 24 bit
  1686. display systems are not supported.
  1687. .PP
  1688. Exposure events are examined after the generation of every 4th
  1689. image scan line: there is some delay after and exposure event
  1690. before the image is actually refreshed.
  1691. .PP
  1692. XXmandel cannot manipluate the colour map.
  1693. .PP
  1694. Performance is slow on workstations,
  1695. especially workstations without floating point hardware.  Alternatively,
  1696. extensive use of
  1697. .I xmandel
  1698. may justify the purchase of a more powerful system.
  1699. .SH AUTHOR
  1700. John L. Freeman (jlf@cray.com)
  1701. .nf
  1702. X
  1703. Changes for gif, Motif and SysV X11-R4:
  1704. X       Tony Field (tony@ajfcal.cuc.ab.ca)
  1705. .fi
  1706. SHAR_EOF
  1707. chmod 0644 xmandel.man ||
  1708. echo 'restore of xmandel.man failed'
  1709. Wc_c="`wc -c < 'xmandel.man'`"
  1710. test 8293 -eq "$Wc_c" ||
  1711.     echo 'xmandel.man: original size 8293, current size' "$Wc_c"
  1712. rm -f _shar_wnt_.tmp
  1713. fi
  1714. # ============= xmandel.mot.ad ==============
  1715. if test -f 'xmandel.mot.ad' -a X"$1" != X"-c"; then
  1716.     echo 'x - skipping xmandel.mot.ad (File already exists)'
  1717.     rm -f _shar_wnt_.tmp
  1718. else
  1719. > _shar_wnt_.tmp
  1720. echo 'x - extracting xmandel.mot.ad (Text)'
  1721. sed 's/^X//' << 'SHAR_EOF' > 'xmandel.mot.ad' &&
  1722. ! Translate buttons so that they remain depressed duing the
  1723. ! course of calculations or processing.
  1724. X
  1725. xmandel.name.mandel.Translations:  #override \
  1726. X        <Btn1Down>: Arm() \n \
  1727. X        <Btn1Up>:   ArmAndActivate()
  1728. X
  1729. xmandel.name.julia.Translations:  #override \
  1730. X        <Btn1Down>: Arm() \n \
  1731. X        <Btn1Up>:   ArmAndActivate()
  1732. X
  1733. xmandel.name.recalc.Translations:  #override \
  1734. X        <Btn1Down>: Arm() \n \
  1735. X        <Btn1Up>:   ArmAndActivate()
  1736. X
  1737. xmandel.name.unzoom.Translations:  #override \
  1738. X        <Btn1Down>: Arm() \n \
  1739. X        <Btn1Up>:   ArmAndActivate()
  1740. X
  1741. xmandel.name.+colour.Translations:  #override \
  1742. X        <Btn1Down>: Arm() \n \
  1743. X        <Btn1Up>:   ArmAndActivate()
  1744. X
  1745. xmandel.name.-colour.Translations:  #override \
  1746. X        <Btn1Down>: Arm() \n \
  1747. X        <Btn1Up>:   ArmAndActivate()
  1748. X
  1749. xmandel.name.Save.Translations:  #override \
  1750. X        <Btn1Down>: Arm() \n \
  1751. X        <Btn1Up>:   ArmAndActivate()
  1752. X
  1753. xmandel.name.zoom.Translations:  #override \
  1754. X        <Btn1Down>: Arm() \n \
  1755. X        <Btn1Up>:   ArmAndActivate()
  1756. SHAR_EOF
  1757. chmod 0644 xmandel.mot.ad ||
  1758. echo 'restore of xmandel.mot.ad failed'
  1759. Wc_c="`wc -c < 'xmandel.mot.ad'`"
  1760. test 929 -eq "$Wc_c" ||
  1761.     echo 'xmandel.mot.ad: original size 929, current size' "$Wc_c"
  1762. rm -f _shar_wnt_.tmp
  1763. fi
  1764. rm -f _shar_seq_.tmp
  1765. echo You have unpacked the last part
  1766. exit 0
  1767. -- 
  1768. --
  1769. Molecular Simulations, Inc.            mail: dcmartin@msi.com
  1770. 796 N. Pastoria Avenue                uucp: uunet!dcmartin
  1771. Sunnyvale, California 94086            at&t: 408/522-9236
  1772.