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