Zalgo/src/PreviewWindow.cpp

348 lines
9.4 KiB
C++
Raw Normal View History

2013-03-30 13:05:37 -04:00
#include <PreviewWindow.hpp>
#include <resource.h>
#include <windowsx.h>
LRESULT PreviewWindow::OnCreate()
{
LOGFONT lf;
2013-03-30 13:05:37 -04:00
RECT client;
GetClientRect(m_hwnd, &client);
GetMessageFont(lf);
hFont = CreateFontIndirect(&lf);
SendMessage(m_hwnd, WM_SETFONT, (WPARAM) hFont, FALSE);
2013-03-30 13:05:37 -04:00
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;
int FirstLine, LastLine;
2013-03-30 13:05:37 -04:00
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);
2013-03-30 13:05:37 -04:00
// Find painting limits.
FirstLine = max(0, yPos + ps.rcPaint.top / yChar);
LastLine = min(lines - 1, yPos + ps.rcPaint.bottom / yChar);
2013-03-30 13:05:37 -04:00
// 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);
2013-03-30 13:05:37 -04:00
rect.top = y;
rect.left = x;
DrawText(ps.hdc, lpLines[i], -1, &rect, DT_EXPANDTABS | DT_NOCLIP | DT_NOPREFIX);
2013-03-30 13:05:37 -04:00
}
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);
}
2013-03-30 13:05:37 -04:00
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);
2013-03-30 13:05:37 -04:00
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;
2013-03-30 13:05:37 -04:00
SelectFont(hdc, hOldFont);
ReleaseDC(m_hwnd, hdc);
break;
2013-03-30 13:05:37 -04:00
}
case WM_CLOSE:
ShowWindow(SW_HIDE);
2013-03-30 13:05:37 -04:00
return 0;
}
2013-09-07 20:18:50 -04:00
return Window::HandleMessage(uMsg, wParam, lParam);
2013-03-30 13:05:37 -04:00
}
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;
}