Initial git commit -- Transition from CodeGuard repository
[sdk] / ecere / src / com / dataTypes.ec
1 namespace com;
2
3 #if defined(ECERE_BOOTSTRAP)
4 #define dllexport
5 #endif
6
7 import "instance"
8
9 default extern Platform runtimePlatform;
10
11 // Limit Definitions
12 public define MAXBYTE = 0xff;
13 public define MAXWORD = 0xffff;
14 public define MININT = ((int)0x80000000);
15 public define MAXINT = ((int)0x7fffffff);
16 public define MININT64 = ((int64)0x8000000000000000LL);
17 public define MAXINT64 = ((int64)0x7fffffffffffffffLL);
18 public define MAXDWORD = 0xffffffff;
19 public define MAXQWORD = 0xffffffffffffffffLL;
20 public define MINFLOAT = ((float)1.17549435082228750e-38);
21 public define MAXFLOAT = ((float)3.40282346638528860e+38);
22 public define MINDOUBLE = ((double) 2.2250738585072014e-308);
23 public define MAXDOUBLE = ((double) 1.7976931348623158e+308);
24
25 public define FORMAT64HEXLL  = (GetRuntimePlatform() == win32) ? "0x%I64XLL" : "0x%llXLL";
26 public define FORMAT64HEX    = (GetRuntimePlatform() == win32) ? "0x%I64X" : "0x%llX";
27 public define FORMAT64DLL    = (GetRuntimePlatform() == win32) ? "%I64dLL" : "%lldLL";
28 public define FORMAT64D      = (GetRuntimePlatform() == win32) ? "%I64d" : "%lld";
29 public define FORMAT64U      = (GetRuntimePlatform() == win32) ? "%I64u" : "%llu";
30
31 #define PUTXWORD(b, w) \
32    (b)[0] = (byte)(((w) >> 8) & 0xFF); \
33    (b)[1] = (byte)(((w)     ) & 0xFF);
34
35 #define GETXWORD(b) (uint16)(((b)[0] << 8) | (b)[1])
36
37 #define PUTXDWORD(b, d) \
38    (b)[0] = (byte)(((d) >> 24) & 0xFF); \
39    (b)[1] = (byte)(((d) >> 16) & 0xFF); \
40    (b)[2] = (byte)(((d) >> 8)  & 0xFF); \
41    (b)[3] = (byte)( (d)        & 0xFF);
42
43 #define GETXDWORD(b) (uint32)(((b)[0] << 24) | ((b)[1] << 16) | ((b)[2] << 8) | (b)[3])
44
45 #define PUTXQWORD(b, d) \
46    (b)[0] = (byte)(((d) >> 56) & 0xFF); \
47    (b)[1] = (byte)(((d) >> 48) & 0xFF); \
48    (b)[2] = (byte)(((d) >> 40) & 0xFF); \
49    (b)[3] = (byte)(((d) >> 32) & 0xFF); \
50    (b)[4] = (byte)(((d) >> 24) & 0xFF); \
51    (b)[5] = (byte)(((d) >> 16) & 0xFF); \
52    (b)[6] = (byte)(((d) >> 8)  & 0xFF); \
53    (b)[7] = (byte)( (d)        & 0xFF);
54
55 #define GETXQWORD(b) (uint64)(((uint64)(b)[0] << 56) | ((uint64)(b)[1] << 48) | ((uint64)(b)[2] << 40) | ((uint64)(b)[3] << 32) | ((uint64)(b)[4] << 24) | ((b)[5] << 16) | ((b)[6] << 8) | (b)[7])
56
57 static void UnusedFunction()
58 {
59    int a;
60    a.OnGetString(0,0,0);
61    a.OnFree();
62    a.OnCopy(null);
63    a.OnCompare(null);
64    a.OnSaveEdit(null,0);
65    a.OnEdit(null,null,0,0,0,0,0);
66    a.OnDisplay(null,0,0,0,0,null,null);
67    a.OnGetDataFromString(null);
68 }
69
70 default:
71 extern int __ecereVMethodID_class_OnGetString;
72 extern int __ecereVMethodID_class_OnGetDataFromString;
73 extern int __ecereVMethodID_class_OnCompare;
74 extern int __ecereVMethodID_class_OnSerialize;
75 extern int __ecereVMethodID_class_OnUnserialize;
76 extern int __ecereVMethodID_class_OnCopy;
77 public:
78
79 public class IOChannel
80 {
81 public:
82    virtual uint WriteData(byte * data, uint numBytes);
83    virtual uint ReadData(byte * data, uint numBytes);
84
85    dllexport void Serialize(typed_object data)
86    {
87       data.OnSerialize(this);
88    }
89
90    dllexport void Unserialize(typed_object & data)
91    {
92       data.OnUnserialize(this);
93    }
94
95    dllexport void Put(typed_object data)
96    {
97       data.OnSerialize(this);
98    }
99
100    dllexport void Get(typed_object & data)
101    {
102       data.OnUnserialize(this);
103    }
104 };
105
106 public class SerialBuffer : IOChannel
107 {
108 public:
109    byte * _buffer;
110    uint count;
111    uint _size;
112    uint pos;
113
114    uint WriteData(byte * bytes, uint numBytes)
115    {
116       if(this != null)
117       {
118          if(count + numBytes > _size)
119          {
120             _size = count + numBytes;
121             _size += _size/2;
122             _buffer = renew _buffer byte[_size];
123          }
124          memcpy(_buffer + count, bytes, numBytes);
125          count += numBytes;
126          return numBytes;
127       }
128       return 0;
129    }
130
131    uint ReadData(byte * bytes, uint numBytes)
132    {
133       if(this != null)
134       {
135          int read = Min(numBytes, count - pos);
136          memcpy(bytes, _buffer + pos, read);
137          pos += read;
138          return read;
139       }
140       return 0;
141    }
142
143    ~SerialBuffer()
144    {
145       Free();
146    }
147
148    dllexport void Free()
149    {
150       if(this)
151       {
152          delete _buffer;
153          count = 0;
154          _size = 0;
155          pos = 0;
156       }
157    }
158
159    // TODO: THIS IS VERY BAD!
160    property byte * buffer
161    {
162       get { return _buffer + pos; }
163       set { _buffer = value; }
164    }
165
166    property uint size
167    {
168       get { return count - pos; }
169       set { count = value; }
170    }
171 };
172
173 /*static */char * Enum_OnGetString(Class _class, int * data, char * tempString, void * fieldData, bool * needClass)
174 {
175    EnumClassData enumeration = (EnumClassData)_class.data;
176    NamedLink item;
177    for(item = enumeration.values.first; item; item = item.next)
178       if((int)item.data == *data)
179          break;
180    if(item)
181    {
182       strcpy(tempString, item.name);
183       if(!needClass || !*needClass)
184          tempString[0] = (char)toupper(tempString[0]);
185       return tempString;
186       //return item.name;
187    }
188    else
189       return null;
190 }
191
192 static bool Enum_OnGetDataFromString(Class _class, int * data, char * string)
193 {
194    EnumClassData enumeration = (EnumClassData)_class.data;
195    NamedLink item;
196    for(item = enumeration.values.first; item; item = item.next)
197    {
198       if(item.name && !strcmpi(item.name, string))
199          break;
200    }
201    if(item)
202    {
203       *data = (int)item.data;
204       return true;
205    }
206    else
207       return Integer_OnGetDataFromString(_class, data, string);
208    return false;
209 }
210
211 static void OnFree(Class _class, void * data)
212 {
213    if(_class.templateClass) _class = _class.templateClass;
214    if(_class.type == normalClass)
215    {
216       // eInstance_Delete(data);
217       eInstance_DecRef(data);
218    }
219    else if(_class.type == noHeadClass && data)
220    {
221       while(_class && _class.type == noHeadClass)
222       {
223          if(_class.Destructor)
224             _class.Destructor(data);
225          _class = _class.base;
226       }
227       delete data;
228    }
229 }
230
231 static int DataMember_OnCompare(DataMember parentMember, void * data1, void * data2)
232 {
233    DataMember member;
234    Module module = parentMember._class.module;
235    for(member = parentMember.members.first; member; member = member.next)
236    {
237       int memberResult = 0;
238       if(member.type == normalMember)
239       {
240          Class memberType = member.dataTypeClass;
241
242          if(!memberType)
243             memberType = member.dataTypeClass = eSystem_FindClass(module, member.dataTypeString);
244          if(!memberType)
245             memberType = member.dataTypeClass = eSystem_FindClass(module, "int");
246
247          if(memberType.type == structClass || memberType.type == normalClass || memberType.type == noHeadClass)
248          {
249             memberResult = memberType._vTbl[__ecereVMethodID_class_OnCompare](memberType, 
250                (byte *)data1 + member.offset, 
251                (byte *)data2 + member.offset);
252             if(memberResult)
253                return memberResult;
254          }
255          else
256          {
257             DataValue value1, value2;
258             value1.i = *(int *)((byte *)data1 + member.offset);
259             value2.i = *(int *)((byte *)data2 + member.offset);
260             memberResult = memberType._vTbl[__ecereVMethodID_class_OnCompare](memberType, &value1, &value2);
261             if(memberResult)
262                return memberResult;
263          }
264       }
265       else
266       {
267          memberResult = DataMember_OnCompare(member, 
268             (byte *)data1 + member.offset, 
269             (byte *)data2 + member.offset);
270          if(memberResult)
271             return memberResult;
272       }
273    }
274    return 0;
275 }
276
277 static int OnCompare(Class _class, void * data1, void * data2)
278 {
279    Module module = _class.module;
280    if(_class.type == normalClass || _class.type == noHeadClass || _class.type == structClass)
281    {
282       if(data1 && data2)
283       {
284          // NOTE: Comparing from top class down here... might want to reverse it
285          for(; _class && _class.type != systemClass; _class = _class.base)
286          {
287             DataMember member;
288
289             // TESTING THIS HERE...
290             if(_class.noExpansion)
291             {
292                if(data1 > data2) return 1;
293                else if(data1 < data2) return -1;
294                else
295                   return 0;
296             }
297
298             for(member = _class.membersAndProperties.first; member; member = member.next)
299             {
300                int memberResult = 0;
301                if(member.isProperty || member.type == normalMember)
302                {
303                   Class memberType = member.dataTypeClass;
304                         
305                   if(!memberType)
306                      memberType = member.dataTypeClass = eSystem_FindClass(module, member.dataTypeString);
307                   /*
308                   if(!memberType)
309                      memberType = member.dataTypeClass = eSystem_FindClass(module, "int");
310                   */
311                   if(memberType)
312                   {
313                      if(member.isProperty)
314                      {
315                         Property prop = (Property)member;
316                         if(!prop.conversion && prop.Get && prop.Set)
317                         {
318                            if(memberType.type == structClass || memberType.type == normalClass || memberType.type == noHeadClass)
319                            {
320                               if(!strcmp(memberType.dataTypeString, "char *"))
321                               {
322                                  String a = ((String(*)())(void *)prop.Get)(data1);
323                                  String b = ((String(*)())(void *)prop.Get)(data2);
324                                  memberResult = memberType._vTbl[__ecereVMethodID_class_OnCompare](memberType, a, b);
325                               }
326                            }
327                            else
328                            {
329                               DataValue value1, value2;
330                               if(!strcmp(memberType.dataTypeString, "float"))
331                               {
332                                  value1.f = ((float(*)())(void *)prop.Get)(data1);
333                                  value2.f = ((float(*)())(void *)prop.Get)(data2);
334                               }
335                               else
336                               {
337                                  value1.i = prop.Get(data1);
338                                  value2.i = prop.Get(data2);
339                               }
340                               memberResult = memberType._vTbl[__ecereVMethodID_class_OnCompare](memberType, &value1, &value2);
341                            }
342                         }
343                      }
344                      else
345                      {
346                         if(memberType.type == structClass || memberType.type == normalClass || memberType.type == noHeadClass)
347                         {
348                            if(memberType.type == normalClass || memberType.type == noHeadClass)
349                            {
350                               // TESTING THIS!
351                               memberResult = memberType._vTbl[__ecereVMethodID_class_OnCompare](memberType, 
352                                  *(void **)((byte *)data1 + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset)), 
353                                  *(void **)((byte *)data2 + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset)));
354                            }
355                            else
356                            {
357                               memberResult = memberType._vTbl[__ecereVMethodID_class_OnCompare](memberType, 
358                                  (byte *)data1 + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset), 
359                                  (byte *)data2 + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset));
360                            }
361                         }
362                         else
363                         {
364                            DataValue value1, value2;
365                            if(memberType.typeSize == 8)
366                            {
367                               value1.ui64 = *(uint64 *)((byte *)data1 + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset));
368                               value2.ui64 = *(uint64 *)((byte *)data2 + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset));
369                            }
370                            else
371                            {
372                               value1.i = *(int *)((byte *)data1 + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset));
373                               value2.i = *(int *)((byte *)data2 + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset));
374                            }
375                            memberResult = memberType._vTbl[__ecereVMethodID_class_OnCompare](memberType, &value1, &value2);
376                         }
377                      }
378                   }
379                   else
380                   {
381                      // printf("Unknown type\n");
382                   }
383                }
384                else
385                {
386                   memberResult = DataMember_OnCompare(member, 
387                      (byte *)data1 + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset), 
388                      (byte *)data2 + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset));
389                }
390                if(memberResult)
391                   return memberResult;
392             }
393          }
394       }
395       else if(!data1 && data2)
396          return 1;
397       else if(data1 && !data2)
398          return -1;
399    }
400    else if(_class.type == unitClass)
401    {
402       Class dataType = eSystem_FindClass(module, _class.dataTypeString);
403       return dataType._vTbl[__ecereVMethodID_class_OnCompare](dataType, data1, data2);
404    }
405    else
406    {
407       int result = 0;
408       if(data1 && data2)
409       {
410          if(*(void **)data1 > *(void **)data2)
411             result = 1;
412          else if(*(void **)data1 < *(void **)data2)
413             result = -1;
414       }
415       else if(!data1 && data2)
416          return 1;
417       else if(data1 && !data2)
418          return -1;
419       return result;
420    }
421    return 0;
422 }
423
424 static char * OnGetString(Class _class, void * data, char * tempString, void * fieldData, bool * needClass)
425 {
426    // WHY DOES _class.module NOT SEEM TO WORK?
427    Module module = _class.templateClass ? _class.templateClass.module : _class.module;
428    if(_class.type == enumClass)
429    {
430       return Enum_OnGetString(_class, data, tempString, fieldData, needClass);
431    }
432    else if(_class.type == unitClass)
433    {
434       Class dataType = eSystem_FindClass(module, _class.dataTypeString);
435       return (char *)dataType._vTbl[__ecereVMethodID_class_OnGetString](dataType, data, tempString, fieldData, needClass);
436    }
437    else
438    {
439       bool atMember = true;
440       bool prev = false;
441       Class mainClass = _class;
442       _class = null;
443       tempString[0] = '\0';
444       if(!data && (mainClass.type == normalClass || mainClass.type == noHeadClass)) return tempString;
445
446       while(_class != mainClass)
447       {
448          DataMember member;
449          Class lastClass = _class;
450
451          for(_class = mainClass; _class.base != lastClass && _class.base.type != systemClass; _class = _class.base);
452
453          for(member = _class.membersAndProperties.first; member; member = member.next)
454          {
455             char memberString[1024];
456             Class memberType = member.dataTypeClass;
457             char * name = member.name;
458                   
459             memberString[0] = 0;
460
461             if(!memberType)
462                memberType = member.dataTypeClass = eSystem_FindClass(module, member.dataTypeString);
463             if(!memberType)
464                memberType = member.dataTypeClass = eSystem_FindClass(module, "int");
465
466             if(member.isProperty)
467             {
468                Property prop = (Property) member;
469
470                if(!prop.conversion && prop.Get && prop.Set)
471                {
472                   if(memberType.type != structClass && (memberType.type != normalClass || !strcmp(memberType.dataTypeString, "char *")) && memberType.type != bitClass && data)
473                   {
474                      DataValue value = { 0 };
475                      if(!strcmp(prop.dataTypeString, "float"))
476                      {
477                         value.f = ((float(*)())(void *)prop.Get)(data);
478                         if(value.f)
479                         {
480                            bool needClass = true;
481                            char * result = (char *)memberType._vTbl[__ecereVMethodID_class_OnGetString](memberType, &value, memberString, null, &needClass);
482                            if(result && result != memberString)
483                               strcpy(memberString, result);
484                            // TESTING THIS HERE
485                            if(strchr(memberString, '.'))
486                               strcat(memberString, "f");
487                         }
488                      }
489                      else
490                      {
491                         value.i = prop.Get(data);
492                         if(value.i)
493                         {
494                            bool needClass = true;
495                            char * result = (char *)memberType._vTbl[__ecereVMethodID_class_OnGetString](memberType, 
496                               (memberType.type == normalClass) ? value.p : &value, memberString, null, &needClass);
497                            if(result && result != memberString)
498                               strcpy(memberString, result);
499                         }
500                      }
501                   }
502                }
503             }
504             else
505             {
506                if(member.type == normalMember)
507                {
508                   if(memberType.type == structClass || memberType.type == normalClass)
509                   {
510                      char internalMemberString[1024];
511                      byte * memberData = ((byte *)data + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset));
512                      int c;
513                      for(c = 0; c < memberType.structSize; c++)
514                         if(memberData[c])
515                            break;
516                      if(c < memberType.structSize)
517                      {
518                         bool needClass = true;
519                         char * result;
520                         if(memberType.type == normalClass)
521                            result = (char *)memberType._vTbl[__ecereVMethodID_class_OnGetString](memberType, *(Instance *)memberData, internalMemberString, null, &needClass);
522                         else
523                            result = (char *)memberType._vTbl[__ecereVMethodID_class_OnGetString](memberType, memberData, internalMemberString, null, &needClass);
524                         if(needClass)
525                         {
526                            //strcpy(memberString, memberType.name);
527                            strcat(memberString, "{ ");
528                            if(result) strcat(memberString, result);
529                            strcat(memberString, " }");
530                         }
531                         else if(result)
532                            strcpy(memberString, result);
533                      }
534                   }
535                   //else if(_class /*memberType*/.type != bitClass)
536                   else // if(_class /*memberType*/.type != bitClass)
537                   {
538                      DataValue value = { 0 };
539                      if(_class.type == bitClass)
540                      {
541                         BitMember bitMember = (BitMember) member;
542                         // TODO: Check if base type is 32 or 64 bit
543
544                         //value.ui = (((uint)data & bitMember.mask) >> bitMember.pos);
545                         value.ui64 = ((*(uint*)data & bitMember.mask) >> bitMember.pos);
546                         if(value.ui64)
547                         {
548                            bool needClass = true;
549                            char internalMemberString[1024];
550                            char * result = (char *)memberType._vTbl[__ecereVMethodID_class_OnGetString](memberType, &value, internalMemberString, null, &needClass);
551
552                            if(needClass && memberType.type != systemClass && memberType.type != enumClass && memberType.type != unitClass)
553                            {
554                               //strcpy(memberString, memberType.name);
555                               strcat(memberString, " { ");
556                               if(result) strcat(memberString, result);
557                               strcat(memberString, " }");
558                            }
559                            else if(result)
560                               strcpy(memberString, result);
561                            /*
562                            if(result && memberString != result)
563                               strcpy(memberString, result);
564                            */
565                         }
566                      }
567                      else if(!memberType.noExpansion)
568                      {
569                         // TOCHECK: Is this still right??
570                         if(memberType.typeSize <= 4)
571                         {
572                            value.i = *(int *)((byte *)data + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset));
573                            if(value.i)
574                            {
575                               bool needClass = true;
576                               char * result = (char *)memberType._vTbl[__ecereVMethodID_class_OnGetString](memberType, &value, memberString, null, &needClass);
577                               if(result && memberString != result)
578                                  strcpy(memberString, result);
579                            }
580                         }
581                         else
582                         {
583                            bool needClass = true;
584                            char * result = (char *)memberType._vTbl[__ecereVMethodID_class_OnGetString](memberType, ((byte *)data + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset)), memberString, null, &needClass);
585                            if(result && memberString != result)
586                               strcpy(memberString, result);
587                         }
588                      }
589                   }
590                   /*else
591                   {
592                      char internalMemberString[1024];
593                      byte * memberData = ((byte *)data + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset));
594                      bool needClass = true;
595                      char * result;
596                      result = (char *)memberType._vTbl[__ecereVMethodID_class_OnGetString](memberType, memberData, internalMemberString, null, &needClass);
597                      if(needClass)
598                      {
599                         //strcpy(memberString, memberType.name);
600                         strcat(memberString, "{ ");
601                         if(result) strcat(memberString, result);
602                         strcat(memberString, " }");
603                      }
604                      else if(result)
605                         strcpy(memberString, result);
606                   }*/
607                }
608                // MemberUnion
609                // MemberStruct
610             }
611             // TODO: Fix atID stuff
612             if(memberString[0])
613             {
614                if(prev)
615                   strcat(tempString, ", ");
616                if(!atMember || !strcmp(memberType.name, "bool"))
617                {
618                   strcat(tempString, name);
619                   strcat(tempString, " = ");
620                }
621
622                if(!strcmp(memberType.name, "char *"))
623                {
624                   int len = strlen(tempString);
625                   int c;
626                   strcat(tempString, "\"");
627                   len ++;
628                   for(c = 0; memberString[c]; c++)
629                   {
630                      if(memberString[c] == '\"')
631                      {
632                         strcat(tempString, "\\\"");
633                         len+=2;
634                      }
635                      else if(memberString[c] == '\\')
636                      {
637                         strcat(tempString, "\\\\");
638                         len+=2;
639                      }
640                      else
641                      {
642                         tempString[len++] = memberString[c];
643                         tempString[len] = 0;
644                      }
645                   }                              
646                   strcat(tempString, "\"");
647                }
648                else
649                   strcat(tempString, memberString);
650                atMember = true;
651
652                prev = true;
653             }
654             else if(member && (!member.isProperty || !((Property)member).conversion))
655                atMember = false;
656          }
657       }
658    }
659    return tempString;
660 }
661
662 static bool OnGetDataFromString(Class _class, void ** data, char * string)
663 {
664    bool result;
665    Module module = _class.module;
666    if(_class.type == enumClass)
667       result = Enum_OnGetDataFromString(_class, (int *)data, string);
668    else if(_class.type == unitClass)
669    {
670       Class dataType = eSystem_FindClass(module, _class.dataTypeString);
671       return dataType._vTbl[__ecereVMethodID_class_OnGetDataFromString](dataType, data, string);
672    }
673    else if(!string[0] && _class.type == normalClass)
674    {
675       // result = false;  // Why was this data = null commented?
676       *data = null;
677       return true;
678    }
679    else
680    {
681       int c;
682       char memberName[1024];
683       char memberString[10240];
684       int count = 0;
685       bool quoted = false;
686       int brackets = 0;
687       char ch;
688       bool escape = false;
689       bool gotChar;
690       uint memberOffset;
691       Class curClass = null;
692       DataMember curMember = null;
693       DataMember subMemberStack[256];
694       int subMemberStackPos = 0;
695
696       result = true;
697
698       if(_class.type == noHeadClass || _class.type == normalClass) 
699       {
700          data = *data = eInstance_New(_class);
701          if(_class.type == normalClass) 
702             ((Instance)data)._refCount++;
703       }
704       else if(/*_class.type == noHeadClass || */_class.type == structClass) 
705          memset(data, 0, _class.structSize);
706       // Bit classes cleared outside?
707
708       memberName[0] = '\0';
709
710       for(c = 0; string[c] && count < sizeof(memberString); )
711       {
712          bool found = false;
713          DataMember thisMember = null;
714
715          brackets = 0;
716          gotChar = false;
717          for(; (ch = string[c]) && count < sizeof(memberString); c++)
718          {
719             if(ch == '\"' && !escape)
720             {
721                quoted ^= true;
722             }
723             else if(quoted)
724             {
725                if(!escape && ch == '\\')
726                {
727                   escape = true;
728                }
729                else
730                {
731                   memberString[count++] = ch;
732                   escape = false;
733                }
734             }
735             // TOFIX: OnGetDataFromString is far from ready as a generic object notation reader...
736             // It has mostly been tested/used for entering data in the IDE's property sheet, as well as for parsing code in the Code Editor
737             // Is it used by the compiler?
738             else if(ch == ' ') // || ch == '\n' || ch == '\t' || ch == '\r')
739             {
740                if(gotChar) 
741                   memberString[count++] = ch;
742             }
743             else if(ch == ',')
744             {
745                if(brackets)
746                {
747                   memberString[count++] = ch;
748                }
749                else
750                {
751                   c++;
752                   break;
753                }
754             }
755             else if(ch == '{')
756             {
757                // If bracket is not initialization
758                if(gotChar && !brackets) 
759                {
760                   count = 0;
761                   gotChar = false;
762                }
763
764                if(brackets)
765                {
766                   memberString[count++] = ch;
767                   gotChar = true;
768                }
769                brackets++;
770             }
771             else if(ch == '}')
772             {
773                brackets--;
774                if(brackets)
775                {
776                   gotChar = true;
777                   memberString[count++] = ch;
778                }
779             }
780             else if(ch == '=')
781             {
782                if(brackets)
783                {
784                   memberString[count++] = ch;
785                }
786                else
787                {
788                   memberString[count] = '\0';
789                   //TrimLSpaces(memberString, memberName);
790                   //TrimRSpaces(memberName, memberString);
791                   //strcpy(memberName, memberString);
792             
793                   TrimRSpaces(memberString, memberName);
794                   count = 0;
795                   gotChar = false;
796                }
797             }
798             else
799             {
800                memberString[count++] = ch;
801                gotChar = true;
802             }
803          }
804
805          memberString[count] = '\0';
806          TrimRSpaces(memberString, memberString);
807
808          if(memberName[0])
809          {
810             DataMember _subMemberStack[256];
811             int _subMemberStackPos = 0;
812
813             thisMember = eClass_FindDataMemberAndOffset(_class, memberName, &memberOffset, _class.module, _subMemberStack, &_subMemberStackPos);
814
815             if(!thisMember)
816                thisMember = (DataMember)eClass_FindProperty(_class, memberName, _class.module);
817             if(thisMember)
818             {
819                if(thisMember.memberAccess == publicAccess)
820                {
821                   curMember = thisMember;
822                   curClass = thisMember._class;
823                   memcpy(subMemberStack, _subMemberStack, sizeof(int) * _subMemberStackPos);
824                   subMemberStackPos = _subMemberStackPos;
825                }
826                found = true;
827             }
828          }
829          else
830          {
831             eClass_FindNextMember(_class, &curClass, (DataMember *)&curMember, subMemberStack, &subMemberStackPos);
832             thisMember = curMember;
833             if(thisMember)
834             {
835                found = true;
836                eClass_FindDataMemberAndOffset(_class, thisMember.name, &memberOffset, _class.module, null, null);
837             }
838          }
839          if(found)
840          {
841             Class memberType = thisMember.dataTypeClass;
842             
843             if(!memberType)
844                memberType = thisMember.dataTypeClass = eSystem_FindClass(module, thisMember.dataTypeString);
845             if(!memberType)
846                memberType = thisMember.dataTypeClass = eSystem_FindClass(module, "int");
847             if(memberType.type == structClass)
848             {
849                if(thisMember)
850                {
851                   if(!memberType._vTbl[__ecereVMethodID_class_OnGetDataFromString](memberType, 
852                      (byte *)data + (((thisMember._class.type == normalClass) ? thisMember._class.offset : 0) + memberOffset), memberString))
853                      result = false;
854                }
855             }
856             else
857             {
858                DataValue value = { 0 };
859                // Patch for hotKey crash ( #556 )
860                // Key has a member KeyCode, which inherits from Key
861                // We don't want KeyCode to use its base class OnGetDataFromString
862                if(memberType._vTbl[__ecereVMethodID_class_OnGetDataFromString] == _class._vTbl[__ecereVMethodID_class_OnGetDataFromString])
863                {
864                   if(!OnGetDataFromString(memberType, &value, memberString))
865                      result = false;
866                }
867                else if(!memberType._vTbl[__ecereVMethodID_class_OnGetDataFromString](memberType, &value, memberString))
868                   result = false;
869                if(thisMember && !thisMember.isProperty)
870                {
871                   if(_class.type == bitClass)
872                   {
873                      BitMember bitMember = (BitMember) thisMember;
874                      // TODO: Check if bit _class is 32 or 64 bit
875                      *(uint *)data = (uint32)(((*(uint *)data & ~bitMember.mask)) | ((value.ui64<<bitMember.pos)&bitMember.mask));
876                   }
877                   else
878                      *(int *)((byte *)data + (((thisMember._class.type == normalClass) ? thisMember._class.offset : 0) + thisMember.offset)) = value.i;
879                }
880                else if(thisMember.isProperty && ((Property)thisMember).Set)
881                   ((Property)thisMember).Set(data, value.i);
882             }
883          }
884          else
885             result = false;
886             
887          count = 0;
888          memberName[0] = '\0';
889       }
890    }
891    return result;
892 }
893
894 static void OnCopy(Class _class, void ** data, void * newData)
895 {
896    // TO IMPROVE: Inherit from Unit class for better performance?
897    if(_class.type == unitClass || _class.type == bitClass || _class.type == enumClass)
898    {
899       Class dataType = eSystem_FindClass(_class.module, _class.dataTypeString);
900       if(dataType)
901          dataType._vTbl[__ecereVMethodID_class_OnCopy](dataType, data, newData);
902    }
903    else if(_class.type != structClass && _class.type != systemClass)
904    {
905       *data = newData;
906    }
907    // Here we have either a structClass or a systemClass
908    else if(newData)
909       memcpy(data, newData, _class.typeSize);
910    else
911       memset(data, 0, _class.typeSize);
912 }
913
914 static int DataMember_OnSerialize(DataMember parentMember, void * data, IOChannel channel)
915 {
916    DataMember member;
917    Module module = parentMember._class.module;
918    for(member = parentMember.members.first; member; member = member.next)
919    {
920       if(member.type == normalMember)
921       {
922          Class memberType = member.dataTypeClass;
923
924          if(!memberType)
925             memberType = member.dataTypeClass = eSystem_FindClass(module, member.dataTypeString);
926          if(!memberType)
927             memberType = member.dataTypeClass = eSystem_FindClass(module, "int");
928
929          if(memberType.type == structClass || memberType.type == normalClass || memberType.type == noHeadClass)
930          {
931             memberType._vTbl[__ecereVMethodID_class_OnSerialize](memberType, (byte *)data + member.offset, channel);
932          }
933          else
934          {
935             DataValue value;
936             value.i = *(int *)((byte *)data + member.offset);
937             memberType._vTbl[__ecereVMethodID_class_OnSerialize](memberType, &value);
938          }
939       }
940       else
941       {
942          DataMember_OnSerialize(member, (byte *)data + member.offset, channel);
943       }
944    }
945    return 0;
946 }
947
948 static void OnSerialize(Class _class, void * data, IOChannel channel)
949 {
950    Module module = _class.module;
951    // TO IMPROVE: Inherit from Unit class for better performance?
952    if(_class.type == unitClass || _class.type == bitClass || _class.type == enumClass)
953    {
954       Class dataType = eSystem_FindClass(module, _class.dataTypeString);
955       if(dataType)
956          dataType._vTbl[__ecereVMethodID_class_OnSerialize](dataType, data, channel);
957    }
958    else if(_class.type == normalClass || _class.type == noHeadClass || _class.type == structClass)
959    {
960       if(data)
961       {
962          Class lastClass = null;
963          while(lastClass != _class)
964          {
965             DataMember member;
966             for(; _class && (!_class.base || _class.base.type != systemClass) && _class != lastClass; _class = _class.base);
967             lastClass = _class;
968
969             for(member = _class.membersAndProperties.first; member; member = member.next)
970             {
971                if(member.isProperty || member.type == normalMember)
972                {
973                   Class memberType = member.dataTypeClass;
974                         
975                   if(!memberType)
976                      memberType = member.dataTypeClass = eSystem_FindClass(module, member.dataTypeString);
977                   if(memberType)
978                   {
979                      if(member.isProperty)
980                      {
981                         /*Property prop = (Property)member;
982                         if(!prop.conversion && prop.Get && prop.Set)
983                         {
984                            if(memberType.type == structClass || memberType.type == normalClass || memberType.type == noHeadClass)
985                            {
986
987                            }
988                            else
989                            {
990                               DataValue value;
991                               if(!strcmp(memberType.dataTypeString, "float"))
992                               {
993                                  value.f = ((float(*)())(void *)prop.Get)(data);
994                               }
995                               else
996                               {
997                                  value.i = prop.Get(data);
998                               }
999                               memberType._vTbl[__ecereVMethodID_class_OnSerialize](memberType, &value, channel);
1000                            }
1001                         }*/
1002                      }
1003                      else
1004                      {
1005                         if(!strcmp(memberType.name, "String"))
1006                         {
1007                            memberType._vTbl[__ecereVMethodID_class_OnSerialize](memberType, *(String *)((byte *)data + member._class.offset + member.offset), channel);
1008                         }
1009                         else
1010                            memberType._vTbl[__ecereVMethodID_class_OnSerialize](memberType, ((byte *)data + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset)), channel);
1011                      }
1012                   }
1013                   else
1014                   {
1015                      // printf("Unknown type\n");
1016                   }
1017                }
1018                else
1019                {
1020                   DataMember_OnSerialize(member, (byte *)data + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset), channel);
1021                }
1022             }
1023          }
1024       }
1025    }
1026 }
1027
1028 static int DataMember_OnUnserialize(DataMember parentMember, void * data, IOChannel channel)
1029 {
1030    DataMember member;
1031    Module module = parentMember._class.module;
1032    for(member = parentMember.members.first; member; member = member.next)
1033    {
1034       if(member.type == normalMember)
1035       {
1036          Class memberType = member.dataTypeClass;
1037
1038          if(!memberType)
1039             memberType = member.dataTypeClass = eSystem_FindClass(module, member.dataTypeString);
1040          if(!memberType)
1041             memberType = member.dataTypeClass = eSystem_FindClass(module, "int");
1042
1043          if(memberType.type == structClass || memberType.type == normalClass || memberType.type == noHeadClass)
1044          {
1045             memberType._vTbl[__ecereVMethodID_class_OnUnserialize](memberType, (byte *)data + member.offset, channel);
1046          }
1047          else
1048          {
1049             DataValue value;
1050             memberType._vTbl[__ecereVMethodID_class_OnUnserialize](memberType, &value);
1051             *(int *)((byte *)data + member.offset) = value.i;
1052          }
1053       }
1054       else
1055       {
1056          DataMember_OnUnserialize(member, (byte *)data + member.offset, channel);
1057       }
1058    }
1059    return 0;
1060 }
1061  
1062 static void OnUnserialize(Class _class, void ** data, IOChannel channel)
1063 {
1064    Module module = _class.module;
1065    if(_class.type == unitClass || _class.type == bitClass || _class.type == enumClass)
1066    {
1067       Class dataType = eSystem_FindClass(module, _class.dataTypeString);
1068       if(dataType)
1069          dataType._vTbl[__ecereVMethodID_class_OnUnserialize](dataType, data, channel);
1070    }
1071    else if(_class.type == normalClass || _class.type == noHeadClass || _class.type == structClass)
1072    {
1073       if(data)
1074       {
1075          Class lastClass = null;
1076          if(_class.type == normalClass || _class.type == noHeadClass)
1077          {
1078             data = *data = eInstance_New(_class);
1079             if(_class.type == normalClass) 
1080                ((Instance)data)._refCount++;
1081          }
1082          else if(/*_class.type == noHeadClass || */_class.type == structClass) 
1083             memset(data, 0, _class.structSize);
1084
1085          while(lastClass != _class)
1086          {
1087             DataMember member;
1088             for(; _class && (!_class.base || _class.base.type != systemClass) && _class != lastClass; _class = _class.base);
1089             lastClass = _class;
1090
1091             for(member = _class.membersAndProperties.first; member; member = member.next)
1092             {
1093                if(member.isProperty || member.type == normalMember)
1094                {
1095                   Class memberType = member.dataTypeClass;
1096                         
1097                   if(!memberType)
1098                      memberType = member.dataTypeClass = eSystem_FindClass(module, member.dataTypeString);
1099                   if(memberType)
1100                   {
1101                      if(member.isProperty)
1102                      {
1103                         /*Property prop = (Property)member;
1104                         if(!prop.conversion && prop.Get && prop.Set)
1105                         {
1106                            if(memberType.type == structClass || memberType.type == normalClass || memberType.type == noHeadClass)
1107                            {
1108
1109                            }
1110                            else
1111                            {
1112                               DataValue value;
1113                               memberType._vTbl[__ecereVMethodID_class_OnUnserialize](memberType, &value, channel);
1114                               prop.Set(data, value.i);
1115                            }
1116                         }*/
1117                      }
1118                      else
1119                         memberType._vTbl[__ecereVMethodID_class_OnUnserialize](memberType, 
1120                            (byte *)data + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset), channel);
1121                   }
1122                   else
1123                   {
1124                      // printf("Unknown type\n");
1125                   }
1126                }
1127                else
1128                {
1129                   DataMember_OnUnserialize(member, (byte *)data + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset), channel);
1130                }
1131             }
1132          }
1133       }
1134    }
1135 }
1136
1137 // Integer
1138 static int Integer_OnCompare(Class _class, int * data1, int * data2)
1139 {
1140    int result = 0;
1141    if(*data1 > *data2)
1142       result = 1;
1143    else if(*data1 < *data2)
1144       result = -1;
1145    return result;
1146 }
1147
1148 /*static */char * Integer_OnGetString(Class _class, int * data, char * string, void * fieldData, bool * needClass)
1149 {
1150    sprintf(string, "%d", *data);
1151    return string;
1152 }
1153
1154 static bool Integer_OnGetDataFromString(Class _class, int * data, char * string)
1155 {
1156    char * end;
1157    int result = strtol(string, &end, 0);
1158
1159    if(end > string)
1160    {
1161       *data = result;
1162       return true;
1163    }
1164    return false;
1165 }
1166
1167 static int UInteger_OnCompare(Class _class, unsigned int * data1, unsigned int * data2)
1168 {
1169    int result = 0;
1170    if(data1 && !data2)
1171       result = 1;
1172    else if(!data1 && data2)
1173       result = -1;
1174    else if(!data1 && !data2)
1175       result = 0;
1176    else if(*data1 > *data2)
1177       result = 1;
1178    else if(*data1 < *data2)
1179       result = -1;
1180    return result;
1181 }
1182
1183 static char * UInteger_OnGetString(Class _class, unsigned int * data, char * string, void * fieldData, bool * needClass)
1184 {
1185    sprintf(string, "%u", *data);
1186    return string;
1187 }
1188
1189 static bool UInteger_OnGetDataFromString(Class _class, unsigned int * data, char * string)
1190 {
1191    char * end;
1192    uint result = strtoul(string, &end, 0);
1193    if(end > string)
1194    {
1195       *data = result;
1196       return true;
1197    }
1198    return false;
1199 }
1200
1201 static int Byte_OnCompare(Class _class, byte * data1, byte * data2)
1202 {
1203    int result = 0;
1204    if(*data1 > *data2)
1205       result = 1;
1206    else if(*data1 < *data2)
1207       result = -1;
1208    return result;
1209 }
1210
1211 static char * Byte_OnGetString(Class _class, byte * data, char * string, void * fieldData, bool * needClass)
1212 {
1213    sprintf(string, "%u", (int)*data);
1214    return string;
1215 }
1216
1217 static char * Char_OnGetString(Class _class, char * data, char * string, void * fieldData, bool * needClass)
1218 {
1219    if(needClass && *needClass)
1220    {
1221       char ch = *data;
1222       if(ch == '\t')      strcpy(string, "'\t'");
1223       else if(ch == '\n') strcpy(string, "'\n'");
1224       else if(ch == '\r') strcpy(string, "'\r'");
1225       else if(ch == '\a') strcpy(string, "'\a'");
1226       else if(ch == '\\') strcpy(string, "'\\'");
1227       else if(ch < 32 || ch >= 127)    sprintf(string, "'\o'", ch);
1228       else sprintf(string, "'%c'", ch);
1229    }
1230    else
1231       sprintf(string, "%c", *data);
1232    return string;
1233 }
1234
1235 static bool Byte_OnGetDataFromString(Class _class, byte * data, char * string)
1236 {
1237    char * end;
1238    byte result = (byte)strtoul(string, &end, 0);
1239    if(end > string)
1240    {
1241       *data = result;
1242       return true;
1243    }
1244    return false;
1245 }
1246
1247 static char * Int64_OnGetString(Class _class, int64 * data, char * string, void * fieldData, bool * needClass)
1248 {
1249    sprintf(string, FORMAT64D, *data);
1250    return string;
1251 }
1252
1253 static char * UInt64_OnGetString(Class _class, uint64 * data, char * string, void * fieldData, bool * needClass)
1254 {
1255    sprintf(string, FORMAT64U, *data);
1256    return string;
1257 }
1258
1259 /*static */void Byte_OnSerialize(Class _class, byte * data, IOChannel channel)
1260 {
1261    channel.WriteData(data, 1);
1262 }
1263
1264 /*static */void Byte_OnUnserialize(Class _class, byte * data, IOChannel channel)
1265 {
1266    if(channel.ReadData(data, 1) != 1)
1267       *data = 0;
1268 }
1269
1270
1271 /*static */void Int_OnSerialize(Class _class, int * data, IOChannel channel)
1272 {
1273    byte bytes[4];
1274    PUTXDWORD(bytes, * data);
1275    channel.WriteData(bytes, 4);
1276 }
1277
1278 /*static */void Int_OnUnserialize(Class _class, int * data, IOChannel channel)
1279 {
1280    byte bytes[4];
1281    if(channel.ReadData(bytes, 4) == 4)
1282       *data = GETXDWORD(bytes);   
1283    else
1284       *data = 0;
1285 }
1286
1287 /*static */void Int64_OnSerialize(Class _class, int64 * data, IOChannel channel)
1288 {
1289    byte bytes[8];
1290    PUTXQWORD(bytes, * data);
1291    channel.WriteData(bytes, 8);
1292 }
1293
1294 /*static */void Int64_OnUnserialize(Class _class, int64 * data, IOChannel channel)
1295 {
1296    byte bytes[8];
1297    if(channel.ReadData(bytes, 8) == 8)
1298       *data = GETXQWORD(bytes);   
1299    else
1300       *data = 0;
1301 }
1302
1303 /*static */void Word_OnSerialize(Class _class, uint16 * data, IOChannel channel)
1304 {
1305    byte bytes[2];
1306    PUTXWORD(bytes, * data);
1307    channel.WriteData(bytes, 2);
1308 }
1309
1310 /*static */void Word_OnUnserialize(Class _class, uint16 * data, IOChannel channel)
1311 {
1312    byte bytes[2];
1313    if(channel.ReadData(bytes, 2) == 2)
1314       *data = GETXWORD(bytes);   
1315    else
1316       *data = 0;
1317 }
1318
1319 static void RegisterClass_Integer(Module module)
1320 {
1321    Class integerClass = eSystem_RegisterClass(normalClass, "int", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1322    integerClass.type = systemClass;
1323    delete integerClass.dataTypeString;
1324    integerClass.dataTypeString = CopyString("int");
1325    integerClass.structSize = 0;
1326    integerClass.typeSize = sizeof(int);
1327    
1328    eClass_AddMethod(integerClass, "OnCompare", null, Integer_OnCompare, publicAccess);
1329    eClass_AddMethod(integerClass, "OnGetString", null, Integer_OnGetString, publicAccess);
1330    eClass_AddMethod(integerClass, "OnGetDataFromString", null, Integer_OnGetDataFromString, publicAccess);
1331    eClass_AddMethod(integerClass, "OnSerialize", null, Int_OnSerialize, publicAccess);
1332    eClass_AddMethod(integerClass, "OnUnserialize", null, Int_OnUnserialize, publicAccess);
1333
1334    integerClass = eSystem_RegisterClass(normalClass, "int64", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1335    integerClass.type = systemClass;
1336    integerClass.structSize = 0;
1337    integerClass.typeSize = sizeof(int64);
1338    delete integerClass.dataTypeString;
1339    integerClass.dataTypeString = CopyString("int64");
1340    eClass_AddMethod(integerClass, "OnGetString", null, Int64_OnGetString, publicAccess);
1341
1342    /*
1343    eClass_AddMethod(integerClass, "OnCompare", null, Integer64_OnCompare, publicAccess);
1344    eClass_AddMethod(integerClass, "OnGetString", null, Integer64_OnGetString, publicAccess);
1345    eClass_AddMethod(integerClass, "OnGetDataFromString", null, Integer64_OnGetDataFromString, publicAccess);
1346    */
1347    eClass_AddMethod(integerClass, "OnSerialize", null, Int64_OnSerialize, publicAccess);
1348    eClass_AddMethod(integerClass, "OnUnserialize", null, Int64_OnUnserialize, publicAccess);
1349
1350    integerClass = eSystem_RegisterClass(normalClass, "uint", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1351    integerClass.type = systemClass;
1352    delete integerClass.dataTypeString;
1353    integerClass.dataTypeString = CopyString("unsigned int");
1354    integerClass.structSize = 0;
1355    integerClass.typeSize = sizeof(uint);
1356    eClass_AddMethod(integerClass, "OnCompare", null, UInteger_OnCompare, publicAccess);
1357    eClass_AddMethod(integerClass, "OnGetString", null, UInteger_OnGetString, publicAccess);
1358    eClass_AddMethod(integerClass, "OnGetDataFromString", null, UInteger_OnGetDataFromString, publicAccess);
1359    eClass_AddMethod(integerClass, "OnSerialize", null, Int_OnSerialize, publicAccess);
1360    eClass_AddMethod(integerClass, "OnUnserialize", null, Int_OnUnserialize, publicAccess);
1361
1362    integerClass = eSystem_RegisterClass(normalClass, "unsigned int", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1363    integerClass.type = systemClass;
1364    delete integerClass.dataTypeString;
1365    integerClass.dataTypeString = CopyString("unsigned int");
1366    integerClass.structSize = 0;
1367    integerClass.typeSize = sizeof(uint);
1368
1369    eClass_AddMethod(integerClass, "OnCompare", null, UInteger_OnCompare, publicAccess);
1370    eClass_AddMethod(integerClass, "OnGetString", null, UInteger_OnGetString, publicAccess);
1371    eClass_AddMethod(integerClass, "OnGetDataFromString", null, UInteger_OnGetDataFromString, publicAccess);
1372    eClass_AddMethod(integerClass, "OnSerialize", null, Int_OnSerialize, publicAccess);
1373    eClass_AddMethod(integerClass, "OnUnserialize", null, Int_OnUnserialize, publicAccess);
1374
1375    integerClass = eSystem_RegisterClass(normalClass, "uint16", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1376    integerClass.type = systemClass;
1377    delete integerClass.dataTypeString;
1378    integerClass.dataTypeString = CopyString("unsigned short");
1379    integerClass.structSize = 0;
1380    integerClass.typeSize = sizeof(uint16);
1381
1382    eClass_AddMethod(integerClass, "OnSerialize", null, Word_OnSerialize, publicAccess);
1383    eClass_AddMethod(integerClass, "OnUnserialize", null, Word_OnUnserialize, publicAccess);
1384
1385    integerClass = eSystem_RegisterClass(normalClass, "short", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1386    integerClass.type = systemClass;
1387    delete integerClass.dataTypeString;
1388    integerClass.dataTypeString = CopyString("short");
1389    integerClass.structSize = 0;
1390    integerClass.typeSize = sizeof(short);
1391
1392    eClass_AddMethod(integerClass, "OnSerialize", null, Word_OnSerialize, publicAccess);
1393    eClass_AddMethod(integerClass, "OnUnserialize", null, Word_OnUnserialize, publicAccess);
1394
1395    /*
1396    integerClass = eSystem_RegisterClass(normalClass, "uint32", null, 0, 0, null, null, module, baseSystemAccess);
1397    integerClass.type = systemClass;
1398    delete integerClass.dataTypeString;
1399    integerClass.dataTypeString = CopyString("uint32");
1400    eClass_AddMethod(integerClass, "OnCompare", null, UInteger_OnCompare, publicAccess);
1401    eClass_AddMethod(integerClass, "OnGetString", null, UInteger_OnGetString, publicAccess);
1402    eClass_AddMethod(integerClass, "OnGetDataFromString", null, UInteger_OnGetDataFromString, publicAccess);
1403    */
1404    integerClass = eSystem_RegisterClass(normalClass, "uint32", "uint", 0, 0, null, null, module, baseSystemAccess, publicAccess);
1405    integerClass.type = systemClass;
1406    delete integerClass.dataTypeString;
1407    integerClass.dataTypeString = CopyString("unsigned int");
1408    integerClass.structSize = 0;
1409    integerClass.typeSize = sizeof(uint32);
1410
1411    integerClass = eSystem_RegisterClass(normalClass, "uint64", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1412    integerClass.type = systemClass;
1413    delete integerClass.dataTypeString;
1414    integerClass.dataTypeString = CopyString("uint64");
1415    integerClass.structSize = 0;
1416    integerClass.typeSize = sizeof(uint64);
1417    eClass_AddMethod(integerClass, "OnGetString", null, UInt64_OnGetString, publicAccess);
1418    eClass_AddMethod(integerClass, "OnSerialize", null, Int64_OnSerialize, publicAccess);
1419    eClass_AddMethod(integerClass, "OnUnserialize", null, Int64_OnUnserialize, publicAccess);
1420
1421    integerClass = eSystem_RegisterClass(normalClass, "byte", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1422    integerClass.type = systemClass;
1423    delete integerClass.dataTypeString;
1424    integerClass.dataTypeString = CopyString("unsigned char");
1425    integerClass.structSize = 0;
1426    integerClass.typeSize = sizeof(byte);
1427    eClass_AddMethod(integerClass, "OnCompare", null, Byte_OnCompare, publicAccess);
1428    eClass_AddMethod(integerClass, "OnGetString", null, Byte_OnGetString, publicAccess);
1429    eClass_AddMethod(integerClass, "OnGetDataFromString", null, Byte_OnGetDataFromString, publicAccess);
1430    eClass_AddMethod(integerClass, "OnSerialize", null, Byte_OnSerialize, publicAccess);
1431    eClass_AddMethod(integerClass, "OnUnserialize", null, Byte_OnUnserialize, publicAccess);
1432
1433    integerClass = eSystem_RegisterClass(normalClass, "char", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1434    integerClass.type = systemClass;
1435    delete integerClass.dataTypeString;
1436    integerClass.dataTypeString = CopyString("char");
1437    integerClass.structSize = 0;
1438    integerClass.typeSize = sizeof(char);
1439    eClass_AddMethod(integerClass, "OnCompare", null, Byte_OnCompare, publicAccess);
1440    eClass_AddMethod(integerClass, "OnGetString", null, Char_OnGetString, publicAccess);
1441    eClass_AddMethod(integerClass, "OnGetDataFromString", null, Byte_OnGetDataFromString, publicAccess);
1442    eClass_AddMethod(integerClass, "OnSerialize", null, Byte_OnSerialize, publicAccess);
1443    eClass_AddMethod(integerClass, "OnUnserialize", null, Byte_OnUnserialize, publicAccess);
1444 }
1445
1446 // Float
1447 static int Float_OnCompare(Class _class, float * data1, float * data2)
1448 {
1449    int result = 0;
1450    if(*data1 > *data2)
1451       result = 1;
1452    else if(*data1 < *data2)
1453       result = -1;
1454    return result;
1455 }
1456
1457 static char * Float_OnGetString(Class _class, float * data, char * string, void * fieldData, bool * needClass)
1458 {
1459    int c;
1460    int last = 0;
1461    int numDigits = 7, num = 1;
1462    char format[10];
1463    while(numDigits && num < *data) numDigits--, num *= 10;
1464    sprintf(format, "%%.%df", numDigits);
1465
1466    //sprintf(string, "%f", *data);
1467    sprintf(string, format, *data);
1468
1469    c = strlen(string)-1;
1470    for( ; c >= 0; c--)
1471    {
1472       if(string[c] != '0') 
1473          last = Max(last, c);
1474       if(string[c] == '.')
1475       {
1476          if(last == c)
1477             string[c] = 0;
1478          else
1479             string[last+1] = 0;
1480          break;
1481       }
1482    }
1483    return string;
1484 }
1485
1486 static bool Float_OnGetDataFromString(Class _class, float * data, char * string)
1487 {
1488    char * end;
1489    float result = (float)strtod(string, &end);
1490    //*data = atof(string);
1491    if(end > string)
1492    {
1493       *data = result;
1494       return true;
1495    }
1496    return false;
1497 }
1498
1499 static void Float_OnSerialize(Class _class, float * data, IOChannel channel)
1500 {
1501    byte bytes[4];
1502    PUTXDWORD(bytes, * (uint *)data);
1503    channel.WriteData(bytes, 4);
1504 }
1505
1506 static void Float_OnUnserialize(Class _class, float * data, IOChannel channel)
1507 {
1508    byte bytes[4];
1509    if(channel.ReadData(bytes, 4) == 4)
1510       *(uint *)data = GETXDWORD(bytes);   
1511    else
1512       *data = 0;
1513 }
1514
1515 static void RegisterClass_Float(Module module)
1516 {
1517    Class floatClass = eSystem_RegisterClass(normalClass, "float", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1518    floatClass.type = systemClass;
1519    delete floatClass.dataTypeString;
1520    floatClass.dataTypeString = CopyString("float");
1521    floatClass.structSize = 0;
1522    floatClass.typeSize = sizeof(float);
1523    eClass_AddMethod(floatClass, "OnCompare", null, Float_OnCompare, publicAccess);
1524    eClass_AddMethod(floatClass, "OnGetString", null, Float_OnGetString, publicAccess);
1525    eClass_AddMethod(floatClass, "OnGetDataFromString", null, Float_OnGetDataFromString, publicAccess);
1526    eClass_AddMethod(floatClass, "OnSerialize", null, Float_OnSerialize, publicAccess);
1527    eClass_AddMethod(floatClass, "OnUnserialize", null, Float_OnUnserialize, publicAccess);
1528 }
1529
1530 // Double
1531 static int Double_OnCompare(Class _class, double * data1, double * data2)
1532 {
1533    int result = 0;
1534    if(*data1 > *data2)
1535       result = 1;
1536    else if(*data1 < *data2)
1537       result = -1;
1538    return result;
1539 }
1540
1541 static char * Double_OnGetString(Class _class, double * data, char * string, void * fieldData, bool * needClass)
1542 {
1543    int c;
1544    int last = 0;
1545    //sprintf(string, "%.20f", *data);
1546    if(runtimePlatform == win32)
1547    // sprintf(string, "%.16g", *data);
1548       sprintf(string, "%.15g", *data);
1549    else
1550       sprintf(string, "%.13lf", *data);
1551
1552    c = strlen(string)-1;
1553    for( ; c >= 0; c--)
1554    {
1555       if(string[c] != '0') 
1556          last = Max(last, c);
1557       if(string[c] == '.')
1558       {
1559          if(last == c)
1560             string[c] = 0;
1561          else
1562             string[last+1] = 0;
1563          break;
1564       }
1565    }
1566    return string;
1567 }
1568
1569 static bool Double_OnGetDataFromString(Class _class, double * data, char * string)
1570 {
1571    char * end;
1572    double result;
1573    //*data = (double)strtod(string, null);
1574    result = strtod(string, &end);
1575    if(end > string)
1576    {
1577       *data = result;
1578       return true;
1579    
1580     }
1581     return false;
1582 }
1583
1584 static void Double_OnSerialize(Class _class, double * data, IOChannel channel)
1585 {
1586    byte bytes[8];
1587    PUTXQWORD(bytes, * (uint64 *)data);
1588    channel.WriteData(bytes, 8);
1589 }
1590
1591 static void Double_OnUnserialize(Class _class, double * data, IOChannel channel)
1592 {
1593    byte bytes[8];
1594    if(channel.ReadData(bytes, 8) == 8)
1595       *(uint64 *)data = GETXQWORD(bytes);
1596    else
1597       *data = 0;
1598 }
1599
1600 static void RegisterClass_Double(Module module)
1601 {
1602    Class doubleClass = eSystem_RegisterClass(normalClass, "double", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1603    doubleClass.type = systemClass;
1604    delete doubleClass.dataTypeString;
1605    doubleClass.dataTypeString = CopyString("double");
1606    doubleClass.structSize = 0;
1607    doubleClass.typeSize = sizeof(double);
1608    eClass_AddMethod(doubleClass, "OnCompare", null, Double_OnCompare, publicAccess);
1609    eClass_AddMethod(doubleClass, "OnGetString", null, Double_OnGetString, publicAccess);
1610    eClass_AddMethod(doubleClass, "OnGetDataFromString", null, Double_OnGetDataFromString, publicAccess);
1611    eClass_AddMethod(doubleClass, "OnSerialize", null, Double_OnSerialize, publicAccess);
1612    eClass_AddMethod(doubleClass, "OnUnserialize", null, Double_OnUnserialize, publicAccess);
1613 }
1614
1615 public struct StaticString
1616 {
1617    char string[1];
1618
1619    void OnSerialize(IOChannel channel)
1620    {
1621       int len = this ? strlen(string) : 0;
1622       channel.WriteData(this ? string : "", len+1);
1623    }
1624
1625    void OnUnserialize(IOChannel channel)
1626    {
1627       if(this)
1628       {
1629          int c;
1630          uint size;
1631
1632          for(c = 0; channel.ReadData(&string[c], 1) && string[c]; c++);
1633          string[c++] = '\0';
1634       }
1635    }
1636
1637    int OnCompare(StaticString string2)
1638    {
1639       int result = 0;
1640       if(this && string2)
1641          result = strcmpi(string, string2.string);
1642       else if(!this && string2)
1643          result = -1;   // INVERTED THESE 2 CASES
1644       else if(this && !string2)
1645          result = 1;
1646       return result;
1647    }
1648
1649    char * OnGetString(char * tempString, void * fieldData, bool * needClass)
1650    {
1651       return (char *)(this ? string : null); // Cast for memguard
1652    }
1653
1654    void OnFree()
1655    {
1656    }
1657 };
1658
1659 static void String_OnCopy(Class _class, char ** data, char * newData)
1660 {
1661    if(newData)
1662    {
1663       int len = strlen(newData);
1664       if(len)
1665       {
1666          *data = eSystem_New(len+1);
1667          memcpy(*data, newData, len+1);
1668       }
1669       else
1670          *data = null;
1671    }
1672    else
1673       *data = null;
1674 }
1675
1676 static bool String_OnGetDataFromString(Class _class, char ** data, char * newData)
1677 {
1678    if(newData)
1679    {
1680       int len = strlen(newData);
1681       if(len)
1682       {
1683          *data = eSystem_New(len+1);
1684          memcpy(*data, newData, len+1);
1685       }
1686       else
1687          *data = null;
1688    }
1689    return true;
1690 }
1691  
1692 /*static */int String_OnCompare(Class _class, char * string1, char * string2)
1693 {
1694    int result = 0;
1695    if(string1 && string2)
1696       result = strcmpi(string1, string2);
1697    else if(!string1 && string2)
1698       result = 1;
1699    else if(string1 && !string2)
1700       result = -1;
1701    return result;
1702 }
1703
1704 static char * String_OnGetString(Class _class, char * string, char * tempString, void * fieldData, bool * needClass)
1705 {
1706    return string;
1707 }
1708
1709 static void String_OnFree(Class _class, char * string)
1710 {
1711    if(string) 
1712    {
1713       eSystem_Delete(string);
1714    }
1715 }
1716
1717 static void String_OnSerialize(Class _class, char * string, IOChannel channel)
1718 {
1719    int len = string ? strlen(string) : 0;
1720    channel.WriteData(string ? string : "", len+1);
1721 }
1722
1723 static void String_OnUnserialize(Class _class, char * * string, IOChannel channel)
1724 {
1725    if(string)
1726    {
1727       int c;
1728       uint size = 64;
1729
1730       *string = new char[size];
1731       for(c = 0; channel.ReadData(&(*string)[c], 1) && (*string)[c]; c++)
1732       {
1733          if(c == size - 1)
1734          {
1735             size += size / 2;
1736             *string = renew *string char[size];
1737          }
1738       }
1739       (*string)[c++] = '\0';
1740       if(!UTF8Validate(*string))
1741       {
1742          char * newString = new char[c*2];
1743          ISO8859_1toUTF8(*string, newString, c*2);
1744          delete *string;
1745          *string = renew newString char[strlen(newString)+1];
1746       }
1747       else
1748          *string = renew *string char[c];
1749    }
1750 }
1751
1752 static void RegisterClass_String(Module module)
1753 {
1754    Class stringClass = eSystem_RegisterClass(normalClass, "char *", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1755    delete stringClass.dataTypeString;
1756    stringClass.dataTypeString = CopyString("char *");
1757    stringClass.structSize = 0;
1758    
1759    eClass_AddMethod(stringClass, "OnCompare", null, String_OnCompare, publicAccess);
1760    eClass_AddMethod(stringClass, "OnCopy", null, String_OnCopy, publicAccess);
1761    eClass_AddMethod(stringClass, "OnFree", null, String_OnFree, publicAccess);
1762    eClass_AddMethod(stringClass, "OnGetString", null, String_OnGetString, publicAccess);
1763    eClass_AddMethod(stringClass, "OnGetDataFromString", null, String_OnGetDataFromString, publicAccess);
1764    eClass_AddMethod(stringClass, "OnSerialize", null, String_OnSerialize, publicAccess);
1765    eClass_AddMethod(stringClass, "OnUnserialize", null, String_OnUnserialize, publicAccess); 
1766    // eClass_AddProperty(stringClass, null, "Class", null, String_GetClass, publicAccess);
1767
1768    stringClass = eSystem_RegisterClass(normalClass, "String", "char *", 0, 0, null, null, module, baseSystemAccess, publicAccess);
1769    stringClass.structSize = 0;
1770    eClass_AddProperty(stringClass, null, "char *", null, null, publicAccess);
1771 }
1772
1773 void InitializeDataTypes1(Module module)
1774 {
1775    Class baseClass = eSystem_FindClass(module, "class");
1776
1777    eClass_AddVirtualMethod(baseClass, "OnDisplay", "void typed_object::OnDisplay(Surface surface, int x, int y, int width, void * fieldData, Alignment alignment, DataDisplayFlags displayFlags)", null, publicAccess);
1778    eClass_AddVirtualMethod(baseClass, "OnCompare", "int typed_object::OnCompare(any_object object)", OnCompare, publicAccess);
1779    eClass_AddVirtualMethod(baseClass, "OnCopy", "void typed_object&::OnCopy(any_object newData)", OnCopy, publicAccess);
1780    eClass_AddVirtualMethod(baseClass, "OnFree", "void typed_object::OnFree(void)", OnFree, publicAccess);
1781    eClass_AddVirtualMethod(baseClass, "OnGetString", "char * typed_object::OnGetString(char * tempString, void * fieldData, bool * needClass)", OnGetString, publicAccess);
1782    eClass_AddVirtualMethod(baseClass, "OnGetDataFromString", "bool typed_object&::OnGetDataFromString(char * string)", OnGetDataFromString, publicAccess);
1783    eClass_AddVirtualMethod(baseClass, "OnEdit", "Window typed_object::OnEdit(DataBox dataBox, DataBox obsolete, int x, int y, int w, int h, void * userData)", null, publicAccess);
1784    eClass_AddVirtualMethod(baseClass, "OnSerialize", "void typed_object::OnSerialize(IOChannel channel)", OnSerialize, publicAccess);
1785    eClass_AddVirtualMethod(baseClass, "OnUnserialize", "void typed_object&::OnUnserialize(IOChannel channel)", OnUnserialize, publicAccess);
1786    eClass_AddVirtualMethod(baseClass, "OnSaveEdit", "bool typed_object&::OnSaveEdit(Window window, void * object)", null, publicAccess);
1787 }
1788
1789 void InitializeDataTypes(Module module)
1790 {
1791    Class enumClass = eSystem_FindClass(module, "enum");
1792
1793    eClass_AddMethod(enumClass, "OnSerialize", null, Int_OnSerialize, publicAccess);
1794    eClass_AddMethod(enumClass, "OnUnserialize", null, Int_OnUnserialize, publicAccess);
1795
1796    // Data Types
1797    RegisterClass_Integer(module);
1798    RegisterClass_Float(module);
1799    RegisterClass_Double(module);
1800    RegisterClass_String(module);
1801 }
1802
1803 #include <stdarg.h>
1804 #include <stdio.h>
1805
1806 public int PrintStdArgsToBuffer(char * buffer, int maxLen, typed_object object, va_list args)
1807 {
1808    int len = 0;
1809    // TOFIX: OnGetString will need a maxLen as well
1810    char * result = object.OnGetString(buffer, null, null);
1811    if(result)
1812    {
1813       len = strlen(result);
1814       if(len >= maxLen) len = maxLen-1;
1815       if(result != buffer)
1816          memcpy(buffer, result, len);
1817    }
1818    while(true)
1819    {
1820       Class _class = null;
1821       void * data = null;
1822
1823       _class = va_arg(args, void *);
1824       if(!_class) break;
1825       data = va_arg(args, void *);
1826       if(data)
1827       {
1828          // TOFIX: OnGetString will need a maxLen as well
1829          result = (char *)_class._vTbl[__ecereVMethodID_class_OnGetString](_class, data, buffer + len, null, null);
1830          if(result)
1831          {
1832             int newLen = strlen(result);
1833             if(len + newLen >= maxLen) newLen = maxLen-1-len;
1834             if(result != buffer + len)
1835                memcpy(buffer + len, result, newLen);
1836             len += newLen;              
1837          }
1838       }
1839    }
1840    buffer[len] = 0;
1841    return len;
1842 }
1843
1844 public int PrintBuf(char * buffer, int maxLen, typed_object object, ...)
1845 {
1846    va_list args;
1847    int len;
1848    va_start(args, object);
1849    len = PrintStdArgsToBuffer(buffer, maxLen, object, args);
1850    va_end(args);
1851    return len;
1852 }
1853
1854 public int PrintLnBuf(char * buffer, int maxLen, typed_object object, ...)
1855 {
1856    va_list args;
1857    int len;
1858    va_start(args, object);
1859    len = PrintStdArgsToBuffer(buffer, maxLen-1, object, args);
1860    buffer[len++] = '\n';
1861    buffer[len] = '\0';
1862    va_end(args);
1863    return len;
1864 }
1865
1866 public char * PrintString(typed_object object, ...)
1867 {
1868    char buffer[4096];
1869    va_list args;
1870    char * string;
1871    int len;
1872    va_start(args, object);
1873    len = PrintStdArgsToBuffer(buffer, sizeof(buffer), object, args);
1874    string = new char[len + 1];
1875    memcpy(string, buffer, len + 1);
1876    va_end(args);
1877    return string;
1878 }
1879
1880 public char * PrintLnString(typed_object object, ...)
1881 {
1882    char buffer[4096];
1883    va_list args;
1884    char * string;
1885    int len;
1886    va_start(args, object);
1887    len = PrintStdArgsToBuffer(buffer, sizeof(buffer), object, args);
1888    string = new char[len + 2];
1889    memcpy(string, buffer, len);
1890    string[len++] = '\n';
1891    string[len] = '\0';
1892    va_end(args);
1893    return string;
1894 }
1895
1896 public void PrintLn(typed_object object, ...)
1897 {
1898    va_list args;
1899    char buffer[4096];
1900    va_start(args, object);
1901    PrintStdArgsToBuffer(buffer, sizeof(buffer), object, args);
1902    va_end(args);
1903    puts(buffer);
1904 }
1905
1906 public void Print(typed_object object, ...)
1907 {
1908    va_list args;
1909    char buffer[4096];
1910    va_start(args, object);
1911    PrintStdArgsToBuffer(buffer, sizeof(buffer), object, args);
1912    va_end(args);
1913    fputs(buffer, stdout);
1914 }