compiler/libec: (#205) Corrections to integer promotions
[sdk] / ecere / src / gui / controls / Menu.ec
index a19a9ae..d3d5185 100644 (file)
@@ -27,7 +27,7 @@ class InsertedFlags { bool deleteLink:1, deleteItem:1, cleanItem:1, placed:1; };
 #define INTERIM_MENU (isMenuBar || interim)
 //#define INTERIM_MENU interim
 
-static int strcmpTillTab(char * a, char * b)
+static int strcmpTillTab(const char * a, const char * b)
 {
    if(a && !b) return 1;
    else if(b && !a) return -1;
@@ -55,17 +55,17 @@ public:
             if(menu)
                menu.RemoveItem(this);
             if(value)
-               value.AddItem(this);   
+               value.AddItem(this);
          }
       }
    };
-   property char * text
+   property const char * text
    {
       set
       {
          if(copyText)
          {
-            delete text;
+            delete (char *)text;
             text = CopyString(value);
          }
          else
@@ -83,7 +83,7 @@ public:
       set
       {
          accelerator = value;
-        
+
          if(!manualAccelText && text)
          {
             char accelString[50] = "\t";
@@ -91,15 +91,15 @@ public:
             char * tabPos;
             int length = 0;
 
-            if(value.ctrl)  strcat(accelString, "Ctrl+");
-            if(value.alt)   strcat(accelString, "Alt+");
-            if(value.shift) strcat(accelString, "Shift+");
+            if(value.ctrl)  strcat(accelString, $"Ctrl+");
+            if(value.alt)   strcat(accelString, $"Alt+");
+            if(value.shift) strcat(accelString, $"Shift+");
 
             if(value.code == k0)
                strcat(accelString, "0");
             else if(value.code >= k1 && value.code <= k9)
             {
-               accelString[strlen(accelString)] = '1' + (char)(value.code - k1);
+               accelString[strlen(accelString)] = (char)('1' + value.code - k1);
                accelString[strlen(accelString)+1] = 0;
             }
             else
@@ -107,7 +107,7 @@ public:
                Key accel = value.code;
                bool needClass = false;
                char tempString[50];
-               char * result = accel.OnGetString(tempString, null, &needClass);
+               const char * result = accel.OnGetString(tempString, null, &needClass);
                int len = strlen(accelString);
                if(result) strcpy(accelString + len, result);
                // accelString[len] = toupper(accelString[len]);
@@ -123,7 +123,7 @@ public:
             memcpy(newText, text, length);
             newText[length] = 0;
             strcat(newText, accelString);
-            if(copyText) delete text;
+            if(copyText) delete (void *)text;
             text = newText;
             copyText = true;
          }
@@ -162,21 +162,31 @@ public:
          }
          // Should callback be called here? guess not ;)
       }
-      get { return checked; } 
+      get { return checked; }
    };
    property bool disabled { set { if(this) disabled = value; } };
    property bool checkable { set { checkable = value; } };
    property bool isRadio { set { radio = value; } };
 
-   property uint id { set { id = value; } get { return id; } };
+   property uint64 id { set { id = value; } get { return id; } };
    property BitmapResource bitmap
    {
       set
       {
+         delete bitmaps[0];
+         delete bitmaps[1];
+         delete bitmaps[2];
          bitmaps[0] = value;
-         bitmaps[1] = BitmapResource { fileName = value.fileName, monochrome = true };
-         bitmaps[2] = BitmapResource { fileName = value.fileName, grayed = true };
+         bitmaps[1] = value ? (value.alphaBlend ? value : { fileName = value.fileName, monochrome = true }) : null;
+         bitmaps[2] = value ? { fileName = value.fileName, grayed = true } : null;
+         if(value)
+         {
+            incref bitmaps[0];
+            incref bitmaps[1];
+            incref bitmaps[2];
+         }
       }
+      get { return bitmaps[0]; }
    };
    property bool copyText
    {
@@ -189,8 +199,8 @@ public:
          }
          else
          {
-            if(text && copyText)
-               delete text;
+            if(copyText)
+               delete (void *)text;
          }
          copyText = value;
       }
