~netrek-developers/netrek-client-cow/trunk

« back to all changes in this revision

Viewing changes to win32/mswindow.c

  • Committer: Collin Pruitt
  • Date: 2009-05-12 04:30:09 UTC
  • Revision ID: collinp111@gmail.com-20090512043009-3jsjojoyrk16oass
Initial upload - updated from http://james.tooraweenah.com/darcs/netrek-client-cow/ using darcs (hince the existnace of _darcs), fully patched.

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* mswindow.c
 
2
 * Windowing code for Win32 API (aka Windows NT)
 
3
 * Jonathan Shekter Aug 94
 
4
 * Updates for COW version, Aug 1995
 
5
 * Shawn Collenburg
 
6
 * Lots of stuff, Aug 1996
 
7
 */
 
8
#include "copyright2.h"
 
9
 
 
10
#undef DEBUG
 
11
 
 
12
#define NO_BOOLEAN   //So defs.h doesn't screw us over
 
13
 
 
14
#include <windows.h>
 
15
#include <windowsx.h>
 
16
#include <stdio.h>
 
17
#include "config.h"
 
18
#include "Wlib.h"
 
19
#include "defs.h"
 
20
#include "struct.h"
 
21
#include "data.h"
 
22
#include "xclrs.h"
 
23
#include "teams.bitmap"
 
24
#include "mapcursor.bitmap"
 
25
#include "localcursor.bitmap"
 
26
#include <limits.h>
 
27
#include INC_STRINGS
 
28
 
 
29
#ifdef __BORLANDC__
 
30
   #pragma warn -par    //Turon off "parameter never used..." warning
 
31
#endif
 
32
 
 
33
#undef WHITE
 
34
#undef BLACK
 
35
#undef RED
 
36
#undef GREEN
 
37
#undef YELLOW
 
38
#undef CYAN
 
39
 
 
40
#define WHITE   0
 
41
#define BLACK   1
 
42
#define RED     2
 
43
#define GREEN   3
 
44
#define YELLOW  4
 
45
#define CYAN    5
 
46
#define GREY    6
 
47
 
 
48
#ifdef RACE_COLORS
 
49
#define C_ROM   7
 
50
#define C_KLI   8
 
51
#define C_FED   9
 
52
#define C_ORI   10
 
53
#define C_IND   11
 
54
#endif
 
55
 
 
56
#ifdef RACE_COLORS
 
57
#define COLORS  12
 
58
#else
 
59
#define COLORS  7
 
60
#endif
 
61
 
 
62
#define RaceDefaultOffset (C_ROM - RED)
 
63
 
 
64
 
 
65
#define WIN_EDGE 1   //Width or window border edge
 
66
#define MENU_PAD 4
 
67
#define MENU_BAR 4
 
68
 
 
69
#define WIN_GRAPH       1
 
70
#define WIN_TEXT        2
 
71
#define WIN_MENU        3
 
72
#define WIN_SCROLL      4
 
73
 
 
74
#define MoveTo(dc, x, y) MoveToEx(dc, x, y, NULL);
 
75
 
 
76
// Custom window messages, used for communicating between threads
 
77
#define WM_TERMINATE_WAIT WM_USER
 
78
#define WM_CROSS_THREAD_DESTROY (WM_USER+1)
 
79
 
 
80
#ifndef DEBUG
 
81
#define MAX_SCROLLWINDOW_LINES 100
 
82
#else
 
83
#define MAX_SCROLLWINDOW_LINES 300
 
84
#endif
 
85
//The max # lines a scrollwindow will have
 
86
 
 
87
#define EVENT_Q_SIZE 15
 
88
//The number of events our custom queue will hold
 
89
 
 
90
struct menuItem
 
91
   {
 
92
   char *string;
 
93
   W_Color color;
 
94
   short len;
 
95
   };
 
96
 
 
97
struct stringList
 
98
  {
 
99
  char *string;
 
100
  W_Color color;
 
101
  struct stringList *next;
 
102
  };
 
103
 
 
104
typedef struct tagWindow
 
105
   {
 
106
   HWND hwnd;
 
107
   short type;
 
108
   short border;
 
109
   W_Color BorderColor;
 
110
   short UsingCreatedCursor;
 
111
   HCURSOR cursor;
 
112
   short tiled;
 
113
   struct Icon *TileIcon;
 
114
   short NumItems;
 
115
   struct menuItem *items;
 
116
   struct stringList *strings;
 
117
   short AddedStrings;
 
118
   short TextHeight;
 
119
   short TextWidth;
 
120
   RECT ClipRect;
 
121
   W_Callback HandleKeydown;
 
122
   W_Callback HandleKeyup;
 
123
   W_Callback HandleButton;
 
124
   W_Callback HandleExpose;
 
125
   }
 
126
Window;
 
127
 
 
128
static Window myroot;
 
129
 
 
130
#define FNHEADER\
 
131
   register Window *win;\
 
132
   if (!window)\
 
133
      return(0);\
 
134
   win = (Window *)window
 
135
 
 
136
#define FNHEADER_VOID\
 
137
   register Window *win;\
 
138
   if (!window)\
 
139
      return;\
 
140
   win = (Window *)window
 
141
 
 
142
/******************************* Function prototypes *********************/
 
143
void W_Cleanup(void );
 
144
void GetColors();
 
145
LRESULT PASCAL NetrekWndProc(HWND,UINT,WPARAM,LPARAM);
 
146
unsigned char *X11toCursor(unsigned char *bits, int width, int height);
 
147
void RedrawMenu(Window *win, HDC hdc);
 
148
void RedrawScrolling(Window *win, HDC hdc);
 
149
void ChangeMenuItem(Window *win, int n, char *str, int len, W_Color color);
 
150
void AddToScrolling(Window *win, W_Color color, char *str, int len);
 
151
void DrawBorder(Window *win, HDC hdc);
 
152
unsigned char *X11toDIB(unsigned char *bits, int width, int height);
 
153
unsigned char *X11toDIBAndMirror(unsigned char *bits, int width, int height,
 
154
                                       int outwidth, int outheight);
 
155
int checkGeometry(char *name, int *x, int *y, int *width, int *height);
 
156
void checkParent(char *name, W_Window *parent);
 
157
int checkMapped(char *name);
 
158
char *GetExeDir();
 
159
 
 
160
inline void ResetSysColors(void);
 
161
inline void SetTrekSysColors(void);
 
162
 
 
163
/******************************* Globals ****************************/
 
164
extern HINSTANCE MyInstance;
 
165
char ClassName[] = "NetrekWindow";
 
166
char FontFileName[] = "\\ntfonts2.fon";
 
167
extern int DefaultsLoaded;
 
168
HWND AnyWindow;
 
169
DWORD MainThreadID;
 
170
#ifdef SUPPORT_WIN32S
 
171
extern W_Window console;
 
172
#endif
 
173
 
 
174
int W_FastClear=0;
 
175
W_Font W_BigFont, W_RegularFont;
 
176
W_Font W_HighlightFont, W_UnderlineFont;
 
177
W_Color W_White=WHITE, W_Black=BLACK, W_Red=RED, W_Green=GREEN;
 
178
W_Color W_Yellow=YELLOW, W_Cyan=CYAN, W_Grey=GREY;
 
179
#ifdef RACE_COLORS
 
180
W_Color W_Ind = C_IND, W_Fed = C_FED, W_Rom = C_ROM, W_Kli = C_KLI, W_Ori = C_ORI;
 
181
#endif
 
182
 
 
183
int W_Textwidth=6, W_Textheight=10;
 
184
int forceMono = 0;
 
185
 
 
186
const int SysColorNames[] = { COLOR_BTNFACE, COLOR_BTNTEXT, COLOR_3DFACE,
 
187
                              COLOR_3DDKSHADOW, COLOR_3DHILIGHT };
 
188
DWORD TrekSysColors[] = { 0, 0xffffff, 0, 0xc0c0c0, 0x808080 };
 
189
DWORD SysColors[sizeof(TrekSysColors)];
 
190
 
 
191
HDC GlobalMemDC, GlobalMemDC2;
 
192
HBITMAP GlobalOldMemDCBitmap, GlobalOldMemDC2Bitmap;
 
193
HCURSOR TrekCursor, WarnCursor;
 
194
 
 
195
struct
 
196
   {
 
197
   COLORREF rgb;
 
198
   HBRUSH brush;
 
199
   HPEN pen;
 
200
   HPEN dashedpen;
 
201
   }
 
202
colortable[COLORS] = {
 
203
   { RGB(0xff, 0xff, 0xff), 0, 0, 0}, //White
 
204
   { RGB(0x00, 0x00, 0x00), 0, 0, 0}, //Black
 
205
   { RGB(0xff, 0x5f, 0x5f), 0, 0, 0}, //Red
 
206
   { RGB(0x5f, 0xff, 0x5f), 0, 0, 0}, //Green
 
207
   { RGB(0xff, 0xff, 0x5f), 0, 0, 0}, //Yellow
 
208
   { RGB(0x5f, 0xff, 0xff), 0, 0, 0}, //Cyan
 
209
   { RGB(0xa0, 0xa0, 0xa0), 0, 0, 0}  //Light grey
 
210
#ifdef RACE_COLORS
 
211
   ,
 
212
   { RGB(0xff, 0x5f, 0x5f), 0, 0, 0}, //Rom
 
213
   { RGB(0x5f, 0xff, 0x5f), 0, 0, 0}, //Kli
 
214
   { RGB(0xff, 0xff, 0x5f), 0, 0, 0}, //Fed
 
215
   { RGB(0x5f, 0xff, 0xff), 0, 0, 0}, //Ori
 
216
   { RGB(0xa0, 0xa0, 0xa0), 0, 0, 0}  //Ind
 
217
#endif   
 
218
},
 
219
// Used when we're in fixed-16 color mode - color values altered so that the color
 
220
// mapper picks the proper color. These are "intense" versions of the standard colors
 
221
altcolortable[COLORS] = {
 
222
   { RGB(0xff, 0xff, 0xff), 0, 0, 0}, //White
 
223
   { RGB(0x00, 0x00, 0x00), 0, 0, 0}, //Black
 
224
   { RGB(0xff, 0x00, 0x00), 0, 0, 0}, //Red
 
225
   { RGB(0x00, 0xff, 0x00), 0, 0, 0}, //Green
 
226
   { RGB(0xff, 0xff, 0x00), 0, 0, 0}, //Yellow
 
227
   { RGB(0x00, 0xff, 0xff), 0, 0, 0}, //Cyan
 
228
   { RGB(0xa0, 0xa0, 0xa0), 0, 0, 0}  //Light grey
 
229
#ifdef RACE_COLORS
 
230
   ,
 
231
   { RGB(0xff, 0x00, 0x00), 0, 0, 0}, //Rom
 
232
   { RGB(0x00, 0xff, 0x00), 0, 0, 0}, //Kli
 
233
   { RGB(0xff, 0xff, 0x00), 0, 0, 0}, //Fed
 
234
   { RGB(0x00, 0xff, 0xff), 0, 0, 0}, //Ori
 
235
   { RGB(0xa0, 0xa0, 0xa0), 0, 0, 0}  //Ind
 
236
#endif
 
237
};
 
238
 
 
239
char *colornames[COLORS] = {
 
240
   {"white"},
 
241
   {"black"},
 
242
   {"red"},
 
243
   {"green"},
 
244
   {"yellow"},
 
245
   {"cyan"},
 
246
   {"light grey"}
 
247
#ifdef RACE_COLORS
 
248
  ,
 
249
  {"Rom"},
 
250
  {"Kli"},
 
251
  {"Fed"},
 
252
  {"Ori"},
 
253
  {"Ind"}
 
254
#endif
 
255
};
 
256
 
 
257
HPALETTE NetrekPalette = 0;
 
258
 
 
259
//A structure that the W_Icon type (really a bitmap, not an icon) points to
 
260
struct Icon
 
261
   {
 
262
   HWND hwnd;              //The window this is going into
 
263
   HBITMAP bm;             //The Windows bitmap it has been stored in
 
264
   int x,y;                //The source position in this bitmap
 
265
   int width, height;      //guess...
 
266
   RECT *ClipRectAddr;     //Address of the window clip region
 
267
   };
 
268
 
 
269
#ifndef SCALE_BITMAPS
 
270
#define BIGBITMAP_WIDTH 240
 
271
#define BIGBITMAP_HEIGHT 240
 
272
#else
 
273
static int BIGBITMAP_WIDTH = 240;
 
274
static int BIGBITMAP_HEIGHT = 240;
 
275
#endif
 
276
 
 
277
struct BitmapList
 
278
   {
 
279
   HBITMAP bm;
 
280
   struct BitmapList *next;   //Put these in a LL for later de-allocation
 
281
   };
 
282
 
 
283
struct BitmapList *CurrentBitmap = NULL;
 
284
int bmlCount = 0;
 
285
 
 
286
 
 
287
//Table that we will build use for virtual key code conversion. We can't
 
288
//just let Windows do it as we want to proces  strange things like
 
289
// ^@ or ^# which the standard windows TranslateMessage() / ToAscii()
 
290
//will not do. So, we process VK codes instead, which means we have
 
291
//to manually map the SHIFT key. We create this mapping by asking for
 
292
// the VK + shift state for each ascii char during init.
 
293
 
 
294
//Mapping tables for VK codes to ASCII. We can't just let windows do
 
295
//it as we want strange combinations like ^@, so we build these maps
 
296
//ourselves.
 
297
char VKMap[256];
 
298
char VKShiftMap[256];
 
299
 
 
300
 
 
301
void W_Initialize(char *display)
 
302
   {
 
303
   int i;
 
304
   TEXTMETRIC tm;
 
305
   HBITMAP junk;
 
306
   LOGFONT lf;
 
307
   char FileName[100];
 
308
   WNDCLASS wc;
 
309
   static int InitDone = 0;
 
310
 
 
311
   GetColors();
 
312
 
 
313
   if (InitDone)
 
314
      return;
 
315
   InitDone = -1;
 
316
 
 
317
#ifdef DEBUG
 
318
   printf("Initializing windowing system\n");
 
319
#endif
 
320
 
 
321
   //Register our class
 
322
   wc.style         = CS_NOCLOSE | CS_HREDRAW | CS_VREDRAW;  //Don't allow them to close windows 
 
323
   wc.lpfnWndProc   = NetrekWndProc;
 
324
   wc.cbClsExtra    = 0;
 
325
   wc.cbWndExtra    = sizeof(Window *); //Store Window * in extra space
 
326
   wc.hInstance     = MyInstance;
 
327
   wc.hIcon         = LoadIcon(MyInstance, "main");
 
328
   wc.hCursor       = NULL;                        //We're handling our own cursors
 
329
   wc.hbrBackground = NULL;
 
330
   wc.lpszMenuName  = NULL;
 
331
   wc.lpszClassName = ClassName;
 
332
 
 
333
   RegisterClass(&wc);
 
334
 
 
335
   //Load our cursors - the ones we use from a resource file, anyway
 
336
   TrekCursor = LoadCursor(MyInstance, "trek");
 
337
   WarnCursor = LoadCursor(MyInstance, "warn");
 
338
 
 
339
   //Create the fonts that we need. The fonts are actually in our resource file
 
340
   strcpy(FileName, GetExeDir());
 
341
   strcat(FileName, FontFileName);
 
342
   AddFontResource(FileName);
 
343
 
 
344
   memset(&lf, 0, sizeof(LOGFONT));
 
345
   strcpy(lf.lfFaceName, "Netrek");
 
346
//   lf.lfWidth = 6;
 
347
//   lf.lfHeight=10;
 
348
   lf.lfHeight = intDefault("fontsize",10);
 
349
   lf.lfWeight = FW_REGULAR;
 
350
   W_RegularFont = (W_Font) CreateFontIndirect(&lf);
 
351
 
 
352
   lf.lfWeight = FW_BOLD;
 
353
   strcpy(lf.lfFaceName, "Netrek");
 
354
   W_HighlightFont = (W_Font) CreateFontIndirect(&lf);
 
355
 
 
356
   lf.lfWeight = FW_REGULAR;
 
357
   lf.lfUnderline = TRUE;
 
358
   strcpy(lf.lfFaceName, "Netrek");
 
359
   W_UnderlineFont = (W_Font) CreateFontIndirect(&lf);
 
360
 
 
361
   //Use arial for the BigFont
 
362
   lf.lfUnderline = FALSE;
 
363
   lf.lfWeight = FW_MEDIUM;
 
364
   strcpy(lf.lfFaceName,"Arial");
 
365
   lf.lfHeight = 52; // 52
 
366
   lf.lfWidth  = 32;
 
367
   W_BigFont = (W_Font) CreateFontIndirect(&lf);
 
368
 
 
369
   //Set up or memory DCs. We need to get the default bitmap and store it,
 
370
   //for later use. The only way we can do this is to select another bitmap
 
371
   //into it... So we'll create a junk one, then delete it.
 
372
   GlobalMemDC = CreateCompatibleDC(NULL);
 
373
   GlobalMemDC2 = CreateCompatibleDC(NULL);
 
374
   junk = CreateBitmap(1,1,1,1,NULL);
 
375
   GlobalOldMemDCBitmap = (HBITMAP) SelectObject(GlobalMemDC, junk);
 
376
   SelectObject(GlobalMemDC, GlobalOldMemDCBitmap);
 
377
   GlobalOldMemDC2Bitmap = (HBITMAP) SelectObject(GlobalMemDC2, junk);
 
378
   SelectObject(GlobalMemDC2, GlobalOldMemDC2Bitmap);
 
379
   DeleteObject(junk);
 
380
 
 
381
   {
 
382
       //Find out just how big the font is
 
383
       TEXTMETRIC ftm;
 
384
 
 
385
       SelectObject(GlobalMemDC,W_HighlightFont); // Should be the biggest
 
386
       if (GetTextMetrics(GlobalMemDC,&ftm))
 
387
       {
 
388
           W_Textwidth = ftm.tmAveCharWidth;
 
389
           W_Textheight = ftm.tmHeight;
 
390
       }
 
391
   }
 
392
 
 
393
   //Create Virtual Key mapping table
 
394
   memset(VKMap, 0, sizeof(VKMap));
 
395
   memset(VKShiftMap, 0, sizeof(VKShiftMap));
 
396
   for (i=0; i<128; i++)
 
397
      {
 
398
      SHORT res = VkKeyScan((TCHAR) i);
 
399
 
 
400
          /* Converted SHR's to TESTs, faster on x86 -SAC */
 
401
      if (!(res & 0xff00))            //!highbyte == no shift,ctrl,alt
 
402
        VKMap[res] = i;
 
403
      else if (res & 0x100)   //Bit 1 of high byte = shift key
 
404
        VKShiftMap[res & 0xff] = i;
 
405
      }
 
406
    VKMap[VK_ESCAPE] = 27; // 27 is mapped as Ctrl-[ by Windows
 
407
    VKMap[VK_TAB] = 'i'+96;     // Make it look like '^i' so macroKey: TAB will work
 
408
    VKShiftMap[VK_SPACE] =' ';  // Map shift+space -> space
 
409
    VKShiftMap[VK_RETURN] ='\r'; // Map shift+return -> return
 
410
    VKShiftMap[VK_ESCAPE] =27; // Map shift+escape-> escape
 
411
   
 
412
   MainThreadID = GetCurrentThreadId(); // Save main thread ID so we can tell
 
413
                                        // which thread we're in later
 
414
 
 
415
   // Get the current system colors
 
416
   for (i=0; i<sizeof(SysColorNames); i++)
 
417
   {
 
418
       SysColors[i] = GetSysColor(SysColorNames[i]);
 
419
   }
 
420
 
 
421
   atexit(W_Cleanup);
 
422
   }
 
