- PCHify notepad and add missing header from regedit.
[reactos.git] / reactos / subsys / system / notepad / dialog.c
index a44a1c6..1a2076c 100644 (file)
  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
  */
 
-#define UNICODE
-
-#include <assert.h>
-#include <stdio.h>
-#include <windows.h>
-#include <commdlg.h>
-
-#include "main.h"
-#include "license.h"
-#include "dialog.h"
+#include <notepad.h>
 
 static const WCHAR helpfileW[] = { 'n','o','t','e','p','a','d','.','h','l','p',0 };
 
@@ -93,7 +84,7 @@ static void AlertFileNotFound(LPCWSTR szFileName)
    wsprintf(szMessage, szResource, szFileName);
 
    /* Load szCaption */
-   LoadString(Globals.hInstance, STRING_ERROR,  szResource, SIZEOF(szResource));
+   LoadString(Globals.hInstance, STRING_NOTEPAD,  szResource, SIZEOF(szResource));
 
    /* Display Modal Dialog */
    MessageBox(Globals.hMainWnd, szMessage, szResource, MB_ICONEXCLAMATION);
@@ -112,7 +103,7 @@ static int AlertFileNotSaved(LPCWSTR szFileName)
    wsprintf(szMessage, szResource, szFileName[0] ? szFileName : szUntitled);
 
    /* Load Caption */
-   LoadString(Globals.hInstance, STRING_ERROR, szResource, SIZEOF(szResource));
+   LoadString(Globals.hInstance, STRING_NOTEPAD, szResource, SIZEOF(szResource));
 
    /* Display modal */
    return MessageBox(Globals.hMainWnd, szMessage, szResource, MB_ICONEXCLAMATION|MB_YESNOCANCEL);
@@ -135,18 +126,22 @@ BOOL FileExists(LPCWSTR szFilename)
 }
 
 
+BOOL HasFileExtension(LPCWSTR szFilename)
+{
+    LPCWSTR s;
+
+    s = wcsrchr(szFilename, '\\');
+    if (s)
+        szFilename = s;
+    return wcsrchr(szFilename, '.') != NULL;
+}
+
+
 static VOID DoSaveFile(VOID)
 {
     HANDLE hFile;
-    DWORD dwNumWrite;
     LPWSTR pTemp;
-    LPVOID pConverted = NULL;
     DWORD size;
-    BYTE bom[3];
-    int iBomSize = 0;
-    int iCodePage = -1;
-    int iNewSize;
-    int i;
 
     hFile = CreateFile(Globals.szFileName, GENERIC_WRITE, FILE_SHARE_WRITE,
                        NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
@@ -166,72 +161,13 @@ static VOID DoSaveFile(VOID)
     }
     size = GetWindowTextW(Globals.hEdit, pTemp, size);
 
-    switch(Globals.iEncoding)
-    {
-        case ENCODING_ANSI:
-            iCodePage = CP_ACP;
-            break;
-
-        case ENCODING_UNICODE:
-            pConverted = pTemp;
-            iBomSize = 2;
-            bom[0] = 0xFF;
-            bom[1] = 0xFE;
-            break;
-
-        case ENCODING_UNICODE_BE:
-            pConverted = pTemp;
-            iBomSize = 2;
-            bom[0] = 0xFE;
-            bom[1] = 0xFF;
-
-            /* flip the endianness */
-            for (i = 0; i < size; i++)
-            {
-                pTemp[i] = ((pTemp[i] & 0x00FF) << 8)
-                           | ((pTemp[i] & 0xFF00) >> 8);
-            }
-            break;
-
-        case ENCODING_UTF8:
-            iCodePage = CP_UTF8;
-            iBomSize = 3;
-            bom[0] = 0xEF;
-            bom[1] = 0xBB;
-            bom[2] = 0xBF;
-            break;
-    }
-
-    if (iCodePage >= 0)
-    {
-        iNewSize = WideCharToMultiByte(iCodePage, 0, pTemp, size, NULL, 0, NULL, NULL);
-        pConverted = HeapAlloc(GetProcessHeap(), 0, iNewSize);
-        if (!pConverted)
-        {
-            HeapFree(GetProcessHeap(), 0, pTemp);
-            CloseHandle(hFile);
-            ShowLastError();
-            return;
-        }
-        WideCharToMultiByte(iCodePage, 0, pTemp, size, pConverted, iNewSize, NULL, NULL);
-    }
-    else
-    {
-        iNewSize = size * sizeof(WCHAR);
-    }
-
-    if ((iBomSize > 0) && !WriteFile(hFile, bom, iBomSize, &dwNumWrite, NULL))
-        ShowLastError();
-    else if (!WriteFile(hFile, pConverted, iNewSize, &dwNumWrite, NULL))
+    if (!WriteText(hFile, pTemp, size, Globals.iEncoding, Globals.iEoln))
         ShowLastError();
     else
         SendMessage(Globals.hEdit, EM_SETMODIFY, FALSE, 0);
 
     CloseHandle(hFile);
     HeapFree(GetProcessHeap(), 0, pTemp);
-
-    if (iCodePage >= 0)
-        HeapFree(GetProcessHeap(), 0, pConverted);
 }
 
 /**
@@ -273,15 +209,9 @@ void DoOpenFile(LPCWSTR szFileName)
 {
     static const WCHAR dotlog[] = { '.','L','O','G',0 };
     HANDLE hFile;
-    LPSTR pTemp;
-    LPWSTR pTemp2 = NULL;
-    DWORD size;
-    DWORD dwNumRead;
+    LPWSTR pszText;
+    DWORD dwTextLen;
     WCHAR log[5];
-    LPWSTR p;
-    LPBYTE p2;
-    int iCodePage;
-    int iNewSize;
 
     /* Close any files and prompt to save changes */
     if (!DoCloseFile())
