* Reorganize the PM interface to encapsulate PM event messages and send
authorChris Hanson <org/chris-hanson/cph>
Fri, 3 Nov 1995 01:30:21 +0000 (01:30 +0000)
committerChris Hanson <org/chris-hanson/cph>
Fri, 3 Nov 1995 01:30:21 +0000 (01:30 +0000)
  them to the window's event qid in their original format.  This
  simplifies the process of adding new event types, and allows the
  window's owner to decide what is relevant information.

* Add some new interface calls to support mouse tracking and pop-up
  menus.

* Implement a mechanism to mark characters with the mouse in the
  console window, and a Copy command to copy them to the clipboard.

v7/src/microcode/os2msg.h
v7/src/microcode/os2pm.c
v7/src/microcode/os2pm.h
v7/src/microcode/os2pm.scm
v7/src/microcode/os2pmcon.c
v7/src/microcode/os2pmcon.rc
v7/src/microcode/pros2pm.c

index a6dbebba24d4f0c3b29458542571e55407e1b6f0..402c16b65d86a4980f99992f9bfb5d2a4de5684f 100644 (file)
@@ -1,6 +1,6 @@
 /* -*-C-*-
 
-$Id: os2msg.h,v 1.12 1995/10/30 08:01:05 cph Exp $
+$Id: os2msg.h,v 1.13 1995/11/03 01:29:04 cph Exp $
 
 Copyright (c) 1994-95 Massachusetts Institute of Technology
 
@@ -97,15 +97,8 @@ typedef enum
 
   /* These are messages that are automatically generated by the PM
      thread when the corresponding events occur.  */
-  mt_button_event,             /* mouse button press */
-  mt_close_event,              /* window close (user command) */
-  mt_focus_event,              /* window focus change */
-  mt_key_event,                        /* key press */
+  mt_pm_event,                 /* undecoded PM input event */
   mt_paint_event,              /* window needs painting */
-  mt_resize_event,             /* window resized */
-  mt_visibility_event,         /* window visibility change */
-  mt_command_event,            /* WM_COMMAND message */
-  mt_help_event,               /* WM_HELP message */
 
   /* This requests the thread on the other end of the connection to
      kill itself.  At present this request is not used.  */
index 37f3e2538cbaac9f2118910d5df682f7d31ce4c3..dda12b4c28569e39c8b64d44fae090ac7d207f9e 100644 (file)
@@ -1,6 +1,6 @@
 /* -*-C-*-
 
-$Id: os2pm.c,v 1.20 1995/10/30 08:02:37 cph Exp $
+$Id: os2pm.c,v 1.21 1995/11/03 01:29:14 cph Exp $
 
 Copyright (c) 1994-95 Massachusetts Institute of Technology
 
@@ -81,6 +81,7 @@ typedef struct _window_t
   unsigned int minimizingp : 1; /* nonzero if window being minimized */
   unsigned int minimizedp : 1; /* nonzero if window is minimized */
   unsigned int permanentp : 1; /* nonzero means don't close on reload */
+  unsigned int mousetrackp : 1;        /* nonzero means generate WM_MOUSEMOVE msgs */
 } window_t;
 #define WINDOW_FRAME(window) ((window) -> frame)
 #define WINDOW_CLIENT(window) ((window) -> client)
@@ -100,6 +101,7 @@ typedef struct _window_t
 #define WINDOW_MINIMIZINGP(window) ((window) -> minimizingp)
 #define WINDOW_MINIMIZEDP(window) ((window) -> minimizedp)
 #define WINDOW_PERMANENTP(window) ((window) -> permanentp)
+#define WINDOW_MOUSETRACKP(window) ((window) -> mousetrackp)
 
 typedef struct _bitmap_t
 {
@@ -130,7 +132,7 @@ typedef struct
    structure definitions for most of the procedures.  */
 #include "os2pm-id.h"
 
-static void get_window_pos (window_t *, short *, short *);
+static void window_pos (window_t *, short *, short *);
 static void handle_window_pos_request (msg_t *);
 
 typedef struct
@@ -149,7 +151,7 @@ typedef struct
 #define SM_POS_REPLY_X(m) (((sm_pos_reply_t *) (m)) -> x)
 #define SM_POS_REPLY_Y(m) (((sm_pos_reply_t *) (m)) -> y)
 
-static void get_window_size (window_t *, unsigned short *, unsigned short *);
+static void window_size (window_t *, unsigned short *, unsigned short *);
 static void handle_window_size_request (msg_t *);
 
 typedef struct
@@ -168,7 +170,7 @@ typedef struct
 #define SM_SIZE_REPLY_WIDTH(m) (((sm_size_reply_t *) (m)) -> width)
 #define SM_SIZE_REPLY_HEIGHT(m) (((sm_size_reply_t *) (m)) -> height)
 
-static void get_window_frame_size
+static void window_frame_size
   (window_t *, unsigned short *, unsigned short *);
 static void handle_window_frame_size_request (msg_t *);
 
@@ -213,6 +215,8 @@ typedef struct
 #define SM_PS_SET_BITMAP_REPLY_BITMAP(m)                               \
   (((sm_ps_set_bitmap_reply_t *) (m)) -> bitmap)
 \f
+static void close_all_windows (void);
+
 static void sync_transaction (qid_t, msg_t *);
 static void sync_reply (qid_t);
 
@@ -223,43 +227,48 @@ static void initialize_id_table (id_table_t *);
 static unsigned int allocate_id (id_table_t *, void *);
 static void deallocate_id (id_table_t *, unsigned int);
 static void * id_to_pointer (id_table_t *, unsigned int);
-
+static int id_validp (id_table_t *, unsigned int);
 static ps_t * psid_to_ps (psid_t);
 static window_t * wid_to_window (wid_t);
 static bitmap_t * bid_to_bitmap (bid_t);
-static void close_all_windows (void);
 
 static MRESULT EXPENTRY object_window_procedure (HWND, ULONG, MPARAM, MPARAM);
 static MRESULT EXPENTRY frame_window_procedure (HWND, ULONG, MPARAM, MPARAM);
 static MRESULT EXPENTRY window_procedure (HWND, ULONG, MPARAM, MPARAM);
 
 static window_t * hwnd_to_window (HWND);
+static msg_t * make_pm_event (wid_t, ULONG, MPARAM, MPARAM);
+static msg_t * make_paint_event
+  (wid_t, unsigned short, unsigned short, unsigned short, unsigned short);
+
+static void recreate_cursor (window_t *);
+static void activate_cursor (window_t *);
+static void deactivate_cursor (window_t *);
+
+static window_t * make_window (qid_t, qid_t);
+
+static void win_create_cursor (HWND, LONG, LONG, LONG, LONG, ULONG, PRECTL);
+static void win_destroy_cursor (HWND);
+static void win_show_cursor (HWND, BOOL);
 static void recreate_cursor (window_t *);
 static void activate_cursor (window_t *);
 static void deactivate_cursor (window_t *);
+static void maybe_activate_cursor (ps_t *);
+static void maybe_deactivate_cursor (ps_t *);
 
 static HDC get_ps_device (HPS);
 static LONG get_device_capability (HDC, LONG);
 static ps_t * create_ps (pst_t, HDC, qid_t);
 static void destroy_ps (ps_t *);
-static void maybe_activate_cursor (ps_t *);
-static void maybe_deactivate_cursor (ps_t *);
 
 static int ps_set_font (ps_t *, unsigned short, const char *);
-
-static msg_t * make_button_event
-  (wid_t, unsigned char, unsigned char, unsigned short, unsigned short,
-   unsigned short);
-static msg_t * make_close_event (wid_t);
-static msg_t * make_focus_event (wid_t, int);
-static msg_t * make_key_event
-  (wid_t, unsigned short, unsigned short, unsigned short);
-static msg_t * make_paint_event
-  (wid_t, unsigned short, unsigned short, unsigned short, unsigned short);
-static msg_t * make_resize_event (wid_t, unsigned short, unsigned short);
-static msg_t * make_visibility_event (wid_t, int);
-static msg_t * make_command_event (wid_t, USHORT, USHORT, USHORT);
-static msg_t * make_help_event (wid_t, USHORT, USHORT, USHORT);
+static int parse_font_spec (const char *, PSZ *, LONG *, USHORT *);
+static const char * unparse_font_spec (PSZ, LONG, USHORT);
+static int ps_set_font_1 (ps_t * ps, PSZ, LONG, USHORT, LONG);
+static PLONG ps_make_char_increments (LONG);
+static int create_font (HPS, LONG, PFONTMETRICS, USHORT);
+static void copy_fontmetrics_to_fattrs (FONTMETRICS *, FATTRS *);
+static void ps_set_font_size (ps_t *, LONG);
 \f
 #define ID_FRAME 1
 
@@ -282,6 +291,7 @@ static HMQ pm_hmq;
 static HWND pm_object_window;
 static tqueue_t * pm_tqueue;
 static PFNWP original_frame_window_procedure;
+static window_t * capture_window;
 
 static const char object_class [] = "mit-scheme.object";
 static const char window_class [] = "mit-scheme.window";
@@ -292,6 +302,13 @@ static const char window_class [] = "mit-scheme.window";
     OS2_send_message ((WINDOW_EVENT_QID (window)), (message));         \
 }
 
+#define SEND_PM_EVENT(hwnd, msg, mp1, mp2)                             \
+{                                                                      \
+  window_t * window = (hwnd_to_window (hwnd));                         \
+  SEND_EVENT (window,                                                  \
+             (make_pm_event ((WINDOW_ID (window)), msg, mp1, mp2)));   \
+}
+
 #define window_error(name) window_error_1 (#name, 1)
 #define window_warning(name) window_error_1 (#name, 0)
 
@@ -332,20 +349,14 @@ OS2_initialize_pm_thread (void)
   SET_MSG_TYPE_LENGTH (mt_ps_set_bitmap_request, sm_ps_set_bitmap_request_t);
   SET_MSG_TYPE_LENGTH (mt_ps_set_bitmap_reply, sm_ps_set_bitmap_reply_t);
 
-  SET_MSG_TYPE_LENGTH (mt_button_event, sm_button_event_t);
-  SET_MSG_TYPE_LENGTH (mt_close_event, sm_close_event_t);
-  SET_MSG_TYPE_LENGTH (mt_focus_event, sm_focus_event_t);
-  SET_MSG_TYPE_LENGTH (mt_key_event, sm_key_event_t);
+  SET_MSG_TYPE_LENGTH (mt_pm_event, sm_pm_event_t);
   SET_MSG_TYPE_LENGTH (mt_paint_event, sm_paint_event_t);
-  SET_MSG_TYPE_LENGTH (mt_resize_event, sm_resize_event_t);
-  SET_MSG_TYPE_LENGTH (mt_visibility_event, sm_visibility_event_t);
-  SET_MSG_TYPE_LENGTH (mt_command_event, sm_command_event_t);
-  SET_MSG_TYPE_LENGTH (mt_help_event, sm_help_event_t);
 
   initialize_id_table (& psid_table);
   initialize_id_table (& wid_table);
   initialize_id_table (& bid_table);
   original_frame_window_procedure = 0;
+  capture_window = 0;
   {
     qid_t qid;
     OS2_make_qid_pair ((&pm_init_qid), (&qid));
@@ -359,6 +370,19 @@ OS2_initialize_pm_thread (void)
   }
   add_reload_cleanup (close_all_windows);
 }
+
+static void
+close_all_windows (void)
+{
+  window_t ** scan = ((window_t **) (ID_TABLE_POINTERS (& wid_table)));
+  window_t ** end = (scan + (ID_TABLE_LENGTH (& wid_table)));
+  while (scan < end)
+    {
+      window_t * window = (*scan++);
+      if ((window != 0) && (!WINDOW_PERMANENTP (window)))
+       window_close (window);
+    }
+}
 \f
 /* Define this to cause a calling thread to wait for the PM thread to
    finish requests that have trivial replies.  Otherwise, the calling
@@ -501,6 +525,12 @@ OS2_write_pm_tqueue (tqueue_t * tqueue, msg_t * message)
     window_warning (WinPostMsg);
 }
 \f
+/* Object IDs
+
+   These tables maintain data structures in the PM thread, and
+   associate those structures with ID numbers that are given out to
+   other threads (and to Scheme programs).  */
+
 static void
 initialize_id_table (id_table_t * table)
 {
@@ -564,61 +594,24 @@ id_validp (id_table_t * table, unsigned int id)
          && (id < (ID_TABLE_LENGTH (table)))
          && (((ID_TABLE_POINTERS (table)) [id]) != 0));
 }
-\f
+
 static ps_t *
 psid_to_ps (psid_t psid)
 {
   return (id_to_pointer ((& psid_table), psid));
 }
 
-int
-OS2_psid_validp (psid_t psid)
-{
-  return (id_validp ((& psid_table), psid));
-}
-
 static window_t *
 wid_to_window (wid_t wid)
 {
   return (id_to_pointer ((& wid_table), wid));
 }
 
-int
-OS2_wid_validp (wid_t wid)
-{
-  return (id_validp ((& wid_table), wid));
-}
-
 static bitmap_t *
 bid_to_bitmap (bid_t bid)
 {
   return (id_to_pointer ((& bid_table), bid));
 }
-
-int
-OS2_bid_validp (bid_t bid)
-{
-  return (id_validp ((& bid_table), bid));
-}
-
-psid_t
-OS2_window_client_ps (wid_t wid)
-{
-  return (PS_ID (WINDOW_CLIENT_PS (wid_to_window (wid))));
-}
-
-static void
-close_all_windows (void)
-{
-  window_t ** scan = ((window_t **) (ID_TABLE_POINTERS (& wid_table)));
-  window_t ** end = (scan + (ID_TABLE_LENGTH (& wid_table)));
-  while (scan < end)
-    {
-      window_t * window = (*scan++);
-      if ((window != 0) && (!WINDOW_PERMANENTP (window)))
-       close_window (window);
-    }
-}
 \f
 /* Implementation of the object window.  The object window handles
    encapsulated messages sent from the Scheme thread.  This defines
@@ -657,150 +650,465 @@ object_window_procedure (HWND window, ULONG msg, MPARAM mp1, MPARAM mp2)
   return (MRVOID);
 }
 \f
-qid_t
-OS2_create_pm_qid (tqueue_t * tqueue)
-{
-  qid_t pm_side;
-  qid_t client_side;
-  OS2_make_qid_pair ((&pm_side), (&client_side));
-  OS2_open_qid (pm_side, pm_tqueue);
-  OS2_open_qid (client_side, tqueue);
-  return (client_side);
-}
-
-void
-OS2_window_permanent (wid_t wid)
-{
-  (WINDOW_PERMANENTP (wid_to_window (wid))) = 1;
-}
-
-HWND
-OS2_window_frame_handle (wid_t wid)
-{
-  /* This is needed by the OS2_menu_create, to supply an owner for the
-     top-level menu bar.  */
-  return (WINDOW_FRAME (wid_to_window (wid)));
-}
+/* Implementation of the Frame Window */
 