423
 
 
424
 
 
425
//Does all the resource de-allocation needed
 
426
//The rest of the silly code doesn't play nice and call DestroyIcon(), etc,
 
427
//so we have to track resource usage ourself.
 
428
void W_Cleanup()
 
429
   {
 
430
   int i;
 
431
   struct BitmapList *tmp, *p = CurrentBitmap;
 
432
   char FileName[100];
 
433
 
 
434
   // Reset the system colors to something recognizable
 
435
   ResetSysColors();
 
436
 
 
437
   //Get rid of the color pens, etc.
 
438
   for (i=0; i<COLORS; i++)
 
439
      {
 
440
      DeleteObject(colortable[i].brush);
 
441
      DeleteObject(colortable[i].pen);
 
442
      DeleteObject(colortable[i].dashedpen);
 
443
      }
 
444
 
 
445
   //Delete our two loaded (and shared, and hence not deleted when the window is
 
446
   //destroyed) cursors
 
447
   DestroyCursor(TrekCursor);
 
448
   DestroyCursor(WarnCursor);
 
449
 
 
450
   //Delete our fonts
 
451
   DeleteObject((HFONT)W_RegularFont);
 
452
   DeleteObject((HFONT)W_HighlightFont);
 
453
   DeleteObject((HFONT)W_UnderlineFont);
 
454
   DeleteObject((HFONT)W_BigFont);
 
455
 
 
456
   strcpy(FileName, GetExeDir());
 
457
   strcat(FileName, FontFileName);
 
458
   RemoveFontResource(FileName);
 
459
 
 
460
   //Select the original bitmaps back and delete our memory DCs
 
461
   SelectObject(GlobalMemDC, GlobalOldMemDCBitmap);
 
462
   DeleteDC(GlobalMemDC);
 
463
   SelectObject(GlobalMemDC2, GlobalOldMemDC2Bitmap);
 
464
   DeleteDC(GlobalMemDC2);
 
465
 
 
466
   //Destory our custom palette
 
467
   if (NetrekPalette)
 
468
      DeleteObject(NetrekPalette);
 
469
 
 
470
   //Remove the bitmap structures we've created, by traversing the linked list
 
471
   while (p)
 
472
      {
 
473
      tmp = p->next;
 
474
      DeleteObject(p->bm);
 
475
      free(p);
 
476
      p = tmp;
 
477
      }
 
478
   }
 
479
 
 
480
 
 
481
   /*
 
482
    * Figure out what kind of display we have, for color mapping
 
483
    * There are basically three possible situations:
 
484
    * 1) A fixed 16 color display (use alternate colors so they map well)
 
485
    * 2) A paletted 8-bit display (create a custom palette and use it)
 
486
    * 3) A 16 (15?) or 24 bit true-color display (no problem...)
 
487
    * We also let the use force a selection on the above.
 
488
    */
 
489
 
 
490
#define hexdig(a) ( ((a)>='a' && (a)<='f') ? ((a)-'a'+10) : \
 
491
                    ( ((a)>='A' && (a)<='F') ? ((a)-'A'+10)  : ((a)-'0') ) )
 
492
#define hexbyte(a) ( hexdig(*(a))*16 + hexdig(*((a)+1)) )
 
493
 
 
494
void GetColors()
 
495
   {
 
496
   HDC hdc;
 
497
   int i,j;
 
498
   char *def;
 
499
   int dtype=0;
 
500
   
 
501
   if (DefaultsLoaded)   
 
502
      {
 
503
      dtype=intDefault("forceDisplay", 0);
 
504
      if (dtype==0)
 
505
          {
 
506
          if (booleanDefault("forceMono", 0))
 
507
            dtype = 1;
 
508
          else
 
509
            {
 
510
            //Look at display hardware and make a choice
 
511
            hdc = GetDC(HWND_DESKTOP);
 
512
 
 
513
            i=GetDeviceCaps(hdc, BITSPIXEL) * GetDeviceCaps(hdc, PLANES);
 
514
#ifdef DEBUG
 
515
            printf("Bits per pixel detected: %d\n", i);
 
516
#endif           
 
517
            
 
518
            if ( (i<=4) || ((i<15) && !(GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE)) )
 
519
               dtype = 1;
 
520
            else if ( (i<15) && (GetDeviceCaps(hdc, RASTERCAPS) & RC_PALETTE) )
 
521
               dtype=2;
 
522
            else
 
523
               dtype=3;
 
524
 
 
525
            ReleaseDC(HWND_DESKTOP, hdc);
 
526
            }
 
527
         }
 
528
 
 
529
       if (dtype == 1)                                  // need extra bright clrs on 4 plane display
 
530
          memcpy(colortable, altcolortable, sizeof(colortable));
 
531
          
 
532
       //Modify colors from netrekrc file directives
 
533
       for (i=0; i<COLORS; i++)
 
534
          {
 
535
          char buf[30];
 
536
          sprintf(buf, "color.%s", colornames[i]);      //Check netrekrc file
 
537
          def = getdefault(buf);
 
538
#ifdef RACE_COLORS
 
539
          if (!def && i>=COLORS-RaceDefaultOffset)      // For race colors we use default color
 
540
             {                                         // color for that race if not set, i.e.
 
541
             sprintf(buf, "color.%s", colornames[i-RaceDefaultOffset]);      
 
542
             def = getdefault(buf);                    // if "color.rom" is not set, "color.red"
 
543
             }
 
544
#endif
 
545
          if (def)                 
 
546
             if (def[0] == '#')                         //Explicit RGB color
 
547
                {
 
548
                colortable[i].rgb = RGB(hexbyte(def+1), hexbyte(def+3), hexbyte(def+5));
 
549
                }
 
550
             else
 
551
                {
 
552
                for (j=0; j<XCLRS; j++)                //Else assume color name
 
553
                   if (!stricmp(def, xclrs[j].name))
 
554
                      break;
 
555
                if (j!=XCLRS)
 
556
                   colortable[i].rgb = RGB(xclrs[j].r, xclrs[j].g, xclrs[j].b);
 
557
                else
 
558
                   fprintf(stderr, "Color '%s' unknown\n", def);
 
559
               }
 
560
          }
 
561
          
 
562
       switch (dtype)
 
563
         {
 
564
         case 1:
 
565
   #ifdef DEBUG
 
566
            printf("16 color display detected.\n");
 
567
   #endif
 
568
            break;
 
569
 
 
570
         case 2:
 
571
            //Paletted display. Create a custom palette, and set the RGB indices
 
572
            //in the colortable to palette indices instead of explicit colors
 
573
            {
 
574
            char space[sizeof(LOGPALETTE) + sizeof(PALETTEENTRY) * (COLORS)];
 
575
            LOGPALETTE *pal = (LOGPALETTE *) space;
 
576
 
 
577
            pal->palVersion = 0x300;      //Windows version >=3.0 palette
 
578
            pal->palNumEntries = COLORS;
 
579
            for (i=0; i<COLORS; i++)
 
580
               {
 
581
               pal->palPalEntry[i].peRed = GetRValue(colortable[i].rgb);
 
582
               pal->palPalEntry[i].peGreen = GetGValue(colortable[i].rgb);
 
583
               pal->palPalEntry[i].peBlue = GetBValue(colortable[i].rgb);
 
584
               pal->palPalEntry[i].peFlags = 0;
 
585
               colortable[i].rgb = PALETTEINDEX(i);
 
586
               }
 
587
            NetrekPalette = CreatePalette(pal);
 
588
 
 
589
   #ifdef DEBUG
 
590
            printf("Paletted color display detected.\n");
 
591
   #endif
 
592
            }
 
593
            break;
 
594
 
 
595
         //else, everything's okey dokey, we have a true-color display
 
596
         }
 
597
 
 
598
      //Create the various pens and brushes for each color
 
599
      for (i=0; i<COLORS; i++)
 
600
         {
 
601
          DWORD dashbits[] = { 1, 2 };
 
602
         colortable[i].brush = CreateSolidBrush(colortable[i].rgb);
 
603
         colortable[i].pen = CreatePen(PS_SOLID | PS_INSIDEFRAME, 1, colortable[i].rgb);
 
604
         colortable[i].dashedpen = CreatePen(PS_DOT, 1, colortable[i].rgb);
 
605
         }
 
606
      }
 
607
   }
 
608
 
 
609
W_Window W_RenameWindow(W_Window window, char *str)
 
610
   {
 
611
   FNHEADER;
 
612
   SetWindowText(win->hwnd, str);
 
613
   return window;
 
614
   }
 
615
 
 
616
 
 
617
//Internal function - used as the base for all window creation
 
618
Window *newWindow(char *name, int x, int y, int width, int height,
 
619
                        W_Window parent, int border, W_Color color, int type)
 
620
   {
 
621
   Window *window,*parentwin=0;
 
622
   HDC hdc;
 
623
   char title_buff[100];
 
624
   char *s;
 
625
   DWORD SpecialStyle = 0;
 
626
 
 
627
   if ( !(window = (Window *)malloc(sizeof(Window)) ) )
 
628
      {
 
629
      printf("Not enough memory to create a new window.");
 
630
      return 0;
 
631
      }
 
632
   memset(window, 0, sizeof(Window));
 
633
 
 
634
   //Stuff ripped from x11window.c - provides nicer titles when the window
 
635
   // is a wait window or the main window.
 
636
   if (strcmp (name, "netrek") == 0)
 
637
      {
 
638
      if (title)
 
639
        s = title;
 
640
      else
 
641
        {
 
642
        s = title_buff;
 
643
        sprintf (title_buff, "Netrek  @  %s", serverName);
 
644
        }
 
645
      SpecialStyle = WS_OVERLAPPEDWINDOW;    //Make main window sizeable
 
646
      //SpecialStyle |=WS_BORDER;
 
647
      }
 
648
   else if (strcmp (name, "wait") == 0)
 
649
      {
 
650
      if (title)
 
651
        s = title;
 
652
      else
 
653
        s = serverName;
 
654
      width += GetSystemMetrics( SM_CXFRAME);
 
655
      //Make the wait window show up in the task list
 
656
      SpecialStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
 
657
      parentwin = &myroot;
 
658
      }
 
659
   else if (strncmp (name, "Meta", 4) == 0)
 
660
      {
 
661
      s = name;
 
662
      height += GetSystemMetrics( SM_CYFRAME ) + border;
 
663
      //Make the Metaserver window show up in the task list
 
664
      SpecialStyle = WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
 
665
      parentwin = &myroot;
 
666
      }
 
667
#ifdef SUPPORT_WIN32S      
 
668
   else if (strcmp (name, "Console") == 0)
 
669
      {
 
670
      SpecialStyle = WS_CAPTION | WS_SYSMENU | WS_MINIMIZEBOX;
 
671
      s = name;
 
672
      }
 
673
#endif      
 
674
   else
 
675
      s = name;
 
676
 
 
677
   //Mask border - 15 pixels max - and make sure it's at least 1, and that it's not black
 
678
   if (border > 15) border = 15;
 
679
   if (!border) border=1;
 
680
   if (color == BLACK) color = WHITE;
 
681
 
 
682
   //Set the various attributes to default states
 
683
   window->type = type;
 
684
   window->border = border;
 
685
   window->BorderColor=color;
 
686
   window->cursor = LoadCursor(NULL, IDC_ARROW);
 
687
 
 
688
   //Check the parent - parent to root (==desktop) if null
 
689
   if (!parentwin)
 
690
   {
 
691
   if (!parent)
 
692
        {
 
693
        parentwin =  (baseWin ? (Window *)baseWin : &myroot);
 
694
            SpecialStyle |= baseWin ? WS_POPUP | WS_CAPTION : WS_POPUP;
 
695
        }
 
696
   else
 
697
        {
 
698
        parentwin =  (Window *)parent;
 
699
        SpecialStyle |= WS_CHILD;
 
700
        }
 
701
   }
 
702
 
 
703
   //Actually create the window
 
704
   //Hacked to allow negative create locations -SAC
 
705
   window->hwnd = CreateWindow(  ClassName,
 
706
                                 s,
 
707
                                 WS_CLIPSIBLINGS | WS_CLIPCHILDREN | SpecialStyle,
 
708
                                 x + parentwin->border,
 
709
                                 y + parentwin->border,
 
710
                                 width + border*2,
 
711
                                 height + border*2 +
 
712
                                    ( (SpecialStyle & WS_CAPTION) ? GetSystemMetrics( SM_CYCAPTION ) : 0),
 
713
                                 parentwin->hwnd,
 
714
                                 NULL,
 
715
                                 MyInstance,
 
716
                                 (void *)window);  //Pass Window struct * as user param
 
717
 
 
718
   if (!window->hwnd)
 
719
      {
 
720
      printf("CreateWindow() for %s failed...",name);
 
721
      return(0);
 
722
      }
 
723
 
 
724
   //Select the custom palette if we're in a paletted mode
 
725
   hdc = GetDC(window->hwnd);
 
726
   if (NetrekPalette)
 
727
      {
 
728
      SelectPalette(hdc, NetrekPalette, FALSE);
 
729
      RealizePalette(hdc);
 
730
      }
 
731
   ReleaseDC(window->hwnd, hdc);
 
732
 
 
733
   if (!AnyWindow)
 
734
      AnyWindow = window->hwnd;
 
735
   
 
736
   return window;
 
737
   }
 
738
 
 
739
W_Window W_MakeWindow(char *name, int x, int y, int width, int height,
 
740
                        W_Window parent, int border, W_Color color)
 
741
   {
 
742
   Window *newwin;
 
743
 
 
744
   //Get the default position, etc.
 
745
   checkGeometry(name, &x, &y, &width, &height);
 
746
 
 
747
   //Get the default parent..
 
748
   checkParent(name, &parent);
 
749
 
 
750
   if ( !(newwin = newWindow(name, x, y, width, height, parent, border, color, WIN_GRAPH)))
 
751
      return(0);
 
752
 
 
753
   //Map (show) the window if the user spec'd it
 
754
   if (checkMapped(name))
 
755
      W_MapWindow((W_Window)newwin);
 
756
 
 
757
   return (W_Window) newwin;
 
758
   }
 
759
 
 
760
 
 
761
//Make a window that contains fixed-spaced text, where columns must be
 
762
//aligned, etc. The x and y passed are in character cells, not pixels.
 
763
W_Window W_MakeTextWindow(char *name, int x, int y, int width, int height,
 
764
                           W_Window parent, int border)
 
765
   {
 
766
   Window *newwin;
 
767
 
 
768
   //Get the default position, etc.
 
769
   checkGeometry(name, &x, &y, &width, &height);
 
770
 
 
771
   //Get the default parent..
 
772
   checkParent(name, &parent);
 
773
 
 
774
   if (!(newwin = newWindow(  name, x, y,
 
775
                              width * W_Textwidth + WIN_EDGE * 2,
 
776
                              MENU_PAD * 2 + height * W_Textheight,
 
777
                              parent, border, W_Black, WIN_TEXT)) )
 
778
      return(0);
 
779
 
 
780
   //Store the original textheight, width
 
781
   newwin->TextHeight = height;
 
782
   newwin->TextWidth = width;
 
783
 
 
784
   //Map (show) the window if the user spec'd it
 
785
   if (checkMapped(name))
 
786
      W_MapWindow((W_Window)newwin);
 
787
 
 
788
   return (W_Window) newwin;
 
789
   }
 
790
 
 
791
// Make a WIN_SCROLL type window.
 
792
// We use a scrollbar so we can look through the text, something the X version
 
793
// didn't have. Nyah, nyah.
 
794
W_Window W_MakeScrollingWindow(char *name, int x, int y, int width, int height,
 
795
                                 W_Window parent, int border)
 
796
   {
 
797
   HWND hsb;
 
798
   RECT ra;
 
799
   Window *newwin;
 
800
   int i;
 
801
 
 
802
   //Get the default position, etc.
 
803
   checkGeometry(name, &x, &y, &width, &height);
 
804
 
 
805
   //Get the default parent..
 
806
   checkParent(name, &parent);
 
807
 
 
808
   if (! (newwin = newWindow( name, x, y,
 
809
                              width * W_Textwidth + WIN_EDGE * 2 + GetSystemMetrics(SM_CXVSCROLL),
 
810
                              height * W_Textheight + MENU_PAD * 2,
 
811
                              parent, border, W_White, WIN_SCROLL)) )
 
812
      return(0);
 
813
 
 
814
   //Store the original textheight, width
 
815
   newwin->TextHeight = height;
 
816
   newwin->TextWidth = width;
 
817
 
 
818
   //Give it a scroll bar, and set the range (to zero, initially)
 
819
   SetWindowLong(newwin->hwnd, GWL_STYLE, GetWindowLong(newwin->hwnd, GWL_STYLE) | WS_VSCROLL );
 
820
   SetScrollRange(newwin->hwnd, SB_VERT, 0, 0, FALSE);
 
821
 
 
822
   //Map (show) the window if the user spec'd it
 
823
   if (checkMapped(name))
 
824
      W_MapWindow((W_Window)newwin);
 
825
 
 
826
   return (W_Window) newwin;
 
827
   }
 
828
 
 
829
 
 
830
//Make a menu window. This is similar to a text window in that it has a 1x1 mappiing
 
831
//between coordinates and character cells. Note that the height parameter
 
832
//specified here indicates the number of items
 
833
W_Window W_MakeMenu(char *name, int x, int y,int width,int height,W_Window parent,int border)
 