@@ -289,90 +219,19 @@ void DoOpenFile(LPCWSTR szFileName)
 
     hFile = CreateFile(szFileName, GENERIC_READ, FILE_SHARE_READ, NULL,
                        OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
-    if(hFile == INVALID_HANDLE_VALUE)
+    if (hFile == INVALID_HANDLE_VALUE)
     {
         ShowLastError();
-        return;
-    }
-
-    size = GetFileSize(hFile, NULL);
-    if (size == INVALID_FILE_SIZE)
-    {
-        CloseHandle(hFile);
-        ShowLastError();
-        return;
+        goto done;
     }
 
-    pTemp = HeapAlloc(GetProcessHeap(), 0, size + sizeof(WCHAR));
-    if (!pTemp)
+    if (!ReadText(hFile, &pszText, &dwTextLen, &Globals.iEncoding, &Globals.iEoln))
     {
-        CloseHandle(hFile);
         ShowLastError();
-        return;
+        goto done;
     }
 
-    if (!ReadFile(hFile, pTemp, size, &dwNumRead, NULL))
-    {
-        CloseHandle(hFile);
-        HeapFree(GetProcessHeap(), 0, pTemp);
-        ShowLastError();
-        return;
-    }
-
-    CloseHandle(hFile);
-    pTemp[dwNumRead] = 0;
-
-    if (IsTextUnicode(pTemp, dwNumRead, NULL))
-    {
-        p = (LPWSTR)pTemp;
-        p[dwNumRead / 2] = 0;
-
-        /* We need to strip BOM Unicode character, SetWindowTextW won't do it for us. */
-        if (*p == 0xFEFF)
-        {
-            Globals.iEncoding = ENCODING_UNICODE_BE;
-            p++;
-        }
-        else if (*p == 0xFFFE)
-        {
-            Globals.iEncoding = ENCODING_UNICODE;
-            p++;
-        }
-    }
-    else
-    {
-        p2 = (LPBYTE)pTemp;
-        if ((p2[0] == 0xEF) && (p2[1] == 0xBB) && (p2[2] == 0xBF))
-        {
-            iCodePage = CP_UTF8;
-            Globals.iEncoding = ENCODING_UTF8;
-            p2 += 3;
-            dwNumRead -= 3;
-        }
-        else
-        {
-            iCodePage = CP_ACP;
-            Globals.iEncoding = ENCODING_ANSI;
-        }
-
-        iNewSize = MultiByteToWideChar(iCodePage, 0, (LPCSTR)p2, dwNumRead, NULL, 0);
-        pTemp2 = HeapAlloc(GetProcessHeap(), 0, (iNewSize + 1) * sizeof(*pTemp2));
-        if (!pTemp2)
-        {
-            CloseHandle(hFile);
-            HeapFree(GetProcessHeap(), 0, pTemp);
-            ShowLastError();
-            return;
-        }
-        MultiByteToWideChar(iCodePage, 0, (LPCSTR)p2, dwNumRead, pTemp2, iNewSize);
-        pTemp2[iNewSize] = 0;
-        p = pTemp2;
-    }
-    SetWindowTextW(Globals.hEdit, p);
-
-    HeapFree(GetProcessHeap(), 0, pTemp);
-    if (pTemp2)
-       HeapFree(GetProcessHeap(), 0, pTemp2);
+    SetWindowTextW(Globals.hEdit, pszText);
 
     SendMessage(Globals.hEdit, EM_SETMODIFY, FALSE, 0);
     SendMessage(Globals.hEdit, EM_EMPTYUNDOBUFFER, 0, 0);
@@ -392,13 +251,19 @@ void DoOpenFile(LPCWSTR szFileName)
 
     SetFileName(szFileName);
     UpdateWindowCaption();
+
+done:
+    if (hFile != INVALID_HANDLE_VALUE)
+        CloseHandle(hFile);
+    if (pszText)
+        HeapFree(GetProcessHeap(), 0, pszText);
 }
 
 VOID DIALOG_FileNew(VOID)
 {
     static const WCHAR empty_strW[] = { 0 };
 
-    /* Close any files and promt to save changes */
+    /* Close any files and prompt to save changes */
     if (DoCloseFile()) {
         SetWindowText(Globals.hEdit, empty_strW);
         SendMessage(Globals.hEdit, EM_EMPTYUNDOBUFFER, 0, 0);
@@ -475,14 +340,33 @@ static UINT_PTR CALLBACK DIALOG_FileSaveAs_Hook(HWND hDlg, UINT msg, WPARAM wPar
             SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM) szText);
 
             SendMessage(hCombo, CB_SETCURSEL, Globals.iEncoding, 0);
+
+            hCombo = GetDlgItem(hDlg, ID_EOLN);
+
+            LoadString(Globals.hInstance, STRING_CRLF, szText, SIZEOF(szText));
+            SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM) szText);
+
+            LoadString(Globals.hInstance, STRING_LF, szText, SIZEOF(szText));
+            SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM) szText);
+
+            LoadString(Globals.hInstance, STRING_CR, szText, SIZEOF(szText));
+            SendMessage(hCombo, CB_ADDSTRING, 0, (LPARAM) szText);
+
+            SendMessage(hCombo, CB_SETCURSEL, Globals.iEoln, 0);
             break;
 
         case WM_NOTIFY:
             if (((NMHDR *) lParam)->code == CDN_FILEOK)
             {
                 pNotify = (OFNOTIFY *) lParam;
+
                 hCombo = GetDlgItem(hDlg, ID_ENCODING);
-                Globals.iEncoding = SendMessage(hCombo, CB_GETCURSEL, 0, 0);
+                               if (hCombo)
+                       Globals.iEncoding = SendMessage(hCombo, CB_GETCURSEL, 0, 0);
+
+                hCombo = GetDlgItem(hDlg, ID_EOLN);
+                               if (hCombo)
+                       Globals.iEoln = SendMessage(hCombo, CB_GETCURSEL, 0, 0);                                        
             }
             break;
     }