@@ -203,10 +213,10 @@ private:
    bool isDivider;
    bool placement;
 
-   uint id;
+   uint64 id;
    Key hotKey;
    Key accelerator;
-   char * text;
+   const char * text;
    BitmapResource bitmaps[3];
    bool checkable, radio;
    bool checked;
@@ -221,8 +231,11 @@ private:
    {
       if(copyText)
          // delete ITEM_TEXT(this);
-         delete text;
+         delete (void *)text;
       delete subMenu;
+      delete bitmaps[0];
+      delete bitmaps[1];
+      delete bitmaps[2];
    }
 };
 
@@ -240,13 +253,13 @@ public class MenuPlacement : MenuItem
 {
    MenuPlacement()
    {
-      placement = true; 
+      placement = true;
    }
 
 public:
 /*
    property Menu parent { set {} };
-   property char * text { set {} };
+   property const char * text { set {} };
    property Key hotKey { set {} };
 */
 };
@@ -297,7 +310,7 @@ public:
          item.menu = this;
       }
    }
-      
+
    void RemoveItem(MenuItem item)
    {
       if(item.menu == this)
@@ -331,7 +344,7 @@ public:
          MenuItem menuItem { };
          ItemPtr ptr { item = menuItem };
          items.Add(ptr);
-         
+
          incref menuItem;
 
          itemCount++;
@@ -345,13 +358,13 @@ public:
          }
       }
    }
-   
+
    void AddDynamic(MenuItem addedItem, Window master, bool persistent)
    {
       if(addedItem)
       {
          ItemPtr ptr = null, oldItemPtr;
-         
+
          for(oldItemPtr = items.first; oldItemPtr; oldItemPtr = oldItemPtr.next)
          {
             if((oldItemPtr.item.subMenu || oldItemPtr.item.placement) && !strcmpTillTab(ITEM_TEXT(oldItemPtr.item), ITEM_TEXT(addedItem)))
@@ -391,11 +404,11 @@ public:
          addedItem.menu = this;
       }
    }
-   
-   MenuItem FindItem(bool (* Window::notifySelect)(MenuItem selection, Modifiers mods), uint id)
+
+   MenuItem FindItem(bool (* Window::notifySelect)(MenuItem selection, Modifiers mods), uint64 id)
    {
       ItemPtr ptr;
-      
+
       for(ptr = items.first; ptr; ptr = ptr.next)
       {
          MenuItem item = ptr.item;
@@ -424,7 +437,7 @@ public:
             ptr.item = ptr.oldItem;
             ptr.oldItem = null;
             delete ptr.item;
-         }      
+         }
          items.Delete(ptr);
       }
    }
@@ -473,7 +486,7 @@ public:
             for(mergeIntoItemPtr = items.first; mergeIntoItemPtr; mergeIntoItemPtr = mergeIntoItemPtr.next)
             {
                MenuItem mergeIntoItem = mergeIntoItemPtr.item;
-               if(/*!mergeIntoItem.subMenu && /*mergeIntoItem.placement && !mergeIntoItemPtr.inserted && */!strcmpTillTab(ITEM_TEXT(mergeIntoItem), ITEM_TEXT(beingMergedItem)))
+               if(/*!mergeIntoItem.subMenu && /-*mergeIntoItem.placement && !mergeIntoItemPtr.inserted && */!strcmpTillTab(ITEM_TEXT(mergeIntoItem), ITEM_TEXT(beingMergedItem)))
                {
                   //if(!beingMergedItem.placement || beingMergedItemPtr.inserted)
                   {
@@ -528,8 +541,8 @@ public:
                      itemCount++;
                   }
                }
-            
-               if(!beingMergedItem.isDivider || (previous.item && !previous.item.isDivider))
+
+               if(!beingMergedItem.isDivider || !previous || (previous.item && !previous.item.isDivider))
                {
                   mergeIntoItemPtr = ItemPtr { };
                   items.Insert(previous, mergeIntoItemPtr);
@@ -558,7 +571,7 @@ public:
          }
          else if(item.subMenu)
             item.subMenu.Clean(window);
-          
+
          if(ptr.inserted.deleteItem)
             delete item;
 
@@ -576,10 +589,10 @@ public:
       }
    }
 
