Subversion Repositories wimsdev

Rev

Rev 1024 | Go to most recent revision | Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
10 reyssat 1
/*    Copyright (C) 1998-2003 XIAO, Gang of Universite de Nice - Sophia Antipolis
2
 *
3
 *  This program is free software; you can redistribute it and/or modify
4
 *  it under the terms of the GNU General Public License as published by
5
 *  the Free Software Foundation; either version 2 of the License, or
6
 *  (at your option) any later version.
7
 *
8
 *  This program is distributed in the hope that it will be useful,
9
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
10
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11
 *  GNU General Public License for more details.
12
 *
13
 *  You should have received a copy of the GNU General Public License
14
 *  along with this program; if not, write to the Free Software
15
 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
16
 */
17
 
18
#include <errno.h>
19
 
20
        /* File opening: with security */
21
FILE *open4read(char *n)
22
{
23
    char *p, *p1, *p2, namebuf[2048];
24
    int t;
25
    FILE *f;
26
    n=find_word_start(n);
27
    if(*n==0) return NULL;
28
    p=getenv("flydraw_filebase");
29
    p1=n+strlen(n)-4;if(p1<n || strcasecmp(p1,".gif")!=0) t=1; else t=0;
30
    if(p!=NULL && *p!=0) {
31
        char pbuf[MAX_LINELEN+1];
32
        snprintf(pbuf,sizeof(pbuf),"%s",p);
33
        p=find_word_start(pbuf); if(strstr(p,"..")!=NULL) return NULL;
34
        if(*n=='/' || strstr(n,"..")!=NULL) return NULL;
35
                /* prohibit unusual file/dir names */
36
        for(p1=p;*p1;p1++)
37
          if(!isalnum(*p1) && !isspace(*p1) && strchr("~_-/.",*p1)==NULL)
38
            return NULL;
39
        for(p1=n;*p1;p1++)
40
          if(!isalnum(*p1) && !isspace(*p1) && strchr("~_-/.",*p1)==NULL)
41
            return NULL;
42
        f=NULL;
43
        for(p1=p; *p1; p1=find_word_start(p2)) {
44
            p2=find_word_end(p1);
45
            if(*p2) *p2++=0;
46
            snprintf(namebuf,sizeof(namebuf),"%s/%s",p1,n);
47
            f=fopen(namebuf,"r"); if(f!=NULL) goto imgtype;
48
        }
49
        p1=getenv("w_wims_session");
50
        if(p1!=NULL && strncmp(n,"insert",6)==0) {
51
            snprintf(namebuf,sizeof(namebuf),"../s2/%s/%s",p1,n);
52
            f=fopen(namebuf,"r");
53
        }
54
    }
55
    else {
56
        snprintf(namebuf,sizeof(namebuf),"%s",n);
57
        f=fopen(namebuf,"r");
58
    }
59
    imgtype:
60
    if(t && f!=NULL) {
61
        char tbuf[1024],sbuf[4096];
62
        fclose(f); f=NULL;
63
        p1=getenv("TMPDIR"); if(p1==NULL || *p1==0) p1=".";
64
        snprintf(tbuf,sizeof(tbuf),"%s/drawfile_.gif",p1);
65
        snprintf(sbuf,sizeof(sbuf),"convert %s %s",namebuf,tbuf);
66
        system(sbuf); f=fopen(tbuf,"r");       
67
    }
68
    return f;
69
}
70
 
71
        /* Does nothing; just a comment. */
72
void obj_comment(objparm *pm)
73
{
74
    return;
75
}
76
 
77
        /* define image size */
78
void obj_size(objparm *pm)
79
{
80
    sizex=rint(pm->pd[0]); sizey=rint(pm->pd[1]);
81
    if(sizex<0 || sizey<0 || sizex>MAX_SIZE || sizey>MAX_SIZE) {
82
        error("bad_size"); return;
83
    }
84
    if(image!=NULL) {
85
        error("size_already_defined"); return;
86
    }
87
    image=gdImageCreate(sizex,sizey);
88
    if(image==NULL) error("image_creation_failure");
89
    else {
90
        color_white=gdImageColorAllocate(image,255,255,255);
91
        color_black=gdImageColorAllocate(image,0,0,0);
92
        color_bounder=gdImageColorAllocate(image,1,2,3);
93
    }
94
}
95
 
96
        /* new image */
97
void obj_new(objparm *pm)
98
{
99
    if(image) {
100
        gdImageDestroy(image);image=NULL;
101
    }
102
    if(pm->pcnt>=2) obj_size(pm);
103
    else sizex=sizey=0;
104
    saved=0;
105
}
106
 
107
        /* new image */
108
void obj_existing(objparm *pm)
109
{
110
    FILE *inf;
111
    char *pp;
112
 
113
    if(image) {
114
        gdImageDestroy(image);image=NULL;
115
    }
116
    pp=find_word_start(pm->str);*find_word_end(pp)=0;
117
    inf=open4read(pp);
118
    if(inf==NULL) {
119
        error("file_not_exist"); return;
120
    }
121
    image=gdImageCreateFromGif(inf); fclose(inf);
122
    if(image==NULL) {
123
        error("bad_gif"); return;
124
    }
125
    sizex=image->sx; sizey=image->sy;
126
    saved=0;
127
}
128
 
129
        /* solid line */
130
void obj_line(objparm *pm)
131
{
132
    scale(pm->pd,pm->p,2);
133
    gdImageLine(image,pm->p[0],pm->p[1],pm->p[2],pm->p[3],pm->color[0]);
134
}
135
 
136
        /* Arrow */
137
void obj_arrow(objparm *pm)
138
{
139
    int l,ii[6],xx,yy;
140
    double dx,dy,length,dd[6];
141
    scale(pm->pd,pm->p,2);
142
    xx=ii[0]=pm->p[2];yy=ii[1]=pm->p[3];
143
    l=pm->pd[4];if(l<0) l=0; if(l>200) l=200;
144
    scale2(pm->pd[0]-pm->pd[2],pm->pd[1]-pm->pd[3],&dx,&dy);
145
    length=sqrt(dx*dx+dy*dy);
146
    if(length<3 || l<5) goto stem;
147
    dd[0]=l*dx/length; dd[1]=l*dy/length;
148
    #define fat 0.27
149
    dd[2]=dd[0]+dd[1]*fat; dd[3]=dd[1]-dd[0]*fat;
150
    dd[4]=dd[0]-dd[1]*fat; dd[5]=dd[1]+dd[0]*fat;
151
    ii[2]=rint(dd[2])+ii[0]; ii[3]=rint(dd[3])+ii[1];
152
    ii[4]=rint(dd[4])+ii[0]; ii[5]=rint(dd[5])+ii[1];
153
    gdImageFilledPolygon(image,(gdPointPtr) ii,3,pm->color[0]);
154
    xx=rint(dd[0])+ii[0];yy=rint(dd[1])+ii[1];
155
    stem: if(pm->fill)
156
      gdImageDashedLine(image,pm->p[0],pm->p[1],xx,yy,pm->color[0]);
157
    else
158
      gdImageLine(image,pm->p[0],pm->p[1],xx,yy,pm->color[0]);
159
 
160
}
161
 
