merge ROS Shell without integrated explorer part into trunk
[reactos.git] / reactos / subsys / system / explorer / taskbar / startmenu.cpp
index b21b3ce..2a00ded 100644 (file)
  //
 
 
-#include "../utility/utility.h"
+#include "precomp.h"
 
-#include "../explorer.h"
-#include "../globals.h"
-#include "../externals.h"
 #include "../explorer_intres.h"
 
 #include "desktopbar.h"
 #include "../dialogs/settings.h"
 
 
+#define        SHELLPATH_CONTROL_PANEL         TEXT("::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}")
+#define        SHELLPATH_PRINTERS                      TEXT("::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{2227A280-3AEA-1069-A2DE-08002B30309D}")
+#define        SHELLPATH_NET_CONNECTIONS       TEXT("::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{7007ACC7-3202-11D1-AAD2-00805FC1270E}")
+
+
 StartMenu::StartMenu(HWND hwnd)
  :     super(hwnd)
 {
        _next_id = IDC_FIRST_MENU;
        _submenu_id = 0;
+
        _border_left = 0;
        _border_top = 0;
+       _bottom_max = INT_MAX;
+
+       _floating_btn = false;
+       _arrow_btns = false;
+       _scroll_mode = SCROLL_NOT;
+       _scroll_pos = 0;
+       _invisible_lines = 0;
+
        _last_pos = WindowRect(hwnd).pos();
 #ifdef _LIGHT_STARTMENU
        _selected_id = -1;
@@ -68,8 +79,17 @@ StartMenu::StartMenu(HWND hwnd, const StartMenuCreateInfo& create_info)
 
        _next_id = IDC_FIRST_MENU;
        _submenu_id = 0;
+
        _border_left = 0;
        _border_top = create_info._border_top;
+       _bottom_max = INT_MAX;
+
+       _floating_btn = create_info._border_top? true: false;
+       _arrow_btns = false;
+       _scroll_mode = SCROLL_NOT;
+       _scroll_pos = 0;
+       _invisible_lines = 0;
+
        _last_pos = WindowRect(hwnd).pos();
 #ifdef _LIGHT_STARTMENU
        _selected_id = -1;
@@ -138,7 +158,7 @@ HWND StartMenu::Create(int x, int y, const StartMenuFolders& folders, HWND hwndP
 }
 
 
-LRESULT        StartMenu::Init(LPCREATESTRUCT pcs)
+LRESULT StartMenu::Init(LPCREATESTRUCT pcs)
 {
        try {
                AddEntries();
@@ -193,9 +213,9 @@ void StartMenu::AddEntries()
                        WaitCursor wait;
 
 #ifdef _LAZY_ICONEXTRACT
-                       dir.smart_scan(SCAN_FILESYSTEM);        // lazy icon extraction, try to read directly from filesystem
+                       dir.smart_scan(SORT_NAME, SCAN_FILESYSTEM);     // lazy icon extraction, try to read directly from filesystem
 #else
-                       dir.smart_scan(SCAN_EXTRACT_ICONS|SCAN_FILESYSTEM);
+                       dir.smart_scan(SORT_NAME, SCAN_EXTRACT_ICONS|SCAN_FILESYSTEM);
 #endif
                }
 
@@ -306,21 +326,70 @@ LRESULT StartMenu::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
 
          case WM_CANCELMODE:
                CloseStartMenu();
+
+#ifdef _LIGHT_STARTMENU
+               if (_scroll_mode != SCROLL_NOT) {
+                       ReleaseCapture();
+                       KillTimer(_hwnd, 0);
+               }
+#endif
                break;
 
 #ifdef _LIGHT_STARTMENU
          case WM_MOUSEMOVE: {
                 // automatically set the focus to startmenu entries when moving the mouse over them
                if (lparam != _last_mouse_pos) { // don't process WM_MOUSEMOVE when opening submenus using keyboard navigation
-                       int new_id = ButtonHitTest(Point(lparam));
+                       Point pt(lparam);
+
+                       if (_arrow_btns) {
+                               RECT rect_up, rect_down;
+
+                               GetArrowButtonRects(&rect_up, &rect_down);
+
+                               SCROLL_MODE scroll_mode = SCROLL_NOT;
 
-                       if (new_id != _selected_id)
+                               if (PtInRect(&rect_up, pt))
+                                       scroll_mode = SCROLL_UP;
+                               else if (PtInRect(&rect_down, pt))
+                                       scroll_mode = SCROLL_DOWN;
+
+                               if (scroll_mode != _scroll_mode) {
+                                       if (scroll_mode == SCROLL_NOT) {
+                                               ReleaseCapture();
+                                               KillTimer(_hwnd, 0);
+                                       } else {
+                                               CloseSubmenus();
+                                               SetTimer(_hwnd, 0, 150, NULL);  // 150 ms scroll interval
+                                               SetCapture(_hwnd);
+                                       }
+
+                                       _scroll_mode = scroll_mode;
+                               }
+                       }
+
+                       int new_id = ButtonHitTest(pt);
+
+                       if (new_id > 0 && new_id != _selected_id)
                                SelectButton(new_id);
 
                        _last_mouse_pos = lparam;
                }
                break;}
 
+         case WM_TIMER:
+               if (_scroll_mode == SCROLL_UP) {
+                       if (_scroll_pos > 0) {
+                               --_scroll_pos;
+                               InvalidateRect(_hwnd, NULL, TRUE);
+                       }
+               } else {
+                       if (_scroll_pos <= _invisible_lines) {
+                               ++_scroll_pos;
+                               InvalidateRect(_hwnd, NULL, TRUE);
+                       }
+               }
+               break;
+
          case WM_KEYDOWN:
                ProcessKey(wparam);
                break;
@@ -361,9 +430,31 @@ LRESULT StartMenu::WndProc(UINT nmsg, WPARAM wparam, LPARAM lparam)
                break;
 
          case PM_SELECT_ENTRY:
-               SelectButtonIndex(0, wparam?true:false);
+               SelectButtonIndex(0, wparam!=0);
                break;
 
+#ifdef _LIGHT_STARTMENU
+         case WM_CONTEXTMENU: {
+               Point screen_pt(lparam), clnt_pt=screen_pt;
+               ScreenToClient(_hwnd, &clnt_pt);
+
+               int id = ButtonHitTest(clnt_pt);
+
+               if (id) {
+                       StartMenuEntry& sme = _entries[id];
+
+                       for(ShellEntrySet::iterator it=sme._entries.begin(); it!=sme._entries.end(); ++it) {
+                               Entry* entry = *it;
+
+                               if (entry) {
+                                       CHECKERROR(entry->do_context_menu(_hwnd, screen_pt, _cm_ifs));  // may close start menu because of focus loss
+                                       break;  ///@todo handle context menu for more than one entry
+                               }
+                       }
+               }
+               break;}
+#endif
+
          default: def:
                return super::WndProc(nmsg, wparam, lparam);
        }
@@ -382,7 +473,7 @@ int StartMenu::ButtonHitTest(POINT pt)
        if (pt.x<rect.left || pt.x>rect.right)
                return 0;
 
-       for(SMBtnVector::const_iterator it=_buttons.begin(); it!=_buttons.end(); ++it) {
+       for(SMBtnVector::const_iterator it=_buttons.begin()+_scroll_pos; it!=_buttons.end(); ++it) {
                const SMBtnInfo& info = *it;
 
                if (rect.top > pt.y)
@@ -390,6 +481,9 @@ int StartMenu::ButtonHitTest(POINT pt)
 
                rect.bottom = rect.top + (info._id==-1? STARTMENU_SEP_HEIGHT: STARTMENU_LINE_HEIGHT);
 
+               if (rect.bottom > _bottom_max)
+                       break;
+
                if (pt.y < rect.bottom) // PtInRect(&rect, pt)
                        return info._id;
 
@@ -401,13 +495,13 @@ int StartMenu::ButtonHitTest(POINT pt)
 
 void StartMenu::InvalidateSelection()
 {
-       if (!_selected_id)
+       if (_selected_id <= 0)
                return;
 
        ClientRect clnt(_hwnd);
        RECT rect = {_border_left, _border_top, clnt.right, STARTMENU_LINE_HEIGHT};
 
-       for(SMBtnVector::const_iterator it=_buttons.begin(); it!=_buttons.end(); ++it) {
+       for(SMBtnVector::const_iterator it=_buttons.begin()+_scroll_pos; it!=_buttons.end(); ++it) {
                const SMBtnInfo& info = *it;
 
                rect.bottom = rect.top + (info._id==-1? STARTMENU_SEP_HEIGHT: STARTMENU_LINE_HEIGHT);
@@ -632,7 +726,7 @@ bool StartMenu::GetButtonRect(int id, PRECT prect) const
        ClientRect clnt(_hwnd);
        RECT rect = {_border_left, _border_top, clnt.right, STARTMENU_LINE_HEIGHT};
 
-       for(SMBtnVector::const_iterator it=_buttons.begin(); it!=_buttons.end(); ++it) {
+       for(SMBtnVector::const_iterator it=_buttons.begin()+_scroll_pos; it!=_buttons.end(); ++it) {
                const SMBtnInfo& info = *it;
 
                rect.bottom = rect.top + (info._id==-1? STARTMENU_SEP_HEIGHT: STARTMENU_LINE_HEIGHT);
@@ -679,12 +773,44 @@ void StartMenu::GetFloatingButtonRect(LPRECT prect)
 }
 
 
+void StartMenu::DrawArrows(HDC hdc)
+{
+       static ResIconEx arrowUpIcon(IDI_ARROW_UP, 8, 4);
+       static ResIconEx arrowDownIcon(IDI_ARROW_DOWN, 8, 4);
+
+       ClientRect clnt(_hwnd);
+
+       DrawIconEx(hdc, clnt.right/2-4, _floating_btn?3:1, arrowUpIcon, 8, 4, 0, 0, DI_NORMAL);
+       DrawIconEx(hdc, clnt.right/2-4, clnt.bottom-5, arrowDownIcon, 8, 4, 0, 0, DI_NORMAL);
+}
+
+void StartMenu::GetArrowButtonRects(LPRECT prect_up, LPRECT prect_down)
+{
+       GetClientRect(_hwnd, prect_up);
+       *prect_down = *prect_up;
+
+//     prect_up->left = prect_up->right/2 - 4;
+//     prect_up->right = prect_up->left + 8;
+       prect_up->right -= 8;
+       prect_up->top = _floating_btn? 3: 1;
+       prect_up->bottom = prect_up->top + 4;
+
+//     prect_down->left = prect_down->right/2 - 4;
+//     prect_down->right = prect_down->left + 8;
+       prect_down->right -= 8;
+       prect_down->top = prect_down->bottom - 5;
+}
+
+
 void StartMenu::Paint(PaintCanvas& canvas)
 {
-       if (_border_top)
+       if (_floating_btn)
                DrawFloatingButton(canvas);
 
 #ifdef _LIGHT_STARTMENU
+       if (_arrow_btns)
+               DrawArrows(canvas);
+
        ClientRect clnt(_hwnd);
        RECT rect = {_border_left, _border_top, clnt.right, STARTMENU_LINE_HEIGHT};
 
@@ -693,7 +819,7 @@ void StartMenu::Paint(PaintCanvas& canvas)
        FontSelection font(canvas, GetStockFont(DEFAULT_GUI_FONT));
        BkMode bk_mode(canvas, TRANSPARENT);
 
-       for(SMBtnVector::const_iterator it=_buttons.begin(); it!=_buttons.end(); ++it) {
+       for(SMBtnVector::const_iterator it=_buttons.begin()+_scroll_pos; it!=_buttons.end(); ++it) {
                const SMBtnInfo& btn = *it;
 
                if (rect.top > canvas.rcPaint.bottom)
@@ -702,6 +828,9 @@ void StartMenu::Paint(PaintCanvas& canvas)
                if (btn._id == -1) {    // a separator?
                        rect.bottom = rect.top + STARTMENU_SEP_HEIGHT;
 
+                       if (rect.bottom > _bottom_max)
+                               break;
+
                        BrushSelection brush_sel(canvas, GetSysColorBrush(COLOR_BTNSHADOW));
                        PatBlt(canvas, rect.left+2, rect.top+STARTMENU_SEP_HEIGHT/2-1, sep_width, 1, PATCOPY);
 
@@ -710,6 +839,9 @@ void StartMenu::Paint(PaintCanvas& canvas)
                } else {
                        rect.bottom = rect.top + STARTMENU_LINE_HEIGHT;
 
+                       if (rect.bottom > _bottom_max)
+                               break;
+
                        if (rect.top >= canvas.rcPaint.top)
                                DrawStartMenuButton(canvas, rect, btn._title, btn, btn._id==_selected_id, false);
                }
@@ -727,7 +859,7 @@ void StartMenu::UpdateIcons(/*int idx*/)
 #ifdef _SINGLE_ICONEXTRACT
 
        //if (idx >= 0)
-       int idx = 0;
+       int idx = _scroll_pos;
 
        for(; idx<(int)_buttons.size(); ++idx) {
                SMBtnInfo& btn = _buttons[idx];
@@ -741,7 +873,11 @@ void StartMenu::UpdateIcons(/*int idx*/)
                                Entry* entry = *it;
 
                                if (entry->_icon_id == ICID_UNKNOWN)
-                                       entry->extract_icon();
+                                       try {
+                                               entry->extract_icon();
+                                       } catch(COMException&) {
+                                               // ignore unexpected exceptions while extracting icons
+                                       }
 
                                if (entry->_icon_id > ICID_NONE) {
                                        btn._icon_id = (ICON_ID)/*@@*/ entry->_icon_id;
@@ -749,6 +885,10 @@ void StartMenu::UpdateIcons(/*int idx*/)
                                        RECT rect;
 
                                        GetButtonRect(btn._id, &rect);
+
+                                       if (rect.bottom > _bottom_max)
+                                               break;
+
                                        WindowCanvas canvas(_hwnd);
                                        DrawStartMenuButton(canvas, rect, NULL, btn, btn._id==_selected_id, false);
 
@@ -870,7 +1010,7 @@ ShellEntryMap::iterator StartMenu::AddEntry(const String& title, ICON_ID icon_id
                for(ShellEntryMap::iterator it=_entries.begin(); it!=_entries.end(); ++it) {
                        StartMenuEntry& sme = it->second;
 
-                       if (sme._title == title)        ///@todo speed up by using a map indexed by name
+                       if (!_tcsicmp(sme._title, title))       ///@todo speed up by using a map indexed by name
                                for(ShellEntrySet::iterator it2=sme._entries.begin(); it2!=sme._entries.end(); ++it2) {
                                        if ((*it2)->_data.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
                                                 // merge the new shell entry with the existing of the same name
@@ -1069,7 +1209,7 @@ void StartMenu::CreateSubmenu(int id, const StartMenuFolders& new_folders, LPCTS
                ClientToScreen(_hwnd, &rect);
 
                x = rect.right; // Submenus should overlap their parent a bit.
-               y = rect.top+STARTMENU_LINE_HEIGHT-_border_top;
+               y = rect.top+STARTMENU_LINE_HEIGHT +_border_top/*own border*/ -STARTMENU_TOP_BTN_SPACE/*border of new submenu*/;
        } else {
                WindowRect pos(_hwnd);
 
@@ -1106,7 +1246,7 @@ void StartMenu::ActivateEntry(int id, const ShellEntrySet& entries)
                        if (title.empty())
                                title = entry->_display_name;
                } else {
-                        // If the entry is no subdirectory, there can only be one shell entry.
+                        // The entry is no subdirectory, so there can only be one shell entry.
                        assert(entries.size()==1);
 
                        HWND hparent = GetParent(_hwnd);
@@ -1119,7 +1259,7 @@ void StartMenu::ActivateEntry(int id, const ShellEntrySet& entries)
                        SHELLEXECUTEINFO shexinfo;
 
                        shexinfo.cbSize = sizeof(SHELLEXECUTEINFO);
-                       shexinfo.fMask = SEE_MASK_INVOKEIDLIST; // SEE_MASK_IDLIST is also possible.
+                       shexinfo.fMask = SEE_MASK_IDLIST;       // SEE_MASK_INVOKEIDLIST is also possible.
                        shexinfo.hwnd = hparent;
                        shexinfo.lpVerb = NULL;
                        shexinfo.lpFile = NULL;
@@ -1267,11 +1407,40 @@ void StartMenu::ResizeToButtons()
 
         // move down if we are too high
        if (rect.top < 0) {
-               rect.top += STARTMENU_LINE_HEIGHT;
-               rect.bottom += STARTMENU_LINE_HEIGHT;
+               int dy = -rect.top;
+               rect.top += dy;
+               rect.bottom += dy;
+       }
+
+        // enable scroll mode for long start menus, which span more than the whole screen height
+       int cyscreen = GetSystemMetrics(SM_CYSCREEN);
+       int bottom_max = 0;
+
+       if (rect.bottom > cyscreen) {
+               _arrow_btns = true;
+
+               _invisible_lines = (rect.bottom-cyscreen+(STARTMENU_LINE_HEIGHT-1))/STARTMENU_LINE_HEIGHT + 1;
+               rect.bottom -= _invisible_lines * STARTMENU_LINE_HEIGHT;
+
+               bottom_max = rect.bottom;
+
+               if (_floating_btn)
+                       rect.bottom += 6;       // lower scroll arrow
+               else {
+                       _border_top += 6;       // upper scroll arrow
+                       rect.bottom += 2*6;     // upper+lower scroll arrow
+               }
        }
 
        MoveWindow(_hwnd, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, TRUE);
+
+       if (bottom_max) {
+               POINT pt = {0, bottom_max};
+
+               ScreenToClient(_hwnd, &pt);
+
+               _bottom_max = pt.y;
+       }
 }
 
 #else // _LIGHT_STARTMENU
@@ -1349,17 +1518,27 @@ StartMenuRoot::StartMenuRoot(HWND hwnd)
 }
 
 
-HWND StartMenuRoot::Create(HWND hwndOwner)
+static void CalculateStartPos(HWND hwndOwner, RECT& rect)
 {
        WindowRect pos(hwndOwner);
 
-       RECT rect = {pos.left, pos.top-STARTMENU_LINE_HEIGHT-4, pos.left+STARTMENU_WIDTH_MIN, pos.top};
+       rect.left = pos.left;
+       rect.top = pos.top-STARTMENU_LINE_HEIGHT-4;
+       rect.right = pos.left+STARTMENU_WIDTH_MIN;
+       rect.bottom = pos.top;
 
 #ifndef _LIGHT_STARTMENU
        rect.top += STARTMENU_LINE_HEIGHT;
 #endif
 
        AdjustWindowRectEx(&rect, WS_POPUP|WS_THICKFRAME|WS_CLIPCHILDREN|WS_VISIBLE, FALSE, 0);
+}
+
+HWND StartMenuRoot::Create(HWND hwndOwner)
+{
+       RECT rect;
+
+       CalculateStartPos(hwndOwner, rect);
 
        return Window::Create(WINDOW_CREATOR(StartMenuRoot), 0, GetWndClasss(), TITLE_STARTMENU,
                                                        WS_POPUP|WS_THICKFRAME|WS_CLIPCHILDREN,
@@ -1376,6 +1555,17 @@ void StartMenuRoot::TrackStartmenu()
        _selected_id = -1;
 #endif
 
+#ifdef _LIGHT_STARTMENU
+        // recalculate start menu root position
+       RECT rect;
+
+       CalculateStartPos(GetParent(hwnd), rect);
+
+       SetWindowPos(hwnd, 0, rect.left, rect.top, rect.right-rect.left, rect.bottom-rect.top, 0);
+
+       ResizeToButtons();
+#endif
+
         // show previously hidden start menu
        ShowWindow(hwnd, SW_SHOW);
        SetForegroundWindow(hwnd);
@@ -1505,6 +1695,9 @@ LRESULT   StartMenuRoot::Init(LPCREATESTRUCT pcs)
                AddButton(ResString(IDS_SHUTDOWN),      ICID_LOGOFF, false, IDC_SHUTDOWN);
 
 
+       AddButton(ResString(IDS_TERMINATE),     ICID_LOGOFF, false, IDC_TERMINATE);
+
+
 #ifdef __MINGW32__
        RegCloseKey(hkeyAdv);
        RegCloseKey(hkey);
@@ -1645,9 +1838,11 @@ int StartMenuHandler::Command(int id, int code)
                break;
 
          case IDC_LOGOFF:
-               /* The shell32 Dialog prompts about some system setting change. This is not what we want to display here.
                CloseStartMenu(id);
-               ShowRestartDialog(g_Globals._hwndDesktopBar, EWX_LOGOFF);*/
+               ShowLogoffDialog(g_Globals._hwndDesktopBar);
+               break;
+
+         case IDC_TERMINATE:
                DestroyWindow(GetParent(_hwnd));
                break;
 
@@ -1664,32 +1859,82 @@ int StartMenuHandler::Command(int id, int code)
                ExplorerPropertySheet(g_Globals._hwndDesktopBar);
                break;
 
+         case IDC_CONTROL_PANEL: {
+               CloseStartMenu(id);
+#ifndef ROSSHELL
+#ifndef _NO_MDI
+               XMLPos explorer_options = g_Globals.get_cfg("general/explorer");
+               bool mdi = XMLBool(explorer_options, "mdi", true);
+
+               if (mdi)
+                       MDIMainFrame::Create(TEXT("::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}"), 0);
+               else
+#endif
+                       SDIMainFrame::Create(TEXT("::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}"), 0);
+#else
+               launch_file(_hwnd, SHELLPATH_CONTROL_PANEL);
+#endif
+               break;}
+
          case IDC_SETTINGS_MENU:
                CreateSubmenu(id, CSIDL_CONTROLS, ResString(IDS_SETTINGS_MENU));
                break;
 
-         case IDC_PRINTERS:
+         case IDC_PRINTERS: {
+               CloseStartMenu(id);
+
+#ifndef ROSSHELL
 #ifdef _ROS_   // to be removed when printer folder will be implemented
                MessageBox(0, TEXT("printer folder not yet implemented in SHELL32"), ResString(IDS_TITLE), MB_OK);
 #else
-               CreateSubmenu(id, CSIDL_PRINTERS, CSIDL_PRINTHOOD, ResString(IDS_PRINTERS));
+#ifndef _NO_MDI
+               XMLPos explorer_options = g_Globals.get_cfg("general/explorer");
+               bool mdi = XMLBool(explorer_options, "mdi", true);
+
+               if (mdi)
+                       MDIMainFrame::Create(TEXT("::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{2227A280-3AEA-1069-A2DE-08002B30309D}"), 0);
+               else
 #endif
-               break;
+                       SDIMainFrame::Create(TEXT("::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{2227A280-3AEA-1069-A2DE-08002B30309D}"), 0);
+#endif
+#else
+               launch_file(_hwnd, SHELLPATH_PRINTERS);
+#endif
+               break;}
 
-         case IDC_CONTROL_PANEL:
-               CloseStartMenu(id);
-               MainFrame::Create(TEXT("::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}"), 0);
+         case IDC_PRINTERS_MENU:
+               CreateSubmenu(id, CSIDL_PRINTERS, CSIDL_PRINTHOOD, ResString(IDS_PRINTERS));
+/*             StartMenuFolders new_folders;
+
+               try {
+                       new_folders.push_back(ShellPath(TEXT("::{20D04FE0-3AEA-1069-A2D8-08002B30309D}\\::{21EC2020-3AEA-1069-A2DD-08002B30309D}\\::{2227A280-3AEA-1069-A2DE-08002B30309D}")));
+               } catch(COMException&) {
+               }
+
+               CreateSubmenu(id, new_folders, ResString(IDS_PRINTERS));*/
                break;
 
          case IDC_ADMIN:
+#ifndef ROSSHELL
                CreateSubmenu(id, CSIDL_COMMON_ADMINTOOLS, CSIDL_ADMINTOOLS, ResString(IDS_ADMIN));
+               //CloseStartMenu(id);
+               //MainFrame::Create(SpecialFolderPath(CSIDL_COMMON_ADMINTOOLS, _hwnd), OWM_PIDL);
+#else
+               launch_file(_hwnd, SpecialFolderFSPath(CSIDL_COMMON_ADMINTOOLS, _hwnd));
+#endif
                break;
 
          case IDC_CONNECTIONS:
+#ifndef ROSSHELL
 #ifdef _ROS_   // to be removed when RAS will be implemented
                MessageBox(0, TEXT("RAS folder not yet implemented in SHELL32"), ResString(IDS_TITLE), MB_OK);
 #else
                CreateSubmenu(id, CSIDL_CONNECTIONS, ResString(IDS_CONNECTIONS));
+               //CloseStartMenu(id);
+               //MainFrame::Create(SpecialFolderPath(CSIDL_CONNECTIONS, _hwnd), OWM_PIDL);
+#endif
+#else
+               launch_file(_hwnd, SHELLPATH_NET_CONNECTIONS);
 #endif
                break;
 
@@ -1705,7 +1950,7 @@ int StartMenuHandler::Command(int id, int code)
                break;
 
          case IDC_DRIVES:
-               ///@todo exclude removeable drives
+               ///@todo exclude removable drives
                CreateSubmenu(id, CSIDL_DRIVES, ResString(IDS_DRIVES));
                break;
 
@@ -1767,7 +2012,6 @@ void StartMenuHandler::ShowLaunchDialog(HWND hwndOwner)
         // Show "Run..." dialog
        if (RunFileDlg) {
 #ifndef _ROS_ /* FIXME: our shell32 always expects Ansi strings */
-#define        W_VER_NT 0
                if ((HIWORD(GetVersion())>>14) == W_VER_NT) {
                        WCHAR wTitle[40], wText[256];
 
@@ -1782,24 +2026,29 @@ void StartMenuHandler::ShowLaunchDialog(HWND hwndOwner)
        }
 }
 
-void StartMenuHandler::ShowRestartDialog(HWND hwndOwner, UINT flags)
+void StartMenuHandler::ShowLogoffDialog(HWND hwndOwner)
 {
-       static DynamicFct<RESTARTWINDOWSDLG> RestartDlg(TEXT("SHELL32"), 59);
+       static DynamicFct<LOGOFFWINDOWSDIALOG> LogoffWindowsDialog(TEXT("SHELL32"), 54);
+//     static DynamicFct<RESTARTWINDOWSDLG> RestartDialog(TEXT("SHELL32"), 59);
 
-       if (RestartDlg)
-               (*RestartDlg)(hwndOwner, (LPWSTR)L"You selected <Log Off>.\n\n", flags);        ///@todo ANSI string conversion if needed
+       if (LogoffWindowsDialog)
+               (*LogoffWindowsDialog)(0);
+/* The RestartDialog function prompts about some system setting change. This is not what we want to display here.
+       else if (RestartDialog)
+               return (*RestartDialog)(hwndOwner, (LPWSTR)L"You selected <Log Off>.\n\n", EWX_LOGOFF) == 1;    ///@todo ANSI string conversion if needed
+*/
        else
-               MessageBox(hwndOwner, TEXT("RestartDlg() not yet implemented in SHELL32"), ResString(IDS_TITLE), MB_OK);
+               MessageBox(hwndOwner, TEXT("LogoffWindowsDialog() not yet implemented in SHELL32"), ResString(IDS_TITLE), MB_OK);
 }
 
 void ShowExitWindowsDialog(HWND hwndOwner)
 {
-       static DynamicFct<EXITWINDOWSDLG> ExitWindowsDlg(TEXT("SHELL32"), 60);
+       static DynamicFct<EXITWINDOWSDLG> ExitWindowsDialog(TEXT("SHELL32"), 60);
 
-       if (ExitWindowsDlg)
-               (*ExitWindowsDlg)(hwndOwner);
+       if (ExitWindowsDialog)
+               (*ExitWindowsDialog)(hwndOwner);
        else
-               MessageBox(hwndOwner, TEXT("ExitWindowsDlg() not yet implemented in SHELL32"), ResString(IDS_TITLE), MB_OK);
+               MessageBox(hwndOwner, TEXT("ExitWindowsDialog() not yet implemented in SHELL32"), ResString(IDS_TITLE), MB_OK);
 }
 
 
@@ -1807,16 +2056,11 @@ void SettingsMenu::AddEntries()
 {
        super::AddEntries();
 
-#ifndef __MINGW32__    // SHRestricted() missing in MinGW (as of 29.10.2003)
-       if (!g_Globals._SHRestricted || !SHRestricted(REST_NOCONTROLPANEL))
-#endif
-               AddButton(ResString(IDS_CONTROL_PANEL), ICID_CONFIG, false, IDC_CONTROL_PANEL);
-
 #ifdef _ROS_   // to be removed when printer/network will be implemented
-       AddButton(ResString(IDS_PRINTERS),                      ICID_PRINTER, false, IDC_PRINTERS);
+       AddButton(ResString(IDS_PRINTERS),                      ICID_PRINTER, false, IDC_PRINTERS_MENU);
        AddButton(ResString(IDS_CONNECTIONS),           ICID_NETWORK, false, IDC_CONNECTIONS);
 #else
-       AddButton(ResString(IDS_PRINTERS),                      ICID_PRINTER, true, IDC_PRINTERS);
+       AddButton(ResString(IDS_PRINTERS),                      ICID_PRINTER, true, IDC_PRINTERS_MENU);
        AddButton(ResString(IDS_CONNECTIONS),           ICID_NETWORK, true, IDC_CONNECTIONS);
 #endif
        AddButton(ResString(IDS_ADMIN),                         ICID_CONFIG, true, IDC_ADMIN);
@@ -1827,6 +2071,13 @@ void SettingsMenu::AddEntries()
                AddButton(ResString(IDS_SETTINGS_MENU), ICID_CONFIG, true, IDC_SETTINGS_MENU);
 
        AddButton(ResString(IDS_DESKTOPBAR_SETTINGS), ICID_CONFIG, false, ID_DESKTOPBAR_SETTINGS);
+
+       AddButton(ResString(IDS_PRINTERS),                      ICID_PRINTER, false, IDC_PRINTERS);
+
+#ifndef __MINGW32__    // SHRestricted() missing in MinGW (as of 29.10.2003)
+       if (!g_Globals._SHRestricted || !SHRestricted(REST_NOCONTROLPANEL))
+#endif
+               AddButton(ResString(IDS_CONTROL_PANEL), ICID_CONFIG, false, IDC_CONTROL_PANEL);
 }
 
 void BrowseMenu::AddEntries()
@@ -1870,9 +2121,9 @@ void RecentStartMenu::AddEntries()
                        WaitCursor wait;
 
 #ifdef _LAZY_ICONEXTRACT
-                       dir.smart_scan(SCAN_FILESYSTEM);
+                       dir.smart_scan(SORT_NAME, SCAN_FILESYSTEM);
 #else
-                       dir.smart_scan(SCAN_EXTRACT_ICONS|SCAN_FILESYSTEM);
+                       dir.smart_scan(SORT_NAME, SCAN_EXTRACT_ICONS|SCAN_FILESYSTEM);
 #endif
                }
 
@@ -1928,8 +2179,11 @@ int FavoritesMenu::Command(int id, int code)
                        Bookmark& bookmark = *node._pbookmark;
 
                        String url = bookmark._url;
+                       HWND hparent = GetParent(_hwnd);
+
                        CloseStartMenu(id);
-                       launch_file(GetParent(_hwnd), url, SW_SHOWNORMAL);
+
+                       launch_file(hparent, url, SW_SHOWNORMAL);
                }
 
                return 0;