From d8145755c3ec9420d5bb7762824df9c3479528ed Mon Sep 17 00:00:00 2001 From: Overhaul Date: Sun, 8 Jul 2007 07:02:56 +0000 Subject: [PATCH] Added window around windowed JA2 Replaced Windows console with freeware console implementation. Activate in windowed mode with \ Added error and quit if JA2 started in window mode in >16bpp color depth Fix to enemy sector investigation: Was deducting from redshirts when elites investigated Fix AWOL militia (need additional fix to prevent them from being redistributed during after reinforcements) Fix to tanks to add them in their original spot when a new one cannot be found. Should modify to remove old wreckage in this case. AI no longer tries to fire mortar when no room for it Tanks no longer try to throw knives git-svn-id: https://ja2svn.mooo.com/source/ja2/trunk/GameSource/ja2_v1.13/Build@1030 3b4a5df2-a311-0410-b5c6-a8a6f20db521 --- Console/ComBSTROut.h | 81 + Console/ComVariantOut.h | 109 + Console/Console.cpp | 4560 +++++++++++++++++ Console/Console.h | 744 +++ Console/Console.rc | 207 + Console/Console_2005Express.vcproj | 319 ++ Console/Cursors.cpp | 842 +++ Console/Cursors.h | 345 ++ Console/Dialogs.cpp | 133 + Console/Dialogs.h | 64 + Console/FileStream.cpp | 259 + Console/FileStream.h | 107 + Console/ReadMe.txt | 1200 +++++ Console/console.ico | Bin 0 -> 18902 bytes Editor/Editor_2005Express.vcproj | 2 +- GameSettings.cpp | 4 +- HelpScreen.cpp | 1 + Init.cpp | 4 +- Intro.cpp | 1 + Laptop/IMP Begin Screen.cpp | 3 +- Laptop/IMP HomePage.cpp | 1 + Laptop/IMP Personality Quiz.cpp | 1 + Laptop/Laptop_2005Express.vcproj | 2 +- Laptop/laptop.cpp | 2 + Laptop/personnel.cpp | 2 + Options Screen.cpp | 1 + Res/resource.h | 9 +- SaveLoadGame.cpp | 6 + SaveLoadScreen.cpp | 1 + .../SGP_2005Express.vcproj | 2 +- Standard Gaming Platform/input.cpp | 63 +- Standard Gaming Platform/input.h | 4 +- Standard Gaming Platform/mousesystem.cpp | 2 +- Standard Gaming Platform/sgp.cpp | 76 +- Standard Gaming Platform/video.cpp | 294 +- Strategic/Auto Resolve.cpp | 8 +- Strategic/Map Screen Interface Bottom.cpp | 3 +- Strategic/Quest Debug System.cpp | 1 + Strategic/Strategic AI.cpp | 4 +- Strategic/Strategic_2005Express.vcproj | 2 +- Strategic/mapscreen.cpp | 9 +- Tactical/Militia Control.cpp | 3 +- Tactical/ShopKeeper Interface.cpp | 1 + Tactical/Soldier Add.cpp | 10 +- Tactical/Soldier Ani.cpp | 1 + Tactical/Tactical_2005Express.vcproj | 2 +- Tactical/Turn Based Input.cpp | 15 + TacticalAI/DecideAction.cpp | 34 +- TacticalAI/TacticalAI_2005Express.vcproj | 2 +- TileEngine/TileEngine_2005Express.vcproj | 2 +- Utils/Utils_2005Express.vcproj | 2 +- gameloop.cpp | 7 +- ja2_2005Express.sln | 21 +- ja2_2005Express.vcproj | 30 +- ja2_2005Express.vsprops | 2 +- ja2_2005ExpressDebug.vsprops | 11 + lua/Console.cpp | 126 - lua/Console.h | 9 - lua/lua_2005Express.vcproj | 10 +- resource.h | 16 - 60 files changed, 9433 insertions(+), 349 deletions(-) create mode 100644 Console/ComBSTROut.h create mode 100644 Console/ComVariantOut.h create mode 100644 Console/Console.cpp create mode 100644 Console/Console.h create mode 100644 Console/Console.rc create mode 100644 Console/Console_2005Express.vcproj create mode 100644 Console/Cursors.cpp create mode 100644 Console/Cursors.h create mode 100644 Console/Dialogs.cpp create mode 100644 Console/Dialogs.h create mode 100644 Console/FileStream.cpp create mode 100644 Console/FileStream.h create mode 100644 Console/ReadMe.txt create mode 100644 Console/console.ico create mode 100644 ja2_2005ExpressDebug.vsprops delete mode 100644 lua/Console.cpp delete mode 100644 lua/Console.h delete mode 100644 resource.h 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 + +