mirror of
https://github.com/quantum5/Zalgo.git
synced 2025-04-24 21:52:03 -04:00
Also: 1. Cleaned up text handling by storing them in resource. 2. Added useful methods to make code look better. 3. Allowed PreviewWindow to be used for general text displaying.
347 lines
9.4 KiB
C++
347 lines
9.4 KiB
C++
#include <PreviewWindow.hpp>
|
|
|
|
#include <resource.h>
|
|
#include <windowsx.h>
|
|
|
|
LRESULT PreviewWindow::OnCreate()
|
|
{
|
|
LOGFONT lf;
|
|
RECT client;
|
|
GetClientRect(m_hwnd, &client);
|
|
|
|
GetMessageFont(lf);
|
|
hFont = CreateFontIndirect(&lf);
|
|
SendMessage(m_hwnd, WM_SETFONT, (WPARAM) hFont, FALSE);
|
|
|
|
lpLines = NULL;
|
|
return 0;
|
|
}
|
|
|
|
LRESULT PreviewWindow::OnDestroy()
|
|
{
|
|
return 0;
|
|
}
|
|
|
|
HICON PreviewWindow::GetIcon()
|
|
{
|
|
return LoadIcon(GetInstance(), MAKEINTRESOURCE(RID_ICON));
|
|
}
|
|
|
|
void PreviewWindow::OnPaint()
|
|
{
|
|
PAINTSTRUCT ps;
|
|
SCROLLINFO si;
|
|
RECT rect;
|
|
|
|
BeginPaint(m_hwnd, &ps);
|
|
GetClientRect(m_hwnd, &rect);
|
|
|
|
if (empty)
|
|
goto done;
|
|
|
|
si.cbSize = sizeof(si);
|
|
si.fMask = SIF_POS;
|
|
GetScrollInfo(m_hwnd, SB_VERT, &si);
|
|
yPos = si.nPos;
|
|
|
|
SelectObject(ps.hdc, hFont);
|
|
SetBkMode(ps.hdc, TRANSPARENT);
|
|
// Find painting limits.
|
|
int FirstLine = max(0, yPos + ps.rcPaint.top / yChar);
|
|
int LastLine = min(lines - 1, yPos + ps.rcPaint.bottom / yChar);
|
|
|
|
// Get horizontal scroll bar position.
|
|
GetScrollInfo(m_hwnd, SB_HORZ, &si);
|
|
xPos = si.nPos;
|
|
for (int i = FirstLine; i <= LastLine; i++) {
|
|
int x = xChar * (1 - xPos);
|
|
int y = yChar * (i - yPos);
|
|
rect.top = y;
|
|
rect.left = x;
|
|
DrawText(ps.hdc, lpLines[i], -1, &rect, DT_EXPANDTABS | DT_NOCLIP | DT_NOPREFIX);
|
|
}
|
|
done:
|
|
EndPaint(m_hwnd, &ps);
|
|
}
|
|
|
|
void PreviewWindow::ChangeText(LPWSTR text, bool padding)
|
|
{
|
|
if (lpLines) {
|
|
for (int i = 0; i < lines; ++i)
|
|
delete [] lpLines[i];
|
|
delete [] lpLines;
|
|
}
|
|
|
|
int l = 0, longest = 0, maxlen = 0;
|
|
LPWSTR str = text;
|
|
|
|
if (*str == L'\0') {
|
|
empty = true;
|
|
lpLines = NULL;
|
|
} else empty = false;
|
|
|
|
while (*str++)
|
|
if (*str == L'\n')
|
|
++l;
|
|
|
|
if (*(str-1) != L'\n')
|
|
++l;
|
|
|
|
lines = l;
|
|
if (padding)
|
|
lines += 8;
|
|
lpLines = new LPTSTR[lines];
|
|
if (padding) {
|
|
for (int i = 0; i < 4; ++i) {
|
|
lpLines[i] = new TCHAR[1];
|
|
lpLines[i][0] = L'\0';
|
|
}
|
|
}
|
|
|
|
for (int i = 0; i < l; ++i) {
|
|
LPTSTR start = text, end, buf;
|
|
int len;
|
|
while (*text++ != L'\n' && *(text-1) != L'\0');
|
|
end = text - 1;
|
|
len = end - start;
|
|
if (len > maxlen) {
|
|
longest = i + (padding ? 4 : 0);
|
|
maxlen = len;
|
|
}
|
|
buf = new TCHAR[len + 1];
|
|
memcpy(buf, start, len*sizeof(TCHAR));
|
|
buf[len] = L'\0';
|
|
lpLines[i + (padding ? 4 : 0)] = buf;
|
|
}
|
|
if (padding) {
|
|
for (int i = l + 4; i < lines; ++i) {
|
|
lpLines[i] = new TCHAR[1];
|
|
lpLines[i][0] = L'\0';
|
|
}
|
|
}
|
|
|
|
int upper = 0, lower = 0;
|
|
for (LPTSTR i = lpLines[longest]; *i; ++i) {
|
|
if (isupper(*i))
|
|
++upper;
|
|
else if (!(*i >= 0x0300 && *i < 0x0370 || *i == 0x489))
|
|
++lower;
|
|
}
|
|
xClientMax = lower * xChar + upper * xUpper;
|
|
|
|
PostMessage(m_hwnd, WM_SIZE, 0, 0);
|
|
}
|
|
|
|
void PreviewWindow::SetFont(HFONT hFont)
|
|
{
|
|
if (used_logfont)
|
|
DeleteFont(this->hFont);
|
|
used_logfont = false;
|
|
SendMessage(m_hwnd, WM_SETFONT, (WPARAM) hFont, TRUE);
|
|
}
|
|
|
|
void PreviewWindow::SetFont(const LOGFONT &lf)
|
|
{
|
|
if (used_logfont)
|
|
DeleteFont(this->hFont);
|
|
used_logfont = true;
|
|
hFont = CreateFontIndirect(&lf);
|
|
SendMessage(m_hwnd, WM_SETFONT, (WPARAM) hFont, TRUE);
|
|
}
|
|
|
|
LRESULT PreviewWindow::HandleMessage(UINT uMsg, WPARAM wParam, LPARAM lParam)
|
|
{
|
|
switch(uMsg) {
|
|
case WM_CREATE:
|
|
return OnCreate();
|
|
case WM_DESTROY:
|
|
return OnDestroy();
|
|
case WM_NCDESTROY:
|
|
PostQuitMessage(0);
|
|
break;
|
|
case WM_PAINT:
|
|
OnPaint();
|
|
return 0;
|
|
case WM_SIZE: {
|
|
RECT client;
|
|
SCROLLINFO si;
|
|
|
|
GetClientRect(m_hwnd, &client);
|
|
yClient = client.bottom - client.top;
|
|
xClient = client.right - client.left;
|
|
|
|
// Set the vertical scrolling range and page size
|
|
si.cbSize = sizeof(si);
|
|
si.fMask = SIF_RANGE | SIF_PAGE;
|
|
si.nMin = 0;
|
|
si.nMax = lines - 1;
|
|
si.nPage = yClient / yChar;
|
|
SetScrollInfo(m_hwnd, SB_VERT, &si, TRUE);
|
|
|
|
// Set the horizontal scrolling range and page size.
|
|
si.cbSize = sizeof(si);
|
|
si.fMask = SIF_RANGE | SIF_PAGE;
|
|
si.nMin = 0;
|
|
si.nMax = 2 + xClientMax / xChar;
|
|
si.nPage = xClient / xChar;
|
|
SetScrollInfo(m_hwnd, SB_HORZ, &si, TRUE);
|
|
return 0;
|
|
}
|
|
case WM_HSCROLL: {
|
|
SCROLLINFO si;
|
|
// Get all the vertial scroll bar information.
|
|
si.cbSize = sizeof(si);
|
|
si.fMask = SIF_ALL;
|
|
|
|
// Save the position for comparison later on.
|
|
GetScrollInfo(m_hwnd, SB_HORZ, &si);
|
|
xPos = si.nPos;
|
|
switch(LOWORD(wParam)) {
|
|
// User clicked the left arrow.
|
|
case SB_LINELEFT:
|
|
si.nPos -= 1;
|
|
break;
|
|
// User clicked the right arrow.
|
|
case SB_LINERIGHT:
|
|
si.nPos += 1;
|
|
break;
|
|
// User clicked the scroll bar shaft left of the scroll box.
|
|
case SB_PAGELEFT:
|
|
si.nPos -= si.nPage;
|
|
break;
|
|
// User clicked the scroll bar shaft right of the scroll box.
|
|
case SB_PAGERIGHT:
|
|
si.nPos += si.nPage;
|
|
break;
|
|
// User dragged the scroll box.
|
|
case SB_THUMBTRACK:
|
|
si.nPos = si.nTrackPos;
|
|
break;
|
|
}
|
|
// Set the position and then retrieve it. Due to adjustments
|
|
// by Windows it may not be the same as the value set.
|
|
si.fMask = SIF_POS;
|
|
SetScrollInfo(m_hwnd, SB_HORZ, &si, TRUE);
|
|
GetScrollInfo(m_hwnd, SB_HORZ, &si);
|
|
|
|
// If the position has changed, scroll the window.
|
|
if(si.nPos != xPos)
|
|
ScrollWindow(m_hwnd, xChar *(xPos - si.nPos), 0, NULL, NULL);
|
|
return 0;
|
|
}
|
|
case WM_VSCROLL: {
|
|
SCROLLINFO si;
|
|
// Get all the vertial scroll bar information.
|
|
si.cbSize = sizeof(si);
|
|
si.fMask = SIF_ALL;
|
|
GetScrollInfo(m_hwnd, SB_VERT, &si);
|
|
|
|
// Save the position for comparison later on.
|
|
yPos = si.nPos;
|
|
switch(LOWORD(wParam)) {
|
|
// User clicked the HOME keyboard key.
|
|
case SB_TOP:
|
|
si.nPos = si.nMin;
|
|
break;
|
|
// User clicked the END keyboard key.
|
|
case SB_BOTTOM:
|
|
si.nPos = si.nMax;
|
|
break;
|
|
// User clicked the top arrow.
|
|
case SB_LINEUP:
|
|
si.nPos -= 1;
|
|
break;
|
|
// User clicked the bottom arrow.
|
|
case SB_LINEDOWN:
|
|
si.nPos += 1;
|
|
break;
|
|
// User clicked the scroll bar shaft above the scroll box.
|
|
case SB_PAGEUP:
|
|
si.nPos -= si.nPage;
|
|
break;
|
|
// User clicked the scroll bar shaft below the scroll box.
|
|
case SB_PAGEDOWN:
|
|
si.nPos += si.nPage;
|
|
break;
|
|
// User dragged the scroll box.
|
|
case SB_THUMBTRACK:
|
|
si.nPos = si.nTrackPos;
|
|
break;
|
|
}
|
|
// Set the position and then retrieve it. Due to adjustments
|
|
// by Windows it may not be the same as the value set.
|
|
si.fMask = SIF_POS;
|
|
SetScrollInfo(m_hwnd, SB_VERT, &si, TRUE);
|
|
GetScrollInfo(m_hwnd, SB_VERT, &si);
|
|
|
|
// If the position has changed, scroll window and update it.
|
|
if(si.nPos != yPos) {
|
|
ScrollWindow(m_hwnd, 0, yChar *(yPos - si.nPos), NULL, NULL);
|
|
UpdateWindow(m_hwnd);
|
|
}
|
|
return 0;
|
|
}
|
|
case WM_MOUSEWHEEL: {
|
|
SCROLLINFO si;
|
|
// Get all the vertial scroll bar information.
|
|
si.cbSize = sizeof(si);
|
|
si.fMask = SIF_ALL;
|
|
GetScrollInfo(m_hwnd, SB_VERT, &si);
|
|
yPos = si.nPos;
|
|
|
|
si.nPos -= GET_WHEEL_DELTA_WPARAM(wParam) / WHEEL_DELTA;
|
|
si.fMask = SIF_POS;
|
|
SetScrollInfo(m_hwnd, SB_VERT, &si, TRUE);
|
|
GetScrollInfo(m_hwnd, SB_VERT, &si);
|
|
|
|
if(si.nPos != yPos) {
|
|
ScrollWindow(m_hwnd, 0, yChar *(yPos - si.nPos), NULL, NULL);
|
|
UpdateWindow(m_hwnd);
|
|
}
|
|
return 0;
|
|
}
|
|
case WM_CHANGETEXT:
|
|
ChangeText((LPTSTR) lParam, (wParam & 1) == 0);
|
|
return 0;
|
|
case WM_SETFONT: {
|
|
HDC hdc = GetDC(m_hwnd);
|
|
hFont = (HFONT) wParam;
|
|
HFONT hOldFont = SelectFont(hdc, hFont);
|
|
|
|
TEXTMETRIC tm;
|
|
// Extract font dimensions from the text metrics.
|
|
GetTextMetrics(hdc, &tm);
|
|
xChar = tm.tmAveCharWidth;
|
|
xUpper =(tm.tmPitchAndFamily & 1 ? 3 : 2) * xChar/2;
|
|
yChar = tm.tmHeight + tm.tmExternalLeading;
|
|
// Set an arbitrary maximum width for client area.
|
|
//(xClientMax is the sum of the widths of 48 average
|
|
// lowercase letters and 12 uppercase letters.)
|
|
xClientMax = 48 * xChar + 12 * xUpper;
|
|
|
|
SelectFont(hdc, hOldFont);
|
|
ReleaseDC(m_hwnd, hdc);
|
|
break;
|
|
}
|
|
case WM_CLOSE:
|
|
ShowWindow(SW_HIDE);
|
|
return 0;
|
|
}
|
|
|
|
return __super::HandleMessage(uMsg, wParam, lParam);
|
|
}
|
|
|
|
PreviewWindow *PreviewWindow::Create(LPCTSTR szTitle)
|
|
{
|
|
PreviewWindow *self = new PreviewWindow();
|
|
if(self &&
|
|
self->WinCreateWindow(0,
|
|
szTitle, WS_OVERLAPPEDWINDOW,
|
|
CW_USEDEFAULT, CW_USEDEFAULT, 640, 480,
|
|
NULL, NULL)) {
|
|
return self;
|
|
}
|
|
delete self;
|
|
return NULL;
|
|
}
|