162
        /* horizontal line */
163
void obj_hline(objparm *pm)
164
{
165
    scale(pm->pd,pm->p,1);
166
    if(pm->fill)
167
      gdImageDashedLine(image,0,pm->p[1],sizex,pm->p[1],pm->color[0]);
168
    else
169
      gdImageLine(image,0,pm->p[1],sizex,pm->p[1],pm->color[0]);
170
}
171
 
172
        /* vertical line */
173
void obj_vline(objparm *pm)
174
{
175
    scale(pm->pd,pm->p,1);
176
    if(pm->fill)
177
      gdImageDashedLine(image,pm->p[0],0,pm->p[0],sizey,pm->color[0]);
178
    else
179
      gdImageLine(image,pm->p[0],0,pm->p[0],sizey,pm->color[0]);
180
}
181
 
182
        /* dashed line */
183
void obj_dline(objparm *pm)
184
{
185
    scale(pm->pd,pm->p,2);
186
    gdImageDashedLine(image,pm->p[0],pm->p[1],pm->p[2],pm->p[3],
187
                      pm->color[0]);
188
}
189
 
190
        /* parallel lines.
191
         * x1,y1,x2,y2,xv,yv,n,color */
192
void obj_parallel(objparm *pm)
193
{
194
    int i, n, xi,yi;
195
    double xv,yv;
196
    n=pm->pd[6]; if(n<0) return; if(n>256) n=256;
197
    scale(pm->pd,pm->p,2);
198
    scale2(pm->pd[4],pm->pd[5],&xv,&yv);
199
    for(i=0;i<n;i++) {
200
        xi=rint(i*xv); yi=rint(i*yv);
201
        gdImageLine(image,pm->p[0]+xi,pm->p[1]+yi,pm->p[2]+xi,pm->p[3]+yi,
202
                    pm->color[0]);
203
    }
204
}
205
 
206
        /* rectangle */
207
void obj_rect(objparm *pm)
208
{
209
    int x1,y1,x2,y2;
210
    scale(pm->pd,pm->p,2);
211
    x1=min(pm->p[0],pm->p[2]); x2=max(pm->p[0],pm->p[2]);
212
    y1=min(pm->p[1],pm->p[3]); y2=max(pm->p[1],pm->p[3]);
213
    if(pm->fill)
214
      gdImageFilledRectangle(image,x1,y1,x2,y2,pm->color[0]);
215
    else
216
      gdImageRectangle(image,x1,y1,x2,y2,pm->color[0]);
217
}
218
 
219
        /* square */
220
void obj_square(objparm *pm)
221
{
222
    int w,h;
223
    scale(pm->pd,pm->p,1);
224
    w=rint(pm->pd[2]); h=rint(pm->pd[2]);
225
    if(pm->fill)
226
      gdImageFilledRectangle(image,pm->p[0],pm->p[1],
227
                     pm->p[0]+w,pm->p[1]+h,pm->color[0]);
228
    else
229
      gdImageRectangle(image,pm->p[0],pm->p[1],
230
                     pm->p[0]+w,pm->p[1]+h,pm->color[0]);
231
}
232
 
233
        /* triangle */
234
void obj_triangle(objparm *pm)
235
{
236
    scale(pm->pd,pm->p,3);
237
    if(pm->fill)
238
      gdImageFilledPolygon(image,(gdPointPtr) pm->p,3,pm->color[0]);
239
    else
240
      gdImagePolygon(image,(gdPointPtr) pm->p,3,pm->color[0]);
241
}
242
 
243
        /* polygon */
244
void obj_poly(objparm *pm)
245
{
246
    int cnt;
247
    cnt=(pm->pcnt)/2;
248
    scale(pm->pd,pm->p,cnt);
249
    if(pm->fill)
250
      gdImageFilledPolygon(image,(gdPointPtr) pm->p,cnt,pm->color[0]);
251
    else
252
      gdImagePolygon(image,(gdPointPtr) pm->p,cnt,pm->color[0]);
253
}
254
 
255
        /* rays */
256
void obj_rays(objparm *pm)
257
{
258
    int i, n;
259
    n=(pm->pcnt)/2;
260
    scale(pm->pd,pm->p,n);
261
    for(i=2;i<2*n;i+=2)
262
      gdImageLine(image,pm->p[0],pm->p[1],pm->p[i],pm->p[i+1],pm->color[0]);
263
}
264
 
265
        /* segments */
266
void obj_lines(objparm *pm)
267
{
268
    int i, n;
269
    n=(pm->pcnt)/2;
270
    scale(pm->pd,pm->p,n);
271
    for(i=2;i<2*n;i+=2)
272
      gdImageLine(image,pm->p[i-2],pm->p[i-1],pm->p[i],pm->p[i+1],pm->color[0]);
273
}
274
 
275
        /* segments */
276
void obj_dlines(objparm *pm)
277
{
278
    int i, n;
279
    n=(pm->pcnt)/2;
280
    scale(pm->pd,pm->p,n);
281
    for(i=2;i<2*n;i+=2)
282
      gdImageDashedLine(image,pm->p[i-2],pm->p[i-1],pm->p[i],pm->p[i+1],pm->color[0]);
283
}
284
 
285
        /* points */
286
void obj_points(objparm *pm)
287
{
288
    int i, n;
289
    n=(pm->pcnt)/2;
290
    scale(pm->pd,pm->p,n);
291
    for(i=0;i<2*n;i+=2)
292
      gdImageSetPixel(image,pm->p[i],pm->p[i+1],pm->color[0]);
293
}
294
 
295
        /* lattice.
296
         * x0,y0,xv1,yv1,xv2,yv2,n1,n2,color */
297
void obj_lattice(objparm *pm)
298
{
299
    int n1,n2,i1,i2,xi1,yi1,xi2,yi2;
300
    double xv1,xv2,yv1,yv2;
301
    n1=pm->pd[6];n2=pm->pd[7]; if(n1<0 || n2<0) return;
302
    if(n1>256) n1=256; if(n2>256) n2=256;
303
    scale(pm->pd,pm->p,1);
304
    scale2(pm->pd[2],pm->pd[3],&xv1,&yv1);
305
    scale2(pm->pd[4],pm->pd[5],&xv2,&yv2);
306
    for(i1=0;i1<n1;i1++) {
307
        xi1=rint(i1*xv1)+pm->p[0]; yi1=rint(i1*yv1)+pm->p[1];
308
        for(i2=0;i2<n2;i2++) {
309
            xi2=i2*xv2+xi1;yi2=i2*yv2+yi1;
310
            gdImageSetPixel(image,xi2,yi2,pm->color[0]);
311
        }
312
    }
313
}
314
 
