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