Synchronize with trunk revision 59636 (just before Alex's CreateProcess revamp).
[reactos.git] / base / applications / notepad / dialog.c
index d8c6adc..57fdb80 100644 (file)
@@ -20,7 +20,7 @@
  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
  */
 
-#include <notepad.h>
+#include "notepad.h"
 
 LRESULT CALLBACK EDIT_WndProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
 
@@ -92,7 +92,7 @@ static LPWSTR ConvertToUNICODE(LPSTR pszText, DWORD *pdwSize)
 }
 #endif
 
-VOID ShowLastError(void)
+VOID ShowLastError(VOID)
 {
     DWORD error = GetLastError();
     if (error != NO_ERROR)
@@ -112,31 +112,27 @@ VOID ShowLastError(void)
 
 /**
  * Sets the caption of the main window according to Globals.szFileTitle:
- *    Notepad - (untitled)      if no file is open
- *    Notepad - [filename]      if a file is given
+ *    (untitled) - Notepad      if no file is open
+ *    [filename] - Notepad      if a file is given
  */
 static void UpdateWindowCaption(void)
 {
   TCHAR szCaption[MAX_STRING_LEN];
-  TCHAR szUntitled[MAX_STRING_LEN];
+  TCHAR szNotepad[MAX_STRING_LEN];
 
-  LoadString(Globals.hInstance, STRING_NOTEPAD, szCaption, SIZEOF(szCaption));
+  LoadString(Globals.hInstance, STRING_NOTEPAD, szNotepad, SIZEOF(szNotepad));
 
-  if (Globals.szFileTitle[0] != '\0') {
-      static const TCHAR bracket_l[] = _T(" - [");
-      static const TCHAR bracket_r[] = _T("]");
-      _tcscat(szCaption, bracket_l);
-      _tcscat(szCaption, Globals.szFileTitle);
-      _tcscat(szCaption, bracket_r);
+  if (Globals.szFileTitle[0] != 0)
+  {
+      StringCchCopy(szCaption, SIZEOF(szCaption), Globals.szFileTitle);
   }
   else
   {
-      static const TCHAR hyphen[] = _T(" - ");
-      LoadString(Globals.hInstance, STRING_UNTITLED, szUntitled, SIZEOF(szUntitled));
-      _tcscat(szCaption, hyphen);
-      _tcscat(szCaption, szUntitled);
+      LoadString(Globals.hInstance, STRING_UNTITLED, szCaption, SIZEOF(szCaption));
   }
-
+  
+  StringCchCat(szCaption, SIZEOF(szCaption), _T(" - "));
+  StringCchCat(szCaption, SIZEOF(szCaption), szNotepad);
   SetWindowText(Globals.hMainWnd, szCaption);
 }
 
@@ -191,7 +187,6 @@ BOOL FileExists(LPCTSTR szFilename)
    return (hFile != INVALID_HANDLE_VALUE);
 }
 
-
 BOOL HasFileExtension(LPCTSTR szFilename)
 {
     LPCTSTR s;
@@ -202,9 +197,9 @@ BOOL HasFileExtension(LPCTSTR szFilename)
     return _tcsrchr(szFilename, _T('.')) != NULL;
 }
 
-
-static VOID DoSaveFile(VOID)
+static BOOL DoSaveFile(VOID)
 {
+    BOOL bRet = TRUE;
     HANDLE hFile;
     LPTSTR pTemp;
     DWORD size;
@@ -214,7 +209,7 @@ static VOID DoSaveFile(VOID)
     if(hFile == INVALID_HANDLE_VALUE)
     {
         ShowLastError();
-        return;
+        return FALSE;
     }
 
     size = GetWindowTextLength(Globals.hEdit) + 1;
@@ -223,30 +218,38 @@ static VOID DoSaveFile(VOID)
     {
         CloseHandle(hFile);
         ShowLastError();
-        return;
+        return FALSE;
     }
     size = GetWindowText(Globals.hEdit, pTemp, size);
 
 #ifndef UNICODE
     pTemp = (LPTSTR)ConvertToUNICODE(pTemp, &size);
-    if (!pTemp) {
+    if (!pTemp)
+    {
         /* original "pTemp" already freed */
         CloseHandle(hFile);
         ShowLastError();
-        return;
+        return FALSE;
     }
 #endif
 
     if (size)
     {
         if (!WriteText(hFile, (LPWSTR)pTemp, size, Globals.iEncoding, Globals.iEoln))
+        {
             ShowLastError();
+            bRet = FALSE;
+        }
         else
+        {
             SendMessage(Globals.hEdit, EM_SETMODIFY, FALSE, 0);
+            bRet = TRUE;
+        }
     }
 
     CloseHandle(hFile);
     HeapFree(GetProcessHeap(), 0, pTemp);
+    return bRet;
 }
 
 /**
@@ -254,7 +257,7 @@ static VOID DoSaveFile(VOID)
  *   TRUE  - User agreed to close (both save/don't save)
  *   FALSE - User cancelled close by selecting "Cancel"
  */
-BOOL DoCloseFile(void)
+BOOL DoCloseFile(VOID)
 {
     int nResult;
 
@@ -262,31 +265,35 @@ BOOL DoCloseFile(void)
     {
         /* prompt user to save changes */
         nResult = AlertFileNotSaved(Globals.szFileName);
-        switch (nResult) {
-            case IDYES:     DIALOG_FileSave();
-                            break;
+        switch (nResult)
+        {
+            case IDYES:
+                if(!DIALOG_FileSave())
+                    return FALSE;
+                break;
 
-            case IDNO:      break;
+            case IDNO:
+                break;
 
-            case IDCANCEL:  return(FALSE);
-                            break;
+            case IDCANCEL:
+                return FALSE;
 
-            default:        return(FALSE);
-                            break;
-        } /* switch */
-    } /* if */
+            default:
+                return FALSE;
+        }
+    }
 
     SetFileName(empty_str);
-
     UpdateWindowCaption();
-    return(TRUE);
+
+    return TRUE;
 }
 
-void DoOpenFile(LPCTSTR szFileName)
+VOID DoOpenFile(LPCTSTR szFileName)
 {
     static const TCHAR dotlog[] = _T(".LOG");
     HANDLE hFile;
-    LPTSTR pszText;
+    LPTSTR pszText = NULL;
     DWORD dwTextLen;
     TCHAR log[5];
 
@@ -388,12 +395,12 @@ VOID DIALOG_FileOpen(VOID)
 }
 
 
-VOID DIALOG_FileSave(VOID)
+BOOL DIALOG_FileSave(VOID)
 {
-    if (Globals.szFileName[0] == '\0')
-        DIALOG_FileSaveAs();
+    if (Globals.szFileName[0] == 0)
+        return DIALOG_FileSaveAs();
     else
-        DoSaveFile();
+        return DoSaveFile();
 }
 
 static UINT_PTR CALLBACK DIALOG_FileSaveAs_Hook(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
@@ -452,7 +459,7 @@ static UINT_PTR CALLBACK DIALOG_FileSaveAs_Hook(HWND hDlg, UINT msg, WPARAM wPar
     return 0;
 }
 
-VOID DIALOG_FileSaveAs(VOID)
+BOOL DIALOG_FileSaveAs(VOID)
 {
     OPENFILENAME saveas;
     TCHAR szDir[MAX_PATH];
@@ -479,10 +486,26 @@ VOID DIALOG_FileSaveAs(VOID)
     saveas.lpTemplateName    = MAKEINTRESOURCE(DIALOG_ENCODING);
     saveas.lpfnHook          = DIALOG_FileSaveAs_Hook;
 
-    if (GetSaveFileName(&saveas)) {
+    if (GetSaveFileName(&saveas))
+    {
+        // HACK: Because in ROS, Save-As boxes don't check the validity
+        // of file names and thus, here, szPath can be invalid !! We only
+        // see its validity when we call DoSaveFile()...
         SetFileName(szPath);
-        UpdateWindowCaption();
-        DoSaveFile();
+        if (DoSaveFile())
+        {
+            UpdateWindowCaption();
+            return TRUE;
+        }
+        else
+        {
+            SetFileName(_T(""));
+            return FALSE;
+        }
+    }
+    else
+    {
+        return FALSE;
     }
 }
 
@@ -684,56 +707,180 @@ VOID DIALOG_EditTimeDate(VOID)
     _tcscat(szText, _T(" "));
     GetDateFormat(LOCALE_USER_DEFAULT, DATE_LONGDATE, &st, NULL, szDate, MAX_STRING_LEN);
     _tcscat(szText, szDate);
-    SendMessage(Globals.hEdit, EM_REPLACESEL, TRUE, (LPARAM)szDate);
+    SendMessage(Globals.hEdit, EM_REPLACESEL, TRUE, (LPARAM)szText);
 }
 
-VOID DIALOG_EditWrap(VOID)
+VOID DoCreateStatusBar(VOID)
 {
-    static const TCHAR edit[] = _T("edit");
-    DWORD dwStyle;
-    RECT rc, rcstatus;
-    DWORD size;
-    LPTSTR pTemp;
-    TCHAR buff[MAX_PATH];
+    RECT rc;
+    RECT rcstatus;
+    BOOL bStatusBarVisible;
 
-    Globals.bWrapLongLines = !Globals.bWrapLongLines;
+    // Check if status bar object already exists.
+    if (Globals.hStatusBar == NULL)
+    {
+        // Try to create the status bar
+        Globals.hStatusBar = CreateStatusWindow(
+                                WS_CHILD | WS_VISIBLE | WS_EX_STATICEDGE,
+                                NULL,
+                                Globals.hMainWnd,
+                                CMD_STATUSBAR_WND_ID);
+
+        if (Globals.hStatusBar == NULL)
+        {
+            ShowLastError();
+            return;
+        }
 
-    size = GetWindowTextLength(Globals.hEdit) + 1;
-    pTemp = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
-    if (!pTemp)
+        // Load the string for formatting column/row text output
+        LoadString(Globals.hInstance, STRING_LINE_COLUMN, Globals.szStatusBarLineCol, MAX_PATH-1);
+
+        // Set the status bar for single-text output
+        SendMessage(Globals.hStatusBar, SB_SIMPLE, (WPARAM)TRUE, (LPARAM)0);
+    }
+
+    // Set status bar visible or not accordind the the settings.
+    if (Globals.bWrapLongLines == TRUE ||
+        Globals.bShowStatusBar == FALSE)
     {
-        ShowLastError();
-        return;
+        bStatusBarVisible = FALSE;
+        ShowWindow(Globals.hStatusBar, SW_HIDE);
+    }
+    else
+    {
+        bStatusBarVisible = TRUE;
+        ShowWindow(Globals.hStatusBar, SW_SHOW);
+        SendMessage(Globals.hStatusBar, WM_SIZE, 0, 0);
+    }
+
+    // Set check state in show status bar item.
+    if (Globals.bShowStatusBar == TRUE)
+    {
+        CheckMenuItem(Globals.hMenu, CMD_STATUSBAR, MF_BYCOMMAND | MF_CHECKED);
     }
-    GetWindowText(Globals.hEdit, pTemp, size);
-    DestroyWindow(Globals.hEdit);
-    GetClientRect(Globals.hMainWnd, &rc);
-    dwStyle = Globals.bWrapLongLines ? EDIT_STYLE_WRAP : EDIT_STYLE;
-    EnableMenuItem(GetMenu(Globals.hMainWnd), CMD_STATUSBAR,
-        MF_BYCOMMAND | (Globals.bWrapLongLines ? MF_DISABLED | MF_GRAYED : MF_ENABLED));
-    if ( Globals.hStatusBar )
+    else
+    {
+        CheckMenuItem(Globals.hMenu, CMD_STATUSBAR, MF_BYCOMMAND | MF_UNCHECKED);
+    }
+
+    // Update menu mar with the previous changes
+    DrawMenuBar(Globals.hMainWnd);
+
+    // Sefety test is edit control exists
+    if (Globals.hEdit != NULL)
+    {
+        // Retrieve the sizes of the controls
+        GetClientRect(Globals.hMainWnd, &rc);
+        GetClientRect(Globals.hStatusBar, &rcstatus);
+
+        // If status bar is currently visible, update dimensions of edir control
+        if (bStatusBarVisible)
+            rc.bottom -= (rcstatus.bottom - rcstatus.top);
+
+        // Resize edit control to right size.
+        MoveWindow(Globals.hEdit, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE);
+    }
+
+    // Update content with current row/column text
+    DIALOG_StatusBarUpdateCaretPos();
+}
+
+VOID DoCreateEditWindow(VOID)
+{
+    DWORD  dwStyle;
+    int    iSize;
+    LPTSTR pTemp = NULL;
+
+    iSize = 0;
+
+    // If the edit control already exists, try to save its content
+    if (Globals.hEdit != NULL)
+    {
+        // number of chars currently written into the editor.
+        iSize = GetWindowTextLength(Globals.hEdit);
+
+        if (iSize)
+        {
+            // Allocates temporary buffer.
+            pTemp = HeapAlloc(GetProcessHeap(), 0, (iSize + 1) * sizeof(TCHAR));
+
+            if (!pTemp)
+            {
+                ShowLastError();
+                return;
+            }
+
+            // Recover the text into the control.
+            GetWindowText(Globals.hEdit, pTemp, iSize + 1);
+        }
+
+        // Restore original window procedure
+        SetWindowLongPtr(Globals.hEdit, GWLP_WNDPROC, (LONG_PTR)Globals.EditProc);
+
+        // Destroy the edit control
+        DestroyWindow(Globals.hEdit);
+    }
+
+    // Update wrap status into the main menu and recover style flags
+    if (Globals.bWrapLongLines)
     {
-       if ( Globals.bWrapLongLines )
-          ShowWindow(Globals.hStatusBar, SW_HIDE);
-       else if ( Globals.bShowStatusBar )
-       {
-          GetClientRect(Globals.hStatusBar, &rcstatus);
-          rc.bottom -= (rcstatus.bottom - rcstatus.top);
-          ShowWindow(Globals.hStatusBar, SW_SHOW);
-       }
+        dwStyle = EDIT_STYLE_WRAP;
+        EnableMenuItem(Globals.hMenu, CMD_STATUSBAR, MF_BYCOMMAND | MF_DISABLED | MF_GRAYED);
+    } else {
+        dwStyle = EDIT_STYLE;
+        EnableMenuItem(Globals.hMenu, CMD_STATUSBAR, MF_BYCOMMAND | MF_ENABLED);
+    }
+
+    // Update previous changes
+    DrawMenuBar(Globals.hMainWnd);
+
+    // Create the new edit control
+    Globals.hEdit = CreateWindowEx(
+                        WS_EX_CLIENTEDGE,
+                        EDIT_CLASS,
+                        NULL,
+                        dwStyle,
+                        CW_USEDEFAULT,
+                        CW_USEDEFAULT,
+                        CW_USEDEFAULT,
+                        CW_USEDEFAULT,
+                        Globals.hMainWnd,
+                        NULL,
+                        Globals.hInstance,
+                        NULL);
+
+    if (Globals.hEdit == NULL)
+    {
+        ShowLastError();
+        return;
     }
-    Globals.hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, edit, NULL, dwStyle,
-                         0, 0, rc.right, rc.bottom, Globals.hMainWnd,
-                         NULL, Globals.hInstance, NULL);
+
     SendMessage(Globals.hEdit, WM_SETFONT, (WPARAM)Globals.hFont, FALSE);
     SendMessage(Globals.hEdit, EM_LIMITTEXT, 0, 0);
-    SetWindowText(Globals.hEdit, pTemp);
-    SetFocus(Globals.hEdit);
+
+    // If some text was previously saved, restore it.
+    if (iSize != 0)
+    {
+        SetWindowText(Globals.hEdit, pTemp);
+        HeapFree(GetProcessHeap(), 0, pTemp);
+    }
+
+    // Sub-class a new window callback for row/column detection.
     Globals.EditProc = (WNDPROC) SetWindowLongPtr(Globals.hEdit, GWLP_WNDPROC, (LONG_PTR)EDIT_WndProc);
-    _stprintf(buff, Globals.szStatusBarLineCol, 1, 1);
-    SendMessage(Globals.hStatusBar, SB_SETTEXT, SB_SIMPLEID, (LPARAM)buff);
-    HeapFree(GetProcessHeap(), 0, pTemp);
-    DrawMenuBar(Globals.hMainWnd);
+
+    // Create/update status bar
+    DoCreateStatusBar();
+
+    // Finally shows new edit control and set focus into it.
+    ShowWindow(Globals.hEdit, SW_SHOW);
+    SetFocus(Globals.hEdit);
+}
+
+VOID DIALOG_EditWrap(VOID)
+{
+    Globals.bWrapLongLines = !Globals.bWrapLongLines;
+
+    DoCreateEditWindow();
 }
 
 VOID DIALOG_SelectFont(VOID)
@@ -887,27 +1034,9 @@ VOID DIALOG_StatusBarUpdateCaretPos(VOID)
 
 VOID DIALOG_ViewStatusBar(VOID)
 {
-   RECT rc;
-   RECT rcstatus;
-
-   Globals.bShowStatusBar = !Globals.bShowStatusBar;
-   if ( !Globals.hStatusBar )
-   {
-       Globals.hStatusBar = CreateStatusWindow(WS_CHILD | WS_VISIBLE | WS_EX_STATICEDGE, TEXT("test"), Globals.hMainWnd, CMD_STATUSBAR_WND_ID );
-       LoadString(Globals.hInstance, STRING_LINE_COLUMN, Globals.szStatusBarLineCol, MAX_PATH-1);
-       SendMessage(Globals.hStatusBar, SB_SIMPLE, (WPARAM)TRUE, (LPARAM)0);
-   }
-    CheckMenuItem(GetMenu(Globals.hMainWnd), CMD_STATUSBAR,
-        MF_BYCOMMAND | (Globals.bShowStatusBar ? MF_CHECKED : MF_UNCHECKED));
-    DrawMenuBar(Globals.hMainWnd);
-    GetClientRect(Globals.hMainWnd, &rc);
-    GetClientRect(Globals.hStatusBar, &rcstatus);
-    if ( Globals.bShowStatusBar )
-        rc.bottom -= (rcstatus.bottom - rcstatus.top);
+    Globals.bShowStatusBar = !Globals.bShowStatusBar;
 
-    MoveWindow(Globals.hEdit, rc.left, rc.top, rc.right - rc.left, rc.bottom - rc.top, TRUE);
-    ShowWindow(Globals.hStatusBar, Globals.bShowStatusBar);
-    DIALOG_StatusBarUpdateCaretPos();
+    DoCreateStatusBar();
 }
 
 VOID DIALOG_HelpContents(VOID)