2
* ========================================================================
3
* Copyright 2006-2007 University of Washington
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
9
* http://www.apache.org/licenses/LICENSE-2.0
11
* ========================================================================
17
#define termdef 1 /* don't define "term" external */
19
#include "../headers.h"
27
#include "../../pith/osdep/pipe.h"
28
#include "../../pith/osdep/canaccess.h"
30
#include "../../pith/charconv/filesys.h"
31
#include "../../pith/charconv/utf8.h"
35
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
39
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
45
/* For debugging, export locals so debugger can see them. */
54
* Define which debugging is desired. Generally only FDEBUG.
56
#define FDEBUG /* Standard file debugging. */
58
#undef SDEBUG /* Verbose debugging of startup and windows handling*/
59
#undef CDEBUG /* Verbose debugging of character input timeing. */
61
#undef OWN_DEBUG_FILE /* Define if we want to write to our own debug file,
65
/* Max size permitted for the screen. */
67
#define MAXNCOLUMN NLINE
69
#define MINNROW 10 /* Minimum screen size */
72
#define MARGINE_LEFT 3
75
#define FRAME_3D_SIZE 1
77
#define WIN_MIN_X_SIZE 190 /* Minimum window size. */
78
#define WIN_MIN_Y_SIZE 180
80
#define WIN_X_BORDER_SIZE 8 /* Space taked by window frame. */
81
#define WIN_Y_BORDER_SIZE 65
83
#define FONT_MIN_SIZE 5
84
#define FONT_MAX_SIZE 21
86
#define PRINT_TAB_SIZE 8 /* Tab size used by print code. */
89
#define TB_HEIGHT 32 /* Tool Bar Height. */
90
#define TB_BUTTONHEIGHT 16 /* Button Height. */
91
#define TB_BUTTONSPACING 8 /* Space between buttons. */
94
/* Some string lengths. */
95
#define MAXLEN_TEMPSTR 256 /* Max size for temp storage. */
97
#define WIN_POS_STR_MAX_LEN 20 /* Max length for window-position
100
#define MENU_ITEM_NAME_LEN 32 /* Menu item name lengths. */
103
/* Length of keyboard input queue. */
104
#define CHARACTER_QUEUE_LENGTH 32
105
#define MOUSE_QUEUE_LENGTH 32
107
/* Number of resize callback functions we can keep track of. */
108
#define RESIZE_CALLBACK_ARRAY_SIZE 3
110
/* Number of bytes held in the write accumulator. */
111
#define WRITE_ACCUM_SIZE 200
113
/* Max time that may pass between calls to GetMessage. See mswin_charavail()
115
#define GM_MAX_TIME 3000 /* In milliseconds.*/
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.
126
#define MY_TIMER_SHORT_PERIOD (UINT)5000 /* used when there is a task in
128
#define MY_TIMER_VERY_SHORT_PERIOD (UINT)500 /* used when SIGALRM and alarm()
130
#define MY_TIMER_EXCEEDINGLY_SHORT_PERIOD (UINT)80 /* used when
131
gAllowMouseTracking is set */
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.")
136
* Task bar notification Icon id and call back message for it.
138
#define TASKBAR_ICON_NEWMAIL 1
139
#define TASKBAR_ICON_MESSAGE WM_USER+1000
143
* Below here are fixed constancs that really should not be changed.
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
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
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
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. */
174
* Different applications that we know about.
176
#define APP_UNKNOWN 0
178
#define APP_PICO_IDENT TEXT("pico")
180
#define APP_PINE_IDENT TEXT("pine")
183
* Control values for call to AccelCtl.
185
/*#undef 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. */
192
* flag bits to control which edit menu options can get lit
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
203
#define EM_MAX_ACCEL 6
205
/* Offsets to objects in window extra storage. */
206
#define GWL_PTTYINFO 0 /* Offset in Window extra storage. */
211
#define FONT_CHARSET_FONT DEFAULT_CHARSET
213
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
217
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
219
/* Type that the screen array is made up of. */
220
#define CHAR unsigned char
222
/* define possible caret shapes */
230
/* Type that the attribute array is made up of. */
231
typedef struct _character_attribute {
236
typedef int (*ResizeCallBackProc)();
237
typedef int (*FileDropCallBackProc)();
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
244
/* Struct that defines command menu entries. */
245
typedef struct tagMenuItem {
253
/* List of child window IDs and previous window procedures. */
254
typedef struct tagBtnList {
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];
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. */
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
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
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? */
313
BtnList *toolBarBtns;
316
BOOL menuItemsCurrent;
318
BOOL scrollRangeChanged;
321
short menuItemsIndex;
322
MenuItem menuItems[KS_COUNT];
323
} TTYINFO, *PTTYINFO ;
326
#define MAXCLEN (MAX(MAXCOLORLEN,RGBLEN+1))
327
typedef struct MSWINColor {
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.
345
* hTask == NULL means "This program" and can be used to arrange for
346
* deletion of files when this program exits.
348
typedef struct ontask {
351
char path[PATH_MAX+1];
354
typedef void (__cdecl *SignalType)(int);
356
typedef struct _iconlist {
358
/* char path[PATH_MAX]; */
362
struct _iconlist *next;
366
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
368
* Forward function declarations.
370
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
373
MyGetWindowLongPtr(HWND hwnd, int nIndex)
375
return (void *)(LONG_PTR)GetWindowLongPtr(hwnd, nIndex);
379
MySetWindowLongPtr(HWND hwnd, int nIndex, void *NewLongPtr)
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);
390
#define GET_HINST( hWnd ) ((HINSTANCE) MyGetWindowLongPtr( hWnd, GWLP_HINSTANCE ))
391
#define GET_ID( hWnd ) (LOWORD(MyGetWindowLongPtr( hWnd, GWLP_ID )))
393
#define GET_HINST( hWnd ) ((HINSTANCE) GetWindowWord( hWnd, GWW_HINSTANCE ))
394
#define GET_ID( hWnd ) ((WORD) GetWindowWord( hWnd, GWW_ID ))
397
#define CONSTRAIN(v,min,max) ((v) = (v) < (min) ? (min) : (v) > (max) ? (max) : (v))
400
/* function prototypes (private) */
401
int app_main (int argc, char *argv[]);
405
LOCAL BOOL InitApplication (HANDLE);
406
LOCAL HWND InitInstance (HANDLE, int);
407
LOCAL void MakeArgv (HINSTANCE hInstance, LPSTR cmdLine, int *pargc,
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);
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);
429
LOCAL void MouseWheelTTY (HWND hWnd, int xPos, int yPos,
430
int fwKeys, int zDelta);
431
LOCAL void MouseWheelMultiplier ();
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);
448
LOCAL VOID GoModalDialogBoxParam (HINSTANCE, LPTSTR, HWND,
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);
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);
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);
470
/* defined in region.c */
471
int copyregion(int f, int n);
475
#ifdef ACCELERATORS_OPT
476
LOCAL void AccelCtl (HWND hWnd, int ctl, BOOL saveChange);
478
LOCAL void AccelManage (HWND hWnd, long accels);
479
LOCAL void UpdateAccelerators (HWND hWnd);
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);
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);
495
LOCAL void UpdateTrayIcon(DWORD dwMsg, HICON hIcon, LPTSTR tip);
497
LOCAL void FlushWriteAccum (void);
499
LOCAL int mswin_reg_lptstr(int, int, LPTSTR, size_t);
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);
510
LOCAL void MSWIconAddList(int row, int id, HICON hIcon);
511
LOCAL int MSWIconPaint(int row, HDC hDC);
512
LOCAL void MSWIconFree(IconList **ppIcon);
515
/* ... interface routines ... */
518
void ProcessMenuItem (HWND hWnd, WPARAM wParam);
520
void AlarmDeliver (void);
521
void HUPDeliver (void);
523
void PrintFontSameAs (HWND hWnd);
524
void PrintFontSelect (HWND hWnd);
525
void ExtractFontInfo(LOGFONT *pFont,
526
LPTSTR fontName, size_t nfontName,
528
LPTSTR fontStyle, size_t nfontStyle,
530
LPTSTR fontCharSet, size_t nfontCharSet);
532
LOCAL void DidResize (PTTYINFO pTTYInfo);
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);
545
LOCAL void MSWHelpShow (cbstr_t);
546
LOCAL int MSWHelpSetMenu (HMENU hmenu);
549
LOCAL void SortHandler (int order, int reverse);
550
LOCAL void FlagHandler (int order, int reverse);
552
LOCAL void MyTimerSet (void);
554
LOCAL LRESULT ConfirmExit (void);
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);
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);
569
LOCAL int MapVKtoMS (WORD c, WORD flags);
571
LOCAL DWORD ExplainSystemErr(void);
573
LOCAL void RestoreMouseCursor();
575
LOCAL BYTE mswin_string2charsetid(LPTSTR);
576
LOCAL int mswin_charsetid2string (LPTSTR fontCharSet,
577
size_t nfontCharSet, BYTE lfCharSet);
579
LOCAL int mswin_tw_init(MSWIN_TEXTWINDOW *mswin_tw, int id,
581
LOCAL MSWIN_TEXTWINDOW *mswin_tw_displaytext_lptstr (LPTSTR, LPTSTR, size_t,
582
LPTSTR *, MSWIN_TEXTWINDOW *mswin_tw,
584
LOCAL void mswin_tw_print_callback(MSWIN_TEXTWINDOW *mswin_tw);
587
/* Functions exported to MS Windows. */
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);
595
LOCAL HDDEDATA CALLBACK DdeCallback(UINT uType, UINT uFmt, HCONV hconv,
596
HSZ hsz1, HSZ hsz2, HDDEDATA hdata,
597
DWORD dwData1, DWORD dwData2);
599
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
603
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
608
HINSTANCE ghInstance;
610
FILE *mswin_debugfile = NULL;
612
TCHAR gszAppName[45];
614
LOCAL TCHAR TempBuf [MAXLEN_TEMPSTR];
616
LOCAL TCHAR gszTTYClass[] = TEXT("PineWnd");
617
LOCAL int gAppIdent = APP_UNKNOWN;
619
LOCAL int gNMW_width;
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;
627
LOCAL HWND ghSplashWnd = NULL;
629
LOCAL COLOR_PAIR *the_rev_color, *the_normal_color;
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;
653
LOCAL BOOL gAllowCopy = FALSE;
654
LOCAL BOOL gAllowCut = FALSE;
656
LOCAL BOOL gAllowMouseTrack = FALSE;/* Upper layer interested in
658
LOCAL short gsMWMultiplier;
659
LOCAL MEvent gMTEvent;
661
LOCAL BOOL gKeyControlDown = FALSE;/* Keep track of the control
664
LOCAL cbstr_t gHelpGenCallback = NULL;
665
LOCAL BOOL gfHelpGenMenu = FALSE; /* TRUE when help menu
667
LOCAL cbstr_t gHelpCallback = NULL;
668
LOCAL BOOL gfHelpMenu = FALSE; /* TRUE when help menu
670
LOCAL char *gpCloseText;
672
LOCAL DWORD gGMLastCall = 0; /* Last time I called
674
LOCAL BOOL gConfirmExit = FALSE;
675
LOCAL HICON ghNormalIcon = NULL;
676
LOCAL HICON ghNewMailIcon = NULL;
677
LOCAL HICON ghMClosedIcon = NULL;
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;
685
LOCAL UINT gTimerCurrentPeriod = 0;
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. */
691
//=========================================================================
693
//=========================================================================
694
MSWIN_TEXTWINDOW gMswinAltWin = {0};
695
MSWIN_TEXTWINDOW gMswinNewMailWin = {0};
697
MSWIN_TEXTWINDOW gMswinIMAPTelem = {0};
698
LOCAL cbvoid_t gIMAPDebugONCallback = NULL;
699
LOCAL cbvoid_t gIMAPDebugOFFCallback = NULL;
700
LOCAL cbvoid_t gEraseCredsCallback = NULL;
702
LOCAL cbvoid_t gConfigScreenCallback = NULL;
704
LOCAL cbarg_t gMouseTrackCallback = NULL;
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
710
* (GetTickCount()/1000) */
711
LOCAL SignalType gSignalHUP = SIG_DFL;
713
LOCAL IconList *gIconList = NULL;
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.
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),
757
#define fullColorTableSize ((sizeof(MSWINColorTable) / sizeof(MSWINColorTable[0])) - 1)
758
#define visibleColorTableSize (fullColorTableSize - 8)
761
LOCAL MSWinCaret_t MSWinCaretTable[] = {
763
"ShortBlock", CaretSmallBlock,
764
"Underline", CaretHorizBar,
765
"VertBar", CaretVertBar,
770
/*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
774
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
776
/*---------------------------------------------------------------------------
777
* int PASCAL WinMain( HANDLE hInstance, HANDLE hPrevInstance,
778
* LPSTR lpszCmdLine, int nCmdShow )
781
* This is the main window loop!
784
* As documented for all WinMain() functions.
786
*--------------------------------------------------------------------------*/
788
wWinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance,
789
LPTSTR lpszCmdLine, int nCmdShow )
792
int argc, i, nosplash = 0;
795
ghInstance = hInstance;
797
if (!InitApplication( hInstance ))
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) {
805
MemDebug (mswin_debug, mswin_debugfile);
806
fprintf (mswin_debugfile, "Show window as: %d\n", nCmdShow);
807
fflush (mswin_debugfile);
811
if (NULL == (ghTTYWnd = InitInstance (hInstance, nCmdShow)))
814
/* cmdline_utf8 memory is never freed */
815
cmdline_utf8 = lptstr_to_utf8(lpszCmdLine);
817
MakeArgv (hInstance, cmdline_utf8, &argc, &argv);
819
for(i = 0; i < argc; i++)
820
if(strcmp((const char *)argv[i], "-nosplash") == 0){
824
/* Create Splash window */
826
ghSplashWnd = CreateDialog(hInstance,
827
MAKEINTRESOURCE( SPLASHDLGBOX ),
828
ghTTYWnd, (DLGPROC)SplashDlgProc);
829
ShowWindow (ghSplashWnd, SW_SHOWNORMAL);
834
app_main (argc, (char **)argv);
845
if (ghTTYWnd == NULL)
848
UpdateTrayIcon(NIM_DELETE, 0, NULL);
850
/* Destroy main window and process remaining events. */
851
DestroyWindow (ghTTYWnd);
852
while (GetMessage (&msg, NULL, 0, 0)) {
853
TranslateMessage (&msg);
854
DispatchMessage (&msg);
857
#ifdef OWN_DEBUG_FILE
858
fclose (mswin_debugfile);
860
if (gWSBlockingProc != NULL)
861
FreeProcInstance (gWSBlockingProc);
868
/*---------------------------------------------------------------------------
869
* BOOL InitApplication( HANDLE hInstance )
872
* First time initialization stuff. This registers information
873
* such as window classes.
877
* Handle to this instance of the application.
879
*--------------------------------------------------------------------------*/
881
InitApplication (HANDLE hInstance)
886
* Register tty window class.
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 ;
900
return (RegisterClass (&wndclass));
904
/*---------------------------------------------------------------------------
905
* HWND InitInstance( HANDLE hInstance, int nCmdShow )
908
* Initializes instance specific information.
915
* How do we show the window?
917
/*--------------------------------------------------------------------------*/
919
InitInstance (HANDLE hInstance, int nCmdShow)
923
SCROLLINFO scrollInfo;
926
if (mswin_debug >= 5)
927
fprintf (mswin_debugfile, "InitInstance::: entered, nCmdShow %d\n",
931
LoadString (hInstance, IDS_APPNAME, gszAppName, sizeof(gszAppName) / sizeof(TCHAR));
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);
940
scrollInfo.cbSize = sizeof(SCROLLINFO);
941
scrollInfo.fMask = SIF_DISABLENOSCROLL | SIF_PAGE | SIF_RANGE | SIF_POS;
944
scrollInfo.nPage = 1;
946
SetScrollInfo(hTTYWnd, SB_VERT, &scrollInfo, FALSE);
947
EnableScrollBar (hTTYWnd, SB_VERT, ESB_DISABLE_BOTH);
954
ghNormalIcon = LoadIcon (hInstance, MAKEINTRESOURCE (ALPINEICON));
955
ghNewMailIcon = LoadIcon (hInstance, MAKEINTRESOURCE (NEWMAILICON));
956
ghMClosedIcon = LoadIcon (hInstance, MAKEINTRESOURCE (MCLOSEDICON));
958
ghCursorArrow = LoadCursor (NULL, IDC_ARROW);
959
ghCursorBusy = LoadCursor (NULL, IDC_WAIT);
960
ghCursorIBeam = LoadCursor (NULL, IDC_IBEAM);
962
ghCursorHand = LoadCursor (NULL, IDC_HAND);
964
ghCursorHand = LoadCursor (hInstance, MAKEINTRESOURCE( PICOHAND ));
966
ghCursorCurrent = ghCursorArrow;
968
MouseWheelMultiplier();
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.
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,
985
else if (_tcscmp (appIdent, APP_PICO_IDENT) == 0)
986
gAppIdent = APP_PICO;
988
gAppIdent = APP_UNKNOWN;
995
/*---------------------------------------------------------------------------
999
* Build a standard C argc, argv pointers into the command line string.
1003
* cmdLine - Command line.
1004
* *argc - Count of words.
1005
* ***argc - Pointer to Pointer to array of pointers to
1008
*--------------------------------------------------------------------------*/
1010
MakeArgv (HINSTANCE hInstance, char *cmdLine_utf8, int *pargc, CHAR ***pargv)
1014
BOOL inWord, inQuote;
1016
#define CMD_PATH_LEN 128
1017
LPTSTR modPath_lptstr;
1021
/* Count words in cmdLine. */
1025
for (c = cmdLine_utf8; *c != '\0'; ++c) {
1027
if(*c == '"' && (*(c+1) == ' ' || *(c+1) == '\t' || *(c+1) == '\0')){
1028
inQuote = inWord = FALSE;
1032
if(inWord && (*c == ' ' || *c == '\t' || *c == '\0')){
1035
else if(!inWord && (*c != ' ' && *c != '\t')){
1044
++wordCount; /* One for program name. */
1045
argv = (CHAR **) MemAlloc (sizeof (CHAR *) * (wordCount + 1));
1049
modPath_lptstr = (LPTSTR) MemAlloc (CMD_PATH_LEN*sizeof(TCHAR));
1050
mpLen = GetModuleFileName (hInstance, modPath_lptstr, CMD_PATH_LEN);
1052
*(modPath_lptstr + mpLen) = '\0';
1053
*(argv++) = (unsigned char *)lptstr_to_utf8(modPath_lptstr);
1056
*(argv++) = (unsigned char *)"Alpine/Pico";
1058
MemFree((void *)modPath_lptstr);
1060
/* Now break up command line. */
1063
for (c = cmdLine_utf8; *c != '\0'; ++c) {
1065
if(*c == '"' && (*(c+1) == ' ' || *(c+1) == '\t' || *(c+1) == '\0')){
1066
inQuote = inWord = FALSE;
1071
if(inWord && (*c == ' ' || *c == '\t' || *c == '\0')){
1075
else if(!inWord && (*c != ' ' && *c != '\t')){
1079
*(argv++) = (unsigned char *)c+1;
1082
*(argv++) = (unsigned char *)c;
1087
*argv = NULL; /* tie off argv */
1091
/*---------------------------------------------------------------------------
1092
* LRESULT FAR PASCAL __export PWndProc( HWND hWnd, UINT uMsg,
1093
* WPARAM wParam, LPARAM lParam )
1096
* This is the TTY Window Proc. This handles ALL messages
1097
* to the tty window.
1100
* As documented for Window procedures.
1102
/*--------------------------------------------------------------------------*/
1103
LRESULT FAR PASCAL __export
1104
PWndProc (HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam)
1107
if (mswin_debug > 12) {
1108
fprintf (mswin_debugfile, "PWndProc:: uMsg = 0x%x\n", uMsg);
1109
fflush (mswin_debugfile);
1115
return (CreateTTYInfo (hWnd));
1118
switch ((WORD) wParam) {
1120
case IDM_OPT_SETFONT:
1121
SelectTTYFont (hWnd);
1124
case IDM_OPT_FONTSAMEAS:
1125
PrintFontSameAs (hWnd);
1128
case IDM_OPT_TOOLBAR:
1132
case IDM_OPT_TOOLBARPOS:
1136
case IDM_OPT_USEDIALOGS: {
1139
gfUseDialogs = !gfUseDialogs;
1140
pTTYInfo = (PTTYINFO)(LONG_PTR)MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
1142
DidResize (pTTYInfo);
1146
case IDM_OPT_ERASE_CREDENTIALS:
1147
if(gEraseCredsCallback)
1148
(*gEraseCredsCallback)();
1151
case IDM_OPT_IMAPTELEM:
1152
mswin_tw_init(&gMswinIMAPTelem, (int)LOWORD(wParam),
1153
TEXT("IMAP Telemetry"));
1154
SetFocus (ghTTYWnd);
1157
case IDM_OPT_NEWMAILWIN:
1158
mswin_tw_init(&gMswinNewMailWin, (int)LOWORD(wParam),
1159
TEXT("New Mail View"));
1160
SetFocus (ghTTYWnd);
1163
#ifdef ACCELERATORS_OPT
1164
case IDM_OPT_USEACCEL:
1165
AccelCtl (hWnd, ACCEL_TOGGLE, TRUE);
1169
case IDM_OPT_SETPRINTFONT:
1170
PrintFontSelect (hWnd);
1173
case IDM_OPT_CARETBLOCK :
1174
CaretTTY(hWnd, CaretBlock);
1177
case IDM_OPT_CARETSMALLBLOCK :
1178
CaretTTY(hWnd, CaretSmallBlock);
1181
case IDM_OPT_CARETVBAR :
1182
CaretTTY(hWnd, CaretVertBar);
1185
case IDM_OPT_CARETHBAR :
1186
CaretTTY(hWnd, CaretHorizBar);
1190
GoModalDialogBoxParam ( GET_HINST( hWnd ),
1191
MAKEINTRESOURCE( ABOUTDLGBOX ),
1193
(DLGPROC)AboutDlgProc, (LPARAM) 0 ) ;
1204
case IDM_EDIT_COPY_APPEND:
1208
case IDM_EDIT_PASTE:
1211
UpdateAccelerators (hWnd);
1215
case IDM_EDIT_CANCEL_PASTE:
1218
UpdateAccelerators (hWnd);
1222
case IDM_EDIT_SEL_ALL :
1227
MSWHelpShow (gHelpCallback);
1230
case IDM_MI_GENERALHELP:
1231
MSWHelpShow (gHelpGenCallback);
1234
case IDM_MI_WHEREIS :
1235
CQAdd (gpTTYInfo->menuItems[KS_WHEREIS - KS_RANGESTART].miKey, 0);
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);
1251
case IDM_MI_SORTREVERSE :
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);
1263
/* value falling within the menu item range are handled here. */
1264
if (wParam >= KS_RANGESTART && wParam <= KS_RANGEEND){
1265
ProcessMenuItem (hWnd, wParam);
1273
ScrollTTY (hWnd, LOWORD(wParam), HIWORD(wParam), (HWND) lParam);
1277
MouseWheelTTY (hWnd, LOWORD(lParam), HIWORD(lParam),
1278
LOWORD(wParam), (short) HIWORD(wParam));
1282
if (IsIconic (hWnd))
1283
return (DefWindowProc (hWnd, WM_ICONERASEBKGND, wParam, lParam));
1285
EraseTTY (hWnd, (HDC) wParam);
1288
case WM_QUERYDRAGICON:
1289
return ((LRESULT)ghNormalIcon);
1295
case WM_GETMINMAXINFO:
1296
GetMinMaxInfoTTY (hWnd, (MINMAXINFO __far *)lParam);
1300
SizeTTY (hWnd, (int)wParam, HIWORD(lParam), LOWORD(lParam));
1304
return(SizingTTY(hWnd, (int)wParam, (LPRECT) lParam));
1307
/* MoveTTY (hWnd, (int) LOWORD(lParam), (int) HIWORD(lParam)); */
1310
case WM_WINDOWPOSCHANGING:
1311
/* Allows us to adjust new size of window. */
1312
AboutToSizeTTY (hWnd, (WINDOWPOS FAR *) lParam);
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);
1323
SetForegroundWindow(hWnd);
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
1336
* I'm going to try to use KEYDOWN for processing just extended keys
1337
* and let CHAR handle the the rest.
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.
1344
* If the windows cursor is visible and we have keyboard input
1345
* then hide the windows cursor
1347
mswin_showcursor(FALSE);
1348
ProcessTTYCharacter (hWnd, (TCHAR)wParam, (DWORD)lParam);
1352
if (ProcessTTYKeyDown (hWnd, (TCHAR) wParam, (DWORD)lParam))
1355
return( DefWindowProc( hWnd, uMsg, wParam, lParam ) ) ;
1358
if (ProcessTTYKeyUp (hWnd, (TCHAR) wParam, (DWORD)lParam))
1360
return( DefWindowProc( hWnd, uMsg, wParam, lParam ) ) ;
1364
if (gFkeyCallback && (*gFkeyCallback)(0, 0)
1365
&& LOBYTE (wParam) == VK_F10){
1366
ProcessTTYCharacter (hWnd, (TCHAR)wParam, (DWORD)lParam);
1370
return( DefWindowProc( hWnd, uMsg, wParam, lParam ) ) ;
1373
if (gFkeyCallback && (*gFkeyCallback)(0, 0)
1374
&& LOBYTE (wParam) == VK_F10
1375
&& ProcessTTYKeyDown (hWnd, (TCHAR) wParam, (DWORD)lParam))
1378
return( DefWindowProc( hWnd, uMsg, wParam, lParam ) ) ;
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
1385
if(ProcessTTYKeyUp (hWnd, (TCHAR) wParam, (DWORD)lParam))
1388
return( DefWindowProc( hWnd, uMsg, wParam, lParam ) ) ;
1391
case WM_LBUTTONDOWN:
1392
ProcessTTYMouse (hWnd, M_EVENT_DOWN, M_BUTTON_LEFT, LOWORD (lParam),
1393
HIWORD (lParam), wParam);
1397
if (ProcessTTYMouse (hWnd, M_EVENT_UP, M_BUTTON_LEFT, LOWORD (lParam),
1398
HIWORD (lParam), wParam))
1402
case WM_MBUTTONDOWN:
1403
ProcessTTYMouse (hWnd, M_EVENT_DOWN, M_BUTTON_MIDDLE, LOWORD (lParam),
1404
HIWORD (lParam), wParam);
1408
ProcessTTYMouse (hWnd, M_EVENT_UP, M_BUTTON_MIDDLE, LOWORD (lParam),
1409
HIWORD (lParam), wParam);
1412
case WM_RBUTTONDOWN:
1413
ProcessTTYMouse (hWnd, M_EVENT_DOWN, M_BUTTON_RIGHT, LOWORD (lParam),
1414
HIWORD (lParam), wParam);
1418
ProcessTTYMouse (hWnd, M_EVENT_UP, M_BUTTON_RIGHT, LOWORD (lParam),
1419
HIWORD (lParam), wParam);
1423
ProcessTTYMouse (hWnd, M_EVENT_TRACK, 0, LOWORD (lParam),
1424
HIWORD (lParam), wParam);
1427
case WM_NCMOUSEMOVE:
1428
mswin_showcursor(TRUE);
1429
goto callDef; /* pretend it never happened */
1436
KillTTYFocus (hWnd);
1440
/* Set cursor. If in client, leave as is. Otherwise, pass to
1442
if (LOWORD(lParam) == HTCLIENT) {
1443
SetCursor (ghCursorCurrent);
1447
return( DefWindowProc( hWnd, uMsg, wParam, lParam ) ) ;
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. */
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 ());
1466
KillTimer (hWnd, MY_TIMER_ID);
1467
DestroyTTYInfo (hWnd);
1468
PostQuitMessage (0);
1473
if(ProcessTTYFileDrop((HANDLE) wParam) == TRUE)
1474
SetForegroundWindow(hWnd);
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);
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)
1496
return( DefWindowProc( hWnd, uMsg, wParam, lParam ) ) ;
1500
} /* end of PWndProc() */
1503
/*---------------------------------------------------------------------------
1504
* LRESULT NEAR CreateTTYInfo( HWND hWnd )
1507
* Creates the tty information structure and sets
1508
* menu option availability. Returns -1 if unsuccessful.
1512
* Handle to main window.
1514
*-------------------------------------------------------------------------*/
1516
CreateTTYInfo (HWND hWnd)
1524
if (mswin_debug >= 5)
1525
fprintf (mswin_debugfile, "CreateTTYInfo::: entered\n");
1528
hDC = GetDC (ghTTYWnd);
1529
ppi = GetDeviceCaps (hDC, LOGPIXELSY);
1530
ReleaseDC (ghTTYWnd, hDC);
1532
pTTYInfo = (PTTYINFO) MemAlloc (sizeof (TTYINFO));
1533
if (pTTYInfo == NULL)
1534
return ((LRESULT) - 1);
1535
gpTTYInfo = pTTYInfo;
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;
1556
pico_set_normal_color();
1557
pTTYInfo->toolBarTop = TRUE;
1558
pTTYInfo->curToolBarID = IDD_TOOLBAR;
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;
1566
/* Clear resize callback procs. */
1567
for (i = 0; i < RESIZE_CALLBACK_ARRAY_SIZE; ++i)
1568
pTTYInfo->resizer[i] = NULL;
1571
/* clear screen space */
1572
pTTYInfo->pScreen = NULL;
1573
pTTYInfo->pCellWidth = NULL;
1574
pTTYInfo->pAttrib = NULL;
1576
/* setup default font information */
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';
1593
/* set TTYInfo handle before any further message processing. */
1595
MySetWindowLongPtr (hWnd, GWL_PTTYINFO, pTTYInfo);
1597
/* reset the character information, etc. */
1599
ResetTTYFont (hWnd, pTTYInfo, &newFont);
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);
1612
/*---------------------------------------------------------------------------
1613
* BOOL NEAR DestroyTTYInfo( HWND hWnd )
1616
* Destroys block associated with TTY window handle.
1620
* handle to TTY window
1622
*-------------------------------------------------------------------------*/
1624
DestroyTTYInfo (HWND hWnd)
1628
pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
1629
if (pTTYInfo == NULL)
1633
if(pTTYInfo->hAccel){
1634
DestroyAcceleratorTable(pTTYInfo->hAccel);
1635
pTTYInfo->hAccel = NULL;
1636
pTTYInfo->fAccel = EM_NONE;
1640
if(pTTYInfo->hTBWnd != NULL)
1641
DestroyWindow (pTTYInfo->hTBWnd);
1643
if(pTTYInfo->hTBBrush != NULL)
1644
DeleteObject(pTTYInfo->hTBBrush);
1646
DeleteObject (pTTYInfo->hTTYFont);
1653
/*---------------------------------------------------------------------------
1654
* void ResizeTTYScreen( HWND hWnd, PTTYINFO pTTYInfo,
1655
* int newNrow, int newNColumn);
1658
* Resize the screen to new size, copying data.
1662
* pointer to TTY info structure
1663
* newNCo.umn, newNRow
1664
* new size of screen.
1666
/*--------------------------------------------------------------------------*/
1668
ResizeTTYScreen (HWND hWnd, PTTYINFO pTTYInfo, int newNRow, int newNColumn)
1670
CharAttrib *pNewAttrib, tmpAttrib, *pSourceAtt, *pDestAtt;
1671
TCHAR *pNewScreen, *pSource, *pDest;
1672
int *pNewCW, *pSourceCW, *pDestCW;
1679
if (newNColumn < MINNCOLUMN)
1680
newNColumn = MINNCOLUMN;
1681
if (newNRow < MINNROW)
1685
if (mswin_debug >= 5)
1686
fprintf (mswin_debugfile, "ResizeTTYScreen::: entered, new row %d, col %d\n",
1687
newNRow, newNColumn);
1692
cells = newNColumn * newNRow;
1693
pNewScreen = (TCHAR *)MemAlloc (cells * sizeof (TCHAR));
1694
if (pNewScreen == NULL)
1697
pNewCW = (int *)MemAlloc(cells * sizeof(int));
1699
MemFree((void *)pNewScreen);
1703
pNewAttrib = (CharAttrib *)MemAlloc (cells * sizeof (CharAttrib));
1704
if (pNewAttrib == NULL) {
1705
MemFree ((void *)pNewScreen);
1706
MemFree ((void *)pNewCW);
1715
for(i = 0; i < cells; i++){
1716
pNewScreen[i] = ' ';
1717
pNewCW[i] = pTTYInfo->xChar; /* xChar set yet ? */
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;
1727
* Copy old screen onto new screen.
1729
if (pTTYInfo->pScreen != NULL) {
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];
1739
pSourceCW = pTTYInfo->pCellWidth
1740
+ ((pTTYInfo->actNRow - r) * pTTYInfo->actNColumn);
1741
pDestCW = pNewCW + ((newNRow - r) * newNColumn);
1742
memcpy(pDestCW, pSourceCW, len * sizeof(int));
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));
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);
1759
pTTYInfo->nColumn = (CORD)MIN (pTTYInfo->nColumn, newNColumn);
1760
pTTYInfo->nRow = (CORD)MIN (pTTYInfo->nRow, newNRow);
1763
pTTYInfo->pScreen = pNewScreen;
1764
pTTYInfo->pCellWidth = pNewCW;
1765
pTTYInfo->pAttrib = pNewAttrib;
1766
pTTYInfo->actNColumn = newNColumn;
1767
pTTYInfo->actNRow = newNRow;
1770
/* Repaint whole screen. */
1771
pTTYInfo->screenDirty = TRUE;
1772
pTTYInfo->eraseScreen = TRUE;
1773
InvalidateRect (hWnd, NULL, FALSE);
1777
/* Pico specific. */
1778
if (term.t_nrow == 0) {
1779
term.t_nrow = (short)(newNRow - 1);
1780
term.t_ncol = (short)newNColumn;
1788
/*---------------------------------------------------------------------------
1789
* BOOL ResetTTYFont( HWND hWnd, PTTYINFO pTTYInfo, LOGFONT *newFont)
1792
* Resets the TTY character information and causes the
1793
* screen to resize to update the scroll information.
1797
* pointer to TTY info structure
1799
/*--------------------------------------------------------------------------*/
1801
ResetTTYFont (HWND hWnd, PTTYINFO pTTYInfo, LOGFONT *newFont)
1812
if (mswin_debug >= 5)
1813
fprintf (mswin_debugfile, "ResetTTYFont::: entered, curent window size X %d, Y %d\n",
1814
pTTYInfo->xSize, pTTYInfo->ySize);
1818
if (NULL == pTTYInfo)
1826
hFont = CreateFontIndirect (newFont);
1830
SelectObject (hDC, hFont);
1831
GetTextMetrics (hDC, &tm);
1832
ReleaseDC (hWnd, hDC);
1838
if (NULL != pTTYInfo->hTTYFont)
1839
DeleteObject (pTTYInfo->hTTYFont);
1840
pTTYInfo->hTTYFont = hFont;
1841
memcpy (&pTTYInfo->lfTTYFont, newFont, sizeof (LOGFONT));
1844
/* Update the char cell size. */
1845
pTTYInfo->xChar = (CORD)tm.tmAveCharWidth;
1846
pTTYInfo->yChar = (CORD)(tm.tmHeight + tm.tmExternalLeading);
1848
/* Update the current number of rows and cols. Don't allow
1849
* either to be less than zero. */
1850
newNRow = MAX (MINNROW,
1852
(pTTYInfo->ySize - pTTYInfo->toolBarSize - (2 * MARGINE_TOP))/
1854
newNColumn = MAX (MINNCOLUMN,
1855
MIN (MAXNCOLUMN, (pTTYInfo->xSize - (2 * pTTYInfo->xOffset))/
1858
newsize = newNRow != pTTYInfo->actNRow ||
1859
newNColumn != pTTYInfo->actNColumn;
1861
ResizeTTYScreen (hWnd, pTTYInfo, newNRow, newNColumn);
1863
/* Resize the caret as well. */
1864
if(pTTYInfo->fCaretOn)
1868
CaretCreateTTY (hWnd);
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);
1875
/* Always call the resize functions - even if the screen size
1876
* has not changed, the font style may have. */
1877
DidResize (pTTYInfo);
1883
/*---------------------------------------------------------------------------
1884
* BOOL EraseTTY (HWND hWnd, HDC hDC)
1887
* Erase the tty background.
1892
* handle to TTY window (as always)
1894
/*--------------------------------------------------------------------------*/
1896
EraseTTY (HWND hWnd, HDC hDC)
1902
GetClientRect (hWnd, &erect);
1903
hBrush = CreateSolidBrush (gpTTYInfo->rgbBGColor);
1904
if (hBrush != NULL) {
1905
FillRect (hDC, &erect, hBrush);
1906
DeleteObject (hBrush);
1912
/*---------------------------------------------------------------------------
1913
* BOOL PaintTTY( HWND hWnd )
1916
* Paints the rectangle determined by the paint struct of
1921
* handle to TTY window (as always)
1923
/*--------------------------------------------------------------------------*/
1925
PaintTTY (HWND hWnd)
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;
1936
HFONT hOrigFont, hOldFont = NULL, hTmpFont;
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. */
1949
if (mswin_debug >= 9)
1950
fprintf (mswin_debugfile, "PaintTTY::: entered\n");
1954
pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
1955
if (pTTYInfo == NULL)
1958
if (IsIconic (hWnd))
1961
hDC = BeginPaint (hWnd, &ps);
1964
hOrigFont = SelectObject (hDC, pTTYInfo->hTTYFont);
1965
SetTextColor (hDC, pTTYInfo->rgbFGColor);
1966
SetBkColor (hDC, pTTYInfo->rgbBGColor);
1967
SetBkMode (hDC, OPAQUE);
1969
nRow = (rect.top - pTTYInfo->yOffset) / pTTYInfo->yChar;
1970
CONSTRAIN (nRow, 0, pTTYInfo->actNRow - 1);
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));
1981
/* Erase screen if necessary. */
1982
if (pTTYInfo->eraseScreen) {
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);
1992
pTTYInfo->eraseScreen = FALSE;
1996
/* Paint an inset frame around the text region. */
1997
if (pTTYInfo->toolBarSize == 0) {
1999
erect.bottom = pTTYInfo->ySize;
2001
else if (pTTYInfo->toolBarTop) {
2002
erect.top = pTTYInfo->toolBarSize;
2003
erect.bottom = pTTYInfo->ySize;
2007
erect.bottom = pTTYInfo->ySize - pTTYInfo->toolBarSize;
2010
erect.right = pTTYInfo->xSize;
2011
FrameRect3D (hDC, &erect, FRAME_3D_SIZE, FALSE);
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;
2019
/* Paint runs of similar attributes. */
2020
col = nCol; /* Start at left. */
2022
if(col == 0 && MSWIconPaint(nRow, hDC))
2026
* col is the column on the screen, not the index
2029
while (col <= nEndCol) { /* While not past right. */
2031
/* Starting with Character at nRow, col, what is its attribute? */
2033
/* offset is an index into the array */
2034
offset = pscreen_offset_from_cord(nRow, col, pTTYInfo);
2035
pNewAttrib = pTTYInfo->pAttrib + offset;
2039
&& pNewAttrib->style == pLastAttrib->style
2040
&& pNewAttrib->rgbFG == pLastAttrib->rgbFG
2041
&& pNewAttrib->rgbBG == pLastAttrib->rgbBG)) {
2046
|| (pNewAttrib->style & CHAR_ATTR_ULINE)
2047
!= (pLastAttrib->style & CHAR_ATTR_ULINE)){
2048
if(pNewAttrib->style & CHAR_ATTR_ULINE){
2050
* Find suitable attribute font...
2052
memcpy (&tmpFont, &pTTYInfo->lfTTYFont,
2055
tmpFont.lfHeight = - pTTYInfo->yChar;
2056
tmpFont.lfWidth = - pTTYInfo->xChar;
2058
tmpFont.lfUnderline = (BYTE)((pNewAttrib->style
2060
== CHAR_ATTR_ULINE);
2062
hTmpFont = CreateFontIndirect (&tmpFont);
2064
hOldFont = SelectObject (hDC, hTmpFont);
2069
* Set new color attributes. If Reverse or Selected, then
2070
* show in reverse colors. But if neither, or both, then
2073
if(pNewAttrib->style & CHAR_ATTR_SEL){
2074
SetTextColor (hDC, pNewAttrib->rgbBG);
2075
SetBkColor (hDC, pNewAttrib->rgbFG);
2079
&& pNewAttrib->rgbFG == pLastAttrib->rgbFG)
2080
|| (pLastAttrib->style & CHAR_ATTR_SEL))
2081
SetTextColor (hDC, pNewAttrib->rgbFG);
2084
&& pNewAttrib->rgbBG == pLastAttrib->rgbBG)
2085
|| (pLastAttrib->style & CHAR_ATTR_SEL))
2086
SetBkColor (hDC, pNewAttrib->rgbBG);
2090
/* Find run of similar attributes. */
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){
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);
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);
2118
ExtTextOut (hDC, nHorzPos, nVertPos, ETO_OPAQUE | ETO_CLIPPED,
2119
&rect, (LPTSTR) (pTTYInfo->pScreen + offset),
2120
count, (int *)(pTTYInfo->pCellWidth+offset));
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));
2130
SetBkMode (hDC, old_mode);
2133
/* Move pointer to end of this span of characters. */
2134
col += scrwidth(pTTYInfo->pScreen+offset, count);
2135
pLastAttrib = pNewAttrib;
2137
if(hTmpFont != NULL){
2138
SelectObject(hDC, hOldFont);
2139
DeleteObject(hTmpFont);
2144
SelectObject (hDC, hOrigFont);
2145
EndPaint (hWnd, &ps);
2146
MoveTTYCursor (hWnd);
2147
pTTYInfo->screenDirty = FALSE;
2156
* FillRectColor is similar to PatB in toolbar.c
2158
* Code based on MFC source code, so presumably efficient.
2162
FillRectColor(HDC hDC, RECT * pRC, COLORREF color)
2164
SetBkColor(hDC, color);
2165
ExtTextOut(hDC, 0, 0, ETO_OPAQUE, pRC, NULL, 0, NULL);
2174
* pRC - pointer to rectangle
2175
* width - width for frame (usually one)
2176
* raised - TRUE for raised effect, FALSE for sunken effect
2185
* Draws a frame with a 3D effect.
2187
* If 'raised' is true, the rectangle will look raised (like
2188
* a button); otherwise, the rectangle will look sunk.
2192
FrameRect3D(HDC hdc, RECT * pRC, int width, BOOL raised)
2194
COLORREF hilite, shadow;
2197
shadow = GetSysColor(COLOR_BTNSHADOW);
2198
hilite = GetSysColor(COLOR_BTNHIGHLIGHT);
2202
rcTemp.right = rcTemp.left + width;
2203
FillRectColor(hdc, &rcTemp, raised ? hilite : shadow);
2204
rcTemp.right = pRC->right;
2206
rcTemp.bottom = rcTemp.top + width;
2207
FillRectColor(hdc, &rcTemp, raised ? hilite : shadow);
2208
rcTemp.bottom = pRC->bottom;
2210
rcTemp.left = rcTemp.right - width;
2211
FillRectColor(hdc, &rcTemp, raised ? shadow : hilite);
2212
rcTemp.left = pRC->left;
2214
rcTemp.top = rcTemp.bottom - width;
2215
FillRectColor(hdc, &rcTemp, raised ? shadow : hilite);
2219
/*---------------------------------------------------------------------------
2220
* BOOL GetMinMaxInfoTTY (HWND hWnd, (MINMAXINFO __far *)lParam)
2223
* Return the min and max size that the window can be.
2227
* handle to TTY window
2230
* Info structure that Windows would like us to fill.
2232
/*--------------------------------------------------------------------------*/
2234
GetMinMaxInfoTTY (HWND hWnd, MINMAXINFO __far *lpmmi)
2240
if (mswin_debug >= 5)
2241
fprintf (mswin_debugfile, "GetMinMaxInfoTTY::: entered\n");
2245
pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
2246
if (pTTYInfo == NULL)
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);
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);
2262
/*---------------------------------------------------------------------------
2263
* BOOL AboutToSizeTTY (HWND hWnd, WINDOWPOS *winPos)
2266
* Called just before Windows resizes our window. We can change the
2267
* values in 'winPos' to change the new size of the window.
2269
* If mswin_setwindow() was called when the window was minimized we
2270
* set the new size here.
2274
* handle to TTY window
2280
* new horizontal size
2282
/*--------------------------------------------------------------------------*/
2284
AboutToSizeTTY (HWND hWnd, WINDOWPOS *winPos)
2289
pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
2290
if (pTTYInfo == NULL)
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);
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.
2305
if (pTTYInfo->fMinimized && pTTYInfo->fDesiredSize &&
2306
(winPos->flags & (SWP_NOSIZE | SWP_NOMOVE)) == 0) {
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);
2313
pTTYInfo->fDesiredSize = FALSE;
2314
winPos->x = pTTYInfo->xDesPos;
2315
winPos->y = pTTYInfo->yDesPos;
2316
winPos->cx = pTTYInfo->xDesSize;
2317
winPos->cy = pTTYInfo->yDesSize;
2323
/*---------------------------------------------------------------------------
2324
* BOOL SizeTTY( HWND hWnd, int fwSizeType, CORD wVertSize,
2328
* Sizes TTY and sets up scrolling regions.
2332
* handle to TTY window
2338
* new horizontal size
2340
/*--------------------------------------------------------------------------*/
2342
SizeTTY (HWND hWnd, int fwSizeType, CORD wVertSize, CORD wHorzSize)
2350
if (mswin_debug >= 5)
2351
fprintf (mswin_debugfile, "SizeTTY::: entered, sizeType %d, New screen size %d, %d pixels\n",
2352
fwSizeType, wHorzSize, wVertSize);
2355
pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
2356
if (pTTYInfo == NULL)
2361
* Is the window being minimized?
2363
if (fwSizeType == SIZE_MINIMIZED) {
2364
pTTYInfo->fMinimized = TRUE;
2370
pTTYInfo->fMinimized = FALSE;
2373
pTTYInfo->ySize = (CORD) wVertSize;
2374
newNRow = MAX(MINNROW, MIN(MAXNROW,
2375
(pTTYInfo->ySize - pTTYInfo->toolBarSize - (2 * MARGINE_TOP)) /
2377
if (pTTYInfo->toolBarTop)
2378
pTTYInfo->yOffset = MARGINE_TOP + pTTYInfo->toolBarSize;
2380
pTTYInfo->yOffset = MARGINE_TOP;
2383
pTTYInfo->xSize = (CORD) wHorzSize;
2384
newNColumn = MAX(MINNCOLUMN,
2385
MIN(MAXNCOLUMN, (pTTYInfo->xSize - (2 * MARGINE_LEFT)) /
2387
pTTYInfo->xOffset = MARGINE_LEFT;
2389
if(newNRow == pTTYInfo->actNRow && newNColumn == pTTYInfo->actNColumn)
2392
ResizeTTYScreen (hWnd, pTTYInfo, newNRow, newNColumn);
2393
pTTYInfo->screenDirty = TRUE;
2394
pTTYInfo->eraseScreen = TRUE;
2395
InvalidateRect (hWnd, NULL, FALSE);
2397
if (pTTYInfo->hTBWnd) {
2398
if (pTTYInfo->toolBarTop)
2399
/* Position at top of window. */
2400
SetWindowPos (pTTYInfo->hTBWnd, HWND_TOP,
2402
wHorzSize, pTTYInfo->toolBarSize,
2403
SWP_NOZORDER | SWP_NOACTIVATE | SWP_SHOWWINDOW);
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);
2413
DidResize (pTTYInfo);
2419
/*---------------------------------------------------------------------------
2420
* BOOL SizingTTY( HWND hWnd, int fwSide, LPRECT pRect)
2423
* Snaps the drag rectangle to char width/height boundaries
2427
* handle to TTY window
2430
* edge of window being sized
2433
* screen coords of drag rectangle in and desired size on return
2435
/*--------------------------------------------------------------------------*/
2437
SizingTTY (HWND hWnd, int fwSide, LPRECT pRect)
2440
int newNRow, newNCol, xClient, yClient,
2441
xSys, ySys, xDiff, yDiff;
2443
pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
2444
if (pTTYInfo == NULL)
2447
xSys = (2 * GetSystemMetrics(SM_CXSIZEFRAME))
2448
+ GetSystemMetrics(SM_CXVSCROLL);
2449
ySys = (2 * GetSystemMetrics(SM_CYSIZEFRAME))
2450
+ GetSystemMetrics(SM_CYCAPTION)
2451
+ GetSystemMetrics(SM_CYMENU);
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;
2458
xClient = (newNCol * pTTYInfo->xChar) + (2 * MARGINE_LEFT);
2459
yClient = (newNRow * pTTYInfo->yChar) + (2 * MARGINE_TOP)
2460
+ pTTYInfo->toolBarSize;
2462
xDiff = (pRect->left + xClient + xSys) - pRect->right;
2463
yDiff = (pRect->top + yClient + ySys) - pRect->bottom;
2465
if(!(xDiff || yDiff))
2469
case WMSZ_BOTTOM : /* Bottom edge */
2470
pRect->bottom += yDiff;
2473
case WMSZ_BOTTOMLEFT : /*Bottom-left corner */
2474
pRect->bottom += yDiff;
2475
pRect->left -= xDiff;
2478
case WMSZ_BOTTOMRIGHT : /* Bottom-right corner */
2479
pRect->bottom += yDiff;
2480
pRect->right += xDiff;
2483
case WMSZ_LEFT : /* Left edge */
2484
pRect->left -= xDiff;
2487
case WMSZ_RIGHT : /* Right edge */
2488
pRect->right += xDiff;
2491
case WMSZ_TOP : /* Top edge */
2492
pRect->top -= yDiff;
2495
case WMSZ_TOPLEFT : /* Top-left corner */
2496
pRect->top -= yDiff;
2497
pRect->left -= xDiff;
2500
case WMSZ_TOPRIGHT : /* Top-right corner */
2501
pRect->top -= yDiff;
2502
pRect->right += xDiff;
2509
if(!(newNRow == pTTYInfo->actNRow && newNCol == pTTYInfo->actNColumn))
2510
SizeTTY(hWnd, SIZE_RESTORED, (CORD) yClient, (CORD) xClient);
2516
/*---------------------------------------------------------------------------
2517
* BOOL MoveTTY (HWND hWnd, int xPos, int yPos)
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.
2526
* handle to TTY window
2529
* New position of the top left corner.
2532
/*--------------------------------------------------------------------------*/
2534
MoveTTY (HWND hWnd, int xPos, int yPos)
2537
if (mswin_debug >= 5)
2538
fprintf (mswin_debugfile, "MoveTTY::: entered\n");
2541
DidResize (gpTTYInfo);
2546
/*---------------------------------------------------------------------------
2550
* Respond to a scroll message by either calling the scroll
2551
* callback or inserting a scroll character into the input
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.
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.
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.
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
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.
2591
/*--------------------------------------------------------------------------*/
2593
ScrollTTY (HWND hWnd, int wScrollCode, int nPos, HWND hScroll)
2597
long scroll_pos = 0;
2598
BOOL noAction = FALSE;
2600
FARPROC prevBlockingProc;
2604
pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
2606
if (pTTYInfo == NULL || gScrolling)
2610
if (gWSBlockingProc != NULL)
2611
prevBlockingProc = WSASetBlockingHook (gWSBlockingProc);
2616
switch (wScrollCode) {
2618
cmd = MSWIN_KEY_SCROLLTO;
2619
scroll_pos = pTTYInfo->scrollTo = 0;
2623
cmd = MSWIN_KEY_SCROLLTO;
2624
scroll_pos = pTTYInfo->scrollTo = pTTYInfo->scrollRange;
2628
cmd = MSWIN_KEY_SCROLLDOWNLINE;
2633
cmd = MSWIN_KEY_SCROLLUPLINE;
2638
cmd = MSWIN_KEY_SCROLLDOWNPAGE;
2643
cmd = MSWIN_KEY_SCROLLUPPAGE;
2648
case SB_THUMBPOSITION:
2649
cmd = MSWIN_KEY_SCROLLTO;
2650
scroll_pos = pTTYInfo->scrollTo = (long) ((float)nPos);
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.
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 ();
2677
* If no callback or callback did not do the scrolling operation,
2678
* insert a scroll cmd in the input stream.
2681
CQAddUniq ((UCS)cmd, 0);
2691
/*---------------------------------------------------------------------------
2692
* void MouseWheelTTY ()
2695
* Respond to a WM_MOUSEWHEEL event by calling scroll callback
2699
/*--------------------------------------------------------------------------*/
2701
MouseWheelTTY (HWND hWnd, int xPos, int yPos, int fwKeys, int zDelta)
2706
FARPROC prevBlockingProc;
2707
SCROLLINFO scrollInfo;
2708
static int zDelta_accumulated;
2710
pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
2712
if (pTTYInfo == NULL || gScrolling)
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))
2723
if (gWSBlockingProc != NULL)
2724
prevBlockingProc = WSASetBlockingHook (gWSBlockingProc);
2726
if(fwKeys == MK_MBUTTON)
2727
zDelta *= 2; /* double the effect! */
2729
if(abs(zDelta += zDelta_accumulated) < WHEEL_DELTA){
2730
zDelta_accumulated = zDelta;
2733
/* Remember any partial increments */
2734
zDelta_accumulated = zDelta % WHEEL_DELTA;
2736
scroll_pos = (long)(gsMWMultiplier * abs((zDelta / WHEEL_DELTA)));
2738
cmd = (zDelta < 0) ? MSWIN_KEY_SCROLLDOWNLINE : MSWIN_KEY_SCROLLUPLINE;
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 ();
2758
MouseWheelMultiplier()
2761
DWORD llen = sizeof(lines)/sizeof(TCHAR);
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;
2771
/*---------------------------------------------------------------------------
2772
* void CaretTTY (HWND hWnd, CARETS cStyle)
2775
* Adjusts the Caret to the user supplied style
2779
* handle to TTY window
2782
* New style to take on
2784
/*--------------------------------------------------------------------------*/
2786
CaretTTY (HWND hWnd, CARETS cStyle)
2790
if(pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO)){
2791
pTTYInfo->cCaretStyle = cStyle;
2792
CaretCreateTTY (hWnd);
2793
DidResize (gpTTYInfo);
2798
/*---------------------------------------------------------------------------
2799
* void CaretCreateTTY (HWND hWnd, BOOL wPosition)
2802
* Adjusts the Caret to the user supplied style
2806
* handle to TTY window
2809
* whether or not to position it too
2811
/*--------------------------------------------------------------------------*/
2813
CaretCreateTTY (HWND hWnd)
2817
if(pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO)){
2820
switch(pTTYInfo->cCaretStyle){
2821
case CaretHorizBar :
2822
x = pTTYInfo->xChar;
2823
y = pTTYInfo->yChar / 5;
2824
n = pTTYInfo->yChar - y;
2828
x = pTTYInfo->xChar / 4;
2829
y = pTTYInfo->yChar;
2832
case CaretSmallBlock :
2833
x = pTTYInfo->xChar;
2834
y = pTTYInfo->yChar / 2;
2835
n = pTTYInfo->yChar - y;
2839
x = pTTYInfo->xChar;
2840
y = pTTYInfo->yChar;
2844
CreateCaret (hWnd, NULL, x, y);
2845
pTTYInfo->yCurOffset = n;
2847
if(pTTYInfo->fCaretOn){
2849
MoveTTYCursor(hWnd);
2856
* This routine is inserted as the winsock blocking hook. It's main perpos
2857
* is to NOT dispatch messages.
2859
BOOL CALLBACK __export
2860
NoMsgsAreSent (void)
2866
/*---------------------------------------------------------------------------
2867
* BOOL SetTTYFocus( HWND hWnd )
2870
* Sets the focus to the TTY window also creates caret.
2874
* handle to TTY window
2876
/*--------------------------------------------------------------------------*/
2878
SetTTYFocus (HWND hWnd)
2883
if (mswin_debug >= 5)
2884
fprintf (mswin_debugfile, "SetTTYFocus::: entered\n");
2887
pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
2888
if (pTTYInfo == NULL)
2891
mswin_showcursor(TRUE);
2893
pTTYInfo->fFocused = TRUE;
2894
gKeyControlDown = FALSE;
2896
CaretCreateTTY (hWnd);
2898
MoveTTYCursor (hWnd);
2903
/*---------------------------------------------------------------------------
2904
* BOOL KillTTYFocus( HWND hWnd )
2907
* Kills TTY focus and destroys the caret.
2911
* handle to TTY window
2913
/*--------------------------------------------------------------------------*/
2915
KillTTYFocus (HWND hWnd)
2920
if (mswin_debug >= 5)
2921
fprintf (mswin_debugfile, "KillTTYFocus::: entered\n");
2923
pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
2924
if (pTTYInfo == NULL)
2927
mswin_showcursor(TRUE);
2929
if(pTTYInfo->fCaretOn)
2934
pTTYInfo->fFocused = FALSE;
2935
gKeyControlDown = FALSE;
2941
/*---------------------------------------------------------------------------
2942
* BOOL MoveTTYCursor( HWND hWnd )
2945
* Moves caret to current position.
2949
* handle to TTY window
2951
/*--------------------------------------------------------------------------*/
2953
MoveTTYCursor (HWND hWnd)
2957
pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
2958
if (pTTYInfo == NULL)
2961
if(pTTYInfo->fCaretOn && !pTTYInfo->fMassiveUpdate) {
2963
SetCaretPos ((pTTYInfo->nColumn * pTTYInfo->xChar) + pTTYInfo->xOffset,
2964
(pTTYInfo->nRow * pTTYInfo->yChar)
2965
+ pTTYInfo->yCurOffset + pTTYInfo->yOffset);
2973
/*---------------------------------------------------------------------------
2974
* BOOL ProcessTTYKeyDown ( HWND hWnd, WORD bOut, DWORD keyData )
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
2983
* We do watch for VK_CONTROL to keep track of it's state such
2984
* that we can implement ^_space.
2988
* handle to TTY window
2994
* Additional flags passed in lParam for WM_KEYDOWN
2996
/*--------------------------------------------------------------------------*/
2998
ProcessTTYKeyDown (HWND hWnd, TCHAR key, DWORD keyData)
3003
if (key == VK_CONTROL)
3004
gKeyControlDown = TRUE;
3007
if (keyData & 0X20000000)
3008
return (FALSE); /* Message NOT handled. */
3011
case VK_UP: myKey = MSWIN_KEY_UP; break;
3012
case VK_DOWN: myKey = MSWIN_KEY_DOWN; break;
3014
myKey = (gKeyControlDown) ? '\0': MSWIN_KEY_RIGHT;
3020
myKey = MSWIN_KEY_LEFT;
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;
3041
/* Control is special - I keep track, but do not claim to handle. */
3042
case VK_CONTROL: gKeyControlDown = TRUE;
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.
3059
if (gKeyControlDown)
3066
* Ctrl-_ is used to invoke alternate editor.
3068
if (gKeyControlDown)
3075
* Ctrl-@ (null) is used to advance to the next word.
3077
if (gKeyControlDown)
3082
default: return (FALSE); /* Message NOT handled.*/
3087
set_time_of_last_input();
3089
return (TRUE); /* Message handled .*/
3093
/*---------------------------------------------------------------------------
3094
* BOOL ProcessTTYKeyUp ( HWND hWnd, WORD bOut, DWORD keyData )
3097
* Called to process MW_KEYDOWN message.
3098
* Used only to detect when the control key goes up.
3102
* handle to TTY window
3108
* Additional flags passed in lParam for WM_KEYDOWN
3110
/*--------------------------------------------------------------------------*/
3112
ProcessTTYKeyUp (HWND hWnd, TCHAR key, DWORD keyData)
3114
if (key == VK_CONTROL)
3115
gKeyControlDown = FALSE;
3119
if (keyData & 0X20000000)
3120
return (FALSE); /* Message NOT handled. */
3123
return (FALSE); /* Message NOT handled.*/
3131
static char timestring[23];
3133
struct _timeb timebuffer;
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);
3145
/*---------------------------------------------------------------------------
3146
* BOOL ProcessTTYCharacter( HWND hWnd, WORD bOut, DWORD keyData )
3149
* Place the character into a queue.
3153
* handle to TTY window
3156
* byte from keyboard
3158
/*--------------------------------------------------------------------------*/
3160
ProcessTTYCharacter (HWND hWnd, TCHAR bOut, DWORD keyData)
3164
* Map Ctrl-space to the null character. Window's does not do
3167
if (bOut == (TCHAR)' ' && gKeyControlDown)
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.
3175
if (bOut == (TCHAR)0x1e)
3178
CQAdd ((UCS)bOut, keyData);
3181
UpdateAccelerators (hWnd);
3184
set_time_of_last_input();
3186
return (TRUE); /* Message handled. */
3190
/*---------------------------------------------------------------------------
3191
* BOOL ProcessTTYMouse(HWND hWnd, int mevent, int button,
3192
* int xPos, int yPos, WPARAM keys)
3195
* This is the central control for all mouse events. Every event
3196
* gets put into a queue to wait for the upper layer.
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.
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
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.
3219
* handle to TTY window
3222
* byte from keyboard
3224
/*--------------------------------------------------------------------------*/
3226
ProcessTTYMouse (HWND hWnd, int mevent, int button,
3227
CORD xPos, CORD yPos, WPARAM winkeys)
3234
* Convert to cell position.
3236
nColumn = (xPos - gpTTYInfo->xOffset) / gpTTYInfo->xChar;
3237
if (xPos < gpTTYInfo->xOffset)
3239
nRow = (yPos - gpTTYInfo->yOffset) / gpTTYInfo->yChar;
3240
if (yPos < gpTTYInfo->yOffset)
3244
* Convert window's keys.
3247
if (winkeys & MK_CONTROL)
3248
keys |= M_KEY_CONTROL;
3249
if (winkeys & MK_SHIFT)
3250
keys |= M_KEY_SHIFT;
3252
/* Adjust the cursor */
3253
if((unsigned long) mevent != M_EVENT_UP){
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));
3263
mswin_setcursor(MSWIN_CURSOR_ARROW);
3267
* Tracking event or mouse up/down?
3269
if ((unsigned long) mevent == M_EVENT_TRACK) {
3271
* Who is doing the tracking?
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);
3285
SelTrackMouse (nRow, nColumn);
3289
* Tracking. Only start tracking mouse down in the text region
3290
* But allow mouse up anywhere.
3292
if ( (nRow >= 0 && nRow < gpTTYInfo->actNRow &&
3293
nColumn >= 0 && nColumn < gpTTYInfo->actNColumn)
3294
|| (unsigned long) mevent == M_EVENT_UP) {
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.
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);
3309
if (!gAllowMouseTrack && button == M_BUTTON_LEFT)
3310
SelFinish (nRow, nColumn);
3311
gMouseTracking = FALSE;
3314
* If right mouse button, toss pop-up menu offering
3317
if(button == M_BUTTON_RIGHT && SelAvailable()){
3318
UINT fAllowed = (EM_CP | EM_CP_APPEND);
3323
if(CopyCutPopup(hWnd, fAllowed) == TRUE)
3324
mevent = M_EVENT_TRACK; /* don't add to input queue! */
3329
* Insert event into queue.
3331
if((unsigned long) mevent != M_EVENT_TRACK)
3332
MQAdd (mevent, button, nRow, nColumn, keys, 0);
3336
mswin_showcursor(TRUE); /* make sure it's visible */
3339
UpdateAccelerators (hWnd);
3342
set_time_of_last_input();
3344
return (0); /* Message handled. */
3348
/*---------------------------------------------------------------------------
3349
* BOOL ProcessTimer ()
3352
* Process the periodic timer calls.
3358
/*--------------------------------------------------------------------------*/
3362
/* Time to deliver an alarm signal? */
3363
if (gAlarmTimeout != 0 && GetTickCount () / 1000 > gAlarmTimeout)
3366
/* Time to make the periodic callback. */
3367
if (gPeriodicCallback != NULL &&
3368
GetTickCount() / 1000 > gPeriodicCBTimeout) {
3369
gPeriodicCBTimeout = GetTickCount() / 1000 +
3371
gPeriodicCallback ();
3375
* If tracking the mouse, insert a fake mouse tracking message
3376
* At the last know location of the mouse.
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);
3386
/*---------------------------------------------------------------------------
3387
* BOOL WriteTTYBlock( HWND hWnd, LPSTR lpBlock, int nLength )
3390
* Writes block to TTY screen. Nothing fancy - just
3395
* handle to TTY window
3398
* far pointer to block of data
3403
/*--------------------------------------------------------------------------*/
3405
WriteTTYBlock (HWND hWnd, LPTSTR lpBlock, int nLength)
3413
pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
3414
if (pTTYInfo == NULL)
3417
for (i = 0 ; i < nLength; i++) {
3418
switch (lpBlock[i]) {
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;
3430
if(pTTYInfo->nColumn > 0)
3431
pTTYInfo->nColumn = (CORD)(pTTYInfo->nColumn - width);
3433
MoveTTYCursor (hWnd);
3437
/* Carriage return */
3438
pTTYInfo->nColumn = 0 ;
3439
MoveTTYCursor (hWnd);
3440
if (!pTTYInfo->fNewLine)
3447
if (++pTTYInfo->nRow == pTTYInfo->actNRow) {
3449
/* Scroll the Screen. */
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));
3456
/* initialize new row n-1 */
3457
for(j = (pTTYInfo->actNRow - 1) * pTTYInfo->actNColumn;
3458
j < pTTYInfo->actNColumn; j++)
3459
pTTYInfo->pScreen[j] = (TCHAR) ' ';
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 ? */
3470
/* Scroll the Attributes. */
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));
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));
3482
pTTYInfo->screenDirty = TRUE;
3483
pTTYInfo->eraseScreen = TRUE;
3484
InvalidateRect (hWnd, NULL, FALSE);
3488
MoveTTYCursor (hWnd);
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) +
3498
rect.right = rect.left + pTTYInfo->xChar;
3499
rect.top = (pTTYInfo->nRow * pTTYInfo->yChar) +
3501
rect.bottom = rect.top + pTTYInfo->yChar;
3502
pTTYInfo->screenDirty = TRUE;
3503
InvalidateRect (hWnd, &rect, FALSE);
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;
3523
/*---------------------------------------------------------------------------
3524
* BOOL WriteTTYText ( HWND hWnd, LPSTR lpBlock, int nLength )
3527
* Like WriteTTYBlock but optimized for strings that are text only,
3528
* no carrage control characters.
3532
* handle to TTY window
3535
* far pointer to block of data
3540
/*--------------------------------------------------------------------------*/
3542
WriteTTYText (HWND hWnd, LPTSTR lpText, int nLength)
3547
long offset, endOffset;
3553
pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
3554
if (pTTYInfo == NULL)
3558
/* Calculate offset of cursor, end of current column, and end of screen */
3559
offset = pscreen_offset_from_cord(pTTYInfo->nRow, pTTYInfo->nColumn, pTTYInfo);
3561
colEnd = (pTTYInfo->nRow + 1) * pTTYInfo->actNColumn;
3562
screenEnd = pTTYInfo->actNRow * pTTYInfo->actNColumn;
3565
/* Text is allowed to wrap around to subsequent lines, but not past end
3567
endOffset = offset + nLength;
3568
if (endOffset >= screenEnd) {
3569
nLength = screenEnd - offset;
3570
endOffset = offset + nLength - 1; /* Last cell, not one past last */
3574
/* Calculate bounding rectangle. */
3575
if (endOffset <= colEnd) {
3578
screenwidth = scrwidth(lpText, nLength);
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);
3589
/* Wraps across multiple lines. Calculate one rect to cover all
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);
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;
3609
/* Invalidate rectangle */
3610
pTTYInfo->screenDirty = TRUE;
3611
InvalidateRect (hWnd, &rect, FALSE);
3616
/*---------------------------------------------------------------------------
3617
* BOOL WriteTTYChar (HWND hWnd, char ch)
3620
* Write a single character to the cursor position and advance the
3621
* cursor. Does not handle carage control.
3625
* handle to TTY window
3628
* character being written.
3630
/*--------------------------------------------------------------------------*/
3632
WriteTTYChar (HWND hWnd, TCHAR ch)
3639
pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
3640
if (pTTYInfo == NULL)
3643
offset = (pTTYInfo->nRow * pTTYInfo->actNColumn) +
3646
*(pTTYInfo->pScreen + offset) = ch;
3647
pTTYInfo->pCellWidth[offset] = wcellwidth((UCS)ch) * pTTYInfo->xChar;
3648
pTTYInfo->pAttrib[offset] = pTTYInfo->curAttrib;
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);
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) {
3666
pTTYInfo->nColumn = 0;
3672
/*---------------------------------------------------------------------------
3673
* VOID GoModalDialogBoxParam( HINSTANCE hInstance,
3674
* LPTSTR lpszTemplate, HWND hWnd,
3675
* DLGPROC lpDlgProc, LPARAM lParam )
3678
* It is a simple utility function that simply performs the
3679
* MPI and invokes the dialog box with a DWORD paramter.
3682
* similar to that of DialogBoxParam() with the exception
3683
* that the lpDlgProc is not a procedure instance
3685
/*--------------------------------------------------------------------------*/
3687
GoModalDialogBoxParam( HINSTANCE hInstance, LPTSTR lpszTemplate,
3688
HWND hWnd, DLGPROC lpDlgProc, LPARAM lParam )
3690
DLGPROC lpProcInstance ;
3692
lpProcInstance = (DLGPROC) MakeProcInstance( (FARPROC) lpDlgProc,
3694
DialogBoxParam( hInstance, lpszTemplate, hWnd, lpProcInstance, lParam ) ;
3695
FreeProcInstance( (FARPROC) lpProcInstance ) ;
3699
/*---------------------------------------------------------------------------
3700
* BOOL FAR PASCAL __export AboutDlgProc( HWND hDlg, UINT uMsg,
3701
* WPARAM wParam, LPARAM lParam )
3704
* Simulates the Windows System Dialog Box.
3707
* Same as standard dialog procedures.
3709
/*--------------------------------------------------------------------------*/
3710
BOOL FAR PASCAL __export
3711
AboutDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
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);
3729
LoadString (GET_HINST (hDlg), IDS_BYLINE, TempBuf,
3730
sizeof(TempBuf) / sizeof(TCHAR));
3731
SetDlgItemText (hDlg, IDD_BYLINE, TempBuf);
3737
EndDialog( hDlg, TRUE ) ;
3741
switch((WORD) wParam){
3743
EndDialog( hDlg, TRUE ) ;
3754
} /* end of AboutDlgProc() */
3757
/*---------------------------------------------------------------------------
3760
* Simulates the Windows System Dialog Box.
3763
* Same as standard dialog procedures.
3765
/*--------------------------------------------------------------------------*/
3766
BOOL FAR PASCAL __export
3767
SplashDlgProc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
3769
static HBITMAP hbmpSplash;
3773
if(hbmpSplash = LoadBitmap(GET_HINST(hDlg),
3774
MAKEINTRESOURCE(ALPINESPLASH))){
3778
cx = GetSystemMetrics(SM_CXSCREEN);
3779
cy = GetSystemMetrics(SM_CYSCREEN);
3780
GetObject(hbmpSplash, sizeof(BITMAP), &stBitmap);
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 */);
3791
case WM_CTLCOLORDLG :
3794
case WM_ERASEBKGND :
3801
if((hMemDC = CreateCompatibleDC((HDC) wParam)) != NULL){
3802
hObject = SelectObject(hMemDC, hbmpSplash);
3803
SetMapMode(hMemDC, GetMapMode((HDC) wParam));
3805
GetObject(hbmpSplash, sizeof(BITMAP), &stBitmap);
3806
stPoint.x = stBitmap.bmWidth;
3807
stPoint.y = stBitmap.bmHeight;
3808
DPtoLP((HDC) wParam, &stPoint, 1);
3810
BitBlt((HDC) wParam,
3811
0, 0, stPoint.x, stPoint.y,
3812
hMemDC, 0, 0, SRCCOPY);
3813
SelectObject(hMemDC, hObject);
3823
DestroyWindow(hDlg);
3828
DeleteObject(hbmpSplash);
3832
case WM_COMMAND: /* No commands! */
3833
DestroyWindow(hDlg);
3844
SelectTTYFontHook(HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
3847
case WM_INITDIALOG :
3850
* Deactivate the Style combo box...
3852
HWND hWnd = GetDlgItem(hDlg, cmb2);
3853
EnableWindow(hWnd, FALSE);
3854
SetWindowPos(hWnd, NULL, 0, 0, 0, 0, SWP_HIDEWINDOW);
3861
switch ((WORD) wParam) {
3866
SendMessage(hDlg, WM_CHOOSEFONT_GETLOGFONT,
3867
0, (LPARAM) &curfont);
3868
ResetTTYFont (ghTTYWnd, gpTTYInfo, &curfont);
3889
/*---------------------------------------------------------------------------
3890
* BOOL SelectTTYFont( HWND hDlg )
3893
* Selects the current font for the TTY screen.
3894
* Uses the Common Dialog ChooseFont() API.
3898
* handle to settings dialog
3900
/*--------------------------------------------------------------------------*/
3902
SelectTTYFont (HWND hWnd)
3904
CHOOSEFONT cfTTYFont;
3905
LOGFONT newFont, origFont;
3908
pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
3909
if (pTTYInfo == NULL)
3912
memcpy (&newFont, &gpTTYInfo->lfTTYFont, sizeof (LOGFONT));
3913
memcpy (&origFont, &gpTTYInfo->lfTTYFont, sizeof (LOGFONT));
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 |
3923
CF_FORCEFONTEXIST | CF_LIMITSIZE |
3924
CF_ENABLEHOOK | CF_APPLY;
3926
CF_FORCEFONTEXIST | CF_LIMITSIZE;
3928
cfTTYFont.nSizeMin = FONT_MIN_SIZE;
3929
cfTTYFont.nSizeMax = FONT_MAX_SIZE;
3930
cfTTYFont.lCustData = (long) 0 ;
3932
cfTTYFont.lpfnHook = SelectTTYFontHook ;
3934
cfTTYFont.lpfnHook = NULL;
3936
cfTTYFont.lpTemplateName = NULL ;
3937
cfTTYFont.hInstance = GET_HINST (hWnd);
3941
if (ChooseFont (&cfTTYFont)) {
3942
pTTYInfo->rgbFGColor = cfTTYFont.rgbColors;
3943
ResetTTYFont (hWnd, pTTYInfo, &newFont);
3947
ResetTTYFont (hWnd, pTTYInfo, &origFont);
3956
* Set a specific color (forground, background, reverse, normal) to
3957
* the color specified by name.
3960
SetColorAttribute (COLORREF *cf, char *colorName)
3962
/* color name not in table. Try converting RGB string. */
3963
ConvertRGBString (colorName, cf);
3965
/* Redraw screen. */
3966
gpTTYInfo->screenDirty = TRUE;
3967
gpTTYInfo->eraseScreen = TRUE;
3968
InvalidateRect (ghTTYWnd, NULL, FALSE);
3973
* Set current color attribute to reverse color
3979
gpTTYInfo->curAttrib.rgbFG = gpTTYInfo->rgbRFGColor;
3980
gpTTYInfo->curAttrib.rgbBG = gpTTYInfo->rgbRBGColor;
3985
* Convert a string to an integer.
3988
ScanInt (char *str, int min, int max, int *val)
3995
if (str == NULL) return (FALSE);
3996
if (*str == '\0' || strlen (str) > 9) return (FALSE);
3998
/* Check for a negative sign. */
4004
/* Check for all digits. */
4005
for (c = str; *c != '\0'; ++c) {
4006
if (!isdigit((unsigned char)*c))
4010
/* Convert from ascii to int. */
4011
v = atoi (str) * neg;
4013
/* Check constraints. */
4014
if (v < min || v > max)
4022
* Convert a RGB string to a color ref. The string should look like:
4024
* where rrr, ggg, and bbb are numbers between 0 and 255 that represent
4025
* red, gree, and blue values. Must be comma seperated.
4027
* TRUE - Successfully converted string.
4028
* FALSE - Bad format, 'cf' unchanged.
4031
ConvertRGBString (char *colorName, COLORREF *cf)
4033
int i, j, n, rgb[3];
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))){
4046
/* Not a named color, try RRR,GGG,BBB */
4047
for(i = 0; i < 3; i++){
4048
if(i && *colorName++ != ',')
4051
for(rgb[i] = 0, j = 0; j < 3; j++)
4052
if((n = *colorName++ - '0') < 0 || n > 9)
4055
rgb[i] = (rgb[i] * 10) + n;
4058
*cf = RGB (rgb[0], rgb[1], rgb[2]);
4064
ConvertStringRGB(char *colorName, size_t ncolorName, COLORREF colorRef)
4068
for(cf = MSWINColorTable;
4069
cf->colorName && cf->colorRef != colorRef;
4074
strncpy(colorName, cf->colorName, ncolorName);
4075
colorName[ncolorName-1] = '\0';
4078
snprintf(colorName, ncolorName, "%.3d,%.3d,%.3d",
4079
GetRValue(colorRef), GetGValue(colorRef), GetBValue(colorRef));
4086
* Map from integer color value to canonical color name.
4092
static char cbuf[RGBLEN+1];
4094
if(color < fullColorTableSize){
4095
ct = &MSWINColorTable[color];
4096
if(ct->canonicalName)
4097
return(ct->canonicalName);
4100
/* not supposed to get here */
4101
snprintf(cbuf, sizeof(cbuf), "color%03.3d", color);
4107
* Argument is a color name which could be an RGB string, a name like "blue",
4108
* or a name like "color011".
4110
* Returns a pointer to the canonical name of the color.
4113
color_to_canonical_name(char *s)
4115
int i, j, n, rgb[3];
4118
static char cn[RGBLEN+1];
4123
for(ct = MSWINColorTable; ct->colorName; ct++)
4124
if(!struncmp(ct->colorName, s, (int)strlen(ct->colorName)))
4128
return(ct->canonicalName);
4130
/* maybe it is RGB? */
4131
for(i = 0; i < 3; i++){
4132
if(i && *s++ != ',')
4135
for(rgb[i] = 0, j = 0; j < 3; j++)
4136
if((n = *s++ - '0') < 0 || n > 9)
4139
rgb[i] = (rgb[i] * 10) + n;
4142
cr = RGB(rgb[0], rgb[1], rgb[2]);
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.
4148
for(ct = MSWINColorTable; ct->colorName; ct++)
4149
if(ct->colorRef == cr)
4153
return(ct->canonicalName);
4155
snprintf(cn, sizeof(cn), "%.3d,%.3d,%.3d",
4156
GetRValue(cr), GetGValue(cr), GetBValue(cr));
4162
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4164
* Toolbar setup routines.
4166
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
4168
TBToggle (HWND hWnd)
4173
pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
4174
if (pTTYInfo == NULL)
4177
if (pTTYInfo->toolBarSize > 0)
4185
TBPosToggle (HWND hWnd)
4190
pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
4191
if (pTTYInfo == NULL)
4194
pTTYInfo->toolBarTop = !pTTYInfo->toolBarTop;
4195
if(pTTYInfo->hTBWnd){
4209
pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
4210
if (pTTYInfo == NULL)
4215
* Make sure the tool bar not already shown.
4217
if (pTTYInfo->toolBarSize > 0)
4223
* Make procinstance for dialog funciton.
4226
if (gToolBarProc == NULL)
4227
gToolBarProc = (DLGPROC) MakeProcInstance( (FARPROC) ToolBarProc,
4229
if (gTBBtnProc == NULL)
4230
gTBBtnProc = (WNDPROC) MakeProcInstance( (FARPROC) TBBtnProc,
4235
* Create the dialog box.
4237
pTTYInfo->hTBWnd = CreateDialog (ghInstance,
4238
MAKEINTRESOURCE (pTTYInfo->curToolBarID),
4241
if (pTTYInfo->hTBWnd == NULL) {
4250
* Adjust the window size.
4252
GetWindowRect (pTTYInfo->hTBWnd, &rc); /* Get Toolbar size. */
4253
pTTYInfo->toolBarSize = (CORD)(rc.bottom - rc.top);
4255
GetClientRect (hWnd, &rc); /* Get TTY window size. */
4256
SizeTTY (hWnd, 0, (CORD)rc.bottom, (CORD)rc.right);
4267
pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
4268
if (pTTYInfo == NULL)
4272
if (pTTYInfo->toolBarSize == 0)
4275
DestroyWindow (pTTYInfo->hTBWnd);
4276
pTTYInfo->hTBWnd = NULL;
4277
if (pTTYInfo->toolBarBtns != NULL)
4278
MemFree (pTTYInfo->toolBarBtns);
4279
pTTYInfo->toolBarBtns = NULL;
4283
* Adjust the window size.
4285
pTTYInfo->toolBarSize = 0;
4286
GetClientRect (hWnd, &rc);
4287
SizeTTY (hWnd, 0, (CORD)rc.bottom, (CORD)rc.right);
4292
TBSwap (HWND hWnd, int newID)
4297
pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
4298
if (pTTYInfo == NULL)
4301
if (pTTYInfo->toolBarSize == 0 || pTTYInfo->curToolBarID == newID)
4305
* Dispose of old tool bar window.
4309
DestroyWindow (pTTYInfo->hTBWnd);
4310
pTTYInfo->hTBWnd = NULL;
4311
if (pTTYInfo->toolBarBtns != NULL)
4312
MemFree (pTTYInfo->toolBarBtns);
4313
pTTYInfo->toolBarBtns = NULL;
4318
* Create the new dialog box.
4320
pTTYInfo->hTBWnd = CreateDialog (ghInstance,
4321
MAKEINTRESOURCE (newID),
4324
if (pTTYInfo->hTBWnd == NULL) {
4328
pTTYInfo->curToolBarID = newID;
4329
SetFocus (hWnd); /* Return focus to parent. */
4333
* Fit new tool bar into old tool bars position. This assumes that
4334
* all tool bars are about the same height.
4336
GetClientRect (hWnd, &rc); /* Get TTY window size. */
4337
if (pTTYInfo->toolBarTop)
4338
/* Position at top of window. */
4339
SetWindowPos (pTTYInfo->hTBWnd, HWND_TOP,
4341
rc.right, pTTYInfo->toolBarSize,
4342
SWP_NOZORDER | SWP_NOACTIVATE | SWP_SHOWWINDOW);
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);
4354
BOOL FAR PASCAL __export
4355
ToolBarProc (HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
4367
pTTYInfo = gpTTYInfo;
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);
4380
/* Count child windows.*/
4382
for (hCld = GetWindow (hWnd, GW_CHILD);
4384
hCld = GetWindow (hCld, GW_HWNDNEXT))
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));
4392
/* Subclass all child windows. */
4393
for (i = 0, hCld = GetWindow (hWnd, GW_CHILD);
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,
4400
MySetWindowLongPtr (hCld, GWLP_WNDPROC, (void *)(LONG_PTR)TBBtnProc);
4402
pTTYInfo->toolBarBtns[i].wndID = 0;
4403
pTTYInfo->toolBarBtns[i].wndProc = NULL;
4410
if (wParam >= KS_RANGESTART && wParam <= KS_RANGEEND){
4411
ProcessMenuItem (GetParent (hWnd), wParam);
4412
/* Set input focus back to parent. */
4413
SetFocus (GetParent (hWnd));
4420
case WM_CTLCOLORBTN:
4424
if (HIWORD (lParam) == CTLCOLOR_DLG) {
4425
if(pTTYInfo->hTBBrush != NULL){
4426
DeleteObject(pTTYInfo->hTBBrush);
4427
pTTYInfo->hTBBrush = NULL;
4430
hBrush = CreateSolidBrush (GetSysColor (COLOR_ACTIVEBORDER));
4431
return ((BOOL)!!(pTTYInfo->hTBBrush = hBrush));
4439
* Subclass toolbar button windows.
4441
* These buttons will automatically return the input focus to
4442
* the toolbar's parent
4444
LRESULT FAR PASCAL __export
4445
TBBtnProc (HWND hBtn, UINT uMsg, WPARAM wParam, LPARAM lParam)
4456
* Find previous window proc.
4458
pTTYInfo = gpTTYInfo;
4460
for (i = 0; pTTYInfo->toolBarBtns[i].wndID != 0; ++i)
4461
if (pTTYInfo->toolBarBtns[i].wndID == id)
4463
/* Whoops! Didn't find window, don't know how to pass message. */
4468
wndProc = pTTYInfo->toolBarBtns[i].wndProc;
4472
if (uMsg == WM_LBUTTONUP || uMsg == WM_MBUTTONUP || uMsg == WM_RBUTTONUP) {
4474
* On mouse button up restore input focus to IDC_RESPONCE, which
4475
* processes keyboard input.
4477
ret = CallWindowProc (wndProc, hBtn, uMsg, wParam, lParam);
4478
hPrnt = GetParent (GetParent (hBtn));
4484
return (CallWindowProc (wndProc, hBtn, uMsg, wParam, lParam));
4489
* return bitmap of allowed Edit Menu items
4492
UpdateEditAllowed(HWND hWnd)
4495
UINT fAccel = EM_NONE;
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)
4504
fAccel |= (EM_CP | EM_CP_APPEND);
4511
fAccel |= (EM_CP | EM_CP_APPEND);
4514
if (pTTYInfo->menuItems[KS_WHEREIS - KS_RANGESTART].miActive)
4522
#ifdef ACCELERATORS_OPT
4523
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4525
* Accelorator key routines.
4527
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
4529
AccelCtl (HWND hWnd, int ctl, BOOL saveChange)
4535
pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
4536
if (pTTYInfo == NULL)
4547
load = pTTYInfo->hAccel == NULL;
4555
if (load && pTTYInfo->hAccel == NULL) {
4557
pTTYInfo->hAccel = LoadAccelerators (ghInstance,
4558
MAKEINTRESOURCE (IDR_ACCEL_PINE));
4561
else if(!load && pTTYInfo->hAccel) {
4563
FreeResource (pTTYInfo->hAccel);
4564
pTTYInfo->hAccel = NULL;
4568
if (changed && saveChange)
4569
DidResize (pTTYInfo);
4574
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4576
* Accelorator key routines.
4578
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
4580
AccelManage (HWND hWnd, long accels)
4583
ACCEL accelarray[EM_MAX_ACCEL];
4585
static ACCEL am_cp = {
4586
FVIRTKEY | FCONTROL | FSHIFT | FNOINVERT, 'C', IDM_EDIT_COPY
4588
static ACCEL am_cp_append = {
4589
FVIRTKEY | FCONTROL | FALT | FNOINVERT, 'C', IDM_EDIT_COPY_APPEND
4591
static ACCEL am_find = {
4592
FVIRTKEY | FCONTROL | FSHIFT | FNOINVERT, 'F', IDM_MI_WHEREIS
4594
static ACCEL am_pst = {
4595
FVIRTKEY | FCONTROL | FSHIFT | FNOINVERT, 'V', IDM_EDIT_PASTE
4597
static ACCEL am_pst_abort = {
4598
FVIRTKEY | FCONTROL | FALT | FNOINVERT, 'V', IDM_EDIT_CANCEL_PASTE
4600
static ACCEL am_cut = {
4601
FVIRTKEY | FCONTROL | FSHIFT | FNOINVERT, 'X', IDM_EDIT_CUT
4604
pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
4605
if (pTTYInfo == NULL || pTTYInfo->fAccel == (UINT)accels)
4608
if(pTTYInfo->hAccel){
4609
DestroyAcceleratorTable(pTTYInfo->hAccel);
4610
pTTYInfo->hAccel = NULL;
4611
pTTYInfo->fAccel = EM_NONE;
4617
accelarray[n++] = am_cp;
4619
if(accels & EM_CP_APPEND)
4620
accelarray[n++] = am_cp_append;
4622
if(accels & EM_FIND)
4623
accelarray[n++] = am_find;
4626
accelarray[n++] = am_pst;
4628
if(accels & EM_PST_ABORT)
4629
accelarray[n++] = am_pst_abort;
4632
accelarray[n++] = am_cut;
4635
if(n && (pTTYInfo->hAccel = CreateAcceleratorTable(accelarray, n)))
4636
pTTYInfo->fAccel = accels;
4638
pTTYInfo->fAccel = EM_NONE;
4643
UpdateAccelerators (HWND hWnd)
4645
AccelManage (hWnd, UpdateEditAllowed(hWnd));
4650
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4652
* Mouse Selection routines
4654
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
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;
4669
SelRSet (int oStart, int oEnd)
4673
for (pca = gpTTYInfo->pAttrib + oStart; oStart < oEnd; ++pca, ++oStart)
4674
pca->style |= CHAR_ATTR_SEL;
4679
SelRClear (int oStart, int oEnd)
4683
for (pca = gpTTYInfo->pAttrib + oStart; oStart < oEnd; ++pca, ++oStart)
4684
pca->style &= ~CHAR_ATTR_SEL;
4689
SelRInvalidate (int oStart, int oEnd)
4695
sRow = oStart / gpTTYInfo->actNColumn;
4696
sCol = oStart % gpTTYInfo->actNColumn;
4697
eRow = oEnd / gpTTYInfo->actNColumn;
4698
eCol = oEnd % gpTTYInfo->actNColumn;
4700
rect.top = (sRow * gpTTYInfo->yChar) + gpTTYInfo->yOffset;
4701
rect.bottom = ((eRow+1) * gpTTYInfo->yChar) + gpTTYInfo->yOffset;
4703
rect.left = (sCol * gpTTYInfo->xChar) + gpTTYInfo->xOffset;
4704
rect.right = ((eCol+1) * gpTTYInfo->xChar) + gpTTYInfo->xOffset;
4706
rect.left = gpTTYInfo->xOffset;
4707
rect.right = (gpTTYInfo->actNColumn * gpTTYInfo->xChar) +
4710
InvalidateRect (ghTTYWnd, &rect, FALSE);
4715
* Start a mouse selection.
4718
SelStart (int nRow, int nColumn)
4723
SelPointerRow = SelAnchorRow = nRow;
4724
SelPointerCol = SelAnchorCol = nColumn;
4730
* Finish a mouse selection.
4733
SelFinish (int nRow, int nColumn)
4735
if (nRow == SelAnchorRow && nColumn == SelAnchorCol) {
4736
/* Mouse up in same place it went down - no selection. */
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;
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;
4770
/* Clear selected attribute of those cells in range. */
4772
SelRInvalidate (s, e);
4773
SelSelected = FALSE;
4774
SelTracking = FALSE;
4779
* Update the position of the mouse point.
4782
SelTrackXYMouse (int xPos, int yPos)
4787
nColumn = (xPos - gpTTYInfo->xOffset) / gpTTYInfo->xChar;
4788
nRow = (yPos - gpTTYInfo->yOffset) / gpTTYInfo->yChar;
4790
SelTrackMouse (nRow, nColumn);
4795
* Update the position of the mouse point.
4798
SelTrackMouse (int nRow, int nColumn)
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);
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;
4820
/* If previous position same as current position, do nothing. */
4824
/* there are six possible orderings of the points, each with
4825
* a different action:
4826
* order clear set redraw
4829
* p a n p - a a - n p - n
4832
* n a p a - p n - a n - p
4838
SelRInvalidate (n, p);
4841
SelRInvalidate (p, n);
4846
SelRInvalidate (p, n);
4852
SelRInvalidate (p, n);
4855
SelRInvalidate (n, p);
4860
SelRInvalidate (n, p);
4864
/* Set new pointer. */
4865
SelPointerRow = nRow;
4866
SelPointerCol = nColumn;
4873
return (SelSelected);
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.
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.
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.
4891
SelDoCopy (HANDLE hCB, DWORD lenCB)
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;
4904
if (OpenClipboard (ghTTYWnd)) { /* ...and we get the CB. */
4905
if (EmptyClipboard ()) { /* ...and clear previous CB.*/
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;
4917
sRow = SelPointerRow;
4918
sCol = SelPointerCol;
4919
eRow = SelAnchorRow;
4920
eCol = SelAnchorCol;
4923
/* Allocate a table in which we store info on rows. */
4924
rowTable = (CopyRow *) MemAlloc (sizeof (CopyRow) * (eRow-sRow+1));
4925
if (rowTable == NULL)
4928
/* Find the start and length of each row. */
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);
4936
/* Calculate pointer to beginning of this line. */
4937
rp->pRow = gpTTYInfo->pScreen +
4938
((row * gpTTYInfo->actNColumn) + c1);
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);
4950
if (*(p2-1) != (TCHAR)' ')
4957
/* Calculate size of line, then increment totalLen plus 2 for
4958
* the CRLF which will terminate each line. */
4960
totalLen += rp->len + 2;
4963
/* Reallocate the memory block. Add one byte for null terminator. */
4964
newCB = GlobalReAlloc (hCB, (lenCB + totalLen + 1)*sizeof(TCHAR), 0);
4969
pCB = GlobalLock (hCB);
4973
/* Append each of the rows, deliminated by a CRLF. */
4975
for (row = sRow, rp = rowTable; row <= eRow; ++row, ++rp) {
4977
memcpy (pCB, rp->pRow, rp->len * sizeof(TCHAR));
4980
if (row < eRow || !noLastCRLF) {
4981
*pCB++ = (TCHAR)ASCII_CR;
4982
*pCB++ = (TCHAR)ASCII_LF;
4985
*pCB = (TCHAR)'\0'; /* Null terminator. */
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. */
5001
Fail2: MemFree (rowTable);
5002
Fail1: GlobalFree (hCB);
5009
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
5011
* Upper Layer Screen routines.
5013
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
5016
* Flush the write accumulator buffer.
5019
FlushWriteAccum (void)
5021
if (gpTTYInfo->writeAccumCount > 0) {
5022
WriteTTYText (ghTTYWnd, gpTTYInfo->writeAccum,
5023
gpTTYInfo->writeAccumCount);
5024
gpTTYInfo->writeAccumCount = 0;
5030
* Set window's title
5033
mswin_settitle(char *utf8_title)
5036
LPTSTR lptstr_title;
5038
lptstr_title = utf8_to_lptstr(utf8_title);
5039
_sntprintf(buf, 256, TEXT("%.*s - Alpine"), 80, lptstr_title);
5040
fs_give((void **) &lptstr_title);
5042
SetWindowText(ghTTYWnd, buf);
5047
* Return the application instance.
5050
mswin_gethinstance ()
5052
return ((WINHAND)ghInstance);
5059
return ((WINHAND)ghTTYWnd);
5064
* destroy splash screen
5069
if(ghSplashWnd != NULL){
5070
DestroyWindow(ghSplashWnd);
5077
* Called to get mouse event.
5080
mswin_getmouseevent (MEvent * pMouse)
5082
return (MQGet (pMouse));
5087
* Make a pop-up menu and track it
5090
mswin_popup(MPopup *members)
5097
if(members && (hMenu = CreatePopupMenu())){
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 */
5111
CQAdd (mp->data.val, 0);
5115
SendMessage(ghTTYWnd, WM_COMMAND, mp->data.msg, 0);
5123
n = -1; /* error or nothing selected; same diff */
5135
PopupConfig(HMENU hMenu, MPopup *members, int *n)
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;
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);
5157
PopupConfig(mitem.hSubMenu, members->data.submenu, n);
5161
switch(members->type){
5163
mitem.fType = MFT_SEPARATOR;
5167
mitem.fMask |= MIIM_ID;
5168
mitem.wID = members->internal.id = (*n)++;
5169
switch(members->label.style){
5171
mitem.fMask |= MIIM_STATE;
5172
mitem.fState = MFS_CHECKED;
5176
mitem.fMask |= MIIM_STATE;
5177
mitem.fState = MFS_GRAYED;
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);
5193
InsertMenuItem(hMenu, index, TRUE, &mitem);
5200
PopupId(MPopup *members, int id)
5204
for(; members->type != tTail; members++)
5205
switch(members->type){
5207
if(mp = PopupId(members->data.submenu, id))
5216
if(members->internal.id == id)
5227
* Make a pop-up offering Copy/Cut/Paste menu and track it
5230
CopyCutPopup(HWND hWnd, UINT fAllowed)
5239
* If nothing to do just silently return
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");
5251
InsertMenuItem(hMenu, ++n, FALSE, &mitem);
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");
5263
InsertMenuItem(hMenu, ++n, FALSE, &mitem);
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");
5275
InsertMenuItem(hMenu, ++n, FALSE, &mitem);
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");
5287
InsertMenuItem(hMenu, ++n, FALSE, &mitem);
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");
5299
InsertMenuItem(hMenu, ++n, FALSE, &mitem);
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);
5331
* If nothing to do just silently return
5333
if(hMenu = CreatePopupMenu()){
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");
5345
InsertMenuItem(hMenu, ++n, FALSE, &mitem);
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");
5356
InsertMenuItem(hMenu, ++n, FALSE, &mitem);
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");
5367
InsertMenuItem(hMenu, ++n, FALSE, &mitem);
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;
5378
InsertMenuItem(hMenu, ++n, FALSE, &mitem);
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");
5391
InsertMenuItem(hMenu, ++n, FALSE, &mitem);
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);
5418
* If nothing to do just silently return
5420
if(hMenu = CreatePopupMenu()){
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;
5432
InsertMenuItem(hMenu, ++n, FALSE, &mitem);
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);
5448
mswin_keymenu_popup()
5450
HMENU hBarMenu, hMenu;
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...
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);
5481
if(j + KS_RANGESTART == IDM_MI_SCREENHELP
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);
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);
5517
mswin_registericon(int row, int id, char *utf8_file)
5524
/* Turn this off until it can get tuned */
5527
/* Already registered? */
5528
for(pIcon = gIconList; pIcon; pIcon = pIcon->next)
5529
if(pIcon->id == id){
5530
pIcon->row = (short)row;
5534
sPathCopy = utf8_to_lptstr(utf8_file);
5536
if(hIcon = ExtractAssociatedIcon(ghInstance, sPathCopy, &iIcon))
5537
MSWIconAddList(row, id, hIcon);
5539
fs_give((void **) &sPathCopy);
5544
mswin_destroyicons()
5546
MSWIconFree(&gIconList);
5551
MSWIconAddList(int row, int id, HICON hIcon)
5555
for(ppIcon = &gIconList; *ppIcon; ppIcon = &(*ppIcon)->next)
5558
*ppIcon = (IconList *) MemAlloc (sizeof (IconList));
5559
memset(*ppIcon, 0, sizeof(IconList));
5560
(*ppIcon)->hIcon = hIcon;
5562
(*ppIcon)->row = (short)row;
5567
MSWIconPaint(int row, HDC hDC)
5572
for(pIcon = gIconList; pIcon && pIcon->row != row; pIcon = pIcon->next)
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);
5589
MSWIconFree(IconList **ppIcon)
5591
if(ppIcon && *ppIcon){
5593
MSWIconFree(&(*ppIcon)->next);
5595
DestroyIcon((*ppIcon)->hIcon);
5603
* Set up debugging stuff.
5606
mswin_setdebug (int debug, FILE *debugfile)
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);
5618
mswin_setnewmailwidth (int width)
5621
gNMW_width = gNMW_width < 20 ? 20 : gNMW_width;
5622
gNMW_width = gNMW_width > 170 ? 170 : gNMW_width;
5627
* Event handler to deal with File Drop events
5630
ProcessTTYFileDrop (HANDLE wDrop)
5632
HDROP hDrop = wDrop;
5638
if(!gpTTYInfo->dndhandler)
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)
5646
row = (pos.y - gpTTYInfo->yOffset) / gpTTYInfo->yChar;
5647
if (pos.y < gpTTYInfo->yOffset)
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);
5659
set_time_of_last_input();
5666
* Set a callback to deal with Drag 'N Drop events
5669
mswin_setdndcallback (int (*cb)())
5671
if(gpTTYInfo->dndhandler)
5672
gpTTYInfo->dndhandler = NULL;
5675
gpTTYInfo->dndhandler = cb;
5676
DragAcceptFiles(ghTTYWnd, TRUE);
5684
* Clear previously installed callback to handle Drag 'N Drop
5688
mswin_cleardndcallback ()
5690
gpTTYInfo->dndhandler = NULL;
5691
DragAcceptFiles(ghTTYWnd, FALSE);
5697
* Set a callback for function 'ch'
5700
mswin_setresizecallback (int (*cb)())
5707
* Look through whole array for this call back function. Don't
5708
* insert duplicate. Also look for empty slot.
5711
for (i = 0; i < RESIZE_CALLBACK_ARRAY_SIZE; ++i) {
5712
if (gpTTYInfo->resizer[i] == cb)
5714
if (e == -1 && gpTTYInfo->resizer[i] == NULL)
5719
* Insert in empty slot or return an error.
5722
gpTTYInfo->resizer[e] = cb;
5730
* Clear all instances of the callback function 'cb'
5733
mswin_clearresizecallback (int (*cb)())
5739
for (i = 0; i < RESIZE_CALLBACK_ARRAY_SIZE; ++i) {
5740
if (gpTTYInfo->resizer[i] == cb) {
5741
gpTTYInfo->resizer[i] = NULL;
5750
mswin_beginupdate (void)
5752
gpTTYInfo->fMassiveUpdate = TRUE;
5757
mswin_endupdate (void)
5759
gpTTYInfo->fMassiveUpdate = FALSE;
5760
MoveTTYCursor (ghTTYWnd);
5765
mswin_charsetid2string(LPTSTR fontCharSet, size_t nfontCharSet, BYTE lfCharSet)
5771
case DEFAULT_CHARSET:
5774
_tcsncpy(buf, TEXT("ANSI_CHARSET"), sizeof(buf)/sizeof(TCHAR));
5777
_tcsncpy(buf, TEXT("OEM_CHARSET"), sizeof(buf)/sizeof(TCHAR));
5779
case BALTIC_CHARSET:
5780
_tcsncpy(buf, TEXT("BALTIC_CHARSET"), sizeof(buf)/sizeof(TCHAR));
5782
case CHINESEBIG5_CHARSET:
5783
_tcsncpy(buf, TEXT("CHINESE_CHARSET"), sizeof(buf)/sizeof(TCHAR));
5785
case EASTEUROPE_CHARSET:
5786
_tcsncpy(buf, TEXT("EASTEUROPE_CHARSET"), sizeof(buf)/sizeof(TCHAR));
5788
case GB2312_CHARSET:
5789
_tcsncpy(buf, TEXT("GF2312_CHARSET"), sizeof(buf)/sizeof(TCHAR));
5792
_tcsncpy(buf, TEXT("GREEK_CHARSET"), sizeof(buf)/sizeof(TCHAR));
5794
case HANGUL_CHARSET:
5795
_tcsncpy(buf, TEXT("HANGUL_CHARSET"), sizeof(buf)/sizeof(TCHAR));
5798
_tcsncpy(buf, TEXT("MAC_CHARSET"), sizeof(buf)/sizeof(TCHAR));
5800
case RUSSIAN_CHARSET:
5801
_tcsncpy(buf, TEXT("RUSSIAN_CHARSET"), sizeof(buf)/sizeof(TCHAR));
5803
case SHIFTJIS_CHARSET:
5804
_tcsncpy(buf, TEXT("SHIFTJIS_CHARSET"), sizeof(buf)/sizeof(TCHAR));
5806
case SYMBOL_CHARSET:
5807
_tcsncpy(buf, TEXT("SYMBOL_CHARSET"), sizeof(buf)/sizeof(TCHAR));
5809
case TURKISH_CHARSET:
5810
_tcsncpy(buf, TEXT("TURKISH_CHARSET"), sizeof(buf)/sizeof(TCHAR));
5812
case VIETNAMESE_CHARSET:
5813
_tcsncpy(buf, TEXT("VIETNAMESE_CHARSET"), sizeof(buf)/sizeof(TCHAR));
5816
_tcsncpy(buf, TEXT("JOHAB_CHARSET"), sizeof(buf)/sizeof(TCHAR));
5818
case ARABIC_CHARSET:
5819
_tcsncpy(buf, TEXT("ARABIC_CHARSET"), sizeof(buf)/sizeof(TCHAR));
5821
case HEBREW_CHARSET:
5822
_tcsncpy(buf, TEXT("HEBREW_CHARSET"), sizeof(buf)/sizeof(TCHAR));
5825
_tcsncpy(buf, TEXT("THAI_CHARSET"), sizeof(buf)/sizeof(TCHAR));
5828
/* default char set if we can't figure it out */
5832
buf[sizeof(buf)/sizeof(TCHAR) - 1] = '\0';
5834
_tcsncpy(fontCharSet, buf, nfontCharSet);
5835
fontCharSet[nfontCharSet-1] = '\0';
5842
mswin_string2charsetid(LPTSTR str)
5846
if(!str || (lstrlen(str) >= 1024))
5847
return DEFAULT_CHARSET;
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)
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)
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;
5893
return DEFAULT_CHARSET;
5897
return((BYTE)(_tstoi(str)));
5899
return DEFAULT_CHARSET;
5905
mswin_setwindow(char *fontName_utf8, char *fontSize_utf8, char *fontStyle_utf8,
5906
char *windowPosition, char *caretStyle, char *fontCharSet_utf8)
5912
RECT wndRect, cliRect;
5916
BOOL toolBar = FALSE;
5917
BOOL toolBarTop = TRUE;
5918
int wColumns, wRows;
5920
int wXBorder, wYBorder;
5922
char wp[WIN_POS_STR_MAX_LEN + 1];
5924
LPTSTR fontName_lpt = NULL;
5925
LPTSTR fontCharSet_lpt;
5928
if (mswin_debug >= 5)
5929
fprintf (mswin_debugfile, "mswin_setwindow::: entered, minimized: %d\n",
5930
gpTTYInfo->fMinimized);
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){
5938
hDC = GetDC(ghTTYWnd);
5939
ppi = GetDeviceCaps(hDC, LOGPIXELSY);
5940
ReleaseDC(ghTTYWnd, hDC);
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);
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;
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);
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);
5981
fs_give((void **) &fontName_lpt);
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.
5988
if(windowPosition != NULL && *windowPosition != '\0'){
5989
if(strlen(windowPosition) > sizeof(wp)-1)
5992
strncpy(wp, windowPosition, sizeof(wp));
5993
wp[sizeof(wp)-1] = '\0';
5996
* Flag characters are at the end of the string. Strip them
5997
* off till we get to a number.
5999
i = (int)strlen(wp) - 1;
6000
while(i > 0 && (*(wp+i) < '0' || *(wp+i) > '9')){
6001
if(*(wp+i) == 't' || *(wp+i) == 'b'){
6003
toolBarTop = (*(wp+i) == 't');
6007
gfUseDialogs = TRUE;
6009
#ifdef ACCELERATORS_OPT
6011
AccelCtl(ghTTYWnd, ACCEL_LOAD, FALSE);
6018
if(strcmp(wp, "MIN0") == 0){
6021
ShowWindow(ghTTYWnd, SW_MINIMIZE);
6023
gpTTYInfo->toolBarTop = toolBarTop;
6028
/* Look for Columns, deliminated by 'x'. */
6029
c = strchr (wp, 'x');
6034
if(!ScanInt(wp, -999, 9999, &wColumns))
6037
/* Look for Rows, deliminated by '+'. */
6044
if(!ScanInt(n, -999, 9999, &wRows))
6047
/* Look for X position, deliminated by '+'. */
6054
if(!ScanInt(n, -999, 9999, &wXPos))
6057
/* And get Y position, deliminated by end of string. */
6059
if(!ScanInt(n, -999, 9999, &wYPos))
6063
/* Constrain the window position and size. */
6070
GetWindowRect(GetDesktopWindow(), &wndRect);
6071
if(wXPos > wndRect.right - 20)
6072
wXPos = wndRect.right - 100;
6074
if(wYPos > wndRect.bottom - 20)
6075
wYPos = wndRect.bottom - 100;
6077
/* Get the current window rect and client area. */
6078
GetWindowRect(ghTTYWnd, &wndRect);
6079
GetClientRect(ghTTYWnd, &cliRect);
6081
/* Calculate boarder sizes. */
6082
wXBorder = wndRect.right - wndRect.left - cliRect.right;
6083
wYBorder = wndRect.bottom - wndRect.top - cliRect.bottom;
6085
/* Show toolbar before calculating content size. */
6087
gpTTYInfo->toolBarTop = toolBarTop;
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);
6099
gpTTYInfo->fDesiredSize = TRUE;
6100
gpTTYInfo->xDesPos = (CORD)wXPos;
6101
gpTTYInfo->yDesPos = (CORD)wYPos;
6102
gpTTYInfo->xDesSize = (CORD)wXSize;
6103
gpTTYInfo->yDesSize = (CORD)wYSize;
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);
6123
ShowWindow (ghTTYWnd, SW_SHOWNORMAL);
6124
UpdateWindow (ghTTYWnd);
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
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)
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);
6156
fs_give((void **) &t);
6159
if(fontCharSet_utf8 != NULL){
6162
lpt = (LPTSTR) fs_get(nfontCharSet * sizeof(TCHAR));
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);
6170
fs_give((void **) &t);
6172
fs_give((void **) &lpt);
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));
6183
if(fontStyle_utf8 != NULL){
6184
char *sep[] = {"", ", "};
6187
*fontStyle_utf8 = '\0';
6188
if(gpTTYInfo->lfTTYFont.lfWeight >= FW_BOLD){
6189
strncpy(fontStyle_utf8, "bold", nfontStyle);
6190
fontStyle_utf8[nfontStyle-1] = '\0';
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';
6202
if(windowPosition != NULL){
6203
if(gpTTYInfo->fMinimized){
6204
strncpy(windowPosition, "MIN0", nwindowPosition);
6205
windowPosition[nwindowPosition-1] = '\0';
6209
* Get the window position. Constrain the top left corner
6210
* to be on the screen.
6212
GetWindowRect(ghTTYWnd, &wndRect);
6213
if(wndRect.left < 0)
6219
snprintf(windowPosition, nwindowPosition, "%dx%d+%d+%d", gpTTYInfo->actNColumn,
6220
gpTTYInfo->actNRow, wndRect.left, wndRect.top);
6223
if(gpTTYInfo->toolBarSize > 0){
6224
strncat(windowPosition, gpTTYInfo->toolBarTop ? "t" : "b",
6225
nwindowPosition-strlen(windowPosition));
6226
windowPosition[nwindowPosition-1] = '\0';
6230
strncat(windowPosition, "d", nwindowPosition-strlen(windowPosition));
6231
windowPosition[nwindowPosition-1] = '\0';
6234
if(gpTTYInfo->hAccel){
6235
strncat(windowPosition, "a", nwindowPosition-strlen(windowPosition));
6236
windowPosition[nwindowPosition-1] = '\0';
6240
if(foreColor != NULL)
6241
ConvertStringRGB(foreColor, nforeColor, gpTTYInfo->rgbFGColor);
6243
if(backColor != NULL)
6244
ConvertStringRGB(backColor, nbackColor, gpTTYInfo->rgbBGColor);
6246
if(caretStyle != NULL){
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';
6262
mswin_noscrollupdate(int flag)
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;
6274
* Set the scroll range.
6277
mswin_setscrollrange (long page, long max)
6279
SCROLLINFO scrollInfo;
6281
if(gpTTYInfo->noScrollUpdate){
6282
gpTTYInfo->noSUpdatePage = page;
6283
gpTTYInfo->noSUpdateRange = max;
6284
gpTTYInfo->scrollRangeChanged = 1;
6287
if (max != gpTTYInfo->scrollRange) {
6288
scrollInfo.cbSize = sizeof(SCROLLINFO);
6289
scrollInfo.fMask = SIF_DISABLENOSCROLL | SIF_PAGE | SIF_RANGE;
6290
scrollInfo.nMin = 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);
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;
6308
gpTTYInfo->scrollRange = (int)max;
6314
* Set the current scroll position.
6317
mswin_setscrollpos (long pos)
6319
SCROLLINFO scrollInfo;
6321
if (pos != gpTTYInfo->scrollPos) {
6322
scrollInfo.cbSize = sizeof(SCROLLINFO);
6323
scrollInfo.fMask = SIF_PAGE | SIF_RANGE;
6325
GetScrollInfo(ghTTYWnd, SB_VERT, &scrollInfo);
6327
scrollInfo.fMask |= SIF_POS;
6328
scrollInfo.nPos = (int) pos;
6329
SetScrollInfo(ghTTYWnd, SB_VERT, &scrollInfo, TRUE);
6331
gpTTYInfo->scrollPos = pos;
6337
* retreive the current scroll postion.
6340
mswin_getscrollpos (void)
6342
return ((long)((float)GetScrollPos (ghTTYWnd, SB_VERT)));
6347
* retreive the latest scroll to position.
6350
mswin_getscrollto (void)
6352
return (gpTTYInfo->scrollTo);
6356
* install function to deal with LINEDOWN events
6359
mswin_setscrollcallback (cbarg_t cbfunc)
6361
gScrollCallback = cbfunc;
6366
* install function to deal with sort menu messages
6369
mswin_setsortcallback (cbarg_t cbfunc)
6371
gSortCallback = cbfunc;
6376
* install function to deal with sort menu messages
6379
mswin_setflagcallback (cbarg_t cbfunc)
6381
gFlagCallback = cbfunc;
6385
mswin_set_erasecreds_callback (cbvoid_t cbfunc)
6387
gEraseCredsCallback = cbfunc;
6391
* install function to deal with header mode flipping
6394
mswin_sethdrmodecallback (cbarg_t cbfunc)
6396
gHdrCallback = cbfunc;
6401
* install function to deal with zoom mode flipping
6404
mswin_setzoomodecallback (cbarg_t cbfunc)
6406
gZoomCallback = cbfunc;
6411
* install function to deal with function key mode flipping
6414
mswin_setfkeymodecallback (cbarg_t cbfunc)
6416
gFkeyCallback = cbfunc;
6421
* install function to deal with apply mode flipping
6424
mswin_setselectedcallback (cbarg_t cbfunc)
6426
gSelectedCallback = cbfunc;
6431
* return 1 if new mail window is being used
6434
mswin_newmailwinon (void)
6436
return(gMswinNewMailWin.hwnd ? 1 : 0);
6443
mswin_setdebugoncallback (cbvoid_t cbfunc)
6445
gIMAPDebugONCallback = cbfunc;
6450
mswin_setdebugoffcallback (cbvoid_t cbfunc)
6452
gIMAPDebugOFFCallback = cbfunc;
6457
mswin_setconfigcallback (cbvoid_t cffunc)
6459
gConfigScreenCallback = cffunc;
6465
* Set the printer font
6468
mswin_setprintfont(char *fontName, char *fontSize,
6469
char *fontStyle, char *fontCharSet)
6471
LPTSTR fn = NULL, fstyle = NULL, fc = NULL;
6474
fn = utf8_to_lptstr(fontName);
6477
fstyle = utf8_to_lptstr(fontStyle);
6480
fc = utf8_to_lptstr(fontCharSet);
6482
/* Require a font name to set font info. */
6483
if(fn != NULL && *fn != '\0' && lstrlen(fn) <= LF_FACESIZE - 1){
6485
_tcsncpy(gPrintFontName, fn, sizeof(gPrintFontName)/sizeof(TCHAR));
6486
gPrintFontName[sizeof(gPrintFontName)/sizeof(TCHAR)-1] = 0;
6488
_tcsncpy(gPrintFontStyle, fstyle, sizeof(gPrintFontStyle)/sizeof(TCHAR));
6489
gPrintFontStyle[sizeof(gPrintFontStyle)/sizeof(TCHAR)-1] = 0;
6490
_tcslwr(gPrintFontStyle); /* Lower case font style. */
6494
_tcsncpy(gPrintFontCharSet, fc, sizeof(gPrintFontCharSet)/sizeof(TCHAR));
6495
gPrintFontCharSet[sizeof(gPrintFontCharSet)/sizeof(TCHAR)-1] = 0;
6498
gPrintFontSize = 12;
6499
if(ScanInt(fontSize, FONT_MIN_SIZE, FONT_MAX_SIZE, &gPrintFontSize))
6500
gPrintFontSize = abs(gPrintFontSize);
6502
gPrintFontSameAs = FALSE;
6505
gPrintFontName[0] = '\0';
6506
gPrintFontSameAs = TRUE;
6510
fs_give((void **) &fn);
6513
fs_give((void **) &fstyle);
6516
fs_give((void **) &fc);
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)
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';
6539
if(fontName_utf8 != NULL){
6540
u = lptstr_to_utf8(gPrintFontName);
6542
strncpy(fontName_utf8, u, nfontName);
6543
fontName_utf8[nfontName-1] = 0;
6544
fs_give((void **) &u);
6548
if(fontSize_utf8 != NULL)
6549
snprintf(fontSize_utf8, nfontSize, "%d", gPrintFontSize);
6552
if(fontStyle_utf8 != NULL){
6553
u = lptstr_to_utf8(gPrintFontStyle);
6555
strncpy(fontStyle_utf8, u, nfontStyle);
6556
fontStyle_utf8[nfontStyle-1] = 0;
6557
fs_give((void **) &u);
6561
if(fontCharSet_utf8 != NULL){
6562
u = lptstr_to_utf8(gPrintFontCharSet);
6564
strncpy(fontCharSet_utf8, u, nfontCharSet);
6565
fontCharSet_utf8[nfontCharSet-1] = 0;
6566
fs_give((void **) &u);
6574
* Set the window help text. Add or delete the Help menu item as needed.
6577
mswin_sethelptextcallback(cbstr_t cbfunc)
6581
gHelpCallback = cbfunc;
6583
hMenu = GetMenu (ghTTYWnd);
6587
return(MSWHelpSetMenu (hMenu));
6593
* Set the window help text. Add or delete the Help menu item as needed.
6596
mswin_setgenhelptextcallback(cbstr_t cbfunc)
6600
gHelpGenCallback = cbfunc;
6602
hMenu = GetMenu (ghTTYWnd);
6606
return(MSWHelpSetMenu (hMenu));
6612
MSWHelpSetMenu(HMENU hMenu)
6618
* Find menu and update it.
6620
count = GetMenuItemCount (hMenu);
6624
hMenu = GetSubMenu (hMenu, count - 1);
6629
* Insert or delete generic help item
6631
if (gHelpGenCallback == NULL){
6632
if (gfHelpGenMenu) {
6633
brc = DeleteMenu (hMenu, IDM_MI_GENERALHELP, MF_BYCOMMAND);
6634
DrawMenuBar (ghTTYWnd);
6636
gfHelpGenMenu = FALSE;
6639
if (!gfHelpGenMenu) {
6640
brc = InsertMenu (hMenu, 0,
6641
MF_BYPOSITION | MF_STRING,
6642
IDM_MI_GENERALHELP, TEXT("&General Help"));
6643
DrawMenuBar (ghTTYWnd);
6645
gfHelpGenMenu = TRUE;
6649
* Insert or delete screen help item
6651
if (gHelpCallback == NULL){
6653
brc = DeleteMenu (hMenu, IDM_HELP, MF_BYCOMMAND);
6654
DrawMenuBar (ghTTYWnd);
6660
brc = InsertMenu (hMenu, gHelpGenCallback ? 2 : 1,
6661
MF_BYPOSITION | MF_STRING,
6662
IDM_HELP, TEXT("Screen Help in &New Window"));
6663
DrawMenuBar (ghTTYWnd);
6673
* Set the text displayed when someone tries to close the application
6677
mswin_setclosetext (char *pCloseText)
6679
gpCloseText = pCloseText;
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.
6698
start = GetTickCount ();
6700
if (mswin_debug > 16)
6701
fprintf (mswin_debugfile, "mswin_yeild:: Entered\n");
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);
6712
if (mswin_debug > 16)
6713
fprintf (mswin_debugfile, "mswin_yeild:: Delay %ld msec\n",
6714
GetTickCount () - start);
6721
* Called to see if we can process input.
6722
* We can't process input when we are in a scrolling mode.
6727
return (!gScrolling && !gMouseTracking);
6732
* Called to see if there is a character available.
6735
mswin_charavail (void)
6743
RestoreMouseCursor();
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
6750
* BUT! Don't let too much time elapse between calls to GetMessage
6751
* or we'll shut out other windows.
6753
ca = CQAvailable ();
6754
pa = EditPasteAvailable ();
6756
start = GetTickCount ();
6757
if (mswin_debug > 16)
6758
fprintf (mswin_debugfile, "%s mswin_charavail:: Entered, ca %d, pa %d\n",dtime(),ca,pa);
6760
if ((ca || pa) && GetTickCount () < gGMLastCall + GM_MAX_TIME)
6761
ma = PeekMessage (&msg, NULL, 0, 0, PM_NOYIELD | PM_REMOVE);
6763
ma = GetMessage (&msg, NULL, 0, 0);
6764
gGMLastCall = GetTickCount ();
6767
if (gpTTYInfo->hAccel == NULL ||
6768
!TranslateAccelerator (ghTTYWnd, gpTTYInfo->hAccel, &msg)) {
6769
TranslateMessage (&msg);
6770
DispatchMessage (&msg);
6774
if (mswin_debug > 16)
6775
fprintf (mswin_debugfile, "%s mswin_charavail:: Delay %ld msec\n",
6776
dtime(), GetTickCount () - start);
6779
return (pa || ca || CQAvailable ());
6784
* Call to get next character. Dispatch one message.
6793
return (MSWIN_KEY_NODATA);
6795
RestoreMouseCursor();
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
6806
ca = CQAvailable ();
6807
pa = EditPasteAvailable ();
6809
if (mswin_debug > 16) {
6810
start = GetTickCount ();
6811
fprintf (mswin_debugfile, "mswin_getc:: Entered, ca %d pa %d\n", ca, pa);
6814
if ((ca || pa) && GetTickCount () < gGMLastCall + GM_MAX_TIME)
6815
ma = PeekMessage (&msg, NULL, 0, 0, PM_NOYIELD | PM_REMOVE);
6817
ma = GetMessage (&msg, NULL, 0, 0);
6818
gGMLastCall = GetTickCount ();
6821
if (gpTTYInfo->hAccel == NULL ||
6822
!TranslateAccelerator (ghTTYWnd, gpTTYInfo->hAccel, &msg)) {
6823
TranslateMessage (&msg);
6824
DispatchMessage (&msg);
6828
if (mswin_debug > 16)
6829
fprintf (mswin_debugfile, "mswin_getc:: Delay %ld msec\n",
6830
GetTickCount () - start);
6836
return (EditPasteGet ());
6838
if (ca || CQAvailable ()) {
6840
return ((UCS)(CQGet ()));
6843
return (MSWIN_KEY_NODATA);
6848
* Like mswin_getc, but don't yield control.
6851
mswin_getc_fast (void)
6853
RestoreMouseCursor();
6855
if (EditPasteAvailable ()) {
6857
return (EditPasteGet ());
6859
if (CQAvailable ()) {
6861
return ((UCS)CQGet ());
6864
return (MSWIN_KEY_NODATA);
6869
* Flush the character input queue.
6872
mswin_flush_input(void)
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.
6882
while(GetQueueStatus(QS_INPUT))
6883
(void) mswin_getc();
6885
/* And we clear Pine's character input queue, too. */
6891
* ibmmove - Move cursor to...
6894
mswin_move (int row, int column)
6898
if (row < 0 || row >= gpTTYInfo->actNRow)
6900
if (column < 0 || column >= gpTTYInfo->actNColumn)
6902
gpTTYInfo->nRow = (CORD)row;
6903
gpTTYInfo->nColumn = (CORD)column;
6904
MoveTTYCursor (ghTTYWnd);
6910
mswin_getpos (int *row, int *column)
6913
if (row == NULL || column == NULL)
6915
*row = gpTTYInfo->nRow;
6916
*column = gpTTYInfo->nColumn;
6922
mswin_getscreensize (int *row, int *column)
6924
if (row == NULL || column == NULL)
6926
*row = gpTTYInfo->actNRow;
6927
*column = gpTTYInfo->actNColumn;
6929
if (mswin_debug >= 5)
6930
fprintf (mswin_debugfile, "mswin_getscreensize::: reported size %d, %d\n",
6934
*column = MIN(*column, NLINE-1);
6943
if (!gpTTYInfo->fMinimized)
6944
ShowWindow(ghTTYWnd, SW_MINIMIZE);
6949
mswin_showcursor (int show)
6951
int was_shown = gpTTYInfo->fCursorOn;
6954
/* if the cursor was not already show, show it now. */
6956
gpTTYInfo->fCursorOn = TRUE;
6961
/* If the cursor is shown, hide it. */
6963
gpTTYInfo->fCursorOn = FALSE;
6973
mswin_showcaret (int show)
6975
int was_shown = gpTTYInfo->fCaretOn;
6978
/* if the caret was not already show, show it now. */
6980
gpTTYInfo->fCaretOn = TRUE;
6981
ShowCaret(ghTTYWnd);
6985
/* If the caret is shown, hide it. */
6987
gpTTYInfo->fCaretOn = FALSE;
6988
HideCaret(ghTTYWnd);
6997
mswin_puts (char *utf8_str)
7003
if (utf8_str == NULL)
7005
if(!(lptstr_str = utf8_to_lptstr(utf8_str)))
7007
strLen = (int)_tcslen (lptstr_str);
7009
WriteTTYText (ghTTYWnd, lptstr_str, strLen);
7011
fs_give((void **) &lptstr_str);
7017
mswin_puts_n (char *utf8_str, int n)
7019
LPTSTR lptstr_str, lptstr_p;
7022
if (utf8_str == NULL)
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++)
7029
if (lptstr_p > lptstr_str)
7030
WriteTTYText (ghTTYWnd, lptstr_str, (int)(lptstr_p - lptstr_str));
7032
fs_give((void **) &lptstr_str);
7038
mswin_putblock (char *utf8_str, int strLen)
7043
if (utf8_str == NULL)
7045
lptstr_str = utf8_to_lptstr(utf8_str);
7047
WriteTTYText (ghTTYWnd, lptstr_str, strLen);
7048
fs_give((void **) &lptstr_str);
7054
* mswin_putc - put a character at the current position in the
7058
mswin_putc (UCS ucs)
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)
7068
/* Carriage control. Need to flush write accumulator and
7069
* write this char. */
7071
WriteTTYBlock (ghTTYWnd, &cc, 1);
7078
* ibmoutc - output a single character with the right attributes, but
7079
* don't advance the cursor
7097
/* Do nothing for these screen motion characters. */
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;
7108
/* Invalidate rectange covering singel character. */
7109
rect.left = (gpTTYInfo->nColumn * gpTTYInfo->xChar) +
7111
rect.right = rect.left + gpTTYInfo->xChar;
7112
rect.top = (gpTTYInfo->nRow * gpTTYInfo->yChar) +
7114
rect.bottom = rect.top + gpTTYInfo->yChar;
7115
gpTTYInfo->screenDirty = TRUE;
7116
InvalidateRect (ghTTYWnd, &rect, FALSE);
7123
* ibmrev - change reverse video state
7126
mswin_rev (int state)
7128
int curState = (gpTTYInfo->curAttrib.style & CHAR_ATTR_REV) != 0;
7130
if (state != curState){
7133
gpTTYInfo->curAttrib.style |= CHAR_ATTR_REV;
7137
gpTTYInfo->curAttrib.style &= ~CHAR_ATTR_REV;
7138
pico_set_normal_color();
7147
* Get current reverse video state.
7150
mswin_getrevstate (void)
7152
return ((gpTTYInfo->curAttrib.style & CHAR_ATTR_REV) != 0);
7157
* ibmrev - change reverse video state
7160
mswin_bold (int state)
7162
int curState = (gpTTYInfo->curAttrib.style & CHAR_ATTR_BOLD) != 0;
7164
if (state != curState){
7167
gpTTYInfo->curAttrib.style |= CHAR_ATTR_BOLD;
7169
gpTTYInfo->curAttrib.style &= ~CHAR_ATTR_BOLD;
7177
* ibmrev - change reverse video state
7180
mswin_uline (int state)
7182
int curState = (gpTTYInfo->curAttrib.style & CHAR_ATTR_ULINE) != 0;
7184
if (state != curState){
7187
gpTTYInfo->curAttrib.style |= CHAR_ATTR_ULINE;
7189
gpTTYInfo->curAttrib.style &= ~CHAR_ATTR_ULINE;
7197
* ibmeeol - erase to the end of the line
7210
/* From current position to end of line. */
7211
length = gpTTYInfo->actNColumn - gpTTYInfo->nColumn;
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;
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;
7231
rect.left = (gpTTYInfo->nColumn * gpTTYInfo->xChar) +
7233
rect.right = gpTTYInfo->xSize;
7234
rect.top = (gpTTYInfo->nRow * gpTTYInfo->yChar) +
7236
rect.bottom = rect.top + gpTTYInfo->yChar;
7237
gpTTYInfo->screenDirty = TRUE;
7238
InvalidateRect (ghTTYWnd, &rect, FALSE);
7245
* ibmeeop - clear from cursor to end of page
7257
/* From current position to end of screen. */
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))
7266
for(i = 0; i < length; i ++){
7267
cStart[i] = (TCHAR)(' ');
7268
cwStart[i] = gpTTYInfo->xChar;
7271
aStart = gpTTYInfo->pAttrib
7272
+ (gpTTYInfo->nRow * gpTTYInfo->actNColumn)
7273
+ gpTTYInfo->nColumn;
7275
for(; length-- > 0; aStart++){
7276
aStart->style = CHAR_ATTR_NORM;
7277
aStart->rgbFG = gpTTYInfo->curAttrib.rgbFG;
7278
aStart->rgbBG = gpTTYInfo->curAttrib.rgbBG;
7281
/* Invalidate a rectangle that includes all of the current line down
7282
* to the bottom of the window. */
7284
rect.right = gpTTYInfo->xSize;
7285
rect.top = (gpTTYInfo->nRow * gpTTYInfo->yChar) +
7287
rect.bottom = gpTTYInfo->ySize;
7288
gpTTYInfo->screenDirty = TRUE;
7289
InvalidateRect (ghTTYWnd, &rect, FALSE);
7296
* ibmbeep - system beep...
7301
MessageBeep (MB_OK);
7307
* pause - wait in function for specified number of seconds.
7310
mswin_pause (int seconds)
7314
stoptime = GetTickCount () + (DWORD) seconds * 1000;
7315
while (stoptime > GetTickCount ())
7321
* ibmflush - Flush output to screen.
7329
* Flush cached changes, then update the window.
7332
UpdateWindow (ghTTYWnd);
7339
* A replacement for fflush
7340
* relies on #define fflush mswin_fflush
7344
mswin_fflush (FILE *f)
7360
mswin_setcursor (int newcursor)
7365
case MSWIN_CURSOR_BUSY :
7366
hNewCursor = ghCursorBusy;
7367
mswin_showcursor(TRUE);
7370
case MSWIN_CURSOR_IBEAM :
7371
hNewCursor = ghCursorIBeam;
7374
case MSWIN_CURSOR_HAND :
7375
if(hNewCursor = ghCursorHand)
7377
/* ELSE fall thru to normal cursor */
7379
case MSWIN_CURSOR_ARROW :
7381
hNewCursor = ghCursorArrow;
7385
/* If new cursor requested, select it. */
7386
if (ghCursorCurrent != hNewCursor)
7387
SetCursor (ghCursorCurrent = hNewCursor);
7392
RestoreMouseCursor()
7394
if(ghCursorCurrent == ghCursorBusy)
7395
mswin_setcursor(MSWIN_CURSOR_ARROW);
7400
* Display message in windows dialog box.
7403
mswin_messagebox (char *msg_utf8, int err)
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);
7417
* Signals whether or not Paste should be turned on in the
7421
mswin_allowpaste (int on)
7423
static short stackp = 0;
7424
static unsigned long stack = 0L;
7427
case MSWIN_PASTE_DISABLE :
7428
if(stackp){ /* previous state? */
7429
if((stackp -= 2) < 0)
7432
gPasteEnabled = ((stack >> stackp) & 0x03);
7435
gPasteEnabled = MSWIN_PASTE_DISABLE;
7439
case MSWIN_PASTE_FULL :
7440
case MSWIN_PASTE_LINE :
7441
if(gPasteEnabled){ /* current state? */
7442
stack |= ((unsigned long) gPasteEnabled << stackp);
7451
UpdateAccelerators(ghTTYWnd);
7457
* Signals whether or not Copy/Cut should be turned on in the
7461
mswin_allowcopy (getc_t copyfunc)
7463
gCopyCutFunction = copyfunc;
7464
gAllowCopy = (copyfunc != NULL);
7466
UpdateAccelerators(ghTTYWnd);
7472
* Signals whether or not Copy/Cut should be turned on in the
7476
mswin_allowcopycut (getc_t copyfunc)
7478
gCopyCutFunction = copyfunc;
7479
gAllowCopy = gAllowCut = (copyfunc != NULL);
7481
UpdateAccelerators(ghTTYWnd);
7487
* Replace the clipboard's contents with the given string
7490
mswin_addclipboard(char *s)
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 */
7506
if (SetClipboardData (CF_TEXT, hCB) == NULL)
7507
/* Failed! Free the data. */
7518
* Signals if the upper layer wants to track the mouse.
7521
mswin_allowmousetrack (int b)
7523
gAllowMouseTrack = b;
7531
* register's callback to warn
7534
mswin_mousetrackcallback(cbarg_t cbfunc)
7536
if(!(gMouseTrackCallback = cbfunc))
7537
mswin_setcursor (MSWIN_CURSOR_ARROW);
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.
7547
mswin_newmailtext (char *t_utf8)
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...
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.
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);
7569
gpTTYInfo->fNewMailIcon = TRUE;
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);
7576
gpTTYInfo->fNewMailIcon = FALSE;
7582
mswin_mclosedtext (char *t_utf8)
7586
if(t_utf8 && gpTTYInfo->fMClosedIcon == FALSE){
7588
* Change the appearance of minimized icon so user knows
7589
* the mailbox closed.
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);
7597
gpTTYInfo->fMClosedIcon = TRUE;
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);
7605
gpTTYInfo->fMClosedIcon = FALSE;
7610
mswin_trayicon(int show)
7613
if(!gpTTYInfo->fTrayIcon){
7614
UpdateTrayIcon(NIM_ADD, ghNormalIcon, TEXT("Alpine"));
7615
gpTTYInfo->fTrayIcon = TRUE;
7619
if(gpTTYInfo->fTrayIcon){
7620
UpdateTrayIcon(NIM_DELETE, 0, NULL);
7621
gpTTYInfo->fTrayIcon = FALSE;
7628
UpdateTrayIcon(DWORD dwMsg, HICON hIcon, LPTSTR tip)
7632
nt.cbSize = sizeof (nt);
7634
nt.uID = TASKBAR_ICON_NEWMAIL;
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;
7645
_tcsncpy (nt.szTip, tip, 63);
7646
nt.szTip[63] = '\0';
7653
case NIM_MODIFY : /* send msg to modify icon in tray */
7654
nt.uFlags = NIF_ICON | NIF_TIP;
7656
_tcsncpy (nt.szTip, tip, 63);
7657
nt.szTip[63] = '\0';
7668
Shell_NotifyIcon (dwMsg, &nt);
7673
/*---------------------------------------------------------------------------
7675
* Client level menu item stuff.
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
7683
*-------------------------------------------------------------------------*/
7686
* Clear active status of all "menu items".
7689
mswin_menuitemclear (void)
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);
7700
EnableWindow(hWnd, FALSE);
7704
gpTTYInfo->menuItemsCurrent = FALSE;
7705
gpTTYInfo->menuItemsIndex = 1;
7706
for(i = 0; i < KS_COUNT; i++)
7707
gpTTYInfo->menuItems[i].miIndex = 0;
7712
* Add an item to the cmdmenu
7715
mswin_menuitemadd (UCS key, char *label, int menuitem, int flags)
7720
if (menuitem >= KS_RANGESTART && menuitem <= KS_RANGEEND) {
7722
gpTTYInfo->menuItemsCurrent = FALSE;
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++;
7732
if (gpTTYInfo->toolBarSize > 0) {
7733
hWnd = GetDlgItem(gpTTYInfo->hTBWnd, menuitem);
7735
EnableWindow(hWnd, TRUE);
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.
7747
ProcessMenuItem (HWND hWnd, WPARAM wParam)
7752
pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
7753
if (pTTYInfo == NULL)
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);
7766
* Called to set a new menu.
7769
mswin_setwindowmenu (int menu)
7776
oldmenu = gpTTYInfo->curWinMenu;
7777
holdmenu = GetMenu (ghTTYWnd);
7778
if (gpTTYInfo->curWinMenu != menu) {
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;
7789
if(menu == MENU_DEFAULT){
7790
TBSwap (ghTTYWnd, IDD_TOOLBAR);
7792
(void) MSWHelpSetMenu(hmenu);
7795
TBSwap (ghTTYWnd, IDD_COMPOSER_TB);
7803
/*---------------------------------------------------------------------------
7807
*-------------------------------------------------------------------------*/
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. */
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)
7830
#define VERTICLE_MARGIN 3 /* lines at top and bottom of page. */
7831
#define HORIZONTAL_MARGIN 1 /* margine at left & right in chars */
7834
* Several errors that can be reported.
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
7848
LOCAL struct pe_error_message {
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" },
7867
* Send text in the line buffer to the printer.
7868
* Advance to next page if necessary.
7871
_print_send_line (void)
7877
TextOut (P_PrintDC, P_LeftOffset,
7878
P_TopOffset + (P_CurRow * P_RowHeight),
7879
P_LineText, P_CurCol);
7881
if (++P_CurRow >= P_PageRows)
7882
status = _print_send_page ();
7893
_print_send_page (void)
7897
if((status = EndPage (P_PrintDC)) > 0){
7899
if((status = StartPage (P_PrintDC)) > 0){
7900
SelectObject (P_PrintDC, P_hFont);
7907
return(PE_GENERAL_ERROR);
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);
7914
case SP_ERROR: break;
7917
return (PE_GENERAL_ERROR);
7923
* Map errors reported to my own error set.
7926
_print_map_dlg_error (DWORD 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);
7939
return (PE_GENERAL_ERROR);
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.
7950
mswin_print_ready(WINHAND hWnd, LPTSTR docDesc)
7956
int fontSize; /* Size in Points. */
7957
int ppi; /* Pixels per inch in device. */
7969
* Show print dialog.
7971
memset(&pd, 0, sizeof(PRINTDLG));
7972
pd.lStructSize = sizeof (PRINTDLG);
7973
pd.hwndOwner = (hWnd ? (HWND) hWnd : ghTTYWnd);
7975
pd.hDevNames = NULL;
7976
pd.Flags = PD_ALLPAGES | PD_NOSELECTION | PD_NOPAGENUMS |
7977
PD_HIDEPRINTTOFILE | PD_RETURNDC;
7979
if(PrintDlg (&pd) == 0)
7980
return(_print_map_dlg_error (CommDlgExtendedError()));
7983
* Returns the device name which we could use to remember what printer
7984
* they selected. But instead, we just toss them.
7987
GlobalFree (pd.hDevNames);
7989
GlobalFree (pd.hDevMode);
7992
* Get the device drawing context.
7993
* (does PringDlg() ever return success but fail to return a DC?)
7998
status = PE_DIALOG_FAILED;
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
8010
if(StartDoc(P_PrintDC, &di) <= 0) {
8012
status = PE_CANT_START_DOC;
8013
DeleteDC (P_PrintDC);
8019
* Printer font is either same as window font, or is it's own
8022
if (gPrintFontSameAs) {
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.
8031
hDC = GetDC (ghTTYWnd); /* Temp screen DC. */
8032
ppi = (int) ((float)GetDeviceCaps (hDC, VERTRES) /
8033
((float) GetDeviceCaps (hDC, VERTSIZE) / 25.3636));
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));
8042
ReleaseDC (ghTTYWnd, hDC);
8044
/* Convert from screen pixels to points. */
8045
fontSize = MulDiv (-gpTTYInfo->lfTTYFont.lfHeight, 72, ppi);
8046
++fontSize; /* Fudge a little. */
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;
8060
if (mswin_debug >= 8) {
8061
fprintf (mswin_debugfile, " font Size %d points\n",
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));
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;
8080
newFont.lfItalic = 0;
8081
if(_tcsstr(gPrintFontStyle, TEXT("italic")))
8082
newFont.lfItalic = 1;
8084
newFont.lfCharSet = mswin_string2charsetid(gPrintFontCharSet);
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);
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.
8112
StartPage (P_PrintDC);
8113
oldFont = SelectObject (P_PrintDC, P_hFont);
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.
8120
GetTextMetrics (P_PrintDC, &tm);
8121
xChar = tm.tmAveCharWidth;
8122
P_RowHeight = tm.tmHeight + tm.tmExternalLeading;
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;
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;
8132
/* And allow for a left and right margine measured in characters. */
8133
P_PageColumns -= HORIZONTAL_MARGIN * 2;
8134
P_LeftOffset = HORIZONTAL_MARGIN * xChar;
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)
8143
DeleteObject (P_hFont);
8145
DeleteDC (P_PrintDC);
8147
status = PE_OUT_OF_MEMORY;
8158
* Called when printing is done.
8159
* xxx what happens if there is an error? Will this get called?
8162
mswin_print_done(void)
8164
if(P_PrintDC != NULL){
8165
if(P_LineText != NULL)
8166
MemFree((void *) P_LineText);
8168
if(EndPage (P_PrintDC) <= 0 || EndDoc (P_PrintDC) <= 0)
8171
DeleteObject(P_hFont);
8173
DeleteDC(P_PrintDC);
8182
* Return ponter to a text string that describes the erorr.
8185
mswin_print_error(int error_code)
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);
8193
return("(Unknown error)");
8198
* Add a single character to the current line.
8199
* Only handles CRLF carrage control.
8202
mswin_print_char(TCHAR c)
8209
return(_print_send_line());
8213
if(P_CurCol == P_PageColumns)
8214
return(_print_send_line());
8216
*(P_LineText + P_CurCol++) = ' ';
8218
while(P_CurCol % PRINT_TAB_SIZE != 0);
8222
if(P_CurCol == P_PageColumns){
8225
if((status = _print_send_line()) != 0)
8229
*(P_LineText + P_CurCol++) = c;
8236
mswin_print_char_utf8(int c)
8238
static unsigned char cbuf[6], *cbufp;
8243
if(utf8_to_ucs4_oneatatime(c, cbuf, sizeof(cbuf), &cbufp, &ucs, NULL)){
8244
/* bogus conversion ignores UTF-16 */
8246
ret = mswin_print_char(tc);
8254
* Send a string to the printer.
8257
mswin_print_text(LPTSTR text)
8263
if((status = mswin_print_char(*(text++))) != 0)
8271
mswin_print_text_utf8(char *text_utf8)
8277
text_lpt = utf8_to_lptstr(text_utf8);
8279
ret = mswin_print_text(text_lpt);
8280
fs_give((void **) &text_lpt);
8288
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8290
* File dialog boxes.
8292
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
8294
LOCAL TCHAR gHomeDir[PATH_MAX];
8295
LOCAL TCHAR gLastDir[PATH_MAX];
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
8304
FillInitialDir (LPCTSTR *iDir, LPTSTR targDir)
8306
if (_tcslen (gHomeDir) == 0) {
8307
_tcscpy (gHomeDir, targDir);
8310
else if (_tcscmp (gHomeDir, targDir) == 0 && *gLastDir)
8319
* Display a save file dialog box.
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.
8327
* Possible return values:
8328
* 0 no file selected
8330
* -1 some sort of error
8333
mswin_savefile(char *dir_utf8, int nMaxDName, char *fName_utf8, int nMaxFName)
8336
TCHAR filters[128], moniker[128];
8338
LPTSTR p, extlist_lpt;
8339
LPTSTR fName_lpt, f, dir_lpt;
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);
8348
_tcsncpy(fName_lpt, f, nMaxFName);
8349
fName_lpt[nMaxFName-1] = '\0';
8350
fs_give((void **) &f);
8354
dir_lpt = (LPTSTR) fs_get(nMaxDName * sizeof(TCHAR));
8356
if(dir_utf8 && dir_utf8[0]){
8357
f = utf8_to_lptstr(dir_utf8);
8359
_tcsncpy(dir_lpt, f, nMaxDName);
8360
dir_lpt[nMaxDName-1] = '\0';
8361
fs_give((void **) &f);
8365
for(extlist_lpt = NULL, p = _tcschr(fName_lpt, '.'); p; p = _tcschr(++p, '.'))
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);
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);
8377
_sntprintf(filters, sizeof(filters)/sizeof(TCHAR),
8378
TEXT("%s (*%s)#*%s#"), moniker, extlist_lpt, extlist_lpt);
8383
_tcsncat(filters, TEXT("Text Files (*.txt)#*.txt#All Files (*.*)#*.*#"),
8384
sizeof(filters)/sizeof(TCHAR));
8385
filters[sizeof(filters)/sizeof(TCHAR) - 1] = '\0';
8387
for(p = filters; *p != '\0'; ++p)
8391
/* Set up the BIG STRUCTURE. */
8392
memset (&ofn, 0, sizeof(ofn));
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.
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");
8412
if(GetSaveFileName(&ofn)){
8413
if(ofn.nFileOffset > nMaxDName-1){
8415
fs_give((void **) &fName_lpt);
8418
fs_give((void **) &dir_lpt);
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';
8430
dir_lpt[ofn.nFileOffset] = '\0';
8432
/* Remember last dir visited. */
8433
_tcsncpy(gLastDir, dir_lpt, PATH_MAX);
8434
gLastDir[PATH_MAX-1] = '\0';
8436
/* convert back to UTF-8 */
8437
cp = lptstr_to_utf8(dir_lpt);
8439
strncpy(dir_utf8, cp, nMaxDName-1);
8440
dir_utf8[nMaxDName-1] = '\0';
8441
fs_give((void **) &cp);
8444
p = fName_lpt + ofn.nFileOffset;
8446
/* convert fName back to UTF-8 */
8447
cp = lptstr_to_utf8(p);
8449
strncpy(fName_utf8, cp, nMaxFName-1);
8450
fName_utf8[nMaxFName-1] = '\0';
8451
fs_give((void **) &cp);
8455
fs_give((void **) &fName_lpt);
8458
fs_give((void **) &dir_lpt);
8464
fs_give((void **) &fName_lpt);
8467
fs_give((void **) &dir_lpt);
8469
rc = CommDlgExtendedError();
8470
return(rc ? -1 : 0);
8478
* Display an open file dialog box.
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.
8486
* Possible return values:
8487
* 0 no file selected
8489
* -1 some sort of error
8492
mswin_openfile(char *dir_utf8, int nMaxDName, char *fName_utf8,
8493
int nMaxFName, char *extlist_utf8)
8496
TCHAR filters[1024];
8499
LPTSTR extlist_lpt = NULL;
8500
LPTSTR fName_lpt, f, dir_lpt;
8505
extlist_lpt = utf8_to_lptstr(extlist_utf8);
8508
* Set filters array. (pairs of null terminated strings, terminated
8509
* by a double null).
8511
_sntprintf(filters, sizeof(filters)/sizeof(TCHAR),
8512
TEXT("%s%sAll Files (*.*)#*.*#"),
8513
extlist_lpt ? extlist_lpt : TEXT(""), extlist_lpt ? TEXT("#") : TEXT(""));
8516
fs_give((void **) &extlist_lpt);
8518
for(p = filters; *p != '\0'; ++p)
8522
/* Set up the BIG STRUCTURE. */
8523
memset(&ofn, 0, sizeof(ofn));
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);
8531
_tcsncpy(fName_lpt, f, nMaxFName);
8532
fName_lpt[nMaxFName-1] = '\0';
8533
fs_give((void **) &f);
8537
dir_lpt = (LPTSTR) fs_get(nMaxDName * sizeof(TCHAR));
8539
if(dir_utf8 && dir_utf8[0]){
8540
f = utf8_to_lptstr(dir_utf8);
8542
_tcsncpy(dir_lpt, f, nMaxDName);
8543
dir_lpt[nMaxDName-1] = '\0';
8544
fs_give((void **) &f);
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.
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");
8567
if(GetOpenFileName(&ofn)){
8568
if(ofn.nFileOffset > nMaxDName-1){
8570
fs_give((void **) &fName_lpt);
8573
fs_give((void **) &dir_lpt);
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';
8585
dir_lpt[ofn.nFileOffset] = '\0';
8587
/* Remember last dir visited. */
8588
_tcsncpy(gLastDir, dir_lpt, PATH_MAX);
8589
gLastDir[PATH_MAX-1] = '\0';
8591
/* convert back to UTF-8 */
8592
cp = lptstr_to_utf8(dir_lpt);
8594
strncpy(dir_utf8, cp, nMaxDName-1);
8595
dir_utf8[nMaxDName-1] = '\0';
8596
fs_give((void **) &cp);
8599
p = fName_lpt + ofn.nFileOffset;
8601
/* convert fName back to UTF-8 */
8602
cp = lptstr_to_utf8(p);
8604
strncpy(fName_utf8, cp, nMaxFName-1);
8605
fName_utf8[nMaxFName-1] = '\0';
8606
fs_give((void **) &cp);
8610
fs_give((void **) &fName_lpt);
8613
fs_give((void **) &dir_lpt);
8619
fs_give((void **) &fName_lpt);
8622
fs_give((void **) &dir_lpt);
8624
rc = CommDlgExtendedError();
8625
return(rc ? -1 : 0);
8631
* Display an open file dialog box.
8632
* Allow selection of multiple files.
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.
8640
* Possible return values:
8641
* 0 no file selected
8643
* -1 some sort of error
8646
mswin_multopenfile(char *dir_utf8, int nMaxDName, char *fName_utf8,
8647
int nMaxFName, char *extlist_utf8)
8650
TCHAR filters[1024];
8653
LPTSTR extlist_lpt = NULL;
8654
LPTSTR fName_lpt, f, dir_lpt;
8659
extlist_lpt = utf8_to_lptstr(extlist_utf8);
8662
* Set filters array. (pairs of null terminated strings, terminated
8663
* by a double null).
8665
_sntprintf(filters, sizeof(filters)/sizeof(TCHAR),
8666
TEXT("%s%sAll Files (*.*)#*.*#"),
8667
extlist_lpt ? extlist_lpt : TEXT(""), extlist_lpt ? TEXT("#") : TEXT(""));
8670
fs_give((void **) &extlist_lpt);
8672
for(p = filters; *p != '\0'; ++p)
8676
/* Set up the BIG STRUCTURE. */
8677
memset (&ofn, 0, sizeof(ofn));
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);
8685
_tcsncpy(fName_lpt, f, nMaxFName);
8686
fName_lpt[nMaxFName-1] = '\0';
8687
fs_give((void **) &f);
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);
8696
_tcsncpy(dir_lpt, f, nMaxDName);
8697
dir_lpt[nMaxDName-1] = '\0';
8698
fs_give((void **) &f);
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.
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");
8722
if(GetOpenFileName(&ofn)){
8723
if(ofn.nFileOffset > nMaxDName-1){
8725
fs_give((void **) &fName_lpt);
8728
fs_give((void **) &dir_lpt);
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';
8740
dir_lpt[ofn.nFileOffset] = '\0';
8742
/* Remember last dir visited. */
8743
_tcsncpy(gLastDir, dir_lpt, PATH_MAX);
8744
gLastDir[PATH_MAX-1] = '\0';
8746
/* convert back to UTF-8 */
8747
cp = lptstr_to_utf8(dir_lpt);
8749
strncpy(dir_utf8, cp, nMaxDName-1);
8750
dir_utf8[nMaxDName-1] = '\0';
8751
fs_give((void **) &cp);
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
8760
* This is complicated because we need to convert all of these file
8763
for(q=fName_utf8, p=fName_lpt + ofn.nFileOffset; *p; p += _tcslen(p)+1){
8764
cp = lptstr_to_utf8(p);
8766
sstrncpy(&q, cp, (int)(nMaxFName-(q-fName_utf8)));
8767
if(q-fName_utf8 < nMaxFName){
8769
if(q-fName_utf8 < nMaxFName)
8770
*q = '\0'; /* the double null if this is the end */
8773
fName_utf8[nMaxFName-1] = '\0';
8775
fs_give((void **) &cp);
8779
fName_utf8[nMaxFName-1] = fName_utf8[nMaxFName-2] = '\0';
8782
fs_give((void **) &fName_lpt);
8785
fs_give((void **) &dir_lpt);
8791
fs_give((void **) &fName_lpt);
8794
fs_give((void **) &dir_lpt);
8796
rc = CommDlgExtendedError();
8797
return(rc ? -1 : 0);
8802
/*---------------------------------------------------------------------------
8806
* pico_XXcolor() - each function sets a particular attribute
8809
pico_nfcolor(char *s)
8814
SetColorAttribute (&gpTTYInfo->rgbFGColor, s);
8815
pico_set_nfg_color();
8817
if(the_normal_color){
8818
strncpy(the_normal_color->fg,
8819
ConvertStringRGB(cbuf, sizeof(cbuf), gpTTYInfo->rgbFGColor),
8821
the_normal_color->fg[MAXCOLORLEN] = '\0';
8825
gpTTYInfo->rgbFGColor = GetSysColor (COLOR_WINDOWTEXT);
8826
if(the_normal_color)
8827
free_color_pair(&the_normal_color);
8830
// Update all textwindows with the new FG color.
8831
mswin_tw_setcolor((MSWIN_TEXTWINDOW *)-1,
8832
gpTTYInfo->rgbFGColor, gpTTYInfo->rgbBGColor);
8837
pico_nbcolor(char *s)
8842
SetColorAttribute (&gpTTYInfo->rgbBGColor, s);
8843
pico_set_nbg_color();
8845
if(the_normal_color){
8846
strncpy(the_normal_color->bg,
8847
ConvertStringRGB(cbuf, sizeof(cbuf), gpTTYInfo->rgbBGColor),
8849
the_normal_color->fg[MAXCOLORLEN] = '\0';
8853
gpTTYInfo->rgbBGColor = GetSysColor (COLOR_WINDOW);
8854
if(the_normal_color)
8855
free_color_pair(&the_normal_color);
8858
// Update all textwindows with the new BG color.
8859
mswin_tw_setcolor((MSWIN_TEXTWINDOW *)-1,
8860
gpTTYInfo->rgbFGColor, gpTTYInfo->rgbBGColor);
8865
pico_rfcolor(char *s)
8870
SetColorAttribute (&gpTTYInfo->rgbRFGColor, s);
8873
strncpy(the_rev_color->fg,
8874
ConvertStringRGB(cbuf, sizeof(cbuf), gpTTYInfo->rgbRFGColor),
8876
the_rev_color->fg[MAXCOLORLEN] = '\0';
8880
gpTTYInfo->rgbRFGColor = GetSysColor (COLOR_HIGHLIGHTTEXT);
8882
free_color_pair(&the_rev_color);
8888
pico_rbcolor(char *s)
8893
SetColorAttribute (&gpTTYInfo->rgbRBGColor, s);
8896
strncpy(the_rev_color->bg,
8897
ConvertStringRGB(cbuf, sizeof(cbuf), gpTTYInfo->rgbRBGColor),
8899
the_rev_color->bg[MAXCOLORLEN] = '\0';
8903
gpTTYInfo->rgbRBGColor = GetSysColor (COLOR_HIGHLIGHT);
8905
free_color_pair(&the_rev_color);
8918
pico_count_in_color_table()
8920
return(visibleColorTableSize);
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.
8928
* Args colorName -- The color to convert to ascii rgb.
8930
* Returns Pointer to a static buffer containing the rgb string.
8933
color_to_asciirgb(char *colorName)
8935
static char c_to_a_buf[RGBLEN+1];
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));
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.
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';
8966
pico_set_nfg_color()
8969
gpTTYInfo->curAttrib.rgbFG = gpTTYInfo->rgbFGColor;
8973
pico_set_nbg_color()
8976
gpTTYInfo->curAttrib.rgbBG = gpTTYInfo->rgbBGColor;
8980
pico_set_normal_color()
8982
pico_set_nfg_color();
8983
pico_set_nbg_color();
8987
pico_get_rev_color()
8989
char fgbuf[MAXCLEN], bgbuf[MAXCLEN];
8993
new_color_pair(ConvertStringRGB(fgbuf,sizeof(fgbuf),gpTTYInfo->rgbRFGColor),
8994
ConvertStringRGB(bgbuf,sizeof(bgbuf),gpTTYInfo->rgbRBGColor));
8995
return(the_rev_color);
8999
pico_get_normal_color()
9001
char fgbuf[MAXCLEN], bgbuf[MAXCLEN];
9003
if(!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);
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.
9016
* If flag PSC_RET is set, returns an allocated copy of the previous
9017
* color pair, otherwise returns NULL.
9020
pico_set_colors(char *fg, char *bg, int flags)
9022
COLOR_PAIR *cp = NULL;
9025
cp = pico_get_cur_color();
9027
if(!(fg && bg && pico_set_fg_color(fg) && pico_set_bg_color(bg))){
9029
if(flags & PSC_NORM)
9030
pico_set_normal_color();
9031
else if(flags & PSC_REV)
9040
pico_is_good_color(char *colorName)
9044
return(ConvertRGBString(colorName, &cf));
9049
pico_set_fg_color(char *colorName)
9052
return(ConvertRGBString(colorName, &gpTTYInfo->curAttrib.rgbFG));
9057
pico_set_bg_color(char *colorName)
9060
return(ConvertRGBString(colorName, &gpTTYInfo->curAttrib.rgbBG));
9065
pico_get_last_fg_color()
9072
pico_get_last_bg_color()
9079
pico_get_color_options()
9081
return((unsigned)0);
9086
pico_set_color_options(unsigned int opts)
9092
pico_get_cur_color()
9094
char fgbuf[MAXCLEN], bgbuf[MAXCLEN];
9096
return(new_color_pair(ConvertStringRGB(fgbuf,sizeof(fgbuf),gpTTYInfo->curAttrib.rgbFG),
9097
ConvertStringRGB(bgbuf,sizeof(bgbuf),gpTTYInfo->curAttrib.rgbBG)));
9102
mswin_rgbchoice(char *pOldRGB)
9105
static COLORREF custColors[16] = {
9119
memset(&cc, 0, sizeof(CHOOSECOLOR));
9121
cc.lStructSize = sizeof(CHOOSECOLOR);
9122
cc.hwndOwner = ghTTYWnd;
9123
cc.Flags = CC_ANYCOLOR;
9124
cc.lpCustColors = &custColors[0];
9129
ConvertRGBString (pOldRGB, &cc.rgbResult);
9130
cc.Flags |= CC_RGBINIT;
9132
for(i = 0; i < 11 && custColors[i] != cc.rgbResult; i++)
9136
custColors[i] = cc.rgbResult;
9137
cc.Flags |= CC_FULLOPEN;
9142
if(ChooseColor(&cc)){
9143
char rgbbuf[MAXCLEN], *p;
9145
ConvertStringRGB(rgbbuf, sizeof(rgbbuf), cc.rgbResult);
9146
if(p = MemAlloc(MAXCLEN * sizeof(char))){
9147
strncpy(p, rgbbuf, MAXCLEN);
9148
p[MAXCLEN-1] = '\0';
9159
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9161
* Signal and alarm functions
9163
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
9166
* Provide a rough implementation of the SIGALRM and alarm functions
9173
* Set a new handler for a signal.
9175
void (__cdecl * __cdecl signal (int sig,void (__cdecl *hndlr)(int)))(int)
9178
SignalType oldValue;
9182
oldValue = gSignalAlarm;
9183
gSignalAlarm = hndlr;
9187
oldValue = gSignalHUP;
9191
/* All other's are always ignored. */
9202
* Set the alarm expiration time (in seconds)
9205
mswin_alarm (int seconds)
9209
prevtime = gAlarmTimeout ? (gAlarmTimeout - (GetTickCount () / 1000)): 0;
9210
gAlarmTimeout = seconds ? (GetTickCount() / 1000) + seconds : 0;
9218
* Deliver and clear the alarm.
9223
if (gSignalAlarm != SIG_DFL && gSignalAlarm != SIG_IGN) {
9224
/* Clear AlarmTimeout BEFORE calling handler. handler may call back
9225
* to reset timeout. */
9228
gSignalAlarm (SIGALRM);
9238
gSignalHUP (SIGHUP);
9246
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9248
* Printer font selection menu
9250
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
9253
* Set the print font to be the same as the window font.
9257
PrintFontSameAs (HWND hWnd)
9264
pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
9265
if (pTTYInfo == NULL)
9268
if (gPrintFontSameAs) {
9270
/* No longer same as window font. Use window font as starting point
9271
* for new printer font. User may later modify printer font. */
9273
ppi = GetDeviceCaps (hDC, LOGPIXELSY);
9274
ReleaseDC (ghTTYWnd, hDC);
9275
ExtractFontInfo(&pTTYInfo->lfTTYFont,
9276
gPrintFontName, sizeof(gPrintFontName)/sizeof(TCHAR),
9278
gPrintFontStyle, sizeof(gPrintFontStyle)/sizeof(TCHAR),
9280
gPrintFontCharSet, sizeof(gPrintFontCharSet)/sizeof(TCHAR));
9281
gPrintFontSameAs = FALSE;
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;
9290
DidResize (gpTTYInfo);
9298
PrintFontSelect (HWND hWnd)
9300
CHOOSEFONT cfTTYFont;
9309
ppi = GetDeviceCaps (hDC, LOGPIXELSY);
9310
ReleaseDC (ghTTYWnd, hDC);
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;
9320
newFont.lfItalic = 0;
9321
if(_tcsstr(gPrintFontStyle, TEXT("italic")))
9322
newFont.lfItalic = 1;
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;
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);
9352
if (ChooseFont (&cfTTYFont)) {
9353
ExtractFontInfo(&newFont,
9354
gPrintFontName, sizeof(gPrintFontName)/sizeof(TCHAR),
9356
gPrintFontStyle, sizeof(gPrintFontStyle)/sizeof(TCHAR),
9358
gPrintFontCharSet, sizeof(gPrintFontCharSet)/sizeof(TCHAR));
9359
DidResize (gpTTYInfo);
9362
/* So I can see with the debugger. */
9363
drc = CommDlgExtendedError();
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)
9372
TCHAR *sep[] = {TEXT(""), TEXT(", ")};
9376
_tcsncpy(fontName, pFont->lfFaceName, nfontName);
9377
fontName[nfontName-1] = '\0';
9380
if(pFont->lfWeight >= FW_BOLD) {
9381
_tcsncpy(fontStyle, TEXT("bold"), nfontStyle);
9382
fontStyle[nfontStyle-1] = '\0';
9386
if(pFont->lfItalic){
9387
_tcsncat(fontStyle, sep[iSep], nfontStyle - _tcslen(fontStyle));
9388
fontStyle[nfontStyle-1] = '\0';
9390
_tcsncat(fontStyle, TEXT("italic"), nfontStyle - _tcslen(fontStyle));
9391
fontStyle[nfontStyle-1] = '\0';
9394
mswin_charsetid2string(fontCharSet, nfontCharSet, pFont->lfCharSet);
9397
*fontSize = MulDiv(-pFont->lfHeight, 72, ppi);
9402
DidResize (PTTYINFO pTTYInfo)
9406
for (i = 0; i < RESIZE_CALLBACK_ARRAY_SIZE; ++i) {
9407
if (pTTYInfo->resizer[i] != NULL)
9408
pTTYInfo->resizer[i] (pTTYInfo->actNRow, pTTYInfo->actNColumn);
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.
9416
CQAdd (MSWIN_KEY_NODATA, 0);
9422
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9424
* Cut, Copy, and Paste operations
9426
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
9430
* Gets called right before the menu is displayed so we can make
9431
* any last minute adjustments.
9434
UpdateMenu (HWND hWnd)
9440
UINT fAccel = EM_NONE;
9443
pTTYInfo = (PTTYINFO) MyGetWindowLongPtr (hWnd, GWL_PTTYINFO);
9444
if (pTTYInfo == NULL)
9447
hMenu = GetMenu (hWnd);
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);
9456
fAccel |= (EM_PST | EM_PST_ABORT);
9461
* Not pasting. If text is available on clipboard and we are
9462
* at a place where we can paste, enable past menu option.
9464
if (IsClipboardFormatAvailable (CF_UNICODETEXT) && gPasteEnabled){
9465
EnableMenuItem (hMenu, IDM_EDIT_PASTE, MF_BYCOMMAND|MF_ENABLED);
9471
EnableMenuItem (hMenu, IDM_EDIT_PASTE, MF_BYCOMMAND|MF_GRAYED);
9473
EnableMenuItem (hMenu, IDM_EDIT_CANCEL_PASTE, MF_BYCOMMAND|MF_GRAYED);
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);
9481
fAccel |= (EM_CP | EM_CP_APPEND);
9486
EnableMenuItem (hMenu, IDM_EDIT_CUT, MF_BYCOMMAND | MF_ENABLED);
9492
EnableMenuItem (hMenu, IDM_EDIT_CUT, MF_BYCOMMAND | MF_GRAYED);
9495
EnableMenuItem (hMenu, IDM_EDIT_COPY, MF_BYCOMMAND | MF_ENABLED);
9496
EnableMenuItem (hMenu, IDM_EDIT_COPY_APPEND,
9497
MF_BYCOMMAND | MF_ENABLED);
9499
fAccel |= (EM_CP | EM_CP_APPEND);
9503
EnableMenuItem (hMenu, IDM_EDIT_COPY, MF_BYCOMMAND | MF_GRAYED);
9504
EnableMenuItem (hMenu, IDM_EDIT_COPY_APPEND,
9505
MF_BYCOMMAND | MF_GRAYED);
9510
* Set up Font selection menu
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);
9518
CheckMenuItem (hMenu, IDM_OPT_FONTSAMEAS,
9519
MF_BYCOMMAND | MF_UNCHECKED);
9520
EnableMenuItem (hMenu, IDM_OPT_SETPRINTFONT,
9521
MF_BYCOMMAND | MF_ENABLED);
9525
* Setup Caret selection menu
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,
9536
* Check toolbar menu.
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));
9548
* Check the dialogs menu.
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));
9555
* Enable the Erase Credentials menu
9557
EnableMenuItem (hMenu, IDM_OPT_ERASE_CREDENTIALS,
9558
MF_BYCOMMAND | (gEraseCredsCallback ? MF_ENABLED : MF_GRAYED));
9560
#ifdef ACCELERATORS_OPT
9561
CheckMenuItem (hMenu, IDM_OPT_USEACCEL, MF_BYCOMMAND |
9562
(pTTYInfo->hAccel ? MF_CHECKED : MF_UNCHECKED));
9566
* Setup the sort menu...
9569
i = (*gSortCallback)(0, 0);
9571
/* NOTE: this func's args are dependent on definition order
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));
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);
9586
* Setup the flag menu...
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));
9600
i = (*gHdrCallback)(0, 0);
9601
CheckMenuItem(hMenu, IDM_MI_HDRMODE,
9602
MF_BYCOMMAND|((i != 0) ? MF_CHECKED : MF_UNCHECKED));
9609
i = (*gZoomCallback)(0, 0);
9610
CheckMenuItem(hMenu, IDM_MI_ZOOM,
9611
MF_BYCOMMAND | (i ? MF_CHECKED : MF_UNCHECKED));
9614
* Set up command menu.
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));
9624
* Special command-specific knowledge here
9626
for(i = IDM_MI_SORTSUBJECT; i <= IDM_MI_SORTREVERSE; i++)
9627
EnableMenuItem (hMenu, i,
9629
| ((pTTYInfo->menuItems[KS_SORT-KS_RANGESTART].miActive)
9630
? MF_ENABLED : MF_GRAYED));
9632
for(i = IDM_MI_FLAGIMPORTANT; i <= IDM_MI_FLAGDELETED; i++)
9633
EnableMenuItem (hMenu, i,
9635
| ((pTTYInfo->menuItems[KS_FLAG - KS_RANGESTART].miActive)
9636
? MF_ENABLED : MF_GRAYED));
9641
* deal with any callback state dependent enabling
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));
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));
9656
if(pTTYInfo->menuItems[KS_WHEREIS - KS_RANGESTART].miActive)
9659
AccelManage (hWnd, fAccel);
9662
pTTYInfo->menuItemsCurrent = TRUE;
9668
* Cut region to kill buffer.
9675
if(gCopyCutFunction == (getc_t)kremove){
9676
hCB = GlobalAlloc (GMEM_MOVEABLE, 0);
9678
kdelete(); /* Clear current kill buffer. */
9679
killregion (1, 0); /* Kill Region (and copy to clipboard). */
9680
update (); /* And update the screen */
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().
9693
mswin_killbuftoclip (getc_t copyfunc)
9698
/* Save old copy function. */
9699
oldfunc = gCopyCutFunction;
9700
gCopyCutFunction = copyfunc;
9702
/* Allocate clip buffer. */
9703
hCB = GlobalAlloc (GMEM_MOVEABLE, 0);
9705
EditDoCopyData (hCB, 0);
9708
/* restore copy function. */
9709
gCopyCutFunction = oldfunc;
9715
* Copy region to kill buffer.
9722
if (SelAvailable()) {
9723
/* This is a copy of the windows selection. */
9724
hCB = GlobalAlloc (GMEM_MOVEABLE, 0);
9730
/* Otherwise, it's a Pico/Pine copy. */
9731
if(gCopyCutFunction == (getc_t)kremove){
9732
kdelete(); /* Clear current kill buffer. */
9736
hCB = GlobalAlloc (GMEM_MOVEABLE, 0);
9738
EditDoCopyData (hCB, 0);
9745
* Called in responce to "Copy Append" menu command, when there is an active
9746
* Windows selection on the screen.
9749
EditCopyAppend (void)
9757
/* Attempt to copy clipboard data to my own handle. */
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);
9772
GlobalFree (hMyCopy);
9777
} /* GetClipboardData. */
9779
} /* OpenClipboard. */
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);
9790
if(gCopyCutFunction == (getc_t)kremove) {
9791
kdelete(); /* Clear current kill buffer. */
9794
EditDoCopyData (hMyCopy, (DWORD)cbSize);
9801
* Copy data from the kill buffer to the clipboard. Handle LF->CRLF
9802
* translation if necessary.
9805
EditDoCopyData (HANDLE hCB, DWORD lenCB)
9809
long c; /* would be TCHAR but needs -1 retval from callback */
9810
TCHAR lastc = (TCHAR)'\0';
9811
DWORD cbSize; /* Allocated size of hCB. */
9813
#define BUF_INC 4096
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);
9821
/* Copy it. (BUG: change int arg) */
9822
for(i = 0L; (c = (*gCopyCutFunction)((int)i)) != -1; i++){
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?
9830
if(lenCB + 2L >= cbSize){
9833
hCB = GlobalReAlloc (hCB, cbSize*sizeof(TCHAR), GMEM_MOVEABLE);
9837
pCB = GlobalLock (hCB);
9841
if(c == (TCHAR)ASCII_LF && lastc != (TCHAR)ASCII_CR) {
9842
*p++ = (TCHAR)ASCII_CR; /* insert CR before LF */
9846
*p++ = lastc = (TCHAR)c;
9850
/* Only if we got some data. */
9855
if (SetClipboardData (CF_UNICODETEXT, hCB) == NULL)
9856
/* Failed! Free the data. */
9860
/* There was no data copied. */
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.
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. */
9896
* If we're paste is enabled but limited to the first
9897
* line of the clipboard, prune the paste buffer...
9899
if(gPasteEnabled == MSWIN_PASTE_LINE
9900
&& (pPaste = _tcschr(gpPasteNext, (TCHAR)ASCII_CR))){
9901
*pPaste = (TCHAR)'\0';
9902
cbSize = _tcslen(gpPasteNext);
9906
* If there is a selection (gCopyCutFunction != NULL)
9907
* then delete it so that it will be replaced by
9910
if (gCopyCutFunction != NULL)
9911
deleteregion (1, 0);
9913
gPasteBytesRemain = cbSize;
9914
gPasteWasCR = FALSE;
9916
if (mswin_debug > 8)
9917
fprintf (mswin_debugfile, "EditPaste:: Paste %d bytes\n",
9934
* Cancel an active paste operation.
9937
EditCancelPaste (void)
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. */
9946
if (mswin_debug > 8)
9947
fprintf (mswin_debugfile, "EditCancelPaste:: Free Paste Data\n");
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.
9961
TCHAR b = MSWIN_KEY_NODATA;
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) {
9971
b = (TCHAR) *gpPasteNext++;
9972
--gPasteBytesRemain;
9975
b = MSWIN_KEY_NODATA; /* Ignore last LF. */
9977
gPasteWasCR = (b == (TCHAR)ASCII_CR);
9979
if (mswin_debug > 8)
9980
fprintf (mswin_debugfile, "EditPasteGet:: char %c, gPasteWasCR %d, gPasteBytesRemain %d\n",
9981
b, gPasteWasCR, gPasteBytesRemain);
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. */
9991
if (mswin_debug > 8)
9992
fprintf (mswin_debugfile, "EditPasteGet:: Free Paste Data\n");
10001
* Return true if Paste data is available. If gpPaste != NULL then there
10005
EditPasteAvailable (void)
10007
return (ghPaste != NULL);
10013
* Select everything in the buffer
10018
if(ComposerEditing){
10024
update (); /* And update the screen */
10031
SortHandler(int order, int reverse)
10033
int old = (*gSortCallback)(0, 0);
10036
old ^= 0x0100; /* flip reverse bit */
10037
(*gSortCallback)(1, old);
10040
(*gSortCallback)(1, order | (old & 0x0100));
10046
FlagHandler(int index, int args)
10048
(void) (*gFlagCallback)(index + 1, 0L);
10055
MSWHelpShow (cbstr_t fpHelpCallback)
10057
if (fpHelpCallback != NULL){
10058
char title[256], *help;
10060
if(help = (*fpHelpCallback) (title))
10061
mswin_displaytext (title, help, strlen(help), NULL, NULL, 0);
10069
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
10071
* Adjust the timer frequency as needed.
10073
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
10079
/* Decide on period to use. */
10080
if (gAllowMouseTrack)
10081
period = MY_TIMER_EXCEEDINGLY_SHORT_PERIOD;
10083
period = my_timer_period;
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);
10090
gTimerCurrentPeriod = period;
10099
mswin_setperiodiccallback (cbvoid_t periodiccb, long period)
10101
if (periodiccb != NULL && period > 0) {
10102
gPeriodicCallback = periodiccb;
10103
gPeriodicCBTime = period;
10104
gPeriodicCBTimeout = GetTickCount () / 1000 + gPeriodicCBTime;
10107
gPeriodicCallback = NULL;
10113
* Execute command and wait for the child to exit
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
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
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)
10135
TCHAR waitingFor[256];
10136
STARTUPINFO start_info;
10137
PROCESS_INFORMATION proc_info;
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;
10146
memset(&proc_info, 0, sizeof(proc_info));
10147
memset(&start_info, 0, sizeof(start_info));
10148
memset(&atts, 0, sizeof(atts));
10150
start_info.dwFlags = STARTF_FORCEONFEEDBACK | STARTF_USESHOWWINDOW;
10151
start_info.wShowWindow = (utf8_infile || utf8_outfile) ? SW_SHOWMINNOACTIVE
10154
/* set file attributes of temp files*/
10155
atts.nLength = sizeof(SECURITY_ATTRIBUTES);
10156
atts.bInheritHandle = TRUE;
10157
atts.lpSecurityDescriptor = NULL;
10159
/* open files if asked for */
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)){
10166
fs_give((void **) &lptstr_infile);
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)){
10178
fs_give((void **) &lptstr_infile);
10181
fs_give((void **) &lptstr_outfile);
10186
/* set up i/o redirection */
10188
start_info.hStdInput = infd;
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;
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)
10200
CREATE_NEW_CONSOLE | CREATE_NEW_PROCESS_GROUP,
10201
NULL, NULL, &start_info, &proc_info) == TRUE){
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);
10207
/* Don't need the thread handle, close it now. */
10208
CloseHandle (proc_info.hThread);
10211
* Go into holding pattern until the other application terminates
10212
* or we are told to stop waiting.
10214
while(GetExitCodeProcess(proc_info.hProcess, &exit_code) == TRUE){
10215
if(exit_code == STILL_ACTIVE){
10217
brc = mswin_getmouseevent (&mouse);
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 */
10226
rc = MessageBox (ghTTYWnd, waitingFor, lptstr_whatsit,
10227
MB_ICONSTOP | MB_OKCANCEL);
10230
if (rc == IDCANCEL){
10231
/* terminate message to child ? */
10235
CloseHandle(outfd);
10237
fs_give((void **) &lptstr_infile);
10239
fs_give((void **) &lptstr_outfile);
10241
fs_give((void **) &lptstr_whatsit);
10243
fs_give((void **) &lptstr_command);
10249
/* do something about child's exit status */
10250
CloseHandle (proc_info.hProcess);
10252
*exit_val = exit_code;
10257
if (gpTTYInfo->fMinimized)
10258
ShowWindow (ghTTYWnd, SW_SHOWNORMAL);
10260
BringWindowToTop (ghTTYWnd);
10264
CloseHandle(outfd);
10266
fs_give((void **) &lptstr_infile);
10268
fs_give((void **) &lptstr_outfile);
10270
fs_give((void **) &lptstr_whatsit);
10272
fs_give((void **) &lptstr_command);
10279
CloseHandle(outfd);
10280
_tunlink(lptstr_outfile);
10283
fs_give((void **) &lptstr_infile);
10285
fs_give((void **) &lptstr_outfile);
10287
fs_give((void **) &lptstr_whatsit);
10289
fs_give((void **) &lptstr_command);
10290
return((rc = (int) GetLastError()) ? rc : -1); /* hack */
10296
mswin_shell_exec(char *command_utf8, HINSTANCE *pChildProc)
10299
SHELLEXECUTEINFO shell_info;
10300
LPTSTR command_lpt, free_command_lpt;
10301
LPTSTR p, q, parm = NULL;
10307
free_command_lpt = command_lpt = utf8_to_lptstr(command_utf8);
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...
10318
if(*(p = command_lpt) == '\"'){
10319
p = ++command_lpt; /* don't include quote */
10325
if(!quoted && _istspace(*p)){
10329
buf_utf8 = lptstr_to_utf8(buf);
10330
if(*buf == '*' || (buf_utf8 && fexist(buf_utf8, "x", (off_t *) NULL) == FIOSUC)){
10333
fs_give((void **) &buf_utf8);
10339
fs_give((void **) &buf_utf8);
10341
else if(quoted && *p == '\"'){
10345
else if(!(*q++ = *p++)){
10350
if(*command_lpt && parm){
10353
while(*parm && _istspace((unsigned char) *parm));
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.
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;
10370
if(free_command_lpt)
10371
fs_give((void **) &free_command_lpt);
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;
10387
ShellExecuteEx(&shell_info);
10389
if((int)(LONG_PTR)shell_info.hInstApp > 32){
10391
*pChildProc = shell_info.hProcess;
10393
if(free_command_lpt)
10394
fs_give((void **) &free_command_lpt);
10396
return(0); /* success! */
10399
if(free_command_lpt)
10400
fs_give((void **) &free_command_lpt);
10407
* Generate an error message for a failed windows exec or loadlibrary.
10410
mswin_exec_err_msg(char *what, int status, char *buf, size_t buflen)
10415
snprintf(buf, buflen, "%s not found.", what);
10419
snprintf(buf, buflen, "Not enough memory to run %s.", what);
10423
snprintf(buf, buflen, "Error %d starting %s.", status, what);
10430
mswin_set_quit_confirm (int confirm)
10432
gConfirmExit = (confirm != 0);
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.
10451
_sntprintf(msg, sizeof(msg)/sizeof(TCHAR),
10452
TEXT("Exiting may cause you to lose work in %s, Exit?"),
10454
rc = MessageBox (ghTTYWnd, msg, gszAppName, MB_ICONSTOP | MB_OKCANCEL);
10463
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
10465
* Registry access functions
10467
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
10472
#define MSWR_KEY_MAX 128
10473
#define MSWR_VAL_MAX 128
10474
#define MSWR_CLASS_MAX 128
10475
#define MSWR_DATA_MAX 1024
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
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 */
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"),
10501
{HKEY_LOCAL_MACHINE,
10502
TEXT("Software\\Clients\\Mail\\Alpine\\Protocols\\Mailto\\shell\\open\\command"),
10504
{HKEY_LOCAL_MACHINE,
10505
TEXT("Software\\Clients\\Mail\\Alpine\\shell\\open\\command"),
10507
{HKEY_LOCAL_MACHINE,
10508
TEXT("Software\\Clients\\News\\Alpine"),
10510
{HKEY_LOCAL_MACHINE,
10511
TEXT("Software\\Clients\\News\\Alpine\\Protocols\\news\\DefaultIcon"),
10513
{HKEY_LOCAL_MACHINE,
10514
TEXT("Software\\Clients\\News\\Alpine\\Protocols\\news\\shell\\open\\command"),
10516
{HKEY_LOCAL_MACHINE,
10517
TEXT("Software\\Clients\\News\\Alpine\\Protocols\\nntp\\DefaultIcon"),
10519
{HKEY_LOCAL_MACHINE,
10520
TEXT("Software\\Clients\\News\\Alpine\\Protocols\\nntp\\shell\\open\\command"),
10522
{HKEY_LOCAL_MACHINE,
10523
TEXT("Software\\Clients\\News\\Alpine\\shell\\open\\command"),
10525
{NULL, NULL, {NULL}}
10530
* data: unitialized buffer, could be null
10533
mswin_reg(int op, int tree, char *data_utf8, size_t size)
10535
LPTSTR data_lptstr = NULL;
10540
/* size is zero when op & MSWR_OP_SET */
10541
data_lptstr = utf8_to_lptstr(data_utf8);
10544
data_lptstr = (LPTSTR)MemAlloc(size * sizeof(TCHAR));
10545
data_lptstr[0] = '\0';
10549
rv = mswin_reg_lptstr(op, tree, data_lptstr, size);
10551
if(data_utf8 && data_lptstr){
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);
10559
MemFree((void *)data_lptstr);
10565
mswin_reg_lptstr(int op, int tree, LPTSTR data_lptstr, size_t size)
10567
if(op & MSWR_OP_SET){
10569
case MSWR_PINE_RC :
10570
MSWRAlpineSet(HKEY_CURRENT_USER, NULL,
10571
TEXT("PineRC"), op & MSWR_OP_FORCE, data_lptstr);
10574
case MSWR_PINE_CONF :
10575
MSWRAlpineSet(HKEY_CURRENT_USER, NULL,
10576
TEXT("PineConf"), op & MSWR_OP_FORCE, data_lptstr);
10579
case MSWR_PINE_AUX :
10580
MSWRAlpineSet(HKEY_CURRENT_USER, NULL,
10581
TEXT("PineAux"), op & MSWR_OP_FORCE, data_lptstr);
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);
10590
case MSWR_PINE_EXE :
10591
MSWRAlpineSet(HKEY_LOCAL_MACHINE, NULL,
10592
TEXT("PineEXE"), op & MSWR_OP_FORCE, data_lptstr);
10595
case MSWR_PINE_POS :
10596
MSWRAlpineSet(HKEY_CURRENT_USER, NULL,
10597
TEXT("PinePos"), op & MSWR_OP_FORCE, data_lptstr);
10604
else if(op & MSWR_OP_GET){
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));
10628
else if(op & MSWR_OP_BLAST){
10631
/* UN-Register as a mail client on this system */
10633
MSWRClear(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Clients\\Mail\\Alpine"));
10635
/* UN-Register as a news client on this system */
10637
MSWRClear(HKEY_LOCAL_MACHINE, TEXT("SOFTWARE\\Clients\\News\\Alpine"));
10639
/* UN-Register as a IMAP url handler */
10641
MSWRClear(HKEY_CLASSES_ROOT, TEXT("imap"));
10644
MSWRClear(HKEY_LOCAL_MACHINE, MSWR_ROOT);
10647
MSWRClear(HKEY_CURRENT_USER, MSWR_ROOT);
10650
/* else, ignore unknown op? */
10657
* Dump all of the registry values into an array of strings.
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];
10668
unsigned long tmpreglen = MSWR_DATA_MAX, tmpbuflen = MSWRDBUF;
10669
char **regtext_utf8;
10671
/* approximate how many lines we're going to need */
10672
while(mswin_pine_regs[i].rkey){
10675
while(mswin_pine_regs[i].rnames[j]){
10681
regtext = (LPTSTR *)MemAlloc((lines+1) * sizeof(LPTSTR));
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){
10700
while(mswin_pine_regs[i].rnames[j]){
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);
10712
tmpreglen = MSWR_DATA_MAX;
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);
10722
_sntprintf(tmpbuf, tmpbuflen, TEXT(""));
10723
regtext[tlines] = (LPTSTR)MemAlloc((_tcslen(tmpbuf) + 1) * sizeof(TCHAR));
10724
_tcsncpy(regtext[tlines++], tmpbuf, _tcslen(tmpbuf)+1);
10727
regtext[tlines] = NULL;
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++){
10733
regtext_utf8[i] = lptstr_to_utf8(regtext[i]);
10734
MemFree((void *)regtext[i]);
10737
regtext_utf8[i] = NULL;
10739
regtext_utf8[lines] = NULL;
10740
MemFree((void *)regtext);
10742
return regtext_utf8;
10748
MSWRAlpineSet(HKEY hRootKey, LPTSTR subkey, LPTSTR val, int update, LPTSTR data)
10751
TCHAR keybuf[MSWR_KEY_MAX+1];
10753
_sntprintf(keybuf, MSWR_KEY_MAX+1, TEXT("%s%s%s"), MSWR_ROOT,
10754
(subkey && *subkey != '\\') ? TEXT("\\") : TEXT(""),
10755
(subkey) ? TEXT("\\") : TEXT(""));
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));
10771
MSWRAlpineGet(HKEY hKey, LPTSTR subkey, LPTSTR val, LPTSTR data_lptstr, size_t len)
10773
TCHAR keybuf[MSWR_KEY_MAX+1];
10774
DWORD dlen = (DWORD)len;
10776
_sntprintf(keybuf, MSWR_KEY_MAX+1, TEXT("%s%s%s"), MSWR_ROOT,
10777
(subkey && *subkey != '\\') ? TEXT("\\") : TEXT(""),
10778
(subkey) ? TEXT("\\") : TEXT(""));
10780
return(MSWRPeek(hKey, keybuf, val, data_lptstr, &dlen) == TRUE);
10786
MSWRAlpineSetHandlers(int update, LPTSTR path_lptstr)
10788
HKEY hKey, hSubKey;
10790
BYTE tmp_b[MSWR_DATA_MAX];
10791
unsigned long tmplen = MSWR_DATA_MAX, tmp_lptstr_tcharlen = MSWR_DATA_MAX/sizeof(TCHAR);
10793
LPTSTR tmp_lptstr = (LPTSTR)tmp_b;
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"),
10802
REG_OPTION_NON_VOLATILE, KEY_ALL_ACCESS,
10803
NULL, &hKey, &dwDisp) == ERROR_SUCCESS){
10804
if(update || !exists){
10806
char *tmp_utf8str = NULL;
10808
MSWRPoke(hKey, NULL, NULL, MSWR_APPNAME);
10809
/* set up MAPI dll stuff */
10811
RegQueryValueEx(hKey, MSWR_DLLPATH, NULL, &dType, tmp_b, &tmplen);
10812
tmp_lptstr = (LPTSTR)tmp_b;
10814
|| (can_access(tmp_utf8str = lptstr_to_utf8(tmp_lptstr), ACCESS_EXISTS) != 0)){
10816
RegDeleteValue(hKey, MSWR_DLLPATH);
10818
MemFree((void *)tmp_utf8str);
10820
_sntprintf(tmp_lptstr, tmp_lptstr_tcharlen,
10821
TEXT("%s%s"), path_lptstr, MSWR_DLLNAME);
10823
if(can_access(tmp_utf8str = lptstr_to_utf8(tmp_lptstr), ACCESS_EXISTS) == 0)
10824
MSWRPoke(hKey, NULL, MSWR_DLLPATH, tmp_lptstr);
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);
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);
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);
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);
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);
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);
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);
10896
mswin_reg_default_browser(char *url_utf8)
10898
TCHAR scheme[MSWR_KEY_MAX+1], *p;
10900
char cmdbuf[MSWR_DATA_MAX], *cmd = NULL;
10902
url_lptstr = utf8_to_lptstr(url_utf8);
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';
10908
if(MSWRShellCanOpen(scheme, cmdbuf, MSWR_DATA_MAX, 0)){
10911
len = strlen(cmdbuf) + 2;
10912
cmd = (char *) fs_get((len+1) * sizeof(char));
10914
if(strchr(cmdbuf, '*'))
10915
snprintf(cmd, len+1, "\"%s\"", cmdbuf);
10917
strncpy(cmd, cmdbuf, len);
10924
MemFree((void *)url_lptstr);
10931
mswin_is_def_client(int type)
10933
TCHAR buf[MSWR_KEY_MAX+1];
10934
DWORD buflen = MSWR_KEY_MAX;
10936
if(type != MSWR_SDC_MAIL && type != MSWR_SDC_NEWS)
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")))
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")))
10954
mswin_set_def_client(int type)
10957
int successful_set = 0;
10958
TCHAR path_lptstr[MSWR_DATA_MAX];
10961
if(type != MSWR_SDC_MAIL && type != MSWR_SDC_NEWS)
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"));
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"));
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);
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);
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);
11009
MSWRProtocolSet(HKEY hKey, int type, LPTSTR path_lptstr)
11011
TCHAR tmp_lptstr[MSWR_DATA_MAX];
11013
unsigned long tmp_lptstr_len = MSWR_DATA_MAX;
11015
if(type != MSWR_SDC_MAIL && type != MSWR_SDC_NEWS
11016
&& type != MSWR_SDC_NNTP && type != MSWR_SDC_IMAP)
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(""));
11025
EditFlags[0] = 0x02;
11026
EditFlags[1] = EditFlags[2] = EditFlags[3] = 0;
11028
(void) RegDeleteValue(hKey, TEXT("EditFlags"));
11029
(void) RegSetValueEx(hKey, TEXT("EditFlags"), 0, REG_BINARY,
11030
EditFlags, (DWORD) 4);
11032
_sntprintf(tmp_lptstr, tmp_lptstr_len,
11033
TEXT("%salpine.exe,0"), path_lptstr);
11034
MSWRPoke(hKey, TEXT("DefaultIcon"), NULL, tmp_lptstr);
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);
11043
/* cmdbuf can stay char * since it's our string */
11045
MSWRShellCanOpen(LPTSTR key, char *cmdbuf, int clen, int allow_noreg)
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){
11055
strncpy(cmdbuf, "*Shell*", clen);
11056
cmdbuf[clen-1] = '\0';
11063
else if(allow_noreg && cmdbuf){
11064
strncpy(cmdbuf, "*Shell*", clen);
11065
cmdbuf[clen-1] = '\0';
11074
* Fundamental registry access function that queries for particular values.
11077
MSWRPeek(HKEY hRootKey, LPTSTR subkey, LPTSTR valstr, LPTSTR data_lptstr, DWORD *dlen)
11080
DWORD dtype, dlen_bytes = (dlen ? *dlen : 0) * (*dlen)*sizeof(TCHAR);
11081
LONG rv = !ERROR_SUCCESS;
11083
if(RegOpenKeyEx(hRootKey, subkey, 0, KEY_READ, &hKey) == ERROR_SUCCESS){
11084
rv = RegQueryValueEx(hKey, valstr, NULL, &dtype, (LPBYTE)data_lptstr, &dlen_bytes);
11086
(*dlen) = dlen_bytes;
11090
return(rv == ERROR_SUCCESS);
11095
* Fundamental registry access function that sets particular values.
11098
MSWRPoke(HKEY hKey, LPTSTR subkey, LPTSTR valstr, LPTSTR data_lptstr)
11100
DWORD dtype, dwDisp, dlen = MSWR_DATA_MAX;
11101
BYTE olddata[MSWR_DATA_MAX];
11105
|| RegCreateKeyEx(hKey, subkey,
11106
0, TEXT("REG_SZ"), REG_OPTION_NON_VOLATILE,
11107
KEY_ALL_ACCESS, NULL,
11108
&hKey, &dwDisp) == ERROR_SUCCESS){
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;
11129
* Fundamental registry access function that removes a registry key
11130
* and all its subkeys, their values and data
11133
MSWRClear(HKEY hKey, LPTSTR pSubKey)
11136
TCHAR KeyBuf[MSWR_KEY_MAX+1];
11137
DWORD dwKeyIndex, dwKeyLen;
11138
FILETIME ftKeyTime;
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){
11154
RegCloseKey(hSubKey);
11155
if(RegDeleteKey(hKey, pSubKey) != ERROR_SUCCESS || rv)
11165
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11167
* Text display Windows.
11169
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
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.
11177
mswin_showhelpmsg(WINHAND wnd, char **helplines)
11180
char *helptext_utf8, *p;
11183
LPTSTR helptext_lpt;
11190
for(l = helplines; *l != NULL; ++l)
11191
buflen += (strlen(*l)+1);
11193
helptext_utf8 = (char *) fs_get((buflen + 1) * sizeof(char));
11194
if(helptext_utf8 == NULL)
11197
*helptext_utf8 = '\0';
11200
for(l = helplines; *l != NULL; ++l){
11201
snprintf(p, buflen+1-(p-helptext_utf8), "%s%s", (p == helptext_utf8) ? "" : " ", *l);
11205
helptext_lpt = utf8_to_lptstr(helptext_utf8);
11207
MessageBox(hWnd, helptext_lpt, TEXT("Help"),
11208
MB_APPLMODAL | MB_ICONINFORMATION | MB_OK);
11210
fs_give((void **) &helptext_utf8);
11211
fs_give((void **) &helptext_lpt);
11215
* Callback for when new mail or imap telem window gets canned.
11218
mswin_tw_close_imap_telem_or_new_mail(MSWIN_TEXTWINDOW *mswin_tw)
11222
if((mswin_tw->id == IDM_OPT_IMAPTELEM) && gIMAPDebugOFFCallback)
11223
(*gIMAPDebugOFFCallback)();
11225
if(hMenu = GetMenu(ghTTYWnd))
11226
CheckMenuItem (hMenu, mswin_tw->id, MF_BYCOMMAND | MF_UNCHECKED);
11230
* Callback for when new mail or imap telem window gets cleared.
11233
mswin_tw_clear_imap_telem_or_new_mail(MSWIN_TEXTWINDOW *mswin_tw)
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");
11241
tmtxt = ctime(&now);
11243
mswin_tw_printf(mswin_tw, TEXT("%s started at %.*S"),
11244
desc, MIN(100, strlen(tmtxt)-1), tmtxt);
11246
if(mswin_tw->id == IDM_OPT_NEWMAILWIN)
11249
int fromlen, subjlen, foldlen, len;
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;
11257
mswin_tw_printf(mswin_tw,
11258
TEXT(" %-*s%-*s%-*s"),
11259
fromlen, TEXT("From:"),
11260
subjlen, TEXT("Subject:"),
11261
foldlen, TEXT("Folder:"));
11263
len = 2 + fromlen + subjlen + foldlen;
11264
if(len >= ARRAYSIZE(ring2) + 1)
11265
len = ARRAYSIZE(ring2) - 2;
11266
for(i = 0; i < len; i++)
11269
mswin_tw_puts_lptstr(mswin_tw, ring2);
11274
* Init new mail or imap telem window
11277
mswin_tw_init(MSWIN_TEXTWINDOW *mswin_tw, int id, LPCTSTR title)
11279
if(mswin_tw->hwnd){
11281
mswin_tw_close(mswin_tw);
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;
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))
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;
11308
if(!mswin_tw_create(mswin_tw, title))
11311
mswin_tw_setfont(mswin_tw, gpTTYInfo->hTTYFont);
11312
mswin_tw_setcolor(mswin_tw, gpTTYInfo->rgbFGColor, gpTTYInfo->rgbBGColor);
11314
mswin_tw_clear(mswin_tw);
11316
if(id == IDM_OPT_IMAPTELEM)
11318
if(gIMAPDebugONCallback)
11319
(*gIMAPDebugONCallback)();
11321
mswin_tw_showwindow(mswin_tw, SW_SHOWNA);
11323
else if(id == IDM_OPT_NEWMAILWIN){
11324
mswin_tw_showwindow(mswin_tw, SW_SHOW);
11327
if(hMenu = GetMenu(ghTTYWnd))
11328
CheckMenuItem (hMenu, mswin_tw->id, MF_BYCOMMAND | MF_CHECKED);
11335
* Display text in a window.
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
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.
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
11358
* mswin_tw - SUCCESS
11362
mswin_displaytext(char *title_utf8, char *pText_utf8, size_t npText,
11363
char **pLines_utf8, MSWIN_TEXTWINDOW *mswin_tw, int flags)
11365
LPTSTR title_lpt = NULL, pText_lpt = NULL, *pLines_lpt = NULL;
11367
size_t pText_lpt_len = 0;
11370
if(pLines_utf8 != NULL){
11371
for(count=0, l = pLines_utf8; *l != NULL; ++l)
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);
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);
11384
fs_give((void **) &pLines_utf8);
11388
if(pText_utf8 != NULL && npText > 0){
11389
pText_lpt = utf8_to_lptstr(pText_utf8);
11390
pText_lpt_len = lstrlen(pText_lpt);
11392
/*caller expects this to be freed */
11393
if(!(flags & MSWIN_DT_NODELETE))
11394
fs_give((void **) &pText_utf8);
11397
if(title_utf8 != NULL)
11398
title_lpt = utf8_to_lptstr(title_utf8);
11400
mswin_tw = mswin_tw_displaytext_lptstr(title_lpt, pText_lpt, pText_lpt_len,
11401
pLines_lpt, mswin_tw, flags);
11403
if(pLines_lpt != NULL){
11404
for(i=0; i < count; ++i)
11406
fs_give((void **) &pLines_lpt[i]);
11408
fs_give((void **) &pLines_lpt);
11411
if(pText_lpt != NULL)
11412
fs_give((void **) &pText_lpt);
11414
if(title_lpt != NULL)
11415
fs_give((void **) &title_lpt);
11421
* Callback for when a generic mswin_tw gets killed.
11424
mswin_tw_close_callback(MSWIN_TEXTWINDOW *mswin_tw)
11426
if(mswin_tw->id != -1)
11431
* Create a new mswin_tw window. If the MSWIN_DT_USEALTWINDOW flag is set,
11432
* then (re)use gMswinAltWin.
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)
11438
if (pText == NULL && pLines == NULL)
11441
/* Was a valid existing window supplied? */
11444
int ctrl_down = GetKeyState(VK_CONTROL) < 0;
11446
if((flags & MSWIN_DT_USEALTWINDOW) && !ctrl_down)
11448
mswin_tw = &gMswinAltWin;
11449
mswin_tw->id = (UINT)-1; // Tell mswin_tw_close_callback not
11450
// to free this buffer.
11454
mswin_tw = (MSWIN_TEXTWINDOW *)MemAlloc (sizeof (MSWIN_TEXTWINDOW));
11458
memset(mswin_tw, 0, sizeof(MSWIN_TEXTWINDOW));
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;
11468
/* Create a new window. */
11469
if (!mswin_tw->hwnd) {
11471
if(IsRectEmpty(&mswin_tw->rcSize))
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;
11484
if(!mswin_tw_create(mswin_tw, title)) {
11485
MemFree (mswin_tw);
11489
mswin_tw_setfont(mswin_tw, gpTTYInfo->hTTYFont);
11490
mswin_tw_setcolor(mswin_tw, gpTTYInfo->rgbFGColor, gpTTYInfo->rgbBGColor);
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);
11498
mswin_tw_clear(mswin_tw);
11501
* How was text supplied?
11503
if (pLines != NULL) {
11506
/* Array of pointers to lines supplied. Count lines. */
11507
for (l = pLines; *l != NULL; ++l){
11508
mswin_tw_puts_lptstr(mswin_tw, *l);
11512
/* Pointer to block of text supplied. */
11513
mswin_tw_puts_lptstr(mswin_tw, pText);
11516
mswin_tw_setsel(mswin_tw, 0, 0);
11518
mswin_tw_showwindow(mswin_tw, SW_SHOW);
11523
mswin_enableimaptelemetry(int state)
11526
MENUITEMINFO mitem;
11530
hMenu = GetMenu (ghTTYWnd);
11535
* Make sure hMenu's the right menubar
11537
mitem.cbSize = sizeof(MENUITEMINFO);
11538
mitem.fMask = (MIIM_SUBMENU | MIIM_TYPE);
11539
mitem.fType = MFT_STRING;
11540
mitem.dwTypeData = buf;
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;
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);
11559
mitem.fMask = (MIIM_TYPE | MIIM_ID);
11560
mitem.fType = MFT_STRING;
11561
mitem.wID = IDM_OPT_IMAPTELEM;
11562
mitem.dwTypeData = TEXT("&IMAP Telemetry");
11564
InsertMenuItem (hMenu, 9, TRUE, &mitem);
11566
DrawMenuBar (ghTTYWnd);
11568
else if(state == FALSE && i == 10){
11569
DeleteMenu (hMenu, 8, MF_BYPOSITION);
11570
DeleteMenu (hMenu, IDM_OPT_IMAPTELEM, MF_BYCOMMAND);
11571
DrawMenuBar (ghTTYWnd);
11576
mswin_imaptelemetry(char *msg)
11578
if(gMswinIMAPTelem.hwnd){
11580
msg_lptstr = utf8_to_lptstr(msg);
11581
mswin_tw_puts_lptstr(&gMswinIMAPTelem, msg_lptstr);
11582
fs_give((void **) &msg_lptstr);
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.
11598
format_newmail_string(LPTSTR orig_lptstr, int format_len)
11603
new_lptstr = (LPTSTR)MemAlloc((format_len+1)*sizeof(TCHAR));
11606
* Fill up string till we reach the format_len, we can backtrack
11607
* if we need elipses.
11609
for(i = 0, colLen = 0;
11610
i < format_len && colLen < format_len && orig_lptstr && orig_lptstr[i];
11612
new_lptstr[i] = orig_lptstr[i];
11613
colLen += wcellwidth(new_lptstr[i]);
11616
if(colLen > format_len || (colLen == format_len && orig_lptstr[i])){
11618
* If we hit the edge of the format and there's still stuff
11619
* to write, go back and add ".."
11622
if(wcellwidth(new_lptstr[i]) > 1){
11623
colLen -= wcellwidth(new_lptstr[i]);
11626
colLen -= wcellwidth(new_lptstr[i]);
11628
colLen -= wcellwidth(new_lptstr[i]);
11630
while(colLen < format_len && i < format_len){
11631
new_lptstr[i++] = '.';
11637
* If we've hit the end of the string, add spaces until
11638
* we get to the correct length.
11640
for(; colLen < format_len && i < format_len; i++, colLen++){
11641
new_lptstr[i] = ' ';
11645
if(i <= format_len)
11646
new_lptstr[i] = '\0';
11648
new_lptstr[format_len] = '\0';
11650
return(new_lptstr);
11654
* We're passed the relevant fields, now format them according to window with
11655
* and put up for display
11658
mswin_newmailwin(int is_us, char *from_utf8, char *subject_utf8, char *folder_utf8)
11661
int foldlen, fromlen, subjlen;
11662
LPTSTR from_lptstr = NULL, subject_lptstr = NULL, folder_lptstr = NULL;
11663
LPTSTR from_format, subject_format, folder_format;
11665
if(!gMswinNewMailWin.hwnd)
11669
from_lptstr = utf8_to_lptstr(from_utf8);
11671
subject_lptstr = utf8_to_lptstr(subject_utf8);
11673
folder_lptstr = utf8_to_lptstr(folder_utf8);
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;
11682
from_format = format_newmail_string(from_lptstr
11683
? from_lptstr : TEXT(""),
11685
subject_format = format_newmail_string(subject_lptstr
11686
? subject_lptstr : TEXT("(no subject)"),
11688
folder_format = format_newmail_string(folder_lptstr
11689
? folder_lptstr : TEXT("INBOX"),
11692
_sntprintf(tcbuf, 256, TEXT("%c %s %s %s"), is_us ? '+' : ' ',
11693
from_format, subject_format, folder_format);
11696
fs_give((void **) &from_lptstr);
11698
fs_give((void **) &subject_lptstr);
11700
fs_give((void **) &folder_lptstr);
11701
MemFree((void *)from_format);
11702
MemFree((void *)subject_format);
11703
MemFree((void *)folder_format);
11705
mswin_tw_puts_lptstr(&gMswinNewMailWin, tcbuf);
11710
* Mouse up, end selection
11714
mswin_tw_print_callback(MSWIN_TEXTWINDOW *mswin_tw)
11719
#define DESC_LEN 180
11720
TCHAR description[DESC_LEN+1];
11722
GetWindowText(mswin_tw->hwnd, description, DESC_LEN);
11724
rc = mswin_print_ready((WINHAND)mswin_tw->hwnd, description);
11726
if (rc != PE_USER_CANCEL) {
11729
e = utf8_to_lptstr(mswin_print_error(rc));
11731
_sntprintf(description, DESC_LEN+1, TEXT("Printing failed: %s"), e);
11732
fs_give((void **) &e);
11735
MessageBox(mswin_tw->hwnd, description, TEXT("Print Failed"),
11736
MB_OK | MB_ICONEXCLAMATION);
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);
11747
mswin_print_done();
11751
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11755
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11760
UCS c; /* Bigger than TCHAR for CTRL and MENU setting */
11763
LOCAL CQEntry CQBuffer [CHARACTER_QUEUE_LENGTH];
11769
/*---------------------------------------------------------------------------
11773
* Initialize the Character queue.
11778
/*--------------------------------------------------------------------------*/
11788
/*---------------------------------------------------------------------------
11789
* BOOL CQAvailable (void)
11792
* Return TRUE if there are characters in the queue.
11797
/*--------------------------------------------------------------------------*/
11802
return (CQCount > 0);
11807
/*---------------------------------------------------------------------------
11808
* BOOL CQAdd (WORD c, DWORC keyData)
11811
* Add 'c' to the end of the character queue.
11814
* return true if successfull.
11816
/*--------------------------------------------------------------------------*/
11819
CQAdd (UCS c, DWORD keyData)
11821
if (CQCount == CHARACTER_QUEUE_LENGTH)
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;
11840
/*---------------------------------------------------------------------------
11841
* BOOL CQAddUniq (WORD c, DWORC keyData)
11844
* Add 'c' to the end of the character queue, only if
11845
* there is no other 'c' in the queue
11848
* return true if successfull.
11850
/*--------------------------------------------------------------------------*/
11853
CQAddUniq (UCS c, DWORD keyData)
11858
if (CQCount == CHARACTER_QUEUE_LENGTH)
11862
for (i = 0; i < CQCount; ++i) {
11863
if (CQBuffer[pos].c == c)
11865
pos = (pos + 1) % CHARACTER_QUEUE_LENGTH;
11867
return (CQAdd (c, keyData));
11873
/*---------------------------------------------------------------------------
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.
11884
/*--------------------------------------------------------------------------*/
11894
c = CQBuffer[CQHead].c;
11895
CQHead = (CQHead + 1) % CHARACTER_QUEUE_LENGTH;
11902
/*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11904
* Mouse Event Queue
11906
*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11910
LOCAL MEvent MQBuffer [MOUSE_QUEUE_LENGTH];
11916
/*---------------------------------------------------------------------------
11920
* Initialize the Character queue.
11925
/*--------------------------------------------------------------------------*/
11935
/*---------------------------------------------------------------------------
11936
* BOOL MQAvailable (void)
11939
* Return TRUE if there are characters in the queue.
11944
/*--------------------------------------------------------------------------*/
11949
return (MQCount > 0);
11954
/*---------------------------------------------------------------------------
11958
* Add 'c' to the end of the character queue.
11961
* return true if successfull.
11963
/*--------------------------------------------------------------------------*/
11966
MQAdd (int mevent, int button, int nRow, int nColumn, int keys, int flags)
11970
BOOL found = FALSE;
11974
* Find a queue insertion point.
11976
if (flags & MSWIN_MF_REPLACING) {
11977
/* Search for same event on queue. */
11978
for ( i = MQHead, c = MQCount;
11980
i = (i + 1) % MOUSE_QUEUE_LENGTH, --c) {
11981
if (MQBuffer[i].event == mevent) {
11988
if (MQCount == MOUSE_QUEUE_LENGTH)
11991
MQTail = (MQTail + 1) % MOUSE_QUEUE_LENGTH;
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;
12007
* Keep record of last mouse position.
12009
gMTEvent = MQBuffer[i];
12018
/*---------------------------------------------------------------------------
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.
12029
/*--------------------------------------------------------------------------*/
12032
MQGet (MEvent * pMouse)
12038
*pMouse = MQBuffer[MQHead];
12039
MQHead = (MQHead + 1) % MOUSE_QUEUE_LENGTH;
12053
void *lpMsgBuf = NULL;
12054
status = GetLastError();
12057
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
12060
MAKELANGID(LANG_NEUTRAL,SUBLANG_DEFAULT),
12061
(LPTSTR) &lpMsgBuf, 0, NULL);
12066
msg = lptstr_to_utf8(lpMsgBuf);
12068
mswin_messagebox(msg, 1);
12069
fs_give((void **) &msg);
12072
LocalFree(lpMsgBuf);
12080
* Called by mswin to scroll text in window in responce to the scrollbar.
12082
* Args: cmd - what type of scroll operation.
12083
* scroll_pos - paramter for operation.
12084
* used as position for SCROLL_TO operation.
12086
* Returns: TRUE - did the scroll operation.
12087
* FALSE - was not able to do the scroll operation.
12090
pico_scroll_callback (int cmd, long scroll_pos)
12093
case MSWIN_KEY_SCROLLUPLINE:
12094
scrollupline (0, 1);
12097
case MSWIN_KEY_SCROLLDOWNLINE:
12098
scrolldownline (0, 1);
12101
case MSWIN_KEY_SCROLLUPPAGE:
12105
case MSWIN_KEY_SCROLLDOWNPAGE:
12109
case MSWIN_KEY_SCROLLTO:
12119
* sleep the given number of seconds
12124
time_t out = (time_t)t + time((long *) 0);
12125
while(out > time((long *) 0))
12131
tcsucmp(LPTSTR o, LPTSTR r)
12133
return(o ? (r ? _tcsicmp(o, r) : 1) : (r ? -1 : 0));
12137
tcsruncmp(LPTSTR o, LPTSTR r, int n)
12139
return(o ? (r ? _tcsnicmp(o, r, n) : 1) : (r ? -1 : 0));
12143
strucmp(char *o, char *r)
12145
return(o ? (r ? stricmp(o, r) : 1) : (r ? -1 : 0));
12150
struncmp(char *o, char *r, int n)
12152
return(o ? (r ? strnicmp(o, r, n) : 1) : (r ? -1 : 0));
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.
12162
scrwidth(LPTSTR lpText, int len)
12166
int i, thislen, offset;
12171
thislen = MIN(len, 1000);
12172
for(i = 0; i < thislen; i++)
12173
ubuf[i] = lpText[offset+i];
12175
w += ucs4_str_width_ptr_to_ptr(&ubuf[0], &ubuf[thislen]);
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.
12191
pscreen_offset_from_cord(int row, int col, PTTYINFO pTTYInfo)
12193
int offset_due_to_row, offset_due_to_col, width;
12196
* Each row starts at a specific offset into pScreen.
12198
offset_due_to_row = row * pTTYInfo->actNColumn;
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
12208
* fewer characters it would be <= desired width, one more would
12209
* be greater than desired width, this one is >= desired width.
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);
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);
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++;
12230
return(offset_due_to_row + offset_due_to_col);
12236
* 1 if store pass prompt is set in the registry to on
12238
* -1 if not set to anything
12241
mswin_store_pass_prompt(void)
12244
* We shouldn't need to prompt anymore, but always return 1