-   Menu FindMenu(char * name)
+   Menu FindMenu(const char * name)
    {
       ItemPtr ptr;
-      
+
       for(ptr = items.first; ptr; ptr = ptr.next)
       {
          MenuItem item = ptr.item;
@@ -591,8 +604,9 @@ public:
    }
 
    property Menu parent { set { if(value) value.AddSubMenu(this); } };
-   property char * text { set { text = value; /* CopyString(value);*/ } };
+   property const char * text { set { text = (char *)value; /* CopyString(value);*/ } };
    property Key hotKey { set { hotKey = value; } };
+   property bool hasMargin { set { hasMargin = value; } };
 
 private:
    OldList items;
@@ -603,6 +617,7 @@ private:
    int itemHeight;
    int itemCount;
    bool mergeClients;
+   bool hasMargin;
 
    Menu()
    {
@@ -623,14 +638,14 @@ public class PopupMenu : Window
    int rw, rh;
    int totalHeight;
    Menu menu;
-   ItemPtr selected;   
+   ItemPtr selected;
    bool pressed;
    bool altDown;
    bool keyboardFocus;
    bool mouseInput;
    Time unpressedTime;
-   
-   void (* FontExtent)(Display display, Font font, char * text, int len, int * width, int * height);
+
+   void (* FontExtent)(Display display, Font font, const char * text, int len, int * width, int * height);
 
    FontResource boldFont { faceName = font.faceName, font.size, bold = true, window = this };
    BitmapResource subArrow { fileName = "<:ecere>elements/arrowRight.png", window = this };
@@ -650,7 +665,6 @@ public class PopupMenu : Window
    {
       bool result;
       PopupMenu window = this, master;
-      PopupMenu popupMenu;
 
       for(; (master = (PopupMenu)window.master); window = master)
       {
@@ -678,8 +692,8 @@ public class PopupMenu : Window
    {
       ItemPtr selected, current = this.selected;
       for(selected = (current && current.prev) ? current.prev : menu.items.last;
-            selected && 
-            (selected.item.isDivider || selected.item.placement || ITEM_DISABLED(selected.item)) && 
+            selected &&
+            (selected.item.isDivider || selected.item.placement || ITEM_DISABLED(selected.item)) &&
             selected != current;
             selected = selected.prev ? selected.prev : menu.items.last)
       {
@@ -693,8 +707,8 @@ public class PopupMenu : Window
    {
       ItemPtr selected, current = this.selected;
       for(selected = (current && current.next) ? current.next : menu.items.first;
-            selected && 
-            (selected.item.isDivider || selected.item.placement || ITEM_DISABLED(selected.item)) && 
+            selected &&
+            (selected.item.isDivider || selected.item.placement || ITEM_DISABLED(selected.item)) &&
             selected != current;
             selected = selected.next ? selected.next : menu.items.first)
       {
@@ -753,7 +767,7 @@ public class PopupMenu : Window
             Window parent = this.parent;
             Window activeClient = parent.activeClient;
             bool systemButtons = activeClient && activeClient.state == maximized;
-            
+
             keyboardFocus = true;
             pressed = true;
 
@@ -820,7 +834,7 @@ public class PopupMenu : Window
             int y = 0;
             int selectedY = 0;
             ItemPtr ptr;
-            
+
             for(ptr = menu.items.first; ptr; ptr = ptr.next)
             {
                MenuItem item = ptr.item;
@@ -828,7 +842,7 @@ public class PopupMenu : Window
                if(item.placement) continue; //&& !ptr.inserted) continue;
                if(selected == ptr)
                {
-                  
+
                   selectedY = y;
                   break;
                }
@@ -855,7 +869,7 @@ public class PopupMenu : Window
       MenuItem selection = selectionPtr.item;
       if(!ITEM_DISABLED(selection))
       {
-         Window master = this;      
+         Window master = this;
 
          if(!isMenuBar)
             master = master.master;
@@ -864,7 +878,7 @@ public class PopupMenu : Window
             master = selectionPtr.master;
          while(eClass_IsDerived(master._class, _class) && master.master)
             master = master.master;
-            
+
          if(selection.checkable)
             selection.checked = !selection.checked;
          else if(selection.radio)
@@ -891,7 +905,7 @@ public class PopupMenu : Window
          MenuItem item = ptr.item;
          if(item.subMenu)
          {
-            if(!CheckAccelerators(item.subMenu, key)) 
+            if(!CheckAccelerators(item.subMenu, key))
                return false;
          }
          else if(!item.isDivider)
@@ -911,7 +925,7 @@ public class PopupMenu : Window
       Menu menu = this.menu;
       // Mouse moved inside menu
       ItemPtr selected = null;
-      
+
       *selectedX = 0;
       *selectedY = 0;
 
@@ -934,7 +948,7 @@ public class PopupMenu : Window
                if(!helpBreak)
                {
                   ItemPtr nextPtr;
-                  
+
                   int breakX = clientSize.w - (systemButtons ? 48 : 0);
                   for(nextPtr = ptr.next; nextPtr; nextPtr = nextPtr.next)
                   {
@@ -952,7 +966,8 @@ public class PopupMenu : Window
             }
             else
             {
-               FontExtent(display, fontObject, ITEM_TEXT(item), strlen(ITEM_TEXT(item)), &len, null);
+               const char * text = ITEM_TEXT(item);
+               FontExtent(display, fontObject, text, text ? strlen(text) : 0, &len, null);
                if((mx >= x - 16 && mx < x + len + 16))
                {
                   if(!ITEM_DISABLED(item))
@@ -996,6 +1011,7 @@ public class PopupMenu : Window
    // Window Overrides
    void OnRedraw(Surface surface)
    {
+      bool hasMargin = menu ? menu.hasMargin : false;
       int x = 0;
       int y = 0;
       int height;
@@ -1004,6 +1020,8 @@ public class PopupMenu : Window
       Window activeClient = parent.activeClient;
       bool systemButtons = activeClient && activeClient.state == maximized;
       int bitmapOffset = 0;
+      bool hasBitmap = false;
+      bool isRadio = false;
 
       surface.TextFont(fontObject);
       surface.TextExtent(" ", 1, null, &height);
@@ -1011,17 +1029,41 @@ public class PopupMenu : Window
 
       if(!isMenuBar)
       {
+         if(menu)
+         {
+            ItemPtr ptr;
+            for(ptr = menu.items.first; ptr; ptr = ptr.next)
+            {
+               if(ptr.item.bitmaps[0])
+               {
+                  hasBitmap = true;
+                  break;
+               }
+            }
+
+            for(ptr = menu.items.first; ptr; ptr = ptr.next)
+            {
+               if(ptr.item.radio)
+               {
+                  isRadio = true;
+                  break;
+               }
+            }
+         }
+
          if(guiApp.textMode)
             bitmapOffset = 16;
          else
-            bitmapOffset = 12;
+            bitmapOffset = hasMargin ? 27 : (hasBitmap ? 18 : 12);
+         if(hasBitmap && isRadio)
+            bitmapOffset += 18;
       }
       else if(guiApp.textMode)
          bitmapOffset = 8;
       else
       {
          // Shiny gradient for menu bar
-         ColorKey keys[2] = 
+         ColorKey keys[2] =
          {
             { white, 0 },
             { popupMenuColor, 1 }
@@ -1045,7 +1087,7 @@ public class PopupMenu : Window
                   surface.Area(0,y,clientSize.w-1,y+rh-1);
                }
                else
-                  surface.Area(2,y,clientSize.w-3,y+rh);
+                  surface.Area(/*(hasMargin ? bitmapOffset : 0) +*/ 2,y,clientSize.w-3,y+rh);
             }
             else
             {
@@ -1087,10 +1129,12 @@ public class PopupMenu : Window
                   }
                   else
                   {
-                     surface.SetForeground(Color { 85, 85, 85 });
-                     surface.HLine(x + 2, x + rw - 5, y + (DIVIDER_HEIGHT) / 2);
-                     surface.SetForeground(white);
-                     surface.HLine(x + 2, x + rw - 5, y + (DIVIDER_HEIGHT) / 2 + 1);
+                     int start = x + hasMargin ? bitmapOffset : 2;
+                     int end   = x + rw - (hasMargin ? 13 : 5);
+                     surface.foreground = Color { 85, 85, 85 };
+                     surface.HLine(start, end, y + (DIVIDER_HEIGHT) / 2);
+                     surface.foreground = white;
+                     surface.HLine(start, end, y + (DIVIDER_HEIGHT) / 2 + 1);
                   }
                }
             }
@@ -1117,7 +1161,7 @@ public class PopupMenu : Window
                   {
                      Bitmap icon = bitmap.bitmap;
                      if(icon)
-                        surface.Blit(icon, x + 3, y + (rh - icon.height)/2, 0,0, icon.width, icon.height);
+                        surface.Blit(icon, x + (isRadio ? 18 : 0) + (hasMargin ? 5 : 3), y + (rh - icon.height)/2, 0,0, icon.width, icon.height);
                   }
 
                   if(item.bold)
@@ -1127,14 +1171,23 @@ public class PopupMenu : Window
 
                   if(ITEM_DISABLED(item) && selected == ptr)
                   {
-                     surface.SetForeground(activeBorder);
+                     surface.SetForeground(formColor);
                      Interface::WriteKeyedText(surface, x + bitmapOffset + 5,
                         textY, ITEM_TEXT(item), ITEM_HOTKEY(item));
                   }
                   else
                      Interface::WriteKeyedTextDisabled(surface, x + bitmapOffset + 5,
                         textY, ITEM_TEXT(item), ITEM_HOTKEY(item), ITEM_DISABLED(item));
-                  surface.SetForeground(foreground);
+
+                  // A nice vertical separation line
+                  if(hasMargin && !isMenuBar)
+                  {
+                     surface.foreground = Color { 85, 85, 85 };
+                     surface.VLine(clientArea.top, clientArea.bottom, x + bitmapOffset - 2);
+                     surface.foreground = white;
+                     surface.VLine(clientArea.top, clientArea.bottom, x + bitmapOffset - 1);
+                  }
+                  surface.foreground = foreground;
                   if(item.checked)
                   {
                      surface.DrawLine(x+5, y+9, x+8,y+12);
@@ -1168,7 +1221,7 @@ public class PopupMenu : Window
                      surface.VLine(y+(rh - 8)/2, y+(rh - 8)/2+7, clientSize.w-10);
                      surface.SetForeground(Color { 85, 85, 85 });
                      surface.DrawLine(clientSize.w-10, y+(rh - 8)/2, clientSize.w-4, y+rh / 2);
-                     surface.SetForeground(activeBorder);
+                     surface.SetForeground(formColor);
                      surface.DrawLine(clientSize.w-10, y+(rh - 8)/2+7, clientSize.w-4, y+rh / 2);
                      */
                   }
@@ -1228,7 +1281,7 @@ public class PopupMenu : Window
                if(key && menu)
                {
                   ItemPtr ptr;
-                  
+
                   for(ptr = menu.items.first; ptr; ptr = ptr.next)
                   {
                      MenuItem item = ptr.item;
@@ -1340,7 +1393,7 @@ public class PopupMenu : Window
                      if(MenuGoToNextItem())
                         Update(null);
                      result = false;
-                  }         
+                  }
                   break;
                case end:
                   if(!isMenuBar)
@@ -1349,7 +1402,7 @@ public class PopupMenu : Window
                      if(MenuGoToPrevItem())
                         Update(null);
                      result = false;
-                  }         
+                  }
                   break;
                case left:
                   if(isMenuBar)
@@ -1475,7 +1528,7 @@ public class PopupMenu : Window
                   if(key && menu)
                   {
                      //ItemPtr ptr;
-                     
+
                      if(ch >= 32 && !isMenuBar)
                         return false;
                      /*
@@ -1531,6 +1584,14 @@ public class PopupMenu : Window
       {
          ItemPtr ptr;
 
+         // Default width & height for merging menus into menu bars
+         if(isMenuBar)
+         {
+            FontExtent(display, font, "W",1, &maxW, &maxH);
+            if(!guiApp.textMode)
+               maxH += 6;
+         }
+
          for(ptr = menu.items.first; ptr; ptr = ptr.next)
          {
             MenuItem item = ptr.item;
@@ -1545,6 +1606,8 @@ public class PopupMenu : Window
                   if(strstr(ITEM_TEXT(item), "\t"))
                      width += 8;
                }
+               if(item.bitmap && item.radio)
+                  width += 20;
                if(item.subMenu) width += 20;
                if(!guiApp.textMode)
                   height += 6;
@@ -1566,7 +1629,7 @@ public class PopupMenu : Window
             if(item.bitmaps[1]) AddResource(item.bitmaps[1]);
             if(item.bitmaps[2]) AddResource(item.bitmaps[2]);
          }
-         maxW += 24;
+         maxW += menu.hasMargin ? 32 : 24;
          if(menu.text)
          {
             FontExtent(display, font,menu.text,strlen(menu.text),&width, &height);
@@ -1597,9 +1660,9 @@ public class PopupMenu : Window
 
       if(this != masterMenuBar)
       {
-         if(!*w) 
+         if(!*w)
             *w = 80;
-         if(!*h) 
+         if(!*h)
             *h = 20;
       }
       return true;
@@ -1635,7 +1698,7 @@ public class PopupMenu : Window
          else
          {
             *x = Min(*x, parent.clientSize.w - w);
-            *y = Min(*y, parent.clientSize.h - h);   
+            *y = Min(*y, parent.clientSize.h - h);
          }
          if(parent == guiApp.desktop)
          {
@@ -1656,8 +1719,11 @@ public class PopupMenu : Window
    bool OnMouseMove(int mx, int my, Modifiers mods)
    {
       int selectedX, selectedY;
+      ItemPtr selected;
 
-      ItemPtr selected = FindSelected(mx, my, &selectedX, &selectedY);
+      if(mods.isSideEffect) return true;
+
+      selected = FindSelected(mx, my, &selectedX, &selectedY);
 
       if((!mods.isSideEffect || !this.selected) && (/*selected && */
          selected != this.selected && (!selected || !ITEM_DISABLED(selected.item)) && (selected || !keyboardFocus)))
@@ -1673,7 +1739,7 @@ public class PopupMenu : Window
             if(this.selected)
             {
                Menu childMenu = selected.item.subMenu;
-               
+
                this.pressed = pressed;
 
                if(this.selected.item.subMenu)
@@ -1694,7 +1760,9 @@ public class PopupMenu : Window
    {
       if(isMenuBar)
       {
-         if(GetTime() - unpressedTime < 0.01)
+         // Had to boost this to 0.1 for Windows Basic / XP theme / Remote Desktop
+         // Aero & Classic were fast enough for 0.01
+         if(GetTime() - unpressedTime < 0.1)
             return true;
          if(INTERIM_MENU)
          {
@@ -1800,7 +1868,7 @@ public class PopupMenu : Window
                      keyboardFocus = false;
                      Update(null);
                   }
-                  if(MenuItemSelection(menu, selected, (Key)mods))
+                  if(MenuItemSelection(menu, selected, Key { modifiers = mods }))
                      return false;
                }
             }
@@ -1827,6 +1895,9 @@ public class PopupMenu : Window
          {
             Window master = this.master;
             Window activeClient = master.activeClient;
+            // TOFIX: Fix need for a cast here...
+            while(activeClient && !((BorderBits)activeClient.borderStyle).fixed)
+               activeClient = activeClient.activeClient;
             if(activeClient && activeClient.state == maximized)
                activeClient.SetState(normal, false, mods);
          }
@@ -1893,7 +1964,7 @@ public class PopupMenu : Window
                         break;
                      }
                }
-               if(destroy) 
+               if(destroy)
                {
                   if(MenuDestroyMasters(false))
                      return false;
@@ -1945,6 +2016,7 @@ public:
             }
          }
       }
+      get { return menu; }
    };
    property bool isMenuBar { set { isMenuBar = value; } };
    property bool focus { get { return keyboardFocus; } };