ecere: Various tweaks in preparation for Android support
[sdk] / ecere / src / com / dataTypes.ec
1 namespace com;
2
3 #if defined(ECERE_BOOTSTRAP)
4 #define dllexport
5 #endif
6
7 import "instance"
8
9 default extern Platform runtimePlatform;
10
11 // Limit Definitions
12 public define MAXBYTE = 0xff;
13 public define MAXWORD = 0xffff;
14 public define MININT = ((int)0x80000000);
15 public define MAXINT = ((int)0x7fffffff);
16 public define MININT64 = ((int64)0x8000000000000000LL);
17 public define MAXINT64 = ((int64)0x7fffffffffffffffLL);
18 public define MAXDWORD = 0xffffffff;
19 public define MAXQWORD = 0xffffffffffffffffLL;
20 public define MINFLOAT = ((float)1.17549435082228750e-38);
21 public define MAXFLOAT = ((float)3.40282346638528860e+38);
22 public define MINDOUBLE = ((double) 2.2250738585072014e-308);
23 public define MAXDOUBLE = ((double) 1.7976931348623158e+308);
24
25 public define FORMAT64HEXLL  = (GetRuntimePlatform() == win32) ? "0x%I64XLL" : "0x%llXLL";
26 public define FORMAT64HEX    = (GetRuntimePlatform() == win32) ? "0x%I64X" : "0x%llX";
27 public define FORMAT64DLL    = (GetRuntimePlatform() == win32) ? "%I64dLL" : "%lldLL";
28 public define FORMAT64D      = (GetRuntimePlatform() == win32) ? "%I64d" : "%lld";
29 public define FORMAT64U      = (GetRuntimePlatform() == win32) ? "%I64u" : "%llu";
30
31 #define PUTXWORD(b, w) \
32    (b)[0] = (byte)(((w) >> 8) & 0xFF); \
33    (b)[1] = (byte)(((w)     ) & 0xFF);
34
35 #define GETXWORD(b) (uint16)(((b)[0] << 8) | (b)[1])
36
37 #define PUTXDWORD(b, d) \
38    (b)[0] = (byte)(((d) >> 24) & 0xFF); \
39    (b)[1] = (byte)(((d) >> 16) & 0xFF); \
40    (b)[2] = (byte)(((d) >> 8)  & 0xFF); \
41    (b)[3] = (byte)( (d)        & 0xFF);
42
43 #define GETXDWORD(b) (uint32)(((b)[0] << 24) | ((b)[1] << 16) | ((b)[2] << 8) | (b)[3])
44
45 #define PUTXQWORD(b, d) \
46    (b)[0] = (byte)(((d) >> 56) & 0xFF); \
47    (b)[1] = (byte)(((d) >> 48) & 0xFF); \
48    (b)[2] = (byte)(((d) >> 40) & 0xFF); \
49    (b)[3] = (byte)(((d) >> 32) & 0xFF); \
50    (b)[4] = (byte)(((d) >> 24) & 0xFF); \
51    (b)[5] = (byte)(((d) >> 16) & 0xFF); \
52    (b)[6] = (byte)(((d) >> 8)  & 0xFF); \
53    (b)[7] = (byte)( (d)        & 0xFF);
54
55 #define GETXQWORD(b) (uint64)(((uint64)(b)[0] << 56) | ((uint64)(b)[1] << 48) | ((uint64)(b)[2] << 40) | ((uint64)(b)[3] << 32) | ((uint64)(b)[4] << 24) | ((b)[5] << 16) | ((b)[6] << 8) | (b)[7])
56
57 static void UnusedFunction()
58 {
59    int a;
60    a.OnGetString(0,0,0);
61    a.OnFree();
62    a.OnCopy(null);
63    a.OnCompare(null);
64    a.OnSaveEdit(null,0);
65    a.OnEdit(null,null,0,0,0,0,0);
66    a.OnDisplay(null,0,0,0,0,null,null);
67    a.OnGetDataFromString(null);
68 }
69
70 default:
71 extern int __ecereVMethodID_class_OnGetString;
72 extern int __ecereVMethodID_class_OnGetDataFromString;
73 extern int __ecereVMethodID_class_OnCompare;
74 extern int __ecereVMethodID_class_OnSerialize;
75 extern int __ecereVMethodID_class_OnUnserialize;
76 extern int __ecereVMethodID_class_OnCopy;
77 public:
78
79 // 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, channel);  // channel was missing here?
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             // TOFIX: Seriously!?!?? Fix me!
1082             data = *data = eInstance_New(_class);
1083             if(_class.type == normalClass) 
1084                ((Instance)data)._refCount++;
1085          }
1086          else if(/*_class.type == noHeadClass || */_class.type == structClass) 
1087             memset(data, 0, _class.structSize);
1088
1089          while(lastClass != _class)
1090          {
1091             DataMember member;
1092             for(; _class && (!_class.base || _class.base.type != systemClass) && _class != lastClass; _class = _class.base);
1093             lastClass = _class;
1094
1095             for(member = _class.membersAndProperties.first; member; member = member.next)
1096             {
1097                if(member.isProperty || member.type == normalMember)
1098                {
1099                   Class memberType = member.dataTypeClass;
1100                         
1101                   if(!memberType)
1102                      memberType = member.dataTypeClass = eSystem_FindClass(module, member.dataTypeString);
1103                   if(memberType)
1104                   {
1105                      if(member.isProperty)
1106                      {
1107                         /*Property prop = (Property)member;
1108                         if(!prop.conversion && prop.Get && prop.Set)
1109                         {
1110                            if(memberType.type == structClass || memberType.type == normalClass || memberType.type == noHeadClass)
1111                            {
1112
1113                            }
1114                            else
1115                            {
1116                               DataValue value;
1117                               memberType._vTbl[__ecereVMethodID_class_OnUnserialize](memberType, &value, channel);
1118                               prop.Set(data, value.i);
1119                            }
1120                         }*/
1121                      }
1122                      else
1123                         memberType._vTbl[__ecereVMethodID_class_OnUnserialize](memberType, 
1124                            (byte *)data + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset), channel);
1125                   }
1126                   else
1127                   {
1128                      // printf("Unknown type\n");
1129                   }
1130                }
1131                else
1132                {
1133                   DataMember_OnUnserialize(member, (byte *)data + (((member._class.type == normalClass) ? member._class.offset : 0) + member.offset), channel);
1134                }
1135             }
1136          }
1137       }
1138    }
1139 }
1140
1141 // Integer
1142 static int Integer_OnCompare(Class _class, int * data1, int * data2)
1143 {
1144    int result = 0;
1145    if(!data1 && !data2) result = 0;
1146    else if(data1 && !data2) result = 1;
1147    else if(!data1 && data2) result = -1;
1148    else if(*data1 > *data2) result = 1;
1149    else if(*data1 < *data2) result = -1;
1150    return result;
1151 }
1152
1153 /*static */char * Integer_OnGetString(Class _class, int * data, char * string, void * fieldData, bool * needClass)
1154 {
1155    sprintf(string, "%d", *data);
1156    return string;
1157 }
1158
1159 static bool Integer_OnGetDataFromString(Class _class, int * data, char * string)
1160 {
1161    char * end;
1162    int result = strtol(string, &end, 0);
1163
1164    if(end > string)
1165    {
1166       *data = result;
1167       return true;
1168    }
1169    return false;
1170 }
1171
1172 static int UInteger_OnCompare(Class _class, unsigned int * data1, unsigned int * data2)
1173 {
1174    int result = 0;
1175    if(!data1 && !data2) result = 0;
1176    else if(data1 && !data2) result = 1;
1177    else if(!data1 && data2) result = -1;
1178    else if(*data1 > *data2) result = 1;
1179    else if(*data1 < *data2) result = -1;
1180    return result;
1181 }
1182
1183 static char * UInteger_OnGetString(Class _class, unsigned int * data, char * string, void * fieldData, bool * needClass)
1184 {
1185    sprintf(string, "%u", *data);
1186    return string;
1187 }
1188
1189 static bool UInteger_OnGetDataFromString(Class _class, unsigned int * data, char * string)
1190 {
1191    char * end;
1192    uint result = strtoul(string, &end, 0);
1193    if(end > string)
1194    {
1195       *data = result;
1196       return true;
1197    }
1198    return false;
1199 }
1200
1201 static int Byte_OnCompare(Class _class, byte * data1, byte * data2)
1202 {
1203    int result = 0;
1204    if(!data1 && !data2) result = 0;
1205    else if(data1 && !data2) result = 1;
1206    else if(!data1 && data2) result = -1;
1207    else if(*data1 > *data2) result = 1;
1208    else if(*data1 < *data2) result = -1;
1209    return result;
1210 }
1211
1212 static char * Byte_OnGetString(Class _class, byte * data, char * string, void * fieldData, bool * needClass)
1213 {
1214    sprintf(string, "%u", (int)*data);
1215    return string;
1216 }
1217
1218 static char * Char_OnGetString(Class _class, char * data, char * string, void * fieldData, bool * needClass)
1219 {
1220    if(needClass && *needClass)
1221    {
1222       char ch = *data;
1223       if(ch == '\t')      strcpy(string, "'\t'");
1224       else if(ch == '\n') strcpy(string, "'\n'");
1225       else if(ch == '\r') strcpy(string, "'\r'");
1226       else if(ch == '\a') strcpy(string, "'\a'");
1227       else if(ch == '\\') strcpy(string, "'\\'");
1228       else if(ch < 32 || ch >= 127)    sprintf(string, "'\o'", ch);
1229       else sprintf(string, "'%c'", ch);
1230    }
1231    else
1232       sprintf(string, "%c", *data);
1233    return string;
1234 }
1235
1236 static bool Byte_OnGetDataFromString(Class _class, byte * data, char * string)
1237 {
1238    char * end;
1239    byte result = (byte)strtoul(string, &end, 0);
1240    if(end > string)
1241    {
1242       *data = result;
1243       return true;
1244    }
1245    return false;
1246 }
1247
1248 static char * Int64_OnGetString(Class _class, int64 * data, char * string, void * fieldData, bool * needClass)
1249 {
1250    sprintf(string, FORMAT64D, *data);
1251    return string;
1252 }
1253
1254 static char * UInt64_OnGetString(Class _class, uint64 * data, char * string, void * fieldData, bool * needClass)
1255 {
1256    sprintf(string, FORMAT64U, *data);
1257    return string;
1258 }
1259
1260 /*static */void Byte_OnSerialize(Class _class, byte * data, IOChannel channel)
1261 {
1262    channel.WriteData(data, 1);
1263 }
1264
1265 /*static */void Byte_OnUnserialize(Class _class, byte * data, IOChannel channel)
1266 {
1267    if(channel.ReadData(data, 1) != 1)
1268       *data = 0;
1269 }
1270
1271
1272 /*static */void Int_OnSerialize(Class _class, int * data, IOChannel channel)
1273 {
1274    byte bytes[4];
1275    PUTXDWORD(bytes, * data);
1276    channel.WriteData(bytes, 4);
1277 }
1278
1279 /*static */void Int_OnUnserialize(Class _class, int * data, IOChannel channel)
1280 {
1281    byte bytes[4];
1282    if(channel.ReadData(bytes, 4) == 4)
1283       *data = GETXDWORD(bytes);   
1284    else
1285       *data = 0;
1286 }
1287
1288 /*static */void Int64_OnSerialize(Class _class, int64 * data, IOChannel channel)
1289 {
1290    byte bytes[8];
1291    PUTXQWORD(bytes, * data);
1292    channel.WriteData(bytes, 8);
1293 }
1294
1295 /*static */void Int64_OnUnserialize(Class _class, int64 * data, IOChannel channel)
1296 {
1297    byte bytes[8];
1298    if(channel.ReadData(bytes, 8) == 8)
1299       *data = GETXQWORD(bytes);   
1300    else
1301       *data = 0;
1302 }
1303
1304 /*static */void Word_OnSerialize(Class _class, uint16 * data, IOChannel channel)
1305 {
1306    byte bytes[2];
1307    PUTXWORD(bytes, * data);
1308    channel.WriteData(bytes, 2);
1309 }
1310
1311 /*static */void Word_OnUnserialize(Class _class, uint16 * data, IOChannel channel)
1312 {
1313    byte bytes[2];
1314    if(channel.ReadData(bytes, 2) == 2)
1315       *data = GETXWORD(bytes);   
1316    else
1317       *data = 0;
1318 }
1319
1320 static void RegisterClass_Integer(Module module)
1321 {
1322    Class integerClass = eSystem_RegisterClass(normalClass, "int", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1323    integerClass.type = systemClass;
1324    delete integerClass.dataTypeString;
1325    integerClass.dataTypeString = CopyString("int");
1326    integerClass.structSize = 0;
1327    integerClass.typeSize = sizeof(int);
1328    
1329    eClass_AddMethod(integerClass, "OnCompare", null, Integer_OnCompare, publicAccess);
1330    eClass_AddMethod(integerClass, "OnGetString", null, Integer_OnGetString, publicAccess);
1331    eClass_AddMethod(integerClass, "OnGetDataFromString", null, Integer_OnGetDataFromString, publicAccess);
1332    eClass_AddMethod(integerClass, "OnSerialize", null, Int_OnSerialize, publicAccess);
1333    eClass_AddMethod(integerClass, "OnUnserialize", null, Int_OnUnserialize, publicAccess);
1334
1335    integerClass = eSystem_RegisterClass(normalClass, "int64", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1336    integerClass.type = systemClass;
1337    integerClass.structSize = 0;
1338    integerClass.typeSize = sizeof(int64);
1339    delete integerClass.dataTypeString;
1340    integerClass.dataTypeString = CopyString("int64");
1341    eClass_AddMethod(integerClass, "OnGetString", null, Int64_OnGetString, publicAccess);
1342
1343    /*
1344    eClass_AddMethod(integerClass, "OnCompare", null, Integer64_OnCompare, publicAccess);
1345    eClass_AddMethod(integerClass, "OnGetString", null, Integer64_OnGetString, publicAccess);
1346    eClass_AddMethod(integerClass, "OnGetDataFromString", null, Integer64_OnGetDataFromString, publicAccess);
1347    */
1348    eClass_AddMethod(integerClass, "OnSerialize", null, Int64_OnSerialize, publicAccess);
1349    eClass_AddMethod(integerClass, "OnUnserialize", null, Int64_OnUnserialize, publicAccess);
1350
1351    integerClass = eSystem_RegisterClass(normalClass, "uint", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1352    integerClass.type = systemClass;
1353    delete integerClass.dataTypeString;
1354    integerClass.dataTypeString = CopyString("unsigned int");
1355    integerClass.structSize = 0;
1356    integerClass.typeSize = sizeof(uint);
1357    eClass_AddMethod(integerClass, "OnCompare", null, UInteger_OnCompare, publicAccess);
1358    eClass_AddMethod(integerClass, "OnGetString", null, UInteger_OnGetString, publicAccess);
1359    eClass_AddMethod(integerClass, "OnGetDataFromString", null, UInteger_OnGetDataFromString, publicAccess);
1360    eClass_AddMethod(integerClass, "OnSerialize", null, Int_OnSerialize, publicAccess);
1361    eClass_AddMethod(integerClass, "OnUnserialize", null, Int_OnUnserialize, publicAccess);
1362
1363    integerClass = eSystem_RegisterClass(normalClass, "unsigned int", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1364    integerClass.type = systemClass;
1365    delete integerClass.dataTypeString;
1366    integerClass.dataTypeString = CopyString("unsigned int");
1367    integerClass.structSize = 0;
1368    integerClass.typeSize = sizeof(uint);
1369
1370    eClass_AddMethod(integerClass, "OnCompare", null, UInteger_OnCompare, publicAccess);
1371    eClass_AddMethod(integerClass, "OnGetString", null, UInteger_OnGetString, publicAccess);
1372    eClass_AddMethod(integerClass, "OnGetDataFromString", null, UInteger_OnGetDataFromString, publicAccess);
1373    eClass_AddMethod(integerClass, "OnSerialize", null, Int_OnSerialize, publicAccess);
1374    eClass_AddMethod(integerClass, "OnUnserialize", null, Int_OnUnserialize, publicAccess);
1375
1376    integerClass = eSystem_RegisterClass(normalClass, "uint16", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1377    integerClass.type = systemClass;
1378    delete integerClass.dataTypeString;
1379    integerClass.dataTypeString = CopyString("unsigned short");
1380    integerClass.structSize = 0;
1381    integerClass.typeSize = sizeof(uint16);
1382
1383    eClass_AddMethod(integerClass, "OnSerialize", null, Word_OnSerialize, publicAccess);
1384    eClass_AddMethod(integerClass, "OnUnserialize", null, Word_OnUnserialize, publicAccess);
1385
1386    integerClass = eSystem_RegisterClass(normalClass, "short", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1387    integerClass.type = systemClass;
1388    delete integerClass.dataTypeString;
1389    integerClass.dataTypeString = CopyString("short");
1390    integerClass.structSize = 0;
1391    integerClass.typeSize = sizeof(short);
1392
1393    eClass_AddMethod(integerClass, "OnSerialize", null, Word_OnSerialize, publicAccess);
1394    eClass_AddMethod(integerClass, "OnUnserialize", null, Word_OnUnserialize, publicAccess);
1395
1396    /*
1397    integerClass = eSystem_RegisterClass(normalClass, "uint32", null, 0, 0, null, null, module, baseSystemAccess);
1398    integerClass.type = systemClass;
1399    delete integerClass.dataTypeString;
1400    integerClass.dataTypeString = CopyString("uint32");
1401    eClass_AddMethod(integerClass, "OnCompare", null, UInteger_OnCompare, publicAccess);
1402    eClass_AddMethod(integerClass, "OnGetString", null, UInteger_OnGetString, publicAccess);
1403    eClass_AddMethod(integerClass, "OnGetDataFromString", null, UInteger_OnGetDataFromString, publicAccess);
1404    */
1405    integerClass = eSystem_RegisterClass(normalClass, "uint32", "uint", 0, 0, null, null, module, baseSystemAccess, publicAccess);
1406    integerClass.type = systemClass;
1407    delete integerClass.dataTypeString;
1408    integerClass.dataTypeString = CopyString("unsigned int");
1409    integerClass.structSize = 0;
1410    integerClass.typeSize = sizeof(uint32);
1411
1412    integerClass = eSystem_RegisterClass(normalClass, "uint64", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1413    integerClass.type = systemClass;
1414    delete integerClass.dataTypeString;
1415    integerClass.dataTypeString = CopyString("uint64");
1416    integerClass.structSize = 0;
1417    integerClass.typeSize = sizeof(uint64);
1418    eClass_AddMethod(integerClass, "OnGetString", null, UInt64_OnGetString, publicAccess);
1419    eClass_AddMethod(integerClass, "OnSerialize", null, Int64_OnSerialize, publicAccess);
1420    eClass_AddMethod(integerClass, "OnUnserialize", null, Int64_OnUnserialize, publicAccess);
1421
1422    integerClass = eSystem_RegisterClass(normalClass, "byte", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1423    integerClass.type = systemClass;
1424    delete integerClass.dataTypeString;
1425    integerClass.dataTypeString = CopyString("unsigned char");
1426    integerClass.structSize = 0;
1427    integerClass.typeSize = sizeof(byte);
1428    eClass_AddMethod(integerClass, "OnCompare", null, Byte_OnCompare, publicAccess);
1429    eClass_AddMethod(integerClass, "OnGetString", null, Byte_OnGetString, publicAccess);
1430    eClass_AddMethod(integerClass, "OnGetDataFromString", null, Byte_OnGetDataFromString, publicAccess);
1431    eClass_AddMethod(integerClass, "OnSerialize", null, Byte_OnSerialize, publicAccess);
1432    eClass_AddMethod(integerClass, "OnUnserialize", null, Byte_OnUnserialize, publicAccess);
1433
1434    integerClass = eSystem_RegisterClass(normalClass, "char", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1435    integerClass.type = systemClass;
1436    delete integerClass.dataTypeString;
1437    integerClass.dataTypeString = CopyString("char");
1438    integerClass.structSize = 0;
1439    integerClass.typeSize = sizeof(char);
1440    eClass_AddMethod(integerClass, "OnCompare", null, Byte_OnCompare, publicAccess);
1441    eClass_AddMethod(integerClass, "OnGetString", null, Char_OnGetString, publicAccess);
1442    eClass_AddMethod(integerClass, "OnGetDataFromString", null, Byte_OnGetDataFromString, publicAccess);
1443    eClass_AddMethod(integerClass, "OnSerialize", null, Byte_OnSerialize, publicAccess);
1444    eClass_AddMethod(integerClass, "OnUnserialize", null, Byte_OnUnserialize, publicAccess);
1445 }
1446
1447 // Float
1448 static int Float_OnCompare(Class _class, float * data1, float * data2)
1449 {
1450    int result = 0;
1451    if(!data1 && !data2) result = 0;
1452    else if(data1 && !data2) result = 1;
1453    else if(!data1 && data2) result = -1;
1454    else if(*data1 > *data2) result = 1;
1455    else if(*data1 < *data2) result = -1;
1456    return result;
1457 }
1458
1459 static char * Float_OnGetString(Class _class, float * data, char * string, void * fieldData, bool * needClass)
1460 {
1461    int c;
1462    int last = 0;
1463    int numDigits = 7, num = 1;
1464    char format[10];
1465    while(numDigits && num < *data) numDigits--, num *= 10;
1466    sprintf(format, "%%.%df", numDigits);
1467
1468    //sprintf(string, "%f", *data);
1469    sprintf(string, format, *data);
1470
1471    c = strlen(string)-1;
1472    for( ; c >= 0; c--)
1473    {
1474       if(string[c] != '0') 
1475          last = Max(last, c);
1476       if(string[c] == '.')
1477       {
1478          if(last == c)
1479             string[c] = 0;
1480          else
1481             string[last+1] = 0;
1482          break;
1483       }
1484    }
1485    return string;
1486 }
1487
1488 static bool Float_OnGetDataFromString(Class _class, float * data, char * string)
1489 {
1490    char * end;
1491    float result = (float)strtod(string, &end);
1492    //*data = atof(string);
1493    if(end > string)
1494    {
1495       *data = result;
1496       return true;
1497    }
1498    return false;
1499 }
1500
1501 static void Float_OnSerialize(Class _class, float * data, IOChannel channel)
1502 {
1503    byte bytes[4];
1504    PUTXDWORD(bytes, * (uint *)data);
1505    channel.WriteData(bytes, 4);
1506 }
1507
1508 static void Float_OnUnserialize(Class _class, float * data, IOChannel channel)
1509 {
1510    byte bytes[4];
1511    if(channel.ReadData(bytes, 4) == 4)
1512       *(uint *)data = GETXDWORD(bytes);   
1513    else
1514       *data = 0;
1515 }
1516
1517 static void RegisterClass_Float(Module module)
1518 {
1519    Class floatClass = eSystem_RegisterClass(normalClass, "float", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
1520    floatClass.type = systemClass;
1521    delete floatClass.dataTypeString;
1522    floatClass.dataTypeString = CopyString("float");
1523    floatClass.structSize = 0;
1524    floatClass.typeSize = sizeof(float);
1525    eClass_AddMethod(floatClass, "OnCompare", null, Float_OnCompare, publicAccess);
1526    eClass_AddMethod(floatClass, "OnGetString", null, Float_OnGetString, publicAccess);
1527    eClass_AddMethod(floatClass, "OnGetDataFromString", null, Float_OnGetDataFromString, publicAccess);
1528    eClass_AddMethod(floatClass, "OnSerialize", null, Float_OnSerialize, publicAccess);
1529    eClass_AddMethod(floatClass, "OnUnserialize", null, Float_OnUnserialize, publicAccess);
1530 }
1531
1532 // Double
1533 static int Double_OnCompare(Class _class, double * data1, double * data2)
1534 {
1535    int result = 0;
1536    if(!data1 && !data2) result = 0;
1537    else if(data1 && !data2) result = 1;
1538    else if(!data1 && data2) result = -1;
1539    else if(*data1 > *data2) result = 1;
1540    else if(*data1 < *data2) 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 #define uint _uint
1807 #include <stdarg.h>
1808 #include <stdio.h>
1809 #undef uint
1810
1811 public int PrintStdArgsToBuffer(char * buffer, int maxLen, typed_object object, va_list args)
1812 {
1813    int len = 0;
1814    // TOFIX: OnGetString will need a maxLen as well
1815    char * result = object.OnGetString(buffer, null, null);
1816    if(result)
1817    {
1818       len = strlen(result);
1819       if(len >= maxLen) len = maxLen-1;
1820       if(result != buffer)
1821          memcpy(buffer, result, len);
1822    }
1823    while(true)
1824    {
1825       Class _class = null;
1826       void * data = null;
1827
1828       _class = va_arg(args, void *);
1829       if(!_class) break;
1830       data = va_arg(args, void *);
1831       if(data)
1832       {
1833          // TOFIX: OnGetString will need a maxLen as well
1834          result = (char *)_class._vTbl[__ecereVMethodID_class_OnGetString](_class, data, buffer + len, null, null);
1835          if(result)
1836          {
1837             int newLen = strlen(result);
1838             if(len + newLen >= maxLen) newLen = maxLen-1-len;
1839             if(result != buffer + len)
1840                memcpy(buffer + len, result, newLen);
1841             len += newLen;              
1842          }
1843       }
1844    }
1845    buffer[len] = 0;
1846    return len;
1847 }
1848
1849 public int PrintBuf(char * buffer, int maxLen, typed_object object, ...)
1850 {
1851    va_list args;
1852    int len;
1853    va_start(args, object);
1854    len = PrintStdArgsToBuffer(buffer, maxLen, object, args);
1855    va_end(args);
1856    return len;
1857 }
1858
1859 public int PrintLnBuf(char * buffer, int maxLen, typed_object object, ...)
1860 {
1861    va_list args;
1862    int len;
1863    va_start(args, object);
1864    len = PrintStdArgsToBuffer(buffer, maxLen-1, object, args);
1865    buffer[len++] = '\n';
1866    buffer[len] = '\0';
1867    va_end(args);
1868    return len;
1869 }
1870
1871 public char * PrintString(typed_object object, ...)
1872 {
1873    char buffer[4096];
1874    va_list args;
1875    char * string;
1876    int len;
1877    va_start(args, object);
1878    len = PrintStdArgsToBuffer(buffer, sizeof(buffer), object, args);
1879    string = new char[len + 1];
1880    memcpy(string, buffer, len + 1);
1881    va_end(args);
1882    return string;
1883 }
1884
1885 public char * PrintLnString(typed_object object, ...)
1886 {
1887    char buffer[4096];
1888    va_list args;
1889    char * string;
1890    int len;
1891    va_start(args, object);
1892    len = PrintStdArgsToBuffer(buffer, sizeof(buffer), object, args);
1893    string = new char[len + 2];
1894    memcpy(string, buffer, len);
1895    string[len++] = '\n';
1896    string[len] = '\0';
1897    va_end(args);
1898    return string;
1899 }
1900
1901 #if defined(__ANDROID__)
1902 #include <android/log.h>
1903 #define LOGI(...) ((void)__android_log_print(ANDROID_LOG_INFO, "ecere-app", __VA_ARGS__))
1904 #endif
1905
1906 public void PrintLn(typed_object object, ...)
1907 {
1908    va_list args;
1909    char buffer[4096];
1910    va_start(args, object);
1911    PrintStdArgsToBuffer(buffer, sizeof(buffer), object, args);
1912    va_end(args);
1913 #if defined(__ANDROID__)
1914    LOGI("%s", buffer);
1915 #else
1916    puts(buffer);
1917 #endif
1918 }
1919
1920 public void Print(typed_object object, ...)
1921 {
1922    va_list args;
1923    char buffer[4096];
1924    va_start(args, object);
1925    PrintStdArgsToBuffer(buffer, sizeof(buffer), object, args);
1926    va_end(args);
1927    fputs(buffer, stdout);
1928 }