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