diff --git a/Console/ComBSTROut.h b/Console/ComBSTROut.h new file mode 100644 index 00000000..07ffa38f --- /dev/null +++ b/Console/ComBSTROut.h @@ -0,0 +1,81 @@ +///////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2001-2004 by Marko Bozikovic +// All rights reserved +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Send bug reports, bug fixes, enhancements, requests, flames, etc., and +// I'll try to keep a version up to date. I can be reached as follows: +// marko.bozikovic@alterbox.net +// bozho@kset.org +///////////////////////////////////////////////////////////////////////////// + +#ifndef _COMBSTROUT_H_ +#define _COMBSTROUT_H_ + +///////////////////////////////////////////////////////////////////////////// +// CComBSTROut - a class that inherits from CComBSTR and adds Out() method +// that should be used instead of & operator for 'out' +// function parameters + +class CComBSTROut : public CComBSTR +{ +public: + + CComBSTROut() + { + } + /*explicit*/ CComBSTROut(int nSize) : CComBSTR(nSize) + { + } + /*explicit*/ CComBSTROut(int nSize, LPCOLESTR sz) : CComBSTR(nSize, sz) + { + } + /*explicit*/ CComBSTROut(LPCOLESTR pSrc) : CComBSTR(pSrc) + { + } + /*explicit*/ CComBSTROut(const CComBSTROut& src) : CComBSTR(src) + { + } + /*explicit*/ CComBSTROut(REFGUID src) : CComBSTR(src) + { + } + +#ifndef OLE2ANSI + CComBSTROut(LPCSTR pSrc) : CComBSTR(pSrc) + { + } + + CComBSTROut(int nSize, LPCSTR sz) : CComBSTR(nSize, sz) + { + } +#endif + + ~CComBSTROut() + { + CComBSTR::~CComBSTR(); + } + + BSTR* Out() + { + Empty(); + return &m_str; + } +}; + +///////////////////////////////////////////////////////////////////////////// + + +#endif // _COMBSTROUT_H_ \ No newline at end of file diff --git a/Console/ComVariantOut.h b/Console/ComVariantOut.h new file mode 100644 index 00000000..085dee0b --- /dev/null +++ b/Console/ComVariantOut.h @@ -0,0 +1,109 @@ +///////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2001-2004 by Marko Bozikovic +// All rights reserved +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Send bug reports, bug fixes, enhancements, requests, flames, etc., and +// I'll try to keep a version up to date. I can be reached as follows: +// marko.bozikovic@alterbox.net +// bozho@kset.org +///////////////////////////////////////////////////////////////////////////// + +#ifndef _COMVARIANTOUT_H_ +#define _COMVARIANTOUT_H_ + +///////////////////////////////////////////////////////////////////////////// +// CComVariantOut - a class that inherits from CComVariant and adds Out() +// method that should be used instead of & operator for +// 'out' function parameters + +class CComVariantOut : public CComVariant +{ + +public: + CComVariantOut() + { + } + ~CComVariantOut() + { + CComVariant::~CComVariant(); + } + + CComVariantOut(const VARIANT& varSrc) : CComVariant(varSrc) + { + } + + CComVariantOut(const CComVariant& varSrc) : CComVariant(varSrc) + { + } + + CComVariantOut(BSTR bstrSrc) : CComVariant(bstrSrc) + { + } + CComVariantOut(LPCOLESTR lpszSrc) : CComVariant(lpszSrc) + { + } + +#ifndef OLE2ANSI + CComVariantOut(LPCSTR lpszSrc) : CComVariant(lpszSrc) + { + } +#endif + + CComVariantOut(bool bSrc) : CComVariant(bSrc) + { + } + + CComVariantOut(int nSrc) : CComVariant(nSrc) + { + } + CComVariantOut(BYTE nSrc) : CComVariant(nSrc) + { + } + CComVariantOut(short nSrc) : CComVariant(nSrc) + { + } + CComVariantOut(long nSrc, VARTYPE m_varSrc = VT_I4) : CComVariant(nSrc, m_varSrc) + { + } + CComVariantOut(float fltSrc) : CComVariant(fltSrc) + { + } + CComVariantOut(double dblSrc) : CComVariant(dblSrc) + { + } + CComVariantOut(CY cySrc) : CComVariant(cySrc) + { + } + CComVariantOut(IDispatch* pSrc) : CComVariant(pSrc) + { + } + CComVariantOut(IUnknown* pSrc) : CComVariant(pSrc) + { + } + +public: + VARIANT* Out() + { + Clear(); + return this; + } +}; + +///////////////////////////////////////////////////////////////////////////// + + +#endif // _COMVARIANTOUT_H_ \ No newline at end of file diff --git a/Console/Console.cpp b/Console/Console.cpp new file mode 100644 index 00000000..a9457cc0 --- /dev/null +++ b/Console/Console.cpp @@ -0,0 +1,4560 @@ +///////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2001-2004 by Marko Bozikovic +// All rights reserved +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Send bug reports, bug fixes, enhancements, requests, flames, etc., and +// I'll try to keep a version up to date. I can be reached as follows: +// marko.bozikovic@alterbox.net +// bozho@kset.org +///////////////////////////////////////////////////////////////////////////// + +#ifdef UNICODE +#error "Unicode defined" +#endif + +///////////////////////////////////////////////////////////////////////////// +// Console.cpp - console class implementation +#include "builddefines.h" +#undef CINTERFACE + +//#include "stdafx.h" +//#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "resource.h" +#include "FileStream.h" +//#include "ComBSTROut.h" +//#include "ComVariantOut.h" +#include "Cursors.h" +#include "Dialogs.h" +#include "Console.h" + +#ifdef _DEBUG +//#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + + +extern HINSTANCE ghInstance; + +///////////////////////////////////////////////////////////////////////////// +// Console class + + +///////////////////////////////////////////////////////////////////////////// +// Console window class names +const TCHAR Console::m_szConsoleClass[] = _T("Console Main Command Window"); +const TCHAR Console::m_szHiddenParentClass[] = _T("Console Invisible Parent Window"); + + +///////////////////////////////////////////////////////////////////////////// +// win console window title +const tstring Console::m_strWinConsoleTitle(_T("Console Command Window")); + + +///////////////////////////////////////////////////////////////////////////// +// ctor/dtor + +Console::Console(LPCTSTR pszConfigFile, LPCTSTR pszShellCmdLine, LPCTSTR pszConsoleTitle, LPCTSTR pszReloadNewConfig) +: m_hWnd(NULL) +, m_bInitializing(TRUE) +, m_bReloading(FALSE) +, m_strConfigEditor(_T("notepad.exe")) +, m_strConfigEditorParams(_T("")) +, m_strShell(_T("")) +, m_strShellCmdLine(pszShellCmdLine) +, m_hwndInvisParent(NULL) +, m_hdcConsole(NULL) +, m_hdcWindow(NULL) +, m_hbmpConsole(NULL) +, m_hbmpConsoleOld(NULL) +, m_hbmpWindow(NULL) +, m_hbmpWindowOld(NULL) +, m_hBkBrush(NULL) +, m_dwMasterRepaintInt(500) +, m_dwChangeRepaintInt(50) +, m_strIconFilename(_T("")) +, m_hSmallIcon(NULL) +, m_hBigIcon(NULL) +, m_hPopupMenu(NULL) +, m_hSysMenu(NULL) +, m_hConfigFilesMenu(NULL) +, m_bPopupMenuDisabled(FALSE) +, m_strWindowTitleDefault(_tcslen(pszConsoleTitle) == 0 ? _T("console") : pszConsoleTitle) +, m_strWindowTitle(m_strWindowTitleDefault) +, m_strWindowTitleCurrent(m_strWindowTitleDefault) +, m_strFontName(_T("Courier New")) +, m_dwFontSize(10) +, m_bBold(FALSE) +, m_bItalic(FALSE) +, m_bUseFontColor(FALSE) +, m_crFontColor(RGB(0, 0, 0)) +, m_hFont(NULL) +, m_hFontOld(NULL) +, m_nX(0) +, m_nY(0) +, m_nInsideBorder(0) +, m_nWindowWidth(0) +, m_nWindowHeight(0) +, m_nXBorderSize(5) +, m_nYBorderSize(5) +, m_nCaptionSize(0) +, m_nClientWidth(0) +, m_nClientHeight(0) +, m_nCharHeight(0) +, m_nCharWidth(0) +, m_dwWindowBorder(BORDER_REGULAR) +, m_bShowScrollbar(TRUE) +, m_nScrollbarStyle(FSB_REGULAR_MODE) +, m_crScrollbarColor(::GetSysColor(COLOR_3DHILIGHT)) +, m_nScrollbarWidth(::GetSystemMetrics(SM_CXVSCROLL)) +, m_nScrollbarButtonHeight(::GetSystemMetrics(SM_CYVSCROLL)) +, m_nScrollbarThunmbHeight(::GetSystemMetrics(SM_CYVTHUMB)) +, m_dwTaskbarButton(TASKBAR_BUTTON_NORMAL) +, m_bMouseDragable(TRUE) +, m_nSnapDst(10) +, m_dwDocked(DOCK_NONE) +, m_dwOriginalZOrder(Z_ORDER_REGULAR) +, m_dwCurrentZOrder(Z_ORDER_REGULAR) +, m_dwTransparency(TRANSPARENCY_NONE) +, m_byAlpha(150) +, m_byInactiveAlpha(150) +, m_crBackground(RGB(0, 0, 0)) +, m_crConsoleBackground(RGB(0, 0, 0)) +, m_bTintSet(FALSE) +, m_byTintOpacity(50) +, m_byTintR(0) +, m_byTintG(0) +, m_byTintB(0) +, m_bBitmapBackground(FALSE) +, m_strBackgroundFile(_T("")) +, m_hdcBackground(NULL) +, m_hbmpBackground(NULL) +, m_hbmpBackgroundOld(NULL) +, m_dwBackgroundStyle(BACKGROUND_STYLE_RESIZE) +, m_bRelativeBackground(FALSE) +, m_bExtendBackground(FALSE) +, m_nBackgroundOffsetX(0) +, m_nBackgroundOffsetY(0) +, m_bHideWindow(FALSE) +, m_bHideConsole(TRUE) +, m_dwHideConsoleTimeout(0) +, m_bStartMinimized(FALSE) +, m_dwCursorStyle(CURSOR_STYLE_CONSOLE) +, m_crCursorColor(RGB(255, 255, 255)) +, m_bCursorVisible(TRUE) +, m_pCursor(NULL) +, m_hWndConsole(NULL) +, m_hStdOut(NULL) +, m_hStdOutFresh(NULL) +, m_hQuitEvent(NULL) +, m_hConsoleProcess(NULL) +, m_hMonitorThread(NULL) +, m_dwRows(50) +, m_dwColumns(80) +, m_dwBufferRows(500) +, m_bUseTextBuffer(TRUE) +, m_nTextSelection(TEXT_SELECTION_NONE) +, m_bCopyOnSelect(FALSE) +, m_bInverseShift(FALSE) +, m_hdcSelection(NULL) +, m_hbmpSelection(NULL) +, m_hbmpSelectionOld(NULL) +, m_hbrushSelection(::CreateSolidBrush(RGB(0xff, 0xff, 0xff))) +, m_pScreenBuffer(NULL) +, m_pScreenBufferNew(NULL) +, m_nTextColor(15) +, m_nTextBgColor(0) +{ + +#if 0 + m_strConfigFile = GetFullFilename(pszConfigFile); + + if (!_tcsicmp(pszReloadNewConfig, _T("yes"))) { + m_dwReloadNewConfigDefault = RELOAD_NEW_CONFIG_YES; + } else if (!_tcsicmp(pszReloadNewConfig, _T("no"))) { + m_dwReloadNewConfigDefault = RELOAD_NEW_CONFIG_NO; + } else { + m_dwReloadNewConfigDefault = RELOAD_NEW_CONFIG_PROMPT; + } + m_dwReloadNewConfig = m_dwReloadNewConfigDefault; +#endif + + m_mouseCursorOffset.x = 0; + m_mouseCursorOffset.y = 0; + + m_coordSelOrigin.X = 0; + m_coordSelOrigin.Y = 0; + + ::ZeroMemory(&m_rectSelection, sizeof(RECT)); + +#if 0 + // get Console.exe directory + TCHAR szPathName[MAX_PATH]; + ::ZeroMemory(szPathName, sizeof(szPathName)); + ::GetModuleFileName(ghInstance, szPathName, MAX_PATH); + + tstring strExeDir(szPathName); + + strExeDir = strExeDir.substr(0, strExeDir.rfind(_T("\\"))); + strExeDir += TCHAR('\\'); + + // if no config file is given, get console.xml from the startup directory + if (m_strConfigFile.length() == 0) { + + m_strConfigFile = strExeDir + tstring(_T("console.xml")); + } + + // get readme filename + m_strReadmeFile = strExeDir + tstring(_T("Readme.txt")); +#endif + + ::ZeroMemory(&m_csbiCursor, sizeof(CONSOLE_SCREEN_BUFFER_INFO)); + ::ZeroMemory(&m_csbiConsole, sizeof(CONSOLE_SCREEN_BUFFER_INFO)); + + SetDefaultConsoleColors(); + + AllocateBuffer(); + + // Set the stdout and stderr to this window + HANDLE myOut; + ::CreatePipe( &m_hStdOut, &myOut, NULL, 0); + ::SetStdHandle( STD_OUTPUT_HANDLE, myOut); + ::SetStdHandle( STD_ERROR_HANDLE, myOut); + + int hConHandle = _open_osfhandle((long)myOut, _O_WTEXT); + FILE *fp = _fdopen( hConHandle, "w" ); + *stdout = *fp; + setvbuf( stdout, NULL, _IONBF, 0 ); + + // create text monitor thread + DWORD dwThreadID; + m_hMonitorThread = ::CreateThread(NULL, 0, Console::MonitorThreadStatic, this, CREATE_SUSPENDED, &dwThreadID); + ::ResumeThread(m_hMonitorThread); +} + +Console::~Console() { + + delete[] m_pScreenBuffer; + delete[] m_pScreenBufferNew; + + if (m_hSmallIcon) ::DestroyIcon(m_hSmallIcon); + if (m_hBigIcon) ::DestroyIcon(m_hBigIcon); + +// ::CloseHandle(m_hConsoleProcess); +// ::CloseHandle(m_hQuitEvent); + + // shutdown console process +// ::CloseHandle(m_hStdOut); +// ::CloseHandle(m_hStdOutFresh); +// if (m_hWndConsole) ::SendMessage(m_hWndConsole, WM_CLOSE, 0, 0); +// ::FreeConsole(); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Public methods + +///////////////////////////////////////////////////////////////////////////// +// creates and shows Console window + +BOOL Console::Create(TCHAR* pszConfigPath) { + + if (m_hWnd) + { + ::ShowWindow( m_hWnd, SW_SHOW); + return TRUE; + } + + if (!GetOptions()) return FALSE; + + if (!RegisterWindowClasses()) return FALSE; + + if (!CreateConsoleWindow()) return FALSE; + + // create window DC + HDC hdcDesktop = ::GetDCEx(m_hWnd, NULL, 0); + m_hdcConsole = ::CreateCompatibleDC(hdcDesktop); + m_hdcWindow = ::CreateCompatibleDC(hdcDesktop); + ::ReleaseDC(m_hWnd, hdcDesktop); + + // create selection DC + m_hdcSelection = ::CreateCompatibleDC(m_hdcWindow); + + if (!SetupMenus()) return FALSE; + + CreateNewFont(); + CreateNewBrush(); + +// SetWindowTransparency(); + SetWindowIcons(); + + GetTextSize(); + GetBordersDimensions(); + CreateCursor(); + + // now we can start the monitor thread + StartShellProcess(); + + // set the long repaint timer + if (m_dwMasterRepaintInt) ::SetTimer(m_hWnd, TIMER_REPAINT_MASTER, m_dwMasterRepaintInt, NULL); + + m_bInitializing = FALSE; + + // register for files/folders drag-n-drop + ::DragAcceptFiles(m_hWnd, TRUE); + + RefreshScreenBuffer(); + ::CopyMemory(m_pScreenBuffer, m_pScreenBufferNew, sizeof(CHAR_INFO) * m_dwRows * m_dwColumns); + RepaintWindow(); + ::UpdateWindow(m_hWnd); + + if (m_bStartMinimized) { + if (m_dwTaskbarButton > TASKBAR_BUTTON_NORMAL) { + m_bHideWindow = TRUE; + } else { + ::ShowWindow(m_hWnd, SW_MINIMIZE); + } + } else { + ::ShowWindow(m_hWnd, SW_SHOW); + } + + ::SetForegroundWindow(m_hWnd); + + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Message handlers + +///////////////////////////////////////////////////////////////////////////// + +void Console::OnDestroy() { + + if (!m_bInitializing) { + ::SetEvent(m_hQuitEvent); + ::WaitForSingleObject(m_hMonitorThread, 2000); + ::CloseHandle(m_hMonitorThread); + + // kill timers + ::KillTimer(m_hWnd, TIMER_REPAINT_CHANGE); + if (m_dwMasterRepaintInt) ::KillTimer(m_hWnd, TIMER_REPAINT_MASTER); + + DestroyCursor(); + + // cleanup graphics objects + if (m_hFontOld) ::SelectObject(m_hdcConsole, m_hFontOld); + if (m_hFont) ::DeleteObject(m_hFont); + + if (m_hBkBrush) ::DeleteObject(m_hBkBrush); + + if (m_hbmpConsoleOld) ::SelectObject(m_hdcConsole, m_hbmpConsoleOld); + if (m_hbmpConsole) ::DeleteObject(m_hbmpConsole); + + if (m_hbmpWindowOld) ::SelectObject(m_hdcWindow, m_hbmpWindowOld); + if (m_hbmpWindow) ::DeleteObject(m_hbmpWindow); + + if (m_hbmpBackgroundOld) ::SelectObject(m_hdcBackground, m_hbmpBackgroundOld); + if (m_hbmpBackground) ::DeleteObject(m_hbmpBackground); + if (m_hdcBackground) ::DeleteDC(m_hdcBackground); + + if (m_hbmpSelectionOld) ::SelectObject(m_hdcSelection, m_hbmpSelectionOld); + if (m_hbmpSelection)::DeleteObject(m_hbmpSelection); + if (m_hdcSelection) ::DeleteDC(m_hdcSelection); + + if (m_hbrushSelection) ::DeleteObject(m_hbrushSelection); + + ::DestroyMenu(m_hConfigFilesMenu); + ::DestroyMenu(m_hPopupMenu); + + SetTrayIcon(NIM_DELETE); + + ::DeleteDC(m_hdcConsole); + ::DeleteDC(m_hdcWindow); + ::PostQuitMessage(0); + } +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::OnNcDestroy() { + if (!m_bInitializing) delete this; +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::OnPaint() { + + PAINTSTRUCT paintStruct; + HDC hdc = ::BeginPaint(m_hWnd, &paintStruct); + + if (!m_nTextSelection) { + // if there's no selection, just blit console image + ::BitBlt( + hdc, + paintStruct.rcPaint.left, + paintStruct.rcPaint.top, + paintStruct.rcPaint.right - paintStruct.rcPaint.left + 1, + paintStruct.rcPaint.bottom - paintStruct.rcPaint.top + 1, + m_hdcConsole, + paintStruct.rcPaint.left, + paintStruct.rcPaint.top, + SRCCOPY); + } else { + // there's a text selection, first compose the image in an off-screen + // buffer, and then blit it + ::BitBlt( + m_hdcWindow, + paintStruct.rcPaint.left, + paintStruct.rcPaint.top, + paintStruct.rcPaint.right - paintStruct.rcPaint.left + 1, + paintStruct.rcPaint.bottom - paintStruct.rcPaint.top + 1, + m_hdcConsole, + paintStruct.rcPaint.left, + paintStruct.rcPaint.top, + SRCCOPY); + + ::BitBlt( + m_hdcWindow, + m_rectSelection.left, + m_rectSelection.top, + m_rectSelection.right - m_rectSelection.left, + m_rectSelection.bottom - m_rectSelection.top, + m_hdcSelection, + 0, + 0, + SRCINVERT); + ::BitBlt( + hdc, + paintStruct.rcPaint.left, + paintStruct.rcPaint.top, + paintStruct.rcPaint.right - paintStruct.rcPaint.left + 1, + paintStruct.rcPaint.bottom - paintStruct.rcPaint.top + 1, + m_hdcWindow, + paintStruct.rcPaint.left, + paintStruct.rcPaint.top, + SRCCOPY); + } + + ::EndPaint(m_hWnd, &paintStruct); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::OnPaintTimer() { + + ::KillTimer(m_hWnd, TIMER_REPAINT_CHANGE); + RefreshStdOut(); + RefreshScreenBuffer(); + + if (GetChangeRate() > 15) { + ::CopyMemory(m_pScreenBuffer, m_pScreenBufferNew, sizeof(CHAR_INFO) * m_dwRows * m_dwColumns); + RepaintWindow(); + } else { + RepaintWindowChanges(); + } +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::OnCursorTimer() { + if (m_pCursor) { + m_pCursor->PrepareNext(); + DrawCursor(); + } +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::OnWindowPosChanging(WINDOWPOS* lpWndPos) { + + if (!(lpWndPos->flags & SWP_NOMOVE)) { + if (m_nSnapDst >= 0) { + // we'll snap Console window to the desktop edges + RECT rectDesktop; + + GetDesktopRect(rectDesktop); + + m_dwDocked = DOCK_NONE; + DWORD dwLeftRight = 0; + DWORD dwTopBottom = 0; + + // now, see if we're close to the edges + if (lpWndPos->x <= rectDesktop.left + m_nSnapDst) { + lpWndPos->x = rectDesktop.left; + dwLeftRight = 1; + } + + if (lpWndPos->x >= rectDesktop.right - m_nWindowWidth - m_nSnapDst) { + lpWndPos->x = rectDesktop.right - m_nWindowWidth; + dwLeftRight = 2; + } + + if (lpWndPos->y <= rectDesktop.top + m_nSnapDst) { + lpWndPos->y = rectDesktop.top; + dwTopBottom = 1; + } + + if (lpWndPos->y >= rectDesktop.bottom - m_nWindowHeight - m_nSnapDst) { + lpWndPos->y = rectDesktop.bottom - m_nWindowHeight; + dwTopBottom = 2; + } + + // now, see if the window is docked + if (dwLeftRight == 1) { + // left edge + if (dwTopBottom == 1) { + // top left + m_dwDocked = DOCK_TOP_LEFT; + } else if (dwTopBottom == 2) { + // bottom left + m_dwDocked = DOCK_BOTTOM_LEFT; + } + } else if (dwLeftRight == 2) { + // right edge + if (dwTopBottom == 1) { + // top right + m_dwDocked = DOCK_TOP_RIGHT; + } else if (dwTopBottom == 2) { + // bottom right + m_dwDocked = DOCK_BOTTOM_RIGHT; + } + } + } + + m_nX = lpWndPos->x; + m_nY = lpWndPos->y; + +// TRACE(_T("Win pos: %ix%i\n"), m_nX, m_nY); + + // we need to repaint for relative backgrounds +// if (m_bRelativeBackground && !m_bInitializing) RepaintWindow(); + } + + if (m_dwCurrentZOrder == Z_ORDER_ONBOTTOM) lpWndPos->hwndInsertAfter = HWND_BOTTOM; +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::OnActivateApp(BOOL bActivate, DWORD dwFlags) { + + if (m_pCursor) { + m_pCursor->SetState(bActivate); + DrawCursor(); + } + +#if 0 + if ((m_dwTransparency == TRANSPARENCY_ALPHA) && (m_byInactiveAlpha > 0)) { + if (bActivate) { + g_pfnSetLayeredWndAttr(m_hWnd, m_crBackground, m_byAlpha, LWA_ALPHA); + } else { + g_pfnSetLayeredWndAttr(m_hWnd, m_crBackground, m_byInactiveAlpha, LWA_ALPHA); + } + + } +#endif +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::OnVScroll(WPARAM wParam) { + +// TRACE(_T("VScroll\n")); + + int nCurrentPos = ::GetScrollPos(m_hWnd, SB_VERT); + int nDelta = 0; + + switch(LOWORD (wParam)) { + + case SB_PAGEUP: + nDelta = -5; + break; + + case SB_PAGEDOWN: + nDelta = 5; + break; + + case SB_LINEUP: + nDelta = -1; + break; + + case SB_LINEDOWN: + nDelta = 1; + break; + + case SB_THUMBTRACK: + nDelta = HIWORD(wParam) - nCurrentPos; + break; + + case SB_ENDSCROLL: + + return; + + default: + return; + } + + if (nDelta = max(-nCurrentPos, min(nDelta, (int)(m_dwBufferRows-m_dwRows) - nCurrentPos))) { + + nCurrentPos += nDelta; + + SMALL_RECT sr; + sr.Top = nCurrentPos; + sr.Bottom = nDelta; + sr.Left = sr.Right = 0; + m_csbiConsole.srWindow = sr; +// ::SetConsoleWindowInfo(m_hStdOutFresh, FALSE, &sr); + + SCROLLINFO si; + si.cbSize = sizeof(si); + si.fMask = SIF_POS; + si.nPos = nCurrentPos; + ::FlatSB_SetScrollInfo(m_hWnd, SB_VERT, &si, TRUE); + + // this seems to work/look much better than direct repainting... + ::SetTimer(m_hWnd, TIMER_REPAINT_CHANGE, m_dwChangeRepaintInt, NULL); + } + +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::OnInputLangChangeRequest(WPARAM wParam, LPARAM lParam) { + ::PostMessage(m_hWndConsole, WM_INPUTLANGCHANGEREQUEST, wParam, lParam); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::OnLButtonDown(UINT uiFlags, POINTS points) { +#if 0 + RECT windowRect; + ::GetCursorPos(&m_mouseCursorOffset); + ::GetWindowRect(m_hWnd, &windowRect); + m_mouseCursorOffset.x -= windowRect.left; + m_mouseCursorOffset.y -= windowRect.top; + + if (!m_bMouseDragable || + (m_bInverseShift == !(uiFlags & MK_SHIFT))) { + + if (m_nCharWidth) { + + if (m_nTextSelection == TEXT_SELECTION_SELECTED) return; + + // fixed-width characters + // start copy text selection + ::SetCapture(m_hWnd); + + if (!m_nTextSelection) { + RECT rect; + rect.left = 0; + rect.top = 0; + rect.right = m_nClientWidth; + rect.bottom = m_nClientHeight; + ::FillRect(m_hdcSelection, &rect, m_hbrushSelection); + } + + m_nTextSelection = TEXT_SELECTION_SELECTING; + + m_coordSelOrigin.X = min(max(points.x - m_nInsideBorder, 0) / m_nCharWidth, m_dwColumns-1); + m_coordSelOrigin.Y = min(max(points.y - m_nInsideBorder, 0) / m_nCharHeight, m_dwRows-1); + + m_rectSelection.left = m_rectSelection.right = m_coordSelOrigin.X * m_nCharWidth + m_nInsideBorder; + m_rectSelection.top = m_rectSelection.bottom = m_coordSelOrigin.Y * m_nCharHeight + m_nInsideBorder; + + TRACE(_T("Starting point: %ix%i\n"), m_coordSelOrigin.X, m_coordSelOrigin.Y); + } + + } else { + if (m_nTextSelection) { + return; + } else if (m_bMouseDragable) { + // start to drag window + ::SetCapture(m_hWnd); + } + } +#endif + wcout << "Test" << endl; +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::OnLButtonUp(UINT uiFlags, POINTS points) { + + if ((m_nTextSelection == TEXT_SELECTION_SELECTED) || + // X Windows select/copy style + ((m_nTextSelection == TEXT_SELECTION_SELECTING) && (m_bCopyOnSelect))) { + + // if the user clicked inside the selection rectangle, copy data + if ((points.x >= m_rectSelection.left) && + (points.x <= m_rectSelection.right) && + (points.y >= m_rectSelection.top) && + (points.y <= m_rectSelection.bottom)) { + + CopyTextToClipboard(); + } + + if (m_bCopyOnSelect) ::ReleaseCapture(); + ClearSelection(); + + } else if (m_nTextSelection == TEXT_SELECTION_SELECTING) { + + if ((m_rectSelection.left == m_rectSelection.right) && + (m_rectSelection.top == m_rectSelection.bottom)) { + + m_nTextSelection = TEXT_SELECTION_NONE; + + } else { + m_nTextSelection = TEXT_SELECTION_SELECTED; + } + ::ReleaseCapture(); + + } else if (m_bMouseDragable) { + // end window drag + ::ReleaseCapture(); + } +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::OnLButtonDblClick(UINT uiFlags, POINTS points) { + +// ToggleWindowOnTop(); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::OnRButtonUp(UINT uiFlags, POINTS points) { + + if (uiFlags & MK_SHIFT) { + PasteClipoardText(); + } else { + + if (m_bPopupMenuDisabled) return; + + POINT point; + point.x = points.x; + point.y = points.y; + ::ClientToScreen(m_hWnd, &point); + + HMENU hPopup = ::GetSubMenu(m_hPopupMenu, 0); + + // show popup menu + ::TrackPopupMenu(hPopup, 0, point.x, point.y, 0, m_hWnd, NULL); + } +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::OnMButtonDown(UINT uiFlags, POINTS points) { + + PasteClipoardText(); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::OnMouseMove(UINT uiFlags, POINTS points) { + + RECT windowRect; + int deltaX, deltaY; + POINT point; + + if (uiFlags & MK_LBUTTON) { + + ::GetWindowRect(m_hWnd, &windowRect); + + point.x = points.x; + point.y = points.y; + + ::ClientToScreen(m_hWnd, &point); + + deltaX = point.x - windowRect.left - m_mouseCursorOffset.x; + deltaY = point.y - windowRect.top - m_mouseCursorOffset.y; + + if (deltaX | deltaY) { + +// TRACE(_T("m_nTextSelection: %i, Delta X: %i Delta Y: %i\n"), m_nTextSelection, deltaX, deltaY); + + if (m_nTextSelection) { + if ((!m_bMouseDragable) || (m_bInverseShift == !(uiFlags & MK_SHIFT))) { + + // some text has been selected, just return + if (m_nTextSelection == TEXT_SELECTION_SELECTED) return; + + // selecting text for copy/paste + COORD coordSel; + + ::InvalidateRect(m_hWnd, &m_rectSelection, FALSE); + + coordSel.X = min(max(points.x - m_nInsideBorder, 0) / m_nCharWidth, m_dwColumns-1); + coordSel.Y = min(max(points.y - m_nInsideBorder, 0) / m_nCharHeight, m_dwRows-1); + +// TRACE(_T("End point: %ix%i\n"), coordSel.X, coordSel.Y); + + if (coordSel.X >= m_coordSelOrigin.X) { + m_rectSelection.left = m_coordSelOrigin.X * m_nCharWidth + m_nInsideBorder; + m_rectSelection.right = (coordSel.X + 1) * m_nCharWidth + m_nInsideBorder; + } else { + m_rectSelection.left = coordSel.X * m_nCharWidth + m_nInsideBorder; + m_rectSelection.right = (m_coordSelOrigin.X + 1) * m_nCharWidth + m_nInsideBorder; + } + + if (coordSel.Y >= m_coordSelOrigin.Y) { + m_rectSelection.top = m_coordSelOrigin.Y * m_nCharHeight + m_nInsideBorder; + m_rectSelection.bottom = (coordSel.Y + 1) * m_nCharHeight + m_nInsideBorder; + } else { + m_rectSelection.top = coordSel.Y * m_nCharHeight + m_nInsideBorder; + m_rectSelection.bottom = (m_coordSelOrigin.Y + 1) * m_nCharHeight + m_nInsideBorder; + } + +// TRACE(_T("Selection rect: %i,%i x %i,%i\n"), m_rectSelection.left, m_rectSelection.top, m_rectSelection.right, m_rectSelection.bottom); + + ::InvalidateRect(m_hWnd, &m_rectSelection, FALSE); + } + + } else if (m_bMouseDragable) { + + // moving the window + HWND hwndZ; + switch (m_dwCurrentZOrder) { + case Z_ORDER_REGULAR : hwndZ = HWND_NOTOPMOST; break; + case Z_ORDER_ONTOP : hwndZ = HWND_TOPMOST; break; + case Z_ORDER_ONBOTTOM : hwndZ = HWND_BOTTOM; break; + } + + ::SetWindowPos( + m_hWnd, + hwndZ, + windowRect.left + deltaX, + windowRect.top + deltaY, + 0, + 0, + SWP_NOSIZE); + + ::PostMessage(m_hWnd, WM_PAINT, 0, 0); + } + } + } +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::OnChar(WORD myChar) { + wchar_t text[16]; + + if (myChar == 8) + { + if (Input.length() > 0) + { + wchar_t last = Input[ Input.length() - 1]; + + text[0] = 8; + text[1] = L' '; + text[2] = 8; + text[3] = 0; + + Input.resize( Input.length() - 1); + + if (last == '\n') + { + int cx = Input.rfind( '\n') + 1; + cx = Input.length() - cx; + SendTextToConsole( text); + m_csbiCursor.dwCursorPosition.X = cx; + + return; + } + } + else + { + return; + } + } + else if (myChar == '\r') + { + text[0] = '\n'; + text[1] = '\r'; + text[2] = 0; + Input += '\n'; + } + else + { + text[0] = myChar; + text[1] = 0; + Input += text; + } + + SendTextToConsole( text); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::OnSetCursor(WORD wHitTest, WORD wMouseMessage) { + + if (wHitTest == HTBORDER) { + if (wMouseMessage == WM_LBUTTONDOWN) { + if (m_bMouseDragable) { + // start to drag window + RECT windowRect; + ::GetCursorPos(&m_mouseCursorOffset); + ::GetWindowRect(m_hWnd, &windowRect); + m_mouseCursorOffset.x -= windowRect.left; + m_mouseCursorOffset.y -= windowRect.top; + ::SetCapture(m_hWnd); + } + } else if (wMouseMessage == WM_LBUTTONUP) { + if (m_bMouseDragable) { + // end window drag + ::ReleaseCapture(); + } + } + } +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::OnInitMenuPopup(HMENU hMenu, UINT uiPos, BOOL bSysMenu) { + + if ((hMenu != ::GetSubMenu(m_hPopupMenu, 0)) && (hMenu != m_hSysMenu)) return; + + // update configuration files submenu + UpdateConfigFilesSubmenu(); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::OnDropFiles(HDROP hDrop) { + + UINT uiFilesCount = DragQueryFile(hDrop, 0xFFFFFFFF, NULL, 0); + tstring strFilenames(_T("")); + + // concatenate all filenames + for (UINT i = 0; i < uiFilesCount; ++i) { + TCHAR szFilename[MAX_PATH]; + ::ZeroMemory(szFilename, sizeof(szFilename)); + + ::DragQueryFile(hDrop, i, szFilename, MAX_PATH); + + tstring strFilename(szFilename); + + // if there are spaces in the filename, put quotes around it + if (strFilename.find(_T(" ")) != tstring::npos) strFilename = tstring(_T("\"")) + strFilename + tstring(_T("\"")); + + if (i > 0) strFilenames += _T(" "); + strFilenames += strFilename; + + } + ::DragFinish(hDrop); + + // This function takes text, not file names +// SendTextToConsole(strFilenames.c_str()); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +BOOL Console::OnCommand(WPARAM wParam, LPARAM lParam) +{ + if (HIWORD(wParam) == 0) { + // popup menu + return HandleMenuCommand(LOWORD(wParam)); + } + + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +BOOL Console::OnSysCommand(WPARAM wParam, LPARAM lParam) { + + return HandleMenuCommand(wParam); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::OnTrayNotify(WPARAM wParam, LPARAM lParam) { + + switch (lParam) { + case WM_RBUTTONUP: { + + if (m_bPopupMenuDisabled) return; + + POINT posCursor; + + ::GetCursorPos(&posCursor); + // show popup menu + ::SetForegroundWindow(m_hWnd); + ::TrackPopupMenu(::GetSubMenu(m_hPopupMenu, 0), 0, posCursor.x, posCursor.y, 0, m_hWnd, NULL); + ::PostMessage(m_hWnd, WM_NULL, 0, 0); + + return; + } + + case WM_LBUTTONDOWN: + m_bHideWindow = false; + ShowHideWindow(); + ::SetForegroundWindow(m_hWnd); + return; + + case WM_LBUTTONDBLCLK: + m_bHideWindow = !m_bHideWindow; + ShowHideWindow(); + ::SetForegroundWindow(m_hWnd); + return; + + default : return; + } +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +#if 0 +void Console::OnWallpaperChanged(const TCHAR* pszFilename) { + + if (m_dwTransparency == TRANSPARENCY_FAKE) { + SetWindowTransparency(); + CreateBackgroundBitmap(); + RepaintWindow(); + } + +} +#endif + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +BOOL Console::GetOptions() { + +#if 0 + class XmlException { + public: XmlException(BOOL bRet) : m_bRet(bRet){}; + BOOL m_bRet; + }; + + BOOL bRet = FALSE; + + IStream* pFileStream = NULL; + IXMLDocument* pConfigDoc = NULL; + IPersistStreamInit* pPersistStream = NULL; + IXMLElement* pRootElement = NULL; + IXMLElementCollection* pColl = NULL; + IXMLElement* pFontElement = NULL; + IXMLElement* pPositionElement = NULL; + IXMLElement* pAppearanceElement = NULL; + IXMLElement* pScrollbarElement = NULL; + IXMLElement* pBackgroundElement = NULL; + IXMLElement* pCursorElement = NULL; + IXMLElement* pBehaviorElement = NULL; + + try { + ::CoInitializeEx(NULL, COINIT_APARTMENTTHREADED); + + USES_CONVERSION; + + // open file stream + if (!SUCCEEDED(CreateFileStream( + m_strConfigFile.c_str(), + GENERIC_READ, + 0, + NULL, + OPEN_EXISTING, + 0, + NULL, + &pFileStream))) { + + throw XmlException(FALSE); + } + + // create XML document instance + if (!SUCCEEDED(::CoCreateInstance( + CLSID_XMLDocument, + NULL, + CLSCTX_INPROC_SERVER, + IID_IXMLDocument, + (void**)&pConfigDoc))) { + + throw XmlException(FALSE); + } + + // load the configuration file + pConfigDoc->QueryInterface(IID_IPersistStreamInit, (void **)&pPersistStream); + + if (!SUCCEEDED(pPersistStream->Load(pFileStream))) throw XmlException(FALSE); + + // see if we're dealing with the skin + if (!SUCCEEDED(pConfigDoc->get_root(&pRootElement))) throw XmlException(FALSE); + + CComVariantOut varAttValue; + CComBSTROut bstr; + CComBSTROut strText; + tstring strTempText(_T("")); + + // root element must be CONSOLE + pRootElement->get_tagName(bstr.Out()); + bstr.ToUpper(); + + if (!(bstr == CComBSTR(_T("CONSOLE")))) throw XmlException(FALSE); + + pRootElement->getAttribute(CComBSTR(_T("title")), varAttValue.Out()); + if (varAttValue.vt == VT_BSTR) { + m_strWindowTitle = OLE2T(varAttValue.bstrVal); + m_strWindowTitleCurrent = m_strWindowTitle; + } + + pRootElement->getAttribute(CComBSTR(_T("refresh")), varAttValue.Out()); + if (varAttValue.vt == VT_BSTR) m_dwMasterRepaintInt = _ttol(OLE2T(varAttValue.bstrVal)); + + pRootElement->getAttribute(CComBSTR(_T("change_refresh")), varAttValue.Out()); + if (varAttValue.vt == VT_BSTR) m_dwChangeRepaintInt = _ttol(OLE2T(varAttValue.bstrVal)); + if ((int)m_dwChangeRepaintInt < 5) m_dwChangeRepaintInt = 5; + + pRootElement->getAttribute(CComBSTR(_T("shell")), varAttValue.Out()); + if (varAttValue.vt == VT_BSTR) m_strShell = OLE2T(varAttValue.bstrVal); + + pRootElement->getAttribute(CComBSTR(_T("editor")), varAttValue.Out()); + if (varAttValue.vt == VT_BSTR) m_strConfigEditor = OLE2T(varAttValue.bstrVal); + + pRootElement->getAttribute(CComBSTR(_T("editor_params")), varAttValue.Out()); + if (varAttValue.vt == VT_BSTR) m_strConfigEditorParams = OLE2T(varAttValue.bstrVal); + + pRootElement->get_children(&pColl); + if (!pColl) throw XmlException(TRUE); + + // get font settings + IXMLElementCollection* pFontColl = NULL; + if (!SUCCEEDED(pColl->item(CComVariant(_T("font")), CComVariant(0), (IDispatch**)&pFontElement))) throw XmlException(FALSE); + if (pFontElement) { + if (!SUCCEEDED(pFontElement->get_children(&pFontColl))) throw XmlException(FALSE); + + if (pFontColl) { + IXMLElement* pFontSubelement = NULL; + + if (!SUCCEEDED(pFontColl->item(CComVariant(_T("size")), CComVariant(0), (IDispatch**)&pFontSubelement))) throw XmlException(FALSE); + if (pFontSubelement) { + pFontSubelement->get_text(strText.Out()); + if (strText.Length() > 0) m_dwFontSize = _ttoi(OLE2T(strText)); + } + SAFERELEASE(pFontSubelement); + + if (!SUCCEEDED(pFontColl->item(CComVariant(_T("italic")), CComVariant(0), (IDispatch**)&pFontSubelement))) throw XmlException(FALSE); + if (pFontSubelement) { + pFontSubelement->get_text(strText.Out()); + m_bItalic = !_tcsicmp(OLE2T(strText), _T("true")); + } + SAFERELEASE(pFontSubelement); + + if (!SUCCEEDED(pFontColl->item(CComVariant(_T("bold")), CComVariant(0), (IDispatch**)&pFontSubelement))) throw XmlException(FALSE); + if (pFontSubelement) { + pFontSubelement->get_text(strText.Out()); + m_bBold = !_tcsicmp(OLE2T(strText), _T("true")); + } + SAFERELEASE(pFontSubelement); + + if (!SUCCEEDED(pFontColl->item(CComVariant(_T("name")), CComVariant(0), (IDispatch**)&pFontSubelement))) throw XmlException(FALSE); + if (pFontSubelement) { + pFontSubelement->get_text(strText.Out()); + if (strText.Length() > 0) m_strFontName = OLE2T(strText); + } + SAFERELEASE(pFontSubelement); + + if (!SUCCEEDED(pFontColl->item(CComVariant(_T("color")), CComVariant(0), (IDispatch**)&pFontSubelement))) throw XmlException(FALSE); + if (pFontSubelement) { + BYTE r = 0; + BYTE g = 0; + BYTE b = 0; + + varAttValue.Clear(); + pFontSubelement->getAttribute(CComBSTR(_T("r")), varAttValue.Out()); + if (varAttValue.vt == VT_BSTR) r = _ttoi(OLE2T(varAttValue.bstrVal)); + varAttValue.Clear(); + pFontSubelement->getAttribute(CComBSTR(_T("g")), varAttValue.Out()); + if (varAttValue.vt == VT_BSTR) g = _ttoi(OLE2T(varAttValue.bstrVal)); + varAttValue.Clear(); + pFontSubelement->getAttribute(CComBSTR(_T("b")), varAttValue.Out()); + if (varAttValue.vt == VT_BSTR) b = _ttoi(OLE2T(varAttValue.bstrVal)); + + m_bUseFontColor = TRUE; + m_crFontColor = RGB(r, g, b); + } + SAFERELEASE(pFontSubelement); + + // get font color mapping + if (!SUCCEEDED(pFontColl->item(CComVariant(_T("colors")), CComVariant(0), (IDispatch**)&pFontSubelement))) throw XmlException(FALSE); + if (pFontSubelement) { + + IXMLElementCollection* pColorsColl = NULL; + + if (!SUCCEEDED(pFontSubelement->get_children(&pColorsColl))) throw XmlException(FALSE); + + if (pColorsColl) { + + for (int i = 0; i < 16; ++i) { + IXMLElement* pColorSubelement = NULL; + TCHAR szColorName[32]; + + _sntprintf(szColorName, sizeof(szColorName)/sizeof(TCHAR), _T("color_%02i"), i); + + if (!SUCCEEDED(pColorsColl->item(CComVariant(szColorName), CComVariant(0), (IDispatch**)&pColorSubelement))) throw XmlException(FALSE); + if (pColorSubelement) { + + BYTE r = 0; + BYTE g = 0; + BYTE b = 0; + + varAttValue.Clear(); + pColorSubelement->getAttribute(CComBSTR(_T("r")), varAttValue.Out()); + if (varAttValue.vt == VT_BSTR) r = _ttoi(OLE2T(varAttValue.bstrVal)); + varAttValue.Clear(); + pColorSubelement->getAttribute(CComBSTR(_T("g")), varAttValue.Out()); + if (varAttValue.vt == VT_BSTR) g = _ttoi(OLE2T(varAttValue.bstrVal)); + varAttValue.Clear(); + pColorSubelement->getAttribute(CComBSTR(_T("b")), varAttValue.Out()); + if (varAttValue.vt == VT_BSTR) b = _ttoi(OLE2T(varAttValue.bstrVal)); + + Console::m_arrConsoleColors[i] = RGB(r, g, b); + } + + SAFERELEASE(pColorSubelement); + } + } + SAFERELEASE(pColorsColl); + } + SAFERELEASE(pFontSubelement); + } + SAFERELEASE(pFontColl); + } + + // get position settings + IXMLElementCollection* pPositionColl = NULL; + if (!SUCCEEDED(pColl->item(CComVariant(_T("position")), CComVariant(0), (IDispatch**)&pPositionElement))) throw XmlException(FALSE); + if (pPositionElement) { + if (!SUCCEEDED(pPositionElement->get_children(&pPositionColl))) throw XmlException(FALSE); + + if (pPositionColl) { + IXMLElement* pPositionSubelement = NULL; + + if (!m_bReloading) { + if (!SUCCEEDED(pPositionColl->item(CComVariant(_T("x")), CComVariant(0), (IDispatch**)&pPositionSubelement))) throw XmlException(FALSE); + if (pPositionSubelement) { + pPositionSubelement->get_text(strText.Out()); + if (strText.Length() > 0) m_nX = _ttoi(OLE2T(strText)); + } + SAFERELEASE(pPositionSubelement); + + if (!SUCCEEDED(pPositionColl->item(CComVariant(_T("y")), CComVariant(0), (IDispatch**)&pPositionSubelement))) throw XmlException(FALSE); + if (pPositionSubelement) { + pPositionSubelement->get_text(strText.Out()); + if (strText.Length() > 0) m_nY = _ttoi(OLE2T(strText)); + } + SAFERELEASE(pPositionSubelement); + } + + if (!SUCCEEDED(pPositionColl->item(CComVariant(_T("docked")), CComVariant(0), (IDispatch**)&pPositionSubelement))) throw XmlException(FALSE); + if (pPositionSubelement) { + pPositionSubelement->get_text(strText.Out()); + strTempText = OLE2T(strText); + + if (!_tcsicmp(strTempText.c_str(), _T("top left"))) { + m_dwDocked = DOCK_TOP_LEFT; + } else if (!_tcsicmp(strTempText.c_str(), _T("top right"))) { + m_dwDocked = DOCK_TOP_RIGHT; + } else if (!_tcsicmp(strTempText.c_str(), _T("bottom right"))) { + m_dwDocked = DOCK_BOTTOM_RIGHT; + } else if (!_tcsicmp(strTempText.c_str(), _T("bottom left"))) { + m_dwDocked = DOCK_BOTTOM_LEFT; + } else { + m_dwDocked = DOCK_NONE; + } + } + SAFERELEASE(pPositionSubelement); + + if (!SUCCEEDED(pPositionColl->item(CComVariant(_T("snap_distance")), CComVariant(0), (IDispatch**)&pPositionSubelement))) throw XmlException(FALSE); + if (pPositionSubelement) { + pPositionSubelement->get_text(strText.Out()); + if (strText.Length() > 0) m_nSnapDst = _ttoi(OLE2T(strText)); + } + SAFERELEASE(pPositionSubelement); + + if (!SUCCEEDED(pPositionColl->item(CComVariant(_T("z_order")), CComVariant(0), (IDispatch**)&pPositionSubelement))) throw XmlException(FALSE); + if (pPositionSubelement) { + pPositionSubelement->get_text(strText.Out()); + strTempText = OLE2T(strText); + + if (!_tcsicmp(strTempText.c_str(), _T("regular"))) { + m_dwCurrentZOrder = Z_ORDER_REGULAR; + m_dwOriginalZOrder = Z_ORDER_REGULAR; + } else if (!_tcsicmp(strTempText.c_str(), _T("on top"))) { + m_dwCurrentZOrder = Z_ORDER_ONTOP; + m_dwOriginalZOrder = Z_ORDER_ONTOP; + } else if (!_tcsicmp(strTempText.c_str(), _T("on bottom"))) { + m_dwCurrentZOrder = Z_ORDER_ONBOTTOM; + m_dwOriginalZOrder = Z_ORDER_ONBOTTOM; + } else { + m_dwCurrentZOrder = Z_ORDER_REGULAR; + m_dwOriginalZOrder = Z_ORDER_REGULAR; + } + } + SAFERELEASE(pPositionSubelement); + } + + SAFERELEASE(pPositionColl); + } + + // get appearance settings + IXMLElementCollection* pAppearanceColl = NULL; + if (!SUCCEEDED(pColl->item(CComVariant(_T("appearance")), CComVariant(0), (IDispatch**)&pAppearanceElement))) throw XmlException(FALSE); + if (pAppearanceElement) { + if (!SUCCEEDED(pAppearanceElement->get_children(&pAppearanceColl))) throw XmlException(FALSE); + + if (pAppearanceColl) { + IXMLElement* pAppearanaceSubelement = NULL; + + if (!SUCCEEDED(pAppearanceColl->item(CComVariant(_T("hide_console")), CComVariant(0), (IDispatch**)&pAppearanaceSubelement))) throw XmlException(FALSE); + if (pAppearanaceSubelement) { + pAppearanaceSubelement->get_text(strText.Out()); + if (!_tcsicmp(OLE2T(strText), _T("true"))) { + m_bHideConsole = TRUE; + } else { + m_bHideConsole = FALSE; + } + } + SAFERELEASE(pAppearanaceSubelement); + + if (!SUCCEEDED(pAppearanceColl->item(CComVariant(_T("hide_console_timeout")), CComVariant(0), (IDispatch**)&pAppearanaceSubelement))) throw XmlException(FALSE); + if (pAppearanaceSubelement) { + pAppearanaceSubelement->get_text(strText.Out()); + if (strText.Length() > 0) m_dwHideConsoleTimeout = _ttoi(OLE2T(strText)); + } + SAFERELEASE(pAppearanaceSubelement); + + if (!SUCCEEDED(pAppearanceColl->item(CComVariant(_T("start_minimized")), CComVariant(0), (IDispatch**)&pAppearanaceSubelement))) throw XmlException(FALSE); + if (pAppearanaceSubelement) { + pAppearanaceSubelement->get_text(strText.Out()); + if (!_tcsicmp(OLE2T(strText), _T("true"))) { + m_bStartMinimized = TRUE; + } else { + m_bStartMinimized = FALSE; + } + } + SAFERELEASE(pAppearanaceSubelement); + + IXMLElementCollection* pScrollbarColl = NULL; + if (!SUCCEEDED(pAppearanceColl->item(CComVariant(_T("scrollbar")), CComVariant(0), (IDispatch**)&pScrollbarElement))) throw XmlException(FALSE); + if (pScrollbarElement) { + if (!SUCCEEDED(pScrollbarElement->get_children(&pScrollbarColl))) throw XmlException(FALSE); + + if (pScrollbarColl) { + IXMLElement* pScrollbarSubelement = NULL; + + if (!SUCCEEDED(pScrollbarColl->item(CComVariant(_T("color")), CComVariant(0), (IDispatch**)&pScrollbarSubelement))) throw XmlException(FALSE); + if (pScrollbarSubelement) { + BYTE r = 0; + BYTE g = 0; + BYTE b = 0; + + pScrollbarSubelement->getAttribute(CComBSTR(_T("r")), varAttValue.Out()); + if (varAttValue.vt == VT_BSTR) r = _ttoi(OLE2T(varAttValue.bstrVal)); + pScrollbarSubelement->getAttribute(CComBSTR(_T("g")), varAttValue.Out()); + if (varAttValue.vt == VT_BSTR) g = _ttoi(OLE2T(varAttValue.bstrVal)); + pScrollbarSubelement->getAttribute(CComBSTR(_T("b")), varAttValue.Out()); + if (varAttValue.vt == VT_BSTR) b = _ttoi(OLE2T(varAttValue.bstrVal)); + + m_crScrollbarColor = RGB(r, g, b); + } + SAFERELEASE(pScrollbarSubelement); + + if (!SUCCEEDED(pScrollbarColl->item(CComVariant(_T("style")), CComVariant(0), (IDispatch**)&pScrollbarSubelement))) throw XmlException(FALSE); + if (pScrollbarSubelement) { + pScrollbarSubelement->get_text(strText.Out()); + strTempText = OLE2T(strText); + + if (!_tcsicmp(strTempText.c_str(), _T("regular"))) { + m_nScrollbarStyle = FSB_REGULAR_MODE; + } else if (!_tcsicmp(strTempText.c_str(), _T("flat"))) { + m_nScrollbarStyle = FSB_FLAT_MODE; + } else if (!_tcsicmp(strTempText.c_str(), _T("encarta"))) { + m_nScrollbarStyle = FSB_ENCARTA_MODE; + } + } + SAFERELEASE(pScrollbarSubelement); + + + if (!SUCCEEDED(pScrollbarColl->item(CComVariant(_T("width")), CComVariant(0), (IDispatch**)&pScrollbarSubelement))) throw XmlException(FALSE); + if (pScrollbarSubelement) { + pScrollbarSubelement->get_text(strText.Out()); + if (strText.Length() > 0) m_nScrollbarWidth = _ttoi(OLE2T(strText)); + } + SAFERELEASE(pScrollbarSubelement); + + if (!SUCCEEDED(pScrollbarColl->item(CComVariant(_T("button_height")), CComVariant(0), (IDispatch**)&pScrollbarSubelement))) throw XmlException(FALSE); + if (pScrollbarSubelement) { + pScrollbarSubelement->get_text(strText.Out()); + if (strText.Length() > 0) m_nScrollbarButtonHeight = _ttoi(OLE2T(strText)); + } + SAFERELEASE(pScrollbarSubelement); + + if (!SUCCEEDED(pScrollbarColl->item(CComVariant(_T("thumb_height")), CComVariant(0), (IDispatch**)&pScrollbarSubelement))) throw XmlException(FALSE); + if (pScrollbarSubelement) { + pScrollbarSubelement->get_text(strText.Out()); + if (strText.Length() > 0) m_nScrollbarThunmbHeight = _ttoi(OLE2T(strText)); + } + SAFERELEASE(pScrollbarSubelement); + } + SAFERELEASE(pScrollbarColl); + } + + if (!SUCCEEDED(pAppearanceColl->item(CComVariant(_T("border")), CComVariant(0), (IDispatch**)&pAppearanaceSubelement))) throw XmlException(FALSE); + if (pAppearanaceSubelement) { + pAppearanaceSubelement->get_text(strText.Out()); + if (!_tcsicmp(OLE2T(strText), _T("true")) || !_tcsicmp(OLE2T(strText), _T("regular"))) { + m_dwWindowBorder = BORDER_REGULAR; + } else if (!_tcsicmp(OLE2T(strText), _T("thin"))) { + m_dwWindowBorder = BORDER_THIN; + } else { + m_dwWindowBorder = BORDER_NONE; + } + } + SAFERELEASE(pAppearanaceSubelement); + + if (!SUCCEEDED(pAppearanceColl->item(CComVariant(_T("inside_border")), CComVariant(0), (IDispatch**)&pAppearanaceSubelement))) throw XmlException(FALSE); + if (pAppearanaceSubelement) { + pAppearanaceSubelement->get_text(strText.Out()); + if (strText.Length() > 0) m_nInsideBorder = _ttoi(OLE2T(strText)); + } + SAFERELEASE(pAppearanaceSubelement); + + if (!SUCCEEDED(pAppearanceColl->item(CComVariant(_T("taskbar_button")), CComVariant(0), (IDispatch**)&pAppearanaceSubelement))) throw XmlException(FALSE); + if (pAppearanaceSubelement) { + pAppearanaceSubelement->get_text(strText.Out()); + if (!_tcsicmp(OLE2T(strText), _T("hide"))) { + m_dwTaskbarButton = TASKBAR_BUTTON_HIDE; + } else if (!_tcsicmp(OLE2T(strText), _T("tray"))) { + m_dwTaskbarButton = TASKBAR_BUTTON_TRAY; + } else { + m_dwTaskbarButton = TASKBAR_BUTTON_NORMAL; + } + } + SAFERELEASE(pAppearanaceSubelement); + + if (!SUCCEEDED(pAppearanceColl->item(CComVariant(_T("size")), CComVariant(0), (IDispatch**)&pAppearanaceSubelement))) throw XmlException(FALSE); + if (pAppearanaceSubelement) { + + pAppearanaceSubelement->getAttribute(CComBSTR(_T("rows")), varAttValue.Out()); + if (varAttValue.vt == VT_BSTR) { + if (_tcsicmp(OLE2T(varAttValue.bstrVal), _T("max")) == 0) { + m_dwRows = 0; + } else { + m_dwRows = _ttoi(OLE2T(varAttValue.bstrVal)); + } + } + + pAppearanaceSubelement->getAttribute(CComBSTR(_T("columns")), varAttValue.Out()); + if (varAttValue.vt == VT_BSTR) { + if (_tcsicmp(OLE2T(varAttValue.bstrVal), _T("max")) == 0) { + m_dwColumns = 0; + } else { + m_dwColumns = _ttoi(OLE2T(varAttValue.bstrVal)); + } + } + + pAppearanaceSubelement->getAttribute(CComBSTR(_T("buffer_rows")), varAttValue.Out()); + if (varAttValue.vt == VT_BSTR) { + m_dwBufferRows = _ttoi(OLE2T(varAttValue.bstrVal)); + m_bUseTextBuffer = TRUE; + } else { + m_dwBufferRows = m_dwRows; + } + } + SAFERELEASE(pAppearanaceSubelement); + + if (!SUCCEEDED(pAppearanceColl->item(CComVariant(_T("transparency")), CComVariant(0), (IDispatch**)&pAppearanaceSubelement))) throw XmlException(FALSE); + if (pAppearanaceSubelement) { + pAppearanaceSubelement->getAttribute(CComBSTR(_T("alpha")), varAttValue.Out()); + if (varAttValue.vt == VT_BSTR) m_byAlpha = (BYTE)_ttoi(OLE2T(varAttValue.bstrVal)); + pAppearanaceSubelement->getAttribute(CComBSTR(_T("inactive_alpha")), varAttValue.Out()); + if (varAttValue.vt == VT_BSTR) m_byInactiveAlpha = (BYTE)_ttoi(OLE2T(varAttValue.bstrVal)); + + pAppearanaceSubelement->get_text(strText.Out()); + strTempText = OLE2T(strText); + + if (!_tcsicmp(strTempText.c_str(), _T("none"))) { + m_dwTransparency = TRANSPARENCY_NONE; + } else if (!_tcsicmp(strTempText.c_str(), _T("alpha"))) { + m_dwTransparency = TRANSPARENCY_ALPHA; + } else if (!_tcsicmp(strTempText.c_str(), _T("color key"))) { + m_dwTransparency = TRANSPARENCY_COLORKEY; + } else if (!_tcsicmp(strTempText.c_str(), _T("fake"))) { + m_dwTransparency = TRANSPARENCY_FAKE; + } + + } + SAFERELEASE(pAppearanaceSubelement); + + // get background settings + IXMLElementCollection* pBackgroundColl = NULL; + if (!SUCCEEDED(pAppearanceColl->item(CComVariant(_T("background")), CComVariant(0), (IDispatch**)&pBackgroundElement))) throw XmlException(FALSE); + if (pBackgroundElement) { + if (!SUCCEEDED(pBackgroundElement->get_children(&pBackgroundColl))) throw XmlException(FALSE); + + if (pBackgroundColl) { + IXMLElement* pBackgroundSubelement = NULL; + + if (!SUCCEEDED(pBackgroundColl->item(CComVariant(_T("color")), CComVariant(0), (IDispatch**)&pBackgroundSubelement))) throw XmlException(FALSE); + if (pBackgroundSubelement) { + BYTE r = 0; + BYTE g = 0; + BYTE b = 0; + + pBackgroundSubelement->getAttribute(CComBSTR(_T("r")), varAttValue.Out()); + if (varAttValue.vt == VT_BSTR) r = _ttoi(OLE2T(varAttValue.bstrVal)); + pBackgroundSubelement->getAttribute(CComBSTR(_T("g")), varAttValue.Out()); + if (varAttValue.vt == VT_BSTR) g = _ttoi(OLE2T(varAttValue.bstrVal)); + pBackgroundSubelement->getAttribute(CComBSTR(_T("b")), varAttValue.Out()); + if (varAttValue.vt == VT_BSTR) b = _ttoi(OLE2T(varAttValue.bstrVal)); + + m_crBackground = RGB(r, g, b); + } + SAFERELEASE(pBackgroundSubelement); + + if (!SUCCEEDED(pBackgroundColl->item(CComVariant(_T("console_color")), CComVariant(0), (IDispatch**)&pBackgroundSubelement))) throw XmlException(FALSE); + if (pBackgroundSubelement) { + BYTE r = 0; + BYTE g = 0; + BYTE b = 0; + + pBackgroundSubelement->getAttribute(CComBSTR(_T("r")), varAttValue.Out()); + if (varAttValue.vt == VT_BSTR) r = _ttoi(OLE2T(varAttValue.bstrVal)); + pBackgroundSubelement->getAttribute(CComBSTR(_T("g")), varAttValue.Out()); + if (varAttValue.vt == VT_BSTR) g = _ttoi(OLE2T(varAttValue.bstrVal)); + pBackgroundSubelement->getAttribute(CComBSTR(_T("b")), varAttValue.Out()); + if (varAttValue.vt == VT_BSTR) b = _ttoi(OLE2T(varAttValue.bstrVal)); + + m_crConsoleBackground = RGB(r, g, b); + } + SAFERELEASE(pBackgroundSubelement); + + if (!SUCCEEDED(pBackgroundColl->item(CComVariant(_T("tint")), CComVariant(0), (IDispatch**)&pBackgroundSubelement))) throw XmlException(FALSE); + if (pBackgroundSubelement) { + BYTE r = 0; + BYTE g = 0; + BYTE b = 0; + + pBackgroundSubelement->getAttribute(CComBSTR(_T("r")), varAttValue.Out()); + if (varAttValue.vt == VT_BSTR) m_byTintR = _ttoi(OLE2T(varAttValue.bstrVal)); + pBackgroundSubelement->getAttribute(CComBSTR(_T("g")), varAttValue.Out()); + if (varAttValue.vt == VT_BSTR) m_byTintG = _ttoi(OLE2T(varAttValue.bstrVal)); + pBackgroundSubelement->getAttribute(CComBSTR(_T("b")), varAttValue.Out()); + if (varAttValue.vt == VT_BSTR) m_byTintB = _ttoi(OLE2T(varAttValue.bstrVal)); + pBackgroundSubelement->getAttribute(CComBSTR(_T("opacity")), varAttValue.Out()); + if (varAttValue.vt == VT_BSTR) m_byTintOpacity = _ttoi(OLE2T(varAttValue.bstrVal)); + + if (m_byTintOpacity > 100) m_byTintOpacity = 50; + m_bTintSet = TRUE; + } + SAFERELEASE(pBackgroundSubelement); + + if (!SUCCEEDED(pBackgroundColl->item(CComVariant(_T("image")), CComVariant(0), (IDispatch**)&pBackgroundSubelement))) throw XmlException(FALSE); + if (pBackgroundSubelement) { + + pBackgroundSubelement->getAttribute(CComBSTR(_T("style")), varAttValue.Out()); + if (varAttValue.vt == VT_BSTR) { + if (!_tcsicmp(OLE2T(varAttValue.bstrVal), _T("resize"))) { + m_dwBackgroundStyle = BACKGROUND_STYLE_RESIZE; + } else if (!_tcsicmp(OLE2T(varAttValue.bstrVal), _T("center"))) { + m_dwBackgroundStyle = BACKGROUND_STYLE_CENTER; + } else if (!_tcsicmp(OLE2T(varAttValue.bstrVal), _T("tile"))) { + m_dwBackgroundStyle = BACKGROUND_STYLE_TILE; + } + } + + pBackgroundSubelement->getAttribute(CComBSTR(_T("relative")), varAttValue.Out()); + if (varAttValue.vt == VT_BSTR) { + if (!_tcsicmp(OLE2T(varAttValue.bstrVal), _T("true"))) { + m_bRelativeBackground = TRUE; + } else { + m_bRelativeBackground = FALSE; + } + } + + pBackgroundSubelement->getAttribute(CComBSTR(_T("extend")), varAttValue.Out()); + if (varAttValue.vt == VT_BSTR) { + if (!_tcsicmp(OLE2T(varAttValue.bstrVal), _T("true"))) { + m_bExtendBackground = TRUE; + } else { + m_bExtendBackground = FALSE; + } + } + + pBackgroundSubelement->get_text(strText.Out()); + m_strBackgroundFile = OLE2T(strText); + m_bBitmapBackground = TRUE; + } + SAFERELEASE(pBackgroundSubelement); + } + SAFERELEASE(pBackgroundColl); + } + + IXMLElementCollection* pCursorColl = NULL; + if (!SUCCEEDED(pAppearanceColl->item(CComVariant(_T("cursor")), CComVariant(0), (IDispatch**)&pCursorElement))) throw XmlException(FALSE); + if (pCursorElement) { + if (!SUCCEEDED(pCursorElement->get_children(&pCursorColl))) throw XmlException(FALSE); + + if (pCursorColl) { + IXMLElement* pCursorSubelement = NULL; + + if (!SUCCEEDED(pCursorColl->item(CComVariant(_T("color")), CComVariant(0), (IDispatch**)&pCursorSubelement))) throw XmlException(FALSE); + if (pCursorSubelement) { + BYTE r = 0; + BYTE g = 0; + BYTE b = 0; + + pCursorSubelement->getAttribute(CComBSTR(_T("r")), varAttValue.Out()); + if (varAttValue.vt == VT_BSTR) r = _ttoi(OLE2T(varAttValue.bstrVal)); + pCursorSubelement->getAttribute(CComBSTR(_T("g")), varAttValue.Out()); + if (varAttValue.vt == VT_BSTR) g = _ttoi(OLE2T(varAttValue.bstrVal)); + pCursorSubelement->getAttribute(CComBSTR(_T("b")), varAttValue.Out()); + if (varAttValue.vt == VT_BSTR) b = _ttoi(OLE2T(varAttValue.bstrVal)); + + m_crCursorColor = RGB(r, g, b); + } + SAFERELEASE(pCursorSubelement); + + if (!SUCCEEDED(pCursorColl->item(CComVariant(_T("style")), CComVariant(0), (IDispatch**)&pCursorSubelement))) throw XmlException(FALSE); + if (pCursorSubelement) { + pCursorSubelement->get_text(strText.Out()); + strTempText = OLE2T(strText); + + if (!_tcsicmp(strTempText.c_str(), _T("none"))) { + m_dwCursorStyle = CURSOR_STYLE_NONE; + } else if (!_tcsicmp(strTempText.c_str(), _T("XTerm"))) { + m_dwCursorStyle = CURSOR_STYLE_XTERM; + } else if (!_tcsicmp(strTempText.c_str(), _T("block"))) { + m_dwCursorStyle = CURSOR_STYLE_BLOCK; + } else if (!_tcsicmp(strTempText.c_str(), _T("noblink block"))) { + m_dwCursorStyle = CURSOR_STYLE_NBBLOCK; + } else if (!_tcsicmp(strTempText.c_str(), _T("pulse block"))) { + m_dwCursorStyle = CURSOR_STYLE_PULSEBLOCK; + } else if (!_tcsicmp(strTempText.c_str(), _T("bar"))) { + m_dwCursorStyle = CURSOR_STYLE_BAR; + } else if (!_tcsicmp(strTempText.c_str(), _T("console"))) { + m_dwCursorStyle = CURSOR_STYLE_CONSOLE; + } else if (!_tcsicmp(strTempText.c_str(), _T("noblink line"))) { + m_dwCursorStyle = CURSOR_STYLE_NBHLINE; + } else if (!_tcsicmp(strTempText.c_str(), _T("horizontal line"))) { + m_dwCursorStyle = CURSOR_STYLE_HLINE; + } else if (!_tcsicmp(strTempText.c_str(), _T("vertical line"))) { + m_dwCursorStyle = CURSOR_STYLE_VLINE; + } else if (!_tcsicmp(strTempText.c_str(), _T("rect"))) { + m_dwCursorStyle = CURSOR_STYLE_RECT; + } else if (!_tcsicmp(strTempText.c_str(), _T("noblink rect"))) { + m_dwCursorStyle = CURSOR_STYLE_NBRECT; + } else if (!_tcsicmp(strTempText.c_str(), _T("pulse rect"))) { + m_dwCursorStyle = CURSOR_STYLE_PULSERECT; + } else if (!_tcsicmp(strTempText.c_str(), _T("fading block"))) { + m_dwCursorStyle = CURSOR_STYLE_FADEBLOCK; + } + } + SAFERELEASE(pCursorSubelement); + } + SAFERELEASE(pCursorColl); + } + + if (!SUCCEEDED(pAppearanceColl->item(CComVariant(_T("icon")), CComVariant(0), (IDispatch**)&pAppearanaceSubelement))) throw XmlException(FALSE); + if (pAppearanaceSubelement) { + pAppearanaceSubelement->get_text(strText.Out()); + if (strText.Length() > 0) m_strIconFilename = OLE2T(strText); + } + SAFERELEASE(pAppearanaceSubelement); + + } + SAFERELEASE(pAppearanceColl); + } + + // get behaviour settings + IXMLElementCollection* pBehaviorColl = NULL; + if (!SUCCEEDED(pColl->item(CComVariant(_T("behaviour")), CComVariant(0), (IDispatch**)&pBehaviorElement))) { + if (!SUCCEEDED(pColl->item(CComVariant(_T("behavior")), CComVariant(0), (IDispatch**)&pBehaviorElement))) throw XmlException(FALSE); + } + + if (pBehaviorElement) { + if (!SUCCEEDED(pBehaviorElement->get_children(&pBehaviorColl))) throw XmlException(FALSE); + + if (pBehaviorColl) { + IXMLElement* pBehaviourSubelement = NULL; + + if (!SUCCEEDED(pBehaviorColl->item(CComVariant(_T("mouse_drag")), CComVariant(0), (IDispatch**)&pBehaviourSubelement))) throw XmlException(FALSE); + if (pBehaviourSubelement) { + pBehaviourSubelement->get_text(strText.Out()); + if (!_tcsicmp(OLE2T(strText), _T("true"))) { + m_bMouseDragable = TRUE; + } else { + m_bMouseDragable = FALSE; + } + } + SAFERELEASE(pBehaviourSubelement); + + if (!SUCCEEDED(pBehaviorColl->item(CComVariant(_T("copy_on_select")), CComVariant(0), (IDispatch**)&pBehaviourSubelement))) throw XmlException(FALSE); + if (pBehaviourSubelement) { + pBehaviourSubelement->get_text(strText.Out()); + if (!_tcsicmp(OLE2T(strText), _T("true"))) { + m_bCopyOnSelect = TRUE; + } else { + m_bCopyOnSelect = FALSE; + } + } + SAFERELEASE(pBehaviourSubelement); + + if (!SUCCEEDED(pBehaviorColl->item(CComVariant(_T("inverse_shift")), CComVariant(0), (IDispatch**)&pBehaviourSubelement))) throw XmlException(FALSE); + if (pBehaviourSubelement) { + pBehaviourSubelement->get_text(strText.Out()); + if (!_tcsicmp(OLE2T(strText), _T("true"))) { + m_bInverseShift = TRUE; + } else { + m_bInverseShift = FALSE; + } + } + SAFERELEASE(pBehaviourSubelement); + + if (!SUCCEEDED(pBehaviorColl->item(CComVariant(_T("reload_new_config")), CComVariant(0), (IDispatch**)&pBehaviourSubelement))) throw XmlException(FALSE); + if (pBehaviourSubelement) { + pBehaviourSubelement->get_text(strText.Out()); + if (!_tcsicmp(OLE2T(strText), _T("yes"))) { + m_dwReloadNewConfig = RELOAD_NEW_CONFIG_YES; + } else if (!_tcsicmp(OLE2T(strText), _T("no"))) { + m_dwReloadNewConfig = RELOAD_NEW_CONFIG_NO; + } else { + m_dwReloadNewConfig = RELOAD_NEW_CONFIG_PROMPT; + } + } + SAFERELEASE(pBehaviourSubelement); + + if (!SUCCEEDED(pBehaviorColl->item(CComVariant(_T("disable_menu")), CComVariant(0), (IDispatch**)&pBehaviourSubelement))) throw XmlException(FALSE); + if (pBehaviourSubelement) { + pBehaviourSubelement->get_text(strText.Out()); + if (!_tcsicmp(OLE2T(strText), _T("true"))) { + m_bPopupMenuDisabled = TRUE; + } else { + m_bPopupMenuDisabled = FALSE; + } + } + SAFERELEASE(pBehaviourSubelement); + + } + SAFERELEASE(pBehaviorColl); + } + + bRet = TRUE; + + } catch (const XmlException& e) { + bRet = e.m_bRet; + } + + SAFERELEASE(pBehaviorElement); + SAFERELEASE(pCursorElement); + SAFERELEASE(pBackgroundElement); + SAFERELEASE(pScrollbarElement); + SAFERELEASE(pAppearanceElement); + SAFERELEASE(pPositionElement); + SAFERELEASE(pFontElement); + SAFERELEASE(pColl); + SAFERELEASE(pRootElement); + SAFERELEASE(pPersistStream); + SAFERELEASE(pConfigDoc); + SAFERELEASE(pFileStream); + + ::CoUninitialize(); + return bRet; +#endif + return 1; +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +BOOL Console::RegisterWindowClasses() { + WNDCLASSEX wcx; + + // register the Console window class + ::ZeroMemory(&wcx, sizeof(WNDCLASSEX)); + wcx.cbSize = sizeof(wcx); + wcx.style = CS_HREDRAW | CS_VREDRAW | CS_OWNDC | CS_DBLCLKS; + wcx.lpfnWndProc = Console::WindowProc; + wcx.cbClsExtra = 0; + wcx.cbWndExtra = sizeof(void*); + wcx.hInstance = ghInstance; + wcx.hIcon = ::LoadIcon(ghInstance, MAKEINTRESOURCE(IDI_ICON2)); + wcx.hCursor = ::LoadCursor(NULL, IDC_ARROW); + wcx.hbrBackground = ::CreateSolidBrush(RGB(0, 0, 0)); + wcx.lpszMenuName = NULL; + wcx.lpszClassName = Console::m_szConsoleClass; + wcx.hIconSm = NULL; + + if ((::RegisterClassEx(&wcx) == 0) && (::GetLastError() != ERROR_CLASS_ALREADY_EXISTS)) return FALSE; + + // register the hidden parent window class + ::ZeroMemory(&wcx, sizeof(WNDCLASSEX)); + wcx.cbSize = sizeof(wcx); + wcx.style = 0; + wcx.lpfnWndProc = ::DefWindowProc; + wcx.cbClsExtra = 0; + wcx.cbWndExtra = 0; + wcx.hInstance = ghInstance; + wcx.hIcon = NULL; + wcx.hCursor = ::LoadCursor(NULL, IDC_ARROW); + wcx.hbrBackground = NULL; + wcx.lpszMenuName = NULL; + wcx.lpszClassName = Console::m_szHiddenParentClass; + wcx.hIconSm = NULL; + + if ((::RegisterClassEx(&wcx) == 0) && (::GetLastError() != ERROR_CLASS_ALREADY_EXISTS)) return FALSE; + + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +BOOL Console::SetupMenus() { + + MENUITEMINFO mii; + + // setup popup menu + if ((m_hPopupMenu = ::LoadMenu(ghInstance, MAKEINTRESOURCE(IDR_POPUP_MENU))) == NULL) return FALSE; + if ((m_hConfigFilesMenu = ::CreateMenu()) == NULL) return FALSE; + + // add stuff to the system menu + TCHAR* arrMenuItems[] = {_T("&Copy"), _T("&Paste")}; + DWORD arrMenuTypes[] = {MFT_STRING, MFT_STRING}; + DWORD arrMenuIDs[] = { ID_COPY, ID_PASTE}; + + m_hSysMenu = ::GetSystemMenu(m_hWnd, FALSE); + + for (int i = 0; i < sizeof(arrMenuIDs)/sizeof(arrMenuIDs[0]); ++i) { + ::ZeroMemory(&mii, sizeof(MENUITEMINFO)); + mii.cbSize = sizeof(MENUITEMINFO); + mii.fMask = MIIM_TYPE | MIIM_ID; + mii.fType = arrMenuTypes[i]; + if (mii.fType == MFT_STRING) { + mii.wID = arrMenuIDs[i]; + mii.dwTypeData = arrMenuItems[i]; + mii.cch = _tcslen(arrMenuItems[i]); + } else { + mii.wID = 0; + } + ::InsertMenuItem(m_hSysMenu, SC_CLOSE, FALSE, &mii); + } + + // set config files menu as a submenu of "Select configuration file" item + // in the popup and system menus + ::ZeroMemory(&mii, sizeof(MENUITEMINFO)); + mii.cbSize = sizeof(MENUITEMINFO); + mii.fMask = MIIM_SUBMENU; + mii.hSubMenu = m_hConfigFilesMenu; + +// ::SetMenuItemInfo(m_hPopupMenu, ID_SEL_CONFIG_FILE, FALSE, &mii); +// ::SetMenuItemInfo(m_hSysMenu, ID_SEL_CONFIG_FILE, FALSE, &mii); + + // load the initial list (so the list can be used by external programs) + UpdateConfigFilesSubmenu(); + + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +BOOL Console::CreateConsoleWindow() { + + // create the window + DWORD dwWindowStyle = WS_VSCROLL; + if (m_dwTaskbarButton == TASKBAR_BUTTON_NORMAL) dwWindowStyle |= WS_MINIMIZEBOX; + + switch (m_dwWindowBorder) { + case BORDER_NONE : + dwWindowStyle |= WS_POPUPWINDOW & ~WS_BORDER; + break; + case BORDER_REGULAR : + dwWindowStyle |= WS_CAPTION|WS_SYSMENU; + break; + + case BORDER_THIN : + dwWindowStyle |= WS_POPUPWINDOW; + break; + + default: dwWindowStyle |= WS_POPUPWINDOW & ~WS_BORDER; + } + + // If the taskbar style is set to hide or tray, we create an invisible window + // to parent the main window to. This hides the taskbar button while allowing + // us to use the normal title bar. + if (m_dwTaskbarButton > TASKBAR_BUTTON_NORMAL) { + if ((m_hwndInvisParent = ::CreateWindowEx( + WS_EX_TOOLWINDOW, + Console::m_szHiddenParentClass, + _T(""), + WS_POPUP, + 0, + 0, + 0, + 0, + NULL, + NULL, + ghInstance, + NULL)) == NULL) { + + return FALSE; + } + + // don't let the user minimize it if there's no way to restore it + if (m_dwTaskbarButton == TASKBAR_BUTTON_HIDE) dwWindowStyle &= ~WS_MINIMIZEBOX; + } + + + if ((m_hWnd = ::CreateWindowEx( + 0, //m_dwTaskbarButton > TASKBAR_BUTTON_NORMAL ? WS_EX_TOOLWINDOW : 0, + Console::m_szConsoleClass, + m_strWindowTitle.c_str(), + dwWindowStyle, + ((m_nX == -1) || (m_nY == -1)) ? CW_USEDEFAULT : 0, + 0, + 0, + 0, + m_hwndInvisParent, + NULL, + ghInstance, + NULL)) == NULL) { + + return FALSE; + } + + ::SetWindowLongPtr( m_hWnd, GWLP_USERDATA, (LONG_PTR)this); + + if ((m_nX == -1) || (m_nY == -1)) { + RECT rectWindow; + + ::GetWindowRect(m_hWnd, &rectWindow); + m_nX = (int)rectWindow.left; + m_nY = (int)rectWindow.top; + } + + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::CreateNewFont() { + + // create a new font + if (m_hFontOld) ::SelectObject(m_hdcConsole, m_hFontOld); + if (m_hFont) ::DeleteObject(m_hFont); + + m_hFont = ::CreateFont( + -MulDiv(m_dwFontSize, ::GetDeviceCaps(m_hdcConsole, LOGPIXELSY), 72), + 0, + 0, + 0, + m_bBold ? FW_BOLD : 0, + m_bItalic, + FALSE, + FALSE, + DEFAULT_CHARSET, + OUT_DEFAULT_PRECIS, + CLIP_DEFAULT_PRECIS, + DEFAULT_QUALITY, + DEFAULT_PITCH, + m_strFontName.c_str()); + + m_hFontOld = (HFONT)::SelectObject(m_hdcConsole, m_hFont); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::CreateNewBrush() { + + // create a new background brush + if (m_hBkBrush) ::DeleteObject(m_hBkBrush); + m_hBkBrush = ::CreateSolidBrush(m_crBackground); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::CreateCursor() { + + switch (m_dwCursorStyle) { + case CURSOR_STYLE_XTERM : + m_pCursor = (Cursor*)new XTermCursor(m_hWnd, m_hdcConsole, m_crCursorColor); + break; + case CURSOR_STYLE_BLOCK : + m_pCursor = (Cursor*)new BlockCursor(m_hWnd, m_hdcConsole, m_crCursorColor); + break; + case CURSOR_STYLE_NBBLOCK : + m_pCursor = (Cursor*)new NBBlockCursor(m_hWnd, m_hdcConsole, m_crCursorColor); + break; + case CURSOR_STYLE_PULSEBLOCK : + m_pCursor = (Cursor*)new PulseBlockCursor(m_hWnd, m_hdcConsole, m_crCursorColor); + break; + case CURSOR_STYLE_BAR : + m_pCursor = (Cursor*)new BarCursor(m_hWnd, m_hdcConsole, m_crCursorColor); + break; + case CURSOR_STYLE_CONSOLE : + m_pCursor = (Cursor*)new ConsoleCursor(m_hWnd, m_hdcConsole, m_crCursorColor); + break; + case CURSOR_STYLE_NBHLINE : + m_pCursor = (Cursor*)new NBHLineCursor(m_hWnd, m_hdcConsole, m_crCursorColor); + break; + case CURSOR_STYLE_HLINE : + m_pCursor = (Cursor*)new HLineCursor(m_hWnd, m_hdcConsole, m_crCursorColor); + break; + case CURSOR_STYLE_VLINE : + m_pCursor = (Cursor*)new VLineCursor(m_hWnd, m_hdcConsole, m_crCursorColor); + break; + case CURSOR_STYLE_RECT : + m_pCursor = (Cursor*)new RectCursor(m_hWnd, m_hdcConsole, m_crCursorColor); + break; + case CURSOR_STYLE_NBRECT : + m_pCursor = (Cursor*)new NBRectCursor(m_hWnd, m_hdcConsole, m_crCursorColor); + break; + case CURSOR_STYLE_PULSERECT : + m_pCursor = (Cursor*)new PulseRectCursor(m_hWnd, m_hdcConsole, m_crCursorColor); + break; + case CURSOR_STYLE_FADEBLOCK : + m_pCursor = (Cursor*)new FadeBlockCursor(m_hWnd, m_hdcConsole, m_crCursorColor, m_crBackground); + break; + } +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::CreateOffscreenBuffers() { + + HDC hdcDesktop = ::GetDCEx(m_hWnd, NULL, 0); + + // create new window bitmap + if (m_hbmpConsoleOld) ::SelectObject(m_hdcConsole, m_hbmpConsoleOld); + if (m_hbmpConsole) ::DeleteObject(m_hbmpConsole); + + m_hbmpConsole = ::CreateCompatibleBitmap(hdcDesktop, m_nClientWidth, m_nClientHeight); + m_hbmpConsoleOld = (HBITMAP)::SelectObject(m_hdcConsole, m_hbmpConsole); + + if (m_hbmpWindowOld) ::SelectObject(m_hdcWindow, m_hbmpWindowOld); + if (m_hbmpWindow) ::DeleteObject(m_hbmpWindow); + + m_hbmpWindow = ::CreateCompatibleBitmap(hdcDesktop, m_nClientWidth, m_nClientHeight); + m_hbmpWindowOld = (HBITMAP)::SelectObject(m_hdcWindow, m_hbmpWindow); + + // create selection bitmap + if (m_hbmpSelectionOld) ::SelectObject(m_hdcSelection, m_hbmpSelectionOld); + if (m_hbmpSelection) ::DeleteObject(m_hbmpSelection); + + m_hbmpSelection = ::CreateCompatibleBitmap(m_hdcWindow, m_nClientWidth, m_nClientHeight); + m_hbmpSelectionOld = (HBITMAP)::SelectObject(m_hdcSelection, m_hbmpSelection); + + RECT rect; + rect.left = 0; + rect.top = 0; + rect.right = m_nClientWidth; + rect.bottom = m_nClientHeight; + ::FillRect(m_hdcSelection, &rect, m_hbrushSelection); + + ::ReleaseDC(m_hWnd, hdcDesktop); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +#if 0 +void Console::CreateBackgroundBitmap() { + + USES_CONVERSION; + + if (m_hbmpBackgroundOld) ::SelectObject(m_hdcBackground, m_hbmpBackgroundOld); + if (m_hbmpBackground) ::DeleteObject(m_hbmpBackground); + if (m_hdcBackground) ::DeleteDC(m_hdcBackground); + + if (!m_bBitmapBackground) return; + + // determine the total size of the background bitmap + DWORD dwPrimaryDisplayWidth = ::GetSystemMetrics(SM_CXSCREEN); + DWORD dwPrimaryDisplayHeight = ::GetSystemMetrics(SM_CYSCREEN); + + DWORD dwBackgroundWidth = 0; + DWORD dwBackgroundHeight = 0; + + if (m_bRelativeBackground) { + + if (g_bWin2000) { + // Win2K and later can handle multiple monitors + dwBackgroundWidth = ::GetSystemMetrics(SM_CXVIRTUALSCREEN); + dwBackgroundHeight = ::GetSystemMetrics(SM_CYVIRTUALSCREEN); + + // get offsets for virtual display + m_nBackgroundOffsetX = ::GetSystemMetrics(SM_XVIRTUALSCREEN); + m_nBackgroundOffsetY = ::GetSystemMetrics(SM_YVIRTUALSCREEN); + } else { + // WinNT compatibility (hope it works, I didn't test it) + dwBackgroundWidth = dwPrimaryDisplayWidth; + dwBackgroundHeight = dwBackgroundHeight; + } + + } else { + dwBackgroundWidth = m_nClientWidth; + dwBackgroundHeight = m_nClientHeight; + } + + // now, load the image... + fipImage image; + IMAGE_DATA imageData; + + if (!image.load(T2A(m_strBackgroundFile.c_str()))) { + m_bBitmapBackground = FALSE; + return; + } + + imageData.hdcImage = NULL; + imageData.dwImageWidth = image.getWidth(); + imageData.dwImageHeight = image.getHeight(); + + image.convertTo24Bits(); + + // ... if needed, tint the background image + if (m_bTintSet) { + + BYTE* pPixels = image.accessPixels(); + BYTE* pPixelsEnd = pPixels + 3*image.getWidth()*image.getHeight(); + BYTE* pPixelSubel = pPixels; + + while (pPixelSubel < pPixelsEnd) { + + *pPixelSubel = (BYTE) ((unsigned long)(*pPixelSubel * (100 - m_byTintOpacity) + m_byTintB*m_byTintOpacity)/100); + ++pPixelSubel; + *pPixelSubel = (BYTE) ((unsigned long)(*pPixelSubel * (100 - m_byTintOpacity) + m_byTintG*m_byTintOpacity)/100); + ++pPixelSubel; + *pPixelSubel = (BYTE) ((unsigned long)(*pPixelSubel * (100 - m_byTintOpacity) + m_byTintR*m_byTintOpacity)/100); + ++pPixelSubel; + } + } + + // create the basic image + HBITMAP hbmpImage = NULL; + HBITMAP hbmpImageOld = NULL; + + if (m_dwBackgroundStyle == BACKGROUND_STYLE_RESIZE) { + + if (m_bRelativeBackground) { + if (m_bExtendBackground) { + imageData.dwImageWidth = dwBackgroundWidth; + imageData.dwImageHeight = dwBackgroundHeight; + } else { + imageData.dwImageWidth = dwPrimaryDisplayWidth; + imageData.dwImageHeight = dwPrimaryDisplayHeight; + } + } else { + imageData.dwImageWidth = (DWORD)m_nClientWidth; + imageData.dwImageHeight = (DWORD)m_nClientHeight; + } + + if ((image.getWidth() != imageData.dwImageWidth) || (image.getHeight() != imageData.dwImageHeight)) { + image.rescale(imageData.dwImageWidth, imageData.dwImageHeight, FILTER_LANCZOS3); + } + } + + + // now, create a DC compatible with the screen and create the basic bitmap + HDC hdcDesktop = ::GetDCEx(m_hWnd, NULL, 0); + imageData.hdcImage = ::CreateCompatibleDC(hdcDesktop); + hbmpImage = ::CreateDIBitmap( + hdcDesktop, + image.getInfoHeader(), + CBM_INIT, + image.accessPixels(), + image.getInfo(), + DIB_RGB_COLORS); + hbmpImageOld= (HBITMAP)::SelectObject(imageData.hdcImage, hbmpImage); + ::ReleaseDC(m_hWnd, hdcDesktop); + + // create the background image + m_hdcBackground = ::CreateCompatibleDC(imageData.hdcImage); + m_hbmpBackground = ::CreateCompatibleBitmap(imageData.hdcImage, dwBackgroundWidth, dwBackgroundHeight); + m_hbmpBackgroundOld = (HBITMAP)::SelectObject(m_hdcBackground, m_hbmpBackground); + + RECT rectBackground; + rectBackground.left = 0; + rectBackground.top = 0; + rectBackground.right = dwBackgroundWidth; + rectBackground.bottom = dwBackgroundHeight; + + // fill the background with the proper background color in case the + // bitmap doesn't cover the entire background, + COLORREF crBackground; + + if (m_dwTransparency == TRANSPARENCY_FAKE) { + // get desktop background color + HKEY hkeyColors; + if (::RegOpenKeyEx(HKEY_CURRENT_USER, _T("Control Panel\\Colors"), 0, KEY_READ, &hkeyColors) == ERROR_SUCCESS) { + + TCHAR szData[MAX_PATH]; + DWORD dwDataSize = MAX_PATH; + + BYTE r = 0; + BYTE g = 0; + BYTE b = 0; + + ::ZeroMemory(szData, sizeof(szData)); + ::RegQueryValueEx(hkeyColors, _T("Background"), NULL, NULL, (BYTE*)szData, &dwDataSize); + + _stscanf(szData, _T("%i %i %i"), &r, &g, &b); + crBackground = RGB(r, g, b); + + ::RegCloseKey(hkeyColors); + } + } else { + ::CopyMemory(&crBackground, &m_crBackground, sizeof(COLORREF)); + } + + HBRUSH hBkBrush = ::CreateSolidBrush(crBackground); + ::FillRect(m_hdcBackground, &rectBackground, hBkBrush); + ::DeleteObject(hBkBrush); + + if (m_dwBackgroundStyle == BACKGROUND_STYLE_TILE) { + + // we're tiling the image, starting at coordinates (0, 0) of the virtual screen + DWORD dwX = 0; + DWORD dwY = 0; + + DWORD dwImageOffsetX = 0; + DWORD dwImageOffsetY = imageData.dwImageHeight + (m_nBackgroundOffsetY - (int)imageData.dwImageHeight*(m_nBackgroundOffsetY/(int)imageData.dwImageHeight)); + + while (dwY < dwBackgroundHeight) { + + dwX = 0; + dwImageOffsetX = imageData.dwImageWidth + (m_nBackgroundOffsetX - (int)imageData.dwImageWidth*(m_nBackgroundOffsetX/(int)imageData.dwImageWidth)); + + while (dwX < dwBackgroundWidth) { + + ::BitBlt( + m_hdcBackground, + dwX, + dwY, + imageData.dwImageWidth, + imageData.dwImageHeight, + imageData.hdcImage, + dwImageOffsetX, + dwImageOffsetY, + SRCCOPY); + + dwX += imageData.dwImageWidth - dwImageOffsetX; + dwImageOffsetX = 0; + } + + dwY += imageData.dwImageHeight - dwImageOffsetY; + dwImageOffsetY = 0; + } + + } else if (m_bExtendBackground || !m_bRelativeBackground) { + + switch (m_dwBackgroundStyle) { + case BACKGROUND_STYLE_RESIZE : + ::BitBlt( + m_hdcBackground, + 0, + 0, + dwBackgroundWidth, + dwBackgroundHeight, + imageData.hdcImage, + 0, + 0, + SRCCOPY); + break; + + case BACKGROUND_STYLE_CENTER : + ::BitBlt( + m_hdcBackground, + (dwBackgroundWidth <= imageData.dwImageWidth) ? 0 : (dwBackgroundWidth - imageData.dwImageWidth)/2, + (dwBackgroundHeight <= imageData.dwImageHeight) ? 0 : (dwBackgroundHeight - imageData.dwImageHeight)/2, + imageData.dwImageWidth, + imageData.dwImageHeight, + imageData.hdcImage, + (dwBackgroundWidth < imageData.dwImageWidth) ? (imageData.dwImageWidth - dwBackgroundWidth)/2 : 0, + (dwBackgroundHeight < imageData.dwImageHeight) ? (imageData.dwImageHeight - dwBackgroundHeight)/2 : 0, + SRCCOPY); + break; + } + } else { + ::EnumDisplayMonitors(NULL, NULL, Console::BackgroundEnumProc, (DWORD)&imageData); + } + + ::SelectObject(imageData.hdcImage, hbmpImageOld); + ::DeleteObject(hbmpImage); + ::DeleteDC(imageData.hdcImage); +} +#endif + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +#if 0 +BOOL CALLBACK Console::BackgroundEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData) { + + IMAGE_DATA* pImageData = (IMAGE_DATA*)dwData; + + DWORD dwDisplayWidth = lprcMonitor->right - lprcMonitor->left; + DWORD dwDisplayHeight = lprcMonitor->bottom - lprcMonitor->top; + + DWORD dwPrimaryDisplayWidth = ::GetSystemMetrics(SM_CXSCREEN); + DWORD dwPrimaryDisplayHeight = ::GetSystemMetrics(SM_CYSCREEN); + + // center the image according to current display's size and position + switch (g_pConsole->m_dwBackgroundStyle) { + + case BACKGROUND_STYLE_RESIZE : + ::BitBlt( + g_pConsole->m_hdcBackground, + (dwDisplayWidth <= dwPrimaryDisplayWidth) ? lprcMonitor->left-g_pConsole->m_nBackgroundOffsetX : lprcMonitor->left-g_pConsole->m_nBackgroundOffsetX + (dwDisplayWidth - dwPrimaryDisplayWidth)/2, + (dwDisplayHeight <= dwPrimaryDisplayHeight) ? lprcMonitor->top-g_pConsole->m_nBackgroundOffsetY : lprcMonitor->top-g_pConsole->m_nBackgroundOffsetY + (dwDisplayHeight - dwPrimaryDisplayHeight)/2, + dwDisplayWidth, + dwDisplayHeight, + pImageData->hdcImage, + (dwDisplayWidth < dwPrimaryDisplayWidth) ? (dwPrimaryDisplayWidth - dwDisplayWidth)/2 : 0, + (dwDisplayHeight < dwPrimaryDisplayHeight) ? (dwPrimaryDisplayHeight - dwDisplayHeight)/2 : 0, + SRCCOPY); + + break; + + case BACKGROUND_STYLE_CENTER : + ::BitBlt( + g_pConsole->m_hdcBackground, + (dwDisplayWidth <= pImageData->dwImageWidth) ? lprcMonitor->left-g_pConsole->m_nBackgroundOffsetX : lprcMonitor->left-g_pConsole->m_nBackgroundOffsetX + (dwDisplayWidth - pImageData->dwImageWidth)/2, + (dwDisplayHeight <= pImageData->dwImageHeight) ? lprcMonitor->top-g_pConsole->m_nBackgroundOffsetY : lprcMonitor->top-g_pConsole->m_nBackgroundOffsetY + (dwDisplayHeight - pImageData->dwImageHeight)/2, + dwDisplayWidth, + dwDisplayHeight, + pImageData->hdcImage, + (dwDisplayWidth < pImageData->dwImageWidth) ? (pImageData->dwImageWidth - dwDisplayWidth)/2 : 0, + (dwDisplayHeight < pImageData->dwImageHeight) ? (pImageData->dwImageHeight - dwDisplayHeight)/2 : 0, + SRCCOPY); + + break; + } + + return TRUE; +} +#endif + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::GetTextSize() { + + TEXTMETRIC textMetric; + ::GetTextMetrics(m_hdcConsole, &textMetric); + + m_nCharHeight = textMetric.tmHeight; + + if (!(textMetric.tmPitchAndFamily & TMPF_FIXED_PITCH)) { + // fixed pitch font (TMPF_FIXED_PITCH is cleared!!!) + m_nCharWidth = textMetric.tmAveCharWidth; + } +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::GetBordersDimensions() { + + WINDOWINFO wndInfo; + TITLEBARINFO titlebarInfo; + + ::ZeroMemory(&wndInfo, sizeof(WINDOWINFO)); + ::ZeroMemory(&titlebarInfo, sizeof(TITLEBARINFO)); + + wndInfo.cbSize = sizeof(WINDOWINFO); + titlebarInfo.cbSize = sizeof(TITLEBARINFO); + + ::GetWindowInfo(m_hWnd, &wndInfo); + ::GetTitleBarInfo(m_hWnd, &titlebarInfo); + + m_nXBorderSize = wndInfo.cxWindowBorders; + m_nYBorderSize = wndInfo.cyWindowBorders; + m_nCaptionSize = (titlebarInfo.rgstate[0] & STATE_SYSTEM_INVISIBLE) ? 0 : titlebarInfo.rcTitleBar.bottom - titlebarInfo.rcTitleBar.top; +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::CalcWindowSize() { + + m_nClientHeight = m_dwRows * m_nCharHeight + 2*m_nInsideBorder; + + if (m_nCharWidth > 0) { + // fixed pitch font + m_nClientWidth = m_dwColumns * m_nCharWidth + 2*m_nInsideBorder; + } else { + // variable pitch font + int nCharWidth; + ::GetCharWidth32(m_hdcConsole, _TCHAR('m'), _TCHAR('m'), &nCharWidth); + m_nClientWidth = m_dwColumns * nCharWidth; + } + + switch (m_dwWindowBorder) { + case BORDER_NONE : + m_nWindowHeight = m_nClientHeight; + m_nWindowWidth = m_nClientWidth; + break; + + case BORDER_REGULAR : { + + m_nWindowHeight = m_nClientHeight + m_nCaptionSize + 2*m_nYBorderSize; + m_nWindowWidth = m_nClientWidth + 2 * m_nXBorderSize; + + break; + } + + case BORDER_THIN : + + m_nWindowHeight = m_nClientHeight + 2*m_nYBorderSize; + m_nWindowWidth = m_nClientWidth + 2*m_nXBorderSize; + } + + if (m_bShowScrollbar) m_nWindowWidth += m_nScrollbarWidth; +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +#if 0 +void Console::SetWindowTransparency() { + // set alpha transparency (Win2000 and later only!) + if (g_bWin2000 && ((m_dwTransparency == TRANSPARENCY_ALPHA) || (m_dwTransparency == TRANSPARENCY_COLORKEY))) { + + ::SetWindowLong(m_hWnd, GWL_EXSTYLE, ::GetWindowLong(m_hWnd, GWL_EXSTYLE) | WS_EX_LAYERED); + g_pfnSetLayeredWndAttr(m_hWnd, m_crBackground, m_byAlpha, m_dwTransparency == TRANSPARENCY_ALPHA ? LWA_ALPHA : LWA_COLORKEY); + + } else if (m_dwTransparency == TRANSPARENCY_FAKE) { + // get wallpaper settings + HKEY hkeyDesktop; + if (::RegOpenKeyEx(HKEY_CURRENT_USER, _T("Control Panel\\Desktop"), 0, KEY_READ, &hkeyDesktop) == ERROR_SUCCESS) { + TCHAR szData[MAX_PATH]; + DWORD dwDataSize = MAX_PATH; + + DWORD dwWallpaperStyle; + DWORD dwTileWallpaper; + + ::ZeroMemory(szData, sizeof(szData)); + ::RegQueryValueEx(hkeyDesktop, _T("Wallpaper"), NULL, NULL, (BYTE*)szData, &dwDataSize); + + if (_tcslen(szData) > 0) { + m_bBitmapBackground = TRUE; + m_strBackgroundFile = szData; + m_bRelativeBackground = TRUE; + m_bExtendBackground = FALSE; + + // get wallpaper style and tile flag + dwDataSize = MAX_PATH; + ::ZeroMemory(szData, sizeof(szData)); + ::RegQueryValueEx(hkeyDesktop, _T("WallpaperStyle"), NULL, NULL, (BYTE*)szData, &dwDataSize); + + dwWallpaperStyle = _ttoi(szData); + + dwDataSize = MAX_PATH; + ::ZeroMemory(szData, sizeof(szData)); + ::RegQueryValueEx(hkeyDesktop, _T("TileWallpaper"), NULL, NULL, (BYTE*)szData, &dwDataSize); + + dwTileWallpaper = _ttoi(szData); + + if (dwTileWallpaper == 1) { + m_dwBackgroundStyle = BACKGROUND_STYLE_TILE; + } else { + + if (dwWallpaperStyle == 0) { + m_dwBackgroundStyle = BACKGROUND_STYLE_CENTER; + } else { + m_dwBackgroundStyle = BACKGROUND_STYLE_RESIZE; + } + } + } + + ::RegCloseKey(hkeyDesktop); + } + } +} +#endif + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::SetScrollbarStuff() { + + if (m_bUseTextBuffer) { + m_bShowScrollbar = m_dwBufferRows > m_dwRows; + } else { + m_bShowScrollbar = FALSE; + } + + // we don't call InitializeFlatSB due to some problems on Win2k, Windowblinds and new-style scrollbars + if (m_nScrollbarStyle != FSB_REGULAR_MODE) ::InitializeFlatSB(m_hWnd); + ::FlatSB_ShowScrollBar(m_hWnd, SB_VERT, m_bShowScrollbar); + ::FlatSB_SetScrollRange(m_hWnd, SB_VERT, 0, m_dwBufferRows-m_dwRows, FALSE); + + // set scrollbar properties + ::FlatSB_SetScrollProp(m_hWnd, WSB_PROP_VSTYLE, m_nScrollbarStyle, FALSE); + ::FlatSB_SetScrollProp(m_hWnd, WSB_PROP_VBKGCOLOR, m_crScrollbarColor, FALSE); + ::FlatSB_SetScrollProp(m_hWnd, WSB_PROP_CXVSCROLL , m_nScrollbarWidth, FALSE); + ::FlatSB_SetScrollProp(m_hWnd, WSB_PROP_CYVSCROLL, m_nScrollbarButtonHeight, FALSE); + ::FlatSB_SetScrollProp(m_hWnd, WSB_PROP_CYVTHUMB, m_nScrollbarThunmbHeight, TRUE); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::SetDefaultConsoleColors() { + + m_arrConsoleColors[0] = 0x000000; + m_arrConsoleColors[1] = 0x800000; + m_arrConsoleColors[2] = 0x008000; + m_arrConsoleColors[3] = 0x808000; + m_arrConsoleColors[4] = 0x000080; + m_arrConsoleColors[5] = 0x800080; + m_arrConsoleColors[6] = 0x008080; + m_arrConsoleColors[7] = 0xC0C0C0; + m_arrConsoleColors[8] = 0x808080; + m_arrConsoleColors[9] = 0xFF0000; + m_arrConsoleColors[10] = 0x00FF00; + m_arrConsoleColors[11] = 0xFFFF00; + m_arrConsoleColors[12] = 0x0000FF; + m_arrConsoleColors[13] = 0xFF00FF; + m_arrConsoleColors[14] = 0x00FFFF; + m_arrConsoleColors[15] = 0xFFFFFF; +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::SetWindowSizeAndPosition() { + + // set window position +#if 0 + DWORD dwScreenWidth = ::GetSystemMetrics(g_bWin2000 ? SM_CXVIRTUALSCREEN : SM_CXSCREEN); + DWORD dwScreenHeight = ::GetSystemMetrics(g_bWin2000 ? SM_CYVIRTUALSCREEN : SM_CYSCREEN); + DWORD dwTop = ::GetSystemMetrics(g_bWin2000 ? SM_YVIRTUALSCREEN : 0); + DWORD dwLeft = ::GetSystemMetrics(g_bWin2000 ? SM_XVIRTUALSCREEN : 0); +#else + DWORD dwScreenWidth = ::GetSystemMetrics(SM_CXSCREEN); + DWORD dwScreenHeight = ::GetSystemMetrics(SM_CYSCREEN); + DWORD dwTop = ::GetSystemMetrics(0); + DWORD dwLeft = ::GetSystemMetrics(0); +#endif + + switch (m_dwDocked) { + case DOCK_TOP_LEFT: + // top left + m_nX = dwLeft; + m_nY = dwTop; + break; + + case DOCK_TOP_RIGHT: + // top right + m_nX = dwScreenWidth - m_nWindowWidth; + m_nY = dwTop; + break; + + case DOCK_BOTTOM_RIGHT: + // bottom right + m_nX = dwScreenWidth - m_nWindowWidth; + m_nY = dwScreenHeight - m_nWindowHeight; + break; + + case DOCK_BOTTOM_LEFT: + // bottom left + m_nX = dwLeft; + m_nY = dwScreenHeight - m_nWindowHeight; + break; + } + + HWND hwndZ; + switch (m_dwCurrentZOrder) { + case Z_ORDER_REGULAR : hwndZ = HWND_NOTOPMOST; break; + case Z_ORDER_ONTOP : hwndZ = HWND_TOPMOST; break; + case Z_ORDER_ONBOTTOM : hwndZ = HWND_BOTTOM; break; + } + + ::SetWindowPos( + m_hWnd, + hwndZ, + m_nX, + m_nY, + m_nWindowWidth, + m_nWindowHeight, + 0); + + UpdateOnTopMenuItem(); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::SetWindowIcons() { + + HICON hOldIcon = NULL; + + if (m_strIconFilename.length() > 0) { + + // custom icon, try loading it... + if ((m_hSmallIcon = (HICON)::LoadImage(NULL, m_strIconFilename.c_str(), IMAGE_ICON, 16, 16, LR_LOADFROMFILE)) != NULL) { + + // icon file exists, load and set the big icon as well + m_hBigIcon = (HICON)::LoadImage(NULL, m_strIconFilename.c_str(), IMAGE_ICON, 0, 0, LR_LOADFROMFILE | LR_DEFAULTSIZE); + hOldIcon = (HICON)::SendMessage(m_hWnd, WM_SETICON, ICON_BIG, (LPARAM)m_hBigIcon); + if (hOldIcon) ::DestroyIcon(hOldIcon); + + } else { + m_hSmallIcon = (HICON)::LoadImage(ghInstance, MAKEINTRESOURCE(IDI_ICON2), IMAGE_ICON, 16, 16, 0); + } + + } else { + m_hSmallIcon = (HICON)::LoadImage(ghInstance, MAKEINTRESOURCE(IDI_ICON2), IMAGE_ICON, 16, 16, 0); + } + + hOldIcon = (HICON)::SendMessage(m_hWnd, WM_SETICON, ICON_SMALL, (LPARAM)m_hSmallIcon); + if (hOldIcon) ::DestroyIcon(hOldIcon); + + SetTrayIcon(m_dwTaskbarButton == TASKBAR_BUTTON_TRAY ? NIM_ADD : NIM_DELETE); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +BOOL Console::SetTrayIcon(DWORD dwMessage) { + + NOTIFYICONDATA tnd; + tstring strToolTip(m_strWindowTitle); + + tnd.cbSize = sizeof(NOTIFYICONDATA); + tnd.hWnd = m_hWnd; + tnd.uID = TRAY_ICON_ID; + tnd.uFlags = NIF_MESSAGE|NIF_ICON|NIF_TIP; + tnd.uCallbackMessage = WM_TRAY_NOTIFY; + tnd.hIcon = m_hSmallIcon; + + if (strToolTip.length() > 63) { + strToolTip.resize(59); + strToolTip += _T(" ..."); + DWORD dw = strToolTip.length(); + } + + _tcscpy(tnd.szTip, strToolTip.c_str()); + return ::Shell_NotifyIcon(dwMessage, &tnd); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::DestroyCursor() { + + if (m_pCursor) + { + delete m_pCursor; + m_pCursor = NULL; + } +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::EditConfigFile() { + + // prepare editor parameters + tstring strParams(m_strConfigEditorParams); + + if (strParams.length() == 0) { + // no params, just use the config file + strParams = m_strConfigFile; + } else { + int nPos = strParams.find(_T("%f")); + + if (nPos == tstring::npos) { + // no '%f' in editor params, concatenate config file name + strParams += _T(" "); + strParams += m_strConfigFile; + } else { + // replace '%f' with config file name + strParams = strParams.replace(nPos, 2, m_strConfigFile); + } + } + + // start editor + ::ShellExecute(NULL, NULL, m_strConfigEditor.c_str(), strParams.c_str(), NULL, SW_SHOWNORMAL); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::ReloadSettings() { + + m_bInitializing = TRUE; + m_bReloading = TRUE; + + // suspend console monitor thread + ::SuspendThread(m_hMonitorThread); + ::KillTimer(m_hWnd, TIMER_REPAINT_CHANGE); + if (m_dwMasterRepaintInt) ::KillTimer(m_hWnd, TIMER_REPAINT_MASTER); + + // hide Windows console + ::ShowWindow(m_hWndConsole, SW_HIDE); + + // destroy icons + SetTrayIcon(NIM_DELETE); + if (m_hSmallIcon) ::DestroyIcon(m_hSmallIcon); + if (m_hBigIcon) ::DestroyIcon(m_hBigIcon); + + // destroy cursor + DestroyCursor(); + + // destory menus + ::DestroyMenu(m_hConfigFilesMenu); + ::DestroyMenu(m_hPopupMenu); + + // uninitialize flat scrollbars + if (m_nScrollbarStyle != FSB_REGULAR_MODE) ::UninitializeFlatSB(m_hWnd); + + // destory window + ::DestroyWindow(m_hWnd); + if (m_hwndInvisParent) ::DestroyWindow(m_hwndInvisParent); + + // set default values + m_strShell = _T(""); + m_strConfigEditor = _T("notepad.exe"); + m_strConfigEditorParams = _T(""); + m_dwReloadNewConfig = m_dwReloadNewConfigDefault; + m_hwndInvisParent = NULL; + m_dwMasterRepaintInt = 500; + m_dwChangeRepaintInt = 50; + m_strIconFilename = _T(""); + m_hSmallIcon = NULL; + m_hBigIcon = NULL; + m_hPopupMenu = NULL; + m_hConfigFilesMenu = NULL; + m_bPopupMenuDisabled = FALSE; + m_strWindowTitle = m_strWindowTitleDefault; + m_strWindowTitleCurrent = m_strWindowTitleDefault; + m_strFontName = _T("Courier New"); + m_dwFontSize = 10; + m_bBold = FALSE; + m_bItalic = FALSE; + m_bUseFontColor = FALSE; + m_crFontColor = RGB(0, 0, 0); + m_nWindowWidth = 0; + m_nWindowHeight = 0; + m_nXBorderSize = 5; + m_nYBorderSize = 5; + m_nCaptionSize = 0; + m_nClientWidth = 0; + m_nClientHeight = 0; + m_nCharHeight = 0; + m_nCharWidth = 0; + m_dwWindowBorder = BORDER_REGULAR; + m_bShowScrollbar = TRUE; + m_nScrollbarStyle = FSB_REGULAR_MODE; + m_crScrollbarColor = ::GetSysColor(COLOR_3DHILIGHT); + m_nScrollbarWidth = ::GetSystemMetrics(SM_CXVSCROLL); + m_nScrollbarButtonHeight= ::GetSystemMetrics(SM_CYVSCROLL); + m_nScrollbarThunmbHeight= ::GetSystemMetrics(SM_CYVTHUMB); + m_dwTaskbarButton = TASKBAR_BUTTON_NORMAL; + m_bMouseDragable = TRUE; + m_nSnapDst = 10; + m_dwDocked = DOCK_NONE; + m_dwOriginalZOrder = Z_ORDER_REGULAR; + m_dwCurrentZOrder = Z_ORDER_REGULAR; + m_dwTransparency = TRANSPARENCY_NONE; + m_byAlpha = 150; + m_byInactiveAlpha = 150; + m_crBackground = RGB(0, 0, 0); + m_crConsoleBackground = RGB(0, 0, 0); + m_bTintSet = FALSE; + m_byTintOpacity = 50; + m_byTintR = 0; + m_byTintG = 0; + m_byTintB = 0; + m_bBitmapBackground = FALSE; + m_strBackgroundFile = _T(""); + m_dwBackgroundStyle = BACKGROUND_STYLE_RESIZE; + m_bRelativeBackground = FALSE; + m_bExtendBackground = FALSE; + m_bHideWindow = FALSE; + m_bHideConsole = TRUE; + m_dwCursorStyle = CURSOR_STYLE_CONSOLE; + m_bStartMinimized = FALSE; + m_crCursorColor = RGB(255, 255, 255); + m_bCursorVisible = TRUE; + m_dwRows = 50; + m_dwColumns = 80; + m_dwBufferRows = 500; + m_bUseTextBuffer = TRUE; + m_bCopyOnSelect = FALSE; + + m_nTextColor = 15; + m_nTextBgColor = 0; + + SetDefaultConsoleColors(); + + GetOptions(); + + CreateConsoleWindow(); + + SetupMenus(); + + CreateNewFont(); + CreateNewBrush(); + +// SetWindowTransparency(); + SetWindowIcons(); + + CreateCursor(); + + RefreshStdOut(); + GetTextSize(); + GetBordersDimensions(); + InitConsoleWndSize(m_dwColumns); + ResizeConsoleWindow(); +// ShowHideConsole(); + + m_bInitializing = FALSE; + m_bReloading = FALSE; + + RefreshScreenBuffer(); + ::CopyMemory(m_pScreenBuffer, m_pScreenBufferNew, sizeof(CHAR_INFO) * m_dwRows * m_dwColumns); + RepaintWindow(); + + if (m_dwMasterRepaintInt) ::SetTimer(m_hWnd, TIMER_REPAINT_MASTER, m_dwMasterRepaintInt, NULL); + + if (m_bStartMinimized) { + if (m_dwTaskbarButton > TASKBAR_BUTTON_NORMAL) { + m_bHideWindow = TRUE; + } else { + ::ShowWindow(m_hWnd, SW_MINIMIZE); + } + } else { + ::ShowWindow(m_hWnd, SW_SHOW); + } + + ::SetForegroundWindow(m_hWnd); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +BOOL Console::StartShellProcess() { + +#if 0 + if (m_strShell.length() == 0) { + TCHAR szComspec[MAX_PATH]; + + if (::GetEnvironmentVariable(_T("COMSPEC"), szComspec, MAX_PATH) > 0) { + m_strShell = szComspec; + } else { + m_strShell = _T("cmd.exe"); + } + } + + tstring strShellCmdLine(m_strShell); + if (m_strShellCmdLine.length() > 0) { + strShellCmdLine += _T(" "); + strShellCmdLine += m_strShellCmdLine; + } + +// strShellCmdLine = "cmd.exe"; + + // create the console window + TCHAR szConsoleTitle[MAX_PATH]; + ::AllocConsole(); + // we use this to avoid possible problems with multiple console instances running + _stprintf(szConsoleTitle, _T("%i"), ::GetCurrentThreadId()); + ::SetConsoleTitle(szConsoleTitle); + m_hStdOut = ::GetStdHandle(STD_OUTPUT_HANDLE); + while ((m_hWndConsole = ::FindWindow(NULL, szConsoleTitle)) == NULL) ::Sleep(50); + ::SetConsoleTitle(m_strWinConsoleTitle.c_str()); +#endif + + // this is a little hack needed to support columns greater than standard 80 + RefreshStdOut(); + InitConsoleWndSize(80); + ResizeConsoleWindow(); + +#if 0 + ::SetConsoleCtrlHandler(Console::CtrlHandler, TRUE); + + // setup the start up info struct + PROCESS_INFORMATION pi; + STARTUPINFO si; + ::ZeroMemory(&si, sizeof(STARTUPINFO)); + si.cb = sizeof(STARTUPINFO); + + if (!::CreateProcess( + NULL, + (TCHAR*)strShellCmdLine.c_str(), + NULL, + NULL, + TRUE, + 0, + NULL, + NULL, + &si, + &pi)) { + + return FALSE; + } + + if (m_dwHideConsoleTimeout > 0) { + ::ShowWindow(m_hWndConsole, SW_MINIMIZE); + ::SetTimer(m_hWnd, TIMER_SHOW_HIDE_CONSOLE, m_dwHideConsoleTimeout, NULL); + } else { + ShowHideConsole(); + } + + // close main thread handle + ::CloseHandle(pi.hThread); + + // set handles + m_hQuitEvent = ::CreateEvent(NULL, FALSE, FALSE, NULL); + m_hConsoleProcess = pi.hProcess; +#endif + + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::RefreshStdOut() { +#if 0 + if (m_hStdOutFresh) ::CloseHandle(m_hStdOutFresh); + m_hStdOutFresh = ::CreateFile(_T("CONOUT$"), GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); +#endif +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::RefreshScreenBuffer() { + // if we're initializing, do nothing + if (m_bInitializing) return; + +// ::GetConsoleScreenBufferInfo(m_hStdOutFresh, &m_csbiConsole); + + SCROLLINFO si; + si.cbSize = sizeof(si); + si.fMask = SIF_POS; + si.nPos = (int)m_csbiConsole.srWindow.Top; + ::FlatSB_SetScrollInfo(m_hWnd, SB_VERT, &si, TRUE); + +#if 0 + if ((m_csbiConsole.srWindow.Right - m_csbiConsole.srWindow.Left + 1 != m_dwColumns) || (m_csbiConsole.srWindow.Bottom - m_csbiConsole.srWindow.Top + 1 != m_dwRows) || (m_csbiConsole.dwSize.Y != m_dwBufferRows)) { + m_dwColumns = m_csbiConsole.srWindow.Right - m_csbiConsole.srWindow.Left + 1; + m_dwRows = m_csbiConsole.srWindow.Bottom - m_csbiConsole.srWindow.Top + 1; + ResizeConsoleWindow(); + } + + COORD coordBufferSize; + COORD coordStart; + SMALL_RECT srRegion; + + coordStart.X = 0; + coordStart.Y = 0; + + coordBufferSize.X = m_dwColumns; + coordBufferSize.Y = m_dwRows; + + srRegion.Top = m_csbiConsole.srWindow.Top; + srRegion.Left = 0; + srRegion.Bottom = m_csbiConsole.srWindow.Top + m_dwRows - 1; + srRegion.Right = m_dwColumns - 1; + + DEL_ARR(m_pScreenBufferNew); + m_pScreenBufferNew = new CHAR_INFO[m_dwRows * m_dwColumns]; + ::ZeroMemory( m_pScreenBufferNew, m_dwRows * m_dwColumns * sizeof(CHAR_INFO)); + for (int i=0; i (DWORD) dwColumns * m_dwBufferRows) { + ::SetConsoleWindowInfo(m_hStdOutFresh, TRUE, &srConsoleRect); + ::SetConsoleScreenBufferSize(m_hStdOutFresh, coordConsoleSize); + } else if (((DWORD)csbi.dwSize.X < dwColumns) || ((DWORD)csbi.dwSize.Y < m_dwBufferRows) || ((DWORD)(csbi.srWindow.Bottom - csbi.srWindow.Top + 1) != m_dwRows)) { + ::SetConsoleScreenBufferSize(m_hStdOutFresh, coordConsoleSize); + ::SetConsoleWindowInfo(m_hStdOutFresh, TRUE, &srConsoleRect); + } +#endif +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::ResizeConsoleWindow() { + + m_bInitializing = TRUE; + + if (m_nTextSelection) ClearSelection(); + +// CONSOLE_SCREEN_BUFFER_INFO csbi; +// ::GetConsoleScreenBufferInfo(m_hStdOutFresh, &csbi); + + // in case buffer rows increased since last resize, and we're not using text buffer + if (!m_bUseTextBuffer) m_dwBufferRows = m_dwRows; + + COORD coordBuffersSize; + coordBuffersSize.X = (SHORT)m_dwColumns; + coordBuffersSize.Y = (SHORT)m_dwBufferRows; + + SMALL_RECT srConsoleRect; + srConsoleRect.Top = srConsoleRect.Left =0; + srConsoleRect.Right = m_dwColumns - 1; + srConsoleRect.Bottom= m_dwRows - 1; + +#if 0 + // order of setting window size and screen buffer size depends on current and desired dimensions + if ((DWORD) csbi.dwSize.X * csbi.dwSize.Y > (DWORD) m_dwColumns * m_dwBufferRows) { + + if (m_bUseTextBuffer && (csbi.dwSize.Y > m_dwBufferRows)) { + coordBuffersSize.Y = m_dwBufferRows = csbi.dwSize.Y; + } + + ::SetConsoleWindowInfo(m_hStdOutFresh, TRUE, &srConsoleRect); + ::SetConsoleScreenBufferSize(m_hStdOutFresh, coordBuffersSize); + + // } else if (((DWORD)csbi.dwSize.X < m_dwColumns) || ((DWORD)csbi.dwSize.Y < m_dwBufferRows) || ((DWORD)(csbi.srWindow.Bottom - csbi.srWindow.Top + 1) != m_dwRows)) { + } else if ((DWORD) csbi.dwSize.X * csbi.dwSize.Y < (DWORD) m_dwColumns * m_dwBufferRows) { + + if (csbi.dwSize.Y < m_dwBufferRows) { + m_dwBufferRows = coordBuffersSize.Y = csbi.dwSize.Y; + } + + ::SetConsoleScreenBufferSize(m_hStdOutFresh, coordBuffersSize); + ::SetConsoleWindowInfo(m_hStdOutFresh, TRUE, &srConsoleRect); + } +#endif + + SetScrollbarStuff(); + CalcWindowSize(); + SetWindowSizeAndPosition(); + CreateOffscreenBuffers(); + +// if (m_bBitmapBackground) CreateBackgroundBitmap(); +} + +void Console::AllocateBuffer() +{ + // resize screen buffer + delete[] m_pScreenBuffer; + m_pScreenBuffer = new CHAR_INFO[m_dwRows * m_dwColumns]; + m_pScreenBufferNew = new CHAR_INFO[m_dwBufferRows * m_dwColumns]; + ::ZeroMemory( m_pScreenBufferNew, m_dwBufferRows * m_dwColumns * sizeof(CHAR_INFO)); + + m_bInitializing = FALSE; +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::RepaintWindow() { + + RECT rect; + rect.top = 0; + rect.left = 0; + rect.bottom = m_nClientHeight; + rect.right = m_nClientWidth; + +#if 0 + if (m_bBitmapBackground) { + if (m_bRelativeBackground) { + ::BitBlt(m_hdcConsole, 0, 0, m_nClientWidth, m_nClientHeight, m_hdcBackground, m_nX+m_nXBorderSize-m_nBackgroundOffsetX, m_nY+m_nCaptionSize+m_nYBorderSize-m_nBackgroundOffsetY, SRCCOPY); + } else { + ::BitBlt(m_hdcConsole, 0, 0, m_nClientWidth, m_nClientHeight, m_hdcBackground, 0, 0, SRCCOPY); + } + } else { +#endif + ::FillRect(m_hdcConsole, &rect, m_hBkBrush); +// } + + DWORD dwX = m_nInsideBorder; + DWORD dwY = m_nInsideBorder; + DWORD dwOffset = m_csbiConsole.srWindow.Top * m_dwColumns; + + WORD attrBG; + + // stuff used for caching + int nBkMode = TRANSPARENT; + COLORREF crBkColor = RGB(0, 0, 0); + COLORREF crTxtColor = RGB(0, 0, 0); + + int nNewBkMode = TRANSPARENT; + COLORREF crNewBkColor = RGB(0, 0, 0); + COLORREF crNewTxtColor = RGB(0, 0, 0); + + bool bTextOut = false; + + wstring strText(L""); + + memcpy(m_pScreenBuffer, m_pScreenBufferNew + dwOffset, sizeof(CHAR_INFO)*m_dwRows * m_dwColumns); + dwOffset = 0; + + if (m_nCharWidth > 0) { + // fixed pitch font + for (DWORD i = 0; i < m_dwRows; ++i) { + + dwX = m_nInsideBorder; + dwY = i*m_nCharHeight + m_nInsideBorder; + + nBkMode = TRANSPARENT; + crBkColor = RGB(0, 0, 0); + crTxtColor = RGB(0, 0, 0); + + bTextOut = false; + + attrBG = m_pScreenBuffer[dwOffset].Attributes >> 4; + + // here we decide how to paint text over the backgound + if (m_arrConsoleColors[attrBG] == m_crConsoleBackground) { + ::SetBkMode(m_hdcConsole, TRANSPARENT); + nBkMode = TRANSPARENT; + } else { + ::SetBkMode(m_hdcConsole, OPAQUE); + nBkMode = OPAQUE; + ::SetBkColor(m_hdcConsole, m_arrConsoleColors[attrBG]); + crBkColor = m_arrConsoleColors[attrBG]; + } + + ::SetTextColor(m_hdcConsole, m_bUseFontColor ? m_crFontColor : m_arrConsoleColors[m_pScreenBuffer[dwOffset].Attributes & 0xF]); + crTxtColor = m_bUseFontColor ? m_crFontColor : m_arrConsoleColors[m_pScreenBuffer[dwOffset].Attributes & 0xF]; + + strText = m_pScreenBuffer[dwOffset].Char.UnicodeChar; + ++dwOffset; + + for (DWORD j = 1; j < m_dwColumns; ++j) { + + attrBG = m_pScreenBuffer[dwOffset].Attributes >> 4; + + if (m_arrConsoleColors[attrBG] == m_crConsoleBackground) { + if (nBkMode != TRANSPARENT) { + nBkMode = TRANSPARENT; + bTextOut = true; + } + } else { + if (nBkMode != OPAQUE) { + nBkMode = OPAQUE; + bTextOut = true; + } + if (crBkColor != m_arrConsoleColors[attrBG]) { + crBkColor = m_arrConsoleColors[attrBG]; + bTextOut = true; + } + } + + if (crTxtColor != (m_bUseFontColor ? m_crFontColor : m_arrConsoleColors[m_pScreenBuffer[dwOffset].Attributes & 0xF])) { + crTxtColor = m_bUseFontColor ? m_crFontColor : m_arrConsoleColors[m_pScreenBuffer[dwOffset].Attributes & 0xF]; + bTextOut = true; + } + + if (bTextOut) { + + ::TextOutW(m_hdcConsole, dwX, dwY, strText.c_str(), strText.length()); + dwX += strText.length() * m_nCharWidth; + + ::SetBkMode(m_hdcConsole, nBkMode); + ::SetBkColor(m_hdcConsole, crBkColor); + ::SetTextColor(m_hdcConsole, crTxtColor); + + strText = m_pScreenBuffer[dwOffset].Char.UnicodeChar; + + } else { + strText += m_pScreenBuffer[dwOffset].Char.UnicodeChar; + } + + ++dwOffset; + } + + if (strText.length() > 0) { + ::TextOutW(m_hdcConsole, dwX, dwY, strText.c_str(), strText.length()); + } + } + + } else { + + // variable pitch font + for (DWORD i = 0; i < m_dwRows; ++i) { + + dwX = m_nInsideBorder; + dwY = i*m_nCharHeight + m_nInsideBorder; + + for (DWORD j = 0; j < m_dwColumns; ++j) { + + attrBG = m_pScreenBuffer[dwOffset].Attributes >> 4; + + // here we decide how to paint text over the backgound + if (m_arrConsoleColors[attrBG] == m_crConsoleBackground) { + ::SetBkMode(m_hdcConsole, TRANSPARENT); + } else { + ::SetBkMode(m_hdcConsole, OPAQUE); + ::SetBkColor(m_hdcConsole, m_arrConsoleColors[attrBG]); + } + + ::SetTextColor(m_hdcConsole, m_bUseFontColor ? m_crFontColor : m_arrConsoleColors[m_pScreenBuffer[dwOffset].Attributes & 0xF]); + ::TextOutW(m_hdcConsole, dwX, dwY, &(m_pScreenBuffer[dwOffset].Char.UnicodeChar), 1); + int nWidth; + ::GetCharWidth32(m_hdcConsole, m_pScreenBuffer[dwOffset].Char.UnicodeChar, m_pScreenBuffer[dwOffset].Char.UnicodeChar, &nWidth); + dwX += nWidth; + ++dwOffset; + } + } + } + + if (m_pCursor) DrawCursor(TRUE); + + ::InvalidateRect(m_hWnd, NULL, FALSE); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::RepaintWindowChanges() { + + DWORD dwX = m_nInsideBorder; + DWORD dwY = m_nInsideBorder; + DWORD dwDestOffset = 0; + DWORD dwSrcOffset = m_csbiConsole.srWindow.Top * m_dwColumns; + + WORD attrBG; + + if (m_nCharWidth > 0) { + + // fixed pitch font + for (DWORD i = 0; i < m_dwRows; ++i) { + + dwX = m_nInsideBorder; + dwY = i*m_nCharHeight + m_nInsideBorder; + + for (DWORD j = 0; j < m_dwColumns; ++j) { + + if (memcmp(&(m_pScreenBuffer[dwDestOffset]), &(m_pScreenBufferNew[dwSrcOffset]), sizeof(CHAR_INFO))) { + + memcpy(&(m_pScreenBuffer[dwDestOffset]), &(m_pScreenBufferNew[dwSrcOffset]), sizeof(CHAR_INFO)); + + RECT rect; + rect.top = dwY; + rect.left = dwX; + rect.bottom = dwY + m_nCharHeight; + rect.right = dwX + m_nCharWidth; + +#if 0 + if (m_bBitmapBackground) { + if (m_bRelativeBackground) { + ::BitBlt(m_hdcConsole, dwX, dwY, m_nCharWidth, m_nCharHeight, m_hdcBackground, m_nX+m_nXBorderSize-m_nBackgroundOffsetX+(int)dwX, m_nY+m_nCaptionSize+m_nYBorderSize-m_nBackgroundOffsetY+(int)dwY, SRCCOPY); + } else { + ::BitBlt(m_hdcConsole, dwX, dwY, m_nCharWidth, m_nCharHeight, m_hdcBackground, dwX, dwY, SRCCOPY); + } + } else { +#endif + ::FillRect(m_hdcConsole, &rect, m_hBkBrush); +// } + + + attrBG = m_pScreenBuffer[dwDestOffset].Attributes >> 4; + + // here we decide how to paint text over the backgound + if (m_arrConsoleColors[attrBG] == m_crConsoleBackground) { + ::SetBkMode(m_hdcConsole, TRANSPARENT); + } else { + ::SetBkMode(m_hdcConsole, OPAQUE); + ::SetBkColor(m_hdcConsole, m_arrConsoleColors[attrBG]); + } + + ::SetTextColor(m_hdcConsole, m_bUseFontColor ? m_crFontColor : m_arrConsoleColors[m_pScreenBuffer[dwDestOffset].Attributes & 0xF]); + ::TextOutW(m_hdcConsole, dwX, dwY, &(m_pScreenBuffer[dwDestOffset].Char.UnicodeChar), 1); + + ::InvalidateRect(m_hWnd, &rect, FALSE); + } + + dwX += m_nCharWidth; + ++dwDestOffset; + ++dwSrcOffset; + } + } + + } else { + + // variable pitch font + if (memcmp(m_pScreenBuffer, m_pScreenBufferNew + dwDestOffset, sizeof(CHAR_INFO)*m_dwRows * m_dwColumns)) { + memcpy(m_pScreenBuffer, m_pScreenBufferNew + dwDestOffset, sizeof(CHAR_INFO)*m_dwRows * m_dwColumns); + + RECT rect; + rect.top = 0; + rect.left = 0; + rect.bottom = m_nClientHeight; + rect.right = m_nClientWidth; + +#if 0 + if (m_bBitmapBackground) { + if (m_bRelativeBackground) { + ::BitBlt(m_hdcConsole, 0, 0, m_nClientWidth, m_nClientHeight, m_hdcBackground, m_nX+m_nXBorderSize-m_nBackgroundOffsetX, m_nY+m_nCaptionSize+m_nYBorderSize-m_nBackgroundOffsetY, SRCCOPY); + } else { + ::BitBlt(m_hdcConsole, 0, 0, m_nClientWidth, m_nClientHeight, m_hdcBackground, 0, 0, SRCCOPY); + } + } else { +#endif + ::FillRect(m_hdcConsole, &rect, m_hBkBrush); +// } + + for (DWORD i = 0; i < m_dwRows; ++i) { + + dwX = m_nInsideBorder; + dwY = i*m_nCharHeight + m_nInsideBorder; + + for (DWORD j = 0; j < m_dwColumns; ++j) { + + attrBG = m_pScreenBuffer[dwDestOffset].Attributes >> 4; + + // here we decide how to paint text over the backgound + if (m_arrConsoleColors[attrBG] == m_crConsoleBackground) { + ::SetBkMode(m_hdcConsole, TRANSPARENT); + } else { + ::SetBkMode(m_hdcConsole, OPAQUE); + ::SetBkColor(m_hdcConsole, m_arrConsoleColors[attrBG]); + } + + ::SetTextColor(m_hdcConsole, m_bUseFontColor ? m_crFontColor : m_arrConsoleColors[m_pScreenBuffer[dwDestOffset].Attributes & 0xF]); + ::TextOutW(m_hdcConsole, dwX, dwY, &(m_pScreenBuffer[dwDestOffset].Char.UnicodeChar), 1); + int nWidth; + ::GetCharWidth32(m_hdcConsole, m_pScreenBuffer[dwDestOffset].Char.UnicodeChar, m_pScreenBuffer[dwDestOffset].Char.UnicodeChar, &nWidth); + dwX += nWidth; + ++dwDestOffset; + } + } + + ::InvalidateRect(m_hWnd, NULL, FALSE); + } + } + + if (m_pCursor) DrawCursor(); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::DrawCursor(BOOL bOnlyCursor) { + + // first, erase old cursor image if needed + if (!bOnlyCursor && m_bCursorVisible) { + RECT rectCursorOld; + DrawCursorBackground(rectCursorOld); + ::InvalidateRect(m_hWnd, &rectCursorOld, FALSE); + } + +#if 0 + // now, see if the cursor is visible... + CONSOLE_CURSOR_INFO cinf; + ::GetConsoleCursorInfo(m_hStdOutFresh, &cinf); + + m_bCursorVisible = cinf.bVisible; +#endif + + // ... and draw it + if (m_bCursorVisible) { +#if 0 + ::GetConsoleScreenBufferInfo(m_hStdOutFresh, &m_csbiCursor); + + if (m_csbiCursor.dwCursorPosition.Y < m_csbiCursor.srWindow.Top || m_csbiCursor.dwCursorPosition.Y > m_csbiCursor.srWindow.Bottom) { + m_bCursorVisible = FALSE; + return; + } + + // set proper cursor offset + m_csbiCursor.dwCursorPosition.Y -= m_csbiCursor.srWindow.Top; +#endif + + RECT rectCursor; + if (!bOnlyCursor) { + DrawCursorBackground(rectCursor); + } else { + GetCursorRect(rectCursor); + } + m_pCursor->Draw(&rectCursor); + ::InvalidateRect(m_hWnd, &rectCursor, FALSE); + } +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +inline void Console::GetCursorRect(RECT& rectCursor) { + + ::ZeroMemory(&rectCursor, sizeof(RECT)); + + if (m_nCharWidth > 0) { + // fixed pitch + + rectCursor.left = m_csbiCursor.dwCursorPosition.X * m_nCharWidth + m_nInsideBorder; + rectCursor.top = m_csbiCursor.dwCursorPosition.Y * m_nCharHeight + m_nInsideBorder; + rectCursor.right = m_csbiCursor.dwCursorPosition.X * m_nCharWidth + m_nCharWidth + m_nInsideBorder; + rectCursor.bottom = m_csbiCursor.dwCursorPosition.Y * m_nCharHeight + m_nCharHeight + m_nInsideBorder; + + } else { + + // variable pitch, we do a little joggling here :-) + RECT rectLine; + int nLastCharWidth; + auto_ptr pszLine(new wchar_t[m_csbiCursor.dwCursorPosition.X + 2]); + ::ZeroMemory(pszLine.get(), (m_csbiCursor.dwCursorPosition.X + 2)*sizeof(wchar_t)); + + for (DWORD i = 0; i <= m_csbiCursor.dwCursorPosition.X; ++i) pszLine.get()[i] = m_pScreenBuffer[m_csbiCursor.dwCursorPosition.Y * m_dwColumns + i].Char.UnicodeChar; + + rectLine.left = rectLine.right = 0; + rectLine.top = rectLine.bottom = m_csbiCursor.dwCursorPosition.Y * m_nCharHeight; + + ::DrawTextW( + m_hdcConsole, + pszLine.get(), + -1, + &rectLine, + DT_CALCRECT); + + if (!::GetCharWidth32( + m_hdcConsole, + pszLine.get()[m_csbiCursor.dwCursorPosition.X], + pszLine.get()[m_csbiCursor.dwCursorPosition.X], + &nLastCharWidth)) { + + return; + } + + rectCursor.left = rectLine.right - (DWORD)nLastCharWidth + m_nInsideBorder; + rectCursor.top = rectLine.top + m_nInsideBorder; + rectCursor.right = rectLine.right + m_nInsideBorder; + rectCursor.bottom = rectLine.bottom + m_nInsideBorder; + } + + rectCursor.top -= m_csbiConsole.srWindow.Top * m_nCharHeight; + rectCursor.bottom -= m_csbiConsole.srWindow.Top * m_nCharHeight; +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +inline void Console::DrawCursorBackground(RECT& rectCursor) { + + GetCursorRect(rectCursor); + + if (m_csbiCursor.dwCursorPosition.Y < m_csbiConsole.srWindow.Top || + m_csbiCursor.dwCursorPosition.Y >= m_csbiConsole.srWindow.Top + m_dwRows) { + return; + } + + DWORD dwOffset = (m_csbiCursor.dwCursorPosition.Y-m_csbiConsole.srWindow.Top)*m_dwColumns + m_csbiCursor.dwCursorPosition.X; + WORD attrBG = m_pScreenBuffer[dwOffset].Attributes >> 4; + + // here we decide how to paint text over the backgound + + if (m_arrConsoleColors[attrBG] == m_crConsoleBackground) { + ::SetBkMode(m_hdcConsole, TRANSPARENT); + } else { + ::SetBkMode(m_hdcConsole, OPAQUE); + ::SetBkColor(m_hdcConsole, m_arrConsoleColors[attrBG]); + } + + ::SetTextColor(m_hdcConsole, m_bUseFontColor ? m_crFontColor : m_arrConsoleColors[m_pScreenBuffer[dwOffset].Attributes & 0xF]); + +#if 0 + if (m_bBitmapBackground) { + if (m_bRelativeBackground) { + ::BitBlt( + m_hdcConsole, + rectCursor.left, + rectCursor.top, + rectCursor.right - rectCursor.left, + rectCursor.bottom - rectCursor.top, + m_hdcBackground, + m_nX+m_nXBorderSize-m_nBackgroundOffsetX + rectCursor.left, + m_nY+m_nCaptionSize+m_nYBorderSize-m_nBackgroundOffsetY + rectCursor.top, + SRCCOPY); + + } else { + ::BitBlt( + m_hdcConsole, + rectCursor.left, + rectCursor.top, + rectCursor.right - rectCursor.left, + rectCursor.bottom - rectCursor.top, + m_hdcBackground, + rectCursor.left, + rectCursor.top, SRCCOPY); + } + } else { +#endif + ::FillRect(m_hdcConsole, &rectCursor, m_hBkBrush); +// } + + ::TextOutW( + m_hdcConsole, + rectCursor.left, + rectCursor.top, + &(m_pScreenBuffer[dwOffset].Char.UnicodeChar), + 1); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::ClearSelection() { + + m_nTextSelection = TEXT_SELECTION_NONE; + m_coordSelOrigin.X = 0; + m_coordSelOrigin.Y = 0; + ::ZeroMemory(&m_rectSelection, sizeof(RECT)); + + RepaintWindow(); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +DWORD Console::GetChangeRate() { + + DWORD dwCount = m_dwRows * m_dwColumns; + DWORD dwChangedPositions = 0; + + for (DWORD i = 0; i < dwCount; ++i) { + if (m_pScreenBuffer[i].Char.UnicodeChar != m_pScreenBufferNew[i].Char.UnicodeChar) ++dwChangedPositions; + } + + return dwChangedPositions*100/dwCount; +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::ShowHideWindow() { + ::ShowWindowAsync(m_hWnd, m_bHideWindow ? SW_HIDE : SW_SHOW); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::ShowHideConsole() { + ::ShowWindow(m_hWndConsole, m_bHideConsole ? SW_HIDE : SW_SHOWNORMAL); + if (!m_bHideConsole) ::SetForegroundWindow(m_hWndConsole); + UpdateHideConsoleMenuItem(); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +#if 0 +void Console::ShowHideConsoleTimeout() { + + ::KillTimer(m_hWnd, TIMER_SHOW_HIDE_CONSOLE); + ShowHideConsole(); +} +#endif + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::ToggleWindowOnTop() { + + if (m_dwCurrentZOrder == m_dwOriginalZOrder) { + m_dwCurrentZOrder = Z_ORDER_ONTOP; + } else { + m_dwCurrentZOrder = m_dwOriginalZOrder; + } + + HWND hwndZ; + switch (m_dwCurrentZOrder) { + case Z_ORDER_REGULAR : hwndZ = HWND_NOTOPMOST; break; + case Z_ORDER_ONTOP : hwndZ = HWND_TOPMOST; break; + case Z_ORDER_ONBOTTOM : hwndZ = HWND_BOTTOM; break; + } + + ::SetWindowPos( + m_hWnd, + hwndZ, + 0, + 0, + 0, + 0, + SWP_SHOWWINDOW | SWP_NOMOVE | SWP_NOSIZE); + + UpdateOnTopMenuItem(); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +BOOL Console::HandleMenuCommand(DWORD dwID) { + + // check if it's one of the main menu commands + switch (dwID) { + +/* + case ID_SHOW_README_FILE: + ShowReadmeFile(); + return FALSE; + + case ID_ABOUT: + About(); + return FALSE; +*/ + + case ID_COPY: + CopyTextToClipboard(); + return FALSE; + + case ID_PASTE: + PasteClipoardText(); + return FALSE; + +#if 0 + case ID_HIDE_CONSOLE: + m_bHideConsole = !m_bHideConsole; + ShowHideConsole(); + return FALSE; + + case ID_EDIT_CONFIG_FILE: + EditConfigFile(); + return FALSE; + + case ID_RELOAD_SETTINGS: + ReloadSettings(); + return FALSE; + + case ID_TOGGLE_ONTOP: + ToggleWindowOnTop(); + return FALSE; +#endif + + case ID_EXIT_CONSOLE: + ::SendMessage(m_hWnd, WM_CLOSE, 0, 0); + return FALSE; + + case SC_MINIMIZE: + if (m_dwTaskbarButton > TASKBAR_BUTTON_NORMAL) { + m_bHideWindow = !m_bHideWindow; + ShowHideWindow(); + ::SetForegroundWindow(m_hWnd); + return FALSE; + } + return TRUE; + } + +#if 0 + // check if it's one of config file submenu items + if ((dwID >= ID_FIRST_XML_FILE) && + (dwID <= ID_LAST_XML_FILE)) { + + TCHAR szFilename[MAX_PATH]; + ::ZeroMemory(szFilename, sizeof(szFilename)); + ::GetMenuString(m_hConfigFilesMenu, dwID, szFilename, MAX_PATH, MF_BYCOMMAND); + m_strConfigFile = tstring(szFilename); + + if (m_dwReloadNewConfig == RELOAD_NEW_CONFIG_PROMPT) { + if (::MessageBox( + m_hWndConsole, + _T("Load new settings?"), + _T("New configuration selected"), + MB_YESNO|MB_ICONQUESTION) == IDYES) { + + ReloadSettings(); + } + } else if (m_dwReloadNewConfig == RELOAD_NEW_CONFIG_YES) { + ReloadSettings(); + } + + return FALSE; + } +#endif + + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::UpdateOnTopMenuItem() { + +#if 0 + ::CheckMenuItem(::GetSubMenu(m_hPopupMenu, 0), ID_TOGGLE_ONTOP, MF_BYCOMMAND | ((m_dwCurrentZOrder == Z_ORDER_ONTOP) ? MF_CHECKED : MF_UNCHECKED)); + ::CheckMenuItem(m_hSysMenu, ID_TOGGLE_ONTOP, MF_BYCOMMAND | ((m_dwCurrentZOrder == Z_ORDER_ONTOP) ? MF_CHECKED : MF_UNCHECKED)); +#endif +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::UpdateHideConsoleMenuItem() { + +#if 0 + ::CheckMenuItem(::GetSubMenu(m_hPopupMenu, 0), ID_HIDE_CONSOLE, MF_BYCOMMAND | (m_bHideConsole ? MF_CHECKED : MF_UNCHECKED)); + ::CheckMenuItem(m_hSysMenu, ID_HIDE_CONSOLE, MF_BYCOMMAND | (m_bHideConsole ? MF_CHECKED : MF_UNCHECKED)); +#endif +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::UpdateConfigFilesSubmenu() { + +#if 0 + // populate m_hConfigFilesMenu + + // first, delete old items + while (::GetMenuItemCount(m_hConfigFilesMenu) != 0) ::DeleteMenu(m_hConfigFilesMenu, 0, MF_BYPOSITION); + + // then, enumerate the files + WIN32_FIND_DATA wfd; + HANDLE hWfd = NULL; + BOOL bMoreFiles = TRUE; + DWORD dwID = ID_FIRST_XML_FILE; + + ::ZeroMemory(&wfd, sizeof(WIN32_FIND_DATA)); + + // create the search mask... + int nBackslashPos = m_strConfigFile.rfind(_TCHAR('\\')); + tstring strConfigFileDir(m_strConfigFile.substr(0, nBackslashPos+1)); + tstring strSearchFileMask(strConfigFileDir + tstring(_T("*.xml"))); + + // ... and enumearate files + hWfd = ::FindFirstFile(strSearchFileMask.c_str(), &wfd); + while ((hWfd != INVALID_HANDLE_VALUE) && bMoreFiles) { + + MENUITEMINFO mii; + TCHAR szFilename[MAX_PATH]; + + _sntprintf(szFilename, MAX_PATH, _T("%s"), (strConfigFileDir + tstring(wfd.cFileName)).c_str()); + + ::ZeroMemory(&mii, sizeof(MENUITEMINFO)); + mii.cbSize = sizeof(MENUITEMINFO); + mii.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE; + mii.fType = MFT_RADIOCHECK | MFT_STRING; + mii.wID = dwID++; + mii.dwTypeData = szFilename; + mii.cch = _tcslen(wfd.cFileName); + + if (_tcsicmp(szFilename, m_strConfigFile.c_str()) == 0) { + mii.fState = MFS_CHECKED; + } else { + mii.fState = MFS_UNCHECKED; + } + + ::InsertMenuItem(m_hConfigFilesMenu, dwID-ID_FIRST_XML_FILE, TRUE, &mii); + + bMoreFiles = ::FindNextFile(hWfd, &wfd); + } + + ::FindClose(hWfd); +#endif +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::CopyTextToClipboard() { + + int nSelX = (m_rectSelection.left - m_nInsideBorder)/m_nCharWidth; + int nSelY = (m_rectSelection.top - m_nInsideBorder)/m_nCharHeight; + int nSelColumns = (m_rectSelection.right-m_rectSelection.left)/m_nCharWidth; + int nSelRows = (m_rectSelection.bottom-m_rectSelection.top)/m_nCharHeight; + + // nothing selected, just return + if ((nSelColumns == 0) || (nSelRows == 0)) { + ClearSelection(); + return; + } + + if (!::OpenClipboard(m_hWnd)) { + ClearSelection(); + return; + } + + ::EmptyClipboard(); + + HGLOBAL hglbData = ::GlobalAlloc(GMEM_MOVEABLE, (nSelColumns+2)*nSelRows*sizeof(TCHAR)); + if (hglbData == NULL) { + ::CloseClipboard(); + ClearSelection(); + return; + } + + // lock the handle and copy the text to the buffer. + wchar_t* pszData = (wchar_t*)::GlobalLock(hglbData); + + { + int i; + for (i = 0; i < nSelRows; ++i) { + for (int j = 0; j < nSelColumns; ++j) { + pszData[i*(nSelColumns+2) + j] = m_pScreenBuffer[(nSelY+i)*m_dwColumns + nSelX + j].Char.UnicodeChar; + } + // at the end of each row we put \r\n (except for the last one where we put \0) + pszData[i*(nSelColumns+2) + nSelColumns] = _TCHAR('\r'); + pszData[i*(nSelColumns+2) + nSelColumns + 1] = _TCHAR('\n'); + } + pszData[(i-1)*(nSelColumns+2) + nSelColumns] = _TCHAR('\x0'); + } + + ::GlobalUnlock(hglbData); + + if (::SetClipboardData(CF_UNICODETEXT, hglbData) == NULL) { + // we need to global-free data only if copying failed + } + ::CloseClipboard(); + // !!! No call to GlobalFree here. Next app that uses clipboard will call EmptyClipboard to free the data + + ClearSelection(); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::PasteClipoardText() { + + if (!IsClipboardFormatAvailable(CF_UNICODETEXT)) return; + + + if (::OpenClipboard(m_hWnd)) { + HANDLE hData = ::GetClipboardData(CF_UNICODETEXT); + + SendTextToConsole((wchar_t*)::GlobalLock(hData)); + + ::GlobalUnlock(hData); + ::CloseClipboard(); + } + +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::ShowReadmeFile() { + + // prepare editor parameters + tstring strParams(m_strConfigEditorParams); + + if (strParams.length() == 0) { + // no params, just use the readme file + strParams = m_strReadmeFile; + } else { + int nPos = strParams.find(_T("%f")); + + if (nPos == tstring::npos) { + // no '%f' in editor params, concatenate readme file name + strParams += _T(" "); + strParams += m_strReadmeFile; + } else { + // replace '%f' with readme file name + strParams = strParams.replace(nPos, 2, m_strReadmeFile); + } + } + + ::ShellExecute(NULL, NULL, m_strConfigEditor.c_str(), strParams.c_str(), NULL, SW_SHOWNORMAL); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// About - shows an about dialog + +void Console::About() +{ + CAboutDlg dlg(m_hWnd); + + dlg.DoModal(); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::SendTextToConsole(const wchar_t *pszText) { + + if (!pszText || (wcslen(pszText) == 0)) return; + + BOOL c_state = m_pCursor->GetState(); + m_pCursor->SetState(FALSE); + DrawCursor(); + + int idx = m_csbiCursor.dwCursorPosition.X + m_csbiCursor.dwCursorPosition.Y * m_dwColumns; + + RECT rectInval; + int cursorX; + int cursorY; + int attr = m_nTextColor + (m_nTextBgColor << 4); + + cursorX = m_csbiCursor.dwCursorPosition.X * m_nCharWidth + m_nInsideBorder; + cursorY = m_csbiCursor.dwCursorPosition.Y * m_nCharHeight + m_nInsideBorder; + rectInval.left = cursorX; + rectInval.top = cursorY; + rectInval.right = cursorX; + rectInval.bottom = cursorY + m_nCharHeight; + + for (; *pszText; pszText++) { + int charWidth; + ::GetCharWidth32( m_hdcConsole, *pszText, *pszText, &charWidth); + if (cursorX + m_nCharWidth > rectInval.right) { + rectInval.right = cursorX + m_nCharWidth; + } + if (cursorX < rectInval.left) { + rectInval.left = cursorX; + } + if (cursorY + m_nCharHeight > rectInval.bottom) { + rectInval.bottom = cursorY + m_nCharHeight; + } + if (cursorY < rectInval.top) { + rectInval.top = cursorY; + } + + if (*pszText == 8) { + if (m_csbiCursor.dwCursorPosition.X) { + m_csbiCursor.dwCursorPosition.X--; + cursorX -= m_nCharWidth; + idx--; + } else if (m_csbiCursor.dwCursorPosition.Y) { + if (m_csbiCursor.dwCursorPosition.Y == m_csbiConsole.srWindow.Top) { + OnVScroll( SB_LINEUP); + } + m_csbiCursor.dwCursorPosition.Y--; + m_csbiCursor.dwCursorPosition.X = m_dwColumns - 1; + cursorX = m_nCharWidth * m_csbiCursor.dwCursorPosition.X; + idx--; + } + } else if (*pszText != '\n' && + *pszText != '\r') { + m_pScreenBufferNew[ idx].Attributes = attr; + m_pScreenBufferNew[ idx].Char.UnicodeChar = *pszText; + idx++; + cursorX += m_nCharWidth; + m_csbiCursor.dwCursorPosition.X++; + } + + if (m_csbiCursor.dwCursorPosition.X >= m_dwColumns || *pszText == '\r' || *pszText == '\n' ) { + m_csbiCursor.dwCursorPosition.X = 0; + cursorX = m_nInsideBorder; + if (*pszText != '\r') { + m_csbiCursor.dwCursorPosition.Y++; + if (m_csbiCursor.dwCursorPosition.Y >= m_dwBufferRows) { + m_csbiCursor.dwCursorPosition.Y--; + idx = m_csbiCursor.dwCursorPosition.X + m_csbiCursor.dwCursorPosition.Y * m_dwColumns; + ::CopyMemory( m_pScreenBufferNew, m_pScreenBufferNew + m_dwColumns, idx * sizeof( CHAR_INFO)); + ::ZeroMemory( m_pScreenBufferNew + idx, m_dwColumns * sizeof( CHAR_INFO)); + } else if (m_csbiCursor.dwCursorPosition.Y == m_csbiConsole.srWindow.Top + m_dwRows) { + OnVScroll( SB_LINEDOWN); + } else { + cursorY += m_nCharHeight; + } + } + idx = m_csbiCursor.dwCursorPosition.X + m_csbiCursor.dwCursorPosition.Y * m_dwColumns; + } + } + + ::InvalidateRect( m_hWnd, &rectInval, TRUE); + ::SetTimer(m_hWnd, TIMER_REPAINT_CHANGE, m_dwChangeRepaintInt, NULL); + + m_pCursor->SetState(c_state); + +#if 0 + HANDLE hStdIn = ::CreateFile(_T("CONIN$"), GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0); + + DWORD dwTextLen = _tcslen(pszText); + DWORD dwTextWritten = 0; + + INPUT_RECORD* pKeyEvents = new INPUT_RECORD[dwTextLen]; + ::ZeroMemory(pKeyEvents, sizeof(INPUT_RECORD)*dwTextLen); + + for (DWORD i = 0; i < dwTextLen; ++i) { + pKeyEvents[i].EventType = KEY_EVENT; + pKeyEvents[i].Event.KeyEvent.bKeyDown = TRUE; + pKeyEvents[i].Event.KeyEvent.wRepeatCount = 1; + pKeyEvents[i].Event.KeyEvent.wVirtualKeyCode = 0; + pKeyEvents[i].Event.KeyEvent.wVirtualScanCode = 0; + pKeyEvents[i].Event.KeyEvent.uChar.UnicodeChar = pszText[i]; + pKeyEvents[i].Event.KeyEvent.dwControlKeyState = 0; + } + ::WriteConsoleInput(hStdIn, pKeyEvents, dwTextLen, &dwTextWritten); + + DEL_ARR(pKeyEvents); + ::CloseHandle(hStdIn); +#endif +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +tstring Console::GetFullFilename(const tstring& strFilename) { + + TCHAR szFilePath[MAX_PATH]; + TCHAR* pszFilename; + + ::ZeroMemory(szFilePath, sizeof(szFilePath)); + ::GetFullPathName(strFilename.c_str(), MAX_PATH, szFilePath, &pszFilename); + + return tstring(szFilePath); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void Console::GetDesktopRect(RECT& rectDesktop) { + +// if (g_bWin2000) { + POINT pt; + if (::GetCursorPos(&pt)) { + MONITORINFO monitorInfo; + monitorInfo.cbSize = sizeof(MONITORINFO); + if (GetMonitorInfo(MonitorFromPoint(pt, MONITOR_DEFAULTTONEAREST), &monitorInfo)) { + rectDesktop = monitorInfo.rcWork; + } + + } else { + rectDesktop.left = ::GetSystemMetrics(SM_XVIRTUALSCREEN); + rectDesktop.top = ::GetSystemMetrics(SM_YVIRTUALSCREEN); + rectDesktop.right = rectDesktop.left + ::GetSystemMetrics(SM_CXVIRTUALSCREEN); + rectDesktop.bottom = rectDesktop.top + ::GetSystemMetrics(SM_CYVIRTUALSCREEN); + } + +#if 0 +} else { + // we keep this for WinNT compatibility + + rectDesktop.left= 0; + rectDesktop.top = 0; + rectDesktop.right = ::GetSystemMetrics(SM_CXSCREEN); + rectDesktop.bottom = ::GetSystemMetrics(SM_CYSCREEN); + + RECT rectTaskbar = {0, 0, 0, 0}; + HWND hWndTaskbar = ::FindWindow(_T("Shell_TrayWnd"), _T("")); + + + if (hWndTaskbar) { + + ::GetWindowRect(hWndTaskbar, &rectTaskbar); + + if ((rectTaskbar.top <= rectDesktop.top) && (rectTaskbar.left <= rectDesktop.left) && (rectTaskbar.right >= rectDesktop.right)) { + // top taskbar + rectDesktop.top += rectTaskbar.bottom; + + } else if ((rectTaskbar.top > rectDesktop.top) && (rectTaskbar.left <= rectDesktop.left)) { + // bottom taskbar + rectDesktop.bottom = rectTaskbar.top; + + } else if ((rectTaskbar.top <= rectDesktop.top) && (rectTaskbar.left > rectDesktop.left)) { + // right taskbar + rectDesktop.right = rectTaskbar.left; + + } else { + // left taskbar + rectDesktop.left += rectTaskbar.right; + } + } + } +#endif +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +LRESULT CALLBACK Console::WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { + + Console *myself = (Console*) ::GetWindowLongPtr( hwnd, GWLP_USERDATA ); + + switch (uMsg) { + case WM_CREATE: + return 0; + + case WM_PAINT: + // paint the window + myself->OnPaint(); + return 0; + + case WM_ERASEBKGND: + return -1; + + case WM_SIZE: + // set the size and position of the window + return 0; + + case WM_CLOSE: +// ::DestroyWindow(myself->m_hWnd); + // Probably want to just hide the window if the X is hit. That way it can continue + // to update on script output + ShowWindow( hwnd, FALSE); + return 0; + + case WM_DESTROY: + myself->OnDestroy(); + return 0; + + case WM_NCDESTROY: + myself->OnNcDestroy(); + return 0; + + case WM_LBUTTONDOWN: + myself->OnLButtonDown((UINT)wParam, MAKEPOINTS(lParam)); + return 0; + + case WM_LBUTTONUP: + myself->OnLButtonUp((UINT)wParam, MAKEPOINTS(lParam)); + return 0; + + case WM_LBUTTONDBLCLK: + myself->OnLButtonDblClick((UINT)wParam, MAKEPOINTS(lParam)); + return 0; + + case WM_RBUTTONUP: + myself->OnRButtonUp((UINT)wParam, MAKEPOINTS(lParam)); + return 0; + + case WM_MBUTTONDOWN: + myself->OnMButtonDown((UINT)wParam, MAKEPOINTS(lParam)); + return 0; + + case WM_MOUSEMOVE: + myself->OnMouseMove((UINT)wParam, MAKEPOINTS(lParam)); + return 0; + + case WM_SETCURSOR: + myself->OnSetCursor(LOWORD(lParam), HIWORD(lParam)); + ::DefWindowProc(myself->m_hWnd, uMsg, wParam, lParam); + return 0; + + case WM_INITMENUPOPUP: + myself->OnInitMenuPopup((HMENU)wParam, LOWORD(lParam), (BOOL)HIWORD(lParam)); + return 0; + + case WM_DROPFILES: + myself->OnDropFiles((HDROP)wParam); + return 0; + + case WM_WINDOWPOSCHANGING: + myself->OnWindowPosChanging((LPWINDOWPOS)lParam); + return 0; + + case WM_ACTIVATEAPP: + myself->OnActivateApp((BOOL)wParam, (DWORD)lParam); + return 0; + +#if 0 + case WM_SYSKEYDOWN: + case WM_SYSKEYUP: + MSG msg; + + ::ZeroMemory(&msg, sizeof(MSG)); + + msg.hwnd = myself->m_hWnd; + msg.message = uMsg; + msg.wParam = wParam; + msg.lParam = lParam; + + ::TranslateMessage(&msg); + ::PostMessage(myself->m_hWndConsole, uMsg, wParam, lParam); + return 0; +#endif + + case WM_CHAR: + myself->OnChar( wParam); + break; + + case WM_KEYDOWN: + case WM_KEYUP: +// case WM_MOUSEWHEEL: +// ::PostMessage(myself->m_hWndConsole, uMsg, wParam, lParam); + return 0; + + + case WM_VSCROLL: + myself->OnVScroll(wParam); + return 0; + + case WM_TIMER: + switch (wParam) { + case TIMER_REPAINT_CHANGE: + case TIMER_REPAINT_MASTER: + myself->OnPaintTimer(); + return 0; + + case CURSOR_TIMER: + myself->OnCursorTimer(); + return 0; + +#if 0 + case TIMER_SHOW_HIDE_CONSOLE: + myself->ShowHideConsoleTimeout(); + return 0; +#endif + + default: + return 1; + } + + case WM_COMMAND: + if (myself->OnCommand(wParam, lParam)) { + return ::DefWindowProc(hwnd, uMsg, wParam, lParam); + } else { + return 0; + } + + case WM_SYSCOMMAND: + if (myself->OnSysCommand(wParam, lParam)) { + return ::DefWindowProc(hwnd, uMsg, wParam, lParam); + } else { + return 0; + } + + case WM_TRAY_NOTIFY: + myself->OnTrayNotify(wParam, lParam); + return 0; + +// case WM_SETTINGCHANGE: +// +// myself->OnWallpaperChanged((TCHAR*)lParam); +// return ::DefWindowProc(hwnd, uMsg, wParam, lParam); + + case WM_INPUTLANGCHANGEREQUEST: + myself->OnInputLangChangeRequest(wParam, lParam); + return ::DefWindowProc(hwnd, uMsg, wParam, lParam); + + // process other messages + default: + return ::DefWindowProc(hwnd, uMsg, wParam, lParam); + } + return 0; +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// MonitorThread - shell activities monitor + +DWORD WINAPI Console::MonitorThreadStatic(LPVOID lpParam) { + return ((Console*)lpParam)->MonitorThread(); +} + +DWORD Console::MonitorThread() { + +// HANDLE arrHandles[] = {m_hConsoleProcess, m_hQuitEvent, m_hStdOut}; + HANDLE arrHandles[] = { m_hStdOut}; + + while (1) { + DWORD dwWait = ::WaitForMultipleObjects(1, arrHandles, FALSE, INFINITE); + +#if 0 + if (dwWait == WAIT_OBJECT_0) { + ::PostMessage(m_hWnd, WM_CLOSE, 0, 0); + break; + } else if (dwWait == WAIT_OBJECT_0 + 1) { + break; + } else if (dwWait == WAIT_OBJECT_0 + 2) { +#endif + AddOutput(); + ::SetTimer(m_hWnd, TIMER_REPAINT_CHANGE, m_dwChangeRepaintInt, NULL); + // we sleep here for a while, to prevent 'flooding' of m_hStdOut events + ::Sleep(m_dwChangeRepaintInt); + ::ResetEvent(m_hStdOut); +// } + } + + return 0; +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +void Console::AddOutput() { + DWORD bytesRead; + wchar_t buf[801]; + ::ReadFile( m_hStdOut, buf, sizeof(buf)/sizeof(wchar_t)-1, &bytesRead, NULL); + if (bytesRead == 0) { + return; + } + buf[bytesRead/sizeof(wchar_t)] = 0; + SendTextToConsole( buf); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +BOOL WINAPI Console::CtrlHandler(DWORD dwCtrlType) { + if ((dwCtrlType == CTRL_C_EVENT) || (dwCtrlType == CTRL_BREAK_EVENT)) { + return TRUE; + } else { + return FALSE; + } +} + +///////////////////////////////////////////////////////////////////////////// + diff --git a/Console/Console.h b/Console/Console.h new file mode 100644 index 00000000..4f85c778 --- /dev/null +++ b/Console/Console.h @@ -0,0 +1,744 @@ +///////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2001-2004 by Marko Bozikovic +// All rights reserved +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Send bug reports, bug fixes, enhancements, requests, flames, etc., and +// I'll try to keep a version up to date. I can be reached as follows: +// marko.bozikovic@alterbox.net +// bozho@kset.org +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Console.h - console class declaration + +#pragma once + +#include +#include + +using namespace std; + +//#include "include/FreeImagePlus.h" + +typedef basic_string tstring; + +#define WM_INPUTREADY WM_USER + 1 + +// tray icon message +#define WM_TRAY_NOTIFY WM_USER + 0x123 + +#define TRAY_ICON_ID 1 + +// timer #defines +#define TIMER_REPAINT_CHANGE 42 // timer that is started after there + // were some changes in the console + +#define TIMER_REPAINT_MASTER 43 // master timer (needed to repaint + // for some DOS programs, can be + // disabled for lower CPU usage) + +#define TIMER_SHOW_HIDE_CONSOLE 100 // used to hide console window when + // starting shell process after a + // defined period of time (some + // shells, like 4NT need console + // window visible during startup for + // all init options to work properly + +// transparency #defines +#define TRANSPARENCY_NONE 0 +#define TRANSPARENCY_ALPHA 1 +#define TRANSPARENCY_COLORKEY 2 +#define TRANSPARENCY_FAKE 3 + +// cusror style #defines +#define CURSOR_STYLE_NONE 0 +#define CURSOR_STYLE_XTERM 1 +#define CURSOR_STYLE_BLOCK 2 +#define CURSOR_STYLE_NBBLOCK 3 +#define CURSOR_STYLE_PULSEBLOCK 4 +#define CURSOR_STYLE_BAR 5 +#define CURSOR_STYLE_CONSOLE 6 +#define CURSOR_STYLE_NBHLINE 7 +#define CURSOR_STYLE_HLINE 8 +#define CURSOR_STYLE_VLINE 9 +#define CURSOR_STYLE_RECT 10 +#define CURSOR_STYLE_NBRECT 11 +#define CURSOR_STYLE_PULSERECT 12 +#define CURSOR_STYLE_FADEBLOCK 13 + +// docking #defines +#define DOCK_NONE 0 +#define DOCK_TOP_LEFT 1 +#define DOCK_TOP_RIGHT 2 +#define DOCK_BOTTOM_RIGHT 3 +#define DOCK_BOTTOM_LEFT 4 + +// Z-order #defines +#define Z_ORDER_REGULAR 0 +#define Z_ORDER_ONTOP 1 +#define Z_ORDER_ONBOTTOM 2 + +// window border defines +#define BORDER_NONE 0 +#define BORDER_REGULAR 1 +#define BORDER_THIN 2 + +// window background style +#define BACKGROUND_STYLE_RESIZE 0 +#define BACKGROUND_STYLE_CENTER 1 +#define BACKGROUND_STYLE_TILE 2 + +// taskbar button defines +#define TASKBAR_BUTTON_NORMAL 0 +#define TASKBAR_BUTTON_HIDE 1 +#define TASKBAR_BUTTON_TRAY 2 + +// new configuration auto-reload defines +#define RELOAD_NEW_CONFIG_PROMPT 0 +#define RELOAD_NEW_CONFIG_YES 1 +#define RELOAD_NEW_CONFIG_NO 2 + +#define TEXT_SELECTION_NONE 0 +#define TEXT_SELECTION_SELECTING 1 +#define TEXT_SELECTION_SELECTED 2 + + +///////////////////////////////////////////////////////////////////////////// +// Console class + +class Console { + public: // ctor/dtor + + Console(LPCTSTR szConfigFile, LPCTSTR szShellCmdLine, LPCTSTR szConsoleTitle, LPCTSTR pszReloadNewConfig); + ~Console(); + + public: + + // creates and shows Console window + BOOL Create(TCHAR* pszConfigPath); + + private: + + //////////////////// + // message handlers + //////////////////// + + //////////////////////////////// + // windows destruction messages + + // destroys GDI stuff and posts a quit message + void OnDestroy(); + // deletes Console object + void OnNcDestroy(); + + + ///////////////////// + // painting messages + + // handles painting from off-screen buffers + void OnPaint(); + + // handles master and 'change' timers + void OnPaintTimer(); + + // handles cursor timer (for animated cursors) + void OnCursorTimer(); + + + ///////////////////////// + // window state messages + + // handles window position changes (for snapping to desktop edges) + void OnWindowPosChanging(WINDOWPOS* lpWndPos); + + // handles activation message (used for setting alpha transparency and cursor states) + void OnActivateApp(BOOL bActivate, DWORD dwFlags); + + // handles vertical scrolling + void OnVScroll(WPARAM wParam); + + // handles keyboard layout change, posts the same message to the windows console window + void OnInputLangChangeRequest(WPARAM wParam, LPARAM lParam); + + + ////////////////// + // mouse messages + + // handles text selection start and window mouse drag start + void OnLButtonDown(UINT uiFlags, POINTS points); + + // handles text selection end, window mouse drag end and text copy + void OnLButtonUp(UINT uiFlags, POINTS points); + + // toggles always on top flag + void OnLButtonDblClick(UINT uiFlags, POINTS points); + + // pops up the Console menu + void OnRButtonUp(UINT uiFlags, POINTS points); + + // pastes text from clipboard + void OnMButtonDown(UINT uiFlags, POINTS points); + + // handles mouse movement for text selection and window mouse drag + void OnMouseMove(UINT uiFlags, POINTS points); + + // handles start/stop mouse drag for window border + void OnSetCursor(WORD wHitTest, WORD wMouseMessage); + + // handles text input + void OnChar(WORD mychar); + + wstring Input; + + ////////////////// + // other messages + + // called before the Console menu or system menu pops up + // (populates config files submenu with filenames) + void OnInitMenuPopup(HMENU hMenu, UINT uiPos, BOOL bSysMenu); + + // handles drag-n-dropped filenames + void OnDropFiles(HDROP hDrop); + + // handles commands from the Console popup menu + BOOL OnCommand(WPARAM wParam, LPARAM lParam); + + // handles commands from the system popup menu + BOOL OnSysCommand(WPARAM wParam, LPARAM lParam); + + // handles tray icon messages + void OnTrayNotify(WPARAM wParam, LPARAM lParam); + + // handles WM_SETTINGCHANGE (we handle only wallpaper changes here) +// void OnWallpaperChanged(const TCHAR* pszFilename); + + + private: + + /////////////////////////////////////////// + // Console window creation/setup functions + /////////////////////////////////////////// + + // gets Console options + BOOL GetOptions(); + + // registers Console window classes + BOOL RegisterWindowClasses(); + + // adds stuff to system and popup menus + BOOL SetupMenus(); + + // creates Console window + BOOL CreateConsoleWindow(); + + // creates new Console font + void CreateNewFont(); + + // creates new background brush + void CreateNewBrush(); + + // creates the cursor + void CreateCursor(); + + // creates offscreen painting buffers + void CreateOffscreenBuffers(); + + // creates background bitmap + void CreateBackgroundBitmap(); + + // called by the ::EnumDisplayMonitors to create background for each display +// static BOOL CALLBACK BackgroundEnumProc(HMONITOR hMonitor, HDC hdcMonitor, LPRECT lprcMonitor, LPARAM dwData); + + // gets character width and height + void GetTextSize(); + + // gets window borders (X, Y and caption sizes) + void GetBordersDimensions(); + + // calculates window and client area sizes + void CalcWindowSize(); + + // sets up window transparency (alpha, color key, fake) +// void SetWindowTransparency(); + + // sets scrollbar stuff + void SetScrollbarStuff(); + + // sets default console colors + void SetDefaultConsoleColors(); + + // sets window size and position + void SetWindowSizeAndPosition(); + + // sets Console's big, small and tray icons + void SetWindowIcons(); + + // sets up traybar icon + BOOL SetTrayIcon(DWORD dwMessage); + + // destroys Console cursor + void DestroyCursor(); + + // opens the configuration file in a text editor + void EditConfigFile(); + + // reloads Console settings + void ReloadSettings(); + + + ///////////////////////////// + // windows console functions + ///////////////////////////// + + // allocates the console and starts the command shell + BOOL StartShellProcess(); + + // refreshes m_hStdOutFresh handle + void RefreshStdOut(); + + // gets a fresh console output + void RefreshScreenBuffer(); + + // sets initial windows console size + void InitConsoleWndSize(DWORD dwColumns); + + // resizes the windows console + void ResizeConsoleWindow(); + + // Allocates the screen buffer + void AllocateBuffer(); + + + ////////////////////// + // painting functions + ////////////////////// + + // repaints the memory hdc + void RepaintWindow(); + + // repaints the memory hdc (paint only changes) + void RepaintWindowChanges(); + + // draws the cursor + void DrawCursor(BOOL bOnlyCursor = FALSE); + + // two helper functions for DrawCursor method + + // returns cursor rectangle + inline void GetCursorRect(RECT& rectCursor); + // draws cursor background and returns the cursor rectangle + inline void DrawCursorBackground(RECT& rectCursor); + + // clears text selection + void ClearSelection(); + + // returns the console text change rate since the last painting + // (using this value we decide whether to repaint entire window + // or just the changes) + DWORD GetChangeRate(); + + + ////////////////////////// + // window state functions + ////////////////////////// + + // shows/hides Console window + void ShowHideWindow(); + + // shows/hides windows console window + void ShowHideConsole(); + + // shows/hides windows console window after a timeout (used during + // shell startup) + void ShowHideConsoleTimeout(); + + // toggles 'always on top' status + void ToggleWindowOnTop(); + + + ////////////////// + // menu functions + ////////////////// + + // called by OnCommand and OnSysCommand to handle menu commands + BOOL HandleMenuCommand(DWORD dwID); + + // updates popup and system menus for 'always on top' status + void UpdateOnTopMenuItem(); + + // updates popup and system menus for 'hide console' status + void UpdateHideConsoleMenuItem(); + + // updates configuration files submenu + void UpdateConfigFilesSubmenu(); + + + /////////////////////// + // clipboard functions + /////////////////////// + + // copies selected text to the clipboard + void CopyTextToClipboard(); + + // pastes text from the clipboard + void PasteClipoardText(); + + ////////////////// + // misc functions + ////////////////// + + // shows Readme.txt file + void ShowReadmeFile(); + + // shows about dialog + void About(); + + // sends text to the windows console + void SendTextToConsole(const wchar_t *pszText); + + // returns the full filename + tstring GetFullFilename(const tstring& strFilename); + + // gets a desktop rectangle + void GetDesktopRect(RECT& rectDesktop); + + // Pulls the text from the stdout or stderr handle (both are the same) and sends it to the console + void AddOutput(); + + + /////////////////////// + // 'gearbox' functions + /////////////////////// + + // Console window procedure + static LRESULT CALLBACK WindowProc(HWND hwnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + + // shell activities monitor + static DWORD WINAPI MonitorThreadStatic(LPVOID lpParam); + DWORD MonitorThread(); + + // CTRL+C, CTRL+BREAK handler + static BOOL WINAPI CtrlHandler(DWORD dwCtrlType); + + + public: // public data + + // Console window handle + HWND m_hWnd; + + // console colors + COLORREF m_arrConsoleColors[16]; + + private: // private data + + // readem filename + tstring m_strReadmeFile; + + BOOL m_bInitializing; + BOOL m_bReloading; + + tstring m_strConfigFile; + tstring m_strConfigEditor; + tstring m_strConfigEditorParams; + + // one of the RELOAD_NEW_CONFIG_* constants + // - specifies relaod behaviour when a new configuration is selected + // (auto reload, don't reload, ask user) + DWORD m_dwReloadNewConfigDefault; + DWORD m_dwReloadNewConfig; + + tstring m_strShell; + tstring m_strShellCmdLine; + + // handle to invisible window - used for hiding the taskbar button in tray and 'hidden' modes + HWND m_hwndInvisParent; + + // memory device context that holds console output image + HDC m_hdcConsole; + // memory device context for an off-screen window buffer (used to + // compose an image from m_hdcConsole and m_hdcSelection if text + // selection is active) + HDC m_hdcWindow; + + // a bitmap used for drawing in the console memory DC + HBITMAP m_hbmpConsole; + HBITMAP m_hbmpConsoleOld; + + // a bitmap used for drawing in the window memory DC + HBITMAP m_hbmpWindow; + HBITMAP m_hbmpWindowOld; + + // brush for painting background + HBRUSH m_hBkBrush; + + // master repaint timer interval (runs independent of changes in the + // console) + DWORD m_dwMasterRepaintInt; + + // change repaint timer interval (when a change occurs, repainting + // will be postponed for this interval) + DWORD m_dwChangeRepaintInt; + + // icon filename + tstring m_strIconFilename; + // program icons + HICON m_hSmallIcon; + HICON m_hBigIcon; + + // popup menu + HMENU m_hPopupMenu; + + // system (taskbar button) menu + HMENU m_hSysMenu; + + // submenu for the XML (config) files + HMENU m_hConfigFilesMenu; + + // set to TRUE if the popup menu is disabled + BOOL m_bPopupMenuDisabled; + + // Console window title variables + // holds the default console title ("console" or the one passed in the cmdline param) + tstring m_strWindowTitleDefault; + // holds the window title (default title, or the one from the config file) + tstring m_strWindowTitle; + // holds the current window title + tstring m_strWindowTitleCurrent; + + // font data + tstring m_strFontName; + DWORD m_dwFontSize; + BOOL m_bBold; + BOOL m_bItalic; + BOOL m_bUseFontColor; + COLORREF m_crFontColor; + HFONT m_hFont; + HFONT m_hFontOld; + + // window X and Y positions + int m_nX; + int m_nY; + + // client area inside border (gives a more 'relaxed' look to windows) + int m_nInsideBorder; + + // window width and height + int m_nWindowWidth; + int m_nWindowHeight; + + // window border sizes + int m_nXBorderSize; + int m_nYBorderSize; + int m_nCaptionSize; + + // client area widht/height + int m_nClientWidth; + int m_nClientHeight; + + // char height and width (used in window repainting) + // Note: width is used only for fixed-pitch fonts to speed up + // repainting + int m_nCharHeight; + int m_nCharWidth; + + // window border type + // 0 - none + // 1 - regular window + // 2 - 1-pixel thin border + DWORD m_dwWindowBorder; + + // scrollbar stuff + BOOL m_bShowScrollbar; + int m_nScrollbarStyle; + COLORREF m_crScrollbarColor; + int m_nScrollbarWidth; + int m_nScrollbarButtonHeight; + int m_nScrollbarThunmbHeight; + + // what to do with the taskbar button + // if the taskbar button is hidden, or placed in the traybar, you + // can't ALT-TAB to console (take care when using with color key + // transparency :-) + // 0 - nothing + // 1 - hide it + // 2 - put icon to traybar + DWORD m_dwTaskbarButton; + + // set to TRUE if the window can be dragged by left-click hold + BOOL m_bMouseDragable; + + // snap distance + int m_nSnapDst; + + // window docking position + // 0 - no dock + // 1 - top left + // 2 - top right + // 3 - bottom right + // 4 - bottom left + DWORD m_dwDocked; + + // window Z-ordering + // 0 - regular + // 1 - always on top + // 2 - always on bottom + DWORD m_dwOriginalZOrder; + DWORD m_dwCurrentZOrder; + + // Win2000/XP transparency + // 0 - none + // 1 - alpha blending + // 2 - colorkey + // 3 - fake transparency + DWORD m_dwTransparency; + + // alpha value for alpha blending (Win2000 and later only!) + BYTE m_byAlpha; + + // alpha value for inactive window + BYTE m_byInactiveAlpha; + + COLORREF m_crBackground; + COLORREF m_crConsoleBackground; + + // this is used for tinting background images and fake transparencies + BOOL m_bTintSet; + BYTE m_byTintOpacity; + BYTE m_byTintR; + BYTE m_byTintG; + BYTE m_byTintB; + + // used when background is an image + BOOL m_bBitmapBackground; + tstring m_strBackgroundFile; + HDC m_hdcBackground; + HBITMAP m_hbmpBackground; + HBITMAP m_hbmpBackgroundOld; + + // background attributes + + // one of BACKGROUND_STYLE_ #defines + DWORD m_dwBackgroundStyle; + // set to true for relative background + BOOL m_bRelativeBackground; + // set to true to extend the background to all monitors + BOOL m_bExtendBackground; + + // offsets used for multiple monitors and relative backgrounds (fake transparency, too) + int m_nBackgroundOffsetX; + int m_nBackgroundOffsetY; + + // used for showing/hiding main window + BOOL m_bHideWindow; + // set to TRUE when the real console is hidden + BOOL m_bHideConsole; + + // timeout used when hiding console window for the first time (some + // shells need console window visible during startup) + DWORD m_dwHideConsoleTimeout; + + // if set to TRUE, Console will be started minimized + BOOL m_bStartMinimized; + + + // cursor style + // 0 - none + // 1 - XTerm + // 2 - block cursor + // 3 - bar cursor + // 4 - console cursor + // 5 - horizontal line + // 6 - vertical line + // 7 - pulse rect + // 8 - fading block + DWORD m_dwCursorStyle; + + COLORREF m_crCursorColor; + + // console screen buffer info for cursor + CONSOLE_SCREEN_BUFFER_INFO m_csbiCursor; + + // wether console cursor is visible or not + BOOL m_bCursorVisible; + + class Cursor* m_pCursor; + + // mouse cursor offset within the window (used for moving the window) + POINT m_mouseCursorOffset; + + ///////////////////// + // console stuff + + // console window handle + HWND m_hWndConsole; + + // console screen buffer info for console repainting + CONSOLE_SCREEN_BUFFER_INFO m_csbiConsole; + + // console stdouts + HANDLE m_hStdOut; + HANDLE m_hStdOutFresh; + + // set when quitting the application + HANDLE m_hQuitEvent; + + // set by monitor thread when detects console process exit + HANDLE m_hConsoleProcess; + + // handle to monitor thread + HANDLE m_hMonitorThread; + + // console rows & columns + DWORD m_dwRows; + DWORD m_dwColumns; + DWORD m_dwBufferRows; + BOOL m_bUseTextBuffer; + + // set to one of TEXT_SELECTION_ #defines + int m_nTextSelection; + + // X Windows style copy-on-select + BOOL m_bCopyOnSelect; + + // Inverse the shift behaviour for selecting and dragging + BOOL m_bInverseShift; + + COORD m_coordSelOrigin; + RECT m_rectSelection; + HDC m_hdcSelection; + HBITMAP m_hbmpSelection; + HBITMAP m_hbmpSelectionOld; + HBRUSH m_hbrushSelection; + + CHAR_INFO* m_pScreenBuffer; + CHAR_INFO* m_pScreenBufferNew; + + DWORD m_nTextColor; + DWORD m_nTextBgColor; + + // Console window class names + static const TCHAR m_szConsoleClass[]; + static const TCHAR m_szHiddenParentClass[]; + + // win console window title + static const tstring m_strWinConsoleTitle; +}; + + + +///////////////////////////////////////////////////////////////////////////// diff --git a/Console/Console.rc b/Console/Console.rc new file mode 100644 index 00000000..09f939d7 --- /dev/null +++ b/Console/Console.rc @@ -0,0 +1,207 @@ +//Microsoft Developer Studio generated resource script. +// +#include "resource.h" + +#define APSTUDIO_READONLY_SYMBOLS +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 2 resource. +// +#include "afxres.h" + +///////////////////////////////////////////////////////////////////////////// +#undef APSTUDIO_READONLY_SYMBOLS + +///////////////////////////////////////////////////////////////////////////// +// Neutral resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEU) +#ifdef _WIN32 +LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL +#pragma code_page(1250) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Dialog +// + +IDD_ABOUT DIALOG DISCARDABLE 0, 0, 146, 87 +STYLE DS_MODALFRAME | DS_NOIDLEMSG | DS_SETFOREGROUND | DS_CENTER | WS_POPUP | + WS_CAPTION | WS_SYSMENU +CAPTION "About Console" +FONT 8, "MS Sans Serif" +BEGIN + DEFPUSHBUTTON "OK",IDOK,48,66,50,14 + LTEXT "Console v1.5",IDC_STATIC,51,11,42,8 + LTEXT "Copyright© 2001-2005 Marko Bozikovic",IDC_STATIC,9,30, + 127,8 + LTEXT "bozho@kset.org",IDC_STATIC,46,45,53,8 +END + + +///////////////////////////////////////////////////////////////////////////// +// +// DESIGNINFO +// + +#ifdef APSTUDIO_INVOKED +GUIDELINES DESIGNINFO DISCARDABLE +BEGIN + IDD_ABOUT, DIALOG + BEGIN + LEFTMARGIN, 7 + RIGHTMARGIN, 139 + TOPMARGIN, 7 + BOTTOMMARGIN, 80 + END +END +#endif // APSTUDIO_INVOKED + +#endif // Neutral resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Neutral (Default) resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_NEUD) +#ifdef _WIN32 +LANGUAGE LANG_NEUTRAL, SUBLANG_DEFAULT +#pragma code_page(1250) +#endif //_WIN32 + +///////////////////////////////////////////////////////////////////////////// +// +// Icon +// + +// Icon with lowest ID value placed first to ensure application icon +// remains consistent on all systems. +//IDI_ICON2 ICON DISCARDABLE "Console.ico" + +///////////////////////////////////////////////////////////////////////////// +// +// Menu +// + +IDR_POPUP_MENU MENU DISCARDABLE +BEGIN + POPUP " " + BEGIN +// MENUITEM "Read&me", ID_SHOW_README_FILE + MENUITEM "&About Console", ID_ABOUT + MENUITEM SEPARATOR + MENUITEM "&Copy", ID_COPY + MENUITEM "&Paste", ID_PASTE + MENUITEM SEPARATOR +// MENUITEM "Always on &top", ID_TOGGLE_ONTOP +// MENUITEM "&Hide console", ID_HIDE_CONSOLE +// MENUITEM SEPARATOR +// MENUITEM "&Select configuration file", ID_SEL_CONFIG_FILE +// MENUITEM "&Edit configuration file", ID_EDIT_CONFIG_FILE +// MENUITEM "&Reload settings", ID_RELOAD_SETTINGS +// MENUITEM SEPARATOR + MENUITEM "E&xit", ID_EXIT_CONSOLE + END +END + +#endif // Neutral (Default) resources +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Croatian resources + +#if !defined(AFX_RESOURCE_DLL) || defined(AFX_TARG_HRV) +#ifdef _WIN32 +LANGUAGE LANG_CROATIAN, SUBLANG_DEFAULT +#pragma code_page(1250) +#endif //_WIN32 + +#ifdef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// TEXTINCLUDE +// + +1 TEXTINCLUDE DISCARDABLE +BEGIN + "resource.h\0" +END + +2 TEXTINCLUDE DISCARDABLE +BEGIN + "#include ""afxres.h""\r\n" + "\0" +END + +3 TEXTINCLUDE DISCARDABLE +BEGIN + "\r\n" + "\0" +END + +#endif // APSTUDIO_INVOKED + + +#ifndef _MAC +///////////////////////////////////////////////////////////////////////////// +// +// Version +// + +VS_VERSION_INFO VERSIONINFO + FILEVERSION 1,5,0,351 + PRODUCTVERSION 1,5,0,351 + FILEFLAGSMASK 0x3fL +#ifdef _DEBUG + FILEFLAGS 0x1L +#else + FILEFLAGS 0x0L +#endif + FILEOS 0x40004L + FILETYPE 0x1L + FILESUBTYPE 0x0L +BEGIN + BLOCK "StringFileInfo" + BEGIN + BLOCK "000004b0" + BEGIN + VALUE "Comments", "A cool console window :-)\0" + VALUE "CompanyName", "Ingenuity Unlimited Ltd.\0" + VALUE "FileDescription", "Console\0" + VALUE "FileVersion", "1.5, Build 351 2005.09.22\0" + VALUE "InternalName", "Console\0" + VALUE "LegalCopyright", "Copyright © 2001-2004 Marko Bozikovic\0" + VALUE "LegalTrademarks", "Copyright © 2001-2004 Marko Bozikovic\0" + VALUE "OriginalFilename", "Console.exe\0" + VALUE "PrivateBuild", "\0" + VALUE "ProductName", "Console\0" + VALUE "ProductVersion", "1.5.00.351\0" + VALUE "SpecialBuild", "\0" + END + END + BLOCK "VarFileInfo" + BEGIN + VALUE "Translation", 0x0, 1200 + END +END + +#endif // !_MAC + +#endif // Croatian resources +///////////////////////////////////////////////////////////////////////////// + + + +#ifndef APSTUDIO_INVOKED +///////////////////////////////////////////////////////////////////////////// +// +// Generated from the TEXTINCLUDE 3 resource. +// + + +///////////////////////////////////////////////////////////////////////////// +#endif // not APSTUDIO_INVOKED + diff --git a/Console/Console_2005Express.vcproj b/Console/Console_2005Express.vcproj new file mode 100644 index 00000000..60967431 --- /dev/null +++ b/Console/Console_2005Express.vcproj @@ -0,0 +1,319 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/Console/Cursors.cpp b/Console/Cursors.cpp new file mode 100644 index 00000000..ad84e462 --- /dev/null +++ b/Console/Cursors.cpp @@ -0,0 +1,842 @@ +///////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2001-2004 by Marko Bozikovic +// All rights reserved +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Send bug reports, bug fixes, enhancements, requests, flames, etc., and +// I'll try to keep a version up to date. I can be reached as follows: +// marko.bozikovic@alterbox.net +// bozho@kset.org +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Cursors.h - cursor classes + +//#include "stdafx.h" +#include +#include +#include "Cursors.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + + +///////////////////////////////////////////////////////////////////////////// +// XTermCursor + +XTermCursor::XTermCursor(HWND hwndConsole, HDC hdcWindow, COLORREF crCursorColor) +: Cursor(hwndConsole, hdcWindow, crCursorColor) +, m_hActiveBrush(::CreateSolidBrush(crCursorColor)) +, m_hInactiveBrush(::CreateSolidBrush(crCursorColor)) +{ +} + +XTermCursor::~XTermCursor() { + + ::DeleteObject(m_hActiveBrush); + ::DeleteObject(m_hInactiveBrush); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void XTermCursor::Draw(LPRECT pRect) { + + if (m_bActive) { + ::FillRect(m_hdcWindow, pRect, m_hActiveBrush); + } else { + ::FrameRect(m_hdcWindow, pRect, m_hInactiveBrush); + } +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void XTermCursor::PrepareNext() { + +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// BlockCursor + +BlockCursor::BlockCursor(HWND hwndParent, HDC hdcWindow, COLORREF crCursorColor) +: Cursor(hwndParent, hdcWindow, crCursorColor) +, m_hActiveBrush(::CreateSolidBrush(crCursorColor)) +, m_bVisible(TRUE) +{ + m_uiTimer = ::SetTimer(hwndParent, CURSOR_TIMER, 750, NULL); +} + +BlockCursor::~BlockCursor() { + + if (m_uiTimer) ::KillTimer(m_hwndParent, m_uiTimer); + ::DeleteObject(m_hActiveBrush); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void BlockCursor::Draw(LPRECT pRect) { + + if (m_bActive && m_bVisible) { + + ::FillRect(m_hdcWindow, pRect, m_hActiveBrush); + } +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void BlockCursor::PrepareNext() { + + m_bVisible = !m_bVisible; +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// NBBlockCursor + +NBBlockCursor::NBBlockCursor(HWND hwndParent, HDC hdcWindow, COLORREF crCursorColor) +: Cursor(hwndParent, hdcWindow, crCursorColor) +, m_hActiveBrush(::CreateSolidBrush(crCursorColor)) +{ +} + +NBBlockCursor::~NBBlockCursor() { + + ::DeleteObject(m_hActiveBrush); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void NBBlockCursor::Draw(LPRECT pRect) { + + ::FillRect(m_hdcWindow, pRect, m_hActiveBrush); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void NBBlockCursor::PrepareNext() { +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// PulseBlockCursor + +PulseBlockCursor::PulseBlockCursor(HWND hwndParent, HDC hdcWindow, COLORREF crCursorColor) +: Cursor(hwndParent, hdcWindow, crCursorColor) +, m_hActiveBrush(::CreateSolidBrush(crCursorColor)) +, m_nSize(0) +, m_nMaxSize(0) +, m_nStep(0) +{ + ::ZeroMemory(&m_rect, sizeof(RECT)); + m_uiTimer = ::SetTimer(hwndParent, CURSOR_TIMER, 100, NULL); +} + +PulseBlockCursor::~PulseBlockCursor() { + + if (m_uiTimer) ::KillTimer(m_hwndParent, m_uiTimer); + ::DeleteObject(m_hActiveBrush); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void PulseBlockCursor::Draw(LPRECT pRect) { + + // this is called only once, to set the size of the cursor + if (m_nMaxSize == 0) { + if ((pRect->right - pRect->left) < (pRect->bottom - pRect->top)) { + m_nMaxSize = (pRect->right - pRect->left) >> 1; + } else { + m_nMaxSize = (pRect->bottom - pRect->top) >> 1; + } + } + + if (m_bActive) { + RECT rect; + ::CopyMemory(&rect, pRect, sizeof(RECT)); + rect.left += m_nSize; + rect.top += m_nSize; + rect.right -= m_nSize; + rect.bottom -= m_nSize; + ::FillRect(m_hdcWindow, &rect, m_hActiveBrush); + } +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void PulseBlockCursor::PrepareNext() { + + if (m_nSize == 0) { + m_nStep = 1; + } else if (m_nSize == m_nMaxSize) { + m_nStep = -1; + } + + m_nSize += m_nStep; +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// BarCursor + +BarCursor::BarCursor(HWND hwndParent, HDC hdcWindow, COLORREF crCursorColor) +: Cursor(hwndParent, hdcWindow, crCursorColor) +, m_hPen(::CreatePen(PS_SOLID, 1, crCursorColor)) +, m_bVisible(TRUE) +{ + m_uiTimer = ::SetTimer(hwndParent, CURSOR_TIMER, 750, NULL); +} + +BarCursor::~BarCursor() { + + if (m_uiTimer) ::KillTimer(m_hwndParent, m_uiTimer); + + ::DeleteObject(m_hPen); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void BarCursor::Draw(LPRECT pRect) { + + if (m_bActive && m_bVisible) { + HPEN hOldPen = (HPEN)::SelectObject(m_hdcWindow, m_hPen); + ::MoveToEx(m_hdcWindow, pRect->left, pRect->top, NULL); + ::LineTo(m_hdcWindow, pRect->left, pRect->bottom); + ::SelectObject(m_hdcWindow, hOldPen); + } +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void BarCursor::PrepareNext() { + + m_bVisible = !m_bVisible; +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// ConsoleCursor + +ConsoleCursor::ConsoleCursor(HWND hwndParent, HDC hdcWindow, COLORREF crCursorColor) +: Cursor(hwndParent, hdcWindow, crCursorColor) +, m_hStdOut(::CreateFile(_T("CONOUT$"), GENERIC_WRITE | GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE, NULL, OPEN_EXISTING, 0, 0)) +, m_hActiveBrush(::CreateSolidBrush(crCursorColor)) +, m_bVisible(TRUE) +{ + m_uiTimer = ::SetTimer(hwndParent, CURSOR_TIMER, 750, NULL); +} + +ConsoleCursor::~ConsoleCursor() { + + if (m_uiTimer) ::KillTimer(m_hwndParent, m_uiTimer); + ::DeleteObject(m_hActiveBrush); + ::CloseHandle(m_hStdOut); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void ConsoleCursor::Draw(LPRECT pRect) { + + RECT rect; + + ::CopyMemory(&rect, pRect, sizeof(RECT)); + + if (m_bActive && m_bVisible) { + +#if 0 + CONSOLE_CURSOR_INFO csi; + ::GetConsoleCursorInfo(m_hStdOut, &csi); + rect.top += (rect.bottom - rect.top) * (100-csi.dwSize)/100; +#else + rect.top += (rect.bottom - rect.top) * 80 / 100; +#endif + + ::FillRect(m_hdcWindow, &rect, m_hActiveBrush); + } +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void ConsoleCursor::PrepareNext() { + + m_bVisible = !m_bVisible; +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// NBHLineCursor + +NBHLineCursor::NBHLineCursor(HWND hwndParent, HDC hdcWindow, COLORREF crCursorColor) +: Cursor(hwndParent, hdcWindow, crCursorColor) +, m_hPen(::CreatePen(PS_SOLID, 1, crCursorColor)) +{ +} + +NBHLineCursor::~NBHLineCursor() { + + ::DeleteObject(m_hPen); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void NBHLineCursor::Draw(LPRECT pRect) { + + HPEN hOldPen = (HPEN)::SelectObject(m_hdcWindow, m_hPen); + ::MoveToEx(m_hdcWindow, pRect->left, pRect->bottom-1, NULL); + ::LineTo(m_hdcWindow, pRect->right, pRect->bottom-1); + ::SelectObject(m_hdcWindow, hOldPen); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void NBHLineCursor::PrepareNext() { + +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// HLineCursor + +HLineCursor::HLineCursor(HWND hwndParent, HDC hdcWindow, COLORREF crCursorColor) +: Cursor(hwndParent, hdcWindow, crCursorColor) +, m_hPen(::CreatePen(PS_SOLID, 1, crCursorColor)) +, m_nSize(0) +, m_nPosition(0) +, m_nStep(0) +{ + m_uiTimer = ::SetTimer(hwndParent, CURSOR_TIMER, 100, NULL); +} + +HLineCursor::~HLineCursor() { + + if (m_uiTimer) ::KillTimer(m_hwndParent, m_uiTimer); + + ::DeleteObject(m_hPen); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void HLineCursor::Draw(LPRECT pRect) { + + // this is called only once, to set the size of the cursor + if (m_nSize != (pRect->bottom - pRect->top - 1)) { + m_nSize = pRect->bottom - pRect->top - 1; + m_nPosition = 0; + m_nStep = 1; + } + + if (m_bActive) { + HPEN hOldPen = (HPEN)::SelectObject(m_hdcWindow, m_hPen); + ::MoveToEx(m_hdcWindow, pRect->left, pRect->top + m_nPosition, NULL); + ::LineTo(m_hdcWindow, pRect->right, pRect->top + m_nPosition); + ::SelectObject(m_hdcWindow, hOldPen); + } +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void HLineCursor::PrepareNext() { + + if (m_nPosition == 0) { + m_nStep = 1; + } else if (m_nPosition == m_nSize) { + m_nStep = -1; + } + + m_nPosition += m_nStep; +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// VLineCursor + +VLineCursor::VLineCursor(HWND hwndParent, HDC hdcWindow, COLORREF crCursorColor) +: Cursor(hwndParent, hdcWindow, crCursorColor) +, m_hPen(::CreatePen(PS_SOLID, 1, crCursorColor)) +, m_nSize(0) +, m_nPosition(0) +, m_nStep(0) +{ + m_uiTimer = ::SetTimer(hwndParent, CURSOR_TIMER, 100, NULL); +} + +VLineCursor::~VLineCursor() { + + if (m_uiTimer) ::KillTimer(m_hwndParent, m_uiTimer); + + ::DeleteObject(m_hPen); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void VLineCursor::Draw(LPRECT pRect) { + + // this is called only once, to set the size of the cursor + if (m_nSize != (pRect->right - pRect->left - 1)) { + m_nSize = pRect->right - pRect->left - 1; + m_nPosition = 0; + m_nStep = 1; + } + + if (m_bActive) { + HPEN hOldPen = (HPEN)::SelectObject(m_hdcWindow, m_hPen); + ::MoveToEx(m_hdcWindow, pRect->left + m_nPosition, pRect->top, NULL); + ::LineTo(m_hdcWindow, pRect->left + m_nPosition, pRect->bottom); + ::SelectObject(m_hdcWindow, hOldPen); + } +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void VLineCursor::PrepareNext() { + + if (m_nPosition == 0) { + m_nStep = 1; + } else if (m_nPosition == m_nSize) { + m_nStep = -1; + } + + m_nPosition += m_nStep; +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// RectCursor + +RectCursor::RectCursor(HWND hwndParent, HDC hdcWindow, COLORREF crCursorColor) +: Cursor(hwndParent, hdcWindow, crCursorColor) +, m_hActiveBrush(::CreateSolidBrush(crCursorColor)) +, m_bVisible(TRUE) +{ + m_uiTimer = ::SetTimer(hwndParent, CURSOR_TIMER, 750, NULL); +} + +RectCursor::~RectCursor() { + + if (m_uiTimer) ::KillTimer(m_hwndParent, m_uiTimer); + ::DeleteObject(m_hActiveBrush); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void RectCursor::Draw(LPRECT pRect) { + + if (m_bActive && m_bVisible) { + + ::FrameRect(m_hdcWindow, pRect, m_hActiveBrush); + } +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void RectCursor::PrepareNext() { + + m_bVisible = !m_bVisible; +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// NBRectCursor + +NBRectCursor::NBRectCursor(HWND hwndParent, HDC hdcWindow, COLORREF crCursorColor) +: Cursor(hwndParent, hdcWindow, crCursorColor) +, m_hActiveBrush(::CreateSolidBrush(crCursorColor)) +{ +} + +NBRectCursor::~NBRectCursor() { + + ::DeleteObject(m_hActiveBrush); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void NBRectCursor::Draw(LPRECT pRect) { + + ::FrameRect(m_hdcWindow, pRect, m_hActiveBrush); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void NBRectCursor::PrepareNext() { +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// PulseRectCursor + +PulseRectCursor::PulseRectCursor(HWND hwndParent, HDC hdcWindow, COLORREF crCursorColor) +: Cursor(hwndParent, hdcWindow, crCursorColor) +, m_hActiveBrush(::CreateSolidBrush(crCursorColor)) +, m_nSize(0) +, m_nMaxSize(0) +, m_nStep(0) +{ + ::ZeroMemory(&m_rect, sizeof(RECT)); + m_uiTimer = ::SetTimer(hwndParent, CURSOR_TIMER, 100, NULL); +} + +PulseRectCursor::~PulseRectCursor() { + + if (m_uiTimer) ::KillTimer(m_hwndParent, m_uiTimer); + ::DeleteObject(m_hActiveBrush); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void PulseRectCursor::Draw(LPRECT pRect) { + + // this is called only once, to set the size of the cursor + if (m_nMaxSize == 0) { + if ((pRect->right - pRect->left) < (pRect->bottom - pRect->top)) { + m_nMaxSize = (pRect->right - pRect->left) >> 1; + } else { + m_nMaxSize = (pRect->bottom - pRect->top) >> 1; + } + } + + if (m_bActive) { + RECT rect; + ::CopyMemory(&rect, pRect, sizeof(RECT)); + rect.left += m_nSize; + rect.top += m_nSize; + rect.right -= m_nSize; + rect.bottom -= m_nSize; + ::FrameRect(m_hdcWindow, &rect, m_hActiveBrush); + } +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void PulseRectCursor::PrepareNext() { + + if (m_nSize == 0) { + m_nStep = 1; + } else if (m_nSize == m_nMaxSize) { + m_nStep = -1; + } + + m_nSize += m_nStep; +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// FadeBlockCursor + +FadeBlockCursor::FadeBlockCursor(HWND hwndParent, HDC hdcWindow, COLORREF crCursorColor, COLORREF crBkColor) +: Cursor(hwndParent, hdcWindow, crCursorColor) +, m_crCursorColor(crCursorColor) +, m_nStep(1) +, m_crBkColor(crBkColor) +, m_nIndex(0) +, m_hUser32(NULL) +, m_hMemDC(NULL) +{ + m_uiTimer = ::SetTimer(hwndParent, CURSOR_TIMER, 35, NULL); + +#if 0 + if (g_bWin2000) { + // on Win2000 we use real alpha blending + + // create a reasonable-sized bitmap, since AlphaBlt resizes + // destination rect if needed, and we don't need to redraw the mem DC + // each time + m_nBmpWidth = BLEND_BMP_WIDTH; + m_nBmpHeight= BLEND_BMP_HEIGHT; + m_hMemDC = ::CreateCompatibleDC(hdcWindow); + m_hBmp = ::CreateCompatibleBitmap(hdcWindow, m_nBmpWidth, m_nBmpHeight); + m_hBmpOld = (HBITMAP)::SelectObject(m_hMemDC, m_hBmp); + + HBRUSH hBrush= ::CreateSolidBrush(m_crCursorColor); + RECT rect; + rect.left = 0; + rect.top = 0; + rect.right = m_nBmpWidth; + rect.bottom = m_nBmpHeight; + + ::FillRect(m_hMemDC, &rect, hBrush); + ::DeleteObject(hBrush); + + m_nStep = -ALPHA_STEP; + + m_bfn.BlendOp = AC_SRC_OVER; + m_bfn.BlendFlags = 0; + m_bfn.SourceConstantAlpha = 255; + m_bfn.AlphaFormat = 0; + + } else { +#endif + FakeBlend(); +// } +} + +FadeBlockCursor::~FadeBlockCursor() { + + if (m_uiTimer) ::KillTimer(m_hwndParent, m_uiTimer); + +#if 0 + if (g_bWin2000) { + ::SelectObject(m_hMemDC, m_hBmpOld); + ::DeleteObject(m_hBmp); + ::DeleteDC(m_hMemDC); + } +#endif +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void FadeBlockCursor::Draw(LPRECT pRect) { + +#if 0 + if (g_bWin2000) { + + g_pfnAlphaBlend( + m_hdcWindow, + pRect->left, + pRect->top, + pRect->right - pRect->left, + pRect->bottom - pRect->top, + m_hMemDC, + 0, + 0, + BLEND_BMP_WIDTH, + BLEND_BMP_HEIGHT, + m_bfn); + + } else { +#endif + + HBRUSH hBrush = ::CreateSolidBrush(m_arrColors[m_nIndex]); + ::FillRect(m_hdcWindow, pRect, hBrush); + ::DeleteObject(hBrush); +// } +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// + +void FadeBlockCursor::PrepareNext() { +#if 0 + if (g_bWin2000){ + if (m_bfn.SourceConstantAlpha < ALPHA_STEP) { + m_nStep = ALPHA_STEP; + } else if ((DWORD)m_bfn.SourceConstantAlpha + ALPHA_STEP > 255) { + m_nStep = -ALPHA_STEP; + } + + m_bfn.SourceConstantAlpha += m_nStep; + } else { +#endif + if (m_nIndex == 0) { + m_nStep = 1; + } else if (m_nIndex == (FADE_STEPS)) { + m_nStep = -1; + } + m_nIndex += m_nStep; +// } +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// This function is used to create a fake blending for WinNT (uuseful only +// for solid background, though) + +void FadeBlockCursor::FakeBlend() { + + int nDeltaR = ((GetRValue(m_crCursorColor) - GetRValue(m_crBkColor)) << 8) / FADE_STEPS; + int nDeltaG = ((GetGValue(m_crCursorColor) - GetGValue(m_crBkColor)) << 8) / FADE_STEPS; + int nDeltaB = ((GetBValue(m_crCursorColor) - GetBValue(m_crBkColor)) << 8) / FADE_STEPS; + + for (int i = 0; i < FADE_STEPS; ++i) { + m_arrColors[i] = RGB(GetRValue(m_crCursorColor) - (nDeltaR*i >> 8), GetGValue(m_crCursorColor) - (nDeltaG*i >> 8), GetBValue(m_crCursorColor) - (nDeltaB*i >> 8)); + } + + m_arrColors[FADE_STEPS] = m_crBkColor; +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + diff --git a/Console/Cursors.h b/Console/Cursors.h new file mode 100644 index 00000000..93e05453 --- /dev/null +++ b/Console/Cursors.h @@ -0,0 +1,345 @@ +///////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2001-2004 by Marko Bozikovic +// All rights reserved +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Send bug reports, bug fixes, enhancements, requests, flames, etc., and +// I'll try to keep a version up to date. I can be reached as follows: +// marko.bozikovic@alterbox.net +// bozho@kset.org +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Cursors.h - cursor classes + +#pragma once + +#define CURSOR_TIMER 45 + +extern BOOL g_bWin2000; + +///////////////////////////////////////////////////////////////////////////// +// A base class for all the cursors + +class Cursor { + public: + Cursor(HWND hwndParent, HDC hdcWindow, COLORREF crCursorColor) + : m_hwndParent(hwndParent) + , m_hdcWindow(hdcWindow) + , m_crCursorColor(crCursorColor) + , m_bActive(TRUE) + {}; + + virtual ~Cursor(){}; + + void SetState(BOOL bActive) {m_bActive = bActive;}; + BOOL GetState() { return m_bActive; } + + // used to draw current frame of the cursor + virtual void Draw(LPRECT pRect) = 0; + // used to prepare the next frame of cursor animation + virtual void PrepareNext() = 0; + + protected: + + HWND m_hwndParent; + HDC m_hdcWindow; + COLORREF m_crCursorColor; + + BOOL m_bActive; + UINT m_uiTimer; +}; + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// XTermCursor + +class XTermCursor : public Cursor { + public: + XTermCursor(HWND hwndParent, HDC hdcWindow, COLORREF crCursorColor); + ~XTermCursor(); + + void Draw(LPRECT pRect); + void PrepareNext(); + + private: + HBRUSH m_hActiveBrush; + HBRUSH m_hInactiveBrush; +}; + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// BlockCursor + +class BlockCursor : public Cursor { + public: + BlockCursor(HWND hwndParent, HDC hdcWindow, COLORREF crCursorColor); + ~BlockCursor(); + + void Draw(LPRECT pRect); + void PrepareNext(); + + private: + HBRUSH m_hActiveBrush; + BOOL m_bVisible; +}; + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// NBBlockCursor + +class NBBlockCursor : public Cursor { + public: + NBBlockCursor(HWND hwndParent, HDC hdcWindow, COLORREF crCursorColor); + ~NBBlockCursor(); + + void Draw(LPRECT pRect); + void PrepareNext(); + + private: + HBRUSH m_hActiveBrush; +}; + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// PulseBlockCursor + +class PulseBlockCursor : public Cursor { + public: + PulseBlockCursor(HWND hwndParent, HDC hdcWindow, COLORREF crCursorColor); + ~PulseBlockCursor(); + + void Draw(LPRECT pRect); + void PrepareNext(); + + private: + HBRUSH m_hActiveBrush; + RECT m_rect; + int m_nSize; + int m_nMaxSize; + int m_nStep; +}; + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// BarCursor + +class BarCursor : public Cursor { + public: + BarCursor(HWND hwndParent, HDC hdcWindow, COLORREF crCursorColor); + ~BarCursor(); + + void Draw(LPRECT pRect); + void PrepareNext(); + + private: + HPEN m_hPen; + BOOL m_bVisible; +}; + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// ConsoleCursor + +class ConsoleCursor : public Cursor { + public: + ConsoleCursor(HWND hwndParent, HDC hdcWindow, COLORREF crCursorColor); + ~ConsoleCursor(); + + void Draw(LPRECT pRect); + void PrepareNext(); + + private: + HANDLE m_hStdOut; + HBRUSH m_hActiveBrush; + BOOL m_bVisible; +}; + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// NBHLineCursor + +class NBHLineCursor : public Cursor { +public: + NBHLineCursor(HWND hwndParent, HDC hdcWindow, COLORREF crCursorColor); + ~NBHLineCursor(); + + void Draw(LPRECT pRect); + void PrepareNext(); + +private: + HPEN m_hPen; +}; + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// HLineCursor + +class HLineCursor : public Cursor { + public: + HLineCursor(HWND hwndParent, HDC hdcWindow, COLORREF crCursorColor); + ~HLineCursor(); + + void Draw(LPRECT pRect); + void PrepareNext(); + + private: + HPEN m_hPen; + int m_nSize; + int m_nPosition; + int m_nStep; +}; + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// VLineCursor + +class VLineCursor : public Cursor { + public: + VLineCursor(HWND hwndParent, HDC hdcWindow, COLORREF crCursorColor); + ~VLineCursor(); + + void Draw(LPRECT pRect); + void PrepareNext(); + + private: + HPEN m_hPen; + int m_nSize; + int m_nPosition; + int m_nStep; +}; + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// RectCursor + +class RectCursor : public Cursor { + public: + RectCursor(HWND hwndParent, HDC hdcWindow, COLORREF crCursorColor); + ~RectCursor(); + + void Draw(LPRECT pRect); + void PrepareNext(); + + private: + HBRUSH m_hActiveBrush; + BOOL m_bVisible; +}; + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// NBRectCursor + +class NBRectCursor : public Cursor { + public: + NBRectCursor(HWND hwndParent, HDC hdcWindow, COLORREF crCursorColor); + ~NBRectCursor(); + + void Draw(LPRECT pRect); + void PrepareNext(); + + private: + HBRUSH m_hActiveBrush; +}; + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// PulseRectCursor + +class PulseRectCursor : public Cursor { + public: + PulseRectCursor(HWND hwndParent, HDC hdcWindow, COLORREF crCursorColor); + ~PulseRectCursor(); + + void Draw(LPRECT pRect); + void PrepareNext(); + + private: + HBRUSH m_hActiveBrush; + RECT m_rect; + int m_nSize; + int m_nMaxSize; + int m_nStep; +}; + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// FadeBlockCursor + +#define FADE_STEPS 20 +#define ALPHA_STEP 12 + +#define BLEND_BMP_WIDTH 10 +#define BLEND_BMP_HEIGHT 20 + +class FadeBlockCursor : public Cursor { + public: + FadeBlockCursor(HWND hwndParent, HDC hdcWindow, COLORREF crCursorColor, COLORREF crBkColor); + ~FadeBlockCursor(); + + void Draw(LPRECT pRect); + void PrepareNext(); + + private: + + void FakeBlend(); + + COLORREF m_crCursorColor; + int m_nStep; + + // used under WinNT 4.0 + COLORREF m_crBkColor; + COLORREF m_arrColors[FADE_STEPS+1]; + int m_nIndex; + + // these are used under Win2000 only + HMODULE m_hUser32; + BLENDFUNCTION m_bfn; + HDC m_hMemDC; + HBITMAP m_hBmp; + HBITMAP m_hBmpOld; + int m_nBmpWidth; + int m_nBmpHeight; +}; + +///////////////////////////////////////////////////////////////////////////// diff --git a/Console/Dialogs.cpp b/Console/Dialogs.cpp new file mode 100644 index 00000000..86180fa4 --- /dev/null +++ b/Console/Dialogs.cpp @@ -0,0 +1,133 @@ +///////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2001-2004 by Marko Bozikovic +// All rights reserved +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Send bug reports, bug fixes, enhancements, requests, flames, etc., and +// I'll try to keep a version up to date. I can be reached as follows: +// marko.bozikovic@alterbox.net +// bozho@kset.org +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Dialogs.h - dialog classes +// +// About dialog class, etc... + +//#include "stdafx.h" +#include + +#include "resource.h" +#include "Console.h" +#include "Dialogs.h" + +#ifdef _DEBUG +#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +#endif + +extern HINSTANCE ghInstance; + +///////////////////////////////////////////////////////////////////////////// +// About dialog class + +///////////////////////////////////////////////////////////////////////////// +// Ctor/Dtor + +CAboutDlg::CAboutDlg(HWND hwndParent) + : m_hWndParent(hwndParent) +{ +} + + +CAboutDlg::~CAboutDlg() +{ +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// public methods + +///////////////////////////////////////////////////////////////////////////// +// DoModal - shows About dialog + +BOOL CAboutDlg::DoModal() +{ + ::DialogBox( + ghInstance, + MAKEINTRESOURCE(IDD_ABOUT), + m_hWndParent, + CAboutDlg::DialogProc); + + return TRUE; +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// message handlers + + +///////////////////////////////////////////////////////////////////////////// +// DialogProc - dialog window procedure + +int CALLBACK CAboutDlg::DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) { + case WM_INITDIALOG: + return TRUE; + + case WM_COMMAND: + switch (LOWORD(wParam)) { + case IDOK: + case IDCANCEL: + if (HIWORD(wParam) == BN_CLICKED) { + ::EndDialog(hwndDlg, MB_OK); + return TRUE; + } + break; + } + } + + return 0; +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + + + + + + + + + + + + + + + diff --git a/Console/Dialogs.h b/Console/Dialogs.h new file mode 100644 index 00000000..eaff697c --- /dev/null +++ b/Console/Dialogs.h @@ -0,0 +1,64 @@ +///////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2001-2004 by Marko Bozikovic +// All rights reserved +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Send bug reports, bug fixes, enhancements, requests, flames, etc., and +// I'll try to keep a version up to date. I can be reached as follows: +// marko.bozikovic@alterbox.net +// bozho@kset.org +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Dialogs.h - dialog classes +// +// About dialog class, etc... + +#pragma once + +///////////////////////////////////////////////////////////////////////////// +// About dialog class + +class CAboutDlg { + public: + CAboutDlg(HWND hwndParent); + ~CAboutDlg(); + + // public methods + public: + + // shows About dialog + BOOL DoModal(); + + // public data + public: + // parent window handle + HWND m_hWndParent; + + // private methods + private: + ///////////////////////// + // message handlers + + // dialog window procedure + static int CALLBACK DialogProc(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam ); + + // private data + private: +}; + +///////////////////////////////////////////////////////////////////////////// diff --git a/Console/FileStream.cpp b/Console/FileStream.cpp new file mode 100644 index 00000000..64a10bb3 --- /dev/null +++ b/Console/FileStream.cpp @@ -0,0 +1,259 @@ +///////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2001-2004 by Marko Bozikovic +// All rights reserved +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Send bug reports, bug fixes, enhancements, requests, flames, etc., and +// I'll try to keep a version up to date. I can be reached as follows: +// marko.bozikovic@alterbox.net +// bozho@kset.org +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// FileStream.cpp - implementation of IStream interface on any file +// (not strictly COM, I'm faking it here a bit :-) +// + +#undef CINTERFACE +#include "builddefines.h" + +//#include "stdafx.h" +//#include +#include +#include +#include "FileStream.h" + +//#ifdef _DEBUG +//#define new DEBUG_NEW +#undef THIS_FILE +static char THIS_FILE[] = __FILE__; +//#endif + +///////////////////////////////////////////////////////////////////////////// +// CreateFileStream - opens/creates a file and returns an IStream interface + +HRESULT CreateFileStream( + LPCTSTR lpFileName, // file name + DWORD dwDesiredAccess, // access mode + DWORD dwShareMode, // share mode + LPSECURITY_ATTRIBUTES lpSecurityAttributes, // SD + DWORD dwCreationDisposition, // how to create + DWORD dwFlagsAndAttributes, // file attributes + HANDLE hTemplateFile, // handle to template file + IStream** ppStream // pointer to IStream interface +) +{ + + HANDLE hFile = ::CreateFile( + lpFileName, + dwDesiredAccess, + dwShareMode, + lpSecurityAttributes, + dwCreationDisposition, + dwFlagsAndAttributes, + hTemplateFile); + + if (hFile == INVALID_HANDLE_VALUE) { + DWORD a = ::GetLastError(); + ppStream = NULL; + return E_FAIL; + } + + FileStream* pFileStream = new FileStream(hFile); + + return pFileStream->QueryInterface(IID_IStream, (void**)ppStream); +} + +///////////////////////////////////////////////////////////////////////////// + + + +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// FileStream class + +///////////////////////////////////////////////////////////////////////////// +// ctor/dtor + +FileStream::FileStream(HANDLE hFile) + : m_lRefCount(0) + , m_hFile(hFile) +{ +} + +FileStream::~FileStream() +{ + if (m_hFile) ::CloseHandle(m_hFile); +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// IStream methods + +///////////////////////////////////////////////////////////////////////////// +// Read - reads a specified number of bytes from the stream object into memory +// starting at the current seek pointer + +STDMETHODIMP FileStream::Read(void *pv, ULONG cb, ULONG *pcbRead) +{ + if (!::ReadFile(m_hFile, pv, cb, pcbRead, NULL)) return S_FALSE; + + return S_OK; +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Write - writes a specified number of bytes into the stream object starting +// at the current seek pointer + +STDMETHODIMP FileStream::Write(void const *pv, ULONG cb, ULONG *pcbWritten) +{ + if (!::WriteFile(m_hFile, pv, cb, pcbWritten, NULL)) return S_FALSE; + + return S_OK; +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Seek - changes the seek pointer to a new location relative to the beginning +// of the stream, to the end of the stream, or to the current seek pointer + +STDMETHODIMP FileStream::Seek(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition) +{ + DWORD dwFileOrigin; + + DWORD dwMoveLow = dlibMove.LowPart; + LONG lMoveHigh = dlibMove.HighPart; + + switch (dwOrigin) { + case STREAM_SEEK_SET : dwFileOrigin = FILE_BEGIN; break; + case STREAM_SEEK_CUR : dwFileOrigin = FILE_CURRENT; break; + case STREAM_SEEK_END : dwFileOrigin = FILE_END; break; + default:dwFileOrigin = FILE_BEGIN; + } + + DWORD dwRet = ::SetFilePointer(m_hFile, dwMoveLow, &lMoveHigh, dwFileOrigin); + + if (::GetLastError() != NO_ERROR) return STG_E_INVALIDPOINTER; + + plibNewPosition->LowPart = dwRet; + plibNewPosition->HighPart = lMoveHigh; + + return S_OK; +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// SetSize - not really doing anything here + +STDMETHODIMP FileStream::SetSize(ULARGE_INTEGER libNewSize) +{ + return S_OK; +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// CopyTo - copies a specified number of bytes from the current seek pointer +// in the stream to the current seek pointer in another stream + +STDMETHODIMP FileStream::CopyTo(IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten) +{ + // later... + return E_NOTIMPL; +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Commit - no work here... + +STDMETHODIMP FileStream::Commit(DWORD grfCommitFlags) +{ + return S_OK; +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Revert - no work here... + +STDMETHODIMP FileStream::Revert(void) +{ + return S_OK; +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// LockRegion - no work here... + +STDMETHODIMP FileStream::LockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) +{ + return E_NOTIMPL; +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// UnlockRegion - no work here... + +STDMETHODIMP FileStream::UnlockRegion(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType) +{ + return E_NOTIMPL; +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Stat - no work here... + +STDMETHODIMP FileStream::Stat(STATSTG *pstatstg, DWORD grfStatFlag) +{ + return E_NOTIMPL; +} + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// Clone - no work here... + +STDMETHODIMP FileStream::Clone(IStream **ppstm) +{ + return E_NOTIMPL; +} + +///////////////////////////////////////////////////////////////////////////// diff --git a/Console/FileStream.h b/Console/FileStream.h new file mode 100644 index 00000000..2dcf08dd --- /dev/null +++ b/Console/FileStream.h @@ -0,0 +1,107 @@ +///////////////////////////////////////////////////////////////////////////// +// Copyright (C) 2001-2004 by Marko Bozikovic +// All rights reserved +// +// This program is free software; you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation; either version 2 of the License, or +// (at your option) any later version. +// +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with this program; if not, write to the Free Software +// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA +// +// Send bug reports, bug fixes, enhancements, requests, flames, etc., and +// I'll try to keep a version up to date. I can be reached as follows: +// marko.bozikovic@alterbox.net +// bozho@kset.org +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// FileStream.h - implementation of IStream interface on any file +// (not really COM, I'm faking it here a bit :-) +// + +#pragma once + + +///////////////////////////////////////////////////////////////////////////// +// CreateFileStream - opens/creates a file and returns an IStream interface + +HRESULT CreateFileStream( + LPCTSTR lpFileName, // file name + DWORD dwDesiredAccess, // access mode + DWORD dwShareMode, // share mode + LPSECURITY_ATTRIBUTES lpSecurityAttributes, // SD + DWORD dwCreationDisposition, // how to create + DWORD dwFlagsAndAttributes, // file attributes + HANDLE hTemplateFile, // handle to template file + IStream** ppStream // pointer to IStream interface +); + + +///////////////////////////////////////////////////////////////////////////// + + +///////////////////////////////////////////////////////////////////////////// +// FileStream class + +class FileStream : public IStream { + public: + FileStream(HANDLE hFile); + ~FileStream(); + + // IUnknown methods + STDMETHOD(QueryInterface)(REFIID riid, void ** ppv) { + if (riid == IID_IUnknown) { + *ppv = static_cast(this); + } else if (riid == IID_IStream) { + *ppv = static_cast(this); + } else { + *ppv = NULL; + return E_NOINTERFACE; + } + + static_cast(*ppv)->AddRef(); + return S_OK; + }; + + STDMETHOD_(ULONG, AddRef)(void) { + return ::InterlockedIncrement(&m_lRefCount); + }; + + STDMETHOD_(ULONG, Release)(void) { + long l = ::InterlockedDecrement(&m_lRefCount); + if (l == 0) delete this; + return l; + }; + + // IStream methods + STDMETHOD(Read)(void *pv, ULONG cb, ULONG *pcbRead); + STDMETHOD(Write)(void const *pv, ULONG cb, ULONG *pcbWritten); + STDMETHOD(Seek)(LARGE_INTEGER dlibMove, DWORD dwOrigin, ULARGE_INTEGER *plibNewPosition); + STDMETHOD(SetSize)(ULARGE_INTEGER libNewSize); + STDMETHOD(CopyTo)(IStream *pstm, ULARGE_INTEGER cb, ULARGE_INTEGER *pcbRead, ULARGE_INTEGER *pcbWritten); + STDMETHOD(Commit)(DWORD grfCommitFlags); + STDMETHOD(Revert)(void); + STDMETHOD(LockRegion)(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType); + STDMETHOD(UnlockRegion)(ULARGE_INTEGER libOffset, ULARGE_INTEGER cb, DWORD dwLockType); + STDMETHOD(Stat)(STATSTG *pstatstg, DWORD grfStatFlag); + STDMETHOD(Clone)(IStream **ppstm); + + private: // private data + + // reference count + long m_lRefCount; + + // file handle + HANDLE m_hFile; +}; + +///////////////////////////////////////////////////////////////////////////// diff --git a/Console/ReadMe.txt b/Console/ReadMe.txt new file mode 100644 index 00000000..dd1ac002 --- /dev/null +++ b/Console/ReadMe.txt @@ -0,0 +1,1200 @@ +Console v1.5 Sep 2005 +===================== +for Windows NT/2000/XP + +Copyright (C) 2001-2005 Marko Bozikovic + +This program is free software; you can redistribute it and/or modify +it under the terms of the GNU General Public License as published by +the Free Software Foundation; either version 2 of the License, or +(at your option) any later version. + +This program is distributed in the hope that it will be useful, +but WITHOUT ANY WARRANTY; without even the implied warranty of +MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +GNU General Public License for more details. + +You should have received a copy of the GNU General Public License +along with this program; if not, write to the Free Software +Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA + +Send bug reports, bug fixes, enhancements, requests, flames, etc., and +I'll try to keep a version up to date. I can be reached as follows: + bozho@kset.org + +Console icon is Copyright (C) 2001-2005 by Ante Vukorepa (orcinus@kset.org) + + +1. Requirements +=============== +WinNT 4.0 SP4 or later (it won't work on Win9x/Me) +IE 4.0 (or later) installed. + + +2. File list +============ + +console.exe +FreeImage.dll +FreeImagePlus.dll +console.inf +console.xml +console_big.xml +console_small.xml +devel-changes.txt +Readme.txt +License.txt +Tab Completition.reg +FixedMedium*.fon +TerminalMedium14.fon + + +3. Installation +=============== + +Unzip Console.zip file somewhere :-) + +If you'd like to have "Console here" in the Explorer right-click menu for +drives and directories, install console.inf file (right-click on console.inf +and choose "Install") Remember to do it in the Console directory! + + +4. Uninstall +============ + +If you have installed console.inf (see "Installation" section), run +"Add/Remove Programs" Control Panel applet and remove "Console Here +Extension". + +Delete all the files. + + +5. Overview +=========== + +Console is a Win console window enhancement. It was inspired by eConsole +(http://www.informatik.uni-frankfurt.de/~corion), a great console-enhancement +program (unfortunately, it seems that it's no longer being developed) + +Console features include configurable font, color, size, background image and +transparency (on Win2000 and later) + +Console is *not* a shell. It's simply a nice-looking front end for a shell +of your choice (cmd.exe, 4NT, ksh, Cygwin bash, etc.) + + +6. Acknowledgements +=================== + +A big thanks to Ante Vukorepa for the program icon. +Also, big thanks to Alen Ladavac for help with painting optimizations. + +Many thanks to code contributors: +- Francois Leblanc for mouse wheel messages patch +- Daniel Soto for adding multiple monitors support +- Dean Scarff for adding stuff +- Adam Hodson for adding flat scrollbar support +- Daniel Cheng for making Console window looking like a regular window when + is set to 'tray' or 'hide' +- Rob Davenport for config reload prompt patch and initial comments in the + sample console.xml file + +Thanks also goes to all the people using and testing Console, reporting bugs +and asking for new stuff :-) + + +7. Included fonts +================= + +The fonts included with Console are XFree86 'misc' fonts converted to TTF. I +added them here, since Windows could use nicer console fonts. If you wish to +use them, simply install them as you would any other TTF font (go to Control +Panel -> Fonts and follow instructions :-) + +I guess these fonts are distributed under XFree86 licence, and if you think +I'm in violation of any licence terms by providing these fonts, please drop me +a line. + + +8. FreeImage library +==================== + +Console uses FreeImage library for background image loading and manipulations. +Console source distribution includes only FreeImage library, include and DLL +files. Complete source code for FreeImage can be obtained at: +http://freeimage.sourceforge.net + + +9. Configuration & usage +======================== + +9.1 Running Console +------------------- + +The first thing you might want to set is your COMSPEC environment variable, +since that is the shell Console will start. Set it to your favorite shell +(cmd.exe, 4nt.exe) + +Console command line syntax: +console.exe [] [OPTIONS] + + is the path to the configuration file. If ommited, Console will +try to locate console.xml configuration file in console.exe directory. If the +path contains blanks, enclose it in double quotes. + +Options: + +-c - sets initial shell command +-t - sets default window title +-r - sets default new configuration auto-load + flag + +You can pass initial shell command by using "-c" switch. If the command string +contains blanks, enclose it in double quotes. If the command string itself +contains double quotes, put two double quotes for each double quote appearing +in the command string. E.g: + console.exe console.xml -c "cd ""C:\Program Files""" + +Note: If you use cmd.exe as your shell, you must use /k switch in your command +line string (4NT doesn't need the /k switch): + console.exe console.xml -c "/k " + +-t switch specifies the default Console window title. Using the 'title' +attribute in the config file will override this switch. + +-r switch specifies the default new configuration auto-reload flag. Possible +values are: 'yes', 'no' and 'prompt'. 'prompt' is the default. Using +'reload_new_config' tag in the config file will override this switch. + +9.2 Copy/Paste +-------------- + +To copy text, press and hold shift+left click (or simply left click if Console +is not mouse draggable) Drag to select text, and then left-click inside the +selection to copy. Left-click outside the selection clears it. If you set +copy_on_select tag to true, the selection will be copied immediately after +releasing the mouse button. + +You can paste text into Console using shift+right click or middle click (you +might want to disable middle-button click support for Console in your mouse +drivers for better performance) + +Note: text selection and copy work for fixed-width fonts *only*. Use Lucida +Console or the supplied fonts (if you have any nice looking free fixed width +fonts, feel free to share them :-) + +9.3 International characters +---------------------------- + +Console fully supports Unicode characters, so it should be able to handle all +national characters, but there are some things to note: + +The font you use in Console must include international characters (this one is +obvious, isn't it? :-) Supplied FixedMediumXX fonts don't include all of them. +I have found some FixedMedium Unicode fonts, but I wasn't able to convert them +from bdf to ttf format yet. Your best bet is using Lucida Console font +supplied with Windows. + +After that, you have to configure the Windows console. Start Console and +unhide Win console. By default, the Win console uses the Raster Font that +doesn't have international characters. Open Win console properties and on the +Fonts tab change the font to Lucida Console. Click OK and on the next small +dialog select "Save properties for future windows with the same title" This +will make Win console windows started by Console use Lucida Console font that +has international characters. + +9.4 Controlling Console from other applications +----------------------------------------------- + +Console can be controlled from other applications that support sending +messages to application windows (e.g. PowerPro) + +Console can handle messages for its menu commands sent from other +applications. The other application should send WM_COMMAND message (0x0111 in +hex, or 273 decimal) to the main Console window, with wParam set to command +ID, and lParam set to 0. + +Command IDs (decimal values) are: + +Show Readme.txt file...............40001 +Show About dialog..................40002 +Copy selected text.................40003 +Paste from clipboard...............40004 +Toggle 'always on top' status......40005 +Toggle show/hide Windows console...40006 +Edit configuration file............40008 +Reload settings....................40009 +Exit Console.......................40010 + +For selecting a configuration file, wParam should be between 1000 and 2000 +(1000 being the first .XML file in the startup config file direcotry, files +sorted by filename, ascending) + +9.5 Maximizing Console window +----------------------------- + +Console window can be maximized by setting 'rows' and/or 'columns' of the + tag to 'max'. + +Maximum number of rows and/or columns is determined by both maximum Windows' +console dimensions and maximum Console window size. The smaller will be used +(since Windows console cannot be resized beyond desktop size) + +If the size of your Console window is limited by Windows console maximum size, +you can choose a smaller font in Windows console properties. + +Note that increasing the number of rows and/or columns and reloading the +settings can sometimes result in a corrupt output. I haven't found a solution +for this yet, but it seems that restarting Console solves the problem. + + +9.6 Misc stuff +-------------- + +Using left button double click you can toggle between z-order selected in the +configuration file and "always on top" z-order. + +Right-click pops up a menu. You can copy/paste text from the menu, toggle +'always on top' and 'hide console' flags, work with configuration files. You +can switch configuration files by selecting a file from 'Select configuration +file' submenu (currently active configuration file is checked) and reloading +configuration. Configuration files are enumerated from the initial +configuration file's directory. + +You can drag-n-drop a file or directory to Console. If several files are +dropped at once, they will be sent to Console, separated by spaces. Filenames +that contain spaces will be enclosed in double quotes. + +The supplied .reg file is a registry file that will turn on file and directory +name completion for cmd.exe (thanks to Rob 'insanitee' for the idea) To +install it, just double-click on it, and click 'Yes'. + +You can map console font colors to custom values (see configuration section) +Check out supplied console.xml for an example with default values. + +Color indexes for default colors are: +00 - Black 08 - Gray (bright black) +01 - Blue 09 - Bright blue +02 - Green 10 - Bright green +03 - Cyan 11 - Bright cyan +04 - Red 12 - Bright red +05 - Magenta 13 - Bright magenta +06 - Yellow 14 - Bright yellow +07 - White 15 - Bright white + + +10. Configuration file +====================== + +The console configuration file is a simple xml file. Here's a general layout +of the configuration file: + + + + + + 8 + + false + false + Lucida Console + + + + 150 + 150 + bottom left + 10 + regular + + + + + true + + + + + 10 + 10 + 120 + + + false + + 1 + + normal + + + + alpha + + + + + 2.bmp + + + + + + + + + + + + true + + true + + true + + prompt + + + + + +If you ommit tags and/or attributes, default values will be used. + +Here are the tags and attributes: + +console +------- +Description: root tag +Parent: none +Attributes: - title -> sets the console window title (default: console) + - change_refresh -> change refresh interval (in ms) for window + repaint (default: 50) It controls how long window repainting is + delayed after a change has been detected in the real console. + The minimum value for this setting is 5. Note that small values + will increase CPU usage when console contents changes + rapidly (like dumping a large text file on the console) + - refresh -> sets main refresh interval (in ms) for window + repaint (default: 500) Console window is periodically refresh + even if there are no changes detected. This is needed for + proper operation of some DOS programs (eg, RAR). You can switch + this off (by setting it to 0) to reduce CPU usage, but some DOS + programs will not be displayed correctly (if at all :-) + - shell -> sets shell program, overriding COMSPEC environment + variable (if you change this while Console is running, you'll + have to restart it for chages to take effect) + - editor -> specifies text editor that will be used to edit the + configuration file (notepad.exe by default); if the program is + not in your PATH, you'll need to specify the full path + - editor_params -> specifies additional parameters to be passed + to a text editor used to edit configuration file and view the + Readme file; %f in editor_params will be replaced by the + configuration/readme file name; if there's no %f in the + editor_params, the configuration/readme file name will be + concatenated to the editor_params string; if there are spaces + in the filename, place " around %f ("%f") +Data: none + +Note on 'change_refresh' and 'refresh' attributes: Console v1.4 introduced +some window painting improvements, increasing the speed and reducing CPU +usage. You might want to set these parameters much lower for better +performance (something like 5-10 for 'change_refresh' and 100-200 for +'refresh') + + + ------ + Description: Sets the font and its properties + Parent: console + Attributes: none + Data: none + + + ------ + Description: sets font size in points + Parent: font + Attributes: none + Data: font size in points (default: 8) + + + ------ + Description: sets font's bold flag + Parent: font + Attributes: none + Data: true/false (default: false) + + + -------- + Description: sets font's italic flag + Parent: font + Attributes: none + Data: true/false (default: false) + + + ------- + Description: sets font color + Parent: font + Attributes: - r -> 0-255, sets Red component (default: 0) + - g -> 0-255, sets Green component (default: 0) + - b -> 0-255, sets Blue component (default: 0) + Data: none + Note: if this tag is not present, Console will use font colors + from the real console (useful if your shell, like 4NT, + supports different coloring options) + + + -------- + Description: groups font color mapping tags + Parent: font + Attributes: none + Data: none + + + ---------- + Description: maps color No. XX to a new color + Parent: colors + Attributes: - r -> 0-255, sets Red component (default: 0) + - g -> 0-255, sets Green component (default: 0) + - b -> 0-255, sets Blue component (default: 0) + Data: none + Note: XX goes from 00 to 15 (you may ommit colors you don't + want to change) See 'Misc Stuff' section above for + color indexes + + + ------ + Description: sets font's name + Parent: font + Attributes: none + Data: font name (default: Lucida Console) + + + + ---------- + Description: groups window position tags + Parent: console + Attributes: none + Data: none + + + --- + Description: sets initial window X coordinate + Parent: position + Attributes: none + Data: X coordinate + Note: Set to -1 to let the system place the Console window at + startup + + + --- + Description: sets initial window Y coordinate + Parent: position + Attributes: none + Data: Y coordinate + Note: Set to -1 to let the system place the Console window at + startup + + + -------- + Description: sets initial window docking position + Parent: position + Attributes: none + Data: docked position: none, bottom left, bottom right, top + left, top right (default: none) + + + --------------- + Description: sets window snap distance + Parent: position + Attributes: none + Data: snap distance in pixels; use -1 for no snapping (default: + 10) + + + --------- + Description: sets window z ordering + Parent: position + Attributes: none + Data: window z-order: regular, on top, on bottom (default: + regular) + + + + ------------ + Description: groups window appearance tags + Parent: console + Attributes: none + Data: none + + + -------------- + Description: sets real console window visibility + Parent: appearance + Attributes: none + Data: true/false (default: true) + + + ---------------------- + Description: sets timeout for initial console hiding (during startup); + some shells need real console window visible during + startup in order to initialize properly + Parent: appearance + Attributes: none + Data: timeout in milliseconds (default: 0) + + + ----------------- + Description: sets initial 'minimized' status + Parent: appearance + Attributes: none + Data: true/false (default: true) + + + ---------------- + Description: groups scrollbar attributes (if visible) + Parent: appearance + Attributes: none + Data: none + + + ------- + Description: sets scrollbar background color + Parent: scrollbar + Attributes: - r -> 0-255, sets Red component (default: system + default) + - g -> 0-255, sets Green component (default: system + default) + - b -> 0-255, sets Blue component (default: system + default) + Data: none + +