834
   {
 
835
   struct menuItem *items;
 
836
   Window *newwin;
 
837
   HWND ParentHWND;
 
838
 
 
839
   int i;
 
840
 
 
841
   //Get the default position, etc.
 
842
   checkGeometry(name, &x, &y, &width, &height);
 
843
 
 
844
   //Get the default parent..
 
845
   checkParent(name, &parent);
 
846
 
 
847
   if (! (newwin = newWindow( name, x, y,
 
848
                              width * W_Textwidth + WIN_EDGE * 2,
 
849
                              height * (W_Textheight + MENU_PAD * 2) + (height - 1) * MENU_BAR,
 
850
                              parent, border, W_Black, WIN_MENU)) )
 
851
      return(0);
 
852
 
 
853
   if ( !(items=(struct menuItem *) malloc(height*sizeof(struct menuItem))) )
 
854
      fprintf(stderr,"Could not allocate storage for menu window");
 
855
   else
 
856
      for (i=0; i<height; i++)
 
857
         {
 
858
         items[i].string=NULL;
 
859
         items[i].color=W_White;
 
860
         }
 
861
   newwin->items = items;
 
862
   newwin->NumItems = height;
 
863
   newwin->TextHeight = height;
 
864
 
 
865
   //Map (show) the window if the user spec'd it
 
866
   if (checkMapped(name))
 
867
      W_MapWindow((W_Window)newwin);
 
868
 
 
869
   return (W_Window) newwin;
 
870
   }
 
871
 
 
872
void W_ChangeBorder(W_Window window, W_Color color)
 
873
   {
 
874
   HDC hdc;
 
875
   FNHEADER_VOID;
 
876
 
 
877
   win->BorderColor = color;
 
878
 
 
879
   hdc = GetDC(win->hwnd);                         //Turn off boder clipping
 
880
   if (NetrekPalette)
 
881
      {
 
882
      SelectPalette(hdc, NetrekPalette, FALSE);
 
883
      RealizePalette(hdc);
 
884
      }
 
885
   DrawBorder(win, hdc);
 
886
   ReleaseDC(win->hwnd, hdc);
 
887
   }
 
888
 
 
889
 
 
890
//Displays the window.
 
891
void W_MapWindow(W_Window window)
 
892
   {
 
893
   FNHEADER_VOID;
 
894
 
 
895
   ShowWindow(win->hwnd, SW_SHOWNORMAL);
 
896
   BringWindowToTop(win->hwnd);
 
897
   if (window==baseWin &&
 
898
       !booleanDefault("netrek.w32caption",1))
 
899
       PostMessage(win->hwnd, WM_SYSKEYDOWN, VK_RETURN, 0);
 
900
   }
 
901
 
 
902
//Hides the window.
 
903
void W_UnmapWindow(W_Window window)
 
904
   {
 
905
   FNHEADER_VOID;
 
906
 
 
907
   ShowWindow(win->hwnd, SW_HIDE);
 
908
   }
 
909
 
 
910
//Returns TRUE if the window is visible, and also not minimized
 
911
int W_IsMapped(W_Window window)
 
912
   {
 
913
   FNHEADER;
 
914
 
 
915
   return (IsWindowVisible(win->hwnd) && !IsIconic(win->hwnd));
 
916
   }
 
917
 
 
918
void W_FillArea(W_Window window, int x, int y, int width, int height, int color)
 
919
   {
 
920
   HDC hdc;
 
921
   RECT r;
 
922
   register int border;
 
923
   FNHEADER_VOID;
 
924
   border = win->border;
 
925
 
 
926
   //do a rectangle intersection with the clipping rect, inlined for speed
 
927
   x+=border; y+=border;
 
928
   r.left = max(x, border);
 
929
   r.right= min(x+width, win->ClipRect.right);
 
930
   if (r.right < r.left)
 
931
      return;                                      //Horizantal extents do not overlap
 
932
   r.top = max(y, border);
 
933
   r.bottom = min(y+height, win->ClipRect.bottom);
 
934
   if (r.bottom < r.top)
 
935
      return;                                      //Vertical extents do not overlap
 
936
 
 
937
   hdc = GetDC(win->hwnd);
 
938
   if (NetrekPalette)
 
939
      {
 
940
      SelectPalette(hdc, NetrekPalette, FALSE);
 
941
      RealizePalette(hdc);
 
942
      }
 
943
   FillRect(hdc, &r, colortable[color].brush);
 
944
   ReleaseDC(win->hwnd, hdc);
 
945
   }
 
946
 
 
947
void W_ClearArea(W_Window window, int x, int y, int width, int height)
 
948
   {
 
949
   HDC hdc;
 
950
   RECT r;
 
951
   register int border;
 
952
   FNHEADER_VOID;
 
953
   border = win->border;
 
954
 
 
955
   if (win->type == WIN_TEXT)
 
956
      {
 
957
      x = x * W_Textwidth + WIN_EDGE;
 
958
      y = y * W_Textheight + MENU_PAD;
 
959
      width *= W_Textwidth;
 
960
      height *= W_Textheight;
 
961
      }
 
962
 
 
963
   //do a rectangle intersection with the clipping rect, inlined for speed
 
964
   x+=border; y+=border;
 
965
   r.left = max(x, border);
 
966
   r.right= min(x+width, win->ClipRect.right);
 
967
   if (r.right < r.left)
 
968
      return;                                      //Horizantal extents do not overlap
 
969
   r.top = max(y, border);
 
970
   r.bottom = min(y+height, win->ClipRect.bottom);
 
971
   if (r.bottom < r.top)
 
972
      return;                                      //Vertical extents do not overlap
 
973
 
 
974
   hdc = GetDC(win->hwnd);
 
975
   if (NetrekPalette)
 
976
      {
 
977
      SelectPalette(hdc, NetrekPalette, FALSE);
 
978
      RealizePalette(hdc);
 
979
      }
 
980
   // FillRect doesn't do the edges (right and bottom) -SAC 
 
981
   r.right++; r.bottom++;
 
982
   FillRect(hdc, &r, colortable[W_Black].brush);
 
983
   ReleaseDC(win->hwnd, hdc);
 
984
   }
 
985
 
 
986
//We don't need to cache...
 
987
void W_CacheClearArea(W_Window window, int x, int y, int width, int height)
 
988
   {
 
989
   W_ClearArea(window, x, y, width, height);
 
990
   }
 
991
 
 
992
void W_FlushClearAreaCache(W_Window window)
 
993
   {
 
994
   //Hmmm.... Do I really prefer lima beans, or coconuts... I wonder...
 
995
   }
 
996
 
 
997
 
 
998
// Clear multiple areas
 
999
void W_ClearAreas(W_Window window, int *xs, int *ys, int *widths, int *heights, int num)
 
1000
{
 
1001
   HDC hdc;
 
1002
   RECT r;
 
1003
   register int border,x,y,width,height;
 
1004
   FNHEADER_VOID;
 
1005
   border = win->border;
 
1006
 
 
1007
   hdc = GetDC(win->hwnd);
 
1008
   if (NetrekPalette)
 
1009
      {
 
1010
      SelectPalette(hdc, NetrekPalette, FALSE);
 
1011
      RealizePalette(hdc);
 
1012
      }
 
1013
 
 
1014
   while (num)
 
1015
   {
 
1016
      num--;
 
1017
 
 
1018
      x = xs[num];
 
1019
      y = ys[num];
 
1020
      width = widths[num];
 
1021
      height = heights[num];
 
1022
      
 
1023
      if (win->type == WIN_TEXT)
 
1024
         {
 
1025
         x = x * W_Textwidth + WIN_EDGE;
 
1026
         y = y * W_Textheight + MENU_PAD;
 
1027
         width *= W_Textwidth;
 
1028
         height *= W_Textheight;
 
1029
         }
 
1030
 
 
1031
      //do a rectangle intersection with the clipping rect, inlined for speed
 
1032
      x+=border; y+=border;
 
1033
      r.left = max(x, border);
 
1034
      r.right= min(x+width, win->ClipRect.right);
 
1035
      if (r.right < r.left)
 
1036
         continue;                                 //Horizantal extents do not overlap
 
1037
      r.top = max(y, border);
 
1038
      r.bottom = min(y+height, win->ClipRect.bottom);
 
1039
      if (r.bottom < r.top)
 
1040
         continue;                                  //Vertical extents do not overlap
 
1041
 
 
1042
      FillRect(hdc, &r, colortable[W_Black].brush);
 
1043
   }
 
1044
   
 
1045
   ReleaseDC(win->hwnd, hdc);
 
1046
 
 
1047
   return;
 
1048
}
 
1049
 
 
1050
void W_ClearWindow(W_Window window)
 
1051
   {
 
1052
   HDC hdc;
 
1053
   FNHEADER_VOID;
 
1054
 
 
1055
   hdc = GetDC(win->hwnd);
 
1056
   if (NetrekPalette)
 
1057
      {
 
1058
      SelectPalette(hdc, NetrekPalette, FALSE);
 
1059
      RealizePalette(hdc);
 
1060
      }
 
1061
 
 
1062
   if (!win->tiled)
 
1063
      FillRect(hdc, &win->ClipRect, colortable[BLACK].brush);
 
1064
   else
 
1065
      {
 
1066
      struct Icon *icon = win->TileIcon;
 
1067
      RECT r;
 
1068
      int i,j;
 
1069
 
 
1070
      GetClientRect(win->hwnd, &r);
 
1071
 
 
1072
      //Bitmap should be white on window bk color
 
1073
      SetTextColor(hdc, colortable[BLACK].rgb);
 
1074
      SetBkColor(hdc, colortable[WHITE].rgb);
 
1075
 
 
1076
      //Select the bitmap
 
1077
      SelectObject(GlobalMemDC, icon->bm);
 
1078
 
 
1079
      //Paste the bitmap into the window
 
1080
      for (i=0; i<r.bottom; i+=icon->height)
 
1081
         for (j=0; j<r.right; j+=icon->width)
 
1082
            BitBlt(hdc, j, i,
 
1083
                   icon->width, icon->height, GlobalMemDC, 0, 0, SRCCOPY );
 
1084
      DrawBorder(win, hdc);
 
1085
      }
 
1086
 
 
1087
   ReleaseDC(win->hwnd, hdc);
 
1088
   }
 
1089
 
 
1090
 
 
1091
//These globals used for communication between the following three fns
 
1092
//We implement a custom queue of only those message we are interested in.
 
1093
//The event (message) processing would really be quite simple, except
 
1094
//for the fact that many messages in Windows are _sent_, rather than
 
1095
//retrieved via GetMessage(), so the window proc must be able to post
 
1096
//events to the queue on its own without calling W_NextEvent().
 
1097
W_Event EventQueue[EVENT_Q_SIZE];
 
1098
int EventHead=0, EventTail=0;
 
1099
 
 
1100
//Are there events (messages) in our queue?
 
1101
//Here is the main message loop of our program. We first a)check
 
1102
//to see if there is an event in the queue, and then if there isn't b) do
 
1103
//the PeekMessage() thing, then c) check the queue again
 
1104
int W_EventsPending()
 
1105
   {
 
1106
   MSG msg;
 
1107
 
 
1108
   if ( (GetAsyncKeyState(VK_SHIFT) & ~0x1) && (GetAsyncKeyState(27) & ~0x1))
 
1109
      exit(-1);   //Safety device - Shft+ESC = clean termination
 
1110
 
 
1111
 
 
1112
   if (EventHead != EventTail)      //Event already in queue
 
1113
      return(1);
 
1114
 
 
1115
   //Essentially, while there is a message in the application queue
 
1116
   //and we haven't got and "event", continue processing messages
 
1117
   while ( PeekMessage(&msg, NULL, 0, 0, PM_REMOVE) )
 
1118
      {
 
1119
      //TranslateMessage(&msg);          //Yes, translate keyboard messages,
 
1120
      DispatchMessage(&msg);           //dispatch the message to the window proc
 
1121
      if  (EventHead != EventTail)
 
1122
         return (1);
 
1123
      }
 
1124
 
 
1125
   return (0);                         //Nothing waiting
 
1126
   }
 
1127
 
 
1128
// Wait for an event to become available; it returns zero if it recieves a
 
1129
// WM_TERMAINTE_WAIT (defined as WM_USER) message,
 
1130
// which we use to reset the game (it's issued by another thread)
 
1131
int W_WaitForEvent()
 
1132
{
 
1133
   MSG msg;
 
1134
 
 
1135
   while (EventHead == EventTail)      // Get an event
 
1136
      {
 
1137
   
 
1138
      GetMessage(&msg, NULL, 0, 0);
 
1139
      if (msg.message == WM_TERMINATE_WAIT)          // Quit message recieved
 
1140
         return 0;
 
1141
 
 
1142
      //TranslateMessage(&msg);          //translate keyboard messages,
 
1143
      DispatchMessage(&msg);           //dispatch the message to the window proc
 
1144
      }
 
1145
   return 1;
 
1146
}
 
1147
 
 
1148
// Force W_WaitForEvent to terminate. Notice we send the message to 
 
1149
// any window, the point is that it will be processed in the main thread.
 
1150
void W_TerminateWait()
 
1151
{
 
1152
   PostMessage(AnyWindow, WM_TERMINATE_WAIT, 0, 0);
 
1153
}
 
1154
 
 
1155
//Get the next event (message). Simply copies the event *, and advances the pointer
 
1156
void W_NextEvent(W_Event *event)
 
1157
   {
 
1158
   if (EventHead == EventTail)   //Make sure there actually is a message!
 
1159
      W_WaitForEvent();
 
1160
 
 
1161
   EventHead = (EventHead + 1) % EVENT_Q_SIZE;  //Advance queue pointer
 
1162
   memcpy(event, &EventQueue[EventHead], sizeof(W_Event));
 
1163
   }
 
1164
 
 
1165
//Return any already queued events
 
1166
int W_SpNextEvent(W_Event *event)
 
1167
 {
 
1168
 if (W_EventsQueued())
 
1169
    {
 
1170
    W_NextEvent(event);
 
1171
    return 1;
 
1172
    }
 
1173
 return 0;
 
1174
 }
 
1175
 
 
1176
 
 
1177
//The main window proc for all of the game's windows. Strange design, this netrek code...
 
1178
//But I guess this is really just a dispatcher function - the events are actually
 
1179
//"processed" in the rest of the code. Also, all these #ifdef's clutter it needlessly...
 
1180
 
 
1181
//Two very useful defines. These capture an event, after it is determined to be
 
1182
//valid. Doing this AFTER the event (message) is determined valid increases
 
1183
//the code size, and makes for the macros, but it also greatly speeds up
 
1184
//processing of the zillion other messages that go through the loop.
 
1185
 
 
1186
#define GET_STRUCT_PTR\
 
1187
   win=(Window *)GetWindowLong(hwnd, 0)
 
1188
 
 
1189
#define STORE_EVENT\
 
1190
   i = (EventTail + 1) % EVENT_Q_SIZE;\
 
1191
   if (i != EventHead)\
 
1192
      EventTail = i;\
 
1193
   if (InSendMessage())\
 
1194
      GetCursorPos(&pos);\
 
1195
   else\
 
1196
      {\
 
1197
      *((DWORD *)&spos) = GetMessagePos();\
 
1198
      pos.x = spos.x; pos.y = spos.y;\
 
1199
      }\
 
1200
   ScreenToClient(hwnd, &pos);\
 
1201
   EventQueue[EventTail].x = pos.x - win->border;\
 
1202
   EventQueue[EventTail].y = pos.y - win->border;\
 
1203
   EventQueue[EventTail].Window=(W_Window) win;\
 
1204
   if ( win->type == WIN_MENU )\
 
1205
      {\
 
1206
      if (EventQueue[EventTail].y % (W_Textheight + MENU_PAD * 2 + MENU_BAR) >=\
 
1207
            W_Textheight + MENU_PAD * 2)\
 
1208
       return (0);\
 
1209
      EventQueue[EventTail].y /= (W_Textheight + MENU_PAD * 2 + MENU_BAR) ;\
 
1210
      }
 
1211
 
 
1212
//A similar version of the above that gets the mouse pos from LPARAM -
 
1213
//used in processing mouse messages
 
1214
#define STORE_EVENT_MOUSE\
 
1215
   i = (EventTail + 1) % EVENT_Q_SIZE;\
 
1216
   if (i != EventHead)\
 
1217
      EventTail = i;\
 
1218
   if (InSendMessage())\
 
1219
      GetCursorPos(&pos);\
 
1220
   else\
 
1221
      {\
 
1222
      *((DWORD *)&spos) = GetMessagePos();\
 
1223
      pos.x = spos.x; pos.y = spos.y;\
 
1224
      }\
 
1225
   ScreenToClient(hwnd, &pos);\
 
1226
   EventQueue[EventTail].x = pos.x - win->border;\
 
1227
   EventQueue[EventTail].y = pos.y - win->border;\
 
1228
   EventQueue[EventTail].Window=(W_Window) win;\
 
1229
   if ( win->type == WIN_MENU )\
 
1230
      {\
 
1231
      if (EventQueue[EventTail].y % (W_Textheight + MENU_PAD * 2 + MENU_BAR) >=\
 
1232
            W_Textheight + MENU_PAD * 2)\
 
1233
       return (0);\
 
1234
      EventQueue[EventTail].y /= (W_Textheight + MENU_PAD * 2 + MENU_BAR) ;\
 
1235
      }
 
1236
 
 
1237
LRESULT CALLBACK NetrekWndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
 