315
        /* arc */
316
void obj_arc(objparm *pm)
317
{
318
    scale(pm->pd,pm->p,1);
319
    pm->p[2]=rint(pm->pd[2]*xscale); pm->p[3]=rint(pm->pd[3]*yscale);
320
    gdImageArc(image,pm->p[0],pm->p[1],pm->p[2],pm->p[3],
321
               pm->pd[4],pm->pd[5],pm->color[0]);
322
}
323
 
324
        /* Ellipse: centre 0,1, width 2, hight 3, color 4,5,6 */
325
void obj_ellipse(objparm *pm)
326
{
327
    scale(pm->pd,pm->p,1);
328
    pm->p[2]=rint(pm->pd[2]*xscale); pm->p[3]=rint(pm->pd[3]*yscale);
329
    if(pm->fill) {
330
        gdImageArc(image,pm->p[0],pm->p[1],pm->p[2],pm->p[3],0,360,
331
                   color_bounder);
332
        gdImageFillToBorder(image,pm->p[0],pm->p[1],
333
                            color_bounder,pm->color[0]);
334
    }
335
    gdImageArc(image,pm->p[0],pm->p[1],pm->p[2],pm->p[3],0,360,pm->color[0]);
336
}
337
 
338
        /* Circle */
339
void obj_circle(objparm *pm)
340
{
341
    scale(pm->pd,pm->p,1);
342
    pm->p[2]=rint(pm->pd[2]); pm->p[3]=rint(pm->pd[2]);
343
    if(pm->fill) {
344
        gdImageArc(image,pm->p[0],pm->p[1],pm->p[2],pm->p[3],0,360,
345
                   color_bounder);
346
        gdImageFillToBorder(image,pm->p[0],pm->p[1],
347
                            color_bounder,pm->color[0]);
348
    }
349
    gdImageArc(image,pm->p[0],pm->p[1],pm->p[2],pm->p[3],0,360,pm->color[0]);
350
}
351
 
352
        /* flood fill */
353
void obj_fill(objparm *pm)
354
{
355
    scale(pm->pd,pm->p,1);
356
    gdImageFill(image,pm->p[0],pm->p[1],pm->color[0]);
357
}
358
 
359
        /* flood fill to border*/
360
void obj_fillb(objparm *pm)
361
{
362
    scale(pm->pd,pm->p,1);
363
    gdImageFillToBorder(image,pm->p[0],pm->p[1],pm->color[0],pm->color[1]);
364
}
365
 
366
gdImagePtr himg;
367
 
368
int makehatchimage(int x, int y, int px, int py, int col)
369
{
370
    int c1,c2,r,g,b;
371
    gdImagePtr saveimg;
372
    himg=gdImageCreate(x,y);
373
    c1=gdImageGetPixel(image,px,py);
374
    r=gdImageRed(image,c1); g=gdImageGreen(image,c1); b=gdImageBlue(image,c1);
375
    if(r>=255) r--; else r++; if(g>=255) g--; else g++; if(b>=255) b--; else b++;
376
    c1=gdImageColorAllocate(himg,r,g,b);
377
    r=gdImageRed(image,col); g=gdImageGreen(image,col); b=gdImageBlue(image,col);
378
    c2=gdImageColorAllocate(himg,r,g,b);
379
    if(width>1) {
380
        savew=-1; saveimg=image;
381
        image=himg; c2=widthcolor(width,c2); image=saveimg;
382
        c2=gdBrushed; savew=-1;
383
    }
384
    return c2;
385
}
386
 
387
        /* flood fill with hatching */
388
void obj_hatchfill(objparm *pm)
389
{
390
    int nx,ny,ax,ay, dir, c;
391
    scale(pm->pd,pm->p,1);
392
    nx=pm->pd[2]; ny=pm->pd[3]; ax=abs(nx); ay=abs(ny);
393
    if(nx==0 && ny==0) {error("bad displacement vector"); return;}
394
    if((nx>0 && ny>0) || (nx<0 && ny<0)) dir=1; else dir=-1;
395
    if(ax==0) {ax=100; dir=2;}
396
    if(ay==0) {ay=100; dir=3;}
397
    c=makehatchimage(ax,ay,pm->p[0],pm->p[1],pm->color[0]);
398
    switch(dir) {
399
        case -1: {
400
            gdImageLine(himg,0,ay-1,ax-1,0,c);
401
            if(width>1) {
402
                gdImageLine(himg,-ax,ay-1,-1,0,c);
403
                gdImageLine(himg,ax,ay-1,2*ax-1,0,c);
404
                gdImageLine(himg,0,-1,ax-1,-ay,c);
405
                gdImageLine(himg,0,2*ay-1,ax-1,ay,c);
406
            }
407
            break;
408
        }
409
        case 1: {
410
            gdImageLine(himg,0,0,ax-1,ay-1,c);
411
            if(width>1) {
412
                gdImageLine(himg,-ax,0,-1,ay-1,c);
413
                gdImageLine(himg,ax,0,2*ax-1,ay-1,c);
414
                gdImageLine(himg,0,-ay,ax-1,-1,c);
415
                gdImageLine(himg,0,ay,ax-1,2*ay-1,c);
416
            }
417
            break;
418
        }
419
        case 2: gdImageLine(himg,0,ay/2,ax-1,ay/2,c); break;
420
        case 3: gdImageLine(himg,ax/2,0,ax/2,ay-1,c); break;
421
    }
422
    gdImageSetTile(image,himg);
423
    gdImageFill(image,pm->p[0],pm->p[1],gdTiled);
424
    gdImageDestroy(himg);
425
    if(tiled) gdImageSetTile(image,tileimg);
426
}
427
 
428
        /* flood fill with grid */
429
void obj_gridfill(objparm *pm)
430
{
431
    int nx,ny, c;
432
    scale(pm->pd,pm->p,1);
433
    nx=pm->pd[2]; ny=pm->pd[3]; nx=abs(nx); ny=abs(ny);
434
    if(nx==0 && ny==0) {error("bad grid size"); return;}
435
    c=makehatchimage(nx,ny,pm->p[0],pm->p[1],pm->color[0]);
436
    gdImageLine(himg,0,ny/2,nx-1,ny/2,c); gdImageLine(himg,nx/2,0,nx/2,ny-1,c);
437
    gdImageSetTile(image,himg);
438
    gdImageFill(image,pm->p[0],pm->p[1],gdTiled);
439
    gdImageDestroy(himg);
440
    if(tiled) gdImageSetTile(image,tileimg);
441
}
442
 
