~ubuntu-branches/ubuntu/intrepid/mit-scheme/intrepid-updates

« back to all changes in this revision

Viewing changes to src/microcode/os2pm.c

  • Committer: Bazaar Package Importer
  • Author(s): Chris Hanson
  • Date: 2002-03-14 17:04:07 UTC
  • Revision ID: james.westby@ubuntu.com-20020314170407-m5lg1d6bdsl9lv0s
Tags: upstream-7.7.0
ImportĀ upstreamĀ versionĀ 7.7.0

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*-C-*-
 
2
 
 
3
$Id: os2pm.c,v 1.33 2000/12/05 21:23:46 cph Exp $
 
4
 
 
5
Copyright (c) 1994-2000 Massachusetts Institute of Technology
 
6
 
 
7
This program is free software; you can redistribute it and/or modify
 
8
it under the terms of the GNU General Public License as published by
 
9
the Free Software Foundation; either version 2 of the License, or (at
 
10
your option) any later version.
 
11
 
 
12
This program is distributed in the hope that it will be useful, but
 
13
WITHOUT ANY WARRANTY; without even the implied warranty of
 
14
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
15
General Public License for more details.
 
16
 
 
17
You should have received a copy of the GNU General Public License
 
18
along with this program; if not, write to the Free Software
 
19
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 
20
*/
 
21
 
 
22
#define INCL_WIN
 
23
#define INCL_GPI
 
24
#include "os2.h"
 
25
 
 
26
extern void add_reload_cleanup (void (*) (void));
 
27
extern psid_t OS2_console_psid (void);
 
28
extern void OS2_console_font_change_hook (font_metrics_t *);
 
29
 
 
30
typedef enum { pst_window, pst_memory } pst_t;
 
31
 
 
32
typedef struct _ps_t
 
33
{
 
34
  psid_t id;                    /* psid for this ps */
 
35
  qid_t qid;                    /* qid to send commands to */
 
36
  HPS handle;
 
37
  COLOR foreground_color;
 
38
  COLOR background_color;
 
39
  pst_t visual_type;            /* window or bitmap */
 
40
  void * visual;                /* the associated window or bitmap */
 
41
  PLONG char_increments;        /* character increments for outline fonts */
 
42
} ps_t;
 
43
#define PS_ID(ps) ((ps) -> id)
 
44
#define PS_QID(ps) ((ps) -> qid)
 
45
#define PS_HANDLE(ps) ((ps) -> handle)
 
46
#define PS_FOREGROUND_COLOR(ps) ((ps) -> foreground_color)
 
47
#define PS_BACKGROUND_COLOR(ps) ((ps) -> background_color)
 
48
#define PS_VISUAL_TYPE(ps) ((ps) -> visual_type)
 
49
#define PS_VISUAL(ps) ((ps) -> visual)
 
50
#define PS_CHAR_INCREMENTS(ps) ((ps) -> char_increments)
 
51
 
 
52
typedef struct _window_t
 
53
{
 
54
  HWND frame;                   /* frame window handle */
 
55
  HWND client;                  /* client window handle */
 
56
  ps_t * client_ps;             /* presentation space for client window */
 
57
  unsigned short grid_x;        /* x dimension of resizing grid */
 
58
  unsigned short grid_y;        /* y dimension of resizing grid */
 
59
  short cursor_x;               /* x coordinate of the cursor */
 
60
  short cursor_y;               /* y coordinate of the cursor */
 
61
  unsigned short cursor_width;  /* width of the cursor */
 
62
  unsigned short cursor_height; /* height of the cursor */
 
63
  unsigned short cursor_style;  /* style of the cursor */
 
64
  qid_t qid;                    /* qid to send commands to */
 
65
  qid_t event_qid;              /* qid to send input events to */
 
66
  wid_t id;                     /* wid for this window */
 
67
  unsigned int cursor_createdp : 1; /* nonzero if cursor created */
 
68
  unsigned int cursor_enabledp : 1; /* nonzero if cursor enabled */
 
69
  unsigned int minimizingp : 1; /* nonzero if window being minimized */
 
70
  unsigned int minimizedp : 1;  /* nonzero if window is minimized */
 
71
  unsigned int permanentp : 1;  /* nonzero means don't close on reload */
 
72
  unsigned int mousetrackp : 1; /* nonzero means generate WM_MOUSEMOVE msgs */
 
73
} window_t;
 
74
#define WINDOW_FRAME(window) ((window) -> frame)
 
75
#define WINDOW_CLIENT(window) ((window) -> client)
 
76
#define WINDOW_CLIENT_PS(window) ((window) -> client_ps)
 
77
#define WINDOW_GRID_X(window) ((window) -> grid_x)
 
78
#define WINDOW_GRID_Y(window) ((window) -> grid_y)
 
79
#define WINDOW_CURSOR_X(window) ((window) -> cursor_x)
 
80
#define WINDOW_CURSOR_Y(window) ((window) -> cursor_y)
 
81
#define WINDOW_CURSOR_WIDTH(window) ((window) -> cursor_width)
 
82
#define WINDOW_CURSOR_HEIGHT(window) ((window) -> cursor_height)
 
83
#define WINDOW_CURSOR_STYLE(window) ((window) -> cursor_style)
 
84
#define WINDOW_QID(window) ((window) -> qid)
 
85
#define WINDOW_EVENT_QID(window) ((window) -> event_qid)
 
86
#define WINDOW_ID(window) ((window) -> id)
 
87
#define WINDOW_CURSOR_CREATEDP(window) ((window) -> cursor_createdp)
 
88
#define WINDOW_CURSOR_ENABLEDP(window) ((window) -> cursor_enabledp)
 
89
#define WINDOW_MINIMIZINGP(window) ((window) -> minimizingp)
 
90
#define WINDOW_MINIMIZEDP(window) ((window) -> minimizedp)
 
91
#define WINDOW_PERMANENTP(window) ((window) -> permanentp)
 
92
#define WINDOW_MOUSETRACKP(window) ((window) -> mousetrackp)
 
93
 
 
94
typedef struct _bitmap_t
 
95
{
 
96
  bid_t id;                     /* bid for this bitmap */
 
97
  qid_t qid;                    /* qid to send commands to */
 
98
  HBITMAP handle;
 
99
} bitmap_t;
 
100
#define BITMAP_ID(bitmap) ((bitmap) -> id)
 
101
#define BITMAP_QID(bitmap) ((bitmap) -> qid)
 
102
#define BITMAP_HANDLE(bitmap) ((bitmap) -> handle)
 
103
 
 
104
typedef struct
 
105
{
 
106
  tqueue_type_t type;
 
107
  HWND hwnd;
 
108
} pm_tqueue_t;
 
109
#define PM_TQUEUE_HWND(q) (((pm_tqueue_t *) (q)) -> hwnd)
 
110
 
 
111
typedef struct
 
112
{
 
113
  unsigned int length;
 
114
  void ** pointers;
 
115
} id_table_t;
 
116
#define ID_TABLE_LENGTH(table) ((table) -> length)
 
117
#define ID_TABLE_POINTERS(table) ((table) -> pointers)
 
118
 
 
119
/* This machine-generated file contains forward references and
 
120
   structure definitions for most of the procedures.  */
 
121
#include "os2pm-id.h"
 
122
 
 
123
static void window_pos (window_t *, short *, short *);
 
124
static void handle_window_pos_request (msg_t *);
 
125
 
 
126
typedef struct
 
127
{
 
128
  DECLARE_MSG_HEADER_FIELDS;
 
129
  window_t * window;
 
130
} sm_pos_request_t;
 
131
#define SM_POS_REQUEST_WINDOW(m) (((sm_pos_request_t *) (m)) -> window)
 
132
 
 
133
typedef struct
 
134
{
 
135
  DECLARE_MSG_HEADER_FIELDS;
 
136
  short x;
 
137
  short y;
 
138
} sm_pos_reply_t;
 
139
#define SM_POS_REPLY_X(m) (((sm_pos_reply_t *) (m)) -> x)
 
140
#define SM_POS_REPLY_Y(m) (((sm_pos_reply_t *) (m)) -> y)
 
141
 
 
142
static void window_size (window_t *, unsigned short *, unsigned short *);
 
143
static void handle_window_size_request (msg_t *);
 
144
 
 
145
typedef struct
 
146
{
 
147
  DECLARE_MSG_HEADER_FIELDS;
 
148
  window_t * window;
 
149
} sm_size_request_t;
 
150
#define SM_SIZE_REQUEST_WINDOW(m) (((sm_size_request_t *) (m)) -> window)
 
151
 
 
152
typedef struct
 
153
{
 
154
  DECLARE_MSG_HEADER_FIELDS;
 
155
  unsigned short width;
 
156
  unsigned short height;
 
157
} sm_size_reply_t;
 
158
#define SM_SIZE_REPLY_WIDTH(m) (((sm_size_reply_t *) (m)) -> width)
 
159
#define SM_SIZE_REPLY_HEIGHT(m) (((sm_size_reply_t *) (m)) -> height)
 
160
 
 
161
static void window_frame_size
 
162
  (window_t *, unsigned short *, unsigned short *);
 
163
static void handle_window_frame_size_request (msg_t *);
 
164
 
 
165
typedef struct
 
166
{
 
167
  DECLARE_MSG_HEADER_FIELDS;
 
168
  window_t * window;
 
169
} sm_frame_size_request_t;
 
170
#define SM_FRAME_SIZE_REQUEST_WINDOW(m)                                 \
 
171
  (((sm_frame_size_request_t *) (m)) -> window)
 
172
 
 
173
typedef struct
 
174
{
 
175
  DECLARE_MSG_HEADER_FIELDS;
 
176
  unsigned short width;
 
177
  unsigned short height;
 
178
} sm_frame_size_reply_t;
 
179
#define SM_FRAME_SIZE_REPLY_WIDTH(m)                                    \
 
180
  (((sm_frame_size_reply_t *) (m)) -> width)
 
181
#define SM_FRAME_SIZE_REPLY_HEIGHT(m)                                   \
 
182
  (((sm_frame_size_reply_t *) (m)) -> height)
 
183
 
 
184
static void handle_ps_set_bitmap_request (msg_t *);
 
185
static bitmap_t * ps_set_bitmap (ps_t *, bitmap_t *);
 
186
 
 
187
typedef struct
 
188
{
 
189
  DECLARE_MSG_HEADER_FIELDS;
 
190
  ps_t * ps;
 
191
  bitmap_t * bitmap;
 
192
} sm_ps_set_bitmap_request_t;
 
193
#define SM_PS_SET_BITMAP_REQUEST_PS(m)                                  \
 
194
  (((sm_ps_set_bitmap_request_t *) (m)) -> ps)
 
195
#define SM_PS_SET_BITMAP_REQUEST_BITMAP(m)                              \
 
196
  (((sm_ps_set_bitmap_request_t *) (m)) -> bitmap)
 
197
 
 
198
typedef struct
 
199
{
 
200
  DECLARE_MSG_HEADER_FIELDS;
 
201
  bitmap_t * bitmap;
 
202
} sm_ps_set_bitmap_reply_t;
 
203
#define SM_PS_SET_BITMAP_REPLY_BITMAP(m)                                \
 
204
  (((sm_ps_set_bitmap_reply_t *) (m)) -> bitmap)
 
205
 
 
206
static void close_all_windows (void);
 
207
 
 
208
static void sync_transaction (qid_t, msg_t *);
 
209
static void sync_reply (qid_t);
 
210
 
 
211
static void pm_thread_procedure (void *);
 
212
static tqueue_t * make_pm_tqueue (HWND);
 
213
 
 
214
static void initialize_id_table (id_table_t *);
 
215
static unsigned int allocate_id (id_table_t *, void *);
 
216
static void deallocate_id (id_table_t *, unsigned int);
 
217
static void * id_to_pointer (id_table_t *, unsigned int);
 
218
static int id_validp (id_table_t *, unsigned int);
 
219
static ps_t * psid_to_ps (psid_t);
 
220
static window_t * wid_to_window (wid_t);
 
221
static bitmap_t * bid_to_bitmap (bid_t);
 
222
 
 
223
static MRESULT EXPENTRY object_window_procedure (HWND, ULONG, MPARAM, MPARAM);
 
224
static MRESULT EXPENTRY frame_window_procedure (HWND, ULONG, MPARAM, MPARAM);
 
225
static MRESULT EXPENTRY window_procedure (HWND, ULONG, MPARAM, MPARAM);
 
226
 
 
227
static window_t * hwnd_to_window (HWND);
 
228
static msg_t * make_pm_event (wid_t, ULONG, MPARAM, MPARAM);
 
229
static msg_t * make_paint_event
 
230
  (wid_t, unsigned short, unsigned short, unsigned short, unsigned short);
 
231
 
 
232
static void recreate_cursor (window_t *);
 
233
static void activate_cursor (window_t *);
 
234
static void deactivate_cursor (window_t *);
 
235
 
 
236
static window_t * make_window (qid_t, qid_t);
 
237
 
 
238
static void win_create_cursor (HWND, LONG, LONG, LONG, LONG, ULONG, PRECTL);
 
239
static void win_destroy_cursor (HWND);
 
240
static void win_show_cursor (HWND, BOOL);
 
241
static void recreate_cursor (window_t *);
 
242
static void activate_cursor (window_t *);
 
243
static void deactivate_cursor (window_t *);
 
244
static void maybe_activate_cursor (ps_t *);
 
245
static void maybe_deactivate_cursor (ps_t *);
 
246
 
 
247
static HDC get_ps_device (HPS);
 
248
static LONG get_device_capability (HDC, LONG);
 
249
static ps_t * create_ps (pst_t, HDC, qid_t);
 
250
static void destroy_ps (ps_t *);
 
251
 
 
252
static int ps_set_font (ps_t *, unsigned short, const char *);
 
253
static int parse_font_spec (const char *, PSZ *, LONG *, USHORT *);
 
254
static const char * unparse_font_spec (PSZ, LONG, USHORT);
 
255
static int ps_set_font_1 (ps_t * ps, PSZ, LONG, USHORT, LONG);
 
256
static PLONG ps_make_char_increments (LONG);
 
257
static int create_font (HPS, LONG, PFONTMETRICS, USHORT);
 
258
static void copy_fontmetrics_to_fattrs (FONTMETRICS *, FATTRS *);
 
