ecere/gui/drivers/X: Native Decorations Tweaks for Linux (Decorations size awareness...
[sdk] / ecere / src / gui / Window.ec
1 namespace gui;
2
3 import "Display"
4
5 import "Anchor"
6 import "Key"
7 import "GuiApplication"
8 import "Interface"
9 import "Skin"
10 import "Timer"
11 import "Cursor"
12 import "ClipBoard"
13
14 import "Button"
15 import "ListBox"
16 import "DropBox"
17 import "Label"
18 import "Picture"
19 import "ScrollBar"
20 import "Button"
21 import "Menu"
22 import "StatusBar"
23 import "ProgressBar"
24 import "EditBox"
25 import "DataBox"
26 import "ToolTip"
27
28 #if !defined(ECERE_VANILLA) && !defined(ECERE_NO3D)
29 import "Desktop3D"
30 #endif
31
32 #if !defined(ECERE_VANILLA) && !defined(ECERE_NOTRUETYPE)
33 import "FormDesigner"
34 #endif
35
36 import "FileDialog"
37 import "MessageBox"
38 import "WindowList"
39 import "i18n"
40
41 // Had to define this here for native decorations support, because the menu bar is part of total decoration's size, but not part of the system decorations
42 define skinMenuHeight = 25;
43 define statusBarHeight = 18;
44
45 default extern int __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown;
46
47 public enum DialogResult { cancel, yes, no, ok };
48
49 public class MouseButtons
50 {
51 public:
52    bool left:1, right:1, middle:1;
53 };
54
55 public struct SizeAnchor
56 {
57    Size size;
58    bool isClientW, isClientH;
59 };
60
61 #include <stdarg.h>
62
63 #define SNAPDOWN(x, d) \
64       if(Abs(x) % (d)) \
65       { \
66          if(x < 0) x -= ((d) - Abs(x) % (d)); else x -= x % (d); \
67       }
68
69 #define SNAPUP(x, d) \
70       if(Abs(x) % (d)) \
71       { \
72          if(x > 0) x += ((d) - Abs(x) % (d)); else x += x % (d); \
73       }
74
75 /*static */define MAX_DIRTY_BACK = 10;
76
77 /////////////////////////////////////////////////////////////////////////////
78 ////////// EXTENT MANIPULATION //////////////////////////////////////////////
79 /////////////////////////////////////////////////////////////////////////////
80
81 #define ACCESS_ITEM(l, id) \
82    id
83
84 #define FASTLIST_LOOP(l, v)      \
85    for(v = (BoxItem)l.first; v; v = (BoxItem)v.next)
86
87 #define FASTLIST_LOOPN(l, v, n) \
88    for(v = (BoxItem)l.first, n = (BoxItem)(v ? v.next : null); v; v = (BoxItem)next, n = (BoxItem)(v ? v.next : null))
89
90 /*
91 #define ACCESS_ITEM(l, id) \
92       ((FastItem)(((id) == -1) ? null : (((byte *)((l).items)) + (id) * (l).itemSize)))
93
94 #define FASTLIST_LOOP(l, v)      \
95    for(v = (void *)ACCESS_ITEM((l), (l).first); v; v = (void *)ACCESS_ITEM((l), v.next))
96
97 #define FASTLIST_LOOPN(l, v, n) \
98    for( v = (void *)ACCESS_ITEM((l), (l).first), \
99         n = v ? ((void *)ACCESS_ITEM((l), v.next)): null; \
100         v; v = n, n = n ? (void *)ACCESS_ITEM((l), n.next) : null)
101
102
103 private class FastItem : struct
104 {
105    int prev, next;
106 };
107
108 private struct FastList
109 {
110    FastItem items;
111    int first, last;
112    int free;
113    int count, size, itemSize;
114
115    void Clear(void)
116    {
117       count = 0;
118       size = 0;
119       items = null;
120       first = last = free = -1;
121       itemSize = 0;
122    }
123
124    void Empty(void)
125    {
126       FastItem item, next;
127       Free();
128       // FASTLIST_LOOPN(this, item, next) { Delete(item); };
129    }
130
131    FastItem Add(uint itemSize)
132    {
133       FastItem item;
134       if(free == -1 || !size)
135       {
136          int c;
137          int newSize;
138                
139          if(size)
140          {
141             newSize = (size + (size >> 1));
142             items = (FastItem)renew items byte[newSize * itemSize];
143          }
144          else
145          {
146             newSize = 4;
147             this.itemSize = itemSize;
148             items = (FastItem)new byte[newSize * itemSize];
149          }
150
151          for(c = size; c<newSize-1; c++)
152          {
153             ACCESS_ITEM(this, c).prev = -1;
154             ACCESS_ITEM(this, c).next = c+1;
155          }
156          ACCESS_ITEM(this, c).prev = -1;
157          ACCESS_ITEM(this, c).next = -1;
158          free = size;
159          size = newSize;
160       }
161       item = ACCESS_ITEM(this, free);
162       item.prev = last;
163       if(item.prev != -1)
164          ACCESS_ITEM(this, item.prev).next = free;
165       if(first == -1)
166          first = free;
167       last = free;
168       free = item.next;
169       item.next = -1;
170       count++;
171       return item;
172    }
173
174    void Delete(FastItem item)
175    {
176       if(item.prev != -1)
177          ACCESS_ITEM(this, item.prev).next = item.next;
178       if(item.next != -1)
179          ACCESS_ITEM(this, item.next).prev = item.prev;
180
181       if(ACCESS_ITEM(this, first) == item)
182          first = item.next;
183       if(ACCESS_ITEM(this, last) == item)
184          last = item.prev;
185       count--;
186
187       item.next = free;
188       free = ((byte *)item - (byte *)items) / itemSize;
189    }
190
191    void Free(void)
192    {
193       delete items;
194       size = 0;
195       count = 0;
196       free = first = last = -1;
197    }
198 };
199 */
200 private class BoxItem : Item //FastItem
201 {
202    Box box;
203 };
204
205 public /*private */struct Extent : OldList //FastList
206 {
207    void Empty()
208    {
209       Free(null);
210    }
211
212    void AddBox(Box box)
213    {
214       //BoxItem extentBox = (BoxItem)Add(sizeof(class BoxItem));
215       Add(BoxItem { box = box });
216    }
217
218    void Copy(Extent source)
219    {
220       BoxItem extentBox;
221
222       // Clear();
223       Empty();
224       //FASTLIST_LOOP(source, extentBox)
225       for(extentBox = (BoxItem)source.first; extentBox; extentBox = (BoxItem)extentBox.next)
226          AddBox(extentBox.box);
227    }
228
229    void IntersectBox(Box box)
230    {
231       // Clip all boxes of extent against inside of the new box
232       BoxItem extentBox, next;
233
234       //FASTLIST_LOOPN(this, extentBox, next)   // Macros still mess up the parser!
235       for(extentBox = (BoxItem)this.first; extentBox; extentBox = next)
236       {
237          next = (BoxItem)extentBox.next;
238          if(box.left > extentBox.box.left) extentBox.box.left = box.left;
239          if(box.top > extentBox.box.top) extentBox.box.top = box.top;
240          if(box.right < extentBox.box.right) extentBox.box.right = box.right;
241          if(box.bottom < extentBox.box.bottom) extentBox.box.bottom = box.bottom;
242          if(extentBox.box.right < extentBox.box.left || extentBox.box.bottom < extentBox.box.top)
243             Delete(extentBox);
244       }
245    }
246
247    void ExcludeBox(Box box, Extent temp)
248    {
249       BoxItem extentBox;
250
251       temp.Copy(this);
252       Empty();
253       
254       for(extentBox = (BoxItem)temp.first; extentBox; extentBox = (BoxItem)extentBox.next)
255       {
256          if(extentBox.box.left < box.right && extentBox.box.right > box.left && 
257             extentBox.box.top < box.bottom && extentBox.box.bottom > box.top)
258          {
259             // Top box
260             if(extentBox.box.top < box.top && extentBox.box.bottom >= box.top)
261             {
262                Box newBox
263                {
264                   extentBox.box.left, extentBox.box.top, 
265                   extentBox.box.right, Min(extentBox.box.bottom, box.top -1)
266                };
267                AddBox(newBox);
268             }
269
270             // Bottom box
271             if(extentBox.box.bottom > box.bottom && extentBox.box.top <= box.bottom)
272             {
273                Box newBox
274                {
275                   extentBox.box.left, Max(extentBox.box.top,box.bottom +1),
276                   extentBox.box.right, extentBox.box.bottom
277                };
278                AddBox(newBox);
279             }
280
281             // Middle boxes
282             if(extentBox.box.bottom >= box.top && extentBox.box.top <= box.bottom)
283             {
284                // Left box
285                if(extentBox.box.left < box.left && extentBox.box.right >= box.left)
286                {
287                   Box newBox
288                   {
289                      extentBox.box.left, Max(extentBox.box.top, box.top),
290                      Min(extentBox.box.right, box.left-1), Min(extentBox.box.bottom, box.bottom)
291                   };
292                   AddBox(newBox);
293                }
294
295                // Right box
296                if(extentBox.box.right > box.right && extentBox.box.left <= box.right)
297                {
298                   Box newBox
299                   {
300                      Max(extentBox.box.left, box.right+1), Max(extentBox.box.top, box.top),
301                      extentBox.box.right, Min(extentBox.box.bottom, box.bottom)
302                   };
303                   AddBox(newBox);
304                }
305             }
306          }
307          else
308          {
309             AddBox(extentBox.box);
310          }
311       }
312       temp.Empty();
313    }
314
315    void UnionBox(Box box, Extent temp)
316    {
317       BoxItem extentBox, next;
318
319       // First pass: check if this box is not already covered by one of the extent's box
320       for(extentBox = (BoxItem)this.first; extentBox; extentBox = (BoxItem)extentBox.next)
321       {
322          if(extentBox.box.left <= box.left && extentBox.box.right >= box.right && 
323             extentBox.box.top <= box.top && extentBox.box.bottom >= box.bottom)
324          {
325             // No change
326             return;
327          }
328       }
329         
330       // Second pass: only keep boxes not completely covered in the new box
331       for(extentBox = (BoxItem)this.first; extentBox; extentBox = next)
332       {
333          next = (BoxItem)extentBox.next;
334          if(extentBox.box.left >= box.left && extentBox.box.right <= box.right &&
335             extentBox.box.top >= box.top && extentBox.box.bottom <= box.bottom)
336             Delete(extentBox);
337       }
338
339       // Add the exclusion to the extent
340       ExcludeBox(box, temp);
341
342       // Add the new box
343       if(box.bottom >= box.top && box.right >= box.left)
344       {
345          // Optimization: if the resulting boxes touch, add them smarter
346          for(extentBox = (BoxItem)this.first; extentBox; extentBox = (BoxItem)extentBox.next)
347          {
348             if(box.top == extentBox.box.top && box.bottom == extentBox.box.bottom)
349             {
350                if(Abs(box.right - extentBox.box.left) <= 1)
351                {
352                   extentBox.box.left = box.left;
353                   break;
354                }
355                else if(Abs(box.left - extentBox.box.right) <= 1)
356                {
357                   extentBox.box.right = box.right;
358                   break;
359                }
360             }
361             else if(box.left == extentBox.box.left && box.right == extentBox.box.right)
362             {
363                if(Abs(box.bottom - extentBox.box.top) <= 1)
364                {
365                   extentBox.box.top = box.top;
366                   break;
367                }
368                else if(Abs(box.top - extentBox.box.bottom) <= 1)
369                {
370                   extentBox.box.bottom = box.bottom;
371                   break;
372                }
373             }
374          }
375          
376          // Else, add it
377          if(!extentBox)
378             AddBox(box);
379       }
380    }
381
382    void Union(Extent b, Extent temp)
383    {
384       BoxItem extentBox;
385
386       for(extentBox = (BoxItem)b.first; extentBox; extentBox = (BoxItem)extentBox.next)
387          UnionBox(extentBox.box, temp);
388    }
389
390    void Intersection(Extent b, Extent temp, Extent temp2, Extent temp3)
391    {
392       BoxItem extentBox;
393       temp.Copy(this);
394
395       Empty();
396
397       for(extentBox = (BoxItem)b.first; extentBox; extentBox = (BoxItem)extentBox.next)
398       {
399          temp2.Copy(temp);
400          temp2.IntersectBox(extentBox.box);
401          Union(temp2, temp3);
402          temp2.Empty();
403       }
404       temp.Empty();
405    }
406
407    void Exclusion(Extent b, Extent temp)
408    {
409       BoxItem extentBox;   
410       for(extentBox = (BoxItem)b.first; extentBox; extentBox = (BoxItem)extentBox.next)
411          ExcludeBox(extentBox.box, temp);
412    }
413
414    void Offset(int x, int y)
415    {
416       BoxItem extentBox;
417       for(extentBox = (BoxItem)this.first; extentBox; extentBox = (BoxItem)extentBox.next)
418       {
419          extentBox.box.left += x;
420          extentBox.box.top += y;
421          extentBox.box.right += x;
422          extentBox.box.bottom += y;
423       }
424    }
425 };
426
427 private define MINIMIZED_WIDTH = 160;
428 private define CASCADE_SPACE = 16;
429
430 // namespace Windows;
431
432 private class ScrollFlags
433 {
434    bool snapX:1, snapY:1, dontHide:1;   
435 };
436
437 public class BorderBits { public: bool contour:1, fixed:1, sizable:1, deep:1, bevel:1, thin:1; };
438
439 class WindowBits : BorderBits
440 {
441    BorderBits borderBits:6:0;
442    bool hidden:1, isActiveClient:1, hasHorzScroll:1, hasVertScroll:1, stayOnTop:1, modal:1, isDefault:1, inactive:1, isRemote:1, drawBehind:1;
443    bool interim:1, tabCycle:1, noCycle:1, dontScrollHorz:1, dontScrollVert:1, hasMaximize:1, hasMinimize:1, hasClose:1;
444    bool embedded:1, hasMenuBar:1, isDocument:1, showInTaskBar:1, hasStatusBar:1, nonClient:1, clickThrough:1;
445 };
446
447 public enum BorderStyle : BorderBits
448 {
449    none,
450    contour      = BorderBits { contour = true },
451    fixed        = BorderBits { fixed = true } | contour,
452    sizable      = BorderBits { sizable = true } | fixed,
453    thin         = BorderBits { fixed = true, thin = true } | contour,
454    sizableThin  = BorderBits { sizable = true } | thin,
455    deep         = BorderBits { deep = true },
456    bevel        = BorderBits { bevel = true },
457    sizableDeep  = sizable|deep,
458    sizableBevel = sizable|bevel,
459    fixedDeep    = fixed|deep,
460    fixedBevel   = fixed|bevel,
461    deepContour  = deep|contour
462 };
463
464 public enum CreationActivationOption
465 {
466    activate, flash, doNothing
467 };
468
469 public enum WindowState { normal, minimized, maximized };
470
471 private class ResPtr : struct
472 {
473    ResPtr prev, next;
474    Resource resource;
475    void * loaded;
476 };
477
478 private class HotKeySlot : struct
479 {
480    HotKeySlot prev, next;
481    Window window;
482    Key key;
483 };
484
485 public class Window
486 {
487 private:
488    class_data char * icon;
489    class_no_expansion
490    class_default_property text;
491    // class_initialize GuiApplication::Initialize;
492    class_designer FormDesigner;
493    class_property char * icon
494    {
495       set { class_data(icon) = value; }
496       get { return class_data(icon); }
497    }
498
499    Window()
500    {
501       if(guiApp) guiApp.Initialize(true);
502
503       if(guiApp && guiApp.currentSkin && ((subclass(Window))_class).pureVTbl)
504       {
505          if(_vTbl == ((subclass(Window))_class).pureVTbl)
506          {
507             _vTbl = _class._vTbl;
508          }
509          else if(_vTbl != _class._vTbl)
510          {
511             int m;
512             for(m = 0; m < _class.vTblSize; m++)
513             {
514                if(_vTbl[m] == ((subclass(Window))_class).pureVTbl[m])
515                   _vTbl[m] = _class._vTbl[m];
516             }
517          }
518       }
519       
520       //tempExtents[0] = { /*first = -1, last = -1, free = -1*/ };
521       //tempExtents[1] = { /*first = -1, last = -1, free = -1*/ };
522       //tempExtents[2] = { /*first = -1, last = -1, free = -1*/ };
523       //tempExtents[3] = { /*first = -1, last = -1, free = -1*/ };
524
525       setVisible = true;
526
527       // caption = CopyString(class.name);
528
529       children.offset = (byte*)&prev - (byte*)this;
530       childrenOrder.circ = true;
531       childrenCycle.circ = true;
532
533       maxSize = Size { MAXINT, MAXINT };
534       background = white;
535       foreground = black;
536       
537       //style.isActiveClient = true;
538       mergeMenus = true;
539       autoCreate = true;
540       modifyVirtArea = true;
541       manageDisplay = true;
542
543       // scrollFlags = ScrollFlags { snapX = true, snapY = true };
544       sbStep.x = sbStep.y = 8;
545
546       if(guiApp)  // dynamic_cast<GuiApplication>(thisModule)
547       {
548          cursor = guiApp.GetCursor(arrow);
549          property::parent = guiApp.desktop;
550       }
551    }
552
553    ~Window()
554    {
555       Window child;
556       OldLink slave;
557       ResPtr ptr;
558
559       if(parent)
560       {
561          stopwatching(parent, font);
562          if(parent.activeChild == this)
563             parent.activeChild = null;
564          if(parent.activeClient == this)
565             parent.activeClient = null;
566       }
567
568       if(!destroyed)
569       { 
570          // Prevent destructor from being called again...
571          incref this;
572          incref this;
573          DestroyEx(0);
574       }
575
576       /////////////////////////////////
577       if(master)
578       {
579          OldLink slave = master.slaves.FindLink(this);
580          master.slaves.Delete(slave);
581          master = null;
582       }
583
584       if(parent)
585       {
586          if(cycle)
587             parent.childrenCycle.Remove(cycle);
588          if(order)
589             parent.childrenOrder.Remove(order);
590          parent.children.Remove(this);
591          parent = null;
592       }
593       delete cycle;
594       delete order;
595       /////////////////////////////////
596
597       while(ptr = resources.first)
598       {
599          delete ptr.resource;
600          resources.Delete(ptr);
601       }
602
603       usedFont = null;
604       delete setFont;
605       delete systemFont;
606
607       for(child = children.first; child; child = child.next)
608       {
609          // child.stopwatching(this, font);
610          if(child.parent)
611             eInstance_StopWatching(this, __ecereProp___ecereNameSpace__ecere__gui__Window_font, child);
612          // Don't want property here
613          *&child.parent = null;
614       }
615
616       while(slave = slaves.first)
617       {
618          // Don't want property here
619          *&((Window)slave.data).master = null;
620          slaves.Delete(slave);
621       }
622
623       // Because we do a decref in DestroyEx...
624       if(!destroyed)
625       {
626          incref this;
627          incref this;
628          DestroyEx(0);
629       }
630
631       // Why was this commented?
632       //if(this != guiApp.desktop)
633       {
634          delete caption;
635          delete fileName;
636       }
637
638       delete menu;
639       delete statusBar;
640
641       OnDestroyed();
642       delete mutex;
643       delete icon;
644
645       if(((subclass(Window))_class).pureVTbl)
646       {
647          if(_vTbl == _class._vTbl)
648          {
649             _vTbl = ((subclass(Window))_class).pureVTbl;
650          }
651          else
652          {
653             int m;
654             for(m = 0; m < _class.vTblSize; m++)
655             {
656                if(_vTbl[m] == _class._vTbl[m])
657                   _vTbl[m] = ((subclass(Window))_class).pureVTbl[m];
658             }
659          }
660       }
661       if(_vTbl == ((subclass(Window))_class).pureVTbl || _vTbl == _class._vTbl)
662          _vTbl = null;
663
664       dirtyArea.Free(null);
665       renderArea.Free(null);
666       overRenderArea.Free(null);
667       clipExtent.Free(null);
668       scrollExtent.Free(null);
669       dirtyBack.Free(null);
670
671       if(tempExtents)
672       {
673          tempExtents[0].Free(null);
674          tempExtents[1].Free(null);
675          tempExtents[2].Free(null);
676          tempExtents[3].Free(null);
677          delete tempExtents;
678       }
679    }
680
681 //#if !defined(ECERE_VANILLA)
682    char * OnGetString(char * stringOutput, void * fieldData, bool * needClass)
683    {
684       if(this == activeDesigner)
685          return "(Desktop)";
686       else 
687       {
688          char * name = property::name;
689          return name ? name : "";
690       }
691    }
692 //#endif
693
694 #if !defined(ECERE_VANILLA) && !defined(ECERE_NOTRUETYPE)
695    bool OnGetDataFromString(char * string)
696    {
697       FormDesigner designer = (FormDesigner)activeDesigner.classDesigner;
698       if(string[0])
699       {
700          if(!strcmp(string, "this") || !strcmp(string, designer.form.name))
701             this = designer.form;
702          else if(!strcmpi(string, "(Desktop)"))
703             this = activeDesigner;
704          else
705             return activeDesigner.FindObject(&this, string);
706       }
707       return true;
708    }
709 #endif
710
711    // --- Window updates system ---
712
713    // Setup a bitmap for Redrawing on client area of Window
714    Surface Redraw(Box box)
715    {
716       Surface surface = null;
717       Box mox = box;
718       Box clientArea = this.clientArea;
719
720       SetBox(clientArea);
721
722       mox.left   -= clientStart.x;
723       mox.top    -= clientStart.y;
724       mox.right  -= clientStart.x;
725       mox.bottom -= clientStart.y;
726
727       mox.Clip(clientArea);
728       // mox.ClipOffset(against, scrolledPos.x, scrolledPos.y);
729
730       if((!guiApp.fullScreenMode || guiApp.desktop.active) && display && mox.right >= mox.left && mox.bottom >= mox.top)
731       {
732          int x = absPosition.x + clientStart.x;
733          int y = absPosition.y + clientStart.y;
734          if(rootWindow.nativeDecorations)
735          {
736             x -= rootWindow.clientStart.x;
737             y -= rootWindow.clientStart.y - (rootWindow.hasMenuBar ? skinMenuHeight : 0);
738          }
739          if(!guiApp.fullScreenMode || is3D)
740          {
741             x -= rootWindow.absPosition.x;
742             y -= rootWindow.absPosition.y;
743
744             if(rootWindow.is3D)
745             {
746                x += rootWindow.parent.clientStart.x;
747                y += rootWindow.parent.clientStart.y;
748                /*
749                mox.left += rootWindow.parent.clientStart.x;
750                mox.top += rootWindow.parent.clientStart.y;
751                mox.right += rootWindow.parent.clientStart.x;
752                mox.bottom += rootWindow.parent.clientStart.y;
753                */
754             }
755          }
756
757          surface = display.GetSurface(x, y, mox);
758          /*if(surface)
759          {
760             surface.width = clientSize.w;
761             surface.height = clientSize.h;
762          }*/
763       }
764       return surface;
765    }
766
767    // Setup a bitmap for Redrawing on full Window
768    Surface RedrawFull(Box box)
769    {
770       Surface surface = null;
771       Box mox;
772       if(box != null)
773          box.Clip(this.box);
774       else
775          box = &this.box;
776       mox = box;
777
778       if((!guiApp.fullScreenMode || guiApp.desktop.active) && display && box.right >= box.left && box.bottom >= box.top)
779       {
780          int x = absPosition.x;
781          int y = absPosition.y;
782          if(rootWindow.nativeDecorations)
783          {
784             x -= rootWindow.clientStart.x;
785             y -= rootWindow.clientStart.y - (rootWindow.hasMenuBar ? skinMenuHeight : 0);
786          }
787          if(!guiApp.fullScreenMode || is3D)
788          {
789             x -= rootWindow.absPosition.x;
790             y -= rootWindow.absPosition.y;
791             if(rootWindow.is3D)
792             {
793                x += rootWindow.parent.clientStart.x;
794                y += rootWindow.parent.clientStart.y;
795                /*
796                mox.left += rootWindow.parent.clientStart.x;
797                mox.top += rootWindow.parent.clientStart.y;
798                mox.right += rootWindow.parent.clientStart.x;
799                mox.bottom += rootWindow.parent.clientStart.y;
800                */
801             }
802          }
803
804          surface = display.GetSurface(x, y, mox);
805          /*if(surface)
806          {
807             surface.width = size.w;
808             surface.height = size.h;
809          }*/
810       }
811       return surface;
812    }
813
814    void FigureCaption(char * caption)
815    {
816       caption[0] = '\0';
817       if(this.caption)
818          strcpy(caption, this.caption);
819       if(style.isDocument || fileName)
820       {
821          if(caption[0]) strcat(caption, " - ");
822          if(fileName)
823             strcat(caption, fileName);
824          else
825          {
826             char title[256];
827             sprintf(title, "Untitled %d", documentID);
828             strcat(caption, title);
829          }
830          if(modifiedDocument)
831             strcat(caption, " *");
832       }
833       if(activeClient && menuBar && 
834          activeClient.state == maximized)
835       {
836          if(activeClient.caption)
837          {
838             if(caption[0]) strcat(caption, " - ");
839             strcat(caption, activeClient.caption);
840          }
841          if(activeClient.style.isDocument || activeClient.fileName)
842          {
843             if(caption[0]) strcat(caption, " - ");
844             strcat(caption, "[");
845             if(activeClient.fileName)
846                strcat(caption, activeClient.fileName);
847             else
848             {
849                char title[256];
850                sprintf(title, "Untitled %d", activeClient.documentID);
851                strcat(caption, title);
852             }
853             if(activeClient.modifiedDocument)
854                strcat(caption, " *");
855             strcat(caption, "]");
856          }
857       }
858    }
859
860    // Code for returning dirty from ScrollDisplay:
861       /*
862       for(d = 0; d<scrollExtent.count; d++)
863       {
864          Box * box = &scrollExtent.boxes[d];
865          if(scroll.x < 0)
866          {
867             Box update
868             {
869                box.left, box.top,
870                Min(box.right, box.left-scroll.x),box.bottom
871             };
872             dirtyArea.UnionBox(update);
873          }
874          else if(scroll.x)
875          {
876             Box update
877             {
878                Max(box.left, box.right-scroll.x), box.top,
879                box.right, box.bottom
880             };
881             dirtyArea.UnionBox(update);
882          }
883
884          if(scroll.y < 0)
885          {
886             Box update
887             {
888                box.left, box.top,
889                box.right, Min(box.bottom, box.top-scroll.y),
890             };
891             dirtyArea.UnionBox(update);
892          }
893          else if(scroll.y)
894          {
895             Box update
896             {
897                box.left, Max(box.top, box.bottom-scroll.y),
898                box.right, box.bottom
899             };
900             dirtyArea.UnionBox(update);
901          }
902       }
903       */
904
905    void UpdateDecorations(void)
906    {
907       // TODO: *** TEMPORARY HACK ***
908       /*
909       if(parent)
910          parent.Update(null);
911       */
912
913       // Top
914       Update({ -clientStart.x, -clientStart.y, -clientStart.x + size.w-1, 0 });
915       // Bottom
916       Update({ -clientStart.x, clientSize.h, -clientStart.x + size.w-1, -clientStart.y + size.h-1 });
917       // Left
918       Update({ -clientStart.x,0, -1, clientSize.h-1 });
919       // Right
920       Update({ clientSize.w, 0, -clientStart.x + size.w-1, clientSize.h-1 });
921    }
922
923    // Returns w & h for Position
924    void ComputeAnchors(Anchor anchor, SizeAnchor sizeAnchor, int *ox, int *oy, int *ow, int *oh)
925    {
926       Window parent = this.parent ? this.parent : guiApp.desktop;
927       int vpw = parent ? parent.clientSize.w : 0;
928       int vph = parent ? parent.clientSize.h : 0;
929       int pw = parent ? parent.clientSize.w : 0;
930       int ph = parent ? parent.clientSize.h : 0;
931       int w = sizeAnchor.size.w, h = sizeAnchor.size.h;
932       int x = anchor.left.distance, y = anchor.top.distance;
933       float ex, ey;
934       MinMaxValue ew = 0, eh = 0;
935       int numCascade;
936       float cascadeW, cascadeH;
937       int numTiling;
938       int tilingW, tilingH, tilingSplit, tilingLastH;
939       int addX = 0, addY = 0;
940
941       if(parent && rootWindow == this && guiApp && guiApp.interfaceDriver)
942       {
943          Window masterWindow = this;
944          Box box { addX, addY, addX + vpw - 1, addY + vph - 1 };
945          if(!visible)
946          {
947             if(master == guiApp.desktop)
948                masterWindow = guiApp.desktop.activeChild;
949             else
950                masterWindow = master.rootWindow;
951             if(!masterWindow) masterWindow = this;
952          }
953          guiApp.interfaceDriver.GetScreenArea(masterWindow, box);
954          if((anchor.left.type == offset && anchor.right.type == offset) || anchor.left.type == none)
955          {
956             addX = box.left;
957             pw = vpw = box.right - box.left + 1;
958          }
959          if((anchor.top.type == offset && anchor.bottom.type == offset) || anchor.top.type == none)
960          {
961             addY = box.top;
962             ph = vph = box.bottom - box.top + 1;
963          }
964       }
965       
966       if(!parent)
967       {
968          *ow = w;
969          *oh = h;
970
971          *ox = x;
972          *oy = y;
973          return;
974       }
975
976       if(style.nonClient)
977       {
978          vpw = pw = parent.size.w;
979          vph = ph = parent.size.h;
980       }
981       else if(!style.fixed /*|| style.isDocument*/)
982       {
983          if(!style.dontScrollHorz && parent.scrollArea.w) vpw = parent.scrollArea.w;
984          if(!style.dontScrollVert && parent.scrollArea.h) vph = parent.scrollArea.h;
985       }
986 #if !defined(ECERE_NO3D) && !defined(ECERE_VANILLA)
987       if(is3D)
988       {
989          Desktop3D_FixSize(&pw, &ph);
990          Desktop3D_FixSize(&vpw, &vph);
991       }
992 #endif
993       if(pw < skinMinSize.w) pw = skinMinSize.w;
994       if(ph < skinMinSize.h) ph = skinMinSize.h;
995       if(vpw < skinMinSize.w) vpw = skinMinSize.w;
996       if(vph < skinMinSize.h) vph = skinMinSize.h;
997
998       // TODO: Must fix what we're snapping
999       if(guiApp.textMode)
1000       {
1001          if(anchor.left.type)
1002          {
1003             SNAPUP(x, textCellW);
1004          }
1005          else if(anchor.right.type)
1006          {
1007             SNAPDOWN(x, textCellW);
1008          }
1009
1010          if(anchor.top.type)
1011          {
1012             SNAPUP(y, textCellH);   
1013          }
1014          else if(anchor.bottom.type)
1015          {
1016             SNAPDOWN(y, textCellH);
1017          }
1018       }
1019
1020       // This is required to get proper initial decoration size using native decorations on Windows
1021       if(nativeDecorations && guiApp && guiApp.interfaceDriver && !visible)
1022          guiApp.interfaceDriver.PositionRootWindow(this, x, y, Max(1, size.w), Max(1, size.h), true, true);
1023       GetDecorationsSize(&ew, &eh);
1024
1025       if(anchor.left.type >= cascade && (state == normal /*|| state == Hidden*/))
1026       {
1027          if(parent.sbv && !parent.sbv.style.hidden) 
1028             pw += guiApp.currentSkin.VerticalSBW();
1029          if(parent.sbh && !parent.sbh.style.hidden)
1030             ph += guiApp.currentSkin.HorizontalSBH();
1031
1032          if(anchor.left.type == cascade)
1033          {
1034             w = (int)(pw * 0.80);
1035             h = (int)(ph * 0.80);
1036          }
1037          else if(anchor.left.type >= vTiled)
1038          {
1039             int leftOver;
1040             int x2, y2;
1041
1042             numTiling = parent.numPositions - parent.numIcons;
1043             if(parent.numIcons) ph -= guiApp.textMode ? 16 : 24;
1044             if(anchor.left.type == vTiled)
1045             {
1046                tilingH = (int)sqrt(numTiling);
1047                tilingW = numTiling / tilingH;
1048             }
1049             else
1050             {
1051                tilingW = (int)sqrt(numTiling);
1052                tilingH = numTiling / tilingW;
1053             }
1054
1055             leftOver = numTiling - tilingH * tilingW;
1056             if(leftOver)
1057             {
1058                tilingSplit = (tilingW - leftOver) * tilingH;
1059                tilingLastH = tilingH+1;
1060             }
1061             else
1062                tilingSplit = numTiling;
1063
1064             if(positionID >= tilingSplit)
1065             {
1066                x = pw * (tilingSplit / tilingH + (positionID - tilingSplit) / tilingLastH)/tilingW;
1067                y = ph * ((positionID - tilingSplit) % tilingLastH) / tilingLastH;
1068                x2 = pw * (tilingSplit/tilingH + (positionID - tilingSplit) / tilingLastH + 1)/tilingW;
1069                y2 = ph * (((positionID - tilingSplit) % tilingLastH) + 1) / tilingLastH;
1070             }
1071             else
1072             {
1073                x = pw * (positionID / tilingH) / tilingW;
1074                y = ph * (positionID % tilingH) / tilingH;
1075                x2 = pw * (positionID / tilingH + 1) / tilingW;
1076                y2 = ph * ((positionID % tilingH) + 1) / tilingH;
1077             }
1078             if(guiApp.textMode)
1079             {
1080                SNAPDOWN(x, textCellW);
1081                SNAPDOWN(y, textCellH);
1082                SNAPDOWN(x2, textCellW);
1083                SNAPDOWN(y2, textCellH);
1084             }
1085             w = x2 - x;
1086             h = y2 - y;
1087          }
1088       }
1089       else
1090       {
1091          if(sizeAnchor.isClientW) w += ew;
1092          if(sizeAnchor.isClientH) h += eh;
1093          
1094          if(anchor.left.type == offset)
1095             x = anchor.left.distance;
1096          else if(anchor.left.type == relative)
1097             x = (anchor.left.percent < 0) ? ((int)(vpw * anchor.left.percent - 0.5)) : (int)(vpw * anchor.left.percent + 0.5);
1098          else if(anchor.right.type == relative)
1099             // ex = (anchor.right.percent < 0) ? ((int)(vpw * anchor.right.percent + 0)) : ((int)(vpw * anchor.right.percent + 0));
1100             ex = (anchor.right.percent < 0) ? ((int)(vpw * (1.0-anchor.right.percent) + 0)) : ((int)(vpw * (1.0-anchor.right.percent) + 0));
1101          else if(anchor.right.type == offset)
1102             ex = vpw - anchor.right.distance;
1103
1104          if(anchor.top.type == offset)
1105             y = anchor.top.distance;
1106          else if(anchor.top.type == relative)
1107             y = (anchor.top.percent < 0) ? ((int)(vph * anchor.top.percent - 0.5)) : ((int)(vph * anchor.top.percent + 0.5));
1108          else if(anchor.bottom.type == relative)
1109             //ey = (anchor.bottom.percent < 0) ? ((int)(vph * anchor.bottom.percent + 0)) : ((int)(vph * anchor.bottom.percent + 0));
1110             ey = (anchor.bottom.percent < 0) ? ((int)(vph * (1.0-anchor.bottom.percent) + 0)) : ((int)(vph * (1.0-anchor.bottom.percent) + 0));
1111          else if(anchor.bottom.type == offset)
1112             ey = vph - anchor.bottom.distance;
1113
1114          if(anchor.left.type && anchor.right.type)
1115          {
1116             switch(anchor.right.type)
1117             {
1118                case relative: 
1119                   ex = pw * (1.0f-anchor.right.percent); 
1120                   w = Max((int)(ex + 0.5) - x, 0);
1121                   break;
1122                case offset:
1123                   ex = vpw - anchor.right.distance;
1124                   w = Max((int)(ex + 0.5) - x, 0);
1125                   break;
1126             }
1127          }
1128          if(anchor.top.type && anchor.bottom.type)
1129          {
1130             switch(anchor.bottom.type)
1131             {
1132                case relative:
1133                   ey = ph * (1.0f-anchor.bottom.percent);
1134                   h = Max((int)(ey + 0.5) - y, 0);
1135                   break;
1136                case offset:
1137                   ey = vph - anchor.bottom.distance;
1138                   h = Max((int)(ey + 0.5) - y, 0);
1139                   break;
1140             }
1141          }
1142       }
1143
1144       w -= ew;
1145       h -= eh; 
1146
1147       if(state == normal /*|| state == Hidden*/)
1148       {
1149          bool addSbV = false, addSbH = false;
1150
1151          if(sizeAnchor.isClientW || (anchor.left.type && anchor.right.type))  w = Max(w, 1); else w = Max(w, 0);
1152          if(sizeAnchor.isClientH || (anchor.top.type && anchor.bottom.type))  h = Max(h, 1); else h = Max(h, 0);
1153
1154          w = Max(w, minSize.w);
1155          h = Max(h, minSize.h);
1156          w = Min(w, maxSize.w);
1157          h = Min(h, maxSize.h);
1158
1159          if((sizeAnchor.isClientW || !w || (anchor.left.type && anchor.right.type)) && reqScrollArea.h > h /*&& w*/ && sbv) 
1160          {
1161             if(w) w -= guiApp.currentSkin.VerticalSBW();
1162             addSbV = true;
1163          }
1164          if((sizeAnchor.isClientH || !h ||  (anchor.top.type && anchor.bottom.type)) && reqScrollArea.w > w /*&& h*/ && sbh) 
1165          {
1166             if(h) h -= guiApp.currentSkin.HorizontalSBH();
1167             addSbH = true;
1168          }
1169
1170          if(!OnResizing(&w, &h))
1171          {
1172             w = clientSize.w;
1173             h = clientSize.h;
1174          }
1175
1176          if((addSbV)) // || reqScrollArea.h > h) && sbv) 
1177             w += guiApp.currentSkin.VerticalSBW();
1178          if((addSbH)) // || reqScrollArea.w > w) && sbh)
1179             h += guiApp.currentSkin.HorizontalSBH();
1180
1181          w = Max(w, skinMinSize.w);
1182          h = Max(h, skinMinSize.h);
1183       }
1184       else
1185       {
1186          w = Max(w, 0);
1187          h = Max(h, 0);
1188       }
1189
1190       w += ew;
1191       h += eh; 
1192
1193       if(guiApp.textMode)
1194       {
1195          SNAPDOWN(w, textCellW);
1196          SNAPDOWN(h, textCellH);
1197       }
1198
1199       if(anchor.left.type == cascade && (state == normal /*|| state == Hidden*/))
1200       {
1201          if(parent.numIcons) ph -= guiApp.textMode ? 16 : 24;
1202
1203          numCascade = Min(
1204             (pw - w) / CASCADE_SPACE, 
1205             (ph - h) / CASCADE_SPACE);
1206          
1207          if(guiApp.textMode)
1208          {
1209                int cascW, cascH;
1210                numCascade++;
1211                cascW = (pw - w) / (numCascade-1);
1212                cascH = (ph - h) / (numCascade-1);
1213                SNAPDOWN(cascW, textCellW);
1214                SNAPDOWN(cascH, textCellH);
1215                cascadeW = (float)cascW;
1216                cascadeH = (float)cascH;
1217          }
1218          else
1219          {
1220             numCascade = Max(numCascade, 2);
1221             cascadeW = (float)(pw - w) / (numCascade-1);
1222             cascadeH = (float)(ph - h) / (numCascade-1);
1223          }
1224
1225          x = (int)((positionID % numCascade) * cascadeW);
1226          y = (int)((positionID % numCascade) * cascadeH);
1227       }
1228       else if(anchor.left.type < vTiled)
1229       {
1230          if(!anchor.left.type || anchor.horz.type == middleRelative)
1231          {
1232             if(!anchor.right.type)
1233             {
1234                if(anchor.horz.type == middleRelative)
1235                   x = (int)(vpw * (0.5 + anchor.horz.percent) - w / 2);
1236                else
1237                   x = vpw / 2 + anchor.horz.distance - w / 2;
1238             }
1239             else
1240                x = (int)(ex - w);
1241          }
1242
1243          // case A_EDGE: x = x - w; break;
1244
1245          if(!anchor.top.type || anchor.vert.type == middleRelative)
1246          {
1247             if(!anchor.bottom.type)
1248             {
1249                if(anchor.vert.type == middleRelative)
1250                   y = (int)(vph * (0.5 + anchor.vert.percent) - h / 2);
1251                else
1252                   y = vph / 2 + anchor.vert.distance - h / 2;      
1253             }
1254             else
1255                y = (int)(ey - h);
1256          }
1257
1258          // case A_EDGE: y = y - h; break;
1259       }
1260
1261       if((state == normal /*|| state == Hidden*/) && !OnMoving(&x, &y, w, h))
1262       {
1263          x = position.x;
1264          y = position.y;
1265       }
1266
1267       if(guiApp.textMode)
1268       {
1269          SNAPDOWN(x, textCellW);
1270          SNAPDOWN(y, textCellH);
1271       }
1272
1273       x += addX;
1274       y += addY;
1275
1276       *ow = w;
1277       *oh = h;
1278
1279       *ox = x;
1280       *oy = y;
1281
1282       if(anchored && style.fixed && style.isActiveClient)
1283          anchored = false;
1284    }
1285
1286    // --- Carets ---
1287    void UpdateCaret(bool forceUpdate, bool erase)
1288    {
1289       static Window lastWindow = null;
1290       static int caretX, caretY, caretSize;
1291
1292       if(guiApp && guiApp.caretOwner == this)
1293       {
1294          int x = caretPos.x - scroll.x;
1295          int y = caretPos.y - scroll.y;
1296
1297          if((erase || this.caretSize) &&
1298             x >= clientArea.left && x <= clientArea.right && 
1299             y >= clientArea.top  && y <= clientArea.bottom)
1300          {
1301             if(!erase)
1302             {
1303                guiApp.interfaceDriver.SetCaret(
1304                   x + absPosition.x + clientStart.x, 
1305                   y + absPosition.y + clientStart.y, this.caretSize);
1306                guiApp.caretEnabled = true;
1307             }
1308             if(erase || lastWindow != this || caretX != x || caretY != y || caretSize != this.caretSize || forceUpdate)
1309             {
1310                Box updateBox;
1311
1312                if(lastWindow != this)
1313                {
1314                   updateBox.left = x + 1;
1315                   updateBox.top = y;
1316                   updateBox.right = x + 2;
1317                   updateBox.bottom = y + this.caretSize - 1;
1318                }
1319                else
1320                {
1321                   updateBox.left = Min(x + 1, caretX + 1);
1322                   updateBox.top = Min(y, caretY);
1323                   updateBox.right = Max(x + 2, caretX + 2);
1324                   updateBox.bottom = Max(y + this.caretSize - 1, caretY + caretSize - 1);
1325                }
1326
1327                guiApp.caretOwner.Update(updateBox);
1328
1329                if(!erase)
1330                {
1331                   lastWindow = this;
1332                   caretX = x;
1333                   caretY = y;
1334                   caretSize = this.caretSize;
1335                }
1336             }
1337          }
1338          else
1339          {
1340             guiApp.interfaceDriver.SetCaret(0,0,0);
1341             guiApp.caretEnabled = false;
1342             lastWindow = null;
1343          }
1344       }
1345    }
1346
1347    void SetPosition(int x, int y, int w, int h, bool modifyArea, bool modifyThisArea, bool modifyClientArea)
1348    {
1349       Window child;
1350
1351       // Set position
1352       scrolledPos.x = position.x = x;
1353       scrolledPos.y = position.y = y;
1354
1355       clientSize.w = size.w = w;
1356       clientSize.h = size.h = h;
1357
1358       if(parent && !style.nonClient)
1359       {
1360          //if(!style.fixed || style.isDocument)
1361          {
1362             if(!style.dontScrollHorz) scrolledPos.x -= parent.scroll.x;
1363             if(!style.dontScrollVert) scrolledPos.y -= parent.scroll.y;
1364          }
1365       }
1366
1367       clientStart.x = clientStart.y = 0;
1368
1369       SetWindowArea(&clientStart.x, &clientStart.y, &size.w, &size.h, &clientSize.w, &clientSize.h);
1370
1371       //if(!activeClient || activeClient.state != maximized)
1372       if(!noAutoScrollArea)
1373       {
1374          // Check if scroll area must be modified
1375          if(guiApp && !guiApp.modeSwitching && (sbv || sbh))
1376          {
1377             bool foundChild = false;
1378             int w = 0, h = 0;
1379             int cw = clientSize.w;// + ((!sbv || sbv.range > 1) ? guiApp.currentSkin.VerticalSBW() : 0);
1380             int ch = clientSize.h;// + ((!sbh || sbh.rangw > 1) ? guiApp.currentSkin.HorizontalSBH() : 0);
1381             for(child = children.first; child; child = child.next)
1382             {
1383                if(child.modifyVirtArea && !child.style.hidden && child.created && /*!child.anchored &&*/
1384                   !child.style.dontScrollHorz && !child.style.dontScrollVert && !child.style.nonClient)
1385                {
1386                   if(child.stateAnchor.right.type == none && child.stateAnchor.left.type == offset)
1387                      w = Max(w, child.position.x + child.size.w);
1388                   else if(child.stateAnchor.right.type == none && child.stateAnchor.left.type == none)
1389                      w = Max(w, Max(child.position.x, 0) + child.size.w);
1390                   if(child.stateAnchor.bottom.type == none && child.stateAnchor.top.type == offset)
1391                      h = Max(h, child.position.y + child.size.h);
1392                   else if(child.stateAnchor.bottom.type == none && child.stateAnchor.top.type == none)
1393                      h = Max(h, Max(child.position.y, 0) + child.size.h);
1394
1395                   foundChild = true;
1396                }
1397             }
1398             if(foundChild && (w > cw || h > ch))
1399             {
1400                //if((w > reqScrollArea.w) || (h > reqScrollArea.w))
1401                {
1402                   int stepX = sbStep.x, stepY = sbStep.y;
1403                   // Needed to make snapped down position match the skin's check of client area 
1404                   // against realvirtual
1405                   if(guiApp.textMode)
1406                   {
1407                      SNAPDOWN(stepX, textCellW);
1408                      SNAPDOWN(stepY, textCellH);
1409                      stepX = Max(stepX, textCellW);
1410                      stepY = Max(stepY, textCellH);
1411                   }
1412                   if(scrollFlags.snapX)
1413                      SNAPUP(w, stepX);
1414                   if(scrollFlags.snapY)
1415                      SNAPUP(h, stepY);
1416
1417                   reqScrollArea.w = w;
1418                   reqScrollArea.h = h;
1419                }
1420             }
1421             else if(reqScrollArea.w || reqScrollArea.h)
1422             {
1423                reqScrollArea.w = 0;
1424                reqScrollArea.h = 0;
1425                SetScrollPosition(0,0);
1426             }
1427          }
1428       }
1429
1430       // Automatic MDI Client Scrolling Area Adjustment
1431       if(parent && !parent.noAutoScrollArea)
1432       {
1433          if(modifyArea && modifyVirtArea /*&& !anchored*/ && (parent.sbv || parent.sbh) && 
1434             !style.dontScrollHorz && !style.dontScrollVert && !style.nonClient)
1435          {
1436             Window parent = this.parent;
1437             int w = parent.reqScrollArea.w;
1438             int h = parent.reqScrollArea.h;
1439
1440             if(stateAnchor.right.type == none && stateAnchor.left.type == offset)
1441                w = Max(w, position.x + size.w);
1442             else if(stateAnchor.right.type == none && stateAnchor.left.type == none)
1443                w = Max(w, Max(position.x, 0) + size.w);
1444             if(stateAnchor.bottom.type == none && stateAnchor.top.type == offset)
1445                h = Max(h, position.y + size.h);
1446             else if(stateAnchor.bottom.type == none && stateAnchor.top.type == none)
1447                h = Max(h, Max(position.y, 0) + size.h);
1448
1449             if((w > parent.clientSize.w && w > parent.reqScrollArea.w) || 
1450                (h > parent.clientSize.h && h > parent.reqScrollArea.h))
1451             {
1452                /*bool resize = false;
1453                int stepX = parent.sbStep.x, stepY = parent.sbStep.y;
1454                // Needed to make snapped down position match the skin's check of client area 
1455                // against realvirtual
1456                if(guiApp.textMode)
1457                {
1458                   SNAPDOWN(stepX, textCellW);
1459                   SNAPDOWN(stepY, textCellH);
1460                   stepX = Max(stepX, textCellW);
1461                   stepY = Max(stepY, textCellH);
1462                }
1463                if(parent.scrollFlags.snapX)
1464                   SNAPUP(w, stepX);
1465                if(parent.scrollFlags.snapY)
1466                   SNAPUP(h, stepY);
1467                if(parent.reqScrollArea.w != w || parent.reqScrollArea.h != h)
1468                {
1469                   parent.reqScrollArea.w = w;
1470                   parent.reqScrollArea.h = h;*/
1471
1472                  // parent.UpdateScrollBars(true, true);
1473                   parent.Position(parent.position.x, parent.position.y, parent.size.w, parent.size.h, 
1474                      false, true, true, true, false, false);
1475                   return;
1476                //}
1477             }
1478             else 
1479                GetRidOfVirtualArea();
1480          }
1481       }
1482       if(modifyThisArea)
1483          UpdateScrollBars(modifyThisArea, false);
1484       else if(guiApp.currentSkin)
1485       {
1486          SetWindowArea(
1487             &clientStart.x, &clientStart.y, &size.w, &size.h, &clientSize.w, &clientSize.h);
1488
1489          if(sbv && (scrollFlags.dontHide || sbv.range > 1))
1490             clientSize.w -= guiApp.currentSkin.VerticalSBW();
1491          if(sbh && (scrollFlags.dontHide || sbh.range > 1))
1492             clientSize.h -= guiApp.currentSkin.HorizontalSBH();
1493       }
1494
1495       scrollArea.w = Max(clientSize.w, reqScrollArea.w);
1496       scrollArea.h = Max(clientSize.h, reqScrollArea.h);
1497
1498       absPosition = scrolledPos;
1499       if(guiApp && guiApp.driver != null && guiApp.interfaceDriver)
1500          guiApp.interfaceDriver.OffsetWindow(this, &absPosition.x, &absPosition.y);
1501
1502       if(this != guiApp.desktop && parent)
1503       {
1504          absPosition.x += parent.absPosition.x;
1505          absPosition.y += parent.absPosition.y;
1506          if(!style.nonClient && this != guiApp.desktop)
1507          {
1508             absPosition.x += parent.clientStart.x;
1509             absPosition.y += parent.clientStart.y;
1510          }
1511       }
1512
1513       box = Box { 0, 0, size.w - 1, size.h - 1 };
1514       SetBox(box);
1515
1516       if(against)
1517       {
1518          // Clip against parent's client area
1519          box.ClipOffset(against, scrolledPos.x, scrolledPos.y);
1520       }
1521       // Compute client area in this window coordinate system
1522       clientArea.left = 0;
1523       clientArea.top = 0;
1524       clientArea.right = clientSize.w - 1;
1525       clientArea.bottom = clientSize.h - 1;
1526
1527       // Clip against parent's client area
1528       if(against)
1529          clientArea.ClipOffset(against, scrolledPos.x + clientStart.x, scrolledPos.y + clientStart.y);
1530
1531       if(is3D)
1532       {
1533          //absPosition.x -= parent.clientStart.x;
1534          //absPosition.y -= parent.clientStart.y;
1535       }
1536
1537       // Adjust all children
1538       for(child = children.first; child; child = child.next)
1539          child.SetPosition(child.position.x, child.position.y, child.size.w, child.size.h, false, true, true);
1540
1541       UpdateCaret(false, false);
1542    }
1543
1544    void GetRidOfVirtualArea(void)
1545    {
1546       if(parent && !parent.destroyed && style.fixed &&
1547          !style.dontScrollHorz && !style.dontScrollVert && !style.nonClient &&
1548          parent.reqScrollArea.w && parent.reqScrollArea.h)
1549       {
1550          if(!parent.noAutoScrollArea)
1551          {
1552             Window child;
1553             bool found = false;
1554             for(child = children.first; child; child = child.next)
1555             {
1556                if(child.modifyVirtArea && !child.style.dontScrollHorz && !child.style.dontScrollVert && !child.style.nonClient)
1557                {
1558                   if(child.position.x + child.size.w > parent.clientSize.w + ((!parent.sbv || parent.sbv.style.hidden) ? 0 : guiApp.currentSkin.VerticalSBW()) ||
1559                      child.position.y + child.size.h > parent.clientSize.h + ((!parent.sbh || parent.sbh.style.hidden) ? 0 : guiApp.currentSkin.HorizontalSBH()))
1560                   {
1561                      found = true;
1562                      break;
1563                   }
1564                }
1565             }
1566             //if(!found)
1567             {
1568                Window parent = this.parent;
1569                parent.Position(
1570                   parent.position.x, parent.position.y, parent.size.w, parent.size.h, 
1571                   false, true, true, true, false, false);
1572                /*
1573                parent.SetScrollArea(0,0,true);
1574                parent.SetScrollPosition(0,0);
1575                */
1576             }
1577          }
1578       }
1579    }
1580    public void ExternalPosition(int x, int y, int w, int h)
1581    {
1582       Position(x, y, w, h, false, true, true, true, false, false);
1583    }
1584
1585    // (w, h): Full window size
1586    bool Position(int x, int y, int w, int h, bool force, bool processAnchors, bool modifyArea, bool updateScrollBars, bool thisOnly, bool changeRootWindow)
1587    {
1588       bool result = false;
1589       int oldCW = clientSize.w, oldCH = clientSize.h;
1590       bool clientResized, windowResized, windowMoved;
1591       Window child;
1592       bool realResized = size.w != w || size.h != h;
1593
1594       // TOCHECK: This wasn't in ecere.dll
1595       //if(!parent) return true;
1596       if(destroyed) return false;
1597
1598       windowMoved = position.x != x || position.y != y || force;
1599
1600       // windowResized = realResized || force;
1601       windowResized = size.w != w || size.h != h || force;
1602      
1603       if(rootWindow != this && display && !display.flags.flipping && scrolledPos.x != MININT)
1604       {
1605          if(style.nonClient)
1606          {
1607             Box box
1608             { 
1609                scrolledPos.x - parent.clientStart.x + this.box.left, scrolledPos.y - parent.clientStart.y + this.box.top, 
1610                scrolledPos.x - parent.clientStart.x + this.box.right,
1611                scrolledPos.y - parent.clientStart.y + this.box.bottom 
1612             };
1613             parent.Update(box);
1614          }
1615          else
1616          {
1617             Box box { scrolledPos.x + this.box.left, scrolledPos.y + this.box.top, scrolledPos.x + this.box.right, scrolledPos.y + this.box.bottom};
1618             parent.Update(box);
1619          }
1620       }
1621
1622       SetPosition(x, y, w, h, true, modifyArea, updateScrollBars);
1623
1624       clientResized = oldCW != clientSize.w || oldCH != clientSize.h || force;
1625       if(clientResized && this == rootWindow && nativeDecorations)
1626          windowResized = true;
1627
1628       if(display && rootWindow != this)
1629          Update(null);
1630
1631       if(guiApp && guiApp.windowMoving)
1632       {
1633          if(guiApp.windowMoving.style.nonClient)
1634             guiApp.windowMoving.parent.SetMouseRangeToWindow();
1635          else
1636             guiApp.windowMoving.parent.SetMouseRangeToClient();
1637       }
1638
1639       if(!positioned)
1640       {
1641          positioned = true;
1642          if(clientResized)
1643          {
1644             if(!thisOnly)
1645             {
1646                // Buttons bitmap resources crash if we do this while switching mode
1647                if(!guiApp || !guiApp.modeSwitching)
1648                   UpdateNonClient();
1649
1650                // Process Anchored Children
1651                if(processAnchors)
1652                {
1653                   int x,y,w,h;
1654                   for(child = children.first; child; child = child.next)
1655                   {
1656                      if(child.created && 
1657                      ((child.stateAnchor.left.type != offset ||
1658                        child.stateAnchor.top.type != offset ||
1659                        child.stateAnchor.right.type != none ||
1660                        child.stateAnchor.bottom.type != none) ||
1661                         child.state == maximized || child.state == minimized))
1662                      {
1663                         child.ComputeAnchors(child.stateAnchor, child.stateSizeAnchor,
1664                            &x, &y, &w, &h);
1665                         // child.Position(x, y, w, h, false, true, true, true, false);
1666                         // This must be true cuz otherwise we're gonna miss everything since we SetPosition recursively already
1667                         child.Position(x, y, w, h, true, true, true, true, false, true /*false*/);
1668                      }
1669                   }
1670                }
1671             }
1672
1673             // Is this gonna cause other problems? Commented out for the FileDialog end bevel bug
1674             //if(updateScrollBars)
1675             if(created)
1676                OnResize(clientSize.w, clientSize.h);
1677          }
1678          if((clientResized || windowMoved) && created)
1679             OnPosition(position.x, position.y, clientSize.w, clientSize.h);
1680    /*
1681          if(guiApp.interimWindow && guiApp.interimWindow.master.rootWindow == this)
1682          {
1683             Window master = guiApp.interimWindow.master;
1684             master.OnPosition(master.position.x, master.position.y, master.clientSize.w, master.clientSize.h);
1685          }
1686    */
1687          if(rootWindow == this && !is3D)
1688          {
1689             /*if(style.interim)
1690             {
1691                x -= guiApp.desktop.absPosition.x;
1692                y -= guiApp.desktop.absPosition.y;
1693             }*/
1694             //guiApp.Log("Position %s\n", caption);
1695             if(windowResized || windowMoved)
1696                if(display && !display.flags.memBackBuffer && changeRootWindow)
1697                   guiApp.interfaceDriver.PositionRootWindow(this, x, y, w, h, windowMoved, windowResized); //realResized);
1698
1699             if(!guiApp.fullScreenMode && this != guiApp.desktop && (windowResized || windowMoved))
1700                for(child = parent.children.first; child && child != this; child = child.next)
1701                   if(child.rootWindow)
1702                      guiApp.interfaceDriver.UpdateRootWindow(child.rootWindow);
1703
1704             if(display)
1705             {
1706                if(windowMoved || windowResized)
1707                {
1708                   display.Lock(true /*false*/);
1709                }
1710                if(windowMoved)
1711                   display.Position(absPosition.x, absPosition.y);
1712                   //display.Position(absPosition.x + clientStart.x, absPosition.y + clientStart.y);
1713                if(windowResized)
1714                {
1715                   // result = realResized ? display.Resize(size.w, size.h) : true;
1716                   if(nativeDecorations)
1717                   {
1718                      int w = clientSize.w, h = clientSize.h;
1719                      if(hasMenuBar) h += skinMenuHeight;
1720                      if(hasStatusBar) h += statusBarHeight;
1721                      if(sbv && sbv.visible) w += sbv.size.w;
1722                      if(sbh && sbh.visible) h += sbh.size.h;
1723                      result = manageDisplay ? display.Resize(w, h) : true;
1724                   }
1725                   else
1726                      result = manageDisplay ? display.Resize(size.w, size.h) : true;
1727                   resized = true;
1728                   Update(null);
1729                }
1730                else if(clientResized)
1731                   Update(clientArea);
1732                // --- Major Slow Down / Fix OpenGL Resizing Main Window Lag
1733                
1734                /*
1735                if(!guiApp.fullScreenMode && !guiApp.modeSwitching && this == rootWindow)
1736                   UpdateDisplay();
1737                */
1738                
1739                if(windowMoved || windowResized)
1740                {
1741                   display.Unlock();
1742                }
1743             }
1744             if(guiApp.driver && changeRootWindow)
1745             {
1746                if(windowResized || windowMoved)
1747                   if(!display || display.flags.memBackBuffer)
1748                      guiApp.interfaceDriver.PositionRootWindow(this, 
1749                         x, y, w, h, windowMoved, windowResized);
1750                guiApp.interfaceDriver.UpdateRootWindow(this);
1751             }
1752             for(child = children.first; child; child = child.next)
1753             {
1754                if(child.is3D && child.created)
1755                {
1756                   // Copy Display Content
1757                   child.display.displaySystem = display.displaySystem;
1758                   child.display.window = display.window;
1759                   child.display.current = display.current;
1760                   child.display.width = display.width;
1761                   child.display.height = display.height;
1762                   child.display.driverData = display.driverData;
1763                   child.display.mutex = null;
1764                }
1765             }
1766          }
1767          else
1768             result = true;
1769          positioned = false;
1770       }
1771       return result;
1772    }
1773
1774    void UpdateScrollBars(bool flag, bool fullThing)
1775    {
1776       int rvw, rvh;
1777       bool resizeH = false, resizeV = false;
1778       bool scrolled = false;
1779       rvw = (activeChild && activeChild.state == maximized) ? 0 : reqScrollArea.w;
1780       rvh = (activeChild && activeChild.state == maximized) ? 0 : reqScrollArea.h;
1781
1782       if(destroyed) return;
1783       if(guiApp.currentSkin)
1784       {
1785          MinMaxValue cw = 0, ch = 0;
1786          bool sbvVisible, sbhVisible;
1787          int rangeH, rangeV;
1788          int positionH, positionV;
1789
1790          // First get client area with no respect to scroll bars
1791
1792          if(flag)
1793          {
1794             SetWindowArea(
1795                &clientStart.x, &clientStart.y, &size.w, &size.h, &cw, &ch);
1796
1797             if(scrollFlags.dontHide)
1798             {
1799                if(sbv)
1800                   cw -= guiApp.currentSkin.VerticalSBW();
1801                if(sbh)
1802                   ch -= guiApp.currentSkin.HorizontalSBH();
1803
1804                // Update the scrollbar visibility
1805                if(sbh)
1806                {
1807                   sbh.seen = cw;
1808                   sbh.total = rvw;
1809                   rangeH = sbh.range;
1810                   sbh.disabled = rangeH <= 1;
1811                   if(sbh.style.hidden)
1812                   {
1813                      resizeH = true;
1814                   }
1815                }
1816                if(sbv)
1817                {
1818                   sbv.seen = ch;
1819                   sbv.total = rvh;
1820                   rangeV = sbv.range;
1821                   sbv.disabled = rangeV <= 1;
1822                   if(sbv.style.hidden)
1823                   {
1824                      resizeV = true;
1825                   }
1826                }
1827             }
1828             else
1829             {
1830                // Then start off with horizontal scrollbar range
1831                if(sbh)
1832                {
1833                   positionH = sbh.thumbPosition;
1834                   sbh.seen = cw;
1835                   sbh.total = rvw;
1836                   rangeH = sbh.range;
1837                   if(rangeH > 1)
1838                      ch -= guiApp.currentSkin.HorizontalSBH();
1839                }
1840
1841                // Do the same for vertical scrollbar
1842                if(sbv)
1843                {
1844                   positionV = sbv.thumbPosition;
1845                   sbv.seen = ch;
1846                   sbv.total = rvh;
1847                   rangeV = sbv.range;
1848                   if(rangeV > 1)
1849                   {
1850                      cw -= guiApp.currentSkin.VerticalSBW();
1851                      // Maybe we need to set the range on the horizontal scrollbar again
1852                      if(sbh)
1853                      {
1854                         sbh.seen = cw;
1855                         sbh.total = rvw;
1856                         sbh.Action(setRange, positionH, 0);
1857                         if(rangeH <= 1 && sbh.range > 1)
1858                         {
1859                            ch -= guiApp.currentSkin.HorizontalSBH();
1860                            sbv.seen = ch;
1861                            sbv.total = rvh;
1862                            rangeV = sbv.range;
1863                            sbv.Action(setRange, positionV, 0);
1864                         }
1865                         rangeH = sbh.range;
1866                      }
1867                   }
1868                }
1869
1870                // Update the scrollbar visibility
1871                if(!scrollFlags.dontHide)
1872                {
1873                   if(sbh && ((rangeH <= 1 && !sbh.style.hidden) || (rangeH > 1 && sbh.style.hidden)))
1874                   {
1875                      resizeH = true;
1876                   }
1877                   if(sbv && ((rangeV <= 1 && !sbv.style.hidden) || (rangeV > 1 && sbv.style.hidden)))
1878                   {
1879                      resizeV = true;
1880                   }
1881                }
1882             }
1883
1884             if(guiApp.currentSkin)
1885             {
1886                clientSize.w = cw;
1887                clientSize.h = ch;
1888             }
1889
1890             if(resizeH)
1891                sbhVisible = sbh.style.hidden ? true : false;
1892             if(resizeV)
1893                sbvVisible = sbv.style.hidden ? true : false;
1894
1895             // Do our resize here
1896             if(flag && (resizeH || resizeV) && fullThing)
1897             {
1898                Position(position.x, position.y, size.w, size.h, false, true, false, false, false, false);
1899                
1900                if(!positioned)
1901                {
1902                   positioned = true;
1903                   OnResize(clientSize.w, clientSize.h);
1904                   positioned = false;
1905                }
1906             }
1907       
1908             if(resizeH && sbh)
1909                sbh.visible = sbhVisible;
1910             if(resizeV && sbv)
1911                sbv.visible = sbvVisible;
1912          }
1913          scrollArea.w = Max(clientSize.w, reqScrollArea.w);
1914          scrollArea.h = Max(clientSize.h, reqScrollArea.h);
1915
1916          if(sbh)
1917             sbh.pageStep = clientSize.w;
1918          if(sbv)
1919             sbv.pageStep = clientSize.h;
1920
1921          // Notify doesn't handle setRange anymore... process it here
1922          if(sbh)
1923          {
1924             int positionH = sbh.thumbPosition;
1925             if(scroll.x != positionH)
1926             {
1927                OnHScroll(setRange, positionH, 0);
1928                scrolled = true;
1929             }
1930             if(guiApp.textMode)
1931                SNAPDOWN(positionH, textCellW);
1932             scroll.x = positionH;
1933          }
1934          else
1935          {
1936             int x = scroll.x;
1937             int range;
1938             int seen = clientSize.w, total = reqScrollArea.w;
1939             seen = Max(1,seen);
1940
1941             if(scrollFlags.snapX)
1942                SNAPDOWN(seen, sbStep.x);
1943
1944             if(!total) total = seen;
1945             range = total - seen + 1;
1946
1947             range = Max(range, 1);
1948             if(x < 0) x = 0;
1949             if(x >= range) x = range - 1;
1950
1951             if(scrollFlags.snapX)
1952                SNAPUP(x, sbStep.x);
1953
1954             if(scroll.x != x)
1955             {
1956                OnHScroll(setRange, x, 0);
1957             }
1958
1959             if(guiApp.textMode)
1960             {
1961                SNAPDOWN(x, textCellW);
1962             }
1963             scroll.x = x;
1964          }
1965          if(sbv)
1966          {
1967             int positionV = sbv.thumbPosition;
1968             if(scroll.y != positionV)
1969             {
1970                OnVScroll(setRange, positionV, 0);
1971                scrolled = true;
1972             }
1973             if(guiApp.textMode)
1974                SNAPDOWN(positionV, textCellH);
1975             scroll.y = positionV;
1976          }
1977          else
1978          {
1979             int y = scroll.y;
1980             int range;
1981             int seen = clientSize.h, total = reqScrollArea.h;
1982             seen = Max(1,seen);
1983
1984             if(scrollFlags.snapY)
1985                SNAPDOWN(seen, sbStep.y);
1986
1987             if(!total) total = seen;
1988             range = total - seen + 1;
1989             range = Max(range, 1);
1990             if(y < 0) y = 0;
1991             if(y >= range) y = range - 1;
1992
1993             if(scrollFlags.snapY)
1994                SNAPUP(y, sbStep.y);
1995
1996             if(scroll.y != y)
1997             {
1998                OnVScroll(setRange, y, 0);
1999             }
2000
2001             if(guiApp.textMode)
2002             {
2003                SNAPDOWN(y, textCellH);
2004             }
2005             scroll.y = y;
2006          }
2007
2008          /*
2009          if(scrolled || (resizeH || resizeV))   // This ensures children anchored to bottom/right gets repositioned correctly
2010          {
2011             Window child;
2012             for(child = children.first; child; child = child.next)
2013             {
2014                if(!child.style.nonClient && child.state != maximized && (!child.style.dontScrollHorz || !child.style.dontScrollVert))
2015                {
2016                   int x,y,w,h;
2017                   child.ComputeAnchors(child.stateAnchor, child.stateSizeAnchor, &x, &y, &w, &h);
2018                   child.Position(x, y, w, h, false, true, false, true, false, false);
2019                }
2020             }
2021          }
2022          */
2023       }
2024
2025       // Process Scrollbars
2026
2027       if(sbh) // && !sbh.style.hidden
2028       {
2029          sbh.Move(clientStart.x, clientStart.y + clientSize.h, clientSize.w,0);
2030          // Need to set the range again (should improve...) since the scrollbars didn't have
2031          // the right size when UpdateScrollArea set the range on it
2032          if(flag)
2033          {
2034             sbh.seen = clientSize.w;
2035             sbh.total = rvw;
2036          }
2037       }
2038       if(sbv) // && !sbv.state.hidden
2039       {
2040          sbv.Move(clientStart.x + clientSize.w, clientStart.y, 0, clientSize.h);
2041          // Need to set the range again (should improve...) since the scrollbars didn't have
2042          // the right size when UpdateScrollArea set the range on it
2043          if(flag)
2044          {
2045             sbv.seen = clientSize.h;
2046             sbv.total = rvh;
2047          }
2048       }
2049
2050       // TESTING THIS LOWER
2051       if(scrolled || (resizeH || resizeV))   // This ensures children anchored to bottom/right gets repositioned correctly
2052       {
2053          Window child;
2054          for(child = children.first; child; child = child.next)
2055          {
2056             if(!child.style.nonClient && child.state != maximized && (!child.style.dontScrollHorz || !child.style.dontScrollVert))
2057             {
2058                int x,y,w,h;
2059                child.ComputeAnchors(child.stateAnchor, child.stateSizeAnchor, &x, &y, &w, &h);
2060                child.Position(x, y, w, h, false, true, false, true, false, false);
2061             }
2062          }
2063       }
2064    }
2065
2066    bool MaximizeButtonClicked(Button button, int x, int y, Modifiers mods)
2067    {
2068       SetState(maximized, false, mods);
2069       return false;
2070    }
2071
2072    bool RestoreButtonClicked(Button button, int x, int y, Modifiers mods)
2073    {
2074       SetState(normal, false, mods);
2075       return false;
2076    }
2077
2078    bool MinimizeButtonClicked(Button button, int x, int y, Modifiers mods)
2079    {
2080       SetState(minimized, false, mods);
2081       parent.CycleChildren(false, true, false, true);
2082       return false;
2083    }
2084
2085    void ScrollBarNotification(ScrollBar control, ScrollBarAction action, int position, Key keyFlags)
2086    {
2087       Window child;
2088       // Scroll bar notifications
2089       if(action != setRange)
2090       {
2091          bool changed = false;
2092
2093          if(control == sbh)
2094          {
2095             if(scroll.x != position)
2096             {
2097                OnHScroll(action, position, keyFlags);
2098                changed = true;
2099             }
2100             if(guiApp.textMode)
2101             {
2102                SNAPDOWN(position, textCellW);
2103             }
2104             scroll.x = position;
2105          }
2106          else
2107          {
2108             if(scroll.y != position)
2109             {
2110                OnVScroll(action, position, keyFlags);
2111                changed = true;
2112             }
2113             if(guiApp.textMode)
2114             {
2115                SNAPDOWN(position, textCellH);
2116             }
2117             scroll.y = position;
2118          }
2119          if(changed)
2120          {
2121             bool childMove = false;
2122             for(child = children.first; child; child = child.next)
2123             {
2124                if(!child.style.nonClient && child.state != maximized && (!child.style.dontScrollHorz || !child.style.dontScrollVert))
2125                {
2126                   int x,y,w,h;
2127                   child.ComputeAnchors(child.stateAnchor, child.stateSizeAnchor, &x, &y, &w, &h);
2128                   child.Position(x, y, w, h, false, true, false, true, false, false);
2129                   childMove = true;
2130                }
2131             }
2132             // Testing this patch out to solve MDI workspace redraw bugs
2133             // We were already supposed to be updating parent's affected area in Position() but it doesn't seem to be working
2134             // Scroll offsets to blame?
2135             if(childMove)
2136                Update(null);
2137          }
2138          UpdateCaret(false, false);
2139       }
2140       else
2141       {
2142          // Testing this patch out to solve MDI workspace redraw bugs
2143          for(child = children.first; child; child = child.next)
2144          {
2145             if(!child.style.nonClient && child.state != maximized && (!child.style.dontScrollHorz || !child.style.dontScrollVert))
2146             {
2147                Update(null);
2148                break;
2149             }
2150          }         
2151       }
2152    }
2153
2154    void CreateSystemChildren(void)
2155    {
2156       Window parent = this;
2157       bool scrollBarChanged = false;
2158       bool hasClose = false, hasMaxMin = false;
2159       Point scroll = this.scroll;
2160
2161       if(state == maximized && this.parent.menuBar)
2162       {
2163          if(this.parent.activeClient == this)
2164             parent = this.parent.menuBar;
2165          else
2166             parent = null;
2167       }
2168
2169       if(parent)
2170       {
2171          if(style.hasClose) hasClose = true;
2172          if(style.hasMaximize || style.hasMinimize)
2173          {
2174             hasClose = true;
2175             hasMaxMin = true;
2176          }
2177       }
2178
2179       if(sysButtons[2] && (!hasClose || sysButtons[2].parent != parent))
2180       {
2181          sysButtons[2].Destroy(0);
2182          sysButtons[2] = null;
2183       }
2184       if(sysButtons[1] && (!hasMaxMin || sysButtons[1].parent != parent))
2185       {
2186          sysButtons[1].Destroy(0);
2187          sysButtons[1] = null;
2188       }
2189       if(sysButtons[0] && (!hasMaxMin || sysButtons[0].parent != parent))
2190       {
2191          sysButtons[0].Destroy(0);
2192          sysButtons[0] = null;
2193       }
2194       //return;
2195       if(hasClose && parent)
2196       {
2197          if(!sysButtons[2])
2198          {
2199             sysButtons[2] = 
2200                Button
2201                {
2202                   parent, master = this,
2203                   inactive = true, nonClient = true, visible = false;
2204
2205                   bool NotifyClicked(Button button, int x, int y, Modifiers mods)
2206                   {
2207                      Destroy(0);
2208                      return true;
2209                   }
2210                };
2211             if(this.parent == guiApp.desktop)
2212                sysButtons[2].hotKey = altF4;
2213             else if(style.isActiveClient)
2214                sysButtons[2].hotKey = ctrlF4;
2215             sysButtons[2].Create();
2216          }
2217          
2218          sysButtons[2].symbol = 'X';
2219          sysButtons[2].disabled = !style.hasClose;
2220       }
2221
2222       if(hasMaxMin && parent)
2223       {
2224          SkinBitmap skin;
2225          unichar symbol;
2226          bool (* method)(Window window, Button button, int x, int y, Modifiers mods);
2227          if(state == maximized) 
2228          {
2229             skin = restore;
2230             method = RestoreButtonClicked;
2231             symbol = '\x12';
2232          }
2233          else
2234          {
2235             skin = maximize;
2236             method = MaximizeButtonClicked;
2237             symbol = '\x18';
2238          }
2239          if(!sysButtons[1])
2240          {
2241             sysButtons[1] =
2242                Button
2243                {
2244                   parent, master = this,
2245                   hotKey = altEnter, inactive = true, nonClient = true, visible = false
2246                };
2247             sysButtons[1].Create();
2248          }
2249          sysButtons[1].NotifyClicked = method;
2250
2251          sysButtons[1].symbol = symbol;
2252          sysButtons[1].disabled = !style.hasMaximize;
2253       }
2254
2255       if(hasMaxMin && parent)
2256       {
2257          SkinBitmap skin;
2258          unichar symbol;
2259          bool (* method)(Window window, Button button, int x, int y, Modifiers mods);
2260          if (state == minimized) 
2261          {
2262             skin = restore;
2263             method = RestoreButtonClicked;
2264             symbol = '\x12';
2265          }
2266          else
2267          {
2268             skin = minimize;
2269             method = MinimizeButtonClicked;
2270             symbol = '\x19';
2271          }
2272          if(!sysButtons[0])
2273          {
2274             sysButtons[0] =
2275                Button
2276                {
2277                   parent, master = this,
2278                   hotKey = altM, inactive = true, nonClient = true, visible = false
2279                };
2280             sysButtons[0].Create();
2281          }
2282          sysButtons[0].NotifyClicked = method;
2283
2284          sysButtons[0].symbol = symbol;
2285          sysButtons[0].disabled = !style.hasMinimize;
2286       }
2287
2288       // Create the scrollbars
2289       if(style.hasHorzScroll && !sbh)
2290       {
2291          sbh =
2292             ScrollBar
2293             {
2294                this,
2295                direction = horizontal,
2296                windowOwned = true,
2297                inactive = true,
2298                nonClient = true,
2299                snap = scrollFlags.snapX,
2300                NotifyScrolling = ScrollBarNotification
2301             };
2302          sbh.Create();
2303          scrollBarChanged = true;
2304       }
2305       else if(sbh && !style.hasHorzScroll)
2306       {
2307          sbh.Destroy(0);
2308          sbh = null;
2309       }
2310
2311       if(style.hasVertScroll && !sbv)
2312       {
2313          sbv =
2314             ScrollBar
2315             {
2316                this,
2317                direction = vertical,
2318                windowOwned = true,
2319                inactive = true,
2320                nonClient = true,
2321                snap = scrollFlags.snapY,
2322                NotifyScrolling = ScrollBarNotification
2323             };
2324          sbv.Create();
2325          scrollBarChanged = true;
2326       }
2327       else if(sbv && !style.hasVertScroll)
2328       {
2329          sbv.Destroy(0);
2330          sbv = null;
2331       }
2332       if(scrollBarChanged)
2333       {
2334          SetScrollLineStep(sbStep.x, sbStep.y);   
2335          UpdateScrollBars(true, true);
2336       }   
2337       UpdateNonClient();
2338
2339       if(scrollBarChanged)
2340       {
2341          if(sbh) sbh.thumbPosition = scroll.x;
2342          if(sbv) sbv.thumbPosition = scroll.y;
2343       }
2344    }
2345
2346    void UpdateCaption(void)
2347    {
2348       if(rootWindow == this)
2349       {
2350          char caption[2048];
2351          FigureCaption(caption);
2352          guiApp.interfaceDriver.SetRootWindowCaption(this, caption);
2353       }
2354       UpdateDecorations();
2355       if(parent)
2356       {
2357          if(parent.rootWindow == parent && parent.activeClient == this) // Added this last check
2358          {
2359             char caption[2048];
2360             parent.FigureCaption(caption);
2361             guiApp.interfaceDriver.SetRootWindowCaption(parent, caption);
2362          }
2363          parent.UpdateDecorations();
2364       }
2365    }
2366
2367    void UpdateActiveDocument(Window previous)
2368    {
2369       Window activeClient = this.activeClient;
2370       Window activeChild = this.activeChild;
2371       if(menuBar)
2372       {
2373          UpdateCaption();
2374          if(!destroyed)
2375          {
2376             if(activeClient)
2377                activeClient.CreateSystemChildren();
2378             if(previous)
2379                previous.CreateSystemChildren();
2380          }
2381       }
2382       if(menu)
2383       {
2384          MenuItem item;
2385          bool disabled;
2386
2387          if(menu)
2388             menu.Clean(this);
2389
2390          if(activeClient && activeClient.menu && activeClient.state != minimized)
2391          {
2392             if(mergeMenus)
2393             {
2394                //activeClient.menu.Clean(activeClient);
2395                menu.Merge(activeClient.menu, true, activeClient);
2396             }
2397          }
2398          
2399          if(activeChild && activeChild != activeClient && activeChild.menu && activeChild.state != minimized)
2400          {
2401             if(mergeMenus)
2402                menu.Merge(activeChild.menu, true, activeChild);
2403          }
2404          
2405          // Build window list
2406          if(activeClient)
2407          {
2408             Menu windowMenu = menu.FindMenu("Window");
2409             if(windowMenu)
2410             {
2411                OldLink cycle;
2412                int id;
2413                for(id = 0, cycle = activeClient.cycle; cycle && id<10;)
2414                {
2415                   MenuItem item;
2416                   Window document = cycle.data;
2417                   if(!document.style.nonClient && document.style.isActiveClient && document.visible)
2418                   {
2419                      char name[2048], caption[2048];
2420                      document.FigureCaption(caption);
2421                      sprintf(name, "%d %s", id+1, caption);
2422                      windowMenu.AddDynamic(MenuItem 
2423                         { 
2424                            copyText = true, text = name, hotKey = Key { k1 + id }, id = id++, 
2425                            NotifySelect = MenuWindowSelectWindow 
2426                         }, this, false);
2427                   }
2428                   cycle = cycle.next;
2429                   if(activeClient.cycle == cycle) break;
2430                }
2431             }
2432          }
2433          
2434          if((!previous && activeClient) || !activeClient)
2435          {
2436             if(!activeClient)
2437                disabled = true;
2438             else
2439                disabled = false;
2440             item = menu.FindItem(MenuWindowCloseAll, 0);
2441             if(item) item.disabled = false;
2442             item = menu.FindItem(MenuWindowNext, 0);
2443             if(item) item.disabled = false;
2444             item = menu.FindItem(MenuWindowPrevious, 0);
2445             if(item) item.disabled = false;
2446             item = menu.FindItem(MenuWindowCascade, 0);
2447             if(item) item.disabled = false;
2448             item = menu.FindItem(MenuWindowTileHorz, 0);
2449             if(item) item.disabled = false;
2450             item = menu.FindItem(MenuWindowTileVert, 0);
2451             if(item) item.disabled = false;
2452             item = menu.FindItem(MenuWindowArrangeIcons, 0);
2453             if(item) item.disabled = false;
2454             item = menu.FindItem(MenuWindowWindows, 0);
2455             if(item) item.disabled = false;
2456          }      
2457
2458          item = menu.FindItem(MenuFileClose, 0);
2459          if(item) item.disabled = !activeClient || !activeClient.style.hasClose;
2460          item = menu.FindItem(MenuFileSaveAll, 0);
2461          if(item) item.disabled = numDocuments < 1;
2462       }
2463       // This is called again for a child window change, with same active client
2464       OnActivateClient(activeClient, previous);
2465    }
2466
2467    void _ShowDecorations(Box box, bool post)
2468    {
2469       if(rootWindow == this && nativeDecorations) return;
2470       if(visible && this != guiApp.desktop)
2471       {
2472          Surface surface = RedrawFull(box);
2473          if(surface)
2474          {
2475             char caption[2048];
2476             FigureCaption(caption);
2477             
2478             if(post)
2479                ShowDecorations(captionFont.font,
2480                   surface,
2481                   caption,
2482                   active, //parent.activeClient == this
2483                   guiApp.windowMoving == this);
2484             else
2485                PreShowDecorations(captionFont.font,
2486                   surface,
2487                   caption,
2488                   active, //parent.activeClient == this
2489                   guiApp.windowMoving == this);
2490                
2491             delete surface;
2492          }
2493       }
2494    }
2495
2496    void UpdateExtent(Box refresh)
2497    {
2498       Surface surface = null;
2499
2500       if(!manageDisplay) { OnRedraw(null);return; }
2501       _ShowDecorations(refresh, false);
2502
2503       surface = Redraw(refresh);               
2504       // Opaque background: just fill before EW_REDRAW (clear?)
2505       if(surface) 
2506       {
2507          surface.SetBackground(background);
2508          surface.SetForeground(foreground);
2509          surface.DrawingChar(' ');
2510          if(this == rootWindow)
2511          {
2512             if(style.drawBehind || background.a)
2513                surface.Clear(colorBuffer);
2514          }
2515          else if(background.a)
2516          {
2517 #ifdef _DEBUG
2518             /*
2519             background.color = { (byte)GetRandom(0,255), (byte)GetRandom(0,255), (byte)GetRandom(0,255) };
2520             surface.SetForeground((background.color.r > 128 || background.color.g > 128) ? black : white);
2521             */
2522 #endif
2523             if(display.flags.alpha && background.a < 255 && background)
2524             {
2525                surface.Area(0,0,clientSize.w, clientSize.h);
2526                /*if(style.clearDepthBuffer)
2527                   surface.Clear(depthBuffer);*/
2528             }
2529             else if(/*style.clearDepthBuffer || */background.a)
2530             {
2531                // surface.Clear((style.clearDepthBuffer ? depthBuffer : 0) | (background.a ? colorBuffer : 0));
2532                surface.Clear(colorBuffer);
2533             }
2534          }
2535
2536          // Default Settings
2537          surface.TextFont(usedFont.font);
2538          surface.TextOpacity(false);
2539
2540          OnRedraw(surface);
2541
2542          // Draw the caret ...
2543          if(!disabled && this == guiApp.caretOwner && guiApp.caretEnabled /*&& !guiApp.interimWindow*/ && !guiApp.currentSkin.textMode)
2544          {
2545             // surface.SetBackground(0xFFFFFF - background.color);
2546             surface.SetBackground(~background.color);
2547             surface.Area(
2548                caretPos.x - scroll.x + 1, caretPos.y - scroll.y,
2549                caretPos.x - scroll.x + 2, caretPos.y - scroll.y + caretSize - 1);
2550          }
2551          delete surface;
2552       }
2553    }
2554
2555    void DrawOverChildren(Box refresh)
2556    {
2557       Surface surface = Redraw(refresh);               
2558       if(surface) 
2559       {
2560          // Default Settings
2561          surface.DrawingChar(' ');
2562          surface.SetBackground(background);
2563          surface.SetForeground(foreground);
2564
2565          surface.TextFont(usedFont.font);
2566          surface.TextOpacity(false);
2567
2568          OnDrawOverChildren(surface);
2569
2570          delete surface;
2571
2572       }
2573       _ShowDecorations(refresh, true);
2574    }
2575
2576    void ComputeClipExtents(void)
2577    {
2578       Window child;
2579       Extent clipExtent { /*first = -1, last = -1, free = -1*/ };
2580
2581       clipExtent.Copy(this.clipExtent);
2582       
2583       for(child = children.last; child; child = child.prev)
2584       {
2585          if(!child.style.hidden && child.created && !child.is3D && child.rootWindow)
2586          {
2587             bool opaque = child.IsOpaque(); // TODO: acess background directly 
2588             int dx = child.absPosition.x - absPosition.x, dy = child.absPosition.y - absPosition.y;
2589
2590             child.clipExtent.Copy(clipExtent);
2591             child.clipExtent.Offset(-dx, -dy);
2592             child.clipExtent.IntersectBox(child.box);
2593
2594             child.ComputeClipExtents();
2595
2596             if(opaque && !child.style.nonClient)
2597             {
2598                // Adjust the box for the parent:
2599                Box box { child.box.left + dx, child.box.top + dy, child.box.right + dx, child.box.bottom + dy };
2600                clipExtent.ExcludeBox(box, rootWindow.tempExtents[0]);
2601             }
2602             
2603          }
2604       }
2605       // ??? Only do this for overlapped window or if parent has with clip children flag
2606
2607       // Do this if window has clip children flag on (default false?)
2608       // this.clipExtent = clipExtent;
2609
2610       clipExtent.Free(null);
2611    }
2612
2613    void ComputeRenderAreaNonOpaque(Extent dirtyExtent, Extent overDirtyExtent, Extent backBufferUpdate)
2614    {
2615       bool opaque = IsOpaque();
2616       Window child;
2617       int offsetX = absPosition.x - rootWindow.absPosition.x, offsetY = absPosition.y - rootWindow.absPosition.y;
2618       if(rootWindow.nativeDecorations)
2619       {
2620          offsetX -= rootWindow.clientStart.x;
2621          offsetY -= rootWindow.clientStart.y - (rootWindow.hasMenuBar ? skinMenuHeight : 0);
2622       }
2623
2624
2625       for(child = children.last; child; child = child.prev)
2626       {
2627          ColorAlpha background = *(ColorAlpha *)&child.background;
2628          bool opaque = child.IsOpaque();
2629          if(!child.style.hidden && child.created && !child.is3D && child.rootWindow)
2630          {
2631             if(!opaque)
2632             {
2633                // Adjust renderArea to the root window level
2634                Extent * renderArea = &rootWindow.tempExtents[1];
2635
2636                int offsetX = child.absPosition.x - rootWindow.absPosition.x, offsetY = child.absPosition.y - rootWindow.absPosition.y;
2637                if(child.rootWindow.nativeDecorations)
2638                {
2639                   offsetX -= child.rootWindow.clientStart.x;
2640                   offsetY -= child.rootWindow.clientStart.y - (child.rootWindow.hasMenuBar ? skinMenuHeight : 0);
2641                }
2642
2643                /*
2644                Extent childRenderArea;
2645                
2646                if(backBufferUpdate != null)
2647                {
2648                   childRenderArea.Copy(backBufferUpdate);
2649                   childRenderArea.Offset(-offsetX, -offsetY);
2650                }
2651                else
2652                   childRenderArea.Copy(child.dirtyArea);
2653
2654                // Add extent forced by transparency to the dirty area, adjusting dirty extent to the window
2655                renderArea.Copy(dirtyExtent);
2656                renderArea.Offset(-offsetX, -offsetY);
2657                childRenderArea.Union(renderArea);
2658                renderArea.Free();
2659
2660                // Intersect with the clip extent
2661                childRenderArea.Intersection(child.clipExtent);
2662                */
2663
2664                renderArea->Copy(child.dirtyArea /*childRenderArea*/);
2665                renderArea->Offset(offsetX, offsetY);
2666                dirtyExtent.Union(renderArea, rootWindow.tempExtents[0]);
2667                // overDirtyExtent.Union(renderArea);
2668                renderArea->Empty();
2669                // childRenderArea.Free();
2670
2671                //child.ComputeRenderAreaNonOpaque(dirtyExtent, overDirtyExtent, backBufferUpdate);
2672             }
2673          }
2674       }
2675
2676       for(child = children.last; child; child = child.prev)
2677       {
2678          if(!child.style.hidden && child.created && !child.is3D && child.rootWindow)
2679          {
2680             child.ComputeRenderAreaNonOpaque(dirtyExtent, overDirtyExtent, backBufferUpdate);
2681          }
2682       }
2683    }
2684
2685    void ComputeRenderArea(Extent dirtyExtent, Extent overDirtyExtent, Extent backBufferUpdate)
2686    {
2687       bool opaque = IsOpaque();
2688       Extent * dirtyExtentWindow = &rootWindow.tempExtents[1];
2689       Window child;
2690       int offsetX = absPosition.x - rootWindow.absPosition.x, offsetY = absPosition.y - rootWindow.absPosition.y;
2691       if(rootWindow.nativeDecorations)
2692       {
2693          offsetX -= rootWindow.clientStart.x;
2694          offsetY -= rootWindow.clientStart.y - (rootWindow.hasMenuBar ? skinMenuHeight : 0);
2695       }
2696
2697 #if 0
2698       for(child = children.last; child; child = child.prev)
2699       {
2700          //child.ComputeRenderAreaNonOpaque(dirtyExtent, overDirtyExtent, backBufferUpdate);
2701          /*
2702          ColorAlpha background = *(ColorAlpha *)&child.background;
2703          bool opaque = child.IsOpaque();
2704          if(!child.style.hidden && child.created && !child.is3D && child.rootWindow)
2705          {
2706             if(!opaque)
2707             {
2708                int offsetX = child.absPosition.x - rootWindow.absPosition.x, offsetY = child.absPosition.y - rootWindow.absPosition.y;
2709                // Adjust renderArea to the root window level
2710                Extent renderArea;
2711                renderArea.Copy(child.dirtyArea);
2712                renderArea.Offset(offsetX, offsetY);
2713                dirtyExtent.Union(renderArea);
2714                overDirtyExtent.Union(renderArea);
2715                renderArea.Free();
2716             }
2717          }*/
2718       }
2719 #endif
2720       for(child = children.last; child; child = child.prev)
2721       {
2722          if(!child.style.hidden && child.created && !child.is3D && child.rootWindow)
2723          {
2724             child.ComputeRenderArea(dirtyExtent, overDirtyExtent, backBufferUpdate);
2725          }
2726       }
2727
2728       if(backBufferUpdate != null)
2729       {
2730          renderArea.Copy(backBufferUpdate);
2731          renderArea.Offset(-offsetX, -offsetY);
2732          
2733          overRenderArea.Copy(backBufferUpdate);
2734          overRenderArea.Offset(-offsetX, -offsetY);
2735          
2736          
2737       }
2738       else
2739       {
2740          renderArea.Copy(dirtyArea);
2741          
2742          overRenderArea.Copy(dirtyArea);
2743       }
2744
2745       // Add extent forced by transparency to the dirty area, adjusting dirty extent to the window
2746       dirtyExtentWindow->Copy(dirtyExtent);
2747       dirtyExtentWindow->Offset(-offsetX, -offsetY);
2748       renderArea.Union(dirtyExtentWindow, rootWindow.tempExtents[0]);
2749       dirtyExtentWindow->Empty();
2750
2751       // Intersect with the clip extent
2752       renderArea.Intersection(clipExtent, rootWindow.tempExtents[0], rootWindow.tempExtents[1], rootWindow.tempExtents[2]);
2753
2754       /*
2755       if(renderArea.count > 10)
2756       {
2757          BoxItem extentBox;
2758          printf("\nToo many extents (%d):\n", renderArea.count);
2759
2760          //extent.UnionBox({ 112, 6, 304, 7 }, rootWindow.tempExtents[0]);
2761          //extent.UnionBox({ 112, 8, 304, 17 }, rootWindow.tempExtents[0]);
2762          //printf("Test\n");
2763
2764          {
2765             int c;
2766             for(c = 0; c<10; c++)
2767             {
2768                Extent extent { };
2769                FASTLIST_LOOP(renderArea, extentBox)
2770                {
2771                   extent.UnionBox(extentBox.box, rootWindow.tempExtents[0]);
2772                }
2773                renderArea.Copy(extent);
2774
2775                FASTLIST_LOOP(renderArea, extentBox)
2776                {
2777       #ifdef _DEBUG
2778                   printf("(%d, %d) - (%d, %d)\n", 
2779                      extentBox.box.left, extentBox.box.top, 
2780                      extentBox.box.right, extentBox.box.bottom);
2781       #endif
2782                }
2783
2784                printf("\nNow %d\n", renderArea.count);
2785             }
2786          }
2787       }
2788       */
2789       
2790       // WHY WAS THIS COMMENTED ??
2791
2792       // Add extent forced by DrawOverChildren to the dirty area, adjusting dirty extent to the window
2793       dirtyExtentWindow->Copy(overDirtyExtent);
2794       dirtyExtentWindow->Offset(-offsetX, -offsetY);
2795       overRenderArea.Union(dirtyExtentWindow, rootWindow.tempExtents[0]);
2796       dirtyExtentWindow->Empty();
2797
2798       // Intersect with the clip extent
2799       overRenderArea.Intersection(clipExtent, rootWindow.tempExtents[0], rootWindow.tempExtents[1], rootWindow.tempExtents[2]);
2800       
2801
2802       if(opaque)
2803       {
2804          // Scrolling
2805          if(scrollExtent.count)
2806          {
2807             // Subtract render extent from scrolling extent
2808             scrollExtent.Exclusion(renderArea, rootWindow.tempExtents[0]);
2809
2810             if(backBufferUpdate == null)
2811             {
2812                Extent * dirty = &rootWindow.tempExtents[3];
2813                BoxItem scrollBox;
2814
2815                // Intersect scrolling extent with clip extent
2816                scrollExtent.Intersection(clipExtent, rootWindow.tempExtents[0], rootWindow.tempExtents[1], rootWindow.tempExtents[2]);
2817
2818                // offset this scroll to be at the root window level
2819                scrollExtent.Offset(offsetX, offsetY);
2820                // Add area that was scrolled to the dirty extents of the back buffer
2821                rootWindow.dirtyBack.Union(scrollExtent, rootWindow.tempExtents[0]);
2822
2823                dirty->Empty();
2824
2825                // Will need scrolledArea.x & scrolledArea.y to support multiple scrolls
2826                for(scrollBox = (BoxItem)scrollExtent.first; scrollBox; scrollBox = (BoxItem)scrollBox.next)
2827                   display.Scroll(scrollBox.box, scrolledArea.x, scrolledArea.y, dirty);
2828
2829                scrolledArea.x = 0;
2830                scrolledArea.y = 0;
2831
2832                scrollExtent.Empty();
2833
2834                // Add the exposed extent to the window render area
2835                dirty->Offset(-offsetX, -offsetY);
2836                renderArea.Union(dirty, rootWindow.tempExtents[0]);
2837                dirty->Empty();
2838             }
2839          }
2840
2841          // Subtract the window's box from the transparency forced extent
2842          dirtyExtent.ExcludeBox({box.left + offsetX, box.top + offsetY, box.right + offsetX, box.bottom + offsetY }, rootWindow.tempExtents[0]);
2843       }
2844       /*else
2845       {
2846          Extent renderArea;
2847
2848          renderArea.Copy(this.renderArea);
2849          renderArea.Offset(offsetX, offsetY);
2850          dirtyExtent.Union(renderArea);
2851          renderArea.Free();
2852       }*/
2853       
2854       
2855       {
2856          Extent renderArea { };
2857          
2858          renderArea.Copy(overRenderArea);
2859          renderArea.Offset(offsetX, offsetY);
2860          overDirtyExtent.Union(renderArea, rootWindow.tempExtents[0]);
2861          renderArea.Empty();
2862       }
2863       
2864
2865       if(backBufferUpdate != null)
2866       {
2867          // Remove render area from dirty area
2868          dirtyArea.Exclusion(renderArea, rootWindow.tempExtents[0]);
2869
2870          dirtyArea.Exclusion(overRenderArea, rootWindow.tempExtents[0]);
2871       }
2872       else
2873          dirtyArea.Empty();
2874
2875       clipExtent.Empty();
2876    /*
2877       // Remove the window render area from the dirty extents of the back buffer
2878       rootWindow.dirtyBack.Exclusion(renderArea);
2879    */
2880    }
2881
2882    void Render(Extent updateExtent)
2883    {
2884       BoxItem extentBox;
2885       Window child;
2886       Window rootWindow = this.rootWindow;
2887       int offsetX = absPosition.x - rootWindow.absPosition.x, offsetY = absPosition.y - rootWindow.absPosition.y;
2888       if(rootWindow.nativeDecorations)
2889       {
2890          offsetX -= rootWindow.clientStart.x;
2891          offsetY -= rootWindow.clientStart.y - (rootWindow.hasMenuBar ? skinMenuHeight : 0);
2892       }
2893
2894       if(rootWindow.fullRender)
2895       {
2896          UpdateExtent(box);
2897          dirtyArea.Empty();
2898       }
2899       else
2900       {
2901 #ifdef _DEBUG
2902          /*
2903          background = Color { (byte)GetRandom(0,255), (byte)GetRandom(0,255), (byte)GetRandom(0,255) };
2904          foreground = (background.color.r > 128 || background.color.g > 128) ? black : white;
2905          */
2906 #endif
2907             
2908 #ifdef _DEBUG
2909          /*if(renderArea.count)
2910             printf("\n\nRendering %s (%x):\n------------------------------------------\n", _class.name, this);*/
2911 #endif
2912             
2913          for(extentBox = (BoxItem)renderArea.first; extentBox; extentBox = (BoxItem)extentBox.next)
2914          {
2915             Box box = extentBox.box;
2916
2917 #ifdef _DEBUG
2918                /*printf("(%d, %d) - (%d, %d)\n", 
2919                   extentBox.box.left, extentBox.box.top, 
2920                   extentBox.box.right, extentBox.box.bottom);*/
2921 #endif
2922                
2923             UpdateExtent(box);
2924
2925             box.left += offsetX;
2926             box.top += offsetY;
2927             box.right += offsetX;
2928             box.bottom += offsetY;
2929
2930             if(updateExtent != null)
2931                updateExtent.UnionBox(box, rootWindow.tempExtents[0]);
2932          }
2933       }
2934
2935       for(child = children.first; child; child = child.next)
2936          if(!child.style.hidden && child.created && !child.is3D && child.rootWindow && !child.nonClient)
2937             child.Render(updateExtent);
2938
2939       if(rootWindow.fullRender)
2940          DrawOverChildren(box);
2941       else
2942       {
2943          // TO DO: There's an issue about draw over children...
2944          // TO DO: Don't wanna go through this if method isn't used
2945          for(extentBox = (BoxItem)overRenderArea.first; extentBox; extentBox = (BoxItem)extentBox.next)
2946          //FASTLIST_LOOP(/*renderArea */overRenderArea, extentBox)
2947          {
2948             Box box = extentBox.box;
2949
2950             DrawOverChildren(box);
2951
2952             box.left += offsetX;
2953             box.top += offsetY;
2954             box.right += offsetX;
2955             box.bottom += offsetY;
2956
2957             if(updateExtent != null)
2958                updateExtent.UnionBox(box, rootWindow.tempExtents[0]);
2959          }
2960       }
2961       for(child = children.first; child; child = child.next)
2962          if(!child.style.hidden && child.created && !child.is3D && child.rootWindow && child.nonClient)
2963             child.Render(updateExtent);
2964
2965       renderArea.Empty();
2966       overRenderArea.Empty();
2967    }
2968
2969    public void UpdateDisplay(void)
2970    {
2971       if(!manageDisplay) { OnRedraw(null);return; }
2972       if(rootWindow && this != rootWindow) 
2973          rootWindow.UpdateDisplay();
2974       else if(display)
2975       {
2976          Extent dirtyExtent { /*first = -1, last = -1, free = -1*/ };  // Extent that needs to be forced due to transparency
2977          Extent overExtent { /*first = -1, last = -1, free = -1*/ };  // Extent that forced for DrawOverChildren
2978          BoxItem extentBox;
2979
2980          dirtyExtent.Clear();
2981          overExtent.Clear();
2982
2983          clipExtent.AddBox(box);
2984
2985          display.StartUpdate();
2986
2987          if(!rootWindow.fullRender)
2988          {
2989             ComputeClipExtents();
2990             ComputeRenderAreaNonOpaque(dirtyExtent, overExtent, null);
2991             ComputeRenderArea(dirtyExtent, overExtent, null);
2992          }
2993          else
2994             clipExtent.Free(null);                     
2995
2996          dirtyExtent.Free(null);
2997          overExtent.Free(null);
2998
2999          if(display.flags.flipping)
3000          {
3001             Render(null);
3002             display.Update(null);
3003          }
3004          else
3005          {
3006             Extent updateExtent { /*first = -1, last = -1, free = -1*/ }; // Extent that needs to be updated
3007             updateExtent.Clear();
3008
3009             Render(updateExtent);
3010             if(fullRender)
3011                updateExtent.UnionBox(this.box, tempExtents[0]);
3012             
3013 #ifdef _DEBUG
3014             //printf("\n\nUpdate:\n------------------------------------------\n");
3015 #endif
3016             
3017             //FASTLIST_LOOP(updateExtent, extentBox)
3018             for(extentBox = (BoxItem)updateExtent.first; extentBox; extentBox = (BoxItem)extentBox.next)
3019             {
3020 #ifdef _DEBUG
3021                /*printf("Updating (%d, %d) - (%d, %d)\n", 
3022                   extentBox.box.left, extentBox.box.top, 
3023                   extentBox.box.right, extentBox.box.bottom);*/
3024 #endif
3025                
3026                display.Update(extentBox.box);
3027                
3028             }
3029             updateExtent.Free(null);
3030          }
3031
3032          display.EndUpdate();
3033          dirtyBack.Empty();
3034
3035          dirty = false;
3036          resized = false;
3037       }
3038    }
3039
3040    void UpdateBackDisplay(Box box)
3041    {
3042       if(display)
3043       {
3044          Extent dirtyExtent;
3045          Extent overExtent;
3046          Extent intersection { /*first = -1, last = -1, free = -1*/ };
3047
3048          //printf("UpdateBackDisplay going through!\n");
3049          display.StartUpdate();
3050
3051          if(resized)
3052          {
3053             intersection.Copy(dirtyBack);
3054             intersection.IntersectBox(box);
3055          
3056             dirtyExtent.Clear();
3057             overExtent.Clear();
3058
3059             clipExtent.AddBox(box);
3060          
3061             if(!rootWindow.fullRender)
3062             {
3063                ComputeClipExtents();
3064                ComputeRenderArea(dirtyExtent, overExtent, intersection);
3065             }
3066             else
3067                clipExtent.Free(null);
3068
3069             intersection.Free(null);
3070             dirtyExtent.Free(null);
3071             overExtent.Free(null);
3072
3073             Render(null);
3074          }
3075
3076          if(display.flags.flipping)
3077             display.Update(null);
3078          else
3079          {
3080             rootWindow.display.Update(box);
3081          }
3082
3083          display.EndUpdate();
3084
3085          if(resized)
3086          {
3087             dirtyBack.ExcludeBox(box, rootWindow.tempExtents[0]);
3088             if(dirtyBack.count > MAX_DIRTY_BACK)
3089             {
3090                BoxItem extentBox, next;
3091                BoxItem first = (BoxItem)ACCESS_ITEM(dirtyBack, dirtyBack.first);
3092                for(extentBox = (BoxItem)dirtyBack.first; extentBox; extentBox = next)
3093                {
3094                   next = (BoxItem)extentBox.next;
3095                   if(extentBox != first)
3096                   {
3097                      if(extentBox.box.left < first.box.left)
3098                         first.box.left = extentBox.box.left;
3099                      if(extentBox.box.top < first.box.top)
3100                         first.box.top = extentBox.box.top;
3101                      if(extentBox.box.right > first.box.right)
3102                         first.box.right = extentBox.box.right;
3103                      if(extentBox.box.bottom > first.box.bottom)
3104                         first.box.bottom = extentBox.box.bottom;
3105                      dirtyBack.Delete(extentBox);
3106                   }
3107                }
3108             }
3109             resized = false;
3110          }
3111       }
3112    }
3113
3114    // --- Window positioning ---
3115    // --- Window identification ---
3116
3117    // Returns window at position "Position"
3118    Window GetAtPosition(int x, int y, bool clickThru, bool acceptDisabled, Window last)
3119    {
3120       Window child, result = null;
3121       Box box = this.box;
3122       box.left += absPosition.x;
3123       box.right += absPosition.x;
3124       box.top += absPosition.y;
3125       box.bottom += absPosition.y;
3126
3127       if(!destroyed && visible && (acceptDisabled || !disabled))
3128       {
3129          int lx = x - absPosition.x;
3130          int ly = y - absPosition.y;
3131          if(IsInside(lx, ly))
3132          // if(box.IsPointInside(Point{x, y}))
3133          {
3134             if(!clickThru || !style.clickThrough) result = (this == last) ? null : this;
3135             // If the window is disabled, stop looking in children (for acceptDisabled mode)
3136             if(!disabled)
3137             {
3138                for(child = (last && last.parent == this) ? last.previous : children.last; child; child = child.prev)
3139                {
3140                   if(child != statusBar && child.rootWindow == rootWindow)
3141                   {
3142                      Window childResult = child.GetAtPosition(x, y, clickThru, acceptDisabled, last);
3143                      if(childResult) 
3144                         return childResult;
3145                   }
3146                }
3147                if(clickThru)
3148                {
3149                   for(child = (last && last.parent == this) ? last.previous : children.last; child; child = child.prev)
3150                   {
3151                      if(child != statusBar && child.rootWindow == rootWindow)
3152                      {
3153                         Window childResult = child.GetAtPosition(x, y, false, acceptDisabled, last);
3154                         if(childResult)
3155                            return childResult;
3156                      }
3157                   }
3158                }
3159             }
3160          }
3161       }
3162       return result;
3163    }
3164
3165    Window FindModal(void)
3166    {
3167       Window modalWindow = this, check;
3168       Window check2 = null;
3169       for(check = this; check.master; check = check.master)
3170       {
3171          if(check.master.modalSlave && check.master.modalSlave.created && check != check.master.modalSlave)
3172          {
3173             modalWindow = check.master.modalSlave;
3174             check = modalWindow;
3175          }
3176          // TESTING THIS FOR DROPBOX...
3177          if(!rootWindow || !rootWindow.style.interim)
3178          {
3179             for(check2 = check; check2.activeChild; check2 = check2.activeChild)
3180             {
3181                if(check2.modalSlave && check2.modalSlave.created)
3182                {
3183                   modalWindow = check2.modalSlave;
3184                   break;
3185                }
3186             }
3187          }
3188       }
3189
3190       /*
3191       if(modalWindow == this)
3192       {
3193          for(check = this; check.activeChild; check = check.activeChild)
3194          {
3195             if(check.modalSlave)
3196             {
3197                modalWindow = check.modalSlave;
3198                break;
3199             }
3200          }
3201       }
3202       */
3203       for(; modalWindow.modalSlave && modalWindow.modalSlave.created; modalWindow = modalWindow.modalSlave);
3204       return (modalWindow == this || this == guiApp.interimWindow || IsDescendantOf(modalWindow)) ? null : modalWindow;
3205    }
3206
3207    void StopMoving(void)
3208    {
3209       if(this == guiApp.windowMoving)
3210       {
3211          guiApp.windowMoving = null;
3212          UpdateDecorations();
3213          SetMouseRange(null);
3214          if(rootWindow)
3215          {
3216             if(rootWindow.active)
3217                guiApp.interfaceDriver.StopMoving(rootWindow);
3218          }
3219          ReleaseCapture();
3220          guiApp.resizeX = guiApp.resizeY = guiApp.resizeEndX = guiApp.resizeEndY = false;
3221          guiApp.windowIsResizing = false;
3222       }
3223    }
3224
3225    void SelectMouseCursor(void)
3226    {
3227       int x,y;
3228       Window mouseWindow;
3229       Window modalWindow;
3230       Window cursorWindow = null;
3231       bool rx, ry, rex, rey;
3232
3233       guiApp.desktop.GetMousePosition(&x, &y);
3234       mouseWindow = rootWindow ? rootWindow.GetAtPosition(x,y, true, false, null) : null;
3235
3236       if((guiApp.windowMoving && !guiApp.windowIsResizing) || guiApp.windowScrolling)
3237          guiApp.SetCurrentCursor(guiApp.systemCursors[moving]);
3238       else if(mouseWindow)
3239       {
3240          modalWindow = mouseWindow.FindModal();
3241          x -= mouseWindow.absPosition.x;
3242          y -= mouseWindow.absPosition.y;
3243          if(guiApp.windowIsResizing)
3244          {
3245             rex = guiApp.resizeEndX;
3246             rey = guiApp.resizeEndY;
3247             rx = guiApp.resizeX;
3248             ry = guiApp.resizeY;
3249             if((rex && rey) || (rx && ry))
3250                guiApp.SetCurrentCursor(guiApp.systemCursors[sizeNWSE]);
3251             else if((rex && ry) || (rx && rey))
3252                guiApp.SetCurrentCursor(guiApp.systemCursors[sizeNESW]);
3253             else if((ry || rey) && (!rx && !rex))
3254                guiApp.SetCurrentCursor(guiApp.systemCursors[sizeNS]);
3255             else if((rx || rex) && (!ry && !rey))
3256                guiApp.SetCurrentCursor(guiApp.systemCursors[sizeWE]);
3257          }
3258          else if(!modalWindow && !guiApp.windowCaptured &&
3259             mouseWindow.IsMouseResizing(x, y, mouseWindow.size.w, mouseWindow.size.h,
3260                &rx, &ry, &rex, &rey))
3261          {
3262             if((rex && rey) || (rx && ry))
3263                guiApp.SetCurrentCursor(guiApp.systemCursors[sizeNWSE]);
3264             else if((rex && ry) || (rx && rey))
3265                guiApp.SetCurrentCursor(guiApp.systemCursors[sizeNESW]);
3266             else if((ry || rey) && (!rx && !rex))
3267                guiApp.SetCurrentCursor(guiApp.systemCursors[sizeNS]);
3268             else if((rx || rex) && (!ry && !rey))
3269                guiApp.SetCurrentCursor(guiApp.systemCursors[sizeWE]);
3270          }
3271          else if(!guiApp.windowCaptured && !modalWindow && !guiApp.interimWindow)
3272          {
3273             if(!mouseWindow.clientArea.IsPointInside({x - mouseWindow.clientStart.x, y - mouseWindow.clientStart.y}))
3274                cursorWindow = mouseWindow.parent;
3275             else
3276                cursorWindow = mouseWindow;
3277          }
3278          else if(!guiApp.interimWindow)
3279             cursorWindow = guiApp.windowCaptured;
3280          if(cursorWindow)
3281          {
3282             for(; !cursorWindow.cursor && !cursorWindow.style.nonClient; cursorWindow = cursorWindow.parent);
3283             guiApp.SetCurrentCursor(cursorWindow.cursor ? cursorWindow.cursor : guiApp.systemCursors[arrow]);
3284          }
3285          else if(modalWindow)
3286          {
3287             guiApp.SetCurrentCursor(guiApp.systemCursors[arrow]);
3288          }
3289          else if(guiApp.interimWindow)
3290          {
3291             if(guiApp.interimWindow.cursor)
3292                guiApp.SetCurrentCursor(guiApp.interimWindow.cursor);
3293             else
3294                guiApp.SetCurrentCursor(mouseWindow.cursor ? mouseWindow.cursor : guiApp.systemCursors[arrow]);
3295          }
3296       }
3297    }
3298
3299    // --- State based input ---
3300    bool AcquireInputEx(bool state)
3301    {
3302       bool result;
3303       if(state) 
3304       {
3305          guiApp.interfaceDriver.GetMousePosition(&guiApp.acquiredMouseX, &guiApp.acquiredMouseY);
3306          guiApp.interfaceDriver.SetMousePosition(clientSize.w/2 + absPosition.x, clientSize.h/2 + absPosition.y);
3307       }
3308       result = guiApp.interfaceDriver.AcquireInput(rootWindow, state);
3309       if(result)
3310          guiApp.acquiredWindow = state ? this : null;
3311       if(state && result)
3312       {
3313          SetMouseRangeToClient();
3314          guiApp.interfaceDriver.SetMouseCursor((SystemCursor)-1);
3315       }
3316       else
3317       {
3318          FreeMouseRange();
3319          SelectMouseCursor();
3320       }
3321       if(!state) guiApp.interfaceDriver.SetMousePosition(guiApp.acquiredMouseX, guiApp.acquiredMouseY);
3322       return result;
3323    }
3324
3325    // --- Window activation ---
3326    bool PropagateActive(bool active, Window previous, bool * goOnWithActivation, bool direct)
3327    {
3328       bool result = true;
3329       if(!parent || !parent.style.inactive)
3330       {
3331          Window parent = this.parent;
3332
3333          /*
3334          if(rootWindow == this)
3335             Log(active ? "active\n" : "inactive\n");
3336          */
3337
3338          // Testing this here...
3339          if(!parent || parent == guiApp.desktop || parent.active)
3340          {
3341             this.active = active;
3342          }
3343
3344          // TESTING THIS HERE
3345          UpdateDecorations();
3346          if(result = OnActivate(active, previous, goOnWithActivation, direct) && *goOnWithActivation && master)
3347             result = NotifyActivate(master, this, active, previous);
3348          else
3349          {
3350             this.active = !active;
3351          }
3352
3353          if(result)
3354          {
3355             if(!parent || parent == guiApp.desktop || parent.active)
3356             {
3357                this.active = active;
3358                if(acquiredInput)
3359                   AcquireInputEx(active);
3360                if(active)
3361                {
3362                   if(caretSize)
3363                   {
3364                      if(guiApp.caretOwner)
3365                      {
3366                         Box extent 
3367                         {
3368                            guiApp.caretOwner.caretPos.x - guiApp.caretOwner.scroll.x + 1, 
3369                            guiApp.caretOwner.caretPos.y - guiApp.caretOwner.scroll.y + 1,
3370                            guiApp.caretOwner.caretPos.x - guiApp.caretOwner.scroll.x + 2, 
3371                            guiApp.caretOwner.caretPos.y - guiApp.caretOwner.scroll.y + guiApp.caretOwner.caretSize - 1
3372                         };
3373                         guiApp.caretOwner.Update(extent);
3374                      }
3375
3376                      if(visible || !guiApp.caretOwner)
3377                         guiApp.caretOwner = this;
3378                      UpdateCaret(false, false);
3379                   }
3380                }
3381             }
3382             else
3383             {
3384                this.active = false;
3385                if(acquiredInput)
3386                   AcquireInputEx(active);
3387             }
3388             if(!active && guiApp.caretOwner == this)
3389             {
3390                UpdateCaret(false, true);
3391                guiApp.caretOwner = null;
3392                guiApp.interfaceDriver.SetCaret(0,0,0);
3393                guiApp.caretEnabled = false;
3394             }
3395
3396             if(!style.interim)
3397             {
3398                if(!active && parent && parent.activeChild && parent.activeChild != this)
3399                   if(!parent.activeChild.PropagateActive(false, previous, goOnWithActivation, true) || !*goOnWithActivation)
3400                   {
3401                      return false;
3402                   }
3403             }
3404
3405             if(!active && menuBar)
3406             {
3407                bool goOn;
3408                menuBar.OnActivate(false, null, &goOn, true);
3409                menuBar.NotifyActivate(menuBar.master, menuBar, false, null);
3410             }
3411
3412             if(activeChild)
3413                if(!activeChild.PropagateActive(active, previous, goOnWithActivation, false) || !*goOnWithActivation)
3414                {
3415                   return false;
3416                }
3417          }
3418       }
3419       return result;
3420    }
3421
3422    void ConsequentialMouseMove(bool kbMoving)
3423    {
3424       if(rootWindow)
3425       {
3426          if(kbMoving || !guiApp.windowMoving)
3427          {
3428             Modifiers mods {};
3429             int x,y;
3430             if(rootWindow == guiApp.desktop || rootWindow.parent == guiApp.desktop)
3431             {
3432                guiApp.interfaceDriver.GetMousePosition(&x, &y);
3433
3434                if(guiApp.windowMoving || rootWindow.GetAtPosition(x, y, true, false, null))
3435                   rootWindow.MouseMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMouseMove, x, y, &mods, true, false);
3436             }
3437          }
3438       }
3439    }
3440
3441    bool IsDescendantOf(Window ancestor)
3442    {
3443       Window window;
3444       for(window = this; window && window != ancestor; window = window.parent);
3445       return window == ancestor;
3446    }
3447
3448    bool IsSlaveOf(Window master)
3449    {
3450       Window window;
3451       for(window = this; window && window != master; window = window.master);
3452       return window == master;
3453    }
3454
3455    bool ActivateEx(bool active, bool activateParent, bool moveInactive, bool activateRoot, Window external, Window externalSwap)
3456    {
3457       bool result = true;
3458
3459       if(this && !destroyed /*&& state != Hidden*/)
3460       {
3461          Window swap = externalSwap;
3462
3463          incref this;
3464
3465          if(parent)
3466          {
3467             if(!active)
3468                StopMoving();
3469             if(activateParent && 
3470                (parent.activeChild != this || 
3471                (guiApp.interimWindow && !IsDescendantOf(guiApp.interimWindow))) &&
3472                active && _isModal &&
3473                parent != master && master)
3474                master.ActivateEx(true, true, false, activateRoot, external, externalSwap);
3475
3476             if(active)
3477             {
3478                if(parent)
3479                {
3480                   bool real = parent.activeChild != this;
3481
3482                   // TEST THIS: New activateParent check here!!! CAUSED MENUS NOT GOING AWAY
3483                   if(/*activateParent && */guiApp.interimWindow && 
3484                      !IsDescendantOf(guiApp.interimWindow) && 
3485                      !IsSlaveOf(guiApp.interimWindow))
3486                   {
3487                      Window interimWindow = guiApp.interimWindow;
3488                      while(interimWindow && interimWindow != this)
3489                      {
3490                         Window master = interimWindow.master;
3491                         bool goOn = true;
3492                         guiApp.interimWindow = null;
3493                         if(guiApp.caretOwner)
3494                            guiApp.caretOwner.UpdateCaret(false, false);
3495
3496                         incref interimWindow;
3497                         if(!interimWindow.PropagateActive(false, this, &goOn, true))
3498                         {
3499                            result = false;
3500                            real = false;
3501                         }
3502                         delete interimWindow;
3503                         interimWindow = (master && master.style.interim) ? master : null;
3504                      }
3505                   }
3506                   if(style.interim)
3507                   {
3508                      guiApp.interimWindow = this;
3509                      /*guiApp.interfaceDriver.SetCaret(0,0,0);
3510                      guiApp.caretEnabled = false;*/
3511                      UpdateCaret(false, true);
3512                   }
3513
3514                   if(real)
3515                   {
3516                      bool acquireInput = false;
3517                      bool maximize =
3518                         parent.activeChild &&
3519                         parent.activeChild.state == maximized &&
3520                         parent != guiApp.desktop;
3521
3522                      if(!style.inactive) // (!style.isRemote || parent.active || parent.style.hidden))
3523                      {
3524                         if(!style.interim)
3525                         {
3526                            if(!swap && parent)
3527                               swap = parent.activeChild;
3528                            if(swap && swap.destroyed) swap = null;
3529                            if(swap && swap != this)
3530                            {
3531                               bool goOn = true;
3532                               if(!swap.PropagateActive(false, this, &goOn, true))
3533                                  swap = parent.activeChild;
3534                               if(!goOn)
3535                               {
3536                                  delete this;
3537                                  return false;
3538                               }
3539                            }
3540                            else
3541                               swap = null;
3542                         }
3543
3544                         if(!parent || parent.activeChild != this || style.interim)
3545                         {
3546                            bool goOn = true;
3547                            result = PropagateActive(true, swap, &goOn, true);
3548                            if(!result && !goOn) 
3549                            {
3550                               delete this;
3551                               return false;
3552                            }
3553                            acquireInput = true;
3554                         }
3555                      }
3556
3557                      if(style.hasMaximize && parent != guiApp.desktop)
3558                      {
3559                         if(maximize)
3560                            SetState(maximized, false, 0);
3561                         else if(state != maximized)
3562                         {
3563                            Window child;
3564                            for(child = parent.children.first; child; child = child.next)
3565                            {
3566                               if(this != child && child.state == maximized)
3567                                  child.SetState(normal, false, 0);
3568                            }
3569                         }
3570                      }
3571                   }
3572                   if(result)
3573                   {
3574                      if(!style.inactive && !style.interim /*&& (!style.isRemote || parent.active || parent.style.hidden)*/)
3575                      {
3576                         Window previous = parent.activeClient;
3577                         parent.activeChild = this;
3578                         if(!style.nonClient /*&& style.isActiveClient*/)
3579                         {
3580                            if(style.isActiveClient && !style.hidden)
3581                               parent.activeClient = this;
3582                            parent.UpdateActiveDocument(previous);
3583                         }
3584                      }
3585                   }
3586
3587                   //if(!style.isRemote)
3588                   {
3589                      if(rootWindow != this)
3590                      {
3591                         if(activateParent && parent && !parent.active /*parent != parent.parent.activeChild*/)
3592                            parent.ActivateEx(true, true, moveInactive, activateRoot, external, externalSwap);
3593                      }
3594                      else if(!guiApp.fullScreenMode)
3595                      {
3596                         Window modalRoot = FindModal();
3597                         if(!modalRoot) modalRoot = this;
3598                         if(!modalRoot.isForegroundWindow)
3599                         {
3600                            modalRoot.isForegroundWindow = true;
3601                            // To check : Why is parent null?
3602                            if(activateRoot && modalRoot.parent && !modalRoot.parent.display && external != modalRoot)
3603                            {
3604                               guiApp.interfaceDriver.ActivateRootWindow(modalRoot);
3605                            }
3606                            modalRoot.isForegroundWindow = false;
3607                         }
3608                      }
3609                   }
3610                
3611                   if(result && real && (!style.inactive || moveInactive) && parent)
3612                   {
3613                      Window last = parent.children.last;
3614
3615                      if(!style.stayOnTop)
3616                         for(; last && last.style.stayOnTop; last = last.prev);
3617                      
3618                      parent.children.Move(this, last);
3619
3620                      // Definitely don't want that:   why not?
3621                      Update(null);
3622
3623                      if(order)
3624                         parent.childrenOrder.Move(order, parent.childrenOrder.last);
3625                   }
3626                }
3627             }
3628             else 
3629             {
3630                if(!parent || style.interim || (parent.activeChild == this && !style.inactive))
3631                {
3632                   bool goOn = true;
3633                   if(!style.interim)
3634                   {
3635                      if(parent)
3636                      {
3637                         parent.activeChild = null;
3638                         if(!style.nonClient /*&& style.isActiveClient*/)
3639                         {
3640                            Window previous = parent.activeClient;
3641                            if(style.isActiveClient)
3642                               parent.activeClient = null;
3643                            parent.UpdateActiveDocument(previous);
3644                         }
3645                      }
3646                   }
3647                   if(this == guiApp.interimWindow)
3648                   {
3649                      guiApp.interimWindow = null;
3650                      if(guiApp.caretOwner)
3651                         guiApp.caretOwner.UpdateCaret(false, false);
3652                   }
3653                   if(!PropagateActive(false, externalSwap, &goOn, true) || !goOn)
3654                   {
3655                      delete this;
3656                      return false;
3657                   }
3658                }
3659             }
3660             if(!active || !swap)
3661                UpdateDecorations();
3662             if(swap)
3663                swap.UpdateDecorations();
3664
3665             if(active && rootWindow != this)
3666                ConsequentialMouseMove(false);
3667          }
3668          delete this;
3669       }
3670       return true;
3671    }
3672
3673    // --- Input Messages ---
3674    void ::UpdateMouseMove(int mouseX, int mouseY, bool consequential)
3675    {
3676       static bool reEntrancy = false;
3677       if(reEntrancy) return;
3678
3679       reEntrancy = true;
3680
3681       guiApp.cursorUpdate = true;
3682       if(guiApp.windowScrolling && !consequential)
3683       {
3684          guiApp.windowScrolling.SetScrollPosition(
3685             (guiApp.windowScrolling.sbh) ? 
3686                (guiApp.windowScrollingBefore.x - mouseX + guiApp.windowScrollingStart.x) : 0,
3687             (guiApp.windowScrolling.sbv) ? 
3688                (guiApp.windowScrollingBefore.y - mouseY + guiApp.windowScrollingStart.y) : 0);
3689       }
3690       if(guiApp.windowMoving)
3691       {
3692          if(mouseX != guiApp.movingLast.x || mouseY != guiApp.movingLast.y)
3693          {
3694             Window window = guiApp.windowMoving;
3695             int rx, ry;
3696             int w = window.size.w;
3697             int h = window.size.h;
3698             int aw, ah;
3699             MinMaxValue ew, eh;
3700             int x, y;
3701
3702             rx = mouseX - guiApp.windowMovingStart.x;
3703             ry = mouseY - guiApp.windowMovingStart.y;
3704
3705             // Size
3706             window.GetDecorationsSize(&ew, &eh);
3707
3708             if(guiApp.windowIsResizing)
3709             {
3710                x = window.scrolledPos.x;
3711                y = window.scrolledPos.y;
3712
3713                if(guiApp.resizeX)
3714                {
3715                   aw = Max(guiApp.windowResizingBefore.w - rx,window.skinMinSize.w);
3716                   rx = guiApp.windowResizingBefore.w - aw;
3717                   rx = Min(guiApp.windowMovingBefore.x + rx, window.parent.clientSize.w-1) - guiApp.windowMovingBefore.x;
3718                   w = guiApp.windowResizingBefore.w - rx;
3719                }
3720                if(guiApp.resizeY)
3721                {
3722                   ah = Max(guiApp.windowResizingBefore.h - ry,window.skinMinSize.h);
3723                   ry = guiApp.windowResizingBefore.h - ah;
3724                   ry = Min(guiApp.windowMovingBefore.y + ry, window.parent.clientSize.h-1) - guiApp.windowMovingBefore.y;
3725                   ry = Max(ry, -guiApp.windowMovingBefore.y);
3726                   h = guiApp.windowResizingBefore.h - ry;
3727                }
3728                if(guiApp.resizeEndX)
3729                {
3730                   w = guiApp.windowResizingBefore.w + rx;
3731                   w = Max(w,1-x);
3732                }
3733                if(guiApp.resizeEndY) h = guiApp.windowResizingBefore.h + ry;
3734
3735                w -= ew;
3736                h -= eh;
3737
3738                w = Max(w, 1);
3739                h = Max(h, 1);
3740
3741                w = Max(w, window.minSize.w);
3742                h = Max(h, window.minSize.h);
3743                w = Min(w, window.maxSize.w);
3744                h = Min(h, window.maxSize.h);
3745
3746                if(!window.OnResizing(&w, &h))
3747                {
3748                   w = window.clientSize.w;
3749                   h = window.clientSize.h;
3750                }
3751
3752                w = Max(w, window.skinMinSize.w);
3753                h = Max(h, window.skinMinSize.h);
3754
3755                w += ew;
3756                h += eh;
3757
3758                if(guiApp.textMode)
3759                {
3760                   SNAPDOWN(w, textCellW);
3761                   SNAPDOWN(h, textCellH);
3762                }
3763
3764                if(guiApp.resizeX)
3765                {
3766                   aw = Max(w,window.skinMinSize.w);
3767                   rx = guiApp.windowResizingBefore.w - aw;
3768                   rx = Min(guiApp.windowMovingBefore.x + rx, window.parent.clientSize.w-1) - guiApp.windowMovingBefore.x;
3769                   w = guiApp.windowResizingBefore.w - rx;
3770                }
3771                if(guiApp.resizeY)
3772                {
3773                   ah = Max(h,window.skinMinSize.h);
3774                   ry = guiApp.windowResizingBefore.h - ah;
3775                   ry = Min(guiApp.windowMovingBefore.y + ry, window.parent.clientSize.h-1) - guiApp.windowMovingBefore.y;
3776                   ry = Max(ry, -guiApp.windowMovingBefore.y);
3777                   h = guiApp.windowResizingBefore.h - ry;
3778                }
3779             }
3780          
3781             // Position
3782             if(!guiApp.windowIsResizing || guiApp.resizeX)
3783                x = guiApp.windowMovingBefore.x + rx;
3784             if(!guiApp.windowIsResizing || guiApp.resizeY)
3785                y = guiApp.windowMovingBefore.y + ry;
3786
3787             if(!guiApp.windowIsResizing)
3788             {
3789                // Limit
3790                if(window.parent == guiApp.desktop && guiApp.virtualScreen.w)
3791                {
3792                   x = Min(x, (guiApp.virtualScreen.w + guiApp.virtualScreenPos.x) -1);
3793                   y = Min(y, (guiApp.virtualScreen.h + guiApp.virtualScreenPos.y) -1);
3794                   x = Max(x,-(w-1) + guiApp.virtualScreenPos.x);
3795                   y = Max(y,-(h-1) + guiApp.virtualScreenPos.y);
3796                }
3797                else
3798                {
3799                   x = Min(x, (window.parent.reqScrollArea.w ? window.parent.reqScrollArea.w : window.parent.clientSize.w) -1);
3800                   y = Min(y, (window.parent.reqScrollArea.h ? window.parent.reqScrollArea.h : window.parent.clientSize.h) -1);
3801                   x = Max(x,-(w-1));
3802                   y = Max(y,-(h-1));
3803                }
3804             }
3805
3806             if(!guiApp.windowIsResizing || (guiApp.resizeX || guiApp.resizeY))
3807             {
3808                if(!window.OnMoving(&x, &y, w, h))
3809                {
3810                   x = window.scrolledPos.x;
3811                   y = window.scrolledPos.y;
3812                }
3813             }
3814
3815             if(guiApp.textMode)
3816             {
3817                SNAPDOWN(x, textCellW);
3818                SNAPDOWN(y, textCellH);
3819             }
3820
3821             if(!window.style.nonClient)
3822             {
3823                if(!window.style.fixed /*|| window.style.isDocument*/)
3824                {
3825                   if(!window.style.dontScrollHorz)
3826                      x += window.parent.scroll.x;
3827                   if(!window.style.dontScrollVert)
3828                      y += window.parent.scroll.y;
3829                }
3830             }
3831
3832             // Break the anchors for moveable/resizable windows
3833             // Will probably cause problem with IDE windows... Will probably need a way to specify if anchors should break
3834             if(window.style.fixed) 
3835             {
3836                if(window.state == normal)
3837                {
3838                   window.normalAnchor = Anchor { left = x, top = y };
3839                   window.normalSizeAnchor = SizeAnchor { { w, h } };
3840                   window.anchored = false;
3841                }
3842             }
3843
3844             window.stateAnchor = Anchor { left = x, top = y };
3845             window.stateSizeAnchor = SizeAnchor { { w, h } };
3846
3847             window.Position(x, y, w, h, false, true, guiApp.windowIsResizing, guiApp.windowIsResizing, false, true);
3848             // TOCHECK: Investigate why the following only redraws the scrollbars
3849             //window.Position(x, y, w, h, false, true, true, true, false, true);
3850
3851             guiApp.movingLast.x = mouseX;
3852             guiApp.movingLast.y = mouseY;
3853          }
3854       }
3855       reEntrancy = false;
3856    }
3857
3858    public bool MouseMessage(uint method, int x, int y, Modifiers * mods, bool consequential, bool activate)
3859    {
3860       bool result = true;
3861       bool wasMoving = guiApp.windowMoving ? true : false;
3862       bool wasScrolling = guiApp.windowScrolling ? true : false;
3863       Window w = null;
3864       while(result && w != this)
3865       {
3866          Window msgWindow = GetAtPosition(x,y, false, true, w);
3867          Window trueWindow = GetAtPosition(x,y, false, false, w);
3868          bool windowDragged = false;
3869          Window window;
3870          delete w;
3871          w = msgWindow;
3872          if(w) incref w;
3873          window = (w && !w.disabled) ? w : null;
3874          
3875          if(trueWindow) incref trueWindow;
3876
3877          if(consequential) mods->isSideEffect = true;
3878
3879          UpdateMouseMove(x, y, consequential);
3880
3881          if(guiApp.windowCaptured && (guiApp.windowCaptured.rootWindow == this))
3882          {
3883             if(!guiApp.windowCaptured.isEnabled)
3884                guiApp.windowCaptured.ReleaseCapture();
3885             else
3886                window = guiApp.windowCaptured;
3887          }
3888
3889          if(trueWindow && activate &&
3890             (method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonDown ||
3891              method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonDown ||
3892              method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonDown ||
3893              method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftDoubleClick))
3894          {
3895             if(mods->alt && !mods->ctrl && !mods->shift)
3896             {
3897                Window moved = trueWindow;
3898                for(moved = trueWindow; moved; moved = moved.parent)
3899                   if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonDown || ((moved.style.fixed || moved.moveable) && moved.state != maximized)) 
3900                      break;
3901                if(moved) 
3902                {
3903                   window = moved;
3904                   windowDragged = true;
3905
3906                   // Cancel the ALT menu toggling...
3907                   window.rootWindow.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown, 0, 0);
3908                }
3909             }
3910          }
3911
3912          if(window && activate &&
3913             (method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonDown ||
3914              method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonDown ||
3915              method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonDown ||
3916              method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftDoubleClick))
3917          {
3918             Window modalWindow = window.FindModal();
3919
3920             /*if(mods->alt && !mods->shift && !mods->ctrl)
3921             {
3922                Window moved = window;
3923                for(moved = window; moved; moved = moved.parent)
3924                   if(method == OnRightButtonDown || ((moved.style.fixed || moved.moveable) && moved.state != maximized)) 
3925                      break;
3926                if(moved) 
3927                {
3928                   window = moved;
3929                   windowDragged = true;
3930
3931                   // Cancel the ALT menu toggling...
3932                   window.rootWindow.KeyMessage(OnKeyDown, 0, 0);
3933                }
3934             }*/
3935
3936             if(!windowDragged)
3937             {
3938                Window activateWindow = modalWindow ? modalWindow : window;
3939                if(activateWindow && !activateWindow.isRemote)
3940                {
3941                   bool doActivation = true;
3942                   //bool needToDoActivation = false;
3943                   Window check = activateWindow;
3944
3945                   for(check = activateWindow; check && check != guiApp.desktop; check = check.parent)
3946                   {
3947                      if(!check.style.inactive)
3948                      {
3949                         //needToDoActivation = true;
3950                         if(check.active)
3951                            doActivation = false;
3952                         break;
3953                      }
3954                   }
3955                   /*
3956                   if(!needToDoActivation)
3957                      doActivation = false;
3958                   */
3959
3960                   if((doActivation && (activateWindow.parent != guiApp.desktop || guiApp.fullScreen)) || 
3961                      (guiApp.interimWindow && !window.IsDescendantOf(guiApp.interimWindow)))
3962                   {
3963                      // Let the OnLeftButtonDown do the activating instead
3964                      if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftDoubleClick)
3965                      {
3966                         window = null;
3967                         result = true;
3968                      }
3969                      else
3970                      //if(activate)
3971                      {
3972                         incref activateWindow;
3973                         if(!activateWindow.ActivateEx(true, true, false, true, null, null))
3974                         {
3975                            delete activateWindow;
3976                            delete trueWindow;
3977                            return false;
3978                         }
3979                         if(activateWindow._refCount == 1)
3980                         {
3981                            delete activateWindow;
3982                            delete trueWindow;
3983                            return false;
3984                         }
3985                         delete activateWindow;
3986                      }
3987                      mods->isActivate = true;
3988                   }
3989                }
3990             }
3991             if(!modalWindow && window && !window.destroyed)
3992             {
3993                if(!guiApp.windowCaptured || windowDragged)
3994                {
3995                   if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonDown)
3996                   {
3997                      bool moving = ((window.state != maximized &&
3998                            window.IsMouseMoving(
3999                         x - window.absPosition.x, y - window.absPosition.y, window.size.w, window.size.h)))
4000                         || (guiApp.windowMoving && !guiApp.windowIsResizing);
4001
4002                      if(!moving && window.IsMouseResizing(
4003                         x - window.absPosition.x,
4004                         y - window.absPosition.y,
4005                         window.size.w, window.size.h,
4006                         &guiApp.resizeX, &guiApp.resizeY, &guiApp.resizeEndX, &guiApp.resizeEndY))
4007                      {
4008                         guiApp.windowIsResizing = true;
4009                         guiApp.windowResizingBefore.w = window.size.w;
4010                         guiApp.windowResizingBefore.h = window.size.h;
4011                      }
4012                      if(guiApp.windowIsResizing || windowDragged || moving)
4013                      {
4014                         window.Capture();
4015                         guiApp.windowMoving = window;
4016                         guiApp.windowMovingStart.x = guiApp.movingLast.x = x;
4017                         guiApp.windowMovingStart.y = guiApp.movingLast.y = y;
4018                         guiApp.windowMovingBefore.x = window.position.x;//s;
4019                         guiApp.windowMovingBefore.y = window.position.y;//s;
4020                         if(guiApp.windowMoving == guiApp.windowMoving.rootWindow)
4021                            guiApp.interfaceDriver.StartMoving(guiApp.windowMoving.rootWindow, 0,0,false);
4022                      }
4023                   }
4024                   else if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonDown)
4025                   {
4026                      if(window.style.fixed &&
4027                         (windowDragged || 
4028                         window.IsMouseMoving(
4029                            x - window.absPosition.x, y - window.absPosition.y, window.size.w, window.size.h)))
4030                      {
4031                         window.ShowSysMenu(x, y);
4032                         result = false;
4033                      }
4034                   }
4035                   else if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonDown)
4036                   {
4037                      if(window.sbv || window.sbh)
4038                      {
4039                         window.Capture();
4040                         guiApp.windowScrolling = window;
4041                         guiApp.windowScrollingStart.x = x;
4042                         guiApp.windowScrollingStart.y = y;
4043                         guiApp.windowScrollingBefore.x = window.scroll.x;
4044                         guiApp.windowScrollingBefore.y = window.scroll.y;
4045                      }
4046                   }
4047                   else if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftDoubleClick)
4048                   {
4049                      if(window.style.hasMaximize && 
4050                         window.IsMouseMoving( 
4051                            x - window.absPosition.x, y - window.absPosition.y, window.size.w, window.size.h))
4052                      {
4053                         window.SetState(
4054                            (window.state == maximized) ? normal : maximized, false, *mods);
4055                         result = false;
4056                      }
4057                   }
4058                }
4059             }
4060             else
4061                window = null;
4062             if(guiApp.windowMoving) 
4063             {
4064                if(guiApp.windowMoving.parent)
4065                {
4066                   if(guiApp.windowMoving.style.nonClient)
4067                      guiApp.windowMoving.parent.SetMouseRangeToWindow();
4068                   else
4069                      guiApp.windowMoving.parent.SetMouseRangeToClient();
4070                }
4071                else
4072                   FreeMouseRange();
4073                window.UpdateDecorations();
4074             }
4075          }
4076          else if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonUp)
4077          {
4078             // Log("\n*** LEFT BUTTON UP ***\n");
4079             if(guiApp.windowMoving)
4080                guiApp.windowMoving.StopMoving();
4081          }
4082          else if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonUp)
4083          {
4084             if(guiApp.windowScrolling)
4085             {
4086                Window windowScrolling = guiApp.windowScrolling;
4087                guiApp.windowScrolling = null;
4088                windowScrolling.ReleaseCapture();
4089             }
4090          }
4091
4092          if(!result || (window && window.destroyed)) window = null;
4093
4094          if(window && window.FindModal())
4095             window = null;
4096
4097          if(trueWindow && trueWindow.FindModal())
4098             delete trueWindow;
4099          
4100          /*if(trueWindow)
4101             incref trueWindow;
4102          */
4103
4104          /*
4105          msgWindow = GetAtPosition(x,y, true, false);
4106          if(msgWindow)
4107             msgWindow.SelectMouseCursor();
4108          */
4109
4110          if(guiApp.windowCaptured || trueWindow)
4111          {
4112             Window prevWindow = guiApp.prevWindow;
4113             if(guiApp.prevWindow && trueWindow != guiApp.prevWindow)
4114             {
4115                guiApp.prevWindow.mouseInside = false;
4116                guiApp.prevWindow = null;
4117
4118                // Eventually fix this not to include captured?
4119                if(!prevWindow.OnMouseLeave(*mods))
4120                   result = false;
4121             }
4122             if(result && trueWindow && !trueWindow.destroyed/* && trueWindow == window*/)
4123             {
4124                Box box = trueWindow.box;
4125                box.left += trueWindow.absPosition.x;
4126                box.right += trueWindow.absPosition.x;
4127                box.top += trueWindow.absPosition.y;
4128                box.bottom += trueWindow.absPosition.y;
4129
4130                if(box.IsPointInside({x, y}) && trueWindow != /*guiApp.*/prevWindow /*!trueWindow.mouseInside*/)
4131                {
4132                   int overX = x - (trueWindow.absPosition.x + trueWindow.clientStart.x);
4133                   int overY = y - (trueWindow.absPosition.y + trueWindow.clientStart.y);
4134
4135                   overX = Max(Min(overX, 32767),-32768);
4136                   overY = Max(Min(overY, 32767),-32768);
4137
4138                   trueWindow.mouseInside = true;
4139                   if(!trueWindow.OnMouseOver(overX, overY, *mods))
4140                      result = false;
4141                }
4142             }
4143             if(trueWindow && trueWindow._refCount > 1 && !trueWindow.destroyed)
4144                guiApp.prevWindow = trueWindow;
4145             else
4146                guiApp.prevWindow = null;
4147          }
4148          SelectMouseCursor();
4149
4150          if(window && !guiApp.windowMoving && !wasMoving && !wasScrolling)
4151          {
4152             int clientX = x - (window.absPosition.x + window.clientStart.x);
4153             int clientY = y - (window.absPosition.y + window.clientStart.y);
4154
4155             bool (* MouseMethod)(Window instance, int x, int y, Modifiers mods);
4156
4157             clientX = Max(Min(clientX, 32767),-32768);
4158             clientY = Max(Min(clientY, 32767),-32768);
4159
4160             MouseMethod = (void *)window._vTbl[method];
4161
4162             if(MouseMethod /*&& !consequential*/ && !window.disabled)
4163             {
4164                incref window;
4165                if(!MouseMethod(window, clientX, clientY, *mods))
4166                   result = false;
4167                delete window;
4168             }
4169          }
4170          delete trueWindow;
4171          /*
4172          if(result && w && w.clickThrough && w.parent)
4173             w = w.parent;
4174          else
4175             break;
4176          */
4177          if(!result || !w || !w.clickThrough)
4178             break;
4179       }
4180       delete w;
4181       return result;
4182    }
4183
4184    // --- Mouse cursor management ---
4185
4186    bool KeyMessage(uint method, Key key, unichar character)
4187    {
4188       bool status = true;
4189       if(!parent)
4190       {
4191          if(guiApp.interimWindow)
4192             this = guiApp.interimWindow;
4193       }
4194 #ifdef _DEBUG
4195       if((SmartKey)key != alt && (SmartKey)key != Key::control && method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown && parent && this != parent.menuBar)
4196          Print("");
4197 #endif
4198
4199       if(!style.inactive || rootWindow != this)
4200       {
4201          bool (*KeyMethod)(Window window, Key key, unichar ch) = (void *)_vTbl[method];
4202          Window modalWindow = FindModal();
4203          Window interimMaster = master ? master.rootWindow : null;
4204
4205          incref this;
4206
4207          if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown)
4208             status = OnSysKeyDown(key, character);
4209          else if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit)
4210             status = OnSysKeyHit(key, character);
4211          else if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp)
4212             status = OnSysKeyUp(key, character);
4213          if(!status)
4214          {
4215             delete this;
4216             return true;
4217          }
4218
4219          // Process Key Message for Internal UI Keyboard actions
4220          if(status && !destroyed && menuBar && state != minimized)
4221          {
4222             // Disable the ALT
4223             if((SmartKey)key != alt) 
4224                menuBar.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown, 0, 0);
4225             if(menuBar.focus)
4226             {
4227                SmartKey sk = (SmartKey) key;
4228                if((character && !key.alt && !key.ctrl) || sk == left || sk == right || sk == up || sk == down || sk == home || sk == end || sk == escape || sk == alt)
4229                {
4230                   status = menuBar.KeyMessage(method, key, character);
4231                   status = false;
4232                }
4233                else
4234                {
4235                   if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown)
4236                      menuBar.OnKeyHit(escape, 0);
4237                }
4238                if(!menuBar.focus && guiApp.caretOwner)
4239                   guiApp.caretOwner.UpdateCaret(true, false);
4240             }
4241          }
4242          if(!destroyed && status)
4243          {
4244             if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit || method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown)
4245             {
4246                switch(key)
4247                {
4248                   case left: case up: case right: case down:
4249                      if(guiApp.windowMoving == this)
4250                      {
4251                         int step = 1; //8;
4252                         int w = guiApp.windowMoving.size.w;
4253                         int h = guiApp.windowMoving.size.h;
4254                         int x = guiApp.windowMoving.scrolledPos.x;
4255                         int y = guiApp.windowMoving.scrolledPos.y;
4256
4257                         if(guiApp.textMode)
4258                         {
4259                            if(key == down || key == up)
4260                               step = Max(step, textCellH);
4261                            else
4262                               step = Max(step, textCellW);
4263                         }
4264
4265                         if(guiApp.windowIsResizing)
4266                         {
4267                            switch(key)
4268                            {
4269                               case left: w-=step; break;
4270                               case right: w+=step; break;
4271                               case up: h-=step;   break;
4272                               case down: h+=step; break;
4273                            }
4274                         }
4275                         else
4276                         {
4277                            switch(key)
4278                            {
4279                               case left: x-=step; break;
4280                               case right: x+=step; break;
4281                               case up: y-=step;   break;
4282                               case down: y+=step; break;
4283                            }
4284                         }
4285
4286                         if(guiApp.resizeX) x += w - guiApp.windowMoving.size.w;
4287                         if(guiApp.resizeY) y += h - guiApp.windowMoving.size.h;
4288
4289                         if(!guiApp.windowIsResizing || guiApp.resizeX)
4290                            x = (x - guiApp.windowMovingBefore.x) + guiApp.windowMovingStart.x;
4291                         else
4292                            x = (w - guiApp.windowResizingBefore.w) + guiApp.windowMovingStart.x;
4293
4294                         if(!guiApp.windowIsResizing || guiApp.resizeY)
4295                            y = (y - guiApp.windowMovingBefore.y) + guiApp.windowMovingStart.y;
4296                         else                           
4297                            y = (h - guiApp.windowResizingBefore.h) + guiApp.windowMovingStart.y;
4298
4299                         guiApp.interfaceDriver.SetMousePosition(x, y);
4300                         ConsequentialMouseMove(true);
4301
4302                         status = false;
4303                      }
4304                      break;
4305                   case escape:
4306                   case enter:
4307                   case keyPadEnter:
4308                      if(guiApp.windowMoving && method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown)
4309                      {
4310                         guiApp.windowMoving.StopMoving();
4311                         ConsequentialMouseMove(false);
4312                   
4313                         status = false;
4314                      }
4315                      break;
4316                   case altSpace:
4317                      if(style.fixed)
4318                      {
4319                         ShowSysMenu(absPosition.x, absPosition.y);
4320                         status = false;
4321                      }
4322                      break;
4323                }
4324             }
4325          }
4326
4327          if(!destroyed && status && state != minimized)
4328          {
4329             // Process all the way down the children
4330             if(activeChild && !activeChild.disabled)
4331             {
4332                status = activeChild.KeyMessage(method, key, character);
4333             }
4334             if(status && activeClient && activeChild != activeClient && !activeClient.disabled && (key.alt || key.ctrl) &&
4335                key.code != left && key.code != right && key.code != up && key.code != down)
4336             {
4337                status = activeClient.KeyMessage(method, key, character);
4338             }
4339
4340             // Default Control
4341             if(!destroyed && status && method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown)
4342             {
4343                if((SmartKey)key == enter && !key.alt && !key.ctrl && defaultControl && !defaultControl.disabled && state != minimized)
4344                   // && defaultControl != activeChild)
4345                {
4346                   delete previousActive;
4347                   previousActive = activeChild;
4348                   if(previousActive) incref previousActive;
4349
4350                   ConsequentialMouseMove(false);
4351                   if((defaultControl.active ||
4352                      defaultControl.ActivateEx(true, true, false, true, null, null)) && !defaultControl.disabled)
4353                      defaultControl.KeyMessage(method, defaultKey, character);
4354                   status = false;                       
4355                }
4356             }
4357          }
4358
4359          if(!destroyed && status && (!modalWindow || this == guiApp.desktop))
4360          {
4361             if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown)
4362             {
4363                switch(key)
4364                {
4365                   case altMinus:
4366                      if(style.fixed)
4367                      {
4368                         ShowSysMenu(absPosition.x, absPosition.y);
4369                         status = false;
4370                      }
4371                      break;
4372                   //case f5:
4373                   /*
4374                   case shiftF5:
4375                      if(this != guiApp.desktop)
4376                      {
4377                         if(!guiApp.windowMoving && !guiApp.windowCaptured)
4378                         {
4379                            if(state != maximized && (key.shift ? style.sizeable : style.fixed))
4380                            {
4381                               MenuMoveOrSize(key.shift, true);
4382                               status = false;
4383                            }
4384                         }
4385                         else if(guiApp.windowMoving)
4386                         {
4387                            guiApp.windowMoving.StopMoving();
4388                            ConsequentialMouseMove(false);
4389                            status = false;
4390                         }
4391                      }
4392                      break;
4393                   */
4394                }
4395             }
4396             if(!destroyed && status && state != minimized)
4397             {
4398                if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit || method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown)
4399                {
4400                   switch(key)
4401                   {
4402                      case tab: case shiftTab:
4403                      {
4404                         Window cycleParent = this;
4405                         if(this == guiApp.interimWindow && !master.style.interim && !cycleParent.style.tabCycle)
4406                            cycleParent = master.parent;
4407                         
4408                         if(!guiApp.windowCaptured && cycleParent.style.tabCycle)
4409                         {
4410                            if(cycleParent.CycleChildren(!key.shift, false, false, true))
4411                            {
4412                               Window child = cycleParent.activeChild;
4413
4414                               // Scroll the window to include the active control
4415                               /*
4416                               if(cycleParent.sbh && !child.style.dontScrollHorz)
4417                               {
4418                                  if(child.scrolledPos.x < 0)
4419                                     cycleParent.sbh.Action(Position, 
4420                                        cycleParent.scroll.x + child.scrolledPos.x, 0);
4421                                  else if(child.scrolledPos.x + child.size.w > cycleParent.clientSize.w)
4422                                     cycleParent.sbh.Action(Position,
4423                                        cycleParent.scroll.x + child.scrolledPos.x + child.size.w - cycleParent.clientSize.w, 0);
4424                               }
4425                               if(cycleParent.sbv && !child.style.dontScrollVert)
4426                               {
4427                                  if(child.scrolledPos.y < 0)
4428                                     cycleParent.sbv.Action(Position, 
4429                                        cycleParent.scroll.y + child.scrolledPos.y, 0);
4430                                  else if(child.scrolledPos.y + child.size.w > window.clientSize.h)
4431                                     cycleParent.sbv.Action(Position,
4432                                        cycleParent.scroll.y + child.scrolledPos.y+child.size.h - cycleParent.clientSize.h, 0);
4433                               }
4434                               */
4435                               cycleParent.ConsequentialMouseMove(false);
4436                               status = false;
4437                            }
4438                         }
4439                         break;
4440                      }
4441                      case f6: case shiftF6:
4442                         if(!guiApp.windowMoving /*!guiApp.windowCaptured*/)
4443                         {
4444                            // NOT NEEDED... guiApp.windowMoving.ReleaseCapture();
4445                            if(parent == guiApp.desktop)
4446                               if(guiApp.desktop.CycleChildren(key.shift, true, false, true))
4447                               {
4448                                  status = false;
4449                                  break;
4450                               }
4451                            if(style.tabCycle ||
4452                               CycleChildren(key.shift, true, false, true))
4453                            {
4454                               delete this;
4455                               return true;
4456                            }
4457                         }
4458                         break;
4459                      /*
4460                      // mIRC Style Window Shortcuts
4461                      case alt1: case alt2: case alt3: case alt4: case alt5:
4462                      case alt6: case alt7: case alt8: case alt9: case alt0:
4463                      {
4464                         if(numPositions)
4465                         {
4466                            Window document;
4467                            for(document = children.first; document; document = document.next)
4468                            {
4469                               if(document.style.isDocument && document.documentID - 1 == key.code - k1)
4470                               {
4471                                  if(document == activeChild)
4472                                  {
4473                                     if(document.state == minimized)
4474                                        document.SetState(normal, false, key);
4475                                     else
4476                                     {
4477                                        document.SetState(minimized, false, key);
4478                                        CycleChildren(false, true, false);
4479                                     }
4480                                  }
4481                                  else
4482                                  {
4483                                     if(activeChild.state == maximized && document.style.hasMaximize)
4484                                        document.SetState(maximized, false, key);
4485                                     else if(document.state == minimized)
4486                                        document.SetState(normal, false, key);
4487                                     document.Activate();
4488                                  }
4489                                  status = false;
4490                                  break;
4491                               }
4492                            }
4493                         }
4494                         break;            
4495                      }
4496                      */
4497                   }
4498                }
4499             }
4500          }
4501
4502          if(!destroyed && status)
4503          {
4504             if(state == minimized)
4505             {
4506                delete this;
4507                return true;
4508             }
4509             if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp)
4510             {
4511                if((SmartKey)key == enter && !key.alt && !key.ctrl && defaultControl && previousActive)
4512                {
4513                   if(defaultControl.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp, key, character))
4514                      previousActive.ActivateEx(true, false, false, true, null, null);
4515                   delete previousActive;
4516                   status = false;
4517                }
4518             }
4519          }
4520
4521          if(!destroyed && status)
4522          {
4523             status = ProcessHotKeys(method, key, character);
4524          }
4525          if(!destroyed && status && !modalWindow && state != minimized)
4526          {
4527             if(KeyMethod)
4528                status = KeyMethod(this, key, character);
4529             if(!destroyed && status && method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown)
4530                status = OnKeyHit(key, character);
4531             if(!destroyed && status && (method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown || method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit))
4532             {
4533                bool result = false;
4534                switch(key)
4535                {
4536                   case ctrlUp: case ctrlDown:
4537                      if(sbv && !guiApp.windowScrolling)
4538                         result = sbv.Action((key == ctrlUp) ? up : down, 0, key);
4539                      break;
4540                   case wheelUp: case wheelDown:
4541                      if(sbv && !guiApp.windowScrolling)
4542                      {
4543                         result = sbv.Action((key == wheelUp) ? wheelUp : wheelDown, 0, key);
4544                         // Do we want to do a consequential move regardless of result in this case?
4545                         ConsequentialMouseMove(false);
4546                      }
4547                      break;
4548                   case ctrlPageUp: case ctrlPageDown:
4549                      if(sbh && !guiApp.windowScrolling)
4550                         result = sbh.Action((key == ctrlPageUp) ? up : down, 0, key);
4551                      break;
4552                }
4553                if(result)
4554                {
4555                   ConsequentialMouseMove(false);
4556                   status = false;
4557                }
4558             }
4559          }
4560          if(status && !destroyed && menuBar && state != minimized)
4561             status = menuBar.KeyMessage(method, key, character);
4562
4563          if(style.interim && /*destroyed && */status && interimMaster)
4564          {
4565             // Testing this... for Ctrl-O to open dialog when autocompletion listbox is popped...
4566             status = interimMaster.KeyMessage(method, key, character);
4567          }
4568          delete this;
4569       }
4570       return status;
4571    }
4572
4573    bool ProcessHotKeys(uint method, Key key, unichar character)
4574    {
4575       bool status = true;
4576       HotKeySlot hotKey;
4577
4578       for(hotKey = hotKeys.first; hotKey; hotKey = hotKey.next)
4579          if((hotKey.key == key || (method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp && hotKey.key.code == key.code)) &&
4580             !hotKey.window.disabled && (hotKey.window.style.nonClient || state != minimized))
4581          {
4582             Window hotKeyWindow = hotKey.window;
4583             Window parent = hotKeyWindow.parent;
4584             Window prevActiveWindow = activeChild;
4585
4586             // Don't process non-visible buttons, but make an exception for the Alt-F4 with Native Decorations turned on
4587             if(hotKeyWindow.style.hidden && (!hotKeyWindow.style.nonClient || !parent || !parent.nativeDecorations || (hotKeyWindow != parent.sysButtons[2] && hotKeyWindow != parent.sysButtons[1] )))
4588                continue;
4589
4590             if(prevActiveWindow) incref prevActiveWindow;
4591             incref hotKeyWindow;
4592             if(method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown && !hotKeyWindow.style.nonClient)
4593                if(!hotKeyWindow.ActivateEx(true, true, false, true, null, null))
4594                {
4595                   status = false;
4596                   delete hotKeyWindow;
4597                   delete prevActiveWindow;
4598                   break;
4599                }
4600
4601             if(hotKeyWindow.style.nonClient && method == __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit)
4602                method = __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown;
4603             if(!hotKeyWindow.KeyMessage(method, Key::hotKey, character))
4604             {
4605                // *********   WORKING ON THIS   ***********
4606                if(prevActiveWindow && !guiApp.interimWindow)
4607                   prevActiveWindow.ActivateEx(true, false, false, false, null, null);
4608                status = false;
4609             }
4610             else if(hotKeyWindow.style.inactive)
4611                status = hotKeyWindow.KeyMessage(__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp, Key::hotKey, character);
4612
4613             delete prevActiveWindow;
4614             delete hotKeyWindow;
4615             // For Key Ups, don't set status to false... (e.g.: Releasing Enter vs AltEnter hot key)
4616             if(method != __ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp)
4617                status = false;
4618             break;
4619          }
4620       if(status && tabCycle)
4621       {
4622          Window child;
4623          for(child = children.first; child; child = child.next)
4624          {
4625             if(child.tabCycle && !child.ProcessHotKeys(method, key, character))
4626             {
4627                status = false;
4628                break;
4629             }
4630          }
4631       }
4632       return status;
4633    }
4634
4635
4636    // --- Windows and graphics initialization / termination ---
4637    bool SetupRoot(void)
4638    {
4639       Window child;
4640
4641       // Setup relationship with outside world (bb root || !bb)
4642       if((!guiApp.fullScreenMode && parent == guiApp.desktop) || this == guiApp.desktop || 
4643          (_displayDriver && dispDriver != parent.dispDriver))
4644       {
4645          rootWindow = this;
4646          if(!tempExtents)
4647             tempExtents = new0 Extent[4];
4648          against = null;
4649       }
4650       else
4651       {
4652          /*if(guiApp.fullScreenMode)
4653             rootWindow = guiApp.desktop;
4654          else*/
4655          //rootWindow = parent.created ? parent.rootWindow : null;
4656          rootWindow = parent.rootWindow;
4657
4658          if(style.nonClient)
4659             against = &parent.box;
4660          else
4661             against = &parent.clientArea;
4662       }
4663
4664       for(child = children.first; child; child = child.next)
4665          child.SetupRoot();
4666
4667       return (rootWindow && (rootWindow == this || rootWindow.created)) ? true : false;
4668    }
4669
4670    bool Setup(bool positionChildren)
4671    {
4672       bool result = false;
4673       Window child;
4674
4675       if((!guiApp.fullScreenMode && parent == guiApp.desktop) || (guiApp.fullScreenMode && (this == guiApp.desktop || (_displayDriver && dispDriver != parent.dispDriver))))
4676       {
4677          subclass(DisplayDriver) dDriver = (dispDriver && !formDesigner) ? dispDriver : GetDisplayDriver(guiApp.defaultDisplayDriver);
4678          DisplaySystem displaySystem = dDriver ? dDriver.displaySystem : null;
4679
4680          windowHandle = dDriver.printer ? null : guiApp.interfaceDriver.CreateRootWindow(this);
4681
4682          // This was here, is it really needed?
4683          //guiApp.interfaceDriver.ActivateRootWindow(this);
4684
4685          if(!displaySystem)
4686          {
4687             displaySystem = DisplaySystem {};
4688             if(!displaySystem.Create(dDriver.name, guiApp.fullScreenMode ? windowHandle : windowHandle /*null*/, guiApp.fullScreenMode))
4689             {
4690                delete displaySystem;
4691             }
4692          }
4693          if(displaySystem)
4694          {
4695             display = Display { alphaBlend = alphaBlend, useSharedMemory = useSharedMemory, windowDriverData = windowData };
4696             if(display.Create(displaySystem, windowHandle))
4697                result = true;
4698             else
4699             {
4700                delete display;
4701             }
4702          }
4703          guiApp.interfaceDriver.SetIcon(this, icon);
4704       }
4705       else if(this != guiApp.desktop)
4706       {
4707          display = rootWindow ? rootWindow.display : null;
4708          result = true;
4709       }
4710       else
4711          result = true;
4712
4713       if(guiApp.acquiredWindow && rootWindow == guiApp.acquiredWindow.rootWindow)
4714          guiApp.interfaceDriver.AcquireInput(guiApp.acquiredWindow.rootWindow, true);
4715
4716       for(child = children.first; child; child = child.next)
4717       {
4718          if(child.created && !child.Setup(false))
4719             result = false; 
4720       }
4721       return result;
4722    }
4723
4724    bool SetupDisplay(void)
4725    {
4726 #if !defined(ECERE_NO3D) && !defined(ECERE_VANILLA)
4727       if(is3D) return Window3D_SetupDisplay(this); else 
4728 #endif   
4729       if(SetupRoot())
4730          return Setup(true);
4731       return false;
4732    }
4733
4734    class_data void ** pureVTbl;
4735
4736    bool LoadGraphics(bool creation, bool resetAnchors)
4737    {
4738       bool result = false;
4739       bool success = false;
4740       Window child;
4741       WindowState stateBackup = state;
4742
4743       /*
4744       if(!rootWindow.created)
4745          printf("");
4746       */
4747       
4748       if(((subclass(Window))_class).pureVTbl)
4749       {
4750          if(_vTbl == _class._vTbl)
4751          {
4752             _vTbl = ((subclass(Window))_class).pureVTbl;
4753          }
4754          else
4755          {
4756             int m;
4757             for(m = 0; m < _class.vTblSize; m++)
4758             {
4759                if(_vTbl[m] == _class._vTbl[m])
4760                   _vTbl[m] = ((subclass(Window))_class).pureVTbl[m];
4761             }
4762          }
4763       }
4764       if(guiApp.currentSkin && ((subclass(Window))_class).pureVTbl)
4765       {
4766          if(_vTbl == ((subclass(Window))_class).pureVTbl)
4767          {
4768             _vTbl = _class._vTbl;
4769          }
4770          else
4771          {
4772             int m;
4773             for(m = 0; m < _class.vTblSize; m++)
4774             {
4775                if(_vTbl[m] == ((subclass(Window))_class).pureVTbl[m])
4776                   _vTbl[m] = _class._vTbl[m];
4777             }
4778          }
4779       }
4780       
4781       if(guiApp.fullScreenMode || this != guiApp.desktop)
4782       {
4783          SetWindowMinimum(&skinMinSize.w, &skinMinSize.h);
4784          if(display)
4785          {
4786             ResPtr ptr;
4787             success = true;
4788
4789             display.Lock(false);
4790             if(rootWindow == this)
4791             {
4792                // Set Color Palette
4793                display.SetPalette(palette, true);
4794
4795                // Load Cursors
4796                /*
4797                if(guiApp.fullScreenMode && this == guiApp.desktop)
4798                {
4799                   int c;
4800                   Cursor cursor;
4801
4802                   for(c=0; c<SystemCursor::enumSize; c++)
4803                      if(!guiApp.systemCursors[c].bitmap)
4804                      {
4805                         guiApp.systemCursors[c].bitmapName = guiApp.currentSkin.CursorsBitmaps(c,
4806                            &guiApp.systemCursors[c].hotSpotX,&guiApp.systemCursors[c].hotSpotY, &guiApp.systemCursors[c].paletteShades);
4807                         if(guiApp.systemCursors[c].bitmapName)
4808                         {
4809                            guiApp.systemCursors[c].bitmap = eBitmap_LoadT(guiApp.systemCursors[c].bitmapName, null,
4810                               guiApp.systemCursors[c].paletteShades ? null : guiApp.desktop.display.displaySystem);
4811                            if(guiApp.systemCursors[c].bitmap)
4812                               guiApp.systemCursors[c].bitmap.paletteShades = guiApp.systemCursors[c].paletteShades;
4813                            else
4814                               success = false;
4815                         }
4816                      }
4817                   for(cursor = guiApp.customCursors.first; cursor; cursor = cursor.next)
4818                   {
4819                      cursor.bitmap = eBitmap_LoadT(cursor.bitmapName, null, 
4820                         cursor.paletteShades ? null : guiApp.desktop.display.displaySystem);
4821                      if(cursor.bitmap)
4822                         cursor.bitmap.paletteShades = cursor.paletteShades;
4823                      else
4824                         success = false;
4825                   }
4826                   guiApp.cursorUpdate = true;
4827
4828                   display.Unlock();
4829                   ConsequentialMouseMove(false);
4830                   display.Lock(true);
4831                }
4832                */
4833             }
4834
4835             // Load Window Graphic Resources
4836             
4837             /*
4838             if(usedFont == setFont || usedFont == window.systemFont)
4839                RemoveResource(usedFont);
4840             */
4841             if(setFont)
4842                RemoveResource(setFont); // TESTING setFont instead of usedFont);
4843
4844             if(systemFont)
4845                RemoveResource(systemFont);
4846             
4847             if(captionFont)
4848                RemoveResource(captionFont);
4849
4850             for(ptr = resources.first; ptr; ptr = ptr.next)
4851             {
4852                ptr.loaded = display.displaySystem.LoadResource(ptr.resource);
4853             }
4854             if(setFont)
4855                AddResource(setFont);
4856             if(systemFont)
4857                AddResource(systemFont);
4858
4859             usedFont = setFont ? setFont : ((parent && parent.parent) ? parent.usedFont : systemFont);
4860
4861             firewatchers font;
4862
4863             /*
4864             if(!setFont)
4865             {
4866                //if(master && master.font)
4867                if(parent && parent.font)
4868                {
4869                   font = FontResource
4870                   {
4871                      faceName = parent.font.faceName,
4872                      size = parent.font.size,
4873                      bold = parent.font.bold,
4874                      italic = parent.font.italic,
4875                      underline = parent.font.underline
4876                   };
4877                   //font = parent.font;
4878                   watch(parent) { font { } };
4879                }
4880                else
4881                   font = guiApp.currentSkin.SystemFont();
4882                AddResource(font);
4883
4884                firewatchers font;
4885             }
4886             */
4887
4888             captionFont = guiApp.currentSkin.CaptionFont();
4889             AddResource(captionFont);
4890
4891             if(OnLoadGraphics())
4892             {
4893                int x,y,w,h;
4894
4895                display.Unlock();
4896
4897                //SetScrollLineStep(sbStep.x, sbStep.y);
4898                
4899                if(this != guiApp.desktop)
4900                {
4901                   if(resetAnchors)
4902                   {
4903                      normalAnchor = anchor;
4904                      normalSizeAnchor = sizeAnchor;
4905                   }
4906
4907                   // Break the anchors for moveable/resizable windows
4908                   /*
4909                   if(style.fixed && style.isDocument)
4910                   {
4911                      ComputeAnchors(ax, ay, aw, ah, &x, &y, &w, &h);
4912                      ax = x;
4913                      ay = y;
4914                      aw = w;
4915                      ah = h;
4916                      anchored = false;
4917                   }
4918                   */
4919                   switch(state)
4920                   {
4921                      case maximized:
4922                      
4923                         stateAnchor = Anchor { left = 0, top = 0, right = 0, bottom = 0 };
4924                         stateSizeAnchor = SizeAnchor {};
4925                         break;
4926                      
4927                      case minimized:
4928                      {
4929                         int maxIcons = parent.clientSize.w / MINIMIZED_WIDTH;
4930
4931                         stateAnchor = 
4932                            Anchor 
4933                            {
4934                               left = (iconID % maxIcons) * MINIMIZED_WIDTH,
4935                               bottom = (iconID / maxIcons) * (guiApp.textMode ? 16 : 24)
4936                            };
4937                         
4938                         stateSizeAnchor = SizeAnchor { size.w = MINIMIZED_WIDTH };
4939                         break;
4940                      }
4941                      case normal:
4942                         stateAnchor = normalAnchor;
4943                         stateSizeAnchor = normalSizeAnchor;
4944                         break;
4945                   }
4946                   position = Point { };
4947                   ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
4948
4949                }
4950                else
4951                {
4952                   x = scrolledPos.x;
4953                   y = scrolledPos.y;
4954                   w = size.w;
4955                   h = size.h;
4956                }
4957
4958                if(Position(x, y, w, h, true, false, true, true, true, true))
4959                {
4960                   if((this != guiApp.desktop || guiApp.fullScreenMode) && rootWindow == this)
4961                   {
4962                      if(!style.hidden)
4963                         guiApp.interfaceDriver.SetRootWindowState(this, normal, true);
4964                   }
4965
4966                   Update(null);
4967
4968                   result = true;
4969                }
4970             }
4971             else
4972             {
4973                result = false;
4974                display.Unlock();
4975             }
4976          }
4977       }
4978       else
4979       {
4980          success = result = true;
4981       }
4982
4983       if(!creation && result)
4984       {
4985          // Load menu bar first because sys buttons are on it...
4986          if(menuBar)
4987          {
4988             if(!menuBar.LoadGraphics(false, resetAnchors))
4989             {
4990                result = false;
4991                success = false;
4992             }
4993          }
4994          for(child = children.first; child; child = child.next)
4995          {
4996             if(child.created && child != menuBar && !child.LoadGraphics(false, resetAnchors))
4997             {
4998                result = false;
4999                success = false;
5000             }
5001          }
5002          if(!creation)
5003             CreateSystemChildren();
5004
5005          OnApplyGraphics();
5006       }
5007       if(this == guiApp.desktop && !guiApp.fullScreenMode)
5008       {
5009          if(activeChild)
5010             guiApp.interfaceDriver.ActivateRootWindow(activeChild);
5011       }
5012       /*
5013       TODO:
5014       if(!success)
5015          //guiApp.LogErrorCode(IERR_GRAPHICS_LOADING_FAILED, caption);
5016          guiApp.LogErrorCode(IERR_GRAPHICS_LOADING_FAILED, class.name);
5017       */
5018
5019       // Do this here to avoid problems on Windows
5020       if(stateBackup == maximized)
5021          property::state = maximized;
5022       return result;
5023    }
5024
5025    void UnloadGraphics(bool destroyWindows)
5026    {
5027       Window child;
5028
5029       // Free children's graphics
5030       for(child = children.first; child; child = child.next)
5031          child.UnloadGraphics(destroyWindows);
5032
5033       if(display)
5034          display.Lock(false);
5035
5036       // Free cursors
5037       if(guiApp.fullScreenMode && this == guiApp.desktop)
5038       {
5039          Cursor cursor;
5040          SystemCursor c;
5041
5042          for(c=0; c<SystemCursor::enumSize; c++)
5043             if(guiApp.systemCursors[c].bitmap)
5044                delete guiApp.systemCursors[c].bitmap;
5045
5046          for(cursor = guiApp.customCursors.first; cursor; cursor = cursor.next)
5047             delete cursor.bitmap;
5048
5049          guiApp.cursorBackground.Free();
5050       }
5051
5052       if(display && display.displaySystem)
5053       {
5054          ResPtr ptr;
5055
5056          for(ptr = resources.first; ptr; ptr = ptr.next)
5057          {
5058             if(ptr.loaded)
5059             {
5060                display.displaySystem.UnloadResource(ptr.resource, ptr.loaded);
5061                ptr.loaded = null;
5062             }
5063          }
5064
5065          // Free window graphics
5066          OnUnloadGraphics();
5067
5068          // Free skin graphics
5069          if(rootWindow == this)
5070          {
5071             DisplaySystem displaySystem = display.displaySystem;
5072             if(is3D)
5073             {
5074                display.driverData = null;
5075                display.displaySystem = null;
5076             }
5077             display.Unlock();
5078             delete display;
5079             if(displaySystem && !displaySystem.numDisplays && !is3D)
5080                delete displaySystem;
5081          }
5082          else
5083          {
5084             display.Unlock();
5085             display = null;
5086          }
5087       }
5088
5089       if(guiApp.acquiredWindow && this == guiApp.acquiredWindow.rootWindow)
5090          guiApp.interfaceDriver.AcquireInput(guiApp.acquiredWindow.rootWindow, false);
5091
5092       if(this == guiApp.desktop || parent == guiApp.desktop)
5093       {
5094          if((guiApp.fullScreenMode || this != guiApp.desktop) && rootWindow == this && windowHandle && destroyWindows)
5095             guiApp.interfaceDriver.DestroyRootWindow(this);
5096       }
5097    }
5098
5099    // --- Window Hiding ---
5100
5101    void SetVisibility(bool state)
5102    {
5103       bool visible = (style.hidden || !created) ? false : state;
5104       if(visible != this.visible)
5105       {
5106          Window child;
5107
5108          this.visible = visible;
5109          for(child = children.first; child; child = child.next)
5110             child.SetVisibility(visible);
5111          Update(null);
5112          ConsequentialMouseMove(false);
5113       }
5114    }
5115
5116    // --- Windows and graphics initialization / termination ---
5117
5118    bool DisplayModeChanged(void)
5119    {
5120       bool result = false;
5121       if(!guiApp.fullScreenMode && !guiApp.modeSwitching/* && guiApp.desktop.active*/)
5122       {
5123          guiApp.modeSwitching = true;
5124          UnloadGraphics(false);
5125          if(SetupDisplay())
5126             if(LoadGraphics(false, false))
5127                result = true;
5128          guiApp.modeSwitching = false;
5129       }
5130       return result;
5131    }
5132
5133    // --- Window updates system ---
5134
5135    void UpdateDirty(Box updateBox)
5136    {
5137       if(!manageDisplay) { OnRedraw(null);return; }
5138       if(visible)
5139       {
5140          if(display && (!guiApp.fullScreenMode || guiApp.desktop.active) && !guiApp.modeSwitching)
5141          {
5142             display.Lock(true);
5143             if(display.flags.flipping)
5144             {
5145                Update(null);
5146                rootWindow.UpdateDisplay();
5147             }
5148             else
5149                UpdateBackDisplay(updateBox);
5150
5151             if(guiApp.fullScreenMode)
5152             {
5153                guiApp.cursorUpdate = true;
5154                guiApp.PreserveAndDrawCursor();
5155             }
5156             if(guiApp.fullScreenMode)
5157                guiApp.RestoreCursorBackground();
5158             display.Unlock();
5159          }
5160       }
5161    }
5162
5163    // This function is strictly called as a result of system window activation
5164    bool ExternalActivate(bool active, bool activateRoot, Window window, Window swap)
5165    {
5166       bool result = true;
5167       Window interimMaster = null;
5168       Window interimWindow = guiApp.interimWindow;
5169       if(interimWindow && interimWindow.master)
5170          interimMaster = interimWindow.master.rootWindow;
5171
5172       if(active && state == minimized) // && (!window.nativeDecorations || window.rootWindow != window)
5173          // SetState(normal, false, 0);
5174          SetState(lastState, false, 0);
5175
5176       if(interimMaster && swap == interimMaster && interimMaster.IsSlaveOf(window))
5177          return false;
5178
5179       incref this;
5180       /* WTH is this doing here?
5181       while(swap && swap.activeChild)
5182       {
5183          swap = swap.activeChild;         
5184       }
5185       */
5186       // TESTING THIS BEFORE...
5187       if(interimWindow && this == interimMaster)
5188       {
5189          if(active)
5190          {
5191             // Window interimSwap = this;
5192             Window menuBar = this.menuBar;
5193             if(menuBar && interimWindow.master == menuBar)
5194             {
5195                /*
5196                while(interimSwap && interimSwap.activeChild)
5197                   interimSwap = interimSwap.activeChild;
5198
5199                result = interimWindow.ActivateEx(false, false, false, activateRoot, null,
5200                (menuBar && interimWindow.master == menuBar) ? menuBar : interimSwap);
5201                */
5202                result = /*interimWindow.*/ActivateEx(false, false, false, activateRoot, null, menuBar);
5203                //result = ActivateEx(true, true, false, activateRoot, window, null);
5204             }
5205          }
5206       }
5207       else
5208          // Testing & FindModal() here: broke reactivating when a modal dialog is up (didn't root activate dialog)
5209          result = ActivateEx(active, active, false, activateRoot /*&& FindModal()*/, window, swap);
5210
5211       if(interimWindow == this && interimMaster && !active)
5212       {
5213          while(interimMaster && interimMaster.interim && interimMaster.master)
5214          {
5215             // printf("Going up one master %s\n", interimMaster._class.name);
5216             interimMaster = interimMaster.master.rootWindow;
5217          }
5218          // printf("Unactivating interim master %s (%x)\n", interimMaster._class.name, interimMaster);
5219          interimMaster.ActivateEx(active, active, false, activateRoot, window, swap);
5220       }
5221       delete this;
5222       return result;
5223    }
5224
5225    bool DestroyEx(int returnCode)
5226    {
5227       OldLink slave;
5228       Timer timer, nextTimer;
5229       Window child;
5230       OldLink prevOrder = null;
5231       Window client = null;
5232
5233       if(parent) stopwatching(parent, font); 
5234
5235       // if(window.modalSlave) return false;
5236       if(destroyed || !created)
5237       {
5238          if(master)
5239          {
5240             /*
5241             if(destroyed)
5242             {
5243                OldLink slave = master.slaves.FindLink(this);
5244                master.slaves.Delete(slave);
5245             }
5246             */
5247             // TOFIX IMMEDIATELY: COMMENTED THIS OUT... causes problem second time creating file dialog
5248             //master = null;
5249          }
5250          return true;
5251       }
5252
5253       this.returnCode = (DialogResult)returnCode;
5254
5255       AcquireInput(false);
5256
5257       destroyed = true;
5258       if(hotKey)
5259       {
5260          master.hotKeys.Delete(hotKey);
5261          hotKey = null;
5262       }
5263
5264       if(guiApp.prevWindow == this)
5265       {
5266          guiApp.prevWindow = null;
5267          OnMouseLeave(0);
5268       }
5269       if(guiApp.caretOwner == this) 
5270       {
5271          guiApp.interfaceDriver.SetCaret(0,0,0);
5272          UpdateCaret(false, true);
5273          guiApp.caretEnabled = false;
5274       }
5275
5276       /*
5277       if(cycle)
5278          parent.childrenCycle.Remove(cycle);
5279       */
5280       if(order)
5281       {
5282          OldLink tmpPrev = order.prev;
5283          if(tmpPrev && !(((Window)tmpPrev.data).style.hidden) && !(((Window)tmpPrev.data).destroyed) && (((Window)tmpPrev.data).created))
5284             prevOrder = tmpPrev;
5285          for(;;)
5286          {
5287             client = tmpPrev ? tmpPrev.data : null;
5288             if(client == this) { client = null; break; }
5289             if(client && (client.style.hidden || client.destroyed || !client.created))
5290                tmpPrev = client.order.prev;
5291             else
5292             {
5293                if(client)
5294                   prevOrder = tmpPrev;
5295                break;
5296             }
5297          }
5298
5299          // If this window can be an active client, make sure the next window we activate can also be one
5300          if(!style.nonClient && style.isActiveClient)
5301          {
5302             tmpPrev = prevOrder;
5303             for(;;)
5304             {
5305                client = tmpPrev ? tmpPrev.data : null;
5306                if(client == this) { client = null; break; }
5307                if(client && (client.style.nonClient || !client.style.isActiveClient || client.style.hidden || client.destroyed || !client.created))
5308                   tmpPrev = client.order.prev;
5309                else 
5310                {
5311                   if(client)
5312                      prevOrder = tmpPrev;
5313                   break;
5314                }
5315             }
5316             if(client && client.style.hidden) client = null;
5317          }
5318          // parent.childrenOrder.Remove(order);
5319       }
5320
5321       if(parent && style.isActiveClient && visible)
5322       {
5323          if(state == minimized) parent.numIcons--;
5324          parent.numPositions--;
5325       }
5326
5327       // TESTING THIS HERE!
5328       created = false;
5329       visible = false;
5330
5331       // If no display, don't bother deactivating stuff (causes unneeded problems when trying
5332       // to create a window inside a rootwindow that's being destroyed)
5333       // DISABLED THIS BECAUSE OF CREATING WINDOW IN DESKTOP IN WINDOWED MODE
5334
5335       if(master && !master.destroyed /*&&
5336          rootWindow && rootWindow.display && !rootWindow.destroyed*/)
5337       {
5338          if(master.defaultControl == this)
5339             master.defaultControl = null;
5340       }
5341       if(parent && !parent.destroyed /*&&
5342          rootWindow && rootWindow.display && !rootWindow.destroyed*/)
5343       {
5344          if((parent.activeChild == this /*|| parent.activeClient == this */|| guiApp.interimWindow == this))
5345          {
5346             if(order && prevOrder && prevOrder.data != this && active)
5347             {
5348                //((Window)prevOrder.data).ActivateEx(true, false, false, false /*true*/, null);
5349
5350                ((Window)prevOrder.data).ActivateEx(true, false, false, (rootWindow == this) ? true : false, null, null);
5351                if(parent.activeClient == this)
5352                {
5353                   parent.activeClient = null;
5354                   parent.UpdateActiveDocument(null);
5355                }
5356             }
5357             else 
5358             {
5359                if(guiApp.interimWindow == this)
5360                {
5361                   bool goOn = true;
5362                   PropagateActive(false, null, &goOn, true);
5363                }
5364                else
5365                {
5366                   //if(window.parent.activeChild == window)
5367                      parent.activeChild = null;
5368                   if(!style.nonClient /*&& style.isActiveClient*/)
5369                   {
5370                      Window previous = parent.activeClient;
5371                      if(style.isActiveClient)
5372                         parent.activeClient = null;
5373                      parent.UpdateActiveDocument(previous);
5374                   }
5375                }
5376             }
5377          }
5378          else if(parent.activeClient == this)
5379          {
5380             parent.activeClient = client;
5381             parent.UpdateActiveDocument(this);
5382
5383          }
5384       }
5385       if(guiApp.interimWindow == this)
5386       {
5387          guiApp.interimWindow = null;
5388          if(guiApp.caretOwner)
5389          {
5390             Window desktop = guiApp.desktop;
5391             if(desktop.activeChild && desktop.activeChild.menuBar && !desktop.activeChild.menuBar.focus)
5392                guiApp.caretOwner.UpdateCaret(false, false);
5393          }
5394       }
5395
5396       active = false;
5397       if(_isModal && master && master.modalSlave == this)
5398          master.modalSlave = null;
5399
5400       if(parent)
5401       {
5402          if(!guiApp.caretOwner && parent.caretSize)
5403          {
5404             guiApp.caretOwner = parent;
5405             parent.UpdateCaret(false, false);
5406             parent.Update(null);
5407          }
5408
5409          // Why was this commented out?
5410          GetRidOfVirtualArea();
5411       }
5412       /*
5413       delete cycle;
5414       delete order;
5415       */
5416       dirtyArea.Free(null);
5417       dirtyBack.Free(null);
5418       scrollExtent.Free(null);
5419
5420       /* ATTEMPTING TO MOVE THAT ABOVE
5421       created = false;
5422       visible = false;
5423       */
5424
5425       /*
5426       OnDestroy();
5427       {
5428          //Window next;
5429          //for(child = window.children.first; next = child ? child.next : null, child; child = next)
5430          for(;(child = window.children.first);)
5431          {
5432             for(; child && (child.destroyed || !child.created); child = child.next);
5433             if(child)
5434                child.DestroyEx(0);
5435             else
5436                break;
5437          }
5438       }
5439       */
5440
5441       UnloadGraphics(true);
5442
5443       if(previousActive)
5444          delete previousActive;
5445
5446       menuBar = null;
5447       // statusBar = null;
5448       sbv = sbh = null;
5449
5450       if(master && !master.destroyed)
5451       {
5452          //master.NotifyDestroyed(this, this.returnCode);
5453          NotifyDestroyed(master, this, this.returnCode);
5454       }
5455
5456       for(timer = guiApp.windowTimers.first; timer; timer = nextTimer)
5457       {
5458          nextTimer = timer.next;
5459          if(timer.window == this)
5460          {
5461             // WHY WERE WE SETTING THIS TO NULL? NO MORE WINDOW WHEN RECREATING...
5462             // timer.window = null;
5463             timer.Stop();
5464             //delete timer;
5465          }
5466       }
5467
5468       if(this == guiApp.windowMoving)
5469          StopMoving();
5470
5471       if(guiApp.windowCaptured == this)
5472          ReleaseCapture();
5473          //guiApp.windowCaptured = null;
5474
5475       if(rootWindow != this && rootWindow)
5476          rootWindow.ConsequentialMouseMove(false);
5477
5478       rootWindow = null;
5479
5480       OnDestroy();
5481
5482       {
5483          //Window next;
5484          //for(child = children.first; next = child ? child.next : null, child; child = next)
5485          for(;(child = children.first); )
5486          {
5487             for(; child && (child.destroyed || !child.created); child = child.next);
5488             if(child)
5489                child.DestroyEx(0);
5490             else
5491                break;
5492          }
5493       }
5494
5495       // master = null;
5496
5497       /* // MOVED THIS UP...
5498       {
5499          //Window next;
5500          //for(child = window.children.first; next = child ? child.next : null, child; child = next)
5501          for(;(child = window.children.first); )
5502          {
5503             for(; child && (child.destroyed || !child.created); child = child.next);
5504             if(child)
5505                child.DestroyEx(0);
5506             else
5507                break;
5508          }
5509       }
5510       */
5511
5512       while((slave = slaves.first))
5513       {
5514          for(; slave && (((Window)slave.data).destroyed || !((Window)slave.data).created); slave = slave.next);
5515          if(slave)
5516             ((Window)slave.data).DestroyEx(0);
5517          else
5518             break;
5519       }
5520
5521       if(guiApp.caretOwner == this)
5522          guiApp.caretOwner = null;
5523
5524       sysButtons[0] = null;
5525       sysButtons[1] = null;
5526       sysButtons[2] = null;
5527       activeChild = null;
5528
5529       if(rootWindow != this)
5530       {
5531          Box box { scrolledPos.x, scrolledPos.y, scrolledPos.x + size.w - 1, scrolledPos.y + size.h - 1 };
5532          if(style.nonClient)
5533          {
5534             box.left   -= parent.clientStart.x;
5535             box.top    -= parent.clientStart.y;
5536             box.right  -= parent.clientStart.x;
5537             box.bottom -= parent.clientStart.y;
5538          }
5539          if(parent) parent.Update(box);
5540       }
5541       /*
5542       if(master)
5543       {
5544          OldLink slave = master.slaves.FindVoid(this);
5545          master.slaves.Delete(slave);
5546          master = null;
5547       }
5548
5549       if(parent)
5550       {
5551          parent.children.Remove(this);
5552          parent = null;
5553       }
5554       */
5555
5556       //autoCreate = false;
5557       //created = false;
5558
5559       // SHOULD THIS BE HERE? FIXED CRASH WITH GOTO DIALOG
5560       if(((subclass(Window))_class).pureVTbl)
5561       {
5562          if(_vTbl == _class._vTbl)
5563          {
5564             _vTbl = ((subclass(Window))_class).pureVTbl;
5565          }
5566          else
5567          {
5568             int m;
5569             for(m = 0; m < _class.vTblSize; m++)
5570             {
5571                if(_vTbl[m] == _class._vTbl[m])
5572                   _vTbl[m] = ((subclass(Window))_class).pureVTbl[m];
5573             }
5574          }
5575       }
5576
5577       delete this;
5578       return true;
5579    }
5580
5581    void SetStateEx(WindowState newState, bool activate)
5582    {
5583       int x,y,w,h;
5584       WindowState prevState = state;
5585
5586       state = newState;
5587
5588       if(prevState != newState)
5589          lastState = prevState;
5590
5591       if(rootWindow != this || !nativeDecorations)
5592       {
5593          if(style.isActiveClient && !style.hidden && prevState == minimized)
5594             parent.numIcons--;
5595
5596          // This block used to be at the end of the function... moved it for flicker problem in X
5597          // ------------------------------------------------------
5598          switch(state)
5599          {
5600             case normal:
5601                stateAnchor = normalAnchor;
5602                stateSizeAnchor = normalSizeAnchor;
5603                break;
5604             case maximized:
5605                stateAnchor = Anchor { left = 0, top = 0, right = 0, bottom = 0 };
5606                stateSizeAnchor = SizeAnchor {};
5607                break;
5608             case minimized:
5609             {
5610                int maxIcons = parent.clientSize.w / MINIMIZED_WIDTH;
5611                Window child;
5612                int size = 256;
5613                byte * idBuffer = new0 byte[size];
5614                int c;
5615                for(child = parent.children.first; child; child = child.next)
5616                {
5617                   if(child != this && child.state == minimized)
5618                   {
5619                      if(child.iconID > size - 2)
5620                      {
5621                         idBuffer = renew0 idBuffer byte[size*2];
5622                         memset(idBuffer + size, 0, size);
5623                         size *= 2;
5624                      }
5625                      idBuffer[child.iconID] = (byte)bool::true;
5626                   }
5627                }
5628                for(c = 0; c<size; c++)
5629                   if(!idBuffer[c])
5630                      break;
5631                iconID = c;
5632                delete idBuffer;
5633                if(style.isActiveClient && !style.hidden)
5634                   parent.numIcons++;
5635
5636                stateAnchor = Anchor { left = (iconID % maxIcons) * MINIMIZED_WIDTH, bottom = (iconID / maxIcons) * (guiApp.textMode ? 16 : 24) };
5637                stateSizeAnchor = SizeAnchor { size.w = MINIMIZED_WIDTH };
5638                break;
5639             }
5640          }
5641          // TOCHECK: Why was this here?
5642          //position.x = (tx > 0) ? tx & 0xFFFFF : tx;
5643          //position.y = (ty > 0) ? ty & 0xFFFFF : ty;
5644          ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
5645
5646          Position(x, y, w, h, true, true, true, true, false, true);
5647
5648          if(!style.inactive && !style.interim && this == parent.activeClient)
5649             parent.UpdateActiveDocument(null);
5650       }
5651
5652       CreateSystemChildren();
5653       // ------------------------------------------------------
5654    }
5655
5656    int GetPositionID(Window forChild)
5657    {
5658       Window child;
5659       int size = 256;
5660       byte * idBuffer = new0 byte[size];
5661       int c;
5662
5663       for(child = children.first; child; child = child.next)
5664       {
5665          if(child.style.isActiveClient && !child.style.hidden && child != forChild)
5666          {
5667             if(child.positionID > size - 2)
5668             {
5669                idBuffer = renew0 idBuffer byte[size*2];
5670                memset(idBuffer + size, 0, size);
5671                size *= 2;
5672             }
5673             idBuffer[child.positionID] = (byte)bool::true;
5674          }
5675       }
5676       for(c = 0; c<size; c++)
5677          if(!idBuffer[c])
5678             break;
5679       delete idBuffer;
5680       return c;
5681    }
5682
5683    // --- Window related graphics ---
5684
5685    void SetPalette(ColorAlpha * newPalette, bool colorMatch)
5686    {
5687       palette = newPalette;
5688       if(rootWindow.display)
5689          rootWindow.display.SetPalette(palette, colorMatch);
5690    }
5691
5692    public bool AcquireInput(bool acquired)
5693    {
5694       bool result = true;
5695       if(acquiredInput != acquired)
5696       {
5697          if(active || (!visible && creationActivation == activate))
5698             result = AcquireInputEx(acquired);
5699          /*if(!result)
5700          {
5701             Print("");
5702          }*/
5703          acquiredInput = acquired ? result : !result;
5704       }
5705       return result;
5706    }
5707
5708    void ListChildren(ListBox listBox)
5709    {
5710       Window child;
5711       char caption[2048];
5712       for(child = children.first; child; child = child.next)
5713       {
5714          if(child.cycle && !child.style.nonClient && child.style.isActiveClient && child.visible)
5715          {
5716             DataRow row = listBox.AddRow();
5717             row.tag = (int)child;
5718             child.FigureCaption(caption);
5719             row.SetData(null, caption);
5720          }
5721       }
5722    }
5723
5724    void UpdateVisual(Box extent)
5725    {
5726       if(guiApp.driver != null)
5727       {
5728          if(guiApp.fullScreenMode && guiApp.desktop.display)
5729          {
5730             guiApp.desktop.mutex.Wait();
5731             guiApp.desktop.display.Lock(true);
5732          
5733             Update(extent);
5734             if(guiApp.desktop.active)
5735             {
5736                if(guiApp.desktop.dirty || guiApp.cursorUpdate)
5737                {
5738                   if(guiApp.desktop.display.flags.flipping)
5739                      guiApp.desktop.Update(null);
5740                   guiApp.desktop.UpdateDisplay();
5741                   guiApp.cursorUpdate = true;
5742                }
5743                if(guiApp.cursorUpdate || guiApp.desktop.dirty)
5744                {
5745                   guiApp.PreserveAndDrawCursor();
5746                   // guiApp.desktop.display.ShowScreen();
5747                   guiApp.cursorUpdate = false;
5748                   guiApp.desktop.dirty = false;
5749                   guiApp.RestoreCursorBackground();
5750                }
5751             }
5752          
5753             guiApp.desktop.display.Unlock();
5754             guiApp.desktop.mutex.Release();
5755          }
5756          else
5757          {
5758             Window rootWindow = this.rootWindow;
5759             rootWindow.mutex.Wait();
5760             display.Lock(true);
5761          
5762             Update(extent);
5763             if(guiApp.waiting)
5764                guiApp.SignalEvent();
5765             else
5766             {
5767                guiApp.waitMutex.Wait();
5768                guiApp.interfaceDriver.Lock(rootWindow);
5769                if(!rootWindow.style.hidden && rootWindow.dirty)
5770                {
5771                   if(rootWindow.display)
5772                   {
5773                      rootWindow.UpdateDisplay();
5774                      //rootWindow.display.ShowScreen(null);
5775                   }
5776                   rootWindow.dirty = false;
5777                }
5778                guiApp.interfaceDriver.Unlock(rootWindow);
5779                guiApp.waitMutex.Release();
5780             }
5781             display.Unlock();
5782             rootWindow.mutex.Release();
5783          }
5784       }
5785    }
5786
5787    void UnlockDisplay(void)
5788    {
5789       guiApp.interfaceDriver.Unlock(rootWindow);
5790    }
5791
5792    void LockDisplay(void)
5793    {
5794       guiApp.interfaceDriver.Lock(rootWindow);
5795    }
5796
5797    Surface GetSurface(Box box)
5798    {
5799       return Redraw((box == null) ? this.box : box);
5800    }
5801
5802    void SetMousePosition(int x, int y)
5803    {
5804       guiApp.interfaceDriver.SetMousePosition(x + absPosition.x + clientStart.x, y + absPosition.y + clientStart.y);
5805    }
5806
5807    /*
5808    void IntegrationActivate(bool active)
5809    {
5810       if(!guiApp.modeSwitching && !guiApp.fullScreenMode)
5811       {
5812          isForegroundWindow = true;
5813          ActivateEx(active, active, false, false, null, null);
5814          isForegroundWindow = false;
5815       }  
5816    }
5817    */
5818
5819    Window QueryCapture(void)
5820    {
5821       return guiApp.windowCaptured;
5822    }
5823
5824    int GetDocumentID(void)
5825    {
5826       Window child;
5827       int size = 256;
5828       byte * idBuffer = new0 byte[size];
5829       int c;
5830
5831       for(child = children.first; child; child = child.next)
5832       {
5833          if(child.style.isDocument)
5834          {
5835             if(child.documentID-1 > size - 2)
5836             {
5837                idBuffer = renew0 idBuffer byte[size*2];
5838                memset(idBuffer + size, 0, size);
5839                size *= 2;
5840             }
5841             idBuffer[child.documentID-1] = 1;
5842          }
5843       }
5844       for(c = 0; c<size; c++)
5845          if(!idBuffer[c])
5846             break;
5847       numDocuments++;
5848       delete idBuffer;
5849       return c + 1;
5850    }
5851
5852    void SetInitSize(Size size)
5853    {
5854       int x, y, w, h;
5855       sizeAnchor.size = size;
5856       normalSizeAnchor = sizeAnchor;
5857
5858       // Break the anchors for moveable/resizable windows
5859       if(state == normal /*|| state == Hidden */)   // Hidden is new here ...
5860       {
5861          stateAnchor = normalAnchor;
5862          stateSizeAnchor = normalSizeAnchor;
5863
5864          ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
5865          Position(x,y, w, h, true, true, true, true, false, true);
5866       }
5867    }
5868
5869    void MenuMoveOrSize(bool resize, bool setCursorPosition)
5870    {
5871       if(this != guiApp.desktop && state != maximized && (resize ? (state != minimized && style.sizable) : (style.fixed || moveable)))
5872       {
5873          guiApp.windowIsResizing = resize;
5874          guiApp.windowMoving = this;
5875          guiApp.windowMovingStart = guiApp.movingLast = absPosition;
5876          if(guiApp.windowIsResizing)
5877          {
5878             guiApp.windowMovingStart.x += size.w - 1;
5879             guiApp.windowMovingStart.y += size.h - 1;
5880          }
5881          guiApp.windowMovingBefore = scrolledPos;
5882          guiApp.windowResizingBefore = size;
5883          guiApp.windowMoving.UpdateDecorations();
5884          if(guiApp.windowIsResizing) 
5885             guiApp.resizeEndX = guiApp.resizeEndY = true;
5886
5887          if(setCursorPosition)
5888             guiApp.interfaceDriver.SetMousePosition(guiApp.windowMovingStart.x, guiApp.windowMovingStart.y);
5889          else
5890          {
5891             int x, y;
5892             guiApp.interfaceDriver.GetMousePosition(&x, &y);
5893             guiApp.windowMovingStart.x += x - absPosition.x;
5894             guiApp.windowMovingStart.y += y - absPosition.y;
5895          } 
5896
5897          if(guiApp.windowMoving)
5898          {
5899             if(guiApp.windowMoving.style.nonClient)
5900                guiApp.windowMoving.parent.SetMouseRangeToWindow();
5901             else
5902                guiApp.windowMoving.parent.SetMouseRangeToClient();
5903          }
5904
5905          Capture();
5906
5907          if(this == rootWindow)
5908             guiApp.interfaceDriver.StartMoving(rootWindow, guiApp.windowMovingStart.x, guiApp.windowMovingStart.y, true);
5909       }
5910    }
5911
5912 public:
5913    // normal Methods
5914    bool Create()
5915    {
5916       bool result = false;
5917
5918       if(created)
5919          result = true;
5920       else if(guiApp && guiApp.driver != null)
5921       {
5922          void * systemParent = null;
5923          OldLink slaveHolder;
5924          Window last;
5925          bool visible = !style.hidden;
5926
5927          if(style.embedded) 
5928          {
5929             systemParent = parent;
5930             parent = guiApp.desktop;
5931          }
5932          last = parent ? parent.children.last : null;
5933
5934          if((parent && parent != guiApp.desktop && !parent.created) ||
5935             (master && master != guiApp.desktop && !master.created))
5936             return false;
5937
5938          if(!parent)
5939             property::parent = guiApp.desktop;
5940          if(!master) master = parent;
5941
5942          if(_isModal && master.modalSlave)
5943             property::master = master.modalSlave;
5944             //return false;
5945
5946          if(parent)
5947             parent.children.Remove(this);
5948          if(master)
5949          {
5950             for(slaveHolder = master.slaves.first; slaveHolder; slaveHolder = slaveHolder.next)
5951                if(slaveHolder.data == this)
5952                {
5953                   master.slaves.Delete(slaveHolder);
5954                   break;
5955                }
5956          }
5957
5958          if(parent == guiApp.desktop && !mutex)
5959             mutex = Mutex {};
5960
5961          if(style.isDocument)
5962          {
5963             if(parent)
5964                parent.numDocuments--;
5965             documentID = parent.GetDocumentID();
5966          }
5967
5968          if(!style.stayOnTop)
5969             for(; last && last.style.stayOnTop; last = last.prev);
5970
5971          parent.children.Insert((last == this) ? null : last, this);
5972          //parent.children.Add(this);
5973
5974          if(!dispDriver)
5975             dispDriver = parent.dispDriver;
5976          destroyed = false;
5977          if(_isModal)
5978             master.modalSlave = this;
5979
5980          box = Box { MAXINT, MAXINT, MININT, MININT }; //-MAXINT, -MAXINT };
5981
5982          incref this;
5983          incref this;
5984
5985          master.slaves.Add(slaveHolder = OldLink { data = this });
5986          if(slaveHolder)
5987          {
5988             if(setHotKey)
5989             {
5990                master.hotKeys.Add(hotKey = HotKeySlot { key = setHotKey, window = this });
5991             }
5992             if(style.isDefault && !master.defaultControl)
5993                master.defaultControl = this;
5994
5995             stateAnchor = normalAnchor = anchor;
5996             stateSizeAnchor = normalSizeAnchor = sizeAnchor;
5997
5998             // TOCHECK: Why is this here?
5999             //position.x = (ax > 0) ? ax & 0xFFFFF : ax;
6000             //position.y = (ay > 0) ? ay & 0xFFFFF : ay;
6001
6002             this.visible = false;
6003             style.hidden = true;
6004     
6005             //created = true;
6006             // autoCreate = true;
6007             wasCreated = true;
6008             if(SetupDisplay())
6009             {
6010                created = true;
6011                if(OnCreate())
6012                {
6013                   /*
6014                   if(parent == guiApp.desktop)
6015                      Log("LoadGraphics %s\n", caption);
6016                   */
6017                   if(LoadGraphics(true, false))
6018                   {
6019                      if(!setFont)
6020                      {
6021                         watch(parent)
6022                         {
6023                            font
6024                            {
6025                               usedFont = setFont ? setFont : (parent.parent ? parent.usedFont : systemFont);
6026                               firewatchers font;
6027                               Update(null);
6028                            }
6029                         };
6030                      }
6031
6032                      if(style.hasMenuBar /*&& menu*/)
6033                      {
6034                         menuBar = 
6035                            PopupMenu
6036                            {
6037                               this,
6038                               menu = menu, isMenuBar = true, anchor = Anchor { top = 23, left = 1, right = 1 },
6039                               interim = false, inactive = true, nonClient = true, size.h = 24
6040                            };
6041                         menuBar.Create();
6042                      }
6043
6044                      if(statusBar)
6045                         statusBar.Create();
6046                      
6047                      // Create the system buttons
6048                      CreateSystemChildren();
6049
6050                      UpdateActiveDocument(null);
6051
6052                      if(style.isDocument)
6053                      {
6054                         if(menu)
6055                         {
6056                            MenuItem item = menu.FindItem(MenuFileSave, 0);
6057                            if(item) item.disabled = !modifiedDocument && fileName;
6058                         }
6059                      }
6060
6061                      /*
6062                      if(parent == guiApp.desktop)
6063                         Log("Preemptive SetState %s\n", caption);
6064                      */
6065
6066                      // Preemptive Set State to ensure proper anchoring
6067                      SetStateEx(state, false);
6068                      /*
6069                      style.hidden = true;
6070                      visible = false;
6071                      */
6072
6073                      {
6074                         Window child, next;
6075                         for(child = children.first; child; child = next)
6076                         {
6077                            next = child.next;
6078                            if(!child.created && (child.autoCreate || child.wasCreated))
6079                               child.Create();
6080                         }
6081                      }
6082
6083                      {
6084                         OldLink link, next;
6085                         for(link = slaves.first; link; link = next)
6086                         {
6087                            Window slave = link.data;
6088                            next = link.next;
6089                            if(!slave.created && (slave.autoCreate || slave.wasCreated))
6090                               slave.Create();
6091                         }
6092                      }
6093
6094                      if(OnPostCreate())
6095                         OnApplyGraphics();
6096
6097                      /*
6098                      if(parent == guiApp.desktop)
6099                         Log("Real SetState %s\n", caption);
6100                      */
6101
6102                      if(isActiveClient && visible)
6103                      {
6104                         parent.numPositions--;
6105                         if(state == minimized) parent.numIcons--;
6106                      }
6107
6108                      // Real set state & activate for proper display & activation
6109                      property::visible = visible;
6110                      //  SetState(state & 0x00000003, true, 0);
6111
6112                      if(visible)
6113                      {
6114                         UpdateCaption();
6115                         /*if(rootWindow == this)
6116                            guiApp.interfaceDriver.ActivateRootWindow(this);
6117                         else*/
6118                         if(creationActivation == activate)
6119                            ActivateEx(true, false, true, true, null, null);
6120                         else if(creationActivation == flash)
6121                            Flash();
6122                      }
6123
6124                      if(!destroyed)
6125                         rootWindow.ConsequentialMouseMove(false);
6126
6127                      result = true;
6128                   }
6129                }
6130             }
6131          }
6132          /*
6133          if(!result)
6134          {
6135             Destroy(0);
6136             guiApp.LogErrorCode(IERR_WINDOW_CREATION_FAILED, caption);
6137          }
6138          */
6139
6140          if(!result)
6141          {
6142             // Testing this here... Otherwise a failed LoadGraphics stalls the application
6143             created = false;
6144             //style.hidden = true; // !visible;
6145             style.hidden = !visible;
6146             if(master.modalSlave == this)
6147                master.modalSlave = null;
6148          }
6149          delete this;
6150       }
6151       return result;
6152    }
6153
6154    void WriteCaption(Surface surface, int x, int y)
6155    {
6156       if(caption)
6157          Interface::WriteKeyedTextDisabled(surface, x,y, caption, hotKey ? hotKey.key : 0, !isEnabled);
6158    }
6159
6160    void Update(Box region)
6161    {
6162       if(this)
6163       {
6164          Window rootWindow;
6165
6166          rootWindow = this.rootWindow;
6167
6168          // rootWindow.mutex.Wait();
6169          if(!destroyed && visible && display)
6170          {
6171             Window child;
6172             Box realBox;
6173             
6174             // Testing this to avoid repetitve full update to take time...
6175             if(dirtyArea.count == 1)
6176             {
6177                BoxItem item = (BoxItem)ACCESS_ITEM(dirtyArea, dirtyArea.first);
6178                if(item.box.left <= box.left &&
6179                   item.box.top <= box.top &&
6180                   item.box.right >= box.right &&
6181                   item.box.bottom >= box.bottom)
6182                {
6183                   rootWindow.dirty = true;
6184                   return;
6185                }
6186             }
6187
6188             if(display.flags.flipping && !rootWindow.dirty)
6189             {
6190                if(this == rootWindow)
6191                   region = null;
6192                else
6193                {
6194                   rootWindow.Update(null);
6195                   return;
6196                }
6197             }
6198             
6199             rootWindow.dirty = true;
6200
6201             if(region != null)
6202             {
6203                realBox = region;
6204                realBox.left += clientStart.x;
6205                realBox.top += clientStart.y;
6206                realBox.right += clientStart.x;
6207                realBox.bottom += clientStart.y;
6208                realBox.Clip(box);
6209             }
6210             else
6211                realBox = box;
6212
6213             if(realBox.right >= realBox.left && 
6214                realBox.bottom >= realBox.top)
6215             {
6216                // if(!rootWindow.fullRender)
6217                   dirtyArea.UnionBox(realBox, rootWindow.tempExtents[0]);
6218
6219                for(child = children.first; child; child = child.next)
6220                {
6221                   if(!child.is3D)
6222                   {
6223                      Box box = realBox;
6224                      box.left -= child.absPosition.x - absPosition.x;
6225                      box.top -= child.absPosition.y - absPosition.y;
6226                      box.right -= child.absPosition.x - absPosition.x;
6227                      box.bottom -= child.absPosition.y - absPosition.y;
6228                      if(box.right >= child.box.left && box.left <= child.box.right &&
6229                         box.bottom >= child.box.top && box.top <= child.box.bottom)
6230                      {
6231                         box.left -= child.clientStart.x;
6232                         box.top -= child.clientStart.y;
6233                         box.right -= child.clientStart.x;
6234                         box.bottom -= child.clientStart.y;
6235                         child.Update(box);
6236                      }
6237                   }
6238                }
6239
6240                realBox.left += absPosition.x - rootWindow.absPosition.x;
6241                realBox.top += absPosition.y - rootWindow.absPosition.y;
6242                realBox.right += absPosition.x - rootWindow.absPosition.x;
6243                realBox.bottom += absPosition.y - rootWindow.absPosition.y;
6244                rootWindow.dirtyBack.UnionBox(realBox, rootWindow.tempExtents[0]);
6245             }
6246          }
6247          else if(this == guiApp.desktop)
6248          {
6249             Window window;
6250             for(window = children.first; window; window = window.next)
6251             {
6252                if(!window.is3D)
6253                {
6254                   if(region != null)
6255                   {
6256                      Box childBox = region;
6257
6258                      childBox.left    -= window.absPosition.x - guiApp.desktop.absPosition.x;
6259                      childBox.top     -= window.absPosition.y - guiApp.desktop.absPosition.y;
6260                      childBox.right   -= window.absPosition.x - guiApp.desktop.absPosition.x;
6261                      childBox.bottom  -= window.absPosition.y - guiApp.desktop.absPosition.y;
6262        
6263                      window.Update(childBox);
6264                   }
6265                   else
6266                      window.Update(null);
6267                }
6268             }
6269          }
6270
6271          // rootWindow.mutex.Release();
6272       }
6273    }
6274
6275    bool Capture(void)
6276    {
6277       bool result = true;
6278       if(guiApp.windowCaptured != this)
6279       {
6280          if(guiApp.windowCaptured)
6281             result = false;
6282          else
6283          {
6284             //Logf("Captured %s (%s)\n", caption, class.name);
6285             guiApp.interfaceDriver.SetMouseCapture(rootWindow);
6286             guiApp.windowCaptured = this;
6287          }
6288       }
6289       return result;
6290    }
6291
6292    bool Destroy(int code)
6293    {
6294       //if(created)
6295       if(this)
6296       {
6297          if(!destroyed && !CloseConfirmation(false)) return false;
6298          incref this;
6299          if(DestroyEx(code))
6300          {
6301             // TOCHECK: Should autoCreate be set to false here?
6302             autoCreate = false;
6303             wasCreated = false;
6304             delete this;
6305             return true;
6306          }
6307          delete this;
6308       }
6309       return false;
6310    }
6311
6312    void Move(int x, int y, int w, int h)
6313    {
6314       normalAnchor = Anchor { left = x, top = y };
6315       normalSizeAnchor = SizeAnchor { size = { w, h } };
6316
6317       if(state == normal /*|| state == Hidden */)   // Hidden is new here ...
6318       {
6319          if(destroyed) return;
6320
6321          stateAnchor = normalAnchor;
6322          stateSizeAnchor = normalSizeAnchor;
6323
6324          ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
6325          Position(x,y, w, h, true, true, true, true, false, true);
6326       }
6327    }
6328
6329    DialogResult Modal(void)
6330    {
6331       isModal = true;
6332       if(Create())
6333          return DoModal();
6334
6335       // FIXES MEMORY LEAK IF Create() FAILED
6336       incref this;
6337       delete this;
6338       return 0;
6339    }
6340
6341    void SetScrollArea(int width, int height, bool snapToStep)
6342    {
6343       bool resize = false;
6344       if(snapToStep)
6345       {
6346          int stepX = sbStep.x, stepY = sbStep.y;
6347          // Needed to make snapped down position match the skin's check of client area 
6348          // against realvirtual
6349          if(guiApp.textMode)
6350          {
6351             SNAPDOWN(stepX, textCellW);
6352             SNAPDOWN(stepY, textCellH);
6353             stepX = Max(stepX, textCellW);
6354             stepY = Max(stepY, textCellH);
6355          }
6356          if(scrollFlags.snapX)
6357             SNAPUP(width, stepX);
6358          if(scrollFlags.snapY)
6359             SNAPUP(height, stepY);
6360       }
6361
6362       reqScrollArea.w = width;
6363       reqScrollArea.h = height;
6364       noAutoScrollArea = (width > 0 || height > 0);
6365
6366       UpdateScrollBars(true, true);
6367    }
6368
6369    void SetScrollPosition(int x, int y)
6370    {
6371       if(sbh)
6372          sbh.Action(setPosition, x, 0);
6373       else
6374       {
6375          int range;
6376          int seen = clientSize.w, total = reqScrollArea.w;
6377          seen = Max(1,seen);
6378          if(scrollFlags.snapX)
6379             SNAPDOWN(seen, sbStep.x);
6380
6381          if(!total) total = seen;
6382          range = total - seen + 1;
6383          range = Max(range, 1);
6384          if(x < 0) x = 0;
6385          if(x >= range) x = range - 1;
6386
6387          if(scrollFlags.snapX)
6388             SNAPUP(x, sbStep.x);
6389
6390          if(scroll.x != x)
6391             OnHScroll(setPosition, x, 0);
6392
6393          if(guiApp.textMode)
6394          {
6395             SNAPDOWN(x, textCellW);
6396          }
6397          scroll.x = x;
6398       }
6399
6400       if(sbv)
6401          sbv.Action(setPosition, y, 0);
6402       else
6403       {
6404          int range;
6405          int seen = clientSize.h, total = reqScrollArea.h;
6406          seen = Max(1,seen);
6407
6408          if(scrollFlags.snapY)
6409             SNAPDOWN(seen, sbStep.y);
6410
6411          if(!total) total = seen;
6412          range = total - seen + 1;
6413          range = Max(range, 1);
6414          if(y < 0) y = 0;
6415          if(y >= range) y = range - 1;
6416
6417          if(scrollFlags.snapY)
6418             SNAPUP(y, sbStep.y);
6419
6420          if(scroll.y != y)
6421             OnVScroll(setPosition, y, 0);
6422          if(guiApp.textMode)
6423          {
6424             SNAPDOWN(y, textCellH);
6425          }
6426          scroll.y = y;
6427       }
6428       if(!sbh || !sbv)
6429          UpdateCaret(false, false);
6430    }
6431
6432    void SetScrollLineStep(int stepX, int stepY)
6433    {
6434       sbStep.x = stepX;
6435       sbStep.y = stepY;
6436       if(guiApp.textMode)
6437       {
6438          SNAPDOWN(stepX, textCellW);
6439          SNAPDOWN(stepY, textCellH);
6440          stepX = Max(stepX, textCellW);
6441          stepY = Max(stepY, textCellH);
6442       }
6443       if(sbh)
6444          sbh.lineStep = stepX;
6445       if(sbv)
6446          sbv.lineStep = stepY;
6447    }
6448
6449    void SetState(WindowState newState, bool activate, Modifiers mods)
6450    {
6451       if(created)
6452       {
6453          if(state == newState || OnStateChange(newState, mods))
6454          {
6455             WindowState prevState = state;
6456
6457             StopMoving();
6458
6459             // This used to be at the end of the brackets... moved for X, testing...
6460             // This has the effect of activating the window through the system...
6461             if(rootWindow == this)
6462                guiApp.interfaceDriver.SetRootWindowState(this, newState, !style.hidden);
6463       
6464             SetStateEx(newState, activate);
6465
6466             if(rootWindow == this && !rootWindow.nativeDecorations)
6467             {
6468                int x = position.x, y = position.y;
6469                /*if(style.interim)
6470                {
6471                   x -= guiApp.desktop.absPosition.x;
6472                   y -= guiApp.desktop.absPosition.y;
6473                }*/
6474                guiApp.interfaceDriver.PositionRootWindow(this, x, y, size.w, size.h, true, true);
6475             }
6476
6477             //state = newState;
6478             //state = prevState;
6479
6480             if(state != maximized && style.hasMaximize)
6481             {
6482                Window child;
6483                for(child = parent.children.first; child; child = child.next)
6484                {
6485                   if(child != this && child.state == maximized)
6486                      child.SetStateEx(normal, false);
6487                }
6488             }
6489
6490             if(!style.nonClient && (sbv || sbh) && this != parent.sbv && this != parent.sbh)
6491                parent.UpdateScrollBars(true, true);
6492
6493             /*
6494             // Do we really need this stuff here? 
6495             // Shouldn't the Activate stuff take care of it?              
6496             if(parent.rootWindow == parent && style)
6497             {
6498                char caption[2048];
6499                parent.FigureCaption(caption);
6500                guiApp.interfaceDriver.SetRootWindowCaption(parent, caption);
6501                parent.UpdateDecorations();
6502             }         
6503             */
6504
6505             rootWindow.ConsequentialMouseMove(false);
6506          }
6507       }
6508       else
6509          state = newState;
6510    }
6511
6512    BitmapResource GetIcon(SkinBitmap iconID)
6513    {
6514       return guiApp.currentSkin.GetBitmap(iconID);
6515    }
6516
6517    void SetMouseRange(Box range)
6518    {
6519       if(range || guiApp.fullScreenMode)
6520       {
6521          Box clip;
6522          if(range != null)
6523          {
6524             clip.left   = range.left + absPosition.x + clientStart.x;
6525             clip.top    = range.top + absPosition.y + clientStart.y;
6526             clip.right  = range.right + absPosition.x + clientStart.x;
6527             clip.bottom = range.bottom + absPosition.y + clientStart.y;
6528          }
6529          else
6530          {
6531             clip.left   = guiApp.desktop.box.left;
6532             clip.top    = guiApp.desktop.box.top;
6533             clip.right  = guiApp.desktop.box.right;
6534             clip.bottom = guiApp.desktop.box.bottom;
6535          }
6536          guiApp.interfaceDriver.SetMouseRange(rootWindow, clip);
6537       }
6538       else
6539          guiApp.interfaceDriver.SetMouseRange(rootWindow, null);
6540    }
6541
6542    void SetMouseRangeToClient(void)
6543    {
6544       if(guiApp.fullScreenMode || this != guiApp.desktop)
6545       {
6546          Box box {0, 0, clientSize.w - 1, clientSize.h - 1 };
6547          box.Clip(clientArea);
6548          SetMouseRange(box);
6549       }
6550       else
6551          SetMouseRange(null);
6552    }
6553
6554    void SetMouseRangeToWindow(void)
6555    {
6556       Box box { -clientStart.x, -clientStart.y, size.w-1, size.h-1 };
6557       if(this == guiApp.desktop)
6558          SetMouseRangeToClient();
6559       else
6560          SetMouseRange(box);
6561    }
6562
6563    // x, y: Desktop Coordinates
6564    void ShowSysMenu(int x, int y)
6565    {
6566       Menu menu { };
6567       PopupMenu windowMenu { master = this, interim = true, position = { x + 1 - guiApp.desktop.position.x, y + 1 - guiApp.desktop.position.y }, menu = menu };
6568       MenuItem
6569       {
6570          menu, "Restore", r, NotifySelect = MenuWindowRestore, 
6571          disabled = (!style.hasMaximize && !style.hasMinimize) || state == normal, bitmap = guiApp.currentSkin.GetBitmap(restore)
6572       };
6573       MenuItem
6574       {
6575          menu, "Move", m, NotifySelect = MenuWindowMove, 
6576          disabled = !style.fixed || state == maximized
6577       };
6578       MenuItem
6579       {
6580          menu, "Size", s, NotifySelect = MenuWindowSize, 
6581          disabled = !style.sizable || state != normal
6582       };
6583       MenuItem
6584       {
6585          menu, "Minimize", n, NotifySelect = MenuWindowMinimize, 
6586          disabled = !style.hasMinimize || state == minimized, bitmap = guiApp.currentSkin.GetBitmap(minimize)
6587       };
6588       MenuItem
6589       {
6590          menu, "Maximize", KeyCode::x, NotifySelect = MenuWindowMaximize, 
6591          disabled = !style.hasMaximize || state == maximized, bitmap = guiApp.currentSkin.GetBitmap(maximize)
6592       };
6593       MenuItem
6594       {
6595          menu, "Stay On Top", t, NotifySelect = MenuWindowStayOnTop, 
6596          disabled = !style.fixed, checkable = true, checked = style.stayOnTop
6597       };
6598       MenuDivider { menu };
6599       MenuItem
6600       {
6601          menu, "Close", c, (parent == guiApp.desktop) ? altF4 : ( style.isActiveClient ? ctrlF4 : 0), NotifySelect = MenuWindowClose,
6602          bold = true, disabled = !style.hasClose, bitmap = guiApp.currentSkin.GetBitmap(close)
6603       };
6604       windowMenu.Create();
6605    }
6606
6607    void Activate(void)
6608    {
6609       ActivateEx(true, true, true, true, null, null);
6610    }
6611
6612    void MakeActive(void)
6613    {
6614       ActivateEx(true, false, true, false, null, null);
6615    }
6616
6617    void SoftActivate(void)
6618    {
6619       if(guiApp.desktop.active)
6620          Activate();
6621       else if(!active)
6622          Flash();
6623    }
6624
6625    void Deactivate(void)
6626    {
6627       ActivateEx(false, true, true, true, null, null);
6628    }
6629
6630    void Flash(void)
6631    {
6632       guiApp.interfaceDriver.FlashRootWindow(rootWindow);
6633    }
6634
6635    bool CycleChildren(bool backward, bool clientOnly, bool tabCycleOnly, bool cycleParents)
6636    {
6637       bool result = false;
6638       if(activeChild && activeChild.cycle)
6639       {
6640          Window modalWindow, child = activeChild;
6641          if(!clientOnly /*&& parent.tabCycle*/)
6642          {
6643             Window next = child;
6644             while(true)
6645             {
6646                if(next.cycle == (backward ? childrenCycle.first : childrenCycle.last))
6647                {
6648                   if(cycleParents)
6649                   {
6650                      if(parent && parent.CycleChildren(backward, false, true, true))
6651                         return true;
6652                      break;
6653                   }
6654                   else
6655                      return false;
6656                }
6657                if(backward)
6658                   next = next.cycle.prev.data;
6659                else
6660                   next = next.cycle.next.data;
6661                if(!next.disabled && !next.inactive /*isRemote*/ && next.created && !next.nonClient && (!clientOnly || next.style.isActiveClient) && !next.style.hidden && next.FindModal() != activeChild)
6662                   break;
6663             }
6664          }
6665          /*
6666          if(!clientOnly && child.cycle == (backward ? childrenCycle.first : childrenCycle.last) && 
6667             parent.tabCycle && parent.CycleChildren(backward, false, false))
6668             return true;
6669          */
6670
6671          if(tabCycleOnly && !tabCycle) return false;
6672
6673          while(child)
6674          {
6675             while(true)
6676             {
6677                if(backward)
6678                   child = child.cycle.prev.data;
6679                else
6680                   child = child.cycle.next.data;
6681                if(child == child.parent.activeChild)
6682                   return result;
6683                else if(!child.disabled && child.created && (!clientOnly || child.style.isActiveClient) && !child.style.hidden && child.FindModal() != activeChild)
6684                   break;
6685             }
6686             modalWindow = child.FindModal();
6687             if(!modalWindow)
6688             {
6689                // Scroll the window to include the active control
6690                if(sbh && !child.style.dontScrollHorz)
6691                {
6692                   if(child.scrolledPos.x < 0)
6693                      sbh.Action(setPosition, scroll.x + child.scrolledPos.x, 0);
6694                   else if(child.scrolledPos.x + child.size.w > clientSize.w)
6695                      sbh.Action(setPosition, scroll.x + child.scrolledPos.x + child.size.w - clientSize.w, 0);
6696                }
6697                if(sbv && !child.style.dontScrollVert)
6698                {
6699                   if(child.scrolledPos.y < 0)
6700                      sbv.Action(setPosition, scroll.y + child.scrolledPos.y, 0);
6701                   else if(child.scrolledPos.y + child.size.h > clientSize.h)
6702                      sbv.Action(setPosition, scroll.y + child.scrolledPos.y + child.size.h - clientSize.h, 0);
6703                }
6704             }
6705             result = true;
6706             child = modalWindow ? modalWindow : child;
6707             child.ActivateEx(true, true, true, true, null, null);
6708             if(child.tabCycle && child.childrenCycle.first)
6709                child = ((OldLink)(backward ? child.childrenCycle.first : child.childrenCycle.last)).data;
6710             else
6711                break;
6712          }
6713       }
6714       else
6715          return false;
6716
6717       ConsequentialMouseMove(false);
6718       return result;
6719    }
6720
6721    void AddResource(Resource resource)
6722    {
6723       if(resource)
6724       {
6725          ResPtr ptr { resource = resource };
6726          resources.Add(ptr);
6727          incref resource;
6728
6729          // Load Graphics here if window is created already
6730          if(/*created && */display)
6731          {
6732             display.Lock(false);
6733             ptr.loaded = display.displaySystem.LoadResource(resource);
6734             display.Unlock();
6735          }
6736          /*
6737          // Temporary hack to load font right away for listbox in dropbox ...
6738          else if(master && master.display)
6739          {
6740             master.display.Lock(false);
6741             master.display.displaySystem.LoadResource(resource);
6742             master.display.Unlock();
6743          }
6744          */
6745       }
6746    }
6747
6748    void RemoveResource(Resource resource)
6749    {
6750       if(resource)
6751       {
6752          ResPtr ptr;
6753          for(ptr = resources.first; ptr; ptr = ptr.next)
6754          {
6755             if(ptr.resource == resource)
6756                break;
6757          }
6758
6759          if(ptr)
6760          {
6761             // Unload Graphics here if window is created already
6762             if(/*created && */display)
6763             {
6764                if(ptr.loaded)
6765                {
6766                   display.Lock(false);
6767                   display.displaySystem.UnloadResource(resource, ptr.loaded);
6768                   display.Unlock();
6769                   ptr.loaded = null;
6770                }
6771             }
6772             delete resource;
6773             resources.Delete(ptr);
6774          }
6775       }
6776    }
6777
6778    void SetCaret(int x, int y, int size)
6779    {
6780       if(!destroyed)
6781       {
6782          caretPos.x = x;
6783          caretPos.y = y;
6784          caretSize = size;
6785          if(active && !style.interim)
6786          {
6787             if(visible || !guiApp.caretOwner)
6788                guiApp.caretOwner = size ? this : null;
6789             if(size)
6790                UpdateCaret(false, false);
6791             else
6792             {
6793                guiApp.interfaceDriver.SetCaret(0,0,0);
6794                UpdateCaret(false, true);
6795                guiApp.caretEnabled = false;
6796             }
6797          }
6798          else if(style.inactive && active)
6799          {
6800             guiApp.interfaceDriver.SetCaret(0,0,0);
6801             UpdateCaret(false, true);
6802             guiApp.caretEnabled = false;
6803          }
6804       }
6805    }
6806
6807    void Scroll(int x, int y)
6808    {
6809       bool opaque = !style.drawBehind || background.a;
6810       if(opaque && display && display.flags.scrolling)
6811       {
6812          Box box = clientArea;
6813          box.left += clientStart.x;
6814          box.top += clientStart.y;
6815          box.right += clientStart.x;
6816          box.bottom += clientStart.y;
6817
6818          //scrollExtent.Free(null);
6819          scrollExtent.AddBox(box);
6820          scrolledArea.x += x;
6821          scrolledArea.y += y;
6822
6823          //scrollExtent.Free();
6824          //scrollExtent.AddBox(clientArea);
6825          //scrollExtent.Offset(clientStart.x, clientStart.y);
6826          //scrolledArea.x = x;
6827          //scrolledArea.y = y;
6828       }
6829       else
6830          Update(clientArea);
6831
6832       if(rootWindow)
6833          rootWindow.dirty = true;
6834    }
6835
6836    void ReleaseCapture()
6837    {
6838       if(guiApp && guiApp.windowCaptured && guiApp.windowCaptured == this)
6839       {
6840          Window oldCaptured = guiApp.windowCaptured;
6841          guiApp.windowCaptured = null;
6842          guiApp.prevWindow = null;
6843          incref oldCaptured;
6844
6845          //guiApp.Log("Released Capture\n");
6846
6847          guiApp.interfaceDriver.SetMouseCapture(null);
6848
6849          //oldCaptured.OnMouseCaptureLost();
6850
6851          if(oldCaptured)
6852             oldCaptured.ConsequentialMouseMove(false);
6853          delete oldCaptured;
6854       }
6855    }
6856
6857    void SetText(char * format, ...)
6858    {
6859       if(this)
6860       {
6861          delete caption;
6862          if(format)
6863          {
6864             char caption[MAX_F_STRING];
6865             va_list args;
6866             va_start(args, format);
6867             vsprintf(caption, format, args);
6868             va_end(args);
6869
6870             this.caption = new char[strlen(caption)+1];
6871             if(this.caption)
6872                strcpy(this.caption, caption);
6873          }
6874          if(created)
6875             UpdateCaption();
6876
6877          firewatchers text;
6878       }
6879    }
6880
6881    bool Grab(Bitmap bitmap, Box box, bool decorations)
6882    {
6883       bool result = false;
6884       if(display || this == guiApp.desktop)
6885       {
6886          Box clip = {MININT, MININT, MAXINT, MAXINT};
6887
6888          if(box != null)
6889             clip = box;
6890
6891          if(!decorations)
6892             clip.Clip(clientArea);
6893          else
6894             clip.Clip(this.box);
6895
6896          if(rootWindow != this)
6897          {
6898             clip.left   += absPosition.y;
6899             clip.top    += absPosition.y;
6900             clip.right  += absPosition.x;
6901             clip.bottom += absPosition.y;
6902          }
6903
6904          clip.left += decorations ? 0 : clientStart.x;
6905          clip.top += decorations ? 0 : clientStart.y;
6906          clip.right += decorations ? 0 : clientStart.x;
6907          clip.bottom += decorations ? 0 : clientStart.y;
6908
6909          if(display && display.flags.flipping)
6910          {
6911             rootWindow.Update(null);
6912             rootWindow.UpdateDisplay();
6913          }
6914
6915          if(!display)
6916          {
6917             Window window { };
6918             window.Create();
6919             result = window.display.displaySystem.driver.GrabScreen(null, bitmap, clip.left, clip.top, 
6920                clip.right - clip.left + 1, clip.bottom - clip.top + 1);
6921             delete window;
6922          }
6923          else
6924             result = display.Grab(bitmap, clip.left, clip.top, 
6925                clip.right - clip.left + 1, clip.bottom - clip.top + 1);
6926
6927          if(bitmap.pixelFormat != pixelFormat888 && bitmap.pixelFormat != pixelFormat8)
6928          {
6929             if(!bitmap.Convert(null, pixelFormat888, null))
6930                result = false;
6931          }
6932       }
6933       return result;
6934    }
6935
6936    void GetMousePosition(int * x, int * y)
6937    {
6938       int mouseX = 0, mouseY = 0;
6939       if(!guiApp.acquiredWindow && (guiApp.desktop.active || !guiApp.fullScreenMode))
6940       {
6941          if(guiApp.driver)
6942             guiApp.interfaceDriver.GetMousePosition(&mouseX, &mouseY);
6943          if(this != guiApp.desktop)
6944          {
6945             mouseX -= absPosition.x + clientStart.x;
6946             mouseY -= absPosition.y + clientStart.y;
6947          }
6948       }
6949       if(x) *x = mouseX;
6950       if(y) *y = mouseY;
6951    }
6952
6953    DialogResult DoModal()
6954    {
6955       DialogResult returnCode = 0;
6956       int terminated = terminateX;
6957       isModal = true;
6958       incref this;
6959       while(!destroyed && guiApp.driver != null)
6960       {
6961          if(terminateX != terminated)
6962          {
6963             terminated = terminateX;
6964             guiApp.desktop.Destroy(0);
6965             if(guiApp.desktop.created)
6966             {
6967                terminated = 0;
6968                //printf("Resetting terminate X to 0\n");
6969                terminateX = 0;
6970             }
6971             break;
6972          }
6973
6974          guiApp.UpdateDisplay();
6975          if(!guiApp.ProcessInput(false))
6976             guiApp.Wait();
6977       }
6978       returnCode = this.returnCode;
6979       delete this;
6980       return returnCode;
6981    }
6982
6983    void DoModalStart()
6984    {
6985       isModal = true;
6986       incref this;
6987    }
6988
6989    bool DoModalLoop()
6990    {
6991       return !destroyed && guiApp.driver != null && terminateX < 2;
6992    }
6993
6994    DialogResult DoModalEnd()
6995    {
6996       DialogResult returnCode = this.returnCode;
6997       delete this;
6998       return returnCode;
6999    }
7000
7001    // --- Window manipulation ---
7002    /*bool GetDisabled()
7003    {
7004       bool disabled = this.disabled;
7005       Window window;
7006       for(window = this; (window = window.master); )
7007       {
7008          if(window.disabled)
7009          {
7010             disabled = true;
7011             break;
7012          }
7013       }
7014       return disabled;
7015    }*/
7016
7017    // --- Mouse Manipulation ---
7018    void GetNCMousePosition(int * x, int * y)
7019    {
7020       GetMousePosition(x, y);
7021       if(x) *x += clientStart.x;
7022       if(y) *y += clientStart.y;
7023    }
7024
7025    // --- Carets manipulation ---
7026    void GetCaretPosition(Point caretPos)
7027    {
7028       caretPos = this.caretPos;
7029    }
7030
7031    int GetCaretSize(void)
7032    {
7033       return caretSize;
7034    }
7035
7036    bool ButtonCloseDialog(Button button, int x, int y, Modifiers mods)
7037    {
7038       Destroy(button.id);
7039       return true;
7040    }
7041
7042    bool CloseConfirmation(bool parentClosing)
7043    {
7044       bool result = true;
7045       OldLink slave;
7046       Window child;
7047
7048       if(closing)
7049          return false;
7050       if(terminateX > 1)
7051          return true;
7052          
7053       closing = true;
7054
7055       if(!OnClose(parentClosing))
7056          result = false;
7057
7058       // If you want to skip this, simply set modifiedDocument to false in OnClose
7059       if(result && (/*fileName || */style.isDocument) && modifiedDocument)
7060       {
7061          DialogResult dialogRes;
7062          char message[1024];
7063          if(fileName)
7064             sprintf(message, "Save changes to %s?", fileName);
7065          else
7066             sprintf(message, "Save changes to Untitled %d?", documentID);
7067
7068          dialogRes = MessageBox { master = master, type = yesNoCancel, text = parent.caption, contents = message }.Modal();
7069
7070          if(dialogRes == yes)
7071          {
7072             // TOFIX: Precomp error if brackets are taken out
7073             result = (DialogResult)MenuFileSave(null, 0) != cancel;
7074          }
7075          else if(dialogRes == cancel)
7076             result = false;
7077       }
7078
7079       if(result)
7080       {
7081          for(slave = slaves.first; slave; slave = slave.next)
7082             if(!((Window)slave.data).CloseConfirmation(true))
7083             {
7084                // ((Window)slave.data).CloseConfirmation(true);
7085                result = false;
7086                break;
7087             }
7088       }
7089
7090       if(result)
7091       {
7092          for(child = children.first; child; child = child.next)
7093             if(child.master != this && !child.CloseConfirmation(true))
7094             {
7095                result = false;
7096                break;
7097             }
7098       }
7099       closing = false;
7100       return result;
7101    }
7102
7103    // Static methods... move them somewhere else?
7104    void ::RestoreCaret()
7105    {
7106       if(guiApp.caretOwner)
7107          guiApp.caretOwner.UpdateCaret(false, false);
7108    }
7109
7110    void ::FreeMouseRange()
7111    {
7112       guiApp.interfaceDriver.SetMouseRange(null, null);
7113    }
7114
7115    // Menu Methods
7116    bool MenuFileClose(MenuItem selection, Modifiers mods)
7117    {
7118       Window document = activeChild;
7119       if(document)
7120          document.Destroy(0);
7121       return true;
7122    }
7123
7124    bool MenuFileExit(MenuItem selection, Modifiers mods)
7125    {
7126       Destroy(0);
7127       return true;
7128    }
7129
7130    bool MenuFileSave(MenuItem selection, Modifiers mods)
7131    {
7132       if(fileName)
7133       {
7134          fileMonitor.fileName = null;
7135          saving = true;
7136
7137          if(OnSaveFile(fileName))
7138          {
7139             //if(OnFileModified != Window::OnFileModified)
7140             {
7141                saving = false;
7142                fileMonitor.fileName = fileName;
7143             }
7144             return true;
7145          }
7146          else
7147          {
7148             MessageBox dialog { master = master, type = yesNoCancel, text = "Error writing file", contents = "Save as a different file?" };
7149             DialogResult answer = dialog.Modal();
7150             saving = false;
7151             if(answer != yes) return (bool)answer;
7152          }
7153       }
7154       return MenuFileSaveAs(selection, mods);
7155    }
7156
7157    bool MenuFileSaveAs(MenuItem selection, Modifiers mods)
7158    {
7159       DialogResult result = (DialogResult)bool::true;
7160       FileDialog fileDialog = saveDialog;
7161
7162       if(!fileDialog)
7163          fileDialog = FileDialog {};
7164       if(fileDialog)
7165       {
7166          incref fileDialog;
7167          if(fileName)
7168             fileDialog.filePath = fileName;
7169          else
7170          {
7171             char filePath[MAX_FILENAME];
7172             sprintf(filePath, "Untitled %d", documentID);
7173             fileDialog.filePath = filePath;
7174          }
7175          fileMonitor.fileName = null;
7176
7177          fileDialog.type = save;
7178          fileDialog.text = "Save As";
7179
7180          while(true)
7181          {
7182             fileDialog.master = master.parent ? master : this;
7183             if(fileDialog.Modal() == ok)
7184             {
7185                char * filePath = fileDialog.filePath;
7186                saving = true;
7187                if(OnSaveFile(filePath))
7188                {
7189                   saving = false;
7190                   property::fileName = filePath;
7191                   NotifySaved(master, this, filePath);
7192                   break;
7193                }
7194                else
7195                {
7196                   MessageBox dialog { master = master.parent ? master : this, type = yesNoCancel, text = "Error writing file", contents = "Save as a different file?" };
7197                   DialogResult answer = dialog.Modal();
7198                   saving = false;
7199                   if(answer != yes) 
7200                   {
7201                      result = answer;
7202                      break;
7203                   }
7204                }
7205             }
7206             else
7207             {
7208                result = cancel;
7209                break;
7210             }
7211          }
7212          //if(OnFileModified != Window::OnFileModified && fileName)
7213          {
7214             if(fileName)
7215                fileMonitor.fileName = fileName;
7216          }
7217          delete fileDialog;
7218       }
7219       return (bool)result; // Actually returning result from Yes/NoCancel message box
7220    }
7221
7222    bool MenuFileSaveAll(MenuItem selection, Modifiers mods)
7223    {
7224       Window document = activeChild;
7225       Window next;
7226       for(document = children.first; document; document = next)
7227       {
7228          next = document.next;
7229          if(document.style.isDocument || document.fileName)
7230             document.MenuFileSave(selection, mods);
7231       }
7232       return true;
7233    }
7234
7235    bool MenuWindowArrangeIcons(MenuItem selection, Modifiers mods)
7236    {
7237       Window document;
7238
7239       for(document = children.first; document; document = document.next)
7240          //if(document.style.isDocument && document.state == minimized)
7241          if(document.style.isActiveClient && document.state == minimized)
7242             document.SetState(minimized, false, mods);
7243       return true;
7244    }
7245
7246    bool MenuWindowCascade(MenuItem selection, Modifiers mods)
7247    {
7248       Window document = activeChild;
7249       if(document)
7250       {
7251          Window firstDocument = null;
7252          Window child;
7253          OldLink cycle = document.cycle.prev;
7254          int id = 0;
7255          while(true)
7256          {
7257             child = cycle.data;
7258             if(child.style.isActiveClient && !child.style.hidden)
7259             {
7260                Window last;
7261
7262                firstDocument = child;
7263                if(child.state == minimized)
7264                   child.SetState(minimized, false, mods);
7265                else
7266                {
7267                   child.positionID = id++;
7268                   child.SetState(normal, false, mods);
7269                   child.anchor.left.type = cascade;
7270                   {
7271                      int x, y, w, h;
7272                      child.normalSizeAnchor = *&child.sizeAnchor;
7273                      child.normalAnchor = child.anchor;
7274
7275                      // Break the anchors for moveable/resizable windows
7276                      if(child.style.fixed)
7277                      {
7278                         child.ComputeAnchors(child.anchor, *&child.sizeAnchor, &x, &y, &w, &h);
7279
7280                         (*&child.normalAnchor).left = x;
7281                         (*&child.normalAnchor).top = y;
7282                         (*&child.normalAnchor).right.type = none;
7283                         (*&child.normalAnchor).bottom.type = none;
7284
7285                         child.normalSizeAnchor.isClientW = false;
7286                         child.normalSizeAnchor.isClientH = false;
7287                         child.normalSizeAnchor.size.w = w;
7288                         child.normalSizeAnchor.size.h = h;
7289                         child.anchored = false;
7290                      }
7291
7292                      if(child.state == normal /*|| child.state == Hidden */)   // Hidden is new here ...
7293                      {
7294                         child.stateAnchor = child.normalAnchor;
7295                         child.stateSizeAnchor = child.normalSizeAnchor;
7296
7297                         child.ComputeAnchors(child.stateAnchor, child.stateSizeAnchor, &x, &y, &w, &h);
7298                         child.Position(x, y, w, h, true, true, true, true, false, false);
7299                      }
7300                   }
7301                }
7302
7303                last = children.last;
7304                if(!child.style.stayOnTop)
7305                   for(; last && last.style.stayOnTop; last = last.prev);
7306                children.Move(child, last);
7307                childrenOrder.Move(child.order, childrenOrder.last);
7308             }
7309             if(cycle == document.cycle) break;
7310             cycle = cycle.prev;
7311          }
7312          if(firstDocument)
7313             firstDocument.Activate();
7314       }
7315       return true;
7316    }
7317
7318    bool MenuWindowClose(MenuItem selection, Modifiers mods)
7319    {
7320       if(style.hasClose)
7321          Destroy(0);
7322       return true;
7323    }
7324
7325    // Close all closes all active clients, not all documents
7326    bool MenuWindowCloseAll(MenuItem selection, Modifiers mods)
7327    {
7328       Window next, document;
7329
7330       for(document = children.first; document; document = next)
7331       {
7332          for(next = document.next; next && !(next.style.isActiveClient; next = next.next);
7333          if(document.style.isActiveClient)
7334             if(!document.Destroy(0) && !document.style.hidden)
7335                return false;
7336       }
7337       return true;
7338    }
7339
7340    bool MenuWindowMaximize(MenuItem selection, Modifiers mods)
7341    {
7342       if(style.hasMaximize && state != maximized)
7343          SetState(maximized, 0, 0);
7344       return true;
7345    }
7346
7347    bool MenuWindowMinimize(MenuItem selection, Modifiers mods)
7348    {
7349       if(style.hasMinimize && state != minimized)
7350       {
7351          SetState(minimized, 0, 0);
7352          parent.CycleChildren(false, true, false, true);
7353       }
7354       return true;
7355    }
7356
7357    bool MenuWindowMove(MenuItem selection, Modifiers mods)
7358    {
7359       MenuMoveOrSize(false, selection ? true : false);
7360       return true;
7361    }
7362
7363    bool MenuWindowNext(MenuItem selection, Modifiers mods)
7364    {
7365       CycleChildren(false, true, false, true);
7366       return true;
7367    }
7368
7369    bool MenuWindowPrevious(MenuItem selection, Modifiers mods)
7370    {
7371       CycleChildren(true, true, false, true);
7372       return true;
7373    }
7374
7375    bool MenuWindowSize(MenuItem selection, Modifiers mods)
7376    {
7377       MenuMoveOrSize(true, true);
7378       return true;
7379    }
7380
7381    bool MenuWindowRestore(MenuItem selection, Modifiers mods)
7382    {
7383       if(state != normal)
7384          SetState(normal, 0, 0);
7385       return true;
7386    }
7387
7388    bool MenuWindowSelectWindow(MenuItem selection, Modifiers mods)
7389    {
7390       Window document;
7391       int id = selection.id;
7392       OldLink cycle = activeClient.cycle;
7393       int c = 0;
7394       //for(c = 0, cycle = activeChild.cycle; c<id; cycle = cycle.next, c++);
7395       while(true)
7396       {
7397          Window sibling = cycle.data;
7398          if(sibling.style.isActiveClient)
7399          {
7400             if(c == id)
7401                break;
7402             c++;
7403          }
7404          cycle = cycle.next;
7405       }
7406       document = cycle.data;
7407       document.Activate();
7408       
7409       //if(activeChild.state == maximized)
7410       //  document.SetState(maximized, false, mods);
7411       //else if(document.state == minimized)
7412       //   document.SetState(normal, false, mods);
7413       return true;
7414    }
7415
7416    bool MenuWindowStayOnTop(MenuItem selection, Modifiers mods)
7417    {
7418       stayOnTop = !style.stayOnTop;
7419       return true;
7420    }
7421
7422    bool MenuWindowTileHorz(MenuItem selection, Modifiers mods)
7423    {
7424       Window document = activeChild;
7425       if(document)
7426       {
7427          Window firstDocument = null;
7428          OldLink cycle = document.cycle;
7429          int id = 0;
7430          while(true)
7431          {
7432             Window child = cycle.data;
7433             if(child.style.isActiveClient && !child.style.hidden)
7434             {
7435                if(!firstDocument) firstDocument = child;
7436                if(child.state == minimized)
7437                   child.SetState(minimized, false, mods);
7438                else
7439                {
7440                   child.positionID = id++;
7441                   child.SetState(normal, false, mods);
7442                   child.ActivateEx(true, false, false, false, null, null);   // To move active clients on top of other windows
7443
7444                   child.anchor.left.type = hTiled;
7445                   {
7446                      int x, y, w, h;
7447                      child.normalSizeAnchor = *&child.sizeAnchor;
7448                      child.normalAnchor = child.anchor;
7449
7450                      // Break the anchors for moveable/resizable windows
7451                      if(child.style.fixed)
7452                      {
7453                         child.ComputeAnchors(child.anchor, *&child.sizeAnchor, &x, &y, &w, &h);
7454
7455                         (*&child.normalAnchor).left = x;
7456                         (*&child.normalAnchor).top = y;
7457                         (*&child.normalAnchor).right.type = none;
7458                         (*&child.normalAnchor).bottom.type = none;
7459                         child.normalSizeAnchor.isClientW = false;
7460                         child.normalSizeAnchor.isClientH = false;
7461                         child.normalSizeAnchor.size.w = w;
7462                         child.normalSizeAnchor.size.h = h;
7463                         child.anchored = false;
7464                      }
7465
7466                      if(child.state == normal /*|| child.state == Hidden */)   // Hidden is new here ...
7467                      {
7468                         child.stateAnchor = child.normalAnchor;
7469                         child.stateSizeAnchor = child.normalSizeAnchor;
7470
7471                         child.ComputeAnchors(child.stateAnchor, child.stateSizeAnchor, &x, &y, &w, &h);
7472                         child.Position(x,y, w, h, true, true, true, true, false, true);
7473                      }
7474                   }
7475                }
7476             }
7477             if((cycle = cycle.next) == document.cycle) break;
7478          }
7479          if(firstDocument)
7480             firstDocument.Activate();
7481       }
7482       return true;
7483    }
7484
7485    bool MenuWindowTileVert(MenuItem selection, Modifiers mods)
7486    {
7487       Window document = activeChild;
7488       if(document)
7489       {
7490          Window firstDocument = null;
7491          Window child;
7492          OldLink cycle = document.cycle;
7493          int id = 0;
7494          while(true)
7495          {
7496             child = cycle.data;
7497             //if(child.style.isDocument)
7498             if(child.style.isActiveClient && !child.style.hidden)
7499             {
7500                if(!firstDocument) firstDocument = child;
7501                if(child.state == minimized)
7502                   child.SetState(minimized, false, mods);
7503                else
7504                {
7505                   child.positionID = id++;
7506                   child.SetState(normal, false, mods);
7507                   child.ActivateEx(true, false, false, false, null, null);   // To move active clients on top of other windows
7508
7509                   child.anchor.left.type = vTiled;
7510                   {
7511                      int x, y, w, h;
7512                      child.normalSizeAnchor = *&child.sizeAnchor;
7513                      child.normalAnchor = child.anchor;
7514
7515                      // Break the anchors for moveable/resizable windows
7516                      if(child.style.fixed)
7517                      {
7518                         child.ComputeAnchors(child.anchor, *&child.sizeAnchor, &x, &y, &w, &h);
7519
7520                         (*&child.normalAnchor).left = x;
7521                         (*&child.normalAnchor).top = y;
7522                         (*&child.normalAnchor).right.type = none;
7523                         (*&child.normalAnchor).bottom.type = none;
7524                         child.normalSizeAnchor.isClientW = false;
7525                         child.normalSizeAnchor.isClientH = false;
7526                         child.normalSizeAnchor.size.w = w;
7527                         child.normalSizeAnchor.size.h = h;
7528                         child.anchored = false;
7529                      }
7530
7531                      if(child.state == normal /*|| child.state == Hidden */)   // Hidden is new here ...
7532                      {
7533                         child.stateAnchor = child.normalAnchor;
7534                         child.stateSizeAnchor = child.normalSizeAnchor;
7535
7536                         child.ComputeAnchors(child.stateAnchor, child.stateSizeAnchor, &x, &y, &w, &h);
7537                         child.Position(x,y, w, h, true, true, true, true, false, true);
7538                      }
7539                   }
7540                }
7541             }
7542             if((cycle = cycle.next) == document.cycle) break;
7543          }
7544          if(firstDocument)
7545             firstDocument.Activate();
7546       }
7547       return true;
7548    }
7549
7550    bool MenuWindowWindows(MenuItem selection, Modifiers mods)
7551    {
7552       WindowList dialog { master = this };
7553       Window document = (Window)dialog.Modal();
7554       if(document)
7555       {
7556          if(activeChild.state == maximized)
7557             document.SetState(maximized, false, mods);
7558          else if(document.state == minimized)
7559             document.SetState(normal, false, mods);
7560          document.Activate();
7561       }
7562       return true;
7563    }
7564
7565    // Virtual Methods
7566    virtual bool OnCreate(void);
7567    virtual void OnDestroy(void);
7568    virtual void OnDestroyed(void);
7569    virtual bool OnClose(bool parentClosing);
7570    virtual bool OnStateChange(WindowState state, Modifiers mods);
7571    virtual bool OnPostCreate(void);
7572    virtual bool OnMoving(int *x, int *y, int w, int h);
7573    virtual bool OnResizing(int *width, int *height);
7574    virtual void OnResize(int width, int height);
7575    virtual void OnPosition(int x, int y, int width, int height);
7576    virtual bool OnLoadGraphics(void);
7577    virtual void OnApplyGraphics(void);
7578    virtual void OnUnloadGraphics(void);
7579    virtual void OnRedraw(Surface surface);
7580    virtual bool OnActivate(bool active, Window previous, bool * goOnWithActivation, bool direct);
7581    virtual void OnActivateClient(Window client, Window previous);
7582    virtual bool OnKeyDown(Key key, unichar ch);
7583    virtual bool OnKeyUp(Key key, unichar ch);
7584    virtual bool OnKeyHit(Key key, unichar ch);
7585    virtual bool OnSysKeyDown(Key key, unichar ch);
7586    virtual bool OnSysKeyUp(Key key, unichar ch);
7587    virtual bool OnSysKeyHit(Key key, unichar ch);
7588    virtual bool OnMouseOver(int x, int y, Modifiers mods);
7589    virtual bool OnMouseLeave(Modifiers mods);
7590    virtual bool OnMouseMove(int x, int y, Modifiers mods);
7591    virtual bool OnLeftButtonDown(int x, int y, Modifiers mods);
7592    virtual bool OnLeftButtonUp(int x, int y, Modifiers mods);
7593    virtual bool OnLeftDoubleClick(int x, int y, Modifiers mods);
7594    virtual bool OnRightButtonDown(int x, int y, Modifiers mods);
7595    virtual bool OnRightButtonUp(int x, int y, Modifiers mods);
7596    virtual bool OnRightDoubleClick(int x, int y, Modifiers mods);
7597    virtual bool OnMiddleButtonDown(int x, int y, Modifiers mods);
7598    virtual bool OnMiddleButtonUp(int x, int y, Modifiers mods);
7599    virtual bool OnMiddleDoubleClick(int x, int y, Modifiers mods);
7600    virtual void OnMouseCaptureLost(void);
7601    virtual void OnHScroll(ScrollBarAction action, int position, Key key);
7602    virtual void OnVScroll(ScrollBarAction action, int position, Key key);
7603    virtual void OnDrawOverChildren(Surface surface);
7604    virtual bool OnFileModified(FileChange fileChange, char * param);
7605    virtual bool OnSaveFile(char * fileName);
7606
7607    // Skins Virtual Functions
7608    virtual void GetDecorationsSize(MinMaxValue * w, MinMaxValue * h);
7609    virtual void SetWindowMinimum(MinMaxValue * mw, MinMaxValue * mh);
7610    virtual void SetWindowArea(int * x, int * y, MinMaxValue * w, MinMaxValue * h, MinMaxValue * cw, MinMaxValue * ch)
7611    {
7612       *cw = *w;
7613       *ch = *h;      
7614    }
7615    virtual void ShowDecorations(Font captionFont, Surface surface, char * name, bool active, bool moving);
7616    virtual void PreShowDecorations(Font captionFont, Surface surface, char * name, bool active, bool moving);
7617    virtual bool IsMouseMoving(int x, int y, int w, int h);
7618    virtual bool IsMouseResizing(int x, int y, int w, int h, bool *resizeX, bool *resizeY, bool *resizeEndX, bool *resizeEndY);
7619    virtual void UpdateNonClient();
7620    virtual void SetBox(Box box);
7621    virtual bool IsInside(int x, int y)
7622    {
7623       return box.IsPointInside({x, y});
7624    }
7625    virtual bool IsOpaque()
7626    {
7627       return (!style.drawBehind || background.a == 255);
7628    }
7629
7630    // Notifications
7631    virtual bool Window::NotifyActivate(Window window, bool active, Window previous);
7632    virtual void Window::NotifyDestroyed(Window window, DialogResult result);
7633    virtual void Window::NotifySaved(Window window, char * filePath);
7634
7635    // Public Methods
7636
7637    // Properties
7638    property Window parent
7639    {
7640       property_category "Layout"
7641       set
7642       {
7643          if(value || guiApp.desktop)
7644          {
7645             Window last;
7646             Window oldParent = parent;
7647             Anchor anchor = this.anchor;
7648
7649             if(value && value.IsDescendantOf(this)) return;
7650             if(value && value == this)
7651                return;
7652             if(!value) value = guiApp.desktop;
7653
7654             if(value == oldParent) return;
7655
7656             if(!master || (master == this.parent && master == guiApp.desktop))
7657                property::master = value;
7658             
7659             if(parent)
7660             {
7661                parent.children.Remove(this);
7662
7663                parent.Update(
7664                {
7665                   box.left - absPosition.x + parent.absPosition.x + style.nonClient * parent.clientStart.x,
7666                   box.top - absPosition.y + parent.absPosition.y + style.nonClient * parent.clientStart.y,
7667                   box.right - absPosition.x + parent.absPosition.x + style.nonClient * parent.clientStart.x,
7668                   box.bottom - absPosition.y + parent.absPosition.y + style.nonClient * parent.clientStart.y
7669                });
7670             }
7671
7672             last = value.children.last;
7673
7674             if(style.isDocument)
7675             {
7676                if(parent)
7677                   parent.numDocuments--;
7678                documentID = value.GetDocumentID();
7679             }
7680
7681             if(style.isActiveClient && !style.hidden)
7682             {
7683                if(parent && parent != guiApp.desktop && !(style.hidden))
7684                {
7685                   if(state == minimized) parent.numIcons--;
7686                   parent.numPositions--;
7687                }
7688             }
7689
7690             if(!style.stayOnTop)
7691                for(; last && last.style.stayOnTop; last = last.prev);
7692
7693             value.children.Insert(last, this);
7694
7695             // *** NEW HERE: ***
7696             if(cycle)
7697                parent.childrenCycle.Delete(cycle);
7698             if(order)
7699                parent.childrenOrder.Delete(order);
7700             cycle = null;
7701             order = null;
7702
7703             //if(created)
7704             {
7705                if(created)
7706                {
7707                   int x = position.x, y = position.y, w = size.w, h = size.h;
7708                   
7709                   int vpw, vph;
7710
7711                   x += parent.absPosition.x - value.absPosition.x + parent.clientStart.x - value.clientStart.x;
7712                   y += parent.absPosition.y - value.absPosition.y + parent.clientStart.y - value.clientStart.y;
7713                   
7714                   vpw = value.clientSize.w;
7715                   vph = value.clientSize.h;
7716                   if(style.nonClient)
7717                   {
7718                      vpw = value.size.w;
7719                      vph = value.size.h;
7720                   }
7721                   else if(style.fixed)
7722                   {
7723                      if(!style.dontScrollHorz && value.scrollArea.w) vpw = value.scrollArea.w;
7724                      if(!style.dontScrollVert && value.scrollArea.h) vph = value.scrollArea.h;
7725                   }
7726
7727                   anchor = this.anchor;
7728
7729                   if(anchor.left.type == offset)            anchor.left.distance = x;
7730                   else if(anchor.left.type == relative)     anchor.left.percent = (float)x / vpw;
7731                   if(anchor.top.type == offset)             anchor.top.distance = y;
7732                   else if(anchor.top.type == relative)      anchor.top.percent = (float)y / vph;
7733                   if(anchor.right.type == offset)           anchor.right.distance = vpw - (x + w);
7734                   //else if(anchor.right.type == relative)  anchor.right.percent = 1.0-(float) (vpw - (x + w)) / vpw;
7735                   else if(anchor.right.type == relative)    anchor.right.percent = (float) (vpw - (x + w)) / vpw;
7736                   if(anchor.bottom.type == offset)          anchor.bottom.distance = vph - (y + h);
7737                   //else if(anchor.bottom.type == relative) anchor.bottom.percent = 1.0-(float) (vph - (y + h)) / vph;
7738                   else if(anchor.bottom.type == relative)   anchor.bottom.percent = (float) (vph - (y + h)) / vph;
7739
7740                   if(!anchor.left.type && !anchor.right.type)
7741                   {
7742                      anchor.horz.distance = (x + w / 2) - (vpw / 2);
7743                      //anchor.horz.type = anchor.horz.distance ? AnchorValueOffset : 0;
7744                   }
7745                   else if(anchor.horz.type == middleRelative) anchor.horz.percent = (float) ((x + w / 2) - (vpw / 2)) / vpw;
7746                   if(!anchor.top.type && !anchor.bottom.type)
7747                   {
7748                      anchor.vert.distance = (y + h / 2) - (vph / 2);
7749                      //anchor.vert.type = anchor.vert.distance ? AnchorValueOffset : 0;
7750                   }
7751                   else if(anchor.vert.type == middleRelative) anchor.vert.percent = (float)((y + h / 2) - (vph / 2)) / vph;
7752                }
7753                parent = value;
7754
7755                // *** NEW HERE ***
7756                if(!style.inactive)
7757                {
7758                   if(!style.noCycle)
7759                      parent.childrenCycle.Insert(
7760                         (parent.activeChild && parent.activeChild.cycle) ? parent.activeChild.cycle.prev : null, 
7761                         cycle = OldLink { data = this });
7762                   parent.childrenOrder.Insert(
7763                      (parent.activeChild && parent.activeChild.order) ? parent.activeChild.order.prev : parent.childrenOrder.last, 
7764                      order = OldLink { data = this });
7765                }
7766
7767                if(!style.hidden && style.isActiveClient)
7768                {
7769                   positionID = parent.GetPositionID(this);
7770                   parent.numPositions++;
7771                   if(state == minimized) parent.numIcons--;
7772                }
7773
7774                // *** FONT INHERITANCE ***
7775                if(!setFont && oldParent) 
7776                   stopwatching(oldParent, font);
7777
7778                if(systemFont)
7779                {
7780                   RemoveResource(systemFont);
7781                   delete systemFont;
7782                }
7783                // TESTING WITH WATCHERS:
7784                usedFont = setFont ? setFont : (parent.parent ? parent.usedFont : systemFont);
7785                // usedFont = setFont ? setFont : (systemFont);
7786
7787                if(!usedFont)
7788                {
7789                   if(guiApp.currentSkin)
7790                   {
7791                      systemFont = guiApp.currentSkin.SystemFont();
7792                      incref systemFont;
7793                   }
7794                   usedFont = systemFont;
7795                   AddResource(systemFont);
7796                }
7797
7798                if(!setFont)
7799                   watch(value)
7800                   {
7801                      font
7802                      {
7803                         usedFont = setFont ? setFont : (parent.parent ? parent.usedFont : systemFont);
7804                         firewatchers font;
7805                         Update(null);
7806                      }
7807                   };
7808                
7809                firewatchers font;
7810
7811
7812                if(value.rootWindow && value.rootWindow.display && rootWindow)
7813                {
7814                   bool reloadGraphics = (oldParent.rootWindow == oldParent && value.rootWindow) || (!value.rootWindow && rootWindow == this) || 
7815                         (value.rootWindow.display && value.rootWindow.display.displaySystem != rootWindow.display.displaySystem);
7816                   
7817                   if(reloadGraphics)
7818                      UnloadGraphics(false);
7819                   SetupDisplay();
7820                   if(reloadGraphics)
7821                      LoadGraphics(false, false);
7822                      
7823                   /*
7824                   if(value.rootWindow != rootWindow)
7825                      DisplayModeChanged();
7826                   else
7827                   */
7828                }
7829                scrolledPos.x = MININT; // Prevent parent update
7830                property::anchor = anchor;
7831                /*
7832                {
7833                   int x, y, w, h;
7834                   if(guiApp.currentSkin)
7835                      guiApp.currentSkin.SetWindowMinimum(this, &skinMinSize.w, &skinMinSize.h);
7836
7837                   ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
7838                   Position(x, y, w, h, true, true, true, true, false, true);
7839                }
7840                */
7841
7842             }
7843             // else parent = value;
7844          }
7845       }
7846       get { return parent; }
7847    };
7848
7849    property Window master
7850    {
7851       property_category "Behavior"
7852       set
7853       {
7854          //if(this == value) return;
7855          if(value && value.IsSlaveOf(this)) return;
7856
7857          if(master != value)
7858          {
7859             if(master)
7860             {
7861                OldLink slaveHolder;
7862                for(slaveHolder = master.slaves.first; slaveHolder; slaveHolder = slaveHolder.next)
7863                   if(slaveHolder.data == this)
7864                   {
7865                      master.slaves.Delete(slaveHolder);
7866                      break;
7867                   }
7868             }
7869
7870             if(value)
7871             {
7872                value.slaves.Add(OldLink { data = this });
7873
7874                if(hotKey)
7875                {
7876                   if(master)
7877                      master.hotKeys.Remove(hotKey);
7878                   value.hotKeys.Add(hotKey);
7879                   hotKey = null;
7880                }
7881                if(master && master.defaultControl == this)
7882                   master.defaultControl = null;
7883
7884                if(style.isDefault && !value.defaultControl)
7885                   value.defaultControl = this;
7886
7887             }
7888          }
7889          master = value;
7890       }
7891       get { return master ? master : parent; }
7892    };
7893
7894    property char * text
7895    {
7896       property_category "Appearance"
7897       watchable
7898       set
7899       {
7900          delete caption;
7901          if(value)
7902          {
7903             caption = new char[strlen(value)+1];
7904             if(caption)
7905                strcpy(caption, value);
7906          }
7907          if(created)
7908             UpdateCaption();
7909       }
7910       get { return caption; }
7911    };
7912
7913    property Key hotKey
7914    {
7915       property_category "Behavior"
7916       set
7917       {
7918          setHotKey = value;
7919          if(created)
7920          {
7921             if(value)
7922             {
7923                if(!hotKey)
7924                   master.hotKeys.Add(hotKey = HotKeySlot { });
7925                if(hotKey)
7926                {
7927                   hotKey.key = value;
7928                   hotKey.window = this;
7929                }
7930             }
7931             else if(hotKey)
7932             {
7933                master.hotKeys.Delete(hotKey);
7934                hotKey = null;
7935             }
7936          }
7937       }
7938       get { return hotKey ? hotKey.key : 0; }
7939    };
7940
7941    property Color background
7942    {
7943       property_category "Appearance"
7944       set
7945       {
7946          background.color = value;
7947          firewatchers;
7948          if(created)
7949          {
7950             Update(null);
7951             if(this == rootWindow)
7952                guiApp.interfaceDriver.SetRootWindowColor(this);
7953          }
7954       }
7955       get { return background.color; }
7956    };
7957
7958    property Percentage opacity
7959    {
7960       property_category "Appearance"
7961       set
7962       {
7963          background.a = (byte)Min(Max((int)(value * 255), 0), 255);
7964          drawBehind = background.a ? false : true;
7965       }
7966       get { return background.a / 255.0f; }
7967    };
7968
7969    property Color foreground
7970    {
7971       property_category "Appearance"
7972       set
7973       {
7974          foreground = value;
7975          firewatchers;
7976          if(created)
7977             Update(null);
7978       }
7979       get { return foreground; }
7980    };
7981
7982    property BorderStyle borderStyle
7983    {
7984       property_category "Appearance"
7985       set
7986       {
7987          if(!((BorderBits)value).fixed)
7988          {
7989             style.hasClose = false;
7990             style.hasMaximize = false;
7991             style.hasMinimize = false;
7992          }
7993          style.borderBits = value;
7994          if(created)
7995          {
7996             int x, y, w, h;
7997             SetWindowMinimum(&skinMinSize.w, &skinMinSize.h);
7998
7999             ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
8000             Position(x, y, w, h, true, true, true, true, false, true);
8001             CreateSystemChildren();
8002          }
8003       }
8004       get { return (BorderStyle)style.borderBits; } 
8005    };
8006
8007    property Size minClientSize
8008    {
8009       property_category "Layout"
8010       set { minSize = value; }
8011       get { value = minSize; }
8012    };
8013
8014    property Size maxClientSize
8015    {
8016       property_category "Layout"
8017       set { maxSize = value; }
8018       get { value = maxSize; }
8019    };
8020
8021    property bool hasMaximize
8022    {
8023       property_category "Window Style"
8024       set
8025       {
8026          style.hasMaximize = value;
8027          if(value) { style.fixed = true; style.contour = true; }
8028          if(created)
8029          {
8030             int x, y, w, h;
8031             SetWindowMinimum(&skinMinSize.w, &skinMinSize.h);
8032
8033             ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
8034             Position(x, y, w, h, true, true, true, true, false, true);
8035
8036             CreateSystemChildren();
8037          }
8038       }
8039       get { return style.hasMaximize; }
8040    };
8041
8042    property bool hasMinimize
8043    {
8044       property_category "Window Style"
8045       set
8046       {
8047          style.hasMinimize = value;
8048          if(value) { style.fixed = true; style.contour = true; }
8049          if(created)
8050          {
8051             int x, y, w, h;
8052             SetWindowMinimum(&skinMinSize.w, &skinMinSize.h);
8053
8054             ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
8055             Position(x, y, w, h, true, true, true, true, false, true);
8056
8057             CreateSystemChildren();
8058          }
8059       }
8060       get { return style.hasMinimize;  }
8061    };
8062
8063    property bool hasClose
8064    {
8065       property_category "Window Style"
8066       set
8067       {
8068          style.hasClose = value;
8069          if(value) { style.fixed = true; style.contour = true; }
8070          if(created)
8071          {
8072             int x, y, w, h;
8073             SetWindowMinimum(&skinMinSize.w, &skinMinSize.h);
8074             ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
8075             Position(x, y, w, h, true, true, true, true, false, true);
8076             CreateSystemChildren();
8077          }
8078       }
8079       get { return style.hasClose; }
8080    };
8081    
8082    property bool nonClient
8083    {
8084       property_category "Layout"
8085       set
8086       {
8087          style.nonClient = value;
8088          if(value)
8089             style.stayOnTop = true;
8090       }
8091       get { return style.nonClient; }
8092    };
8093
8094    property bool inactive
8095    {
8096       property_category "Behavior"
8097       set
8098       {
8099          if(value) 
8100          {
8101             // *** NEW HERE: ***
8102             if(!style.inactive)
8103             {
8104                if(cycle)
8105                   parent.childrenCycle.Delete(cycle);
8106                if(order)
8107                   parent.childrenOrder.Delete(order);
8108                cycle = null;
8109                order = null;
8110             }
8111
8112             if(created)
8113             {
8114                active = false; // true;
8115                if(parent.activeChild == this)
8116                   parent.activeChild = null;
8117                if(parent.activeClient == this)
8118                   parent.activeClient = null;
8119             }
8120          }
8121          else
8122          {
8123             if(style.inactive)
8124             {
8125                if(!style.noCycle)
8126                {
8127                   parent.childrenCycle.Insert(
8128                      (parent.activeChild && parent.activeChild.cycle) ? parent.activeChild.cycle.prev : null, 
8129                      cycle = OldLink { data = this });
8130                }
8131                parent.childrenOrder.Insert(
8132                   (parent.activeChild && parent.activeChild.order) ? parent.activeChild.order.prev : parent.childrenOrder.last,
8133                   order = OldLink { data = this });
8134             }
8135          }
8136          style.inactive = value;
8137       }
8138       get { return style.inactive; }
8139    };
8140
8141    property bool clickThrough
8142    {
8143       property_category "Behavior"
8144       set { style.clickThrough = value; }
8145       get { return style.clickThrough; }
8146    };
8147
8148    property bool isRemote
8149    {
8150       property_category "Behavior"
8151       set { style.isRemote = value; }
8152       get { return style.isRemote; }
8153    };
8154
8155    property bool noCycle
8156    {
8157       property_category "Behavior"
8158       set { style.noCycle = value; }
8159       get { return style.noCycle; }
8160    };
8161
8162    property bool isModal
8163    {
8164       property_category "Behavior"
8165       set { style.modal = value; }
8166       get { return style.modal; }
8167    };
8168
8169    property bool interim
8170    {
8171       property_category "Behavior"
8172       set { style.interim = value; }
8173       get { return style.interim; }
8174    };
8175
8176    property bool tabCycle
8177    {
8178       property_category "Behavior"
8179       set { style.tabCycle = value; }
8180       get { return style.tabCycle; }
8181    };
8182      
8183    property bool isDefault
8184    {
8185       property_category "Behavior"
8186       set
8187       {
8188          if(master)
8189          {
8190             if(value)
8191             {
8192                Window sibling;
8193                /*for(sibling = parent.children.first; sibling; sibling = sibling.next)
8194                   if(sibling != this && sibling.style.isDefault)
8195                      sibling.style.isDefault = false;*/
8196                if(master.defaultControl)
8197                   master.defaultControl.style.isDefault = false;
8198                master.defaultControl = this;
8199             }
8200             else if(master.defaultControl == this)
8201                master.defaultControl = null;
8202
8203             // Update(null);
8204          }
8205          style.isDefault = value;
8206          if(created)
8207             Position(position.x, position.y, size.w, size.h, true, true, true,true,true, true);
8208       }
8209       get { return style.isDefault; }
8210    };
8211
8212    property bool drawBehind
8213    {
8214       property_category "Window Style"
8215       set { style.drawBehind = value; }
8216       get { return style.drawBehind; }
8217    };
8218
8219    property bool hasMenuBar
8220    {
8221       property_category "Window Style"
8222       set
8223       {
8224          if(value) 
8225          {
8226             if(!menu)
8227             {
8228                menu = Menu { };
8229                incref menu;
8230             }
8231             if(created && !menuBar)
8232             {
8233                menuBar =
8234                   PopupMenu 
8235                   {
8236                      this, menu = menu,
8237                      isMenuBar = true,
8238                      anchor = Anchor { top = 23, left = 1, right = 1 },
8239                      size.h = 24,
8240                      inactive = true, nonClient = true                            
8241                   };
8242                menuBar.Create();
8243             }
8244          }
8245          else if(created && menuBar)
8246          {
8247             menuBar.Destroy(0);
8248             menuBar = null;
8249          }
8250          style.hasMenuBar = value;
8251       }
8252       get { return style.hasMenuBar; }
8253    };
8254
8255    property bool hasStatusBar
8256    {
8257       property_category "Window Style"
8258       set
8259       {
8260          if(value)
8261          {
8262             if(!statusBar)
8263             {
8264                statusBar = StatusBar { this };
8265                incref statusBar;
8266                if(created)
8267                   statusBar.Create();
8268             }
8269          }
8270          else if(statusBar)
8271             delete statusBar;
8272          style.hasStatusBar = value;
8273       }
8274       get { return style.hasStatusBar; }
8275    };
8276    property bool stayOnTop
8277    {
8278       property_category "Window Style"
8279       set
8280       {
8281          if(value)
8282          {
8283             if(created && !style.stayOnTop)
8284             {
8285                if(rootWindow == this)
8286                   guiApp.interfaceDriver.OrderRootWindow(this, true);
8287                else if(parent.children.last != this)
8288                {
8289                   parent.children.Move(this, parent.children.last);
8290                   Update(null);
8291                }
8292             }
8293             style.stayOnTop = true;
8294          }
8295          else
8296          {
8297             if(created && style.stayOnTop)
8298             {
8299                if(rootWindow == this)
8300                   guiApp.interfaceDriver.OrderRootWindow(this, false);
8301                else
8302                {
8303                   Window last;
8304                   if(order)
8305                   {
8306                      OldLink order;
8307                      for(order = (this.order == parent.childrenOrder.first) ? null : this.order.prev; 
8308                          order && ((Window)order.data).style.stayOnTop;
8309                          order = (order == parent.childrenOrder.first) ? null : order.prev);
8310                       last = order ? order.data : null;
8311                   }
8312                   else
8313                   {
8314                      for(last = parent.children.last; 
8315                          last && last.style.stayOnTop;
8316                          last = last.prev);
8317                   }
8318
8319                   parent.children.Move(this, last);
8320                   Update(null);
8321                }
8322             }
8323             style.stayOnTop = false;
8324          }
8325       }
8326       get { return style.stayOnTop; }
8327    };
8328
8329    property Menu menu
8330    {
8331       property_category "Window Style"
8332       set
8333       {
8334          delete menu;
8335          if(value)
8336          {
8337             menu = value;
8338             incref menu;
8339          }
8340
8341          if(menuBar && !value)
8342          {
8343             menuBar.Destroy(0);
8344             menuBar = null;
8345          }
8346          if(created)
8347          {
8348             if(!menuBar && style.hasMenuBar && value)
8349             {
8350                menuBar = PopupMenu
8351                          { 
8352                             this, menu = value, isMenuBar = true, 
8353                             anchor = Anchor { left = 1, top = 23, right = 1 }, size.h = 24, 
8354                             inactive = true, nonClient = true
8355                          };
8356                 menuBar.Create();
8357             }
8358             UpdateActiveDocument(null);
8359          }
8360       }
8361       get { return menu; }
8362    };
8363
8364    property FontResource font
8365    {
8366       property_category "Appearance"
8367       watchable
8368       isset { return setFont ? true : false; }
8369       set
8370       {
8371          if(this)
8372          {
8373             if(value && !setFont) { stopwatching(parent, font); }
8374             else if(!value && setFont)
8375             {
8376                watch(parent)
8377                {
8378                   font
8379                   {
8380                      usedFont = setFont ? setFont : (parent.parent ? parent.usedFont : systemFont);
8381                      firewatchers font;
8382                      Update(null);
8383                   }
8384                };
8385             }
8386
8387             if(setFont)
8388             {
8389                RemoveResource(setFont);
8390                delete setFont;
8391             }
8392             if(systemFont)
8393             {
8394                RemoveResource(systemFont);
8395                delete systemFont;
8396             }
8397             setFont = value;
8398             if(setFont)
8399             {
8400                incref setFont;
8401                AddResource(setFont);
8402             }
8403
8404             usedFont = setFont ? setFont : ((parent && parent.parent) ? parent.usedFont : systemFont);
8405             if(!usedFont)
8406             {
8407                systemFont = guiApp.currentSkin.SystemFont();
8408                incref systemFont;
8409                usedFont = systemFont;
8410                AddResource(systemFont);
8411             }
8412
8413             firewatchers;
8414
8415             Update(null);
8416          }
8417       }
8418       get { return usedFont; }
8419    };
8420
8421    property SizeAnchor sizeAnchor
8422    {
8423       property_category "Layout"
8424       isset
8425       {
8426          return ((anchor.left.type == none || anchor.left.type == middleRelative || anchor.right.type == none) || 
8427                 (anchor.top.type == none || anchor.top.type == middleRelative || anchor.bottom.type == none)) &&
8428             sizeAnchor.isClientW != sizeAnchor.isClientH;
8429       }
8430       set
8431       {
8432          int x, y, w, h;
8433          sizeAnchor = value;
8434
8435          normalSizeAnchor = sizeAnchor;
8436
8437          if(state == normal /*|| state == Hidden */)   // Hidden is new here ...
8438          {
8439             stateAnchor = normalAnchor;
8440             stateSizeAnchor = normalSizeAnchor;
8441
8442             ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
8443             Position(x,y, w, h, true, true, true, true, false, true);
8444          }
8445       }
8446       get
8447       {
8448          value =
8449          {
8450             { sizeAnchor.isClientW ? clientSize.w : size.w, sizeAnchor.isClientH ? clientSize.h : size.h },
8451             sizeAnchor.isClientW,
8452             sizeAnchor.isClientH
8453          };
8454       }
8455    };
8456
8457    property Size size
8458    {
8459       property_category "Layout"
8460       isset
8461       {
8462          Anchor thisAnchor = anchor;
8463          SizeAnchor thisSizeAnchor = sizeAnchor;
8464          bool leftRight = (anchor.left.type == none || anchor.left.type == middleRelative || anchor.right.type == none);
8465          bool topBottom = (anchor.top.type == none || anchor.top.type == middleRelative || anchor.bottom.type == none);
8466          bool isClient = !sizeAnchor.isClientW && !sizeAnchor.isClientH;
8467          return ((anchor.left.type == none || anchor.left.type == middleRelative || anchor.right.type == none) || 
8468                 (anchor.top.type == none || anchor.top.type == middleRelative || anchor.bottom.type == none)) &&
8469             !sizeAnchor.isClientW && !sizeAnchor.isClientH && sizeAnchor.size.w && sizeAnchor.size.h;
8470       }
8471       set
8472       {
8473          int x, y, w, h;
8474
8475          sizeAnchor.isClientW = false;
8476          sizeAnchor.isClientH = false;
8477          sizeAnchor.size = value;
8478
8479          normalSizeAnchor = sizeAnchor;
8480
8481          if(state == normal /*|| state == Hidden*/)   // Hidden is new here ...
8482          {
8483             stateAnchor = normalAnchor;
8484             stateSizeAnchor = normalSizeAnchor;
8485
8486             ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
8487             Position(x, y, w, h, true, true, true, true, false, true);
8488          }
8489       }
8490       get { value = size; }
8491    };
8492
8493    property Size clientSize
8494    {
8495       property_category "Layout"
8496       isset
8497       {
8498          return ((anchor.left.type == none || anchor.left.type == middleRelative || anchor.right.type == none) || 
8499                 (anchor.top.type == none || anchor.top.type == middleRelative || anchor.bottom.type == none)) &&
8500             sizeAnchor.isClientW && sizeAnchor.isClientH && sizeAnchor.size.w && sizeAnchor.size.h;
8501       }
8502       set
8503       {
8504          int x, y, w, h;
8505          sizeAnchor.isClientW = true;
8506          sizeAnchor.isClientH = true;
8507          sizeAnchor.size = value;
8508
8509          normalSizeAnchor = sizeAnchor;
8510
8511          if(state == normal /*|| state == Hidden */)   // Hidden is new here ...
8512          {
8513             stateAnchor = normalAnchor;
8514             stateSizeAnchor = normalSizeAnchor;
8515
8516             ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
8517             Position(x,y, w, h, true, true, true, true, false, true);
8518          }
8519       }
8520       get { value = clientSize; }
8521    };
8522
8523    property Size initSize { get { value = sizeAnchor.size; } };
8524
8525    property Anchor anchor
8526    {
8527       property_category "Layout"
8528       isset { return (anchor.left.type != offset || anchor.top.type != offset || anchor.right.type || anchor.bottom.type); }
8529
8530       set
8531       {
8532          if(value != null)
8533          {
8534             if(anchor.left.type && anchor.right.type && (!value.left.type || !value.right.type))
8535             {
8536                normalSizeAnchor.isClientW = sizeAnchor.isClientW = false;
8537                normalSizeAnchor.size.w = sizeAnchor.size.w = size.w;
8538             }
8539             if(anchor.top.type && anchor.bottom.type && (!value.top.type || !value.bottom.type))
8540             {
8541                normalSizeAnchor.isClientH = sizeAnchor.isClientH = false;
8542                normalSizeAnchor.size.h = sizeAnchor.size.h = size.h;
8543             }
8544             anchor = value;
8545
8546             if(anchor.right.type && (anchor.horz.type == middleRelative || !anchor.left.type)) 
8547             {
8548                anchor.left.distance = 0;
8549                anchor.horz.type = 0;
8550             }
8551             if(anchor.bottom.type && (anchor.vert.type == middleRelative || !anchor.top.type))
8552             {
8553                anchor.top.distance = 0;
8554                anchor.vert.type = 0;
8555             }
8556
8557             anchored = true;
8558
8559             //if(created)
8560             {
8561                int x, y, w, h;
8562
8563                normalAnchor = anchor;
8564                
8565                // Break the anchors for moveable/resizable windows
8566                /*if(style.fixed ) //&& value.left.type == cascade)
8567                {
8568                   ComputeAnchors(anchor, sizeAnchor, &x, &y, &w, &h);
8569
8570                   this.anchor = normalAnchor = Anchor { left = x, top = y };
8571                   normalSizeAnchor = SizeAnchor { { w, h } };
8572                   anchored = false;
8573                }*/
8574                if(state == normal /*|| state == Hidden */)   // Hidden is new here ...
8575                {
8576                   stateAnchor = normalAnchor;
8577                   stateSizeAnchor = normalSizeAnchor;
8578
8579                   ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
8580                   Position(x, y, w, h, true, true, true, true, false, true);
8581                }
8582             }
8583          }
8584          else
8585          {
8586             anchored = false;
8587          }
8588       }
8589       get { value = this ? anchor : Anchor { }; }
8590    };
8591
8592    property Point position
8593    {
8594       property_category "Layout"
8595       set
8596       {
8597          if(value == null) return;
8598
8599          anchor.left = value.x;
8600          anchor.top  = value.y;
8601          anchor.right.type = none;
8602          anchor.bottom.type = none;
8603          //if(created)
8604          {
8605             int x, y, w, h;
8606
8607             normalAnchor = anchor;
8608
8609             // Break the anchors for moveable/resizable windows
8610             /*
8611             if(style.fixed)
8612             {
8613                ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
8614
8615                normalAnchor.left = x;
8616                normalAnchor.top = y;
8617                normalAnchor.right.type = none;
8618                normalAnchor.bottom.type = none;
8619                normalSizeAnchor.size.width = w;
8620                normalSizeAnchor.size.height = h;
8621                anchored = false;
8622             }
8623             */
8624             if(state == normal /*|| state == Hidden */)   // Hidden is new here ...
8625             {
8626                stateAnchor = normalAnchor;
8627                stateSizeAnchor = normalSizeAnchor;
8628
8629                ComputeAnchors(stateAnchor, stateSizeAnchor, &x, &y, &w, &h);
8630                Position(x,y, w, h, true, true, true, true, false, true);
8631             }
8632          }
8633       }
8634       get { value = position; }
8635    };
8636
8637    property bool disabled
8638    {
8639       property_category "Behavior"
8640       set
8641       {
8642          if(this && disabled != value)
8643          {
8644             disabled = value;
8645             if(created)
8646                Update(null);
8647          }
8648       }
8649       get { return (bool)disabled; }
8650    };
8651
8652    property bool isEnabled
8653    {
8654       get
8655       {
8656          Window parent;
8657          for(parent = this; parent; parent = parent.parent)
8658             if(parent.disabled)
8659                return false;
8660          return true;
8661       }
8662    };
8663
8664    property WindowState state
8665    {
8666       property_category "Behavior"
8667       set { SetState(value, false, 0); }
8668       get { return this ? state : 0; }
8669    };
8670
8671    property bool visible
8672    {
8673       property_category "Behavior"
8674       set
8675       {
8676          if(this && !value && !style.hidden && parent)
8677          {
8678             bool wasActiveChild = parent.activeChild == this;
8679             Window client = null;
8680
8681             style.hidden = true;
8682             if(style.isActiveClient)
8683             {
8684                parent.numPositions--;
8685                if(state == minimized) parent.numIcons--;
8686             }
8687
8688             if(created)
8689             {
8690                OldLink prevOrder = null;
8691
8692                if(rootWindow == this)
8693                   guiApp.interfaceDriver.SetRootWindowState(this, state, false);
8694                else
8695                {
8696                   Box box { scrolledPos.x, scrolledPos.y, scrolledPos.x + size.w - 1, scrolledPos.y + size.h - 1 };
8697                   if(style.nonClient)
8698                   {
8699                      box.left   -= parent.clientStart.x;
8700                      box.top    -= parent.clientStart.y;
8701                      box.right  -= parent.clientStart.x;
8702                      box.bottom -= parent.clientStart.y;
8703                   }
8704                   parent.Update(box);
8705                }
8706                if(_isModal && master && master.modalSlave == this)
8707                   master.modalSlave = null;
8708
8709                if(order)
8710                {
8711                   OldLink tmpPrev = order.prev;
8712                   client = tmpPrev ? tmpPrev.data : null;
8713                   if(client && !client.style.hidden && !client.destroyed && client.created)
8714                      prevOrder = tmpPrev;
8715                   for(;;)
8716                   {
8717                      client = tmpPrev ? tmpPrev.data : null;
8718                      if(client == this) { client = null; break; }
8719                      if(client && ((client.style.hidden) || client.destroyed || !client.created))
8720                      {
8721                         tmpPrev = client.order.prev;
8722                      }
8723                      else
8724                      {
8725                         if(client)
8726                            prevOrder = tmpPrev;
8727                         break;
8728                      }
8729                   }
8730
8731                   // If this window can be an active client, make sure the next window we activate can also be one
8732                   if(!style.nonClient && style.isActiveClient)
8733                   {
8734                      tmpPrev = prevOrder;
8735                      for(;;)
8736                      {
8737                         client = tmpPrev ? tmpPrev.data : null;
8738                         if(client == this) { client = null; break; }
8739                         if(client && (client.style.nonClient || !client.style.isActiveClient || client.style.hidden || client.destroyed || !client.created))
8740                         {
8741                            tmpPrev = client.order.prev;
8742                         }
8743                         else 
8744                         {
8745                            if(client)
8746                               prevOrder = tmpPrev;
8747                            break;
8748                         }
8749                      }
8750                      if(client && client.style.hidden) client = null;
8751                   }
8752                }
8753
8754                if((wasActiveChild /*parent.activeChild == this*/ || guiApp.interimWindow == this) && true /*activate*/)
8755                {
8756                   if(order && prevOrder && prevOrder.data != this)
8757                      ((Window)prevOrder.data).ActivateEx(true, false, false, true, null, null);
8758                   else
8759                      ActivateEx(false, false, false, true, null, null);
8760
8761                   // TESTING THIS HERE FOR HIDING ACTIVE CLIENT
8762                   if(parent.activeClient == this)
8763                   {
8764                      parent.activeClient = null;
8765                      parent.UpdateActiveDocument(null);
8766                   }
8767                }
8768                else if(parent.activeClient == this)
8769                {
8770                   parent.activeClient = client;
8771                   parent.UpdateActiveDocument(this);
8772                }
8773
8774                // *** Not doing this anymore ***
8775               /*
8776                if(cycle)
8777                   parent.childrenCycle.Delete(cycle);
8778                if(order)
8779                   parent.childrenOrder.Delete(order);
8780                cycle = null;
8781                order = null;
8782                */
8783                
8784                SetVisibility(!parent.style.hidden && (style.hidden ? false : true));
8785             }
8786
8787             firewatchers;
8788          }
8789          else if(this && value && style.hidden)
8790          {
8791             style.hidden = false;
8792             if(created)
8793             {
8794                SetVisibility(!parent.style.hidden && (style.hidden ? false : true));
8795                if(rootWindow == this)
8796                   guiApp.interfaceDriver.SetRootWindowState(this, state, true);
8797
8798                if(_isModal && master)
8799                   master.modalSlave = this;
8800
8801                if(style.isActiveClient)
8802                {
8803                   positionID = parent.GetPositionID(this);
8804                   parent.numPositions++;
8805                   if(state == minimized) parent.numIcons++;
8806                }
8807
8808                // *** NOT DOING THIS ANYMORE ***
8809                /*
8810                if(!(style.inactive))
8811                {
8812                   if(!(style.noCycle))
8813                   {
8814                      cycle = parent.childrenCycle.AddAfter(
8815                         (parent.activeChild && parent.activeChild.cycle) ? 
8816                            parent.activeChild.cycle.prev : null, sizeof(OldLink));
8817                      cycle.data = this;
8818                   }
8819                   order = parent.childrenOrder.AddAfter(
8820                      (parent.activeChild && parent.activeChild.order) ? parent.activeChild.order.prev : parent.childrenOrder.last,
8821                      sizeof(OldLink));
8822                   order.data = this;
8823                }
8824                */
8825      
8826                /*
8827                if(true || !parent.activeChild)
8828                   ActivateEx(true, false, true, true, null, null);
8829                */
8830                if(creationActivation == activate)
8831                   ActivateEx(true, false, true, true, null, null);
8832                else if(creationActivation == flash && !object)
8833                   Flash();               
8834
8835                //SetVisibility(!parent.style.hidden && (style.hidden ? false : true));
8836                Update(null);
8837
8838                // rootWindow.
8839                ConsequentialMouseMove(false);
8840             }
8841
8842             firewatchers;
8843          }
8844          else if(this)
8845             style.hidden = !value;
8846       }
8847
8848       get { return (style.hidden || !setVisible) ? false : true; }
8849    };
8850     
8851    property bool isDocument
8852    {
8853       property_category "Document"
8854       set { style.isDocument = value; }
8855       get { return style.isDocument; }
8856    };
8857
8858    property bool mergeMenus
8859    {
8860       property_category "Window Style"
8861       set { mergeMenus = value; }
8862       get { return (bool)mergeMenus; }
8863    };
8864
8865    property bool hasHorzScroll
8866    {
8867       property_category "Window Style"
8868       set
8869       {
8870          if(value)
8871          {
8872             if(!style.hasHorzScroll && created)
8873             {
8874                CreateSystemChildren();         
8875                Position(position.x, position.y, size.w, size.h, false, true, false, false, false, true);
8876             }
8877          }
8878          else if(style.hasHorzScroll)
8879          {
8880             sbh.Destroy(0);
8881             sbh = null;
8882             Position(position.x, position.y, size.w, size.h, false, true, false, false, false, true);
8883          }
8884          style.hasHorzScroll = value;
8885       }
8886
8887       get { return style.hasHorzScroll; }
8888    };
8889
8890    property bool hasVertScroll
8891    {
8892       property_category "Window Style"
8893       set
8894       {
8895          if(value)
8896          {
8897             if(!style.hasVertScroll && created)
8898             {
8899                style.hasVertScroll = true;
8900                CreateSystemChildren();
8901                Position(position.x, position.y, size.w, size.h, false, true, false, false, false, true);
8902             }
8903          }
8904          else if(style.hasVertScroll)
8905          {
8906             sbv.Destroy(0);
8907             sbv = null;
8908             Position(position.x, position.y, size.w, size.h, false, true, false, false, false, true);
8909          }
8910          style.hasVertScroll = value;
8911       }
8912       get { return style.hasVertScroll; }
8913    };
8914
8915    property bool dontHideScroll
8916    {
8917       property_category "Behavior"
8918       set
8919       {
8920          scrollFlags.dontHide = value;
8921          if(value)
8922          {
8923             //UpdateScrollBars(true, true);
8924             Position(position.x, position.y, size.w, size.h, false, true, true, true, true, true);
8925          }
8926          else
8927          {
8928             // UpdateScrollBars(true, true);
8929             Position(position.x, position.y, size.w, size.h, false, true, true, true, true, true);
8930          }
8931       }
8932       get { return scrollFlags.dontHide; }
8933    };
8934
8935    property bool dontScrollVert
8936    {
8937       property_category "Behavior"
8938       set { style.dontScrollVert = value; }
8939       get { return style.dontScrollVert; }
8940    };
8941    property bool dontScrollHorz
8942    {
8943       property_category "Behavior"
8944       set { style.dontScrollHorz = value; }
8945       get { return style.dontScrollHorz; }
8946    };
8947
8948    property bool snapVertScroll
8949    {
8950       property_category "Behavior"
8951       set
8952       {
8953          scrollFlags.snapY = value;
8954          if(sbv) sbv.snap = value;
8955       }
8956       get { return scrollFlags.snapY; }
8957    };
8958    property bool snapHorzScroll
8959    {
8960        property_category "Behavior"
8961       set
8962       {
8963          scrollFlags.snapX = value;
8964          if(sbh) sbh.snap = value;
8965       }
8966       get { return scrollFlags.snapX; }
8967    };
8968
8969    property Point scroll
8970    {
8971       property_category "Behavior"
8972       set
8973       {
8974          // scroll = value;
8975          // TESTING THIS IMPLEMENTATION:
8976          SetScrollPosition(value.x, value.y);
8977       }
8978       get { value = scroll; }
8979    };
8980
8981    property bool modifyVirtualArea
8982    {
8983       property_category "Behavior"
8984       set { modifyVirtArea = value; }
8985       get { return (bool)modifyVirtArea; }
8986    };
8987
8988    property char * fileName
8989    {
8990       property_category "Document"
8991       set
8992       {
8993          if(menu && ((!fileName && value) || (fileName && !value)))
8994          {
8995             MenuItem item = menu.FindItem(MenuFileSave, 0);
8996             if(item) item.disabled = !modifiedDocument && value;
8997          }
8998
8999          delete fileName;
9000
9001          if(value && value[0])
9002             fileName = CopyString(value);
9003
9004          if(parent && this == parent.activeClient)
9005             parent.UpdateActiveDocument(null);
9006          else
9007             UpdateCaption();
9008
9009          // if(style.isDocument)
9010          if(!saving)
9011             fileMonitor.fileName = value;
9012       }
9013       get { return fileName; }
9014    };
9015
9016    property int id
9017    {
9018       property_category "Data"
9019       set { id = value; }
9020       get { return id; }
9021    };
9022
9023    property bool modifiedDocument
9024    {
9025       property_category "Document"
9026       set
9027       {
9028          if(style.isDocument || fileName)
9029          {
9030             if(menu)
9031             {
9032                MenuItem item = menu.FindItem(MenuFileSave, 0);
9033                if(item) item.disabled = !value && fileName;
9034             }
9035          }
9036
9037          if(modifiedDocument != value)
9038          {
9039             modifiedDocument = value;
9040             if(style.isDocument || fileName)
9041                UpdateCaption();
9042          }
9043       }
9044       get { return (bool)modifiedDocument; }
9045    };
9046
9047    property bool showInTaskBar
9048    {
9049       property_category "Window Style"
9050       set { style.showInTaskBar = value; }
9051       get { return (style.showInTaskBar; }
9052    };
9053    property FileDialog saveDialog { set { saveDialog = value; } };
9054    property bool isActiveClient
9055    {
9056       property_category "Behavior"
9057       set { style.isActiveClient = value; }
9058       get { return style.isActiveClient; }
9059    };
9060
9061    property Cursor cursor
9062    {
9063       property_category "Appearance"
9064       set
9065       {
9066          cursor = value;
9067          SelectMouseCursor();
9068       }
9069       get { return cursor; }
9070    };      
9071
9072 //#if !defined(ECERE_VANILLA)
9073    property char * name
9074    {
9075       property_category "Design"
9076       get
9077       {
9078          return (this && object) ? object.name : null;
9079       }
9080       set
9081       {
9082          if(activeDesigner)
9083             activeDesigner.RenameObject(object, value);
9084       }
9085    };
9086 //#endif
9087    property char * displayDriver
9088    {
9089       property_category "Behavior"
9090       set
9091       {
9092          dispDriver = GetDisplayDriver(value);
9093          //DisplayModeChanged();
9094       }
9095       get
9096       {
9097          return dispDriver ? dispDriver.name : null;
9098       }
9099    }
9100
9101    // RUNTIME PROPERTIES
9102    property bool autoCreate { set { autoCreate = value; } get { return (bool)autoCreate; } };
9103    property Size scrollArea
9104    {
9105       property_category "Behavior"
9106       set
9107       {
9108          if(value != null)
9109             SetScrollArea(value.w, value.h, false);
9110          else
9111             SetScrollArea(0,0, true);
9112       }
9113       get { value = scrollArea; }
9114       isset
9115       {
9116          return scrollArea.w > clientSize.w || scrollArea.h > clientSize.h;
9117       }
9118    };
9119    property bool is3D
9120    {
9121       property_category "Layout"
9122       set { if(this) is3D = value; }
9123       get { return (bool)is3D; }
9124    };
9125
9126    // Runtime Only Properties (No Set, can display the displayable ones depending on the type?)
9127                                                                                                             
9128    // Will be merged with font later
9129    property Font fontObject { get { return usedFont ? usedFont.font : null; } };
9130    property Point clientStart { get { value = clientStart; } };
9131    property Point absPosition { get { value = absPosition; } };
9132    property Anchor normalAnchor { get {value = normalAnchor; } };
9133    // property Size normalSizeAnchor { get { value = normalSizeAnchor; } };
9134    property bool active { get { return (bool)active; } };
9135    property bool created { get { return (bool)created; } };
9136    property bool destroyed { get { return (bool)destroyed; } };
9137    property Window firstSlave { get { return slaves.first ? ((OldLink)slaves.first).data : null; } };
9138    property Window firstChild { get { return children.first; } };   
9139    property Window lastChild { get { return children.last; } };   
9140    property Window activeClient { get { return activeClient; } };
9141    property Window activeChild { get { return activeChild; } };
9142    property Display display  { get { return display ? display : ((parent && parent.rootWindow) ? parent.rootWindow.display : null); } };
9143    property DisplaySystem displaySystem { get { return display ? display.displaySystem : null; } };
9144    property ScrollBar horzScroll { get { return sbh; } };
9145    property ScrollBar vertScroll { get { return sbv; } };
9146    property StatusBar statusBar { get { return statusBar; } };
9147    property Window rootWindow { get { return rootWindow; } };   
9148    property bool closing { get { return (bool)closing; } set { closing = value; } };
9149    property int documentID { get { return documentID; } };
9150    property Window previous { get { return prev; } }
9151    property Window next { get { return next; } }
9152    property Window nextSlave { get { OldLink link = master ? master.slaves.FindLink(this) : null; return (link && link.next) ? link.next.data : null; } }
9153    property PopupMenu menuBar { get { return menuBar; } }
9154    property ScrollBar sbv { get { return sbv; } }
9155    property ScrollBar sbh { get { return sbh; } }
9156    property bool fullRender { set { fullRender = value; } get { return (bool)fullRender; } }
9157    property void * systemHandle { get { return windowHandle; } }
9158    property Button minimizeButton { get { return sysButtons[0]; } };
9159    property Button maximizeButton { get { return sysButtons[1]; } };   
9160    property Button closeButton { get { return sysButtons[2]; } };
9161    property BitmapResource icon
9162    {
9163       get { return icon; }
9164       set
9165       {
9166          icon = value;
9167          if(icon) incref icon;
9168          if(created)
9169             guiApp.interfaceDriver.SetIcon(this, value);
9170       }
9171    };
9172    property bool moveable { get { return (bool)moveable; } set { moveable = value; } };
9173    property bool alphaBlend { get { return (bool)alphaBlend; } set { alphaBlend = value; } };
9174    property bool useSharedMemory { get { return (bool)useSharedMemory; } set { useSharedMemory = value; } };
9175    property CreationActivationOption creationActivation { get { return creationActivation; } set { creationActivation = value; } };
9176    property bool nativeDecorations { get { return (bool)nativeDecorations && (formDesigner || rootWindow == this); } set { nativeDecorations = value; } };
9177    property bool manageDisplay { get { return (bool)manageDisplay; } set { manageDisplay = value; } };
9178    
9179 private:
9180    // Data
9181    //char * yo;
9182    Window prev, next;
9183    WindowBits style;       // Window Style
9184    char * caption;            // Name / Caption
9185    Window parent;    // Parent window
9186    OldList children;          // List of children in Z order
9187    Window activeChild;     // Child window having focus
9188    Window activeClient;
9189    Window previousActive;  // Child active prior to activating the default child
9190    Window master;          // Window owning and receiving notifications concerning this window
9191    OldList slaves;            // List of windows belonging to this window
9192    Display display;        // Display this window is drawn into
9193
9194    Point position;         // Position in parent window client area
9195    Point absPosition;      // Absolute position
9196    Point clientStart;      // Client area position from (0,0) in this window
9197    Size size;              // Size
9198    Size clientSize;        // Client area size
9199    Size scrollArea;        // Virtual Scroll area size
9200    Size reqScrollArea;     // Requested virtual area size
9201    Point scroll;           // Virtual area scrolling position
9202    public ScrollBar sbh, sbv;        // Scrollbar window handles
9203    Cursor cursor;        // Mouse cursor used for this window
9204    WindowState state;
9205    PopupMenu menuBar;
9206    StatusBar statusBar;
9207    Button sysButtons[3];
9208    char * fileName;
9209    Box clientArea;         // Client Area box clipped to parent
9210    Key setHotKey;
9211    HotKeySlot hotKey;        // HotKey for this window
9212    int numDocuments;
9213    int numPositions;
9214    Menu menu;
9215    ScrollFlags scrollFlags;// Window Scrollbar Flags
9216    int id;                 // Control ID
9217    int documentID;
9218    ColorAlpha background;  // Background color used to draw the window area
9219    Color foreground;
9220    subclass(DisplayDriver) dispDriver;   // Display driver name for this window
9221    OldList childrenCycle;     // Cycling order
9222    OldLink cycle;             // Element of parent's cycling order
9223    OldList childrenOrder;     // Circular Z-Order
9224    OldLink order;             // Element of parent's circular Z-Order
9225    Window modalSlave;      // Slave window blocking this window's interaction
9226
9227    Window rootWindow;      // Topmost system managed window
9228    void * windowHandle;    // System window handle
9229
9230    DialogResult returnCode;// Return code for modal windows
9231   
9232    Point sbStep;           // Scrollbar line scrolling steps
9233
9234    Anchor stateAnchor;
9235    SizeAnchor stateSizeAnchor;
9236
9237    Anchor normalAnchor;
9238    SizeAnchor normalSizeAnchor;
9239
9240    Size skinMinSize;       // Minimal window size based on style
9241    Point scrolledPos;      // Scrolled position
9242    Box box;                // Window box clipped to parent
9243    Box * against;          // What to clip the box to
9244
9245    Extent dirtyArea { /*first = -1, last = -1, free = -1*/ };       // Area marked for update by Update
9246    Extent renderArea { /*first = -1, last = -1, free = -1*/ };      // Temporary extent: Area that is going to be rendered
9247    Extent overRenderArea { /*first = -1, last = -1, free = -1*/ };  // Temporary extent: Area that is going to be rendered over children
9248    Extent clipExtent { /*first = -1, last = -1, free = -1*/ };      // Temporary extent against which to clip render area
9249    Extent scrollExtent { /*first = -1, last = -1, free = -1*/ };    // Area to scroll
9250    Point scrolledArea;     // Distance to scroll area by
9251    Extent dirtyBack { /*first = -1, last = -1, free = -1*/ };       // Only used by root window
9252
9253    OldList hotKeys;           // List of the hotkeys of all children
9254    Window defaultControl;  // Default child control
9255    Size minSize;
9256    Size maxSize;
9257
9258    ColorAlpha * palette;   // Color palette used for this window
9259
9260    int caretSize;          // Size of caret, non zero if a caret is present
9261    Point caretPos;         // Caret position
9262
9263    void * systemParent;    // Parent System Window for embedded windows
9264
9265    int iconID;
9266    int numIcons;
9267    int positionID;
9268
9269    Mutex mutex;
9270    WindowState lastState;
9271
9272    FileMonitor fileMonitor
9273    {
9274       this, FileChange { modified = true };
9275
9276       bool OnFileNotify(FileChange action, char * param)
9277       {
9278          incref this;
9279          fileMonitor.StopMonitoring();
9280          if(OnFileModified(action, param))
9281             fileMonitor.StartMonitoring();
9282          delete this;
9283          return true;
9284       }
9285    };
9286    FontResource setFont, systemFont;
9287    FontResource usedFont;
9288    FontResource captionFont;
9289    OldList resources;
9290    FileDialog saveDialog;
9291    Anchor anchor;
9292    SizeAnchor sizeAnchor;
9293
9294    // FormDesigner data
9295    ObjectInfo object;
9296    Window control;
9297    Extent * tempExtents; //[4];
9298    BitmapResource icon;
9299    void * windowData;
9300    CreationActivationOption creationActivation;
9301    struct
9302    {
9303       bool active:1;            // true if window and ancestors are active
9304       bool acquiredInput:1;     // true if the window is processing state based input
9305       bool modifiedDocument:1;
9306       bool disabled:1;          // true if window cannot interact
9307       bool isForegroundWindow:1;// true while a root window is being activated
9308       bool visible:1;           // Visibility flag
9309       bool destroyed:1;         // true if window is being destroyed
9310       bool anchored:1;          // true if this window is repositioned when the parent resizes
9311       bool dirty:1;             // Flag set to true if any descendant must be redrawn
9312       bool mouseInside:1;
9313       bool positioned:1;
9314       bool created:1;
9315       bool is3D:1;
9316       bool mergeMenus:1;
9317       bool modifyVirtArea:1;
9318       bool noAutoScrollArea:1;
9319       bool closing:1;
9320       bool autoCreate:1;
9321       bool setVisible:1;      // FOR FORM DESIGNER
9322       bool wasCreated:1;
9323       bool fullRender:1;
9324       bool moveable:1;
9325       bool alphaBlend:1;
9326       bool composing:1;
9327       bool useSharedMemory:1;
9328       bool resized:1;
9329       bool saving:1;
9330       bool nativeDecorations:1;
9331       bool manageDisplay:1;
9332       bool formDesigner:1; // True if we this is running in the form editor
9333    }; 
9334
9335    // Checks used internally for them not to take effect in FormDesigner
9336    property bool _isModal        { get { return !formDesigner ? style.modal : false; } }
9337    property subclass(DisplayDriver) _displayDriver  { get { return !formDesigner ? dispDriver : null; } }
9338
9339    WindowController controller;
9340    public property WindowController controller { get { return controller; } set { delete controller; controller = value; if(controller) incref controller; } }
9341 };
9342
9343 public class CommonControl : Window
9344 {
9345    // creationActivation = doNothing;
9346
9347    ToolTip toolTip;
9348    public property String toolTip
9349    {
9350       property_category "Appearance"
9351       set
9352       {
9353          if(created) CommonControl::OnDestroy();
9354          delete toolTip;
9355          toolTip = value ? ToolTip { tip = value; } : null;
9356          incref toolTip;
9357          if(created) CommonControl::OnCreate();
9358       }
9359       get { return toolTip ? toolTip.tip : null; }
9360    }
9361
9362    void OnDestroy()
9363    {
9364       if(toolTip)
9365          // (Very) Ugly work around for the fact that the parent watcher
9366          // won't fire when it's already been disconnected...
9367          eInstance_FireSelfWatchers(toolTip,
9368             __ecereProp___ecereNameSpace__ecere__gui__Window_parent);
9369    }
9370
9371    bool OnCreate()
9372    {
9373       if(toolTip)
9374          toolTip.parent = this;
9375       return true;
9376    }
9377    ~CommonControl()
9378    {
9379       delete toolTip;
9380    }
9381 };
9382
9383 public class Percentage : float
9384 {
9385    char * OnGetString(char * string, float * fieldData, bool * needClass)
9386    {
9387       int c;
9388       int last = 0;
9389       sprintf(string, "%.2f", this);
9390       c = strlen(string)-1;
9391       for( ; c >= 0; c--)
9392       {
9393          if(string[c] != '0') 
9394             last = Max(last, c);
9395          if(string[c] == '.')
9396          {
9397             if(last == c)
9398                string[c] = 0;
9399             else
9400                string[last+1] = 0;
9401             break;
9402          }
9403       }
9404       return string;
9405    }
9406 };
9407
9408 public void ApplySkin(Class c, char * name, void ** vTbl)
9409 {
9410    char className[1024];
9411    Class sc;
9412    OldLink d;
9413    int m;
9414
9415    subclass(Window) wc = (subclass(Window))c;
9416    subclass(Window) base = (subclass(Window))c.base;
9417
9418    sprintf(className, "%sSkin_%s", name, c.name);
9419    wc.pureVTbl = c._vTbl;
9420    c._vTbl = new void *[c.vTblSize];
9421    memcpy(c._vTbl, wc.pureVTbl, c.vTblSize * sizeof(void *));
9422    sc = eSystem_FindClass(c.module.application, className);
9423    
9424    if(vTbl)
9425    {
9426       for(m = 0; m < c.base.vTblSize; m++)
9427       {
9428          if(c._vTbl[m] == base.pureVTbl[m])
9429             c._vTbl[m] = vTbl[m];
9430       }
9431    }
9432    if(sc)
9433    {
9434       for(m = 0; m < c.vTblSize; m++)
9435       {
9436          if(sc._vTbl[m] != wc.pureVTbl[m])
9437             c._vTbl[m] = sc._vTbl[m];
9438       }
9439    }
9440       
9441    for(d = c.derivatives.first; d; d = d.next)
9442    {
9443       ApplySkin(d.data, name, c._vTbl);
9444    }
9445 }
9446
9447 public void UnapplySkin(Class c)
9448 {
9449    char className[1024];
9450    Class sc;
9451    subclass(Window) wc = (subclass(Window))c;
9452    subclass(Window) base = (subclass(Window))c.base;
9453    OldLink d;
9454
9455    if(wc.pureVTbl && c._vTbl != wc.pureVTbl)
9456    {
9457       delete c._vTbl;
9458       c._vTbl = wc.pureVTbl;
9459       wc.pureVTbl = null;
9460    }
9461
9462    for(d = c.derivatives.first; d; d = d.next)
9463    {
9464       UnapplySkin(d.data);
9465    }
9466 }
9467 /*
9468 void CheckFontIntegrity(Window window)
9469 {
9470    Window c;
9471    if(window)
9472    {
9473       if(window.usedFont && window.usedFont.font == 0xecececec)
9474       {
9475          FontResource uf = window.usedFont;
9476          char * className = window._class.name;
9477          char * text = window.text;
9478          Print("");
9479       }
9480       for(c = window.firstChild; c; c = c.next)
9481          CheckFontIntegrity(c);
9482    }
9483 }*/
9484
9485 public class ControllableWindow : Window
9486 {
9487    /*WindowController controller;
9488    public property WindowController controller { get { return controller; } set { delete controller; controller = value; incref controller; } }
9489    ~ControllableWindow() { delete controller; }*/
9490 }
9491
9492 class WindowControllerInterface : ControllableWindow
9493 {
9494    bool OnKeyDown(Key key, unichar ch)
9495    {
9496       bool result = ((int(*)())(void *)controller.OnKeyDown)((void *)controller.controlled, (void *)controller, key, ch);
9497       if(result)
9498          result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyDown](controller.window, key, ch);
9499       return result;
9500    }
9501
9502    bool OnKeyUp(Key key, unichar ch)
9503    {
9504       bool result = ((int(*)())(void *)controller.OnKeyUp)((void *)controller.controlled, (void *)controller, key, ch);
9505       if(result)
9506          result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyUp](controller.window, key, ch);
9507       return result;
9508    }
9509
9510    bool OnKeyHit(Key key, unichar ch)
9511    {
9512       bool result = ((int(*)())(void *)controller.OnKeyHit)((void *)controller.controlled, (void *)controller, key, ch);
9513       if(result)
9514          result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnKeyHit](controller.window, key, ch);
9515       return result;
9516    }
9517
9518    bool OnMouseMove(int x, int y, Modifiers mods)
9519    {
9520       bool result = ((int(*)())(void *)controller.OnMouseMove)((void *)controller.controlled, (void *)controller, x, y, mods);
9521       if(result)
9522          result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMouseMove](controller.window, x, y, mods);
9523       return result;
9524    }
9525
9526    bool OnLeftButtonDown(int x, int y, Modifiers mods)
9527    {
9528       bool result = ((int(*)())(void *)controller.OnLeftButtonDown)((void *)controller.controlled, (void *)controller, x, y, mods);
9529       if(result)
9530          result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonDown](controller.window, x, y, mods);
9531       return result;
9532    }
9533
9534    bool OnLeftButtonUp(int x, int y, Modifiers mods)
9535    {
9536       bool result = ((int(*)())(void *)controller.OnLeftButtonUp)((void *)controller.controlled, (void *)controller, x, y, mods);
9537       if(result)
9538          result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftButtonUp](controller.window, x, y, mods);
9539       return result;
9540    }
9541
9542    bool OnLeftDoubleClick(int x, int y, Modifiers mods)
9543    {
9544       bool result = ((int(*)())(void *)controller.OnLeftDoubleClick)((void *)controller.controlled, (void *)controller, x, y, mods);
9545       if(result)
9546          result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnLeftDoubleClick](controller.window, x, y, mods);
9547       return result;
9548    }
9549
9550    bool OnRightButtonDown(int x, int y, Modifiers mods)
9551    {
9552       bool result = ((int(*)())(void *)controller.OnRightButtonDown)((void *)controller.controlled, (void *)controller, x, y, mods);
9553       if(result)
9554          result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonDown](controller.window, x, y, mods);
9555       return result;
9556    }
9557
9558    bool OnRightButtonUp(int x, int y, Modifiers mods)
9559    {
9560       bool result = ((int(*)())(void *)controller.OnRightButtonUp)((void *)controller.controlled, (void *)controller, x, y, mods);
9561       if(result)
9562          result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightButtonUp](controller.window, x, y, mods);
9563       return result;
9564    }
9565
9566    bool OnRightDoubleClick(int x, int y, Modifiers mods)
9567    {
9568       bool result = ((int(*)())(void *)controller.OnRightDoubleClick)((void *)controller.controlled, (void *)controller, x, y, mods);
9569       if(result)
9570          result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRightDoubleClick](controller.window, x, y, mods);
9571       return result;
9572    }
9573
9574    bool OnMiddleButtonDown(int x, int y, Modifiers mods)
9575    {
9576       bool result = ((int(*)())(void *)controller.OnMiddleButtonDown)((void *)controller.controlled, (void *)controller, x, y, mods);
9577       if(result)
9578          result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonDown](controller.window, x, y, mods);
9579       return result;
9580    }
9581
9582    bool OnMiddleButtonUp(int x, int y, Modifiers mods)
9583    {
9584       bool result = ((int(*)())(void *)controller.OnMiddleButtonUp)((void *)controller.controlled, (void *)controller, x, y, mods);
9585       if(result)
9586          result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleButtonUp](controller.window, x, y, mods);
9587       return result;
9588    }
9589
9590    bool OnMiddleDoubleClick(int x, int y, Modifiers mods)
9591    {
9592       bool result = ((int(*)())(void *)controller.OnMiddleDoubleClick)((void *)controller.controlled, (void *)controller, x, y, mods);
9593       if(result)
9594          result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnMiddleDoubleClick](controller.window, x, y, mods);
9595       return result;
9596    }
9597
9598    void OnResize(int width, int height)
9599    {
9600       ((int(*)())(void *)controller.OnResize)((void *)controller.controlled, (void *)controller, width, height);
9601       controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnResize](controller.window, width, height);
9602    }
9603
9604    void OnRedraw(Surface surface)
9605    {
9606       ((int(*)())(void *)controller.OnRedraw)((void *)controller.controlled, (void *)controller, surface);
9607       controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnRedraw](controller.window, surface);
9608    }
9609
9610    bool OnCreate()
9611    {
9612       bool result = ((int(*)())(void *)controller.OnCreate)((void *)controller.controlled, (void *)controller);
9613       if(result)
9614          result = controller.windowVTbl[__ecereVMethodID___ecereNameSpace__ecere__gui__Window_OnCreate](controller.window);
9615       return result;
9616    }
9617 }
9618
9619 public class WindowController<class V>
9620 {
9621 public:
9622    property Window window
9623    {
9624       set
9625       {
9626          uint size = class(Window).vTblSize;
9627          if(value)
9628          {
9629             windowVTbl = new void *[size];
9630             memcpy(windowVTbl, value._vTbl, size * sizeof(void *));
9631             if(value._vTbl == value._class._vTbl)
9632             {
9633                value._vTbl = new void *[value._class.vTblSize];
9634                memcpy(value._vTbl + size, value._class._vTbl + size, (value._class.vTblSize - size) * sizeof(void *));
9635             }
9636             {
9637                int c;
9638                for(c = 0; c < size; c++)
9639                {
9640                   void * function = class(WindowControllerInterface)._vTbl[c];
9641                   if(function != DefaultFunction)
9642                      value._vTbl[c] = function;
9643                   else
9644                      value._vTbl[c] = windowVTbl[c];
9645                }
9646             }
9647          }
9648          else
9649             memcpy(value._vTbl, windowVTbl, class(Window).vTblSize * sizeof(void *));
9650          window = value;
9651       }
9652       get { return window; }
9653    }
9654    property V controlled
9655    {
9656       set { controlled = value; }
9657       get { return controlled; }
9658    }
9659    virtual bool V::OnKeyDown(WindowController controller, Key key, unichar ch);
9660    virtual bool V::OnKeyUp(WindowController controller, Key key, unichar ch);
9661    virtual bool V::OnKeyHit(WindowController controller, Key key, unichar ch);
9662    virtual bool V::OnMouseMove(WindowController controller, int x, int y, Modifiers mods);
9663    virtual bool V::OnLeftButtonDown(WindowController controller, int x, int y, Modifiers mods);
9664    virtual bool V::OnLeftButtonUp(WindowController controller, int x, int y, Modifiers mods);
9665    virtual bool V::OnLeftDoubleClick(WindowController controller, int x, int y, Modifiers mods);
9666    virtual bool V::OnRightButtonDown(WindowController controller, int x, int y, Modifiers mods);
9667    virtual bool V::OnRightButtonUp(WindowController controller, int x, int y, Modifiers mods);
9668    virtual bool V::OnRightDoubleClick(WindowController controller, int x, int y, Modifiers mods);
9669    virtual bool V::OnMiddleButtonDown(WindowController controller, int x, int y, Modifiers mods);
9670    virtual bool V::OnMiddleButtonUp(WindowController controller, int x, int y, Modifiers mods);
9671    virtual bool V::OnMiddleDoubleClick(WindowController controller, int x, int y, Modifiers mods);
9672    virtual void V::OnResize(WindowController controller, int width, int height);
9673    virtual void V::OnRedraw(WindowController controller, Surface surface);
9674    virtual bool V::OnCreate(WindowController controller);
9675
9676 private:
9677    int (** windowVTbl)();   
9678    V controlled;
9679    Window window;
9680
9681    ~WindowController()
9682    {
9683       delete windowVTbl;
9684    }
9685 }