443
        /* flood fill with double hatching */
444
void obj_diafill(objparm *pm)
445
{
446
    int nx,ny, c;
447
    scale(pm->pd,pm->p,1);
448
    nx=pm->pd[2]; ny=pm->pd[3]; nx=abs(nx); ny=abs(ny);
449
    if(nx==0 && ny==0) {error("bad grid size"); return;}
450
    c=makehatchimage(nx,ny,pm->p[0],pm->p[1],pm->color[0]);
451
    gdImageLine(himg,0,0,nx-1,ny-1,c); gdImageLine(himg,0,ny-1,nx-1,0,c);
452
    gdImageSetTile(image,himg);
453
    gdImageFill(image,pm->p[0],pm->p[1],gdTiled);
454
    gdImageDestroy(himg);
455
    if(tiled) gdImageSetTile(image,tileimg);
456
}
457
 
458
        /* flood fill with double hatching */
459
void obj_dotfill(objparm *pm)
460
{
461
    int nx,ny, c;
462
    scale(pm->pd,pm->p,1);
463
    nx=pm->pd[2]; ny=pm->pd[3]; nx=abs(nx); ny=abs(ny);
464
    if(nx==0 && ny==0) {error("bad grid size"); return;}
465
    c=makehatchimage(nx,ny,pm->p[0],pm->p[1],pm->color[0]);
466
    gdImageSetPixel(himg,nx/2,ny/2,c);
467
    gdImageSetTile(image,himg);
468
    gdImageFill(image,pm->p[0],pm->p[1],gdTiled);
469
    gdImageDestroy(himg);
470
    if(tiled) gdImageSetTile(image,tileimg);
471
}
472
 
473
struct {
474
    char *name;
475
    gdFontPtr *fpt;
476
} fonttab[]={
477
      {"tiny",  &gdFontTiny},
478
      {"small", &gdFontSmall},
479
      {"medium",&gdFontMediumBold},
480
      {"large", &gdFontLarge},
481
      {"giant", &gdFontGiant},
482
      {"huge",  &gdFontGiant}
483
};
484
 
485
#define fonttab_no (sizeof(fonttab)/sizeof(fonttab[0]))
486
 
487
        /* string */
488
void obj_string(objparm *pm)
489
{
490
    char *pp, *pe, *p2;
491
    int i;
492
    pp=pm->str; pe=strchr(pp,','); if(pe==NULL) {
493
        error("too_few_parms"); return;
494
    }
495
    *pe++=0; pp=find_word_start(pp); *find_word_end(pp)=0;
496
    pe=find_word_start(pe); strip_trailing_spaces(pe);
497
    if(*pp) {
498
        for(i=0;i<fonttab_no && strcmp(pp,fonttab[i].name)!=0; i++);
499
        if(i>=fonttab_no) i=1;
500
    }
501
    else i=1;
502
    scale(pm->pd,pm->p,1);
503
    if(*pe=='"') {
504
        p2=strchr(pe+1,'"');
505
        if(p2 && *(p2+1)==0) {*p2=0; pe++;}
506
    }
507
    if(pm->fill)
508
      gdImageStringUp(image,*(fonttab[i].fpt),pm->p[0],pm->p[1],pe,
509
                    pm->color[0]);
510
    else
511
      gdImageString(image,*(fonttab[i].fpt),pm->p[0],pm->p[1],pe,
512
                    pm->color[0]);
513
}
514
 
515
        /* point */
516
void obj_point(objparm *pm)
517
{
518
    scale(pm->pd,pm->p,1);
519
    gdImageSetPixel(image,pm->p[0],pm->p[1],pm->color[0]);
520
}
521
 
522
        /* copy an image file */
523
void obj_copy(objparm *pm)
524
{
525
    char *pp;
526
    FILE *inf;
527
    gdImagePtr  insimg;
528
 
529
    pp=find_word_start(pm->str);*find_word_end(pp)=0;
530
    inf=open4read(pp);
531
    if(inf==NULL) {
532
        error("file_not_exist"); return;
533
    }
534
    insimg=gdImageCreateFromGif(inf); fclose(inf);
535
    if(insimg==NULL) {
536
        error("bad_gif"); return;
537
    }
538
    scale(pm->pd,pm->p,1);
539
    if(pm->pd[2]<0 && pm->pd[3]<0 && pm->pd[4]<0 && pm->pd[5]<0)
540
      gdImageCopy(image,insimg,pm->p[0],pm->p[1],0,0,
541
                  insimg->sx,insimg->sy);
542
    else
543
      gdImageCopy(image,insimg,pm->p[0],pm->p[1],pm->pd[2],pm->pd[3],
544
                  pm->pd[4]-pm->pd[2],pm->pd[5]-pm->pd[3]);
545
    gdImageDestroy(insimg);
546
}
547
 
548
        /* copy an image file, with resizing */
549
void obj_copyresize(objparm *pm)
550
{
551
    char *pp;
552
    FILE *inf;
553
    gdImagePtr  insimg;
554
 
555
    pp=find_word_start(pm->str);*find_word_end(pp)=0;
556
    inf=open4read(pp);
557
    if(inf==NULL) {
558
        error("file_not_found"); return;
559
    }
560
    insimg=gdImageCreateFromGif(inf); fclose(inf);
561
    if(insimg==NULL) {
562
        error("bad_gif"); return;
563
    }
564
    scale(pm->pd+4,pm->p+4,2);
565
    if(pm->pd[0]<0 && pm->pd[1]<0 && pm->pd[2]<0 && pm->pd[3]<0)
566
      gdImageCopyResized(image,insimg,pm->p[4],pm->p[5],0,0,
567
                         pm->p[6]-pm->p[4]+1,pm->p[7]-pm->p[5]+1,
568
                         insimg->sx,insimg->sy);
569
    else
570
      gdImageCopyResized(image,insimg,pm->p[4],pm->p[5],pm->pd[0],pm->pd[1],
571
                         pm->p[6]-pm->p[4]+1,pm->p[7]-pm->p[5]+1,
572
                         pm->pd[2]-pm->pd[0]+1,pm->pd[3]-pm->pd[1]+1);
573
    gdImageDestroy(insimg);
574
}
575
 
576
        /* set brush or tile */