-int
-OS2_memory_ps_p (psid_t psid)
-{
-  return ((PS_VISUAL_TYPE (psid_to_ps (psid))) == pst_memory);
-}
-
-bid_t
-OS2_ps_get_bitmap (psid_t psid)
+static MRESULT EXPENTRY
+frame_window_procedure (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
 {
-  bitmap_t * bitmap = (PS_VISUAL (psid_to_ps (psid)));
-  return ((bitmap == 0) ? BID_NONE : (BITMAP_ID (bitmap)));
+  window_t * window = (hwnd_to_window (WinWindowFromID (hwnd, FID_CLIENT)));
+  switch (msg)
+    {
+    case WM_QUERYTRACKINFO:
+      /* Set the tracking grid for the resize operation.  */
+      {
+       MRESULT mr
+         = ((* original_frame_window_procedure) (hwnd, msg, mp1, mp2));
+       if (mr == MRTRUE)
+         {
+           PTRACKINFO pti = (PVOIDFROMMP (mp2));
+           if ((((pti -> fs) & TF_MOVE) != TF_MOVE)
+               && ((((pti -> fs) & TF_MOVE) != 0)
+                   || (((pti -> fs) & TF_SETPOINTERPOS) != 0)))
+             {
+               (pti -> fs) |= TF_GRID;
+               (pti -> cxGrid) = (WINDOW_GRID_X (window));
+               (pti -> cyGrid) = (WINDOW_GRID_Y (window));
+               (pti -> cxKeyboard) = (WINDOW_GRID_X (window));
+               (pti -> cyKeyboard) = (WINDOW_GRID_Y (window));
+             }
+         }
+       return (mr);
+      }
+    case WM_MINMAXFRAME:
+      /* If minimizing, mark the window to indicate this.  The client
+        will shortly receive a WM_SIZE which indicates that the
+        minimization has completed.  */
+      {
+       PSWP pswp = (PVOIDFROMMP (mp1));
+       if ((!WINDOW_MINIMIZEDP (window))
+           && (((pswp -> fl) & SWP_MINIMIZE) != 0))
+         {
+           (WINDOW_MINIMIZINGP (window)) = 1;
+           (WINDOW_MINIMIZEDP (window)) = 1;
+         }
+       else if ((WINDOW_MINIMIZEDP (window))
+                && (((pswp -> fl) & (SWP_RESTORE | SWP_MAXIMIZE)) != 0))
+         (WINDOW_MINIMIZEDP (window)) = 0;
+      }
+      break;
+    }
+  return ((* original_frame_window_procedure) (hwnd, msg, mp1, mp2));
 }
 \f
-/* This macro supplies a NO-OP procedure needed by the
-   machine-generated code for OS2_pm_synchronize.  */
-#define pm_synchronize(qid)
-
-/* This machine-generated file contains most of the external procedure
-   definitions, and their associated handler procedures.  */
-#include "os2pm-rp.h"
-
-void
-OS2_window_pos (wid_t wid, short * x, short * y)
-{
-  window_t * window = (wid_to_window (wid));
-  msg_t * message = (OS2_create_message (mt_window_pos_request));
-  (SM_POS_REQUEST_WINDOW (message)) = window;
-  message
-    = (OS2_message_transaction ((WINDOW_QID (window)),
-                               message,
-                               mt_window_pos_reply));
-  (* x) = (SM_POS_REPLY_X (message));
-  (* y) = (SM_POS_REPLY_Y (message));
-  OS2_destroy_message (message);
-}
-
-static void
-handle_window_pos_request (msg_t * request)
-{
-  qid_t sender = (MSG_SENDER (request));
-  msg_t * reply = (OS2_create_message (mt_window_pos_reply));
-  get_window_pos ((SM_POS_REQUEST_WINDOW (request)),
-                 (& (SM_POS_REPLY_X (reply))),
-                 (& (SM_POS_REPLY_Y (reply))));
-  OS2_destroy_message (request);
-  OS2_send_message (sender, reply);
-}
-
-void
-OS2_window_size (wid_t wid, unsigned short * width, unsigned short * height)
-{
-  window_t * window = (wid_to_window (wid));
-  msg_t * message = (OS2_create_message (mt_window_size_request));
-  (SM_SIZE_REQUEST_WINDOW (message)) = window;
-  message
-    = (OS2_message_transaction ((WINDOW_QID (window)),
-                               message,
-                               mt_window_size_reply));
-  (* width) = (SM_SIZE_REPLY_WIDTH (message));
-  (* height) = (SM_SIZE_REPLY_HEIGHT (message));
-  OS2_destroy_message (message);
-}
-
-static void
-handle_window_size_request (msg_t * request)
-{
-  qid_t sender = (MSG_SENDER (request));
-  msg_t * reply = (OS2_create_message (mt_window_size_reply));
-  get_window_size ((SM_SIZE_REQUEST_WINDOW (request)),
-                  (& (SM_SIZE_REPLY_WIDTH (reply))),
-                  (& (SM_SIZE_REPLY_HEIGHT (reply))));
-  OS2_destroy_message (request);
-  OS2_send_message (sender, reply);
-}
-
-void
-OS2_window_frame_size (wid_t wid,
-                      unsigned short * width, unsigned short * height)
-{
-  window_t * window = (wid_to_window (wid));
-  msg_t * message = (OS2_create_message (mt_window_frame_size_request));
-  (SM_FRAME_SIZE_REQUEST_WINDOW (message)) = window;
-  message
-    = (OS2_message_transaction ((WINDOW_QID (window)),
-                               message,
-                               mt_window_frame_size_reply));
-  (* width) = (SM_FRAME_SIZE_REPLY_WIDTH (message));
-  (* height) = (SM_FRAME_SIZE_REPLY_HEIGHT (message));
-  OS2_destroy_message (message);
-}
-
-static void
-handle_window_frame_size_request (msg_t * request)
-{
-  qid_t sender = (MSG_SENDER (request));
-  msg_t * reply = (OS2_create_message (mt_window_frame_size_reply));
-  get_window_frame_size ((SM_FRAME_SIZE_REQUEST_WINDOW (request)),
-                        (& (SM_FRAME_SIZE_REPLY_WIDTH (reply))),
-                        (& (SM_FRAME_SIZE_REPLY_HEIGHT (reply))));
-  OS2_destroy_message (request);
-  OS2_send_message (sender, reply);
-}
+/* Implementation of the Client Window */
 
-bid_t
-OS2_ps_set_bitmap (psid_t psid, bid_t bid)
+static MRESULT EXPENTRY
+window_procedure (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
 {
-  ps_t * ps = (psid_to_ps (psid));
-  bitmap_t * bitmap = ((bid == BID_NONE) ? 0 : (bid_to_bitmap (bid)));
-  msg_t * message = (OS2_create_message (mt_ps_set_bitmap_request));
-  (SM_PS_SET_BITMAP_REQUEST_PS (message)) = ps;
-  (SM_PS_SET_BITMAP_REQUEST_BITMAP (message)) = bitmap;
-  message
-    = (OS2_message_transaction ((PS_QID (ps)),
-                               message,
-                               mt_ps_set_bitmap_reply));
-  bitmap = (SM_PS_SET_BITMAP_REPLY_BITMAP (message));
-  OS2_destroy_message (message);
-  return ((bitmap == 0) ? BID_NONE : (BITMAP_ID (bitmap)));
-}
+  switch (msg)
+    {
+    case WM_CREATE:
+      {
+       window_t * window = (PVOIDFROMMP (mp1));
+       if (!WinSetWindowPtr (hwnd, QWP_WINDOW, window))
+         window_error (WinSetWindowPtr);
+       (WINDOW_CLIENT (window)) = hwnd;
+       (WINDOW_CLIENT_PS (window))
+         = (create_ps (pst_window,
+                       (WinOpenWindowDC (hwnd)),
+                       (WINDOW_QID (window))));
+       (PS_VISUAL (WINDOW_CLIENT_PS (window))) = window;
+       return (MRFALSE);
+      }
+    case WM_PAINT:
+      {
+       window_t * window = (hwnd_to_window (hwnd));
+       if (((WinQueryWindowULong ((WINDOW_FRAME (window)), QWL_STYLE))
+            & WS_MINIMIZED)
+           != 0)
+         break;
+       {
+         HPS hps = (PS_HANDLE (WINDOW_CLIENT_PS (window)));
+         RECTL rectl;
+         if ((WinBeginPaint ((WINDOW_CLIENT (window)), hps, (& rectl)))
+             == NULLHANDLE)
+           window_error (WinBeginPaint);
+         if (!WinEndPaint (hps))
+           window_error (WinEndPaint);
+         SEND_EVENT (window,
+                     (make_paint_event ((WINDOW_ID (window)),
+                                        (rectl . xLeft),
+                                        (rectl . xRight),
+                                        (rectl . yBottom),
+                                        (rectl . yTop))));
+       }
+       return (MRVOID);
+      }
+    case WM_SETFOCUS:
+      {
+       window_t * window = (hwnd_to_window (hwnd));
+       if (SHORT1FROMMP (mp2))
+         recreate_cursor (window);
+       else
+         {
+           win_destroy_cursor (WINDOW_CLIENT (window));
+           (WINDOW_CURSOR_CREATEDP (window)) = 0;
+         }
+      }
+      SEND_PM_EVENT (hwnd, msg, mp1, mp2);
+      return (MRVOID);
+    case WM_TRANSLATEACCEL:
+      {
+       PQMSG qmsg = (PVOIDFROMMP (mp1));
+       USHORT flags = (SHORT1FROMMP (qmsg -> mp1));
+       USHORT char_code = (SHORT1FROMMP (qmsg -> mp2));
+       USHORT virtual_key = (SHORT2FROMMP (qmsg -> mp2));
+       /* Disable specific default accelerator keys.  */
+       if ((flags & KC_VIRTUALKEY) != 0)
+         switch (virtual_key)
+           {
+           case VK_ALT:
+           case VK_ALTGRAF:
+             /* Disable "Alt" keys, which normally pop up the system
+                menu.  These keys are used often in Edwin and the
+                default behavior is unacceptable.  */
+             return (MRFALSE);
+           case VK_SPACE:
+           case VK_ESC:
+           case VK_TAB:
+             /* Disable "Alt-SPC", "Alt-ESC", and "Alt-TAB", which
+                have standard key bindings in Edwin.  */
+             if ((flags & KC_ALT) != 0)
+               return (MRFALSE);
+           }
+       else if ((flags & KC_CHAR) != 0)
+         switch (char_code)
+           {
+           case ' ':
+           case '\033':
+           case '\t':
+             /* Disable "Alt-SPC", "Alt-ESC", and "Alt-TAB", if for
+                some reason they are reported as ASCII characters
+                rather than as virtual keys.  */
+             if ((flags & KC_ALT) != 0)
+               return (MRFALSE);
+           }
+       break;
+      }
+    case WM_DESTROY:
+      {
+       window_t * window = (hwnd_to_window (hwnd));
+       destroy_ps (WINDOW_CLIENT_PS (window));
+       (WINDOW_CLIENT_PS (window)) = 0;
+       return (MRVOID);
+      }
+    case WM_SIZE:
+      {
+       window_t * window = (hwnd_to_window (hwnd));
+       /* If this message is part of a minimization, ignore it.  */
+       if (WINDOW_MINIMIZINGP (window))
+         {
+           (WINDOW_MINIMIZINGP (window)) = 0;
+           (WINDOW_MINIMIZEDP (window)) = 1;
+           break;
+         }
+       if (WINDOW_CURSOR_CREATEDP (window))
+         {
+           win_destroy_cursor (WINDOW_CLIENT (window));
+           (WINDOW_CURSOR_CREATEDP (window)) = 0;
+           (WINDOW_CURSOR_X (window)) = 0;
+           (WINDOW_CURSOR_Y (window)) = 0;
+           recreate_cursor (window);
+         }
+      }
+      SEND_PM_EVENT (hwnd, msg, mp1, mp2);
+      return (MRVOID);
+    case WM_CLOSE:
+    case WM_COMMAND:
+    case WM_CONTROL:
+    case WM_HELP:
+    case WM_SHOW:
+      SEND_PM_EVENT (hwnd, msg, mp1, mp2);
+      return (MRVOID);
+    case WM_CHAR:
+    case WM_BUTTON1DOWN:
+    case WM_BUTTON1UP:
+    case WM_BUTTON1CLICK:
+    case WM_BUTTON1DBLCLK:
+    case WM_BUTTON2DOWN:
+    case WM_BUTTON2UP:
+    case WM_BUTTON2CLICK:
+    case WM_BUTTON2DBLCLK:
+    case WM_BUTTON3DOWN:
+    case WM_BUTTON3UP:
+    case WM_BUTTON3CLICK:
+    case WM_BUTTON3DBLCLK:
+      SEND_PM_EVENT (hwnd, msg, mp1, mp2);
+      return (MRTRUE);
+    case WM_MOUSEMOVE:
+      if (WINDOW_MOUSETRACKP (hwnd_to_window (hwnd)))
+       {
+         SEND_PM_EVENT (hwnd, msg, mp1, mp2);
+         return (MRTRUE);
+       }
+      break;
+    default:
+      break;
+    }
+  return (WinDefWindowProc (hwnd, msg, mp1, mp2));
+}
+
+static window_t *
+hwnd_to_window (HWND hwnd)
+{
+  window_t * window = (WinQueryWindowPtr (hwnd, QWP_WINDOW));
+  if (window == 0)
+    window_error (WinQueryWindowPtr);
+  return (window);
+}
+
+static msg_t *
+make_pm_event (wid_t wid, ULONG msg, MPARAM mp1, MPARAM mp2)
+{
+  msg_t * message = (OS2_create_message (mt_pm_event));
+  (SM_PM_EVENT_WID (message)) = wid;
+  (SM_PM_EVENT_MSG (message)) = msg;
+  (SM_PM_EVENT_MP1 (message)) = mp1;
+  (SM_PM_EVENT_MP2 (message)) = mp2;
+  return (message);
+}
+
+static msg_t *
+make_paint_event (wid_t wid,
+                 unsigned short xl, unsigned short xh,
+                 unsigned short yl, unsigned short yh)
+{
+  msg_t * message = (OS2_create_message (mt_paint_event));
+  (SM_PAINT_EVENT_WID (message)) = wid;
+  (SM_PAINT_EVENT_XL (message)) = xl;
+  (SM_PAINT_EVENT_XH (message)) = xh;
+  (SM_PAINT_EVENT_YL (message)) = yl;
+  (SM_PAINT_EVENT_YH (message)) = yh;
+  return (message);
+}
+
+int
+OS2_translate_wm_char (MPARAM mp1, MPARAM mp2,
+                      unsigned short * code,
+                      unsigned short * flags,
+                      unsigned char * repeat)
+{
+  (*flags) = (SHORT1FROMMP (mp1));
+  (*repeat) = (CHAR3FROMMP (mp1));
+  /* Ignore compound keys for now.  */
+  if (((*flags) & (KC_DEADKEY | KC_COMPOSITE | KC_INVALIDCOMP | KC_KEYUP))
+      != 0)
+    return (0);
+  if (((*flags) & KC_VIRTUALKEY) != 0)
+    {
+      (*code) = (SHORT2FROMMP (mp2));
+      return (1);
+    }
+  if (((*flags) & (KC_CHAR | KC_CTRL | KC_ALT)) != 0)
+    {
+      (*code) = (SHORT1FROMMP (mp2));
+      return (1);
+    }
+  return (0);
+}
+\f
+/* Direct Operations
+
+   These are exported operations that can be implemented directly in
+   the calling thread.  Other operations that require communication
+   with the PM thread appear on following pages.  */
+
+int
+OS2_psid_validp (psid_t psid)
+{
+  return (id_validp ((& psid_table), psid));
+}
+
+int
+OS2_wid_validp (wid_t wid)
+{
+  return (id_validp ((& wid_table), wid));
+}
+
+int
+OS2_bid_validp (bid_t bid)
+{
+  return (id_validp ((& bid_table), bid));
+}
+
+psid_t
+OS2_window_client_ps (wid_t wid)
+{
+  return (PS_ID (WINDOW_CLIENT_PS (wid_to_window (wid))));
+}
+
+qid_t
+OS2_create_pm_qid (tqueue_t * tqueue)
+{
+  qid_t pm_side;
+  qid_t client_side;
+  OS2_make_qid_pair ((&pm_side), (&client_side));
+  OS2_open_qid (pm_side, pm_tqueue);
+  OS2_open_qid (client_side, tqueue);
+  return (client_side);
+}
+
+void
+OS2_window_permanent (wid_t wid)
+{
+  (WINDOW_PERMANENTP (wid_to_window (wid))) = 1;
+}
+
+void
+OS2_window_mousetrack (wid_t wid, int trackp)
+{
+  (WINDOW_MOUSETRACKP (wid_to_window (wid))) = trackp;
+}
+
+HWND
+OS2_window_frame_handle (wid_t wid)
+{
+  return (WINDOW_FRAME (wid_to_window (wid)));
+}
+
+HWND
+OS2_window_client_handle (wid_t wid)
+{
+  return (WINDOW_CLIENT (wid_to_window (wid)));
+}
+
+int
+OS2_memory_ps_p (psid_t psid)
+{
+  return ((PS_VISUAL_TYPE (psid_to_ps (psid))) == pst_memory);
+}
+
+bid_t
+OS2_ps_get_bitmap (psid_t psid)
+{
+  bitmap_t * bitmap = (PS_VISUAL (psid_to_ps (psid)));
+  return ((bitmap == 0) ? BID_NONE : (BITMAP_ID (bitmap)));
+}
+\f
+/* Relayed Operations
+
+   This page implements exported operations that require communication
+   with the PM thread.  The PM-thread-side of these operations appear
+   on the following pages; this page implements only the mechanism to
+   communicate the operation to the PM thread.  The bulk of these
+   communication procedures is machine-generated.  */
+
+/* This macro supplies a NO-OP procedure needed by the
+   machine-generated code for OS2_pm_synchronize.  */
+#define pm_synchronize(qid)
+
+/* This machine-generated file contains most of the external procedure
+   definitions, and their associated handler procedures.  */
+#include "os2pm-rp.h"
+
+void
+OS2_window_pos (wid_t wid, short * x, short * y)
+{
+  window_t * window = (wid_to_window (wid));
+  msg_t * message = (OS2_create_message (mt_window_pos_request));
+  (SM_POS_REQUEST_WINDOW (message)) = window;
+  message
+    = (OS2_message_transaction ((WINDOW_QID (window)),
+                               message,
+                               mt_window_pos_reply));
+  (* x) = (SM_POS_REPLY_X (message));
+  (* y) = (SM_POS_REPLY_Y (message));
+  OS2_destroy_message (message);
+}
+
+static void
+handle_window_pos_request (msg_t * request)
+{
+  qid_t sender = (MSG_SENDER (request));
+  msg_t * reply = (OS2_create_message (mt_window_pos_reply));
+  window_pos ((SM_POS_REQUEST_WINDOW (request)),
+             (& (SM_POS_REPLY_X (reply))),
+             (& (SM_POS_REPLY_Y (reply))));
+  OS2_destroy_message (request);
+  OS2_send_message (sender, reply);
+}
+
+void
+OS2_window_size (wid_t wid, unsigned short * width, unsigned short * height)
+{
+  window_t * window = (wid_to_window (wid));
+  msg_t * message = (OS2_create_message (mt_window_size_request));
+  (SM_SIZE_REQUEST_WINDOW (message)) = window;
+  message
+    = (OS2_message_transaction ((WINDOW_QID (window)),
+                               message,
+                               mt_window_size_reply));
+  (* width) = (SM_SIZE_REPLY_WIDTH (message));
+  (* height) = (SM_SIZE_REPLY_HEIGHT (message));
+  OS2_destroy_message (message);
+}
+
+static void
+handle_window_size_request (msg_t * request)
+{
+  qid_t sender = (MSG_SENDER (request));
+  msg_t * reply = (OS2_create_message (mt_window_size_reply));
+  window_size ((SM_SIZE_REQUEST_WINDOW (request)),
+              (& (SM_SIZE_REPLY_WIDTH (reply))),
+              (& (SM_SIZE_REPLY_HEIGHT (reply))));
+  OS2_destroy_message (request);
+  OS2_send_message (sender, reply);
+}
+
+void
+OS2_window_frame_size (wid_t wid,
+                      unsigned short * width, unsigned short * height)
+{
+  window_t * window = (wid_to_window (wid));
+  msg_t * message = (OS2_create_message (mt_window_frame_size_request));
+  (SM_FRAME_SIZE_REQUEST_WINDOW (message)) = window;
+  message
+    = (OS2_message_transaction ((WINDOW_QID (window)),
+                               message,
+                               mt_window_frame_size_reply));
+  (* width) = (SM_FRAME_SIZE_REPLY_WIDTH (message));
+  (* height) = (SM_FRAME_SIZE_REPLY_HEIGHT (message));
+  OS2_destroy_message (message);
+}
+
+static void
+handle_window_frame_size_request (msg_t * request)
+{
+  qid_t sender = (MSG_SENDER (request));
+  msg_t * reply = (OS2_create_message (mt_window_frame_size_reply));
+  window_frame_size ((SM_FRAME_SIZE_REQUEST_WINDOW (request)),
+                    (& (SM_FRAME_SIZE_REPLY_WIDTH (reply))),
+                    (& (SM_FRAME_SIZE_REPLY_HEIGHT (reply))));
+  OS2_destroy_message (request);
+  OS2_send_message (sender, reply);
+}
+
+bid_t
+OS2_ps_set_bitmap (psid_t psid, bid_t bid)
+{
+  ps_t * ps = (psid_to_ps (psid));
+  bitmap_t * bitmap = ((bid == BID_NONE) ? 0 : (bid_to_bitmap (bid)));
+  msg_t * message = (OS2_create_message (mt_ps_set_bitmap_request));
+  (SM_PS_SET_BITMAP_REQUEST_PS (message)) = ps;
+  (SM_PS_SET_BITMAP_REQUEST_BITMAP (message)) = bitmap;
+  message
+    = (OS2_message_transaction ((PS_QID (ps)),
+                               message,
+                               mt_ps_set_bitmap_reply));
+  bitmap = (SM_PS_SET_BITMAP_REPLY_BITMAP (message));
+  OS2_destroy_message (message);
+  return ((bitmap == 0) ? BID_NONE : (BITMAP_ID (bitmap)));
+}
 
 static void
 handle_ps_set_bitmap_request (msg_t * request)
@@ -823,10 +1131,17 @@ OS2_ps_set_font (psid_t psid, unsigned short id, const char * name)
   return (metrics);
 }
 \f
-static window_t * make_window (qid_t, qid_t);
+/* PM-thread Operation Implementations
+
+   All of the procedures from this point on are implementations of
+   exported operations.  These implementations are the code that is
+   run in the PM thread to implement the operations that are invoked
+   in other threads.  */
+
+/* Windows */
 
 static wid_t
-open_window (qid_t qid, qid_t event_qid, ULONG flags, HMODULE module, ULONG id,
+window_open (qid_t qid, qid_t event_qid, ULONG flags, HMODULE module, ULONG id,
             ULONG style, const char * title)
 {
   window_t * window = (make_window (qid, event_qid));
@@ -894,109 +1209,30 @@ make_window (qid_t qid, qid_t event_qid)
   (WINDOW_EVENT_QID (window)) = event_qid;
   (WINDOW_ID (window)) = (allocate_id ((& wid_table), window));
   (WINDOW_CURSOR_CREATEDP (window)) = 0;
-  (WINDOW_CURSOR_ENABLEDP (window)) = 0;
-  (WINDOW_MINIMIZINGP (window)) = 0;
-  (WINDOW_MINIMIZEDP (window)) = 0;
-  (WINDOW_PERMANENTP (window)) = 0;
-  return (window);
-}
-
-static void
-close_window (window_t * window)
-{
-  if (!WinDestroyWindow (WINDOW_FRAME (window)))
-    window_warning (WinDestroyWindow);
-  deallocate_id ((& wid_table), (WINDOW_ID (window)));
-  OS_free (window);
-}
-
-static void
-show_window (window_t * window, int showp)
-{
-  if (!WinShowWindow ((WINDOW_FRAME (window)), showp))
-    window_warning (WinShowWindow);
-}
-\f
-static void
-win_create_cursor (HWND client, LONG x, LONG y, LONG cx, LONG cy, ULONG fs,
-                  PRECTL clip_rectl)
-{
-  if (!WinCreateCursor (client, x, y, cx, cy, fs, clip_rectl))
-    window_warning (WinCreateCursor);
-}
-
-static void
-win_destroy_cursor (HWND client)
-{
-  if (!WinDestroyCursor (client))
-    window_warning (WinDestroyCursor);
-}
-
-static void
-win_show_cursor (HWND client, BOOL showp)
-{
-  if (!WinShowCursor (client, showp))
-    window_warning (WinShowCursor);
-}
-
-static void
-move_cursor (window_t * window, short x, short y)
-{
-  (WINDOW_CURSOR_X (window)) = x;
-  (WINDOW_CURSOR_Y (window)) = y;
-  if (WINDOW_CURSOR_CREATEDP (window))
-    win_create_cursor ((WINDOW_CLIENT (window)), x, y, 0, 0, CURSOR_SETPOS, 0);
-}
-
-static void
-shape_cursor (window_t * window, unsigned short width, unsigned short height,
-             unsigned short style)
-{
-  (WINDOW_CURSOR_WIDTH (window)) = width;
-  (WINDOW_CURSOR_HEIGHT (window)) = height;
-  (WINDOW_CURSOR_STYLE (window)) = style;
-  if (WINDOW_CURSOR_CREATEDP (window))
-    recreate_cursor (window);
-}
-
-static void
-enable_cursor (window_t * window, int showp)
-{
-  if ((WINDOW_CURSOR_CREATEDP (window))
-      && ((showp != 0) != (WINDOW_CURSOR_ENABLEDP (window))))
-    win_show_cursor ((WINDOW_CLIENT (window)), showp);
-  (WINDOW_CURSOR_ENABLEDP (window)) = (showp != 0);
-}
-
-static void
-recreate_cursor (window_t * window)
-{
-  win_create_cursor ((WINDOW_CLIENT (window)),
-                    (WINDOW_CURSOR_X (window)),
-                    (WINDOW_CURSOR_Y (window)),
-                    (WINDOW_CURSOR_WIDTH (window)),
-                    (WINDOW_CURSOR_HEIGHT (window)),
-                    (WINDOW_CURSOR_STYLE (window)),
-                    0);
-  (WINDOW_CURSOR_CREATEDP (window)) = 1;
-  if (WINDOW_CURSOR_ENABLEDP (window))
-    win_show_cursor ((WINDOW_CLIENT (window)), TRUE);
+  (WINDOW_CURSOR_ENABLEDP (window)) = 0;
+  (WINDOW_MINIMIZINGP (window)) = 0;
+  (WINDOW_MINIMIZEDP (window)) = 0;
+  (WINDOW_PERMANENTP (window)) = 0;
+  (WINDOW_MOUSETRACKP (window)) = 0;
+  return (window);
 }
 
 static void
-activate_cursor (window_t * window)
+window_close (window_t * window)
 {
-  if ((WINDOW_CURSOR_CREATEDP (window)) && (WINDOW_CURSOR_ENABLEDP (window)))
-    win_show_cursor ((WINDOW_CLIENT (window)), TRUE);
+  if (!WinDestroyWindow (WINDOW_FRAME (window)))
+    window_warning (WinDestroyWindow);
+  deallocate_id ((& wid_table), (WINDOW_ID (window)));
+  OS_free (window);
 }
 
 static void
-deactivate_cursor (window_t * window)
+window_show (window_t * window, int showp)
 {
-  if ((WINDOW_CURSOR_CREATEDP (window)) && (WINDOW_CURSOR_ENABLEDP (window)))
-    win_show_cursor ((WINDOW_CLIENT (window)), FALSE);
+  if (!WinShowWindow ((WINDOW_FRAME (window)), showp))
+    window_warning (WinShowWindow);
 }
-\f
+
 static void
 window_scroll (window_t * window, short xl, short xh, short yl, short yh,
               short x_delta, short y_delta)
@@ -1041,7 +1277,7 @@ window_activate (window_t * window)
 }
 
 static void
-get_window_pos (window_t * window, short * x, short * y)
+window_pos (window_t * window, short * x, short * y)
 {
   SWP swp;
   if (!WinQueryWindowPos ((WINDOW_FRAME (window)), (& swp)))
@@ -1051,7 +1287,7 @@ get_window_pos (window_t * window, short * x, short * y)
 }
 
 static void
-set_window_pos (window_t * window, short x, short y)
+window_set_pos (window_t * window, short x, short y)
 {
   if (!WinSetWindowPos ((WINDOW_FRAME (window)), NULLHANDLE, x, y,
                        0, 0, SWP_MOVE))
@@ -1059,8 +1295,8 @@ set_window_pos (window_t * window, short x, short y)
 }
 
 static void