@@ -735,12 +619,13 @@ VOID DIALOG_EditTimeDate(VOID)
 VOID DIALOG_EditWrap(VOID)
 {
     static const WCHAR editW[] = { 'e','d','i','t',0 };
-    DWORD dwStyle = WS_CHILD | WS_VISIBLE | WS_BORDER | WS_VSCROLL |
-                    ES_AUTOVSCROLL | ES_MULTILINE;
+    DWORD dwStyle;
     RECT rc;
     DWORD size;
     LPWSTR pTemp;
 
+    Globals.bWrapLongLines = !Globals.bWrapLongLines;
+
     size = GetWindowTextLength(Globals.hEdit) + 1;
     pTemp = HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR));
     if (!pTemp)
@@ -751,18 +636,15 @@ VOID DIALOG_EditWrap(VOID)
     GetWindowText(Globals.hEdit, pTemp, size);
     DestroyWindow(Globals.hEdit);
     GetClientRect(Globals.hMainWnd, &rc);
-    if( Globals.bWrapLongLines ) dwStyle |= WS_HSCROLL | ES_AUTOHSCROLL;
+    dwStyle = Globals.bWrapLongLines ? EDIT_STYLE_WRAP : EDIT_STYLE;
     Globals.hEdit = CreateWindowEx(WS_EX_CLIENTEDGE, editW, NULL, dwStyle,
                          0, 0, rc.right, rc.bottom, Globals.hMainWnd,
                          NULL, Globals.hInstance, NULL);
     SendMessage(Globals.hEdit, WM_SETFONT, (WPARAM)Globals.hFont, (LPARAM)FALSE);
