ide/CodeEditor,FindInFilesDialog: Took out setting maxLineSize on EditBoxes
[sdk] / ide / src / designer / CodeEditor.ec
1 import "ide"
2
3 // *** Color Schemes ***
4
5 // *** The Old Color Scheme that was causing me auras and ophtalmic migraines -- Uncomment at your own risk! ***
6 /*
7 FontResource panelFont { $"Courier New", 10 };
8 FontResource codeFont { $"Courier New", 10 };
9 Color selectionColor = Color { 10, 36, 106 };
10 Color selectionText = white;
11 Color viewsBackground = white;
12 Color viewsText = black;
13 Color outputBackground = white;
14 Color outputText = black;
15 Color projectViewBackground = white;
16 Color projectViewText = black;
17 Color codeEditorBG = white;
18 Color codeEditorFG = black;
19 Color marginColor = Color {230, 230, 230};
20 Color selectedMarginColor = Color {200, 200, 200};
21 Color lineNumbersColor = Color {60, 60, 60};
22 SyntaxColorScheme colorScheme
23 {
24    keywordColors = [ blue, blue ];
25    commentColor = dimGray;
26    charLiteralColor = crimson;
27    stringLiteralColor = crimson;
28    preprocessorColor = green;
29    numberColor = teal;
30 };
31 */
32
33 // The new nice dark scheme -- so peaceful on my brain
34
35 FontResource panelFont { $"Courier New", 10 };
36 FontResource codeFont { $"Courier New", 10 };
37 /*
38 FontResource panelFont { $"Consolas", 12 };
39 FontResource codeFont { $"Consolas", 12 };
40 */
41 Color selectionColor = lightYellow;
42 Color selectionText = Color { 30, 40, 50 };
43 Color viewsBackground = Color { 30, 40, 50 };
44 Color viewsText = lightGray;
45 Color outputBackground = black;
46 Color outputText = lime;
47 Color projectViewBackground = Color { 30, 40, 50 };
48 Color projectViewText = lightGray;
49 Color codeEditorBG = black;
50 Color codeEditorFG = ivory;
51 Color marginColor = Color {24, 24, 24};
52 Color selectedMarginColor = Color {64, 64, 64};
53 Color lineNumbersColor = Color {160, 160, 160};
54 SyntaxColorScheme colorScheme
55 {
56    keywordColors = [ skyBlue, skyBlue ];
57    commentColor = Color { 125, 125, 125 };
58    charLiteralColor = Color { 245, 50, 245 };
59    stringLiteralColor = Color { 245, 50, 245 };
60    preprocessorColor = { 120, 220, 140 };
61    numberColor = Color {   0, 192, 192 };
62 };
63
64 // *********************
65
66 import "findCtx"
67 import "findExp"
68 import "findParams"
69
70 // UNTIL IMPLEMENTED IN GRAMMAR
71 #define ACCESS_CLASSDATA(_class, baseClass) \
72    (_class ? ((void *)(((char *)_class.data) + baseClass.offsetClass)) : null)
73
74 #ifdef ECERE_STATIC
75 extern int __attribute__((__stdcall__)) __ecereDll_Load_ecere(struct __ecereNameSpace__ecere__com__Instance * module);
76 extern int __attribute__((__stdcall__)) __ecereDll_Unload_ecere(struct __ecereNameSpace__ecere__com__Instance * module);
77 #endif
78
79 static Array<FileFilter> fileFilters
80 { [
81    { $"C/C++/eC Files (*.ec, *.eh, *.c, *.cpp, *.cc, *.cxx, *.h, *.hpp, *.hh, *.hxx)", "ec, eh, c, cpp, cc, cxx, h, hpp, hh, hxx" },
82    { $"Header Files for C/C++ (*.eh, *.h, *.hpp, *.hh, *.hxx)", "eh, h, hpp, hh, hxx" },
83    { $"C/C++/eC Source Files (*.ec, *.c, *.cpp, *.cc, *.cxx)", "ec, c, cpp, cc, cxx" },
84    { $"Text files (*.txt)", "txt" },
85    { $"All files", null }
86 ] };
87
88 static Array<FileType> fileTypes
89 { [
90    { $"eC Source Code", "ec", whenNoneGiven },
91    { $"Text Files", "txt", never }
92 ] };
93
94 static char * iconNames[] = 
95 {
96    "<:ecere>constructs/class.png",
97    "<:ecere>constructs/data.png",
98    "<:ecere>constructs/method.png",
99    "<:ecere>constructs/event.png",
100    "<:ecere>constructs/property.png",
101    "<:ecere>constructs/namespace.png",
102    "<:ecere>constructs/dataType.png",
103    "<:ecere>constructs/enumValue.png",
104    "<:ecere>constructs/dataPrivate.png",
105    "<:ecere>constructs/methodPrivate.png",
106    "<:ecere>constructs/propertyPrivate.png"
107 };
108
109 enum SheetType { methods, properties };
110
111 extern int __ecereVMethodID_class_OnEdit;
112 extern int __ecereVMethodID_class_OnDisplay;
113 extern int __ecereVMethodID_class_OnGetString;
114 extern int __ecereVMethodID_class_OnFree;
115 extern int __ecereVMethodID_class_OnCompare;
116 extern int __ecereVMethodID_class_OnCopy;
117 extern int __ecereVMethodID_class_OnSaveEdit;
118 extern int __ecereVMethodID___ecereNameSpace__ecere__com__Module_OnLoad;
119
120 class EditFileDialog : FileDialog
121 {
122    bool OnCreate()
123    {
124       if(!ide.projectView && ideSettings.ideFileDialogLocation)
125          currentDirectory = ideSettings.ideFileDialogLocation;
126       return FileDialog::OnCreate();
127    }
128 }
129
130 EditFileDialog codeEditorFileDialog
131 {
132    type = multiOpen, text = $"Open",
133    types = fileTypes.array, sizeTypes = fileTypes.count * sizeof(FileType);
134    filters = fileFilters.array, sizeFilters = fileFilters.count * sizeof(FileFilter)
135 };
136
137 EditFileDialog codeEditorFormFileDialog
138 {
139    type = open, text = $"Open Project",
140    types = fileTypes.array, sizeTypes = fileTypes.count * sizeof(FileType),
141    filters = fileFilters.array, sizeFilters = fileFilters.count * sizeof(FileFilter)
142 };
143
144 define OpenBracket = '{';
145 define CloseBracket = '}';
146
147 enum MethodAction
148 {
149    actionAddMethod = 1, 
150    actionDeleteMethod = 2, 
151    actionDetachMethod = 3, 
152    actionAttachMethod = 4, 
153    actionReattachMethod = 5
154 };
155
156 //extern StatusField pos, ovr, caps, num;
157 //extern Class thisClass;
158
159 File output;
160
161 File fileInput;
162
163 bool parseError = false;
164
165 int returnCode;
166
167 Class insideClass;
168 Expression ctxInsideExp;
169 Expression paramsInsideExp;
170 ClassFunction insideFunction;
171 ClassDef insideDef;
172 Type instanceType;
173 char * instanceName;
174 Type functionType;
175 int paramsID;
176 bool insideInstance;
177
178 /****************************************************************************
179                               GENERATING
180 ****************************************************************************/
181
182 static void OutputString(File f, char * string)
183 {
184    int c;
185    for(c = 0; string[c]; c++)
186    {
187       if(string[c] == '\"')
188          f.Puts("\\\"");
189       else if(string[c] == '\\')
190          f.Puts("\\\\");
191       else
192          f.Putc(string[c]);
193    }                              
194 }
195
196 void OutputType(File f, Type type, bool outputName)
197 {
198    if(type)
199    {
200       switch(type.kind)
201       {
202          case voidType:
203             f.Printf("void");
204             break;
205          case charType:
206             if(!type.isSigned) f.Printf("unsigned ");
207             f.Printf("char");
208             break;
209          case shortType:
210             if(!type.isSigned) f.Printf("unsigned ");
211             f.Printf("short");
212             break;
213          case intType:
214             if(!type.isSigned) f.Printf("unsigned ");
215             f.Printf("int");
216             break;
217          case int64Type:
218             if(!type.isSigned) f.Printf("unsigned ");
219             f.Printf("__int64");
220             break;
221          case longType:
222             if(!type.isSigned) f.Printf("unsigned ");
223             f.Printf("long");
224             break;
225          case floatType:
226             f.Printf("float");
227             break;
228          case doubleType:
229             f.Printf("double");
230             break;
231          case classType:
232             // ADD CODE TO DECIDE WHETHER TO OUTPUT FULLY QUAlIFIED OR NOT:
233             f.Printf(type._class.shortName ? type._class.shortName : type._class.string);
234             break;
235          case structType:
236             break;
237          case unionType:
238             break;
239          case functionType:
240             break;
241          case arrayType:
242             OutputType(f, type.type, false);
243             break;
244          case pointerType:
245             OutputType(f, type.type, false);
246             f.Printf(" *");
247             break;
248          case ellipsisType:
249             f.Printf("...");
250             break;
251          case enumType:
252             break;
253          case methodType:
254             break;
255       }
256       if(outputName)
257       {
258          if(type.name)
259          {
260             f.Printf(" ");
261             f.Printf(type.name);
262          }
263       }
264       if(type.kind == arrayType)
265       {
266          f.Printf("[");
267          f.Printf("%d", type.arraySize);
268          f.Printf("]");
269       }
270    }
271 }
272
273 void DeleteJunkBefore(EditBoxStream f, int pos, int * position)
274 {
275    char ch;
276    int before = 0;
277    
278    if(position)
279       f.Seek(pos - *position, current);
280                                                       
281    // Try to delete spaces and \n before...
282    f.Seek(-1, current);
283    for(;f.Getc(&ch);)
284    {
285       if(!isspace(ch))
286          break;
287       /*else if(ch == '\n')
288       {
289          // Look for // comments on the line before
290          EditBox editBox = f.editBox;
291          EditLine line = editBox.line;
292          char * text;
293          char last = 0;
294          int c;
295          bool quoted = false;
296          line = line.prev;
297          text = line.text;
298          for(c = 0; text[c]; c++)
299          {
300             if(text[c] == '"')
301             {
302                quoted ^= true;
303                last = 0;
304             }
305             else if(!quoted)
306             {
307                if(text[c] == '/' && last == '/')
308                   break;
309                last = text[c];
310             }
311          }
312          if(text[c])
313             break;
314       }*/
315       before++;
316       f.Seek(-2, current);
317    }
318
319    f.DeleteBytes(before);
320    if(position)
321       *position = pos;
322 }
323
324 void GetLocText(EditBox editBox, File f, int position, Location loc, char ** text, int * size, int pad, int linePad)
325 {
326    EditLine l1, l2;
327    int y1,x1, y2,x2;
328
329    editBox.GetSelPos(&l1, &y1, &x1, &l2, &y2, &x2, false);
330
331    // Cut & Paste function
332    
333    {
334       EditLine l1, l2;
335       int y1,x1,y2,x2;
336
337       f.Seek(loc.start.pos - position, current);
338       l1 = editBox.line;
339       x1 = editBox.charPos;
340       y1 = editBox.lineNumber;
341       f.Seek(loc.end.pos - loc.start.pos, current);
342       l2 = editBox.line;
343       x2 = editBox.charPos;
344       y2 = editBox.lineNumber;
345       editBox.SetSelPos(l1, y1, x1, l2, y2, x2);
346
347       *size = editBox.SelSize();
348       *text = new char[*size+1 + (y2-y1+1) * linePad + pad]; // Add pad for tabs and new name
349       editBox.GetSel(*text, false);
350    }
351    
352    editBox.SetSelPos(l1, y1, x1, l2, y2, x2);
353    f.Printf(""); // Make the stream point to where the editbox is
354 }
355
356 void Code_FixProperty(Property prop, Instance object)
357 {
358    Designer::FixProperty(prop, object);
359 }
360
361 bool Code_IsPropertyModified(Instance test, ObjectInfo selected, Property prop)
362 {
363    bool result = false;
364    if(prop.dataTypeString && (!prop.IsSet || prop.IsSet(selected.instance)))
365    {
366       Class dataType = prop.dataTypeClass;
367
368       if(!dataType)
369          dataType = prop.dataTypeClass = eSystem_FindClass(test._class.module, prop.dataTypeString);
370
371       if(dataType && dataType._vTbl && dataType.type == structClass)
372       {
373          void * dataForm = new0 byte[dataType.structSize];
374          void * dataTest = new0 byte[dataType.structSize];
375    
376          ((void (*)(void *, void *))(void *)prop.Get)(selected.instance, dataForm);
377          ((void (*)(void *, void *))(void *)prop.Get)(test, dataTest);
378
379          if((prop.IsSet && !prop.IsSet(test)) || ((int (*)(void *, void *, void *))(void *)dataType._vTbl[__ecereVMethodID_class_OnCompare])(dataType, dataForm, dataTest))
380          {
381             ((void (*)(void *, void *))(void *)prop.Set)(test, dataForm);
382             result = true;
383          }
384          delete dataForm;
385          delete dataTest;
386       }
387       else if(dataType && dataType._vTbl && (dataType.type == normalClass || dataType.type == noHeadClass))
388       {
389          void * dataForm, * dataTest;
390    
391          dataForm = ((void *(*)(void *))(void *)prop.Get)(selected.instance);
392          dataTest = ((void *(*)(void *))(void *)prop.Get)(test);
393    
394          if((prop.IsSet && !prop.IsSet(test)) || ((int (*)(void *, void *, void *))(void *)dataType._vTbl[__ecereVMethodID_class_OnCompare])(dataType, dataForm, dataTest))
395          {
396             ((void (*)(void *, void *))(void *)prop.Set)(test, dataForm);
397             result = true;
398          }
399       }
400       else if(dataType && dataType._vTbl)
401       {
402          DataValue dataForm, dataTest;
403    
404          GetProperty(prop, selected.instance, &dataForm);
405          GetProperty(prop, test, &dataTest);
406    
407          if((prop.IsSet && !prop.IsSet(test)) || ((int (*)(void *, void *, void *))(void *)dataType._vTbl[__ecereVMethodID_class_OnCompare])(dataType, &dataForm, &dataTest))
408          {
409             SetProperty(prop, test, dataForm);
410
411             // In case setting on test unset on real instance (e.g. isDefault)
412             if(strcmp(prop.name, "name"))
413             {
414                GetProperty(prop, selected.instance, &dataTest);
415                if(((int (*)(void *, void *, void *))(void *)dataType._vTbl[__ecereVMethodID_class_OnCompare])(dataType, &dataForm, &dataTest))
416                   SetProperty(prop, selected.instance, dataForm);
417             }
418             result = true;
419          }                                          
420       }
421    }
422    return result;
423 }
424
425 bool Code_IsPropertyDisabled(ObjectInfo selected, char * name)
426 {
427    bool disabled = false;
428    if(selected.oClass == selected)
429    {
430       ClassDef def;                  
431       if(selected.classDefinition)
432       {
433          for(def = selected.classDefinition.definitions->first; def; def = def.next)
434          {
435             if(def.type == defaultPropertiesClassDef)
436             {
437                MemberInit prop;
438                for(prop = def.defProperties->first; prop; prop = prop.next)
439                {
440                   if(prop.identifiers && prop.identifiers->first)
441                   {
442                      Identifier id = prop.identifiers->first;
443                      if(prop.variable && !strcmp(id.string, name))
444                      {
445                         disabled = true;
446                         break;
447                      }
448                   }
449                }
450             }
451             if(disabled) break;
452          }
453       }
454    }
455    else if(selected.instCode)
456    {
457       MembersInit members;
458       if(selected.instCode.members)
459       {
460          for(members = selected.instCode.members->first; members; members = members.next)
461          {
462             if(members.type == dataMembersInit && members.dataMembers)
463             {
464                MemberInit prop;
465                for(prop = members.dataMembers->first; prop; prop = prop.next)
466                {
467                   if(prop.identifiers && prop.identifiers->first)
468                   {
469                      Identifier id = prop.identifiers->first;
470                      if(prop.variable && !strcmp(id.string, name))
471                      {
472                         disabled = true;
473                         break;
474                      }
475                   }
476                }
477             }
478             if(disabled) break;
479          }
480       }
481    }
482    return disabled;
483 }
484
485 static bool CheckCompatibleMethod(Method method, Type type, Class regClass, bool isForm, Symbol selectedClass)
486 {
487    bool result = false;   
488    bool reset = false;
489    if(!method.dataType)
490       method.dataType = ProcessTypeString(method.dataTypeString, false);
491    if(!method.dataType.thisClass && !isForm)
492    {
493       reset = true;
494       method.dataType.thisClass = selectedClass;
495    }
496    //result = MatchTypes(method.dataType, type, null, regClass, regClass, false);
497    result = MatchTypes(type, method.dataType, null, regClass, regClass, false, true, true, false);
498    if(reset)
499       method.dataType.thisClass = null;
500    return result;
501 }
502
503 bool Code_IsFunctionEmpty(ClassFunction function, Method method, ObjectInfo object)
504 {
505    bool confirmation = true;
506    Statement body = function.body;
507    // Check if it contains any code
508    if((!body.compound.declarations || !body.compound.declarations->count) && (!body.compound.statements || body.compound.statements->count <= 1))
509    {
510       Class moduleClass = eSystem_FindClass(object.instance._class.module, "Module");
511       Statement stmt = body.compound.statements ? body.compound.statements->first : null;
512       Type dataType = method.dataType;
513       Type returnType = dataType.returnType;
514       Expression exp = null;
515
516       if(!method.dataType)
517          method.dataType = ProcessTypeString(method.dataTypeString, false);
518
519       confirmation = false;
520      
521       // Check if default function should be calling base class:
522       if(object.instance._class._vTbl[method.vid] == moduleClass._vTbl[__ecereVMethodID___ecereNameSpace__ecere__com__Module_OnLoad]) // Temp Check for DefaultFunction
523       {
524          if(returnType.kind != voidType)
525          {
526             if(!stmt || stmt.type != returnStmt || !stmt.expressions || stmt.expressions->count != 1)
527                confirmation = true;
528             else
529             {
530                exp = stmt.expressions->first;
531                if(returnType.kind == classType && !strcmp(returnType._class.string, "bool"))
532                {
533                   if( (exp.type != identifierExp || strcmp(exp.identifier.string, "true")) &&
534                       (exp.type != constantExp || strcmp(exp.constant, "1")))
535                      confirmation = true;
536                }
537                else
538                {
539                   if(exp.type != constantExp || strcmp(exp.constant, "0"))
540                      confirmation = true;
541                }
542             }
543          }
544          else
545          {
546             if(stmt)
547                confirmation = true;        
548          }
549       }
550       else
551       {
552          if(stmt)
553          {
554             if(returnType.kind != voidType)
555             {
556                if(stmt.type == returnStmt && stmt.expressions && stmt.expressions->count == 1)
557                   exp = stmt.expressions->first;
558             }
559             else if(stmt.type == expressionStmt && stmt.expressions && stmt.expressions->count == 1)
560                exp = stmt.expressions->first;
561          }
562
563          if(!exp || exp.type != callExp || exp.call.exp.type != identifierExp)
564             confirmation = true;        
565          else
566          {
567             Identifier id = exp.call.exp.identifier;
568             Class base = object.instance._class;
569             if(!id._class || (id._class.name && !strcmp(id._class.name, base.name)) || strcmp(id.string, method.name))
570                confirmation = true;
571             else
572             {
573                Expression arg = exp.call.arguments ? exp.call.arguments->first : null;
574                if(!arg || arg.type != identifierExp || strcmp("this", arg.identifier.string))
575                   confirmation = true;
576                else
577                {
578                   Type param;
579                   arg = arg.next;
580                   for(param = dataType.params.first; param; param = param.next)
581                   {
582                      if(!arg || arg.type != identifierExp || strcmp(param.name, arg.identifier.string))
583                      {
584                         confirmation = true;
585                         break;
586                      }
587                      arg = arg ?arg.next : null;
588                   }
589                }
590             }                  
591          }
592       }
593    }
594    return !confirmation;
595 }
596
597 class CodeEditor : Window
598 {
599    background = marginColor;
600    borderStyle = sizableDeep;
601    hasMaximize = true;
602    hasMinimize = true;
603    hasClose = true;
604    isDocument = true;
605    isActiveClient = true;
606    anchor = Anchor { left = 300, right = 150, top = 0, bottom = 0 };
607    menu = Menu { };
608    
609    // eWindow_SetX(A_CASCADE); eWindow_SetY(A_CASCADE); 
610    // eWindow_SetWidth(A_RELATIVE|80); eWindow_SetHeight(A_RELATIVE|80);
611
612    SheetType sheetSelected;
613    ToolBox toolBox;
614    Sheet sheet;
615
616    OldList * ast;
617    Context globalContext { };
618    OldList excludedSymbols { offset = (uint)&((Symbol)0).left };
619
620    OldList defines;
621    OldList imports;
622
623    OldList classes;
624    bool codeModified;
625    bool formModified;
626    
627    ObjectInfo selected;
628    ObjectInfo oClass;
629
630    // Methods Editing:
631    MethodAction methodAction;
632    Method method;
633    ClassFunction function;
634    bool moveAttached;
635    char methodName[1024];
636
637    bool updatingCode;
638    bool loadingFile;
639    bool fixCaret;
640    bool membersListShown;
641    bool membersAbove;
642    Location membersLoc;
643    EditLine membersLine;
644
645    Type functionType, instanceType;
646    int paramsID;
647    bool paramsShown;
648    bool paramsAbove;
649    Point paramsPosition;
650    Expression functionExp;
651    bool expectingMove;
652
653    BitmapResource icons[CodeObjectType];
654    
655    FontResource boldFont { $"Tahoma", 8.25f, bold = true, window = this };
656    FontResource normalFont { $"Tahoma", 8.25f, window = this };
657
658    Module privateModule;
659    NameSpace globalData;
660    bool skipModified;
661    bool inUseDebug;
662    OpenedFileInfo openedFileInfo;
663
664    FontResource font { codeFont.faceName, codeFont.size };
665    saveDialog = codeEditorFileDialog;
666
667    Designer designer { codeEditor = this, visible = false, saveDialog = codeEditorFormFileDialog };
668
669    void ProcessCaretMove(EditBox editBox, int line, int charPos)
670    {
671       char temp[512];
672       ObjectInfo classItem;
673
674       // OnActivateClient is called after OnActivate
675       if(!updatingCode)
676       {
677          sprintf(temp, $"Ln %d, Col %d", line, editBox.column + 1);
678          ide.pos.text = temp;
679       }
680       if(sheet.codeEditor != this) return;
681       
682       if(!updatingCode)
683       {
684          for(classItem = classes.first; classItem; classItem = classItem.next)
685          {
686             ClassDefinition classDef = classItem.classDefinition;
687             if(classDef && classDef.loc.Inside(line, charPos))
688                break;
689          }
690
691          if(classItem)
692          {
693             ObjectInfo object;
694             for(object = classItem.instances.first; object; object = object.next)
695             {
696                if(object.instCode)
697                {
698                   if(object.instCode.loc.Inside(line, charPos))
699                      break;
700                }
701             }
702             if(object)
703                sheet.SelectObject(object);
704             else
705                sheet.SelectObject(classItem);
706             Update(null);
707          }
708          //else
709          {
710             //sheet.SelectObject(null);
711             //Update(null);
712          }
713
714          sprintf(temp, $"Ln %d, Col %d", line, editBox.column + 1);
715          ide.pos.text = temp;
716
717          if(expectingMove)
718             expectingMove = false;
719          else
720          {
721             if(membersListShown)
722             {
723                bool hide = false;
724                if(line-1 != membersLoc.start.line)
725                   hide = true;
726                else
727                {
728                   char * buffer = membersLine.text;
729                   int c;
730
731                   if(charPos - 1 < membersLoc.start.charPos)
732                      hide = true;
733                   else if(charPos - 1 > membersLoc.end.charPos)
734                   {
735                      char * buffer = membersLine.text;
736                      //if(membersList.currentRow)
737                      //   hide = true;
738                      //else
739                      {
740                         for(c = membersLoc.start.charPos; c<=charPos && buffer[c]; c++)
741                            if(buffer[c] != ' ' && buffer[c] != '\t')
742                               break;
743                         if(c < charPos && buffer[c])
744                            hide = true;
745                      }
746                   }
747                }
748                if(hide)
749                {
750                   membersList.Destroy(0);
751                   membersListShown = false;
752                }
753             }
754             {
755                bool back = codeModified;
756                codeModified = false;
757                if(paramsShown)
758                   InvokeParameters(false, false, false);
759                /*if(membersListShown)
760                   InvokeAutoComplete(false, 0, true);*/
761                codeModified = back;
762             }
763          }
764       }
765    }
766
767    watch(modifiedDocument)
768    {
769       ProjectView projectView = ide.projectView;
770       if(projectView)
771       {
772          ProjectNode node = projectView.GetNodeFromWindow(this, null, false);
773          if(node)
774          {
775             node.modified = modifiedDocument;
776             projectView.Update(null);
777          }
778       }
779    };
780
781
782    EditBox editBox
783    {
784       textVertScroll = true, multiLine = true, /*lineNumbers = ideSettings.showLineNumbers,*/
785       freeCaret = ideSettings.useFreeCaret, caretFollowsScrolling = ideSettings.caretFollowsScrolling, 
786       tabKey = true, smartHome = true;
787       tabSelection = true, /*maxLineSize = 65536, */parent = this, hasHorzScroll = true, hasVertScroll = true;
788       selectionColor = selectionColor, selectionText = selectionText,
789       background = codeEditorBG, foreground = codeEditorFG, syntaxColorScheme = colorScheme,
790       font = font, borderStyle = none;
791       anchor = Anchor { left = 0, right = 0, top = 0, bottom = 0 };
792
793       bool OnMouseOver(int x, int y, Modifiers mods)
794       {
795          CodeEditor editor = (CodeEditor)master;
796          if(editor.designer && editor.designer.isDragging && !mods.isSideEffect)
797             Activate();
798          return true;
799       }
800
801       void NotifyCaretMove(EditBox editBox, int line, int charPos)
802       {
803          // Update Line Numbers
804          int spaceH;
805          int oldLine = lastLine;
806          display.FontExtent(font.font, " ", 1, null, &spaceH);
807          {
808             Box box { 0, (Min(oldLine,oldLine)-1) * spaceH - editBox.scroll.y, editBox.anchor.left.distance, (Max(oldLine, oldLine))*spaceH-1 - editBox.scroll.y };
809             Update(box);
810          }
811          {
812             Box box { 0, (Min(line,line)-1) * spaceH - editBox.scroll.y, editBox.anchor.left.distance, (Max(line, line))*spaceH-1 - editBox.scroll.y };
813             Update(box);
814          }
815          lastLine = line;
816
817          if(ide.activeClient == this)
818             ProcessCaretMove(editBox, line, charPos);
819          if(openedFileInfo)
820             openedFileInfo.CaretMove(line, charPos);
821       }
822
823       void NotifyOvrToggle(EditBox editBox, bool overwrite)
824       {
825          ide.ovr.color = overwrite ? black : Color { 128, 128, 128 };
826       }
827
828       void NotifyUpdate(EditBox editBox)
829       {
830          if(designer)
831          {
832             if(!skipModified)
833             {
834                codeModified = true;
835                designer.modifiedDocument = true;
836             }
837          }
838          modifiedDocument = true;
839       }
840
841       bool NotifyUnsetModified(EditBox editBox)
842       {
843          modifiedDocument = false;
844          return true;
845       }
846
847       bool NotifyCharsAdded(EditBox editBox, BufferLocation before, BufferLocation after, bool pasteOperation)
848       {
849          if(!loadingFile && after.y != before.y)
850          {
851             ProjectView projectView = ide.projectView;
852             if(projectView && fileName)
853             {
854                int c;
855                // HOW WE MIGHT WANT TO DO IT:
856                char * text = before.line.text;
857                for(c = before.x-1; c>= 0; c--)
858                   if(!isspace(text[c]))
859                      break;
860                ide.debugger.MoveIcons(fileName, before.y + (((!pasteOperation && c > -1) || !after.line.count) ? 1 : 0), after.y - before.y, false);
861
862                // HOW VISUAL STUDIO DOES IT:
863                /*
864                char * text = after.line.text;
865                for(c = after.line.count-1; c>= 0; c--)
866                   if(!isspace(text[c]))
867                      break;
868                ide.debugger.MoveIcons(fileName, before.y + ((c < 0) ? 1 : 0), after.y - before.y, false);
869                */
870             }
871             Update({ 0, 0, editBox.position.x, clientSize.h });
872          }
873
874          if(!updatingCode)
875          {
876             ObjectInfo oClass;
877
878             for(oClass = classes.first; oClass; oClass = oClass.next)
879             {
880                ObjectInfo object;
881                for(object = oClass.instances.first; object; object = object.next)
882                {
883                   if(object.instCode)
884                   {
885                      object.instCode.loc.start.AdjustAdd(before, after);
886                      object.instCode.loc.end.AdjustAdd(before, after);
887                   }
888                }
889                if(oClass.instCode)
890                {
891                   oClass.classDefinition.loc.start.AdjustAdd(before, after);
892                   oClass.classDefinition.loc.end.AdjustAdd(before, after);
893                }
894             }
895
896             if(!pasteOperation)
897             {
898                expectingMove = true;
899                if(membersListShown)
900                {
901                   bool hide = false;
902                   if(before.y != after.y)
903                      hide = true;
904                   else
905                   {
906                      char * buffer = membersLine.text;
907                      int c;
908                      bool firstChar = true;
909                      bool addedChar = false;
910                      char string[1024];
911                      int len = 0;
912
913                      DataRow row;
914
915                      membersLoc.end.charPos += after.x - Max(membersLoc.start.charPos, before.x);
916
917                      for(c = membersLoc.start.charPos; c<membersLoc.end.charPos && len < sizeof(string)-1; c++)
918                      {
919                         bool isSpace = (buffer[c] == ' ' || buffer[c] == '\t');
920                         if(!isalnum(buffer[c]) && buffer[c] != '_' && (!isSpace || !firstChar)) //|| membersList.currentRow
921                         {
922                            hide = true;
923                            break;
924                         }
925                         if(!isSpace) 
926                            firstChar = false;
927                         else if(firstChar)
928                         {
929                            membersLoc.start.charPos++;
930                            addedChar = true;
931                         }
932
933                         if(!firstChar)
934                            string[len++] = buffer[c];
935                      }
936                      if(firstChar)
937                      {
938                         row = membersList.currentRow;
939                         if(row && row.selected)
940                         {
941                            hide = true;
942                            if(addedChar)
943                               membersLoc.start.charPos--;
944                         }
945                      }
946
947                      string[len] = 0;
948
949                      if(!hide)
950                      {
951                         row = membersList.FindSubString(string);
952                         if(row)
953                            membersList.currentRow = row;
954                         else
955                         {
956                            row = membersList.FindSubStringi(string);
957                            if(row)
958                               membersList.currentRow = row;
959                            membersList.currentRow.selected = false;
960                         }
961                         if(row)
962                            membersList.SetScrollPosition(0, (row.index) * membersList.rowHeight);
963                      }
964                      else
965                      {
966                         row = membersList.currentRow;
967                      }
968
969                      // Accept current string if hiding typing char
970                      if(hide && row && row.selected)
971                      {
972                         char * string = row.string;
973                         int len = strlen(string);
974                         membersLoc.end.charPos -= after.x - before.x;
975                         editBox.GoToPosition(membersLine, membersLoc.start.line, membersLoc.start.charPos);
976                         editBox.Delete(membersLine, membersLoc.start.line, membersLoc.start.charPos,
977                                        membersLine, membersLoc.end.line, membersLoc.end.charPos);
978                         editBox.PutS(string);
979                         editBox.GoToPosition(membersLine, membersLoc.start.line, membersLoc.start.charPos + len + 1 /*after.x - before.x*/);
980
981                         after.x += membersLoc.start.charPos + len - before.x;
982                         before.x = membersLoc.start.charPos + len;
983                      }
984                   }
985                   if(hide)
986                   {
987                      membersList.Destroy(0);
988                      membersListShown = false;
989                   }
990                }
991                if(/*after.x - before.x == 1 && */after.y == before.y && !membersListShown)
992                {
993                   EditLine line = editBox.line;
994                   char * text = line.text;
995                   char ch = text[after.x-1];
996                   if(ch == '.' || (ch == '>' && after.x-1 > 0 && text[after.x-1-1] == '-') || (ch == ':' && after.x-1 > 0 && text[after.x-1-1] == ':'))
997                   {
998
999                      /*
1000                      // Can we call invoke auto complete here instead?
1001
1002
1003                      int line, charPos;
1004                      Expression exp;
1005                      void * l1, * l2;
1006                      int x1,y1, x2,y2;
1007                      int oldCharPos;
1008                      Point caret;
1009
1010                      // Force caret update already...
1011                      editBox.GetSelPos(&l1, &y1, &x1, &l2, &y2, &x2, false);
1012                      editBox.SetSelPos(l1, y1, x1, l2, y2, x2);
1013
1014                      editBox.GetCaretPosition(&caret);
1015
1016                      
1017
1018                      // Go back in the buffer until no space before
1019                      //yydebug = true;
1020                      codeModified = true;
1021                      EnsureUpToDate();
1022                      SetYydebug(false);
1023                      { 
1024                         EditBoxStream f { editBox = editBox };
1025                         oldCharPos = x1;
1026                         x1--;
1027                         x2--;
1028                         if(text[after.x-1] == '>')
1029                         {
1030                            x1--;
1031                            x2--;
1032                         }
1033
1034                         editBox.SetSelPos(l1, y1, x1, l2, y2, x2);
1035                         for(;;)
1036                         {
1037                            char ch;
1038                            if(!f.Seek(-1, current))
1039                               break;
1040                            f.Getc(&ch);
1041                            if(!isspace(ch)) break;
1042                            f.Seek(-1, current);
1043                         }
1044                         editBox.GetSelPos(&l1, &y1, &x1, &l2, &y2, &x2, false);
1045
1046                         line = editBox.lineNumber + 1;
1047                         charPos = editBox.charPos + 1;
1048                         delete f;
1049                      }
1050
1051                      exp = FindExpTree(ast, line, charPos);
1052
1053                      if(exp)
1054                      {
1055                         Type type = exp.expType;
1056
1057                         if(type && text[after.x-1] != '.')
1058                         {
1059                            if(type.kind == TypePointer || type.kind == TypeArray)
1060                               type = type.type;
1061                            else
1062                               type = null;
1063                         }
1064
1065                         membersList.Clear();
1066                         ListMembers(type);
1067
1068                         if(membersList.rowCount)
1069                         {
1070                            membersList.Sort(null, 1);
1071                            membersList.master = this;
1072
1073                            caret.y += editBox.GetCaretSize();
1074                            caret.x -= 20;
1075
1076                            membersList.Create();
1077
1078                            {
1079                               int x = caret.x + editBox.GetAbsX() - app.desktop.GetAbsX() - editBox.GetScrollX();
1080                               int y = caret.y + editBox.GetAbsY() - app.desktop.GetAbsY() - editBox.GetScrollY();
1081                               Window parent = membersList.parent;
1082
1083                               if(!paramsAbove && (paramsShown || y + membersList.GetHeight() > parent.GetClientHeight()))
1084                               {
1085                                  y -= editBox.GetCaretSize() + membersList.GetHeight();
1086                                  membersAbove = true;
1087                               }
1088                               else
1089                                  membersAbove = false;
1090
1091                               membersList.position = { x, y };
1092                            }
1093          
1094                            membersLine = l1;
1095                            membersLoc.start.line = line - 1;
1096                            membersLoc.start.charPos = oldCharPos;
1097                            membersLoc.end = membersLoc.start;
1098                            membersListShown = true;
1099                         }
1100                      }
1101
1102                      SetThisClass(null);
1103                      SetCurrentContext(globalContext);
1104                      */
1105                      codeModified = true;
1106                      skipModified = true;
1107                      if(text[after.x-1] == ':')
1108                         InvokeAutoComplete(false, 0, false);
1109                      else if(text[after.x-1] == '.')
1110                         InvokeAutoComplete(false, 1, false);
1111                      else if(text[after.x-1] == '>')
1112                         InvokeAutoComplete(false, 2, false);
1113                      skipModified = false;
1114                   }
1115                   else if(ch == '(' || ch == OpenBracket || ch == ',' || ch == '='  || ch == '?'  || ch == ':')
1116                   {
1117                      codeModified = true;
1118                      skipModified = true;
1119
1120                      if(InvokeAutoComplete(true, 0, false))
1121                      {
1122                         if(ch == '(' || ch == OpenBracket)
1123                            InvokeParameters(true, true, false);
1124                         else
1125                            InvokeParameters(this.functionType ? false : true, false, false);
1126                      }
1127
1128                      // InvokeAutoComplete(true, 0, false);
1129                      skipModified = false;
1130                   }
1131                   else if(ch == ')' || ch == '}' || ch == ';')
1132                   {
1133                      codeModified = true;               
1134                      skipModified = true;
1135                      if(paramsShown)
1136                         InvokeParameters(false, true, false);
1137                      skipModified = false;
1138                   }
1139                   else 
1140                   {
1141                      bool back = codeModified;
1142                      codeModified = false;
1143                      if(paramsShown)
1144                         InvokeParameters(false, false, true);
1145                      if(membersListShown)
1146                         InvokeAutoComplete(false, 0, true);
1147                      codeModified = back;
1148                   }
1149                }
1150                else
1151                {
1152                   bool back = codeModified;
1153                   codeModified = false;
1154
1155                   if(paramsShown)
1156                      InvokeParameters(false, false, true);
1157                   /*if(membersListShown)
1158                      InvokeAutoComplete(false, 0, true);*/
1159
1160                   codeModified = back;
1161                }
1162             }
1163          }
1164          return true;
1165       }
1166
1167       bool NotifyCharsDeleted(EditBox editBox, BufferLocation before, BufferLocation after, bool pasteOperation)
1168       {
1169          if(!loadingFile && after.y != before.y)
1170          {
1171             ProjectView projectView = ide.projectView;
1172             if(projectView && fileName)
1173                ide.debugger.MoveIcons(fileName, before.y + 1, before.y - after.y, before.x == 0);
1174             Update({ 0, 0, editBox.position.x, clientSize.h });
1175          }
1176
1177          if(!updatingCode)
1178          {
1179             ObjectInfo oClass;
1180
1181             for(oClass = classes.first; oClass; oClass = oClass.next)
1182             {
1183                ObjectInfo object;
1184                Location * loc;
1185                for(object = oClass.instances.first; object; object = object.next)
1186                {
1187                   if(object.instCode)
1188                   {
1189                      loc = &object.instCode.loc;
1190
1191                      if((before.y+1 < loc->start.line || (before.y+1 == loc->start.line && before.x+1 <= loc->start.charPos)) && 
1192                         (after.y+1 > loc->end.line    || (after.y+1 == loc->end.line && after.x+1 >= loc->end.charPos)))
1193                      {
1194                         object.instCode = null;
1195                      }
1196                      else
1197                      {
1198                         loc->start.AdjustDelete(before, after);
1199                         loc->end.AdjustDelete(before, after);
1200                      }
1201                   }
1202                }
1203                if(oClass.classDefinition)
1204                {
1205                   loc = &oClass.classDefinition.loc;
1206                   if((before.y+1 < loc->start.line || (before.y+1 == loc->start.line && before.x+1 <= loc->start.charPos)) && 
1207                      (after.y+1 > loc->end.line    || (after.y+1 == loc->end.line && after.x+1 >= loc->end.charPos)))
1208                   {
1209                      oClass.classDefinition = null;
1210                   }
1211                   else
1212                   {
1213                      loc->start.AdjustDelete(before, after);
1214                      loc->end.AdjustDelete(before, after);
1215                   }
1216                }
1217             }
1218
1219             if(membersListShown)
1220             {
1221                bool hide = false;
1222                if(pasteOperation || before.y != after.y)
1223                   hide = true;
1224                else
1225                {
1226                   char * buffer = membersLine.text;
1227                   int c;
1228                   bool firstChar = true;
1229                   char string[1024];
1230                   int len = 0;
1231
1232                   if(before.x >= membersLoc.start.charPos)
1233                   {
1234                      for(c = membersLoc.start.charPos; c<before.x && len < sizeof(string)-1; c++)
1235                      {
1236                         bool isSpace = (buffer[c] == ' ' || buffer[c] == '\t');
1237                         if(!isalnum(buffer[c]) && buffer[c] != '_' && (!isSpace || !firstChar))
1238                         {
1239                            hide = true;
1240                            break;
1241                         }
1242                         if(!isSpace) firstChar = false;
1243
1244                         if(!firstChar)
1245                            string[len++] = buffer[c];
1246                      }
1247                   }
1248                   else
1249                   {
1250                      // If deleting spaces before...
1251                      for(c = before.x; c<membersLoc.start.charPos; c++)
1252                      {
1253                         bool isSpace = (buffer[c] == ' ' || buffer[c] == '\t');
1254                         if(!isSpace)
1255                         {
1256                            hide = true;
1257                            break;
1258                         }
1259                      }
1260                      if(!hide)
1261                         membersLoc.start.charPos = before.x;
1262                   }
1263
1264                   if(membersLoc.end.charPos >= after.x)
1265                   {
1266                      for(c = after.x; c<membersLoc.end.charPos && len < sizeof(string)-1; c++)
1267                      {
1268                         bool isSpace = (buffer[c] == ' ' || buffer[c] == '\t');
1269                         if(!isalnum(buffer[c]) && buffer[c] != '_' && (!isSpace || !firstChar))
1270                         {
1271                            hide = true;
1272                            break;
1273                         }
1274                         if(!isSpace) firstChar = false;
1275
1276                         if(!firstChar)
1277                            string[len++] = buffer[c];
1278                      }
1279                   }
1280                   else
1281                      hide = true;
1282
1283                   string[len] = '\0';
1284
1285                   membersLoc.end.charPos -= after.x - before.x;
1286                   if(!hide)
1287                   {
1288                      DataRow row;
1289                      row = membersList.FindSubString(string);
1290                      if(!row)
1291                      {
1292                         row = membersList.FindSubStringi(string);
1293                         if(row)
1294                            membersList.currentRow = row;
1295                         membersList.currentRow.selected = false;
1296                      }
1297                      else
1298                         membersList.currentRow = row;
1299                      if(row)
1300                         membersList.SetScrollPosition(0, row.index * membersList.rowHeight);
1301                   }
1302                }
1303                if(hide)
1304                {
1305                   membersList.Destroy(0);
1306                   membersListShown = false;
1307                }
1308
1309                /*
1310                if(paramsShown)
1311                {
1312                   InvokeParameters(false, false);
1313                }
1314                */
1315             }
1316          }
1317          return true;
1318       }
1319
1320       bool NotifyDropped(EditBox editBox, int x, int y)
1321       {
1322          char * controlClass = toolBox.controlClass;
1323          if(controlClass && controlClass[0])
1324          {
1325             Instance control;
1326             ObjectInfo object;
1327             ObjectInfo classObject;
1328
1329             //editBox.NotifyCaretMove(this, editBox, y, x);
1330             editBox.GoToLineNum(y);
1331             editBox.GoToPosition(editBox.line, y, x);
1332
1333             classObject = selected ? selected.oClass : null;
1334
1335             if((!selected || selected == classObject) && classObject && classObject.instances.first)
1336                selected = classObject.instances.last;
1337
1338             UpdateFormCode();
1339             control = eInstance_New(eSystem_FindClass(privateModule, controlClass));
1340             if(control)
1341             {
1342                AddObject(control, &object);
1343
1344                designer.CreateObject(control, object, false, classObject.instance);
1345                // designer.PostCreateObject(control, object, false, classObject.instance);
1346                designer.DroppedObject(control, object, false, classObject.instance);
1347
1348                sheet.AddObject(object, object.name, typeData /* className*/, true);
1349                
1350                UpdateFormCode();
1351                //codeModified = true;
1352                EnsureUpToDate();
1353             }
1354          }
1355          return true;
1356       }
1357
1358       bool NotifyKeyDown(EditBox editBox, Key key, unichar ch)
1359       {
1360          if(key == Key { space, ctrl = true })
1361          {
1362             membersList.Destroy(0);
1363             membersListShown = false;
1364             InvokeAutoComplete(false, 0, false);
1365             return false;
1366          }
1367          else if(key == Key { space, ctrl = true, shift = true })
1368             InvokeParameters(false, true, false);
1369          else if(key == escape)
1370             ide.RepositionWindows(true);
1371          else if(key == ctrlF7)
1372          {
1373             if(ide.projectView)
1374             {
1375                ProjectNode node = ide.projectView.GetNodeFromWindow(this, null, false);
1376                if(!node)
1377                   node = ide.projectView.GetNodeFromWindow(this, null, true);
1378                if(!node)
1379                {
1380                   char * s;
1381                   s = PrintString($"The ", fileName, $" file is not part of any project.\n", 
1382                      $"It can't be compiled.");
1383                   MessageBox { type = ok, parent = ide, master = ide, text = $"File not in project error", contents = s }.Modal();
1384                   delete s;
1385                   return false;
1386                }
1387             }
1388          }
1389          return true;
1390       }
1391
1392       bool OnKeyDown(Key key, unichar ch)
1393       {
1394          CodeEditor editor = (CodeEditor)master;
1395          if(key == escape /*|| key == leftAlt || key == rightAlt || (key.ctrl && key.code != left && key.code != right && key.code != leftShift && key.code != rightShift && key.code !=  space)*/)
1396          {
1397             if(editor.membersListShown)
1398             {
1399                editor.membersList.Destroy(0);
1400                editor.membersListShown = false;
1401                return false;
1402             }
1403             if(editor.paramsShown)
1404             {
1405                editor.paramsList.Destroy(0);
1406                editor.paramsShown = false;
1407                FreeType(editor.functionType);
1408                FreeType(editor.instanceType);
1409
1410                editor.functionType = null;
1411                editor.instanceType = null;
1412                editor.paramsID = -1;
1413                return false;
1414             }
1415          }
1416          return EditBox::OnKeyDown(key, ch);
1417       }
1418
1419       void OnVScroll(ScrollBarAction action, int position, Key key)
1420       {
1421          if(anchor.left.distance)
1422          {
1423             Box box { 0, 0, anchor.left.distance-1, parent.clientSize.h - 1 };
1424             parent.Update(box);
1425          }
1426          EditBox::OnVScroll(action, position, key);
1427          {
1428             CodeEditor ce = (CodeEditor)parent;
1429             if(ce.openedFileInfo)
1430                ce.openedFileInfo.ScrollChange({ scroll.x, position });
1431          }
1432       }
1433
1434       void OnHScroll(ScrollBarAction action, int position, Key key)
1435       {
1436          EditBox::OnHScroll(action, position, key);
1437          {
1438             CodeEditor ce = (CodeEditor)parent;
1439             if(ce.openedFileInfo)
1440                ce.openedFileInfo.ScrollChange({ position, scroll.y });
1441          }
1442       }
1443    };
1444    ListBox membersList
1445    {
1446       master = this,
1447       fullRowSelect = false,
1448       interim = true,
1449       autoCreate = false,
1450       borderStyle = bevel;
1451       // size = { 200, 400 };
1452
1453       bool NotifyDoubleClick(ListBox listBox, int x, int y, Modifiers mods)
1454       {
1455          DataRow row = listBox.currentRow;
1456          if(row)
1457          {
1458             char * string = row.string;
1459
1460             editBox.GoToPosition(membersLine, membersLoc.start.line, membersLoc.start.charPos);
1461             editBox.Delete(
1462                membersLine, membersLoc.start.line, membersLoc.start.charPos,
1463                membersLine, membersLoc.end.line, membersLoc.end.charPos);
1464             editBox.PutS(string);
1465
1466             listBox.Destroy(0);
1467             membersListShown = false;
1468          }
1469          return true;
1470       }
1471
1472       bool OnKeyDown(Key key, unichar ch)
1473       {
1474          CodeEditor editor = (CodeEditor) master;
1475          if(key == escape || key == leftAlt || key == rightAlt || 
1476             (key.ctrl && key.code != left && key.code != right && 
1477              key.code != leftShift && key.code != rightShift && key.code != space))
1478          {
1479             if(editor.paramsShown)
1480                editor.paramsList.Destroy(0);
1481             if(editor.membersListShown)
1482                editor.membersList.Destroy(0);
1483
1484             editor.paramsShown = false;
1485             FreeType(editor.functionType);
1486             FreeType(editor.instanceType);
1487
1488             editor.functionType = null;
1489             editor.instanceType = null;
1490             editor.paramsID = -1;
1491
1492             editor.membersListShown = false;
1493             return true;
1494          }
1495          else 
1496             return editor.editBox.OnKeyDown(key, ch);
1497          return false;
1498       }
1499
1500       bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
1501       {
1502          CodeEditor editor = (CodeEditor)master;
1503          if(!active)
1504          {
1505             Destroy(0);
1506             editor.membersListShown = false;
1507          }
1508          return ListBox::OnActivate(active, previous, goOnWithActivation, direct);
1509       }
1510
1511       bool OnKeyHit(Key key, unichar ch)
1512       {
1513          CodeEditor editor = (CodeEditor) master;
1514
1515          switch(key)
1516          {
1517             case enter: case tab:
1518             {
1519                DataRow row = currentRow;
1520                if(row && row.selected)
1521                {
1522                   char * string = row.string;
1523
1524                   editor.editBox.GoToPosition(editor.membersLine, editor.membersLoc.start.line, editor.membersLoc.start.charPos);
1525                   editor.editBox.Delete(
1526                      editor.membersLine, editor.membersLoc.start.line, editor.membersLoc.start.charPos,
1527                      editor.membersLine, editor.membersLoc.end.line, editor.membersLoc.end.charPos);
1528                   editor.editBox.PutS(string);
1529
1530                   Destroy(0);
1531                   editor.membersListShown = false;
1532                }
1533                else
1534                   editor.editBox.OnKeyHit(key, ch);
1535                break;
1536             }
1537             case down:
1538             case up:
1539             case pageDown:
1540             case pageUp:
1541             case home:
1542             case end:
1543             {
1544                return ListBox::OnKeyHit(key, ch);
1545             }
1546             default:
1547             {
1548                /*
1549                bool result;
1550                // If before . or after
1551                //listBox.Destroy(true);
1552                result = editor.editBox.OnKeyHit(key, ch);
1553                return result;
1554                */
1555                return true;
1556             }
1557          }
1558
1559          return false;
1560       }
1561    };
1562
1563    Window paramsList
1564    {
1565       master = this, 
1566       interim = true,
1567       clickThrough = true,
1568       autoCreate = false,
1569       borderStyle = contour,
1570       cursor = null,
1571       background = { 255,255,225 },
1572       
1573       OnKeyDown = membersList.OnKeyDown;
1574
1575       bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct)
1576       {
1577          CodeEditor editor = (CodeEditor)master;
1578          if(!active)
1579          {
1580             Destroy(0);
1581             editor.membersListShown = false;
1582          }
1583          return Window::OnActivate(active, previous, goOnWithActivation, direct);
1584       }
1585
1586       bool OnKeyHit(Key key, unichar ch)
1587       {
1588          CodeEditor editor = (CodeEditor)master;
1589
1590          if(!editor.membersListShown || editor.membersList.OnKeyHit(key, ch))
1591          {
1592             /*
1593             bool result = true; editor.editBox.OnKeyHit(key, ch);
1594             return (!created) ? false : result;
1595             */
1596             return true;
1597          }
1598          return false;
1599       }
1600
1601       void OnRedraw(Surface surface)
1602       {
1603          CodeEditor editor = (CodeEditor) master;
1604          Type type = editor.functionType ? editor.functionType : editor.instanceType;
1605          Type param;
1606          Type methodType = null;
1607
1608          char string[1024];
1609
1610          int functionW, nameW = 0;
1611          int totalW = 0;
1612          int spaceW, spaceH, commaW, commaWB, parW;
1613          int availW = 1024;
1614          int maxW = 0, lineW = 0;
1615          int realW = 0;
1616          int height = 0;
1617          int x = 2, y = 2;
1618          int id = 0;
1619
1620          Font font = editor.normalFont.font;
1621          Font boldFont = editor.boldFont.font;
1622          Display display = this.display;
1623
1624          if(!type) { return; };
1625
1626          if(type.kind == TypeKind::methodType) { methodType = type; type = type.method.dataType; }
1627
1628          display.FontExtent(boldFont, " ", 1, &spaceW, &spaceH);
1629          display.FontExtent(font, ", ", 2, &commaW, null);
1630          display.FontExtent(boldFont, ", ", 2, &commaWB, null);
1631          display.FontExtent(font, ")", 1, &parW, null);
1632
1633          string[0] = 0;
1634          if(editor.functionType)
1635          {
1636             PrintType(type.returnType, string, true, true);
1637             display.FontExtent(font, string, strlen(string), &functionW, null);
1638             if(type.name)
1639                display.FontExtent(font, type.name, strlen(type.name), &nameW, null);
1640             totalW = nameW + functionW + 2 * parW;
1641          }
1642          else
1643          {
1644             PrintType(type, string, (type.kind == functionType) ? true : false, true); // true);
1645             display.FontExtent(boldFont, string, strlen(string), &functionW, null);
1646             if(instanceName && type.kind != functionType)
1647                display.FontExtent(boldFont, instanceName, strlen(instanceName), &nameW, null);
1648             totalW = functionW + nameW;
1649             surface.TextFont(boldFont);
1650          }   
1651
1652          surface.WriteText(x, y, string, strlen(string));
1653          x += functionW + spaceW;
1654
1655          if(editor.functionType)
1656          {
1657             if(type.name)
1658                surface.WriteText(x, y, type.name, strlen(type.name));
1659             x += nameW;
1660             surface.WriteText(x, y, "(", 1);
1661             x += parW;
1662
1663             if(methodType && !methodType.staticMethod)
1664             {
1665                int tw = 0, width;
1666
1667                if(id == editor.paramsID)
1668                   surface.TextFont(boldFont);
1669                
1670                if(methodType.methodClass)
1671                   surface.TextExtent(methodType.methodClass.name, strlen(methodType.methodClass.name), &tw, null);
1672
1673                width = tw;
1674
1675                if(type.params.first && (((Type)type.params.first).kind != voidType || type.params.count > 1))
1676                   width += ((id == editor.paramsID) ? commaWB : commaW);
1677
1678                if(!height)
1679                   maxW = lineW;
1680
1681                if(lineW && ((height && lineW + width > maxW) || (totalW + lineW + width + 20 > availW)))
1682                {
1683                   height += spaceH;
1684                   lineW = 0;
1685
1686                   x = 2 + nameW + spaceW + functionW + parW;
1687                   y += spaceH;
1688
1689                }
1690                if(methodType.methodClass)
1691                   surface.WriteText(x, y, methodType.methodClass.name, strlen(methodType.methodClass.name));
1692
1693                x += tw;
1694                if(type.params.first && (((Type)type.params.first).kind != voidType || type.params.count > 1))
1695                {
1696                   surface.WriteText(x, y, ",", 1);
1697                   x += ((id ==  editor.paramsID) ? commaWB : commaW);
1698                }      
1699
1700                lineW += width;
1701
1702                if(lineW > realW)
1703                   realW = lineW;
1704
1705                if(id == editor.paramsID)
1706                   surface.TextFont(font);
1707                id ++;
1708             }
1709
1710             if(!methodType || methodType.staticMethod || !type.params.first || ((Type)type.params.first).kind != voidType || type.params.count > 1)
1711             {
1712                for(param = type.params.first; param; param = param.next)
1713                {
1714                   char paramString[1024];
1715                   int tw, width;
1716
1717                   if(id == editor.paramsID || (param.kind == ellipsisType && id < editor.paramsID && editor.paramsID != -1))
1718                      surface.TextFont(boldFont);
1719
1720                   paramString[0] = 0;
1721                   PrintType(param, paramString, true, true);
1722                   surface.TextExtent(paramString, strlen(paramString), &tw, null);
1723                   width = tw;
1724                   if(param.next) width += ((id ==  editor.paramsID) ? commaWB : commaW);
1725
1726                   if(!height)
1727                      maxW = lineW;
1728
1729                   if(lineW && ((height && lineW + width > maxW) || (totalW + lineW + width + 20 > availW)))
1730                   {
1731                      height += spaceH;
1732                      lineW = 0;
1733
1734                      x = 2 + nameW + spaceW + functionW + parW;
1735                      y += spaceH;
1736
1737                   }
1738                   surface.WriteText(x, y, paramString, strlen(paramString));
1739                   x += tw;
1740                   if(param.next)
1741                   {
1742                      surface.WriteText(x, y, ",", 1);
1743                      x += ((id ==  editor.paramsID) ? commaWB : commaW);
1744                   }      
1745
1746                   lineW += width;
1747
1748                   if(lineW > realW)
1749                      realW = lineW;
1750
1751                   if(id == editor.paramsID || (param.kind == ellipsisType && id < editor.paramsID && editor.paramsID != -1))
1752                      surface.TextFont(font);
1753                   id ++;
1754                }
1755             }
1756
1757             surface.WriteText(x, y, ")", 1);
1758          }
1759          else if(instanceName && type.kind != functionType)
1760          {
1761             surface.WriteText(x, y, instanceName, strlen(instanceName));
1762          }
1763       }
1764
1765       bool OnResizing(int * w, int * h)
1766       {
1767          CodeEditor editor = (CodeEditor) master;
1768          Type type = editor.functionType ? editor.functionType : editor.instanceType;
1769          Type param;
1770          Type methodType = null;
1771
1772          char string[1024];
1773
1774          int functionW = 0, nameW = 0;
1775          int totalW = 0;
1776          int spaceW, spaceH, commaW, commaWB, parW;
1777          int availW = 1024;
1778          int maxW = 0, lineW = 0;
1779          int realW = 0;
1780          int height = 0;
1781          int id = 0;
1782
1783          Font font = editor.normalFont.font;
1784          Font boldFont = editor.boldFont.font;
1785          Display display = this.display;
1786
1787          if(type.kind == TypeKind::methodType)
1788          {
1789             methodType = type;
1790             ProcessMethodType(type.method);
1791             type = type.method.dataType;
1792          }
1793
1794          display.FontExtent(boldFont, " ", 1, &spaceW, &spaceH);
1795          display.FontExtent(font, ", ", 2, &commaW, null);
1796          display.FontExtent(boldFont, ", ", 2, &commaWB, null);
1797          display.FontExtent(font, ")", 1, &parW, null);
1798
1799          string[0] = 0;
1800          if(editor.functionType && type)
1801          {
1802             PrintType(type.returnType, string, true, true);
1803             display.FontExtent(font, string, strlen(string), &functionW, null);
1804             if(type.name)
1805                display.FontExtent(font, type.name, strlen(type.name), &nameW, null);
1806             totalW = nameW + spaceW + functionW + 2 * parW;
1807          }
1808          else if(type)
1809          {
1810             PrintType(type, string, false, true); // /*true);
1811             display.FontExtent(boldFont, string, strlen(string), &functionW, null);
1812             if(instanceName && type.kind != functionType)
1813                display.FontExtent(boldFont, instanceName, strlen(instanceName), &nameW, null);
1814             totalW = functionW + nameW + spaceW;
1815          }
1816             
1817          if(editor.functionType)
1818          {
1819             if(methodType)
1820             {
1821                int width = 0;
1822
1823                if(methodType.methodClass)
1824                   display.FontExtent((id == editor.paramsID) ? boldFont : font, methodType.methodClass.name, strlen(methodType.methodClass.name), &width, null);
1825                if(type.params.first && (((Type)type.params.first).kind != voidType || type.params.count > 1))
1826                   width += ((id == editor.paramsID) ? commaWB : commaW);
1827
1828                if(!height)
1829                   maxW = lineW;
1830
1831                if(lineW && ((height && lineW + width > maxW) || (totalW + lineW + width + 20 > availW)))
1832                {
1833                   height += spaceH;
1834                   lineW = 0;
1835                }
1836
1837                lineW += width;
1838
1839                if(lineW > realW)
1840                   realW = lineW;
1841
1842                id++;
1843             }
1844             if(!methodType || methodType.staticMethod || !type.params.first || ((Type)type.params.first).kind != voidType || type.params.count > 1)
1845             {
1846                for(param = type.params.first; param; param = param.next)
1847                {
1848                   char paramString[1024];
1849                   int width = 0;
1850
1851                   paramString[0] = 0;
1852                   PrintType(param, paramString, true, true);
1853                   display.FontExtent((id == editor.paramsID || param.kind == ellipsisType) ? boldFont : font, paramString, strlen(paramString), &width, null);
1854                   if(param.next) 
1855                      width += ((id == editor.paramsID) ? commaWB : commaW);
1856
1857                   if(!height)
1858                      maxW = lineW;
1859
1860                   if(lineW && ((height && lineW + width > maxW) || (totalW + lineW + width + 20 > availW)))
1861                   {
1862                      height += spaceH;
1863                      lineW = 0;
1864                   }
1865
1866                   lineW += width;
1867
1868                   if(lineW > realW)
1869                      realW = lineW;
1870
1871                   id++;
1872                }
1873             }
1874          }
1875          height += spaceH;
1876
1877          *w = realW + totalW + 4;
1878          *h = height + 4;
1879          return true;
1880       }
1881    };
1882
1883    Menu fileMenu { menu, $"File", f };  // MenuPlacement?
1884    MenuItem { fileMenu, $"Save", s, Key { s, ctrl = true }, NotifySelect = MenuFileSave };
1885    MenuItem { fileMenu, $"Save As...", a, NotifySelect = MenuFileSaveAs };
1886
1887    Menu debugMenu { menu, $"Debug", d };  // MenuPlacement?
1888    MenuItem debugRunToCursor
1889    {
1890       debugMenu, $"Run To Cursor", c, Key { f10, ctrl = true };
1891       bool NotifySelect(MenuItem selection, Modifiers mods)
1892       {
1893          ProjectView projectView = ide.projectView;
1894          if(!projectView.buildInProgress)
1895          {
1896             int line = editBox.lineNumber + 1;
1897             if(projectView)
1898             {
1899                CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.compiler);
1900                ProjectConfig config = projectView.project.config;
1901                ide.debugger.RunToCursor(compiler, config, fileName, line, false);
1902                delete compiler;
1903             }
1904          }
1905          return true;
1906       }
1907    };
1908    MenuItem debugSkipRunToCursor
1909    {
1910       debugMenu, $"Run To Cursor Skipping Breakpoints", u, Key { f10, ctrl = true, shift = true };
1911       bool NotifySelect(MenuItem selection, Modifiers mods)
1912       {
1913          ProjectView projectView = ide.projectView;
1914          int line = editBox.lineNumber + 1;
1915          if(projectView)
1916          {
1917             CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.compiler);
1918             ProjectConfig config = projectView.project.config;
1919             ide.debugger.RunToCursor(compiler, config, fileName, line, true);
1920             delete compiler;
1921          }
1922          return true;
1923       }
1924    };
1925    MenuDivider { debugMenu };
1926    MenuItem debugToggleBreakpoint
1927    {
1928       debugMenu, $"Toggle Breakpoint", t, f9;
1929       bool NotifySelect(MenuItem selection, Modifiers mods)
1930       {
1931          ProjectView projectView = ide.projectView;
1932          if(projectView && fileName)
1933          {
1934             int line = editBox.lineNumber + 1;
1935             char name[MAX_LOCATION];
1936             Project prj = null;
1937             // TOFIX: This only looks at the filename...
1938             GetLastDirectory(fileName, name);
1939             if(ide && ide.workspace)
1940             {
1941                for(p : ide.workspace.projects)
1942                {
1943                   if(p.topNode.Find(name, false))
1944                   {
1945                      prj = p;
1946                      break;
1947                   }
1948                }
1949                if(!prj)
1950                {
1951                   for(p : ide.workspace.projects)
1952                   {
1953                      if(IsPathInsideOf(fileName, p.topNode.path))
1954                      {
1955                         prj = p;
1956                         break;
1957                      }
1958                   }
1959                }
1960             }
1961             ide.debugger.ToggleBreakpoint(fileName, line, prj);
1962             Update(null);
1963          }
1964          return true;
1965       }
1966    };
1967
1968    bool debugClosing;
1969    int lastLine;
1970
1971    //MenuItem viewDesignerItem, viewProperties, viewMethods;
1972
1973    bool OnCreate(void)
1974    {
1975       designer.parent = parent;
1976       designer.Create();
1977
1978       toolBox = ((IDEWorkSpace)master).toolBox;
1979       incref toolBox;
1980       // Debugger bug here: value of toolBox appears as 0
1981
1982       sheet = ((IDEWorkSpace)master).sheet;
1983       incref sheet;
1984       return true;
1985    }
1986
1987    bool OnClose(bool parentClosing)
1988    {
1989       if(!parentClosing)
1990       {
1991          if(ide.workspace && fileName)
1992             ide.workspace.UpdateOpenedFileInfo(fileName, closed);
1993          if(inUseDebug && !debugClosing)
1994          {
1995             debugClosing = true;
1996             closing = false;
1997             if(CloseConfirmation(false))
1998             {
1999                visible = false;
2000                OnFileModified({ modified = true }, null);
2001             }
2002             debugClosing = false;
2003             return false;
2004          }
2005          if(designer && !designer.closing)
2006          {
2007             if(designer.visible)
2008             {
2009                visible = false;
2010                return false;
2011             }
2012             /*else
2013             {
2014                //Window formEditor = designer;
2015                //formEditor.Destroy(0);
2016             }*/
2017          }
2018          ide.AdjustFileMenus();
2019       }
2020       return true;
2021    }
2022
2023    void OnDestroy(void)
2024    {
2025       ObjectInfo oClass, next;
2026       Class windowClass = eSystem_FindClass(this.privateModule, "ecere::gui::Window");
2027
2028       FreeType(this.functionType);
2029       FreeType(this.instanceType);
2030
2031       if(designer)
2032       {
2033          designer.Reset();
2034          designer.codeEditor = null;
2035          designer.Destroy(0);
2036          delete designer;
2037       }
2038
2039       for(oClass = (classes).first, next = oClass ? oClass.next : null; oClass; oClass = next, next = next ? (next.next) : null)
2040       {
2041          ObjectInfo object, next;
2042          
2043          for(object = oClass.instances.first; object; object = next)
2044          {
2045             next = object.next;
2046             if(object.instance)
2047             {
2048                Designer::DestroyObject(object.instance);
2049                delete object.instance;
2050             }
2051             sheet.DeleteObject(object);
2052             delete object.name;
2053             oClass.instances.Delete(object);
2054          }
2055          if(oClass.instance)
2056          {
2057             Designer::DestroyObject(oClass.instance);
2058             delete oClass.instance;
2059          }
2060          sheet.DeleteObject(oClass);
2061          delete oClass.name;
2062          classes.Delete(oClass);
2063       }
2064
2065       if(windowClass && windowClass.data)
2066          UnapplySkin(windowClass);
2067
2068       FreeParser();
2069
2070       if(sheet.codeEditor == this)
2071       {
2072          sheet.codeEditor = null;
2073          toolBox.codeEditor = null;
2074       }
2075       delete sheet;
2076       delete toolBox;
2077
2078       {
2079          ProjectView projectView = ide.projectView;
2080          if(projectView)
2081          {
2082             ProjectNode node = projectView.GetNodeFromWindow(this, null, false);
2083             if(node && node.modified)
2084             {
2085                node.modified = false;
2086                projectView.Update(null);
2087             }
2088          }
2089       }
2090    }
2091
2092    bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool directActivation)
2093    {
2094       // WHY WAS THIS HERE? I think this was here because once you move a window in the ide it's hard to reposition it correctly
2095       /*
2096       if(directActivation)
2097          ide.RepositionWindows(false);    // Moved this up before as resizing causes NotifyCaretMove to be called on all editors
2098       */
2099       if(active && directActivation)
2100       {
2101          if(openedFileInfo)
2102             openedFileInfo.Activate();
2103          if(designer)
2104          {
2105             int line, charPos;
2106             Location * loc = null;
2107             UpdateFormCode(); // To ensure update when modifying properties...
2108
2109             // Got to the right spot in code so we don't lose our form selection...
2110             if(selected)
2111             {
2112                if(selected.instCode)
2113                   loc = &selected.instCode.loc;
2114                else if(selected.classDefinition)
2115                   loc = &selected.classDefinition.loc;
2116             }
2117             line = editBox.lineNumber + 1;
2118             charPos = editBox.charPos + 1;
2119             if(fixCaret)
2120             {
2121                fixCaret = false;
2122
2123                if(selected && !loc->Inside(line, charPos))
2124                {
2125                   editBox.GoToPosition(null, loc->start.line - 1, loc->start.charPos - 1);
2126                   line = editBox.lineNumber + 1;
2127                   charPos = editBox.charPos + 1;
2128                }
2129                else if(selected && selected.classDefinition)
2130                {
2131                   ObjectInfo object;
2132                   for(object = selected.instances.first; object; object = object.next)
2133                   {
2134                      if(object.instCode)
2135                      {
2136                         if(object.instCode.loc.Inside(line, charPos))
2137                            break;
2138                      }
2139                   }
2140                   if(object)
2141                   {
2142                      editBox.GoToPosition(null, loc->start.line - 1, loc->start.charPos - 1);
2143                      line = editBox.lineNumber + 1;
2144                      charPos = editBox.charPos + 1;
2145                   }
2146                }
2147             }
2148
2149             ProcessCaretMove(editBox, line, charPos);
2150          }
2151       }
2152       return true;
2153    }
2154
2155    bool OnSaveFile(char * fileName)
2156    {
2157       File f;
2158       if(designer)
2159       {
2160          UpdateFormCode();
2161       }
2162       f = FileOpen(fileName, write);
2163       if(f)
2164       {
2165          if(!ide.projectView)
2166             ide.ChangeFileDialogsDirectory(codeEditorFileDialog.currentDirectory, true);
2167          if(designer)
2168          {
2169             if(!this.fileName)
2170                this.fileName = fileName;  // Put this here because the form designer will check for it...
2171             designer.fileName = fileName;
2172             designer.modifiedDocument = false;
2173          }
2174          editBox.Save(f, false);
2175          modifiedDocument = false;
2176          
2177          delete(f);
2178          return true;
2179       }
2180       return false;
2181    }
2182
2183    bool OnFileModified(FileChange fileChange, char * param)
2184    {
2185       bool reload = false;
2186       if(visible == false && inUseDebug == true)
2187          reload = true;
2188       else
2189       {
2190          char message[2048];
2191
2192          sprintf(message, $"The document %s was modified by another application.\n"
2193             "Would you like to reload it and lose your changes?", fileName);
2194          if(MessageBox { type = yesNo, master = /*parent = */parent, text = $"Document has been modified",
2195             contents = message }.Modal() == yes)
2196             reload = true;
2197       }
2198
2199       if(reload)
2200       {
2201          File f = FileOpen(fileName, read);
2202          if(f)
2203          {
2204             int lineNumber, charPos, len;
2205             Point scroll;
2206
2207             loadingFile = true;
2208             updatingCode = true;
2209             lineNumber = editBox.lineNumber;
2210             charPos = editBox.charPos;
2211             scroll = editBox.scroll;
2212             editBox.Clear();
2213             editBox.Load(f);
2214             lineNumber = lineNumber < editBox.numLines ? lineNumber : editBox.numLines - 1;
2215             len = strlen(editBox.line.text);
2216             editBox.GoToLineNum(lineNumber);
2217             editBox.GoToPosition(editBox.line, lineNumber, charPos <= len ? charPos - 1 : (len ? len - 1 : 0));
2218             editBox.scroll = scroll;
2219             updatingCode = false;
2220             loadingFile = false;
2221
2222             codeModified = true;
2223             if(designer)
2224             {
2225                UpdateFormCode();
2226                designer.modifiedDocument = false;
2227             }
2228             modifiedDocument = false;
2229
2230             delete(f);
2231          }
2232       }
2233       return true;
2234    }
2235
2236    void OnRedraw(Surface surface)
2237    {
2238       // Line Numbers
2239       surface.SetBackground(marginColor);
2240       surface.Area(0, 0, editBox.anchor.left.distance, clientSize.h - 1);
2241       if(ideSettings.showLineNumbers)
2242       {
2243          int currentLineNumber;
2244          int i;
2245          char lineText[256];
2246          int spaceH;
2247
2248          surface.textOpacity = false;
2249          surface.font = font.font;
2250          surface.TextExtent(" ", 1, null, &spaceH);
2251          currentLineNumber = editBox.scroll.y / spaceH + 1;
2252
2253          surface.SetForeground(lineNumbersColor);
2254          for(i = 0; i < editBox.clientSize.h - 4; i += spaceH)
2255          {
2256             // Highlight current line
2257             if(editBox.lineNumber == currentLineNumber - 1)
2258             {
2259                surface.SetBackground(selectedMarginColor);
2260                surface.Area(0, i, editBox.anchor.left.distance, i+spaceH-1);
2261                surface.SetBackground(marginColor);
2262             }
2263             sprintf(lineText,"%5u ", currentLineNumber % 100000);
2264             if(currentLineNumber <= editBox.numLines)
2265                surface.WriteText(editBox.syntaxHighlighting * 20, i+1,lineText,6);
2266             
2267             currentLineNumber++;
2268          }
2269       }
2270
2271       if(editBox.syntaxHighlighting && fileName && ide.projectView)
2272       {
2273          bool error, bpOnCursor, bpOnTopFrame, breakpointEnabled[128];
2274          int lineCursor, lineTopFrame, breakpointLines[128];
2275          int count, i, lineH, boxH, scrollY; //, firstLine; firstLine = editBox.firstLine;
2276          Debugger debugger = ide.debugger;
2277          BitmapResource bmpRes;
2278
2279          boxH = clientSize.h;
2280          scrollY = editBox.scroll.y;
2281          displaySystem.FontExtent(editBox.font.font, " ", 1, null, &lineH);
2282
2283          bpOnCursor = bpOnTopFrame = false;
2284          count = debugger.GetMarginIconsLineNumbers(fileName, breakpointLines, breakpointEnabled, 128, &error, &lineCursor, &lineTopFrame);
2285          if(count)
2286          {
2287             for(i = 0; i < count; i++)
2288             {
2289                if(breakpointLines[i] == lineCursor || breakpointLines[i] == lineTopFrame)
2290                {
2291                   bmpRes = breakpointEnabled[i] ? ide.bmpBpHalf : ide.bmpBpHalfDisabled;
2292                   if(breakpointLines[i] == lineCursor)
2293                      bpOnCursor = true;
2294                   if(breakpointLines[i] == lineTopFrame)
2295                      bpOnTopFrame = true;
2296                }
2297                else
2298                   bmpRes = breakpointEnabled[i] ? ide.bmpBp : ide.bmpBpDisabled;
2299                
2300                DrawLineMarginIcon(surface, bmpRes, breakpointLines[i], lineH, scrollY, boxH);
2301             }
2302          }
2303          DrawLineMarginIcon(surface, error ? ide.bmpCursorError : ide.bmpCursor, lineCursor, lineH, scrollY, boxH);
2304          bmpRes = bpOnTopFrame ? (error ? ide.bmpTopFrameHalfError : ide.bmpTopFrameHalf) : (error ? ide.bmpTopFrameError : ide.bmpTopFrame);
2305          DrawLineMarginIcon(surface, bmpRes, lineTopFrame, lineH, scrollY, boxH);
2306       }
2307       if(editBox.anchor.left.distance)
2308       {
2309          if(editBox.horzScroll && editBox.horzScroll.visible)
2310          {
2311             surface.SetBackground(control);
2312             surface.Area(0, editBox.clientSize.h, editBox.anchor.left.distance, clientSize.h - 1);
2313          }
2314       }
2315    }
2316
2317    void DrawLineMarginIcon(Surface surface, BitmapResource resource, int line, int lineH, int scrollY, int boxH)
2318    {
2319       int lineY;
2320       if(line)
2321       {
2322          lineY = (line - 1) * lineH;
2323          if(lineY + lineH > scrollY && lineY /*+ lineH*/ < scrollY + boxH)
2324          {
2325             Bitmap bitmap = resource.bitmap;
2326             if(bitmap)
2327                surface.Blit(bitmap, 0, lineY - scrollY + (lineH - bitmap.height) / 2 + 1, 0, 0, bitmap.width, bitmap.height);
2328          }
2329       }
2330    }
2331
2332    watch(fileName)
2333    {
2334       char ext[MAX_EXTENSION];
2335       char * fileName = property::fileName;
2336
2337       if(SearchString(fileName, 0, "Makefile", false, true))
2338          editBox.useTab = true;
2339       designer.fileName = fileName;
2340
2341       if(fileName)
2342       {
2343          GetExtension(fileName, ext);
2344          if(!strcmpi(ext, "ec"))
2345          {
2346             codeModified = true;
2347             EnsureUpToDate();
2348          }
2349
2350          if(!strcmpi(ext, "ec") || !strcmpi(ext, "c") || !strcmpi(ext, "cc") || !strcmpi(ext, "cpp") || !strcmpi(ext, "eh") || !strcmpi(ext, "hh") || !strcmpi(ext, "hpp") || !strcmpi(ext, "h") || !strcmpi(ext, "hxx") || !strcmpi(ext, "cxx"))
2351             editBox.syntaxHighlighting = true;
2352          else
2353             editBox.syntaxHighlighting = false;
2354          {
2355             int spaceW;
2356             display.FontExtent(font.font, " ", 1, &spaceW, null);
2357             editBox.anchor = Anchor
2358             {
2359                left = (editBox.syntaxHighlighting ? 20 : 0) + (ideSettings.showLineNumbers ? (6 * spaceW) : 0),
2360                right = 0, top = 0, bottom = 0
2361             };
2362          }
2363       }
2364    };
2365
2366    bool OnPostCreate()
2367    {
2368       int spaceW;
2369       display.FontExtent(font.font, " ", 1, &spaceW, null);
2370       editBox.anchor = Anchor
2371       {
2372          left = (editBox.syntaxHighlighting ? 20 : 0) + (ideSettings.showLineNumbers ? (6 * spaceW) : 0),
2373          right = 0, top = 0, bottom = 0
2374       };
2375       return true;
2376    }
2377
2378    bool LoadFile(char * filePath)
2379    {
2380       File f = FileOpen(filePath, read);
2381       if(f)
2382       {
2383          // Added this here... 
2384          fileName = filePath;
2385          loadingFile = true;
2386          updatingCode = true;
2387          editBox.Load(f);
2388          updatingCode = false;
2389          loadingFile = false;
2390          Create();
2391
2392          delete(f);
2393          return true;
2394       }
2395       return false;
2396    }
2397
2398    void DebugMenusDisabled()
2399    {
2400       bool debugMenusDisabled = ide.GetDebugMenusDisabled();
2401       debugRunToCursor.disabled = debugMenusDisabled;
2402       debugSkipRunToCursor.disabled = debugMenusDisabled;
2403       debugToggleBreakpoint.disabled = debugMenusDisabled;
2404    }
2405
2406    CodeEditor()
2407    {
2408       CodeObjectType c;
2409       ProjectView projectView = ide.projectView;
2410
2411       /*if(fileName)
2412          designer.fileName = fileName;
2413       else
2414       */
2415       if(designer)
2416       {
2417          char title[1024];
2418          sprintf(title, $"Untitled %d", documentID);
2419          // designer.fileName = CopyString(title);
2420          designer.fileName = title;
2421       }
2422
2423       DebugMenusDisabled();
2424
2425       for(c = 0; c < CodeObjectType::enumSize; c++)
2426          icons[c] = BitmapResource { iconNames[c], window = this };
2427
2428       codeModified = true;
2429       inUseDebug = false;
2430       return true;
2431    }
2432
2433    ~CodeEditor()
2434    {
2435
2436    }
2437
2438    void ModifyCode()
2439    {
2440       selected.modified = true;
2441       selected.oClass.modified = true;
2442
2443       designer.modifiedDocument = true;
2444       modifiedDocument = true;
2445       formModified = true;
2446    }
2447
2448    /****************************************************************************
2449                                  PARSING
2450    ****************************************************************************/
2451    void FreeParser()
2452    {
2453       this.defines.Free(FreeModuleDefine);
2454       this.imports.Free(FreeModuleImport);
2455       
2456       if(ast != null)
2457       {
2458          FreeASTTree(ast);
2459          ast = null;
2460       }
2461       FreeExcludedSymbols(this.excludedSymbols);
2462       FreeContext(this.globalContext);
2463       FreeIncludeFiles();
2464       FreeGlobalData(&this.globalData);
2465
2466       if(GetGlobalContext() == globalContext)
2467       {
2468          SetGlobalData(null);
2469          SetGlobalContext(null);
2470          SetExcludedSymbols(null);
2471          SetTopContext(null);
2472          SetCurrentContext(null);
2473          SetDefines(null);
2474          SetImports(null);
2475          SetPrivateModule(null);
2476       }
2477
2478       if(this.privateModule)
2479       {
2480          FreeTypeData(this.privateModule);
2481          delete this.privateModule;
2482          this.privateModule = null;
2483       }
2484    }
2485
2486    void ParseCode()
2487    {
2488       static bool reentrant = false;
2489       External external;
2490       File editFile;
2491       EditLine l1, l2;
2492       int x1,x2,y1,y2;
2493       char * selectedClassName = null, * selectedName = null;
2494       int selectedPos = 0;
2495       Designer backDesigner;
2496       char oldWorkDir[MAX_LOCATION];
2497       char mainModuleName[MAX_FILENAME] = "";
2498       char * fileName;
2499       ImportedModule module;
2500       char extension[MAX_EXTENSION];
2501 #ifdef _TIMINGS
2502       Time parseCodeStart = GetTime();
2503       Time startTime, startFindClass;
2504
2505       findClassTotalTime = 0;
2506       checkTypeTotalTime = 0;
2507       externalImportTotalTime = 0;
2508       findClassIgnoreNSTotalTime = 0;
2509       findSymbolTotalTime = 0;
2510       //ResetClassFindTime();
2511 #endif
2512       Project project;
2513
2514       // This temporarily fixes issue with 2 overrides in release mode with VC6 (only happens with both ecere.dll and ide.exe compiled in release mode)
2515       if(reentrant) return;
2516       reentrant = true;
2517
2518       updatingCode++;
2519
2520       if(selected)
2521       {
2522          selectedClassName = CopyString(oClass.name);
2523          if(selected != oClass)
2524          {
2525             ObjectInfo object = this.selected;
2526             selectedName = CopyString(object.name);
2527             if(!selectedName)
2528             {
2529                ObjectInfo check;
2530                for(check = this.oClass.instances.first; check; check = check.next)
2531                {
2532                   if(check == object)
2533                      break;
2534                   selectedPos++;
2535                }
2536             }
2537          }
2538          else 
2539             selectedPos = -1;
2540       }
2541
2542       editBox.GetSelPos(&l1, &y1, &x1, &l2, &y2, &x2, false);
2543
2544       defines.Free(FreeModuleDefine);
2545       imports.Free(FreeModuleImport);
2546
2547       SetGlobalData(&globalData);
2548       SetGlobalContext(globalContext);
2549       SetExcludedSymbols(&excludedSymbols);
2550       SetTopContext(globalContext);
2551       SetCurrentContext(globalContext);
2552       SetDefines(&defines);
2553       SetImports(&imports);
2554       SetCurrentNameSpace(null);
2555
2556       /*
2557       sprintf(command, "C:\\Program Files\\Microsoft Visual Studio\\VC98\\Bin\\cl "
2558          "/nologo /D \"MSC\" /D \"WIN32\" /D \"NDEBUG\" /D \"_WINDOWS\" /D \"_MBCS\" "
2559          "/I \"C:\\Program Files\\Microsoft Visual Studio\\VC98\\Include\" "
2560          "/I T:\\ecere\\include /E %s", argv[1]);
2561       */
2562
2563       /*
2564       ChangeWorkingDir("e:\\ec");
2565       sprintf(command, "gcc -x c -E -");
2566       fileInput = DualPipeOpen({ output = true, input = true }, command);
2567       SetFileInput(fileInput);
2568       {
2569          for(;;)
2570          {
2571             byte buffer[8192];
2572             uint count = editFile.Read(buffer, 1, sizeof(buffer));
2573             if(count)
2574                fileInput.Write(buffer, 1, count);
2575             else
2576                break;
2577          }
2578          delete editFile;
2579          fileInput.CloseOutput();
2580       }
2581       */
2582
2583       // TOCHECK: COULDN'T WE CALL FreeParser here?
2584       // Clear everything
2585       this.functionType = null;
2586       this.instanceType = null;
2587
2588       // Select nothing
2589       sheet.SelectObject(null);
2590
2591       designer.Reset();
2592
2593       selected = null;
2594
2595       // We don't want the designer to be notified of selection when deleting rows...
2596       backDesigner = designer;
2597       designer = null;
2598
2599       if(this.oClass)
2600       {
2601          ObjectInfo _class, next;
2602          
2603          for(_class = classes.first; _class; _class = next)
2604          {
2605             ObjectInfo object;
2606
2607             next = _class.next;
2608             
2609             for(;object = _class.instances.first;)
2610             {
2611                if(object.instance)
2612                {
2613                   Designer::DestroyObject(object.instance);
2614                   delete object.instance;
2615                }
2616                sheet.DeleteObject(object);
2617                delete object.name;
2618                _class.instances.Delete(object);
2619             }
2620             if(_class.instance)
2621             {
2622                Designer::DestroyObject(_class.instance);
2623                delete _class.instance;
2624             }
2625             sheet.DeleteObject(_class);
2626             delete _class.name;
2627             classes.Delete(_class);
2628          }
2629          this.oClass = null;
2630       }
2631
2632       {
2633          Class windowClass = eSystem_FindClass(this.privateModule, "ecere::gui::Window");
2634          if(windowClass && windowClass.data)
2635             UnapplySkin(windowClass);
2636       }
2637
2638       designer = backDesigner;
2639
2640       SetEchoOn(true);
2641       fileInput = editFile = EditBoxStream { editBox = editBox };
2642       SetFileInput(fileInput);
2643
2644       if(ast)
2645       {
2646          FreeASTTree(ast);
2647          ast = null;
2648          //SetAST(null);
2649       }
2650
2651       FreeContext(this.globalContext);
2652       FreeExcludedSymbols(this.excludedSymbols);
2653
2654       FreeIncludeFiles();
2655       FreeGlobalData(&this.globalData);
2656
2657       if(this.privateModule)
2658       {
2659          FreeTypeData(this.privateModule);
2660          delete this.privateModule;
2661       }
2662
2663 #ifdef _TIMINGS
2664       startTime = GetTime();
2665       printf("Cleaning up took %.3f seconds\n", startTime - parseCodeStart);
2666
2667       printf("classes.count: %d\n", globalContext.classes.count);
2668 #endif
2669
2670       if(ide.workspace)
2671       {
2672          CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.compiler);
2673          SetTargetBits(compiler.supportsBitDepth ? 32 : GetHostBits());
2674          delete compiler;
2675       }
2676       this.privateModule = __ecere_COM_Initialize(false | ((GetTargetBits() == sizeof(uintptr) *8) ? 0 : GetTargetBits() == 64 ? 2 : 4), 1, null);
2677
2678       SetPrivateModule(privateModule);
2679
2680       {
2681          globalContext.types.Add((BTNode)Symbol { string = CopyString("uint"), type = ProcessTypeString("unsigned int", false) });
2682          globalContext.types.Add((BTNode)Symbol { string = CopyString("uint64"), type = ProcessTypeString("unsigned int64", false) });
2683          globalContext.types.Add((BTNode)Symbol { string = CopyString("uint32"), type = ProcessTypeString("unsigned int", false) });
2684          globalContext.types.Add((BTNode)Symbol { string = CopyString("uint16"), type = ProcessTypeString("unsigned short", false) });
2685          globalContext.types.Add((BTNode)Symbol { string = CopyString("byte"), type = ProcessTypeString("unsigned char", false) });
2686       }
2687
2688       fileName = this.fileName;
2689       project = null;
2690       if(ide.workspace && ide.workspace.projects && fileName)
2691       {
2692          for(p : ide.workspace.projects)
2693          {
2694             char path[MAX_LOCATION];
2695             ProjectNode pn;
2696             MakePathRelative(fileName, p.topNode.path, path);
2697             MakeSlashPath(path);
2698
2699             pn = p.topNode.FindWithPath(path, false);
2700             if(pn)
2701             {
2702                project = p;
2703                break;
2704             }
2705          }
2706       }
2707       if(!project)
2708          project = ide.project;
2709          
2710       GetWorkingDir(oldWorkDir, MAX_LOCATION);
2711       if(project)
2712          ChangeWorkingDir(project.topNode.path);
2713
2714       SetSomeSourceFileStack(fileName ? fileName : "", 0); //strcpy(sourceFileStack[0], fileName ? fileName : "");
2715
2716       GetLastDirectory(fileName, mainModuleName);
2717       GetExtension(mainModuleName, extension);
2718
2719       SetBuildingEcereCom(false);
2720       SetBuildingEcereComModule(false);
2721
2722       // TODO: Get symbolsDir from project settings instead...
2723       if(ide.projectView)
2724       {
2725          CompilerConfig compiler = ideSettings.GetCompilerConfig(ide.workspace.compiler);
2726          ProjectConfig config = project.config;
2727          DirExpression objDir = project.GetObjDir(compiler, config);
2728          SetSymbolsDir(objDir.dir);
2729          delete objDir;
2730          delete compiler;
2731          // SetIncludeDirs(ide.projectView.project.config.includeDirs);
2732          // SetSysIncludeDirs(ide.ideSettings.systemDirs[includes]);
2733       }
2734       else
2735       {
2736          switch(GetRuntimePlatform())
2737          {
2738             case win32: SetSymbolsDir("obj/debug.win32"); break;
2739             case tux:   SetSymbolsDir("obj/debug.linux"); break;
2740             case apple: SetSymbolsDir("obj/debug.apple"); break;
2741          }         
2742          SetIncludeDirs(null);
2743          SetSysIncludeDirs(null);
2744       }
2745
2746       {
2747          if(ide.projectView && ide.projectView.IsModuleInProject(this.fileName))
2748          {
2749             // TODO FIX for configless project
2750             if(ide.project.config && ide.project.config.options && ide.project.config.options.preprocessorDefinitions)
2751             {
2752                for(item : ide.project.config.options.preprocessorDefinitions)
2753                {
2754                   if(!strcmp(item, "BUILDING_ECERE_COM"))
2755                   {
2756                      SetBuildingEcereCom(true);
2757                      break;
2758                   }
2759                }
2760             }
2761          }
2762          
2763          if(!(strcmpi(mainModuleName, "instance.ec") && strcmpi(mainModuleName, "BinaryTree.ec") &&
2764             strcmpi(mainModuleName, "dataTypes.ec") && strcmpi(mainModuleName, "OldList.ec") &&
2765             strcmpi(mainModuleName, "String.ec") && strcmpi(mainModuleName, "BTNode.ec") &&
2766             strcmpi(mainModuleName, "Array.ec") && strcmpi(mainModuleName, "AVLTree.ec") &&
2767             strcmpi(mainModuleName, "BuiltInContainer.ec") && strcmpi(mainModuleName, "Container.ec") &&
2768             strcmpi(mainModuleName, "CustomAVLTree.ec") && strcmpi(mainModuleName, "LinkList.ec") &&
2769             strcmpi(mainModuleName, "List.ec") && strcmpi(mainModuleName, "Map.ec") &&
2770             strcmpi(mainModuleName, "Mutex.ec")))
2771          {
2772             SetBuildingEcereComModule(true);
2773          }
2774
2775          // Predeclare all classes
2776          {
2777             char symFile[MAX_FILENAME];
2778             char symLocation[MAX_LOCATION];
2779             ImportedModule module, next;
2780
2781             GetLastDirectory(fileName, symFile);
2782             ChangeExtension(symFile, "sym", symFile);
2783
2784             strcpy(symLocation, GetSymbolsDir());
2785             PathCat(symLocation, symFile);
2786             
2787             // if(!GetEcereImported() && !GetBuildingEcereCom())
2788             if(!strcmp(extension, "ec") || !strcmp(extension, "eh"))
2789             {
2790 #ifdef _TIMINGS
2791                startTime = GetTime();
2792 #endif
2793                eModule_LoadStrict(privateModule, "ecereCOM", privateAccess);
2794 #ifdef _TIMINGS
2795                printf("Loading ecereCOM took %.3f seconds\n", GetTime() - startTime);
2796 #endif
2797             }
2798
2799 #ifdef _TIMINGS
2800             startTime = GetTime();
2801 #endif
2802             // LoadSymbols(symLocation, normalImport, true);
2803             LoadSymbols(symLocation, preDeclImport, false);
2804 #ifdef _TIMINGS
2805             printf("Loading symbols took %.3f seconds\n", GetTime() - startTime);
2806 #endif
2807
2808             for(module = defines.first; module; module = next)
2809             {
2810                next = module.next;
2811                if(module.type == moduleDefinition && strcmpi(module.name, mainModuleName))
2812                {
2813                   delete module.name;
2814                   defines.Delete(module);
2815                }
2816             }
2817          }
2818       }
2819       if(!strcmp(extension, "ec") || !strcmp(extension, "eh"))
2820       {
2821          SetDefaultDeclMode(privateAccess);
2822          SetDeclMode(privateAccess);
2823       }
2824       else
2825       {
2826          SetDefaultDeclMode(defaultAccess);
2827          SetDeclMode(defaultAccess);
2828       }
2829
2830       StripExtension(mainModuleName);
2831       module = ImportedModule { name = CopyString(mainModuleName), type = moduleDefinition };
2832       defines.AddName(module);
2833
2834    #ifdef _DEBUG
2835       // SetYydebug(true);
2836    #endif
2837       resetScanner();
2838
2839 #ifdef _TIMINGS
2840       startTime = GetTime();
2841       startFindClass = checkTypeTotalTime;
2842 #endif
2843       ParseEc();
2844 #ifdef _TIMINGS
2845       printf("ParseEc took %.3f seconds, out of which %.3f seconds were in CheckType\n", GetTime() - startTime, checkTypeTotalTime - startFindClass);
2846 #endif
2847       CheckDataRedefinitions();
2848       SetYydebug(false);
2849
2850       SetIncludeDirs(null);
2851       SetSysIncludeDirs(null);
2852       
2853       delete editFile;
2854       fileInput = null;
2855       SetFileInput(null);
2856
2857       if(GetAST())
2858       {
2859          ast = GetAST();
2860          
2861 #ifdef _TIMINGS
2862          startTime = GetTime();
2863 #endif
2864          PrePreProcessClassDefinitions();
2865          ComputeModuleClasses(privateModule);
2866          PreProcessClassDefinitions();
2867          ProcessClassDefinitions();
2868 #ifdef _TIMINGS
2869          printf("Initial Passes took %.3f seconds\n", GetTime() - startTime);
2870          startTime = GetTime();
2871 #endif
2872
2873          ComputeDataTypes();
2874 #ifdef _TIMINGS
2875          printf("ComputeDataTypes took %.3f seconds\n", GetTime() - startTime);
2876          startTime = GetTime();
2877 #endif
2878          ProcessInstantiations();
2879 #ifdef _TIMINGS
2880          printf("ProcessInstantiations took %.3f seconds\n", GetTime() - startTime);
2881 #endif
2882
2883          if(!strcmp(extension, "ec") || !strcmp(extension, "eh"))
2884          {
2885             Class windowClass = eSystem_FindClass(this.privateModule, "ecere::gui::Window");
2886             if(!windowClass || windowClass.internalDecl)
2887             {
2888 #ifdef _TIMINGS
2889                startTime = GetTime();
2890 #endif
2891                // *** COMMENTED THIS OUT DUE TO ecereCOM issues
2892                // eModule_Load(this.privateModule.application.allModules.first ? this.privateModule.application.allModules.first : this.privateModule, "ecere", privateAccess);
2893                eModule_Load(this.privateModule, "ecere", privateAccess);
2894 #ifdef _TIMINGS
2895                printf("Loading ecere.dll took %.3f seconds\n", GetTime() - startTime);
2896 #endif
2897             }
2898             windowClass = eSystem_FindClass(this.privateModule, "ecere::gui::Window");
2899
2900             if(windowClass && windowClass.data)
2901                ApplySkin(windowClass, app.currentSkin.name, null);
2902          }
2903
2904 #ifdef _TIMINGS
2905          startTime = GetTime();
2906 #endif
2907          for(external = ast->first; external; external = external.next)
2908          {
2909             if(external.type == classExternal)
2910             {
2911                ClassDefinition _class = external._class;
2912                if(_class.baseSpecs && _class.baseSpecs->first && ((Specifier)_class.baseSpecs->first).type == nameSpecifier ) // classSpecifier
2913                {
2914                   Class regClass = eSystem_FindClass(this.privateModule, ((Specifier)_class.baseSpecs->first).name);
2915                   if(regClass)
2916                   {
2917                      if(eClass_GetDesigner(regClass) && !GetBuildingEcereComModule())
2918                      {
2919                         Instance instance = eInstance_New(regClass);
2920                         ObjectInfo classObject 
2921                         {
2922                            name = CopyString(_class._class.name);
2923                            instance = instance;
2924                            classDefinition = _class;
2925                            oClass = classObject;
2926                         };
2927                         Symbol symbol;
2928                         classes.Add(classObject);
2929
2930                         incref instance;
2931
2932                         // Moved this at bottom so that the file dialog doesn't show up in eCom
2933                         designer.CreateObject(instance, classObject, true, null);
2934                         sheet.AddObject(classObject, classObject.name ? classObject.name : _class._class.name, typeClass, false);
2935
2936                         if(_class.definitions)
2937                         {
2938                            ClassDef def;
2939                            ObjectInfo object;
2940                            for(def = _class.definitions->first; def; def = def.next)
2941                            {
2942                               switch(def.type)
2943                               {
2944                                  case defaultPropertiesClassDef:
2945                                  {
2946                                     MemberInit propDef;
2947                                     for(propDef = def.defProperties->first; propDef; propDef = propDef.next)
2948                                     {
2949                                        Identifier id = propDef.identifiers->first;
2950                                        if(id)
2951                                        {
2952                                           Property prop = eClass_FindProperty(regClass, id.string, this.privateModule);
2953                                           if(prop)
2954                                           {
2955                                              Class propertyClass = prop.dataTypeClass;
2956                                              if(!propertyClass)
2957                                                 propertyClass = prop.dataTypeClass = eSystem_FindClass(this.privateModule, prop.dataTypeString);
2958                                              if(prop.compiled && prop.Set && prop.Get && propertyClass && propDef.initializer && propDef.initializer.type == expInitializer && propDef.initializer.exp)
2959                                              {
2960                                                 FreeType(propDef.initializer.exp.destType);
2961                                                 propDef.initializer.exp.destType = MkClassType(propertyClass.name);
2962                                                 ProcessExpressionType(propDef.initializer.exp);
2963                                              
2964                                                 if(propertyClass.type == structClass || propertyClass.type == noHeadClass || propertyClass.type == normalClass)
2965                                                 {
2966                                                    Expression computed = CopyExpression(propDef.initializer.exp);
2967                                                    ComputeExpression(computed);
2968
2969                                                    if(computed.isConstant && computed.type == instanceExp && !id.next)
2970                                                    {
2971                                                       if(prop.Set)
2972                                                       {
2973                                                          if(computed.instance._class && computed.instance._class.symbol &&
2974                                                             computed.instance._class.symbol.registered && 
2975                                                             eClass_IsDerived(computed.instance._class.symbol.registered, propertyClass))
2976                                                          {
2977                                                             ((void (*)(void *, void *))(void *)prop.Set)(instance, computed.instance.data);
2978
2979                                                             // This was saved in the control and shouldn't be freed by FreeExpression...
2980                                                             if(propertyClass.type == normalClass)
2981                                                                computed.instance.data = null;
2982                                                          }
2983                                                       }
2984                                                    }
2985                                                    // MOVED THIS UP NOW THAT char * IS A NORMAL CLASS
2986                                                    else if(computed.type == stringExp && propertyClass.dataTypeString && strstr(propertyClass.dataTypeString, "char *"))
2987                                                    {
2988                                                       String temp = new char[strlen(computed.string)+1];
2989                                                       ReadString(temp, computed.string);
2990                                                       ((void (*)(void *, void *))(void *)prop.Set)(instance, temp);
2991                                                       delete temp;
2992                                                    }
2993                                                    else
2994                                                       propDef.variable = true;
2995                                                    
2996                                                    FreeExpression(computed);
2997                                                 }
2998                                                 else
2999                                                 {
3000                                                    Expression computed = CopyExpression(propDef.initializer.exp);
3001                                                    ComputeExpression(computed);
3002                                                    if(computed.isConstant)
3003                                                    {
3004                                                       //if(computed.type == memberExp) computed = computed.member.exp;
3005
3006                                                       if(computed.type == constantExp)
3007                                                       {
3008                                                          Operand value = GetOperand(computed);
3009                                                          DataValue valueData;
3010                                                          valueData.i64 = value.i64;
3011                                                          SetProperty(prop, instance, valueData);
3012                                                       }
3013                                                       else if(computed.type == stringExp && propertyClass.dataTypeString && strstr(propertyClass.dataTypeString, "char *"))
3014                                                       {
3015                                                          String temp = new char[strlen(computed.string)+1];
3016                                                          ReadString(temp, computed.string);
3017                                                          ((void (*)(void *, void *))(void *)prop.Set)(instance, temp);
3018                                                          delete temp;
3019                                                       }
3020                                                    }
3021                                                    else
3022                                                       propDef.variable = true;
3023
3024                                                    FreeExpression(computed);
3025                                                 }
3026                                              }
3027                                              else
3028                                                 propDef.variable = true;
3029                                           }
3030                                           else
3031                                           {
3032                                              Method method = eClass_FindMethod(regClass, id.string, this.privateModule);
3033                                              if(method && method.type == virtualMethod && propDef.initializer && propDef.initializer.type == expInitializer && 
3034                                                 propDef.initializer.exp && propDef.initializer.exp.type == identifierExp)
3035                                              {
3036                                                 ClassDef def;
3037                                                 // Maintain a list in FunctionDefinition of who is attached to it
3038                                                 for(def = _class.definitions->first; def; def = def.next)
3039                                                 {
3040                                                    if(def.type == functionClassDef)
3041                                                    {
3042                                                       ClassFunction function = def.function;
3043                                                       if(!strcmp(function.declarator.symbol.string, propDef.initializer.exp.identifier.string))
3044                                                       {
3045                                                          function.attached.Add(OldLink { data = method });
3046                                                       }
3047                                                    }
3048                                                 }
3049                                              }                                          
3050                                           }
3051                                        }
3052                                     }
3053                                     break;
3054                                  }
3055                                  case declarationClassDef:
3056                                  {
3057                                     Declaration decl = def.decl;
3058                                     switch(decl.type)
3059                                     {
3060                                        case instDeclaration:
3061                                        {
3062                                           Instantiation inst = decl.inst;
3063                                           Class instClass = eSystem_FindClass(this.privateModule, inst._class.name);
3064                                           if(instClass && eClass_GetDesigner(instClass))
3065                                           {
3066                                              Instance control = eInstance_New(instClass);
3067                                              incref control;
3068
3069                                              object = ObjectInfo
3070                                              {
3071                                                 oClass = classObject;
3072                                                 instance = control;
3073                                                 instCode = inst;
3074                                              };
3075                                              classObject.instances.Add(object);
3076                                              if(inst.exp)
3077                                                 // TOCHECK: Why is this needed now?
3078                                                 object.name = CopyString((inst.exp.type == memberExp) ? inst.exp.member.member.string : inst.exp.identifier.string);
3079                                              def.object = object;
3080
3081                                              // if(object.name) { symbol = eList_Add(&curContext.symbols, sizeof(Symbol)); symbol.string = object.name; symbol.type = MkClassType(instClass.name); }
3082
3083                                              designer.CreateObject(control, object, false, classObject.instance);
3084                                              sheet.AddObject(object, object.name ? object.name : inst._class.name, typeData, false);
3085                                           }
3086                                           break;
3087                                        }
3088                                     }
3089                                     break;
3090                                  }
3091                               }
3092                            }
3093
3094                            // Second pass, process instantiation members
3095                            object = null;
3096                            for(def = _class.definitions->first; def; def = def.next)
3097                            {
3098                               switch(def.type)
3099                               {
3100                                  case declarationClassDef:
3101                                  {
3102                                     Declaration decl = def.decl;
3103                                     switch(decl.type)
3104                                     {
3105                                        case instDeclaration:
3106                                        {
3107                                           Instantiation inst = decl.inst;
3108                                           Class instClass = eSystem_FindClass(this.privateModule, inst._class.name);
3109                                           if(instClass && eClass_GetDesigner(instClass))
3110                                           {
3111                                              Instance control;
3112                                              object = object ? object.next : classObject.instances.first;
3113                                              control = object.instance;                                             
3114                                              
3115                                              if(inst.members)
3116                                              {
3117                                                 MembersInit members;
3118                                                 for(members = inst.members->first; members; members = members.next)
3119                                                 {
3120                                                    switch(members.type)
3121                                                    {
3122                                                       case dataMembersInit:
3123                                                       {
3124                                                          if(members.dataMembers)
3125                                                          {
3126                                                             MemberInit member;
3127                                                             DataMember curMember = null;
3128                                                             Class curClass = null;
3129                                                             DataMember subMemberStack[256];
3130                                                             int subMemberStackPos = 0;
3131
3132                                                             for(member = members.dataMembers->first; member; member = member.next)
3133                                                             {
3134                                                                bool found = false;
3135                                                                Identifier ident = member.identifiers ? member.identifiers->first : null;
3136                                                                if(ident)
3137                                                                {
3138                                                                   DataMember _subMemberStack[256];
3139                                                                   int _subMemberStackPos = 0;
3140                                                                   DataMember thisMember = (DataMember)eClass_FindDataMember(instClass, ident.string, privateModule, _subMemberStack, &_subMemberStackPos);
3141
3142                                                                   if(!thisMember)
3143                                                                   {
3144                                                                      thisMember = (DataMember)eClass_FindProperty(instClass, ident.string, privateModule);
3145                                                                   }
3146                                                                   if(thisMember && thisMember.memberAccess == publicAccess)
3147                                                                   {
3148                                                                      curMember = thisMember;
3149                                                                      curClass = curMember._class;
3150                                                                      memcpy(subMemberStack, _subMemberStack, sizeof(int) * _subMemberStackPos);
3151                                                                      subMemberStackPos = _subMemberStackPos;
3152                                                                      found = true;
3153                                                                   }
3154                                                                }
3155                                                                else
3156                                                                {
3157                                                                   eClass_FindNextMember(instClass, &curClass, (DataMember *)&curMember, subMemberStack, &subMemberStackPos);
3158                                                                   if(curMember) found = true;
3159                                                                }
3160                                                                if(found && curMember.isProperty)
3161                                                                {
3162                                                                   Property prop = (Property) curMember;
3163                                                                   Class propertyClass = prop.dataTypeClass;
3164                                                                   if(!propertyClass)
3165                                                                      propertyClass = prop.dataTypeClass = eSystem_FindClass(this.privateModule, prop.dataTypeString);
3166
3167                                                                   if(prop.compiled && prop.Set && prop.Get && propertyClass && member.initializer && member.initializer.type == expInitializer && member.initializer.exp)
3168                                                                   {
3169                                                                      FreeType(member.initializer.exp.destType);
3170                                                                      member.initializer.exp.destType = MkClassType(propertyClass.name);
3171                                                                      if(propertyClass)
3172                                                                      {
3173                                                                         ProcessExpressionType(member.initializer.exp);
3174                                        
3175                                                                         if(propertyClass.type == structClass || propertyClass.type == normalClass || propertyClass.type == noHeadClass)
3176                                                                         {
3177                                                                            Expression computed;
3178 #ifdef _DEBUG
3179                                                                            /*char debugExpString[4096];
3180                                                                            debugExpString[0] = '\0';
3181                                                                            PrintExpression(member.initializer.exp, debugExpString);*/
3182 #endif
3183                                                                            computed = CopyExpression(member.initializer.exp);
3184                                                                            if(computed)
3185                                                                            {
3186                                                                               ComputeExpression(computed);
3187                                                                               
3188                                                                               if(computed.type == instanceExp && computed.isConstant && computed.isConstant)
3189                                                                               {
3190                                                                                  if(computed.instance.data)
3191                                                                                  {
3192                                                                                     if(computed.instance._class && computed.instance._class.symbol &&
3193                                                                                        computed.instance._class.symbol.registered && 
3194                                                                                        eClass_IsDerived(computed.instance._class.symbol.registered, propertyClass))
3195                                                                                     {
3196                                                                                        ((void (*)(void *, void *))(void *)prop.Set)(control, computed.instance.data);
3197
3198                                                                                        // This was saved in the control and shouldn't be freed by FreeExpression...
3199                                                                                        if(propertyClass.type == normalClass)
3200                                                                                           computed.instance.data = null;
3201                                                                                     }
3202                                                                                  }
3203                                                                               }
3204                                                                               else if(computed.type == identifierExp)
3205                                                                               {
3206                                                                                  member.variable = true;
3207
3208                                                                                  if(eClass_GetDesigner(propertyClass))
3209                                                                                  //if(prop.Set)
3210                                                                                  {
3211                                                                                     char * name = computed.identifier.string;
3212                                                                                     if(!strcmp(name, "this"))
3213                                                                                     {
3214                                                                                        if(prop.Set)
3215                                                                                           ((void (*)(void *, void *))(void *)prop.Set)(control, instance);
3216                                                                                        member.variable = false;
3217                                                                                     }
3218                                                                                     else
3219                                                                                     {
3220                                                                                        ObjectInfo check;
3221                                                                                        for(check = classObject.instances.first; check; check = check.next)
3222                                                                                           if(check.name && !strcmp(name, check.name))
3223                                                                                           {
3224                                                                                              if(prop.Set)
3225                                                                                                 ((void (*)(void *, void *))(void *)prop.Set)(control, check.instance);
3226                                                                                              member.variable = false;
3227                                                                                              break;
3228                                                                                           }
3229                                                                                     }
3230                                                                                  }
3231                                                                               }
3232                                                                               else if(computed.type == memberExp)
3233                                                                               {
3234                                                                                  member.variable = true;
3235                                                                                  if(computed.member.exp.type == identifierExp)
3236                                                                                  {
3237                                                                                     char * name = computed.member.exp.identifier.string;
3238                                                                                     if(!strcmp(name, "this"))
3239                                                                                     {
3240                                                                                        char * name = computed.member.member.string;
3241                                                                                        {
3242                                                                                           ObjectInfo check;
3243                                                                                           for(check = classObject.instances.first; check; check = check.next)
3244                                                                                              if(check.name && !strcmp(name, check.name))
3245                                                                                              {
3246                                                                                                 if(prop.Set)
3247                                                                                                    ((void (*)(void *, void *))(void *)prop.Set)(control, check.instance);
3248                                                                                                 member.variable = false;
3249                                                                                                 break;
3250                                                                                              }
3251                                                                                        }
3252                                                                                     }
3253                                                                                     else
3254                                                                                     {
3255                                                                                        ObjectInfo check;
3256                                                                                        for(check = classObject.instances.first; check; check = check.next)
3257                                                                                        {
3258                                                                                           if(check.name && !strcmp(name, check.name))
3259                                                                                           {
3260                                                                                              Property getProperty = eClass_FindProperty(check.instance._class, computed.member.member.string, this.privateModule);
3261                                                                                              if(getProperty)
3262                                                                                              {
3263                                                                                                 DataValue value { };
3264                                                                                                 GetProperty(getProperty, check.instance, &value);
3265                                                                                                 SetProperty(prop, control, value);
3266                                                                                                 member.variable = false;
3267                                                                                              }
3268                                                                                              break;
3269                                                                                           }
3270                                                                                        }
3271                                                                                     }
3272                                                                                  }
3273                                                                               }
3274                                                                               // MOVED THIS UP NOW THAT char * IS A NORMAL CLASS
3275                                                                               else if(computed.isConstant && computed.type == stringExp && propertyClass.dataTypeString && strstr(propertyClass.dataTypeString, "char *"))
3276                                                                               {
3277                                                                                  String temp = new char[strlen(computed.string)+1];
3278                                                                                  ReadString(temp, computed.string);
3279                                                                                  ((void (*)(void *, void *))(void *)prop.Set)(control, temp);
3280                                                                                  delete temp;
3281                                                                               }
3282                                                                               else
3283                                                                                  member.variable = true;
3284
3285                                                                               FreeExpression(computed);
3286                                                                            }
3287                                                                         }
3288                                                                         else
3289                                                                         {
3290                                                                            Expression computed = CopyExpression(member.initializer.exp);
3291                                                                            if(computed)
3292                                                                            {
3293                                                                               ComputeExpression(computed);
3294                                                                               if(computed.isConstant)
3295                                                                               {
3296                                                                                  if(computed.type == constantExp && (!propertyClass.dataTypeString || strcmp(propertyClass.dataTypeString, "char *"))) //(strcmp(propertyClass.name, "char *") && (strcmp(propertyClass.name, "String"))))
3297                                                                                  {
3298                                                                                     if(!strcmp(propertyClass.dataTypeString, "float"))
3299                                                                                        ((void (*)(void *, float))(void *)prop.Set)(control, (float)strtod(computed.constant, null));
3300                                                                                     else if(!strcmp(propertyClass.dataTypeString, "double"))
3301                                                                                        ((void (*)(void *, double))(void *)prop.Set)(control, strtod(computed.constant, null));
3302                                                                                     else
3303                                                                                        ((void (*)(void *, int))(void *)prop.Set)(control, strtol(computed.constant, null, 0));
3304                                                                                  }
3305                                                                                  else if(computed.type == stringExp  && propertyClass.dataTypeString && strstr(propertyClass.dataTypeString, "char *"))
3306                                                                                  {
3307                                                                                     String temp = new char[strlen(computed.string)+1];
3308                                                                                     ReadString(temp, computed.string);
3309                                                                                     ((void (*)(void *, void *))(void *)prop.Set)(control, temp);
3310                                                                                     delete temp;
3311                                                                                  }
3312                                                                               }
3313                                                                               else
3314                                                                                  member.variable = true;
3315
3316                                                                               FreeExpression(computed);
3317                                                                            }
3318                                                                         }
3319                                                                      }
3320                                                                   }
3321                                                                   else
3322                                                                      member.variable = true;
3323                                                                }
3324                                                                else if(ident && member.initializer && member.initializer.type == expInitializer && member.initializer.exp && 
3325                                                                   member.initializer.exp.type == memberExp) // identifierExp
3326                                                                {
3327                                                                   Method method = eClass_FindMethod(instClass, ident.string, this.privateModule);
3328                                                                   if(method && method.type == virtualMethod)
3329                                                                   {
3330                                                                      ClassDef def;
3331                                                                      // Maintain a list in FunctionDefinition of who is attached to it
3332                                                                      for(def = _class.definitions->first; def; def = def.next)
3333                                                                      {
3334                                                                         if(def.type == functionClassDef)
3335                                                                         {
3336                                                                            ClassFunction function = def.function;
3337                                                                            Identifier id = (member.initializer.exp.type == memberExp) ? member.initializer.exp.member.member : member.initializer.exp.identifier;
3338                                                                            if(function.declarator && !strcmp(function.declarator.symbol.string, id.string))
3339                                                                            {
3340                                                                               function.attached.Add(OldLink { data = method });
3341                                                                               // Reference this particular instance?
3342                                                                            }
3343                                                                         }
3344                                                                      }
3345                                                                   }
3346                                                                }
3347                                                                id++;
3348                                                             }
3349                                                          }
3350                                                          break;
3351                                                       }
3352                                                    }
3353                                                 }                                          
3354                                              }
3355
3356                                              designer.PostCreateObject(object.instance, object, false, classObject.instance);
3357                                              break;
3358                                           }
3359                                        }
3360                                        break;
3361                                     }
3362                                  }
3363                               }
3364                            }
3365                         }
3366
3367                         //designer.CreateObject(instance, classObject, true, null);
3368                         //sheet.AddObject(classObject, classObject.name ? classObject.name : _class._class.name, classType, false);
3369
3370                         designer.PostCreateObject(instance, classObject, true, null);
3371
3372                         //instance.state = Hidden;
3373                         //instance.Create();
3374                         //instance.SetState(Normal, true, 0);
3375                      }
3376                   }
3377                }
3378             }
3379          }
3380
3381          SetAST(null);
3382 #ifdef _TIMINGS
3383          printf("Class/Instance Processing took %.3f seconds\n", GetTime() - startTime);
3384 #endif
3385       }
3386
3387       // Restore Selection
3388       if(selectedClassName)
3389       {
3390          ObjectInfo oClass;
3391          for(oClass = classes.first; oClass; oClass = oClass.next)
3392          {
3393             if(!strcmp(oClass.name, selectedClassName))
3394             {
3395                this.oClass = oClass;
3396                break;
3397             }
3398          }
3399          delete selectedClassName;
3400       }
3401       if(this.oClass)
3402       {
3403          if(selectedName)
3404          {
3405             ObjectInfo check;
3406             int pos = 0;
3407          
3408             for(check = this.oClass.instances.first; check; check = check.next)
3409             {
3410                if(check.name && !strcmp(check.name, selectedName))
3411                {
3412                   this.selected = check;
3413                   break;
3414                }
3415             }
3416             if(!check)
3417             {
3418                if(this.oClass.instances.first)
3419                   this.selected = this.oClass.instances.first;
3420                else
3421                   this.selected = this.oClass;
3422             }
3423          }
3424          else if(selectedPos == -1 || !this.oClass.instances.count)
3425             this.selected = this.oClass;
3426          else
3427          {
3428             ObjectInfo check;
3429             int pos = 0;
3430
3431             if(selectedPos > this.oClass.instances.count)
3432                selectedPos = 0;
3433             for(check = this.oClass.instances.first; check; check = check.next)
3434             {
3435                if(selectedPos == pos++)
3436                {
3437                   this.selected = check;
3438                   break;
3439                }
3440             }
3441          }
3442       }
3443       else
3444       {
3445          this.oClass = classes.first;
3446          this.selected = (this.oClass && this.oClass.instances.first) ? this.oClass.instances.first : this.oClass;
3447       }
3448       delete selectedName;
3449       SetSymbolsDir(null);
3450
3451       if(sheet.codeEditor == this)
3452          sheet.SelectObject(selected);
3453       Update(null);
3454
3455       codeModified = false;
3456
3457       // TESTING THIS TO NOT GET EMPTY PARAMETERS
3458       if(paramsShown)
3459       {
3460          InvokeParameters(false, false, false);
3461       }
3462
3463       editBox.SetSelPos(l1, y1, x1, l2, y2, x2);
3464
3465       reentrant = false;
3466
3467       updatingCode--;
3468
3469       ChangeWorkingDir(oldWorkDir);
3470 #ifdef _TIMINGS
3471       printf("Total FindClass time is %.3f seconds, out of which %.3f is in Ignore NS\n\n", findClassTotalTime, findClassIgnoreNSTotalTime);
3472       printf("Total CheckType time is %.3f seconds\n\n", checkTypeTotalTime);
3473       printf("Total MkExternalImport time is %.3f seconds\n\n", externalImportTotalTime);
3474       printf("Total FindSymbol time is %.3f seconds\n\n", findSymbolTotalTime);
3475       // printf("Total Class Members Find time is %.3f seconds\n\n", GetClassFindTime());
3476       
3477       printf("Whole ParseCode function took %.3f seconds\n\n", GetTime() - parseCodeStart);
3478 #endif
3479       if(inUseDebug && ide.projectView)
3480          ide.debugger.EvaluateWatches();
3481    }
3482
3483    void UpdateInstanceCodeClass(Class _class, ObjectInfo object, EditBoxStream f, Instance test, bool * prev, bool * lastIsMethod, DataMember * curMember, Class * curClass)
3484    {
3485       Property propIt;
3486       Window control = (Window)object.instance;
3487       ObjectInfo classObject = object.oClass;
3488
3489       if(_class.base && _class.base.type != systemClass) UpdateInstanceCodeClass(_class.base, object, f, test, prev, lastIsMethod, curMember, curClass);
3490
3491       if(!strcmp(_class.name, "DesignerBase")) return;
3492
3493       for(propIt = _class.membersAndProperties.first; propIt; propIt = propIt.next)
3494       {
3495          Property prop = eClass_FindProperty(object.instance._class, propIt.name, privateModule);
3496          if(prop && prop.isProperty && !prop.conversion && eClass_FindProperty(object.instance._class, prop.name, privateModule))
3497          {
3498             if(prop.Set && prop.Get && prop.dataTypeString && strcmp(prop.name, "name") && !Code_IsPropertyDisabled(object, prop.name) &&
3499                prop.compiled && (!prop.IsSet || prop.IsSet(control)))
3500             {
3501                Class dataType = prop.dataTypeClass;
3502                if(!dataType)
3503                   dataType = prop.dataTypeClass = eSystem_FindClass(this.privateModule, prop.dataTypeString);
3504          
3505                if(dataType)
3506                {
3507                   if(dataType.type == structClass)
3508                   {
3509                      void * dataForm = new0 byte[dataType.structSize];
3510                      void * dataTest = new0 byte[dataType.structSize];
3511                
3512                      ((void (*)(void *, void *))(void *)prop.Get)(control, dataForm);
3513                      ((void (*)(void *, void *))(void *)prop.Get)(test, dataTest);
3514                
3515                      if((prop.IsSet && !prop.IsSet(test)) || ((int (*)(void *, void *, void *))(void *)dataType._vTbl[__ecereVMethodID_class_OnCompare])(dataType, dataForm, dataTest))
3516                      {
3517                         char tempString[1024] = "";
3518                         char * string = "";
3519                         bool needClass = true;
3520                         if(*prev)
3521                            f.Printf(", ");
3522                   
3523                         ((void (*)(void *, void *))(void *)prop.Set)(test, dataForm);
3524                   
3525                         string = ((char * (*)(void *, void *, void *, void *, void *))(void *)dataType._vTbl[__ecereVMethodID_class_OnGetString])(dataType, dataForm, tempString, null, &needClass);
3526                         
3527                         eClass_FindNextMember(_class, curClass, curMember, null, null);
3528                         if(*curMember != (DataMember)prop)
3529                            f.Printf("%s = ", prop.name);
3530
3531                         *curMember = (DataMember)prop;
3532                         *curClass = curMember->_class;
3533
3534                         if(needClass)
3535                            f.Printf("%c %s %c", /*dataType.name, */OpenBracket, string, CloseBracket);
3536                         else
3537                            f.Printf("%s", string);
3538                         *prev = true;
3539                      }
3540
3541                      delete dataForm;
3542                      delete dataTest;
3543                   }
3544                   else if(dataType.type == normalClass || dataType.type == noHeadClass)
3545                   {
3546                      void * dataForm, * dataTest;
3547                
3548                      dataForm = ((void *(*)(void *))(void *)prop.Get)(control);
3549                      dataTest = ((void *(*)(void *))(void *)prop.Get)(test);
3550                
3551                      if((prop.IsSet && !prop.IsSet(test)) || ((int (*)(void *, void *, void *))(void *)dataType._vTbl[__ecereVMethodID_class_OnCompare])(dataType, dataForm, dataTest))
3552                      {
3553                         char tempString[1024] = "";
3554                         char * string = "";
3555                         if(*prev)
3556                            f.Printf(", ");
3557                   
3558                         ((void (*)(void *, void *))(void *)prop.Set)(test, dataForm);
3559                   
3560                         eClass_FindNextMember(_class, curClass, curMember, null, null);
3561                         if(*curMember != (DataMember)prop)
3562                            f.Printf("%s = ", prop.name);
3563                         *curMember = (DataMember)prop;
3564                         *curClass = curMember->_class;
3565
3566                         if(eClass_GetDesigner(dataType))
3567                         {
3568                            if(eClass_IsDerived(classObject.instance._class, dataType) && classObject.instance == dataForm)
3569                            //if(!strcmp(classObject.instance._class.name, dataType.name) && classObject.instance == dataForm)
3570                               f.Printf("this", prop.name);
3571                            else
3572                            {
3573                               //ObjectInfo classObject;
3574                               //for(classObject = classes.first; classObject; classObject = classObject.next)
3575                               {
3576                                  ObjectInfo object;
3577
3578                                  for(object = classObject.instances.first; object; object = object.next)
3579                                  {
3580                                     if(!object.deleted && eClass_IsDerived(object.instance._class, dataType) && object.instance == dataForm && object.name)
3581                                     {
3582                                        f.Printf("%s", object.name);
3583                                        break;
3584                                     }
3585                                  }
3586
3587                                  if(!object)
3588                                  {
3589                                     bool needClass = true;
3590                                     string = ((char * (*)(void *, void *, void *, void *, void *))(void *)dataType._vTbl[__ecereVMethodID_class_OnGetString])(dataType, dataForm, tempString, null, &needClass);
3591                                     f.Printf("%s", string);
3592                                  }
3593                               }
3594                            }
3595                         }
3596                         else
3597                         {
3598                            bool needClass = true;
3599                            string = ((char * (*)(void *, void *, void *, void *, void *))(void *)dataType._vTbl[__ecereVMethodID_class_OnGetString])(dataType, dataForm, tempString, null, &needClass);
3600
3601                            if(!strcmp(dataType.dataTypeString, "char *"))
3602                            {
3603                               f.Printf("\"");
3604                               OutputString(f, string);
3605                               f.Puts("\"");
3606                            }
3607                            else if(needClass)
3608                               f.Printf("%c %s %c", /*dataType.name, */OpenBracket, string, CloseBracket);
3609                            else
3610                               f.Printf("%s", string);
3611                         }
3612                         *prev = true;
3613                         *lastIsMethod = false;
3614                      }
3615                   }
3616                   else
3617                   {
3618                      DataValue dataForm, dataTest;
3619                
3620                      GetProperty(prop, control, &dataForm);
3621                      GetProperty(prop, test, &dataTest);
3622                
3623                      if((prop.IsSet && !prop.IsSet(test)) || ((int (*)(void *, void *, void *))(void *)dataType._vTbl[__ecereVMethodID_class_OnCompare])(dataType, &dataForm, &dataTest))
3624                      {
3625                         char * string;
3626                         char tempString[1024] = "";
3627                         SetProperty(prop, test, dataForm);
3628                   
3629                         if(dataType.type != bitClass)
3630                         {
3631                            bool needClass = true;
3632
3633                            if(dataType.type == enumClass)
3634                            {
3635                               NamedLink value;
3636                               Class enumClass = eSystem_FindClass(privateModule, "enum");
3637                               EnumClassData e = ACCESS_CLASSDATA(dataType, enumClass);
3638
3639                               for(value = e.values.first; value; value = value.next)
3640                               {
3641                                  if((int)value.data == dataForm.i)
3642                                  {
3643                                     string = value.name;
3644                                     break;
3645                                  }
3646                               }
3647                            }
3648                            else
3649                               string = ((char * (*)(void *, void *, void *, void *, void *))(void *)dataType._vTbl[__ecereVMethodID_class_OnGetString])(dataType, &dataForm, tempString, null, &needClass);
3650                      
3651                            if(string && string[0])
3652                            {
3653                               if(*prev)
3654                                  f.Printf(", ");
3655
3656                               eClass_FindNextMember(_class, curClass, curMember, null, null);
3657                               if(*curMember != (DataMember)prop)
3658                                  f.Printf("%s = ", prop.name);
3659                               *curMember = (DataMember)prop;
3660                               *curClass = curMember->_class;
3661
3662                               if(!strcmp(dataType.dataTypeString, "float") && strchr(string, '.'))
3663                                  f.Printf("%sf", string);
3664                               else
3665                                  f.Printf("%s", string);
3666                               *prev = true;
3667                            }
3668                         }
3669                         else if(dataType.type == bitClass)
3670                         {
3671                            bool needClass = true;
3672
3673                            if(*prev) f.Printf(", ");
3674
3675                            eClass_FindNextMember(_class, curClass, curMember, null, null);
3676                            if(*curMember != (DataMember)prop)
3677                               f.Printf("%s = ", prop.name);
3678                            *curMember = (DataMember)prop;
3679                            *curClass = curMember->_class;
3680
3681                            string = ((char * (*)(void *, void *, void *, void *, void *))(void *)dataType._vTbl[__ecereVMethodID_class_OnGetString])(dataType, &dataForm.ui, tempString, null, &needClass);
3682                            if(needClass)
3683                               f.Printf("%c %s %c", /*dataType.name, */OpenBracket, string, CloseBracket);
3684                            else
3685                               f.Printf("%s", string);
3686                            *prev = true;
3687                            *lastIsMethod = false;
3688                         }
3689                      }
3690                   }
3691                }
3692             }
3693          }
3694       }
3695    }
3696
3697    int UpdateInstanceCode(EditBoxStream f, int position, Class regClass, ObjectInfo object, bool * firstObject, char ** text, int * textSize, int movedFuncIdLen, int movedFuncIdPos)
3698    {
3699       Instantiation inst = object.instCode;
3700       Window control = (Window)object.instance;
3701       bool prev = false;
3702       bool methodPresent = false;
3703       Class _class;
3704       bool lastIsMethod = true;
3705       ObjectInfo classObject = object.oClass;
3706       
3707       if(inst)
3708       {
3709          if(object.deleted)
3710          {
3711             // Instance removed, delete it
3712             DeleteJunkBefore(f, inst.loc.start.pos, &position);
3713
3714             f.DeleteBytes(inst.loc.end.pos - inst.loc.start.pos + 1);
3715             position = inst.loc.end.pos + 1;
3716          }
3717          else
3718          {
3719             bool multiLine = false;
3720
3721             // Change the name
3722             // Check if it's an unnamed instance
3723             if(inst.exp)
3724             {
3725                f.Seek(inst.nameLoc.start.pos - position, current);
3726                f.DeleteBytes(inst.nameLoc.end.pos - inst.nameLoc.start.pos);
3727                position = inst.nameLoc.end.pos;
3728                if(object.name)
3729                   f.Printf(object.name);
3730                else
3731                {
3732                   char ch = 0;
3733                   f.Getc(&ch);
3734                   if(isspace(ch) && ch != '\n')
3735                   {
3736                      f.Seek(-1, current);
3737                      f.DeleteBytes(1);
3738                      position ++;
3739                   }
3740                }
3741             }
3742             else
3743             {
3744                int pos = inst.loc.start.pos; // + strlen(inst._class.name);
3745                char ch;
3746                f.Seek(pos - position, current);
3747                while(f.Getc(&ch))
3748                {  
3749                   if(isspace(ch))
3750                   {
3751                      f.Seek(-1, current);
3752                      break;
3753                   }
3754                   pos++;
3755                }
3756
3757                if(object.name)
3758                {
3759                   f.Puts(" ");
3760                   f.Puts(object.name);
3761                }
3762                position = pos;
3763             }
3764
3765             if((this.methodAction == actionAddMethod || this.moveAttached) && this.selected == object)
3766                methodPresent = true;
3767
3768             for(;;)
3769             {
3770                char ch = 0;
3771                if(!f.Getc(&ch))
3772                   break;
3773                position++;
3774                if(ch == OpenBracket)
3775                   break;
3776                if(ch == '\n')
3777                   multiLine = true;
3778             }
3779
3780             // TODO: Simplify this?
3781             if(methodPresent)
3782             {
3783                if(!multiLine)
3784                {
3785                   int count = 0;
3786                   int toDelete = 0;
3787                   int toAdd = 0;
3788
3789                   f.Seek(-1, current);
3790                   f.Puts("\n   ");
3791                   f.Seek(1, current);
3792                   //f.Puts("\n");
3793
3794                   // Fix indentation
3795                   for(;;)
3796                   {
3797                      char ch = 0;
3798                      if(!f.Getc(&ch))
3799                         break;
3800                      position++;
3801                      if(ch == '\n') { toDelete = count; count = 0; }
3802                      else if(isspace(ch)) count++;
3803                      else
3804                      {
3805                         f.Seek(-1, current);
3806                         position--;
3807                         if(count > 6)
3808                         {
3809                            toDelete += count - 6; 
3810                            count = 6;
3811                         }
3812                         else 
3813                            toAdd = 6 - count;
3814                         break;                              
3815                      }
3816                   }
3817                   if(toDelete)
3818                   {
3819                      f.Seek(-toDelete-count, current);
3820                      f.DeleteBytes(toDelete);
3821                      f.Seek(count, current);
3822                   }
3823                   if(toAdd)
3824                   {
3825                      int c;
3826                      for(c = 0; c<toAdd; c++)
3827                         f.Putc(' ');
3828                   }
3829                }
3830             }
3831             else
3832                methodPresent = multiLine;
3833
3834             if(!prev)
3835                f.Printf(methodPresent ? "\n      " : " ");
3836
3837          }
3838       }
3839       else 
3840       {
3841          // Instance not there, create a brand new one
3842          DeleteJunkBefore(f, position, &position);
3843          f.Printf(*firstObject ? "\n\n" : "\n");
3844          *firstObject = false;
3845
3846          if((this.methodAction == actionAddMethod || this.moveAttached) && this.selected == object)
3847             methodPresent = true;
3848
3849          if(methodPresent)
3850          {
3851             if(object.name)
3852                f.Printf("   %s %s\n   %c\n      ", control._class.name, object.name, OpenBracket);
3853             else
3854                f.Printf("   %s\n   %c\n      ", control._class.name, OpenBracket);
3855          }
3856          else
3857          {
3858             if(object.name)
3859                f.Printf("   %s %s %c ", control._class.name, object.name, OpenBracket);
3860             else
3861                f.Printf("   %s %c ", control._class.name, OpenBracket);
3862          }
3863       }
3864
3865       if(!object.deleted)
3866       {
3867          Instance test = eInstance_New(control._class);
3868          DataMember curMember = null;
3869          Class curClass = null;
3870          incref test;
3871
3872          UpdateInstanceCodeClass(control._class, object, f, test, &prev, &lastIsMethod, &curMember, &curClass);
3873
3874          delete test;
3875
3876          // Attach Method here
3877          if((this.methodAction == actionAttachMethod || this.methodAction == actionReattachMethod) && !this.moveAttached && this.selected == object)
3878          {
3879             if(prev) f.Printf(", ");
3880             f.Printf("%s = %s", this.method.name, function.declarator.symbol.string);
3881             prev = true;
3882          }
3883       }
3884
3885       if(inst && !object.deleted)
3886       {
3887          MembersInit members;
3888          Class instClass = eSystem_FindClass(this.privateModule, inst._class.name);
3889
3890          DeleteJunkBefore(f, position, &position);
3891          
3892          // Instance already there, clear out the properties
3893          for(members = inst.members->first; members; members = members.next)
3894          {
3895             if(members.type == dataMembersInit)
3896             {
3897                MemberInit member;
3898
3899                if(members.dataMembers)
3900                {
3901                   bool keptMember = false;
3902                   MemberInit lastKept = null;
3903
3904                   for(member = members.dataMembers->first; member; member = member.next)
3905                   {
3906                      Identifier ident = member.identifiers ? member.identifiers->first : null;
3907                      bool deleted = false;
3908
3909                      // For now delete if it's not a method
3910                      if(!member.variable) // && ident)
3911                      {
3912                         if(!ident || !ident.next)
3913                         {
3914                            Property prop = ident ? eClass_FindProperty(instClass, ident.string, this.privateModule) : null;
3915                            if(!ident || prop)
3916                            {
3917                               f.Seek(member.loc.start.pos - position, current);
3918                               f.DeleteBytes(member.loc.end.pos - member.loc.start.pos);
3919                               position = member.loc.end.pos;
3920                               deleted = true;
3921                            }
3922                            else
3923                            {
3924                               Method method = eClass_FindMethod(instClass, ident.string, this.privateModule);
3925                               if(method && method.type == virtualMethod && member.initializer && member.initializer.type == expInitializer && member.initializer.exp && 
3926                                  member.initializer.exp.type == memberExp /*ExpIdentifier*/)
3927                               {
3928                                  if(((this.methodAction == actionDetachMethod || this.methodAction == actionReattachMethod) && this.method == method && this.selected == object) ||
3929                                     (this.methodAction == actionDeleteMethod && !strcmp(function.declarator.symbol.string, member.initializer.exp.identifier.string)))
3930                                  {
3931                                     f.Seek(member.loc.start.pos - position, current);
3932                                     f.DeleteBytes(member.loc.end.pos - member.loc.start.pos);
3933                                     position = member.loc.end.pos;
3934                                     deleted = true;
3935                                  }
3936                               }                                          
3937                            }
3938                         }
3939                      }
3940                      if(!deleted)
3941                      {
3942                         keptMember = true;
3943                         lastKept = member;
3944
3945                         //f.Seek(member.loc.start.pos - position, current);
3946                         //position = member.loc.start.pos;
3947                         DeleteJunkBefore(f, member.loc.start.pos, &position);
3948                         if(prev) f.Printf(", "); 
3949                         else if(keptMember) f.Printf(" ");
3950                         prev = false;
3951                      }
3952                   } 
3953                
3954                   if(!keptMember || !members.next)
3955                   {
3956                      char ch = 0;
3957                      int count = 0;
3958
3959                      if(keptMember && lastKept != members.dataMembers->last)
3960                      {
3961                         // Delete the comma
3962                         char ch;
3963                         int count = 0;
3964                         f.Seek(-1, current);
3965                         for(;f.Getc(&ch);)
3966                         {
3967                            if(ch == ',')
3968                            {
3969                               count++;
3970                               f.Seek(-1, current);
3971                               break;
3972                            }
3973                            else if(!isspace(ch))
3974                               break;
3975                            f.Seek(-2, current);
3976                            count++;
3977                         }
3978
3979                         if(ch == ',')
3980                            f.DeleteBytes(count);
3981                      }
3982
3983                      f.Seek(members.loc.end.pos - position, current);
3984                      f.Getc(&ch);
3985             
3986                      if(ch == ';')
3987                      {
3988                         f.Seek(-1, current);
3989                         f.DeleteBytes(1);
3990                         position = members.loc.end.pos + 1;
3991                      }
3992                      else
3993                      {
3994                         f.Seek(-1, current);
3995                         position = members.loc.end.pos;
3996                      }
3997
3998                      if(keptMember)
3999                      {
4000                         prev = true;
4001                         lastIsMethod = false;
4002                      }
4003                   }
4004                   else
4005                   {
4006                      DeleteJunkBefore(f, position, &position);
4007                      f.Printf(" ");
4008
4009                      if(lastKept != members.dataMembers->last)
4010                      {
4011                         // Delete the comma
4012                         char ch;
4013                         int count = 0;
4014                         f.Seek(-1, current);
4015                         for(;f.Getc(&ch);)
4016                         {
4017                            if(ch == ',')
4018                            {
4019                               count++;
4020                               f.Seek(-1, current);
4021                               break;
4022                            }
4023                            else if(!isspace(ch))
4024                               break;
4025                            f.Seek(-2, current);
4026                            count++;
4027                         }
4028
4029                         if(ch == ',')
4030                            f.DeleteBytes(count);
4031                      }
4032                      else
4033                      {
4034                         f.Seek(members.loc.end.pos - position, current);
4035                         position = members.loc.end.pos;
4036                      }
4037                      /*
4038                      prev = false;
4039                      lastIsMethod = true;
4040                      */
4041                      prev = true;
4042                      lastIsMethod = false;
4043                      
4044                   }
4045                }
4046                else
4047                {
4048                   f.Seek(members.loc.end.pos - position, current);
4049                   position = members.loc.end.pos;
4050                   prev = false;
4051                   lastIsMethod = true;
4052                }
4053             }
4054             else if(members.type == methodMembersInit)
4055             {
4056                if(this.methodAction == actionDeleteMethod && members.function == function);
4057                else
4058                   methodPresent = true;
4059
4060                // Delete instance method here
4061                if((this.methodAction == actionDeleteMethod || (this.methodAction == actionDetachMethod && this.moveAttached)) && 
4062                   members.function == function)
4063                {
4064                   if(this.moveAttached && !*text)
4065                      GetLocText(editBox, f, position, &function.loc, text, textSize, Max((int)strlen(this.methodName) - movedFuncIdLen,0), 0);
4066
4067                   DeleteJunkBefore(f, members.loc.start.pos, &position);
4068                   f.DeleteBytes(members.loc.end.pos - members.loc.start.pos + 1);
4069                   position = members.loc.end.pos + 1;
4070                   f.Printf("\n");
4071                }
4072                else
4073                {
4074                   DeleteJunkBefore(f, position, &position);
4075                   if(!lastIsMethod)
4076                      f.Printf(";");
4077
4078                   DeleteJunkBefore(f, members.loc.start.pos, &position);
4079                   lastIsMethod = true;
4080                   f.Printf("\n\n      ");               
4081                }
4082
4083                f.Seek(members.loc.end.pos - position, current);
4084                position = members.loc.end.pos;
4085             }
4086             DeleteJunkBefore(f, position, &position);
4087          }
4088       }
4089
4090       if(!object.deleted)
4091       {
4092          if(!methodPresent)
4093             f.Printf(" ");
4094
4095          if((this.methodAction == actionAddMethod || (this.moveAttached && (this.methodAction == actionAttachMethod || this.methodAction == actionReattachMethod))) && this.selected == object)
4096          {
4097             Method method = this.method;
4098             DeleteJunkBefore(f, position, &position);
4099             if(!lastIsMethod)
4100                f.Printf(";");
4101
4102             f.Printf("\n");
4103
4104             if(!method.dataType)
4105                method.dataType = ProcessTypeString(method.dataTypeString, false);
4106
4107             {
4108                Type dataType = method.dataType;
4109                Type returnType = dataType.returnType;
4110                Type param;
4111
4112                if(this.moveAttached)
4113                {
4114                   // Move function here:
4115                   int newLen = strlen(method.name);
4116
4117                   f.Printf("\n   ");
4118
4119                   if(!*text)
4120                      GetLocText(editBox, f, position, &function.loc, text, textSize, Max(newLen - movedFuncIdLen, 0), 3);
4121
4122                   // First change name of function
4123                   memmove(*text + movedFuncIdPos + newLen, *text + movedFuncIdPos + movedFuncIdLen, *textSize - movedFuncIdPos - movedFuncIdLen + 1);
4124                   *textSize += newLen - movedFuncIdLen;
4125                   memcpy(*text + movedFuncIdPos, method.name, newLen);
4126                                           
4127                   // Second, tab right
4128                   {
4129                      int c;
4130                      for(c = 0; (*text)[c]; )
4131                      {
4132                         int i;
4133                         for(i = c; (*text)[i] && (*text)[i] != '\n'; i++);
4134                         if(i != c)
4135                         {
4136                            memmove((*text)+c+3, (*text)+c, *textSize+1-c);
4137                            (*text)[c] = (*text)[c+1] = (*text)[c+2] = ' ';
4138                            c += 3;
4139                            *textSize += 3;
4140                         }
4141                         for(; (*text)[c] && (*text)[c] != '\n'; c++);
4142                         if((*text)[c]) c++;
4143                      }
4144                   }
4145
4146                   f.Puts((*text));
4147                   f.Printf("\n");
4148                }
4149                else
4150                {
4151                   Class moduleClass = eSystem_FindClass(this.privateModule, "Module");
4152
4153                   // ADDING METHOD HERE
4154                   f.Printf("\n      ");
4155                   OutputType(f, returnType, false);
4156             
4157                   f.Printf(" ");
4158                   if(dataType.thisClass)
4159                   {
4160                      if(!eClass_IsDerived(regClass, dataType.thisClass.registered) && !dataType.classObjectType)     // Just fixed this... was backwards.
4161                      {
4162                         if(dataType.thisClass.shortName)
4163                            f.Printf(dataType.thisClass.shortName);
4164                         else
4165                            f.Printf(dataType.thisClass.string);
4166                         f.Printf("::");
4167                      }
4168                   }
4169                   f.Printf(method.name);
4170                   f.Printf("(");
4171                   for(param = dataType.params.first; param; param = param.next)
4172                   {
4173                      OutputType(f, param, true);
4174                      if(param.next)
4175                         f.Printf(", ");
4176                   }
4177                   f.Printf(")\n");                  
4178                   f.Printf("      %c\n\n", OpenBracket);
4179
4180                   if(control._class._vTbl[method.vid] == moduleClass._vTbl[__ecereVMethodID___ecereNameSpace__ecere__com__Module_OnLoad]) // Temp Check for DefaultFunction
4181                   {
4182                      if(returnType.kind == classType && !strcmp(returnType._class.string, "bool"))
4183                         f.Printf("         return true;\n");
4184                      else if(returnType.kind != voidType)
4185                         f.Printf("         return 0;\n");
4186                   }
4187                   else
4188                   {
4189                      f.Printf("         ");
4190                      if(returnType.kind != voidType)
4191                         f.Printf("return ");
4192                      f.Printf("%s::%s(", control._class.name, method.name);
4193                      for(param = dataType.params.first; param; param = param.next)
4194                      {
4195                         if(param.prev) f.Printf(", ");
4196                         if(param.kind != voidType)
4197                            f.Printf(param.name);
4198                      }
4199                      f.Printf(");\n");
4200                   }
4201                   f.Printf("      %c\n", CloseBracket);
4202                }
4203             }
4204          }
4205       }
4206
4207       if(!object.instCode)
4208       {
4209          if(methodPresent)
4210             f.Printf("   %c;\n", CloseBracket);
4211          else
4212             f.Printf("%c;\n", CloseBracket);
4213       }
4214       else if(!object.deleted)
4215       {
4216          // Turn this into a multiline instance when adding a method
4217          DeleteJunkBefore(f, inst.loc.end.pos-1, &position);
4218
4219          f.Printf(methodPresent ? "\n   " : " ");
4220
4221          f.Seek(inst.loc.end.pos + 1 - position, current);
4222          position = inst.loc.end.pos + 1;
4223       }
4224       return position;
4225    }
4226
4227    void OutputClassProperties(Class _class, ObjectInfo classObject, EditBoxStream f, Instance test)
4228    {
4229       Property propIt;
4230       Class regClass = eSystem_FindClass(privateModule, classObject.name);
4231      
4232       if(_class.base && _class.base.type != systemClass) OutputClassProperties(_class.base, classObject, f, test);
4233       
4234       for(propIt = _class.membersAndProperties.first; propIt; propIt = propIt.next)
4235       {
4236          Property prop = eClass_FindProperty(selected.instance._class, propIt.name, privateModule);
4237          if(prop && prop.isProperty && !prop.conversion)
4238          {
4239             if(prop.Set && prop.Get && prop.dataTypeString && strcmp(prop.name, "name") && !Code_IsPropertyDisabled(classObject, prop.name) && 
4240                (!prop.IsSet || prop.IsSet(classObject.instance)))
4241             {
4242                Class dataType = prop.dataTypeClass;
4243                char tempString[1024] = "";
4244                char * string;
4245                bool specify = false;
4246                DataMember member;
4247
4248                member = eClass_FindDataMember(regClass, prop.name, privateModule, null, null);
4249                if(member && member._class == regClass)
4250                   specify = true;
4251
4252                if(!dataType)
4253                   dataType = prop.dataTypeClass = eSystem_FindClass(this.privateModule, prop.dataTypeString);
4254             
4255                if(dataType && dataType.type == structClass)
4256                {
4257                   void * dataForm = new0 byte[dataType.structSize];
4258                   void * dataTest = new0 byte[dataType.structSize];
4259                
4260                   ((void (*)(void *, void *))(void *)prop.Get)(classObject.instance, dataForm);
4261                   ((void (*)(void *, void *))(void *)prop.Get)(test, dataTest);
4262
4263                   if(((int (*)(void *, void *, void *))(void *)dataType._vTbl[__ecereVMethodID_class_OnCompare])(dataType, dataForm, dataTest))
4264                   {
4265                      bool needClass = true;
4266                      
4267                      string = ((char * (*)(void *, void *, void *, void *, void *))(void *)dataType._vTbl[__ecereVMethodID_class_OnGetString])(dataType, dataForm, tempString, null, &needClass);
4268                      ((void (*)(void *, void *))(void *)prop.Set)(test, dataForm);
4269                      if(needClass)
4270                         f.Printf("\n   %s%s = %c %s %c;", specify ? "property::" : "", prop.name, /*dataType.name, */OpenBracket, string, CloseBracket);
4271                      else
4272                         f.Printf("\n   %s%s = %s;", specify ? "property::" : "", prop.name, string);
4273                   }
4274                   delete dataForm;
4275                   delete dataTest;
4276                }
4277                else if(dataType && (dataType.type == normalClass || dataType.type == noHeadClass))
4278                {
4279                   void * dataForm, * dataTest;
4280                
4281                   dataForm = ((void *(*)(void *))(void *)prop.Get)(classObject.instance);
4282                   dataTest = ((void *(*)(void *))(void *)prop.Get)(test);
4283                
4284                   if(((int (*)(void *, void *, void *))(void *)dataType._vTbl[__ecereVMethodID_class_OnCompare])(dataType, dataForm, dataTest))
4285                   {
4286                      char tempString[1024] = "";
4287                      char * string;
4288                      ((void (*)(void *, void *))(void *)prop.Set)(test, dataForm);
4289                   
4290                      if(eClass_IsDerived(classObject.instance._class, dataType) && classObject.instance == dataForm)
4291                      {
4292                         // Shouldn't go here ...
4293                         f.Printf("\n   %s%s = this;", specify ? "property::" : "", prop.name);
4294                      }
4295                      else
4296                      {
4297                         bool needClass = true;
4298
4299                         string = ((char * (*)(void *, void *, void *, void *, void *))(void *)dataType._vTbl[__ecereVMethodID_class_OnGetString])(dataType, dataForm, tempString, null, &needClass);
4300
4301                         if(!strcmp(dataType.dataTypeString, "char *"))
4302                         {
4303                            f.Printf("\n   %s%s = \"", specify ? "property::" : "", prop.name);
4304                            OutputString(f, string);
4305                            f.Puts("\";");
4306                         }
4307                         else if(needClass)
4308                            f.Printf("\n   %s%s = %c %s %c;", specify ? "property::" : "", prop.name, /*dataType.name, */OpenBracket, string, CloseBracket);
4309                         else
4310                            f.Printf("\n   %s%s = %s;", specify ? "property::" : "", prop.name, string);
4311                      }
4312                   }
4313                }
4314                else if(dataType)
4315                {
4316                   DataValue dataForm, dataTest;
4317                
4318                   GetProperty(prop, classObject.instance, &dataForm);
4319                   GetProperty(prop, test, &dataTest);
4320                
4321                   if(((int (*)(void *, void *, void *))(void *)dataType._vTbl[__ecereVMethodID_class_OnCompare])(dataType, &dataForm, &dataTest))
4322                   {
4323                      SetProperty(prop, test, dataForm);
4324                      if(dataType.type == bitClass)
4325                      {
4326                         bool needClass = true;
4327                         string = ((char * (*)(void *, void *, void *, void *, void *))(void *)dataType._vTbl[__ecereVMethodID_class_OnGetString])(dataType, &dataForm, tempString, null, &needClass);
4328                         if(needClass)
4329                            f.Printf("\n   %s%s = %c %s %c;", specify ? "property::" : "", prop.name, /*dataType.name, */OpenBracket, string, CloseBracket);
4330                         else if(string[0])
4331                            f.Printf("\n   %s%s = %s;", specify ? "property::" : "", prop.name, string);
4332                      }
4333                      else
4334                      {
4335                         bool needClass = true;
4336                         if(dataType.type == enumClass)
4337                         {
4338                            NamedLink value;
4339                            Class enumClass = eSystem_FindClass(privateModule, "enum");
4340                            EnumClassData e = ACCESS_CLASSDATA(dataType, enumClass);
4341
4342                            for(value = e.values.first; value; value = value.next)
4343                            {
4344                               if((int)value.data == dataForm.i)
4345                               {
4346                                  string = value.name;
4347                                  break;
4348                               }
4349                            }
4350                         }
4351                         else
4352                            string = ((char * (*)(void *, void *, void *, void *, void *))(void *)dataType._vTbl[__ecereVMethodID_class_OnGetString])(dataType, &dataForm, tempString, null, &needClass);
4353                         if(!strcmp(dataType.dataTypeString, "float") && strchr(string, '.'))
4354                            f.Printf("\n   %s%s = %sf;", specify ? "property::" : "", prop.name, string);
4355                         else if(string[0])
4356                            f.Printf("\n   %s%s = %s;", specify ? "property::" : "", prop.name, string);
4357                      }
4358                   }                                          
4359                }
4360             }
4361          }
4362       }
4363    }
4364
4365    void UpdateFormCode()
4366    {
4367       if(!this) return;
4368          
4369       updatingCode++;
4370       if(codeModified)
4371       {
4372          ParseCode();
4373       }
4374       else if(formModified)
4375       {
4376          EditBoxStream f { editBox = editBox };
4377          int position = 0;
4378          char * text = null;
4379          int textSize;
4380          Identifier movedFuncId; 
4381          int movedFuncIdLen = 0, movedFuncIdPos = 0;
4382          ObjectInfo classObject;
4383
4384            updatingCode++;
4385
4386          if(moveAttached)
4387          {
4388             movedFuncId = GetDeclId(function.declarator);
4389             movedFuncIdLen = movedFuncId.loc.end.pos - movedFuncId.loc.start.pos;
4390             movedFuncIdPos = movedFuncId.loc.start.pos - function.loc.start.pos;
4391          }
4392
4393          for(classObject = classes.first; classObject; classObject = classObject.next)
4394          {
4395             Class _class;
4396             ClassDefinition classDef = classObject.classDefinition;
4397             Class regClass = eSystem_FindClass(this.privateModule, ((Specifier)classDef.baseSpecs->first).name);
4398             Instance test;
4399             ClassDef def;
4400             bool firstObject = true;
4401             ObjectInfo object = classObject.instances.first;
4402             bool lastIsDecl = false;
4403
4404             if(!classObject.modified) continue;
4405
4406             test = eInstance_New(regClass);
4407             incref test;
4408
4409             // Put it in the same desktop window...
4410             designer.PrepareTestObject(test);
4411             
4412             //f.Printf("class %s : %s\n", classObject.name, classObject.oClass.name);
4413             //f.Printf("%c\n\n", OpenBracket);
4414
4415             // Change the _class name
4416             f.Seek(classDef.nameLoc.start.pos - position, current);
4417             f.DeleteBytes(classDef.nameLoc.end.pos - classDef.nameLoc.start.pos);
4418             f.Printf(classObject.name);
4419             position = classDef.nameLoc.end.pos;
4420
4421             {
4422                // Go to block start, delete all until no white space, put \n
4423                char ch;
4424                int count = 0;
4425                int back = 0;
4426                f.Seek(classDef.blockStart.end.pos - position, current);
4427                position = classDef.blockStart.end.pos;
4428                
4429                for(; f.Getc(&ch); count++)
4430                {
4431                   if(!isspace(ch))
4432                   {
4433                      f.Seek(-1, current);
4434                      break;
4435                   }
4436                
4437                   if(ch == '\n')
4438                      back = 0;
4439                   else
4440                      back++;
4441                }
4442             
4443                f.Seek(-count, current);
4444             
4445                f.DeleteBytes(count-back);
4446                //f.Printf("\n");
4447                position += count-back;
4448             }
4449
4450             // Output properties
4451             OutputClassProperties(classObject.instance._class, classObject, f, test);
4452
4453             for(def = classDef.definitions->first; def; def = def.next)
4454             {
4455                switch(def.type)
4456                {
4457                   case defaultPropertiesClassDef:
4458                   {
4459                      bool keptMember = false;
4460                      MemberInit propDef;
4461                      MemberInit lastKept = null;
4462                      
4463                      lastIsDecl = false;
4464                      DeleteJunkBefore(f, def.loc.start.pos, &position);
4465                      f.Printf("\n   ");
4466
4467                      for(propDef = def.defProperties->first; propDef; propDef = propDef.next)
4468                      {
4469                         Identifier ident = propDef.identifiers->first;
4470                         bool deleted = false;
4471
4472                         // For now delete if it's a prop
4473                         if(!propDef.variable && ident)
4474                         {
4475                            if(!ident.next)
4476                            {
4477                               Property prop = eClass_FindProperty(regClass, ident.string, this.privateModule);
4478                               if(prop)
4479                               {
4480                                  f.Seek(propDef.loc.start.pos - position, current);
4481                                  f.DeleteBytes(propDef.loc.end.pos - propDef.loc.start.pos);
4482                                  position = propDef.loc.end.pos;
4483                                  deleted = true;
4484                               }
4485                               else
4486                               {
4487                                  Method method = eClass_FindMethod(regClass, ident.string, this.privateModule);
4488                                  if(method && method.type == virtualMethod && propDef.initializer && propDef.initializer.type == expInitializer && propDef.initializer.exp && propDef.initializer.exp.type == identifierExp)
4489                                  {
4490                                     if(((methodAction == actionDetachMethod || methodAction == actionReattachMethod) && method == this.method && selected == classObject) ||
4491                                        (methodAction == actionDeleteMethod && !strcmp(function.declarator.symbol.string, propDef.initializer.exp.identifier.string)))
4492                                     {
4493                                        f.Seek(propDef.loc.start.pos - position, current);
4494                                        f.DeleteBytes(propDef.loc.end.pos - propDef.loc.start.pos);
4495                                        position = propDef.loc.end.pos;
4496                                        deleted = true;
4497                                     }
4498                                  }                                          
4499                               }
4500                            }
4501                         }
4502                         if(!deleted)
4503                         {
4504                            keptMember = true;
4505                            lastKept = propDef;
4506                         }
4507                      }
4508                   
4509                      if(!keptMember)
4510                      {
4511                         char ch = 0;
4512                         int count = 0;
4513                         f.Seek(def.loc.end.pos - position - 1, current);
4514                         f.Getc(&ch);
4515                         
4516                         if(ch == ';')
4517                         {
4518                            f.Seek(-1, current);
4519                            f.DeleteBytes(1);
4520                         }
4521                         position = def.loc.end.pos;
4522                      }
4523                      else
4524                      {
4525                         if(lastKept != def.defProperties->last)
4526                         {
4527                            char ch;
4528                            int count = 0;
4529                            
4530                            f.Seek(-1, current);
4531                            for(;f.Getc(&ch);)
4532                            {
4533                               if(ch == ',')
4534                               {
4535                                  count++;
4536                                  f.Seek(-1, current);
4537                                  break;
4538                               }
4539                               else if(!isspace(ch))
4540                                  break;
4541                               f.Seek(-2, current);
4542                               count++;
4543                            }
4544
4545                            if(ch == ',')
4546                               f.DeleteBytes(count);
4547                         }
4548                         else
4549                         {
4550                            f.Seek(def.loc.end.pos - position, current);
4551                            position = def.loc.end.pos;
4552                         }                
4553                      }
4554                      break;
4555                   }
4556                   case declarationClassDef:
4557                   {
4558                      Declaration decl = def.decl;
4559
4560                      if(decl.type == instDeclaration)
4561                      {
4562                         if(def.object/* && ((ObjectInfo)def.object).modified*/)
4563                         {
4564                            while(def.object && object != def.object)
4565                            {
4566                               if(object /*&& ((ObjectInfo)def.object).modified*/)
4567                                  position = UpdateInstanceCode(f, position, regClass, object, &firstObject, &text, &textSize, movedFuncIdLen, movedFuncIdPos);
4568                               object = object.next;
4569                            }
4570
4571                            DeleteJunkBefore(f, def.loc.start.pos, &position);
4572                            f.Printf(firstObject ? "\n\n   " : "\n   ");
4573                            firstObject = false;
4574
4575                            if(def.object && ((ObjectInfo)def.object).modified)
4576                               position = UpdateInstanceCode(f, position, regClass, def.object, &firstObject, &text, &textSize, movedFuncIdLen, movedFuncIdPos);
4577
4578                            object = object ? object.next : null;
4579                         }
4580                         else
4581                         {
4582                            DeleteJunkBefore(f, def.loc.start.pos, &position);
4583                            f.Printf(firstObject ? "\n\n   " : "\n   ");
4584                            firstObject = false;
4585                         }
4586                         lastIsDecl = false;
4587                      }
4588                      else
4589                      {
4590                         DeleteJunkBefore(f, def.loc.start.pos, &position);
4591                         f.Printf(lastIsDecl ? "\n   " : "\n\n   ");
4592                         lastIsDecl = true;
4593                      }
4594                      break;
4595                   }
4596                   case functionClassDef:
4597                   {
4598                      // TESTING IF THIS IS GOOD ENOUGH FOR GENERATED FUNCTION...
4599                      if(!def.function.body) continue;
4600
4601                      lastIsDecl = false;
4602
4603                      DeleteJunkBefore(f, def.loc.start.pos, &position);
4604                      f.Printf("\n\n   ");
4605
4606                      // Delete _class methods
4607                      if((methodAction == actionDeleteMethod || (moveAttached && selected != classObject)) && 
4608                         def.function == function)
4609                      {
4610                         char ch;
4611                         int count = 0;
4612
4613                         if(moveAttached && !text)
4614                         {
4615                            GetLocText(editBox, f, position, &function.loc, &text, &textSize, Max((int)strlen(methodName) - movedFuncIdLen,0), 3);
4616                         }
4617
4618                         f.Seek(def.loc.end.pos - position, current);
4619                         for(; f.Getc(&ch); count++)
4620                         {
4621                            if(!isspace(ch))
4622                            {
4623                               f.Seek(-1, current);
4624                               break;
4625                            }
4626                         }
4627                         f.Seek(def.loc.start.pos - def.loc.end.pos - count, current);
4628
4629                         f.DeleteBytes(def.loc.end.pos - def.loc.start.pos + count);
4630                         position = def.loc.end.pos + count;
4631                      }
4632
4633                      // In case of detaching methods in the _class, simply rename the method
4634                      if(methodAction == actionDetachMethod && moveAttached && selected == classObject && function == def.function)
4635                      {
4636                         f.Seek(function.loc.start.pos + movedFuncIdPos - position, current);
4637                         f.DeleteBytes(movedFuncIdLen);
4638                         f.Puts(methodName);
4639                         position = function.loc.start.pos + movedFuncIdPos + movedFuncIdLen;
4640                      }
4641
4642                      if((methodAction == actionAttachMethod || methodAction == actionReattachMethod) && selected == classObject && moveAttached && 
4643                         function == def.function)
4644                      {
4645                         // In case of attaching methods in the _class, simply rename the method
4646                         f.Seek(function.loc.start.pos + movedFuncIdPos - position, current);
4647                         position = function.loc.start.pos + movedFuncIdPos;
4648                         f.DeleteBytes(movedFuncIdLen);
4649                         if(method.dataType.thisClass)
4650                            f.Printf("%s::", method.dataType.thisClass.string);
4651                         f.Puts(method.name);
4652                         position += movedFuncIdLen;
4653                      }
4654                      break;
4655                   }
4656                   default:
4657                      DeleteJunkBefore(f, def.loc.start.pos, &position);
4658                      if(def.type == memberAccessClassDef)
4659                      {
4660                         f.Printf("\n\n");
4661                         firstObject = false;
4662                         lastIsDecl = true;
4663                      }
4664                      else           
4665                      {
4666                         f.Printf("\n   ");
4667                         lastIsDecl = false;
4668                      }
4669                }
4670
4671                f.Seek(def.loc.end.pos - position, current);
4672                position = def.loc.end.pos;
4673             }
4674
4675             // Output attached methods
4676             if((methodAction == actionAttachMethod || methodAction == actionReattachMethod) && selected == classObject && !moveAttached)
4677             {
4678                DeleteJunkBefore(f, position, &position);
4679                f.Printf("\n   %s = %s;\n", method.name, function.declarator.symbol.string);
4680             }
4681             
4682             // ********** INSTANCES ***************
4683             for(; object; object = object.next)
4684             {
4685                if(!object.instCode)
4686                {
4687                   position = UpdateInstanceCode(f, position, regClass, object, &firstObject, &text, &textSize, movedFuncIdLen, movedFuncIdPos);
4688                }
4689             }
4690
4691             DeleteJunkBefore(f, position, &position);
4692
4693             // ****************** METHODS ***********************
4694             if(methodAction == actionDetachMethod && moveAttached && classObject == oClass)
4695             {
4696                // If detaching an instance method
4697                if(selected != classObject)
4698                {
4699                   int newLen = strlen(methodName);
4700
4701                   if(!text)
4702                      GetLocText(editBox, f, position, &function.loc, &text, &textSize, Max(newLen - movedFuncIdLen,0), 0);
4703                   // Tab selection left
4704                   {
4705                      int c;
4706                      for(c = 0; text[c]; )
4707                      {
4708                         int start = c, i;
4709                         for(i = 0; i<3 && text[c] == ' '; i++, c++);
4710                         memmove(text+start, text+start+i, textSize+1-start-i);
4711                         textSize -= i;
4712                         c -= i;
4713                         for(; text[c] && text[c] != '\n'; c++);
4714                         if(text[c]) c++;
4715                      }
4716                   }
4717
4718                   // Rename function
4719                   memmove(text + movedFuncIdPos + newLen, text + movedFuncIdPos + movedFuncIdLen, textSize - movedFuncIdPos - movedFuncIdLen + 1);
4720                   textSize += newLen - movedFuncIdLen;
4721                   memcpy(text + movedFuncIdPos, methodName, newLen);
4722
4723                   f.Printf("\n\n   ");
4724                   f.Puts(text);
4725                }
4726             }
4727
4728             if(methodAction == actionAddMethod && selected == classObject)
4729             {
4730                Method method = this.method;
4731
4732                if(!method.dataType)
4733                   method.dataType = ProcessTypeString(method.dataTypeString, false);
4734
4735                // ADDING METHOD HERE
4736                {
4737                   Type dataType = method.dataType;
4738                   Type returnType = dataType.returnType;
4739                   Type param;
4740                   Class moduleClass = eSystem_FindClass(this.privateModule, "Module");
4741
4742                   f.Printf("\n\n");
4743                   f.Printf("   ");
4744                   OutputType(f, returnType, false);
4745                
4746                   f.Printf(" ");
4747                   if(dataType.thisClass && !dataType.classObjectType)
4748                   {
4749                      if(dataType.thisClass.shortName)
4750                         f.Printf(dataType.thisClass.shortName);
4751                      else
4752                         f.Printf(dataType.thisClass.string);
4753                      f.Printf("::");
4754                   }
4755                   f.Printf(method.name);
4756                   f.Printf("(");
4757                   for(param = dataType.params.first; param; param = param.next)
4758                   {
4759                      OutputType(f, param, true);
4760                      if(param.next)
4761                         f.Printf(", ");
4762                   }
4763                   f.Printf(")\n");                  
4764                   f.Printf("   %c\n\n", OpenBracket);
4765
4766                   if(test._class._vTbl[method.vid] == moduleClass._vTbl[__ecereVMethodID___ecereNameSpace__ecere__com__Module_OnLoad]) // Temp Check for DefaultFunction
4767                   {
4768                      if(returnType && returnType.kind == classType && !strcmp(returnType._class.string, "bool"))
4769                         f.Printf("      return true;\n");
4770                      else if(returnType && returnType.kind != voidType)
4771                         f.Printf("      return 0;\n");
4772                   }
4773                   else
4774                   {
4775                      f.Printf("      ");
4776                      if(returnType.kind != voidType)
4777                         f.Printf("return ");
4778                      {
4779                         char * name = ((Specifier)classDef.baseSpecs->first).name;
4780                         Symbol _class = FindClass(name);
4781                         f.Printf("%s::%s(", (_class && _class.registered) ? _class.registered.name : name, method.name);
4782                      }
4783                      for(param = dataType.params.first; param; param = param.next)
4784                      {
4785                         if(param.prev) f.Printf(", ");
4786                         if(param.kind != voidType)
4787                            f.Printf(param.name);
4788                      }
4789                      f.Printf(");\n");
4790                   }
4791
4792                   f.Printf("   %c", CloseBracket);
4793                }
4794             }
4795
4796             DeleteJunkBefore(f, classDef.loc.end.pos-1, &position);
4797             f.Printf("\n");
4798
4799             delete test;
4800          }
4801
4802          updatingCode--;
4803          delete f;
4804
4805          ParseCode();
4806          delete text;
4807
4808          // TOFIX: Patch for a glitch where clicking at the end of the view seems one line off. No idea what could be going on?
4809          editBox.OnVScroll(setRange, editBox.scroll.y, 0);
4810       }
4811
4812       updatingCode--;
4813       codeModified = false;
4814       formModified = false;
4815       methodAction = 0;
4816       moveAttached = false;
4817       function = null;
4818       method = null;
4819    }
4820
4821    int FindMethod(char * methodName /*Method method*/, ClassFunction*functionPtr, Location propLoc)
4822    {
4823       int found = 0;
4824       ClassFunction function = null;
4825       if(methodName)
4826       {
4827          ObjectInfo object = this.selected;
4828          
4829          if(object && object == this.oClass)
4830          {
4831             ClassDefinition classDef = object.oClass.classDefinition;
4832             ClassDef def;
4833             if(classDef && classDef.definitions)
4834             {
4835                for(def = classDef.definitions->first; def; def = def.next)
4836                {
4837                   if(def.type == functionClassDef && def.function.declarator)
4838                   {
4839                      if(!strcmp(def.function.declarator.symbol.string, methodName))
4840                      {
4841                         function = def.function;
4842                         found = 1;
4843                         break;
4844                      }
4845                   }
4846                   else if(def.type == defaultPropertiesClassDef)
4847                   {
4848                      MemberInit propDef;
4849
4850                      for(propDef = def.defProperties->first; propDef; propDef = propDef.next)
4851                      {
4852                         Identifier ident = propDef.identifiers ? propDef.identifiers->first : null;
4853                         if(ident && !ident.next)
4854                         {
4855                            if(!strcmp(ident.string, methodName) && propDef.initializer && propDef.initializer.type == expInitializer && propDef.initializer.exp && propDef.initializer.exp.type == identifierExp)
4856                            {
4857                               found = 2;
4858                               if(propLoc != null)
4859                                  propLoc = propDef.loc;
4860                               if(functionPtr)
4861                               {
4862                                  ClassDefinition classDef = object.oClass.classDefinition;
4863                                  ClassDef def;
4864                                  if(classDef.definitions)
4865                                  {
4866                                     for(def = classDef.definitions->first; def; def = def.next)
4867                                     {
4868                                        if(def.type == functionClassDef)
4869                                        {
4870                                           if(!strcmp(def.function.declarator.symbol.string, propDef.initializer.exp.identifier.string))
4871                                           {
4872                                              function = def.function;
4873                                              break;
4874                                           }
4875                                        }
4876                                     }
4877                                     if(function) break;
4878                                  }
4879                               }
4880                               else
4881                                  break;
4882                            }
4883                         }
4884                      }
4885                   }
4886                }
4887             }
4888          }
4889          else if(object)
4890          {
4891             Instantiation inst = object.instCode;
4892
4893             // Check here to see if the method already exists, no need to call ModifyCode in that case
4894             if(inst && inst.members)
4895             {
4896                MembersInit members;
4897                for(members = inst.members->first; members; members = members.next)
4898                {
4899                   switch(members.type)
4900                   {
4901                      case dataMembersInit:
4902                      {
4903                         if(members.dataMembers)
4904                         {
4905                            MemberInit member;
4906                            for(member = members.dataMembers->first; member; member = member.next)
4907                            {
4908                               Identifier ident = member.identifiers ? member.identifiers->first : null;
4909                               if(ident && !ident.next)
4910                               {
4911                                  if(!strcmp(ident.string, methodName) && member.initializer && member.initializer.type == expInitializer && member.initializer.exp && member.initializer.exp.type == memberExp /*ExpIdentifier*/)
4912                                  {
4913                                     found = 2;
4914                                     if(propLoc != null)
4915                                        propLoc = member.loc;
4916                                     if(functionPtr)
4917                                     {
4918                                        ClassDefinition classDef = object.oClass.classDefinition;
4919                                        ClassDef def;
4920                                        if(classDef.definitions)
4921                                        {
4922                                           for(def = classDef.definitions->first; def; def = def.next)
4923                                           {
4924                                              if(def.type == functionClassDef)
4925                                              {
4926                                                 if(def.function.declarator && !strcmp(def.function.declarator.symbol.string, member.initializer.exp.identifier.string))
4927                                                 {
4928                                                    function = def.function;
4929                                                    break;
4930                                                 }
4931                                              }
4932                                           }
4933                                           if(function) break;
4934                                        }
4935                                        if(!function)
4936                                        {
4937                                           // TODO: Fix memory leak
4938                                           function = ClassFunction
4939                                           {
4940                                              declarator = Declarator { symbol = Symbol { string = CopyString(member.initializer.exp.member.member ? member.initializer.exp.member.member.string : "") } }
4941                                           };
4942                                        }
4943                                     }
4944                                     else
4945                                        break;
4946                                  }
4947                               }
4948                            }
4949                         }
4950                         break;
4951                      }
4952                      case methodMembersInit:
4953                      {
4954                         if(members.function.declarator && !strcmp(members.function.declarator.symbol.string, methodName))
4955                         {
4956                            function = members.function;
4957                            found = 1;
4958                         }
4959                         break;
4960                      }
4961                   }
4962                   if(function)
4963                      break;
4964                }
4965             }
4966          }
4967       }
4968       if(functionPtr) *functionPtr = function;
4969       return found;
4970    }
4971
4972    void GoToMethod(char * methodName /*Method method*/)
4973    {
4974       if(methodName)
4975       {
4976          ObjectInfo object = selected;
4977          EditBoxStream f { editBox = editBox };
4978          ClassFunction function = null;
4979          bool atChar = false;
4980          int indent = 6;
4981          EditLine l1, l2;
4982          int y1,y2, x1, x2;
4983          Location propLoc = { {0,0,-1} };
4984
4985          // GO TO THE METHOD
4986          if(FindMethod(methodName, &function, &propLoc) == 1 && object != this.oClass) indent = 9;
4987          if(function && function.body)
4988          {
4989             bool lfCount = 0;
4990             f.Seek(function.body.loc.start.pos+1, current);
4991             for(;;)
4992             {
4993                char ch;
4994                if(!f.Getc(&ch))
4995                   break;
4996                if(ch == '\n')
4997                {
4998                   if(lfCount)
4999                   {
5000                      f.Seek(-1, current);
5001                      break;
5002                   }
5003                   lfCount++;
5004                }
5005                else if(!isspace(ch))
5006                {
5007                   f.Seek(-1, current);
5008                   atChar = true;
5009                   break;
5010                }
5011             }
5012          }
5013          else if(propLoc.start.pos > -1)
5014          {
5015             f.Seek(propLoc.start.pos, current);
5016             atChar = true;
5017          }
5018          editBox.GetSelPos(&l1, &y1, &x1, &l2, &y2, &x2, false);
5019          delete f;
5020          if(function || propLoc.start.pos > -1)
5021          {
5022             editBox.SetSelPos(l1, y1, atChar ? x1 : indent, l2, y2, atChar ? x2 : indent);
5023             editBox.CenterOnCursor();
5024             SetState(normal, false, 0);
5025             Activate();
5026
5027             if(function && function.declarator && function.declarator.symbol && !function.declarator.symbol.type)
5028             {
5029                FreeClassFunction(function);
5030             }
5031          }
5032       }
5033    }
5034
5035    void FindCompatibleMethods(Method method, OldList compatible)
5036    {
5037       ClassDefinition classDef = this.oClass.classDefinition;
5038       if(classDef && classDef.definitions)
5039       {
5040          Class regClass { };
5041          Class baseClass = eSystem_FindClass(this.privateModule, ((Specifier)classDef.baseSpecs->first).name);
5042          ClassDef def;
5043          Class _class;
5044          Symbol classSym { };
5045          Symbol selectedClass;
5046          if(this.selected == this.oClass)
5047             selectedClass = classSym;
5048          else
5049             selectedClass = FindClass(this.selected.instance._class.name);
5050
5051          regClass.name = classDef._class.name;
5052          regClass.base = eSystem_FindClass(this.privateModule, ((Specifier)classDef.baseSpecs->first).name);
5053          for(def = classDef.definitions->first; def; def = def.next)
5054          {
5055             if(def.type == functionClassDef && def.function.declarator)
5056             {
5057                Method vMethod = eClass_FindMethod(baseClass, def.function.declarator.symbol.string, this.privateModule);
5058                if(!vMethod)
5059                   vMethod = eClass_FindMethod(this.selected.instance._class, def.function.declarator.symbol.string, this.privateModule);
5060                if(!vMethod)
5061                {
5062                   Type type = def.function.declarator.symbol.type;
5063                   if(CheckCompatibleMethod(method, type, regClass, this.selected == this.oClass, FindClass(this.selected.instance._class.name)))
5064                   {
5065                      compatible.Add(OldLink { data = def.function });
5066                   }
5067                }
5068             }
5069          }
5070
5071          if(this.oClass && this.oClass.instance)
5072          {
5073             classSym.registered = regClass;
5074             //classSym.registered = this.oClass.oClass;
5075
5076             for(_class = regClass.base; _class; _class = _class.base)
5077             {
5078                Method testMethod;
5079                for(testMethod = (Method)_class.methods.first; testMethod; testMethod = (Method)((BTNode)testMethod).next)
5080                {
5081                   // TODO: Understand why these functions popup in attach list
5082                   if(testMethod.type != virtualMethod /*&& testMethod.function != Window_OnGetString && testMethod.function != Window_OnGetDataFromString*/)
5083                   {
5084                      if(!testMethod.dataType)
5085                         testMethod.dataType = ProcessTypeString(testMethod.dataTypeString, false);
5086                         
5087                      //if(CheckCompatibleMethod(method, testMethod.dataType, &regClass, false, selectedClass)) // this.selected == this.oClass, selectedClass))
5088                      if(CheckCompatibleMethod(method, testMethod.dataType, this.oClass.instance._class, false, selectedClass)) // this.selected == this.oClass, selectedClass))
5089                      //if(CheckCompatibleMethod(method, testMethod.dataType, &regClass, this.selected == this.oClass, FindClass(this.oClass.oClass.name)))
5090                      {
5091                         // TODO: Fix memory leak, Figure out if it should be ClassFunction or FunctionDefinition
5092                         // ClassFunction function { };
5093                         FunctionDefinition function { };
5094
5095                         function.declarator = Declarator { };
5096                         function.declarator.symbol = Symbol { string = CopyString(testMethod.name) };
5097                         excludedSymbols.Add(function.declarator.symbol);
5098
5099                         compatible.Add(OldLink { data = function });
5100                      }
5101                   }
5102                }
5103             }
5104          }
5105          delete regClass;
5106          delete classSym;
5107       }
5108    }
5109
5110    void AddMethod(Method method)
5111    {
5112       if(method)
5113       {
5114          char methodName[1024];
5115          strcpy(methodName, method.name);
5116          if(!FindMethod(methodName, null, null))
5117          {
5118             methodAction = actionAddMethod;
5119             this.method = method;
5120             ModifyCode();
5121          }
5122          UpdateFormCode();         
5123          GoToMethod(methodName);
5124       }
5125    }
5126
5127    void DeleteMethod(ClassFunction function)
5128    {
5129       if(function)
5130       {
5131          methodAction = actionDeleteMethod;
5132          this.function = function;
5133          ModifyCode();
5134          UpdateFormCode(); 
5135
5136          Update(null);
5137       }
5138    }
5139
5140    void AttachMethod(Method method, ClassFunction function)
5141    {
5142       if(function)
5143       {
5144          // If it's an instance we'll ask if we want to move it inside...
5145          if(!function.attached.count && function.body)
5146          {
5147             // Find the function in the _class to check if it's a virtual function
5148             Class regClass = eSystem_FindClass(this.privateModule, ((Specifier)this.oClass.classDefinition.baseSpecs->first).name);
5149             Method method = eClass_FindMethod(regClass, function.declarator.symbol.string, this.privateModule);
5150             /*    LATER we'll need to check for public/virtual properties etc, for now only checked if virtual in base _class
5151             ClassDef def;
5152             for(def = this.classDefinition.first; def; def = def.next)
5153             {
5154                if(def.type == functionClassDef)
5155                {
5156                   if(def.function == function)
5157                      break;
5158                }
5159             }
5160             */
5161             if(!method || method.type != virtualMethod)
5162             {
5163                char title[1024];
5164                sprintf(title, $"Attach %s", function.declarator.symbol.string);
5165                if(MessageBox { type = yesNo, master = parent, text = title, contents = $"Method is unused. Move method inside instance?"}.Modal() == yes)
5166                {
5167                   moveAttached = true;
5168                }
5169             }
5170          }
5171
5172          methodAction = actionAttachMethod;
5173          this.method = method;
5174          this.function = function;
5175          ModifyCode();
5176          UpdateFormCode(); 
5177          Update(null);
5178       }
5179    }
5180
5181    void ReAttachMethod(Method method, ClassFunction function)
5182    {
5183       if(function)
5184       {
5185          // If it's an instance we'll ask if we want to move it inside...
5186          if(!function.attached.count && function.body)
5187          {
5188             // Find the function in the _class to check if it's a virtual function
5189             Class regClass = eSystem_FindClass(this.privateModule, ((Specifier)this.oClass.classDefinition.baseSpecs->first).name);
5190             Method method = eClass_FindMethod(regClass, function.declarator.symbol.string, this.privateModule);
5191             /*    LATER we'll need to check for public/virtual properties etc, for now only checked if virtual in base _class
5192             ClassDef def;
5193             for(def = this.classDefinition.first; def; def = def.next)
5194             {
5195                if(def.type == functionClassDef)
5196                {
5197                   if(def.function == function)
5198                      break;
5199                }
5200             }
5201             */
5202             if(!method || method.type != virtualMethod)
5203             {
5204                char title[1024];
5205                sprintf(title, $"Attach %s", function.declarator.symbol.string);
5206                if(MessageBox { type = yesNo, master = parent, text = title, 
5207                   contents = $"Method is unused. Move method inside instance?" }.Modal() == yes)
5208                {
5209                   moveAttached = true;
5210                }
5211             }
5212          }
5213
5214          methodAction = actionReattachMethod;
5215          this.method = method;
5216          this.function = function;
5217          ModifyCode();
5218          UpdateFormCode(); 
5219          Update(null);
5220       }
5221    }
5222
5223    void DetachMethod(Method method, ClassFunction function, int type)
5224    {
5225       bool result = true;
5226
5227       if(type == 1)
5228       {
5229          Window dialog
5230          {
5231             hasClose = true, borderStyle = sizable, minClientSize = { 300, 55 }, 
5232             master = sheet, text = $"Name detached method", background = formColor
5233          };
5234          Button cancelButton
5235          {
5236             dialog, anchor = { horz = 45, top = 30 }, size = { 80 }, text = $"Cancel", hotKey = escape,
5237             id = DialogResult::cancel, NotifyClicked = ButtonCloseDialog
5238          };
5239          Button okButton
5240          {
5241             dialog, anchor = { horz = -45, top = 30 }, size = { 80 }, text = $"OK", isDefault = true,
5242             id = DialogResult::ok, NotifyClicked = ButtonCloseDialog
5243          };
5244          EditBox nameBox
5245          {
5246             dialog, anchor = { left = 5, right = 5, top = 5 }
5247          };
5248          sprintf(methodName, "%s_%s", selected.name, method.name);
5249          nameBox.contents = methodName;
5250          incref nameBox;
5251          result = dialog.Modal() == ok;
5252          strcpy(methodName, nameBox.contents);
5253          delete nameBox;
5254       }
5255       if(result)
5256       {
5257          // If the method is not attached, move it outside
5258          if(type == 1)
5259          {
5260             // Add this class to the methodName
5261             char name[1024] = "";
5262
5263             if(this.selected != this.oClass && !method.dataType.thisClass)
5264             {
5265                strcat(name, this.selected.instance._class.name);
5266                strcat(name, "::");
5267                strcat(name, this.methodName);
5268                strcpy(this.methodName, name);
5269             }
5270             else if(method.dataType.thisClass && (this.selected == this.oClass || !eClass_IsDerived(this.oClass.instance._class, method.dataType.thisClass.registered)))
5271             {
5272                strcat(name, method.dataType.thisClass.string);
5273                strcat(name, "::");
5274                strcat(name, this.methodName);
5275                strcpy(this.methodName, name);
5276             }
5277             
5278             this.moveAttached = true;
5279          }
5280
5281          this.methodAction = actionDetachMethod;
5282          this.method = method;
5283          this.function = function;
5284          ModifyCode();
5285          UpdateFormCode(); 
5286          Update(null);
5287       }
5288    }
5289
5290    void AddObject(Instance instance, ObjectInfo * object)
5291    {
5292       int id;
5293       incref instance;
5294       //*object = _class.instances.Add(sizeof(ObjectInfo));
5295       *object = ObjectInfo { };
5296       oClass.instances.Insert((selected.oClass == selected) ? null : selected, *object);
5297       (*object).oClass = oClass;
5298       (*object).instance = instance;
5299       for(id = 1;; id++)
5300       {
5301          char name[1024];
5302          ObjectInfo check;
5303          sprintf(name, "%c%s%d", tolower(instance._class.name[0]), instance._class.name+1, id);
5304
5305          // if(strcmp(name, this.oClass.instance.name)) 
5306          
5307          {
5308             for(check = oClass.instances.first; check; check = check.next)
5309                if(!check.deleted && check.name && !strcmp(name, check.name)) 
5310                   break;
5311             if(!check)
5312             {
5313                (*object).name = CopyString(name);
5314                break;
5315             }
5316          }
5317       }            
5318       toolBox.controlClass = null;
5319
5320       ModifyCode();
5321
5322       //sheet.AddObject(*object, (*object).name, TypeData, true);
5323
5324       selected = *object;
5325    }
5326
5327    void EnsureUpToDate()
5328    {
5329       if(sheet && codeModified)
5330          ParseCode();
5331    }
5332
5333    void SelectObject(ObjectInfo object)
5334    {
5335       selected = object;
5336       oClass = object ? object.oClass : null;
5337       if(designer)
5338          designer.SelectObject(object, object ? object.instance : null);
5339    }
5340
5341    void SelectObjectFromDesigner(ObjectInfo object)
5342    {
5343       selected = object;
5344       sheet.SelectObject(object);
5345    }
5346
5347    void EnumerateObjects(Sheet sheet)
5348    {
5349       ObjectInfo oClass;
5350
5351       for(oClass = classes.first; oClass; oClass = oClass.next)
5352       {
5353          if(oClass.instance)
5354          {
5355             ObjectInfo object;
5356
5357             sheet.AddObject(oClass, oClass.name ? oClass.name : oClass.instance._class.name, typeClass, false);
5358             for(object = oClass.instances.first; object; object = object.next)
5359                sheet.AddObject(object, object.name ? object.name : object.instance._class.name, typeData, false);
5360          }
5361       }
5362       sheet.SelectObject(selected);
5363    }
5364
5365    void AddControl()
5366    {
5367       designer.AddObject();
5368    }
5369
5370    void DeleteObject(ObjectInfo object)
5371    {
5372       delete object.instance;
5373       object.deleted = true;
5374       object.modified = true;
5375       object.oClass.modified = true;
5376
5377       if(selected == object)
5378       {
5379          bool looped = false;
5380          ObjectInfo select = object;
5381
5382          for(;;)
5383          {            
5384             select = select.prev;
5385             if(!select) 
5386             {
5387                if(looped) break;
5388                select = object.oClass.instances.last;
5389                if(!select) break;
5390                looped = true;
5391             }
5392             if(!select.deleted)
5393                break;
5394          }
5395          sheet.SelectObject(select ? select : oClass);
5396       }
5397
5398       if(!object.instCode && object.oClass != object)
5399       {
5400          delete object.name;
5401          oClass.instances.Delete(object);
5402       }
5403
5404       if(sheet.codeEditor == this)
5405          sheet.DeleteObject(object);
5406    }
5407
5408    void RenameObject(ObjectInfo object, char * name)
5409    {
5410       bool valid = false;
5411
5412       // Validate the name:
5413       if(object != oClass && (!name || !name[0])) valid = true;   // What's this one again?
5414       else if(name[0] && (isalpha(name[0]) || name[0] == '_'))
5415       {
5416          int c;
5417          for(c = 0; name[c]; c++)
5418             if(!isalnum(name[c]) && name[c] != '_' && name[c] != '_')
5419                break;
5420          if(!name[c])
5421             valid = true;
5422       }
5423       if(valid)
5424       {
5425          delete object.name;
5426          object.name = (name && name[0]) ? CopyString(name) : null;
5427
5428          sheet.RenameObject(object, object.name ? object.name : object.instance._class.name);
5429       }
5430    }
5431
5432    void DesignerModifiedObject()
5433    {
5434       sheet.ListProperties(false);
5435       sheet.Update(null);
5436    }
5437
5438    void ListSubMembers(Type member)
5439    {
5440       Type subMember;
5441
5442       for(subMember = member.members.first; subMember; subMember = subMember.next)
5443       {
5444          if(subMember.name)
5445          {
5446             DataRow row = membersList.AddString(subMember.name);
5447             row.icon = icons[typeData];
5448          }
5449          else
5450          {
5451             ListSubMembers(subMember);
5452          }
5453       }
5454    }
5455
5456    void ListSubDataMembers(DataMember member, bool isPrivate)
5457    {
5458       DataMember subMember;
5459       for(subMember = member.members.first; subMember; subMember = subMember.next)
5460       {
5461          if((subMember.memberAccess == publicAccess && !isPrivate) || subMember._class.module == privateModule)
5462          {
5463             if(subMember.name)
5464             {
5465                DataRow row = membersList.AddString(subMember.name);
5466                BitmapResource bitmap = null;
5467                if(!subMember.dataType)
5468                   subMember.dataType = ProcessTypeString(subMember.dataTypeString, false);
5469             
5470                if(subMember.dataType && subMember.dataType.kind == classType && subMember.dataType._class)
5471                {
5472                   char * bitmapName = (char *)eClass_GetProperty(subMember.dataType._class.registered, "icon");
5473                   if(bitmapName)
5474                   {
5475                      bitmap = { bitmapName };
5476                      membersList.AddResource(bitmap);
5477                   }
5478                }
5479                row.icon = bitmap ? bitmap : icons[(subMember.memberAccess == publicAccess && !isPrivate) ? typeData : typeDataPrivate];
5480             }
5481             else
5482             {
5483                ListSubDataMembers(subMember, isPrivate || member.memberAccess == privateAccess);
5484             }
5485          }
5486       }
5487    }
5488
5489    void ListClassMembers(Class whatClass, bool methodsOnly)
5490    {
5491       Class _class;
5492       Class baseClass = eSystem_FindClass(this.privateModule, "class");
5493       bool isPrivate = false;
5494
5495       for(_class = whatClass; _class && _class.type != systemClass; _class = _class.base)
5496       {
5497          Method method, methodIt;
5498          DataMember member;
5499          DataMember memberIt;
5500
5501          for(methodIt = (Method)_class.methods.first; methodIt; methodIt = (Method)((BTNode)methodIt).next)
5502          {
5503             method = eClass_FindMethod(whatClass, methodIt.name, privateModule);
5504             if(methodIt.memberAccess == privateAccess && method && method.memberAccess == publicAccess)
5505                method = methodIt;
5506             if(method && method._class.type != systemClass && !eClass_FindMethod(baseClass, method.name, this.privateModule))
5507             {
5508                if(method.memberAccess == publicAccess || method._class.module == privateModule)
5509                {
5510                   DataRow row = membersList.FindString(method.name);
5511                   if(!row)
5512                   {
5513                      row = membersList.AddString(method.name);
5514
5515                      if(!method.dataType)
5516                         method.dataType = ProcessTypeString(method.dataTypeString, false);
5517
5518                      row.icon = icons[(method.type == virtualMethod && method.dataType && method.dataType.thisClass) ? typeEvent : ((method.memberAccess == publicAccess && !isPrivate) ? typeMethod : typeMethodPrivate)];
5519                   }
5520                }
5521             }
5522          }
5523
5524          if(!methodsOnly)
5525          {
5526             for(memberIt = _class.membersAndProperties.first; memberIt; memberIt = memberIt.next)
5527             {
5528                if(memberIt.name)
5529                {
5530                   if(memberIt.isProperty)
5531                   {
5532                      member = (DataMember)eClass_FindProperty(whatClass, memberIt.name, privateModule);
5533                      if(!member)
5534                         member = eClass_FindDataMember(whatClass, memberIt.name, privateModule, null, null);
5535                   }
5536                   else
5537                   {
5538                      member = eClass_FindDataMember(whatClass, memberIt.name, privateModule, null, null);
5539                      if(!member)
5540                         member = (DataMember)eClass_FindProperty(whatClass, memberIt.name, privateModule);
5541                   }
5542
5543                   if(memberIt.memberAccess == privateAccess && member && member.memberAccess == publicAccess)
5544                      member = memberIt;
5545                }
5546                else
5547                   member = memberIt;
5548
5549                if(member && (member.memberAccess == publicAccess || member._class.module == privateModule))
5550                {
5551                   if(member.isProperty)
5552                   {
5553                      Property prop = (Property) member;
5554                      if(!membersList.FindString(prop.name))
5555                      {
5556                         DataRow row = membersList.AddString(prop.name);
5557                         row.icon = icons[(member.memberAccess == publicAccess && !isPrivate) ? typeProperty : typePropertyPrivate];
5558                      }
5559                   }
5560                   else if(member.name && !membersList.FindString(member.name))
5561                   {
5562                      DataRow row = membersList.AddString(member.name);
5563                
5564                      BitmapResource bitmap = null;
5565                      if(!member.dataType)
5566                         member.dataType = ProcessTypeString(member.dataTypeString, false);
5567                
5568                      if(member.dataType && member.dataType.kind == classType && member.dataType._class)
5569                      {
5570                         char * bitmapName = (char *)eClass_GetProperty(member.dataType._class.registered, "icon");
5571                         if(bitmapName)
5572                         {
5573                            bitmap = { bitmapName };
5574                            membersList.AddResource(bitmap);
5575                         }
5576                      }
5577                      row.icon = bitmap ? bitmap : icons[(member.memberAccess == publicAccess && !isPrivate) ? typeData : typeDataPrivate];
5578                   }
5579                   else
5580                      ListSubDataMembers(member, member.memberAccess == privateAccess);
5581                }
5582             }
5583          }
5584          if(_class.inheritanceAccess == privateAccess)
5585          {
5586             isPrivate = true;
5587             if(_class.module != privateModule) break;
5588          }
5589       }
5590    }
5591
5592    void ListClassMembersMatch(Class whatClass, Type methodType)
5593    {
5594       Class _class;
5595       Class baseClass = eSystem_FindClass(this.privateModule, "class");
5596       bool isPrivate = false;
5597
5598       for(_class = whatClass; _class && _class.type != systemClass; _class = _class.base)
5599       {
5600          Method method;
5601          Property prop;
5602          DataMember member;
5603
5604          for(method = (Method)_class.methods.first; method; method = (Method)((BTNode)method).next)
5605          {
5606             if(method.memberAccess == publicAccess || method._class.module == privateModule)
5607             {
5608                if(method._class.type != systemClass && !eClass_FindMethod(baseClass, method.name, this.privateModule))
5609                {
5610                   if(!method.dataType)
5611                      method.dataType = ProcessTypeString(method.dataTypeString, false);
5612
5613                   if(MatchTypes(method.dataType, methodType, null, whatClass, /*null, */whatClass, false, true, false, false))
5614                   {
5615                      DataRow row = membersList.FindString(method.name);
5616                      if(!row)
5617                      {
5618                         row = membersList.AddString(method.name);
5619                         row.icon = icons[(method.type == virtualMethod && method.dataType.thisClass) ? typeEvent : ((method.memberAccess == publicAccess && !isPrivate) ? typeMethod : typeMethodPrivate)];
5620                      }
5621                   }
5622                }
5623             }
5624          }
5625          if(_class.inheritanceAccess == privateAccess)
5626          {
5627             isPrivate = true;
5628             if(_class.module != privateModule) break;
5629          }
5630       }
5631    }
5632
5633    void ListClassPropertiesAndVirtual(Class whatClass)
5634    {
5635       Class _class;
5636       bool isPrivate = false;
5637       for(_class = whatClass; _class && _class.type != systemClass; _class = _class.base)
5638       {
5639          Method method;
5640          Property prop;
5641          DataMember member;
5642
5643          for(method = (Method)_class.methods.first; method; method = (Method)((BTNode)method).next)
5644          {
5645             if(method.type == virtualMethod)
5646             {
5647                if(method.memberAccess == publicAccess || method._class.module == privateModule)
5648                {
5649                   DataRow row = membersList.FindString(method.name);
5650                   if(!row)
5651                   {
5652                      row = membersList.AddString(method.name);
5653
5654                      if(!method.dataType)
5655                         method.dataType = ProcessTypeString(method.dataTypeString, false);
5656
5657                      row.icon = icons[method.dataType.thisClass ? typeEvent : ((method.memberAccess == publicAccess && !isPrivate) ? typeMethod : typeMethodPrivate)];
5658                   }
5659                }
5660             }
5661          }
5662
5663          for(member = _class.membersAndProperties.first; member; member = member.next)
5664          {
5665             if(member.memberAccess == publicAccess || member._class.module == privateModule)
5666             {
5667                if(member.isProperty)
5668                {
5669                   Property prop = (Property)member;
5670                   {
5671                      DataRow row = membersList.AddString(prop.name);
5672                      row.icon = icons[(member.memberAccess == publicAccess && !isPrivate) ? typeProperty : typePropertyPrivate];
5673                   }
5674                }
5675                else if(member.name)
5676                {
5677                   DataRow row = membersList.AddString(member.name);
5678                
5679                   BitmapResource bitmap = null;
5680                   if(!member.dataType)
5681                      member.dataType = ProcessTypeString(member.dataTypeString, false);
5682                
5683                   if(member.dataType && member.dataType.kind == classType && member.dataType._class)
5684                   {
5685                      char * bitmapName = (char *)eClass_GetProperty(member.dataType._class.registered, "icon");
5686                      if(bitmapName)
5687                      {
5688                         bitmap = { bitmapName };
5689                         membersList.AddResource(bitmap);
5690                      }
5691                   }
5692                   row.icon = bitmap ? bitmap : icons[(member.memberAccess == publicAccess && !isPrivate) ? typeData : typeDataPrivate];
5693                }
5694                else
5695                   ListSubDataMembers(member, member.memberAccess == privateAccess || isPrivate);
5696             }
5697          }
5698          if(_class.inheritanceAccess == privateAccess)
5699          {
5700             isPrivate = true;
5701             if(_class.module != privateModule) break;
5702          }
5703       }
5704    }
5705
5706    void ListMembers(Type type)
5707    {
5708       if(type && (type.kind == classType || type.kind == structType || type.kind == unionType))
5709       {
5710          Class _class;
5711          
5712          if(type.kind == classType)
5713          {
5714             if(type._class)
5715                ListClassMembers(type._class.registered, false);
5716          }
5717          else
5718          {
5719             Type member;
5720             for(member = type.members.first; member; member = member.next)
5721             {
5722                if(member.name)
5723                {
5724                   DataRow row = membersList.AddString(member.name);
5725                   row.icon = icons[typeData];
5726                }
5727                else if(member.kind == structType || member.kind == unionType)
5728                   ListSubMembers(member);
5729             }
5730          }
5731       }
5732    }
5733
5734    void ListModule(Module mainModule, int recurse, bool listClasses)
5735    {
5736       Module module;
5737       ListNameSpace(mainModule.application.systemNameSpace, 1, listClasses);
5738       ListNameSpace(mainModule.application.privateNameSpace, 1, listClasses);
5739       ListNameSpace(mainModule.application.publicNameSpace, 1, listClasses);
5740       for(module = mainModule.application.allModules.first; module; module = module.next)
5741       {
5742          if(ModuleVisibility(mainModule, module))
5743             ListNameSpace(module.publicNameSpace, recurse, listClasses);
5744       }
5745    }
5746
5747    void ListNameSpace(NameSpace nameSpace, int recurse, bool listClasses)
5748    {
5749       NameSpace * ns;
5750       BTNamedLink link;
5751
5752       if(listClasses)
5753       {
5754          for(link = (BTNamedLink)nameSpace.classes.first; link; link = (BTNamedLink)((BTNode)link).next)
5755          {
5756             Class _class = link.data;
5757             if(_class.type != systemClass)
5758             {
5759                DataRow row = membersList.AddString(_class.name);
5760                row.icon = (_class.type == unitClass || _class.type == enumClass) ? icons[typeDataType] : icons[typeClass];
5761             }
5762          }
5763       }
5764
5765       for(link = (BTNamedLink)nameSpace.defines.first; link; link = (BTNamedLink)((BTNode)link).next )
5766       {
5767          DefinedExpression definedExp = link.data;
5768          DataRow row = membersList.AddString(link /*definedExp*/.name);
5769          row.icon = icons[typeData];
5770       }
5771
5772       for(link = (BTNamedLink)nameSpace.functions.first; link; link = (BTNamedLink)((BTNode)link).next)
5773       {
5774          GlobalFunction function = link.data;
5775          DataRow row = membersList.AddString(link /*function*/.name);
5776          row.icon = icons[typeMethod];
5777       }
5778
5779
5780       for(ns = (NameSpace *)nameSpace.nameSpaces.first; ns; ns = (NameSpace *)((BTNode)ns).next)
5781       {
5782          if(recurse != 2 && listClasses)
5783          {
5784             if(!membersList.FindString(ns->name))
5785             {
5786                DataRow row = membersList.AddString(ns->name);
5787                row.icon = icons[typeNameSpace];
5788             }
5789          }
5790
5791          if(recurse)
5792             ListNameSpace(ns, 2, listClasses);
5793       }
5794    }
5795
5796    void ListEnumValues(Class _class)
5797    {
5798       List<Class> classes { };
5799       for(; _class && _class.type == enumClass; _class = _class.base)
5800          classes.Insert(null, _class);
5801       for(_class : classes)
5802       {
5803          EnumClassData enumeration = (EnumClassData)_class.data;
5804          NamedLink item;
5805          for(item = enumeration.values.first; item; item = item.next)
5806          {
5807             DataRow row = membersList.AddString(item.name);
5808             row.icon = icons[typeEnumValue];
5809          }
5810       }
5811       delete classes;
5812    }
5813
5814    bool ListEnumsModule(Module mainModule, Type dest)
5815    {
5816       bool result = false;
5817       Module module;
5818       result |= ListEnums(mainModule.application.systemNameSpace, dest);
5819       result |= ListEnums(mainModule.application.privateNameSpace, dest);
5820       result |= ListEnums(mainModule.application.publicNameSpace, dest);
5821       for(module = mainModule.application.allModules.first; module; module = module.next)
5822       {
5823          if(ModuleVisibility(mainModule, module))
5824             result |= ListEnums(module.publicNameSpace, dest);
5825       }
5826       return result;
5827    }
5828
5829    void ListNameSpaceByString(Module mainModule, char * string)
5830    {
5831       NameSpace * nameSpace;
5832       Module module;
5833       nameSpace = FindNameSpace(mainModule.application.systemNameSpace, string);
5834       if(nameSpace) ListNameSpace(nameSpace, 0, true);
5835       nameSpace = FindNameSpace(mainModule.application.privateNameSpace, string);
5836       if(nameSpace) ListNameSpace(nameSpace, 0, true);
5837       nameSpace = FindNameSpace(mainModule.application.publicNameSpace, string);
5838       if(nameSpace) ListNameSpace(nameSpace, 0, true);
5839       for(module = mainModule.application.allModules.first; module; module = module.next)
5840       {
5841          if(ModuleVisibility(mainModule, module))
5842          {
5843             nameSpace = FindNameSpace(module.publicNameSpace, string);
5844             if(nameSpace) ListNameSpace(nameSpace, 0, true);
5845          }
5846       }
5847    }
5848
5849    bool ListEnums(NameSpace nameSpace, Type dest)
5850    {
5851       BTNamedLink link;
5852       bool result = false;
5853
5854       for(link = (BTNamedLink)nameSpace.classes.first; link; link = (BTNamedLink)((BTNode)link).next)
5855       {
5856          Class _class = link.data;
5857          if(_class.type == enumClass && (dest.kind != classType || !dest._class || dest._class.registered != _class))
5858          {
5859             OldList conversions { };
5860             Type type { };
5861             type.kind = classType;
5862             type._class = FindClass(_class.name);
5863             if(MatchTypes(type, dest, &conversions, null, null, true, false, false, false))
5864             {
5865                ListEnumValues(_class);
5866                result = true;
5867             }
5868             conversions.Free(null);
5869             delete type;
5870          }
5871       }
5872       for(nameSpace = (NameSpace *)nameSpace.nameSpaces.first; nameSpace != null; nameSpace = (NameSpace *)((BTNode)nameSpace).next)
5873       {
5874          result |= ListEnums(nameSpace, dest);
5875       }
5876       return result;
5877    }
5878
5879    NameSpace * FindNameSpace(NameSpace nameSpace, char * name)
5880    {
5881       int start = 0, c;
5882       char ch;
5883       for(c = 0; (ch = name[c]); c++)
5884       {
5885          if(ch == '.' || (ch == ':' && name[c+1] == ':'))
5886          {
5887             NameSpace * newSpace;
5888             char * spaceName = new char[c - start + 1];
5889             memcpy(spaceName, name + start, c - start);
5890             spaceName[c-start] = '\0';
5891             newSpace = (NameSpace *)nameSpace.nameSpaces.FindString(spaceName);
5892             delete spaceName;
5893             if(!newSpace)
5894                return null;
5895             nameSpace = newSpace;
5896             if(ch == ':') c++;
5897             start = c+1;
5898          }
5899       }
5900       if(c - start)
5901       {
5902          // name + start;
5903       }
5904       return (NameSpace *)nameSpace;
5905    }
5906
5907    void ListSymbols(Expression exp, bool enumOnly, char * string, Identifier realIdentifier)
5908    {
5909       bool listedEnums = false;
5910       Type destType = (exp && exp.destType && !exp.destType.truth) ? exp.destType : null;
5911       bool listClasses = true;
5912
5913       if(exp && (exp.type == identifierExp || exp.type == memberExp))
5914       {
5915          // TOCHECK: This memberExp check wasn't here... Some stuff isn't quite done
5916          Identifier id = (exp.type == memberExp) ? exp.member.member : exp.identifier;
5917          char * colons = id ? RSearchString(id.string, "::", strlen(id.string), true, false) : null;
5918
5919          if(exp.type == identifierExp)
5920             id = realIdentifier;
5921
5922          if(id && id._class && !id._class.name)
5923          {
5924             listClasses = false;
5925             SetThisClass(null);
5926          }
5927          else if(id && id._class && id._class.name)
5928          {
5929             if(id.classSym)
5930             {
5931                Class _class = id.classSym.registered;
5932                if(_class && _class.type == enumClass)
5933                {
5934                   ListEnumValues(_class);
5935                }
5936                else
5937                   ListClassMembers(id.classSym.registered, true);
5938                return;
5939             }
5940             return;
5941          }
5942          else if(id && colons)
5943          {
5944             ListNameSpaceByString(this.privateModule, id.string);
5945             return;
5946          }
5947       }
5948
5949       if(this.privateModule && destType && (destType.kind != pointerType || destType.type.kind != voidType) && destType.kind != ellipsisType)
5950       {
5951          listedEnums = ListEnumsModule(this.privateModule, destType);
5952       }
5953
5954       if(destType && destType.kind == classType && destType._class.registered && destType._class.registered.type == enumClass)
5955       {
5956          ListEnumValues(destType._class.registered);
5957
5958          if(insideClass)
5959             ListClassPropertiesAndVirtual(insideClass);
5960
5961          listedEnums = true;
5962       }
5963       else if(destType && destType.kind == enumType)
5964       {
5965          NamedLink value;
5966
5967          for(value = destType.members.first; value; value = value.next)
5968          {
5969             DataRow row = membersList.AddString(value.name);
5970             row.icon = icons[typeEnumValue];
5971          }
5972
5973          if(insideClass)
5974             ListClassPropertiesAndVirtual(insideClass);
5975
5976          listedEnums = true;
5977       }
5978       else if(insideClass && !enumOnly)
5979       {
5980          ListClassPropertiesAndVirtual(insideClass);
5981       }
5982
5983       if(listedEnums && string && string[0])
5984       {
5985          DataRow row = membersList.FindSubString(string);
5986          if(!row)
5987             listedEnums = false;      
5988       }
5989       
5990       if(!insideClass && exp && exp.destType && exp.destType.kind == functionType && GetThisClass())
5991       {
5992          ListClassMembersMatch(GetThisClass(), exp.destType);
5993       }
5994       else if(!insideClass && !enumOnly && !listedEnums)
5995       {
5996          Context ctx;
5997          Symbol symbol = null;
5998          {
5999             if(GetThisClass())
6000             { 
6001                ListClassMembers(GetThisClass(), false);
6002             }
6003
6004             for(ctx = listClasses ? GetCurrentContext() : GetTopContext(); ctx != GetTopContext().parent && !symbol; ctx = ctx.parent)
6005             {
6006                for(symbol = (Symbol)ctx.symbols.first; symbol; symbol = (Symbol)((BTNode)symbol).next)
6007                {
6008                   // Don't list enum values?
6009                   //if(symbol.type.kind != TypeEnum)
6010                   DataRow row = membersList.FindString(symbol.string);
6011                   if(!row)
6012                   {
6013                      if(GetBuildingEcereComModule() && symbol.type && symbol.type.kind == functionType && eSystem_FindFunction(privateModule, symbol.string))
6014                         continue;
6015                      row = membersList.AddString(symbol.string);
6016                      if(symbol.type && symbol.type.kind == functionType)
6017                         row.icon = icons[typeMethod];
6018                      else if(symbol.type && symbol.type.kind == enumType)
6019                      {
6020                         row.icon = icons[typeEnumValue];
6021                      }
6022                      else 
6023                      {
6024                         BitmapResource bitmap = null;
6025                         if(symbol.type && symbol.type.kind == classType && symbol.type._class && symbol.type._class)
6026                         {
6027                            char * bitmapName = (char *)eClass_GetProperty(symbol.type._class.registered, "icon");
6028                            if(bitmapName)
6029                            {
6030                               bitmap = { bitmapName };
6031                               membersList.AddResource(bitmap);
6032                            }
6033                         }
6034                         row.icon = bitmap ? bitmap : icons[typeData];
6035                      }
6036                   }
6037                }
6038
6039                if(listClasses)
6040                {
6041                   for(symbol = (Symbol)ctx.types.first; symbol; symbol = (Symbol)((BTNode)symbol).next)
6042                   {
6043                      DataRow row = membersList.FindString(symbol.string);
6044                      if(!row)
6045                      {
6046                         row = membersList.AddString(symbol.string);
6047                         if(symbol.type.kind == functionType)
6048                            row.icon = icons[typeMethod];
6049                         else if(symbol.type.kind == classType && (!symbol.type._class.registered || (symbol.type._class.registered.type != unitClass && symbol.type._class.registered.type != enumClass)))
6050                         {
6051                            row.icon = icons[typeClass];
6052                         }
6053                         else
6054                         {
6055                            row.icon = icons[typeDataType];
6056                         }
6057                      }
6058                   }
6059                }
6060             }
6061
6062             ListModule(this.privateModule, 1, listClasses);
6063             // TODO: Implement this with name space
6064             /*
6065             {
6066                GlobalData data;
6067                for(data = globalData.first; data; data = data.next)
6068                {
6069                   DataRow row = membersList.FindString(data.name);
6070                   if(!data.dataType)
6071                      data.dataType = ProcessTypeString(data.dataTypeString, false);
6072                   if(!row)
6073                   {
6074                      row = membersList.AddString(data.name);
6075
6076                      if(data.dataType && data.dataType.kind == TypeEnum)
6077                      {
6078                         row.icon = icons[typeEnumValue];
6079                      }
6080                      else 
6081                      {
6082                         BitmapResource bitmap = null;
6083                         if(data.dataType && data.dataType.kind == classType && data.dataType._class && data.dataType._class)
6084                         {
6085                            char * bitmapName = (char *)eClass_GetProperty(data.dataType._class.registered, "icon");
6086                            if(bitmapName)
6087                            {
6088                               bitmap = { bitmapName };
6089                               membersList.AddResource(bitmap);
6090                            }
6091                         }
6092                         row.icon = bitmap ? bitmap : icons[typeData];
6093                      }
6094                   }
6095                }
6096             }
6097             */
6098
6099             {
6100                DataRow row = membersList.AddString("Min");
6101                row.icon = icons[typeMethod];
6102
6103                row = membersList.AddString("Max");
6104                row.icon = icons[typeMethod];
6105
6106                row = membersList.AddString("Abs");
6107                row.icon = icons[typeMethod];
6108
6109                row = membersList.AddString("Sgn");
6110                row.icon = icons[typeMethod];
6111             }
6112          }
6113       }
6114    }
6115
6116    void OverrideVirtualFunction(ClassFunction function, Method method, Class _class, bool isInstance, bool extraIndent)
6117    {
6118       EditBoxStream f { editBox = editBox };
6119       uint position = 0;
6120       EditLine l1, l2;
6121       int x1,y1,x2,y2;
6122
6123       updatingCode = true;
6124
6125       if(!method.dataType)
6126          method.dataType = ProcessTypeString(method.dataTypeString, false);
6127
6128       DeleteJunkBefore(f, function.loc.start.pos, &position);
6129       f.DeleteBytes(function.loc.end.pos - function.loc.start.pos - 1);
6130
6131       // ADDING METHOD HERE
6132       {
6133          Type dataType = method.dataType;
6134          Type returnType = dataType.returnType;
6135          Type param;
6136          Class moduleClass = eSystem_FindClass(this.privateModule, "Module");
6137
6138          if(insideDef.prev)
6139              f.Printf("\n\n");
6140          else
6141             f.Printf("\n");
6142          if(extraIndent) f.Printf("   ");
6143          f.Printf("   ");
6144          OutputType(f, returnType, false);
6145
6146          f.Printf(" ");
6147          
6148          if(dataType.thisClass && !dataType.classObjectType && (!isInstance || !insideClass || !eClass_IsDerived(insideClass, dataType.thisClass.registered)))
6149          {
6150             if(dataType.thisClass.shortName)
6151                f.Printf(dataType.thisClass.shortName);
6152             else
6153                f.Printf(dataType.thisClass.string);
6154             f.Printf("::");
6155          }
6156          f.Printf(method.name);
6157          f.Printf("(");
6158          for(param = dataType.params.first; param; param = param.next)
6159          {
6160             // Decided not to write void...
6161             if(param.kind != voidType)
6162             {
6163                OutputType(f, param, true);
6164                if(param.next)
6165                   f.Printf(", ");
6166             }
6167          }
6168          f.Printf(")\n");                  
6169          if(extraIndent) f.Printf("   ");
6170          f.Printf("   %c\n", OpenBracket);
6171
6172          editBox.GetSelPos(&l1, &y1, &x1, &l2, &y2, &x2, false);
6173
6174          f.Printf("\n");
6175
6176          if(!_class || 
6177             (
6178                (isInstance ? _class : _class.base)._vTbl[method.vid] == moduleClass._vTbl[__ecereVMethodID___ecereNameSpace__ecere__com__Module_OnLoad] ||
6179                (isInstance ? _class : _class.base)._vTbl[method.vid] == DummyMethod)) // Temp Check for DefaultFunction
6180          {
6181             if(returnType && returnType.kind == classType && !strcmp(returnType._class.string, "bool"))
6182             {
6183                if(extraIndent) f.Printf("   ");
6184                f.Printf("      return true;\n");
6185             }
6186             else if(returnType && returnType.kind != voidType)
6187             {
6188                if(extraIndent) f.Printf("   ");
6189                f.Printf("      return 0;\n");
6190             }
6191          }
6192          else
6193          {
6194             if(extraIndent) f.Printf("   ");
6195             f.Printf("      ");
6196             if(returnType.kind != voidType)
6197                f.Printf("return ");
6198             f.Printf("%s::%s(", isInstance ? _class.name : _class.base.name, method.name);
6199             for(param = dataType.params.first; param; param = param.next)
6200             {
6201                if(param.prev) f.Printf(", ");
6202                if(param.kind != voidType)
6203                   f.Printf(param.name);
6204             }
6205             f.Printf(");\n");
6206          }
6207       }
6208
6209       if(extraIndent) f.Printf("   ");
6210       f.Printf("   %c", CloseBracket);
6211       // f.Printf("\n");
6212
6213       delete f;
6214
6215       if(extraIndent) { x1 += 3; x2 += 3; }
6216       editBox.SetSelPos(l1, y1, x1 + 6, l2, y2, x2 + 6);
6217
6218       this.updatingCode = false;
6219
6220    }
6221
6222    // Return false if we overrided a function and don't want to run params listing
6223    bool InvokeAutoComplete(bool enumOnly, int pointer, bool caretMove)
6224    {
6225       bool didOverride = false;
6226       EditLine line = editBox.line;
6227       char * text = line.text;
6228       int lineNum, charPos;
6229       Expression exp = null;
6230       EditLine l1, l2;
6231       int x1,y1, x2,y2;
6232       //Identifier id = null;
6233       Expression memberExp = null;
6234       Identifier realIdentifier = null;
6235
6236       if(!privateModule) return !didOverride;
6237
6238       insideFunction = null;
6239
6240       charPos = editBox.charPos + 1;
6241       if(!membersListShown)
6242       {
6243          EnsureUpToDate();
6244       }
6245
6246       editBox.GetSelPos(&l1, &y1, &x1, &l2, &y2, &x2, false);
6247       { 
6248          EditBoxStream f { editBox = editBox };
6249
6250          updatingCode = true;
6251          editBox.SetSelPos(l1, y1, x1, l2, y2, x2);
6252          for(;;)
6253          {
6254             char ch;
6255             if(!f.Seek(-1, current))
6256                break;
6257             f.Getc(&ch);
6258             if(!isspace(ch)) break;
6259             f.Seek(-1, current);
6260          }
6261          editBox.GetSelPos(&l1, &y1, &x1, &l2, &y2, &x2, false);
6262
6263          lineNum = editBox.lineNumber + 1;
6264          charPos = editBox.charPos + 1;
6265          delete f;
6266          updatingCode = false;
6267       }
6268
6269       if(!membersListShown)
6270       {
6271          memberExp = FindExpTree(ast, lineNum, charPos);
6272          if(memberExp && (memberExp.type == TypeKind::memberExp || memberExp.type == pointerExp) && !memberExp.addedThis)
6273          {
6274          }
6275          else if(!pointer)
6276          {
6277             editBox.GetSelPos(&l1, &y1, &x1, &l2, &y2, &x2, false);
6278             { 
6279                EditBoxStream f { editBox = editBox };
6280                char ch = 0;
6281
6282                updatingCode = true;
6283
6284                editBox.SetSelPos(l1, y1, x1, l2, y2, x2);
6285
6286                f.Getc(&ch);
6287                if(ch == '}' || ch == ',' || ch == ')')
6288                {
6289                   f.Seek(-1, current);
6290                   ch = ' ';
6291                }
6292                if(isspace(ch))
6293                {
6294                   for(;;)
6295                   {
6296                      char ch;
6297                      if(!f.Seek(-1, current))
6298                         break;
6299                      f.Getc(&ch);
6300                      if(!isspace(ch)) break;
6301                      f.Seek(-1, current);
6302                   }
6303                }
6304                else
6305                   f.Seek(-1, current);
6306
6307                editBox.GetSelPos(&l1, &y1, &x1, &l2, &y2, &x2, false);
6308
6309                lineNum = editBox.lineNumber + 1;
6310                charPos = editBox.charPos + 1;
6311                delete f;
6312                updatingCode = false;
6313             }
6314
6315             realIdentifier = FindCtxTree(ast, lineNum, charPos);
6316             exp = ctxInsideExp;
6317          }
6318       }
6319
6320       editBox.GetSelPos(&l1, &y1, &x1, &l2, &y2, &x2, false);
6321       lineNum = editBox.lineNumber + 1;
6322       charPos = editBox.charPos/* + 1*/;
6323
6324       {
6325          int rowCount;
6326          char tempString[1024];
6327          char * string = null;
6328          CodePosition idStart, idEnd;
6329
6330          if(membersListShown)
6331          {
6332             char * buffer = membersLine.text;
6333             int c;
6334             bool firstChar = true;
6335             int len = 0;
6336             string = tempString;
6337
6338             for(c = membersLoc.start.charPos; c<membersLoc.end.charPos; c++)
6339             {
6340                bool isSpace = (buffer[c] == ' ' || buffer[c] == '\t');
6341                if(!isSpace) firstChar = false;
6342                if(!firstChar)
6343                   string[len++] = buffer[c];
6344             }
6345             string[len] = 0;
6346          }
6347          else //if(realIdentifier)//if(id)
6348          {
6349             /*
6350             char * buffer = id.string;
6351             int c;
6352             bool firstChar = true;
6353             int len = 0;
6354             string = tempString;
6355             for(c = 0; c<= charPos - id.loc.start.charPos; c++)
6356             {
6357                bool isSpace = (buffer[c] == ' ' || buffer[c] == '\t');
6358                if(!isSpace) firstChar = false;
6359                if(!firstChar)
6360                   string[len++] = buffer[c];
6361             }
6362             string[len] = 0;
6363             */
6364             int x, y;
6365             int len = 0;
6366             EditLine editLine = editBox.line;
6367             bool firstChar = true;
6368             bool done = false;
6369
6370             string = tempString;
6371             for(y = lineNum-1; y >= 0; y--)
6372             {
6373                char * buffer = editLine.text;
6374                int lineCount = editLine.count;
6375                for(x = (y == lineNum-1) ? (Min(charPos, lineCount) - 1 ): lineCount-1; x >= 0; x--)
6376                {
6377                   bool isSpace = (buffer[x] == ' ' || buffer[x] == '\t');
6378                   if(!isSpace)
6379                   {
6380                      if(firstChar)
6381                      {
6382                         idEnd.charPos = x + 2;
6383                         idEnd.line = y + 1;
6384                      }
6385                      firstChar = false;
6386                   }
6387                   // TESTING THIS CODE HERE FOR NOT CONSIDERING bool when doing ctrl-space past it
6388                   else if(firstChar)
6389                   {
6390                      idEnd.charPos = x + 2;
6391                      idEnd.line = y + 1;
6392                      done = true;
6393                      break;
6394                   }
6395                   if(!firstChar)
6396                   {
6397                      if(!isalnum(buffer[x]) && buffer[x] != '_')
6398                      {
6399                         x++;
6400                         done = true;
6401                         break;
6402                      }
6403                      memmove(string+1, string, len++);
6404                      string[0] = buffer[x];
6405                   }
6406                }
6407
6408                //if(done || firstChar)
6409                if(done || !firstChar)
6410                   break;
6411                editLine = editLine.prev;
6412             }
6413             string[len] = 0;
6414             if(!strcmp(string, "case"))
6415             {
6416                idEnd.charPos += 4;
6417                x+=4;
6418                string[0] = '\0';
6419             }
6420             else if(!strcmp(string, "return"))
6421             {
6422                idEnd.charPos += 6;
6423                x+=6;
6424                string[0] = '\0';
6425             }
6426             else if(!strcmp(string, "delete"))
6427             {
6428                idEnd.charPos += 6;
6429                x+=6;
6430                string[0] = '\0';
6431             }
6432             else if(!strcmp(string, "new"))
6433             {
6434                idEnd.charPos += 3;
6435                x+=3;
6436                string[0] = '\0';
6437             }
6438             else if(!strcmp(string, "renew"))
6439             {
6440                idEnd.charPos +=5;
6441                x+=5;
6442                string[0] = '\0';
6443             }
6444             if(x < 0) x = 0;
6445
6446             idStart.charPos = x + 1;
6447             idStart.line = y + 1;
6448          }
6449
6450          if(!membersListShown)
6451          {
6452             membersList.Clear();
6453             if(memberExp && (memberExp.type == ExpressionType::memberExp || memberExp.type == pointerExp) && !memberExp.addedThis)
6454             {
6455                Type type = memberExp.member.exp.expType;
6456                if(pointer == 2 && type)
6457                {
6458                   if(type.kind == pointerType || type.kind == arrayType)
6459                      type = type.type;
6460                   /*else
6461                      type = null;*/
6462                }
6463                ListMembers(type);
6464             }
6465             else if(!pointer)
6466             {
6467                ListSymbols(exp, enumOnly, string, realIdentifier);
6468             }
6469             membersList.Sort(null, 1);
6470          }
6471
6472          if(insideFunction)
6473          {
6474             // Virtual function override
6475             Identifier id = GetDeclId(insideFunction.declarator);
6476             char * string = id ? id.string : null;
6477
6478             Method method = eClass_FindMethod(GetThisClass(), string, this.privateModule);
6479             if(method)
6480             {
6481                if(method.type != virtualMethod || (!insideInstance && method._class == GetThisClass()))
6482                   insideFunction = null;
6483                else
6484                {
6485                   OverrideVirtualFunction(insideFunction, method, GetThisClass(), insideInstance, insideInstance && insideClass);
6486                   didOverride = true;
6487                }
6488             }
6489          }
6490          if(!didOverride) //insideFunction)
6491          {
6492             rowCount = membersList.rowCount;
6493             if(rowCount)
6494             {
6495                DataRow row = string ? membersList.FindSubString(string) : null;
6496                if(row && !membersList.FindSubStringAfter(row, string) && !caretMove)
6497                {
6498                   char * newString = row.string;
6499                   if(!membersListShown)
6500                   {
6501                      membersLoc.start.line = idStart.line-1;
6502                      membersLoc.start.charPos = idStart.charPos-1;
6503                      //membersLoc.end = membersLoc.start;
6504                       membersLoc.end.charPos = idEnd.charPos-1;
6505                       membersLoc.end.line = idEnd.line-1;
6506                      //membersLoc.end.charPos = idStart.charPos + strlen(string)-1; //end.charPos-1;
6507                      //membersLoc.end.charPos = idStart.charPos + strlen(string)-1; //end.charPos-1;
6508                      membersLine = line;
6509                   }
6510                   else
6511                   {
6512                      membersList.Destroy(0);
6513                      membersListShown = false;
6514                   }
6515
6516                   editBox.GoToPosition(membersLine, membersLoc.start.line, membersLoc.start.charPos);
6517                   editBox.Delete(
6518                      line, membersLoc.start.line, membersLoc.start.charPos,
6519                      line, membersLoc.end.line, membersLoc.end.charPos);
6520                   editBox.PutS(newString);
6521                }
6522                else
6523                {
6524                   if(!row)
6525                   {
6526                      row = membersList.FindSubStringi(string);
6527                      if(row)
6528                         membersList.currentRow = row;
6529                      membersList.currentRow.selected = false;
6530                   }
6531                   else
6532                      membersList.currentRow = row;
6533
6534                   if(!membersListShown)
6535                   {
6536                      Point caret;
6537
6538                      // TESTING THESE ADDITIONS TO THE IF SO THAT CARET ISNT MOVED IF NOT ON TOP OF A WORD
6539                      if(string && string[0] && lineNum == idStart.line && charPos >= idStart.charPos-1 && charPos <= idEnd.charPos-1)
6540                         editBox.SetSelPos(l1, y1, idStart.charPos-1, l2, y2, idStart.charPos-1);
6541                      editBox.GetCaretPosition(caret);
6542                      editBox.SetSelPos(l1, y1, x1, l2, y2, x2);
6543                
6544                      membersList.master = this;
6545
6546                      caret.y += editBox.GetCaretSize();
6547                      caret.x -= 20;
6548                      membersList.Create();
6549
6550                      {
6551                         int x = caret.x + editBox.absPosition.x - app.desktop.absPosition.x - editBox.scroll.x;
6552                         int y = caret.y + editBox.absPosition.y - app.desktop.absPosition.y - editBox.scroll.y;
6553                         Window parent = membersList.parent;
6554
6555                         if(!paramsAbove && (paramsShown || y + membersList.size.h > parent.clientSize.h))
6556                         {
6557                            y -= editBox.GetCaretSize() + membersList.size.h;
6558                            membersAbove = true;
6559                         }
6560                         else
6561                            membersAbove = false;
6562
6563                         membersList.position = { x, y };
6564                      }
6565
6566                      membersLine = l1;
6567                      membersLoc.start.line = lineNum - 1;
6568
6569                      if(string && string[0])
6570                      {
6571                         membersLoc.start.charPos = idStart.charPos-1;
6572                         membersLoc.end = membersLoc.start;
6573                         //membersLoc.end.charPos = id.loc.end.charPos-1;
6574                         membersLoc.end.charPos = idStart.charPos + strlen(string)-1; //end.charPos-1;
6575                      }
6576                      else
6577                      {
6578                         membersLoc.start.charPos = charPos;
6579                         membersLoc.end = membersLoc.start;
6580                         membersLoc.end.charPos = charPos;
6581                      }
6582                      membersListShown = true;
6583
6584                      // Hack to keep caret shown
6585                      editBox.GetCaretPosition(caret);
6586                      editBox.SetCaret(caret.x, caret.y, editBox.GetCaretSize());
6587                   }
6588                   if(row)
6589                      membersList.SetScrollPosition(0, row.index * membersList.rowHeight);
6590                }            
6591             }
6592          }
6593       }
6594
6595       SetCurrentContext(globalContext);
6596       SetThisClass(null);
6597
6598       return !didOverride;
6599    }
6600
6601    void InvokeParameters(bool exact, bool reposition, bool caretMove)
6602    {
6603       EditLine line = editBox.line;
6604       char * text = line.text;
6605       int lineNum, charPos;
6606       Expression exp = null;
6607       EditLine l1, l2;
6608       int x1,y1, x2,y2;
6609
6610       charPos = editBox.charPos + 1;
6611       EnsureUpToDate();
6612
6613       editBox.GetSelPos(&l1, &y1, &x1, &l2, &y2, &x2, false);
6614       { 
6615          EditBoxStream f { editBox = editBox };
6616          char ch;
6617
6618          updatingCode = true;
6619          editBox.SetSelPos(l1, y1, x1, l2, y2, x2);
6620
6621          f.Getc(&ch);
6622          if(ch == '}' || ch == ',' || ch == ')')
6623          {
6624             f.Seek(-1, current);
6625             ch = ' ';
6626          }
6627          if(isspace(ch))
6628          {
6629             for(;;)
6630             {
6631                char ch;
6632                if(!f.Seek(-1, current))
6633                   break;
6634                f.Getc(&ch);
6635                if(!isspace(ch)) break;
6636                f.Seek(-1, current);
6637             }
6638          }
6639          else
6640             f.Seek(-1, current);
6641
6642          editBox.GetSelPos(&l1, &y1, &x1, &l2, &y2, &x2, false);
6643
6644          lineNum = editBox.lineNumber + 1;
6645          charPos = editBox.charPos + 1;
6646          delete f;
6647          updatingCode = false;
6648       }
6649       
6650       charPos = Min(charPos, l1.count + 1);
6651       if(!caretMove)
6652          FindParamsTree(ast, lineNum, charPos);
6653
6654       // Not sure about this == ExpCall... paramsInsideExp doesn't seem to necessarily be a ExpCall
6655       if(exact && ((::functionType && paramsInsideExp.type == callExp && paramsInsideExp.call.exp.loc.end.charPos != charPos-1) /*|| instanceType*/))
6656       {
6657          ::functionType = null;
6658          ::instanceType = null;
6659       }
6660
6661       //if((::functionType || ::instanceType) && (!paramsShown || insideExp != functionExp || ::paramsID != this.paramsID))
6662       if((::functionType || ::instanceType) && (!paramsShown || true /*paramsInsideExp.destType != functionExp.destType */|| ::paramsID != this.paramsID))
6663       {
6664
6665          int x, y;
6666          Window parent = paramsList.parent;
6667
6668          if(this.functionType != ::functionType || this.instanceType != ::instanceType)
6669             reposition = false;
6670
6671          if(!this.paramsShown || reposition || paramsInsideExp != functionExp || ::instanceType) // Added instanceType here, otherwise instance popups never reposition... 
6672                                                                                                           // ( Dummy exp: always ends up with same memory)
6673          {
6674             editBox.GetSelPos(&l1, &y1, &x1, &l2, &y2, &x2, false);
6675             editBox.GetCaretPosition(paramsPosition);
6676             this.paramsPosition.y += editBox.GetCaretSize();
6677          }
6678
6679          FreeType(this.functionType);
6680          FreeType(this.instanceType);
6681
6682          this.functionType = ::functionType;
6683          this.instanceType = ::instanceType;
6684
6685          if(this.functionType) this.functionType.refCount++;
6686          if(this.instanceType) this.instanceType.refCount++;
6687
6688          this.paramsID = ::paramsID;
6689          functionExp = paramsInsideExp;
6690
6691          paramsList.master = this;
6692
6693          paramsList.Create();
6694
6695          x = paramsPosition.x + editBox.absPosition.x - app.desktop.absPosition.x - editBox.scroll.x;
6696          y = paramsPosition.y + editBox.absPosition.y - app.desktop.absPosition.y - editBox.scroll.y;
6697
6698          if(!this.membersAbove && ( this.membersListShown || y + paramsList.size.h > parent.clientSize.h) )
6699          {
6700             y -= editBox.GetCaretSize() + paramsList.clientSize.h;
6701             paramsAbove = true;
6702          }
6703          else
6704             paramsAbove = false;
6705          if(x + paramsList.size.w > parent.clientSize.w)
6706          {
6707             x = parent.clientSize.w - paramsList.size.w;
6708             if(x < 0) x = 0;
6709          }
6710
6711          paramsList.position = { x, y };
6712
6713          // Hack to keep caret shown
6714          {
6715             Point caret;
6716             editBox.GetCaretPosition(caret);
6717             editBox.SetCaret(caret.x, caret.y, editBox.GetCaretSize());
6718          }
6719
6720          this.paramsShown = true;
6721       }
6722       else if((!::functionType && !::instanceType) || reposition)
6723       {
6724          paramsList.Destroy(0);
6725          paramsShown = false;
6726
6727          FreeType(this.functionType);
6728          FreeType(this.instanceType);
6729          this.functionType = null;
6730          this.instanceType = null;
6731          this.paramsID = -1;
6732       }
6733
6734       SetCurrentContext(globalContext);
6735       SetThisClass(null);
6736    }
6737
6738    bool ViewDesigner()
6739    {
6740       if(designer)
6741       {
6742          designer.visible = true;
6743          designer.Activate();
6744       }
6745       return true;
6746    }
6747 };
6748
6749 CodeEditor NewCodeEditor(Window parent, WindowState state, bool modified)
6750 {
6751    CodeEditor document { state = state, parent = parent, modifiedDocument = modified };
6752    document.Create();
6753    return document;
6754 }