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