-get_window_size (window_t * window,
-                unsigned short * width, unsigned short * height)
+window_size (window_t * window,
+            unsigned short * width, unsigned short * height)
 {
   SWP swp;
   if (!WinQueryWindowPos ((WINDOW_CLIENT (window)), (& swp)))
@@ -1070,8 +1306,8 @@ get_window_size (window_t * window,
 }
 
 static void
-get_window_frame_size (window_t * window,
-                      unsigned short * width, unsigned short * height)
+window_frame_size (window_t * window,
+                  unsigned short * width, unsigned short * height)
 {
   SWP swp;
   if (!WinQueryWindowPos ((WINDOW_FRAME (window)), (& swp)))
@@ -1081,7 +1317,7 @@ get_window_frame_size (window_t * window,
 }
 
 static void
-set_window_size (window_t * window,
+window_set_size (window_t * window,
                 unsigned short width, unsigned short height)
 {
   SWP swp;
@@ -1114,7 +1350,7 @@ window_focusp (window_t * window)
 }
 
 static void
-set_window_state (window_t * window, window_state_t state)
+window_set_state (window_t * window, window_state_t state)
 {
   ULONG op = 0;
   HWND behind = NULLHANDLE;
@@ -1155,20 +1391,148 @@ set_window_state (window_t * window, window_state_t state)
 }
 
 static void
-set_window_title (window_t * window, const char * title)
+window_set_title (window_t * window, const char * title)
 {
   if (!WinSetWindowText ((WINDOW_FRAME (window)), ((PSZ) title)))
     window_warning (WinSetWindowText);
 }
 
 static void
-update_frame_window (window_t * window, USHORT flags)
+window_update_frame (window_t * window, USHORT flags)
 {
   (void) WinSendMsg ((WINDOW_FRAME (window)), WM_UPDATEFRAME,
                     (MPFROMSHORT (flags)),
                     0);
 }
+
+static HWND
+window_handle_from_id (qid_t qid, HWND window, ULONG id)
+{
+  return (WinWindowFromID (window, id));
+}
+
+static BOOL
+window_set_capture (window_t * window, int capturep)
+{
+  if (capturep)
+    {
+      if (capture_window == 0)
+       {
+         BOOL rc = (WinSetCapture (HWND_DESKTOP, (WINDOW_CLIENT (window))));
+         if (rc)
+           capture_window = window;
+         return (rc);
+       }
+      else
+       return (capture_window == window);
+    }
+  else
+    {
+      capture_window = 0;
+      return (WinSetCapture (HWND_DESKTOP, NULLHANDLE));
+    }
+}
+\f
+/* Text Cursors */
+
+static void
+window_move_cursor (window_t * window, short x, short y)
+{
+  (WINDOW_CURSOR_X (window)) = x;
+  (WINDOW_CURSOR_Y (window)) = y;
+  if (WINDOW_CURSOR_CREATEDP (window))
+    win_create_cursor ((WINDOW_CLIENT (window)), x, y, 0, 0, CURSOR_SETPOS, 0);
+}
+
+static void
+window_shape_cursor (window_t * window, unsigned short width,
+                    unsigned short height, unsigned short style)
+{
+  (WINDOW_CURSOR_WIDTH (window)) = width;
+  (WINDOW_CURSOR_HEIGHT (window)) = height;
+  (WINDOW_CURSOR_STYLE (window)) = style;
+  if (WINDOW_CURSOR_CREATEDP (window))
+    recreate_cursor (window);
+}
+
+static void
+window_show_cursor (window_t * window, int showp)
+{
+  if ((WINDOW_CURSOR_CREATEDP (window))
+      && ((showp != 0) != (WINDOW_CURSOR_ENABLEDP (window))))
+    win_show_cursor ((WINDOW_CLIENT (window)), showp);
+  (WINDOW_CURSOR_ENABLEDP (window)) = (showp != 0);
+}
+
+/* Helper Procedures */
+
+static void
+win_create_cursor (HWND client, LONG x, LONG y, LONG cx, LONG cy, ULONG fs,
+                  PRECTL clip_rectl)
+{
+  if (!WinCreateCursor (client, x, y, cx, cy, fs, clip_rectl))
+    window_warning (WinCreateCursor);
+}
+
+static void
+win_destroy_cursor (HWND client)
+{
+  if (!WinDestroyCursor (client))
+    window_warning (WinDestroyCursor);
+}
+
+static void
+win_show_cursor (HWND client, BOOL showp)
+{
+  if (!WinShowCursor (client, showp))
+    window_warning (WinShowCursor);
+}
+
+static void
+recreate_cursor (window_t * window)
+{
+  win_create_cursor ((WINDOW_CLIENT (window)),
+                    (WINDOW_CURSOR_X (window)),
+                    (WINDOW_CURSOR_Y (window)),
+                    (WINDOW_CURSOR_WIDTH (window)),
+                    (WINDOW_CURSOR_HEIGHT (window)),
+                    (WINDOW_CURSOR_STYLE (window)),
+                    0);
+  (WINDOW_CURSOR_CREATEDP (window)) = 1;
+  if (WINDOW_CURSOR_ENABLEDP (window))
+    win_show_cursor ((WINDOW_CLIENT (window)), TRUE);
+}
+
+static void
+activate_cursor (window_t * window)
+{
+  if ((WINDOW_CURSOR_CREATEDP (window)) && (WINDOW_CURSOR_ENABLEDP (window)))
+    win_show_cursor ((WINDOW_CLIENT (window)), TRUE);
+}
+
+static void
+deactivate_cursor (window_t * window)
+{
+  if ((WINDOW_CURSOR_CREATEDP (window)) && (WINDOW_CURSOR_ENABLEDP (window)))
+    win_show_cursor ((WINDOW_CLIENT (window)), FALSE);
+}
+
+static void
+maybe_activate_cursor (ps_t * ps)
+{
+  if ((PS_VISUAL_TYPE (ps)) == pst_window)
+    activate_cursor (PS_VISUAL (ps));
+}
+
+static void
+maybe_deactivate_cursor (ps_t * ps)
+{
+  if ((PS_VISUAL_TYPE (ps)) == pst_window)
+    deactivate_cursor (PS_VISUAL (ps));
+}
 \f
+/* Presentation Spaces */
+
 static ps_t *
 create_memory_ps (qid_t qid)
 {
@@ -1236,61 +1600,6 @@ ps_set_bitmap (ps_t * ps, bitmap_t * bitmap)
   return (previous_bitmap);
 }
 
-static HDC
-get_ps_device (HPS hps)
-{
-  HDC hdc = (GpiQueryDevice (hps));
-  if (hdc == HDC_ERROR)
-    window_error (GpiQueryDevice);
-  return (hdc);
-}
-
-static LONG
-get_device_capability (HDC hdc, LONG index)
-{
-  LONG result;
-  if (!DevQueryCaps (hdc, index, 1, (& result)))
-    window_error (DevQueryCaps);
-  return (result);
-}
-
-static ps_t *
-create_ps (pst_t type, HDC hdc, qid_t qid)
-{
-  ps_t * ps = (OS_malloc (sizeof (ps_t)));
-  SIZEL sizel;
-  HPS hps;
-  (sizel . cx) = 0;
-  (sizel . cy) = 0;
-  hps = (GpiCreatePS (pm_hab, hdc, (& sizel),
-                     (PU_PELS | GPIF_DEFAULT | GPIT_MICRO | GPIA_ASSOC)));
-  if (hps == 0)
-    window_error (GpiCreatePS);
-  /* Put color table in RGB mode so we can specify colors
-     directly in RGB values rather than as indices.  */
-  if (!GpiCreateLogColorTable (hps, LCOL_PURECOLOR, LCOLF_RGB, 0, 0, 0))
-    window_warning (GpiCreateLogColorTable);
-  (PS_HANDLE (ps)) = hps;
-  (PS_ID (ps)) = (allocate_id ((& psid_table), ps));
-  (PS_QID (ps)) = qid;
-  (PS_VISUAL_TYPE (ps)) = type;
-  (PS_VISUAL (ps)) = 0;
-  (PS_CHAR_INCREMENTS (ps)) = 0;
-  ps_set_colors (ps, RGB_BLACK, RGB_WHITE);
-  return (ps);
-}
-
-static void
-destroy_ps (ps_t * ps)
-{
-  if ((PS_CHAR_INCREMENTS (ps)) != 0)
-    OS_free (PS_CHAR_INCREMENTS (ps));
-  if (!GpiDestroyPS (PS_HANDLE (ps)))
-    window_warning (GpiDestroyPS);
-  deallocate_id ((& psid_table), (PS_ID (ps)));
-  OS_free (ps);
-}
-
 static void
 ps_bitblt (ps_t * target, ps_t * source, LONG npoints, PPOINTL points,
           LONG rop, ULONG options)
@@ -1355,20 +1664,6 @@ ps_text_width (ps_t * ps, const char * data, unsigned short size)
     return (size * ((PS_CHAR_INCREMENTS (ps)) [0]));
 }
 
-static void
-maybe_activate_cursor (ps_t * ps)
-{
-  if ((PS_VISUAL_TYPE (ps)) == pst_window)
-    activate_cursor (PS_VISUAL (ps));
-}
-
-static void
-maybe_deactivate_cursor (ps_t * ps)
-{
-  if ((PS_VISUAL_TYPE (ps)) == pst_window)
-    deactivate_cursor (PS_VISUAL (ps));
-}
-
 static void
 ps_clear (ps_t * ps, short xl, short xh, short yl, short yh)
 {
@@ -1383,6 +1678,18 @@ ps_clear (ps_t * ps, short xl, short xh, short yl, short yh)
   maybe_activate_cursor (ps);
 }
 
+static COLOR
+ps_get_foreground_color (ps_t * ps)
+{
+  return (PS_FOREGROUND_COLOR (ps));
+}
+
+static COLOR
+ps_get_background_color (ps_t * ps)
+{
+  return (PS_BACKGROUND_COLOR (ps));
+}
+
 static void
 ps_set_colors (ps_t * ps, COLOR foreground, COLOR background)
 {
@@ -1519,15 +1826,74 @@ ps_get_bitmap_bits (ps_t * ps, unsigned long start, unsigned long length,
   return (r);
 }
 
-static unsigned long
-ps_set_bitmap_bits (ps_t * ps, unsigned long start, unsigned long length,
-                   PBYTE data, PBITMAPINFO2 info)
+static unsigned long
+ps_set_bitmap_bits (ps_t * ps, unsigned long start, unsigned long length,
+                   PBYTE data, PBITMAPINFO2 info)
+{
+  LONG r = (GpiSetBitmapBits ((PS_HANDLE (ps)), start, length, data, info));
+  if (r < 0)
+    window_error (GpiSetBitmapBits);
+  return (r);
+}
+
+/* Helper Procedures */
+
+static HDC
+get_ps_device (HPS hps)
+{
+  HDC hdc = (GpiQueryDevice (hps));
+  if (hdc == HDC_ERROR)
+    window_error (GpiQueryDevice);
+  return (hdc);
+}
+
+static LONG
+get_device_capability (HDC hdc, LONG index)
+{
+  LONG result;
+  if (!DevQueryCaps (hdc, index, 1, (& result)))
+    window_error (DevQueryCaps);
+  return (result);
+}
+
+static ps_t *
+create_ps (pst_t type, HDC hdc, qid_t qid)
+{
+  ps_t * ps = (OS_malloc (sizeof (ps_t)));
+  SIZEL sizel;
+  HPS hps;
+  (sizel . cx) = 0;
+  (sizel . cy) = 0;
+  hps = (GpiCreatePS (pm_hab, hdc, (& sizel),
+                     (PU_PELS | GPIF_DEFAULT | GPIT_MICRO | GPIA_ASSOC)));
+  if (hps == 0)
+    window_error (GpiCreatePS);
+  /* Put color table in RGB mode so we can specify colors
+     directly in RGB values rather than as indices.  */
+  if (!GpiCreateLogColorTable (hps, LCOL_PURECOLOR, LCOLF_RGB, 0, 0, 0))
+    window_warning (GpiCreateLogColorTable);
+  (PS_HANDLE (ps)) = hps;
+  (PS_ID (ps)) = (allocate_id ((& psid_table), ps));
+  (PS_QID (ps)) = qid;
+  (PS_VISUAL_TYPE (ps)) = type;
+  (PS_VISUAL (ps)) = 0;
+  (PS_CHAR_INCREMENTS (ps)) = 0;
+  ps_set_colors (ps, RGB_BLACK, RGB_WHITE);
+  return (ps);
+}
+
+static void
+destroy_ps (ps_t * ps)
 {
-  LONG r = (GpiSetBitmapBits ((PS_HANDLE (ps)), start, length, data, info));
-  if (r < 0)
-    window_error (GpiSetBitmapBits);
-  return (r);
+  if ((PS_CHAR_INCREMENTS (ps)) != 0)
+    OS_free (PS_CHAR_INCREMENTS (ps));
+  if (!GpiDestroyPS (PS_HANDLE (ps)))
+    window_warning (GpiDestroyPS);
+  deallocate_id ((& psid_table), (PS_ID (ps)));
+  OS_free (ps);
 }
+\f
+/* Clipboard */
 
 static void
 clipboard_write_text (qid_t qid, const char * text)
@@ -1573,31 +1939,29 @@ clipboard_read_text (qid_t qid)
   return (result);
 }
 \f
+/* Menus */
+
 static HWND
 menu_create (qid_t qid, HWND owner, USHORT style, USHORT id)
 {
-  HWND menu
-    = (WinCreateWindow (owner, /* parent window */
-                       WC_MENU, /* class name */
-                       "",     /* window text */
-                       style,  /* window style */
-                       0, 0, 0, 0, /* size and position */
-                       owner,  /* owner window */
-                       HWND_TOP, /* sibling window */
-                       id,     /* ID */
-                       0,      /* control data */
-                       0       /* presentation parameters */
-                       ));
-  if (menu == NULLHANDLE)
-    window_error (WinCreateWindow);
-  return (menu);
-}
-
-static void
+  return
+    (WinCreateWindow (owner,   /* parent window */
+                     WC_MENU,  /* class name */
+                     "",       /* window text */
+                     style,    /* window style */
+                     0, 0, 0, 0, /* size and position */
+                     owner,    /* owner window */
+                     HWND_TOP, /* sibling window */
+                     id,       /* ID */
+                     0,        /* control data */
+                     0         /* presentation parameters */
+                     ));
+}
+
+static BOOL
 menu_destroy (qid_t qid, HWND menu)
 {
-  if (!WinDestroyWindow (menu))
-    window_error (WinDestroyWindow);
+  return (WinDestroyWindow (menu));
 }
 
 static USHORT
@@ -1671,21 +2035,19 @@ menu_set_item_attributes (qid_t qid, HWND menu, USHORT id, USHORT submenup,
 }
 
 static HWND
-window_handle_from_id (qid_t qid, HWND window, ULONG id)
+window_load_menu (window_t * window, HMODULE module, ULONG id)
 {
-  return (WinWindowFromID (window, id));
+  return (WinLoadMenu ((WINDOW_FRAME (window)), module, id));
 }
 
-static HWND
-window_load_menu (window_t * window, HMODULE module, ULONG id)
+static BOOL
+window_popup_menu (qid_t qid, HWND parent, HWND owner, HWND menu,
+                  LONG x, LONG y, LONG id, ULONG options)
 {
-  return (WinLoadMenu ((WINDOW_FRAME (window)), module, id));
+  return (WinPopupMenu (parent, owner, menu, x, y, id, options));
 }
 \f
-static int parse_font_spec (const char *, PSZ *, LONG *, USHORT *);
-static const char * unparse_font_spec (PSZ, LONG, USHORT);
-static int ps_set_font_1 (ps_t * ps, PSZ, LONG, USHORT, LONG);
-static PLONG ps_make_char_increments (LONG);
+/* Fonts */
 
 static font_metrics_t *
 ps_get_font_metrics (ps_t * ps)
@@ -1700,245 +2062,10 @@ ps_get_font_metrics (ps_t * ps)
   return (metrics);
 }
 
-static font_metrics_t *
-ps_set_font_internal (ps_t * ps, unsigned short id, const char * spec)
-{
-  return ((ps_set_font (ps, id, spec)) ? (ps_get_font_metrics (ps)) : 0);
-}
-
-static int
-ps_set_font (ps_t * ps, unsigned short id, const char * spec)
-{
-  PSZ name = 0;
-  LONG size;
-  USHORT selection;
-  if (!parse_font_spec (spec, (& name), (& size), (& selection)))
-    return (0);
-  if (!ps_set_font_1 (ps, name, size, selection, id))
-    {
-      OS_free (name);
-      return (0);
-    }
-  {
-    FONTMETRICS fm;
-    if (!GpiQueryFontMetrics ((PS_HANDLE (ps)), (sizeof (fm)), (& fm)))
-      window_error (GpiQueryFontMetrics);
-    if ((PS_CHAR_INCREMENTS (ps)) != 0)
-      OS_free (PS_CHAR_INCREMENTS (ps));
-    (PS_CHAR_INCREMENTS (ps))
-      = ((((fm . fsDefn) & FM_DEFN_OUTLINE) != 0)
-        ? (ps_make_char_increments (fm . lMaxCharInc))
-        : 0);
-  }
-  return (1);
-}
-
-static int
-parse_font_spec (const char * spec,
-                PSZ * pname, LONG * psize, USHORT * pselection)
-{
-  const char * scan = spec;
-  unsigned int size = 0;
-  unsigned int selection = 0;
-  while (('0' <= (*scan)) && ((*scan) <= '9'))
-    size = ((size * 10) + ((*scan++) - '0'));
-  if (size == 0)
-    return (0);
-  while (1)
-    {
-      if ((strncmp (scan, ".bold", 5)) == 0)
-       {
-         selection |= FATTR_SEL_BOLD;
-         scan += 5;
-       }
-      else if ((strncmp (scan, ".italic", 7)) == 0)
-       {
-         selection |= FATTR_SEL_ITALIC;
-         scan += 7;
-       }
-      else if ((strncmp (scan, ".outline", 8)) == 0)
-       {
-         selection |= FATTR_SEL_OUTLINE;
-         scan += 8;
-       }
-      else if ((strncmp (scan, ".strikeout", 10)) == 0)
-       {
-         selection |= FATTR_SEL_STRIKEOUT;
-         scan += 10;
-       }
-      else if ((strncmp (scan, ".underscore", 11)) == 0)
-       {
-         selection |= FATTR_SEL_UNDERSCORE;
-         scan += 11;
-       }
-      else
-       break;
-    }
-  if ((*scan++) != '.')
-    return (0);
-  (*pname) = (OS_malloc ((strlen (scan)) + 1));
-  strcpy ((*pname), scan);
-  (*psize) = (size * 10);
-  (*pselection) = selection;
-  return (1);
-}
-
-static const char *
-unparse_font_spec (PSZ name, LONG size, USHORT selection)
-{
-  char size_buffer [16];
-  char selection_buffer [16];
-  char * result;
-
-  sprintf (size_buffer, "%d", (size / 10));
-  strcpy (selection_buffer, "");
-  if ((selection & FATTR_SEL_BOLD) != 0)
-    strcat (selection_buffer, ".bold");
-  if ((selection & FATTR_SEL_ITALIC) != 0)
-    strcat (selection_buffer, ".italic");
-  if ((selection & FATTR_SEL_OUTLINE) != 0)
-    strcat (selection_buffer, ".outline");
-  if ((selection & FATTR_SEL_STRIKEOUT) != 0)
-    strcat (selection_buffer, ".strikeout");
-  if ((selection & FATTR_SEL_UNDERSCORE) != 0)
-    strcat (selection_buffer, ".underscore");
-  result
-    = (OS_malloc ((strlen (size_buffer))
-                 + (strlen (name))
-                 + (strlen (selection_buffer))
-                 + 2));
-  strcpy (result, size_buffer);
-  strcat (result, selection_buffer);
-  strcat (result, ".");
-  strcat (result, name);
-  return (result);
-}
-
-static int create_font (HPS, LONG, PFONTMETRICS, USHORT);
-static void copy_fontmetrics_to_fattrs (FONTMETRICS *, FATTRS *);
-static void ps_set_font_size (ps_t *, LONG);
-
-static int
-ps_set_font_1 (ps_t * ps, PSZ name, LONG size, USHORT selection, LONG id)
-{
-  HPS hps = (PS_HANDLE (ps));
-  LONG nfonts;
-  ULONG index;
-  PFONTMETRICS pfm;
-
-  nfonts = 0;
-  nfonts = (GpiQueryFonts (hps,
-                          (QF_PUBLIC | QF_PRIVATE),
-                          name,
-                          (& nfonts),
-                          (sizeof (FONTMETRICS)),
-                          0));
-  if (nfonts == GPI_ALTERROR)
-    window_error (GpiQueryFonts);
-  if (nfonts == 0)
-    return (0);
-  pfm = (OS_malloc (nfonts * (sizeof (FONTMETRICS))));
-  if ((GpiQueryFonts (hps,
-                     (QF_PUBLIC | QF_PRIVATE),
-                     name,
-                     (& nfonts),
-                     (sizeof (FONTMETRICS)),
-                     pfm))
-      == GPI_ALTERROR)
-    window_error (GpiQueryFonts);
-  {
-    int result = 0;
-    /* Choose an image font if one is available.  */
-    for (index = 0; (index < nfonts); index += 1)
-      if (((((pfm [index]) . fsType) & FM_TYPE_FIXED) != 0)
-         && ((((pfm [index]) . fsDefn) & FM_DEFN_OUTLINE) == 0)
-         && (((pfm [index]) . sNominalPointSize) == size)
-         && (create_font (hps, id, (& (pfm [index])), selection)))
-       {
-         GpiSetCharSet (hps, id);
-         result = 1;
-         goto done;
-       }
-    /* Otherwise, look for an outline font.  */
-    for (index = 0; (index < nfonts); index += 1)
-      if (((((pfm [index]) . fsType) & FM_TYPE_FIXED) != 0)
-         && ((((pfm [index]) . fsDefn) & FM_DEFN_OUTLINE) != 0)
-         && (create_font (hps, id, (& (pfm [index])), selection)))
-       {
-         GpiSetCharSet (hps, id);
-         ps_set_font_size (ps, size);
-         result = 1;
-         goto done;
-       }
-  done:
-    OS_free (pfm);
-    return (result);
-  }
-}
-
-static int
-create_font (HPS hps, LONG font_id, PFONTMETRICS pfm, USHORT selection)
-{
-  FATTRS fa;
-  copy_fontmetrics_to_fattrs (pfm, (&fa));
-  (fa . fsSelection) = selection;
-  return ((GpiCreateLogFont (hps, 0, font_id, (&fa))) == FONT_MATCH);
-}
-
-static void
-copy_fontmetrics_to_fattrs (FONTMETRICS * pfm, FATTRS * pfa)
-{
-  (pfa -> usRecordLength) = (sizeof (*pfa));
-  (pfa -> fsSelection) = (pfm -> fsSelection);
-  (pfa -> lMatch) = (pfm -> lMatch);
-  strcpy ((pfa -> szFacename), (pfm -> szFacename));
-  (pfa -> idRegistry) = (pfm -> idRegistry);
-  (pfa -> usCodePage) = (pfm -> usCodePage);
-  (pfa -> lMaxBaselineExt) = 0;
-  (pfa -> lAveCharWidth) = 0;
-  (pfa -> fsType) = 0;
-  (pfa -> fsFontUse)
-    = ((((pfm -> fsDefn) & FM_DEFN_OUTLINE) != 0)
-       ? (FATTR_FONTUSE_OUTLINE | FATTR_FONTUSE_TRANSFORMABLE)
-       : 0);
-}
-
-static void
-ps_set_font_size (ps_t * ps, LONG size)
-{
-  POINTL ptl [2];
-
-  ((ptl[0]) . x) = 0;
-  ((ptl[0]) . y) = 0;
-  {
-    LONG xres;
-    ps_query_caps (ps, CAPS_HORIZONTAL_FONT_RES, 1, (&xres));
-    ((ptl[1]) . x) = ((((xres * size) << 4) + 360) / 720);
-  }
-  {
-    LONG yres;
-    ps_query_caps (ps, CAPS_VERTICAL_FONT_RES, 1, (&yres));
-    ((ptl[1]) . y) = ((((yres * size) << 4) + 360) / 720);
-  }
-  if (!GpiConvert ((PS_HANDLE (ps)), CVTC_DEVICE, CVTC_WORLD, 2, ptl))
-    window_error (GpiConvert);
-  {
-    SIZEF s;
-    (s . cx) = ((((ptl[1]) . x) - ((ptl[0]) . x)) << 12);
-    (s . cy) = ((((ptl[1]) . y) - ((ptl[0]) . y)) << 12);
-    if (!GpiSetCharBox ((PS_HANDLE (ps)), (&s)))
-      window_error (GpiSetCharBox);
-  }
-}
-
-static PLONG
-ps_make_char_increments (LONG increment)
-{
-  PLONG increments = (OS_malloc ((sizeof (LONG)) * 512));
-  unsigned int index;
-  for (index = 0; (index < 512); index += 1)
-    (increments[index]) = increment;
-  return (increments);
+static font_metrics_t *
+ps_set_font_internal (ps_t * ps, unsigned short id, const char * spec)
+{
+  return ((ps_set_font (ps, id, spec)) ? (ps_get_font_metrics (ps)) : 0);
 }
 
 static const char *
@@ -1974,458 +2101,287 @@ window_font_dialog (window_t * window, const char * title)
        (info . flStyle) = (fm . fsSelection);
        /* copy_fontmetrics_to_fattrs ((&fm), (& (info . fAttrs))); */
       }
