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