Welcome to mirror list, hosted at ThFree Co, Russian Federation.

github.com/elfmz/far2l.git - Unnamed repository; edit this file 'description' to name the repository.
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorelfmz <fenix1905@tut.by>2021-12-31 00:27:16 +0300
committerelfmz <fenix1905@tut.by>2021-12-31 02:27:02 +0300
commita14dc1a81c797928d4f1b7d6a6b46ecc63f98308 (patch)
treec27c61ac33582bc4d469c6608cd042add388f230 /far2l/src/console
parentd5f1bf245e96834d44390d1723cfef3dfbb1fb02 (diff)
shuffle a bit far2l sources
Diffstat (limited to 'far2l/src/console')
-rw-r--r--far2l/src/console/AnsiEsc.cpp345
-rw-r--r--far2l/src/console/AnsiEsc.hpp48
-rw-r--r--far2l/src/console/colors.hpp291
-rw-r--r--far2l/src/console/console.cpp611
-rw-r--r--far2l/src/console/console.hpp120
-rw-r--r--far2l/src/console/constitle.cpp158
-rw-r--r--far2l/src/console/constitle.hpp55
-rw-r--r--far2l/src/console/grabber.cpp488
-rw-r--r--far2l/src/console/grabber.hpp66
-rw-r--r--far2l/src/console/interf.cpp1260
-rw-r--r--far2l/src/console/interf.hpp133
-rw-r--r--far2l/src/console/keyboard.cpp2948
-rw-r--r--far2l/src/console/keyboard.hpp77
-rw-r--r--far2l/src/console/keys.hpp809
-rw-r--r--far2l/src/console/lockscrn.cpp50
-rw-r--r--far2l/src/console/lockscrn.hpp41
-rw-r--r--far2l/src/console/palette.cpp422
-rw-r--r--far2l/src/console/palette.hpp44
-rw-r--r--far2l/src/console/savescr.cpp313
-rw-r--r--far2l/src/console/savescr.hpp69
-rw-r--r--far2l/src/console/scrbuf.cpp569
-rw-r--r--far2l/src/console/scrbuf.hpp93
-rw-r--r--far2l/src/console/scrobj.cpp239
-rw-r--r--far2l/src/console/scrobj.hpp102
-rw-r--r--far2l/src/console/scrsaver.cpp236
-rw-r--r--far2l/src/console/scrsaver.hpp36
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);