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