From 7b7fbb2009f18c05fc5705e8ca4033af4d48740a Mon Sep 17 00:00:00 2001 From: Quantum Date: Tue, 27 Aug 2013 17:10:09 -0400 Subject: [PATCH] Added loading/saving abilities. --- Makefile | 4 +- include/MainWindow.hpp | 9 ++- include/resource.h | 15 +++++ src/MainLoadSave.cpp | 140 +++++++++++++++++++++++++++++++++++++++++ src/MainWindow.cpp | 56 ++++++++++++++--- 5 files changed, 213 insertions(+), 11 deletions(-) create mode 100644 src/MainLoadSave.cpp diff --git a/Makefile b/Makefile index 90753e8..1890fcf 100644 --- a/Makefile +++ b/Makefile @@ -26,6 +26,7 @@ FILES=$(OUTDIR)\Zalgo.obj \ $(OUTDIR)\Window.obj \ $(OUTDIR)\DropTarget.obj \ $(OUTDIR)\MainLogic.obj \ + $(OUTDIR)\MainLoadSave.obj \ $(OUTDIR)\PreviewWindow.obj \ $(OUTDIR)\NLSWrap.obj \ $(OUTDIR)\MyDropTarget.obj \ @@ -39,11 +40,12 @@ initdir: if not exist build md dist if not exist $(DISTDIR) md $(DISTDIR) -$(INCDIR)\MainWindow.hpp: $(INCDIR)\Window.hpp $(INCDIR)\MyDropTarget.hpp +$(INCDIR)\MainWindow.hpp: $(INCDIR)\Window.hpp $(INCDIR)\MyDropTarget.hpp $(INCDIR)\PreviewWindow.hpp $(INCDIR)\PreviewWindow.hpp: $(INCDIR)\Window.hpp $(INCDIR)\MyDropTarget.hpp: $(INCDIR)\DropTarget.hpp $(SRCDIR)\MainWindow.cpp: $(INCDIR)\MainWindow.hpp $(INCDIR)\PreviewWindow.hpp +$(SRCDIR)\MainLoadSave.cpp: $(INCDIR)\MainWindow.hpp $(SRCDIR)\DropTarget.cpp: $(INCDIR)\DropTarget.hpp $(SRCDIR)\MyDropTarget.cpp: $(INCDIR)\MyDropTarget.hpp $(SRCDIR)\Zalgo.cpp: $(INCDIR)\MainWindow.hpp diff --git a/include/MainWindow.hpp b/include/MainWindow.hpp index 0592b83..c555e23 100644 --- a/include/MainWindow.hpp +++ b/include/MainWindow.hpp @@ -28,6 +28,9 @@ #define ZALGO_GREEK 0xA556 #define ZALGO_XSAMPA 0xA557 #define ZALGO_XSAMPA_TABLE 0xA558 +#define ZALGO_LOAD 0xA559 +#define ZALGO_SAVE 0xA55A +#define ZALGO_USE_UTF8 0xA55B class MainWindow : public Window { public: @@ -49,13 +52,17 @@ protected: void OnTextLatin(); void OnTextGreek(); void OnTextXSAMPA(); + + void OnLoadFile(); + void OnSaveFile(); - HWND m_message; + HWND m_message, m_settings; HWND m_goUp, m_goMiddle, m_goDown; HWND m_messMini, m_messNormal, m_messMax, m_messCustom; HWND m_messLevel, m_messUpDown; HWND m_mess, m_unmess, m_previewShow; HWND m_nfc, m_nfd; + HWND m_load, m_save, m_use_utf8; HWND m_latin, m_cyrillic, m_greek, m_xsampa, m_xsampa_table; MyDropTarget m_dropTarget; PreviewWindow *m_preview, *m_data_display; diff --git a/include/resource.h b/include/resource.h index 5dc1b0a..5e40c40 100644 --- a/include/resource.h +++ b/include/resource.h @@ -8,3 +8,18 @@ inline void GetMessageFont(LOGFONT &lf) { SystemParametersInfo(SPI_GETNONCLIENTMETRICS, 0, &ncmMetrics, 0); memcpy(&lf, &ncmMetrics.lfMessageFont, sizeof lf); } + +inline void TellError(LPWSTR title, HWND hwnd = NULL, DWORD error = (DWORD) -1) { + LPTSTR message; + if (error == (DWORD) -1) + error = GetLastError(); + if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, + NULL, error, 0, (LPWSTR) &message, 0, NULL) == 0) { + TCHAR str[25]; + wsprintf(str, L"0x%x", error); + MessageBox(hwnd, str, title, MB_ICONERROR); + } else { + MessageBox(hwnd, message, title, MB_ICONERROR); + LocalFree(message); + } +} diff --git a/src/MainLoadSave.cpp b/src/MainLoadSave.cpp new file mode 100644 index 0000000..0c3456f --- /dev/null +++ b/src/MainLoadSave.cpp @@ -0,0 +1,140 @@ +#include + +#include +#include +#include + +void MainWindow::OnLoadFile() +{ + OPENFILENAME ofn = { sizeof(OPENFILENAME), 0 }; + WCHAR path[MAX_PATH] = { 0 }; + HANDLE file = INVALID_HANDLE_VALUE, mapping = 0; + LPSTR data = NULL; + LPWSTR storage = NULL; + + ofn.hwndOwner = m_hwnd; + ofn.lpstrFilter = L"Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0"; + ofn.lpstrFile = path; + ofn.nMaxFile = MAX_PATH; + ofn.lpstrTitle = L"Load Text/Zalgo File"; + ofn.Flags = OFN_EXPLORER | OFN_FILEMUSTEXIST; + + if (!GetOpenFileName(&ofn)) + return; + + file = CreateFile(path, GENERIC_READ, FILE_SHARE_READ, + NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); + if (file == INVALID_HANDLE_VALUE) { + TellError(L"Failed to Load File", m_hwnd); + return; + } + + DWORD length = GetFileSize(file, NULL); + if (!length) { + MessageBox(m_hwnd, L"You have to choose a file with contents!", + L"Zero size file", MB_ICONERROR); + goto cleanup; + } + + mapping = CreateFileMapping(file, NULL, PAGE_READONLY, 0, 0, NULL); + if (!mapping) { + TellError(L"Failed to Load File", m_hwnd); + goto cleanup; + } + + data = (LPSTR) MapViewOfFile(mapping, FILE_MAP_READ, 0, 0, 0); + if (!data) { + TellError(L"Failed to Load File into Memory", m_hwnd); + goto cleanup; + } + int codepage = IsDlgButtonChecked(m_hwnd, ZALGO_USE_UTF8) ? CP_UTF8 : CP_ACP; + DWORD size = MultiByteToWideChar(codepage, 0, data, -1, NULL, 0); + storage = (LPWSTR) HeapAlloc(GetProcessHeap(), 0, size * sizeof(WCHAR)); + + if (!storage) { + MessageBox(m_hwnd, L"Out of memory/address space!", + L"Can't Allocate Memory", MB_ICONERROR); + goto cleanup; + } + + if (!MultiByteToWideChar(codepage, 0, data, -1, storage, size)) { + TellError(L"Failed to Convert to UTF-16", m_hwnd); + goto cleanup; + } + + if (!Edit_SetText(m_message, storage)) { + MessageBox(m_hwnd, L"Failed to load file into editor", + L"Failed to Load File", MB_ICONERROR); + } + + cleanup: + if (storage) + HeapFree(GetProcessHeap(), 0, storage); + if (data) + UnmapViewOfFile(data); + if (mapping) + CloseHandle(mapping); + if (file != INVALID_HANDLE_VALUE) + CloseHandle(file); +} + +void MainWindow::OnSaveFile() +{ + OPENFILENAME ofn = { sizeof(OPENFILENAME), 0 }; + WCHAR path[MAX_PATH] = { 0 }; + LPWSTR data = NULL; + LPSTR storage = NULL; + HANDLE file = INVALID_HANDLE_VALUE; + + ofn.hwndOwner = m_hwnd; + ofn.lpstrFilter = L"Text Files (*.txt)\0*.txt\0All Files (*.*)\0*.*\0"; + ofn.lpstrFile = path; + ofn.nMaxFile = MAX_PATH; + ofn.lpstrTitle = L"Save Text/Zalgo File"; + ofn.Flags = OFN_EXPLORER; + ofn.lpstrDefExt = L"txt"; + + if (!GetSaveFileName(&ofn)) + return; + + HLOCAL buf = Edit_GetHandle(m_message); + data = (LPWSTR) LocalLock(buf); + + int codepage = IsDlgButtonChecked(m_hwnd, ZALGO_USE_UTF8) ? CP_UTF8 : CP_ACP; + int size = WideCharToMultiByte(codepage, 0, data, -1, NULL, 0, NULL, NULL); + storage = (LPSTR) HeapAlloc(GetProcessHeap(), 0, size); + + if (!storage) { + MessageBox(m_hwnd, L"Out of memory/address space!", + L"Can't Allocate Memory", MB_ICONERROR); + goto cleanup; + } + + if (!WideCharToMultiByte(codepage, 0, data, -1, storage, size, NULL, NULL)) { + TellError(L"Failed to Convert to Multibyte", m_hwnd); + goto cleanup; + } + + file = CreateFile(path, GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, NULL); + if (file == INVALID_HANDLE_VALUE) { + TellError(L"Failed to Create Save File", m_hwnd); + goto cleanup; + } + + DWORD length = lstrlenA(storage); + DWORD written; + if (!WriteFile(file, storage, length, &written, NULL)) + TellError(L"Failed to Write to Save File", m_hwnd); + + if (written != length) + MessageBox(m_hwnd, L"File might not be written fully.", L"Warning", MB_ICONWARNING); + + cleanup: + if (file != INVALID_HANDLE_VALUE) + CloseHandle(file); + if (storage) + HeapFree(GetProcessHeap(), 0, storage); + if (data) + LocalUnlock(buf); +} diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index 5e7e266..a705248 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -87,6 +87,10 @@ LRESULT MainWindow::OnCreate() if (initial) delete [] initial; + m_settings = CreateWindow(WC_STATIC, L"Options:", + WS_CHILDWINDOW | WS_VISIBLE, 0, 0, 0, 0, + m_hwnd, NULL, GetInstance(), NULL); + m_goUp = CreateWindow(WC_BUTTON, L"fuck up going &up", WS_CHILDWINDOW | WS_VISIBLE | BS_CHECKBOX, 0, 0, 0, 0, m_hwnd, (HMENU) ZALGO_GO_UP, GetInstance(), NULL); @@ -128,6 +132,16 @@ LRESULT MainWindow::OnCreate() WS_CHILDWINDOW | WS_VISIBLE | BS_PUSHBUTTON, 0, 0, 0, 0, m_hwnd, (HMENU) ZALGO_PREVIEW, GetInstance(), NULL); + m_use_utf8 = CreateWindow(WC_BUTTON, L"Use U&TF-8 in Load/Save", + WS_CHILDWINDOW | WS_VISIBLE | BS_CHECKBOX, 0, 0, 0, 0, + m_hwnd, (HMENU) ZALGO_USE_UTF8, GetInstance(), NULL); + m_load = CreateWindow(WC_BUTTON, L"L&oad", + WS_CHILDWINDOW | WS_VISIBLE | BS_PUSHBUTTON, 0, 0, 0, 0, + m_hwnd, (HMENU) ZALGO_LOAD, GetInstance(), NULL); + m_save = CreateWindow(WC_BUTTON, L"S&ave", + WS_CHILDWINDOW | WS_VISIBLE | BS_PUSHBUTTON, 0, 0, 0, 0, + m_hwnd, (HMENU) ZALGO_SAVE, GetInstance(), NULL); + m_nfc = CreateWindow(WC_BUTTON, L"N&FC", WS_CHILDWINDOW | WS_VISIBLE | BS_PUSHBUTTON, 0, 0, 0, 0, m_hwnd, (HMENU) TEXT_TO_NFC, GetInstance(), NULL); @@ -155,6 +169,7 @@ LRESULT MainWindow::OnCreate() PostMessage(m_messUpDown, UDM_SETPOS32, 0, ZALGO_MESS_LEVEL_OF(ZALGO_NORMAL_MESS)); #define SETFONT(hwnd) PostMessage(hwnd, WM_SETFONT, (WPARAM) hFont, (LPARAM) FALSE) SETFONT(m_message); + SETFONT(m_settings); SETFONT(m_goUp); SETFONT(m_goMiddle); SETFONT(m_goDown); @@ -166,6 +181,9 @@ LRESULT MainWindow::OnCreate() SETFONT(m_mess); SETFONT(m_unmess); SETFONT(m_previewShow); + SETFONT(m_use_utf8); + SETFONT(m_load); + SETFONT(m_save); SETFONT(m_nfc); SETFONT(m_nfd); SETFONT(m_latin); @@ -179,6 +197,7 @@ LRESULT MainWindow::OnCreate() Button_SetCheck(m_goMiddle, 1); Button_SetCheck(m_goDown, 1); Button_SetCheck(m_messNormal, 1); + Button_SetCheck(m_use_utf8, 1); Edit_Enable(m_messLevel, 0); if (!m_dropTarget.DragDropRegister(m_hwnd)) @@ -203,6 +222,7 @@ LRESULT MainWindow::OnDestroy() SetWindowLongPtr(m_message, GWL_WNDPROC, (LONG_PTR) wpOrigEditProc); DestroyWindow(m_message); + DestroyWindow(m_settings); DestroyWindow(m_goUp); DestroyWindow(m_goMiddle); DestroyWindow(m_goDown); @@ -215,6 +235,9 @@ LRESULT MainWindow::OnDestroy() DestroyWindow(m_mess); DestroyWindow(m_unmess); DestroyWindow(m_previewShow); + DestroyWindow(m_use_utf8); + DestroyWindow(m_load); + DestroyWindow(m_save); DestroyWindow(m_nfc); DestroyWindow(m_nfd); DestroyWindow(m_latin); @@ -259,7 +282,8 @@ LRESULT MainWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) GetClientRect(m_hwnd, &client); #define REPOS(hwnd, k) hdwp = DeferWindowPos(hdwp, hwnd, 0, k, SWP_NOACTIVATE|SWP_NOZORDER) hdwp = BeginDeferWindowPos(14); - REPOS(m_message, LEFT(12, 12, client.right - 24, client.bottom - 124)); + REPOS(m_message, LEFT(12, 12, client.right - 24, client.bottom - 149)); + REPOS(m_settings, BOTTOM(12, client.bottom - 84, 140, 20)); REPOS(m_goUp, BOTTOM(12, client.bottom - 59, 140, 20)); REPOS(m_goMiddle, BOTTOM(12, client.bottom - 34, 140, 20)); REPOS(m_goDown, BOTTOM(12, client.bottom - 9, 140, 20)); @@ -273,12 +297,15 @@ LRESULT MainWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) REPOS(m_unmess, BOTTOMRIGHT(client.right - 12, client.bottom - 12, 100, 25)); REPOS(m_nfc, BOTTOMRIGHT(client.right - 117, client.bottom - 41, 50, 25)); REPOS(m_nfd, BOTTOMRIGHT(client.right - 117, client.bottom - 12, 50, 25)); - REPOS(m_previewShow, BOTTOMRIGHT(client.right - 172, client.bottom - 12, 100, 25)); - REPOS(m_latin, BOTTOM(12, client.bottom - 84, 100, 25)); - REPOS(m_cyrillic, BOTTOM(117, client.bottom - 84, 100, 25)); - REPOS(m_greek, BOTTOM(222, client.bottom - 84, 100, 25)); - REPOS(m_xsampa, BOTTOM(327, client.bottom - 84, 100, 25)); - REPOS(m_xsampa_table, BOTTOM(432, client.bottom - 84, 100, 25)); + REPOS(m_latin, BOTTOM(12, client.bottom - 109, 100, 25)); + REPOS(m_cyrillic, BOTTOM(117, client.bottom - 109, 100, 25)); + REPOS(m_greek, BOTTOM(222, client.bottom - 109, 100, 25)); + REPOS(m_xsampa, BOTTOM(327, client.bottom - 109, 100, 25)); + REPOS(m_xsampa_table, BOTTOM(432, client.bottom - 109, 100, 25)); + REPOS(m_use_utf8, BOTTOMRIGHT(client.right - 332, client.bottom - 80, 160, 25)); + REPOS(m_previewShow, BOTTOMRIGHT(client.right - 222, client.bottom - 80, 100, 25)); + REPOS(m_load, BOTTOMRIGHT(client.right - 117, client.bottom - 80, 100, 25)); + REPOS(m_save, BOTTOMRIGHT(client.right - 12, client.bottom - 80, 100, 25)); EndDeferWindowPos(hdwp); #undef REPOS return 0; @@ -325,6 +352,7 @@ LRESULT MainWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) case ZALGO_GO_UP: case ZALGO_GO_CENTER: case ZALGO_GO_DOWN: + case ZALGO_USE_UTF8: Button_SetCheck((HWND) lParam, !IsDlgButtonChecked(m_hwnd, LOWORD(wParam))); break; case ZALGO_XSAMPA_TABLE: { @@ -342,6 +370,12 @@ LRESULT MainWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) delete [] text; break; } + case ZALGO_LOAD: + OnLoadFile(); + break; + case ZALGO_SAVE: + OnSaveFile(); + break; default: Button_SetCheck(GetDlgItem(m_hwnd, ZALGO_MINI_MESS), 0); Button_SetCheck(GetDlgItem(m_hwnd, ZALGO_NORMAL_MESS), 0); @@ -369,6 +403,10 @@ LRESULT MainWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) HBRUSH white = CreateSolidBrush(RGB(255, 255, 255)); if ((HWND) lParam == m_messLevel && IsWindowEnabled(m_messLevel)) return (LRESULT) white; + if ((HWND) lParam == m_settings) { + SetBkColor((HDC) wParam, GetSysColor(COLOR_3DFACE)); + return (LRESULT) GetSysColorBrush(COLOR_3DFACE); + } SetBkColor((HDC) wParam, rgbWindowBackground); return (LRESULT) hBrush; } @@ -378,7 +416,7 @@ LRESULT MainWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam) static bool unlocked = false; LPWSTR text = GetResourceString(RID_LOOSE); // A user has tried to go beyond max, let it work - if (!unlocked && MessageBox(m_hwnd, text,L"About to Unlock Secret", + if (!unlocked && MessageBox(m_hwnd, text, L"About to Unlock Secret", MB_YESNO | MB_ICONQUESTION) == IDYES) { PostMessage(m_messUpDown, UDM_SETRANGE32, 1, LONG_MAX); PostMessage(m_messLevel, EM_SETREADONLY, 0, 0); @@ -408,7 +446,7 @@ MainWindow *MainWindow::Create(LPCTSTR szTitle) if (self && self->WinCreateWindow(0, szTitle, WS_OVERLAPPEDWINDOW | WS_CLIPCHILDREN, - CW_USEDEFAULT, CW_USEDEFAULT, 640, 480, + CW_USEDEFAULT, CW_USEDEFAULT, 640, 500, NULL, NULL)) { return self; }