-  }
-  result = (WinFontDlg (HWND_DESKTOP, (WINDOW_CLIENT (window)), (&info)));
-  if ((result == NULLHANDLE) || ((info . lReturn) != DID_OK))
-    return (0);
-  {
-    PSZ face_name;
-    const char * font_spec;
-    {
-      FACENAMEDESC desc;
-      ULONG face_name_length;
-      (desc . usSize) = (sizeof (desc));
-      (desc . usWeightClass) = (info . usWeight);
-      (desc . usWidthClass) = (info . usWidth);
-      (desc . flOptions) = (info . flType);
-      face_name_length
-       = (GpiQueryFaceString (hps, (info . pszFamilyname), (&desc), 0, 0));
-      if (face_name_length == GPI_ERROR)
-       return (0);
-      face_name = (OS_malloc (face_name_length));
-      face_name_length
-       = (GpiQueryFaceString (hps, (info . pszFamilyname), (&desc),
-                              face_name_length, face_name));
-      if (face_name_length == GPI_ERROR)
-       {
-         OS_free (face_name);
-         return (0);
-       }
-    }
-    font_spec = (unparse_font_spec (face_name,
-                                   ((FIXEDINT (info . fxPointSize)) * 10),
-                                   (info . flStyle)));
-    OS_free (face_name);
-    return (font_spec);
-  }
-}
-\f
-static MRESULT EXPENTRY
-frame_window_procedure (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
-{
-  window_t * window = (hwnd_to_window (WinWindowFromID (hwnd, FID_CLIENT)));
-  switch (msg)
-    {
-    case WM_QUERYTRACKINFO:
-      /* Set the tracking grid for the resize operation.  */
-      {
-       MRESULT mr
-         = ((* original_frame_window_procedure) (hwnd, msg, mp1, mp2));
-       if (mr == MRTRUE)
-         {
-           PTRACKINFO pti = (PVOIDFROMMP (mp2));
-           if ((((pti -> fs) & TF_MOVE) != TF_MOVE)
-               && ((((pti -> fs) & TF_MOVE) != 0)
-                   || (((pti -> fs) & TF_SETPOINTERPOS) != 0)))
-             {
-               (pti -> fs) |= TF_GRID;
-               (pti -> cxGrid) = (WINDOW_GRID_X (window));
-               (pti -> cyGrid) = (WINDOW_GRID_Y (window));
-               (pti -> cxKeyboard) = (WINDOW_GRID_X (window));
-               (pti -> cyKeyboard) = (WINDOW_GRID_Y (window));
-             }
-         }
-       return (mr);
-      }
-    case WM_MINMAXFRAME:
-      /* If minimizing, mark the window to indicate this.  The client
-        will shortly receive a WM_SIZE which indicates that the
-        minimization has completed.  */
-      {
-       PSWP pswp = (PVOIDFROMMP (mp1));
-       if ((!WINDOW_MINIMIZEDP (window))
-           && (((pswp -> fl) & SWP_MINIMIZE) != 0))
-         {
-           (WINDOW_MINIMIZINGP (window)) = 1;
-           (WINDOW_MINIMIZEDP (window)) = 1;
-         }
-       else if ((WINDOW_MINIMIZEDP (window))
-                && (((pswp -> fl) & (SWP_RESTORE | SWP_MAXIMIZE)) != 0))
-         (WINDOW_MINIMIZEDP (window)) = 0;
-      }
-      break;
-    }
-  return ((* original_frame_window_procedure) (hwnd, msg, mp1, mp2));
-}
-\f
-static int process_keychar
-  (window_t *, unsigned short, unsigned char, unsigned char, unsigned short,
-   unsigned short);
-static int process_button (HWND, MPARAM, MPARAM, unsigned char, unsigned char);
-
-static MRESULT EXPENTRY
-window_procedure (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
-{
-  switch (msg)
-    {
-    case WM_CREATE:
-      {
-       window_t * window = (PVOIDFROMMP (mp1));
-       if (!WinSetWindowPtr (hwnd, QWP_WINDOW, window))
-         window_error (WinSetWindowPtr);
-       (WINDOW_CLIENT (window)) = hwnd;
-       (WINDOW_CLIENT_PS (window))
-         = (create_ps (pst_window,
-                       (WinOpenWindowDC (hwnd)),
-                       (WINDOW_QID (window))));
-       (PS_VISUAL (WINDOW_CLIENT_PS (window))) = window;
-       return (MRFALSE);
-      }
-    case WM_PAINT:
-      {
-       window_t * window = (hwnd_to_window (hwnd));
-       if (((WinQueryWindowULong ((WINDOW_FRAME (window)), QWL_STYLE))
-            & WS_MINIMIZED)
-           != 0)
-         break;
-       {
-         HPS hps = (PS_HANDLE (WINDOW_CLIENT_PS (window)));
-         RECTL rectl;
-         if ((WinBeginPaint ((WINDOW_CLIENT (window)), hps, (& rectl)))
-             == NULLHANDLE)
-           window_error (WinBeginPaint);
-         if (!WinEndPaint (hps))
-           window_error (WinEndPaint);
-         SEND_EVENT (window,
-                     (make_paint_event ((WINDOW_ID (window)),
-                                        (rectl . xLeft),
-                                        (rectl . xRight),
-                                        (rectl . yBottom),
-                                        (rectl . yTop))));
-       }
-       return (MRVOID);
-      }
-    case WM_SETFOCUS:
-      {
-       window_t * window = (hwnd_to_window (hwnd));
-       if (SHORT1FROMMP (mp2))
-         recreate_cursor (window);
-       else
-         {
-           win_destroy_cursor (WINDOW_CLIENT (window));
-           (WINDOW_CURSOR_CREATEDP (window)) = 0;
-         }
-       SEND_EVENT (window,
-                   (make_focus_event ((WINDOW_ID (window)),
-                                      (SHORT1FROMMP (mp2)))));
-       return (MRVOID);
-      }
-    case WM_CHAR:
-      return
-       ((process_keychar ((hwnd_to_window (hwnd)),
-                          (SHORT1FROMMP (mp1)),
-                          (CHAR3FROMMP (mp1)),
-                          (CHAR4FROMMP (mp1)),
-                          (SHORT1FROMMP (mp2)),
-                          (SHORT2FROMMP (mp2))))
-        ? MRTRUE
-        : MRFALSE);
-
-    case WM_TRANSLATEACCEL:
-      {
-       PQMSG qmsg = (PVOIDFROMMP (mp1));
-       USHORT flags = (SHORT1FROMMP (qmsg -> mp1));
-       USHORT char_code = (SHORT1FROMMP (qmsg -> mp2));
-       USHORT virtual_key = (SHORT2FROMMP (qmsg -> mp2));
-       /* Disable specific default accelerator keys.  */
-       if ((flags & KC_VIRTUALKEY) != 0)
-         switch (virtual_key)
-           {
-           case VK_ALT:
-           case VK_ALTGRAF:
-             /* Disable "Alt" keys, which normally pop up the system
-                menu.  These keys are used often in Edwin and the
-                default behavior is unacceptable.  */
-             return (MRFALSE);
-           case VK_SPACE:
-           case VK_ESC:
-           case VK_TAB:
-             /* Disable "Alt-SPC", "Alt-ESC", and "Alt-TAB", which
-                have standard key bindings in Edwin.  */
-             if ((flags & KC_ALT) != 0)
-               return (MRFALSE);
-           }
-       else if ((flags & KC_CHAR) != 0)
-         switch (char_code)
-           {
-           case ' ':
-           case '\033':
-           case '\t':
-             /* Disable "Alt-SPC", "Alt-ESC", and "Alt-TAB", if for
-                some reason they are reported as ASCII characters
-                rather than as virtual keys.  */
-             if ((flags & KC_ALT) != 0)
-               return (MRFALSE);
-           }
-       break;
-      }
-    case WM_CLOSE:
-      {
-       window_t * window = (hwnd_to_window (hwnd));
-       SEND_EVENT (window, (make_close_event (WINDOW_ID (window))));
-       return (MRVOID);
-      }
-    case WM_DESTROY:
-      {
-       window_t * window = (hwnd_to_window (hwnd));
-       destroy_ps (WINDOW_CLIENT_PS (window));
-       (WINDOW_CLIENT_PS (window)) = 0;
-       return (MRVOID);
-      }
-    case WM_SIZE:
-      {
-       window_t * window = (hwnd_to_window (hwnd));
-       /* If this message is part of a minimization, ignore it.  */
-       if (WINDOW_MINIMIZINGP (window))
-         {
-           (WINDOW_MINIMIZINGP (window)) = 0;
-           (WINDOW_MINIMIZEDP (window)) = 1;
-           break;
-         }
-       if (WINDOW_CURSOR_CREATEDP (window))
-         {
-           win_destroy_cursor (WINDOW_CLIENT (window));
-           (WINDOW_CURSOR_CREATEDP (window)) = 0;
-           (WINDOW_CURSOR_X (window)) = 0;
-           (WINDOW_CURSOR_Y (window)) = 0;
-           recreate_cursor (window);
-         }
-       SEND_EVENT (window,
-                   (make_resize_event ((WINDOW_ID (window)),
-                                       (SHORT1FROMMP (mp2)),
-                                       (SHORT2FROMMP (mp2)))));
-       return (MRVOID);
-      }
-    case WM_SHOW:
-      {
-       window_t * window = (hwnd_to_window (hwnd));
-       SEND_EVENT (window,
-                   (make_visibility_event ((WINDOW_ID (window)),
-                                           (SHORT1FROMMP (mp1)))));
-       return (MRVOID);
-      }
-    case WM_COMMAND:
-      {
-       window_t * window = (hwnd_to_window (hwnd));
-       SEND_EVENT (window,
-                   (make_command_event ((WINDOW_ID (window)),
-                                        ((COMMANDMSG (&msg)) -> cmd),
-                                        ((COMMANDMSG (&msg)) -> source),
-                                        ((COMMANDMSG (&msg)) -> fMouse))));
-       return (MRVOID);
-      }
-    case WM_HELP:
-      {
-       window_t * window = (hwnd_to_window (hwnd));
-       SEND_EVENT (window,
-                   (make_help_event ((WINDOW_ID (window)),
-                                     ((COMMANDMSG (&msg)) -> cmd),
-                                     ((COMMANDMSG (&msg)) -> source),
-                                     ((COMMANDMSG (&msg)) -> fMouse))));
-       return (MRVOID);
-      }
-    case WM_BUTTON1DOWN:
-      if (process_button (hwnd, mp1, mp2, 0, BUTTON_EVENT_DOWN))
-       return (MRTRUE);
-      break;
-    case WM_BUTTON1UP:
-      if (process_button (hwnd, mp1, mp2, 0, BUTTON_EVENT_UP))
-       return (MRTRUE);
-      break;
-    case WM_BUTTON1CLICK:
-      if (process_button (hwnd, mp1, mp2, 0, BUTTON_EVENT_CLICK))
-       return (MRTRUE);
-      break;
-    case WM_BUTTON1DBLCLK:
-      if (process_button (hwnd, mp1, mp2, 0, BUTTON_EVENT_DBLCLK))
-       return (MRTRUE);
-      break;
-    case WM_BUTTON2DOWN:
-      if (process_button (hwnd, mp1, mp2, 1, BUTTON_EVENT_DOWN))
-       return (MRTRUE);
-      break;
-    case WM_BUTTON2UP:
-      if (process_button (hwnd, mp1, mp2, 1, BUTTON_EVENT_UP))
-       return (MRTRUE);
-      break;
-    case WM_BUTTON2CLICK:
-      if (process_button (hwnd, mp1, mp2, 1, BUTTON_EVENT_CLICK))
-       return (MRTRUE);
-      break;
-    case WM_BUTTON2DBLCLK:
-      if (process_button (hwnd, mp1, mp2, 1, BUTTON_EVENT_DBLCLK))
-       return (MRTRUE);
-      break;
-    case WM_BUTTON3DOWN:
-      if (process_button (hwnd, mp1, mp2, 2, BUTTON_EVENT_DOWN))
-       return (MRTRUE);
-      break;
-    case WM_BUTTON3UP:
-      if (process_button (hwnd, mp1, mp2, 2, BUTTON_EVENT_UP))
-       return (MRTRUE);
-      break;
-    case WM_BUTTON3CLICK:
-      if (process_button (hwnd, mp1, mp2, 2, BUTTON_EVENT_CLICK))
-       return (MRTRUE);
-      break;
-    case WM_BUTTON3DBLCLK:
-      if (process_button (hwnd, mp1, mp2, 2, BUTTON_EVENT_DBLCLK))
-       return (MRTRUE);
-      break;
-    default:
-      break;
+  }
+  result = (WinFontDlg (HWND_DESKTOP, (WINDOW_CLIENT (window)), (&info)));
+  if ((result == NULLHANDLE) || ((info . lReturn) != DID_OK))
+    return (0);
+  {
+    PSZ face_name;
+    const char * font_spec;
+    {
+      FACENAMEDESC desc;
+      ULONG face_name_length;
+      (desc . usSize) = (sizeof (desc));
+      (desc . usWeightClass) = (info . usWeight);
+      (desc . usWidthClass) = (info . usWidth);
+      (desc . flOptions) = (info . flType);
+      face_name_length
+       = (GpiQueryFaceString (hps, (info . pszFamilyname), (&desc), 0, 0));
+      if (face_name_length == GPI_ERROR)
+       return (0);
+      face_name = (OS_malloc (face_name_length));
+      face_name_length
+       = (GpiQueryFaceString (hps, (info . pszFamilyname), (&desc),
+                              face_name_length, face_name));
+      if (face_name_length == GPI_ERROR)
+       {
+         OS_free (face_name);
+         return (0);
+       }
     }
-  return (WinDefWindowProc (hwnd, msg, mp1, mp2));
+    font_spec = (unparse_font_spec (face_name,
+                                   ((FIXEDINT (info . fxPointSize)) * 10),
+                                   (info . flStyle)));
+    OS_free (face_name);
+    return (font_spec);
+  }
 }
 
-static window_t *
-hwnd_to_window (HWND hwnd)
+/* Helper Procedures */
+
+static int
+ps_set_font (ps_t * ps, unsigned short id, const char * spec)
 {
-  window_t * window = (WinQueryWindowPtr (hwnd, QWP_WINDOW));
-  if (window == 0)
-    window_error (WinQueryWindowPtr);
-  return (window);
+  PSZ name = 0;
+  LONG size;
+  USHORT selection;
+  if (!parse_font_spec (spec, (& name), (& size), (& selection)))
+    return (0);
+  if (!ps_set_font_1 (ps, name, size, selection, id))
+    {
+      OS_free (name);
+      return (0);
+    }
+  {
+    FONTMETRICS fm;
+    if (!GpiQueryFontMetrics ((PS_HANDLE (ps)), (sizeof (fm)), (& fm)))
+      window_error (GpiQueryFontMetrics);
+    if ((PS_CHAR_INCREMENTS (ps)) != 0)
+      OS_free (PS_CHAR_INCREMENTS (ps));
+    (PS_CHAR_INCREMENTS (ps))
+      = ((((fm . fsDefn) & FM_DEFN_OUTLINE) != 0)
+        ? (ps_make_char_increments (fm . lMaxCharInc))
+        : 0);
+  }
+  return (1);
 }
-\f
+
 static int
-process_keychar (window_t * window, unsigned short flags,
-                unsigned char repeat, unsigned char scan_code,
-                unsigned short char_code, unsigned short virtual_key)
+ps_set_font_1 (ps_t * ps, PSZ name, LONG size, USHORT selection, LONG id)
 {
-  unsigned short code;
-  /* Ignore compound keys for now.  */
-  if ((flags & (KC_DEADKEY | KC_COMPOSITE | KC_INVALIDCOMP | KC_KEYUP)) != 0)
-    return (0);
-  else if ((flags & KC_VIRTUALKEY) != 0)
-    code = virtual_key;
-  else if ((flags & (KC_CHAR | KC_CTRL | KC_ALT)) != 0)
-    code = char_code;
-  else
+  HPS hps = (PS_HANDLE (ps));
+  LONG nfonts;
+  ULONG index;
+  PFONTMETRICS pfm;
+
+  nfonts = 0;
+  nfonts = (GpiQueryFonts (hps,
+                          (QF_PUBLIC | QF_PRIVATE),
+                          name,
+                          (& nfonts),
+                          (sizeof (FONTMETRICS)),
+                          0));
+  if (nfonts == GPI_ALTERROR)
+    window_error (GpiQueryFonts);
+  if (nfonts == 0)
     return (0);
-  SEND_EVENT
-    (window,
-     (make_key_event ((WINDOW_ID (window)), code, flags, repeat)));
+  pfm = (OS_malloc (nfonts * (sizeof (FONTMETRICS))));
+  if ((GpiQueryFonts (hps,
+                     (QF_PUBLIC | QF_PRIVATE),
+                     name,
+                     (& nfonts),
+                     (sizeof (FONTMETRICS)),
+                     pfm))
+      == GPI_ALTERROR)
+    window_error (GpiQueryFonts);
+  {
+    int result = 0;
+    /* Choose an image font if one is available.  */
+    for (index = 0; (index < nfonts); index += 1)
+      if (((((pfm [index]) . fsType) & FM_TYPE_FIXED) != 0)
+         && ((((pfm [index]) . fsDefn) & FM_DEFN_OUTLINE) == 0)
+         && (((pfm [index]) . sNominalPointSize) == size)
+         && (create_font (hps, id, (& (pfm [index])), selection)))
+       {
+         GpiSetCharSet (hps, id);
+         result = 1;
+         goto done;
+       }
+    /* Otherwise, look for an outline font.  */
+    for (index = 0; (index < nfonts); index += 1)
+      if (((((pfm [index]) . fsType) & FM_TYPE_FIXED) != 0)
+         && ((((pfm [index]) . fsDefn) & FM_DEFN_OUTLINE) != 0)
+         && (create_font (hps, id, (& (pfm [index])), selection)))
+       {
+         GpiSetCharSet (hps, id);
+         ps_set_font_size (ps, size);
+         result = 1;
+         goto done;
+       }
+  done:
+    OS_free (pfm);
+    return (result);
+  }
 }
 
 static int
-process_button (HWND hwnd, MPARAM mp1, MPARAM mp2,
-               unsigned char number, unsigned char type)
-{
-  window_t * window = (hwnd_to_window (hwnd));
-  SEND_EVENT (window,
-             (make_button_event ((WINDOW_ID (window)),
-                                 number,
-                                 type,
-                                 (SHORT1FROMMP (mp1)),
-                                 (SHORT2FROMMP (mp1)),
-                                 ((SHORT2FROMMP (mp2))
-                                  & (KC_SHIFT | KC_CTRL | KC_ALT)))));
-  return (1);
-}
-\f
-static msg_t *
-make_button_event (wid_t wid, unsigned char number, unsigned char type,
-                  unsigned short x, unsigned short y, unsigned short flags)
-{
-  msg_t * message = (OS2_create_message (mt_button_event));
-  (SM_BUTTON_EVENT_WID (message)) = wid;
-  (SM_BUTTON_EVENT_TYPE (message)) = (number | (type << 4));
-  (SM_BUTTON_EVENT_X (message)) = x;
-  (SM_BUTTON_EVENT_Y (message)) = y;
-  (SM_BUTTON_EVENT_FLAGS (message)) = flags;
-  return (message);
+create_font (HPS hps, LONG font_id, PFONTMETRICS pfm, USHORT selection)
+{
+  FATTRS fa;
+  copy_fontmetrics_to_fattrs (pfm, (&fa));
+  (fa . fsSelection) = selection;
+  return ((GpiCreateLogFont (hps, 0, font_id, (&fa))) == FONT_MATCH);
 }
 
-static msg_t *
-make_close_event (wid_t wid)
+static void
+copy_fontmetrics_to_fattrs (FONTMETRICS * pfm, FATTRS * pfa)
 {
-  msg_t * message = (OS2_create_message (mt_close_event));
-  (SM_CLOSE_EVENT_WID (message)) = wid;
-  return (message);
+  (pfa -> usRecordLength) = (sizeof (*pfa));
+  (pfa -> fsSelection) = (pfm -> fsSelection);
+  (pfa -> lMatch) = (pfm -> lMatch);
+  strcpy ((pfa -> szFacename), (pfm -> szFacename));
+  (pfa -> idRegistry) = (pfm -> idRegistry);
+  (pfa -> usCodePage) = (pfm -> usCodePage);
+  (pfa -> lMaxBaselineExt) = 0;
+  (pfa -> lAveCharWidth) = 0;
+  (pfa -> fsType) = 0;
+  (pfa -> fsFontUse)
+    = ((((pfm -> fsDefn) & FM_DEFN_OUTLINE) != 0)
+       ? (FATTR_FONTUSE_OUTLINE | FATTR_FONTUSE_TRANSFORMABLE)
+       : 0);
 }
 
-static msg_t *
-make_focus_event (wid_t wid, int gainedp)
+static void
+ps_set_font_size (ps_t * ps, LONG size)
 {
-  msg_t * message = (OS2_create_message (mt_focus_event));
-  (SM_FOCUS_EVENT_WID (message)) = wid;
-  (SM_FOCUS_EVENT_GAINEDP (message)) = gainedp;
-  return (message);
-}
+  POINTL ptl [2];
 
-static msg_t *
-make_key_event (wid_t wid, unsigned short code,
-               unsigned short flags, unsigned short repeat)
-{
-  msg_t * message = (OS2_create_message (mt_key_event));
-  (SM_KEY_EVENT_WID (message)) = wid;
-  (SM_KEY_EVENT_CODE (message)) = code;
-  (SM_KEY_EVENT_FLAGS (message)) = flags;
-  (SM_KEY_EVENT_REPEAT (message)) = repeat;
-  return (message);
+  ((ptl[0]) . x) = 0;
+  ((ptl[0]) . y) = 0;
+  {
+    LONG xres;
+    ps_query_caps (ps, CAPS_HORIZONTAL_FONT_RES, 1, (&xres));
+    ((ptl[1]) . x) = ((((xres * size) << 4) + 360) / 720);
+  }
+  {
+    LONG yres;
+    ps_query_caps (ps, CAPS_VERTICAL_FONT_RES, 1, (&yres));
+    ((ptl[1]) . y) = ((((yres * size) << 4) + 360) / 720);
+  }
+  if (!GpiConvert ((PS_HANDLE (ps)), CVTC_DEVICE, CVTC_WORLD, 2, ptl))
+    window_error (GpiConvert);
+  {
+    SIZEF s;
+    (s . cx) = ((((ptl[1]) . x) - ((ptl[0]) . x)) << 12);
+    (s . cy) = ((((ptl[1]) . y) - ((ptl[0]) . y)) << 12);
+    if (!GpiSetCharBox ((PS_HANDLE (ps)), (&s)))
+      window_error (GpiSetCharBox);
+  }
 }
 
-static msg_t *
-make_paint_event (wid_t wid,
-                 unsigned short xl, unsigned short xh,
-                 unsigned short yl, unsigned short yh)
+static PLONG
+ps_make_char_increments (LONG increment)
 {
-  msg_t * message = (OS2_create_message (mt_paint_event));
-  (SM_PAINT_EVENT_WID (message)) = wid;
-  (SM_PAINT_EVENT_XL (message)) = xl;
-  (SM_PAINT_EVENT_XH (message)) = xh;
-  (SM_PAINT_EVENT_YL (message)) = yl;
-  (SM_PAINT_EVENT_YH (message)) = yh;
-  return (message);
+  PLONG increments = (OS_malloc ((sizeof (LONG)) * 512));
+  unsigned int index;
+  for (index = 0; (index < 512); index += 1)
+    (increments[index]) = increment;
+  return (increments);
 }
 
-static msg_t *
-make_resize_event (wid_t wid, unsigned short width, unsigned short height)
+static struct font_selection
 {
-  msg_t * message = (OS2_create_message (mt_resize_event));
-  (SM_RESIZE_EVENT_WID (message)) = wid;
-  (SM_RESIZE_EVENT_WIDTH (message)) = width;
-  (SM_RESIZE_EVENT_HEIGHT (message)) = height;
-  return (message);
+  const char * name;
+  unsigned int selector;
+} font_selections [] =
+{
+  { ".bold", FATTR_SEL_BOLD },
+  { ".italic", FATTR_SEL_ITALIC },
+  { ".outline", FATTR_SEL_OUTLINE },
+  { ".strikeout", FATTR_SEL_STRIKEOUT },
+  { ".underscore", FATTR_SEL_UNDERSCORE },
+  { 0, 0 }
+};
+
+static int
+parse_font_spec (const char * spec,
+                PSZ * pname, LONG * psize, USHORT * pselection)
+{
+  const char * scan = spec;
+  unsigned int size = 0;
+  unsigned int selection = 0;
+  while (('0' <= (*scan)) && ((*scan) <= '9'))
+    size = ((size * 10) + ((*scan++) - '0'));
+  if (size == 0)
+    return (0);
+  while (1)
+    {
+      struct font_selection * selections = font_selections;
+      unsigned int name_length;
+      while (1)
+       {
+         if ((selections -> name) == 0)
+           goto no_more_selections;
+         name_length = (strlen (selections -> name));
+         if ((strncmp (scan, (selections -> name), name_length)) == 0)
+           {
+             selection |= (selections -> selector);
+             scan += name_length;
+             break;
+           }
+         selections += 1;
+       }
+    }
+ no_more_selections:
+  if ((*scan++) != '.')
+    return (0);
+  (*pname) = (OS_malloc ((strlen (scan)) + 1));
+  strcpy ((*pname), scan);
+  (*psize) = (size * 10);
+  (*pselection) = selection;
+  return (1);
 }
 
-static msg_t *
-make_visibility_event (wid_t wid, int shownp)
+static const char *
+unparse_font_spec (PSZ name, LONG size, USHORT selection)
 {
-  msg_t * message = (OS2_create_message (mt_visibility_event));
-  (SM_VISIBILITY_EVENT_WID (message)) = wid;
-  (SM_VISIBILITY_EVENT_SHOWNP (message)) = shownp;
-  return (message);
+  char size_buffer [16];
+  char selection_buffer [16];
+  struct font_selection * selections = font_selections;
+  char * result;
+
+  sprintf (size_buffer, "%d", (size / 10));
+  strcpy (selection_buffer, "");
+  while (1)
+    {
+      if ((selections -> name) == 0)
+       break;
+      if ((selection & (selections -> selector)) != 0)
+       strcat (selection_buffer, (selections -> name));
+      selections += 1;
+    }
+  result
+    = (OS_malloc ((strlen (size_buffer))
+                 + (strlen (name))
+                 + (strlen (selection_buffer))
+                 + 2));
+  strcpy (result, size_buffer);
+  strcat (result, selection_buffer);
+  strcat (result, ".");
+  strcat (result, name);
+  return (result);
 }
+\f
+/* Pointers */
 
-static msg_t *
-make_command_event (wid_t wid, USHORT command, USHORT source, USHORT mousep)
+static HPOINTER
+query_system_pointer (qid_t qid, HWND desktop, LONG id, BOOL copyp)
 {
-  msg_t * message = (OS2_create_message (mt_command_event));
-  (SM_COMMAND_EVENT_WID (message)) = wid;
-  (SM_COMMAND_EVENT_COMMAND (message)) = command;
-  (SM_COMMAND_EVENT_SOURCE (message)) = source;
-  (SM_COMMAND_EVENT_MOUSEP (message)) = mousep;
-  return (message);
+  return (WinQuerySysPointer (desktop, id, copyp));
 }
 
-static msg_t *
-make_help_event (wid_t wid, USHORT command, USHORT source, USHORT mousep)
+static BOOL
+set_pointer (qid_t qid, HWND desktop, HPOINTER pointer)
 {
-  msg_t * message = (OS2_create_message (mt_help_event));
-  (SM_HELP_EVENT_WID (message)) = wid;
-  (SM_HELP_EVENT_COMMAND (message)) = command;
-  (SM_HELP_EVENT_SOURCE (message)) = source;
-  (SM_HELP_EVENT_MOUSEP (message)) = mousep;
-  return (message);
+  return (WinSetPointer (desktop, pointer));
 }
index 5550e87c3fe2c5f7e15705d223606db3279f3123..14770848a5053bf1693596d7711540914f31965e 100644 (file)
@@ -1,6 +1,6 @@
 /* -*-C-*-
 
-$Id: os2pm.h,v 1.11 1995/10/30 08:03:19 cph Exp $
+$Id: os2pm.h,v 1.12 1995/11/03 01:29:32 cph Exp $
 
 Copyright (c) 1994-95 Massachusetts Institute of Technology
 
@@ -58,53 +58,14 @@ typedef struct
 {
   DECLARE_MSG_HEADER_FIELDS;
   wid_t wid;
-  unsigned char btype;
-  unsigned short x;
-  unsigned short y;
-  unsigned short flags;
-} sm_button_event_t;
-#define SM_BUTTON_EVENT_WID(m) (((sm_button_event_t *) (m)) -> wid)
-#define SM_BUTTON_EVENT_TYPE(m) (((sm_button_event_t *) (m)) -> btype)
-#define SM_BUTTON_EVENT_X(m) (((sm_button_event_t *) (m)) -> x)
-#define SM_BUTTON_EVENT_Y(m) (((sm_button_event_t *) (m)) -> y)
-#define SM_BUTTON_EVENT_FLAGS(m) (((sm_button_event_t *) (m)) -> flags)
-
-#define BUTTON_EVENT_DOWN 0
-#define BUTTON_EVENT_UP 1
-#define BUTTON_EVENT_CLICK 2
-#define BUTTON_EVENT_DBLCLK 3
-
-#define BUTTON_TYPE_NUMBER(type) ((type) & 0xf)
-#define BUTTON_TYPE_EVENT(type) (((type) >> 4) & 0xf)
-
-typedef struct
-{
-  DECLARE_MSG_HEADER_FIELDS;
-  wid_t wid;
-} sm_close_event_t;
-#define SM_CLOSE_EVENT_WID(m) (((sm_close_event_t *) (m)) -> wid)
-
-typedef struct
-{
-  DECLARE_MSG_HEADER_FIELDS;
-  wid_t wid;
-  char gainedp;
-} sm_focus_event_t;
-#define SM_FOCUS_EVENT_WID(m) (((sm_focus_event_t *) (m)) -> wid)
-#define SM_FOCUS_EVENT_GAINEDP(m) (((sm_focus_event_t *) (m)) -> gainedp)
-
-typedef struct
-{
-  DECLARE_MSG_HEADER_FIELDS;
-  wid_t wid;
-  unsigned short code;
-  unsigned short flags;
-  unsigned short repeat;
-} sm_key_event_t;
-#define SM_KEY_EVENT_WID(m) (((sm_key_event_t *) (m)) -> wid)
-#define SM_KEY_EVENT_CODE(m) (((sm_key_event_t *) (m)) -> code)
-#define SM_KEY_EVENT_FLAGS(m) (((sm_key_event_t *) (m)) -> flags)
-#define SM_KEY_EVENT_REPEAT(m) (((sm_key_event_t *) (m)) -> repeat)
+  ULONG msg;
+  MPARAM mp1;
+  MPARAM mp2;
+} sm_pm_event_t;
+#define SM_PM_EVENT_WID(m) (((sm_pm_event_t *) (m)) -> wid)
+#define SM_PM_EVENT_MSG(m) (((sm_pm_event_t *) (m)) -> msg)
+#define SM_PM_EVENT_MP1(m) (((sm_pm_event_t *) (m)) -> mp1)
+#define SM_PM_EVENT_MP2(m) (((sm_pm_event_t *) (m)) -> mp2)
 
 typedef struct
 {
@@ -120,53 +81,6 @@ typedef struct
 #define SM_PAINT_EVENT_XH(m) (((sm_paint_event_t *) (m)) -> xh)
 #define SM_PAINT_EVENT_YL(m) (((sm_paint_event_t *) (m)) -> yl)
 #define SM_PAINT_EVENT_YH(m) (((sm_paint_event_t *) (m)) -> yh)
-
-typedef struct
-{
-  DECLARE_MSG_HEADER_FIELDS;
-  wid_t wid;
-  unsigned short width;
-  unsigned short height;
-} sm_resize_event_t;
-#define SM_RESIZE_EVENT_WID(m) (((sm_resize_event_t *) (m)) -> wid)
-#define SM_RESIZE_EVENT_WIDTH(m) (((sm_resize_event_t *) (m)) -> width)
-#define SM_RESIZE_EVENT_HEIGHT(m) (((sm_resize_event_t *) (m)) -> height)
-
-typedef struct
-{
-  DECLARE_MSG_HEADER_FIELDS;
-  wid_t wid;
-  char shownp;
-} sm_visibility_event_t;
-#define SM_VISIBILITY_EVENT_WID(m) (((sm_visibility_event_t *) (m)) -> wid)
-#define SM_VISIBILITY_EVENT_SHOWNP(m)                                  \
-  (((sm_visibility_event_t *) (m)) -> shownp)
-
-typedef struct
-{
-  DECLARE_MSG_HEADER_FIELDS;
-  wid_t wid;
-  unsigned short command;
-  unsigned short source;
-  unsigned short mousep;
-} sm_command_event_t;
-#define SM_COMMAND_EVENT_WID(m) (((sm_command_event_t *) (m)) -> wid)
-#define SM_COMMAND_EVENT_COMMAND(m) (((sm_command_event_t *) (m)) -> command)
-#define SM_COMMAND_EVENT_SOURCE(m) (((sm_command_event_t *) (m)) -> source)
-#define SM_COMMAND_EVENT_MOUSEP(m) (((sm_command_event_t *) (m)) -> mousep)
-
-typedef struct
-{
-  DECLARE_MSG_HEADER_FIELDS;
-  wid_t wid;
-  unsigned short command;
-  unsigned short source;
-  unsigned short mousep;
-} sm_help_event_t;
-#define SM_HELP_EVENT_WID(m) (((sm_help_event_t *) (m)) -> wid)
-#define SM_HELP_EVENT_COMMAND(m) (((sm_help_event_t *) (m)) -> command)
-#define SM_HELP_EVENT_SOURCE(m) (((sm_help_event_t *) (m)) -> source)
-#define SM_HELP_EVENT_MOUSEP(m) (((sm_help_event_t *) (m)) -> mousep)
 \f
 typedef enum
 {
@@ -185,23 +99,28 @@ typedef enum
 extern msg_t * OS2_read_pm_tqueue (tqueue_t *, int);
 extern void OS2_write_pm_tqueue (tqueue_t *, msg_t *);
 
-extern int OS2_psid_validp (psid_t);
-extern int OS2_wid_validp (wid_t);
-extern int OS2_bid_validp (bid_t);
-
 /* This machine-generated file contains most of the procedure prototypes.  */
 #include "os2pm-ed.h"
 
+extern int OS2_psid_validp (psid_t);
+extern int OS2_wid_validp (wid_t);
+extern int OS2_bid_validp (bid_t);
 extern psid_t OS2_window_client_ps (wid_t);
 extern qid_t OS2_create_pm_qid (tqueue_t *);
 extern void OS2_window_permanent (wid_t);
-extern void OS2_window_pos (wid_t, short *, short *);
-extern void OS2_window_size (wid_t, unsigned short *, unsigned short *);
-extern void OS2_window_frame_size (wid_t, unsigned short *, unsigned short *);
+extern void OS2_window_mousetrack (wid_t, int);
 extern HWND OS2_window_frame_handle (wid_t);
+extern HWND OS2_window_client_handle (wid_t);
 extern int OS2_memory_ps_p (psid_t);
 extern bid_t OS2_ps_get_bitmap (psid_t);
+
+extern void OS2_window_pos (wid_t, short *, short *);
+extern void OS2_window_size (wid_t, unsigned short *, unsigned short *);
+extern void OS2_window_frame_size (wid_t, unsigned short *, unsigned short *);
 extern bid_t OS2_ps_set_bitmap (psid_t, bid_t);
 extern font_metrics_t * OS2_ps_set_font (psid_t, unsigned short, const char *);
 
+extern int OS2_translate_wm_char
+  (MPARAM, MPARAM, unsigned short *, unsigned short *, unsigned char *);
+
 #endif /* SCM_OS2PM_H */
index f980191b43515be9fa9184f7a7fdaa2b1e89839b..969a2403638bdf3580dcb163ae8aabf09a57630d 100644 (file)
@@ -1,6 +1,6 @@
 #| -*-Scheme-*-
 
-$Id: os2pm.scm,v 1.1 1995/10/30 07:57:55 cph Exp $
+$Id: os2pm.scm,v 1.2 1995/11/03 01:29:45 cph Exp $
 
 Copyright (c) 1995 Massachusetts Institute of Technology
 
@@ -766,7 +766,9 @@ MIT in each case. */
   (value sync)
   (arguments qid))
 
-(define-pm-procedure (window_open open_window)
+;;; Windows
+
+(define-pm-procedure window_open
   (value ("wid_t" wid))
   (arguments qid
             (qid_t event_qid)
@@ -776,19 +778,10 @@ MIT in each case. */
             (ulong style)
             ((array (const char)) title)))
 
-(define-pm-procedure (window_close close_window)
+(define-pm-procedure window_close
   (arguments window))
 
-(define-pm-procedure (window_show show_window)
-  (arguments window (boolean showp)))
-
-(define-pm-procedure (window_move_cursor move_cursor)
-  (arguments window (short x) (short y)))
-
-(define-pm-procedure (window_shape_cursor shape_cursor)
-  (arguments window (ushort width) (ushort height) (ushort style)))
-
-(define-pm-procedure (window_show_cursor enable_cursor)
+(define-pm-procedure window_show
   (arguments window (boolean showp)))
 
 (define-pm-procedure window_scroll
@@ -809,30 +802,51 @@ MIT in each case. */
 (define-pm-procedure window_activate
   (arguments window))
 
-;;; window_pos
+;;; (define_pm_procedure window_pos ...)
 
-(define-pm-procedure (window_set_pos set_window_pos)
+(define-pm-procedure window_set_pos
   (arguments window (short x) (short y)))
 
-;;; window_size
-;;; window_frame_size
+;;; (define_pm_procedure window_size ...)
+;;; (define_pm_procedure window_frame_size ...)
 
-(define-pm-procedure (window_set_size set_window_size)
+(define-pm-procedure window_set_size
   (arguments window (ushort x) (ushort y)))
 
 (define-pm-procedure window_focusp
   (value (boolean focusp))
   (arguments window))
 
-(define-pm-procedure (window_set_state set_window_state)
+(define-pm-procedure window_set_state
   (arguments window (window_state_t state)))
 
-(define-pm-procedure (window_set_title set_window_title)
+(define-pm-procedure window_set_title
   (arguments window ((array (const char)) title)))
 
-(define-pm-procedure (window_update_frame update_frame_window)
+(define-pm-procedure window_update_frame
   (arguments window (ushort flags)))
 
+(define-pm-procedure window_handle_from_id
+  (value ("HWND" child))
+  (arguments qid ("HWND" parent) (ulong id)))
+
+(define-pm-procedure window_set_capture
+  (value ("BOOL" successp))
+  (arguments window (int capturep)))
+
+;;; Text Cursors
+
+(define-pm-procedure window_move_cursor
+  (arguments window (short x) (short y)))
+
+(define-pm-procedure window_shape_cursor
+  (arguments window (ushort width) (ushort height) (ushort style)))
+
+(define-pm-procedure window_show_cursor
+  (arguments window (boolean showp)))
+
+;;; Presentation Spaces
+
 (define-pm-procedure create_memory_ps
   (value ps)
   (arguments qid))
@@ -847,7 +861,7 @@ MIT in each case. */
 (define-pm-procedure destroy_bitmap
   (arguments bitmap))
 
-;;; ps_set_bitmap
+;;; (define_pm_procedure ps_set_bitmap ...)
 
 (define-pm-procedure ps_bitblt
   (arguments ((id ps) target)
@@ -870,18 +884,16 @@ MIT in each case. */
             ((array (const char)) data size)
             (ushort size)))
 
-(define-pm-procedure ps_get_font_metrics
-  (value ((pointer font_metrics_t) metrics))
-  (arguments ps))
-
 (define-pm-procedure ps_clear
   (arguments ps (short xl) (short xh) (short yl) (short yh)))
 
-(define-pm-procedure ps_set_font_internal
-  (value ((pointer font_metrics_t) metrics))
-  (arguments ps
-            (ushort id)
-            ((array (const char)) name)))
+(define-pm-procedure ps_get_foreground_color
+  (value ("COLOR" color))
+  (arguments ps))
+
+(define-pm-procedure ps_get_background_color
+  (value ("COLOR" color))
+  (arguments ps))
 
 (define-pm-procedure ps_set_colors
   (arguments ps ("COLOR" foreground) ("COLOR" background)))
@@ -943,6 +955,8 @@ MIT in each case. */
             ((pointer "BYTE") data)
             ((pointer "BITMAPINFO2") info)))
 
+;;; Clipboard
+
 (define-pm-procedure clipboard_write_text
   (value sync)
   (arguments qid ((pointer (const char)) text)))
@@ -951,11 +965,14 @@ MIT in each case. */
   (value ((pointer (const char)) text))
   (arguments qid))
 
+;;; Menus
+
 (define-pm-procedure menu_create
   (value ("HWND" menu))
   (arguments qid ("HWND" owner) (ushort style) (ushort id)))
 
 (define-pm-procedure menu_destroy
+  (value ("BOOL" successp))
   (arguments qid ("HWND" menu)))
 
 (define-pm-procedure menu_insert_item
@@ -1008,16 +1025,45 @@ MIT in each case. */
             (ushort mask)
             (ushort attributes)))
 
-(define-pm-procedure window_handle_from_id
-  (value ("HWND" child))
-  (arguments qid ("HWND" parent) (ulong id)))
-
 (define-pm-procedure window_load_menu
   (value ("HWND" menu))
   (arguments window ("HMODULE" module) (ulong id)))
 
+(define-pm-procedure window_popup_menu
+  (value ("BOOL" successp))
+  (arguments qid
+            ("HWND" parent)
+            ("HWND" owner)
+            ("HWND" menu)
+            (long x)
+            (long y)
+            (long id)
+            (ulong options)))
+
+;;; Font
+
+(define-pm-procedure ps_get_font_metrics
+  (value ((pointer font_metrics_t) metrics))
+  (arguments ps))
+
+(define-pm-procedure ps_set_font_internal
+  (value ((pointer font_metrics_t) metrics))
+  (arguments ps
+            (ushort id)
+            ((array (const char)) name)))
+
 (define-pm-procedure window_font_dialog
   (value ((pointer (const char)) spec))
   (arguments window ((pointer (const char)) title)))
 
+;;; Pointers
+
+(define-pm-procedure query_system_pointer
+  (value ("HPOINTER" pointer))
+  (arguments qid ("HWND" desktop) (long id) ("BOOL" copyp)))
+
+(define-pm-procedure set_pointer
+  (value ("BOOL" successp))
+  (arguments qid ("HWND" desktop) ("HPOINTER" pointer)))
+
 (write-all-files)
\ No newline at end of file
index e35e01a992bb8be33aa0b87010d76b9e9cd53281..469bfa519db7ffc44a717ef4b1a9214a2a7e404b 100644 (file)
@@ -1,6 +1,6 @@
 /* -*-C-*-
 
-$Id: os2pmcon.c,v 1.16 1995/10/30 08:07:22 cph Exp $
+$Id: os2pmcon.c,v 1.17 1995/11/03 01:29:57 cph Exp $
 
 Copyright (c) 1994-95 Massachusetts Institute of Technology
 
@@ -45,18 +45,31 @@ static void grab_console_lock (void);
 static void release_console_lock (void);
 static unsigned short cx2x (unsigned short);
 static unsigned short cy2y (unsigned short, int);
-static unsigned short x2cx (unsigned short, int);
-static unsigned short y2cy (unsigned short, int);
+static unsigned short x2cx (short, int);
+static unsigned short y2cy (short, int);
 static void process_events (int);
 static void enqueue_pending_event (msg_t *);
+static void initialize_marked_region (short, short);
+static void update_marked_region (short, short);
+static void unmark_marked_region (void);
+static void compute_marked_region
+  (short, short, short, short,
+   unsigned short *, unsigned short *, unsigned short *, unsigned short *);
+static void highlight_marked_region
+  (unsigned short, unsigned short, unsigned short, unsigned short, char);
+static void paint_marked_region_segment
+  (unsigned short, unsigned short, unsigned short, unsigned short);
+static char * extract_marked_region (int);
 static void console_resize (unsigned short, unsigned short);
 static void console_paint
   (unsigned short, unsigned short, unsigned short, unsigned short);
+static unsigned short compute_run_length (const char *, const char *);
 static void console_clear
   (unsigned short, unsigned short, unsigned short, unsigned short);
 static void console_clear_all (void);
 static int do_paste (void);
-static int translate_key_event (msg_t *);
+static int translate_key_event
+  (MPARAM, MPARAM, unsigned short *, unsigned char *);
 static const char * find_nonprint (const char *, const char *);
 static void do_carriage_return (void);
 static void do_linefeed (void);
@@ -71,6 +84,8 @@ static unsigned short console_pel_height;
 static unsigned short console_width;
 static unsigned short console_height;
 static char * console_chars;
+static char * console_highlights;
+static unsigned short * console_line_lengths;
 static font_metrics_t * console_metrics;
 static unsigned short point_x;
 static unsigned short point_y;
@@ -87,11 +102,20 @@ static qid_t console_event_qid;
 static qid_t console_pm_qid;
 static wid_t console_wid;
 static psid_t console_psid;
+static int console_tracking_mouse_p;
+static HWND console_tracking_mouse_pointer;
+static int console_marked_region_active_p;
+static short console_mark_x;
+static short console_mark_y;
+static short console_point_x;
+static short console_point_y;
 
 #define CHAR_WIDTH (FONT_METRICS_WIDTH (console_metrics))
 #define CHAR_HEIGHT (FONT_METRICS_HEIGHT (console_metrics))
 #define CHAR_DESCENDER (FONT_METRICS_DESCENDER (console_metrics))
 #define CHAR_LOC(x, y) (& (console_chars [((y) * console_width) + (x)]))
+#define CHAR_HL(x, y) (& (console_highlights [((y) * console_width) + (x)]))
+#define LINE_LEN_LOC(y) ((char *) (& (console_line_lengths [(y)])))
 
 #define FASTFILL(p, n, c)                                              \
 {                                                                      \
@@ -110,10 +134,16 @@ OS2_initialize_pm_console (void)
   console_width = 0;
   console_height = 0;
   console_chars = 0;
+  console_highlights = 0;
+  console_line_lengths = 0;
   point_x = 0;
   point_y = 0;
   console_visiblep = 0;
   console_closedp = 0;
+  console_tracking_mouse_p = 0;
+  console_tracking_mouse_pointer
+    = (WinQuerySysPointer (HWND_DESKTOP, SPTR_TEXT, FALSE));
+  console_marked_region_active_p = 0;
   readahead_repeat = 0;
   readahead_insert = 0;
   pending_events_head = 0;
@@ -215,21 +245,21 @@ cy2y (unsigned short y, int lowerp)
 }
 
 static unsigned short
-x2cx (unsigned short x, int lowerp)
+x2cx (short x, int lowerp)
 {
   /* lowerp => `x' is inclusive lower bound, and result is cell it
      falls in.  Otherwise, `x' is exclusive upper bound, and result is
      cell to its right, unless it falls on leftmost edge of cell.  If
      the argument is inclusive-lower, then the result is also;
      likewise for exclusive-upper.  */
-  unsigned short cx = (x / CHAR_WIDTH);
+  short cx = (x / CHAR_WIDTH);
   if (! (lowerp || ((x % CHAR_WIDTH) == 0)))
     cx += 1;
-  return ((cx > console_width) ? console_width : cx);
+  return ((cx < 0) ? 0 : (cx > console_width) ? console_width : cx);
 }
 
 static unsigned short
-y2cy (unsigned short y, int lowerp)
+y2cy (short y, int lowerp)
 {
   /* lowerp => `y' is inclusive lower bound, and result is cell below
      the one it falls in.  Otherwise, `y' is exclusive upper bound,
@@ -240,7 +270,7 @@ y2cy (unsigned short y, int lowerp)
   short cy = (((short) (console_height - 1)) - ((short) (y / CHAR_HEIGHT)));
   if (lowerp || ((y % CHAR_HEIGHT) == 0))
     cy += 1;
-  return ((cy < 0) ? 0 : cy);
+  return ((cy < 0) ? 0 : (cy > console_height) ? console_height : cy);
 }
 \f
 static void
@@ -254,22 +284,6 @@ process_events (int blockp)
        break;
       switch (MSG_TYPE (message))
        {
-       case mt_key_event:
-       case mt_close_event:
-         enqueue_pending_event (message);
-         if (blockp)
-           return;
-         break;
-       case mt_resize_event:
-         {
-           unsigned short new_pel_width = (SM_RESIZE_EVENT_WIDTH (message));
-           unsigned short new_pel_height = (SM_RESIZE_EVENT_HEIGHT (message));
-           OS2_destroy_message (message);
-           grab_console_lock ();
-           console_resize (new_pel_width, new_pel_height);
-           release_console_lock ();
-           break;
-         }
        case mt_paint_event:
          {
            unsigned short xl = (SM_PAINT_EVENT_XL (message));
@@ -278,65 +292,135 @@ process_events (int blockp)
            unsigned short yh = (SM_PAINT_EVENT_YH (message));
            OS2_destroy_message (message);
            grab_console_lock ();
-           console_paint (xl, xh, yl, yh);
+           OS2_ps_clear (console_psid, xl, xh, yl, yh);
+           console_paint ((x2cx (xl, 1)),
+                          (x2cx (xh, 0)),
+                          (y2cy (yh, 0)),
+                          (y2cy (yl, 1)));
            release_console_lock ();
            break;
          }
-       case mt_visibility_event:
-         if ((!console_visiblep) && (SM_VISIBILITY_EVENT_SHOWNP (message)))
-           {
-             grab_console_lock ();
-             OS2_window_invalidate (console_wid,
-                                    0, console_pel_width,
-                                    0, console_pel_height);
-             release_console_lock ();
-           }
-         console_visiblep = (SM_VISIBILITY_EVENT_SHOWNP (message));
-         OS2_destroy_message (message);
-         break;
-       case mt_button_event:
-         if ((BUTTON_TYPE_EVENT (SM_BUTTON_EVENT_TYPE (message)))
-              == BUTTON_EVENT_DOWN)
-           OS2_window_activate (SM_BUTTON_EVENT_WID (message));
-         OS2_destroy_message (message);
-         break;
-       case mt_command_event:
-         switch (SM_COMMAND_EVENT_COMMAND (message))
-           {
-           case IDM_CUT:
-           case IDM_COPY:
-           case IDM_PASTE:
-             enqueue_pending_event (message);
-             if (blockp)
-               return;
-             break;
-           case IDM_FONT:
+       case mt_pm_event:
+         {
+           ULONG msg = (SM_PM_EVENT_MSG (message));
+           MPARAM mp1 = (SM_PM_EVENT_MP1 (message));
+           MPARAM mp2 = (SM_PM_EVENT_MP2 (message));
+           switch (msg)
              {
-               const char * font_spec
-                 = (OS2_window_font_dialog (console_wid,
-                                            "Console Window Font"));
-               if (font_spec != 0)
+             case WM_CHAR:
+             case WM_CLOSE:
+             postpone_event:
+               enqueue_pending_event (message);
+               message = 0;
+               if (blockp)
+                 return;
+               break;
+             case WM_SIZE:
+               {
+                 unsigned short new_pel_width = (SHORT1FROMMP (mp2));
+                 unsigned short new_pel_height = (SHORT2FROMMP (mp2));
+                 grab_console_lock ();
+                 console_resize (new_pel_width, new_pel_height);
+                 release_console_lock ();
+                 break;
+               }
+             case WM_SHOW:
+               if ((!console_visiblep) && (SHORT1FROMMP (mp1)))
                  {
-                   (void) OS2_ps_set_font (console_psid, 1, font_spec);
-                   OS_free ((void *) font_spec);
+                   grab_console_lock ();
+                   OS2_window_invalidate (console_wid,
+                                          0, console_pel_width,
+                                          0, console_pel_height);
+                   release_console_lock ();
+                 }
+               console_visiblep = (SHORT1FROMMP (mp1));
+               break;
+             case WM_BUTTON1DOWN:
+               grab_console_lock ();
+               if (!OS2_window_focusp (console_wid))
+                 OS2_window_activate (console_wid);
+               else if (OS2_window_set_capture (console_wid, 1))
+                 {
+                   console_tracking_mouse_p = 1;
+                   initialize_marked_region ((SHORT1FROMMP (mp1)),
+                                             (SHORT2FROMMP (mp1)));
+                   OS2_window_mousetrack (console_wid, 1);
+                   OS2_set_pointer (console_pm_qid,
+                                    HWND_DESKTOP,
+                                    console_tracking_mouse_pointer);
+                 }
+               else
+                 (void) WinAlarm (HWND_DESKTOP, WA_ERROR);
+               release_console_lock ();
+               break;
+             case WM_BUTTON1UP:
+               if (console_tracking_mouse_p)
+                 {
+                   grab_console_lock ();
+                   update_marked_region ((SHORT1FROMMP (mp1)),
+                                         (SHORT2FROMMP (mp1)));
+                   (void) OS2_window_set_capture (console_wid, 0);
+                   OS2_window_mousetrack (console_wid, 0);
+                   console_tracking_mouse_p = 0;
+                   release_console_lock ();
+                 }
+               break;
+             case WM_MOUSEMOVE:
+               if (console_tracking_mouse_p)
+                 {
+                   grab_console_lock ();
+                   update_marked_region ((SHORT1FROMMP (mp1)),
+                                         (SHORT2FROMMP (mp1)));
+                   OS2_set_pointer (console_pm_qid,
+                                    HWND_DESKTOP,
+                                    console_tracking_mouse_pointer);
+                   release_console_lock ();
+                 }
+               break;
+             case WM_BUTTON2DOWN:
+             case WM_BUTTON3DOWN:
+               grab_console_lock ();
+               if (!OS2_window_focusp (console_wid))
+                 OS2_window_activate (console_wid);
+               release_console_lock ();
+               break;
+             case WM_COMMAND:
+               switch (SHORT1FROMMP (mp1))
+                 {
+                 case IDM_CUT:
+                 case IDM_COPY:
+                 case IDM_PASTE:
+                   goto postpone_event;
+                 case IDM_FONT:
+                   grab_console_lock ();
+                   {
+                     const char * font_spec
+                       = (OS2_window_font_dialog (console_wid,
+                                                  "Console Window Font"));
+                     if (font_spec != 0)
+                       {
+                         (void) OS2_ps_set_font (console_psid, 1, font_spec);
+                         OS_free ((void *) font_spec);
+                       }
+                   }
+                   release_console_lock ();
+                   break;
+                 case IDM_EXIT:
+                   termination_normal (0);
+                   break;
+                 case IDM_ABOUT:
+                   (void) WinMessageBox
+                     (HWND_DESKTOP, NULLHANDLE,
+                      "This is MIT Scheme Release "
+                      RELEASE
+                      ", brought to you by the MIT Scheme Team.\n",
+                      "The Uncommon Lisp", 0, MB_OK);
+                   break;
                  }
              }
-             break;
-           case IDM_EXIT:
-             termination_normal (0);
-             break;
-           case IDM_ABOUT:
-             {
-               char buffer [256];
-               sprintf (buffer,
-                        "This is MIT Scheme Release %s, built on %s.  "
-                        "Brought to you by the MIT Scheme Team.\n",
-                        RELEASE, __DATE__);
-               (void) WinMessageBox (HWND_DESKTOP, NULLHANDLE, buffer, "", 0,
-                                     MB_OK);
-             }
-             break;
-           }
+           if (message != 0)
+             OS2_destroy_message (message);
+         }
          break;
        default:
          OS2_destroy_message (message);
@@ -359,36 +443,294 @@ enqueue_pending_event (msg_t * message)
 }
 \f
 static void
+initialize_marked_region (short x, short y)
+{
+  unmark_marked_region ();
+  console_mark_x = x;
+  console_mark_y = y;
+  console_point_x = x;
+  console_point_y = y;
+  console_marked_region_active_p = 1;
+}
+
+static void
+update_marked_region (short x, short y)
+{
+  unsigned short cx11;
+  unsigned short cy11;
+  unsigned short cx21;
+  unsigned short cy21;
+  unsigned short cx12;
+  unsigned short cy12;
+  unsigned short cx22;
+  unsigned short cy22;
+
+  unsigned short i11;
+  unsigned short i21;
+  unsigned short i12;
+  unsigned short i22;
+
+  compute_marked_region (console_mark_x, console_mark_y,
+                        console_point_x, console_point_y,
+                        (&cx11), (&cy11), (&cx21), (&cy21));
+  highlight_marked_region (cx11, cy11, cx21, cy21, '\0');
+
+  compute_marked_region (console_mark_x, console_mark_y, x, y,
+                        (&cx12), (&cy12), (&cx22), (&cy22));
+  highlight_marked_region (cx12, cy12, cx22, cy22, '\1');
+
+  i11 = ((cy11 * console_width) + cx11);
+  i21 = ((cy21 * console_width) + cx21);
+  i12 = ((cy12 * console_width) + cx12);
+  i22 = ((cy22 * console_width) + cx22);
+
+  if (i11 < i12)
+    paint_marked_region_segment (cx11, cy11, cx12, cy12);
+  else if (i12 < i11)
+    paint_marked_region_segment (cx12, cy12, cx11, cy11);
+  if (i21 < i22)
+    paint_marked_region_segment (cx21, cy21, cx22, cy22);
+  else if (i22 < i21)
+    paint_marked_region_segment (cx22, cy22, cx21, cy21);
+
+  console_point_x = x;
+  console_point_y = y;
+  console_marked_region_active_p = 1;
+}
+
+static void
+unmark_marked_region (void)
+{
+  if (console_marked_region_active_p)
+    {
+      unsigned short cx1;
+      unsigned short cy1;
+      unsigned short cx2;
+      unsigned short cy2;
+      compute_marked_region (console_mark_x, console_mark_y,
+                            console_point_x, console_point_y,
+                            (&cx1), (&cy1), (&cx2), (&cy2));
+      highlight_marked_region (cx1, cy1, cx2, cy2, '\0');
+      paint_marked_region_segment (cx1, cy1, cx2, cy2);
+      console_marked_region_active_p = 0;
+    }
+}
+
+static char *
+extract_marked_region (int cutp)
+{
+  if (console_marked_region_active_p)
+    {
+      unsigned short cx1;
+      unsigned short cy1;
+      unsigned short cx2;
+      unsigned short cy2;
+      unsigned short length;
+      unsigned short y;
+      char * result;
+      char * scan;
+
+      compute_marked_region (console_mark_x, console_mark_y,
+                            console_point_x, console_point_y,
+                            (&cx1), (&cy1), (&cx2), (&cy2));
+      length = 1;
+      for (y = cy1; (y <= cy2); y += 1)
+       {
+         unsigned short xl = ((y == cy1) ? cx1 : 0);
+         unsigned short xh = ((y == cy2) ? cx2 : console_width);
+         unsigned short lx = (console_line_lengths[y]);
+         if (y > cy1)
+           length += 2;
+         if (xl < lx)
+           length += (((xh < lx) ? xh : lx) - xl);
+       }
+      result = (OS_malloc (length));
+      scan = result;
+      for (y = cy1; (y <= cy2); y += 1)
+       {
+         unsigned short xl = ((y == cy1) ? cx1 : 0);
+         unsigned short xh = ((y == cy2) ? cx2 : console_width);
+         unsigned short lx = (console_line_lengths[y]);
+         if (y > cy1)
+           {
+             (*scan++) = '\r';
+             (*scan++) = '\n';
+           }
+         if (xl < lx)
+           {
+             unsigned short ll = (((xh < lx) ? xh : lx) - xl);
+             FASTCOPY ((CHAR_LOC (xl, y)), scan, ll);
+             scan += ll;
+           }
+       }
+      (*scan) = '\0';
+      if (cutp)
+       {
+         unsigned short x1
+           = ((cx1 < (console_line_lengths[cy1]))
+              ? cx1
+              : (console_line_lengths[cy1]));
+         {
+           unsigned short d
+             = ((cx2 < (console_line_lengths[cy2]))
+                ? ((console_line_lengths[cy2]) - cx2)
+                : 0);
+           FASTCOPY ((CHAR_LOC (cx2, cy2)), (CHAR_LOC (x1, cy1)), d);
+           FASTFILL ((CHAR_LOC ((x1 + d), cy1)),
+                     (console_width - (x1 + d)),
+                     ' ');
+           FASTCOPY ((CHAR_HL (cx2, cy2)), (CHAR_HL (x1, cy1)), d);
+           FASTFILL ((CHAR_HL ((x1 + d), cy1)),
+                     (console_width - (x1 + d)),
+                     '\0');
+           (console_line_lengths[cy1]) = (x1 + d);
+         }
+         if (cy1 < cy2)
+           {
+             unsigned short d = (console_height - (cy2 + 1));
+             FASTCOPY ((CHAR_LOC (0, (cy2 + 1))),
+                       (CHAR_LOC (0, (cy1 + 1))),
+                       (d * console_width));
+             FASTCOPY ((CHAR_HL (0, (cy2 + 1))),
+                       (CHAR_HL (0, (cy1 + 1))),
+                       (d * console_width));
+             FASTCOPY ((LINE_LEN_LOC (cy2 + 1)),
+                       (LINE_LEN_LOC (cy1 + 1)),
+                       (d * (sizeof (unsigned short))));
+           }
+         if ((cy1 < point_y) || ((cy1 == point_y) && (x1 < point_x)))
+           {
+             if ((cy2 > point_y) || ((cy2 == point_y) && (cx2 >= point_x)))
+               {
+                 point_x = x1;
+                 point_y = cy1;
+               }
+             else if (cy2 < point_y)
+               point_y -= (cy2 - cy1);
+             else
+               point_x -= (cx2 - ((cy1 == cy2) ? x1 : 0));
+             OS2_window_move_cursor (console_wid,
+                                     (cx2x (point_x)),
+                                     (cy2y (point_y, 1)));
+           }
+         console_paint (0, console_width, cy1, console_height);
+       }
+      return (result);
+    }
+  else
+    return (0);
+}
+
+static void
+compute_marked_region (short x1, short y1, short x2, short y2,
+                      unsigned short * cx1, unsigned short * cy1,
+                      unsigned short * cx2, unsigned short * cy2)
+{
+  /* (cx1,cy1) is inclusive, and (cx2,cy2) is exclusive.  */
+  unsigned short cx1a = (x2cx (x1, 1));
+  unsigned short cy1a = (y2cy (y1, 0));
+  unsigned short cx2a = (x2cx (x2, 1));
+  unsigned short cy2a = (y2cy (y2, 0));
+  if (((cy1a * console_width) + cx1a) < ((cy2a * console_width) + cx2a))
+    {
+      (*cx1) = cx1a;
+      (*cy1) = cy1a;
+      (*cx2) = cx2a;
+      (*cy2) = cy2a;
+    }
+  else
+    {
+      (*cx1) = cx2a;
+      (*cy1) = cy2a;
+      (*cx2) = cx1a;
+      (*cy2) = cy1a;
+    }
+}
+
+static void
+highlight_marked_region (unsigned short cx1, unsigned short cy1,
+                        unsigned short cx2, unsigned short cy2,
+                        char hl)
+{
+  char * start = (CHAR_HL (cx1, cy1));
+  FASTFILL (start, ((CHAR_HL (cx2, cy2)) - start), hl);
+}
+
+static void
+paint_marked_region_segment (unsigned short x1, unsigned short y1,
+                            unsigned short x2, unsigned short y2)
+{
+  if (y1 == y2)
+    console_paint (x1, x2, y1, (y1 + 1));
+  else
+    {
+      console_paint (x1, console_width, y1, (y1 + 1));
+      if ((y1 + 1) < y2)
+       console_paint (0, console_width, (y1 + 1), y2);
+      console_paint (0, x2, y2, (y2 + 1));
+    }
+}
+\f
+static void
 console_resize (unsigned short new_pel_width, unsigned short new_pel_height)
 {
   unsigned short new_width = (new_pel_width / CHAR_WIDTH);
   unsigned short new_height = (new_pel_height / CHAR_HEIGHT);
-  char * new_chars = (OS_malloc (new_width * new_height));
+  char * new_chars;
+  char * new_highlights;
+  unsigned short * new_line_lengths;
+
+  if ((console_chars != 0)
+      && (new_width == console_width)
+      && (new_height == console_height))
+    return;
+
+  new_chars = (OS_malloc (new_width * new_height));
+  new_highlights = (OS_malloc (new_width * new_height));
+  new_line_lengths = (OS_malloc ((sizeof (unsigned short)) * new_height));
+
   FASTFILL (new_chars, (new_width * new_height), ' ');
+  FASTFILL (new_highlights, (new_width * new_height), '\0');
+  FASTFILL (((char *) new_line_lengths),
+           ((sizeof (unsigned short)) * new_height),
+           0);
+
   if (console_chars != 0)
     {
       unsigned short xlim
        = ((new_width < console_width) ? new_width : console_width);
-      unsigned short y
+      unsigned short oy
        = (((point_y + 1) > new_height) ? ((point_y + 1) - new_height) : 0);
-      unsigned short ylim
-       = (y + ((new_height < console_height) ? new_height : console_height));
-      char * from = (CHAR_LOC (0, y));
-      char * to = new_chars;
-      while (y < ylim)
+      unsigned short oylim
+       = (oy + ((new_height < console_height) ? new_height : console_height));
+      char * cfrom = (CHAR_LOC (0, oy));
+      char * cto = new_chars;
+      char * hfrom = (CHAR_HL (0, oy));
+      char * hto = new_highlights;
+      unsigned short ny = 0;
+      while (oy < oylim)
        {
-         FASTCOPY (from, to, xlim);
-         from += console_width;
-         to += new_width;
-         y += 1;
+         FASTCOPY (cfrom, cto, xlim);
+         FASTCOPY (hfrom, hto, xlim);
+         (new_line_lengths[ny]) = (console_line_lengths[oy]);
+         cfrom += console_width;
+         cto += new_width;
+         hfrom += console_width;
+         hto += new_width;
+         oy += 1;
+         ny += 1;
        }
       OS_free (console_chars);
+      OS_free (console_highlights);
+      OS_free (console_line_lengths);
     }
   console_pel_width = new_pel_width;
   console_pel_height = new_pel_height;
   console_width = new_width;
   console_height = new_height;
   console_chars = new_chars;
+  console_highlights = new_highlights;
+  console_line_lengths = new_line_lengths;
   if (point_x >= new_width)
     point_x = (new_width - 1);
   if ((point_y + 1) >= new_height)
@@ -400,28 +742,63 @@ console_resize (unsigned short new_pel_width, unsigned short new_pel_height)
 }
 
 static void
-console_paint (unsigned short xl, unsigned short xh,
-              unsigned short yl, unsigned short yh)
+console_paint (unsigned short cxl, unsigned short cxh,
+              unsigned short cyl, unsigned short cyh)
 {
-  unsigned short cxl = (x2cx (xl, 1));
-  unsigned short cxh = (x2cx (xh, 0));
-  unsigned short cyl = (y2cy (yh, 0));
-  unsigned short cyh = (y2cy (yl, 1));
-  OS2_ps_clear (console_psid, xl, xh, yl, yh);
   if ((cxl < cxh) && (cyl < cyh))
     {
+      COLOR foreground = (OS2_ps_get_foreground_color (console_psid));
+      COLOR background = (OS2_ps_get_background_color (console_psid));
       unsigned short size = (cxh - cxl);
-      unsigned short x = (cx2x (cxl));
+      char current_hl = '\0';
       while (cyl < cyh)
        {
-         OS2_ps_draw_text (console_psid,
-                           x, ((cy2y (cyl, 1)) + CHAR_DESCENDER),
-                           (CHAR_LOC (cxl, cyl)), size);
+         unsigned short x = (cx2x (cxl));
+         unsigned short y = ((cy2y (cyl, 1)) + CHAR_DESCENDER);
+         char * cstart = (CHAR_LOC (cxl, cyl));
+         char * hstart = (CHAR_HL (cxl, cyl));
+         char * hend = (hstart + size);
+         while (hstart < hend)
+           {
+             unsigned short run_length = (compute_run_length (hstart, hend));
+             if (current_hl != (*hstart))
+               {
+                 if ((*hstart) == '\0')
+                   OS2_ps_set_colors (console_psid, foreground, background);
+                 else
+                   OS2_ps_set_colors (console_psid, background, foreground);
+                 current_hl = (*hstart);
+               }
+             OS2_ps_draw_text (console_psid, x, y, cstart, run_length);
+             x += (run_length * CHAR_WIDTH);
+             cstart += run_length;
+             hstart += run_length;
+           }
          cyl += 1;
        }
+      if (current_hl != '\0')
+       OS2_ps_set_colors (console_psid, foreground, background);
     }
 }
 
+static unsigned short
+compute_run_length (const char * start, const char * end)
+{
+  if (start < end)
+    {
+      const char * scan = start;
+      const char c = (*scan++);
+      while (scan < end)
+       if ((*scan) == c)
+         scan += 1;
+       else
+         break;
+      return (scan - start);
+    }
+  else
+    return (0);
+}
+
 static void
 console_clear (unsigned short xl, unsigned short xh,
               unsigned short yl, unsigned short yh)
@@ -449,24 +826,47 @@ OS2_pm_console_getch (void)
        {
          msg_list_t * element = pending_events_head;
          msg_t * message = (element -> message);
+         ULONG msg = (SM_PM_EVENT_MSG (message));
+         MPARAM mp1 = (SM_PM_EVENT_MP1 (message));
+         MPARAM mp2 = (SM_PM_EVENT_MP2 (message));
          pending_events_head = (element -> next);
+         OS2_destroy_message (message);
          OS_free (element);
-         switch (MSG_TYPE (message))
+         switch (msg)
            {
-           case mt_key_event:
+           case WM_CHAR:
              {
-               int translation = (translate_key_event (message));
-               unsigned short repeat = (SM_KEY_EVENT_REPEAT (message));
-               OS2_destroy_message (message);
-               if ((translation >= 0) && (repeat > 0))
+               unsigned short code;
+               unsigned char repeat;
+               if (translate_key_event (mp1, mp2, (&code), (&repeat)))
                  {
-                   readahead_char = translation;
-                   readahead_repeat = repeat;
-                   goto do_read;
+                   /* The feature that causes Delete and Backspace to
+                      delete the marked region is disabled because it
+                      is too much trouble to make the typeahead
+                      buffer conform to the displayed characters.  */
+#if 0
+                   /* Delete and Backspace must discard the marked
+                      region if there is one.  */
+                   if ((code == '\177') && (repeat > 0))
+                     {
+                       char * region = (extract_marked_region (1));
+                       if (region != 0)
+                         {
+                           OS_free (region);
+                           repeat -= 1;
+                         }
+                     }
+#endif
+                   if (repeat > 0)
+                     {
+                       readahead_char = code;
+                       readahead_repeat = repeat;
+                       goto do_read;
+                     }
                  }
-               break;
              }
-           case mt_close_event:
+             break;
+           case WM_CLOSE:
              switch
                (WinMessageBox
                 (HWND_DESKTOP,
@@ -487,27 +887,42 @@ OS2_pm_console_getch (void)
                    break;
                  case MBID_NO:
                    console_closedp = 1;
-                   {
-                     wid_t wid = (SM_CLOSE_EVENT_WID (message));
-                     OS2_destroy_message (message);
-                     OS2_window_close (wid);
-                   }
+                   OS2_window_close (console_wid);
                    OS2_close_qid (console_event_qid);
                    OS2_close_std_tqueue (console_tqueue);
                    goto do_read;
                  }
              break;
-           case mt_command_event:
-             switch (SM_COMMAND_EVENT_COMMAND (message))
-               {
-               case IDM_PASTE:
-                 if (do_paste ())
-                   goto do_read;
-                 break;
-               }
-             break;
-           default:
-             OS2_logic_error ("Unknown message type received by PM console.");
+           case WM_COMMAND:
+             {
+               ULONG msg = (SHORT1FROMMP (mp1));
+               switch (msg)
+                 {
+                 case IDM_PASTE:
+                   if (do_paste ())
+                     goto do_read;
+                   break;
+#if 0
+                 /* IDM_CUT is disabled because it is too much
+                    trouble to make the typeahead buffer conform to
+                    the displayed characters.  */
+                 case IDM_CUT:
+#endif
+                 case IDM_COPY:
+                   grab_console_lock ();
+                   {
+                     char * region = (extract_marked_region (msg == IDM_CUT));
+                     if (region != 0)
+                       {
+                         OS2_clipboard_write_text (console_pm_qid, region);
+                         OS_free (region);
+                         unmark_marked_region ();
+                       }
+                   }
+                   release_console_lock ();
+                   break;
+                 }
+             }
              break;
            }
        }
@@ -535,7 +950,7 @@ static int
 do_paste (void)
 {
   const char * text = (OS2_clipboard_read_text (console_pm_qid));
-  if ((*text) != '\0')
+  if ((text != 0) && ((*text) != '\0'))
     {
       readahead_insert = text;
       readahead_insert_scan = text;
@@ -549,42 +964,45 @@ do_paste (void)
 }
 \f
 static int
-translate_key_event (msg_t * message)
+translate_key_event (MPARAM mp1, MPARAM mp2,
+                    unsigned short * code, unsigned char * repeat)
 {
-  unsigned short code = (SM_KEY_EVENT_CODE (message));
-  unsigned short flags = (SM_KEY_EVENT_FLAGS (message));
+  unsigned short flags;
+  if (!OS2_translate_wm_char (mp1, mp2, code, (&flags), repeat))
+    return (0);
   if ((flags & KC_VIRTUALKEY) != 0)
-    switch (code)
+    switch (*code)
       {
       case VK_BACKSPACE:
-       code = '\177';
+      case VK_DELETE:
+       (*code) = '\177';
        break;
       case VK_TAB:
-       code = '\t';
+       (*code) = '\t';
        break;
       case VK_ESC:
-       code = '\033';
+       (*code) = '\033';
        break;
       case VK_SPACE:
-       code = ' ';
+       (*code) = ' ';
        break;
       case VK_NEWLINE:
       case VK_ENTER:
-       code = '\r';
+       (*code) = '\r';
        break;
       default:
-       return (-1);
+       return (0);
       }
-  if ((code >= 0200) || ((flags & KC_ALT) != 0))
-    return (-1);
+  if (((*code) >= 0200) || ((flags & KC_ALT) != 0))
+    return (0);
   if ((flags & KC_CTRL) != 0)
-    if (code >= 040)
-      code &= 037;
+    if ((*code) >= 040)
+      (*code) &= 037;
     else
-      return (-1);
-  if (code == 0)
-    return (-1);
-  return (code);
+      return (0);
+  if ((*code) == 0)
+    return (0);
+  return (1);
 }
 \f
 void
@@ -595,6 +1013,7 @@ OS2_pm_console_write (const char * data, size_t size)
   if (console_closedp)
     return;
   grab_console_lock ();
+  unmark_marked_region ();
   while (data < end)
     {
       nonprint = (find_nonprint (data, end));
@@ -605,6 +1024,7 @@ OS2_pm_console_write (const char * data, size_t size)
            if (size > (console_width - point_x))
              size = (console_width - point_x);
            FASTCOPY (data, (CHAR_LOC (point_x, point_y)), size);
+           FASTFILL ((CHAR_HL (point_x, point_y)), size, '\0');
            OS2_ps_draw_text (console_psid,
                              (cx2x (point_x)),
                              ((cy2y (point_y, 1)) + CHAR_DESCENDER),
@@ -612,6 +1032,7 @@ OS2_pm_console_write (const char * data, size_t size)
                              size);
            data += size;
            point_x += size;
+           (console_line_lengths[point_y]) = point_x;
            if (point_x == console_width)
              {
                do_carriage_return ();
@@ -663,30 +1084,32 @@ static void
 do_linefeed (void)
 {
   if (point_y < (console_height - 1))
-    {
-      point_y += 1;
-      FASTFILL ((CHAR_LOC (0, point_y)), console_width, ' ');
-      console_clear (0, console_width, point_y, (point_y + 1));
-    }
+    point_y += 1;
   else
     {
 #ifdef CONSOLE_WRAP
       point_y = 0;
-      FASTFILL ((CHAR_LOC (0, 0)), console_width, ' ');
-      console_clear (0, console_width, 0, 1);
 #else /* not CONSOLE_WRAP */
       point_y = (console_height - 1);
       FASTCOPY ((CHAR_LOC (0, 1)),
                (CHAR_LOC (0, 0)),
                (point_y * console_width));
-      FASTFILL ((CHAR_LOC (0, point_y)), console_width, ' ');
+      FASTCOPY ((CHAR_HL (0, 1)),
+               (CHAR_HL (0, 0)),
+               (point_y * console_width));
+      FASTCOPY ((LINE_LEN_LOC (1)),
+               (LINE_LEN_LOC (0)),
+               (point_y * (sizeof (unsigned short))));
       OS2_window_scroll (console_wid,
                         0, console_pel_width,
                         0, (point_y * CHAR_HEIGHT),
                         0, CHAR_HEIGHT);
-      OS2_ps_clear (console_psid, 0, console_pel_width, 0, CHAR_HEIGHT);
 #endif /* not CONSOLE_WRAP */
     }
+  FASTFILL ((CHAR_LOC (0, point_y)), console_width, ' ');
+  FASTFILL ((CHAR_HL (0, point_y)), console_width, '\0');
+  (console_line_lengths[point_y]) = 0;
+  console_clear (0, console_width, point_y, (point_y + 1));
 }
 
 static void
@@ -694,7 +1117,11 @@ do_formfeed (void)
 {
   point_x = 0;
   point_y = 0;
-  FASTFILL ((CHAR_LOC (0, 0)), (console_width * console_height), ' ');
+  FASTFILL ((CHAR_LOC (0, 0)), (console_height * console_width), ' ');
+  FASTFILL ((CHAR_HL (0, 0)), (console_height * console_width), '\0');
+  FASTFILL ((LINE_LEN_LOC (0)),
+           (console_height * (sizeof (unsigned short))),
+           0);
   console_clear_all ();
 }
 
@@ -704,11 +1131,12 @@ do_backspace (void)
   if (point_x > 0)
     {
       point_x -= 1;
+      (console_line_lengths[point_y]) = point_x;
     }
 }
 
 static void
 do_alert (void)
 {
-  DosBeep (880, 50);
+  WinAlarm (HWND_DESKTOP, WA_ERROR);
 }
index 53978d80c8eceae9518d982dcc9db31afe438333..1da75c6853ba82a3de148315c20e0815732a08ad 100644 (file)
@@ -1,6 +1,6 @@
 /* -*-C-*-
 
-$Id: os2pmcon.rc,v 1.1 1995/10/30 07:58:27 cph Exp $
+$Id: os2pmcon.rc,v 1.2 1995/11/03 01:30:07 cph Exp $
 
 Copyright (c) 1995 Massachusetts Institute of Technology
 
@@ -41,12 +41,12 @@ MENU ID_PMCON_RESOURCES
 {
   SUBMENU "~File", IDM_FILE
   {
-    MENUITEM "~Exit", IDM_EXIT
+    MENUITEM "E~xit", IDM_EXIT
   }
   SUBMENU "~Edit", IDM_EDIT
   {
     MENUITEM "Cu~t\tShift+Delete", IDM_CUT, 0, MIA_DISABLED
-    MENUITEM "~Copy\tCtrl+Insert", IDM_COPY, 0, MIA_DISABLED
+    MENUITEM "~Copy\tCtrl+Insert", IDM_COPY
     MENUITEM "~Paste\tShift+Insert", IDM_PASTE
   }
   SUBMENU "~Options", IDM_OPTIONS
@@ -55,7 +55,7 @@ MENU ID_PMCON_RESOURCES
   }
   SUBMENU "~Help", IDM_HELP
   {
-    MENUITEM "~Product information...", IDM_ABOUT
+    MENUITEM "~About...", IDM_ABOUT
   }
 }
 
index 9831db32a570e1d8d99ad8b4a9f2ee920797a509..fbf866fcd79db7aefabc0af872ed8d966db5e5e9 100644 (file)
@@ -1,6 +1,6 @@
 /* -*-C-*-
 
-$Id: pros2pm.c,v 1.10 1995/10/30 08:04:30 cph Exp $
+$Id: pros2pm.c,v 1.11 1995/11/03 01:30:21 cph Exp $
 
 Copyright (c) 1994-95 Massachusetts Institute of Technology
 
@@ -55,7 +55,7 @@ qid_argument (unsigned int arg_number)
 static psid_t
 psid_argument (unsigned int arg_number)
 {
-  unsigned long result = (arg_nonnegative_integer (arg_number));
+  unsigned long result = (arg_ulong_integer (arg_number));
   if (!OS2_psid_validp (result))
     error_bad_range_arg (arg_number);
   return (result);
@@ -73,7 +73,7 @@ memory_psid_argument (unsigned int arg_number)
 static wid_t
 wid_argument (unsigned int arg_number)
 {
-  unsigned long result = (arg_nonnegative_integer (arg_number));
+  unsigned long result = (arg_ulong_integer (arg_number));
   if (!OS2_wid_validp (result))
     error_bad_range_arg (arg_number);
   return (result);
@@ -82,7 +82,7 @@ wid_argument (unsigned int arg_number)
 static bid_t
 bid_argument (unsigned int arg_number)
 {
-  unsigned long result = (arg_nonnegative_integer (arg_number));
+  unsigned long result = (arg_ulong_integer (arg_number));
   if (!OS2_bid_validp (result))
     error_bad_range_arg (arg_number);
   return (result);
@@ -119,10 +119,17 @@ OS2_initialize_window_primitives (void)
   pm_qid = (OS2_create_pm_qid (OS2_scheme_tqueue));
 }
 
+DEFINE_PRIMITIVE ("OS2WIN-ALARM", Prim_OS2_window_alarm, 1, 1, 0)
+{
+  PRIMITIVE_HEADER (1);
+  PRIMITIVE_RETURN
+    (BOOLEAN_TO_OBJECT (WinAlarm (HWND_DESKTOP, (arg_ulong_integer (1)))));
+}
+
 DEFINE_PRIMITIVE ("OS2WIN-BEEP", Prim_OS2_window_beep, 2, 2, 0)
 {
   PRIMITIVE_HEADER (2);
-  DosBeep ((arg_nonnegative_integer (1)), (arg_nonnegative_integer (2)));
+  DosBeep ((arg_ulong_integer (1)), (arg_ulong_integer (2)));
   PRIMITIVE_RETURN (UNSPECIFIC);
 }
 
@@ -137,15 +144,15 @@ DEFINE_PRIMITIVE ("OS2WIN-OPEN", Prim_OS2_window_open, 2, 2, 0)
 {
   PRIMITIVE_HEADER (2);
   PRIMITIVE_RETURN
-    (long_to_integer (OS2_window_open (pm_qid,
-                                      (OS2_qid_twin (qid_argument (1))),
-                                      (FCF_TITLEBAR | FCF_SYSMENU
-                                       | FCF_SHELLPOSITION | FCF_SIZEBORDER
-                                       | FCF_MINMAX | FCF_TASKLIST),
-                                      NULLHANDLE,
-                                      1,
-                                      0,
-                                      (STRING_ARG (2)))));
+    (ulong_to_integer (OS2_window_open (pm_qid,
+                                       (OS2_qid_twin (qid_argument (1))),
+                                       (FCF_TITLEBAR | FCF_SYSMENU
+                                        | FCF_SHELLPOSITION | FCF_SIZEBORDER
+                                        | FCF_MINMAX | FCF_TASKLIST),
+                                       NULLHANDLE,
+                                       1,
+                                       0,
+                                       (STRING_ARG (2)))));
 }
 
 DEFINE_PRIMITIVE ("OS2WIN-CLOSE", Prim_OS2_window_close, 1, 1, 0)
@@ -177,7 +184,7 @@ DEFINE_PRIMITIVE ("OS2WIN-SHAPE-CURSOR", Prim_OS2_window_shape_cursor, 4, 4, 0)
   OS2_window_shape_cursor ((wid_argument (1)),
                           (DIMENSION_ARG (2)),
                           (DIMENSION_ARG (3)),
-                          (arg_nonnegative_integer (4)));
+                          (USHORT_ARG (4)));
   PRIMITIVE_RETURN (UNSPECIFIC);
 }
 
@@ -306,11 +313,25 @@ DEFINE_PRIMITIVE ("OS2WIN-SET-TITLE", Prim_OS2_window_set_title, 2, 2, 0)
   PRIMITIVE_RETURN (UNSPECIFIC);
 }
 
+DEFINE_PRIMITIVE ("OS2WIN-TRACK-MOUSE", Prim_OS2_window_track_mouse, 2, 2, 0)
+{
+  PRIMITIVE_HEADER (2);
+  OS2_window_mousetrack ((wid_argument (1)), (BOOLEAN_ARG (2)));
+  PRIMITIVE_RETURN (UNSPECIFIC);
+}
+
 DEFINE_PRIMITIVE ("OS2WIN-FRAME-HANDLE", Prim_OS2_window_frame_handle, 1, 1, 0)
 {
   PRIMITIVE_HEADER (1);
   PRIMITIVE_RETURN
-    (long_to_integer (OS2_window_frame_handle (wid_argument (1))));
+    (ulong_to_integer (OS2_window_frame_handle (wid_argument (1))));
+}
+
+DEFINE_PRIMITIVE ("OS2WIN-CLIENT-HANDLE", Prim_OS2_window_client_handle, 1, 1, 0)
+{
+  PRIMITIVE_HEADER (1);
+  PRIMITIVE_RETURN
+    (ulong_to_integer (OS2_window_client_handle (wid_argument (1))));
 }
 
 DEFINE_PRIMITIVE ("OS2WIN-UPDATE-FRAME", Prim_OS2_window_update_frame, 2, 2, 0)
@@ -319,17 +340,63 @@ DEFINE_PRIMITIVE ("OS2WIN-UPDATE-FRAME", Prim_OS2_window_update_frame, 2, 2, 0)
   OS2_window_update_frame ((wid_argument (1)), (USHORT_ARG (2)));
   PRIMITIVE_RETURN (UNSPECIFIC);
 }
+
+DEFINE_PRIMITIVE ("OS2-WINDOW-HANDLE-FROM-ID", Prim_OS2_window_handle_from_id, 2, 2, 0)
+{
+  PRIMITIVE_HEADER (2);
+  PRIMITIVE_RETURN
+    (ulong_to_integer (OS2_window_handle_from_id (pm_qid,
+                                                 (arg_ulong_integer (1)),
+                                                 (arg_ulong_integer (2)))));
+}
+
+DEFINE_PRIMITIVE ("OS2-MAP-WINDOW-POINT", Prim_OS2_map_window_point, 3, 3, 0)
+{
+  PRIMITIVE_HEADER (3);
+  {
+    SCHEME_OBJECT scheme_point;
+    POINTL point;
+    BOOL rc;
+
+    CHECK_ARG (3, PAIR_P);
+    scheme_point = (ARG_REF (3));
+    if ((!INTEGER_P (PAIR_CAR (scheme_point)))
+       || (!INTEGER_P (PAIR_CDR (scheme_point))))
+      error_wrong_type_arg (3);
+    if ((!integer_to_long_p (PAIR_CAR (scheme_point)))
+       || (!integer_to_long_p (PAIR_CDR (scheme_point))))
+      error_bad_range_arg (3);
+    (point . x) = (integer_to_long (PAIR_CAR (scheme_point)));
+    (point . y) = (integer_to_long (PAIR_CDR (scheme_point)));
+    rc = (WinMapWindowPoints ((HWND_ARG (1)), (HWND_ARG (2)), (&point), 1));
+    if (rc)
+      {
+       SET_PAIR_CAR (scheme_point, (long_to_integer (point . x)));
+       SET_PAIR_CDR (scheme_point, (long_to_integer (point . y)));
+      }
+    PRIMITIVE_RETURN (BOOLEAN_TO_OBJECT (rc));
+  }
+}
+
+DEFINE_PRIMITIVE ("OS2WIN-SET-CAPTURE", PRIM_OS2_WINDOW_SET_CAPTURE, 2, 2, 0)
+{
+  PRIMITIVE_HEADER (2);
+  PRIMITIVE_RETURN
+    (BOOLEAN_TO_OBJECT
+     (OS2_window_set_capture ((wid_argument (1)), (BOOLEAN_ARG (2)))));
+}
 \f
 DEFINE_PRIMITIVE ("OS2WIN-PS", Prim_OS2_window_ps, 1, 1, 0)
 {
   PRIMITIVE_HEADER (1);
-  PRIMITIVE_RETURN (long_to_integer (OS2_window_client_ps (wid_argument (1))));
+  PRIMITIVE_RETURN
+    (ulong_to_integer (OS2_window_client_ps (wid_argument (1))));
 }
 
 DEFINE_PRIMITIVE ("OS2PS-CREATE-MEMORY-PS", Prim_OS2_create_memory_ps, 0, 0, 0)
 {
   PRIMITIVE_HEADER (0);
-  PRIMITIVE_RETURN (long_to_integer (OS2_create_memory_ps (pm_qid)));
+  PRIMITIVE_RETURN (ulong_to_integer (OS2_create_memory_ps (pm_qid)));
 }
 
 DEFINE_PRIMITIVE ("OS2PS-DESTROY-MEMORY-PS", Prim_OS2_destroy_memory_ps, 1, 1, 0)
@@ -343,9 +410,9 @@ DEFINE_PRIMITIVE ("OS2PS-CREATE-BITMAP", Prim_OS2_create_bitmap, 3, 3, 0)
 {
   PRIMITIVE_HEADER (3);
   PRIMITIVE_RETURN
-    (long_to_integer (OS2_create_bitmap ((psid_argument (1)),
-                                        (USHORT_ARG (2)),
-                                        (USHORT_ARG (3)))));
+    (ulong_to_integer (OS2_create_bitmap ((psid_argument (1)),
+                                         (USHORT_ARG (2)),
+                                         (USHORT_ARG (3)))));
 }
 
 DEFINE_PRIMITIVE ("OS2PS-DESTROY-BITMAP", Prim_OS2_destroy_bitmap, 1, 1, 0)
@@ -360,7 +427,7 @@ DEFINE_PRIMITIVE ("OS2PS-GET-BITMAP", Prim_OS2_ps_get_bitmap, 1, 1, 0)
   PRIMITIVE_HEADER (1);
   {
     bid_t bid = (OS2_ps_get_bitmap ((memory_psid_argument (1))));
-    PRIMITIVE_RETURN ((bid == BID_NONE) ? SHARP_F : (long_to_integer (bid)));
+    PRIMITIVE_RETURN ((bid == BID_NONE) ? SHARP_F : (ulong_to_integer (bid)));
   }
 }
 
@@ -372,7 +439,7 @@ DEFINE_PRIMITIVE ("OS2PS-SET-BITMAP", Prim_OS2_ps_set_bitmap, 2, 2, 0)
       = (OS2_ps_set_bitmap
         ((memory_psid_argument (1)),
          (((ARG_REF (2)) == SHARP_F) ? BID_NONE : (bid_argument (2)))));
-    PRIMITIVE_RETURN ((bid == BID_NONE) ? SHARP_F : (long_to_integer (bid)));
+    PRIMITIVE_RETURN ((bid == BID_NONE) ? SHARP_F : (ulong_to_integer (bid)));
   }
 }
 
@@ -386,7 +453,7 @@ DEFINE_PRIMITIVE ("OS2PS-BITBLT", Prim_OS2_ps_bitblt, 6, 6, 0)
     unsigned long npoints;
     PPOINTL points = (coordinate_vector_point_args (3, 4, (& npoints)));
     LONG rop = (arg_index_integer (5, 0x100));
-    ULONG options = (arg_nonnegative_integer (6));
+    ULONG options = (arg_ulong_integer (6));
     if (! ((npoints == 3) || (npoints == 4)))
       error_bad_range_arg (3);
     OS2_ps_bitblt (target, source, npoints, points, rop, options);
@@ -401,8 +468,8 @@ DEFINE_PRIMITIVE ("OS2PS-WRITE", Prim_OS2_ps_write, 6, 6, 0)
   CHECK_ARG (4, STRING_P);
   {
     SCHEME_OBJECT string = (ARG_REF (4));
-    unsigned long start = (arg_nonnegative_integer (5));
-    unsigned long end = (arg_nonnegative_integer (6));
+    unsigned long start = (arg_ulong_integer (5));
+    unsigned long end = (arg_ulong_integer (6));
     if (end > (STRING_LENGTH (string)))
       error_bad_range_arg (6);
     if (start > end)
@@ -422,14 +489,14 @@ DEFINE_PRIMITIVE ("OS2PS-TEXT-WIDTH", Prim_OS2_ps_text_width, 4, 4, 0)
   CHECK_ARG (2, STRING_P);
   {
     SCHEME_OBJECT string = (ARG_REF (2));
-    unsigned long start = (arg_nonnegative_integer (3));
-    unsigned long end = (arg_nonnegative_integer (4));
+    unsigned long start = (arg_ulong_integer (3));
+    unsigned long end = (arg_ulong_integer (4));
     if (end > (STRING_LENGTH (string)))
       error_bad_range_arg (4);
     if (start > end)
       error_bad_range_arg (3);
     PRIMITIVE_RETURN
-      (long_to_integer
+      (ulong_to_integer
        (OS2_ps_text_width ((psid_argument (1)),
                           (STRING_LOC (string, start)),
                           (end - start))));
@@ -444,9 +511,9 @@ convert_font_metrics (font_metrics_t * m)
   else
     {
       SCHEME_OBJECT v = (allocate_marked_vector (TC_VECTOR, 3, 1));
-      VECTOR_SET (v, 0, (long_to_integer (FONT_METRICS_WIDTH (m))));
-      VECTOR_SET (v, 1, (long_to_integer (FONT_METRICS_HEIGHT (m))));
-      VECTOR_SET (v, 2, (long_to_integer (FONT_METRICS_DESCENDER (m))));
+      VECTOR_SET (v, 0, (ulong_to_integer (FONT_METRICS_WIDTH (m))));
+      VECTOR_SET (v, 1, (ulong_to_integer (FONT_METRICS_HEIGHT (m))));
+      VECTOR_SET (v, 2, (ulong_to_integer (FONT_METRICS_DESCENDER (m))));
       OS_free (m);
       return (v);
     }
@@ -666,10 +733,10 @@ DEFINE_PRIMITIVE ("OS2PS-GET-BITMAP-BITS", Prim_OS2_ps_get_bitmap_bits, 5, 5, 0)
 {
   PRIMITIVE_HEADER (5);
   PRIMITIVE_RETURN
-    (long_to_integer
+    (ulong_to_integer
      (OS2_ps_get_bitmap_bits ((memory_psid_argument (1)),
-                             (arg_nonnegative_integer (2)),
-                             (arg_nonnegative_integer (3)),
+                             (arg_ulong_integer (2)),
+                             (arg_ulong_integer (3)),
                              (STRING_ARG (4)),
                              ((void *) (STRING_ARG (5))))));
 }
@@ -678,10 +745,10 @@ DEFINE_PRIMITIVE ("OS2PS-SET-BITMAP-BITS", Prim_OS2_ps_set_bitmap_bits, 5, 5, 0)
 {
   PRIMITIVE_HEADER (5);
   PRIMITIVE_RETURN
-    (long_to_integer
+    (ulong_to_integer
      (OS2_ps_set_bitmap_bits ((memory_psid_argument (1)),
-                             (arg_nonnegative_integer (2)),
-                             (arg_nonnegative_integer (3)),
+                             (arg_ulong_integer (2)),
+                             (arg_ulong_integer (3)),
                              (STRING_ARG (4)),
                              ((void *) (STRING_ARG (5))))));
 }
@@ -814,15 +881,6 @@ DEFINE_PRIMITIVE ("OS2MENU-SET-ITEM-ATTRIBUTES", Prim_OS2_menu_set_item_attribut
   PRIMITIVE_RETURN (UNSPECIFIC);
 }
 
-DEFINE_PRIMITIVE ("OS2-WINDOW-HANDLE-FROM-ID", Prim_OS2_window_handle_from_id, 2, 2, 0)
-{
-  PRIMITIVE_HEADER (2);
-  PRIMITIVE_RETURN
-    (ulong_to_integer (OS2_window_handle_from_id (pm_qid,
-                                                 (arg_ulong_integer (1)),
-                                                 (arg_ulong_integer (2)))));
-}
-
 DEFINE_PRIMITIVE ("OS2WIN-LOAD-MENU", Prim_OS2_window_load_menu, 3, 3, 0)
 {
   PRIMITIVE_HEADER (3);
@@ -832,6 +890,21 @@ DEFINE_PRIMITIVE ("OS2WIN-LOAD-MENU", Prim_OS2_window_load_menu, 3, 3, 0)
                                             (arg_ulong_integer (3)))));
 }
 
+DEFINE_PRIMITIVE ("OS2WIN-POPUP-MENU", Prim_OS2_window_popup_menu, 7, 7, 0)
+{
+  PRIMITIVE_HEADER (7);
+  PRIMITIVE_RETURN
+    (BOOLEAN_TO_OBJECT
+     (OS2_window_popup_menu (pm_qid,
+                            (HWND_ARG (1)),
+                            (HWND_ARG (2)),
+                            (HWND_ARG (3)),
+                            (arg_integer (4)),
+                            (arg_integer (5)),
+                            (arg_integer (6)),
+                            (arg_ulong_integer (7)))));
+}
+
 DEFINE_PRIMITIVE ("OS2WIN-FONT-DIALOG", Prim_OS2_window_font_dialog, 2, 2, 0)
 {
   const char * spec;
@@ -849,6 +922,25 @@ DEFINE_PRIMITIVE ("OS2WIN-FONT-DIALOG", Prim_OS2_window_font_dialog, 2, 2, 0)
   PRIMITIVE_RETURN (result);
 }
 \f
+DEFINE_PRIMITIVE ("OS2-QUERY-SYSTEM-POINTER", Prim_OS2_query_system_pointer, 3, 3, 0)
+{
+  PRIMITIVE_HEADER (3);
+  PRIMITIVE_RETURN
+    (ulong_to_integer (OS2_query_system_pointer (pm_qid,
+                                                (HWND_ARG (1)),
+                                                (arg_integer (2)),
+                                                (BOOLEAN_ARG (3)))));
+}
+
+DEFINE_PRIMITIVE ("OS2-SET-POINTER", Prim_OS2_set_pointer, 2, 2, 0)
+{
+  PRIMITIVE_HEADER (2);
+  PRIMITIVE_RETURN
+    (BOOLEAN_TO_OBJECT (OS2_set_pointer (pm_qid,
+                                        (HWND_ARG (1)),
+                                        (arg_ulong_integer (2)))));
+}
+\f
 DEFINE_PRIMITIVE ("OS2WIN-OPEN-EVENT-QID", Prim_OS2_window_open_event_qid, 0, 0, 0)
 {
   qid_t local;
@@ -875,119 +967,190 @@ DEFINE_PRIMITIVE ("OS2WIN-CLOSE-EVENT-QID", Prim_OS2_window_close_event_qid, 1,
 #define ET_VISIBILITY  6
 #define ET_COMMAND     7
 #define ET_HELP                8
+#define ET_MOUSEMOVE   9
 
-#define CVT_UNSIGNED(n, v)                                             \
+#define CVT_USHORT(n, v)                                               \
   VECTOR_SET (result, n, (LONG_TO_UNSIGNED_FIXNUM (v)))
+#define CVT_SHORT(n, v)                                                        \
+  VECTOR_SET (result, n, (LONG_TO_FIXNUM (v)))
 #define CVT_BOOLEAN(n, v)                                              \
   VECTOR_SET (result, n, (BOOLEAN_TO_OBJECT (v)))
 
+static SCHEME_OBJECT make_button_event
+  (wid_t, MPARAM, MPARAM, unsigned short, unsigned short);
+
 DEFINE_PRIMITIVE ("OS2WIN-GET-EVENT", Prim_OS2_window_get_event, 2, 2, 0)
 {
+  qid_t qid;
+  int blockp;
   PRIMITIVE_HEADER (2);
+
+  qid = (qid_argument (1));
+  blockp = (BOOLEAN_ARG (2));
   Primitive_GC_If_Needed (8);
-  {
-    msg_t * message
-      = (OS2_receive_message ((qid_argument (1)), (BOOLEAN_ARG (2)), 1));
-    SCHEME_OBJECT result = SHARP_F;
-    if (message != 0)
-      {
-       switch (MSG_TYPE (message))
+  while (1)
+    {
+      msg_t * message = (OS2_receive_message (qid, blockp, 1));
+      SCHEME_OBJECT result = SHARP_F;
+      if (message == 0)
+       PRIMITIVE_RETURN (result);
+      switch (MSG_TYPE (message))
+       {
+       case mt_pm_event:
          {
-         case mt_button_event:
-           {
-             unsigned short type = (SM_BUTTON_EVENT_TYPE (message));
-             result = (allocate_marked_vector (TC_VECTOR, 7, 0));
-             CVT_UNSIGNED (0, ET_BUTTON);
-             CVT_UNSIGNED (1, (SM_BUTTON_EVENT_WID (message)));
-             CVT_UNSIGNED (2, (BUTTON_TYPE_NUMBER (type)));
-             CVT_UNSIGNED (3, (BUTTON_TYPE_EVENT (type)));
-             CVT_UNSIGNED (4, (SM_BUTTON_EVENT_X (message)));
-             CVT_UNSIGNED (5, (SM_BUTTON_EVENT_Y (message)));
-             CVT_UNSIGNED (6, (SM_BUTTON_EVENT_FLAGS (message)));
-             break;
-           }
-         case mt_close_event:
-           {
-             result = (allocate_marked_vector (TC_VECTOR, 2, 0));
-             CVT_UNSIGNED (0, ET_CLOSE);
-             CVT_UNSIGNED (1, (SM_CLOSE_EVENT_WID (message)));
-             break;
-           }
-         case mt_focus_event:
-           {
-             result = (allocate_marked_vector (TC_VECTOR, 3, 0));
-             CVT_UNSIGNED (0, ET_FOCUS);
-             CVT_UNSIGNED (1, (SM_FOCUS_EVENT_WID (message)));
-             CVT_BOOLEAN  (2, (SM_FOCUS_EVENT_GAINEDP (message)));
-             break;
-           }
-         case mt_key_event:
-           {
-             result = (allocate_marked_vector (TC_VECTOR, 5, 0));
-             CVT_UNSIGNED (0, ET_KEY);
-             CVT_UNSIGNED (1, (SM_KEY_EVENT_WID (message)));
-             CVT_UNSIGNED (2, (SM_KEY_EVENT_CODE (message)));
-             CVT_UNSIGNED (3, (SM_KEY_EVENT_FLAGS (message)));
-             CVT_UNSIGNED (4, (SM_KEY_EVENT_REPEAT (message)));
-             break;
-           }
-         case mt_paint_event:
-           {
-             result = (allocate_marked_vector (TC_VECTOR, 6, 0));
-             CVT_UNSIGNED (0, ET_PAINT);
-             CVT_UNSIGNED (1, (SM_PAINT_EVENT_WID (message)));
-             CVT_UNSIGNED (2, (SM_PAINT_EVENT_XL (message)));
-             CVT_UNSIGNED (3, (SM_PAINT_EVENT_XH (message)));
-             CVT_UNSIGNED (4, (SM_PAINT_EVENT_YL (message)));
-             CVT_UNSIGNED (5, (SM_PAINT_EVENT_YH (message)));
-             break;
-           }
-         case mt_resize_event:
-           {
-             result = (allocate_marked_vector (TC_VECTOR, 4, 0));
-             CVT_UNSIGNED (0, ET_RESIZE);
-             CVT_UNSIGNED (1, (SM_RESIZE_EVENT_WID (message)));
-             CVT_UNSIGNED (2, (SM_RESIZE_EVENT_WIDTH (message)));
-             CVT_UNSIGNED (3, (SM_RESIZE_EVENT_HEIGHT (message)));
-             break;
-           }
-         case mt_visibility_event:
-           {
-             result = (allocate_marked_vector (TC_VECTOR, 3, 0));
-             CVT_UNSIGNED (0, ET_VISIBILITY);
-             CVT_UNSIGNED (1, (SM_VISIBILITY_EVENT_WID (message)));
-             CVT_BOOLEAN  (2, (SM_VISIBILITY_EVENT_SHOWNP (message)));
-             break;
-           }
-         case mt_command_event:
-           {
-             result = (allocate_marked_vector (TC_VECTOR, 5, 0));
-             CVT_UNSIGNED (0, ET_COMMAND);
-             CVT_UNSIGNED (1, (SM_COMMAND_EVENT_WID (message)));
-             CVT_UNSIGNED (2, (SM_COMMAND_EVENT_COMMAND (message)));
-             CVT_UNSIGNED (3, (SM_COMMAND_EVENT_SOURCE (message)));
-             CVT_BOOLEAN  (4, (SM_COMMAND_EVENT_MOUSEP (message)));
-             break;
-           }
-         case mt_help_event:
-           {
-             result = (allocate_marked_vector (TC_VECTOR, 5, 0));
-             CVT_UNSIGNED (0, ET_HELP);
-             CVT_UNSIGNED (1, (SM_HELP_EVENT_WID (message)));
-             CVT_UNSIGNED (2, (SM_HELP_EVENT_COMMAND (message)));
-             CVT_UNSIGNED (3, (SM_HELP_EVENT_SOURCE (message)));
-             CVT_BOOLEAN  (4, (SM_HELP_EVENT_MOUSEP (message)));
-             break;
-           }
-         default:
+           wid_t wid = (SM_PM_EVENT_WID (message));
+           ULONG msg = (SM_PM_EVENT_MSG (message));
+           MPARAM mp1 = (SM_PM_EVENT_MP1 (message));
+           MPARAM mp2 = (SM_PM_EVENT_MP2 (message));
            OS2_destroy_message (message);
-           OS2_error_anonymous ();
+           switch (msg)
+             {
+             case WM_SETFOCUS:
+               {
+                 result = (allocate_marked_vector (TC_VECTOR, 3, 0));
+                 CVT_USHORT (0, ET_FOCUS);
+                 CVT_USHORT (1, wid);
+                 CVT_BOOLEAN (2, (SHORT1FROMMP (mp2)));
+                 break;
+               }
+             case WM_SIZE:
+               {
+                 result = (allocate_marked_vector (TC_VECTOR, 4, 0));
+                 CVT_USHORT (0, ET_RESIZE);
+                 CVT_USHORT (1, wid);
+                 CVT_USHORT (2, (SHORT1FROMMP (mp2)));
+                 CVT_USHORT (3, (SHORT2FROMMP (mp2)));
+                 break;
+               }
+             case WM_CLOSE:
+               {
+                 result = (allocate_marked_vector (TC_VECTOR, 2, 0));
+                 CVT_USHORT (0, ET_CLOSE);
+                 CVT_USHORT (1, wid);
+                 break;
+               }
+             case WM_COMMAND:
+             case WM_HELP:
+               {
+                 result = (allocate_marked_vector (TC_VECTOR, 5, 0));
+                 CVT_USHORT (0,
+                               ((msg == WM_HELP) ? ET_HELP : ET_COMMAND));
+                 CVT_USHORT (1, wid);
+                 CVT_USHORT (2, (SHORT1FROMMP (mp1)));
+                 CVT_USHORT (3, (SHORT1FROMMP (mp2)));
+                 CVT_BOOLEAN (4, (SHORT2FROMMP (mp2)));
+                 break;
+               }
+             case WM_SHOW:
+               {
+                 result = (allocate_marked_vector (TC_VECTOR, 3, 0));
+                 CVT_USHORT (0, ET_VISIBILITY);
+                 CVT_USHORT (1, wid);
+                 CVT_BOOLEAN (2, (SHORT1FROMMP (mp1)));
+                 break;
+               }
+             case WM_CHAR:
+               {
+                 unsigned short code;
+                 unsigned short flags;
+                 unsigned char repeat;
+                 if (OS2_translate_wm_char (mp1, mp2,
+                                            (&code), (&flags), (&repeat)))
+                   {
+                     result = (allocate_marked_vector (TC_VECTOR, 5, 0));
+                     CVT_USHORT (0, ET_KEY);
+                     CVT_USHORT (1, wid);
+                     CVT_USHORT (2, code);
+                     CVT_USHORT (3, flags);
+                     CVT_USHORT (4, repeat);
+                   }
+                 break;
+               }
+             case WM_BUTTON1DOWN:
+               result = (make_button_event (wid, mp1, mp2, 0, 0));
+               break;
+             case WM_BUTTON1UP:
+               result = (make_button_event (wid, mp1, mp2, 0, 1));
+               break;
+             case WM_BUTTON1CLICK:
+               result = (make_button_event (wid, mp1, mp2, 0, 2));
+               break;
+             case WM_BUTTON1DBLCLK:
+               result = (make_button_event (wid, mp1, mp2, 0, 3));
+               break;
+             case WM_BUTTON2DOWN:
+               result = (make_button_event (wid, mp1, mp2, 1, 0));
+               break;
+             case WM_BUTTON2UP:
+               result = (make_button_event (wid, mp1, mp2, 1, 1));
+               break;
+             case WM_BUTTON2CLICK:
+               result = (make_button_event (wid, mp1, mp2, 1, 2));
+               break;
+             case WM_BUTTON2DBLCLK:
+               result = (make_button_event (wid, mp1, mp2, 1, 3));
+               break;
+             case WM_BUTTON3DOWN:
+               result = (make_button_event (wid, mp1, mp2, 2, 0));
+               break;
+             case WM_BUTTON3UP:
+               result = (make_button_event (wid, mp1, mp2, 2, 1));
+               break;
+             case WM_BUTTON3CLICK:
+               result = (make_button_event (wid, mp1, mp2, 2, 2));
+               break;
+             case WM_BUTTON3DBLCLK:
+               result = (make_button_event (wid, mp1, mp2, 2, 3));
+               break;
+             case WM_MOUSEMOVE:
+               result = (allocate_marked_vector (TC_VECTOR, 6, 0));
+               CVT_USHORT (0, ET_MOUSEMOVE);
+               CVT_USHORT (1, wid);
+               CVT_SHORT (2, (SHORT1FROMMP (mp1)));
+               CVT_SHORT (3, (SHORT2FROMMP (mp1)));
+               CVT_USHORT (4, (SHORT1FROMMP (mp2)));
+               CVT_USHORT (5, (SHORT2FROMMP (mp2)));
+               break;
+             default:
+               break;
+             }
            break;
          }
-       OS2_destroy_message (message);
-      }
-    PRIMITIVE_RETURN (result);
-  }
+       case mt_paint_event:
+         {
+           result = (allocate_marked_vector (TC_VECTOR, 6, 0));
+           CVT_USHORT (0, ET_PAINT);
+           CVT_USHORT (1, (SM_PAINT_EVENT_WID (message)));
+           CVT_USHORT (2, (SM_PAINT_EVENT_XL (message)));
+           CVT_USHORT (3, (SM_PAINT_EVENT_XH (message)));
+           CVT_USHORT (4, (SM_PAINT_EVENT_YL (message)));
+           CVT_USHORT (5, (SM_PAINT_EVENT_YH (message)));
+           OS2_destroy_message (message);
+           break;
+         }
+       default:
+         OS2_destroy_message (message);
+         OS2_error_anonymous ();
+         break;
+       }
+      if (result != SHARP_F)
+       PRIMITIVE_RETURN (result);
+    }
+}
+
+static SCHEME_OBJECT
+make_button_event (wid_t wid, MPARAM mp1, MPARAM mp2,
+                  unsigned short number, unsigned short type)
+{
+  SCHEME_OBJECT result = (allocate_marked_vector (TC_VECTOR, 7, 0));
+  CVT_USHORT (0, ET_BUTTON);
+  CVT_USHORT (1, wid);
+  CVT_USHORT (2, number);
+  CVT_USHORT (3, type);
+  CVT_SHORT (4, (SHORT1FROMMP (mp1)));
+  CVT_SHORT (5, (SHORT2FROMMP (mp1)));
+  CVT_USHORT (6, ((SHORT2FROMMP (mp2)) & (KC_SHIFT | KC_CTRL | KC_ALT)));
+  return (result);
 }
 
 DEFINE_PRIMITIVE ("OS2WIN-EVENT-READY?", Prim_OS2_window_event_ready, 2, 2, 0)
@@ -1008,7 +1171,7 @@ DEFINE_PRIMITIVE ("OS2WIN-CONSOLE-WID", Prim_OS2_window_console_wid, 0, 0, 0)
 {
   extern wid_t OS2_console_wid (void);
   PRIMITIVE_HEADER (0);
-  PRIMITIVE_RETURN (long_to_integer (OS2_console_wid ()));
+  PRIMITIVE_RETURN (ulong_to_integer (OS2_console_wid ()));
 }
 
 DEFINE_PRIMITIVE ("OS2WIN-DESKTOP-WIDTH", Prim_OS2_window_desktop_width, 0, 0, 0)