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