FreeWRL/FreeX3D  3.0.0
fieldSet.c
1 /*
2 
3  FreeWRL support library.
4  VRML/X3D fields manipulation.
5 
6 */
7 
8 /****************************************************************************
9  This file is part of the FreeWRL/FreeX3D Distribution.
10 
11  Copyright 2009 CRC Canada. (http://www.crc.gc.ca)
12 
13  FreeWRL/FreeX3D is free software: you can redistribute it and/or modify
14  it under the terms of the GNU Lesser Public License as published by
15  the Free Software Foundation, either version 3 of the License, or
16  (at your option) any later version.
17 
18  FreeWRL/FreeX3D is distributed in the hope that it will be useful,
19  but WITHOUT ANY WARRANTY; without even the implied warranty of
20  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
21  GNU General Public License for more details.
22 
23  You should have received a copy of the GNU General Public License
24  along with FreeWRL/FreeX3D. If not, see <http://www.gnu.org/licenses/>.
25 ****************************************************************************/
26 
27 
28 
29 #include <config.h>
30 #include <system.h>
31 #include <display.h>
32 #include <internal.h>
33 
34 #include <libFreeWRL.h>
35 #include <io_files.h>
36 
37 #include "../vrml_parser/Structs.h"
38 #include "../vrml_parser/CRoutes.h"
39 #include "../main/headers.h"
40 #include "../vrml_parser/CParseGeneral.h"
41 #include "../main/Snapshot.h"
42 #include "../scenegraph/Collision.h"
43 #include "../scenegraph/quaternion.h"
44 #include "../scenegraph/Viewer.h"
45 #include "../input/SensInterps.h"
46 #include "../input/EAIHeaders.h"
47 #include "../input/EAIHelpers.h" /* resolving implicit declarations */
48 #include "../x3d_parser/Bindable.h"
49 
50 #include "JScript.h"
51 #include "CScripts.h"
52 #include "fieldSet.h"
53 #include "fieldGet.h"
54 
55 
56 
57 /* Useful dump routines defined in world_script/field[GS]et.c */
58 void dumpOneNode(int myptr);
59 void dumpOne_X3D_Node(struct X3D_Node * boxptr);
60 void fudgeIfNeeded(int myptr,int myoffset);
61 
62 
63 /*******************************************************************
64 
65 A group of routines to SET a field in memory - in the FreeWRL
66 scene graph.
67 
68 Different methods are used, depending on the format of the call.
69 
70 *********************************************************************/
71 
72 /* copy new scanned in data over to the memory area in the scene graph. */
73 static char *Multi_Struct_memptr (int type, char *memptr) {
74  struct Multi_Vec3f *mp;
75  char * retval;
76 
77  /* is this a straight copy, or do we have a struct to send to? */
78  /* now, some internal reps use a structure defined as:
79  struct Multi_Vec3f { int n; struct SFColor *p; };
80  so, we have to put the data in the p pointer, so as to
81  not overwrite the data. */
82 
83  retval = memptr;
84 
85  switch (type) {
86  case FIELDTYPE_MFInt32:
87  case FIELDTYPE_MFFloat:
88  case FIELDTYPE_MFRotation:
89  case FIELDTYPE_MFVec3f:
90  case FIELDTYPE_MFColorRGBA:
91  case FIELDTYPE_MFColor:
92  case FIELDTYPE_MFString:
93  case FIELDTYPE_MFVec2f:
94  mp = (struct Multi_Vec3f*) memptr;
95  /* printf ("Multi_Struct_memptr, have multi thing, have %d elements, pointer %p\n",mp->n, (char *) mp->p); */
96  retval = (char *) (mp->p);
97 
98  default: {}
99  }
100 if (retval == memptr) printf ("Multi_Struct_memptr, just returning original pointer...\n");
101 
102  return retval;
103 }
104 
105 
106 /*
107 SF_TYPE(SFBool, sfbool, Bool)
108 MF_TYPE(MFBool, mfbool, Bool)
109 SF_TYPE(SFColor, sfcolor, Color)
110 MF_TYPE(MFColor, mfcolor, Color)
111 SF_TYPE(SFColorRGBA, sfcolorrgba, ColorRGBA)
112 MF_TYPE(MFColorRGBA, mfcolorrgba, ColorRGBA)
113 */
114 
115 /* how many rows are in this data type? SF nodes have 1, other nodes... */
116 static int returnNumberOfRows(int datatype,union anyVrml *memptr) {
117  switch (datatype) {
118 
119  #define SF_TYPE(fttype, type, ttype) \
120  case FIELDTYPE_##fttype: return 1; break;
121 
122  #define MF_TYPE(fttype, type, ttype) \
123  case FIELDTYPE_##fttype: return memptr->type.n; break;
124 
125 #include "../vrml_parser/VrmlTypeList.h"
126 
127 #undef SF_TYPE
128 #undef MF_TYPE
129 
130  default:
131  parseError("Unsupported type in defaultValue!");
132 
133 
134 
135  }
136  return 1;
137 }
138 
139 
140 
141 /* set a field; used in JavaScript, and in the Parser VRML parser
142 
143  fields are:
144  ptr: pointer to a node (eg, X3D_Box)
145  field: string field name (eg, "size")
146  value: string of value (eg "2 2 2");
147 
148 This is used mainly in parsing */
149 
150 void setField_fromJavascript (struct X3D_Node *node, char *field, char *value, int isXML) {
151  int foffset;
152  int coffset;
153  int ctype;
154  int ctmp;
155 
156  #ifdef SETFIELDVERBOSE
157  printf ("\nsetField_fromJavascript, node %p field %s value %s\n", (char*) node, field, value);
158  #endif
159 
160  /* is this a valid field? */
161  foffset = findRoutedFieldInFIELDNAMES(node,field,1);
162  if (foffset < 0) {
163  ConsoleMessage ("field %s is not a valid field of a node %s",field,stringNodeType(node->_nodeType));
164  printf ("field %s is not a valid field of a node %s\n",field,stringNodeType(node->_nodeType));
165  return;
166  }
167 
168  /* get offsets for this field in this nodeType */
169  #ifdef SETFIELDVERBOSE
170  printf ("getting nodeOffsets for type %s field %s value %s\n",stringNodeType(node->_nodeType),field,value);
171  #endif
172 
173  findFieldInOFFSETS(node->_nodeType, foffset, &coffset, &ctype, &ctmp);
174 
175  #ifdef SETFIELDVERBOSE
176  printf ("so, offset is %d, type %d value %s\n",coffset, ctype, value);
177  #endif
178 
179  if (coffset <= 0) {
180  printf ("setField_fromJavascript, trouble finding field %s in node %s\n",field,stringNodeType(node->_nodeType));
181  if(isProto(node))
182  printf("this is a Proto...have to go through PROTO defs to get to it\n");
183  /*
184  printf ("is this maybe a PROTO?? if so, it will be a Group node with FreeWRL__protoDef set to an index\n");
185  if (node->_nodeType == NODE_Group) {
186  struct X3D_Group *group = (struct X3D_Group *)node;
187  printf ("it IS a group...\n");
188  if (group->FreeWRL__protoDef!= INT_ID_UNDEFINED) {
189  printf ("and, this is a PROTO...have to go through PROTO defs to get to it\n");
190  }
191  }
192  */
193  }
194 
195  Parser_scanStringValueToMem(node, (size_t) coffset, ctype, value, isXML);
196 }
197 
198 
199 /* and incoming EAI event has come in, and the destination is an inputOnly field of a script.
200  Make It So. This mimics the routing function "getField_ToJavascript" except that we do not
201  have a routing entry for the from address and size and type, so we have to do this by hand.
202 */
203 
204 static int setField_FromEAI_ToScript(int tonode, int toname,
205  int datatype, void *data, unsigned rowcount) {
206 
207 
208  int datalen;
209 
210  #ifdef SETFIELDVERBOSE
211  printf ("doing setField_FromEAI_ToScript, for script %u, nameIndex %u, type %s\n",tonode, toname, stringFieldtypeType(datatype));
212  #endif
213 
214  switch (datatype) {
215  case FIELDTYPE_SFBool:
216  case FIELDTYPE_SFFloat:
217  case FIELDTYPE_SFTime:
218  case FIELDTYPE_SFDouble:
219  case FIELDTYPE_SFInt32:
220  case FIELDTYPE_SFString:
221 
222  /* this one expects datalen to be in bytes */
223  datalen = returnElementLength(datatype) * returnElementRowSize(datatype);
224  #ifdef SETFIELDVERBOSE
225  printf ("SFSingle in setField_FromEAI_ToScript, setting script, dataLength is made up of %d x %d x %d for %s\n",
226  returnElementLength(datatype), returnElementRowSize(datatype), rowcount, stringFieldtypeType(datatype));
227  #endif
228 
229  set_one_ECMAtype (tonode, toname, datatype, data, datalen);
230  break;
231  case FIELDTYPE_SFColor:
232  case FIELDTYPE_SFVec2f:
233  case FIELDTYPE_SFVec3f:
234  case FIELDTYPE_SFVec3d:
235  case FIELDTYPE_SFRotation:
236  /* this one expects datalen to be in bytes */
237  datalen = returnElementLength(datatype) * returnElementRowSize(datatype);
238  #ifdef SETFIELDVERBOSE
239  printf ("SFColor-style in setField_FromEAI_ToScript, setting script, dataLength is made up of %d x %d x %d for %s\n",
240  returnElementLength(datatype), returnElementRowSize(datatype), rowcount, stringFieldtypeType(datatype));
241  #endif
242  set_one_MultiElementType (tonode, toname, data, datalen);
243  break;
244  case FIELDTYPE_SFNode:
245  #ifdef SETFIELDVERBOSE
246  printf ("SFNode copy, tonode %u...\n",tonode);
247  #endif
248 
249  datalen = returnElementLength(FIELDTYPE_SFNode);
250  set_one_MultiElementType (tonode, toname, data, datalen);
251  break;
252 
253 
254 
255  case FIELDTYPE_MFColor:
256  case FIELDTYPE_MFVec3f:
257  case FIELDTYPE_MFVec3d:
258  case FIELDTYPE_MFVec2f:
259  case FIELDTYPE_MFFloat:
260  case FIELDTYPE_MFTime:
261  case FIELDTYPE_MFInt32:
262  case FIELDTYPE_MFString:
263  case FIELDTYPE_MFNode:
264  case FIELDTYPE_MFRotation:
265  case FIELDTYPE_SFImage:
266  #ifdef SETFIELDVERBOSE
267  printf ("going to call MF types in set_one_MFElementType rowcount %d\n",rowcount);
268  #endif
269  set_one_MFElementType(tonode, toname, datatype, data, rowcount);
270  break;
271  default : {
272  printf("WARNING: setField_FromEAI_ToScript, type %s not handled yet\n",
273  stringFieldtypeType(datatype));
274  }
275  }
276 
277 
278  return TRUE;
279 
280 }
281 
282 void fudgeIfNeeded(int myptr,int myoffset){
283  /*
284  * Problem to solve:
285  * Before operating on a set_ABC field that is of type multi,
286  * we should copy across the data from the ABC field,
287  * because if we do not, ONEVAL will not work.
288  *
289  * Method: We have been given myptr and myoffset (by the EAI request).
290  * We can map the offset to an name like set_ABC, and map set_ABC to ABC
291  * We can then copy the data from ABC to set_ABC
292  */
293  struct X3D_Node *boxptr;
294  int *np;
295  int f_indx;
296  int myc = 0;
297  int scanning = TRUE;
298  int foundSet = 0; /* Did we find set_ABC ? */
299  int foundAlt = 0; /* Did we find ABC ? */
300 
301  char *setnameIs = NULL ;
302  char *altnameIs = NULL ;
303  int relSet = 0 ; /* RoutingElementLength of set_ABC */
304  int relAlt = 0 ; /* RoutingElementLength of ABC */
305 
306  void *sourceNode = NULL;
307  void *destNode = NULL;
308 
309  boxptr = getEAINodeFromTable(myptr,-1);
310  #ifdef SETFIELDVERBOSE
311  printf ("%s,%d fudgeIfNeeded node %u -> %p\n",__FILE__,__LINE__, (unsigned int)myptr, boxptr);
312  #endif
313 
314  /* Iterate over all the fields in the node because there is no easy way of getting to the name from the offset */
315  np = (int *) NODE_OFFSETS[boxptr->_nodeType];
316  while (scanning && (*np != INT_ID_UNDEFINED)) {
317  /* We need not skip hidden fields (EAI cannot see them anyway) */
318 
319  /* The primary basis of comparison is 'myoffset' because this is
320  * what the EAI request passed to FreeWRL.
321  */
322  if (myoffset == np[1]) {
323  #ifdef SETFIELDVERBOSE
324  printf("Field %d %s ", myc, stringFieldType(np[0]));
325  #endif
326  if (0 == strncmp("set_",stringFieldType(np[0]),4)) {
327  int offset=np[1];
328  #ifdef SETFIELDVERBOSE
329  printf(" , Found a set_ ; offset=%d\n",offset);
330  #endif
331 
332  /* We do not really need setnameIs (except to calculate altnamesIs
333  * but we do use it later on just for debugging.
334  */
335  setnameIs = (char *)stringFieldType(np[0]);
336  altnameIs = setnameIs+4;
337 
338  /* Use this as a flag to see if we need to return quickly or not. */
339  foundSet = myc;
340 
341  /* This has to be negative and the same as what
342  * we are going to be copying from. Also, we need
343  * to pass this to Multimemcpy
344  */
345  relSet = returnRoutingElementLength(np[2]);
346 
347  /* Also needed by Multimemcpy */
348  destNode = offsetPointer_deref(void *, boxptr, offset);
349  } else {
350  #ifdef SETFIELDVERBOSE
351  printf("\n");
352  #endif
353  }
354  scanning = FALSE;
355  }
356  myc ++;
357  np +=5;
358  }
359 
360  /* If foundSet is zero, then the field name is not set_ABC */
361  if (!foundSet) return;
362 
363  #ifdef SETFIELDVERBOSE
364  printf("%s,%d setnameIs=%s , altnameIs=%s foundSet=%d relSet=%d\n",__FILE__,__LINE__,setnameIs,altnameIs,foundSet,relSet);
365  #endif
366 
367  /* We now know everything we need to know about the destination;
368  * find out what we need to know about the source
369  */
370 
371  f_indx = findFieldInFIELDNAMES(altnameIs);
372  /* Mind, is findFieldInFIELDNAMES any quicker ?
373  * If hashing is not used, then using strcmp below might be faster
374  * because we are only comparing a subset, not all the names...
375  */
376 
377  #ifdef SETFIELDVERBOSE
378  printf ("field index %s is %d, it had better not be -1 !! \n",altnameIs,f_indx);
379  #endif
380  myc = 0;
381  scanning = TRUE;
382  np = (int *) NODE_OFFSETS[boxptr->_nodeType];
383  while (scanning && (*np != INT_ID_UNDEFINED)) {
384  /* It is now less messy if we skip the hidden fields */
385  if (0 != strncmp(stringFieldType(np[0]), "_", 1) ) {
386  #ifdef SETFIELDVERBOSE
387  printf("Field %d %s", myc, stringFieldType(np[0]));
388  #endif
389 
390  /* We need not compare strings, but see comment about findFieldInFIELDNAMES above
391  if (0 == strcmp(altnameIs,stringFieldType(np[0]))) {
392  */
393  if (f_indx == np[0]) {
394  #ifdef SETFIELDVERBOSE
395  printf(" , Found alternate name, ie %s f_indx=%d offset=%d\n",altnameIs,f_indx,np[1]);
396  #endif
397  foundAlt = myc;
398 
399  /* See relSet comment above */
400  relAlt = returnRoutingElementLength(np[2]);
401 
402  /* Also needed by Multimemcpy */
403  sourceNode = offsetPointer_deref(void *, boxptr, np[1]);
404  scanning = FALSE;
405  } else {
406  #ifdef SETFIELDVERBOSE
407  printf("\n");
408  #endif
409  }
410  }
411  myc ++;
412  np +=5;
413  }
414  if (!foundAlt) return;
415 
416  #ifdef SETFIELDVERBOSE
417  printf("%s,%d setnameIs=%s , altnameIs=%s foundAlt=%d relAlt=%d\n",__FILE__,__LINE__,setnameIs,altnameIs,foundAlt,relAlt);
418  #endif
419 
420  /* final check for compatibility */
421  if (relAlt == relSet && relSet < 0) {
422  #ifdef SETFIELDVERBOSE
423  printf("%s,%d About to call Multimemcpy (boxptr=%p, boxptr=%p, destNode=%p, sourceNode=%p, relAlt=%d);\n",__FILE__, __LINE__, boxptr, boxptr, destNode, sourceNode, relAlt);
424  #endif
425  Multimemcpy (boxptr, boxptr, destNode, sourceNode, relAlt);
426  } else {
427  return;
428  }
429 
430  #ifdef SETFIELDVERBOSE
431  printf("=================================== Fudged %s,%d ==================================\n",__FILE__,__LINE__);
432  dumpOneNode(myptr);
433  printf("====================================== %s,%d ======================================\n",__FILE__,__LINE__);
434  #endif
435 
436  return;
437 }
438 
439 void dumpOneNode(int myptr) {
440  struct X3D_Node *boxptr;
441  bool eaiverbose = gglobal()->EAI_C_CommonFunctions.eaiverbose;
442  boxptr = getEAINodeFromTable(myptr,-1);
443 
444  if (eaiverbose) {
445  printf ("GETFIELDDEFS, node %u -> %p\n",(unsigned int)myptr, boxptr);
446  }
447  dumpOne_X3D_Node(boxptr) ;
448 }
449 
450 void dumpOne_X3D_Node(struct X3D_Node * boxptr) {
451  int myc;
452  int *np;
453 
454  char *tmpptr;
455  int dtmp;
456  char ctmp;
457  char utilBuf[EAIREADSIZE];
458  int errcount;
459 
460  if (boxptr == 0) {
461  printf ("makeFIELDDEFret have null node here \n");
462  return;
463  }
464 
465  printf ("node type is %s\n",stringNodeType(boxptr->_nodeType));
466 
467  /* Iterate over all the fields in the node */
468  np = (int *) NODE_OFFSETS[boxptr->_nodeType];
469  myc = 0;
470  while (*np != -1) {
471  /* is this a hidden field? */
472  if (0 != strncmp(stringFieldType(np[0]), "_", 1) ) {
473  ctmp = (char) mapFieldTypeToEAItype(np[2]);
474  dtmp = mapEAItypeToFieldType(ctmp);
475 
476  tmpptr = offsetPointer_deref (char *, boxptr,np[1]);
477  printf("%s,%d ",__FILE__,__LINE__);
478  printf("Field %d %s , ", myc, stringFieldType(np[0]));
479  printf("offset=%d bytes , ", np[1]);
480 /*
481  printf("field_type= %c (%d) , ", ctmp , dtmp);
482  printf("Routing=%s , ", stringKeywordType(np[3]));
483  printf("Spec=%d , ", np[4]) ;
484 */
485  errcount = UtilEAI_Convert_mem_to_ASCII (dtmp,tmpptr, utilBuf);
486  if (0 == errcount) {
487  printf ("\t\tValue = %s\n",utilBuf);
488  } else {
489  printf ("\t\tValue = indeterminate....\n");
490  }
491  myc ++;
492  }
493  np +=5;
494  }
495 }
496 
497 /* an incoming EAI/CLASS event has come in, convert the ASCII characters
498  * to an internal representation, and act upon it */
499 
500 unsigned int setField_FromEAI (char *ptr) {
501  unsigned char nt;
502  int datatype;
503  int nodeIndex, fieldIndex;
504  struct X3D_Node* nodeptr;
505  int offset;
506  int myoffset;
507  unsigned int scripttype;
508  char *eol;
509 
510  char * memptr = 0;
511  struct X3D_Node* myptr = 0;
512 
513  int valIndex;
514  struct Multi_Color *tcol;
515  int retint; /* used to get return value of sscanf */
516 
517  union anyVrml myAnyValue;
518 
519  #ifdef SETFIELDVERBOSE
520  printf ("%s,%d setField_FromEAI, string :%s:\n",__FILE__,__LINE__,ptr);
521  #endif
522 
523  /* we have an event, get the data properly scanned in from the ASCII string. */
524 
525  /* node type */
526  while (*ptr==' ')ptr++; /* remove blank space at front of string */
527  nt = *ptr; ptr++; /* get the ASCII indication of node type */
528  datatype = mapEAItypeToFieldType(nt);
529 
530  /* blank space */
531  ptr++;
532 
533  /* nodeptr, offset */
534  retint=sscanf (ptr, "%d %d %d",&nodeIndex, &fieldIndex, &scripttype);
535  if (retint != 3) ConsoleMessage ("setField_FromEAI: error reading 3 numbers from the string :%s:\n",ptr);
536  #ifdef SETFIELDVERBOSE
537  printf("setField_FromEAI: nodeIndex=%d, fieldIndex=%d, scripttype=%d\n",nodeIndex, fieldIndex, scripttype);
538  #endif
539 
540  while ((*ptr) > ' ') ptr++; /* node ptr */
541  while ((*ptr) == ' ') ptr++; /* inter number space(s) */
542  while ((*ptr) > ' ') ptr++; /* node offset */
543  while ((*ptr) == ' ') ptr++; /* inter number space(s) */
544  while ((*ptr) > ' ') ptr++; /* script type */
545 
546  #ifdef SETFIELDVERBOSE
547  {
548  struct X3D_Node *np;
549  int nt;
550  /* get the actual node pointer from this index */
551  np = getEAINodeFromTable(nodeIndex,fieldIndex);
552 
553  printf("=================================== Pre op %s,%d ==================================\n",__FILE__,__LINE__);
554  dumpOneNode(nodeIndex);
555  printf("====================================== %s,%d ======================================\n",__FILE__,__LINE__);
556 
557  nt = getEAINodeTypeFromTable(nodeIndex);
558 
559  printf ("EAI_SendEvent, type %s, nodeptr (index %d) %u offset %d script type %d ",
560  stringFieldtypeType(datatype),nodeIndex, np->_nodeType, fieldIndex, scripttype);
561  printf ("np->_nodeType %s\n",stringNodeType(np->_nodeType));
562 
563  if (nt == EAI_NODETYPE_SCRIPT) printf ("setField_FromEAI - sending to a script node!\n");
564  else if (nt == EAI_NODETYPE_PROTO) printf ("setField_FromEAI - sending to a script node!\n");
565  else if(nt == EAI_NODETYPE_STANDARD) printf ("setField_FromEAI - sending to a standard node!\n");
566  else printf ("setField_FromEAI - unknown type!\n");
567  }
568  #endif
569 
570 
571  /* We have either a event to a memory location, or to a script. */
572  /* the field scripttype tells us whether this is true or not. */
573 
574  if (scripttype == EAI_NODETYPE_SCRIPT) {
575  /* a local temporary area for us */
576  memptr = (char *) &myAnyValue;
577  } else {
578  memptr = (char *) getEAIMemoryPointer (nodeIndex,fieldIndex);
579  }
580 
581  offset = getEAIActualOffset(nodeIndex, fieldIndex);
582  myoffset = offset;
583  nodeptr = getEAINodeFromTable(nodeIndex,fieldIndex);
584  myptr = nodeptr;
585 
586  /* now, we are at start of the incoming data. */
587  /* lets go to the first non-blank character in the string */
588  while (*ptr == ' ') ptr++;
589 
590  #ifdef SETFIELDVERBOSE
591  printf ("setField_FromEAI EAI_SendEvent, event string now is :%s:\n",ptr);
592  #endif
593 
594  /* is this a MF node, that has floats or ints, and the set1Value method is called? */
595  /* check out the java external/field/MF*java files for the string "ONEVAL " */
596  if (strncmp("ONEVAL ",ptr, strlen("ONEVAL ")) == 0) {
597  #ifdef SETFIELDVERBOSE
598  printf ("%s,%d This is a ONEVAL operation\n",__FILE__,__LINE__);
599  #endif
600 
601  fudgeIfNeeded(nodeIndex,myoffset);
602 
603  ptr += strlen ("ONEVAL ");
604 
605  /* find out which element the user wants to set - that should be the next number */
606  while (*ptr==' ')ptr++;
607  retint=sscanf (ptr,"%d",&valIndex);
608  #ifdef SETFIELDVERBOSE
609  printf ("%s,%d Request to set element %d\n",__FILE__,__LINE__,valIndex);
610  #endif
611 
612  if (retint != 1) ConsoleMessage ("setField_FromEAI: error reading 1 numbers from the string :%s:\n",ptr);
613  while (*ptr>' ')ptr++; /* past the number */
614  while (*ptr==' ')ptr++;
615 
616  /* lets do some bounds checking here. */
617  tcol = (struct Multi_Color *) memptr;
618  #ifdef SETFIELDVERBOSE
619  printf ("%s,%d now, we have valIndex %d, tcol->n %d\n",__FILE__,__LINE__,valIndex,tcol->n);
620  #endif
621 
622  if (valIndex >= tcol->n) {
623  void *nmemptr;
624  int malSize;
625 
626  /* expand this array so that we can put the value in */
627  /*
628  printf ("have to expand MF value, had %d, wanted %d\n",tcol->n, valIndex);
629  printf ("and we have elementLength %d and rowSize %d\n",returnElementLength(datatype) ,returnElementRowSize(datatype));
630  */
631 
632  /* if we want index "5", say, we make it "5+1" long because we are zero based */
633  malSize = (valIndex+1) * returnElementLength(datatype) * returnElementRowSize(datatype);
634  nmemptr = MALLOC(void *, malSize);
635 
636  /* zero the new array - this will give us null holes, maybe */
637  bzero (nmemptr,(size_t)malSize);
638  /* printf ("locked and loaded %d bytes\n",malSize); */
639 
640  /* copy the old data over */
641  memcpy (nmemptr,tcol->p, tcol->n * returnElementLength(datatype) * returnElementRowSize(datatype));
642 
643  /* printf ("copied over %d bytes from the old school \n",tcol->n * returnElementLength(datatype) * returnElementRowSize(datatype)); */
644 
645  /* if this is Strings, then verify that ALL pointers are ok, and point to some string */
646  if (datatype == FIELDTYPE_MFString) {
647  int count;
648  struct Uni_String * *strarr = (struct Uni_String **) nmemptr;
649  for (count = 0; count <=valIndex ; count++) {
650 
651  /* is this one NULL? If so, make it into something */
652  if ((*strarr) == NULL) *strarr = newASCIIString (""); /* "created from set1Value" */
653  /* printf ("index %d, the stringis :%s:\n",count,(*strarr)->strptr); */
654  strarr++;
655  }
656  }
657 
658  tcol->n = 0;
659  FREE_IF_NZ(tcol->p);
660  tcol->p = nmemptr;
661  tcol->n = valIndex+1;
662 
663  /* printf ("now, we have valIndex %d, tcol->n %d\n",valIndex,tcol->n); */
664  } else {
665  #ifdef SETFIELDVERBOSE
666  printf ("%s,%d Size OK, replacing element %d in %d elements\n",__FILE__,__LINE__,valIndex,tcol->n);
667  #endif
668  }
669 
670 
671  /* if this is a struct Multi* node type, move the actual memory pointer to the data */
672  memptr = Multi_Struct_memptr(datatype, (void *) memptr);
673 
674  /* and index into that array; we have the index, and sizes to worry about */
675  memptr += valIndex * returnElementLength(datatype) * returnElementRowSize(datatype);
676 
677  /* and change the nodetype to reflect this change */
678  datatype = convertToSFType(datatype);
679 
680  /* For ONEVAL need to pass memptr, not nodeptr */
681  myptr = X3D_NODE(memptr);
682  myoffset = 0;
683  } else {
684  #ifdef SETFIELDVERBOSE
685  printf ("%s,%d Not a ONEVAL operation\n",__FILE__,__LINE__);
686  #endif
687  }
688 
689  /* lets replace the end of the string with a NULL, for parsing purposes */
690  eol = strchr (ptr,'\n'); if (eol != NULL) *eol = '\0';
691 
692  /* at this point, we have:
693  memptr = pointer to memory location to start scanning;
694  offset = actual offset in node, or 0 if ONEVAL invoked;
695  nodeptr = actual memory pointer of X3D_Node* */
696 
697  /* first, parse the value into the local variable */
698  Parser_scanStringValueToMem(myptr,myoffset,datatype,ptr,FALSE);
699 
700  if (scripttype == EAI_NODETYPE_SCRIPT) {
701  struct Shader_Script * sp;
702  int rowCount;
703 
704  /* we send along the script number, not the node pointer */
705  sp = (struct Shader_Script *) (X3D_SCRIPT(nodeptr)->__scriptObj);
706 
707  mark_script (sp->num);
708 
709  /* now, send the number of rows along; SFs return 1, MFS return rows */
710  rowCount = returnNumberOfRows(datatype,(union anyVrml *) memptr);
711  #ifdef SETFIELDVERBOSE
712  printf("%s,%d rowCount=%d\n",__FILE__,__LINE__,rowCount);
713  #endif
714 
715  /* inch the type along, to the data pointer */
716  memptr = Multi_Struct_memptr(datatype, memptr);
717 
718  setField_FromEAI_ToScript(sp->num,offset,datatype,memptr,rowCount);
719  } else {
720 
721 
722  /* if this is a geometry, make it re-render.
723  Some nodes (PROTO interface params w/o IS's)
724  will have an offset of zero, and are thus not
725  "real" nodes, only memory locations
726  */
727 
728  update_node ((void *)nodeptr);
729 
730  /* if anything uses this for routing, tell it that it has changed */
731  MARK_EVENT (X3D_NODE(nodeptr),offset);
732  }
733 
734 
735  #ifdef SETFIELDVERBOSE
736  printf("================================== Post op %s,%d ==================================\n",__FILE__,__LINE__);
737  dumpOneNode(nodeIndex);
738  printf("====================================== %s,%d ======================================\n",__FILE__,__LINE__);
739  #endif
740 
741  /* replace the end of the line with a newline */
742  if (eol != NULL) *eol = '\n';
743  return TRUE;
744 
745 }
746 
747 
748 /* find the ASCII string name of this field of this node */
749 char *findFIELDNAMESfromNodeOffset(struct X3D_Node *node, int offset) {
750  int* np;
751  if (node == 0) return "unknown";
752 
753  np = (int *) NODE_OFFSETS[node->_nodeType];
754  np++; /* go to the offset field */
755 
756  while ((*np != -1) && (*np != offset)) np +=5;
757 
758  if (*np == -1) return "fieldNotFound";
759 
760  /* go back to the field name */
761  np --;
762  return ((char *) FIELDNAMES[*np]);
763 }
764 
765 /* go through the generated table FIELDTYPES, and find the int of this string, returning it, or -1 on error
766  or if it is an "internal" field */
767 int findFieldInARR(const char* field, const char** arr, size_t cnt)
768 {
769  int x;
770  size_t mystrlen;
771 
772  if (field == NULL) return -1;
773 
774  #ifdef SETFIELDVERBOSE
775  if (field[0] == '_') {
776  printf ("findFieldInFIELDNAMES - internal field %s\n",field);
777  }
778  #endif
779 
780  mystrlen = strlen(field);
781  for (x=0; x!=cnt; ++x) {
782  if (strlen(arr[x]) == mystrlen) {
783  if (strcmp(field, arr[x])==0) return x;
784  }
785  }
786  return -1;
787 
788 }
789 #define DEF_FINDFIELD(arr) \
790  int findFieldIn##arr(const char* field) \
791  { \
792  return findFieldInARR(field, arr, arr##_COUNT); \
793  }
794 DEF_FINDFIELD(FIELDNAMES)
795 DEF_FINDFIELD(FIELD)
796 DEF_FINDFIELD(EXPOSED_FIELD)
797 DEF_FINDFIELD(EVENT_IN)
798 DEF_FINDFIELD(EVENT_OUT)
799 DEF_FINDFIELD(KEYWORDS)
800 DEF_FINDFIELD(PROTOKEYWORDS)
801 DEF_FINDFIELD(NODES)
802 DEF_FINDFIELD(PROFILES)
803 DEF_FINDFIELD(COMPONENTS)
804 DEF_FINDFIELD(FIELDTYPES)
805 DEF_FINDFIELD(X3DSPECIAL)
806 DEF_FINDFIELD(GEOSPATIAL)
807 DEF_FINDFIELD(MULTITEXTUREMODE);
808 DEF_FINDFIELD(MULTITEXTURESOURCE);
809 DEF_FINDFIELD(MULTITEXTUREFUNCTION);
810 
811 /* lets see if this node has a routed field fromTo = 0 = from node, anything else = to node */
812 /* returns the FIELDNAMES index. */
813 /* for user-fields, the additional check is skipped */
814 int findRoutedFieldInARR (struct X3D_Node * node, const char *field, int fromTo,
815  const char** arr, size_t cnt, BOOL user) {
816  int retval;
817  char mychar[200];
818  int a,b,c;
819 
820  retval = -1;
821 
822 #define FIELDCHECK(fld) \
823  if (retval >= 0) { \
824  if (user) return retval; \
825  {int fieldNamesIndex = findIndexInFIELDNAMES(retval, arr, cnt); \
826  if (fieldNamesIndex >= 0) { \
827  findFieldInOFFSETS (node->_nodeType, fieldNamesIndex,\
828  &a, &b, &c); \
829  /* did this return any of the ints as != -1? */ \
830  /* printf (" findRoutedField for field %s, nodetype %s is %d\n", fld,stringNodeType(node->_nodeType),a); */ \
831  if (a >= 0) return retval; /* found it! */ \
832  }} \
833  }
834 
835 
836  /* step try the field as is. */
837  retval = findFieldInARR(field, arr, cnt);
838  /* printf ("findRoutedField, field %s retval %d\n",field,retval); */
839  FIELDCHECK (field)
840 
841  /* try REMOVING/STRIPPING the "set_" or "_changed" */
842  strncpy (mychar, field, 100);
843  if (fromTo != 0) {
844  if (strlen(field) > strlen("set_"))
845  retval=findFieldInARR(mychar+strlen("set_"), arr, cnt);
846  } else {
847  if (strlen(field) > strlen("_changed")) {
848  mychar[strlen(field) - strlen("_changed")] = '\0';
849  retval = findFieldInARR(mychar, arr, cnt);
850  }
851  }
852  /* printf ("findRoutedField, mychar %s retval %d\n",mychar,retval); */
853  FIELDCHECK (mychar)
854 
855  /* try ADDING the "set_" or "_changed" some nodes have fields ending in "_changed" - maybe the
856  user forgot about that? (eg, ProximitySensor) */
857  if (fromTo != 0) {
858  strcpy (mychar,"set_");
859  strncat (mychar, field,100);
860  retval=findFieldInARR(mychar, arr, cnt);
861  } else {
862  strncpy (mychar, field, 100);
863  strcat (mychar,"_changed");
864  retval = findFieldInARR(mychar, arr, cnt);
865  }
866  /* printf ("findRoutedField, mychar %s retval %d\n",mychar,retval); */
867  FIELDCHECK (mychar)
868 
869 
870  return retval;
871 }
872 #define DEF_FINDROUTEDFIELD(arr) \
873  int findRoutedFieldIn##arr(struct X3D_Node* node, const char* field, int fromTo) \
874  { \
875  return findRoutedFieldInARR(node, field, fromTo, arr, arr##_COUNT, FALSE); \
876  }
877 DEF_FINDROUTEDFIELD(FIELDNAMES)
878 DEF_FINDROUTEDFIELD(EXPOSED_FIELD)
879 DEF_FINDROUTEDFIELD(EVENT_IN)
880 DEF_FINDROUTEDFIELD(EVENT_OUT)
881 
882 
883 /* go through the OFFSETS for this node, looking for field, and return offset, type, and kind */
884 void findFieldInOFFSETS(int nodeType, const int field, int *coffset, int *ctype, int *ckind) {
885  int *x;
886  int X3DLevel;
887  int mask = 0;
888 
889  x = (int *) NODE_OFFSETS[nodeType];
890 
891  #ifdef SETFIELDVERBOSE
892  printf ("findFieldInOFFSETS, nodeType %s\n",stringNodeType(nodeType));
893  printf ("findFieldInOffsets, comparing %d to %d\n",*x, field);
894  #endif
895 
896  while ((*x != field) && (*x != -1)) {
897  x += 5;
898  }
899  if (*x == field) {
900  x++; *coffset = (int)*x; x++; *ctype = (int)*x; x++; *ckind = (int)*x; x++; X3DLevel = (int)*x;
901 
902  #ifdef SETFIELDVERBOSE
903  printf ("found field, coffset %d ctype %d ckind %d X3DLevel %x\n",*coffset, *ctype, *ckind, X3DLevel);
904  #endif
905 
906  /* do we care if, maybe, this field is not correct for requested version of FreeWRL? */
907  if (gglobal()->internalc.global_strictParsing) {
908  if (inputFileVersion[0] == 2) { /* VRML 2.0 */
909  if ((X3DLevel & SPEC_VRML) == SPEC_VRML) {
910  return; /* field ok */
911  }
912  } else if (inputFileVersion[0] == 3) { /* X3D V3.x */
913  switch (inputFileVersion[1]) {
914  case 0: mask = SPEC_X3D30; break;
915  case 1: mask = SPEC_X3D31; break;
916  case 2: mask = SPEC_X3D32; break;
917  case 3: mask = SPEC_X3D33; break;
918  case 4: mask = SPEC_X3D34; break;
919  default: {printf ("unknown X3D level %d\n",inputFileVersion[1]);
920  mask = SPEC_X3D33;
921  }
922  }
923  if ((X3DLevel & mask) == mask) {
924  return; /* field ok */
925  }
926  } else {
927  printf ("unknown input file version %d for strictParsing! help!\n",inputFileVersion[0]);
928  }
929  ConsoleMessage ("strictParsing, Node %s field %s is not valid for X3D version %d.%d",
930  stringNodeType(nodeType),stringFieldType(field),inputFileVersion[0],inputFileVersion[1]);
931  }
932 
933  return;
934  }
935  if (*x == -1) {
936  #ifdef SETFIELDVERBOSE
937  printf ("did not find field %d in OFFSETS\n",field);
938  #endif
939 
940  *coffset = -1; *ctype = -1, *ckind = -1;
941  return;
942  }
943 }
944 
945 
946 /************************************************************************/
947 /* a script is returning a MFNode type; add or remove this to the C */
948 /* children field */
949 /* note params - tn is the address of the actual field, parent is parent*/
950 /* structure */
951 /************************************************************************/
952 
953 void getMFNodetype (struct X3D_Node *strp, struct Multi_Node *tn, struct X3D_Node *parent, int ar) {
954  /* now, perform the add/remove */
955  AddRemoveChildren (parent, tn, &strp, 1, ar,__FILE__,__LINE__);
956 }
957 
958 
959 /* Map the given index into arr to an index into FIELDNAMES or -1, if the
960  * string in question isn't there. */
961 int findIndexInFIELDNAMES(int index, const char** arr, size_t arrCnt) {
962  int i;
963 
964  /* If this is already FIELDNAMES, return index. */
965  if(arr==FIELDNAMES)
966  return index;
967 
968  /* Look for the string */
969  for(i=0; i!=FIELDNAMES_COUNT; ++i) {
970  if(!strcmp(FIELDNAMES[i], arr[index]))
971  return i;
972  }
973 
974  /* Not found */
975  return -1;
976 }