1238
   {
 
1239
   register Window *win;
 
1240
   POINT pos;
 
1241
   POINTS spos;
 
1242
   HDC hdc;
 
1243
   PAINTSTRUCT ps;
 
1244
   int i,j, thresh;
 
1245
   struct Icon *icon;
 
1246
   RECT r;
 
1247
#if defined(MOTION_MOUSE) || defined(XTRA_MESSAGE_UI)
 
1248
   static POINTS prev_pos;
 
1249
   static HWND LastPressHwnd;
 
1250
#endif
 
1251
 
 
1252
   switch (msg)
 
1253
      {
 
1254
      case WM_CREATE:
 
1255
         //Store our structure pointer - passed from newWindow() as final CreateWindow() param
 
1256
         SetWindowLong(hwnd, 0, (LONG)(Window *)((CREATESTRUCT *)lParam)->lpCreateParams );
 
1257
         return(0);
 
1258
 
 
1259
      case WM_SIZE:
 
1260
         //Create/adjust our clipping rect, which is used to prevent drawing into
 
1261
         //the border area.
 
1262
         GET_STRUCT_PTR;
 
1263
 
 
1264
         win->ClipRect.left = win->ClipRect.top = win->border;
 
1265
         win->ClipRect.right = LOWORD(lParam) - win->border;
 
1266
         win->ClipRect.bottom =  HIWORD(lParam) - win->border;
 
1267
         break;
 
1268
 
 
1269
      case  WM_PAINT:
 
1270
         GET_STRUCT_PTR;
 
1271
 
 
1272
         hdc = BeginPaint(hwnd, &ps);           //Do the beginpaint/endpaint thing
 
1273
                                                //so that the invalid rectangle is updated
 
1274
         if (NetrekPalette)
 
1275
            {
 
1276
            SelectPalette(hdc, NetrekPalette, FALSE);
 
1277
            RealizePalette(hdc);
 
1278
            }
 
1279
                                                
 
1280
         i = TRUE;                              //Store this event
 
1281
         if (win->type == WIN_MENU)
 
1282
            {
 
1283
            RedrawMenu(win, hdc);
 
1284
            i = FALSE;                          //Don't store this event
 
1285
            }
 
1286
         else if (win->type == WIN_SCROLL)
 
1287
            {
 
1288
            RedrawScrolling(win, hdc);
 
1289
            i = FALSE;                          //Don't store this event
 
1290
            }
 
1291
 
 
1292
         DrawBorder(win, hdc);
 
1293
 
 
1294
         EndPaint(hwnd, &ps);                   //Update the invalid region, etc.
 
1295
 
 
1296
         if (i)
 
1297
            {
 
1298
            i = (EventTail + 1) % EVENT_Q_SIZE;
 
1299
            if (i != EventHead)
 
1300
               EventTail = i;
 
1301
            EventQueue[EventTail].type=W_EV_EXPOSE;
 
1302
            EventQueue[EventTail].Window = (W_Window) GetWindowLong(hwnd, 0);
 
1303
            EventQueue[EventTail].x = ps.rcPaint.left ;//- win->border;
 
1304
            EventQueue[EventTail].y = ps.rcPaint.top ;//- win->border;
 
1305
/*            EventQueue[EventTail].width = ps.rcPaint.right - ps.rcPaint.left;
 
1306
            EventQueue[EventTail].height = ps.rcPaint.bottom - ps.rcPaint.top;*/
 
1307
            }
 
1308
         return(0);
 
1309
 
 
1310
      case WM_LBUTTONDOWN:
 
1311
         BringWindowToTop(hwnd);
 
1312
         GET_STRUCT_PTR;
 
1313
 
 
1314
         STORE_EVENT_MOUSE;
 
1315
         LastPressHwnd = hwnd;
 
1316
         
 
1317
#ifdef SHIFTED_MOUSE
 
1318
         if ((wParam & MK_SHIFT) && (wParam & MK_CONTROL))
 
1319
            EventQueue[EventTail].key = W_LBUTTON4;
 
1320
         else if (wParam & MK_SHIFT)
 
1321
            EventQueue[EventTail].key = W_LBUTTON2;
 
1322
         else if (wParam & MK_CONTROL)
 
1323
            EventQueue[EventTail].key = W_LBUTTON3;
 
1324
         else
 
1325
            EventQueue[EventTail].key = W_LBUTTON;
 
1326
#else
 
1327
         EventQueue[EventTail].key = W_LBUTTON;
 
1328
#endif /* SHIFTED_MOUSE */
 
1329
 
 
1330
#ifdef MOTION_MOUSE
 
1331
         prev_pos = MAKEPOINTS(lParam);
 
1332
#endif
 
1333
         EventQueue[EventTail].type=W_EV_BUTTON;
 
1334
         return(0);
 
1335
 
 
1336
 
 
1337
      case WM_MBUTTONDOWN:                
 
1338
         BringWindowToTop(hwnd);
 
1339
         GET_STRUCT_PTR;
 
1340
 
 
1341
         STORE_EVENT_MOUSE;
 
1342
         LastPressHwnd = hwnd;
 
1343
         
 
1344
#ifdef SHIFTED_MOUSE
 
1345
         if ((wParam & MK_SHIFT) && (wParam & MK_CONTROL))
 
1346
            EventQueue[EventTail].key = W_MBUTTON4;
 
1347
         else if (wParam & MK_SHIFT)
 
1348
            EventQueue[EventTail].key = W_MBUTTON2;
 
1349
         else if (wParam & MK_CONTROL)
 
1350
            EventQueue[EventTail].key = W_MBUTTON3;
 
1351
         else
 
1352
            EventQueue[EventTail].key = W_MBUTTON;
 
1353
#else
 
1354
         EventQueue[EventTail].key = W_MBUTTON;
 
1355
#endif /* SHIFTED_MOUSE */
 
1356
 
 
1357
#ifdef MOTION_MOUSE
 
1358
         prev_pos = MAKEPOINTS(lParam);
 
1359
#endif
 
1360
         EventQueue[EventTail].type=W_EV_BUTTON;
 
1361
         return(0);
 
1362
 
 
1363
      case WM_RBUTTONDOWN:
 
1364
         BringWindowToTop(hwnd);
 
1365
         GET_STRUCT_PTR;
 
1366
 
 
1367
         STORE_EVENT_MOUSE;
 
1368
         LastPressHwnd = hwnd;
 
1369
         
 
1370
#ifdef SHIFTED_MOUSE
 
1371
         if ((wParam & MK_SHIFT) && (wParam & MK_CONTROL))
 
1372
            EventQueue[EventTail].key = W_RBUTTON4;
 
1373
         else if (wParam & MK_SHIFT)
 
1374
            EventQueue[EventTail].key = W_RBUTTON2;
 
1375
         else if (wParam & MK_CONTROL)
 
1376
            EventQueue[EventTail].key = W_RBUTTON3;
 
1377
         else
 
1378
            EventQueue[EventTail].key = W_RBUTTON;
 
1379
#else
 
1380
         EventQueue[EventTail].key = W_RBUTTON;
 
1381
#endif /* SHIFTED_MOUSE */
 
1382
 
 
1383
#ifdef MOTION_MOUSE
 
1384
         prev_pos = MAKEPOINTS(lParam);
 
1385
#endif
 
1386
         EventQueue[EventTail].type=W_EV_BUTTON;
 
1387
         return(0);
 
1388
 
 
1389
      // Watch for stuff like ALT-ENTER
 
1390
      case WM_SYSKEYDOWN:
 
1391
         if (wParam == VK_RETURN)
 
1392
         {
 
1393
             LONG wl;
 
1394
             RECT r;
 
1395
             int cx,cy;
 
1396
 
 
1397
             cx = GetSystemMetrics(SM_CXEDGE);
 
1398
             if (!cx)
 
1399
                 cx = GetSystemMetrics(SM_CXBORDER);
 
1400
             cy = GetSystemMetrics(SM_CYEDGE);
 
1401
             if (!cy)
 
1402
                 GetSystemMetrics(SM_CYBORDER);
 
1403
 
 
1404
             wl = GetWindowLong(((Window *)baseWin)->hwnd, GWL_STYLE);
 
1405
             GetWindowRect(((Window *)baseWin)->hwnd, &r);
 
1406
             if (wl & WS_CAPTION)
 
1407
             {
 
1408
                 wl &= ~WS_CAPTION;
 
1409
                 r.left += GetSystemMetrics(SM_CXBORDER);
 
1410
                 r.top  += GetSystemMetrics(SM_CYBORDER);
 
1411
             } else {
 
1412
                 wl |= WS_CAPTION;
 
1413
                 r.left -= GetSystemMetrics(SM_CXBORDER);
 
1414
                 r.top  -= GetSystemMetrics(SM_CYBORDER);
 
1415
             }
 
1416
             SetWindowLong(((Window *)baseWin)->hwnd, GWL_STYLE, wl);
 
1417
             // Update the window since the height has changed
 
1418
             MoveWindow(((Window *)baseWin)->hwnd, r.left, r.top,
 
1419
                         r.right-r.left, r.bottom-r.top, TRUE);
 
1420
             return(0);
 
1421
         }          
 
1422
         break;
 
1423
 
 
1424
      //Keyboard event - also catch the mousebuttons, #ifdef
 
1425
      case WM_KEYDOWN:
 
1426
         //Manually map key to ASCII based on shift state
 
1427
         j = ( (GetKeyState(VK_SHIFT) & ~0x1 ) ? VKShiftMap : VKMap)[wParam];
 
1428
 
 
1429
         if (!j)    //No event if we can't map the key to ASCII
 
1430
            break;
 
1431
            
 
1432
         //If we're not supposed to ignore caps lock, xlate keys on Caps Lock
 
1433
         if (GetKeyState(VK_CAPITAL) & 0x1)
 
1434
            if (ignoreCaps)
 
1435
               printf("Got a capslock!\n");
 
1436
            else
 
1437
               j = ( islower((char)j) ? toupper((char)j) : tolower((char)j) );
 
1438
         
 
1439
         //Modified version of STORE_EVENT... we flip window pointers
 
1440
         //in middle of processing after we get the mouse pos.  This
 
1441
         //lets us emulate X-style keyboard focus
 
1442
 
 
1443
         i = (EventTail + 1) % EVENT_Q_SIZE;
 
1444
         if (i != EventHead)
 
1445
            EventTail = i;
 
1446
         if (InSendMessage())
 
1447
            GetCursorPos(&pos);
 
1448
         else
 
1449
           {
 
1450
           *((DWORD *)&spos) = GetMessagePos();
 
1451
           pos.x = spos.x; pos.y = spos.y;
 
1452
           }
 
1453
 
 
1454
         //Change the source window in the middle of all this to the one
 
1455
         //the mouse is in.
 
1456
 
 
1457
         hwnd = WindowFromPoint( pos);
 
1458
         if (GetWindowLong(hwnd, GWL_WNDPROC) != (LONG) NetrekWndProc)
 
1459
            return 0; //Mouse is not in one of our windows
 
1460
 
 
1461
         if (!hwnd || hwnd == ((Window *)baseWin))
 
1462
            hwnd = ((Window *)w)->hwnd;
 
1463
 
 
1464
         LastPressHwnd = hwnd;
 
1465
 
 
1466
         ScreenToClient(hwnd, &pos);
 
1467
 
 
1468
         GET_STRUCT_PTR;
 
1469
 
 
1470
         EventQueue[EventTail].x = pos.x - win->border;
 
1471
         EventQueue[EventTail].y = pos.y - win->border;
 
1472
         EventQueue[EventTail].Window=(W_Window) win;
 
1473
         if ( win->type == WIN_MENU )
 
1474
           {
 
1475
           if (EventQueue[EventTail].y % (W_Textheight + MENU_PAD * 2 + MENU_BAR) >=
 
1476
                 W_Textheight + MENU_PAD * 2)
 
1477
               return (0);
 
1478
           EventQueue[EventTail].y /= (W_Textheight + MENU_PAD * 2 + MENU_BAR) ;
 
1479
           }
 
1480
 
 
1481
         EventQueue[EventTail].type=W_EV_KEY;
 
1482
 
 
1483
#ifdef CONTROL_KEY
 
1484
         if (use_control_key && (GetKeyState(VK_CONTROL) & ~0x1) )
 
1485
            EventQueue[EventTail].key = (char) j + 96;
 
1486
         else
 
1487
            EventQueue[EventTail].key=(char) j;
 
1488
#else
 
1489
         EventQueue[EventTail].key=(char)j;
 
1490
#endif
 
1491
         return(0);
 
1492
 
 
1493
      case WM_MOUSEMOVE:
 
1494
         GET_STRUCT_PTR;
 
1495
         SetCursor(win->cursor);
 
1496
 
 
1497
#if defined(MOTION_MOUSE) || defined(XTRA_MESSAGE_UI)
 
1498
         if  ((win->type != WIN_GRAPH) || (hwnd != LastPressHwnd))  
 
1499
            return(0);  // only allow in graphics windows and must be the window last clicked in
 
1500
                        // (the latter avoids a bug where Windows sends a mousemove message
 
1501
                        //  to a window exposed when the one on top is hidden/destroyed)
 
1502
 
 
1503
                 //Check to see if we are entering a message and should be looking
 
1504
                 //to place the message on hold
 
1505
                 if (messageon && messHoldThresh)
 
1506
                 {
 
1507
                         if (messMouseDelta)
 
1508
             {
 
1509
                 /* a^2 + b^2 = c^2 - messHoldThresh is c^2.
 
1510
                  * Keep a running total of (a^2 + b^2) */
 
1511
                 int x;
 
1512
 
 
1513
                 x = prev_pos.x - LOWORD(lParam);
 
1514
                 messMouseDelta += x*x;
 
1515
                 x = prev_pos.y - HIWORD(lParam);
 
1516
                 messMouseDelta += x*x;
 
1517
             } else {
 
1518
                 messMouseDelta++;
 
1519
                 prev_pos = MAKEPOINTS(lParam);
 
1520
             }
 
1521
             if ((messMouseDelta>=messHoldThresh) || 
 
1522
                 (wParam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)))
 
1523
                 message_hold();
 
1524
             return(0);
 
1525
         }
 
1526
 
 
1527
         if (! (wParam & (MK_LBUTTON | MK_MBUTTON | MK_RBUTTON)) )
 
1528
            return(0);  //We don't want to know about it if no mouse buttons are down
 
1529
 
 
1530
         //Check to see if the mouse has moved >= user_motion_thresh
 
1531
         thresh = abs (prev_pos.x - LOWORD(lParam)) + abs (prev_pos.y - HIWORD(lParam));
 
1532
         if (thresh < user_motion_thresh)
 
1533
            return (0);
 
1534
 
 
1535
         prev_pos = MAKEPOINTS(lParam);
 
1536
 
 
1537
         //Okay, we have an event - store and process further
 
1538
         STORE_EVENT_MOUSE;
 
1539
         EventQueue[EventTail].type = W_EV_BUTTON;
 
1540
 
 
1541
#ifdef SHIFTED_MOUSE
 
1542
         //Turn shift+button into a differnt code, and that sort of thing...
 
1543
         if (extended_mouse)
 
1544
            {
 
1545
            if (wParam & MK_CONTROL && wParam & MK_SHIFT)
 
1546
               {
 
1547
               if (wParam & MK_LBUTTON)
 
1548
                   EventQueue[EventTail].key = W_LBUTTON4;
 
1549
               else if (wParam & MK_MBUTTON)
 
1550
                   EventQueue[EventTail].key = W_MBUTTON4;
 
1551
               else if (wParam & MK_RBUTTON)
 
1552
                   EventQueue[EventTail].key = W_RBUTTON4;
 
1553
 
 
1554
               return(0);
 
1555
               }
 
1556
 
 
1557
            if (wParam & MK_SHIFT)
 
1558
               {
 
1559
               if (wParam & MK_LBUTTON)
 
1560
                   EventQueue[EventTail].key = W_LBUTTON2;
 
1561
               else if (wParam & MK_MBUTTON)
 
1562
                   EventQueue[EventTail].key = W_MBUTTON2;
 
1563
               else if (wParam & MK_RBUTTON)
 
1564
                   EventQueue[EventTail].key = W_RBUTTON2;
 
1565
 
 
1566
               return(0);
 
1567
               }
 
1568
 
 
1569
            if (wParam & MK_CONTROL)
 
1570
               {
 
1571
               if (wParam & MK_LBUTTON)
 
1572
                   EventQueue[EventTail].key = W_LBUTTON3;
 
1573
               else if (wParam & MK_MBUTTON)
 
1574
                   EventQueue[EventTail].key = W_MBUTTON3;
 
1575
               else if (wParam & MK_RBUTTON)
 
1576
                   EventQueue[EventTail].key = W_RBUTTON3;
 
1577
               return(0);
 
1578
               }
 
1579
            }
 
1580
 
 
1581
#endif /* SHIFTED_MOUSE */
 
1582
 
 
1583
         //Whew! If, after checking for all that, there are no shift keys,
 
1584
         //no controls keys, process this normally
 
1585
            if (wParam & MK_LBUTTON)
 
1586
                EventQueue[EventTail].key = W_LBUTTON;
 
1587
            else if (wParam & MK_MBUTTON)
 
1588
               EventQueue[EventTail].key = W_MBUTTON;
 
1589
            else if (wParam & MK_RBUTTON)
 
1590
                EventQueue[EventTail].key = W_RBUTTON;
 
1591
            return(0);
 
1592
 
 
1593
#endif /* MOTION_MOUSE */
 
1594
 
 
1595
         return (0);
 
1596
 
 
1597
 
 
1598
      //And now, for your amusement and edification, some of the more exotic
 
1599
      //mesages handled here for things like our scroll windows,
 
1600
      //background bitmap tiling, and dragging windows by their borders
 
1601
 
 
1602
      //Scroll bar moved message - from a scrolling window
 
1603
      case WM_VSCROLL:
 
1604
         GET_STRUCT_PTR;
 
1605
         i = GetScrollPos(hwnd, SB_VERT);
 
1606
         switch (LOWORD(wParam))
 
1607
            {
 
1608
            case SB_LINEDOWN:
 
1609
               i += 1;
 
1610
               break;
 
1611
            case SB_LINEUP:
 
1612
               i -= 1;
 
1613
               break;
 
1614
            case SB_PAGEDOWN:
 
1615
               i += win->TextHeight;
 
1616
               break;
 
1617
            case SB_PAGEUP:
 
1618
               i -= win->TextHeight;
 
1619
               break;
 
1620
            case SB_THUMBTRACK:
 
1621
            case SB_THUMBPOSITION:
 
1622
               i = HIWORD(wParam);
 
1623
               break;
 
1624
            default:
 
1625
               return(0);
 
1626
            }
 
1627
         SetScrollPos(hwnd, SB_VERT, i, TRUE);        //Move scroll
 
1628
         InvalidateRect(hwnd, &win->ClipRect, TRUE);  //Redraw text in window
 
1629
         UpdateWindow(hwnd);
 
1630
         return(0);
 
1631
 
 
1632
      //Trap WM_ERASEBKGRND, to handle windows with tiled backgrounds
 
1633
      case WM_ERASEBKGND:
 
1634
         GET_STRUCT_PTR;
 
1635
 
 
1636
         GetClientRect(hwnd, &r);
 
1637
         if (NetrekPalette)
 
1638
            {
 
1639
            SelectPalette((HDC)wParam, NetrekPalette, FALSE);
 
1640
            RealizePalette((HDC)wParam);
 
1641
            }
 
1642
 
 
1643
         if (!win->tiled)
 
1644
            {
 
1645
            FillRect((HDC)wParam, &r, colortable[BLACK].brush);
 
1646
            }
 
1647
         else
 
1648
            {
 
1649
            //As far as I can tell, the bitmap should be white on window bk color...
 
1650
            SetTextColor((HDC)wParam, colortable[BLACK].rgb);
 
1651
            SetBkColor((HDC)wParam, colortable[WHITE].rgb);
 
1652
   
 
1653
            //Select the bitmap
 
1654
            icon = win->TileIcon;
 
1655
            SelectObject(GlobalMemDC, icon->bm);
 
1656
   
 
1657
             //Paste the bitmap into the window
 
1658
             for (i=0; i<r.bottom; i+=icon->height)
 
1659
               for (j=0; j<r.right; j+=icon->width)
 
1660
                  BitBlt(  (HDC)wParam, j, i,
 
1661
                           icon->width, icon->height, GlobalMemDC, 0, 0, SRCCOPY );
 
1662
            }
 
1663
   
 
1664
          return TRUE;
 
1665
 
 
1666
      //Return "in caption" whenever the mouse is on the border, or in client otherwise
 
1667
      case WM_NCHITTEST:
 
1668
         i = DefWindowProc(hwnd, WM_NCHITTEST, wParam, lParam);
 
1669
         if (i == HTCLIENT)
 
1670
            {
 
1671
            GET_STRUCT_PTR;
 
1672
            pos.x = LOWORD(lParam); pos.y = HIWORD(lParam);
 
1673
            ScreenToClient(hwnd, &pos);
 
1674
            return ( ( (pos.x < win->border) || (pos.x >= win->ClipRect.right) ||
 
1675
                     (pos.y < win->border) || (pos.y >= win->ClipRect.bottom) ) ?
 
1676
                  HTCAPTION :
 
1677
                  HTCLIENT );
 
1678
            }
 
1679
         else if (i == HTBORDER)
 
1680
            return HTCAPTION;
 
1681
         else
 
1682
            return i;
 
1683
 
 
1684
      //This message sent from another thread to indicate a window should be destroyed,
 
1685
      // which only the main thread can do
 
1686
      case WM_CROSS_THREAD_DESTROY:
 
1687
         DestroyWindow((HWND)wParam);
 
1688
         return 0;
 
1689
      
 
1690
      //Delete all of our data, etc, when the window is killed
 
1691
      //DON'T PRINTF() HERE!!! Unless of course you feel like crashing...
 
1692
      case WM_DESTROY:
 
1693
         GET_STRUCT_PTR;
 
1694
 
 
1695
         if (win->UsingCreatedCursor)
 
1696
            DeleteObject( win->cursor );
 
1697
 
 
1698
         //If it is a menu or scroll window, free the menu item data
 
1699
         if ( win->type == WIN_MENU )
 
1700
            {
 
1701
            for (i=0; i<win->NumItems; i++)
 
1702
               if (win->items[i].string)
 
1703
                  free((void *)win->items[i].string);
 
1704
            free((void *)win->items);
 
1705
            }
 
1706
         else if ( win->type == WIN_SCROLL)
 
1707
            {
 
1708
            struct stringList *p = win->strings;
 
1709
            struct stringList *tmp;
 
1710
            while (p)
 
1711
               {
 
1712
               tmp = p->next;
 
1713
               free((void *)p->string);
 
1714
               free((void *)p);
 
1715
               p = tmp;
 
1716
               }
 
1717
            }
 
1718
 
 
1719
         //Free the Window structure
 
1720
         free((void *)win);
 
1721
 
 
1722
         return(0);
 
1723
 
 
1724
      case WM_SETFOCUS:
 
1725
          if (hwnd==((Window *)baseWin)->hwnd)
 
1726
          {
 
1727
              SetTrekSysColors();
 
1728
              return (0);
 
1729
          }
 
1730
          break;
 
1731
 
 
1732
      case WM_KILLFOCUS:
 
1733
          //if (baseWin && (((void *)wParam)==((Window *)baseWin)->hwnd))
 
1734
          if (hwnd==((Window *)baseWin)->hwnd)
 
1735
          {
 
1736
              ResetSysColors();
 
1737
              return (0);
 
1738
          }
 
1739
          break;
 
1740
 
 
1741
      }
 
