Initial git commit -- Transition from CodeGuard repository
[sdk] / eda / libeda / src / idList.ec
1 #ifdef ECERE_STATIC
2 public import static "ecere"
3 #else
4 public import "ecere"
5 #endif
6
7 import "EDA.ec"
8 import "gui"
9
10 default:
11 extern int __ecereVMethodID_class_OnGetString;
12 extern int __ecereVMethodID_class_OnCompare;
13 extern int __ecereVMethodID_class_OnUnserialize;
14 extern int __ecereVMethodID_class_OnSerialize;
15 extern int __ecereVMethodID_class_OnFree;
16
17 static void UnusedFunction()
18 {
19    int a;
20    a.OnGetString(0,0,0);
21    a.OnFree();
22    a.OnCopy(null);
23    a.OnCompare(null);
24    a.OnSaveEdit(null,0);
25    a.OnEdit(null,null,0,0,0,0,0);
26    a.OnDisplay(null,0,0,0,0,0,0);
27    a.OnGetDataFromString(null);
28    a.OnUnserialize(null);
29    a.OnSerialize(null);
30 }
31 private:
32
33 public class Id : uint
34 {
35    class_data Table * table;     class_property Table * table     { set { class_data(table) = value; } get { return class_data(table); } };
36    class_data Field * nameField; class_property Field * nameField { set { class_data(nameField) = value; } get { return class_data(nameField); } };
37    class_data char * addText;   class_property char * addText  { set { class_data(addText) = value; } };
38    class_data void * Refill;    class_property void * Refill   { set { class_data(Refill) = value; } };
39
40    Window OnEdit(DataBox dataBox, void * obsolete, int x, int y, int w, int h, void * userData)
41    {
42       if(this || !this) {     // FIXME
43          TableDropBox dropBox = dataBox.keepEditor ? (TableDropBox)dataBox.editor /*obsolete*/ : null;
44          if(!dropBox)
45          {
46             dropBox = TableDropBox
47             {
48                dataBox, borderStyle = 0, anchor = { 0, 0, 0, 0 }, 
49                modifyVirtualArea = false, activeStipple = false;
50                showNone = true;
51                nameField = *class_data(nameField);
52                table = *class_data(table);
53
54                bool DataBox::NotifySelect(DropBox control, DataRow row, Modifiers mods)
55                {
56                   uint id = row ? row.tag : 0;
57                   SetData(&id, mods.closingDropDown);
58                   return true;
59                }
60
61                bool DataBox::NotifyTextEntry(DropBox _dropBox, char * string, bool confirmed)
62                {
63                   TableDropBox dropBox = (TableDropBox)_dropBox;
64                   //Table tbl = dropBox.table.db.OpenTable(dropBox.table.name, { tableRows });
65                   //if(tbl)
66                   {
67                      /*FieldIndex indexedFields[1];
68                      Row r { };*/
69                      char * trimmed = new char[strlen(string) + 1];
70                      /*indexedFields[0] = { dropBox.nameField };
71                      tbl.GenerateIndex(1, indexedFields, false);
72                      r.tbl = tbl;*/
73                      DataRow row = null;
74
75                      TrimLSpaces(string, trimmed);
76                      TrimRSpaces(trimmed, trimmed);
77
78                      /*if(r.Find(dropBox.nameField, middle, nil, trimmed))
79                      {
80                         if(dropBox.filterField)
81                         {
82                            // TODO: Improve this... Multi field?
83                            while(true)
84                            {
85                               DataRow row;
86                               Id id = 0;
87                               Field fldId = dropBox.table.FindField(defaultIdField);
88                               r.GetData(fldId, id);
89                               row = dropBox.FindSubRow(id);
90                               if(row)
91                               {
92                                  dropBox.SelectRow(row);
93                                  break;
94                               }
95                               //if(!r.Find(dropBox.nameField, next, nil, trimmed))
96                               if(!r.Next())
97                                  break;
98                            }
99                         }
100                         else
101                         {
102                            Id id = 0;
103                            Field fldId = dropBox.table.FindField(defaultIdField);
104                            r.GetData(fldId, id);
105                            dropBox.SelectRow(dropBox.FindSubRow(id));
106                         }
107                      }
108                      */
109
110                      {
111                         for(row = dropBox.firstRow; row; row = row.next)
112                         {
113                            char * string = row.string;
114                            if(string && !strcmp(trimmed, string))
115                               break;
116                         }
117                      }
118                      if(row)
119                      {
120                         dropBox.SelectRow(row);
121                      }
122                      else
123                      {
124                         dropBox.changeContents = false;
125                         dropBox.contents = trimmed;
126                         dropBox.SelectRow(null);
127                         dropBox.changeContents = true;
128                      }
129                      //delete r;
130                   }
131                   return true;
132                }
133             };
134             if(class_data(Refill))
135                dropBox.Refill = class_data(Refill);
136
137             // dropBox.Refill();
138          }
139          dataBox.OnConfigure(dropBox);
140          dropBox.Create();
141          dropBox.currentRow = dropBox.FindSubRow(this);
142          {
143             DataRow r = dropBox.currentRow;
144             if(r)
145                for(r = r.parent; r; r = r.parent)
146                   r.collapsed = false;
147          }
148          return dropBox;
149       }
150       return null;
151    }
152
153    char * OnGetString(char * tempString, void * fieldData, bool * needClass)
154    {
155       if(&this)
156       {
157          // FIXME
158          Table tbl = *class_data(table);
159          Field idField = tbl.FindField(defaultIdField);
160          Row r { tbl };
161
162          if(this)
163          {
164             if(r.Find(idField, middle, nil, this))
165             {
166                String name = null;
167                Field * nameField = class_data(nameField);
168                char * fn = nameField->name;
169                r.GetData(*nameField, name);
170                if(name)
171                {
172                   strcpy(tempString, name);
173                   delete name;
174                }
175                else
176                   strcpy(tempString, "");
177             }
178          }
179          else
180          {
181             sprintf(tempString, "(Click to add a new %s...)", "item"/*class_data(addText)*/);
182          }
183          delete r;
184       }
185       return tempString;
186    }
187 }
188
189 public class IdList
190 {
191 public:
192    int count;
193    Id * ids;
194    class_data Class type;
195    class_property Class type
196    {
197       set {  class_data(type) = value; }
198       get { return class_data(type); }
199    };
200
201    public void Clear()
202    {
203       if(this)
204       {
205          delete ids;
206          count = 0;
207       }
208    }
209    
210    public bool Includes(Id id)
211    {
212       if(this)
213       {
214          int c;
215          for(c = 0; c < count; c++)
216             if(ids[c] == id) 
217                return true;
218       }
219       return false;
220    }
221
222    public bool Add(Id id)
223    {
224       int c;
225       for(c = 0; c < count; c++)
226          if(ids[c] == id) break;
227       if(c == count)
228       {
229          ids = renew ids Id[count + 1];
230          ids[count] = id;
231          count++;
232          return true;
233       }
234       return false;
235    }
236
237    public bool Delete(Id id)
238    {
239       int c;
240       for(c = 0; c < count; c++)
241          if(ids[c] == id)
242          {
243             if(c < count - 1)
244                memcpy(ids + c, ids + c + 1, (count - 1 - c) * sizeof(Id));
245             ids = renew ids Id[count - 1];
246             count--;
247             return true;
248          }
249       return false;
250    }
251
252    void OnUnserialize(IOChannel channel)
253    {
254       int c, count;
255
256       this = null;
257
258       channel.Unserialize(count);
259       if(count != MAXDWORD)
260       {
261          this = eInstance_New(_class); //IdList { };
262          for(c = 0; c < count; c++)
263          {
264             Id id;
265             channel.Unserialize(id);
266             Add(id);
267          }
268       }
269    }
270
271    void OnSerialize(IOChannel channel)
272    {
273       if(this)
274       {
275          int c;
276          channel.Serialize(count);
277          for(c = 0; c < count; c++)
278             channel.Serialize(ids[c]);
279       }
280       else
281       {
282          Id none = MAXDWORD;
283          channel.Serialize(none);
284       }
285    }
286
287    void OnDisplay(Surface surface, int x, int y, int width, void * fieldData, Alignment alignment, DataDisplayFlags displayFlags)
288    {
289
290    }
291    
292    char * OnGetString(char * stringOutput, void * fieldData, bool * needClass)
293    {
294       stringOutput[0] = 0;
295       if(this)
296       {
297          int c;
298          for(c = 0; c<count; c++)
299          {
300             char tempString[256];
301             Class type = class_data(type);
302             if(c) strcat(stringOutput, ", ");
303
304             if(type)
305                type._vTbl[__ecereVMethodID_class_OnGetString](type, &ids[c], tempString, null, null);
306             // strcatf(stringOutput, "%d", ids[c]);
307             strcat(stringOutput, tempString);
308          }
309       }
310       return stringOutput;
311    }
312
313    bool OnGetDataFromString(char * string)
314    {
315       char value[256];
316       this = IdList { };
317       while(GetAlNum(&string, value, sizeof(value)))
318          if(isdigit(value[0]))
319             Add(atoi(value));
320       return true;
321    }
322
323    int OnCompare(IdList b)
324    {
325       if(count > b.count) return 1;
326       else if(count < b.count) return -1;
327       else
328       {
329          int c;
330          for(c = 0; c<count; c++)
331          {
332             int idA = ids[c], idB = b.ids[c];
333             if(idA > idB) return 1;
334             else if(idA < idB) return -1;
335          }         
336       }
337       return 0;
338    }
339
340    Window OnEdit(DataBox dataBox, DataBox obsolete, int x, int y, int w, int h, void * userData)
341    {
342       ListBox list
343       {
344          dataBox,
345          borderStyle = 0,
346          alwaysEdit = true,
347          anchor = { 0, 0, 0, 0 };
348
349          bool DataBox::NotifyChanged(ListBox listBox, DataRow row)
350          {
351             Id id = row.GetData(null);
352             if(!id)
353             {
354                if(row.next)
355                   listBox.DeleteRow(row);
356             }            
357             else
358             {
359                if(row == listBox.lastRow)
360                {
361                   row = listBox.AddRow();
362                   row.SetData(null, 0);
363                   listBox.scroll.y = listBox.scrollArea.h;
364                }
365                else if(row.next == listBox.lastRow)
366                   listBox.scroll.y = listBox.scrollArea.h;
367             }
368             Modified();
369             return true;
370          }
371       };
372
373       int c;
374       DataRow r;
375       /*if(!this)
376          this = eInstance_New(_class);
377          */
378       if(this || !this)    // FIXME
379       {
380          Class type = class_data(type);
381          list.AddField({ type, editable = true });
382       }
383       for(c = 0; c < (this ? count : 0); c++)
384       {
385          r = list.AddRow();
386          r.SetData(null, ids[c]);
387       }
388       r = list.AddRow();
389       r.SetData(null, 0);
390       list.Create();
391       list.modifiedDocument = false;
392       return list;
393    }
394
395    bool OnSaveEdit(Window window, void * object)
396    {
397       ListBox list = (ListBox) window;
398       if(list.modifiedDocument)
399       {
400          DataRow r;
401          if(!this)
402             this = eInstance_New(_class);
403          Clear();
404          for(r = list.firstRow; r; r = r.next)
405          {
406             Id id = r.GetData(null);
407             if(id)
408                Add(id);         
409          }
410          return true;
411       }
412       return false;
413    }
414    
415    ~IdList()
416    {
417       delete ids;
418    }
419 }
420
421 static void FreeString(String string)
422 {
423    delete string;
424 }
425
426 public class StringList
427 {
428    StringBinaryTree strings
429    {  
430       CompareKey = (void *)BinaryTree::CompareString;
431       FreeKey = (void *)FreeString;
432    };
433
434    void Clear()
435    {
436       strings.Free();
437    }
438    
439    bool Includes(String string)
440    {
441       return strings.FindString(string) != null;
442    }
443
444    bool Add(String string)
445    {
446       BTNode node { key = (uint)CopyString(string) };
447       if(strings.Add(node))
448          return true;
449       else
450       {
451          FreeString((String)node.key);
452          delete node;
453       }
454       return false;
455    }
456
457    bool Delete(String string)
458    {
459       BTNode node = strings.FindString(string);
460       if(node)
461       {
462          strings.Delete(node);
463          return true;
464       }
465       return false;
466    }
467
468    void _OnUnserialize(IOChannel channel)
469    {
470       channel.Get(strings);
471    }
472    
473    void OnUnserialize(IOChannel channel)
474    {
475       this = eInstance_New(class(StringList));
476       _OnUnserialize(channel);
477    }
478
479    void OnSerialize(IOChannel channel)
480    {
481       channel.Put(strings);
482    }
483
484    int OnCompare(StringList b)
485    {
486       BTNode nodeA = strings.first, nodeB = b.strings.first;
487       for(; nodeA || nodeB; nodeA = nodeA ? nodeA.next : null, nodeB = nodeB ? nodeB.next : null)
488       {
489          int result;
490          if(nodeA && !nodeB) return 1;
491          else if(nodeB && !nodeA) return -1;
492          else
493          {
494             result = strcmp((char *)nodeA.key, (char *)nodeB.key);
495             if(result) return result;
496          }
497       }         
498       return 0;
499    }
500
501    Window OnEdit(DataBox dataBox, DataBox obsolete, int x, int y, int w, int h, void * userData)
502    {
503       ListBox list
504       {
505          dataBox,
506          borderStyle = 0,
507          alwaysEdit = true,
508          anchor = { 0, 0, 0, 0 };
509
510          bool OnKeyHit(Key key, unichar ch)
511          {
512             return (key == enter) ? false : ListBox::OnKeyHit(key, ch);
513          }
514          
515          bool DataBox::NotifyChanged(ListBox listBox, DataRow row)
516          {
517             String string = row.GetData(null);
518             if(!string || !string[0])
519             {
520                if(row.next)
521                {
522                   listBox.DeleteRow(row);
523                   listBox.firstChild.Activate();
524                }
525             }            
526             else
527             {
528                if(row == listBox.lastRow)
529                {
530                   row = listBox.AddRow();
531                   row.SetData(null, null);
532                   listBox.scroll.y = listBox.scrollArea.h;
533                }
534                else
535                {
536                   row = row.next;
537                   /*
538                   if(row.next == listBox.lastRow)
539                      listBox.scroll.y = listBox.scrollArea.h;
540                   */
541                }
542                listBox.SelectRow(row);
543             }
544             Modified();
545             return true;
546          }
547
548          bool DataBox::NotifyEdited(ListBox listBox, DataRow row)
549          {
550             listBox.firstChild.Activate();
551             return true;
552          }
553
554          bool DataBox::NotifyModified(ListBox listBox, DataRow row)
555          {
556             String string = row.GetData(null);
557             if(!string || !string[0])
558             {
559                if(row.next)
560                {
561                   listBox.DeleteRow(row);
562                   listBox.firstChild.Activate();
563                }
564             }            
565             else
566             {
567                if(row == listBox.lastRow)
568                {
569                   row = listBox.AddRow();
570                   row.SetData(null, null);
571                   listBox.scroll.y = listBox.scrollArea.h;
572                }
573                else if(row.next == listBox.lastRow)
574                   listBox.scroll.y = listBox.scrollArea.h;
575             }
576             Modified();
577             return true;
578          }
579       };
580
581       BTNode node;
582       DataRow r;
583       
584       /*
585       {
586          if(!this)
587             this = eInstance_New(_class);
588       }
589       */
590
591       if(this || !this)    // FIXME
592       {
593       list.AddField({ class(char *), editable = true });
594       }
595       for(node = strings.first; node; node = node.next)
596       {
597          r = list.AddRow();
598          r.SetData(null, (String)node.key);
599       }
600       r = list.AddRow();
601       r.SetData(null, null);
602       list.Create();
603       list.modifiedDocument = false;
604       return list;
605    }
606
607    bool OnSaveEdit(Window window, void * object)
608    {
609       ListBox list = (ListBox) window;
610       if(list.modifiedDocument)
611       {
612          
613          DataRow r;
614          if(list.activeChild)
615             ((DataBox)list.activeChild).SaveData();
616
617          if(!this)
618             this = eInstance_New(_class);
619
620          // TODO: Fix how to get the data box...
621          Clear();
622          for(r = list.firstRow; r; r = r.next)
623          {
624             String string = r.GetData(null);
625             if(string)
626             {
627                Add(string);
628             }
629          }
630          return true;
631       }
632       return false;
633    }
634    
635    ~StringList()
636    {
637       strings.Free();
638    }
639 }
640
641 public class FixedMultiLineString : String
642 {
643    Window OnEdit(DataBox dataBox, DataBox obsolete, int x, int y, int w, int h, void * userData)
644    {
645       // Don't show the editbox right away so that the text is highlighted by default
646       char * string = "";
647       EditBox editBox
648       {
649          dataBox, visible = false,
650          borderStyle = 0,
651          textHorzScroll = true,
652          modifyVirtualArea = false,
653          anchor = { 0, 0, 0, 0 };
654          multiLine = true;
655
656          void DataBox::NotifyUpdate(EditBox editBox)
657          {
658             Modified();          
659             modifiedDocument = true;
660          }
661       };
662       editBox.contents = this;
663       editBox.visible = true;
664
665       editBox.Create();
666       if(!dataBox.active)
667          editBox.contents = this;
668       return editBox;
669    }
670
671    bool OnSaveEdit(Window window, void * object)
672    {
673       bool changed = false;
674       EditBox editBox = (EditBox)window;
675       if(editBox.modifiedDocument)
676       {
677          EditLine line;
678          int size = 0;
679          char * string;
680
681          delete this;
682
683          for(line = editBox.firstLine; line; line = line.next)
684             size += line.count+1;
685          this = string = new char[size+1];
686          size = 0;
687          for(line = editBox.firstLine; line; line = line.next)
688          {
689             memcpy(string + size, line.text, line.count);
690             size += line.count;
691             string[size] = '\n';
692             size++;
693          }
694          string[size] = '\0';
695
696          changed = true;
697       }
698       return changed;
699    }
700 };
701
702 public class CIString : String
703 {
704    
705 }
706
707 public class MultiLineString : String
708 {
709    Window OnEdit(DataBox dataBox, DataBox obsolete, int x, int y, int w, int h, void * userData)
710    {
711       // Don't show the editbox right away so that the text is highlighted by default
712       char * string = "";
713       EditBox editBox
714       {
715          dataBox, visible = false,
716          borderStyle = 0,
717          hasHorzScroll = true, hasVertScroll = true,
718          modifyVirtualArea = false,
719          anchor = { 0, 0, 0, 0 };
720          multiLine = true;
721
722          void DataBox::NotifyUpdate(EditBox editBox)
723          {
724             Modified();
725             modifiedDocument = true;
726          }
727       };
728       editBox.contents = this;
729       editBox.visible = true;
730
731       editBox.Create();
732       if(!dataBox.active)
733          editBox.contents = this;
734       return editBox;
735    }
736
737    bool OnSaveEdit(Window window, void * object)
738    {
739       bool changed = false;
740       EditBox editBox = (EditBox)window;
741       if(editBox.modifiedDocument)
742       {
743          EditLine line;
744          int size = 0;
745          char * string;
746
747          delete this;
748
749          for(line = editBox.firstLine; line; line = line.next)
750             size += line.count+1;
751          this = string = new char[size+1];
752          size = 0;
753          for(line = editBox.firstLine; line; line = line.next)
754          {
755             memcpy(string + size, line.text, line.count);
756             size += line.count;
757             string[size] = '\n';
758             size++;
759          }
760          string[size] = '\0';
761
762          changed = true;
763       }
764       return changed;
765    }
766 };
767
768 public struct DataList : OldList
769 {
770    class_data Class type;
771    class_data char * typeName;
772    // class_property Class type { set { class_data(type) = value; } };
773    class_property char * type { set { class_data(typeName) = value; } };
774    class_property Class dataType { get { return class_data(type); } };
775
776    void OnUnserialize(IOChannel channel)
777    {
778       Class type;
779       if(!class_data(type))
780          class_data(type) = eSystem_FindClass(__thisModule.application, class_data(typeName));
781       type = class_data(type);
782       
783       this = { };
784
785       while(true)
786       {
787          bool truth;
788          OldLink link;
789          channel.Unserialize(truth);
790          if(!truth) break;
791          link = OldLink { };
792
793          if(type)
794          {
795             if(type.type == structClass)
796                link.data = new0 byte[type.structSize];
797             type._vTbl[__ecereVMethodID_class_OnUnserialize](type, (type.type == structClass) ? link.data : &link.data, channel);
798          }
799          Add(link);
800       }
801    }
802
803    void OnSerialize(IOChannel channel)
804    {
805       OldLink node = first;
806       Class type;
807       if(!class_data(type))
808          class_data(type) = eSystem_FindClass(__thisModule.application, class_data(typeName));
809       type = class_data(type);
810
811       while(true)
812       {
813          bool truth = true;
814          if(node)
815          {
816             channel.Serialize(truth);
817             if(type.type == bitClass || type.type == unitClass || (type.type == systemClass && type.typeSize))
818                type._vTbl[__ecereVMethodID_class_OnSerialize](type, &node.data, channel);
819             else
820                type._vTbl[__ecereVMethodID_class_OnSerialize](type, node.data, channel);
821             node = node.next;
822          }
823          else
824          {
825             truth = false;
826             channel.Serialize(truth);
827             node = null;
828          }
829          if(!node) break;
830       }
831    }
832
833    int OnCompare(DataList b)
834    {
835       OldLink nodeA = first, nodeB = b.first;
836       for(; nodeA || nodeB; nodeA = nodeA ? nodeA.next : null, nodeB = nodeB ? nodeB.next : null)
837       {
838          int result;
839          if(nodeA && !nodeB) return 1;
840          else if(nodeB && !nodeA) return -1;
841          else
842          {
843             Class type = class_data(type);
844             result = type._vTbl[__ecereVMethodID_class_OnCompare](type, 
845                (type.type == systemClass || type.type == bitClass || type.type == enumClass || type.type == unitClass) ? &nodeA.data : (void *)nodeA.data,
846                (type.type == systemClass || type.type == bitClass || type.type == enumClass || type.type == unitClass) ? &nodeB.data : (void *)nodeB.data);
847             if(result) return result;
848          }
849       }         
850       return 0;
851    }
852
853    Window OnEdit(DataBox dataBox, DataBox obsolete, int x, int y, int w, int h, void * userData)
854    {
855       ListBox list
856       {
857          dataBox,
858          borderStyle = 0,
859          alwaysEdit = true,
860          anchor = { 0, 0, 0, 0 };
861
862          bool OnKeyHit(Key key, unichar ch)
863          {
864             return (key == enter) ? false : ListBox::OnKeyHit(key, ch);
865          }
866          
867          bool DataBox::NotifyChanged(ListBox listBox, DataRow row)
868          {
869             Class type = ((subclass(DataList))this.type).dataType;
870             if(type.type == normalClass && !strcmp(type.dataTypeString, "char *"))
871             {
872                String string = row.GetData(null);
873                if(!string || !string[0])
874                {
875                   /*if(row.next)
876                   {
877                      listBox.DeleteRow(row);
878                      listBox.firstChild.Activate();
879                   }*/
880                }            
881                else
882                {
883                   if(row == listBox.lastRow)
884                   {
885                      /*row = listBox.AddRow();
886                      row.SetData(null, null);
887                      listBox.scroll.y = listBox.scrollArea.h;*/
888                   }
889                   else
890                   {
891                      row = row.next;
892                   }
893                   listBox.SelectRow(row);
894                }
895                //Modified();
896             }
897             return true;
898          }
899          /*
900          bool DataBox::NotifyModified(ListBox listBox, DataRow row)
901          {
902             Class type = ((subclass(DataList))this.type).dataType;
903             if(type.type == normalClass && !strcmp(type.dataTypeString, "char *"))
904             {
905                String string = row.GetData(null);
906                if(!string || !string[0])
907                {
908                   if(row.next)
909                   {
910                      listBox.DeleteRow(row);
911                      listBox.firstChild.Activate();
912                   }
913                }            
914                else
915                {
916                   if(row == listBox.lastRow)
917                   {
918                      row = listBox.AddRow();
919                      row.SetData(null, null);
920                      listBox.scroll.y = listBox.scrollArea.h;
921                   }
922                   else if(row.next == listBox.lastRow)
923                      listBox.scroll.y = listBox.scrollArea.h;
924                }
925                Modified();
926             }
927             return true;
928          }
929          */
930          bool DataBox::NotifyEditing(ListBox listBox, DataRow row)
931          {
932             Class type = ((subclass(DataList))this.type).dataType;
933             DataBox editData = (DataBox)listBox.firstChild;
934             // if(type.type != normalClass || strcmp(type.dataTypeString, "char *"))
935             {
936                if(type)
937                {
938                   if(type.type == normalClass && !*(void **)editData.data && strcmp(type.dataTypeString, "char *"))
939                   {
940                      *(void **)editData.data = eInstance_New(type);
941                      row.SetData(null, *(void **)editData.data);
942                   }
943                }
944
945                if(row == listBox.lastRow)
946                {
947                   listBox.alwaysEdit = false;
948                   if(type.type == normalClass || type.type == structClass || type.type == noHeadClass)
949                      listBox.AddRow().SetData(null, null);
950                   else
951                      listBox.AddRow().SetData(null, 0);
952                   listBox.scroll.y = listBox.scrollArea.h;
953                   listBox.alwaysEdit = true;
954                }
955             }            
956             return true;
957          }
958
959          bool DataBox::NotifyEdited(ListBox listBox, DataRow row)
960          {
961             listBox.firstChild.Activate();
962             return true;
963          }
964
965          bool DataBox::NotifyEditDone(ListBox listBox, DataRow row)
966          {
967             Class type = ((subclass(DataList))this.type).dataType;
968             // if(type.type != normalClass || strcmp(type.dataTypeString, "char *"))
969             if(type)
970             {
971                void * data = ((type.type == normalClass || type.type == noHeadClass || type.type == structClass) ? row.GetData(null) : *(uint *)row.GetData(null));
972                if(!data)
973                {
974                   //if(strcmp(type.dataTypeString, char *"))
975                      //listBox.currentRow = null;
976                   if(row != listBox.lastRow)
977                   {
978                      listBox.alwaysEdit = false;
979                      listBox.DeleteRow(row);
980                      listBox.alwaysEdit = true;
981                   }
982                }
983             }
984             Modified();
985             return true;
986          }
987    
988          void OnDestroy()
989          {
990             Class type = firstField.dataType;
991             // if(type.type != normalClass || strcmp(type.dataTypeString, "char *"))
992             if(type)
993             {
994                if(type.type == normalClass && strcmp(type.dataTypeString, "char *"))
995                   eInstance_Delete(lastRow.GetData(null));
996                if(type.type == normalClass || type.type == structClass || type.type == noHeadClass)
997                   lastRow.SetData(null, null);
998                else
999                   lastRow.SetData(null, 0);
1000             }
1001          }
1002       };
1003
1004       OldLink node;
1005       DataRow r;
1006       Class type;
1007       if(!class_data(type))
1008          class_data(type) = eSystem_FindClass(__thisModule.application, class_data(typeName));
1009       type = class_data(type);
1010       
1011       list.AddField({ type, editable = true });
1012       for(node = first; node; node = node.next)
1013       {
1014          r = list.AddRow();
1015          if(type)
1016          {
1017             if(type.type == normalClass && !strcmp(type.dataTypeString, "char *"))
1018                r.SetData(null, CopyString((String)node.data));
1019             else
1020                r.SetData(null, node.data);
1021          }
1022       }
1023       r = list.AddRow();
1024       if(type.type == normalClass || type.type == structClass || type.type == noHeadClass)
1025          r.SetData(null, null);
1026       else
1027          r.SetData(null, 0);
1028       list.Create();
1029       list.modifiedDocument = false;
1030       return list;
1031    }
1032
1033    bool OnSaveEdit(Window window, void * object)
1034    {
1035       ListBox list = (ListBox) window;
1036       if(list.modifiedDocument)
1037       {
1038          Class type = class_data(type);
1039          DataRow r;
1040          if(list.activeChild)
1041             ((DataBox)list.activeChild).SaveData();
1042
1043          if(type.type != normalClass || !strcmp(type.dataTypeString, "char *"))
1044             OnFree();
1045          else if(type.type == structClass)
1046             Free(OldLink::Free);
1047          else
1048             Free(null);
1049
1050          for(r = list.firstRow; r; r = r.next)
1051          {
1052             if(type.type == noHeadClass || type.type == normalClass || type.type == structClass)
1053             {
1054                void * data = r.GetData(null);
1055                if(data)
1056                {
1057                   if(type.type == normalClass && !strcmp(type.dataTypeString, "char *"))
1058                      Add(OldLink { data = CopyString(data) });
1059                   else if(type.type == structClass)
1060                   {
1061                      OldLink link { data = new byte[type.structSize] };
1062                      Add(link);
1063                      memcpy(link.data, data, type.structSize);
1064                   }
1065                   else
1066                      Add(OldLink { data = data });
1067                }
1068             }
1069             else
1070             {
1071                uint i = r.GetData(null);
1072                if(i)
1073                   Add(OldLink { data = (void *)i });
1074             }
1075          }
1076          return true;
1077       }
1078       return false;
1079    }
1080
1081    void OnFree()
1082    {  
1083       Class type;
1084       OldLink node;
1085
1086       if(!class_data(type))
1087          class_data(type) = eSystem_FindClass(__thisModule.application, class_data(typeName));
1088       type = class_data(type);
1089       while(node = first)
1090       {
1091          // TO STUDY: ONFREE SHOULD BE USED ONLY FOR LISTBOX?
1092          if(type)
1093          {
1094             if(type.type == normalClass && strcmp(type.dataTypeString, "char *"))
1095                eInstance_Delete(node.data);
1096             else if(type.type == structClass)
1097                delete node.data;
1098             else
1099                type._vTbl[__ecereVMethodID_class_OnFree](type, node.data);
1100          }
1101          Delete(node);
1102       }
1103    }
1104 };