home *** CD-ROM | disk | FTP | other *** search
/ Amiga ACS 1998 #4 / amigaacscoverdisc1998-041998.iso / utilities / shareware / dev / ucb_logoppc / source / graphics.c < prev    next >
Encoding:
C/C++ Source or Header  |  1998-02-20  |  32.1 KB  |  1,370 lines

  1. /*
  2.  *      graphics.c          logo graphics module          mak
  3.  *
  4.  * Copyright (C) 1993 by the Regents of the University of California
  5.  *
  6.  *      This program is free software; you can redistribute it and/or modify
  7.  *      it under the terms of the GNU General Public License as published by
  8.  *      the Free Software Foundation; either version 2 of the License, or
  9.  *      (at your option) any later version.
  10.  *
  11.  *      This program is distributed in the hope that it will be useful,
  12.  *      but WITHOUT ANY WARRANTY; without even the implied warranty of
  13.  *      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14.  *      GNU General Public License for more details.
  15.  *
  16.  *      You should have received a copy of the GNU General Public License
  17.  *      along with this program; if not, write to the Free Software
  18.  *      Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  19.  *
  20.  */
  21.  
  22. #ifdef WIN32
  23. #include <windows.h>
  24. #endif /* WIN32 */
  25.  
  26. #include "logo.h"
  27. /*   #include "globals.h"   has been moved further down */
  28. #include <math.h>
  29.  
  30. #if defined(__PPC__) && defined(AMIGA)
  31.  
  32. #define __USE_SYSBASE
  33. #include <proto/exec.h>
  34. #include <proto/dos.h>
  35. #include <proto/graphics.h>
  36. #include <proto/intuition.h>
  37. #include <proto/asl.h>
  38. #include <powerup/ppclib/interface.h>
  39. #include <powerup/gcclib/powerup_protos.h>
  40.  
  41. #define AllocVec(n, f) PPCAllocVec(n, f)
  42. #define FreeVec(b)     PPCFreeVec(b)
  43.  
  44. #endif
  45.  
  46. #ifdef mac
  47. #include "macterm.h"
  48. #elif defined(WIN32)
  49. #include "win32trm.h"
  50. #elif defined(__ZTC__)
  51. #include <fg.h>
  52. #include "ztcterm.h"
  53. #elif defined(x_window)
  54. #include "xgraphics.h"
  55. #elif defined(ibm)
  56. #include "ibmterm.h"
  57. #elif defined(AMIGA)
  58. #include "amiterm.h"
  59. #else
  60. #include "nographics.h"
  61. #endif /* end this whole big huge tree */
  62.  
  63. #include "globals.h"
  64.  
  65. #if defined(__ZTC__) && !defined(WIN32) /* sowings */
  66. #define total_turtle_bottom_max (-(MaxY/2))
  67. #else
  68. #define total_turtle_bottom_max turtle_bottom_max
  69. #endif
  70.  
  71. /* types of graphics moves that can be recorded */
  72. #define LINEXY         1
  73. #define MOVEXY         2
  74. #define LABEL          3
  75. #define SETPENVIS      4
  76. #define SETPENMODE     5
  77. #define SETPENCOLOR    6
  78. #define SETPENSIZE     7
  79. #define SETPENPATTERN  8
  80. #define FILLERUP     9
  81.  
  82. /* NOTE: See the files (macterm.c and macterm.h) or (ibmterm.c and ibmterm.h)
  83.    for examples of the functions and macros that this file assumes exist. */
  84.  
  85. #define One (sizeof(int))
  86. #define Two (2*One)
  87. #define Three (3*One)
  88.  
  89. #define PENMODE_PAINT   0
  90. #define PENMODE_ERASE   1
  91. #define PENMODE_REVERSE 2
  92.  
  93. int internal_penmode = PENMODE_PAINT;
  94.  
  95. mode_type current_mode = wrapmode;
  96. FLONUM turtle_x = 0.0, turtle_y = 0.0, turtle_heading = 0.0;
  97. FLONUM x_scale = 1.0, y_scale = 1.0;
  98. BOOLEAN turtle_shown = TRUE;
  99. FLONUM wanna_x = 0.0, wanna_y = 0.0;
  100. BOOLEAN out_of_bounds = FALSE;
  101. void setpos_bynumber(FLONUM, FLONUM);
  102.  
  103. char record[GR_SIZE];
  104. int record_index = 0;
  105. pen_info orig_pen;
  106.  
  107. BOOLEAN record_next_move = FALSE, refresh_p = TRUE;
  108.  
  109. /************************************************************/
  110.  
  111. double pfmod(double x, double y) {
  112.     double temp = fmod(x,y);
  113.  
  114.     if (temp < 0) return temp+y;
  115.     return temp;
  116. }
  117.  
  118. FLONUM cut_error(FLONUM n) {
  119.     n *= 1000000;
  120.     n = (n > 0 ? floor(n) : ceil(n));
  121.     n /= 1000000;
  122.     if (n == -0.0) n = 0.0;
  123.     return(n);
  124. }
  125.  
  126. FIXNUM g_round(FLONUM n) {
  127.     n += (n < 0.0 ? -0.5 : 0.5);
  128.     if (n < 0.0)
  129.    return((FIXNUM)ceil(n));
  130.     return((FIXNUM)floor(n));
  131. }
  132.  
  133. /************************************************************/
  134. void draw_turtle_helper(void);
  135. void check_x_high(void);
  136. void check_x_low(void);
  137.  
  138. void draw_turtle(void) {
  139.     if (!turtle_shown) return;
  140.     draw_turtle_helper();
  141.     /* all that follows is for "turtle wrap" effect */
  142.     if ((turtle_y > turtle_top_max - turtle_height) &&
  143.        (current_mode == wrapmode)) {
  144.    turtle_y -= (screen_height + 1);
  145.    draw_turtle_helper();
  146.    check_x_high();
  147.    check_x_low();
  148.    turtle_y += (screen_height + 1);
  149.     }
  150.     if ((turtle_y < turtle_bottom_max + turtle_height) &&
  151.        (current_mode == wrapmode)) {
  152.    turtle_y += (screen_height + 1);
  153.    draw_turtle_helper();
  154.    check_x_high();
  155.    check_x_low();
  156.    turtle_y -= (screen_height + 1);
  157.     }
  158.     check_x_high();
  159.     check_x_low();
  160. }
  161.  
  162. void check_x_high(void) {
  163.     if ((turtle_x > turtle_right_max - turtle_height) &&
  164.        (current_mode == wrapmode)) {
  165.    turtle_x -= (screen_width + 1);
  166.    draw_turtle_helper();
  167.    turtle_x += (screen_width + 1);
  168.     }
  169. }
  170.  
  171. void check_x_low(void) {
  172.     if ((turtle_x < turtle_left_max + turtle_height) &&
  173.        (current_mode == wrapmode)) {
  174.    turtle_x += (screen_width + 1);
  175.    draw_turtle_helper();
  176.    turtle_x -= (screen_width + 1);
  177.     }
  178. }
  179.  
  180. void draw_turtle_helper(void) {
  181.     pen_info saved_pen;
  182.     FLONUM real_heading;
  183.     int left_x, left_y, right_x, right_y, top_x, top_y;
  184.  
  185.     prepare_to_draw;
  186.     prepare_to_draw_turtle;
  187.     save_pen(&saved_pen);
  188.     plain_xor_pen();
  189.     pen_vis = 0;
  190.  
  191.     real_heading = -turtle_heading + 90.0;
  192.  
  193.     left_x = g_round(turtle_x + x_scale*(FLONUM)(cos((FLONUM)((real_heading + 90.0)*degrad))*turtle_half_bottom));
  194.     left_y = g_round(turtle_y + y_scale*(FLONUM)(sin((FLONUM)((real_heading + 90.0)*degrad))*turtle_half_bottom));
  195.  
  196.     right_x = g_round(turtle_x + x_scale*(FLONUM)(cos((FLONUM)((real_heading - 90.0)*degrad))*turtle_half_bottom));
  197.     right_y = g_round(turtle_y + y_scale*(FLONUM)(sin((FLONUM)((real_heading - 90.0)*degrad))*turtle_half_bottom));
  198.  
  199.     top_x = g_round(turtle_x + x_scale*(FLONUM)(cos((FLONUM)(real_heading*degrad))*turtle_side));
  200.     top_y = g_round(turtle_y + y_scale*(FLONUM)(sin((FLONUM)(real_heading*degrad))*turtle_side));
  201.  
  202.     move_to(screen_x_center + left_x, screen_y_center - left_y);
  203.     line_to(screen_x_center + top_x, screen_y_center - top_y);
  204.     move_to(screen_x_center + right_x, screen_y_center - right_y);
  205.     line_to(screen_x_center + top_x, screen_y_center - top_y);
  206.     move_to(screen_x_center + left_x, screen_y_center - left_y);
  207.     line_to(screen_x_center + right_x, screen_y_center - right_y);
  208.  
  209.     restore_pen(&saved_pen);
  210.     done_drawing_turtle;
  211.     done_drawing;
  212. }
  213.  
  214. /************************************************************/
  215. void forward_helper(FLONUM);
  216. BOOLEAN safe_to_save(void);
  217. void save_line(void), save_move(void), save_vis(void), save_mode(void);
  218. void save_color(void), save_size(void), save_pattern(void);
  219. void save_string(char *, int);
  220.  
  221. void right(FLONUM a) {
  222.     draw_turtle();
  223.     turtle_heading += a;
  224.     turtle_heading = pfmod(turtle_heading,360.0);
  225.     draw_turtle();
  226. }
  227.  
  228. NODE *numeric_arg(NODE *args) {
  229.     NODE *arg = car(args), *val;
  230.  
  231.     val = cnv_node_to_numnode(arg);
  232.     while (val == UNBOUND && NOT_THROWING) {
  233.    setcar(args, err_logo(BAD_DATA, arg));
  234.    arg = car(args);
  235.    val = cnv_node_to_numnode(arg);
  236.     }
  237.     setcar(args,val);
  238.     return(val);
  239. }
  240.  
  241. NODE *lright(NODE *arg) {
  242.     NODE *val;
  243.     FLONUM a;
  244.  
  245.     val = numeric_arg(arg);
  246.     if (NOT_THROWING) {
  247.    if (nodetype(val) == INT)
  248.        a = (FLONUM)getint(val);
  249.    else
  250.        a = getfloat(val);
  251.    right(a);
  252.     }
  253.     return(UNBOUND);
  254. }
  255.  
  256. NODE *lleft(NODE *arg) {
  257.     NODE *val;
  258.     FLONUM a;
  259.  
  260.     val = numeric_arg(arg);
  261.     if (NOT_THROWING) {
  262.    if (nodetype(val) == INT)
  263.        a = (FLONUM)getint(val);
  264.    else
  265.        a = getfloat(val);
  266.    right(-a);
  267.     }
  268.     return(UNBOUND);
  269. }
  270.  
  271. int wrap_right(FLONUM, FLONUM, FLONUM, FLONUM, FLONUM);
  272. int wrap_left(FLONUM, FLONUM, FLONUM, FLONUM, FLONUM);
  273. int wrap_up(FLONUM, FLONUM, FLONUM, FLONUM, FLONUM);
  274. int wrap_down(FLONUM, FLONUM, FLONUM, FLONUM, FLONUM);
  275.  
  276. void forward(FLONUM d) {
  277.     prepare_to_draw;
  278.     draw_turtle();
  279.     forward_helper(d);
  280.     draw_turtle();
  281.     done_drawing;
  282.     wanna_x = turtle_x;
  283.     wanna_y = turtle_y;
  284.     out_of_bounds = FALSE;
  285. }
  286.  
  287. void forward_helper(FLONUM d) {
  288.     FLONUM real_heading, dx, dy, x1, y1, x2, y2;
  289.  
  290.     real_heading = -turtle_heading + 90.0;
  291.     x1 = screen_x_coord;
  292.     y1 = screen_y_coord;
  293.     dx = (FLONUM)(cos((FLONUM)(real_heading*degrad))*d*x_scale);
  294.     dy = (FLONUM)(sin((FLONUM)(real_heading*degrad))*d*y_scale);
  295.     if ((dx < 0 && dx > -0.000001) || (dx > 0 && dx < 0.000001)) dx = 0;
  296.     if ((dy < 0 && dy > -0.000001) || (dy > 0 && dy < 0.000001)) dy = 0;
  297.     x2 = x1 + dx;
  298.     y2 = y1 - dy;
  299.  
  300.     move_to(g_round(x1), g_round(y1));
  301.     if (record_next_move) {
  302.    save_move();
  303.    record_next_move = FALSE;
  304.     }
  305.  
  306.     if (check_throwing) return;
  307.  
  308.     if (internal_penmode == PENMODE_REVERSE && pen_vis == 0 && d > 0.0) {
  309.    line_to(g_round(x1), g_round(y1));  /* flip the corner */
  310.    save_line();
  311.     }
  312.  
  313.     if (current_mode == windowmode ||
  314.    (x2 >= screen_left && x2 <= screen_right &&
  315.     y2 >= screen_top && y2 <= screen_bottom)) {
  316.    turtle_x = turtle_x + dx;
  317.    turtle_y = turtle_y + dy;
  318.    line_to(g_round(x2), g_round(y2));
  319.    save_line();
  320.     }
  321.     else
  322.    if (!wrap_right(d, x1, y1, x2, y2))
  323.        if (!wrap_left(d, x1, y1, x2, y2))
  324.       if (!wrap_up(d, x1, y1, x2, y2))
  325.           wrap_down(d, x1, y1, x2, y2);
  326.  
  327.     if (internal_penmode == PENMODE_REVERSE && pen_vis == 0 && d < 0.0) {
  328.    line_to(g_round(screen_x_coord), g_round(screen_y_coord));
  329.    save_line();
  330.     }
  331. }
  332.  
  333. int wrap_right(FLONUM d, FLONUM x1, FLONUM y1, FLONUM x2, FLONUM y2) {
  334.     FLONUM yi, newd;
  335.  
  336.     if (x2 > screen_right) {
  337.    yi = ((y2 - y1)/(x2 - x1)) * (screen_right + 1 - x1) + y1;
  338.    if (yi >= screen_top && yi <= screen_bottom) {
  339.        line_to(screen_right, g_round(yi));
  340.        save_line();
  341.        record_next_move = TRUE;
  342.        turtle_x = turtle_left_max;
  343.        turtle_y = screen_y_center - yi;
  344.        if (current_mode == wrapmode) {
  345.       newd = d * ((x2 - screen_right - 1)/(x2 - x1));
  346.       if (newd*d > 0) forward_helper(newd);
  347.       return(1);
  348.        }
  349.        turtle_x = turtle_right_max;
  350.        err_logo(TURTLE_OUT_OF_BOUNDS, NIL);
  351.    }
  352.     }
  353.     return(0);
  354. }
  355.  
  356. int wrap_left(FLONUM d, FLONUM x1, FLONUM y1, FLONUM x2, FLONUM y2) {
  357.     FLONUM yi, newd;
  358.  
  359.     if (x2 < screen_left) {
  360.    yi = ((y1 - y2)/(x2 - x1)) * (x1 + 1 - screen_left) + y1;
  361.    if (yi >= screen_top && yi <= screen_bottom) {
  362.        line_to(screen_left, g_round(yi));
  363.        save_line();
  364.        record_next_move = TRUE;
  365.        turtle_x = turtle_right_max;
  366.        turtle_y = screen_y_center - yi;
  367.        if (current_mode == wrapmode) {
  368.       newd = d * ((x2 + 1 - screen_left)/(x2 - x1));
  369.       if (newd*d > 0) forward_helper(newd);
  370.       return(1);
  371.        }
  372.        turtle_x = turtle_left_max;
  373.        err_logo(TURTLE_OUT_OF_BOUNDS, NIL);
  374.    }
  375.     }
  376.     return(0);
  377. }
  378.  
  379. int wrap_up(FLONUM d, FLONUM x1, FLONUM y1, FLONUM x2, FLONUM y2) {
  380.     FLONUM xi, newd;
  381.  
  382.     if (y2 < screen_top) {
  383.    xi = ((x2 - x1)/(y1 - y2)) * (y1 + 1 - screen_top) + x1;
  384.    if (xi >= screen_left && xi <= screen_right) {
  385.        line_to(g_round(xi), screen_top);
  386.        save_line();
  387.        record_next_move = TRUE;
  388.        turtle_x = xi - screen_x_center;
  389.        turtle_y = turtle_bottom_max;
  390.        if (current_mode == wrapmode) {
  391.       newd = d * ((y2 + 1 - screen_top)/(y2 - y1));
  392.       if (newd*d > 0) forward_helper(newd);
  393.       return(1);
  394.        }
  395.        turtle_y = turtle_top_max;
  396.        err_logo(TURTLE_OUT_OF_BOUNDS, NIL);
  397.    }
  398.     }
  399.     return(0);
  400. }
  401.  
  402. int wrap_down(FLONUM d, FLONUM x1, FLONUM y1, FLONUM x2, FLONUM y2) {
  403.     FLONUM xi, newd;
  404.  
  405.     if (y2 > screen_bottom) {
  406.    xi = ((x2 - x1)/(y2 - y1)) * (screen_bottom + 1 - y1) + x1;
  407.    if (xi >= screen_left && xi <= screen_right) {
  408.        line_to(g_round(xi), screen_bottom);
  409.        save_line();
  410.        record_next_move = TRUE;
  411.        turtle_x = xi - screen_x_center;
  412.        turtle_y = turtle_top_max;
  413.        if (current_mode == wrapmode) {
  414.       newd = d * ((y2 - screen_bottom - 1)/(y2 - y1));
  415.       if (newd*d > 0) forward_helper(newd);
  416.       return(1);
  417.        }
  418.        turtle_y = turtle_bottom_max;
  419.        err_logo(TURTLE_OUT_OF_BOUNDS, NIL);
  420.    }
  421.     }
  422.     return(0);
  423. }
  424.  
  425. NODE *lforward(NODE *arg) {
  426.     NODE *val;
  427.     FLONUM d;
  428.  
  429.     val = numeric_arg(arg);
  430.     if (NOT_THROWING) {
  431.    if (nodetype(val) == INT)
  432.        d = (FLONUM)getint(val);
  433.    else
  434.        d = getfloat(val);
  435.    forward(d);
  436.     }
  437.     return(UNBOUND);
  438. }
  439.  
  440. NODE *lback(NODE *arg) {
  441.     NODE *val;
  442.     FLONUM d;
  443.  
  444.     val = numeric_arg(arg);
  445.     if (NOT_THROWING) {
  446.    if (nodetype(val) == INT)
  447.        d = (FLONUM)getint(val);
  448.    else
  449.        d = getfloat(val);
  450.    forward(-d);
  451.     }
  452.     return(UNBOUND);
  453. }
  454.  
  455. NODE *lshowturtle(NODE *args) {
  456.     prepare_to_draw;
  457.     if (!turtle_shown) {
  458.    turtle_shown = TRUE;
  459.    draw_turtle();
  460.     }
  461.     done_drawing;
  462.     return(UNBOUND);
  463. }
  464.  
  465. NODE *lhideturtle(NODE *args) {
  466.     prepare_to_draw;
  467.     if (turtle_shown) {
  468.    draw_turtle();
  469.    turtle_shown = FALSE;
  470.     }
  471.     done_drawing;
  472.     return(UNBOUND);
  473. }
  474.  
  475. NODE *lshownp(NODE *args) {
  476.     return(turtle_shown ? True : False);
  477. }
  478.  
  479. NODE *lsetheading(NODE *arg) {
  480.     NODE *val;
  481.  
  482.     val = numeric_arg(arg);
  483.     if (NOT_THROWING) {
  484.    draw_turtle();
  485.    if (nodetype(val) == INT)
  486.        turtle_heading = (FLONUM)getint(val);
  487.    else
  488.        turtle_heading = getfloat(val);
  489.    turtle_heading = pfmod(turtle_heading,360.0);
  490.    draw_turtle();
  491.     }
  492.     return(UNBOUND);
  493. }
  494.  
  495. NODE *lheading(NODE *args) {
  496.     return(make_floatnode(turtle_heading));
  497. }
  498.  
  499. NODE *vec_arg_helper(NODE *args, BOOLEAN floatok, BOOLEAN three) {
  500.     NODE *arg = car(args), *val1, *val2, *val3 = NIL;
  501.  
  502.     while (NOT_THROWING) {
  503.    if (arg != NIL &&
  504.    is_list(arg) &&
  505.    cdr(arg) != NIL &&
  506.    (three ? (cddr(arg) != NIL && cdr(cddr(arg)) == NIL) : cddr(arg) == NIL)) {
  507.        val1 = cnv_node_to_numnode(car(arg));
  508.        val2 = cnv_node_to_numnode(cadr(arg));
  509.       if (three) val3 = cnv_node_to_numnode(car(cddr(arg)));
  510.        if (val1 != UNBOUND && val2 != UNBOUND &&
  511.       (floatok || (nodetype(val1) == INT && getint(val1) >= 0 &&
  512.               nodetype(val2) == INT && getint(val2) >= 0 &&
  513.              (!three || (nodetype(val3) == INT && getint(val3) >= 0))))) {
  514.       setcar(arg, val1);
  515.       setcar(cdr(arg), val2);
  516.       if (three) setcar (cddr(arg), val3);
  517.       return(arg);
  518.        }
  519.    }
  520.    setcar(args, err_logo(BAD_DATA, arg));
  521.    arg = car(args);
  522.     }
  523.     return(UNBOUND);
  524. }
  525.  
  526. NODE *vector_arg(NODE *args) {
  527.     return vec_arg_helper(args,TRUE,FALSE);
  528. }
  529.  
  530. NODE *pos_int_vector_arg(NODE *args) {
  531.     return vec_arg_helper(args,FALSE,FALSE);
  532. }
  533.  
  534. NODE *rgb_arg(NODE *args) {
  535.    return vec_arg_helper(args,FALSE,TRUE);
  536. }
  537.  
  538. FLONUM towards_helper(FLONUM x, FLONUM y, FLONUM from_x, FLONUM from_y) {
  539.     FLONUM m, a, tx, ty;
  540.  
  541.     tx = from_x/x_scale;
  542.     ty = from_y/y_scale;
  543.  
  544.     if (x != tx || y != ty) {
  545.    if (x == tx)
  546.        a = (y < ty) ? -90 : 90;
  547.    else {
  548.        m = (y - ty)/(x - tx);
  549.        a = atan(m)/degrad;
  550.        if (x < tx) a = fmod(a + 180.0,360.0);
  551.    }
  552.    a = -(a - 90.0);
  553.    return (a < 0 ? 360.0+a : a);
  554.     }
  555.     return 0.0;
  556. }
  557.  
  558. NODE *ltowards(NODE *args) {
  559.     NODE *xnode, *ynode = UNBOUND, *arg;
  560.     FLONUM x, y;
  561.  
  562.     arg = vector_arg(args);
  563.     if (NOT_THROWING) {
  564.    xnode = car(arg);
  565.    ynode = cadr(arg);
  566.  
  567.    x = ((nodetype(xnode) == FLOATT) ? getfloat(xnode) :
  568.            (FLONUM)getint(xnode));
  569.    y = ((nodetype(ynode) == FLOATT) ? getfloat(ynode) :
  570.            (FLONUM)getint(ynode));
  571.    return make_floatnode(towards_helper(x, y, turtle_x, turtle_y));
  572.     }
  573.     return(UNBOUND);
  574. }
  575.  
  576. NODE *lpos(NODE *args) {
  577.     return(cons(make_floatnode(cut_error(turtle_x/x_scale)),
  578.    cons(make_floatnode(cut_error(turtle_y/y_scale)), NIL)));
  579. }
  580.  
  581. NODE *lscrunch(NODE *args) {
  582.     return(cons(make_floatnode(x_scale), cons(make_floatnode(y_scale), NIL)));
  583. }
  584.  
  585. NODE *lhome(NODE *args) {
  586.     out_of_bounds = FALSE;
  587.     setpos_bynumber((FLONUM)0.0, (FLONUM)0.0);
  588.     draw_turtle();
  589.     turtle_heading = 0.0;
  590.     draw_turtle();
  591.     return(UNBOUND);
  592. }
  593.  
  594. void cs_helper(int centerp) {
  595.     prepare_to_draw;
  596.     clear_screen;
  597.     if (centerp) {
  598.    wanna_x = wanna_y = turtle_x = turtle_y = turtle_heading = 0.0;
  599.    out_of_bounds = FALSE;
  600.    move_to(screen_x_coord, screen_y_coord);
  601.     }
  602.     draw_turtle();
  603.     save_pen(&orig_pen);
  604.     p_info_x(orig_pen) = g_round(screen_x_coord);
  605.     p_info_y(orig_pen) = g_round(screen_y_coord);
  606.     record_index = 0;
  607.     done_drawing;
  608. }
  609.  
  610. NODE *lclearscreen(NODE *args) {
  611.     cs_helper(TRUE);
  612.     return(UNBOUND);
  613. }
  614.  
  615. NODE *lclean(NODE *args) {
  616.     cs_helper(FALSE);
  617.     return(UNBOUND);
  618. }
  619.  
  620. void setpos_commonpart(FLONUM target_x, FLONUM target_y) {
  621.    FLONUM scaled_x, scaled_y, tx, ty, save_heading;
  622.    BOOLEAN wrapping = FALSE;
  623.  
  624.    if (NOT_THROWING) {
  625.       scaled_x = target_x * x_scale;
  626.       scaled_y = target_y * y_scale;
  627.       wrapping = scaled_x > turtle_right_max || scaled_x < turtle_left_max ||
  628.          scaled_y > turtle_top_max || scaled_y < turtle_bottom_max;
  629.       if (current_mode == fencemode && wrapping)
  630.          err_logo(TURTLE_OUT_OF_BOUNDS, NIL);
  631.       else if (current_mode == wrapmode && (wrapping || out_of_bounds)) {
  632.          save_heading = turtle_heading;
  633.          turtle_heading = towards_helper(target_x, target_y,
  634.             wanna_x, wanna_y);
  635.          tx = wanna_x/x_scale;
  636.          ty = wanna_y/y_scale;
  637.    #define sq(z) ((z)*(z))
  638.          forward_helper(sqrt(sq(target_x - tx) + sq(target_y - ty)));
  639.          turtle_heading = save_heading;
  640.          wanna_x = scaled_x;
  641.          wanna_y = scaled_y;
  642.          out_of_bounds = wrapping;
  643.       } else {
  644.          out_of_bounds = FALSE;
  645.          wanna_x = turtle_x = scaled_x;
  646.          wanna_y = turtle_y = scaled_y;
  647.          line_to(g_round(screen_x_coord),
  648.          g_round(screen_y_coord));
  649.          save_line();
  650.       }
  651.       done_drawing;
  652.       draw_turtle();
  653.    }
  654. }
  655.  
  656. void setpos_bynumber(FLONUM target_x, FLONUM target_y) {
  657.    if (NOT_THROWING) {
  658.       prepare_to_draw;
  659.       draw_turtle();
  660.       move_to(g_round(screen_x_coord), g_round(screen_y_coord));
  661.       setpos_commonpart(target_x, target_y);
  662.    }
  663. }
  664.  
  665. void setpos_helper(NODE *xnode, NODE *ynode) {
  666.     FLONUM target_x, target_y;
  667.  
  668.     if (NOT_THROWING) {
  669.    prepare_to_draw;
  670.    draw_turtle();
  671.    move_to(g_round(screen_x_coord), g_round(screen_y_coord));
  672.    target_x = ((xnode == NIL) ?
  673.       turtle_x :
  674.       ((nodetype(xnode) == FLOATT) ? getfloat(xnode) :
  675.        (FLONUM)getint(xnode)));
  676.    target_y = ((ynode == NIL) ?
  677.       turtle_y :
  678.       ((nodetype(ynode) == FLOATT) ? getfloat(ynode) :
  679.        (FLONUM)getint(ynode)));
  680.    setpos_commonpart(target_x, target_y);
  681.     }
  682. }
  683.  
  684. NODE *lsetpos(NODE *args) {
  685.     NODE *arg = vector_arg(args);
  686.  
  687.     if (NOT_THROWING) {
  688.    setpos_helper(car(arg), cadr(arg));
  689.     }
  690.     return(UNBOUND);
  691. }
  692.  
  693. NODE *lsetxy(NODE *args) {
  694.     NODE *xnode, *ynode;
  695.  
  696.     xnode = numeric_arg(args);
  697.     ynode = numeric_arg(cdr(args));
  698.     if (NOT_THROWING) {
  699.    setpos_helper(xnode, ynode);
  700.     }
  701.     return(UNBOUND);
  702. }
  703.  
  704. NODE *lsetx(NODE *args) {
  705.     NODE *xnode;
  706.  
  707.     xnode = numeric_arg(args);
  708.     if (NOT_THROWING) {
  709.    setpos_helper(xnode, NIL);
  710.     }
  711.     return(UNBOUND);
  712. }
  713.  
  714. NODE *lsety(NODE *args) {
  715.     NODE *ynode;
  716.  
  717.     ynode = numeric_arg(args);
  718.     if (NOT_THROWING) {
  719.    setpos_helper(NIL, ynode);
  720.     }
  721.     return(UNBOUND);
  722. }
  723.  
  724. NODE *lwrap(NODE *args) {
  725.     draw_turtle();
  726.     current_mode = wrapmode;
  727.     while (turtle_x > turtle_right_max) {
  728.    turtle_x -= screen_width;
  729.     }
  730.     while (turtle_x < turtle_left_max) {
  731.    turtle_x += screen_width;
  732.     }
  733.     while (turtle_y > turtle_top_max) {
  734.    turtle_y -= screen_height;
  735.     }
  736.     while (turtle_y < turtle_bottom_max) {
  737.    turtle_y += screen_height;
  738.     }
  739.     move_to(screen_x_coord, screen_y_coord);
  740.     draw_turtle();
  741.     return(UNBOUND);
  742. }
  743.  
  744. NODE *lfence(NODE *args) {
  745.     (void)lwrap(args);      /* get turtle inside the fence */
  746.     draw_turtle();
  747.     current_mode = fencemode;
  748.     draw_turtle();
  749.     return(UNBOUND);
  750. }
  751.  
  752. NODE *lwindow(NODE *args) {
  753.     draw_turtle();
  754.     current_mode = windowmode;
  755.     draw_turtle();
  756.     return(UNBOUND);
  757. }
  758.  
  759. NODE *lfill(NODE *args) {
  760.     draw_turtle();
  761.     logofill();
  762.     draw_turtle();
  763.     if (safe_to_save()) {
  764.    record[record_index] = FILLERUP;
  765.    record_index += One;
  766.     }
  767.     return(UNBOUND);
  768. }
  769.  
  770. NODE *llabel(NODE *arg) {
  771.     char textbuf[300];
  772.     short theLength;
  773.  
  774.     print_stringptr = textbuf;
  775.     print_stringlen = 300;
  776.     ndprintf((FILE *)NULL,"%p",car(arg));
  777.     *print_stringptr = '\0';
  778.  
  779.     if (NOT_THROWING) {
  780.    prepare_to_draw;
  781.    draw_turtle();
  782.    theLength = strlen(textbuf);
  783. #ifdef mac
  784.    c_to_pascal_string(textbuf, theLength);
  785. #endif
  786.    label(textbuf);
  787.    save_string(textbuf,theLength);
  788.    record_next_move = TRUE;
  789.    draw_turtle();
  790.    done_drawing;
  791.     }
  792.     return(UNBOUND);
  793. }
  794.  
  795. NODE *ltextscreen(NODE *args) {
  796.     text_screen;
  797.     return(UNBOUND);
  798. }
  799.  
  800. NODE *lsplitscreen(NODE *args) {
  801.     split_screen;
  802.     return(UNBOUND);
  803. }
  804.  
  805. NODE *lfullscreen(NODE *args) {
  806.     full_screen;
  807.     return(UNBOUND);
  808. }
  809.  
  810. NODE *lpendownp(NODE *args) {
  811.     return(pen_vis == 0 ? True : False);
  812. }
  813.  
  814. NODE *lpenmode(NODE *args) {
  815.     return(get_node_pen_mode);
  816. }
  817.  
  818. NODE *lpencolor(NODE *args) {
  819.     return(make_intnode((FIXNUM)pen_color));
  820. }
  821.  
  822. NODE *lbackground(NODE *args) {
  823.     return(make_intnode((FIXNUM)back_ground));
  824. }
  825.  
  826. NODE *lpensize(NODE *args) {
  827.     return(cons(make_intnode((FIXNUM)pen_width),
  828.    cons(make_intnode((FIXNUM)pen_height), NIL)));
  829. }
  830.  
  831. NODE *lpenpattern(NODE *args) {
  832.     return(get_node_pen_pattern);
  833. }
  834.  
  835. NODE *lpendown(NODE *args) {
  836.     pen_vis = 0;
  837.     save_vis();
  838.     return(UNBOUND);
  839. }
  840.  
  841. NODE *lpenup(NODE *args) {
  842.     if (pen_vis == 0)
  843.    pen_vis--;
  844.     save_vis();
  845.     return(UNBOUND);
  846. }
  847.  
  848. NODE *lpenpaint(NODE *args) {
  849.     internal_penmode = PENMODE_PAINT;
  850.     pen_down;
  851.     save_mode();
  852.     return(lpendown(NIL));
  853. }
  854.  
  855. NODE *lpenerase(NODE *args) {
  856.     internal_penmode = PENMODE_ERASE;
  857.     pen_erase;
  858.     save_mode();
  859.     return(lpendown(NIL));
  860. }
  861.  
  862. NODE *lpenreverse(NODE *args) {
  863.     internal_penmode = PENMODE_REVERSE;
  864.     pen_reverse;
  865.     save_mode();
  866.     return(lpendown(NIL));
  867. }
  868.  
  869. NODE *lsetpencolor(NODE *arg) {
  870.     NODE *val = pos_int_arg(arg);
  871.  
  872.     if (NOT_THROWING) {
  873.    prepare_to_draw;
  874.    set_pen_color(getint(val));
  875.    save_color();
  876.    done_drawing;
  877.     }
  878.     return(UNBOUND);
  879. }
  880.  
  881. NODE *lsetbackground(NODE *arg) {
  882.     NODE *val = pos_int_arg(arg);
  883.  
  884.     if (NOT_THROWING) {
  885.    prepare_to_draw;
  886.    set_back_ground(getint(val));
  887.    done_drawing;
  888.     }
  889.     return(UNBOUND);
  890. }
  891.  
  892. NODE *lsetpalette(NODE *args) {
  893.    NODE *slot = pos_int_arg(args);
  894.    NODE *arg = rgb_arg(cdr(args));
  895.  
  896.    if (NOT_THROWING && ((int)getint(slot) > 7)) {
  897.       prepare_to_draw;
  898.       set_palette((int)getint(slot),
  899.              (unsigned int)getint(car(arg)),
  900.              (unsigned int)getint(cadr(arg)),
  901.              (unsigned int)getint(car(cddr(arg))));
  902.       done_drawing;
  903.    }
  904.    return(UNBOUND);
  905. }
  906.  
  907. NODE *lpalette(NODE *args) {
  908.    NODE *arg = pos_int_arg(args);
  909.    unsigned int r=0, g=0, b=0;
  910.  
  911.    if (NOT_THROWING) {
  912.       get_palette((int)getint(arg), &r, &g, &b);
  913.       return cons(make_intnode((FIXNUM)r),
  914.                cons(make_intnode((FIXNUM)g),
  915.                    cons(make_intnode((FIXNUM)b), NIL)));
  916.    }
  917.    return UNBOUND;
  918. }
  919.  
  920. NODE *lsetpensize(NODE *args) {
  921.     NODE *arg = pos_int_vector_arg(args);
  922.  
  923.     if (NOT_THROWING) {
  924.    prepare_to_draw;
  925.    set_pen_width((int)getint(car(arg)));
  926.    set_pen_height((int)getint(cadr(arg)));
  927.    save_size();
  928.    done_drawing;
  929.     }
  930.     return(UNBOUND);
  931. }
  932.  
  933. NODE *lsetpenpattern(NODE *args) {
  934.     NODE *arg;
  935.  
  936.     arg = car(args);
  937.     while ((!is_list(arg)) && NOT_THROWING)
  938.    arg = err_logo(BAD_DATA, arg);
  939.  
  940.     if (NOT_THROWING) {
  941.    prepare_to_draw;
  942.    set_list_pen_pattern(arg);
  943.    save_pattern();
  944.    done_drawing;
  945.     }
  946.  
  947.     return(UNBOUND);
  948. }
  949.  
  950. NODE *lsetscrunch(NODE *args) {
  951.     NODE *xnode, *ynode;
  952.  
  953.     xnode = numeric_arg(args);
  954.     ynode = numeric_arg(cdr(args));
  955.  
  956.     if (NOT_THROWING) {
  957.    prepare_to_draw;
  958.    draw_turtle();
  959.    x_scale = (nodetype(xnode) == FLOATT) ? getfloat(xnode) :
  960.                 (FLONUM)getint(xnode);
  961.    y_scale = (nodetype(ynode) == FLOATT) ? getfloat(ynode) :
  962.                 (FLONUM)getint(ynode);
  963.    draw_turtle();
  964.    done_drawing;
  965. #ifdef __ZTC__
  966.    {
  967.        FILE *fp = fopen("scrunch.dat","r");
  968.        if (fp != NULL) {
  969.       fclose(fp);
  970.       fp = fopen("scrunch.dat","w");
  971.       if (fp != NULL) {
  972.           fwrite(&x_scale, sizeof(FLONUM), 1, fp);
  973.           fwrite(&y_scale, sizeof(FLONUM), 1, fp);
  974.           fclose(fp);
  975.       }
  976.        }
  977.    }
  978. #endif
  979.     }
  980.     return(UNBOUND);
  981. }
  982.  
  983. NODE *lmousepos(NODE *args) {
  984. #ifdef WIN32 /* sowings */
  985.     return NIL;
  986. #else
  987.     return(cons(make_intnode(mouse_x), cons(make_intnode(mouse_y), NIL)));
  988. #endif
  989. }
  990.  
  991. NODE *lbuttonp(NODE *args) {
  992.     if (button)
  993.    return(True);
  994.     return(False);
  995. }
  996.  
  997. NODE *ltone(NODE *args) {
  998. #ifndef WIN32
  999.     NODE *p, *d;
  1000.     FIXNUM pitch, duration;
  1001.  
  1002.     p = numeric_arg(args);
  1003.     d = numeric_arg(cdr(args));
  1004.  
  1005.     if (NOT_THROWING) {
  1006.    pitch = (nodetype(p) == FLOATT) ? (FIXNUM)getfloat(p) : getint(p);
  1007.    duration = (nodetype(d) == FLOATT) ? (FIXNUM)getfloat(d) : getint(d);
  1008.    if (pitch > 0) tone(pitch, duration);
  1009.     }
  1010. #else
  1011.     MessageBeep(0xffffffff);
  1012. #endif
  1013.  
  1014.     return(UNBOUND);
  1015. }
  1016.  
  1017. NODE *larc(NODE *arg) {
  1018.     NODE *val1;
  1019.     NODE *val2;
  1020.  
  1021.     FLONUM angle;
  1022.     FLONUM radius;
  1023.     FLONUM ang;
  1024.     FLONUM tx;
  1025.     FLONUM ty;
  1026.     FLONUM x;
  1027.     FLONUM y;
  1028.     FLONUM count;
  1029.     FLONUM delta;
  1030.     FLONUM i;
  1031.  
  1032.     int turtle_state;
  1033.     int pen_state;
  1034.  
  1035.     /* get args */
  1036.  
  1037.     val1 = numeric_arg(arg);
  1038.     val2 = numeric_arg(cdr(arg));
  1039.  
  1040.     if (NOT_THROWING) {
  1041.  
  1042.    if (nodetype(val1) == INT)
  1043.        angle = (FLONUM)getint(val1);
  1044.    else
  1045.        angle = getfloat(val1);
  1046.  
  1047.    if (nodetype(val2) == INT)
  1048.        radius = (FLONUM)getint(val2);
  1049.    else
  1050.        radius = getfloat(val2);
  1051.  
  1052.     prepare_to_draw;
  1053.     draw_turtle();
  1054.  
  1055.     /* save and force turtle state */
  1056.  
  1057.     turtle_state = turtle_shown;
  1058.     turtle_shown = 0;
  1059.  
  1060.     /* grab things before they change and use for restore */
  1061.  
  1062.     ang = turtle_heading;
  1063.     tx = turtle_x;
  1064.     ty = turtle_y;
  1065.  
  1066.     /* calculate resolution parameters */
  1067.  
  1068.     count = abs(angle*radius/200.0);
  1069.     if (count == 0.0) count = 1.0;
  1070.     delta = angle/count;
  1071.  
  1072.     /* draw each line segment of arc (will do wrap) */
  1073.  
  1074.     for (i=0.0;i<=count;i=i+1.0)
  1075.        {
  1076.  
  1077.        /* calc x y */
  1078.  
  1079.        x = sin(ang*3.141592654/180.0)*radius;
  1080.        y = cos(ang*3.141592654/180.0)*radius;
  1081.  
  1082.        /* jump to begin of first line segment without drawing */
  1083.  
  1084.        if (i==0.0)
  1085.           {
  1086.           pen_state = pen_vis;
  1087.           pen_vis = -1;
  1088.      save_vis();
  1089. #ifdef AMIGA   /* unexplained Amiga bug */
  1090.           setpos_bynumber(tx/x_scale+x, ty/y_scale+y);
  1091. #else
  1092.           setpos_bynumber(tx+x, ty+y);
  1093. #endif
  1094.           pen_vis = pen_state;
  1095.      save_vis();
  1096.           }
  1097.  
  1098.        /* else do segment */
  1099.  
  1100.        else
  1101.           {
  1102. #ifdef AMIGA
  1103.           setpos_bynumber(tx/x_scale+x, ty/y_scale+y);
  1104. #else
  1105.           setpos_bynumber(tx+x, ty+y);
  1106. #endif
  1107.           }
  1108.  
  1109.        ang = ang + delta;
  1110.        }
  1111.  
  1112.     /* assure we draw something and end in the exact right place */
  1113.  
  1114.     x = sin((turtle_heading+angle)*3.141592654/180.0)*radius;
  1115.     y = cos((turtle_heading+angle)*3.141592654/180.0)*radius;
  1116.  
  1117. #ifdef AMIGA
  1118.     setpos_bynumber(tx/x_scale+x, ty/y_scale+y);
  1119. #else
  1120.     setpos_bynumber(tx+x, ty+y);
  1121. #endif
  1122.  
  1123.     /* restore state */
  1124.  
  1125.     turtle_shown = turtle_state;
  1126.  
  1127.     turtle_x = tx;
  1128.     turtle_y = ty;
  1129.  
  1130.     draw_turtle();
  1131.     wanna_x = turtle_x;
  1132.     wanna_y = turtle_y;
  1133.     out_of_bounds = FALSE;
  1134.     pen_state = pen_vis;
  1135.     pen_vis = -1;
  1136.     save_vis();
  1137.     forward_helper((FLONUM)0.0);    /* Lets fill work -- dunno why */
  1138.     pen_vis = pen_state;
  1139.     save_vis();
  1140.  
  1141.     done_drawing;
  1142.     }
  1143.     return(UNBOUND);
  1144. }
  1145.  
  1146. /************************************************************/
  1147. /* The rest of this file implements the recording of moves in
  1148.    the graphics window and the playing back of those moves.  It's
  1149.    needed on machines like the Macintosh where the contents of the
  1150.    graphics window can get erased and need to be redrawn.  On
  1151.    machines where no graphics redrawing is necessary, set the size
  1152.    of the recording buffer to 1 in logo.h. */
  1153.  
  1154. BOOLEAN safe_to_save(void) {
  1155.     return(refresh_p && record_index < (GR_SIZE - 300));
  1156. }
  1157.  
  1158. void save_lm_helper (void) {
  1159.     *(int *)(record + record_index + One) = pen_x;
  1160.     *(int *)(record + record_index + Two) = pen_y;
  1161.     record_index += Three;
  1162. }
  1163.  
  1164. void save_line(void) {
  1165.     if (safe_to_save()) {
  1166.    record[record_index] = LINEXY;
  1167.    save_lm_helper();
  1168.     }
  1169. }
  1170.  
  1171. void save_move(void) {
  1172.     if (safe_to_save()) {
  1173.    record[record_index] = MOVEXY;
  1174.    save_lm_helper();
  1175.     }
  1176. }
  1177.  
  1178. void save_vis(void) {
  1179.     if (safe_to_save()) {
  1180.    record[record_index] = SETPENVIS;
  1181.    record[record_index + 1] = (char)pen_vis;
  1182.    record_index += One;
  1183.     }
  1184. }
  1185.  
  1186. void save_mode(void) {
  1187.     if (safe_to_save()) {
  1188.    record[record_index] = SETPENMODE;
  1189. #ifdef x_window
  1190.    *(GC *)(record + record_index + One) = pen_mode;
  1191. #else
  1192.    *(int *)(record + record_index + One) = pen_mode;
  1193. #endif
  1194.    *(int *)(record + record_index + Two) = internal_penmode;
  1195.    record_index += Three;
  1196.    save_color();
  1197.     }
  1198. }
  1199.  
  1200. void save_color(void) {
  1201.     if (safe_to_save()) {
  1202.    record[record_index] = SETPENCOLOR;
  1203.    *(int *)(record + record_index + One) = pen_color;
  1204.    record_index += Two;
  1205.     }
  1206. }
  1207.  
  1208. void save_size(void) {
  1209.     if (safe_to_save()) {
  1210.    record[record_index] = SETPENSIZE;
  1211.    *(int *)(record + record_index + One) = pen_width;
  1212.    *(int *)(record + record_index + Two) = pen_height;
  1213.    record_index += Three;
  1214.     }
  1215. }
  1216.  
  1217. void save_pattern(void) {
  1218.     if (safe_to_save()) {
  1219.    record[record_index] = SETPENPATTERN;
  1220.    get_pen_pattern(&record[record_index + One]);
  1221.    record_index += One+8;
  1222.     }
  1223. }
  1224.  
  1225. void save_string(char *s, int len) {
  1226.     int count;
  1227.  
  1228.     if (safe_to_save()) {
  1229.    record[record_index] = LABEL;
  1230.    record[record_index + One] = (unsigned char)len;
  1231.    for (count = 0; count <= len; count++)
  1232.        record[record_index + One+1 + count] = s[count];
  1233.    record[record_index + One+2 + len] = '\0';
  1234.    record_index += (One+2 + len + (One-1)) & ~(One-1);
  1235.     }
  1236. }
  1237.  
  1238. NODE *lrefresh(NODE *args) {
  1239.     refresh_p = TRUE;
  1240.     return(UNBOUND);
  1241. }
  1242.  
  1243. NODE *lnorefresh(NODE *args) {
  1244.     refresh_p = FALSE;
  1245.     return(UNBOUND);
  1246. }
  1247.  
  1248. void redraw_graphics(void) {
  1249.     int r_index = 0;
  1250.     pen_info saved_pen;
  1251.     BOOLEAN saved_shown;
  1252. #if defined(__ZTC__) && !defined(WIN32)
  1253.     BOOLEAN save_splitscreen = in_splitscreen;
  1254. #endif
  1255.  
  1256.     if (!refresh_p) {
  1257.     /*   clear_screen;
  1258.    draw_turtle(); */
  1259.    return;
  1260.     }
  1261.  
  1262.     saved_shown = turtle_shown;
  1263.     turtle_shown = FALSE;
  1264.     save_pen(&saved_pen);
  1265.     restore_pen(&orig_pen);
  1266.  
  1267. #if defined(__ZTC__) && !defined(WIN32)
  1268.     full_screen;
  1269. #endif
  1270.  
  1271.     erase_screen();
  1272.  
  1273. #ifdef __TURBOC__
  1274.     moveto(p_info_x(orig_pen),p_info_y(orig_pen));
  1275. #endif
  1276.  
  1277.     while (r_index < record_index)
  1278.    switch (record[r_index]) {
  1279.        case (LINEXY) :
  1280.       line_to(*(int *)(record + r_index + One),
  1281.          *(int *)(record + r_index + Two));
  1282.       r_index += Three;
  1283.       break;
  1284.        case (MOVEXY) :
  1285.       move_to(*(int *)(record + r_index + One),
  1286.          *(int *)(record + r_index + Two));
  1287.       r_index += Three;
  1288.       break;
  1289.        case (LABEL) :
  1290.       draw_string(record + r_index + One+1);
  1291.       r_index += (One+2 + record[r_index + One] + (One-1)) & ~(One-1);
  1292.       break;
  1293.        case (SETPENVIS) :
  1294.       set_pen_vis(record[r_index + 1]);
  1295.       r_index += One;
  1296.       break;
  1297.        case (SETPENMODE) :
  1298. #ifdef x_window
  1299.       set_pen_mode(*(GC *)(record + r_index + One));
  1300. #else
  1301.       set_pen_mode(*(int *)(record + r_index + One));
  1302. #endif
  1303.       internal_penmode = *(int *)(record + record_index + Two);
  1304.       r_index += Three;
  1305.       break;
  1306.        case (SETPENCOLOR) :
  1307.       set_pen_color(*(int *)(record + r_index + One));
  1308.       r_index += Two;
  1309.       break;
  1310.        case (SETPENSIZE) :
  1311.       set_pen_width(*(int *)(record + r_index + One));
  1312.       set_pen_height(*(int *)(record + r_index + Two));
  1313.       r_index += Three;
  1314.       break;
  1315.        case (SETPENPATTERN) :
  1316.       set_pen_pattern(&record[r_index + One]);
  1317.       r_index += One+8;
  1318.       break;
  1319.        case (FILLERUP) :
  1320.       logofill();
  1321.       r_index += One;
  1322.       break;
  1323.    }
  1324.  
  1325.     restore_pen(&saved_pen);
  1326.     turtle_shown = saved_shown;
  1327.  
  1328. #if defined(__ZTC__) && !defined(WIN32)
  1329.     if (save_splitscreen) {split_screen;}
  1330. #endif
  1331.  
  1332.     draw_turtle();
  1333. }
  1334.  
  1335. /* This is called when the graphics coordinate system has been shifted.
  1336.    It adds a constant amount to each x and y coordinate in the record. */
  1337. void resize_record(int dh, int dv) {
  1338.     int r_index = 0;
  1339.  
  1340.     p_info_x(orig_pen) += dh;
  1341.     p_info_y(orig_pen) += dv;
  1342.  
  1343.     while (r_index < record_index)
  1344.    switch (record[r_index]) {
  1345.        case (LINEXY) :
  1346.        case (MOVEXY) :
  1347.       *(int *)(record + r_index + One) += dh;
  1348.       *(int *)(record + r_index + Two) += dv;
  1349.       r_index += Three;
  1350.       break;
  1351.        case (LABEL) :
  1352.       r_index += (One+2 + record[r_index + One] + (One-1)) & ~(One-1);
  1353.       break;
  1354.        case (SETPENVIS) :
  1355.        case (FILLERUP) :
  1356.       r_index += One;
  1357.       break;
  1358.        case (SETPENCOLOR) :
  1359.       r_index += Two;
  1360.       break;
  1361.        case (SETPENSIZE) :
  1362.        case (SETPENMODE) :
  1363.       r_index += Three;
  1364.       break;
  1365.        case (SETPENPATTERN) :
  1366.       r_index += One+8;
  1367.       break;
  1368.    }
  1369. }
  1370.