ecere/com: Adjustment to 32 bit cross-compiling fix
[sdk] / ecere / src / com / instance.ec
1 namespace com;
2
3 import "BinaryTree"
4 import "OldList"
5 import "String"
6 import "dataTypes"
7
8 #if defined(ECERE_BOOTSTRAP) || defined(ECERE_STATIC)
9 #define dllexport
10 #if !defined(ECERE_BOOTSTRAP)
11 #define stdcall
12 #endif
13 #endif
14
15 #undef __BLOCKS__
16
17 #if !defined(ECERE_BOOTSTRAP)
18 import "Mutex"
19 #endif
20
21 // #define MEMINFO
22
23 // #define REDZONE   256
24 #ifndef REDZONE
25 #define REDZONE 0
26 #endif
27
28 #ifdef MEMINFO
29 import "Thread"
30 static define MAX_MEMORY_LOC = 40;
31
32 static class MemStack : BTNode
33 {
34    char * frames[1000];
35    int pos;
36    bool recurse;
37 };
38
39 static BinaryTree memStacks { };
40 static uint memoryErrorsCount = 0;
41
42 #endif
43
44 default:
45 #define property _property
46 #define bool _bool
47 #define uint _uint
48 #define true _true
49 #define false _false
50
51 #include <stdlib.h>
52 #include <stdio.h>
53
54 private:
55
56 #if defined(__ANDROID__)
57
58 default const char * AndroidInterface_GetLibLocation();
59
60 #include <android/log.h>
61 #include <android/native_activity.h>
62
63 #define printf(...)  ((void)__android_log_print(ANDROID_LOG_VERBOSE, "ecere-app", __VA_ARGS__))
64 #endif
65
66 #undef property
67 #undef bool
68 #undef uint
69 #undef true
70 #undef false
71
72 #undef CompareString
73
74 public define null = ((void *)0);
75
76 dllexport Class eSystem_FindClass(Module module, char * name);
77 dllexport void * eSystem_Renew(void * memory, unsigned int size);
78 dllexport void * eSystem_Renew0(void * memory, unsigned int size);
79 dllexport void * eSystem_New(unsigned int size);
80 dllexport void * eSystem_New0(unsigned int size);
81 dllexport void eSystem_Delete(void * memory);
82 dllexport void * eInstance_New(Class _class);
83
84 default:
85 extern int __ecereVMethodID_class_OnGetDataFromString;
86
87 // IMPLEMENTATION FOR THESE IN _instance.c:
88 bool Instance_LocateModule(char * name, char * fileName);
89 void Instance_COM_Initialize(int argc, char ** argv, char ** parsedCommand, int * argcPtr, char *** argvPtr);
90 void * Instance_Module_Load(const char * libLocation, const char * name, void ** Load, void ** Unload);
91 void Instance_Module_Free(void * library);
92 #if defined(_DEBUG)
93 void InternalModuleLoadBreakpoint();
94 #endif
95
96 private:
97
98 public class unichar : uint32
99 {
100
101    char * OnGetString(char * tempString, void * fieldData, bool * needClass)
102    {
103       UTF32toUTF8Len(&this, 1, tempString, 5);
104       return tempString;
105    }
106
107    bool OnGetDataFromString(char * string)
108    {
109       int nb;
110       this = UTF8GetChar(string, &nb);
111       return true;
112    }
113
114 };
115
116 public class Property : struct
117 {
118 public:
119    class_fixed
120    class_no_expansion
121    Property prev, next;
122    char * name;
123    bool isProperty;
124    AccessMode memberAccess;
125    int id;
126    Class _class;
127    char * dataTypeString;
128    Class dataTypeClass;
129    Type dataType;
130
131    void (*Set)(void *, int);
132    int (*Get)(void *);
133    bool (*IsSet)(void *);
134    void * data;
135    void * symbol;
136    int vid;
137    bool conversion;
138    uint watcherOffset;
139    char * category;
140    bool compiled;
141    bool selfWatchable, isWatchable;
142 };
143
144 dllexport void eInstance_FireWatchers(Instance instance, Property _property);
145
146 public dllexport void MemoryGuard_PushLoc(char * loc)
147 {
148 #ifdef MEMINFO
149    MemStack stack;
150    memMutex.Wait();
151    stack = (MemStack)memStacks.Find(GetCurrentThreadID());
152    if(!stack)
153    {
154       stack = (MemStack)calloc(1, sizeof(class MemStack));
155       stack.key = GetCurrentThreadID();
156       memStacks.Add(stack);
157    }
158    if(stack.pos < 1000)
159       stack.frames[stack.pos++] = loc;
160    else
161       printf("");
162    memMutex.Release();
163 #endif
164 }
165
166 public dllexport void MemoryGuard_PopLoc()
167 {
168 #ifdef MEMINFO
169    MemStack stack;
170    memMutex.Wait();
171    stack = (MemStack)memStacks.Find(GetCurrentThreadID());
172    if(stack && stack.pos > 0)
173    {
174       stack.pos--;
175    }
176    else
177       printf("");
178    memMutex.Release();
179 #endif
180 }
181
182 #ifdef ECERE_STATIC
183
184 #ifdef ECERE_COM_ONLY
185
186 #define COM_LOAD_FUNCTION  __ecereDll_Load_ecereCOM
187 #define COM_UNLOAD_FUNCTION  __ecereDll_Unload_ecereCOM
188
189 #else
190
191 #define COM_LOAD_FUNCTION  __ecereDll_Load_ecere
192 #define COM_UNLOAD_FUNCTION  __ecereDll_Unload_ecere
193
194 #endif
195
196 #else
197
198 #define COM_LOAD_FUNCTION  __ecereDll_Load
199 #define COM_UNLOAD_FUNCTION  __ecereDll_Unload
200
201 #endif
202
203 default:
204
205 #if defined(ECERE_BOOTSTRAP)
206 extern bool COM_LOAD_FUNCTION(Module module);
207 extern bool COM_UNLOAD_FUNCTION(Module module);
208 #else
209 extern bool stdcall COM_LOAD_FUNCTION(Module module);
210 extern bool stdcall COM_UNLOAD_FUNCTION(Module module);
211 #endif
212
213 private:
214
215 public class BTNamedLink : struct
216 {
217    class_fixed
218 public:
219    char * name;
220    BTNamedLink parent, left, right;
221    int depth;
222    void * data;
223 };
224
225 class SelfWatcher : struct
226 {
227    class_fixed
228    SelfWatcher prev, next;
229    void (*callback)(Instance);
230    Property _property;
231 };
232
233 public enum AccessMode
234
235    defaultAccess,
236    publicAccess,
237    privateAccess,
238    staticAccess,
239    baseSystemAccess
240 };
241
242 public class SubModule : struct
243 {
244 public:
245    SubModule prev, next;
246    Module module;
247    AccessMode importMode;      
248 };
249
250 public enum DataMemberType { normalMember, unionMember, structMember };
251
252 public enum ClassType
253 {
254    normalClass,
255    structClass,
256    bitClass,
257    unitClass,
258    enumClass,
259    noHeadClass,
260    unionClass, // Temporary only in firstPass
261    systemClass = 1000
262 };
263
264 public class Class : struct
265 {
266 public:
267    class_fixed
268    class_no_expansion
269    Class prev, next;
270    char * name;
271    int offset, structSize;
272    int (** _vTbl)();
273    int vTblSize;
274    int (*Constructor)(Instance);
275    void (*Destructor)(Instance);
276
277    int offsetClass, sizeClass;
278    Class base;
279    BinaryTree methods;
280    BinaryTree members;
281    BinaryTree prop;
282    OldList membersAndProperties;
283    BinaryTree classProperties;
284    OldList derivatives;
285    int memberID, startMemberID;
286    ClassType type;
287    Module module;
288    NameSpace * nameSpace;
289    char * dataTypeString;
290    Type dataType;
291    int typeSize;
292    int defaultAlignment;
293    void (*Initialize)();
294    int memberOffset;       // For structs, this includes all base classes structSize. Otherwise it restarts at for each class hierarchy level.
295    OldList selfWatchers;
296    char * designerClass;
297    bool noExpansion;
298    char * defaultProperty;
299    bool comRedefinition;
300
301    int count;     // DEBUGGING
302
303    bool isRemote;
304    bool internalDecl;
305    void * data;
306    bool computeSize;
307    int structAlignment;
308    int destructionWatchOffset;
309    bool fixed;
310    OldList delayedCPValues;
311    AccessMode inheritanceAccess;
312    char * fullName;
313    void * symbol;
314    OldList conversions;
315
316    OldList templateParams;
317    ClassTemplateArgument * templateArgs;
318    Class templateClass;
319    OldList templatized;
320    int numParams;
321
322    property char *
323    {
324       get { return name; }
325       set
326       {  
327          Class theClass = eSystem_FindClass(__thisModule, value);
328          /*
329          if(!theClass)
330             theClass = eSystem_FindClass(__thisModule.application, value);
331          */
332          return theClass;
333       }
334    };
335
336    char * OnGetString(char * tempString, void * fieldData, bool * needClass)
337    {
338       return name;
339    }
340
341    bool OnGetDataFromString(char * string)
342    {
343       Class theClass;
344       theClass = eSystem_FindClass(__thisModule, string);
345       if(!theClass)
346          theClass = eSystem_FindClass(__thisModule.application, string);
347       this = (void *)theClass;
348       return theClass != null;
349    }
350
351    void OnSerialize(IOChannel channel)
352    {
353       channel.Serialize(fullName);
354    }
355
356    void OnFree()
357    {
358
359    }
360
361    void OnUnserialize(IOChannel channel)
362    {
363       Class theClass;
364       String string;
365       channel.Unserialize(string);
366       theClass = eSystem_FindClass(__thisModule, string);
367       if(!theClass)
368          theClass = eSystem_FindClass(__thisModule.application, string);
369       delete string;
370       this = (void *)theClass;
371    }
372 };
373
374
375 public enum TemplateParameterType { type, identifier, expression };
376 public enum TemplateMemberType { dataMember, method, prop };
377
378 public struct ClassTemplateArgument
379 {
380 public:
381    union
382    {
383       // For type
384       struct
385       {
386          char * dataTypeString;
387          Class dataTypeClass;
388          // Type dataType;
389       };
390       // For expression
391       DataValue expression;
392
393       // For identifier
394       struct
395       {
396          char * memberString;
397          union
398          {
399             DataMember member;
400             Property prop;
401             Method method;
402          };
403       };
404    };
405 };
406
407 public class ClassTemplateParameter : struct
408 {
409 class_fixed
410 public:
411    ClassTemplateParameter prev, next;
412    char * name;
413    TemplateParameterType type;
414    union
415    {
416       // Class baseClass;                 // For type
417       char * dataTypeString;           // For expression
418       TemplateMemberType memberType;   // For identifier
419    };
420    ClassTemplateArgument defaultArg;
421    void * param;  // To attach to Compiler TemplateParameter
422 }
423
424 /*    // Module inherits off the Instance class (_vTbl, _class, _refCount)
425 public class Module
426 {
427    class_no_expansion
428
429    Application app;
430
431    // So we can clean them up
432    OldList classes;
433    OldList defines;
434    OldList functions;
435    OldList modules;
436
437    Module prev, next;
438    char * name;
439    void * library;
440    void (stdcall * Unload)(Module module);
441    ImportType importType;
442    // Added to solve stdcall issues with the bootstrap on Windows for Unload
443    ImportType origImportType;
444
445    NameSpace privateNameSpace;
446    NameSpace publicNameSpace;
447 };
448
449 public class Application : Module
450 {
451    int argc;
452    char ** argv;
453    int exitCode;
454    bool isGUIApp;
455    OldList allModules;
456    char * parsedCommand;
457    NameSpace systemNameSpace;
458 };
459 */
460 public enum MethodType { normalMethod, virtualMethod };
461
462 public class Method : struct
463 {
464 public:
465    class_fixed
466    char * name;
467    Method parent, left, right;
468    int depth;
469    int (*function)();
470    int vid;              // For METHOD_VIRTUAL:  Index into the class virtual table
471    MethodType type;
472    Class _class;
473    void * symbol;
474    char * dataTypeString;
475    Type dataType;
476    AccessMode memberAccess;
477 };
478
479 public enum ImportType
480 {
481    normalImport,
482    staticImport,
483    remoteImport,
484
485 // For internal usage in the compiler:
486    preDeclImport,
487    comCheckImport
488 };
489
490 public struct NameSpace
491 {
492    char * name;
493    NameSpace * btParent, * left, * right;
494    int depth;
495
496    NameSpace * parent;
497    BinaryTree nameSpaces;
498    BinaryTree classes;
499    BinaryTree defines;
500    BinaryTree functions;
501 };
502
503 public union DataValue
504 {
505    char c;
506    unsigned char uc;
507    short s;
508    unsigned short us;
509    int i;
510    unsigned int ui;
511    void * p;
512    float f;
513    double d;
514    int64 i64;
515    uint64 ui64;
516 };
517
518 public class DataMember : struct
519 {
520 public:
521    class_fixed
522    DataMember prev, next;
523    char * name;
524    bool isProperty;
525    AccessMode memberAccess;
526    int id;
527    Class _class;
528    char * dataTypeString;
529    Class dataTypeClass;
530    Type dataType;
531
532    DataMemberType type;
533    int offset;
534    int memberID;
535    OldList members;
536    BinaryTree membersAlpha;
537    int memberOffset;
538    int structAlignment;
539 };
540
541 public class BitMember : struct
542 {
543 public:
544    class_fixed
545    BitMember prev, next;
546    char * name;
547    bool isProperty;
548    AccessMode memberAccess;
549    int id;
550    Class _class;
551    char * dataTypeString;
552    Class dataTypeClass;
553    Type dataType;
554
555    DataMemberType type;
556    int size;
557    int pos;
558    uint64 mask;
559 };
560
561 public class ClassProperty : struct
562 {
563 public:
564    class_fixed
565    char * name;
566    ClassProperty parent, left, right;
567    int depth;
568    void (*Set)(Class, int64);
569    int64 (*Get)(Class);
570    char * dataTypeString;
571    Type dataType;
572    bool constant;
573 };
574
575 public class DefinedExpression : struct
576 {
577 public:
578    class_fixed
579    DefinedExpression prev, next;
580    char * name;
581    char * value;
582    NameSpace * nameSpace;
583 };
584
585 public class GlobalFunction : struct
586 {
587 public:
588    class_fixed
589    GlobalFunction prev, next;
590    char * name;
591    int (*function)();
592    Module module;
593    NameSpace * nameSpace;
594    char * dataTypeString;
595    Type dataType;
596    void * symbol;
597 };
598
599 public class EnumClassData : struct 
600 {
601 public:
602    class_fixed
603    OldList values;
604    int largest;
605 };
606
607 class Watcher : struct
608 {
609    class_fixed
610    Watcher prev, next;
611    void (*callback)(Instance, Instance);
612    Instance object;
613 };
614
615 #ifdef MEMINFO
616 static class MemInfo : BTNode //struct
617 {
618    class_fixed
619
620    /*
621    byte * key;
622    MemInfo parent, left, right;
623    int depth;
624    */
625
626    byte * oldmem;
627    uint size;
628    bool freed;
629    char * _class;
630    uint id;
631    char * allocLoc[MAX_MEMORY_LOC];
632    char * freeLoc[MAX_MEMORY_LOC];
633    bool internal;
634
635    void OutputStacks(bool showFree)
636    {
637       int c;
638
639       if(_class)
640          printf("Object of class %s\n", _class);
641       printf("   Allocation Stack:\n");
642       for(c = 0; c<MAX_MEMORY_LOC; c++)
643          if(allocLoc[c] && allocLoc[c] != (void *)0xabababab)
644             printf("      %s\n", allocLoc[c]);
645
646       if(showFree)
647       {
648          printf("   Free Location Stack:\n");
649          for(c = 0; c<MAX_MEMORY_LOC; c++)
650             if(freeLoc[c])
651                printf("      %s\n", freeLoc[c]);
652       }
653       //getch();
654    }
655 };
656
657 static BinaryTree memBlocks;
658
659 bool recurse = false;
660 static int blockID;
661 //Class allocateClass;
662 char * allocateClass;
663 bool allocateInternal;
664
665 #endif
666
667 static uint TOTAL_MEM = 0;
668 static uint OUTSIDE_MEM = 0;
669
670 #if !defined(ECERE_BOOTSTRAP)
671 static Mutex memMutex { };
672 #endif
673
674 private class MemBlock : struct
675 {
676    MemBlock prev, next;
677    MemPart part;
678    uint size;
679 };
680
681 private class MemPart : struct
682 {
683    void * memory;
684    int blocksUsed;
685    int size;
686    BlockPool * pool;
687 };
688 /*
689 #define NUM_POOLS          29
690 #define NEXT_SIZE(s)       NextFibonacci(s)
691 #define SIZE_POSITION(s)   PosFibonacci(s)
692 #define NTH_SIZE(p)        NthFibonacci(p)
693
694 static uint initNumBlocks[NUM_POOLS] =
695 {
696    1024, // 1
697    1024, // 2
698    1024, // 3
699    1024, // 5
700    1024, // 8
701    1024, // 13
702    1024, // 21
703    1024, // 34
704    1024, // 55
705    1024, // 89
706    1024, // 144
707    512,  // 233
708    512,  // 377
709    256,  // 610
710    128,  // 987
711    128,  // 1597
712    64,   // 2584
713    32,   // 4181
714    32,   // 6765
715    16,   // 10946
716    16,   // 17711
717    8,    // 28657
718    4,    // 46368
719    2,    // 75025
720    1,    // 121393
721    1,    // 196418
722    1,    // 317811
723    1,    // 514229
724    1,    // 832040
725 };
726
727 */
728 /*
729 #define NUM_POOLS 20
730 #define NEXT_SIZE(s)       pow2i(s)
731 #define SIZE_POSITION(s)   log2i(s)
732 #define NTH_SIZE(p)        (1<<p)
733
734    1024,  // 1 byte
735    4000,  // 1024,    // 2 bytes
736    2500,  // 1024,    // 4 bytes
737    18000, //1024,    // 8 bytes
738    20000, //1024,    // 16 bytes
739    29000, //1024,    // 32 bytes
740    46000, //1024,    // 64 bytes
741    20000, //1024,    // 128 bytes
742    26000, //512,     // 256 bytes
743    1400,  //256,     // 512 bytes
744    160,   //128,     // 1 K
745    500,  //64,      // 2 K
746
747 static uint initNumBlocks[NUM_POOLS] =
748 {
749    1024,  // 1 byte
750    1024,    // 2 bytes
751    1024,    // 4 bytes
752    1024,    // 8 bytes
753    1024,    // 16 bytes
754    1024,    // 32 bytes
755    1024,    // 64 bytes
756    1024,    // 128 bytes
757    512,     // 256 bytes
758    256,     // 512 bytes
759    128,     // 1 K
760    64,      // 2 K
761    32,      // 4 K
762    16,      // 8 K
763    8,       // 16 K
764    4,       // 32 K
765    2,       // 64 K
766    1,       // 128 K
767    1,       // 256 K
768    1        // 512 K
769 };
770 */
771
772 #define NUM_POOLS 31
773 #define NEXT_SIZE(s)       pow1_5i(s)
774 #define SIZE_POSITION(s)   log1_5i(s)
775 #define NTH_SIZE(p)        pow1_5(p)
776
777 static int power15[] =
778 {
779 /*
780 1
781 2
782 3
783 */
784 /*
785 4     // 4
786 6     // 8
787 9     // 12
788 13    // 16
789 19    // 24
790 28    // 32
791 42    // 48
792 63    // 64
793 94    // 96
794 141   // 144
795 211   // 224
796 316   // 320
797 474   // 480
798 711   // 720
799 1066  // 1072
800 1599  // 1600
801 2398  // 2400
802 3597  // 6900
803 5395  // 5408
804 8092  // 8096
805 12138 // 12144
806 18207 // 18208
807 27310 // 27312
808 40965 // 40976
809 61447 // 61456
810 92170 // 92176
811 138255   // 138256
812 207382   // 207392
813 311073   // 311088
814 466609   // 466624
815 699913   // 699920
816 */
817 4,
818 8,
819 12,
820 16,
821 24,
822 32,
823 48,
824 64,
825 96,
826 144,
827 224,
828 320,
829 480,
830 720,
831 1072,
832 1600,
833 2400,
834 6900,
835 5408,
836 8096,
837 12144,
838 18208,
839 27312,
840 40976,
841 61456,
842 92176,
843 138256,
844 207392,
845 311088,
846 466624,
847 699920
848 };
849
850 private struct BlockPool
851 {
852    MemBlock first, last;
853    MemBlock free;
854    uint blockSize;
855    uint blockSpace;
856    //MemPart * parts;
857    int numParts;
858    int numBlocks;
859    uint totalSize;
860    uint usedSpace;
861
862    bool Expand(uint numBlocks)
863    {
864       byte * memory = malloc(numBlocks * blockSpace);
865       // byte * memory = calloc(1, numBlocks * blockSpace);
866       TOTAL_MEM += numBlocks * blockSpace;
867 #ifdef _DEBUG
868       /*if(blockSize == 28)
869          printf("Expanding pool %x (%d)\n", this, blockSize);*/
870 #endif
871       if(memory)
872       {
873          int c;
874 #ifdef _DEBUG
875          uint totalAvailable = 0, totalAllocated = 0, totalBlocks = 0, totalUsed = 0;
876          uint totalParts = 0;
877 #endif
878          MemBlock block = (MemBlock)memory;
879          MemPart part = calloc(1, sizeof(class MemPart));
880          TOTAL_MEM += sizeof(class MemPart);
881          free = block;
882          for(c = 0; c<numBlocks - 1; c++)
883          {
884             // block.pool = this;
885             block.part = part;
886             /*if(part.size < 0)
887                printf("WARNING! part.size < 0\n");*/
888             block.prev = null;
889             block.next = (MemBlock)((byte *)block + blockSpace);
890             block = block.next;
891          }
892          part.blocksUsed = 0;
893          part.pool = this;
894          part.memory = memory;
895          part.size = numBlocks;
896
897          // block.pool = this;
898          block.part = part;
899          /*if(part.size < 0)
900             printf("/! part.size < 0\n");
901          if(part.pool == (void*) -1)
902             printf("WARNING! pool is -1\n");*/
903          block.prev = null;
904          block.next = null;
905
906          /*if(free && free.part && (free.part.size < 0 || free.part.pool == (void *)-1))
907             printf("WARNING! Bad next free block!\n");*/
908
909          //parts = realloc(parts, sizeof(MemPart) * (numParts + 1));
910
911          totalSize += numBlocks;
912
913 #ifdef _DEBUG
914          /*
915          {
916             for(c = 0; c<NUM_POOLS; c++)
917             {
918                BlockPool * pool = &pools[c];
919                printf("[%d %s (%d)]: available: %d, allocated: %d, free: %d, used: %d k, wasted: %d k, free: %d k\n", c, (&pools[c] == this) ? "*" : " ",
920                   pools[c].blockSize, pools[c].totalSize, pools[c].numBlocks, 
921                   pools[c].totalSize - pools[c].numBlocks, pools[c].usedSpace / 1024, ((pools[c].numBlocks * pools[c].blockSize) - pools[c].usedSpace) / 1024,
922                   (pools[c].totalSize - pools[c].numBlocks) * pools[c].blockSize / 1024);
923                totalAvailable += pools[c].totalSize * pools[c].blockSize;
924                totalAllocated += pools[c].numBlocks * pools[c].blockSize;
925                totalUsed += pools[c].usedSpace;
926                totalBlocks += pools[c].totalSize;
927                totalParts += pools[c].numParts;
928             }
929             printf("Total Available %d k, Total Allocated: %d k, Total Free: %d k\n", totalAvailable / 1024, totalAllocated / 1024, (totalAvailable - totalAllocated) / 1024);
930             printf("Total Number of Blocks %d, overhead of %d k\n", totalBlocks, totalBlocks * sizeof(class MemBlock) / 1024);
931             printf("Total Used Space %d k, wasted from roundup: %d k\n", totalUsed / 1024, (totalAllocated - totalUsed) / 1024);
932             printf("Total Memory Parts: %d\n", totalParts);
933             printf("TOTAL_MEM: %d k, OUTSIDE_MEM: %d k, BLOCKS: %d k\n", TOTAL_MEM / 1024, OUTSIDE_MEM / 1024, (totalAvailable + totalBlocks * sizeof(class MemBlock)) / 1024);
934             printf("\n");
935          }
936          */
937 #endif
938          //parts[] = part;
939          numParts++;
940          return true;
941       }
942       return false;
943    }
944
945    MemBlock Add()
946    {
947       MemBlock block = null;
948       /*if(blockSize == 28)
949          printf("BlockPool::Add (%d)\n", blockSize);*/
950       if(!free)
951          Expand(Max(1, numBlocks / 2));
952       if(free)
953       {
954          block = free;
955          block.prev = last;
956          if(block.prev)
957             block.prev.next = block;
958          if(!first)
959             first = block;
960          last = block;
961          free = block.next;
962          /*if(blockSize == 28)
963             printf("Free: %x, free.part: %x, free.part.size: %d, free.part.pool: %x (this = %x), next = %x (part = %x)\n", free, free ? free.part : null, 
964                (free && free.part) ? free.part.size : 0, (free && free.part) ? free.part.pool : 0, this, 
965                (free ? free.next : 0), (free && free.next) ? free.next.part : 0);
966          if(free && free.part && (free.part.size < 0 || free.part.pool == (void *)-1))
967             printf("WARNING! Bad next free block!\n");*/
968
969          block.next = null;
970          //if(block.part)
971             block.part.blocksUsed++;
972          /*else
973          {
974             printf("");
975          }*/
976          numBlocks++;
977       }
978       return block;
979    }
980
981    void Remove(MemBlock block)
982    {
983       /*if(blockSize == 28)
984          printf("BlockPool::Remove (%d)\n", blockSize);*/
985       if(block.prev)
986          block.prev.next = block.next;
987       if(block.next)
988          block.next.prev = block.prev;
989
990       if(first == block)
991          first = block.next;
992       if(last == block)
993          last = block.prev;
994       
995       // block.prev = null;
996       block.next = free;
997       free = block;
998
999       /*if(blockSize == 28)
1000       {
1001          printf("Setting new free block: part = %x\n", block.part);
1002       }*/
1003
1004       block.part.blocksUsed--;
1005       numBlocks--;
1006       block.part.pool->usedSpace -= block.size;
1007
1008       if(!block.part.blocksUsed && numBlocks && totalSize > numBlocks + numBlocks / 2)
1009       {
1010          MemBlock next = free, prev = null;
1011          MemPart part = block.part;
1012          free = null;
1013          totalSize -= part.size;
1014          /*if(blockSize == 28)
1015             printf("Freeing a part\n");*/
1016          while(next)
1017          {
1018             if(next.part != part)
1019             {
1020                if(prev)
1021                   prev.next = next;
1022                else
1023                   free = next;
1024                prev = next;
1025             }
1026             next = next.next;
1027          };
1028          if(prev)
1029             prev.next = null;
1030          
1031          TOTAL_MEM -= part.size * blockSpace;
1032          TOTAL_MEM -= sizeof(class MemPart);
1033          numParts--;
1034
1035          ::free(part.memory);
1036          ::free(part);
1037       }
1038       /*if(free && free.part && (free.part.size < 0 || free.part.pool == (void *)-1))
1039          printf("WARNING! Bad next free block!\n");*/
1040    }
1041 };
1042
1043 static BlockPool * pools; //[NUM_POOLS];
1044
1045 static uint PosFibonacci(uint number)
1046 {
1047    uint pos;
1048    uint last = 1, prev = 0;
1049    uint current = 1;
1050    
1051    for(pos=0; ; pos++)
1052    {
1053       current += prev;
1054       prev = last;
1055       last = current;
1056       if(current >= number)
1057          break;
1058    }
1059    return pos;
1060 }
1061
1062 static uint NthFibonacci(uint number)
1063 {
1064    uint pos;
1065    uint last = 1, prev = 0;
1066    uint current = 1;
1067    
1068    for(pos=0; pos <= number; pos++)
1069    {
1070       current += prev;
1071       prev = last;
1072       last = current;
1073    }
1074    return current;
1075 }
1076
1077 static uint NextFibonacci(uint number)
1078 {
1079    uint pos;
1080    uint last = 1, prev = 0;
1081    uint current = 1;
1082    
1083    for(pos=0; ; pos++)
1084    {
1085       current += prev;
1086       prev = last;
1087       last = current;
1088       if(current >= number)
1089          return current;
1090    }
1091 }
1092
1093 static uint log1_5i(uint number)
1094 {
1095    uint pos;
1096    uint64 current = sizeof(void *);
1097    
1098    for(pos=0; pos < NUM_POOLS; pos++)
1099    {
1100       if(current >= number)
1101          break;
1102       current = current * 3 / 2;
1103       if(current == 1) current = 2;
1104    }
1105    return pos;
1106 }
1107
1108 static uint pow1_5(uint number)
1109 {
1110    uint pos;
1111    uint64 current = sizeof(void *);
1112    for(pos=0; pos < number; pos++)
1113    {
1114       current = current * 3 / 2;
1115       if(current == 1) current = 2;
1116    }
1117    return (uint)current;
1118 }
1119
1120 static uint pow1_5i(uint number)
1121 {
1122    uint pos;
1123    uint64 current = sizeof(void *);
1124    
1125    for(pos=0; pos < NUM_POOLS; pos++)
1126    {
1127       if(current >= number)
1128          return (uint)current;
1129       current = current * 3 / 2;
1130       if(current == 1) current = 2;
1131    }
1132    return (uint)current;
1133
1134
1135 // -- Math Helpers ---
1136 public uint log2i(uint number)
1137 {
1138    uint power;
1139
1140    for(power=0; power<32; power++)
1141       if((1L<<power) >= number)
1142          break;
1143    return power;
1144 }
1145
1146 public uint pow2i(uint number)
1147 {
1148    return 1<<log2i(number);
1149 }
1150
1151 static bool memoryInitialized = false;
1152 static void InitMemory()
1153 {
1154    int c;
1155    memoryInitialized = true;
1156    pools = calloc(1, sizeof(BlockPool) * NUM_POOLS);
1157    for(c = 0; c<NUM_POOLS; c++)
1158    {
1159       int expansion;
1160       
1161       pools[c].blockSize = NTH_SIZE(c);
1162       if(pools[c].blockSize % sizeof(void *))
1163          pools[c].blockSize += sizeof(void *) - (pools[c].blockSize % sizeof(void *));
1164       pools[c].blockSpace = pools[c].blockSize;
1165       pools[c].blockSpace += sizeof(class MemBlock);      
1166       // pools[c].Expand(initNumBlocks[c]);
1167       
1168       expansion = (pools[c].blockSize < 128) ? 1024 : (131072 / pools[c].blockSize);
1169
1170       if(c < 12)
1171          pools[c].Expand(Max(1, expansion));
1172    }
1173 }
1174
1175 static void * _mymalloc(unsigned int size)
1176 {
1177    MemBlock block = null;
1178    if(size)
1179    {
1180       unsigned int p = SIZE_POSITION(size);
1181       if(!memoryInitialized) InitMemory();
1182       if(p < NUM_POOLS)
1183       {
1184          block = pools[p].Add();
1185          if(block)
1186          {
1187             block.size = size;
1188             pools[p].usedSpace += size;
1189          }
1190       }
1191       else
1192       {
1193          block = malloc(sizeof(class MemBlock) + size);
1194          if(block)
1195          {
1196             TOTAL_MEM += sizeof(class MemBlock) + size;
1197             OUTSIDE_MEM += sizeof(class MemBlock) + size;
1198             block.part = null;
1199             block.size = size;
1200          }
1201       }
1202    }
1203    return block ? ((struct MemBlock *)block + 1) : null;
1204 }
1205
1206 static void * _mycalloc(int n, unsigned int size)
1207 {
1208    void * pointer = _mymalloc(n*size);
1209    if(pointer)
1210       memset(pointer, 0, n*size);
1211    return pointer;
1212 }
1213
1214 static void _myfree(void * pointer)
1215 {
1216    if(pointer)
1217    {
1218       MemBlock block = (MemBlock)((byte *)pointer - sizeof(class MemBlock));
1219       MemPart part = block.part;
1220       BlockPool * pool = part ? part.pool : null; //block.pool;
1221       /*if(pool == (void*) -1)
1222          printf("WARNING! pool is -1\n");
1223       else   */
1224       if(pool)
1225          pool->Remove(block);
1226       else
1227       {
1228          TOTAL_MEM -= sizeof(class MemBlock) + block.size;
1229          OUTSIDE_MEM -= sizeof(class MemBlock) + block.size;
1230          free(block);
1231       }
1232    }
1233 }
1234
1235 static void * _myrealloc(void * pointer, unsigned int size)
1236 {
1237    MemBlock block = pointer ? ((MemBlock)((byte *)pointer - sizeof(class MemBlock))) : null;
1238    void * newPointer = null;
1239    MemPart part = block ? block.part : null;
1240    BlockPool * pool = part ? part.pool : null;
1241    if(block)
1242    {
1243       /*if(pool == (void*) -1)
1244          printf("WARNING! pool is -1\n");
1245       else*/
1246       if(pool)
1247       {
1248          // if((1 << pool) >= size && (pool - SIZE_POSITION(size)) <= 1)
1249          uint ns = NEXT_SIZE(size);
1250          uint mod = ns % sizeof(void *);
1251          if(mod) ns += sizeof(void *)-mod;
1252          if(ns == pool->blockSize)
1253          {
1254             newPointer = pointer;
1255             pool->usedSpace += size - block.size;
1256             block.size = size;
1257          }
1258       }
1259       else if(size)
1260       {
1261          MemBlock newBlock = realloc(block, sizeof(class MemBlock) + size);
1262          if(newBlock)
1263          {
1264             TOTAL_MEM += size - newBlock.size;
1265             OUTSIDE_MEM += size - newBlock.size;
1266             newPointer = ((struct MemBlock *)newBlock + 1);
1267          }
1268       }
1269    }
1270    if(!newPointer)
1271    {
1272       newPointer = _mymalloc(size);
1273       if(pointer && newPointer)
1274       {
1275          memcpy(newPointer, pointer, Min(size, block.size));
1276          _myfree(pointer);
1277       }
1278    }
1279    return newPointer;
1280 }
1281
1282 static void * _mycrealloc(void * pointer, unsigned int size)
1283 {
1284    MemBlock block = pointer ? ((MemBlock)((byte *)pointer - sizeof(class MemBlock))) : null;
1285    void * newPointer = null;
1286    MemPart part = block ? block.part : null;
1287    BlockPool * pool = part ? part.pool : null;
1288    if(block)
1289    {
1290       /*if(pool == (void*) -1)
1291          printf("WARNING! pool is -1\n");
1292       else*/
1293
1294       if(pool)
1295       {
1296          // if((1 << pool) >= size && (pool - SIZE_POSITION(size)) <= 1)
1297          uint ns = NEXT_SIZE(size);
1298          uint mod = ns % sizeof(void *);
1299          if(mod) ns += sizeof(void *)-mod;
1300          if(ns == pool->blockSize)
1301          {
1302             int extra = size - block.size;
1303             newPointer = pointer;
1304             pool->usedSpace += extra;
1305             if(extra > 0)
1306                memset((byte *)pointer + block.size, 0, extra);
1307             block.size = size;
1308          }
1309       }
1310       else if(size)
1311       {
1312          MemBlock newBlock = realloc(block, sizeof(class MemBlock) + size);
1313          if(newBlock)
1314          {
1315             int extra = size - newBlock.size;
1316             TOTAL_MEM += extra;
1317             OUTSIDE_MEM += extra;
1318             newPointer = ((struct MemBlock *)newBlock + 1);
1319             if(extra > 0)
1320                memset((byte *)newPointer + newBlock.size, 0, extra);
1321             newBlock.size = size;
1322          }
1323       }
1324    }
1325    if(!newPointer)
1326    {
1327       newPointer = _mymalloc(size);
1328       if(newPointer)
1329       {
1330          if(pointer)
1331          {
1332             memcpy(newPointer, pointer, Min(size, block.size));
1333             if(size > block.size)
1334                memset((byte *)newPointer + block.size, 0, size - block.size);
1335             _myfree(pointer);
1336          }
1337          else
1338             memset((byte *)newPointer, 0, size);
1339       }
1340    }
1341    return newPointer;
1342 }
1343
1344 #ifndef MEMINFO
1345 #undef realloc
1346 #undef crealloc
1347 #undef malloc
1348 #undef free
1349 #undef calloc
1350
1351 #define realloc _myrealloc
1352 #define crealloc _mycrealloc
1353 #define malloc _mymalloc
1354 #define free _myfree
1355 #define calloc _mycalloc
1356 #endif
1357
1358 static void * _malloc(unsigned int size)
1359 {
1360    void * pointer;
1361
1362 #if !defined(ECERE_BOOTSTRAP)
1363    memMutex.Wait();
1364 #endif
1365
1366    pointer = size ? malloc(size + 2 * REDZONE) : null;
1367 #ifdef MEMINFO
1368    if(pointer)
1369    {
1370       MemInfo block;
1371       MemStack stack = (MemStack)memStacks.Find(GetCurrentThreadID());
1372       if(!stack)
1373       {
1374          stack = (MemStack)calloc(1, sizeof(class MemStack));
1375          stack.key = GetCurrentThreadID();
1376          memStacks.Add(stack);
1377       }
1378
1379       if(!pointer)
1380       {
1381          int c;
1382          printf("Memory allocation of %d bytes failed\n", size);
1383          printf("Current Stack:\n");
1384          for(c = 0; c<stack.pos; c++)
1385             if(stack.frames[c])
1386                printf("      %s\n", stack.frames[c]);
1387
1388          memoryErrorsCount++;
1389          memMutex.Release();
1390          return null;
1391       }
1392
1393       if(!recurse && !stack.recurse)
1394       {
1395          stack.recurse = true;
1396          block = MemInfo { size = size, key = (uintptr)((byte *)pointer + REDZONE), id = blockID++ };
1397          memcpy(block.allocLoc, stack.frames + stack.pos - Min(stack.pos, MAX_MEMORY_LOC), Min(stack.pos, MAX_MEMORY_LOC) * sizeof(char *));
1398          memBlocks.Add(block);
1399          stack.recurse = false;
1400       }
1401    }
1402 #endif
1403
1404 #if !defined(ECERE_BOOTSTRAP)
1405    memMutex.Release();
1406 #endif
1407
1408 #if REDZONE
1409    if(pointer)
1410    {
1411       memset(pointer, 0xAB, REDZONE);
1412       memset((byte *)pointer + REDZONE + size, 0xAB, REDZONE);
1413       // ((byte *)pointer)[0] = 0x00;
1414    }
1415 #endif
1416    return pointer ? ((byte*)pointer + REDZONE) : null;
1417 }
1418
1419 static void * _calloc(int n, unsigned int size)
1420 {
1421    void * pointer;
1422 #if !defined(ECERE_BOOTSTRAP)
1423    memMutex.Wait();
1424 #endif
1425
1426    pointer = (n*size) ? calloc(1, n*size + 2 * REDZONE) : null;
1427 #ifdef MEMINFO
1428    if(pointer)
1429    {
1430       MemStack stack;
1431       stack = (MemStack)memStacks.Find(GetCurrentThreadID());
1432       if(!stack)
1433       {
1434          stack = (MemStack)calloc(1, sizeof(class MemStack));
1435          stack.key = GetCurrentThreadID();
1436          memStacks.Add(stack);
1437       }
1438       if(!pointer)
1439       {
1440          int c;
1441          printf("Memory allocation of %d bytes failed\n", size);
1442          printf("Current Stack:\n");
1443          for(c = 0; c<stack.pos; c++)
1444             if(stack.frames[c])
1445                printf("      %s\n", stack.frames[c]);
1446          memoryErrorsCount++;
1447          memMutex.Release();
1448          return null;
1449       }
1450
1451       if(!recurse && !stack.recurse)
1452       {
1453          MemInfo block;
1454
1455          stack.recurse = true;
1456          block = MemInfo { (unsigned int)n*size = size, key = (uintptr)((byte *)pointer + REDZONE), _class = allocateClass, internal = allocateInternal, id = blockID++ };
1457          memcpy(block.allocLoc, stack.frames + stack.pos - Min(stack.pos, MAX_MEMORY_LOC), Min(stack.pos, MAX_MEMORY_LOC) * sizeof(char *));
1458          memBlocks.Add(block);
1459          stack.recurse = false;
1460       }
1461    }
1462 }
1463 #endif
1464
1465 #if !defined(ECERE_BOOTSTRAP)
1466    memMutex.Release();
1467 #endif
1468
1469 #if REDZONE
1470    if(pointer)
1471    {
1472       memset(pointer, 0xAB, REDZONE);
1473       memset((byte *)pointer + REDZONE + (unsigned int)n*size, 0xAB, REDZONE);
1474    }
1475 #endif
1476    return pointer ? ((byte*)pointer + REDZONE) : null;
1477 }
1478
1479 static void * _realloc(void * pointer, unsigned int size)
1480 {
1481    if(!size) { _free(pointer); return null; }
1482 #if !defined(ECERE_BOOTSTRAP)
1483    memMutex.Wait();
1484 #endif
1485
1486 #ifdef MEMINFO
1487 {
1488    MemInfo block = null;
1489    MemStack stack;
1490    stack = (MemStack)memStacks.Find(GetCurrentThreadID());
1491    if(!stack)
1492    {
1493       stack = (MemStack)calloc(1, sizeof(class MemStack));
1494       stack.key = GetCurrentThreadID();
1495       memStacks.Add(stack);
1496    }
1497
1498    if(!recurse && !stack.recurse && pointer)
1499    {
1500       block = (MemInfo)memBlocks.Find((uintptr)pointer);
1501       if(!block)
1502       {
1503          printf("Reallocating Bad Memory\n");
1504          memoryErrorsCount++;
1505       }
1506       else if(block.freed)
1507       {
1508          printf("Reallocating Freed Memory\n");
1509          memoryErrorsCount++;
1510          block.OutputStacks(true);
1511       }
1512    }
1513    
1514    pointer = malloc(size + REDZONE * 2);
1515    if(!pointer)
1516    {
1517       int c;
1518       printf("Memory allocation of %d bytes failed\n", size);
1519       printf("Current Stack:\n");
1520       for(c = 0; c<stack.pos; c++)
1521          if(stack.frames[c])
1522             printf("      %s\n", stack.frames[c]);
1523       memoryErrorsCount++;
1524       memMutex.Release();
1525       return null;
1526    }
1527    memset(pointer, 0xAB, REDZONE);
1528    memset((byte *)pointer + REDZONE + size, 0xAB, REDZONE);
1529
1530    if(block)
1531    {
1532       if(block.freed)
1533       {
1534          memcpy((byte *)pointer + REDZONE, block.oldmem, Min(block.size, size));
1535       }
1536       else
1537       {
1538          memcpy(block.freeLoc, stack.frames + stack.pos - Min(stack.pos, MAX_MEMORY_LOC), Min(stack.pos, MAX_MEMORY_LOC) * sizeof(char *));
1539          memcpy((byte *)pointer + REDZONE, (byte *)block.key, Min(block.size, size));
1540          block.oldmem = (byte *)malloc(block.size + REDZONE * 2);
1541          if(block.oldmem)
1542          {
1543             block.oldmem += REDZONE;
1544             memcpy(block.oldmem - REDZONE, (byte *)block.key - REDZONE, block.size + 2 * REDZONE);
1545          }
1546          memset((byte *)block.key - REDZONE, 0xEC, block.size + REDZONE * 2);
1547          block.freed = true;
1548       }
1549    }
1550
1551    if(!recurse && !stack.recurse)
1552    {
1553       MemInfo block;
1554       stack.recurse = true;
1555       block = MemInfo { size = size, key = (uintptr)((byte *)pointer + REDZONE), id = blockID++ };
1556       memcpy(block.allocLoc, stack.frames + stack.pos - Min(stack.pos, MAX_MEMORY_LOC), Min(stack.pos, MAX_MEMORY_LOC) * sizeof(char *));
1557       memBlocks.Add(block);
1558       stack.recurse = false;
1559    }
1560 }
1561 #else
1562    pointer = realloc(pointer, size);
1563 #endif
1564
1565 #if !defined(ECERE_BOOTSTRAP)
1566    memMutex.Release();
1567 #endif
1568    return pointer ? ((byte *)pointer + REDZONE) : null;
1569 }
1570
1571 static void * _crealloc(void * pointer, unsigned int size)
1572 {
1573    if(!size) return null;
1574 #if !defined(ECERE_BOOTSTRAP)
1575    memMutex.Wait();
1576 #endif
1577
1578 #ifdef MEMINFO
1579 {
1580    MemInfo block = null;
1581    MemStack stack;
1582    stack = (MemStack)memStacks.Find(GetCurrentThreadID());
1583    if(!stack)
1584    {
1585       stack = (MemStack)calloc(1, sizeof(class MemStack));
1586       stack.key = GetCurrentThreadID();
1587       memStacks.Add(stack);
1588    }
1589
1590    if(!recurse && !stack.recurse && pointer)
1591    {
1592       block = (MemInfo)memBlocks.Find((uintptr)pointer);
1593       if(!block)
1594       {
1595          printf("Reallocating Bad Memory\n");
1596          memoryErrorsCount++;
1597       }
1598       else if(block.freed)
1599       {
1600          printf("Reallocating Freed Memory\n");
1601          memoryErrorsCount++;
1602          block.OutputStacks(true);
1603       }
1604    }
1605    
1606    pointer = calloc(1, size + REDZONE * 2);
1607    if(!pointer)
1608    {
1609       int c;
1610       printf("Memory allocation of %d bytes failed\n", size);
1611       printf("Current Stack:\n");
1612       for(c = 0; c<stack.pos; c++)
1613          if(stack.frames[c])
1614             printf("      %s\n", stack.frames[c]);
1615       memoryErrorsCount++;
1616       memMutex.Release();
1617       return null;
1618    }
1619    memset(pointer, 0xAB, REDZONE);
1620    memset((byte *)pointer + REDZONE + size, 0xAB, REDZONE);
1621
1622    if(block)
1623    {
1624       if(block.freed)
1625       {
1626          memcpy((byte *)pointer + REDZONE, block.oldmem, Min(block.size, size));
1627       }
1628       else
1629       {
1630          memcpy(block.freeLoc, stack.frames + stack.pos - Min(stack.pos, MAX_MEMORY_LOC), Min(stack.pos, MAX_MEMORY_LOC) * sizeof(char *));
1631          memcpy((byte *)pointer + REDZONE, (byte *)block.key, Min(block.size, size));
1632          block.oldmem = (byte *)malloc(block.size + REDZONE * 2);
1633          if(block.oldmem)
1634          {
1635             block.oldmem += REDZONE;
1636             memcpy(block.oldmem - REDZONE, (byte *)block.key - REDZONE, block.size + 2 * REDZONE);
1637          }
1638          memset((byte *)block.key - REDZONE, 0xEC, block.size + REDZONE * 2);
1639          block.freed = true;
1640       }
1641    }
1642
1643    if(!recurse && !stack.recurse)
1644    {
1645       MemInfo block;
1646       stack.recurse = true;
1647       block = MemInfo { size = size, key = (uintptr)((byte *)pointer + REDZONE), id = blockID++ };
1648       memcpy(block.allocLoc, stack.frames + stack.pos - Min(stack.pos, MAX_MEMORY_LOC), Min(stack.pos, MAX_MEMORY_LOC) * sizeof(char *));
1649       memBlocks.Add(block);
1650       stack.recurse = false;
1651    }
1652 }
1653 #else
1654    pointer = crealloc(pointer, size);
1655 #endif
1656
1657 #if !defined(ECERE_BOOTSTRAP)
1658    memMutex.Release();
1659 #endif
1660    return pointer ? ((byte *)pointer + REDZONE) : null;
1661 }
1662
1663 static void _free(void * pointer)
1664 {
1665    if(pointer)
1666    {
1667 #if !defined(ECERE_BOOTSTRAP)
1668       if(memMutex != pointer) memMutex.Wait();
1669 #endif
1670
1671 #ifdef MEMINFO
1672 {
1673       MemStack stack;
1674
1675       stack = (MemStack)memStacks.Find(GetCurrentThreadID());
1676       if(!stack)
1677       {
1678          stack = (MemStack)calloc(1, sizeof(class MemStack));
1679          stack.key = GetCurrentThreadID();
1680          memStacks.Add(stack);
1681       }
1682
1683       if(!recurse && !stack.recurse)
1684       {
1685          MemInfo block;
1686          stack.recurse = true;
1687          block = (MemInfo)memBlocks.Find((uintptr)pointer);
1688          if(!block)
1689          {
1690             int c;
1691             printf("Freeing Bad Memory\n");
1692             printf("Current Stack:\n");
1693             for(c = 0; c<stack.pos; c++)
1694                if(stack.frames[c])
1695                   printf("      %s\n", stack.frames[c]);
1696
1697             memoryErrorsCount++;
1698          }
1699          else if(block.freed)
1700          {
1701             int c;
1702             printf("Freeing Already Freed Memory\n");
1703             printf("Current Stack:\n");
1704             for(c = 0; c<stack.pos; c++)
1705                if(stack.frames[c])
1706                   printf("      %s\n", stack.frames[c]);
1707
1708             memoryErrorsCount++;
1709             block.OutputStacks(true);
1710          }
1711          else
1712          {
1713             /*int c;
1714             byte * address = (byte *)block.key;
1715             for(c = 0; c<REDZONE; c++)
1716             {
1717                if(address[-c-1] != 0xEC)
1718                {
1719                   printf("Buffer Underrun\n");
1720                   memoryErrorsCount++;
1721                   block.OutputStacks(block.freed);
1722                }
1723                if(address[c + block.size] != 0xEC)
1724                {
1725                   printf("Buffer Overrun\n");
1726                   memoryErrorsCount++;
1727                   block.OutputStacks(block.freed);
1728                }
1729             }*/
1730
1731             {
1732                byte * address;
1733                int c;
1734                int size = block.size;
1735                address = (byte *)block.key;
1736                for(c = 0; c<REDZONE; c++)
1737                {
1738                   if(address[-c-1] != 0xAB)
1739                   {
1740                      printf("Buffer Underrun\n");
1741                      memoryErrorsCount++;
1742                      block.OutputStacks(block.freed);
1743                   }
1744                   if(address[c + size] != 0xAB)
1745                   {
1746                      printf("Buffer Overrun\n");
1747                      memoryErrorsCount++;
1748                      block.OutputStacks(block.freed);
1749                   }
1750                }
1751             }
1752
1753             block.freed = true;
1754             block.oldmem = (byte *)malloc(block.size + REDZONE * 2);
1755             if(block.oldmem)
1756             {
1757                block.oldmem += REDZONE;
1758                memcpy(block.oldmem - REDZONE, (byte *)block.key - REDZONE, block.size + REDZONE * 2);
1759             }
1760             memset((byte *)block.key - REDZONE, 0xEC, block.size + REDZONE * 2);
1761
1762             memcpy(block.freeLoc, stack.frames + stack.pos - Min(stack.pos, MAX_MEMORY_LOC), Min(stack.pos, MAX_MEMORY_LOC) * sizeof(char *));
1763          }
1764          stack.recurse = false;
1765       }
1766 }
1767 #else
1768       free(pointer);
1769 #endif
1770
1771 #if !defined(ECERE_BOOTSTRAP)
1772       if(memMutex != pointer) memMutex.Release();
1773 #endif
1774    }
1775 }
1776
1777 public void memswap(byte * a, byte * b, uint size)
1778 {
1779    uint c;
1780    byte buffer[1024];
1781    for(c = 0; c<size;)
1782    {
1783       int s = sizeof(buffer);
1784       if(c + s > size) s = size - c;
1785       memcpy(buffer, a + c, s);
1786       memcpy(a + c, b + c, s);
1787       memcpy(b + c, buffer, s);
1788       c += s;
1789    }
1790 }
1791
1792 public void CheckMemory()
1793 {
1794 #ifdef MEMINFO
1795    MemInfo block;
1796    uint leaksCount = 0;
1797    uint leakedObjects = 0;
1798    uint leaksSize = 0;
1799    recurse = true;
1800    // Verify Tree Integrity
1801    if(!memBlocks.Check())
1802    {
1803       printf("Memory Blocks Tree Integrity Failed\n");
1804       memoryErrorsCount++;
1805    }
1806    printf("Starting Memory Check\n");
1807    for(block = (MemInfo)memBlocks.first; block; block = (MemInfo)block.next)
1808    {
1809       if(!block.freed && block._class)
1810          leakedObjects++;
1811    }
1812
1813    for(block = (MemInfo)memBlocks.root; block;)
1814    {
1815       if(block.freed)
1816          memswap((byte *)block.key - REDZONE, block.oldmem - REDZONE, block.size + REDZONE * 2);
1817       else
1818       {
1819          if(block._class)
1820          {
1821             // if(!block.internal)
1822             {
1823                // printf("Object of class %s\n", block._class);
1824                block.OutputStacks(false);
1825             }
1826          }
1827          else if(!leakedObjects)
1828          {
1829             printf("Memory Leak\n");
1830             block.OutputStacks(false);
1831          }
1832
1833          leaksCount ++;
1834          leaksSize += block.size;
1835       }
1836
1837       if(block.left)
1838          block = (MemInfo)block.left;
1839       else if(block.right)
1840          block = (MemInfo)block.right;
1841       else
1842       {
1843          while(block)
1844          {
1845             MemInfo parent = (MemInfo)block.parent;
1846             if(parent && block == (MemInfo)parent.left && parent.right)
1847             {
1848                block = (MemInfo)parent.right;
1849                break;
1850             }
1851             block = parent;
1852          }
1853       }
1854    }
1855
1856    while(block = (MemInfo)memBlocks.root)
1857    {
1858       byte * address;
1859       int c;
1860       int size = block.size;
1861       if(block.freed)
1862       {
1863          address = block.oldmem;
1864          for(c = -REDZONE; c<size + REDZONE; c++)
1865             if(address[c] != 0xEC)
1866             {
1867                break;
1868             }
1869          if(c < size + REDZONE)
1870          {
1871             printf("Freed Memory Write\n");
1872             memoryErrorsCount++;
1873             block.OutputStacks(true);
1874          }
1875       }
1876       
1877       address = (byte *)block.key;
1878       for(c = 0; c<REDZONE; c++)
1879       {
1880          if(address[-c-1] != 0xAB)
1881          {
1882             printf("Buffer Underrun\n");
1883             memoryErrorsCount++;
1884             block.OutputStacks(block.freed);
1885          }
1886          if(address[c + size] != 0xAB)
1887          {
1888             printf("Buffer Overrun\n");
1889             memoryErrorsCount++;
1890             block.OutputStacks(block.freed);
1891          }
1892       }
1893             
1894       memBlocks.Delete(block);
1895    }
1896    if(leaksCount)
1897    {
1898       printf("%d Memory Leaks Detected (%d objects, %d bytes).\n", leaksCount, leakedObjects, leaksSize);
1899       memoryErrorsCount++;
1900    }
1901    printf("Memory Check Completed.\n");
1902 #if defined(__WIN32__) && !defined(ECERE_BOOTSTRAP)
1903    if(memoryErrorsCount)
1904       getch();
1905 #endif
1906 #endif
1907 }
1908
1909 static void FixDerivativesBase(Class base, Class mod)
1910 {
1911    OldLink derivative;
1912    OldLink templateLink;
1913
1914    ComputeClassParameters(base, strchr(base.name, '<'), null);
1915
1916    for(derivative = base.derivatives.first; derivative; derivative = derivative.next)
1917    {
1918       Class _class = derivative.data;
1919       ClassType type = _class.type;
1920       int size = _class.structSize - _class.offset;
1921       int oldSizeClass = _class.sizeClass;
1922       int sizeClass = _class.sizeClass - _class.offsetClass;
1923       Class enumBase = null;
1924       char * dataTypeString = null;
1925       // NOTE: baseClass is class(class)
1926       Class baseClass;
1927       uint offsetBefore = _class.offset;
1928
1929       int offsetClass, totalSizeClass;
1930
1931       for(baseClass = base; baseClass.base; baseClass = baseClass.base);
1932
1933       if(base && !base.internalDecl && (base.type == noHeadClass || base.type == structClass || base.type == normalClass))
1934       {
1935          // Normal classes inheriting off simple classes should become no head classes
1936          if(base.type == structClass && type == normalClass)
1937             type = noHeadClass;
1938          else
1939             type = base.type;
1940       }
1941       if(base && (_class.type == normalClass || _class.type == noHeadClass || _class.type == structClass) &&
1942          (base.type == unitClass || base.type == bitClass || base.type == enumClass))
1943       {
1944          type = base.type;
1945       }
1946
1947       if(type == enumClass)
1948       {
1949          if(base.type != enumClass)
1950          {
1951             enumBase = base;
1952             base = eSystem_FindClass(_class.module, "enum");
1953          }
1954       }
1955
1956       dataTypeString = enumBase ? enumBase.dataTypeString : base.dataTypeString;
1957
1958       /////////////////////
1959       
1960       offsetClass = base ? (base.templateClass ? base.templateClass.sizeClass : base.sizeClass) : (type == noHeadClass ? 0 : 0 /*sizeof(class Class)*/);
1961       totalSizeClass = offsetClass + sizeClass;
1962
1963       // TESTING WITHOUT THIS... Seems to yield better results, as it otherwise prevents ComputeClassMembers from doing its job on derived classes
1964
1965       // _class.memberID = _class.startMemberID = (base && (type == normalClass || type == noHeadClass || type == structClass)) ? base.memberID : 0;
1966
1967       if(type == normalClass || type == noHeadClass)
1968          _class.offset = (base && (base.templateClass ? base.templateClass.structSize : base.structSize) && base.type != systemClass) ? (base.templateClass ? base.templateClass.structSize : base.structSize) : ((type == noHeadClass) ? 0 : sizeof(class Instance));
1969
1970       if(type == structClass)
1971       {
1972          _class.memberOffset = (base && (base.templateClass ? base.templateClass.structSize : base.structSize) && base.type != systemClass) ? (base.templateClass ? base.templateClass.structSize : base.structSize) : 0;
1973          // THIS IS NEW...
1974          _class.typeSize = _class.structSize = _class.memberOffset + size;
1975       }
1976       else if(type == bitClass || type == enumClass || type == unitClass)
1977       {  
1978          Class dataTypeClass = eSystem_FindClass(_class.module, dataTypeString);
1979          if(dataTypeClass)
1980             _class.typeSize = dataTypeClass.typeSize;
1981          _class.structSize = 0;
1982       }
1983       else if(type == normalClass || type == noHeadClass)
1984       {
1985          _class.structSize = _class.offset + size;
1986           _class.typeSize = sizeof(void *);
1987       }
1988
1989       /////////////////////
1990
1991       if(_class.type != systemClass)
1992          _class.type = type;
1993       delete _class.dataTypeString;
1994       _class.dataTypeString = CopyString(dataTypeString);
1995
1996       if(totalSizeClass != oldSizeClass)
1997       {
1998          _class.data = renew _class.data byte[totalSizeClass];
1999          /*
2000          memmove((byte *)_class.data + offsetClass, (byte *)_class.data + _class.offsetClass, _class.sizeClass - _class.offsetClass);
2001          if(base.type != systemClass && base.type != enumClass)
2002             memcpy((byte *)_class.data + _class.offsetClass, (byte *)base.data + _class.offsetClass, totalSizeClass - _class.sizeClass);
2003          else
2004             memset((byte *)_class.data + _class.offsetClass, 0, totalSizeClass - _class.sizeClass);
2005          */
2006          memmove((byte *)_class.data + mod.offsetClass, (byte *)_class.data, totalSizeClass - mod.sizeClass);
2007          if(base.type != systemClass && base.type != enumClass)
2008             memcpy((byte *)_class.data, (byte *)base.data, totalSizeClass - _class.sizeClass);
2009          else
2010             memset((byte *)_class.data, 0, totalSizeClass - _class.sizeClass);
2011       }
2012
2013       _class.offsetClass = offsetClass;
2014       _class.sizeClass = totalSizeClass;
2015
2016       {
2017          Method method, next;
2018          Class b;
2019          bool needUpdate = (mod != (base.templateClass ? base.templateClass : base) || _class.vTblSize != mod.vTblSize;
2020          int updateStart = -1, updateEnd = -1;
2021
2022          if(mod.base && mod.base.base && mod.base.vTblSize > baseClass.vTblSize && needUpdate)
2023          {
2024             _class.vTblSize += mod.base.vTblSize - baseClass.vTblSize;
2025             _class._vTbl = renew _class._vTbl void *[_class.vTblSize];
2026             // memmove(_class._vTbl + mod.base.vTblSize, _class._vTbl + baseClass.vTblSize, (mod.base.vTblSize - baseClass.vTblSize) * sizeof(void *));
2027             memmove(_class._vTbl + mod.base.vTblSize, _class._vTbl + baseClass.vTblSize, (_class.vTblSize - mod.vTblSize) * sizeof(void *));
2028
2029             updateStart = baseClass.vTblSize;
2030             updateEnd = updateStart + mod.base.vTblSize - baseClass.vTblSize;
2031
2032             for(method = (Method)_class.methods.first; method; method = next)
2033             {
2034                next = (Method)((BTNode)method).next;
2035                if(method.type == virtualMethod)
2036                   method.vid += mod.base.vTblSize - baseClass.vTblSize;
2037             }
2038          }
2039
2040             for(b = mod.base; b && b != null; b = b.base)
2041             {
2042                Method vMethod;
2043                for(vMethod = (Method)b.methods.first; vMethod; vMethod = (Method)((BTNode)vMethod).next)
2044                {
2045                   if(vMethod.type == virtualMethod)
2046                   {
2047                      method = (Method)_class.methods.FindString(vMethod.name);
2048                      if(method)
2049                      {
2050                         if(method.function) _class._vTbl[vMethod.vid] = method.function;
2051                         if(!method.symbol)
2052                         {
2053                            delete method.name;
2054                            delete method.dataTypeString;
2055                            _class.methods.Delete((BTNode)method);
2056                         }
2057                         else
2058                         {
2059                            delete method.dataTypeString;
2060                            method.type = vMethod.type;
2061                            method.dataTypeString = CopyString(vMethod.dataTypeString);
2062                            method._class = vMethod._class;
2063                         }
2064                      }
2065                      else if((vMethod.vid >= updateStart && vMethod.vid < updateEnd ) || _class._vTbl[vMethod.vid] == b._vTbl[vMethod.vid])
2066                         _class._vTbl[vMethod.vid] = _class.base._vTbl[vMethod.vid];
2067                   }
2068                }
2069             }
2070          //}
2071
2072          // Trying to simply move out the above block of code outside the if to handle this
2073          /*
2074          // Also doing this now, otherwise overridden methods of base classes from intermediate classes will not be set in higher level class
2075          // (e.g. OnGetString overridden in Id , Location inheriting from Id, LocationAbbreviation created later inheriting from Location would not get Id's OnGetString)
2076          for(b = mod.base; b && b != null; b = b.base)
2077          {
2078             Method vMethod;
2079             for(vMethod = (Method)b.methods.first; vMethod; vMethod = (Method)((BTNode)vMethod).next)
2080             {
2081                if(vMethod.type == virtualMethod)
2082                {
2083                   if(_class._vTbl[vMethod.vid] == b._vTbl[vMethod.vid] && _class._vTbl[vMethod.vid] != _class.base._vTbl[vMethod.vid])
2084                      _class._vTbl[vMethod.vid] = _class.base._vTbl[vMethod.vid];
2085                }
2086             }
2087          }
2088          */
2089       }
2090
2091       // _class.defaultAlignment = base ? base.defaultAlignment : 0;
2092    
2093       if(type == normalClass || type == noHeadClass || type == structClass)
2094       {
2095          Property prop;
2096          DataMember member;
2097          Class c;
2098          for(c = mod.base; c; c = c.base)
2099          {
2100             Property _property;
2101             for(_property = c.membersAndProperties.first; _property; _property = _property.next)
2102             {
2103                if(_property.isProperty)
2104                {
2105                   BTNamedLink link = (BTNamedLink)_class.prop.FindString(_property.name);
2106                   if(link)
2107                   {
2108                      prop = link.data;
2109                      if(!prop.Set && !prop.Get && prop.memberAccess == baseSystemAccess)
2110                      {
2111                         SelfWatcher watcher;
2112                         for(watcher = _class.selfWatchers.first; watcher; watcher = watcher.next)
2113                         {
2114                            if(watcher._property == prop)
2115                               watcher._property = _property;
2116                         }
2117                         _property.selfWatchable = true;
2118                         _class.prop.Delete((BTNode)link);
2119                         delete prop.name;
2120                         delete prop.dataTypeString;
2121                         _class.membersAndProperties.Delete(prop);    // Remove only was done before?
2122                      }
2123                   }
2124                }
2125             }
2126          }
2127          // if(mod.base.memberID)
2128          {
2129             for(member = _class.membersAndProperties.first; member; member = member.next)
2130             {
2131                int offsetDiff = _class.offset - offsetBefore;
2132                if(!member.isProperty && offsetDiff > 0)
2133                {
2134                   member.offset += offsetDiff;
2135                   member.memberOffset += offsetDiff;
2136                }
2137                member.id += mod.base.memberID;
2138             }
2139
2140             _class.memberID += mod.base.memberID;
2141             _class.startMemberID += mod.base.memberID;
2142          }
2143       }
2144       // Moved this before to ensure CPValues have their data ready
2145       FixDerivativesBase(_class, mod);
2146       {
2147          Class c;
2148          for(c = mod.base; c; c = c.base)
2149          {
2150             ClassProperty _property;
2151             for(_property = (ClassProperty)c.classProperties.first; _property; _property = (ClassProperty)((BTNode)_property).next)
2152             {
2153                SetDelayedCPValues(_class, _property);
2154             }
2155          }
2156       }
2157    }
2158    
2159    {
2160       OldLink templateLink;
2161       for(templateLink = base.templatized.first; templateLink; templateLink = templateLink.next)
2162       {
2163          Class template = templateLink.data;
2164          char * templateParams = strchr(template.name, '<');
2165          template.base = base.base;
2166          template._vTbl = base._vTbl;
2167          //ComputeClassParameters(template, templateParams, null);
2168
2169          template.data = base.data;
2170          template.offset = base.offset;
2171          template.offsetClass = base.offsetClass;
2172          template.sizeClass = base.sizeClass;
2173          template.structSize = base.structSize;
2174          template.vTblSize = base.vTblSize;
2175          
2176          FixDerivativesBase(template, mod);
2177       }
2178    }
2179 }
2180
2181 public dllexport Class eSystem_RegisterClass(ClassType type, char * name, char * baseName, int size, int sizeClass,
2182                              bool (* Constructor)(void *),void (* Destructor)(void *),
2183                              Module module, AccessMode declMode, AccessMode inheritanceAccess)
2184 {
2185    int start = 0, c;
2186    NameSpace * nameSpace = null;
2187    bool force64Bits = (module.application.isGUIApp & 2) ? true : false;
2188    bool force32Bits = (module.application.isGUIApp & 4) ? true : false;
2189    bool inCompiler = (module.application.isGUIApp & 8) ? true : false;
2190    bool crossBits = force32Bits || force64Bits;
2191
2192    {
2193       nameSpace = (declMode == publicAccess) ? &module.publicNameSpace : &module.privateNameSpace;
2194       if(declMode == baseSystemAccess) nameSpace = &module.application.systemNameSpace;
2195
2196       // if(declMode != staticAccess)
2197       {
2198          for(c = 0; name[c]; c++)
2199          {
2200             if(name[c] == '.' || (name[c] == ':' && name[c+1] == ':'))
2201             {
2202                NameSpace * newSpace;
2203
2204                char * spaceName = _malloc(c - start + 1);
2205                strncpy(spaceName, name + start, c - start);
2206                spaceName[c-start] = '\0';
2207
2208                newSpace = (NameSpace *)nameSpace->nameSpaces.FindString(spaceName);
2209                if(!newSpace)
2210                {
2211                   newSpace = new0 NameSpace[1];
2212                   newSpace->classes.CompareKey = (void *)BinaryTree::CompareString;
2213                   newSpace->defines.CompareKey = (void *)BinaryTree::CompareString;
2214                   newSpace->functions.CompareKey = (void *)BinaryTree::CompareString;
2215                   newSpace->nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
2216                   newSpace->name = spaceName;
2217                   newSpace->parent = nameSpace;
2218                   nameSpace->nameSpaces.Add((BTNode)newSpace);
2219                }
2220                else
2221                   delete spaceName;
2222                nameSpace = newSpace;
2223                if(name[c] == ':') c++;
2224                start = c+1;
2225             }
2226          }
2227       }
2228       /*else
2229          c = strlen(name);*/
2230    }
2231
2232    if(c - start)
2233    {
2234       int offsetClass; 
2235       int totalSizeClass;
2236       BTNamedLink classLink = null;
2237       Class _class = null;
2238       char * dataTypeString = null;
2239       Class enumBase = null;
2240       Class base = (baseName && baseName[0]) ? eSystem_FindClass(module, baseName) : null;
2241       bool refine = false;
2242
2243       if(base && !base.internalDecl && (base.type == noHeadClass || base.type == structClass || base.type == normalClass)) 
2244       {
2245          // Normal classes inheriting off simple classes should become no head classes
2246          if(base.type == structClass && type == normalClass)
2247             type = noHeadClass;
2248          else
2249             type = base.type;
2250       }
2251       if(base && (type == normalClass || type == noHeadClass || type == structClass) && 
2252          (base.type == unitClass || base.type == bitClass || base.type == enumClass))
2253       {
2254          type = base.type;
2255       }
2256       if(!base || base.type == systemClass)
2257       {
2258          if(type == enumClass)
2259          {
2260             // TO IMPROVE:
2261             if(base || !baseName || !baseName[0] ||
2262                !strcmp(baseName, "unsigned int") || 
2263                !strcmp(baseName, "uint") || 
2264                !strcmp(baseName, "unsigned int64") || 
2265                !strcmp(baseName, "uint64") || 
2266                !strcmp(baseName, "int64") || 
2267                !strcmp(baseName, "unsigned short") || 
2268                !strcmp(baseName, "short") || 
2269                !strcmp(baseName, "unsigned char") || 
2270                !strcmp(baseName, "byte") || 
2271                !strcmp(baseName, "char") || 
2272                !strcmp(baseName, "uint32") || 
2273                !strcmp(baseName, "uint16"))
2274             {
2275                base = eSystem_FindClass(module, "enum");
2276                dataTypeString = (baseName && baseName[0]) ? baseName : "int"; //"unsigned int";
2277             }
2278             else
2279             {
2280                // Undefined base
2281                base = eSystem_RegisterClass(0, baseName, null, 0,0, null, null, module, declMode, publicAccess);
2282                base.internalDecl = true;
2283
2284                enumBase = base;
2285                base = eSystem_FindClass(module, "enum");
2286                //dataTypeString = (baseName && baseName[0]) ? baseName : "unsigned int";
2287             }
2288          }
2289          else if(type == structClass && (!baseName || !baseName[0]))
2290          {
2291             base = eSystem_FindClass(module, "struct");
2292             dataTypeString = name + start;
2293          }
2294          else 
2295          {
2296             if(type == normalClass)
2297                // dataTypeString = "struct Instance";
2298                dataTypeString = "struct __ecereNameSpace__ecere__com__Instance";
2299             else if(type == noHeadClass)
2300                dataTypeString = "void *";
2301             else if(type == bitClass)
2302                dataTypeString = (baseName && baseName[0]) ? baseName : "unsigned int";
2303             else if(type == unitClass)
2304                dataTypeString = (baseName && baseName[0]) ? baseName : "int";
2305             else if(type == structClass)
2306                dataTypeString = name + start;
2307
2308             // TODO: base bit, unit or enum classes not defined yet
2309             if(base || (!baseName || !baseName[0]) || type == bitClass || type == unitClass)
2310             {
2311                // DANGEROUSLY TESTING THIS... PUT IT BACK
2312                //if(!base)
2313                if(base || !baseName || !baseName[0] ||
2314                   !strcmp(baseName, "unsigned int") || 
2315                   !strcmp(baseName, "uint") || 
2316                   !strcmp(baseName, "unsigned int64") || 
2317                   !strcmp(baseName, "uint64") || 
2318                   !strcmp(baseName, "int64") || 
2319                   !strcmp(baseName, "unsigned short") || 
2320                   !strcmp(baseName, "short") || 
2321                   !strcmp(baseName, "unsigned char") || 
2322                   !strcmp(baseName, "byte") || 
2323                   !strcmp(baseName, "char") || 
2324                   !strcmp(baseName, "uint32") || 
2325                   !strcmp(baseName, "uint16"))
2326                {
2327                   if(type == normalClass && strcmp(name, "ecere::com::Instance") && strcmp(name, "enum") && strcmp(name, "struct"))
2328                      base = eSystem_FindClass(module, "ecere::com::Instance");
2329                   else
2330                      base = eSystem_FindClass(module, "class");
2331                }
2332             }
2333             else
2334             {
2335                // Base class has not been defined yet!
2336             }
2337          }
2338       }
2339       else
2340       {
2341          if(type == enumClass)
2342          {
2343             if(base.type != enumClass)
2344             {
2345                enumBase = base;
2346                base = eSystem_FindClass(module, "enum");
2347             }
2348          }
2349          dataTypeString = enumBase ? enumBase.dataTypeString : base.dataTypeString;
2350       }
2351
2352       offsetClass = base ? base.sizeClass : (type == noHeadClass ? 0 : 0 /*sizeof(class Class)*/);
2353       totalSizeClass = offsetClass + sizeClass;
2354    
2355       if((_class = eSystem_FindClass(module, name)))
2356       {
2357          FreeTemplatesDerivatives(_class);
2358
2359          if(!_class.internalDecl)
2360          {
2361             if(declMode != baseSystemAccess)
2362                // i18n in instance.ec is more trouble than it's worth.
2363                printf("error: Redefinition of class %s\n", name);
2364             else
2365             {
2366                _class.comRedefinition = true;
2367                return _class;
2368             }
2369             return null;
2370          }
2371
2372          classLink = (BTNamedLink)_class.nameSpace->classes.FindString(name + start);
2373          _class.nameSpace->classes.Delete((BTNode)classLink);
2374          {
2375             OldLink t;
2376             for(t = _class.templatized.first; t; t = t.next)
2377             {
2378                Class template = t.data;
2379                classLink = (BTNamedLink)_class.nameSpace->classes.FindString(template.name);
2380
2381                _class.nameSpace->classes.Delete((BTNode)classLink);
2382             }
2383          }
2384          {
2385             NameSpace * ns = _class.nameSpace;
2386             while(ns->parent && 
2387                !ns->classes.first && 
2388                !ns->functions.first &&
2389                !ns->defines.first &&
2390                !ns->nameSpaces.first)
2391             {
2392                NameSpace * parent = ns->parent;
2393                NameSpace_Free(ns);
2394                parent->nameSpaces.Delete((BTNode)ns);
2395                ns = parent;
2396             }
2397          }
2398          refine = true;
2399       }
2400       else
2401       {
2402          classLink = SearchNameSpace(module.application.privateNameSpace, name, &((NameSpace *)0)->classes);
2403          if(!classLink)
2404             classLink = SearchNameSpace(module.application.publicNameSpace, name, &((NameSpace *)0)->classes);
2405
2406          if(!classLink)
2407             classLink = SearchNameSpace(module.application.privateNameSpace, name + start, &((NameSpace *)0)->classes);
2408          if(!classLink)
2409             classLink = SearchNameSpace(module.application.publicNameSpace, name + start, &((NameSpace *)0)->classes);
2410
2411          if(classLink)
2412             _class = classLink.data;
2413          if(_class && _class.internalDecl)
2414          {
2415             FreeTemplatesDerivatives(_class);
2416
2417             _class.nameSpace->classes.Delete((BTNode)classLink);
2418             {
2419                OldLink t;
2420                for(t = _class.templatized.first; t; t = t.next)
2421                {
2422                   Class template = t.data;
2423                   classLink = (BTNamedLink)_class.nameSpace->classes.FindString(template.name);
2424                   _class.nameSpace->classes.Delete((BTNode)classLink);
2425
2426                }
2427             }
2428
2429             refine = true;
2430             delete _class.fullName;
2431             _class.fullName = CopyString(name);
2432          }
2433          else
2434          {
2435             _class = _calloc(1, sizeof(class Class));
2436             _class.methods.CompareKey = (void *)BinaryTree::CompareString;
2437             _class.members.CompareKey = (void *)BinaryTree::CompareString;
2438             _class.prop.CompareKey = (void *)BinaryTree::CompareString;
2439             _class.classProperties.CompareKey = (void *)BinaryTree::CompareString;
2440
2441             _class.name = CopyString(name + start);
2442             _class.fullName = CopyString(name);
2443          }
2444       }
2445       if(nameSpace)
2446       {
2447          nameSpace->classes.Add((BTNode)BTNamedLink { name = _class.name, data = _class });
2448          {
2449             OldLink t;
2450             for(t = _class.templatized.first; t; t = t.next)
2451             {
2452                Class template = t.data;
2453                nameSpace->classes.Add((BTNode)BTNamedLink { name = template.name, data = template });
2454             }
2455          }
2456
2457       }
2458
2459       if(_class)
2460       {
2461          if(!base && baseName && strcmp(baseName, name))
2462          {
2463             // Undefined base
2464             if(strchr(baseName, '<'))
2465             {
2466                char templateClassName[1024];
2467                Class templateBase;
2468                strcpy(templateClassName, baseName);
2469                *strchr(templateClassName, '<') = '\0';
2470                templateBase = eSystem_FindClass(module, templateClassName);
2471                if(!templateBase)
2472                {
2473                   templateBase = eSystem_RegisterClass(0, templateClassName, null, 0,0, null, null, module, declMode, publicAccess);
2474                   templateBase.internalDecl = true;
2475                }
2476                base = eSystem_FindClass(module, baseName);
2477             }
2478             else
2479             {
2480                base = eSystem_RegisterClass(0, baseName, null, 0,0, null, null, module, declMode, publicAccess);
2481                base.internalDecl = true;
2482             }
2483             /*
2484             base.size = 0;
2485             base.offset = 0;
2486             base.memberOffset = 0;
2487             */
2488          }
2489          else
2490             _class.internalDecl = false;
2491
2492          if(totalSizeClass)
2493          {
2494             _class.data = renew _class.data byte[totalSizeClass];
2495             // Class Data is often not inherited... e.g. Window::pureVtbl problem
2496             // memset(_class.data, 0, totalSizeClass);
2497             if(base && base.type != systemClass && base.type != enumClass)
2498                memcpy(_class.data, base.data, offsetClass);
2499             else
2500                memset(_class.data, 0, offsetClass);
2501             memset((byte *)_class.data + offsetClass, 0, sizeClass);
2502          }
2503
2504          delete _class.dataTypeString;
2505          _class.dataTypeString = CopyString(dataTypeString);
2506          _class.defaultAlignment = base ? base.defaultAlignment : 0;
2507
2508          // Dereference the class in previous module the classed belonged to
2509          if(_class.module)
2510          {
2511             _class.module.classes.Remove(_class);
2512          }
2513
2514          if(_class.base)
2515          {
2516             //Class base = _class.base.templateClass ? _class.base.templateClass : _class.base;
2517             Class base = _class.base;
2518             OldLink deriv = base.derivatives.FindLink(_class);
2519             base.derivatives.Delete(deriv);
2520          }
2521
2522          // Reference the class in the module
2523          if(module)
2524          {
2525             module.classes.Add(_class);
2526          }
2527
2528          _class.nameSpace = nameSpace;
2529          {
2530             OldLink t;
2531             for(t = _class.templatized.first; t; t = t.next)
2532             {
2533                Class template = t.data;
2534                template.nameSpace = nameSpace;
2535             }
2536          }
2537
2538          _class.module = module;
2539          _class.base = base;
2540          if(base)
2541          {
2542             int numParams = 0;
2543             Class sClass;
2544             for(sClass = base; sClass; sClass = sClass.base)
2545             {
2546                if(sClass.templateClass) sClass = sClass.templateClass;
2547                numParams += sClass.templateParams.count;
2548             }
2549             if(numParams)
2550             {
2551                if(_class.templateArgs)
2552                {
2553                   FreeTemplateArgs(_class);
2554                }
2555                delete _class.templateArgs;
2556                _class.templateArgs = new0 ClassTemplateArgument[numParams];
2557                _class.numParams = numParams;
2558
2559                for(sClass = _class; sClass; sClass = sClass.base)
2560                {
2561                   Class prevClass;
2562                   ClassTemplateParameter param;
2563                   int id = 0;
2564                   if(sClass.templateClass) sClass = sClass.templateClass;
2565                   for(prevClass = sClass.base; prevClass; prevClass = prevClass.base)
2566                   {
2567                      if(prevClass.templateClass) prevClass = prevClass.templateClass;
2568                      id += prevClass.templateParams.count;
2569                   }
2570
2571                   if(base.templateArgs)   // Add numParams test here?
2572                   {
2573                      for(param = sClass.templateParams.first; param; param = param.next)
2574                      {
2575                         _class.templateArgs[id] = base.templateArgs[id];
2576                         CopyTemplateArg(param, _class.templateArgs[id]);
2577                         id++;
2578                      }
2579                   }
2580                }
2581             }
2582          }
2583          _class.memberID = _class.startMemberID = (base && (type == normalClass || type == noHeadClass || type == structClass)) ? base.memberID : 0;
2584          if(type == normalClass || type == noHeadClass)
2585             _class.offset = (base && base.structSize && base.type != systemClass) ? base.structSize : ((type == noHeadClass) ? 0 : (force64Bits ? 24 : (force32Bits && inCompiler) ? 12 : sizeof(class Instance)));
2586
2587          // For cross-bitness-compiling
2588          if(crossBits)
2589          {
2590             // Ideally, the running library should be aware of the struct size of both 32 and 64 bit, since the compiler has no knowledge whatsoever of private members
2591             if(strstr(name, "ecere::sys::EARHeader") ||
2592                strstr(name, "AnchorValue") ||
2593                !strcmp(name, "ecere::com::CustomAVLTree") ||
2594                !strcmp(name, "ecere::sys::Mutex"));   // Never recompute these, they're always problematic (errors, crashes)
2595             else
2596             {
2597                if(!strcmp(name, "ecere::sys::FileListing"))
2598                {
2599                   size = 3*(force32Bits ? 4 : 8);
2600                   _class.structAlignment = force32Bits ? 4 : 8;   // FileListing is problematic because it is a struct with private data that the user allocates
2601                }
2602                // These we want to recompute inside the IDE to help the debugger
2603                else if(!strcmp(name, "ecere::com::Class"))           size = 0; // 616
2604                else if(!strcmp(name, "ecere::com::ClassProperty"))   size = 0; // 80
2605                else if(!strcmp(name, "ecere::com::NameSpace"))       size = 0; // 176
2606                else if(!strcmp(name, "ecere::sys::BufferedFile"))    size = 0;
2607                else if(!strcmp(name, "ecere::sys::BTNode"))          size = 0;
2608                else if(!strcmp(name, "ecere::sys::StringBTNode"))    size = 0;
2609                else if(!strcmp(name, "ecere::sys::OldList"))         size = 0; // 32
2610                else if(!strcmp(name, "ecere::sys::Item"))            size = 0;
2611                else if(!strcmp(name, "ecere::sys::NamedLink"))       size = 0;
2612                else if(!strcmp(name, "ecere::sys::OldLink"))         size = 0;
2613                else if(!strcmp(name, "ecere::sys::NamedItem"))       size = 0;
2614                else if(!strcmp(name, "ecere::sys::NamedItem64"))     size = 0;
2615                else if(!strcmp(name, "ecere::sys::BinaryTree"))      size = 0;
2616                else if(module != module.application && inCompiler)
2617                {
2618                   // These we only want to recompute inside the compiler
2619                   size = 0;
2620                }
2621             }
2622          }
2623          if(type == structClass)
2624          {
2625             _class.memberOffset = (base && base.structSize && base.type != systemClass) ? base.structSize : 0;
2626             // THIS IS NEW...
2627             _class.typeSize = _class.structSize = _class.memberOffset + size;
2628          }
2629          else if(type == bitClass || type == enumClass || type == unitClass)
2630          {  
2631             Class dataTypeClass = eSystem_FindClass(_class.module, dataTypeString);
2632             if(dataTypeClass)
2633                _class.typeSize = dataTypeClass.typeSize;
2634             _class.structSize = 0;
2635          }
2636          else if(type == normalClass || type == noHeadClass)
2637          {
2638             _class.structSize = _class.offset + size;
2639             _class.typeSize = sizeof(void *);
2640          }
2641          _class.offsetClass = offsetClass;
2642          _class.sizeClass = totalSizeClass;
2643          _class.Constructor = (void *)Constructor;
2644          _class.Destructor = Destructor;
2645          if(_class.type != systemClass)
2646             _class.type = type;
2647          if(!size)
2648             _class.computeSize = true;
2649          else
2650             _class.computeSize = false;
2651          _class.inheritanceAccess = inheritanceAccess;
2652
2653          /*if(type == bitClass)
2654             _class.size = 0;*/
2655          if(type == enumClass)
2656          {
2657             if(enumBase)
2658                _class.base = base = enumBase;
2659             //else
2660             {
2661                EnumClassData data = (EnumClassData)_class.data;
2662                // TOCHECK: Trying this (if specifiers specified, no class found...)
2663                // What about bit classes, unit classes...
2664                if(base && base.type != enumClass)
2665                   data.largest = -1;//_class.base = null;
2666                else
2667                   data.largest = ((EnumClassData)(base.data)).largest;
2668             }
2669          }
2670          if(base && base.vTblSize)
2671          {
2672             _class.vTblSize = base.vTblSize;
2673             // OK to scrap existing virtual table?
2674             delete _class._vTbl;
2675             _class._vTbl = _malloc(sizeof(int(*)()) * _class.vTblSize);
2676             memcpy(_class._vTbl, base._vTbl, sizeof(int(*)()) * _class.vTblSize);
2677          }
2678
2679          if(_class.base)
2680          {
2681             OldLink link { data = _class };
2682             /*(_class.base.templateClass ? _class.base.templateClass : _class.base)*/_class.base.derivatives.Add(link);
2683          }
2684
2685          FixDerivativesBase(_class, _class);
2686          return _class;
2687       }
2688    }
2689    return null;
2690 }
2691
2692 static void DataMember_Free(DataMember parentMember)
2693 {
2694    DataMember member;
2695    BTNamedLink namedLink;
2696    delete parentMember.name;
2697    delete parentMember.dataTypeString;
2698
2699    while((member = parentMember.members.first))
2700    {
2701       DataMember_Free(member);
2702       parentMember.members.Delete(member);
2703    }
2704
2705    while((namedLink = (BTNamedLink)parentMember.membersAlpha.first))
2706    {
2707       parentMember.membersAlpha.Delete((BTNode)namedLink);
2708    }
2709 }
2710
2711 static void FreeEnumValue(NamedLink value)
2712 {
2713    delete value.name;
2714 }
2715
2716 static void FreeTemplateArg(Class template, ClassTemplateParameter param, int id)
2717 {
2718    switch(param.type)
2719    {
2720       case type:
2721          delete template.templateArgs[id].dataTypeString;
2722          break;
2723       case identifier:
2724          delete template.templateArgs[id].memberString;
2725          break;
2726       case expression:
2727          
2728          break;
2729    }
2730 }
2731
2732 static void FreeTemplateArgs(Class template)
2733 {
2734    if(template.templateArgs)
2735    {
2736       Class _class;
2737       for(_class = template; _class; _class = _class.base)
2738       {
2739          Class prevClass;
2740          ClassTemplateParameter param;
2741          int id = 0;
2742          if(_class.templateClass) _class = _class.templateClass;
2743          for(prevClass = _class.base; prevClass; prevClass = prevClass.base) 
2744          {
2745             if(prevClass.templateClass) prevClass = prevClass.templateClass;
2746             id += prevClass.templateParams.count;
2747          }
2748          if(id < template.numParams)
2749          {
2750             for(param = _class.templateParams.first; param; param = param.next)
2751             {
2752                switch(param.type)
2753                {
2754                   case type:
2755                      delete template.templateArgs[id].dataTypeString;
2756                      break;
2757                   case identifier:
2758                      delete template.templateArgs[id].memberString;
2759                      break;
2760                   case expression:
2761                      // delete template.templateArgs[id].dataTypeString;
2762                      break;
2763                }
2764                id++;
2765             }
2766          }
2767       }
2768    }
2769 }
2770
2771 static void FreeTemplate(Class template)
2772 {
2773    OldLink deriv;
2774
2775    if(template.nameSpace)
2776    {
2777       BTNamedLink link = (BTNamedLink)template.nameSpace->classes.FindString(template.name);
2778       template.nameSpace->classes.Delete((BTNode)link);
2779    }
2780    FreeTemplateArgs(template);
2781
2782    delete template.fullName;
2783    delete template.name;
2784    delete template.templateArgs;
2785    delete template.dataTypeString;
2786
2787    while((deriv = template.derivatives.first))
2788    {
2789       ((Class)deriv.data).base = null;
2790       template.derivatives.Delete(deriv);
2791    }
2792
2793    _free(template);
2794 }
2795
2796 static void FreeTemplates(Class _class)
2797 {
2798    OldLink deriv, template;
2799
2800    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
2801    {
2802       FreeTemplates(deriv.data);
2803    }
2804
2805    FreeTemplateArgs(_class);
2806    //if(_class.templateArgs)
2807       //printf("Deleting  Template args for %s\n", _class.name);
2808    delete _class.templateArgs;
2809    delete _class.dataTypeString;
2810
2811    while((template = _class.templatized.first))
2812    {
2813       FreeTemplates(template.data);
2814       FreeTemplate(template.data);
2815       _class.templatized.Delete(template);
2816    }
2817 }
2818
2819 public dllexport void eClass_Unregister(Class _class)
2820 {
2821    BTNamedLink namedLink;
2822    DataMember member;
2823    Method method;
2824    OldLink deriv, template;
2825    ClassProperty classProp;
2826    ClassTemplateParameter param;
2827
2828    delete _class._vTbl;
2829
2830    FreeTemplates(_class);
2831    
2832    FreeTemplateArgs(_class);
2833    delete _class.templateArgs;
2834
2835    while((template = _class.templatized.first))
2836    {
2837       FreeTemplate(template.data);
2838       _class.templatized.Delete(template);
2839    }
2840
2841    while((member = _class.membersAndProperties.first))
2842    {
2843       if(!member.isProperty && (member.type == unionMember || member.type == structMember))
2844          DataMember_Free(member);
2845       delete member.name;
2846       delete member.dataTypeString;
2847       _class.membersAndProperties.Delete(member);
2848    }
2849
2850    while((member = _class.conversions.first))
2851    {
2852       delete member.name;
2853       delete member.dataTypeString;
2854       _class.conversions.Delete(member);
2855    }
2856
2857    while((namedLink = (BTNamedLink)_class.prop.first))
2858    {
2859       _class.prop.Delete((BTNode)namedLink);
2860    }
2861
2862    while((namedLink = (BTNamedLink)_class.members.first))
2863    {
2864       _class.members.Delete((BTNode)namedLink);
2865    }
2866
2867    while((classProp = (ClassProperty)_class.classProperties.first))
2868    {
2869       delete classProp.name;
2870       delete classProp.dataTypeString;
2871       _class.classProperties.Delete((BTNode)classProp);
2872    }
2873
2874    while((method = (Method)_class.methods.first))
2875    {
2876       delete method.name;
2877       delete method.dataTypeString;
2878       _class.methods.Delete((BTNode)method);
2879    }
2880
2881    if(_class.type == enumClass)
2882    {
2883       EnumClassData data = (EnumClassData)_class.data;
2884
2885       data.values.Free((void *)FreeEnumValue);
2886    }
2887    _class.delayedCPValues.Free(null);
2888
2889    _class.selfWatchers.Free(null);
2890    
2891    if(_class.base)
2892    {
2893       // Class base = _class.base.templateClass ? _class.base.templateClass : _class.base;
2894       Class base = _class.base;
2895       for(deriv = base.derivatives.first; deriv; deriv = deriv.next)
2896       {
2897          if(deriv.data == _class)
2898             break;
2899       }
2900       if(deriv)
2901          base.derivatives.Delete(deriv);
2902    }
2903    while((deriv = _class.derivatives.first))
2904    {
2905       ((Class)deriv.data).base = null;
2906       _class.derivatives.Delete(deriv);
2907    }
2908
2909    if(_class.nameSpace)
2910    {
2911       BTNamedLink link = (BTNamedLink)_class.nameSpace->classes.FindString(_class.name);
2912       _class.nameSpace->classes.Delete((BTNode)link);
2913    }
2914
2915    delete _class.name;
2916    delete _class.fullName;
2917    
2918    delete _class.dataTypeString;
2919
2920    delete _class.data;
2921
2922    while((param = _class.templateParams.first))
2923    {
2924       switch(param.type)
2925       {
2926          case type:
2927             delete param.defaultArg.dataTypeString;
2928             break;
2929          case identifier:
2930             delete param.defaultArg.memberString;
2931             break;
2932          case expression:
2933             
2934             break;
2935       }
2936       if(param.type != identifier) delete param.dataTypeString;
2937       delete param.name;
2938
2939       _class.templateParams.Delete(param);
2940    }
2941
2942    //_class.nameSpace->classes.Delete(_class);
2943    _free(_class);
2944 }
2945
2946 static BTNamedLink ScanNameSpace(NameSpace nameSpace, char * name, void * listOffset)
2947 {
2948    BinaryTree * tree = (BinaryTree *)((byte *)nameSpace + (uint)listOffset);
2949    BTNamedLink link = (BTNamedLink)tree->Find((uintptr)name);
2950    NameSpace * child;
2951    if(!link)
2952    {
2953       for(child = (NameSpace *)nameSpace.nameSpaces.first; child; child = (NameSpace *)((BTNode)child).next)
2954       {
2955          link = ScanNameSpace(child, name, listOffset);
2956          if(link)
2957             break;
2958       }
2959    }
2960    return link;
2961 }
2962
2963 static BTNamedLink SearchNameSpace(NameSpace nameSpace, char * name, void * listOffset)
2964 {
2965    int start = 0, c;
2966    char ch;
2967    int level = 0;
2968    for(c = 0; (ch = name[c]); c++)
2969    {
2970       if(ch == '<') level++;
2971       if(ch == '>') level--;
2972       if(level == 0 && (ch == '.' || (ch == ':' && name[c+1] == ':')))
2973       {
2974          NameSpace * newSpace;
2975          char * spaceName = _malloc(c - start + 1);
2976          memcpy(spaceName, name + start, c - start);
2977          spaceName[c-start] = '\0';
2978          newSpace = (NameSpace *)nameSpace.nameSpaces.FindString(spaceName);
2979          _free(spaceName);
2980          if(!newSpace)
2981             return null;
2982          nameSpace = newSpace;
2983          if(level == 0 && ch == ':') c++;
2984          start = c+1;
2985       }
2986    }
2987    if(c - start)
2988    {
2989       return ScanNameSpace(nameSpace, name + start, listOffset);
2990    }
2991    return null;
2992 }
2993
2994 static BTNamedLink SearchModule(Module module, char * name, void * listOffset, bool searchPrivate)
2995 {
2996    SubModule subModule;
2997    BTNamedLink link;
2998
2999    if(searchPrivate)
3000    {
3001       link = SearchNameSpace(&module.privateNameSpace, name, listOffset);
3002       if(link) return link;
3003    }
3004    link = SearchNameSpace(&module.publicNameSpace, name, listOffset);
3005    if(link) return link;
3006
3007    for(subModule = module.modules.first; subModule; subModule = subModule.next)
3008    {
3009       if(searchPrivate || subModule.importMode == publicAccess)
3010       {
3011          // TOCHECK: Reverting to false to test what we were trying to fix by passing searchPrivate
3012          // Passing searchPrivate finds ALL classes private or not and thus classes clash
3013          // SearchModule here is called mainly from eSystem_FindClass, and also for Functions and Defines
3014
3015          link = SearchModule(subModule.module, name, listOffset, false);
3016          //link = SearchModule(subModule.module, name, listOffset, searchPrivate /*false*/);
3017          if(link) return link;
3018       }
3019    }
3020    return null;
3021 }
3022
3023 public int64 _strtoi64(char * string, char ** endString, int base)
3024 {
3025    int64 value = 0;
3026    int sign = 1;
3027    int c;
3028    char ch;
3029    for(c = 0; (ch = string[c]) && isspace(ch); c++);
3030    if(ch =='+') c++;
3031    else if(ch == '-') { sign = -1; c++; };
3032    if(!base)
3033    {
3034       if(ch == '0' && string[c+1] == 'x')
3035       {
3036          base = 16;
3037          c+=2;
3038       }
3039       else if(ch == '0')
3040       {
3041          base = 8;
3042          c++;
3043       }
3044       else
3045          base = 10;
3046    }
3047    for( ;(ch = string[c]); c++)
3048    {
3049       if(ch >= '0' && ch <= '9')
3050          ch -= '0';
3051       else if(ch >= 'a' && ch <= 'z') 
3052          ch -= ('a' - 10); 
3053       else if(ch >= 'A' && ch <= 'Z') 
3054          ch -= ('A'- 10);
3055       else
3056       {
3057          if(endString)
3058             *endString = string + c;
3059          // Invalid character
3060          break;
3061       }
3062       if(ch < base)
3063       {
3064          value *= base;
3065          value += ch;
3066       }
3067       else
3068       {
3069          if(endString)
3070             *endString = string + c;
3071          // Invalid character
3072          break;
3073       }
3074    }
3075    return sign*value;
3076 }
3077
3078 public uint64 _strtoui64(char * string, char ** endString, int base)
3079 {
3080    uint64 value = 0;
3081    int sign = 1;
3082    int c;
3083    char ch;
3084    for(c = 0; (ch = string[c]) && isspace(ch); c++);
3085    if(ch =='+') c++;
3086    else if(ch == '-') { sign = -1; c++; };
3087    if(!base)
3088    {
3089       if(ch == '0' && string[c+1] == 'x')
3090       {
3091          base = 16;
3092          c+=2;
3093       }
3094       else if(ch == '0')
3095       {
3096          base = 8;
3097          c++;
3098       }
3099       else
3100          base = 10;
3101    }
3102    for( ;(ch = string[c]); c++)
3103    {
3104       if(ch >= '0' && ch <= '9')
3105          ch -= '0';
3106       else if(ch >= 'a' && ch <= 'z') 
3107          ch -= ('a' - 10); 
3108       else if(ch >= 'A' && ch <= 'Z') 
3109          ch -= ('A' - 10);
3110       else
3111       {
3112          if(endString)
3113             *endString = string + c;
3114          // Invalid character
3115          break;
3116       }
3117       if(ch < base)
3118       {
3119          value *= base;
3120          value += ch;
3121       }
3122       else
3123       {
3124          if(endString)
3125             *endString = string + c;
3126          // Invalid character
3127          break;
3128       }
3129    }
3130    return sign*value;
3131 }
3132
3133 public dllexport Class eSystem_FindClass(Module module, char * name)
3134 {
3135    if(name && module)
3136    {
3137       BTNamedLink link;
3138       link = SearchNameSpace(&module.application.systemNameSpace, name, &((NameSpace *)0)->classes);
3139       if(link) return link.data;
3140
3141       link = SearchModule(module, name, &((NameSpace *)0)->classes, true);
3142       if(link) return link.data;
3143       
3144       {
3145          char noTemplateName[1024];
3146          char * templateParams = strchr(name, '<');
3147
3148          if(templateParams)
3149          {
3150             strncpy(noTemplateName, name, templateParams - name);
3151             noTemplateName[templateParams - name] = '\0';
3152          }
3153          else
3154             strcpy(noTemplateName, name);
3155
3156          link = SearchNameSpace(&module.application.systemNameSpace, noTemplateName, &((NameSpace *)0)->classes);
3157          if(!link)
3158             link = SearchModule(module, noTemplateName, &((NameSpace *)0)->classes, true);
3159          if(link)
3160          {
3161             Class _class = link.data;
3162             Class templatedClass = null;
3163             char className[1024];
3164             strcpy(className, _class.fullName);
3165             strcat(className, templateParams);
3166
3167             link = SearchNameSpace(&module.application.systemNameSpace, className, &((NameSpace *)0)->classes);
3168             if(link)
3169                return link.data;
3170
3171             link = SearchModule(module, className, &((NameSpace *)0)->classes, true);
3172             if(link)
3173                return link.data;
3174
3175             if(_class && templateParams)
3176             {
3177                // if(!numParams) return null;
3178
3179                templatedClass = Class { };
3180                *templatedClass = *_class;
3181                templatedClass.templateClass = _class;
3182                //templatedClass.fullName = CopyString(name);
3183                templatedClass.fullName = CopyString(className);
3184                templatedClass.dataTypeString = CopyString(_class.dataTypeString);
3185                templatedClass.name = CopyString(templatedClass.fullName + strlen(_class.fullName) - strlen(_class.name));
3186                templatedClass.nameSpace->classes.Add((BTNode)BTNamedLink { name = templatedClass.name, data = templatedClass });
3187                templatedClass.templateArgs = null;
3188                templatedClass.numParams = 0;
3189                templatedClass.derivatives = { };
3190                templatedClass.templatized = { };
3191
3192                ComputeClassParameters(templatedClass, templateParams, module);
3193
3194                _class.templatized.Add(OldLink { data = templatedClass });
3195             }
3196             return templatedClass;
3197          }
3198       }
3199    }
3200    return null;
3201 }
3202
3203 static void CopyTemplateArg(ClassTemplateParameter param, ClassTemplateArgument arg)
3204 {
3205    switch(param.type)
3206    {
3207       case type:
3208          arg.dataTypeString = CopyString(arg.dataTypeString);
3209          break;
3210       case expression:
3211          
3212          break;
3213       case identifier:
3214          arg.memberString = CopyString(arg.memberString);
3215          break;
3216    }
3217 }
3218
3219 static void ComputeClassParameters(Class templatedClass, char * templateParams, Module findModule)
3220 {
3221    char ch;
3222    char * nextParamStart = templateParams ? (templateParams + 1) : null;
3223    ClassTemplateParameter curParam = null;
3224    Class lastClass = null, sClass;
3225    int curParamID = 0;
3226    int numParams = 0;
3227    Class _class = templatedClass.templateClass ? templatedClass.templateClass : templatedClass;
3228
3229    for(sClass = _class; sClass; sClass = sClass.base)
3230    {
3231       if(sClass.templateClass) sClass = sClass.templateClass;
3232       numParams += sClass.templateParams.count;
3233    }
3234    
3235    if(templatedClass.templateArgs)
3236       FreeTemplateArgs(templatedClass);
3237    delete templatedClass.templateArgs;
3238    templatedClass.templateArgs = new0 ClassTemplateArgument[numParams];
3239    templatedClass.numParams = numParams;
3240
3241    if(_class != templatedClass)
3242    {
3243       /*int c;
3244       Class sClass;
3245       memcpy(templatedClass.templateArgs, _class.templateArgs, numParams * sizeof(ClassTemplateArgument));
3246       for(sClass = _class; sClass; sClass = sClass.base)
3247       {
3248          ClassTemplateParameter param;
3249          Class prevClass;
3250          int id = 0;
3251          if(sClass.templateClass) sClass = sClass.templateClass;
3252          for(prevClass = sClass.base; prevClass; prevClass = prevClass.base)
3253          {
3254             if(prevClass.templateClass) prevClass = prevClass.templateClass;
3255             id += prevClass.templateParams.count;
3256          }
3257          for(param = sClass.templateParams.first; param; param = param.next)
3258            CopyTemplateArg(param, templatedClass.templateArgs[id++]);
3259       }*/
3260    }
3261    
3262    if(templatedClass.base && templatedClass.base.templateArgs && _class == templatedClass)
3263    {
3264       Class sClass;
3265       memcpy(templatedClass.templateArgs, templatedClass.base.templateArgs, 
3266          sizeof(ClassTemplateArgument) * (numParams - templatedClass.templateParams.count));
3267       for(sClass = templatedClass.base; sClass; sClass = sClass.base)
3268       {
3269          ClassTemplateParameter param;
3270          Class prevClass;
3271          int id = 0;
3272          for(prevClass = sClass.base; prevClass; prevClass = prevClass.base)
3273          {
3274             if(prevClass.templateClass) prevClass = prevClass.templateClass;
3275             id += prevClass.templateParams.count;
3276          }
3277
3278          if(sClass.templateClass) sClass = sClass.templateClass;
3279          for(param = sClass.templateParams.first; param; param = param.next)
3280             CopyTemplateArg(param, templatedClass.templateArgs[id++]);
3281       }
3282    }
3283    
3284    while(nextParamStart)
3285    {
3286       char * paramStart = nextParamStart;
3287       char * paramEnd;
3288       int level = 0;
3289       while(*paramStart == ' ') paramStart++;
3290       paramEnd = paramStart;
3291       while((ch = *paramEnd, ch && (level > 0 || (ch != '>' && ch != ',')))) 
3292       {
3293          if(ch == '<') level++;
3294          if(ch == '>') level--;
3295
3296          paramEnd++;
3297       }
3298       nextParamStart = (ch == ',') ? (paramEnd + 1) : null;
3299       while(*paramEnd == ' ') paramEnd--;
3300       if(paramEnd > paramStart)
3301       {
3302          char * ptr, * equal = null;
3303          for(ptr = paramStart; ptr <= paramEnd; ptr++)
3304          {
3305             if(*ptr == '=')
3306             {
3307                equal = ptr;
3308                break;
3309             }
3310          }
3311          if(equal)
3312          {
3313             char * end = equal - 1;
3314             char ident[1024];
3315             
3316             while(*end == ' ') end--;
3317             strncpy(ident, paramStart, end + 1 - paramStart);
3318             ident[end + 1 - paramStart] = 0;
3319             
3320             for(sClass = _class; sClass; sClass = sClass.base)
3321             {
3322                if(sClass.templateClass) sClass = sClass.templateClass;
3323                for(curParam = sClass.templateParams.first; curParam; curParam = curParam.next)
3324                {
3325                   if(!strcmp(curParam.name, ident))
3326                      break;
3327                }
3328                if(curParam)
3329                {
3330                   Class nextClass;
3331                   ClassTemplateParameter prevParam;
3332                   curParamID = 0;
3333                   for(prevParam = curParam.prev; prevParam; prevParam = prevParam.prev) curParamID++;
3334                   for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3335                   {
3336                      if(nextClass.templateClass) nextClass = nextClass.templateClass;
3337                      curParamID += nextClass.templateParams.count;
3338                   }
3339                   break;
3340                }
3341             }
3342             lastClass = sClass;
3343          }
3344          else
3345          {
3346             if(curParam)
3347             {
3348                curParam = curParam.next;
3349                curParamID++;
3350             }
3351
3352             if(!curParam)
3353             {
3354                for(sClass = lastClass ? lastClass.base : _class; sClass; sClass = sClass.base)
3355                {
3356                   ClassTemplateParameter param;
3357                   curParamID = 0;
3358                   if(sClass.templateClass) sClass = sClass.templateClass;
3359                   for(param = sClass.templateParams.first; param; param = param.next, curParamID++)
3360                   {
3361                      curParam = param;
3362                      break;
3363                   }
3364                   if(curParam) 
3365                   {
3366                      Class nextClass;
3367                      for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3368                      {
3369                         if(nextClass.templateClass) nextClass = nextClass.templateClass;
3370                         curParamID += nextClass.templateParams.count;
3371                      }
3372                      lastClass = sClass;
3373                      break;
3374                   }
3375                }
3376                /*
3377                for(sClass = _class; sClass; sClass = sClass.base)
3378                {
3379                   if(sClass.templateParams.first)
3380                   {
3381                      Class nextClass;
3382                      for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3383                         if(nextClass.templateParams.first)
3384                            break;
3385                      if(nextClass != lastClass) continue;
3386
3387                      curParam = sClass.templateParams.first;
3388                      lastClass = sClass;
3389
3390                      for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3391                         if(nextClass.templateParams.first)
3392                         {
3393                            curParamID += nextClass.templateParams.count;
3394                            break;
3395                         } 
3396                      break;
3397                   }
3398                }
3399                */
3400             }
3401          }
3402
3403          if(curParam)
3404          {
3405             ClassTemplateArgument argument { };
3406             char value[1024];
3407             if(equal) 
3408             {
3409                equal++;
3410                while(*equal == ' ') equal++;
3411                memcpy(value, equal, paramEnd - equal);
3412                value[paramEnd - equal] = 0;
3413             }
3414             else
3415             {
3416                memcpy(value, paramStart, paramEnd - paramStart);
3417                value[paramEnd - paramStart] = 0;
3418             }
3419             TrimRSpaces(value, value);
3420
3421             switch(curParam.type)
3422             {
3423                case type:
3424                   argument.dataTypeString = CopyString(value);
3425                   argument.dataTypeClass = eSystem_FindClass(_class.module, value);
3426                   if(!argument.dataTypeClass) argument.dataTypeClass = eSystem_FindClass(_class.module.application, value);
3427                   if(!argument.dataTypeClass) argument.dataTypeClass = eSystem_FindClass(findModule, value);
3428                   break;
3429                case expression:
3430                {
3431                   Class expClass = eSystem_FindClass(_class.module, curParam.dataTypeString);
3432                   if(!expClass) expClass = eSystem_FindClass(_class.module.application, curParam.dataTypeString);
3433                   if(expClass)
3434                   {
3435                      //if(expClass.type == 
3436                      ((bool (*)(void *, void *, const char *))(void *)expClass._vTbl[__ecereVMethodID_class_OnGetDataFromString])(expClass, &argument.expression, value);
3437                   }
3438                   // Expression should be pre simplified here
3439                   else if(value[0] == '\"')
3440                   {
3441                      char * endQuote = value + strlen(value) - 1;
3442                      if(*endQuote != '\"') endQuote++;
3443                      *endQuote = '\0';
3444                      argument.expression.p = CopyString(value + 1);
3445                   }
3446                   else if(value[0] == '\'')
3447                   {
3448                      int nb;
3449                      unichar ch = UTF8GetChar(value + 1, &nb);
3450                      argument.expression.ui = ch;
3451                   }
3452                   else if(!strcmp(curParam.dataTypeString, "uint"))
3453                   {
3454                      argument.expression.ui = strtoul(value, null, 0);
3455                   }
3456                   else if(!strcmp(curParam.dataTypeString, "char"))
3457                   {
3458                      argument.expression.c = (char)strtol(value, null, 0);
3459                   }
3460                   else if(!strcmp(curParam.dataTypeString, "byte"))
3461                   {
3462                      argument.expression.uc = (unsigned char)strtoul(value, null, 0);
3463                   }
3464                   else if(!strcmp(curParam.dataTypeString, "short"))
3465                   {
3466                      argument.expression.s = (short)strtol(value, null, 0);
3467                   }
3468                   else if(!strcmp(curParam.dataTypeString, "uint16"))
3469                   {
3470                      argument.expression.us = (unsigned short)strtoul(value, null, 0);
3471                   }
3472                   else if(!strcmp(curParam.dataTypeString, "int64"))
3473                   {
3474                      argument.expression.i64 = _strtoi64(value, null, 0);
3475                   }
3476                   else if(!strcmp(curParam.dataTypeString, "uint64"))
3477                   {
3478                      argument.expression.ui64 = _strtoui64(value, null, 0);
3479                   }
3480                   else if(!strcmp(curParam.dataTypeString, "float"))
3481                   {
3482                      argument.expression.f = (float)strtod(value, null);
3483                   }
3484                   else if(!strcmp(curParam.dataTypeString, "double"))
3485                   {
3486                      argument.expression.d = strtod(value, null);
3487                   }
3488                   else // if(!strcmp(curParam.dataTypeString, "int"))
3489                   {
3490                      argument.expression.i = strtol(value, null, 0);
3491                   }
3492                   break;
3493                } 
3494                case identifier:
3495                   argument.memberString = CopyString(value);
3496                   break;
3497             }
3498             FreeTemplateArg(templatedClass, curParam, curParamID);
3499             templatedClass.templateArgs[curParamID] = argument;
3500          }
3501       }
3502    }
3503
3504    // TESTING THIS BEFORE...
3505    if(templatedClass == _class)
3506    {
3507       Class sClass = _class;
3508       int curParamID = 0;
3509       Class nextClass;
3510       ClassTemplateParameter param;
3511       for(nextClass = sClass.base; nextClass; nextClass = nextClass.base)
3512       {
3513          if(nextClass.templateClass) nextClass = nextClass.templateClass;
3514          curParamID += nextClass.templateParams.count;
3515       }
3516
3517       for(param = sClass.templateParams.first; param; param = param.next)
3518       {
3519          if(!templatedClass.templateArgs[curParamID].dataTypeString)
3520          {
3521             templatedClass.templateArgs[curParamID] = param.defaultArg;
3522             CopyTemplateArg(param, templatedClass.templateArgs[curParamID]);
3523             if(param.type == type && param.defaultArg.dataTypeString)
3524             {
3525                templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(templatedClass.module, param.defaultArg.dataTypeString);
3526                if(!templatedClass.templateArgs[curParamID].dataTypeClass) 
3527                   templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(templatedClass.module.application, param.defaultArg.dataTypeString);
3528                if(!templatedClass.templateArgs[curParamID].dataTypeClass) 
3529                   templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(findModule, param.defaultArg.dataTypeString);
3530             }
3531          }
3532          curParamID++;
3533       }
3534    }
3535
3536    if(templatedClass.base && templatedClass.base.templateArgs && numParams - _class.templateParams.count)
3537    {
3538       int c = numParams - _class.templateParams.count-1;
3539
3540       for(sClass = _class.base; sClass; sClass = sClass.base)
3541       {
3542          ClassTemplateParameter param;
3543          if(sClass.templateClass) sClass = sClass.templateClass;
3544          for(param = sClass.templateParams.last; param; param = param.prev)
3545          {
3546             ClassTemplateArgument * arg = &templatedClass.templateArgs[c];
3547             ClassTemplateArgument * baseArg = &templatedClass.base.templateArgs[c];
3548             if(!arg->dataTypeString)
3549             {
3550                *arg = templatedClass.base.templateArgs[c];
3551                CopyTemplateArg(param, arg);
3552                if(param.type == type)
3553                {
3554                   if(arg->dataTypeClass && strchr(arg->dataTypeString, '<') && arg->dataTypeClass.templateArgs)
3555                   {
3556                      Class expClass = arg->dataTypeClass;
3557                      Class cClass = null;
3558                      int paramCount = 0;
3559                      int lastParam = -1;
3560                      
3561                      char templateString[1024];
3562                      sprintf(templateString, "%s<", expClass.templateClass.fullName);
3563                      for(cClass = expClass; cClass; cClass = cClass.base)
3564                      {
3565                         int p = 0;
3566                         ClassTemplateParameter param;
3567                         for(param = cClass.templateParams.first; param; param = param.next)
3568                         {
3569                            int id = p;
3570                            Class sClass;
3571                            ClassTemplateArgument arg;
3572                            for(sClass = expClass.base; sClass; sClass = sClass.base) id += sClass.templateParams.count;
3573                            arg = expClass.templateArgs[id];
3574
3575                            {
3576                               ClassTemplateParameter cParam;
3577                               int p = numParams - _class.templateParams.count;
3578                               for(cParam = _class.templateParams.first; cParam; cParam = cParam.next, p++)
3579                               {
3580                                  if(cParam.type == type && arg.dataTypeString && !strcmp(cParam.name, arg.dataTypeString))
3581                                  {
3582                                     arg.dataTypeString = templatedClass.templateArgs[p].dataTypeString;
3583                                     arg.dataTypeClass = templatedClass.templateArgs[p].dataTypeClass;
3584                                     break;
3585                                  }
3586                               }
3587                            }
3588
3589                            {
3590                               char argument[256];
3591                               argument[0] = '\0';
3592                               switch(param.type)
3593                               {
3594                                  case expression:
3595                                  {
3596                                     // THIS WHOLE THING IS A WILD GUESS... FIX IT UP
3597                                     /*
3598                                     char expString[1024];
3599                                     OldList * specs = MkList();
3600                                     Declarator decl = SpecDeclFromString(param.dataTypeString, specs, null);
3601                                     Expression exp;
3602                                     char * string = PrintHexUInt64(arg.expression.ui64);
3603                                     exp = MkExpCast(MkTypeName(specs, decl), MkExpConstant(string));
3604
3605                                     ProcessExpressionType(exp);
3606                                     ComputeExpression(exp);
3607                                     expString[0] = '\0';
3608                                     PrintExpression(exp, expString);
3609                                     strcat(argument, expString);
3610                                     //delete exp;
3611                                     FreeExpression(exp);
3612                                     */
3613                                     break;
3614                                  }
3615                                  case identifier:
3616                                  {
3617                                     strcat(argument, arg.member.name);
3618                                     break;
3619                                  }
3620                                  case TemplateParameterType::type:
3621                                  {
3622                                     if(arg.dataTypeString)
3623                                        strcat(argument, arg.dataTypeString);
3624                                     break;
3625                                  }
3626                               }
3627                               if(argument[0])
3628                               {
3629                                  if(paramCount) strcat(templateString, ", ");
3630                                  if(lastParam != p - 1)
3631                                  {
3632                                     strcat(templateString, param.name);
3633                                     strcat(templateString, " = ");
3634                                  }
3635                                  strcat(templateString, argument);
3636                                  paramCount++;
3637                                  lastParam = p;
3638                               }
3639                            }
3640                            p++;
3641                         }
3642                      }
3643                      {
3644                         int len = strlen(templateString);
3645                         if(templateString[len-1] == '>') templateString[len++] = ' ';
3646                         templateString[len++] = '>';
3647                         templateString[len++] = '\0';
3648                      }
3649
3650                      FreeTemplateArg(templatedClass, param, c);
3651
3652                      arg->dataTypeString = CopyString(templateString);
3653                      arg->dataTypeClass = eSystem_FindClass(templatedClass.module, templateString);
3654                      if(!arg->dataTypeClass)
3655                         arg->dataTypeClass = eSystem_FindClass(templatedClass.module.application, templateString);
3656                   }
3657                   else
3658                   {
3659                      ClassTemplateParameter cParam;
3660                      int p = numParams - _class.templateParams.count;
3661                      for(cParam = _class.templateParams.first; cParam; cParam = cParam.next, p++)
3662                      {
3663                         // if(cParam.type == type && !strcmp(cParam.name, param.name))
3664                         if(cParam.type == type && baseArg->dataTypeString && !strcmp(cParam.name, baseArg->dataTypeString))
3665                         {
3666                            FreeTemplateArg(templatedClass, param, c);
3667
3668                            arg->dataTypeString = templatedClass.templateArgs[p].dataTypeString;
3669                            arg->dataTypeClass = templatedClass.templateArgs[p].dataTypeClass;
3670                            CopyTemplateArg(cParam, arg);
3671                            break;
3672                         }
3673                      }
3674                   }
3675                }
3676             }
3677             c--;                        
3678          }
3679       }
3680    }
3681
3682    {
3683       Class sClass;
3684       for(sClass = _class; sClass; sClass = sClass.base)
3685       {
3686          int curParamID = 0;
3687          Class nextClass;
3688          ClassTemplateParameter param;
3689          if(sClass.templateClass) sClass = sClass.templateClass;
3690          
3691          for(nextClass = sClass.base; nextClass; nextClass = nextClass.base) 
3692          {
3693             if(nextClass.templateClass) nextClass = nextClass.templateClass;
3694             curParamID += nextClass.templateParams.count;
3695          }
3696
3697          for(param = sClass.templateParams.first; param; param = param.next)
3698          {
3699             if(!templatedClass.templateArgs[curParamID].dataTypeString)
3700             {
3701                templatedClass.templateArgs[curParamID] = param.defaultArg;
3702                CopyTemplateArg(param, templatedClass.templateArgs[curParamID]);
3703                if(param.type == type && param.defaultArg.dataTypeString)
3704                {
3705                   templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(templatedClass.module, param.defaultArg.dataTypeString);
3706                   if(!templatedClass.templateArgs[curParamID].dataTypeClass)
3707                      templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(templatedClass.module.application, param.defaultArg.dataTypeString);
3708                   if(!templatedClass.templateArgs[curParamID].dataTypeClass)
3709                      templatedClass.templateArgs[curParamID].dataTypeClass = eSystem_FindClass(findModule, param.defaultArg.dataTypeString);
3710                }
3711             }
3712             curParamID++;
3713          }
3714       }
3715    }
3716
3717    {
3718       int c = numParams - 1;
3719       for(sClass = _class; sClass; sClass = sClass.base)
3720       {
3721          ClassTemplateParameter param;
3722          if(sClass.templateClass) sClass = sClass.templateClass;
3723          for(param = sClass.templateParams.last; param; param = param.prev)
3724          {
3725             if(param.type == type)
3726             {
3727                ClassTemplateArgument * arg = &templatedClass.templateArgs[c];
3728                ClassTemplateParameter cParam;
3729                Class dClass;
3730                int p = numParams - 1;
3731                for(dClass = _class; dClass; dClass = dClass.base)
3732                {                              
3733                   if(dClass.templateClass) dClass = dClass.templateClass;
3734                   for(cParam = dClass.templateParams.last; cParam; cParam = cParam.prev, p--)
3735                   {
3736                      if(cParam.type == type && arg->dataTypeString && !strcmp(cParam.name, arg->dataTypeString))
3737                      {
3738                         if(templatedClass.templateArgs[p].dataTypeString && c != p)
3739                         {
3740                            FreeTemplateArg(templatedClass, param, c);
3741
3742                            arg->dataTypeString = templatedClass.templateArgs[p].dataTypeString;
3743                            arg->dataTypeClass = templatedClass.templateArgs[p].dataTypeClass;
3744                            CopyTemplateArg(cParam, arg);
3745                         }
3746                      }
3747                   }
3748                }
3749             }
3750             c--;
3751          }
3752       }
3753    }
3754
3755    {
3756       Class tClass;
3757       int c = numParams - 1;
3758       for(tClass = _class; tClass; tClass = tClass.base)
3759       {
3760          ClassTemplateParameter param;
3761          if(tClass.templateClass) tClass = tClass.templateClass;
3762          for(param = tClass.templateParams.last; param; param = param.prev)
3763          {
3764             ClassTemplateArgument * arg = &templatedClass.templateArgs[c];
3765             if(param.type == identifier && arg->memberString)
3766             {
3767                Class memberClass = templatedClass;
3768                char * memberString = arg->memberString;
3769                char * colon = strstr(memberString, "::");
3770                char * memberName = memberString;
3771                if(colon) memberName = colon + 2;
3772                if(!colon)
3773                {
3774                   memberString = param.defaultArg.memberString;
3775                   colon = memberString ? strstr(memberString, "::") : null;
3776                }
3777
3778                if(colon)
3779                {
3780                   char className[1024];
3781                   Class sClass;
3782
3783                   memcpy(className, memberString, colon - memberString);
3784                   className[colon - memberString] = '\0';
3785                   
3786                   for(sClass = _class; sClass; sClass = sClass.base)
3787                   {
3788                      ClassTemplateParameter cParam;
3789                      Class nextClass;
3790                      int id = 0;
3791
3792                      if(sClass.templateClass) sClass = sClass.templateClass;
3793                      for(nextClass = sClass.base; nextClass; nextClass = nextClass.base) 
3794                      {
3795                         if(nextClass.templateClass) nextClass = nextClass.templateClass;
3796                         id += nextClass.templateParams.count;
3797                      }
3798                      for(cParam = sClass.templateParams.first; cParam; cParam = cParam.next)
3799                      {
3800                         if(cParam.type == type && !strcmp(cParam.name, className) && templatedClass.templateArgs[id].dataTypeString)
3801                         {
3802                            strcpy(className, templatedClass.templateArgs[id].dataTypeString);
3803                         }
3804                         id++;
3805                      }                  
3806                   }
3807                   memberClass = eSystem_FindClass(templatedClass.module, className);
3808                   // TESTING: Added this here...
3809                   if(!memberClass)
3810                      memberClass = eSystem_FindClass(findModule, className);
3811                   if(!memberClass)
3812                      memberClass = eSystem_FindClass(templatedClass.module.application, className);
3813                }
3814
3815                if(memberClass)
3816                {
3817                   switch(param.memberType)
3818                   {
3819                      case dataMember:
3820                         arg->member = eClass_FindDataMember(memberClass, memberName, memberClass.module, null, null);
3821                         break;
3822                      case method:
3823                         arg->method = eClass_FindMethod(memberClass, memberName, memberClass.module);
3824                         break;
3825                      case prop:
3826                         arg->prop = eClass_FindProperty(memberClass, memberName, memberClass.module);
3827                         break;
3828                   }
3829                }
3830             }
3831             c--;
3832          }
3833       }
3834    }
3835 }
3836
3837 /*static */bool DefaultFunction()
3838 {
3839    return true;
3840 }
3841
3842 public dllexport bool eClass_IsDerived(Class _class, Class from)
3843 {
3844    if(!_class && !from)
3845       return true;
3846
3847    if(_class && from && (_class.templateClass || from.templateClass))
3848    {
3849       if(eClass_IsDerived(_class.templateClass ? _class.templateClass : _class, from.templateClass ? from.templateClass : from))
3850       {
3851          if(!from.templateClass)
3852             return true;
3853          else if(!_class.templateClass && _class == from.templateClass)
3854             return false;
3855          else
3856          {
3857             Class sClass;
3858             for(sClass = from; sClass; sClass = sClass.base)
3859             {
3860                if(sClass.templateParams.first)
3861                {
3862                   ClassTemplateParameter param;
3863                   Class nextClass;
3864                   int p = 0;
3865                   for(nextClass = sClass.base; nextClass; nextClass = nextClass.base) p += nextClass.templateParams.count;               
3866                   for(param = sClass.templateParams.first; param; param = param.next, p++)
3867                   {
3868                      ClassTemplateArgument * arg = &_class.templateArgs[p];
3869                      ClassTemplateArgument * fArg = &from.templateArgs[p];
3870                      if(param.type == type)
3871                      {
3872                         if(arg->dataTypeString != fArg->dataTypeString && arg->dataTypeString && fArg->dataTypeString &&
3873                           strcmp(arg->dataTypeString, fArg->dataTypeString))
3874                            break;
3875                      }
3876                      else if(param.type == identifier)
3877                      {
3878                         if(arg->member != fArg->member)
3879                            break;
3880                      }
3881                      else if(param.type == expression)
3882                      {
3883                         if(arg->expression.ui64 != fArg->expression.ui64)
3884                            break;
3885                      }
3886                   }
3887                   if(param)
3888                      return false;
3889                }
3890             }
3891             return true;
3892          }
3893       }
3894    }
3895    else
3896    {
3897       for(; _class && from; _class = _class.base)
3898       {
3899          if(_class == from || _class.templateClass == from || (_class.type == systemClass && from.name && !strcmp(_class.name, from.name)))
3900             return true;
3901       }
3902    }
3903    return false;
3904 }
3905
3906 static void FixDerivativeVirtualMethod(Class base, char * name, int vid, void * origFunction, char * type)
3907 {
3908    OldLink derivative;
3909    for(derivative = base.derivatives.first; derivative; derivative = derivative.next)
3910    {
3911       Class _class = derivative.data;
3912       Method method, next;
3913       void * function = origFunction;
3914
3915       _class.vTblSize++;
3916       _class._vTbl = renew _class._vTbl void *[_class.vTblSize];
3917       memmove(_class._vTbl + vid + 1, _class._vTbl + vid, (_class.vTblSize - vid - 1) * sizeof(void *));
3918
3919       method = (Method) _class.methods.FindString(name);
3920       if(method)
3921       {
3922          if(method.function) function = method.function;
3923
3924          if(!method.symbol)
3925          {
3926             delete method.name;
3927             delete method.dataTypeString;
3928             _class.methods.Delete((BTNode)method);
3929          }
3930          else
3931          {
3932             delete method.dataTypeString;
3933             method.type = virtualMethod;
3934             method.dataTypeString = CopyString(type);
3935             method._class = base;
3936          }
3937       }
3938       for(method = (Method)_class.methods.first; method; method = next)
3939       {
3940          next = (Method)((BTNode)method).next;
3941          if(method.type == virtualMethod)
3942             method.vid++;
3943       }
3944       _class._vTbl[vid] = function;
3945
3946       {
3947          OldLink templateLink;
3948          for(templateLink = _class.templatized.first; templateLink; templateLink = templateLink.next)
3949          {
3950             Class template = templateLink.data;
3951             template._vTbl = _class._vTbl;
3952          }
3953       }
3954       if(_class.derivatives.first || _class.templatized.first)
3955          FixDerivativeVirtualMethod(_class, name, vid, function, type);
3956    }
3957    {
3958       OldLink templateLink;
3959       for(templateLink = base.templatized.first; templateLink; templateLink = templateLink.next)
3960       {
3961          Class template = templateLink.data;
3962          template._vTbl = base._vTbl;
3963          FixDerivativeVirtualMethod(template, name, vid, origFunction, type);
3964       }
3965    }
3966 }
3967
3968 public dllexport Method eClass_AddMethod(Class _class, char * name, char * type, void * function, AccessMode declMode)
3969 {
3970    if(_class && name)
3971    {
3972       Class base;
3973       for(base = _class; base; base = base.base)
3974       {
3975          Method method = (Method)base.methods.FindString(name);
3976          if(method)
3977          {
3978             // If this overides a virtual method
3979             if(method.type == virtualMethod)
3980             {
3981                OldLink deriv;
3982                void * oldFunction = _class._vTbl[method.vid];
3983                if(method.vid > _class.vTblSize)
3984                   printf("error");
3985                else
3986                   _class._vTbl[method.vid] = function ? function : DefaultFunction;
3987                for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
3988                {
3989                   Class derivClass = deriv.data;
3990                   if(derivClass._vTbl[method.vid] == oldFunction)
3991                      eClass_AddMethod(derivClass, name, type, function, declMode);
3992                }
3993                {
3994                   OldLink templateLink;
3995                   for(templateLink = _class.templatized.first; templateLink; templateLink = templateLink.next)
3996                   {
3997                      Class template = templateLink.data;
3998                      for(deriv = template.derivatives.first; deriv; deriv = deriv.next)
3999                      {
4000                         Class derivClass = deriv.data;
4001                         if(derivClass._vTbl[method.vid] == oldFunction)
4002                            eClass_AddMethod(derivClass, name, type, function, declMode);
4003                      }
4004                   }
4005                }
4006
4007             }
4008             else
4009             {
4010                if(base == _class)
4011                {
4012                   // printf("error: Redefinition of method %s in class %s\n", name, _class.name);
4013                   break;
4014                }
4015                base = null;
4016                break;
4017             }
4018             return method;
4019          }
4020       }
4021
4022       if(!base)
4023       {
4024          Method method
4025          {
4026             name = CopyString(name),
4027             function = function ? function : DefaultFunction;
4028             _class = _class;
4029             dataTypeString = CopyString(type);
4030             memberAccess = declMode;
4031          };
4032          _class.methods.Add((BTNode)method);
4033          return method;
4034       }
4035    }
4036    return null;
4037 }
4038
4039 public dllexport Method eClass_AddVirtualMethod(Class _class, char * name, char * type, void * function, AccessMode declMode)
4040 {
4041    if(_class && name)
4042    {
4043       Class base;
4044       for(base = _class; base; base = base.base)
4045       {
4046          Method method = (Method)base.methods.FindString(name);
4047          if(method)
4048          {
4049             // If this overides a virtual method
4050             if(method.type == virtualMethod)
4051                _class._vTbl[method.vid] = function ? function : DefaultFunction;
4052             else
4053                base = null;
4054             return method;
4055          }
4056       }
4057
4058       if(!base)
4059       {
4060          Method method
4061          {
4062             name = CopyString(name);
4063             function = function ? function : DefaultFunction;
4064             type = virtualMethod;
4065             _class = _class;
4066             vid = _class.vTblSize++;
4067             dataTypeString = CopyString(type);
4068             memberAccess = declMode;
4069          };
4070          _class.methods.Add((BTNode)method);
4071          _class._vTbl = renew _class._vTbl void *[_class.vTblSize];
4072          _class._vTbl[method.vid] = function ? function : DefaultFunction;
4073
4074          // TODO: Fix derived classes
4075          if(_class.derivatives.first || _class.templatized.first)
4076             FixDerivativeVirtualMethod(_class, name, method.vid, function ? function : (void *)DefaultFunction, type);
4077          return method;
4078       }
4079    }
4080    return null;
4081 }
4082
4083 static void FixDerivativeProperty(Class base, Property _property)
4084 {
4085    OldLink derivative;
4086    for(derivative = base.derivatives.first; derivative; derivative = derivative.next)
4087    {
4088       Class _class = derivative.data;
4089       Property prop;
4090       BTNamedLink link;
4091       link = (BTNamedLink)_class.prop.FindString(_property.name);
4092       if(link)
4093       {
4094          prop = link.data;
4095          if(!prop.Set && !prop.Get && prop.memberAccess == baseSystemAccess)
4096          {
4097             SelfWatcher watcher;
4098             for(watcher = _class.selfWatchers.first; watcher; watcher = watcher.next)
4099             {
4100                if(watcher._property == prop)
4101                   watcher._property = _property;
4102             }
4103             _property.selfWatchable = true;
4104
4105             delete prop.name;
4106             delete prop.dataTypeString;
4107             _class.membersAndProperties.Delete(prop);
4108             _class.prop.Delete((BTNode)link);
4109          }
4110       }
4111
4112       for(prop = _class.membersAndProperties.first; prop; prop = prop.next)
4113          prop.id++;
4114       _class.memberID++;
4115       _class.startMemberID++;
4116
4117       FixDerivativeProperty(_class, _property);
4118    }
4119 }
4120
4121 public dllexport Property eClass_AddProperty(Class _class, char * name, char * dataType, void * setStmt, void * getStmt, AccessMode declMode)
4122 {
4123    Property _property = null;
4124    if(_class)
4125    {
4126       if(!_class.prop.FindString((name ? name : dataType))) 
4127       {
4128          _property =
4129          {
4130             isProperty = true;
4131             name = CopyString(name ? name : dataType);
4132             id = (name && (setStmt || getStmt || dataType)) ? _class.memberID++ : 0;
4133             Set = setStmt;
4134             Get = getStmt;
4135             dataTypeString = CopyString(dataType);
4136             _class = _class;
4137             compiled = true;
4138             conversion = name ? false : true;
4139             memberAccess = declMode;
4140          };
4141          if(name)
4142             _class.membersAndProperties.Add(_property);
4143          else
4144             _class.conversions.Add(_property);
4145          _class.prop.Add((BTNode)BTNamedLink { name = _property.name, data = _property });
4146
4147          if(!_property.conversion)
4148          {
4149             FixDerivativeProperty(_class, _property);
4150          }
4151       }
4152    }
4153    return _property;
4154 }
4155
4156 static void SetDelayedCPValues(Class _class, ClassProperty _property)
4157 {
4158    OldLink deriv;
4159    NamedLink64 value, next;
4160
4161    for(value = _class.delayedCPValues.first; value; value = next)
4162    {
4163       next = value.next;
4164       if(!strcmp(value.name, _property.name))
4165       {
4166          // eClass_SetProperty(_class, _property.name, value.data);
4167          _property.Set(_class, value.data);
4168          _class.delayedCPValues.Delete(value);
4169       }
4170    }
4171
4172    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
4173    {
4174       SetDelayedCPValues(deriv.data, _property);
4175    }
4176 }
4177
4178 public dllexport ClassProperty eClass_AddClassProperty(Class _class, char * name, char * dataType, void * setStmt, void * getStmt)
4179 {
4180    if(name && !_class.classProperties.FindString(name)) 
4181    {
4182       ClassProperty _property
4183       {
4184          name = CopyString(name);
4185          Set = setStmt;
4186          Get = getStmt;
4187          dataTypeString = CopyString(dataType);
4188       };
4189       _class.classProperties.Add((BTNode)_property);
4190       SetDelayedCPValues(_class, _property);
4191       return _property;
4192    }
4193    return null;
4194 }
4195
4196 /*import "Time"
4197
4198 Time classFindTotalTime;
4199
4200 public dllexport void ResetClassFindTime()
4201 {
4202    classFindTotalTime = 0;
4203 }
4204
4205 public dllexport Time GetClassFindTime()
4206 {
4207    return classFindTotalTime;
4208 }
4209 */
4210 public dllexport ClassProperty eClass_FindClassProperty(Class _class, char * name)
4211 {
4212    //Time startTime = GetTime();
4213    ClassProperty _property = null;
4214    if(name && _class)
4215    {
4216       Class origClass = _class;
4217       for(; _class; _class = _class.base)
4218       {
4219          _property = (ClassProperty)_class.classProperties.FindString(name);
4220          if(_property)
4221             break;
4222       }
4223       // For enum class deriving off something else than enum to find enumSize...
4224       if(!_property && origClass.type == enumClass)
4225       {
4226          Class enumClass = eSystem_FindClass(origClass.module, "enum");
4227          _property = eClass_FindClassProperty(enumClass, name);
4228       }
4229    }
4230    /*if(!_property)
4231       eSystem_Logf("No such property (%s) for class %s\n", name, _class.name);*/
4232    //classFindTotalTime += GetTime() - startTime;
4233    return _property;
4234 }
4235
4236 public dllexport int64 eClass_GetProperty(Class _class, char * name)
4237 {
4238    ClassProperty _property = eClass_FindClassProperty(_class, name);
4239    if(_property && _property.Get && _property.Get != (void *)1)
4240    {
4241       int64 result = _property.Get(_class);
4242       return result;
4243    }
4244    return 0;
4245 }
4246
4247 public dllexport void eClass_SetProperty(Class _class, char * name, int64 value)
4248 {
4249    ClassProperty _property = eClass_FindClassProperty(_class, name);
4250    if(_property)
4251    {
4252       if(_property.Set)
4253          ((void(*)(void *, int64))_property.Set)(_class, value);
4254    }
4255    else
4256    {
4257       _class.delayedCPValues.Add(NamedLink64 { name = name, value });
4258    }
4259 }
4260
4261 public dllexport Method eClass_FindMethod(Class _class, char * name, Module module)
4262 {
4263    //Time startTime = GetTime();
4264    if(_class && name)
4265    {
4266       for(; _class; _class = _class.base)
4267       {
4268          Method method;
4269          if(_class.templateClass) _class = _class.templateClass;
4270          method = (Method)_class.methods.FindString(name);
4271          if(method && (method.memberAccess == publicAccess || _class.module == module || !method.dataTypeString))
4272          {
4273             if(!method.dataTypeString)
4274             {
4275                if(_class.module != module)
4276                {
4277                   if(method.memberAccess == publicAccess)
4278                      module = _class.module;
4279                   else
4280                   {
4281                      //classFindTotalTime += GetTime() - startTime;
4282                      return null;
4283                   }
4284                }
4285             }
4286             else
4287             {
4288                //classFindTotalTime += GetTime() - startTime;
4289                return method;
4290             }
4291          }
4292          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4293       }
4294    }
4295    //classFindTotalTime += GetTime() - startTime;
4296    return null;
4297 }
4298
4299 // Construct an instance
4300 static bool ConstructInstance(void * instance, Class _class, Class from)
4301 {
4302    if(_class.templateClass) _class = _class.templateClass;
4303    if(_class.base && from != _class.base)
4304    {
4305       if(!ConstructInstance(instance, _class.base, from))
4306          return false;
4307    }
4308    if(_class.Initialize)
4309    {
4310       void (* Initialize)(Module module) = (void *)_class.Initialize;
4311       _class.Initialize = null;
4312       Initialize(_class.module);
4313    }
4314    if(_class.Constructor)
4315    {
4316       if(!_class.Constructor(instance))
4317       {
4318          for(; _class; _class = _class.base)
4319          {
4320             if(_class.templateClass) _class = _class.templateClass;
4321             if(_class.Destructor)
4322                _class.Destructor(instance);
4323          }
4324          return false;
4325       }
4326    }
4327    (_class.templateClass ? _class.templateClass : _class).count++;
4328    return true;
4329 }
4330
4331 public dllexport void * eInstance_New(Class _class)
4332 {
4333    Instance instance = null;
4334    if(_class)
4335    {
4336       // instance = _malloc(_class.size);   
4337 #ifdef MEMINFO
4338
4339 #undef malloc
4340    memMutex.Wait();
4341       //allocateClass = _class;
4342       allocateClass = malloc(strlen(_class.name)+1);
4343       allocateInternal = _class.module == __thisModule;
4344       strcpy(allocateClass, _class.name);
4345 #ifndef MEMINFO
4346 #define malloc _mymalloc
4347 #endif
4348
4349 #endif
4350       {
4351          int size = _class.structSize;
4352          int flags = _class.module.application.isGUIApp;
4353          bool inCompiler = (flags & 8) ? true : false;
4354          if(inCompiler)
4355          {
4356             bool force32Bits = (flags & 4) ? true : false;
4357             if(force32Bits)
4358             {
4359                // Allocate 64 bit sizes for these when cross-compiling for 32 bit to allow loaded libraries to work properly
4360                if(!strcmp(_class.name, "Module"))
4361                   size = 560;
4362                else if(_class.templateClass && !strcmp(_class.templateClass.name, "Map"))
4363                   size = 40;
4364             }
4365          }
4366          instance = _calloc(1, size);
4367       }
4368 #ifdef MEMINFO
4369       allocateClass = null;
4370    memMutex.Release();
4371 #endif
4372       if(_class.type == normalClass)
4373       {
4374          instance._class = _class;
4375          // Copy the virtual table initially
4376          instance._vTbl = _class._vTbl;
4377       }
4378       if(!ConstructInstance(instance, _class, null))
4379       {
4380          _free(instance);
4381          instance = null;
4382       }
4383       /*if(_class.type == normalClass && _class.count > 1000)
4384          printf("%s: %d instances\n", _class.name, _class.count);*/
4385    }
4386    return instance;
4387 }
4388
4389 public dllexport void eInstance_Evolve(Instance * instancePtr, Class _class)
4390 {
4391    if(_class && instancePtr && *instancePtr)
4392    {
4393       bool wasApp = false, wasGuiApp = false;
4394       Instance instance = (Instance)renew *instancePtr byte[_class.structSize];
4395       Class fromClass = instance._class;
4396       *instancePtr = instance;
4397       memset(((byte *)instance) + instance._class.structSize, 0, _class.structSize - instance._class.structSize);
4398       // Fix pointers to application
4399       if((wasApp = !strcmp(instance._class.name, "Application")) ||
4400          (wasGuiApp = !strcmp(instance._class.name, "GuiApplication")))
4401       {
4402          Module module;
4403          Application app = (Application) instance;
4404          BTNamedLink link;
4405          Class _class;
4406          NameSpace * nameSpace;
4407          for(module = app.allModules.first; module; module = module.next)
4408             module.application = app;
4409
4410          for(link = (BTNamedLink)app.privateNameSpace.classes.first; link; link = (BTNamedLink)((BTNode)link).next)
4411          {
4412             OldLink t;
4413             ((Class)link.data).nameSpace = &app.privateNameSpace;
4414             for(t = ((Class)link.data).templatized.first; t; t = t.next) { Class template = t.data; template.nameSpace = ((Class)link.data).nameSpace; }
4415          }
4416          for(link = (BTNamedLink)app.publicNameSpace.classes.first; link; link = (BTNamedLink)((BTNode)link).next)
4417          {
4418             OldLink t;
4419             ((Class)link.data).nameSpace = &app.publicNameSpace;
4420             for(t = ((Class)link.data).templatized.first; t; t = t.next) { Class template = t.data; template.nameSpace = ((Class)link.data).nameSpace; }
4421          }
4422
4423          for(link = (BTNamedLink)app.privateNameSpace.defines.first; link; link = (BTNamedLink)((BTNode)link).next)
4424             ((DefinedExpression)link.data).nameSpace = &app.privateNameSpace;
4425          for(link = (BTNamedLink)app.publicNameSpace.defines.first; link; link = (BTNamedLink)((BTNode)link).next)
4426             ((DefinedExpression)link.data).nameSpace = &app.publicNameSpace;
4427
4428          for(link = (BTNamedLink)app.privateNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4429             ((GlobalFunction)link.data).nameSpace = &app.privateNameSpace;
4430          for(link = (BTNamedLink)app.publicNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4431             ((GlobalFunction)link.data).nameSpace = &app.publicNameSpace;
4432
4433          for(nameSpace = (NameSpace *)app.privateNameSpace.nameSpaces.first; nameSpace; nameSpace = (NameSpace *)((BTNode)nameSpace).next)
4434             nameSpace->parent = &app.privateNameSpace;
4435          for(nameSpace = (NameSpace *)app.publicNameSpace.nameSpaces.first; nameSpace; nameSpace = (NameSpace *)((BTNode)nameSpace).next)
4436             nameSpace->parent = &app.publicNameSpace;
4437
4438          // --------------------------------------------------
4439          for(link = (BTNamedLink)app.systemNameSpace.classes.first; link; link = (BTNamedLink)((BTNode)link).next)
4440          {
4441             OldLink t;
4442             ((Class)link.data).nameSpace = &app.systemNameSpace;
4443             for(t = ((Class)link.data).templatized.first; t; t = t.next) { Class template = t.data; template.nameSpace = ((Class)link.data).nameSpace; }
4444          }
4445          for(link = (BTNamedLink)app.systemNameSpace.defines.first; link; link = (BTNamedLink)((BTNode)link).next)
4446             ((DefinedExpression)link.data).nameSpace = &app.systemNameSpace;
4447          for(link = (BTNamedLink)app.systemNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4448             ((GlobalFunction)link.data).nameSpace = &app.systemNameSpace;
4449          for(link = (BTNamedLink)app.systemNameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
4450             ((GlobalFunction)link.data).nameSpace = &app.systemNameSpace;
4451          for(nameSpace = (NameSpace *)app.systemNameSpace.nameSpaces.first; nameSpace; nameSpace = (NameSpace *)((BTNode)nameSpace).next)
4452             nameSpace->parent = &app.systemNameSpace;
4453          // --------------------------------------------------
4454          
4455          for(_class = app.classes.first; _class; _class = _class.next)
4456          {
4457             OldLink templateLink;
4458             _class.module = (Module) app;
4459             for(templateLink = _class.templatized.first; templateLink; templateLink = templateLink.next)
4460             {  
4461                Class template = templateLink.data;
4462                template.module = _class.module;
4463             }
4464          }
4465
4466          for(module = app.allModules.first; module; module = module.next)
4467          {
4468             for(_class = module.classes.first; _class; _class = _class.next)
4469             {
4470                OldLink templateLink;
4471                _class.module = module;
4472                for(templateLink = _class.templatized.first; templateLink; templateLink = templateLink.next)
4473                {
4474                   Class template = templateLink.data;
4475                   template.module = _class.module;
4476                }
4477             }
4478          }
4479
4480          app.application = app;
4481       }
4482
4483       {
4484          Class base;
4485          for(base = instance._class; base && base.type == normalClass && base.count; base = base.base)
4486             (base.templateClass ? base.templateClass : base).count--;
4487       }
4488
4489       instance._class = _class;
4490       // Copy the virtual table initially
4491       instance._vTbl = _class._vTbl;
4492
4493       // We don't want to reconstruct the portion already constructed...
4494       if(!ConstructInstance(instance, _class, fromClass))
4495       {
4496          _free(instance);
4497          *instancePtr = null;
4498       }
4499    }
4500 }
4501
4502 public dllexport void eInstance_Delete(Instance instance)
4503 {
4504 #ifdef MEMINFO
4505    bool checkMemory = false;
4506 #endif
4507    if(instance)
4508    {
4509       Class _class, base;
4510       bool ownVtbl;
4511
4512 #ifdef MEMINFO
4513       if(instance._class == (void *)0xecececec)
4514          _free(instance);
4515 #endif
4516
4517       ownVtbl = instance._vTbl != instance._class._vTbl;
4518
4519       for(_class = instance._class; _class; _class = base)
4520       {
4521          if(_class.templateClass) _class = _class.templateClass;
4522          if(_class.destructionWatchOffset)
4523          {
4524             OldList * watchers = (OldList *)((byte *)instance + _class.destructionWatchOffset);
4525             Watcher watcher, next;
4526
4527             for(watcher = watchers->first; watcher; watcher = next)
4528             {
4529                next = watcher.next;
4530                watchers->Remove(watcher);
4531                watcher.callback(watcher.object, instance);
4532                watchers->Delete(watcher);
4533             }
4534          }
4535
4536          /*// Loop through properties to delete all watchers? Might slow down destruction...
4537          {
4538             Property _property;
4539             for(_property = _class.membersAndProperties.first; _property; _property = _property.next)
4540             {
4541                if(_property.isProperty && _property.isWatchable)
4542                {
4543                   OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
4544                   Watcher watcher, next;
4545                   for(watcher = watchers->first; watcher; watcher = next)
4546                   {  
4547                      next = watcher.next;
4548                      watchers->Delete(watcher);
4549                   }
4550                }
4551             }
4552          }*/
4553          
4554
4555          base = _class.base;
4556          if(base && base.type == systemClass) base = null;
4557          if(_class.Destructor)
4558             _class.Destructor(instance);
4559 #ifdef MEMINFO
4560          if(_class == class(Application))
4561             checkMemory = true;
4562 #endif
4563       }
4564
4565       for(_class = instance._class; _class; _class = base)
4566       {
4567          if(_class.templateClass) _class = _class.templateClass;
4568
4569          base = _class.base;
4570          (_class.templateClass ? _class.templateClass : _class).count--;
4571          if(_class.type == normalClass && !_class.count && !_class.module)
4572          {
4573 #ifdef MEMINFO
4574             // printf("Now Destructing class %s\n", _class.name);
4575 #endif
4576             eClass_Unregister(_class);
4577          }
4578       }
4579
4580       if(ownVtbl)
4581       {
4582          delete instance._vTbl;
4583       }
4584       //instance.prop.Free(null);
4585       _free(instance);
4586 #ifdef MEMINFO
4587       if(checkMemory) CheckMemory();
4588 #endif
4589    }
4590 }
4591
4592 public dllexport Property eClass_FindProperty(Class _class, char * name, Module module)
4593 {
4594    //Time startTime = GetTime();
4595    if(_class && name)
4596    {
4597       for(; _class; _class = _class.base)
4598       {
4599          BTNamedLink link;
4600          if(_class.templateClass) _class = _class.templateClass;
4601          link = (BTNamedLink)_class.prop.FindString(name);
4602          if(link)
4603          {
4604             Property _property = (Property)link.data;
4605             if(_property.memberAccess == publicAccess || _class.module == module || !_property.dataTypeString)
4606             {
4607                if(!_property.dataTypeString)
4608                {
4609                   if(_class.module != module)
4610                   {
4611                      if(_property.memberAccess == publicAccess)
4612                         module = _class.module;
4613                      else
4614                      {
4615                         //classFindTotalTime += GetTime() - startTime;
4616                         return null;
4617                      }
4618                   }
4619                }
4620                else
4621                {
4622                   //classFindTotalTime += GetTime() - startTime;
4623                   return _property;
4624                }
4625             }
4626          }
4627          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4628       }
4629    }
4630    //classFindTotalTime += GetTime() - startTime;
4631    return null;
4632 }
4633
4634 static DataMember FindDataMember(OldList list, BinaryTree alist, char * name, uint * offset, int * id, bool searchPrivate, DataMember * subMemberStack, int * subMemberStackPos)
4635 {
4636    BTNamedLink link;
4637    DataMember dataMember;
4638
4639    link = (BTNamedLink)alist.FindString(name);
4640    if(link)
4641    {
4642       dataMember = link.data;
4643       if(dataMember.type == normalMember && (dataMember.memberAccess == publicAccess || searchPrivate || !dataMember.dataTypeString))
4644       {
4645          if(offset)
4646             *offset += dataMember.offset;
4647          if(id) *id = dataMember.id;
4648          return dataMember;
4649       }
4650       return null;
4651    }
4652    for(dataMember = list.first; dataMember; dataMember = dataMember.next)
4653    {
4654       if(!dataMember.isProperty && (dataMember.memberAccess == publicAccess || searchPrivate) && !dataMember.name && (dataMember.type == unionMember || dataMember.type == structMember))
4655       {
4656          DataMember childMember;
4657          if(subMemberStackPos) subMemberStack[(*subMemberStackPos)++] = dataMember;
4658          childMember = FindDataMember(dataMember.members, dataMember.membersAlpha, name, offset, id, searchPrivate, subMemberStack, subMemberStackPos);
4659          if(childMember)
4660          {
4661             if(offset)
4662                *offset += dataMember.offset;
4663             if(id) *id += dataMember.id;
4664             return childMember;
4665          }
4666          if(subMemberStackPos) (*subMemberStackPos)--;
4667       }
4668    }
4669    return null;
4670 }
4671
4672 public dllexport DataMember eClass_FindDataMember(Class _class, char * name, Module module, DataMember * subMemberStack, int * subMemberStackPos)
4673 {
4674    //Time startTime = GetTime();
4675    DataMember dataMember = null;
4676    if(subMemberStackPos) *subMemberStackPos = 0;
4677    if(_class && name)
4678    {
4679       for(; _class; _class = _class.base)
4680       {
4681          if(_class.templateClass) _class = _class.templateClass;
4682          dataMember = FindDataMember(_class.membersAndProperties, _class.members, name, null, null, _class.module == module, subMemberStack, subMemberStackPos);
4683          if(dataMember)
4684          {
4685             if(!dataMember.dataTypeString)
4686             {
4687                if(_class.module != module)
4688                {
4689                   if(dataMember.memberAccess == publicAccess)
4690                      module = _class.module;
4691                   else
4692                   {
4693                      //classFindTotalTime += GetTime() - startTime;
4694                      return null;
4695                   }
4696                }
4697                dataMember = null;
4698             }
4699             else
4700             {
4701                // HACK: Is this good enough? avoiding setting it when adding...
4702                dataMember._class = _class.templateClass ? _class.templateClass : _class;
4703                //classFindTotalTime += GetTime() - startTime;
4704                return dataMember;
4705             }
4706          }
4707          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4708       }
4709    }
4710    //classFindTotalTime += GetTime() - startTime;
4711    return dataMember;
4712 }
4713
4714 public dllexport DataMember eClass_FindDataMemberAndOffset(Class _class, char * name, uint * offset, Module module, DataMember * subMemberStack, int * subMemberStackPos)
4715 {
4716    //Time startTime = GetTime();
4717    DataMember dataMember = null;
4718    if(subMemberStackPos) *subMemberStackPos = 0;
4719    if(offset) *offset = 0;
4720    if(_class)
4721    {
4722       for(; _class; _class = _class.base)
4723       {
4724          if(_class.templateClass) _class = _class.templateClass;
4725          dataMember = FindDataMember(_class.membersAndProperties, _class.members, name, offset, null, _class.module == module, subMemberStack, subMemberStackPos);
4726          if(dataMember)
4727          {
4728             if(!dataMember.dataTypeString)
4729             {
4730                if(_class.module != module)
4731                {
4732                   if(dataMember.memberAccess == publicAccess)
4733                      module = _class.module;
4734                   else
4735                   {
4736                      //classFindTotalTime += GetTime() - startTime;
4737                      return null;
4738                   }
4739                }
4740                dataMember = null;
4741             }
4742             else
4743             {
4744                // HACK: Is this good enouh? avoiding setting it when adding...
4745                dataMember._class = _class;
4746                //classFindTotalTime += GetTime() - startTime;
4747                return dataMember;
4748             }
4749          }
4750          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4751       }
4752    }
4753    //classFindTotalTime += GetTime() - startTime;
4754    return dataMember;
4755 }
4756
4757 public dllexport DataMember eClass_FindDataMemberAndId(Class _class, char * name, int * id, Module module, DataMember * subMemberStack, int * subMemberStackPos)
4758 {
4759    //Time startTime = GetTime();
4760    DataMember dataMember = null;
4761    if(subMemberStackPos) *subMemberStackPos = 0;
4762    if(_class)
4763    {
4764       for(; _class; _class = _class.base)
4765       {
4766          if(_class.templateClass) _class = _class.templateClass;
4767          dataMember = FindDataMember(_class.membersAndProperties, _class.members, name, null, id, _class.module == module, subMemberStack, subMemberStackPos);  // TOCHECK: Why was this null? null, null);
4768          if(dataMember)
4769          {
4770             if(!dataMember.dataTypeString)
4771             {
4772                if(_class.module != module)
4773                {
4774                   if(dataMember.memberAccess == publicAccess)
4775                      module = _class.module;
4776                   else
4777                   {
4778                      //classFindTotalTime += GetTime() - startTime;
4779                      return null;
4780                   }
4781                }
4782                dataMember = null;
4783             }
4784             else
4785             {
4786                // HACK: Is this good enouh? avoiding setting it when adding...
4787                dataMember._class = _class;
4788                //classFindTotalTime += GetTime() - startTime;
4789                return dataMember;
4790             }
4791          }
4792          if(_class.inheritanceAccess == privateAccess && _class.module != module) break;
4793       }
4794    }
4795    //classFindTotalTime += GetTime() - startTime;
4796    return dataMember;
4797 }
4798
4799 public dllexport void eClass_FindNextMember(Class _class, Class * curClass, DataMember * curMember, DataMember * subMemberStack, int * subMemberStackPos)
4800 {
4801    // THIS CODE WILL FIND NEXT MEMBER... (PUBLIC MEMBERS ONLY)
4802    if(*curMember) 
4803    {
4804       *curMember = (*curMember).next;
4805
4806       if(subMemberStackPos && *subMemberStackPos > 0 && subMemberStack[*subMemberStackPos-1].type == unionMember)
4807       {
4808          *curMember = subMemberStack[--(*subMemberStackPos)];
4809          *curMember = (*curMember).next;
4810       }
4811
4812       if(subMemberStackPos && *subMemberStackPos > 0)
4813       {
4814          while(*curMember && ((*curMember).memberAccess == privateAccess))
4815             *curMember = (*curMember).next;
4816       }
4817       else
4818          while(*curMember && (*curMember).name)      // ADDED THIS HERE for eComPacket packet { Connect, 0, { ECOMMUNICATOR_PROTOCOL_VERSION } };
4819          {
4820             DataMember dataMember = eClass_FindDataMember(_class, curMember->name, null, null, null);
4821             if(!dataMember) dataMember = (DataMember)eClass_FindProperty(_class, curMember->name, null);
4822             if(dataMember && dataMember.memberAccess != privateAccess)
4823             {
4824                *curMember = dataMember;
4825                break;
4826             }
4827             else
4828                *curMember = (*curMember).next;
4829          }
4830
4831       if(subMemberStackPos)
4832       {
4833          while((*curMember) && !(*curMember).isProperty && !(*curMember).name && ((*curMember).type == structMember || (*curMember).type == unionMember))
4834          {
4835             subMemberStack[(*subMemberStackPos)++] = *curMember;
4836
4837             *curMember = (*curMember).members.first;
4838             while(*curMember && ((*curMember).memberAccess == privateAccess))
4839                *curMember = (*curMember).next;                     
4840          }
4841       }
4842    }
4843    while(!*curMember)
4844    {
4845       if(!*curMember)
4846       {
4847          if(subMemberStackPos && *subMemberStackPos)
4848          {
4849             *curMember = subMemberStack[--(*subMemberStackPos)];
4850             *curMember = (*curMember).next;
4851          }
4852          else
4853          {
4854             Class lastCurClass = *curClass;
4855
4856             if(*curClass == _class) break;     // REACHED THE END
4857
4858             for(*curClass = _class; (*curClass).base != lastCurClass && (*curClass).base.type != systemClass && (*curClass).inheritanceAccess != privateAccess; *curClass = (*curClass).base);
4859             *curMember = (*curClass).membersAndProperties.first;
4860          }
4861
4862          if(subMemberStackPos && *subMemberStackPos > 0)
4863          {
4864             while(*curMember && ((*curMember).memberAccess == privateAccess))
4865                *curMember = (*curMember).next;
4866          }
4867          else
4868             while(*curMember && (*curMember).name)      // ADDED THIS HERE for eComPacket packet { Connect, 0, { ECOMMUNICATOR_PROTOCOL_VERSION } };
4869             {
4870                DataMember dataMember = eClass_FindDataMember(_class, curMember->name, null, null, null);
4871                if(!dataMember) dataMember = (DataMember)eClass_FindProperty(_class, curMember->name, null);
4872                if(dataMember && dataMember.memberAccess != privateAccess)
4873                {
4874                   *curMember = dataMember;
4875                   break;
4876                }
4877                else
4878                   *curMember = (*curMember).next;
4879             }
4880
4881          if(subMemberStackPos)
4882          {
4883             while((*curMember) && !(*curMember).isProperty && !(*curMember).name && ((*curMember).type == structMember || (*curMember).type == unionMember))
4884             {
4885                subMemberStack[(*subMemberStackPos)++] = *curMember;
4886
4887                *curMember = (*curMember).members.first;
4888                while(*curMember && (*curMember).memberAccess == privateAccess)
4889                   *curMember = (*curMember).next;                     
4890             }
4891          }
4892       }
4893    }
4894 }
4895
4896 public dllexport void eInstance_SetMethod(Instance instance, char * name, void * function)     // YET TO BE DECIDED:   , Module module)
4897 {
4898    if(instance && name)
4899    {
4900       Class _class;
4901       for(_class = instance._class; _class; _class = _class.base)
4902       {
4903          Method method = (Method)_class.methods.FindString(name);
4904          if(method && method.type == virtualMethod)
4905          {
4906             if(instance._vTbl == instance._class._vTbl)
4907             {
4908                instance._vTbl = _malloc(sizeof(void *) * instance._class.vTblSize);
4909                memcpy(instance._vTbl, instance._class._vTbl,
4910                   sizeof(int(*)()) * instance._class.vTblSize);               
4911             }
4912             instance._vTbl[method.vid] = function ? function : DefaultFunction;
4913          }
4914       }
4915    }
4916 }
4917
4918 public dllexport bool eInstance_IsDerived(Instance instance, Class from)
4919 {
4920    if(instance)
4921    {
4922       Class _class = instance._class;
4923       for(; _class; _class = _class.base)
4924       {
4925          if(_class == from)
4926             return true;
4927       }
4928    }
4929    return false;
4930 }
4931
4932 public dllexport void eInstance_IncRef(Instance instance)
4933 {
4934    if(instance)
4935       instance._refCount++;
4936 }
4937
4938 public dllexport void eInstance_DecRef(Instance instance)
4939 {
4940    if(instance)
4941    {
4942       instance._refCount--;
4943       //if(!instance._refCount)
4944       if(instance._refCount <= 0)
4945       {
4946          eInstance_Delete(instance);
4947       }
4948    }
4949 }
4950
4951 static void FixOffsets(Class _class)
4952 {
4953    OldLink deriv;
4954    _class.structSize += _class.base.structSize - _class.offset;
4955
4956    _class.offset = _class.base.structSize;   
4957
4958    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
4959       FixOffsets(deriv.data);
4960 }
4961
4962 public dllexport void eClass_Resize(Class _class, int newSize)
4963 {
4964    OldLink deriv;
4965    _class.structSize = newSize;
4966    for(deriv = _class.derivatives.first; deriv; deriv = deriv.next)
4967       FixOffsets(deriv.data);
4968 }
4969
4970 public dllexport DataMember eClass_AddDataMember(Class _class, char * name, char * type, unsigned int size, unsigned int alignment, AccessMode declMode)
4971 {
4972    if(_class && name)
4973    {
4974       if(!_class.members.FindString(name)) 
4975       {
4976          DataMember dataMember;
4977
4978          if(alignment)
4979          {
4980             _class.structAlignment = Max(_class.structAlignment, alignment);
4981
4982             if(_class.memberOffset % alignment)
4983                _class.memberOffset += alignment - (_class.memberOffset % alignment);
4984          }
4985          
4986          dataMember = DataMember {
4987             name = CopyString(name);
4988             dataTypeString = CopyString(type);
4989             id = _class.memberID++;
4990             _class = _class;
4991             offset = _class.memberOffset;
4992             memberOffset = size;
4993             memberAccess = declMode;
4994             membersAlpha.CompareKey = (void *)BinaryTree::CompareString;
4995          };
4996          _class.membersAndProperties.Add(dataMember);
4997          _class.memberOffset += size;
4998
4999          _class.members.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
5000          return dataMember;
5001       }
5002    }
5003    return null;
5004 }
5005
5006 public dllexport DataMember eMember_AddDataMember(DataMember member, char * name, char * type, unsigned int size, unsigned int alignment, AccessMode declMode)
5007 {
5008    if(name && !member.membersAlpha.FindString(name)) 
5009    {
5010       DataMember dataMember;
5011
5012       if(alignment)
5013       {
5014          member.structAlignment = Max(member.structAlignment, alignment);
5015
5016          if(member.memberOffset % alignment)
5017             member.memberOffset += alignment - (member.memberOffset % alignment);
5018       }
5019       dataMember = DataMember {
5020          name = CopyString(name);
5021          _class = member._class;
5022          dataTypeString = CopyString(type);
5023          id = member.memberID++;
5024          offset = (member.type == unionMember) ? 0 : member.memberOffset;
5025          memberAccess = declMode;
5026          membersAlpha.CompareKey = (void *)BinaryTree::CompareString;
5027       };
5028       member.members.Add(dataMember);
5029       if(member.type == unionMember)
5030       {
5031          if(size > member.memberOffset)
5032             member.memberOffset = size;
5033       }
5034       else
5035          member.memberOffset += size;
5036       member.membersAlpha.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
5037       return dataMember;
5038    }
5039    return null;
5040 }
5041
5042 public dllexport DataMember eMember_New(DataMemberType type, AccessMode declMode)
5043 {
5044    return DataMember { type = type, memberAccess = declMode, membersAlpha.CompareKey = (void *)BinaryTree::CompareString };
5045 }
5046
5047 static void SetMemberClass(DataMember member, Class _class)
5048 {
5049    DataMember dataMember;
5050    member._class = _class;
5051    for(dataMember = member.members.first; dataMember; dataMember = dataMember.next)
5052       SetMemberClass(dataMember, _class);      
5053 }
5054
5055 public dllexport bool eMember_AddMember(DataMember addTo, DataMember dataMember)
5056 {
5057    if(dataMember.name && addTo.membersAlpha.FindString(dataMember.name)) return false;
5058    addTo.members.Add(dataMember);
5059
5060    if(dataMember.name)
5061       addTo.membersAlpha.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
5062
5063    dataMember._class = addTo._class;
5064    // ? SetMemberClass(dataMember, addTo._class);
5065
5066    //dataMember.id = addTo.memberID++;
5067    dataMember.id = addTo.memberID;
5068    if(dataMember.type == unionMember)
5069       addTo.memberID += 1;
5070    else
5071       addTo.memberID += dataMember.memberID;
5072
5073    addTo.structAlignment = Max(addTo.structAlignment, dataMember.structAlignment);
5074    dataMember.offset = (addTo.type == unionMember) ? 0 : addTo.memberOffset;
5075    if(addTo.type == unionMember)
5076    {
5077       if(dataMember.memberOffset > addTo.memberOffset)
5078          addTo.memberOffset = dataMember.memberOffset;
5079    }
5080    else
5081       addTo.memberOffset += dataMember.memberOffset;
5082    return true;
5083 }
5084
5085 public dllexport bool eClass_AddMember(Class _class, DataMember dataMember)
5086 {
5087    if(!_class || _class.comRedefinition || (dataMember.name && _class.members.FindString(dataMember.name)))
5088       return false;
5089    _class.membersAndProperties.Add(dataMember);
5090
5091    if(dataMember.name)
5092       _class.members.Add((BTNode)BTNamedLink { name = dataMember.name, data = dataMember });
5093
5094    //dataMember._class = _class;
5095    SetMemberClass(dataMember, _class);
5096
5097    //dataMember.id = _class.memberID++;
5098    dataMember.id = _class.memberID;
5099
5100    _class.structAlignment = Max(_class.structAlignment, dataMember.structAlignment);
5101    if(dataMember.type == unionMember)
5102       _class.memberID += 1;
5103    else
5104       _class.memberID += dataMember.memberID;
5105    dataMember.offset = _class.memberOffset;
5106    _class.memberOffset += dataMember.memberOffset;
5107    return true;
5108 }
5109
5110 public dllexport BitMember eClass_AddBitMember(Class _class, char * name, char * type, int bitSize, int bitPos, AccessMode declMode)
5111 {
5112    if(_class && name && !_class.members.FindString(name)) 
5113    {
5114       uint64 mask = 0;
5115       int c;
5116       BitMember bitMember
5117       {
5118          name = CopyString(name);
5119          _class = _class;
5120          dataTypeString = CopyString(type);
5121          id = _class.memberID++;
5122          memberAccess = declMode;
5123       };
5124       _class.membersAndProperties.Add(bitMember);
5125       if(bitSize)
5126       {
5127          bitMember.pos = (bitPos == -1) ? _class.memberOffset : bitPos;
5128          bitMember.size = bitSize;
5129          _class.memberOffset = bitMember.pos + bitMember.size;
5130          for(c = 0; c<bitSize; c++)
5131          {
5132             if(c)
5133                mask <<= 1;
5134             mask |= 1;
5135          }
5136          bitMember.mask = mask << bitMember.pos;
5137       }
5138
5139      _class.members.Add((BTNode)BTNamedLink { name = bitMember.name, data = bitMember });
5140       return bitMember;
5141    }
5142    return null;
5143 }
5144
5145 static Module Module_Load(Module fromModule, char * name, AccessMode importAccess, bool ensureCOM)
5146 {
5147    bool (stdcall * Load)(Module module) = null;
5148    bool (stdcall * Unload)(Module module) = null;
5149    Module module;
5150
5151    for(module = fromModule.application.allModules.first; module; module = module.next)
5152    {
5153       if(!strcmp(module.name, name))
5154          break;
5155    }
5156    if(ensureCOM && (!strcmp(name, "ecereCOM") || !strcmp(name, "ecere")))
5157    {
5158       for(module = fromModule.application.allModules.first; module; module = module.next)
5159       {
5160          if(!strcmp(module.name, "ecere") || !strcmp(module.name, "ecereCOM"))
5161             break;
5162       }
5163    }
5164    if(!module)
5165    {
5166       void * library = null;
5167
5168       if(ensureCOM && !strcmp(name, "ecereCOM"))
5169       {
5170          Load = COM_LOAD_FUNCTION;
5171          Unload = COM_UNLOAD_FUNCTION;
5172       }
5173       else
5174       {
5175          char * libLocation = null;
5176 #if defined(__ANDROID__)
5177          libLocation = AndroidInterface_GetLibLocation();
5178 #endif
5179          library = Instance_Module_Load(libLocation, name, &Load, &Unload);
5180       }
5181       if(Load)
5182       {
5183          module = (Module)eInstance_New(eSystem_FindClass(fromModule, "Module"));
5184          module.application = fromModule.application;
5185          module.library = library;
5186          module.name = CopyString(name);
5187          module.Unload = Unload;
5188          module.origImportType = normalImport;
5189          if(!Load(module))
5190          {
5191             eInstance_Delete((Instance)module);
5192             module = null;
5193          }
5194       }
5195       fromModule.application.allModules.Add(module);
5196    }
5197    if(ensureCOM && !strcmp(name, "ecere") && module)
5198    {
5199       name = !strcmp(module.name, "ecereCOM") ? "ecere" : "ecereCOM";
5200       if((!Load && !strcmp(module.name, "ecereCOM")) || 
5201          (Load && (!__thisModule || !__thisModule.name || !strcmp(__thisModule.name, "ecereCOM")) && Load != COM_LOAD_FUNCTION))
5202       {
5203          Module module;
5204          for(module = fromModule.application.allModules.first; module; module = module.next)
5205          {
5206             if(!strcmp(module.name, name))
5207                break;
5208          }
5209          if(!module)
5210          {
5211             Load = COM_LOAD_FUNCTION;
5212             Unload = COM_UNLOAD_FUNCTION;
5213
5214             module = (Module)eInstance_New(eSystem_FindClass(fromModule, "Module"));
5215             module.application = fromModule.application;
5216             module.library = null;
5217             module.name = CopyString(name);
5218             module.Unload = Unload;
5219             if(!Load(module))
5220             {
5221                eInstance_Delete((Instance)module);
5222                module = null;
5223             }
5224             fromModule.application.allModules.Add(module);
5225          }
5226          if(module)
5227          {
5228             if(fromModule)
5229             {
5230                fromModule.modules.Add(SubModule { module = module, importMode = importAccess });
5231             }
5232             incref module;
5233          }
5234       }
5235    }
5236    if(module)
5237    {
5238       if(fromModule)
5239       {
5240          fromModule.modules.Add(SubModule { module = module, importMode = importAccess });
5241       }
5242       incref module;
5243    }
5244 #if defined(_DEBUG)
5245    InternalModuleLoadBreakpoint();
5246 #endif
5247    return module;
5248 }
5249
5250 public dllexport Module eModule_Load(Module fromModule, char * name, AccessMode importAccess)
5251 {
5252    return Module_Load(fromModule, name, importAccess, true);
5253 }
5254
5255 public dllexport Module eModule_LoadStrict(Module fromModule, char * name, AccessMode importAccess)
5256 {
5257    return Module_Load(fromModule, name, importAccess, false);
5258 }
5259
5260 public dllexport Module eModule_LoadStatic(Module fromModule, char * name, AccessMode importAccess, bool (* Load)(Module module), bool (* Unload)(Module module))
5261 {
5262    Module module;
5263    for(module = fromModule.application.allModules.first; module; module = module.next)
5264    {
5265       if(!strcmp(module.name, name))
5266          break;
5267    }
5268    if(!module)
5269    {
5270       if(Load)
5271       {
5272          module = (Module)eInstance_New(eSystem_FindClass(fromModule, "Module"));
5273          module.application = fromModule.application;
5274          module.name = CopyString(name);
5275          module.origImportType = staticImport;
5276          module.Unload = (void *)Unload;
5277          if(!Load(module))
5278          {
5279             eInstance_Delete((Instance)module);
5280             module = null;
5281          }
5282       }
5283       fromModule.application.allModules.Add(module);
5284    }
5285    if(module)
5286    {
5287       if(fromModule)
5288       {
5289          fromModule.modules.Add(SubModule { module = module, importMode = importAccess });
5290       }
5291       incref module;
5292    }
5293    return module;
5294 }
5295
5296 public dllexport void eModule_Unload(Module fromModule, Module module)
5297 {
5298    OldLink m;
5299    for(m = fromModule.modules.first; m; m = m.next)
5300    {
5301       if(m.data == module)
5302          break;
5303    }
5304    if(m)
5305    {
5306       fromModule.modules.Delete(m);
5307       delete module;
5308    }
5309 }
5310
5311 public dllexport void eEnum_AddFixedValue(Class _class, char * string, int value)
5312 {
5313    if(_class && _class.type == enumClass)
5314    {
5315       EnumClassData data = (EnumClassData)_class.data;
5316       NamedLink item;
5317       
5318       for(item = data.values.first; item; item = item.next)
5319          if(!strcmp(item.name, string)) 
5320             break;
5321       if(!item)
5322       {
5323          data.values.Add(NamedLink { data = (void *)value, name = CopyString(string) });
5324          if(value > data.largest)
5325             data.largest = value;
5326       }
5327    }
5328 }
5329
5330 public dllexport int eEnum_AddValue(Class _class, char * string)
5331 {
5332    if(_class && _class.type == enumClass)
5333    {
5334       EnumClassData data = (EnumClassData)_class.data;
5335       int value = ((int) data.largest) + 1;
5336       NamedLink item;
5337       for(item = data.values.first; item; item = item.next)
5338          if(!strcmp(item.name, string)) 
5339             break;
5340       if(!item)
5341       {
5342          data.values.Add(NamedLink { data = (void *)value, name = CopyString(string) });
5343          if(value > data.largest)
5344             data.largest = value;
5345          return value;
5346       }
5347    }
5348    return -1;
5349 }
5350
5351 static void NameSpace_Free(NameSpace parentNameSpace)
5352 {
5353    NameSpace * nameSpace;
5354    delete parentNameSpace.name;
5355
5356    while((nameSpace = (NameSpace *)parentNameSpace.nameSpaces.first))
5357    {
5358       NameSpace_Free(nameSpace);
5359       parentNameSpace.nameSpaces.Delete((BTNode)nameSpace);
5360    }
5361 }
5362
5363 static void Application_Destructor(Application app)
5364 {
5365    if(app.parsedCommand)
5366    {
5367       delete app.argv;
5368       delete app.parsedCommand;
5369    }
5370 }
5371
5372 static bool Module_Constructor(Module module)
5373 {
5374    module.privateNameSpace.classes.CompareKey = (void *)BinaryTree::CompareString;
5375    module.privateNameSpace.defines.CompareKey = (void *)BinaryTree::CompareString;
5376    module.privateNameSpace.functions.CompareKey = (void *)BinaryTree::CompareString;
5377    module.privateNameSpace.nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5378
5379    module.publicNameSpace.classes.CompareKey = (void *)BinaryTree::CompareString;
5380    module.publicNameSpace.defines.CompareKey = (void *)BinaryTree::CompareString;
5381    module.publicNameSpace.functions.CompareKey = (void *)BinaryTree::CompareString;
5382    module.publicNameSpace.nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5383    return true;
5384 }
5385
5386 static void Module_Destructor(Module module)
5387 {
5388    Class _class;
5389    DefinedExpression def;
5390    GlobalFunction function;
5391    Module m;
5392    SubModule handle;
5393
5394    // printf("Destructing module %s\n", module.name);
5395
5396    // Take out references from all modules
5397    for(m = module.application.allModules.first; m; m = m.next)
5398    {
5399       SubModule next;
5400       for(handle = m.modules.first; handle; handle = next)
5401       {
5402          next = handle.next;
5403          if(handle.module == module)
5404             m.modules.Delete(handle);
5405       }
5406    }
5407
5408    if(module.Unload)
5409    {
5410       if(module.origImportType == staticImport)
5411       {
5412          bool (* Unload)(Module module) = (void *)module.Unload;
5413          Unload(module);
5414       }
5415       else
5416       {
5417          bool (stdcall * Unload)(Module module) = (void *)module.Unload;
5418          Unload(module);
5419       }
5420    }
5421
5422    // Unload dependencies
5423    {
5424       Module ourWorld = class(Class).module;
5425       void * ourHandle = null;
5426       while((handle = module.modules.last))  // STARTING WITH LAST SO THAT ecereCOM IS UNLOADED LAST...
5427       {
5428          Module depModule = handle.module;
5429          if(depModule == ourWorld) 
5430          {
5431             module.modules.Remove(handle);
5432             ourHandle = handle;
5433          }
5434          else
5435          {
5436             module.modules.Delete(handle);
5437             delete depModule;
5438          }         
5439       }
5440       if(ourHandle)
5441       {
5442          delete ourHandle;
5443          delete ourWorld;
5444       }
5445    }
5446
5447    // Unload classes
5448    for(;(_class = module.classes.first);)
5449    {
5450       if(_class.nameSpace)
5451       {
5452          BTNamedLink classLink = (BTNamedLink)_class.nameSpace->classes.FindString(_class.name);
5453          OldLink t;
5454          for(t = _class.templatized.first; t; t = t.next)
5455          {
5456             Class template = t.data;
5457             BTNamedLink link;
5458             link = (BTNamedLink)template.nameSpace->classes.FindString(template.name);
5459
5460             template.nameSpace->classes.Delete((BTNode)link);
5461             template.nameSpace = null;
5462          }
5463          _class.nameSpace->classes.Delete((BTNode)classLink);
5464          _class.nameSpace = null;
5465       }
5466       _class.module = null;
5467       module.classes.Remove(_class);
5468       if(!_class.count || _class.type != normalClass)
5469          eClass_Unregister(_class);
5470       else
5471       {
5472 #ifdef MEMINFO
5473          // printf("Delayed destruction of class %s\n", _class.name);
5474 #endif
5475       }
5476    }
5477
5478    // Unload defines
5479    for(;(def = module.defines.first);)
5480    {
5481       if(def.nameSpace)
5482       {
5483          BTNamedLink defLink;
5484          for(defLink = (BTNamedLink)def.nameSpace->defines.first; defLink; defLink = (BTNamedLink)((BTNode)defLink).next)
5485             if(defLink.data == def)
5486             {
5487                def.nameSpace->defines.Delete((BTNode)defLink);
5488                break;
5489             }
5490       }
5491       delete def.name;
5492       delete def.value;
5493       module.defines.Delete(def);
5494    }
5495
5496    // Unload functions
5497    for(;(function = module.functions.first);)
5498    {
5499       if(function.nameSpace)
5500       {
5501          BTNamedLink functionLink;
5502          for(functionLink = (BTNamedLink)function.nameSpace->functions.first; functionLink; functionLink = (BTNamedLink)((BTNode)functionLink).next)
5503             if(functionLink.data == function)
5504             {
5505                function.nameSpace->functions.Delete((BTNode)functionLink);
5506                break;
5507             }
5508       }
5509       delete function.name;
5510       delete function.dataTypeString;
5511       module.functions.Delete(function);
5512    }
5513
5514    delete module.name;
5515
5516    NameSpace_Free(module.privateNameSpace);
5517    NameSpace_Free(module.publicNameSpace);
5518
5519    if(module != module.application)
5520       module.application.allModules.Remove(module);
5521    else
5522       NameSpace_Free(module.application.systemNameSpace);
5523
5524 #ifndef MEMINFO
5525    Instance_Module_Free(module.library);
5526 #endif
5527 }
5528
5529 static int GetEnumSize(Class _class)
5530 {
5531    EnumClassData data = (EnumClassData)_class.data;
5532    return data.largest+1;
5533 }
5534
5535 #if defined(__GNUC__)
5536 #define strcmpi strcasecmp
5537 #define strnicmp strncasecmp
5538 #endif
5539
5540 #if defined(ECERE_BOOTSTRAP) || (defined(__GNUC__) && !defined(__DJGPP__) && !defined(__WIN32__))
5541 #undef strlwr
5542 #undef strupr
5543 default dllexport char * strlwr(char *string)
5544 {
5545    int c;
5546    for(c=0; string[c]; c++)
5547       if(string[c]>='A' && string[c]<='Z')
5548          string[c]+='a'-'A';
5549    return string;
5550 }
5551 default dllexport char * strupr(char *string)
5552 {
5553    int c;
5554    for(c=0; string[c]; c++)
5555       if(string[c]>='a' && string[c]<='z')
5556          string[c]-='a'-'A';
5557    return string;
5558 }
5559 #endif
5560
5561 public dllexport DefinedExpression eSystem_RegisterDefine(char * name, char * value, Module module, AccessMode declMode)
5562 {
5563    NameSpace * nameSpace = null;
5564    
5565    int start = 0, c;
5566
5567    nameSpace = (declMode == publicAccess) ? &module.publicNameSpace : &module.privateNameSpace;
5568    if(declMode == baseSystemAccess) nameSpace = &module.application.systemNameSpace;
5569
5570    if(declMode != staticAccess)
5571    {
5572       for(c = 0; name[c]; c++)
5573       {
5574          if(name[c] == '.' || (name[c] == ':' && name[c+1] == ':'))
5575          {
5576             NameSpace * newSpace;
5577
5578             char * spaceName = _malloc(c - start + 1);
5579             strncpy(spaceName, name + start, c - start);
5580             spaceName[c-start] = '\0';
5581
5582             newSpace = (NameSpace *)nameSpace->nameSpaces.FindString(spaceName);
5583             if(!newSpace)
5584             {
5585                newSpace = new0 NameSpace[1];
5586                newSpace->classes.CompareKey = (void *)BinaryTree::CompareString;
5587                newSpace->defines.CompareKey = (void *)BinaryTree::CompareString;
5588                newSpace->functions.CompareKey = (void *)BinaryTree::CompareString;
5589                newSpace->nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5590                newSpace->name = spaceName;
5591                newSpace->parent = nameSpace;
5592                nameSpace->nameSpaces.Add((BTNode)newSpace);
5593             }
5594             else
5595                delete spaceName;
5596             nameSpace = newSpace;
5597             if(name[c] == ':') c++;
5598             start = c+1;         
5599          }
5600       }
5601    }
5602    else
5603       c = strlen(name);
5604
5605    if(c - start && !nameSpace->defines.FindString(name + start))
5606    {
5607       DefinedExpression def
5608       {
5609          name = CopyString(name);
5610          nameSpace = nameSpace;
5611          value = CopyString(value);
5612       };
5613       nameSpace->defines.Add((BTNode)BTNamedLink { name = def.name + start, data = def });
5614       // Reference the definition in the module
5615       module.defines.Add(def);
5616       return def;
5617    }
5618    return null;
5619 }
5620
5621 public dllexport GlobalFunction eSystem_RegisterFunction(char * name, char * type, void * func, Module module, AccessMode declMode)
5622 {
5623    NameSpace * nameSpace = null;
5624    int start = 0, c;
5625
5626    nameSpace = (declMode == publicAccess) ? &module.publicNameSpace : &module.privateNameSpace;
5627    if(declMode == baseSystemAccess) nameSpace = &module.application.systemNameSpace;
5628
5629    if(declMode != staticAccess)
5630    {
5631       for(c = 0; name[c]; c++)
5632       {
5633          if(name[c] == '.' || (name[c] == ':' && name[c+1] == ':'))
5634          {
5635             NameSpace * newSpace;
5636
5637             char * spaceName = _malloc(c - start + 1);
5638             strncpy(spaceName, name + start, c - start);
5639             spaceName[c-start] = '\0';
5640
5641             newSpace = (NameSpace *)nameSpace->nameSpaces.FindString(spaceName);
5642             if(!newSpace)
5643             {
5644                newSpace = new0 NameSpace[1];
5645                newSpace->classes.CompareKey = (void *)BinaryTree::CompareString;
5646                newSpace->defines.CompareKey = (void *)BinaryTree::CompareString;
5647                newSpace->functions.CompareKey = (void *)BinaryTree::CompareString;
5648                newSpace->nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
5649                newSpace->name = spaceName;
5650                newSpace->parent = nameSpace;
5651                nameSpace->nameSpaces.Add((BTNode)newSpace);
5652             }
5653             else
5654                delete spaceName;
5655             nameSpace = newSpace;
5656             if(name[c] == ':') c++;
5657             start = c+1;         
5658          }
5659       }
5660    }
5661    else
5662       c = strlen(name);
5663
5664    if(c - start && !nameSpace->functions.FindString(name + start))
5665    {
5666       GlobalFunction function
5667       {
5668          name = CopyString(name);
5669          nameSpace = nameSpace;
5670          dataTypeString = CopyString(type);
5671          function = func;
5672          module = module;
5673       };
5674       nameSpace->functions.Add((BTNode)BTNamedLink { name = function.name + start, data = function });
5675       // Reference the definition in the module
5676       module.functions.Add(function);
5677       return function;
5678    }
5679    return null;
5680 }
5681
5682 public dllexport DefinedExpression eSystem_FindDefine(Module module, char * name)
5683 {
5684    if(name && module)
5685    {
5686       BTNamedLink link;
5687       link = SearchNameSpace(&module.application.systemNameSpace, name, &((NameSpace *)0)->defines);
5688       if(link) return link.data;
5689
5690       link = SearchModule(module, name, &((NameSpace *)0)->defines, true);
5691       if(link) return link.data;
5692    }
5693    return null;
5694 }
5695
5696 public dllexport GlobalFunction eSystem_FindFunction(Module module, char * name)
5697 {
5698    if(name && module)
5699    {
5700       BTNamedLink link;
5701       link = SearchNameSpace(&module.application.systemNameSpace, name, &((NameSpace *)0)->functions);
5702       if(link) return link.data;
5703
5704       link = SearchModule(module, name, &((NameSpace *)0)->functions, true);
5705       if(link) return link.data;
5706    }
5707    return null;
5708 }
5709
5710 public dllexport void * eSystem_Renew(void * memory, unsigned int size)
5711 {
5712    return _realloc(memory, size);
5713 }
5714
5715 public dllexport void * eSystem_Renew0(void * memory, unsigned int size)
5716 {
5717    return _crealloc(memory, size);
5718 }
5719
5720 public dllexport void * eSystem_New(unsigned int size)
5721 {
5722 /*#ifdef _DEBUG
5723    void * pointer = _malloc(size);
5724    memset(pointer, 0xec, size);
5725    return pointer;
5726 #else*/
5727    return _malloc(size);
5728 //#endif
5729 }
5730
5731 public dllexport void * eSystem_New0(unsigned int size)
5732 {
5733    return _calloc(1,size);
5734 }
5735
5736 public dllexport void eSystem_Delete(void * memory)
5737 {
5738    if(memory)
5739       _free(memory);
5740 }
5741
5742 // Properties
5743 public dllexport void eInstance_FireSelfWatchers(Instance instance, Property _property)
5744 {
5745    if(instance && _property && _property.selfWatchable)
5746    {
5747       Class _class;
5748       for(_class = instance._class; _class; _class = _class.base)
5749       {
5750          SelfWatcher selfWatcher, next;
5751          for(selfWatcher = _class.selfWatchers.first; selfWatcher; selfWatcher = next)
5752          {
5753             next = selfWatcher.next;
5754             if(selfWatcher._property == _property)
5755                selfWatcher.callback(instance);
5756          }
5757       }
5758    }
5759 }
5760
5761 public dllexport void eInstance_FireWatchers(Instance instance, Property _property)
5762 {
5763    if(instance && _property && _property.isWatchable)
5764    {
5765       OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
5766       Watcher watcher, next;
5767
5768       for(watcher = watchers->first; watcher; watcher = next)
5769       {
5770          next = watcher.next;
5771          watcher.callback(watcher.object, instance);
5772       }
5773    }
5774 }
5775
5776 public dllexport void eProperty_Watchable(Property _property)
5777 {
5778    if(!_property.isWatchable)
5779    {
5780       Class _class = _property._class;
5781       if(!_class.computeSize)
5782       {
5783          _property.watcherOffset = _class.structSize;
5784          _class.structSize += sizeof(OldList);
5785
5786          // highly inefficient
5787          FixDerivativesBase(_class, _class);
5788       }
5789       _property.isWatchable = true;
5790    }
5791 }
5792
5793 public dllexport void eClass_DestructionWatchable(Class _class)
5794 {
5795    if(!_class.destructionWatchOffset)
5796    {
5797       _class.destructionWatchOffset = _class.structSize;
5798       _class.structSize += sizeof(OldList);
5799       // highly inefficient
5800       FixDerivativesBase(_class, _class);
5801    }
5802 }
5803
5804 public dllexport void eProperty_SelfWatch(Class _class, char * name, void (*callback)(void *))
5805 {
5806    if(_class)
5807    {
5808       Property _property = eClass_FindProperty(_class, name, _class.module);
5809       
5810       if(!_property)
5811          _property = eClass_AddProperty(_class, name, null, null, null, baseSystemAccess /*privateAccess*/);
5812       _class.selfWatchers.Add(SelfWatcher { _property = _property, callback = callback });
5813       _property.selfWatchable = true;
5814    }
5815 }
5816
5817 public dllexport void eInstance_Watch(void * instance, Property _property, void * object, void (*callback)(void *, void *))
5818 {
5819    if(_property.isWatchable)
5820    {
5821       OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
5822       watchers->Add(Watcher { callback = callback, object = object });
5823    }
5824 }
5825
5826 public dllexport void eInstance_WatchDestruction(Instance instance, Instance object, void (*callback)(Instance, Instance))
5827 {
5828    OldList * watchers = (OldList *)((byte *)instance + instance._class.destructionWatchOffset);
5829    watchers->Add(Watcher { callback = callback, object = object });
5830 }
5831
5832 public dllexport void eInstance_StopWatching(Instance instance, Property _property, Instance object)
5833 {
5834    if(instance && (!_property || _property.isWatchable))
5835    {
5836       if(_property)
5837       {
5838          OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
5839          Watcher watcher;
5840          for(watcher = watchers->first; watcher; watcher = watcher.next)
5841             if(watcher.object == object)
5842             {
5843                watchers->Delete(watcher);
5844                break;
5845             }
5846       }
5847       else
5848       {
5849          // Stop watching all properties as well as destruction
5850          Class _class, base;
5851          for(_class = instance._class; _class; _class = base)
5852          {
5853             if(_class.destructionWatchOffset)
5854             {
5855                OldList * watchers = (OldList *)((byte *)instance + _class.destructionWatchOffset);
5856                Watcher watcher;
5857
5858                for(watcher = watchers->first; watcher; watcher = watcher.next)
5859                {
5860                   watchers->Delete(watcher);
5861                   break;
5862                }
5863             }
5864             for(_property = (Property)_class.membersAndProperties.first; _property; _property = _property.next)
5865             {
5866                if(_property.isProperty && _property.isWatchable)
5867                {
5868                   OldList * watchers = (OldList *)((byte *)instance + _property.watcherOffset);
5869                   Watcher watcher;
5870                   for(watcher = watchers->first; watcher; watcher = watcher.next)
5871                      if(watcher.object == object)
5872                      {
5873                         watchers->Delete(watcher);
5874                         break;
5875                      }
5876                }
5877             }
5878             base = _class.base;
5879             if(base && base.type == systemClass) base = null;
5880          }
5881       }
5882    }
5883 }
5884
5885 public dllexport subclass(ClassDesignerBase) eClass_GetDesigner(Class _class)
5886 {
5887    for(;_class;_class = _class.base)
5888    {
5889       if(_class.designerClass)
5890          return (subclass(ClassDesignerBase))eSystem_FindClass(_class.module, _class.designerClass);
5891    }
5892    return null;
5893 }
5894
5895
5896 public dllexport subclass(ClassDesignerBase) eInstance_GetDesigner(Instance instance)
5897 {
5898    if(instance)
5899       return eClass_GetDesigner(instance._class);
5900    return null;
5901 }
5902
5903 public bool LocateModule(char * name, char * fileName)
5904 {
5905    return Instance_LocateModule(name, fileName);
5906 }
5907
5908 static void LoadCOM(Module module)
5909 {
5910    bool force64Bits = (module.application.isGUIApp & 2) ? true : false;
5911    bool force32Bits = (module.application.isGUIApp & 4) ? true : false;
5912    bool inCompiler = (module.application.isGUIApp & 8) ? true : false;
5913    int pointerSize = force64Bits ? 8 : force32Bits ? 4 : sizeof(void *);
5914    Class applicationClass;
5915    Class enumClass, structClass, boolClass;
5916    Class moduleClass;
5917
5918    // Create Base Class
5919    Class baseClass = eSystem_RegisterClass(normalClass, "class", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
5920    baseClass.type = systemClass;
5921    baseClass.memberOffset = 0;
5922    baseClass.offset = 0;
5923    baseClass.structSize = 0;
5924    baseClass.typeSize = 0;
5925
5926    {
5927       Class instanceClass = eSystem_RegisterClass(normalClass, "ecere::com::Instance", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
5928       // Instance should really be a Normal class, but inheritance checks for systemClass to see if something has a non system ancestor
5929       instanceClass.type = systemClass;
5930       instanceClass.fixed = true;
5931       instanceClass.memberOffset = 0;
5932       instanceClass.offset = 0;
5933
5934       instanceClass.memberID = -3;
5935       instanceClass.startMemberID = -3;
5936
5937       eClass_AddDataMember(instanceClass, "_vTbl", "int (**)()", pointerSize, pointerSize, publicAccess);
5938       eClass_AddDataMember(instanceClass, "_class", "ecere::com::Class", pointerSize, pointerSize, publicAccess);
5939       eClass_AddDataMember(instanceClass, "_refCount", "int", sizeof(int), sizeof(int), publicAccess);
5940    }
5941
5942    InitializeDataTypes1(module);
5943
5944    // Create Enum class
5945    enumClass = eSystem_RegisterClass(normalClass, "enum", null, 0, force64Bits ? 40 : sizeof(class EnumClassData), null, null, module, baseSystemAccess, publicAccess);
5946    eClass_AddClassProperty(enumClass, "enumSize", "int", null, GetEnumSize).constant = true;
5947    enumClass.type = systemClass;
5948    
5949    delete enumClass.dataTypeString;
5950    enumClass.dataTypeString = CopyString(/*"unsigned int"*/"int");
5951
5952    // Create Struct (simple) class
5953    //structClass = eSystem_RegisterClass(structClass, "struct", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
5954    structClass = eSystem_RegisterClass(normalClass, "struct", null, 0, 0, null, null, module, baseSystemAccess, publicAccess);
5955    structClass.type = systemClass;
5956    structClass.memberOffset = 0;
5957    structClass.offset = 0;
5958    structClass.structSize = 0;
5959    structClass.typeSize = 0;
5960
5961    //eClass_AddMethod(enumClass, "AddValue", "int()", eEnum_AddValue);
5962    //eClass_AddMethod(enumClass, "AddFixedValue", "void()", eEnum_AddFixedValue);
5963
5964    InitializeDataTypes(module);
5965
5966    // Create bool class
5967    boolClass = eSystem_RegisterClass(ClassType::enumClass, "bool", "uint", 0, 0, null, null, module, baseSystemAccess, publicAccess);
5968    eEnum_AddFixedValue(boolClass, "true",  bool::true);
5969    eEnum_AddFixedValue(boolClass, "false", bool::false);
5970
5971    // Create Module class
5972    moduleClass = eSystem_RegisterClass(normalClass, "ecere::com::Module", null, force64Bits ? 8 + 32 + 32 + 32 + 32 + 8 + 8 + 8 + 8 + 8 + 4 + 4 + (32 + 8 + 8 + 4*32) + (32 + 8 + 8 + 4*32) :
5973                                                                                 sizeof(struct Module), 0, (void *)Module_Constructor, (void *)Module_Destructor, module, baseSystemAccess, publicAccess);
5974    eClass_AddVirtualMethod(moduleClass, "OnLoad", "bool()", null, publicAccess);
5975    eClass_AddVirtualMethod(moduleClass, "OnUnload", "void()", null, publicAccess);
5976    eClass_AddMethod(moduleClass, "Load", "Module(char * name, AccessMode importAccess)", eModule_Load, publicAccess);
5977    eClass_AddMethod(moduleClass, "Unload", "void(Module module)", eModule_Unload, publicAccess);
5978    eClass_AddDataMember(moduleClass, "application", "Application", pointerSize, pointerSize, publicAccess);
5979    eClass_AddDataMember(moduleClass, "classes", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
5980    eClass_AddDataMember(moduleClass, "defines", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
5981    eClass_AddDataMember(moduleClass, "functions", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
5982    eClass_AddDataMember(moduleClass, "modules", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
5983    eClass_AddDataMember(moduleClass, "prev", "Module", pointerSize, pointerSize, publicAccess);
5984    eClass_AddDataMember(moduleClass, "next", "Module", pointerSize, pointerSize, publicAccess);
5985    eClass_AddDataMember(moduleClass, "name", "char *", pointerSize, pointerSize, publicAccess);
5986    eClass_AddDataMember(moduleClass, "library", "void *", pointerSize, pointerSize, publicAccess);
5987    eClass_AddDataMember(moduleClass, "Unload", "void *", pointerSize, pointerSize, publicAccess);
5988    eClass_AddDataMember(moduleClass, "importType", "ImportType", sizeof(ImportType), 4, publicAccess);
5989    eClass_AddDataMember(moduleClass, "origImportType", "ImportType", sizeof(ImportType), 4, publicAccess);
5990    eClass_AddDataMember(moduleClass, "privateNameSpace", "NameSpace", force64Bits ? (32 + 8 + 8 + 4*32) : force32Bits ? (16 + 4 + 4 + 4*16) : sizeof(NameSpace), pointerSize, publicAccess);
5991    eClass_AddDataMember(moduleClass, "publicNameSpace", "NameSpace",  force64Bits ? (32 + 8 + 8 + 4*32) : force32Bits ? (16 + 4 + 4 + 4*16) : sizeof(NameSpace), pointerSize, publicAccess);
5992    moduleClass.fixed = true;
5993    moduleClass.count++;
5994    if(inCompiler && force32Bits)
5995       moduleClass.structSize = 12 + 4 + 20 + 20 + 20 + 20 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + (16 + 4 + 4 + 4*16) + (16 + 4 + 4 + 4*16);
5996    
5997    // Create Application class
5998    applicationClass = eSystem_RegisterClass(normalClass, "ecere::com::Application", "Module", force64Bits ? (8+8+4+4 + 32 + 8 + 176) : sizeof(struct Application), 0, null, (void *)Application_Destructor, module, baseSystemAccess, publicAccess);
5999    if(inCompiler && force32Bits)
6000    {
6001       applicationClass.offset = 12 + 4 + 20 + 20 + 20 + 20 + 4 + 4 + 4 + 4 + 4 + 4 + 4 + (16 + 4 + 4 + 4*16) + (16 + 4 + 4 + 4*16);
6002       applicationClass.structSize = applicationClass.offset + (4+4+4+4 + 20 + 4 + 88);
6003    }
6004    eClass_AddVirtualMethod(applicationClass, "Main", "void()", null, publicAccess);
6005    eClass_AddDataMember(applicationClass, "argc", "int", sizeof(int), 4, publicAccess);
6006    eClass_AddDataMember(applicationClass, "argv", "char **", pointerSize, pointerSize, publicAccess);
6007    eClass_AddDataMember(applicationClass, "exitCode", "int", sizeof(int), 4, publicAccess);
6008    eClass_AddDataMember(applicationClass, "isGUIApp", "bool", sizeof(bool), 4, publicAccess);
6009    eClass_AddDataMember(applicationClass, "allModules", "OldList", force64Bits ? 32 : force32Bits ? 20 : sizeof(OldList), pointerSize, publicAccess);
6010    eClass_AddDataMember(applicationClass, "parsedCommand", "char *", pointerSize, pointerSize, publicAccess);
6011    eClass_AddDataMember(applicationClass, "systemNameSpace", "NameSpace", force64Bits ? (32 + 8 + 8 + 4*32) : force32Bits ? (16 + 4 + 4 + 4*16) : sizeof(NameSpace), pointerSize, publicAccess);
6012    applicationClass.fixed = true;
6013    applicationClass.count++;
6014
6015    //AttachConsole(-1);
6016    //AllocConsole();
6017
6018    // --- Math ---
6019    eSystem_RegisterFunction("sin", "double sin(Angle number)", sin, module, baseSystemAccess);
6020    eSystem_RegisterFunction("sinh", "double sinh(Angle number)", sinh, module, baseSystemAccess);
6021    eSystem_RegisterFunction("cosh", "double cosh(Angle number)", cosh, module, baseSystemAccess);
6022    eSystem_RegisterFunction("tanh", "double tanh(Angle number)", tanh, module, baseSystemAccess);
6023    eSystem_RegisterFunction("sqrt", "double sqrt(double number)", sqrt, module, baseSystemAccess);
6024    eSystem_RegisterFunction("cos", "double cos(Angle number)", cos, module, baseSystemAccess);
6025    eSystem_RegisterFunction("tan", "double tan(Angle number)", tan, module, baseSystemAccess);
6026    eSystem_RegisterFunction("atan2", "Angle atan2(double y, double x)", atan2, module, baseSystemAccess);
6027    eSystem_RegisterFunction("asin", "Angle asin(double number)", asin, module, baseSystemAccess);
6028    eSystem_RegisterFunction("acos", "Angle acos(double number)", acos, module, baseSystemAccess);
6029    eSystem_RegisterFunction("atan", "Angle atan(double number)", atan, module, baseSystemAccess);
6030    eSystem_RegisterFunction("pow", "double pow(double number, double number2)", pow, module, baseSystemAccess);
6031    eSystem_RegisterFunction("fmod", "double fmod(double x, double y)", fmod, module, baseSystemAccess);
6032    eSystem_RegisterFunction("fabs", "double fabs(double number)", fabs, module, baseSystemAccess);
6033    eSystem_RegisterFunction("log", "double log(double number)", log, module, baseSystemAccess);
6034    eSystem_RegisterFunction("log10", "double log10(double number)", log10, module, baseSystemAccess);
6035    eSystem_RegisterFunction("ceil", "double ceil(double number)", ceil, module, baseSystemAccess);
6036    eSystem_RegisterFunction("floor", "double floor(double number)", floor, module, baseSystemAccess);
6037    eSystem_RegisterFunction("exp", "double exp(double number)", exp, module, baseSystemAccess);
6038
6039    // --- Stdlib ---
6040    eSystem_RegisterFunction("qsort", "void qsort(void *, uintsize, uintsize, int (*)(void *, void *))", qsort, module, baseSystemAccess);
6041    eSystem_RegisterFunction("strtod", "double strtod(char*, char**)", strtod, module, baseSystemAccess);
6042    eSystem_RegisterFunction("strtol", "int strtol(char*, char**, int base)", strtol, module, baseSystemAccess);
6043    eSystem_RegisterFunction("system", "int system(const char*)", system, module, baseSystemAccess);
6044    eSystem_RegisterFunction("atoi", "int atoi(const char*)", atoi, module, baseSystemAccess);
6045    eSystem_RegisterFunction("atof", "float atof(const char*)", atof, module, baseSystemAccess);
6046    eSystem_RegisterFunction("tolower", "int tolower(int)", tolower, module, baseSystemAccess);
6047    eSystem_RegisterFunction("toupper", "int toupper(int)", toupper, module, baseSystemAccess);
6048    eSystem_RegisterFunction("isdigit", "bool isdigit(int)", isdigit, module, baseSystemAccess);
6049    eSystem_RegisterFunction("memset", "void * memset(void * area, int value, uintsize count)", memset, module, baseSystemAccess);
6050    eSystem_RegisterFunction("getenv", "char * getenv(const char * name)", getenv, module, baseSystemAccess);
6051    eSystem_RegisterFunction("rename", "int rename(const char *oldpath, const char *newpath)", rename, module, baseSystemAccess);
6052
6053    // --- String --- (These might move to the string class)
6054    eSystem_RegisterFunction("strlen", "uintsize strlen(const char *)", strlen, module, baseSystemAccess);
6055    eSystem_RegisterFunction("strcat", "char * strcat(char *, const char *)", strcat, module, baseSystemAccess);
6056    eSystem_RegisterFunction("strncat", "char * strncat(char *, const char *, uintsize n)", strncat, module, baseSystemAccess);
6057    eSystem_RegisterFunction("strchr", "char * strchr(const char *, int)", strchr, module, baseSystemAccess);
6058    eSystem_RegisterFunction("strstr", "char * strstr(const char *, const char *)", strstr, module, baseSystemAccess);
6059
6060    eSystem_RegisterDefine("fstrcmp", "(GetRuntimePlatform() == win32) ? strcmpi : strcmp", module, baseSystemAccess);
6061
6062 //#if defined(__GNUC__)
6063    eSystem_RegisterDefine("strcmpi", "strcasecmp", module, baseSystemAccess);
6064    eSystem_RegisterDefine("strnicmp", "strncasecmp", module, baseSystemAccess);
6065    eSystem_RegisterFunction("strcasecmp", "int strcasecmp(const char *, const char *)", strcmpi, module, baseSystemAccess);
6066    eSystem_RegisterFunction("strncasecmp", "int strncasecmp(const char *, const char *, uintsize n)", strnicmp, module, baseSystemAccess);
6067 /*
6068 #else
6069    eSystem_RegisterDefine("strcasecmp", "strcmpi", module, baseSystemAccess);
6070    eSystem_RegisterDefine("strncasecmp", "strnicmp", module, baseSystemAccess);
6071    eSystem_RegisterFunction("strcmpi", "int strcmpi(const char *, const char *)", strcmpi, module, baseSystemAccess);
6072    eSystem_RegisterFunction("strnicmp", "int strnicmp(const char *, const char *, int n)", strnicmp, module, baseSystemAccess);
6073 #endif
6074 */
6075
6076    eSystem_RegisterFunction("strcmp", "int strcmp(const char *, const char *)", strcmp, module, baseSystemAccess);
6077    eSystem_RegisterFunction("strncmp", "int strncmp(const char *, const char *, uintsize n)", strncmp, module, baseSystemAccess);
6078    eSystem_RegisterFunction("strlwr", "char * strlwr(char *)", strlwr, module, baseSystemAccess);
6079    eSystem_RegisterFunction("strupr", "char * strupr(char *)", strupr, module, baseSystemAccess);
6080    eSystem_RegisterFunction("strcpy", "char * strcpy(char *, const char *)", strcpy, module, baseSystemAccess);
6081    eSystem_RegisterFunction("strncpy", "char * strncpy(char *, const char *, uintsize n)", strncpy, module, baseSystemAccess);
6082    eSystem_RegisterFunction("memcpy", "void * memcpy(void *, const void *, uintsize size)", memcpy, module, baseSystemAccess);
6083    eSystem_RegisterFunction("memmove", "void * memmove(void *, const void *, uintsize size)", memmove, module, baseSystemAccess);
6084
6085    // --- Stdio ---
6086    eSystem_RegisterFunction("sprintf", "int sprintf(char *, char *, ...)", sprintf, module, baseSystemAccess);
6087    eSystem_RegisterFunction("snprintf", "int sprintf(char *, uintsize, char *, ...)", snprintf, module, baseSystemAccess);
6088    eSystem_RegisterFunction("printf", "int printf(char *, ...)", printf, module, baseSystemAccess);
6089    eSystem_RegisterFunction("vsprintf", "int vsprintf(char*, const char*, __builtin_va_list)", vsprintf, module, baseSystemAccess);
6090    eSystem_RegisterFunction("vsnprintf", "int vsnprintf(char*, uintsize, const char*, __builtin_va_list)", vsnprintf, module, baseSystemAccess);
6091    eSystem_RegisterFunction("puts", "int puts(char *)", puts, module, baseSystemAccess);
6092    eSystem_RegisterFunction("fputs", "int fputs(char *, void * stream)", fputs, module, baseSystemAccess);
6093
6094    // --- Ctype ---
6095    eSystem_RegisterFunction("isalnum", "int isalnum(int c)", isalnum, module, baseSystemAccess);
6096    eSystem_RegisterFunction("isspace", "int isspace(int c)", isspace, module, baseSystemAccess);
6097    eSystem_RegisterFunction("isalpha", "int isalpha(int c)", isalpha, module, baseSystemAccess);
6098    eSystem_RegisterFunction("islower", "int islower(int c)", islower, module, baseSystemAccess);
6099    eSystem_RegisterFunction("isupper", "int isupper(int c)", isupper, module, baseSystemAccess);
6100    eSystem_RegisterFunction("isprint", "int isprint(int c)", isprint, module, baseSystemAccess);
6101    eSystem_RegisterFunction("strtoul", "unsigned long strtoul(const char * nptr, char ** endptr, int base)", strtoul, module, baseSystemAccess);
6102
6103 }
6104
6105 public dllexport Application __ecere_COM_Initialize(bool guiApp, int argc, char * argv[])
6106 {
6107    Application app;
6108
6109 #ifdef __ANDROID__
6110    // Clean up global variables
6111    memoryInitialized = false;
6112    pools = null;
6113 #ifdef MEMINFO
6114    memset(&memStacks, 0, sizeof(BinaryTree));
6115    memoryErrorsCount = 0;
6116    memset(&memBlocks, 0, sizeof(BinaryTree));
6117    recurse = false;
6118    blockID = 0;
6119    allocateClass = null;
6120    allocateInternal = false;
6121    TOTAL_MEM = 0;
6122    OUTSIDE_MEM = 0;
6123 #endif
6124 #endif
6125
6126 #ifdef _DEBUG
6127    // printf("Using debug ecere runtime library\n");
6128 #endif
6129    app = _calloc(1, sizeof(class Application));
6130
6131    Module_Constructor(app);
6132    app.systemNameSpace.classes.CompareKey = (void *)BinaryTree::CompareString;
6133    app.systemNameSpace.defines.CompareKey = (void *)BinaryTree::CompareString;
6134    app.systemNameSpace.functions.CompareKey = (void *)BinaryTree::CompareString;
6135    app.systemNameSpace.nameSpaces.CompareKey = (void *)BinaryTree::CompareString;
6136
6137    Instance_COM_Initialize(argc, argv, &app.parsedCommand, &app.argc, &app.argv);
6138
6139    app.application = app;
6140    app.allModules.offset = sizeof(class Instance) + (uint)&((struct Module *)0)->prev;
6141    app.isGUIApp = guiApp;
6142
6143    LoadCOM(app);
6144
6145    app._class = eSystem_FindClass(app, "Application");
6146
6147    return app;
6148 }
6149
6150 public dllexport ClassTemplateParameter eClass_AddTemplateParameter(Class _class, char * name, TemplateParameterType type, void * info, ClassTemplateArgument defaultArg)
6151 {
6152    if(_class && name)
6153    {
6154       ClassTemplateParameter param;
6155
6156       for(param = _class.templateParams.first; param; param = param.next)
6157       {
6158          if(!strcmp(param.name, name))
6159             return param;
6160       }
6161       param =
6162       {
6163          name = CopyString(name);
6164          type = type;
6165          (type == identifier) ? info : CopyString(info);
6166       };
6167       if(defaultArg != null) 
6168       {
6169          param.defaultArg = defaultArg;
6170          CopyTemplateArg(param, param.defaultArg);
6171       }
6172       _class.templateParams.Add(param);
6173       return param;
6174    }
6175    return null;
6176 }
6177
6178 public dllexport void eClass_DoneAddingTemplateParameters(Class base)
6179 {
6180    if(base)
6181    {
6182       OldLink derivative;
6183       ClassTemplateParameter param;
6184       {
6185          void * first = base.templateParams.first;
6186          int count = base.templateParams.count;
6187          base.templateParams.first = null;
6188          base.templateParams.count = 0;
6189
6190          FreeTemplateArgs(base);
6191          delete base.templateArgs;
6192          FreeTemplatesDerivatives(base);
6193
6194          base.templateParams.first = first;
6195          base.templateParams.count = count;
6196       }
6197
6198       for(param = base.templateParams.first; param; param = param.next)
6199       {
6200          if(param.type == identifier && param.defaultArg.memberString)
6201          {
6202             Class memberClass = base;
6203             char * colon = strstr(param.defaultArg.memberString, "::");
6204             char * memberName;
6205             if(colon)
6206             {
6207                char className[1024];
6208                Class sClass;
6209
6210                memcpy(className, param.defaultArg.memberString, colon - param.defaultArg.memberString);
6211                className[colon - param.defaultArg.memberString] = '\0';
6212                memberName = colon + 2;
6213
6214                for(sClass = base; sClass; sClass = sClass.base)
6215                {
6216                   ClassTemplateParameter cParam;
6217                   Class nextClass;
6218                   int id = 0;
6219                   for(nextClass = sClass.base; nextClass; nextClass = nextClass.base) id += nextClass.templateParams.count;
6220                   // Safety! What could cause base.templateArgs to be null?
6221                   if(sClass == base || base.templateArgs)
6222                   {
6223                      for(cParam = sClass.templateParams.first; cParam; cParam = cParam.next)
6224                      {
6225                         if(cParam.type == type && !strcmp(cParam.name, className))
6226                            strcpy(className, (sClass == base) ? cParam.defaultArg.dataTypeString : base.templateArgs[id].dataTypeString);
6227                         id++;
6228                      }
6229                   }
6230                }
6231                memberClass = eSystem_FindClass(base.module, className);
6232                if(!memberClass)
6233                   memberClass = eSystem_FindClass(base.module.application, className);
6234             }
6235             else
6236                memberName = param.defaultArg.memberString;
6237
6238             if(memberClass)
6239             {
6240                switch(param.memberType)
6241                {
6242                   case dataMember:
6243                      param.defaultArg.member = eClass_FindDataMember(memberClass, memberName, memberClass.module, null, null);
6244                      break;
6245                   case method:
6246                      param.defaultArg.method = eClass_FindMethod(memberClass, memberName, memberClass.module);
6247                      break;
6248                   case prop:
6249                      param.defaultArg.prop = eClass_FindProperty(memberClass, memberName, memberClass.module);
6250                      break;
6251                }
6252             }
6253          }
6254       }      
6255
6256       //ComputeClassParameters(base, null, null);
6257
6258       FixDerivativesBase(base, base);
6259    }
6260 }
6261
6262 static void FreeTemplatesDerivatives(Class base)
6263 {
6264    OldLink derivative, templateLink;
6265    for(derivative = base.derivatives.first; derivative; derivative = derivative.next)
6266    {
6267       Class _class = derivative.data;
6268       if(_class.templateArgs)
6269       {
6270          FreeTemplateArgs(_class);
6271          delete _class.templateArgs;
6272       }
6273       FreeTemplatesDerivatives(_class);
6274    }
6275
6276    for(templateLink = base.templatized.first; templateLink; templateLink = templateLink.next)
6277    {
6278       Class _class = templateLink.data;
6279       if(_class.templateArgs)
6280       {
6281          FreeTemplateArgs(_class);
6282          delete _class.templateArgs;
6283       }
6284       FreeTemplatesDerivatives(_class);
6285    }
6286 }
6287
6288 static const char * platformNames[Platform] = { "", "win32", "linux", "apple" }; // how to have this be accessible outside of dll/lib
6289 static const Platform firstPlatform = win32;
6290 static const Platform lastPlatform = apple;
6291
6292 public enum Platform
6293 {
6294    unknown, win32, tux, apple;
6295
6296    property char *
6297    {
6298       get { return OnGetString(null, null, null); }
6299       set
6300       {  
6301          if(value)
6302          {
6303             Platform c;
6304             for(c = firstPlatform; c <= lastPlatform; c++)
6305                if(!strcmpi(value, platformNames[c]))
6306                   return c;
6307          }
6308          return unknown;
6309       }
6310    };
6311
6312    char * OnGetString(char * tempString, void * fieldData, bool * needClass)
6313    {
6314       if(this >= firstPlatform && this <= lastPlatform)
6315       {
6316          if(tempString)
6317             strcpy(tempString, platformNames[this]);
6318          return platformNames[this];
6319       }
6320       if(tempString && tempString[0])
6321          tempString[0] = '\0';
6322       return null;
6323    }
6324    
6325    bool OnGetDataFromString(char * string)
6326    {
6327       this = string;
6328       return (bool)this;
6329    }
6330 };
6331
6332 default extern Platform runtimePlatform;
6333
6334 public Platform GetRuntimePlatform()
6335 {
6336    return runtimePlatform;
6337 }
6338
6339 namespace gui;
6340
6341 class Window;
6342
6343 namespace com;
6344 // CLASS DESIGNER SUPPORT
6345
6346 public class ObjectInfo : struct
6347 {
6348 public:
6349    ObjectInfo prev, next;
6350    Instance instance;
6351    char * name;
6352    Instantiation instCode;
6353    bool deleted;
6354    ObjectInfo oClass;
6355    OldList instances;
6356    ClassDefinition classDefinition;
6357    bool modified;
6358 };
6359
6360 public class DesignerBase : Window
6361 {
6362 public:
6363    virtual bool FindObject(Instance * instance, char * string);
6364    virtual void RenameObject(ObjectInfo object, char * name);
6365    virtual void SelectObjectFromDesigner(ObjectInfo object);
6366    virtual void CodeAddObject(Instance instance, ObjectInfo * object);
6367    virtual void SheetAddObject(ObjectInfo object);
6368    virtual void AddToolBoxClass(Class _class);
6369    virtual void AddDefaultMethod(Instance instance, Instance classInstance);
6370    virtual void DeleteObject(ObjectInfo object);
6371    virtual bool ObjectContainsCode(ObjectInfo object);
6372    virtual void ModifyCode(void);
6373    virtual void UpdateProperties(void);
6374
6375    ClassDesignerBase classDesigner;
6376    char * objectClass;
6377    bool isDragging;
6378
6379    // FIX THIS WITH PUBLIC:
6380    property ClassDesignerBase classDesigner
6381    { 
6382       get { return classDesigner; }
6383       set { classDesigner = value; }
6384    };
6385    property char * objectClass
6386    { 
6387       get { return objectClass; }
6388       set { objectClass = value; }
6389    };
6390    property bool isDragging
6391    { 
6392       get { return isDragging; }
6393       set { isDragging = value; }
6394    };
6395 }
6396  
6397 public class ClassDesignerBase : Window
6398 {
6399 public:
6400    virtual void Reset(void);
6401    virtual void AddObject(void);
6402    virtual void SelectObject(ObjectInfo object, Instance control);
6403
6404    virtual void ListToolBoxClasses(DesignerBase designer);
6405
6406    virtual void ::PrepareTestObject(DesignerBase designer, Instance test);
6407    virtual void ::CreateObject(DesignerBase designer, Instance instance, ObjectInfo object, bool isClass, Instance _class);
6408    virtual void ::PostCreateObject(Instance instance, ObjectInfo object, bool isClass, Instance _class);
6409    virtual void ::DroppedObject(Instance instance, ObjectInfo object, bool isClass, Instance _class);
6410    virtual void ::DestroyObject(Instance object);
6411    virtual void ::FixProperty(Property prop, Instance object);
6412    virtual void ::CreateNew(EditBox editBox, Size clientSize, char * name, char * inherit);
6413 }
6414
6415 DesignerBase activeDesigner;
6416
6417 public void SetActiveDesigner(DesignerBase designer)
6418 {
6419    activeDesigner = designer;
6420 }
6421
6422 public DesignerBase GetActiveDesigner()
6423 {
6424    return activeDesigner;
6425 }
6426
6427 namespace sys;
6428
6429 // constants
6430 define LEAD_OFFSET      = 0xD800 - (0x10000 >> 10);
6431 define SURROGATE_OFFSET = 0x10000 - (0xD800 << 10) - 0xDC00;
6432
6433 public bool UTF8Validate(char * source)
6434 {
6435    if(source)
6436    {
6437       int c;
6438       for(c = 0; source[c];)
6439       {
6440          byte ch = source[c];
6441          unichar codePoint = 0;
6442          int numBytes = 1;
6443          int i;
6444          byte mask = 0x7F;
6445          if(ch & 0x80)
6446          {
6447             if(ch & 0x40)
6448             {
6449                mask >>= 2;
6450                numBytes++;
6451                if(ch & 0x20)
6452                {
6453                   numBytes++;
6454                   mask >>= 1;
6455                   if(ch & 0x10)
6456                   {
6457                      if(ch & 0x08)
6458                         return false;
6459                      numBytes++;
6460                      mask >>= 1;
6461                   }
6462                }
6463             }
6464             else
6465                return false;
6466          }
6467          for(i = 0; i<numBytes && (ch = source[c]); i++, c++)
6468          {
6469             codePoint <<= 6;
6470             codePoint |= ch & mask;
6471             mask = 0x3F;
6472             if(i > 1)
6473             {
6474                if(!(ch & 0x80) || (ch & 0x40))
6475                   return false;
6476             }
6477          }
6478          if(i < numBytes) return false;
6479
6480          if(codePoint > 0x10FFFF || (codePoint >= 0xD800 && codePoint <= 0xDFFF) || 
6481            (codePoint < 0x80 && numBytes > 1) || 
6482            (codePoint < 0x800 && numBytes > 2) || 
6483            (codePoint < 0x10000 && numBytes > 3))
6484             return false;
6485       }
6486    }
6487    return true;
6488 }
6489
6490 public int ISO8859_1toUTF8(char * source, char * dest, int max)
6491 {
6492    int c;
6493    int d = 0;
6494    for(c = 0; source[c]; c++)
6495    {
6496       unichar ch = ((byte *)source)[c];
6497       if(ch < 0x80)
6498       {
6499          if(d + 1 >= max) break;
6500          dest[d++] = (char)ch;
6501       }
6502       else if(ch < 0x800)
6503       {
6504          if(d + 2 >= max) break;
6505          dest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
6506          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6507       }
6508       else if(ch < 0x10000)
6509       {
6510          if(d + 3 >= max) break;
6511          dest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
6512          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6513          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6514       }
6515       else
6516       {
6517          if(d + 4 >= max) break;
6518          dest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
6519          dest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
6520          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6521          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6522       }
6523    }
6524    dest[d] = 0;
6525    return d;
6526 }
6527
6528 public char * UTF16toUTF8(uint16 * source)
6529 {
6530    int c;
6531    int d = 0;
6532    int len;
6533    char * dest;
6534    uint16 u16;
6535    bool invert = false;
6536
6537    for(len = 0; source[len]; len++);
6538    dest = new char[len * 3 + 1];
6539    for(c = 0; (u16 = source[c]); c++)
6540    {
6541       unichar ch;
6542       if(!c && (u16 == 0xFFFE || u16 == 0xFEFF))
6543       {
6544          if(u16 == 0xFFFE) invert = true;
6545          continue;
6546       }
6547       if(invert) { u16 = ((u16 & 0xFF00) >> 8) | ((u16 & 0x00FF) << 8); }
6548       
6549       if(u16 < 0xD800 || u16 > 0xDBFF)
6550          ch = (unichar)u16;         
6551       else
6552          ch = ((unichar)u16 << 10) + source[c++] + SURROGATE_OFFSET;
6553                   
6554       if(ch < 0x80)
6555       {
6556          dest[d++] = (char)ch;
6557       }
6558       else if(ch < 0x800)
6559       {
6560          dest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
6561          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6562       }
6563       else if(ch < 0x10000)
6564       {
6565          dest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
6566          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6567          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6568       }
6569       else
6570       {
6571          dest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
6572          dest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
6573          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6574          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6575       }
6576    }
6577    dest[d] = 0;
6578    dest = renew dest char[d+1];
6579    return dest;
6580 }
6581
6582 public int UTF16toUTF8Buffer(uint16 * source, byte * dest, int max)
6583 {
6584    int c;
6585    int d = 0;
6586    uint16 u16;
6587    for(c = 0; (u16 = source[c]); c++)
6588    {
6589       unichar ch;
6590       if(u16 < 0xD800 || u16 > 0xDBFF)
6591          ch = (unichar)u16;         
6592       else
6593          ch = ((unichar)u16 << 10) + source[c++] + SURROGATE_OFFSET;
6594
6595       if(ch < 0x80)
6596       {
6597          if(d + 1 >= max) break;
6598          dest[d++] = (char)ch;
6599       }
6600       else if(ch < 0x800)
6601       {
6602          if(d + 2 >= max) break;
6603          dest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
6604          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6605       }
6606       else if(ch < 0x10000)
6607       {
6608          if(d + 3 >= max) break;
6609          dest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
6610          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6611          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6612       }
6613       else
6614       {
6615          if(d + 4 >= max) break;
6616          dest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
6617          dest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
6618          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6619          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6620       }
6621    }
6622    dest[d] = 0;
6623    return d;
6624 }
6625
6626 public unichar UTF8GetChar(char * string, int * numBytes)
6627 {
6628    unichar ch;
6629    byte b = ((byte *)string)[0];
6630    int i;
6631    byte mask = 0x7F;
6632    int nb = 1;
6633    ch = 0;
6634    if(b & 0x80)
6635    {
6636       if(b & 0x40)
6637       {
6638          mask >>= 2;
6639          nb++;
6640          if(b & 0x20)
6641          {
6642             nb++;
6643             mask >>= 1;
6644             if(b & 0x10)
6645             {
6646                if(b & 0x08) { nb = 0; }
6647                nb++;
6648                mask >>= 1;
6649             }
6650          }
6651       }
6652       else
6653          nb = 0;
6654    }
6655    for(i = 0; i<nb; i++)
6656    {
6657       ch <<= 6;
6658       ch |= (b = ((byte *)string)[i]) & mask;
6659       mask = 0x3F;
6660       if(i > 1 && (!(b & 0x80) || (b & 0x40)))
6661       {
6662          nb = 0;
6663          ch = 0;
6664       }
6665    }
6666
6667    if(i < nb || 
6668       ch > 0x10FFFF || (ch >= 0xD800 && ch <= 0xDFFF) || 
6669      (ch < 0x80 && nb > 1) || 
6670      (ch < 0x800 && nb > 2) || 
6671      (ch < 0x10000 && nb > 3))
6672    {
6673       ch = 0;
6674       nb = 0;
6675    }
6676    if(numBytes) *numBytes = nb;
6677    return ch;
6678 }
6679
6680 public int UTF8toUTF16Buffer(char * source, uint16 * dest, int max)
6681 {
6682    if(source)
6683    {
6684       int c;
6685       int d = 0;
6686       for(c = 0; source[c];)
6687       {
6688          byte ch = source[c];
6689          unichar codePoint = 0;
6690          int numBytes = 1;
6691          int i;
6692          byte mask = 0x7F;
6693          if(ch & 0x80 && ch & 0x40)
6694          {
6695             mask >>= 2;
6696             numBytes++;
6697             if(ch & 0x20)
6698             {
6699                numBytes++;
6700                mask >>= 1;
6701                if(ch & 0x10)
6702                {
6703                   numBytes++;
6704                   mask >>= 1;
6705                }
6706             }
6707          }
6708          for(i = 0; i<numBytes; i++)
6709          {
6710             codePoint <<= 6;
6711             codePoint |= source[c++] & mask;
6712             mask = 0x3F;
6713          }
6714
6715          if(codePoint > 0xFFFF)
6716          {
6717             uint16 lead = (uint16)(LEAD_OFFSET + (codePoint >> 10));
6718             uint16 trail = 0xDC00 + (uint16)(codePoint & 0x3FF);
6719             if(d >= max - 1) break;
6720             dest[d++] = lead;
6721             dest[d++] = trail;
6722          }
6723          else
6724          {
6725             if(d >= max) break;
6726             dest[d++] = (uint16)codePoint;
6727          }
6728       }
6729       dest[d] = 0;
6730       return d;
6731    }
6732    return 0;   
6733 }
6734
6735 public int UTF32toUTF8Len(unichar * source, int count, byte * dest, int max)
6736 {
6737    int c;
6738    int d = 0;
6739    uint32 ch;
6740    for(c = 0; c<count && (ch = source[c]); c++)
6741    {
6742       if(ch < 0x80)
6743       {
6744          if(d + 1 >= max) break;
6745          dest[d++] = (char)ch;
6746       }
6747       else if(ch < 0x800)
6748       {
6749          if(d + 2 >= max) break;
6750          dest[d++] = 0xC0 | (byte)((ch & 0x7C0) >> 6);
6751          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6752       }
6753       else if(ch < 0x10000)
6754       {
6755          if(d + 3 >= max) break;
6756          dest[d++] = 0xE0 | (byte)((ch & 0xF000) >> 12);
6757          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6758          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6759       }
6760       else
6761       {
6762          if(d + 4 >= max) break;
6763          dest[d++] = 0xF0 | (byte)((ch & 0x1C0000) >> 18);
6764          dest[d++] = 0x80 | (byte)((ch & 0x3F000) >> 12);
6765          dest[d++] = 0x80 | (byte)((ch & 0xFC0) >> 6);
6766          dest[d++] = 0x80 | (byte)(ch & 0x03F);
6767       }
6768    }
6769    dest[d] = 0;
6770    return d;
6771 }
6772
6773 public uint16 * UTF8toUTF16(char * source, int * wordCount)
6774 {
6775    if(source)
6776    {
6777       int len = strlen(source);
6778       uint16 * dest = new uint16[len + 1];
6779       int c;
6780       int d = 0;
6781       for(c = 0; source[c];)
6782       {
6783          byte ch = source[c];
6784          unichar codePoint = 0;
6785          int numBytes = 1;
6786          int i;
6787          byte mask = 0x7F;
6788          if(ch & 0x80 && ch & 0x40)
6789          {
6790             mask >>= 2;
6791             numBytes++;
6792             if(ch & 0x20)
6793             {
6794                numBytes++;
6795                mask >>= 1;
6796                if(ch & 0x10)
6797                {
6798                   numBytes++;
6799                   mask >>= 1;
6800                }
6801             }
6802          }
6803          for(i = 0; i<numBytes; i++)
6804          {
6805             codePoint <<= 6;
6806             codePoint |= source[c++] & mask;
6807             mask = 0x3F;
6808          }
6809
6810          if(codePoint > 0xFFFF)
6811          {
6812             uint16 lead = (uint16)(LEAD_OFFSET + (codePoint >> 10));
6813             uint16 trail = 0xDC00 + (uint16)(codePoint & 0x3FF);
6814             dest[d++] = lead;
6815             dest[d++] = trail;
6816          }
6817          else
6818          {
6819             dest[d++] = (uint16)codePoint;
6820          }
6821       }
6822       dest[d] = 0;
6823       if(wordCount) *wordCount = d;
6824       return dest;
6825    }
6826    return null;
6827 }
6828
6829 namespace com;