577
void obj_setbrush(objparm *pm)
578
{
579
    char *pp;
580
    FILE *inf;
581
    gdImagePtr insimg;
582
 
583
    pp=find_word_start(pm->str); *find_word_end(pp)=0;
584
    inf=open4read(pp); if(inf==NULL) {
585
        error("file_not_found"); return;
586
    }
587
    insimg=gdImageCreateFromGif(inf); fclose(inf);
588
    if(insimg==NULL) {
589
        error("bad_gif"); return;
590
    }
591
    if(pm->fill) {
592
        gdImageSetTile(image,insimg); tiled=1; tileimg=insimg;
593
    }
594
    else {
595
        gdImageSetBrush(image,insimg);brushed=1; brushimg=insimg;
596
    }
597
}
598
 
599
        /* kill brush */
600
void obj_killbrush(objparm *pm)
601
{
602
    if(brushimg) gdImageDestroy(brushimg);
603
    brushed=0; brushimg=NULL;
604
}
605
 
606
        /* kill tile */
607
void obj_killtile(objparm *pm)
608
{
609
    if(tileimg) gdImageDestroy(tileimg);
610
    tiled=0; tileimg=NULL;
611
}
612
 
613
        /* set style */
614
void obj_setstyle(objparm *pm)
615
{
616
    int i,t;
617
    t=pm->pcnt/3; if(t<=0) {
618
        error("too_few_parms"); return;
619
    }
620
    for(i=0;i<t;i++) {
621
        if(pm->pd[3*i]<0 || pm->pd[3*i+1]<0 || pm->pd[3*i+2]<0)
622
          pm->p[i]=gdTransparent;
623
        else
624
          pm->p[i]=getcolor(pm->pd[3*i],pm->pd[3*i+1],pm->pd[3*i+2]);
625
    }
626
 
627
    gdImageSetStyle(image,pm->p,t); styled=1;
628
}
629
 
630
        /* kill style */
631
void obj_killstyle(objparm *pm)
632
{
633
    styled=0;
634
}
635
 
636
        /* set transparent */
637
void obj_transp(objparm *pm)
638
{
639
    gdImageColorTransparent(image,pm->color[0]);
640
}
641
 
642
        /* set interlace */
643
void obj_interlace(objparm *pm)
644
{
645
    gdImageInterlace(image,1);
646
}
647
 
648
        /* set linewidth */
649
void obj_linewidth(objparm *pm)
650
{
651
    if(pm->pd[0]<1 || pm->pd[0]>255) error("bad_parms");
652
    else width=pm->pd[0];
653
}
654
 
655
        /* set x range */
656
void obj_xrange(objparm *pm)
657
{
658
    double dd;
659
    dd=pm->pd[1]-pm->pd[0];
660
    xstart=pm->pd[0]; xscale=sizex/dd;
661
}
662
 
663
        /* set y range */
664
void obj_yrange(objparm *pm)
665
{
666
    double dd;
667
    dd=pm->pd[1]-pm->pd[0];
668
    ystart=pm->pd[1]; yscale=-sizey/dd;
669
}
670
 
671
        /* set x et y range */
672
void obj_range(objparm *pm)
673
{
674
    double d1,d2;
675
    d1=pm->pd[1]-pm->pd[0]; d2=pm->pd[3]-pm->pd[2];
676
    xstart=pm->pd[0]; xscale=(sizex-1)/d1;
677
    ystart=pm->pd[3]; yscale=-(sizey-1)/d2;
678
}
679
 
680
        /* set t range */
681
void obj_trange(objparm *pm)
682
{
683
    double dd;
684
    dd=pm->pd[1]-pm->pd[0];
685
    tstart=pm->pd[0]; tend=pm->pd[1];
686
    tranged=1;
687
}
688
 
689
        /* set tstep (plotting step) */
690
void obj_tstep(objparm *pm)
691
{
692
    int dd;
693
    dd=pm->pd[0];
694
    if(dd<3) {
695
        error("bad_step"); return;
696
    }
697
    if(dd>2000) dd=2000;
698
    tstep=dd;
699
}
700
 
701
        /* set plotjump (plot jump break threashold) */
702
void obj_plotjump(objparm *pm)
703
{
704
    int dd;
705
    dd=pm->pd[0];
706
    if(dd<3) dd=3; if(dd>MAX_SIZE) dd=MAX_SIZE;
707
    plotjump=dd;
708
}
709
 
710
        /* plot a curve, either parametric or explicit */
711
void obj_plot(objparm *pm)
712
{
713
    int i,j,n,dist,xx,yy,varpos;
714
    char p1[MAX_LINELEN+1], p2[MAX_LINELEN+1];
715
    char *varn, *pp;
716
    double dc[2],t,v;
717
    int ic[2],oc[2];
718
 
719
    n=itemnum(pm->str);
720
    if(n<1) {
721
        error("bad_parms"); return;
722
    }
723
    fnd_item(pm->str,1,p1); fnd_item(pm->str,2,p2);
724
    if(n==1 && !tranged) v=sizex/xscale/tstep;
725
    else v=(tend-tstart)/tstep;
726
    if(n==1) varn="x"; else varn="t";
727
    for(pp=varchr(p1,varn); pp; pp=varchr(pp,varn)) {
728
        string_modify(p1,pp,pp+strlen(varn),EV_T);
729
        pp+=strlen(EV_T);
730
    }
731
    for(pp=varchr(p2,varn); pp; pp=varchr(pp,varn)) {
732
        string_modify(p2,pp,pp+strlen(varn),EV_T);
733
        pp+=strlen(EV_T);
734
    }
735
    varpos=eval_getpos(EV_T);
736
    if(varpos<0) return; /* unknown error */
737
    evalue_compile(p1); evalue_compile(p2);
738
    for(i=j=0;i<=tstep;i++) {
739
        if(n==1) {
740
            if(tranged) t=tstart+i*v; else t=xstart+i*v;
741
            eval_setval(varpos,t); dc[0]=t; dc[1]=evalue(p1);
742
        }
743
        else {
744
            t=tstart+i*v; eval_setval(varpos,t);
745
            dc[0]=evalue(p1); dc[1]=evalue(p2);
746
        }
747
        if(!finite(dc[0]) || !finite(dc[1])) ic[0]=ic[1]=-BOUND;
748
        else scale(dc,ic,1);
749
        if(j==0) {
750
            gdImageSetPixel(image,ic[0],ic[1],pm->color[0]); j++;
751
        }
752
        else {
753
            xx=ic[0]-oc[0]; yy=ic[1]-oc[1];
754
            dist=sqrt(xx*xx+yy*yy);
755
            if(dist>0) {
756
                if(dist>plotjump || dist==1)
757
                  gdImageSetPixel(image,ic[0],ic[1],pm->color[0]);
758
                else
759
                  gdImageLine(image,oc[0],oc[1],ic[0],ic[1],pm->color[0]);
760
 
761
            }
762
        }
763
        memmove(oc,ic,sizeof(oc));
764
    }
765
}
766
 
