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