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