259
static void ps_set_font_size (ps_t *, LONG);
 
260
 
 
261
#define ID_FRAME 1
 
262
 
 
263
#define UWM_ENCAPSULATION WM_USER
 
264
 
 
265
#define QWP_WINDOW QWL_USER
 
266
 
 
267
/* These should have been defined by PM header file.  */
 
268
#define MRVOID MRFROMP (0)
 
269
#define MRTRUE MRFROMLONG (TRUE)
 
270
#define MRFALSE MRFROMLONG (FALSE)
 
271
 
 
272
static id_table_t psid_table;
 
273
static id_table_t wid_table;
 
274
static id_table_t bid_table;
 
275
static qid_t pm_init_qid;
 
276
TID OS2_pm_tid;
 
277
static HAB pm_hab;
 
278
static HMQ pm_hmq;
 
279
static HWND pm_object_window;
 
280
static tqueue_t * pm_tqueue;
 
281
static PFNWP original_frame_window_procedure;
 
282
static window_t * capture_window;
 
283
 
 
284
static const char object_class [] = "mit-scheme.object";
 
285
static const char window_class [] = "mit-scheme.window";
 
286
 
 
287
#define SEND_EVENT(window, message)                                     \
 
288
{                                                                       \
 
289
  if ((WINDOW_EVENT_QID (window)) != QID_NONE)                          \
 
290
    OS2_send_message ((WINDOW_EVENT_QID (window)), (message));          \
 
291
}
 
292
 
 
293
#define SEND_PM_EVENT(hwnd, msg, mp1, mp2)                              \
 
294
{                                                                       \
 
295
  window_t * window = (hwnd_to_window (hwnd));                          \
 
296
  SEND_EVENT (window,                                                   \
 
297
              (make_pm_event ((WINDOW_ID (window)), msg, mp1, mp2)));   \
 
298
}
 
299
 
 
300
#define window_error(name) window_error_1 (#name, 1)
 
301
#define window_warning(name) window_error_1 (#name, 0)
 
302
 
 
303
static void
 
304
window_error_1 (const char * name, int fatalp)
 
305
{
 
306
  char buffer [1024];
 
307
  ERRORID code = (WinGetLastError (pm_hab));
 
308
  if (fatalp)
 
309
    {
 
310
      sprintf (buffer, "Fatal error 0x%08x occurred in the %s procedure.",
 
311
               code, name);
 
312
      OS2_logic_error (buffer);
 
313
    }
 
314
  else
 
315
    {
 
316
      sprintf (buffer, "Non-fatal error 0x%08x occurred in the %s procedure.  \
 
317
This indicates a bug in the Scheme implementation.  \
 
318
Please report this information to a Scheme wizard.",
 
319
               code, name);
 
320
      (void) WinMessageBox (HWND_DESKTOP,
 
321
                            NULLHANDLE,
 
322
                            buffer,
 
323
                            "Scheme Error",
 
324
                            0,
 
325
                            (MB_OK | MB_WARNING));
 
326
    }
 
327
}
 
328
 
 
329
void
 
330
OS2_initialize_pm_thread (void)
 
331
{
 
332
  /* This machine-generated file contains code to initialize the
 
333
     message-type sizes for most of the procedure messages.  */
 
334
#include "os2pm-mi.h"
 
335
 
 
336
  SET_MSG_TYPE_LENGTH (mt_window_pos_request, sm_pos_request_t);
 
337
  SET_MSG_TYPE_LENGTH (mt_window_pos_reply, sm_pos_reply_t);
 
338
  SET_MSG_TYPE_LENGTH (mt_window_size_request, sm_size_request_t);
 
339
  SET_MSG_TYPE_LENGTH (mt_window_size_reply, sm_size_reply_t);
 
340
  SET_MSG_TYPE_LENGTH (mt_window_frame_size_request, sm_frame_size_request_t);
 
341
  SET_MSG_TYPE_LENGTH (mt_window_frame_size_reply, sm_frame_size_reply_t);
 
342
 
 
343
  SET_MSG_TYPE_LENGTH (mt_ps_set_bitmap_request, sm_ps_set_bitmap_request_t);
 
344
  SET_MSG_TYPE_LENGTH (mt_ps_set_bitmap_reply, sm_ps_set_bitmap_reply_t);
 
345
 
 
346
  SET_MSG_TYPE_LENGTH (mt_pm_event, sm_pm_event_t);
 
347
  SET_MSG_TYPE_LENGTH (mt_paint_event, sm_paint_event_t);
 
348
 
 
349
  initialize_id_table (& psid_table);
 
350
  initialize_id_table (& wid_table);
 
351
  initialize_id_table (& bid_table);
 
352
  original_frame_window_procedure = 0;
 
353
  capture_window = 0;
 
354
  {
 
355
    qid_t qid;
 
356
    OS2_make_qid_pair ((&pm_init_qid), (&qid));
 
357
    OS2_open_qid (qid, OS2_scheme_tqueue);
 
358
    OS2_pm_tid = (OS2_beginthread (pm_thread_procedure, 0, 0x8000));
 
359
    /* Wait for init message from PM thread.  This message tells us
 
360
       that the other end of the connection is established and that it
 
361
       is safe to send messages on the connection.  */
 
362
    OS2_destroy_message (OS2_wait_for_message (qid, mt_init));
 
363
    OS2_close_qid (qid);
 
364
  }
 
365
  add_reload_cleanup (close_all_windows);
 
366
}
 
367
 
 
368
static void
 
369
close_all_windows (void)
 
370
{
 
371
  window_t ** scan = ((window_t **) (ID_TABLE_POINTERS (& wid_table)));
 
372
  window_t ** end = (scan + (ID_TABLE_LENGTH (& wid_table)));
 
373
  while (scan < end)
 
374
    {
 
375
      window_t * window = (*scan++);
 
376
      if ((window != 0) && (!WINDOW_PERMANENTP (window)))
 
377
        window_close (window);
 
378
    }
 
379
}
 
380
 
 
381
/* Define this to cause a calling thread to wait for the PM thread to
 
382
   finish requests that have trivial replies.  Otherwise, the calling
 
383
   thread waits only when the request has a non-trivial reply.
 
384
   Usually there is no good reason to wait for trivial replies, but
 
385
   this could be useful during debugging.  */
 
386
/* #define SYNC_SIMPLE_TRANSACTIONS */
 
387
#ifdef SYNC_SIMPLE_TRANSACTIONS
 
388
 
 
389
#define simple_transaction sync_transaction
 
390
#define simple_reply sync_reply
 
391
 
 
392
#else
 
393
 
 
394
#define simple_transaction OS2_send_message
 
395
#define simple_reply(qid)
 
396
 
 
397
#endif
 
398
 
 
399
static void
 
400
sync_transaction (qid_t qid, msg_t * message)
 
401
{
 
402
  OS2_destroy_message
 
403
    (OS2_message_transaction (qid, message, mt_generic_reply));
 
404
}
 
405
 
 
406
static void
 
407
sync_reply (qid_t qid)
 
408
{
 
409
  OS2_send_message (qid, (OS2_create_message (mt_generic_reply)));
 
410
}
 
411
 
 
412
/* These macros simplify the code needed to perform message
 
413
   transactions, by hiding the many type-casts needed.  */
 
414
 
 
415
#define CREATE_MESSAGE(mt)                                              \
 
416
  ((void *) (OS2_create_message (mt)))
 
417
 
 
418
#define CREATE_MESSAGE_1(mt, extra)                                     \
 
419
  ((void *) (OS2_create_message_1 ((mt), (extra))))
 
420
 
 
421
#define DESTROY_MESSAGE(msg)                                            \
 
422
  OS2_destroy_message ((msg_t *) (msg))
 
423
 
 
424
#define SEND_MESSAGE(qid, msg)                                          \
 
425
  OS2_send_message ((qid), ((msg_t *) (msg)))
 
426
 
 
427
#define SIMPLE_TRANSACTION(qid, msg)                                    \
 
428
  simple_transaction ((qid), ((msg_t *) (msg)))
 
429
 
 
430
#define SYNC_TRANSACTION(qid, msg)                                      \
 
431
  sync_transaction ((qid), ((msg_t *) (msg)))
 
432
 
 
433
#define MESSAGE_TRANSACTION(qid, msg, mt)                               \
 
434
  ((void *) (OS2_message_transaction ((qid), ((msg_t *) (msg)), (mt))))
 
435
 
 
436
#define MEMCPY(to, from, length)                                        \
 
437
  FASTCOPY (((const char *) (from)), ((char *) (to)), (length))
 
438
 
 
439
#define STRCPY(to, from)                                                \
 
440
  strcpy (((char *) (to)), (from))
 
441
 
 
442
static void
 
443
pm_thread_procedure (void * arg)
 
444
{
 
445
  EXCEPTIONREGISTRATIONRECORD registration;
 
446
  QMSG qmsg;
 
447
 
 
448
  if ((OS2_thread_initialize_1 ((&registration), QID_NONE)) != 0)
 
449
    OS2_logic_error ("Error signalled within PM thread.");
 
450
  pm_hab = (WinInitialize (0));
 
451
  if (pm_hab == NULLHANDLE)
 
452
    window_error (WinInitialize);
 
453
  pm_hmq = (WinCreateMsgQueue (pm_hab, 1000));
 
454
  if (pm_hmq == NULLHANDLE)
 
455
    window_error (WinCreateMsgQueue);
 
456
  if (!WinRegisterClass (pm_hab,
 
457
                         ((PSZ) object_class),
 
458
                         object_window_procedure,
 
459
                         0,     /* class style */
 
460
                         0))
 
461
    window_error (WinRegisterClass);
 
462
  if (!WinRegisterClass (pm_hab,
 
463
                         ((PSZ) window_class),
 
464
                         window_procedure,
 
465
                         0,     /* class style */
 
466
                         (sizeof (void *))))
 
467
    window_error (WinRegisterClass);
 
468
  pm_object_window
 
469
    = (WinCreateWindow (HWND_OBJECT,
 
470
                        ((PSZ) object_class),
 
471
                        "",     /* text */
 
472
                        0,      /* style */
 
473
                        0, 0, 0, 0, /* size and position */
 
474
                        NULLHANDLE, /* owner */
 
475
                        HWND_BOTTOM,
 
476
                        0,      /* ID */
 
477
                        0,      /* control data */
 
478
                        0       /* presentation parameters */
 
479
                        ));
 
480
  if (pm_object_window == NULLHANDLE)
 
481
    window_error (WinCreateWindow);
 
482
  pm_tqueue = (make_pm_tqueue (pm_object_window));
 
483
  OS2_send_message (pm_init_qid, (OS2_create_message (mt_init)));
 
484
  while (WinGetMsg (pm_hab, (&qmsg), 0, 0, 0))
 
485
    WinDispatchMsg (pm_hab, (&qmsg));
 
486
  if (!WinDestroyWindow (pm_object_window))
 
487
    window_error (WinDestroyWindow);
 
488
  WinDestroyMsgQueue (pm_hmq);
 
489
  WinTerminate (pm_hab);
 
490
  /* There's no way to exit properly, because the normal exit depends
 
491
     on the PM thread being active enough to print the closing
 
492
     messages.  So just use exit.  */
 
493
  exit (1);
 
494
}
 
495
 
 
496
static tqueue_t *
 
497
make_pm_tqueue (HWND hwnd)
 
498
{
 
499
  tqueue_t * tqueue = (OS_malloc (sizeof (pm_tqueue_t)));
 
500
  (TQUEUE_TYPE (tqueue)) = tqt_pm;
 
501
  (PM_TQUEUE_HWND (tqueue)) = hwnd;
 
502
  return (tqueue);
 
503
}
 
504
 
 
505
msg_t *
 
506
OS2_read_pm_tqueue (tqueue_t * tqueue, int blockp)
 
507
{
 
508
  OS2_logic_error ("Read from PM tqueue.");
 
509
  return (0);
 
510
}
 
511
 
 
512
void
 
513
OS2_write_pm_tqueue (tqueue_t * tqueue, msg_t * message)
 
514
{
 
515
  if (!WinPostMsg ((PM_TQUEUE_HWND (tqueue)),
 
516
                   UWM_ENCAPSULATION,
 
517
                   (MPFROMP (message)),
 
518
                   MPVOID))
 
519
    window_warning (WinPostMsg);
 
520
}
 
521
 
 
522
/* Object IDs
 
523
 
 
524
   These tables maintain data structures in the PM thread, and
 
525
   associate those structures with ID numbers that are given out to
 
526
   other threads (and to Scheme programs).  */
 
527
 
 
528
static void
 
529
initialize_id_table (id_table_t * table)
 
530
{
 
531
  unsigned int length = 16;
 
532
  void ** pointers = (OS_malloc ((sizeof (void *)) * length));
 
533
  void ** scan = pointers;
 
534
  void ** end = (scan + length);
 
535
  while (scan < end)
 
536
    (*scan++) = 0;
 
537
  (ID_TABLE_LENGTH (table)) = length;
 
538
  (ID_TABLE_POINTERS (table)) = pointers;
 
539
}
 
540
 
 
541
static unsigned int
 
542
allocate_id (id_table_t * table, void * pointer)
 
543
{
 
544
  unsigned int length = (ID_TABLE_LENGTH (table));
 
545
  void ** pointers = (ID_TABLE_POINTERS (table));
 
546
  void ** scan = (pointers + 1); /* don't allocate ID zero */
 
547
  void ** end = (pointers + length);
 
548
  while (scan < end)
 
549
    if ((*scan++) == 0)
 
550
      {
 
551
        (*--scan) = pointer;
 
552
        return (scan - pointers);
 
553
      }
 
554
  {
 
555
    unsigned int id = length;
 
556
    length *= 2;
 
557
    pointers = (OS_realloc (pointers, ((sizeof (void *)) * length)));
 
558
    scan = (pointers + id + 1);
 
559
    end = (pointers + length);
 
560
    while (scan < end)
 
561
      (*scan++) = 0;
 
562
    (ID_TABLE_LENGTH (table)) = length;
 
563
    (ID_TABLE_POINTERS (table)) = pointers;
 
564
    (pointers[id]) = pointer;
 
565
    return (id);
 
566
  }
 
567
}
 
568
 
 
569
static void
 
570
deallocate_id (id_table_t * table, unsigned int id)
 
