home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
OS/2 Shareware BBS: 5 Edit
/
05-Edit.zip
/
NOTEPAD2.ZIP
/
MKEY.C
< prev
next >
Wrap
C/C++ Source or Header
|
1989-02-08
|
16KB
|
495 lines
/*
* mkey.c -- Translate character messages into appropriate actions
*
* Created by Microsoft Corporation, 1989
*/
#define INCL_WIN
#include <os2.h>
#include "mtypes.h"
#include "mfuncs.h"
/***********************************************************************
* Private cursor-movement functions
***********************************************************************/
/*
* VOID MoveCursorDown(PED ped, LINE lLines, BOOL fExtend)
*
* Move cursor down lLines lines. If fExtend is TRUE, just move the
* cursor point; if fExtend is FALSE, move both cursor and anchor
* points. Assumes properly-formatted text.
*/
#define MoveCursorDown(ped, lLines, fExtend)
/*
* VOID MoveCursorUp(PED ped, LINE lLines, BOOL fExtend)
*
* Move cursor up lLines lines. If fExtend is TRUE, just move the
* cursor point; if fExtend is FALSE, move both cursor and anchor
* points. Assumes properly-formatted text.
*/
#define MoveCursorUp(ped, lLines, fExtend)
/***********************************************************************
* Virtual-key processing for command keys
***********************************************************************/
/*
* VOID VKInsert(PED ped, USHORT fus)
*
* Handle the Insert key, with flags in fus.
* SHIFT+INS -> Paste from clipboard
* CTRL+INS -> Copies to clipboard
* Shift takes precedence over Ctrl.
*/
private VOID VKInsert(PED ped, USHORT fus)
{
if (fus & KC_SHIFT) {
if (ped->fTyping) {
TxtClipPaste (ped,
TxtQueryAnchor(ped),
TxtQueryCursor(ped));
}
} else if (fus & KC_CTRL) {
TxtClipCopy (ped,
TxtQueryAnchor(ped),
TxtQueryCursor(ped));
}
}
/*
* VOID VKDelete(PED ped, USHORT fus)
*
* Handle a series of presses of the DEL key.
* SHIFT+DEL -> cut to clipboard
* CTRL+DEL -> delete to end of line; if at end of line, delete line break
* (if applicable)
* If any text is selected, delete it (and ignore cchRepeats).
* Otherwise, we normally delete the cchRepeats characters
* following the cursor. In the case of a Ctrl-Del, however,
* we delete from the cursor to the end of the line; we don't
* delete the final \n on the line (if any) UNLESS it's the
* only character left on the line.
*/
static VOID VKDelete(PED ped, USHORT fus)
{
IPT iptAnchor, iptCursor, cchToEnd;
if (!(ped->fTyping))
return;
iptAnchor = TxtQueryAnchor(ped);
iptCursor = TxtQueryCursor(ped);
if (fus & KC_SHIFT)
TxtClipCut (ped,iptAnchor,iptCursor);
else if (fus & KC_CTRL) {
cchToEnd = TxtLengthToEOL(ped, iptCursor, FALSE);
if (cchToEnd == 0) {
TxtChange(ped, iptCursor,
iptCursor+TxtLengthToEOL(ped,iptCursor,TRUE),
NULL, 0);
} else {
TxtChange(ped, iptCursor, iptCursor+cchToEnd, NULL, 0);
}
} else {
if (iptAnchor == iptCursor) {
if (iptCursor < ped->iptMac) {
TxtChange(ped, iptCursor, iptCursor+1, NULL, 0);
}
} else {
TxtChange(ped, iptAnchor, iptCursor, NULL, 0);
}
}
}
/*
* VOID VKBackspace(PED ped, SHORT cchRepeats)
*
* Handle a series of presses of the Backspace key.
* Reduce the selection to the cursor point, then delete the cchRepeats chars
* before the cursor.
*/
static VOID VKBackspace(PED ped, SHORT cchRepeats)
{
IPT iptCursor;
IPT iptAnchor;
iptCursor = TxtQueryCursor(ped);
iptAnchor = TxtQueryAnchor(ped);
if (iptAnchor == iptCursor) {
cchRepeats = (SHORT)min((IPT)cchRepeats,iptCursor);
TxtChange(ped, iptCursor-cchRepeats, iptCursor, NULL, 0);
TxtSetAnchorCursor(ped, iptCursor-cchRepeats, iptCursor-cchRepeats);
} else {
TxtChange(ped, iptAnchor, iptCursor, NULL, 0);
}
}
/*
* VOID VKDown(PED ped, USHORT fus, SHORT cchRepeats)
*
* Handle a series of presses of the Down key.
* DOWN => selection region to one line down from current cursor
* SHIFT+DOWN => cursor to one line down from current cursor
* CTRL+DOWN => selection to end of doc
*/
static VOID VKDown(PED ped, USHORT fus, SHORT cchRepeats)
{
IPT iptCursor;
if (fus & KC_CTRL) {
iptCursor = TxtLength(ped);
TxtSetAnchorCursor(ped, iptCursor, iptCursor);
} else {
MoveCursorDown(ped, (LINE)cchRepeats, fus & KC_SHIFT);
cchRepeats = 0;
}
}
/*
* VOID VKUp(PED ped, USHORT fus, SHORT cchRepeats)
*
* Handle a series of presses of the Up key.
* UP => selection region to one line up from current cursor
* SHIFT+UP => cursor to one line up from current cursor
* CTRL+UP => selection to beginning of first line of doc
*/
static VOID VKUp(PED ped, USHORT fus, SHORT cchRepeats)
{
if (fus & KC_CTRL) {
TxtSetAnchorCursor(ped, 0L, 0L);
} else {
MoveCursorUp(ped, (LINE)cchRepeats, fus & KC_SHIFT);
cchRepeats = 0;
}
}
/*
* VOID VKPageDown(PED ped, USHORT usChar, USHORT fus, SHORT cchRepeats)
*
* Handle a series of presses of the PageDown key.
* PAGEDOWN => move selection region to one screenful down from cursor
* SHIFT+PAGEDOWN => move cursor one screenful down from cursor
* CTRL+PAGEDOWN is identical to CTRL+DOWN
*/
static VOID VKPageDown(PED ped, USHORT usChar, USHORT fus, SHORT cchRepeats)
{
if (fus & KC_CTRL)
ProcessKey (ped, VK_DOWN, usChar, fus, cchRepeats);
else {
MoveCursorDown(ped, cchRepeats * max(1, ped->lyWndSize - 1),
fus & KC_SHIFT);
}
}
/*
* VOID VKPageUp(PED ped, USHORT usChar, USHORT fus, SHORT cchRepeats)
*
* Handle a series of presses of the PageUp key.
* PAGEUP => move selection region to one screenful up from cursor
* SHIFT+PAGEUP => move cursor one screenful up from cursor
* CTRL+PAGEUP is identical to CTRL+UP
*/
static VOID VKPageUp(PED ped, USHORT usChar, USHORT fus, SHORT cchRepeats)
{
if (fus & KC_CTRL)
ProcessKey (ped, VK_UP, usChar, fus, cchRepeats);
else {
MoveCursorUp(ped, cchRepeats * max(1, ped->lyWndSize - 1),
fus & KC_SHIFT);
}
}
/*
* VOID VKLeft(PED ped, USHORT fus, SHORT cchRepeats)
*
* Handle a series of presses of the Left key.
* LEFT => move selection to one ipt left of cursor point
* SHIFT+LEFT => move cursor one ipt left
* CTRL+LEFT => moves selection region to previous word beginning
*/
static VOID VKLeft(PED ped, USHORT fus, SHORT cchRepeats)
{
IPT iptCursor;
if (!(fus & KC_CTRL)) {
iptCursor = max((IPT)0, TxtQueryCursor(ped)-(IPT)cchRepeats);
TxtSetAnchorCursor(ped,
(fus&KC_SHIFT)?(IPT)(-1):iptCursor,
iptCursor);
}
}
/*
* VOID VKRight(PED ped, USHORT fus, SHORT cchRepeats)
*
* Handle a series of presses of the Right key.
* RIGHT => move selection to one ipt right of cursor point
* SHIFT+RIGHT => move cursor one ipt right
* CTRL+RIGHT => moves selection region to next word ending
*/
static VOID VKRight(PED ped, USHORT fus, SHORT cchRepeats)
{
IPT iptCursor;
if (! (fus & KC_CTRL) ) {
iptCursor = min(TxtLength(ped),
TxtQueryCursor(ped)+(IPT)cchRepeats);
TxtSetAnchorCursor(ped,
(fus&KC_SHIFT)?(IPT)(-1):iptCursor,
iptCursor);
}
}
/*
* VOID VKHome(PED ped, USHORT fus)
*
* Handle a series of presses of the Home key. Repeats are ignored.
* HOME => moves the selection region to the beginning of the cursor line
* SHIFT+HOME => moves cursor to beginning of cursor line
* CTRL+HOME => moves selection region to beginning of document
*/
static VOID VKHome(PED ped, USHORT fus)
{
IPT iptCursor;
if (fus & KC_CTRL) {
TxtSetAnchorCursor(ped, 0L, 0L);
} else {
iptCursor = TxtQueryCursor(ped);
iptCursor = iptCursor - TxtLengthToBOL(ped,iptCursor);
TxtSetAnchorCursor(ped,
(fus&KC_SHIFT)?(IPT)(-1):iptCursor,
iptCursor);
}
}
/*
* VOID VKEnd(PED ped, USHORT fus)
*
* Handle a series of presses of the End key. Repeats are ignored.
* END => moves the selection region to the end of the cursor line
* SHIFT+END => moves cursor to end of cursor line
* CTRL+END => moves selection region to end of document
*/
static VOID VKEnd(PED ped, USHORT fus)
{
IPT iptCursor;
if (fus & KC_CTRL) {
iptCursor = TxtLength(ped);
TxtSetAnchorCursor(ped,
(fus&KC_SHIFT)?(IPT)(-1):iptCursor,
iptCursor);
} else {
iptCursor = TxtQueryCursor(ped);
iptCursor = iptCursor + TxtLengthToEOL(ped,iptCursor,FALSE);
TxtSetAnchorCursor(ped,
(fus&KC_SHIFT)?(IPT)(-1):iptCursor,
iptCursor);
}
}
/*
* VOID InsertTyping(PED ped, USHORT usChar,
* USHORT fus, SHORT cchRepeats)
*
* Handle inserting normal typed text.
*
* Dead-key support works like this: When the dead key is
* presed, the corresponding diacritical mark is inserted at
* the cursor position, but the cursor isn't advanced.
* The next char is handled as follows:
* - If it's a valid composite key (i.e., a vowel to be
* composed with the diacritical), the mark is replaced by
* the appropirate diacriticized character.
* - If it's an invalid composite key, the diacritical
* (which is presumed to still follow the cursor) is removed.
* Unless the invalid composite was a backspace, we beep.
* - If it's another dead key, we replace the original
* diacritical mark with the new one, and keep waiting
* for a composite key.
*
* Results aren't defined if the user selects using the
* mouse between the relevant keypresses, except that they
* won't cause problems.
*
* The above translates to the following algorithm:
*
* - If KC_INVALIDCOMP or KC_COMPOSITE is set, delete the
* presumed diacritical following the cursor.
* - If KC_INVALIDCOMP is set, beep (unless usChar is \b).
* - If KC_INVALIDCOMP isn't set, then insert the character
* regardless of its dead-key status. If KC_DEADKEY is
* set, we don't advance the cursor or pay attention to
* cchRepeats.
*/
private VOID InsertTyping(PED ped, USHORT usChar,
USHORT fus, SHORT cchRepeats)
{
IPT iptBegin, iptEnd;
CHAR ch;
SHORT cch;
// if this is the second key of a dead-key combo,
// delete char after cursor; if a valid composite,
// prepare to insert at that pos
iptBegin = TxtQueryMinSel(ped);
iptEnd = TxtQueryMaxSel(ped);
if (fus & (KC_INVALIDCOMP | KC_COMPOSITE)) {
iptEnd++;
}
if (fus & KC_INVALIDCOMP) {
cchRepeats = 0;
if (usChar != '\b') {
// a backspace unrelated to dead keys
// would've been processed as
// VK_BACKSPACE
WinAlarm (HWND_DESKTOP, WA_WARNING);
}
} else if (fus & KC_DEADKEY) {
cchRepeats = 1;
WinShowCursor (ped->hwnd, FALSE);
}
// Insert space for cchRepeats chars at the
// end of ppr, and fill it in with copies of
// the typed char.
cch = cchRepeats;
ch = (CHAR)usChar;
while (cch > 0) {
TxtChange(ped, iptBegin, iptEnd, &ch, 1);
iptBegin = iptEnd = iptBegin+1;
cch --;
}
// if a new diacritical, move cursor back one
if (!(fus & KC_DEADKEY) || (fus & (KC_COMPOSITE | KC_INVALIDCOMP))) {
TxtSetAnchorCursor(ped, iptBegin, iptBegin);
}
if (fus & KC_DEADKEY) {
WinShowCursor (ped->hwnd, TRUE);
}
}
/*
* VOID ProcessKey (PED ped, USHORT usVirtKey, USHORT usChar,
* USHORT fus, SHORT cchRepeats)
*
* Responds to a WM_CHAR message sent to the MLE window procedure.
* usVirtKey is the virtual key, usChar the character, and fus the
* flags (which are guaranteed not to include KC_KEYUP). cchRepeats is
* usually 1, but if the same key was held down and we couldn't process
* the WM_CHAR messages fast enough, it'll be > 1; we can safely ignore
* it, or we can process the keys "all at once" for greater speed.
*/
public VOID ProcessKey (PED ped, USHORT usVirtKey, USHORT usChar, USHORT fus,
SHORT cchRepeats)
{
/* Process as a virtual key or a char key. If we've got a virtual key
* that's not being used for dead-key purposes -- and it's not an
* unshifted char, except backspace -- then we process it as a vkey.
* Otherwise treat it as a char.
*/
if ((fus & KC_VIRTUALKEY) &&
! (fus & (KC_DEADKEY | KC_COMPOSITE | KC_INVALIDCOMP)) &&
(!(fus & KC_CHAR) || (fus & KC_SHIFT) || (usChar=='\b'))) {
switch (usVirtKey) { /* branch on virtual key code */
case VK_INSERT:
VKInsert(ped,fus);
break;
case VK_DELETE:
VKDelete(ped,fus);
break;
case VK_BACKSPACE:
VKBackspace(ped,cchRepeats);
break;
case VK_DOWN:
VKDown(ped,fus,cchRepeats);
break;
case VK_UP:
VKUp(ped,fus,cchRepeats);
break;
case VK_PAGEDOWN:
VKPageDown(ped,usChar,fus,cchRepeats);
break;
case VK_PAGEUP:
VKPageUp(ped,usChar,fus,cchRepeats);
break;
case VK_LEFT:
VKLeft(ped,fus,cchRepeats);
break;
case VK_RIGHT:
VKRight(ped,fus,cchRepeats);
break;
case VK_HOME:
VKHome(ped,fus);
break;
case VK_END:
VKEnd(ped,fus);
break;
}
} else if (fus & (KC_CHAR | KC_DEADKEY)) {
switch (usChar) {
case '\r': // enter -- change to \n and fall through
usChar = (USHORT) '\n';
default:
InsertTyping(ped,usChar,fus,cchRepeats);
}
}
}
/*
* BOOL QueryTyping(PED ped)
*
* returns whether typing is allowed for the given edit control.
*/
public BOOL QueryTyping(PED ped)
{
return(ped->fTyping);
}
/*
* BOOL SetTyping(PED ped, BOOL fTyping)
*
* sets whether typing is allowed for the given edit control; returns old
* setting.
*/
public BOOL SetTyping(PED ped, BOOL fTyping)
{
if (ped->fTyping) {
ped->fTyping = fTyping;
return(TRUE);
} else {
ped->fTyping = fTyping;
return(FALSE);
}
}
/*
* BOOL KbdInit(PED ped)
*
* Initializes the Keyboard Manager
*/
public BOOL KbdInit(PED ped)
{
ped->fTyping = TRUE;
return(TRUE);
}