home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 5 Edit / 05-Edit.zip / ue312os2.zip / src / mswinput.c < prev    next >
C/C++ Source or Header  |  1994-08-26  |  11KB  |  392 lines

  1. /* The routines in this file provide keyboard and mouse input support
  2.    under the Microsoft Windows environment on an IBM-PC or compatible
  3.    computer.
  4.  
  5.    Must be compiled with Borland C++ 2.0 or MSC 6.0 or later versions.
  6.  
  7.    It should not be compiled if the WINDOW_MSWIN symbol is not set */
  8.  
  9. #include    "estruct.h"
  10. #include    "elang.h"
  11. #include    <stdio.h>
  12. #include    <time.h>
  13. #include    "eproto.h"
  14. #include    "edef.h"
  15.  
  16. #include    "mswin.h"
  17.  
  18. #define IBUFSIZE    64      /* this must be a power of 2 */
  19.  
  20. static unsigned char in_buf[IBUFSIZE];  /* input character buffer */
  21. static int in_next = 0;                 /* pos to retrieve next input character */
  22. static int in_last = 0;                 /* pos to place most recent input character */
  23. static int in_free = 0;                 /* number of unused char entries */
  24.  
  25. static int vk_at = -1;                  /* VK code for '@' key */
  26.  
  27. /* in_init: initialize the input stream buffer */
  28. /* =======                                     */
  29.  
  30. void    in_init (void)
  31. {
  32.     /*-initialize input stream buffer */
  33.     in_next = in_last = 0;
  34.     in_free = IBUFSIZE;
  35.     
  36.     /*-initialize vk_at to try to support the popular ^@ */
  37.     vk_at = VkKeyScan ('@');
  38.     if ((vk_at >> 8) != 1) {
  39.         /* not a shifted key. no cigar! */
  40.         vk_at = -1;
  41.     }
  42. } /* in_init */
  43.  
  44. /* in_room: is there enough room for n chars ? */
  45. /* =======                                     */
  46.  
  47. BOOL    in_room (int n)
  48. {
  49.     if (n <= in_free) return TRUE;
  50.     else {
  51.         MessageBeep (0);
  52.     return FALSE;
  53.     }
  54. } /* in_room */
  55.  
  56. /* in_check:    is the input buffer non empty? */
  57. /* ========                                    */
  58.  
  59. BOOL    in_check (void)
  60. {
  61.     if (in_next == in_last)
  62.         return(FALSE);
  63.     else
  64.         return(TRUE);
  65. } /* in_check */
  66.  
  67. /* in_put:  enter an event into the input buffer */
  68. /* ======                                        */
  69.  
  70. void    in_put (int event)
  71. {
  72.     in_buf[in_last++] = event;
  73.     in_last &= (IBUFSIZE - 1);
  74.     --in_free;
  75. } /* in_put */
  76.  
  77. /* in_get:  get an event from the input buffer */
  78. /* ======                                      */
  79.  
  80. int in_get (void)
  81. {
  82.     register int event;    /* event to return */
  83.  
  84.     event = in_buf[in_next++];
  85.     in_next &= (IBUFSIZE - 1);
  86.     ++in_free;
  87.     return(event);
  88. } /* in_get */
  89.  
  90. /* typahead:    TRUE if there are typeahead characters in the input stream */
  91. /* ========                                                                */
  92.  
  93. PASCAL typahead (void)
  94. {
  95.     if (in_check()) return TRUE;
  96.     else return FALSE;
  97. } /* typahead */
  98.  
  99. /* EatKey: processes WM_(SYS)KEYxxx and WM_(SYS/MENU)CHAR messages */
  100. /* ======                                                          */
  101.  
  102. BOOL FAR PASCAL EatKey (UINT MsgCode, UINT wParam, LONG lParam)
  103.  
  104. /* This function must be called for each WM_(SYS)KEYxxx or
  105.    WM_(SYS/MENU)CHAR message. It returns TRUE if it has taken possesion
  106.    of the keyboard action. In that case, the message processing should
  107.    be terminated */
  108. {
  109.     int     evt = -1;       /* -1 means: key not for emacs */
  110.     WORD    prefix = 0;
  111.     WORD    Key;
  112.  
  113.     if (IsIconic (hFrameWnd)) return FALSE;   /* no input while fully
  114.                          iconic */
  115.     Key = LOWORD(wParam);
  116.     
  117.     switch (MsgCode) {
  118.         
  119.     case WM_KEYDOWN:
  120. KeyDown:
  121.         /*-process the non-ascii keys (Page-up, Page-down, End, Home,
  122.        Arrows, Insert, Delete, function keys) */
  123.     prefix |= SPEC;
  124.     if (GetKeyState (VK_CONTROL) < 0) prefix |= CTRL;
  125.     if (GetKeyState (VK_SHIFT) < 0) prefix |= SHFT;
  126.     switch (Key) {
  127.  
  128.     case VK_HOME:
  129.         evt = '<';
  130.         break;
  131.     case VK_UP:
  132.         evt = 'P';
  133.         break;
  134.     case VK_PRIOR:  /* Page-up */
  135.         evt = 'Z';
  136.         break;
  137.     case VK_LEFT:
  138.         evt = 'B';
  139.         break;
  140.     case VK_RIGHT:
  141.         evt = 'F';
  142.         break;
  143.     case VK_END:
  144.         evt = '>';
  145.         break;
  146.     case VK_DOWN:
  147.         evt = 'N';
  148.         break;
  149.     case VK_NEXT:   /* Page-down */
  150.         evt = 'V';
  151.         break;
  152.     case VK_INSERT:
  153.         evt = 'C';
  154.         break;
  155.     case VK_DELETE:
  156.         evt = 'D';
  157.         break;
  158.     default:
  159.         if ((Key >= VK_F1) && (Key <= VK_F10)) {    /* function key */
  160.         if (Key == VK_F10) evt = '0';
  161.         else evt = Key - VK_F1 + '1';
  162.         }
  163.         else if ((vk_at > 0) && (Key == LOBYTE(vk_at)) &&
  164.                      ((prefix & (SHFT | CTRL)) == CTRL)) {
  165.                 /* we assume a ^@ or A-^@ */
  166.                 prefix &= ALTD;
  167.                 evt = 0;
  168.             }
  169.         break;
  170.     }
  171.     break;
  172.  
  173.     case WM_SYSKEYDOWN:
  174.         /*-process ALT'ed function keys */
  175.         if (!(lParam & 0x20000000)) goto KeyDown;
  176.             /* for some reason, plain F10 arrives as a SYS message ! */
  177.         if (Key == VK_F4) return FALSE; /* standard accelerator for
  178.                        Frame's SC_CLOSE */
  179.         prefix |= ALTD;
  180.         goto KeyDown;
  181.         
  182.     case WM_CHAR:
  183.         /*-process regular ASCII, with CTRL & SHFT embedded in event */ 
  184.     evt = Key;
  185.     break;
  186.  
  187.     case WM_SYSCHAR:
  188.         if (lParam & 0x20000000) {  /*-process ALT'ed ASCII char */
  189.         evt = upperc((char)Key);
  190.         prefix = ALTD;
  191.         if (getbind(ALTD | evt) == NULL) {
  192.             /* that key is not bound, let's ignore it to have
  193.            Windows check for a menu-bar accelerator */
  194.             evt = -1;
  195.         }
  196.     }
  197.     break;
  198.  
  199.     case WM_MENUCHAR:
  200. #if WINDOW_MSWIN32
  201.     if (!(HIWORD(wParam) & MF_POPUP) && (GetKeyState (VK_MENU) < 0)) {
  202. #else
  203.     if (!(LOWORD(lParam) & MF_POPUP) && (GetKeyState (VK_MENU) < 0)) {
  204. #endif
  205.         /* it is an ALT'ed char that does not match any accelerator */
  206.         evt = upperc((char)Key);
  207.         prefix = ALTD;
  208.     }
  209.     break;
  210.     }
  211.     
  212.     if (evt == -1) return FALSE; /* nothing of interest ! */
  213.  
  214.     if (in_room (3)) {
  215.     if ((prefix != 0) || (evt == 0)) {
  216.         in_put (0);
  217.         in_put (prefix >> 8);
  218.     }
  219.     in_put (evt);
  220.     }
  221.     return TRUE;
  222. } /* EatKey */
  223.  
  224. /* PutMouseMessage: feeds a mouse message into the in_put queue */
  225. /* ===============                                              */
  226.  
  227. void PASCAL    PutMouseMessage (UINT wMsg, UINT wParam, POINT Position)
  228.  
  229. {
  230.     char    c;
  231.     int     prefix;
  232.  
  233.     if (!mouseflag) return; /* mouse input is disabled */
  234.     
  235.     switch (wMsg) {
  236.     case WM_LBUTTONDOWN:
  237.     c = 'a';
  238.     break;
  239.     case WM_LBUTTONUP:
  240.     c = 'b';
  241.     break;
  242.     case WM_MBUTTONDOWN:
  243.     c = 'c';
  244.     break;
  245.     case WM_MBUTTONUP:
  246.     c = 'd';
  247.     break;
  248.     case WM_RBUTTONDOWN:
  249.     c = 'e';
  250.     break;
  251.     case WM_RBUTTONUP:
  252.     c = 'f';
  253.     break;
  254.     case WM_MOUSEMOVE:
  255.     /* mouse move events being suppressed? */
  256.     if (((mouse_move == 1) &&
  257.         ((mmove_flag == FALSE) || (!MouseTracking))) ||
  258.         (mouse_move == 0))
  259.         return;
  260.         c = 'm';
  261.         break;
  262.     default:
  263.     return; /* should not happen, but let's be safe! */
  264.     }
  265.     prefix = MOUS;
  266.     if (wParam & MK_SHIFT)
  267.     prefix |= SHFT;
  268.     if (wParam & MK_CONTROL)
  269.     prefix |= CTRL;
  270.     in_put (0);
  271.     in_put (prefix >> 8);
  272.     in_put ((unsigned char)Position.x);
  273.     in_put ((unsigned char)Position.y);
  274.     in_put (c);
  275. } /* PutMouseMessage */
  276.  
  277. /* MouseMessage:    handles client area mouse messages */
  278. /* ============                                        */
  279.  
  280. void FAR PASCAL MouseMessage (HWND hWnd, UINT wMsg, UINT wParam, LONG lParam)
  281. {
  282.     POINT           Position;
  283.     static POINT old_Position = {-1, -1};/* last position reported by movement */
  284.  
  285.     Position.x = (short)LOWORD(lParam);
  286.     Position.y = (short)HIWORD(lParam);
  287.     ClientToCell (hWnd, Position, &Position);
  288.     
  289.     switch (wMsg) {
  290.     case WM_MOUSEMOVE:
  291. #if    0
  292.     if (MouseTracking && !notquiescent) {
  293.             MoveEmacsCaret (hWnd, Position.x, Position.y);
  294.         }
  295. #endif
  296.     if ((old_Position.x != Position.x) || (old_Position.y != Position.y)) {
  297.         if (in_room (5))
  298.             PutMouseMessage (wMsg, wParam, Position);
  299.         old_Position.x = Position.x;
  300.         old_Position.y = Position.y;
  301.     }
  302.     break;
  303.  
  304.     case WM_LBUTTONDOWN:
  305.     case WM_MBUTTONDOWN:
  306.     case WM_RBUTTONDOWN:
  307.         if (in_room (5) && mouseflag) {
  308.         PutMouseMessage (wMsg, wParam, Position);
  309.         MouseTracking = TRUE;
  310.         SetCapture (hWnd);
  311.         if (!notquiescent) MoveEmacsCaret (hWnd, Position.x, Position.y);
  312.     }
  313.     break;
  314.  
  315.     case WM_LBUTTONUP:
  316.     case WM_MBUTTONUP:
  317.     case WM_RBUTTONUP:
  318.         if (MouseTracking) {
  319.         if (in_room (5)) PutMouseMessage (wMsg, wParam, Position);
  320.         MouseTracking = FALSE;
  321.         ReleaseCapture ();  /* let go of the mouse */
  322.         if (!notquiescent) {
  323.                 MoveEmacsCaret (hWnd, CurrentCol, CurrentRow);
  324.                     /* restore the caret */
  325.             }
  326.     }
  327.     break;
  328.  
  329.     default:
  330.         break;
  331.     }
  332. } /* MouseMessage */
  333.  
  334. #if !WIN30SDK
  335. /* DropMessage:    handles WM_DROPFILES messages */
  336. /* ===========                                   */
  337.  
  338. void FAR PASCAL DropMessage (HWND hWnd, HDROP hDrop)
  339.  
  340. /* Generates a MS! keystroke. $xpos/$ypos contain the position where
  341.    the files were dropped, or -1 (actually, 255) if the drop occurred
  342.    outside a screen client area. The invisible buffer "Dropped files" is
  343.    filled with the list of files dropped (one per line), except the first
  344.    line which is either empty or contains the name of the screen where the
  345.    drop occurred. */
  346. {
  347.     BUFFER  *DropBuf;
  348.     POINT   Point;
  349.  
  350.     DropBuf = bfind("Dropped files", TRUE, BFINVS);
  351.     if (DropBuf && bclear (DropBuf)) {
  352.         if ((hWnd == hFrameWnd) || (hWnd == hMDIClientWnd)) {
  353.             Point.x = -1;
  354.             Point.y = -1;
  355.             addline (DropBuf, "");  /* no screen name */
  356.         }
  357.         else {
  358.             /* the drop occured on a screen */
  359.             addline (DropBuf, ((SCREEN*)GetWindowLong (hWnd, GWL_SCRPTR))->s_screen_name);
  360.             if (DragQueryPoint (hDrop, &Point)) {
  361.                 ClientToCell (hWnd, Point, &Point);
  362.             }
  363.             else {
  364.                 /* not within the client area! */
  365.                 Point.x = -1;
  366.                 Point.y = -1;
  367.             }
  368.         }
  369.         {   /*-complete the DropBuf with the file name list */
  370.             char    FileName [NFILEN];
  371.             WORD    Number;
  372.             WORD    i;
  373.  
  374.             Number = DragQueryFile (hDrop, -1, NULL, 0);
  375.             for (i = 0; i < Number; i++) {
  376.                 DragQueryFile (hDrop, i, FileName, NFILEN);
  377.                 addline (DropBuf, FileName);
  378.             }
  379.             DropBuf->b_dotp = lforw(DropBuf->b_linep);
  380.             DropBuf->b_doto = 0;
  381.         }
  382.         /*-feed the pseudo-keystroke into the in_put stream */
  383.         in_put (0);
  384.         in_put (MOUS >> 8);
  385.         in_put ((unsigned char)Point.x);
  386.         in_put ((unsigned char)Point.y);
  387.         in_put ('!');
  388.     }
  389.     DragFinish (hDrop);
  390. } /* DropMessage */
  391. #endif
  392.