767
        /* set levelcurve granularity */
768
void obj_levelstep(objparm *pm)
769
{
770
    int dd;
771
    dd=pm->pd[0];
772
    if(dd<1) return; if(dd>16) dd=16;
773
    lstep=dd;
774
}
775
 
776
        /* level curve */
777
void obj_levelcurve(objparm *pm)
778
{
779
    char fn[MAX_LINELEN+1],tc[MAX_LINELEN+1];
780
    int n,i;
781
    double d;
782
    leveldata *ld;
783
 
784
    ld=xmalloc(sizeof(leveldata)+16);
785
    ld->xname="x"; ld->yname="y";
786
    ld->xsize=sizex; ld->ysize=sizey; ld->datacnt=0;
787
    ld->xrange[0]=xstart; ld->xrange[1]=sizex/xscale+xstart;
788
    ld->yrange[0]=sizey/yscale+ystart; ld->yrange[1]=ystart;
789
    ld->grain=lstep;
790
    fnd_item(pm->str,1,fn); ld->fn=fn;
791
    n=itemnum(pm->str);
792
    if(n<=1) {ld->levelcnt=1; ld->levels[0]=0;}
793
    else {
794
        if(n>LEVEL_LIM+1) n=LEVEL_LIM+1;
795
        for(i=0;i<n-1;i++) {
796
            fnd_item(pm->str,i+2,tc);
797
            d=evalue(tc);
798
            if(finite(d)) ld->levels[i]=d; else ld->levels[i]=0;
799
        }
800
        ld->levelcnt=n-1;
801
    }
802
    levelcurve(ld);
803
    for(i=0;i<ld->datacnt;i++) {
804
        gdImageSetPixel(image,ld->xdata[i],ld->ydata[i],pm->color[0]);
805
    }
806
    free(ld);
807
}
808
 
809
        /* set animation step */
810
void obj_animstep(objparm *pm)
811
{
812
    animstep=pm->pd[0];
813
    setvar("animstep",pm->pd[0]);
814
}
815
 
816
        /* Starts a line counting */
817
void obj_linecount(objparm *pm)
818
{
819
    linecnt=pm->pd[0];
820
}
821
 
822
        /* marks end of execution */
823
void obj_end(objparm *pm)
824
{
825
    error("successful_end_of_execution");
826
}
827
 
828
        /* output */
829
void obj_output(objparm *pm)
830
{
831
    char *p, namebuf[1024];
832
    p=find_word_start(pm->str); *find_word_end(p)=0;
833
    snprintf(namebuf,sizeof(namebuf),"%s",imagefilename);
834
    snprintf(imagefilename,sizeof(imagefilename),"%s",p);
835
    output();
836
    snprintf(imagefilename,sizeof(imagefilename),"%s",namebuf);
837
}
838
 
839
        /* Set affine transformation */
840
void obj_affine(objparm *pm)
841
{
842
    int i;
843
    for(i=0;i<4;i++) matrix[i]=pm->pd[i];
844
    transx=pm->pd[4]; transy=pm->pd[5];
845
    transform=1;
846
}
847
 
848
        /* Set affine transformation */
849
void obj_rotation(objparm *pm)
850
{
851
    double r;
852
    r=M_PI*pm->pd[0]/180;
853
    matrix[0]=matrix[3]=cos(r);
854
    matrix[1]=-sin(r); matrix[2]=sin(r);
855
    transform=1;
856
}
857
 
858
        /* Set affine transformation */
859
void obj_linear(objparm *pm)
860
{
861
    int i;
862
    for(i=0;i<4;i++) matrix[i]=pm->pd[i];
863
    transform=1;
864
}
865
 
866
        /* Set affine transformation */
867
void obj_translation(objparm *pm)
868
{
869
    transx=pm->pd[0]; transy=pm->pd[1];
870
}
871
 
872
        /* Set affine transformation */
873
void obj_killaffine(objparm *pm)
874
{
875
    matrix[0]=matrix[3]=1;
876
    matrix[1]=matrix[2]=transx=transy=0;
877
    transform=0;
878
}
879
 
880
        /* Set affine transformation */
881
void obj_killlinear(objparm *pm)
882
{
883
    matrix[0]=matrix[3]=1;
884
    matrix[1]=matrix[2]=0;
885
    transform=0;
886
}
887
 
888
        /* Set affine transformation */
889
void obj_killtranslation(objparm *pm)
890
{
891
    transx=transy=0;
892
}
893
 
894
/***** Les modifs de Jean-Christophe Leger Fev 2006 *****/
895
 
896
/* arguments: un numero de matrice entre 1 et JC_NB_MATRICES, une liste de 4 nombres reels pour la matrice */
897
void obj_setmatrix(objparm *pm)
898
{
899
  int nummatrix = (int) (pm->pd[0]);
900
  if((nummatrix < 1) ||(nummatrix>JC_NB_MATRICES)) {
901
    error("bad_matrix_number");
902
    return;
903
  }
904
  matrices_pavage[nummatrix][0] = pm->pd[1];
905
  matrices_pavage[nummatrix][1] = pm->pd[2];
906
  matrices_pavage[nummatrix][2] = pm->pd[3];
907
  matrices_pavage[nummatrix][3] = pm->pd[4];
908
}
909
 
910
/* arguments: un numero de matrice entre 1 et JC_NB_MATRICES */
911
void obj_resetmatrix(objparm *pm)
912
{
913
  int nummatrix = (int) (pm->pd[0]);
914
  if((nummatrix < 1) ||(nummatrix>JC_NB_MATRICES)) {
915
    error("bad_matrix_number");
916
    return;
917
  }
918
  matrices_pavage[nummatrix][0] = 1;
919
  matrices_pavage[nummatrix][1] = 0;
920
  matrices_pavage[nummatrix][2] = 0;
921
  matrices_pavage[nummatrix][3] = 1;
922
 
923
}
924
/* arguments: un numero de vecteur entre 1 et JC_NB_MATRICES, une liste de 2 nombres reels pour le vecteur */
925
void obj_setvector(objparm *pm)
926
{
927
  int nummatrix = (int) (pm->pd[0]);
928
  if((nummatrix < 1) ||(nummatrix>JC_NB_MATRICES)) {
929
    error("bad_vector_number");
930
    return;
931
  }
932
  vecteurs_pavage[nummatrix][0] = pm->pd[1];
933
  vecteurs_pavage[nummatrix][1] = pm->pd[2];
934
}
935
 
