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