0022590: Migration to FreeImage - revision of Xw and WNT packages
[occt.git] / src / Xw / Xw_draw_poly.cxx
1 // Copyright (c) 1999-2012 OPEN CASCADE SAS
2 //
3 // The content of this file is subject to the Open CASCADE Technology Public
4 // License Version 6.5 (the "License"). You may not use the content of this file
5 // except in compliance with the License. Please obtain a copy of the License
6 // at http://www.opencascade.org and read it completely before using this file.
7 //
8 // The Initial Developer of the Original Code is Open CASCADE S.A.S., having its
9 // main offices at: 1, place des Freres Montgolfier, 78280 Guyancourt, France.
10 //
11 // The Original Code and all software distributed under the License is
12 // distributed on an "AS IS" basis, without warranty of any kind, and the
13 // Initial Developer hereby disclaims all such warranties, including without
14 // limitation, any warranties of merchantability, fitness for a particular
15 // purpose or non-infringement. Please see the License for the specific terms
16 // and conditions governing the rights and limitations under the License.
17
18 #define BUC40223         /*GG_070797
19 Protection contre zoom trop grand*/
20
21 #include <Xw_Extension.h>
22
23         /* ifdef then trace on */
24 #ifdef TRACE
25 #define TRACE_DRAW_POLY
26 #endif
27
28 /*
29    STATUS Xw_draw_poly (awindow,npoint,px,py):
30    XW_EXT_WINDOW *awindow
31    int npoint           Polygone point number
32    float *px,*py        Polygone points
33
34
35         Display continuous poly in current QG set by set_poly_attrib .
36         Note that polys can be buffered depending of the DisplayMode context
37         and Flush at Xw_flush time .
38
39         returns ERROR if npoint > MAXPOINTS
40         returns SUCCESS if successful 
41
42 */
43
44 static int FirstPolyPoint = -1 ;
45 static int FirstPolyLine = -1 ;
46 static int FirstPathPoint = -1 ;
47 static XW_EXT_POLY *ppolylist ;
48 static XW_EXT_POINT *plinedesc ;
49 static XSegment segment;
50
51 #ifdef XW_PROTOTYPE
52 XW_STATUS Xw_draw_poly (void* awindow,int npoint,float* px,float* py)
53 #else
54 XW_STATUS Xw_draw_poly (awindow,npoint,px,py)
55 void *awindow;
56 int npoint ;
57 float *px,*py ;
58 #endif /*XW_PROTOTYPE*/
59 {
60 XW_EXT_WINDOW *pwindow = (XW_EXT_WINDOW*)awindow;
61 XW_EXT_BUFFER *pbuffer ;
62 int i,npoly,ldesc,bindex;
63 int x=0,y=0,lx=0,ly=0 ;
64 XPoint *ppoint ;
65
66         if( !Xw_isdefine_window(pwindow) ) {
67             /*ERROR*Bad EXT_WINDOW Address*/
68             Xw_set_error(24,"Xw_draw_poly",pwindow) ;
69             return (XW_ERROR) ;
70         }
71
72         if( npoint >= MAXPOINTS ) {
73             npoint = MAXPOINTS-1 ;
74             /*ERROR*Too many points in POLYGONE*/
75             Xw_set_error(28,"Xw_draw_poly",&npoint) ;
76             return (XW_ERROR) ;
77         }
78
79         if( npoint < 3 ) {
80             /*WARNING*POLYGONE is Empty !!!*/
81             Xw_set_error(33,"Xw_draw_poly",&npoint) ;
82             return (XW_ERROR) ;
83         }
84
85         bindex = _BINDEX ;
86         pbuffer = &_BUFFER(bindex) ;
87         for( ppolylist = pbuffer->ppolylist ; ppolylist ;
88                          ppolylist = (XW_EXT_POLY*)ppolylist->link ) {
89             if( ppolylist->npoly < MAXPOLYS ) break ;
90         }
91
92         if( !ppolylist ) {
93             ppolylist = Xw_add_polygone_structure(pbuffer) ;
94         }
95
96         if( !ppolylist ) return XW_ERROR ;
97
98         for( plinedesc = pbuffer->plinedesc ; plinedesc ;
99                         plinedesc = (XW_EXT_POINT*)plinedesc->link ) {
100             if( plinedesc->npoint + npoint < MAXPOINTS ) break ;
101         }
102  
103         if( !plinedesc ) {
104             plinedesc = Xw_add_line_desc_structure(pbuffer) ;
105         }
106  
107         if( !plinedesc ) return XW_ERROR ;
108  
109         npoly = ppolylist->npoly ;
110         ldesc = plinedesc->npoint ;
111         ppolylist->ppolys[npoly] = ppoint = &plinedesc->rpoints[ldesc] ;
112         for( i=0 ; i<npoint ; i++ ) {
113 //OCC186
114             x = PXPOINT(px[i], pwindow->xratio) ;
115             y = PYPOINT(py[i], pwindow->attributes.height, pwindow->yratio) ;
116 //OCC186
117 #ifdef BUC40223
118             if( i > 0 ) {
119               int status;
120               status = Xw_clip_segment(pwindow,lx,ly,x,y,&segment);
121               if( status >= 0 ) {
122                 if( (i < 2) || (status & 0xF ) ) {
123                   plinedesc->rpoints[ldesc].x = segment.x1 ;
124                   plinedesc->rpoints[ldesc].y = segment.y1 ;
125                   ldesc++;
126                   if( bindex > 0 ) {
127                     int xx = segment.x1,yy = segment.y1;
128                     pbuffer->rxmin = min(pbuffer->rxmin,xx) ;
129                     pbuffer->rymin = min(pbuffer->rymin,yy) ;
130                     pbuffer->rxmax = max(pbuffer->rxmax,xx) ;
131                     pbuffer->rymax = max(pbuffer->rymax,yy) ;
132                   }
133                 }
134                 plinedesc->rpoints[ldesc].x = segment.x2 ;
135                 plinedesc->rpoints[ldesc].y = segment.y2 ;
136                 ldesc++;
137                 if( bindex > 0 ) {
138                   int xx = segment.x2,yy = segment.y2;
139                   pbuffer->rxmin = min(pbuffer->rxmin,xx) ;
140                   pbuffer->rymin = min(pbuffer->rymin,yy) ;
141                   pbuffer->rxmax = max(pbuffer->rxmax,xx) ;
142                   pbuffer->rymax = max(pbuffer->rymax,yy) ;
143                 }
144               }
145             }
146             lx = x; ly = y;
147 #else
148             plinedesc->rpoints[ldesc].x = x ;
149             plinedesc->rpoints[ldesc].y = y ;
150             ldesc++ ;
151             if( bindex > 0 ) {
152               pbuffer->rxmin = min(pbuffer->rxmin,x) ;
153               pbuffer->rymin = min(pbuffer->rymin,y) ;
154               pbuffer->rxmax = max(pbuffer->rxmax,x) ;
155               pbuffer->rymax = max(pbuffer->rymax,y) ;
156             }
157 #endif
158         }
159         if( ppoint->x != x || ppoint->y != y ) {
160             plinedesc->rpoints[ldesc].x = ppoint->x ;
161             plinedesc->rpoints[ldesc].y = ppoint->y ;
162             ldesc++ ;
163         }
164         ppolylist->polys[npoly] = ldesc - plinedesc->npoint ;
165         ppolylist->paths[npoly] = ppolylist->polys[npoly] ;
166         if( ppolylist->polys[npoly] > 3 ) {
167           ppolylist->npoly++ ;
168           plinedesc->npoint = ldesc ;
169
170           if( bindex > 0 ) {
171             pbuffer->isempty = False ;
172           } else if( FirstPolyPoint < 0 ) {
173             int polyindex = pwindow->polyindex ;
174             int lineindex = pwindow->lineindex ;
175             GC gcpoly = (QGTILE(pwindow->qgpoly[polyindex].code)) ?
176                                 pwindow->qgpoly[polyindex].gc : NULL ;
177             GC gcline = (QGTYPE(pwindow->qgpoly[polyindex].code)) ?
178                                 pwindow->qgline[lineindex].gc : NULL ;
179             Xw_draw_pixel_polys(pwindow,ppolylist,gcpoly,gcline);
180             ppolylist->npoly = 0 ;
181             plinedesc->npoint = 0 ;
182           }
183         }
184
185 #ifdef  TRACE_DRAW_POLY
186 if( Xw_get_trace() > 2 ) {
187     printf(" Xw_draw_poly(%lx,%d)\n",(long ) pwindow,npoint) ;
188     for( i=0 ; i<npoint ; i++ ) {
189         printf("        Point(%d) = {%f,%f}\n",i,px[i],py[i]) ;
190     }
191 }
192 #endif
193
194         return (XW_SUCCESS);
195 }
196
197 #ifdef XW_PROTOTYPE
198 void Xw_draw_pixel_polys(XW_EXT_WINDOW* pwindow,XW_EXT_POLY* ppolylist,
199                                                         GC gcpoly,GC gcline)
200 #else
201 void Xw_draw_pixel_polys(pwindow,ppolylist,gcpoly,gcline)
202 XW_EXT_WINDOW *pwindow ;
203 XW_EXT_POLY *ppolylist ;
204 GC gcpoly,gcline ;
205 #endif
206 {
207 int i,npolypoint,npathpoint,shape,npoint=0,count=0;
208 Region chr_region=NULL;
209 XPoint *ppoint ;
210
211         for( i=0 ; i<ppolylist->npoly ; i++ ) { 
212             npolypoint = ppolylist->polys[i] ;
213             npathpoint = ppolylist->paths[i] ;
214             ppoint = ppolylist->ppolys[i] ;
215             if( ppolylist->isupdated ) {
216               ppoint += MAXPOINTS ;
217             }
218             if( gcpoly ) {
219               if( npolypoint > 0 ) {
220                 npoint = npolypoint; count = 0;
221                 chr_region = 0;
222               }
223               if( npoint > npathpoint ) {
224                 if( npathpoint > 3 ) {
225                   if( chr_region == 0 ) {
226                     chr_region = 
227                         XPolygonRegion(ppoint,npathpoint-1,EvenOddRule);
228                   } else {
229                     Region chr_pathreg = 
230                         XPolygonRegion(ppoint,npathpoint-1,EvenOddRule);
231                     Region chr_xorreg = XCreateRegion ();
232                     XXorRegion (chr_region, chr_pathreg, chr_xorreg);
233                     XDestroyRegion (chr_region);
234                     chr_region = chr_xorreg;
235                   }
236                 }
237                 count += npathpoint;
238                 if( count >= npoint && chr_region ) {
239                   XRectangle rect;
240                   XSetRegion(_DISPLAY,gcpoly,chr_region);
241                   XClipBox(chr_region,&rect);
242                   XFillRectangles(_DISPLAY,_DRAWABLE,gcpoly,&rect,1);
243                   XDestroyRegion(chr_region);
244                   XSetClipMask(_DISPLAY,gcpoly,None);
245                 }
246               } else if( npoint > 3 ) { 
247                 shape = (npoint > 4) ? Nonconvex : Convex;
248                 XFillPolygon(_DISPLAY,_DRAWABLE,gcpoly,ppoint,npoint-1,
249                                                 shape,CoordModeOrigin) ;
250         
251               }
252             }
253             if( gcline && (gcpoly != gcline) && (npathpoint > 3) ) {
254               XDrawLines(_DISPLAY,_DRAWABLE,gcline,
255                                         ppoint,npathpoint,CoordModeOrigin) ;
256             }
257         }
258 }
259
260 /*
261    STATUS Xw_begin_poly (awindow,npoint,npath):
262    XW_EXT_WINDOW *awindow
263    int npoint           Estimated polygone point number
264    int npath            Estimated polygone path number
265
266
267         Begin Polygone which must be filled by Xw_poly_point and
268                                      closed by Xw_close_poly
269
270         returns ERROR if npoint > MAXPOINTS
271                       or npath > MAXPOLYS
272         returns SUCCESS if successful 
273
274 */
275
276 static int Npoint = 0;
277 static int Lx,Ly;
278 #ifdef XW_PROTOTYPE
279 XW_STATUS Xw_begin_poly(void* awindow,int npoint,int npath)
280 #else
281 XW_STATUS Xw_begin_poly(awindow,npoint,npath)
282 void *awindow ;
283 int npoint,npath ;
284 #endif /*XW_PROTOTYPE*/
285 {
286 XW_EXT_WINDOW *pwindow = (XW_EXT_WINDOW*)awindow ;
287 int npoly,ldesc,bindex ;
288
289         if( !Xw_isdefine_window(pwindow) ) {
290             /*ERROR*Bad EXT_WINDOW Address*/
291             Xw_set_error(24,"Xw_begin_poly",pwindow) ;
292             return (XW_ERROR) ;
293         }
294
295         if( npoint >= MAXPOINTS ) {
296             npoint = MAXPOINTS-1 ;
297             /*ERROR*Too many points in POLYGONE*/
298             Xw_set_error(32,"Xw_begin_poly",&npoint) ;
299             return (XW_ERROR) ;
300         }
301
302         if( npath >= MAXPOLYS ) {
303             npath = MAXPOLYS-1 ;
304             /*ERROR*Too many paths in POLYGONE*/
305             Xw_set_error(32,"Xw_begin_poly",&npath) ;
306             return (XW_ERROR) ;
307         }
308
309         if( FirstPolyPoint >= 0 ) Xw_close_poly(pwindow) ;
310
311         bindex = _BINDEX ;
312         for( ppolylist = _BUFFER(bindex).ppolylist ; ppolylist ;
313                         ppolylist = (XW_EXT_POLY*)ppolylist->link ) {
314             if( (ppolylist->npoly + npath) < MAXPOLYS ) break ;
315         }    
316  
317         if( !ppolylist ) {
318             ppolylist = Xw_add_polygone_structure(&_BUFFER(bindex)) ;
319         }    
320  
321         if( !ppolylist ) return XW_ERROR ;
322  
323         for( plinedesc = _BUFFER(bindex).plinedesc ; plinedesc ;
324                         plinedesc = (XW_EXT_POINT*)plinedesc->link ) {
325             if( (plinedesc->npoint + npoint) < MAXPOINTS ) break ;
326         }    
327  
328         if( !plinedesc ) {
329             plinedesc = Xw_add_line_desc_structure(&_BUFFER(bindex)) ;
330         }    
331  
332         if( !plinedesc ) return XW_ERROR ;
333  
334         npoly = ppolylist->npoly ;
335         ldesc = plinedesc->npoint ;
336         ppolylist->polys[npoly] = 0 ;
337         ppolylist->paths[npoly] = Npoint = 0 ;
338         ppolylist->ppolys[npoly] = &plinedesc->rpoints[ldesc] ;
339         FirstPolyPoint = FirstPathPoint = ldesc ;
340         FirstPolyLine = npoly;
341
342
343 #ifdef  TRACE_DRAW_POLY
344 if( Xw_get_trace() > 2 ) {
345     printf(" Xw_begin_poly(%lx,%d,%d)\n",(long ) pwindow,npoint,npath) ;
346 }
347 #endif
348         return (XW_SUCCESS) ;
349 }
350
351 /*
352    STATUS Xw_poly_point (awindow,x,y):
353    XW_EXT_WINDOW *awindow
354    float x,y    New point to add in polygone in user-space coordinates
355
356         Fill Polygone with one point more
357
358         returns ERROR if Too Many Points in polygones
359         returns SUCCESS if successful 
360
361 */
362
363 #ifdef XW_PROTOTYPE
364 XW_STATUS Xw_poly_point(void* awindow,float x,float y)
365 #else
366 XW_STATUS Xw_poly_point(awindow,x,y)
367 void *awindow ;
368 float x,y ;
369 #endif /*XW_PROTOTYPE*/
370 {
371 XW_EXT_WINDOW *pwindow = (XW_EXT_WINDOW*)awindow ;
372 XW_EXT_BUFFER *pbuffer ;
373 int bindex,xi,yi ;
374
375         if( FirstPolyPoint >= 0 ) {
376           int ldesc = plinedesc->npoint ;
377           if( ldesc >= MAXPOINTS ) {
378             /*ERROR*Too many points in POLYGONE*/
379             Xw_set_error(32,"Xw_poly_point",&ldesc) ;
380             Xw_close_poly(pwindow) ;
381             return (XW_ERROR) ;
382           }
383
384           bindex = _BINDEX ;
385 //OCC186
386           xi = PXPOINT(x, pwindow->xratio) ;
387           yi = PYPOINT(y, pwindow->attributes.height, pwindow->yratio) ;
388 //OCC186
389 #ifdef BUC40223
390           if( Npoint > 0 ) {
391             int status;
392             status = Xw_clip_segment(pwindow,Lx,Ly,xi,yi,&segment);
393             if( status >= 0 ) {
394               if( (Npoint < 2) || (status & 0xF ) ) {
395                 plinedesc->rpoints[ldesc].x = segment.x1 ;
396                 plinedesc->rpoints[ldesc].y = segment.y1 ;
397                 ldesc++; plinedesc->npoint++ ;
398                 if( bindex > 0 ) {
399                   int xx = segment.x1,yy = segment.y1;
400                   pbuffer = &_BUFFER(bindex) ;
401                   pbuffer->isempty = False ;
402                   pbuffer->rxmin = min(pbuffer->rxmin,xx) ;
403                   pbuffer->rymin = min(pbuffer->rymin,yy) ;
404                   pbuffer->rxmax = max(pbuffer->rxmax,xx) ;
405                   pbuffer->rymax = max(pbuffer->rymax,yy) ;
406                 }
407               }
408               plinedesc->rpoints[ldesc].x = segment.x2 ;
409               plinedesc->rpoints[ldesc].y = segment.y2 ;
410               plinedesc->npoint++ ;
411               if( bindex > 0 ) {
412                 int xx = segment.x2,yy = segment.y2;
413                 pbuffer = &_BUFFER(bindex) ;
414                 pbuffer->isempty = False ;
415                 pbuffer->rxmin = min(pbuffer->rxmin,xx) ;
416                 pbuffer->rymin = min(pbuffer->rymin,yy) ;
417                 pbuffer->rxmax = max(pbuffer->rxmax,xx) ;
418                 pbuffer->rymax = max(pbuffer->rymax,yy) ;
419               }
420             }
421           }
422           Lx = xi; Ly = yi;
423           Npoint++;
424 #else
425           plinedesc->rpoints[ldesc].x = xi ;
426           plinedesc->rpoints[ldesc].y = yi ;
427           plinedesc->npoint++ ;
428           if( bindex > 0 ) {
429             pbuffer = &_BUFFER(bindex) ;
430             pbuffer->isempty = False ;
431             pbuffer->rxmin = min(pbuffer->rxmin,xi) ;
432             pbuffer->rymin = min(pbuffer->rymin,yi) ;
433             pbuffer->rxmax = max(pbuffer->rxmax,xi) ;
434             pbuffer->rymax = max(pbuffer->rymax,yi) ;
435           }
436 #endif
437         }
438
439 #ifdef  TRACE_DRAW_POLY
440 if( Xw_get_trace() > 3 ) {
441     printf(" Xw_poly_point(%lx,%f,%f)\n",(long ) pwindow,x,y) ;
442 }
443 #endif
444         return (XW_SUCCESS) ;
445 }
446
447 /*
448    STATUS Xw_close_path (awindow):
449    XW_EXT_WINDOW *awindow
450
451         Close the Polygone path
452
453         returns ERROR if TOO many path 
454         returns SUCCESS if successful 
455
456 */
457
458 #ifdef XW_PROTOTYPE
459 XW_STATUS Xw_close_path(void* awindow)
460 #else
461 XW_STATUS Xw_close_path(awindow)
462 void *awindow ;
463 #endif /*XW_PROTOTYPE*/
464 {
465 #ifdef  TRACE_DRAW_POLY
466 XW_EXT_WINDOW *pwindow = (XW_EXT_WINDOW*)awindow ;
467 #endif
468
469         if( FirstPolyPoint >= 0 ) {
470           int npoly = ppolylist->npoly ;
471           int ldesc = plinedesc->npoint ;
472             
473           if( plinedesc->rpoints[FirstPathPoint].x != plinedesc->rpoints[ldesc-1].x ||
474               plinedesc->rpoints[FirstPathPoint].y != plinedesc->rpoints[ldesc-1].y ) {
475             plinedesc->rpoints[ldesc].x = plinedesc->rpoints[FirstPathPoint].x ; 
476             plinedesc->rpoints[ldesc].y = plinedesc->rpoints[FirstPathPoint].y ; 
477             plinedesc->npoint++ ; ldesc++ ;
478           } 
479           ppolylist->polys[FirstPolyLine] = ldesc - FirstPolyPoint ;
480           ppolylist->paths[npoly] = ldesc - FirstPathPoint ;
481           FirstPathPoint = ldesc;
482           if( ppolylist->npoly < MAXPOLYS ) {
483             ppolylist->npoly = ++npoly ;
484             ppolylist->polys[npoly] = 0 ;
485             ppolylist->paths[npoly] = Npoint = 0 ;
486             ppolylist->ppolys[npoly] = &plinedesc->rpoints[ldesc] ;
487           } else {
488             /*ERROR*Too many paths in POLYGONE*/
489             Xw_set_error(32,"Xw_close_path",&ppolylist->npoly) ;
490             return (XW_ERROR) ;
491           }
492         }    
493           
494 #ifdef  TRACE_DRAW_POLY
495 if( Xw_get_trace() > 2 ) {
496     printf(" Xw_close_path(%lx)\n",(long ) pwindow) ;
497 }
498 #endif
499         return (XW_SUCCESS) ;
500 }
501
502 /*
503    STATUS Xw_close_poly (awindow):
504    XW_EXT_WINDOW *awindow
505
506         Close the Polygone
507
508         returns ERROR if Polygone is empty
509         returns SUCCESS if successful 
510
511 */
512
513 #ifdef XW_PROTOTYPE
514 XW_STATUS Xw_close_poly(void* awindow)
515 #else
516 XW_STATUS Xw_close_poly(awindow)
517 void *awindow ;
518 #endif /*XW_PROTOTYPE*/
519 {
520 XW_EXT_WINDOW *pwindow = (XW_EXT_WINDOW*)awindow ;
521
522         if( FirstPolyPoint >= 0 ) {
523         
524           if( plinedesc->npoint > FirstPathPoint ) Xw_close_path(pwindow); 
525  
526           if( !_BINDEX ) {
527             int polyindex = pwindow->polyindex ;
528             int lineindex = pwindow->lineindex ;
529             GC gcpoly = (QGTILE(pwindow->qgpoly[polyindex].code)) ?
530                                 pwindow->qgpoly[polyindex].gc : NULL ;
531             GC gcline = (QGTYPE(pwindow->qgpoly[polyindex].code)) ?
532                                 pwindow->qgline[lineindex].gc : NULL ;
533             Xw_draw_pixel_polys(pwindow,ppolylist,gcpoly,gcline);
534             ppolylist->npoly = 0 ;
535             plinedesc->npoint = 0 ;
536           }  
537           FirstPolyPoint = -1 ;
538         }    
539           
540 #ifdef  TRACE_DRAW_POLY
541 if( Xw_get_trace() > 2 ) {
542     printf(" Xw_close_poly(%lx)\n",(long ) pwindow) ;
543 }
544 #endif
545         return (XW_SUCCESS) ;
546 }
547
548 #ifdef XW_PROTOTYPE
549 XW_EXT_POLY* Xw_add_polygone_structure(XW_EXT_BUFFER* pbuflist )
550 #else
551 XW_EXT_POLY* Xw_add_polygone_structure(pbuflist )
552 XW_EXT_BUFFER *pbuflist ;
553 #endif /*XW_PROTOTYPE*/
554 /*
555         Create and Insert at end one Extended polygone structure in the
556         polygone List
557
558         returns Extended polygone address if successful
559                 or NULL if Bad Allocation
560 */
561 {
562 XW_EXT_POLY *ppoly ;
563
564         ppoly = (XW_EXT_POLY*) Xw_malloc(sizeof(XW_EXT_POLY)) ;
565         if( ppoly ) {
566             ppoly->link = pbuflist->ppolylist ;
567             ppoly->isupdated = False ;
568             ppoly->npoly = 0 ;
569             pbuflist->ppolylist = ppoly ;
570         } else {
571             /*ERROR*EXT_POLYGONE allocation failed*/
572             Xw_set_error(34,"Xw_add_polygone_structure",NULL) ;
573         }
574
575         return (ppoly) ;
576 }
577
578 #ifdef XW_PROTOTYPE
579 XW_STATUS Xw_del_polygone_structure(XW_EXT_BUFFER* pbuflist)
580 #else
581 XW_STATUS Xw_del_polygone_structure(pbuflist)
582 XW_EXT_BUFFER *pbuflist ;
583 #endif /*XW_PROTOTYPE*/
584 /*
585         Remove ALL Extended polygone structure in the
586         polygone List
587
588         SUCCESS always
589 */
590 {
591 XW_EXT_POLY *ppoly,*qpoly ;
592
593         for( ppoly = pbuflist->ppolylist ; ppoly ; ppoly = qpoly ) {
594             qpoly = (XW_EXT_POLY*)ppoly->link ;
595             Xw_free(ppoly) ;
596         }
597         pbuflist->ppolylist = NULL ;
598
599         return (XW_SUCCESS) ;
600 }