1742
 
 
1743
   return DefWindowProc(hwnd, msg, wParam, lParam);
 
1744
   }
 
1745
 
 
1746
//Slightly diffent from W_EventsPending -- does not get any new events, merely
 
1747
//reads from out queue.
 
1748
int W_EventsQueued()
 
1749
   {
 
1750
   return  (EventHead != EventTail);
 
1751
   }
 
1752
 
 
1753
 
 
1754
//Draw a line.. yay, what a challenge
 
1755
//Well, considering XDrawLine goes from pt to pt, and
 
1756
//LineTo doesn't draw the last point, a bigger one -SAC 07 Aug 1996
 
1757
//Changed to SACLineTo 25 Aug 96
 
1758
void W_MakeLine(W_Window window, int x0, int y0, int x1, int y1, W_Color color)
 
1759
   {
 
1760
   register HDC hdc;
 
1761
   register HWND hwnd;
 
1762
   register int border;
 
1763
   FNHEADER_VOID;
 
1764
   border=win->border;
 
1765
 
 
1766
   hdc = GetDC(win->hwnd);
 
1767
   if (NetrekPalette)
 
1768
      {
 
1769
      SelectPalette(hdc, NetrekPalette, FALSE);
 
1770
      RealizePalette(hdc);
 
1771
      }
 
1772
   SelectObject(hdc, colortable[color].pen);
 
1773
   MoveTo(hdc, x0+border, y0+border);
 
1774
   LineTo(hdc, x1+border, y1+border);
 
1775
   /* Get that last point in there ... -SAC */
 
1776
   SetPixel(hdc, x1+border, y1+border, colortable[color].rgb);
 
1777
   ReleaseDC(win->hwnd, hdc);
 
1778
 
 
1779
   }
 
1780
 
 
1781
//We don't need to cache...
 
1782
void W_CacheLine(W_Window window, int x0, int y0, int x1, int y1, W_Color color)
 
1783
{
 
1784
   W_MakeLine(window, x0, y0, x1, y1, color);
 
1785
}
 
1786
 
 
1787
void W_FlushLineCaches(W_Window window)
 
1788
{
 
1789
}
 
1790
 
 
1791
// Make *many* lines :)
 
1792
void W_MakeLines(W_Window window, int *x0, int *y0, int *x1, int *y1, int num, W_Color color)
 
1793
{
 
1794
   register HDC hdc;
 
1795
   register int border;
 
1796
   FNHEADER_VOID;
 
1797
   border=win->border;
 
1798
 
 
1799
   hdc = GetDC(win->hwnd);
 
1800
   if (NetrekPalette)
 
1801
      {
 
1802
      SelectPalette(hdc, NetrekPalette, FALSE);
 
1803
      RealizePalette(hdc);
 
1804
      }
 
1805
   SelectObject(hdc, colortable[color].pen);
 
1806
 
 
1807
   while (num)
 
1808
   {
 
1809
      num--;
 
1810
      MoveTo(hdc, x0[num]+border, y0[num]+border);
 
1811
      LineTo(hdc, x1[num]+border, y1[num]+border);
 
1812
          SetPixel(hdc, x1[num]+border, y1[num]+border, colortable[color].rgb);
 
1813
   }
 
1814
   
 
1815
   ReleaseDC(win->hwnd, hdc);
 
1816
 
 
1817
   return;
 
1818
}
 
1819
 
 
1820
 
 
1821
//Draw a dashed line, inidicating a tractor/pressor beam
 
1822
//Do it manually though, as Win32 sucks at creating arbitrary pens
 
1823
//Apologies if this isn't perfect, it's been a while since I had to
 
1824
//write an integer linedraw routine.
 
1825
//Whoops! Can't swap the points - 26 Aug 96
 
1826
#define CINIT 1<<31
 
1827
void W_MakeTractLine (W_Window window, int x0, int y0, int x1, int y1, W_Color color)
 
1828
   {
 
1829
HDC hdc;
 
1830
HWND hwnd;
 
1831
int border;
 
1832
unsigned __int32 d1,d2,d3;
 
1833
int dp /* Dash pointer */, dc /* Dash counter */;
 
1834
register int Md /* Major direction */, md; /* minor direction */
 
1835
/* 3 blank, 1 solid... etc. -SAC */
 
1836
int dashdesc[] = { 10, 1 };
 
1837
 
 
1838
FNHEADER_VOID;
 
1839
 
 
1840
    dashdesc[0] = intDefault("tpdotdist",dashdesc[0]);
 
1841
 
 
1842
    md = x0;
 
1843
    x0 = x1;
 
1844
    x1 = md;
 
1845
    md = y0;
 
1846
    y0 = y1;
 
1847
    y1 = md;
 
1848
 
 
1849
    hdc = GetDC(win->hwnd);
 
1850
    if (NetrekPalette)
 
1851
      {
 
1852
      SelectPalette(hdc, NetrekPalette, FALSE);
 
1853
      RealizePalette(hdc);
 
1854
      }
 
1855
 
 
1856
    border=win->border;
 
1857
    x0 += border;
 
1858
    y0 += border;
 
1859
    x1 += border;
 
1860
    y1 += border;
 
1861
    d2 = abs(x0-x1);
 
1862
    d3 = abs(y0-y1);
 
1863
    if (d2 > d3)
 
1864
    {
 
1865
        /* Major axis is x */
 
1866
 
 
1867
        if (d3) d1 = (((__int64) d3)<<32)/d2;
 
1868
           else d1 = 1;
 
1869
        d2 = CINIT;
 
1870
        Md = x0 < x1 ? 1 : -1;
 
1871
        md = y0 < y1 ? 1 : -1;
 
1872
        dp = 0;
 
1873
        dc = dashdesc[dp];
 
1874
 
 
1875
        while ((Md==1 ? x0 <= x1 : x0 >= x1))
 
1876
        {
 
1877
            if (dp & 1) // An odd number
 
1878
                SetPixel(hdc, x0, y0, colortable[color].rgb);
 
1879
            dc--;
 
1880
            if (dc<1)
 
1881
            {
 
1882
                if (++dp >= 2)
 
1883
                {
 
1884
                    dp = 0;
 
1885
                    dashdesc[dp]+=2;
 
1886
                }
 
1887
                dc = dashdesc[dp];
 
1888
            }
 
1889
 
 
1890
            x0+=Md;
 
1891
            d3 = d2;
 
1892
            d2+=d1;
 
1893
            if (!d1 || (d3 > d2))
 
1894
            {
 
1895
                y0 += md;
 
1896
                dc--;
 
1897
            }
 
1898
        }
 
1899
    } else {
 
1900
        /* Major axis is y */
 
1901
 
 
1902
        if (d2) d1 = (((__int64) d2)<<32)/d3;
 
1903
           else d1 = 1;
 
1904
        d2 = CINIT;
 
1905
 
 
1906
        Md = y0 < y1 ? 1 : -1;
 
1907
        md = x0 < x1 ? 1 : -1;
 
1908
        dp = 0;
 
1909
        dc = dashdesc[dp];
 
1910
 
 
1911
        while ((Md==1 ? y0 <= y1 : y0 >= y1))
 
1912
        {
 
1913
            if (dp & 1) // An odd number
 
1914
                SetPixel(hdc, x0, y0, colortable[color].rgb);
 
1915
            dc--;
 
1916
            if (dc<1)
 
1917
            {
 
1918
                if (++dp >= 2)
 
1919
                {
 
1920
                    dp = 0;
 
1921
                    dashdesc[dp]+=2;
 
1922
                }
 
1923
                dc = dashdesc[dp];
 
1924
            }
 
1925
 
 
1926
            y0+=Md;
 
1927
            d3 = d2;
 
1928
            d2+=d1;
 
1929
            if (!d1 || (d3 > d2))
 
1930
            {
 
1931
                x0 += md;
 
1932
                dc--;
 
1933
            }
 
1934
        }
 
1935
    }
 
1936
 
 
1937
    ReleaseDC(win->hwnd, hdc);
 
1938
    return;
 
1939
}
 
1940
 
 
1941
//Draw a dashed line, inidicating a tractor/pressor beam
 
1942
void Old_W_MakeTractLine (W_Window window, int x0, int y0, int x1, int y1, W_Color color)
 
1943
   {
 
1944
   register HDC hdc;
 
1945
   register HWND hwnd;
 
1946
   register int border;
 
1947
   FNHEADER_VOID;
 
1948
   border=win->border;
 
1949
   
 
1950
   hdc = GetDC(win->hwnd);
 
1951
   if (NetrekPalette)
 
1952
      {
 
1953
      SelectPalette(hdc, NetrekPalette, FALSE);
 
1954
      RealizePalette(hdc);
 
1955
      }
 
1956
   SetBkMode(hdc, TRANSPARENT);
 
1957
   SelectObject(hdc, colortable[color].dashedpen);
 
1958
   MoveTo(hdc, x0+border, y0+border);
 
1959
   LineTo(hdc, x1+border, y1+border);
 
1960
   ReleaseDC(win->hwnd, hdc);
 
1961
 
 
1962
   }
 
1963
 
 
1964
//The same as MakeLine, for now... at least, for the X code it was.
 
1965
void W_MakePhaserLine (W_Window window, int x0, int y0, int x1, int y1, W_Color color)
 
1966
   {
 
1967
   register HDC hdc;
 
1968
   register HWND hwnd;
 
1969
   register int border;
 
1970
   FNHEADER_VOID;
 
1971
   border=win->border;
 
1972
 
 
1973
   hdc = GetDC(win->hwnd);
 
1974
   if (NetrekPalette)
 
1975
      {
 
1976
      SelectPalette(hdc, NetrekPalette, FALSE);
 
1977
      RealizePalette(hdc);
 
1978
      }
 
1979
   SelectObject(hdc, colortable[color].pen);
 
1980
   MoveTo(hdc, x0+border, y0+border);
 
1981
   LineTo(hdc, x1+border, y1+border);
 
1982
   SetPixel(hdc, x1+border, y1+border, colortable[color].rgb);
 
1983
   ReleaseDC(win->hwnd, hdc);
 
1984
 
 
1985
   }
 
1986
 
 
1987
//Draw a triangle. Yay.
 
1988
void W_WriteTriangle (W_Window window, int x, int y, int s, int t, W_Color color)
 
1989
   {
 
1990
   register HDC hdc;
 
1991
   register HWND hwnd;
 
1992
   POINT points[3];
 
1993
   FNHEADER_VOID;
 
1994
 
 
1995
   x+= win->border;
 
1996
   y+= win->border;
 
1997
   
 
1998
   if (t == 0)
 
1999
      {
 
2000
      points[0].x = x;
 
2001
      points[0].y = y;
 
2002
      points[1].x = x + s;
 
2003
      points[1].y = y - s;
 
2004
      points[2].x = x - s;
 
2005
      points[2].y = y - s;
 
2006
      }
 
2007
   else
 
2008
      {
 
2009
      points[0].x = x;
 
2010
      points[0].y = y;
 
2011
      points[1].x = x + s;
 
2012
      points[1].y = y + s;
 
2013
      points[2].x = x - s;
 
2014
      points[2].y = y + s;
 
2015
      }
 
2016
 
 
2017
 
 
2018
   hdc = GetDC(win->hwnd);
 
2019
   if (NetrekPalette)
 
2020
      {
 
2021
      SelectPalette(hdc, NetrekPalette, FALSE);
 
2022
      RealizePalette(hdc);
 
2023
      }
 
2024
   SelectObject(hdc, colortable[color].pen);
 
2025
   SelectObject(hdc, GetStockObject(NULL_BRUSH));
 
2026
 
 
2027
   Polygon(hdc, points, 3);
 
2028
 
 
2029
   ReleaseDC(win->hwnd, hdc);
 
2030
   }
 
2031
 
 
2032
 
 
2033
//Put some text in a window. This is a straight ExtTextOut call if it's a
 
2034
//graphics window, a ExtTextOut call with mapped coordinates if it's a
 
2035
//text window, an addition to a listbox if it's a scrolling window
 
2036
//(in which case the position is ignored: it always goes at the end
 
2037
//of the list) and a call to set a menu item if it's a menu window.
 
2038
void W_WriteText(W_Window window, int x,int y,W_Color color,char *str,int len, W_Font font)
 
2039
   {
 
2040
   HDC hdc;
 
2041
   RECT r;
 
2042
   SIZE ext;
 
2043
   register int border;
 
2044
   FNHEADER_VOID;
 
2045
   border = win->border;
 
2046
 
 
2047
   switch (win->type)
 
2048
      {
 
2049
      case WIN_TEXT:
 
2050
         x = x * W_Textwidth + WIN_EDGE;
 
2051
         y = y * W_Textheight+MENU_PAD;
 
2052
         /* fall through */
 
2053
 
 
2054
      case WIN_GRAPH:
 
2055
         hdc = GetDC(win->hwnd);
 
2056
         if (NetrekPalette)
 
2057
            {
 
2058
            SelectPalette(hdc, NetrekPalette, FALSE);
 
2059
            RealizePalette(hdc);
 
2060
            }
 
2061
 
 
2062
         SelectObject(hdc, (HFONT)font);
 
2063
         SetTextColor(hdc, colortable[color].rgb);
 
2064
         SetBkColor(hdc, colortable[BLACK].rgb);
 
2065
 
 
2066
         GetTextExtentPoint(hdc, str, len, &ext);
 
2067
 
 
2068
         //do a rectangle intersection with the clipping rect, inlined for speed
 
2069
         x+=border; y+=border;
 
2070
         r.left = max(x, border);
 
2071
         r.right= min(x+ext.cx, win->ClipRect.right);
 
2072
         if (r.right < r.left)
 
2073
            return;                                      //Horizantal extents do not overlap
 
2074
         r.top = max(y, border);
 
2075
         r.bottom = min(y+ext.cy, win->ClipRect.bottom);
 
2076
         if (r.bottom < r.top)
 
2077
            return;                                      //Vertical extents do not overlap
 
2078
 
 
2079
         ExtTextOut( hdc, x, y, ETO_CLIPPED|ETO_OPAQUE, &r, str, len, NULL);
 
2080
 
 
2081
         ReleaseDC(win->hwnd, hdc);
 
2082
         break;
 
2083
 
 
2084
      case WIN_SCROLL:
 
2085
         str[len]=0;
 
2086
         AddToScrolling(win, color, str, len);
 
2087
         break;
 
2088
 
 
2089
      case WIN_MENU:
 
2090
         str[len]=0;
 
2091
         ChangeMenuItem(win, y, str, len, color);
 
2092
         break;
 
2093
 
 
2094
      default:
 
2095
         printf("Unknown window type in W_WriteText");
 
2096
      }
 
2097
   }
 
2098
 
 
2099
 
 
2100
void W_MaskText(W_Window window, int x,int y,W_Color color,char *str,int len, W_Font font)
 
2101
   {
 
2102
   HDC hdc;
 
2103
   FNHEADER_VOID;
 
2104
 
 
2105
   switch (win->type)
 
2106
      {
 
2107
      case WIN_TEXT:
 
2108
         x = x * W_Textwidth + WIN_EDGE;
 
2109
         y = y * W_Textheight+MENU_PAD;
 
2110
         /* fall through */
 
2111
 
 
2112
      case WIN_GRAPH:
 
2113
         hdc = GetDC(win->hwnd);
 
2114
         if (NetrekPalette)
 
2115
            {
 
2116
            SelectPalette(hdc, NetrekPalette, FALSE);
 
2117
            RealizePalette(hdc);
 
2118
            }
 
2119
         SelectObject(hdc, (HFONT)font);
 
2120
         SetTextColor(hdc, colortable[color].rgb);
 
2121
         SetBkMode(hdc, TRANSPARENT);
 
2122
 
 
2123
         ExtTextOut( hdc, x+win->border, y+win->border, ETO_CLIPPED, &(win->ClipRect), str, len, NULL);
 
2124
 
 
2125
         ReleaseDC(win->hwnd, hdc);
 
2126
         break;
 
2127
 
 
2128
      case WIN_SCROLL:
 
2129
         str[len]=0;
 
2130
         AddToScrolling(win, color, str, len);
 
2131
         break;
 
2132
 
 
2133
      case WIN_MENU:
 
2134
         str[len]=0;
 
2135
         ChangeMenuItem(win, y, str, len, color);
 
2136
         break;
 
2137
 
 
2138
      default:
 
2139
         printf("Unknown window type in W_WriteText");
 
2140
      }
 
2141
   }
 