936
/* arguments: un numero de matrice entre 1 et JC_NB_MATRICES */
937
void obj_resetvector(objparm *pm)
938
{
939
  int nummatrix = (int) (pm->pd[0]);
940
  if((nummatrix < 1) ||(nummatrix>JC_NB_MATRICES)) {
941
    error("bad_vector_number");
942
    return;
943
  }
944
  vecteurs_pavage[nummatrix][0] = 0;
945
  vecteurs_pavage[nummatrix][1] = 0;
946
}
947
 
948
/* arguments: un numero de vecteur entre 1 et JC_NB_MATRICES, une liste de 6 nombres reels pour la matrice et le vecteur */
949
void obj_settransform(objparm *pm)
950
{
951
  int nummatrix = (int) (pm->pd[0]);
952
  if((nummatrix < 1) ||(nummatrix>JC_NB_MATRICES)) {
953
    error("bad_vector_number");
954
    return;
955
  }
956
  matrices_pavage[nummatrix][0] = pm->pd[1];
957
  matrices_pavage[nummatrix][1] = pm->pd[2];
958
  matrices_pavage[nummatrix][2] = pm->pd[3];
959
  matrices_pavage[nummatrix][3] = pm->pd[4];
960
  vecteurs_pavage[nummatrix][0] = pm->pd[5];
961
  vecteurs_pavage[nummatrix][1] = pm->pd[6];
962
}
963
 
964
 
965
/* arguments: un numero de matrice entre 1 et JC_NB_MATRICES */
966
void obj_resettransform(objparm *pm)
967
{
968
  int nummatrix = (int) (pm->pd[0]);
969
  if((nummatrix < 1) ||(nummatrix>JC_NB_MATRICES)) {
970
    error("bad_vector_number");
971
    return;
972
  }
973
  vecteurs_pavage[nummatrix][0] = 0;
974
  vecteurs_pavage[nummatrix][1] = 0;
975
  matrices_pavage[nummatrix][0] = 1;
976
  matrices_pavage[nummatrix][1] = 0;
977
  matrices_pavage[nummatrix][2] = 0;
978
  matrices_pavage[nummatrix][3] = 1;
979
}
980
 
981
/* arguments: une liste de 6 nombres reels pour les coordonnees de l'origine et des vecteurs de base */
982
void obj_setparallelogram(objparm *pm)
983
{
984
  int i;
985
  for(i=0;i<6;i++)  parallogram_fonda[i]=pm->pd[i];
986
}
987
 
988
/* arguments :aucun */
989
void obj_resetparallelogram(objparm *pm)
990
{
991
  parallogram_fonda[0]=0;
992
  parallogram_fonda[1]=0;
993
  parallogram_fonda[2]=100;
994
  parallogram_fonda[3]=0;
995
  parallogram_fonda[4]=0;
996
  parallogram_fonda[5]=100;
997
}
998
 
999
/* argument : la liste des numeros des matrices a faire agir, le nom du fichier de l'image a inclure */
1000
void obj_multicopy(objparm *pm)
1001
{
1002
    char *pp,*pe,*cptr;
1003
    FILE *inf;
1004
    gdImagePtr  insimg;
1005
    int i,j;
1006
    int imax,jmax;
1007
    int c; /* la couleur reperee */
1008
    int mat;
1009
    int nummatrices[JC_NB_MATRICES];
1010
    double pt[2]; /* les coordonnees math. du point repere dans le parallelogramme */
1011
    double ptr[2]; /* les coordonnees math. du point transforme */
1012
    int pti[2]; /* les coordonnees img du point a placer sur le canevas */
1013
    int t;
1014
    /* gestion palette de couleur de l'image a inserer */
1015
    int colorMap[gdMaxColors];
1016
    int comptmat=0; /* combien de matrices en tout ? */
1017
 
1018
    for (i=0; (i<gdMaxColors); i++) {
1019
      colorMap[i] = (-1);
1020
    }
1021
 
1022
    /* Gestion des parametres la liste est censee finir avec le nom du fichier */
1023
    t=pm->pcnt-1; /* il faut enlever le nom de fichier ! c'est le nombre de parametres en plus */
1024
    pp=find_word_start(pm->str);
1025
    /* visiblement find_word_start n'arrive pas a trouver le dernier mot dans un contexte ou le nombre de parameters est variable
1026
     * on cherche donc l'emplacement de la derniere virgule:
1027
     * il y en a une car t>0, on retrouve ensuite le debut de mot
1028
     */
1029
    for(pe=pp;*pe!=0;pe++);/* trouve la fin de la chaine */
1030
    if(t>0){
1031
      for(cptr = pe; cptr > pp && *cptr != ','; cptr--);
1032
      pp=find_word_start(cptr+1);
1033
    }
1034
    pe=find_word_end(pp);*pe=0; /* strip junk final */
1035
    //      printf("pp contient %s\n",pp);
1036
 
1037
 
1038
    inf=open4read(pp);
1039
    if(inf==NULL) {
1040
        error("file_not_exist"); return;
1041
    }
1042
    insimg=gdImageCreateFromGif(inf); fclose(inf);
1043
    if(insimg==NULL) {
1044
        error("bad_gif"); return;
1045
    }
1046
 
1047
    /* On recupere les numeros des matrices/vecteurs a faire agir,
1048
     * s'il n'y en a pas, on les fait toutes agir
1049
     */
1050
    for(i=0;i<t && i< JC_NB_MATRICES;i++) {
1051
      if(pm->pd[i]>=1 && pm->pd[i]<=JC_NB_MATRICES){
1052
          nummatrices[comptmat] = pm->pd[i];
1053
          comptmat++;
1054
      }
1055
    }
1056
    if(t<=0){
1057
      for(i=0;i<JC_NB_MATRICES;i++) {
1058
        nummatrices[i] = i+1;
1059
      }
1060
      comptmat=JC_NB_MATRICES;
1061
    }
1062
 
1063
 
1064
    imax = gdImageSX(insimg);
1065
    jmax = gdImageSY(insimg);
1066
 
1067
    for(i=0;i<imax;i++){
1068
      for(j=0;j<jmax;j++){
1069
        int nc;
1070
        c=gdImageGetPixel(insimg,i,j);
1071
        /* Le code suivant est une copie du code dans gdImageCopy  Added 7/24/95: support transparent copies */
1072
        if (gdImageGetTransparent(insimg) != c) {
1073
          /* Have we established a mapping for this color? */
1074
          if (colorMap[c] == (-1)) {
1075
            /* If it's the same image, mapping is trivial, dans notre cas ca n'arrive jamais... */
1076
            if (image == insimg) {
1077
              nc = c;
1078
            } else {
1079
              /* First look for an exact match */
1080
              nc = gdImageColorExact(image,
1081
                                     insimg->red[c], insimg->green[c],
1082
                                     insimg->blue[c]);
1083
            }  
1084
            if (nc == (-1)) {
1085
              /* No, so try to allocate it */
1086
              nc = gdImageColorAllocate(image,
1087
                                        insimg->red[c], insimg->green[c],
1088
                                        insimg->blue[c]);
1089
              /* If we're out of colors, go for the
1090
                 closest color */
1091
              if (nc == (-1)) {
1092
                nc = gdImageColorClosest(image,
1093
                                         insimg->red[c], insimg->green[c],
1094
                                         insimg->blue[c]);
1095
              }
1096
            }
1097
            colorMap[c] = nc;
1098
          }
1099
 
1100
          pt[0]= i*(parallogram_fonda[2])/(imax-1)+(jmax-j)*(parallogram_fonda[4])/(jmax-1)+parallogram_fonda[0];
1101
          pt[1]= i*(parallogram_fonda[3])/(imax-1)+(jmax-j)*(parallogram_fonda[5])/(jmax-1)+parallogram_fonda[1];
1102
          for(mat=0;mat<comptmat;mat++){
1103
            double *matricecourante = matrices_pavage[nummatrices[mat]];
1104
            double *vecteurcourant = vecteurs_pavage[nummatrices[mat]];
1105
            ptr[0] = matricecourante[0]*pt[0]+matricecourante[1]*pt[1]+vecteurcourant[0];
1106
            ptr[1] = matricecourante[2]*pt[0]+matricecourante[3]*pt[1]+vecteurcourant[1];
1107
            scale(ptr,pti,1);
1108
            gdImageSetPixel(image,pti[0],pti[1],colorMap[c]);
1109
          }
1110
        }
1111
      }
1112
    }
1113
    gdImageDestroy(insimg);
1114
}
1115
 
