diff options
author | elfmz <fenix1905@tut.by> | 2021-12-31 00:27:16 +0300 |
---|---|---|
committer | elfmz <fenix1905@tut.by> | 2021-12-31 02:27:02 +0300 |
commit | a14dc1a81c797928d4f1b7d6a6b46ecc63f98308 (patch) | |
tree | c27c61ac33582bc4d469c6608cd042add388f230 /far2l/src/console | |
parent | d5f1bf245e96834d44390d1723cfef3dfbb1fb02 (diff) |
shuffle a bit far2l sources
Diffstat (limited to 'far2l/src/console')
26 files changed, 9623 insertions, 0 deletions
diff --git a/far2l/src/console/AnsiEsc.cpp b/far2l/src/console/AnsiEsc.cpp new file mode 100644 index 00000000..cbaf1cdb --- /dev/null +++ b/far2l/src/console/AnsiEsc.cpp @@ -0,0 +1,345 @@ +#include "headers.hpp" +#include "AnsiEsc.hpp" +#include "interf.hpp" +#include "colors.hpp" + +namespace AnsiEsc +{ + +#define FOREGROUND_BLACK 0 +#define FOREGROUND_WHITE FOREGROUND_RED|FOREGROUND_GREEN|FOREGROUND_BLUE + +#define BACKGROUND_BLACK 0 +#define BACKGROUND_WHITE BACKGROUND_RED|BACKGROUND_GREEN|BACKGROUND_BLUE + +static const BYTE ForegroundColor[16] = { + FOREGROUND_BLACK, // black foreground + FOREGROUND_RED, // red foreground + FOREGROUND_GREEN, // green foreground + FOREGROUND_RED | FOREGROUND_GREEN, // yellow foreground + FOREGROUND_BLUE, // blue foreground + FOREGROUND_BLUE | FOREGROUND_RED, // magenta foreground + FOREGROUND_BLUE | FOREGROUND_GREEN, // cyan foreground + FOREGROUND_WHITE, // white foreground + + FOREGROUND_INTENSITY | FOREGROUND_BLACK, // black foreground + FOREGROUND_INTENSITY | FOREGROUND_RED, // red foreground + FOREGROUND_INTENSITY | FOREGROUND_GREEN, // green foreground + FOREGROUND_INTENSITY | FOREGROUND_RED | FOREGROUND_GREEN, // yellow foreground + FOREGROUND_INTENSITY | FOREGROUND_BLUE, // blue foreground + FOREGROUND_INTENSITY | FOREGROUND_BLUE | FOREGROUND_RED, // magenta foreground + FOREGROUND_INTENSITY | FOREGROUND_BLUE | FOREGROUND_GREEN, // cyan foreground + FOREGROUND_INTENSITY | FOREGROUND_WHITE, // white foreground + +}; + +static const BYTE BackgroundColor[16] = { + BACKGROUND_BLACK, // black background + BACKGROUND_RED, // red background + BACKGROUND_GREEN, // green background + BACKGROUND_RED | BACKGROUND_GREEN, // yellow background + BACKGROUND_BLUE, // blue background + BACKGROUND_BLUE | BACKGROUND_RED, // magenta background + BACKGROUND_BLUE | BACKGROUND_GREEN, // cyan background + BACKGROUND_WHITE, // white background + + BACKGROUND_INTENSITY | BACKGROUND_BLACK, // black background + BACKGROUND_INTENSITY | BACKGROUND_RED, // red background + BACKGROUND_INTENSITY | BACKGROUND_GREEN, // green background + BACKGROUND_INTENSITY | BACKGROUND_RED | BACKGROUND_GREEN, // yellow background + BACKGROUND_INTENSITY | BACKGROUND_BLUE, // blue background + BACKGROUND_INTENSITY | BACKGROUND_BLUE | BACKGROUND_RED, // magenta background + BACKGROUND_INTENSITY | BACKGROUND_BLUE | BACKGROUND_GREEN, // cyan background + BACKGROUND_INTENSITY | BACKGROUND_WHITE, // white background +}; + + +static const BYTE Attr2Ansi[8] = { // map console attribute to ANSI number + 0, // black + 4, // blue + 2, // green + 6, // cyan + 1, // red + 5, // magenta + 3, // yellow + 7 // white +}; + +///////////////// +void FontState::ParseSuffixM(const int *args, int argc) +{ + int argz = 0; + if (argc == 0) { + argc = 1; + args = &argz; + } + + for (int i = 0; i < argc; ++i) { + const int a = args[i]; + if (30 <= a && a <= 37) { + foreground = a - 30; + + } else if (90 <= a && a <= 97) { + foreground = (a - 90) + 8; + + } else if (40 <= a && a <= 47) { + background = a - 40; + + } else if (100 <= a && a <= 107) { + background = (a - 100) + 8; + + } else if (a == 38 || a == 48) { + // This is technically incorrect, but it's what xterm does, so + // that's what we do. According to T.416 (ISO 8613-6), there is + // only one parameter, which is divided into elements. So where + // xterm does "38;2;R;G;B" it should really be "38;2:I:R:G:B" (I is + // a colour space identifier). + if (i + 1 < argc) { + if (args[i + 1] == 2) // rgb + i += 4; + else if (args[i + 1] == 5) // index + i += 2; + } + + } else switch (a) { + case 0: + rvideo = false; + concealed = false; + bold = false; + underline = false; + + case 39: + case 49: { + const BYTE def_attr = 7;//FOREGROUND_WHITE; + reverse = false; + if (def_attr != 49) { + foreground = Attr2Ansi[def_attr & 15]; + } + if (def_attr != 39) { + background = Attr2Ansi[(def_attr >> 4) & 15]; + } + } break; + + case 1: + bold = true; + break; + case 5: // blink + case 4: + underline = true; + break; + case 7: + rvideo = 1; + break; + case 8: + concealed = 1; + break; + case 21: // oops, this actually turns on double underline + // but xterm turns off bold too, so that's alright + case 22: + bold = 0; + break; + case 25: + case 24: + underline = 0; + break; + case 27: + rvideo = 0; + break; + case 28: + concealed = 0; + break; + } + } +} + +void FontState::FromConsoleAttributes(WORD wAttributes) +{ + bold = (wAttributes & FOREGROUND_INTENSITY) != 0; + underline = (wAttributes & BACKGROUND_INTENSITY) != 0; + foreground = Attr2Ansi[wAttributes & 7]; + background = Attr2Ansi[(wAttributes >> 4) & 7]; +} + +WORD FontState::ToConsoleAttributes() +{ + WORD attribut = 0; + + if (concealed) { + if (rvideo) { + attribut = ForegroundColor[foreground] | BackgroundColor[foreground]; + if (bold) { + attribut|= FOREGROUND_INTENSITY | BACKGROUND_INTENSITY; + } + } else { + attribut = ForegroundColor[background] | BackgroundColor[background]; + if (underline) { + attribut|= FOREGROUND_INTENSITY | BACKGROUND_INTENSITY; + } + } + } else if (rvideo) { + attribut = ForegroundColor[background] | BackgroundColor[foreground]; + if (bold) { + attribut|= BACKGROUND_INTENSITY; + } + if (underline) { + attribut|= FOREGROUND_INTENSITY; + } + } else { + attribut = ForegroundColor[foreground] | BackgroundColor[background]; + if (bold) { + attribut|= FOREGROUND_INTENSITY; + } + if (underline) { + attribut|= BACKGROUND_INTENSITY; + } + } + if (reverse) { + attribut = ((attribut >> 4) & 15) | ((attribut & 15) << 4); + } + return attribut; +} + +////////////////////////////////////////////////////////////////////////////////////////// + +const wchar_t *Parser::Parse(const wchar_t *str) +{ + args.clear(); + suffix = 0; + + if (str[0] == 033 && str[1] == '[') { + int a = 0; + for (size_t i = 2; str[i]; ++i) { + if (str[i] == ';' + || (str[i] >= L'a' && str[i] <= L'z') + || (str[i] >= L'A' && str[i] <= L'Z')) { + args.push_back(a); + if (str[i] != ';') { + suffix = str[i]; + return &str[i + 1]; + } + a = 0; + + } else if (i < 32 && str[i] >= '0' && str[i] <= '9') { + a*= 10; + a+= str[i] - '0'; + + } else { + return nullptr; + } + } + } + + return nullptr; +} + +///////////// + +Printer::Printer(WORD wAttributes) + : + _initial_attr(GetRealColor()) +{ + _font_state.FromConsoleAttributes(wAttributes); +} + +Printer::~Printer() +{ + SetRealColor(_initial_attr); +} + +int Printer::Length(const wchar_t *str, int limit) +{ + Parser tmp_parser; + size_t out = 0; + for (const wchar_t *ch = str; *ch && limit != 0;) { + const wchar_t *end_of_esc = tmp_parser.Parse(ch); + if (end_of_esc) { + if (end_of_esc - ch > limit) { + return out; + } + limit-= end_of_esc - ch; + ch = end_of_esc; + if (tmp_parser.suffix == L'C') { // skip N chars + out+= tmp_parser.args[0] ? tmp_parser.args[0] : 1; + } + else if (tmp_parser.suffix == L'b') { // repeate last char N times + out+= tmp_parser.args[0] ? tmp_parser.args[0] : 1; + } + } else { + if (!ShouldSkip(*ch)) { + ++out; + } + ++ch; + --limit; + } + } + return out; +} + +void Printer::EnforceStateColor() +{ + if (_selection) + SetColor(COL_VIEWERSELECTEDTEXT); + else + SetRealColor(_font_state.ToConsoleAttributes()); +} + +void Printer::Print(int skip_len, int print_len, const wchar_t *str) +{ + int processed = 0; + EnforceStateColor(); + for (const wchar_t *ch = str; ;) { + const wchar_t *end_of_chunk = (*ch && !ShouldSkip(*ch)) ? _parser.Parse(ch) : ch; + if (end_of_chunk) + { + if (skip_len >= processed) { + int skip_part = std::min(skip_len - processed, int(ch - str)); + processed+= skip_part; + str+= skip_part; + } + if (ch != str && processed < skip_len + print_len) { + int print_part = int(ch - str); + if (processed + print_part > skip_len + print_len) { + print_part = skip_len + print_len - processed; + } + Text(str, print_part); + } + processed+= ch - str; + if (!*ch) { + break; + } + if (ShouldSkip(*ch)) { + str = ++ch; + continue; + } + if (_parser.suffix == L'C') { + for (int i = 0; i < _parser.args[0] || i < 1; ++i, ++processed ) { + if (processed >= skip_len && processed < skip_len + print_len) { + Text(L" ", 1); + } + } + } else if (_parser.suffix == L'b') { + for (int i = 0; i < _parser.args[0] || i < 1; ++i, ++processed ) { + if (processed >= skip_len && processed < skip_len + print_len) { + Text(&_last_char, 1); + } + } + } else if (_parser.suffix == L'm') { + _font_state.ParseSuffixM(_parser.args.data(), (int)_parser.args.size()); + EnforceStateColor(); + } + str = ch = end_of_chunk; + + } else { + _last_char = *ch; + ++ch; + } + } + while (processed < skip_len) { + ++processed; + } + if (processed < skip_len + print_len) { + PrintSpaces(skip_len + print_len - processed); + } +} + +} diff --git a/far2l/src/console/AnsiEsc.hpp b/far2l/src/console/AnsiEsc.hpp new file mode 100644 index 00000000..7dba73c6 --- /dev/null +++ b/far2l/src/console/AnsiEsc.hpp @@ -0,0 +1,48 @@ +#pragma once +#include <vector> +#include <string> +#include "ViewerPrinter.hpp" +#include <WinCompat.h> + +namespace AnsiEsc +{ + struct FontState + { + BYTE foreground = false; // ANSI base color (0 to 7; add 30) + BYTE background = false; // ANSI base color (0 to 7; add 40) + bool bold = false; // + bool underline = false; // + bool rvideo = false; // swap foreground/bold & background/underline + bool concealed = false; // set foreground/bold to background/underline + bool reverse = false; // swap console foreground & background attributes + + void ParseSuffixM(const int *args, int argc); + void FromConsoleAttributes(WORD wAttributes); + WORD ToConsoleAttributes(); + }; + + struct Parser + { + std::vector<int> args; + wchar_t suffix = 0; + + const wchar_t *Parse(const wchar_t *str); + }; + + struct Printer : ViewerPrinter + { + Printer(WORD wAttributes); + virtual ~Printer(); + + virtual int Length(const wchar_t *str, int limit = -1); + virtual void Print(int skip_len, int print_len, const wchar_t *str); + + private: + Parser _parser; + FontState _font_state; + WORD _initial_attr; + wchar_t _last_char = L' '; + + void EnforceStateColor(); + }; +} diff --git a/far2l/src/console/colors.hpp b/far2l/src/console/colors.hpp new file mode 100644 index 00000000..f275e045 --- /dev/null +++ b/far2l/src/console/colors.hpp @@ -0,0 +1,291 @@ +#pragma once +#ifndef __COLORS_HPP__ +#define __COLORS_HPP__ +#ifndef FAR_USE_INTERNALS +#define FAR_USE_INTERNALS +#endif // END FAR_USE_INTERNALS +#ifdef FAR_USE_INTERNALS +/* +colors.hpp + +Цвета + +*/ +#else // ELSE FAR_USE_INTERNALS +/* + farcolor.hpp + + Colors Index for FAR Manager <%VERSION%> + HKCU\Software\Far\Colors\CurrentPalette +*/ +#endif // END FAR_USE_INTERNALS + +/* +Copyright (c) 1996 Eugene Roshal +Copyright (c) 2000 Far Group +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +EXCEPTION: +Far Manager plugins that use this header file can be distributed under any +other possible license with no implications from the above license on them. +*/ + +#ifdef FAR_USE_INTERNALS +/* + Внимание! + Пункт COL_LASTPALETTECOLOR должен быть самым последним!!!!!! +*/ + +#include <WinCompat.h> + +// Стандартные цвета FAR Manager +enum +{ + F_BLACK=0, + F_BLUE=FOREGROUND_BLUE, + F_GREEN=FOREGROUND_GREEN, + F_CYAN=FOREGROUND_BLUE|FOREGROUND_GREEN, + F_RED=FOREGROUND_RED, + F_MAGENTA=FOREGROUND_BLUE|FOREGROUND_RED, + F_BROWN=FOREGROUND_GREEN|FOREGROUND_RED, + F_LIGHTGRAY=FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_RED, + F_DARKGRAY=FOREGROUND_INTENSITY, + F_LIGHTBLUE=FOREGROUND_BLUE|FOREGROUND_INTENSITY, + F_LIGHTGREEN=FOREGROUND_GREEN|FOREGROUND_INTENSITY, + F_LIGHTCYAN=FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_INTENSITY, + F_LIGHTRED=FOREGROUND_RED|FOREGROUND_INTENSITY, + F_LIGHTMAGENTA=FOREGROUND_BLUE|FOREGROUND_RED|FOREGROUND_INTENSITY, + F_YELLOW=FOREGROUND_GREEN|FOREGROUND_RED|FOREGROUND_INTENSITY, + F_WHITE=FOREGROUND_BLUE|FOREGROUND_GREEN|FOREGROUND_RED|FOREGROUND_INTENSITY, + B_BLACK=0, + B_BLUE=BACKGROUND_BLUE, + B_GREEN=BACKGROUND_GREEN, + B_CYAN=BACKGROUND_BLUE|BACKGROUND_GREEN, + B_RED=BACKGROUND_RED, + B_MAGENTA=BACKGROUND_BLUE|BACKGROUND_RED, + B_BROWN=BACKGROUND_GREEN|BACKGROUND_RED, + B_LIGHTGRAY=BACKGROUND_BLUE|BACKGROUND_GREEN|BACKGROUND_RED, + B_DARKGRAY=BACKGROUND_INTENSITY, + B_LIGHTBLUE=BACKGROUND_BLUE|BACKGROUND_INTENSITY, + B_LIGHTGREEN=BACKGROUND_GREEN|BACKGROUND_INTENSITY, + B_LIGHTCYAN=BACKGROUND_BLUE|BACKGROUND_GREEN|BACKGROUND_INTENSITY, + B_LIGHTRED=BACKGROUND_RED|BACKGROUND_INTENSITY, + B_LIGHTMAGENTA=BACKGROUND_BLUE|BACKGROUND_RED|BACKGROUND_INTENSITY, + B_YELLOW=BACKGROUND_GREEN|BACKGROUND_RED|BACKGROUND_INTENSITY, + B_WHITE=BACKGROUND_BLUE|BACKGROUND_GREEN|BACKGROUND_RED|BACKGROUND_INTENSITY, + F_MASK=F_WHITE, + B_MASK=B_WHITE +}; +#endif // END FAR_USE_INTERNALS + +enum PaletteColors +{ +#ifdef FAR_USE_INTERNALS + COL_FIRSTPALETTECOLOR=1000, + + COL_MENUTEXT=COL_FIRSTPALETTECOLOR, +#else // ELSE FAR_USE_INTERNALS + COL_MENUTEXT, +#endif // END FAR_USE_INTERNALS + COL_MENUSELECTEDTEXT, + COL_MENUHIGHLIGHT, + COL_MENUSELECTEDHIGHLIGHT, + COL_MENUBOX, + COL_MENUTITLE, + + COL_HMENUTEXT, + COL_HMENUSELECTEDTEXT, + COL_HMENUHIGHLIGHT, + COL_HMENUSELECTEDHIGHLIGHT, + + COL_PANELTEXT, + COL_PANELSELECTEDTEXT, + COL_PANELHIGHLIGHTTEXT, + COL_PANELINFOTEXT, + COL_PANELCURSOR, + COL_PANELSELECTEDCURSOR, + COL_PANELTITLE, + COL_PANELSELECTEDTITLE, + COL_PANELCOLUMNTITLE, + COL_PANELTOTALINFO, + COL_PANELSELECTEDINFO, + + COL_DIALOGTEXT, + COL_DIALOGHIGHLIGHTTEXT, + COL_DIALOGBOX, + COL_DIALOGBOXTITLE, + COL_DIALOGHIGHLIGHTBOXTITLE, + COL_DIALOGEDIT, + COL_DIALOGBUTTON, + COL_DIALOGSELECTEDBUTTON, + COL_DIALOGHIGHLIGHTBUTTON, + COL_DIALOGHIGHLIGHTSELECTEDBUTTON, + + COL_DIALOGLISTTEXT, + COL_DIALOGLISTSELECTEDTEXT, + COL_DIALOGLISTHIGHLIGHT, + COL_DIALOGLISTSELECTEDHIGHLIGHT, + + COL_WARNDIALOGTEXT, + COL_WARNDIALOGHIGHLIGHTTEXT, + COL_WARNDIALOGBOX, + COL_WARNDIALOGBOXTITLE, + COL_WARNDIALOGHIGHLIGHTBOXTITLE, + COL_WARNDIALOGEDIT, + COL_WARNDIALOGBUTTON, + COL_WARNDIALOGSELECTEDBUTTON, + COL_WARNDIALOGHIGHLIGHTBUTTON, + COL_WARNDIALOGHIGHLIGHTSELECTEDBUTTON, + + COL_KEYBARNUM, + COL_KEYBARTEXT, + COL_KEYBARBACKGROUND, + + COL_COMMANDLINE, + + COL_CLOCK, + + COL_VIEWERTEXT, + COL_VIEWERSELECTEDTEXT, + COL_VIEWERSTATUS, + + COL_EDITORTEXT, + COL_EDITORSELECTEDTEXT, + COL_EDITORSTATUS, + + COL_HELPTEXT, + COL_HELPHIGHLIGHTTEXT, + COL_HELPTOPIC, + COL_HELPSELECTEDTOPIC, + COL_HELPBOX, + COL_HELPBOXTITLE, + + COL_PANELDRAGTEXT, + COL_DIALOGEDITUNCHANGED, + COL_PANELSCROLLBAR, + COL_HELPSCROLLBAR, + COL_PANELBOX, + COL_PANELSCREENSNUMBER, + COL_DIALOGEDITSELECTED, + COL_COMMANDLINESELECTED, + COL_VIEWERARROWS, + +#ifdef FAR_USE_INTERNALS + // + 1 Служебная позиция перед новыми цветами :-) + COL_PRIVATEPOSITION_FOR_DIF165ABOVE, +#else // ELSE FAR_USE_INTERNALS + COL_RESERVED0, +#endif // END FAR_USE_INTERNALS + + COL_DIALOGLISTSCROLLBAR, + COL_MENUSCROLLBAR, + COL_VIEWERSCROLLBAR, + COL_COMMANDLINEPREFIX, + COL_DIALOGDISABLED, + COL_DIALOGEDITDISABLED, + COL_DIALOGLISTDISABLED, + COL_WARNDIALOGDISABLED, + COL_WARNDIALOGEDITDISABLED, + COL_WARNDIALOGLISTDISABLED, + + COL_MENUDISABLEDTEXT, + + COL_EDITORCLOCK, + COL_VIEWERCLOCK, + + COL_DIALOGLISTTITLE, + COL_DIALOGLISTBOX, + + COL_WARNDIALOGEDITSELECTED, + COL_WARNDIALOGEDITUNCHANGED, + + COL_DIALOGCOMBOTEXT, + COL_DIALOGCOMBOSELECTEDTEXT, + COL_DIALOGCOMBOHIGHLIGHT, + COL_DIALOGCOMBOSELECTEDHIGHLIGHT, + COL_DIALOGCOMBOBOX, + COL_DIALOGCOMBOTITLE, + COL_DIALOGCOMBODISABLED, + COL_DIALOGCOMBOSCROLLBAR, + + COL_WARNDIALOGLISTTEXT, + COL_WARNDIALOGLISTSELECTEDTEXT, + COL_WARNDIALOGLISTHIGHLIGHT, + COL_WARNDIALOGLISTSELECTEDHIGHLIGHT, + COL_WARNDIALOGLISTBOX, + COL_WARNDIALOGLISTTITLE, + COL_WARNDIALOGLISTSCROLLBAR, + + COL_WARNDIALOGCOMBOTEXT, + COL_WARNDIALOGCOMBOSELECTEDTEXT, + COL_WARNDIALOGCOMBOHIGHLIGHT, + COL_WARNDIALOGCOMBOSELECTEDHIGHLIGHT, + COL_WARNDIALOGCOMBOBOX, + COL_WARNDIALOGCOMBOTITLE, + COL_WARNDIALOGCOMBODISABLED, + COL_WARNDIALOGCOMBOSCROLLBAR, + + COL_DIALOGLISTARROWS, + COL_DIALOGLISTARROWSDISABLED, + COL_DIALOGLISTARROWSSELECTED, + COL_DIALOGCOMBOARROWS, + COL_DIALOGCOMBOARROWSDISABLED, + COL_DIALOGCOMBOARROWSSELECTED, + COL_WARNDIALOGLISTARROWS, + COL_WARNDIALOGLISTARROWSDISABLED, + COL_WARNDIALOGLISTARROWSSELECTED, + COL_WARNDIALOGCOMBOARROWS, + COL_WARNDIALOGCOMBOARROWSDISABLED, + COL_WARNDIALOGCOMBOARROWSSELECTED, + COL_MENUARROWS, + COL_MENUARROWSDISABLED, + COL_MENUARROWSSELECTED, + COL_COMMANDLINEUSERSCREEN, + COL_EDITORSCROLLBAR, + + COL_MENUGRAYTEXT, + COL_MENUSELECTEDGRAYTEXT, + COL_DIALOGCOMBOGRAY, + COL_DIALOGCOMBOSELECTEDGRAYTEXT, + COL_DIALOGLISTGRAY, + COL_DIALOGLISTSELECTEDGRAYTEXT, + COL_WARNDIALOGCOMBOGRAY, + COL_WARNDIALOGCOMBOSELECTEDGRAYTEXT, + COL_WARNDIALOGLISTGRAY, + COL_WARNDIALOGLISTSELECTEDGRAYTEXT, + + COL_DIALOGDEFAULTBUTTON, + COL_DIALOGSELECTEDDEFAULTBUTTON, + COL_DIALOGHIGHLIGHTDEFAULTBUTTON, + COL_DIALOGHIGHLIGHTSELECTEDDEFAULTBUTTON, + COL_WARNDIALOGDEFAULTBUTTON, + COL_WARNDIALOGSELECTEDDEFAULTBUTTON, + COL_WARNDIALOGHIGHLIGHTDEFAULTBUTTON, + COL_WARNDIALOGHIGHLIGHTSELECTEDDEFAULTBUTTON, + + COL_LASTPALETTECOLOR +}; + +#endif // __COLORS_HPP__ diff --git a/far2l/src/console/console.cpp b/far2l/src/console/console.cpp new file mode 100644 index 00000000..abe02da6 --- /dev/null +++ b/far2l/src/console/console.cpp @@ -0,0 +1,611 @@ +/* +console.cpp + +Console functions +*/ +/* +Copyright (c) 2010 Far Group +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "headers.hpp" + +#include <StackHeapArray.hpp> +#include "console.hpp" +#include "config.hpp" +#include "palette.hpp" +#include "colors.hpp" +#include "interf.hpp" + +console Console; + +//#define WINPORT(NAME) NAME + +bool console::Allocate() +{ + return TRUE;//AllocConsole()!=FALSE; +} + +bool console::Free() +{ + return TRUE;//FreeConsole()!=FALSE; +} + +HANDLE console::GetInputHandle() +{ + return stdin;//GetStdHandle(STD_INPUT_HANDLE); +} + +HANDLE console::GetOutputHandle() +{ + return stdout;//GetStdHandle(STD_OUTPUT_HANDLE); +} + +HANDLE console::GetErrorHandle() +{ + return stderr;//GetStdHandle(STD_ERROR_HANDLE); +} + +bool console::GetSize(COORD& Size) +{ + bool Result=false; + CONSOLE_SCREEN_BUFFER_INFO ConsoleScreenBufferInfo; + if(WINPORT(GetConsoleScreenBufferInfo)(GetOutputHandle(), &ConsoleScreenBufferInfo)) + { + if(Opt.WindowMode) + { + Size.X=ConsoleScreenBufferInfo.srWindow.Right-ConsoleScreenBufferInfo.srWindow.Left+1; + Size.Y=ConsoleScreenBufferInfo.srWindow.Bottom-ConsoleScreenBufferInfo.srWindow.Top+1; + } + else + { + Size=ConsoleScreenBufferInfo.dwSize; + } + Result=true; + } + return Result; +} + +bool console::SetSize(COORD Size) +{ + bool Result=false; + if(Opt.WindowMode) + { + CONSOLE_SCREEN_BUFFER_INFO csbi; + WINPORT(GetConsoleScreenBufferInfo)(GetOutputHandle(), &csbi); + csbi.srWindow.Left=0; + csbi.srWindow.Right=Size.X-1; + csbi.srWindow.Bottom=csbi.dwSize.Y-1; + csbi.srWindow.Top=csbi.srWindow.Bottom-(Size.Y-1); + COORD WindowCoord={(SHORT)(csbi.srWindow.Right-csbi.srWindow.Left+1), (SHORT)(csbi.srWindow.Bottom-csbi.srWindow.Top+1)}; + if(WindowCoord.X>csbi.dwSize.X || WindowCoord.Y>csbi.dwSize.Y) + { + WindowCoord.X=Max(WindowCoord.X,csbi.dwSize.X); + WindowCoord.Y=Max(WindowCoord.Y,csbi.dwSize.Y); + WINPORT(SetConsoleScreenBufferSize)(GetOutputHandle(), WindowCoord); + } + Result=SetWindowRect(csbi.srWindow); + } + else + { + Result=WINPORT(SetConsoleScreenBufferSize)(GetOutputHandle(), Size)!=FALSE; + } + return Result; +} + +bool console::GetWindowRect(SMALL_RECT& ConsoleWindow) +{ + bool Result=false; + CONSOLE_SCREEN_BUFFER_INFO ConsoleScreenBufferInfo; + if(WINPORT(GetConsoleScreenBufferInfo)(GetOutputHandle(), &ConsoleScreenBufferInfo)) + { + ConsoleWindow=ConsoleScreenBufferInfo.srWindow; + Result=true; + } + return Result; +} + +bool console::SetWindowRect(const SMALL_RECT& ConsoleWindow) +{ + return WINPORT(SetConsoleWindowInfo)(GetOutputHandle(), true, &ConsoleWindow)!=FALSE; +} + +bool console::GetWorkingRect(SMALL_RECT& WorkingRect) +{ + bool Result=false; + CONSOLE_SCREEN_BUFFER_INFO csbi; + if(WINPORT(GetConsoleScreenBufferInfo)(GetOutputHandle(), &csbi)) + { + WorkingRect.Bottom=csbi.dwSize.Y-1; + WorkingRect.Left=0; + WorkingRect.Right=WorkingRect.Left+ScrX; + WorkingRect.Top=WorkingRect.Bottom-ScrY; + Result=true; + } + return Result; +} + +bool console::GetTitle(FARString &strTitle) +{ + for (DWORD Size = 0x100; Size; Size<<= 1) + { + StackHeapArray<wchar_t, 0x200> buf(Size); + if (!buf.Get()) + break; + + if (WINPORT(GetConsoleTitle)(buf.Get(), Size) < Size) + { + strTitle = buf.Get(); + return true; + } + } + + return false; +} + +bool console::SetTitle(LPCWSTR Title) +{ + return WINPORT(SetConsoleTitle)(Title)!=FALSE; +} + +bool console::GetKeyboardLayoutName(FARString &strName) +{ + bool Result=false; + strName.Clear(); +/* if (ifn.pfnGetConsoleKeyboardLayoutName) + { + wchar_t *p = strName.GetBuffer(KL_NAMELENGTH+1); + if (p && ifn.pfnGetConsoleKeyboardLayoutName(p)) + { + Result=true; + } + strName.ReleaseBuffer(); + } + else*/ + { + WINPORT(SetLastError)(ERROR_CALL_NOT_IMPLEMENTED); + } + return Result; +} + +UINT console::GetInputCodepage() +{ + return CP_ACP;//GetConsoleCP(); +} + +bool console::SetInputCodepage(UINT Codepage) +{ + return TRUE;//SetConsoleCP(Codepage)!=FALSE; +} + +UINT console::GetOutputCodepage() +{ + return CP_ACP; //GetConsoleOutputCP(); +} + +bool console::SetOutputCodepage(UINT Codepage) +{ + return TRUE;//SetConsoleOutputCP(Codepage)!=FALSE; +} + +bool console::SetControlHandler(PHANDLER_ROUTINE HandlerRoutine, bool Add) +{ + return WINPORT(SetConsoleCtrlHandler)(HandlerRoutine, Add)!=FALSE; +} + +bool console::GetMode(HANDLE ConsoleHandle, DWORD& Mode) +{ + return WINPORT(GetConsoleMode)(ConsoleHandle, &Mode)!=FALSE; +} + +bool console::SetMode(HANDLE ConsoleHandle, DWORD Mode) +{ + return WINPORT(SetConsoleMode)(ConsoleHandle, Mode)!=FALSE; +} + +bool console::InspectStickyKeyEvent(INPUT_RECORD& ir) +{ + if (ir.EventType != KEY_EVENT) + return false; + + if (ir.Event.KeyEvent.uChar.UnicodeChar == ' ' && ir.Event.KeyEvent.wVirtualKeyCode == VK_SPACE) + { + if (ir.Event.KeyEvent.bKeyDown) + { + if ((ir.Event.KeyEvent.dwControlKeyState + & (LEFT_CTRL_PRESSED | RIGHT_CTRL_PRESSED | RIGHT_ALT_PRESSED | LEFT_ALT_PRESSED)) != 0) + { + _StickyControlKeyState|= ir.Event.KeyEvent.dwControlKeyState; + _StickySkipKeyUp = true; + return true; + } + } + } + + if (_StickySkipKeyUp) + { + if (!ir.Event.KeyEvent.bKeyDown) + return true; + + _StickySkipKeyUp = false; + } + + if (_StickyControlKeyState) + { + ir.Event.KeyEvent.dwControlKeyState|= _StickyControlKeyState; + if (!ir.Event.KeyEvent.bKeyDown) + _StickyControlKeyState = 0; + } + + return false; +} + +bool console::PeekInput(INPUT_RECORD& Buffer) +{ + for (;;) + { + DWORD NumberOfEventsRead = 0; + if (!WINPORT(PeekConsoleInput)(GetInputHandle(), &Buffer, 1, &NumberOfEventsRead) || !NumberOfEventsRead) + return false; + + if (!InspectStickyKeyEvent(Buffer)) + break; + + if (!WINPORT(ReadConsoleInput)(GetInputHandle(), &Buffer, 1, &NumberOfEventsRead) || !NumberOfEventsRead) + WINPORT(Sleep)(100); + } + + if(Opt.WindowMode && Buffer.EventType==MOUSE_EVENT) + { + Buffer.Event.MouseEvent.dwMousePosition.Y=Max(0, Buffer.Event.MouseEvent.dwMousePosition.Y-GetDelta()); + COORD Size; + GetSize(Size); + Buffer.Event.MouseEvent.dwMousePosition.X=Min(Buffer.Event.MouseEvent.dwMousePosition.X, static_cast<SHORT>(Size.X-1)); + } + + return true; +} + +bool console::ReadInput(INPUT_RECORD& Buffer) +{ + DWORD NumberOfEventsRead = 0; + do { + if (!WINPORT(ReadConsoleInput)(GetInputHandle(), &Buffer, 1, &NumberOfEventsRead) || !NumberOfEventsRead) + return false; + + } while (InspectStickyKeyEvent(Buffer)); + + if(Opt.WindowMode && Buffer.EventType==MOUSE_EVENT) + { + Buffer.Event.MouseEvent.dwMousePosition.Y=Max(0, Buffer.Event.MouseEvent.dwMousePosition.Y-GetDelta()); + COORD Size; + GetSize(Size); + Buffer.Event.MouseEvent.dwMousePosition.X=Min(Buffer.Event.MouseEvent.dwMousePosition.X, static_cast<SHORT>(Size.X-1)); + } + return true; +} + +bool console::WriteInput(INPUT_RECORD& Buffer, DWORD Length, DWORD& NumberOfEventsWritten) +{ + if(Opt.WindowMode && Buffer.EventType==MOUSE_EVENT) + { + Buffer.Event.MouseEvent.dwMousePosition.Y+=GetDelta(); + } + return WINPORT(WriteConsoleInput)(GetInputHandle(), &Buffer, Length, &NumberOfEventsWritten)!=FALSE; +} + +// пишем/читаем порциями по 32 K, иначе проблемы. +const unsigned int MAXSIZE=0x8000; + +bool console::ReadOutput(CHAR_INFO& Buffer, COORD BufferSize, COORD BufferCoord, SMALL_RECT& ReadRegion) +{ + bool Result=false; + int Delta=Opt.WindowMode?GetDelta():0; + ReadRegion.Top+=Delta; + ReadRegion.Bottom+=Delta; + + // skip unused region + PCHAR_INFO BufferStart=&Buffer+BufferCoord.Y*BufferSize.X; + BufferSize.Y-=BufferCoord.Y; + BufferCoord.Y=0; + + if(BufferSize.X*BufferSize.Y*sizeof(CHAR_INFO)>MAXSIZE) + { + BufferSize.Y=static_cast<SHORT>(Max(static_cast<int>(MAXSIZE/(BufferSize.X*sizeof(CHAR_INFO))),1)); + int Height=ReadRegion.Bottom-ReadRegion.Top+1; + int Start=ReadRegion.Top; + SMALL_RECT SavedWriteRegion=ReadRegion; + for(int i=0;i<Height;i+=BufferSize.Y) + { + ReadRegion=SavedWriteRegion; + ReadRegion.Top=Start+i; + PCHAR_INFO BufPtr=BufferStart+i*BufferSize.X; + Result=WINPORT(ReadConsoleOutput)(GetOutputHandle(), BufPtr, BufferSize, BufferCoord, &ReadRegion)!=FALSE; + } + } + else + { + Result=WINPORT(ReadConsoleOutput)(GetOutputHandle(), BufferStart, BufferSize, BufferCoord, &ReadRegion)!=FALSE; + } + + if(Opt.WindowMode) + { + ReadRegion.Top-=Delta; + ReadRegion.Bottom-=Delta; + } + + return Result; +} + +bool console::WriteOutput(const CHAR_INFO& Buffer, COORD BufferSize, COORD BufferCoord, SMALL_RECT& WriteRegion) +{ + bool Result=false; + int Delta=Opt.WindowMode?GetDelta():0; + WriteRegion.Top+=Delta; + WriteRegion.Bottom+=Delta; + + // skip unused region + const CHAR_INFO* BufferStart=&Buffer+BufferCoord.Y*BufferSize.X; + BufferSize.Y-=BufferCoord.Y; + BufferCoord.Y=0; + + if(BufferSize.X*BufferSize.Y*sizeof(CHAR_INFO)>MAXSIZE) + { + BufferSize.Y=static_cast<SHORT>(Max(static_cast<int>(MAXSIZE/(BufferSize.X*sizeof(CHAR_INFO))),1)); + int Height=WriteRegion.Bottom-WriteRegion.Top+1; + int Start=WriteRegion.Top; + SMALL_RECT SavedWriteRegion=WriteRegion; + for(int i=0;i<Height;i+=BufferSize.Y) + { + WriteRegion=SavedWriteRegion; + WriteRegion.Top=Start+i; + const CHAR_INFO* BufPtr=BufferStart+i*BufferSize.X; + Result=WINPORT(WriteConsoleOutput)(GetOutputHandle(), BufPtr, BufferSize, BufferCoord, &WriteRegion)!=FALSE; + } + } + else + { + Result=WINPORT(WriteConsoleOutput)(GetOutputHandle(), BufferStart, BufferSize, BufferCoord, &WriteRegion)!=FALSE; + } + + if(Opt.WindowMode) + { + WriteRegion.Top-=Delta; + WriteRegion.Bottom-=Delta; + } + + return Result; +} + +bool console::Write(LPCWSTR Buffer, DWORD NumberOfCharsToWrite) +{ + DWORD NumberOfCharsWritten; + return WINPORT(WriteConsole)(GetOutputHandle(), Buffer, NumberOfCharsToWrite, &NumberOfCharsWritten, nullptr)!=FALSE; +} + +bool console::GetTextAttributes(WORD& Attributes) +{ + bool Result=false; + CONSOLE_SCREEN_BUFFER_INFO ConsoleScreenBufferInfo; + if(WINPORT(GetConsoleScreenBufferInfo)(GetOutputHandle(), &ConsoleScreenBufferInfo)) + { + Attributes=ConsoleScreenBufferInfo.wAttributes; + Result=true; + } + return Result; +} + +bool console::SetTextAttributes(WORD Attributes) +{ + return WINPORT(SetConsoleTextAttribute)(GetOutputHandle(), Attributes)!=FALSE; +} + +bool console::GetCursorInfo(CONSOLE_CURSOR_INFO& ConsoleCursorInfo) +{ + return WINPORT(GetConsoleCursorInfo)(GetOutputHandle(), &ConsoleCursorInfo)!=FALSE; +} + +bool console::SetCursorInfo(const CONSOLE_CURSOR_INFO& ConsoleCursorInfo) +{ + return WINPORT(SetConsoleCursorInfo)(GetOutputHandle(), &ConsoleCursorInfo)!=FALSE; +} + +bool console::GetCursorPosition(COORD& Position) +{ + bool Result=false; + CONSOLE_SCREEN_BUFFER_INFO ConsoleScreenBufferInfo; + if(WINPORT(GetConsoleScreenBufferInfo)(GetOutputHandle(), &ConsoleScreenBufferInfo)) + { + Position=ConsoleScreenBufferInfo.dwCursorPosition; + if(Opt.WindowMode) + { + Position.Y-=GetDelta(); + } + Result=true; + } + return Result; +} + +bool console::SetCursorPosition(COORD Position) +{ + + if(Opt.WindowMode) + { + ResetPosition(); + COORD Size; + GetSize(Size); + Position.X=Min(Position.X,static_cast<SHORT>(Size.X-1)); + Position.Y=Max(static_cast<SHORT>(0),Position.Y); + Position.Y+=GetDelta(); + } + return WINPORT(SetConsoleCursorPosition)(GetOutputHandle(), Position)!=FALSE; +} + +bool console::FlushInputBuffer() +{ + return WINPORT(FlushConsoleInputBuffer)(GetInputHandle())!=FALSE; +} + +bool console::GetNumberOfInputEvents(DWORD& NumberOfEvents) +{ + return WINPORT(GetNumberOfConsoleInputEvents)(GetInputHandle(), &NumberOfEvents)!=FALSE; +} + +DWORD console::GetAlias(LPCWSTR Source, LPWSTR TargetBuffer, DWORD TargetBufferLength, LPCWSTR ExeName) +{ + return WINPORT(GetConsoleAlias)(const_cast<LPWSTR>(Source), TargetBuffer, TargetBufferLength, const_cast<LPWSTR>(ExeName)); +} + +bool console::GetDisplayMode(DWORD& Mode) +{ + return WINPORT(GetConsoleDisplayMode)(&Mode)!=FALSE; +} + +COORD console::GetLargestWindowSize() +{ + return WINPORT(GetLargestConsoleWindowSize)(GetOutputHandle()); +} + +bool console::SetActiveScreenBuffer(HANDLE ConsoleOutput) +{ + return WINPORT(SetConsoleActiveScreenBuffer)(ConsoleOutput)!=FALSE; +} + +bool console::ClearExtraRegions(WORD Color) +{ + CONSOLE_SCREEN_BUFFER_INFO csbi; + WINPORT(GetConsoleScreenBufferInfo)(GetOutputHandle(), &csbi); + DWORD TopSize = csbi.dwSize.X*csbi.srWindow.Top; + DWORD CharsWritten; + COORD TopCoord={0,0}; + WINPORT(FillConsoleOutputCharacter)(GetOutputHandle(), L' ', TopSize, TopCoord, &CharsWritten); + WINPORT(FillConsoleOutputAttribute)(GetOutputHandle(), Color, TopSize, TopCoord, &CharsWritten ); + + DWORD RightSize = csbi.dwSize.X-csbi.srWindow.Right; + COORD RightCoord={csbi.srWindow.Right,(SHORT)GetDelta()}; + for(; RightCoord.Y<csbi.dwSize.Y; RightCoord.Y++) + { + WINPORT(FillConsoleOutputCharacter)(GetOutputHandle(), L' ', RightSize, RightCoord, &CharsWritten); + WINPORT(FillConsoleOutputAttribute)(GetOutputHandle(), Color, RightSize, RightCoord, &CharsWritten); + } + return true; +} + +bool console::ScrollWindow(int Lines,int Columns) +{ + bool process=false; + CONSOLE_SCREEN_BUFFER_INFO csbi; + WINPORT(GetConsoleScreenBufferInfo)(GetOutputHandle(), &csbi); + + if((Lines<0 && csbi.srWindow.Top) || (Lines>0 && csbi.srWindow.Bottom!=csbi.dwSize.Y-1)) + { + csbi.srWindow.Top+=Lines; + csbi.srWindow.Bottom+=Lines; + + if(csbi.srWindow.Top<0) + { + csbi.srWindow.Bottom-=csbi.srWindow.Top; + csbi.srWindow.Top=0; + } + + if(csbi.srWindow.Bottom>=csbi.dwSize.Y) + { + csbi.srWindow.Top-=(csbi.srWindow.Bottom-(csbi.dwSize.Y-1)); + csbi.srWindow.Bottom=csbi.dwSize.Y-1; + } + process=true; + } + + if((Columns<0 && csbi.srWindow.Left) || (Columns>0 && csbi.srWindow.Right!=csbi.dwSize.X-1)) + { + csbi.srWindow.Left+=Columns; + csbi.srWindow.Right+=Columns; + + if(csbi.srWindow.Left<0) + { + csbi.srWindow.Right-=csbi.srWindow.Left; + csbi.srWindow.Left=0; + } + + if(csbi.srWindow.Right>=csbi.dwSize.X) + { + csbi.srWindow.Left-=(csbi.srWindow.Right-(csbi.dwSize.X-1)); + csbi.srWindow.Right=csbi.dwSize.X-1; + } + process=true; + } + + if (process) + { + SetWindowRect(csbi.srWindow); + return true; + } + + return false; +} + +bool console::ScrollScreenBuffer(int Lines) +{ + CONSOLE_SCREEN_BUFFER_INFO csbi; + WINPORT(GetConsoleScreenBufferInfo)(GetOutputHandle(), &csbi); + SMALL_RECT ScrollRectangle={0, 0, (SHORT)(csbi.dwSize.X-1), (SHORT)(csbi.dwSize.Y-1)}; + COORD DestinationOrigin={0,(SHORT)(-Lines)}; + CHAR_INFO Fill={{L' '}, FarColorToReal(COL_COMMANDLINEUSERSCREEN)}; + return WINPORT(ScrollConsoleScreenBuffer)(GetOutputHandle(), &ScrollRectangle, nullptr, DestinationOrigin, &Fill)!=FALSE; +} + +bool console::ResetPosition() +{ + CONSOLE_SCREEN_BUFFER_INFO csbi; + WINPORT(GetConsoleScreenBufferInfo)(GetOutputHandle(), &csbi); + if(csbi.srWindow.Left || csbi.srWindow.Bottom!=csbi.dwSize.Y-1) + { + csbi.srWindow.Right-=csbi.srWindow.Left; + csbi.srWindow.Left=0; + csbi.srWindow.Top+=csbi.dwSize.Y-1-csbi.srWindow.Bottom; + csbi.srWindow.Bottom=csbi.dwSize.Y-1; + SetWindowRect(csbi.srWindow); + } + return true; +} + +int console::GetDelta() +{ + CONSOLE_SCREEN_BUFFER_INFO csbi; + WINPORT(GetConsoleScreenBufferInfo)(GetOutputHandle(), &csbi); + return csbi.dwSize.Y-(csbi.srWindow.Bottom-csbi.srWindow.Top+1); +} + +BOOL console::IsZoomed() +{ + //todo + return FALSE; +} + +BOOL console::IsIconic() +{ + //todo + return FALSE; +} diff --git a/far2l/src/console/console.hpp b/far2l/src/console/console.hpp new file mode 100644 index 00000000..2b05483b --- /dev/null +++ b/far2l/src/console/console.hpp @@ -0,0 +1,120 @@ +#pragma once + +/* +console.hpp + +Console functions +*/ +/* +Copyright (c) 2010 Far Group +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <WinCompat.h> +#include "FARString.hpp" + +class console +{ + DWORD _StickyControlKeyState = 0; + bool _StickySkipKeyUp = 0; + + bool InspectStickyKeyEvent(INPUT_RECORD& ir); + +public: + bool Allocate(); + bool Free(); + + HANDLE GetInputHandle(); + HANDLE GetOutputHandle(); + HANDLE GetErrorHandle(); + + BOOL IsZoomed(); + BOOL IsIconic(); + + bool GetSize(COORD& Size); + bool SetSize(COORD Size); + + bool GetWindowRect(SMALL_RECT& ConsoleWindow); + bool SetWindowRect(const SMALL_RECT& ConsoleWindow); + + bool GetWorkingRect(SMALL_RECT& WorkingRect); + + bool GetTitle(FARString &strTitle); + bool SetTitle(LPCWSTR Title); + + bool GetKeyboardLayoutName(FARString &strName); + + UINT GetInputCodepage(); + bool SetInputCodepage(UINT Codepage); + + UINT GetOutputCodepage(); + bool SetOutputCodepage(UINT Codepage); + + bool SetControlHandler(PHANDLER_ROUTINE HandlerRoutine, bool Add); + + bool GetMode(HANDLE ConsoleHandle, DWORD& Mode); + bool SetMode(HANDLE ConsoleHandle, DWORD Mode); + + bool PeekInput(INPUT_RECORD& Buffer); + bool ReadInput(INPUT_RECORD& Buffer); + bool WriteInput(INPUT_RECORD& Buffer, DWORD Length, DWORD& NumberOfEventsWritten); + bool ReadOutput(CHAR_INFO& Buffer, COORD BufferSize, COORD BufferCoord, SMALL_RECT& ReadRegion); + bool WriteOutput(const CHAR_INFO& Buffer, COORD BufferSize, COORD BufferCoord, SMALL_RECT& WriteRegion); + bool Write(LPCWSTR Buffer, DWORD NumberOfCharsToWrite); + + bool GetTextAttributes(WORD& Attributes); + bool SetTextAttributes(WORD Attributes); + + bool GetCursorInfo(CONSOLE_CURSOR_INFO& ConsoleCursorInfo); + bool SetCursorInfo(const CONSOLE_CURSOR_INFO& ConsoleCursorInfo); + + bool GetCursorPosition(COORD& Position); + bool SetCursorPosition(COORD Position); + + bool FlushInputBuffer(); + + bool GetNumberOfInputEvents(DWORD& NumberOfEvents); + + DWORD GetAlias(LPCWSTR Source, LPWSTR TargetBuffer, DWORD TargetBufferLength, LPCWSTR ExeName); + + bool GetDisplayMode(DWORD& Mode); + + COORD GetLargestWindowSize(); + + bool SetActiveScreenBuffer(HANDLE ConsoleOutput); + + bool ClearExtraRegions(WORD Color); + + bool ScrollWindow(int Lines,int Columns=0); + + bool ScrollScreenBuffer(int Lines); + + bool ResetPosition(); + +private: + int GetDelta(); +}; + +extern console Console; diff --git a/far2l/src/console/constitle.cpp b/far2l/src/console/constitle.cpp new file mode 100644 index 00000000..b4e20dc3 --- /dev/null +++ b/far2l/src/console/constitle.cpp @@ -0,0 +1,158 @@ +/* +constitle.cpp + +Заголовок консоли +*/ +/* +Copyright (c) 1996 Eugene Roshal +Copyright (c) 2000 Far Group +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "headers.hpp" + + +#include "constitle.hpp" +#include "lang.hpp" +#include "language.hpp" +#include "interf.hpp" +#include "config.hpp" +#include "ctrlobj.hpp" +#include "CriticalSections.hpp" +#include "console.hpp" +#include <stdarg.h> + +static const FARString& GetFarTitleAddons() +{ + // " - Far%Ver%Backend%Admin" + /* + %Ver - 2.3.102-beta + %Platform - x86 + %Backend - gui + %Admin - MFarTitleAddonsAdmin + */ + static FARString strVer(FAR_BUILD); + static FARString strPlatform(FAR_PLATFORM); + static FARString strTitleAddons; + + strTitleAddons = L" - FAR2L "; + strTitleAddons+= Opt.strTitleAddons; + + ReplaceStrings(strTitleAddons,L"%Ver",strVer,-1); + ReplaceStrings(strTitleAddons,L"%Platform", strPlatform, -1); + ReplaceStrings(strTitleAddons,L"%Backend", WinPortBackend(), -1); + ReplaceStrings(strTitleAddons,L"%Admin",Opt.IsUserAdmin?MSG(MFarTitleAddonsAdmin):L"",-1); + + FARString hn, un; + apiGetEnvironmentVariable("HOSTNAME", hn); + apiGetEnvironmentVariable("USER", un); + ReplaceStrings(strTitleAddons,L"%Host",hn,-1); + ReplaceStrings(strTitleAddons,L"%User",un,-1); + + RemoveTrailingSpaces(strTitleAddons); + + return strTitleAddons; +} + +bool ConsoleTitle::TitleModified = false; +DWORD ConsoleTitle::ShowTime = 0; + +CriticalSection TitleCS; + +ConsoleTitle::ConsoleTitle(const wchar_t *title) +{ + CriticalSectionLock Lock(TitleCS); + Console.GetTitle(strOldTitle); + + if (title) + ConsoleTitle::SetFarTitle(title, true); +} + +ConsoleTitle::~ConsoleTitle() +{ + CriticalSectionLock Lock(TitleCS); + const FARString &strTitleAddons = GetFarTitleAddons(); + size_t OldLen = strOldTitle.GetLength(); + size_t AddonsLen = strTitleAddons.GetLength(); + + if (AddonsLen <= OldLen) + { + if (!StrCmpI(strOldTitle.CPtr()+OldLen-AddonsLen, strTitleAddons)) + strOldTitle.Truncate(OldLen-AddonsLen); + } + + ConsoleTitle::SetFarTitle(strOldTitle, true); +} + +void ConsoleTitle::Set(const wchar_t *fmt, ...) +{ + CriticalSectionLock Lock(TitleCS); + wchar_t msg[2048]; + va_list argptr; + va_start(argptr, fmt); + vswprintf(msg, ARRAYSIZE(msg)-1, fmt, argptr); + va_end(argptr); + SetFarTitle(msg); +} + +void ConsoleTitle::SetFarTitle(const wchar_t *Title, bool Force) +{ + CriticalSectionLock Lock(TitleCS); + static FARString strFarTitle; + FARString strOldFarTitle; + + if (Title) + { + Console.GetTitle(strOldFarTitle); + strFarTitle=Title; + strFarTitle.Truncate(0x100); + strFarTitle+=GetFarTitleAddons(); + TitleModified=true; + + if (StrCmp(strOldFarTitle, strFarTitle) && + ((CtrlObject->Macro.IsExecuting() && !CtrlObject->Macro.IsDsableOutput()) || + !CtrlObject->Macro.IsExecuting() || CtrlObject->Macro.IsExecutingLastKey())) + { + DWORD CurTime=WINPORT(GetTickCount)(); + if(CurTime-ShowTime>RedrawTimeout || Force) + { + ShowTime=CurTime; + Console.SetTitle(strFarTitle); + TitleModified=true; + } + } + } + else + { + /* + Title=nullptr для случая, когда нужно выставить пред.заголовок + SetFarTitle(nullptr) - это не для всех! + Этот вызов имеет право делать только макро-движок! + */ + Console.SetTitle(strFarTitle); + TitleModified=false; + //_SVS(SysLog(L" (nullptr)FarTitle='%s'",FarTitle)); + } +} diff --git a/far2l/src/console/constitle.hpp b/far2l/src/console/constitle.hpp new file mode 100644 index 00000000..ff1dbc3c --- /dev/null +++ b/far2l/src/console/constitle.hpp @@ -0,0 +1,55 @@ +#pragma once + +/* +constitle.hpp + +Заголовок консоли +*/ +/* +Copyright (c) 1996 Eugene Roshal +Copyright (c) 2000 Far Group +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "FARString.hpp" + +class ConsoleTitle +{ + private: + FARString strOldTitle; + static bool TitleModified; + static DWORD ShowTime; + + public: + ConsoleTitle(const wchar_t *title=nullptr); + ~ConsoleTitle(); + + public: + void Set(const wchar_t *fmt,...); + + public: + static void SetFarTitle(const wchar_t *Title, bool Force=false); + static bool WasTitleModified() { return TitleModified; } +}; diff --git a/far2l/src/console/grabber.cpp b/far2l/src/console/grabber.cpp new file mode 100644 index 00000000..e146286f --- /dev/null +++ b/far2l/src/console/grabber.cpp @@ -0,0 +1,488 @@ +/* +grabber.cpp + +Screen grabber +*/ +/* +Copyright (c) 1996 Eugene Roshal +Copyright (c) 2000 Far Group +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "headers.hpp" + + +#include "grabber.hpp" +#include "keyboard.hpp" +#include "colors.hpp" +#include "keys.hpp" +#include "savescr.hpp" +#include "ctrlobj.hpp" +#include "manager.hpp" +#include "frame.hpp" +#include "interf.hpp" +#include "clipboard.hpp" +#include "config.hpp" + +Grabber::Grabber() : + CMM(MACRO_OTHER) +{ + Frame *pFrame = FrameManager->GetCurrentFrame(); + pFrame->Lock(); + SaveScr=new SaveScreen; + memset(&GArea,0,sizeof(GArea)); + memset(&PrevArea,0,sizeof(PrevArea)); + bool Visible=false; + DWORD Size=0; + GetCursorType(Visible,Size); + + if (Visible) + GetCursorPos(GArea.CurX,GArea.CurY); + else + { + GArea.CurX=0; + GArea.CurY=0; + } + + GArea.X1=-1; + SetCursorType(TRUE,60); + PrevArea=GArea; + ResetArea=TRUE; + DisplayObject(); + Process(); + delete SaveScr; + pFrame->Unlock(); + FrameManager->RefreshFrame(); +} + + +Grabber::~Grabber() +{ +} + + +void Grabber::CopyGrabbedArea(int Append) +{ + if (GArea.X1 < 0) + return; + + int X1,Y1,X2,Y2; + X1=Min(GArea.X1,GArea.X2); + X2=Max(GArea.X1,GArea.X2); + Y1=Min(GArea.Y1,GArea.Y2); + Y2=Max(GArea.Y1,GArea.Y2); + int GWidth=X2-X1+1,GHeight=Y2-Y1+1; + int BufSize=(GWidth+3)*GHeight; + CHAR_INFO *CharBuf=new CHAR_INFO[BufSize], *PtrCharBuf; + wchar_t *CopyBuf=(wchar_t *)malloc(BufSize*sizeof(wchar_t)), *PtrCopyBuf; + WORD Chr; + GetText(X1,Y1,X2,Y2,CharBuf,BufSize*sizeof(CHAR_INFO)); + *CopyBuf=0; + PtrCharBuf=CharBuf; + PtrCopyBuf=CopyBuf; + + for (int I=0; I<GHeight; I++) + { + if (I>0) + { + *PtrCopyBuf++=L'\r'; + *PtrCopyBuf++=L'\n'; + *PtrCopyBuf=0; + } + + for (int J=0; J<GWidth; J++, ++PtrCharBuf) + { + WORD Chr2 = PtrCharBuf->Char.UnicodeChar; + Chr=PtrCharBuf->Char.UnicodeChar; + + if (Opt.CleanAscii) + { + switch (Chr2) + { + case L'.': Chr=L'.'; break; + case 0x07: Chr=L'*'; break; + case 0x10: Chr=L'>'; break; + case 0x11: Chr=L'<'; break; + case 0x18: + case 0x19: Chr=L'|'; break; + case 0x1E: + case 0x1F: Chr=L'X'; break; + case 0xFF: Chr=L' '; break; + default: + + if (Chr2 < 0x20) + Chr=L'.'; + else if (Chr2 < 0x100) + Chr=Chr2; + + break; + } + } + + if (Opt.NoGraphics && Chr2 >=0xB3 && Chr2 <= 0xDA) + { + switch (Chr2) + { + case 0xB3: + case 0xBA: Chr=L'|'; break; + case 0xC4: Chr=L'-'; break; + case 0xCD: Chr=L'='; break; + default: Chr=L'+'; break; + } + } + + *PtrCopyBuf++=Chr; + *PtrCopyBuf=0; + } + + for (int K=StrLength(CopyBuf)-1; K>=0 && CopyBuf[K]==L' '; K--) + CopyBuf[K]=0; + + PtrCopyBuf=CopyBuf+StrLength(CopyBuf); + } + + Clipboard clip; + + if (clip.Open()) + { + if (Append) + { + wchar_t *AppendBuf=clip.Paste(); + int add=0; + + if (AppendBuf) + { + size_t DataSize=StrLength(AppendBuf); + + if (AppendBuf[DataSize-1]!=L'\n') + { + add=2; + } + + AppendBuf=(wchar_t *)realloc(AppendBuf,(DataSize+BufSize+add)*sizeof(wchar_t)); + wmemcpy(AppendBuf+DataSize+add,CopyBuf,BufSize); + + if (add) { + wmemcpy(AppendBuf+DataSize, NATIVE_EOLW, wcslen(NATIVE_EOLW)); + } + + free(CopyBuf); + CopyBuf=AppendBuf; + } + } + + clip.Copy(CopyBuf); + + clip.Close(); + } + if (CopyBuf) + free(CopyBuf); + + delete[] CharBuf; +} + + +void Grabber::DisplayObject() +{ + MoveCursor(GArea.CurX,GArea.CurY); + + if (PrevArea.X1!=GArea.X1 || PrevArea.X2!=GArea.X2 || + PrevArea.Y1!=GArea.Y1 || PrevArea.Y2!=GArea.Y2) + { + int X1,Y1,X2,Y2; + X1=Min(GArea.X1,GArea.X2); + X2=Max(GArea.X1,GArea.X2); + Y1=Min(GArea.Y1,GArea.Y2); + Y2=Max(GArea.Y1,GArea.Y2); + + if (X1>Min(PrevArea.X1,PrevArea.X2) || X2<Max(PrevArea.X1,PrevArea.X2) || + Y1>Min(PrevArea.Y1,PrevArea.Y2) || Y2<Max(PrevArea.Y1,PrevArea.Y2)) + SaveScr->RestoreArea(FALSE); + + if (GArea.X1!=-1) + { + CHAR_INFO *CharBuf=new CHAR_INFO[(X2-X1+1)*(Y2-Y1+1)]; + CHAR_INFO *PrevBuf=SaveScr->GetBufferAddress(); + GetText(X1,Y1,X2,Y2,CharBuf,sizeof(CHAR_INFO)*(X2-X1+1)*(Y2-Y1+1)); + + for (int X=X1; X<=X2; X++) + for (int Y=Y1; Y<=Y2; Y++) + { + int NewColor; + + if ((PrevBuf[X+Y*(ScrX+1)].Attributes & B_LIGHTGRAY)==B_LIGHTGRAY) + NewColor=B_BLACK|F_LIGHTGRAY; + else + NewColor=B_LIGHTGRAY|F_BLACK; + + int Pos=(X-X1)+(Y-Y1)*(X2-X1+1); + CharBuf[Pos].Attributes=(CharBuf[Pos].Attributes & ~0xff) | NewColor; + } + + PutText(X1,Y1,X2,Y2,CharBuf); + delete[] CharBuf; + } + + if (GArea.X1==-2) + { + SaveScr->RestoreArea(FALSE); + GArea.X1=GArea.X2; + } + + PrevArea=GArea; + } +} + + +int Grabber::ProcessKey(int Key) +{ + /* $ 14.03.2001 SVS + [-] Неправильно воспроизводился макрос в режиме грабления экрана. + При воспроизведении клавиша Home перемещала курсор в координаты + 0,0 консоли. + Не было учтено режима выполнения макроса. + */ + SetCursorType(TRUE,60); + + if (CtrlObject->Macro.IsExecuting()) + { + if ((Key&KEY_SHIFT) && Key!=KEY_NONE && ResetArea) + Reset(); + else if (Key!=KEY_IDLE && Key!=KEY_NONE && !(Key&KEY_SHIFT)) + ResetArea=TRUE; + } + else + { + if ((ShiftPressed || Key!=KEY_SHIFT) && (Key&KEY_SHIFT) && Key!=KEY_NONE && ResetArea) + Reset(); + else if (Key!=KEY_IDLE && Key!=KEY_NONE && Key!=KEY_SHIFT && !ShiftPressed && !(Key&KEY_SHIFT)) + ResetArea=TRUE; + } + + switch (Key) + { + case KEY_CTRLU: + Reset(); + GArea.X1=-2; + break; + case KEY_ESC: + SetExitCode(0); + break; + case KEY_NUMENTER: + case KEY_ENTER: + case KEY_CTRLINS: case KEY_CTRLNUMPAD0: + case KEY_CTRLADD: + CopyGrabbedArea(Key == KEY_CTRLADD); + SetExitCode(1); + break; + case KEY_LEFT: case KEY_NUMPAD4: case L'4': + + if (GArea.CurX>0) + GArea.CurX--; + + break; + case KEY_RIGHT: case KEY_NUMPAD6: case L'6': + + if (GArea.CurX<ScrX) + GArea.CurX++; + + break; + case KEY_UP: case KEY_NUMPAD8: case L'8': + + if (GArea.CurY>0) + GArea.CurY--; + + break; + case KEY_DOWN: case KEY_NUMPAD2: case L'2': + + if (GArea.CurY<ScrY) + GArea.CurY++; + + break; + case KEY_HOME: case KEY_NUMPAD7: case L'7': + GArea.CurX=0; + break; + case KEY_END: case KEY_NUMPAD1: case L'1': + GArea.CurX=ScrX; + break; + case KEY_PGUP: case KEY_NUMPAD9: case L'9': + GArea.CurY=0; + break; + case KEY_PGDN: case KEY_NUMPAD3: case L'3': + GArea.CurY=ScrY; + break; + case KEY_CTRLHOME: case KEY_CTRLNUMPAD7: + GArea.CurX=GArea.CurY=0; + break; + case KEY_CTRLEND: case KEY_CTRLNUMPAD1: + GArea.CurX=ScrX; + GArea.CurY=ScrY; + break; + case KEY_CTRLLEFT: case KEY_CTRLNUMPAD4: + case KEY_CTRLSHIFTLEFT: case KEY_CTRLSHIFTNUMPAD4: + + if ((GArea.CurX-=10)<0) + GArea.CurX=0; + + if (Key == KEY_CTRLSHIFTLEFT || Key == KEY_CTRLSHIFTNUMPAD4) + GArea.X1=GArea.CurX; + + break; + case KEY_CTRLRIGHT: case KEY_CTRLNUMPAD6: + case KEY_CTRLSHIFTRIGHT: case KEY_CTRLSHIFTNUMPAD6: + + if ((GArea.CurX+=10)>ScrX) + GArea.CurX=ScrX; + + if (Key == KEY_CTRLSHIFTRIGHT || Key == KEY_CTRLSHIFTNUMPAD6) + GArea.X1=GArea.CurX; + + break; + case KEY_CTRLUP: case KEY_CTRLNUMPAD8: + case KEY_CTRLSHIFTUP: case KEY_CTRLSHIFTNUMPAD8: + + if ((GArea.CurY-=5)<0) + GArea.CurY=0; + + if (Key == KEY_CTRLSHIFTUP || Key == KEY_CTRLSHIFTNUMPAD8) + GArea.Y1=GArea.CurY; + + break; + case KEY_CTRLDOWN: case KEY_CTRLNUMPAD2: + case KEY_CTRLSHIFTDOWN: case KEY_CTRLSHIFTNUMPAD2: + + if ((GArea.CurY+=5)>ScrY) + GArea.CurY=ScrY; + + if (Key == KEY_CTRLSHIFTDOWN || Key == KEY_CTRLSHIFTNUMPAD8) + GArea.Y1=GArea.CurY; + + break; + case KEY_SHIFTLEFT: case KEY_SHIFTNUMPAD4: + + if (GArea.X1>0) + GArea.X1--; + + GArea.CurX=GArea.X1; + break; + case KEY_SHIFTRIGHT: case KEY_SHIFTNUMPAD6: + + if (GArea.X1<ScrX) + GArea.X1++; + + GArea.CurX=GArea.X1; + break; + case KEY_SHIFTUP: case KEY_SHIFTNUMPAD8: + + if (GArea.Y1>0) + GArea.Y1--; + + GArea.CurY=GArea.Y1; + break; + case KEY_SHIFTDOWN: case KEY_SHIFTNUMPAD2: + + if (GArea.Y1<ScrY) + GArea.Y1++; + + GArea.CurY=GArea.Y1; + break; + case KEY_SHIFTHOME: case KEY_SHIFTNUMPAD7: + GArea.CurX=GArea.X1=0; + break; + case KEY_SHIFTEND: case KEY_SHIFTNUMPAD1: + GArea.CurX=GArea.X1=ScrX; + break; + case KEY_SHIFTPGUP: case KEY_SHIFTNUMPAD9: + GArea.CurY=GArea.Y1=0; + break; + case KEY_SHIFTPGDN: case KEY_SHIFTNUMPAD3: + GArea.CurY=GArea.Y1=ScrY; + break; + } + + DisplayObject(); + return TRUE; +} + + +int Grabber::ProcessMouse(MOUSE_EVENT_RECORD *MouseEvent) +{ + if (MouseEvent->dwEventFlags==DOUBLE_CLICK || + (!MouseEvent->dwEventFlags && (MouseEvent->dwButtonState & RIGHTMOST_BUTTON_PRESSED))) + { + ProcessKey(KEY_ENTER); + return TRUE; + } + + if (MouseButtonState!=FROM_LEFT_1ST_BUTTON_PRESSED) + return FALSE; + + GArea.CurX=Min(Max(static_cast<SHORT>(0),MouseX),ScrX); + GArea.CurY=Min(Max(static_cast<SHORT>(0),MouseY),ScrY); + + if (!MouseEvent->dwEventFlags) + ResetArea=TRUE; + else if (MouseEvent->dwEventFlags==MOUSE_MOVED) + { + if (ResetArea) + { + GArea.X2=GArea.CurX; + GArea.Y2=GArea.CurY; + ResetArea=FALSE; + } + + GArea.X1=GArea.CurX; + GArea.Y1=GArea.CurY; + } + + //VerticalBlock=MouseEvent->dwControlKeyState&(LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED); + DisplayObject(); + return TRUE; +} + +void Grabber::Reset() +{ + GArea.X1=GArea.X2=GArea.CurX; + GArea.Y1=GArea.Y2=GArea.CurY; + ResetArea=FALSE; + //DisplayObject(); +} + +bool RunGraber() +{ + static bool InGrabber=false; + + if (!InGrabber) + { + InGrabber=true; + WaitInMainLoop=FALSE; + FlushInputBuffer(); + Grabber Grabber; + InGrabber=false; + return true; + } + + return false; +} diff --git a/far2l/src/console/grabber.hpp b/far2l/src/console/grabber.hpp new file mode 100644 index 00000000..0c8597b2 --- /dev/null +++ b/far2l/src/console/grabber.hpp @@ -0,0 +1,66 @@ +#pragma once + +/* +grabber.hpp + +Screen grabber +*/ +/* +Copyright (c) 1996 Eugene Roshal +Copyright (c) 2000 Far Group +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "modal.hpp" +#include "chgmmode.hpp" + +struct GrabberArea +{ + SHORT X1,Y1,X2,Y2; + SHORT CurX,CurY; +}; + +class Grabber:Modal +{ + private: + ChangeMacroMode CMM; + SaveScreen *SaveScr; + GrabberArea PrevArea; + GrabberArea GArea; + int ResetArea; + + private: + virtual void DisplayObject(); + virtual int ProcessKey(int Key); + virtual int ProcessMouse(MOUSE_EVENT_RECORD *MouseEvent); + void CopyGrabbedArea(int Append); + void Reset(); + + public: + Grabber(); + virtual ~Grabber(); +}; + +bool RunGraber(); diff --git a/far2l/src/console/interf.cpp b/far2l/src/console/interf.cpp new file mode 100644 index 00000000..d70fd23d --- /dev/null +++ b/far2l/src/console/interf.cpp @@ -0,0 +1,1260 @@ +/* +interf.cpp + +Консольные функции ввода-вывода +*/ +/* +Copyright (c) 1996 Eugene Roshal +Copyright (c) 2000 Far Group +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "headers.hpp" + +#include <stdarg.h> + +#include "interf.hpp" +#include "keyboard.hpp" +#include "keys.hpp" +#include "colors.hpp" +#include "ctrlobj.hpp" +#include "filepanels.hpp" +#include "panel.hpp" +#include "fileedit.hpp" +#include "manager.hpp" +#include "scrbuf.hpp" +#include "syslog.hpp" +#include "palette.hpp" +#include "strmix.hpp" +#include "console.hpp" +#include "vtshell.h" + +BOOL WINAPI CtrlHandler(DWORD CtrlType); + +static int CurX,CurY; +static int CurColor; + +static CONSOLE_CURSOR_INFO InitialCursorInfo; + +static SMALL_RECT windowholder_rect; + +WCHAR Oem2Unicode[256]; +WCHAR BoxSymbols[64]; + +COORD InitSize{}; +COORD CurSize{}; +SHORT ScrX=0,ScrY=0; +SHORT PrevScrX=-1,PrevScrY=-1; +DWORD InitialConsoleMode=0; +FARString strInitTitle; +SMALL_RECT InitWindowRect; +COORD InitialSize; + +//static HICON hOldLargeIcon=nullptr, hOldSmallIcon=nullptr; + +const size_t StackBufferSize=0x2000; + +void InitConsole(int FirstInit) +{ + InitRecodeOutTable(); + Console.GetCursorInfo(InitialCursorInfo); + Console.SetControlHandler(CtrlHandler,TRUE); + Console.GetMode(Console.GetInputHandle(),InitialConsoleMode); + Console.GetTitle(strInitTitle); + Console.GetWindowRect(InitWindowRect); + Console.GetSize(InitialSize); + CONSOLE_CURSOR_INFO InitCursorInfo; + Console.GetCursorInfo(InitCursorInfo); + + AssertConfigLoaded(); + + // размер клавиатурной очереди = 1024 кода клавиши + if (!KeyQueue) + KeyQueue=new FarQueue<DWORD>(1024); + + SetFarConsoleMode(); + + /* $ 09.04.2002 DJ + если размер консольного буфера больше размера окна, выставим + их равными + */ + if (FirstInit) + { + SMALL_RECT WindowRect; + Console.GetWindowRect(WindowRect); + GetVideoMode(InitSize); + + if(Opt.WindowMode) + { + Console.ResetPosition(); + } + else + { + if (WindowRect.Left || WindowRect.Top || WindowRect.Right != InitSize.X-1 || WindowRect.Bottom != InitSize.Y-1) + { + COORD newSize; + newSize.X = WindowRect.Right - WindowRect.Left + 1; + newSize.Y = WindowRect.Bottom - WindowRect.Top + 1; + Console.SetSize(newSize); + GetVideoMode(InitSize); + } + } + } + + GetVideoMode(CurSize); + ScrBuf.FillBuf(); +} + +void CloseConsole() +{ + ScrBuf.Flush(); + Console.SetCursorInfo(InitialCursorInfo); + ChangeConsoleMode(InitialConsoleMode); + + Console.SetTitle(strInitTitle); + Console.SetSize(InitialSize); + Console.SetWindowRect(InitWindowRect); + Console.SetSize(InitialSize); + + delete KeyQueue; + KeyQueue=nullptr; +} + + +void SetFarConsoleMode(BOOL SetsActiveBuffer) +{ + int Mode=ENABLE_WINDOW_INPUT; + + if (Opt.Mouse) + { + //ENABLE_EXTENDED_FLAGS actually disables all the extended flags. + Mode|=ENABLE_MOUSE_INPUT|ENABLE_EXTENDED_FLAGS; + } + else + { + //если вдруг изменили опцию во время работы фара, то включим то что надо + Mode|=InitialConsoleMode&(ENABLE_EXTENDED_FLAGS|ENABLE_QUICK_EDIT_MODE); + } + + if (SetsActiveBuffer) + Console.SetActiveScreenBuffer(Console.GetOutputHandle()); + + ChangeConsoleMode(Mode); +} + +void ChangeConsoleMode(int Mode) +{ + DWORD CurrentConsoleMode; + HANDLE hConIn = Console.GetInputHandle(); + Console.GetMode(hConIn, CurrentConsoleMode); + + if (CurrentConsoleMode!=(DWORD)Mode) + Console.SetMode(hConIn, Mode); +} + +void SaveConsoleWindowRect() +{ + Console.GetWindowRect(windowholder_rect); +} + +void RestoreConsoleWindowRect() +{ + SMALL_RECT WindowRect; + Console.GetWindowRect(WindowRect); + if(WindowRect.Right-WindowRect.Left<windowholder_rect.Right-windowholder_rect.Left || + WindowRect.Bottom-WindowRect.Top<windowholder_rect.Bottom-windowholder_rect.Top) + { + Console.SetWindowRect(windowholder_rect); + } +} + +void FlushInputBuffer() +{ + Console.FlushInputBuffer(); + MouseButtonState=0; + MouseEventFlags=0; +} + +void SetVideoMode() +{ + if (!IsFullscreen()) + { + ChangeVideoMode(InitSize.X==CurSize.X && InitSize.Y==CurSize.Y); + } + else + { + ChangeVideoMode(ScrY==24?50:25,80); + } +} + +void ChangeVideoMode(int Maximized) +{ + COORD coordScreen; + + if (Maximized) + { + WINPORT(SetConsoleWindowMaximized)(TRUE); + //SendMessage(Console.GetWindow(),WM_SYSCOMMAND,SC_MAXIMIZE,0); + coordScreen = Console.GetLargestWindowSize(); + coordScreen.X+=Opt.ScrSize.DeltaXY.X; + coordScreen.Y+=Opt.ScrSize.DeltaXY.Y; + } + else + { + WINPORT(SetConsoleWindowMaximized)(FALSE); + //SendMessage(Console.GetWindow(),WM_SYSCOMMAND,SC_RESTORE,0); + coordScreen = InitSize; + } + + ChangeVideoMode(coordScreen.Y,coordScreen.X); +} + +void ChangeVideoMode(int NumLines,int NumColumns) +{ + int xSize=NumColumns,ySize=NumLines; + + COORD Size; + Console.GetSize(Size); + + SMALL_RECT srWindowRect; + srWindowRect.Right = xSize-1; + srWindowRect.Bottom = ySize-1; + srWindowRect.Left = srWindowRect.Top = 0; + + COORD coordScreen={(SHORT)xSize,(SHORT)ySize}; + + if (xSize>Size.X || ySize > Size.Y) + { + if (Size.X < xSize-1) + { + srWindowRect.Right = Size.X - 1; + Console.SetWindowRect(srWindowRect); + srWindowRect.Right = xSize-1; + } + + if (Size.Y < ySize-1) + { + srWindowRect.Bottom=Size.Y - 1; + Console.SetWindowRect(srWindowRect); + srWindowRect.Bottom = ySize-1; + } + + Console.SetSize(coordScreen); + } + + if (!Console.SetWindowRect(srWindowRect)) + { + Console.SetSize(coordScreen); + Console.SetWindowRect(srWindowRect); + } + else + { + Console.SetSize(coordScreen); + } + + // зашлем эвент только в случае, когда макросы не исполняются + if (CtrlObject && !CtrlObject->Macro.IsExecuting()) + GenerateWINDOW_BUFFER_SIZE_EVENT(NumColumns,NumLines); +} + +void GenerateWINDOW_BUFFER_SIZE_EVENT(int Sx, int Sy) +{ + COORD Size; + if (Sx==-1 || Sy==-1) + { + Console.GetSize(Size); + } + INPUT_RECORD Rec; + Rec.EventType=WINDOW_BUFFER_SIZE_EVENT; + Rec.Event.WindowBufferSizeEvent.dwSize.X=Sx==-1?Size.X:Sx; + Rec.Event.WindowBufferSizeEvent.dwSize.Y=Sy==-1?Size.Y:Sy; + DWORD Writes; + Console.WriteInput(Rec,1,Writes); +} + +void GetVideoMode(COORD& Size) +{ + //чтоб решить баг винды приводящий к появлению скролов и т.п. после потери фокуса + SaveConsoleWindowRect(); + Size.X=0; + Size.Y=0; + Console.GetSize(Size); + ScrX=Size.X-1; + ScrY=Size.Y-1; + assert(ScrX>0); + assert(ScrY>0); + WidthNameForMessage=(ScrX*38)/100+1; + + if (PrevScrX == -1) PrevScrX=ScrX; + + if (PrevScrY == -1) PrevScrY=ScrY; + + _OT(SysLog(L"ScrX=%d ScrY=%d",ScrX,ScrY)); + ScrBuf.AllocBuf(Size.X,Size.Y); + _OT(ViewConsoleInfo()); +} + +BOOL WINAPI CtrlHandler(DWORD CtrlType) +{ + /* + TODO: need handle + CTRL_CLOSE_EVENT + CTRL_LOGOFF_EVENT + CTRL_SHUTDOWN_EVENT + */ + if (CtrlType==CTRL_C_EVENT || CtrlType==CTRL_BREAK_EVENT) + { + if (CtrlType==CTRL_BREAK_EVENT) + WriteInput(KEY_BREAK); + + if (CtrlObject && CtrlObject->Cp()) + { + if (CtrlObject->Cp()->LeftPanel && CtrlObject->Cp()->LeftPanel->GetMode()==PLUGIN_PANEL) + CtrlObject->Plugins.ProcessEvent(CtrlObject->Cp()->LeftPanel->GetPluginHandle(),FE_BREAK,(void *)(DWORD_PTR)CtrlType); + + if (CtrlObject->Cp()->RightPanel && CtrlObject->Cp()->RightPanel->GetMode()==PLUGIN_PANEL) + CtrlObject->Plugins.ProcessEvent(CtrlObject->Cp()->RightPanel->GetPluginHandle(),FE_BREAK,(void *)(DWORD_PTR)CtrlType); + } + + return TRUE; + } + + if (!CtrlObject->Plugins.MayExitFar()) { + return TRUE; + } + + CloseFAR=TRUE; + + + /* $ 30.08.2001 IS + При закрытии окна "по кресту" всегда возвращаем TRUE, в противном случае + Фар будет закрыт системой и не будут выполнены обычные при закрытии + процедуры: оповещены плагины, вызваны деструкторы, сохранены настройки и + т.п. + */ + if (!Opt.CloseConsoleRule) + { + if ((FileEditor::CurrentEditor && FileEditor::CurrentEditor->IsFileModified()) || + (FrameManager && FrameManager->IsAnyFrameModified(FALSE))) + return TRUE; + + return FALSE; + } + + // write some dummy console input to kick any pending ReadConsoleInput + INPUT_RECORD ir = {}; + ir.EventType = NOOP_EVENT; + DWORD dw = 0; + WINPORT(WriteConsoleInput)(0, &ir, 1, &dw); + + return TRUE; +} + + +void ShowTime(int ShowAlways) +{ + FARString strClockText; + static SYSTEMTIME lasttm={0,0,0,0,0,0,0,0}; + SYSTEMTIME tm; + WINPORT(GetLocalTime)(&tm); + CHAR_INFO ScreenClockText[5]; + GetText(ScrX-4,0,ScrX,0,ScreenClockText,sizeof(ScreenClockText)); + + if (ShowAlways==2) + { + memset(&lasttm,0,sizeof(lasttm)); + return; + } + + if ((!ShowAlways && lasttm.wMinute==tm.wMinute && lasttm.wHour==tm.wHour && + ScreenClockText[2].Char.UnicodeChar==L':') || ScreenSaverActive) + return; + + ProcessShowClock++; + lasttm=tm; + strClockText.Format(L"%02d:%02d",tm.wHour,tm.wMinute); + GotoXY(ScrX-4,0); + // Здесь хрень какая-то получается с ModType - все время не верное значение! + Frame *CurFrame=FrameManager->GetCurrentFrame(); + + if (CurFrame) + { + int ModType=CurFrame->GetType(); + SetColor(ModType==MODALTYPE_VIEWER?COL_VIEWERCLOCK: + (ModType==MODALTYPE_EDITOR?COL_EDITORCLOCK:COL_CLOCK)); + Text(strClockText); + //ScrBuf.Flush(); + } + + ProcessShowClock--; +} + +void GotoXY(int X,int Y) +{ + CurX=X; + CurY=Y; +} + + +int WhereX() +{ + return(CurX); +} + + +int WhereY() +{ + return(CurY); +} + + +void MoveCursor(int X,int Y) +{ + ScrBuf.MoveCursor(X,Y); +} + + +void GetCursorPos(SHORT& X,SHORT& Y) +{ + ScrBuf.GetCursorPos(X,Y); +} + + +void SetCursorType(bool Visible, DWORD Size) +{ + if (Size==(DWORD)-1 || !Visible) + Size=IsFullscreen()? + (Opt.CursorSize[1]?Opt.CursorSize[1]:InitialCursorInfo.dwSize): + (Opt.CursorSize[0]?Opt.CursorSize[0]:InitialCursorInfo.dwSize); + + ScrBuf.SetCursorType(Visible,Size); +} + +void SetInitialCursorType() +{ + ScrBuf.SetCursorType(InitialCursorInfo.bVisible!=FALSE,InitialCursorInfo.dwSize); +} + + +void GetCursorType(bool& Visible, DWORD& Size) +{ + ScrBuf.GetCursorType(Visible,Size); +} + + +void MoveRealCursor(int X,int Y) +{ + COORD C={(SHORT)X,(SHORT)Y}; + Console.SetCursorPosition(C); +} + + +void GetRealCursorPos(SHORT& X,SHORT& Y) +{ + COORD CursorPosition; + Console.GetCursorPosition(CursorPosition); + X=CursorPosition.X; + Y=CursorPosition.Y; +} + +void InitRecodeOutTable() +{ + for (size_t i=0; i<ARRAYSIZE(Oem2Unicode); i++) + { + char c = static_cast<char>(i); + WINPORT(MultiByteToWideChar)(CP_OEMCP, MB_USEGLYPHCHARS, &c, 1, &Oem2Unicode[i], 1); + } + + if (Opt.CleanAscii) + { + for (size_t i=0; i<0x20; i++) + Oem2Unicode[i]=L'.'; + + Oem2Unicode[0x07]=L'*'; + Oem2Unicode[0x10]=L'>'; + Oem2Unicode[0x11]=L'<'; + Oem2Unicode[0x15]=L'$'; + Oem2Unicode[0x16]=L'-'; + Oem2Unicode[0x18]=L'|'; + Oem2Unicode[0x19]=L'V'; + Oem2Unicode[0x1A]=L'>'; + Oem2Unicode[0x1B]=L'<'; + Oem2Unicode[0x1E]=L'X'; + Oem2Unicode[0x1F]=L'X'; + + Oem2Unicode[0x7F]=L'.'; + } + + if (Opt.NoGraphics) + { + for (int i=0xB3; i<=0xDA; i++) + { + Oem2Unicode[i]=L'+'; + } + Oem2Unicode[0xB3]=L'|'; + Oem2Unicode[0xBA]=L'|'; + Oem2Unicode[0xC4]=L'-'; + Oem2Unicode[0xCD]=L'='; + } + + { + static WCHAR _BoxSymbols[48] = + { + 0x2591, 0x2592, 0x2593, 0x2502, 0x2524, 0x2561, 0x2562, 0x2556, + 0x2555, 0x2563, 0x2551, 0x2557, 0x255D, 0x255C, 0x255B, 0x2510, + 0x2514, 0x2534, 0x252C, 0x251C, 0x2500, 0x253C, 0x255E, 0x255F, + 0x255A, 0x2554, 0x2569, 0x2566, 0x2560, 0x2550, 0x256C, 0x2567, + 0x2568, 0x2564, 0x2565, 0x2559, 0x2558, 0x2552, 0x2553, 0x256B, + 0x256A, 0x2518, 0x250C, 0x2588, 0x2584, 0x258C, 0x2590, 0x2580, + }; + // перед [пере]инициализацией восстановим буфер + memcpy(BoxSymbols,(BYTE*)_BoxSymbols,sizeof(_BoxSymbols)); + + if (Opt.NoGraphics) + { + for (int i=BS_V1; i<=BS_LT_H1V1; i++) + BoxSymbols[i]=L'+'; + + BoxSymbols[BS_V1]=BoxSymbols[BS_V2]=L'|'; + BoxSymbols[BS_H1]=L'-'; + BoxSymbols[BS_H2]=L'='; + } + } + + //_SVS(SysLogDump("Oem2Unicode",0,(LPBYTE)Oem2Unicode,sizeof(Oem2Unicode),nullptr)); +} + + +void Text(int X, int Y, int Color, const WCHAR *Str) +{ + CurColor=FarColorToReal(Color); + CurX=X; + CurY=Y; + Text(Str); +} + +void Text(const WCHAR *Str, size_t Length) +{ + if (Length == (size_t)-1) + Length = StrLength(Str); + + if (Length == 0) + return; + + CHAR_INFO StackBuffer[StackBufferSize]; + PCHAR_INFO HeapBuffer=nullptr; + PCHAR_INFO BufPtr=StackBuffer; + + if (Length >= StackBufferSize) + { + HeapBuffer=new CHAR_INFO[Length+1]; + BufPtr=HeapBuffer; + } + + for (size_t i=0; i < Length; i++) + { + BufPtr[i].Char.UnicodeChar=Str[i]; + BufPtr[i].Attributes=CurColor; + } + + ScrBuf.Write(CurX, CurY, BufPtr, static_cast<int>(Length)); + if(HeapBuffer) + { + delete[] HeapBuffer; + } + CurX+=static_cast<int>(Length); +} + + +void Text(int MsgId) +{ + Text(MSG(MsgId)); +} + +void VText(const WCHAR *Str) +{ + int Length=StrLength(Str); + + if (Length<=0) + return; + + int StartCurX=CurX; + WCHAR ChrStr[2]={0,0}; + + for (int I=0; I<Length; I++) + { + GotoXY(CurX,CurY); + ChrStr[0]=Str[I]; + Text(ChrStr); + CurY++; + CurX=StartCurX; + } +} + +void HiText(const wchar_t *Str,int HiColor,int isVertText) +{ + FARString strTextStr; + int SaveColor; + size_t pos; + strTextStr = Str; + + if (!strTextStr.Pos(pos,L'&')) + { + if (isVertText) + VText(strTextStr); + else + Text(strTextStr); + } + else + { + /* + && = '&' + &&& = '&' + ^H + &&&& = '&&' + &&&&& = '&&' + ^H + &&&&&& = '&&&' + */ + wchar_t *ChPtr = strTextStr.GetBuffer() + pos; + int I=0; + wchar_t *ChPtr2=ChPtr; + + while (*ChPtr2++ == L'&') + ++I; + + if (I&1) // нечет? + { + *ChPtr=0; + + if (isVertText) + VText(strTextStr); + else + Text(strTextStr); //BUGBUG BAD!!! + + if (ChPtr[1]) + { + wchar_t Chr[]={ChPtr[1],0}; + SaveColor=CurColor; + SetColor(HiColor); + + if (isVertText) + VText(Chr); + else + Text(Chr); + + SetColor(SaveColor); + FARString strText = (ChPtr+1); + strTextStr.ReleaseBuffer(); + ReplaceStrings(strText,L"&&",L"&",-1); + + if (isVertText) + VText(strText.CPtr()+1); + else + Text(strText.CPtr()+1); + } + } + else + { + strTextStr.ReleaseBuffer(); + ReplaceStrings(strTextStr,L"&&",L"&",-1); + + if (isVertText) + VText(strTextStr); + else + Text(strTextStr); //BUGBUG BAD!!! + } + } +} + + + +void SetScreen(int X1,int Y1,int X2,int Y2,wchar_t Ch,int Color) +{ + if (X1<0) X1=0; + + if (Y1<0) Y1=0; + + if (X2>ScrX) X2=ScrX; + + if (Y2>ScrY) Y2=ScrY; + + ScrBuf.FillRect(X1,Y1,X2,Y2,Ch,FarColorToReal(Color)); +} + + +void MakeShadow(int X1,int Y1,int X2,int Y2) +{ + if (X1<0) X1=0; + + if (Y1<0) Y1=0; + + if (X2>ScrX) X2=ScrX; + + if (Y2>ScrY) Y2=ScrY; + + ScrBuf.ApplyColorMask(X1,Y1,X2,Y2,0xF8); +} + +void ChangeBlockColor(int X1,int Y1,int X2,int Y2,int Color) +{ + if (X1<0) X1=0; + + if (Y1<0) Y1=0; + + if (X2>ScrX) X2=ScrX; + + if (Y2>ScrY) Y2=ScrY; + + ScrBuf.ApplyColor(X1,Y1,X2,Y2,FarColorToReal(Color)); +} + +void mprintf(const WCHAR *fmt,...) +{ + va_list argptr; + va_start(argptr,fmt); + WCHAR OutStr[2048]; + vswprintf(OutStr,ARRAYSIZE(OutStr)-1,fmt,argptr); + Text(OutStr); + va_end(argptr); +} + +void vmprintf(const WCHAR *fmt,...) +{ + va_list argptr; + va_start(argptr,fmt); + WCHAR OutStr[2048]; + vswprintf(OutStr,ARRAYSIZE(OutStr)-1,fmt,argptr); + VText(OutStr); + va_end(argptr); +} + + +void SetColor(int Color, bool ApplyToConsole) +{ + CurColor = FarColorToReal(Color); + if (ApplyToConsole) { + Console.SetTextAttributes(CurColor); + } +} + +void SetRealColor(WORD wAttributes, bool ApplyToConsole) +{ + CurColor = wAttributes; + if (ApplyToConsole) { + Console.SetTextAttributes(CurColor); + } +} + +WORD GetRealColor() +{ + return CurColor; +} + +void ClearScreen(int Color) +{ + Color=FarColorToReal(Color); + ScrBuf.FillRect(0,0,ScrX,ScrY,L' ',Color); + if(Opt.WindowMode) + { + Console.ClearExtraRegions(Color); + } + ScrBuf.ResetShadow(); + ScrBuf.Flush(); + Console.SetTextAttributes(Color); +} + +int GetColor() +{ + return(CurColor); +} + + +void ScrollScreen(int Count) +{ + ScrBuf.Scroll(Count); + ScrBuf.FillRect(0,ScrY+1-Count,ScrX,ScrY,L' ',FarColorToReal(COL_COMMANDLINEUSERSCREEN)); +} + + +void GetText(int X1,int Y1,int X2,int Y2,void *Dest,int DestSize) +{ + ScrBuf.Read(X1,Y1,X2,Y2,(CHAR_INFO *)Dest,DestSize); +} + +void PutText(int X1,int Y1,int X2,int Y2,const void *Src) +{ + int Width=X2-X1+1; + int Y; + CHAR_INFO *SrcPtr=(CHAR_INFO*)Src; + + for (Y=Y1; Y<=Y2; ++Y,SrcPtr+=Width) + ScrBuf.Write(X1,Y,SrcPtr,Width); +} + +void BoxText(wchar_t Chr) +{ + wchar_t Str[]={Chr,L'\0'}; + BoxText(Str); +} + + +void BoxText(const wchar_t *Str,int IsVert) +{ + if (IsVert) + VText(Str); + else + Text(Str); +} + + +/* + Отрисовка прямоугольника. +*/ +void Box(int x1,int y1,int x2,int y2,int Color,int Type) +{ + if (x1>=x2 || y1>=y2) + return; + + SetColor(Color); + Type=(Type==DOUBLE_BOX || Type==SHORT_DOUBLE_BOX); + + WCHAR StackBuffer[StackBufferSize]; + LPWSTR HeapBuffer=nullptr; + LPWSTR BufPtr=StackBuffer; + + const size_t height=y2-y1; + if(height>StackBufferSize) + { + HeapBuffer=new WCHAR[height]; + BufPtr=HeapBuffer; + } + wmemset(BufPtr, BoxSymbols[Type?BS_V2:BS_V1], height-1); + BufPtr[height-1]=0; + GotoXY(x1,y1+1); + VText(BufPtr); + GotoXY(x2,y1+1); + VText(BufPtr); + const size_t width=x2-x1+2; + if(width>StackBufferSize) + { + if(width>height) + { + if(HeapBuffer) + { + delete[] HeapBuffer; + } + HeapBuffer=new WCHAR[width]; + } + BufPtr=HeapBuffer; + } + BufPtr[0]=BoxSymbols[Type?BS_LT_H2V2:BS_LT_H1V1]; + wmemset(BufPtr+1, BoxSymbols[Type?BS_H2:BS_H1], width-3); + BufPtr[width-2]=BoxSymbols[Type?BS_RT_H2V2:BS_RT_H1V1]; + BufPtr[width-1]=0; + GotoXY(x1,y1); + Text(BufPtr); + BufPtr[0]=BoxSymbols[Type?BS_LB_H2V2:BS_LB_H1V1]; + BufPtr[width-2]=BoxSymbols[Type?BS_RB_H2V2:BS_RB_H1V1]; + GotoXY(x1,y2); + Text(BufPtr); + + if(HeapBuffer) + { + delete[] HeapBuffer; + } +} + +bool ScrollBarRequired(UINT Length, UINT64 ItemsCount) +{ + return Length>2 && ItemsCount && Length<ItemsCount; +} + +bool ScrollBarEx(UINT X1,UINT Y1,UINT Length,UINT64 TopItem,UINT64 ItemsCount) +{ + if (ScrollBarRequired(Length, ItemsCount)) + { + Length-=2; + ItemsCount-=2; + UINT CaretPos=static_cast<UINT>(Round(Length*TopItem,ItemsCount)); + UINT CaretLength=Max(1U,static_cast<UINT>(Round(static_cast<UINT64>(Length*Length),ItemsCount))); + + if (!CaretPos && TopItem) + { + CaretPos++; + } + else if (CaretPos+CaretLength==Length && TopItem+2+Length<ItemsCount) + { + CaretPos--; + } + + CaretPos=Min(CaretPos,Length-CaretLength); + WCHAR StackBuffer[StackBufferSize]; + LPWSTR HeapBuffer=nullptr; + LPWSTR BufPtr=StackBuffer; + if(Length+3>=StackBufferSize) + { + HeapBuffer=new WCHAR[Length+3]; + BufPtr=HeapBuffer; + } + wmemset(BufPtr+1,BoxSymbols[BS_X_B0],Length); + BufPtr[0]=Oem2Unicode[0x1E]; + + for (size_t i=0; i<CaretLength; i++) + BufPtr[CaretPos+1+i]=BoxSymbols[BS_X_B2]; + + BufPtr[Length+1]=Oem2Unicode[0x1F]; + BufPtr[Length+2]=0; + GotoXY(X1,Y1); + VText(BufPtr); + if(HeapBuffer) + { + delete[] HeapBuffer; + } + return true; + } + + return false; +} + +void ScrollBar(int X1,int Y1,int Length, unsigned int Current, unsigned int Total) +{ + int ThumbPos; + + if ((Length-=2)<1) + return; + + if (Total>0) + ThumbPos=Length*Current/Total; + else + ThumbPos=0; + + if (ThumbPos>=Length) + ThumbPos=Length-1; + + GotoXY(X1,Y1); + { + WCHAR StackBuffer[StackBufferSize]; + LPWSTR HeapBuffer=nullptr; + LPWSTR BufPtr=StackBuffer; + if(static_cast<size_t>(Length+3)>=StackBufferSize) + { + HeapBuffer=new WCHAR[Length+3]; + BufPtr=HeapBuffer; + } + wmemset(BufPtr+1,BoxSymbols[BS_X_B0],Length); + BufPtr[ThumbPos+1]=BoxSymbols[BS_X_B2]; + BufPtr[0]=Oem2Unicode[0x1E]; + BufPtr[Length+1]=Oem2Unicode[0x1F]; + BufPtr[Length+2]=0; + VText(BufPtr); + if(HeapBuffer) + { + delete[] HeapBuffer; + } + } +} + +void DrawLine(int Length,int Type, const wchar_t* UserSep) +{ + if (Length>1) + { + WCHAR StackBuffer[StackBufferSize]; + LPWSTR HeapBuffer=nullptr; + LPWSTR BufPtr=StackBuffer; + if(static_cast<size_t>(Length)>=StackBufferSize) + { + HeapBuffer=new WCHAR[Length+1]; + BufPtr=HeapBuffer; + } + MakeSeparator(Length,BufPtr,Type,UserSep); + + (Type >= 4 && Type <= 7) || (Type >= 10 && Type <= 11)? VText(BufPtr) : Text(BufPtr); + if(HeapBuffer) + { + delete[] HeapBuffer; + } + } +} + +// "Нарисовать" сепаратор в памяти. +WCHAR* MakeSeparator(int Length,WCHAR *DestStr,int Type, const wchar_t* UserSep) +{ + wchar_t BoxType[12][3]= + { + // h-horiz, s-space, v-vert, b-border, 1-one line, 2-two line + /* 00 */{L' ', L' ', BoxSymbols[BS_H1]}, // - h1s + /* 01 */{BoxSymbols[BS_L_H1V2],BoxSymbols[BS_R_H1V2],BoxSymbols[BS_H1]}, // ||-|| h1b2 + /* 02 */{BoxSymbols[BS_L_H1V1],BoxSymbols[BS_R_H1V1],BoxSymbols[BS_H1]}, // |-| h1b1 + /* 03 */{BoxSymbols[BS_L_H2V2],BoxSymbols[BS_R_H2V2],BoxSymbols[BS_H2]}, // ||=|| h2b2 + + /* 04 */{L' ', L' ', BoxSymbols[BS_V1]}, // | v1s + /* 05 */{BoxSymbols[BS_T_H2V1],BoxSymbols[BS_B_H2V1],BoxSymbols[BS_V1]}, // =|= v1b2 + /* 06 */{BoxSymbols[BS_T_H1V1],BoxSymbols[BS_B_H1V1],BoxSymbols[BS_V1]}, // -|- v1b1 + /* 07 */{BoxSymbols[BS_T_H2V2],BoxSymbols[BS_B_H2V2],BoxSymbols[BS_V2]}, // =||= v2b2 + + /* 08 */{BoxSymbols[BS_H1], BoxSymbols[BS_H1], BoxSymbols[BS_H1]}, // - h1 + /* 09 */{BoxSymbols[BS_H2], BoxSymbols[BS_H2], BoxSymbols[BS_H2]}, // = h2 + /* 10 */{BoxSymbols[BS_V1], BoxSymbols[BS_V1], BoxSymbols[BS_V1]}, // | v1 + /* 11 */{BoxSymbols[BS_V2], BoxSymbols[BS_V2], BoxSymbols[BS_V2]}, // || v2 + }; + + if (Length>1 && DestStr) + { + Type%=ARRAYSIZE(BoxType); + wmemset(DestStr,BoxType[Type][2],Length); + DestStr[0]=BoxType[Type][0]; + DestStr[Length-1]=BoxType[Type][1]; + DestStr[Length]=0; + } + + return DestStr; +} + +FARString& HiText2Str(FARString& strDest, const wchar_t *Str) +{ + const wchar_t *ChPtr; + strDest = Str; + + if ((ChPtr=wcschr(Str,L'&')) ) + { + /* + && = '&' + &&& = '&' + ^H + &&&& = '&&' + &&&&& = '&&' + ^H + &&&&&& = '&&&' + */ + int I=0; + const wchar_t *ChPtr2=ChPtr; + + while (*ChPtr2++ == L'&') + ++I; + + if (I&1) // нечет? + { + strDest.Truncate(ChPtr-Str); + + if (ChPtr[1]) + { + wchar_t Chr[]={ChPtr[1],0}; + strDest+=Chr; + FARString strText = (ChPtr+1); + ReplaceStrings(strText,L"&&",L"&",-1); + strDest+=strText.CPtr()+1; + } + } + else + { + ReplaceStrings(strDest,L"&&",L"&",-1); + } + } + + return strDest; +} + +int HiStrlen(const wchar_t *Str) +{ + /* + && = '&' + &&& = '&' + ^H + &&&& = '&&' + &&&&& = '&&' + ^H + &&&&&& = '&&&' + */ + + int Length=0; + bool Hi=false; + + if (Str) + { + while (*Str) + { + if (*Str == L'&') + { + int Count=0; + + while (*Str == L'&') + { + Str++; + Count++; + } + + if (Count&1) //нечёт? + { + if (Hi) + Length+=+1; + else + Hi=true; + } + + Length+=Count/2; + } + else + { + Str++; + Length++; + } + } + } + + return Length; + +} + +int HiFindRealPos(const wchar_t *Str, int Pos, BOOL ShowAmp) +{ + /* + && = '&' + &&& = '&' + ^H + &&&& = '&&' + &&&&& = '&&' + ^H + &&&&&& = '&&&' + */ + + if (ShowAmp) + { + return Pos; + } + + int RealPos = 0; + int VisPos = 0; + + if (Str) + { + while (VisPos < Pos && *Str) + { + if (*Str == L'&') + { + Str++; + RealPos++; + + if (*Str == L'&' && *(Str+1) == L'&' && *(Str+2) != L'&') + { + Str++; + RealPos++; + } + } + + Str++; + VisPos++; + RealPos++; + } + } + + return RealPos; +} + +int HiFindNextVisualPos(const wchar_t *Str, int Pos, int Direct) +{ + /* + && = '&' + &&& = '&' + ^H + &&&& = '&&' + &&&&& = '&&' + ^H + &&&&&& = '&&&' + */ + + if (Str) + { + if (Direct < 0) + { + if (!Pos || Pos == 1) + return 0; + + if (Str[Pos-1] != L'&') + { + if (Str[Pos-2] == L'&') + { + if (Pos-3 >= 0 && Str[Pos-3] == L'&') + return Pos-1; + + return Pos-2; + } + + return Pos-1; + } + else + { + if (Pos-3 >= 0 && Str[Pos-3] == L'&') + return Pos-3; + + return Pos-2; + } + } + else + { + if (!Str[Pos]) + return Pos+1; + + if (Str[Pos] == L'&') + { + if (Str[Pos+1] == L'&' && Str[Pos+2] == L'&') + return Pos+3; + + return Pos+2; + } + else + { + return Pos+1; + } + } + } + + return 0; +} + +bool IsFullscreen() +{ + bool Result=false; + /*DWORD ModeFlags=0; + if(Console.GetDisplayMode(ModeFlags) && ModeFlags&CONSOLE_FULLSCREEN_HARDWARE) + { + Result=true; + }*/ + return Result; +} + +bool CheckForInactivityExit() +{ + if (Opt.InactivityExit && Opt.InactivityExitTime > 0 && + GetProcessUptimeMSec() - StartIdleTime > Opt.InactivityExitTime*60000 && + FrameManager && FrameManager->GetFrameCount()==1 && + (!CtrlObject || !CtrlObject->Plugins.HasBackgroundTasks())) + { + FrameManager->ExitMainLoop(FALSE); + return true; + } + + return false; +} diff --git a/far2l/src/console/interf.hpp b/far2l/src/console/interf.hpp new file mode 100644 index 00000000..12baa869 --- /dev/null +++ b/far2l/src/console/interf.hpp @@ -0,0 +1,133 @@ +#pragma once + +/* +interf.hpp + +Консольные функции ввода-вывода +*/ +/* +Copyright (c) 1996 Eugene Roshal +Copyright (c) 2000 Far Group +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "strmix.hpp" + +extern WCHAR Oem2Unicode[]; +extern WCHAR BoxSymbols[]; +extern COORD InitSize, CurSize; +extern SHORT ScrX,ScrY; +extern SHORT PrevScrX,PrevScrY; +extern DWORD InitialConsoleMode; + +// типы рамок +enum +{ + NO_BOX, + SINGLE_BOX, + SHORT_SINGLE_BOX, + DOUBLE_BOX, + SHORT_DOUBLE_BOX +}; + +void ShowTime(int ShowAlways); + +/*$ 14.02.2001 SKV + Инитить ли палитру default значениями. + По умолчанию - да. + С 0 используется для ConsoleDetach. +*/ +void InitConsole(int FirstInit=TRUE); +void CloseConsole(); +void SetFarConsoleMode(BOOL SetsActiveBuffer=FALSE); +void ChangeConsoleMode(int Mode); +void FlushInputBuffer(); +void SetVideoMode(); +void ChangeVideoMode(int Maximized); +void ChangeVideoMode(int NumLines,int NumColumns); +void GetVideoMode(COORD& Size); +void GenerateWINDOW_BUFFER_SIZE_EVENT(int Sx=-1, int Sy=-1); +void SaveConsoleWindowRect(); +void RestoreConsoleWindowRect(); + +void GotoXY(int X,int Y); +int WhereX(); +int WhereY(); +void MoveCursor(int X,int Y); +void GetCursorPos(SHORT& X,SHORT& Y); +void SetCursorType(bool Visible, DWORD Size); +void SetInitialCursorType(); +void GetCursorType(bool& Visible, DWORD& Size); +void MoveRealCursor(int X,int Y); +void GetRealCursorPos(SHORT& X,SHORT& Y); +void ScrollScreen(int Count); + +void Text(int X, int Y, int Color, const WCHAR *Str); +void Text(const WCHAR *Str, size_t Length = (size_t)-1); +void Text(int MsgId); +void VText(const WCHAR *Str); +void HiText(const WCHAR *Str,int HiColor,int isVertText=0); +void mprintf(const WCHAR *fmt,...); +void vmprintf(const WCHAR *fmt,...); +void PutText(int X1,int Y1,int X2,int Y2,const void *Src); +void GetText(int X1,int Y1,int X2,int Y2,void *Dest,int DestSize); +void BoxText(wchar_t Chr); +void BoxText(const wchar_t *Str,int IsVert=0); + +void SetScreen(int X1,int Y1,int X2,int Y2,wchar_t Ch,int Color); +void MakeShadow(int X1,int Y1,int X2,int Y2); +void ChangeBlockColor(int X1,int Y1,int X2,int Y2,int Color); +void SetColor(int Color, bool ApplyToConsole = false); +void SetRealColor(WORD wAttributes, bool ApplyToConsole = false); +WORD GetRealColor(); +void ClearScreen(int Color); +int GetColor(); + +void Box(int x1,int y1,int x2,int y2,int Color,int Type); +void ScrollBar(int X1,int Y1,int Length, unsigned int Current,unsigned int Total); +bool ScrollBarRequired(UINT Length, UINT64 ItemsCount); +bool ScrollBarEx(UINT X1,UINT Y1,UINT Length,UINT64 TopItem,UINT64 ItemsCount); +void DrawLine(int Length,int Type, const wchar_t* UserSep=nullptr); +#define ShowSeparator(Length,Type) DrawLine(Length,Type) +#define ShowUserSeparator(Length,Type,UserSep) DrawLine(Length,Type,UserSep) +WCHAR* MakeSeparator(int Length,WCHAR *DestStr,int Type=1, const wchar_t* UserSep=nullptr); + +void InitRecodeOutTable(); + +int WINAPI TextToCharInfo(const char *Text,WORD Attr, CHAR_INFO *CharInfo, int Length, DWORD Reserved); + +inline void SetVidChar(CHAR_INFO& CI,wchar_t Chr) +{ + CI.Char.UnicodeChar = (Chr >= 0 && (Chr < L'\x20' || Chr == L'\x7f')) ? Oem2Unicode[Chr] : Chr; +} + +int HiStrlen(const wchar_t *Str); +int HiFindRealPos(const wchar_t *Str, int Pos, BOOL ShowAmp); +int HiFindNextVisualPos(const wchar_t *Str, int Pos, int Direct); +FARString& HiText2Str(FARString& strDest, const wchar_t *Str); +#define RemoveHighlights(Str) RemoveChar(Str,L'&') + +bool IsFullscreen(); +bool CheckForInactivityExit(); diff --git a/far2l/src/console/keyboard.cpp b/far2l/src/console/keyboard.cpp new file mode 100644 index 00000000..537a7aa8 --- /dev/null +++ b/far2l/src/console/keyboard.cpp @@ -0,0 +1,2948 @@ +/* +keyboard.cpp + +Функции, имеющие отношение к клавитуре +*/ +/* +Copyright (c) 1996 Eugene Roshal +Copyright (c) 2000 Far Group +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "headers.hpp" + + +#include <ctype.h> +#include "keyboard.hpp" +#include "keys.hpp" +#include "farqueue.hpp" +#include "lang.hpp" +#include "ctrlobj.hpp" +#include "filepanels.hpp" +#include "panel.hpp" +#include "cmdline.hpp" +#include "grabber.hpp" +#include "manager.hpp" +#include "scrbuf.hpp" +#include "savescr.hpp" +#include "lockscrn.hpp" +#include "TPreRedrawFunc.hpp" +#include "syslog.hpp" +#include "interf.hpp" +#include "message.hpp" +#include "config.hpp" +#include "scrsaver.hpp" +#include "strmix.hpp" +#include "synchro.hpp" +#include "constitle.hpp" +#include "console.hpp" +#include "palette.hpp" + +/* start Глобальные переменные */ + +// "дополнительная" очередь кодов клавиш +FarQueue<DWORD> *KeyQueue=nullptr; +int AltPressed=0,CtrlPressed=0,ShiftPressed=0; +int RightAltPressed=0,RightCtrlPressed=0,RightShiftPressed=0; +DWORD MouseButtonState=0,PrevMouseButtonState=0; +int PrevLButtonPressed=0, PrevRButtonPressed=0, PrevMButtonPressed=0; +SHORT PrevMouseX=0,PrevMouseY=0,MouseX=0,MouseY=0; +int PreMouseEventFlags=0,MouseEventFlags=0; +// только что был ввод Alt-Цифира? +int ReturnAltValue=0; + +/* end Глобальные переменные */ + + +//static SHORT KeyToVKey[MAX_VKEY_CODE]; +//static WCHAR VKeyToASCII[0x200]; + +static unsigned int AltValue=0; +static int KeyCodeForALT_LastPressed=0; + +static MOUSE_EVENT_RECORD lastMOUSE_EVENT_RECORD; +static int ShiftPressedLast=FALSE,AltPressedLast=FALSE,CtrlPressedLast=FALSE; +static BOOL IsKeyCASPressed=FALSE; // CtrlAltShift - нажато или нет? + +static int RightShiftPressedLast=FALSE,RightAltPressedLast=FALSE,RightCtrlPressedLast=FALSE; +static BOOL IsKeyRCASPressed=FALSE; // Right CtrlAltShift - нажато или нет? + +static clock_t PressedLastTime,KeyPressedLastTime; +static int ShiftState=0; +static int LastShiftEnterPressed=FALSE; + +/* ----------------------------------------------------------------- */ +static struct TTable_KeyToVK +{ + int Key; + int VK; +} Table_KeyToVK[]= +{ +// {KEY_PGUP, VK_PRIOR}, +// {KEY_PGDN, VK_NEXT}, +// {KEY_END, VK_END}, +// {KEY_HOME, VK_HOME}, +// {KEY_LEFT, VK_LEFT}, +// {KEY_UP, VK_UP}, +// {KEY_RIGHT, VK_RIGHT}, +// {KEY_DOWN, VK_DOWN}, +// {KEY_INS, VK_INSERT}, +// {KEY_DEL, VK_DELETE}, +// {KEY_LWIN, VK_LWIN}, +// {KEY_RWIN, VK_RWIN}, +// {KEY_APPS, VK_APPS}, +// {KEY_MULTIPLY, VK_MULTIPLY}, +// {KEY_ADD, VK_ADD}, +// {KEY_SUBTRACT, VK_SUBTRACT}, +// {KEY_DIVIDE, VK_DIVIDE}, +// {KEY_F1, VK_F1}, +// {KEY_F2, VK_F2}, +// {KEY_F3, VK_F3}, +// {KEY_F4, VK_F4}, +// {KEY_F5, VK_F5}, +// {KEY_F6, VK_F6}, +// {KEY_F7, VK_F7}, +// {KEY_F8, VK_F8}, +// {KEY_F9, VK_F9}, +// {KEY_F10, VK_F10}, +// {KEY_F11, VK_F11}, +// {KEY_F12, VK_F12}, + {KEY_BREAK, VK_CANCEL}, + {KEY_BS, VK_BACK}, + {KEY_TAB, VK_TAB}, + {KEY_ENTER, VK_RETURN}, + {KEY_NUMENTER, VK_RETURN}, //???? + {KEY_ESC, VK_ESCAPE}, + {KEY_SPACE, VK_SPACE}, + {KEY_NUMPAD5, VK_CLEAR}, +}; + + +struct TFKey3 +{ + DWORD Key; + int Len; + const wchar_t *Name; + const wchar_t *UName; +}; + +static TFKey3 FKeys1[]= +{ + { KEY_RCTRLALTSHIFTRELEASE,24, L"RightCtrlAltShiftRelease", L"RIGHTCTRLALTSHIFTRELEASE"}, + { KEY_RCTRLALTSHIFTPRESS, 22, L"RightCtrlAltShiftPress", L"RIGHTCTRLALTSHIFTPRESS"}, + { KEY_CTRLALTSHIFTRELEASE, 19, L"CtrlAltShiftRelease", L"CTRLALTSHIFTRELEASE"}, + { KEY_CTRLALTSHIFTPRESS, 17, L"CtrlAltShiftPress", L"CTRLALTSHIFTPRESS"}, + { KEY_LAUNCH_MEDIA_SELECT, 17, L"LaunchMediaSelect", L"LAUNCHMEDIASELECT"}, + { KEY_BROWSER_FAVORITES, 16, L"BrowserFavorites", L"BROWSERFAVORITES"}, + { KEY_MEDIA_PREV_TRACK, 14, L"MediaPrevTrack", L"MEDIAPREVTRACK"}, + { KEY_MEDIA_PLAY_PAUSE, 14, L"MediaPlayPause", L"MEDIAPLAYPAUSE"}, + { KEY_MEDIA_NEXT_TRACK, 14, L"MediaNextTrack", L"MEDIANEXTTRACK"}, + { KEY_BROWSER_REFRESH, 14, L"BrowserRefresh", L"BROWSERREFRESH"}, + { KEY_BROWSER_FORWARD, 14, L"BrowserForward", L"BROWSERFORWARD"}, + //{ KEY_HP_COMMUNITIES, 13, L"HPCommunities", L"HPCOMMUNITIES"}, + { KEY_BROWSER_SEARCH, 13, L"BrowserSearch", L"BROWSERSEARCH"}, + { KEY_MSWHEEL_RIGHT, 12, L"MsWheelRight", L"MSWHEELRIGHT"}, +#if 0 + { KEY_MSM1DBLCLICK, 12, L"MsM1DblClick", L"MSM1DBLCLICK"}, + { KEY_MSM2DBLCLICK, 12, L"MsM2DblClick", L"MSM2DBLCLICK"}, + { KEY_MSM3DBLCLICK, 12, L"MsM3DblClick", L"MSM3DBLCLICK"}, + { KEY_MSLDBLCLICK, 11, L"MsLDblClick", L"MSLDBLCLICK"}, + { KEY_MSRDBLCLICK, 11, L"MsRDblClick", L"MSRDBLCLICK"}, +#endif + { KEY_MSWHEEL_DOWN, 11, L"MsWheelDown", L"MSWHEELDOWN"}, + { KEY_MSWHEEL_LEFT, 11, L"MsWheelLeft", L"MSWHEELLEFT"}, + //{ KEY_AC_BOOKMARKS, 11, L"ACBookmarks", L"ACBOOKMARKS"}, + { KEY_BROWSER_STOP, 11, L"BrowserStop", L"BROWSERSTOP"}, + { KEY_BROWSER_HOME, 11, L"BrowserHome", L"BROWSERHOME"}, + { KEY_BROWSER_BACK, 11, L"BrowserBack", L"BROWSERBACK"}, + { KEY_VOLUME_MUTE, 10, L"VolumeMute", L"VOLUMEMUTE"}, + { KEY_VOLUME_DOWN, 10, L"VolumeDown", L"VOLUMEDOWN"}, + { KEY_SCROLLLOCK, 10, L"ScrollLock", L"SCROLLLOCK"}, + { KEY_LAUNCH_MAIL, 10, L"LaunchMail", L"LAUNCHMAIL"}, + { KEY_LAUNCH_APP2, 10, L"LaunchApp2", L"LAUNCHAPP2"}, + { KEY_LAUNCH_APP1, 10, L"LaunchApp1", L"LAUNCHAPP1"}, + //{ KEY_HP_INTERNET, 10, L"HPInternet", L"HPINTERNET"}, + //{ KEY_AC_FORWARD, 9, L"ACForward", L"ACFORWARD"}, + //{ KEY_AC_REFRESH, 9, L"ACRefresh", L"ACREFRESH"}, + { KEY_MSWHEEL_UP, 9, L"MsWheelUp", L"MSWHEELUP"}, + { KEY_MEDIA_STOP, 9, L"MediaStop", L"MEDIASTOP"}, + { KEY_BACKSLASH, 9, L"BackSlash", L"BACKSLASH"}, + //{ KEY_HP_MEETING, 9, L"HPMeeting", L"HPMEETING"}, + { KEY_MSM1CLICK, 9, L"MsM1Click", L"MSM1CLICK"}, + { KEY_MSM2CLICK, 9, L"MsM2Click", L"MSM2CLICK"}, + { KEY_MSM3CLICK, 9, L"MsM3Click", L"MSM3CLICK"}, + { KEY_MSLCLICK, 8, L"MsLClick", L"MSLCLICK"}, + { KEY_MSRCLICK, 8, L"MsRClick", L"MSRCLICK"}, + //{ KEY_HP_MARKET, 8, L"HPMarket", L"HPMARKET"}, + { KEY_VOLUME_UP, 8, L"VolumeUp", L"VOLUMEUP"}, + { KEY_SUBTRACT, 8, L"Subtract", L"SUBTRACT"}, + { KEY_NUMENTER, 8, L"NumEnter", L"NUMENTER"}, + { KEY_MULTIPLY, 8, L"Multiply", L"MULTIPLY"}, + { KEY_CAPSLOCK, 8, L"CapsLock", L"CAPSLOCK"}, + { KEY_PRNTSCRN, 8, L"PrntScrn", L"PRNTSCRN"}, + { KEY_NUMLOCK, 7, L"NumLock", L"NUMLOCK"}, + { KEY_DECIMAL, 7, L"Decimal", L"DECIMAL"}, + { KEY_STANDBY, 7, L"Standby", L"STANDBY"}, + //{ KEY_HP_SEARCH, 8, L"HPSearch", L"HPSEARCH"}, + //{ KEY_HP_HOME, 6, L"HPHome", L"HPHOME"}, + //{ KEY_HP_MAIL, 6, L"HPMail", L"HPMAIL"}, + //{ KEY_HP_NEWS, 6, L"HPNews", L"HPNEWS"}, + //{ KEY_AC_BACK, 6, L"ACBack", L"ACBACK"}, + //{ KEY_AC_STOP, 6, L"ACStop", L"ACSTOP"}, + { KEY_DIVIDE, 6, L"Divide", L"DIVIDE"}, + { KEY_NUMDEL, 6, L"NumDel", L"NUMDEL"}, + { KEY_SPACE, 5, L"Space", L"SPACE"}, + { KEY_RIGHT, 5, L"Right", L"RIGHT"}, + { KEY_PAUSE, 5, L"Pause", L"PAUSE"}, + { KEY_ENTER, 5, L"Enter", L"ENTER"}, + { KEY_CLEAR, 5, L"Clear", L"CLEAR"}, + { KEY_BREAK, 5, L"Break", L"BREAK"}, + { KEY_PGUP, 4, L"PgUp", L"PGUP"}, + { KEY_PGDN, 4, L"PgDn", L"PGDN"}, + { KEY_LEFT, 4, L"Left", L"LEFT"}, + { KEY_HOME, 4, L"Home", L"HOME"}, + { KEY_DOWN, 4, L"Down", L"DOWN"}, + { KEY_APPS, 4, L"Apps", L"APPS"}, + { KEY_RWIN, 4 ,L"RWin", L"RWIN"}, + { KEY_NUMPAD9, 4 ,L"Num9", L"NUM9"}, + { KEY_NUMPAD8, 4 ,L"Num8", L"NUM8"}, + { KEY_NUMPAD7, 4 ,L"Num7", L"NUM7"}, + { KEY_NUMPAD6, 4 ,L"Num6", L"NUM6"}, + { KEY_NUMPAD5, 4, L"Num5", L"NUM5"}, + { KEY_NUMPAD4, 4 ,L"Num4", L"NUM4"}, + { KEY_NUMPAD3, 4 ,L"Num3", L"NUM3"}, + { KEY_NUMPAD2, 4 ,L"Num2", L"NUM2"}, + { KEY_NUMPAD1, 4 ,L"Num1", L"NUM1"}, + { KEY_NUMPAD0, 4 ,L"Num0", L"NUM0"}, + { KEY_LWIN, 4 ,L"LWin", L"LWIN"}, + { KEY_TAB, 3, L"Tab", L"TAB"}, + { KEY_INS, 3, L"Ins", L"INS"}, + { KEY_F10, 3, L"F10", L"F10"}, + { KEY_F11, 3, L"F11", L"F11"}, + { KEY_F12, 3, L"F12", L"F12"}, + { KEY_F13, 3, L"F13", L"F13"}, + { KEY_F14, 3, L"F14", L"F14"}, + { KEY_F15, 3, L"F15", L"F15"}, + { KEY_F16, 3, L"F16", L"F16"}, + { KEY_F17, 3, L"F17", L"F17"}, + { KEY_F18, 3, L"F18", L"F18"}, + { KEY_F19, 3, L"F19", L"F19"}, + { KEY_F20, 3, L"F20", L"F20"}, + { KEY_F21, 3, L"F21", L"F21"}, + { KEY_F22, 3, L"F22", L"F22"}, + { KEY_F23, 3, L"F23", L"F23"}, + { KEY_F24, 3, L"F24", L"F24"}, + { KEY_ESC, 3, L"Esc", L"ESC"}, + { KEY_END, 3, L"End", L"END"}, + { KEY_DEL, 3, L"Del", L"DEL"}, + { KEY_ADD, 3, L"Add", L"ADD"}, + { KEY_UP, 2, L"Up", L"UP"}, + { KEY_F9, 2, L"F9", L"F9"}, + { KEY_F8, 2, L"F8", L"F8"}, + { KEY_F7, 2, L"F7", L"F7"}, + { KEY_F6, 2, L"F6", L"F6"}, + { KEY_F5, 2, L"F5", L"F5"}, + { KEY_F4, 2, L"F4", L"F4"}, + { KEY_F3, 2, L"F3", L"F3"}, + { KEY_F2, 2, L"F2", L"F2"}, + { KEY_F1, 2, L"F1", L"F1"}, + { KEY_BS, 2, L"BS", L"BS"}, + { KEY_BACKBRACKET, 1, L"]", L"]"}, + { KEY_QUOTE, 1, L"\"", L"\""}, + { KEY_BRACKET, 1, L"[", L"["}, + { KEY_COLON, 1, L":", L":"}, + { KEY_SEMICOLON, 1, L";", L";"}, + { KEY_SLASH, 1, L"/", L"/"}, + { KEY_DOT, 1, L".", L"."}, + { KEY_COMMA, 1, L",", L","}, +}; + +static TFKey3 ModifKeyName[]= +{ + { KEY_RCTRL ,5 ,L"RCtrl", L"RCTRL"}, + { KEY_SHIFT ,5 ,L"Shift", L"SHIFT"}, + { KEY_CTRL ,4 ,L"Ctrl", L"CTRL"}, + { KEY_RALT ,4 ,L"RAlt", L"RALT"}, + { KEY_ALT ,3 ,L"Alt", L"ALT"}, + { KEY_M_SPEC ,4 ,L"Spec", L"SPEC"}, + { KEY_M_OEM ,3 ,L"Oem", L"OEM"}, +// { KEY_LCTRL ,5 ,L"LCtrl", L"LCTRL"}, +// { KEY_LALT ,4 ,L"LAlt", L"LALT"}, +// { KEY_LSHIFT ,6 ,L"LShift", L"LSHIFT"}, +// { KEY_RSHIFT ,6 ,L"RShift", L"RSHIFT"}, +}; + +#if defined(SYSLOG) +static TFKey3 SpecKeyName[]= +{ + { KEY_CONSOLE_BUFFER_RESIZE,19, L"ConsoleBufferResize", L"CONSOLEBUFFERRESIZE"}, + { KEY_OP_SELWORD ,10, L"OP_SelWord", L"OP_SELWORD"}, + { KEY_KILLFOCUS ,9, L"KillFocus", L"KILLFOCUS"}, + { KEY_GOTFOCUS ,8, L"GotFocus", L"GOTFOCUS"}, + { KEY_DRAGCOPY , 8, L"DragCopy", L"DRAGCOPY"}, + { KEY_DRAGMOVE , 8, L"DragMove", L"DRAGMOVE"}, + { KEY_OP_PLAINTEXT , 7, L"OP_Text", L"OP_TEXT"}, + { KEY_OP_XLAT , 7, L"OP_Xlat", L"OP_XLAT"}, + { KEY_NONE , 4, L"None", L"NONE"}, + { KEY_IDLE , 4, L"Idle", L"IDLE"}, +}; +#endif + +/* ----------------------------------------------------------------- */ + +/* + Инициализация массива клавиш. + Вызывать только после CopyGlobalSettings, потому что только тогда GetRegKey + считает правильные данные. +*/ +void InitKeysArray() +{ +#if 0 + HKL Layout[10]; + int LayoutNumber=WINPORT(GetKeyboardLayoutList)(ARRAYSIZE(Layout),Layout); // возвращает 0! в telnet + + + memset(KeyToVKey,0,sizeof(KeyToVKey)); + memset(VKeyToASCII,0,sizeof(VKeyToASCII)); + + if (LayoutNumber && LayoutNumber < (int)ARRAYSIZE(Layout)) + { + BYTE KeyState[0x100]={0}; + WCHAR buf[1]; + + //KeyToVKey - используется чтоб проверить если два символа это одна и таже кнопка на клаве + //********* + //Так как сделать полноценное мапирование между всеми раскладками не реально, + //по причине того что во время проигрывания макросов нет такого понятия раскладка + //то сделаем наилучшую попытку - смысл такой, делаем полное мапирование всех возможных + //VKs и ShiftVKs в юникодные символы проходясь по всем раскладкам с одним но: + //если разные VK мапятся в тот же юникод символ то мапирование будет только для первой + //раскладки которая вернула этот символ + // + for (BYTE j=0; j<2; j++) + { + KeyState[VK_SHIFT]=j*0x80; + + for (int i=0; i<LayoutNumber; i++) + { + for (int VK=0; VK<256; VK++) + { + if (WINPORT(ToUnicodeEx)(LOBYTE(VK),0,KeyState,buf,1,0,Layout[i]) > 0) + { + if (!KeyToVKey[buf[0]]) + KeyToVKey[buf[0]] = VK + j*0x100; + } + } + } + } + + //VKeyToASCII - используется вместе с KeyToVKey чтоб подменить нац. символ на US-ASCII + //*********** + //Имея мапирование юникод -> VK строим обратное мапирование + //VK -> символы с кодом меньше 0x80, т.е. только US-ASCII символы + for (WCHAR i=1, x=0; i < 0x80; i++) + { + x = KeyToVKey[i]; + + if (x && !VKeyToASCII[x]) + VKeyToASCII[x]=Upper(i); + } + } + + //_SVS(SysLogDump(L"KeyToKey calculate",0,KeyToKey,sizeof(KeyToKey),nullptr)); + //unsigned char KeyToKeyMap[256]; + //if(GetRegKey(L"System",L"KeyToKeyMap",KeyToKeyMap,KeyToKey,sizeof(KeyToKeyMap))) + //memcpy(KeyToKey,KeyToKeyMap,sizeof(KeyToKey)); + //_SVS(SysLogDump("KeyToKey readed",0,KeyToKey,sizeof(KeyToKey),nullptr)); +#endif +} + +//Сравнивает если Key и CompareKey это одна и та же клавиша в разных раскладках +bool KeyToKeyLayoutCompare(int Key, int CompareKey) +{ + _KEYMACRO(CleverSysLog Clev(L"KeyToKeyLayoutCompare()")); + _KEYMACRO(SysLog(L"Param: Key=%08X",Key)); +// Key = KeyToVKey[Key&0xFFFF]&0xFF; +// CompareKey = KeyToVKey[CompareKey&0xFFFF]&0xFF; + + if (Key && Key == CompareKey) + return true; + + return false; +} + +//Должно вернуть клавишный Eng эквивалент Key +int KeyToKeyLayout(int Key) +{ + _KEYMACRO(CleverSysLog Clev(L"KeyToKeyLayout()")); + _KEYMACRO(SysLog(L"Param: Key=%08X",Key)); +return Key; +/* + int VK = KeyToVKey[Key&0xFFFF]; + + if (VK && VKeyToASCII[VK]) + return VKeyToASCII[VK]; + + return Key;*/ +} + +/* + State: + -1 get state + 0 off + 1 on + 2 flip +*/ +int SetFLockState(UINT vkKey, int State) +{ + return State; + /* + VK_NUMLOCK (90) + VK_SCROLL (91) + VK_CAPITAL (14) + */ + /* + UINT ExKey=(vkKey==VK_CAPITAL?0:KEYEVENTF_EXTENDEDKEY); + + switch (vkKey) + { + case VK_NUMLOCK: + case VK_CAPITAL: + case VK_SCROLL: + break; + default: + return -1; + } + + short oldState=GetKeyState(vkKey); + + if (State >= 0) + { + //if (State == 2 || (State==1 && !(keyState[vkKey] & 1)) || (!State && (keyState[vkKey] & 1)) ) + if (State == 2 || (State==1 && !oldState) || (!State && oldState)) + { + keybd_event(vkKey, 0, ExKey, 0); + keybd_event(vkKey, 0, ExKey | KEYEVENTF_KEYUP, 0); + } + } + + return (int)(WORD)oldState;*/ +} + +int WINAPI InputRecordToKey(const INPUT_RECORD *r) +{ + if (r) + { + INPUT_RECORD Rec=*r; // НАДО!, т.к. внутри CalcKeyCode + // структура INPUT_RECORD модифицируется! + return (int)CalcKeyCode(&Rec,FALSE); + } + + return KEY_NONE; +} + + +DWORD IsMouseButtonPressed() +{ + INPUT_RECORD rec; + + if (PeekInputRecord(&rec)) + { + GetInputRecord(&rec); + } + + WINPORT(Sleep)(10); + return MouseButtonState; +} + +static DWORD KeyMsClick2ButtonState(DWORD Key,DWORD& Event) +{ + Event=0; +#if 0 + + switch (Key) + { + case KEY_MSM1DBLCLICK: + case KEY_MSM2DBLCLICK: + case KEY_MSM3DBLCLICK: + case KEY_MSLDBLCLICK: + case KEY_MSRDBLCLICK: + Event=MOUSE_MOVED; + } + +#endif + + switch (Key) + { + case KEY_MSLCLICK: + return FROM_LEFT_1ST_BUTTON_PRESSED; + case KEY_MSM1CLICK: + return FROM_LEFT_2ND_BUTTON_PRESSED; + case KEY_MSM2CLICK: + return FROM_LEFT_3RD_BUTTON_PRESSED; + case KEY_MSM3CLICK: + return FROM_LEFT_4TH_BUTTON_PRESSED; + case KEY_MSRCLICK: + return RIGHTMOST_BUTTON_PRESSED; + } + + return 0; +} + +DWORD GetInputRecord(INPUT_RECORD *rec,bool ExcludeMacro,bool ProcessMouse,bool AllowSynchro) +{ + _KEYMACRO(CleverSysLog Clev(L"GetInputRecord()")); + static int LastEventIdle=FALSE; + DWORD LoopCount=0,CalcKey; + DWORD ReadKey=0; + int NotMacros=FALSE; + static int LastMsClickMacroKey=0; + static clock_t sLastIdleDelivered = 0; + + if (AllowSynchro) + PluginSynchroManager.Process(); + + FARString::ScanForLeaks(); + + if (FrameManager && FrameManager->RegularIdleWantersCount()) + { + clock_t now = GetProcessUptimeMSec(); + if (now - sLastIdleDelivered >= 1000) { + LastEventIdle=TRUE; + memset(rec,0,sizeof(*rec)); + rec->EventType=KEY_EVENT; + sLastIdleDelivered=now; + return KEY_IDLE; + } + } + + if (!ExcludeMacro && CtrlObject && CtrlObject->Cp()) + { +// _KEYMACRO(CleverSysLog SL(L"GetInputRecord()")); + int VirtKey,ControlState; + CtrlObject->Macro.RunStartMacro(); + int MacroKey=CtrlObject->Macro.GetKey(); + + if (MacroKey) + { + DWORD EventState,MsClickKey; + + if ((MsClickKey=KeyMsClick2ButtonState(MacroKey,EventState)) ) + { + // Ахтунг! Для мышиной клавиши вернем значение MOUSE_EVENT, соответствующее _последнему_ событию мыши. + rec->EventType=MOUSE_EVENT; + rec->Event.MouseEvent=lastMOUSE_EVENT_RECORD; + rec->Event.MouseEvent.dwButtonState=MsClickKey; + rec->Event.MouseEvent.dwEventFlags=EventState; + LastMsClickMacroKey=MacroKey; + return MacroKey; + } + else + { + // если предыдущая клавиша мышиная - сбросим состояние панели Drag + if (KeyMsClick2ButtonState(LastMsClickMacroKey,EventState)) + { + LastMsClickMacroKey=0; + Panel::EndDrag(); + } + + ScrBuf.Flush(); + TranslateKeyToVK(MacroKey,VirtKey,ControlState,rec); + rec->EventType=((((unsigned int)MacroKey >= KEY_MACRO_BASE && (unsigned int)MacroKey <= KEY_MACRO_ENDBASE) || ((unsigned int)MacroKey>=KEY_OP_BASE && (unsigned int)MacroKey <=KEY_OP_ENDBASE)) || (MacroKey&(~0xFF000000)) >= KEY_END_FKEY)?0:FARMACRO_KEY_EVENT; + + if (!(MacroKey&KEY_SHIFT)) + ShiftPressed=0; + + //_KEYMACRO(SysLog(L"MacroKey1 =%ls",_FARKEY_ToName(MacroKey))); + // memset(rec,0,sizeof(*rec)); + return(MacroKey); + } + } + } + + if (KeyQueue && KeyQueue->Peek()) + { + CalcKey=KeyQueue->Get(); + NotMacros=CalcKey&0x80000000?1:0; + CalcKey&=~0x80000000; + + //??? + if (!ExcludeMacro && CtrlObject && CtrlObject->Macro.IsRecording() && (CalcKey == (KEY_ALT|KEY_NUMPAD0) || CalcKey == (KEY_ALT|KEY_INS))) + { + _KEYMACRO(SysLog(L"[%d] CALL CtrlObject->Macro.ProcessKey(%ls)",__LINE__,_FARKEY_ToName(CalcKey))); + FrameManager->SetLastInputRecord(rec); + if (CtrlObject->Macro.ProcessKey(CalcKey)) + { + RunGraber(); + rec->EventType=0; + CalcKey=KEY_NONE; + } + + return(CalcKey); + } + + if (!NotMacros) + { + _KEYMACRO(SysLog(L"[%d] CALL CtrlObject->Macro.ProcessKey(%ls)",__LINE__,_FARKEY_ToName(CalcKey))); + FrameManager->SetLastInputRecord(rec); + if (!ExcludeMacro && CtrlObject && CtrlObject->Macro.ProcessKey(CalcKey)) + { + rec->EventType=0; + CalcKey=KEY_NONE; + } + } + + return(CalcKey); + } + + int EnableShowTime=Opt.Clock && (WaitInMainLoop || (CtrlObject && + CtrlObject->Macro.GetMode()==MACRO_SEARCH)); + + if (EnableShowTime) + ShowTime(1); + + ScrBuf.Flush(); + + if (!LastEventIdle) + StartIdleTime=GetProcessUptimeMSec(); + + LastEventIdle=FALSE; + SetFarConsoleMode(); + BOOL ZoomedState=Console.IsZoomed(); + BOOL IconicState=Console.IsIconic(); + + bool FullscreenState=IsFullscreen(); + + for (;;) + { + // "Реакция" на максимизацию/восстановление окна консоли + if (ZoomedState!=Console.IsZoomed() && IconicState==Console.IsIconic()) + { + ZoomedState=!ZoomedState; + ChangeVideoMode(ZoomedState); + } + + bool CurrentFullscreenState=IsFullscreen(); + if(CurrentFullscreenState && !FullscreenState) + { + ChangeVideoMode(25,80); + } + FullscreenState=CurrentFullscreenState; + + /* $ 26.04.2001 VVM + ! Убрал подмену колесика */ + if (Console.PeekInput(*rec)) + { + //cheat for flock + if (rec->EventType==KEY_EVENT && !rec->Event.KeyEvent.wVirtualScanCode && (rec->Event.KeyEvent.wVirtualKeyCode==VK_NUMLOCK||rec->Event.KeyEvent.wVirtualKeyCode==VK_CAPITAL||rec->Event.KeyEvent.wVirtualKeyCode==VK_SCROLL)) + { + INPUT_RECORD pinp; + Console.ReadInput(pinp); + continue; + } + + // // _SVS(INPUT_RECORD_DumpBuffer()); +#if 0 + + if (rec->EventType==KEY_EVENT) + { + // берем количество оставшейся порции эвентов + DWORD ReadCount2; + GetNumberOfConsoleInputEvents(Console.GetInputHandle(),&ReadCount2); + + // если их безобразно много, то просмотрим все на предмет KEY_EVENT + if (ReadCount2 > 1) + { + INPUT_RECORD *TmpRec=(INPUT_RECORD*)malloc(sizeof(INPUT_RECORD)*ReadCount2); + + if (TmpRec) + { + DWORD ReadCount3; + INPUT_RECORD TmpRec2; + Console.PeekInput(Console.GetInputHandle(),TmpRec,ReadCount2,&ReadCount3); + + for (int I=0; I < ReadCount2; ++I) + { + if (TmpRec[I].EventType!=KEY_EVENT) + break; + + // // _SVS(SysLog(L"%d> %ls",I,_INPUT_RECORD_Dump(rec))); + Console.ReadInput((Console.GetInputHandle(),&TmpRec2,1,&ReadCount3); + + if (TmpRec[I].Event.KeyEvent.bKeyDown==1) + { + if (TmpRec[I].Event.KeyEvent.uChar.AsciiChar ) + WriteInput(TmpRec[I].Event.KeyEvent.uChar.AsciiChar,0); + } + else if (TmpRec[I].Event.KeyEvent.wVirtualKeyCode==0x12) + { + if (TmpRec[I].Event.KeyEvent.uChar.AsciiChar ) + WriteInput(TmpRec[I].Event.KeyEvent.uChar.AsciiChar,0); + } + } + + // освободим память + free(TmpRec); + return KEY_NONE; + } + } + } + +#endif + break; + } + + ScrBuf.Flush(); + WINPORT(Sleep)(10); + + // Позволяет избежать ситуации блокирования мыши + if (Opt.Mouse) // А нужно ли это условие??? + SetFarConsoleMode(); + + if (CloseFAR) + { +// CloseFAR=FALSE; + /* $ 30.08.2001 IS + При принудительном закрытии Фара пытаемся вести себя так же, как и при + нажатии на F10 в панелях, только не запрашиваем подтверждение закрытия, + если это возможно. + */ + if (!Opt.CloseConsoleRule) + FrameManager->IsAnyFrameModified(TRUE); + else + FrameManager->ExitMainLoop(FALSE); + + return KEY_NONE; + } + + if (!(LoopCount & 15)) + { + clock_t CurTime=GetProcessUptimeMSec(); + + if (EnableShowTime) + ShowTime(0); + + if (WaitInMainLoop) + { + if (CheckForInactivityExit()) + return(KEY_NONE); + + if (!(LoopCount & 63)) + { + static int Reenter=0; + + if (!Reenter) + { + Reenter++; + SHORT X,Y; + GetRealCursorPos(X,Y); + + if (!X && Y==ScrY && CtrlObject->CmdLine->IsVisible()) + { + for (;;) + { + INPUT_RECORD tmprec; + int Key=GetInputRecord(&tmprec); + + if ((DWORD)Key==KEY_NONE || ((DWORD)Key!=KEY_SHIFT && tmprec.Event.KeyEvent.bKeyDown)) + break; + } + + CtrlObject->Cp()->SetScreenPosition(); + ScrBuf.ResetShadow(); + ScrBuf.Flush(); + } + + Reenter--; + } + + static int UpdateReenter=0; + + if (!UpdateReenter && CurTime-KeyPressedLastTime>700) + { + UpdateReenter=TRUE; + CtrlObject->Cp()->LeftPanel->UpdateIfChanged(UIC_UPDATE_NORMAL); + CtrlObject->Cp()->RightPanel->UpdateIfChanged(UIC_UPDATE_NORMAL); + UpdateReenter=FALSE; + } + } + } + + if (Opt.ScreenSaver && Opt.ScreenSaverTime>0 && + CurTime-StartIdleTime>Opt.ScreenSaverTime*60000) + if (!ScreenSaver(WaitInMainLoop)) + return(KEY_NONE); + + if (!WaitInMainLoop && LoopCount==64) + { + LastEventIdle=TRUE; + memset(rec,0,sizeof(*rec)); + rec->EventType=KEY_EVENT; + sLastIdleDelivered=GetProcessUptimeMSec(); + return(KEY_IDLE); + } + } + + if (PluginSynchroManager.Process()) + { + memset(rec,0,sizeof(*rec)); + return KEY_NONE; + } + + LoopCount++; + } // while (1) + + if (rec->EventType==NOOP_EVENT) { + Console.ReadInput(*rec); + memset(rec,0,sizeof(*rec)); + rec->EventType=KEY_EVENT; + return KEY_NONE; + } + + clock_t CurClock=GetProcessUptimeMSec(); + + if (rec->EventType==FOCUS_EVENT) + { + /* $ 28.04.2001 VVM + + Не только обработаем сами смену фокуса, но и передадим дальше */ + ShiftPressed=RightShiftPressedLast=ShiftPressedLast=FALSE; + CtrlPressed=CtrlPressedLast=RightCtrlPressedLast=FALSE; + AltPressed=AltPressedLast=RightAltPressedLast=FALSE; + MouseButtonState=0; + ShiftState=FALSE; + PressedLastTime=0; + Console.ReadInput(*rec); + CalcKey=rec->Event.FocusEvent.bSetFocus?KEY_GOTFOCUS:KEY_KILLFOCUS; + memset(rec,0,sizeof(*rec)); + rec->EventType=KEY_EVENT; + //чтоб решить баг винды приводящий к появлению скролов и т.п. после потери фокуса + if (CalcKey == KEY_GOTFOCUS) + RestoreConsoleWindowRect(); + else + SaveConsoleWindowRect(); + + return CalcKey; + } + + if (rec->EventType==KEY_EVENT) + { + /* коррекция шифта, т.к. + NumLock=ON Shift-Numpad1 + Dn, 1, Vk=0x0010, Scan=0x002A Ctrl=0x00000030 (caSa - cecN) + Dn, 1, Vk=0x0023, Scan=0x004F Ctrl=0x00000020 (casa - cecN) + Up, 1, Vk=0x0023, Scan=0x004F Ctrl=0x00000020 (casa - cecN) + >>>Dn, 1, Vk=0x0010, Scan=0x002A Ctrl=0x00000030 (caSa - cecN) + Up, 1, Vk=0x0010, Scan=0x002A Ctrl=0x00000020 (casa - cecN) + винда вставляет лишний шифт + */ + /* + if(rec->Event.KeyEvent.wVirtualKeyCode == VK_SHIFT) + { + if(rec->Event.KeyEvent.bKeyDown) + { + if(!ShiftState) + ShiftState=TRUE; + else // Здесь удалим из очереди... этот самый кривой шифт + { + INPUT_RECORD pinp; + Console.ReadInput(&pinp); + return KEY_NONE; + } + } + else if(!rec->Event.KeyEvent.bKeyDown) + ShiftState=FALSE; + } + + if(!(rec->Event.KeyEvent.dwControlKeyState & SHIFT_PRESSED) && ShiftState) + rec->Event.KeyEvent.dwControlKeyState|=SHIFT_PRESSED; + */ +//_SVS(if(rec->EventType==KEY_EVENT)SysLog(L"%ls",_INPUT_RECORD_Dump(rec))); + DWORD CtrlState=rec->Event.KeyEvent.dwControlKeyState; + +//_SVS(if(rec->EventType==KEY_EVENT)SysLog(L"[%d] if(rec->EventType==KEY_EVENT) >>> %ls",__LINE__,_INPUT_RECORD_Dump(rec))); + if (CtrlObject && CtrlObject->Macro.IsRecording()) + { + static WORD PrevVKKeyCode=0; // NumLock+Cursor + WORD PrevVKKeyCode2=PrevVKKeyCode; + PrevVKKeyCode=rec->Event.KeyEvent.wVirtualKeyCode; + + /* 1.07.2001 KM + При отпускании Shift-Enter в диалоге назначения + вылазил Shift после отпускания клавиш. + */ + if ((PrevVKKeyCode2==VK_SHIFT && PrevVKKeyCode==VK_RETURN && + rec->Event.KeyEvent.bKeyDown) || + (PrevVKKeyCode2==VK_RETURN && PrevVKKeyCode==VK_SHIFT && + !rec->Event.KeyEvent.bKeyDown)) + { + if (PrevVKKeyCode2 != VK_SHIFT) + { + INPUT_RECORD pinp; + // Удалим из очереди... + Console.ReadInput(pinp); + return KEY_NONE; + } + } + } + + CtrlPressed=(CtrlState & (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED)); + AltPressed=(CtrlState & (LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED)); + ShiftPressed=(CtrlState & SHIFT_PRESSED); + RightCtrlPressed=(CtrlState & RIGHT_CTRL_PRESSED); + RightAltPressed=(CtrlState & RIGHT_ALT_PRESSED); + RightShiftPressed=(CtrlState & SHIFT_PRESSED); //??? + KeyPressedLastTime=CurClock; + + /* $ 24.08.2000 SVS + + Добавление на реакцию KEY_CTRLALTSHIFTRELEASE + */ + if (IsKeyCASPressed && (Opt.CASRule&1) && (!CtrlPressed || !AltPressed || !ShiftPressed)) + { + IsKeyCASPressed=FALSE; + return KEY_CTRLALTSHIFTRELEASE; + } + + if (IsKeyRCASPressed && (Opt.CASRule&2) && (!RightCtrlPressed || !RightAltPressed || !ShiftPressed)) + { + IsKeyRCASPressed=FALSE; + return KEY_RCTRLALTSHIFTRELEASE; + } + } + +//_SVS(if(rec->EventType==KEY_EVENT)SysLog(L"[%d] if(rec->EventType==KEY_EVENT) >>> %ls",__LINE__,_INPUT_RECORD_Dump(rec))); + ReturnAltValue=FALSE; + CalcKey=CalcKeyCode(rec,TRUE,&NotMacros); + /* + if(CtrlObject && CtrlObject->Macro.IsRecording() && (CalcKey == (KEY_ALT|KEY_NUMPAD0) || CalcKey == (KEY_ALT|KEY_INS))) + { + _KEYMACRO(SysLog(L"[%d] CALL CtrlObject->Macro.ProcessKey(%ls)",__LINE__,_FARKEY_ToName(CalcKey))); + FrameManager->SetLastInputRecord(rec); + if(CtrlObject->Macro.ProcessKey(CalcKey)) + { + RunGraber(); + rec->EventType=0; + CalcKey=KEY_NONE; + } + return(CalcKey); + } + */ + +//_SVS(SysLog(L"1) CalcKey=%ls",_FARKEY_ToName(CalcKey))); + if (ReturnAltValue && !NotMacros) + { + _KEYMACRO(SysLog(L"[%d] CALL CtrlObject->Macro.ProcessKey(%ls)",__LINE__,_FARKEY_ToName(CalcKey))); + FrameManager->SetLastInputRecord(rec); + if (CtrlObject && CtrlObject->Macro.ProcessKey(CalcKey)) + { + rec->EventType=0; + CalcKey=KEY_NONE; + } + + return(CalcKey); + } + + Console.ReadInput(*rec); + + if (EnableShowTime) + ShowTime(1); + + bool SizeChanged=false; + if(Opt.WindowMode) + { + SMALL_RECT CurConRect; + Console.GetWindowRect(CurConRect); + if(CurConRect.Bottom-CurConRect.Top!=ScrY || CurConRect.Right-CurConRect.Left!=ScrX) + { + SizeChanged=true; + } + } + + /*& 17.05.2001 OT Изменился размер консоли, генерим клавишу*/ + if (rec->EventType==WINDOW_BUFFER_SIZE_EVENT || SizeChanged) + { + int PScrX=ScrX; + int PScrY=ScrY; + //// // _SVS(SysLog(1,"GetInputRecord(WINDOW_BUFFER_SIZE_EVENT)")); + WINPORT(Sleep)(10); + GetVideoMode(CurSize); + bool NotIgnore=Opt.WindowMode && (rec->Event.WindowBufferSizeEvent.dwSize.X!=CurSize.X || rec->Event.WindowBufferSizeEvent.dwSize.Y!=CurSize.Y); + if (PScrX+1 == CurSize.X && PScrY+1 == CurSize.Y && !NotIgnore) + { + return KEY_NONE; + } + else + { + if(Opt.WindowMode && (PScrX+1>CurSize.X || PScrY+1>CurSize.Y)) + { + //Console.ClearExtraRegions(FarColorToReal(COL_COMMANDLINEUSERSCREEN)); + } + PrevScrX=PScrX; + PrevScrY=PScrY; + //// // _SVS(SysLog(-1,"GetInputRecord(WINDOW_BUFFER_SIZE_EVENT); return KEY_CONSOLE_BUFFER_RESIZE")); + WINPORT(Sleep)(10); + + if (FrameManager) + { + ScrBuf.ResetShadow(); + // апдейтим панели (именно они сейчас!) + LockScreen LckScr; + + if (GlobalSaveScrPtr) + GlobalSaveScrPtr->Discard(); + + FrameManager->ResizeAllFrame(); + FrameManager->GetCurrentFrame()->Show(); + //// // _SVS(SysLog(L"PreRedrawFunc = %p",PreRedrawFunc)); + PreRedrawItem preRedrawItem=PreRedraw.Peek(); + + if (preRedrawItem.PreRedrawFunc) + { + preRedrawItem.PreRedrawFunc(); + } + } + + return(KEY_CONSOLE_BUFFER_RESIZE); + } + } + + if (rec->EventType==KEY_EVENT) + { + DWORD CtrlState=rec->Event.KeyEvent.dwControlKeyState; + DWORD KeyCode=rec->Event.KeyEvent.wVirtualKeyCode; + CtrlPressed=(CtrlState & (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED)); + AltPressed=(CtrlState & (LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED)); + RightCtrlPressed=(CtrlState & RIGHT_CTRL_PRESSED); + RightAltPressed=(CtrlState & RIGHT_ALT_PRESSED); + + // Для NumPad! + if ((CalcKey&(KEY_CTRL|KEY_SHIFT|KEY_ALT|KEY_RCTRL|KEY_RALT)) == KEY_SHIFT && + (CalcKey&KEY_MASKF) >= KEY_NUMPAD0 && (CalcKey&KEY_MASKF) <= KEY_NUMPAD9) + ShiftPressed=SHIFT_PRESSED; + else + ShiftPressed=(CtrlState & SHIFT_PRESSED); + + if ((KeyCode==VK_F16 && ReadKey==VK_F16) || !KeyCode) + return(KEY_NONE); + + if (!rec->Event.KeyEvent.bKeyDown && + (KeyCode==VK_SHIFT || KeyCode==VK_CONTROL || KeyCode==VK_MENU) && + CurClock-PressedLastTime<500) + { + uint32_t Key {std::numeric_limits<uint32_t>::max()}; + + if (ShiftPressedLast && KeyCode==VK_SHIFT) + { + if (ShiftPressedLast) + { + Key=KEY_SHIFT; + //// // _SVS(SysLog(L"ShiftPressedLast, Key=KEY_SHIFT")); + } + else if (RightShiftPressedLast) + { + Key=KEY_RSHIFT; + //// // _SVS(SysLog(L"RightShiftPressedLast, Key=KEY_RSHIFT")); + } + } + + if (KeyCode==VK_CONTROL) + { + if (CtrlPressedLast) + { + Key=KEY_CTRL; + //// // _SVS(SysLog(L"CtrlPressedLast, Key=KEY_CTRL")); + } + else if (RightCtrlPressedLast) + { + Key=KEY_RCTRL; + //// // _SVS(SysLog(L"CtrlPressedLast, Key=KEY_RCTRL")); + } + } + + if (KeyCode==VK_MENU) + { + if (AltPressedLast) + { + Key=KEY_ALT; + //// // _SVS(SysLog(L"AltPressedLast, Key=KEY_ALT")); + } + else if (RightAltPressedLast) + { + Key=KEY_RALT; + //// // _SVS(SysLog(L"RightAltPressedLast, Key=KEY_RALT")); + } + } + + { + _KEYMACRO(SysLog(L"[%d] CALL CtrlObject->Macro.ProcessKey(%ls)",__LINE__,_FARKEY_ToName(Key))); + if(FrameManager) + { + FrameManager->SetLastInputRecord(rec); + } + if (Key!=std::numeric_limits<uint32_t>::max() && !NotMacros && CtrlObject && CtrlObject->Macro.ProcessKey(Key)) + { + rec->EventType=0; + Key=KEY_NONE; + } + } + + if (Key!=std::numeric_limits<uint32_t>::max()) + return(Key); + } + + ShiftPressedLast=RightShiftPressedLast=FALSE; + CtrlPressedLast=RightCtrlPressedLast=FALSE; + AltPressedLast=RightAltPressedLast=FALSE; + ShiftPressedLast=(KeyCode==VK_SHIFT && rec->Event.KeyEvent.bKeyDown) || + (KeyCode==VK_RETURN && ShiftPressed && !rec->Event.KeyEvent.bKeyDown); + + if (!ShiftPressedLast) + if (KeyCode==VK_CONTROL && rec->Event.KeyEvent.bKeyDown) + { + if (CtrlState & RIGHT_CTRL_PRESSED) + { + RightCtrlPressedLast=TRUE; + //// // _SVS(SysLog(L"RightCtrlPressedLast=TRUE;")); + } + else + { + CtrlPressedLast=TRUE; + //// // _SVS(SysLog(L"CtrlPressedLast=TRUE;")); + } + } + + if (!ShiftPressedLast && !CtrlPressedLast && !RightCtrlPressedLast) + { + if (KeyCode==VK_MENU && rec->Event.KeyEvent.bKeyDown) + { + if (CtrlState & RIGHT_ALT_PRESSED) + { + RightAltPressedLast=TRUE; + } + else + { + AltPressedLast=TRUE; + } + + PressedLastTime=CurClock; + } + } + else + PressedLastTime=CurClock; + + if (KeyCode==VK_SHIFT || KeyCode==VK_MENU || KeyCode==VK_CONTROL || KeyCode==VK_NUMLOCK || KeyCode==VK_SCROLL || KeyCode==VK_CAPITAL) + { + if ((KeyCode==VK_NUMLOCK || KeyCode==VK_SCROLL || KeyCode==VK_CAPITAL) && + (CtrlState&(LEFT_CTRL_PRESSED|LEFT_ALT_PRESSED|SHIFT_PRESSED|RIGHT_ALT_PRESSED|RIGHT_CTRL_PRESSED)) + ) + { + // TODO: + ; + } + else + { + /* $ 24.08.2000 SVS + + Добавление на реакцию KEY_CTRLALTSHIFTPRESS + */ + switch (KeyCode) + { + case VK_SHIFT: + case VK_MENU: + case VK_CONTROL: + + if (!IsKeyCASPressed && CtrlPressed && AltPressed && ShiftPressed) + { + if (!IsKeyRCASPressed && RightCtrlPressed && RightAltPressed && RightShiftPressed) + { + if (Opt.CASRule&2) + { + IsKeyRCASPressed=TRUE; + return (KEY_RCTRLALTSHIFTPRESS); + } + } + else if (Opt.CASRule&1) + { + IsKeyCASPressed=TRUE; + return (KEY_CTRLALTSHIFTPRESS); + } + } + + break; + case VK_LSHIFT: + case VK_LMENU: + case VK_LCONTROL: + + if (!IsKeyRCASPressed && RightCtrlPressed && RightAltPressed && RightShiftPressed) + { + if ((Opt.CASRule&2)) + { + IsKeyRCASPressed=TRUE; + return (KEY_RCTRLALTSHIFTPRESS); + } + } + + break; + } + + return(KEY_NONE); + } + } + + Panel::EndDrag(); + } + + if (rec->EventType==MOUSE_EVENT) + { + lastMOUSE_EVENT_RECORD=rec->Event.MouseEvent; + PreMouseEventFlags=MouseEventFlags; + MouseEventFlags=rec->Event.MouseEvent.dwEventFlags; + DWORD CtrlState=rec->Event.MouseEvent.dwControlKeyState; + KeyMacro::SetMacroConst(constMsCtrlState,(int64_t)CtrlState); + KeyMacro::SetMacroConst(constMsEventFlags,(int64_t)MouseEventFlags); + /* + // Сигнал на прорисовку ;-) Помогает прорисовать кейбар при движении мышью + if(CtrlState != (CtrlPressed|AltPressed|ShiftPressed)) + { + static INPUT_RECORD TempRec[2]={ + {KEY_EVENT,{1,1,VK_F16,0,{0},0}}, + {KEY_EVENT,{0,1,VK_F16,0,{0},0}} + }; + DWORD WriteCount; + TempRec[0].Event.KeyEvent.dwControlKeyState=TempRec[1].Event.KeyEvent.dwControlKeyState=CtrlState; + Console.WriteInput(*TempRec, 2, WriteCount); + } + */ + CtrlPressed=(CtrlState & (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED)); + AltPressed=(CtrlState & (LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED)); + ShiftPressed=(CtrlState & SHIFT_PRESSED); + RightCtrlPressed=(CtrlState & RIGHT_CTRL_PRESSED); + RightAltPressed=(CtrlState & RIGHT_ALT_PRESSED); + RightShiftPressed=(CtrlState & SHIFT_PRESSED); + DWORD BtnState=rec->Event.MouseEvent.dwButtonState; + KeyMacro::SetMacroConst(constMsButton,(int64_t)rec->Event.MouseEvent.dwButtonState); + + if (MouseEventFlags != MOUSE_MOVED) + { +//// // _SVS(SysLog(L"1. CtrlState=%X PrevRButtonPressed=%d,RButtonPressed=%d",CtrlState,PrevRButtonPressed,RButtonPressed)); + PrevMouseButtonState=MouseButtonState; + } + + MouseButtonState=BtnState; +//// // _SVS(SysLog(L"2. BtnState=%X PrevRButtonPressed=%d,RButtonPressed=%d",BtnState,PrevRButtonPressed,RButtonPressed)); + PrevMouseX=MouseX; + PrevMouseY=MouseY; + MouseX=rec->Event.MouseEvent.dwMousePosition.X; + MouseY=rec->Event.MouseEvent.dwMousePosition.Y; + KeyMacro::SetMacroConst(constMsX,(int64_t)MouseX); + KeyMacro::SetMacroConst(constMsY,(int64_t)MouseY); + + /* $ 26.04.2001 VVM + + Обработка колесика мышки. */ + if (MouseEventFlags == MOUSE_WHEELED) + { // Обработаем колесо и заменим на спец.клавиши + short zDelta = HIWORD(rec->Event.MouseEvent.dwButtonState); + CalcKey = (zDelta>0)?KEY_MSWHEEL_UP:KEY_MSWHEEL_DOWN; + /* $ 27.04.2001 SVS + Не были учтены шифтовые клавиши при прокрутке колеса, из-за чего + нельзя было использовать в макросах нечто вроде "ShiftMsWheelUp" + */ + CalcKey |= (CtrlState&SHIFT_PRESSED?KEY_SHIFT:0)| + (CtrlState&(LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED)?KEY_CTRL:0)| + (CtrlState&(LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED)?KEY_ALT:0); + memset(rec,0,sizeof(*rec)); + rec->EventType = KEY_EVENT; + } + + // Обработка горизонтального колесика (NT>=6) + if (MouseEventFlags == MOUSE_HWHEELED) + { + short zDelta = HIWORD(rec->Event.MouseEvent.dwButtonState); + CalcKey = (zDelta>0)?KEY_MSWHEEL_RIGHT:KEY_MSWHEEL_LEFT; + CalcKey |= (CtrlState&SHIFT_PRESSED?KEY_SHIFT:0)| + (CtrlState&(LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED)?KEY_CTRL:0)| + (CtrlState&(LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED)?KEY_ALT:0); + memset(rec,0,sizeof(*rec)); + rec->EventType = KEY_EVENT; + } + + if (rec->EventType==MOUSE_EVENT && (!ExcludeMacro||ProcessMouse) && CtrlObject && (ProcessMouse || !(CtrlObject->Macro.IsRecording() || CtrlObject->Macro.IsExecuting()))) + { + if (MouseEventFlags != MOUSE_MOVED) + { + DWORD MsCalcKey=0; +#if 0 + + if (rec->Event.MouseEvent.dwButtonState&RIGHTMOST_BUTTON_PRESSED) + MsCalcKey=(MouseEventFlags == DOUBLE_CLICK)?KEY_MSRDBLCLICK:KEY_MSRCLICK; + else if (rec->Event.MouseEvent.dwButtonState&FROM_LEFT_1ST_BUTTON_PRESSED) + MsCalcKey=(MouseEventFlags == DOUBLE_CLICK)?KEY_MSLDBLCLICK:KEY_MSLCLICK; + else if (rec->Event.MouseEvent.dwButtonState&FROM_LEFT_2ND_BUTTON_PRESSED) + MsCalcKey=(MouseEventFlags == DOUBLE_CLICK)?KEY_MSM1DBLCLICK:KEY_MSM1CLICK; + else if (rec->Event.MouseEvent.dwButtonState&FROM_LEFT_3RD_BUTTON_PRESSED) + MsCalcKey=(MouseEventFlags == DOUBLE_CLICK)?KEY_MSM2DBLCLICK:KEY_MSM2CLICK; + else if (rec->Event.MouseEvent.dwButtonState&FROM_LEFT_4TH_BUTTON_PRESSED) + MsCalcKey=(MouseEventFlags == DOUBLE_CLICK)?KEY_MSM3DBLCLICK:KEY_MSM3CLICK; + +#else + + if (rec->Event.MouseEvent.dwButtonState&RIGHTMOST_BUTTON_PRESSED) + MsCalcKey=KEY_MSRCLICK; + else if (rec->Event.MouseEvent.dwButtonState&FROM_LEFT_1ST_BUTTON_PRESSED) + MsCalcKey=KEY_MSLCLICK; + else if (rec->Event.MouseEvent.dwButtonState&FROM_LEFT_2ND_BUTTON_PRESSED) + MsCalcKey=KEY_MSM1CLICK; + else if (rec->Event.MouseEvent.dwButtonState&FROM_LEFT_3RD_BUTTON_PRESSED) + MsCalcKey=KEY_MSM2CLICK; + else if (rec->Event.MouseEvent.dwButtonState&FROM_LEFT_4TH_BUTTON_PRESSED) + MsCalcKey=KEY_MSM3CLICK; + +#endif + + if (MsCalcKey) + { + MsCalcKey |= (CtrlState&SHIFT_PRESSED?KEY_SHIFT:0)| + (CtrlState&(LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED)?KEY_CTRL:0)| + (CtrlState&(LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED)?KEY_ALT:0); + + // для WaitKey() + if (ProcessMouse) + return MsCalcKey; + else + { + _KEYMACRO(SysLog(L"[%d] CALL CtrlObject->Macro.ProcessKey(%ls)",__LINE__,_FARKEY_ToName(MsCalcKey))); + FrameManager->SetLastInputRecord(rec); + if (CtrlObject->Macro.ProcessKey(MsCalcKey)) + { + memset(rec,0,sizeof(*rec)); + return KEY_NONE; + } + } + } + } + } + } + + int GrayKey=(CalcKey==KEY_ADD || CalcKey==KEY_SUBTRACT || CalcKey==KEY_MULTIPLY); + + if (ReadKey && !GrayKey) + CalcKey=ReadKey; + + { + _KEYMACRO(SysLog(L"[%d] CALL CtrlObject->Macro.ProcessKey(%ls)",__LINE__,_FARKEY_ToName(CalcKey))); + if(FrameManager) + { + FrameManager->SetLastInputRecord(rec); + } + if (!NotMacros && CtrlObject && CtrlObject->Macro.ProcessKey(CalcKey)) + { + rec->EventType=0; + CalcKey=KEY_NONE; + } + } + return(CalcKey); +} + +DWORD PeekInputRecord(INPUT_RECORD *rec,bool ExcludeMacro) +{ + DWORD Key; + ScrBuf.Flush(); + + if (KeyQueue && (Key=KeyQueue->Peek()) ) + { + int VirtKey,ControlState; + if (!TranslateKeyToVK(Key,VirtKey,ControlState,rec)) + return 0; + } + else if ((!ExcludeMacro) && (Key=CtrlObject->Macro.PeekKey()) ) + { + int VirtKey,ControlState; + if (!TranslateKeyToVK(Key,VirtKey,ControlState,rec)) + return 0; + } + else + { + if (!Console.PeekInput(*rec)) + return 0; + } + + return(CalcKeyCode(rec,TRUE)); +} + +/* $ 24.08.2000 SVS + + Пераметр у фунции WaitKey - возможность ожидать конкретную клавишу + Если KeyWait = -1 - как и раньше +*/ +DWORD WaitKey(DWORD KeyWait,DWORD delayMS,bool ExcludeMacro) +{ + bool Visible=false; + bool AdHocQuickEdit= ((KeyWait&(~KEY_CTRLMASK)) != KEY_MSLCLICK); + DWORD Size=0; + + if (KeyWait == KEY_CTRLALTSHIFTRELEASE || KeyWait == KEY_RCTRLALTSHIFTRELEASE) + { + GetCursorType(Visible,Size); + SetCursorType(0,10); + } + + clock_t CheckTime=GetProcessUptimeMSec()+delayMS; + DWORD Key; + + for (;;) + { + INPUT_RECORD rec; + Key=KEY_NONE; + + if (PeekInputRecord(&rec,ExcludeMacro)) + { + Key=GetInputRecord(&rec,ExcludeMacro,true); + } + + if (AdHocQuickEdit && (Key&(~KEY_CTRLMASK)) == KEY_MSLCLICK) { + WINPORT(BeginConsoleAdhocQuickEdit)(); + continue; + } + + if (KeyWait == KEY_INVALID) + { + if ((Key&(~KEY_CTRLMASK)) < KEY_END_FKEY || IS_INTERNAL_KEY_REAL(Key&(~KEY_CTRLMASK))) + break; + } + else if (Key == KeyWait) + break; + + if (delayMS && GetProcessUptimeMSec() >= CheckTime) + { + Key=KEY_NONE; + break; + } + + WINPORT(Sleep)(10); + } + + if (KeyWait == KEY_CTRLALTSHIFTRELEASE || KeyWait == KEY_RCTRLALTSHIFTRELEASE) + SetCursorType(Visible,Size); + + return Key; +} + +int WriteInput(int Key,DWORD Flags) +{ + if (Flags&(SKEY_VK_KEYS|SKEY_IDLE)) + { + INPUT_RECORD Rec; + DWORD WriteCount; + + if (Flags&SKEY_IDLE) + { + Rec.EventType=FOCUS_EVENT; + Rec.Event.FocusEvent.bSetFocus=TRUE; + } + else + { + Rec.EventType=KEY_EVENT; + Rec.Event.KeyEvent.bKeyDown=1; + Rec.Event.KeyEvent.wRepeatCount=1; + Rec.Event.KeyEvent.wVirtualKeyCode=Key; + Rec.Event.KeyEvent.wVirtualScanCode=WINPORT(MapVirtualKey)(Rec.Event.KeyEvent.wVirtualKeyCode,MAPVK_VK_TO_VSC); + + if (Key < 0x30 || Key > 0x5A) // 0-9:;<=>?@@ A..Z //????? + Key=0; + + Rec.Event.KeyEvent.uChar.UnicodeChar=Rec.Event.KeyEvent.uChar.AsciiChar=Key; + Rec.Event.KeyEvent.dwControlKeyState=0; + } + + return Console.WriteInput(Rec, 1, WriteCount); + } + else if (KeyQueue) + { + return KeyQueue->Put(((DWORD)Key)|(Flags&SKEY_NOTMACROS?0x80000000:0)); + } + else + return 0; +} + + +int CheckForEscSilent() +{ + INPUT_RECORD rec; + int Key; + BOOL Processed=TRUE; + /* TODO: Здесь, в общем то - ХЗ, т.к. + по хорошему нужно проверять CtrlObject->Macro.PeekKey() на ESC или BREAK + Но к чему это приведет - пока не могу дать ответ !!! + */ + + // если в "макросе"... + if (CtrlObject->Macro.IsExecuting() != MACROMODE_NOMACRO && FrameManager->GetCurrentFrame()) + { +#if 0 + + // ...но ЭТО конец последовательности (не Op-код)... + if (CtrlObject->Macro.IsExecutingLastKey() && !CtrlObject->Macro.IsOpCode(CtrlObject->Macro.PeekKey())) + CtrlObject->Macro.GetKey(); // ...то "завершим" макрос + else + Processed=FALSE; + +#else + + if (CtrlObject->Macro.IsDsableOutput()) + Processed=FALSE; + +#endif + } + + if (Processed && PeekInputRecord(&rec)) + { + int MMode=CtrlObject->Macro.GetMode(); + CtrlObject->Macro.SetMode(MACRO_LAST); // чтобы не срабатывали макросы :-) + Key=GetInputRecord(&rec,false,false,false); + CtrlObject->Macro.SetMode(MMode); + + /* + if(Key == KEY_CONSOLE_BUFFER_RESIZE) + { + // апдейтим панели (именно они сейчас!) + LockScreen LckScr; + FrameManager->ResizeAllFrame(); + FrameManager->GetCurrentFrame()->Show(); + PreRedrawItem preRedrawItem=PreRedraw.Peek(); + if(preRedrawItem.PreRedrawFunc) + { + preRedrawItem.PreRedrawFunc(); + } + + } + else + */ + if (Key==KEY_ESC || Key==KEY_BREAK) + return TRUE; + else if (Key==KEY_ALTF9) + FrameManager->ProcessKey(KEY_ALTF9); + } + + if (!Processed && CtrlObject->Macro.IsExecuting() != MACROMODE_NOMACRO) + ScrBuf.Flush(); + + return FALSE; +} + +int ConfirmAbortOp() +{ + return Opt.Confirm.Esc?AbortMessage():TRUE; +} + +/* $ 09.02.2001 IS + Подтверждение нажатия Esc +*/ +int CheckForEsc() +{ + if (CheckForEscSilent()) + return(ConfirmAbortOp()); + else + return FALSE; +} + +/* $ 25.07.2000 SVS + ! Функция KeyToText сделана самосотоятельной - вошла в состав FSF +*/ +/* $ 01.08.2000 SVS + ! дополнительный параметра у KeyToText - размер данных + Size=0 - по максимуму! +*/ +static FARString &GetShiftKeyName(FARString &strName, DWORD Key,int& Len) +{ + if ((Key&KEY_RCTRL) == KEY_RCTRL) strName += ModifKeyName[0].Name; + else if (Key&KEY_CTRL) strName += ModifKeyName[2].Name; + +// else if(Key&KEY_LCTRL) strcat(Name,ModifKeyName[3].Name); + + if ((Key&KEY_RALT) == KEY_RALT) strName += ModifKeyName[3].Name; + else if (Key&KEY_ALT) strName += ModifKeyName[4].Name; + +// else if(Key&KEY_LALT) strcat(Name,ModifKeyName[6].Name); + + if (Key&KEY_SHIFT) strName += ModifKeyName[1].Name; + +// else if(Key&KEY_LSHIFT) strcat(Name,ModifKeyName[0].Name); +// else if(Key&KEY_RSHIFT) strcat(Name,ModifKeyName[1].Name); + if (Key&KEY_M_SPEC) strName += ModifKeyName[5].Name; + else if (Key&KEY_M_OEM) strName += ModifKeyName[6].Name; + + Len=(int)strName.GetLength(); + return strName; +} + +/* $ 24.09.2000 SVS + + Функция KeyNameToKey - получение кода клавиши по имени + Если имя не верно или нет такого - возвращается 0xFFFFFFFF + Может и криво, но правильно и коротко! + + Функция KeyNameToKey ждет строку по вот такой спецификации: + + 1. Сочетания, определенные в структуре FKeys1[] + 2. Опциональные модификаторы (Alt/RAlt/Ctrl/RCtrl/Shift) и 1 символ, например, AltD или CtrlC + 3. "Alt" (или RAlt) и 5 десятичных цифр (с ведущими нулями) + 4. "Spec" и 5 десятичных цифр (с ведущими нулями) + 5. "Oem" и 5 десятичных цифр (с ведущими нулями) + 6. только модификаторы (Alt/RAlt/Ctrl/RCtrl/Shift) +*/ +uint32_t WINAPI KeyNameToKey(const wchar_t *Name) +{ + if (!Name || !*Name) + return KEY_INVALID; + + uint32_t Key=0; + // _SVS(SysLog(L"KeyNameToKey('%ls')",Name)); + + // Это макроклавиша? + if (Name[0] == L'$' && Name[1]) + return KEY_INVALID; // KeyNameMacroToKey(Name); + + if (Name[0] == L'%' && Name[1]) + return KEY_INVALID; + + if (Name[1] && FindAnyOfChars(Name, "()")) // если не один символ и встречаются '(' или ')', то это явно не клавиша! + return KEY_INVALID; + +// if((Key=KeyNameMacroToKey(Name)) != (DWORD)-1) +// return Key; + int I, Pos; + static FARString strTmpName; + strTmpName = Name; + strTmpName.Upper(); + int Len=(int)strTmpName.GetLength(); + + // пройдемся по всем модификаторам + for (Pos=I=0; I < int(ARRAYSIZE(ModifKeyName)); ++I) + { + if (wcsstr(strTmpName,ModifKeyName[I].UName) && !(Key&ModifKeyName[I].Key)) + { + int CntReplace=ReplaceStrings(strTmpName,ModifKeyName[I].UName,L"",-1,TRUE); + Key|=ModifKeyName[I].Key; + Pos+=ModifKeyName[I].Len*CntReplace; + } + } + // _SVS(SysLog(L"[%d] Name=%ls",__LINE__,Name)); + + //Pos=strlen(TmpName); + + // если что-то осталось - преобразуем. + if (Pos < Len) + { + // сначала - FKeys1 - Вариант (1) + const wchar_t* Ptr=Name+Pos; + int PtrLen = Len-Pos; + + for (I=(int)ARRAYSIZE(FKeys1)-1; I>=0; I--) + { + if (PtrLen == FKeys1[I].Len && !StrCmpI(Ptr,FKeys1[I].Name)) + { + Key|=FKeys1[I].Key; + Pos+=FKeys1[I].Len; + break; + } + } + + if (I == -1) // F-клавиш нет? + { + /* + здесь только 5 оставшихся вариантов: + 2) Опциональные модификаторы (Alt/RAlt/Ctrl/RCtrl/Shift) и 1 символ, например, AltD или CtrlC + 3) "Alt" (или RAlt) и 5 десятичных цифр (с ведущими нулями) + 4) "Spec" и 5 десятичных цифр (с ведущими нулями) + 5) "Oem" и 5 десятичных цифр (с ведущими нулями) + 6) только модификаторы (Alt/RAlt/Ctrl/RCtrl/Shift) + */ + + if (Len == 1 || Pos == Len-1) // Вариант (2) + { + int Chr=Name[Pos]; + + // если были модификаторы Alt/Ctrl, то преобразуем в "физичекую клавишу" (независимо от языка) + if (Key&(KEY_ALT|KEY_RCTRL|KEY_CTRL|KEY_RALT)) + { + if (Chr > 0x7F) + Chr=KeyToKeyLayout(Chr); + + Chr=Upper(Chr); + } + + Key|=Chr; + + if (Chr) + Pos++; + } + else if (Key == KEY_ALT || Key == KEY_RALT || Key == KEY_M_SPEC || Key == KEY_M_OEM) // Варианты (3), (4) и (5) + { + wchar_t *endptr=nullptr; + uint32_t K=static_cast<uint32_t>(wcstoul(Ptr, &endptr, 10)); + + if (Ptr+5 == endptr) + { + if (Key == KEY_ALT || Key == KEY_RALT) // Вариант (3) - Alt-Num + Key=(Key|K|KEY_ALTDIGIT)&(~(KEY_ALT|KEY_RALT)); + else if (Key == KEY_M_SPEC) // Вариант (4) + Key=(Key|(K+KEY_VK_0xFF_BEGIN))&(~(KEY_M_SPEC|KEY_M_OEM)); + else if (Key == KEY_M_OEM) // Вариант (5) + Key=(Key|(K+KEY_FKEY_BEGIN))&(~(KEY_M_SPEC|KEY_M_OEM)); + + Pos=Len; + } + } + // Вариант (6). Уже "собран". + } + } + + /* + if(!(Key&(KEY_ALT|KEY_RCTRL|KEY_CTRL|KEY_RALT|KEY_ALTDIGIT)) && (Key&KEY_SHIFT) && LocalIsalpha(Key&(~KEY_CTRLMASK))) + { + Key&=~KEY_SHIFT; + Key=LocalUpper(Key); + } + */ + // _SVS(SysLog(L"Key=0x%08X (%c) => '%ls'",Key,(Key?Key:' '),Name)); + return (!Key || Pos < Len)? KEY_INVALID : Key; +} + +BOOL WINAPI KeyToText(uint32_t Key0, FARString &strKeyText0) +{ + FARString strKeyText; + FARString strKeyTemp; + int I, Len; + DWORD Key=Key0, FKey=Key0&0xFFFFFF; + //if(Key >= KEY_MACRO_BASE && Key <= KEY_MACRO_ENDBASE) + // return KeyMacroToText(Key0, strKeyText0); + + if (Key&KEY_ALTDIGIT) + strKeyText.Format(L"Alt%05d", Key&FKey); + else + { + GetShiftKeyName(strKeyText,Key,Len); + + for (I=0; I<int(ARRAYSIZE(FKeys1)); I++) + { + if (FKey==FKeys1[I].Key) + { + strKeyText += FKeys1[I].Name; + break; + } + } + + if (I == ARRAYSIZE(FKeys1)) + { + if (FKey >= KEY_VK_0xFF_BEGIN && FKey <= KEY_VK_0xFF_END) + { + strKeyTemp.Format(L"Spec%05d",FKey-KEY_VK_0xFF_BEGIN); + strKeyText += strKeyTemp; + } + else if (FKey > KEY_LAUNCH_APP2 && FKey < KEY_CTRLALTSHIFTPRESS) + { + strKeyTemp.Format(L"Oem%05d",FKey-KEY_FKEY_BEGIN); + strKeyText += strKeyTemp; + } + else + { +#if defined(SYSLOG) + + // Этот кусок кода нужен только для того, что "спецклавиши" логировались нормально + for (I=0; I<ARRAYSIZE(SpecKeyName); I++) + if (FKey==SpecKeyName[I].Key) + { + strKeyText += SpecKeyName[I].Name; + break; + } + + if (I == ARRAYSIZE(SpecKeyName)) +#endif + { + FKey=Upper((wchar_t)Key&0xFFFF); + + wchar_t KeyText[2]={0}; + + if (FKey >= L'A' && FKey <= L'Z') + { + if (Key&(KEY_RCTRL|KEY_CTRL|KEY_ALT|KEY_RALT)) // ??? а если есть другие модификаторы ??? + KeyText[0]=(wchar_t)FKey; // для клавиш с модификаторами подставляем "латиницу" в верхнем регистре + else + KeyText[0]=(wchar_t)(Key&0xFFFF); + } + else + KeyText[0]=(wchar_t)Key&0xFFFF; + + strKeyText += KeyText; + } + } + } + + if (strKeyText.IsEmpty()) + { + strKeyText0.Clear(); + return FALSE; + } + } + + strKeyText0 = strKeyText; + return TRUE; +} + + +int TranslateKeyToVK(int Key,int &VirtKey,int &ControlState,INPUT_RECORD *Rec) +{ + int FKey =Key&0x0003FFFF; + int FShift=Key&0x7F000000; // старший бит используется в других целях! + VirtKey=0; + ControlState=(FShift&KEY_SHIFT?PKF_SHIFT:0)| + (FShift&KEY_ALT?PKF_ALT:0)| + (FShift&KEY_CTRL?PKF_CONTROL:0); + + bool KeyInTable=false; + for (size_t i=0; i < ARRAYSIZE(Table_KeyToVK); i++) + { + if (FKey==Table_KeyToVK[i].Key) + { + VirtKey=Table_KeyToVK[i].VK; + KeyInTable=true; + break; + } + } + + if (!KeyInTable) + { + if ((FKey>='0' && FKey<='9') || (FKey>='A' && FKey<='Z')) + VirtKey=FKey; + else if ((unsigned int)FKey > KEY_FKEY_BEGIN && (unsigned int)FKey < KEY_END_FKEY) + VirtKey=FKey-KEY_FKEY_BEGIN; + else if (FKey < MAX_VKEY_CODE) + VirtKey=WINPORT(VkKeyScan)(FKey); + else + VirtKey=FKey; + } + + if (Rec && VirtKey) + { + Rec->EventType=KEY_EVENT; + Rec->Event.KeyEvent.bKeyDown=1; + Rec->Event.KeyEvent.wRepeatCount=1; + Rec->Event.KeyEvent.wVirtualKeyCode=VirtKey; + Rec->Event.KeyEvent.wVirtualScanCode = WINPORT(MapVirtualKey)(Rec->Event.KeyEvent.wVirtualKeyCode,MAPVK_VK_TO_VSC); + + Rec->Event.KeyEvent.uChar.UnicodeChar=Key>MAX_VKEY_CODE?0:Key; + + // здесь подход к Shift-клавишам другой, нежели для ControlState + Rec->Event.KeyEvent.dwControlKeyState= + (FShift&KEY_SHIFT?SHIFT_PRESSED:0)| + (FShift&KEY_ALT?LEFT_ALT_PRESSED:0)| + (FShift&KEY_CTRL?LEFT_CTRL_PRESSED:0)| + (FShift&KEY_RALT?RIGHT_ALT_PRESSED:0)| + (FShift&KEY_RCTRL?RIGHT_CTRL_PRESSED:0); + } + + return VirtKey; +} + + +int IsNavKey(DWORD Key) +{ + static DWORD NavKeys[][2]= + { + {0,KEY_CTRLC}, + {0,KEY_INS}, {0,KEY_NUMPAD0}, + {0,KEY_CTRLINS}, {0,KEY_CTRLNUMPAD0}, + + {1,KEY_LEFT}, {1,KEY_NUMPAD4}, + {1,KEY_RIGHT}, {1,KEY_NUMPAD6}, + {1,KEY_HOME}, {1,KEY_NUMPAD7}, + {1,KEY_END}, {1,KEY_NUMPAD1}, + {1,KEY_UP}, {1,KEY_NUMPAD8}, + {1,KEY_DOWN}, {1,KEY_NUMPAD2}, + {1,KEY_PGUP}, {1,KEY_NUMPAD9}, + {1,KEY_PGDN}, {1,KEY_NUMPAD3}, + //!!!!!!!!!!! + }; + + for (int I=0; I < int(ARRAYSIZE(NavKeys)); I++) + if ((!NavKeys[I][0] && Key==NavKeys[I][1]) || + (NavKeys[I][0] && (Key&0x00FFFFFF)==(NavKeys[I][1]&0x00FFFFFF))) + return TRUE; + + return FALSE; +} + +int IsShiftKey(DWORD Key) +{ + static DWORD ShiftKeys[]= + { + KEY_SHIFTLEFT, KEY_SHIFTNUMPAD4, + KEY_SHIFTRIGHT, KEY_SHIFTNUMPAD6, + KEY_SHIFTHOME, KEY_SHIFTNUMPAD7, + KEY_SHIFTEND, KEY_SHIFTNUMPAD1, + KEY_SHIFTUP, KEY_SHIFTNUMPAD8, + KEY_SHIFTDOWN, KEY_SHIFTNUMPAD2, + KEY_SHIFTPGUP, KEY_SHIFTNUMPAD9, + KEY_SHIFTPGDN, KEY_SHIFTNUMPAD3, + KEY_CTRLSHIFTHOME, KEY_CTRLSHIFTNUMPAD7, + KEY_CTRLSHIFTPGUP, KEY_CTRLSHIFTNUMPAD9, + KEY_CTRLSHIFTEND, KEY_CTRLSHIFTNUMPAD1, + KEY_CTRLSHIFTPGDN, KEY_CTRLSHIFTNUMPAD3, + KEY_CTRLSHIFTLEFT, KEY_CTRLSHIFTNUMPAD4, + KEY_CTRLSHIFTRIGHT, KEY_CTRLSHIFTNUMPAD6, + KEY_ALTSHIFTDOWN, KEY_ALTSHIFTNUMPAD2, + KEY_ALTSHIFTLEFT, KEY_ALTSHIFTNUMPAD4, + KEY_ALTSHIFTRIGHT, KEY_ALTSHIFTNUMPAD6, + KEY_ALTSHIFTUP, KEY_ALTSHIFTNUMPAD8, + KEY_ALTSHIFTEND, KEY_ALTSHIFTNUMPAD1, + KEY_ALTSHIFTHOME, KEY_ALTSHIFTNUMPAD7, + KEY_ALTSHIFTPGDN, KEY_ALTSHIFTNUMPAD3, + KEY_ALTSHIFTPGUP, KEY_ALTSHIFTNUMPAD9, + KEY_CTRLALTPGUP, KEY_CTRLALTNUMPAD9, + KEY_CTRLALTHOME, KEY_CTRLALTNUMPAD7, + KEY_CTRLALTPGDN, KEY_CTRLALTNUMPAD2, + KEY_CTRLALTEND, KEY_CTRLALTNUMPAD1, + KEY_CTRLALTLEFT, KEY_CTRLALTNUMPAD4, + KEY_CTRLALTRIGHT, KEY_CTRLALTNUMPAD6, + KEY_ALTUP, + KEY_ALTLEFT, + KEY_ALTDOWN, + KEY_ALTRIGHT, + KEY_ALTHOME, + KEY_ALTEND, + KEY_ALTPGUP, + KEY_ALTPGDN, + KEY_ALT, + KEY_CTRL, + }; + + for (int I=0; I<int(ARRAYSIZE(ShiftKeys)); I++) + if (Key==ShiftKeys[I]) + return TRUE; + + return FALSE; +} + + +// GetAsyncKeyState(VK_RSHIFT) +DWORD CalcKeyCode(INPUT_RECORD *rec,int RealKey,int *NotMacros) +{ + _SVS(CleverSysLog Clev(L"CalcKeyCode")); + _SVS(SysLog(L"CalcKeyCode -> %ls| RealKey=%d *NotMacros=%d",_INPUT_RECORD_Dump(rec),RealKey,(NotMacros?*NotMacros:0))); + UINT CtrlState=rec->Event.KeyEvent.dwControlKeyState; + UINT ScanCode=rec->Event.KeyEvent.wVirtualScanCode; + UINT KeyCode=rec->Event.KeyEvent.wVirtualKeyCode; + WCHAR Char=rec->Event.KeyEvent.uChar.UnicodeChar; + //// // _SVS(if(KeyCode == VK_DECIMAL || KeyCode == VK_DELETE) SysLog(L"CalcKeyCode -> CtrlState=%04X KeyCode=%ls ScanCode=%08X AsciiChar=%02X ShiftPressed=%d ShiftPressedLast=%d",CtrlState,_VK_KEY_ToName(KeyCode), ScanCode, Char.AsciiChar,ShiftPressed,ShiftPressedLast)); + + if (NotMacros) + *NotMacros=CtrlState&0x80000000?TRUE:FALSE; + +// CtrlState&=~0x80000000; + + if (!(rec->EventType==KEY_EVENT || rec->EventType == FARMACRO_KEY_EVENT)) + return(KEY_NONE); + + if (!RealKey) + { + CtrlPressed=(CtrlState & (LEFT_CTRL_PRESSED|RIGHT_CTRL_PRESSED)); + AltPressed=(CtrlState & (LEFT_ALT_PRESSED|RIGHT_ALT_PRESSED)); + ShiftPressed=(CtrlState & SHIFT_PRESSED); + RightCtrlPressed=(CtrlState & RIGHT_CTRL_PRESSED); + RightAltPressed=(CtrlState & RIGHT_ALT_PRESSED); + RightShiftPressed=(CtrlState & SHIFT_PRESSED); + } + + DWORD Modif=(CtrlPressed?KEY_CTRL:0)|(AltPressed?KEY_ALT:0)|(ShiftPressed?KEY_SHIFT:0); + + if (rec->Event.KeyEvent.wVirtualKeyCode >= 0xFF && RealKey) + { + //VK_?=0x00FF, Scan=0x0013 uChar=[U=' ' (0x0000): A=' ' (0x00)] Ctrl=0x00000120 (casac - EcNs) + //VK_?=0x00FF, Scan=0x0014 uChar=[U=' ' (0x0000): A=' ' (0x00)] Ctrl=0x00000120 (casac - EcNs) + //VK_?=0x00FF, Scan=0x0015 uChar=[U=' ' (0x0000): A=' ' (0x00)] Ctrl=0x00000120 (casac - EcNs) + //VK_?=0x00FF, Scan=0x001A uChar=[U=' ' (0x0000): A=' ' (0x00)] Ctrl=0x00000120 (casac - EcNs) + //VK_?=0x00FF, Scan=0x001B uChar=[U=' ' (0x0000): A=' ' (0x00)] Ctrl=0x00000120 (casac - EcNs) + //VK_?=0x00FF, Scan=0x001E uChar=[U=' ' (0x0000): A=' ' (0x00)] Ctrl=0x00000120 (casac - EcNs) + //VK_?=0x00FF, Scan=0x001F uChar=[U=' ' (0x0000): A=' ' (0x00)] Ctrl=0x00000120 (casac - EcNs) + //VK_?=0x00FF, Scan=0x0023 uChar=[U=' ' (0x0000): A=' ' (0x00)] Ctrl=0x00000120 (casac - EcNs) + if (!rec->Event.KeyEvent.bKeyDown && (CtrlState&(ENHANCED_KEY|NUMLOCK_ON))) + return Modif|(KEY_VK_0xFF_BEGIN+ScanCode); + + return KEY_IDLE; + } + + static DWORD Time=0; + + if (!AltValue) + { + Time=WINPORT(GetTickCount)(); + } + + if (!rec->Event.KeyEvent.bKeyDown) + { + KeyCodeForALT_LastPressed=0; + + if (KeyCode==VK_MENU && AltValue) + { + //FlushInputBuffer();//??? + INPUT_RECORD TempRec; + Console.ReadInput(TempRec); + ReturnAltValue=TRUE; + //_SVS(SysLog(L"0 AltNumPad -> AltValue=0x%0X CtrlState=%X",AltValue,CtrlState)); + AltValue&=0xFFFF; + /* + О перетаскивании из проводника / вставке текста в консоль, на примере буквы 'ы': + + 1. Нажимается Alt: + bKeyDown=TRUE, wRepeatCount=1, wVirtualKeyCode=VK_MENU, UnicodeChar=0, dwControlKeyState=LEFT_ALT_PRESSED + + 2. Через numpad-клавиши вводится код символа в OEM, если он туда мапится, или 63 ('?'), если не мапится: + bKeyDown=TRUE, wRepeatCount=1, wVirtualKeyCode=VK_NUMPAD2, UnicodeChar=0, dwControlKeyState=LEFT_ALT_PRESSED + bKeyDown=FALSE, wRepeatCount=1, wVirtualKeyCode=VK_NUMPAD2, UnicodeChar=0, dwControlKeyState=LEFT_ALT_PRESSED + bKeyDown=TRUE, wRepeatCount=1, wVirtualKeyCode=VK_NUMPAD3, UnicodeChar=0, dwControlKeyState=LEFT_ALT_PRESSED + bKeyDown=FALSE, wRepeatCount=1, wVirtualKeyCode=VK_NUMPAD3, UnicodeChar=0, dwControlKeyState=LEFT_ALT_PRESSED + bKeyDown=TRUE, wRepeatCount=1, wVirtualKeyCode=VK_NUMPAD5, UnicodeChar=0, dwControlKeyState=LEFT_ALT_PRESSED + bKeyDown=FALSE, wRepeatCount=1, wVirtualKeyCode=VK_NUMPAD5, UnicodeChar=0, dwControlKeyState=LEFT_ALT_PRESSED + + 3. Отжимается Alt, при этом в uChar.UnicodeChar лежит исходный символ: + bKeyDown=FALSE, wRepeatCount=1, wVirtualKeyCode=VK_MENU, UnicodeChar=1099, dwControlKeyState=0 + + Мораль сей басни такова: если rec->Event.KeyEvent.uChar.UnicodeChar не пуст - берём его, а не то, что во время удерживания Alt пришло. + */ + + if (rec->Event.KeyEvent.uChar.UnicodeChar) + { + // BUGBUG: в Windows 7 Event.KeyEvent.uChar.UnicodeChar _всегда_ заполнен, но далеко не всегда тем, чем надо. + // условно считаем, что если интервал между нажатиями не превышает 50 мс, то это сгенерированная при D&D или вставке комбинация, + // иначе - ручной ввод. + if (WINPORT(GetTickCount)()-Time<50) + { + AltValue=rec->Event.KeyEvent.uChar.UnicodeChar; + } + } + else + { + rec->Event.KeyEvent.uChar.UnicodeChar=static_cast<WCHAR>(AltValue); + } + + //// // _SVS(SysLog(L"KeyCode==VK_MENU -> AltValue=%X (%c)",AltValue,AltValue)); + return(AltValue); + } + else + return(KEY_NONE); + } + + if ((CtrlState & 9)==9) + { + if (Char) + return Char; + else + CtrlPressed=0; + } + + if (KeyCode==VK_MENU) + AltValue=0; + + if (Char && !CtrlPressed && !AltPressed) + { + if (KeyCode==VK_OEM_3 && !Opt.UseVk_oem_x) + return(ShiftPressed ? '~':'`'); + + if (KeyCode==VK_OEM_7 && !Opt.UseVk_oem_x) + return(ShiftPressed ? '"':'\''); + } + + if (Char<L' ' && (CtrlPressed || AltPressed)) + { + switch (KeyCode) + { + case VK_OEM_COMMA: + Char=L','; + break; + case VK_OEM_PERIOD: + Char=L'.'; + break; + case VK_OEM_4: + + if (!Opt.UseVk_oem_x) + Char=L'['; + + break; + case VK_OEM_5: + + //Char.AsciiChar=ScanCode==0x29?0x15:'\\'; //??? + if (!Opt.UseVk_oem_x) + Char=L'\\'; + + break; + case VK_OEM_6: + + if (!Opt.UseVk_oem_x) + Char=L']'; + + break; + case VK_OEM_7: + + if (!Opt.UseVk_oem_x) + Char=L'\"'; + + break; + } + } + + /* $ 24.08.2000 SVS + "Персональные 100 грамм" :-) + */ + if (CtrlPressed && AltPressed && ShiftPressed) + { + switch (KeyCode) + { + case VK_SHIFT: + case VK_MENU: + case VK_CONTROL: + { + if (RightCtrlPressed && RightAltPressed && RightShiftPressed) + { + if ((Opt.CASRule&2)) + return (IsKeyRCASPressed?KEY_RCTRLALTSHIFTPRESS:KEY_RCTRLALTSHIFTRELEASE); + } + else if (Opt.CASRule&1) + return (IsKeyCASPressed?KEY_CTRLALTSHIFTPRESS:KEY_CTRLALTSHIFTRELEASE); + } + } + } + + if (RightCtrlPressed && RightAltPressed && RightShiftPressed) + { + switch (KeyCode) + { + case VK_RSHIFT: + case VK_RMENU: + case VK_RCONTROL: + + if (Opt.CASRule&2) + return (IsKeyRCASPressed?KEY_RCTRLALTSHIFTPRESS:KEY_RCTRLALTSHIFTRELEASE); + + break; + } + } + + if (KeyCode>=VK_F1 && KeyCode<=VK_F24) +// return(Modif+KEY_F1+((KeyCode-VK_F1)<<8)); + return(Modif+KEY_F1+((KeyCode-VK_F1))); + + int NotShift=!CtrlPressed && !AltPressed && !ShiftPressed; + + if (AltPressed && !CtrlPressed && !ShiftPressed) + { +#if 0 + + if (!AltValue && (CtrlObject->Macro.IsRecording() == MACROMODE_NOMACRO || !Opt.UseNumPad)) + { + // VK_INSERT = 0x2D AS-0 = 0x2D + // VK_NUMPAD0 = 0x60 A-0 = 0x60 + /* + С грабером не все понятно - что, где и когда вызывать, + посему его оставим пока в покое. + */ + if (//(CtrlState&NUMLOCK_ON) && KeyCode==VK_NUMPAD0 && !(CtrlState&ENHANCED_KEY) || + (Opt.UseNumPad && KeyCode==VK_INSERT && (CtrlState&ENHANCED_KEY)) || + (!Opt.UseNumPad && (KeyCode==VK_INSERT || KeyCode==VK_NUMPAD0)) + ) + { // CtrlObject->Macro.IsRecording() + //// // _SVS(SysLog(L"IsProcessAssignMacroKey=%d",IsProcessAssignMacroKey)); + if (IsProcessAssignMacroKey && Opt.UseNumPad) + { + return KEY_INS|KEY_ALT; + } + else + { + RunGraber(); + } + + return(KEY_NONE); + } + } + +#else + + if (!AltValue) + { + if (KeyCode==VK_INSERT || KeyCode==VK_NUMPAD0) + { + if (CtrlObject && CtrlObject->Macro.IsRecording()) + { + _KEYMACRO(SysLog(L"[%d] CALL CtrlObject->Macro.ProcessKey(KEY_INS|KEY_ALT)",__LINE__)); + CtrlObject->Macro.ProcessKey(KEY_INS|KEY_ALT); + } + + // макрос проигрывается и мы "сейчас" в состоянии выполнения функции waitkey? (Mantis#0000968: waitkey() пропускает AltIns) + if (CtrlObject->Macro.IsExecuting() && CtrlObject->Macro.CheckWaitKeyFunc()) + return KEY_INS|KEY_ALT; + + RunGraber(); + return(KEY_NONE); + } + } + +#endif + + //// // _SVS(SysLog(L"1 AltNumPad -> CalcKeyCode -> KeyCode=%ls ScanCode=0x%0X AltValue=0x%0X CtrlState=%X GetAsyncKeyState(VK_SHIFT)=%X",_VK_KEY_ToName(KeyCode),ScanCode,AltValue,CtrlState,GetAsyncKeyState(VK_SHIFT))); + if (!(CtrlState & ENHANCED_KEY) + //(CtrlState&NUMLOCK_ON) && KeyCode >= VK_NUMPAD0 && KeyCode <= VK_NUMPAD9 || + // !(CtrlState&NUMLOCK_ON) && KeyCode < VK_NUMPAD0 + ) + { + //// // _SVS(SysLog(L"2 AltNumPad -> CalcKeyCode -> KeyCode=%ls ScanCode=0x%0X AltValue=0x%0X CtrlState=%X GetAsyncKeyState(VK_SHIFT)=%X",_VK_KEY_ToName(KeyCode),ScanCode,AltValue,CtrlState,GetAsyncKeyState(VK_SHIFT))); + static unsigned int ScanCodes[]={82,79,80,81,75,76,77,71,72,73}; + + for (int I=0; I<int(ARRAYSIZE(ScanCodes)); I++) + { + if (ScanCodes[I]==ScanCode) + { + if (RealKey && (unsigned int)KeyCodeForALT_LastPressed != KeyCode) + { + AltValue=AltValue*10+I; + KeyCodeForALT_LastPressed=KeyCode; + } + +// _SVS(SysLog(L"AltNumPad -> AltValue=0x%0X CtrlState=%X",AltValue,CtrlState)); + if (AltValue) + return(KEY_NONE); + } + } + } + } + + /* + NumLock=Off + Down + CtrlState=0100 KeyCode=0028 ScanCode=00000050 AsciiChar=00 ENHANCED_KEY + CtrlState=0100 KeyCode=0028 ScanCode=00000050 AsciiChar=00 + Num2 + CtrlState=0000 KeyCode=0028 ScanCode=00000050 AsciiChar=00 + CtrlState=0000 KeyCode=0028 ScanCode=00000050 AsciiChar=00 + + Ctrl-8 + CtrlState=0008 KeyCode=0026 ScanCode=00000048 AsciiChar=00 + Ctrl-Shift-8 ^^!!! + CtrlState=0018 KeyCode=0026 ScanCode=00000048 AsciiChar=00 + + ------------------------------------------------------------------------ + NumLock=On + + Down + CtrlState=0120 KeyCode=0028 ScanCode=00000050 AsciiChar=00 ENHANCED_KEY + CtrlState=0120 KeyCode=0028 ScanCode=00000050 AsciiChar=00 + Num2 + CtrlState=0020 KeyCode=0062 ScanCode=00000050 AsciiChar=32 + CtrlState=0020 KeyCode=0062 ScanCode=00000050 AsciiChar=32 + + Ctrl-8 + CtrlState=0028 KeyCode=0068 ScanCode=00000048 AsciiChar=00 + Ctrl-Shift-8 ^^!!! + CtrlState=0028 KeyCode=0026 ScanCode=00000048 AsciiChar=00 + */ + + /* ------------------------------------------------------------- */ + switch (KeyCode) + { + case VK_INSERT: + case VK_NUMPAD0: + + if (CtrlState&ENHANCED_KEY) + { + return(Modif|KEY_INS); + } + else if ((CtrlState&NUMLOCK_ON) && NotShift && KeyCode == VK_NUMPAD0) + return '0'; + + return Modif|(Opt.UseNumPad?KEY_NUMPAD0:KEY_INS); + case VK_DOWN: + case VK_NUMPAD2: + + if (CtrlState&ENHANCED_KEY) + { + return(Modif|KEY_DOWN); + } + else if ((CtrlState&NUMLOCK_ON) && NotShift && KeyCode == VK_NUMPAD2) + return '2'; + + return Modif|(Opt.UseNumPad?KEY_NUMPAD2:KEY_DOWN); + case VK_LEFT: + case VK_NUMPAD4: + + if (CtrlState&ENHANCED_KEY) + { + return(Modif|KEY_LEFT); + } + else if ((CtrlState&NUMLOCK_ON) && NotShift && KeyCode == VK_NUMPAD4) + return '4'; + + return Modif|(Opt.UseNumPad?KEY_NUMPAD4:KEY_LEFT); + case VK_RIGHT: + case VK_NUMPAD6: + + if (CtrlState&ENHANCED_KEY) + { + return(Modif|KEY_RIGHT); + } + else if ((CtrlState&NUMLOCK_ON) && NotShift && KeyCode == VK_NUMPAD6) + return '6'; + + return Modif|(Opt.UseNumPad?KEY_NUMPAD6:KEY_RIGHT); + case VK_UP: + case VK_NUMPAD8: + + if (CtrlState&ENHANCED_KEY) + { + return(Modif|KEY_UP); + } + else if ((CtrlState&NUMLOCK_ON) && NotShift && KeyCode == VK_NUMPAD8) + return '8'; + + return Modif|(Opt.UseNumPad?KEY_NUMPAD8:KEY_UP); + case VK_END: + case VK_NUMPAD1: + + if (CtrlState&ENHANCED_KEY) + { + return(Modif|KEY_END); + } + else if ((CtrlState&NUMLOCK_ON) && NotShift && KeyCode == VK_NUMPAD1) + return '1'; + + return Modif|(Opt.UseNumPad?KEY_NUMPAD1:KEY_END); + case VK_HOME: + case VK_NUMPAD7: + + if (CtrlState&ENHANCED_KEY) + { + return(Modif|KEY_HOME); + } + else if ((CtrlState&NUMLOCK_ON) && NotShift && KeyCode == VK_NUMPAD7) + return '7'; + + return Modif|(Opt.UseNumPad?KEY_NUMPAD7:KEY_HOME); + case VK_NEXT: + case VK_NUMPAD3: + + if (CtrlState&ENHANCED_KEY) + { + return(Modif|KEY_PGDN); + } + else if ((CtrlState&NUMLOCK_ON) && NotShift && KeyCode == VK_NUMPAD3) + return '3'; + + return Modif|(Opt.UseNumPad?KEY_NUMPAD3:KEY_PGDN); + case VK_PRIOR: + case VK_NUMPAD9: + + if (CtrlState&ENHANCED_KEY) + { + return(Modif|KEY_PGUP); + } + else if ((CtrlState&NUMLOCK_ON) && NotShift && KeyCode == VK_NUMPAD9) + return '9'; + + return Modif|(Opt.UseNumPad?KEY_NUMPAD9:KEY_PGUP); + case VK_CLEAR: + case VK_NUMPAD5: + + if (CtrlState&ENHANCED_KEY) + { + return(Modif|KEY_NUMPAD5); + } + else if ((CtrlState&NUMLOCK_ON) && NotShift && KeyCode == VK_NUMPAD5) + return '5'; + + return Modif|KEY_NUMPAD5; + case VK_DELETE: + case VK_DECIMAL: + + if (CtrlState&ENHANCED_KEY) + { + return (Modif|KEY_DEL); + } + else if ((CtrlState&NUMLOCK_ON) && NotShift && KeyCode == VK_DECIMAL) + return KEY_DECIMAL; + + return Modif|(Opt.UseNumPad?KEY_NUMDEL:KEY_DEL); + } + + switch (KeyCode) + { + case VK_RETURN: + // !!!!!!!!!!!!! - Если "!ShiftPressed", то Shift-F4 Shift-Enter, не + // отпуская Shift... +//_SVS(SysLog(L"ShiftPressed=%d RealKey=%d !ShiftPressedLast=%d !CtrlPressed=%d !AltPressed=%d (%d)",ShiftPressed,RealKey,ShiftPressedLast,CtrlPressed,AltPressed,(ShiftPressed && RealKey && !ShiftPressedLast && !CtrlPressed && !AltPressed))); +#if 0 + + if (ShiftPressed && RealKey && !ShiftPressedLast && !CtrlPressed && !AltPressed && !LastShiftEnterPressed) + return(KEY_ENTER); + + LastShiftEnterPressed=Modif&KEY_SHIFT?TRUE:FALSE; + return(Modif|KEY_ENTER); +#else + + if (ShiftPressed && RealKey && !ShiftPressedLast && !CtrlPressed && !AltPressed && !LastShiftEnterPressed) + return(Opt.UseNumPad && (CtrlState&ENHANCED_KEY)?KEY_NUMENTER:KEY_ENTER); + + LastShiftEnterPressed=Modif&KEY_SHIFT?TRUE:FALSE; + return(Modif|(Opt.UseNumPad && (CtrlState&ENHANCED_KEY)?KEY_NUMENTER:KEY_ENTER)); +#endif + case VK_BROWSER_BACK: + return Modif|KEY_BROWSER_BACK; + case VK_BROWSER_FORWARD: + return Modif|KEY_BROWSER_FORWARD; + case VK_BROWSER_REFRESH: + return Modif|KEY_BROWSER_REFRESH; + case VK_BROWSER_STOP: + return Modif|KEY_BROWSER_STOP; + case VK_BROWSER_SEARCH: + return Modif|KEY_BROWSER_SEARCH; + case VK_BROWSER_FAVORITES: + return Modif|KEY_BROWSER_FAVORITES; + case VK_BROWSER_HOME: + return Modif|KEY_BROWSER_HOME; + case VK_VOLUME_MUTE: + return Modif|KEY_VOLUME_MUTE; + case VK_VOLUME_DOWN: + return Modif|KEY_VOLUME_DOWN; + case VK_VOLUME_UP: + return Modif|KEY_VOLUME_UP; + case VK_MEDIA_NEXT_TRACK: + return Modif|KEY_MEDIA_NEXT_TRACK; + case VK_MEDIA_PREV_TRACK: + return Modif|KEY_MEDIA_PREV_TRACK; + case VK_MEDIA_STOP: + return Modif|KEY_MEDIA_STOP; + case VK_MEDIA_PLAY_PAUSE: + return Modif|KEY_MEDIA_PLAY_PAUSE; + case VK_LAUNCH_MAIL: + return Modif|KEY_LAUNCH_MAIL; + case VK_LAUNCH_MEDIA_SELECT: + return Modif|KEY_LAUNCH_MEDIA_SELECT; + case VK_LAUNCH_APP1: + return Modif|KEY_LAUNCH_APP1; + case VK_LAUNCH_APP2: + return Modif|KEY_LAUNCH_APP2; + case VK_APPS: + return(Modif|KEY_APPS); + case VK_LWIN: + return(Modif|KEY_LWIN); + case VK_RWIN: + return(Modif|KEY_RWIN); + case VK_BACK: + return(Modif|KEY_BS); + case VK_SPACE: + + if (Char == L' ' || !Char) + return(Modif|KEY_SPACE); + + return Char; + case VK_TAB: + return(Modif|KEY_TAB); + case VK_ADD: + return(Modif|KEY_ADD); + case VK_SUBTRACT: + return(Modif|KEY_SUBTRACT); + case VK_ESCAPE: + return(Modif|KEY_ESC); + } + + switch (KeyCode) + { + case VK_CAPITAL: + return(Modif|KEY_CAPSLOCK); + case VK_NUMLOCK: + return(Modif|KEY_NUMLOCK); + case VK_SCROLL: + return(Modif|KEY_SCROLLLOCK); + } + + /* ------------------------------------------------------------- */ + if (CtrlPressed && AltPressed && ShiftPressed) + { + + _SVS(if (KeyCode!=VK_CONTROL && KeyCode!=VK_MENU) SysLog(L"CtrlAltShift -> |%ls|%ls|",_VK_KEY_ToName(KeyCode),_INPUT_RECORD_Dump(rec))); + + if (KeyCode>='A' && KeyCode<='Z') + return((KEY_SHIFT|KEY_CTRL|KEY_ALT)+KeyCode); + + if (Opt.ShiftsKeyRules) //??? + switch (KeyCode) + { + case VK_OEM_3: + return(KEY_SHIFT+KEY_CTRL+KEY_ALT+'`'); + case VK_OEM_MINUS: + return(KEY_SHIFT+KEY_CTRL+KEY_ALT+'-'); + case VK_OEM_PLUS: + return(KEY_SHIFT+KEY_CTRL+KEY_ALT+'='); + case VK_OEM_5: + return(KEY_SHIFT+KEY_CTRL+KEY_ALT+KEY_BACKSLASH); + case VK_OEM_6: + return(KEY_SHIFT+KEY_CTRL+KEY_ALT+KEY_BACKBRACKET); + case VK_OEM_4: + return(KEY_SHIFT+KEY_CTRL+KEY_ALT+KEY_BRACKET); + case VK_OEM_7: + return(KEY_SHIFT+KEY_CTRL+KEY_ALT+'\''); + case VK_OEM_1: + return(KEY_SHIFT+KEY_CTRL+KEY_ALT+KEY_SEMICOLON); + case VK_OEM_2: + return(KEY_SHIFT+KEY_CTRL+KEY_ALT+KEY_SLASH); + case VK_OEM_PERIOD: + return(KEY_SHIFT+KEY_CTRL+KEY_ALT+KEY_DOT); + case VK_OEM_COMMA: + return(KEY_SHIFT+KEY_CTRL+KEY_ALT+KEY_COMMA); + case VK_OEM_102: // <> \| + return KEY_SHIFT+KEY_CTRL+KEY_ALT+KEY_BACKSLASH; + } + + switch (KeyCode) + { + case VK_DIVIDE: + return(KEY_SHIFT|KEY_CTRLALT|KEY_DIVIDE); + case VK_MULTIPLY: + return(KEY_SHIFT|KEY_CTRLALT|KEY_MULTIPLY); + case VK_CANCEL: + return(KEY_SHIFT|KEY_CTRLALT|KEY_PAUSE); + case VK_SLEEP: + return KEY_SHIFT|KEY_CTRLALT|KEY_STANDBY; + case VK_SNAPSHOT: + return KEY_SHIFT|KEY_CTRLALT|KEY_PRNTSCRN; + } + + if (Char) + return KEY_SHIFT|KEY_CTRL|KEY_ALT|Char; + + if (!RealKey && (KeyCode==VK_CONTROL || KeyCode==VK_MENU)) + return(KEY_NONE); + + if (KeyCode) + return((KEY_SHIFT|KEY_CTRL|KEY_ALT)+KeyCode); + } + + /* ------------------------------------------------------------- */ + if (CtrlPressed && AltPressed) + { + + _SVS(if (KeyCode!=VK_CONTROL && KeyCode!=VK_MENU) SysLog(L"CtrlAlt -> |%ls|%ls|",_VK_KEY_ToName(KeyCode),_INPUT_RECORD_Dump(rec))); + + if (KeyCode>='A' && KeyCode<='Z') + return((KEY_CTRL|KEY_ALT)+KeyCode); + + if (Opt.ShiftsKeyRules) //??? + switch (KeyCode) + { + case VK_OEM_3: + return(KEY_CTRL+KEY_ALT+'`'); + case VK_OEM_MINUS: + return(KEY_CTRL+KEY_ALT+'-'); + case VK_OEM_PLUS: + return(KEY_CTRL+KEY_ALT+'='); + case VK_OEM_5: + return(KEY_CTRL+KEY_ALT+KEY_BACKSLASH); + case VK_OEM_6: + return(KEY_CTRL+KEY_ALT+KEY_BACKBRACKET); + case VK_OEM_4: + return(KEY_CTRL+KEY_ALT+KEY_BRACKET); + case VK_OEM_7: + return(KEY_CTRL+KEY_ALT+'\''); + case VK_OEM_1: + return(KEY_CTRL+KEY_ALT+KEY_SEMICOLON); + case VK_OEM_2: + return(KEY_CTRL+KEY_ALT+KEY_SLASH); + case VK_OEM_PERIOD: + return(KEY_CTRL+KEY_ALT+KEY_DOT); + case VK_OEM_COMMA: + return(KEY_CTRL+KEY_ALT+KEY_COMMA); + case VK_OEM_102: // <> \| + return KEY_CTRL+KEY_ALT+KEY_BACKSLASH; + } + + switch (KeyCode) + { + case VK_DIVIDE: + return(KEY_CTRLALT|KEY_DIVIDE); + case VK_MULTIPLY: + return(KEY_CTRLALT|KEY_MULTIPLY); + // KEY_EVENT_RECORD: Dn, 1, Vk="VK_CANCEL" [3/0x0003], Scan=0x0046 uChar=[U=' ' (0x0000): A=' ' (0x00)] Ctrl=0x0000014A (CAsac - EcnS) + //case VK_PAUSE: + case VK_CANCEL: // Ctrl-Alt-Pause + + if (!ShiftPressed && (CtrlState&ENHANCED_KEY)) + return KEY_CTRLALT|KEY_PAUSE; + + return KEY_NONE; + case VK_SLEEP: + return KEY_CTRLALT|KEY_STANDBY; + case VK_SNAPSHOT: + return KEY_CTRLALT|KEY_PRNTSCRN; + } + + if (Char) + return KEY_CTRL|KEY_ALT|Char; + + if (!RealKey && (KeyCode==VK_CONTROL || KeyCode==VK_MENU)) + return(KEY_NONE); + + if (KeyCode) + return((KEY_CTRL|KEY_ALT)+KeyCode); + } + + /* ------------------------------------------------------------- */ + if (AltPressed && ShiftPressed) + { + + _SVS(if (KeyCode!=VK_MENU && KeyCode!=VK_SHIFT) SysLog(L"AltShift -> |%ls|%ls|",_VK_KEY_ToName(KeyCode),_INPUT_RECORD_Dump(rec))); + + if (KeyCode>='0' && KeyCode<='9') + { + if (WaitInFastFind > 0 && + CtrlObject->Macro.GetCurRecord(nullptr,nullptr) < MACROMODE_RECORDING && + CtrlObject->Macro.GetIndex(KEY_ALTSHIFT0+KeyCode-'0',-1) == -1) + { + return KEY_ALT|KEY_SHIFT|Char; + } + else + return(KEY_ALTSHIFT0+KeyCode-'0'); + } + + if (!WaitInMainLoop && KeyCode>='A' && KeyCode<='Z') + return(KEY_ALTSHIFT+KeyCode); + + if (Opt.ShiftsKeyRules) //??? + switch (KeyCode) + { + case VK_OEM_3: + return(KEY_ALT+KEY_SHIFT+'`'); + case VK_OEM_MINUS: + return(KEY_ALT+KEY_SHIFT+'_'); + case VK_OEM_PLUS: + return(KEY_ALT+KEY_SHIFT+'='); + case VK_OEM_5: + return(KEY_ALT+KEY_SHIFT+KEY_BACKSLASH); + case VK_OEM_6: + return(KEY_ALT+KEY_SHIFT+KEY_BACKBRACKET); + case VK_OEM_4: + return(KEY_ALT+KEY_SHIFT+KEY_BRACKET); + case VK_OEM_7: + return(KEY_ALT+KEY_SHIFT+'\''); + case VK_OEM_1: + return(KEY_ALT+KEY_SHIFT+KEY_SEMICOLON); + case VK_OEM_2: + //if(WaitInFastFind) + // return(KEY_ALT+KEY_SHIFT+'?'); + //else + return(KEY_ALT+KEY_SHIFT+KEY_SLASH); + case VK_OEM_PERIOD: + return(KEY_ALT+KEY_SHIFT+KEY_DOT); + case VK_OEM_COMMA: + return(KEY_ALT+KEY_SHIFT+KEY_COMMA); + case VK_OEM_102: // <> \| + return KEY_ALT+KEY_SHIFT+KEY_BACKSLASH; + } + + switch (KeyCode) + { + case VK_DIVIDE: + //if(WaitInFastFind) + // return(KEY_ALT+KEY_SHIFT+'/'); + //else + return(KEY_ALTSHIFT|KEY_DIVIDE); + case VK_MULTIPLY: + //if(WaitInFastFind) + //{ + // return(KEY_ALT+KEY_SHIFT+'*'); + //} + //else + return(KEY_ALTSHIFT|KEY_MULTIPLY); + case VK_PAUSE: + return(KEY_ALTSHIFT|KEY_PAUSE); + case VK_SLEEP: + return KEY_ALTSHIFT|KEY_STANDBY; + case VK_SNAPSHOT: + return KEY_ALTSHIFT|KEY_PRNTSCRN; + } + + if (Char) + return KEY_ALT|KEY_SHIFT|Char; + + if (!RealKey && (KeyCode==VK_MENU || KeyCode==VK_SHIFT)) + return(KEY_NONE); + + if (KeyCode) + return(KEY_ALT+KEY_SHIFT+KeyCode); + } + + /* ------------------------------------------------------------- */ + if (CtrlPressed && ShiftPressed) + { + + _SVS(if (KeyCode!=VK_CONTROL && KeyCode!=VK_SHIFT) SysLog(L"CtrlShift -> |%ls|%ls|",_VK_KEY_ToName(KeyCode),_INPUT_RECORD_Dump(rec))); + + if (KeyCode>='0' && KeyCode<='9') + return(KEY_CTRLSHIFT0+KeyCode-'0'); + + if (KeyCode>='A' && KeyCode<='Z') + return(KEY_CTRLSHIFTA+KeyCode-'A'); + + switch (KeyCode) + { + case VK_OEM_PERIOD: + return(KEY_CTRLSHIFTDOT); + case VK_OEM_4: + return(KEY_CTRLSHIFTBRACKET); + case VK_OEM_6: + return(KEY_CTRLSHIFTBACKBRACKET); + case VK_OEM_2: + return(KEY_CTRLSHIFTSLASH); + case VK_OEM_5: + return(KEY_CTRLSHIFTBACKSLASH); + case VK_DIVIDE: + return(KEY_CTRLSHIFT|KEY_DIVIDE); + case VK_MULTIPLY: + return(KEY_CTRLSHIFT|KEY_MULTIPLY); + case VK_SLEEP: + return KEY_CTRLSHIFT|KEY_STANDBY; + case VK_SNAPSHOT: + return KEY_CTRLSHIFT|KEY_PRNTSCRN; + } + + if (Opt.ShiftsKeyRules) //??? + switch (KeyCode) + { + case VK_OEM_3: + return(KEY_CTRL+KEY_SHIFT+'`'); + case VK_OEM_MINUS: + return(KEY_CTRL+KEY_SHIFT+'-'); + case VK_OEM_PLUS: + return(KEY_CTRL+KEY_SHIFT+'='); + case VK_OEM_7: + return(KEY_CTRL+KEY_SHIFT+'\''); + case VK_OEM_1: + return(KEY_CTRL+KEY_SHIFT+KEY_SEMICOLON); + case VK_OEM_COMMA: + return(KEY_CTRL+KEY_SHIFT+KEY_COMMA); + case VK_OEM_102: // <> \| + return KEY_CTRL+KEY_SHIFT+KEY_BACKSLASH; + } + + if (Char) + return KEY_CTRL|KEY_SHIFT|Char; + + if (!RealKey && (KeyCode==VK_CONTROL || KeyCode==VK_SHIFT)) + return(KEY_NONE); + + if (KeyCode) + return((KEY_CTRL|KEY_SHIFT)+KeyCode); + } + + /* ------------------------------------------------------------- */ + if ((CtrlState & RIGHT_CTRL_PRESSED)==RIGHT_CTRL_PRESSED) + { + if (KeyCode>='0' && KeyCode<='9') + return(KEY_RCTRL0+KeyCode-'0'); + } + + /* ------------------------------------------------------------- */ + if (!CtrlPressed && !AltPressed && !ShiftPressed) + { + switch (KeyCode) + { + case VK_DIVIDE: + return(KEY_DIVIDE); + case VK_CANCEL: + return(KEY_BREAK); + case VK_MULTIPLY: + return(KEY_MULTIPLY); + case VK_PAUSE: + return(KEY_PAUSE); + case VK_SLEEP: + return KEY_STANDBY; + case VK_SNAPSHOT: + return KEY_PRNTSCRN; + } + } + + /* ------------------------------------------------------------- */ + if (CtrlPressed) + { + + _SVS(if (KeyCode!=VK_CONTROL) SysLog(L"Ctrl -> |%ls|%ls|",_VK_KEY_ToName(KeyCode),_INPUT_RECORD_Dump(rec))); + + if (KeyCode>='0' && KeyCode<='9') + return(KEY_CTRL0+KeyCode-'0'); + + if (KeyCode>='A' && KeyCode<='Z') + return(KEY_CTRL+KeyCode); + + switch (KeyCode) + { + case VK_OEM_COMMA: + return(KEY_CTRLCOMMA); + case VK_OEM_PERIOD: + return(KEY_CTRLDOT); + case VK_OEM_2: + return(KEY_CTRLSLASH); + case VK_OEM_4: + return(KEY_CTRLBRACKET); + case VK_OEM_5: + return(KEY_CTRLBACKSLASH); + case VK_OEM_6: + return(KEY_CTRLBACKBRACKET); + case VK_OEM_7: + return(KEY_CTRL+'\''); // KEY_QUOTE + case VK_MULTIPLY: + return(KEY_CTRL|KEY_MULTIPLY); + case VK_DIVIDE: + return(KEY_CTRL|KEY_DIVIDE); + case VK_PAUSE: + + if (CtrlState&ENHANCED_KEY) + return KEY_CTRL|KEY_NUMLOCK; + + return(KEY_BREAK); + case VK_SLEEP: + return KEY_CTRL|KEY_STANDBY; + case VK_SNAPSHOT: + return KEY_CTRL|KEY_PRNTSCRN; + case VK_OEM_102: // <> \| + return KEY_CTRL|KEY_BACKSLASH; + } + + if (Opt.ShiftsKeyRules) //??? + switch (KeyCode) + { + case VK_OEM_3: + return(KEY_CTRL+'`'); + case VK_OEM_MINUS: + return(KEY_CTRL+'-'); + case VK_OEM_PLUS: + return(KEY_CTRL+'='); + case VK_OEM_1: + return(KEY_CTRL+KEY_SEMICOLON); + } + + if (KeyCode) + { + if (!RealKey && KeyCode==VK_CONTROL) + return(KEY_NONE); + + return(KEY_CTRL+KeyCode); + } + } + + /* ------------------------------------------------------------- */ + if (AltPressed) + { + + _SVS(if (KeyCode!=VK_MENU) SysLog(L"Alt -> |%ls|%ls|",_VK_KEY_ToName(KeyCode),_INPUT_RECORD_Dump(rec))); + + if (Opt.ShiftsKeyRules) //??? + switch (KeyCode) + { + case VK_OEM_3: + return(KEY_ALT+'`'); + case VK_OEM_MINUS: + //if(WaitInFastFind) + // return(KEY_ALT+KEY_SHIFT+'_'); + //else + return(KEY_ALT+'-'); + case VK_OEM_PLUS: + return(KEY_ALT+'='); + case VK_OEM_5: + return(KEY_ALT+KEY_BACKSLASH); + case VK_OEM_6: + return(KEY_ALT+KEY_BACKBRACKET); + case VK_OEM_4: + return(KEY_ALT+KEY_BRACKET); + case VK_OEM_7: + return(KEY_ALT+'\''); + case VK_OEM_1: + return(KEY_ALT+KEY_SEMICOLON); + case VK_OEM_2: + return(KEY_ALT+KEY_SLASH); + case VK_OEM_102: // <> \| + return KEY_ALT+KEY_BACKSLASH; + } + + switch (KeyCode) + { + case VK_OEM_COMMA: + return(KEY_ALTCOMMA); + case VK_OEM_PERIOD: + return(KEY_ALTDOT); + case VK_DIVIDE: + //if(WaitInFastFind) + // return(KEY_ALT+KEY_SHIFT+'/'); + //else + return(KEY_ALT|KEY_DIVIDE); + case VK_MULTIPLY: +// if(WaitInFastFind) +// return(KEY_ALT+KEY_SHIFT+'*'); +// else + return(KEY_ALT|KEY_MULTIPLY); + case VK_PAUSE: + return(KEY_ALT+KEY_PAUSE); + case VK_SLEEP: + return KEY_ALT|KEY_STANDBY; + case VK_SNAPSHOT: + return KEY_ALT|KEY_PRNTSCRN; + } + + if (Char) + { + if (!Opt.ShiftsKeyRules || WaitInFastFind > 0) + return KEY_ALT|Upper(Char); + else if (WaitInMainLoop) + return KEY_ALT|Char; + } + + if (!RealKey && KeyCode==VK_MENU) + return(KEY_NONE); + + return(KEY_ALT+KeyCode); + } + + if (ShiftPressed) + { + + _SVS(if (KeyCode!=VK_SHIFT) SysLog(L"Shift -> |%ls|%ls|",_VK_KEY_ToName(KeyCode),_INPUT_RECORD_Dump(rec))); + + switch (KeyCode) + { + case VK_DIVIDE: + return(KEY_SHIFT|KEY_DIVIDE); + case VK_MULTIPLY: + return(KEY_SHIFT|KEY_MULTIPLY); + case VK_PAUSE: + return(KEY_SHIFT|KEY_PAUSE); + case VK_SLEEP: + return KEY_SHIFT|KEY_STANDBY; + case VK_SNAPSHOT: + return KEY_SHIFT|KEY_PRNTSCRN; + } + } + + return Char?Char:KEY_NONE; +} diff --git a/far2l/src/console/keyboard.hpp b/far2l/src/console/keyboard.hpp new file mode 100644 index 00000000..39f17655 --- /dev/null +++ b/far2l/src/console/keyboard.hpp @@ -0,0 +1,77 @@ +#pragma once + +/* +keyboard.hpp + +Функции, имеющие отношение к клавитуре +*/ +/* +Copyright (c) 1996 Eugene Roshal +Copyright (c) 2000 Far Group +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "farqueue.hpp" +#include <WinCompat.h> +#include "FARString.hpp" + +enum +{ + SKEY_VK_KEYS = 0x40000000, + SKEY_IDLE = 0x80000000, + SKEY_NOTMACROS = 0x00000001, +}; + +#define MOUSE_ANY_BUTTON_PRESSED (FROM_LEFT_1ST_BUTTON_PRESSED|RIGHTMOST_BUTTON_PRESSED|FROM_LEFT_2ND_BUTTON_PRESSED|FROM_LEFT_3RD_BUTTON_PRESSED|FROM_LEFT_4TH_BUTTON_PRESSED) + +extern FarQueue<DWORD> *KeyQueue; +extern int AltPressed,CtrlPressed,ShiftPressed; +extern int RightAltPressed,RightCtrlPressed,RightShiftPressed; +extern DWORD MouseButtonState,PrevMouseButtonState; +extern SHORT PrevMouseX,PrevMouseY,MouseX,MouseY; +extern int PreMouseEventFlags,MouseEventFlags; +extern int ReturnAltValue; + +void InitKeysArray(); +bool KeyToKeyLayoutCompare(int Key, int CompareKey); +int KeyToKeyLayout(int Key); + +// возвращает: 1 - LeftPressed, 2 - Right Pressed, 3 - Middle Pressed, 0 - none +DWORD IsMouseButtonPressed(); +int TranslateKeyToVK(int Key,int &VirtKey,int &ControlState,INPUT_RECORD *rec=nullptr); +uint32_t WINAPI KeyNameToKey(const wchar_t *Name); +BOOL WINAPI KeyToText(uint32_t Key, FARString &strKeyText); +int WINAPI InputRecordToKey(const INPUT_RECORD *Rec); +DWORD GetInputRecord(INPUT_RECORD *rec,bool ExcludeMacro=false,bool ProcessMouse=false,bool AllowSynchro=true); +DWORD PeekInputRecord(INPUT_RECORD *rec,bool ExcludeMacro=true); +DWORD CalcKeyCode(INPUT_RECORD *rec,int RealKey,int *NotMacros=nullptr); +DWORD WaitKey(DWORD KeyWait=(DWORD)-1,DWORD delayMS=0,bool ExcludeMacro=true); +int SetFLockState(UINT vkKey, int State); +int WriteInput(int Key,DWORD Flags=0); +int IsNavKey(DWORD Key); +int IsShiftKey(DWORD Key); +int CheckForEsc(); +int CheckForEscSilent(); +int ConfirmAbortOp(); diff --git a/far2l/src/console/keys.hpp b/far2l/src/console/keys.hpp new file mode 100644 index 00000000..8bc8d61d --- /dev/null +++ b/far2l/src/console/keys.hpp @@ -0,0 +1,809 @@ +#pragma once +#ifndef __FARKEYS_HPP__ +#define __FARKEYS_HPP__ +#ifndef FAR_USE_INTERNALS +#define FAR_USE_INTERNALS +#endif // END FAR_USE_INTERNALS +#ifdef FAR_USE_INTERNALS +/* +keys.hpp + +Внутренние фаровские имена клавиш + +ВНИМАНИЕ! + Новые пвсевдоклавиши, типа KEY_FOCUS_CHANGED и KEY_CONSOLE_BUFFER_RESIZE + добавлять между KEY_END_FKEY и KEY_END_SKEY +*/ +#else // ELSE FAR_USE_INTERNALS +/* + farkeys.hpp + + Inside KeyName for FAR Manager <%VERSION%> +*/ +#endif // END FAR_USE_INTERNALS + +/* +Copyright (c) 1996 Eugene Roshal +Copyright (c) 2000 Far Group +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + +EXCEPTION: +Far Manager plugins that use this header file can be distributed under any +other possible license with no implications from the above license on them. +*/ + +#include <cstdint> +#include <limits> +#include <WinCompat.h> + +#define EXTENDED_KEY_BASE 0x00010000 +#define INTERNAL_KEY_BASE 0x00020000 +#define INTERNAL_KEY_BASE_2 0x00030000 +#ifdef FAR_USE_INTERNALS +#define INTERNAL_MACRO_BASE 0x00080000 +#endif // END FAR_USE_INTERNALS + +enum BaseDefKeyboard : uint32_t +{ + KEY_CTRLMASK =0xFFF00000, +#ifdef FAR_USE_INTERNALS + KEY_M_OEM =0x00100000, + KEY_M_SPEC =0x00200000, + // + // +#endif // END FAR_USE_INTERNALS + KEY_CTRL =0x01000000, + KEY_ALT =0x02000000, + KEY_SHIFT =0x04000000, + // + KEY_RCTRL =0x10000000, + KEY_RALT =0x20000000, +#ifdef FAR_USE_INTERNALS + KEY_ALTDIGIT =0x40000000, + KEY_RSHIFT =0x80000000, +#endif // END FAR_USE_INTERNALS + + KEY_BRACKET ='[', + KEY_BACKBRACKET =']', + KEY_COMMA =',', + KEY_QUOTE ='"', + KEY_DOT ='.', + KEY_SLASH ='/', + KEY_COLON =':', + KEY_SEMICOLON =';', + KEY_BACKSLASH ='\\', + + KEY_BS =0x00000008, + KEY_TAB =0x00000009, + KEY_ENTER =0x0000000D, + KEY_ESC =0x0000001B, + KEY_SPACE =0x00000020, + + KEY_MASKF =0x0001FFFF, + + KEY_FKEY_BEGIN =EXTENDED_KEY_BASE, + + KEY_BREAK =EXTENDED_KEY_BASE+VK_CANCEL, + + KEY_PAUSE =EXTENDED_KEY_BASE+VK_PAUSE, + KEY_CAPSLOCK =EXTENDED_KEY_BASE+VK_CAPITAL, + + KEY_PGUP =EXTENDED_KEY_BASE+VK_PRIOR, + KEY_PGDN =EXTENDED_KEY_BASE+VK_NEXT, + KEY_END =EXTENDED_KEY_BASE+VK_END, + KEY_HOME =EXTENDED_KEY_BASE+VK_HOME, + KEY_LEFT =EXTENDED_KEY_BASE+VK_LEFT, + KEY_UP =EXTENDED_KEY_BASE+VK_UP, + KEY_RIGHT =EXTENDED_KEY_BASE+VK_RIGHT, + KEY_DOWN =EXTENDED_KEY_BASE+VK_DOWN, + KEY_PRNTSCRN =EXTENDED_KEY_BASE+VK_SNAPSHOT, + KEY_INS =EXTENDED_KEY_BASE+VK_INSERT, + KEY_DEL =EXTENDED_KEY_BASE+VK_DELETE, + + KEY_LWIN =EXTENDED_KEY_BASE+VK_LWIN, + KEY_RWIN =EXTENDED_KEY_BASE+VK_RWIN, + KEY_APPS =EXTENDED_KEY_BASE+VK_APPS, + KEY_STANDBY =EXTENDED_KEY_BASE+VK_SLEEP, + + KEY_NUMPAD0 =EXTENDED_KEY_BASE+VK_NUMPAD0, + KEY_NUMPAD1 =EXTENDED_KEY_BASE+VK_NUMPAD1, + KEY_NUMPAD2 =EXTENDED_KEY_BASE+VK_NUMPAD2, + KEY_NUMPAD3 =EXTENDED_KEY_BASE+VK_NUMPAD3, + KEY_NUMPAD4 =EXTENDED_KEY_BASE+VK_NUMPAD4, + KEY_NUMPAD5 =EXTENDED_KEY_BASE+VK_NUMPAD5, + KEY_CLEAR =KEY_NUMPAD5, + KEY_NUMPAD6 =EXTENDED_KEY_BASE+VK_NUMPAD6, + KEY_NUMPAD7 =EXTENDED_KEY_BASE+VK_NUMPAD7, + KEY_NUMPAD8 =EXTENDED_KEY_BASE+VK_NUMPAD8, + KEY_NUMPAD9 =EXTENDED_KEY_BASE+VK_NUMPAD9, + + KEY_MULTIPLY =EXTENDED_KEY_BASE+VK_MULTIPLY, + KEY_ADD =EXTENDED_KEY_BASE+VK_ADD, + KEY_SUBTRACT =EXTENDED_KEY_BASE+VK_SUBTRACT, + KEY_DECIMAL =EXTENDED_KEY_BASE+VK_DECIMAL, + KEY_DIVIDE =EXTENDED_KEY_BASE+VK_DIVIDE, + + KEY_F1 =EXTENDED_KEY_BASE+VK_F1, + KEY_F2 =EXTENDED_KEY_BASE+VK_F2, + KEY_F3 =EXTENDED_KEY_BASE+VK_F3, + KEY_F4 =EXTENDED_KEY_BASE+VK_F4, + KEY_F5 =EXTENDED_KEY_BASE+VK_F5, + KEY_F6 =EXTENDED_KEY_BASE+VK_F6, + KEY_F7 =EXTENDED_KEY_BASE+VK_F7, + KEY_F8 =EXTENDED_KEY_BASE+VK_F8, + KEY_F9 =EXTENDED_KEY_BASE+VK_F9, + KEY_F10 =EXTENDED_KEY_BASE+VK_F10, + KEY_F11 =EXTENDED_KEY_BASE+VK_F11, + KEY_F12 =EXTENDED_KEY_BASE+VK_F12, + + KEY_F13 =EXTENDED_KEY_BASE+VK_F13, + KEY_F14 =EXTENDED_KEY_BASE+VK_F14, + KEY_F15 =EXTENDED_KEY_BASE+VK_F15, + KEY_F16 =EXTENDED_KEY_BASE+VK_F16, + KEY_F17 =EXTENDED_KEY_BASE+VK_F17, + KEY_F18 =EXTENDED_KEY_BASE+VK_F18, + KEY_F19 =EXTENDED_KEY_BASE+VK_F19, + KEY_F20 =EXTENDED_KEY_BASE+VK_F20, + KEY_F21 =EXTENDED_KEY_BASE+VK_F21, + KEY_F22 =EXTENDED_KEY_BASE+VK_F22, + KEY_F23 =EXTENDED_KEY_BASE+VK_F23, + KEY_F24 =EXTENDED_KEY_BASE+VK_F24, + + KEY_NUMLOCK =EXTENDED_KEY_BASE+VK_NUMLOCK, + KEY_SCROLLLOCK =EXTENDED_KEY_BASE+VK_SCROLL, + + KEY_BROWSER_BACK =EXTENDED_KEY_BASE+VK_BROWSER_BACK, + KEY_BROWSER_FORWARD =EXTENDED_KEY_BASE+VK_BROWSER_FORWARD, + KEY_BROWSER_REFRESH =EXTENDED_KEY_BASE+VK_BROWSER_REFRESH, + KEY_BROWSER_STOP =EXTENDED_KEY_BASE+VK_BROWSER_STOP, + KEY_BROWSER_SEARCH =EXTENDED_KEY_BASE+VK_BROWSER_SEARCH, + KEY_BROWSER_FAVORITES =EXTENDED_KEY_BASE+VK_BROWSER_FAVORITES, + KEY_BROWSER_HOME =EXTENDED_KEY_BASE+VK_BROWSER_HOME, + KEY_VOLUME_MUTE =EXTENDED_KEY_BASE+VK_VOLUME_MUTE, + KEY_VOLUME_DOWN =EXTENDED_KEY_BASE+VK_VOLUME_DOWN, + KEY_VOLUME_UP =EXTENDED_KEY_BASE+VK_VOLUME_UP, + KEY_MEDIA_NEXT_TRACK =EXTENDED_KEY_BASE+VK_MEDIA_NEXT_TRACK, + KEY_MEDIA_PREV_TRACK =EXTENDED_KEY_BASE+VK_MEDIA_PREV_TRACK, + KEY_MEDIA_STOP =EXTENDED_KEY_BASE+VK_MEDIA_STOP, + KEY_MEDIA_PLAY_PAUSE =EXTENDED_KEY_BASE+VK_MEDIA_PLAY_PAUSE, + KEY_LAUNCH_MAIL =EXTENDED_KEY_BASE+VK_LAUNCH_MAIL, + KEY_LAUNCH_MEDIA_SELECT =EXTENDED_KEY_BASE+VK_LAUNCH_MEDIA_SELECT, + KEY_LAUNCH_APP1 =EXTENDED_KEY_BASE+VK_LAUNCH_APP1, + KEY_LAUNCH_APP2 =EXTENDED_KEY_BASE+VK_LAUNCH_APP2, + + KEY_CTRLALTSHIFTPRESS =INTERNAL_KEY_BASE+1, + KEY_CTRLALTSHIFTRELEASE =INTERNAL_KEY_BASE+2, + + KEY_MSWHEEL_UP =INTERNAL_KEY_BASE+3, + KEY_MSWHEEL_DOWN =INTERNAL_KEY_BASE+4, +#ifdef FAR_USE_INTERNALS + KEY_RCTRLALTSHIFTPRESS =INTERNAL_KEY_BASE+7, + KEY_RCTRLALTSHIFTRELEASE =INTERNAL_KEY_BASE+8, +#endif // END FAR_USE_INTERNALS + KEY_NUMDEL =INTERNAL_KEY_BASE+9, + KEY_NUMENTER =INTERNAL_KEY_BASE+0xB, + + KEY_MSWHEEL_LEFT =INTERNAL_KEY_BASE+0xC, + KEY_MSWHEEL_RIGHT =INTERNAL_KEY_BASE+0xD, + + KEY_MSLCLICK =INTERNAL_KEY_BASE+0xF, + KEY_MSRCLICK =INTERNAL_KEY_BASE+0x10, + + KEY_MSM1CLICK =INTERNAL_KEY_BASE+0x11, + KEY_MSM2CLICK =INTERNAL_KEY_BASE+0x12, + KEY_MSM3CLICK =INTERNAL_KEY_BASE+0x13, + +#ifdef FAR_USE_INTERNALS +#if 0 + KEY_MSLDBLCLICK =INTERNAL_KEY_BASE+0x14, + KEY_MSRDBLCLICK =INTERNAL_KEY_BASE+0x15, + + KEY_MSM1DBLCLICK =INTERNAL_KEY_BASE+0x16, + KEY_MSM2DBLCLICK =INTERNAL_KEY_BASE+0x17, + KEY_MSM3DBLCLICK =INTERNAL_KEY_BASE+0x18, +#endif +#endif // END FAR_USE_INTERNALS + + + KEY_VK_0xFF_BEGIN =EXTENDED_KEY_BASE+0x00000100, +#ifdef FAR_USE_INTERNALS +// KEY_HP_INTERNET =KEY_VK_0xFF_BEGIN+0x00000023, +// KEY_HP_HOME =KEY_VK_0xFF_BEGIN+0x0000001F, +// KEY_HP_SEARCH =KEY_VK_0xFF_BEGIN+0x0000001A, +// KEY_HP_MAIL =KEY_VK_0xFF_BEGIN+0x0000001E, +// KEY_HP_COMMUNITIES =KEY_VK_0xFF_BEGIN+0x00000013, +// KEY_HP_MARKET =KEY_VK_0xFF_BEGIN+0x00000014, +// KEY_HP_MEETING =KEY_VK_0xFF_BEGIN+0x00000015, +// KEY_HP_NEWS =KEY_VK_0xFF_BEGIN+0x0000001B, +// +// KEY_AC_HOME =KEY_VK_0xFF_BEGIN+0x00000023, +// KEY_AC_BACK =KEY_VK_0xFF_BEGIN+0x00000024, +// KEY_AC_FORWARD =KEY_VK_0xFF_BEGIN+0x00000025, +// KEY_AC_STOP =KEY_VK_0xFF_BEGIN+0x00000026, +// KEY_AC_REFRESH =KEY_VK_0xFF_BEGIN+0x00000027, +// KEY_AC_BOOKMARKS =KEY_VK_0xFF_BEGIN+0x0000002A, +#endif // END FAR_USE_INTERNALS + KEY_VK_0xFF_END =EXTENDED_KEY_BASE+0x000001FF, + + KEY_END_FKEY =0x0001FFFF, + + KEY_NONE =INTERNAL_KEY_BASE_2+1, + KEY_IDLE =INTERNAL_KEY_BASE_2+2, +#ifdef FAR_USE_INTERNALS + KEY_DRAGCOPY =INTERNAL_KEY_BASE_2+3, + KEY_DRAGMOVE =INTERNAL_KEY_BASE_2+4, +#endif // END FAR_USE_INTERNALS + + KEY_KILLFOCUS =INTERNAL_KEY_BASE_2+6, + KEY_GOTFOCUS =INTERNAL_KEY_BASE_2+7, + KEY_CONSOLE_BUFFER_RESIZE=INTERNAL_KEY_BASE_2+8, + +#ifdef FAR_USE_INTERNALS + KEY_OP_BASE =INTERNAL_KEY_BASE_2+0x100, + KEY_OP_XLAT =KEY_OP_BASE+0, + KEY_OP_PLAINTEXT =KEY_OP_BASE+2, + KEY_OP_SELWORD =KEY_OP_BASE+3, + KEY_OP_ENDBASE =INTERNAL_KEY_BASE_2+0x1FF, +#endif // END FAR_USE_INTERNALS + + KEY_END_SKEY =0x0003FFFF, + KEY_LAST_BASE =KEY_END_SKEY, + +#ifdef FAR_USE_INTERNALS + // см macroopcode.hpp + KEY_MACRO_BASE =INTERNAL_MACRO_BASE, + KEY_MACRO_OP_BASE =INTERNAL_MACRO_BASE+0x0000, // opcode 0x00080000 - 0x000803FF + KEY_MACRO_C_BASE =INTERNAL_MACRO_BASE+0x0400, // булевые условия 0x00080400 - 0x000807FF + KEY_MACRO_V_BASE =INTERNAL_MACRO_BASE+0x0800, // разные переменные 0x00080800 - 0x00080BFF + KEY_MACRO_F_BASE =INTERNAL_MACRO_BASE+0x0C00, // функции 0x00080C00 - + + KEY_MACRO_U_BASE =INTERNAL_MACRO_BASE+0x8000, // внешние функции 0x00088000 - + + KEY_MACRO_ENDBASE =0x000FFFFF, +#endif // END FAR_USE_INTERNALS + + KEY_INVALID =std::numeric_limits<uint32_t>::max() + +}; + +enum AddDefKeyboard +{ + KEY_CTRLSHIFT =KEY_CTRL|KEY_SHIFT, + KEY_ALTSHIFT =KEY_ALT|KEY_SHIFT, + KEY_CTRLALT =KEY_CTRL|KEY_ALT, + + KEY_CTRL0 =KEY_CTRL+'0', + KEY_CTRL1 =KEY_CTRL+'1', + KEY_CTRL2 =KEY_CTRL+'2', + KEY_CTRL3 =KEY_CTRL+'3', + KEY_CTRL4 =KEY_CTRL+'4', + KEY_CTRL5 =KEY_CTRL+'5', + KEY_CTRL6 =KEY_CTRL+'6', + KEY_CTRL7 =KEY_CTRL+'7', + KEY_CTRL8 =KEY_CTRL+'8', + KEY_CTRL9 =KEY_CTRL+'9', + + KEY_RCTRL0 =KEY_RCTRL+'0', + KEY_RCTRL1 =KEY_RCTRL+'1', + KEY_RCTRL2 =KEY_RCTRL+'2', + KEY_RCTRL3 =KEY_RCTRL+'3', + KEY_RCTRL4 =KEY_RCTRL+'4', + KEY_RCTRL5 =KEY_RCTRL+'5', + KEY_RCTRL6 =KEY_RCTRL+'6', + KEY_RCTRL7 =KEY_RCTRL+'7', + KEY_RCTRL8 =KEY_RCTRL+'8', + KEY_RCTRL9 =KEY_RCTRL+'9', + + KEY_CTRLA =KEY_CTRL+'A', + KEY_CTRLB =KEY_CTRL+'B', + KEY_CTRLC =KEY_CTRL+'C', + KEY_CTRLD =KEY_CTRL+'D', + KEY_CTRLE =KEY_CTRL+'E', + KEY_CTRLF =KEY_CTRL+'F', + KEY_CTRLG =KEY_CTRL+'G', + KEY_CTRLH =KEY_CTRL+'H', + KEY_CTRLI =KEY_CTRL+'I', + KEY_CTRLJ =KEY_CTRL+'J', + KEY_CTRLK =KEY_CTRL+'K', + KEY_CTRLL =KEY_CTRL+'L', + KEY_CTRLM =KEY_CTRL+'M', + KEY_CTRLN =KEY_CTRL+'N', + KEY_CTRLO =KEY_CTRL+'O', + KEY_CTRLP =KEY_CTRL+'P', + KEY_CTRLQ =KEY_CTRL+'Q', + KEY_CTRLR =KEY_CTRL+'R', + KEY_CTRLS =KEY_CTRL+'S', + KEY_CTRLT =KEY_CTRL+'T', + KEY_CTRLU =KEY_CTRL+'U', + KEY_CTRLV =KEY_CTRL+'V', + KEY_CTRLW =KEY_CTRL+'W', + KEY_CTRLX =KEY_CTRL+'X', + KEY_CTRLY =KEY_CTRL+'Y', + KEY_CTRLZ =KEY_CTRL+'Z', + + KEY_CTRLBRACKET =KEY_CTRL|KEY_BRACKET, + KEY_CTRLBACKBRACKET =KEY_CTRL|KEY_BACKBRACKET, + KEY_CTRLCOMMA =KEY_CTRL|KEY_COMMA, + KEY_CTRLQUOTE =KEY_CTRL|KEY_QUOTE, + KEY_CTRLDOT =KEY_CTRL|KEY_DOT, + + KEY_ALT0 =KEY_ALT+'0', + KEY_ALT1 =KEY_ALT+'1', + KEY_ALT2 =KEY_ALT+'2', + KEY_ALT3 =KEY_ALT+'3', + KEY_ALT4 =KEY_ALT+'4', + KEY_ALT5 =KEY_ALT+'5', + KEY_ALT6 =KEY_ALT+'6', + KEY_ALT7 =KEY_ALT+'7', + KEY_ALT8 =KEY_ALT+'8', + KEY_ALT9 =KEY_ALT+'9', + + KEY_ALTADD =KEY_ALT|KEY_ADD, + KEY_ALTDOT =KEY_ALT|KEY_DOT, + KEY_ALTCOMMA =KEY_ALT|KEY_COMMA, + KEY_ALTMULTIPLY =KEY_ALT|KEY_MULTIPLY, + + KEY_ALTA =KEY_ALT+'A', + KEY_ALTB =KEY_ALT+'B', + KEY_ALTC =KEY_ALT+'C', + KEY_ALTD =KEY_ALT+'D', + KEY_ALTE =KEY_ALT+'E', + KEY_ALTF =KEY_ALT+'F', + KEY_ALTG =KEY_ALT+'G', + KEY_ALTH =KEY_ALT+'H', + KEY_ALTI =KEY_ALT+'I', + KEY_ALTJ =KEY_ALT+'J', + KEY_ALTK =KEY_ALT+'K', + KEY_ALTL =KEY_ALT+'L', + KEY_ALTM =KEY_ALT+'M', + KEY_ALTN =KEY_ALT+'N', + KEY_ALTO =KEY_ALT+'O', + KEY_ALTP =KEY_ALT+'P', + KEY_ALTQ =KEY_ALT+'Q', + KEY_ALTR =KEY_ALT+'R', + KEY_ALTS =KEY_ALT+'S', + KEY_ALTT =KEY_ALT+'T', + KEY_ALTU =KEY_ALT+'U', + KEY_ALTV =KEY_ALT+'V', + KEY_ALTW =KEY_ALT+'W', + KEY_ALTX =KEY_ALT+'X', + KEY_ALTY =KEY_ALT+'Y', + KEY_ALTZ =KEY_ALT+'Z', + + KEY_CTRLSHIFTADD =KEY_CTRL|KEY_SHIFT|KEY_ADD, + KEY_CTRLSHIFTSUBTRACT =KEY_CTRL|KEY_SHIFT|KEY_SUBTRACT, + KEY_CTRLSHIFTDOT =KEY_CTRL|KEY_SHIFT|KEY_DOT, + KEY_CTRLSHIFTSLASH =KEY_CTRL|KEY_SHIFT|KEY_SLASH, + + KEY_CTRLSHIFT0 =(KEY_CTRL|KEY_SHIFT)+'0', + KEY_CTRLSHIFT1 =(KEY_CTRL|KEY_SHIFT)+'1', + KEY_CTRLSHIFT2 =(KEY_CTRL|KEY_SHIFT)+'2', + KEY_CTRLSHIFT3 =(KEY_CTRL|KEY_SHIFT)+'3', + KEY_CTRLSHIFT4 =(KEY_CTRL|KEY_SHIFT)+'4', + KEY_CTRLSHIFT5 =(KEY_CTRL|KEY_SHIFT)+'5', + KEY_CTRLSHIFT6 =(KEY_CTRL|KEY_SHIFT)+'6', + KEY_CTRLSHIFT7 =(KEY_CTRL|KEY_SHIFT)+'7', + KEY_CTRLSHIFT8 =(KEY_CTRL|KEY_SHIFT)+'8', + KEY_CTRLSHIFT9 =(KEY_CTRL|KEY_SHIFT)+'9', + + KEY_RCTRLSHIFT0 =KEY_RCTRL+KEY_SHIFT+'0', + KEY_RCTRLSHIFT1 =KEY_RCTRL+KEY_SHIFT+'1', + KEY_RCTRLSHIFT2 =KEY_RCTRL+KEY_SHIFT+'2', + KEY_RCTRLSHIFT3 =KEY_RCTRL+KEY_SHIFT+'3', + KEY_RCTRLSHIFT4 =KEY_RCTRL+KEY_SHIFT+'4', + KEY_RCTRLSHIFT5 =KEY_RCTRL+KEY_SHIFT+'5', + KEY_RCTRLSHIFT6 =KEY_RCTRL+KEY_SHIFT+'6', + KEY_RCTRLSHIFT7 =KEY_RCTRL+KEY_SHIFT+'7', + KEY_RCTRLSHIFT8 =KEY_RCTRL+KEY_SHIFT+'8', + KEY_RCTRLSHIFT9 =KEY_RCTRL+KEY_SHIFT+'9', + + KEY_CTRLSHIFTA =(KEY_CTRL|KEY_SHIFT)+'A', + KEY_CTRLSHIFTB =(KEY_CTRL|KEY_SHIFT)+'B', + KEY_CTRLSHIFTC =(KEY_CTRL|KEY_SHIFT)+'C', + KEY_CTRLSHIFTD =(KEY_CTRL|KEY_SHIFT)+'D', + KEY_CTRLSHIFTE =(KEY_CTRL|KEY_SHIFT)+'E', + KEY_CTRLSHIFTF =(KEY_CTRL|KEY_SHIFT)+'F', + KEY_CTRLSHIFTG =(KEY_CTRL|KEY_SHIFT)+'G', + KEY_CTRLSHIFTH =(KEY_CTRL|KEY_SHIFT)+'H', + KEY_CTRLSHIFTI =(KEY_CTRL|KEY_SHIFT)+'I', + KEY_CTRLSHIFTJ =(KEY_CTRL|KEY_SHIFT)+'J', + KEY_CTRLSHIFTK =(KEY_CTRL|KEY_SHIFT)+'K', + KEY_CTRLSHIFTL =(KEY_CTRL|KEY_SHIFT)+'L', + KEY_CTRLSHIFTM =(KEY_CTRL|KEY_SHIFT)+'M', + KEY_CTRLSHIFTN =(KEY_CTRL|KEY_SHIFT)+'N', + KEY_CTRLSHIFTO =(KEY_CTRL|KEY_SHIFT)+'O', + KEY_CTRLSHIFTP =(KEY_CTRL|KEY_SHIFT)+'P', + KEY_CTRLSHIFTQ =(KEY_CTRL|KEY_SHIFT)+'Q', + KEY_CTRLSHIFTR =(KEY_CTRL|KEY_SHIFT)+'R', + KEY_CTRLSHIFTS =(KEY_CTRL|KEY_SHIFT)+'S', + KEY_CTRLSHIFTT =(KEY_CTRL|KEY_SHIFT)+'T', + KEY_CTRLSHIFTU =(KEY_CTRL|KEY_SHIFT)+'U', + KEY_CTRLSHIFTV =(KEY_CTRL|KEY_SHIFT)+'V', + KEY_CTRLSHIFTW =(KEY_CTRL|KEY_SHIFT)+'W', + KEY_CTRLSHIFTX =(KEY_CTRL|KEY_SHIFT)+'X', + KEY_CTRLSHIFTY =(KEY_CTRL|KEY_SHIFT)+'Y', + KEY_CTRLSHIFTZ =(KEY_CTRL|KEY_SHIFT)+'Z', + + KEY_CTRLSHIFTBRACKET =KEY_CTRL|KEY_SHIFT|KEY_BRACKET, + KEY_CTRLSHIFTBACKSLASH =KEY_CTRL|KEY_SHIFT|KEY_BACKSLASH, + KEY_CTRLSHIFTBACKBRACKET =KEY_CTRL|KEY_SHIFT|KEY_BACKBRACKET, + + KEY_ALTSHIFT0 =(KEY_ALT|KEY_SHIFT)+'0', + KEY_ALTSHIFT1 =(KEY_ALT|KEY_SHIFT)+'1', + KEY_ALTSHIFT2 =(KEY_ALT|KEY_SHIFT)+'2', + KEY_ALTSHIFT3 =(KEY_ALT|KEY_SHIFT)+'3', + KEY_ALTSHIFT4 =(KEY_ALT|KEY_SHIFT)+'4', + KEY_ALTSHIFT5 =(KEY_ALT|KEY_SHIFT)+'5', + KEY_ALTSHIFT6 =(KEY_ALT|KEY_SHIFT)+'6', + KEY_ALTSHIFT7 =(KEY_ALT|KEY_SHIFT)+'7', + KEY_ALTSHIFT8 =(KEY_ALT|KEY_SHIFT)+'8', + KEY_ALTSHIFT9 =(KEY_ALT|KEY_SHIFT)+'9', + + KEY_ALTSHIFTA =(KEY_ALT|KEY_SHIFT)+'A', + KEY_ALTSHIFTB =(KEY_ALT|KEY_SHIFT)+'B', + KEY_ALTSHIFTC =(KEY_ALT|KEY_SHIFT)+'C', + KEY_ALTSHIFTD =(KEY_ALT|KEY_SHIFT)+'D', + KEY_ALTSHIFTE =(KEY_ALT|KEY_SHIFT)+'E', + KEY_ALTSHIFTF =(KEY_ALT|KEY_SHIFT)+'F', + KEY_ALTSHIFTG =(KEY_ALT|KEY_SHIFT)+'G', + KEY_ALTSHIFTH =(KEY_ALT|KEY_SHIFT)+'H', + KEY_ALTSHIFTI =(KEY_ALT|KEY_SHIFT)+'I', + KEY_ALTSHIFTJ =(KEY_ALT|KEY_SHIFT)+'J', + KEY_ALTSHIFTK =(KEY_ALT|KEY_SHIFT)+'K', + KEY_ALTSHIFTL =(KEY_ALT|KEY_SHIFT)+'L', + KEY_ALTSHIFTM =(KEY_ALT|KEY_SHIFT)+'M', + KEY_ALTSHIFTN =(KEY_ALT|KEY_SHIFT)+'N', + KEY_ALTSHIFTO =(KEY_ALT|KEY_SHIFT)+'O', + KEY_ALTSHIFTP =(KEY_ALT|KEY_SHIFT)+'P', + KEY_ALTSHIFTQ =(KEY_ALT|KEY_SHIFT)+'Q', + KEY_ALTSHIFTR =(KEY_ALT|KEY_SHIFT)+'R', + KEY_ALTSHIFTS =(KEY_ALT|KEY_SHIFT)+'S', + KEY_ALTSHIFTT =(KEY_ALT|KEY_SHIFT)+'T', + KEY_ALTSHIFTU =(KEY_ALT|KEY_SHIFT)+'U', + KEY_ALTSHIFTV =(KEY_ALT|KEY_SHIFT)+'V', + KEY_ALTSHIFTW =(KEY_ALT|KEY_SHIFT)+'W', + KEY_ALTSHIFTX =(KEY_ALT|KEY_SHIFT)+'X', + KEY_ALTSHIFTY =(KEY_ALT|KEY_SHIFT)+'Y', + KEY_ALTSHIFTZ =(KEY_ALT|KEY_SHIFT)+'Z', + + KEY_ALTSHIFTBRACKET =KEY_ALT|KEY_SHIFT|KEY_BRACKET, + KEY_ALTSHIFTBACKBRACKET =KEY_ALT|KEY_SHIFT|KEY_BACKBRACKET, + + KEY_CTRLALT0 =(KEY_CTRL|KEY_ALT)+'0', + KEY_CTRLALT1 =(KEY_CTRL|KEY_ALT)+'1', + KEY_CTRLALT2 =(KEY_CTRL|KEY_ALT)+'2', + KEY_CTRLALT3 =(KEY_CTRL|KEY_ALT)+'3', + KEY_CTRLALT4 =(KEY_CTRL|KEY_ALT)+'4', + KEY_CTRLALT5 =(KEY_CTRL|KEY_ALT)+'5', + KEY_CTRLALT6 =(KEY_CTRL|KEY_ALT)+'6', + KEY_CTRLALT7 =(KEY_CTRL|KEY_ALT)+'7', + KEY_CTRLALT8 =(KEY_CTRL|KEY_ALT)+'8', + KEY_CTRLALT9 =(KEY_CTRL|KEY_ALT)+'9', + + KEY_CTRLALTA =(KEY_CTRL|KEY_ALT)+'A', + KEY_CTRLALTB =(KEY_CTRL|KEY_ALT)+'B', + KEY_CTRLALTC =(KEY_CTRL|KEY_ALT)+'C', + KEY_CTRLALTD =(KEY_CTRL|KEY_ALT)+'D', + KEY_CTRLALTE =(KEY_CTRL|KEY_ALT)+'E', + KEY_CTRLALTF =(KEY_CTRL|KEY_ALT)+'F', + KEY_CTRLALTG =(KEY_CTRL|KEY_ALT)+'G', + KEY_CTRLALTH =(KEY_CTRL|KEY_ALT)+'H', + KEY_CTRLALTI =(KEY_CTRL|KEY_ALT)+'I', + KEY_CTRLALTJ =(KEY_CTRL|KEY_ALT)+'J', + KEY_CTRLALTK =(KEY_CTRL|KEY_ALT)+'K', + KEY_CTRLALTL =(KEY_CTRL|KEY_ALT)+'L', + KEY_CTRLALTM =(KEY_CTRL|KEY_ALT)+'M', + KEY_CTRLALTN =(KEY_CTRL|KEY_ALT)+'N', + KEY_CTRLALTO =(KEY_CTRL|KEY_ALT)+'O', + KEY_CTRLALTP =(KEY_CTRL|KEY_ALT)+'P', + KEY_CTRLALTQ =(KEY_CTRL|KEY_ALT)+'Q', + KEY_CTRLALTR =(KEY_CTRL|KEY_ALT)+'R', + KEY_CTRLALTS =(KEY_CTRL|KEY_ALT)+'S', + KEY_CTRLALTT =(KEY_CTRL|KEY_ALT)+'T', + KEY_CTRLALTU =(KEY_CTRL|KEY_ALT)+'U', + KEY_CTRLALTV =(KEY_CTRL|KEY_ALT)+'V', + KEY_CTRLALTW =(KEY_CTRL|KEY_ALT)+'W', + KEY_CTRLALTX =(KEY_CTRL|KEY_ALT)+'X', + KEY_CTRLALTY =(KEY_CTRL|KEY_ALT)+'Y', + KEY_CTRLALTZ =(KEY_CTRL|KEY_ALT)+'Z', + + KEY_CTRLALTBRACKET =KEY_CTRL|KEY_ALT|KEY_BRACKET, + KEY_CTRLALTBACKBRACKET =KEY_CTRL|KEY_ALT|KEY_BACKBRACKET, + + KEY_CTRLF1 =KEY_CTRL|KEY_F1, + KEY_CTRLF2 =KEY_CTRL|KEY_F2, + KEY_CTRLF3 =KEY_CTRL|KEY_F3, + KEY_CTRLF4 =KEY_CTRL|KEY_F4, + KEY_CTRLF5 =KEY_CTRL|KEY_F5, + KEY_CTRLF6 =KEY_CTRL|KEY_F6, + KEY_CTRLF7 =KEY_CTRL|KEY_F7, + KEY_CTRLF8 =KEY_CTRL|KEY_F8, + KEY_CTRLF9 =KEY_CTRL|KEY_F9, + KEY_CTRLF10 =KEY_CTRL|KEY_F10, + KEY_CTRLF11 =KEY_CTRL|KEY_F11, + KEY_CTRLF12 =KEY_CTRL|KEY_F12, + + KEY_SHIFTF1 =KEY_SHIFT|KEY_F1, + KEY_SHIFTF2 =KEY_SHIFT|KEY_F2, + KEY_SHIFTF3 =KEY_SHIFT|KEY_F3, + KEY_SHIFTF4 =KEY_SHIFT|KEY_F4, + KEY_SHIFTF5 =KEY_SHIFT|KEY_F5, + KEY_SHIFTF6 =KEY_SHIFT|KEY_F6, + KEY_SHIFTF7 =KEY_SHIFT|KEY_F7, + KEY_SHIFTF8 =KEY_SHIFT|KEY_F8, + KEY_SHIFTF9 =KEY_SHIFT|KEY_F9, + KEY_SHIFTF10 =KEY_SHIFT|KEY_F10, + KEY_SHIFTF11 =KEY_SHIFT|KEY_F11, + KEY_SHIFTF12 =KEY_SHIFT|KEY_F12, + + KEY_ALTF1 =KEY_ALT|KEY_F1, + KEY_ALTF2 =KEY_ALT|KEY_F2, + KEY_ALTF3 =KEY_ALT|KEY_F3, + KEY_ALTF4 =KEY_ALT|KEY_F4, + KEY_ALTF5 =KEY_ALT|KEY_F5, + KEY_ALTF6 =KEY_ALT|KEY_F6, + KEY_ALTF7 =KEY_ALT|KEY_F7, + KEY_ALTF8 =KEY_ALT|KEY_F8, + KEY_ALTF9 =KEY_ALT|KEY_F9, + KEY_ALTF10 =KEY_ALT|KEY_F10, + KEY_ALTF11 =KEY_ALT|KEY_F11, + KEY_ALTF12 =KEY_ALT|KEY_F12, + + KEY_CTRLSHIFTF1 =KEY_CTRL|KEY_SHIFT|KEY_F1, + KEY_CTRLSHIFTF2 =KEY_CTRL|KEY_SHIFT|KEY_F2, + KEY_CTRLSHIFTF3 =KEY_CTRL|KEY_SHIFT|KEY_F3, + KEY_CTRLSHIFTF4 =KEY_CTRL|KEY_SHIFT|KEY_F4, + KEY_CTRLSHIFTF5 =KEY_CTRL|KEY_SHIFT|KEY_F5, + KEY_CTRLSHIFTF6 =KEY_CTRL|KEY_SHIFT|KEY_F6, + KEY_CTRLSHIFTF7 =KEY_CTRL|KEY_SHIFT|KEY_F7, + KEY_CTRLSHIFTF8 =KEY_CTRL|KEY_SHIFT|KEY_F8, + KEY_CTRLSHIFTF9 =KEY_CTRL|KEY_SHIFT|KEY_F9, + KEY_CTRLSHIFTF10 =KEY_CTRL|KEY_SHIFT|KEY_F10, + KEY_CTRLSHIFTF11 =KEY_CTRL|KEY_SHIFT|KEY_F11, + KEY_CTRLSHIFTF12 =KEY_CTRL|KEY_SHIFT|KEY_F12, + + KEY_ALTSHIFTF1 =KEY_ALT|KEY_SHIFT|KEY_F1, + KEY_ALTSHIFTF2 =KEY_ALT|KEY_SHIFT|KEY_F2, + KEY_ALTSHIFTF3 =KEY_ALT|KEY_SHIFT|KEY_F3, + KEY_ALTSHIFTF4 =KEY_ALT|KEY_SHIFT|KEY_F4, + KEY_ALTSHIFTF5 =KEY_ALT|KEY_SHIFT|KEY_F5, + KEY_ALTSHIFTF6 =KEY_ALT|KEY_SHIFT|KEY_F6, + KEY_ALTSHIFTF7 =KEY_ALT|KEY_SHIFT|KEY_F7, + KEY_ALTSHIFTF8 =KEY_ALT|KEY_SHIFT|KEY_F8, + KEY_ALTSHIFTF9 =KEY_ALT|KEY_SHIFT|KEY_F9, + KEY_ALTSHIFTF10 =KEY_ALT|KEY_SHIFT|KEY_F10, + KEY_ALTSHIFTF11 =KEY_ALT|KEY_SHIFT|KEY_F11, + KEY_ALTSHIFTF12 =KEY_ALT|KEY_SHIFT|KEY_F12, + + KEY_CTRLALTF1 =KEY_CTRL|KEY_ALT|KEY_F1, + KEY_CTRLALTF2 =KEY_CTRL|KEY_ALT|KEY_F2, + KEY_CTRLALTF3 =KEY_CTRL|KEY_ALT|KEY_F3, + KEY_CTRLALTF4 =KEY_CTRL|KEY_ALT|KEY_F4, + KEY_CTRLALTF5 =KEY_CTRL|KEY_ALT|KEY_F5, + KEY_CTRLALTF6 =KEY_CTRL|KEY_ALT|KEY_F6, + KEY_CTRLALTF7 =KEY_CTRL|KEY_ALT|KEY_F7, + KEY_CTRLALTF8 =KEY_CTRL|KEY_ALT|KEY_F8, + KEY_CTRLALTF9 =KEY_CTRL|KEY_ALT|KEY_F9, + KEY_CTRLALTF10 =KEY_CTRL|KEY_ALT|KEY_F10, + KEY_CTRLALTF11 =KEY_CTRL|KEY_ALT|KEY_F11, + KEY_CTRLALTF12 =KEY_CTRL|KEY_ALT|KEY_F12, + + KEY_CTRLHOME =KEY_CTRL|KEY_HOME, + KEY_CTRLUP =KEY_CTRL|KEY_UP, + KEY_CTRLPGUP =KEY_CTRL|KEY_PGUP, + KEY_CTRLLEFT =KEY_CTRL|KEY_LEFT, + KEY_CTRLRIGHT =KEY_CTRL|KEY_RIGHT, + KEY_CTRLEND =KEY_CTRL|KEY_END, + KEY_CTRLDOWN =KEY_CTRL|KEY_DOWN, + KEY_CTRLPGDN =KEY_CTRL|KEY_PGDN, + KEY_CTRLINS =KEY_CTRL|KEY_INS, + KEY_CTRLDEL =KEY_CTRL|KEY_DEL, + KEY_CTRLNUMDEL =KEY_CTRL|KEY_NUMDEL, + KEY_CTRLDECIMAL =KEY_CTRL|KEY_DECIMAL, + + KEY_SHIFTHOME =KEY_SHIFT|KEY_HOME, + KEY_SHIFTUP =KEY_SHIFT|KEY_UP, + KEY_SHIFTPGUP =KEY_SHIFT|KEY_PGUP, + KEY_SHIFTLEFT =KEY_SHIFT|KEY_LEFT, + KEY_SHIFTRIGHT =KEY_SHIFT|KEY_RIGHT, + KEY_SHIFTEND =KEY_SHIFT|KEY_END, + KEY_SHIFTDOWN =KEY_SHIFT|KEY_DOWN, + KEY_SHIFTPGDN =KEY_SHIFT|KEY_PGDN, + KEY_SHIFTINS =KEY_SHIFT|KEY_INS, + KEY_SHIFTDEL =KEY_SHIFT|KEY_DEL, + KEY_SHIFTNUMDEL =KEY_SHIFT|KEY_NUMDEL, + KEY_SHIFTDECIMAL =KEY_SHIFT|KEY_DECIMAL, + + KEY_ALTHOME =KEY_ALT|KEY_HOME, + KEY_ALTUP =KEY_ALT|KEY_UP, + KEY_ALTPGUP =KEY_ALT|KEY_PGUP, + KEY_ALTLEFT =KEY_ALT|KEY_LEFT, + KEY_ALTRIGHT =KEY_ALT|KEY_RIGHT, + KEY_ALTEND =KEY_ALT|KEY_END, + KEY_ALTDOWN =KEY_ALT|KEY_DOWN, + KEY_ALTPGDN =KEY_ALT|KEY_PGDN, + KEY_ALTINS =KEY_ALT|KEY_INS, + KEY_ALTDEL =KEY_ALT|KEY_DEL, + KEY_ALTNUMDEL =KEY_ALT|KEY_NUMDEL, + KEY_ALTDECIMAL =KEY_ALT|KEY_DECIMAL, + + KEY_CTRLSHIFTHOME =KEY_CTRL|KEY_SHIFT|KEY_HOME, + KEY_CTRLSHIFTUP =KEY_CTRL|KEY_SHIFT|KEY_UP, + KEY_CTRLSHIFTPGUP =KEY_CTRL|KEY_SHIFT|KEY_PGUP, + KEY_CTRLSHIFTLEFT =KEY_CTRL|KEY_SHIFT|KEY_LEFT, + KEY_CTRLSHIFTRIGHT =KEY_CTRL|KEY_SHIFT|KEY_RIGHT, + KEY_CTRLSHIFTEND =KEY_CTRL|KEY_SHIFT|KEY_END, + KEY_CTRLSHIFTDOWN =KEY_CTRL|KEY_SHIFT|KEY_DOWN, + KEY_CTRLSHIFTPGDN =KEY_CTRL|KEY_SHIFT|KEY_PGDN, + KEY_CTRLSHIFTINS =KEY_CTRL|KEY_SHIFT|KEY_INS, + KEY_CTRLSHIFTDEL =KEY_CTRL|KEY_SHIFT|KEY_DEL, + KEY_CTRLSHIFTNUMDEL =KEY_CTRL|KEY_SHIFT|KEY_NUMDEL, + KEY_CTRLSHIFTDECIMAL =KEY_CTRL|KEY_SHIFT|KEY_DECIMAL, + + KEY_ALTSHIFTHOME =KEY_ALT|KEY_SHIFT|KEY_HOME, + KEY_ALTSHIFTUP =KEY_ALT|KEY_SHIFT|KEY_UP, + KEY_ALTSHIFTPGUP =KEY_ALT|KEY_SHIFT|KEY_PGUP, + KEY_ALTSHIFTLEFT =KEY_ALT|KEY_SHIFT|KEY_LEFT, + KEY_ALTSHIFTRIGHT =KEY_ALT|KEY_SHIFT|KEY_RIGHT, + KEY_ALTSHIFTEND =KEY_ALT|KEY_SHIFT|KEY_END, + KEY_ALTSHIFTDOWN =KEY_ALT|KEY_SHIFT|KEY_DOWN, + KEY_ALTSHIFTPGDN =KEY_ALT|KEY_SHIFT|KEY_PGDN, + KEY_ALTSHIFTINS =KEY_ALT|KEY_SHIFT|KEY_INS, + KEY_ALTSHIFTDEL =KEY_ALT|KEY_SHIFT|KEY_DEL, + KEY_ALTSHIFTNUMDEL =KEY_ALT|KEY_SHIFT|KEY_NUMDEL, + KEY_ALTSHIFTDECIMAL =KEY_ALT|KEY_SHIFT|KEY_DECIMAL, + + KEY_CTRLALTHOME =KEY_CTRL|KEY_ALT|KEY_HOME, + KEY_CTRLALTUP =KEY_CTRL|KEY_ALT|KEY_UP, + KEY_CTRLALTPGUP =KEY_CTRL|KEY_ALT|KEY_PGUP, + KEY_CTRLALTLEFT =KEY_CTRL|KEY_ALT|KEY_LEFT, + KEY_CTRLALTRIGHT =KEY_CTRL|KEY_ALT|KEY_RIGHT, + KEY_CTRLALTEND =KEY_CTRL|KEY_ALT|KEY_END, + KEY_CTRLALTDOWN =KEY_CTRL|KEY_ALT|KEY_DOWN, + KEY_CTRLALTPGDN =KEY_CTRL|KEY_ALT|KEY_PGDN, + KEY_CTRLALTINS =KEY_CTRL|KEY_ALT|KEY_INS, + + KEY_CTRLNUMPAD0 =KEY_CTRL|KEY_NUMPAD0, + KEY_CTRLNUMPAD1 =KEY_CTRL|KEY_NUMPAD1, + KEY_CTRLNUMPAD2 =KEY_CTRL|KEY_NUMPAD2, + KEY_CTRLNUMPAD3 =KEY_CTRL|KEY_NUMPAD3, + KEY_CTRLNUMPAD4 =KEY_CTRL|KEY_NUMPAD4, + KEY_CTRLNUMPAD5 =KEY_CTRL|KEY_NUMPAD5, + KEY_CTRLNUMPAD6 =KEY_CTRL|KEY_NUMPAD6, + KEY_CTRLNUMPAD7 =KEY_CTRL|KEY_NUMPAD7, + KEY_CTRLNUMPAD8 =KEY_CTRL|KEY_NUMPAD8, + KEY_CTRLNUMPAD9 =KEY_CTRL|KEY_NUMPAD9, + + KEY_SHIFTNUMPAD0 =KEY_SHIFT|KEY_NUMPAD0, + KEY_SHIFTNUMPAD1 =KEY_SHIFT|KEY_NUMPAD1, + KEY_SHIFTNUMPAD2 =KEY_SHIFT|KEY_NUMPAD2, + KEY_SHIFTNUMPAD3 =KEY_SHIFT|KEY_NUMPAD3, + KEY_SHIFTNUMPAD4 =KEY_SHIFT|KEY_NUMPAD4, + KEY_SHIFTNUMPAD5 =KEY_SHIFT|KEY_NUMPAD5, + KEY_SHIFTNUMPAD6 =KEY_SHIFT|KEY_NUMPAD6, + KEY_SHIFTNUMPAD7 =KEY_SHIFT|KEY_NUMPAD7, + KEY_SHIFTNUMPAD8 =KEY_SHIFT|KEY_NUMPAD8, + KEY_SHIFTNUMPAD9 =KEY_SHIFT|KEY_NUMPAD9, + + KEY_CTRLSHIFTNUMPAD0 =KEY_CTRL|KEY_SHIFT|KEY_NUMPAD0, + KEY_CTRLSHIFTNUMPAD1 =KEY_CTRL|KEY_SHIFT|KEY_NUMPAD1, + KEY_CTRLSHIFTNUMPAD2 =KEY_CTRL|KEY_SHIFT|KEY_NUMPAD2, + KEY_CTRLSHIFTNUMPAD3 =KEY_CTRL|KEY_SHIFT|KEY_NUMPAD3, + KEY_CTRLSHIFTNUMPAD4 =KEY_CTRL|KEY_SHIFT|KEY_NUMPAD4, + KEY_CTRLSHIFTNUMPAD5 =KEY_CTRL|KEY_SHIFT|KEY_NUMPAD5, + KEY_CTRLSHIFTNUMPAD6 =KEY_CTRL|KEY_SHIFT|KEY_NUMPAD6, + KEY_CTRLSHIFTNUMPAD7 =KEY_CTRL|KEY_SHIFT|KEY_NUMPAD7, + KEY_CTRLSHIFTNUMPAD8 =KEY_CTRL|KEY_SHIFT|KEY_NUMPAD8, + KEY_CTRLSHIFTNUMPAD9 =KEY_CTRL|KEY_SHIFT|KEY_NUMPAD9, + + KEY_CTRLALTNUMPAD0 =KEY_CTRL|KEY_ALT|KEY_NUMPAD0, + KEY_CTRLALTNUMPAD1 =KEY_CTRL|KEY_ALT|KEY_NUMPAD1, + KEY_CTRLALTNUMPAD2 =KEY_CTRL|KEY_ALT|KEY_NUMPAD2, + KEY_CTRLALTNUMPAD3 =KEY_CTRL|KEY_ALT|KEY_NUMPAD3, + KEY_CTRLALTNUMPAD4 =KEY_CTRL|KEY_ALT|KEY_NUMPAD4, + KEY_CTRLALTNUMPAD5 =KEY_CTRL|KEY_ALT|KEY_NUMPAD5, + KEY_CTRLALTNUMPAD6 =KEY_CTRL|KEY_ALT|KEY_NUMPAD6, + KEY_CTRLALTNUMPAD7 =KEY_CTRL|KEY_ALT|KEY_NUMPAD7, + KEY_CTRLALTNUMPAD8 =KEY_CTRL|KEY_ALT|KEY_NUMPAD8, + KEY_CTRLALTNUMPAD9 =KEY_CTRL|KEY_ALT|KEY_NUMPAD9, + + KEY_ALTSHIFTNUMPAD0 =KEY_ALT|KEY_SHIFT|KEY_NUMPAD0, + KEY_ALTSHIFTNUMPAD1 =KEY_ALT|KEY_SHIFT|KEY_NUMPAD1, + KEY_ALTSHIFTNUMPAD2 =KEY_ALT|KEY_SHIFT|KEY_NUMPAD2, + KEY_ALTSHIFTNUMPAD3 =KEY_ALT|KEY_SHIFT|KEY_NUMPAD3, + KEY_ALTSHIFTNUMPAD4 =KEY_ALT|KEY_SHIFT|KEY_NUMPAD4, + KEY_ALTSHIFTNUMPAD5 =KEY_ALT|KEY_SHIFT|KEY_NUMPAD5, + KEY_ALTSHIFTNUMPAD6 =KEY_ALT|KEY_SHIFT|KEY_NUMPAD6, + KEY_ALTSHIFTNUMPAD7 =KEY_ALT|KEY_SHIFT|KEY_NUMPAD7, + KEY_ALTSHIFTNUMPAD8 =KEY_ALT|KEY_SHIFT|KEY_NUMPAD8, + KEY_ALTSHIFTNUMPAD9 =KEY_ALT|KEY_SHIFT|KEY_NUMPAD9, + + KEY_CTRLSLASH =KEY_CTRL|KEY_SLASH, + KEY_CTRLBACKSLASH =KEY_CTRL|KEY_BACKSLASH, + KEY_CTRLCLEAR =KEY_CTRL|KEY_CLEAR, + KEY_CTRLSHIFTCLEAR =KEY_CTRL|KEY_SHIFT|KEY_CLEAR, + KEY_CTRLALTCLEAR =KEY_CTRL|KEY_ALT|KEY_CLEAR, + KEY_CTRLADD =KEY_CTRL|KEY_ADD, + KEY_SHIFTADD =KEY_SHIFT|KEY_ADD, + + KEY_CTRLSUBTRACT =KEY_CTRL|KEY_SUBTRACT, + KEY_ALTSUBTRACT =KEY_ALT|KEY_SUBTRACT, + KEY_SHIFTSUBTRACT =KEY_SHIFT|KEY_SUBTRACT, + KEY_CTRLMULTIPLY =KEY_CTRL|KEY_MULTIPLY, + + KEY_CTRLBS =KEY_CTRL|KEY_BS, + KEY_ALTBS =KEY_ALT|KEY_BS, + KEY_CTRLSHIFTBS =KEY_CTRL|KEY_SHIFT|KEY_BS, + KEY_SHIFTBS =KEY_SHIFT|KEY_BS, + + KEY_CTRLSHIFTTAB =KEY_CTRL|KEY_SHIFT|KEY_TAB, + KEY_CTRLTAB =KEY_CTRL|KEY_TAB, + KEY_SHIFTTAB =KEY_SHIFT|KEY_TAB, + + KEY_CTRLENTER =KEY_CTRL|KEY_ENTER, + KEY_SHIFTENTER =KEY_SHIFT|KEY_ENTER, + KEY_ALTSHIFTENTER =KEY_ALT|KEY_SHIFT|KEY_ENTER, + KEY_CTRLALTENTER =KEY_CTRL|KEY_ALT|KEY_ENTER, + KEY_CTRLSHIFTENTER =KEY_CTRL|KEY_SHIFT|KEY_ENTER, + + KEY_CTRLNUMENTER =KEY_CTRL|KEY_NUMENTER, + KEY_SHIFTNUMENTER =KEY_SHIFT|KEY_NUMENTER, + KEY_ALTSHIFTNUMENTER =KEY_ALT|KEY_SHIFT|KEY_NUMENTER, + KEY_CTRLALTNUMENTER =KEY_CTRL|KEY_ALT|KEY_NUMENTER, + KEY_CTRLSHIFTNUMENTER =KEY_CTRL|KEY_SHIFT|KEY_NUMENTER, + + KEY_CTRLAPPS =KEY_CTRL|KEY_APPS, + KEY_ALTAPPS =KEY_ALT|KEY_APPS, + KEY_SHIFTAPPS =KEY_SHIFT|KEY_APPS, + KEY_CTRLSHIFTAPPS =KEY_CTRL|KEY_SHIFT|KEY_APPS, + KEY_ALTSHIFTAPPS =KEY_ALT|KEY_SHIFT|KEY_APPS, + KEY_CTRLALTAPPS =KEY_CTRL|KEY_ALT|KEY_APPS, + + KEY_CTRLSPACE =KEY_CTRL|KEY_SPACE, + KEY_SHIFTSPACE =KEY_SHIFT|KEY_SPACE, + KEY_CTRLSHIFTSPACE =KEY_CTRL|KEY_SHIFT|KEY_SPACE, + + KEY_ALT_BASE =KEY_ALT, + KEY_ALTSHIFT_BASE =KEY_ALTSHIFT +}; + +#ifdef FAR_USE_INTERNALS +#define IS_INTERNAL_KEY_REAL(Key)\ + (\ + (Key)==KEY_MSWHEEL_UP||\ + (Key)==KEY_MSWHEEL_DOWN||\ + (Key)==KEY_NUMDEL||\ + (Key)==KEY_NUMENTER||\ + (Key)==KEY_MSWHEEL_LEFT||\ + (Key)==KEY_MSWHEEL_RIGHT||\ + (Key)==KEY_MSLCLICK||\ + (Key)==KEY_MSRCLICK||\ + (Key)==KEY_MSM1CLICK||\ + (Key)==KEY_MSM2CLICK||\ + (Key)==KEY_MSM3CLICK\ + ) +#endif // END FAR_USE_INTERNALS + +#endif // __FARKEYS_HPP__ diff --git a/far2l/src/console/lockscrn.cpp b/far2l/src/console/lockscrn.cpp new file mode 100644 index 00000000..1d7dea4e --- /dev/null +++ b/far2l/src/console/lockscrn.cpp @@ -0,0 +1,50 @@ +/* +lockscrn.cpp + +class LockScreen +*/ +/* +Copyright (c) 1996 Eugene Roshal +Copyright (c) 2000 Far Group +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "headers.hpp" + + +#include "lockscrn.hpp" +#include "scrbuf.hpp" + +LockScreen::LockScreen() +{ + ScrBuf.Lock(); +} + + +LockScreen::~LockScreen() +{ + ScrBuf.Unlock(); + ScrBuf.Flush(); +} diff --git a/far2l/src/console/lockscrn.hpp b/far2l/src/console/lockscrn.hpp new file mode 100644 index 00000000..f5070cde --- /dev/null +++ b/far2l/src/console/lockscrn.hpp @@ -0,0 +1,41 @@ +#pragma once + +/* +lockscrn.hpp + +class LockScreen +*/ +/* +Copyright (c) 1996 Eugene Roshal +Copyright (c) 2000 Far Group +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +class LockScreen +{ + public: + LockScreen(); + ~LockScreen(); +}; diff --git a/far2l/src/console/palette.cpp b/far2l/src/console/palette.cpp new file mode 100644 index 00000000..931028f2 --- /dev/null +++ b/far2l/src/console/palette.cpp @@ -0,0 +1,422 @@ +/* +palette.cpp + +Таблица цветов +*/ +/* +Copyright (c) 1996 Eugene Roshal +Copyright (c) 2000 Far Group +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "headers.hpp" + + +#include "palette.hpp" +#include "colors.hpp" + +unsigned char DefaultPalette[]= +{ + F_WHITE|B_CYAN, // COL_MENUTEXT, + F_WHITE|B_BLACK, // COL_MENUSELECTEDTEXT, + F_YELLOW|B_CYAN, // COL_MENUHIGHLIGHT, + F_YELLOW|B_BLACK, // COL_MENUSELECTEDHIGHLIGHT, + F_WHITE|B_CYAN, // COL_MENUBOX, + F_WHITE|B_CYAN, // COL_MENUTITLE, + + F_BLACK|B_CYAN, // COL_HMENUTEXT, + F_WHITE|B_BLACK, // COL_HMENUSELECTEDTEXT, + F_YELLOW|B_CYAN, // COL_HMENUHIGHLIGHT, + F_YELLOW|B_BLACK, // COL_HMENUSELECTEDHIGHLIGHT, + + F_LIGHTCYAN|B_BLUE, // COL_PANELTEXT, + F_YELLOW|B_BLUE, // COL_PANELSELECTEDTEXT, + F_LIGHTGRAY|B_BLUE, // COL_PANELHIGHLIGHTTEXT, + F_YELLOW|B_BLUE, // COL_PANELINFOTEXT, + F_BLACK|B_CYAN, // COL_PANELCURSOR, + F_YELLOW|B_CYAN, // COL_PANELSELECTEDCURSOR, + F_LIGHTCYAN|B_BLUE, // COL_PANELTITLE, + F_BLACK|B_CYAN, // COL_PANELSELECTEDTITLE, + F_YELLOW|B_BLUE, // COL_PANELCOLUMNTITLE, + F_LIGHTCYAN|B_BLUE, // COL_PANELTOTALINFO, + F_YELLOW|B_CYAN, // COL_PANELSELECTEDINFO, + + F_BLACK|B_LIGHTGRAY, // COL_DIALOGTEXT, + F_YELLOW|B_LIGHTGRAY, // COL_DIALOGHIGHLIGHTTEXT, + F_BLACK|B_LIGHTGRAY, // COL_DIALOGBOX, + F_BLACK|B_LIGHTGRAY, // COL_DIALOGBOXTITLE, + F_YELLOW|B_LIGHTGRAY, // COL_DIALOGHIGHLIGHTBOXTITLE, + F_BLACK|B_CYAN, // COL_DIALOGEDIT, + F_BLACK|B_LIGHTGRAY, // COL_DIALOGBUTTON, + F_BLACK|B_CYAN, // COL_DIALOGSELECTEDBUTTON, + F_YELLOW|B_LIGHTGRAY, // COL_DIALOGHIGHLIGHTBUTTON, + F_YELLOW|B_CYAN, // COL_DIALOGHIGHLIGHTSELECTEDBUTTON, + + F_BLACK|B_LIGHTGRAY, // COL_DIALOGLISTTEXT, + F_WHITE|B_BLACK, // COL_DIALOGLISTSELECTEDTEXT, + F_YELLOW|B_LIGHTGRAY, // COL_DIALOGLISTHIGHLIGHT, + F_YELLOW|B_BLACK, // COL_DIALOGLISTSELECTEDHIGHLIGHT, + + F_WHITE|B_RED, // COL_WARNDIALOGTEXT, + F_YELLOW|B_RED, // COL_WARNDIALOGHIGHLIGHTTEXT, + F_WHITE|B_RED, // COL_WARNDIALOGBOX, + F_WHITE|B_RED, // COL_WARNDIALOGBOXTITLE, + F_YELLOW|B_RED, // COL_WARNDIALOGHIGHLIGHTBOXTITLE, + F_BLACK|B_CYAN, // COL_WARNDIALOGEDIT, + F_WHITE|B_RED, // COL_WARNDIALOGBUTTON, + F_BLACK|B_LIGHTGRAY, // COL_WARNDIALOGSELECTEDBUTTON, + F_YELLOW|B_RED, // COL_WARNDIALOGHIGHLIGHTBUTTON, + F_YELLOW|B_LIGHTGRAY, // COL_WARNDIALOGHIGHLIGHTSELECTEDBUTTON, + + F_LIGHTGRAY|B_BLACK, // COL_KEYBARNUM, + F_BLACK|B_CYAN, // COL_KEYBARTEXT, + F_LIGHTGRAY|B_BLACK, // COL_KEYBARBACKGROUND, + + F_LIGHTGRAY|B_BLACK, // COL_COMMANDLINE, + + F_BLACK|B_CYAN, // COL_CLOCK, + + F_LIGHTCYAN|B_BLUE, // COL_VIEWERTEXT, + F_BLACK|B_CYAN, // COL_VIEWERSELECTEDTEXT, + F_BLACK|B_CYAN, // COL_VIEWERSTATUS, + + F_LIGHTCYAN|B_BLUE, // COL_EDITORTEXT, + F_BLACK|B_CYAN, // COL_EDITORSELECTEDTEXT, + F_BLACK|B_CYAN, // COL_EDITORSTATUS, + + F_BLACK|B_CYAN, // COL_HELPTEXT, + F_WHITE|B_CYAN, // COL_HELPHIGHLIGHTTEXT, + F_YELLOW|B_CYAN, // COL_HELPTOPIC, + F_WHITE|B_BLACK, // COL_HELPSELECTEDTOPIC, + F_BLACK|B_CYAN, // COL_HELPBOX, + F_BLACK|B_CYAN, // COL_HELPBOXTITLE, + + F_YELLOW|B_CYAN, // COL_PANELDRAGTEXT, + F_LIGHTGRAY|B_CYAN, // COL_DIALOGEDITUNCHANGED, + F_LIGHTCYAN|B_BLUE, // COL_PANELSCROLLBAR, + F_BLACK|B_CYAN, // COL_HELPSCROLLBAR, + F_LIGHTCYAN|B_BLUE, // COL_PANELBOX, + F_LIGHTCYAN|B_BLACK, // COL_PANELSCREENSNUMBER, + F_WHITE|B_BLACK, // COL_DIALOGEDITSELECTED, + F_BLACK|B_CYAN, // COL_COMMANDLINESELECTED, + F_YELLOW|B_BLUE, // COL_VIEWERARROWS, + + 0, // COL_RESERVED0 // Служебная позиция: 1 - это есть default color + + F_BLACK|B_LIGHTGRAY, // COL_DIALOGLISTSCROLLBAR, + F_WHITE|B_CYAN, // COL_MENUSCROLLBAR, + F_LIGHTCYAN|B_BLUE, // COL_VIEWERSCROLLBAR, + + F_LIGHTGRAY|B_BLACK, // COL_COMMANDLINEPREFIX, + + F_DARKGRAY|B_LIGHTGRAY, // COL_DIALOGDISABLED, + F_DARKGRAY|B_CYAN, // COL_DIALOGEDITDISABLED, + F_DARKGRAY|B_LIGHTGRAY, // COL_DIALOGLISTDISABLED, + + F_DARKGRAY|B_RED, // COL_WARNDIALOGDISABLED, + F_DARKGRAY|B_CYAN, // COL_WARNDIALOGEDITDISABLED, + F_DARKGRAY|B_RED, // COL_WARNDIALOGLISTDISABLED, + + F_DARKGRAY|B_CYAN, // COL_MENUDISABLEDTEXT, + + F_BLACK|B_CYAN, // COL_EDITORCLOCK, + F_BLACK|B_CYAN, // COL_VIEWERCLOCK, + + F_BLACK|B_LIGHTGRAY, // COL_DIALOGLISTTITLE + F_BLACK|B_LIGHTGRAY, // COL_DIALOGLISTBOX, + + F_WHITE|B_BLACK, // COL_WARNDIALOGEDITSELECTED, + F_LIGHTGRAY|B_CYAN, // COL_WARNDIALOGEDITUNCHANGED, + + F_WHITE|B_CYAN, // COL_DIALOGCBOXTEXT, + F_WHITE|B_BLACK, // COL_DIALOGCBOXSELECTEDTEXT, + F_YELLOW|B_CYAN, // COL_DIALOGCBOXHIGHLIGHT, + F_YELLOW|B_BLACK, // COL_DIALOGCBOXSELECTEDHIGHLIGHT, + F_WHITE|B_CYAN, // COL_DIALOGCBOXBOX, + F_WHITE|B_CYAN, // COL_DIALOGCBOXTITLE, + F_DARKGRAY|B_CYAN, // COL_DIALOGCBOXDISABLED, + F_WHITE|B_CYAN, // COL_DIALOGCBOXSCROLLBAR, + + F_WHITE|B_RED, // COL_WARNDIALOGLISTTEXT, + F_BLACK|B_LIGHTGRAY, // COL_WARNDIALOGLISTSELECTEDTEXT, + F_YELLOW|B_RED, // COL_WARNDIALOGLISTHIGHLIGHT, + F_YELLOW|B_LIGHTGRAY, // COL_WARNDIALOGLISTSELECTEDHIGHLIGHT, + F_WHITE|B_RED, // COL_WARNDIALOGLISTBOX, + F_WHITE|B_RED, // COL_WARNDIALOGLISTTITLE, + F_WHITE|B_RED, // COL_WARNDIALOGLISTSCROLLBAR, + + F_WHITE|B_CYAN, // COL_WARNDIALOGCBOXTEXT, + F_WHITE|B_BLACK, // COL_WARNDIALOGCBOXSELECTEDTEXT, + F_YELLOW|B_CYAN, // COL_WARNDIALOGCBOXHIGHLIGHT, + F_YELLOW|B_BLACK, // COL_WARNDIALOGCBOXSELECTEDHIGHLIGHT, + F_WHITE|B_CYAN, // COL_WARNDIALOGCBOXBOX, + F_WHITE|B_CYAN, // COL_WARNDIALOGCBOXTITLE, + F_DARKGRAY|B_CYAN, // COL_WARNDIALOGCBOXDISABLED, + F_WHITE|B_CYAN, // COL_WARNDIALOGCBOXSCROLLBAR, + + F_YELLOW|B_LIGHTGRAY, // COL_DIALOGLISTARROWS, + F_DARKGRAY|B_LIGHTGRAY, // COL_DIALOGLISTARROWSDISABLED, + F_YELLOW|B_BLACK, // COL_DIALOGLISTARROWSSELECTED, + F_YELLOW|B_CYAN, // COL_DIALOGCOMBOARROWS, + F_DARKGRAY|B_CYAN, // COL_DIALOGCOMBOARROWSDISABLED, + F_YELLOW|B_BLACK, // COL_DIALOGCOMBOARROWSSELECTED, + F_YELLOW|B_RED, // COL_WARNDIALOGLISTARROWS, + F_DARKGRAY|B_RED, // COL_WARNDIALOGLISTARROWSDISABLED, + F_YELLOW|B_LIGHTGRAY, // COL_WARNDIALOGLISTARROWSSELECTED, + F_YELLOW|B_CYAN, // COL_WARNDIALOGCOMBOARROWS, + F_DARKGRAY|B_CYAN, // COL_WARNDIALOGCOMBOARROWSDISABLED, + F_YELLOW|B_BLACK, // COL_WARNDIALOGCOMBOARROWSSELECTED, + F_YELLOW|B_CYAN, // COL_MENUARROWS, + F_DARKGRAY|B_CYAN, // COL_MENUARROWSDISABLED, + F_YELLOW|B_BLACK, // COL_MENUARROWSSELECTED, + F_LIGHTGRAY|B_BLACK, // COL_COMMANDLINEUSERSCREEN, + F_LIGHTCYAN|B_BLUE, // COL_EDITORSCROLLBAR, + + F_DARKGRAY|B_CYAN, // COL_MENUGRAYTEXT, + F_LIGHTGRAY|B_BLACK, // COL_MENUSELECTEDGRAYTEXT, + F_DARKGRAY|B_CYAN, // COL_DIALOGCOMBOGRAY, + F_LIGHTGRAY|B_BLACK, // COL_DIALOGCOMBOSELECTEDGRAYTEXT, + F_DARKGRAY|B_LIGHTGRAY, // COL_DIALOGLISTGRAY, + F_LIGHTGRAY|B_BLACK, // COL_DIALOGLISTSELECTEDGRAYTEXT, + F_DARKGRAY|B_CYAN, // COL_WARNDIALOGCOMBOGRAY, + F_LIGHTGRAY|B_BLACK, // COL_WARNDIALOGCOMBOSELECTEDGRAYTEXT, + F_DARKGRAY|B_RED, // COL_WARNDIALOGLISTGRAY, + F_BLACK|B_LIGHTGRAY, // COL_WARNDIALOGLISTSELECTEDGRAYTEXT, + + F_BLACK|B_LIGHTGRAY, // COL_DIALOGDEFAULTBUTTON, + F_BLACK|B_CYAN, // COL_DIALOGSELECTEDDEFAULTBUTTON, + F_YELLOW|B_LIGHTGRAY, // COL_DIALOGHIGHLIGHTDEFAULTBUTTON, + F_YELLOW|B_CYAN, // COL_DIALOGHIGHLIGHTSELECTEDDEFAULTBUTTON, + F_WHITE|B_RED, // COL_WARNDIALOGDEFAULTBUTTON, + F_BLACK|B_LIGHTGRAY, // COL_WARNDIALOGSELECTEDDEFAULTBUTTON, + F_YELLOW|B_RED, // COL_WARNDIALOGHIGHLIGHTDEFAULTBUTTON, + F_YELLOW|B_LIGHTGRAY, // COL_WARNDIALOGHIGHLIGHTSELECTEDDEFAULTBUTTON, +}; + + +unsigned char BlackPalette[]= +{ + F_BLACK|B_LIGHTGRAY, // COL_MENUTEXT, + F_LIGHTGRAY|B_BLACK, // COL_MENUSELECTEDTEXT, + F_WHITE|B_LIGHTGRAY, // COL_MENUHIGHLIGHT, + F_WHITE|B_BLACK, // COL_MENUSELECTEDHIGHLIGHT, + F_BLACK|B_LIGHTGRAY, // COL_MENUBOX, + F_BLACK|B_LIGHTGRAY, // COL_MENUTITLE, + + F_BLACK|B_LIGHTGRAY, // COL_HMENUTEXT, + F_LIGHTGRAY|B_BLACK, // COL_HMENUSELECTEDTEXT, + F_WHITE|B_LIGHTGRAY, // COL_HMENUHIGHLIGHT, + F_WHITE|B_BLACK, // COL_HMENUSELECTEDHIGHLIGHT, + + F_LIGHTGRAY|B_BLACK, // COL_PANELTEXT, + F_WHITE|B_BLACK, // COL_PANELSELECTEDTEXT, + F_LIGHTGRAY|B_BLACK, // COL_PANELHIGHLIGHTTEXT, + F_WHITE|B_BLACK, // COL_PANELINFOTEXT, + F_BLACK|B_LIGHTGRAY, // COL_PANELCURSOR, + F_WHITE|B_LIGHTGRAY, // COL_PANELSELECTEDCURSOR, + F_LIGHTGRAY|B_BLACK, // COL_PANELTITLE, + F_BLACK|B_LIGHTGRAY, // COL_PANELSELECTEDTITLE, + F_WHITE|B_BLACK, // COL_PANELCOLUMNTITLE, + F_LIGHTGRAY|B_BLACK, // COL_PANELTOTALINFO, + F_BLACK|B_LIGHTGRAY, // COL_PANELSELECTEDINFO, + + F_BLACK|B_LIGHTGRAY, // COL_DIALOGTEXT, + F_WHITE|B_LIGHTGRAY, // COL_DIALOGHIGHLIGHTTEXT, + F_BLACK|B_LIGHTGRAY, // COL_DIALOGBOX, + F_BLACK|B_LIGHTGRAY, // COL_DIALOGBOXTITLE, + F_WHITE|B_BLACK, // COL_DIALOGHIGHLIGHTBOXTITLE, + F_LIGHTGRAY|B_BLACK, // COL_DIALOGEDIT, + F_BLACK|B_LIGHTGRAY, // COL_DIALOGBUTTON, + F_LIGHTGRAY|B_BLACK, // COL_DIALOGSELECTEDBUTTON, + F_WHITE|B_LIGHTGRAY, // COL_DIALOGHIGHLIGHTBUTTON, + F_WHITE|B_BLACK, // COL_DIALOGHIGHLIGHTSELECTEDBUTTON, + + F_BLACK|B_LIGHTGRAY, // COL_DIALOGLISTTEXT, + F_WHITE|B_BLACK, // COL_DIALOGLISTSELECTEDTEXT, + F_WHITE|B_LIGHTGRAY, // COL_DIALOGLISTHIGHLIGHT, + F_WHITE|B_BLACK, // COL_DIALOGLISTSELECTEDHIGHLIGHT, + + F_BLACK|B_LIGHTGRAY, // COL_WARNDIALOGTEXT, + F_WHITE|B_LIGHTGRAY, // COL_WARNDIALOGHIGHLIGHTTEXT, + F_BLACK|B_LIGHTGRAY, // COL_WARNDIALOGBOX, + F_BLACK|B_LIGHTGRAY, // COL_WARNDIALOGBOXTITLE, + F_WHITE|B_BLACK, // COL_WARNDIALOGHIGHLIGHTBOXTITLE, + F_LIGHTGRAY|B_BLACK, // COL_WARNDIALOGEDIT, + F_BLACK|B_LIGHTGRAY, // COL_WARNDIALOGBUTTON, + F_LIGHTGRAY|B_BLACK, // COL_WARNDIALOGSELECTEDBUTTON, + F_WHITE|B_LIGHTGRAY, // COL_WARNDIALOGHIGHLIGHTBUTTON, + F_WHITE|B_BLACK, // COL_WARNDIALOGHIGHLIGHTSELECTEDBUTTON, + + F_LIGHTGRAY|B_BLACK, // COL_KEYBARNUM, + F_BLACK|B_LIGHTGRAY, // COL_KEYBARTEXT, + F_LIGHTGRAY|B_BLACK, // COL_KEYBARBACKGROUND, + + F_LIGHTGRAY|B_BLACK, // COL_COMMANDLINE, + + F_BLACK|B_LIGHTGRAY, // COL_CLOCK, + + F_LIGHTGRAY|B_BLACK, // COL_VIEWERTEXT, + F_BLACK|B_LIGHTGRAY, // COL_VIEWERSELECTEDTEXT, + F_BLACK|B_LIGHTGRAY, // COL_VIEWERSTATUS, + + F_LIGHTGRAY|B_BLACK, // COL_EDITORTEXT, + F_BLACK|B_LIGHTGRAY, // COL_EDITORSELECTEDTEXT, + F_BLACK|B_LIGHTGRAY, // COL_EDITORSTATUS, + + F_LIGHTGRAY|B_BLACK, // COL_HELPTEXT, + F_LIGHTGRAY|B_BLACK, // COL_HELPHIGHLIGHTTEXT, + F_WHITE|B_BLACK, // COL_HELPTOPIC, + F_BLACK|B_LIGHTGRAY, // COL_HELPSELECTEDTOPIC, + F_LIGHTGRAY|B_BLACK, // COL_HELPBOX, + F_LIGHTGRAY|B_BLACK, // COL_HELPBOXTITLE, + + F_BLACK|B_LIGHTGRAY, // COL_PANELDRAGTEXT, + F_WHITE|B_BLACK, // COL_DIALOGEDITUNCHANGED, + F_LIGHTGRAY|B_BLACK, // COL_PANELSCROLLBAR, + F_LIGHTGRAY|B_BLACK, // COL_HELPSCROLLBAR, + F_LIGHTGRAY|B_BLACK, // COL_PANELBOX, + F_WHITE|B_BLACK, // COL_PANELSCREENSNUMBER, + F_BLACK|B_LIGHTGRAY, // COL_DIALOGEDITSELECTED, + F_BLACK|B_LIGHTGRAY, // COL_COMMANDLINESELECTED, + F_WHITE|B_BLACK, // COL_VIEWERARROWS, + + 1, // COL_RESERVED0 // Служебная позиция: 1 - это есть default color + + F_BLACK|B_LIGHTGRAY, // COL_DIALOGLISTSCROLLBAR, + F_BLACK|B_LIGHTGRAY, // COL_MENUSCROLLBAR, + F_LIGHTGRAY|B_BLACK, // COL_VIEWERSCROLLBAR, + + F_LIGHTGRAY|B_BLACK, // COL_COMMANDLINEPREFIX, + + F_LIGHTGRAY|B_BLACK, // COL_DIALOGDISABLED, + F_DARKGRAY|B_LIGHTGRAY, // COL_DIALOGEDITDISABLED, + F_DARKGRAY|B_LIGHTGRAY, // COL_DIALOGLISTDISABLED, + + F_DARKGRAY|B_LIGHTGRAY, // COL_WARNDIALOGDISABLED, + F_DARKGRAY|B_LIGHTGRAY, // COL_WARNDIALOGEDITDISABLED, + F_DARKGRAY|B_LIGHTGRAY, // COL_WARNDIALOGLISTDISABLED, + + F_DARKGRAY|B_LIGHTGRAY, // COL_MENUDISABLEDTEXT, + + F_BLACK|B_LIGHTGRAY, // COL_EDITORCLOCK, + F_BLACK|B_LIGHTGRAY, // COL_VIEWERCLOCK, + + F_BLACK|B_LIGHTGRAY, // COL_DIALOGLISTTITLE + F_BLACK|B_LIGHTGRAY, // COL_DIALOGLISTBOX, + + F_BLACK|B_WHITE, // COL_WARNDIALOGEDITSELECTED, + F_WHITE|B_BLACK, // COL_WARNDIALOGEDITUNCHANGED, + + F_BLACK|B_LIGHTGRAY, // COL_DIALOGCBOXTEXT, + F_LIGHTGRAY|B_BLACK, // COL_DIALOGCBOXSELECTEDTEXT, + F_WHITE|B_LIGHTGRAY, // COL_DIALOGCBOXHIGHLIGHT, + F_WHITE|B_BLACK, // COL_DIALOGCBOXSELECTEDHIGHLIGHT, + F_BLACK|B_LIGHTGRAY, // COL_DIALOGCBOXBOX, + F_BLACK|B_LIGHTGRAY, // COL_DIALOGCBOXTITLE, + F_DARKGRAY|B_LIGHTGRAY, // COL_DIALOGCBOXDISABLED, + F_BLACK|B_LIGHTGRAY, // COL_DIALOGCBOXSCROLLBAR, + + F_BLACK|B_LIGHTGRAY, // COL_WARNDIALOGLISTTEXT, + F_WHITE|B_BLACK, // COL_WARNDIALOGLISTSELECTEDTEXT, + F_WHITE|B_LIGHTGRAY, // COL_WARNDIALOGLISTHIGHLIGHT, + F_WHITE|B_BLACK, // COL_WARNDIALOGLISTSELECTEDHIGHLIGHT, + F_BLACK|B_LIGHTGRAY, // COL_WARNDIALOGLISTBOX, + F_BLACK|B_LIGHTGRAY, // COL_WARNDIALOGLISTTITLE, + F_BLACK|B_LIGHTGRAY, // COL_WARNDIALOGLISTSCROLLBAR, + + F_BLACK|B_LIGHTGRAY, // COL_WARNDIALOGCBOXTEXT, + F_WHITE|B_BLACK, // COL_WARNDIALOGCBOXSELECTEDTEXT, + F_WHITE|B_LIGHTGRAY, // COL_WARNDIALOGCBOXHIGHLIGHT, + F_WHITE|B_BLACK, // COL_WARNDIALOGCBOXSELECTEDHIGHLIGHT, + F_BLACK|B_LIGHTGRAY, // COL_WARNDIALOGCBOXBOX, + F_BLACK|B_LIGHTGRAY, // COL_WARNDIALOGCBOXTITLE, + F_DARKGRAY|B_LIGHTGRAY, // COL_WARNDIALOGCBOXDISABLED, + F_BLACK|B_LIGHTGRAY, // COL_WARNDIALOGCBOXSCROLLBAR, + + F_WHITE|B_LIGHTGRAY, // COL_DIALOGLISTARROWS, + F_DARKGRAY|B_LIGHTGRAY, // COL_DIALOGLISTARROWSDISABLED, + F_WHITE|B_BLACK, // COL_DIALOGLISTARROWSSELECTED, + F_WHITE|B_LIGHTGRAY, // COL_DIALOGCOMBOARROWS, + F_DARKGRAY|B_LIGHTGRAY, // COL_DIALOGCOMBOARROWSDISABLED, + F_WHITE|B_BLACK, // COL_DIALOGCOMBOARROWSSELECTED, + F_WHITE|B_LIGHTGRAY, // COL_WARNDIALOGLISTARROWS, + F_DARKGRAY|B_LIGHTGRAY, // COL_WARNDIALOGLISTARROWSDISABLED, + F_WHITE|B_BLACK, // COL_WARNDIALOGLISTARROWSSELECTED, + F_WHITE|B_LIGHTGRAY, // COL_WARNDIALOGCOMBOARROWS, + F_DARKGRAY|B_LIGHTGRAY, // COL_WARNDIALOGCOMBOARROWSDISABLED, + F_WHITE|B_BLACK, // COL_WARNDIALOGCOMBOARROWSSELECTED, + F_WHITE|B_LIGHTGRAY, // COL_MENUARROWS, + F_DARKGRAY|B_LIGHTGRAY, // COL_MENUARROWSDISABLED, + F_WHITE|B_BLACK, // COL_MENUARROWSSELECTED, + F_LIGHTGRAY|B_BLACK, // COL_COMMANDLINEUSERSCREEN, + F_LIGHTGRAY|B_BLACK, // COL_EDITORSCROLLBAR, + + F_DARKGRAY|B_LIGHTGRAY, // COL_MENUGRAYTEXT, + F_LIGHTGRAY|B_BLACK, // COL_MENUSELECTEDGRAYTEXT, + F_DARKGRAY|B_LIGHTGRAY, // COL_DIALOGCOMBOGRAY, + F_LIGHTGRAY|B_BLACK, // COL_DIALOGCOMBOSELECTEDGRAYTEXT, + F_DARKGRAY|B_LIGHTGRAY, // COL_DIALOGLISTGRAY, + F_WHITE|B_BLACK, // COL_DIALOGLISTSELECTEDGRAYTEXT, + F_DARKGRAY|B_LIGHTGRAY, // COL_WARNDIALOGCOMBOGRAY, + F_WHITE|B_BLACK, // COL_WARNDIALOGCOMBOSELECTEDGRAYTEXT, + F_DARKGRAY|B_LIGHTGRAY, // COL_WARNDIALOGLISTGRAY, + F_WHITE|B_BLACK, // COL_WARNDIALOGLISTSELECTEDGRAYTEXT, + + F_BLACK|B_LIGHTGRAY, // COL_DIALOGDEFAULTBUTTON, + F_LIGHTGRAY|B_BLACK, // COL_DIALOGSELECTEDDEFAULTBUTTON, + F_WHITE|B_LIGHTGRAY, // COL_DIALOGHIGHLIGHTDEFAULTBUTTON, + F_WHITE|B_BLACK, // COL_DIALOGHIGHLIGHTSELECTEDDEFAULTBUTTON, + F_BLACK|B_LIGHTGRAY, // COL_WARNDIALOGDEFAULTBUTTON, + F_LIGHTGRAY|B_BLACK, // COL_WARNDIALOGSELECTEDDEFAULTBUTTON, + F_WHITE|B_LIGHTGRAY, // COL_WARNDIALOGHIGHLIGHTDEFAULTBUTTON, + F_WHITE|B_BLACK, // COL_WARNDIALOGHIGHLIGHTSELECTEDDEFAULTBUTTON, +}; + + +int SizeArrayPalette=ARRAYSIZE(DefaultPalette); +unsigned char Palette[ARRAYSIZE(DefaultPalette)]; + +BYTE FarColorToReal(int FarColor) +{ + return (FarColor<COL_FIRSTPALETTECOLOR)?FarColor:Palette[(FarColor-COL_FIRSTPALETTECOLOR)%SizeArrayPalette]; +} + +/* + 1.65 - 0x52 + 1.70 b1 (272) - 0x54 + 1.70 b2 (321) - 0x54 + 1.70 b3 (591) - 0x54 + 1.70 b4 (1282) - 0x60 + 1.70 b5 () - 0x70 + + 1.71 a4 (2468) - 0x81 + 1.80 (606) - 0x81 + 1.75 rc1 (2555) - 0x8B + 2.0 (848) - 0x8B +*/ +void ConvertCurrentPalette() +{ +// DWORD Size=GetRegKeySize("Colors","CurrentPalette"); +} diff --git a/far2l/src/console/palette.hpp b/far2l/src/console/palette.hpp new file mode 100644 index 00000000..8b5978ab --- /dev/null +++ b/far2l/src/console/palette.hpp @@ -0,0 +1,44 @@ +#pragma once + +/* +palette.hpp + +Таблица цветов +*/ +/* +Copyright (c) 1996 Eugene Roshal +Copyright (c) 2000 Far Group +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <WinCompat.h> + +extern unsigned char DefaultPalette[]; +extern unsigned char Palette[]; +extern unsigned char BlackPalette[]; +extern int SizeArrayPalette; + +BYTE FarColorToReal(int FarColor); +void ConvertCurrentPalette(); diff --git a/far2l/src/console/savescr.cpp b/far2l/src/console/savescr.cpp new file mode 100644 index 00000000..79da142d --- /dev/null +++ b/far2l/src/console/savescr.cpp @@ -0,0 +1,313 @@ +/* +savescr.cpp + +Сохраняем и восстанавливааем экран кусками и целиком +*/ +/* +Copyright (c) 1996 Eugene Roshal +Copyright (c) 2000 Far Group +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "headers.hpp" + + +#include "savescr.hpp" +#include "colors.hpp" +#include "syslog.hpp" +#include "interf.hpp" +#include "palette.hpp" +#include "console.hpp" + +SaveScreen::SaveScreen() +{ + _OT(SysLog(L"[%p] SaveScreen::SaveScreen()", this)); + SaveArea(0,0,ScrX,ScrY); +} + +SaveScreen::SaveScreen(int X1,int Y1,int X2,int Y2) +{ + _OT(SysLog(L"[%p] SaveScreen::SaveScreen(X1=%i,Y1=%i,X2=%i,Y2=%i)",this,X1,Y1,X2,Y2)); + + X1=Min(static_cast<int>(ScrX), Max(0, X1)); + X2=Min(static_cast<int>(ScrX), Max(0, X2)); + Y1=Min(static_cast<int>(ScrY), Max(0, Y1)); + Y2=Min(static_cast<int>(ScrY), Max(0, Y2)); + + SaveArea(X1,Y1,X2,Y2); +} + + +SaveScreen::~SaveScreen() +{ + if (!ScreenBuf) + return; + + _OT(SysLog(L"[%p] SaveScreen::~SaveScreen()", this)); + RestoreArea(); + delete[] ScreenBuf; +} + + +void SaveScreen::Discard() +{ + if (!ScreenBuf) + return; + + delete[] ScreenBuf; + ScreenBuf=nullptr; +} + + +void SaveScreen::RestoreArea(int RestoreCursor) +{ + if (!ScreenBuf) { + fprintf(stderr, "SaveScreen::RestoreArea: no ScreenBuf\n"); + return; + } + + PutText(X1,Y1,X2,Y2,ScreenBuf); + + if (RestoreCursor) + { + SetCursorType(CurVisible,CurSize); + MoveCursor(CurPosX,CurPosY); + } +} + + +void SaveScreen::SaveArea(int X1,int Y1,int X2,int Y2) +{ + SaveScreen::X1=X1; + SaveScreen::Y1=Y1; + SaveScreen::X2=X2; + SaveScreen::Y2=Y2; + ScreenBuf=new(std::nothrow) CHAR_INFO[ScreenBufCharCount()]; + + if (!ScreenBuf) + return; + + GetText(X1,Y1,X2,Y2,ScreenBuf,ScreenBufCharCount()*sizeof(CHAR_INFO)); + GetCursorPos(CurPosX,CurPosY); + GetCursorType(CurVisible,CurSize); +} + +void SaveScreen::SaveArea() +{ + if (!ScreenBuf) + return; + + GetText(X1,Y1,X2,Y2,ScreenBuf,ScreenBufCharCount()*sizeof(CHAR_INFO)); + GetCursorPos(CurPosX,CurPosY); + GetCursorType(CurVisible,CurSize); +} + +void SaveScreen::CorrectRealScreenCoord() +{ + if (X1 < 0) X1=0; + + if (Y1 < 0) Y1=0; + + if (X2 >= ScrX) X2=ScrX; + + if (Y2 >= ScrY) Y2=ScrY; +} + +void SaveScreen::AppendArea(SaveScreen *NewArea) +{ + CHAR_INFO *Buf=ScreenBuf,*NewBuf=NewArea->ScreenBuf; + + if (!Buf || !NewBuf) + return; + + for (int X=X1; X<=X2; X++) + if (X>=NewArea->X1 && X<=NewArea->X2) + for (int Y=Y1; Y<=Y2; Y++) + if (Y>=NewArea->Y1 && Y<=NewArea->Y2) + Buf[X-X1+(X2-X1+1)*(Y-Y1)]=NewBuf[X-NewArea->X1+(NewArea->X2-NewArea->X1+1)*(Y-NewArea->Y1)]; +} + +void SaveScreen::Resize(int NewX,int NewY, DWORD Corner, bool SyncWithConsole) +// Corner definition: +// 0 --- 1 +// | | +// 2 --- 3 +{ + int OWi=X2-X1+1, OHe=Y2-Y1+1, iY=0; + + if (OWi==NewX && OHe==NewY) + { + return; + } + + int NX1,NX2,NY1,NY2; + NX1=NX2=NY1=NY2=0; + PCHAR_INFO NewBuf = new CHAR_INFO[NewX*NewY]; + CleanupBuffer(NewBuf,NewX*NewY); + int NewWidth=Min(OWi,NewX); + int NewHeight=Min(OHe,NewY); + int iYReal; + int ToIndex=0; + int FromIndex=0; + + if (Corner & 2) + { + NY2=Y1+NewY-1; NY1=NY2-NewY+1; + } + else + { + NY1=Y1; NY2=NY1+NewY-1; + } + + if (Corner & 1) + { + NX2=X1+NewX-1; NX1=NX2-NewX+1; + } + else + { + NX1=X1; NX2=NX1+NewX-1; + } + + for (iY=0; iY<NewHeight; iY++) + { + if (Corner & 2) + { + if (OHe>NewY) + { + iYReal=OHe-NewY+iY; + FromIndex=iYReal*OWi; + ToIndex=iY*NewX; + } + else + { + iYReal=NewY-OHe+iY; + ToIndex=iYReal*NewX; + FromIndex=iY*OWi; + } + } + + if (Corner & 1) + { + if (OWi>NewX) + { + FromIndex+=OWi-NewX; + } + else + { + ToIndex+=NewX-OWi; + } + } + + CharCopy(&NewBuf[ToIndex],&ScreenBuf[FromIndex],NewWidth); + } + + // achtung, experimental + if((Corner&2) && SyncWithConsole) + { + Console.ResetPosition(); + if(NewY!=OHe) + { + COORD Size={(SHORT)Max(NewX,OWi), (SHORT)abs(OHe-NewY)}; + COORD Coord={0, 0}; + PCHAR_INFO Tmp=new CHAR_INFO[Size.X*Size.Y]; + if(NewY>OHe) + { + SMALL_RECT ReadRegion={0, 0, (SHORT)(NewX-1), (SHORT)(NewY-OHe-1)}; + Console.ReadOutput(*Tmp, Size, Coord, ReadRegion); + for(int i=0; i<Size.Y;i++) + { + CharCopy(&NewBuf[i*Size.X],&Tmp[i*Size.X], Size.X); + } + } + else + { + SMALL_RECT WriteRegion={0, (SHORT)(NewY-OHe), (SHORT)(NewX-1), (SHORT)(-1)}; + for(int i=0; i<Size.Y;i++) + { + CharCopy(&Tmp[i*Size.X],&ScreenBuf[i*OWi], Size.X); + } + Console.WriteOutput(*Tmp, Size, Coord, WriteRegion); + } + delete[] Tmp; + } + + if(NewX!=OWi) + { + COORD Size={(SHORT)abs(NewX-OWi), (SHORT)Max(NewY,OHe)}; + COORD Coord={0, 0}; + PCHAR_INFO Tmp=new CHAR_INFO[Size.X*Size.Y]; + if(NewX>OWi) + { + SMALL_RECT ReadRegion={(SHORT)OWi, 0, (SHORT)(NewX-1), (SHORT)(NewY-1)}; + Console.ReadOutput(*Tmp, Size, Coord, ReadRegion); + for(int i=0; i<Size.Y;i++) + { + CharCopy(&NewBuf[i*NewX+OWi],&Tmp[i*Size.X], Size.X); + } + } + else + { + SMALL_RECT WriteRegion={(SHORT)NewX, (SHORT)(NewY-OHe), (SHORT)(OWi-1), (SHORT)(NewY-1)}; + for(int i=0; i<Size.Y;i++) + { + CharCopy(&Tmp[i*Size.X],&ScreenBuf[i*OWi+NewX], Size.X); + } + Console.WriteOutput(*Tmp, Size, Coord, WriteRegion); + } + delete[] Tmp; + } + } + + delete [] ScreenBuf; + ScreenBuf=NewBuf; + X1=NX1; Y1=NY1; X2=NX2; Y2=NY2; +} + + +int SaveScreen::ScreenBufCharCount() +{ + return (X2-X1+1)*(Y2-Y1+1); +} + +void SaveScreen::CharCopy(PCHAR_INFO ToBuffer,PCHAR_INFO FromBuffer,int Count) +{ + memcpy(ToBuffer,FromBuffer,Count*sizeof(CHAR_INFO)); +} + +void SaveScreen::CleanupBuffer(PCHAR_INFO Buffer, size_t BufSize) +{ + WORD Attr=FarColorToReal(COL_COMMANDLINEUSERSCREEN); + + for (size_t i=0; i<BufSize; i++) + { + Buffer[i].Attributes=Attr; + Buffer[i].Char.UnicodeChar=L' '; + } +} + +void SaveScreen::DumpBuffer(const wchar_t *Title) +{ + SaveScreenDumpBuffer(Title,GetBufferAddress(),X1,Y1,X2,Y2,nullptr); +} diff --git a/far2l/src/console/savescr.hpp b/far2l/src/console/savescr.hpp new file mode 100644 index 00000000..c6f97cb9 --- /dev/null +++ b/far2l/src/console/savescr.hpp @@ -0,0 +1,69 @@ +#pragma once + +/* +savescr.hpp + +Сохраняем и восстанавливааем экран кусками и целиком +*/ +/* +Copyright (c) 1996 Eugene Roshal +Copyright (c) 2000 Far Group +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include <WinCompat.h> + +class SaveScreen +{ + friend class Grabber; + private: + PCHAR_INFO ScreenBuf; + SHORT CurPosX,CurPosY; + bool CurVisible; + DWORD CurSize; + int X1,Y1,X2,Y2; + + void CleanupBuffer(PCHAR_INFO Buffer, size_t BufSize); + int ScreenBufCharCount(); + void CharCopy(PCHAR_INFO ToBuffer,PCHAR_INFO FromBuffer,int Count); + CHAR_INFO* GetBufferAddress() {return ScreenBuf;}; + + public: + SaveScreen(); + SaveScreen(int X1,int Y1,int X2,int Y2); + ~SaveScreen(); + + public: + void CorrectRealScreenCoord(); + void SaveArea(int X1,int Y1,int X2,int Y2); + void SaveArea(); + void RestoreArea(int RestoreCursor=TRUE); + void Discard(); + void AppendArea(SaveScreen *NewArea); + /*$ 18.05.2001 OT */ + void Resize(int ScrX,int ScrY,DWORD Corner, bool SyncWithConsole); + + void DumpBuffer(const wchar_t *Title); +}; diff --git a/far2l/src/console/scrbuf.cpp b/far2l/src/console/scrbuf.cpp new file mode 100644 index 00000000..831856a9 --- /dev/null +++ b/far2l/src/console/scrbuf.cpp @@ -0,0 +1,569 @@ +/* +scrbuf.cpp + +Буферизация вывода на экран, весь вывод идет через этот буфер +*/ +/* +Copyright (c) 1996 Eugene Roshal +Copyright (c) 2000 Far Group +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "headers.hpp" + + +#include "scrbuf.hpp" +#include "colors.hpp" +#include "ctrlobj.hpp" +#include "syslog.hpp" +#include "interf.hpp" +#include "palette.hpp" +#include "config.hpp" +#include "DList.hpp" +#include "console.hpp" + +enum +{ + SBFLAGS_FLUSHED = 0x00000001, + SBFLAGS_FLUSHEDCURPOS = 0x00000002, + SBFLAGS_FLUSHEDCURTYPE = 0x00000004, + SBFLAGS_USESHADOW = 0x00000008, +}; + + +//#if defined(SYSLOG_OT) +// #define DIRECT_SCREEN_OUT +//#endif + +#ifdef DIRECT_RT +extern int DirectRT; +#endif + +ScreenBuf ScrBuf; + +static bool AreSameCharInfoBuffers(const CHAR_INFO *left, const CHAR_INFO *right, size_t count) +{//use this instead of memcmp cuz it can produce wrong results due to uninitialized alignment gaps + for (; count; --count, ++left, ++right) { + if (left->Char.UnicodeChar != right->Char.UnicodeChar) return false; + if (left->Attributes != right->Attributes) return false; + } + return true; +} + +ScreenBuf::ScreenBuf(): + Buf(nullptr), + Shadow(nullptr), + MacroCharUsed(false), + ElevationCharUsed(false), + BufX(0), + BufY(0), + CurX(0), + CurY(0), + CurVisible(false), + CurSize(0), + LockCount(0) +{ + SBFlags.Set(SBFLAGS_FLUSHED|SBFLAGS_FLUSHEDCURPOS|SBFLAGS_FLUSHEDCURTYPE); +} + + +ScreenBuf::~ScreenBuf() +{ + if (Buf) delete[] Buf; + + if (Shadow) delete[] Shadow; +} + + +void ScreenBuf::AllocBuf(int X,int Y) +{ + CriticalSectionLock Lock(CS); + + if (X==BufX && Y==BufY) + return; + + if (Buf) delete[] Buf; + + if (Shadow) delete[] Shadow; + + unsigned Cnt=X*Y; + Buf=new CHAR_INFO[Cnt](); + Shadow=new CHAR_INFO[Cnt](); + BufX=X; + BufY=Y; +} + +/* Заполнение виртуального буфера значением из консоли. +*/ +void ScreenBuf::FillBuf() +{ + CriticalSectionLock Lock(CS); + COORD BufferSize={BufX, BufY}, BufferCoord={0, 0}; + SMALL_RECT ReadRegion={0, 0, (SHORT)(BufX-1), (SHORT)(BufY-1)}; + Console.ReadOutput(*Buf, BufferSize, BufferCoord, ReadRegion); + memcpy(Shadow,Buf,BufX*BufY*sizeof(CHAR_INFO)); + SBFlags.Set(SBFLAGS_USESHADOW); + COORD CursorPosition; + Console.GetCursorPosition(CursorPosition); + CurX=CursorPosition.X; + CurY=CursorPosition.Y; +} + +/* Записать Text в виртуальный буфер +*/ +void ScreenBuf::Write(int X,int Y,const CHAR_INFO *Text,int TextLength) +{ + CriticalSectionLock Lock(CS); + + if (X<0) + { + Text-=X; + TextLength=Max(0,TextLength+X); + X=0; + } + + if (X>=BufX || Y>=BufY || !TextLength || Y<0) { + return; + } + + if (X+TextLength >= BufX) + TextLength=BufX-X; //?? + + CHAR_INFO *PtrBuf=Buf+Y*BufX+X; + + for (int i=0; i<TextLength; i++) + { + SetVidChar(PtrBuf[i],Text[i].Char.UnicodeChar); + PtrBuf[i].Attributes=Text[i].Attributes; + } + + SBFlags.Clear(SBFLAGS_FLUSHED); +#ifdef DIRECT_SCREEN_OUT + Flush(); +#elif defined(DIRECT_RT) + if (DirectRT) + Flush(); + +#endif +} + + +/* Читать блок из виртуального буфера. +*/ +void ScreenBuf::Read(int X1,int Y1,int X2,int Y2,CHAR_INFO *Text,int MaxTextLength) +{ + CriticalSectionLock Lock(CS); + int Width=X2-X1+1; + int Height=Y2-Y1+1; + int I, Idx; + + for (Idx=I=0; I < Height; I++, Idx+=Width) + memcpy(Text+Idx,Buf+(Y1+I)*BufX+X1,Min((int)sizeof(CHAR_INFO)*Width,(int)MaxTextLength)); +} + +/* Изменить значение цветовых атрибутов в соответствии с маской + (в основном применяется для "создания" тени) +*/ +void ScreenBuf::ApplyColorMask(int X1,int Y1,int X2,int Y2,WORD ColorMask) +{ + CriticalSectionLock Lock(CS); + int Width=X2-X1+1; + int Height=Y2-Y1+1; + int I, J; + + for (I=0; I < Height; I++) + { + CHAR_INFO *PtrBuf=Buf+(Y1+I)*BufX+X1; + + for (J=0; J < Width; J++, ++PtrBuf) + { + if (!(PtrBuf->Attributes&=~ColorMask)) + PtrBuf->Attributes=0x08; + } + } + +#ifdef DIRECT_SCREEN_OUT + Flush(); +#elif defined(DIRECT_RT) + + if (DirectRT) + Flush(); + +#endif +} + +/* Непосредственное изменение цветовых атрибутов +*/ +void ScreenBuf::ApplyColor(int X1,int Y1,int X2,int Y2,WORD Color) +{ + CriticalSectionLock Lock(CS); + if(X1<=ScrX && Y1<=ScrY && X2>=0 && Y2>=0) + { + X1=Max(0,X1); + X2=Min(static_cast<int>(ScrX),X2); + Y1=Max(0,Y1); + Y2=Min(static_cast<int>(ScrY),Y2); + + int Width=X2-X1+1; + int Height=Y2-Y1+1; + int I, J; + + for (I=0; I < Height; I++) + { + CHAR_INFO *PtrBuf=Buf+(Y1+I)*BufX+X1; + + for (J=0; J < Width; J++, ++PtrBuf) + PtrBuf->Attributes=Color; + + //Buf[K+J].Attributes=Color; + } + +#ifdef DIRECT_SCREEN_OUT + Flush(); +#elif defined(DIRECT_RT) + + if (DirectRT) + Flush(); + +#endif + } +} + +/* Непосредственное изменение цветовых атрибутов с заданым цетом исключением +*/ +void ScreenBuf::ApplyColor(int X1,int Y1,int X2,int Y2,int Color,WORD ExceptColor) +{ + CriticalSectionLock Lock(CS); + if(X1<=ScrX && Y1<=ScrY && X2>=0 && Y2>=0) + { + X1=Max(0,X1); + X2=Min(static_cast<int>(ScrX),X2); + Y1=Max(0,Y1); + Y2=Min(static_cast<int>(ScrY),Y2); + + for (int I = 0; I < Y2-Y1+1; I++) + { + CHAR_INFO *PtrBuf = Buf+(Y1+I)*BufX+X1; + + for (int J = 0; J < X2-X1+1; J++, ++PtrBuf) + if (PtrBuf->Attributes != ExceptColor) + PtrBuf->Attributes = Color; + } + +#ifdef DIRECT_SCREEN_OUT + Flush(); +#elif defined(DIRECT_RT) + + if (DirectRT) + Flush(); + +#endif + } +} + +/* Закрасить прямоугольник символом Ch и цветом Color +*/ +void ScreenBuf::FillRect(int X1,int Y1,int X2,int Y2,WCHAR Ch,WORD Color) +{ + CriticalSectionLock Lock(CS); + int Width=X2-X1+1; + int Height=Y2-Y1+1; + int I, J; + CHAR_INFO CI,*PtrBuf; + CI.Attributes=Color; + SetVidChar(CI,Ch); + + for (I=0; I < Height; I++) + { + for (PtrBuf=Buf+(Y1+I)*BufX+X1, J=0; J < Width; J++, ++PtrBuf) + *PtrBuf=CI; + } + + SBFlags.Clear(SBFLAGS_FLUSHED); +#ifdef DIRECT_SCREEN_OUT + Flush(); +#elif defined(DIRECT_RT) + + if (DirectRT) + Flush(); + +#endif +} + +/* "Сбросить" виртуальный буфер на консоль +*/ +void ScreenBuf::Flush() +{ + CriticalSectionLock Lock(CS); + + if (!LockCount) + { + if (CtrlObject && (CtrlObject->Macro.IsRecording() || CtrlObject->Macro.IsExecuting())) + { + MacroChar=Buf[0]; + MacroCharUsed=true; + + if(CtrlObject->Macro.IsRecording()) + { + Buf[0].Char.UnicodeChar=L'R'; + Buf[0].Attributes=0xCF; + } + else + { + Buf[0].Char.UnicodeChar=L'P'; + Buf[0].Attributes=0x2F; + } + } + + if (!SBFlags.Check(SBFLAGS_FLUSHEDCURTYPE) && !CurVisible) + { + CONSOLE_CURSOR_INFO cci={CurSize,CurVisible}; + Console.SetCursorInfo(cci); + SBFlags.Set(SBFLAGS_FLUSHEDCURTYPE); + } + + if (!SBFlags.Check(SBFLAGS_FLUSHED)) + { + SBFlags.Set(SBFLAGS_FLUSHED); + + if (WaitInMainLoop && Opt.Clock && !ProcessShowClock) + { + ShowTime(FALSE); + } + + DList<SMALL_RECT>WriteList; + bool Changes=false; + + if (SBFlags.Check(SBFLAGS_USESHADOW)) + { + PCHAR_INFO PtrBuf=Buf,PtrShadow=Shadow; + + { + bool Started=false; + SMALL_RECT WriteRegion={(SHORT)(BufX-1),(SHORT)(BufY-1),0,0}; + + for (SHORT I=0; I<BufY; I++) + { + for (SHORT J=0; J<BufX; J++,++PtrBuf,++PtrShadow) + { + if (!AreSameCharInfoBuffers(PtrBuf, PtrShadow, 1)) + { + WriteRegion.Left=Min(WriteRegion.Left,J); + WriteRegion.Top=Min(WriteRegion.Top,I); + WriteRegion.Right=Max(WriteRegion.Right,J); + WriteRegion.Bottom=Max(WriteRegion.Bottom,I); + Changes=true; + Started=true; + } + else if (Started && I>WriteRegion.Bottom && J>=WriteRegion.Left) + { + //BUGBUG: при включенном СlearType-сглаживании на экране остаётся "мусор" - тонкие вертикальные полосы + // кстати, и при выключенном тоже (но реже). + // баг, конечно, не наш, но что делать. + // расширяем область прорисовки влево-вправо на 1 символ: + WriteRegion.Left=Max(static_cast<SHORT>(0),static_cast<SHORT>(WriteRegion.Left-1)); + WriteRegion.Right=Min(static_cast<SHORT>(WriteRegion.Right+1),static_cast<SHORT>(BufX-1)); + bool Merge=false; + PSMALL_RECT Last=WriteList.Last(); + + if (Last) + { +#define MAX_DELTA 5 + + if (WriteRegion.Top-1==Last->Bottom && ((WriteRegion.Left>=Last->Left && WriteRegion.Left-Last->Left<MAX_DELTA) || (Last->Right>=WriteRegion.Right && Last->Right-WriteRegion.Right<MAX_DELTA))) + { + Last->Bottom=WriteRegion.Bottom; + Last->Left=Min(Last->Left,WriteRegion.Left); + Last->Right=Max(Last->Right,WriteRegion.Right); + Merge=true; + } + } + + if (!Merge) + WriteList.Push(&WriteRegion); + + WriteRegion.Left=BufX-1; + WriteRegion.Top=BufY-1; + WriteRegion.Right=0; + WriteRegion.Bottom=0; + Started=false; + } + } + } + + if (Started) + { + WriteList.Push(&WriteRegion); + } + } + } + else + { + Changes=true; + SMALL_RECT WriteRegion={0,0,(SHORT)(BufX-1),(SHORT)(BufY-1)}; + WriteList.Push(&WriteRegion); + } + + if (Changes) + { + for (PSMALL_RECT PtrRect=WriteList.First(); PtrRect; PtrRect=WriteList.Next(PtrRect)) + { + COORD BufferSize={BufX, BufY}, BufferCoord={PtrRect->Left,PtrRect->Top}; + SMALL_RECT WriteRegion=*PtrRect; + Console.WriteOutput(*Buf, BufferSize, BufferCoord, WriteRegion); + } + memcpy(Shadow,Buf,BufX*BufY*sizeof(CHAR_INFO)); + } + } + + if (MacroCharUsed) + { + Buf[0]=MacroChar; + } + + if (ElevationCharUsed) + { + Buf[BufX*BufY-1]=ElevationChar; + } + + if (!SBFlags.Check(SBFLAGS_FLUSHEDCURPOS)) + { + COORD C={CurX,CurY}; + Console.SetCursorPosition(C); + SBFlags.Set(SBFLAGS_FLUSHEDCURPOS); + } + + if (!SBFlags.Check(SBFLAGS_FLUSHEDCURTYPE) && CurVisible) + { + CONSOLE_CURSOR_INFO cci={CurSize,CurVisible}; + Console.SetCursorInfo(cci); + SBFlags.Set(SBFLAGS_FLUSHEDCURTYPE); + } + + SBFlags.Set(SBFLAGS_USESHADOW|SBFLAGS_FLUSHED); + } +} + + +void ScreenBuf::Lock() +{ + LockCount++; +} + + +void ScreenBuf::Unlock() +{ + if (LockCount>0) + LockCount--; +} + + +void ScreenBuf::ResetShadow() +{ + SBFlags.Clear(SBFLAGS_FLUSHED|SBFLAGS_FLUSHEDCURTYPE|SBFLAGS_FLUSHEDCURPOS|SBFLAGS_USESHADOW); +} + + +void ScreenBuf::MoveCursor(int X,int Y) +{ + CriticalSectionLock Lock(CS); + + if (CurX<0||CurY<0||CurX>ScrX||CurY>ScrY) + { + CurVisible=FALSE; + } + + if(X!=CurX || Y!=CurY || !CurVisible) + { + CurX=X; + CurY=Y; + SBFlags.Clear(SBFLAGS_FLUSHEDCURPOS); + } +} + + +void ScreenBuf::GetCursorPos(SHORT& X,SHORT& Y) +{ + X=CurX; + Y=CurY; +} + + +void ScreenBuf::SetCursorType(bool Visible, DWORD Size) +{ + /* $ 09.01.2001 SVS + По наводке ER - в SetCursorType не дергать раньше + времени установку курсора + */ + if (CurVisible!=Visible || CurSize!=Size) + { + CurVisible=Visible; + CurSize=Size; + SBFlags.Clear(SBFLAGS_FLUSHEDCURTYPE); + } +} + +void ScreenBuf::GetCursorType(bool& Visible, DWORD& Size) +{ + Visible=CurVisible; + Size=CurSize; +} + + +void ScreenBuf::RestoreMacroChar() +{ + if(MacroCharUsed) + { + Write(0,0,&MacroChar,1); + MacroCharUsed=false; + } +} + +void ScreenBuf::RestoreElevationChar() +{ + if(ElevationCharUsed) + { + Write(BufX-1,BufY-1,&ElevationChar,1); + ElevationCharUsed=false; + } +} + +// проскроллировать буффер на одну строку вверх. +void ScreenBuf::Scroll(int Num) +{ + CriticalSectionLock Lock(CS); + + if (Num > 0 && Num < BufY) + memmove(Buf,Buf+Num*BufX,(BufY-Num)*BufX*sizeof(CHAR_INFO)); + +#ifdef DIRECT_SCREEN_OUT + Flush(); +#elif defined(DIRECT_RT) + + if (DirectRT) + Flush(); + +#endif +} diff --git a/far2l/src/console/scrbuf.hpp b/far2l/src/console/scrbuf.hpp new file mode 100644 index 00000000..497c01a9 --- /dev/null +++ b/far2l/src/console/scrbuf.hpp @@ -0,0 +1,93 @@ +#pragma once + +/* +scrbuf.hpp + +Буферизация вывода на экран, весь вывод идет через этот буфер +*/ +/* +Copyright (c) 1996 Eugene Roshal +Copyright (c) 2000 Far Group +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "bitflags.hpp" +#include "CriticalSections.hpp" +#include <WinCompat.h> + +class ScreenBuf +{ + private: + BitFlags SBFlags; + + CHAR_INFO *Buf; + CHAR_INFO *Shadow; + CHAR_INFO MacroChar; + bool MacroCharUsed; + CHAR_INFO ElevationChar; + bool ElevationCharUsed; + + SHORT BufX,BufY; + SHORT CurX,CurY; + bool CurVisible; + DWORD CurSize; + + int LockCount; + + CriticalSection CS; + + public: + ScreenBuf(); + ~ScreenBuf(); + + public: + void AllocBuf(int X,int Y); + void Lock(); + void Unlock(); + int GetLockCount() {return(LockCount);}; + void SetLockCount(int Count) {LockCount=Count;}; + void ResetShadow(); + void MoveCursor(int X,int Y); + void GetCursorPos(SHORT& X,SHORT& Y); + void SetCursorType(bool Visible, DWORD Size); + void GetCursorType(bool& Visible, DWORD& Size); + + public: + void FillBuf(); + void Read(int X1,int Y1,int X2,int Y2,CHAR_INFO *Text,int MaxTextLength); + void Write(int X,int Y,const CHAR_INFO *Text,int TextLength); + void RestoreMacroChar(); + void RestoreElevationChar(); + + void ApplyColorMask(int X1,int Y1,int X2,int Y2,WORD ColorMask); + void ApplyColor(int X1,int Y1,int X2,int Y2,WORD Color); + void ApplyColor(int X1,int Y1,int X2,int Y2,int Color,WORD ExceptColor); + void FillRect(int X1,int Y1,int X2,int Y2,WCHAR Ch,WORD Color); + + void Scroll(int); + void Flush(); +}; + +extern ScreenBuf ScrBuf; diff --git a/far2l/src/console/scrobj.cpp b/far2l/src/console/scrobj.cpp new file mode 100644 index 00000000..ffe78e47 --- /dev/null +++ b/far2l/src/console/scrobj.cpp @@ -0,0 +1,239 @@ +/* +scrobj.cpp + +Parent class для всех screen objects +*/ +/* +Copyright (c) 1996 Eugene Roshal +Copyright (c) 2000 Far Group +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "headers.hpp" + + +#include "scrobj.hpp" +#include "savescr.hpp" +#include "interf.hpp" + +ScreenObject *ScreenObject::CaptureMouseObject=nullptr; + +ScreenObject::ScreenObject(): + ShadowSaveScr(nullptr), + X1(0), + Y1(0), + X2(0), + Y2(0), + ObjWidth(0), + ObjHeight(0), + nLockCount(0), + pOwner(nullptr), + SaveScr(nullptr) +{ +// _OT(SysLog(L"[%p] ScreenObject::ScreenObject()", this)); +} + + +ScreenObject::~ScreenObject() +{ +// _OT(SysLog(L"[%p] ScreenObject::~ScreenObject()", this)); + if (!Flags.Check(FSCROBJ_ENABLERESTORESCREEN)) + { + if (ShadowSaveScr) + ShadowSaveScr->Discard(); + + if (SaveScr) + SaveScr->Discard(); + } + + if (ShadowSaveScr) + delete ShadowSaveScr; + + if (SaveScr) + delete SaveScr; +} + +void ScreenObject::Lock() +{ + nLockCount++; +} + +void ScreenObject::Unlock() +{ + if (nLockCount > 0) + nLockCount--; + else + nLockCount = 0; +} + +bool ScreenObject::Locked() +{ + return (nLockCount > 0) || (pOwner?pOwner->Locked():false); +} + +void ScreenObject::SetOwner(ScreenObject *pOwner) +{ + ScreenObject::pOwner = pOwner; +} + +ScreenObject* ScreenObject::GetOwner() +{ + return pOwner; +} + +void ScreenObject::SetPosition(int X1,int Y1,int X2,int Y2) +{ + /* $ 13.04.2002 KM + - Раз меняем позицию объекта на экране, то тогда + перед этим восстановим изображение под ним для + предотвращения восстановления ранее сохранённого + изображения в новом месте. + */ + if (SaveScr) + { + delete SaveScr; + SaveScr=nullptr; + } + + ScreenObject::X1=X1; + ScreenObject::Y1=Y1; + ScreenObject::X2=X2; + ScreenObject::Y2=Y2; + ObjWidth=X2-X1+1; + ObjHeight=Y2-Y1+1; + Flags.Set(FSCROBJ_SETPOSITIONDONE); +} + +void ScreenObject::SetScreenPosition() +{ + Flags.Clear(FSCROBJ_SETPOSITIONDONE); +} + + +void ScreenObject::GetPosition(int& X1,int& Y1,int& X2,int& Y2) +{ + X1=ScreenObject::X1; + Y1=ScreenObject::Y1; + X2=ScreenObject::X2; + Y2=ScreenObject::Y2; +} + + +void ScreenObject::Hide() +{ +// _tran(SysLog(L"[%p] ScreenObject::Hide()",this)); + if (!Flags.Check(FSCROBJ_VISIBLE)) + return; + + Flags.Clear(FSCROBJ_VISIBLE); + + if (ShadowSaveScr) + { + delete ShadowSaveScr; + ShadowSaveScr=nullptr; + } + + if (SaveScr) + { + delete SaveScr; + SaveScr=nullptr; + } +} + +/* $ 15.07.2000 tran + add ugly new method */ +void ScreenObject::Hide0() +{ + Flags.Clear(FSCROBJ_VISIBLE); +} +/* tran 15.07.2000 $ */ + +void ScreenObject::Show() +{ + if (Locked()) + return; + +// _tran(SysLog(L"[%p] ScreenObject::Show()",this)); + if (!Flags.Check(FSCROBJ_SETPOSITIONDONE)) + return; + +// if (Flags.Check(FSCROBJ_ISREDRAWING)) +// return; +// Flags.Set(FSCROBJ_ISREDRAWING); + SavePrevScreen(); + DisplayObject(); +// Flags.Clear(FSCROBJ_ISREDRAWING); +} + + +void ScreenObject::SavePrevScreen() +{ + if (!Flags.Check(FSCROBJ_SETPOSITIONDONE)) + return; + + if (!Flags.Check(FSCROBJ_VISIBLE)) + { + Flags.Set(FSCROBJ_VISIBLE); + + if (Flags.Check(FSCROBJ_ENABLERESTORESCREEN) && !SaveScr) + SaveScr=new SaveScreen(X1,Y1,X2,Y2); + } +} + + +void ScreenObject::Redraw() +{ +// _tran(SysLog(L"[%p] ScreenObject::Redraw()",this)); + if (Flags.Check(FSCROBJ_VISIBLE)) + Show(); +} + + +void ScreenObject::Shadow(bool Full) +{ + if (Flags.Check(FSCROBJ_VISIBLE)) + { + if(Full) + { + if (!ShadowSaveScr) + ShadowSaveScr=new SaveScreen(0,0,ScrX,ScrY); + + MakeShadow(0,0,ScrX,ScrY); + } + else + { + if (!ShadowSaveScr) + ShadowSaveScr=new SaveScreen(X1,Y1,X2+2,Y2+1); + + MakeShadow(X1+2,Y2+1,X2+1,Y2+1); + MakeShadow(X2+1,Y1+1,X2+2,Y2+1); + } + } +} + +void ScreenObject::SetCapture(ScreenObject *Obj) +{ + ScreenObject::CaptureMouseObject=Obj; +} diff --git a/far2l/src/console/scrobj.hpp b/far2l/src/console/scrobj.hpp new file mode 100644 index 00000000..000f5fdf --- /dev/null +++ b/far2l/src/console/scrobj.hpp @@ -0,0 +1,102 @@ +#pragma once + +/* +scrobj.hpp + +Parent class для всех screen objects +*/ +/* +Copyright (c) 1996 Eugene Roshal +Copyright (c) 2000 Far Group +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "bitflags.hpp" +#include <WinCompat.h> + +class SaveScreen; + +// можно использовать только младший байт (т.е. маска 0x000000FF), остальное отдается порожденным классам +enum +{ + FSCROBJ_VISIBLE = 0x00000001, + FSCROBJ_ENABLERESTORESCREEN = 0x00000002, + FSCROBJ_SETPOSITIONDONE = 0x00000004, + FSCROBJ_ISREDRAWING = 0x00000008, // идет процесс Show? +}; + +class ScreenObject +{ + protected: + BitFlags Flags; + SaveScreen *ShadowSaveScr; + int X1,Y1,X2,Y2; + int ObjWidth,ObjHeight; + + int nLockCount; + ScreenObject *pOwner; + + public: + SaveScreen *SaveScr; + static ScreenObject *CaptureMouseObject; + + private: + virtual void DisplayObject() {}; + + public: + ScreenObject(); + virtual ~ScreenObject(); + + public: + virtual int ProcessKey(int Key) { return 0; }; + virtual int ProcessMouse(MOUSE_EVENT_RECORD *MouseEvent) { return 0; }; + + virtual void Hide(); + virtual void Hide0(); // 15.07.2000 tran - dirty hack :( + virtual void Show(); + virtual void ShowConsoleTitle() {}; + virtual void SetPosition(int X1,int Y1,int X2,int Y2); + virtual void GetPosition(int& X1,int& Y1,int& X2,int& Y2); + virtual void SetScreenPosition(); + virtual void ResizeConsole() {}; + + virtual int64_t VMProcess(int OpCode,void *vParam=nullptr,int64_t iParam=0) {return 0;}; + + void Lock(); + void Unlock(); + bool Locked(); + + void SetOwner(ScreenObject *pOwner); + ScreenObject* GetOwner(); + + void SavePrevScreen(); + void Redraw(); + int IsVisible() { return Flags.Check(FSCROBJ_VISIBLE); }; + void SetVisible(int Visible) {Flags.Change(FSCROBJ_VISIBLE,Visible);}; + void SetRestoreScreenMode(int Mode) {Flags.Change(FSCROBJ_ENABLERESTORESCREEN,Mode);}; + void Shadow(bool Full=false); + + static void SetCapture(ScreenObject *Obj); +}; diff --git a/far2l/src/console/scrsaver.cpp b/far2l/src/console/scrsaver.cpp new file mode 100644 index 00000000..5477697e --- /dev/null +++ b/far2l/src/console/scrsaver.cpp @@ -0,0 +1,236 @@ +/* +scrsaver.cpp + +ScreenSaver +*/ +/* +Copyright (c) 1996 Eugene Roshal +Copyright (c) 2000 Far Group +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +#include "headers.hpp" + + +#include "colors.hpp" +#include "chgprior.hpp" +#include "savescr.hpp" +#include "manager.hpp" +#include "interf.hpp" +#include "keyboard.hpp" +#include "config.hpp" +#include "scrsaver.hpp" +#include "console.hpp" +#include <time.h> + +#define randomize() srand(time(NULL)) +#define random(x) (rand() % (x) ) + +enum {STAR_NONE,STAR_NORMAL,STAR_PLANET,STAR_EGGSTRA}; + +static struct +{ + int X; + int Y; + int Type; + int Color; + int Speed; +} Star[16]; + +static wchar_t StarSymbol[3][2]= +{ + {0x25cf,0x0000}, // ● + {0x2022,0x0000}, // • + {0x00B7,0x0000} // · +}; + +static wchar_t PlanetSymbol[3][2]= +{ + {0x25c9,0x0000}, // ◉ + {0x25ce,0x0000}, // ◎ + {0x00B0,0x0000}, // ° +}; + +static wchar_t EggstraSymbol[3][2]= +{ +#if defined(__linux__) + {0x1F427,0x0000}, // 🐧 + {0x1F427,0x0000}, // 🐧 // 0x1F425🐥 + {0x1F427,0x0000}, // 🐧 // 0x1F423🐣 + +#elif defined(__APPLE__) + {0x1F34E,0x0000}, // 🍎 + {0x1F34E,0x0000}, // 🍎 + {0x1F34E,0x0000}, // 🍎 + +#elif defined(__FreeBSD__) + {0x1F608,0x0000}, // 😈 + {0x1F608,0x0000}, // 😈 + {0x1F608,0x0000}, // 😈 + +#else + {0x1F95A,0x0000}, // 🥚 + {0x1F95A,0x0000}, // 🥚 + {0x1F95A,0x0000}, // 🥚 +#endif +}; + +static void ShowSaver(int Step) +{ + for (size_t I=0; I<ARRAYSIZE(Star); I++) + if (Star[I].Type!=STAR_NONE && !(Step%Star[I].Speed)) + { + SetColor(F_LIGHTCYAN|B_BLACK); + GotoXY(Star[I].X/100,Star[I].Y/100); + Text(L" "); + int dx=Star[I].X/100-ScrX/2; + Star[I].X+=dx*10+((dx<0) ? -1:1); + int dy=Star[I].Y/100-ScrY/2; + Star[I].Y+=dy*10+((dy<0) ? -1:1); + + if (Star[I].X<0 || Star[I].X/100>ScrX || Star[I].Y<0 || Star[I].Y/100>ScrY) + Star[I].Type=STAR_NONE; + else + { + SetColor(Star[I].Color|B_BLACK); + GotoXY(Star[I].X/100,Star[I].Y/100); + + if (abs(dx)>3*ScrX/8 || abs(dy)>3*ScrY/8) + { + if (Star[I].Type==STAR_NORMAL) + { + SetColor(F_WHITE|B_BLACK); + Text(StarSymbol[0]); + } + else + { + SetColor(Star[I].Color|FOREGROUND_INTENSITY|B_BLACK); + Text((Star[I].Type==STAR_PLANET) ? PlanetSymbol[0] : EggstraSymbol[0]); + } + } + else if (abs(dx)>ScrX/7 || abs(dy)>ScrY/7) + { + if (Star[I].Type==STAR_NORMAL) + { + if (abs(dx)>ScrX/4 || abs(dy)>ScrY/4) + SetColor(F_LIGHTCYAN|B_BLACK); + else + SetColor(F_CYAN|B_BLACK); + + Text(StarSymbol[1]); + } + else + { + SetColor(Star[I].Color|FOREGROUND_INTENSITY|B_BLACK); + Text((Star[I].Type==STAR_PLANET) ? PlanetSymbol[1] : EggstraSymbol[1]); + } + } + else + { + if (Star[I].Type==STAR_NORMAL) + { + SetColor(F_CYAN|B_BLACK); + Text(StarSymbol[2]); + } + else + { + SetColor(Star[I].Color|B_BLACK); + Text((Star[I].Type==STAR_PLANET) ? PlanetSymbol[2] : EggstraSymbol[2]); + } + } + } + } + + for (size_t I=0; I<ARRAYSIZE(Star); I++) + if (Star[I].Type==STAR_NONE) + { + static const int Colors[]={F_MAGENTA,F_RED,F_BLUE}; + int rnd_type = random(7700); + if (rnd_type == 0) + Star[I].Type=STAR_EGGSTRA; + else if (rnd_type < 300) + Star[I].Type=STAR_PLANET; + else + Star[I].Type=STAR_NORMAL; + Star[I].X=(ScrX/2-ScrX/4+random(ScrX/2))*100; + Star[I].Y=(ScrY/2-ScrY/4+random(ScrY/2))*100; + Star[I].Color=Colors[random(ARRAYSIZE(Colors))]; + Star[I].Speed=(Star[I].Type==STAR_PLANET) ? 1:2; + break; + } +} + +int ScreenSaver(int EnableExit) +{ + INPUT_RECORD rec; + clock_t WaitTime; + + if (ScreenSaverActive) + return 1; + + ChangePriority ChPriority(ChangePriority::IDLE); + + for (WaitTime=GetProcessUptimeMSec(); GetProcessUptimeMSec()-WaitTime<500;) + { + if (PeekInputRecord(&rec)) + return 1; + + WINPORT(Sleep)(100); + } + + ScreenSaverActive=TRUE; + CONSOLE_CURSOR_INFO CursorInfo; + Console.GetCursorInfo(CursorInfo); + { + SaveScreen SaveScr; + SetCursorType(0,10); + randomize(); + SetScreen(0,0,ScrX,ScrY,L' ',F_LIGHTGRAY|B_BLACK); + + for (size_t I=0; I<ARRAYSIZE(Star); I++) + { + Star[I].Type=STAR_NONE; + Star[I].Color=0; + } + + int Step=0; + + while (!PeekInputRecord(&rec)) + { + if (EnableExit && CheckForInactivityExit()) + return 0; + + WINPORT(Sleep)(50); + ShowSaver(Step++); + } + } + SetCursorType(CursorInfo.bVisible!=FALSE, CursorInfo.dwSize); + ScreenSaverActive=FALSE; + FlushInputBuffer(); + StartIdleTime=GetProcessUptimeMSec(); + return 1; +} + + diff --git a/far2l/src/console/scrsaver.hpp b/far2l/src/console/scrsaver.hpp new file mode 100644 index 00000000..89035f28 --- /dev/null +++ b/far2l/src/console/scrsaver.hpp @@ -0,0 +1,36 @@ +#pragma once + +/* +scrsaver.hpp + +ScreenSaver +*/ +/* +Copyright (c) 1996 Eugene Roshal +Copyright (c) 2000 Far Group +All rights reserved. + +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions +are met: +1. Redistributions of source code must retain the above copyright + notice, this list of conditions and the following disclaimer. +2. Redistributions in binary form must reproduce the above copyright + notice, this list of conditions and the following disclaimer in the + documentation and/or other materials provided with the distribution. +3. The name of the authors may not be used to endorse or promote products + derived from this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR +IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES +OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. +IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, +INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT +NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF +THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. +*/ + +int ScreenSaver(int EnableExit); |