2142
 
 
2143
 
 
2144
// Succesively dump each BitmapList
 
2145
void W_ShowBitmaps()
 
2146
{
 
2147
    static struct BitmapList *pBM=0;
 
2148
    static W_Window tmp = 0;
 
2149
    HDC hdc;
 
2150
    int t;
 
2151
 
 
2152
    printf("pBM: %p\nbmlCount: %d",pBM,bmlCount);
 
2153
 
 
2154
    if (!pBM)
 
2155
    {
 
2156
        pBM = CurrentBitmap;
 
2157
        if (!tmp)
 
2158
            tmp = W_MakeWindow("Bitmap",10,10,BIGBITMAP_WIDTH+5,BIGBITMAP_HEIGHT+5,
 
2159
                               NULL,0,W_Black);
 
2160
        if (tmp)
 
2161
            W_MapWindow(tmp);
 
2162
    } else
 
2163
    {
 
2164
        pBM = pBM->next;
 
2165
    }
 
2166
 
 
2167
    if (pBM && tmp)
 
2168
    {
 
2169
        printf("tmp: %p\n",tmp);
 
2170
        if (!SelectObject(GlobalMemDC, pBM->bm))
 
2171
            goto fail;
 
2172
        if (!(hdc = GetDC( ((Window *)tmp)->hwnd)))
 
2173
            goto fail;
 
2174
        BitBlt(hdc,0,0,BIGBITMAP_WIDTH, BIGBITMAP_HEIGHT, GlobalMemDC, 0, 0, SRCCOPY);
 
2175
        SelectObject(GlobalMemDC, GlobalOldMemDCBitmap);
 
2176
        ReleaseDC(((Window *)tmp)->hwnd, hdc);
 
2177
    fail: ;
 
2178
 
 
2179
    } else
 
2180
    {
 
2181
        // We've reached the end, kill the window.
 
2182
        if (tmp)
 
2183
            W_DestroyWindow(tmp);
 
2184
        pBM = NULL;
 
2185
    }
 
2186
 
 
2187
    return;
 
2188
}
 
2189
 
 
2190
//Creates a bitmap object out of X11 bitmap data...
 
2191
//What we actually do is allocate a number of 240x240 bitmaps, and copy
 
2192
//each image to a new section of the bitmap. Part of the W_Icon structure
 
2193
//that we return has an x,y index into this bitmap. In this fashion,
 
2194
//we avoid allocating every bitmap handle in the system for the 1,000 or so
 
2195
//bitmaps that we need.
 
2196
//Fixed to actually work as intended - 19 Aug 96 SAC
 
2197
W_Icon W_StoreBitmap(int width,int height,char *bits,W_Window window)
 
2198
   {
 
2199
   static int CurX=0, CurY=-1, MaxY=0;
 
2200
   struct Icon *bitmap=0;
 
2201
   struct BitmapList *NewBitmap=0;
 
2202
   unsigned char *bits2=0;
 
2203
   HBITMAP temp=0,temp2=0;
 
2204
   int newwidth,re;
 
2205
 
 
2206
   FNHEADER;
 
2207
 
 
2208
   if (CurY==-1)
 
2209
       CurY = BIGBITMAP_HEIGHT+1; // Force the first bitmap to be created
 
2210
 
 
2211
   //Allocate memory for the bitmap structure and convert the
 
2212
   //X11 bitmap into a useful form
 
2213
   if (!(bitmap = (struct Icon *) malloc(sizeof(struct Icon))) ||
 
2214
         !(bits2 = X11toDIB(bits, width, height)) )
 
2215
      goto memfail;
 
2216
 
 
2217
   newwidth = ((width + 0xf) & ~0xf);
 
2218
   //Create a temporary Windows bitmap object
 
2219
   if (! (temp = CreateBitmap(newwidth, height, 1, 1, bits2)) )
 
2220
      goto memfail;
 
2221
 
 
2222
   free(bits2);
 
2223
 
 
2224
   //Save the width, height, window...
 
2225
   bitmap->hwnd = win->hwnd;
 
2226
   bitmap->width = width;
 
2227
   bitmap->height = height;
 
2228
   bitmap->ClipRectAddr = &win->ClipRect;
 
2229
 
 
2230
   //Is the bitmap large enough to justify it's own HBitmap, or
 
2231
   //should we make it part of a "Big Bitmap"?
 
2232
   if ( (width>(BIGBITMAP_WIDTH/2)) && (height>(BIGBITMAP_HEIGHT/2)) ) //if it's big....
 
2233
      {
 
2234
      if ( !(NewBitmap = (struct BitmapList *) malloc(sizeof(struct BitmapList))) )
 
2235
         goto memfail;
 
2236
 
 
2237
      //Copy the bitmap to new location so we can mirror it
 
2238
      if ( !(temp2 = CreateBitmap(width, height, 1, 1, NULL)) )
 
2239
         goto memfail;
 
2240
 
 
2241
      printf(".");
 
2242
      bmlCount++;
 
2243
 
 
2244
      //Mirror bitmap
 
2245
      SelectObject(GlobalMemDC, temp);
 
2246
      SelectObject(GlobalMemDC2, temp2);
 
2247
      StretchBlt(GlobalMemDC2, 0, 0, width, height, GlobalMemDC, newwidth-1, 0, -width, height, SRCCOPY);
 
2248
 
 
2249
      NewBitmap->bm = temp2;
 
2250
      bitmap->bm = temp2;
 
2251
      bitmap->x = 0;
 
2252
      bitmap->y = 0;
 
2253
 
 
2254
      if (CurrentBitmap)
 
2255
         {
 
2256
         NewBitmap->next = CurrentBitmap->next; //Insert the entry in the linked list
 
2257
         CurrentBitmap->next = NewBitmap;       //as the item after CurrentBitmap
 
2258
         }
 
2259
      else
 
2260
         {
 
2261
         printf("Got impossible internal error in W_StoreBitmap(). Please report to author.\n");
 
2262
         exit(-1);
 
2263
         }
 
2264
 
 
2265
      }
 
2266
   else  // Small(ish)
 
2267
      {
 
2268
      //Figure out where to store the image in the current big bitmap
 
2269
      width = (width + 0x7) & ~0x7; //Round up to nearest eight bits
 
2270
      //height = (height + 0x7) & ~0x7;
 
2271
      if ( (CurX + width) > BIGBITMAP_WIDTH || (CurY + height) > BIGBITMAP_HEIGHT )
 
2272
         {
 
2273
         CurX = 0;               //Advance to next line
 
2274
         CurY += MaxY;
 
2275
         MaxY = 0;
 
2276
         if ( (CurY + height) > BIGBITMAP_HEIGHT)
 
2277
            {
 
2278
            HBRUSH SpeckleBr;
 
2279
            HBITMAP hb ;
 
2280
            WORD mask[] = { 0xaaaa, 0x5555 }; 
 
2281
            RECT bmrect;
 
2282
 
 
2283
            if ( !(NewBitmap = (struct BitmapList *) malloc(sizeof(struct BitmapList))) ||
 
2284
                 !(NewBitmap->bm = CreateBitmap(BIGBITMAP_WIDTH, BIGBITMAP_HEIGHT, 1,1, NULL)) )
 
2285
               goto memfail;
 
2286
 
 
2287
            bmlCount++;
 
2288
 
 
2289
            NewBitmap->next = CurrentBitmap;    //Advance to next bitmap
 
2290
            CurrentBitmap = NewBitmap;          //Store in LL
 
2291
 
 
2292
            CurX = 0;
 
2293
            CurY = 0;
 
2294
            MaxY = 0;
 
2295
            bmrect.top = 0;
 
2296
            bmrect.left = 0;
 
2297
            bmrect.right = BIGBITMAP_WIDTH-1;
 
2298
            bmrect.bottom = BIGBITMAP_HEIGHT-1;
 
2299
 
 
2300
            hb = CreateBitmap(2,2,1,1,(const void *) mask   );
 
2301
            SpeckleBr = CreatePatternBrush(hb);
 
2302
            DeleteObject(hb);
 
2303
            SelectObject(GlobalMemDC2, CurrentBitmap->bm);
 
2304
            FillRect(GlobalMemDC2, &bmrect, SpeckleBr);
 
2305
            DeleteObject(SpeckleBr);
 
2306
            SelectObject(GlobalMemDC2, GlobalOldMemDC2Bitmap);
 
2307
 
 
2308
            }
 
2309
         }
 
2310
 
 
2311
      //Copy the bits to their new location, mirroring as we go
 
2312
      if (!SelectObject(GlobalMemDC, temp))
 
2313
          printf("SelectObject(DC, temp) bombed");
 
2314
      if (!SelectObject(GlobalMemDC2, CurrentBitmap->bm))
 
2315
          printf("SelectObject(DC2,CurrentBitmap->tm) bombed");
 
2316
 
 
2317
#ifdef FOOBAR
 
2318
      // Don't ask -SAC
 
2319
      re = 100;
 
2320
      while (!StretchBlt(GlobalMemDC2, CurX, CurY, width, height, GlobalMemDC, newwidth-1, 0, -width, height, SRCCOPY) &&
 
2321
             re--);
 
2322
      if (re<100)
 
2323
      {
 
2324
          DWORD x;
 
2325
          x = GetLastError();
 
2326
          printf("   CurX=%3d CurY=%3d width=%3d height=%3d newwidth-1=%3d -width=%3d re=%3d %d\n",
 
2327
                 CurX, CurY, width, height, newwidth-1, -width, re, x);
 
2328
      } else {
 
2329
          printf("++ CurX=%3d CurY=%3d width=%3d height=%3d newwidth-1=%3d -width=%3d\n",
 
2330
                 CurX, CurY, width, height, newwidth-1, -width);
 
2331
      }
 
2332
#else
 
2333
      StretchBlt(GlobalMemDC2, CurX, CurY, width, height, GlobalMemDC, newwidth-1, 0, -width, height, SRCCOPY);
 
2334
   #endif
 
2335
 
 
2336
      MaxY = max(MaxY, height);    //The current row (of bitmaps) max height
 
2337
 
 
2338
      //Store the position in the big bitmap, and increment the current X pointer
 
2339
      bitmap->bm = CurrentBitmap->bm;
 
2340
      bitmap->x = CurX;
 
2341
      bitmap->y = CurY;
 
2342
      CurX += width;
 
2343
      }
 
2344
 
 
2345
   SelectObject(GlobalMemDC, GlobalOldMemDCBitmap);   //So we don't crunch on the next line...
 
2346
   DeleteObject(temp);
 
2347
   SelectObject(GlobalMemDC2, GlobalOldMemDC2Bitmap); //Bitmaps can only be selected into one
 
2348
                                                      //DC at a time, so deselect it from here.
 
2349
   return (W_Icon) bitmap;
 
2350
 
 
2351
memfail:
 
2352
   printf("Memory allocation or CreateBitmap() failure in StoreBitmap\n");
 
2353
   if (bits2) free(bits2);
 
2354
   if (bitmap) free(bitmap);
 
2355
   if (NewBitmap) free(NewBitmap);
 
2356
   if (temp) DeleteObject(temp);
 
2357
   if (temp2) DeleteObject(temp2);
 
2358
   return NULL;
 
2359
   }
 
2360
 
 
2361
//Put an image on the screen (yay!). Because of all the #$%#$ work that
 
2362
//has gone into storing the bitmaps (see above), this is thankfully
 
2363
//a low-overhead call - almost directly translates into the GDI BitBlt
 
2364
void W_WriteBitmap(int x, int y, W_Icon icon, W_Color color)
 
2365
   {
 
2366
   register struct Icon *bitmap = (struct Icon *)icon;
 
2367
   register int border,width,height;
 
2368
   register int srcx,srcy;
 
2369
   HDC hdc;
 
2370
 
 
2371
   //Fast (I hope) rectangle intersection, don't overwrite our borders
 
2372
   srcx=bitmap->x;
 
2373
   srcy=bitmap->y;
 
2374
   border=bitmap->ClipRectAddr->top;
 
2375
   x+=border; y+=border;
 
2376
   if (x < border)
 
2377
     {
 
2378
     width = bitmap->width - (border-x);
 
2379
     srcx += border-x;
 
2380
     x=border;
 
2381
     }
 
2382
   else if ( (width = bitmap->ClipRectAddr->right-x) > bitmap->width)
 
2383
      width = bitmap->width;
 
2384
   if (y<border)
 
2385
     {
 
2386
     height = bitmap->height - (border-y);
 
2387
     srcy += (border-y);
 
2388
     y=border;
 
2389
     }
 
2390
   else if ( (height = bitmap->ClipRectAddr->bottom-y) > bitmap->height)
 
2391
      height = bitmap->height;
 
2392
 
 
2393
   hdc = GetDC( bitmap->hwnd );
 
2394
   if (NetrekPalette)
 
2395
      {
 
2396
      SelectPalette(hdc, NetrekPalette, FALSE);
 
2397
      RealizePalette(hdc);
 
2398
      }
 
2399
   SelectObject(GlobalMemDC, bitmap->bm );
 
2400
 
 
2401
   //Set the color of the bitmap
 
2402
   //(oddly enough, 1-bit = bk color, 0-bit = text (fg) color)
 
2403
   SetBkColor(hdc, colortable[color].rgb);
 
2404
   SetTextColor(hdc, colortable[BLACK].rgb);
 
2405
 
 
2406
   BitBlt(hdc, x, y,                                //Copy the bitmap
 
2407
            width,
 
2408
            height,
 
2409
            GlobalMemDC,
 
2410
            srcx,
 
2411
            srcy,
 
2412
            SRCPAINT);                                   // <-- using OR mode
 
2413
 
 
2414
   ReleaseDC( bitmap->hwnd, hdc);
 
2415
   }
 
2416
 
 
2417
void W_TileWindow(W_Window window, W_Icon icon)
 
2418
   {
 
2419
   FNHEADER_VOID;
 
2420
 
 
2421
   win->tiled = TRUE;
 
2422
   win->TileIcon = (struct Icon *)icon;
 
2423
 
 
2424
   InvalidateRect(win->hwnd, NULL, TRUE);
 
2425
   UpdateWindow(win->hwnd);
 
2426
   }
 
2427
 
 
2428
void W_UnTileWindow(W_Window window)
 
2429
   {
 
2430
   FNHEADER_VOID;
 
2431
 
 
2432
   if (!win->tiled)
 
2433
      return;
 
2434
 
 
2435
   win->tiled = FALSE;
 
2436
 
 
2437
   InvalidateRect(win->hwnd, NULL, TRUE);
 
2438
   UpdateWindow(win->hwnd);
 
2439
   }
 
2440
 
 
2441
 
 
2442
int W_WindowWidth(W_Window window)
 
2443
   {
 
2444
   FNHEADER;
 
2445
 
 
2446
   return (win->ClipRect.right - win->border);
 
2447
   }
 
2448
 
 
2449
int W_WindowHeight(W_Window window)
 
2450
   {
 
2451
   FNHEADER;
 
2452
 
 
2453
   return (win->ClipRect.bottom - win->border);
 
2454
   }
 
2455
 
 
2456
//We fake window events as a socket, by using this magic number
 
2457
//and a fudge in our implementation of select()... 
 
2458
int W_Socket()
 
2459
   {
 
2460
   return(0x0CABBABE); //Magic number, can be anything but must match winmain.c's select()
 
2461
   }
 
2462
 
 
2463
void W_Beep()
 
2464
   {
 
2465
   MessageBeep(MB_ICONEXCLAMATION);
 
2466
   }
 
2467
 
 
2468
void W_SetIconWindow(W_Window main, W_Window icon)
 
2469
   {
 
2470
   /*
 
2471
    * MS-Windows requires an icon, i.e. a pixmap, not a window, as the iconized image.
 
2472
    * So, ignore this. We use our own special blend of 11 herbs and spices, stored
 
2473
    * in the resource file, and coated in crispy batter, as the icon for all of our windows.
 
2474
    */
 
2475
   }
 
2476
 
 
2477
//Easy enough... except for the fact that only the thread which created the window
 
2478
// can destroy it. So if we are not the main thread we post a message
 
2479
void W_DestroyWindow(W_Window window)
 
2480
   {
 
2481
   FNHEADER_VOID;
 
2482
#ifdef DEBUG
 
2483
   printf("Destroying %X\n", win->hwnd);
 
2484
#endif
 
2485
   if (GetCurrentThreadId() == MainThreadID)
 
2486
      DestroyWindow(win->hwnd);
 
2487
   else
 
2488
      PostMessage(AnyWindow, WM_CROSS_THREAD_DESTROY, (WPARAM)win->hwnd, 0);
 
2489
   }
 
2490
 
 
2491
//Redraw a menu window.
 
2492
void RedrawMenu(Window *win, HDC hdc)
 
2493
   {
 
2494
   int count;
 
2495
   RECT r;
 
2496
 
 
2497
   SelectObject(hdc, (HFONT)W_RegularFont);
 
2498
 
 
2499
   r.left = win->border;
 
2500
   r.right = win->ClipRect.right;
 
2501
 
 
2502
   for (count = 1; count < win->NumItems; count++)
 
2503
      {
 
2504
      r.top =  count * (W_Textheight + MENU_PAD * 2) + (count - 1) * MENU_BAR + win->border;
 
2505
      r.bottom = r.top + MENU_BAR;
 
2506
      FillRect(hdc, &r, colortable[W_White].brush);
 
2507
      }
 
2508
 
 
2509
   SetBkMode(hdc, TRANSPARENT);
 
2510
 
 
2511
   for (count = 0; count < win->NumItems; count++)
 
2512
      if ((win->items[count]).string)
 
2513
         {
 
2514
         SetTextColor(hdc, colortable[(win->items[count]).color].rgb);
 
2515
         TextOut( hdc, WIN_EDGE + win->border,
 
2516
                  count * (W_Textheight + MENU_PAD * 2 + MENU_BAR) + MENU_PAD + win->border,
 
2517
                  win->items[count].string, win->items[count].len);
 
2518
         }
 
2519
   }
 
2520
 
 
2521
//Change a specific menu item, and redraw.
 
2522
void ChangeMenuItem(Window *win, int n, char *str, int len, W_Color color)
 