1116
/**** Fin modifs JC Fev 06 ******/
1117
 
1118
        /* get color from value */
1119
int calc_color(char *p, struct objtab *o)
1120
{
1121
    int k, cc[3];
1122
    char buf[MAX_LINELEN+1];
1123
    for(k=0;k<3;k++) {
1124
        fnd_item(p,k+1,buf);
1125
        cc[k]=evalue(buf);
1126
    }
1127
    collapse_item(p,3);
1128
    if(cc[0]==-1 && cc[1]==-1 && cc[2]==-255) {
1129
 
1130
        if(brushed && o->subst&1) return gdBrushed;
1131
        else return color_black;
1132
    }
1133
    if(cc[0]==-1 && cc[1]==-255 && cc[2]==-1) {
1134
        if(styled && o->subst&2)  return gdStyled;
1135
        else return color_black;
1136
    }
1137
    if(cc[0]==-255 && cc[1]==-1 && cc[2]==-1) {
1138
        if(tiled && o->fill_tag==1)  return gdTiled;
1139
        else return color_black;
1140
    }
1141
    return getcolor(cc[0],cc[1],cc[2]);
1142
}
1143
 
1144
        /* Routine to parse parameters */
1145
int parse_parms(char *p,objparm *pm,struct objtab *o)
1146
{
1147
    char buf[MAX_LINELEN+1];
1148
    char *p1, *p2;
1149
    int j,t,c,c1,c2;
1150
 
1151
    c=o->color_pos;c1=c2=0;
1152
    pm->color[0]=pm->color[1]=0;
1153
    if(c>0) c1=c; if(c<0) c2=-c; c=c1+c2;
1154
    t=itemnum(p);if(t<o->required_parms+3*c) return -1;
1155
    if(c1>0 && t>o->required_parms+3*c) t=o->required_parms+3*c;
1156
    pm->pcnt=t-3*c;
1157
    if(pm->pcnt>MAX_PARMS) pm->pcnt=MAX_PARMS;
1158
    if(c2>0) {
1159
        for(j=0;j<2 && j<c2; j++) pm->color[j]=calc_color(p,o);
1160
    }
1161
    snprintf(buf,sizeof(buf),"%s",p);
1162
    for(j=0, p1=buf; j<pm->pcnt; j++, p1=p2) {
1163
        p2=find_item_end(p1); if(*p2) *p2++=0;
1164
        p1=find_word_start(p1);
1165
        if(*p1) pm->pd[j]=evalue(p1); else pm->pd[j]=0;
1166
        if(!finite(pm->pd[j])) {
1167
            if(j<o->required_parms) return -1;
1168
            else {pm->pd[j]=0;break;}
1169
        }
1170
    }
1171
    collapse_item(p,o->required_parms);
1172
    if(c1>0) {
1173
        for(j=0;j<c1 && j<2; j++) pm->color[j]=calc_color(p,o);
1174
    }
1175
    if(width>1 && o->subst&1 && pm->color[0]!=gdBrushed
1176
       && pm->color[0]!=gdStyled && pm->color[0]!=gdTiled) {
1177
        pm->color[1]=pm->color[0];
1178
        pm->color[0]=widthcolor(width,pm->color[0]);
1179
    }
1180
    pm->fill=o->fill_tag;
1181
    strcpy(pm->str,p); return 0;
1182
}
1183
 
1184
        /* Execute a command. Returns 0 if OK. */
1185
int obj_main(char *p)
1186
{
1187
    int i;
1188
    char *pp,*name,*pt;
1189
    char tbuf2[MAX_LINELEN+1];
1190
    struct objparm pm;
1191
 
1192
    p=find_word_start(p);
1193
    if(*p==exec_prefix_char || *p==0) return 0; /* comment */
1194
    name=p;
1195
    pp=find_name_end(p);
1196
    pt=find_word_start(pp); if(*pt=='=') *pt=' ';
1197
    if(*pt==':' && *(pt+1)=='=') *pt=*(pt+1)=' ';
1198
    pp=find_word_end(p);
1199
    if(*pp!=0) {
1200
        *(pp++)=0; pp=find_word_start(pp);
1201
    }
1202
    if(strlen(p)==1 || (strlen(p)==2 && isdigit(*(p+1)))) {
1203
        setvar(p,evalue(pp)); return 0;
1204
    }
1205
    i=search_list(objtab,obj_no,sizeof(objtab[0]),name);
1206
    if(i<0) {
1207
        error("bad_cmd"); return 1;
1208
    }
1209
    if(image==NULL && (objtab[i].color_pos || objtab[i].required_parms>2)) {
1210
        error("image_not_defined"); return 1;
1211
    }
1212
    strcpy(tbuf2,pp);
1213
    if(objtab[i].color_pos || objtab[i].routine==obj_setstyle) {
1214
        substit(tbuf2);
1215
    }
1216
    if(parse_parms(tbuf2,&pm,objtab+i)!=0) error("bad_parms");
1217
    else objtab[i].routine(&pm);
1218
    return 0;
1219
}
1220