571
{
 
572
  ((ID_TABLE_POINTERS (table)) [id]) = 0;
 
573
}
 
574
 
 
575
static void *
 
576
id_to_pointer (id_table_t * table, unsigned int id)
 
577
{
 
578
  void * pointer = ((ID_TABLE_POINTERS (table)) [id]);
 
579
  if (pointer == 0)
 
580
    OS2_logic_error ("Invalid PM ID.");
 
581
  return (pointer);
 
582
}
 
583
 
 
584
static int
 
585
id_validp (id_table_t * table, unsigned int id)
 
586
{
 
587
  return ((id > 0)
 
588
          && (id < (ID_TABLE_LENGTH (table)))
 
589
          && (((ID_TABLE_POINTERS (table)) [id]) != 0));
 
590
}
 
591
 
 
592
static ps_t *
 
593
psid_to_ps (psid_t psid)
 
594
{
 
595
  return (id_to_pointer ((& psid_table), psid));
 
596
}
 
597
 
 
598
static window_t *
 
599
wid_to_window (wid_t wid)
 
600
{
 
601
  return (id_to_pointer ((& wid_table), wid));
 
602
}
 
603
 
 
604
static bitmap_t *
 
605
bid_to_bitmap (bid_t bid)
 
606
{
 
607
  return (id_to_pointer ((& bid_table), bid));
 
608
}
 
609
 
 
610
/* Implementation of the object window.  The object window handles
 
611
   encapsulated messages sent from the Scheme thread.  This defines
 
612
   the protocol used to communicate with the Scheme thread.  */
 
613
 
 
614
static MRESULT EXPENTRY
 
615
object_window_procedure (HWND window, ULONG msg, MPARAM mp1, MPARAM mp2)
 
616
{
 
617
  if (msg == UWM_ENCAPSULATION)
 
618
    {
 
619
      msg_t * message = (PVOIDFROMMP (mp1));
 
620
      switch (MSG_TYPE (message))
 
621
        {
 
622
          /* This machine-generated file contains dispatch cases for
 
623
             most of the procedure messages.  */
 
624
#include "os2pm-dc.h"
 
625
 
 
626
        case mt_window_pos_request:
 
627
          handle_window_pos_request (message);
 
628
          break;
 
629
        case mt_window_size_request:
 
630
          handle_window_size_request (message);
 
631
          break;
 
632
        case mt_window_frame_size_request:
 
633
          handle_window_frame_size_request (message);
 
634
          break;
 
635
        case mt_ps_set_bitmap_request:
 
636
          handle_ps_set_bitmap_request (message);
 
637
          break;
 
638
 
 
639
        default:
 
640
          OS2_logic_error ("Unknown message type sent to PM thread.");
 
641
          break;
 
642
        }
 
643
    }
 
644
  return (MRVOID);
 
645
}
 
646
 
 
647
/* Implementation of the Frame Window */
 
648
 
 
649
static MRESULT EXPENTRY
 
