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