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