+    SendMessage(Globals.hEdit, EM_LIMITTEXT, 0, 0);
     SetWindowTextW(Globals.hEdit, pTemp);
     SetFocus(Globals.hEdit);
     HeapFree(GetProcessHeap(), 0, pTemp);
-    
-    Globals.bWrapLongLines = !Globals.bWrapLongLines;
-    CheckMenuItem(GetMenu(Globals.hMainWnd), CMD_WRAP,
-        MF_BYCOMMAND | (Globals.bWrapLongLines ? MF_CHECKED : MF_UNCHECKED));
 }
 
 VOID DIALOG_SelectFont(VOID)
@@ -788,21 +670,30 @@ VOID DIALOG_SelectFont(VOID)
     }
 }
 
-VOID DIALOG_Search(VOID)
+typedef HWND (WINAPI *FINDPROC)(LPFINDREPLACE lpfr);
+
+static VOID DIALOG_SearchDialog(FINDPROC pfnProc)
 {
-        ZeroMemory(&Globals.find, sizeof(Globals.find));
-        Globals.find.lStructSize      = sizeof(Globals.find);
-        Globals.find.hwndOwner        = Globals.hMainWnd;
-        Globals.find.hInstance        = Globals.hInstance;
-        Globals.find.lpstrFindWhat    = Globals.szFindText;
-        Globals.find.wFindWhatLen     = SIZEOF(Globals.szFindText);
-        Globals.find.Flags            = FR_DOWN;
+    ZeroMemory(&Globals.find, sizeof(Globals.find));
+    Globals.find.lStructSize      = sizeof(Globals.find);
+    Globals.find.hwndOwner        = Globals.hMainWnd;
+    Globals.find.hInstance        = Globals.hInstance;
+    Globals.find.lpstrFindWhat    = Globals.szFindText;
+    Globals.find.wFindWhatLen     = SIZEOF(Globals.szFindText);
+    Globals.find.lpstrReplaceWith = Globals.szReplaceText;
+    Globals.find.wReplaceWithLen  = SIZEOF(Globals.szReplaceText);
+    Globals.find.Flags            = FR_DOWN;
 
-        /* We only need to create the modal FindReplace dialog which will */
-        /* notify us of incoming events using hMainWnd Window Messages    */
+    /* We only need to create the modal FindReplace dialog which will */
+    /* notify us of incoming events using hMainWnd Window Messages    */
 
-        Globals.hFindReplaceDlg = FindText(&Globals.find);
-        assert(Globals.hFindReplaceDlg !=0);
+    Globals.hFindReplaceDlg = pfnProc(&Globals.find);
+    assert(Globals.hFindReplaceDlg !=0);
+}
+
+VOID DIALOG_Search(VOID)
+{
+    DIALOG_SearchDialog(FindText);
 }
 
 VOID DIALOG_SearchNext(VOID)
