home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / NOTEPAD2.ZIP / MKEY.C < prev    next >
C/C++ Source or Header  |  1989-02-08  |  16KB  |  495 lines

  1. /*
  2.  * mkey.c -- Translate character messages into appropriate actions
  3.  *
  4.  * Created by Microsoft Corporation, 1989
  5.  */
  6.  
  7. #define INCL_WIN
  8. #include <os2.h>
  9. #include "mtypes.h"
  10. #include "mfuncs.h"
  11.  
  12. /***********************************************************************
  13. * Private cursor-movement functions
  14. ***********************************************************************/
  15.  
  16. /*
  17.  * VOID MoveCursorDown(PED ped, LINE lLines, BOOL fExtend)
  18.  *
  19.  * Move cursor down lLines lines.  If fExtend is TRUE, just move the
  20.  * cursor point; if fExtend is FALSE, move both cursor and anchor
  21.  * points.  Assumes properly-formatted text.
  22.  */
  23. #define MoveCursorDown(ped, lLines, fExtend)
  24.  
  25. /*
  26.  * VOID MoveCursorUp(PED ped, LINE lLines, BOOL fExtend)
  27.  *
  28.  * Move cursor up lLines lines.  If fExtend is TRUE, just move the
  29.  * cursor point; if fExtend is FALSE, move both cursor and anchor
  30.  * points.  Assumes properly-formatted text.
  31.  */
  32. #define MoveCursorUp(ped, lLines, fExtend)
  33.  
  34. /***********************************************************************
  35. * Virtual-key processing for command keys
  36. ***********************************************************************/
  37.  
  38. /*
  39.  * VOID VKInsert(PED ped, USHORT fus)
  40.  *
  41.  * Handle the Insert key, with flags in fus.
  42.  * SHIFT+INS -> Paste from clipboard
  43.  * CTRL+INS -> Copies to clipboard
  44.  * Shift takes precedence over Ctrl.
  45.  */
  46.  
  47. private VOID VKInsert(PED ped, USHORT fus)
  48. {
  49.         if (fus & KC_SHIFT) {
  50.                 if (ped->fTyping) {
  51.                         TxtClipPaste (ped,
  52.                                 TxtQueryAnchor(ped),
  53.                                 TxtQueryCursor(ped));
  54.                 }
  55.         } else if (fus & KC_CTRL) {
  56.                 TxtClipCopy (ped,
  57.                         TxtQueryAnchor(ped),
  58.                         TxtQueryCursor(ped));
  59.         }
  60. }
  61.  
  62. /*
  63.  * VOID VKDelete(PED ped, USHORT fus)
  64.  *
  65.  * Handle a series of presses of the DEL key.
  66.  * SHIFT+DEL -> cut to clipboard
  67.  * CTRL+DEL -> delete to end of line; if at end of line, delete line break
  68.  *    (if applicable)
  69.  * If any text is selected, delete it (and ignore cchRepeats).
  70.  * Otherwise, we normally delete the cchRepeats characters
  71.  * following the cursor.  In the case of a Ctrl-Del, however,
  72.  * we delete from the cursor to the end of the line; we don't
  73.  * delete the final \n on the line (if any) UNLESS it's the
  74.  * only character left on the line.
  75.  */
  76.  
  77. static VOID VKDelete(PED ped, USHORT fus)
  78. {
  79.     IPT iptAnchor, iptCursor, cchToEnd;
  80.  
  81.     if (!(ped->fTyping))
  82.         return;
  83.  
  84.     iptAnchor = TxtQueryAnchor(ped);
  85.     iptCursor = TxtQueryCursor(ped);
  86.     if (fus & KC_SHIFT)
  87.         TxtClipCut (ped,iptAnchor,iptCursor);
  88.     else if (fus & KC_CTRL) {
  89.         cchToEnd = TxtLengthToEOL(ped, iptCursor, FALSE);
  90.         if (cchToEnd == 0) {
  91.             TxtChange(ped, iptCursor,
  92.                     iptCursor+TxtLengthToEOL(ped,iptCursor,TRUE),
  93.                     NULL, 0);
  94.         } else {
  95.             TxtChange(ped, iptCursor, iptCursor+cchToEnd, NULL, 0);
  96.         }
  97.     } else {
  98.         if (iptAnchor == iptCursor) {
  99.             if (iptCursor < ped->iptMac) {
  100.                 TxtChange(ped,  iptCursor, iptCursor+1, NULL, 0);
  101.             }
  102.         } else {
  103.             TxtChange(ped, iptAnchor, iptCursor, NULL, 0);
  104.         }
  105.     }
  106. }
  107.  
  108. /*
  109.  * VOID VKBackspace(PED ped, SHORT cchRepeats)
  110.  *
  111.  * Handle a series of presses of the Backspace key.
  112.  * Reduce the selection to the cursor point, then delete the cchRepeats chars
  113.  * before the cursor.
  114.  */
  115. static VOID VKBackspace(PED ped, SHORT cchRepeats)
  116. {
  117.     IPT iptCursor;
  118.     IPT iptAnchor;
  119.  
  120.     iptCursor = TxtQueryCursor(ped);
  121.     iptAnchor = TxtQueryAnchor(ped);
  122.     if (iptAnchor == iptCursor) {
  123.         cchRepeats = (SHORT)min((IPT)cchRepeats,iptCursor);
  124.         TxtChange(ped, iptCursor-cchRepeats, iptCursor, NULL, 0);
  125.         TxtSetAnchorCursor(ped, iptCursor-cchRepeats,  iptCursor-cchRepeats);
  126.     } else {
  127.         TxtChange(ped, iptAnchor, iptCursor, NULL, 0);
  128.     }
  129.  
  130. }
  131.  
  132. /*
  133.  * VOID VKDown(PED ped, USHORT fus, SHORT cchRepeats)
  134.  *
  135.  * Handle a series of presses of the Down key.
  136.  * DOWN => selection region to one line down from current cursor
  137.  * SHIFT+DOWN => cursor to one line down from current cursor
  138.  * CTRL+DOWN => selection to end of doc
  139.  */
  140. static VOID VKDown(PED ped, USHORT fus, SHORT cchRepeats)
  141. {
  142.     IPT iptCursor;
  143.  
  144.     if (fus & KC_CTRL) {
  145.         iptCursor = TxtLength(ped);
  146.         TxtSetAnchorCursor(ped, iptCursor, iptCursor);
  147.     } else {
  148.         MoveCursorDown(ped, (LINE)cchRepeats, fus & KC_SHIFT);
  149.     cchRepeats = 0;
  150.     }
  151. }
  152.  
  153. /*
  154.  * VOID VKUp(PED ped, USHORT fus, SHORT cchRepeats)
  155.  *
  156.  * Handle a series of presses of the Up key.
  157.  * UP => selection region to one line up from current cursor
  158.  * SHIFT+UP => cursor to one line up from current cursor
  159.  * CTRL+UP => selection to beginning of first line of doc
  160.  */
  161. static VOID VKUp(PED ped, USHORT fus, SHORT cchRepeats)
  162. {
  163.         if (fus & KC_CTRL) {
  164.                 TxtSetAnchorCursor(ped, 0L, 0L);
  165.         } else {
  166.                 MoveCursorUp(ped, (LINE)cchRepeats, fus & KC_SHIFT);
  167.         cchRepeats = 0;
  168.         }
  169. }
  170.  
  171.  
  172. /*
  173.  * VOID VKPageDown(PED ped, USHORT usChar, USHORT fus, SHORT cchRepeats)
  174.  *
  175.  * Handle a series of presses of the PageDown key.
  176.  * PAGEDOWN => move selection region to one screenful down from cursor
  177.  * SHIFT+PAGEDOWN => move cursor one screenful down from cursor
  178.  * CTRL+PAGEDOWN is identical to CTRL+DOWN
  179.  */
  180. static VOID VKPageDown(PED ped, USHORT usChar, USHORT fus, SHORT cchRepeats)
  181. {
  182.     if (fus & KC_CTRL)
  183.         ProcessKey (ped, VK_DOWN, usChar, fus, cchRepeats);
  184.     else {
  185.         MoveCursorDown(ped, cchRepeats * max(1, ped->lyWndSize - 1),
  186.                 fus & KC_SHIFT);
  187.     }
  188. }
  189.  
  190.  
  191. /*
  192.  * VOID VKPageUp(PED ped, USHORT usChar, USHORT fus, SHORT cchRepeats)
  193.  *
  194.  * Handle a series of presses of the PageUp key.
  195.  * PAGEUP => move selection region to one screenful up from cursor
  196.  * SHIFT+PAGEUP => move cursor one screenful up from cursor
  197.  * CTRL+PAGEUP is identical to CTRL+UP
  198.  */
  199. static VOID VKPageUp(PED ped, USHORT usChar, USHORT fus, SHORT cchRepeats)
  200. {
  201.     if (fus & KC_CTRL)
  202.         ProcessKey (ped, VK_UP, usChar, fus, cchRepeats);
  203.     else {
  204.         MoveCursorUp(ped, cchRepeats * max(1, ped->lyWndSize - 1),
  205.                 fus & KC_SHIFT);
  206.     }
  207. }
  208.  
  209. /*
  210.  * VOID VKLeft(PED ped, USHORT fus, SHORT cchRepeats)
  211.  *
  212.  * Handle a series of presses of the Left key.
  213.  * LEFT => move selection to one ipt left of cursor point
  214.  * SHIFT+LEFT => move cursor one ipt left
  215.  * CTRL+LEFT => moves selection region to previous word beginning
  216.  */
  217. static VOID VKLeft(PED ped, USHORT fus, SHORT cchRepeats)
  218. {
  219.         IPT iptCursor;
  220.  
  221.         if (!(fus & KC_CTRL)) {
  222.                 iptCursor = max((IPT)0, TxtQueryCursor(ped)-(IPT)cchRepeats);
  223.                 TxtSetAnchorCursor(ped,
  224.                         (fus&KC_SHIFT)?(IPT)(-1):iptCursor,
  225.                         iptCursor);
  226.         }
  227. }
  228.  
  229. /*
  230.  * VOID VKRight(PED ped, USHORT fus, SHORT cchRepeats)
  231.  *
  232.  * Handle a series of presses of the Right key.
  233.  * RIGHT => move selection to one ipt right of cursor point
  234.  * SHIFT+RIGHT => move cursor one ipt right
  235.  * CTRL+RIGHT => moves selection region to next word ending
  236.  */
  237. static VOID VKRight(PED ped, USHORT fus, SHORT cchRepeats)
  238. {
  239.         IPT iptCursor;
  240.  
  241.         if (! (fus & KC_CTRL) ) {
  242.                 iptCursor = min(TxtLength(ped),
  243.                                 TxtQueryCursor(ped)+(IPT)cchRepeats);
  244.                 TxtSetAnchorCursor(ped,
  245.                         (fus&KC_SHIFT)?(IPT)(-1):iptCursor,
  246.                         iptCursor);
  247.         }
  248. }
  249.  
  250.  
  251. /*
  252.  * VOID VKHome(PED ped, USHORT fus)
  253.  *
  254.  * Handle a series of presses of the Home key.  Repeats are ignored.
  255.  * HOME => moves the selection region to the beginning of the cursor line
  256.  * SHIFT+HOME => moves cursor to beginning of cursor line
  257.  * CTRL+HOME => moves selection region to beginning of document
  258.  */
  259. static VOID VKHome(PED ped, USHORT fus)
  260. {
  261.         IPT iptCursor;
  262.  
  263.         if (fus & KC_CTRL) {
  264.                 TxtSetAnchorCursor(ped, 0L, 0L);
  265.         } else {
  266.                 iptCursor = TxtQueryCursor(ped);
  267.                 iptCursor = iptCursor - TxtLengthToBOL(ped,iptCursor);
  268.                 TxtSetAnchorCursor(ped,
  269.                         (fus&KC_SHIFT)?(IPT)(-1):iptCursor,
  270.                         iptCursor);
  271.         }
  272. }
  273.  
  274. /*
  275.  * VOID VKEnd(PED ped, USHORT fus)
  276.  *
  277.  * Handle a series of presses of the End key.  Repeats are ignored.
  278.  * END => moves the selection region to the end of the cursor line
  279.  * SHIFT+END => moves cursor to end of cursor line
  280.  * CTRL+END => moves selection region to end of document
  281.  */
  282. static VOID VKEnd(PED ped, USHORT fus)
  283. {
  284.         IPT iptCursor;
  285.  
  286.         if (fus & KC_CTRL) {
  287.                 iptCursor = TxtLength(ped);
  288.                 TxtSetAnchorCursor(ped,
  289.                                    (fus&KC_SHIFT)?(IPT)(-1):iptCursor,
  290.                                    iptCursor);
  291.         } else {
  292.                 iptCursor = TxtQueryCursor(ped);
  293.                 iptCursor = iptCursor + TxtLengthToEOL(ped,iptCursor,FALSE);
  294.                 TxtSetAnchorCursor(ped,
  295.                         (fus&KC_SHIFT)?(IPT)(-1):iptCursor,
  296.                         iptCursor);
  297.         }
  298. }
  299.  
  300. /*
  301.  * VOID InsertTyping(PED ped, USHORT usChar,
  302.  *                   USHORT fus, SHORT cchRepeats)
  303.  *
  304.  * Handle inserting normal typed text.
  305.  *
  306.  * Dead-key support works like this: When the dead key is
  307.  * presed, the corresponding diacritical mark is inserted at
  308.  * the cursor position, but the cursor isn't advanced.
  309.  * The next char is handled as follows:
  310.  * - If it's a valid composite key (i.e., a vowel to be
  311.  *   composed with the diacritical), the mark is replaced by
  312.  *   the appropirate diacriticized character.
  313.  * - If it's an invalid composite key, the diacritical
  314.  *   (which is presumed to still follow the cursor) is removed.
  315.  *   Unless the invalid composite was a backspace, we beep.
  316.  * - If it's another dead key, we replace the original
  317.  *   diacritical mark with the new one, and keep waiting
  318.  *   for a composite key.
  319.  *
  320.  * Results aren't defined if the user selects using the
  321.  * mouse between the relevant keypresses, except that they
  322.  * won't cause problems.
  323.  *
  324.  * The above translates to the following algorithm:
  325.  *
  326.  * - If KC_INVALIDCOMP or KC_COMPOSITE is set, delete the
  327.  *   presumed diacritical following the cursor.
  328.  * - If KC_INVALIDCOMP is set, beep (unless usChar is \b).
  329.  * - If KC_INVALIDCOMP isn't set, then insert the character
  330.  *   regardless of its dead-key status.  If KC_DEADKEY is
  331.  *   set, we don't advance the cursor or pay attention to
  332.  *   cchRepeats.
  333.  */
  334. private VOID InsertTyping(PED ped, USHORT usChar,
  335.         USHORT fus, SHORT cchRepeats)
  336. {
  337.         IPT iptBegin, iptEnd;
  338.         CHAR ch;
  339.         SHORT cch;
  340.  
  341.         // if this is the second key of a dead-key combo,
  342.         // delete char after cursor; if a valid composite,
  343.         // prepare to insert at that pos
  344.  
  345.         iptBegin = TxtQueryMinSel(ped);
  346.         iptEnd = TxtQueryMaxSel(ped);
  347.         if (fus & (KC_INVALIDCOMP | KC_COMPOSITE)) {
  348.                 iptEnd++;
  349.         }
  350.  
  351.         if (fus & KC_INVALIDCOMP) {
  352.                 cchRepeats = 0;
  353.                 if (usChar != '\b') {
  354.                         // a backspace unrelated to dead keys
  355.                         // would've been processed as
  356.                         // VK_BACKSPACE
  357.                         WinAlarm (HWND_DESKTOP, WA_WARNING);
  358.                 }
  359.         } else if (fus & KC_DEADKEY) {
  360.                 cchRepeats = 1;
  361.                 WinShowCursor (ped->hwnd, FALSE);
  362.         }
  363.  
  364.         // Insert space for cchRepeats chars at the
  365.         // end of ppr, and fill it in with copies of
  366.         // the typed char.
  367.         cch = cchRepeats;
  368.         ch = (CHAR)usChar;
  369.         while (cch > 0) {
  370.                 TxtChange(ped, iptBegin, iptEnd, &ch, 1);
  371.                 iptBegin = iptEnd = iptBegin+1;
  372.                 cch --;
  373.         }
  374.  
  375.         // if a new diacritical, move cursor back one
  376.         if (!(fus & KC_DEADKEY) || (fus & (KC_COMPOSITE | KC_INVALIDCOMP))) {
  377.                 TxtSetAnchorCursor(ped, iptBegin, iptBegin);
  378.         }
  379.         if (fus & KC_DEADKEY) {
  380.                 WinShowCursor (ped->hwnd, TRUE);
  381.         }
  382. }
  383.  
  384. /*
  385.  * VOID ProcessKey (PED ped, USHORT usVirtKey, USHORT usChar,
  386.  *       USHORT fus, SHORT cchRepeats)
  387.  *
  388.  * Responds to a WM_CHAR message sent to the MLE window procedure.
  389.  * usVirtKey is the virtual key, usChar the character, and fus the
  390.  * flags (which are guaranteed not to include KC_KEYUP).  cchRepeats is
  391.  * usually 1, but if the same key was held down and we couldn't process
  392.  * the WM_CHAR messages fast enough, it'll be > 1; we can safely ignore
  393.  * it, or we can process the keys "all at once" for greater speed.
  394.  */
  395.  
  396. public VOID ProcessKey (PED ped, USHORT usVirtKey, USHORT usChar, USHORT fus,
  397.                         SHORT cchRepeats)
  398. {
  399.     /*  Process as a virtual key or a char key. If we've got a virtual key
  400.      *  that's not being used for dead-key purposes -- and it's not an
  401.      *  unshifted char, except backspace -- then we process it as a vkey.
  402.      *  Otherwise treat it as a char.
  403.      */
  404.  
  405.         if ((fus & KC_VIRTUALKEY) &&
  406.                 ! (fus & (KC_DEADKEY | KC_COMPOSITE | KC_INVALIDCOMP)) &&
  407.                 (!(fus & KC_CHAR) || (fus & KC_SHIFT) || (usChar=='\b'))) {
  408.                 switch (usVirtKey) {       /* branch on virtual key code */
  409.                 case VK_INSERT:
  410.                         VKInsert(ped,fus);
  411.                         break;
  412.                 case VK_DELETE:
  413.                         VKDelete(ped,fus);
  414.                         break;
  415.                 case VK_BACKSPACE:
  416.                         VKBackspace(ped,cchRepeats);
  417.                         break;
  418.                 case VK_DOWN:
  419.                         VKDown(ped,fus,cchRepeats);
  420.                         break;
  421.                 case VK_UP:
  422.                         VKUp(ped,fus,cchRepeats);
  423.                         break;
  424.                 case VK_PAGEDOWN:
  425.                         VKPageDown(ped,usChar,fus,cchRepeats);
  426.                         break;
  427.                 case VK_PAGEUP:
  428.                         VKPageUp(ped,usChar,fus,cchRepeats);
  429.                         break;
  430.                 case VK_LEFT:
  431.                         VKLeft(ped,fus,cchRepeats);
  432.                         break;
  433.                 case VK_RIGHT:
  434.                         VKRight(ped,fus,cchRepeats);
  435.                         break;
  436.                 case VK_HOME:
  437.                         VKHome(ped,fus);
  438.                         break;
  439.                 case VK_END:
  440.                         VKEnd(ped,fus);
  441.                         break;
  442.                 }
  443.         } else if (fus & (KC_CHAR | KC_DEADKEY)) {
  444.                 switch (usChar) {
  445.                 case '\r':          // enter -- change to \n and fall through
  446.                         usChar = (USHORT) '\n';
  447.                 default:
  448.                         InsertTyping(ped,usChar,fus,cchRepeats);
  449.                 }
  450.         }
  451. }
  452.  
  453.  
  454.  
  455. /*
  456.  * BOOL QueryTyping(PED ped)
  457.  *
  458.  * returns whether typing is allowed for the given edit control.
  459.  */
  460. public BOOL QueryTyping(PED ped)
  461. {
  462.         return(ped->fTyping);
  463. }
  464.  
  465.  
  466. /*
  467.  * BOOL SetTyping(PED ped, BOOL fTyping)
  468.  *
  469.  * sets whether typing is allowed for the given edit control; returns old
  470.  * setting.
  471.  */
  472. public BOOL SetTyping(PED ped, BOOL fTyping)
  473. {
  474.         if (ped->fTyping) {
  475.                 ped->fTyping = fTyping;
  476.                 return(TRUE);
  477.         } else {
  478.                 ped->fTyping = fTyping;
  479.                 return(FALSE);
  480.         }
  481. }
  482.  
  483.  
  484. /*
  485.  * BOOL KbdInit(PED ped)
  486.  *
  487.  * Initializes the Keyboard Manager
  488.  */
  489. public BOOL KbdInit(PED ped)
  490. {
  491.         ped->fTyping = TRUE;
  492.         return(TRUE);
  493. }
  494.  
  495.