2523
   {
 
2524
   register struct menuItem *p = &(win->items[n]);
 
2525
   HDC hdc;
 
2526
   RECT r;
 
2527
 
 
2528
   if (n >= win->NumItems)
 
2529
      return;
 
2530
 
 
2531
   if (p->string)
 
2532
      free(p->string);
 
2533
 
 
2534
   p->string = (char *) malloc(len + 1);
 
2535
   strcpy(p->string, str);
 
2536
   p->color = color;
 
2537
   p->len = len;
 
2538
 
 
2539
   hdc = GetDC(win->hwnd);
 
2540
   if (NetrekPalette)
 
2541
      {
 
2542
      SelectPalette(hdc, NetrekPalette, FALSE);
 
2543
      RealizePalette(hdc);
 
2544
      }
 
2545
 
 
2546
   r.left = win->ClipRect.left;
 
2547
   r.right = win->ClipRect.right;
 
2548
   r.top = n * (W_Textheight + MENU_PAD * 2 + MENU_BAR) + MENU_PAD + win->border;
 
2549
   r.bottom = r.top + W_Textheight;
 
2550
   FillRect(hdc, &r, colortable[W_Black].brush);
 
2551
 
 
2552
   SetBkMode(hdc, TRANSPARENT);
 
2553
   SelectObject(hdc, (HFONT)W_RegularFont);
 
2554
 
 
2555
   if (p->string)
 
2556
      {
 
2557
      SetTextColor(hdc, colortable[p->color].rgb);
 
2558
      TextOut( hdc, WIN_EDGE + win->border,
 
2559
               n * (W_Textheight + MENU_PAD * 2 + MENU_BAR) + MENU_PAD + win->border,
 
2560
               p->string, p->len);
 
2561
      }
 
2562
 
 
2563
   DrawBorder(win, hdc);
 
2564
   ReleaseDC(win->hwnd, hdc);
 
2565
   }
 
2566
 
 
2567
 
 
2568
void AddToScrolling(Window *win, W_Color color, char *str, int len)
 
2569
   {
 
2570
   struct stringList *p = win->strings;
 
2571
   struct stringList *end, *p2;
 
2572
   int NumStrings = win->NumItems;
 
2573
 
 
2574
   //Find the end of the linked-list of strings...
 
2575
   if (p)  // ...if the list has been created
 
2576
      {
 
2577
      end = p;
 
2578
      while (end->next)
 
2579
         end=end->next;
 
2580
      }
 
2581
   else
 
2582
      {
 
2583
      end = 0;
 
2584
      NumStrings = 0;
 
2585
      }
 
2586
 
 
2587
   if (NumStrings < MAX_SCROLLWINDOW_LINES)  //Create a new stringList item
 
2588
      {
 
2589
      p2 = (struct stringList *) malloc(sizeof(struct stringList));
 
2590
      if (!p2)
 
2591
         {
 
2592
         fprintf(stderr,"Not enough memory to allocate a new listbox string.\n");
 
2593
         return;
 
2594
         }
 
2595
 
 
2596
      if (!p)
 
2597
         win->strings = p2;                        //Store the new start of list
 
2598
 
 
2599
      p = p2;                                      //Point p to the new string
 
2600
 
 
2601
      win->NumItems = ++NumStrings;                //Inc the string number
 
2602
      }
 
2603
   else  //Re-use the first string, place it at the end of the list
 
2604
      {
 
2605
      if (p->string)
 
2606
         free(p->string);
 
2607
      win->strings = p->next;                      //Store the new start of list
 
2608
      }
 
2609
 
 
2610
   if (str[len-1] == '\n')                         //Remove trailing newlines
 
2611
      str[--len] = 0;
 
2612
 
 
2613
   p->string = (char *) malloc(win->TextWidth+ 1);
 
2614
   if (!p->string)
 
2615
      {
 
2616
      printf("Not enough memory to allocate a new listbox string.");
 
2617
      return;
 
2618
      }
 
2619
 
 
2620
   p->color = color;
 
2621
   strncpy(p->string, str, win->TextWidth);
 
2622
 
 
2623
      /* we pad out the string with spaces so we don't have to clear
 
2624
         the window */
 
2625
   if (len < win->TextWidth-1)
 
2626
      memset(p->string + len, ' ', win->TextWidth-len-1);
 
2627
   p->string[win->TextWidth-1] = 0;
 
2628
 
 
2629
   if (end) end->next = p;
 
2630
   p->next = 0;
 
2631
 
 
2632
   //Mark as out of date...
 
2633
   win->AddedStrings++;
 
2634
   }
 
2635
 
 
2636
//Redraw a scrolling window
 
2637
void RedrawScrolling(Window *win, HDC hdc)
 
2638
   {
 
2639
   struct stringList *p = win->strings;
 
2640
   int NumStrings = win->NumItems;
 
2641
   int HiddenLines;
 
2642
   int i;
 
2643
 
 
2644
   if (!win->AddedStrings && !win->NumItems)
 
2645
       return;
 
2646
 
 
2647
   if (win->AddedStrings)              //If strings were added since last paint,
 
2648
    {                                  //Turn off clipping == FULL redraw
 
2649
      i = win->NumItems - win->TextHeight;
 
2650
      i = max(0, i);
 
2651
      if ((i - win->AddedStrings) > GetScrollPos(win->hwnd, SB_VERT))
 
2652
        {
 
2653
          // The player is looking back in the list. Don't move things on him!
 
2654
          HiddenLines = GetScrollPos(win->hwnd,SB_VERT);
 
2655
          win->AddedStrings = 0;
 
2656
          SetScrollRange(win->hwnd, SB_VERT, 0, i, TRUE);
 
2657
        } else {
 
2658
          // We are at then end away, scroll away
 
2659
          SelectClipRgn(hdc, NULL);
 
2660
          win->AddedStrings = 0;
 
2661
          SetScrollRange(win->hwnd, SB_VERT, 0, i, FALSE);
 
2662
             //update the scrollbar range
 
2663
          SetScrollPos(win->hwnd, SB_VERT, i, TRUE);
 
2664
             //update the scrollbar pos and redraw the scroll bar
 
2665
          HiddenLines = i;
 
2666
        }
 
2667
    } else {
 
2668
       HiddenLines = GetScrollPos(win->hwnd,SB_VERT);
 
2669
    }
 
2670
 
 
2671
   //Advance to the first visible line
 
2672
   NumStrings -= HiddenLines;
 
2673
   while (HiddenLines--)
 
2674
      p = p->next;
 
2675
 
 
2676
   //Setup the HDC
 
2677
   SelectObject(hdc, (HFONT)W_RegularFont);
 
2678
   SetBkMode(hdc, OPAQUE);
 
2679
   SetBkColor(hdc, colortable[W_Black].rgb);
 
2680
 
 
2681
   //Draw each line of text
 
2682
   if (NumStrings > win->TextHeight)
 
2683
      NumStrings = win->TextHeight;
 
2684
   for (i = win->TextHeight-NumStrings; i<win->TextHeight && p; i++)
 
2685
      {
 
2686
      SetTextColor(hdc, colortable[p->color].rgb);
 
2687
      TextOut( hdc, WIN_EDGE, MENU_PAD + i * W_Textheight, p->string, strlen(p->string));
 
2688
      p = p->next;
 
2689
      }
 
2690
 
 
2691
   }
 
2692
 
 
2693
void W_FlushScrollingWindow(W_Window window)
 
2694
   {
 
2695
   HDC hdc;
 
2696
   struct stringList *p;
 
2697
   int HiddenLines;
 
2698
   int y;
 
2699
   FNHEADER_VOID;
 
2700
 
 
2701
   if (!win->AddedStrings)
 
2702
      return;
 
2703
 
 
2704
   y = win->NumItems - win->TextHeight;
 
2705
   y = max(0, y);
 
2706
 
 
2707
   // Just update scrollbar if we are looking back
 
2708
   if ((y - win->AddedStrings) > GetScrollPos(win->hwnd, SB_VERT))
 
2709
     {
 
2710
       SetScrollRange(win->hwnd, SB_VERT, 0, y, TRUE);
 
2711
       win->AddedStrings = 0;
 
2712
       return;
 
2713
     }
 
2714
   //Do full redraw if faster
 
2715
   if (win->AddedStrings > (win->TextHeight/2))
 
2716
      {
 
2717
      InvalidateRect(win->hwnd, NULL, FALSE);
 
2718
      UpdateWindow(win->hwnd);                  //Generates paint msg, which calls RedrawScrolling
 
2719
      return;
 
2720
      }
 
2721
 
 
2722
   //Setup the HDC
 
2723
   hdc = GetDC(win->hwnd);
 
2724
   if (NetrekPalette)
 
2725
      {
 
2726
      SelectPalette(hdc, NetrekPalette, FALSE);
 
2727
      RealizePalette(hdc);
 
2728
      }
 
2729
   SelectObject(hdc, (HFONT)W_RegularFont);
 
2730
   SetBkColor(hdc, colortable[W_Black].rgb);
 
2731
   SetBkMode(hdc, OPAQUE);
 
2732
 
 
2733
   //update the scrollbar range and position
 
2734
   SetScrollRange(win->hwnd, SB_VERT, 0, y, FALSE);
 
2735
   SetScrollPos(win->hwnd, SB_VERT, y, TRUE);
 
2736
 
 
2737
      //Scroll up however many lines. Use ScrollDC se we don't invalidate the window
 
2738
      y = win->TextHeight - win->AddedStrings;
 
2739
 
 
2740
      if (y < 0)                        //Pathalogical case (but it does happen):
 
2741
         {                              //First Flush() call has more lines added than will fit
 
2742
         win->AddedStrings += y;        //in one window height
 
2743
         y=0;
 
2744
         }
 
2745
      else
 
2746
         ScrollDC(hdc, 0, -win->AddedStrings * W_Textheight, &win->ClipRect, &win->ClipRect, NULL, NULL);
 
2747
 
 
2748
   //Advance to the first visible line
 
2749
   p = win->strings;
 
2750
   HiddenLines = max(0, win->NumItems - win->AddedStrings);
 
2751
   for (; HiddenLines; HiddenLines--)
 
2752
      p = p->next;
 
2753
 
 
2754
   //Draw each line of text
 
2755
   y = y * W_Textheight + MENU_PAD;
 
2756
   while (win->AddedStrings)
 
2757
      {
 
2758
      SetTextColor(hdc, colortable[p->color].rgb);
 
2759
      TextOut( hdc, WIN_EDGE, y, p->string, win->TextWidth);
 
2760
      p = p->next;
 
2761
      y += W_Textheight;
 
2762
      win->AddedStrings--;
 
2763
      }
 
2764
 
 
2765
   DrawBorder(win, hdc);
 
2766
   ReleaseDC(win->hwnd, hdc);
 
2767
   }
 
2768
 
 
2769
void W_DefineMapcursor(W_Window window)
 
2770
   {
 
2771
   W_DefineCursor(window,
 
2772
                  mapcursor_width,
 
2773
                  mapcursor_height,
 
2774
                  mapmask_bits,
 
2775
                  NULL,
 
2776
                  mapcursor_x_hot,
 
2777
                  mapcursor_y_hot);
 
2778
   }
 
2779
 
 
2780
void W_DefineLocalcursor(W_Window window)
 
2781
   {
 
2782
   W_DefineCursor(window,
 
2783
                  localcursor_width,
 
2784
                  localcursor_height,
 
2785
                  localmask_bits,
 
2786
                  NULL,
 
2787
                  localcursor_x_hot,
 
2788
                  localcursor_y_hot);
 
2789
   }
 
2790
 
 
2791
#define MakeTeamCursor(upper, team) \
 
2792
void W_Define##upper##Cursor(W_Window window) \
 