650
frame_window_procedure (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
 
651
{
 
652
  window_t * window = (hwnd_to_window (WinWindowFromID (hwnd, FID_CLIENT)));
 
653
  switch (msg)
 
654
    {
 
655
    case WM_QUERYTRACKINFO:
 
656
      /* Set the tracking grid for the resize operation.  */
 
657
      {
 
658
        MRESULT mr
 
659
          = ((* original_frame_window_procedure) (hwnd, msg, mp1, mp2));
 
660
        if (mr == MRTRUE)
 
661
          {
 
662
            PTRACKINFO pti = (PVOIDFROMMP (mp2));
 
663
            if ((((pti -> fs) & TF_MOVE) != TF_MOVE)
 
664
                && ((((pti -> fs) & TF_MOVE) != 0)
 
665
                    || (((pti -> fs) & TF_SETPOINTERPOS) != 0)))
 
666
              {
 
667
                (pti -> fs) |= TF_GRID;
 
668
                (pti -> cxGrid) = (WINDOW_GRID_X (window));
 
669
                (pti -> cyGrid) = (WINDOW_GRID_Y (window));
 
670
                (pti -> cxKeyboard) = (WINDOW_GRID_X (window));
 
671
                (pti -> cyKeyboard) = (WINDOW_GRID_Y (window));
 
672
              }
 
673
          }
 
674
        return (mr);
 
675
      }
 
676
    case WM_MINMAXFRAME:
 
677
      /* If minimizing, mark the window to indicate this.  The client
 
678
         will shortly receive a WM_SIZE which indicates that the
 
679
         minimization has completed.  */
 
680
      {
 
681
        PSWP pswp = (PVOIDFROMMP (mp1));
 
682
        if ((!WINDOW_MINIMIZEDP (window))
 
683
            && (((pswp -> fl) & SWP_MINIMIZE) != 0))
 
684
          {
 
685
            (WINDOW_MINIMIZINGP (window)) = 1;
 
686
            (WINDOW_MINIMIZEDP (window)) = 1;
 
687
          }
 
688
        else if ((WINDOW_MINIMIZEDP (window))
 
689
                 && (((pswp -> fl) & (SWP_RESTORE | SWP_MAXIMIZE)) != 0))
 
690
          (WINDOW_MINIMIZEDP (window)) = 0;
 
691
      }
 
692
      break;
 
693
    }
 
694
  return ((* original_frame_window_procedure) (hwnd, msg, mp1, mp2));
 
695
}
 
696
 
 
697
/* Implementation of the Client Window */
 
698
 
 
699
static MRESULT EXPENTRY
 
700
window_procedure (HWND hwnd, ULONG msg, MPARAM mp1, MPARAM mp2)
 
701
{
 
702
  switch (msg)
 
703
    {
 
704
    case WM_CREATE:
 
705
      {
 
706
        window_t * window = (PVOIDFROMMP (mp1));
 
707
        if (!WinSetWindowPtr (hwnd, QWP_WINDOW, window))
 
708
          window_error (WinSetWindowPtr);
 
709
        (WINDOW_CLIENT (window)) = hwnd;
 
710
        (WINDOW_CLIENT_PS (window))
 
711
          = (create_ps (pst_window,
 
712
                        (WinOpenWindowDC (hwnd)),
 
713
                        (WINDOW_QID (window))));
 
714
        (PS_VISUAL (WINDOW_CLIENT_PS (window))) = window;
 
715
        return (MRFALSE);
 
716
      }
 
717
    case WM_PAINT:
 
718
      {
 
719
        window_t * window = (hwnd_to_window (hwnd));
 
720
        if (((WinQueryWindowULong ((WINDOW_FRAME (window)), QWL_STYLE))
 
721
             & WS_MINIMIZED)
 
722
            != 0)
 
723
          break;
 
724
        {
 
725
          HPS hps = (PS_HANDLE (WINDOW_CLIENT_PS (window)));
 
726
          RECTL rectl;
 
727
          if ((WinBeginPaint ((WINDOW_CLIENT (window)), hps, (& rectl)))
 
728
              == NULLHANDLE)
 
729
            window_error (WinBeginPaint);
 
730
          if (!WinEndPaint (hps))
 
731
            window_error (WinEndPaint);
 
732
          SEND_EVENT (window,
 
733
                      (make_paint_event ((WINDOW_ID (window)),
 
734
                                         (rectl . xLeft),
 
735
                                         (rectl . xRight),
 
736
                                         (rectl . yBottom),
 
737
                                         (rectl . yTop))));
 
738
        }
 
739
        return (MRVOID);
 
740
      }
 
741
    case WM_SETFOCUS:
 
742
      {
 
743
        window_t * window = (hwnd_to_window (hwnd));
 
744
        if (SHORT1FROMMP (mp2))
 
745
          recreate_cursor (window);
 
746
        else
 
747
          {
 
748
            win_destroy_cursor (WINDOW_CLIENT (window));
 
749
            (WINDOW_CURSOR_CREATEDP (window)) = 0;
 
750
          }
 
751
      }
 
752
      SEND_PM_EVENT (hwnd, msg, mp1, mp2);
 
753
      return (MRVOID);
 
754
    case WM_TRANSLATEACCEL:
 
755
      {
 
756
        PQMSG qmsg = (PVOIDFROMMP (mp1));
 
757
        USHORT flags = (SHORT1FROMMP (qmsg -> mp1));
 
758
        USHORT char_code = (SHORT1FROMMP (qmsg -> mp2));
 
759
        USHORT virtual_key = (SHORT2FROMMP (qmsg -> mp2));
 
760
        /* Disable specific default accelerator keys.  */
 
761
        if ((flags & KC_VIRTUALKEY) != 0)
 
762
          switch (virtual_key)
 
763
            {
 
764
            case VK_ALT:
 
765
            case VK_ALTGRAF:
 
766
              /* Disable "Alt" keys, which normally pop up the system
 
767
                 menu.  These keys are used often in Edwin and the
 
768
                 default behavior is unacceptable.  */
 
769
              return (MRFALSE);
 
770
            case VK_SPACE:
 
771
            case VK_ESC:
 
772
            case VK_TAB:
 
773
              /* Disable "Alt-SPC", "Alt-ESC", and "Alt-TAB", which
 
774
                 have standard key bindings in Edwin.  */
 
775
              if ((flags & KC_ALT) != 0)
 
776
                return (MRFALSE);
 
777
            }
 
778
        else if ((flags & KC_CHAR) != 0)
 
779
          switch (char_code)
 
780
            {
 
781
            case ' ':
 
782
            case '\033':
 
783
            case '\t':
 
784
              /* Disable "Alt-SPC", "Alt-ESC", and "Alt-TAB", if for
 
785
                 some reason they are reported as ASCII characters
 
786
                 rather than as virtual keys.  */
 
787
              if ((flags & KC_ALT) != 0)
 
788
                return (MRFALSE);
 
789
            }
 
790
        break;
 
791
      }
 
792
    case WM_DESTROY:
 
793
      {
 
794
        window_t * window = (hwnd_to_window (hwnd));
 
795
        destroy_ps (WINDOW_CLIENT_PS (window));
 
796
        (WINDOW_CLIENT_PS (window)) = 0;
 
797
        return (MRVOID);
 
798
      }
 
799
    case WM_SIZE:
 
800
      {
 
801
        window_t * window = (hwnd_to_window (hwnd));
 
802
        /* If this message is part of a minimization, ignore it.  */
 
803
        if (WINDOW_MINIMIZINGP (window))
 
804
          {
 
805
            (WINDOW_MINIMIZINGP (window)) = 0;
 
806
            (WINDOW_MINIMIZEDP (window)) = 1;
 
807
            break;
 
808
          }
 
809
        if (WINDOW_CURSOR_CREATEDP (window))
 
810
          {
 
811
            win_destroy_cursor (WINDOW_CLIENT (window));
 
812
            (WINDOW_CURSOR_CREATEDP (window)) = 0;
 
813
            (WINDOW_CURSOR_X (window)) = 0;
 
814
            (WINDOW_CURSOR_Y (window)) = 0;
 
815
            recreate_cursor (window);
 
816
          }
 
817
      }
 
818
      SEND_PM_EVENT (hwnd, msg, mp1, mp2);
 
819
      return (MRVOID);
 
820
    case WM_CLOSE:
 
821
    case WM_COMMAND:
 
822
    case WM_CONTROL:
 
823
    case WM_HELP:
 
824
    case WM_SHOW:
 
825
      SEND_PM_EVENT (hwnd, msg, mp1, mp2);
 
826
      return (MRVOID);
 
827
    case WM_CHAR:
 
828
    case WM_BUTTON1DOWN:
 
829
    case WM_BUTTON1UP:
 
830
    case WM_BUTTON1CLICK:
 
831
    case WM_BUTTON1DBLCLK:
 
832
    case WM_BUTTON2DOWN:
 
833
    case WM_BUTTON2UP:
 
834
    case WM_BUTTON2CLICK:
 
835
    case WM_BUTTON2DBLCLK:
 
836
    case WM_BUTTON3DOWN:
 
837
    case WM_BUTTON3UP:
 
838
    case WM_BUTTON3CLICK:
 
839
    case WM_BUTTON3DBLCLK:
 
840
      SEND_PM_EVENT (hwnd, msg, mp1, mp2);
 
841
      return (MRTRUE);
 
842
    case WM_MOUSEMOVE:
 
843
      if (WINDOW_MOUSETRACKP (hwnd_to_window (hwnd)))
 
844
        {
 
845
          SEND_PM_EVENT (hwnd, msg, mp1, mp2);
 
846
          return (MRTRUE);
 
847
        }
 
848
      break;
 
849
    default:
 
850
      break;
 
851
    }
 
852
  return (WinDefWindowProc (hwnd, msg, mp1, mp2));
 
853
}
 
854
 
 
855
static window_t *
 
856
hwnd_to_window (HWND hwnd)
 
857
{
 
858
  window_t * window = (WinQueryWindowPtr (hwnd, QWP_WINDOW));
 
859
  if (window == 0)
 
860
    window_error (WinQueryWindowPtr);
 
861
  return (window);
 
862
}
 
863
 
 
864
static msg_t *
 
865
make_pm_event (wid_t wid, ULONG msg, MPARAM mp1, MPARAM mp2)
 
866
{
 
867
  msg_t * message = (OS2_create_message (mt_pm_event));
 
868
  (SM_PM_EVENT_WID (message)) = wid;
 
869
  (SM_PM_EVENT_MSG (message)) = msg;
 
870
  (SM_PM_EVENT_MP1 (message)) = mp1;
 
871
  (SM_PM_EVENT_MP2 (message)) = mp2;
 
872
  return (message);
 
873
}
 
874
 
 
875
static msg_t *
 
876
make_paint_event (wid_t wid,
 
877
                  unsigned short xl, unsigned short xh,
 
878
                  unsigned short yl, unsigned short yh)
 
879
{
 
880
  msg_t * message = (OS2_create_message (mt_paint_event));
 
881
  (SM_PAINT_EVENT_WID (message)) = wid;
 
882
  (SM_PAINT_EVENT_XL (message)) = xl;
 
883
  (SM_PAINT_EVENT_XH (message)) = xh;
 
884
  (SM_PAINT_EVENT_YL (message)) = yl;
 
885
  (SM_PAINT_EVENT_YH (message)) = yh;
 
886
  return (message);
 
887
}
 
888
 
 
889
int
 
890
OS2_translate_wm_char (MPARAM mp1, MPARAM mp2,
 
891
                       unsigned short * code,
 
892
                       unsigned short * flags,
 
893
                       unsigned char * repeat)
 
894
{
 
895
  (*flags) = (SHORT1FROMMP (mp1));
 
896
  (*repeat) = (CHAR3FROMMP (mp1));
 
897
  /* Ignore compound keys for now.  */
 
898
  if (((*flags) & (KC_DEADKEY | KC_COMPOSITE | KC_INVALIDCOMP | KC_KEYUP))
 
899
      != 0)
 
900
    return (0);
 
901
  if (((*flags) & KC_VIRTUALKEY) != 0)
 
902
    {
 
903
      (*code) = (SHORT2FROMMP (mp2));
 
904
      return (1);
 
905
    }
 
906
  if (((*flags) & (KC_CHAR | KC_CTRL | KC_ALT)) != 0)
 
907
    {
 
908
      (*code) = (SHORT1FROMMP (mp2));
 
909
      return (1);
 
910
    }
 
911
  return (0);
 
912
}
 
913
 
 
914
/* Direct Operations
 
915
 
 
916
   These are exported operations that can be implemented directly in
 
917
   the calling thread.  Other operations that require communication
 
918
   with the PM thread appear on following pages.  */
 
919
 
 
920
int
 
921
OS2_psid_validp (psid_t psid)
 
922
{
 
923
  return (id_validp ((& psid_table), psid));
 
924
}
 
925
 
 
926
int
 
927
OS2_wid_validp (wid_t wid)
 
928
{
 
929
  return (id_validp ((& wid_table), wid));
 
930
}
 
931
 
 
932
int
 
933
OS2_bid_validp (bid_t bid)
 
934
{
 
935
  return (id_validp ((& bid_table), bid));
 
936
}
 
937
 
 
938
psid_t
 
939
OS2_window_client_ps (wid_t wid)
 
940
{
 
941
  return (PS_ID (WINDOW_CLIENT_PS (wid_to_window (wid))));
 
942
}
 
943
 
 
944
qid_t
 
945
OS2_create_pm_qid (tqueue_t * tqueue)
 
946
{
 
947
  qid_t pm_side;
 
948
  qid_t client_side;
 
949
  OS2_make_qid_pair ((&pm_side), (&client_side));
 
950
  OS2_open_qid (pm_side, pm_tqueue);
 
951
  OS2_open_qid (client_side, tqueue);
 
952
  return (client_side);
 
953
}
 
954
 
 
955
void
 
956
OS2_window_permanent (wid_t wid)
 
957
{
 
958
  (WINDOW_PERMANENTP (wid_to_window (wid))) = 1;
 
959
}
 
960
 
 
961
void
 
962
OS2_window_mousetrack (wid_t wid, int trackp)
 
963
{
 
964
  (WINDOW_MOUSETRACKP (wid_to_window (wid))) = trackp;
 
965
}
 
966
 
 
967
HWND
 
968
OS2_window_frame_handle (wid_t wid)
 
969
{
 
970
  return (WINDOW_FRAME (wid_to_window (wid)));
 
971
}
 
972
 
 
973
HWND
 
974
OS2_window_client_handle (wid_t wid)
 
975
{
 
976
  return (WINDOW_CLIENT (wid_to_window (wid)));
 
977
}
 
978
 
 
979
int
 
980
OS2_memory_ps_p (psid_t psid)
 
981
{
 
982
  return ((PS_VISUAL_TYPE (psid_to_ps (psid))) == pst_memory);
 
983
}
 
984
 
 
985
bid_t
 
986
OS2_ps_get_bitmap (psid_t psid)
 
987
{
 
988
  bitmap_t * bitmap = (PS_VISUAL (psid_to_ps (psid)));
 
989
  return ((bitmap == 0) ? BID_NONE : (BITMAP_ID (bitmap)));
 
990
}
 
991
 
 
992
/* Relayed Operations
 
993
 
 
994
   This page implements exported operations that require communication
 
995
   with the PM thread.  The PM-thread-side of these operations appear
 
996
   on the following pages; this page implements only the mechanism to
 
997
   communicate the operation to the PM thread.  The bulk of these
 
998
   communication procedures is machine-generated.  */
 
999
 
 
1000
/* This macro supplies a NO-OP procedure needed by the
 
1001
   machine-generated code for OS2_pm_synchronize.  */
 
1002
#define pm_synchronize(qid)
 
1003
 
 
1004
/* This machine-generated file contains most of the external procedure
 
1005
   definitions, and their associated handler procedures.  */
 
1006
#include "os2pm-rp.h"
 
1007
 
 
1008
void
 
1009
OS2_window_pos (wid_t wid, short * x, short * y)
 
1010
{
 
1011
  window_t * window = (wid_to_window (wid));
 
1012
  msg_t * message = (OS2_create_message (mt_window_pos_request));
 
1013
  (SM_POS_REQUEST_WINDOW (message)) = window;
 
1014
  message
 
1015
    = (OS2_message_transaction ((WINDOW_QID (window)),
 
1016
                                message,
 
1017
                                mt_window_pos_reply));
 
1018
  (* x) = (SM_POS_REPLY_X (message));
 
1019
  (* y) = (SM_POS_REPLY_Y (message));
 
1020
  OS2_destroy_message (message);
 
1021
}
 
1022
 
 
1023
static void
 
1024
handle_window_pos_request (msg_t * request)
 
1025
{
 
1026
  qid_t sender = (MSG_SENDER (request));
 
1027
  msg_t * reply = (OS2_create_message (mt_window_pos_reply));
 
1028
  window_pos ((SM_POS_REQUEST_WINDOW (request)),
 
1029
              (& (SM_POS_REPLY_X (reply))),
 
1030
              (& (SM_POS_REPLY_Y (reply))));
 
1031
  OS2_destroy_message (request);
 
1032
  OS2_send_message (sender, reply);
 
1033
}
 
1034
 
 
1035
void
 
1036
OS2_window_size (wid_t wid, unsigned short * width, unsigned short * height)
 
1037
{
 
1038
  window_t * window = (wid_to_window (wid));
 
1039
  msg_t * message = (OS2_create_message (mt_window_size_request));
 
1040
  (SM_SIZE_REQUEST_WINDOW (message)) = window;
 
1041
  message
 
1042
    = (OS2_message_transaction ((WINDOW_QID (window)),
 
1043
                                message,
 
1044
                                mt_window_size_reply));
 
1045
  (* width) = (SM_SIZE_REPLY_WIDTH (message));
 
1046
  (* height) = (SM_SIZE_REPLY_HEIGHT (message));
 
1047
  OS2_destroy_message (message);
 
1048
}
 
1049
 
 
1050
static void
 
1051
handle_window_size_request (msg_t * request)
 
1052
{
 
1053
  qid_t sender = (MSG_SENDER (request));
 
1054
  msg_t * reply = (OS2_create_message (mt_window_size_reply));
 
1055
  window_size ((SM_SIZE_REQUEST_WINDOW (request)),
 
1056
               (& (SM_SIZE_REPLY_WIDTH (reply))),
 
1057
               (& (SM_SIZE_REPLY_HEIGHT (reply))));
 
1058
  OS2_destroy_message (request);
 
1059
  OS2_send_message (sender, reply);
 
1060
}
 
1061
 
 
1062
void
 
1063
OS2_window_frame_size (wid_t wid,
 
1064
                       unsigned short * width, unsigned short * height)
 
1065
{
 
1066
  window_t * window = (wid_to_window (wid));
 
1067
  msg_t * message = (OS2_create_message (mt_window_frame_size_request));
 
1068
  (SM_FRAME_SIZE_REQUEST_WINDOW (message)) = window;
 
1069
  message
 
1070
    = (OS2_message_transaction ((WINDOW_QID (window)),
 
1071
                                message,
 
1072
                                mt_window_frame_size_reply));
 
1073
  (* width) = (SM_FRAME_SIZE_REPLY_WIDTH (message));
 
1074
  (* height) = (SM_FRAME_SIZE_REPLY_HEIGHT (message));
 
1075
  OS2_destroy_message (message);
 
1076
}
 
1077
 
 
1078
static void
 
1079
handle_window_frame_size_request (msg_t * request)
 
1080
{
 
1081
  qid_t sender = (MSG_SENDER (request));
 
1082
  msg_t * reply = (OS2_create_message (mt_window_frame_size_reply));
 
1083
  window_frame_size ((SM_FRAME_SIZE_REQUEST_WINDOW (request)),
 
1084
                     (& (SM_FRAME_SIZE_REPLY_WIDTH (reply))),
 
1085
                     (& (SM_FRAME_SIZE_REPLY_HEIGHT (reply))));
 
1086
  OS2_destroy_message (request);
 
1087
  OS2_send_message (sender, reply);
 
1088
}
 
1089
 
 
1090
bid_t
 
1091
OS2_ps_set_bitmap (psid_t psid, bid_t bid)
 
1092
{
 
1093
  ps_t * ps = (psid_to_ps (psid));
 
1094
  bitmap_t * bitmap = ((bid == BID_NONE) ? 0 : (bid_to_bitmap (bid)));
 
1095
  msg_t * message = (OS2_create_message (mt_ps_set_bitmap_request));
 
1096
  (SM_PS_SET_BITMAP_REQUEST_PS (message)) = ps;
 
1097
  (SM_PS_SET_BITMAP_REQUEST_BITMAP (message)) = bitmap;
 
1098
  message
 
1099
    = (OS2_message_transaction ((PS_QID (ps)),
 
1100
                                message,
 
1101
                                mt_ps_set_bitmap_reply));
 
1102
  bitmap = (SM_PS_SET_BITMAP_REPLY_BITMAP (message));
 
1103
  OS2_destroy_message (message);
 
1104
  return ((bitmap == 0) ? BID_NONE : (BITMAP_ID (bitmap)));
 
1105
}
 
1106
 
 
1107
static void
 
1108
handle_ps_set_bitmap_request (msg_t * request)
 
1109
{
 
1110
  qid_t sender = (MSG_SENDER (request));
 
1111
  msg_t * reply = (OS2_create_message (mt_ps_set_bitmap_reply));
 
1112
  (SM_PS_SET_BITMAP_REPLY_BITMAP (reply))
 
1113
    = (ps_set_bitmap ((SM_PS_SET_BITMAP_REQUEST_PS (request)),
 
1114
                      (SM_PS_SET_BITMAP_REQUEST_BITMAP (request))));
 
1115
  OS2_destroy_message (request);
 
1116
  OS2_send_message (sender, reply);
 
1117
}
 
1118
 
 
1119
font_metrics_t *
 
1120
OS2_ps_set_font (psid_t psid, unsigned short id, const char * name)
 
1121
{
 
1122
  font_metrics_t * metrics = (OS2_ps_set_font_internal (psid, id, name));
 
1123
  if ((metrics != 0) && (psid == (OS2_console_psid ())))
 
1124
    OS2_console_font_change_hook (metrics);
 
1125
  return (metrics);
 
1126
}
 
1127
 
 
1128
/* PM-thread Operation Implementations
 
1129
 
 
1130
   All of the procedures from this point on are implementations of
 
1131
   exported operations.  These implementations are the code that is
 
1132
   run in the PM thread to implement the operations that are invoked
 
1133
   in other threads.  */
 
1134
 
 
1135
/* Windows */
 
1136
 
 
1137
static wid_t
 
1138
window_open (qid_t qid, qid_t event_qid, ULONG flags, HMODULE module, ULONG id,
 
1139
             ULONG style, const char * title)
 
1140
{
 
1141
  window_t * window = (make_window (qid, event_qid));
 
1142
  FRAMECDATA frame_data;
 
1143
  HWND frame_window;
 
1144
 
 
1145
  (frame_data . cb) = (sizeof (frame_data));
 
1146
  (frame_data . flCreateFlags) = flags;
 
1147
  (frame_data . hmodResources) = module;
 
1148
  (frame_data . idResources) = id;
 
1149
  frame_window
 
1150
    = (WinCreateWindow (HWND_DESKTOP,
 
1151
                        WC_FRAME,
 
1152
                        ((PSZ) title), /* title string */
 
1153
                        0,      /* window style */
 
1154
                        0, 0, 0, 0, /* size and position */
 
1155
                        NULLHANDLE, /* owner window */
 
1156
                        HWND_TOP,
 
1157
                        ID_FRAME,       /* window ID */
 
1158
                        (& frame_data),
 
1159
                        0));
 
1160
  if (frame_window == NULLHANDLE)
 
1161
    window_error (WinCreateWindow);
 
1162
  (WINDOW_FRAME (window)) = frame_window;
 
1163
  {
 
1164
    PFNWP procedure
 
1165
      = (WinSubclassWindow (frame_window, frame_window_procedure));
 
1166
    if (procedure == 0)
 
1167
      window_error (WinSubclassWindow);
 
1168
    if (original_frame_window_procedure == 0)
 
1169
      original_frame_window_procedure = procedure;
 
1170
    else if (original_frame_window_procedure != procedure)
 
1171
      OS2_logic_error ("WinSubclassWindow returned two different answers.");
 
1172
  }
 
1173
  if ((WinCreateWindow (frame_window,
 
1174
                        ((PSZ) window_class),
 
1175
                        0,      /* window text (class-specific) */
 
1176
                        style,  /* window style */
 
1177
                        0, 0, 0, 0, /* size and position */
 
1178
                        frame_window, /* owner window */
 
1179
                        HWND_BOTTOM,
 
1180
                        FID_CLIENT, /* window ID */
 
1181
                        window,
 
1182
                        0))
 
1183
      == NULLHANDLE)
 
1184
    window_error (WinCreateWindow);
 
1185
  return (WINDOW_ID (window));
 
1186
}
 
1187
 
 
1188
static window_t *
 
1189
make_window (qid_t qid, qid_t event_qid)
 
1190
{
 
1191
  window_t * window = (OS_malloc (sizeof (window_t)));
 
1192
  (WINDOW_FRAME (window)) = NULLHANDLE;
 
1193
  (WINDOW_CLIENT (window)) = NULLHANDLE;
 
1194
  (WINDOW_CLIENT_PS (window)) = 0;
 
1195
  (WINDOW_GRID_X (window)) = 1;
 
1196
  (WINDOW_GRID_Y (window)) = 1;
 
1197
  (WINDOW_CURSOR_X (window)) = 0;
 
1198
  (WINDOW_CURSOR_Y (window)) = 0;
 
1199
  (WINDOW_CURSOR_WIDTH (window)) = 0;
 
1200
  (WINDOW_CURSOR_HEIGHT (window)) = 0;
 
1201
  (WINDOW_CURSOR_STYLE (window)) = (CURSOR_SOLID | CURSOR_FLASH);
 
1202
  (WINDOW_QID (window)) = qid;
 
1203
  (WINDOW_EVENT_QID (window)) = event_qid;
 
1204
  (WINDOW_ID (window)) = (allocate_id ((& wid_table), window));
 
1205
  (WINDOW_CURSOR_CREATEDP (window)) = 0;
 
1206
  (WINDOW_CURSOR_ENABLEDP (window)) = 0;
 
1207
  (WINDOW_MINIMIZINGP (window)) = 0;
 
1208
  (WINDOW_MINIMIZEDP (window)) = 0;
 
1209
  (WINDOW_PERMANENTP (window)) = 0;
 
1210
  (WINDOW_MOUSETRACKP (window)) = 0;
 
1211
  return (window);
 
1212
}
 
1213
 
 
1214
static void
 
1215
window_close (window_t * window)
 
1216
{
 
1217
  if (!WinDestroyWindow (WINDOW_FRAME (window)))
 
1218
    window_warning (WinDestroyWindow);
 
1219
  deallocate_id ((& wid_table), (WINDOW_ID (window)));
 
1220
  OS_free (window);
 
1221
}
 
1222
 
 
1223
static void
 
1224
window_show (window_t * window, int showp)
 
1225
{
 
1226
  if (!WinShowWindow ((WINDOW_FRAME (window)), showp))
 
1227
    window_warning (WinShowWindow);
 
1228
}
 
1229
 
 
1230
static void
 
1231
window_scroll (window_t * window, short xl, short xh, short yl, short yh,
 
1232
               short x_delta, short y_delta)
 
1233
{
 
1234
  RECTL rectl;
 
1235
  (rectl . xLeft) = xl;
 
1236
  (rectl . xRight) = xh;
 
1237
  (rectl . yBottom) = yl;
 
1238
  (rectl . yTop) = yh;
 
1239
  deactivate_cursor (window);
 
1240
  if ((WinScrollWindow ((WINDOW_CLIENT (window)), x_delta, y_delta, (& rectl),
 
1241
                        0, NULLHANDLE, 0, 0))
 
1242
      == RGN_ERROR)
 
1243
    window_warning (WinScrollWindow);
 
1244
  activate_cursor (window);
 
1245
}
 
1246
 
 
1247
static void
 
1248
window_invalidate (window_t * window, short xl, short xh, short yl, short yh)
 
1249
{
 
1250
  RECTL rectl;
 
1251
  (rectl . xLeft) = xl;
 
1252
  (rectl . xRight) = xh;
 
1253
  (rectl . yBottom) = yl;
 
1254
  (rectl . yTop) = yh;
 
1255
  if (!WinInvalidateRect ((WINDOW_CLIENT (window)), (& rectl), FALSE))
 
1256
    window_warning (WinInvalidateRect);
 
1257
}
 
1258
 
 
1259
static void
 
1260
window_set_grid (window_t * window, unsigned short x, unsigned short y)
 
1261
{
 
1262
  (WINDOW_GRID_X (window)) = x;
 
1263
  (WINDOW_GRID_Y (window)) = y;
 
1264
}
 
1265
 
 
1266
static void
 
1267
window_activate (window_t * window)
 
1268
{
 
1269
  if (!WinSetActiveWindow (HWND_DESKTOP, (WINDOW_FRAME (window))))
 
1270
    window_warning (WinSetActiveWindow);
 
1271
}
 
1272
 
 
1273
static void
 
1274
window_pos (window_t * window, short * x, short * y)
 
1275
{
 
1276
  SWP swp;
 
1277
  if (!WinQueryWindowPos ((WINDOW_FRAME (window)), (& swp)))
 
1278
    window_error (WinQueryWindowPos);
 
1279
  (* x) = (swp . x);
 
1280
  (* y) = (swp . y);
 
1281
}
 
1282
 
 
1283
static void
 
1284
window_set_pos (window_t * window, short x, short y)
 
1285
{
 
1286
  if (!WinSetWindowPos ((WINDOW_FRAME (window)), NULLHANDLE, x, y,
 
1287
                        0, 0, SWP_MOVE))
 
1288
    window_warning (WinSetWindowPos);
 
1289
}
 
1290
 
 
1291
static void
 
1292
window_size (window_t * window,
 
1293
             unsigned short * width, unsigned short * height)
 
1294
{
 
1295
  SWP swp;
 
1296
  if (!WinQueryWindowPos ((WINDOW_CLIENT (window)), (& swp)))
 
1297
    window_error (WinQueryWindowPos);
 
1298
  (* width) = (swp . cx);
 
1299
  (* height) = (swp . cy);
 
1300
}
 
1301
 
 
1302
static void
 
1303
window_frame_size (window_t * window,
 
1304
                   unsigned short * width, unsigned short * height)
 
1305
{
 
1306
  SWP swp;
 
1307
  if (!WinQueryWindowPos ((WINDOW_FRAME (window)), (& swp)))
 
1308
    window_error (WinQueryWindowPos);
 
1309
  (* width) = (swp . cx);
 
1310
  (* height) = (swp . cy);
 
1311
}
 
1312
 
 
1313
static void
 
1314
window_set_size (window_t * window,
 
1315
                 unsigned short width, unsigned short height)
 
1316
{
 
1317
  RECTL rcl;
 
1318
  (rcl . xLeft) = 0;
 
1319
  (rcl . xRight) = width;
 
1320
  (rcl . yBottom) = 0;
 
1321
  (rcl . yTop) = height;
 
1322
  if (!WinMapWindowPoints ((WINDOW_CLIENT (window)), HWND_DESKTOP,
 
1323
                           ((PPOINTL) (& rcl)), 2))
 
1324
    window_error (WinMapWindowPoints);
 
1325
  if (!WinCalcFrameRect ((WINDOW_FRAME (window)), (& rcl), FALSE))
 
1326
    window_error (WinCalcFrameRect);
 
1327
  if (!WinSetWindowPos ((WINDOW_FRAME (window)),
 
1328
                        NULLHANDLE, 0, 0,
 
1329
                        ((rcl . xRight) - (rcl . xLeft)),
 
1330
                        ((rcl . yTop) - (rcl . yBottom)),
 
1331
                        SWP_SIZE))
 
1332
    window_warning (WinSetWindowPos);
 
1333
}
 
1334
 
 
1335
static int
 
1336
window_focusp (window_t * window)
 
1337
{
 
1338
  return ((WINDOW_CLIENT (window)) == (WinQueryFocus (HWND_DESKTOP)));
 
1339
}
 
1340
 
 
1341
static void
 
1342
window_set_state (window_t * window, window_state_t state)
 
1343
{
 
1344
  ULONG op = 0;
 
1345
  HWND behind = NULLHANDLE;
 
1346
  switch (state)
 
1347
    {
 
1348
    case state_top:
 
1349
      op = SWP_ZORDER;
 
1350
      behind = HWND_TOP;
 
1351
      break;
 
1352
    case state_bottom:
 
1353
      op = SWP_ZORDER;
 
1354
      behind = HWND_BOTTOM;
 
1355
      break;
 
1356
    case state_show:
 
1357
      op = SWP_SHOW;
 
1358
      break;
 
1359
    case state_hide:
 
1360
      op = SWP_HIDE;
 
1361
      break;
 
1362
    case state_activate:
 
1363
      op = SWP_ACTIVATE;
 
1364
      break;
 
1365
    case state_deactivate:
 
1366
      op = SWP_DEACTIVATE;
 
1367
      break;
 
1368
    case state_minimize:
 
1369
      op = SWP_MINIMIZE;
 
1370
      break;
 
1371
    case state_maximize:
 
1372
      op = SWP_MAXIMIZE;
 
1373
      break;
 
1374
    case state_restore:
 
1375
      op = SWP_RESTORE;
 
1376
      break;
 
1377
    }
 
1378
  if (!WinSetWindowPos ((WINDOW_FRAME (window)), behind, 0, 0, 0, 0, op))
 
1379
    window_warning (WinSetWindowPos);
 
1380
}
 
1381
 
 
1382
static void
 
1383
window_set_title (window_t * window, const char * title)
 
1384
{
 
1385
  if (!WinSetWindowText ((WINDOW_FRAME (window)), ((PSZ) title)))
 
1386
    window_warning (WinSetWindowText);
 
1387
}
 
1388
 
 
1389
static void
 
1390
window_update_frame (window_t * window, USHORT flags)
 
1391
{
 
1392
  (void) WinSendMsg ((WINDOW_FRAME (window)), WM_UPDATEFRAME,
 
1393
                     (MPFROMSHORT (flags)),
 
1394
                     0);
 
1395
}
 
1396
 
 
1397
static HWND
 
1398
window_handle_from_id (qid_t qid, HWND window, ULONG id)
 
1399
{
 
1400
  return (WinWindowFromID (window, id));
 
1401
}
 
1402
 
 
1403
static BOOL
 
1404
window_set_capture (window_t * window, int capturep)
 
1405
{
 
1406
  if (capturep)
 
1407
    {
 
1408
      if (capture_window == 0)
 
1409
        {
 
1410
          BOOL rc = (WinSetCapture (HWND_DESKTOP, (WINDOW_CLIENT (window))));
 
1411
          if (rc)
 
1412
            capture_window = window;
 
1413
          return (rc);
 
1414
        }
 
1415
      else
 
1416
        return (capture_window == window);
 
1417
    }
 
1418
  else
 
1419
    {
 
1420
      capture_window = 0;
 
1421
      return (WinSetCapture (HWND_DESKTOP, NULLHANDLE));
 
1422
    }
 
1423
}
 
1424
 
 
1425
static LONG
 
1426
window_query_sys_value (qid_t qid, HWND window, LONG id)
 
1427
{
 
1428
  LONG value = (WinQuerySysValue (window, id));
 
1429
  if (value == 0)
 
1430
    window_error (WinQuerySysValue);
 
1431
  return (value);
 
1432
}
 
1433
 
 
1434
/* Text Cursors */
 
1435
 
 
1436
static void
 
1437
window_move_cursor (window_t * window, short x, short y)
 
1438
{
 
1439
  (WINDOW_CURSOR_X (window)) = x;
 
1440
  (WINDOW_CURSOR_Y (window)) = y;
 
1441
  if (WINDOW_CURSOR_CREATEDP (window))
 
1442
    win_create_cursor ((WINDOW_CLIENT (window)), x, y, 0, 0, CURSOR_SETPOS, 0);
 
1443
}
 
1444
 
 
1445
static void
 
1446
window_shape_cursor (window_t * window, unsigned short width,
 
1447
                     unsigned short height, unsigned short style)
 
1448
{
 
1449
  (WINDOW_CURSOR_WIDTH (window)) = width;
 
1450
  (WINDOW_CURSOR_HEIGHT (window)) = height;
 
1451
  (WINDOW_CURSOR_STYLE (window)) = style;
 
1452
  if (WINDOW_CURSOR_CREATEDP (window))
 
1453
    recreate_cursor (window);
 
1454
}
 
1455
 
 
1456
static void
 
1457
window_show_cursor (window_t * window, int showp)
 
1458
{
 
1459
  if ((WINDOW_CURSOR_CREATEDP (window))
 
1460
      && ((showp != 0) != (WINDOW_CURSOR_ENABLEDP (window))))
 
1461
    win_show_cursor ((WINDOW_CLIENT (window)), showp);
 
1462
  (WINDOW_CURSOR_ENABLEDP (window)) = (showp != 0);
 
1463
}
 
1464
 
 
1465
/* Helper Procedures */
 
1466
 
 
1467
static void
 
1468
win_create_cursor (HWND client, LONG x, LONG y, LONG cx, LONG cy, ULONG fs,
 
1469
                   PRECTL clip_rectl)
 
1470
{
 
1471
  if (!WinCreateCursor (client, x, y, cx, cy, fs, clip_rectl))
 
1472
    window_warning (WinCreateCursor);
 
1473
}
 
1474
 
 
1475
static void
 
1476
win_destroy_cursor (HWND client)
 
1477
{
 
1478
  if (!WinDestroyCursor (client))
 
1479
    window_warning (WinDestroyCursor);
 
1480
}
 
1481
 
 
1482
static void
 
1483
win_show_cursor (HWND client, BOOL showp)
 
1484
{
 
1485
  if (!WinShowCursor (client, showp))
 
1486
    window_warning (WinShowCursor);
 
1487
}
 
1488
 
 
1489
static void
 
1490
recreate_cursor (window_t * window)
 
1491
{
 
1492
  win_create_cursor ((WINDOW_CLIENT (window)),
 
1493
                     (WINDOW_CURSOR_X (window)),
 
1494
                     (WINDOW_CURSOR_Y (window)),
 
1495
                     (WINDOW_CURSOR_WIDTH (window)),
 
1496
                     (WINDOW_CURSOR_HEIGHT (window)),
 
1497
                     (WINDOW_CURSOR_STYLE (window)),
 
1498
                     0);
 
1499
  (WINDOW_CURSOR_CREATEDP (window)) = 1;
 
1500
  if (WINDOW_CURSOR_ENABLEDP (window))
 
1501
    win_show_cursor ((WINDOW_CLIENT (window)), TRUE);
 
1502
}
 
1503
 
 
1504
static void
 
1505
activate_cursor (window_t * window)
 
1506
{
 
1507
  if ((WINDOW_CURSOR_CREATEDP (window)) && (WINDOW_CURSOR_ENABLEDP (window)))
 
1508
    win_show_cursor ((WINDOW_CLIENT (window)), TRUE);
 
1509
}
 
1510
 
 
1511
static void
 
1512
deactivate_cursor (window_t * window)
 
1513
{
 
1514
  if ((WINDOW_CURSOR_CREATEDP (window)) && (WINDOW_CURSOR_ENABLEDP (window)))
 
1515
    win_show_cursor ((WINDOW_CLIENT (window)), FALSE);
 
1516
}
 
1517
 
 
1518
static void
 
1519
maybe_activate_cursor (ps_t * ps)
 
1520
{
 
1521
  if ((PS_VISUAL_TYPE (ps)) == pst_window)
 
1522
    activate_cursor (PS_VISUAL (ps));
 
1523
}
 
1524
 
 
1525
static void
 
1526
maybe_deactivate_cursor (ps_t * ps)
 
1527
{
 
1528
  if ((PS_VISUAL_TYPE (ps)) == pst_window)
 
1529
    deactivate_cursor (PS_VISUAL (ps));
 
1530
}
 
1531
 
 
1532
/* Presentation Spaces */
 
1533
 
 
1534
static ps_t *
 
1535
create_memory_ps (qid_t qid)
 
1536
{
 
1537
  HDC hdc = (DevOpenDC (pm_hab, OD_MEMORY, "*", 0, 0, NULLHANDLE));
 
1538
  if (hdc == DEV_ERROR)
 
1539
    window_error (DevOpenDC);
 
1540
  return (create_ps (pst_memory, hdc, qid));
 
1541
}
 
1542
 
 
1543
static void
 
1544
destroy_memory_ps (ps_t * ps)
 
1545
{
 
1546
  HDC hdc = (get_ps_device (PS_HANDLE (ps)));
 
1547
  bitmap_t * bitmap = (PS_VISUAL (ps));
 
1548
  destroy_ps (ps);
 
1549
  if ((hdc != NULLHANDLE) && ((DevCloseDC (hdc)) == DEV_ERROR))
 
1550
    window_warning (DevCloseDC);
 
1551
  if (bitmap != 0)
 
1552
    destroy_bitmap (bitmap);
 
1553
}
 
1554
 
 
1555
static bitmap_t *
 
1556
create_bitmap (ps_t * ps, USHORT width, USHORT height)
 
1557
{
 
1558
  HPS hps = (PS_HANDLE (ps));
 
1559
  HDC hdc = (get_ps_device (hps));
 
1560
  BITMAPINFOHEADER2 header;
 
1561
  HBITMAP hbm;
 
1562
  bitmap_t * bitmap;
 
1563
 
 
1564
  memset ((& header), 0, (sizeof (header)));
 
1565
  (header . cbFix) = (sizeof (header));
 
1566
  (header . cx) = width;
 
1567
  (header . cy) = height;
 
1568
  (header . cPlanes) = (get_device_capability (hdc, CAPS_COLOR_PLANES));
 
1569
  (header . cBitCount) = (get_device_capability (hdc, CAPS_COLOR_BITCOUNT));
 
1570
  hbm = (GpiCreateBitmap (hps, (& header), 0, 0, 0));
 
1571
  if (hbm == GPI_ERROR)
 
1572
    window_error (GpiCreateBitmap);
 
1573
  bitmap = (OS_malloc (sizeof (bitmap_t)));
 
1574
  (BITMAP_ID (bitmap)) = (allocate_id ((& bid_table), bitmap));
 
1575
  (BITMAP_QID (bitmap)) = (PS_QID (ps));
 
1576
  (BITMAP_HANDLE (bitmap)) = hbm;
 
1577
  return (bitmap);
 
1578
}
 
1579
 
 
1580
static void
 
1581
destroy_bitmap (bitmap_t * bitmap)
 
1582
{
 
1583
  if (!GpiDeleteBitmap (BITMAP_HANDLE (bitmap)))
 
1584
    window_warning (GpiDeleteBitmap);
 
1585
  deallocate_id ((& bid_table), (BITMAP_ID (bitmap)));
 
1586
  OS_free (bitmap);
 
1587
}
 
1588
 
 
1589
static bitmap_t *
 
1590
ps_set_bitmap (ps_t * ps, bitmap_t * bitmap)
 
1591
{
 
1592
  bitmap_t * previous_bitmap = (PS_VISUAL (ps));
 
1593
  if ((GpiSetBitmap ((PS_HANDLE (ps)),
 
1594
                     ((bitmap == 0) ? 0 : (BITMAP_HANDLE (bitmap)))))
 
1595
      == HBM_ERROR)
 
1596
    window_error (GpiSetBitmap);
 
1597
  (PS_VISUAL (ps)) = bitmap;
 
1598
  return (previous_bitmap);
 
1599
}
 
1600
 
 
1601
static void
 
1602
ps_bitblt (ps_t * target, ps_t * source, LONG npoints, PPOINTL points,
 
1603
           LONG rop, ULONG options)
 
1604
{
 
1605
  maybe_deactivate_cursor (target);
 
1606
  if ((GpiBitBlt ((PS_HANDLE (target)), (PS_HANDLE (source)), npoints, points,
 
1607
                  rop, options))
 
1608
      == GPI_ERROR)
 
1609
    window_warning (GpiBitBlt);
 
1610
  maybe_activate_cursor (target);
 
1611
}
 
1612
 
 
1613
static void
 
1614
ps_draw_text (ps_t * ps, short x, short y,
 
1615
              const char * data, unsigned short size)
 
1616
{
 
1617
  HPS hps = (PS_HANDLE (ps));
 
1618
  PLONG increments = (PS_CHAR_INCREMENTS (ps));
 
1619
  POINTL ptl;
 
1620
  (ptl . x) = x;
 
1621
  (ptl . y) = y;
 
1622
  maybe_deactivate_cursor (ps);
 
1623
  if (size <= 512)
 
1624
    {
 
1625
      if (increments == 0)
 
1626
        GpiCharStringAt (hps, (& ptl), size, ((char *) data));
 
1627
      else
 
1628
        GpiCharStringPosAt (hps, (& ptl), 0, CHS_VECTOR, size, ((char *) data),
 
1629
                            increments);
 
1630
    }
 
1631
  else
 
1632
    {
 
1633
      const char * scan = data;
 
1634
      GpiMove (hps, (& ptl));
 
1635
      while (size > 0)
 
1636
        {
 
1637
          unsigned short n = ((size > 512) ? 512 : size);
 
1638
          if (increments == 0)
 
1639
            GpiCharString (hps, n, ((char *) scan));
 
1640
          else
 
1641
            GpiCharStringPos (hps, 0, CHS_VECTOR, n, ((char *) scan),
 
1642
                              increments);
 
1643
          size -= n;
 
1644
          scan += n;
 
1645
        }
 
1646
    }
 
1647
  maybe_activate_cursor (ps);
 
1648
}
 
1649
 
 
1650
static unsigned short
 
1651
ps_text_width (ps_t * ps, const char * data, unsigned short size)
 
1652
{
 
1653
  if ((PS_CHAR_INCREMENTS (ps)) == 0)
 
1654
    {
 
1655
      POINTL points [TXTBOX_COUNT];
 
1656
      if (!GpiQueryTextBox ((PS_HANDLE (ps)), size, ((char *) data),
 
1657
                            TXTBOX_COUNT, points))
 
1658
        window_error (GpiQueryTextBox);
 
1659
      return ((points [TXTBOX_CONCAT]) . x);
 
1660
    }
 
1661
  else
 
1662
    return (size * ((PS_CHAR_INCREMENTS (ps)) [0]));
 
1663
}
 
1664
 
 
1665
static void
 
1666
ps_clear (ps_t * ps, short xl, short xh, short yl, short yh)
 
1667
{
 
1668
  RECTL rectl;
 
1669
  (rectl . xLeft) = xl;
 
1670
  (rectl . xRight) = xh;
 
1671
  (rectl . yBottom) = yl;
 
1672
  (rectl . yTop) = yh;
 
1673
  maybe_deactivate_cursor (ps);
 
1674
  if (!WinFillRect ((PS_HANDLE (ps)), (&rectl), (PS_BACKGROUND_COLOR (ps))))
 
1675
    window_warning (WinFillRect);
 
1676
  maybe_activate_cursor (ps);
 
1677
}
 
1678
 
 
1679
static COLOR
 
1680
ps_get_foreground_color (ps_t * ps)
 
1681
{
 
1682
  return (PS_FOREGROUND_COLOR (ps));
 
1683
}
 
1684
 
 
1685
static COLOR
 
1686
ps_get_background_color (ps_t * ps)
 
1687
{
 
1688
  return (PS_BACKGROUND_COLOR (ps));
 
1689
}
 
1690
 
 
1691
static void
 
1692
ps_set_colors (ps_t * ps, COLOR foreground, COLOR background)
 
1693
{
 
1694
  if (!GpiSetColor ((PS_HANDLE (ps)), foreground))
 
1695
    window_warning (GpiSetColor);
 
1696
  if (!GpiSetMix ((PS_HANDLE (ps)), FM_OVERPAINT))
 
1697
    window_warning (GpiSetMix);
 
1698
  if (!GpiSetBackColor ((PS_HANDLE (ps)), background))
 
1699
    window_warning (GpiSetBackColor);
 
1700
  if (!GpiSetBackMix ((PS_HANDLE (ps)), BM_OVERPAINT))
 
1701
    window_warning (GpiSetBackMix);
 
1702
  (PS_FOREGROUND_COLOR (ps)) = foreground;
 
1703
  (PS_BACKGROUND_COLOR (ps)) = background;
 
1704
}
 
1705
 
 
1706
static void
 
1707
ps_move_gcursor (ps_t * ps, short x, short y)
 
1708
{
 
1709
  POINTL ptl;
 
1710
  (ptl . x) = x;
 
1711
  (ptl . y) = y;
 
1712
  if (!GpiMove ((PS_HANDLE (ps)), (& ptl)))
 
1713
    window_warning (GpiMove);
 
1714
}
 
1715
 
 
1716
static void
 
1717
ps_draw_line (ps_t * ps, short x, short y)
 
1718
{
 
1719
  POINTL ptl;
 
1720
  (ptl . x) = x;
 
1721
  (ptl . y) = y;
 
1722
  if ((GpiLine ((PS_HANDLE (ps)), (& ptl))) == GPI_ERROR)
 
1723
    window_warning (GpiLine);
 
1724
}
 
1725
 
 
1726
static void
 
1727
ps_draw_point (ps_t * ps, short x, short y)
 
1728
{
 
1729
  POINTL ptl;
 
1730
  (ptl . x) = x;
 
1731
  (ptl . y) = y;
 
1732
  if ((GpiSetPel ((PS_HANDLE (ps)), (& ptl))) == GPI_ERROR)
 
1733
    window_warning (GpiSetPel);
 
1734
}
 
1735
 
 
1736
static void
 
1737
ps_poly_line (ps_t * ps, unsigned long npoints, PPOINTL points)
 
1738
{
 
1739
  if ((GpiPolyLine ((PS_HANDLE (ps)), npoints, points)) == GPI_ERROR)
 
1740
    window_warning (GpiPolyLine);
 
1741
}
 
1742
 
 
1743
static void
 
1744
ps_poly_line_disjoint (ps_t * ps, unsigned long npoints, PPOINTL points)
 
1745
{
 
1746
  if ((GpiPolyLineDisjoint ((PS_HANDLE (ps)), npoints, points))
 
1747
      == GPI_ERROR)
 
1748
    window_warning (GpiPolyLineDisjoint);
 
1749
}
 
1750
 
 
1751
static void
 
1752
ps_set_line_type (ps_t * ps, LONG type)
 
1753
{
 
1754
  if (!GpiSetLineType ((PS_HANDLE (ps)), type))
 
1755
    window_warning (GpiSetLineType);
 
1756
}
 
1757
 
 
1758
static void
 
1759
ps_set_mix (ps_t * ps, LONG mix)
 
1760
{
 
1761
  if (!GpiSetMix ((PS_HANDLE (ps)), mix))
 
1762
    window_warning (GpiSetMix);
 
1763
}
 
1764
 
 
1765
static void
 
1766
ps_query_caps (ps_t * ps, LONG start, LONG count, PLONG values)
 
1767
{
 
1768
  HDC hdc = (get_ps_device (PS_HANDLE (ps)));
 
1769
  if (hdc == NULLHANDLE)
 
1770
    window_error (GpiQueryDevice);
 
1771
  if (!DevQueryCaps (hdc, start, count, values))
 
1772
    window_error (DevQueryCaps);
 
1773
}
 
1774
 
 
1775
static void
 
1776
ps_reset_clip_rectangle (ps_t * ps)
 
1777
{
 
1778
  if (!GpiSetClipPath ((PS_HANDLE (ps)), 0, SCP_RESET))
 
1779
    window_error (GpiSetClipPath);
 
1780
}
 
1781
 
 
1782
static void
 
1783
ps_set_clip_rectangle (ps_t * ps, short xl, short xh, short yl, short yh)
 
1784
{
 
1785
  HPS hps = (PS_HANDLE (ps));
 
1786
  ps_reset_clip_rectangle (ps);
 
1787
  if (!GpiBeginPath (hps, 1))
 
1788
    window_error (GpiBeginPath);
 
1789
  {
 
1790
    POINTL points [4];
 
1791
    ((points[0]) . x) = xl;
 
1792
    ((points[0]) . y) = yl;
 
1793
    ((points[1]) . x) = xl;
 
1794
    ((points[1]) . y) = yh;
 
1795
    ((points[2]) . x) = xh;
 
1796
    ((points[2]) . y) = yh;
 
1797
    ((points[3]) . x) = xh;
 
1798
    ((points[3]) . y) = yl;
 
1799
    if (!GpiMove (hps, (&points[3])))
 
1800
      window_warning (GpiMove);
 
1801
    if ((GpiPolyLine (hps, 4, points)) == GPI_ERROR)
 
1802
      window_warning (GpiPolyLine);
 
1803
  }
 
1804
  if (!GpiEndPath (hps))
 
1805
    window_error (GpiEndPath);
 
1806
  if (!GpiSetClipPath (hps, 1, (SCP_AND | SCP_INCL)))
 
1807
    window_error (GpiSetClipPath);
 
1808
}
 
1809
 
 
1810
static void
 
1811
get_bitmap_parameters (bitmap_t * bitmap, PBITMAPINFOHEADER params)
 
1812
{
 
1813
  if (!GpiQueryBitmapParameters ((BITMAP_HANDLE (bitmap)), params))
 
1814
    window_error (GpiQueryBitmapParameters);
 
1815
}
 
1816
 
 
1817
static unsigned long
 
1818
ps_get_bitmap_bits (ps_t * ps, unsigned long start, unsigned long length,
 
1819
                    PBYTE data, PBITMAPINFO2 info)
 
1820
{
 
1821
  LONG r = (GpiQueryBitmapBits ((PS_HANDLE (ps)), start, length, data, info));
 
1822
  if (r < 0)
 
1823
    window_error (GpiQueryBitmapBits);
 
1824
  return (r);
 
1825
}
 
1826
 
 
1827
static unsigned long
 
1828
ps_set_bitmap_bits (ps_t * ps, unsigned long start, unsigned long length,
 
1829
                    PBYTE data, PBITMAPINFO2 info)
 
1830
{
 
1831
  LONG r = (GpiSetBitmapBits ((PS_HANDLE (ps)), start, length, data, info));
 
1832
  if (r < 0)
 
1833
    window_error (GpiSetBitmapBits);
 
1834
  return (r);
 
1835
}
 
1836
 
 
1837
/* Helper Procedures */
 
1838
 
 
1839
static HDC
 
1840
get_ps_device (HPS hps)
 
1841
{
 
1842
  HDC hdc = (GpiQueryDevice (hps));
 
1843
  if (hdc == HDC_ERROR)
 
1844
    window_error (GpiQueryDevice);
 
1845
  return (hdc);
 
1846
}
 
1847
 
 
1848
static LONG
 
1849
get_device_capability (HDC hdc, LONG index)
 
1850
{
 
1851
  LONG result;
 
1852
  if (!DevQueryCaps (hdc, index, 1, (& result)))
 
1853
    window_error (DevQueryCaps);
 
1854
  return (result);
 
1855
}
 
1856
 
 
1857
static ps_t *
 
1858
create_ps (pst_t type, HDC hdc, qid_t qid)
 
1859
{
 
1860
  ps_t * ps = (OS_malloc (sizeof (ps_t)));
 
1861
  SIZEL sizel;
 
1862
  HPS hps;
 
1863
  (sizel . cx) = 0;
 
1864
  (sizel . cy) = 0;
 
1865
  hps = (GpiCreatePS (pm_hab, hdc, (& sizel),
 
1866
                      (PU_PELS | GPIF_DEFAULT | GPIT_MICRO | GPIA_ASSOC)));
 
1867
  if (hps == 0)
 
1868
    window_error (GpiCreatePS);
 
1869
  /* Put color table in RGB mode so we can specify colors
 
1870
     directly in RGB values rather than as indices.  */
 
1871
  if (!GpiCreateLogColorTable (hps, LCOL_PURECOLOR, LCOLF_RGB, 0, 0, 0))
 
1872
    window_warning (GpiCreateLogColorTable);
 
1873
  (PS_HANDLE (ps)) = hps;
 
1874
  (PS_ID (ps)) = (allocate_id ((& psid_table), ps));
 
1875
  (PS_QID (ps)) = qid;
 
1876
  (PS_VISUAL_TYPE (ps)) = type;
 
1877
  (PS_VISUAL (ps)) = 0;
 
1878
  (PS_CHAR_INCREMENTS (ps)) = 0;
 
1879
  ps_set_colors (ps, RGB_BLACK, RGB_WHITE);
 
1880
  return (ps);
 
1881
}
 
1882
 
 
1883
static void
 
1884
destroy_ps (ps_t * ps)
 
1885
{
 
1886
  if ((PS_CHAR_INCREMENTS (ps)) != 0)
 
1887
    OS_free (PS_CHAR_INCREMENTS (ps));
 
1888
  if (!GpiDestroyPS (PS_HANDLE (ps)))
 
1889
    window_warning (GpiDestroyPS);
 
1890
  deallocate_id ((& psid_table), (PS_ID (ps)));
 
1891
  OS_free (ps);
 
1892
}
 
1893
 
 
1894
/* Clipboard */
 
1895
 
 
1896
static void
 
1897
clipboard_write_text (qid_t qid, const char * text)
 
1898
{
 
1899
  unsigned int len = ((strlen (text)) + 1);
 
1900
  PVOID shared_copy;
 
1901
  int copy_used = 0;
 
1902
 
 
1903
  STD_API_CALL
 
1904
    (dos_alloc_shared_mem,
 
1905
     ((&shared_copy), 0, len,
 
1906
      (PAG_COMMIT | PAG_READ | PAG_WRITE | OBJ_GIVEABLE)));
 
1907
  FASTCOPY (text, ((char *) shared_copy), len);
 
1908
 
 
1909
  if (WinOpenClipbrd (pm_hab))
 
1910
    {
 
1911
      if (WinEmptyClipbrd (pm_hab))
 
1912
        copy_used
 
1913
          = (WinSetClipbrdData
 
1914
             (pm_hab, ((ULONG) shared_copy), CF_TEXT, CFI_POINTER));
 
1915
      (void) WinCloseClipbrd (pm_hab);
 
1916
    }
 
1917
  if (!copy_used)
 
1918
    STD_API_CALL (dos_free_mem, (shared_copy));
 
1919
}
 
1920
 
 
1921
static const char *
 
1922
clipboard_read_text (qid_t qid)
 
1923
{
 
1924
  char * result = 0;
 
1925
  if (WinOpenClipbrd (pm_hab))
 
1926
    {
 
1927
      const char * shared_copy
 
1928
        = ((const char *) (WinQueryClipbrdData (pm_hab, CF_TEXT)));
 
1929
      if (shared_copy != 0)
 
1930
        {
 
1931
          unsigned int len = ((strlen (shared_copy)) + 1);
 
1932
          result = (OS_malloc (len));
 
1933
          FASTCOPY (shared_copy, result, len);
 
1934
        }
 
1935
      (void) WinCloseClipbrd (pm_hab);
 
1936
    }
 
1937
  return (result);
 
1938
}
 
1939
 
 
1940
/* Menus */
 
1941
 
 
1942
static HWND
 
1943
menu_create (qid_t qid, HWND owner, USHORT style, USHORT id)
 
1944
{
 
1945
  return
 
1946
    (WinCreateWindow (owner,    /* parent window */
 
1947
                      WC_MENU,  /* class name */
 
1948
                      "",       /* window text */
 
1949
                      style,    /* window style */
 
1950
                      0, 0, 0, 0, /* size and position */
 
1951
                      owner,    /* owner window */
 
1952
                      HWND_TOP, /* sibling window */
 
1953
                      id,       /* ID */
 
1954
                      0,        /* control data */
 
1955
                      0         /* presentation parameters */
 
1956
                      ));
 
1957
}
 
1958
 
 
1959
static BOOL
 
1960
menu_destroy (qid_t qid, HWND menu)
 
1961
{
 
1962
  return (WinDestroyWindow (menu));
 
1963
}
 
1964
 
 
1965
static USHORT
 
1966
menu_insert_item (qid_t qid, HWND menu, USHORT position, USHORT style,
 
1967
                  USHORT attributes, USHORT id, HWND submenu, char * text)
 
1968
{
 
1969
  MENUITEM item;
 
1970
  (item . iPosition) = position;
 
1971
  (item . afStyle) = style;
 
1972
  (item . afAttribute) = attributes;
 
1973
  (item . id) = id;
 
1974
  (item . hwndSubMenu) = submenu;
 
1975
  (item . hItem) = 0;
 
1976
  return (SHORT1FROMMR (WinSendMsg (menu, MM_INSERTITEM,
 
1977
                                    (MPFROMP (&item)),
 
1978
                                    (MPFROMP (text)))));
 
1979
}
 
1980
 
 
1981
static USHORT
 
1982
menu_remove_item (qid_t qid, HWND menu, USHORT id, USHORT submenup,
 
1983
                  USHORT deletep)
 
1984
{
 
1985
  return (SHORT1FROMMR (WinSendMsg (menu,
 
1986
                                    (deletep ? MM_DELETEITEM : MM_REMOVEITEM),
 
1987
                                    (MPFROM2SHORT (id, submenup)),
 
1988
                                    0)));
 
1989
}
 
1990
 
 
1991
static PMENUITEM
 
1992
menu_get_item (qid_t qid, HWND menu, USHORT id, USHORT submenup)
 
1993
{
 
1994
  PMENUITEM item = (OS_malloc (sizeof (MENUITEM)));
 
1995
  if (LONGFROMMR (WinSendMsg (menu, MM_QUERYITEM,
 
1996
                              (MPFROM2SHORT (id, submenup)),
 
1997
                              (MPFROMP (item)))))
 
1998
    return (item);
 
1999
  OS_free (item);
 
2000
  return (0);
 
2001
}
 
2002
 
 
2003
static USHORT
 
2004
menu_n_items (qid_t qid, HWND menu)
 
2005
{
 
2006
  return (SHORT1FROMMR (WinSendMsg (menu, MM_QUERYITEMCOUNT, 0, 0)));
 
2007
}
 
2008
 
 
2009
static USHORT
 
2010
menu_nth_item_id (qid_t qid, HWND menu, USHORT position)
 
2011
{
 
2012
  return (SHORT1FROMMR (WinSendMsg (menu, MM_ITEMIDFROMPOSITION,
 
2013
                                    (MPFROMSHORT (position)),
 
2014
                                    0)));
 
2015
}
 
2016
 
 
2017
static USHORT
 
2018
menu_get_item_attributes (qid_t qid, HWND menu, USHORT id, USHORT submenup,
 
2019
                          USHORT mask)
 
2020
{
 
2021
  return (SHORT1FROMMR (WinSendMsg (menu, MM_QUERYITEMATTR,
 
2022
                                    (MPFROM2SHORT (id, submenup)),
 
2023
                                    (MPFROMSHORT (mask)))));
 
2024
}
 
2025
 
 
2026
static BOOL
 
2027
menu_set_item_attributes (qid_t qid, HWND menu, USHORT id, USHORT submenup,
 
2028
                          USHORT mask, USHORT attributes)
 
2029
{
 
2030
  return (LONGFROMMR (WinSendMsg (menu, MM_SETITEMATTR,
 
2031
                                  (MPFROM2SHORT (id, submenup)),
 
2032
                                  (MPFROM2SHORT (mask, attributes)))));
 
2033
}
 
2034
 
 
2035
static HWND
 
2036
window_load_menu (window_t * window, HMODULE module, ULONG id)
 
2037
{
 
2038
  return (WinLoadMenu ((WINDOW_FRAME (window)), module, id));
 
2039
}
 
2040
 
 
2041
static BOOL
 
2042
window_popup_menu (qid_t qid, HWND parent, HWND owner, HWND menu,
 
2043
                   LONG x, LONG y, LONG id, ULONG options)
 
2044
{
 
2045
  return (WinPopupMenu (parent, owner, menu, x, y, id, options));
 
2046
}
 
2047
 
 
2048
/* Fonts */
 
2049
 
 
2050
static font_metrics_t *
 
2051
ps_get_font_metrics (ps_t * ps)
 
2052
{
 
2053
  font_metrics_t * metrics = (OS_malloc (sizeof (font_metrics_t)));
 
2054
  FONTMETRICS fm;
 
2055
  if (!GpiQueryFontMetrics ((PS_HANDLE (ps)), (sizeof (fm)), (& fm)))
 
2056
    window_error (GpiQueryFontMetrics);
 
2057
  (FONT_METRICS_WIDTH (metrics)) = (fm . lMaxCharInc);
 
2058
  (FONT_METRICS_HEIGHT (metrics)) = (fm . lMaxBaselineExt);
 
2059
  (FONT_METRICS_DESCENDER (metrics)) = (fm . lMaxDescender);
 
2060
  return (metrics);
 
2061
}
 
2062
 
 
2063
static font_metrics_t *
 
2064
ps_set_font_internal (ps_t * ps, unsigned short id, const char * spec)
 
2065
{
 
2066
  return ((ps_set_font (ps, id, spec)) ? (ps_get_font_metrics (ps)) : 0);
 
2067
}
 
2068
 
 
2069
static const char *
 
2070
window_font_dialog (window_t * window, const char * title)
 
2071
{
 
2072
  ps_t * ps = (WINDOW_CLIENT_PS (window));
 
2073
  HPS hps = (PS_HANDLE (ps));
 
2074
  FONTDLG info;
 
2075
  char name_buffer [FACESIZE];
 
2076
  HWND result;
 
2077
 
 
2078
  memset ((&info), 0, (sizeof (info)));
 
2079
  (name_buffer[0]) = '\0';
 
2080
  (info . cbSize) = (sizeof (info));
 
2081
  (info . hpsScreen) = hps;
 
2082
  (info . pszTitle) = ((PSZ) title);
 
2083
  (info . fl) = (FNTS_FIXEDWIDTHONLY | FNTS_CENTER); /* FNTS_INITFROMFATTRS */
 
2084
  (info . pszFamilyname) = name_buffer;
 
2085
  (info . usFamilyBufLen) = (sizeof (name_buffer));
 
2086
  /* Because our PS is in RGB mode, the RGB color specs we are using
 
2087
     are useless.  It's undocumented, but only indexed colors work in
 
2088
     the font dialog, so we must override with indexes.  */
 
2089
  (info . clrFore) = CLR_BLACK; /* (PS_FOREGROUND_COLOR (ps)) */
 
2090
  (info . clrBack) = CLR_WHITE; /* (PS_BACKGROUND_COLOR (ps)) */
 
2091
  {
 
2092
    FONTMETRICS fm;
 
2093
    if (GpiQueryFontMetrics (hps, (sizeof (fm)), (&fm)))
 
2094
      {
 
2095
        strcpy (name_buffer, (fm . szFamilyname));
 
2096
        (info . usWeight) = (fm . usWeightClass);
 
2097
        (info . usWidth) = (fm . usWidthClass);
 
2098
        (info . fxPointSize)
 
2099
          = (MAKEFIXED (((fm . sNominalPointSize) / 10), 0));
 
2100
        (info . flStyle) = (fm . fsSelection);
 
2101
        copy_fontmetrics_to_fattrs ((&fm), (& (info . fAttrs)));
 
2102
#if 0
 
2103
        /* The following, for some unknown reason, causes the
 
2104
           selection of incorrect fonts: */
 
2105
        (info . fl) |= FNTS_INITFROMFATTRS;
 
2106
#endif
 
2107
      }
 
2108
  }
 
2109
  result = (WinFontDlg (HWND_DESKTOP, (WINDOW_CLIENT (window)), (&info)));
 
2110
  if ((result == NULLHANDLE) || ((info . lReturn) != DID_OK))
 
2111
    return (0);
 
2112
  {
 
2113
    PSZ face_name;
 
2114
    const char * font_spec;
 
2115
    {
 
2116
      FACENAMEDESC desc;
 
2117
      ULONG face_name_length;
 
2118
      char face_name_dummy [1];
 
2119
      memset ((&desc), 0, (sizeof (desc)));
 
2120
      (desc . usSize) = (sizeof (desc));
 
2121
      (desc . usWeightClass) = (info . usWeight);
 
2122
      (desc . usWidthClass) = (info . usWidth);
 
2123
      (desc . flOptions) = (info . flType);
 
2124
      face_name = face_name_dummy;
 
2125
      face_name_length
 
2126
        = (GpiQueryFaceString (hps, (info . pszFamilyname), (&desc),
 
2127
                               0, face_name));
 
2128
      if (face_name_length == GPI_ERROR)
 
2129
        {
 
2130
          window_warning (GpiQueryFaceString);
 
2131
          return (0);
 
2132
        }
 
2133
      face_name = (OS_malloc (face_name_length));
 
2134
      face_name_length
 
2135
        = (GpiQueryFaceString (hps, (info . pszFamilyname), (&desc),
 
2136
                               face_name_length, face_name));
 
2137
      if (face_name_length == GPI_ERROR)
 
2138
        {
 
2139
          OS_free (face_name);
 
2140
          window_warning (GpiQueryFaceString);
 
2141
          return (0);
 
2142
        }
 
2143
    }
 
2144
    font_spec = (unparse_font_spec (face_name,
 
2145
                                    ((FIXEDINT (info . fxPointSize)) * 10),
 
2146
                                    (info . flStyle)));
 
2147
    OS_free (face_name);
 
2148
    return (font_spec);
 
2149
  }
 
2150
}
 
2151
 
 
2152
/* Helper Procedures */
 
2153
 
 
2154
static int
 
2155
ps_set_font (ps_t * ps, unsigned short id, const char * spec)
 
2156
{
 
2157
  PSZ name = 0;
 
2158
  LONG size;
 
2159
  USHORT selection;
 
2160
  if (!parse_font_spec (spec, (& name), (& size), (& selection)))
 
2161
    return (0);
 
2162
  if (!ps_set_font_1 (ps, name, size, selection, id))
 
2163
    {
 
2164
      OS_free (name);
 
2165
      return (0);
 
2166
    }
 
2167
  {
 
2168
    FONTMETRICS fm;
 
2169
    if (!GpiQueryFontMetrics ((PS_HANDLE (ps)), (sizeof (fm)), (& fm)))
 
2170
      window_error (GpiQueryFontMetrics);
 
2171
    if ((PS_CHAR_INCREMENTS (ps)) != 0)
 
2172
      OS_free (PS_CHAR_INCREMENTS (ps));
 
2173
    (PS_CHAR_INCREMENTS (ps))
 
2174
      = ((((fm . fsDefn) & FM_DEFN_OUTLINE) != 0)
 
2175
         ? (ps_make_char_increments (fm . lMaxCharInc))
 
2176
         : 0);
 
2177
  }
 
2178
  return (1);
 
2179
}
 
2180
 
 
2181
static int
 
2182
ps_set_font_1 (ps_t * ps, PSZ name, LONG size, USHORT selection, LONG id)
 
2183
{
 
2184
  HPS hps = (PS_HANDLE (ps));
 
2185
  LONG nfonts;
 
2186
  ULONG index;
 
2187
  PFONTMETRICS pfm;
 
2188
 
 
2189
  nfonts = 0;
 
2190
  nfonts = (GpiQueryFonts (hps,
 
2191
                           (QF_PUBLIC | QF_PRIVATE),
 
2192
                           name,
 
2193
                           (& nfonts),
 
2194
                           (sizeof (FONTMETRICS)),
 
2195
                           0));
 
2196
  if (nfonts == GPI_ALTERROR)
 
2197
    window_error (GpiQueryFonts);
 
2198
  if (nfonts == 0)
 
2199
    return (0);
 
2200
  pfm = (OS_malloc (nfonts * (sizeof (FONTMETRICS))));
 
2201
  if ((GpiQueryFonts (hps,
 
2202
                      (QF_PUBLIC | QF_PRIVATE),
 
2203
                      name,
 
2204
                      (& nfonts),
 
2205
                      (sizeof (FONTMETRICS)),
 
2206
                      pfm))
 
2207
      == GPI_ALTERROR)
 
2208
    window_error (GpiQueryFonts);
 
2209
  {
 
2210
    int result = 0;
 
2211
    /* Choose an image font if one is available.  */
 
2212
    for (index = 0; (index < nfonts); index += 1)
 
2213
      if (((((pfm [index]) . fsType) & FM_TYPE_FIXED) != 0)
 
2214
          && ((((pfm [index]) . fsDefn) & FM_DEFN_OUTLINE) == 0)
 
2215
          && (((pfm [index]) . sNominalPointSize) == size)
 
2216
          && (create_font (hps, id, (& (pfm [index])), selection)))
 
2217
        {
 
2218
          GpiSetCharSet (hps, id);
 
2219
          result = 1;
 
2220
          goto done;
 
2221
        }
 
2222
    /* Otherwise, look for an outline font.  */
 
2223
    for (index = 0; (index < nfonts); index += 1)
 
2224
      if (((((pfm [index]) . fsType) & FM_TYPE_FIXED) != 0)
 
2225
          && ((((pfm [index]) . fsDefn) & FM_DEFN_OUTLINE) != 0)
 
2226
          && (create_font (hps, id, (& (pfm [index])), selection)))
 
2227
        {
 
2228
          GpiSetCharSet (hps, id);
 
2229
          ps_set_font_size (ps, size);
 
2230
          result = 1;
 
2231
          goto done;
 
2232
        }
 
2233
  done:
 
2234
    OS_free (pfm);
 
2235
    return (result);
 
2236
  }
 
2237
}
 
2238
 
 
2239
static int
 
2240
create_font (HPS hps, LONG font_id, PFONTMETRICS pfm, USHORT selection)
 
2241
{
 
2242
  FATTRS fa;
 
2243
  copy_fontmetrics_to_fattrs (pfm, (&fa));
 
2244
  (fa . fsSelection) = selection;
 
2245
  return ((GpiCreateLogFont (hps, 0, font_id, (&fa))) == FONT_MATCH);
 
2246
}
 
2247
 
 
2248
static void
 
2249
copy_fontmetrics_to_fattrs (FONTMETRICS * pfm, FATTRS * pfa)
 
2250
{
 
2251
  (pfa -> usRecordLength) = (sizeof (*pfa));
 
2252
  (pfa -> fsSelection) = (pfm -> fsSelection);
 
2253
  (pfa -> lMatch) = (pfm -> lMatch);
 
2254
  strcpy ((pfa -> szFacename), (pfm -> szFacename));
 
2255
  (pfa -> idRegistry) = (pfm -> idRegistry);
 
2256
  (pfa -> usCodePage) = (pfm -> usCodePage);
 
2257
  (pfa -> fsType) = 0;
 
2258
  if (((pfm -> fsDefn) & FM_DEFN_OUTLINE) != 0)
 
2259
    {
 
2260
      (pfa -> lMaxBaselineExt) = 0;
 
2261
      (pfa -> lAveCharWidth) = 0;
 
2262
      (pfa -> fsFontUse)
 
2263
        = (FATTR_FONTUSE_OUTLINE | FATTR_FONTUSE_TRANSFORMABLE);
 
2264
    }
 
2265
  else
 
2266
    {
 
2267
      (pfa -> lMaxBaselineExt) = (pfm -> lMaxBaselineExt);
 
2268
      (pfa -> lAveCharWidth) = (pfm -> lAveCharWidth);
 
2269
      (pfa -> fsFontUse) = 0;
 
2270
    }
 
2271
}
 
2272
 
 
2273
static void
 
2274
ps_set_font_size (ps_t * ps, LONG size)
 
2275
{
 
2276
  POINTL ptl [2];
 
2277
 
 
2278
  ((ptl[0]) . x) = 0;
 
2279
  ((ptl[0]) . y) = 0;
 
2280
  {
 
2281
    LONG xres;
 
2282
    ps_query_caps (ps, CAPS_HORIZONTAL_FONT_RES, 1, (&xres));
 
2283
    ((ptl[1]) . x) = ((((xres * size) << 4) + 360) / 720);
 
2284
  }
 
2285
  {
 
2286
    LONG yres;
 
2287
    ps_query_caps (ps, CAPS_VERTICAL_FONT_RES, 1, (&yres));
 
2288
    ((ptl[1]) . y) = ((((yres * size) << 4) + 360) / 720);
 
2289
  }
 
2290
  if (!GpiConvert ((PS_HANDLE (ps)), CVTC_DEVICE, CVTC_WORLD, 2, ptl))
 
2291
    window_error (GpiConvert);
 
2292
  {
 
2293
    SIZEF s;
 
2294
    (s . cx) = ((((ptl[1]) . x) - ((ptl[0]) . x)) << 12);
 
2295
    (s . cy) = ((((ptl[1]) . y) - ((ptl[0]) . y)) << 12);
 
2296
    if (!GpiSetCharBox ((PS_HANDLE (ps)), (&s)))
 
2297
      window_error (GpiSetCharBox);
 
2298
  }
 
2299
}
 
2300
 
 
2301
static PLONG
 
2302
ps_make_char_increments (LONG increment)
 
2303
{
 
2304
  PLONG increments = (OS_malloc ((sizeof (LONG)) * 512));
 
2305
  unsigned int index;
 
2306
  for (index = 0; (index < 512); index += 1)
 
2307
    (increments[index]) = increment;
 
2308
  return (increments);
 
2309
}
 
2310
 
 
2311
static struct font_selection
 
2312
{
 
2313
  const char * name;
 
2314
  unsigned int selector;
 
2315
} font_selections [] =
 
2316
{
 
2317
  { ".bold", FATTR_SEL_BOLD },
 
2318
  { ".italic", FATTR_SEL_ITALIC },
 
2319
  { ".outline", FATTR_SEL_OUTLINE },
 
2320
  { ".strikeout", FATTR_SEL_STRIKEOUT },
 
2321
  { ".underscore", FATTR_SEL_UNDERSCORE },
 
2322
  { 0, 0 }
 
2323
};
 
2324
 
 
2325
static int
 
2326
parse_font_spec (const char * spec,
 
2327
                 PSZ * pname, LONG * psize, USHORT * pselection)
 
2328
{
 
2329
  const char * scan = spec;
 
2330
  unsigned int size = 0;
 
2331
  unsigned int selection = 0;
 
2332
  while (('0' <= (*scan)) && ((*scan) <= '9'))
 
2333
    size = ((size * 10) + ((*scan++) - '0'));
 
2334
  if (size == 0)
 
2335
    return (0);
 
2336
  while (1)
 
2337
    {
 
2338
      struct font_selection * selections = font_selections;
 
2339
      unsigned int name_length;
 
2340
      while (1)
 
2341
        {
 
2342
          if ((selections -> name) == 0)
 
2343
            goto no_more_selections;
 
2344
          name_length = (strlen (selections -> name));
 
2345
          if ((strncmp (scan, (selections -> name), name_length)) == 0)
 
2346
            {
 
2347
              selection |= (selections -> selector);
 
2348
              scan += name_length;
 
2349
              break;
 
2350
            }
 
2351
          selections += 1;
 
2352
        }
 
2353
    }
 
2354
 no_more_selections:
 
2355
  if ((*scan++) != '.')
 
2356
    return (0);
 
2357
  (*pname) = (OS_malloc ((strlen (scan)) + 1));
 
2358
  strcpy ((*pname), scan);
 
2359
  (*psize) = (size * 10);
 
2360
  (*pselection) = selection;
 
2361
  return (1);
 
2362
}
 
2363
 
 
2364
static const char *
 
2365
unparse_font_spec (PSZ name, LONG size, USHORT selection)
 
2366
{
 
2367
  char size_buffer [16];
 
2368
  char selection_buffer [16];
 
2369
  struct font_selection * selections = font_selections;
 
2370
  char * result;
 
2371
 
 
2372
  sprintf (size_buffer, "%d", (size / 10));
 
2373
  strcpy (selection_buffer, "");
 
2374
  while (1)
 
2375
    {
 
2376
      if ((selections -> name) == 0)
 
2377
        break;
 
2378
      if ((selection & (selections -> selector)) != 0)
 
2379
        strcat (selection_buffer, (selections -> name));
 
2380
      selections += 1;
 
2381
    }
 
2382
  result
 
2383
    = (OS_malloc ((strlen (size_buffer))
 
2384
                  + (strlen (name))
 
2385
                  + (strlen (selection_buffer))
 
2386
                  + 2));
 
2387
  strcpy (result, size_buffer);
 
2388
  strcat (result, selection_buffer);
 
2389
  strcat (result, ".");
 
2390
  strcat (result, name);
 
2391
  return (result);
 
2392
}
 
2393
 
 
2394
/* Pointers and Icons */
 
2395
 
 
2396
static HPOINTER
 
2397
query_system_pointer (qid_t qid, HWND desktop, LONG id, BOOL copyp)
 
2398
{
 
2399
  return (WinQuerySysPointer (desktop, id, copyp));
 
2400
}
 
2401
 
 
2402
static BOOL
 
2403
set_pointer (qid_t qid, HWND desktop, HPOINTER pointer)
 
2404
{
 
2405
  return (WinSetPointer (desktop, pointer));
 
2406
}
 
2407
 
 
2408
static HPOINTER
 
2409
window_load_pointer (qid_t qid, HWND desktop, HMODULE module, ULONG id)
 
2410
{
 
2411
  return (WinLoadPointer (desktop, module, id));
 
2412
}
 
2413
 
 
2414
static BOOL
 
2415
window_destroy_pointer (qid_t qid, HPOINTER pointer)
 
2416
{
 
2417
  return (WinDestroyPointer (pointer));
 
2418
}
 
2419
 
 
2420
static BOOL
 
2421
window_set_icon (window_t * window, HPOINTER icon)
 
2422
{
 
2423
  return (LONGFROMMR (WinSendMsg ((WINDOW_FRAME (window)), WM_SETICON,
 
2424
                                  (MPFROMLONG (icon)),
 
2425
                                  (MPFROMLONG (0)))));
 
2426
}