Skip to content

Commit e099fa8

Browse files
committed
Introduce class TKey
1 parent 9ef997b commit e099fa8

File tree

15 files changed

+601
-46
lines changed

15 files changed

+601
-46
lines changed

.gitignore

+2
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@
99
!project/**/
1010
!source/
1111
!source/**/
12+
!test/
13+
!test/**/
1214
!.github/
1315
!.github/**/
1416

CMakeLists.txt

+7
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
# (CMake 3.16 or newer), at the cost of possibly increasing its size.
1515
# * TV_BUILD_AVSCOLOR (default OFF) to build an AviSynth plugin for testing the
1616
# terminal color quantization (Unix only).
17+
# * TV_BUILD_TESTS (default OFF) to build and run tests.
1718

1819
cmake_minimum_required (VERSION 3.5)
1920
if (CMAKE_VERSION VERSION_GREATER_EQUAL "3.13.0")
@@ -157,10 +158,16 @@ if (MAY_USE_STATIC_RTL)
157158
tv_message_mp(STATUS "Link w/static RTL: ${TV_USE_STATIC_RTL}")
158159
endif()
159160

161+
option(TV_BUILD_TESTS "Build and run tests" OFF)
162+
160163
# Library
161164

162165
add_subdirectory(source)
163166

164167
# Examples
165168

166169
add_subdirectory(examples)
170+
171+
# Test
172+
173+
add_subdirectory(test)

README.md

