~ubuntu-branches/debian/lenny/alpine/lenny

« back to all changes in this revision

Viewing changes to pico/osdep/mswin.c

  • Committer: Bazaar Package Importer
  • Author(s): Asheesh Laroia
  • Date: 2007-02-17 13:17:42 UTC
  • Revision ID: james.westby@ubuntu.com-20070217131742-99x5c6cpg1pbkdhw
Tags: upstream-0.82+dfsg
ImportĀ upstreamĀ versionĀ 0.82+dfsg

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 * ========================================================================
 
3
 * Copyright 2006-2007 University of Washington
 
4
 *
 
5
 * Licensed under the Apache License, Version 2.0 (the "License");
 
6
 * you may not use this file except in compliance with the License.
 
7
 * You may obtain a copy of the License at
 
8
 *
 
9
 *     http://www.apache.org/licenses/LICENSE-2.0
 
10
 *
 
11
 * ========================================================================
 
12
 */
 
13
 
 
14
#define WIN31
 
15
#define STRICT
 
16
 
 
17
#define termdef 1                       /* don't define "term" external */
 
18
 
 
19
#include "../headers.h"
 
20
 
 
21
#include <stdarg.h>
 
22
#include <ddeml.h>
 
23
 
 
24
#include "mswin.h"
 
25
#include "resource.h"
 
26
 
 
27
#include "../../pith/osdep/pipe.h"
 
28
#include "../../pith/osdep/canaccess.h"
 
29
 
 
30
#include "../../pith/charconv/filesys.h"
 
31
#include "../../pith/charconv/utf8.h"
 
32
 
 
33
#include "mswin_tw.h"
 
34
 
 
35
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
36
 *
 
37
 *                      Defines
 
38
 *
 
39
 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
 
40
 
 
41
 
 
42
#define ICON
 
43
 
 
44
 
 
45
/* For debugging, export locals so debugger can see them. */
 
46
#ifdef DEBUG
 
47
#define LOCAL
 
48
#else
 
49
#define LOCAL           static
 
50
#endif
 
51
 
 
52
 
 
53
/*
 
54
 * Define which debugging is desired.  Generally only FDEBUG.
 
55
 */
 
56
#define FDEBUG          /* Standard file debugging. */
 
57
 
 
58
#undef SDEBUG           /* Verbose debugging of startup and windows handling*/
 
59
#undef CDEBUG           /* Verbose debugging of character input timeing. */
 
60
 
 
61
#undef OWN_DEBUG_FILE   /* Define if we want to write to our own debug file,
 
62
                         * not pine's. */
 
63
 
 
64
 
 
65
/* Max size permitted for the screen. */
 
66
#define MAXNROW                 200
 
67
#define MAXNCOLUMN              NLINE
 
68
 
 
69
#define MINNROW                 10      /* Minimum screen size */
 
70
#define MINNCOLUMN              32
 
71
 
 
72
#define MARGINE_LEFT            3
 
73
#define MARGINE_TOP             1
 
74
 
 
75
#define FRAME_3D_SIZE           1
 
76
 
 
77
#define WIN_MIN_X_SIZE          190     /* Minimum window size. */
 
78
#define WIN_MIN_Y_SIZE          180
 
79
 
 
80
#define WIN_X_BORDER_SIZE       8       /* Space taked by window frame. */
 
81
#define WIN_Y_BORDER_SIZE       65
 
82
 
 
83
#define FONT_MIN_SIZE           5
 
84
#define FONT_MAX_SIZE           21
 
85
 
 
86
#define PRINT_TAB_SIZE          8       /* Tab size used by print code. */
 
87
 
 
88
 
 
89
#define TB_HEIGHT               32      /* Tool Bar Height. */
 
90
#define TB_BUTTONHEIGHT         16      /* Button Height. */
 
91
#define TB_BUTTONSPACING        8       /* Space between buttons. */
 
92
 
 
93
 
 
94
/* Some string lengths. */
 
95
#define MAXLEN_TEMPSTR          256     /* Max size for temp storage. */
 
96
 
 
97
#define WIN_POS_STR_MAX_LEN     20      /* Max length for window-position
 
98
                                         * string. */
 
99
 
 
100
#define MENU_ITEM_NAME_LEN      32      /* Menu item name lengths. */
 
101
 
 
102
 
 
103
/* Length of keyboard input queue. */
 
104
#define CHARACTER_QUEUE_LENGTH  32
 
105
#define MOUSE_QUEUE_LENGTH      32
 
106
 
 
107
/* Number of resize callback functions we can keep track of. */
 
108
#define RESIZE_CALLBACK_ARRAY_SIZE      3
 
109
 
 
110
/* Number of bytes held in the write accumulator. */
 
111
#define WRITE_ACCUM_SIZE                200
 
112
 
 
113
/* Max time that may pass between calls to GetMessage.  See mswin_charavail()
 
114
 */
 
115
#define GM_MAX_TIME     3000            /* In milliseconds.*/
 
116
 
 
117
/* My Timer Message */
 
118
#define MY_TIMER_ID     33
 
119
/* timeout period in miliseconds. */
 
120
#define MY_TIMER_PERIOD (UINT)((IDLE_TIMEOUT + 1)*1000)
 
121
/***** We use variable my_timer_period now instead so that we can set
 
122
       it differently when in pine and when in regular old pico.
 
123
       We're not entirely sure we need it in pico, but we will leave
 
124
       it there because we don't understand.
 
125
 *****/
 
126
#define MY_TIMER_SHORT_PERIOD (UINT)5000  /* used when there is a task in
 
127
                                             the OnTask list. */
 
128
#define MY_TIMER_VERY_SHORT_PERIOD (UINT)500  /* used when SIGALRM and alarm()
 
129
                                                 is set. */
 
130
#define MY_TIMER_EXCEEDINGLY_SHORT_PERIOD (UINT)80 /* used when
 
131
                                                 gAllowMouseTracking is set */
 
132
 
 
133
#define TIMER_FAIL_MESSAGE TEXT("Failed to get all necessary Windows resources (timers).  Alpine will run, but may not be able to keep the connection to the server alive.  Quitting other applications and restarting Alpine may solve the problem.")
 
134
 
 
135
/*
 
136
 * Task bar notification Icon id and call back message for it.
 
137
 */
 
138
#define TASKBAR_ICON_NEWMAIL            1
 
139
#define TASKBAR_ICON_MESSAGE            WM_USER+1000
 
140
 
 
141
 
 
142
/*
 
143
 * Below here are fixed constancs that really should not be changed.
 
144
 */
 
145
 
 
146
/* Auto Wrap States. */
 
147
#define WRAP_OFF        0               /* Never wrap to next line. */
 
148
#define WRAP_ON         1               /* Wrap to next line. */
 
149
#define WRAP_NO_SCROLL  2               /* Wrap to next line but DON'T scroll
 
150
                                           screen to do it. */
 
151
/* Speicial keys in the Character Queue. */
 
152
#define CQ_FLAG_DOWN            0x01
 
153
#define CQ_FLAG_EXTENDED        0x02
 
154
#define CQ_FLAG_ALT             0x04
 
155
 
 
156
/* Special ASCII characters. */
 
157
#define ASCII_BEL       0x07
 
158
#define ASCII_BS        0x08
 
159
#define ASCII_TAB       0x09
 
160
#define ASCII_LF        0x0A
 
161
#define ASCII_CR        0x0D
 
162
#define ASCII_XON       0x11
 
163
#define ASCII_XOFF      0x13
 
164
 
 
165
/* Character Attributes. */
 
166
#define CHAR_ATTR_NORM  0x00            /* Normal. */
 
167
#define CHAR_ATTR_REV   0x01            /* Reverse Video. */
 
168
#define CHAR_ATTR_BOLD  0x02            /* Reverse Video. */
 
169
#define CHAR_ATTR_ULINE 0x04            /* Reverse Video. */
 
170
#define CHAR_ATTR_SEL   0x08            /* Selected text. */
 
171
#define CHAR_ATTR_NOT   0x80            /* No attributes. */
 
172
 
 
173
/*
 
174
 * Different applications that we know about.
 
175
 */
 
176
#define APP_UNKNOWN             0
 
177
#define APP_PICO                1
 
178
#define APP_PICO_IDENT          TEXT("pico")
 
179
#define APP_PINE                2
 
180
#define APP_PINE_IDENT          TEXT("pine")
 
181
 
 
182
/*
 
183
 * Control values for call to AccelCtl.
 
184
 */
 
185
/*#undef ACCELERATORS*/
 
186
#define ACCELERATORS
 
187
#define ACCEL_UNLOAD            0       /* Unload the accelerators. */
 
188
#define ACCEL_LOAD              1       /* Load the accelerators. */
 
189
#define ACCEL_TOGGLE            2       /* Toggle the accelerators. */
 
190
 
 
191
/*
 
192
 * flag bits to control which edit menu options can get lit
 
193
 */
 
194
#define EM_NONE                 0L
 
195
#define EM_CP                   0x0001
 
196
#define EM_CP_APPEND            0x0002
 
197
#define EM_FIND                 0x0004
 
198
#define EM_PST                  0x0008
 
199
#define EM_PST_ABORT            0x0010
 
200
#define EM_CUT                  0x0020
 
201
#define EM_SEL_ALL              0x0040
 
202
 
 
203
#define EM_MAX_ACCEL            6
 
204
 
 
205
/* Offsets to objects in window extra storage. */
 
206
#define GWL_PTTYINFO            0       /* Offset in Window extra storage. */
 
207
 
 
208
/*
 
209
 *
 
210
 */
 
211
#define FONT_CHARSET_FONT       DEFAULT_CHARSET
 
212
 
 
213
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
214
 *
 
215
 *                      Typedefs
 
216
 *
 
217
 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
 
218
 
 
219
/* Type that the screen array is made up of. */
 
220
#define CHAR    unsigned char
 
221
 
 
222
/* define possible caret shapes */
 
223
typedef enum {
 
224
    CaretBlock = 0,
 
225
    CaretSmallBlock,
 
226
    CaretHorizBar,
 
227
    CaretVertBar
 
228
} CARETS;
 
229
 
 
230
/* Type that the attribute array is made up of. */
 
231
typedef struct _character_attribute {
 
232
    unsigned  style:8;
 
233
    DWORD     rgbFG, rgbBG;
 
234
} CharAttrib;
 
235
 
 
236
typedef int                     (*ResizeCallBackProc)();
 
237
typedef int                     (*FileDropCallBackProc)();
 
238
typedef short                   CORD;
 
239
 
 
240
/* NOTE:  There is currently code that assumes that CHAR and CharAttrib
 
241
 *      are one byte in size.  All this code is flaged with a preceeding
 
242
 *      assert () */
 
243
 
 
244
/* Struct that defines command menu entries. */
 
245
typedef struct tagMenuItem {
 
246
    BOOL        miActive;
 
247
    UCS         miKey;
 
248
    short       miIndex;
 
249
    char       *miLabel;
 
250
} MenuItem;
 
251
 
 
252
 
 
253
/* List of child window IDs and previous window procedures. */
 
254
typedef struct tagBtnList {
 
255
    WORD        wndID;
 
256
    WNDPROC     wndProc;
 
257
} BtnList;
 
258
 
 
259
 
 
260
/* General info. */
 
261
typedef struct tagTTYINFO {
 
262
    TCHAR       *pScreen;       /* Screen. */
 
263
    int         *pCellWidth;    /* how wide to paint the char */
 
264
    CharAttrib  *pAttrib;       /* Attributes. */
 
265
    TCHAR       writeAccum[WRITE_ACCUM_SIZE];
 
266
    int         writeAccumCount;
 
267
    CARETS      cCaretStyle;    /* Current caret's style */
 
268
    int         scrollRange;    /* Current scroll bar range. */
 
269
    long        scrollPos;      /* Current scroll position. */
 
270
    long        scrollTo;       /* Possition of last scroll to. */
 
271
    HFONT       hTTYFont;
 
272
    LOGFONT     lfTTYFont;
 
273
    DWORD       rgbFGColor;     /* Normal forground color. */
 
274
    DWORD       rgbBGColor;     /* Normal background color. */
 
275
    DWORD       rgbRFGColor;    /* Reverse forground color. */
 
276
    DWORD       rgbRBGColor;    /* Reverse background color */
 
277
    unsigned    screenDirty:1;  /* TRUE if screen needs update. */
 
278
    unsigned    eraseScreen:1;  /* TRUE if need to erase whole screen */
 
279
    unsigned    fMinimized:1;   /* True when window is minimized. */
 
280
    unsigned    fFocused:1;     /* True when we have focus. */
 
281
    unsigned    fNewLine:1;     /* Auto LF on CR. */
 
282
    unsigned    fMassiveUpdate:1;/* True when in Massive screen update. */
 
283
    unsigned    fNewMailIcon:1; /* True when new mail has arrived. */
 
284
    unsigned    fMClosedIcon:1; /* True when no mailbox is open. */
 
285
    unsigned    fCursorOn:1;            /* True when cursor's shown */
 
286
    unsigned    fCaretOn:1;             /* True if caret's displayed */
 
287
    unsigned    fTrayIcon:1;            /* True if tool tray icon's on */
 
288
    ResizeCallBackProc  resizer[RESIZE_CALLBACK_ARRAY_SIZE];
 
289
    FileDropCallBackProc dndhandler;
 
290
    int         autoWrap;       /* Auto wrap to next line. */
 
291
    CharAttrib  curAttrib;      /* Current character attributes. */
 
292
    int         actNRow, actNColumn;    /* Actual number of rows and comumns
 
293
                                         * displayed. */
 
294
    CORD        xSize, ySize;           /* Size of screen in pixels */
 
295
    CORD        xScroll, yScroll;       /* ?? */
 
296
    CORD        xOffset, yOffset;       /* Offset from the left and top of
 
297
                                         * window contents. */
 
298
    CORD        nColumn, nRow;          /* Current position of cursor in
 
299
                                         * cells. */
 
300
    CORD        xChar, yChar;           /* Width of a char in pixels. */
 
301
    int         yCurOffset;             /* offset of cursor Y-size */
 
302
    CORD        fDesiredSize;           /* TRUE when there is a specific size
 
303
                                         * the window should be expanded to
 
304
                                         * after being minimized. */
 
305
    CORD        xDesPos, yDesPos;       /* Desired position. */
 
306
    CORD        xDesSize, yDesSize;     /* Desired window position. */
 
307
    int         curWinMenu;             /* Current window menu. */
 
308
    HACCEL      hAccel;                 /* Handle to accelorator keys. */
 
309
    UINT        fAccel;                 /* vector of bound accelerator keys. */
 
310
    CORD        toolBarSize;            /* Size of toolbar. */
 
311
    BOOL        toolBarTop;             /* Toolbar on top? */
 
312
    int         curToolBarID;
 
313
    BtnList     *toolBarBtns;
 
314
    HWND        hTBWnd;
 
315
    HBRUSH      hTBBrush;
 
316
    BOOL        menuItemsCurrent;
 
317
    BOOL        noScrollUpdate;
 
318
    BOOL        scrollRangeChanged;
 
319
    long        noSUpdatePage;
 
320
    long        noSUpdateRange;
 
321
    short       menuItemsIndex;
 
322
    MenuItem    menuItems[KS_COUNT];
 
323
} TTYINFO, *PTTYINFO ;
 
324
 
 
325
 
 
326
#define MAXCLEN (MAX(MAXCOLORLEN,RGBLEN+1))
 
327
typedef struct MSWINColor {
 
328
    char                *colorName;
 
329
    char                *canonicalName;
 
330
    COLORREF            colorRef;
 
331
} MSWINColor;
 
332
 
 
333
 
 
334
typedef struct {
 
335
    char        *name;
 
336
    CARETS       style;
 
337
} MSWinCaret_t;
 
338
 
 
339
 
 
340
/*
 
341
 * Entry in the OnTask list.  This is a list of actions to perform
 
342
 * when a task exits.  Currently, the only thing we do is delete
 
343
 * files.  if that changes this structure will get more complex.
 
344
 *
 
345
 * hTask == NULL means "This program" and can be used to arrange for
 
346
 * deletion of files when this program exits.
 
347
 */
 
348
typedef struct ontask {
 
349
    struct ontask       *next;
 
350
    HTASK               hTask;
 
351
    char                path[PATH_MAX+1];
 
352
} OnTaskItem;
 
353
 
 
354
typedef void (__cdecl *SignalType)(int);
 
355
 
 
356
typedef struct _iconlist {
 
357
    HICON  hIcon;
 
358
/*    char    path[PATH_MAX]; */
 
359
/*    WORD    index;          */
 
360
    int     id;
 
361
    short   row;
 
362
    struct _iconlist *next;
 
363
} IconList;
 
364
 
 
365
 
 
366
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
367
 *
 
368
 *                      Forward function declarations.
 
369
 *
 
370
 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
 
371
 
 
372
LOCAL void *
 
373
MyGetWindowLongPtr(HWND hwnd, int nIndex)
 
374
{
 
375
    return (void *)(LONG_PTR)GetWindowLongPtr(hwnd, nIndex);
 
376
}
 
377
 
 
378
LOCAL LONG_PTR
 
379
MySetWindowLongPtr(HWND hwnd, int nIndex, void *NewLongPtr)
 
380
{
 
381
// warning C4244: 'function': conversion from 'LONG_PTR' to 'LONG',
 
382
//  possible loss of data
 
383
#pragma warning(push)
 
384
#pragma warning(disable: 4244)
 
385
    return SetWindowLongPtr(hwnd, nIndex, (LONG_PTR)NewLongPtr);
 
386
#pragma warning(pop)
 
387
}
 
388
 
 
389
#ifdef  WIN32
 
390
#define GET_HINST( hWnd )  ((HINSTANCE) MyGetWindowLongPtr( hWnd, GWLP_HINSTANCE ))
 
391
#define GET_ID( hWnd )  (LOWORD(MyGetWindowLongPtr( hWnd, GWLP_ID )))
 
392
#else
 
393
#define GET_HINST( hWnd )  ((HINSTANCE) GetWindowWord( hWnd, GWW_HINSTANCE ))
 
394
#define GET_ID( hWnd )  ((WORD) GetWindowWord( hWnd, GWW_ID ))
 
395
#endif
 
396
 
 
397
#define CONSTRAIN(v,min,max)    ((v) = (v) < (min) ? (min) : (v) > (max) ? (max) : (v))
 
398
 
 
399
 
 
400
/* function prototypes (private) */
 
401
int app_main (int argc, char *argv[]);
 
402
 
 
403
void            WinExit (void);
 
404
 
 
405
LOCAL BOOL      InitApplication (HANDLE);
 
406
LOCAL HWND      InitInstance (HANDLE, int);
 
407
LOCAL void      MakeArgv (HINSTANCE hInstance, LPSTR cmdLine, int *pargc,
 
408
                                CHAR ***pargv);
 
409
LOCAL LRESULT NEAR      CreateTTYInfo (HWND hWnd);
 
410
LOCAL BOOL NEAR DestroyTTYInfo (HWND hWnd);
 
411
LOCAL int       ResizeTTYScreen (HWND hWnd, PTTYINFO pTTYInfo,
 
412
                                        int newNRow, int newNColumn);
 
413
LOCAL BOOL      ResetTTYFont (HWND, PTTYINFO, LOGFONT *);
 
414
LOCAL BOOL      EraseTTY (HWND, HDC);
 
415
LOCAL BOOL      PaintTTY (HWND);
 
416
LOCAL BOOL      GetMinMaxInfoTTY (HWND hWnd, MINMAXINFO __far *lpmmi);
 
417
LOCAL BOOL      AboutToSizeTTY (HWND hWnd, WINDOWPOS *winPos);
 
418
LOCAL BOOL      SizeTTY (HWND, int, CORD, CORD);
 
419
LOCAL BOOL      SizingTTY (HWND hWnd, int fwSide, LPRECT pRect);
 
420
LOCAL void      FrameRect3D(HDC hdc, RECT * pRC, int width, BOOL raised);
 
421
LOCAL void      FillRectColor(HDC hDC, RECT * pRC, COLORREF color);
 
422
 
 
423
 
 
424
LOCAL BOOL      MoveTTY (HWND hWnd, int xPos, int yPos);
 
425
LOCAL void      ScrollTTY (HWND hWnd, int wScrollCode, int nPos, HWND hScroll);
 
426
LOCAL void      CaretTTY (HWND hWnd, CARETS cStyle);
 
427
LOCAL void      CaretCreateTTY (HWND hWnd);
 
428
#ifdef  WIN32
 
429
LOCAL void      MouseWheelTTY (HWND hWnd, int xPos, int yPos,
 
430
                               int fwKeys, int zDelta);
 
431
LOCAL void      MouseWheelMultiplier ();
 
432
#endif
 
433
BOOL CALLBACK   NoMsgsAreSent (void);
 
434
LOCAL BOOL      SetTTYFocus (HWND);
 
435
LOCAL BOOL      KillTTYFocus (HWND);
 
436
LOCAL BOOL      MoveTTYCursor (HWND);
 
437
LOCAL BOOL      ProcessTTYKeyDown (HWND hWnd, TCHAR bOut, DWORD keyData);
 
438
LOCAL BOOL      ProcessTTYKeyUp (HWND hWnd, TCHAR key, DWORD keyData);
 
439
LOCAL BOOL      ProcessTTYCharacter (HWND hWnd, TCHAR bOut, DWORD keyData);
 
440
LOCAL BOOL      ProcessTTYMouse (HWND hWnd, int mevent, int button, CORD xPos,
 
441
                                        CORD yPos, WPARAM keys);
 
442
LOCAL BOOL      ProcessTTYFileDrop (HANDLE wParam);
 
443
LOCAL void      ProcessTimer (void);
 
444
LOCAL BOOL      WriteTTYBlock (HWND, LPTSTR, int);
 
445
LOCAL BOOL      WriteTTYText (HWND, LPTSTR, int);
 
446
LOCAL BOOL      WriteTTYChar (HWND, TCHAR);
 
447
 
 
448
LOCAL VOID      GoModalDialogBoxParam (HINSTANCE, LPTSTR, HWND,
 
449
                                        DLGPROC, LPARAM);
 
450
LOCAL BOOL      SelectTTYFont (HWND);
 
451
LOCAL void      SetColorAttribute (COLORREF *cf, char *colorName);
 
452
LOCAL void      SetReverseColor (void);
 
453
LOCAL BOOL      ConvertRGBString (char *colorName, COLORREF *cf);
 
454
LOCAL char     *ConvertStringRGB (char *colorName, size_t ncolorName, COLORREF colorRef);
 
455
LOCAL BOOL      ScanInt (char *str, int min, int max, int *val);
 
456
 
 
457
LOCAL void      TBToggle (HWND);
 
458
LOCAL void      TBPosToggle (HWND);
 
459
LOCAL void      TBShow (HWND);
 
460
LOCAL void      TBHide (HWND);
 
461
LOCAL void      TBSwap (HWND, int);
 
462
LOCAL unsigned  scrwidth(LPTSTR lpText, int nLength);
 
463
LOCAL long      pscreen_offset_from_cord(int row, int col, PTTYINFO pTTYInfo);
 
464
 
 
465
LOCAL int       struncmp(char *o, char *r, int n);
 
466
LOCAL int       tcsucmp(LPTSTR o, LPTSTR r);
 
467
LOCAL int       strucmp(char *o, char *r);
 
468
LOCAL int       _print_send_page(void);
 
469
 
 
470
/* defined in region.c */
 
471
int            copyregion(int f, int n);
 
472
 
 
473
 
 
474
#ifdef ACCELERATORS
 
475
#ifdef ACCELERATORS_OPT
 
476
LOCAL void      AccelCtl (HWND hWnd, int ctl, BOOL saveChange);
 
477
#endif
 
478
LOCAL void      AccelManage (HWND hWnd, long accels);
 
479
LOCAL void      UpdateAccelerators (HWND hWnd);
 
480
#endif
 
481
 
 
482
LOCAL UINT      UpdateEditAllowed(HWND hWnd);
 
483
LOCAL void      PopupConfig(HMENU hMenu, MPopup *members, int *n);
 
484
LOCAL MPopup   *PopupId(MPopup *members, int id);
 
485
LOCAL BOOL      CopyCutPopup (HWND hWnd, UINT fAllowed);
 
486
 
 
487
LOCAL void      SelStart (int nRow, int nColumn);
 
488
LOCAL void      SelFinish (int nRow, int nColumn);
 
489
LOCAL void      SelClear (void);
 
490
LOCAL void      SelTrackXYMouse (int xPos, int yPos);
 
491
LOCAL void      SelTrackMouse (int nRow, int nColumn);
 
492
LOCAL BOOL      SelAvailable (void);
 
493
LOCAL void      SelDoCopy (HANDLE hCB, DWORD lenCB);
 
494
 
 
495
LOCAL void      UpdateTrayIcon(DWORD dwMsg, HICON hIcon, LPTSTR tip);
 
496
 
 
497
LOCAL void      FlushWriteAccum (void);
 
498
 
 
499
LOCAL int       mswin_reg_lptstr(int, int, LPTSTR, size_t);
 
500
 
 
501
LOCAL BOOL      MSWRPoke(HKEY hKey, LPTSTR subkey, LPTSTR valstr, LPTSTR data);
 
502
LOCAL int       MSWRClear(HKEY hKey, LPTSTR pSubKey);
 
503
LOCAL void      MSWRAlpineSet(HKEY hRootKey, LPTSTR subkey, LPTSTR val,
 
504
                               int update, LPTSTR data);
 
505
LOCAL int       MSWRProtocolSet(HKEY hKey, int type, LPTSTR path_lptstr);
 
506
LOCAL void      MSWRAlpineSetHandlers(int update, LPTSTR path);
 
507
LOCAL int       MSWRAlpineGet(HKEY hKey, LPTSTR subkey, LPTSTR val,
 
508
                               LPTSTR data_lptstr, size_t len);
 
509
 
 
510
LOCAL void      MSWIconAddList(int row, int id, HICON hIcon);
 
511
LOCAL int       MSWIconPaint(int row, HDC hDC);
 
512
LOCAL void      MSWIconFree(IconList **ppIcon);
 
513
 
 
514
 
 
515
                /* ... interface routines ... */
 
516
 
 
517
 
 
518
void            ProcessMenuItem (HWND hWnd, WPARAM wParam);
 
519
 
 
520
void            AlarmDeliver (void);
 
521
void            HUPDeliver (void);
 
522
 
 
523
void            PrintFontSameAs (HWND hWnd);
 
524
void            PrintFontSelect (HWND hWnd);
 
525
void            ExtractFontInfo(LOGFONT *pFont,
 
526
                                LPTSTR fontName, size_t nfontName,
 
527
                                int *fontSize,
 
528
                                LPTSTR fontStyle, size_t nfontStyle,
 
529
                                int ppi,
 
530
                                LPTSTR fontCharSet, size_t nfontCharSet);
 
531
 
 
532
LOCAL void      DidResize (PTTYINFO pTTYInfo);
 
533
 
 
534
LOCAL void      UpdateMenu (HWND hWnd);
 
535
LOCAL void      EditCut (void);
 
536
LOCAL void      EditCopy (void);
 
537
LOCAL void      EditCopyAppend (void);
 
538
LOCAL void      EditDoCopyData (HANDLE hCB, DWORD lenCB);
 
539
LOCAL void      EditPaste (void);
 
540
LOCAL void      EditCancelPaste (void);
 
541
LOCAL UCS       EditPasteGet (void);
 
542
LOCAL BOOL      EditPasteAvailable (void);
 
543
LOCAL void      EditSelectAll (void);
 
544
 
 
545
LOCAL void      MSWHelpShow (cbstr_t);
 
546
LOCAL int       MSWHelpSetMenu (HMENU hmenu);
 
547
 
 
548
 
 
549
LOCAL void      SortHandler (int order, int reverse);
 
550
LOCAL void      FlagHandler (int order, int reverse);
 
551
 
 
552
LOCAL void      MyTimerSet (void);
 
553
 
 
554
LOCAL LRESULT   ConfirmExit (void);
 
555
 
 
556
LOCAL void      CQInit (void);
 
557
LOCAL BOOL      CQAvailable (void);
 
558
LOCAL BOOL      CQAdd (UCS c, DWORD keyData);
 
559
LOCAL BOOL      CQAddUniq (UCS c, DWORD keyData);
 
560
LOCAL UCS       CQGet ();
 
561
 
 
562
LOCAL void      MQInit (void);
 
563
LOCAL BOOL      MQAvailable (void);
 
564
LOCAL BOOL      MQAdd (int mevent, int button, int nRow, int nColumn,
 
565
                                int keys, int flags);
 
566
LOCAL BOOL      MQGet (MEvent * pmouse);
 
567
LOCAL BOOL      MQClear (int flag);
 
568
 
 
569
LOCAL int       MapVKtoMS (WORD c, WORD flags);
 
570
 
 
571
LOCAL DWORD     ExplainSystemErr(void);
 
572
 
 
573
LOCAL void      RestoreMouseCursor();
 
574
 
 
575
LOCAL BYTE      mswin_string2charsetid(LPTSTR);
 
576
LOCAL int   mswin_charsetid2string (LPTSTR fontCharSet,
 
577
                                        size_t nfontCharSet, BYTE lfCharSet);
 
578
 
 
579
LOCAL int       mswin_tw_init(MSWIN_TEXTWINDOW *mswin_tw, int id,
 
580
                              LPCTSTR title);
 
581
LOCAL MSWIN_TEXTWINDOW *mswin_tw_displaytext_lptstr (LPTSTR, LPTSTR, size_t,
 
582
                                                     LPTSTR *, MSWIN_TEXTWINDOW *mswin_tw,
 
583
                                                     int);
 
584
LOCAL void      mswin_tw_print_callback(MSWIN_TEXTWINDOW *mswin_tw);
 
585
 
 
586
 
 
587
/* Functions exported to MS Windows. */
 
588
 
 
589
LRESULT FAR PASCAL __export PWndProc (HWND, UINT, WPARAM, LPARAM);
 
590
BOOL FAR PASCAL __export ToolBarProc (HWND, UINT, WPARAM, LPARAM);
 
591
LRESULT FAR PASCAL __export TBBtnProc (HWND, UINT, WPARAM, LPARAM);
 
592
BOOL FAR PASCAL __export AboutDlgProc (HWND, UINT, WPARAM, LPARAM);
 
593
BOOL FAR PASCAL __export SplashDlgProc (HWND, UINT, WPARAM, LPARAM);
 
594
 
 
595
LOCAL HDDEDATA CALLBACK DdeCallback(UINT uType, UINT uFmt, HCONV hconv,
 
596
                                    HSZ hsz1, HSZ hsz2, HDDEDATA hdata,
 
597
                                    DWORD dwData1, DWORD dwData2);
 
598
 
 
599
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
600
 *
 
601
 *                      Module globals.
 
602
 *
 
603
 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
 
604
 
 
605
 
 
606
PTTYINFO                gpTTYInfo;
 
607
HWND                    ghTTYWnd;
 
608
HINSTANCE               ghInstance;
 
609
BOOL                    gfUseDialogs;
 
610
FILE                    *mswin_debugfile = NULL;
 
611
int                     mswin_debug = 0;
 
612
TCHAR                   gszAppName[45];
 
613
 
 
614
LOCAL TCHAR             TempBuf [MAXLEN_TEMPSTR];
 
615
 
 
616
LOCAL TCHAR             gszTTYClass[] = TEXT("PineWnd");
 
617
LOCAL int               gAppIdent = APP_UNKNOWN;
 
618
 
 
619
LOCAL int               gNMW_width;
 
620
 
 
621
LOCAL HCURSOR           ghCursorArrow = NULL;
 
622
LOCAL HCURSOR           ghCursorBusy = NULL;
 
623
LOCAL HCURSOR           ghCursorIBeam = NULL;
 
624
LOCAL HCURSOR           ghCursorHand = NULL;
 
625
LOCAL HCURSOR           ghCursorCurrent = NULL;
 
626
 
 
627
LOCAL HWND              ghSplashWnd = NULL;
 
628
 
 
629
LOCAL COLOR_PAIR *the_rev_color, *the_normal_color;
 
630
 
 
631
/* Used for Pasting text. */
 
632
LOCAL HANDLE            ghPaste = NULL;         /* Handle to Paste data. */
 
633
LOCAL TCHAR             *gpPasteNext = NULL;    /* Pointer to current char. */
 
634
LOCAL size_t            gPasteBytesRemain = 0;  /* Count of bytes left. */
 
635
LOCAL BOOL              gPasteWasCR = FALSE;    /* Previous char was CR. */
 
636
LOCAL int               gPasteEnabled = MSWIN_PASTE_DISABLE;
 
637
LOCAL getc_t            gCopyCutFunction = NULL;
 
638
LOCAL cbarg_t           gScrollCallback = NULL;
 
639
LOCAL BOOL              gScrolling = FALSE;     /* Keeps track of when we are
 
640
                                                 * in scroll routine. */
 
641
LOCAL cbarg_t           gSortCallback = NULL;
 
642
LOCAL cbarg_t           gFlagCallback = NULL;
 
643
LOCAL cbarg_t           gHdrCallback = NULL;
 
644
LOCAL cbarg_t           gZoomCallback = NULL;
 
645
LOCAL cbarg_t           gFkeyCallback = NULL;
 
646
LOCAL cbarg_t           gSelectedCallback = NULL;
 
647
LOCAL BOOL              gMouseTracking = FALSE; /* Keeps track of when we are
 
648
                                                 * tracking the mouse. */
 
649
LOCAL FARPROC           gWSBlockingProc = NULL;
 
650
LOCAL DLGPROC           gToolBarProc = NULL;
 
651
LOCAL WNDPROC           gTBBtnProc = NULL;
 
652
 
 
653
LOCAL BOOL              gAllowCopy = FALSE;
 
654
LOCAL BOOL              gAllowCut = FALSE;
 
655
 
 
656
LOCAL BOOL              gAllowMouseTrack = FALSE;/* Upper layer interested in
 
657
                                                 * mouse tracking. */
 
658
LOCAL short             gsMWMultiplier;
 
659
LOCAL MEvent            gMTEvent;
 
660
 
 
661
LOCAL BOOL              gKeyControlDown = FALSE;/* Keep track of the control
 
662
                                                 * key position. */
 
663
 
 
664
LOCAL cbstr_t           gHelpGenCallback = NULL;
 
665
LOCAL BOOL              gfHelpGenMenu = FALSE;  /* TRUE when help menu
 
666
                                                 * installed. */
 
667
LOCAL cbstr_t           gHelpCallback = NULL;
 
668
LOCAL BOOL              gfHelpMenu = FALSE;     /* TRUE when help menu
 
669
                                                 * installed. */
 
670
LOCAL char              *gpCloseText;
 
671
 
 
672
LOCAL DWORD             gGMLastCall = 0;        /* Last time I called
 
673
                                                 * GetMessage. */
 
674
LOCAL BOOL              gConfirmExit = FALSE;
 
675
LOCAL HICON             ghNormalIcon = NULL;
 
676
LOCAL HICON             ghNewMailIcon = NULL;
 
677
LOCAL HICON             ghMClosedIcon = NULL;
 
678
 
 
679
LOCAL int               gPrintFontSize;
 
680
LOCAL TCHAR             gPrintFontName[LF_FACESIZE];
 
681
LOCAL TCHAR             gPrintFontStyle[64];
 
682
LOCAL TCHAR             gPrintFontCharSet[256];
 
683
LOCAL BOOL              gPrintFontSameAs = TRUE;
 
684
 
 
685
LOCAL UINT              gTimerCurrentPeriod = 0;
 
686
 
 
687
LOCAL cbvoid_t          gPeriodicCallback = NULL; /* Function to call. */
 
688
LOCAL DWORD             gPeriodicCBTimeout = 0;   /* Time of next call. */
 
689
LOCAL DWORD             gPeriodicCBTime = 0;      /* Delay between calls. */
 
690
 
 
691
//=========================================================================
 
692
// n
 
693
//=========================================================================
 
694
MSWIN_TEXTWINDOW        gMswinAltWin = {0};
 
695
MSWIN_TEXTWINDOW        gMswinNewMailWin = {0};
 
696
 
 
697
MSWIN_TEXTWINDOW        gMswinIMAPTelem = {0};
 
698
LOCAL cbvoid_t          gIMAPDebugONCallback = NULL;
 
699
LOCAL cbvoid_t          gIMAPDebugOFFCallback = NULL;
 
700
LOCAL cbvoid_t          gEraseCredsCallback = NULL;
 
701
 
 
702
LOCAL cbvoid_t          gConfigScreenCallback = NULL;
 
703
 
 
704
LOCAL cbarg_t           gMouseTrackCallback = NULL;
 
705
 
 
706
/* Currently only implement one SIGNAL so only need single variable. */
 
707
LOCAL SignalType        gSignalAlarm = SIG_DFL;
 
708
LOCAL DWORD             gAlarmTimeout = 0;      /* Time alarm expires in
 
709
                                                 * seconds
 
710
                                                 * (GetTickCount()/1000) */
 
711
LOCAL SignalType        gSignalHUP = SIG_DFL;
 
712
 
 
713
LOCAL IconList         *gIconList = NULL;
 
714
 
 
715
 
 
716
/*
 
717
 * There is some coordination between these names and the similar names
 
718
 * in osdep/unix. The names in the left column are mapped to the colors
 
719
 * in the right column when displaying. Note that the last eight colors map
 
720
 * to the same thing as the 1st eight colors. This is an attempt to inter-
 
721
 * operate with 16-color xterms. When editing a color and writing the color
 
722
 * into the config file, we use the canonical_name (middle column). So if
 
723
 * the user chooses green from the menu we write color010 in the config
 
724
 * file. [This has changed. Now we put the RGB value in the config file
 
725
 * instead. We leave this so that we can interpret color010 in the config
 
726
 * file from old versions of pine.]
 
727
 * We display that as green later. The xterm also displays that as
 
728
 * green, because the bright green (color010) on the xterm is what we want
 
729
 * to consider to be green, and the other one (color002) is dark green.
 
730
 * And dark green sucks.
 
731
 * On the PC we only use the first 11 colors in this table when giving the
 
732
 * user the set color display, since the last eight are repeats.
 
733
 */
 
734
LOCAL MSWINColor  MSWINColorTable[] =  {
 
735
        "black",        "000,000,000",  RGB(0,0,0),
 
736
        "red",          "255,000,000",  RGB(255,0,0),
 
737
        "green",        "000,255,000",  RGB(0,255,0),
 
738
        "yellow",       "255,255,000",  RGB(255,255,0),
 
739
        "blue",         "000,000,255",  RGB(0,0,255),
 
740
        "magenta",      "255,000,255",  RGB(255,0,255),
 
741
        "cyan",         "000,255,255",  RGB(0,255,255),
 
742
        "white",        "255,255,255",  RGB(255,255,255),
 
743
        "colorlgr",     "192,192,192",  RGB(192,192,192),       /* lite gray */
 
744
        "colormgr",     "128,128,128",  RGB(128,128,128),       /* med. gray */
 
745
        "colordgr",     "064,064,064",  RGB(64,64,64),          /* dark gray */
 
746
        "color008",     "000,000,000",  RGB(0,0,0),
 
747
        "color009",     "255,000,000",  RGB(255,0,0),
 
748
        "color010",     "000,255,000",  RGB(0,255,0),
 
749
        "color011",     "255,255,000",  RGB(255,255,0),
 
750
        "color012",     "000,000,255",  RGB(0,0,255),
 
751
        "color013",     "255,000,255",  RGB(255,0,255),
 
752
        "color014",     "000,255,255",  RGB(0,255,255),
 
753
        "color015",     "255,255,255",  RGB(255,255,255),
 
754
        NULL,           NULL,           0
 
755
};
 
756
 
 
757
#define fullColorTableSize ((sizeof(MSWINColorTable) / sizeof(MSWINColorTable[0])) - 1)
 
758
#define visibleColorTableSize  (fullColorTableSize - 8)
 
759
 
 
760
 
 
761
LOCAL MSWinCaret_t MSWinCaretTable[] = {
 
762
        "Block",        CaretBlock,
 
763
        "ShortBlock",   CaretSmallBlock,
 
764
        "Underline",    CaretHorizBar,
 
765
        "VertBar",      CaretVertBar,
 
766
        NULL,           0
 
767
};
 
768
 
 
769
 
 
770
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
771
 *
 
772
 *                      Windows Functions.
 
773
 *
 
774
 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
 
775
 
 
776
/*---------------------------------------------------------------------------
 
777
 *  int PASCAL WinMain( HANDLE hInstance, HANDLE hPrevInstance,
 
778
 *                      LPSTR lpszCmdLine, int nCmdShow )
 
779
 *
 
780
 *  Description:
 
781
 *     This is the main window loop!
 
782
 *
 
783
 *  Parameters:
 
784
 *     As documented for all WinMain() functions.
 
785
 *
 
786
 *--------------------------------------------------------------------------*/
 
787
int PASCAL
 
788
wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
 
789
                    LPTSTR lpszCmdLine, int nCmdShow )
 
790
{
 
791
    CHAR                **argv;
 
792
    int                 argc, i, nosplash = 0;
 
793
    char               *cmdline_utf8;
 
794
 
 
795
    ghInstance = hInstance;
 
796
    if (!hPrevInstance)
 
797
        if (!InitApplication( hInstance ))
 
798
            return ( FALSE ) ;
 
799
 
 
800
#ifdef OWN_DEBUG_FILE   /* Want to write to seperate memdebug.txt file. */
 
801
    mswin_debugfile = fopen ("memdebug.txt", "w");
 
802
    fprintf (mswin_debugfile, "Beginning of mswin debug log\n");
 
803
    if (mswin_debugfile != NULL) {
 
804
        mswin_debug = 4;
 
805
        MemDebug (mswin_debug, mswin_debugfile);
 
806
        fprintf (mswin_debugfile, "Show window as:  %d\n", nCmdShow);
 
807
        fflush (mswin_debugfile);
 
808
    }
 
809
#endif
 
810
 
 
811
    if (NULL == (ghTTYWnd = InitInstance (hInstance, nCmdShow)))
 
812
        return (FALSE);
 
813
 
 
814
    /* cmdline_utf8 memory is never freed */
 
815
    cmdline_utf8 = lptstr_to_utf8(lpszCmdLine);
 
816
 
 
817
    MakeArgv (hInstance, cmdline_utf8, &argc, &argv);
 
818
 
 
819
    for(i = 0; i < argc; i++)
 
820
      if(strcmp((const char *)argv[i], "-nosplash") == 0){
 
821
          nosplash = 1;
 
822
          break;
 
823
      }
 
824
    /* Create Splash window */
 
825
    if(nosplash == 0){
 
826
        ghSplashWnd = CreateDialog(hInstance,
 
827
                                   MAKEINTRESOURCE( SPLASHDLGBOX ),
 
828
                                   ghTTYWnd, (DLGPROC)SplashDlgProc);
 
829
        ShowWindow (ghSplashWnd, SW_SHOWNORMAL);
 
830
    }
 
831
 
 
832
    atexit (WinExit);
 
833
 
 
834
    app_main (argc, (char **)argv);
 
835
 
 
836
    return (TRUE);
 
837
}
 
838
 
 
839
 
 
840
void
 
841
WinExit (void)
 
842
{
 
843
    MSG                 msg;
 
844
 
 
845
    if (ghTTYWnd == NULL)
 
846
        return;
 
847
 
 
848
    UpdateTrayIcon(NIM_DELETE, 0, NULL);
 
849
 
 
850
    /* Destroy main window and process remaining events. */
 
851
    DestroyWindow (ghTTYWnd);
 
852
    while (GetMessage (&msg, NULL, 0, 0)) {
 
853
        TranslateMessage (&msg);
 
854
        DispatchMessage (&msg);
 
855
    }
 
856
 
 
857
#ifdef OWN_DEBUG_FILE
 
858
    fclose (mswin_debugfile);
 
859
#endif
 
860
    if (gWSBlockingProc != NULL)
 
861
        FreeProcInstance (gWSBlockingProc);
 
862
 
 
863
    MemFreeAll ();
 
864
    ghTTYWnd = NULL;
 
865
}
 
866
 
 
867
 
 
868
/*---------------------------------------------------------------------------
 
869
 *  BOOL  InitApplication( HANDLE hInstance )
 
870
 *
 
871
 *  Description:
 
872
 *     First time initialization stuff.  This registers information
 
873
 *     such as window classes.
 
874
 *
 
875
 *  Parameters:
 
876
 *     HANDLE hInstance
 
877
 *        Handle to this instance of the application.
 
878
 *
 
879
 *--------------------------------------------------------------------------*/
 
880
LOCAL BOOL
 
881
InitApplication (HANDLE hInstance)
 
882
{
 
883
    WNDCLASS  wndclass;
 
884
 
 
885
    /*
 
886
     * Register tty window class.
 
887
     */
 
888
    wndclass.style =         0;  /* CS_NOCLOSE; */
 
889
    wndclass.lpfnWndProc =   PWndProc;
 
890
    wndclass.cbClsExtra =    0;
 
891
    wndclass.cbWndExtra =    sizeof (LONG);
 
892
    wndclass.hInstance =     hInstance ;
 
893
    /* In win16 we paint our own icon. */
 
894
    wndclass.hIcon =         LoadIcon (hInstance, MAKEINTRESOURCE (ALPINEICON));
 
895
    wndclass.hCursor =       LoadCursor (NULL, IDC_ARROW);
 
896
    wndclass.hbrBackground = (HBRUSH) (COLOR_WINDOW + 1);
 
897
    wndclass.lpszMenuName =  MAKEINTRESOURCE (ALPINEMENU);
 
898
    wndclass.lpszClassName = gszTTYClass ;
 
899
 
 
900
    return (RegisterClass (&wndclass));
 
901
}
 
902
 
 
903
 
 
904
/*---------------------------------------------------------------------------
 
905
 *  HWND  InitInstance( HANDLE hInstance, int nCmdShow )
 
906
 *
 
907
 *  Description:
 
908
 *     Initializes instance specific information.
 
909
 *
 
910
 *  Parameters:
 
911
 *     HANDLE hInstance
 
912
 *        Handle to instance
 
913
 *
 
914
 *     int nCmdShow
 
915
 *        How do we show the window?
 
916
 *
 
917
/*--------------------------------------------------------------------------*/
 
918
LOCAL HWND
 
919
InitInstance (HANDLE hInstance, int nCmdShow)
 
920
{
 
921
    HWND       hTTYWnd;
 
922
    TCHAR      appIdent[32];
 
923
    SCROLLINFO scrollInfo;
 
924
 
 
925
#ifdef SDEBUG
 
926
    if (mswin_debug >= 5)
 
927
        fprintf (mswin_debugfile, "InitInstance:::  entered, nCmdShow %d\n",
 
928
                nCmdShow);
 
929
#endif
 
930
 
 
931
    LoadString (hInstance, IDS_APPNAME, gszAppName, sizeof(gszAppName) / sizeof(TCHAR));
 
932
 
 
933
    /* create the TTY window */
 
934
    hTTYWnd = CreateWindow (gszTTYClass, gszAppName,
 
935
                       WS_OVERLAPPEDWINDOW | WS_VSCROLL,
 
936
                       CW_USEDEFAULT, CW_USEDEFAULT,
 
937
                       CW_USEDEFAULT, CW_USEDEFAULT,
 
938
                       HWND_DESKTOP, NULL, hInstance, NULL);
 
939
        
 
940
    scrollInfo.cbSize = sizeof(SCROLLINFO);
 
941
    scrollInfo.fMask = SIF_DISABLENOSCROLL | SIF_PAGE | SIF_RANGE | SIF_POS;
 
942
    scrollInfo.nMin = 0;
 
943
    scrollInfo.nMax = 1;
 
944
    scrollInfo.nPage = 1;
 
945
    scrollInfo.nPos = 0;
 
946
    SetScrollInfo(hTTYWnd, SB_VERT, &scrollInfo, FALSE);
 
947
    EnableScrollBar (hTTYWnd, SB_VERT, ESB_DISABLE_BOTH);
 
948
 
 
949
    if (NULL == hTTYWnd)
 
950
            return (NULL);
 
951
 
 
952
    ghTTYWnd = hTTYWnd;
 
953
 
 
954
    ghNormalIcon = LoadIcon (hInstance, MAKEINTRESOURCE (ALPINEICON));
 
955
    ghNewMailIcon = LoadIcon (hInstance, MAKEINTRESOURCE (NEWMAILICON));
 
956
    ghMClosedIcon = LoadIcon (hInstance, MAKEINTRESOURCE (MCLOSEDICON));
 
957
 
 
958
    ghCursorArrow = LoadCursor (NULL, IDC_ARROW);
 
959
    ghCursorBusy = LoadCursor (NULL, IDC_WAIT);
 
960
    ghCursorIBeam = LoadCursor (NULL, IDC_IBEAM);
 
961
#ifdef  IDC_HAND
 
962
    ghCursorHand = LoadCursor (NULL, IDC_HAND);
 
963
#else
 
964
    ghCursorHand = LoadCursor (hInstance, MAKEINTRESOURCE( PICOHAND ));
 
965
#endif
 
966
    ghCursorCurrent = ghCursorArrow;
 
967
 
 
968
    MouseWheelMultiplier();
 
969
 
 
970
    CQInit ();
 
971
    MQInit ();
 
972
 
 
973
 
 
974
    /*
 
975
     * Load a resource with the name of the application.  Compare to
 
976
     * known applications to determine who we are running under.
 
977
     * currently, only differentiation is the WINSOCK blocking hook.
 
978
     */
 
979
    LoadString (hInstance, IDS_APPIDENT, appIdent, sizeof(appIdent) / sizeof(TCHAR));
 
980
    if (_tcscmp (appIdent, APP_PINE_IDENT) == 0) {
 
981
        gAppIdent = APP_PINE;
 
982
        gWSBlockingProc = MakeProcInstance ( (FARPROC) NoMsgsAreSent,
 
983
                                              hInstance);
 
984
    }
 
985
    else if (_tcscmp (appIdent, APP_PICO_IDENT) == 0)
 
986
        gAppIdent = APP_PICO;
 
987
    else
 
988
        gAppIdent = APP_UNKNOWN;
 
989
 
 
990
 
 
991
    return (hTTYWnd);
 
992
}
 
993
 
 
994
 
 
995
/*---------------------------------------------------------------------------
 
996
 *  void MakeArgv ()
 
997
 *
 
998
 *  Description:
 
999
 *      Build a standard C argc, argv pointers into the command line string.
 
1000
 *
 
1001
 *
 
1002
 *  Parameters:
 
1003
 *      cmdLine         - Command line.
 
1004
 *      *argc           - Count of words.
 
1005
 *      ***argc         - Pointer to Pointer to array of pointers to
 
1006
 *                        characters.
 
1007
 *
 
1008
 *--------------------------------------------------------------------------*/
 
1009
LOCAL void
 
1010
MakeArgv (HINSTANCE hInstance, char *cmdLine_utf8, int *pargc, CHAR ***pargv)
 
1011
{
 
1012
    CHAR                **argv;
 
1013
    LPSTR               c;
 
1014
    BOOL                inWord, inQuote;
 
1015
    int                 wordCount;
 
1016
#define CMD_PATH_LEN    128
 
1017
    LPTSTR              modPath_lptstr;
 
1018
    DWORD               mpLen;
 
1019
 
 
1020
 
 
1021
    /* Count words in cmdLine. */
 
1022
    wordCount = 0;
 
1023
    inWord = FALSE;
 
1024
    inQuote = FALSE;
 
1025
    for (c = cmdLine_utf8; *c != '\0'; ++c) {
 
1026
        if (inQuote) {
 
1027
            if(*c == '"' && (*(c+1) == ' ' || *(c+1) == '\t' || *(c+1) == '\0')){
 
1028
                inQuote = inWord = FALSE;
 
1029
            }
 
1030
        }
 
1031
        else {
 
1032
            if(inWord && (*c == ' ' || *c == '\t' || *c == '\0')){
 
1033
                inWord = FALSE;
 
1034
            }
 
1035
            else if(!inWord && (*c != ' ' && *c != '\t')){
 
1036
                inWord = TRUE;
 
1037
                wordCount++;
 
1038
                if(*c == '"')
 
1039
                  inQuote = TRUE;
 
1040
            }
 
1041
        }
 
1042
    }
 
1043
 
 
1044
    ++wordCount;                                /* One for program name. */
 
1045
    argv = (CHAR **) MemAlloc (sizeof (CHAR *) * (wordCount + 1));
 
1046
    *pargv = argv;
 
1047
    *pargc = wordCount;
 
1048
 
 
1049
    modPath_lptstr = (LPTSTR) MemAlloc (CMD_PATH_LEN*sizeof(TCHAR));
 
1050
    mpLen = GetModuleFileName (hInstance, modPath_lptstr, CMD_PATH_LEN);
 
1051
    if (mpLen > 0) {
 
1052
        *(modPath_lptstr + mpLen) = '\0';
 
1053
        *(argv++) = (unsigned char *)lptstr_to_utf8(modPath_lptstr);
 
1054
    }
 
1055
    else
 
1056
      *(argv++) = (unsigned char *)"Alpine/Pico";
 
1057
 
 
1058
    MemFree((void *)modPath_lptstr);
 
1059
 
 
1060
    /* Now break up command line. */
 
1061
    inWord = FALSE;
 
1062
    inQuote = FALSE;
 
1063
    for (c = cmdLine_utf8; *c != '\0'; ++c) {
 
1064
        if (inQuote) {
 
1065
            if(*c == '"' && (*(c+1) == ' ' || *(c+1) == '\t' || *(c+1) == '\0')){
 
1066
                inQuote = inWord = FALSE;
 
1067
                *c = '\0';
 
1068
            }
 
1069
        }
 
1070
        else {
 
1071
            if(inWord && (*c == ' ' || *c == '\t' || *c == '\0')){
 
1072
                *c = '\0';
 
1073
                inWord = FALSE;
 
1074
            }
 
1075
            else if(!inWord && (*c != ' ' && *c != '\t')){
 
1076
                inWord = TRUE;
 
1077
                if(*c == '"'){
 
1078
                  inQuote = TRUE;
 
1079
                  *(argv++) = (unsigned char *)c+1;
 
1080
                }
 
1081
                else
 
1082
                  *(argv++) = (unsigned char *)c;
 
1083
            }
 
1084
        }
 
1085
    }
 
1086
 
 
1087
    *argv = NULL;                       /* tie off argv */
 
1088
}
 
1089
 
 
1090
 
 
1091
/*---------------------------------------------------------------------------
 
1092
 *  LRESULT FAR PASCAL __export PWndProc( HWND hWnd, UINT uMsg,
 
1093
 *                                 WPARAM wParam, LPARAM lParam )
 
1094
 *
 
1095
 *  Description:
 
1096
 *     This is the TTY Window Proc.  This handles ALL messages
 
1097
 *     to the tty window.
 
1098
 *
 
1099
 *  Parameters:
 
1100
 *     As documented for Window procedures.
 
1101
 *
 
1102
/*--------------------------------------------------------------------------*/
 
1103
LRESULT FAR PASCAL __export
 
1104
PWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
 
1105
{
 
1106
#ifdef CDEBUG
 
1107
    if (mswin_debug > 12) {
 
1108
        fprintf (mswin_debugfile, "PWndProc::  uMsg = 0x%x\n", uMsg);
 
1109
        fflush (mswin_debugfile);
 
1110
    }
 
1111
#endif
 
1112
    switch (uMsg) {
 
1113
    case WM_CREATE:
 
1114
         MyTimerSet ();
 
1115
         return (CreateTTYInfo (hWnd));
 
1116
 
 
1117
    case WM_COMMAND:
 
1118
        switch ((WORD) wParam) {
 
1119
 
 
1120
        case IDM_OPT_SETFONT:
 
1121
            SelectTTYFont (hWnd);
 
1122
            break ;
 
1123
        
 
1124
        case IDM_OPT_FONTSAMEAS:
 
1125
            PrintFontSameAs (hWnd);
 
1126
            break;
 
1127
        
 
1128
        case IDM_OPT_TOOLBAR:
 
1129
            TBToggle (hWnd);
 
1130
            break;
 
1131
        
 
1132
        case IDM_OPT_TOOLBARPOS:
 
1133
            TBPosToggle (hWnd);
 
1134
            break;
 
1135
        
 
1136
        case IDM_OPT_USEDIALOGS: {
 
1137
            PTTYINFO    pTTYInfo;
 
1138
        
 
1139
            gfUseDialogs = !gfUseDialogs;
 
1140
            pTTYInfo = (PTTYINFO)(LONG_PTR)MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
 
1141
            if (pTTYInfo)
 
1142
                DidResize (pTTYInfo);
 
1143
            break;
 
1144
            }
 
1145
 
 
1146
        case IDM_OPT_ERASE_CREDENTIALS:
 
1147
            if(gEraseCredsCallback)
 
1148
              (*gEraseCredsCallback)();
 
1149
            break;
 
1150
 
 
1151
        case IDM_OPT_IMAPTELEM:
 
1152
            mswin_tw_init(&gMswinIMAPTelem, (int)LOWORD(wParam),
 
1153
                TEXT("IMAP Telemetry"));
 
1154
            SetFocus (ghTTYWnd);
 
1155
            break;
 
1156
 
 
1157
        case IDM_OPT_NEWMAILWIN:
 
1158
            mswin_tw_init(&gMswinNewMailWin, (int)LOWORD(wParam),
 
1159
                TEXT("New Mail View"));
 
1160
            SetFocus (ghTTYWnd);
 
1161
            break;
 
1162
 
 
1163
#ifdef ACCELERATORS_OPT
 
1164
        case IDM_OPT_USEACCEL:
 
1165
            AccelCtl (hWnd, ACCEL_TOGGLE, TRUE);
 
1166
            break;
 
1167
#endif  
 
1168
        
 
1169
        case IDM_OPT_SETPRINTFONT:
 
1170
            PrintFontSelect (hWnd);
 
1171
            break;
 
1172
 
 
1173
        case IDM_OPT_CARETBLOCK :
 
1174
          CaretTTY(hWnd, CaretBlock);
 
1175
          break;
 
1176
 
 
1177
        case IDM_OPT_CARETSMALLBLOCK :
 
1178
          CaretTTY(hWnd, CaretSmallBlock);
 
1179
          break;
 
1180
 
 
1181
        case IDM_OPT_CARETVBAR :
 
1182
          CaretTTY(hWnd, CaretVertBar);
 
1183
          break;
 
1184
 
 
1185
        case IDM_OPT_CARETHBAR :
 
1186
          CaretTTY(hWnd, CaretHorizBar);
 
1187
          break;
 
1188
 
 
1189
        case IDM_ABOUT:
 
1190
            GoModalDialogBoxParam ( GET_HINST( hWnd ),
 
1191
                                       MAKEINTRESOURCE( ABOUTDLGBOX ),
 
1192
                                       hWnd,
 
1193
                                       (DLGPROC)AboutDlgProc, (LPARAM) 0 ) ;
 
1194
            break;
 
1195
        
 
1196
        case IDM_EDIT_CUT:
 
1197
            EditCut ();
 
1198
            break;
 
1199
        
 
1200
        case IDM_EDIT_COPY:
 
1201
            EditCopy ();
 
1202
            break;
 
1203
        
 
1204
        case IDM_EDIT_COPY_APPEND:
 
1205
            EditCopyAppend ();
 
1206
            break;
 
1207
        
 
1208
        case IDM_EDIT_PASTE:
 
1209
            EditPaste ();
 
1210
#ifdef ACCELERATORS
 
1211
            UpdateAccelerators (hWnd);
 
1212
#endif
 
1213
            break;
 
1214
        
 
1215
        case IDM_EDIT_CANCEL_PASTE:
 
1216
            EditCancelPaste ();
 
1217
#ifdef ACCELERATORS
 
1218
            UpdateAccelerators (hWnd);
 
1219
#endif
 
1220
            break;
 
1221
 
 
1222
        case IDM_EDIT_SEL_ALL :
 
1223
          EditSelectAll();
 
1224
          break;
 
1225
        
 
1226
        case IDM_HELP:
 
1227
            MSWHelpShow (gHelpCallback);
 
1228
            break;
 
1229
 
 
1230
        case IDM_MI_GENERALHELP:
 
1231
            MSWHelpShow (gHelpGenCallback);
 
1232
            break;
 
1233
 
 
1234
        case IDM_MI_WHEREIS :
 
1235
          CQAdd (gpTTYInfo->menuItems[KS_WHEREIS - KS_RANGESTART].miKey, 0);
 
1236
          break;
 
1237
 
 
1238
        case IDM_MI_SORTSUBJECT :
 
1239
        case IDM_MI_SORTARRIVAL :
 
1240
        case IDM_MI_SORTSIZE :
 
1241
        case IDM_MI_SORTFROM :
 
1242
        case IDM_MI_SORTTO :
 
1243
        case IDM_MI_SORTCC :
 
1244
        case IDM_MI_SORTDATE :
 
1245
        case IDM_MI_SORTORDERSUB :
 
1246
        case IDM_MI_SORTSCORE :
 
1247
        case IDM_MI_SORTTHREAD :
 
1248
          SortHandler((int)(wParam - IDM_MI_SORTSUBJECT), 0);
 
1249
          break;
 
1250
        
 
1251
        case IDM_MI_SORTREVERSE :
 
1252
          SortHandler(-1, 1);
 
1253
          break;
 
1254
 
 
1255
        case IDM_MI_FLAGIMPORTANT :
 
1256
        case IDM_MI_FLAGNEW :
 
1257
        case IDM_MI_FLAGANSWERED :
 
1258
        case IDM_MI_FLAGDELETED :
 
1259
          FlagHandler((int)(wParam - IDM_MI_FLAGIMPORTANT), 0);
 
1260
          break;
 
1261
 
 
1262
        default:
 
1263
            /* value falling within the menu item range are handled here. */
 
1264
            if (wParam >= KS_RANGESTART && wParam <= KS_RANGEEND){
 
1265
                ProcessMenuItem (hWnd, wParam);
 
1266
                break;
 
1267
            }
 
1268
            break;
 
1269
        }
 
1270
        break ;
 
1271
        
 
1272
    case WM_VSCROLL:
 
1273
        ScrollTTY (hWnd, LOWORD(wParam), HIWORD(wParam), (HWND) lParam);
 
1274
        break;
 
1275
 
 
1276
    case WM_MOUSEWHEEL:
 
1277
        MouseWheelTTY (hWnd, LOWORD(lParam), HIWORD(lParam),
 
1278
                       LOWORD(wParam), (short) HIWORD(wParam));
 
1279
        break;
 
1280
 
 
1281
    case WM_ERASEBKGND:
 
1282
        if (IsIconic (hWnd))
 
1283
            return (DefWindowProc (hWnd, WM_ICONERASEBKGND, wParam, lParam));
 
1284
        else
 
1285
            EraseTTY (hWnd, (HDC) wParam);
 
1286
        break;
 
1287
        
 
1288
    case WM_QUERYDRAGICON:
 
1289
        return ((LRESULT)ghNormalIcon);
 
1290
 
 
1291
    case WM_PAINT:
 
1292
        PaintTTY (hWnd);
 
1293
        break ;
 
1294
        
 
1295
    case WM_GETMINMAXINFO:
 
1296
        GetMinMaxInfoTTY (hWnd, (MINMAXINFO __far *)lParam);
 
1297
        break;
 
1298
 
 
1299
    case WM_SIZE:
 
1300
        SizeTTY (hWnd, (int)wParam, HIWORD(lParam), LOWORD(lParam));
 
1301
        break ;
 
1302
 
 
1303
    case WM_SIZING :
 
1304
        return(SizingTTY(hWnd, (int)wParam, (LPRECT) lParam));
 
1305
        
 
1306
    case WM_MOVE:
 
1307
/*      MoveTTY (hWnd, (int) LOWORD(lParam), (int) HIWORD(lParam));  */
 
1308
        break;
 
1309
        
 
1310
    case WM_WINDOWPOSCHANGING:
 
1311
        /* Allows us to adjust new size of window. */
 
1312
        AboutToSizeTTY (hWnd, (WINDOWPOS FAR *) lParam);
 
1313
        break;
 
1314
 
 
1315
 
 
1316
    case TASKBAR_ICON_MESSAGE:
 
1317
        /* Notification of a mouse event in the task bar tray.
 
1318
         * If they are clicking on it we will restore the window. */
 
1319
        if (lParam == WM_LBUTTONDOWN){
 
1320
            if(gpTTYInfo->fMinimized)
 
1321
              ShowWindow (hWnd, SW_RESTORE);
 
1322
            else
 
1323
              SetForegroundWindow(hWnd);
 
1324
        }
 
1325
 
 
1326
        break;
 
1327
                
 
1328
 
 
1329
    /*
 
1330
     * WM_KEYDOWN is sent for every "key press" and reports on the
 
1331
     * keyboard key, with out processing shift and control keys.
 
1332
     * WM_CHAR is a synthetic event, created from KEYDOWN and KEYUP
 
1333
     * events.  It includes processing or control and shift characters.
 
1334
     * But does not get generated for extended keys suchs as arrow
 
1335
     * keys.
 
1336
     * I'm going to try to use KEYDOWN for processing just extended keys
 
1337
     * and let CHAR handle the the rest.
 
1338
     *
 
1339
     * The only key combo that is special is ^-space.  For that, I'll use
 
1340
     * WM_KEYDOWN and WM_KEYUP to track the state of the control key.
 
1341
     */
 
1342
    case WM_CHAR:
 
1343
        /*
 
1344
         * If the windows cursor is visible and we have keyboard input
 
1345
         * then hide the windows cursor
 
1346
         */
 
1347
        mswin_showcursor(FALSE);
 
1348
        ProcessTTYCharacter (hWnd, (TCHAR)wParam, (DWORD)lParam);
 
1349
        break ;
 
1350
        
 
1351
    case WM_KEYDOWN:
 
1352
      if (ProcessTTYKeyDown (hWnd, (TCHAR) wParam, (DWORD)lParam))
 
1353
            return (0);
 
1354
 
 
1355
        return( DefWindowProc( hWnd, uMsg, wParam, lParam ) ) ;
 
1356
 
 
1357
    case WM_KEYUP:
 
1358
      if (ProcessTTYKeyUp (hWnd, (TCHAR) wParam, (DWORD)lParam))
 
1359
            return (0);
 
1360
        return( DefWindowProc( hWnd, uMsg, wParam, lParam ) ) ;
 
1361
        
 
1362
        
 
1363
    case WM_SYSCHAR:
 
1364
        if (gFkeyCallback && (*gFkeyCallback)(0, 0)
 
1365
            && LOBYTE (wParam) == VK_F10){
 
1366
            ProcessTTYCharacter (hWnd, (TCHAR)wParam, (DWORD)lParam);
 
1367
            return (0);
 
1368
        }
 
1369
 
 
1370
        return( DefWindowProc( hWnd, uMsg, wParam, lParam ) ) ;
 
1371
        
 
1372
    case WM_SYSKEYDOWN:
 
1373
        if (gFkeyCallback && (*gFkeyCallback)(0, 0)
 
1374
            && LOBYTE (wParam) == VK_F10
 
1375
            && ProcessTTYKeyDown (hWnd, (TCHAR) wParam, (DWORD)lParam))
 
1376
          return (0);
 
1377
 
 
1378
        return( DefWindowProc( hWnd, uMsg, wParam, lParam ) ) ;
 
1379
 
 
1380
    case WM_SYSKEYUP:
 
1381
        /* As it looks like syskedown and syskeyup aren't symetric,
 
1382
         * at least as far as "altgr" is concerned, always check
 
1383
         * for VK_CONTROL to flip off gKeyControlDown
 
1384
         */
 
1385
      if(ProcessTTYKeyUp (hWnd, (TCHAR) wParam, (DWORD)lParam))
 
1386
          return (0);
 
1387
 
 
1388
        return( DefWindowProc( hWnd, uMsg, wParam, lParam ) ) ;
 
1389
        
 
1390
 
 
1391
    case WM_LBUTTONDOWN:
 
1392
        ProcessTTYMouse (hWnd, M_EVENT_DOWN, M_BUTTON_LEFT, LOWORD (lParam),
 
1393
                         HIWORD (lParam), wParam);
 
1394
        break;
 
1395
 
 
1396
    case WM_LBUTTONUP:
 
1397
        if (ProcessTTYMouse (hWnd, M_EVENT_UP, M_BUTTON_LEFT, LOWORD (lParam),
 
1398
                         HIWORD (lParam), wParam))
 
1399
            goto callDef;
 
1400
        break;
 
1401
 
 
1402
    case WM_MBUTTONDOWN:
 
1403
        ProcessTTYMouse (hWnd, M_EVENT_DOWN, M_BUTTON_MIDDLE, LOWORD (lParam),
 
1404
                 HIWORD (lParam), wParam);
 
1405
        break;
 
1406
 
 
1407
    case WM_MBUTTONUP:
 
1408
        ProcessTTYMouse (hWnd, M_EVENT_UP, M_BUTTON_MIDDLE, LOWORD (lParam),
 
1409
                         HIWORD (lParam), wParam);
 
1410
        break;
 
1411
 
 
1412
    case WM_RBUTTONDOWN:
 
1413
        ProcessTTYMouse (hWnd, M_EVENT_DOWN, M_BUTTON_RIGHT, LOWORD (lParam),
 
1414
                         HIWORD (lParam), wParam);
 
1415
        break;
 
1416
 
 
1417
    case WM_RBUTTONUP:
 
1418
        ProcessTTYMouse (hWnd, M_EVENT_UP, M_BUTTON_RIGHT, LOWORD (lParam),
 
1419
                         HIWORD (lParam), wParam);
 
1420
        break;
 
1421
        
 
1422
    case WM_MOUSEMOVE:
 
1423
        ProcessTTYMouse (hWnd, M_EVENT_TRACK, 0, LOWORD (lParam),
 
1424
                        HIWORD (lParam), wParam);
 
1425
        break;
 
1426
 
 
1427
    case WM_NCMOUSEMOVE:
 
1428
        mswin_showcursor(TRUE);
 
1429
        goto callDef;           /* pretend it never happened */
 
1430
 
 
1431
    case WM_SETFOCUS:
 
1432
        SetTTYFocus (hWnd);
 
1433
        break;
 
1434
 
 
1435
    case WM_KILLFOCUS:
 
1436
        KillTTYFocus (hWnd);
 
1437
        break;
 
1438
        
 
1439
    case WM_SETCURSOR:
 
1440
        /* Set cursor.  If in client, leave as is.  Otherwise, pass to
 
1441
         * DefWindow Proc */
 
1442
        if (LOWORD(lParam) == HTCLIENT) {
 
1443
            SetCursor (ghCursorCurrent);
 
1444
            return (TRUE);
 
1445
        }
 
1446
 
 
1447
        return( DefWindowProc( hWnd, uMsg, wParam, lParam ) ) ;
 
1448
 
 
1449
    case WM_INITMENU:
 
1450
        UpdateMenu (hWnd);
 
1451
        break;
 
1452
        
 
1453
    case WM_TIMER:
 
1454
        /* Really just used so that we continue to receive messages even while
 
1455
         * in background.  Causes mswin_getc() to process message and return
 
1456
         * to caller so that it can get some periodic processing in. */
 
1457
        ProcessTimer ();
 
1458
        break;
 
1459
        
 
1460
    case WM_QUERYENDSESSION:
 
1461
        /* Returns non-zero if I can exit, otherwize zero, and the end
 
1462
         * session operation stops. */
 
1463
        return ((LRESULT)ConfirmExit ());
 
1464
        
 
1465
    case WM_DESTROY:
 
1466
        KillTimer (hWnd, MY_TIMER_ID);
 
1467
        DestroyTTYInfo (hWnd);
 
1468
        PostQuitMessage (0);
 
1469
        break;
 
1470
 
 
1471
 
 
1472
    case WM_DROPFILES:
 
1473
        if(ProcessTTYFileDrop((HANDLE) wParam) == TRUE)
 
1474
          SetForegroundWindow(hWnd);
 
1475
 
 
1476
       break;
 
1477
 
 
1478
 
 
1479
    case WM_CLOSE:
 
1480
        /* If the quit menu is active then insert the quit command
 
1481
         * Otherwise, abort. */
 
1482
        if (gpTTYInfo->menuItems[KS_EXIT - KS_RANGESTART].miActive) {
 
1483
            CQAdd (gpTTYInfo->menuItems[KS_EXIT - KS_RANGESTART].miKey, 0);
 
1484
        }
 
1485
        else if (gSignalHUP != SIG_DFL && gSignalHUP != SIG_IGN) {
 
1486
            if (MessageBox (hWnd,
 
1487
                            TEXT("Abort PINE/PICO, possibly losing current work?"),
 
1488
                            gszAppName, MB_OKCANCEL | MB_ICONQUESTION) == IDOK)
 
1489
                HUPDeliver ();
 
1490
        }
 
1491
        break;  
 
1492
 
 
1493
 
 
1494
    default:
 
1495
callDef:        
 
1496
        return( DefWindowProc( hWnd, uMsg, wParam, lParam ) ) ;
 
1497
    }
 
1498
    return 0L ;
 
1499
 
 
1500
} /* end of PWndProc() */
 
1501
 
 
1502
 
 
1503
/*---------------------------------------------------------------------------
 
1504
 *  LRESULT NEAR CreateTTYInfo( HWND hWnd )
 
1505
 *
 
1506
 *  Description:
 
1507
 *     Creates the tty information structure and sets
 
1508
 *     menu option availability.  Returns -1 if unsuccessful.
 
1509
 *
 
1510
 *  Parameters:
 
1511
 *     HWND  hWnd
 
1512
 *        Handle to main window.
 
1513
 *
 
1514
 *-------------------------------------------------------------------------*/
 
1515
LOCAL LRESULT NEAR
 
1516
CreateTTYInfo (HWND hWnd)
 
1517
{
 
1518
    HMENU               hMenu;
 
1519
    PTTYINFO            pTTYInfo;
 
1520
    LOGFONT             newFont;
 
1521
    int                 i, ppi;
 
1522
    HDC                 hDC;
 
1523
#ifdef SDEBUG
 
1524
    if (mswin_debug >= 5)
 
1525
        fprintf (mswin_debugfile, "CreateTTYInfo:::  entered\n");
 
1526
#endif
 
1527
 
 
1528
    hDC = GetDC (ghTTYWnd);
 
1529
    ppi = GetDeviceCaps (hDC, LOGPIXELSY);
 
1530
    ReleaseDC (ghTTYWnd, hDC);
 
1531
 
 
1532
    pTTYInfo = (PTTYINFO) MemAlloc (sizeof (TTYINFO));
 
1533
    if (pTTYInfo == NULL)
 
1534
        return ((LRESULT) - 1);
 
1535
    gpTTYInfo = pTTYInfo;
 
1536
 
 
1537
    /* initialize TTY info structure */
 
1538
    memset (pTTYInfo, 0, sizeof (TTYINFO));
 
1539
    /* Shown but not focused. */
 
1540
    pTTYInfo->cCaretStyle               = CaretBlock;
 
1541
    pTTYInfo->fMinimized                = FALSE;
 
1542
    pTTYInfo->fFocused                  = FALSE;
 
1543
    pTTYInfo->fNewLine                  = FALSE;
 
1544
    pTTYInfo->fMassiveUpdate            = FALSE;
 
1545
    pTTYInfo->fNewMailIcon              = FALSE;
 
1546
    pTTYInfo->fMClosedIcon              = FALSE;
 
1547
    pTTYInfo->autoWrap                  = WRAP_NO_SCROLL;
 
1548
    pTTYInfo->xOffset                   = MARGINE_LEFT;
 
1549
    pTTYInfo->yOffset                   = MARGINE_TOP;
 
1550
    pTTYInfo->fDesiredSize              = FALSE;
 
1551
    pTTYInfo->fCursorOn                 = TRUE;
 
1552
    pico_nfcolor(NULL);
 
1553
    pico_nbcolor(NULL);
 
1554
    pico_rfcolor(NULL);
 
1555
    pico_rbcolor(NULL);
 
1556
    pico_set_normal_color();
 
1557
    pTTYInfo->toolBarTop                = TRUE;
 
1558
    pTTYInfo->curToolBarID              = IDD_TOOLBAR;
 
1559
 
 
1560
    /* Clear menu item array. */
 
1561
    pTTYInfo->curWinMenu = ALPINEMENU;
 
1562
    for (i = 0; i < KS_COUNT; ++i)
 
1563
        pTTYInfo->menuItems[i].miActive = FALSE;
 
1564
    pTTYInfo->menuItemsCurrent = FALSE;
 
1565
 
 
1566
    /* Clear resize callback procs. */
 
1567
    for (i = 0; i < RESIZE_CALLBACK_ARRAY_SIZE; ++i)
 
1568
        pTTYInfo->resizer[i] = NULL;
 
1569
 
 
1570
 
 
1571
    /* clear screen space */
 
1572
    pTTYInfo->pScreen = NULL;
 
1573
    pTTYInfo->pCellWidth = NULL;
 
1574
    pTTYInfo->pAttrib = NULL;
 
1575
 
 
1576
    /* setup default font information */
 
1577
 
 
1578
    newFont.lfHeight =         -MulDiv(12, ppi, 72);
 
1579
    newFont.lfWidth =          0;
 
1580
    newFont.lfEscapement =     0;
 
1581
    newFont.lfOrientation =    0;
 
1582
    newFont.lfWeight =         0;
 
1583
    newFont.lfItalic =         0;
 
1584
    newFont.lfUnderline =      0;
 
1585
    newFont.lfStrikeOut =      0;
 
1586
    newFont.lfCharSet =        FONT_CHARSET_FONT;
 
1587
    newFont.lfOutPrecision =   OUT_DEFAULT_PRECIS;
 
1588
    newFont.lfClipPrecision =  CLIP_DEFAULT_PRECIS;
 
1589
    newFont.lfQuality =        DEFAULT_QUALITY;
 
1590
    newFont.lfPitchAndFamily = FIXED_PITCH | FF_MODERN;
 
1591
    newFont.lfFaceName[0] =    '\0';
 
1592
 
 
1593
    /* set TTYInfo handle before any further message processing. */
 
1594
 
 
1595
    MySetWindowLongPtr (hWnd, GWL_PTTYINFO, pTTYInfo);
 
1596
 
 
1597
    /* reset the character information, etc. */
 
1598
 
 
1599
    ResetTTYFont (hWnd, pTTYInfo, &newFont);
 
1600
 
 
1601
 
 
1602
 
 
1603
    hMenu = GetMenu (hWnd);
 
1604
    EnableMenuItem (hMenu, IDM_EDIT_CUT, MF_BYCOMMAND | MF_GRAYED);
 
1605
    EnableMenuItem (hMenu, IDM_EDIT_COPY, MF_BYCOMMAND | MF_GRAYED);
 
1606
    EnableMenuItem (hMenu, IDM_EDIT_COPY_APPEND, MF_BYCOMMAND | MF_GRAYED);
 
1607
    EnableMenuItem (hMenu, IDM_EDIT_PASTE, MF_BYCOMMAND | MF_GRAYED);
 
1608
    return ((LRESULT) TRUE);
 
1609
}
 
1610
 
 
1611
 
 
1612
/*---------------------------------------------------------------------------
 
1613
 *  BOOL NEAR DestroyTTYInfo( HWND hWnd )
 
1614
 *
 
1615
 *  Description:
 
1616
 *     Destroys block associated with TTY window handle.
 
1617
 *
 
1618
 *  Parameters:
 
1619
 *     HWND hWnd
 
1620
 *        handle to TTY window
 
1621
 *
 
1622
 *-------------------------------------------------------------------------*/
 
1623
LOCAL BOOL NEAR
 
1624
DestroyTTYInfo (HWND hWnd)
 
1625
{
 
1626
    PTTYINFO                    pTTYInfo;
 
1627
 
 
1628
    pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
 
1629
    if (pTTYInfo == NULL)
 
1630
        return (FALSE);
 
1631
 
 
1632
#ifdef  ACCELERATORS
 
1633
    if(pTTYInfo->hAccel){
 
1634
        DestroyAcceleratorTable(pTTYInfo->hAccel);
 
1635
        pTTYInfo->hAccel = NULL;
 
1636
        pTTYInfo->fAccel = EM_NONE;
 
1637
    }
 
1638
#endif
 
1639
 
 
1640
    if(pTTYInfo->hTBWnd != NULL)
 
1641
      DestroyWindow (pTTYInfo->hTBWnd);
 
1642
 
 
1643
    if(pTTYInfo->hTBBrush != NULL)
 
1644
      DeleteObject(pTTYInfo->hTBBrush);
 
1645
 
 
1646
    DeleteObject (pTTYInfo->hTTYFont);
 
1647
 
 
1648
    MemFree (pTTYInfo);
 
1649
    return (TRUE);
 
1650
}
 
1651
 
 
1652
 
 
1653
/*---------------------------------------------------------------------------
 
1654
 *  void  ResizeTTYScreen( HWND hWnd, PTTYINFO pTTYInfo,
 
1655
 *                                      int newNrow, int newNColumn);
 
1656
 *
 
1657
 *  Description:
 
1658
 *              Resize the screen to new size, copying data.
 
1659
 *
 
1660
 *  Parameters:
 
1661
 *     PTTYINFO  pTTYInfo
 
1662
 *        pointer to TTY info structure
 
1663
 *              newNCo.umn, newNRow
 
1664
 *                      new size of screen.
 
1665
 *
 
1666
/*--------------------------------------------------------------------------*/
 
1667
LOCAL BOOL
 
1668
ResizeTTYScreen (HWND hWnd, PTTYINFO pTTYInfo, int newNRow, int newNColumn)
 
1669
{
 
1670
    CharAttrib          *pNewAttrib, tmpAttrib, *pSourceAtt, *pDestAtt;
 
1671
    TCHAR               *pNewScreen, *pSource, *pDest;
 
1672
    int                 *pNewCW, *pSourceCW, *pDestCW;
 
1673
    size_t               len;
 
1674
    int                  cells;
 
1675
    int                  r, i;
 
1676
    extern TERM          term;
 
1677
 
 
1678
 
 
1679
    if (newNColumn < MINNCOLUMN)
 
1680
            newNColumn = MINNCOLUMN;
 
1681
    if (newNRow < MINNROW)
 
1682
            newNRow = MINNROW;
 
1683
 
 
1684
#ifdef SDEBUG
 
1685
    if (mswin_debug >= 5)
 
1686
        fprintf (mswin_debugfile, "ResizeTTYScreen:::  entered, new row %d, col %d\n",
 
1687
                newNRow, newNColumn);
 
1688
#endif
 
1689
 
 
1690
        
 
1691
    SelClear ();
 
1692
    cells = newNColumn * newNRow;
 
1693
    pNewScreen = (TCHAR *)MemAlloc (cells * sizeof (TCHAR));
 
1694
    if (pNewScreen == NULL)
 
1695
        return (FALSE);
 
1696
 
 
1697
    pNewCW = (int *)MemAlloc(cells * sizeof(int));
 
1698
    if(pNewCW == NULL){
 
1699
        MemFree((void *)pNewScreen);
 
1700
        return(FALSE);
 
1701
    }
 
1702
 
 
1703
    pNewAttrib = (CharAttrib *)MemAlloc (cells * sizeof (CharAttrib));
 
1704
    if (pNewAttrib == NULL) {
 
1705
        MemFree ((void *)pNewScreen);
 
1706
        MemFree ((void *)pNewCW);
 
1707
        return (FALSE);
 
1708
    }
 
1709
 
 
1710
 
 
1711
    /*
 
1712
     * Clear new screen.
 
1713
     */
 
1714
 
 
1715
    for(i = 0; i < cells; i++){
 
1716
        pNewScreen[i] = ' ';
 
1717
        pNewCW[i] = pTTYInfo->xChar;  /* xChar set yet ? */
 
1718
    }
 
1719
 
 
1720
    tmpAttrib.style = CHAR_ATTR_NORM;
 
1721
    tmpAttrib.rgbFG = pTTYInfo->rgbFGColor;
 
1722
    tmpAttrib.rgbBG = pTTYInfo->rgbBGColor;
 
1723
    for(r = 0; r < cells; r++)
 
1724
        pNewAttrib[r] = tmpAttrib;
 
1725
 
 
1726
    /*
 
1727
     * Copy old screen onto new screen.
 
1728
     */
 
1729
    if (pTTYInfo->pScreen != NULL) {
 
1730
 
 
1731
        for (r = 1; r <= newNRow && r <= pTTYInfo->actNRow; ++r) {
 
1732
            pSource = pTTYInfo->pScreen + ((pTTYInfo->actNRow - r) *
 
1733
                                                    pTTYInfo->actNColumn);
 
1734
            pDest = pNewScreen + ((newNRow - r) * newNColumn);
 
1735
            len = MIN (newNColumn, pTTYInfo->actNColumn);
 
1736
            for(i = 0; i < len; i++)
 
1737
              pDest[i] = pSource[i];
 
1738
 
 
1739
            pSourceCW = pTTYInfo->pCellWidth
 
1740
              + ((pTTYInfo->actNRow - r) * pTTYInfo->actNColumn);
 
1741
            pDestCW = pNewCW + ((newNRow - r) * newNColumn);
 
1742
            memcpy(pDestCW, pSourceCW, len * sizeof(int));
 
1743
 
 
1744
            pSourceAtt = pTTYInfo->pAttrib
 
1745
              + ((pTTYInfo->actNRow - r) * pTTYInfo->actNColumn);
 
1746
            pDestAtt = pNewAttrib + ((newNRow - r) * newNColumn);
 
1747
            len = MIN (newNColumn, pTTYInfo->actNColumn);
 
1748
            memcpy (pDestAtt, pSourceAtt, len * sizeof(CharAttrib));
 
1749
        }
 
1750
 
 
1751
        pTTYInfo->nColumn = (CORD)MIN (pTTYInfo->nColumn, newNColumn);
 
1752
        pTTYInfo->nRow = (CORD)MAX (0,
 
1753
                        pTTYInfo->nRow + (newNRow - pTTYInfo->actNRow));
 
1754
        MemFree (pTTYInfo->pScreen);
 
1755
        MemFree (pTTYInfo->pCellWidth);
 
1756
        MemFree (pTTYInfo->pAttrib);
 
1757
    }
 
1758
    else {
 
1759
        pTTYInfo->nColumn = (CORD)MIN (pTTYInfo->nColumn, newNColumn);
 
1760
        pTTYInfo->nRow = (CORD)MIN (pTTYInfo->nRow, newNRow);
 
1761
    }
 
1762
 
 
1763
    pTTYInfo->pScreen = pNewScreen;
 
1764
    pTTYInfo->pCellWidth = pNewCW;
 
1765
    pTTYInfo->pAttrib = pNewAttrib;
 
1766
    pTTYInfo->actNColumn = newNColumn;
 
1767
    pTTYInfo->actNRow = newNRow;
 
1768
 
 
1769
 
 
1770
    /* Repaint whole screen. */
 
1771
    pTTYInfo->screenDirty = TRUE;
 
1772
    pTTYInfo->eraseScreen = TRUE;
 
1773
    InvalidateRect (hWnd, NULL, FALSE);
 
1774
 
 
1775
 
 
1776
 
 
1777
    /* Pico specific. */
 
1778
    if (term.t_nrow == 0) {
 
1779
        term.t_nrow = (short)(newNRow - 1);
 
1780
        term.t_ncol = (short)newNColumn;
 
1781
    }
 
1782
 
 
1783
 
 
1784
    return (TRUE);
 
1785
}
 
1786
 
 
1787
 
 
1788
/*---------------------------------------------------------------------------
 
1789
 *  BOOL  ResetTTYFont( HWND hWnd, PTTYINFO pTTYInfo, LOGFONT *newFont)
 
1790
 *
 
1791
 *  Description:
 
1792
 *     Resets the TTY character information and causes the
 
1793
 *     screen to resize to update the scroll information.
 
1794
 *
 
1795
 *  Parameters:
 
1796
 *     PTTYINFO  pTTYInfo
 
1797
 *        pointer to TTY info structure
 
1798
 *
 
1799
/*--------------------------------------------------------------------------*/
 
1800
LOCAL BOOL
 
1801
ResetTTYFont (HWND hWnd, PTTYINFO pTTYInfo, LOGFONT *newFont)
 
1802
{
 
1803
    HDC                 hDC;
 
1804
    HFONT               hFont;
 
1805
    TEXTMETRIC          tm;
 
1806
    int                 newNRow;
 
1807
    int                 newNColumn;
 
1808
    BOOL                newsize;
 
1809
 
 
1810
 
 
1811
#ifdef SDEBUG
 
1812
    if (mswin_debug >= 5)
 
1813
        fprintf (mswin_debugfile, "ResetTTYFont:::  entered, curent window size X %d, Y %d\n",
 
1814
                pTTYInfo->xSize, pTTYInfo->ySize);
 
1815
#endif
 
1816
 
 
1817
 
 
1818
    if (NULL == pTTYInfo)
 
1819
            return (FALSE);
 
1820
 
 
1821
    SelClear ();
 
1822
 
 
1823
    /*
 
1824
     * Create new font.
 
1825
     */
 
1826
    hFont = CreateFontIndirect (newFont);
 
1827
    if (hFont == NULL)
 
1828
            return (FALSE);
 
1829
    hDC = GetDC (hWnd);
 
1830
    SelectObject (hDC, hFont);
 
1831
    GetTextMetrics (hDC, &tm);
 
1832
    ReleaseDC (hWnd, hDC);
 
1833
 
 
1834
 
 
1835
    /*
 
1836
     * Replace old font.
 
1837
     */
 
1838
    if (NULL != pTTYInfo->hTTYFont)
 
1839
            DeleteObject (pTTYInfo->hTTYFont);
 
1840
    pTTYInfo->hTTYFont = hFont;
 
1841
    memcpy (&pTTYInfo->lfTTYFont, newFont, sizeof (LOGFONT));
 
1842
 
 
1843
 
 
1844
    /* Update the char cell size. */
 
1845
    pTTYInfo->xChar = (CORD)tm.tmAveCharWidth;
 
1846
    pTTYInfo->yChar = (CORD)(tm.tmHeight + tm.tmExternalLeading);
 
1847
 
 
1848
    /* Update the current number of rows and cols.  Don't allow
 
1849
     * either to be less than zero. */
 
1850
    newNRow = MAX (MINNROW,
 
1851
            MIN (MAXNROW,
 
1852
                (pTTYInfo->ySize - pTTYInfo->toolBarSize - (2 * MARGINE_TOP))/
 
1853
                                pTTYInfo->yChar));
 
1854
    newNColumn = MAX (MINNCOLUMN,
 
1855
            MIN (MAXNCOLUMN, (pTTYInfo->xSize - (2 * pTTYInfo->xOffset))/
 
1856
                                    pTTYInfo->xChar));
 
1857
 
 
1858
    newsize = newNRow != pTTYInfo->actNRow ||
 
1859
                    newNColumn != pTTYInfo->actNColumn;
 
1860
    if (newsize)
 
1861
            ResizeTTYScreen (hWnd, pTTYInfo, newNRow, newNColumn);
 
1862
 
 
1863
    /* Resize the caret as well. */
 
1864
    if(pTTYInfo->fCaretOn)
 
1865
      HideCaret (hWnd);
 
1866
 
 
1867
    DestroyCaret ();
 
1868
    CaretCreateTTY (hWnd);
 
1869
 
 
1870
    /* Redraw screen and, if the "size" changed, tell the upper layers. */
 
1871
    pTTYInfo->screenDirty = TRUE;
 
1872
    pTTYInfo->eraseScreen = TRUE;
 
1873
    InvalidateRect (hWnd, NULL, FALSE);
 
1874
 
 
1875
    /* Always call the resize functions - even if the screen size
 
1876
     * has not changed, the font style may have. */
 
1877
    DidResize (pTTYInfo);
 
1878
 
 
1879
    return (TRUE);
 
1880
}
 
1881
 
 
1882
 
 
1883
/*---------------------------------------------------------------------------
 
1884
 *  BOOL  EraseTTY (HWND hWnd, HDC hDC)
 
1885
 *
 
1886
 *  Description:
 
1887
 *     Erase the tty background.
 
1888
 *
 
1889
 *
 
1890
 *  Parameters:
 
1891
 *     HWND hWnd
 
1892
 *        handle to TTY window (as always)
 
1893
 *
 
1894
/*--------------------------------------------------------------------------*/
 
1895
LOCAL BOOL
 
1896
EraseTTY (HWND hWnd, HDC hDC)
 
1897
{
 
1898
    RECT        erect;
 
1899
    HBRUSH      hBrush;
 
1900
 
 
1901
 
 
1902
    GetClientRect (hWnd, &erect);
 
1903
    hBrush = CreateSolidBrush (gpTTYInfo->rgbBGColor);
 
1904
    if (hBrush != NULL) {
 
1905
        FillRect (hDC, &erect, hBrush);
 
1906
        DeleteObject (hBrush);
 
1907
    }
 
1908
    return (TRUE);
 
1909
}
 
1910
 
 
1911
 
 
1912
/*---------------------------------------------------------------------------
 
1913
 *  BOOL  PaintTTY( HWND hWnd )
 
1914
 *
 
1915
 *  Description:
 
1916
 *     Paints the rectangle determined by the paint struct of
 
1917
 *     the DC.
 
1918
 *
 
1919
 *  Parameters:
 
1920
 *     HWND hWnd
 
1921
 *        handle to TTY window (as always)
 
1922
 *
 
1923
/*--------------------------------------------------------------------------*/
 
1924
LOCAL BOOL
 
1925
PaintTTY (HWND hWnd)
 
1926
{
 
1927
    int          nRow, nCol;            /* Top left corner of update. */
 
1928
    int          nEndRow, nEndCol;      /* lower right corner of update. */
 
1929
    int          nHorzPos, nVertPos;    /* Position of each text write. */
 
1930
    int          col;                   /* start col of run of similar attr */
 
1931
    int          count;                 /* count of run of similar attrib. */
 
1932
    int          endCount;              /* How far to count. */
 
1933
    CharAttrib  *pAttrib;
 
1934
    HDC          hDC;
 
1935
    LOGFONT      tmpFont;
 
1936
    HFONT        hOrigFont, hOldFont = NULL, hTmpFont;
 
1937
    PTTYINFO    pTTYInfo;
 
1938
    PAINTSTRUCT  ps;
 
1939
    RECT         rect;
 
1940
    RECT         erect;
 
1941
    HBRUSH       hBrush;
 
1942
    long         offset;                /* Offset into pScreen array */
 
1943
    long         endoffset;             /* Offset of nEndCol in each row array */
 
1944
    CharAttrib  *pLastAttrib;           /* Attributes of last text write. */
 
1945
    CharAttrib  *pNewAttrib;            /* Attributes of this text write. */
 
1946
 
 
1947
 
 
1948
#ifdef CDEBUG
 
1949
    if (mswin_debug >= 9)
 
1950
        fprintf (mswin_debugfile, "PaintTTY:::  entered\n");
 
1951
#endif
 
1952
 
 
1953
 
 
1954
    pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
 
1955
    if (pTTYInfo == NULL)
 
1956
        return (FALSE);
 
1957
 
 
1958
    if (IsIconic (hWnd))
 
1959
      return (TRUE);
 
1960
 
 
1961
    hDC = BeginPaint (hWnd, &ps);
 
1962
    rect = ps.rcPaint;
 
1963
 
 
1964
    hOrigFont = SelectObject (hDC, pTTYInfo->hTTYFont);
 
1965
    SetTextColor (hDC, pTTYInfo->rgbFGColor);
 
1966
    SetBkColor (hDC, pTTYInfo->rgbBGColor);
 
1967
    SetBkMode (hDC, OPAQUE);
 
1968
 
 
1969
    nRow = (rect.top - pTTYInfo->yOffset) / pTTYInfo->yChar;
 
1970
    CONSTRAIN (nRow, 0, pTTYInfo->actNRow - 1);
 
1971
 
 
1972
    nEndRow = MIN(pTTYInfo->actNRow - 1,
 
1973
            ((rect.bottom - pTTYInfo->yOffset - 1) / pTTYInfo->yChar));
 
1974
    nCol = MIN(pTTYInfo->actNColumn - 1,
 
1975
            MAX(0, (rect.left - pTTYInfo->xOffset) / pTTYInfo->xChar));
 
1976
    nEndCol = MIN(pTTYInfo->actNColumn - 1,
 
1977
            ((rect.right - pTTYInfo->xOffset - 1) / pTTYInfo->xChar));
 
1978
 
 
1979
    pLastAttrib = NULL;
 
1980
 
 
1981
    /* Erase screen if necessary. */
 
1982
    if (pTTYInfo->eraseScreen) {
 
1983
        erect.top = 0;
 
1984
        erect.left = 0;
 
1985
        erect.bottom = pTTYInfo->ySize;
 
1986
        erect.right = pTTYInfo->xSize;
 
1987
        hBrush = CreateSolidBrush (pTTYInfo->rgbBGColor);
 
1988
        if (hBrush != NULL) {
 
1989
            FillRect (hDC, &erect, hBrush);
 
1990
            DeleteObject (hBrush);
 
1991
        }
 
1992
        pTTYInfo->eraseScreen = FALSE;
 
1993
    }
 
1994
 
 
1995
 
 
1996
    /* Paint an inset frame around the text region. */
 
1997
    if (pTTYInfo->toolBarSize == 0) {
 
1998
        erect.top = 0;
 
1999
        erect.bottom = pTTYInfo->ySize;
 
2000
    }
 
2001
    else if (pTTYInfo->toolBarTop) {
 
2002
        erect.top = pTTYInfo->toolBarSize;
 
2003
        erect.bottom = pTTYInfo->ySize;
 
2004
    }
 
2005
    else {
 
2006
        erect.top = 0;
 
2007
        erect.bottom = pTTYInfo->ySize - pTTYInfo->toolBarSize;
 
2008
    }
 
2009
    erect.left = 0;
 
2010
    erect.right = pTTYInfo->xSize;
 
2011
    FrameRect3D (hDC, &erect, FRAME_3D_SIZE, FALSE);
 
2012
 
 
2013
    /* Paint rows of text. */
 
2014
    for (; nRow <= nEndRow; nRow++)    {
 
2015
        nVertPos = (nRow * pTTYInfo->yChar) + pTTYInfo->yOffset;
 
2016
        rect.top = nVertPos;
 
2017
        rect.bottom = nVertPos + pTTYInfo->yChar;
 
2018
        
 
2019
        /* Paint runs of similar attributes. */
 
2020
        col = nCol;                             /* Start at left. */
 
2021
 
 
2022
        if(col == 0 && MSWIconPaint(nRow, hDC))
 
2023
          col += 2;
 
2024
 
 
2025
        /*
 
2026
         * col is the column on the screen, not the index
 
2027
         * into the array.
 
2028
         */
 
2029
        while (col <= nEndCol) {                /* While not past right. */
 
2030
 
 
2031
            /* Starting with Character at nRow, col, what is its attribute? */
 
2032
 
 
2033
            /* offset is an index into the array */
 
2034
            offset = pscreen_offset_from_cord(nRow, col, pTTYInfo);
 
2035
            pNewAttrib = pTTYInfo->pAttrib + offset;
 
2036
 
 
2037
            hTmpFont = NULL;
 
2038
            if (!(pLastAttrib
 
2039
                  && pNewAttrib->style == pLastAttrib->style
 
2040
                  && pNewAttrib->rgbFG == pLastAttrib->rgbFG
 
2041
                  && pNewAttrib->rgbBG == pLastAttrib->rgbBG)) {
 
2042
                /*
 
2043
                 * Require new font?
 
2044
                 */
 
2045
                if(!pLastAttrib
 
2046
                   || (pNewAttrib->style & CHAR_ATTR_ULINE)
 
2047
                                 != (pLastAttrib->style & CHAR_ATTR_ULINE)){
 
2048
                    if(pNewAttrib->style & CHAR_ATTR_ULINE){
 
2049
                        /*
 
2050
                         * Find suitable attribute font...
 
2051
                         */
 
2052
                        memcpy (&tmpFont, &pTTYInfo->lfTTYFont,
 
2053
                                sizeof (LOGFONT));
 
2054
 
 
2055
                        tmpFont.lfHeight = - pTTYInfo->yChar;
 
2056
                        tmpFont.lfWidth  = - pTTYInfo->xChar;
 
2057
 
 
2058
                        tmpFont.lfUnderline = (BYTE)((pNewAttrib->style
 
2059
                                                            & CHAR_ATTR_ULINE)
 
2060
                                                            == CHAR_ATTR_ULINE);
 
2061
 
 
2062
                        hTmpFont = CreateFontIndirect (&tmpFont);
 
2063
 
 
2064
                        hOldFont = SelectObject (hDC, hTmpFont);
 
2065
                    }
 
2066
                }
 
2067
 
 
2068
                /*
 
2069
                 * Set new color attributes.  If Reverse or Selected, then
 
2070
                 * show in reverse colors.  But if neither, or both, then
 
2071
                 * normal colors.
 
2072
                 */
 
2073
                if(pNewAttrib->style & CHAR_ATTR_SEL){
 
2074
                    SetTextColor (hDC, pNewAttrib->rgbBG);
 
2075
                    SetBkColor (hDC, pNewAttrib->rgbFG);
 
2076
                }
 
2077
                else {
 
2078
                    if(!(pLastAttrib
 
2079
                         && pNewAttrib->rgbFG == pLastAttrib->rgbFG)
 
2080
                       || (pLastAttrib->style & CHAR_ATTR_SEL))
 
2081
                      SetTextColor (hDC, pNewAttrib->rgbFG);
 
2082
 
 
2083
                    if(!(pLastAttrib
 
2084
                         && pNewAttrib->rgbBG == pLastAttrib->rgbBG)
 
2085
                       || (pLastAttrib->style & CHAR_ATTR_SEL))
 
2086
                      SetBkColor (hDC, pNewAttrib->rgbBG);
 
2087
                }
 
2088
            }
 
2089
        
 
2090
            /* Find run of similar attributes. */
 
2091
            count = 1;
 
2092
            pAttrib = pTTYInfo->pAttrib + (offset + 1);
 
2093
            /* endoffset is an index into the pScreen array */
 
2094
            endoffset = pscreen_offset_from_cord(nRow, nEndCol, pTTYInfo);
 
2095
            endCount = endoffset - offset;
 
2096
            while (count <= endCount
 
2097
                   && pAttrib->style == pNewAttrib->style
 
2098
                   && pAttrib->rgbFG == pNewAttrib->rgbFG
 
2099
                   && pAttrib->rgbBG == pNewAttrib->rgbBG){
 
2100
                ++pAttrib;
 
2101
                ++count;
 
2102
            }
 
2103
 
 
2104
            if(hTmpFont != NULL){
 
2105
/* BUG: compute new offsets based on hTmpFont font if required */
 
2106
                nHorzPos = (col * pTTYInfo->xChar) + pTTYInfo->xOffset;
 
2107
                rect.left = nHorzPos;
 
2108
                rect.right = nHorzPos + pTTYInfo->xChar * scrwidth(pTTYInfo->pScreen+offset, count);
 
2109
            }
 
2110
            else{
 
2111
                /* Paint run of characters from nRow, col to nRow, col + count
 
2112
                 * rect.top and rect.bottom have already been calculated. */
 
2113
                nHorzPos = (col * pTTYInfo->xChar) + pTTYInfo->xOffset;
 
2114
                rect.left = nHorzPos;
 
2115
                rect.right = nHorzPos + pTTYInfo->xChar * scrwidth(pTTYInfo->pScreen+offset, count);
 
2116
            }
 
2117
 
 
2118
            ExtTextOut (hDC, nHorzPos, nVertPos, ETO_OPAQUE | ETO_CLIPPED,
 
2119
                        &rect, (LPTSTR) (pTTYInfo->pScreen + offset),
 
2120
                        count, (int *)(pTTYInfo->pCellWidth+offset));
 
2121
 
 
2122
            /* Overstrike bold chars by hand to preserve char cell size */
 
2123
            if(pNewAttrib->style & CHAR_ATTR_BOLD){
 
2124
                int old_mode = GetBkMode(hDC);
 
2125
                SetBkMode (hDC, TRANSPARENT);
 
2126
                ExtTextOut (hDC, nHorzPos + 1, nVertPos, 0,
 
2127
                            &rect, (LPTSTR) (pTTYInfo->pScreen + offset),
 
2128
                            count, (int *)(pTTYInfo->pCellWidth+offset));
 
2129
                if(old_mode)
 
2130
                  SetBkMode (hDC, old_mode);
 
2131
            }
 
2132
 
 
2133
            /* Move pointer to end of this span of characters. */
 
2134
            col += scrwidth(pTTYInfo->pScreen+offset, count);
 
2135
            pLastAttrib = pNewAttrib;
 
2136
 
 
2137
            if(hTmpFont != NULL){
 
2138
                SelectObject(hDC, hOldFont);
 
2139
                DeleteObject(hTmpFont);
 
2140
            }
 
2141
        }
 
2142
    }
 
2143
 
 
2144
    SelectObject (hDC, hOrigFont);
 
2145
    EndPaint (hWnd, &ps);
 
2146
    MoveTTYCursor (hWnd);
 
2147
    pTTYInfo->screenDirty = FALSE;
 
2148
    return (TRUE);
 
2149
}
 
2150
 
 
2151
 
 
2152
/* FillRectColor
 
2153
 *
 
2154
 *
 
2155
 * Description:
 
2156
 *              FillRectColor is similar to PatB in toolbar.c
 
2157
 *
 
2158
 *              Code based on MFC source code, so presumably efficient.
 
2159
 *
 
2160
 */
 
2161
LOCAL void
 
2162
FillRectColor(HDC hDC, RECT * pRC, COLORREF color)
 
2163
{
 
2164
    SetBkColor(hDC, color);
 
2165
    ExtTextOut(hDC, 0, 0, ETO_OPAQUE, pRC, NULL, 0, NULL);
 
2166
}
 
2167
 
 
2168
 
 
2169
/** FrameRect3D
 
2170
 *
 
2171
 *
 
2172
 * Inputs:
 
2173
 *              hdc                     - HDC
 
2174
 *              pRC                     - pointer to rectangle
 
2175
 *              width           - width for frame (usually one)
 
2176
 *              raised          - TRUE for raised effect, FALSE for sunken effect
 
2177
 *
 
2178
 * Outputs:
 
2179
 *              none
 
2180
 *
 
2181
 * Returns:
 
2182
 *              void
 
2183
 *
 
2184
 * Description
 
2185
 *              Draws a frame with a 3D effect.
 
2186
 *
 
2187
 *              If 'raised' is true, the rectangle will look raised (like
 
2188
 *              a button); otherwise, the rectangle will look sunk.
 
2189
 *
 
2190
 */
 
2191
void
 
2192
FrameRect3D(HDC hdc, RECT * pRC, int width, BOOL raised)
 
2193
{
 
2194
    COLORREF    hilite, shadow;
 
2195
    RECT                rcTemp;
 
2196
 
 
2197
    shadow              = GetSysColor(COLOR_BTNSHADOW);
 
2198
    hilite              = GetSysColor(COLOR_BTNHIGHLIGHT);
 
2199
 
 
2200
    rcTemp              = *pRC;
 
2201
 
 
2202
    rcTemp.right        = rcTemp.left + width;
 
2203
    FillRectColor(hdc, &rcTemp, raised ? hilite : shadow);
 
2204
    rcTemp.right        = pRC->right;
 
2205
 
 
2206
    rcTemp.bottom       = rcTemp.top + width;
 
2207
    FillRectColor(hdc, &rcTemp, raised ? hilite : shadow);
 
2208
    rcTemp.bottom       = pRC->bottom;
 
2209
 
 
2210
    rcTemp.left         = rcTemp.right - width;
 
2211
    FillRectColor(hdc, &rcTemp, raised ? shadow : hilite);
 
2212
    rcTemp.left         = pRC->left;
 
2213
 
 
2214
    rcTemp.top          = rcTemp.bottom - width;
 
2215
    FillRectColor(hdc, &rcTemp, raised ? shadow : hilite);
 
2216
}
 
2217
 
 
2218
 
 
2219
/*---------------------------------------------------------------------------
 
2220
 *  BOOL  GetMinMaxInfoTTY (HWND hWnd, (MINMAXINFO __far *)lParam)
 
2221
 *
 
2222
 *  Description:
 
2223
 *     Return the min and max size that the window can be.
 
2224
 *
 
2225
 *  Parameters:
 
2226
 *     HWND hWnd
 
2227
 *        handle to TTY window
 
2228
 *
 
2229
 *     MINMAXINFO
 
2230
 *        Info structure that Windows would like us to fill.
 
2231
 *
 
2232
/*--------------------------------------------------------------------------*/
 
2233
LOCAL BOOL
 
2234
GetMinMaxInfoTTY (HWND hWnd, MINMAXINFO __far *lpmmi)
 
2235
{
 
2236
    PTTYINFO            pTTYInfo;
 
2237
 
 
2238
 
 
2239
#ifdef SDEBUG
 
2240
    if (mswin_debug >= 5)
 
2241
        fprintf (mswin_debugfile, "GetMinMaxInfoTTY:::  entered\n");
 
2242
#endif
 
2243
 
 
2244
 
 
2245
    pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
 
2246
    if (pTTYInfo == NULL)
 
2247
        return (FALSE);
 
2248
 
 
2249
    lpmmi->ptMaxTrackSize.x = lpmmi->ptMaxSize.x = MIN (lpmmi->ptMaxSize.x,
 
2250
                            pTTYInfo->xChar * MAXNCOLUMN + WIN_X_BORDER_SIZE);
 
2251
    lpmmi->ptMaxTrackSize.y = lpmmi->ptMaxSize.y = MIN (lpmmi->ptMaxSize.y,
 
2252
                            pTTYInfo->yChar * MAXNROW + WIN_Y_BORDER_SIZE);
 
2253
 
 
2254
    lpmmi->ptMinTrackSize.x = MAX (WIN_MIN_X_SIZE,
 
2255
                    pTTYInfo->xChar * MINNCOLUMN + WIN_X_BORDER_SIZE);
 
2256
    lpmmi->ptMinTrackSize.y = MAX (WIN_MIN_Y_SIZE,
 
2257
                    pTTYInfo->yChar * MINNROW + WIN_Y_BORDER_SIZE);
 
2258
    return (TRUE);
 
2259
}
 
2260
 
 
2261
 
 
2262
/*---------------------------------------------------------------------------
 
2263
 *  BOOL  AboutToSizeTTY (HWND hWnd, WINDOWPOS *winPos)
 
2264
 *
 
2265
 *  Description:
 
2266
 *      Called just before Windows resizes our window.  We can change the
 
2267
 *      values in 'winPos' to change the new size of the window.
 
2268
 *
 
2269
 *      If mswin_setwindow() was called when the window was minimized we
 
2270
 *      set the new size here.
 
2271
 *
 
2272
 *  Parameters:
 
2273
 *     HWND hWnd
 
2274
 *        handle to TTY window
 
2275
 *
 
2276
 *     WORD wVertSize
 
2277
 *        new vertical size
 
2278
 *
 
2279
 *     WORD wHorzSize
 
2280
 *        new horizontal size
 
2281
 *
 
2282
/*--------------------------------------------------------------------------*/
 
2283
LOCAL BOOL
 
2284
AboutToSizeTTY (HWND hWnd, WINDOWPOS *winPos)
 
2285
{
 
2286
    PTTYINFO    pTTYInfo;
 
2287
 
 
2288
 
 
2289
    pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
 
2290
    if (pTTYInfo == NULL)
 
2291
            return ( FALSE );
 
2292
 
 
2293
#ifdef SDEBUG
 
2294
    if (mswin_debug >= 5)
 
2295
        fprintf (mswin_debugfile, "AboutToSizeTTY:::  After x%lx, pos %d, %d, size %d, %d, flags x%x\n",
 
2296
            winPos->hwndInsertAfter, winPos->x, winPos->y, winPos->cx,
 
2297
            winPos->cy, winPos->flags);
 
2298
 
 
2299
#endif
 
2300
 
 
2301
    /*
 
2302
     * Was the window minimized AND is there a desired new size for it?
 
2303
     * AND is this a call that specifies a new size and position.
 
2304
     */
 
2305
    if (pTTYInfo->fMinimized && pTTYInfo->fDesiredSize &&
 
2306
            (winPos->flags & (SWP_NOSIZE | SWP_NOMOVE)) == 0) {
 
2307
#ifdef SDEBUG
 
2308
        if (mswin_debug >= 5)
 
2309
            fprintf (mswin_debugfile, "AboutToSizeTTY:::  substitue pos (%d, %d), size (%d, %d)\n",
 
2310
                    pTTYInfo->xDesPos, pTTYInfo->yDesPos,
 
2311
                    pTTYInfo->xDesSize, pTTYInfo->yDesSize);
 
2312
#endif
 
2313
        pTTYInfo->fDesiredSize = FALSE;
 
2314
        winPos->x = pTTYInfo->xDesPos;
 
2315
        winPos->y = pTTYInfo->yDesPos;
 
2316
        winPos->cx = pTTYInfo->xDesSize;
 
2317
        winPos->cy = pTTYInfo->yDesSize;
 
2318
    }
 
2319
    return (TRUE);
 
2320
}
 
2321
 
 
2322
 
 
2323
/*---------------------------------------------------------------------------
 
2324
 *  BOOL  SizeTTY( HWND hWnd, int fwSizeType, CORD wVertSize,
 
2325
 *                                      CORD wHorzSize)
 
2326
 *
 
2327
 *  Description:
 
2328
 *     Sizes TTY and sets up scrolling regions.
 
2329
 *
 
2330
 *  Parameters:
 
2331
 *     HWND hWnd
 
2332
 *        handle to TTY window
 
2333
 *
 
2334
 *     WORD wVertSize
 
2335
 *        new vertical size
 
2336
 *
 
2337
 *     WORD wHorzSize
 
2338
 *        new horizontal size
 
2339
 *
 
2340
/*--------------------------------------------------------------------------*/
 
2341
LOCAL BOOL
 
2342
SizeTTY (HWND hWnd, int fwSizeType, CORD wVertSize, CORD wHorzSize)
 
2343
{
 
2344
    PTTYINFO    pTTYInfo;
 
2345
    int         newNColumn;
 
2346
    int         newNRow;
 
2347
 
 
2348
 
 
2349
#ifdef SDEBUG
 
2350
    if (mswin_debug >= 5)
 
2351
        fprintf (mswin_debugfile, "SizeTTY:::  entered, sizeType %d, New screen size %d, %d pixels\n",
 
2352
                fwSizeType, wHorzSize, wVertSize);
 
2353
#endif
 
2354
 
 
2355
    pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
 
2356
    if (pTTYInfo == NULL)
 
2357
            return ( FALSE );
 
2358
 
 
2359
 
 
2360
    /*
 
2361
     * Is the window being minimized?
 
2362
     */
 
2363
    if (fwSizeType == SIZE_MINIMIZED) {
 
2364
        pTTYInfo->fMinimized = TRUE;
 
2365
        return (TRUE);
 
2366
    }
 
2367
 
 
2368
 
 
2369
 
 
2370
    pTTYInfo->fMinimized = FALSE;
 
2371
        
 
2372
        
 
2373
    pTTYInfo->ySize = (CORD) wVertSize;
 
2374
    newNRow = MAX(MINNROW, MIN(MAXNROW,
 
2375
            (pTTYInfo->ySize - pTTYInfo->toolBarSize - (2 * MARGINE_TOP)) /
 
2376
                                    pTTYInfo->yChar));
 
2377
    if (pTTYInfo->toolBarTop)           
 
2378
        pTTYInfo->yOffset = MARGINE_TOP + pTTYInfo->toolBarSize;
 
2379
    else
 
2380
        pTTYInfo->yOffset = MARGINE_TOP;
 
2381
        
 
2382
 
 
2383
    pTTYInfo->xSize = (CORD) wHorzSize;
 
2384
    newNColumn = MAX(MINNCOLUMN,
 
2385
                    MIN(MAXNCOLUMN, (pTTYInfo->xSize - (2 * MARGINE_LEFT)) /
 
2386
                    pTTYInfo->xChar));
 
2387
    pTTYInfo->xOffset = MARGINE_LEFT;
 
2388
 
 
2389
    if(newNRow == pTTYInfo->actNRow && newNColumn == pTTYInfo->actNColumn)
 
2390
      return(FALSE);
 
2391
 
 
2392
    ResizeTTYScreen (hWnd, pTTYInfo, newNRow, newNColumn);
 
2393
    pTTYInfo->screenDirty = TRUE;
 
2394
    pTTYInfo->eraseScreen = TRUE;
 
2395
    InvalidateRect (hWnd, NULL, FALSE);
 
2396
 
 
2397
    if (pTTYInfo->hTBWnd) {
 
2398
        if (pTTYInfo->toolBarTop)
 
2399
            /* Position at top of window. */
 
2400
            SetWindowPos (pTTYInfo->hTBWnd, HWND_TOP,
 
2401
                    0, 0,
 
2402
                    wHorzSize, pTTYInfo->toolBarSize,
 
2403
                    SWP_NOZORDER | SWP_NOACTIVATE | SWP_SHOWWINDOW);
 
2404
        else
 
2405
            /* Position at bottom of window. */
 
2406
            SetWindowPos (pTTYInfo->hTBWnd, HWND_TOP,
 
2407
                    0, pTTYInfo->ySize - pTTYInfo->toolBarSize,
 
2408
                    wHorzSize, pTTYInfo->toolBarSize,
 
2409
                    SWP_NOZORDER | SWP_NOACTIVATE | SWP_SHOWWINDOW);
 
2410
    }
 
2411
 
 
2412
 
 
2413
    DidResize (pTTYInfo);
 
2414
 
 
2415
    return (TRUE);
 
2416
}
 
2417
 
 
2418
 
 
2419
/*---------------------------------------------------------------------------
 
2420
 *  BOOL  SizingTTY( HWND hWnd, int fwSide, LPRECT pRect)
 
2421
 *
 
2422
 *  Description:
 
2423
 *     Snaps the drag rectangle to char width/height boundaries
 
2424
 *
 
2425
 *  Parameters:
 
2426
 *     HWND hWnd
 
2427
 *        handle to TTY window
 
2428
 *
 
2429
 *     WORD fwSide
 
2430
 *        edge of window being sized
 
2431
 *
 
2432
 *     LPRECT
 
2433
 *        screen coords of drag rectangle in and desired size on return
 
2434
 *
 
2435
/*--------------------------------------------------------------------------*/
 
2436
LOCAL BOOL
 
2437
SizingTTY (HWND hWnd, int fwSide, LPRECT pRect)
 
2438
{
 
2439
    PTTYINFO pTTYInfo;
 
2440
    int      newNRow, newNCol, xClient, yClient,
 
2441
             xSys, ySys, xDiff, yDiff;
 
2442
 
 
2443
    pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
 
2444
    if (pTTYInfo == NULL)
 
2445
        return (FALSE);
 
2446
 
 
2447
    xSys  = (2 * GetSystemMetrics(SM_CXSIZEFRAME))
 
2448
                                              + GetSystemMetrics(SM_CXVSCROLL);
 
2449
    ySys  = (2 * GetSystemMetrics(SM_CYSIZEFRAME))
 
2450
                                              + GetSystemMetrics(SM_CYCAPTION)
 
2451
                                              + GetSystemMetrics(SM_CYMENU);
 
2452
 
 
2453
    newNCol = (((pRect->right - pRect->left) - xSys)
 
2454
                                       - (2 * MARGINE_LEFT)) / pTTYInfo->xChar;
 
2455
    newNRow = (((pRect->bottom - pRect->top) - ySys) - (2 * MARGINE_TOP)
 
2456
                                   - pTTYInfo->toolBarSize) / pTTYInfo->yChar;
 
2457
 
 
2458
    xClient = (newNCol * pTTYInfo->xChar) + (2 * MARGINE_LEFT);
 
2459
    yClient = (newNRow * pTTYInfo->yChar) + (2 * MARGINE_TOP)
 
2460
                                                      + pTTYInfo->toolBarSize;
 
2461
 
 
2462
    xDiff  = (pRect->left + xClient + xSys) - pRect->right;
 
2463
    yDiff = (pRect->top + yClient + ySys) - pRect->bottom;
 
2464
 
 
2465
    if(!(xDiff || yDiff))
 
2466
      return(FALSE);
 
2467
 
 
2468
    switch(fwSide){
 
2469
      case WMSZ_BOTTOM :        /* Bottom edge */
 
2470
        pRect->bottom += yDiff;
 
2471
        break;
 
2472
 
 
2473
      case WMSZ_BOTTOMLEFT :    /*Bottom-left corner */
 
2474
        pRect->bottom += yDiff;
 
2475
        pRect->left -= xDiff;
 
2476
        break;
 
2477
 
 
2478
      case WMSZ_BOTTOMRIGHT :   /* Bottom-right corner */
 
2479
        pRect->bottom += yDiff;
 
2480
        pRect->right += xDiff;
 
2481
        break;
 
2482
 
 
2483
      case WMSZ_LEFT :          /* Left edge */
 
2484
        pRect->left -= xDiff;
 
2485
        break;
 
2486
 
 
2487
      case WMSZ_RIGHT :         /* Right edge */
 
2488
        pRect->right += xDiff;
 
2489
        break;
 
2490
 
 
2491
      case WMSZ_TOP :           /* Top edge */
 
2492
        pRect->top -= yDiff;
 
2493
        break;
 
2494
        
 
2495
      case WMSZ_TOPLEFT :       /* Top-left corner */
 
2496
        pRect->top -= yDiff;
 
2497
        pRect->left -= xDiff;
 
2498
        break;
 
2499
 
 
2500
      case WMSZ_TOPRIGHT :      /* Top-right corner */
 
2501
        pRect->top -= yDiff;
 
2502
        pRect->right += xDiff;
 
2503
        break;
 
2504
 
 
2505
      default :
 
2506
        break;
 
2507
    }
 
2508
 
 
2509
    if(!(newNRow == pTTYInfo->actNRow && newNCol == pTTYInfo->actNColumn))
 
2510
      SizeTTY(hWnd, SIZE_RESTORED, (CORD) yClient, (CORD) xClient);
 
2511
 
 
2512
    return(TRUE);
 
2513
}
 
2514
 
 
2515
 
 
2516
/*---------------------------------------------------------------------------
 
2517
 *  BOOL  MoveTTY (HWND hWnd, int xPos, int yPos)
 
2518
 *
 
2519
 *  Description:
 
2520
 *     Notes the fact that the window has moved.
 
2521
 *     Only real purpose is so we can tell pine which can the write the
 
2522
 *     new window position to the 'pinerc' file.
 
2523
 *
 
2524
 *  Parameters:
 
2525
 *     HWND hWnd
 
2526
 *        handle to TTY window
 
2527
 *
 
2528
 *     int xPos, yPos
 
2529
 *        New position of the top left corner.
 
2530
 *
 
2531
 *
 
2532
/*--------------------------------------------------------------------------*/
 
2533
LOCAL BOOL
 
2534
MoveTTY (HWND hWnd, int xPos, int yPos)
 
2535
{
 
2536
#ifdef SDEBUG
 
2537
    if (mswin_debug >= 5)
 
2538
        fprintf (mswin_debugfile, "MoveTTY:::  entered\n");
 
2539
#endif
 
2540
 
 
2541
    DidResize (gpTTYInfo);
 
2542
    return (TRUE);
 
2543
}
 
2544
 
 
2545
 
 
2546
/*---------------------------------------------------------------------------
 
2547
 *  void  ScrollTTY ()
 
2548
 *
 
2549
 *  Description:
 
2550
 *      Respond to a scroll message by either calling the scroll
 
2551
 *      callback or inserting a scroll character into the input
 
2552
 *      stream.
 
2553
 *
 
2554
 *      Scrolling in the TTY window is complicated by the way pine
 
2555
 *      process events.  Normal windows applications are entirly event
 
2556
 *      driven.  The top level does nothing but dispatch events.  In
 
2557
 *      pine, the top level implements the logic.  Events are only
 
2558
 *      dispatched by the lowest levels.
 
2559
 *
 
2560
 *      In normal applications, mouse down in the scroll bar causes
 
2561
 *      an internal scroll function to be entered.  It tracks the
 
2562
 *      mouse and issues scroll messages as needed.  If the
 
2563
 *      application redraws the screen the scroll function also
 
2564
 *      dispatches the WM_PAINT message to the application.  The
 
2565
 *      important thing is that this internal scroll function does
 
2566
 *      not exit until the mouse is released.
 
2567
 *
 
2568
 *      We implement two methods for pine's screen managers to deal
 
2569
 *      with scroll events.  They can receive scroll events as
 
2570
 *      characters in the normal input stream or they can register a
 
2571
 *      callback function.
 
2572
 *
 
2573
 *      In the "insert a character in the queue" mode, the scroll
 
2574
 *      event never gets process until the mouse is release.  Auto
 
2575
 *      repeat scroll events (generated as the mouse is held down)
 
2576
 *      will cause multiple chars to be inserted in the queue, none
 
2577
 *      of which will get processed till the mouse is release.  In a
 
2578
 *      compromise, we allow only one scroll char in the queue,
 
2579
 *      which prevents makes for a more friendly and controllable
 
2580
 *      behavior.
 
2581
 *
 
2582
 *      In the callback mode, the callback repaints the screen, and
 
2583
 *      then it calls mswin_flush() which PROCESSES EVENTS!  The
 
2584
 *      Windows internal scroll function does NOT expect that.  This
 
2585
 *      behavior can confuses the scroll function, causing it to
 
2586
 *      miss mouse up events.  We avoid this by setting gScrolling TRUE
 
2587
 *      when this routine is entered and FALSE when this routine exits
 
2588
 *      All PeekMessage processors avoid processing any message when
 
2589
 *      gScrolling is TRUE.
 
2590
 *
 
2591
/*--------------------------------------------------------------------------*/
 
2592
LOCAL void
 
2593
ScrollTTY (HWND hWnd, int wScrollCode, int nPos, HWND hScroll)
 
2594
{
 
2595
    PTTYINFO    pTTYInfo;
 
2596
    TCHAR       cmd = 0;
 
2597
    long        scroll_pos = 0;
 
2598
    BOOL        noAction = FALSE;
 
2599
    BOOL        didScroll;
 
2600
    FARPROC     prevBlockingProc;
 
2601
        
 
2602
 
 
2603
 
 
2604
    pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
 
2605
 
 
2606
    if (pTTYInfo == NULL || gScrolling)
 
2607
        return;
 
2608
 
 
2609
    gScrolling = TRUE;
 
2610
    if (gWSBlockingProc != NULL)
 
2611
        prevBlockingProc = WSASetBlockingHook (gWSBlockingProc);
 
2612
 
 
2613
 
 
2614
 
 
2615
 
 
2616
    switch (wScrollCode) {
 
2617
    case SB_BOTTOM:
 
2618
        cmd = MSWIN_KEY_SCROLLTO;
 
2619
        scroll_pos = pTTYInfo->scrollTo = 0;
 
2620
        break;
 
2621
        
 
2622
    case SB_TOP:
 
2623
        cmd = MSWIN_KEY_SCROLLTO;
 
2624
        scroll_pos = pTTYInfo->scrollTo = pTTYInfo->scrollRange;
 
2625
        break;
 
2626
        
 
2627
    case SB_LINEDOWN:
 
2628
        cmd = MSWIN_KEY_SCROLLDOWNLINE;
 
2629
        scroll_pos = 1;
 
2630
        break;
 
2631
 
 
2632
    case SB_LINEUP:
 
2633
        cmd = MSWIN_KEY_SCROLLUPLINE;
 
2634
        scroll_pos = 1;
 
2635
        break;
 
2636
 
 
2637
    case SB_PAGEDOWN:
 
2638
        cmd = MSWIN_KEY_SCROLLDOWNPAGE;
 
2639
        scroll_pos = 1;
 
2640
        break;
 
2641
 
 
2642
    case SB_PAGEUP:
 
2643
        cmd = MSWIN_KEY_SCROLLUPPAGE;
 
2644
        scroll_pos = 1;
 
2645
        break;
 
2646
        
 
2647
    case SB_THUMBTRACK:
 
2648
    case SB_THUMBPOSITION:
 
2649
        cmd = MSWIN_KEY_SCROLLTO;
 
2650
        scroll_pos = pTTYInfo->scrollTo = (long) ((float)nPos);
 
2651
        break;
 
2652
 
 
2653
    default:
 
2654
        noAction = TRUE;
 
2655
        break;
 
2656
    }
 
2657
 
 
2658
 
 
2659
    /*
 
2660
     * If there is a scroll callback call that.  If there is no scroll
 
2661
     * callback or the callback says it did not handle the event (returned,
 
2662
     * FALSE) queue the scroll cmd.
 
2663
     */
 
2664
    if (!noAction) {
 
2665
        SelClear ();
 
2666
        didScroll = FALSE;
 
2667
        if (gScrollCallback != NULL) {
 
2668
            /* Call scrolling callback.  Set blocking hook to our routine
 
2669
             * which prevents messages from being dispatched. */
 
2670
            if (gWSBlockingProc != NULL)
 
2671
                WSASetBlockingHook (gWSBlockingProc);
 
2672
            didScroll = gScrollCallback (cmd, scroll_pos);
 
2673
            if (gWSBlockingProc != NULL)
 
2674
                WSAUnhookBlockingHook ();
 
2675
        }
 
2676
        /*
 
2677
         * If no callback or callback did not do the scrolling operation,
 
2678
         * insert a scroll cmd in the input stream.
 
2679
         */
 
2680
        if (!didScroll)
 
2681
          CQAddUniq ((UCS)cmd, 0);
 
2682
    }
 
2683
 
 
2684
 
 
2685
    gScrolling = FALSE;
 
2686
    return;
 
2687
}
 
2688
 
 
2689
 
 
2690
#ifdef  WIN32
 
2691
/*---------------------------------------------------------------------------
 
2692
 *  void  MouseWheelTTY ()
 
2693
 *
 
2694
 *  Description:
 
2695
 *      Respond to a WM_MOUSEWHEEL event by calling scroll callback
 
2696
 *      ala ScrollTTY.
 
2697
 *
 
2698
 *
 
2699
/*--------------------------------------------------------------------------*/
 
2700
LOCAL void
 
2701
MouseWheelTTY (HWND hWnd, int xPos, int yPos, int fwKeys, int zDelta)
 
2702
{
 
2703
    PTTYINFO    pTTYInfo;
 
2704
    WORD        cmd;
 
2705
    long        scroll_pos;
 
2706
    FARPROC     prevBlockingProc;
 
2707
    SCROLLINFO  scrollInfo;
 
2708
    static int  zDelta_accumulated;
 
2709
        
 
2710
    pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
 
2711
 
 
2712
    if (pTTYInfo == NULL || gScrolling)
 
2713
        return;
 
2714
 
 
2715
    scrollInfo.cbSize = sizeof(SCROLLINFO);
 
2716
    scrollInfo.fMask = SIF_POS | SIF_RANGE;
 
2717
    GetScrollInfo(hWnd, SB_VERT, &scrollInfo);
 
2718
    if((zDelta < 0 && scrollInfo.nPos < scrollInfo.nMin)
 
2719
       || (zDelta > 0 && scrollInfo.nPos >= scrollInfo.nMax))
 
2720
      return;
 
2721
 
 
2722
    gScrolling = TRUE;
 
2723
    if (gWSBlockingProc != NULL)
 
2724
        prevBlockingProc = WSASetBlockingHook (gWSBlockingProc);
 
2725
 
 
2726
    if(fwKeys == MK_MBUTTON)
 
2727
       zDelta *= 2;                     /* double the effect! */
 
2728
 
 
2729
    if(abs(zDelta += zDelta_accumulated) < WHEEL_DELTA){
 
2730
        zDelta_accumulated = zDelta;
 
2731
    }
 
2732
    else{
 
2733
        /* Remember any partial increments */
 
2734
        zDelta_accumulated = zDelta % WHEEL_DELTA;
 
2735
 
 
2736
        scroll_pos = (long)(gsMWMultiplier * abs((zDelta / WHEEL_DELTA)));
 
2737
 
 
2738
        cmd = (zDelta < 0) ? MSWIN_KEY_SCROLLDOWNLINE : MSWIN_KEY_SCROLLUPLINE;
 
2739
 
 
2740
        SelClear ();
 
2741
        if (gScrollCallback != NULL) {
 
2742
            /* Call scrolling callback.  Set blocking hook to our routine
 
2743
             * which prevents messages from being dispatched. */
 
2744
            if (gWSBlockingProc != NULL)
 
2745
              WSASetBlockingHook (gWSBlockingProc);
 
2746
            (void) gScrollCallback (cmd, scroll_pos);
 
2747
            if (gWSBlockingProc != NULL)
 
2748
              WSAUnhookBlockingHook ();
 
2749
        }
 
2750
    }
 
2751
 
 
2752
    gScrolling = FALSE;
 
2753
    return;
 
2754
}
 
2755
 
 
2756
 
 
2757
LOCAL void
 
2758
MouseWheelMultiplier()
 
2759
{
 
2760
    TCHAR lines[8];
 
2761
    DWORD llen = sizeof(lines)/sizeof(TCHAR);
 
2762
 
 
2763
    /* HKEY_CURRENT_USER\Control Panel\Desktop holds the key */
 
2764
    gsMWMultiplier = (MSWRPeek(HKEY_CURRENT_USER, TEXT("Control Panel\\Desktop"),
 
2765
                               TEXT("WheelScrollLines"), lines, &llen) == TRUE)
 
2766
                       ? (short)_ttoi(lines) : 1;
 
2767
}
 
2768
#endif
 
2769
 
 
2770
 
 
2771
/*---------------------------------------------------------------------------
 
2772
 *  void  CaretTTY (HWND hWnd, CARETS cStyle)
 
2773
 *
 
2774
 *  Description:
 
2775
 *     Adjusts the Caret to the user supplied style
 
2776
 *
 
2777
 *  Parameters:
 
2778
 *     HWND hWnd
 
2779
 *        handle to TTY window
 
2780
 *
 
2781
 *     int wStyle
 
2782
 *        New style to take on
 
2783
 *
 
2784
/*--------------------------------------------------------------------------*/
 
2785
LOCAL void
 
2786
CaretTTY (HWND hWnd, CARETS cStyle)
 
2787
{
 
2788
    PTTYINFO  pTTYInfo;
 
2789
 
 
2790
    if(pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO)){
 
2791
        pTTYInfo->cCaretStyle = cStyle;
 
2792
        CaretCreateTTY (hWnd);
 
2793
        DidResize (gpTTYInfo);
 
2794
    }
 
2795
}
 
2796
 
 
2797
 
 
2798
/*---------------------------------------------------------------------------
 
2799
 *  void  CaretCreateTTY (HWND hWnd, BOOL wPosition)
 
2800
 *
 
2801
 *  Description:
 
2802
 *     Adjusts the Caret to the user supplied style
 
2803
 *
 
2804
 *  Parameters:
 
2805
 *     HWND hWnd
 
2806
 *        handle to TTY window
 
2807
 *
 
2808
 *     BOOL wPosition
 
2809
 *        whether or not to position it too
 
2810
 *
 
2811
/*--------------------------------------------------------------------------*/
 
2812
LOCAL void
 
2813
CaretCreateTTY (HWND hWnd)
 
2814
{
 
2815
    PTTYINFO  pTTYInfo;
 
2816
 
 
2817
    if(pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO)){
 
2818
        int n = 0, x, y;
 
2819
 
 
2820
        switch(pTTYInfo->cCaretStyle){
 
2821
          case CaretHorizBar :
 
2822
            x = pTTYInfo->xChar;
 
2823
            y = pTTYInfo->yChar / 5;
 
2824
            n = pTTYInfo->yChar - y;
 
2825
            break;
 
2826
 
 
2827
          case CaretVertBar :
 
2828
            x = pTTYInfo->xChar / 4;
 
2829
            y = pTTYInfo->yChar;
 
2830
            break;
 
2831
 
 
2832
          case CaretSmallBlock :
 
2833
            x = pTTYInfo->xChar;
 
2834
            y = pTTYInfo->yChar / 2;
 
2835
            n = pTTYInfo->yChar - y;
 
2836
            break;
 
2837
 
 
2838
          default :
 
2839
            x = pTTYInfo->xChar;
 
2840
            y = pTTYInfo->yChar;
 
2841
            break;
 
2842
        }
 
2843
 
 
2844
        CreateCaret (hWnd, NULL, x, y);
 
2845
        pTTYInfo->yCurOffset = n;
 
2846
 
 
2847
        if(pTTYInfo->fCaretOn){
 
2848
            ShowCaret(hWnd);
 
2849
            MoveTTYCursor(hWnd);
 
2850
        }
 
2851
    }
 
2852
}
 
2853
 
 
2854
 
 
2855
/*
 
2856
 * This routine is inserted as the winsock blocking hook.  It's main perpos
 
2857
 * is to NOT dispatch messages.
 
2858
 */
 
2859
BOOL CALLBACK __export
 
2860
NoMsgsAreSent (void)
 
2861
{
 
2862
    return (FALSE);
 
2863
}
 
2864
 
 
2865
 
 
2866
/*---------------------------------------------------------------------------
 
2867
 *  BOOL  SetTTYFocus( HWND hWnd )
 
2868
 *
 
2869
 *  Description:
 
2870
 *     Sets the focus to the TTY window also creates caret.
 
2871
 *
 
2872
 *  Parameters:
 
2873
 *     HWND hWnd
 
2874
 *        handle to TTY window
 
2875
 *
 
2876
/*--------------------------------------------------------------------------*/
 
2877
LOCAL BOOL
 
2878
SetTTYFocus (HWND hWnd)
 
2879
{
 
2880
    PTTYINFO  pTTYInfo;
 
2881
 
 
2882
#ifdef SDEBUG
 
2883
    if (mswin_debug >= 5)
 
2884
        fprintf (mswin_debugfile, "SetTTYFocus:::  entered\n");
 
2885
#endif
 
2886
 
 
2887
    pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
 
2888
    if (pTTYInfo == NULL)
 
2889
      return (FALSE);
 
2890
 
 
2891
    mswin_showcursor(TRUE);
 
2892
 
 
2893
    pTTYInfo->fFocused = TRUE;
 
2894
    gKeyControlDown = FALSE;
 
2895
 
 
2896
    CaretCreateTTY (hWnd);
 
2897
 
 
2898
    MoveTTYCursor (hWnd);
 
2899
    return (TRUE);
 
2900
}
 
2901
 
 
2902
 
 
2903
/*---------------------------------------------------------------------------
 
2904
 *  BOOL  KillTTYFocus( HWND hWnd )
 
2905
 *
 
2906
 *  Description:
 
2907
 *     Kills TTY focus and destroys the caret.
 
2908
 *
 
2909
 *  Parameters:
 
2910
 *     HWND hWnd
 
2911
 *        handle to TTY window
 
2912
 *
 
2913
/*--------------------------------------------------------------------------*/
 
2914
LOCAL BOOL
 
2915
KillTTYFocus (HWND hWnd)
 
2916
{
 
2917
    PTTYINFO  pTTYInfo;
 
2918
 
 
2919
#ifdef SDEBUG
 
2920
    if (mswin_debug >= 5)
 
2921
        fprintf (mswin_debugfile, "KillTTYFocus:::  entered\n");
 
2922
#endif
 
2923
    pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
 
2924
    if (pTTYInfo == NULL)
 
2925
            return (FALSE);
 
2926
 
 
2927
    mswin_showcursor(TRUE);
 
2928
 
 
2929
    if(pTTYInfo->fCaretOn)
 
2930
      HideCaret (hWnd);
 
2931
 
 
2932
    DestroyCaret();
 
2933
 
 
2934
    pTTYInfo->fFocused = FALSE;
 
2935
    gKeyControlDown = FALSE;
 
2936
 
 
2937
    return (TRUE);
 
2938
}
 
2939
 
 
2940
 
 
2941
/*---------------------------------------------------------------------------
 
2942
 *  BOOL  MoveTTYCursor( HWND hWnd )
 
2943
 *
 
2944
 *  Description:
 
2945
 *     Moves caret to current position.
 
2946
 *
 
2947
 *  Parameters:
 
2948
 *     HWND hWnd
 
2949
 *        handle to TTY window
 
2950
 *
 
2951
/*--------------------------------------------------------------------------*/
 
2952
LOCAL BOOL
 
2953
MoveTTYCursor (HWND hWnd)
 
2954
{
 
2955
    PTTYINFO  pTTYInfo;
 
2956
 
 
2957
    pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
 
2958
    if (pTTYInfo == NULL)
 
2959
            return (FALSE);
 
2960
 
 
2961
    if(pTTYInfo->fCaretOn && !pTTYInfo->fMassiveUpdate) {
 
2962
        HideCaret (hWnd);
 
2963
        SetCaretPos ((pTTYInfo->nColumn * pTTYInfo->xChar) + pTTYInfo->xOffset,
 
2964
                     (pTTYInfo->nRow * pTTYInfo->yChar)
 
2965
                                   + pTTYInfo->yCurOffset + pTTYInfo->yOffset);
 
2966
        ShowCaret (hWnd);
 
2967
    }
 
2968
 
 
2969
    return (TRUE);
 
2970
}
 
2971
 
 
2972
 
 
2973
/*---------------------------------------------------------------------------
 
2974
 *  BOOL  ProcessTTYKeyDown ( HWND hWnd, WORD bOut, DWORD keyData )
 
2975
 *
 
2976
 *  Description:
 
2977
 *      Called to process MW_KEYDOWN message.  We are only interested in
 
2978
 *      virtual keys that pico/pine use.  All others get passed on to
 
2979
 *      the default message handler.  Regular key presses will return
 
2980
 *      latter as a WM_CHAR message, with SHIFT and CONTROL processing
 
2981
 *      already done.
 
2982
 *
 
2983
 *      We do watch for VK_CONTROL to keep track of it's state such
 
2984
 *      that we can implement ^_space.
 
2985
 *
 
2986
 *  Parameters:
 
2987
 *     HWND hWnd
 
2988
 *        handle to TTY window
 
2989
 *
 
2990
 *     BYTE key
 
2991
 *        Virtual key code.
 
2992
 *
 
2993
 *     DWORD keyData
 
2994
 *        Additional flags passed in lParam for WM_KEYDOWN
 
2995
 *
 
2996
/*--------------------------------------------------------------------------*/
 
2997
LOCAL BOOL
 
2998
ProcessTTYKeyDown (HWND hWnd, TCHAR key, DWORD keyData)
 
2999
{
 
3000
    TCHAR               myKey;
 
3001
 
 
3002
 
 
3003
    if (key == VK_CONTROL)
 
3004
        gKeyControlDown = TRUE;
 
3005
 
 
3006
    /* Special keys. */
 
3007
    if (keyData & 0X20000000)
 
3008
        return (FALSE);                 /* Message NOT handled. */
 
3009
 
 
3010
    switch (key) {
 
3011
        case VK_UP:             myKey = MSWIN_KEY_UP;           break;
 
3012
        case VK_DOWN:           myKey = MSWIN_KEY_DOWN;         break;
 
3013
        case VK_RIGHT:
 
3014
          myKey = (gKeyControlDown) ? '\0': MSWIN_KEY_RIGHT;
 
3015
          break;
 
3016
        case VK_LEFT:
 
3017
          if(gKeyControlDown)
 
3018
            return(FALSE);
 
3019
          else
 
3020
            myKey = MSWIN_KEY_LEFT;
 
3021
          break;
 
3022
        case VK_PRIOR:          myKey = MSWIN_KEY_PREVPAGE;     break;
 
3023
        case VK_NEXT:           myKey = MSWIN_KEY_NEXTPAGE;     break;
 
3024
        case VK_HOME:           myKey = MSWIN_KEY_HOME;         break;
 
3025
        case VK_END:            myKey = MSWIN_KEY_END;          break;
 
3026
        case VK_DELETE:         myKey = MSWIN_KEY_DELETE;       break;
 
3027
        case VK_F1:             myKey = MSWIN_KEY_F1;           break;
 
3028
        case VK_F2:             myKey = MSWIN_KEY_F2;           break;
 
3029
        case VK_F3:             myKey = MSWIN_KEY_F3;           break;
 
3030
        case VK_F4:             myKey = MSWIN_KEY_F4;           break;
 
3031
        case VK_F5:             myKey = MSWIN_KEY_F5;           break;
 
3032
        case VK_F6:             myKey = MSWIN_KEY_F6;           break;
 
3033
        case VK_F7:             myKey = MSWIN_KEY_F7;           break;
 
3034
        case VK_F8:             myKey = MSWIN_KEY_F8;           break;
 
3035
        case VK_F9:             myKey = MSWIN_KEY_F9;           break;
 
3036
        case VK_F10:            myKey = MSWIN_KEY_F10;          break;
 
3037
        case VK_F11:            myKey = MSWIN_KEY_F11;          break;
 
3038
        case VK_F12:            myKey = MSWIN_KEY_F12;          break;
 
3039
        
 
3040
#if 0           
 
3041
        /* Control is special - I keep track, but do not claim to handle. */
 
3042
        case VK_CONTROL:        gKeyControlDown = TRUE;
 
3043
                                return (FALSE);
 
3044
#endif
 
3045
        case '6':
 
3046
            /*
 
3047
             * Ctrl-^ is used to set and clear the mark in the
 
3048
             * composer (pico) On most other systems Ctrl-6 does the
 
3049
             * same thing.  Allow that on windows too.  If we detect
 
3050
             * '6' key down while the control key is pressed we then
 
3051
             * insert a ctrl-^ character.  Position of the shift key
 
3052
             * is not checked so this code handles both combinations.
 
3053
             * There is one more trick: ctrl-shift-6 will result in a
 
3054
             * WM_CHAR message for 0x1e.  But that will be a
 
3055
             * duplicate control character because this code already
 
3056
             * generated a control character.  So, in ProcessTTYChar
 
3057
             * is ignore the 0x1e characters.
 
3058
             */
 
3059
            if (gKeyControlDown)
 
3060
                myKey = 0x1e;
 
3061
            else
 
3062
                return (FALSE);
 
3063
            break;
 
3064
        case '-':
 
3065
            /*
 
3066
             * Ctrl-_ is used to invoke alternate editor.
 
3067
             */
 
3068
            if (gKeyControlDown)
 
3069
                myKey = 0x1f;
 
3070
            else
 
3071
                return (FALSE);
 
3072
            break;
 
3073
        case '2':
 
3074
            /*
 
3075
             * Ctrl-@ (null) is used to advance to the next word.
 
3076
             */
 
3077
            if (gKeyControlDown)
 
3078
                myKey = '\0';
 
3079
            else
 
3080
                return (FALSE);
 
3081
            break;
 
3082
        default:                return (FALSE); /* Message NOT handled.*/
 
3083
    }
 
3084
 
 
3085
    CQAdd (myKey, 0);
 
3086
 
 
3087
    set_time_of_last_input();
 
3088
 
 
3089
    return (TRUE);                      /* Message handled .*/
 
3090
}
 
3091
 
 
3092
 
 
3093
/*---------------------------------------------------------------------------
 
3094
 *  BOOL  ProcessTTYKeyUp ( HWND hWnd, WORD bOut, DWORD keyData )
 
3095
 *
 
3096
 *  Description:
 
3097
 *      Called to process MW_KEYDOWN message.
 
3098
 *      Used only to detect when the control key goes up.
 
3099
 *
 
3100
 *  Parameters:
 
3101
 *     HWND hWnd
 
3102
 *        handle to TTY window
 
3103
 *
 
3104
 *     BYTE key
 
3105
 *        Virtual key code.
 
3106
 *
 
3107
 *     DWORD keyData
 
3108
 *        Additional flags passed in lParam for WM_KEYDOWN
 
3109
 *
 
3110
/*--------------------------------------------------------------------------*/
 
3111
LOCAL BOOL
 
3112
ProcessTTYKeyUp (HWND hWnd, TCHAR key, DWORD keyData)
 
3113
{
 
3114
    if (key == VK_CONTROL)
 
3115
        gKeyControlDown = FALSE;
 
3116
 
 
3117
#if 0
 
3118
    /* Special keys. */
 
3119
    if (keyData & 0X20000000)
 
3120
        return (FALSE);                 /* Message NOT handled. */
 
3121
#endif
 
3122
                                
 
3123
    return (FALSE);     /* Message NOT handled.*/
 
3124
}
 
3125
 
 
3126
 
 
3127
#ifdef CDEBUG
 
3128
char *
 
3129
dtime()
 
3130
{
 
3131
    static char timestring[23];
 
3132
    time_t t;
 
3133
    struct _timeb timebuffer;
 
3134
 
 
3135
    timestring[0] = '\0';
 
3136
    t = time((time_t *) 0);
 
3137
    _ftime(&timebuffer);
 
3138
    snprintf(timestring, sizeof(timestring), "%.8s.%03ld", ctime(&t)+11, timebuffer.millitm);
 
3139
 
 
3140
    return(timestring);
 
3141
}
 
3142
#endif
 
3143
 
 
3144
 
 
3145
/*---------------------------------------------------------------------------
 
3146
 *  BOOL  ProcessTTYCharacter( HWND hWnd, WORD bOut, DWORD keyData )
 
3147
 *
 
3148
 *  Description:
 
3149
 *              Place the character into a queue.
 
3150
 *
 
3151
 *  Parameters:
 
3152
 *     HWND hWnd
 
3153
 *        handle to TTY window
 
3154
 *
 
3155
 *     BYTE bOut
 
3156
 *        byte from keyboard
 
3157
 *
 
3158
/*--------------------------------------------------------------------------*/
 
3159
LOCAL BOOL
 
3160
ProcessTTYCharacter (HWND hWnd, TCHAR bOut, DWORD keyData)
 
3161
{
 
3162
 
 
3163
    /*
 
3164
     * Map Ctrl-space to the null character.  Window's does not do
 
3165
     * this for us.
 
3166
     */
 
3167
    if (bOut == (TCHAR)' ' && gKeyControlDown)
 
3168
      bOut = (TCHAR)'\0';
 
3169
 
 
3170
    /*
 
3171
     * This is the second half of the code to handle ctrl-6 and
 
3172
     * ctrl-shift-6 (ctrl-^).  Here, we ignore the WM_CHAR message
 
3173
     * generated by ctrl-shift-6.
 
3174
     */
 
3175
    if (bOut == (TCHAR)0x1e)
 
3176
        return (TRUE);
 
3177
 
 
3178
    CQAdd ((UCS)bOut, keyData);
 
3179
 
 
3180
#ifdef ACCELERATORS
 
3181
    UpdateAccelerators (hWnd);
 
3182
#endif
 
3183
 
 
3184
    set_time_of_last_input();
 
3185
 
 
3186
    return (TRUE);              /* Message handled. */
 
3187
}
 
3188
 
 
3189
 
 
3190
/*---------------------------------------------------------------------------
 
3191
 *  BOOL  ProcessTTYMouse(HWND hWnd, int mevent, int button,
 
3192
 *                        int xPos, int yPos, WPARAM keys)
 
3193
 *
 
3194
 *  Description:
 
3195
 *      This is the central control for all mouse events.  Every event
 
3196
 *      gets put into a queue to wait for the upper layer.
 
3197
 *
 
3198
 *      The upper's input routine calls checkmouse() which pulls the
 
3199
 *      mouse event off the input queue.  checkmouse() has a list of
 
3200
 *      of screen regions.  Some regions correspond to a "menu" item
 
3201
 *      (text button at bottom of screen).  There is generally one
 
3202
 *      region for the central region of the screen.
 
3203
 *
 
3204
 *      Because pine/pico do not interpret mouse drags, we do that here.
 
3205
 *      When the user presses the button and drags the mouse across the
 
3206
 *      screen this select the text in the region defined by the drag.
 
3207
 *      The operation is local to mswin.c, and can only get what text
 
3208
 *      is on the screen.
 
3209
 *
 
3210
 *      The one exception is that now pico interprets mouse drag events
 
3211
 *      in the body.  pico signals that it wants to track the mouse
 
3212
 *      by calling mswin_allowmousetrack().  This will 1) turn off
 
3213
 *      our mouse tracking and 2) cause mouse movement events to
 
3214
 *      be put on the mouse queue.
 
3215
 *
 
3216
 *
 
3217
 *  Parameters:
 
3218
 *     HWND hWnd
 
3219
 *        handle to TTY window
 
3220
 *
 
3221
 *     BYTE bOut
 
3222
 *        byte from keyboard
 
3223
 *
 
3224
/*--------------------------------------------------------------------------*/
 
3225
LOCAL BOOL
 
3226
ProcessTTYMouse (HWND hWnd, int mevent, int button,
 
3227
                 CORD xPos, CORD yPos, WPARAM winkeys)
 
3228
{
 
3229
    int         nRow;
 
3230
    int         nColumn;
 
3231
    int         keys;
 
3232
 
 
3233
    /*
 
3234
     * Convert to cell position.
 
3235
     */
 
3236
    nColumn = (xPos - gpTTYInfo->xOffset) / gpTTYInfo->xChar;
 
3237
    if (xPos < gpTTYInfo->xOffset)
 
3238
        --nColumn;
 
3239
    nRow = (yPos - gpTTYInfo->yOffset) / gpTTYInfo->yChar;
 
3240
    if (yPos < gpTTYInfo->yOffset)
 
3241
        --nRow;
 
3242
 
 
3243
    /*
 
3244
     * Convert window's keys.
 
3245
     */
 
3246
    keys = 0;
 
3247
    if (winkeys & MK_CONTROL)
 
3248
            keys |= M_KEY_CONTROL;
 
3249
    if (winkeys & MK_SHIFT)
 
3250
            keys |= M_KEY_SHIFT;
 
3251
 
 
3252
    /* Adjust the cursor */
 
3253
    if((unsigned long) mevent != M_EVENT_UP){
 
3254
        if(gMouseTracking)
 
3255
          mswin_setcursor(MSWIN_CURSOR_IBEAM);
 
3256
        else if(ghCursorCurrent == ghCursorBusy)
 
3257
          mswin_setcursor(MSWIN_CURSOR_BUSY);
 
3258
        else if(mouse_on_key(nRow, nColumn))
 
3259
          mswin_setcursor(MSWIN_CURSOR_HAND);
 
3260
        else if(gMouseTrackCallback)
 
3261
          mswin_setcursor((*gMouseTrackCallback)(nColumn, (long) nRow));
 
3262
        else
 
3263
          mswin_setcursor(MSWIN_CURSOR_ARROW);
 
3264
    }
 
3265
 
 
3266
    /*
 
3267
     * Tracking event or mouse up/down?
 
3268
     */
 
3269
    if ((unsigned long) mevent == M_EVENT_TRACK) {
 
3270
        /*
 
3271
         * Who is doing the tracking?
 
3272
         */
 
3273
        if (gAllowMouseTrack) {
 
3274
            /* For tracking, Button info is different. */
 
3275
            if (keys & MK_LBUTTON)
 
3276
                button = M_BUTTON_LEFT;
 
3277
            else if (keys & MK_MBUTTON)
 
3278
                button = M_BUTTON_MIDDLE;
 
3279
            else if (keys & MK_RBUTTON)
 
3280
                button = M_BUTTON_RIGHT;
 
3281
            MQAdd (mevent, button, nRow, nColumn, keys,
 
3282
                    MSWIN_MF_REPLACING);
 
3283
        }
 
3284
        else
 
3285
            SelTrackMouse (nRow, nColumn);
 
3286
    }
 
3287
    else{
 
3288
        /*
 
3289
         * Tracking.  Only start tracking mouse down in the text region
 
3290
         * But allow mouse up anywhere.
 
3291
         */
 
3292
        if ( (nRow >= 0 && nRow < gpTTYInfo->actNRow &&
 
3293
                   nColumn >= 0 && nColumn < gpTTYInfo->actNColumn)
 
3294
                  || (unsigned long) mevent == M_EVENT_UP) {
 
3295
 
 
3296
            /*
 
3297
             * Mouse tracking.  When the mouse goes down we start
 
3298
             * capturing all mouse movement events.  If no one else wants
 
3299
             * them we will start defining a text selection.
 
3300
             */
 
3301
            if ((unsigned long) mevent == M_EVENT_DOWN) {
 
3302
                gMouseTracking = TRUE;
 
3303
                SetCapture (ghTTYWnd);
 
3304
                if (!gAllowMouseTrack && button == M_BUTTON_LEFT)
 
3305
                    SelStart (nRow, nColumn);
 
3306
            }
 
3307
            else {
 
3308
                ReleaseCapture ();
 
3309
                if (!gAllowMouseTrack && button == M_BUTTON_LEFT)
 
3310
                    SelFinish (nRow, nColumn);
 
3311
                gMouseTracking = FALSE;
 
3312
 
 
3313
                /*
 
3314
                 * If right mouse button, toss pop-up menu offering
 
3315
                 * cut/copy/paste
 
3316
                 */
 
3317
                if(button == M_BUTTON_RIGHT && SelAvailable()){
 
3318
                    UINT fAllowed = (EM_CP | EM_CP_APPEND);
 
3319
 
 
3320
                    if(gAllowCut)
 
3321
                      fAllowed |= EM_CUT;
 
3322
 
 
3323
                    if(CopyCutPopup(hWnd, fAllowed) == TRUE)
 
3324
                      mevent = M_EVENT_TRACK; /* don't add to input queue! */
 
3325
                }
 
3326
            }
 
3327
 
 
3328
            /*
 
3329
             * Insert event into queue.
 
3330
             */
 
3331
            if((unsigned long) mevent != M_EVENT_TRACK)
 
3332
              MQAdd (mevent, button, nRow, nColumn, keys, 0);
 
3333
        }
 
3334
    }
 
3335
 
 
3336
    mswin_showcursor(TRUE);     /* make sure it's visible */
 
3337
 
 
3338
#ifdef ACCELERATORS
 
3339
    UpdateAccelerators (hWnd);
 
3340
#endif
 
3341
 
 
3342
    set_time_of_last_input();
 
3343
 
 
3344
    return (0);         /* Message handled. */
 
3345
}
 
3346
 
 
3347
 
 
3348
/*---------------------------------------------------------------------------
 
3349
 *  BOOL  ProcessTimer ()
 
3350
 *
 
3351
 *  Description:
 
3352
 *     Process the periodic timer calls.
 
3353
 *
 
3354
 *
 
3355
 *  Parameters:
 
3356
 *      None.
 
3357
 *
 
3358
/*--------------------------------------------------------------------------*/
 
3359
LOCAL void
 
3360
ProcessTimer (void)
 
3361
{
 
3362
    /* Time to deliver an alarm signal? */
 
3363
    if (gAlarmTimeout != 0 && GetTickCount () / 1000 > gAlarmTimeout)
 
3364
        AlarmDeliver ();
 
3365
 
 
3366
    /* Time to make the periodic callback. */
 
3367
    if (gPeriodicCallback != NULL &&
 
3368
            GetTickCount() / 1000 > gPeriodicCBTimeout) {
 
3369
        gPeriodicCBTimeout = GetTickCount() / 1000 +
 
3370
                                                gPeriodicCBTime;
 
3371
        gPeriodicCallback ();
 
3372
    }
 
3373
 
 
3374
    /*
 
3375
     * If tracking the mouse, insert a fake mouse tracking message
 
3376
     * At the last know location of the mouse.
 
3377
     */
 
3378
    if (gAllowMouseTrack) {
 
3379
        gMTEvent.event = M_EVENT_TRACK;
 
3380
        MQAdd (gMTEvent.event, gMTEvent.button, gMTEvent.nRow,
 
3381
                gMTEvent.nColumn, gMTEvent.keys, MSWIN_MF_REPLACING);
 
3382
    }
 
3383
}
 
3384
 
 
3385
 
 
3386
/*---------------------------------------------------------------------------
 
3387
 *  BOOL  WriteTTYBlock( HWND hWnd, LPSTR lpBlock, int nLength )
 
3388
 *
 
3389
 *  Description:
 
3390
 *     Writes block to TTY screen.  Nothing fancy - just
 
3391
 *     straight TTY.
 
3392
 *
 
3393
 *  Parameters:
 
3394
 *     HWND hWnd
 
3395
 *        handle to TTY window
 
3396
 *
 
3397
 *     LPSTR lpBlock
 
3398
 *        far pointer to block of data
 
3399
 *
 
3400
 *     int nLength
 
3401
 *        length of block
 
3402
 *
 
3403
/*--------------------------------------------------------------------------*/
 
3404
LOCAL BOOL
 
3405
WriteTTYBlock (HWND hWnd, LPTSTR lpBlock, int nLength)
 
3406
{
 
3407
    int                         i, j, width;
 
3408
    PTTYINFO                    pTTYInfo;
 
3409
    RECT                        rect;
 
3410
    BOOL                        fNewLine;
 
3411
    long                        offset;
 
3412
 
 
3413
    pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
 
3414
    if (pTTYInfo == NULL)
 
3415
            return (FALSE);
 
3416
 
 
3417
    for (i = 0 ; i < nLength; i++) {
 
3418
        switch (lpBlock[i]) {
 
3419
        case ASCII_BEL:
 
3420
            /* Bell */
 
3421
            MessageBeep (0) ;
 
3422
            break ;
 
3423
 
 
3424
        case ASCII_BS:
 
3425
            /* Backspace over a whole character */
 
3426
            offset = pscreen_offset_from_cord(pTTYInfo->nRow, pTTYInfo->nColumn, pTTYInfo);
 
3427
            width = (offset > pTTYInfo->nRow * pTTYInfo->actNColumn)
 
3428
                            ? scrwidth(pTTYInfo->pScreen+offset-1, 1) : 0;
 
3429
 
 
3430
            if(pTTYInfo->nColumn > 0)
 
3431
              pTTYInfo->nColumn = (CORD)(pTTYInfo->nColumn - width);
 
3432
 
 
3433
            MoveTTYCursor (hWnd);
 
3434
            break;
 
3435
 
 
3436
        case ASCII_CR:
 
3437
            /* Carriage return */
 
3438
            pTTYInfo->nColumn = 0 ;
 
3439
            MoveTTYCursor (hWnd);
 
3440
            if (!pTTYInfo->fNewLine)
 
3441
                    break;
 
3442
 
 
3443
            /* fall through */
 
3444
 
 
3445
        case ASCII_LF:
 
3446
            /* Line feed */
 
3447
            if (++pTTYInfo->nRow == pTTYInfo->actNRow) {
 
3448
 
 
3449
                /* Scroll the Screen. */
 
3450
 
 
3451
                /* slide rows 1 - n-1 up to row 0 */
 
3452
                memmove ((LPTSTR)pTTYInfo->pScreen,
 
3453
                        (LPTSTR) (pTTYInfo->pScreen + pTTYInfo->actNColumn),
 
3454
                        (pTTYInfo->actNRow - 1) * pTTYInfo->actNColumn * sizeof (TCHAR));
 
3455
 
 
3456
                /* initialize new row n-1 */
 
3457
                for(j = (pTTYInfo->actNRow - 1) * pTTYInfo->actNColumn;
 
3458
                    j < pTTYInfo->actNColumn; j++)
 
3459
                  pTTYInfo->pScreen[j] = (TCHAR) ' ';
 
3460
 
 
3461
 
 
3462
                /* Scroll the Cell Widths */
 
3463
                memmove ((int *)pTTYInfo->pCellWidth,
 
3464
                         (int *) (pTTYInfo->pCellWidth + pTTYInfo->actNColumn),
 
3465
                        (pTTYInfo->actNRow - 1) * pTTYInfo->actNColumn * sizeof (int));         
 
3466
                for(j = (pTTYInfo->actNRow - 1) * pTTYInfo->actNColumn;
 
3467
                    j < pTTYInfo->actNColumn; j++)
 
3468
                  pTTYInfo->pCellWidth[j] = pTTYInfo->xChar;    /* xChar set yet ? */
 
3469
 
 
3470
                /* Scroll the Attributes. */
 
3471
 
 
3472
                /* slide rows 1 - n-1 up to row 0 */
 
3473
                memmove ((CharAttrib *) pTTYInfo->pAttrib,
 
3474
                         (CharAttrib *) (pTTYInfo->pAttrib + pTTYInfo->actNColumn),
 
3475
                         (pTTYInfo->actNRow - 1) * pTTYInfo->actNColumn * sizeof(CharAttrib));
 
3476
 
 
3477
                /* initialize new row n-1 to zero */
 
3478
                memset ((CharAttrib *) (pTTYInfo->pAttrib +
 
3479
                            (pTTYInfo->actNRow - 1) * pTTYInfo->actNColumn),
 
3480
                        0, pTTYInfo->actNColumn*sizeof(CharAttrib));
 
3481
 
 
3482
                pTTYInfo->screenDirty = TRUE;
 
3483
                pTTYInfo->eraseScreen = TRUE;
 
3484
                InvalidateRect (hWnd, NULL, FALSE);
 
3485
                --pTTYInfo->nRow;
 
3486
            }
 
3487
 
 
3488
            MoveTTYCursor (hWnd);
 
3489
            break;
 
3490
 
 
3491
        default:
 
3492
            offset = pscreen_offset_from_cord(pTTYInfo->nRow, pTTYInfo->nColumn, pTTYInfo);
 
3493
            pTTYInfo->pScreen[offset] = lpBlock[i];
 
3494
            pTTYInfo->pCellWidth[offset] = wcellwidth((UCS)lpBlock[i]) * pTTYInfo->xChar;
 
3495
            pTTYInfo->pAttrib[offset] = pTTYInfo->curAttrib;
 
3496
            rect.left = (pTTYInfo->nColumn * pTTYInfo->xChar) +
 
3497
                    pTTYInfo->xOffset;
 
3498
            rect.right = rect.left + pTTYInfo->xChar;
 
3499
            rect.top = (pTTYInfo->nRow * pTTYInfo->yChar) +
 
3500
                    pTTYInfo->yOffset;
 
3501
            rect.bottom = rect.top + pTTYInfo->yChar;
 
3502
            pTTYInfo->screenDirty = TRUE;
 
3503
            InvalidateRect (hWnd, &rect, FALSE);
 
3504
 
 
3505
            /* Line Wrap. */
 
3506
            if (pTTYInfo->nColumn < pTTYInfo->actNColumn - 1)
 
3507
                    pTTYInfo->nColumn++ ;
 
3508
            else if (pTTYInfo->autoWrap == WRAP_ON ||
 
3509
                    (pTTYInfo->autoWrap == WRAP_NO_SCROLL &&
 
3510
                            pTTYInfo->nRow < pTTYInfo->actNRow - 1)) {
 
3511
                    fNewLine = pTTYInfo->fNewLine;
 
3512
                    pTTYInfo->fNewLine = FALSE;
 
3513
                    WriteTTYBlock (hWnd, TEXT("\r\n"), 2);
 
3514
                    pTTYInfo->fNewLine = fNewLine;
 
3515
            }
 
3516
            break;
 
3517
        }
 
3518
    }
 
3519
    return (TRUE);
 
3520
}
 
3521
 
 
3522
 
 
3523
/*---------------------------------------------------------------------------
 
3524
 *  BOOL  WriteTTYText ( HWND hWnd, LPSTR lpBlock, int nLength )
 
3525
 *
 
3526
 *  Description:
 
3527
 *      Like WriteTTYBlock but optimized for strings that are text only,
 
3528
 *      no carrage control characters.
 
3529
 *
 
3530
 *  Parameters:
 
3531
 *     HWND hWnd
 
3532
 *        handle to TTY window
 
3533
 *
 
3534
 *     LPSTR lpBlock
 
3535
 *        far pointer to block of data
 
3536
 *
 
3537
 *     int nLength
 
3538
 *        length of block
 
3539
 *
 
3540
/*--------------------------------------------------------------------------*/
 
3541
LOCAL BOOL
 
3542
WriteTTYText (HWND hWnd, LPTSTR lpText, int nLength)
 
3543
{
 
3544
    int                         i;
 
3545
    PTTYINFO                    pTTYInfo;
 
3546
    RECT                        rect;
 
3547
    long                        offset, endOffset;
 
3548
    long                        colEnd;
 
3549
    long                        screenEnd;
 
3550
    int                         screenwidth;
 
3551
 
 
3552
 
 
3553
    pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
 
3554
    if (pTTYInfo == NULL)
 
3555
      return ( FALSE );
 
3556
 
 
3557
 
 
3558
    /* Calculate offset of cursor, end of current column, and end of screen */
 
3559
    offset = pscreen_offset_from_cord(pTTYInfo->nRow, pTTYInfo->nColumn, pTTYInfo);
 
3560
 
 
3561
    colEnd = (pTTYInfo->nRow + 1) * pTTYInfo->actNColumn;
 
3562
    screenEnd = pTTYInfo->actNRow * pTTYInfo->actNColumn;
 
3563
 
 
3564
 
 
3565
    /* Text is allowed to wrap around to subsequent lines, but not past end
 
3566
     * of screen */
 
3567
    endOffset = offset + nLength;
 
3568
    if (endOffset >= screenEnd) {
 
3569
        nLength = screenEnd - offset;
 
3570
        endOffset = offset + nLength - 1;  /* Last cell, not one past last */
 
3571
    }
 
3572
 
 
3573
 
 
3574
    /* Calculate bounding rectangle. */
 
3575
    if (endOffset <= colEnd) {
 
3576
        /* Single line. */
 
3577
 
 
3578
        screenwidth = scrwidth(lpText, nLength);
 
3579
 
 
3580
        rect.left = (pTTYInfo->nColumn * pTTYInfo->xChar) + pTTYInfo->xOffset;
 
3581
        rect.right = rect.left + (pTTYInfo->xChar * screenwidth);
 
3582
        rect.top = (pTTYInfo->nRow * pTTYInfo->yChar) + pTTYInfo->yOffset;
 
3583
        rect.bottom = rect.top + pTTYInfo->yChar;
 
3584
        /* Advance cursor on cur line but not past end. */
 
3585
        pTTYInfo->nColumn = (CORD)MIN(pTTYInfo->nColumn + screenwidth,
 
3586
                                      pTTYInfo->actNColumn - 1);
 
3587
    }
 
3588
    else {
 
3589
        /* Wraps across multiple lines.  Calculate one rect to cover all
 
3590
         * lines. */
 
3591
        rect.left = 0;
 
3592
        rect.right = pTTYInfo->xSize;
 
3593
        rect.top = (pTTYInfo->nRow * pTTYInfo->yChar) + pTTYInfo->yOffset;
 
3594
        rect.bottom = ((((offset + nLength) / pTTYInfo->actNColumn) + 1) *
 
3595
                        pTTYInfo->yChar) + pTTYInfo->yOffset;
 
3596
        pTTYInfo->nRow = (CORD)(endOffset / pTTYInfo->actNColumn);
 
3597
        pTTYInfo->nColumn = (CORD)(endOffset % pTTYInfo->actNColumn);
 
3598
    }
 
3599
 
 
3600
 
 
3601
    /* Apply text and attributes to screen in one smooth motion. */
 
3602
    for(i = 0; i < nLength; i++)
 
3603
      (pTTYInfo->pScreen+offset)[i] = lpText[i];
 
3604
    for(i = 0; i < nLength; i++)
 
3605
      (pTTYInfo->pCellWidth+offset)[i] = wcellwidth((UCS)lpText[i]) * pTTYInfo->xChar;
 
3606
    for(i = 0; i < nLength; i++)
 
3607
      pTTYInfo->pAttrib[offset+i] = pTTYInfo->curAttrib;
 
3608
 
 
3609
    /* Invalidate rectangle */
 
3610
    pTTYInfo->screenDirty = TRUE;
 
3611
    InvalidateRect (hWnd, &rect, FALSE);
 
3612
    return (TRUE);
 
3613
}
 
3614
 
 
3615
 
 
3616
/*---------------------------------------------------------------------------
 
3617
 *  BOOL  WriteTTYChar (HWND hWnd, char ch)
 
3618
 *
 
3619
 *  Description:
 
3620
 *      Write a single character to the cursor position and advance the
 
3621
 *      cursor.  Does not handle carage control.
 
3622
 *
 
3623
 *  Parameters:
 
3624
 *     HWND hWnd
 
3625
 *        handle to TTY window
 
3626
 *
 
3627
 *     char ch
 
3628
 *        character being written.
 
3629
 *
 
3630
/*--------------------------------------------------------------------------*/
 
3631
LOCAL BOOL
 
3632
WriteTTYChar (HWND hWnd, TCHAR ch)
 
3633
{
 
3634
    PTTYINFO                    pTTYInfo;
 
3635
    RECT                        rect;
 
3636
    long                        offset;
 
3637
 
 
3638
 
 
3639
    pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
 
3640
    if (pTTYInfo == NULL)
 
3641
        return (FALSE);
 
3642
 
 
3643
    offset = (pTTYInfo->nRow * pTTYInfo->actNColumn) +
 
3644
            pTTYInfo->nColumn;
 
3645
 
 
3646
    *(pTTYInfo->pScreen + offset) = ch;
 
3647
    pTTYInfo->pCellWidth[offset] = wcellwidth((UCS)ch) * pTTYInfo->xChar;
 
3648
    pTTYInfo->pAttrib[offset] = pTTYInfo->curAttrib;
 
3649
 
 
3650
    rect.left = (pTTYInfo->nColumn * pTTYInfo->xChar) + pTTYInfo->xOffset;
 
3651
    rect.right = rect.left + pTTYInfo->xChar;
 
3652
    rect.top = (pTTYInfo->nRow * pTTYInfo->yChar) + pTTYInfo->yOffset;
 
3653
    rect.bottom = rect.top + pTTYInfo->yChar;
 
3654
    pTTYInfo->screenDirty = TRUE;
 
3655
    InvalidateRect (hWnd, &rect, FALSE);
 
3656
 
 
3657
 
 
3658
 
 
3659
    /* Line Wrap. */
 
3660
    if (pTTYInfo->nColumn < pTTYInfo->actNColumn - 1)
 
3661
        pTTYInfo->nColumn++ ;
 
3662
    else if ((pTTYInfo->autoWrap == WRAP_ON ||
 
3663
              pTTYInfo->autoWrap == WRAP_NO_SCROLL) &&
 
3664
                    pTTYInfo->nRow < pTTYInfo->actNRow - 1) {
 
3665
       pTTYInfo->nRow++;
 
3666
       pTTYInfo->nColumn = 0;
 
3667
    }
 
3668
    return (TRUE);
 
3669
}
 
3670
 
 
3671
 
 
3672
/*---------------------------------------------------------------------------
 
3673
 *  VOID  GoModalDialogBoxParam( HINSTANCE hInstance,
 
3674
 *                                   LPTSTR lpszTemplate, HWND hWnd,
 
3675
 *                                   DLGPROC lpDlgProc, LPARAM lParam )
 
3676
 *
 
3677
 *  Description:
 
3678
 *     It is a simple utility function that simply performs the
 
3679
 *     MPI and invokes the dialog box with a DWORD paramter.
 
3680
 *
 
3681
 *  Parameters:
 
3682
 *     similar to that of DialogBoxParam() with the exception
 
3683
 *     that the lpDlgProc is not a procedure instance
 
3684
 *
 
3685
/*--------------------------------------------------------------------------*/
 
3686
LOCAL VOID
 
3687
GoModalDialogBoxParam( HINSTANCE hInstance, LPTSTR lpszTemplate,
 
3688
                                 HWND hWnd, DLGPROC lpDlgProc, LPARAM lParam )
 
3689
{
 
3690
   DLGPROC  lpProcInstance ;
 
3691
 
 
3692
   lpProcInstance = (DLGPROC) MakeProcInstance( (FARPROC) lpDlgProc,
 
3693
                                                hInstance ) ;
 
3694
   DialogBoxParam( hInstance, lpszTemplate, hWnd, lpProcInstance, lParam ) ;
 
3695
   FreeProcInstance( (FARPROC) lpProcInstance ) ;
 
3696
}
 
3697
 
 
3698
 
 
3699
/*---------------------------------------------------------------------------
 
3700
 *  BOOL FAR PASCAL __export AboutDlgProc( HWND hDlg, UINT uMsg,
 
3701
 *                                WPARAM wParam, LPARAM lParam )
 
3702
 *
 
3703
 *  Description:
 
3704
 *     Simulates the Windows System Dialog Box.
 
3705
 *
 
3706
 *  Parameters:
 
3707
 *     Same as standard dialog procedures.
 
3708
 *
 
3709
/*--------------------------------------------------------------------------*/
 
3710
BOOL FAR PASCAL __export
 
3711
AboutDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
 
3712
{
 
3713
   switch (uMsg) {
 
3714
      case WM_INITDIALOG:
 
3715
      {
 
3716
         int          idModeString ;
 
3717
         TCHAR        szTemp [81];
 
3718
 
 
3719
         /* sets up version number for PINE */
 
3720
         GetDlgItemText (hDlg, IDD_VERSION, szTemp, sizeof(szTemp)/sizeof(TCHAR));
 
3721
         /* szTemp is unicode, mswin_compilation_date etc are cast as %S in mswin.rc */
 
3722
         _sntprintf (TempBuf, sizeof(TempBuf)/sizeof(TCHAR), szTemp, mswin_specific_winver(),
 
3723
                   mswin_majorver(), mswin_minorver(),
 
3724
                   mswin_compilation_remarks(),
 
3725
                   mswin_compilation_date());
 
3726
         SetDlgItemText (hDlg, IDD_VERSION, (LPTSTR) TempBuf);
 
3727
 
 
3728
         /* get by-line */
 
3729
         LoadString (GET_HINST (hDlg), IDS_BYLINE, TempBuf,
 
3730
                     sizeof(TempBuf) / sizeof(TCHAR));
 
3731
         SetDlgItemText (hDlg, IDD_BYLINE, TempBuf);
 
3732
 
 
3733
      }
 
3734
      return ( TRUE ) ;
 
3735
 
 
3736
      case WM_CLOSE:
 
3737
        EndDialog( hDlg, TRUE ) ;
 
3738
        return ( TRUE ) ;
 
3739
 
 
3740
      case WM_COMMAND:
 
3741
        switch((WORD) wParam){
 
3742
          case IDD_OK :
 
3743
            EndDialog( hDlg, TRUE ) ;
 
3744
            return ( TRUE ) ;
 
3745
 
 
3746
          default :
 
3747
            break;
 
3748
         }
 
3749
 
 
3750
        break;
 
3751
   }
 
3752
   return ( FALSE ) ;
 
3753
 
 
3754
} /* end of AboutDlgProc() */
 
3755
 
 
3756
 
 
3757
/*---------------------------------------------------------------------------
 
3758
 *
 
3759
 *  Description:
 
3760
 *     Simulates the Windows System Dialog Box.
 
3761
 *
 
3762
 *  Parameters:
 
3763
 *     Same as standard dialog procedures.
 
3764
 *
 
3765
/*--------------------------------------------------------------------------*/
 
3766
BOOL FAR PASCAL __export
 
3767
SplashDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
 
3768
{
 
3769
    static  HBITMAP hbmpSplash;
 
3770
 
 
3771
    switch (uMsg) {
 
3772
      case WM_INITDIALOG:
 
3773
        if(hbmpSplash = LoadBitmap(GET_HINST(hDlg),
 
3774
                                   MAKEINTRESOURCE(ALPINESPLASH))){
 
3775
            BITMAP stBitmap;
 
3776
            int   cx, cy;
 
3777
 
 
3778
            cx = GetSystemMetrics(SM_CXSCREEN);
 
3779
            cy = GetSystemMetrics(SM_CYSCREEN);
 
3780
            GetObject(hbmpSplash, sizeof(BITMAP), &stBitmap);
 
3781
 
 
3782
            SetWindowPos(hDlg, HWND_TOPMOST,
 
3783
                         (cx - stBitmap.bmWidth) / 2,
 
3784
                         (cy - stBitmap.bmHeight) / 2,
 
3785
                         stBitmap.bmWidth, stBitmap.bmHeight,
 
3786
                         SWP_NOCOPYBITS /* | SWP_SHOWWINDOW */);
 
3787
        }
 
3788
 
 
3789
        return(TRUE);
 
3790
 
 
3791
      case WM_CTLCOLORDLG :
 
3792
        return(TRUE);
 
3793
 
 
3794
      case WM_ERASEBKGND :
 
3795
        {
 
3796
            HDC          hMemDC;
 
3797
            POINT        stPoint;
 
3798
            BITMAP       stBitmap;
 
3799
            HGDIOBJ      hObject;
 
3800
 
 
3801
          if((hMemDC = CreateCompatibleDC((HDC) wParam)) != NULL){
 
3802
              hObject = SelectObject(hMemDC, hbmpSplash);
 
3803
              SetMapMode(hMemDC, GetMapMode((HDC) wParam));
 
3804
 
 
3805
              GetObject(hbmpSplash, sizeof(BITMAP), &stBitmap);
 
3806
              stPoint.x = stBitmap.bmWidth;
 
3807
              stPoint.y = stBitmap.bmHeight;
 
3808
              DPtoLP((HDC) wParam, &stPoint, 1);
 
3809
 
 
3810
              BitBlt((HDC) wParam,
 
3811
                     0, 0, stPoint.x, stPoint.y,
 
3812
                     hMemDC, 0, 0, SRCCOPY);
 
3813
              SelectObject(hMemDC, hObject);
 
3814
              DeleteDC(hMemDC) ;
 
3815
          }
 
3816
 
 
3817
          return(TRUE);
 
3818
      }
 
3819
 
 
3820
      break;
 
3821
 
 
3822
      case WM_CLOSE:
 
3823
        DestroyWindow(hDlg);
 
3824
        return(TRUE);
 
3825
 
 
3826
     case WM_DESTROY :
 
3827
       if(hbmpSplash)
 
3828
         DeleteObject(hbmpSplash);
 
3829
 
 
3830
       break;
 
3831
 
 
3832
      case WM_COMMAND:          /* No commands! */
 
3833
        DestroyWindow(hDlg);
 
3834
        return(TRUE);
 
3835
   }
 
3836
 
 
3837
   return(FALSE);
 
3838
 
 
3839
}
 
3840
 
 
3841
 
 
3842
#if     0
 
3843
UINT APIENTRY
 
3844
SelectTTYFontHook(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
 
3845
{
 
3846
    switch(uMsg){
 
3847
      case WM_INITDIALOG :
 
3848
      {
 
3849
          /*
 
3850
           * Deactivate the Style combo box...
 
3851
           */
 
3852
          HWND hWnd = GetDlgItem(hDlg, cmb2);
 
3853
          EnableWindow(hWnd, FALSE);
 
3854
          SetWindowPos(hWnd, NULL, 0, 0, 0, 0, SWP_HIDEWINDOW);
 
3855
          return(TRUE);
 
3856
      }
 
3857
 
 
3858
      break;
 
3859
 
 
3860
      case WM_COMMAND :
 
3861
        switch ((WORD) wParam) {
 
3862
          case psh3 :
 
3863
            {
 
3864
                LOGFONT curfont;
 
3865
 
 
3866
                SendMessage(hDlg, WM_CHOOSEFONT_GETLOGFONT,
 
3867
                            0, (LPARAM) &curfont);
 
3868
                ResetTTYFont (ghTTYWnd, gpTTYInfo, &curfont);
 
3869
                return (TRUE);
 
3870
            }
 
3871
 
 
3872
            break;
 
3873
 
 
3874
          default :
 
3875
            break;
 
3876
        }
 
3877
 
 
3878
        break;
 
3879
 
 
3880
      default :
 
3881
        break;
 
3882
    }
 
3883
 
 
3884
    return(FALSE);
 
3885
}
 
3886
#endif
 
3887
 
 
3888
 
 
3889
/*---------------------------------------------------------------------------
 
3890
 *  BOOL  SelectTTYFont( HWND hDlg )
 
3891
 *
 
3892
 *  Description:
 
3893
 *     Selects the current font for the TTY screen.
 
3894
 *     Uses the Common Dialog ChooseFont() API.
 
3895
 *
 
3896
 *  Parameters:
 
3897
 *     HWND hDlg
 
3898
 *        handle to settings dialog
 
3899
 *
 
3900
/*--------------------------------------------------------------------------*/
 
3901
LOCAL BOOL
 
3902
SelectTTYFont (HWND hWnd)
 
3903
{
 
3904
    CHOOSEFONT          cfTTYFont;
 
3905
    LOGFONT             newFont, origFont;
 
3906
    PTTYINFO            pTTYInfo;
 
3907
 
 
3908
    pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
 
3909
    if (pTTYInfo == NULL)
 
3910
        return (FALSE);
 
3911
 
 
3912
    memcpy (&newFont, &gpTTYInfo->lfTTYFont, sizeof (LOGFONT));
 
3913
    memcpy (&origFont, &gpTTYInfo->lfTTYFont, sizeof (LOGFONT));
 
3914
 
 
3915
    cfTTYFont.lStructSize    = sizeof (CHOOSEFONT);
 
3916
    cfTTYFont.hwndOwner      = hWnd ;
 
3917
    cfTTYFont.hDC            = NULL ;
 
3918
    cfTTYFont.rgbColors      = pTTYInfo->rgbFGColor;
 
3919
    cfTTYFont.lpLogFont      = &newFont;
 
3920
    cfTTYFont.Flags          = CF_SCREENFONTS | CF_FIXEDPITCHONLY |
 
3921
            CF_EFFECTS | CF_INITTOLOGFONTSTRUCT |
 
3922
#if     0
 
3923
            CF_FORCEFONTEXIST | CF_LIMITSIZE |
 
3924
            CF_ENABLEHOOK | CF_APPLY;
 
3925
#else
 
3926
            CF_FORCEFONTEXIST | CF_LIMITSIZE;
 
3927
#endif
 
3928
    cfTTYFont.nSizeMin       = FONT_MIN_SIZE;
 
3929
    cfTTYFont.nSizeMax       = FONT_MAX_SIZE;
 
3930
    cfTTYFont.lCustData      = (long) 0 ;
 
3931
#if     0
 
3932
    cfTTYFont.lpfnHook       = SelectTTYFontHook ;
 
3933
#else
 
3934
    cfTTYFont.lpfnHook       = NULL;
 
3935
#endif
 
3936
    cfTTYFont.lpTemplateName = NULL ;
 
3937
    cfTTYFont.hInstance      = GET_HINST (hWnd);
 
3938
 
 
3939
 
 
3940
 
 
3941
    if (ChooseFont (&cfTTYFont)) {
 
3942
        pTTYInfo->rgbFGColor = cfTTYFont.rgbColors;
 
3943
        ResetTTYFont (hWnd, pTTYInfo, &newFont);
 
3944
    }
 
3945
#if     0
 
3946
    else{
 
3947
        ResetTTYFont (hWnd, pTTYInfo, &origFont);
 
3948
    }
 
3949
#endif
 
3950
 
 
3951
    return (TRUE);
 
3952
}
 
3953
 
 
3954
 
 
3955
/*
 
3956
 * Set a specific color (forground, background, reverse, normal) to
 
3957
 * the color specified by name.
 
3958
 */
 
3959
LOCAL void
 
3960
SetColorAttribute (COLORREF *cf, char *colorName)
 
3961
{
 
3962
    /* color name not in table.  Try converting RGB string. */
 
3963
    ConvertRGBString (colorName, cf);
 
3964
 
 
3965
    /* Redraw screen. */
 
3966
    gpTTYInfo->screenDirty = TRUE;
 
3967
    gpTTYInfo->eraseScreen = TRUE;
 
3968
    InvalidateRect (ghTTYWnd, NULL, FALSE);
 
3969
}
 
3970
 
 
3971
 
 
3972
/*
 
3973
 * Set current color attribute to reverse color
 
3974
 */
 
3975
void
 
3976
SetReverseColor()
 
3977
{
 
3978
    FlushWriteAccum ();
 
3979
    gpTTYInfo->curAttrib.rgbFG = gpTTYInfo->rgbRFGColor;
 
3980
    gpTTYInfo->curAttrib.rgbBG = gpTTYInfo->rgbRBGColor;
 
3981
}
 
3982
 
 
3983
 
 
3984
/*
 
3985
 * Convert a string to an integer.
 
3986
 */
 
3987
LOCAL BOOL
 
3988
ScanInt (char *str, int min, int max, int *val)
 
3989
{
 
3990
    char        *c;
 
3991
    int         v;
 
3992
    int         neg = 1;
 
3993
 
 
3994
 
 
3995
    if (str == NULL) return (FALSE);
 
3996
    if (*str == '\0' || strlen (str) > 9) return (FALSE);
 
3997
 
 
3998
    /* Check for a negative sign. */
 
3999
    if (*str == '-') {
 
4000
        neg = -1;
 
4001
        ++str;
 
4002
    }
 
4003
 
 
4004
    /* Check for all digits. */
 
4005
    for (c = str; *c != '\0'; ++c) {
 
4006
        if (!isdigit((unsigned char)*c))
 
4007
            return (FALSE);
 
4008
    }
 
4009
 
 
4010
    /* Convert from ascii to int. */
 
4011
    v = atoi (str) * neg;
 
4012
 
 
4013
    /* Check constraints. */
 
4014
    if (v < min || v > max)
 
4015
        return (FALSE);
 
4016
    *val = v;
 
4017
    return (TRUE);
 
4018
}
 
4019
 
 
4020
 
 
4021
/*
 
4022
 * Convert a RGB string to a color ref.  The string should look like:
 
4023
 *    rrr,ggg,bbb
 
4024
 * where rrr, ggg, and bbb are numbers between 0 and 255 that represent
 
4025
 * red, gree, and blue values.  Must be comma seperated.
 
4026
 * Returns:
 
4027
 *      TRUE    - Successfully converted string.
 
4028
 *      FALSE   - Bad format, 'cf' unchanged.
 
4029
 */
 
4030
LOCAL BOOL
 
4031
ConvertRGBString (char *colorName, COLORREF *cf)
 
4032
{
 
4033
    int         i, j, n, rgb[3];
 
4034
    MSWINColor *ct;
 
4035
 
 
4036
    if(!colorName)
 
4037
      return(FALSE);
 
4038
 
 
4039
    /* Is the name in the global color table? */
 
4040
    for(ct = MSWINColorTable; ct->colorName; ct++)
 
4041
      if(!struncmp(ct->colorName, colorName, (int)strlen(ct->colorName))){
 
4042
          *cf = ct->colorRef;
 
4043
          return(TRUE);
 
4044
      }
 
4045
 
 
4046
    /* Not a named color, try RRR,GGG,BBB */
 
4047
    for(i = 0; i < 3; i++){
 
4048
        if(i && *colorName++ != ',')
 
4049
          return(FALSE);
 
4050
 
 
4051
        for(rgb[i] = 0, j = 0; j < 3; j++)
 
4052
          if((n = *colorName++ - '0') < 0 || n > 9)
 
4053
            return(FALSE);
 
4054
          else
 
4055
            rgb[i] = (rgb[i] * 10) + n;
 
4056
    }
 
4057
 
 
4058
    *cf = RGB (rgb[0], rgb[1], rgb[2]);
 
4059
    return (TRUE);
 
4060
}
 
4061
 
 
4062
 
 
4063
LOCAL char *
 
4064
ConvertStringRGB(char *colorName, size_t ncolorName, COLORREF colorRef)
 
4065
{
 
4066
    MSWINColor *cf;
 
4067
 
 
4068
    for(cf = MSWINColorTable;
 
4069
        cf->colorName && cf->colorRef != colorRef;
 
4070
        cf++)
 
4071
      ;
 
4072
 
 
4073
    if(cf->colorName){
 
4074
        strncpy(colorName, cf->colorName, ncolorName);
 
4075
        colorName[ncolorName-1] = '\0';
 
4076
    }
 
4077
    else
 
4078
      snprintf(colorName, ncolorName, "%.3d,%.3d,%.3d",
 
4079
               GetRValue(colorRef), GetGValue(colorRef), GetBValue(colorRef));
 
4080
 
 
4081
    return(colorName);
 
4082
}
 
4083
 
 
4084
 
 
4085
/*
 
4086
 * Map from integer color value to canonical color name.
 
4087
 */
 
4088
char *
 
4089
colorx(int color)
 
4090
{
 
4091
    MSWINColor *ct;
 
4092
    static char cbuf[RGBLEN+1];
 
4093
 
 
4094
    if(color < fullColorTableSize){
 
4095
        ct = &MSWINColorTable[color];
 
4096
        if(ct->canonicalName)
 
4097
          return(ct->canonicalName);
 
4098
    }
 
4099
 
 
4100
    /* not supposed to get here */
 
4101
    snprintf(cbuf, sizeof(cbuf), "color%03.3d", color);
 
4102
    return(cbuf);
 
4103
}
 
4104
 
 
4105
 
 
4106
/*
 
4107
 * Argument is a color name which could be an RGB string, a name like "blue",
 
4108
 * or a name like "color011".
 
4109
 *
 
4110
 * Returns a pointer to the canonical name of the color.
 
4111
 */
 
4112
char *
 
4113
color_to_canonical_name(char *s)
 
4114
{
 
4115
    int         i, j, n, rgb[3];
 
4116
    MSWINColor *ct;
 
4117
    COLORREF    cr;
 
4118
    static char cn[RGBLEN+1];
 
4119
 
 
4120
    if(!s)
 
4121
      return(NULL);
 
4122
 
 
4123
    for(ct = MSWINColorTable; ct->colorName; ct++)
 
4124
      if(!struncmp(ct->colorName, s, (int)strlen(ct->colorName)))
 
4125
        break;
 
4126
 
 
4127
    if(ct->colorName)
 
4128
      return(ct->canonicalName);
 
4129
 
 
4130
    /* maybe it is RGB? */
 
4131
    for(i = 0; i < 3; i++){
 
4132
        if(i && *s++ != ',')
 
4133
          return("");
 
4134
 
 
4135
        for(rgb[i] = 0, j = 0; j < 3; j++)
 
4136
          if((n = *s++ - '0') < 0 || n > 9)
 
4137
            return("");
 
4138
          else
 
4139
            rgb[i] = (rgb[i] * 10) + n;
 
4140
    }
 
4141
 
 
4142
    cr = RGB(rgb[0], rgb[1], rgb[2]);
 
4143
 
 
4144
    /*
 
4145
     * Now compare that RGB against the color table RGBs. If it is
 
4146
     * in the table, return the canonical name, else return the RGB string.
 
4147
     */
 
4148
    for(ct = MSWINColorTable; ct->colorName; ct++)
 
4149
      if(ct->colorRef == cr)
 
4150
        break;
 
4151
 
 
4152
    if(ct->colorName)
 
4153
      return(ct->canonicalName);
 
4154
    else{
 
4155
        snprintf(cn, sizeof(cn), "%.3d,%.3d,%.3d",
 
4156
                GetRValue(cr), GetGValue(cr), GetBValue(cr));
 
4157
        return(cn);
 
4158
    }
 
4159
}
 
4160
 
 
4161
 
 
4162
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
4163
 *
 
4164
 *                  Toolbar setup routines.
 
4165
 *
 
4166
 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
 
4167
LOCAL void
 
4168
TBToggle (HWND hWnd)
 
4169
{
 
4170
    PTTYINFO            pTTYInfo;
 
4171
 
 
4172
 
 
4173
    pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
 
4174
    if (pTTYInfo == NULL)
 
4175
        return;
 
4176
 
 
4177
    if (pTTYInfo->toolBarSize > 0)
 
4178
        TBHide (hWnd);
 
4179
    else
 
4180
        TBShow (hWnd);
 
4181
}
 
4182
 
 
4183
 
 
4184
LOCAL void
 
4185
TBPosToggle (HWND hWnd)
 
4186
{
 
4187
    PTTYINFO            pTTYInfo;
 
4188
 
 
4189
 
 
4190
    pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
 
4191
    if (pTTYInfo == NULL)
 
4192
        return;
 
4193
 
 
4194
    pTTYInfo->toolBarTop = !pTTYInfo->toolBarTop;
 
4195
    if(pTTYInfo->hTBWnd){
 
4196
        TBHide (hWnd);
 
4197
        TBShow (hWnd);
 
4198
    }
 
4199
}
 
4200
 
 
4201
 
 
4202
LOCAL void
 
4203
TBShow (HWND hWnd)
 
4204
{
 
4205
    PTTYINFO            pTTYInfo;
 
4206
    RECT                rc;
 
4207
 
 
4208
 
 
4209
    pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
 
4210
    if (pTTYInfo == NULL)
 
4211
        return;
 
4212
 
 
4213
 
 
4214
    /*
 
4215
     * Make sure the tool bar not already shown.
 
4216
     */
 
4217
    if (pTTYInfo->toolBarSize > 0)
 
4218
        return;
 
4219
 
 
4220
 
 
4221
 
 
4222
    /*
 
4223
     * Make procinstance for dialog funciton.
 
4224
     */
 
4225
    HideCaret (hWnd);
 
4226
    if (gToolBarProc == NULL)
 
4227
        gToolBarProc = (DLGPROC) MakeProcInstance( (FARPROC) ToolBarProc,
 
4228
                                                ghInstance ) ;
 
4229
    if (gTBBtnProc == NULL)
 
4230
        gTBBtnProc = (WNDPROC) MakeProcInstance( (FARPROC) TBBtnProc,
 
4231
                                                ghInstance ) ;
 
4232
 
 
4233
        
 
4234
    /*
 
4235
     * Create the dialog box.
 
4236
     */
 
4237
    pTTYInfo->hTBWnd = CreateDialog (ghInstance,
 
4238
                    MAKEINTRESOURCE (pTTYInfo->curToolBarID),
 
4239
                    hWnd,
 
4240
                    gToolBarProc);
 
4241
    if (pTTYInfo->hTBWnd == NULL) {
 
4242
        ShowCaret (hWnd);
 
4243
        return;
 
4244
    }
 
4245
 
 
4246
    SetFocus (hWnd);
 
4247
 
 
4248
 
 
4249
    /*
 
4250
     * Adjust the window size.
 
4251
     */
 
4252
    GetWindowRect (pTTYInfo->hTBWnd, &rc);      /* Get Toolbar size. */
 
4253
    pTTYInfo->toolBarSize = (CORD)(rc.bottom - rc.top);
 
4254
 
 
4255
    GetClientRect (hWnd, &rc);                  /* Get TTY window size. */
 
4256
    SizeTTY (hWnd, 0, (CORD)rc.bottom, (CORD)rc.right);
 
4257
    ShowCaret (hWnd);
 
4258
}
 
4259
 
 
4260
 
 
4261
LOCAL void
 
4262
TBHide (HWND hWnd)
 
4263
{
 
4264
    PTTYINFO            pTTYInfo;
 
4265
    RECT                rc;
 
4266
 
 
4267
    pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
 
4268
    if (pTTYInfo == NULL)
 
4269
        return;
 
4270
 
 
4271
 
 
4272
    if (pTTYInfo->toolBarSize == 0)
 
4273
        return;
 
4274
 
 
4275
    DestroyWindow (pTTYInfo->hTBWnd);
 
4276
    pTTYInfo->hTBWnd = NULL;
 
4277
    if (pTTYInfo->toolBarBtns != NULL)
 
4278
        MemFree (pTTYInfo->toolBarBtns);
 
4279
    pTTYInfo->toolBarBtns = NULL;
 
4280
 
 
4281
 
 
4282
    /*
 
4283
     * Adjust the window size.
 
4284
     */
 
4285
    pTTYInfo->toolBarSize = 0;
 
4286
    GetClientRect (hWnd, &rc);
 
4287
    SizeTTY (hWnd, 0, (CORD)rc.bottom, (CORD)rc.right);
 
4288
}
 
4289
 
 
4290
 
 
4291
LOCAL void
 
4292
TBSwap (HWND hWnd, int newID)
 
4293
{
 
4294
    PTTYINFO            pTTYInfo;
 
4295
    RECT                rc;
 
4296
 
 
4297
    pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
 
4298
    if (pTTYInfo == NULL)
 
4299
        return;
 
4300
 
 
4301
    if (pTTYInfo->toolBarSize == 0 || pTTYInfo->curToolBarID == newID)
 
4302
        return;
 
4303
 
 
4304
    /*
 
4305
     * Dispose of old tool bar window.
 
4306
     */
 
4307
    HideCaret (hWnd);
 
4308
 
 
4309
    DestroyWindow (pTTYInfo->hTBWnd);
 
4310
    pTTYInfo->hTBWnd = NULL;
 
4311
    if (pTTYInfo->toolBarBtns != NULL)
 
4312
        MemFree (pTTYInfo->toolBarBtns);
 
4313
    pTTYInfo->toolBarBtns = NULL;
 
4314
 
 
4315
 
 
4316
 
 
4317
    /*
 
4318
     * Create the new dialog box.
 
4319
     */
 
4320
    pTTYInfo->hTBWnd = CreateDialog (ghInstance,
 
4321
                    MAKEINTRESOURCE (newID),
 
4322
                    hWnd,
 
4323
                    gToolBarProc);
 
4324
    if (pTTYInfo->hTBWnd == NULL) {
 
4325
        ShowCaret (hWnd);
 
4326
        return;
 
4327
    }
 
4328
    pTTYInfo->curToolBarID = newID;
 
4329
    SetFocus (hWnd);            /* Return focus to parent. */
 
4330
 
 
4331
 
 
4332
    /*
 
4333
     * Fit new tool bar into old tool bars position.  This assumes that
 
4334
     * all tool bars are about the same height.
 
4335
     */
 
4336
    GetClientRect (hWnd, &rc);                  /* Get TTY window size. */
 
4337
    if (pTTYInfo->toolBarTop)
 
4338
        /* Position at top of window. */
 
4339
        SetWindowPos (pTTYInfo->hTBWnd, HWND_TOP,
 
4340
                0, 0,
 
4341
                rc.right, pTTYInfo->toolBarSize,
 
4342
                SWP_NOZORDER | SWP_NOACTIVATE | SWP_SHOWWINDOW);
 
4343
    else
 
4344
        /* Position at bottom of window. */
 
4345
        SetWindowPos (pTTYInfo->hTBWnd, HWND_TOP,
 
4346
                0, pTTYInfo->ySize - pTTYInfo->toolBarSize,
 
4347
                rc.right, pTTYInfo->toolBarSize,
 
4348
                SWP_NOZORDER | SWP_NOACTIVATE | SWP_SHOWWINDOW);
 
4349
 
 
4350
    ShowCaret (hWnd);
 
4351
}
 
4352
 
 
4353
 
 
4354
BOOL FAR PASCAL __export
 
4355
ToolBarProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
 
4356
{
 
4357
    RECT                rc;
 
4358
    BOOL                ret;
 
4359
    int                 height;
 
4360
    HBRUSH              hBrush;
 
4361
    HWND                hCld;
 
4362
    int                 btnCount;
 
4363
    int                 i;
 
4364
    PTTYINFO            pTTYInfo;
 
4365
 
 
4366
 
 
4367
    pTTYInfo = gpTTYInfo;
 
4368
 
 
4369
    ret = FALSE;
 
4370
    switch (msg) {
 
4371
        
 
4372
    case WM_INITDIALOG:
 
4373
        /* Fit dialog to window. */
 
4374
        GetWindowRect (hWnd, &rc);
 
4375
        height = rc.bottom - rc.top;
 
4376
        GetClientRect (GetParent (hWnd), &rc);
 
4377
        SetWindowPos (hWnd, HWND_TOP, 0, 0, rc.right, height,
 
4378
                        SWP_NOZORDER | SWP_NOACTIVATE);
 
4379
 
 
4380
        /* Count child windows.*/
 
4381
        btnCount = 0;
 
4382
        for (hCld = GetWindow (hWnd, GW_CHILD);
 
4383
             hCld;
 
4384
             hCld = GetWindow (hCld, GW_HWNDNEXT))
 
4385
                ++btnCount;
 
4386
 
 
4387
        /* Allocate a list of previous child procs. */
 
4388
        if (pTTYInfo->toolBarBtns != NULL)
 
4389
            MemFree (pTTYInfo->toolBarBtns);
 
4390
        pTTYInfo->toolBarBtns = MemAlloc (sizeof (BtnList) * (btnCount + 1));
 
4391
        
 
4392
        /* Subclass all child windows. */
 
4393
        for (i = 0, hCld = GetWindow (hWnd, GW_CHILD);
 
4394
            hCld;
 
4395
            ++i, hCld = GetWindow (hCld, GW_HWNDNEXT)) {
 
4396
            pTTYInfo->toolBarBtns[i].wndID = GET_ID (hCld);
 
4397
            pTTYInfo->toolBarBtns[i].wndProc =
 
4398
                                        (WNDPROC)(LONG_PTR)MyGetWindowLongPtr (hCld,
 
4399
                                        GWLP_WNDPROC);
 
4400
            MySetWindowLongPtr (hCld, GWLP_WNDPROC, (void *)(LONG_PTR)TBBtnProc);
 
4401
        }
 
4402
        pTTYInfo->toolBarBtns[i].wndID = 0;
 
4403
        pTTYInfo->toolBarBtns[i].wndProc = NULL;
 
4404
 
 
4405
        ret = FALSE;
 
4406
        break;
 
4407
        
 
4408
 
 
4409
    case WM_COMMAND:
 
4410
        if (wParam >= KS_RANGESTART && wParam <= KS_RANGEEND){
 
4411
            ProcessMenuItem (GetParent (hWnd), wParam);
 
4412
            /* Set input focus back to parent. */
 
4413
            SetFocus (GetParent (hWnd));
 
4414
            ret = TRUE;
 
4415
            break;
 
4416
        }
 
4417
        break;
 
4418
 
 
4419
#ifdef  WIN32
 
4420
    case WM_CTLCOLORBTN:
 
4421
#else
 
4422
    case WM_CTLCOLOR:
 
4423
#endif
 
4424
        if (HIWORD (lParam) == CTLCOLOR_DLG) {
 
4425
            if(pTTYInfo->hTBBrush != NULL){
 
4426
                DeleteObject(pTTYInfo->hTBBrush);
 
4427
                pTTYInfo->hTBBrush = NULL;
 
4428
            }
 
4429
 
 
4430
            hBrush = CreateSolidBrush (GetSysColor (COLOR_ACTIVEBORDER));
 
4431
            return ((BOOL)!!(pTTYInfo->hTBBrush = hBrush));
 
4432
        }
 
4433
    }
 
4434
    return (ret);
 
4435
}
 
4436
 
 
4437
 
 
4438
/*
 
4439
 * Subclass toolbar button windows.
 
4440
 *
 
4441
 * These buttons will automatically return the input focus to
 
4442
 * the toolbar's parent
 
4443
 */
 
4444
LRESULT FAR PASCAL __export
 
4445
TBBtnProc (HWND hBtn, UINT uMsg, WPARAM wParam, LPARAM lParam)
 
4446
{
 
4447
    PTTYINFO            pTTYInfo;
 
4448
    HWND                hPrnt;
 
4449
    int                 i;
 
4450
    WORD                id;
 
4451
    LRESULT             ret;
 
4452
    WNDPROC             wndProc;
 
4453
 
 
4454
 
 
4455
    /*
 
4456
     * Find previous window proc.
 
4457
     */
 
4458
    pTTYInfo = gpTTYInfo;
 
4459
    id = GET_ID (hBtn);
 
4460
    for (i = 0; pTTYInfo->toolBarBtns[i].wndID != 0; ++i)
 
4461
        if (pTTYInfo->toolBarBtns[i].wndID == id)
 
4462
            goto FoundWindow;
 
4463
    /* Whoops!  Didn't find window, don't know how to pass message. */
 
4464
    return (0);
 
4465
 
 
4466
 
 
4467
FoundWindow:
 
4468
    wndProc = pTTYInfo->toolBarBtns[i].wndProc;
 
4469
 
 
4470
 
 
4471
 
 
4472
    if (uMsg == WM_LBUTTONUP || uMsg == WM_MBUTTONUP || uMsg == WM_RBUTTONUP) {
 
4473
        /*
 
4474
         * On mouse button up restore input focus to IDC_RESPONCE, which
 
4475
         * processes keyboard input.
 
4476
         */
 
4477
        ret = CallWindowProc (wndProc, hBtn, uMsg, wParam, lParam);
 
4478
        hPrnt = GetParent (GetParent (hBtn));
 
4479
        if (hPrnt)
 
4480
            SetFocus (hPrnt);
 
4481
        return (ret);
 
4482
    }
 
4483
 
 
4484
    return (CallWindowProc (wndProc, hBtn, uMsg, wParam, lParam));
 
4485
}
 
4486
 
 
4487
 
 
4488
/*
 
4489
 * return bitmap of allowed Edit Menu items
 
4490
 */
 
4491
LOCAL UINT
 
4492
UpdateEditAllowed(HWND hWnd)
 
4493
{
 
4494
    PTTYINFO            pTTYInfo;
 
4495
    UINT                fAccel = EM_NONE;
 
4496
 
 
4497
    if((pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO)) != NULL){
 
4498
        if(EditPasteAvailable())
 
4499
          fAccel |= (EM_PST | EM_PST_ABORT);
 
4500
        else if(IsClipboardFormatAvailable (CF_UNICODETEXT) && gPasteEnabled)
 
4501
          fAccel |= EM_PST;
 
4502
 
 
4503
        if(SelAvailable()){
 
4504
            fAccel |= (EM_CP | EM_CP_APPEND);
 
4505
        }
 
4506
        else{
 
4507
            if(gAllowCut)
 
4508
              fAccel |= EM_CUT;
 
4509
 
 
4510
            if(gAllowCopy)
 
4511
              fAccel |= (EM_CP | EM_CP_APPEND);
 
4512
        }
 
4513
 
 
4514
        if (pTTYInfo->menuItems[KS_WHEREIS - KS_RANGESTART].miActive)
 
4515
          fAccel |= EM_FIND;
 
4516
    }
 
4517
    return(fAccel);
 
4518
}
 
4519
 
 
4520
 
 
4521
#ifdef ACCELERATORS
 
4522
#ifdef ACCELERATORS_OPT
 
4523
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
4524
 *
 
4525
 *      Accelorator key routines.
 
4526
 *
 
4527
 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
 
4528
LOCAL void
 
4529
AccelCtl (HWND hWnd, int ctl, BOOL saveChange)
 
4530
{
 
4531
    PTTYINFO            pTTYInfo;
 
4532
    BOOL                load, changed;
 
4533
 
 
4534
 
 
4535
    pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
 
4536
    if (pTTYInfo == NULL)
 
4537
        return;
 
4538
 
 
4539
    switch (ctl) {
 
4540
      case ACCEL_LOAD :
 
4541
        load = TRUE;
 
4542
        break;
 
4543
      case ACCEL_UNLOAD :
 
4544
        load = FALSE;
 
4545
        break;
 
4546
      case ACCEL_TOGGLE :
 
4547
        load = pTTYInfo->hAccel == NULL;
 
4548
        break;
 
4549
      default :
 
4550
        load = FALSE;
 
4551
        break;
 
4552
    }
 
4553
 
 
4554
    changed = FALSE;
 
4555
    if (load && pTTYInfo->hAccel == NULL) {
 
4556
        /* Load em up. */
 
4557
        pTTYInfo->hAccel = LoadAccelerators (ghInstance,
 
4558
                                        MAKEINTRESOURCE (IDR_ACCEL_PINE));
 
4559
        changed = TRUE;
 
4560
    }
 
4561
    else if(!load && pTTYInfo->hAccel) {
 
4562
        /* unload em. */
 
4563
        FreeResource (pTTYInfo->hAccel);
 
4564
        pTTYInfo->hAccel = NULL;
 
4565
        changed = TRUE;
 
4566
    }
 
4567
 
 
4568
    if (changed && saveChange)
 
4569
        DidResize (pTTYInfo);
 
4570
}
 
4571
#endif
 
4572
 
 
4573
 
 
4574
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
4575
 *
 
4576
 *      Accelorator key routines.
 
4577
 *
 
4578
 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
 
4579
LOCAL void
 
4580
AccelManage (HWND hWnd, long accels)
 
4581
{
 
4582
    PTTYINFO            pTTYInfo;
 
4583
    ACCEL               accelarray[EM_MAX_ACCEL];
 
4584
    int                 n;
 
4585
    static ACCEL am_cp = {
 
4586
        FVIRTKEY | FCONTROL | FSHIFT | FNOINVERT, 'C', IDM_EDIT_COPY
 
4587
    };
 
4588
    static ACCEL am_cp_append = {
 
4589
        FVIRTKEY | FCONTROL | FALT | FNOINVERT, 'C', IDM_EDIT_COPY_APPEND
 
4590
    };
 
4591
    static ACCEL am_find = {
 
4592
        FVIRTKEY | FCONTROL | FSHIFT | FNOINVERT, 'F', IDM_MI_WHEREIS
 
4593
    };
 
4594
    static ACCEL am_pst = {
 
4595
        FVIRTKEY | FCONTROL | FSHIFT | FNOINVERT, 'V', IDM_EDIT_PASTE
 
4596
    };
 
4597
    static ACCEL am_pst_abort = {
 
4598
        FVIRTKEY | FCONTROL | FALT | FNOINVERT, 'V', IDM_EDIT_CANCEL_PASTE
 
4599
    };
 
4600
    static ACCEL am_cut = {
 
4601
        FVIRTKEY | FCONTROL | FSHIFT | FNOINVERT, 'X', IDM_EDIT_CUT
 
4602
    };
 
4603
 
 
4604
    pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
 
4605
    if (pTTYInfo == NULL || pTTYInfo->fAccel == (UINT)accels)
 
4606
        return;
 
4607
 
 
4608
    if(pTTYInfo->hAccel){
 
4609
        DestroyAcceleratorTable(pTTYInfo->hAccel);
 
4610
        pTTYInfo->hAccel = NULL;
 
4611
        pTTYInfo->fAccel = EM_NONE;
 
4612
    }
 
4613
 
 
4614
    n = 0;
 
4615
 
 
4616
    if(accels & EM_CP)
 
4617
      accelarray[n++] = am_cp;
 
4618
 
 
4619
    if(accels & EM_CP_APPEND)
 
4620
      accelarray[n++] = am_cp_append;
 
4621
 
 
4622
    if(accels & EM_FIND)
 
4623
      accelarray[n++] = am_find;
 
4624
 
 
4625
    if(accels & EM_PST)
 
4626
      accelarray[n++] = am_pst;
 
4627
 
 
4628
    if(accels & EM_PST_ABORT)
 
4629
      accelarray[n++] = am_pst_abort;
 
4630
 
 
4631
    if(accels & EM_CUT)
 
4632
      accelarray[n++] = am_cut;
 
4633
 
 
4634
    /* Load em up. */
 
4635
    if(n && (pTTYInfo->hAccel = CreateAcceleratorTable(accelarray, n)))
 
4636
      pTTYInfo->fAccel = accels;
 
4637
    else
 
4638
      pTTYInfo->fAccel = EM_NONE;
 
4639
}
 
4640
 
 
4641
 
 
4642
LOCAL void
 
4643
UpdateAccelerators (HWND hWnd)
 
4644
{
 
4645
    AccelManage (hWnd, UpdateEditAllowed(hWnd));
 
4646
}
 
4647
#endif
 
4648
 
 
4649
 
 
4650
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
4651
 *
 
4652
 *                  Mouse Selection routines
 
4653
 *
 
4654
 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
 
4655
 
 
4656
LOCAL BOOL      SelSelected = FALSE;
 
4657
LOCAL BOOL      SelTracking = FALSE;
 
4658
LOCAL int       SelAnchorRow;
 
4659
LOCAL int       SelAnchorCol;
 
4660
LOCAL int       SelPointerRow;
 
4661
LOCAL int       SelPointerCol;
 
4662
typedef struct {
 
4663
    TCHAR       *pRow;
 
4664
    int         len;
 
4665
} CopyRow;
 
4666
 
 
4667
 
 
4668
LOCAL void
 
4669
SelRSet (int oStart, int oEnd)
 
4670
{
 
4671
    CharAttrib  *pca;
 
4672
 
 
4673
    for (pca = gpTTYInfo->pAttrib + oStart; oStart < oEnd; ++pca, ++oStart)
 
4674
      pca->style |= CHAR_ATTR_SEL;
 
4675
}
 
4676
 
 
4677
 
 
4678
LOCAL void
 
4679
SelRClear (int oStart, int oEnd)
 
4680
{
 
4681
    CharAttrib  *pca;
 
4682
 
 
4683
    for (pca = gpTTYInfo->pAttrib + oStart; oStart < oEnd; ++pca, ++oStart)
 
4684
        pca->style &= ~CHAR_ATTR_SEL;
 
4685
}
 
4686
 
 
4687
 
 
4688
LOCAL void
 
4689
SelRInvalidate (int oStart, int oEnd)
 
4690
{
 
4691
    RECT        rect;
 
4692
    int         sRow, sCol;
 
4693
    int         eRow, eCol;
 
4694
 
 
4695
    sRow = oStart / gpTTYInfo->actNColumn;
 
4696
    sCol = oStart % gpTTYInfo->actNColumn;
 
4697
    eRow = oEnd   / gpTTYInfo->actNColumn;
 
4698
    eCol = oEnd   % gpTTYInfo->actNColumn;
 
4699
 
 
4700
    rect.top = (sRow * gpTTYInfo->yChar) + gpTTYInfo->yOffset;
 
4701
    rect.bottom = ((eRow+1) * gpTTYInfo->yChar) + gpTTYInfo->yOffset;
 
4702
    if (sRow == eRow) {
 
4703
        rect.left = (sCol * gpTTYInfo->xChar) + gpTTYInfo->xOffset;
 
4704
        rect.right = ((eCol+1) * gpTTYInfo->xChar) + gpTTYInfo->xOffset;
 
4705
    } else {
 
4706
        rect.left = gpTTYInfo->xOffset;
 
4707
        rect.right = (gpTTYInfo->actNColumn * gpTTYInfo->xChar) +
 
4708
                        gpTTYInfo->xOffset;
 
4709
    }
 
4710
    InvalidateRect (ghTTYWnd, &rect, FALSE);
 
4711
}
 
4712
 
 
4713
 
 
4714
/*
 
4715
 * Start a mouse selection.
 
4716
 */
 
4717
LOCAL void
 
4718
SelStart (int nRow, int nColumn)
 
4719
{
 
4720
    SelClear ();
 
4721
    SelTracking = TRUE;
 
4722
    SelSelected = TRUE;
 
4723
    SelPointerRow = SelAnchorRow = nRow;
 
4724
    SelPointerCol = SelAnchorCol = nColumn;
 
4725
    return;
 
4726
}
 
4727
 
 
4728
 
 
4729
/*
 
4730
 * Finish a mouse selection.
 
4731
 */
 
4732
LOCAL void
 
4733
SelFinish (int nRow, int nColumn)
 
4734
{
 
4735
    if (nRow == SelAnchorRow && nColumn == SelAnchorCol) {
 
4736
        /* Mouse up in same place it went down - no selection. */
 
4737
        SelClear ();
 
4738
    }
 
4739
    else {
 
4740
        /* Update screen selection and set final position of mouse
 
4741
         * then turn of mouse tracking.  Selection remains in effect
 
4742
         * until SelClear is called. */
 
4743
        SelTrackMouse (nRow, nColumn);
 
4744
        SelTracking = FALSE;
 
4745
    }
 
4746
}
 
4747
 
 
4748
 
 
4749
LOCAL void
 
4750
SelClear (void)
 
4751
{
 
4752
    int         a, p;
 
4753
    int         s, e;
 
4754
 
 
4755
    if (!SelSelected)
 
4756
        return;
 
4757
 
 
4758
    /* Convert the anchor and point coordinates to offsets then
 
4759
     * order the offsets. */
 
4760
    a = (SelAnchorRow * gpTTYInfo->actNColumn) + SelAnchorCol;
 
4761
    p = (SelPointerRow * gpTTYInfo->actNColumn) + SelPointerCol;
 
4762
    if (a < p) {
 
4763
        s = a;
 
4764
        e = p;
 
4765
    } else {
 
4766
        s = p;
 
4767
        e = a;
 
4768
    }
 
4769
 
 
4770
    /* Clear selected attribute of those cells in range. */
 
4771
    SelRClear (s, e);
 
4772
    SelRInvalidate (s, e);
 
4773
    SelSelected = FALSE;
 
4774
    SelTracking = FALSE;
 
4775
}
 
4776
 
 
4777
 
 
4778
/*
 
4779
 * Update the position of the mouse point.
 
4780
 */
 
4781
LOCAL void
 
4782
SelTrackXYMouse (int xPos, int yPos)
 
4783
{
 
4784
    int         nRow;
 
4785
    int         nColumn;
 
4786
 
 
4787
    nColumn = (xPos - gpTTYInfo->xOffset) / gpTTYInfo->xChar;
 
4788
    nRow = (yPos - gpTTYInfo->yOffset) / gpTTYInfo->yChar;
 
4789
 
 
4790
    SelTrackMouse (nRow, nColumn);
 
4791
}
 
4792
 
 
4793
 
 
4794
/*
 
4795
 * Update the position of the mouse point.
 
4796
 */
 
4797
LOCAL void
 
4798
SelTrackMouse (int nRow, int nColumn)
 
4799
{
 
4800
    int         a, p, n;
 
4801
 
 
4802
    if (!SelTracking)
 
4803
        return;
 
4804
 
 
4805
    /* Constrain the cel position to be on the screen.  But allow
 
4806
     * for the Column to be one past the right edge of the screen so
 
4807
     * the user can select the right most cel of a row. */
 
4808
    nColumn = MAX(0, nColumn);
 
4809
    nColumn = MIN(gpTTYInfo->actNColumn, nColumn);
 
4810
    nRow = MAX(0, nRow);
 
4811
    nRow = MIN(gpTTYInfo->actNRow-1, nRow);
 
4812
 
 
4813
 
 
4814
    /* Convert the anchor, previous mouse position, and new mouse
 
4815
     * position to offsets. */
 
4816
    a = (SelAnchorRow * gpTTYInfo->actNColumn) + SelAnchorCol;
 
4817
    p = (SelPointerRow * gpTTYInfo->actNColumn) + SelPointerCol;
 
4818
    n = (nRow * gpTTYInfo->actNColumn) + nColumn;
 
4819
 
 
4820
    /* If previous position same as current position, do nothing. */
 
4821
    if (p == n)
 
4822
        return;
 
4823
 
 
4824
    /* there are six possible orderings of the points, each with
 
4825
     * a different action:
 
4826
     *  order           clear           set             redraw
 
4827
     *  n p a                           n - p           n - p
 
4828
     *  p n a           p - n                           p - n
 
4829
     *  p a n           p - a           a - n           p - n
 
4830
     *  a p n                           p - n           p - n
 
4831
     *  a n p           n - p                           n - p
 
4832
     *  n a p           a - p           n - a           n - p
 
4833
     */
 
4834
    if (p < a) {
 
4835
        if (n < a) {
 
4836
            if (n < p) {
 
4837
                SelRSet (n, p);
 
4838
                SelRInvalidate (n, p);
 
4839
            } else {
 
4840
                SelRClear (p, n);
 
4841
                SelRInvalidate (p, n);
 
4842
            }
 
4843
        } else {
 
4844
            SelRClear (p, a);
 
4845
            SelRSet (a, n);
 
4846
            SelRInvalidate (p, n);
 
4847
        }
 
4848
    } else {
 
4849
        if (n > a) {
 
4850
            if (n > p) {
 
4851
                SelRSet (p, n);
 
4852
                SelRInvalidate (p, n);
 
4853
            } else {
 
4854
                SelRClear (n, p);
 
4855
                SelRInvalidate (n, p);
 
4856
            }
 
4857
        } else {
 
4858
            SelRClear (a, p);
 
4859
            SelRSet (n, a);
 
4860
            SelRInvalidate (n, p);
 
4861
        }
 
4862
    }
 
4863
 
 
4864
    /* Set new pointer. */
 
4865
    SelPointerRow = nRow;
 
4866
    SelPointerCol = nColumn;
 
4867
}
 
4868
 
 
4869
 
 
4870
LOCAL BOOL
 
4871
SelAvailable (void)
 
4872
{
 
4873
    return (SelSelected);
 
4874
}
 
4875
 
 
4876
 
 
4877
/*
 
4878
 * Copy screen data to clipboard.  Actually appends data from screen to
 
4879
 * existing handle so as we can implement a "Copy Append" to append to
 
4880
 * existing clipboard data.
 
4881
 *
 
4882
 * The screen does not have real line terminators.  We decide where the
 
4883
 * actual screen data ends by scanning the line (row) from end backwards
 
4884
 * to find the first non-space.
 
4885
 *
 
4886
 * I don't know how many bytes of data I'll be appending to the clipboard.
 
4887
 * So I implemented in two passes.  The first finds all the row starts
 
4888
 * and length while the second copies the data.
 
4889
 */
 
4890
LOCAL void
 
4891
SelDoCopy (HANDLE hCB, DWORD lenCB)
 
4892
{
 
4893
    HANDLE              newCB;          /* Used in reallocation. */
 
4894
    TCHAR               *pCB;           /* Points to CB data. */        
 
4895
    TCHAR               *p2;            /* Temp pointer to screen data. */
 
4896
    int                 sRow, eRow;     /* Start and End Rows. */
 
4897
    int                 sCol, eCol;     /* Start and End columns. */
 
4898
    int                 row, c1, c2;    /* temp row and column indexes. */
 
4899
    int                 totalLen;       /* total len of new data. */
 
4900
    CopyRow             *rowTable, *rp; /* pointers to table of rows. */
 
4901
    BOOL                noLastCRLF = FALSE;
 
4902
 
 
4903
 
 
4904
    if (OpenClipboard (ghTTYWnd)) {             /* ...and we get the CB. */
 
4905
      if (EmptyClipboard ()) {          /* ...and clear previous CB.*/
 
4906
 
 
4907
 
 
4908
        /* Find the start and end row and column. */
 
4909
        if ( (SelAnchorRow * gpTTYInfo->actNColumn) + SelAnchorCol <
 
4910
             (SelPointerRow * gpTTYInfo->actNColumn) + SelPointerCol) {
 
4911
            sRow = SelAnchorRow;
 
4912
            sCol = SelAnchorCol;
 
4913
            eRow = SelPointerRow;
 
4914
            eCol = SelPointerCol;
 
4915
        }
 
4916
        else {
 
4917
            sRow = SelPointerRow;
 
4918
            sCol = SelPointerCol;
 
4919
            eRow = SelAnchorRow;
 
4920
            eCol = SelAnchorCol;
 
4921
        }
 
4922
 
 
4923
        /* Allocate a table in which we store info on rows. */
 
4924
        rowTable = (CopyRow *) MemAlloc (sizeof (CopyRow) * (eRow-sRow+1));
 
4925
        if (rowTable == NULL)
 
4926
            goto Fail1;
 
4927
 
 
4928
        /* Find the start and length of each row. */
 
4929
        totalLen = 0;
 
4930
        for (row = sRow, rp = rowTable; row <= eRow; ++row, ++rp) {
 
4931
            /* Find beginning and end columns, which depends on if
 
4932
             * this is the first or last row in the selection. */
 
4933
            c1 = (row == sRow ? sCol : 0);
 
4934
            c2 = (row == eRow ? eCol : gpTTYInfo->actNColumn);
 
4935
 
 
4936
            /* Calculate pointer to beginning of this line. */
 
4937
            rp->pRow = gpTTYInfo->pScreen +
 
4938
                    ((row * gpTTYInfo->actNColumn) + c1);
 
4939
 
 
4940
            /* Back down from end column to find first non space.
 
4941
             * noLastCRLF indicates if it looks like the selection
 
4942
             * should include a CRLF on the end of the line.  It
 
4943
             * gets set for each line, but only the setting for the
 
4944
             * last line in the selection is remembered (which is all
 
4945
             * we're interested in). */
 
4946
            p2 = gpTTYInfo->pScreen +
 
4947
                    ((row * gpTTYInfo->actNColumn) + c2);
 
4948
            noLastCRLF = TRUE;
 
4949
            while (c2 > c1) {
 
4950
                if (*(p2-1) != (TCHAR)' ')
 
4951
                    break;
 
4952
                noLastCRLF = FALSE;
 
4953
                --c2;
 
4954
                --p2;
 
4955
            }
 
4956
 
 
4957
            /* Calculate size of line, then increment totalLen plus 2 for
 
4958
             * the CRLF which will terminate each line. */
 
4959
            rp->len = c2 - c1;
 
4960
            totalLen += rp->len + 2;
 
4961
        }
 
4962
 
 
4963
        /* Reallocate the memory block.  Add one byte for null terminator. */
 
4964
        newCB = GlobalReAlloc (hCB, (lenCB + totalLen + 1)*sizeof(TCHAR), 0);
 
4965
        if (newCB == NULL)
 
4966
            goto Fail2;
 
4967
        hCB = newCB;
 
4968
 
 
4969
        pCB = GlobalLock (hCB);
 
4970
        if (pCB == NULL)
 
4971
            goto Fail2;
 
4972
 
 
4973
        /* Append each of the rows, deliminated by a CRLF. */
 
4974
        pCB += lenCB;
 
4975
        for (row = sRow, rp = rowTable; row <= eRow; ++row, ++rp) {
 
4976
            if (rp->len > 0) {
 
4977
                memcpy (pCB, rp->pRow, rp->len * sizeof(TCHAR));
 
4978
                pCB += rp->len;
 
4979
            }
 
4980
            if (row < eRow || !noLastCRLF) {
 
4981
                *pCB++ = (TCHAR)ASCII_CR;
 
4982
                *pCB++ = (TCHAR)ASCII_LF;
 
4983
            }
 
4984
        }
 
4985
        *pCB = (TCHAR)'\0';                     /* Null terminator. */
 
4986
        MemFree (rowTable);
 
4987
        GlobalUnlock (hCB);
 
4988
 
 
4989
        /* Attempt to pass the data to the clipboard, then release clipboard
 
4990
         * and exit function. */
 
4991
        if (SetClipboardData (CF_UNICODETEXT, hCB) == NULL)
 
4992
                      /* Failed!  Free the data. */
 
4993
                      GlobalFree (hCB);
 
4994
        CloseClipboard ();
 
4995
      }
 
4996
    }
 
4997
    return;
 
4998
 
 
4999
 
 
5000
        /* Error exit. */
 
5001
Fail2:  MemFree (rowTable);
 
5002
Fail1:  GlobalFree (hCB);
 
5003
        CloseClipboard ();
 
5004
        return;
 
5005
}
 
5006
 
 
5007
 
 
5008
 
 
5009
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
5010
 *
 
5011
 *                  Upper Layer Screen routines.
 
5012
 *
 
5013
 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
 
5014
 
 
5015
/*
 
5016
 * Flush the write accumulator buffer.
 
5017
 */
 
5018
LOCAL void
 
5019
FlushWriteAccum (void)
 
5020
{
 
5021
    if (gpTTYInfo->writeAccumCount > 0) {
 
5022
        WriteTTYText (ghTTYWnd, gpTTYInfo->writeAccum,
 
5023
                                        gpTTYInfo->writeAccumCount);
 
5024
        gpTTYInfo->writeAccumCount = 0;
 
5025
    }
 
5026
}
 
5027
 
 
5028
 
 
5029
/*
 
5030
 * Set window's title
 
5031
 */
 
5032
void
 
5033
mswin_settitle(char *utf8_title)
 
5034
{
 
5035
    TCHAR buf[256];
 
5036
    LPTSTR lptstr_title;
 
5037
 
 
5038
    lptstr_title = utf8_to_lptstr(utf8_title);
 
5039
    _sntprintf(buf, 256, TEXT("%.*s - Alpine"), 80, lptstr_title);
 
5040
    fs_give((void **) &lptstr_title);
 
5041
 
 
5042
    SetWindowText(ghTTYWnd, buf);
 
5043
}
 
5044
 
 
5045
 
 
5046
/*
 
5047
 * Return the application instance.
 
5048
 */
 
5049
WINHAND
 
5050
mswin_gethinstance ()
 
5051
{
 
5052
    return ((WINHAND)ghInstance);
 
5053
}
 
5054
 
 
5055
 
 
5056
WINHAND
 
5057
mswin_gethwnd ()
 
5058
{
 
5059
    return ((WINHAND)ghTTYWnd);
 
5060
}
 
5061
 
 
5062
 
 
5063
/*
 
5064
 * destroy splash screen
 
5065
 */
 
5066
void
 
5067
mswin_killsplash()
 
5068
{
 
5069
    if(ghSplashWnd != NULL){
 
5070
        DestroyWindow(ghSplashWnd);
 
5071
        ghSplashWnd = NULL;
 
5072
    }
 
5073
}
 
5074
 
 
5075
 
 
5076
/*
 
5077
 *      Called to get mouse event.
 
5078
 */
 
5079
int
 
5080
mswin_getmouseevent (MEvent * pMouse)
 
5081
{
 
5082
        return (MQGet (pMouse));
 
5083
}
 
5084
 
 
5085
 
 
5086
/*
 
5087
 * Make a pop-up menu and track it
 
5088
 */
 
5089
int
 
5090
mswin_popup(MPopup *members)
 
5091
{
 
5092
    HMENU   hMenu;
 
5093
    POINT   point;
 
5094
    MPopup *mp;
 
5095
    int     n = 1;
 
5096
 
 
5097
    if(members && (hMenu = CreatePopupMenu())){
 
5098
 
 
5099
        PopupConfig(hMenu, members, &n);
 
5100
        if(GetCursorPos(&point)
 
5101
           && (n = TrackPopupMenu(hMenu,
 
5102
                                  TPM_LEFTALIGN | TPM_TOPALIGN
 
5103
                                    | TPM_RIGHTBUTTON | TPM_LEFTBUTTON
 
5104
                                    | TPM_NONOTIFY | TPM_RETURNCMD,
 
5105
                                  point.x, point.y, 0, ghTTYWnd, NULL))
 
5106
           && (mp = PopupId(members, n))){
 
5107
            /* Find the member with the internal.id of n */
 
5108
            n = mp->internal.id - 1;    /* item's "selectable" index */
 
5109
            switch(mp->type){
 
5110
              case tQueue :
 
5111
                CQAdd (mp->data.val, 0);
 
5112
                break;
 
5113
 
 
5114
              case tMessage :
 
5115
                SendMessage(ghTTYWnd, WM_COMMAND, mp->data.msg, 0);
 
5116
                break;
 
5117
 
 
5118
              default :
 
5119
                break;
 
5120
            }
 
5121
        }
 
5122
        else
 
5123
          n = -1;               /* error or nothing selected; same diff */
 
5124
 
 
5125
        DestroyMenu(hMenu);
 
5126
    }
 
5127
    else
 
5128
      n = -1;                   /* error */
 
5129
 
 
5130
    return(n);
 
5131
}
 
5132
 
 
5133
 
 
5134
LOCAL void
 
5135
PopupConfig(HMENU hMenu, MPopup *members, int *n)
 
5136
{
 
5137
    MENUITEMINFO  mitem;
 
5138
    int           index;
 
5139
    TCHAR         tcbuf[256];
 
5140
 
 
5141
    for(index = 0; members->type != tTail; members++, index++){
 
5142
        memset(&mitem, 0, sizeof(MENUITEMINFO));
 
5143
        mitem.cbSize = sizeof(MENUITEMINFO);
 
5144
        mitem.fMask  = MIIM_TYPE;
 
5145
 
 
5146
        if(members->type == tSubMenu){
 
5147
            mitem.fMask |= MIIM_SUBMENU;
 
5148
            mitem.fType  = MFT_STRING;
 
5149
            if(mitem.hSubMenu = CreatePopupMenu()){
 
5150
                /* members->label.string is still just a char * */
 
5151
                _sntprintf(tcbuf, sizeof(tcbuf)/sizeof(TCHAR),
 
5152
                           TEXT("%S"), members->label.string);
 
5153
                mitem.dwTypeData = tcbuf;
 
5154
                mitem.cch        = (UINT)_tcslen(tcbuf);
 
5155
                InsertMenuItem(hMenu, index, TRUE, &mitem);
 
5156
 
 
5157
                PopupConfig(mitem.hSubMenu, members->data.submenu, n);
 
5158
            }
 
5159
        }
 
5160
        else{
 
5161
            switch(members->type){
 
5162
              case tSeparator :
 
5163
                mitem.fType = MFT_SEPARATOR;
 
5164
                break;
 
5165
 
 
5166
              default :
 
5167
                mitem.fMask      |= MIIM_ID;
 
5168
                mitem.wID         = members->internal.id = (*n)++;
 
5169
                switch(members->label.style){
 
5170
                  case lChecked :
 
5171
                    mitem.fMask  |= MIIM_STATE;
 
5172
                    mitem.fState  = MFS_CHECKED;
 
5173
                    break;
 
5174
 
 
5175
                  case lDisabled :
 
5176
                    mitem.fMask  |= MIIM_STATE;
 
5177
                    mitem.fState  = MFS_GRAYED;
 
5178
                    break;
 
5179
 
 
5180
                  case lNormal :
 
5181
                  default :
 
5182
                    break;
 
5183
                }
 
5184
 
 
5185
                mitem.fType      = MFT_STRING;
 
5186
                _sntprintf(tcbuf, sizeof(tcbuf)/sizeof(TCHAR),
 
5187
                           TEXT("%S"), members->label.string);
 
5188
                mitem.dwTypeData = tcbuf;
 
5189
                mitem.cch        = (UINT)_tcslen(tcbuf);
 
5190
                break;
 
5191
            }
 
5192
 
 
5193
            InsertMenuItem(hMenu, index, TRUE, &mitem);
 
5194
        }
 
5195
    }
 
5196
}
 
5197
 
 
5198
 
 
5199
LOCAL MPopup *
 
5200
PopupId(MPopup *members, int id)
 
5201
{
 
5202
    MPopup *mp;
 
5203
 
 
5204
    for(; members->type != tTail; members++)
 
5205
      switch(members->type){
 
5206
        case tSubMenu :
 
5207
          if(mp = PopupId(members->data.submenu, id))
 
5208
            return(mp);
 
5209
 
 
5210
          break;
 
5211
 
 
5212
        case tSeparator :
 
5213
          break;
 
5214
 
 
5215
        default :
 
5216
          if(members->internal.id == id)
 
5217
            return(members);
 
5218
 
 
5219
          break;
 
5220
      }
 
5221
 
 
5222
    return(NULL);
 
5223
}
 
5224
 
 
5225
 
 
5226
/*
 
5227
 * Make a pop-up offering Copy/Cut/Paste menu and track it
 
5228
 */
 
5229
LOCAL BOOL
 
5230
CopyCutPopup(HWND hWnd, UINT fAllowed)
 
5231
{
 
5232
    MENUITEMINFO  mitem;
 
5233
    HMENU         hMenu;
 
5234
    POINT         point;
 
5235
    BOOL          rv = FALSE;
 
5236
    int           n = -1;
 
5237
 
 
5238
    /*
 
5239
     * If nothing to do just silently return
 
5240
     */
 
5241
    if(fAllowed != EM_NONE && (hMenu = CreatePopupMenu())){
 
5242
        if(fAllowed & EM_CUT){
 
5243
            /* Insert a "Copy" option */
 
5244
            memset(&mitem, 0, sizeof(MENUITEMINFO));
 
5245
            mitem.cbSize = sizeof(MENUITEMINFO);
 
5246
            mitem.fMask = MIIM_TYPE | MIIM_ID;
 
5247
            mitem.wID = IDM_EDIT_CUT;
 
5248
            mitem.fType = MFT_STRING;
 
5249
            mitem.dwTypeData = TEXT("Cut");
 
5250
            mitem.cch = 3;
 
5251
            InsertMenuItem(hMenu, ++n, FALSE, &mitem);
 
5252
        }
 
5253
 
 
5254
        if(fAllowed & EM_CP){
 
5255
            /* Insert a "Copy" option */
 
5256
            memset(&mitem, 0, sizeof(MENUITEMINFO));
 
5257
            mitem.cbSize = sizeof(MENUITEMINFO);
 
5258
            mitem.fMask = MIIM_TYPE | MIIM_ID;
 
5259
            mitem.wID = IDM_EDIT_COPY;
 
5260
            mitem.fType = MFT_STRING;
 
5261
            mitem.dwTypeData = TEXT("Copy");
 
5262
            mitem.cch = 4;
 
5263
            InsertMenuItem(hMenu, ++n, FALSE, &mitem);
 
5264
        }
 
5265
 
 
5266
        if(fAllowed & EM_CP_APPEND){
 
5267
            /* Insert a "Copy Append" option */
 
5268
            memset(&mitem, 0, sizeof(MENUITEMINFO));
 
5269
            mitem.cbSize = sizeof(MENUITEMINFO);
 
5270
            mitem.fMask = MIIM_TYPE | MIIM_ID;
 
5271
            mitem.wID = IDM_EDIT_COPY_APPEND;
 
5272
            mitem.fType = MFT_STRING;
 
5273
            mitem.dwTypeData = TEXT("Copy Append");
 
5274
            mitem.cch = 11;
 
5275
            InsertMenuItem(hMenu, ++n, FALSE, &mitem);
 
5276
        }
 
5277
 
 
5278
        if(fAllowed & EM_PST){
 
5279
            /* Insert a "Paste" option */
 
5280
            memset(&mitem, 0, sizeof(MENUITEMINFO));
 
5281
            mitem.cbSize = sizeof(MENUITEMINFO);
 
5282
            mitem.fMask = MIIM_TYPE | MIIM_ID;
 
5283
            mitem.wID = IDM_EDIT_PASTE;
 
5284
            mitem.fType = MFT_STRING;
 
5285
            mitem.dwTypeData = TEXT("Paste");
 
5286
            mitem.cch = 5;
 
5287
            InsertMenuItem(hMenu, ++n, FALSE, &mitem);
 
5288
        }
 
5289
 
 
5290
        if((fAllowed & EM_SEL_ALL) && !(fAllowed & (EM_CP | EM_CP_APPEND))){
 
5291
            /* Insert a "Select All" option */
 
5292
            memset(&mitem, 0, sizeof(MENUITEMINFO));
 
5293
            mitem.cbSize = sizeof(MENUITEMINFO);
 
5294
            mitem.fMask = MIIM_TYPE | MIIM_ID;
 
5295
            mitem.wID = IDM_EDIT_SEL_ALL;
 
5296
            mitem.fType = MFT_STRING;
 
5297
            mitem.dwTypeData = TEXT("Select &All");
 
5298
            mitem.cch = 11;
 
5299
            InsertMenuItem(hMenu, ++n, FALSE, &mitem);
 
5300
        }
 
5301
 
 
5302
        if(n >= 0 && GetCursorPos(&point)){
 
5303
            TrackPopupMenu(hMenu,
 
5304
                           TPM_LEFTALIGN | TPM_TOPALIGN
 
5305
                           | TPM_RIGHTBUTTON | TPM_LEFTBUTTON,
 
5306
                           point.x, point.y, 0, hWnd, NULL);
 
5307
            rv = TRUE;
 
5308
        }
 
5309
 
 
5310
        DestroyMenu(hMenu);
 
5311
    }
 
5312
 
 
5313
    return(rv);
 
5314
}
 
5315
 
 
5316
 
 
5317
 
 
5318
/*
 
5319
 *
 
5320
 */
 
5321
void
 
5322
pico_popup()
 
5323
{
 
5324
    MENUITEMINFO  mitem;
 
5325
    HMENU         hMenu;
 
5326
    POINT         point;
 
5327
    UINT          fAllow;
 
5328
    int           n = -1;
 
5329
 
 
5330
    /*
 
5331
     * If nothing to do just silently return
 
5332
     */
 
5333
    if(hMenu = CreatePopupMenu()){
 
5334
 
 
5335
        if((fAllow = UpdateEditAllowed(ghTTYWnd)) != EM_NONE){
 
5336
            /* Insert a "Cut" option */
 
5337
            memset(&mitem, 0, sizeof(MENUITEMINFO));
 
5338
            mitem.cbSize = sizeof(MENUITEMINFO);
 
5339
            mitem.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
 
5340
            mitem.wID = IDM_EDIT_CUT;
 
5341
            mitem.fState = (fAllow & EM_CUT) ? MFS_ENABLED : MFS_GRAYED;
 
5342
            mitem.fType = MFT_STRING;
 
5343
            mitem.dwTypeData = TEXT("Cut");
 
5344
            mitem.cch = 3;
 
5345
            InsertMenuItem(hMenu, ++n, FALSE, &mitem);
 
5346
 
 
5347
            /* Insert a "Copy" option */
 
5348
            memset(&mitem, 0, sizeof(MENUITEMINFO));
 
5349
            mitem.cbSize = sizeof(MENUITEMINFO);
 
5350
            mitem.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
 
5351
            mitem.wID = IDM_EDIT_COPY;
 
5352
            mitem.fState = (fAllow & EM_CP) ? MFS_ENABLED : MFS_GRAYED;
 
5353
            mitem.fType = MFT_STRING;
 
5354
            mitem.dwTypeData = TEXT("Copy");
 
5355
            mitem.cch = 4;
 
5356
            InsertMenuItem(hMenu, ++n, FALSE, &mitem);
 
5357
 
 
5358
            /* Insert a "Copy Append" option */
 
5359
            memset(&mitem, 0, sizeof(MENUITEMINFO));
 
5360
            mitem.cbSize = sizeof(MENUITEMINFO);
 
5361
            mitem.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
 
5362
            mitem.wID = IDM_EDIT_COPY_APPEND;
 
5363
            mitem.fState = (fAllow & EM_CP_APPEND) ? MFS_ENABLED : MFS_GRAYED;
 
5364
            mitem.fType = MFT_STRING;
 
5365
            mitem.dwTypeData = TEXT("Copy Append");
 
5366
            mitem.cch = 11;
 
5367
            InsertMenuItem(hMenu, ++n, FALSE, &mitem);
 
5368
 
 
5369
            /* Insert a "Paste" option */
 
5370
            memset(&mitem, 0, sizeof(MENUITEMINFO));
 
5371
            mitem.cbSize = sizeof(MENUITEMINFO);
 
5372
            mitem.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
 
5373
            mitem.wID = IDM_EDIT_PASTE;
 
5374
            mitem.fType = MFT_STRING;
 
5375
            mitem.dwTypeData = TEXT("Paste");
 
5376
            mitem.fState = (fAllow & EM_PST) ? MFS_ENABLED : MFS_GRAYED;
 
5377
            mitem.cch = 5;
 
5378
            InsertMenuItem(hMenu, ++n, FALSE, &mitem);
 
5379
        }
 
5380
 
 
5381
        /* Insert a "Select All" option */
 
5382
        memset(&mitem, 0, sizeof(MENUITEMINFO));
 
5383
        mitem.cbSize = sizeof(MENUITEMINFO);
 
5384
        mitem.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
 
5385
        mitem.wID = IDM_EDIT_SEL_ALL;
 
5386
        mitem.fType = MFT_STRING;
 
5387
        mitem.fState = (fAllow & (EM_CP | EM_CP_APPEND))
 
5388
                          ? MFS_GRAYED : MFS_ENABLED;
 
5389
        mitem.dwTypeData = TEXT("Select &All");
 
5390
        mitem.cch = 11;
 
5391
        InsertMenuItem(hMenu, ++n, FALSE, &mitem);
 
5392
 
 
5393
        if(n >= 0 && GetCursorPos(&point))
 
5394
          TrackPopupMenu(hMenu,
 
5395
                         TPM_LEFTALIGN | TPM_TOPALIGN
 
5396
                         | TPM_RIGHTBUTTON | TPM_LEFTBUTTON,
 
5397
                         point.x, point.y, 0, ghTTYWnd, NULL);
 
5398
 
 
5399
        DestroyMenu(hMenu);
 
5400
    }
 
5401
}
 
5402
 
 
5403
 
 
5404
 
 
5405
/*
 
5406
 *
 
5407
 */
 
5408
void
 
5409
mswin_paste_popup()
 
5410
{
 
5411
    MENUITEMINFO  mitem;
 
5412
    HMENU         hMenu;
 
5413
    POINT         point;
 
5414
    UINT          fAllow;
 
5415
    int           n = -1;
 
5416
 
 
5417
    /*
 
5418
     * If nothing to do just silently return
 
5419
     */
 
5420
    if(hMenu = CreatePopupMenu()){
 
5421
 
 
5422
        if((fAllow = UpdateEditAllowed(ghTTYWnd)) != EM_NONE){
 
5423
            /* Insert a "Paste" option */
 
5424
            memset(&mitem, 0, sizeof(MENUITEMINFO));
 
5425
            mitem.cbSize = sizeof(MENUITEMINFO);
 
5426
            mitem.fMask = MIIM_TYPE | MIIM_ID | MIIM_STATE;
 
5427
            mitem.wID = IDM_EDIT_PASTE;
 
5428
            mitem.fType = MFT_STRING;
 
5429
            mitem.dwTypeData = TEXT("Paste");
 
5430
            mitem.fState = (fAllow & EM_PST) ? MFS_ENABLED : MFS_GRAYED;
 
5431
            mitem.cch = 5;
 
5432
            InsertMenuItem(hMenu, ++n, FALSE, &mitem);
 
5433
 
 
5434
            if(n >= 0 && GetCursorPos(&point))
 
5435
              TrackPopupMenu(hMenu,
 
5436
                             TPM_LEFTALIGN | TPM_TOPALIGN
 
5437
                             | TPM_RIGHTBUTTON | TPM_LEFTBUTTON,
 
5438
                             point.x, point.y, 0, ghTTYWnd, NULL);
 
5439
        }
 
5440
 
 
5441
        DestroyMenu(hMenu);
 
5442
    }
 
5443
}
 
5444
 
 
5445
 
 
5446
 
 
5447
void
 
5448
mswin_keymenu_popup()
 
5449
{
 
5450
    HMENU        hBarMenu, hMenu;
 
5451
    MENUITEMINFO mitem;
 
5452
    POINT        point;
 
5453
    int          i, j, n;
 
5454
    TCHAR        tcbuf[256];
 
5455
 
 
5456
    /*
 
5457
     * run thru menubar from left to right and down each list building
 
5458
     * a popup of all active members.  we run down the menu's rather
 
5459
     * than thru the menuItems array so we can preserve order...
 
5460
     */
 
5461
    if((hMenu = CreatePopupMenu())){
 
5462
        if(hBarMenu = GetMenu(ghTTYWnd)){
 
5463
            /* For each possible index, look for matching registered key  */
 
5464
            for(n = 0, i = 1; i <= KS_COUNT; i++)
 
5465
              for(j = 0; j < KS_COUNT; j++)
 
5466
                if(gpTTYInfo->menuItems[j].miIndex == i){
 
5467
                    if(gpTTYInfo->menuItems[j].miActive == TRUE
 
5468
                       && gpTTYInfo->menuItems[j].miLabel){
 
5469
                        mitem.cbSize = sizeof(MENUITEMINFO);
 
5470
                        mitem.fMask =  MIIM_ID | MIIM_STATE | MIIM_TYPE;
 
5471
                        mitem.wID = j + KS_RANGESTART;
 
5472
                        mitem.fState = MFS_ENABLED;
 
5473
                        mitem.fType = MFT_STRING;
 
5474
                        /* miLabel is still plain old char *, not utf8 */
 
5475
                        _sntprintf(tcbuf, sizeof(tcbuf)/sizeof(TCHAR),
 
5476
                                   TEXT("%S"), gpTTYInfo->menuItems[j].miLabel);
 
5477
                        mitem.dwTypeData = tcbuf;
 
5478
                        mitem.cch = (UINT)_tcslen(tcbuf);
 
5479
                        InsertMenuItem(hMenu, n++, TRUE, &mitem);
 
5480
 
 
5481
                        if(j + KS_RANGESTART == IDM_MI_SCREENHELP
 
5482
                            && gHelpCallback){
 
5483
                            mitem.cbSize = sizeof(MENUITEMINFO);
 
5484
                            mitem.fMask =  MIIM_ID | MIIM_STATE | MIIM_TYPE;
 
5485
                            mitem.wID = IDM_HELP;
 
5486
                            mitem.fState = MFS_ENABLED;
 
5487
                            mitem.fType = MFT_STRING;
 
5488
                            _sntprintf(tcbuf, sizeof(tcbuf)/sizeof(TCHAR),
 
5489
                                       TEXT("%S"), "Help in New Window");
 
5490
                            mitem.dwTypeData = tcbuf;
 
5491
                            mitem.cch = (UINT)_tcslen(tcbuf);
 
5492
                            InsertMenuItem(hMenu, n++, TRUE, &mitem);
 
5493
                        }
 
5494
                    }
 
5495
 
 
5496
                    break;
 
5497
                }
 
5498
 
 
5499
            if(n > 0 && GetCursorPos(&point)){
 
5500
                TrackPopupMenu(hMenu,
 
5501
                               TPM_LEFTALIGN | TPM_TOPALIGN
 
5502
                               | TPM_RIGHTBUTTON | TPM_LEFTBUTTON,
 
5503
                               point.x, point.y, 0, ghTTYWnd, NULL);
 
5504
            }
 
5505
        }
 
5506
 
 
5507
        DestroyMenu(hMenu);
 
5508
    }
 
5509
}
 
5510
 
 
5511
 
 
5512
 
 
5513
/*
 
5514
 *
 
5515
 */
 
5516
void
 
5517
mswin_registericon(int row, int id, char *utf8_file)
 
5518
{
 
5519
    LPTSTR    sPathCopy;
 
5520
    HICON     hIcon;
 
5521
    WORD      iIcon;
 
5522
    IconList *pIcon;
 
5523
 
 
5524
    /* Turn this off until it can get tuned */
 
5525
    return;
 
5526
 
 
5527
    /* Already registered? */
 
5528
    for(pIcon = gIconList; pIcon; pIcon = pIcon->next)
 
5529
      if(pIcon->id == id){
 
5530
          pIcon->row = (short)row;
 
5531
          return;
 
5532
      }
 
5533
 
 
5534
    sPathCopy = utf8_to_lptstr(utf8_file);
 
5535
 
 
5536
    if(hIcon = ExtractAssociatedIcon(ghInstance, sPathCopy, &iIcon))
 
5537
      MSWIconAddList(row, id, hIcon);
 
5538
 
 
5539
    fs_give((void **) &sPathCopy);
 
5540
}
 
5541
 
 
5542
 
 
5543
void
 
5544
mswin_destroyicons()
 
5545
{
 
5546
    MSWIconFree(&gIconList);
 
5547
}
 
5548
 
 
5549
 
 
5550
void
 
5551
MSWIconAddList(int row, int id, HICON hIcon)
 
5552
{
 
5553
    IconList **ppIcon;
 
5554
 
 
5555
    for(ppIcon = &gIconList; *ppIcon; ppIcon = &(*ppIcon)->next)
 
5556
      ;
 
5557
 
 
5558
    *ppIcon = (IconList *) MemAlloc (sizeof (IconList));
 
5559
    memset(*ppIcon, 0, sizeof(IconList));
 
5560
    (*ppIcon)->hIcon = hIcon;
 
5561
    (*ppIcon)->id = id;
 
5562
    (*ppIcon)->row = (short)row;
 
5563
}
 
5564
 
 
5565
 
 
5566
int
 
5567
MSWIconPaint(int row, HDC hDC)
 
5568
{
 
5569
    IconList *pIcon;
 
5570
    int       rv = 0;
 
5571
 
 
5572
    for(pIcon = gIconList; pIcon && pIcon->row != row; pIcon = pIcon->next)
 
5573
      ;
 
5574
 
 
5575
    if(pIcon){
 
5576
        /* Invalidate rectange covering singel character. */
 
5577
        DrawIconEx(hDC, 0, (row * gpTTYInfo->yChar) + gpTTYInfo->yOffset,
 
5578
                   pIcon->hIcon, 2 * gpTTYInfo->xChar, gpTTYInfo->yChar,
 
5579
                   0, NULL, DI_NORMAL);
 
5580
 
 
5581
        rv = 1;
 
5582
    }
 
5583
 
 
5584
    return(rv);
 
5585
}
 
5586
 
 
5587
 
 
5588
void
 
5589
MSWIconFree(IconList **ppIcon)
 
5590
{
 
5591
    if(ppIcon && *ppIcon){
 
5592
        if((*ppIcon)->next)
 
5593
          MSWIconFree(&(*ppIcon)->next);
 
5594
 
 
5595
        DestroyIcon((*ppIcon)->hIcon);
 
5596
        MemFree (*ppIcon);
 
5597
        *ppIcon = NULL;
 
5598
    }
 
5599
}
 
5600
 
 
5601
 
 
5602
/*
 
5603
 * Set up debugging stuff.
 
5604
 */
 
5605
void
 
5606
mswin_setdebug (int debug, FILE *debugfile)
 
5607
{
 
5608
    /* Accept new file only if we don't already have a file. */
 
5609
    if (mswin_debugfile == 0) {
 
5610
        mswin_debug = debug;
 
5611
        mswin_debugfile = debugfile;
 
5612
        MemDebug (debug, mswin_debugfile);
 
5613
    }
 
5614
}
 
5615
 
 
5616
 
 
5617
void
 
5618
mswin_setnewmailwidth (int width)
 
5619
{
 
5620
    gNMW_width = width;
 
5621
    gNMW_width = gNMW_width < 20 ? 20 : gNMW_width;
 
5622
    gNMW_width = gNMW_width > 170 ? 170 : gNMW_width;
 
5623
}
 
5624
 
 
5625
 
 
5626
/*
 
5627
 * Event handler to deal with File Drop events
 
5628
 */
 
5629
LOCAL BOOL
 
5630
ProcessTTYFileDrop (HANDLE wDrop)
 
5631
{
 
5632
    HDROP hDrop = wDrop;
 
5633
    POINT pos;
 
5634
    int   col, row, i, n;
 
5635
    TCHAR fname[1024];
 
5636
    char *utf8_fname;
 
5637
 
 
5638
    if(!gpTTYInfo->dndhandler)
 
5639
      return(FALSE);
 
5640
 
 
5641
    /* translate drop point to character cell */
 
5642
    DragQueryPoint(hDrop, &pos);
 
5643
    col = (pos.x - gpTTYInfo->xOffset) / gpTTYInfo->xChar;
 
5644
    if (pos.x < gpTTYInfo->xOffset)
 
5645
        --col;
 
5646
    row = (pos.y - gpTTYInfo->yOffset) / gpTTYInfo->yChar;
 
5647
    if (pos.y < gpTTYInfo->yOffset)
 
5648
        --row;
 
5649
 
 
5650
    for(n = DragQueryFile(hDrop, (UINT)-1, NULL, 0), i = 0; i < n; i++){
 
5651
        DragQueryFile(hDrop, i, fname, 1024);
 
5652
        utf8_fname = lptstr_to_utf8(fname);
 
5653
        gpTTYInfo->dndhandler (row, col, utf8_fname);
 
5654
        fs_give((void **) &utf8_fname);
 
5655
    }
 
5656
 
 
5657
    DragFinish(hDrop);
 
5658
 
 
5659
    set_time_of_last_input();
 
5660
 
 
5661
    return(TRUE);
 
5662
}
 
5663
 
 
5664
 
 
5665
/*
 
5666
 * Set a callback to deal with Drag 'N Drop events
 
5667
 */
 
5668
int
 
5669
mswin_setdndcallback (int (*cb)())
 
5670
{
 
5671
    if(gpTTYInfo->dndhandler)
 
5672
      gpTTYInfo->dndhandler = NULL;
 
5673
 
 
5674
    if(cb){
 
5675
        gpTTYInfo->dndhandler = cb;
 
5676
        DragAcceptFiles(ghTTYWnd, TRUE);
 
5677
    }
 
5678
 
 
5679
    return(1);
 
5680
}
 
5681
 
 
5682
 
 
5683
/*
 
5684
 * Clear previously installed callback to handle Drag 'N Drop
 
5685
 * events
 
5686
 */
 
5687
int
 
5688
mswin_cleardndcallback ()
 
5689
{
 
5690
    gpTTYInfo->dndhandler = NULL;
 
5691
    DragAcceptFiles(ghTTYWnd, FALSE);
 
5692
    return(1);
 
5693
}
 
5694
 
 
5695
 
 
5696
/*
 
5697
 * Set a callback for function 'ch'
 
5698
 */
 
5699
int
 
5700
mswin_setresizecallback (int (*cb)())
 
5701
{
 
5702
    int         i;
 
5703
    int         e;
 
5704
 
 
5705
 
 
5706
    /*
 
5707
     * Look through whole array for this call back function.  Don't
 
5708
     * insert duplicate.  Also look for empty slot.
 
5709
     */
 
5710
    e = -1;
 
5711
    for (i = 0; i < RESIZE_CALLBACK_ARRAY_SIZE; ++i) {
 
5712
        if (gpTTYInfo->resizer[i] == cb)
 
5713
            return (0);
 
5714
        if (e == -1 && gpTTYInfo->resizer[i] == NULL)
 
5715
            e = i;
 
5716
    }
 
5717
 
 
5718
    /*
 
5719
     * Insert in empty slot or return an error.
 
5720
     */
 
5721
    if (e != -1) {
 
5722
        gpTTYInfo->resizer[e] = cb;
 
5723
        return (0);
 
5724
    }
 
5725
    return (-1);
 
5726
}
 
5727
 
 
5728
 
 
5729
/*
 
5730
 * Clear all instances of the callback function 'cb'
 
5731
 */
 
5732
int
 
5733
mswin_clearresizecallback (int (*cb)())
 
5734
{
 
5735
    int         i;
 
5736
    int         status;
 
5737
 
 
5738
    status = -1;
 
5739
    for (i = 0; i < RESIZE_CALLBACK_ARRAY_SIZE; ++i) {
 
5740
        if (gpTTYInfo->resizer[i] == cb) {
 
5741
            gpTTYInfo->resizer[i] = NULL;
 
5742
            status = 0;
 
5743
        }
 
5744
    }
 
5745
    return (status);
 
5746
}
 
5747
 
 
5748
 
 
5749
void
 
5750
mswin_beginupdate (void)
 
5751
{
 
5752
    gpTTYInfo->fMassiveUpdate = TRUE;
 
5753
}
 
5754
 
 
5755
 
 
5756
void
 
5757
mswin_endupdate (void)
 
5758
{
 
5759
    gpTTYInfo->fMassiveUpdate = FALSE;
 
5760
    MoveTTYCursor (ghTTYWnd);
 
5761
}
 
5762
 
 
5763
 
 
5764
int
 
5765
mswin_charsetid2string(LPTSTR fontCharSet, size_t nfontCharSet, BYTE lfCharSet)
 
5766
{
 
5767
    TCHAR buf[1024];
 
5768
 
 
5769
    buf[0] = '\0';
 
5770
    switch(lfCharSet){
 
5771
      case DEFAULT_CHARSET:
 
5772
        break;
 
5773
      case ANSI_CHARSET:
 
5774
        _tcsncpy(buf, TEXT("ANSI_CHARSET"), sizeof(buf)/sizeof(TCHAR));
 
5775
        break;
 
5776
      case OEM_CHARSET:
 
5777
        _tcsncpy(buf, TEXT("OEM_CHARSET"), sizeof(buf)/sizeof(TCHAR));
 
5778
        break;
 
5779
      case BALTIC_CHARSET:
 
5780
        _tcsncpy(buf, TEXT("BALTIC_CHARSET"), sizeof(buf)/sizeof(TCHAR));
 
5781
        break;
 
5782
      case CHINESEBIG5_CHARSET:
 
5783
        _tcsncpy(buf, TEXT("CHINESE_CHARSET"), sizeof(buf)/sizeof(TCHAR));
 
5784
        break;
 
5785
      case EASTEUROPE_CHARSET:
 
5786
        _tcsncpy(buf, TEXT("EASTEUROPE_CHARSET"), sizeof(buf)/sizeof(TCHAR));
 
5787
        break;
 
5788
      case GB2312_CHARSET:
 
5789
        _tcsncpy(buf, TEXT("GF2312_CHARSET"), sizeof(buf)/sizeof(TCHAR));
 
5790
        break;
 
5791
      case GREEK_CHARSET:
 
5792
        _tcsncpy(buf, TEXT("GREEK_CHARSET"), sizeof(buf)/sizeof(TCHAR));
 
5793
        break;
 
5794
      case HANGUL_CHARSET:
 
5795
        _tcsncpy(buf, TEXT("HANGUL_CHARSET"), sizeof(buf)/sizeof(TCHAR));
 
5796
        break;
 
5797
      case MAC_CHARSET:
 
5798
        _tcsncpy(buf, TEXT("MAC_CHARSET"), sizeof(buf)/sizeof(TCHAR));
 
5799
        break;
 
5800
      case RUSSIAN_CHARSET:
 
5801
        _tcsncpy(buf, TEXT("RUSSIAN_CHARSET"), sizeof(buf)/sizeof(TCHAR));
 
5802
        break;
 
5803
      case SHIFTJIS_CHARSET:
 
5804
        _tcsncpy(buf, TEXT("SHIFTJIS_CHARSET"), sizeof(buf)/sizeof(TCHAR));
 
5805
        break;
 
5806
      case SYMBOL_CHARSET:
 
5807
        _tcsncpy(buf, TEXT("SYMBOL_CHARSET"), sizeof(buf)/sizeof(TCHAR));
 
5808
        break;
 
5809
      case TURKISH_CHARSET:
 
5810
        _tcsncpy(buf, TEXT("TURKISH_CHARSET"), sizeof(buf)/sizeof(TCHAR));
 
5811
        break;
 
5812
      case VIETNAMESE_CHARSET:
 
5813
        _tcsncpy(buf, TEXT("VIETNAMESE_CHARSET"), sizeof(buf)/sizeof(TCHAR));
 
5814
        break;
 
5815
      case JOHAB_CHARSET:
 
5816
        _tcsncpy(buf, TEXT("JOHAB_CHARSET"), sizeof(buf)/sizeof(TCHAR));
 
5817
        break;
 
5818
      case ARABIC_CHARSET:
 
5819
        _tcsncpy(buf, TEXT("ARABIC_CHARSET"), sizeof(buf)/sizeof(TCHAR));
 
5820
        break;
 
5821
      case HEBREW_CHARSET:
 
5822
        _tcsncpy(buf, TEXT("HEBREW_CHARSET"), sizeof(buf)/sizeof(TCHAR));
 
5823
        break;
 
5824
      case THAI_CHARSET:
 
5825
        _tcsncpy(buf, TEXT("THAI_CHARSET"), sizeof(buf)/sizeof(TCHAR));
 
5826
        break;
 
5827
      default:
 
5828
        /* default char set if we can't figure it out */
 
5829
        break;
 
5830
    }
 
5831
 
 
5832
    buf[sizeof(buf)/sizeof(TCHAR) - 1] = '\0';
 
5833
 
 
5834
    _tcsncpy(fontCharSet, buf, nfontCharSet);
 
5835
    fontCharSet[nfontCharSet-1] = '\0';
 
5836
 
 
5837
    return 0;
 
5838
}
 
5839
 
 
5840
 
 
5841
BYTE
 
5842
mswin_string2charsetid(LPTSTR str)
 
5843
{
 
5844
    TCHAR tstr[1024];
 
5845
 
 
5846
    if(!str || (lstrlen(str) >= 1024))
 
5847
      return DEFAULT_CHARSET;
 
5848
 
 
5849
    if((lstrlen(str) > lstrlen(TEXT("_CHARSET")))
 
5850
       && (tcsucmp(str + lstrlen(str) - lstrlen(TEXT("_CHARSET")), TEXT("_CHARSET")) == 0)){
 
5851
        _tcsncpy(tstr, str, 1024);
 
5852
        tstr[lstrlen(str) - lstrlen(TEXT("_CHARSET"))] = '\0';
 
5853
        tstr[1024-1] = '\0';
 
5854
        if(tcsucmp(tstr, TEXT("ANSI")) == 0)
 
5855
          return ANSI_CHARSET;
 
5856
        else if(tcsucmp(tstr, TEXT("DEFAULT")) == 0)
 
5857
          return DEFAULT_CHARSET;
 
5858
        else if(tcsucmp(tstr, TEXT("OEM")) == 0)
 
5859
          return OEM_CHARSET;
 
5860
        else if(tcsucmp(tstr, TEXT("BALTIC")) == 0)
 
5861
          return BALTIC_CHARSET;
 
5862
        else if(tcsucmp(tstr, TEXT("CHINESEBIG5")) == 0)
 
5863
          return CHINESEBIG5_CHARSET;
 
5864
        else if(tcsucmp(tstr, TEXT("EASTEUROPE")) == 0)
 
5865
          return EASTEUROPE_CHARSET;
 
5866
        else if(tcsucmp(tstr, TEXT("GB2312")) == 0)
 
5867
          return GB2312_CHARSET;
 
5868
        else if(tcsucmp(tstr, TEXT("GREEK")) == 0)
 
5869
          return GREEK_CHARSET;
 
5870
        else if(tcsucmp(tstr, TEXT("HANGUL")) == 0)
 
5871
          return HANGUL_CHARSET;
 
5872
        else if(tcsucmp(tstr, TEXT("MAC")) == 0)
 
5873
          return MAC_CHARSET;
 
5874
        else if(tcsucmp(tstr, TEXT("RUSSIAN")) == 0)
 
5875
          return RUSSIAN_CHARSET;
 
5876
        else if(tcsucmp(tstr, TEXT("SHIFTJIS")) == 0)
 
5877
          return SHIFTJIS_CHARSET;
 
5878
        else if(tcsucmp(tstr, TEXT("SYMBOL")) == 0)
 
5879
          return SYMBOL_CHARSET;
 
5880
        else if(tcsucmp(tstr, TEXT("TURKISH")) == 0)
 
5881
          return TURKISH_CHARSET;
 
5882
        else if(tcsucmp(tstr, TEXT("VIETNAMESE")) == 0)
 
5883
          return VIETNAMESE_CHARSET;
 
5884
        else if(tcsucmp(tstr, TEXT("JOHAB")) == 0)
 
5885
          return JOHAB_CHARSET;
 
5886
        else if(tcsucmp(tstr, TEXT("ARABIC")) == 0)
 
5887
          return ARABIC_CHARSET;
 
5888
        else if(tcsucmp(tstr, TEXT("HEBREW")) == 0)
 
5889
          return HEBREW_CHARSET;
 
5890
        else if(tcsucmp(tstr, TEXT("THAI")) == 0)
 
5891
          return THAI_CHARSET;
 
5892
        else
 
5893
          return DEFAULT_CHARSET;
 
5894
    }
 
5895
    else{
 
5896
        if(_tstoi(str) > 0)
 
5897
          return((BYTE)(_tstoi(str)));
 
5898
        else
 
5899
          return DEFAULT_CHARSET;
 
5900
    }
 
5901
}
 
5902
 
 
5903
 
 
5904
int
 
5905
mswin_setwindow(char *fontName_utf8, char *fontSize_utf8, char *fontStyle_utf8,
 
5906
                char *windowPosition, char *caretStyle, char *fontCharSet_utf8)
 
5907
{
 
5908
    LOGFONT             newFont;
 
5909
    int                 newHeight;
 
5910
    HDC                 hDC;
 
5911
    int                 ppi;
 
5912
    RECT                wndRect, cliRect;
 
5913
    char                *c;
 
5914
    char                *n;
 
5915
    int                 i;
 
5916
    BOOL                toolBar = FALSE;
 
5917
    BOOL                toolBarTop = TRUE;
 
5918
    int                 wColumns, wRows;
 
5919
    int                 wXPos, wYPos;
 
5920
    int                 wXBorder, wYBorder;
 
5921
    int                 wXSize, wYSize;
 
5922
    char                wp[WIN_POS_STR_MAX_LEN + 1];
 
5923
    int                 showWin = 1;
 
5924
    LPTSTR              fontName_lpt = NULL;
 
5925
    LPTSTR              fontCharSet_lpt;
 
5926
 
 
5927
#ifdef SDEBUG
 
5928
    if (mswin_debug >= 5)
 
5929
        fprintf (mswin_debugfile, "mswin_setwindow:::  entered, minimized:  %d\n",
 
5930
                gpTTYInfo->fMinimized);
 
5931
#endif
 
5932
 
 
5933
    /* Require a font name to set font info. */
 
5934
    if(fontName_utf8 != NULL && *fontName_utf8 != '\0' &&
 
5935
        (fontName_lpt = utf8_to_lptstr(fontName_utf8)) &&
 
5936
        _tcslen(fontName_lpt) <= LF_FACESIZE - 1){
 
5937
        
 
5938
        hDC = GetDC(ghTTYWnd);
 
5939
        ppi = GetDeviceCaps(hDC, LOGPIXELSY);
 
5940
        ReleaseDC(ghTTYWnd, hDC);
 
5941
 
 
5942
        /* Default height, then examin the requested fontSize. */
 
5943
        newFont.lfHeight = -MulDiv(12, ppi, 72);
 
5944
        if(ScanInt(fontSize_utf8, FONT_MIN_SIZE, FONT_MAX_SIZE, &newHeight)){
 
5945
            newHeight = abs(newHeight);
 
5946
            newFont.lfHeight = -MulDiv(newHeight, ppi, 72);
 
5947
        }
 
5948
        
 
5949
        /* Default font style, then read requested style. */
 
5950
        newFont.lfWeight =         0;
 
5951
        newFont.lfItalic =         0;
 
5952
        if(fontStyle_utf8 != NULL){
 
5953
            _strlwr(fontStyle_utf8);
 
5954
            if(strstr(fontStyle_utf8, "bold"))
 
5955
                newFont.lfWeight = FW_BOLD;
 
5956
            if(strstr(fontStyle_utf8, "italic"))
 
5957
                newFont.lfItalic = 1;
 
5958
        }
 
5959
        
 
5960
        /* Everything else takes the default. */
 
5961
        newFont.lfWidth =          0;
 
5962
        newFont.lfEscapement =     0;
 
5963
        newFont.lfOrientation =    0;
 
5964
        newFont.lfUnderline =      0;
 
5965
        newFont.lfStrikeOut =      0;
 
5966
        fontCharSet_lpt = utf8_to_lptstr(fontCharSet_utf8);
 
5967
        if(fontCharSet_lpt){
 
5968
            newFont.lfCharSet = mswin_string2charsetid(fontCharSet_lpt);
 
5969
            fs_give((void **) &fontCharSet_lpt);
 
5970
        }
 
5971
 
 
5972
        newFont.lfOutPrecision =   OUT_DEFAULT_PRECIS;
 
5973
        newFont.lfClipPrecision =  CLIP_DEFAULT_PRECIS;
 
5974
        newFont.lfQuality =        DEFAULT_QUALITY;
 
5975
        newFont.lfPitchAndFamily = FIXED_PITCH;
 
5976
        _sntprintf(newFont.lfFaceName, LF_FACESIZE, TEXT("%s"), fontName_lpt);
 
5977
        ResetTTYFont (ghTTYWnd, gpTTYInfo, &newFont);
 
5978
    }
 
5979
 
 
5980
    if(fontName_lpt)
 
5981
      fs_give((void **) &fontName_lpt);
 
5982
 
 
5983
    /*
 
5984
     * Set window position.  String format is:  CxR+X+Y
 
5985
     * Where C is the number of columns, R is the number of rows,
 
5986
     * and X and Y specify the top left corner of the window.
 
5987
     */
 
5988
    if(windowPosition != NULL && *windowPosition != '\0'){
 
5989
        if(strlen(windowPosition) > sizeof(wp)-1)
 
5990
          return(0);
 
5991
 
 
5992
        strncpy(wp, windowPosition, sizeof(wp));
 
5993
        wp[sizeof(wp)-1] = '\0';
 
5994
        
 
5995
        /*
 
5996
         * Flag characters are at the end of the string.  Strip them
 
5997
         * off till we get to a number.
 
5998
         */
 
5999
        i = (int)strlen(wp) - 1;
 
6000
        while(i > 0 && (*(wp+i) < '0' || *(wp+i) > '9')){
 
6001
            if(*(wp+i) == 't' || *(wp+i) == 'b'){
 
6002
                toolBar = TRUE;
 
6003
                toolBarTop = (*(wp+i) == 't');
 
6004
            }
 
6005
 
 
6006
            if(*(wp+i) == 'd')
 
6007
              gfUseDialogs = TRUE;
 
6008
 
 
6009
#ifdef ACCELERATORS_OPT
 
6010
            if(*(wp+i) == 'a')
 
6011
                AccelCtl(ghTTYWnd, ACCEL_LOAD, FALSE);
 
6012
#endif  
 
6013
 
 
6014
            *(wp+i) = 0;
 
6015
            --i;
 
6016
        }
 
6017
 
 
6018
        if(strcmp(wp, "MIN0") == 0){
 
6019
            mswin_killsplash();
 
6020
            showWin = 0;
 
6021
            ShowWindow(ghTTYWnd, SW_MINIMIZE);
 
6022
            if(toolBar){
 
6023
                gpTTYInfo->toolBarTop = toolBarTop;
 
6024
                TBShow(ghTTYWnd);
 
6025
            }
 
6026
        }
 
6027
        else{
 
6028
            /* Look for Columns, deliminated by 'x'. */
 
6029
            c = strchr (wp, 'x');
 
6030
            if (c == NULL)
 
6031
              return(0);
 
6032
 
 
6033
            *c = '\0';
 
6034
            if(!ScanInt(wp, -999, 9999, &wColumns))
 
6035
              return(0);
 
6036
 
 
6037
            /* Look for Rows, deliminated by '+'. */
 
6038
            n = c + 1;
 
6039
            c = strchr(n, '+');
 
6040
            if(c == NULL)
 
6041
              return (0);
 
6042
 
 
6043
            *c = '\0';
 
6044
            if(!ScanInt(n, -999, 9999, &wRows))
 
6045
              return(0);
 
6046
 
 
6047
            /* Look for X position, deliminated by '+'. */
 
6048
            n = c + 1;
 
6049
            c = strchr(n, '+');
 
6050
            if(c == NULL)
 
6051
              return(0);
 
6052
 
 
6053
            *c = '\0';
 
6054
            if(!ScanInt(n, -999, 9999, &wXPos))
 
6055
              return(0);
 
6056
 
 
6057
            /* And get Y position, deliminated by end of string. */
 
6058
            n = c + 1;
 
6059
            if(!ScanInt(n, -999, 9999, &wYPos))
 
6060
              return(0);
 
6061
 
 
6062
 
 
6063
            /* Constrain the window position and size. */
 
6064
            if(wXPos < 0)
 
6065
              wXPos = 0;
 
6066
 
 
6067
            if(wYPos < 0)
 
6068
              wYPos = 0;
 
6069
 
 
6070
            GetWindowRect(GetDesktopWindow(), &wndRect);
 
6071
            if(wXPos > wndRect.right - 20)
 
6072
              wXPos = wndRect.right - 100;
 
6073
 
 
6074
            if(wYPos > wndRect.bottom - 20)
 
6075
              wYPos = wndRect.bottom - 100;
 
6076
 
 
6077
            /* Get the current window rect and client area. */
 
6078
            GetWindowRect(ghTTYWnd, &wndRect);
 
6079
            GetClientRect(ghTTYWnd, &cliRect);
 
6080
 
 
6081
            /* Calculate boarder sizes. */
 
6082
            wXBorder = wndRect.right - wndRect.left - cliRect.right;
 
6083
            wYBorder = wndRect.bottom - wndRect.top - cliRect.bottom;
 
6084
 
 
6085
            /* Show toolbar before calculating content size. */
 
6086
            if(toolBar){
 
6087
                gpTTYInfo->toolBarTop = toolBarTop;
 
6088
                TBShow(ghTTYWnd);
 
6089
            }
 
6090
 
 
6091
            /* Calculate new window pos and size. */
 
6092
            wXSize = wXBorder + (wColumns * gpTTYInfo->xChar) +
 
6093
                                                    (2 * gpTTYInfo->xOffset);
 
6094
            wYSize = wYBorder + (wRows * gpTTYInfo->yChar) +
 
6095
                                    gpTTYInfo->toolBarSize + (2 * MARGINE_TOP);
 
6096
            if(!gpTTYInfo->fMinimized)
 
6097
              MoveWindow(ghTTYWnd, wXPos, wYPos, wXSize, wYSize, TRUE);
 
6098
            else{
 
6099
                gpTTYInfo->fDesiredSize = TRUE;
 
6100
                gpTTYInfo->xDesPos = (CORD)wXPos;
 
6101
                gpTTYInfo->yDesPos = (CORD)wYPos;
 
6102
                gpTTYInfo->xDesSize = (CORD)wXSize;
 
6103
                gpTTYInfo->yDesSize = (CORD)wYSize;
 
6104
            }
 
6105
        }
 
6106
    }
 
6107
 
 
6108
    if(caretStyle != NULL && *caretStyle != '\0')
 
6109
      for(i = 0; MSWinCaretTable[i].name; i++)
 
6110
        if(!strucmp(MSWinCaretTable[i].name, caretStyle)){
 
6111
            CaretTTY(ghTTYWnd, MSWinCaretTable[i].style);
 
6112
            break;
 
6113
        }
 
6114
 
 
6115
    return(0);
 
6116
}
 
6117
 
 
6118
 
 
6119
int
 
6120
mswin_showwindow()
 
6121
{
 
6122
    mswin_killsplash();
 
6123
    ShowWindow (ghTTYWnd, SW_SHOWNORMAL);
 
6124
    UpdateWindow (ghTTYWnd);
 
6125
 
 
6126
    return(0);
 
6127
}
 
6128
 
 
6129
 
 
6130
/*
 
6131
 * Retreive the current font name, font size, and window position
 
6132
 * These get stored in the pinerc file and will be passed to
 
6133
 * mswin_setwindow() when pine starts up.  See pinerc for comments
 
6134
 * on the format.
 
6135
 */
 
6136
int
 
6137
mswin_getwindow(char *fontName_utf8, size_t nfontName,
 
6138
                char *fontSize_utf8, size_t nfontSize,
 
6139
                char *fontStyle_utf8, size_t nfontStyle,
 
6140
                char *windowPosition, size_t nwindowPosition,
 
6141
                char *foreColor, size_t nforeColor,
 
6142
                char *backColor, size_t nbackColor,
 
6143
                char *caretStyle, size_t ncaretStyle,
 
6144
                char *fontCharSet_utf8, size_t nfontCharSet)
 
6145
{
 
6146
    HDC                 hDC;
 
6147
    int                 ppi;
 
6148
    RECT                wndRect;
 
6149
    char               *t;
 
6150
 
 
6151
    if(fontName_utf8 != NULL){
 
6152
        t = lptstr_to_utf8(gpTTYInfo->lfTTYFont.lfFaceName);
 
6153
        if(strlen(t) < nfontName)
 
6154
          snprintf(fontName_utf8, nfontName, "%s", t);
 
6155
 
 
6156
        fs_give((void **) &t);
 
6157
    }
 
6158
 
 
6159
    if(fontCharSet_utf8 != NULL){
 
6160
        LPTSTR lpt;
 
6161
 
 
6162
        lpt = (LPTSTR) fs_get(nfontCharSet * sizeof(TCHAR));
 
6163
        if(lpt){
 
6164
            lpt[0] = '\0';
 
6165
            mswin_charsetid2string(lpt, nfontCharSet, gpTTYInfo->lfTTYFont.lfCharSet);
 
6166
            t = lptstr_to_utf8(lpt);
 
6167
            if(strlen(t) < nfontCharSet)
 
6168
              snprintf(fontCharSet_utf8, nfontCharSet, "%s", t);
 
6169
 
 
6170
            fs_give((void **) &t);
 
6171
 
 
6172
            fs_give((void **) &lpt);
 
6173
        }
 
6174
    }
 
6175
 
 
6176
    if(fontSize_utf8 != NULL){
 
6177
        hDC = GetDC(ghTTYWnd);
 
6178
        ppi = GetDeviceCaps(hDC, LOGPIXELSY);
 
6179
        ReleaseDC(ghTTYWnd, hDC);
 
6180
        snprintf(fontSize_utf8, nfontSize, "%d", MulDiv(-gpTTYInfo->lfTTYFont.lfHeight, 72, ppi));
 
6181
    }
 
6182
 
 
6183
    if(fontStyle_utf8 != NULL){
 
6184
        char            *sep[] = {"", ", "};
 
6185
        int             iSep = 0;
 
6186
        
 
6187
        *fontStyle_utf8 = '\0';
 
6188
        if(gpTTYInfo->lfTTYFont.lfWeight >= FW_BOLD){
 
6189
            strncpy(fontStyle_utf8, "bold", nfontStyle);
 
6190
            fontStyle_utf8[nfontStyle-1] = '\0';
 
6191
            iSep = 1;
 
6192
        }
 
6193
 
 
6194
        if(gpTTYInfo->lfTTYFont.lfItalic){
 
6195
            strncat(fontStyle_utf8, sep[iSep], nfontStyle-strlen(fontStyle_utf8));
 
6196
            fontStyle_utf8[nfontStyle-1] = '\0';
 
6197
            strncat(fontStyle_utf8, "italic", nfontStyle-strlen(fontStyle_utf8));
 
6198
            fontStyle_utf8[nfontStyle-1] = '\0';
 
6199
        }
 
6200
    }
 
6201
 
 
6202
    if(windowPosition != NULL){
 
6203
        if(gpTTYInfo->fMinimized){
 
6204
            strncpy(windowPosition, "MIN0", nwindowPosition);
 
6205
            windowPosition[nwindowPosition-1] = '\0';
 
6206
        }
 
6207
        else{
 
6208
            /*
 
6209
             * Get the window position.  Constrain the top left corner
 
6210
             * to be on the screen.
 
6211
             */
 
6212
            GetWindowRect(ghTTYWnd, &wndRect);
 
6213
            if(wndRect.left < 0)
 
6214
              wndRect.left = 0;
 
6215
 
 
6216
            if(wndRect.top < 0)
 
6217
              wndRect.top = 0;
 
6218
 
 
6219
            snprintf(windowPosition, nwindowPosition, "%dx%d+%d+%d", gpTTYInfo->actNColumn,
 
6220
                    gpTTYInfo->actNRow, wndRect.left, wndRect.top);
 
6221
        }
 
6222
 
 
6223
        if(gpTTYInfo->toolBarSize > 0){
 
6224
            strncat(windowPosition, gpTTYInfo->toolBarTop ? "t" : "b",
 
6225
                    nwindowPosition-strlen(windowPosition));
 
6226
            windowPosition[nwindowPosition-1] = '\0';
 
6227
        }
 
6228
 
 
6229
        if(gfUseDialogs){
 
6230
            strncat(windowPosition, "d", nwindowPosition-strlen(windowPosition));
 
6231
            windowPosition[nwindowPosition-1] = '\0';
 
6232
        }
 
6233
 
 
6234
        if(gpTTYInfo->hAccel){
 
6235
            strncat(windowPosition, "a", nwindowPosition-strlen(windowPosition));
 
6236
            windowPosition[nwindowPosition-1] = '\0';
 
6237
        }
 
6238
    }
 
6239
 
 
6240
    if(foreColor != NULL)
 
6241
      ConvertStringRGB(foreColor, nforeColor, gpTTYInfo->rgbFGColor);
 
6242
 
 
6243
    if(backColor != NULL)
 
6244
      ConvertStringRGB(backColor, nbackColor, gpTTYInfo->rgbBGColor);
 
6245
 
 
6246
    if(caretStyle != NULL){
 
6247
        int i;
 
6248
 
 
6249
        for(i = 0; MSWinCaretTable[i].name; i++)
 
6250
          if(MSWinCaretTable[i].style == gpTTYInfo->cCaretStyle){
 
6251
              strncpy(caretStyle, MSWinCaretTable[i].name, ncaretStyle);
 
6252
              caretStyle[ncaretStyle-1] = '\0';
 
6253
              break;
 
6254
          }
 
6255
    }
 
6256
 
 
6257
    return (0);
 
6258
}
 
6259
 
 
6260
 
 
6261
void
 
6262
mswin_noscrollupdate(int flag)
 
6263
{
 
6264
    gpTTYInfo->noScrollUpdate = (flag != 0);
 
6265
    if(flag == 0 && gpTTYInfo->scrollRangeChanged){
 
6266
        mswin_setscrollrange(gpTTYInfo->noSUpdatePage, gpTTYInfo->noSUpdateRange);
 
6267
        gpTTYInfo->noSUpdatePage = gpTTYInfo->noSUpdateRange = 0;
 
6268
        gpTTYInfo->scrollRangeChanged = 0;
 
6269
    }
 
6270
}
 
6271
 
 
6272
 
 
6273
/*
 
6274
 * Set the scroll range.
 
6275
 */
 
6276
void
 
6277
mswin_setscrollrange (long page, long max)
 
6278
{
 
6279
    SCROLLINFO scrollInfo;
 
6280
 
 
6281
    if(gpTTYInfo->noScrollUpdate){
 
6282
        gpTTYInfo->noSUpdatePage = page;
 
6283
        gpTTYInfo->noSUpdateRange = max;
 
6284
        gpTTYInfo->scrollRangeChanged = 1;
 
6285
        return;
 
6286
    }
 
6287
    if (max != gpTTYInfo->scrollRange) {
 
6288
        scrollInfo.cbSize = sizeof(SCROLLINFO);
 
6289
        scrollInfo.fMask = SIF_DISABLENOSCROLL | SIF_PAGE | SIF_RANGE;
 
6290
        scrollInfo.nMin = 0;
 
6291
 
 
6292
        if (max > 0) {
 
6293
            scrollInfo.nMax = (int) max;
 
6294
            scrollInfo.nPage = page;
 
6295
            SetScrollInfo(ghTTYWnd, SB_VERT, &scrollInfo, TRUE);
 
6296
            EnableScrollBar (ghTTYWnd, SB_VERT, ESB_ENABLE_BOTH);
 
6297
        }
 
6298
        else {
 
6299
            max = 0;
 
6300
            scrollInfo.cbSize = sizeof(SCROLLINFO);
 
6301
            scrollInfo.fMask |= SIF_POS;
 
6302
            scrollInfo.nMax = 1;
 
6303
            scrollInfo.nPos = 0;
 
6304
            SetScrollInfo(ghTTYWnd, SB_VERT, &scrollInfo, TRUE);
 
6305
            EnableScrollBar (ghTTYWnd, SB_VERT, ESB_DISABLE_BOTH);
 
6306
            gpTTYInfo->scrollPos = 0;
 
6307
        }
 
6308
        gpTTYInfo->scrollRange = (int)max;
 
6309
    }
 
6310
}
 
6311
 
 
6312
 
 
6313
/*
 
6314
 * Set the current scroll position.
 
6315
 */
 
6316
void
 
6317
mswin_setscrollpos (long pos)
 
6318
{
 
6319
    SCROLLINFO scrollInfo;
 
6320
 
 
6321
    if (pos != gpTTYInfo->scrollPos) {
 
6322
        scrollInfo.cbSize = sizeof(SCROLLINFO);
 
6323
        scrollInfo.fMask = SIF_PAGE | SIF_RANGE;
 
6324
 
 
6325
        GetScrollInfo(ghTTYWnd, SB_VERT, &scrollInfo);
 
6326
 
 
6327
        scrollInfo.fMask |= SIF_POS;
 
6328
        scrollInfo.nPos = (int) pos;
 
6329
        SetScrollInfo(ghTTYWnd, SB_VERT, &scrollInfo, TRUE);
 
6330
 
 
6331
        gpTTYInfo->scrollPos = pos;
 
6332
    }
 
6333
}
 
6334
 
 
6335
 
 
6336
/*
 
6337
 * retreive the current scroll postion.
 
6338
 */
 
6339
long
 
6340
mswin_getscrollpos (void)
 
6341
{
 
6342
   return ((long)((float)GetScrollPos (ghTTYWnd, SB_VERT)));
 
6343
}
 
6344
 
 
6345
 
 
6346
/*
 
6347
 * retreive the latest scroll to position.
 
6348
 */
 
6349
long
 
6350
mswin_getscrollto (void)
 
6351
{
 
6352
   return (gpTTYInfo->scrollTo);
 
6353
}
 
6354
 
 
6355
/*
 
6356
 * install function to deal with LINEDOWN events
 
6357
 */
 
6358
void
 
6359
mswin_setscrollcallback (cbarg_t cbfunc)
 
6360
{
 
6361
    gScrollCallback = cbfunc;
 
6362
}
 
6363
 
 
6364
 
 
6365
/*
 
6366
 * install function to deal with sort menu messages
 
6367
 */
 
6368
void
 
6369
mswin_setsortcallback (cbarg_t cbfunc)
 
6370
{
 
6371
    gSortCallback = cbfunc;
 
6372
}
 
6373
 
 
6374
 
 
6375
/*
 
6376
 * install function to deal with sort menu messages
 
6377
 */
 
6378
void
 
6379
mswin_setflagcallback (cbarg_t cbfunc)
 
6380
{
 
6381
    gFlagCallback = cbfunc;
 
6382
}
 
6383
 
 
6384
void
 
6385
mswin_set_erasecreds_callback (cbvoid_t cbfunc)
 
6386
{
 
6387
    gEraseCredsCallback = cbfunc;
 
6388
}
 
6389
 
 
6390
/*
 
6391
 * install function to deal with header mode flipping
 
6392
 */
 
6393
void
 
6394
mswin_sethdrmodecallback (cbarg_t cbfunc)
 
6395
{
 
6396
    gHdrCallback = cbfunc;
 
6397
}
 
6398
 
 
6399
 
 
6400
/*
 
6401
 * install function to deal with zoom mode flipping
 
6402
 */
 
6403
void
 
6404
mswin_setzoomodecallback (cbarg_t cbfunc)
 
6405
{
 
6406
    gZoomCallback = cbfunc;
 
6407
}
 
6408
 
 
6409
 
 
6410
/*
 
6411
 * install function to deal with function key mode flipping
 
6412
 */
 
6413
void
 
6414
mswin_setfkeymodecallback (cbarg_t cbfunc)
 
6415
{
 
6416
    gFkeyCallback = cbfunc;
 
6417
}
 
6418
 
 
6419
 
 
6420
/*
 
6421
 * install function to deal with apply mode flipping
 
6422
 */
 
6423
void
 
6424
mswin_setselectedcallback (cbarg_t cbfunc)
 
6425
{
 
6426
    gSelectedCallback = cbfunc;
 
6427
}
 
6428
 
 
6429
 
 
6430
/*
 
6431
 * return 1 if new mail window is being used
 
6432
 */
 
6433
int
 
6434
mswin_newmailwinon (void)
 
6435
{
 
6436
    return(gMswinNewMailWin.hwnd ? 1 : 0);
 
6437
}
 
6438
 
 
6439
 
 
6440
/*
 
6441
 */
 
6442
void
 
6443
mswin_setdebugoncallback (cbvoid_t cbfunc)
 
6444
{
 
6445
    gIMAPDebugONCallback = cbfunc;
 
6446
}
 
6447
 
 
6448
 
 
6449
void
 
6450
mswin_setdebugoffcallback (cbvoid_t cbfunc)
 
6451
{
 
6452
    gIMAPDebugOFFCallback = cbfunc;
 
6453
}
 
6454
 
 
6455
 
 
6456
int
 
6457
mswin_setconfigcallback (cbvoid_t cffunc)
 
6458
{
 
6459
    gConfigScreenCallback = cffunc;
 
6460
    return(1);
 
6461
}
 
6462
 
 
6463
 
 
6464
/*
 
6465
 * Set the printer font
 
6466
 */
 
6467
void            
 
6468
mswin_setprintfont(char *fontName, char *fontSize,
 
6469
                   char *fontStyle, char *fontCharSet)
 
6470
{
 
6471
    LPTSTR fn = NULL, fstyle = NULL, fc = NULL;
 
6472
 
 
6473
    if(fontName)
 
6474
      fn = utf8_to_lptstr(fontName);
 
6475
 
 
6476
    if(fontStyle)
 
6477
      fstyle = utf8_to_lptstr(fontStyle);
 
6478
 
 
6479
    if(fontCharSet)
 
6480
      fc = utf8_to_lptstr(fontCharSet);
 
6481
 
 
6482
    /* Require a font name to set font info. */
 
6483
    if(fn != NULL && *fn != '\0' && lstrlen(fn) <= LF_FACESIZE - 1){
 
6484
        
 
6485
        _tcsncpy(gPrintFontName, fn, sizeof(gPrintFontName)/sizeof(TCHAR));
 
6486
        gPrintFontName[sizeof(gPrintFontName)/sizeof(TCHAR)-1] = 0;
 
6487
        if(fstyle){
 
6488
            _tcsncpy(gPrintFontStyle, fstyle, sizeof(gPrintFontStyle)/sizeof(TCHAR));
 
6489
            gPrintFontStyle[sizeof(gPrintFontStyle)/sizeof(TCHAR)-1] = 0;
 
6490
            _tcslwr(gPrintFontStyle);   /* Lower case font style. */
 
6491
        }
 
6492
 
 
6493
        if(fc){
 
6494
            _tcsncpy(gPrintFontCharSet, fc, sizeof(gPrintFontCharSet)/sizeof(TCHAR));
 
6495
            gPrintFontCharSet[sizeof(gPrintFontCharSet)/sizeof(TCHAR)-1] = 0;
 
6496
        }
 
6497
 
 
6498
        gPrintFontSize = 12;
 
6499
        if(ScanInt(fontSize, FONT_MIN_SIZE, FONT_MAX_SIZE, &gPrintFontSize))
 
6500
          gPrintFontSize = abs(gPrintFontSize);
 
6501
 
 
6502
        gPrintFontSameAs = FALSE;
 
6503
    }
 
6504
    else{
 
6505
        gPrintFontName[0] = '\0';
 
6506
        gPrintFontSameAs = TRUE;
 
6507
    }
 
6508
 
 
6509
    if(fn)
 
6510
      fs_give((void **) &fn);
 
6511
 
 
6512
    if(fstyle)
 
6513
      fs_give((void **) &fstyle);
 
6514
 
 
6515
    if(fc)
 
6516
      fs_give((void **) &fc);
 
6517
}
 
6518
 
 
6519
 
 
6520
void
 
6521
mswin_getprintfont(char *fontName_utf8, size_t nfontName,
 
6522
                   char *fontSize_utf8, size_t nfontSize,
 
6523
                   char *fontStyle_utf8, size_t nfontStyle,
 
6524
                   char *fontCharSet_utf8, size_t nfontCharSet)
 
6525
{
 
6526
    if(gPrintFontName[0] == '\0' || gPrintFontSameAs){
 
6527
        if(fontName_utf8 != NULL)
 
6528
            *fontName_utf8 = '\0';
 
6529
        if(fontSize_utf8 != NULL)
 
6530
            *fontSize_utf8 = '\0';
 
6531
        if(fontStyle_utf8 != NULL)
 
6532
            *fontStyle_utf8 = '\0';
 
6533
        if(fontCharSet_utf8 != NULL)
 
6534
            *fontCharSet_utf8 = '\0';
 
6535
    }
 
6536
    else{
 
6537
        char *u;
 
6538
 
 
6539
        if(fontName_utf8 != NULL){
 
6540
            u = lptstr_to_utf8(gPrintFontName);
 
6541
            if(u){
 
6542
                strncpy(fontName_utf8, u, nfontName);
 
6543
                fontName_utf8[nfontName-1] = 0;
 
6544
                fs_give((void **) &u);
 
6545
            }
 
6546
        }
 
6547
 
 
6548
        if(fontSize_utf8 != NULL)
 
6549
          snprintf(fontSize_utf8, nfontSize, "%d", gPrintFontSize);
 
6550
 
 
6551
 
 
6552
        if(fontStyle_utf8 != NULL){
 
6553
            u = lptstr_to_utf8(gPrintFontStyle);
 
6554
            if(u){
 
6555
                strncpy(fontStyle_utf8, u, nfontStyle);
 
6556
                fontStyle_utf8[nfontStyle-1] = 0;
 
6557
                fs_give((void **) &u);
 
6558
            }
 
6559
        }
 
6560
 
 
6561
        if(fontCharSet_utf8 != NULL){
 
6562
            u = lptstr_to_utf8(gPrintFontCharSet);
 
6563
            if(u){
 
6564
                strncpy(fontCharSet_utf8, u, nfontCharSet);
 
6565
                fontCharSet_utf8[nfontCharSet-1] = 0;
 
6566
                fs_give((void **) &u);
 
6567
            }
 
6568
        }
 
6569
    }
 
6570
}
 
6571
 
 
6572
 
 
6573
/*
 
6574
 * Set the window help text.  Add or delete the Help menu item as needed.
 
6575
 */
 
6576
int
 
6577
mswin_sethelptextcallback(cbstr_t cbfunc)
 
6578
{
 
6579
    HMENU               hMenu;
 
6580
 
 
6581
    gHelpCallback = cbfunc;
 
6582
 
 
6583
    hMenu = GetMenu (ghTTYWnd);
 
6584
    if (hMenu == NULL)
 
6585
        return (1);
 
6586
 
 
6587
    return(MSWHelpSetMenu (hMenu));
 
6588
 
 
6589
}
 
6590
 
 
6591
 
 
6592
/*
 
6593
 * Set the window help text.  Add or delete the Help menu item as needed.
 
6594
 */
 
6595
int
 
6596
mswin_setgenhelptextcallback(cbstr_t cbfunc)
 
6597
{
 
6598
    HMENU               hMenu;
 
6599
 
 
6600
    gHelpGenCallback = cbfunc;
 
6601
 
 
6602
    hMenu = GetMenu (ghTTYWnd);
 
6603
    if (hMenu == NULL)
 
6604
        return (1);
 
6605
 
 
6606
    return(MSWHelpSetMenu (hMenu));
 
6607
 
 
6608
}
 
6609
 
 
6610
 
 
6611
int
 
6612
MSWHelpSetMenu(HMENU hMenu)
 
6613
{
 
6614
    BOOL                brc;
 
6615
    int                 count;
 
6616
 
 
6617
    /*
 
6618
     * Find menu and update it.
 
6619
     */
 
6620
    count = GetMenuItemCount (hMenu);
 
6621
    if (count == -1)
 
6622
        return (1);
 
6623
 
 
6624
    hMenu = GetSubMenu (hMenu, count - 1);
 
6625
    if (hMenu == NULL)
 
6626
        return (1);
 
6627
 
 
6628
    /*
 
6629
     * Insert or delete generic help item
 
6630
     */
 
6631
    if (gHelpGenCallback == NULL){
 
6632
        if (gfHelpGenMenu) {
 
6633
            brc = DeleteMenu (hMenu, IDM_MI_GENERALHELP, MF_BYCOMMAND);
 
6634
            DrawMenuBar (ghTTYWnd);
 
6635
        }
 
6636
        gfHelpGenMenu = FALSE;
 
6637
    }
 
6638
    else {
 
6639
        if (!gfHelpGenMenu) {
 
6640
            brc = InsertMenu (hMenu, 0,
 
6641
                              MF_BYPOSITION | MF_STRING,
 
6642
                              IDM_MI_GENERALHELP, TEXT("&General Help"));
 
6643
            DrawMenuBar (ghTTYWnd);
 
6644
        }
 
6645
        gfHelpGenMenu = TRUE;
 
6646
    }
 
6647
 
 
6648
    /*
 
6649
     * Insert or delete screen help item
 
6650
     */
 
6651
    if (gHelpCallback == NULL){
 
6652
        if (gfHelpMenu) {
 
6653
            brc = DeleteMenu (hMenu, IDM_HELP, MF_BYCOMMAND);
 
6654
            DrawMenuBar (ghTTYWnd);
 
6655
        }
 
6656
        gfHelpMenu = FALSE;
 
6657
    }
 
6658
    else {
 
6659
        if (!gfHelpMenu) {
 
6660
            brc = InsertMenu (hMenu, gHelpGenCallback ? 2 : 1,
 
6661
                              MF_BYPOSITION | MF_STRING,
 
6662
                              IDM_HELP, TEXT("Screen Help in &New Window"));
 
6663
            DrawMenuBar (ghTTYWnd);
 
6664
        }
 
6665
        gfHelpMenu = TRUE;
 
6666
    }
 
6667
 
 
6668
    return (0);
 
6669
}
 
6670
 
 
6671
 
 
6672
/*
 
6673
 * Set the text displayed when someone tries to close the application
 
6674
 * the wrong way.
 
6675
 */
 
6676
void
 
6677
mswin_setclosetext (char *pCloseText)
 
6678
{
 
6679
    gpCloseText = pCloseText;
 
6680
}
 
6681
 
 
6682
 
 
6683
/*
 
6684
 * Called when upper layer is in a busy loop.  Allows us to yeild to
 
6685
 * Windows and perhaps process some events.  Does not yeild control
 
6686
 * to other applications.
 
6687
 */
 
6688
int
 
6689
mswin_yeild (void)
 
6690
{
 
6691
    MSG         msg;
 
6692
    DWORD       start;
 
6693
    int         didmsg = FALSE;
 
6694
 
 
6695
    if (gScrolling)
 
6696
        return (TRUE);
 
6697
 
 
6698
    start = GetTickCount ();
 
6699
#ifdef CDEBUG
 
6700
    if (mswin_debug > 16)
 
6701
        fprintf (mswin_debugfile, "mswin_yeild:: Entered\n");
 
6702
#endif
 
6703
    if (PeekMessage (&msg, NULL, 0, 0, PM_REMOVE)) {
 
6704
        if (gpTTYInfo->hAccel == NULL ||
 
6705
                !TranslateAccelerator (ghTTYWnd, gpTTYInfo->hAccel, &msg)) {
 
6706
            TranslateMessage (&msg);
 
6707
            DispatchMessage (&msg);
 
6708
            didmsg = TRUE;
 
6709
        }
 
6710
    }
 
6711
#ifdef CDEBUG
 
6712
    if (mswin_debug > 16)
 
6713
        fprintf (mswin_debugfile, "mswin_yeild::  Delay %ld msec\n",
 
6714
                GetTickCount () - start);
 
6715
#endif
 
6716
    return (didmsg);
 
6717
}
 
6718
 
 
6719
 
 
6720
/*
 
6721
 *      Called to see if we can process input.
 
6722
 *      We can't process input when we are in a scrolling mode.
 
6723
 */
 
6724
int
 
6725
mswin_caninput ()
 
6726
{
 
6727
    return (!gScrolling && !gMouseTracking);
 
6728
}
 
6729
 
 
6730
 
 
6731
/*
 
6732
 *      Called to see if there is a character available.
 
6733
 */
 
6734
int
 
6735
mswin_charavail (void)
 
6736
{
 
6737
    MSG         msg;
 
6738
    BOOL        ca, pa, ma;
 
6739
 
 
6740
    if (gScrolling)
 
6741
        return (FALSE);
 
6742
 
 
6743
    RestoreMouseCursor();
 
6744
 
 
6745
    /*
 
6746
     * If there are no windows messages waiting for this app, GetMessage
 
6747
     * can take a long time.  So before calling GetMessage check if
 
6748
     * there is anything I should be doing.  If there is, then only
 
6749
     * call PeekMessage.
 
6750
     * BUT!  Don't let too much time elapse between calls to GetMessage
 
6751
     * or we'll shut out other windows.
 
6752
     */
 
6753
    ca = CQAvailable ();
 
6754
    pa = EditPasteAvailable ();
 
6755
#ifdef CDEBUG
 
6756
    start = GetTickCount ();
 
6757
    if (mswin_debug > 16)
 
6758
        fprintf (mswin_debugfile, "%s mswin_charavail::  Entered, ca %d, pa %d\n",dtime(),ca,pa);
 
6759
#endif
 
6760
    if ((ca || pa) && GetTickCount () < gGMLastCall + GM_MAX_TIME)
 
6761
        ma = PeekMessage (&msg, NULL, 0, 0, PM_NOYIELD | PM_REMOVE);
 
6762
    else {
 
6763
        ma = GetMessage (&msg, NULL, 0, 0);
 
6764
        gGMLastCall = GetTickCount ();
 
6765
    }
 
6766
    if (ma) {
 
6767
        if (gpTTYInfo->hAccel == NULL ||
 
6768
                !TranslateAccelerator (ghTTYWnd, gpTTYInfo->hAccel, &msg)) {
 
6769
            TranslateMessage (&msg);
 
6770
            DispatchMessage (&msg);
 
6771
        }
 
6772
    }
 
6773
#ifdef CDEBUG
 
6774
    if (mswin_debug > 16)
 
6775
        fprintf (mswin_debugfile, "%s mswin_charavail::  Delay %ld msec\n",
 
6776
                dtime(), GetTickCount () - start);
 
6777
#endif
 
6778
 
 
6779
    return (pa || ca || CQAvailable ());
 
6780
}
 
6781
 
 
6782
 
 
6783
/*
 
6784
 *      Call to get next character.  Dispatch one message.
 
6785
 */
 
6786
UCS
 
6787
mswin_getc (void)
 
6788
{
 
6789
    BOOL        ca, pa, ma;
 
6790
    MSG         msg;
 
6791
 
 
6792
    if (gScrolling)
 
6793
        return (MSWIN_KEY_NODATA);
 
6794
 
 
6795
    RestoreMouseCursor();
 
6796
 
 
6797
    mswin_flush();
 
6798
 
 
6799
 
 
6800
    /*
 
6801
     * If there are no windows messages waiting for this app, GetMessage
 
6802
     * can take a long time.  So before calling GetMessage check if
 
6803
     * there is anything I should be doing.  If there is, then only
 
6804
     * call PeekMessage.
 
6805
     */
 
6806
    ca = CQAvailable ();
 
6807
    pa = EditPasteAvailable ();
 
6808
#ifdef CDEBUG
 
6809
    if (mswin_debug > 16) {
 
6810
        start = GetTickCount ();
 
6811
        fprintf (mswin_debugfile, "mswin_getc::  Entered, ca %d pa %d\n", ca, pa);
 
6812
    }
 
6813
#endif
 
6814
    if ((ca || pa) && GetTickCount () < gGMLastCall + GM_MAX_TIME)
 
6815
        ma = PeekMessage (&msg, NULL, 0, 0, PM_NOYIELD | PM_REMOVE);
 
6816
    else {
 
6817
        ma = GetMessage (&msg, NULL, 0, 0);
 
6818
        gGMLastCall = GetTickCount ();
 
6819
    }
 
6820
    if (ma) {
 
6821
        if (gpTTYInfo->hAccel == NULL ||
 
6822
                !TranslateAccelerator (ghTTYWnd, gpTTYInfo->hAccel, &msg)) {
 
6823
            TranslateMessage (&msg);
 
6824
            DispatchMessage (&msg);
 
6825
        }
 
6826
    }
 
6827
#ifdef CDEBUG
 
6828
    if (mswin_debug > 16)
 
6829
        fprintf (mswin_debugfile, "mswin_getc::  Delay %ld msec\n",
 
6830
                GetTickCount () - start);
 
6831
#endif
 
6832
 
 
6833
 
 
6834
    if (pa) {
 
6835
        SelClear ();
 
6836
        return (EditPasteGet ());
 
6837
    }
 
6838
    if (ca || CQAvailable ()) {
 
6839
        SelClear();
 
6840
        return ((UCS)(CQGet ()));
 
6841
    }
 
6842
 
 
6843
    return (MSWIN_KEY_NODATA);
 
6844
}
 
6845
 
 
6846
 
 
6847
/*
 
6848
 *      Like mswin_getc, but don't yield control.
 
6849
 */
 
6850
UCS
 
6851
mswin_getc_fast (void)
 
6852
{
 
6853
    RestoreMouseCursor();
 
6854
 
 
6855
    if (EditPasteAvailable ()) {
 
6856
        SelClear ();
 
6857
        return (EditPasteGet ());
 
6858
    }
 
6859
    if (CQAvailable ()) {
 
6860
        SelClear ();
 
6861
        return ((UCS)CQGet ());
 
6862
    }
 
6863
 
 
6864
    return (MSWIN_KEY_NODATA);
 
6865
}
 
6866
 
 
6867
 
 
6868
/*
 
6869
 * Flush the character input queue.
 
6870
 */
 
6871
void
 
6872
mswin_flush_input(void)
 
6873
{
 
6874
    /*
 
6875
     * GetQueueStatus tells us if there are any input messages in the message
 
6876
     * queue. If there are, we call mswin_getc which will retrieve the
 
6877
     * next message (which may or may not be an input message) and process
 
6878
     * it. We do that until all the input messages are gone.
 
6879
     */
 
6880
    CQInit();
 
6881
 
 
6882
    while(GetQueueStatus(QS_INPUT))
 
6883
      (void) mswin_getc();
 
6884
 
 
6885
    /* And we clear Pine's character input queue, too. */
 
6886
    CQInit();
 
6887
}
 
6888
 
 
6889
 
 
6890
/*
 
6891
 * ibmmove - Move cursor to...
 
6892
 */
 
6893
int
 
6894
mswin_move (int row, int column)
 
6895
 
 
6896
{
 
6897
    FlushWriteAccum ();
 
6898
    if (row < 0 || row >= gpTTYInfo->actNRow)
 
6899
        return (-1);
 
6900
    if (column < 0 || column >= gpTTYInfo->actNColumn)
 
6901
        return (-1);
 
6902
    gpTTYInfo->nRow = (CORD)row;
 
6903
    gpTTYInfo->nColumn = (CORD)column;
 
6904
    MoveTTYCursor (ghTTYWnd);
 
6905
    return (0);
 
6906
}
 
6907
 
 
6908
 
 
6909
int
 
6910
mswin_getpos (int *row, int *column)
 
6911
{
 
6912
    FlushWriteAccum ();
 
6913
    if (row == NULL || column == NULL)
 
6914
        return (-1);
 
6915
    *row = gpTTYInfo->nRow;
 
6916
    *column = gpTTYInfo->nColumn;
 
6917
    return (0);
 
6918
}
 
6919
 
 
6920
 
 
6921
int
 
6922
mswin_getscreensize (int *row, int *column)
 
6923
{
 
6924
    if (row == NULL || column == NULL)
 
6925
        return (-1);
 
6926
    *row = gpTTYInfo->actNRow;
 
6927
    *column = gpTTYInfo->actNColumn;
 
6928
#ifdef SDEBUG
 
6929
    if (mswin_debug >= 5)
 
6930
        fprintf (mswin_debugfile, "mswin_getscreensize::: reported size %d, %d\n",
 
6931
                *row, *column);
 
6932
#endif
 
6933
 
 
6934
    *column = MIN(*column, NLINE-1);
 
6935
 
 
6936
    return (0);
 
6937
}
 
6938
 
 
6939
 
 
6940
void
 
6941
mswin_minimize()
 
6942
{
 
6943
    if (!gpTTYInfo->fMinimized)
 
6944
      ShowWindow(ghTTYWnd, SW_MINIMIZE);
 
6945
}
 
6946
        
 
6947
 
 
6948
int
 
6949
mswin_showcursor (int show)
 
6950
{
 
6951
    int was_shown = gpTTYInfo->fCursorOn;
 
6952
 
 
6953
    if (show) {
 
6954
        /* if the cursor was not already show, show it now. */
 
6955
        if (!was_shown) {
 
6956
            gpTTYInfo->fCursorOn = TRUE;
 
6957
            ShowCursor(TRUE);
 
6958
        }
 
6959
    }
 
6960
    else {
 
6961
        /* If the cursor is shown, hide it. */
 
6962
        if (was_shown){
 
6963
            gpTTYInfo->fCursorOn = FALSE;
 
6964
            ShowCursor(FALSE);
 
6965
        }
 
6966
    }
 
6967
 
 
6968
    return (was_shown);
 
6969
}
 
6970
 
 
6971
 
 
6972
int
 
6973
mswin_showcaret (int show)
 
6974
{
 
6975
    int was_shown = gpTTYInfo->fCaretOn;
 
6976
 
 
6977
    if (show) {
 
6978
        /* if the caret was not already show, show it now. */
 
6979
        if (!was_shown) {
 
6980
            gpTTYInfo->fCaretOn = TRUE;
 
6981
            ShowCaret(ghTTYWnd);
 
6982
        }
 
6983
    }
 
6984
    else {
 
6985
        /* If the caret is shown, hide it. */
 
6986
        if (was_shown){
 
6987
            gpTTYInfo->fCaretOn = FALSE;
 
6988
            HideCaret(ghTTYWnd);
 
6989
        }
 
6990
    }
 
6991
 
 
6992
    return (was_shown);
 
6993
}
 
6994
 
 
6995
 
 
6996
int
 
6997
mswin_puts (char *utf8_str)
 
6998
{
 
6999
    int                 strLen;
 
7000
    LPTSTR              lptstr_str;
 
7001
 
 
7002
    FlushWriteAccum ();
 
7003
    if (utf8_str == NULL)
 
7004
        return (-1);
 
7005
    if(!(lptstr_str = utf8_to_lptstr(utf8_str)))
 
7006
      return(-1);
 
7007
    strLen = (int)_tcslen (lptstr_str);
 
7008
    if (strLen > 0)
 
7009
        WriteTTYText (ghTTYWnd, lptstr_str, strLen);
 
7010
 
 
7011
    fs_give((void **) &lptstr_str);
 
7012
    return (0);
 
7013
}
 
7014
 
 
7015
 
 
7016
int
 
7017
mswin_puts_n (char *utf8_str, int n)
 
7018
{
 
7019
    LPTSTR lptstr_str, lptstr_p;
 
7020
 
 
7021
    FlushWriteAccum ();
 
7022
    if (utf8_str == NULL)
 
7023
        return (-1);
 
7024
    lptstr_str = utf8_to_lptstr(utf8_str);
 
7025
    if(n < _tcslen(lptstr_str))
 
7026
      lptstr_str[n] = '\0';
 
7027
    for (lptstr_p = lptstr_str; n > 0 && *lptstr_p; n--, lptstr_p++)
 
7028
        ;
 
7029
    if (lptstr_p > lptstr_str)
 
7030
        WriteTTYText (ghTTYWnd, lptstr_str, (int)(lptstr_p - lptstr_str));
 
7031
 
 
7032
    fs_give((void **) &lptstr_str);
 
7033
    return (0);
 
7034
}
 
7035
 
 
7036
 
 
7037
int
 
7038
mswin_putblock (char *utf8_str, int strLen)
 
7039
{
 
7040
    LPTSTR lptstr_str;
 
7041
 
 
7042
    FlushWriteAccum ();
 
7043
    if (utf8_str == NULL)
 
7044
        return (-1);
 
7045
    lptstr_str = utf8_to_lptstr(utf8_str);
 
7046
    if (strLen > 0)
 
7047
        WriteTTYText (ghTTYWnd, lptstr_str, strLen);
 
7048
    fs_give((void **) &lptstr_str);
 
7049
    return (0);
 
7050
}
 
7051
 
 
7052
 
 
7053
/*
 
7054
 * mswin_putc - put a character at the current position in the
 
7055
 *           current colors
 
7056
 */
 
7057
int
 
7058
mswin_putc (UCS ucs)
 
7059
{
 
7060
    TCHAR cc = (TCHAR)ucs;
 
7061
    if (ucs >= (UCS)(' ')) {
 
7062
        /* Not carriage control. */
 
7063
        gpTTYInfo->writeAccum[gpTTYInfo->writeAccumCount++] = (TCHAR)ucs;
 
7064
        if (gpTTYInfo->writeAccumCount == WRITE_ACCUM_SIZE)
 
7065
                FlushWriteAccum ();
 
7066
    }
 
7067
    else {
 
7068
        /* Carriage control.  Need to flush write accumulator and
 
7069
         * write this char. */
 
7070
        FlushWriteAccum ();
 
7071
        WriteTTYBlock (ghTTYWnd, &cc, 1);
 
7072
    }
 
7073
    return (0);
 
7074
}
 
7075
 
 
7076
 
 
7077
/*
 
7078
 * ibmoutc - output a single character with the right attributes, but
 
7079
 *           don't advance the cursor
 
7080
 */
 
7081
int
 
7082
mswin_outc (char c)
 
7083
{
 
7084
    RECT        rect;
 
7085
    long        offset;
 
7086
 
 
7087
    FlushWriteAccum ();
 
7088
 
 
7089
    switch (c) {
 
7090
    case ASCII_BEL:
 
7091
        MessageBeep (0);
 
7092
        break;
 
7093
        
 
7094
    case ASCII_BS:
 
7095
    case ASCII_CR:
 
7096
    case ASCII_LF:
 
7097
        /* Do nothing for these screen motion characters. */
 
7098
        break;
 
7099
        
 
7100
        
 
7101
    default:
 
7102
        /* Paint character to screen. */
 
7103
        offset = (gpTTYInfo->nRow * gpTTYInfo->actNColumn) + gpTTYInfo->nColumn;
 
7104
        gpTTYInfo->pScreen[offset] = c;
 
7105
        gpTTYInfo->pCellWidth[offset] = wcellwidth((UCS)c) * gpTTYInfo->xChar;
 
7106
        gpTTYInfo->pAttrib[offset] = gpTTYInfo->curAttrib;
 
7107
        
 
7108
        /* Invalidate rectange covering singel character. */
 
7109
        rect.left = (gpTTYInfo->nColumn * gpTTYInfo->xChar) +
 
7110
                gpTTYInfo->xOffset;
 
7111
        rect.right = rect.left + gpTTYInfo->xChar;
 
7112
        rect.top = (gpTTYInfo->nRow * gpTTYInfo->yChar) +
 
7113
                gpTTYInfo->yOffset;
 
7114
        rect.bottom = rect.top + gpTTYInfo->yChar;
 
7115
        gpTTYInfo->screenDirty = TRUE;
 
7116
        InvalidateRect (ghTTYWnd, &rect, FALSE);
 
7117
        break;
 
7118
    }
 
7119
    return (0);
 
7120
}
 
7121
 
 
7122
/*
 
7123
 * ibmrev - change reverse video state
 
7124
 */
 
7125
int
 
7126
mswin_rev (int state)
 
7127
{
 
7128
    int curState = (gpTTYInfo->curAttrib.style & CHAR_ATTR_REV) != 0;
 
7129
 
 
7130
    if (state != curState){
 
7131
        FlushWriteAccum ();
 
7132
        if (state) {
 
7133
            gpTTYInfo->curAttrib.style |= CHAR_ATTR_REV;
 
7134
            SetReverseColor();
 
7135
        }
 
7136
        else{
 
7137
            gpTTYInfo->curAttrib.style &= ~CHAR_ATTR_REV;
 
7138
            pico_set_normal_color();
 
7139
        }
 
7140
    }
 
7141
 
 
7142
    return (0);
 
7143
}
 
7144
        
 
7145
 
 
7146
/*
 
7147
 * Get current reverse video state.
 
7148
 */
 
7149
int
 
7150
mswin_getrevstate (void)
 
7151
{
 
7152
    return ((gpTTYInfo->curAttrib.style & CHAR_ATTR_REV) != 0);
 
7153
}
 
7154
 
 
7155
 
 
7156
/*
 
7157
 * ibmrev - change reverse video state
 
7158
 */
 
7159
int
 
7160
mswin_bold (int state)
 
7161
{
 
7162
    int curState = (gpTTYInfo->curAttrib.style & CHAR_ATTR_BOLD) != 0;
 
7163
 
 
7164
    if (state != curState){
 
7165
        FlushWriteAccum ();
 
7166
        if (state)
 
7167
          gpTTYInfo->curAttrib.style |= CHAR_ATTR_BOLD;
 
7168
        else
 
7169
          gpTTYInfo->curAttrib.style &= ~CHAR_ATTR_BOLD;
 
7170
    }
 
7171
 
 
7172
    return (0);
 
7173
}
 
7174
        
 
7175
 
 
7176
/*
 
7177
 * ibmrev - change reverse video state
 
7178
 */
 
7179
int
 
7180
mswin_uline (int state)
 
7181
{
 
7182
    int curState = (gpTTYInfo->curAttrib.style & CHAR_ATTR_ULINE) != 0;
 
7183
 
 
7184
    if (state != curState){
 
7185
        FlushWriteAccum ();
 
7186
        if (state)
 
7187
          gpTTYInfo->curAttrib.style |= CHAR_ATTR_ULINE;
 
7188
        else
 
7189
          gpTTYInfo->curAttrib.style &= ~CHAR_ATTR_ULINE;
 
7190
    }
 
7191
 
 
7192
    return (0);
 
7193
}
 
7194
 
 
7195
 
 
7196
/*
 
7197
 * ibmeeol - erase to the end of the line
 
7198
 */
 
7199
int
 
7200
mswin_eeol (void)
 
7201
{
 
7202
    TCHAR       *cStart;
 
7203
    CharAttrib  *aStart;
 
7204
    int         *cwStart;
 
7205
    long        length, i;
 
7206
    RECT        rect;
 
7207
 
 
7208
    FlushWriteAccum ();
 
7209
 
 
7210
    /* From current position to end of line. */
 
7211
    length = gpTTYInfo->actNColumn - gpTTYInfo->nColumn;                
 
7212
 
 
7213
    cStart = gpTTYInfo->pScreen + (gpTTYInfo->nRow * gpTTYInfo->actNColumn)
 
7214
                        + gpTTYInfo->nColumn;
 
7215
    cwStart = gpTTYInfo->pCellWidth + (gpTTYInfo->nRow * gpTTYInfo->actNColumn)
 
7216
                        + gpTTYInfo->nColumn;
 
7217
    for(i = 0; i < length; i++){
 
7218
        cStart[i] = (TCHAR)(' ');
 
7219
        cwStart[i] = gpTTYInfo->xChar;
 
7220
    }
 
7221
 
 
7222
    aStart = gpTTYInfo->pAttrib
 
7223
                      + (gpTTYInfo->nRow * gpTTYInfo->actNColumn)
 
7224
                      + gpTTYInfo->nColumn;
 
7225
    for(; length > 0; length--, aStart++){
 
7226
        aStart->style = CHAR_ATTR_NORM;
 
7227
        aStart->rgbFG = gpTTYInfo->curAttrib.rgbFG;
 
7228
        aStart->rgbBG = gpTTYInfo->curAttrib.rgbBG;
 
7229
    }
 
7230
 
 
7231
    rect.left = (gpTTYInfo->nColumn * gpTTYInfo->xChar) +
 
7232
            gpTTYInfo->xOffset;
 
7233
    rect.right = gpTTYInfo->xSize;
 
7234
    rect.top = (gpTTYInfo->nRow * gpTTYInfo->yChar) +
 
7235
            gpTTYInfo->yOffset;
 
7236
    rect.bottom = rect.top + gpTTYInfo->yChar;
 
7237
    gpTTYInfo->screenDirty = TRUE;
 
7238
    InvalidateRect (ghTTYWnd, &rect, FALSE);
 
7239
 
 
7240
    return (0);
 
7241
}
 
7242
 
 
7243
 
 
7244
/*
 
7245
 * ibmeeop - clear from cursor to end of page
 
7246
 */
 
7247
int
 
7248
mswin_eeop (void)
 
7249
{
 
7250
    TCHAR       *cStart;
 
7251
    CharAttrib  *aStart;
 
7252
    int         *cwStart;
 
7253
    long        length, i;
 
7254
    RECT        rect;
 
7255
 
 
7256
    FlushWriteAccum ();
 
7257
    /* From current position to end of screen. */
 
7258
 
 
7259
    cStart = gpTTYInfo->pScreen + (gpTTYInfo->nRow * gpTTYInfo->actNColumn)
 
7260
                        + gpTTYInfo->nColumn;
 
7261
    cwStart = gpTTYInfo->pCellWidth + (gpTTYInfo->nRow * gpTTYInfo->actNColumn)
 
7262
                        + gpTTYInfo->nColumn;
 
7263
    length = (long)((gpTTYInfo->pScreen
 
7264
                              + (gpTTYInfo->actNColumn * gpTTYInfo->actNRow))
 
7265
                              - cStart);
 
7266
    for(i = 0; i < length; i ++){
 
7267
        cStart[i] = (TCHAR)(' ');
 
7268
        cwStart[i] = gpTTYInfo->xChar;
 
7269
    }
 
7270
 
 
7271
    aStart = gpTTYInfo->pAttrib
 
7272
                      + (gpTTYInfo->nRow * gpTTYInfo->actNColumn)
 
7273
                      + gpTTYInfo->nColumn;
 
7274
 
 
7275
    for(; length-- > 0; aStart++){
 
7276
        aStart->style = CHAR_ATTR_NORM;
 
7277
        aStart->rgbFG = gpTTYInfo->curAttrib.rgbFG;
 
7278
        aStart->rgbBG = gpTTYInfo->curAttrib.rgbBG;
 
7279
    }
 
7280
 
 
7281
    /* Invalidate a rectangle that includes all of the current line down
 
7282
     * to the bottom of the window. */
 
7283
    rect.left = 0;
 
7284
    rect.right = gpTTYInfo->xSize;
 
7285
    rect.top = (gpTTYInfo->nRow * gpTTYInfo->yChar) +
 
7286
            gpTTYInfo->yOffset;
 
7287
    rect.bottom = gpTTYInfo->ySize;
 
7288
    gpTTYInfo->screenDirty = TRUE;
 
7289
    InvalidateRect (ghTTYWnd, &rect, FALSE);
 
7290
 
 
7291
    return (0);
 
7292
}
 
7293
 
 
7294
 
 
7295
/*
 
7296
 * ibmbeep - system beep...
 
7297
 */
 
7298
int
 
7299
mswin_beep (void)
 
7300
{
 
7301
    MessageBeep (MB_OK);
 
7302
    return (0);
 
7303
}
 
7304
 
 
7305
 
 
7306
/*
 
7307
 * pause - wait in function for specified number of seconds.
 
7308
 */
 
7309
void
 
7310
mswin_pause (int seconds)
 
7311
{
 
7312
    DWORD       stoptime;
 
7313
 
 
7314
    stoptime = GetTickCount () + (DWORD) seconds * 1000;
 
7315
    while (stoptime > GetTickCount ())
 
7316
        mswin_yeild ();
 
7317
}
 
7318
        
 
7319
 
 
7320
/*
 
7321
 * ibmflush - Flush output to screen.
 
7322
 *
 
7323
 */
 
7324
int
 
7325
mswin_flush (void)
 
7326
{
 
7327
 
 
7328
    /*
 
7329
     * Flush cached changes, then update the window.
 
7330
     */
 
7331
    FlushWriteAccum ();
 
7332
    UpdateWindow (ghTTYWnd);
 
7333
 
 
7334
    return (0);
 
7335
}
 
7336
 
 
7337
 
 
7338
/*
 
7339
 * A replacement for fflush
 
7340
 * relies on #define fflush mswin_fflush
 
7341
 */
 
7342
#undef fflush
 
7343
int
 
7344
mswin_fflush (FILE *f)
 
7345
{
 
7346
    if (f == stdout) {
 
7347
        mswin_flush();
 
7348
    }
 
7349
    else
 
7350
        fflush (f);
 
7351
 
 
7352
    return(0);
 
7353
}
 
7354
 
 
7355
 
 
7356
/*
 
7357
 * Set the cursor
 
7358
 */
 
7359
void
 
7360
mswin_setcursor (int newcursor)
 
7361
{
 
7362
    HCURSOR hNewCursor;
 
7363
 
 
7364
    switch(newcursor){
 
7365
      case MSWIN_CURSOR_BUSY :
 
7366
        hNewCursor = ghCursorBusy;
 
7367
        mswin_showcursor(TRUE);
 
7368
        break;
 
7369
 
 
7370
      case MSWIN_CURSOR_IBEAM :
 
7371
        hNewCursor = ghCursorIBeam;
 
7372
        break;
 
7373
 
 
7374
      case MSWIN_CURSOR_HAND :
 
7375
        if(hNewCursor = ghCursorHand)
 
7376
          break;
 
7377
        /* ELSE fall thru to normal cursor */
 
7378
 
 
7379
      case MSWIN_CURSOR_ARROW :
 
7380
      default :
 
7381
        hNewCursor = ghCursorArrow;
 
7382
        break;
 
7383
    }
 
7384
 
 
7385
    /* If new cursor requested, select it. */
 
7386
    if (ghCursorCurrent != hNewCursor)
 
7387
      SetCursor (ghCursorCurrent = hNewCursor);
 
7388
}
 
7389
 
 
7390
 
 
7391
void
 
7392
RestoreMouseCursor()
 
7393
{
 
7394
    if(ghCursorCurrent == ghCursorBusy)
 
7395
      mswin_setcursor(MSWIN_CURSOR_ARROW);
 
7396
}
 
7397
 
 
7398
 
 
7399
/*
 
7400
 * Display message in windows dialog box.
 
7401
 */
 
7402
void
 
7403
mswin_messagebox (char *msg_utf8, int err)
 
7404
{
 
7405
    LPTSTR msg_lptstr;
 
7406
 
 
7407
    mswin_killsplash();
 
7408
 
 
7409
    msg_lptstr = utf8_to_lptstr(msg_utf8);
 
7410
    MessageBox (NULL, msg_lptstr, gszAppName,
 
7411
                MB_OK | ((err) ?  MB_ICONSTOP : MB_ICONINFORMATION));
 
7412
    fs_give((void **) &msg_lptstr);
 
7413
}
 
7414
 
 
7415
 
 
7416
/*
 
7417
 * Signals whether or not Paste should be turned on in the
 
7418
 * menu bar.
 
7419
 */
 
7420
void
 
7421
mswin_allowpaste (int on)
 
7422
{
 
7423
    static short         stackp = 0;
 
7424
    static unsigned long stack = 0L;
 
7425
 
 
7426
    switch(on){
 
7427
      case MSWIN_PASTE_DISABLE :
 
7428
        if(stackp){             /* previous state? */
 
7429
            if((stackp -= 2) < 0)
 
7430
              stackp = 0;
 
7431
 
 
7432
            gPasteEnabled = ((stack >> stackp) & 0x03);
 
7433
        }
 
7434
        else
 
7435
          gPasteEnabled = MSWIN_PASTE_DISABLE;
 
7436
 
 
7437
        break;
 
7438
 
 
7439
      case MSWIN_PASTE_FULL :
 
7440
      case MSWIN_PASTE_LINE :
 
7441
        if(gPasteEnabled){      /* current state? */
 
7442
            stack |= ((unsigned long) gPasteEnabled << stackp);
 
7443
            stackp += 2;
 
7444
        }
 
7445
 
 
7446
        gPasteEnabled = on;
 
7447
        break;
 
7448
    }
 
7449
 
 
7450
#ifdef  ACCELERATORS
 
7451
    UpdateAccelerators(ghTTYWnd);
 
7452
#endif
 
7453
}
 
7454
 
 
7455
 
 
7456
/*
 
7457
 * Signals whether or not Copy/Cut should be turned on in the
 
7458
 * menu bar.
 
7459
 */
 
7460
void
 
7461
mswin_allowcopy (getc_t copyfunc)
 
7462
{
 
7463
    gCopyCutFunction = copyfunc;
 
7464
    gAllowCopy = (copyfunc != NULL);
 
7465
#ifdef  ACCELERATORS
 
7466
    UpdateAccelerators(ghTTYWnd);
 
7467
#endif
 
7468
}
 
7469
 
 
7470
 
 
7471
/*
 
7472
 * Signals whether or not Copy/Cut should be turned on in the
 
7473
 * menu bar.
 
7474
 */
 
7475
void
 
7476
mswin_allowcopycut (getc_t copyfunc)
 
7477
{
 
7478
    gCopyCutFunction = copyfunc;
 
7479
    gAllowCopy = gAllowCut = (copyfunc != NULL);
 
7480
#ifdef  ACCELERATORS
 
7481
    UpdateAccelerators(ghTTYWnd);
 
7482
#endif
 
7483
}
 
7484
 
 
7485
 
 
7486
/*
 
7487
 * Replace the clipboard's contents with the given string
 
7488
 */
 
7489
void
 
7490
mswin_addclipboard(char *s)
 
7491
{
 
7492
    HANDLE  hCB;
 
7493
    char   *pCB;
 
7494
    size_t  sSize;
 
7495
 
 
7496
    if(s && (sSize = strlen(s))){
 
7497
        if (OpenClipboard (ghTTYWnd)) {         /* ...and we get the CB. */
 
7498
            if (EmptyClipboard ()
 
7499
                && (hCB = GlobalAlloc (GMEM_MOVEABLE, sSize+2))){
 
7500
                pCB = GlobalLock (hCB);
 
7501
                memcpy (pCB, s, sSize);
 
7502
                pCB[sSize] = '\0';              /* tie it off  */
 
7503
 
 
7504
                GlobalUnlock (hCB);
 
7505
 
 
7506
                if (SetClipboardData (CF_TEXT, hCB) == NULL)
 
7507
                  /* Failed!  Free the data. */
 
7508
                  GlobalFree (hCB);
 
7509
            }
 
7510
 
 
7511
            CloseClipboard ();
 
7512
        }
 
7513
    }
 
7514
}
 
7515
 
 
7516
 
 
7517
/*
 
7518
 * Signals if the upper layer wants to track the mouse.
 
7519
 */
 
7520
void
 
7521
mswin_allowmousetrack (int b)
 
7522
{
 
7523
    gAllowMouseTrack = b;
 
7524
    if (b)
 
7525
        SelClear ();
 
7526
    MyTimerSet ();
 
7527
}
 
7528
 
 
7529
 
 
7530
/*
 
7531
 * register's callback to warn
 
7532
 */
 
7533
void
 
7534
mswin_mousetrackcallback(cbarg_t cbfunc)
 
7535
{
 
7536
    if(!(gMouseTrackCallback = cbfunc))
 
7537
      mswin_setcursor (MSWIN_CURSOR_ARROW);
 
7538
}
 
7539
 
 
7540
 
 
7541
/*
 
7542
 * Add text to the new mail icon.
 
7543
 * Nothing done in win 3.1 (consider changing the program name?)
 
7544
 * For win95 we add some tool tip text to the tray icon.
 
7545
 */
 
7546
void
 
7547
mswin_newmailtext (char *t_utf8)
 
7548
{
 
7549
    LPTSTR t_lptstr;
 
7550
 
 
7551
    /*
 
7552
     * If we're given text, then blip the icon to let the user know.
 
7553
     * (NOTE: the new shell also gets an updated tooltip.)
 
7554
     * Otherwise, we're being asked to resume our normal state...
 
7555
     */
 
7556
    if(t_utf8){
 
7557
        /*
 
7558
         * Change the appearance of minimized icon so user knows there's new
 
7559
         * mail waiting for them.  On win 3.1 systems we redraw the icon.
 
7560
         * on win95 systems we update the icon in the task bar,
 
7561
         * and possibly udpate the small icon in the taskbar tool tray.
 
7562
         */
 
7563
        t_lptstr = utf8_to_lptstr(t_utf8);
 
7564
        UpdateTrayIcon(NIM_MODIFY, ghNewMailIcon, t_lptstr);
 
7565
        fs_give((void **) &t_lptstr);
 
7566
        PostMessage(ghTTYWnd,WM_SETICON,ICON_BIG,(LPARAM) ghNewMailIcon);
 
7567
        PostMessage(ghTTYWnd,WM_SETICON,ICON_SMALL,(LPARAM) ghNewMailIcon);
 
7568
 
 
7569
        gpTTYInfo->fNewMailIcon = TRUE;
 
7570
    }
 
7571
    else if(gpTTYInfo->fNewMailIcon) {
 
7572
        UpdateTrayIcon(NIM_MODIFY, ghNormalIcon, TEXT("Alpine"));
 
7573
        PostMessage(ghTTYWnd,WM_SETICON,ICON_BIG,(LPARAM) ghNormalIcon);
 
7574
        PostMessage(ghTTYWnd,WM_SETICON,ICON_SMALL,(LPARAM) ghNormalIcon);
 
7575
 
 
7576
        gpTTYInfo->fNewMailIcon = FALSE;
 
7577
    }
 
7578
}
 
7579
 
 
7580
 
 
7581
void
 
7582
mswin_mclosedtext (char *t_utf8)
 
7583
{
 
7584
    LPTSTR t_lptstr;
 
7585
 
 
7586
    if(t_utf8 && gpTTYInfo->fMClosedIcon == FALSE){
 
7587
        /*
 
7588
         * Change the appearance of minimized icon so user knows
 
7589
         * the mailbox closed.
 
7590
         */
 
7591
        t_lptstr = utf8_to_lptstr(t_utf8);
 
7592
        UpdateTrayIcon(NIM_MODIFY, ghMClosedIcon, t_lptstr);
 
7593
        fs_give((void **) &t_lptstr);
 
7594
        PostMessage(ghTTYWnd,WM_SETICON,ICON_BIG,(LPARAM) ghMClosedIcon);
 
7595
        PostMessage(ghTTYWnd,WM_SETICON,ICON_SMALL,(LPARAM) ghMClosedIcon);
 
7596
 
 
7597
        gpTTYInfo->fMClosedIcon = TRUE;
 
7598
    }
 
7599
    else if(t_utf8 == NULL && gpTTYInfo->fMClosedIcon) {
 
7600
        /* only go from yellow to green */
 
7601
        UpdateTrayIcon(NIM_MODIFY, ghNormalIcon, TEXT("Alpine"));
 
7602
        PostMessage(ghTTYWnd,WM_SETICON,ICON_BIG,(LPARAM) ghNormalIcon);
 
7603
        PostMessage(ghTTYWnd,WM_SETICON,ICON_SMALL,(LPARAM) ghNormalIcon);
 
7604
 
 
7605
        gpTTYInfo->fMClosedIcon = FALSE;
 
7606
    }
 
7607
}
 
7608
 
 
7609
void
 
7610
mswin_trayicon(int show)
 
7611
{
 
7612
    if(show){
 
7613
        if(!gpTTYInfo->fTrayIcon){
 
7614
            UpdateTrayIcon(NIM_ADD, ghNormalIcon, TEXT("Alpine"));
 
7615
            gpTTYInfo->fTrayIcon = TRUE;
 
7616
        }
 
7617
    }
 
7618
    else{
 
7619
        if(gpTTYInfo->fTrayIcon){
 
7620
            UpdateTrayIcon(NIM_DELETE, 0, NULL);
 
7621
            gpTTYInfo->fTrayIcon = FALSE;
 
7622
        }
 
7623
    }
 
7624
}
 
7625
 
 
7626
 
 
7627
void
 
7628
UpdateTrayIcon(DWORD dwMsg, HICON hIcon, LPTSTR tip)
 
7629
{
 
7630
    NOTIFYICONDATA nt;
 
7631
 
 
7632
    nt.cbSize = sizeof (nt);
 
7633
    nt.hWnd   = ghTTYWnd;
 
7634
    nt.uID    = TASKBAR_ICON_NEWMAIL;
 
7635
    switch(dwMsg){
 
7636
      case NIM_DELETE :
 
7637
        nt.uFlags = 0;
 
7638
        break;
 
7639
 
 
7640
      case NIM_ADD :            /* send msg to add icon to tray */
 
7641
        nt.uFlags = NIF_ICON | NIF_MESSAGE | NIF_TIP;
 
7642
        nt.uCallbackMessage = TASKBAR_ICON_MESSAGE;
 
7643
 
 
7644
        if(tip){
 
7645
            _tcsncpy (nt.szTip, tip, 63);
 
7646
            nt.szTip[63] = '\0';
 
7647
        }
 
7648
        else
 
7649
          nt.szTip[0] = '\0';
 
7650
        nt.hIcon = hIcon;
 
7651
        break;
 
7652
 
 
7653
      case NIM_MODIFY :         /* send msg to modify icon in tray */
 
7654
        nt.uFlags = NIF_ICON | NIF_TIP;
 
7655
        if(tip){
 
7656
            _tcsncpy (nt.szTip, tip, 63);
 
7657
            nt.szTip[63] = '\0';
 
7658
        }
 
7659
        else
 
7660
          nt.szTip[0] = '\0';
 
7661
        nt.hIcon = hIcon;
 
7662
        break;
 
7663
 
 
7664
      default :
 
7665
        return;
 
7666
    }
 
7667
 
 
7668
    Shell_NotifyIcon (dwMsg, &nt);
 
7669
}
 
7670
        
 
7671
 
 
7672
 
 
7673
/*---------------------------------------------------------------------------
 
7674
 *
 
7675
 * Client level menu item stuff.
 
7676
 *
 
7677
 * These are menu items that activate commands in the "client" program.
 
7678
 * Generally, the client calls us to tell us which menu items are active
 
7679
 * and what key stroke they generate.  When such an item is selected it's
 
7680
 * key stroke is injected into the character queue as if it was typed by
 
7681
 * the user.
 
7682
 *
 
7683
 *-------------------------------------------------------------------------*/
 
7684
 
 
7685
/*
 
7686
 * Clear active status of all "menu items".
 
7687
 */
 
7688
void
 
7689
mswin_menuitemclear (void)
 
7690
{
 
7691
    int                 i;
 
7692
    HWND                hWnd;
 
7693
 
 
7694
 
 
7695
    for (i = 0; i < KS_COUNT; ++i) {
 
7696
        gpTTYInfo->menuItems[i].miActive = FALSE;
 
7697
        if (gpTTYInfo->toolBarSize > 0) {
 
7698
            hWnd = GetDlgItem(gpTTYInfo->hTBWnd, i + KS_RANGESTART);
 
7699
            if (hWnd != NULL)
 
7700
                EnableWindow(hWnd, FALSE);
 
7701
        }
 
7702
    }
 
7703
 
 
7704
    gpTTYInfo->menuItemsCurrent = FALSE;
 
7705
    gpTTYInfo->menuItemsIndex = 1;
 
7706
    for(i = 0; i < KS_COUNT; i++)
 
7707
      gpTTYInfo->menuItems[i].miIndex = 0;
 
7708
}
 
7709
 
 
7710
 
 
7711
/*
 
7712
 * Add an item to the cmdmenu
 
7713
 */
 
7714
void
 
7715
mswin_menuitemadd (UCS key, char *label, int menuitem, int flags)
 
7716
{
 
7717
    int                 i;
 
7718
    HWND                hWnd;
 
7719
 
 
7720
    if (menuitem >= KS_RANGESTART && menuitem <= KS_RANGEEND) {
 
7721
        
 
7722
        gpTTYInfo->menuItemsCurrent = FALSE;
 
7723
        
 
7724
        i = menuitem - KS_RANGESTART;
 
7725
        gpTTYInfo->menuItems[i].miActive = TRUE;
 
7726
        gpTTYInfo->menuItems[i].miKey = key;
 
7727
        if(!gpTTYInfo->menuItems[i].miIndex){
 
7728
            gpTTYInfo->menuItems[i].miLabel = label;
 
7729
            gpTTYInfo->menuItems[i].miIndex = gpTTYInfo->menuItemsIndex++;
 
7730
        }
 
7731
 
 
7732
        if (gpTTYInfo->toolBarSize > 0) {
 
7733
            hWnd = GetDlgItem(gpTTYInfo->hTBWnd, menuitem);
 
7734
            if (hWnd != NULL)
 
7735
                EnableWindow(hWnd, TRUE);
 
7736
        }
 
7737
    }
 
7738
}
 
7739
 
 
7740
 
 
7741
/*
 
7742
 * Called when a menu command arrives with an unknown ID.  If it is
 
7743
 * within the range of the additional menu items, insert the
 
7744
 * corresponding character into the char input queue.
 
7745
 */
 
7746
void
 
7747
ProcessMenuItem (HWND hWnd, WPARAM wParam)
 
7748
{
 
7749
    PTTYINFO            pTTYInfo;
 
7750
    int                 i;
 
7751
 
 
7752
    pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
 
7753
    if (pTTYInfo == NULL)
 
7754
        return;
 
7755
 
 
7756
 
 
7757
    if (wParam >= KS_RANGESTART && wParam <= KS_RANGEEND) {
 
7758
        i = (int)(wParam - KS_RANGESTART);
 
7759
        if (pTTYInfo->menuItems[i].miActive)
 
7760
            CQAdd (pTTYInfo->menuItems[i].miKey, 0);
 
7761
    }
 
7762
}
 
7763
 
 
7764
 
 
7765
/*
 
7766
 * Called to set a new menu.
 
7767
 */
 
7768
int
 
7769
mswin_setwindowmenu (int menu)
 
7770
{
 
7771
    int         oldmenu;
 
7772
    HMENU       holdmenu;
 
7773
    HMENU       hmenu;
 
7774
 
 
7775
 
 
7776
    oldmenu = gpTTYInfo->curWinMenu;
 
7777
    holdmenu = GetMenu (ghTTYWnd);
 
7778
    if (gpTTYInfo->curWinMenu != menu) {
 
7779
        
 
7780
        hmenu = LoadMenu (ghInstance, MAKEINTRESOURCE (menu));
 
7781
        if (hmenu != NULL) {
 
7782
            if (SetMenu (ghTTYWnd, hmenu) != 0) {
 
7783
                DestroyMenu (holdmenu);
 
7784
                gfHelpMenu = gfHelpGenMenu = FALSE;
 
7785
                gpTTYInfo->curWinMenu = menu;
 
7786
            }
 
7787
        }
 
7788
 
 
7789
        if(menu == MENU_DEFAULT){
 
7790
            TBSwap (ghTTYWnd, IDD_TOOLBAR);
 
7791
            if(hmenu != NULL)
 
7792
              (void) MSWHelpSetMenu(hmenu);
 
7793
        }
 
7794
        else{
 
7795
            TBSwap (ghTTYWnd, IDD_COMPOSER_TB);
 
7796
        }
 
7797
    }
 
7798
    return (oldmenu);
 
7799
}
 
7800
 
 
7801
 
 
7802
 
 
7803
/*---------------------------------------------------------------------------
 
7804
 *
 
7805
 * Printing stuff
 
7806
 *
 
7807
 *-------------------------------------------------------------------------*/
 
7808
 
 
7809
/*
 
7810
 * Printing globals
 
7811
 */
 
7812
LOCAL HDC       P_PrintDC;      /* Printer device context. */
 
7813
LOCAL int       P_PageRows;     /* Number of rows we put on a page. */
 
7814
LOCAL int       P_PageColumns;  /* Number of columns we put on a page. */
 
7815
LOCAL int       P_RowHeight;    /* Hight of a row in printer pixels. */
 
7816
LOCAL int       P_CurRow;       /* Current row, starting at zero */
 
7817
LOCAL int       P_CurCol;       /* Current col, starting at zero. */
 
7818
LOCAL int       P_TopOffset;    /* Top Margin offset, in pixels. */
 
7819
LOCAL int       P_LeftOffset;   /* Top Margin offset, in pixels. */
 
7820
LOCAL HFONT     P_hFont;        /* Handle to printing font. */
 
7821
LPTSTR          P_LineText;     /* Pointer to line buffer. */
 
7822
 
 
7823
 
 
7824
 
 
7825
 
 
7826
/*
 
7827
 * Define the margin as number of lines at top and bottom of page.
 
7828
 * (might be better to define as a percent of verticle page size)
 
7829
 */
 
7830
#define VERTICLE_MARGIN         3       /* lines at top and bottom of page. */
 
7831
#define HORIZONTAL_MARGIN       1       /* margine at left & right in chars */
 
7832
 
 
7833
/*
 
7834
 * Several errors that can be reported.
 
7835
 */
 
7836
#define PE_DIALOG_FAILED        1
 
7837
#define PE_USER_CANCEL          2
 
7838
#define PE_CANT_START_DOC       3
 
7839
#define PE_CANT_FINISH_DOC      4
 
7840
#define PE_OUT_OF_MEMORY        5
 
7841
#define PE_GENERAL_ERROR        6
 
7842
#define PE_OUT_OF_DISK          7
 
7843
#define PE_PRINTER_NOT_FOUND    8
 
7844
#define PE_PINE_INTERNAL        9
 
7845
#define PE_FONT_FAILED          10
 
7846
 
 
7847
 
 
7848
LOCAL struct pe_error_message {
 
7849
        int             error_code;
 
7850
        char            *error_message;
 
7851
 } P_ErrorMessages[] = {
 
7852
        { PE_DIALOG_FAILED,     "Print Dialog Failed"},
 
7853
        { PE_USER_CANCEL,       "User canceled" },
 
7854
        { PE_CANT_START_DOC,    "Can't start document" },
 
7855
        { PE_OUT_OF_MEMORY,     "Out of memory" },
 
7856
        { PE_CANT_FINISH_DOC,   "Can't finish document" },
 
7857
        { PE_OUT_OF_MEMORY,     "Out of memory" },
 
7858
        { PE_OUT_OF_DISK,       "Out of disk space" },
 
7859
        { PE_PRINTER_NOT_FOUND, "Printer not found" },
 
7860
        { PE_PINE_INTERNAL,     "Pine internal error" },
 
7861
        { PE_FONT_FAILED,       "Failed to create font" },
 
7862
        { 0, NULL }};
 
7863
 
 
7864
 
 
7865
 
 
7866
/*
 
7867
 * Send text in the line buffer to the printer.
 
7868
 * Advance to next page if necessary.
 
7869
 */
 
7870
LOCAL int
 
7871
_print_send_line (void)
 
7872
{
 
7873
    int         status;
 
7874
 
 
7875
    status = 0;
 
7876
    if (P_CurCol > 0)
 
7877
        TextOut (P_PrintDC, P_LeftOffset,
 
7878
                                P_TopOffset + (P_CurRow * P_RowHeight),
 
7879
                P_LineText, P_CurCol);
 
7880
    P_CurCol = 0;
 
7881
    if (++P_CurRow >= P_PageRows)
 
7882
        status = _print_send_page ();
 
7883
        
 
7884
    return (status);
 
7885
}
 
7886
 
 
7887
 
 
7888
 
 
7889
/*
 
7890
 * Advance one page.
 
7891
 */
 
7892
int
 
7893
_print_send_page (void)
 
7894
{
 
7895
    DWORD status;
 
7896
 
 
7897
    if((status = EndPage (P_PrintDC)) > 0){
 
7898
        P_CurRow = 0;
 
7899
        if((status = StartPage (P_PrintDC)) > 0){
 
7900
            SelectObject (P_PrintDC, P_hFont);
 
7901
            return(0);
 
7902
        }
 
7903
    }
 
7904
 
 
7905
#ifdef  WIN32
 
7906
    ExplainSystemErr();
 
7907
    return(PE_GENERAL_ERROR);
 
7908
#else
 
7909
    switch (status) {
 
7910
    case SP_USERABORT:          return (PE_USER_CANCEL);
 
7911
    case SP_OUTOFDISK:          return (PE_OUT_OF_DISK);
 
7912
    case SP_OUTOFMEMORY:        return (PE_OUT_OF_MEMORY);
 
7913
    default:
 
7914
    case SP_ERROR:              break;
 
7915
    }
 
7916
#endif
 
7917
    return (PE_GENERAL_ERROR);
 
7918
}
 
7919
 
 
7920
 
 
7921
 
 
7922
/*
 
7923
 * Map errors reported to my own error set.
 
7924
 */
 
7925
int
 
7926
_print_map_dlg_error (DWORD error)
 
7927
{
 
7928
    switch (error) {
 
7929
    case 0:                         return (PE_USER_CANCEL);
 
7930
    case CDERR_MEMALLOCFAILURE:
 
7931
    case CDERR_MEMLOCKFAILURE:
 
7932
                                    return (PE_OUT_OF_MEMORY);
 
7933
    case PDERR_PRINTERNOTFOUND:
 
7934
    case PDERR_NODEVICES:
 
7935
                                    return (PE_PRINTER_NOT_FOUND);
 
7936
    case CDERR_STRUCTSIZE:
 
7937
                                    return (PE_PINE_INTERNAL);
 
7938
    default:
 
7939
                                    return (PE_GENERAL_ERROR);
 
7940
    }
 
7941
}
 
7942
        
 
7943
 
 
7944
 
 
7945
/*
 
7946
 * Get the printer ready.  Returns ZERO for success, or an error code that
 
7947
 * can be passed to mswin_print_error() to get a text message.
 
7948
 */
 
7949
int
 
7950
mswin_print_ready(WINHAND hWnd, LPTSTR docDesc)
 
7951
{
 
7952
    PRINTDLG            pd;
 
7953
    DOCINFO             di;
 
7954
    TEXTMETRIC          tm;
 
7955
    HDC                 hDC;
 
7956
    int                 fontSize;       /* Size in Points. */
 
7957
    int                 ppi;            /* Pixels per inch in device. */
 
7958
    int                 xChar;
 
7959
    int                 status;
 
7960
    HFONT               oldFont;
 
7961
    LOGFONT             newFont;
 
7962
 
 
7963
 
 
7964
    status = 0;
 
7965
    P_PrintDC = NULL;
 
7966
 
 
7967
 
 
7968
    /*
 
7969
     * Show print dialog.
 
7970
     */
 
7971
    memset(&pd, 0, sizeof(PRINTDLG));
 
7972
    pd.lStructSize = sizeof (PRINTDLG);
 
7973
    pd.hwndOwner = (hWnd ? (HWND) hWnd : ghTTYWnd);
 
7974
    pd.hDevMode = NULL;
 
7975
    pd.hDevNames = NULL;
 
7976
    pd.Flags = PD_ALLPAGES | PD_NOSELECTION | PD_NOPAGENUMS |
 
7977
            PD_HIDEPRINTTOFILE | PD_RETURNDC;
 
7978
    pd.nCopies = 1;
 
7979
    if(PrintDlg (&pd) == 0)
 
7980
        return(_print_map_dlg_error (CommDlgExtendedError()));
 
7981
 
 
7982
    /*
 
7983
     * Returns the device name which we could use to remember what printer
 
7984
     * they selected.  But instead, we just toss them.
 
7985
     */
 
7986
    if (pd.hDevNames)
 
7987
        GlobalFree (pd.hDevNames);
 
7988
    if (pd.hDevMode)
 
7989
        GlobalFree (pd.hDevMode);
 
7990
 
 
7991
    /*
 
7992
     * Get the device drawing context.
 
7993
     * (does PringDlg() ever return success but fail to return a DC?)
 
7994
     */
 
7995
    if (pd.hDC != NULL)
 
7996
        P_PrintDC = pd.hDC;
 
7997
    else {
 
7998
        status = PE_DIALOG_FAILED;
 
7999
        goto Done;
 
8000
    }
 
8001
 
 
8002
    /*
 
8003
     * Start Document
 
8004
     */
 
8005
    memset(&di, 0, sizeof (DOCINFO));
 
8006
    di.cbSize = sizeof (DOCINFO);
 
8007
    di.lpszDocName = docDesc;           /* This appears in the print manager*/
 
8008
    di.lpszOutput = NULL;               /* Could suply a file name to print
 
8009
                                           to. */
 
8010
    if(StartDoc(P_PrintDC, &di) <= 0) {
 
8011
        ExplainSystemErr();
 
8012
        status = PE_CANT_START_DOC;
 
8013
        DeleteDC (P_PrintDC);
 
8014
        P_PrintDC = NULL;
 
8015
        goto Done;
 
8016
    }
 
8017
 
 
8018
    /*
 
8019
     * Printer font is either same as window font, or is it's own
 
8020
     * font.
 
8021
     */
 
8022
    if (gPrintFontSameAs) {
 
8023
 
 
8024
        /*
 
8025
         * Get the current font size in points, then create a new font
 
8026
         * of same size for printer.  Do the calculation using the actual
 
8027
         * screen resolution instead of the logical resolution so that
 
8028
         * we get pretty close to the same font size on the printer
 
8029
         * as we see on the screen.
 
8030
         */
 
8031
        hDC = GetDC (ghTTYWnd);                 /* Temp screen DC. */
 
8032
        ppi = (int) ((float)GetDeviceCaps (hDC, VERTRES) /
 
8033
                    ((float) GetDeviceCaps (hDC, VERTSIZE) / 25.3636));
 
8034
#ifdef FDEBUG
 
8035
        if (mswin_debug >= 8) {
 
8036
            fprintf (mswin_debugfile, "mswin_print_ready:  Screen res %d ppi, font height %d pixels\n",
 
8037
                ppi, -gpTTYInfo->lfTTYFont.lfHeight);
 
8038
            fprintf (mswin_debugfile, "                    Screen height %d pixel, %d mm\n",
 
8039
                    GetDeviceCaps (hDC, VERTRES), GetDeviceCaps (hDC, VERTSIZE));
 
8040
        }
 
8041
#endif
 
8042
        ReleaseDC (ghTTYWnd, hDC);
 
8043
 
 
8044
        /* Convert from screen pixels to points. */
 
8045
        fontSize = MulDiv (-gpTTYInfo->lfTTYFont.lfHeight, 72, ppi);
 
8046
        ++fontSize;             /* Fudge a little. */
 
8047
 
 
8048
 
 
8049
        /* Get printer resolution and convert form points to printer pixels. */
 
8050
        ppi = GetDeviceCaps (P_PrintDC, LOGPIXELSY);
 
8051
        newFont.lfHeight =  -MulDiv (fontSize, ppi, 72);
 
8052
        _tcsncpy(newFont.lfFaceName, gpTTYInfo->lfTTYFont.lfFaceName, LF_FACESIZE);
 
8053
        newFont.lfFaceName[LF_FACESIZE-1] = 0;
 
8054
        newFont.lfItalic = gpTTYInfo->lfTTYFont.lfItalic;
 
8055
        newFont.lfWeight = gpTTYInfo->lfTTYFont.lfWeight;
 
8056
        newFont.lfCharSet = gpTTYInfo->lfTTYFont.lfCharSet;
 
8057
        
 
8058
 
 
8059
#ifdef FDEBUG
 
8060
        if (mswin_debug >= 8) {
 
8061
            fprintf (mswin_debugfile, "                    font Size %d points\n",
 
8062
                    fontSize);
 
8063
            fprintf (mswin_debugfile, "                    printer res %d ppi, font height %d pixels\n",
 
8064
                ppi, -newFont.lfHeight);
 
8065
            fprintf (mswin_debugfile, "                    paper height %d pixel, %d mm\n",
 
8066
                    GetDeviceCaps (P_PrintDC, VERTRES),
 
8067
                    GetDeviceCaps (P_PrintDC, VERTSIZE));
 
8068
        }
 
8069
#endif
 
8070
    }
 
8071
    else {
 
8072
        ppi = GetDeviceCaps (P_PrintDC, LOGPIXELSY);
 
8073
        newFont.lfHeight =  -MulDiv (gPrintFontSize, ppi, 72);
 
8074
        _tcsncpy(newFont.lfFaceName, gPrintFontName, LF_FACESIZE);
 
8075
        newFont.lfFaceName[LF_FACESIZE-1] = 0;
 
8076
        newFont.lfWeight = 0;
 
8077
        if(_tcsstr(gPrintFontStyle, TEXT("bold")))
 
8078
            newFont.lfWeight = FW_BOLD;
 
8079
 
 
8080
        newFont.lfItalic = 0;
 
8081
        if(_tcsstr(gPrintFontStyle, TEXT("italic")))
 
8082
            newFont.lfItalic = 1;
 
8083
 
 
8084
        newFont.lfCharSet = mswin_string2charsetid(gPrintFontCharSet);
 
8085
    }
 
8086
 
 
8087
        
 
8088
    /* Fill out rest of font description and request font. */
 
8089
    newFont.lfWidth =          0;
 
8090
    newFont.lfEscapement =     0;
 
8091
    newFont.lfOrientation =    0;
 
8092
    newFont.lfUnderline =      0;
 
8093
    newFont.lfStrikeOut =      0;
 
8094
    newFont.lfOutPrecision =   OUT_DEFAULT_PRECIS;
 
8095
    newFont.lfClipPrecision =  CLIP_DEFAULT_PRECIS;
 
8096
    newFont.lfQuality =        DEFAULT_QUALITY;
 
8097
    newFont.lfPitchAndFamily = FIXED_PITCH;
 
8098
    P_hFont = CreateFontIndirect (&newFont);
 
8099
    if (P_hFont == NULL) {
 
8100
        status = PE_FONT_FAILED;
 
8101
        DeleteDC (P_PrintDC);
 
8102
        goto Done;
 
8103
    }
 
8104
 
 
8105
 
 
8106
    /*
 
8107
     * Start page.
 
8108
     * Must select font for each page or it returns to default.
 
8109
     * Windows seems good about maping selected font to a font that
 
8110
     * will actually print on the printer.
 
8111
     */
 
8112
    StartPage (P_PrintDC);
 
8113
    oldFont = SelectObject (P_PrintDC, P_hFont);
 
8114
 
 
8115
 
 
8116
    /*
 
8117
     * Find out about the font we got and set up page size and margins.
 
8118
     * This assumes all pages are the same size - which seems reasonable.
 
8119
     */
 
8120
    GetTextMetrics (P_PrintDC, &tm);
 
8121
    xChar = tm.tmAveCharWidth;                  
 
8122
    P_RowHeight = tm.tmHeight + tm.tmExternalLeading;
 
8123
 
 
8124
    /* HORZRES and VERTRES report size of page in printer pixels. */
 
8125
    P_PageColumns = GetDeviceCaps (P_PrintDC, HORZRES) / xChar;
 
8126
    P_PageRows = GetDeviceCaps (P_PrintDC, VERTRES) / P_RowHeight;
 
8127
 
 
8128
    /* We allow a margin at top and bottom measured in text rows. */
 
8129
    P_PageRows -= VERTICLE_MARGIN * 2;
 
8130
    P_TopOffset = VERTICLE_MARGIN * P_RowHeight;
 
8131
 
 
8132
    /* And allow for a left and right margine measured in characters. */
 
8133
    P_PageColumns -= HORIZONTAL_MARGIN * 2;
 
8134
    P_LeftOffset = HORIZONTAL_MARGIN * xChar;
 
8135
 
 
8136
    P_CurRow = 0;                       /* Start counting at row 0. */
 
8137
    P_CurCol = 0;                       /* At character 0. */
 
8138
    P_LineText = (LPTSTR) MemAlloc((P_PageColumns + 1) * sizeof(TCHAR));
 
8139
    if(P_LineText == NULL){
 
8140
        if(EndDoc (P_PrintDC) <= 0)
 
8141
          ExplainSystemErr();
 
8142
 
 
8143
        DeleteObject (P_hFont);
 
8144
        P_hFont = NULL;
 
8145
        DeleteDC (P_PrintDC);
 
8146
        P_PrintDC = NULL;
 
8147
        status = PE_OUT_OF_MEMORY;
 
8148
        goto Done;
 
8149
    }
 
8150
 
 
8151
 
 
8152
Done:
 
8153
    return (status);
 
8154
}
 
8155
 
 
8156
 
 
8157
/*
 
8158
 * Called when printing is done.
 
8159
 * xxx what happens if there is an error?  Will this get called?
 
8160
 */
 
8161
int
 
8162
mswin_print_done(void)
 
8163
{
 
8164
    if(P_PrintDC != NULL){
 
8165
        if(P_LineText != NULL)
 
8166
          MemFree((void *) P_LineText);
 
8167
 
 
8168
        if(EndPage (P_PrintDC) <= 0 || EndDoc (P_PrintDC) <= 0)
 
8169
          ExplainSystemErr();
 
8170
 
 
8171
        DeleteObject(P_hFont);
 
8172
        P_hFont = NULL;
 
8173
        DeleteDC(P_PrintDC);
 
8174
        P_PrintDC = NULL;
 
8175
    }
 
8176
 
 
8177
    return (0);
 
8178
}
 
8179
 
 
8180
 
 
8181
/*
 
8182
 * Return ponter to a text string that describes the erorr.
 
8183
 */
 
8184
char *
 
8185
mswin_print_error(int error_code)
 
8186
{
 
8187
    int i;
 
8188
 
 
8189
    for(i = 0; P_ErrorMessages[i].error_message != NULL; ++i)
 
8190
      if(P_ErrorMessages[i].error_code == error_code)
 
8191
        return(P_ErrorMessages[i].error_message);
 
8192
 
 
8193
    return("(Unknown error)");
 
8194
}
 
8195
 
 
8196
 
 
8197
/*
 
8198
 * Add a single character to the current line.
 
8199
 * Only handles CRLF carrage control.
 
8200
 */
 
8201
int
 
8202
mswin_print_char(TCHAR c)
 
8203
{
 
8204
    switch(c){
 
8205
      case ASCII_CR:
 
8206
        return(0);
 
8207
 
 
8208
      case ASCII_LF:
 
8209
        return(_print_send_line());
 
8210
        
 
8211
      case ASCII_TAB:
 
8212
        do{
 
8213
            if(P_CurCol == P_PageColumns)
 
8214
              return(_print_send_line());
 
8215
 
 
8216
            *(P_LineText + P_CurCol++) = ' ';
 
8217
        }
 
8218
        while(P_CurCol % PRINT_TAB_SIZE != 0);
 
8219
        return(0);
 
8220
 
 
8221
      default:
 
8222
        if(P_CurCol == P_PageColumns){
 
8223
            int status;
 
8224
 
 
8225
            if((status = _print_send_line()) != 0)
 
8226
              return(status);
 
8227
        }
 
8228
 
 
8229
        *(P_LineText + P_CurCol++) = c;
 
8230
        return(0);
 
8231
    }
 
8232
}
 
8233
 
 
8234
 
 
8235
int
 
8236
mswin_print_char_utf8(int c)
 
8237
{
 
8238
    static unsigned char cbuf[6], *cbufp;
 
8239
    UCS ucs;
 
8240
    TCHAR tc;
 
8241
    int ret = 0;
 
8242
 
 
8243
    if(utf8_to_ucs4_oneatatime(c, cbuf, sizeof(cbuf), &cbufp, &ucs, NULL)){
 
8244
        /* bogus conversion ignores UTF-16 */
 
8245
        tc = (TCHAR) ucs;
 
8246
        ret = mswin_print_char(tc);
 
8247
    }
 
8248
 
 
8249
    return(ret);
 
8250
}
 
8251
 
 
8252
 
 
8253
/*
 
8254
 * Send a string to the printer.
 
8255
 */
 
8256
int
 
8257
mswin_print_text(LPTSTR text)
 
8258
{
 
8259
    int status;
 
8260
 
 
8261
    if(text)
 
8262
      while(*text)
 
8263
        if((status = mswin_print_char(*(text++))) != 0)
 
8264
          return(status);
 
8265
 
 
8266
    return(0);
 
8267
}
 
8268
 
 
8269
 
 
8270
int
 
8271
mswin_print_text_utf8(char *text_utf8)
 
8272
{
 
8273
    LPTSTR text_lpt;
 
8274
    int ret = 0;
 
8275
 
 
8276
    if(text_utf8){
 
8277
        text_lpt = utf8_to_lptstr(text_utf8);
 
8278
        if(text_lpt){
 
8279
            ret = mswin_print_text(text_lpt);
 
8280
            fs_give((void **) &text_lpt);
 
8281
        }
 
8282
    }
 
8283
 
 
8284
    return(ret);
 
8285
}
 
8286
 
 
8287
 
 
8288
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
8289
 *
 
8290
 *        File dialog boxes.
 
8291
 *
 
8292
 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
 
8293
 
 
8294
LOCAL TCHAR gHomeDir[PATH_MAX];
 
8295
LOCAL TCHAR gLastDir[PATH_MAX];
 
8296
 
 
8297
/*
 
8298
 * Keep track of the last dir visited.  Most of the time pine just passes us
 
8299
 * the "home directory", which usually is not where the user wants to start.
 
8300
 * Assume that the first time we are called we are being passed the home
 
8301
 * direcory.
 
8302
 */
 
8303
static void
 
8304
FillInitialDir (LPCTSTR *iDir, LPTSTR targDir)
 
8305
{
 
8306
    if (_tcslen (gHomeDir) == 0) {
 
8307
        _tcscpy (gHomeDir, targDir);
 
8308
        *iDir = targDir;
 
8309
    }
 
8310
    else if (_tcscmp (gHomeDir, targDir) == 0 && *gLastDir)
 
8311
            *iDir = gLastDir;
 
8312
        else
 
8313
            *iDir = targDir;
 
8314
}
 
8315
 
 
8316
 
 
8317
 
 
8318
/*
 
8319
 * Display a save file dialog box.
 
8320
 *
 
8321
 *      dir_utf8        >       directory to start search in
 
8322
 *                      <       directory finished in.
 
8323
 *      fName_utf8      <       Name of file selected
 
8324
 *      nMaxDName               length of dir_utf8
 
8325
 *      nMaxFName               length of fName_utf8.
 
8326
 *
 
8327
 *      Possible return values:
 
8328
 *      0   no file selected
 
8329
 *      1   file selected
 
8330
 *     -1   some sort of error
 
8331
 */
 
8332
int
 
8333
mswin_savefile(char *dir_utf8, int nMaxDName, char *fName_utf8, int nMaxFName)
 
8334
{
 
8335
    OPENFILENAME        ofn;
 
8336
    TCHAR               filters[128], moniker[128];
 
8337
    DWORD               rc, len;
 
8338
    LPTSTR              p, extlist_lpt;
 
8339
    LPTSTR              fName_lpt, f, dir_lpt;
 
8340
    char               *cp;
 
8341
 
 
8342
    /* convert fName_utf8 to LPTSTR */
 
8343
    fName_lpt = (LPTSTR) fs_get(nMaxFName * sizeof(TCHAR));
 
8344
    fName_lpt[0] = '\0';
 
8345
    if(fName_utf8 && fName_utf8[0]){
 
8346
        f = utf8_to_lptstr(fName_utf8);
 
8347
        if(f){
 
8348
            _tcsncpy(fName_lpt, f, nMaxFName);
 
8349
            fName_lpt[nMaxFName-1] = '\0';
 
8350
            fs_give((void **) &f);
 
8351
        }
 
8352
    }
 
8353
 
 
8354
    dir_lpt = (LPTSTR) fs_get(nMaxDName * sizeof(TCHAR));
 
8355
    dir_lpt[0] = '\0';
 
8356
    if(dir_utf8 && dir_utf8[0]){
 
8357
        f = utf8_to_lptstr(dir_utf8);
 
8358
        if(f){
 
8359
            _tcsncpy(dir_lpt, f, nMaxDName);
 
8360
            dir_lpt[nMaxDName-1] = '\0';
 
8361
            fs_give((void **) &f);
 
8362
        }
 
8363
    }
 
8364
 
 
8365
    for(extlist_lpt = NULL, p = _tcschr(fName_lpt, '.'); p; p = _tcschr(++p, '.'))
 
8366
      extlist_lpt = p;
 
8367
 
 
8368
    len = sizeof(moniker)/sizeof(TCHAR);
 
8369
    if(extlist_lpt && MSWRPeek(HKEY_CLASSES_ROOT, extlist_lpt, NULL, moniker, &len) == TRUE){
 
8370
        len = sizeof(filters)/sizeof(TCHAR);
 
8371
        filters[0] = '\0';
 
8372
        if(MSWRPeek(HKEY_CLASSES_ROOT, moniker, NULL, filters, &len) == TRUE)
 
8373
          _sntprintf(filters + _tcslen(filters),
 
8374
                     sizeof(filters)/sizeof(TCHAR) - _tcslen(filters),
 
8375
                     TEXT(" (*%s)#*%s#"), extlist_lpt, extlist_lpt);
 
8376
        else
 
8377
          _sntprintf(filters, sizeof(filters)/sizeof(TCHAR),
 
8378
                     TEXT("%s (*%s)#*%s#"), moniker, extlist_lpt, extlist_lpt);
 
8379
    }
 
8380
    else
 
8381
      filters[0] = '\0';
 
8382
 
 
8383
    _tcsncat(filters, TEXT("Text Files (*.txt)#*.txt#All Files (*.*)#*.*#"),
 
8384
             sizeof(filters)/sizeof(TCHAR));
 
8385
    filters[sizeof(filters)/sizeof(TCHAR) - 1] = '\0';
 
8386
 
 
8387
    for(p = filters; *p != '\0'; ++p)
 
8388
      if(*p == L'#')
 
8389
        *p = '\0';
 
8390
 
 
8391
    /* Set up the BIG STRUCTURE. */
 
8392
    memset (&ofn, 0, sizeof(ofn));
 
8393
    /*
 
8394
     * sizeof(OPENFILENAME) used to work but doesn't work now with
 
8395
     * pre-Windows 2000. This is supposed to be the magic constant to
 
8396
     * make it work in both cases, according to MSDN.
 
8397
     */
 
8398
    ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
 
8399
    ofn.hwndOwner = ghTTYWnd;
 
8400
    ofn.lpstrFilter = filters;
 
8401
    ofn.lpstrCustomFilter = NULL;
 
8402
    ofn.nFilterIndex = 1;
 
8403
    ofn.lpstrFile = fName_lpt;
 
8404
    ofn.nMaxFile = nMaxFName;
 
8405
    ofn.lpstrFileTitle = NULL;
 
8406
    ofn.nMaxFileTitle = 0;
 
8407
    FillInitialDir (&ofn.lpstrInitialDir, dir_lpt);
 
8408
    ofn.lpstrTitle = TEXT("Save To File");
 
8409
    ofn.Flags = OFN_NOREADONLYRETURN | OFN_OVERWRITEPROMPT | OFN_PATHMUSTEXIST;
 
8410
    ofn.lpstrDefExt = TEXT("txt");
 
8411
 
 
8412
    if(GetSaveFileName(&ofn)){
 
8413
        if(ofn.nFileOffset > nMaxDName-1){
 
8414
            if(fName_lpt)
 
8415
              fs_give((void **) &fName_lpt);
 
8416
 
 
8417
            if(dir_lpt)
 
8418
              fs_give((void **) &dir_lpt);
 
8419
 
 
8420
            return(0);
 
8421
        }
 
8422
 
 
8423
        /* Copy directory name to dir_lpt. */
 
8424
        _tcsncpy(dir_lpt, fName_lpt, nMaxDName-1);
 
8425
        dir_lpt[nMaxDName-1] = '\0';
 
8426
        if(dir_lpt[ofn.nFileOffset-1] == '\\'
 
8427
           && !(ofn.nFileOffset == 3 && _istalpha(dir_lpt[0]) && dir_lpt[1] == ':'))
 
8428
          dir_lpt[ofn.nFileOffset-1] = '\0';
 
8429
        else
 
8430
          dir_lpt[ofn.nFileOffset] = '\0';
 
8431
 
 
8432
        /* Remember last dir visited. */
 
8433
        _tcsncpy(gLastDir, dir_lpt, PATH_MAX);
 
8434
        gLastDir[PATH_MAX-1] = '\0';
 
8435
 
 
8436
        /* convert back to UTF-8 */
 
8437
        cp = lptstr_to_utf8(dir_lpt);
 
8438
        if(cp){
 
8439
            strncpy(dir_utf8, cp, nMaxDName-1);
 
8440
            dir_utf8[nMaxDName-1] = '\0';
 
8441
            fs_give((void **) &cp);
 
8442
        }
 
8443
 
 
8444
        p = fName_lpt + ofn.nFileOffset;
 
8445
 
 
8446
        /* convert fName back to UTF-8 */
 
8447
        cp = lptstr_to_utf8(p);
 
8448
        if(cp){
 
8449
            strncpy(fName_utf8, cp, nMaxFName-1);
 
8450
            fName_utf8[nMaxFName-1] = '\0';
 
8451
            fs_give((void **) &cp);
 
8452
        }
 
8453
 
 
8454
        if(fName_lpt)
 
8455
          fs_give((void **) &fName_lpt);
 
8456
 
 
8457
        if(dir_lpt)
 
8458
          fs_give((void **) &dir_lpt);
 
8459
 
 
8460
        return(1);
 
8461
    }
 
8462
    else{
 
8463
        if(fName_lpt)
 
8464
          fs_give((void **) &fName_lpt);
 
8465
 
 
8466
        if(dir_lpt)
 
8467
          fs_give((void **) &dir_lpt);
 
8468
 
 
8469
        rc = CommDlgExtendedError();
 
8470
        return(rc ? -1 : 0);
 
8471
    }
 
8472
}
 
8473
 
 
8474
 
 
8475
 
 
8476
 
 
8477
/*
 
8478
 * Display an open file dialog box.
 
8479
 *
 
8480
 *      dir_utf8        >       directory to start search in
 
8481
 *                      <       directory finished in.
 
8482
 *      fName_utf8      <       Name of file selected
 
8483
 *      nMaxDName               length of dir_utf8
 
8484
 *      nMaxFName               length of fName_utf8.
 
8485
 *
 
8486
 *      Possible return values:
 
8487
 *      0   no file selected
 
8488
 *      1   file selected
 
8489
 *     -1   some sort of error
 
8490
 */
 
8491
int
 
8492
mswin_openfile(char *dir_utf8, int nMaxDName, char *fName_utf8,
 
8493
               int nMaxFName, char *extlist_utf8)
 
8494
{
 
8495
    OPENFILENAME        ofn;
 
8496
    TCHAR               filters[1024];
 
8497
    DWORD               rc;
 
8498
    LPTSTR              p;
 
8499
    LPTSTR              extlist_lpt = NULL;
 
8500
    LPTSTR              fName_lpt, f, dir_lpt;
 
8501
    char               *cp;
 
8502
 
 
8503
 
 
8504
    if(extlist_utf8)
 
8505
      extlist_lpt = utf8_to_lptstr(extlist_utf8);
 
8506
 
 
8507
    /*
 
8508
     * Set filters array.  (pairs of null terminated strings, terminated
 
8509
     * by a double null).
 
8510
     */
 
8511
    _sntprintf(filters, sizeof(filters)/sizeof(TCHAR),
 
8512
               TEXT("%s%sAll Files (*.*)#*.*#"),
 
8513
               extlist_lpt ? extlist_lpt : TEXT(""), extlist_lpt ? TEXT("#") : TEXT(""));
 
8514
 
 
8515
    if(extlist_lpt)
 
8516
      fs_give((void **) &extlist_lpt);
 
8517
 
 
8518
    for(p = filters; *p != '\0'; ++p)
 
8519
      if(*p == L'#')
 
8520
        *p = '\0';
 
8521
 
 
8522
    /* Set up the BIG STRUCTURE. */
 
8523
    memset(&ofn, 0, sizeof(ofn));
 
8524
 
 
8525
    /* convert fName_utf8 to LPTSTR */
 
8526
    fName_lpt = (LPTSTR) fs_get(nMaxFName * sizeof(TCHAR));
 
8527
    fName_lpt[0] = '\0';
 
8528
    if(fName_utf8 && fName_utf8[0]){
 
8529
        f = utf8_to_lptstr(fName_utf8);
 
8530
        if(f){
 
8531
            _tcsncpy(fName_lpt, f, nMaxFName);
 
8532
            fName_lpt[nMaxFName-1] = '\0';
 
8533
            fs_give((void **) &f);
 
8534
        }
 
8535
    }
 
8536
 
 
8537
    dir_lpt = (LPTSTR) fs_get(nMaxDName * sizeof(TCHAR));
 
8538
    dir_lpt[0] = '\0';
 
8539
    if(dir_utf8 && dir_utf8[0]){
 
8540
        f = utf8_to_lptstr(dir_utf8);
 
8541
        if(f){
 
8542
            _tcsncpy(dir_lpt, f, nMaxDName);
 
8543
            dir_lpt[nMaxDName-1] = '\0';
 
8544
            fs_give((void **) &f);
 
8545
        }
 
8546
    }
 
8547
 
 
8548
    /*
 
8549
     * sizeof(OPENFILENAME) used to work but doesn't work now with
 
8550
     * pre-Windows 2000. This is supposed to be the magic constant to
 
8551
     * make it work in both cases, according to MSDN.
 
8552
     */
 
8553
    ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
 
8554
    ofn.hwndOwner = ghTTYWnd;
 
8555
    ofn.lpstrFilter = filters;
 
8556
    ofn.lpstrCustomFilter = NULL;
 
8557
    ofn.nFilterIndex = 1;
 
8558
    ofn.lpstrFile = fName_lpt;
 
8559
    ofn.nMaxFile = nMaxFName;
 
8560
    ofn.lpstrFileTitle = NULL;
 
8561
    ofn.nMaxFileTitle = 0;
 
8562
    FillInitialDir(&ofn.lpstrInitialDir, dir_lpt);
 
8563
    ofn.lpstrTitle = TEXT("Select File");
 
8564
    ofn.Flags = OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
 
8565
    ofn.lpstrDefExt = TEXT("txt");
 
8566
 
 
8567
    if(GetOpenFileName(&ofn)){
 
8568
        if(ofn.nFileOffset > nMaxDName-1){
 
8569
            if(fName_lpt)
 
8570
              fs_give((void **) &fName_lpt);
 
8571
 
 
8572
            if(dir_lpt)
 
8573
              fs_give((void **) &dir_lpt);
 
8574
 
 
8575
            return(0);
 
8576
        }
 
8577
 
 
8578
        /* Copy directory name to dir_lpt. */
 
8579
        _tcsncpy(dir_lpt, fName_lpt, nMaxDName-1);
 
8580
        dir_lpt[nMaxDName-1] = '\0';
 
8581
        if(dir_lpt[ofn.nFileOffset-1] == '\\'
 
8582
           && !(ofn.nFileOffset == 3 && _istalpha(dir_lpt[0]) && dir_lpt[1] == ':'))
 
8583
          dir_lpt[ofn.nFileOffset-1] = '\0';
 
8584
        else
 
8585
          dir_lpt[ofn.nFileOffset] = '\0';
 
8586
 
 
8587
        /* Remember last dir visited. */
 
8588
        _tcsncpy(gLastDir, dir_lpt, PATH_MAX);
 
8589
        gLastDir[PATH_MAX-1] = '\0';
 
8590
 
 
8591
        /* convert back to UTF-8 */
 
8592
        cp = lptstr_to_utf8(dir_lpt);
 
8593
        if(cp){
 
8594
            strncpy(dir_utf8, cp, nMaxDName-1);
 
8595
            dir_utf8[nMaxDName-1] = '\0';
 
8596
            fs_give((void **) &cp);
 
8597
        }
 
8598
        
 
8599
        p = fName_lpt + ofn.nFileOffset;
 
8600
 
 
8601
        /* convert fName back to UTF-8 */
 
8602
        cp = lptstr_to_utf8(p);
 
8603
        if(cp){
 
8604
            strncpy(fName_utf8, cp, nMaxFName-1);
 
8605
            fName_utf8[nMaxFName-1] = '\0';
 
8606
            fs_give((void **) &cp);
 
8607
        }
 
8608
 
 
8609
        if(fName_lpt)
 
8610
          fs_give((void **) &fName_lpt);
 
8611
 
 
8612
        if(dir_lpt)
 
8613
          fs_give((void **) &dir_lpt);
 
8614
 
 
8615
        return(1);
 
8616
    }
 
8617
    else{
 
8618
        if(fName_lpt)
 
8619
          fs_give((void **) &fName_lpt);
 
8620
 
 
8621
        if(dir_lpt)
 
8622
          fs_give((void **) &dir_lpt);
 
8623
 
 
8624
        rc = CommDlgExtendedError();
 
8625
        return(rc ? -1 : 0);
 
8626
    }
 
8627
}
 
8628
 
 
8629
 
 
8630
/*
 
8631
 * Display an open file dialog box.
 
8632
 * Allow selection of multiple files.
 
8633
 *
 
8634
 *      dir_utf8        >       directory to start search in
 
8635
 *                      <       directory finished in.
 
8636
 *      fName_utf8      <       Names of files selected
 
8637
 *      nMaxDName               length of dir_utf8
 
8638
 *      nMaxFName               length of fName_utf8.
 
8639
 *
 
8640
 *      Possible return values:
 
8641
 *      0   no file selected
 
8642
 *      1   file selected
 
8643
 *     -1   some sort of error
 
8644
 */
 
8645
int
 
8646
mswin_multopenfile(char *dir_utf8, int nMaxDName, char *fName_utf8,
 
8647
                   int nMaxFName, char *extlist_utf8)
 
8648
{
 
8649
    OPENFILENAME        ofn;
 
8650
    TCHAR               filters[1024];
 
8651
    DWORD               rc;
 
8652
    LPTSTR              p;
 
8653
    LPTSTR              extlist_lpt = NULL;
 
8654
    LPTSTR              fName_lpt, f, dir_lpt;
 
8655
    char               *cp, *q;
 
8656
 
 
8657
 
 
8658
    if(extlist_utf8)
 
8659
      extlist_lpt = utf8_to_lptstr(extlist_utf8);
 
8660
 
 
8661
    /*
 
8662
     * Set filters array.  (pairs of null terminated strings, terminated
 
8663
     * by a double null).
 
8664
     */
 
8665
    _sntprintf(filters, sizeof(filters)/sizeof(TCHAR),
 
8666
               TEXT("%s%sAll Files (*.*)#*.*#"),
 
8667
               extlist_lpt ? extlist_lpt : TEXT(""), extlist_lpt ? TEXT("#") : TEXT(""));
 
8668
 
 
8669
    if(extlist_lpt)
 
8670
      fs_give((void **) &extlist_lpt);
 
8671
 
 
8672
    for(p = filters; *p != '\0'; ++p)
 
8673
      if(*p == L'#')
 
8674
        *p = '\0';
 
8675
 
 
8676
    /* Set up the BIG STRUCTURE. */
 
8677
    memset (&ofn, 0, sizeof(ofn));
 
8678
 
 
8679
    /* convert fName_utf8 to LPTSTR */
 
8680
    fName_lpt = (LPTSTR) fs_get(nMaxFName * sizeof(TCHAR));
 
8681
    memset(fName_lpt, 0, nMaxFName * sizeof(TCHAR));
 
8682
    if(fName_utf8 && fName_utf8[0]){
 
8683
        f = utf8_to_lptstr(fName_utf8);
 
8684
        if(f){
 
8685
            _tcsncpy(fName_lpt, f, nMaxFName);
 
8686
            fName_lpt[nMaxFName-1] = '\0';
 
8687
            fs_give((void **) &f);
 
8688
        }
 
8689
    }
 
8690
 
 
8691
    dir_lpt = (LPTSTR) fs_get(nMaxDName * sizeof(TCHAR));
 
8692
    memset(dir_lpt, 0, nMaxDName * sizeof(TCHAR));
 
8693
    if(dir_utf8 && dir_utf8[0]){
 
8694
        f = utf8_to_lptstr(dir_utf8);
 
8695
        if(f){
 
8696
            _tcsncpy(dir_lpt, f, nMaxDName);
 
8697
            dir_lpt[nMaxDName-1] = '\0';
 
8698
            fs_give((void **) &f);
 
8699
        }
 
8700
    }
 
8701
 
 
8702
    /*
 
8703
     * sizeof(OPENFILENAME) used to work but doesn't work now with
 
8704
     * pre-Windows 2000. This is supposed to be the magic constant to
 
8705
     * make it work in both cases, according to MSDN.
 
8706
     */
 
8707
    ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
 
8708
    ofn.hwndOwner = ghTTYWnd;
 
8709
    ofn.lpstrFilter = filters;
 
8710
    ofn.lpstrCustomFilter = NULL;
 
8711
    ofn.nFilterIndex = 1;
 
8712
    ofn.lpstrFile = fName_lpt;
 
8713
    ofn.nMaxFile = nMaxFName;
 
8714
    ofn.lpstrFileTitle = NULL;
 
8715
    ofn.nMaxFileTitle = 0;
 
8716
    FillInitialDir(&ofn.lpstrInitialDir, dir_lpt);
 
8717
    ofn.lpstrTitle = TEXT("Select Files");
 
8718
    ofn.Flags = OFN_ALLOWMULTISELECT | OFN_EXPLORER |
 
8719
                OFN_HIDEREADONLY | OFN_FILEMUSTEXIST | OFN_PATHMUSTEXIST;
 
8720
    ofn.lpstrDefExt = TEXT("txt");
 
8721
 
 
8722
    if(GetOpenFileName(&ofn)){
 
8723
        if(ofn.nFileOffset > nMaxDName-1){
 
8724
            if(fName_lpt)
 
8725
              fs_give((void **) &fName_lpt);
 
8726
 
 
8727
            if(dir_lpt)
 
8728
              fs_give((void **) &dir_lpt);
 
8729
 
 
8730
            return(0);
 
8731
        }
 
8732
 
 
8733
        /* Copy directory name to dir_lpt. */
 
8734
        _tcsncpy(dir_lpt, fName_lpt, nMaxDName-1);
 
8735
        dir_lpt[nMaxDName-1] = '\0';
 
8736
        if(dir_lpt[ofn.nFileOffset-1] == '\\'
 
8737
           && !(ofn.nFileOffset == 3 && _istalpha(dir_lpt[0]) && dir_lpt[1] == ':'))
 
8738
          dir_lpt[ofn.nFileOffset-1] = '\0';
 
8739
        else
 
8740
          dir_lpt[ofn.nFileOffset] = '\0';
 
8741
 
 
8742
        /* Remember last dir visited. */
 
8743
        _tcsncpy(gLastDir, dir_lpt, PATH_MAX);
 
8744
        gLastDir[PATH_MAX-1] = '\0';
 
8745
 
 
8746
        /* convert back to UTF-8 */
 
8747
        cp = lptstr_to_utf8(dir_lpt);
 
8748
        if(cp){
 
8749
            strncpy(dir_utf8, cp, nMaxDName-1);
 
8750
            dir_utf8[nMaxDName-1] = '\0';
 
8751
            fs_give((void **) &cp);
 
8752
        }
 
8753
        
 
8754
        /*
 
8755
         * The file names are all in the same directory and are separated
 
8756
         * by '\0' characters and terminated by double '\0'.
 
8757
         * This fact depends on the OFN_EXPLORER bit being set in the flags
 
8758
         * above.
 
8759
         *
 
8760
         * This is complicated because we need to convert all of these file
 
8761
         * names to UTF-8.
 
8762
         */
 
8763
        for(q=fName_utf8, p=fName_lpt + ofn.nFileOffset; *p; p += _tcslen(p)+1){
 
8764
            cp = lptstr_to_utf8(p);
 
8765
            if(cp){
 
8766
                sstrncpy(&q, cp, (int)(nMaxFName-(q-fName_utf8)));
 
8767
                if(q-fName_utf8 < nMaxFName){
 
8768
                    *q++ = '\0';
 
8769
                    if(q-fName_utf8 < nMaxFName)
 
8770
                      *q = '\0';                /* the double null if this is the end */
 
8771
                }
 
8772
                else
 
8773
                  fName_utf8[nMaxFName-1] = '\0';
 
8774
 
 
8775
                fs_give((void **) &cp);
 
8776
            }
 
8777
        }
 
8778
 
 
8779
        fName_utf8[nMaxFName-1] = fName_utf8[nMaxFName-2] = '\0';
 
8780
 
 
8781
        if(fName_lpt)
 
8782
          fs_give((void **) &fName_lpt);
 
8783
 
 
8784
        if(dir_lpt)
 
8785
          fs_give((void **) &dir_lpt);
 
8786
 
 
8787
        return (1);
 
8788
    }
 
8789
    else{
 
8790
        if(fName_lpt)
 
8791
          fs_give((void **) &fName_lpt);
 
8792
 
 
8793
        if(dir_lpt)
 
8794
          fs_give((void **) &dir_lpt);
 
8795
 
 
8796
        rc = CommDlgExtendedError();
 
8797
        return(rc ? -1 : 0);
 
8798
    }
 
8799
}
 
8800
        
 
8801
        
 
8802
/*---------------------------------------------------------------------------
 
8803
 */
 
8804
 
 
8805
/*
 
8806
 * pico_XXcolor() - each function sets a particular attribute
 
8807
 */
 
8808
void
 
8809
pico_nfcolor(char *s)
 
8810
{
 
8811
    char cbuf[MAXCLEN];
 
8812
 
 
8813
    if(s){
 
8814
        SetColorAttribute (&gpTTYInfo->rgbFGColor, s);
 
8815
        pico_set_nfg_color();
 
8816
 
 
8817
        if(the_normal_color){
 
8818
          strncpy(the_normal_color->fg,
 
8819
                  ConvertStringRGB(cbuf, sizeof(cbuf), gpTTYInfo->rgbFGColor),
 
8820
                  MAXCOLORLEN+1);
 
8821
          the_normal_color->fg[MAXCOLORLEN] = '\0';
 
8822
        }
 
8823
    }
 
8824
    else{
 
8825
        gpTTYInfo->rgbFGColor = GetSysColor (COLOR_WINDOWTEXT);
 
8826
        if(the_normal_color)
 
8827
          free_color_pair(&the_normal_color);
 
8828
    }
 
8829
 
 
8830
    // Update all textwindows with the new FG color.
 
8831
    mswin_tw_setcolor((MSWIN_TEXTWINDOW *)-1,
 
8832
        gpTTYInfo->rgbFGColor, gpTTYInfo->rgbBGColor);
 
8833
}
 
8834
 
 
8835
 
 
8836
void
 
8837
pico_nbcolor(char *s)
 
8838
{
 
8839
    char cbuf[MAXCLEN];
 
8840
 
 
8841
    if(s){
 
8842
        SetColorAttribute (&gpTTYInfo->rgbBGColor, s);
 
8843
        pico_set_nbg_color();
 
8844
 
 
8845
        if(the_normal_color){
 
8846
          strncpy(the_normal_color->bg,
 
8847
                  ConvertStringRGB(cbuf, sizeof(cbuf), gpTTYInfo->rgbBGColor),
 
8848
                  MAXCOLORLEN+1);
 
8849
          the_normal_color->fg[MAXCOLORLEN] = '\0';
 
8850
        }
 
8851
    }
 
8852
    else{
 
8853
        gpTTYInfo->rgbBGColor = GetSysColor (COLOR_WINDOW);
 
8854
        if(the_normal_color)
 
8855
          free_color_pair(&the_normal_color);
 
8856
    }
 
8857
 
 
8858
    // Update all textwindows with the new BG color.
 
8859
    mswin_tw_setcolor((MSWIN_TEXTWINDOW *)-1,
 
8860
        gpTTYInfo->rgbFGColor, gpTTYInfo->rgbBGColor);
 
8861
}
 
8862
 
 
8863
 
 
8864
void
 
8865
pico_rfcolor(char *s)
 
8866
{
 
8867
    char cbuf[MAXCLEN];
 
8868
 
 
8869
    if(s){
 
8870
        SetColorAttribute (&gpTTYInfo->rgbRFGColor, s);
 
8871
 
 
8872
        if(the_rev_color){
 
8873
          strncpy(the_rev_color->fg,
 
8874
                  ConvertStringRGB(cbuf, sizeof(cbuf), gpTTYInfo->rgbRFGColor),
 
8875
                  MAXCOLORLEN+1);
 
8876
          the_rev_color->fg[MAXCOLORLEN] = '\0';
 
8877
        }
 
8878
    }
 
8879
    else{
 
8880
        gpTTYInfo->rgbRFGColor = GetSysColor (COLOR_HIGHLIGHTTEXT);
 
8881
        if(the_rev_color)
 
8882
          free_color_pair(&the_rev_color);
 
8883
    }
 
8884
}
 
8885
 
 
8886
 
 
8887
void
 
8888
pico_rbcolor(char *s)
 
8889
{
 
8890
    char cbuf[MAXCLEN];
 
8891
 
 
8892
    if(s){
 
8893
        SetColorAttribute (&gpTTYInfo->rgbRBGColor, s);
 
8894
 
 
8895
        if(the_rev_color){
 
8896
          strncpy(the_rev_color->bg,
 
8897
                  ConvertStringRGB(cbuf, sizeof(cbuf), gpTTYInfo->rgbRBGColor),
 
8898
                  MAXCOLORLEN+1);
 
8899
          the_rev_color->bg[MAXCOLORLEN] = '\0';
 
8900
        }
 
8901
    }
 
8902
    else{
 
8903
        gpTTYInfo->rgbRBGColor = GetSysColor (COLOR_HIGHLIGHT);
 
8904
        if(the_rev_color)
 
8905
          free_color_pair(&the_rev_color);
 
8906
    }
 
8907
}
 
8908
 
 
8909
 
 
8910
int
 
8911
pico_usingcolor()
 
8912
{
 
8913
    return(TRUE);
 
8914
}
 
8915
 
 
8916
 
 
8917
int
 
8918
pico_count_in_color_table()
 
8919
{
 
8920
    return(visibleColorTableSize);
 
8921
}
 
8922
 
 
8923
 
 
8924
/*
 
8925
 * Return a pointer to an rgb string for the input color. The output is 11
 
8926
 * characters long and looks like rrr,ggg,bbb.
 
8927
 *
 
8928
 * Args    colorName -- The color to convert to ascii rgb.
 
8929
 *
 
8930
 * Returns  Pointer to a static buffer containing the rgb string.
 
8931
 */
 
8932
char *
 
8933
color_to_asciirgb(char *colorName)
 
8934
{
 
8935
    static char  c_to_a_buf[RGBLEN+1];
 
8936
    COLORREF     cf;
 
8937
    int          l;
 
8938
 
 
8939
    if(ConvertRGBString(colorName, &cf)){
 
8940
        snprintf(c_to_a_buf, sizeof(c_to_a_buf), "%.3d,%.3d,%.3d",
 
8941
                GetRValue(cf), GetGValue(cf), GetBValue(cf));
 
8942
    }
 
8943
    else{
 
8944
        /*
 
8945
         * If we didn't find the color we're in a bit of trouble. This
 
8946
         * most likely means that the user is using the same pinerc on
 
8947
         * two terminals, one with more colors than the other. We didn't
 
8948
         * find a match because this color isn't present on this terminal.
 
8949
         * Since the return value of this function is assumed to be
 
8950
         * RGBLEN long, we'd better make it that long.
 
8951
         * It still won't work correctly because colors will be screwed up,
 
8952
         * but at least the embedded colors in filter.c will get properly
 
8953
         * sucked up when they're encountered.
 
8954
         */
 
8955
        strncpy(c_to_a_buf, "xxxxxxxxxxx", RGBLEN);
 
8956
        l = (int)strlen(colorName);
 
8957
        strncpy(c_to_a_buf, colorName, (l < RGBLEN) ? l : RGBLEN);
 
8958
        c_to_a_buf[RGBLEN] = '\0';
 
8959
    }
 
8960
 
 
8961
    return(c_to_a_buf);
 
8962
}
 
8963
 
 
8964
 
 
8965
void
 
8966
pico_set_nfg_color()
 
8967
{
 
8968
    FlushWriteAccum ();
 
8969
    gpTTYInfo->curAttrib.rgbFG = gpTTYInfo->rgbFGColor;
 
8970
}
 
8971
 
 
8972
void
 
8973
pico_set_nbg_color()
 
8974
{
 
8975
    FlushWriteAccum ();
 
8976
    gpTTYInfo->curAttrib.rgbBG = gpTTYInfo->rgbBGColor;
 
8977
}
 
8978
 
 
8979
void
 
8980
pico_set_normal_color()
 
8981
{
 
8982
    pico_set_nfg_color();
 
8983
    pico_set_nbg_color();
 
8984
}
 
8985
 
 
8986
COLOR_PAIR *
 
8987
pico_get_rev_color()
 
8988
{
 
8989
    char fgbuf[MAXCLEN], bgbuf[MAXCLEN];
 
8990
 
 
8991
    if(!the_rev_color)
 
8992
      the_rev_color =
 
8993
           new_color_pair(ConvertStringRGB(fgbuf,sizeof(fgbuf),gpTTYInfo->rgbRFGColor),
 
8994
                          ConvertStringRGB(bgbuf,sizeof(bgbuf),gpTTYInfo->rgbRBGColor));
 
8995
    return(the_rev_color);
 
8996
}
 
8997
 
 
8998
COLOR_PAIR *
 
8999
pico_get_normal_color()
 
9000
{
 
9001
    char fgbuf[MAXCLEN], bgbuf[MAXCLEN];
 
9002
 
 
9003
    if(!the_normal_color)
 
9004
      the_normal_color =
 
9005
           new_color_pair(ConvertStringRGB(fgbuf,sizeof(fgbuf),gpTTYInfo->rgbFGColor),
 
9006
                          ConvertStringRGB(bgbuf,sizeof(bgbuf),gpTTYInfo->rgbBGColor));
 
9007
    return(the_normal_color);
 
9008
}
 
9009
 
 
9010
/*
 
9011
 * Sets color to (fg,bg).
 
9012
 * Flags == PSC_NONE  No alternate default if fg,bg fails.
 
9013
 *       == PSC_NORM  Set it to Normal color on failure.
 
9014
 *       == PSC_REV   Set it to Reverse color on failure.
 
9015
 *
 
9016
 * If flag PSC_RET is set, returns an allocated copy of the previous
 
9017
 * color pair, otherwise returns NULL.
 
9018
 */
 
9019
COLOR_PAIR *
 
9020
pico_set_colors(char *fg, char *bg, int flags)
 
9021
{
 
9022
    COLOR_PAIR *cp = NULL;
 
9023
 
 
9024
    if(flags & PSC_RET)
 
9025
      cp = pico_get_cur_color();
 
9026
 
 
9027
    if(!(fg && bg && pico_set_fg_color(fg) && pico_set_bg_color(bg))){
 
9028
 
 
9029
        if(flags & PSC_NORM)
 
9030
          pico_set_normal_color();
 
9031
        else if(flags & PSC_REV)
 
9032
          SetReverseColor();
 
9033
    }
 
9034
 
 
9035
    return(cp);
 
9036
}
 
9037
 
 
9038
 
 
9039
int
 
9040
pico_is_good_color(char *colorName)
 
9041
{
 
9042
    COLORREF     cf;
 
9043
 
 
9044
    return(ConvertRGBString(colorName, &cf));
 
9045
}
 
9046
 
 
9047
 
 
9048
int
 
9049
pico_set_fg_color(char *colorName)
 
9050
{
 
9051
    FlushWriteAccum ();
 
9052
    return(ConvertRGBString(colorName, &gpTTYInfo->curAttrib.rgbFG));
 
9053
}
 
9054
 
 
9055
 
 
9056
int
 
9057
pico_set_bg_color(char *colorName)
 
9058
{
 
9059
    FlushWriteAccum ();
 
9060
    return(ConvertRGBString(colorName, &gpTTYInfo->curAttrib.rgbBG));
 
9061
}
 
9062
 
 
9063
 
 
9064
char *
 
9065
pico_get_last_fg_color()
 
9066
{
 
9067
    return(NULL);
 
9068
}
 
9069
 
 
9070
 
 
9071
char *
 
9072
pico_get_last_bg_color()
 
9073
{
 
9074
    return(NULL);
 
9075
}
 
9076
 
 
9077
 
 
9078
unsigned
 
9079
pico_get_color_options()
 
9080
{
 
9081
    return((unsigned)0);
 
9082
}
 
9083
 
 
9084
 
 
9085
void
 
9086
pico_set_color_options(unsigned int opts)
 
9087
{
 
9088
}
 
9089
 
 
9090
 
 
9091
COLOR_PAIR *
 
9092
pico_get_cur_color()
 
9093
{
 
9094
    char fgbuf[MAXCLEN], bgbuf[MAXCLEN];
 
9095
 
 
9096
    return(new_color_pair(ConvertStringRGB(fgbuf,sizeof(fgbuf),gpTTYInfo->curAttrib.rgbFG),
 
9097
                          ConvertStringRGB(bgbuf,sizeof(bgbuf),gpTTYInfo->curAttrib.rgbBG)));
 
9098
}
 
9099
 
 
9100
 
 
9101
char *
 
9102
mswin_rgbchoice(char *pOldRGB)
 
9103
{
 
9104
    CHOOSECOLOR cc;
 
9105
    static COLORREF custColors[16] = {
 
9106
        RGB(0,0,0),
 
9107
        RGB(0,0,255),
 
9108
        RGB(0,255,0),
 
9109
        RGB(0,255,255),
 
9110
        RGB(255,0,0),
 
9111
        RGB(255,0,255),
 
9112
        RGB(255,255,0),
 
9113
        RGB(255,255,255),
 
9114
        RGB(192,192,192),
 
9115
        RGB(128,128,128),
 
9116
        RGB(64,64,64)
 
9117
    };
 
9118
 
 
9119
    memset(&cc, 0, sizeof(CHOOSECOLOR));
 
9120
 
 
9121
    cc.lStructSize  = sizeof(CHOOSECOLOR);
 
9122
    cc.hwndOwner    = ghTTYWnd;
 
9123
    cc.Flags        = CC_ANYCOLOR;
 
9124
    cc.lpCustColors = &custColors[0];
 
9125
 
 
9126
    if(pOldRGB){
 
9127
        int i;
 
9128
 
 
9129
        ConvertRGBString (pOldRGB, &cc.rgbResult);
 
9130
        cc.Flags |= CC_RGBINIT;
 
9131
 
 
9132
        for(i = 0; i < 11 && custColors[i] != cc.rgbResult; i++)
 
9133
          ;
 
9134
 
 
9135
        if(i == 11){
 
9136
            custColors[i] = cc.rgbResult;
 
9137
            cc.Flags |= CC_FULLOPEN;
 
9138
        }
 
9139
        
 
9140
    }
 
9141
 
 
9142
    if(ChooseColor(&cc)){
 
9143
        char rgbbuf[MAXCLEN], *p;
 
9144
 
 
9145
        ConvertStringRGB(rgbbuf, sizeof(rgbbuf), cc.rgbResult);
 
9146
        if(p = MemAlloc(MAXCLEN * sizeof(char))){
 
9147
            strncpy(p, rgbbuf, MAXCLEN);
 
9148
            p[MAXCLEN-1] = '\0';
 
9149
            return(p);
 
9150
        }
 
9151
    }
 
9152
 
 
9153
    return(NULL);
 
9154
}
 
9155
 
 
9156
 
 
9157
 
 
9158
 
 
9159
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
9160
 *
 
9161
 *        Signal and alarm functions
 
9162
 *
 
9163
 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
 
9164
 
 
9165
/*
 
9166
 * Provide a rough implementation of the SIGALRM and alarm functions
 
9167
 */
 
9168
 
 
9169
 
 
9170
 
 
9171
#if 0
 
9172
/*
 
9173
 * Set a new handler for a signal.
 
9174
 */
 
9175
void (__cdecl * __cdecl signal (int sig,void (__cdecl *hndlr)(int)))(int)
 
9176
 
 
9177
{
 
9178
    SignalType  oldValue;
 
9179
 
 
9180
    switch(sig) {
 
9181
      case SIGALRM :
 
9182
        oldValue = gSignalAlarm;
 
9183
        gSignalAlarm = hndlr;
 
9184
        break;
 
9185
 
 
9186
      case SIGHUP :
 
9187
        oldValue = gSignalHUP;
 
9188
        gSignalHUP = hndlr;
 
9189
 
 
9190
      default:
 
9191
        /* All other's are always ignored. */
 
9192
        oldValue = SIG_IGN;
 
9193
        break;
 
9194
    }
 
9195
 
 
9196
    return (oldValue);
 
9197
}
 
9198
#endif
 
9199
 
 
9200
 
 
9201
/*
 
9202
 * Set the alarm expiration time (in seconds)
 
9203
 */
 
9204
int
 
9205
mswin_alarm (int seconds)
 
9206
{
 
9207
    int         prevtime;
 
9208
 
 
9209
    prevtime = gAlarmTimeout ? (gAlarmTimeout - (GetTickCount () / 1000)): 0;
 
9210
    gAlarmTimeout = seconds ? (GetTickCount() / 1000) + seconds : 0;
 
9211
    MyTimerSet ();
 
9212
    return (prevtime);
 
9213
}
 
9214
 
 
9215
 
 
9216
 
 
9217
/*
 
9218
 * Deliver and clear the alarm.
 
9219
 */
 
9220
void
 
9221
AlarmDeliver ()
 
9222
{
 
9223
    if (gSignalAlarm != SIG_DFL && gSignalAlarm != SIG_IGN) {
 
9224
        /* Clear AlarmTimeout BEFORE calling handler.  handler may call back
 
9225
         * to reset timeout. */
 
9226
        gAlarmTimeout = 0;
 
9227
        MyTimerSet ();
 
9228
        gSignalAlarm (SIGALRM);
 
9229
    }
 
9230
}
 
9231
 
 
9232
 
 
9233
 
 
9234
void
 
9235
HUPDeliver ()
 
9236
{
 
9237
    if (gSignalHUP) {
 
9238
        gSignalHUP (SIGHUP);
 
9239
        exit (0);
 
9240
    }
 
9241
}
 
9242
 
 
9243
 
 
9244
 
 
9245
 
 
9246
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
9247
 *
 
9248
 *        Printer font selection menu
 
9249
 *
 
9250
 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
 
9251
 
 
9252
/*
 
9253
 * Set the print font to be the same as the window font.
 
9254
 * Toggle setting.
 
9255
 */
 
9256
void
 
9257
PrintFontSameAs (HWND hWnd)
 
9258
{
 
9259
    HDC                 hDC;
 
9260
    int                 ppi;
 
9261
    PTTYINFO            pTTYInfo;
 
9262
 
 
9263
 
 
9264
    pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
 
9265
    if (pTTYInfo == NULL)
 
9266
        return;
 
9267
 
 
9268
    if (gPrintFontSameAs) {
 
9269
        
 
9270
        /* No longer same as window font.  Use window font as starting point
 
9271
         * for new printer font.  User may later modify printer font. */
 
9272
        hDC = GetDC (hWnd);
 
9273
        ppi = GetDeviceCaps (hDC, LOGPIXELSY);
 
9274
        ReleaseDC (ghTTYWnd, hDC);
 
9275
        ExtractFontInfo(&pTTYInfo->lfTTYFont,
 
9276
                        gPrintFontName, sizeof(gPrintFontName)/sizeof(TCHAR),
 
9277
                        &gPrintFontSize,
 
9278
                        gPrintFontStyle, sizeof(gPrintFontStyle)/sizeof(TCHAR),
 
9279
                        ppi,
 
9280
                        gPrintFontCharSet, sizeof(gPrintFontCharSet)/sizeof(TCHAR));
 
9281
        gPrintFontSameAs = FALSE;
 
9282
    }
 
9283
    else {
 
9284
        
 
9285
        /* Set to be same as the printer font.  Destroy printer font info
 
9286
         * and set "sameAs" flag to TRUE. */
 
9287
        gPrintFontName[0] = '\0';
 
9288
        gPrintFontSameAs = TRUE;
 
9289
    }
 
9290
    DidResize (gpTTYInfo);
 
9291
}
 
9292
 
 
9293
 
 
9294
 
 
9295
 
 
9296
 
 
9297
void
 
9298
PrintFontSelect (HWND hWnd)
 
9299
{
 
9300
    CHOOSEFONT          cfTTYFont;
 
9301
    LOGFONT             newFont;
 
9302
    DWORD               drc;
 
9303
    int                 ppi;
 
9304
    HDC                 hDC;
 
9305
 
 
9306
 
 
9307
 
 
9308
    hDC = GetDC (hWnd);
 
9309
    ppi = GetDeviceCaps (hDC, LOGPIXELSY);
 
9310
    ReleaseDC (ghTTYWnd, hDC);
 
9311
 
 
9312
 
 
9313
    newFont.lfHeight =  -MulDiv (gPrintFontSize, ppi, 72);
 
9314
    _tcsncpy(newFont.lfFaceName, gPrintFontName, LF_FACESIZE);
 
9315
    newFont.lfFaceName[LF_FACESIZE-1] = 0;
 
9316
    newFont.lfWeight = 0;
 
9317
    if(_tcsstr(gPrintFontStyle, TEXT("bold")))
 
9318
        newFont.lfWeight = FW_BOLD;
 
9319
 
 
9320
    newFont.lfItalic = 0;
 
9321
    if(_tcsstr(gPrintFontStyle, TEXT("italic")))
 
9322
        newFont.lfItalic = 1;
 
9323
 
 
9324
    newFont.lfWidth =          0;
 
9325
    newFont.lfEscapement =     0;
 
9326
    newFont.lfOrientation =    0;
 
9327
    newFont.lfUnderline =      0;
 
9328
    newFont.lfStrikeOut =      0;
 
9329
    newFont.lfCharSet =        mswin_string2charsetid(gPrintFontCharSet);
 
9330
    newFont.lfOutPrecision =   OUT_DEFAULT_PRECIS;
 
9331
    newFont.lfClipPrecision =  CLIP_DEFAULT_PRECIS;
 
9332
    newFont.lfQuality =        DEFAULT_QUALITY;
 
9333
    newFont.lfPitchAndFamily = FIXED_PITCH;
 
9334
 
 
9335
 
 
9336
    cfTTYFont.lStructSize    = sizeof (CHOOSEFONT);
 
9337
    cfTTYFont.hwndOwner      = hWnd ;
 
9338
    cfTTYFont.hDC            = NULL ;
 
9339
    cfTTYFont.rgbColors      = 0;
 
9340
    cfTTYFont.lpLogFont      = &newFont;
 
9341
    cfTTYFont.Flags          = CF_BOTH | CF_FIXEDPITCHONLY |
 
9342
            CF_INITTOLOGFONTSTRUCT | CF_ANSIONLY |
 
9343
            CF_FORCEFONTEXIST | CF_LIMITSIZE;
 
9344
    cfTTYFont.nSizeMin       = FONT_MIN_SIZE;
 
9345
    cfTTYFont.nSizeMax       = FONT_MAX_SIZE;
 
9346
    cfTTYFont.lCustData      = 0 ;
 
9347
    cfTTYFont.lpfnHook       = NULL ;
 
9348
    cfTTYFont.lpTemplateName = NULL ;
 
9349
    cfTTYFont.hInstance      = GET_HINST (hWnd);
 
9350
 
 
9351
 
 
9352
    if (ChooseFont (&cfTTYFont)) {
 
9353
        ExtractFontInfo(&newFont,
 
9354
                        gPrintFontName, sizeof(gPrintFontName)/sizeof(TCHAR),
 
9355
                        &gPrintFontSize,
 
9356
                        gPrintFontStyle, sizeof(gPrintFontStyle)/sizeof(TCHAR),
 
9357
                        ppi,
 
9358
                        gPrintFontCharSet, sizeof(gPrintFontCharSet)/sizeof(TCHAR));
 
9359
        DidResize (gpTTYInfo);
 
9360
    }
 
9361
    else
 
9362
        /* So I can see with the debugger. */
 
9363
        drc = CommDlgExtendedError();
 
9364
}
 
9365
 
 
9366
 
 
9367
void
 
9368
ExtractFontInfo(LOGFONT *pFont, LPTSTR fontName, size_t nfontName,
 
9369
                int *fontSize, LPTSTR fontStyle, size_t nfontStyle,
 
9370
                int ppi, LPTSTR fontCharSet, size_t nfontCharSet)
 
9371
{
 
9372
    TCHAR               *sep[] = {TEXT(""), TEXT(", ")};
 
9373
    int                 iSep = 0;
 
9374
 
 
9375
 
 
9376
    _tcsncpy(fontName, pFont->lfFaceName, nfontName);
 
9377
    fontName[nfontName-1] = '\0';
 
9378
 
 
9379
    *fontStyle = '\0';
 
9380
    if(pFont->lfWeight >= FW_BOLD) {
 
9381
        _tcsncpy(fontStyle, TEXT("bold"), nfontStyle);
 
9382
        fontStyle[nfontStyle-1] = '\0';
 
9383
        iSep = 1;
 
9384
    }
 
9385
 
 
9386
    if(pFont->lfItalic){
 
9387
        _tcsncat(fontStyle, sep[iSep], nfontStyle - _tcslen(fontStyle));
 
9388
        fontStyle[nfontStyle-1] = '\0';
 
9389
 
 
9390
        _tcsncat(fontStyle, TEXT("italic"), nfontStyle - _tcslen(fontStyle));
 
9391
        fontStyle[nfontStyle-1] = '\0';
 
9392
    }
 
9393
 
 
9394
    mswin_charsetid2string(fontCharSet, nfontCharSet, pFont->lfCharSet);
 
9395
 
 
9396
    if(fontSize)
 
9397
      *fontSize = MulDiv(-pFont->lfHeight, 72, ppi);
 
9398
}
 
9399
 
 
9400
 
 
9401
LOCAL void
 
9402
DidResize (PTTYINFO pTTYInfo)
 
9403
{
 
9404
    int                 i;
 
9405
 
 
9406
    for (i = 0; i < RESIZE_CALLBACK_ARRAY_SIZE; ++i) {
 
9407
        if (pTTYInfo->resizer[i] != NULL)
 
9408
            pTTYInfo->resizer[i] (pTTYInfo->actNRow, pTTYInfo->actNColumn);
 
9409
    }
 
9410
    /*
 
9411
     * Put a null character into the input queue so that the data input
 
9412
     * loops stop and return to their callers who will then re-calculate the
 
9413
     * mouse regions so that the user can click on the new regions of the
 
9414
     * screen and have the right thing happen.
 
9415
     */
 
9416
    CQAdd (MSWIN_KEY_NODATA, 0);
 
9417
}
 
9418
 
 
9419
 
 
9420
        
 
9421
 
 
9422
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
9423
 *
 
9424
 *        Cut, Copy, and Paste operations
 
9425
 *
 
9426
 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
 
9427
 
 
9428
 
 
9429
/*
 
9430
 * Gets called right before the menu is displayed so we can make
 
9431
 * any last minute adjustments.
 
9432
 */
 
9433
LOCAL void
 
9434
UpdateMenu (HWND hWnd)
 
9435
{
 
9436
    HMENU               hMenu;
 
9437
    PTTYINFO            pTTYInfo;
 
9438
    int                 i;
 
9439
#ifdef  ACCELERATORS
 
9440
    UINT                fAccel = EM_NONE;
 
9441
#endif
 
9442
 
 
9443
    pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
 
9444
    if (pTTYInfo == NULL)
 
9445
        return;
 
9446
 
 
9447
    hMenu = GetMenu (hWnd);
 
9448
    if (hMenu == NULL)
 
9449
        return;
 
9450
 
 
9451
    if (ghPaste) {
 
9452
        /* Currently pasting so disable paste and enable cancel paste. */
 
9453
        EnableMenuItem (hMenu, IDM_EDIT_PASTE, MF_BYCOMMAND|MF_GRAYED);
 
9454
        EnableMenuItem (hMenu, IDM_EDIT_CANCEL_PASTE, MF_BYCOMMAND|MF_ENABLED);
 
9455
#ifdef  ACCELERATORS
 
9456
        fAccel |= (EM_PST | EM_PST_ABORT);
 
9457
#endif
 
9458
    }
 
9459
    else {
 
9460
        /*
 
9461
         * Not pasting.  If text is available on clipboard and we are
 
9462
         * at a place where we can paste, enable past menu option.
 
9463
         */
 
9464
        if (IsClipboardFormatAvailable (CF_UNICODETEXT) && gPasteEnabled){
 
9465
            EnableMenuItem (hMenu, IDM_EDIT_PASTE, MF_BYCOMMAND|MF_ENABLED);
 
9466
#ifdef  ACCELERATORS
 
9467
            fAccel |= EM_PST;
 
9468
#endif
 
9469
        }
 
9470
        else
 
9471
            EnableMenuItem (hMenu, IDM_EDIT_PASTE, MF_BYCOMMAND|MF_GRAYED);
 
9472
 
 
9473
        EnableMenuItem (hMenu, IDM_EDIT_CANCEL_PASTE, MF_BYCOMMAND|MF_GRAYED);
 
9474
    }
 
9475
 
 
9476
    if (SelAvailable ()) {
 
9477
        EnableMenuItem (hMenu, IDM_EDIT_CUT, MF_BYCOMMAND|MF_GRAYED);
 
9478
        EnableMenuItem (hMenu, IDM_EDIT_COPY, MF_BYCOMMAND|MF_ENABLED);
 
9479
        EnableMenuItem (hMenu, IDM_EDIT_COPY_APPEND, MF_BYCOMMAND|MF_ENABLED);
 
9480
#ifdef  ACCELERATORS
 
9481
        fAccel |= (EM_CP | EM_CP_APPEND);
 
9482
#endif
 
9483
    }
 
9484
    else {
 
9485
        if (gAllowCut){
 
9486
            EnableMenuItem (hMenu, IDM_EDIT_CUT, MF_BYCOMMAND | MF_ENABLED);
 
9487
#ifdef  ACCELERATORS
 
9488
            fAccel |= EM_CUT;
 
9489
#endif
 
9490
        }
 
9491
        else
 
9492
            EnableMenuItem (hMenu, IDM_EDIT_CUT, MF_BYCOMMAND | MF_GRAYED);
 
9493
 
 
9494
        if (gAllowCopy) {
 
9495
            EnableMenuItem (hMenu, IDM_EDIT_COPY, MF_BYCOMMAND | MF_ENABLED);
 
9496
            EnableMenuItem (hMenu, IDM_EDIT_COPY_APPEND,
 
9497
                            MF_BYCOMMAND | MF_ENABLED);
 
9498
#ifdef  ACCELERATORS
 
9499
            fAccel |= (EM_CP | EM_CP_APPEND);
 
9500
#endif
 
9501
        }
 
9502
        else {
 
9503
            EnableMenuItem (hMenu, IDM_EDIT_COPY, MF_BYCOMMAND | MF_GRAYED);
 
9504
            EnableMenuItem (hMenu, IDM_EDIT_COPY_APPEND,
 
9505
                                MF_BYCOMMAND | MF_GRAYED);      
 
9506
        }
 
9507
    }
 
9508
 
 
9509
    /*
 
9510
     * Set up Font selection menu
 
9511
     */
 
9512
    if (gPrintFontName[0] == '\0') {
 
9513
        CheckMenuItem (hMenu, IDM_OPT_FONTSAMEAS, MF_BYCOMMAND | MF_CHECKED);
 
9514
        EnableMenuItem (hMenu, IDM_OPT_SETPRINTFONT,
 
9515
                                                MF_BYCOMMAND | MF_GRAYED);
 
9516
    }
 
9517
    else {
 
9518
        CheckMenuItem (hMenu, IDM_OPT_FONTSAMEAS,
 
9519
                                                MF_BYCOMMAND | MF_UNCHECKED);
 
9520
        EnableMenuItem (hMenu, IDM_OPT_SETPRINTFONT,
 
9521
                                                MF_BYCOMMAND | MF_ENABLED);
 
9522
    }
 
9523
 
 
9524
    /*
 
9525
     * Setup Caret selection menu
 
9526
     */
 
9527
    EnableMenuItem (hMenu, IDM_OPT_CARETBLOCK, MF_BYCOMMAND | MF_ENABLED);
 
9528
    EnableMenuItem (hMenu, IDM_OPT_CARETSMALLBLOCK, MF_BYCOMMAND | MF_ENABLED);
 
9529
    EnableMenuItem (hMenu, IDM_OPT_CARETHBAR, MF_BYCOMMAND | MF_ENABLED);
 
9530
    EnableMenuItem (hMenu, IDM_OPT_CARETVBAR, MF_BYCOMMAND | MF_ENABLED);
 
9531
    CheckMenuRadioItem(hMenu, IDM_OPT_CARETBLOCK, IDM_OPT_CARETVBAR,
 
9532
                       IDM_OPT_CARETBLOCK + pTTYInfo->cCaretStyle,
 
9533
                       MF_BYCOMMAND);
 
9534
 
 
9535
    /*
 
9536
     * Check toolbar menu.
 
9537
     */
 
9538
    EnableMenuItem (hMenu, IDM_OPT_TOOLBAR, MF_BYCOMMAND | MF_ENABLED);
 
9539
    CheckMenuItem (hMenu, IDM_OPT_TOOLBAR, MF_BYCOMMAND |
 
9540
            (pTTYInfo->toolBarSize > 0 ? MF_CHECKED : MF_UNCHECKED));
 
9541
    EnableMenuItem (hMenu, IDM_OPT_TOOLBARPOS, MF_BYCOMMAND | MF_ENABLED);
 
9542
    CheckMenuItem (hMenu, IDM_OPT_TOOLBARPOS, MF_BYCOMMAND |
 
9543
            (pTTYInfo->toolBarTop > 0 ? MF_CHECKED : MF_UNCHECKED));
 
9544
 
 
9545
 
 
9546
 
 
9547
    /*
 
9548
     * Check the dialogs menu.
 
9549
     */
 
9550
    /* xxx EnableMenuItem (hMenu, IDM_OPT_USEDIALOGS, MF_BYCOMMAND | MF_ENABLED);*/
 
9551
    CheckMenuItem (hMenu, IDM_OPT_USEDIALOGS, MF_BYCOMMAND |
 
9552
            (gfUseDialogs ? MF_CHECKED : MF_UNCHECKED));
 
9553
 
 
9554
    /*
 
9555
     * Enable the Erase Credentials menu
 
9556
     */
 
9557
    EnableMenuItem (hMenu, IDM_OPT_ERASE_CREDENTIALS,
 
9558
                    MF_BYCOMMAND | (gEraseCredsCallback ? MF_ENABLED : MF_GRAYED));
 
9559
    
 
9560
#ifdef ACCELERATORS_OPT
 
9561
    CheckMenuItem (hMenu, IDM_OPT_USEACCEL, MF_BYCOMMAND |
 
9562
            (pTTYInfo->hAccel ? MF_CHECKED : MF_UNCHECKED));
 
9563
#endif
 
9564
 
 
9565
    /*
 
9566
     * Setup the sort menu...
 
9567
     */
 
9568
    if(gSortCallback){
 
9569
        i = (*gSortCallback)(0, 0);
 
9570
 
 
9571
        /* NOTE: this func's args are dependent on definition order
 
9572
         *       in resource.h
 
9573
         */
 
9574
        CheckMenuRadioItem(hMenu, IDM_MI_SORTSUBJECT, IDM_MI_SORTTHREAD,
 
9575
                           IDM_MI_SORTSUBJECT + (i & 0x00ff), MF_BYCOMMAND);
 
9576
        CheckMenuItem(hMenu, IDM_MI_SORTREVERSE,
 
9577
                      MF_BYCOMMAND|((i & 0x0100) ? MF_CHECKED : MF_UNCHECKED));
 
9578
    }
 
9579
    else{
 
9580
        CheckMenuRadioItem(hMenu, IDM_MI_SORTSUBJECT, IDM_MI_SORTTHREAD,
 
9581
                           IDM_MI_SORTARRIVAL, MF_BYCOMMAND);
 
9582
        CheckMenuItem(hMenu, IDM_MI_SORTREVERSE, MF_BYCOMMAND | MF_UNCHECKED);
 
9583
    }
 
9584
 
 
9585
    /*
 
9586
     * Setup the flag menu...
 
9587
     */
 
9588
    if(gFlagCallback){
 
9589
        int flags = (*gFlagCallback)(0, 0);
 
9590
        for(i = IDM_MI_FLAGIMPORTANT; i <= IDM_MI_FLAGDELETED; i++)
 
9591
          CheckMenuItem(hMenu, i, MF_BYCOMMAND
 
9592
                        | (((flags >> (i - IDM_MI_FLAGIMPORTANT)) & 0x0001)
 
9593
                             ? MF_CHECKED : MF_UNCHECKED));
 
9594
    }
 
9595
 
 
9596
    /*
 
9597
     *
 
9598
     */
 
9599
    if(gHdrCallback){
 
9600
        i = (*gHdrCallback)(0, 0);
 
9601
        CheckMenuItem(hMenu, IDM_MI_HDRMODE,
 
9602
                      MF_BYCOMMAND|((i != 0) ? MF_CHECKED : MF_UNCHECKED));
 
9603
    }
 
9604
 
 
9605
    /*
 
9606
     *
 
9607
     */
 
9608
    if(gZoomCallback){
 
9609
        i = (*gZoomCallback)(0, 0);
 
9610
        CheckMenuItem(hMenu, IDM_MI_ZOOM,
 
9611
                      MF_BYCOMMAND | (i ? MF_CHECKED : MF_UNCHECKED));
 
9612
    }
 
9613
    /*
 
9614
     * Set up command menu.
 
9615
     */
 
9616
    if (!pTTYInfo->menuItemsCurrent) {
 
9617
        for (i = 0; i < KS_COUNT; ++i)
 
9618
          if(i + KS_RANGESTART != KS_GENERALHELP)
 
9619
            EnableMenuItem (hMenu, i + KS_RANGESTART,
 
9620
                            MF_BYCOMMAND | ((pTTYInfo->menuItems[i].miActive)
 
9621
                                              ? MF_ENABLED : MF_GRAYED));
 
9622
 
 
9623
        /*
 
9624
         * Special command-specific knowledge here
 
9625
         */
 
9626
        for(i = IDM_MI_SORTSUBJECT; i <= IDM_MI_SORTREVERSE; i++)
 
9627
          EnableMenuItem (hMenu, i,
 
9628
                      MF_BYCOMMAND
 
9629
                       | ((pTTYInfo->menuItems[KS_SORT-KS_RANGESTART].miActive)
 
9630
                            ? MF_ENABLED : MF_GRAYED));
 
9631
 
 
9632
        for(i = IDM_MI_FLAGIMPORTANT; i <= IDM_MI_FLAGDELETED; i++)
 
9633
          EnableMenuItem (hMenu, i,
 
9634
                  MF_BYCOMMAND
 
9635
                  | ((pTTYInfo->menuItems[KS_FLAG - KS_RANGESTART].miActive)
 
9636
                     ? MF_ENABLED : MF_GRAYED));
 
9637
 
 
9638
    }
 
9639
 
 
9640
    /*
 
9641
     * deal with any callback state dependent enabling
 
9642
     */
 
9643
    if(pTTYInfo->menuItems[IDM_MI_APPLY - KS_RANGESTART].miActive)
 
9644
      EnableMenuItem(hMenu, IDM_MI_APPLY,
 
9645
                     MF_BYCOMMAND | ((gSelectedCallback
 
9646
                                      && (*gSelectedCallback)(0, 0))
 
9647
                                        ? MF_ENABLED : MF_GRAYED));
 
9648
 
 
9649
    if(pTTYInfo->menuItems[IDM_MI_ZOOM - KS_RANGESTART].miActive)
 
9650
      EnableMenuItem(hMenu, IDM_MI_ZOOM,
 
9651
                     MF_BYCOMMAND | ((gSelectedCallback
 
9652
                                      && (*gSelectedCallback)(0, 0))
 
9653
                                        ? MF_ENABLED : MF_GRAYED));
 
9654
 
 
9655
#ifdef  ACCELERATORS
 
9656
    if(pTTYInfo->menuItems[KS_WHEREIS - KS_RANGESTART].miActive)
 
9657
      fAccel |= EM_FIND;
 
9658
 
 
9659
    AccelManage (hWnd, fAccel);
 
9660
#endif
 
9661
 
 
9662
    pTTYInfo->menuItemsCurrent = TRUE;
 
9663
}
 
9664
 
 
9665
 
 
9666
 
 
9667
/*
 
9668
 * Cut region to kill buffer.
 
9669
 */
 
9670
LOCAL void
 
9671
EditCut (void)
 
9672
{
 
9673
    HANDLE              hCB;
 
9674
 
 
9675
    if(gCopyCutFunction == (getc_t)kremove){
 
9676
        hCB = GlobalAlloc (GMEM_MOVEABLE, 0);
 
9677
        if (hCB != NULL) {
 
9678
            kdelete();          /* Clear current kill buffer. */
 
9679
            killregion (1, 0);  /* Kill Region (and copy to clipboard). */
 
9680
            update ();          /* And update the screen */
 
9681
        }
 
9682
    }
 
9683
}
 
9684
 
 
9685
 
 
9686
 
 
9687
/*
 
9688
 * This function copies the kill buffer to the window's clip board.
 
9689
 * (actually, it can copy any buffer for which a copyfunc is provided).
 
9690
 * Called from ldelete().
 
9691
 */
 
9692
void
 
9693
mswin_killbuftoclip (getc_t copyfunc)
 
9694
{
 
9695
    HANDLE              hCB;
 
9696
    getc_t              oldfunc;
 
9697
 
 
9698
    /* Save old copy function. */
 
9699
    oldfunc = gCopyCutFunction;
 
9700
    gCopyCutFunction = copyfunc;
 
9701
 
 
9702
    /* Allocate clip buffer. */
 
9703
    hCB = GlobalAlloc (GMEM_MOVEABLE, 0);
 
9704
    if (hCB != NULL) {
 
9705
        EditDoCopyData (hCB, 0);
 
9706
    }
 
9707
 
 
9708
    /* restore copy function. */
 
9709
    gCopyCutFunction = oldfunc;
 
9710
}
 
9711
        
 
9712
 
 
9713
 
 
9714
/*
 
9715
 * Copy region to kill buffer.
 
9716
 */
 
9717
LOCAL void
 
9718
EditCopy (void)
 
9719
{
 
9720
    HANDLE              hCB;
 
9721
 
 
9722
    if (SelAvailable()) {
 
9723
        /* This is a copy of the windows selection. */
 
9724
        hCB = GlobalAlloc (GMEM_MOVEABLE, 0);
 
9725
        if (hCB != NULL)
 
9726
            SelDoCopy (hCB, 0);
 
9727
    }
 
9728
    else {
 
9729
        
 
9730
        /* Otherwise, it's a Pico/Pine copy. */
 
9731
        if(gCopyCutFunction == (getc_t)kremove){
 
9732
            kdelete();          /* Clear current kill buffer. */
 
9733
            copyregion (1, 0);
 
9734
        }
 
9735
 
 
9736
        hCB = GlobalAlloc (GMEM_MOVEABLE, 0);
 
9737
        if (hCB != NULL)
 
9738
            EditDoCopyData (hCB, 0);
 
9739
    }
 
9740
}
 
9741
 
 
9742
 
 
9743
 
 
9744
/*
 
9745
 * Called in responce to "Copy Append" menu command, when there is an active
 
9746
 * Windows selection on the screen.
 
9747
 */
 
9748
LOCAL void
 
9749
EditCopyAppend (void)
 
9750
{
 
9751
    HANDLE      hCB;
 
9752
    HANDLE      hMyCopy;
 
9753
    TCHAR       *pCB;
 
9754
    TCHAR       *pMyCopy;
 
9755
    size_t      cbSize = 0;
 
9756
 
 
9757
    /* Attempt to copy clipboard data to my own handle. */
 
9758
    hMyCopy = NULL;
 
9759
    if (OpenClipboard (ghTTYWnd)) {             /* And can get clipboard. */
 
9760
        hCB = GetClipboardData (CF_UNICODETEXT);
 
9761
        if (hCB != NULL) {                      /* And can get data. */
 
9762
            pCB = GlobalLock (hCB);
 
9763
            cbSize = _tcslen (pCB);             /* It's a null term string. */
 
9764
            hMyCopy = GlobalAlloc (GMEM_MOVEABLE, (cbSize+1)*sizeof(*pCB));
 
9765
            if (hMyCopy != NULL) {              /* And can get memory. */
 
9766
                pMyCopy = GlobalLock (hMyCopy);
 
9767
                if (pMyCopy != NULL) {
 
9768
                    memcpy (pMyCopy, pCB, cbSize*sizeof(*pCB));  /* Copy data. */
 
9769
                    GlobalUnlock (hMyCopy);
 
9770
                }
 
9771
                else {
 
9772
                    GlobalFree (hMyCopy);
 
9773
                    hMyCopy = NULL;
 
9774
                }
 
9775
            }
 
9776
            GlobalUnlock (hCB);
 
9777
        }                                       /* GetClipboardData. */
 
9778
        CloseClipboard ();
 
9779
    }                                   /* OpenClipboard. */
 
9780
 
 
9781
 
 
9782
 
 
9783
    /* Now, if I got a copy, append current selection to that
 
9784
     * and stuff it back into the clipboard. */
 
9785
    if (hMyCopy != NULL) {
 
9786
        if (SelAvailable ()) {
 
9787
            SelDoCopy (hMyCopy, (DWORD)cbSize);
 
9788
        }
 
9789
        else {
 
9790
            if(gCopyCutFunction == (getc_t)kremove) {
 
9791
                kdelete();              /* Clear current kill buffer. */
 
9792
                copyregion (1, 0);
 
9793
            }
 
9794
            EditDoCopyData (hMyCopy, (DWORD)cbSize);
 
9795
        }
 
9796
    }
 
9797
}
 
9798
 
 
9799
 
 
9800
/*
 
9801
 * Copy data from the kill buffer to the clipboard.  Handle LF->CRLF
 
9802
 * translation if necessary.
 
9803
 */
 
9804
LOCAL void
 
9805
EditDoCopyData (HANDLE hCB, DWORD lenCB)
 
9806
{
 
9807
    TCHAR               *pCB;
 
9808
    TCHAR               *p;
 
9809
    long                c; /* would be TCHAR but needs -1 retval from callback */
 
9810
    TCHAR               lastc = (TCHAR)'\0';
 
9811
    DWORD               cbSize;                 /* Allocated size of hCB. */
 
9812
    DWORD               i;
 
9813
#define BUF_INC 4096
 
9814
 
 
9815
    if (gCopyCutFunction != NULL) {             /* If there really is data. */
 
9816
        if (OpenClipboard (ghTTYWnd)) {         /* ...and we get the CB. */
 
9817
            if (EmptyClipboard ()) {            /* ...and clear previous CB.*/
 
9818
                pCB = GlobalLock (hCB);
 
9819
                p = pCB + lenCB;
 
9820
                cbSize = lenCB;
 
9821
                /* Copy it. (BUG: change int arg) */
 
9822
                for(i = 0L; (c = (*gCopyCutFunction)((int)i)) != -1; i++){
 
9823
                    /*
 
9824
                     * Rather than fix every function that might
 
9825
                     * get called for character retrieval to supply
 
9826
                     * CRLF EOLs, let's just fix it here.  The downside
 
9827
                     * is a much slower copy for large buffers, but
 
9828
                     * hey, what do they want?
 
9829
                     */
 
9830
                    if(lenCB + 2L >= cbSize){
 
9831
                        cbSize += BUF_INC;
 
9832
                        GlobalUnlock (hCB);
 
9833
                        hCB = GlobalReAlloc (hCB, cbSize*sizeof(TCHAR), GMEM_MOVEABLE);
 
9834
                        if (hCB == NULL)
 
9835
                          return;
 
9836
 
 
9837
                        pCB = GlobalLock (hCB);
 
9838
                        p = pCB + lenCB;
 
9839
                    }
 
9840
 
 
9841
                    if(c == (TCHAR)ASCII_LF && lastc != (TCHAR)ASCII_CR) {
 
9842
                        *p++ = (TCHAR)ASCII_CR; /* insert CR before LF */
 
9843
                      lenCB++;
 
9844
                    }
 
9845
 
 
9846
                    *p++ = lastc = (TCHAR)c;
 
9847
                    lenCB++;
 
9848
                }
 
9849
 
 
9850
                /* Only if we got some data. */
 
9851
                if (lenCB > 0) {
 
9852
                    *p = (TCHAR)'\0';
 
9853
                    GlobalUnlock (hCB);
 
9854
 
 
9855
                    if (SetClipboardData (CF_UNICODETEXT, hCB) == NULL)
 
9856
                      /* Failed!  Free the data. */
 
9857
                      GlobalFree (hCB);
 
9858
                }
 
9859
                else {
 
9860
                    /* There was no data copied. */
 
9861
                    GlobalUnlock (hCB);
 
9862
                    GlobalFree (hCB);
 
9863
                }
 
9864
            }
 
9865
            CloseClipboard ();
 
9866
        }
 
9867
    }
 
9868
}
 
9869
 
 
9870
 
 
9871
/*
 
9872
 * Get a handle to the current (text) clipboard and make my own copy.
 
9873
 * Keep my copy locked because I'll be using it to read bytes from.
 
9874
 */
 
9875
LOCAL void
 
9876
EditPaste (void)
 
9877
{
 
9878
    HANDLE      hCB;
 
9879
    LPTSTR      pCB;
 
9880
    LPTSTR      pPaste;
 
9881
    size_t      cbSize;
 
9882
 
 
9883
    if (ghPaste == NULL) {              /* If we are not already pasting. */
 
9884
        if (OpenClipboard (ghTTYWnd)) {         /* And can get clipboard. */
 
9885
            hCB = GetClipboardData (CF_UNICODETEXT);
 
9886
            if (hCB != NULL) {                  /* And can get data. */
 
9887
                pCB = GlobalLock (hCB);
 
9888
                cbSize = _tcslen (pCB);         /* It's a null term string. */
 
9889
                ghPaste = GlobalAlloc (GMEM_MOVEABLE, (cbSize+1)*sizeof(TCHAR));
 
9890
                if (ghPaste != NULL) {          /* And can get memory. */
 
9891
                    gpPasteNext = GlobalLock (ghPaste);
 
9892
                    memcpy (gpPasteNext, pCB, (cbSize+1)*sizeof(TCHAR));  /* Copy data. */
 
9893
                    /* Keep ghPaste locked. */
 
9894
 
 
9895
                    /*
 
9896
                     * If we're paste is enabled but limited to the first
 
9897
                     * line of the clipboard, prune the paste buffer...
 
9898
                     */
 
9899
                    if(gPasteEnabled == MSWIN_PASTE_LINE
 
9900
                       && (pPaste = _tcschr(gpPasteNext, (TCHAR)ASCII_CR))){
 
9901
                        *pPaste = (TCHAR)'\0';
 
9902
                        cbSize  = _tcslen(gpPasteNext);
 
9903
                    }
 
9904
 
 
9905
                    /*
 
9906
                     * If there is a selection (gCopyCutFunction != NULL)
 
9907
                     * then delete it so that it will be replaced by
 
9908
                     * the pasted text.
 
9909
                     */
 
9910
                    if (gCopyCutFunction != NULL)
 
9911
                        deleteregion (1, 0);
 
9912
 
 
9913
                    gPasteBytesRemain = cbSize;
 
9914
                    gPasteWasCR = FALSE;
 
9915
#ifdef FDEBUG
 
9916
                    if (mswin_debug > 8)
 
9917
                        fprintf (mswin_debugfile, "EditPaste::  Paste %d bytes\n",
 
9918
                                    gPasteBytesRemain);
 
9919
#endif
 
9920
                }
 
9921
                GlobalUnlock (hCB);
 
9922
            }
 
9923
            CloseClipboard ();
 
9924
        }
 
9925
    }
 
9926
}
 
9927
 
 
9928
 
 
9929
 
 
9930
 
 
9931
 
 
9932
 
 
9933
/*
 
9934
 * Cancel an active paste operation.
 
9935
 */
 
9936
LOCAL void
 
9937
EditCancelPaste (void)
 
9938
{
 
9939
    if (ghPaste != NULL) {      /* Must be pasting. */
 
9940
        GlobalUnlock (ghPaste); /* Then Unlock... */
 
9941
        GlobalFree (ghPaste);   /* ...and free the paste buffer. */
 
9942
        ghPaste = NULL;         /* Indicates no paste data. */
 
9943
        gpPasteNext = NULL;             /* Just being tidy. */
 
9944
        gPasteBytesRemain = 0;  /* ditto. */
 
9945
#ifdef FDEBUG
 
9946
        if (mswin_debug > 8)
 
9947
            fprintf (mswin_debugfile, "EditCancelPaste::  Free Paste Data\n");
 
9948
#endif
 
9949
    }
 
9950
}
 
9951
 
 
9952
 
 
9953
/*
 
9954
 * Get the next byte from the paste buffer.  If all bytes have been
 
9955
 * retreived, free the paste buffer.
 
9956
 * Map all CRLF sequence to a single CR.
 
9957
 */
 
9958
LOCAL UCS
 
9959
EditPasteGet (void)
 
9960
{
 
9961
    TCHAR  b = MSWIN_KEY_NODATA;
 
9962
 
 
9963
    if (ghPaste != NULL) {              /* ghPaste tells if we are pasting. */
 
9964
        if (gPasteBytesRemain > 0) {    /* Just in case... */
 
9965
                                        /* Get one byte and move pointer. */
 
9966
            b = (TCHAR) *gpPasteNext++;
 
9967
            --gPasteBytesRemain;        /*    one less. */
 
9968
            if (gPasteWasCR && b == (TCHAR)ASCII_LF) {
 
9969
                if (gPasteBytesRemain) {
 
9970
                                        /* Skip of LF. */
 
9971
                    b = (TCHAR) *gpPasteNext++;
 
9972
                    --gPasteBytesRemain;
 
9973
                }
 
9974
                else
 
9975
                    b = MSWIN_KEY_NODATA;  /* Ignore last LF. */
 
9976
            }
 
9977
            gPasteWasCR = (b == (TCHAR)ASCII_CR);
 
9978
#ifdef FDEBUG
 
9979
            if (mswin_debug > 8)
 
9980
                fprintf (mswin_debugfile, "EditPasteGet::  char %c, gPasteWasCR %d, gPasteBytesRemain %d\n",
 
9981
                        b, gPasteWasCR, gPasteBytesRemain);
 
9982
#endif
 
9983
        }
 
9984
        if (gPasteBytesRemain <= 0) {   /* All Done? */
 
9985
            GlobalUnlock (ghPaste);     /* Then Unlock... */
 
9986
            GlobalFree (ghPaste);       /* ...and free the paste buffer. */
 
9987
            ghPaste = NULL;             /* Indicates no paste data. */
 
9988
            gpPasteNext = NULL;         /* Just being tidy. */
 
9989
            gPasteBytesRemain = 0;      /* ditto. */
 
9990
#ifdef FDEBUG
 
9991
            if (mswin_debug > 8)
 
9992
                fprintf (mswin_debugfile, "EditPasteGet::  Free Paste Data\n");
 
9993
#endif
 
9994
        }
 
9995
    }
 
9996
    return ((UCS)b);
 
9997
}
 
9998
 
 
9999
 
 
10000
/*
 
10001
 * Return true if Paste data is available.  If gpPaste != NULL then there
 
10002
 * is paste data.
 
10003
 */
 
10004
LOCAL BOOL
 
10005
EditPasteAvailable (void)
 
10006
{
 
10007
    return (ghPaste != NULL);
 
10008
}
 
10009
 
 
10010
 
 
10011
 
 
10012
/*
 
10013
 * Select everything in the buffer
 
10014
 */
 
10015
LOCAL void
 
10016
EditSelectAll()
 
10017
{
 
10018
    if(ComposerEditing){
 
10019
    }
 
10020
    else{
 
10021
        gotobob(0, 1);
 
10022
        setmark(0, 1);
 
10023
        gotoeob(0, 1);
 
10024
        update ();              /* And update the screen */
 
10025
    }
 
10026
}
 
10027
 
 
10028
 
 
10029
 
 
10030
LOCAL void
 
10031
SortHandler(int order, int reverse)
 
10032
{
 
10033
    int old = (*gSortCallback)(0, 0);
 
10034
 
 
10035
    if(order < 0){
 
10036
        old ^= 0x0100;          /* flip reverse bit */
 
10037
        (*gSortCallback)(1, old);
 
10038
    }
 
10039
    else
 
10040
      (*gSortCallback)(1, order | (old & 0x0100));
 
10041
}
 
10042
 
 
10043
 
 
10044
 
 
10045
LOCAL void
 
10046
FlagHandler(int index, int args)
 
10047
{
 
10048
    (void) (*gFlagCallback)(index + 1, 0L);
 
10049
}
 
10050
 
 
10051
 
 
10052
 
 
10053
 
 
10054
LOCAL void
 
10055
MSWHelpShow (cbstr_t fpHelpCallback)
 
10056
{
 
10057
    if (fpHelpCallback != NULL){
 
10058
        char title[256], *help;
 
10059
 
 
10060
        if(help = (*fpHelpCallback) (title))
 
10061
          mswin_displaytext (title, help, strlen(help), NULL, NULL, 0);
 
10062
    }
 
10063
}
 
10064
 
 
10065
 
 
10066
 
 
10067
 
 
10068
 
 
10069
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
10070
 *
 
10071
 *                 Adjust the timer frequency as needed.
 
10072
 *
 
10073
 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
 
10074
 
 
10075
LOCAL void
 
10076
MyTimerSet (void)
 
10077
{
 
10078
    UINT        period;
 
10079
    /* Decide on period to use. */
 
10080
    if (gAllowMouseTrack)
 
10081
        period = MY_TIMER_EXCEEDINGLY_SHORT_PERIOD;
 
10082
    else
 
10083
        period = my_timer_period;
 
10084
 
 
10085
    if (period != gTimerCurrentPeriod) {
 
10086
        if (SetTimer (ghTTYWnd, MY_TIMER_ID, period, NULL) == 0)
 
10087
                MessageBox (ghTTYWnd, TIMER_FAIL_MESSAGE, NULL,
 
10088
                             MB_OK | MB_ICONINFORMATION);
 
10089
        else
 
10090
            gTimerCurrentPeriod = period;
 
10091
    }
 
10092
}
 
10093
 
 
10094
 
 
10095
 
 
10096
 
 
10097
 
 
10098
void
 
10099
mswin_setperiodiccallback (cbvoid_t periodiccb, long period)
 
10100
{
 
10101
    if (periodiccb != NULL && period > 0) {
 
10102
        gPeriodicCallback = periodiccb;
 
10103
        gPeriodicCBTime = period;
 
10104
        gPeriodicCBTimeout = GetTickCount () / 1000 + gPeriodicCBTime;
 
10105
    }
 
10106
    else {
 
10107
        gPeriodicCallback = NULL;
 
10108
    }
 
10109
}
 
10110
 
 
10111
 
 
10112
/*
 
10113
 * Execute command and wait for the child to exit
 
10114
 *
 
10115
 * whatsit - description of reason exec being called
 
10116
 * command - command to run
 
10117
 * infile - name of file to pass as stdin
 
10118
 * outfile - name of file to pass as stdout
 
10119
 * exit_val - where to store return value of the process
 
10120
 * mswe_flags -
 
10121
 *   MSWIN_EAW_CAPT_STDERR - capture stderr along with stdout
 
10122
 *   MSWIN_EAW_CTRL_C_CANCELS - if user presses ctrl-c, detach child
 
10123
 * Returns: 0, successfully completed program
 
10124
 *         -1, errors occurred
 
10125
 *         -2, user chose to stop waiting for program before it finished
 
10126
 */
 
10127
int
 
10128
mswin_exec_and_wait (char *utf8_whatsit, char *utf8_command,
 
10129
                     char *utf8_infile, char *utf8_outfile,
 
10130
                     int *exit_val, unsigned mswe_flags)
 
10131
{
 
10132
    MEvent              mouse;
 
10133
    BOOL                brc;
 
10134
    int                 rc;
 
10135
    TCHAR               waitingFor[256];
 
10136
    STARTUPINFO         start_info;
 
10137
    PROCESS_INFORMATION proc_info;
 
10138
    DWORD               exit_code;
 
10139
    FILE               *infd = NULL, *outfd = NULL;
 
10140
    SECURITY_ATTRIBUTES atts;
 
10141
    LPTSTR              lptstr_whatsit = NULL, lptstr_command = NULL;
 
10142
    LPTSTR              lptstr_infile = NULL, lptstr_outfile = NULL;
 
10143
 
 
10144
    mswin_flush ();
 
10145
 
 
10146
    memset(&proc_info, 0, sizeof(proc_info));
 
10147
    memset(&start_info, 0, sizeof(start_info));
 
10148
    memset(&atts, 0, sizeof(atts));
 
10149
 
 
10150
    start_info.dwFlags      = STARTF_FORCEONFEEDBACK | STARTF_USESHOWWINDOW;
 
10151
    start_info.wShowWindow  = (utf8_infile || utf8_outfile) ? SW_SHOWMINNOACTIVE
 
10152
      : SW_SHOWNA;
 
10153
 
 
10154
    /* set file attributes of temp files*/
 
10155
    atts.nLength = sizeof(SECURITY_ATTRIBUTES);
 
10156
    atts.bInheritHandle = TRUE;
 
10157
    atts.lpSecurityDescriptor = NULL;
 
10158
 
 
10159
    /* open files if asked for */
 
10160
    if(utf8_infile
 
10161
       && ((infd = CreateFile((lptstr_infile = utf8_to_lptstr(utf8_infile)),
 
10162
                              GENERIC_READ, 0, &atts,
 
10163
                              OPEN_EXISTING, FILE_ATTRIBUTE_READONLY, NULL))
 
10164
           == INVALID_HANDLE_VALUE)){
 
10165
        if(lptstr_infile)
 
10166
          fs_give((void **) &lptstr_infile);
 
10167
 
 
10168
        return(-1);
 
10169
    }
 
10170
    if(utf8_outfile
 
10171
       && ((outfd = CreateFile((lptstr_outfile = utf8_to_lptstr(utf8_outfile)),
 
10172
                               GENERIC_WRITE, 0, &atts,
 
10173
                               OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL))
 
10174
           == INVALID_HANDLE_VALUE)){
 
10175
        if(infd)
 
10176
          CloseHandle(infd);
 
10177
        if(lptstr_infile)
 
10178
          fs_give((void **) &lptstr_infile);
 
10179
 
 
10180
        if(lptstr_outfile)
 
10181
          fs_give((void **) &lptstr_outfile);
 
10182
 
 
10183
        return(-1);
 
10184
    }
 
10185
 
 
10186
    /* set up i/o redirection */
 
10187
    if(utf8_infile)
 
10188
      start_info.hStdInput = infd;
 
10189
    if(utf8_outfile)
 
10190
      start_info.hStdOutput = outfd;
 
10191
    if(utf8_outfile && (mswe_flags & MSWIN_EAW_CAPT_STDERR))
 
10192
      start_info.hStdError = outfd;
 
10193
    if(utf8_infile || utf8_outfile)
 
10194
      start_info.dwFlags |= STARTF_USESTDHANDLES;
 
10195
 
 
10196
    lptstr_command = utf8_to_lptstr(utf8_command);
 
10197
    lptstr_whatsit = utf8_to_lptstr(utf8_whatsit);
 
10198
    if(CreateProcess(NULL, lptstr_command, NULL, NULL, (utf8_infile || utf8_outfile)
 
10199
                     ? TRUE : FALSE,
 
10200
                     CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP,
 
10201
                     NULL, NULL, &start_info, &proc_info) == TRUE){
 
10202
 
 
10203
        _sntprintf(waitingFor, sizeof(waitingFor)/sizeof(TCHAR),
 
10204
                   TEXT("%s is currently waiting for the %s (%s) to complete.  Click \"Cancel\" to stop waiting, or \"OK\" to continue waiting."),
 
10205
                 gszAppName, lptstr_whatsit, lptstr_command);
 
10206
 
 
10207
        /* Don't need the thread handle, close it now. */
 
10208
        CloseHandle (proc_info.hThread);
 
10209
 
 
10210
        /*
 
10211
         * Go into holding pattern until the other application terminates
 
10212
         * or we are told to stop waiting.
 
10213
         */
 
10214
        while(GetExitCodeProcess(proc_info.hProcess, &exit_code) == TRUE){
 
10215
            if(exit_code == STILL_ACTIVE){
 
10216
                rc = mswin_getc();
 
10217
                brc = mswin_getmouseevent (&mouse);
 
10218
 
 
10219
                if (rc != MSWIN_KEY_NODATA ||
 
10220
                    (brc && mouse.event == M_EVENT_DOWN)) {
 
10221
                    if(mswe_flags & MSWIN_EAW_CTRL_C_CANCELS){
 
10222
                        if(rc < ' ' && (rc + '@' == 'C')) /* dumb way of saying ctrl-C */
 
10223
                          rc = IDCANCEL;
 
10224
                    }
 
10225
                    else{
 
10226
                        rc = MessageBox (ghTTYWnd, waitingFor, lptstr_whatsit,
 
10227
                                         MB_ICONSTOP | MB_OKCANCEL);
 
10228
                    }
 
10229
                    SelClear ();
 
10230
                    if (rc == IDCANCEL){
 
10231
                        /* terminate message to child ? */
 
10232
                        if(infd)
 
10233
                          CloseHandle(infd);
 
10234
                        if(outfd)
 
10235
                          CloseHandle(outfd);
 
10236
                        if(lptstr_infile)
 
10237
                          fs_give((void **) &lptstr_infile);
 
10238
                        if(lptstr_outfile)
 
10239
                          fs_give((void **) &lptstr_outfile);
 
10240
                        if(lptstr_whatsit)
 
10241
                          fs_give((void **) &lptstr_whatsit);
 
10242
                        if(lptstr_command)
 
10243
                          fs_give((void **) &lptstr_command);
 
10244
                        return (-2);
 
10245
                    }
 
10246
                }
 
10247
            }
 
10248
            else{
 
10249
                /* do something about child's exit status */
 
10250
                CloseHandle (proc_info.hProcess);
 
10251
                if(exit_val)
 
10252
                  *exit_val = exit_code;
 
10253
                break;
 
10254
            }
 
10255
        }
 
10256
 
 
10257
        if (gpTTYInfo->fMinimized)
 
10258
          ShowWindow (ghTTYWnd, SW_SHOWNORMAL);
 
10259
 
 
10260
        BringWindowToTop (ghTTYWnd);
 
10261
        if(infd)
 
10262
          CloseHandle(infd);
 
10263
        if(outfd)
 
10264
          CloseHandle(outfd);
 
10265
        if(lptstr_infile)
 
10266
          fs_give((void **) &lptstr_infile);
 
10267
        if(lptstr_outfile)
 
10268
          fs_give((void **) &lptstr_outfile);
 
10269
        if(lptstr_whatsit)
 
10270
          fs_give((void **) &lptstr_whatsit);
 
10271
        if(lptstr_command)
 
10272
          fs_give((void **) &lptstr_command);
 
10273
        return (0);
 
10274
    }
 
10275
    else{
 
10276
        if(infd)
 
10277
          CloseHandle(infd);
 
10278
        if(outfd){
 
10279
            CloseHandle(outfd);
 
10280
            _tunlink(lptstr_outfile);
 
10281
        }
 
10282
        if(lptstr_infile)
 
10283
          fs_give((void **) &lptstr_infile);
 
10284
        if(lptstr_outfile)
 
10285
          fs_give((void **) &lptstr_outfile);
 
10286
        if(lptstr_whatsit)
 
10287
          fs_give((void **) &lptstr_whatsit);
 
10288
        if(lptstr_command)
 
10289
          fs_give((void **) &lptstr_command);
 
10290
        return((rc = (int) GetLastError()) ? rc : -1);          /* hack */
 
10291
    }
 
10292
}
 
10293
 
 
10294
 
 
10295
int
 
10296
mswin_shell_exec(char *command_utf8, HINSTANCE *pChildProc)
 
10297
{
 
10298
    int               quoted = 0;
 
10299
    SHELLEXECUTEINFO  shell_info;
 
10300
    LPTSTR            command_lpt, free_command_lpt;
 
10301
    LPTSTR            p, q, parm = NULL;
 
10302
    TCHAR             buf[1024];
 
10303
 
 
10304
    if(!command_utf8)
 
10305
      return(-1);
 
10306
 
 
10307
    free_command_lpt = command_lpt = utf8_to_lptstr(command_utf8);
 
10308
    if(!command_lpt)
 
10309
      return(-1);
 
10310
 
 
10311
    mswin_flush ();
 
10312
 
 
10313
    /*
 
10314
     * Pick first arg apart by whitespace until what's to the left
 
10315
     * is no longer a valid path/file.  Everything else is then an
 
10316
     * command line arg...
 
10317
     */
 
10318
    if(*(p = command_lpt) == '\"'){
 
10319
        p = ++command_lpt;                              /* don't include quote */
 
10320
        quoted++;
 
10321
    }
 
10322
 
 
10323
    q = buf;
 
10324
    while(1)
 
10325
      if(!quoted && _istspace(*p)){
 
10326
          char *buf_utf8;
 
10327
 
 
10328
          *q = '\0';
 
10329
          buf_utf8 = lptstr_to_utf8(buf);
 
10330
          if(*buf == '*' || (buf_utf8 && fexist(buf_utf8, "x", (off_t *) NULL) == FIOSUC)){
 
10331
              parm = p;
 
10332
              if(buf_utf8)
 
10333
                fs_give((void **) &buf_utf8);
 
10334
 
 
10335
              break;
 
10336
          }
 
10337
 
 
10338
          if(buf_utf8)
 
10339
            fs_give((void **) &buf_utf8);
 
10340
      }
 
10341
      else if(quoted && *p == '\"'){
 
10342
          parm = p;
 
10343
          break;
 
10344
      }
 
10345
      else if(!(*q++ = *p++)){
 
10346
          parm = p - 1;
 
10347
          break;
 
10348
      }
 
10349
 
 
10350
    if(*command_lpt && parm){
 
10351
        do
 
10352
          *parm++ = '\0';
 
10353
        while(*parm && _istspace((unsigned char) *parm));
 
10354
 
 
10355
 
 
10356
        /*
 
10357
         * HACK -- since star is very unlikely to actually appear
 
10358
         * in a command name thats launched via a shell command line,
 
10359
         * a leading one indicates special handling.
 
10360
         */
 
10361
        if(command_lpt[0] == '*'){
 
10362
            if(!_tcsncmp(command_lpt + 1, TEXT("Shell*"), 8)){
 
10363
                /* Leave it to ShellExecute magic to "open" the thing */
 
10364
                command_lpt = parm;
 
10365
                parm = NULL;
 
10366
            }
 
10367
        }
 
10368
    }
 
10369
    else{
 
10370
      if(free_command_lpt)
 
10371
        fs_give((void **) &free_command_lpt);
 
10372
 
 
10373
      return(-1);
 
10374
    }
 
10375
 
 
10376
    memset(&shell_info, 0, sizeof(SHELLEXECUTEINFO));
 
10377
    shell_info.cbSize = sizeof(SHELLEXECUTEINFO);
 
10378
    shell_info.fMask = SEE_MASK_DOENVSUBST
 
10379
                      | SEE_MASK_NOCLOSEPROCESS
 
10380
                      | SEE_MASK_FLAG_DDEWAIT;
 
10381
    shell_info.hwnd = ghTTYWnd;
 
10382
    shell_info.lpFile = command_lpt;
 
10383
    shell_info.lpParameters = parm;
 
10384
    shell_info.lpDirectory = NULL;      /* default is current directory */
 
10385
    shell_info.nShow = SW_SHOWNORMAL;
 
10386
 
 
10387
    ShellExecuteEx(&shell_info);
 
10388
 
 
10389
    if((int)(LONG_PTR)shell_info.hInstApp > 32){
 
10390
        if(pChildProc)
 
10391
          *pChildProc = shell_info.hProcess;
 
10392
 
 
10393
        if(free_command_lpt)
 
10394
          fs_give((void **) &free_command_lpt);
 
10395
 
 
10396
        return(0);              /* success! */
 
10397
    }
 
10398
 
 
10399
    if(free_command_lpt)
 
10400
      fs_give((void **) &free_command_lpt);
 
10401
 
 
10402
    return(-1);
 
10403
}
 
10404
 
 
10405
 
 
10406
/*
 
10407
 * Generate an error message for a failed windows exec or loadlibrary.
 
10408
 */
 
10409
void
 
10410
mswin_exec_err_msg(char *what, int status, char *buf, size_t buflen)
 
10411
{
 
10412
    switch(status){
 
10413
      case 2:
 
10414
      case 3:
 
10415
        snprintf(buf, buflen, "%s not found.", what);
 
10416
        break;
 
10417
        
 
10418
      case 8:
 
10419
        snprintf(buf, buflen, "Not enough memory to run %s.", what);
 
10420
        break;
 
10421
        
 
10422
      default:
 
10423
        snprintf(buf, buflen, "Error %d starting %s.", status, what);
 
10424
        break;
 
10425
    }
 
10426
}
 
10427
 
 
10428
        
 
10429
int
 
10430
mswin_set_quit_confirm (int confirm)
 
10431
{
 
10432
    gConfirmExit = (confirm != 0);
 
10433
    return (confirm);
 
10434
}
 
10435
 
 
10436
 
 
10437
/*
 
10438
 * Called when Windows is in shutting down.  Before actually shutting down
 
10439
 * Windows goes around to all the applications and asks if it is OK with
 
10440
 * them to shut down (WM_QUERYENDSESSION).
 
10441
 * If gConfirmExit is set, ask the user if they want to exit.
 
10442
 * Returning zero will stop the shutdown, non-zero allows it to proceed.
 
10443
 */
 
10444
LOCAL LRESULT
 
10445
ConfirmExit (void)
 
10446
{
 
10447
    TCHAR       msg[256];
 
10448
    int         rc;
 
10449
 
 
10450
    if(gConfirmExit){
 
10451
        _sntprintf(msg, sizeof(msg)/sizeof(TCHAR),
 
10452
                   TEXT("Exiting may cause you to lose work in %s, Exit?"),
 
10453
                   gszAppName);
 
10454
        rc = MessageBox (ghTTYWnd, msg, gszAppName, MB_ICONSTOP | MB_OKCANCEL);
 
10455
        if(rc == IDCANCEL)
 
10456
          return(0);
 
10457
    }
 
10458
 
 
10459
    return(1);
 
10460
}
 
10461
 
 
10462
 
 
10463
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
10464
 *
 
10465
 *                  Registry access functions
 
10466
 *
 
10467
 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
 
10468
 
 
10469
/*
 
10470
 * Useful def's
 
10471
 */
 
10472
#define MSWR_KEY_MAX    128
 
10473
#define MSWR_VAL_MAX    128
 
10474
#define MSWR_CLASS_MAX  128
 
10475
#define MSWR_DATA_MAX   1024
 
10476
 
 
10477
 
 
10478
#define MSWR_ROOT       TEXT("Software\\University of Washington\\Alpine\\1.0")
 
10479
#define MSWR_APPNAME    TEXT("Alpine")
 
10480
#define MSWR_DLLPATH    TEXT("DLLPath")
 
10481
#define MSWR_DLLNAME    TEXT("pmapi32.dll")
 
10482
#define MSWRDBUF 1152
 
10483
 
 
10484
 
 
10485
struct mswin_reg_key {
 
10486
  HKEY   rhk;        /* root key (HKEY_LOCAL_MACHINE, ...) */
 
10487
  LPTSTR rkey;       /* key name */
 
10488
  LPTSTR rnames[3];  /* NULL terminated list of key values */
 
10489
};
 
10490
 
 
10491
static struct mswin_reg_key mswin_pine_regs[] = {
 
10492
    {HKEY_LOCAL_MACHINE, MSWR_ROOT, {TEXT("Pinedir"), TEXT("PineEXE"), NULL}},
 
10493
    {HKEY_CURRENT_USER, MSWR_ROOT, {TEXT("PineRC"), NULL}},
 
10494
    {HKEY_CURRENT_USER, MSWR_ROOT, {TEXT("PineAux"), NULL}},
 
10495
    {HKEY_CURRENT_USER, MSWR_ROOT, {TEXT("PinePos"), NULL}},
 
10496
    {HKEY_LOCAL_MACHINE,
 
10497
     TEXT("Software\\Clients\\Mail\\Alpine"),
 
10498
     {TEXT(""), TEXT("DLLPath"), NULL}},
 
10499
    {HKEY_LOCAL_MACHINE, TEXT("Software\\Clients\\Mail\\Alpine\\Protocols\\Mailto\\DefaultIcon"),
 
10500
     {TEXT(""), NULL}},
 
10501
    {HKEY_LOCAL_MACHINE,
 
10502
     TEXT("Software\\Clients\\Mail\\Alpine\\Protocols\\Mailto\\shell\\open\\command"),
 
10503
     {TEXT(""), NULL}},
 
10504
   {HKEY_LOCAL_MACHINE,
 
10505
    TEXT("Software\\Clients\\Mail\\Alpine\\shell\\open\\command"),
 
10506
    {TEXT(""), NULL}},
 
10507
   {HKEY_LOCAL_MACHINE,
 
10508
    TEXT("Software\\Clients\\News\\Alpine"),
 
10509
    {TEXT(""), NULL}},
 
10510
   {HKEY_LOCAL_MACHINE,
 
10511
    TEXT("Software\\Clients\\News\\Alpine\\Protocols\\news\\DefaultIcon"),
 
10512
    {TEXT(""), NULL}},
 
10513
   {HKEY_LOCAL_MACHINE,
 
10514
    TEXT("Software\\Clients\\News\\Alpine\\Protocols\\news\\shell\\open\\command"),
 
10515
    {TEXT(""), NULL}},
 
10516
   {HKEY_LOCAL_MACHINE,
 
10517
    TEXT("Software\\Clients\\News\\Alpine\\Protocols\\nntp\\DefaultIcon"),
 
10518
    {TEXT(""), NULL}},
 
10519
   {HKEY_LOCAL_MACHINE,
 
10520
    TEXT("Software\\Clients\\News\\Alpine\\Protocols\\nntp\\shell\\open\\command"),
 
10521
    {TEXT(""), NULL}},
 
10522
   {HKEY_LOCAL_MACHINE,
 
10523
    TEXT("Software\\Clients\\News\\Alpine\\shell\\open\\command"),
 
10524
    {TEXT(""), NULL}},
 
10525
  {NULL, NULL, {NULL}}
 
10526
};
 
10527
 
 
10528
 
 
10529
/*
 
10530
 *  data: unitialized buffer, could be null
 
10531
 */
 
10532
int
 
10533
mswin_reg(int op, int tree, char *data_utf8, size_t size)
 
10534
{
 
10535
    LPTSTR data_lptstr = NULL;
 
10536
    int rv;
 
10537
 
 
10538
    if(data_utf8){
 
10539
        if(size == 0){
 
10540
            /* size is zero when op & MSWR_OP_SET */
 
10541
            data_lptstr = utf8_to_lptstr(data_utf8);
 
10542
        }
 
10543
        else {
 
10544
            data_lptstr = (LPTSTR)MemAlloc(size * sizeof(TCHAR));
 
10545
            data_lptstr[0] = '\0';
 
10546
        }
 
10547
    }
 
10548
 
 
10549
    rv = mswin_reg_lptstr(op, tree, data_lptstr, size);
 
10550
 
 
10551
    if(data_utf8 && data_lptstr){
 
10552
        char *t_utf8str;
 
10553
        if(size){
 
10554
            t_utf8str = lptstr_to_utf8(data_lptstr);
 
10555
            strncpy(data_utf8, t_utf8str, size);
 
10556
            data_utf8[size-1] = '\0';
 
10557
            MemFree((void *)t_utf8str);
 
10558
        }
 
10559
        MemFree((void *)data_lptstr);
 
10560
    }
 
10561
    return(rv);
 
10562
}
 
10563
 
 
10564
int
 
10565
mswin_reg_lptstr(int op, int tree, LPTSTR data_lptstr, size_t size)
 
10566
{
 
10567
    if(op & MSWR_OP_SET){
 
10568
        switch(tree){
 
10569
          case MSWR_PINE_RC :
 
10570
            MSWRAlpineSet(HKEY_CURRENT_USER, NULL,
 
10571
                        TEXT("PineRC"), op & MSWR_OP_FORCE, data_lptstr);
 
10572
            break;
 
10573
 
 
10574
          case MSWR_PINE_CONF :
 
10575
            MSWRAlpineSet(HKEY_CURRENT_USER, NULL,
 
10576
                        TEXT("PineConf"), op & MSWR_OP_FORCE, data_lptstr);
 
10577
            break;
 
10578
 
 
10579
          case MSWR_PINE_AUX :
 
10580
            MSWRAlpineSet(HKEY_CURRENT_USER, NULL,
 
10581
                        TEXT("PineAux"), op & MSWR_OP_FORCE, data_lptstr);
 
10582
            break;
 
10583
 
 
10584
          case MSWR_PINE_DIR :
 
10585
            MSWRAlpineSet(HKEY_LOCAL_MACHINE, NULL,
 
10586
                        TEXT("Pinedir"), op & MSWR_OP_FORCE, data_lptstr);
 
10587
            MSWRAlpineSetHandlers(op & MSWR_OP_FORCE, data_lptstr);
 
10588
            break;
 
10589
 
 
10590
          case MSWR_PINE_EXE :
 
10591
            MSWRAlpineSet(HKEY_LOCAL_MACHINE, NULL,
 
10592
                        TEXT("PineEXE"), op & MSWR_OP_FORCE, data_lptstr);
 
10593
            break;
 
10594
 
 
10595
          case MSWR_PINE_POS :
 
10596
            MSWRAlpineSet(HKEY_CURRENT_USER, NULL,
 
10597
                        TEXT("PinePos"), op & MSWR_OP_FORCE, data_lptstr);
 
10598
            break;
 
10599
 
 
10600
          default :
 
10601
           break;
 
10602
        }
 
10603
    }
 
10604
    else if(op & MSWR_OP_GET){
 
10605
        switch(tree){
 
10606
          case MSWR_PINE_RC :
 
10607
            return(MSWRAlpineGet(HKEY_CURRENT_USER, NULL,
 
10608
                               TEXT("PineRC"), data_lptstr, size));
 
10609
          case MSWR_PINE_CONF :
 
10610
            return(MSWRAlpineGet(HKEY_CURRENT_USER, NULL,
 
10611
                               TEXT("PineConf"), data_lptstr, size));
 
10612
          case MSWR_PINE_AUX :
 
10613
            return(MSWRAlpineGet(HKEY_CURRENT_USER, NULL,
 
10614
                               TEXT("PineAux"), data_lptstr, size));                    
 
10615
          case MSWR_PINE_DIR :
 
10616
            return(MSWRAlpineGet(HKEY_LOCAL_MACHINE, NULL,
 
10617
                               TEXT("Pinedir"), data_lptstr, size));
 
10618
          case MSWR_PINE_EXE :
 
10619
            return(MSWRAlpineGet(HKEY_LOCAL_MACHINE, NULL,
 
10620
                               TEXT("PineEXE"), data_lptstr, size));
 
10621
          case MSWR_PINE_POS :
 
10622
            return(MSWRAlpineGet(HKEY_CURRENT_USER, NULL,
 
10623
                               TEXT("PinePos"), data_lptstr, size));
 
10624
          default :
 
10625
           break;
 
10626
        }
 
10627
    }
 
10628
    else if(op & MSWR_OP_BLAST){
 
10629
        int rv = 0;
 
10630
 
 
10631
        /* UN-Register as a mail client on this system */
 
10632
        rv +=
 
10633
          MSWRClear(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Clients\\Mail\\Alpine"));
 
10634
 
 
10635
        /* UN-Register as a news client on this system */
 
10636
        rv +=
 
10637
          MSWRClear(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Clients\\News\\Alpine"));
 
10638
 
 
10639
        /* UN-Register as a IMAP url handler */
 
10640
        rv +=
 
10641
          MSWRClear(HKEY_CLASSES_ROOT, TEXT("imap"));
 
10642
 
 
10643
        rv +=
 
10644
          MSWRClear(HKEY_LOCAL_MACHINE, MSWR_ROOT);
 
10645
 
 
10646
        rv +=
 
10647
          MSWRClear(HKEY_CURRENT_USER, MSWR_ROOT);
 
10648
        if(rv) return -1;
 
10649
    }
 
10650
    /* else, ignore unknown op? */
 
10651
 
 
10652
    return(0);
 
10653
}
 
10654
 
 
10655
 
 
10656
/*
 
10657
 *  Dump all of the registry values into an array of strings.
 
10658
 */
 
10659
char **
 
10660
mswin_reg_dump()
 
10661
{
 
10662
    int            lines = 10;  /* initial amount of lines */
 
10663
    int            i = 0, j, tlines = 0;
 
10664
    LPTSTR         *regtext, tmpreg_lptstr;
 
10665
    TCHAR          tmpbuf[MSWRDBUF];
 
10666
    BYTE           tmpreg[MSWR_DATA_MAX];
 
10667
    HKEY           hKey;
 
10668
    unsigned long  tmpreglen = MSWR_DATA_MAX, tmpbuflen = MSWRDBUF;
 
10669
    char           **regtext_utf8;
 
10670
 
 
10671
    /* approximate how many lines we're going to need */
 
10672
    while(mswin_pine_regs[i].rkey){
 
10673
      lines += 2;
 
10674
      j = 0;
 
10675
      while(mswin_pine_regs[i].rnames[j]){
 
10676
        lines++;
 
10677
        j++;
 
10678
      }
 
10679
      i++;
 
10680
    }
 
10681
    regtext = (LPTSTR *)MemAlloc((lines+1) * sizeof(LPTSTR));
 
10682
    i = tlines = 0;
 
10683
    _sntprintf(tmpbuf, tmpbuflen, TEXT("Registry values for Alpine:"));
 
10684
    regtext[tlines] = MemAlloc((_tcslen(tmpbuf) + 1) * sizeof(TCHAR));
 
10685
    _tcsncpy(regtext[tlines++], tmpbuf, _tcslen(tmpbuf)+1);
 
10686
    _sntprintf(tmpbuf, tmpbuflen, TEXT(""));
 
10687
    regtext[tlines] = MemAlloc((_tcslen(tmpbuf) + 1) * sizeof(TCHAR));
 
10688
    _tcsncpy(regtext[tlines++], tmpbuf, _tcslen(tmpbuf)+1);
 
10689
    while(i < lines && mswin_pine_regs[i].rkey){
 
10690
        _sntprintf(tmpbuf, tmpbuflen, TEXT("[ %s\\%s ]"),
 
10691
              mswin_pine_regs[i].rhk == HKEY_LOCAL_MACHINE ?
 
10692
                   TEXT("HKEY_LOCAL_MACHINE") : TEXT("HKEY_CURRENT_USER"),
 
10693
                   mswin_pine_regs[i].rkey);
 
10694
      regtext[tlines] = MemAlloc((_tcslen(tmpbuf) + 1) * sizeof(TCHAR));
 
10695
      _tcsncpy(regtext[tlines++], tmpbuf, _tcslen(tmpbuf)+1);
 
10696
      if(RegOpenKeyEx(mswin_pine_regs[i].rhk,
 
10697
                      mswin_pine_regs[i].rkey,
 
10698
                      0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS){
 
10699
        j = 0;
 
10700
        while(mswin_pine_regs[i].rnames[j]){
 
10701
            DWORD dType;
 
10702
 
 
10703
            RegQueryValueEx(hKey, mswin_pine_regs[i].rnames[j], NULL, &dType,
 
10704
                            tmpreg, &tmpreglen);
 
10705
            tmpreg_lptstr = (LPTSTR)tmpreg;
 
10706
            _sntprintf(tmpbuf, tmpbuflen, TEXT("\t%s = %s"), *(mswin_pine_regs[i].rnames[j]) ?
 
10707
                       mswin_pine_regs[i].rnames[j] : TEXT("(Default)"),
 
10708
                       *tmpreg_lptstr ? tmpreg_lptstr : TEXT("(Not Defined)"));
 
10709
            regtext[tlines] = (LPTSTR)MemAlloc((_tcslen(tmpbuf) + 1) * sizeof(TCHAR));
 
10710
            _tcsncpy(regtext[tlines++], tmpbuf, _tcslen(tmpbuf)+1);
 
10711
            tmpreg[0] = 0;
 
10712
            tmpreglen = MSWR_DATA_MAX;
 
10713
            j++;
 
10714
        }
 
10715
        RegCloseKey(hKey);
 
10716
      }
 
10717
      else{
 
10718
          _sntprintf(tmpbuf, tmpbuflen, TEXT("\tNOT DEFINED"));
 
10719
          regtext[tlines] = (LPTSTR)MemAlloc((_tcslen(tmpbuf) + 1) * sizeof(TCHAR));
 
10720
          _tcsncpy(regtext[tlines++], tmpbuf, _tcslen(tmpbuf)+1);
 
10721
      }
 
10722
      _sntprintf(tmpbuf, tmpbuflen, TEXT(""));
 
10723
      regtext[tlines] = (LPTSTR)MemAlloc((_tcslen(tmpbuf) + 1) * sizeof(TCHAR));
 
10724
      _tcsncpy(regtext[tlines++], tmpbuf, _tcslen(tmpbuf)+1);
 
10725
      i++;
 
10726
    }
 
10727
    regtext[tlines] = NULL;
 
10728
 
 
10729
    /* kinda silly to convert to utf8 only to convert back */
 
10730
    regtext_utf8 = (char **)MemAlloc((tlines+1) * sizeof(char *));
 
10731
    for(i = 0; i < tlines; i++){
 
10732
        if(regtext[i]){
 
10733
            regtext_utf8[i] = lptstr_to_utf8(regtext[i]);
 
10734
            MemFree((void *)regtext[i]);
 
10735
        }
 
10736
        else
 
10737
          regtext_utf8[i] = NULL;
 
10738
    }
 
10739
    regtext_utf8[lines] = NULL;
 
10740
    MemFree((void *)regtext);
 
10741
 
 
10742
    return regtext_utf8;
 
10743
}
 
10744
 
 
10745
 
 
10746
 
 
10747
LOCAL void
 
10748
MSWRAlpineSet(HKEY hRootKey, LPTSTR subkey, LPTSTR val, int update, LPTSTR data)
 
10749
{
 
10750
    HKEY  hKey;
 
10751
    TCHAR keybuf[MSWR_KEY_MAX+1];
 
10752
 
 
10753
    _sntprintf(keybuf, MSWR_KEY_MAX+1, TEXT("%s%s%s"), MSWR_ROOT,
 
10754
               (subkey && *subkey != '\\') ? TEXT("\\") : TEXT(""),
 
10755
               (subkey) ? TEXT("\\") : TEXT(""));
 
10756
 
 
10757
    if(RegCreateKeyEx(hRootKey, keybuf, 0, TEXT("REG_SZ"),
 
10758
                      REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
 
10759
                      NULL, &hKey, NULL) == ERROR_SUCCESS){
 
10760
        if(update || RegQueryValueEx(hKey, val, NULL, NULL,
 
10761
                                      NULL, NULL) != ERROR_SUCCESS)
 
10762
          RegSetValueEx(hKey, val, 0, REG_SZ, (LPBYTE)data, (DWORD)(_tcslen(data)+1)*sizeof(TCHAR));
 
10763
 
 
10764
        RegCloseKey(hKey);
 
10765
    }
 
10766
}
 
10767
 
 
10768
 
 
10769
 
 
10770
LOCAL int
 
10771
MSWRAlpineGet(HKEY hKey, LPTSTR subkey, LPTSTR val, LPTSTR data_lptstr, size_t len)
 
10772
{
 
10773
    TCHAR keybuf[MSWR_KEY_MAX+1];
 
10774
    DWORD dlen = (DWORD)len;
 
10775
 
 
10776
    _sntprintf(keybuf, MSWR_KEY_MAX+1, TEXT("%s%s%s"), MSWR_ROOT,
 
10777
            (subkey && *subkey != '\\') ? TEXT("\\") : TEXT(""),
 
10778
            (subkey) ? TEXT("\\") : TEXT(""));
 
10779
 
 
10780
    return(MSWRPeek(hKey, keybuf, val, data_lptstr, &dlen) == TRUE);
 
10781
}
 
10782
 
 
10783
 
 
10784
 
 
10785
LOCAL void
 
10786
MSWRAlpineSetHandlers(int update, LPTSTR path_lptstr)
 
10787
{
 
10788
    HKEY  hKey, hSubKey;
 
10789
    DWORD dwDisp;
 
10790
    BYTE tmp_b[MSWR_DATA_MAX];
 
10791
    unsigned long tmplen = MSWR_DATA_MAX, tmp_lptstr_tcharlen = MSWR_DATA_MAX/sizeof(TCHAR);
 
10792
    int   exists;
 
10793
    LPTSTR tmp_lptstr = (LPTSTR)tmp_b;
 
10794
 
 
10795
    /* Register as a mail client on this system */
 
10796
    if((exists = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
 
10797
                              TEXT("SOFTWARE\\Clients\\Mail\\Alpine"),
 
10798
                              0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
 
10799
       || RegCreateKeyEx(HKEY_LOCAL_MACHINE,
 
10800
                         TEXT("SOFTWARE\\Clients\\Mail\\Alpine"),
 
10801
                         0, TEXT("REG_SZ"),
 
10802
                         REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
 
10803
                         NULL, &hKey, &dwDisp) == ERROR_SUCCESS){
 
10804
        if(update || !exists){
 
10805
            DWORD dType;
 
10806
            char *tmp_utf8str = NULL;
 
10807
 
 
10808
            MSWRPoke(hKey, NULL, NULL, MSWR_APPNAME);
 
10809
            /* set up MAPI dll stuff */
 
10810
            *tmp_b = 0;
 
10811
            RegQueryValueEx(hKey, MSWR_DLLPATH, NULL, &dType, tmp_b, &tmplen);
 
10812
            tmp_lptstr = (LPTSTR)tmp_b;
 
10813
            if(!(*tmp_lptstr)
 
10814
               || (can_access(tmp_utf8str = lptstr_to_utf8(tmp_lptstr), ACCESS_EXISTS) != 0)){
 
10815
              if(*tmp_lptstr)
 
10816
                RegDeleteValue(hKey, MSWR_DLLPATH);
 
10817
              if(tmp_utf8str)
 
10818
                MemFree((void *)tmp_utf8str);
 
10819
 
 
10820
              _sntprintf(tmp_lptstr, tmp_lptstr_tcharlen,
 
10821
                         TEXT("%s%s"), path_lptstr, MSWR_DLLNAME);
 
10822
 
 
10823
              if(can_access(tmp_utf8str = lptstr_to_utf8(tmp_lptstr), ACCESS_EXISTS) == 0)
 
10824
                MSWRPoke(hKey, NULL, MSWR_DLLPATH, tmp_lptstr);
 
10825
            }
 
10826
            if(tmp_utf8str)
 
10827
              MemFree((void *)tmp_utf8str);
 
10828
            /* Set "mailto" handler */
 
10829
            if(RegCreateKeyEx(hKey, TEXT("Protocols\\Mailto"), 0, TEXT("REG_SZ"),
 
10830
                              REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
 
10831
                              NULL, &hSubKey, &dwDisp) == ERROR_SUCCESS){
 
10832
                MSWRProtocolSet(hSubKey, MSWR_SDC_MAIL, path_lptstr);
 
10833
                RegCloseKey(hSubKey);
 
10834
            }
 
10835
 
 
10836
            /* Set normal handler */
 
10837
            _sntprintf(tmp_lptstr, tmp_lptstr_tcharlen,
 
10838
                       TEXT("\"%salpine.exe\""), path_lptstr);
 
10839
            MSWRPoke(hKey, TEXT("shell\\open\\command"), NULL, tmp_lptstr);
 
10840
        }
 
10841
 
 
10842
        RegCloseKey(hKey);
 
10843
    }
 
10844
 
 
10845
    /* Register as a news client on this system */
 
10846
    if((exists = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
 
10847
                              TEXT("SOFTWARE\\Clients\\News\\Alpine"),
 
10848
                              0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
 
10849
       || RegCreateKeyEx(HKEY_LOCAL_MACHINE,
 
10850
                         TEXT("SOFTWARE\\Clients\\News\\Alpine"),
 
10851
                         0, TEXT("REG_SZ"), REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
 
10852
                         NULL, &hKey, &dwDisp) == ERROR_SUCCESS){
 
10853
        if(update || !exists){
 
10854
            MSWRPoke(hKey, NULL, NULL, MSWR_APPNAME);
 
10855
 
 
10856
            /* Set "news" handler */
 
10857
            if(RegCreateKeyEx(hKey, TEXT("Protocols\\news"), 0, TEXT("REG_SZ"),
 
10858
                              REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
 
10859
                              NULL, &hSubKey, &dwDisp) == ERROR_SUCCESS){
 
10860
                MSWRProtocolSet(hSubKey, MSWR_SDC_NEWS, path_lptstr);
 
10861
                RegCloseKey(hSubKey);
 
10862
            }
 
10863
            /* Set "nntp" handler */
 
10864
            if(RegCreateKeyEx(hKey, TEXT("Protocols\\nntp"), 0, TEXT("REG_SZ"),
 
10865
                              REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
 
10866
                              NULL, &hSubKey, &dwDisp) == ERROR_SUCCESS){
 
10867
                MSWRProtocolSet(hSubKey, MSWR_SDC_NNTP, path_lptstr);
 
10868
                RegCloseKey(hSubKey);
 
10869
            }
 
10870
 
 
10871
            /* Set normal handler */
 
10872
            _sntprintf(tmp_lptstr, tmp_lptstr_tcharlen,
 
10873
                      TEXT("\"%salpine.exe\""), path_lptstr);
 
10874
            MSWRPoke(hKey, TEXT("shell\\open\\command"), NULL, tmp_lptstr);
 
10875
        }
 
10876
 
 
10877
        RegCloseKey(hKey);
 
10878
    }
 
10879
 
 
10880
    /* Register as a IMAP url handler */
 
10881
    if((exists = RegOpenKeyEx(HKEY_CLASSES_ROOT, TEXT("imap"),
 
10882
                              0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS)
 
10883
       || RegCreateKeyEx(HKEY_CLASSES_ROOT, TEXT("imap"), 0, TEXT("REG_SZ"),
 
10884
                         REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
 
10885
                         NULL, &hKey, &dwDisp) == ERROR_SUCCESS){
 
10886
        if(update || !exists)
 
10887
          MSWRProtocolSet(hKey, MSWR_SDC_IMAP, path_lptstr);
 
10888
 
 
10889
        RegCloseKey(hKey);
 
10890
    }
 
10891
}
 
10892
 
 
10893
 
 
10894
 
 
10895
char *
 
10896
mswin_reg_default_browser(char *url_utf8)
 
10897
{
 
10898
    TCHAR scheme[MSWR_KEY_MAX+1], *p;
 
10899
    LPTSTR url_lptstr;
 
10900
    char cmdbuf[MSWR_DATA_MAX], *cmd = NULL;
 
10901
 
 
10902
    url_lptstr = utf8_to_lptstr(url_utf8);
 
10903
 
 
10904
    if(url_lptstr && (p = _tcschr(url_lptstr, ':')) && p - url_lptstr < MSWR_KEY_MAX){
 
10905
        _tcsncpy(scheme, url_lptstr, p - url_lptstr);
 
10906
        scheme[p-url_lptstr] = '\0';
 
10907
 
 
10908
        if(MSWRShellCanOpen(scheme, cmdbuf, MSWR_DATA_MAX, 0)){
 
10909
            size_t len;
 
10910
 
 
10911
            len = strlen(cmdbuf) + 2;
 
10912
            cmd = (char *) fs_get((len+1) * sizeof(char));
 
10913
            if(cmd){
 
10914
                if(strchr(cmdbuf, '*'))
 
10915
                  snprintf(cmd, len+1, "\"%s\"", cmdbuf);
 
10916
                else{
 
10917
                    strncpy(cmd, cmdbuf, len);
 
10918
                    cmd[len] = '\0';
 
10919
                }
 
10920
            }
 
10921
        }
 
10922
    }
 
10923
 
 
10924
    MemFree((void *)url_lptstr);
 
10925
 
 
10926
    return(cmd);
 
10927
}
 
10928
 
 
10929
 
 
10930
int
 
10931
mswin_is_def_client(int type)
 
10932
{
 
10933
    TCHAR buf[MSWR_KEY_MAX+1];
 
10934
    DWORD buflen = MSWR_KEY_MAX;
 
10935
 
 
10936
    if(type != MSWR_SDC_MAIL && type != MSWR_SDC_NEWS)
 
10937
      return -1;
 
10938
 
 
10939
    if(MSWRPeek(HKEY_CURRENT_USER,
 
10940
                type == MSWR_SDC_MAIL ? TEXT("Software\\Clients\\Mail")
 
10941
                : TEXT("Software\\Clients\\News"), NULL,
 
10942
                buf, &buflen) && !_tcscmp(buf, TEXT("Alpine")))
 
10943
      return 1;
 
10944
    buflen = MSWR_KEY_MAX;
 
10945
    if(MSWRPeek(HKEY_LOCAL_MACHINE,
 
10946
                type == MSWR_SDC_MAIL ? TEXT("Software\\Clients\\Mail")
 
10947
                : TEXT("Software\\Clients\\News"), NULL,
 
10948
                buf, &buflen) && !_tcscmp(buf, TEXT("Alpine")))
 
10949
      return 1;
 
10950
    return 0;
 
10951
}
 
10952
 
 
10953
int
 
10954
mswin_set_def_client(int type)
 
10955
{
 
10956
    HKEY hKey;
 
10957
    int successful_set = 0;
 
10958
    TCHAR path_lptstr[MSWR_DATA_MAX];
 
10959
    DWORD dwDisp;
 
10960
 
 
10961
    if(type != MSWR_SDC_MAIL && type != MSWR_SDC_NEWS)
 
10962
      return 1;
 
10963
    if(RegOpenKeyEx(HKEY_CURRENT_USER,
 
10964
                    type == MSWR_SDC_MAIL ? TEXT("Software\\Clients\\Mail")
 
10965
                    : TEXT("Software\\Clients\\News"),
 
10966
                    0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS){
 
10967
        successful_set = MSWRPoke(hKey, NULL, NULL, TEXT("Alpine"));
 
10968
        RegCloseKey(hKey);
 
10969
    }
 
10970
    else if(RegOpenKeyEx(HKEY_LOCAL_MACHINE,
 
10971
                         type == MSWR_SDC_MAIL ? TEXT("Software\\Clients\\Mail")
 
10972
                         : TEXT("Software\\Clients\\News"),
 
10973
                         0, KEY_ALL_ACCESS, &hKey) == ERROR_SUCCESS){
 
10974
        successful_set = MSWRPoke(hKey, NULL, NULL, TEXT("Alpine"));
 
10975
        RegCloseKey(hKey);
 
10976
    }
 
10977
    if(successful_set){
 
10978
        mswin_reg_lptstr(MSWR_OP_GET, MSWR_PINE_DIR, path_lptstr, sizeof(path_lptstr)/sizeof(TCHAR));
 
10979
        if(type == MSWR_SDC_MAIL){
 
10980
            MSWRClear(HKEY_CLASSES_ROOT, TEXT("mailto"));
 
10981
            if(RegCreateKeyEx(HKEY_CLASSES_ROOT, TEXT("mailto"), 0, TEXT("REG_SZ"),
 
10982
                              REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
 
10983
                              NULL, &hKey, &dwDisp) == ERROR_SUCCESS){
 
10984
                MSWRProtocolSet(hKey, MSWR_SDC_MAIL, path_lptstr);
 
10985
                RegCloseKey(hKey);
 
10986
            }
 
10987
        }
 
10988
        else if(type == MSWR_SDC_NEWS){
 
10989
            MSWRClear(HKEY_CLASSES_ROOT, TEXT("news"));
 
10990
            if(RegCreateKeyEx(HKEY_CLASSES_ROOT, TEXT("news"), 0, TEXT("REG_SZ"),
 
10991
                              REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
 
10992
                              NULL, &hKey, &dwDisp) == ERROR_SUCCESS){
 
10993
                MSWRProtocolSet(hKey, MSWR_SDC_NEWS, path_lptstr);
 
10994
                RegCloseKey(hKey);
 
10995
            }
 
10996
            MSWRClear(HKEY_CLASSES_ROOT, TEXT("nntp"));
 
10997
            if(RegCreateKeyEx(HKEY_CLASSES_ROOT, TEXT("nntp"), 0, TEXT("REG_SZ"),
 
10998
                              REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
 
10999
                              NULL, &hKey, &dwDisp) == ERROR_SUCCESS){
 
11000
                MSWRProtocolSet(hKey, MSWR_SDC_NNTP, path_lptstr);
 
11001
                RegCloseKey(hKey);
 
11002
            }
 
11003
        }
 
11004
    }
 
11005
    return 0;
 
11006
}
 
11007
 
 
11008
int
 
11009
MSWRProtocolSet(HKEY hKey, int type, LPTSTR path_lptstr)
 
11010
{
 
11011
    TCHAR tmp_lptstr[MSWR_DATA_MAX];
 
11012
    BYTE EditFlags[4];
 
11013
    unsigned long tmp_lptstr_len = MSWR_DATA_MAX;
 
11014
 
 
11015
    if(type != MSWR_SDC_MAIL && type != MSWR_SDC_NEWS
 
11016
       && type != MSWR_SDC_NNTP && type != MSWR_SDC_IMAP)
 
11017
      return -1;
 
11018
    MSWRPoke(hKey, NULL, NULL, type == MSWR_SDC_MAIL
 
11019
             ? TEXT("URL:MailTo Protocol")
 
11020
             : type == MSWR_SDC_NEWS ? TEXT("URL:News Protocol")
 
11021
             : type == MSWR_SDC_NNTP ? TEXT("URL:NNTP Protocol")
 
11022
             : TEXT("URL:IMAP Prototcol"));
 
11023
    MSWRPoke(hKey, NULL, TEXT("URL Protocol"), TEXT(""));
 
11024
 
 
11025
    EditFlags[0] = 0x02;
 
11026
    EditFlags[1] = EditFlags[2] = EditFlags[3] = 0;
 
11027
 
 
11028
    (void) RegDeleteValue(hKey, TEXT("EditFlags"));
 
11029
    (void) RegSetValueEx(hKey, TEXT("EditFlags"), 0, REG_BINARY,
 
11030
                         EditFlags, (DWORD) 4);
 
11031
 
 
11032
    _sntprintf(tmp_lptstr, tmp_lptstr_len,
 
11033
               TEXT("%salpine.exe,0"), path_lptstr);
 
11034
    MSWRPoke(hKey, TEXT("DefaultIcon"), NULL, tmp_lptstr);
 
11035
 
 
11036
    _sntprintf(tmp_lptstr, tmp_lptstr_len,
 
11037
              TEXT("\"%salpine.exe\" -url \"%%1\""), path_lptstr);
 
11038
    MSWRPoke(hKey, TEXT("shell\\open\\command"), NULL, tmp_lptstr);
 
11039
    return 0;
 
11040
}
 
11041
 
 
11042
 
 
11043
/* cmdbuf can stay char * since it's our string */
 
11044
BOOL
 
11045
MSWRShellCanOpen(LPTSTR key, char *cmdbuf, int clen, int allow_noreg)
 
11046
{
 
11047
    HKEY   hKey;
 
11048
    BOOL   rv = FALSE;
 
11049
 
 
11050
    /* See if Shell provides a method to open the thing... */
 
11051
    if(RegOpenKeyEx(HKEY_CLASSES_ROOT, key,
 
11052
                    0, KEY_READ, &hKey) == ERROR_SUCCESS){
 
11053
 
 
11054
        if(cmdbuf){
 
11055
            strncpy(cmdbuf, "*Shell*", clen);
 
11056
            cmdbuf[clen-1] = '\0';
 
11057
        }
 
11058
 
 
11059
        rv = TRUE;
 
11060
 
 
11061
        RegCloseKey(hKey);
 
11062
    }
 
11063
    else if(allow_noreg && cmdbuf){
 
11064
        strncpy(cmdbuf, "*Shell*", clen);
 
11065
        cmdbuf[clen-1] = '\0';
 
11066
        rv = TRUE;
 
11067
    }
 
11068
 
 
11069
    return(rv);
 
11070
}
 
11071
 
 
11072
 
 
11073
/*
 
11074
 * Fundamental registry access function that queries for particular values.
 
11075
 */
 
11076
LOCAL BOOL
 
11077
MSWRPeek(HKEY hRootKey, LPTSTR subkey, LPTSTR valstr, LPTSTR data_lptstr, DWORD *dlen)
 
11078
{
 
11079
    HKEY   hKey;
 
11080
    DWORD  dtype, dlen_bytes = (dlen ? *dlen : 0) * (*dlen)*sizeof(TCHAR);
 
11081
    LONG   rv = !ERROR_SUCCESS;
 
11082
 
 
11083
    if(RegOpenKeyEx(hRootKey, subkey, 0, KEY_READ, &hKey) == ERROR_SUCCESS){
 
11084
        rv = RegQueryValueEx(hKey, valstr, NULL, &dtype, (LPBYTE)data_lptstr, &dlen_bytes);
 
11085
        if(dlen)
 
11086
          (*dlen) = dlen_bytes;
 
11087
        RegCloseKey(hKey);
 
11088
    }
 
11089
 
 
11090
    return(rv == ERROR_SUCCESS);
 
11091
}
 
11092
 
 
11093
 
 
11094
/*
 
11095
 * Fundamental registry access function that sets particular values.
 
11096
 */
 
11097
LOCAL BOOL
 
11098
MSWRPoke(HKEY hKey, LPTSTR subkey, LPTSTR valstr, LPTSTR data_lptstr)
 
11099
{
 
11100
    DWORD  dtype, dwDisp, dlen = MSWR_DATA_MAX;
 
11101
    BYTE   olddata[MSWR_DATA_MAX];
 
11102
    BOOL   rv = FALSE;
 
11103
 
 
11104
    if(!subkey
 
11105
       || RegCreateKeyEx(hKey, subkey,
 
11106
                         0, TEXT("REG_SZ"), REG_OPTION_NON_VOLATILE,
 
11107
                         KEY_ALL_ACCESS, NULL,
 
11108
                         &hKey, &dwDisp) == ERROR_SUCCESS){
 
11109
 
 
11110
        if(RegQueryValueEx(hKey, valstr, NULL, &dtype,
 
11111
                           olddata, &dlen) != ERROR_SUCCESS
 
11112
           || _tcscmp((LPTSTR)olddata, data_lptstr)){
 
11113
            (void) RegDeleteValue(hKey, valstr);
 
11114
            rv = RegSetValueEx(hKey, valstr, 0, REG_SZ,
 
11115
                               (LPBYTE)data_lptstr,
 
11116
                               (DWORD)(_tcslen(data_lptstr) + 1)*sizeof(TCHAR)) == ERROR_SUCCESS;
 
11117
        }
 
11118
 
 
11119
        if(subkey)
 
11120
          RegCloseKey(hKey);
 
11121
    }
 
11122
 
 
11123
    return(rv);
 
11124
}
 
11125
 
 
11126
 
 
11127
 
 
11128
/*
 
11129
 * Fundamental registry access function that removes a registry key
 
11130
 * and all its subkeys, their values and data
 
11131
 */
 
11132
LOCAL int
 
11133
MSWRClear(HKEY hKey, LPTSTR pSubKey)
 
11134
{
 
11135
    HKEY        hSubKey;
 
11136
    TCHAR       KeyBuf[MSWR_KEY_MAX+1];
 
11137
    DWORD       dwKeyIndex, dwKeyLen;
 
11138
    FILETIME    ftKeyTime;
 
11139
    int         rv = 0;
 
11140
 
 
11141
    if(RegOpenKeyEx(hKey, pSubKey, 0,
 
11142
                    KEY_READ, &hSubKey) == ERROR_SUCCESS){
 
11143
      RegCloseKey(hSubKey);
 
11144
        if(RegOpenKeyEx(hKey, pSubKey, 0,
 
11145
                        KEY_ALL_ACCESS, &hSubKey) == ERROR_SUCCESS){
 
11146
            for(dwKeyIndex = 0L, dwKeyLen = MSWR_KEY_MAX + 1;
 
11147
                RegEnumKeyEx(hSubKey, dwKeyIndex, KeyBuf, &dwKeyLen,
 
11148
                             NULL, NULL, NULL, &ftKeyTime) == ERROR_SUCCESS;
 
11149
                dwKeyLen = MSWR_KEY_MAX + 1)
 
11150
                if(MSWRClear(hSubKey, KeyBuf)!= 0){
 
11151
                    rv = -1;
 
11152
                    dwKeyIndex++;
 
11153
                }
 
11154
            RegCloseKey(hSubKey);
 
11155
            if(RegDeleteKey(hKey, pSubKey) != ERROR_SUCCESS || rv)
 
11156
              return -1;
 
11157
            return 0;
 
11158
        }
 
11159
        return -1;
 
11160
    }
 
11161
    return 0;
 
11162
}
 
11163
 
 
11164
 
 
11165
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
11166
 *
 
11167
 *                  Text display Windows.
 
11168
 *
 
11169
 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
 
11170
 
 
11171
/*
 
11172
 * Show a help message.
 
11173
 * Help text comes as a null terminated array of pointers to lines of
 
11174
 * text.  Stuff these into a buffer and pass that to MessageBox.
 
11175
 */
 
11176
void
 
11177
mswin_showhelpmsg(WINHAND wnd, char **helplines)
 
11178
{
 
11179
    char      **l;
 
11180
    char       *helptext_utf8, *p;
 
11181
    size_t      buflen;
 
11182
    HWND        hWnd;
 
11183
    LPTSTR      helptext_lpt;
 
11184
 
 
11185
    hWnd = (HWND) wnd;
 
11186
    if(hWnd == NULL)
 
11187
      hWnd = ghTTYWnd;
 
11188
 
 
11189
    buflen = 0;
 
11190
    for(l = helplines; *l != NULL; ++l)
 
11191
      buflen += (strlen(*l)+1);
 
11192
 
 
11193
    helptext_utf8 = (char *) fs_get((buflen + 1) * sizeof(char));
 
11194
    if(helptext_utf8 == NULL)
 
11195
      return;
 
11196
 
 
11197
    *helptext_utf8 = '\0';
 
11198
 
 
11199
    p = helptext_utf8;
 
11200
    for(l = helplines; *l != NULL; ++l){
 
11201
        snprintf(p, buflen+1-(p-helptext_utf8), "%s%s", (p == helptext_utf8) ? "" : " ", *l);
 
11202
        p += strlen(p);
 
11203
    }
 
11204
 
 
11205
    helptext_lpt = utf8_to_lptstr(helptext_utf8);
 
11206
 
 
11207
    MessageBox(hWnd, helptext_lpt, TEXT("Help"),
 
11208
               MB_APPLMODAL | MB_ICONINFORMATION | MB_OK);
 
11209
 
 
11210
    fs_give((void **) &helptext_utf8);
 
11211
    fs_give((void **) &helptext_lpt);
 
11212
}
 
11213
 
 
11214
/*
 
11215
 * Callback for when new mail or imap telem window gets canned.
 
11216
 */
 
11217
LOCAL void
 
11218
mswin_tw_close_imap_telem_or_new_mail(MSWIN_TEXTWINDOW *mswin_tw)
 
11219
{
 
11220
    HMENU hMenu;
 
11221
 
 
11222
    if((mswin_tw->id == IDM_OPT_IMAPTELEM) && gIMAPDebugOFFCallback)
 
11223
        (*gIMAPDebugOFFCallback)();
 
11224
 
 
11225
    if(hMenu = GetMenu(ghTTYWnd))
 
11226
        CheckMenuItem (hMenu, mswin_tw->id, MF_BYCOMMAND | MF_UNCHECKED);
 
11227
}
 
11228
 
 
11229
/*
 
11230
 * Callback for when new mail or imap telem window gets cleared.
 
11231
 */
 
11232
LOCAL void
 
11233
mswin_tw_clear_imap_telem_or_new_mail(MSWIN_TEXTWINDOW *mswin_tw)
 
11234
{
 
11235
    char *tmtxt;
 
11236
    time_t now = time((time_t *)0);
 
11237
    LPCTSTR desc = (mswin_tw->id == IDM_OPT_IMAPTELEM) ?
 
11238
                TEXT("IMAP telemetry recorder") :
 
11239
                TEXT("New Mail window");
 
11240
 
 
11241
    tmtxt = ctime(&now);
 
11242
 
 
11243
    mswin_tw_printf(mswin_tw, TEXT("%s started at %.*S"),
 
11244
        desc, MIN(100, strlen(tmtxt)-1), tmtxt);
 
11245
 
 
11246
    if(mswin_tw->id == IDM_OPT_NEWMAILWIN)
 
11247
    {
 
11248
        int i;
 
11249
        int fromlen, subjlen, foldlen, len;
 
11250
        TCHAR ring2[256];
 
11251
 
 
11252
        foldlen = (int)(.18 * gNMW_width);
 
11253
        foldlen = foldlen > 5 ? foldlen : 5;
 
11254
        fromlen = (int)(.28 * gNMW_width);
 
11255
        subjlen = gNMW_width - 2 - foldlen - fromlen;
 
11256
 
 
11257
        mswin_tw_printf(mswin_tw,
 
11258
           TEXT("  %-*s%-*s%-*s"),
 
11259
           fromlen, TEXT("From:"),
 
11260
           subjlen, TEXT("Subject:"),
 
11261
           foldlen, TEXT("Folder:"));
 
11262
 
 
11263
        len = 2 + fromlen + subjlen + foldlen;
 
11264
        if(len >= ARRAYSIZE(ring2) + 1)
 
11265
            len = ARRAYSIZE(ring2) - 2;
 
11266
        for(i = 0; i < len; i++)
 
11267
            ring2[i] = '-';
 
11268
        ring2[i] = '\0';
 
11269
        mswin_tw_puts_lptstr(mswin_tw, ring2);
 
11270
    }
 
11271
}
 
11272
 
 
11273
/*
 
11274
 * Init new mail or imap telem window
 
11275
 */
 
11276
LOCAL int
 
11277
mswin_tw_init(MSWIN_TEXTWINDOW *mswin_tw, int id, LPCTSTR title)
 
11278
{
 
11279
    if(mswin_tw->hwnd){
 
11280
        /* destroy it */
 
11281
        mswin_tw_close(mswin_tw);
 
11282
    }
 
11283
    else{
 
11284
        HMENU hMenu;
 
11285
 
 
11286
        mswin_tw->id = id;
 
11287
        mswin_tw->hInstance = ghInstance;
 
11288
        mswin_tw->print_callback = mswin_tw_print_callback;
 
11289
        mswin_tw->close_callback = mswin_tw_close_imap_telem_or_new_mail;
 
11290
        mswin_tw->clear_callback = mswin_tw_clear_imap_telem_or_new_mail;
 
11291
 
 
11292
        // If the rcSize rect is empty, then init it to something resembling
 
11293
        //   the size of the current Pine window. Otherwise we just re-use
 
11294
        //   whatever the last position/size was.
 
11295
        if(IsRectEmpty(&mswin_tw->rcSize))
 
11296
        {
 
11297
            RECT cliRect;
 
11298
            RECT sizeRect;
 
11299
 
 
11300
            GetClientRect(ghTTYWnd, &cliRect);
 
11301
            sizeRect.left = CW_USEDEFAULT;
 
11302
            sizeRect.top = CW_USEDEFAULT;
 
11303
            sizeRect.right = cliRect.right;
 
11304
            sizeRect.bottom = cliRect.bottom;
 
11305
            mswin_tw->rcSize = sizeRect;
 
11306
        }
 
11307
 
 
11308
        if(!mswin_tw_create(mswin_tw, title))
 
11309
            return 1;
 
11310
 
 
11311
        mswin_tw_setfont(mswin_tw, gpTTYInfo->hTTYFont);
 
11312
        mswin_tw_setcolor(mswin_tw, gpTTYInfo->rgbFGColor, gpTTYInfo->rgbBGColor);
 
11313
 
 
11314
        mswin_tw_clear(mswin_tw);
 
11315
 
 
11316
        if(id == IDM_OPT_IMAPTELEM)
 
11317
        {
 
11318
            if(gIMAPDebugONCallback)
 
11319
              (*gIMAPDebugONCallback)();
 
11320
 
 
11321
            mswin_tw_showwindow(mswin_tw, SW_SHOWNA);
 
11322
        }
 
11323
        else if(id == IDM_OPT_NEWMAILWIN){
 
11324
            mswin_tw_showwindow(mswin_tw, SW_SHOW);
 
11325
        }
 
11326
 
 
11327
        if(hMenu = GetMenu(ghTTYWnd))
 
11328
            CheckMenuItem (hMenu, mswin_tw->id, MF_BYCOMMAND | MF_CHECKED);
 
11329
    }
 
11330
 
 
11331
    return(0);
 
11332
}
 
11333
 
 
11334
/*
 
11335
 * Display text in a window.
 
11336
 *
 
11337
 * Parameters:
 
11338
 *      title           - Title of window.
 
11339
 *      pText           - address of text to display.
 
11340
 *      textLen         - Length of text, in bytes.  Limited to 64K.
 
11341
 *      pLines          - Array of pointers to lines of text.  Each
 
11342
 *                        line is a sepreate allocation block.  The
 
11343
 *                        entry in the array of pointers should be a
 
11344
 *                        NULL.
 
11345
 *                      
 
11346
 * The text can be supplied as a buffer (pText and textLen) in which
 
11347
 * lines are terminated by CRLF (including the last line in buffer).
 
11348
 * This buffer should be NULL terminated, too.
 
11349
 * Or it can be supplied as a NULL terminated array of pointers to
 
11350
 * lines.  Each entry points to a separately allocated memory block
 
11351
 * containing a null terminated string.
 
11352
 *
 
11353
 * If the function succeeds the memory containing the text will be
 
11354
 * used until the user closes the window, at which point it will be
 
11355
 * freed.
 
11356
 *
 
11357
 * Returns:
 
11358
 *      mswin_tw  - SUCCESS
 
11359
 *      NULL      - Failed.
 
11360
 */
 
11361
MSWIN_TEXTWINDOW *
 
11362
mswin_displaytext(char *title_utf8, char *pText_utf8, size_t npText,
 
11363
                  char **pLines_utf8, MSWIN_TEXTWINDOW *mswin_tw, int flags)
 
11364
{
 
11365
    LPTSTR  title_lpt = NULL, pText_lpt = NULL, *pLines_lpt = NULL;
 
11366
    char  **l;
 
11367
    size_t  pText_lpt_len = 0;
 
11368
    int     i, count = 0;
 
11369
 
 
11370
    if(pLines_utf8 != NULL){
 
11371
        for(count=0, l = pLines_utf8; *l != NULL; ++l)
 
11372
          ++count;
 
11373
 
 
11374
        pLines_lpt = (LPTSTR *) fs_get((count + 1) * sizeof(LPTSTR));
 
11375
        memset(pLines_lpt, 0, (count + 1) * sizeof(LPTSTR));
 
11376
        for(i=0, l = pLines_utf8; *l != NULL && i < count; ++l, ++i)
 
11377
          pLines_lpt[i] = utf8_to_lptstr(*l);
 
11378
 
 
11379
        /*caller expects this to be freed */
 
11380
        if(!(flags & MSWIN_DT_NODELETE)){
 
11381
            for(l = pLines_utf8; *l != NULL; ++l)
 
11382
              fs_give((void **) l);
 
11383
 
 
11384
            fs_give((void **) &pLines_utf8);
 
11385
        }
 
11386
    }
 
11387
 
 
11388
    if(pText_utf8 != NULL && npText > 0){
 
11389
        pText_lpt = utf8_to_lptstr(pText_utf8);
 
11390
        pText_lpt_len = lstrlen(pText_lpt);
 
11391
 
 
11392
        /*caller expects this to be freed */
 
11393
        if(!(flags & MSWIN_DT_NODELETE))
 
11394
          fs_give((void **) &pText_utf8);
 
11395
    }
 
11396
 
 
11397
    if(title_utf8 != NULL)
 
11398
      title_lpt = utf8_to_lptstr(title_utf8);
 
11399
 
 
11400
    mswin_tw = mswin_tw_displaytext_lptstr(title_lpt, pText_lpt, pText_lpt_len,
 
11401
                                           pLines_lpt, mswin_tw, flags);
 
11402
 
 
11403
    if(pLines_lpt != NULL){
 
11404
        for(i=0; i < count; ++i)
 
11405
            if(pLines_lpt[i])
 
11406
                fs_give((void **) &pLines_lpt[i]);
 
11407
 
 
11408
            fs_give((void **) &pLines_lpt);
 
11409
        }
 
11410
 
 
11411
    if(pText_lpt != NULL)
 
11412
        fs_give((void **) &pText_lpt);
 
11413
 
 
11414
    if(title_lpt != NULL)
 
11415
      fs_give((void **) &title_lpt);
 
11416
 
 
11417
    return(mswin_tw);
 
11418
}
 
11419
 
 
11420
/*
 
11421
 * Callback for when a generic mswin_tw gets killed.
 
11422
 */
 
11423
LOCAL void
 
11424
mswin_tw_close_callback(MSWIN_TEXTWINDOW *mswin_tw)
 
11425
{
 
11426
    if(mswin_tw->id != -1)
 
11427
        MemFree(mswin_tw);
 
11428
}
 
11429
 
 
11430
/*
 
11431
 * Create a new mswin_tw window. If the MSWIN_DT_USEALTWINDOW flag is set,
 
11432
 *      then (re)use gMswinAltWin.
 
11433
 */
 
11434
LOCAL MSWIN_TEXTWINDOW *
 
11435
mswin_tw_displaytext_lptstr (LPTSTR title, LPTSTR pText, size_t textLen, LPTSTR *pLines,
 
11436
        MSWIN_TEXTWINDOW *mswin_tw, int flags)
 
11437
{
 
11438
    if (pText == NULL && pLines == NULL)
 
11439
        return (NULL);
 
11440
 
 
11441
    /* Was a valid existing window supplied? */
 
11442
    if(!mswin_tw)
 
11443
    {
 
11444
        int ctrl_down = GetKeyState(VK_CONTROL) < 0;
 
11445
 
 
11446
        if((flags & MSWIN_DT_USEALTWINDOW) && !ctrl_down)
 
11447
        {
 
11448
            mswin_tw = &gMswinAltWin;
 
11449
            mswin_tw->id = (UINT)-1;  // Tell mswin_tw_close_callback not
 
11450
                                      //  to free this buffer.
 
11451
        }
 
11452
        else
 
11453
        {
 
11454
            mswin_tw = (MSWIN_TEXTWINDOW *)MemAlloc (sizeof (MSWIN_TEXTWINDOW));
 
11455
            if(!mswin_tw)
 
11456
                return NULL;
 
11457
 
 
11458
            memset(mswin_tw, 0, sizeof(MSWIN_TEXTWINDOW));
 
11459
            mswin_tw->id = 0;
 
11460
        }
 
11461
 
 
11462
        mswin_tw->hInstance = ghInstance;
 
11463
        mswin_tw->print_callback = mswin_tw_print_callback;
 
11464
        mswin_tw->close_callback = mswin_tw_close_callback;
 
11465
        mswin_tw->clear_callback = NULL;
 
11466
    }
 
11467
 
 
11468
    /* Create a new window. */
 
11469
    if (!mswin_tw->hwnd) {
 
11470
 
 
11471
        if(IsRectEmpty(&mswin_tw->rcSize))
 
11472
        {
 
11473
            RECT sizeRect;
 
11474
            RECT cliRect;
 
11475
 
 
11476
            GetClientRect(ghTTYWnd, &cliRect);
 
11477
            sizeRect.left = CW_USEDEFAULT;
 
11478
            sizeRect.top = CW_USEDEFAULT;
 
11479
            sizeRect.right = cliRect.right;
 
11480
            sizeRect.bottom = cliRect.bottom;
 
11481
            mswin_tw->rcSize = sizeRect;
 
11482
        }
 
11483
 
 
11484
        if(!mswin_tw_create(mswin_tw, title)) {
 
11485
            MemFree (mswin_tw);
 
11486
            return (NULL);
 
11487
        }
 
11488
 
 
11489
        mswin_tw_setfont(mswin_tw, gpTTYInfo->hTTYFont);
 
11490
        mswin_tw_setcolor(mswin_tw, gpTTYInfo->rgbFGColor, gpTTYInfo->rgbBGColor);
 
11491
    }
 
11492
    else {
 
11493
        /* Invalidate whole window, change title, and move to top. */
 
11494
        SetWindowText (mswin_tw->hwnd, title);
 
11495
        SetWindowPos (mswin_tw->hwnd, HWND_TOP, 0, 0, 0, 0, SWP_NOMOVE | SWP_NOSIZE);
 
11496
    }
 
11497
 
 
11498
    mswin_tw_clear(mswin_tw);
 
11499
 
 
11500
    /*
 
11501
     * How was text supplied?
 
11502
     */
 
11503
    if (pLines != NULL) {
 
11504
        LPTSTR *l;
 
11505
 
 
11506
        /* Array of pointers to lines supplied. Count lines. */
 
11507
        for (l = pLines; *l != NULL; ++l){
 
11508
            mswin_tw_puts_lptstr(mswin_tw, *l);
 
11509
        }
 
11510
    }
 
11511
    else {
 
11512
        /* Pointer to block of text supplied. */
 
11513
        mswin_tw_puts_lptstr(mswin_tw, pText);
 
11514
    }
 
11515
 
 
11516
    mswin_tw_setsel(mswin_tw, 0, 0);
 
11517
 
 
11518
    mswin_tw_showwindow(mswin_tw, SW_SHOW);
 
11519
    return mswin_tw;
 
11520
}
 
11521
 
 
11522
void
 
11523
mswin_enableimaptelemetry(int state)
 
11524
{
 
11525
    HMENU               hMenu;
 
11526
    MENUITEMINFO        mitem;
 
11527
    TCHAR               buf[256];
 
11528
    int                 i;
 
11529
 
 
11530
    hMenu = GetMenu (ghTTYWnd);
 
11531
    if (hMenu == NULL)
 
11532
        return;
 
11533
 
 
11534
    /*
 
11535
     * Make sure hMenu's the right menubar
 
11536
     */
 
11537
    mitem.cbSize = sizeof(MENUITEMINFO);
 
11538
    mitem.fMask = (MIIM_SUBMENU | MIIM_TYPE);
 
11539
    mitem.fType = MFT_STRING;
 
11540
    mitem.dwTypeData = buf;
 
11541
    mitem.cch = 255;
 
11542
    if(GetMenuItemCount(hMenu) == 7
 
11543
       && GetMenuItemInfo(hMenu, 5, TRUE, &mitem)){
 
11544
        if(mitem.fType == MFT_STRING
 
11545
           && !_tcscmp(mitem.dwTypeData, TEXT("&Config")))
 
11546
          hMenu = mitem.hSubMenu;
 
11547
        else
 
11548
          return;
 
11549
    }
 
11550
    else
 
11551
      return;
 
11552
 
 
11553
    i = GetMenuItemCount(hMenu);
 
11554
    if(state == TRUE && i < 10){
 
11555
        mitem.fMask = MIIM_TYPE;
 
11556
        mitem.fType = MFT_SEPARATOR;
 
11557
        InsertMenuItem (hMenu, 8, TRUE, &mitem);
 
11558
 
 
11559
        mitem.fMask = (MIIM_TYPE | MIIM_ID);
 
11560
        mitem.fType = MFT_STRING;
 
11561
        mitem.wID = IDM_OPT_IMAPTELEM;
 
11562
        mitem.dwTypeData = TEXT("&IMAP Telemetry");
 
11563
        mitem.cch = 15;
 
11564
        InsertMenuItem (hMenu, 9, TRUE, &mitem);
 
11565
 
 
11566
        DrawMenuBar (ghTTYWnd);
 
11567
    }
 
11568
    else if(state == FALSE && i == 10){
 
11569
        DeleteMenu (hMenu, 8, MF_BYPOSITION);
 
11570
        DeleteMenu (hMenu, IDM_OPT_IMAPTELEM, MF_BYCOMMAND);
 
11571
        DrawMenuBar (ghTTYWnd);
 
11572
    }
 
11573
}
 
11574
 
 
11575
int
 
11576
mswin_imaptelemetry(char *msg)
 
11577
{
 
11578
    if(gMswinIMAPTelem.hwnd){
 
11579
        LPTSTR msg_lptstr;
 
11580
        msg_lptstr = utf8_to_lptstr(msg);
 
11581
        mswin_tw_puts_lptstr(&gMswinIMAPTelem, msg_lptstr);
 
11582
        fs_give((void **) &msg_lptstr);
 
11583
        return(1);
 
11584
    }
 
11585
    return(0);
 
11586
}
 
11587
 
 
11588
 
 
11589
/*
 
11590
 * The newmail window has a format proportional to screen width.
 
11591
 * At this point, we've figured out the sizes of the fields, now
 
11592
 * we fill that field to it's desired column size.  This used to
 
11593
 * be a lot eaier when it was one char per column, but in the
 
11594
 * unicode world it's not that easy.  This code does make the
 
11595
 * assumption that ASCII characters are 1 column.
 
11596
 */
 
11597
LPTSTR
 
11598
format_newmail_string(LPTSTR orig_lptstr, int format_len)
 
11599
{
 
11600
    LPTSTR new_lptstr;
 
11601
    int i, colLen;
 
11602
 
 
11603
    new_lptstr = (LPTSTR)MemAlloc((format_len+1)*sizeof(TCHAR));
 
11604
 
 
11605
    /*
 
11606
     * Fill up string till we reach the format_len, we can backtrack
 
11607
     * if we need elipses.
 
11608
     */
 
11609
    for(i = 0, colLen = 0;
 
11610
        i < format_len && colLen < format_len && orig_lptstr && orig_lptstr[i];
 
11611
        i++){
 
11612
        new_lptstr[i] = orig_lptstr[i];
 
11613
        colLen += wcellwidth(new_lptstr[i]);
 
11614
    }
 
11615
 
 
11616
    if(colLen > format_len || (colLen == format_len && orig_lptstr[i])){
 
11617
        /*
 
11618
         * If we hit the edge of the format and there's still stuff
 
11619
         * to write, go back and add ".."
 
11620
         */
 
11621
        i--;
 
11622
        if(wcellwidth(new_lptstr[i]) > 1){
 
11623
            colLen -= wcellwidth(new_lptstr[i]);
 
11624
        }
 
11625
        else{
 
11626
            colLen -= wcellwidth(new_lptstr[i]);
 
11627
            i--;
 
11628
            colLen -= wcellwidth(new_lptstr[i]);
 
11629
        }
 
11630
        while(colLen < format_len && i < format_len){
 
11631
            new_lptstr[i++] = '.';
 
11632
            colLen++;
 
11633
        }
 
11634
    }
 
11635
    else{
 
11636
        /*
 
11637
         * If we've hit the end of the string, add spaces until
 
11638
         * we get to the correct length.
 
11639
         */
 
11640
        for(; colLen < format_len && i < format_len; i++, colLen++){
 
11641
            new_lptstr[i] = ' ';
 
11642
        }
 
11643
    }
 
11644
 
 
11645
    if(i <= format_len)
 
11646
      new_lptstr[i] = '\0';
 
11647
    else
 
11648
      new_lptstr[format_len] = '\0';
 
11649
 
 
11650
    return(new_lptstr);
 
11651
}
 
11652
 
 
11653
/*
 
11654
 * We're passed the relevant fields, now format them according to window with
 
11655
 * and put up for display
 
11656
 */
 
11657
int
 
11658
mswin_newmailwin(int is_us, char *from_utf8, char *subject_utf8, char *folder_utf8)
 
11659
{
 
11660
    TCHAR tcbuf[256];
 
11661
    int foldlen, fromlen, subjlen;
 
11662
    LPTSTR from_lptstr = NULL, subject_lptstr = NULL, folder_lptstr = NULL;
 
11663
    LPTSTR from_format, subject_format, folder_format;
 
11664
 
 
11665
    if(!gMswinNewMailWin.hwnd)
 
11666
        return 0;
 
11667
 
 
11668
    if(from_utf8)
 
11669
      from_lptstr = utf8_to_lptstr(from_utf8);
 
11670
    if(subject_utf8)
 
11671
      subject_lptstr = utf8_to_lptstr(subject_utf8);
 
11672
    if(folder_utf8)
 
11673
      folder_lptstr = utf8_to_lptstr(folder_utf8);
 
11674
 
 
11675
 
 
11676
    foldlen = (int)(.18 * gNMW_width);
 
11677
    foldlen = foldlen > 5 ? foldlen : 5;
 
11678
    fromlen = (int)(.28 * gNMW_width);
 
11679
    subjlen = gNMW_width - 2 - foldlen - fromlen;
 
11680
 
 
11681
 
 
11682
    from_format = format_newmail_string(from_lptstr
 
11683
                                         ? from_lptstr : TEXT(""),
 
11684
                                         fromlen - 1);
 
11685
    subject_format = format_newmail_string(subject_lptstr
 
11686
                                            ? subject_lptstr : TEXT("(no subject)"),
 
11687
                                            subjlen - 1);
 
11688
    folder_format = format_newmail_string(folder_lptstr
 
11689
                                           ? folder_lptstr : TEXT("INBOX"),
 
11690
                                           foldlen);
 
11691
 
 
11692
    _sntprintf(tcbuf, 256, TEXT("%c %s %s %s"), is_us ? '+' : ' ',
 
11693
               from_format, subject_format, folder_format);
 
11694
 
 
11695
    if(from_lptstr)
 
11696
      fs_give((void **) &from_lptstr);
 
11697
    if(subject_lptstr)
 
11698
      fs_give((void **) &subject_lptstr);
 
11699
    if(folder_lptstr)
 
11700
      fs_give((void **) &folder_lptstr);
 
11701
    MemFree((void *)from_format);
 
11702
    MemFree((void *)subject_format);
 
11703
    MemFree((void *)folder_format);
 
11704
 
 
11705
    mswin_tw_puts_lptstr(&gMswinNewMailWin, tcbuf);
 
11706
    return 1;
 
11707
}
 
11708
 
 
11709
/*
 
11710
 * Mouse up, end selection
 
11711
 */
 
11712
 
 
11713
LOCAL void
 
11714
mswin_tw_print_callback(MSWIN_TEXTWINDOW *mswin_tw)
 
11715
{
 
11716
    LPTSTR              text;
 
11717
    UINT                text_len;
 
11718
    int                 rc;
 
11719
#define DESC_LEN        180
 
11720
    TCHAR               description[DESC_LEN+1];
 
11721
 
 
11722
    GetWindowText(mswin_tw->hwnd, description, DESC_LEN);
 
11723
 
 
11724
    rc = mswin_print_ready((WINHAND)mswin_tw->hwnd, description);
 
11725
    if (rc != 0) {
 
11726
        if (rc != PE_USER_CANCEL) {
 
11727
            LPTSTR e;
 
11728
 
 
11729
            e = utf8_to_lptstr(mswin_print_error(rc));
 
11730
            if(e){
 
11731
                _sntprintf(description, DESC_LEN+1, TEXT("Printing failed:  %s"), e);
 
11732
                fs_give((void **) &e);
 
11733
            }
 
11734
 
 
11735
            MessageBox(mswin_tw->hwnd, description, TEXT("Print Failed"),
 
11736
                MB_OK | MB_ICONEXCLAMATION);
 
11737
        }
 
11738
        return;
 
11739
    }
 
11740
 
 
11741
    text_len = mswin_tw_gettextlength(mswin_tw);
 
11742
    text = (LPTSTR) fs_get(text_len * sizeof(TCHAR));
 
11743
    mswin_tw_gettext(mswin_tw, text, text_len);
 
11744
    mswin_print_text(text);
 
11745
    fs_give((void **)&text);
 
11746
 
 
11747
    mswin_print_done();
 
11748
}
 
11749
                
 
11750
 
 
11751
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
11752
 *
 
11753
 *                  Character Queue
 
11754
 *
 
11755
 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
 
11756
 
 
11757
 
 
11758
typedef struct {
 
11759
        WORD    flags;
 
11760
        UCS     c;   /* Bigger than TCHAR for CTRL and MENU setting */
 
11761
} CQEntry;
 
11762
 
 
11763
LOCAL CQEntry CQBuffer [CHARACTER_QUEUE_LENGTH];
 
11764
LOCAL int CQHead;
 
11765
LOCAL int CQTail;
 
11766
LOCAL int CQCount;
 
11767
 
 
11768
 
 
11769
/*---------------------------------------------------------------------------
 
11770
 *  BOOL  CQInit ()
 
11771
 *
 
11772
 *  Description:
 
11773
 *              Initialize the Character queue.
 
11774
 *
 
11775
 *  Parameters:
 
11776
 *
 
11777
 *
 
11778
/*--------------------------------------------------------------------------*/
 
11779
LOCAL void
 
11780
CQInit (void)
 
11781
{
 
11782
        CQHead = 0;
 
11783
        CQTail = 0;
 
11784
        CQCount = 0;
 
11785
}
 
11786
 
 
11787
 
 
11788
/*---------------------------------------------------------------------------
 
11789
 *  BOOL  CQAvailable (void)
 
11790
 *
 
11791
 *  Description:
 
11792
 *              Return TRUE if there are characters in the queue.
 
11793
 *
 
11794
 *  Parameters:
 
11795
 *
 
11796
 *
 
11797
/*--------------------------------------------------------------------------*/
 
11798
 
 
11799
LOCAL BOOL
 
11800
CQAvailable (void)
 
11801
{
 
11802
        return (CQCount > 0);
 
11803
}
 
11804
 
 
11805
 
 
11806
 
 
11807
/*---------------------------------------------------------------------------
 
11808
 *  BOOL  CQAdd (WORD c, DWORC keyData)
 
11809
 *
 
11810
 *  Description:
 
11811
 *              Add 'c' to the end of the character queue.
 
11812
 *
 
11813
 *  Parameters:
 
11814
 *              return true if successfull.
 
11815
 *
 
11816
/*--------------------------------------------------------------------------*/
 
11817
 
 
11818
LOCAL BOOL
 
11819
CQAdd (UCS c, DWORD keyData)
 
11820
{
 
11821
        if (CQCount == CHARACTER_QUEUE_LENGTH)
 
11822
                return (FALSE);
 
11823
        
 
11824
        
 
11825
        CQBuffer[CQTail].flags = 0;
 
11826
        if ((keyData & 0x80000000) == 0)
 
11827
            CQBuffer[CQTail].flags |= CQ_FLAG_DOWN;
 
11828
        if (keyData & 0x01000000)
 
11829
            CQBuffer[CQTail].flags |= CQ_FLAG_EXTENDED;
 
11830
        if (keyData & 0x20000000)
 
11831
            CQBuffer[CQTail].flags |= CQ_FLAG_ALT;
 
11832
        CQBuffer[CQTail].c = c;
 
11833
        CQTail = (CQTail + 1) % CHARACTER_QUEUE_LENGTH;
 
11834
        ++CQCount;
 
11835
        return (TRUE);
 
11836
}
 
11837
 
 
11838
 
 
11839
 
 
11840
/*---------------------------------------------------------------------------
 
11841
 *  BOOL  CQAddUniq (WORD c, DWORC keyData)
 
11842
 *
 
11843
 *  Description:
 
11844
 *              Add 'c' to the end of the character queue, only if
 
11845
 *              there is no other 'c' in the queue
 
11846
 *
 
11847
 *  Parameters:
 
11848
 *              return true if successfull.
 
11849
 *
 
11850
/*--------------------------------------------------------------------------*/
 
11851
 
 
11852
LOCAL BOOL
 
11853
CQAddUniq (UCS c, DWORD keyData)
 
11854
{
 
11855
        int             i;
 
11856
        int             pos;
 
11857
        
 
11858
        if (CQCount == CHARACTER_QUEUE_LENGTH)
 
11859
                return (FALSE);
 
11860
        
 
11861
        pos = CQHead;
 
11862
        for (i = 0; i < CQCount; ++i) {
 
11863
            if (CQBuffer[pos].c == c)
 
11864
                return (FALSE);
 
11865
            pos = (pos + 1) % CHARACTER_QUEUE_LENGTH;
 
11866
        }
 
11867
        return (CQAdd (c, keyData));
 
11868
}
 
11869
 
 
11870
 
 
11871
 
 
11872
 
 
11873
/*---------------------------------------------------------------------------
 
11874
 *  int  CQGet ()
 
11875
 *
 
11876
 *  Description:
 
11877
 *              Return the next byte from the head of the queue.  If there is
 
11878
 *              no byte available, returns 0, which is indistinquishable from
 
11879
 *              '\0'.  So it is a good idea to call CQAvailable first.
 
11880
 *
 
11881
 *  Parameters:
 
11882
 *              none.
 
11883
 *
 
11884
/*--------------------------------------------------------------------------*/
 
11885
 
 
11886
LOCAL UCS
 
11887
CQGet ()
 
11888
{
 
11889
    UCS c;
 
11890
 
 
11891
    if (CQCount == 0)
 
11892
        return (0);
 
11893
 
 
11894
    c = CQBuffer[CQHead].c;
 
11895
    CQHead = (CQHead + 1) % CHARACTER_QUEUE_LENGTH;
 
11896
    --CQCount;
 
11897
    return (c);
 
11898
}
 
11899
 
 
11900
 
 
11901
 
 
11902
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
11903
 *
 
11904
 *                  Mouse Event Queue
 
11905
 *
 
11906
 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
 
11907
 
 
11908
 
 
11909
 
 
11910
LOCAL MEvent MQBuffer [MOUSE_QUEUE_LENGTH];
 
11911
LOCAL int MQHead;
 
11912
LOCAL int MQTail;
 
11913
LOCAL int MQCount;
 
11914
 
 
11915
 
 
11916
/*---------------------------------------------------------------------------
 
11917
 *  BOOL  MQInit ()
 
11918
 *
 
11919
 *  Description:
 
11920
 *              Initialize the Character queue.
 
11921
 *
 
11922
 *  Parameters:
 
11923
 *
 
11924
 *
 
11925
/*--------------------------------------------------------------------------*/
 
11926
LOCAL void
 
11927
MQInit (void)
 
11928
{
 
11929
        MQHead = 0;
 
11930
        MQTail = 0;
 
11931
        MQCount = 0;
 
11932
}
 
11933
 
 
11934
 
 
11935
/*---------------------------------------------------------------------------
 
11936
 *  BOOL  MQAvailable (void)
 
11937
 *
 
11938
 *  Description:
 
11939
 *              Return TRUE if there are characters in the queue.
 
11940
 *
 
11941
 *  Parameters:
 
11942
 *
 
11943
 *
 
11944
/*--------------------------------------------------------------------------*/
 
11945
 
 
11946
LOCAL BOOL
 
11947
MQAvailable (void)
 
11948
{
 
11949
        return (MQCount > 0);
 
11950
}
 
11951
 
 
11952
 
 
11953
 
 
11954
/*---------------------------------------------------------------------------
 
11955
 *  BOOL  MQAdd ()
 
11956
 *
 
11957
 *  Description:
 
11958
 *              Add 'c' to the end of the character queue.
 
11959
 *
 
11960
 *  Parameters:
 
11961
 *              return true if successfull.
 
11962
 *
 
11963
/*--------------------------------------------------------------------------*/
 
11964
 
 
11965
LOCAL BOOL
 
11966
MQAdd (int mevent, int button, int nRow, int nColumn, int keys, int flags)
 
11967
{
 
11968
    int         c;
 
11969
    int         i = 0;
 
11970
    BOOL        found = FALSE;
 
11971
 
 
11972
 
 
11973
    /*
 
11974
     * Find a queue insertion point.
 
11975
     */
 
11976
    if (flags & MSWIN_MF_REPLACING) {
 
11977
        /* Search for same event on queue. */
 
11978
        for (   i = MQHead, c = MQCount;
 
11979
                c > 0;
 
11980
                i = (i + 1) % MOUSE_QUEUE_LENGTH, --c) {
 
11981
            if (MQBuffer[i].event == mevent) {
 
11982
                found = TRUE;
 
11983
                break;
 
11984
            }
 
11985
        }
 
11986
    }
 
11987
    if (!found) {
 
11988
        if (MQCount == MOUSE_QUEUE_LENGTH)
 
11989
            return (FALSE);
 
11990
        i = MQTail;
 
11991
        MQTail = (MQTail + 1) % MOUSE_QUEUE_LENGTH;
 
11992
        ++MQCount;
 
11993
    }
 
11994
 
 
11995
 
 
11996
    /*
 
11997
     * Record data.
 
11998
     */
 
11999
    MQBuffer[i].event = mevent;
 
12000
    MQBuffer[i].button = button;
 
12001
    MQBuffer[i].nRow = nRow;
 
12002
    MQBuffer[i].nColumn = nColumn;
 
12003
    MQBuffer[i].keys = keys;
 
12004
    MQBuffer[i].flags = flags;
 
12005
 
 
12006
    /*
 
12007
     * Keep record of last mouse position.
 
12008
     */
 
12009
    gMTEvent = MQBuffer[i];
 
12010
 
 
12011
    return (TRUE);
 
12012
}
 
12013
 
 
12014
 
 
12015
 
 
12016
 
 
12017
 
 
12018
/*---------------------------------------------------------------------------
 
12019
 *  BOOL  MQGet ()
 
12020
 *
 
12021
 *  Description:
 
12022
 *              Return the next byte from the head of the queue.  If there is
 
12023
 *              no byte available, returns 0, which is indistinquishable from
 
12024
 *              '\0'.  So it is a good idea to call MQAvailable first.
 
12025
 *
 
12026
 *  Parameters:
 
12027
 *              none.
 
12028
 *
 
12029
/*--------------------------------------------------------------------------*/
 
12030
 
 
12031
LOCAL BOOL
 
12032
MQGet (MEvent * pMouse)
 
12033
{
 
12034
    if (MQCount == 0)
 
12035
        return (FALSE);
 
12036
 
 
12037
 
 
12038
    *pMouse = MQBuffer[MQHead];
 
12039
    MQHead = (MQHead + 1) % MOUSE_QUEUE_LENGTH;
 
12040
    --MQCount;
 
12041
    return (TRUE);
 
12042
}
 
12043
 
 
12044
 
 
12045
 
 
12046
 
 
12047
 
 
12048
 
 
12049
DWORD
 
12050
ExplainSystemErr()
 
12051
{
 
12052
    DWORD status;
 
12053
    void *lpMsgBuf = NULL;
 
12054
    status = GetLastError();
 
12055
 
 
12056
    FormatMessage(
 
12057
        FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
 
12058
        NULL,
 
12059
        status,
 
12060
        MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
 
12061
        (LPTSTR) &lpMsgBuf, 0, NULL);
 
12062
 
 
12063
    if(lpMsgBuf){
 
12064
        char *msg;
 
12065
 
 
12066
        msg = lptstr_to_utf8(lpMsgBuf);
 
12067
        if(msg){
 
12068
            mswin_messagebox(msg, 1);
 
12069
            fs_give((void **) &msg);
 
12070
        }
 
12071
 
 
12072
        LocalFree(lpMsgBuf);
 
12073
    }
 
12074
 
 
12075
    return(status);
 
12076
}
 
12077
 
 
12078
 
 
12079
/*
 
12080
 * Called by mswin to scroll text in window in responce to the scrollbar.
 
12081
 *
 
12082
 *  Args: cmd - what type of scroll operation.
 
12083
 *      scroll_pos - paramter for operation.
 
12084
 *                      used as position for SCROLL_TO operation.
 
12085
 *
 
12086
 *  Returns: TRUE - did the scroll operation.
 
12087
 *         FALSE - was not able to do the scroll operation.
 
12088
 */
 
12089
int
 
12090
pico_scroll_callback (int cmd, long scroll_pos)
 
12091
{
 
12092
    switch (cmd) {
 
12093
    case MSWIN_KEY_SCROLLUPLINE:
 
12094
        scrollupline (0, 1);
 
12095
        break;
 
12096
 
 
12097
    case MSWIN_KEY_SCROLLDOWNLINE:
 
12098
        scrolldownline (0, 1);
 
12099
        break;
 
12100
                
 
12101
    case MSWIN_KEY_SCROLLUPPAGE:
 
12102
        backpage (0, 1);
 
12103
        break;
 
12104
        
 
12105
    case MSWIN_KEY_SCROLLDOWNPAGE:
 
12106
        forwpage (0, 1);
 
12107
        break;
 
12108
        
 
12109
    case MSWIN_KEY_SCROLLTO:
 
12110
        scrollto (0, 0);
 
12111
        break;
 
12112
    }
 
12113
 
 
12114
    update ();
 
12115
    return (TRUE);
 
12116
}
 
12117
 
 
12118
/*
 
12119
 * sleep the given number of seconds
 
12120
 */
 
12121
int
 
12122
sleep(int t)
 
12123
{
 
12124
    time_t out = (time_t)t + time((long *) 0);
 
12125
    while(out > time((long *) 0))
 
12126
      ;
 
12127
    return(0);
 
12128
}
 
12129
 
 
12130
int
 
12131
tcsucmp(LPTSTR o, LPTSTR r)
 
12132
{
 
12133
    return(o ? (r ? _tcsicmp(o, r) : 1) : (r ? -1 : 0));
 
12134
}
 
12135
 
 
12136
int
 
12137
tcsruncmp(LPTSTR o, LPTSTR r, int n)
 
12138
{
 
12139
    return(o ? (r ? _tcsnicmp(o, r, n) : 1) : (r ? -1 : 0));
 
12140
}
 
12141
 
 
12142
int
 
12143
strucmp(char *o, char *r)
 
12144
{
 
12145
    return(o ? (r ? stricmp(o, r) : 1) : (r ? -1 : 0));
 
12146
}
 
12147
 
 
12148
 
 
12149
int
 
12150
struncmp(char *o, char *r, int n)
 
12151
{
 
12152
    return(o ? (r ? strnicmp(o, r, n) : 1) : (r ? -1 : 0));
 
12153
}
 
12154
 
 
12155
 
 
12156
/*
 
12157
 * Returns screen width of len characters of lpText.
 
12158
 * The width is in character cells. That is, an ascii "A" has
 
12159
 * width 1 but a CJK character probably has width 2.
 
12160
 */
 
12161
unsigned
 
12162
scrwidth(LPTSTR lpText, int len)
 
12163
{
 
12164
    UCS ubuf[1000];
 
12165
    unsigned w;
 
12166
    int i, thislen, offset;
 
12167
 
 
12168
    offset = w = 0;
 
12169
 
 
12170
    while(len > 0){
 
12171
        thislen = MIN(len, 1000);
 
12172
        for(i = 0; i < thislen; i++)
 
12173
          ubuf[i] = lpText[offset+i];
 
12174
 
 
12175
        w += ucs4_str_width_ptr_to_ptr(&ubuf[0], &ubuf[thislen]);
 
12176
 
 
12177
        offset += thislen;
 
12178
        len -= thislen;
 
12179
    }
 
12180
 
 
12181
    return w;
 
12182
}
 
12183
 
 
12184
 
 
12185
/*
 
12186
 * Returns the index into pScreen given the row,col location
 
12187
 * on the screen, taking into account characters with widths
 
12188
 * other than 1 cell.
 
12189
 */
 
12190
long
 
12191
pscreen_offset_from_cord(int row, int col, PTTYINFO pTTYInfo)
 
12192
{
 
12193
    int offset_due_to_row, offset_due_to_col, width;
 
12194
 
 
12195
    /*
 
12196
     * Each row starts at a specific offset into pScreen.
 
12197
     */
 
12198
    offset_due_to_row = row * pTTYInfo->actNColumn;
 
12199
 
 
12200
    /*
 
12201
     * Start with col (all chars single width) and go from there.
 
12202
     * We need to find the offset that makes the string col wide.
 
12203
     * Hopefully we won't ever get a rectange that causes us to
 
12204
     * draw half characters, but in case we do we need to err on the
 
12205
     * side of too much width instead of not enough. It's a little
 
12206
     * tricky because we want to include following zero-width
 
12207
     * characters.
 
12208
     * fewer characters it would be <= desired width, one more would
 
12209
     * be greater than desired width, this one is >= desired width.
 
12210
     */
 
12211
 
 
12212
    /* first go to some offset where width is > col */
 
12213
    offset_due_to_col = col;
 
12214
    width = scrwidth(pTTYInfo->pScreen+offset_due_to_row, offset_due_to_col);
 
12215
    while(width <= col && offset_due_to_col < pTTYInfo->actNColumn-1){
 
12216
        offset_due_to_col++;
 
12217
        width = scrwidth(pTTYInfo->pScreen+offset_due_to_row, offset_due_to_col);
 
12218
    }
 
12219
 
 
12220
    /* Now back up until width is no longer > col */
 
12221
    while(width > col){
 
12222
        offset_due_to_col--;
 
12223
        width = scrwidth(pTTYInfo->pScreen+offset_due_to_row, offset_due_to_col);
 
12224
    }
 
12225
 
 
12226
    /* But, if we're now less than col, go forward one again. */
 
12227
    if(width < col && offset_due_to_col < pTTYInfo->actNColumn-1)
 
12228
      offset_due_to_col++;
 
12229
 
 
12230
    return(offset_due_to_row + offset_due_to_col);
 
12231
}
 
12232
 
 
12233
 
 
12234
/*
 
12235
 *  Returns:
 
12236
 *   1 if store pass prompt is set in the registry to on
 
12237
 *   0 if set to off
 
12238
 *   -1 if not set to anything
 
12239
 */
 
12240
int
 
12241
mswin_store_pass_prompt(void)
 
12242
{
 
12243
    /* 
 
12244
     * We shouldn't need to prompt anymore, but always return 1 
 
12245
     * just in case
 
12246
     */
 
12247
    return(1);
 
12248
}