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