[BACK]Return to plotport.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib / pari-2.2 / src / graph

Annotation of OpenXM_contrib/pari-2.2/src/graph/plotport.c, Revision 1.1.1.1

1.1       noro        1: /* $Id: plotport.c,v 1.15 2001/03/26 13:52:07 karim Exp $
                      2:
                      3: Copyright (C) 2000  The PARI group.
                      4:
                      5: This file is part of the PARI/GP package.
                      6:
                      7: PARI/GP is free software; you can redistribute it and/or modify it under the
                      8: terms of the GNU General Public License as published by the Free Software
                      9: Foundation. It is distributed in the hope that it will be useful, but WITHOUT
                     10: ANY WARRANTY WHATSOEVER.
                     11:
                     12: Check the License for details. You should have received a copy of it, along
                     13: with the package; see the file 'COPYING'. If not, write to the Free Software
                     14: Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
                     15:
                     16: /*******************************************************************/
                     17: /*                                                                 */
                     18: /*                         PLOT ROUTINES                           */
                     19: /*                                                                 */
                     20: /*******************************************************************/
                     21: #include "pari.h"
                     22: #include "rect.h"
                     23:
                     24: extern void push_val(entree *ep, GEN a);
                     25: extern void pop_val(entree *ep);
                     26: extern void postdraw0(long *w, long *x, long *y, long lw);
                     27: extern void postdraw00(long *w, long *x, long *y, long lw, long scale);
                     28: extern void rectdraw0(long *w, long *x, long *y, long lw, long do_free);
                     29: static void PARI_get_psplot();
                     30:
                     31: static long current_color[NUMRECT];
                     32: PariRect **rectgraph = NULL;
                     33: PARI_plot pari_plot, pari_psplot;
                     34: long  rectpoint_itype = 0;
                     35: long  rectline_itype  = 0;
                     36:
                     37: #define STRINGRECT (NUMRECT-2)
                     38: #define DRAWRECT (NUMRECT-1)
                     39:
                     40: #define PLOTH_NUMPOINTS 1000
                     41: #define PARAM_NUMPOINTS 1500
                     42: #define RECUR_NUMPOINTS 8
                     43:
                     44: #define RECUR_MAXDEPTH 10
                     45: #define RECUR_PREC 0.001
                     46: #define PARAMR_MAXDEPTH 10
                     47:
                     48: /********************************************************************/
                     49: /**                                                                **/
                     50: /**                         LOW-RES PLOT                           **/
                     51: /**                                                                **/
                     52: /********************************************************************/
                     53: #define ISCR 64
                     54: #define JSCR 22
                     55: #define BLANK ' '
                     56: #define ZERO1 ','
                     57: #define ZERO2 '-'
                     58: #define ZERO3 '`'
                     59: #define PICTZERO(j) ((j) % 3 ? ((j) % 3 == 2 ? ZERO3 : ZERO2) : ZERO1)
                     60: #define YY '|'
                     61: #define XX_UPPER '\''
                     62: #define XX_LOWER '.'
                     63: #define FF1 '_'
                     64: #define FF2 'x'
                     65: #define FF3 '"'
                     66: #define PICT(j) ((j) % 3 ? ((j) % 3 == 2 ? FF3 : FF2) : FF1)
                     67:
                     68: static char *
                     69: dsprintf9(double d, char *buf)
                     70: {
                     71:   int i = 10;
                     72:
                     73:   while (--i >= 0) {
                     74:     sprintf(buf, "%9.*g", i, d);
                     75:     if (strlen(buf) <= 9) return buf;
                     76:   }
                     77:   return buf; /* Should not happen? */
                     78: }
                     79:
                     80: typedef unsigned char screen[ISCR+1][JSCR+1];
                     81:
                     82: static void
                     83: fill_gap(screen scr, long i, int jnew, int jpre)
                     84: {
                     85:   int mid, i_up, i_lo, up, lo;
                     86:
                     87:   if (jpre < jnew - 2) {
                     88:     up = jnew - 1; i_up = i;
                     89:     lo = jpre + 1; i_lo = i - 1;
                     90:   } else if (jnew < jpre - 2) {
                     91:     up = jpre - 1; i_up = i - 1;
                     92:     lo = jnew + 1; i_lo = i;
                     93:   } else return; /* if gap < 2, leave it as it is. */
                     94:
                     95:   mid = (jpre+jnew)/2;
                     96:   if (mid>JSCR) mid=JSCR; else if (mid<0) mid=0;
                     97:   if (lo<0) lo=0;
                     98:   if (lo<=JSCR) while (lo <= mid) scr[i_lo][lo++] = ':';
                     99:   if (up>JSCR) up=JSCR;
                    100:   if (up>=0) while (up > mid) scr[i_up][up--] = ':';
                    101: }
                    102:
                    103: #define QUARK  ((char*)NULL) /* Used as a special-case */
                    104: static GEN quark_gen;
                    105:
                    106: #define READ_EXPR(s)   ((s)==QUARK? quark_gen : lisexpr(s))
                    107:
                    108: void
                    109: plot(entree *ep, GEN a, GEN b, char *ch,GEN ysmlu,GEN ybigu, long prec)
                    110: {
                    111:   long av = avma, av2,limite,jz,j,i,sig;
                    112:   int jnew, jpre = 0; /* for lint */
                    113:   GEN p1,p2,ysml,ybig,x,diff,dyj,dx,y[ISCR+1];
                    114:   screen scr;
                    115:   char buf[80], z;
                    116:
                    117:   sig=gcmp(b,a); if (!sig) return;
                    118:   if (sig<0) { x=a; a=b; b=x; }
                    119:   x = cgetr(prec); gaffect(a,x); push_val(ep, x);
                    120:   for (i=1; i<=ISCR; i++) y[i]=cgetr(3);
                    121:   p1 = gdivgs(gsub(b,a), ISCR-1);
                    122:   dx = cgetr(prec); gaffect(p1, dx);
                    123:   ysml=gzero; ybig=gzero;
                    124:   for (j=1; j<=JSCR; j++) scr[1][j]=scr[ISCR][j]=YY;
                    125:   for (i=2; i<ISCR; i++)
                    126:   {
                    127:     scr[i][1] = XX_LOWER;
                    128:     scr[i][JSCR]=XX_UPPER;
                    129:     for (j=2; j<JSCR; j++) scr[i][j]=BLANK;
                    130:   }
                    131:   av2=avma; limite=stack_lim(av2,1);
                    132:   for (i=1; i<=ISCR; i++)
                    133:   {
                    134:     gaffect(READ_EXPR(ch),y[i]);
                    135:     if (gcmp(y[i],ysml)<0) ysml=y[i];
                    136:     if (gcmp(y[i],ybig)>0) ybig=y[i];
                    137:     x = addrr(x,dx);
                    138:     if (low_stack(limite, stack_lim(av2,1)))
                    139:     {
                    140:       long tetpil=avma;
                    141:       if (DEBUGMEM>1) err(warnmem,"plot");
                    142:       x = gerepile(av2,tetpil,rcopy(x));
                    143:     }
                    144:     ep->value = (void*)x;
                    145:   }
                    146:   if (ysmlu) ysml=ysmlu;
                    147:   if (ybigu) ybig=ybigu;
                    148:   avma=av2; diff=gsub(ybig,ysml);
                    149:   if (gcmp0(diff)) { ybig=gaddsg(1,ybig); diff=gun; }
                    150:   dyj = gdivsg((JSCR-1)*3+2,diff);
                    151:   jz = 3-gtolong(gmul(ysml,dyj));
                    152:   av2=avma; z = PICTZERO(jz); jz = jz/3;
                    153:   for (i=1; i<=ISCR; i++)
                    154:   {
                    155:     if (0<=jz && jz<=JSCR) scr[i][jz]=z;
                    156:     j = 3+gtolong(gmul(gsub(y[i],ysml),dyj));
                    157:     jnew = j/3;
                    158:     if (i > 1) fill_gap(scr, i, jnew, jpre);
                    159:     if (0<=jnew && jnew<=JSCR) scr[i][jnew] = PICT(j);
                    160:     avma = av2;
                    161:     jpre = jnew;
                    162:   }
                    163:   p1=cgetr(3); gaffect(ybig,p1); pariputc('\n');
                    164:   pariputsf("%s ", dsprintf9(rtodbl(p1), buf));
                    165:   for (i=1; i<=ISCR; i++) pariputc(scr[i][JSCR]);
                    166:   pariputc('\n');
                    167:   for (j=(JSCR-1); j>=2; j--)
                    168:   {
                    169:     pariputs("          ");
                    170:     for (i=1; i<=ISCR; i++) pariputc(scr[i][j]);
                    171:     pariputc('\n');
                    172:   }
                    173:   p1=cgetr(3); gaffect(ysml,p1);
                    174:   pariputsf("%s ", dsprintf9(rtodbl(p1), buf));
                    175:   for (i=1; i<=ISCR; i++)  pariputc(scr[i][1]);
                    176:   pariputc('\n');
                    177:   p1=cgetr(3); gaffect(a,p1);
                    178:   p2=cgetr(3); gaffect(b,p2);
                    179:   pariputsf("%10s%-9.7g%*.7g\n"," ",rtodbl(p1),ISCR-9,rtodbl(p2));
                    180:   pop_val(ep); avma=av;
                    181: }
                    182:
                    183: /********************************************************************/
                    184: /**                                                                **/
                    185: /**                      RECTPLOT FUNCTIONS                        **/
                    186: /**                                                                **/
                    187: /********************************************************************/
                    188: void
                    189: init_graph()
                    190: {
                    191:   int n;
                    192:
                    193:   rectgraph = (PariRect**) gpmalloc(sizeof(PariRect*)*NUMRECT);
                    194:   for (n=0; n<NUMRECT; n++)
                    195:   {
                    196:     PariRect *e = (PariRect*) gpmalloc(sizeof(PariRect));
                    197:
                    198:     e->head = e->tail = NULL;
                    199:     e->sizex = e->sizey = 0;
                    200:     current_color[n] = DEFAULT_COLOR;
                    201:     rectgraph[n] = e;
                    202:   }
                    203: }
                    204:
                    205: void
                    206: free_graph()
                    207: {
                    208:   int i;
                    209:
                    210:   for (i=0; i<NUMRECT; i++)
                    211:   {
                    212:     PariRect *e=rectgraph[i];
                    213:
                    214:     if (RHead(e)) killrect(i);
                    215:     free((void *)e);
                    216:   }
                    217:   free((void *)rectgraph);
                    218: }
                    219:
                    220: static PariRect *
                    221: check_rect(long ne)
                    222: {
                    223:   if (!GOODRECT(ne))
                    224:     err(talker,"not an rplot vector type in graphic function");
                    225:   return rectgraph[ne];
                    226: }
                    227:
                    228: static PariRect *
                    229: check_rect_init(long ne)
                    230: {
                    231:   PariRect *e = check_rect(ne);
                    232:   if (!RHead(e))
                    233:     err(talker,"you must initialize the rectwindow first");
                    234:   return e;
                    235: }
                    236:
                    237: void
                    238: initrect_gen(long ne, GEN x, GEN y, long flag)
                    239: {
                    240:   long xi, yi;
                    241:   if (flag) {
                    242:     double xd = gtodouble(x), yd = gtodouble(y);
                    243:
                    244:     PARI_get_plot(0);
                    245:     xi = w_width - 1;  yi = w_height - 1;
                    246:     if (xd)
                    247:       xi = (long)(xd*xi + 0.5);
                    248:     if (yd)
                    249:       yi = (long)(yd*yi + 0.5);
                    250:   } else {
                    251:     xi = itos(x);  yi = itos(y);
                    252:     if (!xi || !yi)
                    253:       PARI_get_plot(0);
                    254:     if (!xi)
                    255:       xi = w_width - 1;
                    256:     if (!yi)
                    257:       yi = w_height - 1;
                    258:   }
                    259:   initrect(ne, xi, yi);
                    260: }
                    261:
                    262: void
                    263: initrect(long ne, long x, long y)
                    264: {
                    265:   PariRect *e;
                    266:   RectObj *z;
                    267:
                    268:   if (x<=1 || y<=1) err(talker,"incorrect dimensions in initrect");
                    269:   e = check_rect(ne); if (RHead(e)) killrect(ne);
                    270:
                    271:   z = (RectObj*) gpmalloc(sizeof(RectObj));
                    272:   RoNext(z) = NULL;
                    273:   RoType(z) = ROt_NULL;
                    274:   RHead(e)=RTail(e)=z;
                    275:   RXsize(e)=x; RYsize(e)=y;
                    276:   RXcursor(e)=0; RYcursor(e)=0;
                    277:   RXscale(e)=1; RXshift(e)=0;
                    278:   RYscale(e)=1; RYshift(e)=0;
                    279:   RHasGraph(e) = 0;
                    280: }
                    281:
                    282: GEN
                    283: rectcursor(long ne)
                    284: {
                    285:   PariRect *e = check_rect_init(ne);
                    286:   GEN z=cgetg(3,t_VEC);
                    287:
                    288:   z[1] = lstoi((long)RXcursor(e)); z[2] = lstoi((long)RYcursor(e));
                    289:   return z;
                    290: }
                    291:
                    292: static void
                    293: rectscale0(long ne, double x1, double x2, double y1, double y2)
                    294: {
                    295:   PariRect *e = check_rect_init(ne);
                    296:   double p2,p3;
                    297:
                    298:   p2 = RXshift(e) + RXscale(e) * RXcursor(e);
                    299:   p3 = RYshift(e) + RYscale(e) * RYcursor(e);
                    300:   RXscale(e) = RXsize(e)/(x2-x1); RXshift(e) = -x1*RXscale(e);
                    301:   RYscale(e) = RYsize(e)/(y1-y2); RYshift(e) = -y2*RYscale(e);
                    302:   RXcursor(e) = (p2 - RXshift(e)) / RXscale(e);
                    303:   RYcursor(e) = (p3 - RYshift(e)) / RYscale(e);
                    304: }
                    305:
                    306: void
                    307: rectscale(long ne, GEN x1, GEN x2, GEN y1, GEN y2)
                    308: {
                    309:   rectscale0(ne, gtodouble(x1), gtodouble(x2), gtodouble(y1), gtodouble(y2));
                    310: }
                    311:
                    312: /*
                    313:  * #ifdef LONG_IS_64BIT
                    314:  * #  define MAXDTOL 9223372036854775807.0
                    315:  * #else
                    316:  * #  define MAXDTOL 2147483647.0
                    317:  * #endif
                    318:  *
                    319:  *
                    320:  * long
                    321:  * DTOL(double t)
                    322:  * {
                    323:  *   if (fabs(t) > MAXDTOL) err(affer2);
                    324:  *   return (long)t;
                    325:  * }
                    326:  */
                    327:
                    328: static void
                    329: rectmove0(long ne, double x, double y, long relative)
                    330: {
                    331:   PariRect *e = check_rect_init(ne);
                    332:   RectObj *z = (RectObj*) gpmalloc(sizeof(RectObj1P));
                    333:
                    334:   if (relative)
                    335:    { RXcursor(e) += x; RYcursor(e) += y; }
                    336:   else
                    337:    { RXcursor(e) = x; RYcursor(e) = y; }
                    338:   RoNext(z) = 0; RoType(z) = ROt_MV;
                    339:   RoMVx(z) = RXcursor(e) * RXscale(e) + RXshift(e);
                    340:   RoMVy(z) = RYcursor(e) * RYscale(e) + RYshift(e);
                    341:   if (!RHead(e)) RHead(e)=RTail(e)=z;
                    342:   else { RoNext(RTail(e))=z; RTail(e)=z; }
                    343: }
                    344:
                    345: void
                    346: rectmove(long ne, GEN x, GEN y)
                    347: {
                    348:   rectmove0(ne,gtodouble(x),gtodouble(y),0);
                    349: }
                    350:
                    351: void
                    352: rectrmove(long ne, GEN x, GEN y)
                    353: {
                    354:   rectmove0(ne,gtodouble(x),gtodouble(y),1);
                    355: }
                    356:
                    357: void
                    358: rectpoint0(long ne, double x, double y,long relative) /* code = ROt_MV/ROt_PT */
                    359: {
                    360:   PariRect *e = check_rect_init(ne);
                    361:   RectObj *z = (RectObj*) gpmalloc(sizeof(RectObj1P));
                    362:
                    363:   if (relative)
                    364:    { RXcursor(e) += x; RYcursor(e) += y; }
                    365:   else
                    366:    { RXcursor(e) = x; RYcursor(e) = y; }
                    367:   RoNext(z)=0;
                    368:   RoPTx(z) = RXcursor(e)*RXscale(e) + RXshift(e);
                    369:   RoPTy(z) = RYcursor(e)*RYscale(e) + RYshift(e);
                    370:   RoType(z) = ( DTOL(RoPTx(z)) < 0
                    371:                || DTOL(RoPTy(z)) < 0 || DTOL(RoPTx(z)) > RXsize(e)
                    372:                || DTOL(RoPTy(z)) > RYsize(e) ) ? ROt_MV : ROt_PT;
                    373:   if (!RHead(e)) RHead(e)=RTail(e)=z;
                    374:   else { RoNext(RTail(e))=z; RTail(e)=z; }
                    375:   RoCol(z)=current_color[ne];
                    376: }
                    377:
                    378: void
                    379: rectpoint(long ne, GEN x, GEN y)
                    380: {
                    381:   rectpoint0(ne,gtodouble(x),gtodouble(y),0);
                    382: }
                    383:
                    384: void
                    385: rectrpoint(long ne, GEN x, GEN y)
                    386: {
                    387:   rectpoint0(ne,gtodouble(x),gtodouble(y),1);
                    388: }
                    389:
                    390: void
                    391: rectcolor(long ne, long color)
                    392: {
                    393:   check_rect(ne);
                    394:   if (!GOODCOLOR(color)) err(talker,"This is not a valid color");
                    395:   current_color[ne]=color;
                    396: }
                    397:
                    398: void
                    399: rectline0(long ne, double gx2, double gy2, long relative) /* code = ROt_MV/ROt_LN */
                    400: {
                    401:   double dx,dy,dxy,xmin,xmax,ymin,ymax,x1,y1,x2,y2;
                    402:   PariRect *e = check_rect_init(ne);
                    403:   RectObj *z = (RectObj*) gpmalloc(sizeof(RectObj2P));
                    404:   const double c = 1 + 1e-10;
                    405:
                    406:   x1 = RXcursor(e)*RXscale(e) + RXshift(e);
                    407:   y1 = RYcursor(e)*RYscale(e) + RYshift(e);
                    408:   if (relative)
                    409:     { RXcursor(e)+=gx2; RYcursor(e)+=gy2; }
                    410:   else
                    411:     { RXcursor(e)=gx2; RYcursor(e)=gy2; }
                    412:   x2 = RXcursor(e)*RXscale(e) + RXshift(e);
                    413:   y2 = RYcursor(e)*RYscale(e) + RYshift(e);
                    414:   xmin = max(min(x1,x2),0); xmax = min(max(x1,x2),RXsize(e));
                    415:   ymin = max(min(y1,y2),0); ymax = min(max(y1,y2),RYsize(e));
                    416:   dxy = x1*y2 - y1*x2; dx = x2-x1; dy = y2-y1;
                    417:   if (dy)
                    418:   {
                    419:     if (dx*dy<0)
                    420:       { xmin = max(xmin,(dxy+RYsize(e)*dx)/dy); xmax=min(xmax,dxy/dy); }
                    421:     else
                    422:       { xmin=max(xmin,dxy/dy); xmax=min(xmax,(dxy+RYsize(e)*dx)/dy); }
                    423:   }
                    424:   if (dx)
                    425:   {
                    426:     if (dx*dy<0)
                    427:       { ymin=max(ymin,(RXsize(e)*dy-dxy)/dx); ymax=min(ymax,-dxy/dx); }
                    428:     else
                    429:       { ymin=max(ymin,-dxy/dx); ymax=min(ymax,(RXsize(e)*dy-dxy)/dx); }
                    430:   }
                    431:   RoNext(z)=0;
                    432:   RoLNx1(z) = xmin; RoLNx2(z) = xmax;
                    433:   if (dx*dy<0) { RoLNy1(z) = ymax; RoLNy2(z) = ymin; }
                    434:   else { RoLNy1(z) = ymin; RoLNy2(z) = ymax; }
                    435:   RoType(z) = (xmin>xmax*c || ymin>ymax*c) ? ROt_MV : ROt_LN;
                    436:   if (!RHead(e)) RHead(e)=RTail(e)=z;
                    437:   else { RoNext(RTail(e))=z; RTail(e)=z; }
                    438:   RoCol(z)=current_color[ne];
                    439: }
                    440:
                    441: /* Given coordinates of ends of a line, and labels l1 l2 attached to the
                    442:    ends, plot ticks where the label coordinate takes "round" values */
                    443:
                    444: static void
                    445: rectticks(PARI_plot *WW, long ne,
                    446:           double dx1, double dy1, double dx2, double dy2,
                    447:           double l1, double l2, long flags)
                    448: {
                    449:   long dx,dy,dxy,dxy1,x1,y1,x2,y2,nticks,n,n1,dn;
                    450:   double minstep, maxstep, step, l_min, l_max, minl, maxl, dl, dtx, dty, x, y;
                    451:   double ddx, ddy;
                    452:   const double mult[3] = { 2./1., 5./2., 10./5. };
                    453:   PariRect *e = check_rect_init(ne);
                    454:   int do_double = !(flags & TICKS_NODOUBLE);
                    455:
                    456:   x1 = DTOL(dx1*RXscale(e) + RXshift(e));
                    457:   y1 = DTOL(dy1*RYscale(e) + RYshift(e));
                    458:   x2 = DTOL(dx2*RXscale(e) + RXshift(e));
                    459:   y2 = DTOL(dy2*RYscale(e) + RYshift(e));
                    460:   dx = x2 - x1;
                    461:   dy = y2 - y1;
                    462:   if (dx < 0) dx = -dx;
                    463:   if (dy < 0) dy = -dy;
                    464:   dxy1 = max(dx, dy);
                    465:   if (WW) {
                    466:     dx /= WW->hunit;
                    467:     dy /= WW->vunit;
                    468:   }
                    469:   else {
                    470:     PARI_get_plot(0);
                    471:     dx /= h_unit;
                    472:     dy /= v_unit;
                    473:   }
                    474:   dxy = (long)sqrt(dx*dx + dy*dy);
                    475:   nticks = (long) ((dxy + 2.5)/4);
                    476:   if (!nticks) return;
                    477:
                    478:   /* Now we want to find nticks (or less) "round" numbers between l1 and l2.
                    479:      For our purpose round numbers have "last significant" digit either
                    480:        *) any;
                    481:        *) even;
                    482:        *) divisible by 5.
                    483:      We need to choose which alternative is better.
                    484:    */
                    485:   if (l1 < l2)
                    486:     l_min = l1, l_max = l2;
                    487:   else
                    488:     l_min = l2, l_max = l1;
                    489:   minstep = (l_max - l_min)/(nticks + 1);
                    490:   maxstep = 2.5*(l_max - l_min);
                    491:   step = exp(log(10) * floor(log10(minstep)));
                    492:   if (!(flags & TICKS_ENDSTOO)) {
                    493:     double d = 2*(l_max - l_min)/dxy1; /* Two pixels off */
                    494:
                    495:     l_min += d;
                    496:     l_max -= d;
                    497:   }
                    498:   for (n = 0; ; n++) {
                    499:     if (step >= maxstep) return;
                    500:
                    501:     if (step >= minstep) {
                    502:       minl = ceil(l_min/step);
                    503:       maxl = floor(l_max/step);
                    504:       if (minl <= maxl && maxl - minl + 1 <= nticks) {
                    505:        nticks = (long) (maxl - minl + 1);
                    506:         l_min = minl * step;
                    507:         l_max = maxl * step; break;
                    508:       }
                    509:     }
                    510:     step *= mult[ n % 3 ];
                    511:   }
                    512:   /* Where to position doubleticks, variants:
                    513:      small: each 5, double: each 10    (n===2 mod 3)
                    514:      small: each 2, double: each 10    (n===1  mod 3)
                    515:      small: each 1, double: each  5 */
                    516:   dn = (n % 3 == 2)? 2: 5;
                    517:   n1 = ((long)minl) % dn; /* unused if do_double = FALSE */
                    518:
                    519:   /* now l_min and l_max keep min/max values of l with ticks, and nticks is
                    520:      the number of ticks to draw. */
                    521:   if (nticks == 1) ddx = ddy = 0; /* unused: for lint */
                    522:   else {
                    523:     dl = (l_max - l_min)/(nticks - 1);
                    524:     ddx = (dx2 - dx1) * dl / (l2 - l1);
                    525:     ddy = (dy2 - dy1) * dl / (l2 - l1);
                    526:   }
                    527:   x = dx1 + (dx2 - dx1) * (l_min - l1) / (l2 - l1);
                    528:   y = dy1 + (dy2 - dy1) * (l_min - l1) / (l2 - l1);
                    529:   /* assume h_unit and v_unit form a square.  For clockwise ticks: */
                    530:   dtx = h_unit * dy/dxy * (y2 > y1 ? 1 : -1);  /* y-coord runs down */
                    531:   dty = v_unit * dx/dxy * (x2 > x1 ? 1 : -1);
                    532:   for (n = 0; n < nticks; n++) {
                    533:     RectObj *z = (RectObj*) gpmalloc(sizeof(RectObj2P));
                    534:     double lunit = h_unit > 1 ? 1.5 : 2;
                    535:     double l = (do_double && (n + n1) % dn == 0) ? lunit: 1;
                    536:
                    537:     RoNext(z) = 0;
                    538:     RoLNx1(z) = RoLNx2(z) = x*RXscale(e) + RXshift(e);
                    539:     RoLNy1(z) = RoLNy2(z) = y*RYscale(e) + RYshift(e);
                    540:
                    541:     if (flags & TICKS_CLOCKW) {
                    542:       RoLNx1(z) += dtx*l;
                    543:       RoLNy1(z) -= dty*l;              /* y-coord runs down */
                    544:     }
                    545:     if (flags & TICKS_ACLOCKW) {
                    546:       RoLNx2(z) -= dtx*l;
                    547:       RoLNy2(z) += dty*l;              /* y-coord runs down */
                    548:     }
                    549:     RoType(z) = ROt_LN;
                    550:
                    551:     if (!RHead(e))
                    552:       RHead(e)=RTail(e)=z;
                    553:     else {
                    554:       RoNext(RTail(e))=z; RTail(e)=z;
                    555:     }
                    556:     RoCol(z)=current_color[ne];
                    557:     x += ddx;
                    558:     y += ddy;
                    559:   }
                    560: }
                    561:
                    562: void
                    563: rectline(long ne, GEN gx2, GEN gy2)
                    564: {
                    565:   rectline0(ne, gtodouble(gx2), gtodouble(gy2),0);
                    566: }
                    567:
                    568: void
                    569: rectrline(long ne, GEN gx2, GEN gy2)
                    570: {
                    571:   rectline0(ne, gtodouble(gx2), gtodouble(gy2),1);
                    572: }
                    573:
                    574: void
                    575: rectbox0(long ne, double gx2, double gy2, long relative)
                    576: {
                    577:   double x1,y1,x2,y2,xmin,ymin,xmax,ymax;
                    578:   double xx,yy;
                    579:   PariRect *e = check_rect_init(ne);
                    580:   RectObj *z = (RectObj*) gpmalloc(sizeof(RectObj2P));
                    581:
                    582:   x1 = RXcursor(e)*RXscale(e) + RXshift(e);
                    583:   y1 = RYcursor(e)*RYscale(e) + RYshift(e);
                    584:   if (relative)
                    585:   { xx = RXcursor(e)+gx2; yy = RYcursor(e)+gy2; }
                    586:   else
                    587:   {  xx = gx2; yy = gy2; }
                    588:   x2 = xx*RXscale(e) + RXshift(e);
                    589:   y2 = yy*RYscale(e) + RYshift(e);
                    590:   xmin = max(min(x1,x2),0); xmax = min(max(x1,x2),RXsize(e));
                    591:   ymin = max(min(y1,y2),0); ymax = min(max(y1,y2),RYsize(e));
                    592:
                    593:   RoNext(z)=0; RoType(z) = ROt_BX;
                    594:   RoBXx1(z) = xmin; RoBXy1(z) = ymin;
                    595:   RoBXx2(z) = xmax; RoBXy2(z) = ymax;
                    596:   if (!RHead(e)) RHead(e)=RTail(e)=z;
                    597:   else { RoNext(RTail(e))=z; RTail(e)=z; }
                    598:   RoCol(z)=current_color[ne];
                    599: }
                    600:
                    601: void
                    602: rectbox(long ne, GEN gx2, GEN gy2)
                    603: {
                    604:   rectbox0(ne, gtodouble(gx2), gtodouble(gy2), 0);
                    605: }
                    606:
                    607: void
                    608: rectrbox(long ne, GEN gx2, GEN gy2)
                    609: {
                    610:   rectbox0(ne, gtodouble(gx2), gtodouble(gy2), 1);
                    611: }
                    612:
                    613: void
                    614: killrect(long ne)
                    615: {
                    616:   RectObj *p1,*p2;
                    617:   PariRect *e = check_rect_init(ne);
                    618:
                    619:   current_color[ne]=DEFAULT_COLOR;
                    620:   p1=RHead(e);
                    621:   RHead(e) = RTail(e) = NULL;
                    622:   RXsize(e) = RYsize(e) = 0;
                    623:   RXcursor(e) = RYcursor(e) = 0;
                    624:   RXscale(e) = RYscale(e) = 1;
                    625:   RXshift(e) = RYshift(e) = 0;
                    626:   while (p1)
                    627:   {
                    628:     if (RoType(p1)==ROt_MP || RoType(p1)==ROt_ML)
                    629:     {
                    630:       free(RoMPxs(p1)); free(RoMPys(p1));
                    631:     }
                    632:     if (RoType(p1)==ROt_ST) free(RoSTs(p1));
                    633:     p2=RoNext(p1); free(p1); p1=p2;
                    634:   }
                    635: }
                    636:
                    637: void
                    638: rectpoints0(long ne, double *listx, double *listy, long lx) /* code = ROt_MP */
                    639: {
                    640:   double *ptx, *pty, x, y;
                    641:   long i, cp=0;
                    642:   PariRect *e = check_rect_init(ne);
                    643:   RectObj *z = (RectObj*) gpmalloc(sizeof(RectObjMP));
                    644:
                    645:   ptx=(double*) gpmalloc(lx*sizeof(double));
                    646:   pty=(double*) gpmalloc(lx*sizeof(double));
                    647:   for (i=0; i<lx; i++)
                    648:   {
                    649:     x = RXscale(e)*listx[i] + RXshift(e);
                    650:     y = RYscale(e)*listy[i] + RYshift(e);
                    651:     if ((x>=0)&&(y>=0)&&(x<=RXsize(e))&&(y<=RYsize(e)))
                    652:     {
                    653:       ptx[cp]=x; pty[cp]=y; cp++;
                    654:     }
                    655:   }
                    656:   RoNext(z)=0; RoType(z) = ROt_MP;
                    657:   RoMPcnt(z) = cp; RoMPxs(z) = ptx; RoMPys(z) = pty;
                    658:   if (!RHead(e)) RHead(e)=RTail(e)=z;
                    659:   else { RoNext(RTail(e))=z; RTail(e)=z; }
                    660:   RoCol(z)=current_color[ne];
                    661: }
                    662:
                    663: void
                    664: rectpoints(long ne, GEN listx, GEN listy)
                    665: {
                    666:   long i,lx, tx=typ(listx), ty=typ(listy);
                    667:   double *px,*py;
                    668:
                    669:   if (!is_matvec_t(tx) || !is_matvec_t(ty))
                    670:   {
                    671:     rectpoint(ne, listx, listy); return;
                    672:   }
                    673:   if (tx == t_MAT || ty == t_MAT) err(ploter4);
                    674:   lx=lg(listx); if (lg(listy)!=lx) err(ploter5);
                    675:   lx--; if (!lx) return;
                    676:
                    677:   px = (double*) gpmalloc(lx*sizeof(double));
                    678:   py = (double*) gpmalloc(lx*sizeof(double));
                    679:   for (i=0; i<lx; i++)
                    680:   {
                    681:     px[i]=gtodouble((GEN)listx[i+1]); py[i]=gtodouble((GEN)listy[i+1]);
                    682:   }
                    683:   rectpoints0(ne,px,py,lx);
                    684:   free(px); free(py);
                    685: }
                    686:
                    687: void
                    688: rectlines0(long ne, double *x, double *y, long lx, long flag) /* code = ROt_ML */
                    689: {
                    690:   long i,I;
                    691:   double *ptx,*pty;
                    692:   PariRect *e = check_rect_init(ne);
                    693:   RectObj *z = (RectObj*) gpmalloc(sizeof(RectObj2P));
                    694:
                    695:   I = flag ? lx+1 : lx;
                    696:   ptx = (double*) gpmalloc(I*sizeof(double));
                    697:   pty = (double*) gpmalloc(I*sizeof(double));
                    698:   for (i=0; i<lx; i++)
                    699:   {
                    700:     ptx[i] = RXscale(e)*x[i] + RXshift(e);
                    701:     pty[i] = RYscale(e)*y[i] + RYshift(e);
                    702:   }
                    703:   if (flag)
                    704:   {
                    705:     ptx[i] = RXscale(e)*x[0] + RXshift(e);
                    706:     pty[i] = RYscale(e)*y[0] + RYshift(e);
                    707:   }
                    708:   RoNext(z)=0; RoType(z)=ROt_ML;
                    709:   RoMLcnt(z)=lx; RoMLxs(z)=ptx; RoMLys(z)=pty;
                    710:   if (!RHead(e)) RHead(e)=RTail(e)=z;
                    711:   else { RoNext(RTail(e))=z; RTail(e)=z; }
                    712:   RoCol(z) = current_color[ne];
                    713: }
                    714:
                    715: void
                    716: rectlines(long ne, GEN listx, GEN listy, long flag)
                    717: {
                    718:   long tx=typ(listx), ty=typ(listy), lx=lg(listx), i;
                    719:   double *x, *y;
                    720:
                    721:   if (!is_matvec_t(tx) || !is_matvec_t(ty))
                    722:   {
                    723:     rectline(ne, listx, listy); return;
                    724:   }
                    725:   if (tx == t_MAT || ty == t_MAT) err(ploter4);
                    726:   if (lg(listy)!=lx) err(ploter5);
                    727:   lx--; if (!lx) return;
                    728:
                    729:   x = (double*) gpmalloc(lx*sizeof(double));
                    730:   y = (double*) gpmalloc(lx*sizeof(double));
                    731:   for (i=0; i<lx; i++)
                    732:   {
                    733:     x[i] = gtodouble((GEN)listx[i+1]); y[i] = gtodouble((GEN)listy[i+1]);
                    734:   }
                    735:   rectlines0(ne,x,y,lx,flag);
                    736:   free(x); free(y);
                    737: }
                    738:
                    739: static void
                    740: put_string(long win, long x, long y, char *str, long dir)
                    741: {
                    742:   rectmove0(win,(double)x,(double)y,0); rectstring3(win,str,dir);
                    743: }
                    744:
                    745: void
                    746: rectstring(long ne, char *str)
                    747: {
                    748:     rectstring3(ne,str,RoSTdirLEFT);
                    749: }
                    750:
                    751: /* Allocate memory, then put string */
                    752: void
                    753: rectstring3(long ne, char *str, long dir) /* code = ROt_ST */
                    754: {
                    755:   PariRect *e = check_rect_init(ne);
                    756:   RectObj *z = (RectObj*) gpmalloc(sizeof(RectObjST));
                    757:   long l = strlen(str);
                    758:   char *s = (char *) gpmalloc(l+1);
                    759:
                    760:   strcpy(s,str);
                    761:   RoNext(z)=0; RoType(z) = ROt_ST;
                    762:   RoSTl(z) = l; RoSTs(z) = s;
                    763:   RoSTx(z) = RXscale(e)*RXcursor(e)+RXshift(e);
                    764:   RoSTy(z) = RYscale(e)*RYcursor(e)+RYshift(e);
                    765:   RoSTdir(z) = dir;
                    766:   if (!RHead(e)) RHead(e)=RTail(e)=z;
                    767:   else { RoNext(RTail(e))=z; RTail(e)=z; }
                    768:   RoCol(z)=current_color[ne];
                    769: }
                    770:
                    771: void
                    772: rectpointtype(long ne, long type) /* code = ROt_PTT */
                    773: {
                    774:  if (ne == -1) {
                    775:      rectpoint_itype = type;
                    776:  } else {
                    777:   PariRect *e = check_rect_init(ne);
                    778:   RectObj *z = (RectObj*) gpmalloc(sizeof(RectObjPN));
                    779:
                    780:   RoNext(z) = 0; RoType(z) = ROt_PTT;
                    781:   RoPTTpen(z) = type;
                    782:   if (!RHead(e)) RHead(e)=RTail(e)=z;
                    783:   else { RoNext(RTail(e))=z; RTail(e)=z; }
                    784:  }
                    785: }
                    786:
                    787: void
                    788: rectpointsize(long ne, GEN size) /* code = ROt_PTS */
                    789: {
                    790:  if (ne == -1) {
                    791:      set_pointsize(gtodouble(size));   /* Immediate set */
                    792:  } else {
                    793:      PariRect *e = check_rect_init(ne);
                    794:      RectObj *z = (RectObj*) gpmalloc(sizeof(RectObjPS));
                    795:
                    796:      RoNext(z) = 0; RoType(z) = ROt_PTS;
                    797:      RoPTSsize(z) = gtodouble(size);
                    798:      if (!RHead(e)) RHead(e)=RTail(e)=z;
                    799:      else { RoNext(RTail(e))=z; RTail(e)=z; }
                    800:  }
                    801: }
                    802:
                    803: void
                    804: rectlinetype(long ne, long type)
                    805: {
                    806:  if (ne == -1) {
                    807:      rectline_itype = type;
                    808:  } else {
                    809:   PariRect *e = check_rect_init(ne);
                    810:   RectObj *z = (RectObj*) gpmalloc(sizeof(RectObjPN));
                    811:
                    812:   RoNext(z) = 0; RoType(z) = ROt_LNT;
                    813:   RoLNTpen(z) = type;
                    814:   if (!RHead(e)) RHead(e)=RTail(e)=z;
                    815:   else { RoNext(RTail(e))=z; RTail(e)=z; }
                    816:  }
                    817: }
                    818:
                    819: void
                    820: rectcopy_gen(long source, long dest, GEN xoff, GEN yoff, long flag)
                    821: {
                    822:   long xi, yi;
                    823:   if (flag & RECT_CP_RELATIVE) {
                    824:     double xd = gtodouble(xoff), yd = gtodouble(yoff);
                    825:
                    826:     PARI_get_plot(0);
                    827:     xi = w_width - 1;  yi = w_height - 1;
                    828:     xi = (long)(xd*xi + 0.5);
                    829:     yi = (long)(yd*yi + 0.5);
                    830:   } else {
                    831:     xi = itos(xoff);  yi = itos(yoff);
                    832:   }
                    833:   if (flag & ~RECT_CP_RELATIVE) {
                    834:     PariRect *s = check_rect_init(source), *d = check_rect_init(dest);
                    835:
                    836:     switch (flag & ~RECT_CP_RELATIVE) {
                    837:       case RECT_CP_NW:
                    838:        break;
                    839:       case RECT_CP_SW:
                    840:        yi = RYsize(d) - RYsize(s) - yi;
                    841:        break;
                    842:       case RECT_CP_SE:
                    843:        yi = RYsize(d) - RYsize(s) - yi;
                    844:        /* FALL THROUGH */
                    845:       case RECT_CP_NE:
                    846:        xi = RXsize(d) - RXsize(s) - xi;
                    847:        break;
                    848:     }
                    849:   }
                    850:   rectcopy(source, dest, xi, yi);
                    851: }
                    852:
                    853: void
                    854: rectcopy(long source, long dest, long xoff, long yoff)
                    855: {
                    856:   PariRect *s = check_rect_init(source), *d = check_rect_init(dest);
                    857:   RectObj *p1 = RHead(s);
                    858:   RectObj *tail = RTail(d);
                    859:   RectObj *next;
                    860:   int i;
                    861:
                    862:   while (p1)
                    863:   {
                    864:     switch(RoType(p1))
                    865:     {
                    866:       case ROt_PT:
                    867:        next = (RectObj*) gpmalloc(sizeof(RectObj1P));
                    868:        memcpy(next,p1,sizeof(RectObj1P));
                    869:        RoPTx(next) += xoff; RoPTy(next) += yoff;
                    870:        RoNext(tail) = next; tail = next;
                    871:        break;
                    872:       case ROt_LN: case ROt_BX:
                    873:        next = (RectObj*) gpmalloc(sizeof(RectObj2P));
                    874:        memcpy(next,p1,sizeof(RectObj2P));
                    875:        RoLNx1(next) += xoff; RoLNy1(next) += yoff;
                    876:        RoLNx2(next) += xoff; RoLNy2(next) += yoff;
                    877:        RoNext(tail) = next; tail = next;
                    878:        break;
                    879:       case ROt_MP: case ROt_ML:
                    880:        next = (RectObj*) gpmalloc(sizeof(RectObjMP));
                    881:        memcpy(next,p1,sizeof(RectObjMP));
                    882:        RoMPxs(next) = (double*) gpmalloc(sizeof(double)*RoMPcnt(next));
                    883:        RoMPys(next) = (double*) gpmalloc(sizeof(double)*RoMPcnt(next));
                    884:        memcpy(RoMPxs(next),RoMPxs(p1),sizeof(double)*RoMPcnt(next));
                    885:        memcpy(RoMPys(next),RoMPys(p1),sizeof(double)*RoMPcnt(next));
                    886:        for (i=0; i<RoMPcnt(next); i++)
                    887:        {
                    888:          RoMPxs(next)[i] += xoff; RoMPys(next)[i] += yoff;
                    889:         }
                    890:        RoNext(tail) = next; tail = next;
                    891:        break;
                    892:       case ROt_ST:
                    893:        next = (RectObj*) gpmalloc(sizeof(RectObjST));
                    894:        memcpy(next,p1,sizeof(RectObjMP));
                    895:        RoSTs(next) = (char*) gpmalloc(RoSTl(p1)+1);
                    896:        memcpy(RoSTs(next),RoSTs(p1),RoSTl(p1)+1);
                    897:        RoSTx(next) += xoff; RoSTy(next) += yoff;
                    898:        RoNext(tail) = next; tail = next;
                    899:        break;
                    900:       case ROt_PTT: case ROt_LNT: case ROt_PTS:
                    901:        next = (RectObj*) gpmalloc(sizeof(RectObjPN));
                    902:        memcpy(next,p1,sizeof(RectObjPN));
                    903:        RoNext(tail) = next; tail = next;
                    904:        break;
                    905:     }
                    906:     p1=RoNext(p1);
                    907:   }
                    908:   RoNext(tail) = NULL; RTail(d) = tail;
                    909: }
                    910:
                    911: #define CLIPLINE_NONEMPTY      1
                    912: #define CLIPLINE_CLIP_1                2
                    913: #define CLIPLINE_CLIP_2                4
                    914:
                    915: /* A simpler way is to clip by 4 half-planes */
                    916: static int
                    917: clipline(double xmin, double xmax, double ymin, double ymax,
                    918:          double *x1p, double *y1p, double *x2p, double *y2p)
                    919: {
                    920:     int xy_exch = 0, rc = CLIPLINE_NONEMPTY;
                    921:     double t, sl;
                    922:     double xi, xmn, xmx;
                    923:     double yi, ymn, ymx;
                    924:     int x1_is_ymn, x1_is_xmn;
                    925:     double x1 = *x1p, x2 = *x2p, y1 = *y1p, y2 = *y2p;
                    926:
                    927:     if ((x1 < xmin &&  x2 < xmin) || (x1 > xmax && x2 > xmax))
                    928:        return 0;
                    929:     if (fabs(x1 - x2) < fabs(y1 - y2)) { /* Exchange x and y */
                    930:        xy_exch = 1;
                    931:        t = xmin; xmin = ymin; ymin = t;
                    932:        t = xmax; xmax = ymax; ymax = t;
                    933:        t = x1; x1 = y1; y1 = t;
                    934:        t = x2; x2 = y2; y2 = t;
                    935:     }
                    936:
                    937:     /* Build y as a function of x */
                    938:     xi = x1, yi = y1;
                    939:     sl = ( (x1==x2) ? 0 : (y2 - yi)/(x2 - xi) );
                    940:
                    941:     xmn = x1, xmx = x2;
                    942:     if (x1 > x2) {
                    943:        x1_is_xmn = 0;
                    944:        xmn = x2, xmx = x1;
                    945:     } else
                    946:        x1_is_xmn = 1;
                    947:
                    948:     if (xmn < xmin) {
                    949:        xmn = xmin;
                    950:        rc |= (x1_is_xmn ? CLIPLINE_CLIP_1 : CLIPLINE_CLIP_2);
                    951:     }
                    952:
                    953:     if (xmx > xmax) {
                    954:        xmx = xmax;
                    955:        rc |= (x1_is_xmn ? CLIPLINE_CLIP_2 : CLIPLINE_CLIP_1);
                    956:     }
                    957:
                    958:     if (xmn > xmx)
                    959:        return 0;
                    960:
                    961:     ymn = yi + (xmn - xi)*sl;
                    962:     ymx = yi + (xmx - xi)*sl;
                    963:
                    964:     if (sl < 0)
                    965:        t = ymn, ymn = ymx, ymx = t;
                    966:     if (ymn > ymax || ymx < ymin)
                    967:        return 0;
                    968:
                    969:     if (rc & CLIPLINE_CLIP_1)
                    970:        x1 = (x1_is_xmn ? xmn : xmx);
                    971:     if (rc & CLIPLINE_CLIP_2)
                    972:        x2 = (x1_is_xmn ? xmx : xmn);
                    973:
                    974:     /* Now we know there is an intersection, need to move x1 and x2 */
                    975:     x1_is_ymn = ((sl >= 0) == (x1 < x2));
                    976:     if (ymn < ymin) {
                    977:        double x = (ymin - yi)/sl + xi; /* slope != 0  ! */
                    978:
                    979:        if (x1_is_ymn)
                    980:            x1 = x, rc |= CLIPLINE_CLIP_1;
                    981:        else
                    982:            x2 = x, rc |= CLIPLINE_CLIP_2;
                    983:     }
                    984:     if (ymx > ymax) {
                    985:        double x = (ymax - yi)/sl + xi; /* slope != 0  ! */
                    986:
                    987:        if (x1_is_ymn)
                    988:            x2 = x, rc |= CLIPLINE_CLIP_2;
                    989:        else
                    990:            x1 = x, rc |= CLIPLINE_CLIP_1;
                    991:     }
                    992:     if (rc & CLIPLINE_CLIP_1)
                    993:        y1 = yi + (x1 - xi)*sl;
                    994:     if (rc & CLIPLINE_CLIP_2)
                    995:        y2 = yi + (x2 - xi)*sl;
                    996:     if (xy_exch)                       /* Exchange x and y */
                    997:        *x1p = y1, *x2p = y2, *y1p = x1, *y2p = x2;
                    998:     else
                    999:        *x1p = x1, *x2p = x2, *y1p = y1, *y2p = y2;
                   1000:     return rc;
                   1001: }
                   1002:
                   1003: void
                   1004: rectclip(long rect)
                   1005: {
                   1006:   PariRect *s = check_rect_init(rect);
                   1007:   RectObj *p1 = RHead(s);
                   1008:   RectObj **prevp = &RHead(s);
                   1009:   RectObj *next;
                   1010:   double xmin = 0;
                   1011:   double xmax = RXsize(s);
                   1012:   double ymin = 0;
                   1013:   double ymax = RYsize(s);
                   1014:
                   1015:   while (p1) {
                   1016:       int did_clip = 0;
                   1017:
                   1018:       next = RoNext(p1);
                   1019:       switch(RoType(p1)) {
                   1020:       case ROt_PT:
                   1021:          if ( DTOL(RoPTx(p1)) < xmin || DTOL(RoPTx(p1)) > xmax
                   1022:               || DTOL(RoPTy(p1)) < ymin || DTOL(RoPTy(p1)) > ymax) {
                   1023:                 remove:
                   1024:              *prevp = next;
                   1025:              free(p1);
                   1026:              break;
                   1027:          }
                   1028:          goto do_next;
                   1029:       case ROt_BX:
                   1030:          if (RoLNx1(p1) < xmin)
                   1031:              RoLNx1(p1) = xmin, did_clip = 1;
                   1032:          if (RoLNx2(p1) < xmin)
                   1033:              RoLNx2(p1) = xmin, did_clip = 1;
                   1034:          if (RoLNy1(p1) < ymin)
                   1035:              RoLNy1(p1) = ymin, did_clip = 1;
                   1036:          if (RoLNy2(p1) < ymin)
                   1037:              RoLNy2(p1) = ymin, did_clip = 1;
                   1038:          if (RoLNx1(p1) > xmax)
                   1039:              RoLNx1(p1) = xmax, did_clip = 1;
                   1040:          if (RoLNx2(p1) > xmax)
                   1041:              RoLNx2(p1) = xmax, did_clip = 1;
                   1042:          if (RoLNy1(p1) > ymax)
                   1043:              RoLNy1(p1) = ymax, did_clip = 1;
                   1044:          if (RoLNy2(p1) > ymax)
                   1045:              RoLNy2(p1) = ymax, did_clip = 1;
                   1046:          /* Remove zero-size clipped boxes */
                   1047:          if ( did_clip
                   1048:               && RoLNx1(p1) == RoLNx2(p1) && RoLNy1(p1) == RoLNy2(p1) )
                   1049:              goto remove;
                   1050:          goto do_next;
                   1051:       case ROt_LN:
                   1052:          if (!clipline(xmin, xmax, ymin, ymax,
                   1053:                        &RoLNx1(p1), &RoLNy1(p1), &RoLNx2(p1), &RoLNy2(p1)))
                   1054:              goto remove;
                   1055:          goto do_next;
                   1056:       case ROt_MP:
                   1057:       {
                   1058:          int c = RoMPcnt(p1);
                   1059:          int f = 0, t = 0;
                   1060:
                   1061:          while (f < c) {
                   1062:              if ( DTOL(RoMPxs(p1)[f]) >= xmin && DTOL(RoMPxs(p1)[f]) <= xmax
                   1063:                   && DTOL(RoMPys(p1)[f]) >= ymin
                   1064:                   && DTOL(RoMPys(p1)[f]) <= ymax) {
                   1065:                  if (t != f) {
                   1066:                      RoMPxs(p1)[t] = RoMPxs(p1)[f];
                   1067:                      RoMPys(p1)[t] = RoMPys(p1)[f];
                   1068:                  }
                   1069:                  t++;
                   1070:              }
                   1071:              f++;
                   1072:          }
                   1073:          if (t == 0)
                   1074:              goto remove;
                   1075:          RoMPcnt(p1) = t;
                   1076:          goto do_next;
                   1077:       }
                   1078:       case ROt_ML:
                   1079:       {
                   1080:          /* Hard case.  Here we need to break a multiline into
                   1081:             several pieces if some part is clipped. */
                   1082:          int c = RoMPcnt(p1) - 1;
                   1083:          int f = 0, t = 0, had_lines = 0, had_hole = 0, rc;
                   1084:          double ox = RoMLxs(p1)[0], oy = RoMLys(p1)[0], oxn, oyn;
                   1085:
                   1086:          while (f < c) {
                   1087:              /* Endpoint of this segment is the startpoint of the
                   1088:                 next one, so we need to preserve it if it is clipped. */
                   1089:              oxn = RoMLxs(p1)[f + 1], oyn = RoMLys(p1)[f + 1];
                   1090:              rc = clipline(xmin, xmax, ymin, ymax,
                   1091:                            /* &RoMLxs(p1)[f], &RoMLys(p1)[f], */
                   1092:                            &ox, &oy,
                   1093:                            &RoMLxs(p1)[f+1], &RoMLys(p1)[f+1]);
                   1094:              RoMLxs(p1)[f] = ox; RoMLys(p1)[f] = oy;
                   1095:              ox = oxn; oy = oyn;
                   1096:              if (!rc) {
                   1097:                  if (had_lines)
                   1098:                      had_hole = 1;
                   1099:                  f++;
                   1100:                  continue;
                   1101:              }
                   1102:
                   1103:              if ( !had_lines || (!(rc & CLIPLINE_CLIP_1) && !had_hole) ) {
                   1104:                  /* Continuous */
                   1105:                  had_lines = 1;
                   1106:                  if (t != f) {
                   1107:                      if (t == 0) {
                   1108:                          RoMPxs(p1)[t] = RoMPxs(p1)[f];
                   1109:                          RoMPys(p1)[t] = RoMPys(p1)[f];
                   1110:                      }
                   1111:                      RoMPxs(p1)[t+1] = RoMPxs(p1)[f+1];
                   1112:                      RoMPys(p1)[t+1] = RoMPys(p1)[f+1];
                   1113:                  }
                   1114:                  t++;
                   1115:                  f++;
                   1116:                  if ( rc & CLIPLINE_CLIP_2)
                   1117:                      had_hole = 1, RoMLcnt(p1) = t + 1;
                   1118:                  continue;
                   1119:              }
                   1120:              /* Is not continuous, automatically p1 is not free()ed.  */
                   1121:              RoMLcnt(p1) = t + 1;
                   1122:              if ( rc & CLIPLINE_CLIP_2) { /* Needs separate entry */
                   1123:                  RectObj *n = (RectObj*) gpmalloc(sizeof(RectObj2P));
                   1124:
                   1125:                  RoType(n) = ROt_LN;
                   1126:                  RoCol(n) = RoCol(p1);
                   1127:                  RoLNx1(n) = RoMLxs(p1)[f];    RoLNy1(n) = RoMLys(p1)[f];
                   1128:                  RoLNx2(n) = RoMLxs(p1)[f+1];  RoLNy2(n) = RoMLys(p1)[f+1];
                   1129:                  RoNext(n) = next;
                   1130:                  RoNext(p1) = n;
                   1131:                  /* Restore the unclipped value: */
                   1132:                  RoMLxs(p1)[f + 1] = oxn;      RoMLys(p1)[f + 1] = oyn;
                   1133:                  f++;
                   1134:                  prevp = &RoNext(n);
                   1135:              }
                   1136:              if (f + 1 < c) {          /* Are other lines */
                   1137:                  RectObj *n = (RectObj*) gpmalloc(sizeof(RectObjMP));
                   1138:                  RoType(n) = ROt_ML;
                   1139:                  RoCol(n) = RoCol(p1);
                   1140:                  RoMLcnt(n) = c - f;
                   1141:                  RoMLxs(n) = (double*) gpmalloc(sizeof(double)*(c - f));
                   1142:                  RoMLys(n) = (double*) gpmalloc(sizeof(double)*(c - f));
                   1143:                  memcpy(RoMPxs(n),RoMPxs(p1) + f, sizeof(double)*(c - f));
                   1144:                  memcpy(RoMPys(n),RoMPys(p1) + f, sizeof(double)*(c - f));
                   1145:                  RoMPxs(n)[0] = oxn; RoMPys(n)[0] = oyn;
                   1146:                  RoNext(n) = next;
                   1147:                  RoNext(p1) = n;
                   1148:                  next = n;
                   1149:              }
                   1150:              goto do_next;
                   1151:          }
                   1152:          if (t == 0)
                   1153:              goto remove;
                   1154:          goto do_next;
                   1155:       }
                   1156: #if 0
                   1157:       case ROt_ST:
                   1158:          next = (RectObj*) gpmalloc(sizeof(RectObjMP));
                   1159:          memcpy(next,p1,sizeof(RectObjMP));
                   1160:          RoSTs(next) = (char*) gpmalloc(RoSTl(p1)+1);
                   1161:          memcpy(RoSTs(next),RoSTs(p1),RoSTl(p1)+1);
                   1162:          RoSTx(next) += xoff; RoSTy(next) += yoff;
                   1163:          RoNext(tail) = next; tail = next;
                   1164:          break;
                   1165: #endif
                   1166:       default: {
                   1167:        do_next:
                   1168:              prevp = &RoNext(p1);
                   1169:              break;
                   1170:          }
                   1171:       }
                   1172:       p1 = next;
                   1173:   }
                   1174: }
                   1175:
                   1176: /********************************************************************/
                   1177: /**                                                                **/
                   1178: /**                        HI-RES PLOT                             **/
                   1179: /**                                                                **/
                   1180: /********************************************************************/
                   1181:
                   1182: static void
                   1183: Appendx(dblPointList *f, dblPointList *l,double x)
                   1184: {
                   1185:   (l->d)[l->nb++]=x;
                   1186:   if (x < f->xsml) f->xsml=x;
                   1187:   else if (x > f->xbig) f->xbig=x;
                   1188: }
                   1189:
                   1190: static void
                   1191: Appendy(dblPointList *f, dblPointList *l,double y)
                   1192: {
                   1193:   (l->d)[l->nb++]=y;
                   1194:   if (y < f->ysml) f->ysml=y;
                   1195:   else if (y > f->ybig) f->ybig=y;
                   1196: }
                   1197:
                   1198: /* Convert data from GEN to double before we call rectplothrawin */
                   1199: static dblPointList*
                   1200: gtodblList(GEN data, long flags)
                   1201: {
                   1202:   dblPointList *l;
                   1203:   double xsml,xbig,ysml,ybig;
                   1204:   long tx=typ(data), ty, nl=lg(data)-1, lx1,lx;
                   1205:   register long i,j,u,v;
                   1206:   long param=(flags & PLOT_PARAMETRIC);
                   1207:   GEN x,y;
                   1208:
                   1209:   if (! is_vec_t(tx)) err(talker,"not a vector in gtodblList");
                   1210:   if (!nl) return NULL;
                   1211:   lx1=lg(data[1]);
                   1212:
                   1213:   /* Allocate memory, then convert coord. to double */
                   1214:   l=(dblPointList*) gpmalloc(nl*sizeof(dblPointList));
                   1215:   for (i=0; i<nl-1; i+=2)
                   1216:   {
                   1217:     u=i+1;
                   1218:     x=(GEN)data[u]; tx = typ(x);
                   1219:     y=(GEN)data[u+1]; ty = typ(y);
                   1220:     if (!is_vec_t(tx) || !is_vec_t(ty)) err(ploter4);
                   1221:     lx=lg(x); if (lg(y)!=lx) err(ploter5);
                   1222:     if (!param && lx != lx1) err(ploter5);
                   1223:     lx--;
                   1224:
                   1225:     if (lx)
                   1226:     {
                   1227:       l[i].d = (double*) gpmalloc(lx*sizeof(double));
                   1228:       l[u].d = (double*) gpmalloc(lx*sizeof(double));
                   1229:
                   1230:       for (j=0; j<lx; j=v)
                   1231:       {
                   1232:        v=j+1;
                   1233:        l[i].d[j]=gtodouble((GEN)x[v]);
                   1234:        l[u].d[j]=gtodouble((GEN)y[v]);
                   1235:       }
                   1236:     }
                   1237:     l[i].nb=l[u].nb=lx;
                   1238:   }
                   1239:
                   1240:   xsml=xbig=l[0].d[0]; ysml=ybig=l[1].d[0];
                   1241:
                   1242:   /* Now compute extremas */
                   1243:   if (param)
                   1244:   {
                   1245:     l[0].nb=nl/2;
                   1246:     for (i=0; i<l[0].nb; i+=2)
                   1247:     {
                   1248:       u=i+1;
                   1249:       for (j=0; j<l[u].nb; j++)
                   1250:       {
                   1251:        if (l[i].d[j]<xsml)
                   1252:          xsml=l[i].d[j];
                   1253:        else
                   1254:          if (l[i].d[j]>xbig) xbig=l[i].d[j];
                   1255:
                   1256:        if (l[u].d[j]<ysml)
                   1257:          ysml=l[u].d[j];
                   1258:        else
                   1259:          if (l[u].d[j]>ybig) ybig=l[u].d[j];
                   1260:       }
                   1261:     }
                   1262:   }
                   1263:   else
                   1264:   {
                   1265:     l[0].nb=nl-1;
                   1266:     for (j=0; j<l[1].nb; j++)
                   1267:     {
                   1268:       if (l[0].d[j]<xsml)
                   1269:        xsml=l[0].d[j];
                   1270:       else
                   1271:        if (l[0].d[j]>xbig) xbig=l[0].d[j];
                   1272:     }
                   1273:     for (i=1; i<=l[0].nb; i++)
                   1274:     {
                   1275:       for (j=0; j<l[i].nb; j++)
                   1276:       {
                   1277:        if (l[i].d[j]<ysml)
                   1278:          ysml=l[i].d[j];
                   1279:        else
                   1280:          if (l[i].d[j]>ybig) ybig=l[i].d[j];
                   1281:       }
                   1282:     }
                   1283:   }
                   1284:   l[0].xsml=xsml; l[0].xbig=xbig;
                   1285:   l[0].ysml=ysml; l[0].ybig=ybig;
                   1286:   return l;
                   1287: }
                   1288:
                   1289: static void
                   1290: single_recursion(dblPointList *pl,char *ch,entree *ep,GEN xleft,GEN yleft,
                   1291:   GEN xright,GEN yright,long depth)
                   1292: {
                   1293:   GEN xx,yy;
                   1294:   long av=avma;
                   1295:   double dy=pl[0].ybig - pl[0].ysml;
                   1296:
                   1297:   if (depth==RECUR_MAXDEPTH) return;
                   1298:
                   1299:   yy=cgetr(3); xx=gmul2n(gadd(xleft,xright),-1);
                   1300:   ep->value = (void*) xx; gaffect(READ_EXPR(ch), yy);
                   1301:
                   1302:   if (dy)
                   1303:   {
                   1304:     if (fabs(rtodbl(yleft)+rtodbl(yright)-2*rtodbl(yy))/dy < RECUR_PREC)
                   1305:       return;
                   1306:   }
                   1307:   single_recursion(pl,ch,ep, xleft,yleft, xx,yy, depth+1);
                   1308:
                   1309:   Appendx(&pl[0],&pl[0],rtodbl(xx));
                   1310:   Appendy(&pl[0],&pl[1],rtodbl(yy));
                   1311:
                   1312:   single_recursion(pl,ch,ep, xx,yy, xright,yright, depth+1);
                   1313:
                   1314:   avma=av;
                   1315: }
                   1316:
                   1317: static void
                   1318: param_recursion(dblPointList *pl,char *ch,entree *ep, GEN tleft,GEN xleft,
                   1319:   GEN yleft, GEN tright,GEN xright,GEN yright, long depth)
                   1320: {
                   1321:   GEN tt,xx,yy, p1;
                   1322:   long av=avma;
                   1323:   double dy=pl[0].ybig - pl[0].ysml;
                   1324:   double dx=pl[0].xbig - pl[0].xsml;
                   1325:
                   1326:   if (depth==PARAMR_MAXDEPTH) return;
                   1327:
                   1328:   xx=cgetr(3); yy=cgetr(3); tt=gmul2n(gadd(tleft,tright),-1);
                   1329:   ep->value = (void*)tt; p1=READ_EXPR(ch);
                   1330:   gaffect((GEN)p1[1],xx); gaffect((GEN)p1[2],yy);
                   1331:
                   1332:   if (dx && dy)
                   1333:   {
                   1334:     if (fabs(rtodbl(xleft)+rtodbl(xright)-2*rtodbl(xx))/dx < RECUR_PREC &&
                   1335:        fabs(rtodbl(yleft)+rtodbl(yright)-2*rtodbl(yy))/dy < RECUR_PREC)
                   1336:         return;
                   1337:   }
                   1338:   param_recursion(pl,ch,ep, tleft,xleft,yleft, tt,xx,yy, depth+1);
                   1339:
                   1340:   Appendx(&pl[0],&pl[0],rtodbl(xx));
                   1341:   Appendy(&pl[0],&pl[1],rtodbl(yy));
                   1342:
                   1343:   param_recursion(pl,ch,ep, tt,xx,yy, tright,xright,yright, depth+1);
                   1344:
                   1345:   avma=av;
                   1346: }
                   1347:
                   1348: /*
                   1349:  *  Pure graphing. If testpoints is 0, it is set to the default.
                   1350:  *  Returns a dblPointList of (absolute) coordinates.
                   1351:  */
                   1352: static dblPointList *
                   1353: rectplothin(entree *ep, GEN a, GEN b, char *ch, long prec, ulong flags,
                   1354:             long testpoints)
                   1355: {
                   1356:   long single_c;
                   1357:   long param=flags & PLOT_PARAMETRIC;
                   1358:   long recur=flags & PLOT_RECURSIVE;
                   1359:   GEN p1,dx,x,xleft,xright,yleft,yright,tleft,tright;
                   1360:   dblPointList *pl;
                   1361:   long tx,av = avma,av2,i,j,sig,nc,nl,nbpoints;
                   1362:   double xsml,xbig,ysml,ybig,fx,fy;
                   1363:
                   1364:   if (!testpoints)
                   1365:   {
                   1366:     if (recur)
                   1367:       testpoints = RECUR_NUMPOINTS;
                   1368:     else
                   1369:       testpoints = param? PARAM_NUMPOINTS : PLOTH_NUMPOINTS;
                   1370:   }
                   1371:   if (recur)
                   1372:     nbpoints = testpoints << (param? PARAMR_MAXDEPTH : RECUR_MAXDEPTH);
                   1373:   else
                   1374:     nbpoints = testpoints;
                   1375:
                   1376:   sig=gcmp(b,a); if (!sig) return 0;
                   1377:   if (sig<0) { x=a; a=b; b=x; }
                   1378:   dx=gdivgs(gsub(b,a),testpoints-1);
                   1379:
                   1380:   x = cgetr(prec); gaffect(a,x); push_val(ep, x);
                   1381:   av2=avma; p1=READ_EXPR(ch); tx=typ(p1);
                   1382:   if (!is_matvec_t(tx))
                   1383:   {
                   1384:     xsml = gtodouble(a);
                   1385:     xbig = gtodouble(b);
                   1386:     ysml = ybig = gtodouble(p1);
                   1387:     nc=1; nl=2; /* nc = nb of curves; nl = nb of coord. lists */
                   1388:     if (param)
                   1389:       err(warner,"flag PLOT_PARAMETRIC ignored");
                   1390:     single_c=1; param=0;
                   1391:   }
                   1392:   else
                   1393:   {
                   1394:     if (tx != t_VEC) err(talker,"not a row vector in ploth");
                   1395:     nl=lg(p1)-1; if (!nl) { avma=av; return 0; }
                   1396:     single_c=0;
                   1397:     if (param) nc=nl/2; else { nc=nl; nl++; }
                   1398:     if (recur && nc > 1) err(talker,"multi-curves cannot be plot recursively");
                   1399:
                   1400:     if (param)
                   1401:     {
                   1402:       xbig=xsml=gtodouble((GEN)p1[1]);
                   1403:       ybig=ysml=gtodouble((GEN)p1[2]);
                   1404:       for (i=3; i<=nl; i++)
                   1405:       {
                   1406:        fx=gtodouble((GEN)p1[i]); i++;
                   1407:         fy=gtodouble((GEN)p1[i]);
                   1408:        if (xsml>fx) xsml=fx; else if (xbig<fx) xbig=fx;
                   1409:        if (ysml>fy) ysml=fy; else if (ybig<fy) ybig=fy;
                   1410:       }
                   1411:     }
                   1412:     else
                   1413:     {
                   1414:       xsml=gtodouble(a); xbig=gtodouble(b);
                   1415:       ysml=gtodouble(vecmin(p1)); ybig=gtodouble(vecmax(p1));
                   1416:     }
                   1417:   }
                   1418:
                   1419:   pl=(dblPointList*) gpmalloc(nl*sizeof(dblPointList));
                   1420:   for (i = 0; i < nl; i++)
                   1421:   {
                   1422:     pl[i].d = (double*) gpmalloc((nbpoints+1)*sizeof(dblPointList));
                   1423:     pl[i].nb=0;
                   1424:   }
                   1425:   pl[0].xsml=xsml; pl[0].ysml=ysml; pl[0].xbig=xbig; pl[0].ybig=ybig;
                   1426:
                   1427:   if (recur) /* recursive plot */
                   1428:   {
                   1429:     xleft=cgetr(3); xright=cgetr(3); yleft=cgetr(3); yright=cgetr(3);
                   1430:     if (param)
                   1431:     {
                   1432:       tleft=cgetr(prec); tright=cgetr(prec);
                   1433:       av2=avma;
                   1434:       gaffect(a,tleft); ep->value = (void*)tleft; p1=READ_EXPR(ch);
                   1435:       gaffect((GEN)p1[1],xleft); gaffect((GEN)p1[2],yleft);
                   1436:       for (i=0; i<testpoints-1; i++)
                   1437:       {
                   1438:        if (i) {
                   1439:          gaffect(tright,tleft); gaffect(xright,xleft); gaffect(yright,yleft);
                   1440:         }
                   1441:        gaddz(tleft,dx,tright); ep->value = (void*)tright;
                   1442:         p1 = READ_EXPR(ch);
                   1443:         if (lg(p1) != 3) err(talker,"inconsistent data in rectplothin");
                   1444:         gaffect((GEN)p1[1],xright); gaffect((GEN)p1[2],yright);
                   1445:
                   1446:        Appendx(&pl[0],&pl[0],rtodbl(xleft));
                   1447:        Appendy(&pl[0],&pl[1],rtodbl(yleft));
                   1448:
                   1449:        param_recursion(pl,ch,ep, tleft,xleft,yleft, tright,xright,yright, 0);
                   1450:        avma=av2;
                   1451:       }
                   1452:       Appendx(&pl[0],&pl[0],rtodbl(xright));
                   1453:       Appendy(&pl[0],&pl[1],rtodbl(yright));
                   1454:     }
                   1455:     else /* single_c */
                   1456:     {
                   1457:       av2=avma;
                   1458:       gaffect(a,xleft); ep->value = (void*) xleft;
                   1459:       gaffect(READ_EXPR(ch),yleft);
                   1460:       for (i=0; i<testpoints-1; i++)
                   1461:       {
                   1462:         gaddz(xleft,dx,xright); ep->value = (void*) xright;
                   1463:        gaffect(READ_EXPR(ch),yright);
                   1464:
                   1465:        Appendx(&pl[0],&pl[0],rtodbl(xleft));
                   1466:        Appendy(&pl[0],&pl[1],rtodbl(yleft));
                   1467:
                   1468:         single_recursion(pl,ch,ep,xleft,yleft,xright,yright,0);
                   1469:         avma=av2;
                   1470:         gaffect(xright,xleft); gaffect(yright,yleft);
                   1471:       }
                   1472:       Appendx(&pl[0],&pl[0],rtodbl(xright));
                   1473:       Appendy(&pl[0],&pl[1],rtodbl(yright));
                   1474:     }
                   1475:   }
                   1476:   else /* non-recursive plot */
                   1477:   {
                   1478:     if (single_c)
                   1479:       for (i=0; i<testpoints; i++)
                   1480:       {
                   1481:        p1 = READ_EXPR(ch);
                   1482:        pl[0].d[i]=gtodouble(x);
                   1483:        Appendy(&pl[0],&pl[1],gtodouble(p1));
                   1484:        gaddz(x,dx,x); avma=av2;
                   1485:       }
                   1486:     else if (param)
                   1487:     {
                   1488:       long k;
                   1489:       double z;
                   1490:
                   1491:       for (i=0; i<testpoints; i++)
                   1492:       {
                   1493:        p1 = READ_EXPR(ch);
                   1494:         if (lg(p1) != nl+1) err(talker,"inconsistent data in rectplothin");
                   1495:        for (j=0; j<nl; j=k)
                   1496:        {
                   1497:          k=j+1; z=gtodouble((GEN)p1[k]);
                   1498:          Appendx(&pl[0], &pl[j],z);
                   1499:
                   1500:          j=k; k++; z=gtodouble((GEN)p1[k]);
                   1501:          Appendy(&pl[0], &pl[j],z);
                   1502:         }
                   1503:        gaddz(x,dx,x); avma=av2;
                   1504:       }
                   1505:     }
                   1506:     else /* plothmult */
                   1507:       for (i=0; i<testpoints; i++)
                   1508:       {
                   1509:        p1 = READ_EXPR(ch);
                   1510:         if (lg(p1) != nl) err(talker,"inconsistent data in rectplothin");
                   1511:        pl[0].d[i]=gtodouble(x);
                   1512:        for (j=1; j<nl; j++) { Appendy(&pl[0],&pl[j],gtodouble((GEN)p1[j])); }
                   1513:        gaddz(x,dx,x); avma=av2;
                   1514:       }
                   1515:   }
                   1516:   pl[0].nb=nc; pop_val(ep); avma = av;
                   1517:   return pl;
                   1518: }
                   1519:
                   1520: extern GEN polint_i(GEN xa, GEN ya, GEN x, long n, GEN *ptdy);
                   1521:
                   1522: /* Uses highlevel plotting functions to implement splines as
                   1523:    a low-level plotting function.
                   1524:    Most probably one does not need to make varn==0 into pure variable,
                   1525:    since plotting functions should take care of this. */
                   1526: static void
                   1527: rectsplines(long ne, double *x, double *y, long lx, long flag)
                   1528: {
                   1529:   long i, j, oldavma = avma;
                   1530:   GEN tas, xa = cgetg(lx+1, t_VEC), ya = cgetg(lx+1, t_VEC);
                   1531:   entree *var0 = varentries[ordvar[0]];
                   1532:
                   1533:   if (lx < 4)
                   1534:       err(talker, "Too few points (%ld) for spline plot", lx);
                   1535:   for (i = 1; i <= lx; i++) {
                   1536:       xa[i] = (long) dbltor(x[i-1]);
                   1537:       ya[i] = (long) dbltor(y[i-1]);
                   1538:   }
                   1539:   if (flag & PLOT_PARAMETRIC) {
                   1540:       tas = new_chunk(4);
                   1541:       for (j = 1; j <= 4; j++) tas[j-1] = lstoi(j);
                   1542:       quark_gen = cgetg(2 + 1, t_VEC);
                   1543:   }
                   1544:   else tas = NULL; /* for lint */
                   1545:   for (i = 0; i <= lx - 4; i++) {
                   1546:       long oavma = avma;
                   1547:
                   1548:       xa++; ya++;
                   1549:       if (flag & PLOT_PARAMETRIC) {
                   1550:          quark_gen[1] = (long)polint_i(tas, xa, polx[0], 4, NULL);
                   1551:          quark_gen[2] = (long)polint_i(tas, ya, polx[0], 4, NULL);
                   1552:       } else {
                   1553:          quark_gen = polint_i(xa, ya, polx[0], 4, NULL);
                   1554:           tas = xa;
                   1555:       }
                   1556:       rectploth(ne, var0,
                   1557:                  (GEN)(i==0 ? tas[0] : tas[1]),
                   1558:                  (GEN)(i==lx-4 ? tas[3] : tas[2]),
                   1559:                  QUARK,
                   1560:                 DEFAULTPREC,           /* XXXX precision */
                   1561:                 PLOT_RECURSIVE
                   1562:                    | PLOT_NO_RESCALE
                   1563:                    | PLOT_NO_FRAME
                   1564:                   | PLOT_NO_AXE_Y
                   1565:                    | PLOT_NO_AXE_X
                   1566:                    | (flag & PLOT_PARAMETRIC),
                   1567:                 2);                    /* Start with 3 points */
                   1568:       avma = oavma;
                   1569:   }
                   1570:   avma = oldavma;
                   1571: }
                   1572:
                   1573: /*
                   1574:  * Plot a dblPointList. Complete with axes, bounding box, etc.
                   1575:  * We use two drawing rectangles: one for strings, another
                   1576:  * for graphs.
                   1577:  *
                   1578:  * data is an array of structs. Its meaning depends on flags :
                   1579:  *
                   1580:  * + data[0] contains global extremas, the number of curves to plot
                   1581:  *   (data[0].nb) and a list of doubles (first set of x-coordinates).
                   1582:  *
                   1583:  * + data[i].nb (i>0) contains the number of points in the list
                   1584:  *   data[i].d (hopefully, data[2i].nb=data[2i+1].nb when i>0...)
                   1585:  *
                   1586:  * + If flags contain PLOT_PARAMETRIC, the array length should be
                   1587:  *   even, and successive pairs (data[2i].d, data[2i+1].d) represent
                   1588:  *   curves to plot.
                   1589:  *
                   1590:  * + If there is no such flag, the first element is an array with
                   1591:  *   x-coordinates and the following ones contain y-coordinates.
                   1592:  *
                   1593:  * Additional flags: PLOT_NO_AXE_X, PLOT_NO_AXE_Y, PLOT_NO_FRAME.
                   1594:  */
                   1595:
                   1596: static GEN
                   1597: rectplothrawin(long stringrect, long drawrect, dblPointList *data,
                   1598:                long flags, PARI_plot *WW)
                   1599: {
                   1600:   GEN res;
                   1601:   dblPointList y,x;
                   1602:   double xsml,xbig,ysml,ybig,tmp;
                   1603:   long ltype, ltop=avma;
                   1604:   long i,nc,nbpoints, w[2], wx[2], wy[2];
                   1605:
                   1606:   w[0]=stringrect; w[1]=drawrect;
                   1607:   if (!data) return cgetg(1,t_VEC);
                   1608:   x = data[0]; nc = x.nb;
                   1609:   xsml = x.xsml; xbig = x.xbig;
                   1610:   ysml = x.ysml; ybig = x.ybig;
                   1611:   if (xbig-xsml < 1.e-9)
                   1612:   {
                   1613:     tmp=fabs(xsml)/10; if (!tmp) tmp=0.1;
                   1614:     xbig+=tmp; xsml-=tmp;
                   1615:   }
                   1616:   if (ybig-ysml < 1.e-9)
                   1617:   {
                   1618:     tmp=fabs(ysml)/10; if (!tmp) tmp=0.1;
                   1619:     ybig+=tmp; ysml-=tmp;
                   1620:   }
                   1621:
                   1622:   if (WW)
                   1623:   { /* no rectwindow supplied ==> ps or screen output */
                   1624:     char c1[16],c2[16],c3[16],c4[16];
                   1625:     PARI_plot W = *WW;
                   1626:     long lm = W.fwidth*10; /* left margin   */
                   1627:     long rm = W.hunit-1; /* right margin  */
                   1628:     long tm = W.vunit-1; /* top margin    */
                   1629:     long bm = W.vunit+W.fheight-1; /* bottom margin */
                   1630:     long is = W.width - (lm+rm);
                   1631:     long js = W.height - (tm+bm);
                   1632:
                   1633:     wx[0]=wy[0]=0; wx[1]=lm; wy[1]=tm;
                   1634:    /* Window size (W.width x W.height) is given in pixels, and
                   1635:     * correct pixels are 0..w_width-1.
                   1636:     * On the other hand, rect functions work with windows whose pixel
                   1637:     * range is [0,width]. */
                   1638:     initrect(stringrect, W.width-1, W.height-1);
                   1639:     if (drawrect != stringrect) initrect(drawrect, is-1, js-1);
                   1640:
                   1641:     /* draw labels on stringrect */
                   1642:     sprintf(c1,"%.5g",ybig); sprintf(c2,"%.5g",ysml);
                   1643:     sprintf(c3,"%.5g",xsml); sprintf(c4,"%.5g",xbig);
                   1644:
                   1645:     rectlinetype(stringrect,-2); /* Frame */
                   1646:     current_color[stringrect]=BLACK;
                   1647:     put_string( stringrect, lm, 0, c1,
                   1648:                RoSTdirRIGHT | RoSTdirHGAP | RoSTdirTOP);
                   1649:     put_string(stringrect, lm, W.height - bm, c2,
                   1650:                RoSTdirRIGHT | RoSTdirHGAP | RoSTdirVGAP);
                   1651:     put_string(stringrect, lm, W.height - bm, c3,
                   1652:                RoSTdirLEFT | RoSTdirTOP);
                   1653:     put_string(stringrect, W.width - rm - 1, W.height - bm, c4,
                   1654:                RoSTdirRIGHT | RoSTdirTOP);
                   1655:   }
                   1656:   RHasGraph(check_rect(drawrect)) = 1;
                   1657:
                   1658:   if (!(flags & PLOT_NO_RESCALE))
                   1659:     rectscale0(drawrect, xsml, xbig, ysml, ybig);
                   1660:
                   1661:   if (!(flags & PLOT_NO_FRAME))
                   1662:   {
                   1663:     int do_double = (flags & PLOT_NODOUBLETICK) ? TICKS_NODOUBLE : 0;
                   1664:
                   1665:     rectlinetype(drawrect, -2);                /* Frame. */
                   1666:     current_color[drawrect]=BLACK;
                   1667:     rectmove0(drawrect,xsml,ysml,0);
                   1668:     rectbox0(drawrect,xbig,ybig,0);
                   1669:     if (!(flags & PLOT_NO_TICK_X)) {
                   1670:       rectticks(WW, drawrect, xsml, ysml, xbig, ysml, xsml, xbig,
                   1671:        TICKS_CLOCKW | do_double);
                   1672:       rectticks(WW, drawrect, xbig, ybig, xsml, ybig, xbig, xsml,
                   1673:        TICKS_CLOCKW | do_double);
                   1674:     }
                   1675:     if (!(flags & PLOT_NO_TICK_Y)) {
                   1676:       rectticks(WW, drawrect, xbig, ysml, xbig, ybig, ysml, ybig,
                   1677:        TICKS_CLOCKW | do_double);
                   1678:       rectticks(WW, drawrect, xsml, ybig, xsml, ysml, ybig, ysml,
                   1679:        TICKS_CLOCKW | do_double);
                   1680:     }
                   1681:   }
                   1682:
                   1683:   if (!(flags & PLOT_NO_AXE_Y) && (xsml<=0 && xbig >=0))
                   1684:   {
                   1685:     rectlinetype(drawrect, -1);                /* Axes. */
                   1686:     current_color[drawrect]=BLUE;
                   1687:     rectmove0(drawrect,0.0,ysml,0);
                   1688:     rectline0(drawrect,0.0,ybig,0);
                   1689:   }
                   1690:
                   1691:   if (!(flags & PLOT_NO_AXE_X) && (ysml<=0 && ybig >=0))
                   1692:   {
                   1693:     rectlinetype(drawrect, -1);                /* Axes. */
                   1694:     current_color[drawrect]=BLUE;
                   1695:     rectmove0(drawrect,xsml,0.0,0);
                   1696:     rectline0(drawrect,xbig,0.0,0);
                   1697:   }
                   1698:
                   1699:   i = (flags & PLOT_PARAMETRIC)? 0: 1;
                   1700:   for (ltype = 0; ltype < nc; ltype++)
                   1701:   {
                   1702:     current_color[drawrect] = ltype&1 ? SIENNA: RED;
                   1703:     if (flags & PLOT_PARAMETRIC) x = data[i++];
                   1704:
                   1705:     y=data[i++]; nbpoints=y.nb;
                   1706:     if ((flags & PLOT_POINTS_LINES) || (flags & PLOT_POINTS)) {
                   1707:        rectlinetype(drawrect, rectpoint_itype + ltype);        /* Graphs. */
                   1708:        rectpointtype(drawrect, rectpoint_itype + ltype);       /* Graphs. */
                   1709:        rectpoints0(drawrect,x.d,y.d,nbpoints);
                   1710:     }
                   1711:     if ((flags & PLOT_POINTS_LINES) || !(flags & PLOT_POINTS)) {
                   1712:        if (flags & PLOT_SPLINES) {
                   1713:            /* rectsplines will call us back with ltype == 0 */
                   1714:            int old = rectline_itype;
                   1715:
                   1716:            rectline_itype = rectline_itype + ltype;
                   1717:            rectsplines(drawrect,x.d,y.d,nbpoints,flags);
                   1718:            rectline_itype = old;
                   1719:        } else {
                   1720:            rectlinetype(drawrect, rectline_itype + ltype);     /* Graphs. */
                   1721:            rectlines0(drawrect,x.d,y.d,nbpoints,0);
                   1722:        }
                   1723:     }
                   1724:   }
                   1725:   for (i--; i>=0; i--) free(data[i].d);
                   1726:   free(data);
                   1727:
                   1728:   if (WW)
                   1729:   {
                   1730:     if (flags & PLOT_POSTSCRIPT)
                   1731:       postdraw0(w,wx,wy,2);
                   1732:     else
                   1733:       rectdraw0(w,wx,wy,2, 0);
                   1734:
                   1735:     killrect(drawrect); if (stringrect != drawrect) killrect(stringrect);
                   1736:   }
                   1737:
                   1738:   avma=ltop;
                   1739:   res = cgetg(5,t_VEC);
                   1740:   res[1]=(long)dbltor(xsml); res[2]=(long)dbltor(xbig);
                   1741:   res[3]=(long)dbltor(ysml); res[4]=(long)dbltor(ybig);
                   1742:   return res;
                   1743: }
                   1744:
                   1745: /*************************************************************************/
                   1746: /*                                                                       */
                   1747: /*                          HI-RES FUNCTIONS                             */
                   1748: /*                                                                       */
                   1749: /*************************************************************************/
                   1750:
                   1751: GEN
                   1752: rectploth(long drawrect,entree *ep,GEN a,GEN b,char *ch,
                   1753:           long prec,ulong flags,long testpoints)
                   1754: {
                   1755:   dblPointList *pl=rectplothin(ep, a,b, ch, prec, flags,testpoints);
                   1756:   return rectplothrawin(0,drawrect, pl, flags,NULL);
                   1757: }
                   1758:
                   1759: GEN
                   1760: rectplothraw(long drawrect, GEN data, long flags)
                   1761: {
                   1762:   dblPointList *pl=gtodblList(data,flags);
                   1763:   return rectplothrawin(0,drawrect,pl,flags,NULL);
                   1764: }
                   1765:
                   1766: static PARI_plot*
                   1767: init_output(long flags)
                   1768: {
                   1769:   if (flags & PLOT_POSTSCRIPT)
                   1770:     { PARI_get_psplot(); return &pari_psplot; }
                   1771:   else
                   1772:     { PARI_get_plot(0); return &pari_plot; }
                   1773: }
                   1774:
                   1775: static GEN
                   1776: ploth0(long stringrect,long drawrect,entree *ep,GEN a,GEN b,char *ch,
                   1777:              long prec,ulong flags,long testpoints)
                   1778: {
                   1779:   PARI_plot *output = init_output(flags);
                   1780:   dblPointList *pl=rectplothin(ep, a,b, ch, prec, flags,testpoints);
                   1781:   return rectplothrawin(stringrect,drawrect, pl, flags, output);
                   1782: }
                   1783:
                   1784: static GEN
                   1785: plothraw0(long stringrect, long drawrect, GEN listx, GEN listy, long flags)
                   1786: {
                   1787:   PARI_plot *output = init_output(flags);
                   1788:   long data[] = {evaltyp(t_VEC) | m_evallg(3), 0, 0};
                   1789:   dblPointList *pl;
                   1790:
                   1791:   data[1] = (long) listx;
                   1792:   data[2] = (long) listy;
                   1793:   pl=gtodblList(data,PLOT_PARAMETRIC);
                   1794:   if (!pl) return cgetg(1,t_VEC);
                   1795:   return rectplothrawin(stringrect,drawrect,pl,flags | PLOT_PARAMETRIC,output);
                   1796: }
                   1797:
                   1798: GEN
                   1799: plothraw(GEN listx, GEN listy, long flags)
                   1800: {
                   1801:   flags = (flags > 1 ? flags : (flags ? 0: PLOT_POINTS));
                   1802:   return plothraw0(STRINGRECT, DRAWRECT, listx, listy, flags);
                   1803: }
                   1804:
                   1805: GEN
                   1806: ploth(entree *ep, GEN a, GEN b, char *ch, long prec,long flags,long numpoints)
                   1807: {
                   1808:   return ploth0(STRINGRECT, DRAWRECT, ep,a,b,ch,prec,flags,numpoints);
                   1809: }
                   1810:
                   1811: GEN
                   1812: ploth2(entree *ep, GEN a, GEN b, char *ch, long prec)
                   1813: {
                   1814:   return ploth0(STRINGRECT, DRAWRECT, ep,a,b,ch,prec,PLOT_PARAMETRIC,0);
                   1815: }
                   1816:
                   1817: GEN
                   1818: plothmult(entree *ep, GEN a, GEN b, char *ch, long prec)
                   1819: {
                   1820:   return ploth0(STRINGRECT, DRAWRECT, ep,a,b,ch,prec,0,0);
                   1821: }
                   1822:
                   1823: GEN
                   1824: postplothraw(GEN listx, GEN listy, long flags)
                   1825: {
                   1826:   flags=(flags)? 0: PLOT_POINTS;
                   1827:   return plothraw0(STRINGRECT, DRAWRECT, listx, listy, flags|PLOT_POSTSCRIPT);
                   1828: }
                   1829:
                   1830: GEN
                   1831: postploth(entree *ep, GEN a, GEN b, char *ch, long prec,long flags,
                   1832:            long numpoints)
                   1833: {
                   1834:   return ploth0(STRINGRECT,DRAWRECT,ep,a,b,ch,prec,flags|PLOT_POSTSCRIPT,
                   1835:                 numpoints);
                   1836: }
                   1837:
                   1838: GEN
                   1839: postploth2(entree *ep, GEN a, GEN b, char *ch, long prec,
                   1840:            long numpoints)
                   1841: {
                   1842:   return ploth0(STRINGRECT,DRAWRECT,ep,a,b,ch,prec,
                   1843:                PLOT_PARAMETRIC|PLOT_POSTSCRIPT,numpoints);
                   1844: }
                   1845:
                   1846: GEN
                   1847: plothsizes()
                   1848: {
                   1849:   return plothsizes_flag(0);
                   1850: }
                   1851:
                   1852: GEN
                   1853: plothsizes_flag(long flag)
                   1854: {
                   1855:   GEN vect = cgetg(1+6,t_VEC);
                   1856:
                   1857:   PARI_get_plot(0);
                   1858:   vect[1] = lstoi(w_width);
                   1859:   vect[2] = lstoi(w_height);
                   1860:   if (flag) {
                   1861:     vect[3] = (long)dbltor(h_unit*1.0/w_width);
                   1862:     vect[4] = (long)dbltor(v_unit*1.0/w_height);
                   1863:     vect[5] = (long)dbltor(f_width*1.0/w_width);
                   1864:     vect[6] = (long)dbltor(f_height*1.0/w_height);
                   1865:   } else {
                   1866:     vect[3] = lstoi(h_unit);
                   1867:     vect[4] = lstoi(v_unit);
                   1868:     vect[5] = lstoi(f_width);
                   1869:     vect[6] = lstoi(f_height);
                   1870:   }
                   1871:   return vect;
                   1872: }
                   1873:
                   1874: /*************************************************************************/
                   1875: /*                                                                       */
                   1876: /*                         POSTSCRIPT OUTPUT                             */
                   1877: /*                                                                       */
                   1878: /*************************************************************************/
                   1879:
                   1880: typedef struct spoint {
                   1881:   int x,y; } SPoint;
                   1882: typedef struct ssegment {
                   1883:   int x1,y1,x2,y2; } SSegment;
                   1884: typedef struct srectangle {
                   1885:   int x,y,width,height; } SRectangle;
                   1886:
                   1887: static void ps_point(FILE *psfile, int x, int y);
                   1888: static void ps_line(FILE *psfile, int x1, int y1, int x2, int y2);
                   1889: static void ps_rect(FILE *psfile, int x1, int y1, int x2, int y2);
                   1890: static void ps_string(FILE *psfile, int x, int y, char *c, long dir);
                   1891:
                   1892: #undef ISCR
                   1893: #undef JSCR
                   1894: #define ISCR 1120 /* 1400 en haute resolution */
                   1895: #define JSCR 800  /* 1120 en haute resolution */
                   1896:
                   1897: static void
                   1898: PARI_get_psplot()
                   1899: {
                   1900:   pari_psplot.height = JSCR - 60;
                   1901:   pari_psplot.width  = ISCR - 40;
                   1902:   pari_psplot.fheight = 15;
                   1903:   pari_psplot.fwidth = 6;
                   1904:   pari_psplot.hunit = 5;
                   1905:   pari_psplot.vunit = 5;
                   1906: }
                   1907:
                   1908: static void
                   1909: gendraw(GEN list, long ps, long flag)
                   1910: {
                   1911:   long i,n,ne,*w,*x,*y;
                   1912:   GEN x0,y0,win;
                   1913:
                   1914:   if (typ(list) != t_VEC) err(talker,"not a vector in rectdraw");
                   1915:   n = lg(list)-1;
                   1916:   if (n%3) err(talker,"incorrect number of components in rectdraw");
                   1917:   n = n/3; if (!n) return;
                   1918:   w = (long*)gpmalloc(n*sizeof(long));
                   1919:   x = (long*)gpmalloc(n*sizeof(long));
                   1920:   y = (long*)gpmalloc(n*sizeof(long));
                   1921:   if (flag)
                   1922:     PARI_get_plot(0);
                   1923:   for (i=0; i<n; i++)
                   1924:   {
                   1925:     win=(GEN)list[3*i+1]; x0=(GEN)list[3*i+2]; y0=(GEN)list[3*i+3];
                   1926:     if (typ(win)!=t_INT || (!flag && (typ(x0)!=t_INT || typ(y0)!= t_INT)))
                   1927:       err(talker, "not an integer type in rectdraw");
                   1928:     if (flag) {
                   1929:       double xd = gtodouble(x0), yd = gtodouble(y0);
                   1930:       long xi, yi;
                   1931:
                   1932:       xi = w_width - 1;  yi = w_height - 1;
                   1933:       xi = (long)(xd*xi + 0.5);
                   1934:       yi = (long)(yd*yi + 0.5);
                   1935:       x[i] = xi; y[i] = yi;
                   1936:     } else {
                   1937:       x[i]=itos(x0); y[i]=itos(y0);
                   1938:     }
                   1939:     ne=itos(win); check_rect(ne);
                   1940:     w[i]=ne;
                   1941:   }
                   1942:   if (ps) postdraw00(w,x,y,n,flag); else rectdraw0(w,x,y,n, 1);
                   1943:   free(x); free(y); free(w);
                   1944: }
                   1945:
                   1946: void
                   1947: postdraw(GEN list) { gendraw(list, 1, 0); }
                   1948:
                   1949: void
                   1950: rectdraw(GEN list) { gendraw(list, 0, 0); }
                   1951:
                   1952: void
                   1953: postdraw_flag(GEN list, long flag) { gendraw(list, 1, flag); }
                   1954:
                   1955: void
                   1956: rectdraw_flag(GEN list, long flag) { gendraw(list, 0, flag); }
                   1957:
                   1958: static char*
                   1959: zmalloc(size_t x)
                   1960: {
                   1961:   return x? gpmalloc(x): NULL;
                   1962: }
                   1963:
                   1964: void
                   1965: postdraw0(long *w, long *x, long *y, long lw)
                   1966: {
                   1967:   postdraw00(w, x, y, lw, 0);
                   1968: }
                   1969:
                   1970: void
                   1971: postdraw00(long *w, long *x, long *y, long lw, long scale)
                   1972: {
                   1973:   double *ptx,*pty;
                   1974:   long *numpoints,*numtexts,*xtexts,*ytexts,*dirtexts;
                   1975:   RectObj *p1;
                   1976:   PariRect *e;
                   1977:   long i,j,x0,y0;
                   1978:   long a,b,c,d,nd[ROt_MAX+1];
                   1979:   char **texts;
                   1980:   FILE *psfile;
                   1981:   double xscale = 0.65, yscale = 0.65;
                   1982:   long fontsize = 16, xtick = 5, ytick = 5;
                   1983:
                   1984:   SPoint *points, **lines, *SLine;
                   1985:   SSegment *seg;
                   1986:   SRectangle *rect, SRec;
                   1987:
                   1988:   if (scale) {
                   1989:     double postxsize, postysize;
                   1990:
                   1991:     PARI_get_psplot();
                   1992:     postxsize = pari_psplot.width;
                   1993:     postysize = pari_psplot.height;
                   1994:     PARI_get_plot(0);
                   1995:     xscale *= postxsize * 1.0/w_width;
                   1996:     fontsize = (long) (fontsize/(postxsize * 1.0/w_width));
                   1997:     yscale *= postysize * 1.0/w_height;
                   1998:     xtick = h_unit;  ytick = v_unit;
                   1999:   }
                   2000:   psfile = fopen(current_psfile, "a");
                   2001:   if (!psfile)
                   2002:     err(openfiler,"postscript",current_psfile);
                   2003:
                   2004:   for (i=0; i<=ROt_MAX; i++) nd[i]=0;
                   2005:
                   2006:   for (i=0; i<lw; i++)
                   2007:   {
                   2008:     e = check_rect_init(w[i]); p1=RHead(e);
                   2009:     while (p1)
                   2010:     {
                   2011:       if (RoType(p1) != ROt_MP) nd[RoType(p1)]++;
                   2012:       else nd[ROt_PT]+=RoMPcnt(p1);
                   2013:       p1=RoNext(p1);
                   2014:     }
                   2015:   }
                   2016:   points=(SPoint*) zmalloc(nd[ROt_PT]*sizeof(SPoint));
                   2017:   seg=(SSegment*) zmalloc(nd[ROt_LN]*sizeof(SSegment));
                   2018:   rect=(SRectangle*) zmalloc(nd[ROt_BX]*sizeof(SRectangle));
                   2019:   lines=(SPoint**) zmalloc(nd[ROt_ML]*sizeof(SPoint*));
                   2020:   numpoints=(long*) zmalloc(nd[ROt_ML]*sizeof(long));
                   2021:   texts=(char**) zmalloc(nd[ROt_ST]*sizeof(char*));
                   2022:   numtexts=(long*) zmalloc(nd[ROt_ST]*sizeof(long));
                   2023:   xtexts = (long*) zmalloc(nd[ROt_ST]*sizeof(long));
                   2024:   ytexts = (long*) zmalloc(nd[ROt_ST]*sizeof(long));
                   2025:   dirtexts = (long*) zmalloc(nd[ROt_ST]*sizeof(long));
                   2026:   for (i=0; i<=ROt_MAX; i++) nd[i]=0;
                   2027:
                   2028:   for (i=0; i<lw; i++)
                   2029:   {
                   2030:     e=rectgraph[w[i]]; p1=RHead(e); x0=x[i]; y0=y[i];
                   2031:     while (p1)
                   2032:     {
                   2033:       switch(RoType(p1))
                   2034:       {
                   2035:        case ROt_PT:
                   2036:          points[nd[ROt_PT]].x = DTOL(RoPTx(p1)+x0);
                   2037:          points[nd[ROt_PT]].y = DTOL(RoPTy(p1)+y0);
                   2038:          nd[ROt_PT]++; break;
                   2039:        case ROt_LN:
                   2040:          seg[nd[ROt_LN]].x1 = DTOL(RoLNx1(p1)+x0);
                   2041:          seg[nd[ROt_LN]].y1 = DTOL(RoLNy1(p1)+y0);
                   2042:          seg[nd[ROt_LN]].x2 = DTOL(RoLNx2(p1)+x0);
                   2043:          seg[nd[ROt_LN]].y2 = DTOL(RoLNy2(p1)+y0);
                   2044:          nd[ROt_LN]++; break;
                   2045:        case ROt_BX:
                   2046:          a=rect[nd[ROt_BX]].x = DTOL(RoBXx1(p1)+x0);
                   2047:          b=rect[nd[ROt_BX]].y = DTOL(RoBXy1(p1)+y0);
                   2048:          rect[nd[ROt_BX]].width = DTOL(RoBXx2(p1)+x0-a);
                   2049:          rect[nd[ROt_BX]].height = DTOL(RoBXy2(p1)+y0-b);
                   2050:          nd[ROt_BX]++; break;
                   2051:        case ROt_MP:
                   2052:          ptx = RoMPxs(p1); pty = RoMPys(p1);
                   2053:          for (j=0; j<RoMPcnt(p1); j++)
                   2054:          {
                   2055:            points[nd[ROt_PT]+j].x = DTOL(ptx[j]+x0);
                   2056:            points[nd[ROt_PT]+j].y = DTOL(pty[j]+y0);
                   2057:          }
                   2058:          nd[ROt_PT]+=RoMPcnt(p1); break;
                   2059:        case ROt_ML:
                   2060:          ptx=RoMLxs(p1); pty=RoMLys(p1);
                   2061:          numpoints[nd[ROt_ML]]=RoMLcnt(p1);
                   2062:          lines[nd[ROt_ML]]=(SPoint*)gpmalloc(RoMLcnt(p1)*sizeof(SPoint));
                   2063:          for (j=0; j<RoMLcnt(p1); j++)
                   2064:          {
                   2065:            lines[nd[ROt_ML]][j].x = DTOL(ptx[j]+x0);
                   2066:            lines[nd[ROt_ML]][j].y = DTOL(pty[j]+y0);
                   2067:          }
                   2068:          nd[ROt_ML]++; break;
                   2069:        case ROt_ST:
                   2070:          texts[nd[ROt_ST]] = RoSTs(p1);
                   2071:          numtexts[nd[ROt_ST]] = RoSTl(p1);
                   2072:          xtexts[nd[ROt_ST]] = DTOL(RoSTx(p1)+x0);
                   2073:          ytexts[nd[ROt_ST]] = DTOL(RoSTy(p1)+y0);
                   2074:          dirtexts[nd[ROt_ST]] = RoSTdir(p1);
                   2075:          nd[ROt_ST]++; break;
                   2076:        default: break;
                   2077:       }
                   2078:       p1=RoNext(p1);
                   2079:     }
                   2080:   }
                   2081:   /* Definitions taken from post terminal of Gnuplot. */
                   2082:   fprintf(psfile,"%%!\n50 50 translate\n/Times-Roman findfont %ld scalefont setfont\n%g %g scale\n", fontsize, yscale,xscale);
                   2083:   fprintf(psfile,"/Lshow { moveto 90 rotate show -90 rotate } def\n/Rshow { 3 -1 roll dup 4 1 roll stringwidth pop sub Lshow } def\n/Cshow { 3 -1 roll dup 4 1 roll stringwidth pop 2 div sub Lshow } def\n");
                   2084:   fprintf(psfile,"/Xgap %ld def\n/Ygap %ld def\n", xtick, ytick);
                   2085:   fprintf(psfile,"/Bbox { gsave newpath 0 0 moveto true charpath pathbbox grestore } def\n");
                   2086:   fprintf(psfile,"/Height { Bbox 4 1 roll pop pop pop } def\n");
                   2087:   fprintf(psfile,"/TopAt { 3 -1 roll dup 4 1 roll Height 3 -1 roll add exch } def\n");
                   2088:   fprintf(psfile,"/VCenter { 3 -1 roll dup 4 1 roll Height 2 div 3 -1 roll add exch } def\n");
                   2089:   fprintf(psfile,"/Tgap { exch Ygap add exch } def\n");
                   2090:   fprintf(psfile,"/Bgap { exch Ygap sub exch } def\n");
                   2091:   fprintf(psfile,"/Lgap { Xgap add } def\n");
                   2092:   fprintf(psfile,"/Rgap { Xgap sub } def\n");
                   2093:
                   2094:   for (i=0; i<nd[ROt_PT]; i++)
                   2095:     ps_point(psfile,points[i].x,points[i].y);
                   2096:   for (i=0; i<nd[ROt_LN]; i++)
                   2097:     ps_line(psfile,seg[i].x1,seg[i].y1,seg[i].x2,seg[i].y2);
                   2098:   for (i=0; i<nd[ROt_BX]; i++)
                   2099:   {
                   2100:     SRec=rect[i]; a=SRec.x; b=SRec.y; c=a+SRec.width;
                   2101:     d=b+SRec.height; ps_rect(psfile,a,b,c,d);
                   2102:   }
                   2103:   for (i=0; i<nd[ROt_ML]; i++)
                   2104:   {
                   2105:     SLine=lines[i];
                   2106:     for (j=0; j<numpoints[i]; j++)
                   2107:     {
                   2108:       if (!j) fprintf(psfile,"%d %d moveto\n",SLine[0].y,SLine[0].x);
                   2109:       else fprintf(psfile,"%d %d lineto\n",SLine[j].y,SLine[j].x);
                   2110:     }
                   2111:   }
                   2112:   for (i=0; i<nd[ROt_ST]; i++)
                   2113:     ps_string(psfile,xtexts[i],ytexts[i],texts[i], dirtexts[i]);
                   2114:   fprintf(psfile,"stroke showpage\n"); fclose(psfile);
                   2115: #define xfree(pointer) if (pointer) free(pointer)
                   2116:   xfree(points); xfree(seg); xfree(rect); xfree(numpoints);
                   2117:   for (i=0; i<nd[ROt_ML]; i++) xfree(lines[i]);
                   2118:   xfree(lines); xfree(texts); xfree(numtexts); xfree(xtexts); xfree(ytexts);
                   2119: #undef xfree
                   2120: }
                   2121:
                   2122: static void
                   2123: ps_point(FILE *psfile, int x, int y)
                   2124: {
                   2125:   fprintf(psfile,"%d %d moveto\n0 2 rlineto 2 0 rlineto 0 -2 rlineto closepath fill\n",y,x);
                   2126: }
                   2127:
                   2128: static void
                   2129: ps_line(FILE *psfile, int x1, int y1, int x2, int y2)
                   2130: {
                   2131:   fprintf(psfile,"%d %d moveto\n%d %d lineto\n",y1,x1,y2,x2);
                   2132: }
                   2133:
                   2134: static void
                   2135: ps_rect(FILE *psfile, int x1, int y1, int x2, int y2)
                   2136: {
                   2137:   fprintf(psfile,"%d %d moveto\n%d %d lineto\n%d %d lineto\n%d %d lineto\nclosepath\n",y1,x1,y1,x2,y2,x2,y2,x1);
                   2138: }
                   2139:
                   2140: static void
                   2141: ps_string(FILE *psfile, int x, int y, char *s, long dir)
                   2142: {
                   2143:     if (strpbrk(s, "(\\)")) {
                   2144:        fprintf(psfile,"(");
                   2145:        while (*s) {
                   2146:            if ( *s=='(' || *s==')' || *s=='\\' )
                   2147:                fputc('\\', psfile);
                   2148:            fputc(*s, psfile);
                   2149:            s++;
                   2150:        }
                   2151:     } else
                   2152:        fprintf(psfile,"(%s", s);
                   2153:     fprintf(psfile,") %d %d %s%s%s%sshow\n",
                   2154:            y, x,
                   2155:            ((dir & RoSTdirVGAP)
                   2156:             ? ((dir & RoSTdirVPOS_mask) == RoSTdirTOP ? "Tgap " : "Bgap ")
                   2157:             : ""),
                   2158:            ((dir & RoSTdirHGAP)
                   2159:             ? ((dir & RoSTdirHPOS_mask) == RoSTdirRIGHT ? "Rgap " : "Lgap ")
                   2160:             : ""),
                   2161:            ((dir & RoSTdirVPOS_mask) == RoSTdirBOTTOM ? ""
                   2162:             : (dir & RoSTdirVPOS_mask) == RoSTdirTOP ? "TopAt " : "VCenter "),
                   2163:            ((dir & RoSTdirHPOS_mask) == RoSTdirLEFT ? "L"
                   2164:             : ((dir & RoSTdirHPOS_mask) == RoSTdirRIGHT ? "R" : "C")));
                   2165: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>