2793
   { \
 
2794
   W_DefineCursor(window, \
 
2795
                  team##_cruiser_width, \
 
2796
                  team##_cruiser_height, \
 
2797
                  team##_cruiser_bits, \
 
2798
                  NULL,  \
 
2799
                  team##_cruiser_width/2, \
 
2800
                  team##_cruiser_height/2); \
 
2801
   }
 
2802
 
 
2803
MakeTeamCursor(Fed, fed)
 
2804
MakeTeamCursor(Kli, kli)
 
2805
MakeTeamCursor(Rom, rom)
 
2806
MakeTeamCursor(Ori, ori)
 
2807
 
 
2808
 
 
2809
//Sets the cursor to a Star-Trek badge
 
2810
void W_DefineTrekCursor(W_Window window)
 
2811
   {
 
2812
   FNHEADER_VOID;
 
2813
 
 
2814
   if (win->UsingCreatedCursor)
 
2815
      {
 
2816
      DestroyCursor( win->cursor );
 
2817
      win->UsingCreatedCursor = FALSE;
 
2818
      }
 
2819
 
 
2820
   win->cursor = TrekCursor;
 
2821
   }
 
2822
 
 
2823
//Sets the cursor to an exclamation mark
 
2824
void W_DefineWarningCursor(W_Window window)
 
2825
   {
 
2826
   FNHEADER_VOID;
 
2827
 
 
2828
   if (win->UsingCreatedCursor)
 
2829
      {
 
2830
      DestroyCursor( win->cursor );
 
2831
      win->UsingCreatedCursor = FALSE;
 
2832
      }
 
2833
 
 
2834
   win->cursor = WarnCursor;
 
2835
   }
 
2836
 
 
2837
 
 
2838
//Sets the cursor to the ol' boring arrow...
 
2839
void W_DefineArrowCursor(W_Window window)
 
2840
   {
 
2841
   FNHEADER_VOID;
 
2842
 
 
2843
   if (win->UsingCreatedCursor)
 
2844
      {
 
2845
      DestroyCursor( win->cursor );
 
2846
      win->UsingCreatedCursor = FALSE;
 
2847
      }
 
2848
 
 
2849
   win->cursor = LoadCursor(NULL, IDC_ARROW);
 
2850
   }
 
2851
 
 
2852
//Sets the cursor to a an I-beam, indicating text insertion
 
2853
void W_DefineTextCursor(W_Window window)
 
2854
   {
 
2855
   FNHEADER_VOID;
 
2856
 
 
2857
   if (win->UsingCreatedCursor)
 
2858
      {
 
2859
      DestroyCursor( win->cursor );
 
2860
      win->UsingCreatedCursor = FALSE;
 
2861
      }
 
2862
 
 
2863
   win->cursor = LoadCursor(NULL, IDC_IBEAM);
 
2864
   }
 
2865
 
 
2866
 
 
2867
//Sets the cursor for a window, from an arbitrary set of bits
 
2868
void W_DefineCursor(W_Window window,int width,int height,
 
2869
               char *bits,char *mask,int xhot,int yhot)
 
2870
   {
 
2871
   HCURSOR old;
 
2872
   int flags;
 
2873
   int i;
 
2874
   unsigned char *bits2, *mask2;
 
2875
   FNHEADER_VOID;
 
2876
 
 
2877
   //NB: we throw away the passed bitmap and create our own,
 
2878
   //since the X bitmap passed is blank, since it uses the masks
 
2879
   //to display.
 
2880
   bits2 = X11toCursor(bits, width, height);
 
2881
   mask2 = (unsigned char *) malloc(32 * 32/8);
 
2882
 
 
2883
   if (!bits2 || !mask2)
 
2884
      {
 
2885
      fprintf(stderr, "Memory allocation failed while setting a cursor");
 
2886
      return;
 
2887
      }
 
2888
 
 
2889
   //Create the mask as the inverse of the bitmap
 
2890
   for (i=0; i<32*32/8; i++)
 
2891
      mask2[i] = ~bits2[i];
 
2892
 
 
2893
   //Check to see if we are using a created (i.e., must be deleted) cursor already,
 
2894
   //and also set this flag for future reference
 
2895
   if (win->UsingCreatedCursor)
 
2896
      DestroyCursor( win->cursor );
 
2897
   else
 
2898
      win->UsingCreatedCursor = TRUE;
 
2899
 
 
2900
   win->cursor =
 
2901
      CreateCursor(MyInstance, xhot, yhot, 32, 32, (void *)mask2, (void *)bits2);
 
2902
 
 
2903
   free(mask2);
 
2904
   free(bits2);
 
2905
   }
 
2906
 
 
2907
 
 
2908
/***************************************************************************/
 
2909
/* Looks up any default geometry specified in the defaults file and        */
 
2910
/* returns the values found there.  Geometry should be of the form         */
 
2911
/* 502x885+1+1, 502x885, or +1+1.  This allows width or width and height   */
 
2912
/* or width height and x, or width height x and y, or x or x and y. Note   */
 
2913
/* that height or y can not be specified unless width and x are also       */
 
2914
/* specified.                                                              */
 
2915
/*                                                                         */
 
2916
/*   The result returned indicates which values were set.                  */
 
2917
/*                                                                         */
 
2918
/* result & 0x1 ----> width set        G_SET_WIDTH                         */
 
2919
/* result & 0x2 ----> height set       G_SET_HEIGHT                        */
 
2920
/* result & 0x4 ----> x set            G_SET_X                             */
 
2921
/* result & 0x8 ----> y set            G_SET_Y                             */
 
2922
/***************************************************************************/
 
2923
/* Hacked to handle negative geometries 21 Aug 96 -SAC */
 
2924
#define G_SET_WIDTH 0x1
 
2925
#define G_SET_HEIGHT 0x2
 
2926
#define G_SET_X 0x4
 
2927
#define G_SET_Y 0x8
 
2928
int checkGeometry(char *name, int *x, int *y, int *width, int *height)
 
2929
   {
 
2930
   char           *geom_default;
 
2931
   char            buf[100];
 
2932
   char           *s;
 
2933
   int             result = 0;
 
2934
 
 
2935
   sprintf(buf, "%s.geometry", name);
 
2936
   geom_default = getdefault(buf);
 
2937
   if (!geom_default)
 
2938
      return 0;                  /* nothing set */
 
2939
   s = geom_default;
 
2940
   if (*s != '+' && *s != '-')   /* width and height at least */
 
2941
      {
 
2942
      while (*s != 'x' && *s != 0)
 
2943
         s++;
 
2944
      *width = atoi(geom_default);
 
2945
      result |= G_SET_WIDTH;
 
2946
      if (*s == 0)
 
2947
         return result;
 
2948
      s++;
 
2949
         geom_default = s;
 
2950
      while (*s != '+' && *s != '-' && *s != 0)
 
2951
         s++;
 
2952
      *height = atoi(geom_default);
 
2953
         result |= G_SET_HEIGHT;
 
2954
      if (*s == 0)
 
2955
         return result;
 
2956
      }
 
2957
   s++;
 
2958
   geom_default = s;
 
2959
   while (*s != '+' && *s != '-' && *s != 0)
 
2960
      s++;
 
2961
   *x = atoi(geom_default);
 
2962
   if (*(geom_default-1)=='-')
 
2963
       *x = -(*x);
 
2964
   result |= G_SET_X;
 
2965
   if (*s == 0)
 
2966
      return result;
 
2967
   s++;
 
2968
   geom_default = s;
 
2969
   *y = atoi(geom_default);
 
2970
   if (*(geom_default-1)=='-')
 
2971
       *y = -(*y);
 
2972
   result |= G_SET_Y;
 
2973
   return result;
 
2974
   }
 
2975
 
 
2976
void checkParent (char *name, W_Window *parent)
 
2977
   {
 
2978
   char *adefault;
 
2979
   char buf[100];
 
2980
   int i;
 
2981
   HWND found;
 
2982
 
 
2983
   sprintf (buf, "%s.parent", name);
 
2984
   adefault = getdefault (buf);
 
2985
   if (adefault == NULL)
 
2986
      return;
 
2987
 
 
2988
   /* parent must be name of other window or "root" */
 
2989
   if (strcmpi (adefault, "root") == 0)
 
2990
      {
 
2991
      //*parent = (W_Window) &myroot;
 
2992
      *parent = NULL;
 
2993
      return;
 
2994
      }
 
2995
   else if (strcmpi(adefault,"netrek") == 0)
 
2996
      {
 
2997
      //we changed the title of the netrek window,
 
2998
      //so FindWindow won't work. Do it manually
 
2999
      *parent = baseWin;
 
3000
      return;
 
3001
      }
 
3002
 
 
3003
   /* find the window with the name specified */
 
3004
   if (found = FindWindow(ClassName, adefault))
 
3005
      *parent = (W_Window) GetWindowLong(found, 0);   //Return struct ptr
 
3006
 
 
3007
   return;
 
3008
   }
 
3009
 
 
3010
 
 
3011
//Should this window be initially mapped?
 
3012
int checkMapped(char *name)
 
3013
   {
 
3014
   char *adefault;
 
3015
   char buf[100];
 
3016
 
 
3017
   sprintf(buf, "%s.mapped", name);
 
3018
   return(booleanDefault(buf, 0));
 
3019
   }
 
3020
 
 
3021
checkMappedPref(char *name, int preferred)
 
3022
{
 
3023
  char   *adefault;
 
3024
  char    buf[100];
 
3025
 
 
3026
  sprintf(buf, "%s.mapped", name);
 
3027
  return (booleanDefault(buf, preferred));
 
3028
}
 
3029
 
 
3030
//Move the mouse cursor to the new window, or back to old pos if window==NULL
 
3031
void W_WarpPointer(W_Window window)
 
3032
   {
 
3033
   static POINT warped_from;
 
3034
   static int W_in_message = 0;
 
3035
 
 
3036
   if (window == NULL)
 
3037
      {
 
3038
      if (W_in_message)
 
3039
         {
 
3040
         SetCursorPos(warped_from.x, warped_from.y);
 
3041
         W_in_message = 0;
 
3042
         }
 
3043
      }
 
3044
   else
 
3045
      {
 
3046
      RECT r;
 
3047
      GetWindowRect(((Window *)window)->hwnd, &r);
 
3048
      GetCursorPos(&warped_from);
 
3049
      SetCursorPos((r.left + r.right)/2, (r.top + r.bottom)/2);
 
3050
      W_in_message = 1;
 
3051
      }
 
3052
   }
 
3053
 
 
3054
 
 
3055
//An un-documented function that seems to be needed anyway
 
3056
//Checks if the mouse is in the given window - and if so, where?
 
3057
int findMouseInWin(int *x, int *y, W_Window window)
 
3058
   {
 
3059
   RECT rect;
 
3060
   POINT p;
 
3061
   HWND hwnd;
 
3062
   FNHEADER;
 
3063
 
 
3064
   GetCursorPos(&p);
 
3065
   hwnd = ChildWindowFromPoint(((Window *)baseWin)->hwnd, p);
 
3066
   if (!hwnd || (W_Window)GetWindowLong(hwnd, 0) != window)
 
3067
        {
 
3068
        *x=0;
 
3069
        *y=0;
 
3070
        return 0;
 
3071
        }
 
3072
 
 
3073
   ScreenToClient(hwnd, &p);
 
3074
   *x = p.x;
 
3075
   *y = p.y;
 
3076
   return 1;
 
3077
   }
 
3078
 
 
3079
 
 
3080
void DrawBorder(Window *win, HDC hdc)
 
3081
   {
 
3082
   RECT r;
 
3083
   register int size = win->border;
 
3084
 
 
3085
   GetClientRect(win->hwnd, &r);
 
3086
   SelectObject(hdc, colortable[ win->BorderColor ].pen);
 
3087
   SelectObject(hdc, GetStockObject(NULL_BRUSH));
 
3088
 
 
3089
   for ( ; size; size--)                           //Draw a series of shrinking rectangles
 
3090
      {
 
3091
      Rectangle(hdc, r.left, r.top, r.right, r.bottom);
 
3092
      r.left++;
 
3093
      r.top++;
 
3094
      r.bottom--;
 
3095
      r.right--;
 
3096
      }
 
3097
 
 
3098
   }
 
3099
 
 
3100
 
 
3101
//Converts a NxM X11 cursor bitmap, where N<=32 && M<=32 into a 32 x 32 Windows cursor bitmap
 
3102
//To expand the size, it simply places the NxM in the upper left corner
 
3103
//of the 32x32
 
3104
unsigned char *X11toCursor(unsigned char *bits, int width, int height)
 
3105
   {
 
3106
   if (width > 32 || height > 32)
 
3107
      {
 
3108
      fprintf(stderr,"Attempt to define cursor > 32x32. Cursor will be garbled!");
 
3109
      width = min(32, width);
 
3110
      height = min(32, height);
 
3111
      }
 
3112
   return X11toDIBAndMirror(bits, width, height, 32, 32);
 
3113
   }
 
3114
 
 
3115
 
 
3116
//Convert X11-style packed monochrome bitmap information to a Windows monochrome DIB
 
3117
//Picks the smallest size that will fit the original X-bitmap (X-bitmaps are byte-padded
 
3118
//while Windows bitmaps are word-padded). Does not mirror the bitmap  --  we use StretchBlt
 
3119
//with negative width when we copy into the initial memory DC during StoreBitmap (faster method)
 
3120
unsigned char *X11toDIB(unsigned char *bits, int width, int height)
 
3121
   {
 
3122
   int outbytewidth = ((width + 0xF) & ~0xF)/8;        //width of a line in bytes
 
3123
   int inbytewidth =  (width + 0x7) /8;
 
3124
   int i;
 
3125
   register int j;
 
3126
   register unsigned char *data;
 
3127
   unsigned char *base =
 
3128
      (unsigned char *)malloc(outbytewidth * height);    //malloc decode space
 
3129
   if (!base)
 
3130
      return NULL;
 
3131
 
 
3132
   memset(base, 0, outbytewidth * height);         //Clear the array
 
3133
 
 
3134
   for (i=0; i<height; i++)
 
3135
     {
 
3136
     data = base + ((i+1) * outbytewidth);
 
3137
     for (j=0; j<inbytewidth; j++)
 
3138
        *--data = *bits++;
 
3139
     }
 
3140
 
 
3141
   return base;
 
3142
   }
 
3143
 
 
3144
 
 
3145
//Converts X-style monochrome bitmap to GDI usable format
 
3146
//and mirrors the image (As X11 bmps are right-to-left). Used for
 
3147
//defining cursors.
 
3148
unsigned char *X11toDIBAndMirror(unsigned char *bits, int width, int height,
 
3149
                                       int outwidth, int outheight)
 
3150
   {
 
3151
   register unsigned char rot,rot2;                   //Need lotsa register vars
 
3152
   register unsigned char *data;                      //for this to run fast
 
3153
   register int j,i;
 
3154
 
 
3155
   int bytewidth = outwidth /8;                          //width of a line in bytes
 
3156
   unsigned char *base =
 
3157
      (unsigned char *)malloc(bytewidth * outheight);    //malloc decode space
 
3158
   if (!base)
 
3159
      return NULL;
 
3160
 
 
3161
   memset(base, 0, bytewidth * outheight);         //Clear the array
 
3162
 
 
3163
   //Perform the actual conversion. X11 bitmaps are stored in
 
3164
   //reverse bit-order (i.e. 0xC0 when the image is actually 0x03)
 
3165
   for (i=0; i<height; i++)                        //For each line in height...
 
3166
      {
 
3167
      data = base + (i*bytewidth);                 //Get start of line in dest
 
3168
      rot=0x01;                                    //Mask = 00000001b
 
3169
      rot2=0x80;                                   //Mask = 10000000b
 
3170
      for (j=0; j<width; j++)                      //For each pixel in width...
 
3171
         {
 
3172
         if (*bits & rot)                          //If bit is set in source,
 
3173
            *data |= rot2;                         // or dest with the other mask.
 
3174
 
 
3175
         rot<<=1;                                  //Shift masks in opposite directions
 
3176
         rot2>>=1;
 
3177
         if (!rot2)                                //If we have done 8 shifts,
 
3178
            {
 
3179
            rot=0x01;                              // reset masks,
 
3180
            rot2=0x80;
 
3181
            bits++;                                // inc source and dest ptrs.
 
3182
            data++;
 
3183
            }
 
3184
         }
 
3185
      if (rot != 0x1)                              //If we didn't process the whole byte,
 
3186
         bits++;                                   //inc source ptr
 
3187
      }
 
3188
 
 
3189
   return base;
 
3190
   }
 
3191
 
 
3192
 
 
3193
void W_Flush()
 
3194
   {
 
3195
   /* Supposed to flush input caches... whatever */
 
3196
   }
 
3197
 
 
3198
#define MAKE_WINDOW_GETTER(name, part) \
 
3199
 W_Callback name(W_Window w) \
 
3200
  { \
 
3201
  return ( w ? ((Window *)w)->part : NULL );\
 
3202
  }
 
3203
 
 
3204
#define MAKE_WINDOW_SETTER(name, part) \
 
3205
 W_Callback name(W_Window w, W_Callback c) \
 
3206
  { \
 
3207
  if (w)\
 
3208
   ((Window *)w)->part = c;\
 
3209
  return c;\
 
3210
  }
 
3211
 
 
3212
MAKE_WINDOW_GETTER(W_GetWindowKeyDownHandler, HandleKeydown);
 
3213
MAKE_WINDOW_SETTER(W_SetWindowKeyDownHandler, HandleKeydown);
 
3214
 
 
3215
MAKE_WINDOW_GETTER(W_GetWindowKeyUpHandler, HandleKeyup);
 
3216
MAKE_WINDOW_SETTER(W_SetWindowKeyUpHandler, HandleKeyup);
 
3217
 
 
3218
MAKE_WINDOW_GETTER(W_GetWindowButtonHandler, HandleButton);
 
3219
MAKE_WINDOW_SETTER(W_SetWindowButtonHandler, HandleButton);
 
3220
 
 
3221
MAKE_WINDOW_GETTER(W_GetWindowExposeHandler, HandleExpose);
 
3222
MAKE_WINDOW_SETTER(W_SetWindowExposeHandler, HandleExpose);
 
3223
 
 
3224
 
 
3225
void W_ResizeWindow(W_Window window, int neww, int newh)              /* TSH 2/93 */
 
3226
   {
 
3227
   if (!window)
 
3228
      return;
 
3229
   SetWindowPos(((Window *)window)->hwnd, NULL, 0, 0, neww, newh, SWP_NOMOVE);
 
3230
   }
 
3231
 
 
3232
void W_ResizeTextWindow(W_Window window, int neww, int newh)                /* TSH 2/93 */
 
3233
   {
 
3234
   FNHEADER_VOID;
 
3235
 
 
3236
   if (!window)
 
3237
      return;
 
3238
   win->TextHeight = newh;
 
3239
   win->TextWidth = neww;
 
3240
   W_ResizeWindow(window, neww*W_Textwidth + WIN_EDGE*2,
 
3241
                  newh*W_Textheight + WIN_EDGE*2 );
 
3242
   }
 
3243
 
 
3244
void W_ResizeMenu(W_Window window, int neww, int newh)                /* TSH 2/93 */
 
3245
  {
 
3246
  FNHEADER_VOID;
 
3247
 
 
3248
  win->NumItems = newh;
 
3249
  win->TextHeight = newh;
 
3250
  win->TextWidth = neww;
 
3251
 
 
3252
  W_ResizeWindow(window, neww*W_Textwidth+WIN_EDGE*2,
 
3253
                 newh*(W_Textheight+MENU_PAD*2)+(newh-1)*MENU_BAR);
 
3254
  }
 
3255
 
 
3256
//Is this a mono display?
 
3257
int W_Mono()
 
3258
   {
 
3259
   HDC hdc = GetDC(HWND_DESKTOP);
 
3260
   register int result =
 
3261
      ( (GetDeviceCaps(hdc, PLANES) == 1) && (GetDeviceCaps(hdc, COLORRES) == 1) );
 
3262
   ReleaseDC(HWND_DESKTOP, hdc);
 
3263
   return result;
 
3264
   }
 
3265
 
 
3266
 
 
3267
#ifdef  SHORT_PACKETS
 
3268
/* Apparently this solves some problem on X, but here it just forces a redraw...*/
 
3269
/* Hrm - This was using redrawScrolling(win), updated to (win, hdc) -SAC 24 Jul 96 */
 
3270
/* Was void W_SetSensitive(Window *window, int b) -SAC */
 
3271
void W_SetSensitive(Window *window, int b)
 
3272
{
 
3273
   HDC hdc;
 
3274
   
 
3275
   FNHEADER_VOID;
 
3276
 
 
3277
 
 
3278
   b; /* Makes compiler happy -SAC */
 
3279
   if (win->type == WIN_SCROLL)
 
3280
     {
 
3281
       hdc = GetDC(win);
 
3282
       if (hdc)
 
3283
         RedrawScrolling(win,hdc);
 
3284
       ReleaseDC(win,hdc);
 
3285
     }
 
3286
}
 
3287
#endif
 
3288
 
 
3289
#ifdef BEEPLITE
 
3290
 
 
3291
// We use OR mode for drawing bitmaps anyway, so this is the same call
 
3292
void W_OverlayBitmap(int x, int y, W_Icon icon, W_Color color)
 
3293
   {
 
3294
   register struct Icon *bitmap = (struct Icon *)icon;
 
3295
   register int border,width,height;
 
3296
   register int srcx,srcy;
 
3297
   HDC hdc;
 
3298
 
 
3299
   //Fast (I hope) rectangle intersection, don't overwrite our borders
 
3300
   srcx=bitmap->x;
 
3301
   srcy=bitmap->y;
 
3302
   border=bitmap->ClipRectAddr->top;
 
3303
   x+=border; y+=border;
 
3304
   if (x < border)
 
3305
     {
 
3306
     width = bitmap->width - (border-x);
 
3307
     srcx += border-x;
 
3308
     x=border;
 
3309
     }
 
3310
   else if ( (width = bitmap->ClipRectAddr->right-x) > bitmap->width)
 
3311
      width = bitmap->width;
 
3312
   if (y<border)
 
3313
     {
 
3314
     height = bitmap->height - (border-y);
 
3315
     srcy += (border-y);
 
3316
     y=border;
 
3317
     }
 
3318
   else if ( (height = bitmap->ClipRectAddr->bottom-y) > bitmap->height)
 
3319
      height = bitmap->height;
 
3320
 
 
3321
   hdc = GetDC( bitmap->hwnd );
 
3322
   if (NetrekPalette)
 
3323
      {
 
3324
      SelectPalette(hdc, NetrekPalette, FALSE);
 
3325
      RealizePalette(hdc);
 
3326
      }
 
3327
   SelectObject(GlobalMemDC, bitmap->bm );
 
3328
 
 
3329
   //Set the color of the bitmap
 
3330
   //(oddly enough, 1-bit = bk color, 0-bit = text (fg) color)
 
3331
   SetBkColor(hdc, colortable[color].rgb);
 
3332
   SetTextColor(hdc, colortable[BLACK].rgb);
 
3333
 
 
3334
   BitBlt(hdc, x, y,                                //Copy the bitmap
 
3335
            width,
 
3336
            height,
 
3337
            GlobalMemDC,
 
3338
            srcx,
 
3339
            srcy,
 
3340
            SRCPAINT);                                   // <-- using OR mode
 
3341
 
 
3342
   ReleaseDC( bitmap->hwnd, hdc);
 
3343
   }
 
3344
 
 
3345
 
 
3346
void W_EraseTTSText(W_Window window, int max_width, int y, int width)
 
3347
{
 
3348
  register int x = (max_width - width) / 2;
 
3349
 
 
3350
  if (x < 0)
 
3351
    x = 4;
 
3352
  y -= W_Textheight;
 
3353
 
 
3354
  W_ClearArea(window, x, y, width, W_Textheight);
 
3355
}
 
3356
 
 
3357
void W_WriteTTSText(W_Window window, int max_width, int y, int width, char *str, int len)
 
3358
{
 
3359
  register int x = (max_width - width) / 2;
 
3360
  HDC hdc;
 
3361
  FNHEADER_VOID;
 
3362
 
 
3363
  if (x < 0)
 
3364
    x = 4;
 
3365
 
 
3366
  y -= W_Textheight;
 
3367
 
 
3368
  hdc = GetDC(win->hwnd);
 
3369
  if (NetrekPalette)
 
3370
   {
 
3371
   SelectPalette(hdc, NetrekPalette, FALSE);
 
3372
   RealizePalette(hdc);
 
3373
   }
 
3374
  
 
3375
  SetTextColor(hdc, colortable[GREY].rgb);
 
3376
  SetBkMode(hdc, TRANSPARENT);
 
3377
  TextOut(hdc, x, y, str, len);
 
3378
  ReleaseDC(win->hwnd, hdc);
 
3379
}
 
3380
 
 
3381
 
 
3382
int W_TTSTextWidth(char *s, int len)
 
3383
{
 
3384
   return len*W_Textwidth;
 
3385
}
 
3386
 
 
3387
#endif
 
3388
 
 
3389
void W_SetWindowName(W_Window window, char *name)
 
3390
{
 
3391
  FNHEADER_VOID;
 
3392
 
 
3393
  SetWindowText(win->hwnd, name);
 
3394
  return;
 
3395
}
 
3396
 
 
3397
//////////////////////////////////////////////////////////////////////////////////
 
3398
// Reset the system colors. inlines >> macros! -SAC
 
3399
 
 
3400
inline void ResetSysColors(void)
 
3401
{
 
3402
  if (booleanDefault("mungscrollbarcolors",0))
 
3403
    SetSysColors(sizeof(SysColorNames),SysColorNames,SysColors);
 
3404
  return;
 
3405
}
 
3406
 
 
3407
inline void SetTrekSysColors(void)
 
3408
{
 
3409
  if (booleanDefault("mungscrollbarcolors",0))
 
3410
    SetSysColors(sizeof(SysColorNames),SysColorNames,TrekSysColors);
 
3411
  return;
 
3412
}