+11
Original file line numberDiff line numberDiff line change
@@ -395,6 +395,17 @@ The following are new features not available in Borland's release of Turbo Visio
395395
void printMouseWheelState(ostream &, ushort wheelState);
396396
void printMouseEventFlags(ostream &, ushort eventFlags);
397397
```
398+
* New class `TKey` which can be used to define new key combinations (e.g. `Shift+Alt+Up`) by specifying a key code and a mask of key modifiers:
399+
```c++
400+
auto kbShiftAltUp = TKey(kbUp, kbShift | kbAltShift);
401+
assert(kbCtrlA == TKey('A', kbCtrlShift));
402+
assert(TKey(kbCtrlTab, kbShift) == TKey(kbTab, kbShift | kbCtrlShift));
403+
// Create menu hotkeys.
404+
new TMenuItem("~R~estart", cmRestart, TKey(kbDel, kbCtrlShift | kbAltShift), hcNoContext, "Ctrl-Alt-Del")
405+
// Examine KeyDown events:
406+
if (event.keyDown == TKey(kbEnter, kbShift))
407+
doStuff();
408+
```
398409
399410
## Screenshots
400411

include/tvision/menus.h

+10-10
Original file line numberDiff line numberDiff line change
@@ -44,13 +44,13 @@ class TMenuItem
4444

4545
TMenuItem( TStringView aName,
4646
ushort aCommand,
47-
ushort aKeyCode,
47+
TKey aKey,
4848
ushort aHelpCtx = hcNoContext,
4949
TStringView p = 0,
5050
TMenuItem *aNext = 0
5151
) noexcept;
5252
TMenuItem( TStringView aName,
53-
ushort aKeyCode,
53+
TKey aKey,
5454
TMenu *aSubMenu,
5555
ushort aHelpCtx = hcNoContext,
5656
TMenuItem *aNext = 0
@@ -64,7 +64,7 @@ class TMenuItem
6464
const char *name;
6565
ushort command;
6666
Boolean disabled;
67-
ushort keyCode;
67+
TKey keyCode;
6868
ushort helpCtx;
6969
union
7070
{
@@ -93,7 +93,7 @@ class TSubMenu : public TMenuItem
9393

9494
public:
9595

96-
TSubMenu( TStringView nm, ushort key, ushort helpCtx = hcNoContext ) noexcept;
96+
TSubMenu( TStringView nm, TKey key, ushort helpCtx = hcNoContext ) noexcept;
9797

9898
};
9999

@@ -154,7 +154,7 @@ class TMenuView : public TView
154154
virtual ushort getHelpCtx();
155155
virtual TPalette& getPalette() const;
156156
virtual void handleEvent( TEvent& event );
157-
TMenuItem *hotKey( ushort keyCode );
157+
TMenuItem *hotKey( TKey key );
158158
TMenuView *newSubView( const TRect& bounds,
159159
TMenu *aMenu,
160160
TMenuView *aParentMenu
@@ -179,7 +179,7 @@ class TMenuView : public TView
179179
TMenuView *topMenu();
180180
Boolean updateMenu( TMenu *menu );
181181
void do_a_select( TEvent& );
182-
TMenuItem *findHotKey( TMenuItem *p, ushort keyCode );
182+
TMenuItem *findHotKey( TMenuItem *p, TKey key );
183183

184184
private:
185185

@@ -402,25 +402,25 @@ class TStatusItem
402402
public:
403403

404404
TStatusItem( TStringView aText,
405-
ushort key,
405+
TKey aKey,
406406
ushort cmd,
407407
TStatusItem *aNext = 0
408408
) noexcept;
409409
~TStatusItem();
410410

411411
TStatusItem *next;
412412
char *text;
413-
ushort keyCode;
413+
TKey keyCode;
414414
ushort command;
415415

416416
};
417417

418418
inline TStatusItem::TStatusItem( TStringView aText,
419-
ushort key,
419+
TKey aKey,
420420
ushort cmd,
421421
TStatusItem *aNext
422422
) noexcept :
423-
next( aNext ), text( newStr(aText) ), keyCode( key ), command( cmd )
423+
next( aNext ), text( newStr(aText) ), keyCode( aKey ), command( cmd )
424424
{
425425
}
426426

include/tvision/system.h

+7-2
Original file line numberDiff line numberDiff line change
@@ -72,7 +72,6 @@ const int meTripleClick = 0x10;
7272

7373
#endif // __EVENT_CODES
7474

75-
7675
#if defined( Uses_TEvent ) && !defined( __TEvent )
7776
#define __TEvent
7877

@@ -203,14 +202,20 @@ struct KeyDownEvent
203202
char text[4];
204203
uchar textLength;
205204

206-
inline TStringView getText() const;
205+
TStringView getText() const;
206+
operator TKey() const;
207207
};
208208

209209
inline TStringView KeyDownEvent::getText() const
210210
{
211211
return TStringView(text, textLength);
212212
}
213213

214+
inline KeyDownEvent::operator TKey() const
215+
{
216+
return TKey(keyCode, controlKeyState);
217+
}
218+
214219
struct MessageEvent
215220
{
216221
ushort command;

include/tvision/tkeys.h

+99-20
Original file line numberDiff line numberDiff line change
@@ -13,20 +13,40 @@
1313
*
1414
*/
1515

16-
#if !defined( __TKEYS_H )
17-
#define __TKEYS_H
16+
#if defined( Uses_TKeys ) && !defined( __TKeys )
17+
#define __TKeys
1818

1919
#if defined( __FLAT__ ) && !defined( __WINDOWS_H )
2020
#include <tvision/compat/windows/windows.h>
2121
#endif
2222

23+
//// Key codes
24+
//
25+
// The following constants can be used to define menu hotkeys and to
26+
// examine the 'keyCode' field of 'evKeyDown' event records.
27+
//
28+
// Not all key combinations can be used in all platforms. In particular:
29+
//
30+
// * In 16-bit mode, the 'control key' definitions cannot be used to define
31+
// menu hotkeys, etc., which require scan codes. They are intended only
32+
// to provide mnemonic names for the ASCII control codes.
33+
//
34+
// * In 16-bit mode, keystrokes corresponding to the 'additional extended
35+
// key codes' are not reported.
36+
//
37+
// * Keystrokes corresponding to system shortcuts (e.g. Alt+F4 for 'close
38+
// window' in graphical environments) are not reported either.
39+
//
40+
// * In Unix, support for key combinations varies among terminal emulators.
41+
// Ctrl+H, Ctrl+I, Ctrl+J and Ctrl+M are not likely to work since they
42+
// usually represent Backspace, Tab and Enter.
43+
//
44+
// These constants do not cover all possible combinations of the Shift, Ctrl
45+
// and Alt modifiers. For that purpose, see the TKey class below.
46+
2347
const ushort
2448

25-
// Control keys
26-
//
27-
// NOTE: these Control key definitions are intended only to provide
28-
// mnemonic names for the ASCII control codes. In 16-bit mode, they
29-
// cannot be used to define menu hotkeys, etc., which require scan codes.
49+
// Control keys
3050

3151
kbCtrlA = 0x0001, kbCtrlB = 0x0002, kbCtrlC = 0x0003,
3252
kbCtrlD = 0x0004, kbCtrlE = 0x0005, kbCtrlF = 0x0006,
@@ -78,7 +98,7 @@ const ushort
7898
kbAlt0 = 0x8100, kbAltMinus = 0x8200, kbAltEqual = 0x8300,
7999
kbCtrlPgUp = 0x8400, kbNoKey = 0x0000,
80100

81-
// Additional extended key codes, usable in 32-bit mode
101+
// Additional extended key codes
82102

83103
kbAltEsc = 0x0100, kbAltBack = 0x0e00, kbF11 = 0x8500,
84104
kbF12 = 0x8600, kbShiftF11 = 0x8700, kbShiftF12 = 0x8800,
@@ -90,18 +110,17 @@ const ushort
90110
kbAltIns = 0xa200, kbAltDel = 0xa300, kbAltTab = 0xa500,
91111
kbAltEnter = 0xa600,
92112

93-
// Keyboard state and shift masks
94-
95-
// Changes for this version:
96-
// In 32-bit mode, distinguishing between the right and left shift
97-
// keys is not supported, and there is an additional new flag,
98-
// kbEnhanced, which is set if the key pressed was an enhanced key
99-
// (e.g. <insert> or <home>)
113+
//// Keyboard state and shift masks
114+
//
115+
// The following constants can be used when examining the 'controlKeyState'
116+
// field of an 'evKeyDown' event record.
100117
//
101-
// In 16-bit mode, there are additional flags for the right and left
102-
// Control and Alt keys, but this is not supported. The flags are
103-
// there for source compatibility with the 32-bit version which does
104-
// support this.
118+
// Distinguishing between the left and right Shift keys is only supported in
119+
// 16-bit mode, while distinguishing between the left and right Ctrl and Alt
120+
// keys is only supported in 32-bit DPMI and on Windows.
121+
//
122+
// The kbScrollState, kbNumState, kbCapsState and kbEnhanced flags are only
123+
// reported on DOS and Windows.
105124

106125
#if !defined( __FLAT__ )
107126
kbLeftShift = 0x0001,
@@ -134,4 +153,64 @@ const ushort
134153
kbInsState = 0x200; // Ensure this doesn't overlap above values
135154
#endif
136155

137-
#endif // __TKEYS_H
156+
#endif // __TKeys
157+
158+
#if !defined( __TKey )
159+
#define __TKey
160+
161+
//// TKey
162+
//
163+
// This class provides the ability to define new key combinations by
164+
// specifying a key code and a mask of key modifiers. These key combinations
165+
// can then be used to define menu hotkeys and examine 'evKeyDown' event
166+
// records.
167+
//
168+
// The only modifiers taken into account are Shift, Ctrl and Alt, making no
169+
// distinction between the left and right key on platforms that support it.
170+
//
171+
// Given that some key code constants already imply the presence of a key
172+
// modifier, there are key combinations which can be defined in multiple
173+
// ways. TKey ensures equality between all of them. For example:
174+
//
175+
// assert(kbCtrlA == TKey('A', kbCtrlShift));
176+
// assert(TKey(kbCtrlTab, kbShift) == TKey(kbTab, kbShift | kbCtrlShift));
177+
// assert(TKey(kbAltDel, kbCtrlShift) == TKey(kbCtrlDel, kbAltShift));
178+
179+
class TKey
180+
{
181+
public:
182+
183+
constexpr TKey() noexcept;
184+
TKey(ushort keyCode, ushort shiftState = 0) noexcept;
185+
186+
ushort code;
187+
ushort mods;
188+
};
189+
190+
inline constexpr TKey::TKey() noexcept :
191+
code(0),
192+
mods(0)
193+
{
194+
}
195+
196+
inline constexpr Boolean operator==(TKey a, TKey b) noexcept
197+
{
198+
return (a.code | (a.mods << 16)) == (b.code | (b.mods << 16));
199+
}
200+
201+
inline constexpr Boolean operator!=(TKey a, TKey b) noexcept
202+
{
203+
return !(a == b);
204+
}
205+
206+
inline ipstream& operator >> ( ipstream& is, TKey& p )
207+
{ return is >> p.code >> p.mods; }
208+
inline ipstream& operator >> ( ipstream& is, TKey*& p )
209+
{ return is >> p->code >> p->mods; }
210+
211+
inline opstream& operator << ( opstream& os, TKey& p )
212+
{ return os << p.code << p.mods; }
213+
inline opstream& operator << ( opstream& os, TKey* p )
214+
{ return os << p->code << p->mods; }
215+
216+
#endif // __TKey

include/tvision/tv.h

+1
Original file line numberDiff line numberDiff line change
@@ -57,6 +57,7 @@
5757

5858
#define Uses_EventCodes
5959
#define Uses_ViewCommands
60+
#define __INC_TKEYS_H
6061
#define __INC_STDDLG_H
6162

6263
#if defined( Uses_TApplication )

source/tvision/makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -208,7 +208,7 @@ TOBJS = pfxCOLORSEL.OBJ pfxDRIVERS.OBJ pfxDRIVERS2.OBJ pfxEDITSTAT.OBJ \
208208
pfxTSTATICT.OBJ pfxTSTATUSL.OBJ pfxTSTRCOLL.OBJ pfxTSTRLIST.OBJ \
209209
pfxTVALIDAT.OBJ pfxTVIEW.OBJ pfxTVTEXT1.OBJ pfxTVTEXT2.OBJ \
210210
pfxTWINDOW.OBJ pfxTMENUPOP.OBJ pfxPOPUPMNU.OBJ pfxTSTRVIEW.OBJ \
211-
pfxPRNTCNST.OBJ
211+
pfxPRNTCNST.OBJ pfxTKEY.OBJ
212212

213213
NOBJS = pfxNMBKGRND.OBJ pfxNMBUTTON.OBJ pfxNMCHDRDL.OBJ pfxNMCHKBOX.OBJ \
214214
pfxNMCLRSEL.OBJ pfxNMCLUSTR.OBJ pfxNMCOLLCT.OBJ pfxNMDIALOG.OBJ \

source/tvision/menu.cpp

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
#include <string.h>
2424
#endif // __STRING_H
2525

26-
TSubMenu::TSubMenu( TStringView nm, ushort key, ushort helpCtx ) noexcept :
26+
TSubMenu::TSubMenu( TStringView nm, TKey key, ushort helpCtx ) noexcept :
2727
TMenuItem( nm, key, new TMenu, helpCtx )
2828
{
2929
}

0 commit comments

Comments
 (0)