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