Tizen 2.1 base
[platform/core/uifw/ise-engine-sunpinyin.git] / wrapper / xim / IMdkit / FrameMgr.c
1 /******************************************************************
2 Copyright 1993, 1994 by Digital Equipment Corporation, Maynard, Massachusetts,
3  
4                         All Rights Reserved
5  
6 Permission to use, copy, modify, and distribute this software and its 
7 documentation for any purpose and without fee is hereby granted, 
8 provided that the above copyright notice appear in all copies and that
9 both that copyright notice and this permission notice appear in 
10 supporting documentation, and that the names of Digital or MIT not be
11 used in advertising or publicity pertaining to distribution of the
12 software without specific, written prior permission.  
13  
14 DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
15 ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
16 DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
17 ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
18 WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
19 ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
20 SOFTWARE.
21  
22   Author: Hiroyuki Miyamoto  Digital Equipment Corporation
23                              miyamoto@jrd.dec.com
24
25     This version tidied and debugged by Steve Underwood May 1999
26
27 ******************************************************************/
28
29 #include <X11/Xlibint.h>
30 #include <stdlib.h>
31 #include "FrameMgr.h"
32
33 /* Convenient macro */
34
35 #define _UNIT(n)   ((int)(n) & 0xFF)
36 #define _NUMBER(n) (((int)(n) >> 8) & 0xFF)
37
38 /* For byte swapping */
39
40 #define Swap16(p, n) ((p)->byte_swap ?       \
41 (((n) << 8 & 0xFF00) | \
42  ((n) >> 8 & 0xFF)     \
43 ) : n)
44 #define Swap32(p, n) ((p)->byte_swap ?            \
45         (((n) << 24 & 0xFF000000) | \
46          ((n) <<  8 & 0xFF0000) |   \
47          ((n) >>  8 & 0xFF00) |     \
48          ((n) >> 24 & 0xFF)         \
49         ) : n)
50 #define Swap64(p, n) ((p)->byte_swap ?            \
51         (((n) << 56 & 0xFF00000000000000) | \
52          ((n) << 40 & 0xFF000000000000) |   \
53          ((n) << 24 & 0xFF0000000000) |     \
54          ((n) <<  8 & 0xFF00000000) |       \
55          ((n) >>  8 & 0xFF000000) |         \
56          ((n) >> 24 & 0xFF0000) |           \
57          ((n) >> 40 & 0xFF00) |             \
58          ((n) >> 56 & 0xFF)                 \
59         ) : n)
60
61 /* Type definition */
62
63 typedef struct _Iter *Iter;
64
65 typedef struct _FrameInst *FrameInst;
66
67 typedef union
68 {
69     int num;            /* For BARRAY */
70     FrameInst fi;       /* For POINTER */
71     Iter iter;          /* For ITER */
72 } ExtraDataRec, *ExtraData;
73
74 typedef struct _Chain
75 {
76     ExtraDataRec d;
77     int frame_no;
78     struct _Chain *next;
79 } ChainRec, *Chain;
80
81 typedef struct _ChainMgr
82 {
83     Chain top;
84     Chain tail;
85 } ChainMgrRec, *ChainMgr;
86
87 typedef struct _ChainIter
88 {
89     Chain cur;
90 } ChainIterRec, *ChainIter;
91
92 typedef struct _FrameIter
93 {
94     Iter iter;
95     Bool counting;
96     unsigned int counter;
97     int end;
98     struct _FrameIter* next;
99 } FrameIterRec, *FrameIter;
100
101 typedef struct _FrameInst
102 {
103     XimFrame template;
104     ChainMgrRec cm;
105     int cur_no;
106 } FrameInstRec;
107
108 typedef void (*IterStartWatchProc) (Iter it, void *client_data);
109
110 typedef struct _Iter
111 {
112     XimFrame template;
113     int max_count;
114     Bool allow_expansion;
115     ChainMgrRec cm;
116     int cur_no;
117     IterStartWatchProc start_watch_proc;
118     void *client_data;
119     Bool start_counter;
120 } IterRec;
121
122 typedef struct _FrameMgr
123 {
124     XimFrame frame;
125     FrameInst fi;
126     char *area;
127     int idx;
128     Bool byte_swap;
129     int total_size;
130     FrameIter iters;
131 } FrameMgrRec;
132
133 typedef union
134 {
135     int num;           /* For BARRAY and PAD */
136     struct
137     {          /* For COUNTER_* */
138         Iter iter;
139         Bool is_byte_len;
140     } counter;
141 } XimFrameTypeInfoRec, *XimFrameTypeInfo;
142
143 /* Special values */
144 #define NO_VALUE -1
145 #define NO_VALID_FIELD -2
146
147 static FrameInst FrameInstInit(XimFrame frame);
148 static void FrameInstFree(FrameInst fi);
149 static XimFrameType FrameInstGetNextType(FrameInst fi, XimFrameTypeInfo info);
150 static XimFrameType FrameInstPeekNextType(FrameInst fi, XimFrameTypeInfo info);
151 static FmStatus FrameInstSetSize(FrameInst fi, int num);
152 static FmStatus FrameInstSetIterCount(FrameInst fi, int num);
153 static int FrameInstGetTotalSize(FrameInst fi);
154 static void FrameInstReset(FrameInst fi);
155
156 static Iter IterInit(XimFrame frame, int count);
157 static void IterFree(Iter it);
158 static int FrameInstGetSize(FrameInst fi);
159 static int IterGetSize(Iter it);
160 static XimFrameType IterGetNextType(Iter it, XimFrameTypeInfo info);
161 static XimFrameType IterPeekNextType(Iter it, XimFrameTypeInfo info);
162 static FmStatus IterSetSize(Iter it, int num);
163 static FmStatus IterSetIterCount(Iter it, int num);
164 static int IterGetTotalSize(Iter it);
165 static void IterReset(Iter it);
166 static Bool IterIsLoopEnd(Iter it, Bool* myself);
167 static void IterSetStartWatch(Iter it, IterStartWatchProc proc, void* client_data);
168 static void _IterStartWatch(Iter it, void* client_data);
169
170 static ExtraData ChainMgrGetExtraData(ChainMgr cm, int frame_no);
171 static ExtraData ChainMgrSetData(ChainMgr cm, int frame_no,
172                                  ExtraDataRec data);
173 static Bool ChainIterGetNext(ChainIter ci, int* frame_no, ExtraData d);
174 static int _FrameInstIncrement(XimFrame frame, int count);
175 static int _FrameInstDecrement(XimFrame frame, int count);
176 static int _FrameInstGetItemSize(FrameInst fi, int cur_no);
177 static Bool FrameInstIsIterLoopEnd(FrameInst fi);
178
179 static FrameIter _FrameMgrAppendIter(FrameMgr fm, Iter it, int end);
180 static FrameIter _FrameIterCounterIncr(FrameIter fitr, int i);
181 static void _FrameMgrRemoveIter(FrameMgr fm, FrameIter it);
182 static Bool _FrameMgrIsIterLoopEnd(FrameMgr fm);
183 static Bool _FrameMgrProcessPadding(FrameMgr fm, FmStatus* status);
184
185 #define IterGetIterCount(it) ((it)->allow_expansion ? \
186 NO_VALUE : (it)->max_count)
187
188 #define IterFixIteration(it) ((it)->allow_expansion = False)
189
190 #define IterSetStarter(it) ((it)->start_counter = True)
191
192 #define ChainMgrInit(cm) (cm)->top = (cm)->tail = NULL
193 #define ChainMgrFree(cm)                \
194 {                                       \
195     Chain tmp;                          \
196     Chain cur = (cm)->top;              \
197                                         \
198     while (cur)                         \
199     {                                   \
200         tmp = cur->next;                \
201         Xfree (cur);                    \
202         cur = tmp;                      \
203     }                                   \
204 }
205
206 #define ChainIterInit(ci, cm)           \
207 {                                       \
208     (ci)->cur = (cm)->top;              \
209 }
210
211 /* ChainIterFree has nothing to do. */
212 #define ChainIterFree(ci)
213
214 #define FrameInstIsEnd(fi) ((fi)->template[(fi)->cur_no].type == EOL)
215
216 FrameMgr FrameMgrInit (XimFrame frame, char* area, Bool byte_swap)
217 {
218     FrameMgr fm;
219
220     fm = (FrameMgr) Xmalloc (sizeof (FrameMgrRec));
221
222     fm->frame = frame;
223     fm->fi = FrameInstInit (frame);
224     fm->area = (char *) area;
225     fm->idx = 0;
226     fm->byte_swap = byte_swap;
227     fm->total_size = NO_VALUE;
228     fm->iters = NULL;
229
230     return fm;
231 }
232
233 void FrameMgrInitWithData (FrameMgr fm,
234                            XimFrame frame,
235                            void * area,
236                            Bool byte_swap)
237 {
238     fm->frame = frame;
239     fm->fi = FrameInstInit (frame);
240     fm->area = (char *) area;
241     fm->idx = 0;
242     fm->byte_swap = byte_swap;
243     fm->total_size = NO_VALUE;
244 }
245
246 void FrameMgrFree (FrameMgr fm)
247 {
248     FrameIter p, cur;
249
250     p = fm->iters;
251     cur = p;
252
253     while (p)
254     {
255         p = p->next;
256         Xfree (cur);
257         cur = p;
258     }
259     /*endwhile*/
260
261     FrameInstFree (fm->fi);
262     Xfree (fm);
263 }
264
265 FmStatus FrameMgrSetBuffer (FrameMgr fm, void* area)
266 {
267     if (fm->area)
268         return FmBufExist;
269     fm->area = (char *) area;
270     return FmSuccess;
271 }
272
273 FmStatus _FrameMgrPutToken (FrameMgr fm, void *data, int data_size)
274 {
275     XimFrameType type;
276     XimFrameTypeInfoRec info;
277
278     if (fm->total_size != NO_VALUE  &&  fm->idx >= fm->total_size)
279         return FmNoMoreData;
280     /*endif*/
281     
282     type = FrameInstGetNextType(fm->fi, &info);
283
284     if (type & COUNTER_MASK)
285     {
286         unsigned long input_length;
287
288         if (info.counter.is_byte_len)
289         {
290             if ((input_length = IterGetTotalSize (info.counter.iter))
291                     == NO_VALUE)
292             {
293                 return FmCannotCalc;
294             }
295             /*endif*/
296         }
297         else
298         {
299             if ((input_length = IterGetIterCount (info.counter.iter))
300                 == NO_VALUE)
301             {
302                 return FmCannotCalc;
303             }
304             /*endif*/
305         }
306         /*endif*/
307         switch (type)
308         {
309         case COUNTER_BIT8:
310             *(CARD8 *) (fm->area + fm->idx) = input_length;
311             fm->idx++;
312             break;
313         
314         case COUNTER_BIT16:
315             *(CARD16 *) (fm->area + fm->idx) = Swap16 (fm, input_length);
316             fm->idx += 2;
317             break;
318             
319         case COUNTER_BIT32:
320             *(CARD32 *) (fm->area + fm->idx) = Swap32 (fm, input_length);
321             fm->idx += 4;
322             break;
323
324 #if defined(_NEED64BIT)
325         case COUNTER_BIT64:
326             *(CARD64 *) (fm->area + fm->idx) = Swap64 (fm, input_length);
327             fm->idx += 8;
328             break;
329 #endif
330         default:
331             break;
332         }
333         /*endswitch*/
334         _FrameMgrPutToken(fm, data, data_size);
335         return FmSuccess;
336     }
337     /*endif*/
338
339     switch (type)
340     {
341     case BIT8:
342         if (data_size == sizeof (unsigned char))
343         {
344             unsigned long num = *(unsigned char *) data;
345             *(CARD8 *) (fm->area + fm->idx) = num;
346         }
347         else if (data_size == sizeof (unsigned short))
348         {
349             unsigned long num = *(unsigned short *) data;
350             *(CARD8 *) (fm->area + fm->idx) = num;
351         }
352         else if (data_size == sizeof (unsigned int))
353         {
354             unsigned long num = *(unsigned int *) data;
355             *(CARD8 *) (fm->area + fm->idx) = num;
356         }
357         else if (data_size == sizeof (unsigned long))
358         {
359             unsigned long num = *(unsigned long *) data;
360             *(CARD8 *) (fm->area + fm->idx) = num;
361         }
362         else
363         {
364             ; /* Should never be reached */
365         }
366         /*endif*/
367         fm->idx++;
368         return FmSuccess;
369
370     case BIT16:
371         if (data_size == sizeof (unsigned char))
372         {
373             unsigned long num = *(unsigned char *) data;
374             *(CARD16*)(fm->area + fm->idx) = Swap16 (fm, num);
375         }
376         else if (data_size == sizeof (unsigned short))
377         {
378             unsigned long num = *(unsigned short *) data;
379             *(CARD16 *) (fm->area + fm->idx) = Swap16 (fm, num);
380         }
381         else if (data_size == sizeof (unsigned int))
382         {
383             unsigned long num = *(unsigned int *) data;
384             *(CARD16 *) (fm->area + fm->idx) = Swap16 (fm, num);
385         }
386         else if (data_size == sizeof (unsigned long))
387         {
388             unsigned long num = *(unsigned long *) data;
389             *(CARD16 *) (fm->area + fm->idx) = Swap16 (fm, num);
390         }
391         else
392         {
393             ; /* Should never reached */
394         }
395         /*endif*/
396         fm->idx += 2;
397         return FmSuccess;
398
399     case BIT32:
400         if (data_size == sizeof (unsigned char))
401         {
402             unsigned long num = *(unsigned char *) data;
403             *(CARD32 *) (fm->area + fm->idx) = Swap32 (fm, num);
404         }
405         else if (data_size == sizeof (unsigned short))
406         {
407             unsigned long num = *(unsigned short *) data;
408             *(CARD32 *) (fm->area + fm->idx) = Swap32 (fm, num);
409         }
410         else if (data_size == sizeof (unsigned int))
411         {
412             unsigned long num = *(unsigned int *) data;
413             *(CARD32 *) (fm->area + fm->idx) = Swap32 (fm, num);
414         }
415         else if (data_size == sizeof (unsigned long))
416         {
417             unsigned long num = *(unsigned long *) data;
418             *(CARD32 *) (fm->area + fm->idx) = Swap32 (fm, num);
419         }
420         else
421         {
422             ; /* Should never reached */
423         }
424         /*endif*/
425         fm->idx += 4;
426         return FmSuccess;
427
428 #if defined(_NEED64BIT)
429     case BIT64:
430         if (data_size == sizeof (unsigned char))
431         {
432             unsigned long num = *(unsigned char *) data;
433             *(CARD64 *) (fm->area + fm->idx) = Swap64 (fm, num);
434         }
435         else if (data_size == sizeof (unsigned short))
436         {
437             unsigned long num = *(unsigned short *) data;
438             *(CARD64 *) (fm->area + fm->idx) = Swap64 (fm, num);
439         }
440         else if (data_size == sizeof (unsigned int))
441         {
442             unsigned long num = *(unsigned int *) data;
443             *(CARD64 *) (fm->area + fm->idx) = Swap64 (fm, num);
444         }
445         else if (data_size == sizeof (unsigned long))
446         {
447             unsigned long num = *(unsigned long *) data;
448             *(CARD64 *) (fm->area + fm->idx) = Swap64 (fm, num);
449         }
450         else
451         {
452             ; /* Should never reached */
453         }
454         /*endif*/
455         fm->idx += 4;
456         return FmSuccess;
457 #endif
458
459     case BARRAY:
460         if (info.num == NO_VALUE)
461             return FmInvalidCall;
462         /*endif*/
463         if (info.num > 0)
464         {
465             bcopy (*(char **) data, fm->area + fm->idx, info.num);
466             fm->idx += info.num;
467         }
468         /*endif*/
469         return FmSuccess;
470
471     case PADDING:
472         if (info.num == NO_VALUE)
473             return FmInvalidCall;
474         /*endif*/
475         fm->idx += info.num;
476         return _FrameMgrPutToken(fm, data, data_size);
477
478     case ITER:
479         return FmInvalidCall;
480         
481     case EOL:
482         return FmEOD;
483     default:
484         break;
485     }
486     /*endswitch*/
487     return (FmStatus) NULL;  /* Should never be reached */
488 }
489
490 FmStatus _FrameMgrGetToken (FrameMgr fm , void* data, int data_size)
491 {
492     XimFrameType type;
493     static XimFrameTypeInfoRec info;  /* memory */
494     FrameIter fitr;
495
496     if (fm->total_size != NO_VALUE  &&  fm->idx >= fm->total_size)
497         return FmNoMoreData;
498     /*endif*/
499     
500     type = FrameInstGetNextType(fm->fi, &info);
501
502     if (type & COUNTER_MASK)
503     {
504         int end=0;
505         FrameIter client_data;
506
507         type &= ~COUNTER_MASK;
508         switch (type)
509         {
510         case BIT8:
511             end = *(CARD8 *) (fm->area + fm->idx);
512             break;
513         
514         case BIT16:
515             end = Swap16 (fm, *(CARD16 *) (fm->area + fm->idx));
516             break;
517         
518         case BIT32:
519             end = Swap32 (fm, *(CARD32 *) (fm->area + fm->idx));
520             break;
521
522 #if defined(_NEED64BIT)        
523         case BIT64:
524             end = Swap64 (fm, *(CARD64 *) (fm->area + fm->idx));
525             break;
526 #endif
527         default:
528             break;
529         }
530         /*endswitch*/
531         
532         if ((client_data = _FrameMgrAppendIter (fm, info.counter.iter, end)))
533         {
534             IterSetStarter (info.counter.iter);
535             IterSetStartWatch (info.counter.iter,
536                                _IterStartWatch,
537                                (void *) client_data);
538         }
539         /*endif*/
540     }
541     /*endif*/
542
543     type &= ~COUNTER_MASK;
544     switch (type)
545     {
546     case BIT8:
547         if (data_size == sizeof (unsigned char))
548         {
549             *(unsigned char*) data = *(CARD8 *) (fm->area + fm->idx);
550         }
551         else if (data_size == sizeof (unsigned short))
552         {
553             *(unsigned short *) data = *(CARD8 *) (fm->area + fm->idx);
554         }
555         else if (data_size == sizeof (unsigned int))
556         {
557             *(unsigned int *) data = *(CARD8 *) (fm->area + fm->idx);
558         }
559         else if (data_size == sizeof (unsigned long))
560         {
561             *(unsigned long *) data = *(CARD8 *) (fm->area + fm->idx);
562         }
563         else
564         {
565             ; /* Should never reached */
566         }
567         /*endif*/
568         fm->idx++;
569         if ((fitr = _FrameIterCounterIncr (fm->iters, 1/*BIT8*/)))
570             _FrameMgrRemoveIter (fm, fitr);
571         /*endif*/
572         return FmSuccess;
573
574     case BIT16:
575         if (data_size == sizeof (unsigned char))
576         {
577             *(unsigned char *) data =
578                 Swap16 (fm, *(CARD16 *) (fm->area + fm->idx));
579         }
580         else if (data_size == sizeof (unsigned short))
581         {
582             *(unsigned short *) data =
583                 Swap16 (fm, *(CARD16 *) (fm->area + fm->idx));
584         }
585         else if (data_size == sizeof (unsigned int))
586         {
587             *(unsigned int *) data =
588                 Swap16 (fm, *(CARD16 *) (fm->area + fm->idx));
589         }
590         else if (data_size == sizeof (unsigned long))
591         {
592             *(unsigned long *) data =
593                 Swap16 (fm, *(CARD16 *) (fm->area + fm->idx));
594         }
595         else
596         {
597             ; /* Should never reached */
598         }
599         /*endif*/
600         fm->idx += 2;
601         if ((fitr = _FrameIterCounterIncr (fm->iters, 2/*BIT16*/)))
602             _FrameMgrRemoveIter(fm, fitr);
603         /*endif*/
604         return FmSuccess;
605
606     case BIT32:
607         if (data_size == sizeof (unsigned char))
608         {
609             *(unsigned char *) data =
610                 Swap32 (fm, *(CARD32 *) (fm->area + fm->idx));
611         }
612         else if (data_size == sizeof (unsigned short))
613         {
614             *(unsigned short *) data =
615                 Swap32 (fm, *(CARD32 *) (fm->area + fm->idx));
616         }
617         else if (data_size == sizeof (unsigned int))
618         {
619             *(unsigned int *) data =
620                 Swap32 (fm, *(CARD32 *) (fm->area + fm->idx));
621         }
622         else if (data_size == sizeof (unsigned long))
623         {
624             *(unsigned long *) data =
625                 Swap32 (fm, *(CARD32 *) (fm->area + fm->idx));
626         }
627         else
628         {
629             ; /* Should never reached */
630         }
631         /*endif*/
632         fm->idx += 4;
633         if ((fitr = _FrameIterCounterIncr (fm->iters, 4/*BIT32*/)))
634             _FrameMgrRemoveIter (fm, fitr);
635         /*endif*/
636         return FmSuccess;
637
638 #if defined(_NEED64BIT)    
639     case BIT64:
640         if (data_size == sizeof (unsigned char))
641         {
642             *(unsigned char *) data =
643                 Swap64 (fm, *(CARD64 *) (fm->area + fm->idx));
644         }
645         else if (data_size == sizeof (unsigned short))
646         {
647             *(unsigned short *) data =
648                 Swap64 (fm, *(CARD64 *) (fm->area + fm->idx));
649         }
650         else if (data_size == sizeof (unsigned int))
651         {
652             *(unsigned int *) data =
653                 Swap64 (fm, *(CARD64 *) (fm->area + fm->idx));
654         }
655         else if (data_size == sizeof (unsigned long))
656         {
657             *(unsigned long *) data =
658                 Swap64 (fm, *(CARD64 *) (fm->area + fm->idx));
659         }
660         else
661         {
662             ; /* Should never reached */
663         }
664         /*endif*/
665         fm->idx += 8;
666         if ((fitr = _FrameIterCounterIncr (fm->iters, 8/*BIT64*/)))
667             _FrameMgrRemoveIter (fm, fitr);
668         /*endif*/
669         return FmSuccess;
670 #endif
671
672     case BARRAY:
673         if (info.num == NO_VALUE)
674             return FmInvalidCall;
675         /*endif*/
676         if (info.num > 0)
677         {
678             *(char **) data = fm->area + fm->idx;
679             
680             fm->idx += info.num;
681             if ((fitr = _FrameIterCounterIncr (fm->iters, info.num)))
682                 _FrameMgrRemoveIter (fm, fitr);
683             /*endif*/
684         }
685         else
686         {
687             *(char **) data = NULL;
688         }
689         /*endif*/
690         return FmSuccess;
691
692     case PADDING:
693         if (info.num == NO_VALUE)
694             return FmInvalidCall;
695         /*endif*/
696         fm->idx += info.num;
697         if ((fitr = _FrameIterCounterIncr (fm->iters, info.num)))
698             _FrameMgrRemoveIter (fm, fitr);
699         /*endif*/
700         return _FrameMgrGetToken (fm, data, data_size);
701
702     case ITER:
703         return FmInvalidCall;   /* if comes here, it's a bug! */
704
705     case EOL:
706         return FmEOD;
707     default:
708         break;
709     }
710     /*endswitch*/
711     return (FmStatus) NULL;  /* Should never be reached */
712 }
713
714 FmStatus FrameMgrSetSize (FrameMgr fm, int barray_size)
715 {
716     if (FrameInstSetSize (fm->fi, barray_size) == FmSuccess)
717         return FmSuccess;
718     /*endif*/
719     return FmNoMoreData;
720 }
721
722 FmStatus FrameMgrSetIterCount (FrameMgr fm, int count)
723 {
724     if (FrameInstSetIterCount (fm->fi, count) == FmSuccess)
725         return FmSuccess;
726     /*endif*/
727     return FmNoMoreData;
728 }
729
730 FmStatus FrameMgrSetTotalSize (FrameMgr fm, int total_size)
731 {
732     fm->total_size = total_size;
733     return FmSuccess;
734 }
735
736 int FrameMgrGetTotalSize (FrameMgr fm)
737 {
738     return FrameInstGetTotalSize (fm->fi);
739 }
740
741 int FrameMgrGetSize (FrameMgr fm)
742 {
743     register int ret_size;
744
745     ret_size = FrameInstGetSize (fm->fi);
746     if (ret_size == NO_VALID_FIELD)
747         return NO_VALUE;
748     /*endif*/
749     return ret_size;
750 }
751
752 FmStatus FrameMgrSkipToken (FrameMgr fm, int skip_count)
753 {
754     XimFrameType type;
755     XimFrameTypeInfoRec info;
756     register int i;
757
758     if (fm->total_size != NO_VALUE  &&  fm->idx >= fm->total_size)
759         return FmNoMoreData;
760     /*endif*/
761     for (i = 0;  i < skip_count;  i++)
762     {
763         type = FrameInstGetNextType (fm->fi, &info);
764         type &= ~COUNTER_MASK;
765
766         switch (type)
767         {
768         case BIT8:
769             fm->idx++;
770             break;
771             
772         case BIT16:
773             fm->idx += 2;
774             break;
775             
776         case BIT32:
777             fm->idx += 4;
778             break;
779             
780         case BIT64:
781             fm->idx += 8;
782             break;
783             
784         case BARRAY:
785             if (info.num == NO_VALUE)
786                 return FmInvalidCall;
787             /*endif*/
788             fm->idx += info.num;
789             break;
790             
791         case PADDING:
792             if (info.num == NO_VALUE)
793                 return FmInvalidCall;
794             /*endif*/
795             fm->idx += info.num;
796             return FrameMgrSkipToken (fm, skip_count);
797             
798         case ITER:
799             return FmInvalidCall;
800             
801         case EOL:
802             return FmEOD;
803         default:
804             break;
805         }
806         /*endswitch*/
807     }
808     /*endfor*/
809     return FmSuccess;
810 }
811
812 void FrameMgrReset (FrameMgr fm)
813 {
814     fm->idx = 0;
815     FrameInstReset (fm->fi);
816 }
817
818 Bool FrameMgrIsIterLoopEnd (FrameMgr fm, FmStatus* status)
819 {
820     do
821     {
822         if (_FrameMgrIsIterLoopEnd (fm))
823             return  True;
824         /*endif*/
825     }
826     while (_FrameMgrProcessPadding (fm, status));
827
828     return False;
829 }
830
831
832 /* Internal routines */
833
834 static Bool _FrameMgrIsIterLoopEnd (FrameMgr fm)
835 {
836     return FrameInstIsIterLoopEnd (fm->fi);
837 }
838
839 static Bool _FrameMgrProcessPadding (FrameMgr fm, FmStatus* status)
840 {
841     XimFrameTypeInfoRec info;
842     XimFrameType next_type = FrameInstPeekNextType (fm->fi, &info);
843     FrameIter fitr;
844
845     if (next_type == PADDING)
846     {
847         if (info.num == NO_VALUE)
848         {
849             *status = FmInvalidCall;
850             return True;
851         }
852         /*endif*/
853         next_type = FrameInstGetNextType (fm->fi, &info);
854         fm->idx += info.num;
855         if ((fitr = _FrameIterCounterIncr (fm->iters, info.num)))
856             _FrameMgrRemoveIter (fm, fitr);
857         /*endif*/
858         *status = FmSuccess;
859         return True;
860     }
861     /*endif*/
862     *status = FmSuccess;
863     return False;
864 }
865
866 static FrameInst FrameInstInit (XimFrame frame)
867 {
868     FrameInst fi;
869
870     fi = (FrameInst) Xmalloc (sizeof (FrameInstRec));
871
872     fi->template = frame;
873     fi->cur_no = 0;
874     ChainMgrInit (&fi->cm);
875     return fi;
876 }
877
878 static void FrameInstFree (FrameInst fi)
879 {
880     ChainIterRec ci;
881     int frame_no;
882     ExtraDataRec d;
883
884     ChainIterInit (&ci, &fi->cm);
885
886     while (ChainIterGetNext (&ci, &frame_no, &d))
887     {
888         register XimFrameType type;
889         type = fi->template[frame_no].type;
890         if (type == ITER)
891         {
892             if (d.iter)
893                 IterFree (d.iter);
894             /*endif*/
895         }
896         else if (type == POINTER)
897         {
898             if (d.fi)
899                 FrameInstFree (d.fi);
900             /*endif*/
901         }
902         /*endif*/
903     }
904     /*endwhile*/
905     ChainIterFree (&ci);
906     ChainMgrFree (&fi->cm);
907     Xfree (fi);
908 }
909
910 static XimFrameType FrameInstGetNextType(FrameInst fi, XimFrameTypeInfo info)
911 {
912     XimFrameType ret_type;
913
914     ret_type = fi->template[fi->cur_no].type;
915
916     switch (ret_type)
917     {
918     case BIT8:
919     case BIT16:
920     case BIT32:
921     case BIT64:
922     case EOL:
923         fi->cur_no = _FrameInstIncrement(fi->template, fi->cur_no);
924         break;
925
926     case COUNTER_BIT8:
927     case COUNTER_BIT16:
928     case COUNTER_BIT32:
929     case COUNTER_BIT64:
930         if (info)
931         {
932             register int offset, iter_idx;
933
934             info->counter.is_byte_len =
935                 (((long) fi->template[fi->cur_no].data & 0xFF)) == FmCounterByte;
936             offset = ((long) fi->template[fi->cur_no].data) >> 8;
937             iter_idx = fi->cur_no + offset;
938             if (fi->template[iter_idx].type == ITER)
939             {
940                 ExtraData d;
941                 ExtraDataRec dr;
942
943                 if ((d = ChainMgrGetExtraData (&fi->cm, iter_idx)) == NULL)
944                 {
945                     dr.iter = IterInit (&fi->template[iter_idx + 1], NO_VALUE);
946                     d = ChainMgrSetData (&fi->cm, iter_idx, dr);
947                 }
948                 /*endif*/
949                 info->counter.iter = d->iter;
950             }
951             else
952             {
953                 /* Should never reach here */
954             }
955             /*endif*/
956         }
957         /*endif*/
958         fi->cur_no = _FrameInstIncrement (fi->template, fi->cur_no);
959         break;
960
961     case BARRAY:
962         if (info)
963         {
964             ExtraData d;
965
966             if ((d = ChainMgrGetExtraData (&fi->cm, fi->cur_no)) == NULL)
967                 info->num = NO_VALUE;
968             else
969                 info->num = d->num;
970             /*endif*/
971         }
972         /*endif*/
973         fi->cur_no = _FrameInstIncrement (fi->template, fi->cur_no);
974         break;
975
976     case PADDING:
977         if (info)
978         {
979             register int unit;
980             register int number;
981             register int size;
982             register int i;
983
984             unit = _UNIT ((long) fi->template[fi->cur_no].data);
985             number = _NUMBER ((long) fi->template[fi->cur_no].data);
986
987             i = fi->cur_no;
988             size = 0;
989             while (number > 0)
990             {
991                 i = _FrameInstDecrement (fi->template, i);
992                 size += _FrameInstGetItemSize (fi, i);
993                 number--;
994             }
995             /*endwhile*/
996             info->num = (unit - (size%unit))%unit;
997         }
998         /*endif*/
999         fi->cur_no = _FrameInstIncrement (fi->template, fi->cur_no);
1000         break;
1001
1002     case ITER:
1003         {
1004             ExtraData d;
1005             ExtraDataRec dr;
1006             XimFrameType sub_type;
1007
1008
1009             if ((d = ChainMgrGetExtraData (&fi->cm, fi->cur_no)) == NULL)
1010             {
1011                 dr.iter = IterInit (&fi->template[fi->cur_no + 1], NO_VALUE);
1012                 d = ChainMgrSetData (&fi->cm, fi->cur_no, dr);
1013             }
1014             /*endif*/
1015             sub_type = IterGetNextType (d->iter, info);
1016             if (sub_type == EOL)
1017             {
1018                 fi->cur_no = _FrameInstIncrement (fi->template, fi->cur_no);
1019                 ret_type = FrameInstGetNextType (fi, info);
1020             }
1021             else
1022             {
1023                 ret_type = sub_type;
1024             }
1025             /*endif*/
1026         }
1027         break;
1028
1029     case POINTER:
1030         {
1031             ExtraData d;
1032             ExtraDataRec dr;
1033             XimFrameType sub_type;
1034
1035             if ((d = ChainMgrGetExtraData (&fi->cm, fi->cur_no)) == NULL)
1036             {
1037                 dr.fi = FrameInstInit (fi->template[fi->cur_no + 1].data);
1038                 d = ChainMgrSetData (&fi->cm, fi->cur_no, dr);
1039             }
1040             /*endif*/
1041             sub_type = FrameInstGetNextType (d->fi, info);
1042             if (sub_type == EOL)
1043             {
1044                 fi->cur_no = _FrameInstIncrement (fi->template, fi->cur_no);
1045                 ret_type = FrameInstGetNextType (fi, info);
1046             }
1047             else
1048             {
1049                 ret_type = sub_type;
1050             }
1051             /*endif*/
1052         }
1053         break;
1054     default:
1055         break;
1056     }
1057     /*endswitch*/
1058     return ret_type;
1059 }
1060
1061 static XimFrameType FrameInstPeekNextType (FrameInst fi, XimFrameTypeInfo info)
1062 {
1063     XimFrameType ret_type;
1064
1065     ret_type = fi->template[fi->cur_no].type;
1066
1067     switch (ret_type)
1068     {
1069     case BIT8:
1070     case BIT16:
1071     case BIT32:
1072     case BIT64:
1073     case EOL:
1074         break;
1075
1076     case COUNTER_BIT8:
1077     case COUNTER_BIT16:
1078     case COUNTER_BIT32:
1079     case COUNTER_BIT64:
1080         if (info)
1081         {
1082             register int offset;
1083             register int iter_idx;
1084
1085             info->counter.is_byte_len =
1086                 (((long) fi->template[fi->cur_no].data) & 0xFF) == FmCounterByte;
1087             offset = ((long)fi->template[fi->cur_no].data) >> 8;
1088             iter_idx = fi->cur_no + offset;
1089             if (fi->template[iter_idx].type == ITER)
1090             {
1091                 ExtraData d;
1092                 ExtraDataRec dr;
1093
1094                 if ((d = ChainMgrGetExtraData (&fi->cm, iter_idx)) == NULL)
1095                 {
1096                     dr.iter = IterInit (&fi->template[iter_idx + 1], NO_VALUE);
1097                     d = ChainMgrSetData (&fi->cm, iter_idx, dr);
1098                 }
1099                 /*endif*/
1100                 info->counter.iter = d->iter;
1101             }
1102             else
1103             {
1104                 /* Should not be reached here */
1105             }
1106             /*endif*/
1107         }
1108         /*endif*/
1109         break;
1110
1111     case BARRAY:
1112         if (info)
1113         {
1114             ExtraData d;
1115
1116             if ((d = ChainMgrGetExtraData (&fi->cm, fi->cur_no)) == NULL)
1117                 info->num = NO_VALUE;
1118             else
1119                 info->num = d->num;
1120             /*endif*/
1121         }
1122         /*endif*/
1123         break;
1124
1125     case PADDING:
1126         if (info)
1127         {
1128             register int unit;
1129             register int number;
1130             register int size;
1131             register int i;
1132
1133             unit = _UNIT ((long) fi->template[fi->cur_no].data);
1134             number = _NUMBER ((long) fi->template[fi->cur_no].data);
1135
1136             i = fi->cur_no;
1137             size = 0;
1138             while (number > 0)
1139             {
1140                 i = _FrameInstDecrement (fi->template, i);
1141                 size += _FrameInstGetItemSize (fi, i);
1142                 number--;
1143             }
1144             /*endwhile*/
1145             info->num = (unit - (size%unit))%unit;
1146         }
1147         /*endif*/
1148         break;
1149
1150     case ITER:
1151         {
1152             ExtraData d;
1153             ExtraDataRec dr;
1154             XimFrameType sub_type;
1155
1156             if ((d = ChainMgrGetExtraData (&fi->cm, fi->cur_no)) == NULL)
1157             {
1158                 dr.iter = IterInit (&fi->template[fi->cur_no + 1], NO_VALUE);
1159                 d = ChainMgrSetData (&fi->cm, fi->cur_no, dr);
1160             }
1161             /*endif*/
1162             sub_type = IterPeekNextType (d->iter, info);
1163             if (sub_type == EOL)
1164                 ret_type = FrameInstPeekNextType (fi, info);
1165             else
1166                 ret_type = sub_type;
1167             /*endif*/
1168         }
1169         break;
1170
1171     case POINTER:
1172         {
1173             ExtraData d;
1174             ExtraDataRec dr;
1175             XimFrameType sub_type;
1176
1177             if ((d = ChainMgrGetExtraData (&fi->cm, fi->cur_no)) == NULL)
1178             {
1179                 dr.fi = FrameInstInit (fi->template[fi->cur_no + 1].data);
1180                 d = ChainMgrSetData (&fi->cm, fi->cur_no, dr);
1181             }
1182             /*endif*/
1183             sub_type = FrameInstPeekNextType (d->fi, info);
1184             if (sub_type == EOL)
1185                 ret_type = FrameInstPeekNextType (fi, info);
1186             else
1187                 ret_type = sub_type;
1188             /*endif*/
1189         default:
1190             break;
1191         }
1192         break;
1193     }
1194     /*endswitch*/
1195     return ret_type;
1196 }
1197
1198 static Bool FrameInstIsIterLoopEnd (FrameInst fi)
1199 {
1200     Bool ret = False;
1201
1202     if (fi->template[fi->cur_no].type == ITER)
1203     {
1204         ExtraData d = ChainMgrGetExtraData (&fi->cm, fi->cur_no);
1205         Bool yourself;
1206
1207         if (d)
1208         {
1209             ret = IterIsLoopEnd (d->iter, &yourself);
1210             if (ret  &&  yourself)
1211                 fi->cur_no = _FrameInstIncrement (fi->template, fi->cur_no);
1212             /*endif*/
1213         }
1214         /*endif*/
1215     }
1216     /*endif*/
1217     return (ret);
1218 }
1219
1220 static FrameIter _FrameMgrAppendIter (FrameMgr fm, Iter it, int end)
1221 {
1222     FrameIter p = fm->iters;
1223
1224     while (p  &&  p->next)
1225         p = p->next;
1226     /*endwhile*/
1227     
1228     if (!p)
1229     {
1230         fm->iters =
1231         p = (FrameIter) Xmalloc (sizeof (FrameIterRec));
1232     }
1233     else
1234     {
1235         p->next = (FrameIter) Xmalloc (sizeof (FrameIterRec));
1236         p = p->next;
1237     }
1238     /*endif*/
1239     if (p)
1240     {
1241         p->iter = it;
1242         p->counting = False;
1243         p->counter = 0;
1244         p->end = end;
1245         p->next = NULL;
1246     }
1247     /*endif*/
1248     return (p);
1249 }
1250
1251 static void _FrameMgrRemoveIter (FrameMgr fm, FrameIter it)
1252 {
1253     FrameIter prev;
1254     FrameIter p;
1255
1256     prev = NULL;
1257     p = fm->iters;
1258     while (p)
1259     {
1260         if (p == it)
1261         {
1262             if (prev)
1263                 prev->next = p->next;
1264             else
1265                 fm->iters = p->next;
1266             /*endif*/
1267             Xfree (p);
1268             break;
1269         }
1270         /*endif*/
1271         prev = p;
1272         p = p->next;
1273     }
1274     /*endwhile*/
1275 }
1276
1277 static FrameIter _FrameIterCounterIncr (FrameIter fitr, int i)
1278 {
1279     FrameIter p = fitr;
1280
1281     while (p)
1282     {
1283         if (p->counting)
1284         {
1285             p->counter += i;
1286             if (p->counter >= p->end)
1287             {
1288                 IterFixIteration (p->iter);
1289                 return (p);
1290             }
1291             /*endif*/
1292         }
1293         /*endif*/
1294         p = p->next;
1295     }
1296     /*endwhile*/
1297     return (NULL);
1298 }
1299
1300 static void _IterStartWatch (Iter it, void *client_data)
1301 {
1302     FrameIter p = (FrameIter) client_data;
1303     p->counting = True;
1304 }
1305
1306 static FmStatus FrameInstSetSize (FrameInst fi, int num)
1307 {
1308     ExtraData d;
1309     ExtraDataRec dr;
1310     XimFrameType type;
1311     register int i;
1312
1313     i = 0;
1314     while ((type = fi->template[i].type) != EOL)
1315     {
1316         switch (type)
1317         {
1318         case BARRAY:
1319             if ((d = ChainMgrGetExtraData (&fi->cm, i)) == NULL)
1320             {
1321                 dr.num = -1;
1322                 d = ChainMgrSetData (&fi->cm, i, dr);
1323             }
1324             /*endif*/
1325             if (d->num == NO_VALUE)
1326             {
1327                 d->num = num;
1328                 return FmSuccess;
1329             }
1330             /*endif*/
1331             break;
1332         case ITER:
1333             if ((d = ChainMgrGetExtraData (&fi->cm, i)) == NULL)
1334             {
1335                 dr.iter = IterInit (&fi->template[i + 1], NO_VALUE);
1336                 d = ChainMgrSetData (&fi->cm, i, dr);
1337             }
1338             /*endif*/
1339             if (IterSetSize (d->iter, num) == FmSuccess)
1340                 return FmSuccess;
1341             /*endif*/
1342             break;
1343             
1344         case POINTER:
1345             if ((d = ChainMgrGetExtraData(&fi->cm, i)) == NULL)
1346             {
1347                 dr.fi = FrameInstInit(fi->template[i + 1].data);
1348                 d = ChainMgrSetData(&fi->cm, i, dr);
1349             }
1350             /*endif*/
1351             if (FrameInstSetSize(d->fi, num) == FmSuccess)
1352                 return FmSuccess;
1353             /*endif*/
1354             break;
1355         default:
1356             break;
1357         }
1358         /*endswitch*/
1359         i = _FrameInstIncrement(fi->template, i);
1360     }
1361     /*endwhile*/
1362     return FmNoMoreData;
1363 }
1364
1365 static int FrameInstGetSize (FrameInst fi)
1366 {
1367     XimFrameType type;
1368     register int i;
1369     ExtraData d;
1370     ExtraDataRec dr;
1371     int ret_size;
1372
1373     i = fi->cur_no;
1374     while ((type = fi->template[i].type) != EOL)
1375     {
1376         switch (type)
1377         {
1378         case BARRAY:
1379             if ((d = ChainMgrGetExtraData (&fi->cm, i)) == NULL)
1380                 return NO_VALUE;
1381             /*endif*/
1382             return d->num;
1383
1384         case ITER:
1385             if ((d = ChainMgrGetExtraData (&fi->cm, i)) == NULL)
1386             {
1387                 dr.iter = IterInit (&fi->template[i + 1], NO_VALUE);
1388                 d = ChainMgrSetData (&fi->cm, i, dr);
1389             }
1390             /*endif*/
1391             ret_size = IterGetSize(d->iter);
1392             if (ret_size != NO_VALID_FIELD)
1393                 return ret_size;
1394             /*endif*/
1395             break;
1396             
1397         case POINTER:
1398             if ((d = ChainMgrGetExtraData (&fi->cm, i)) == NULL)
1399             {
1400                 dr.fi = FrameInstInit (fi->template[i + 1].data);
1401                 d = ChainMgrSetData (&fi->cm, i, dr);
1402             }
1403             /*endif*/
1404             ret_size = FrameInstGetSize (d->fi);
1405             if (ret_size != NO_VALID_FIELD)
1406                 return ret_size;
1407             /*endif*/
1408             break;
1409         default:
1410             break;
1411         }
1412         /*endswitch*/
1413         i = _FrameInstIncrement (fi->template, i);
1414     }
1415     /*endwhile*/
1416     return NO_VALID_FIELD;
1417 }
1418
1419 static FmStatus FrameInstSetIterCount (FrameInst fi, int num)
1420 {
1421     ExtraData d;
1422     ExtraDataRec dr;
1423     register int i;
1424     XimFrameType type;
1425
1426     i = 0;
1427     while ((type = fi->template[i].type) != EOL)
1428     {
1429         switch (type)
1430         {
1431         case ITER:
1432             if ((d = ChainMgrGetExtraData (&fi->cm, i)) == NULL)
1433             {
1434                 dr.iter = IterInit (&fi->template[i + 1], num);
1435                 (void)ChainMgrSetData (&fi->cm, i, dr);
1436                 return FmSuccess;
1437             }
1438             /*endif*/
1439             if (IterSetIterCount (d->iter, num) == FmSuccess)
1440                 return FmSuccess;
1441             /*endif*/
1442             break;
1443             
1444         case POINTER:
1445             if ((d = ChainMgrGetExtraData (&fi->cm, i)) == NULL)
1446             {
1447                 dr.fi = FrameInstInit (fi->template[i + 1].data);
1448                 d = ChainMgrSetData (&fi->cm, i, dr);
1449             }
1450             /*endif*/
1451             if (FrameInstSetIterCount (d->fi, num) == FmSuccess)
1452                 return FmSuccess;
1453             /*endif*/
1454             break;
1455
1456         default:
1457             break;
1458         }
1459         /*endswitch*/
1460         i = _FrameInstIncrement (fi->template, i);
1461     }
1462     /*endwhile*/
1463     return FmNoMoreData;
1464 }
1465
1466 static int FrameInstGetTotalSize (FrameInst fi)
1467 {
1468     register int size;
1469     register int i;
1470
1471     size = 0;
1472     i = 0;
1473
1474     while (fi->template[i].type != EOL)
1475     {
1476         size += _FrameInstGetItemSize (fi, i);
1477         i = _FrameInstIncrement (fi->template, i);
1478     }
1479     /*endwhile*/
1480     return size;
1481 }
1482
1483 static void FrameInstReset (FrameInst fi)
1484 {
1485     ChainIterRec ci;
1486     int frame_no;
1487     ExtraDataRec d;
1488
1489     ChainIterInit (&ci, &fi->cm);
1490
1491     while (ChainIterGetNext (&ci, &frame_no, &d))
1492     {
1493         register XimFrameType type;
1494         type = fi->template[frame_no].type;
1495         if (type == ITER)
1496         {
1497             if (d.iter)
1498                 IterReset (d.iter);
1499             /*endif*/
1500         }
1501         else if (type == POINTER)
1502         {
1503             if (d.fi)
1504                 FrameInstReset (d.fi);
1505             /*endif*/
1506         }
1507         /*endif*/
1508     }
1509     /*endwhile*/
1510     ChainIterFree (&ci);
1511
1512     fi->cur_no = 0;
1513 }
1514
1515 static Iter IterInit (XimFrame frame, int count)
1516 {
1517     Iter it;
1518     register XimFrameType type;
1519
1520     it = (Iter) Xmalloc (sizeof (IterRec));
1521     it->template = frame;
1522     it->max_count = (count == NO_VALUE)  ?  0  :  count;
1523     it->allow_expansion = (count == NO_VALUE);
1524     it->cur_no = 0;
1525     it->start_watch_proc = NULL;
1526     it->client_data = NULL;
1527     it->start_counter = False;
1528
1529     type = frame->type;
1530     if (type & COUNTER_MASK)
1531     {
1532         /* COUNTER_XXX cannot be an item of a ITER */
1533         Xfree (it);
1534         return NULL;
1535     }
1536     /*endif*/
1537
1538     switch (type)
1539     {
1540     case BIT8:
1541     case BIT16:
1542     case BIT32:
1543     case BIT64:
1544         /* Do nothing */
1545         break;
1546         
1547     case BARRAY:
1548     case ITER:
1549     case POINTER:
1550         ChainMgrInit (&it->cm);
1551         break;
1552         
1553     default:
1554         Xfree (it);
1555         return NULL; /* This should never occur */
1556     }
1557     /*endswitch*/
1558     return it;
1559 }
1560
1561 static void IterFree (Iter it)
1562 {
1563     switch (it->template->type)
1564     {
1565     case BARRAY:
1566         ChainMgrFree (&it->cm);
1567         break;
1568     
1569     case ITER:
1570         {
1571             ChainIterRec ci;
1572             int count;
1573             ExtraDataRec d;
1574
1575             ChainIterInit (&ci, &it->cm);
1576             while (ChainIterGetNext (&ci, &count, &d))
1577                 IterFree (d.iter);
1578             /*endwhile*/
1579             ChainIterFree (&ci);
1580             ChainMgrFree (&it->cm);
1581         }
1582         break;
1583     
1584     case POINTER:
1585         {
1586             ChainIterRec ci;
1587             int count;
1588             ExtraDataRec dr;
1589     
1590             ChainIterInit (&ci, &it->cm);
1591             while (ChainIterGetNext (&ci, &count, &dr))
1592                 FrameInstFree (dr.fi);
1593             /*endwhile*/
1594             ChainIterFree (&ci);
1595             ChainMgrFree (&it->cm);
1596         }
1597         break;
1598
1599     default:
1600         break;
1601     }
1602     /*endswitch*/
1603     Xfree (it);
1604 }
1605
1606 static Bool IterIsLoopEnd (Iter it, Bool *myself)
1607 {
1608     Bool ret = False;
1609     *myself = False;
1610
1611     if (!it->allow_expansion  &&  (it->cur_no == it->max_count))
1612     {
1613         *myself = True;
1614         return True;
1615     }
1616     /*endif*/
1617     
1618     if (it->template->type == POINTER)
1619     {
1620         ExtraData d = ChainMgrGetExtraData (&it->cm, it->cur_no);
1621         if (d)
1622         {
1623             if (FrameInstIsIterLoopEnd (d->fi))
1624             {
1625                 ret = True;
1626             }
1627             else
1628             {
1629                 if (FrameInstIsEnd (d->fi))
1630                 {
1631                     it->cur_no++;
1632                     if (!it->allow_expansion  &&  it->cur_no == it->max_count)
1633                     {
1634                         *myself = True;
1635                         ret = True;
1636                     }
1637                     /*endif*/
1638                 }
1639                 /*endif*/
1640             }
1641             /*endif*/
1642         }
1643         /*endif*/
1644     }
1645     else if (it->template->type == ITER)
1646     {
1647         ExtraData d = ChainMgrGetExtraData (&it->cm, it->cur_no);
1648         if (d)
1649         {
1650             Bool yourself;
1651             
1652             if (IterIsLoopEnd (d->iter, &yourself))
1653                 ret = True;
1654             /*endif*/
1655         }
1656         /*endif*/
1657     }
1658     /*endif*/
1659
1660     return ret;
1661 }
1662
1663 static XimFrameType IterGetNextType (Iter it, XimFrameTypeInfo info)
1664 {
1665     XimFrameType type = it->template->type;
1666
1667     if (it->start_counter)
1668     {
1669         (*it->start_watch_proc) (it, it->client_data);
1670         it->start_counter = False;
1671     }
1672     /*endif*/
1673     if (it->cur_no >= it->max_count)
1674     {
1675         if (it->allow_expansion)
1676             it->max_count = it->cur_no + 1;
1677         else
1678             return EOL;
1679         /*endif*/
1680     }
1681     /*endif*/
1682
1683     switch (type)
1684     {
1685     case BIT8:
1686     case BIT16:
1687     case BIT32:
1688     case BIT64:
1689         it->cur_no++;
1690         return type;
1691
1692     case BARRAY:
1693         if (info)
1694         {
1695             ExtraData d;
1696     
1697             if ((d = ChainMgrGetExtraData (&it->cm, it->cur_no)) == NULL)
1698                 info->num = NO_VALUE;
1699             else
1700                 info->num = d->num;
1701             /*endif*/
1702         }
1703         /*endif*/
1704         it->cur_no++;
1705         return BARRAY;
1706
1707     case ITER:
1708         {
1709             XimFrameType ret_type;
1710             ExtraData d;
1711             ExtraDataRec dr;
1712
1713             if ((d = ChainMgrGetExtraData (&it->cm, it->cur_no)) == NULL)
1714             {
1715                 dr.iter = IterInit (it->template + 1, NO_VALUE);
1716                 d = ChainMgrSetData (&it->cm, it->cur_no, dr);
1717             }
1718             /*endif*/
1719
1720             ret_type = IterGetNextType (d->iter, info);
1721             if (ret_type == EOL)
1722             {
1723                 it->cur_no++;
1724                 ret_type = IterGetNextType (it, info);
1725             }
1726             /*endif*/
1727             return ret_type;
1728         }
1729
1730     case POINTER:
1731         {
1732             XimFrameType ret_type;
1733             ExtraData d;
1734             ExtraDataRec dr;
1735
1736             if ((d = ChainMgrGetExtraData (&it->cm, it->cur_no)) == NULL)
1737             {
1738                 dr.fi = FrameInstInit (it->template[1].data);
1739                 d = ChainMgrSetData (&it->cm, it->cur_no, dr);
1740             }
1741             /*endif*/
1742
1743             ret_type = FrameInstGetNextType (d->fi, info);
1744             if (ret_type == EOL)
1745             {
1746                 it->cur_no++;
1747                 ret_type = IterGetNextType (it, info);
1748             }
1749             /*endif*/
1750             return ret_type;
1751         }
1752
1753     default:
1754         return (XimFrameType) NULL;
1755     }
1756     /*endswitch*/
1757     return (XimFrameType) NULL;  /* This should never occur */
1758 }
1759
1760 static XimFrameType IterPeekNextType (Iter it, XimFrameTypeInfo info)
1761 {
1762     XimFrameType type = it->template->type;
1763
1764     if (!it->allow_expansion  &&  it->cur_no >= it->max_count)
1765         return (EOL);
1766     /*endif*/
1767     
1768     switch (type)
1769     {
1770     case BIT8:
1771     case BIT16:
1772     case BIT32:
1773     case BIT64:
1774         return type;
1775
1776     case BARRAY:
1777         if (info)
1778         {
1779             ExtraData d;
1780
1781             if ((d = ChainMgrGetExtraData (&it->cm, it->cur_no)) == NULL)
1782                 info->num = NO_VALUE;
1783             else
1784                 info->num = d->num;
1785             /*endif*/
1786         }
1787         /*endif*/
1788         return BARRAY;
1789     
1790     case ITER:
1791         {
1792             XimFrameType ret_type;
1793             ExtraData d;
1794             ExtraDataRec dr;
1795
1796             if ((d = ChainMgrGetExtraData (&it->cm, it->cur_no)) == NULL)
1797             {
1798                 dr.iter = IterInit (it->template + 1, NO_VALUE);
1799                 d = ChainMgrSetData (&it->cm, it->cur_no, dr);
1800             }
1801             /*endif*/
1802
1803             ret_type = IterPeekNextType (d->iter, info);
1804             if (ret_type == EOL)
1805                 ret_type = IterPeekNextType (it, info);
1806             /*endif*/
1807             return ret_type;
1808         }
1809         
1810     case POINTER:
1811         {
1812             XimFrameType ret_type;
1813             ExtraData d;
1814             ExtraDataRec dr;
1815
1816             if ((d = ChainMgrGetExtraData (&it->cm, it->cur_no)) == NULL)
1817             {
1818                 dr.fi = FrameInstInit (it->template[1].data);
1819                 d = ChainMgrSetData (&it->cm, it->cur_no, dr);
1820             }
1821             /*endif*/
1822
1823             ret_type = FrameInstPeekNextType (d->fi, info);
1824             if (ret_type == EOL)
1825                 ret_type = IterPeekNextType (it, info);
1826             /*endif*/
1827             return (ret_type);
1828         }
1829
1830     default:
1831         break;
1832     }
1833     /*endswitch*/
1834     /* Reaching here is a bug! */
1835     return (XimFrameType) NULL;
1836 }
1837
1838 static FmStatus IterSetSize (Iter it, int num)
1839 {
1840     XimFrameType type;
1841     register int i;
1842
1843     if (!it->allow_expansion  &&  it->max_count == 0)
1844         return FmNoMoreData;
1845     /*endif*/
1846     
1847     type = it->template->type;
1848     switch (type)
1849     {
1850     case BARRAY:
1851         {
1852             ExtraData d;
1853             ExtraDataRec dr;
1854
1855             for (i = 0;  i < it->max_count;  i++)
1856             {
1857                 if ((d = ChainMgrGetExtraData (&it->cm, i)) == NULL)
1858                 {
1859                     dr.num = NO_VALUE;
1860                     d = ChainMgrSetData (&it->cm, i, dr);
1861                 }
1862                 /*endif*/
1863                 if (d->num == NO_VALUE)
1864                 {
1865                     d->num = num;
1866                     return FmSuccess;
1867                 }
1868                 /*endif*/
1869             }
1870             /*endfor*/
1871             if (it->allow_expansion)
1872             {
1873                 ExtraDataRec dr;
1874                 
1875                 dr.num = num;
1876                 ChainMgrSetData (&it->cm, it->max_count, dr);
1877                 it->max_count++;
1878     
1879                 return FmSuccess;
1880             }
1881             /*endif*/
1882         }   
1883         return FmNoMoreData;
1884
1885     case ITER:
1886         {
1887             ExtraData d;
1888             ExtraDataRec dr;
1889
1890             for (i = 0;  i < it->max_count;  i++)
1891             {
1892                 if ((d = ChainMgrGetExtraData (&it->cm, i)) == NULL)
1893                 {
1894                     dr.iter = IterInit (it->template + 1, NO_VALUE);
1895                     d = ChainMgrSetData (&it->cm, i, dr);
1896                 }
1897                 /*endif*/
1898                 if (IterSetSize (d->iter, num) == FmSuccess)
1899                     return FmSuccess;
1900                 /*endif*/
1901             }
1902             /*endfor*/
1903             if (it->allow_expansion)
1904             {
1905                 ExtraDataRec dr;
1906
1907                 dr.iter = IterInit (it->template + 1, NO_VALUE);
1908                 ChainMgrSetData (&it->cm, it->max_count, dr);
1909                 it->max_count++;
1910
1911                 if (IterSetSize(dr.iter, num) == FmSuccess)
1912                     return FmSuccess;
1913                 /*endif*/
1914             }
1915             /*endif*/
1916         }
1917         return FmNoMoreData;
1918
1919     case POINTER:
1920         {
1921             ExtraData d;
1922             ExtraDataRec dr;
1923
1924             for (i = 0;  i < it->max_count;  i++)
1925             {
1926                 if ((d = ChainMgrGetExtraData (&it->cm, i)) == NULL)
1927                 {
1928                     dr.fi = FrameInstInit (it->template[1].data);
1929                     d = ChainMgrSetData (&it->cm, i, dr);
1930                 }
1931                 /*endif*/
1932                 if (FrameInstSetSize (d->fi, num) == FmSuccess)
1933                     return FmSuccess;
1934                 /*endif*/
1935             }
1936             /*endfor*/
1937             if (it->allow_expansion)
1938             {
1939                 ExtraDataRec dr;
1940
1941                 dr.fi = FrameInstInit (it->template[1].data);
1942                 ChainMgrSetData (&it->cm, it->max_count, dr);
1943                 it->max_count++;
1944
1945                 if (FrameInstSetSize (dr.fi, num) == FmSuccess)
1946                     return FmSuccess;
1947                 /*endif*/
1948             }
1949             /*endif*/
1950         }
1951         return FmNoMoreData;
1952
1953     default:
1954         break;
1955     }
1956     /*endswitch*/
1957     return FmNoMoreData;
1958 }
1959
1960 static int IterGetSize (Iter it)
1961 {
1962     register int i;
1963     ExtraData d;
1964     ExtraDataRec dr;
1965
1966     if (it->cur_no >= it->max_count)
1967         return NO_VALID_FIELD;
1968     /*endif*/
1969     
1970     switch (it->template->type)
1971     {
1972     case BARRAY:
1973         if ((d = ChainMgrGetExtraData (&it->cm, it->cur_no)) == NULL)
1974             return NO_VALUE;
1975         /*endif*/
1976         return d->num;
1977
1978     case ITER:
1979         for (i = it->cur_no; i < it->max_count; i++)
1980         {
1981             int ret_size;
1982
1983             if ((d = ChainMgrGetExtraData (&it->cm, i)) == NULL)
1984             {
1985                 dr.iter = IterInit (it->template + 1, NO_VALUE);
1986                 d = ChainMgrSetData (&it->cm, i, dr);
1987             }
1988             /*endif*/
1989             ret_size = IterGetSize (d->iter);
1990             if (ret_size != NO_VALID_FIELD)
1991                 return ret_size;
1992             /*endif*/
1993         }
1994         /*endfor*/
1995         return NO_VALID_FIELD;
1996     
1997     case POINTER:
1998         for (i = it->cur_no;  i < it->max_count;  i++)
1999         {
2000             int ret_size;
2001             
2002             if ((d = ChainMgrGetExtraData (&it->cm, i)) == NULL)
2003             {
2004                 dr.fi = FrameInstInit (it->template[1].data);
2005                 d = ChainMgrSetData (&it->cm, i, dr);
2006             }
2007             /*endif*/
2008             ret_size = FrameInstGetSize (d->fi);
2009             if (ret_size != NO_VALID_FIELD)
2010                 return ret_size;
2011             /*endif*/
2012         }
2013         /*endfor*/
2014         return NO_VALID_FIELD;
2015
2016     default:
2017         break;
2018     }
2019     /*endswitch*/
2020     return NO_VALID_FIELD;
2021 }
2022
2023 static FmStatus IterSetIterCount (Iter it, int num)
2024 {
2025     register int i;
2026
2027     if (it->allow_expansion)
2028     {
2029         it->max_count = num;
2030         it->allow_expansion = False;
2031         return FmSuccess;
2032     }
2033     /*endif*/
2034
2035     if (it->max_count == 0)
2036         return FmNoMoreData;
2037     /*endif*/
2038
2039     switch (it->template->type)
2040     {
2041     case ITER:
2042         for (i = 0;  i < it->max_count;  i++)
2043         {
2044             ExtraData d;
2045             ExtraDataRec dr;
2046
2047             if ((d = ChainMgrGetExtraData(&it->cm, i)) == NULL)
2048             {
2049                 dr.iter = IterInit(it->template + 1, num);
2050                 (void)ChainMgrSetData(&it->cm, i, dr);
2051                 return FmSuccess;
2052             }
2053             /*endif*/
2054             if (IterSetIterCount(d->iter, num) == FmSuccess)
2055                 return FmSuccess;
2056             /*endif*/
2057         }
2058         /*endfor*/
2059         if (it->allow_expansion)
2060         {
2061             ExtraDataRec dr;
2062
2063             dr.iter = IterInit (it->template + 1, num);
2064             ChainMgrSetData (&it->cm, it->max_count, dr);
2065             it->max_count++;
2066
2067             return FmSuccess;
2068         }
2069         /*endif*/
2070         break;
2071     
2072     case POINTER:
2073         for (i = 0;  i < it->max_count;  i++)
2074         {
2075             ExtraData d;
2076             ExtraDataRec dr;
2077             
2078             if ((d = ChainMgrGetExtraData (&it->cm, i)) == NULL)
2079             {
2080                 dr.fi = FrameInstInit (it->template[1].data);
2081                 d = ChainMgrSetData (&it->cm, i, dr);
2082             }
2083             /*endif*/
2084             if (FrameInstSetIterCount (d->fi, num) == FmSuccess)
2085                 return FmSuccess;
2086             /*endif*/
2087         }
2088         /*endfor*/
2089         if (it->allow_expansion)
2090         {
2091             ExtraDataRec dr;
2092             
2093             dr.fi = FrameInstInit (it->template[1].data);
2094             ChainMgrSetData (&it->cm, it->max_count, dr);
2095             it->max_count++;
2096
2097             if (FrameInstSetIterCount (dr.fi, num) == FmSuccess)
2098                 return FmSuccess;
2099             /*endif*/
2100         }
2101         /*endif*/
2102         break;
2103
2104     default:
2105         break;
2106     }
2107     /*endswitch*/
2108     return FmNoMoreData;
2109 }
2110
2111 static int IterGetTotalSize (Iter it)
2112 {
2113     register int size, i;
2114     XimFrameType type;
2115
2116     if (it->allow_expansion)
2117         return NO_VALUE;
2118     /*endif*/
2119     if (it->max_count == 0)
2120         return 0;
2121     /*endif*/
2122
2123     size = 0;
2124     type = it->template->type;
2125
2126     switch (type)
2127     {
2128     case BIT8:
2129         size = it->max_count;
2130         break;
2131
2132     case BIT16:
2133         size = it->max_count*2;
2134         break;
2135
2136     case BIT32:
2137         size = it->max_count*4;
2138         break;
2139
2140     case BIT64:
2141         size = it->max_count*8;
2142         break;
2143
2144     case BARRAY:
2145         for (i = 0;  i < it->max_count;  i++)
2146         {
2147             register int num;
2148             ExtraData d;
2149             
2150             if ((d = ChainMgrGetExtraData (&it->cm, i)) == NULL)
2151                 return  NO_VALUE;
2152             /*endif*/
2153             if ((num = d->num) == NO_VALUE)
2154                 return  NO_VALUE;
2155             /*endif*/
2156             size += num;
2157         }
2158         /*endfor*/
2159         break;
2160         
2161     case ITER:
2162         for (i = 0;  i < it->max_count;  i++)
2163         {
2164             register int num;
2165             ExtraData d;
2166             
2167             if ((d = ChainMgrGetExtraData (&it->cm, i)) == NULL)
2168                 return  NO_VALUE;
2169             /*endif*/
2170             if ((num = IterGetTotalSize (d->iter)) == NO_VALUE)
2171                 return  NO_VALUE;
2172             /*endif*/
2173             size += num;
2174         }
2175         /*endfor*/
2176         break;
2177         
2178     case POINTER:
2179         for (i = 0;  i < it->max_count;  i++)
2180         {
2181             register int num;
2182             ExtraData d;
2183             ExtraDataRec dr;
2184             
2185             if ((d = ChainMgrGetExtraData (&it->cm, i)) == NULL)
2186             {
2187                 dr.fi = FrameInstInit (it->template[1].data);
2188                 d = ChainMgrSetData (&it->cm, i, dr);
2189             }
2190             /*endif*/
2191             if ((num = FrameInstGetTotalSize (d->fi)) == NO_VALUE)
2192                 return NO_VALUE;
2193             /*endif*/
2194             size += num;
2195         }
2196         /*endfor*/
2197         break;
2198
2199     default:
2200         break;
2201     }
2202     /*endswitch*/
2203     return  size;
2204 }
2205
2206 static void IterReset (Iter it)
2207 {
2208     ChainIterRec ci;
2209     int count;
2210     ExtraDataRec d;
2211
2212     switch (it->template->type)
2213     {
2214     case ITER:
2215         ChainIterInit (&ci, &it->cm);
2216         while (ChainIterGetNext (&ci, &count, &d))
2217             IterReset (d.iter);
2218         /*endwhile*/
2219         ChainIterFree (&ci);
2220         break;
2221   
2222     case POINTER:
2223         ChainIterInit (&ci, &it->cm);
2224         while (ChainIterGetNext (&ci, &count, &d))
2225             FrameInstReset (d.fi);
2226         /*endwhile*/
2227         ChainIterFree (&ci);
2228         break;
2229
2230     default:
2231         break;
2232     }
2233     /*endswitch*/
2234     it->cur_no = 0;
2235 }
2236
2237 static void IterSetStartWatch (Iter it,
2238                                IterStartWatchProc proc,
2239                                void *client_data)
2240 {
2241     it->start_watch_proc = proc;
2242     it->client_data = client_data;
2243 }
2244
2245 static ExtraData ChainMgrSetData (ChainMgr cm,
2246                                   int frame_no,
2247                                   ExtraDataRec data)
2248 {
2249     Chain cur = (Chain) Xmalloc (sizeof (ChainRec));
2250
2251     cur->frame_no = frame_no;
2252     cur->d = data;
2253     cur->next = NULL;
2254
2255     if (cm->top == NULL)
2256     {
2257         cm->top = cm->tail = cur;
2258     }
2259     else
2260     {
2261         cm->tail->next = cur;
2262         cm->tail = cur;
2263     }
2264     /*endif*/
2265     return &cur->d;
2266 }
2267
2268 static ExtraData ChainMgrGetExtraData (ChainMgr cm, int frame_no)
2269 {
2270     Chain cur;
2271
2272     cur = cm->top;
2273
2274     while (cur)
2275     {
2276         if (cur->frame_no == frame_no)
2277             return &cur->d;
2278         /*endif*/
2279         cur = cur->next;
2280     }
2281     /*endwhile*/
2282     return NULL;
2283 }
2284
2285 static Bool ChainIterGetNext (ChainIter ci, int *frame_no, ExtraData d)
2286 {
2287     if (ci->cur == NULL)
2288         return False;
2289     /*endif*/
2290     
2291     *frame_no = ci->cur->frame_no;
2292     *d = ci->cur->d;
2293
2294     ci->cur = ci->cur->next;
2295
2296     return True;
2297 }
2298
2299 static int _FrameInstIncrement (XimFrame frame, int count)
2300 {
2301     XimFrameType type;
2302
2303     type = frame[count].type;
2304     type &= ~COUNTER_MASK;
2305
2306     switch (type)
2307     {
2308     case BIT8:
2309     case BIT16:
2310     case BIT32:
2311     case BIT64:
2312     case BARRAY:
2313     case PADDING:
2314         return count + 1;
2315         
2316     case POINTER:
2317         return count + 2;
2318         
2319     case ITER:
2320         return _FrameInstIncrement (frame, count + 1);
2321     default:
2322         break;
2323     }
2324     /*endswitch*/
2325     return - 1;    /* Error */
2326 }
2327
2328 static int _FrameInstDecrement (XimFrame frame, int count)
2329 {
2330     register int i;
2331     XimFrameType type;
2332
2333     if (count == 0)
2334         return - 1;    /* cannot decrement */
2335     /*endif*/
2336     
2337     if (count == 1)
2338         return 0;     /* BOGUS - It should check the contents of data */
2339     /*endif*/
2340     
2341     type = frame[count - 2].type;
2342     type &= ~COUNTER_MASK;
2343
2344     switch (type)
2345     {
2346     case BIT8:
2347     case BIT16:
2348     case BIT32:
2349     case BIT64:
2350     case BARRAY:
2351     case PADDING:
2352     case PTR_ITEM:
2353         return count - 1;
2354
2355     case POINTER:
2356     case ITER:
2357         i = count - 3;
2358         while (i >= 0)
2359         {
2360             if (frame[i].type != ITER)
2361                 return i + 1;
2362             /*endif*/
2363             i--;
2364         }
2365         /*endwhile*/
2366         return 0;
2367     default:
2368         break;
2369     }
2370     /*enswitch*/
2371     return - 1;    /* Error */
2372 }
2373
2374 static int _FrameInstGetItemSize (FrameInst fi, int cur_no)
2375 {
2376     XimFrameType type;
2377
2378     type = fi->template[cur_no].type;
2379     type &= ~COUNTER_MASK;
2380
2381     switch (type)
2382     {
2383     case BIT8:
2384         return 1;
2385
2386     case BIT16:
2387         return 2;
2388
2389     case BIT32:
2390         return 4;
2391
2392     case BIT64:
2393         return 8;
2394
2395     case BARRAY:
2396         {
2397             ExtraData d;
2398
2399             if ((d = ChainMgrGetExtraData (&fi->cm, cur_no)) == NULL)
2400                 return NO_VALUE;
2401             /*endif*/
2402             if (d->num == NO_VALUE)
2403                 return NO_VALUE;
2404             /*endif*/
2405             return d->num;
2406         }
2407
2408     case PADDING:
2409         {
2410             register int unit;
2411             register int number;
2412             register int size;
2413             register int i;
2414
2415             unit = _UNIT ((long) fi->template[cur_no].data);
2416             number = _NUMBER ((long) fi->template[cur_no].data);
2417
2418             i = cur_no;
2419             size = 0;
2420             while (number > 0)
2421             {
2422                 i = _FrameInstDecrement (fi->template, i);
2423                 size += _FrameInstGetItemSize (fi, i);
2424                 number--;
2425             }
2426             /*endwhile*/
2427             size = (unit - (size%unit))%unit;
2428             return size;
2429         }
2430
2431     case ITER:
2432         {
2433             ExtraData d;
2434             int sub_size;
2435
2436             if ((d = ChainMgrGetExtraData (&fi->cm, cur_no)) == NULL)
2437                 return NO_VALUE;
2438             /*endif*/
2439             sub_size = IterGetTotalSize (d->iter);
2440             if (sub_size == NO_VALUE)
2441                 return NO_VALUE;
2442             /*endif*/
2443             return sub_size;
2444         }
2445
2446     case POINTER:
2447         {
2448             ExtraData d;
2449             int sub_size;
2450
2451             if ((d = ChainMgrGetExtraData (&fi->cm, cur_no)) == NULL)
2452                 return NO_VALUE;
2453             /*endif*/
2454             sub_size = FrameInstGetTotalSize (d->fi);
2455             if (sub_size == NO_VALUE)
2456                 return NO_VALUE;
2457             /*endif*/
2458             return sub_size;
2459         }
2460
2461     default:
2462         break;
2463     }
2464     /*endswitch*/
2465     return NO_VALUE;
2466 }