0022337: V3d_View::Print crashes in OCCT 6.5.0
[occt.git] / src / OpenGl / OpenGl_tsm.cxx
1 /***********************************************************************
2
3 FONCTION :
4 ----------
5 File OpenGl_togl_texture.c :
6
7
8 REMARQUES:
9 ---------- 
10
11
12 HISTORIQUE DES MODIFICATIONS   :
13 --------------------------------
14 05-08-97 : PCT ; Support texture mapping
15 ajout pour deuxieme passe du texture mapping
16
17 ************************************************************************/
18
19 #define G003  /* EUG 16-09-99 ZBufferAuto treatment
20 */
21
22 /*----------------------------------------------------------------------*/
23 /*
24 * Includes
25 */
26
27 #include <OpenGl_tgl_all.hxx>
28
29 #include <stddef.h>
30 #include <stdio.h>
31
32 #include <OpenGl_cmn_varargs.hxx>
33 #include <OpenGl_tsm.hxx>
34 #include <OpenGl_tsm_ws.hxx>
35 #include <OpenGl_Memory.hxx>
36
37 static  MtblPtr   TsmMtblArray[TelLast];
38
39 /* Fixed Header info for a structure */
40 struct  TSM_HEAD_STRUCT
41 {
42   Tint    num;               /* number of elements present */
43 };
44 typedef TSM_HEAD_STRUCT  TSM_HEAD;
45 typedef TSM_HEAD_STRUCT* tsm_head;
46
47 /* The head of the list when the structure is in the form of a list */
48 struct  TSM_LHEAD_STRUCT
49 {
50   tsm_node  next; // first list node
51   tsm_node  prev; // last list node for reverse iteration
52   TSM_HEAD  header;
53 };
54 typedef TSM_LHEAD_STRUCT  TSM_LHEAD;
55 typedef TSM_LHEAD_STRUCT *tsm_lhead;
56
57 /* A Structure having fixed header and variable list of elements */
58 struct  TSM_STRUCT_STRUCT
59 {
60   TSM_LHEAD elemListHead;
61   IMPLEMENT_MEMORY_OPERATORS
62 };
63 typedef TSM_STRUCT_STRUCT  TSM_STRUCT;
64 typedef TSM_STRUCT_STRUCT *tsm_struct;
65
66 #define    TsmStructureNotOpen      -1
67 #define    TsmInvalidStructure      -1
68
69 /* Context maintained for the currently open structure */
70 struct  TSM_CONTEXT_STRUCT
71 {
72   Tint     stid;   /* Current  Open Structure */
73   Tint      ind;   /* Current  Element Index  */
74   /* = TsmStructureNotOpen if no structure currently open */
75   tsm_struct  s;   /* Current  Structure Pointer */
76   tsm_node    n;   /* Current  Element list node */
77 };
78 typedef TSM_CONTEXT_STRUCT  TSM_CONTEXT;
79 typedef TSM_CONTEXT_STRUCT* tsm_context;
80
81 static  TSM_CONTEXT   context = { TsmInvalidStructure, TsmStructureNotOpen, 0, 0 };
82
83 static  TEditMode     edit_mode;
84
85 #define  TSM_HTBL_SIZE  251
86 typedef NCollection_List<TSM_NODE*> NodeList;
87 typedef NCollection_DataMap<Tint, TSM_STRUCT*> StructMap;
88 Handle(NCollection_BaseAllocator)  _Allocator = NCollection_BaseAllocator::CommonBaseAllocator();
89 static StructMap _StructMap( 1, _Allocator );
90
91
92
93 /* Global workstation variable */
94 Tint    TglActiveWs;        /* valid only during traversals */
95
96 void
97 TsmInitAllClasses( MtblPtr  (**tbl)(TelType*), Tint size )
98 {
99   register  Tint  i;
100   TelType   el;
101   register  MtblPtr   fp;
102
103   for( i=0; i<size; i++ )
104   {
105     fp = tbl[i](&el);
106     TsmMtblArray[el] = fp;
107   }
108   return;
109 }
110
111 /* This function invokes the required method of the element type by looking
112 up an array of Method Tables of each element.
113 The arguments passed to the method are the data of the element and any
114 other data that needs to be sent.
115 In the case of ADD_TO_STRUCTURE methods, data should be the address of the
116 element data. Other wise, it is the element data itself
117 */
118
119 TStatus
120 TsmSendMessage( TelType el, TMsgType msg, TSM_ELEM_DATA data, Tint n, ... )
121 {
122 #if defined (SOLARIS) || defined (IRIXO32)
123   cmn_key  *k;
124 #else
125   cmn_key  k[TMaxArgs];
126
127   // Nullifies 0-th element of the "k" array
128   // because it might be used in a UserDraw function
129   // to get information on view ID, for example.
130   k[0] = NULL;
131   // Uncomment the code below if you caught
132   // exception because of k[1] is NULL.
133   // Nullifies the whole array of "k"
134   //int i = TMaxArgs;
135   //while (--i)
136   //    k[i] = NULL;
137
138 #endif
139   TStatus  TheStatus = TSuccess;
140
141   CMN_GET_STACK( n, k );
142
143   if( TsmMtblArray[el] && TsmMtblArray[el][msg] )
144     TheStatus = TsmMtblArray[el][msg]( data, n, k );
145   return  TheStatus;
146 }
147
148 static  void
149 TsmFreeList( tsm_struct s )
150 {
151   if ( !s )
152     return;
153
154   if( _Allocator.IsNull() )
155     return ;
156
157   tsm_node  node, prev;
158   Tint      num, i;
159
160   num = s->elemListHead.header.num;
161   node = s->elemListHead.next;
162
163   for( i=0; i<num; i++ )
164   {
165     TsmSendMessage( node->elem.el, Delete, node->elem.data, 0 );
166     prev = node;
167     node = node->next;
168     delete prev;
169   }
170
171   s->elemListHead.next = s->elemListHead.prev = (tsm_node)&(s->elemListHead);
172   s->elemListHead.header.num = 0;
173   return;
174 }
175
176 TStatus
177 TsmOpenStructure( Tint  stid )
178 {
179   tsm_struct s = 0;
180
181   if( _Allocator.IsNull() )
182     return TFailure;    
183
184   if( context.ind != TsmStructureNotOpen )
185     return TFailure; /* Some structure already open */
186
187   if ( !_StructMap.IsBound(stid) ){
188     s = new TSM_STRUCT();
189     if ( !s )
190       return TFailure; // Memory allocation failed
191
192     _StructMap.Bind( stid, s );
193     s->elemListHead.next = s->elemListHead.prev = (tsm_node)&(s->elemListHead);
194     s->elemListHead.header.num = 0;
195   }
196
197   s = _StructMap.Find(stid);
198
199   context.s = s;
200   context.stid = stid;
201   // Make the context point at the last node of the structure,
202   // this is the list head in case of an empty structure
203   context.ind = s->elemListHead.header.num;
204   context.n = s->elemListHead.prev;
205
206   /* Ajout CAL, 14/09/95 */
207   /* on force l'update_state de toutes les wks a TNotDone */
208   TsmInitUpdateState ();
209
210   return TSuccess;
211 }
212
213 TStatus
214 TsmCloseStructure()
215 {
216   if( context.ind == TsmStructureNotOpen )
217     return TFailure; /* No structure currently open */
218
219   context.ind = TsmStructureNotOpen;
220
221   return TSuccess;
222 }
223
224
225 TStatus
226 TsmDisplayStructure( Tint stid, Tint  wsid )
227 {
228   TSM_ELEM_DATA  data;
229   CMN_KEY        key;
230
231   TglActiveWs = wsid;
232
233   if( context.ind != TsmStructureNotOpen )
234     return TFailure; /* Some structure currently open */
235
236   key.id = wsid;
237   data.ldata = stid;
238   TsmSendMessage( TelExecuteStructure, DisplayTraverse, data, 1, &key );
239
240   return TSuccess;
241 }
242
243 TStatus
244 TsmPrintStructure( Tint stid )
245 {
246   tsm_node       node;
247   Tint           i, num;
248   tsm_struct     s;
249
250   if( context.ind != TsmStructureNotOpen )
251     return TFailure; /* Some structure currently open */
252
253   if ( _StructMap.IsEmpty() )
254     return TFailure; /* No structure created yet */
255
256   /* Obtain structure pointer from hash table */
257   if ( !_StructMap.IsBound(stid) )
258     return TFailure; /* Non-existent structure */
259
260   s = _StructMap.Find(stid);
261
262   printf( "\nPRINT:" );
263   printf( "\n\tSTRUCTURE ID = %d", stid );
264   if( !s ){
265     num = 0;
266     node = 0;
267   }
268   else{
269     num = s->elemListHead.header.num;
270     node = s->elemListHead.next;
271   }
272
273   printf( "\n\tNUMBER OF ELEMENTS = %d", num);
274   printf( "\n" );
275
276   /* For each element Send Message Print */
277   for( i = 0; i < num; i++ ){
278     printf("\n\tElement[%d] : ", i+1);
279     TsmSendMessage( node->elem.el, Print, node->elem.data, 0 );
280     node = node->next;
281   }
282
283   return TSuccess;
284 }
285
286 TStatus
287 TsmAddToStructure( TelType  el, Tint n, ... )
288 {
289   TSM_ELEM_DATA    data;
290 #if defined (SOLARIS) || defined (IRIXO32)
291   cmn_key  *k;
292 #else
293   cmn_key  k[TMaxArgs];
294 #endif
295
296   if( context.ind == TsmStructureNotOpen )
297     return TFailure; /* No structure currently open */
298
299   CMN_GET_STACK( n, k );
300   data.pdata = &data;
301   if( TsmSendMessage( el, Add, data, -n, k ) == TFailure )
302     return TFailure;
303
304   if( edit_mode == TEditReplace ){
305     TsmSendMessage( context.n->elem.el, Delete, context.n->elem.data, 0 );
306   }
307   else{
308     tsm_node node = new TSM_NODE();
309
310     if( !node )
311       return TFailure;
312
313     /* insert the node in the linked list after the current node */
314     node->prev       = context.n;
315     node->next       = context.n->next;
316     context.n->next  = node;
317     node->next->prev = node;
318
319     /* Make this node as current node */
320     context.n = node;
321     context.ind++;
322
323     /* Increment the no of elements */
324     context.s->elemListHead.header.num++;
325   }
326
327   context.n->elem.el = el;
328   context.n->elem.data = data;
329
330   return TSuccess;
331 }
332
333 TStatus
334 TsmDeleteStructure( Tint stid )
335 {
336   if( context.ind != TsmStructureNotOpen && context.stid == stid )
337     return TFailure; /* Same structure currently open */
338
339   if ( _StructMap.IsEmpty() )
340     return TFailure; /* No structure created yet */
341
342   if ( !_StructMap.IsBound(stid) )
343     return TFailure; /* Non-existent structure */
344
345   tsm_struct s = _StructMap.ChangeFind(stid);
346
347   if( stid == context.stid ){
348     context.stid = TsmInvalidStructure;
349     // Ensure the context doesn't point to freed memory
350     context.s = 0;
351     context.n = 0;
352   }
353
354   if( s ){
355     TsmFreeList( s );
356
357     /* Free structure memory */
358     delete s;
359   }
360
361   /* Remove hash table entry */
362   _StructMap.UnBind( stid );
363
364   /* Ajout BGN, 27/05/97 */
365   /* on force l'update_state de toutes les wks a TNotDone */
366   TsmInitUpdateState ();
367
368   return TSuccess;
369 }
370
371 TEditMode
372 TsmSetEditMode( TEditMode mode )
373 {
374   TEditMode m;
375
376   m = edit_mode;
377
378   /* Set static variable for mode */
379   edit_mode = mode;
380
381   /* return previous mode */
382   return m;
383 }
384
385 TStatus
386 TsmDeleteElement()
387 {
388   tsm_node node;
389
390   if( context.ind == TsmStructureNotOpen )
391     return TFailure; /* No structure currently open */
392
393   // Zero ind means the currently open structure is empty 
394   // or the current node is the list head -> nothing to delete
395   // See also TsmSetElementPointer()
396   if( !context.ind )
397     return TFailure;
398
399   /* Send message DELETE element */
400   TsmSendMessage( context.n->elem.el, Delete, context.n->elem.data, 0 );
401
402   node = context.n;
403   node->prev->next = node->next;
404   node->next->prev = node->prev;
405
406   /* make previous node as current node */
407   context.n = node->prev;
408   context.ind--;
409
410   /* Decrement the no of elements */
411   context.s->elemListHead.header.num--;
412
413   /* free the linked list node */
414   delete node;
415
416   return TSuccess;
417 }
418
419 TStatus
420 TsmDeleteElementsBetweenLabels( Tint label_id1, Tint label_id2 )
421 /* label_id1 & label_id2 exclusive */
422 {
423   Tint elem1, elem2;
424
425   if( context.ind == TsmStructureNotOpen )
426     return TFailure; /* No structure currently open */
427
428   TsmSetElementPointer( 0 );
429
430   if( TsmSetElementPointerAtLabel( label_id1 ) == TFailure)
431     return TFailure;
432   elem1 = context.ind;
433
434   if( TsmSetElementPointerAtLabel( label_id2 ) == TFailure)
435     return TFailure;
436   elem2 = context.ind;
437
438   TsmDeleteElementRange( elem1, elem2 );
439
440   return TSuccess;
441 }
442
443 TStatus
444 TsmDeleteElementRange( Tint elem1, Tint elem2 ) /* elem1 & elem2 exclusive */
445 {
446   if( context.ind == TsmStructureNotOpen )
447     return TFailure; /* No structure currently open */
448
449   TsmSetElementPointer( elem2 - 1 );
450   while( context.ind != elem1 && context.ind )
451     TsmDeleteElement();
452
453   return TSuccess;
454 }
455
456 TStatus
457 TsmSetElementPointer( Tint index )
458 {
459   if( context.ind == TsmStructureNotOpen )
460     return TFailure; /* No structure currently open */
461
462   /* Set static variable accordingly */
463   if( context.ind == index ){
464     return TSuccess;
465   }
466   if( index >= context.s->elemListHead.header.num ){
467     index = context.s->elemListHead.header.num;
468     context.n = context.s->elemListHead.prev;
469   }
470   else if( index <= 0 ){
471     index = 0;
472     context.n = (tsm_node)&(context.s->elemListHead);
473   }
474   else{
475     Tint     a, b, c, d;
476     tsm_node node;
477
478     a = index - 0;
479     b = context.ind - index; if( b < 0 ) b = -b; /* b = labs(b) */
480     c = context.s->elemListHead.header.num - index;
481     d = ( a < b ) ? ( a < c ? a : c ) : ( b < c ? b : c ) ;
482
483     if( a == d ){
484       /* Traverse from head in forward direction */
485       d = index-1;
486       node = context.s->elemListHead.next;
487       while( d-- ){
488         node = node->next;
489       }
490     }
491     else if( b == d ){
492       /* Traverse from current node in appropriate direction */
493       node = context.n;
494       d    = context.ind;
495       if( context.ind < index ){
496         while( d != index ){
497           node = node->next;
498           d++;
499         }
500       }
501       else{
502         while( d != index ){
503           node = node->prev;
504           d--;
505         }
506       }
507     }
508     else{ /* ( c == d ) */
509       /* Traverse from head in backward direction */
510       d = context.s->elemListHead.header.num;
511       node = context.s->elemListHead.prev;
512       while( d != index ){
513         node = node->prev;
514         d--;
515       }
516     }
517
518     context.n = node;
519   }
520
521   context.ind = index;
522
523   return TSuccess;
524 }
525
526
527 TStatus
528 TsmSetElementPointerAtLabel( Tint label_id )
529 {
530   Tint   i, num;
531   tsm_node  node;
532
533   if( context.ind == TsmStructureNotOpen )
534     return TFailure; /* No structure currently open */
535
536   num = context.s->elemListHead.header.num;
537   for( i=context.ind+1, node=context.n->next; i<=num; i++, node=node->next ){
538     if( node->elem.el == TelLabel && node->elem.data.ldata == label_id ){
539       context.ind = i;
540       context.n = node;
541       return TSuccess;
542     }
543   }
544
545   return TFailure;
546 }
547
548 TStatus
549 TsmOffsetElementPointer( Tint offset )
550 {
551   return TsmSetElementPointer( context.ind + offset );
552 }
553
554 TStatus
555 TsmGetStructure( Tint stid, Tint *num, tsm_node *n )
556 {
557   if ( _StructMap.IsEmpty() )
558     return TFailure; /* No structure created yet */
559
560   if ( !_StructMap.IsBound(stid) )
561     return TFailure; /* Non-existent structure */
562
563   tsm_struct s = _StructMap.Find(stid);
564
565   *num = s ? s->elemListHead.header.num : 0;
566   // Here we cannot return a pointer to the structure's list head,
567   // as it will wrongly interpreted as a regular pointer to TSM_NODE,
568   // thus returning null pointer - this should be checked by callers!
569   *n = s ? s->elemListHead.next : 0;
570
571   return TSuccess;
572 }
573
574 static TStatus
575 GetDepth( Tint stid, Tint *depth )
576 {
577   tsm_struct     s;
578   Tint           i, d, b, num;
579
580   if ( _StructMap.IsEmpty() )
581     return TFailure; /* No structure created yet */
582
583   if ( !_StructMap.IsBound(stid) )
584     return TFailure; /* Non-existent structure */
585
586   s = _StructMap.Find(stid);
587
588   (*depth)++;
589   d = b = *depth;
590
591   if( s ){
592     num = s->elemListHead.header.num;
593     tsm_node node = s->elemListHead.next;
594     for( i = 0; i < num; i++ ){
595       if( node->elem.el == TelExecuteStructure ){
596         GetDepth( node->elem.data.ldata, &d );
597         if( *depth < d )
598           *depth = d;
599       }
600       d = b;
601       node = node->next;
602     }
603   }
604
605   return TSuccess;
606 }
607
608
609 TStatus
610 TsmGetStructureDepth( Tint stid, Tint *depth )
611 {
612   *depth = 0;
613
614   GetDepth( stid, depth );
615   return TSuccess;
616 }
617
618 TStatus
619 TsmGetCurElem( TSM_ELEM *elem )
620 {
621   // Zero ind means no current element
622   if( context.ind == TsmStructureNotOpen || 
623       !context.ind )
624     return TFailure;
625
626   *elem = context.n->elem;
627   return TSuccess;
628 }
629
630 TStatus
631 TsmGetCurElemPtr( Tint *ptr )
632 {
633   // Zero ind means no current element
634   if( context.ind == TsmStructureNotOpen ||
635       !context.ind )
636     return TFailure;
637
638   *ptr = context.ind;
639   return TSuccess;
640 }