@@ -811,6 +702,84 @@ VOID DIALOG_SearchNext(VOID)
     DIALOG_Search();
 }
 
+VOID DIALOG_Replace(VOID)
+{
+    DIALOG_SearchDialog(ReplaceText);
+}
+
+static INT_PTR CALLBACK DIALOG_GoTo_DialogProc(HWND hwndDialog, UINT uMsg, WPARAM wParam, LPARAM lParam)
+{
+    BOOL bResult = FALSE;
+    HWND hTextBox;
+    TCHAR szText[32];
+
+    switch(uMsg) {
+       case WM_INITDIALOG:
+        hTextBox = GetDlgItem(hwndDialog, ID_LINENUMBER);
+               _sntprintf(szText, sizeof(szText) / sizeof(szText[0]), _T("%d"), lParam);
+        SetWindowText(hTextBox, szText);
+               break;
+    case WM_COMMAND:
+        if (HIWORD(wParam) == BN_CLICKED)
+        {
+            if (LOWORD(wParam) == IDOK)
+            {
+                hTextBox = GetDlgItem(hwndDialog, ID_LINENUMBER);
+                GetWindowText(hTextBox, szText, sizeof(szText) / sizeof(szText[0]));
+                EndDialog(hwndDialog, _ttoi(szText));
+                bResult = TRUE;
+            }
+                       else if (LOWORD(wParam) == IDCANCEL)
+                       {
+                EndDialog(hwndDialog, 0);
+                bResult = TRUE;
+                       }
+        }
+        break;
+    }
+
+    return bResult;
+}
+
+VOID DIALOG_GoTo(VOID)
+{
+    INT_PTR nLine;
+    LPTSTR pszText;
+    int nLength, i;
+    DWORD dwStart, dwEnd;
+
+    nLength = GetWindowTextLength(Globals.hEdit);
+    pszText = (LPTSTR) HeapAlloc(GetProcessHeap(), 0, (nLength + 1) * sizeof(*pszText));
+    if (!pszText)
+        return;
+
+    /* Retrieve current text */
+    GetWindowText(Globals.hEdit, pszText, nLength + 1);
+    SendMessage(Globals.hEdit, EM_GETSEL, (WPARAM) &dwStart, (LPARAM) &dwEnd);
+
+    nLine = 1;
+    for (i = 0; pszText[i] && (i < dwStart); i++)
+    {
+        if (pszText[i] == '\n')
+            nLine++;
+    }
+
+    nLine = DialogBoxParam(Globals.hInstance, MAKEINTRESOURCE(DIALOG_GOTO),
+        Globals.hMainWnd, DIALOG_GoTo_DialogProc, nLine);
+
+    if (nLine >= 1)
+       {
+        for (i = 0; pszText[i] && (nLine > 1) && (i < nLength - 1); i++)
+        {
+            if (pszText[i] == '\n')
+                nLine--;
+        }
+        SendMessage(Globals.hEdit, EM_SETSEL, i, i);
+        SendMessage(Globals.hEdit, EM_SCROLLCARET, 0, 0);
+       }
+       HeapFree(GetProcessHeap(), 0, pszText);
+}
+
 VOID DIALOG_HelpContents(VOID)
 {
     WinHelp(Globals.hMainWnd, helpfileW, HELP_INDEX, 0);
@@ -865,51 +834,54 @@ VOID DIALOG_FilePageSetup(void)
 static INT_PTR WINAPI DIALOG_PAGESETUP_DlgProc(HWND hDlg, UINT msg, WPARAM wParam, LPARAM lParam)
 {
 
-   switch (msg)
+    switch (msg)
     {
     case WM_COMMAND:
-      switch (wParam)
+        if (HIWORD(wParam) == BN_CLICKED)
         {
-        case IDOK:
-          /* save user input and close dialog */
-          GetDlgItemText(hDlg, 0x141, Globals.szHeader, SIZEOF(Globals.szHeader));
-          GetDlgItemText(hDlg, 0x143, Globals.szFooter, SIZEOF(Globals.szFooter));
-          GetDlgItemText(hDlg, 0x14A, Globals.szMarginTop, SIZEOF(Globals.szMarginTop));
-          GetDlgItemText(hDlg, 0x150, Globals.szMarginBottom, SIZEOF(Globals.szMarginBottom));
-          GetDlgItemText(hDlg, 0x147, Globals.szMarginLeft, SIZEOF(Globals.szMarginLeft));
-          GetDlgItemText(hDlg, 0x14D, Globals.szMarginRight, SIZEOF(Globals.szMarginRight));
-          EndDialog(hDlg, IDOK);
-          return TRUE;
-
-        case IDCANCEL:
-          /* discard user input and close dialog */
-          EndDialog(hDlg, IDCANCEL);
-          return TRUE;
-
-        case IDHELP:
-        {
-          /* FIXME: Bring this to work */
-          static const WCHAR sorryW[] = { 'S','o','r','r','y',',',' ','n','o',' ','h','e','l','p',' ','a','v','a','i','l','a','b','l','e',0 };
-          static const WCHAR helpW[] = { 'H','e','l','p',0 };
-          MessageBox(Globals.hMainWnd, sorryW, helpW, MB_ICONEXCLAMATION);
-          return TRUE;
-        }
+            switch (LOWORD(wParam))
+            {
+            case IDOK:
+                /* save user input and close dialog */
+                GetDlgItemText(hDlg, 0x141, Globals.szHeader, SIZEOF(Globals.szHeader));
+                GetDlgItemText(hDlg, 0x143, Globals.szFooter, SIZEOF(Globals.szFooter));
+                GetDlgItemText(hDlg, 0x14A, Globals.szMarginTop, SIZEOF(Globals.szMarginTop));
+                GetDlgItemText(hDlg, 0x150, Globals.szMarginBottom, SIZEOF(Globals.szMarginBottom));
+                GetDlgItemText(hDlg, 0x147, Globals.szMarginLeft, SIZEOF(Globals.szMarginLeft));
+                GetDlgItemText(hDlg, 0x14D, Globals.szMarginRight, SIZEOF(Globals.szMarginRight));
+                EndDialog(hDlg, IDOK);
+                return TRUE;
+
+            case IDCANCEL:
+                /* discard user input and close dialog */
+                EndDialog(hDlg, IDCANCEL);
+                return TRUE;
+
+            case IDHELP:
+                {
+                    /* FIXME: Bring this to work */
+                    static const WCHAR sorryW[] = { 'S','o','r','r','y',',',' ','n','o',' ','h','e','l','p',' ','a','v','a','i','l','a','b','l','e',0 };
+                    static const WCHAR helpW[] = { 'H','e','l','p',0 };
+                    MessageBox(Globals.hMainWnd, sorryW, helpW, MB_ICONEXCLAMATION);
+                    return TRUE;
+                }
 
-        default:
-          break;
+            default:
+                break;
+            }
         }
-      break;
+        break;
 
     case WM_INITDIALOG:
-       /* fetch last user input prior to display dialog */
-       SetDlgItemText(hDlg, 0x141, Globals.szHeader);
-       SetDlgItemText(hDlg, 0x143, Globals.szFooter);
-       SetDlgItemText(hDlg, 0x14A, Globals.szMarginTop);
-       SetDlgItemText(hDlg, 0x150, Globals.szMarginBottom);
-       SetDlgItemText(hDlg, 0x147, Globals.szMarginLeft);
-       SetDlgItemText(hDlg, 0x14D, Globals.szMarginRight);
-       break;
+        /* fetch last user input prior to display dialog */
+        SetDlgItemText(hDlg, 0x141, Globals.szHeader);
+        SetDlgItemText(hDlg, 0x143, Globals.szFooter);
+        SetDlgItemText(hDlg, 0x14A, Globals.szMarginTop);
+        SetDlgItemText(hDlg, 0x150, Globals.szMarginBottom);
+        SetDlgItemText(hDlg, 0x147, Globals.szMarginLeft);
+        SetDlgItemText(hDlg, 0x14D, Globals.szMarginRight);
+        break;
     }
 
-  return FALSE;
+    return FALSE;
 }