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