2 * ========================================================================
3 * Copyright 2006-2007 University of Washington
4 * Copyright 2013-2018 Eduardo Chappa
6 * Licensed under the Apache License, Version 2.0 (the "License");
7 * you may not use this file except in compliance with the License.
8 * You may obtain a copy of the License at
10 * http://www.apache.org/licenses/LICENSE-2.0
12 * ========================================================================
18 #define termdef 1 /* don't define "term" external */
20 #include "../headers.h"
28 #include "../../pith/osdep/pipe.h"
29 #include "../../pith/osdep/canaccess.h"
31 #include "../../pith/charconv/filesys.h"
32 #include "../../pith/charconv/utf8.h"
34 #include "../../pith/filttype.h"
35 #include "../../pith/osdep/color.h"
39 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
43 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
49 /* For debugging, export locals so debugger can see them. */
58 * Define which debugging is desired. Generally only FDEBUG.
60 #define FDEBUG /* Standard file debugging. */
62 #undef SDEBUG /* Verbose debugging of startup and windows handling*/
63 #undef CDEBUG /* Verbose debugging of character input timeing. */
65 #undef OWN_DEBUG_FILE /* Define if we want to write to our own debug file,
69 /* Max size permitted for the screen. */
71 #define MAXNCOLUMN NLINE
73 #define MINNROW 10 /* Minimum screen size */
76 #define MARGINE_LEFT 3
79 #define FRAME_3D_SIZE 1
81 #define WIN_MIN_X_SIZE 190 /* Minimum window size. */
82 #define WIN_MIN_Y_SIZE 180
84 #define WIN_X_BORDER_SIZE 8 /* Space taked by window frame. */
85 #define WIN_Y_BORDER_SIZE 65
87 #define FONT_MIN_SIZE 5
88 #define FONT_MAX_SIZE 21
90 #define PRINT_TAB_SIZE 8 /* Tab size used by print code. */
93 #define TB_HEIGHT 32 /* Tool Bar Height. */
94 #define TB_BUTTONHEIGHT 16 /* Button Height. */
95 #define TB_BUTTONSPACING 8 /* Space between buttons. */
98 /* Some string lengths. */
99 #define MAXLEN_TEMPSTR 256 /* Max size for temp storage. */
101 #define WIN_POS_STR_MAX_LEN 21 /* Max length for window-position
104 #define MENU_ITEM_NAME_LEN 32 /* Menu item name lengths. */
107 /* Length of keyboard input queue. */
108 #define CHARACTER_QUEUE_LENGTH 32
109 #define MOUSE_QUEUE_LENGTH 32
111 /* Number of resize callback functions we can keep track of. */
112 #define RESIZE_CALLBACK_ARRAY_SIZE 3
114 /* Number of bytes held in the write accumulator. */
115 #define WRITE_ACCUM_SIZE 200
117 /* Max time that may pass between calls to GetMessage. See mswin_charavail()
119 #define GM_MAX_TIME 3000 /* In milliseconds.*/
121 /* My Timer Message */
122 #define MY_TIMER_ID 33
123 /* timeout period in miliseconds. */
124 #define MY_TIMER_PERIOD (UINT)((IDLE_TIMEOUT + 1)*1000)
125 /***** We use variable my_timer_period now instead so that we can set
126 it differently when in pine and when in regular old pico.
127 We're not entirely sure we need it in pico, but we will leave
128 it there because we don't understand.
130 #define MY_TIMER_SHORT_PERIOD (UINT)5000 /* used when there is a task in
132 #define MY_TIMER_VERY_SHORT_PERIOD (UINT)500 /* used when SIGALRM and alarm()
134 #define MY_TIMER_EXCEEDINGLY_SHORT_PERIOD (UINT)80 /* used when
135 gAllowMouseTracking is set */
137 #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.")
140 * Task bar notification Icon id and call back message for it.
142 #define TASKBAR_ICON_NEWMAIL 1
143 #define TASKBAR_ICON_MESSAGE WM_USER+1000
147 * Below here are fixed constancs that really should not be changed.
150 /* Auto Wrap States. */
151 #define WRAP_OFF 0 /* Never wrap to next line. */
152 #define WRAP_ON 1 /* Wrap to next line. */
153 #define WRAP_NO_SCROLL 2 /* Wrap to next line but DON'T scroll
155 /* Speicial keys in the Character Queue. */
156 #define CQ_FLAG_DOWN 0x01
157 #define CQ_FLAG_EXTENDED 0x02
158 #define CQ_FLAG_ALT 0x04
160 #define ARABIC_LRM 0x200E
161 #define ARABIC_RLM 0x200F
163 /* Special ASCII characters. */
164 #define ASCII_BEL 0x07
165 #define ASCII_BS 0x08
166 #define ASCII_TAB 0x09
167 #define ASCII_LF 0x0A
168 #define ASCII_CR 0x0D
169 #define ASCII_XON 0x11
170 #define ASCII_XOFF 0x13
172 /* Character Attributes. */
173 #define CHAR_ATTR_NORM 0x00 /* Normal. */
174 #define CHAR_ATTR_REV 0x01 /* Reverse Video. */
175 #define CHAR_ATTR_BOLD 0x02 /* Reverse Video. */
176 #define CHAR_ATTR_ULINE 0x04 /* Reverse Video. */
177 #define CHAR_ATTR_SEL 0x08 /* Selected text. */
178 #define CHAR_ATTR_NOT 0x80 /* No attributes. */
181 * Different applications that we know about.
183 #define APP_UNKNOWN 0
185 #define APP_PICO_IDENT TEXT("pico")
187 #define APP_PINE_IDENT TEXT("pine")
190 * Control values for call to AccelCtl.
192 /*#undef ACCELERATORS*/
194 #define ACCEL_UNLOAD 0 /* Unload the accelerators. */
195 #define ACCEL_LOAD 1 /* Load the accelerators. */
196 #define ACCEL_TOGGLE 2 /* Toggle the accelerators. */
199 * flag bits to control which edit menu options can get lit
203 #define EM_CP_APPEND 0x0002
204 #define EM_FIND 0x0004
205 #define EM_PST 0x0008
206 #define EM_PST_ABORT 0x0010
207 #define EM_CUT 0x0020
208 #define EM_SEL_ALL 0x0040
210 #define EM_MAX_ACCEL 6
212 /* Offsets to objects in window extra storage. */
213 #define GWL_PTTYINFO 0 /* Offset in Window extra storage. */
218 #define FONT_CHARSET_FONT DEFAULT_CHARSET
220 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
224 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
226 /* Type that the screen array is made up of. */
227 #define CHAR unsigned char
229 /* define possible caret shapes */
237 /* Type that the attribute array is made up of. */
238 typedef struct _character_attribute
{
243 typedef int (*ResizeCallBackProc
)();
244 typedef int (*FileDropCallBackProc
)();
247 /* NOTE: There is currently code that assumes that CHAR and CharAttrib
248 * are one byte in size. All this code is flaged with a preceeding
251 /* Struct that defines command menu entries. */
252 typedef struct tagMenuItem
{
260 /* List of child window IDs and previous window procedures. */
261 typedef struct tagBtnList
{
268 typedef struct tagTTYINFO
{
269 TCHAR
*pScreen
; /* Screen. */
270 int *pCellWidth
; /* how wide to paint the char */
271 CharAttrib
*pAttrib
; /* Attributes. */
272 TCHAR writeAccum
[WRITE_ACCUM_SIZE
];
274 CARETS cCaretStyle
; /* Current caret's style */
275 int scrollRange
; /* Current scroll bar range. */
276 long scrollPos
; /* Current scroll position. */
277 long scrollTo
; /* Possition of last scroll to. */
280 DWORD rgbFGColor
; /* Normal forground color. */
281 DWORD rgbBGColor
; /* Normal background color. */
282 DWORD rgbRFGColor
; /* Reverse forground color. */
283 DWORD rgbRBGColor
; /* Reverse background color */
284 unsigned screenDirty
:1; /* TRUE if screen needs update. */
285 unsigned eraseScreen
:1; /* TRUE if need to erase whole screen */
286 unsigned fMinimized
:1; /* True when window is minimized. */
287 unsigned fMaximized
:1; /* True when window is maximized. */
288 unsigned fFocused
:1; /* True when we have focus. */
289 unsigned fNewLine
:1; /* Auto LF on CR. */
290 unsigned fMassiveUpdate
:1;/* True when in Massive screen update. */
291 unsigned fNewMailIcon
:1; /* True when new mail has arrived. */
292 unsigned fMClosedIcon
:1; /* True when no mailbox is open. */
293 unsigned fCursorOn
:1; /* True when cursor's shown */
294 unsigned fCaretOn
:1; /* True if caret's displayed */
295 unsigned fTrayIcon
:1; /* True if tool tray icon's on */
296 ResizeCallBackProc resizer
[RESIZE_CALLBACK_ARRAY_SIZE
];
297 FileDropCallBackProc dndhandler
;
298 int autoWrap
; /* Auto wrap to next line. */
299 CharAttrib curAttrib
; /* Current character attributes. */
300 int actNRow
, actNColumn
; /* Actual number of rows and comumns
302 CORD xSize
, ySize
; /* Size of screen in pixels */
303 CORD xScroll
, yScroll
; /* ?? */
304 CORD xOffset
, yOffset
; /* Offset from the left and top of
305 * window contents. */
306 CORD nColumn
, nRow
; /* Current position of cursor in
308 CORD xChar
, yChar
; /* Width of a char in pixels. */
309 int yCurOffset
; /* offset of cursor Y-size */
310 CORD fDesiredSize
; /* TRUE when there is a specific size
311 * the window should be expanded to
312 * after being minimized. */
313 CORD xDesPos
, yDesPos
; /* Desired position. */
314 CORD xDesSize
, yDesSize
; /* Desired window position. */
315 int curWinMenu
; /* Current window menu. */
316 HACCEL hAccel
; /* Handle to accelorator keys. */
317 UINT fAccel
; /* vector of bound accelerator keys. */
318 CORD toolBarSize
; /* Size of toolbar. */
319 BOOL toolBarTop
; /* Toolbar on top? */
321 BtnList
*toolBarBtns
;
324 BOOL menuItemsCurrent
;
326 BOOL scrollRangeChanged
;
329 short menuItemsIndex
;
330 MenuItem menuItems
[KS_COUNT
];
331 } TTYINFO
, *PTTYINFO
;
334 #define MAXCLEN (MAX(MAXCOLORLEN,RGBLEN+1))
335 typedef struct MSWINColor
{
349 * Entry in the OnTask list. This is a list of actions to perform
350 * when a task exits. Currently, the only thing we do is delete
351 * files. if that changes this structure will get more complex.
353 * hTask == NULL means "This program" and can be used to arrange for
354 * deletion of files when this program exits.
356 typedef struct ontask
{
359 char path
[PATH_MAX
+1];
362 typedef void (__cdecl
*SignalType
)(int);
364 typedef struct _iconlist
{
366 /* char path[PATH_MAX]; */
370 struct _iconlist
*next
;
374 * char * array for printing registry settings.
376 typedef struct MSWR_LINE_BUFFER
{
377 char **linep
; /* store these as utf8, since that's what we have to pass back */
379 unsigned long offset
;
380 } MSWR_LINE_BUFFER_S
;
383 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
385 * Forward function declarations.
387 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
390 MyGetWindowLongPtr(HWND hwnd
, int nIndex
)
392 return (void *)(LONG_PTR
)GetWindowLongPtr(hwnd
, nIndex
);
396 MySetWindowLongPtr(HWND hwnd
, int nIndex
, void *NewLongPtr
)
398 // warning C4244: 'function': conversion from 'LONG_PTR' to 'LONG',
399 // possible loss of data
400 #pragma warning(push)
401 #pragma warning(disable: 4244)
402 return SetWindowLongPtr(hwnd
, nIndex
, (LONG_PTR
)NewLongPtr
);
407 #define GET_HINST( hWnd ) ((HINSTANCE) MyGetWindowLongPtr( hWnd, GWLP_HINSTANCE ))
408 #define GET_ID( hWnd ) (LOWORD(MyGetWindowLongPtr( hWnd, GWLP_ID )))
410 #define GET_HINST( hWnd ) ((HINSTANCE) GetWindowWord( hWnd, GWW_HINSTANCE ))
411 #define GET_ID( hWnd ) ((WORD) GetWindowWord( hWnd, GWW_ID ))
414 #define CONSTRAIN(v,min,max) ((v) = (v) < (min) ? (min) : (v) > (max) ? (max) : (v))
417 /* function prototypes (private) */
418 int app_main (int argc
, char *argv
[]);
422 LOCAL
void mswin_invalidparameter(const wchar_t *, const wchar_t *,
423 const wchar_t *, unsigned int, uintptr_t);
425 LOCAL BOOL
InitApplication (HANDLE
);
426 LOCAL HWND
InitInstance (HANDLE
, int);
427 LOCAL
void MakeArgv (HINSTANCE hInstance
, LPSTR cmdLine
, int *pargc
,
429 LOCAL LRESULT NEAR
CreateTTYInfo (HWND hWnd
);
430 LOCAL BOOL NEAR
DestroyTTYInfo (HWND hWnd
);
431 LOCAL
int ResizeTTYScreen (HWND hWnd
, PTTYINFO pTTYInfo
,
432 int newNRow
, int newNColumn
);
433 LOCAL BOOL
ResetTTYFont (HWND
, PTTYINFO
, LOGFONT
*);
434 LOCAL BOOL
EraseTTY (HWND
, HDC
);
435 LOCAL BOOL
PaintTTY (HWND
);
436 LOCAL BOOL
GetMinMaxInfoTTY (HWND hWnd
, MINMAXINFO __far
*lpmmi
);
437 LOCAL BOOL
AboutToSizeTTY (HWND hWnd
, WINDOWPOS
*winPos
);
438 LOCAL BOOL
SizeTTY (HWND
, int, CORD
, CORD
);
439 LOCAL BOOL
SizingTTY (HWND hWnd
, int fwSide
, LPRECT pRect
);
440 LOCAL
void FrameRect3D(HDC hdc
, RECT
* pRC
, int width
, BOOL raised
);
441 LOCAL
void FillRectColor(HDC hDC
, RECT
* pRC
, COLORREF color
);
444 LOCAL BOOL
MoveTTY (HWND hWnd
, int xPos
, int yPos
);
445 LOCAL
void ScrollTTY (HWND hWnd
, int wScrollCode
, int nPos
, HWND hScroll
);
446 LOCAL
void CaretTTY (HWND hWnd
, CARETS cStyle
);
447 LOCAL
void CaretCreateTTY (HWND hWnd
);
449 LOCAL
void MouseWheelTTY (HWND hWnd
, int xPos
, int yPos
,
450 int fwKeys
, int zDelta
);
451 LOCAL
void MouseWheelMultiplier ();
453 BOOL CALLBACK
NoMsgsAreSent (void);
454 LOCAL BOOL
SetTTYFocus (HWND
);
455 LOCAL BOOL
KillTTYFocus (HWND
);
456 LOCAL BOOL
MoveTTYCursor (HWND
);
457 LOCAL BOOL
ProcessTTYKeyDown (HWND hWnd
, TCHAR bOut
);
458 LOCAL BOOL
ProcessTTYCharacter (HWND hWnd
, TCHAR bOut
);
459 LOCAL BOOL
ProcessTTYMouse (HWND hWnd
, int mevent
, int button
, CORD xPos
,
460 CORD yPos
, WPARAM keys
);
461 LOCAL BOOL
ProcessTTYFileDrop (HANDLE wParam
);
462 LOCAL
void ProcessTimer (void);
463 LOCAL BOOL
WriteTTYBlock (HWND
, LPTSTR
, int);
464 LOCAL BOOL
WriteTTYText (HWND
, LPTSTR
, int);
465 LOCAL BOOL
WriteTTYChar (HWND
, TCHAR
);
467 LOCAL VOID
GoModalDialogBoxParam (HINSTANCE
, LPTSTR
, HWND
,
469 LOCAL BOOL
SelectTTYFont (HWND
);
470 LOCAL
void SetColorAttribute (COLORREF
*cf
, char *colorName
);
471 LOCAL
void SetReverseColor (void);
472 LOCAL BOOL
ConvertRGBString (char *colorName
, COLORREF
*cf
);
473 LOCAL
char *ConvertStringRGB (char *colorName
, size_t ncolorName
, COLORREF colorRef
);
474 LOCAL BOOL
ScanInt (char *str
, int min
, int max
, int *val
);
476 LOCAL
void TBToggle (HWND
);
477 LOCAL
void TBPosToggle (HWND
);
478 LOCAL
void TBShow (HWND
);
479 LOCAL
void TBHide (HWND
);
480 LOCAL
void TBSwap (HWND
, int);
481 LOCAL
unsigned scrwidth(LPTSTR lpText
, int nLength
);
482 LOCAL
long pscreen_offset_from_cord(int row
, int col
, PTTYINFO pTTYInfo
);
484 LOCAL
int tcsucmp(LPTSTR o
, LPTSTR r
);
485 LOCAL
int _print_send_page(void);
487 /* defined in region.c */
488 int copyregion(int f
, int n
);
492 #ifdef ACCELERATORS_OPT
493 LOCAL
void AccelCtl (HWND hWnd
, int ctl
, BOOL saveChange
);
495 LOCAL
void AccelManage (HWND hWnd
, long accels
);
496 LOCAL
void UpdateAccelerators (HWND hWnd
);
499 LOCAL UINT
UpdateEditAllowed(HWND hWnd
);
500 LOCAL
void PopupConfig(HMENU hMenu
, MPopup
*members
, int *n
);
501 LOCAL MPopup
*PopupId(MPopup
*members
, int id
);
502 LOCAL BOOL
CopyCutPopup (HWND hWnd
, UINT fAllowed
);
504 LOCAL
void SelStart (int nRow
, int nColumn
);
505 LOCAL
void SelFinish (int nRow
, int nColumn
);
506 LOCAL
void SelClear (void);
507 LOCAL
void SelTrackXYMouse (int xPos
, int yPos
);
508 LOCAL
void SelTrackMouse (int nRow
, int nColumn
);
509 LOCAL BOOL
SelAvailable (void);
510 LOCAL
void SelDoCopy (HANDLE hCB
, DWORD lenCB
);
512 LOCAL
void UpdateTrayIcon(DWORD dwMsg
, HICON hIcon
, LPTSTR tip
);
514 LOCAL
void FlushWriteAccum (void);
516 LOCAL
int mswin_reg_lptstr(int, int, LPTSTR
, size_t);
518 LOCAL BOOL
MSWRPoke(HKEY hKey
, LPTSTR subkey
, LPTSTR valstr
, LPTSTR data
);
519 LOCAL
int MSWRClear(HKEY hKey
, LPTSTR pSubKey
);
520 LOCAL
void MSWRAlpineSet(HKEY hRootKey
, LPTSTR subkey
, LPTSTR val
,
521 int update
, LPTSTR data
);
522 LOCAL
int MSWRProtocolSet(HKEY hKey
, int type
, LPTSTR path_lptstr
);
523 LOCAL
void MSWRAlpineSetHandlers(int update
, LPTSTR path
);
524 LOCAL
int MSWRAlpineGet(HKEY hKey
, LPTSTR subkey
, LPTSTR val
,
525 LPTSTR data_lptstr
, size_t len
);
527 LOCAL
void MSWIconAddList(int row
, int id
, HICON hIcon
);
528 LOCAL
int MSWIconPaint(int row
, HDC hDC
);
529 LOCAL
void MSWIconFree(IconList
**ppIcon
);
530 LOCAL
void MSWRLineBufAdd(MSWR_LINE_BUFFER_S
*lpLineBuf
, LPTSTR line
);
531 LOCAL
int MSWRDump(HKEY hKey
, LPTSTR pSubKey
, int keyDepth
,
532 MSWR_LINE_BUFFER_S
*lpLineBuf
);
535 /* ... interface routines ... */
538 void ProcessMenuItem (HWND hWnd
, WPARAM wParam
);
540 void AlarmDeliver (void);
541 void HUPDeliver (void);
543 void PrintFontSameAs (HWND hWnd
);
544 void PrintFontSelect (HWND hWnd
);
545 void ExtractFontInfo(LOGFONT
*pFont
,
546 LPTSTR fontName
, size_t nfontName
,
548 LPTSTR fontStyle
, size_t nfontStyle
,
550 LPTSTR fontCharSet
, size_t nfontCharSet
);
552 LOCAL
void DidResize (PTTYINFO pTTYInfo
);
554 LOCAL
void UpdateMenu (HWND hWnd
);
555 LOCAL
void EditCut (void);
556 LOCAL
void EditCopy (void);
557 LOCAL
void EditCopyAppend (void);
558 LOCAL
void EditDoCopyData (HANDLE hCB
, DWORD lenCB
);
559 LOCAL
void EditPaste (void);
560 LOCAL
void EditCancelPaste (void);
561 LOCAL UCS
EditPasteGet (void);
562 LOCAL BOOL
EditPasteAvailable (void);
563 LOCAL
void EditSelectAll (void);
565 LOCAL
void MSWHelpShow (cbstr_t
);
566 LOCAL
int MSWHelpSetMenu (HMENU hmenu
);
569 LOCAL
void SortHandler (int order
, int reverse
);
570 LOCAL
void FlagHandler (int order
, int reverse
);
572 LOCAL
void MyTimerSet (void);
574 LOCAL LRESULT
ConfirmExit (void);
576 LOCAL
void CQInit (void);
577 LOCAL BOOL
CQAvailable (void);
578 LOCAL BOOL
CQAdd (UCS c
, BOOL fKeyControlDown
);
579 LOCAL BOOL
CQAddUniq (UCS c
, BOOL fKeyControlDown
);
582 LOCAL
void MQInit (void);
583 LOCAL BOOL
MQAvailable (void);
584 LOCAL BOOL
MQAdd (int mevent
, int button
, int nRow
, int nColumn
,
585 int keys
, int flags
);
586 LOCAL BOOL
MQGet (MEvent
* pmouse
);
587 LOCAL BOOL
MQClear (int flag
);
589 LOCAL UCS
mswin_getc (void);
591 LOCAL DWORD
ExplainSystemErr(void);
593 LOCAL
void RestoreMouseCursor();
595 LOCAL BYTE
mswin_string2charsetid(LPTSTR
);
596 LOCAL
int mswin_charsetid2string (LPTSTR fontCharSet
,
597 size_t nfontCharSet
, BYTE lfCharSet
);
599 LOCAL
int mswin_tw_init(MSWIN_TEXTWINDOW
*mswin_tw
, int id
,
601 LOCAL MSWIN_TEXTWINDOW
*mswin_tw_displaytext_lptstr (LPTSTR
, LPTSTR
, size_t,
602 LPTSTR
*, MSWIN_TEXTWINDOW
*mswin_tw
,
604 LOCAL
void mswin_tw_print_callback(MSWIN_TEXTWINDOW
*mswin_tw
);
607 /* Functions exported to MS Windows. */
609 LRESULT FAR PASCAL __export
PWndProc (HWND
, UINT
, WPARAM
, LPARAM
);
610 BOOL FAR PASCAL __export
ToolBarProc (HWND
, UINT
, WPARAM
, LPARAM
);
611 LRESULT FAR PASCAL __export
TBBtnProc (HWND
, UINT
, WPARAM
, LPARAM
);
612 BOOL FAR PASCAL __export
AboutDlgProc (HWND
, UINT
, WPARAM
, LPARAM
);
613 BOOL FAR PASCAL __export
SplashDlgProc (HWND
, UINT
, WPARAM
, LPARAM
);
615 LOCAL HDDEDATA CALLBACK
DdeCallback(UINT uType
, UINT uFmt
, HCONV hconv
,
616 HSZ hsz1
, HSZ hsz2
, HDDEDATA hdata
,
617 DWORD dwData1
, DWORD dwData2
);
619 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
623 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
628 HINSTANCE ghInstance
;
630 FILE *mswin_debugfile
= NULL
;
632 TCHAR gszAppName
[45];
634 LOCAL TCHAR TempBuf
[MAXLEN_TEMPSTR
];
636 LOCAL TCHAR gszTTYClass
[] = TEXT("PineWnd");
637 LOCAL
int gAppIdent
= APP_UNKNOWN
;
639 LOCAL
int gNMW_width
;
641 LOCAL HCURSOR ghCursorArrow
= NULL
;
642 LOCAL HCURSOR ghCursorBusy
= NULL
;
643 LOCAL HCURSOR ghCursorIBeam
= NULL
;
644 LOCAL HCURSOR ghCursorHand
= NULL
;
645 LOCAL HCURSOR ghCursorCurrent
= NULL
;
647 LOCAL HWND ghSplashWnd
= NULL
;
649 LOCAL COLOR_PAIR
*the_rev_color
, *the_normal_color
;
651 /* Used for Pasting text. */
652 LOCAL HANDLE ghPaste
= NULL
; /* Handle to Paste data. */
653 LOCAL TCHAR
*gpPasteNext
= NULL
; /* Pointer to current char. */
654 LOCAL
size_t gPasteBytesRemain
= 0; /* Count of bytes left. */
655 LOCAL BOOL gPasteWasCR
= FALSE
; /* Previous char was CR. */
656 LOCAL
int gPasteEnabled
= MSWIN_PASTE_DISABLE
;
657 LOCAL getc_t gCopyCutFunction
= NULL
;
658 LOCAL cbarg_t gScrollCallback
= NULL
;
659 LOCAL BOOL gScrolling
= FALSE
; /* Keeps track of when we are
660 * in scroll routine. */
661 LOCAL cbarg_t gSortCallback
= NULL
;
662 LOCAL cbarg_t gFlagCallback
= NULL
;
663 LOCAL cbarg_t gHdrCallback
= NULL
;
664 LOCAL cbarg_t gZoomCallback
= NULL
;
665 LOCAL cbarg_t gFkeyCallback
= NULL
;
666 LOCAL cbarg_t gSelectedCallback
= NULL
;
667 LOCAL BOOL gMouseTracking
= FALSE
; /* Keeps track of when we are
668 * tracking the mouse. */
669 LOCAL FARPROC gWSBlockingProc
= NULL
;
670 LOCAL DLGPROC gToolBarProc
= NULL
;
671 LOCAL WNDPROC gTBBtnProc
= NULL
;
673 LOCAL BOOL gAllowCopy
= FALSE
;
674 LOCAL BOOL gAllowCut
= FALSE
;
676 LOCAL BOOL gAllowMouseTrack
= FALSE
;/* Upper layer interested in
678 LOCAL
short gsMWMultiplier
;
679 LOCAL MEvent gMTEvent
;
681 LOCAL cbstr_t gHelpGenCallback
= NULL
;
682 LOCAL BOOL gfHelpGenMenu
= FALSE
; /* TRUE when help menu
684 LOCAL cbstr_t gHelpCallback
= NULL
;
685 LOCAL BOOL gfHelpMenu
= FALSE
; /* TRUE when help menu
687 LOCAL
char *gpCloseText
;
689 LOCAL DWORD gGMLastCall
= 0; /* Last time I called
691 LOCAL BOOL gConfirmExit
= FALSE
;
692 LOCAL HICON ghNormalIcon
= NULL
;
693 LOCAL HICON ghNewMailIcon
= NULL
;
694 LOCAL HICON ghMClosedIcon
= NULL
;
696 LOCAL
int gPrintFontSize
;
697 LOCAL TCHAR gPrintFontName
[LF_FACESIZE
];
698 LOCAL TCHAR gPrintFontStyle
[64];
699 LOCAL TCHAR gPrintFontCharSet
[256];
700 LOCAL BOOL gPrintFontSameAs
= TRUE
;
702 LOCAL UINT gTimerCurrentPeriod
= 0;
704 LOCAL cbvoid_t gPeriodicCallback
= NULL
; /* Function to call. */
705 LOCAL DWORD gPeriodicCBTimeout
= 0; /* Time of next call. */
706 LOCAL DWORD gPeriodicCBTime
= 0; /* Delay between calls. */
708 //=========================================================================
710 //=========================================================================
711 MSWIN_TEXTWINDOW gMswinAltWin
= {0};
712 MSWIN_TEXTWINDOW gMswinNewMailWin
= {0};
714 MSWIN_TEXTWINDOW gMswinIMAPTelem
= {0};
715 LOCAL cbvoid_t gIMAPDebugONCallback
= NULL
;
716 LOCAL cbvoid_t gIMAPDebugOFFCallback
= NULL
;
717 LOCAL cbvoid_t gEraseCredsCallback
= NULL
;
718 LOCAL cbvoid_t gViewInWindCallback
= NULL
;
720 LOCAL cbvoid_t gConfigScreenCallback
= NULL
;
722 LOCAL cbarg_t gMouseTrackCallback
= NULL
;
724 /* Currently only implement one SIGNAL so only need single variable. */
725 LOCAL SignalType gSignalAlarm
= SIG_DFL
;
726 LOCAL DWORD gAlarmTimeout
= 0; /* Time alarm expires in
728 * (GetTickCount()/1000) */
729 LOCAL SignalType gSignalHUP
= SIG_DFL
;
731 LOCAL IconList
*gIconList
= NULL
;
735 * There is some coordination between these names and the similar names
736 * in osdep/unix. The names in the left column are mapped to the colors
737 * in the right column when displaying. Note that the last eight colors map
738 * to the same thing as the 1st eight colors. This is an attempt to inter-
739 * operate with 16-color xterms. When editing a color and writing the color
740 * into the config file, we use the canonical_name (middle column). So if
741 * the user chooses green from the menu we write color010 in the config
742 * file. [This has changed. Now we put the RGB value in the config file
743 * instead. We leave this so that we can interpret color010 in the config
744 * file from old versions of pine.]
745 * We display that as green later. The xterm also displays that as
746 * green, because the bright green (color010) on the xterm is what we want
747 * to consider to be green, and the other one (color002) is dark green.
748 * And dark green sucks.
749 * On the PC we only use the first 11 colors in this table when giving the
750 * user the set color display, since the last eight are repeats.
752 LOCAL MSWINColor MSWINColorTable
[] = {
753 "black", "000,000,000", RGB(0,0,0),
754 "red", "255,000,000", RGB(255,0,0),
755 "green", "000,255,000", RGB(0,255,0),
756 "yellow", "255,255,000", RGB(255,255,0),
757 "blue", "000,000,255", RGB(0,0,255),
758 "magenta", "255,000,255", RGB(255,0,255),
759 "cyan", "000,255,255", RGB(0,255,255),
760 "white", "255,255,255", RGB(255,255,255),
761 "colorlgr", "192,192,192", RGB(192,192,192), /* lite gray */
762 "colormgr", "128,128,128", RGB(128,128,128), /* med. gray */
763 "colordgr", "064,064,064", RGB(64,64,64), /* dark gray */
764 "color008", "000,000,000", RGB(0,0,0),
765 "color009", "255,000,000", RGB(255,0,0),
766 "color010", "000,255,000", RGB(0,255,0),
767 "color011", "255,255,000", RGB(255,255,0),
768 "color012", "000,000,255", RGB(0,0,255),
769 "color013", "255,000,255", RGB(255,0,255),
770 "color014", "000,255,255", RGB(0,255,255),
771 "color015", "255,255,255", RGB(255,255,255),
775 #define fullColorTableSize ((sizeof(MSWINColorTable) / sizeof(MSWINColorTable[0])) - 1)
776 #define visibleColorTableSize (fullColorTableSize - 8)
779 LOCAL MSWinCaret_t MSWinCaretTable
[] = {
781 "ShortBlock", CaretSmallBlock
,
782 "Underline", CaretHorizBar
,
783 "VertBar", CaretVertBar
,
788 /*++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
792 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
794 /*---------------------------------------------------------------------------
795 * int PASCAL WinMain( HANDLE hInstance, HANDLE hPrevInstance,
796 * LPSTR lpszCmdLine, int nCmdShow )
799 * This is the main window loop!
802 * As documented for all WinMain() functions.
804 *--------------------------------------------------------------------------*/
806 wWinMain( HINSTANCE hInstance
, HINSTANCE hPrevInstance
,
807 LPTSTR lpszCmdLine
, int nCmdShow
)
810 int argc
, i
, nosplash
= 0;
813 ghInstance
= hInstance
;
815 if (!InitApplication( hInstance
))
819 * Instead of crashing into Dr. Watson on invalid parameter calls
820 * into the C library, just return the error indication that these
821 * functions are normally expected to return.
823 _set_invalid_parameter_handler (mswin_invalidparameter
);
825 #ifdef OWN_DEBUG_FILE /* Want to write to seperate memdebug.txt file. */
826 mswin_debugfile
= fopen ("memdebug.txt", "w");
827 fprintf (mswin_debugfile
, "Beginning of mswin debug log\n");
828 if (mswin_debugfile
!= NULL
) {
830 MemDebug (mswin_debug
, mswin_debugfile
);
831 fprintf (mswin_debugfile
, "Show window as: %d\n", nCmdShow
);
832 fflush (mswin_debugfile
);
836 if (NULL
== (ghTTYWnd
= InitInstance (hInstance
, nCmdShow
)))
839 /* cmdline_utf8 memory is never freed */
840 cmdline_utf8
= lptstr_to_utf8(lpszCmdLine
);
842 MakeArgv (hInstance
, cmdline_utf8
, &argc
, &argv
);
844 for(i
= 0; i
< argc
; i
++)
845 if(strcmp((const char *)argv
[i
], "-nosplash") == 0){
849 /* Create Splash window */
851 ghSplashWnd
= CreateDialog(hInstance
,
852 MAKEINTRESOURCE( SPLASHDLGBOX
),
853 ghTTYWnd
, (DLGPROC
)SplashDlgProc
);
854 ShowWindow (ghSplashWnd
, SW_SHOWNORMAL
);
859 app_main (argc
, (char **)argv
);
866 mswin_invalidparameter(const wchar_t *expression
,
867 const wchar_t *function
,
872 /* do nothing for now */
881 if (ghTTYWnd
== NULL
)
884 UpdateTrayIcon(NIM_DELETE
, 0, NULL
);
886 /* Destroy main window and process remaining events. */
887 DestroyWindow (ghTTYWnd
);
888 while (GetMessage (&msg
, NULL
, 0, 0)) {
889 TranslateMessage (&msg
);
890 DispatchMessage (&msg
);
893 #ifdef OWN_DEBUG_FILE
894 fclose (mswin_debugfile
);
896 if (gWSBlockingProc
!= NULL
)
897 FreeProcInstance (gWSBlockingProc
);
904 /*---------------------------------------------------------------------------
905 * BOOL InitApplication( HANDLE hInstance )
908 * First time initialization stuff. This registers information
909 * such as window classes.
913 * Handle to this instance of the application.
915 *--------------------------------------------------------------------------*/
917 InitApplication (HANDLE hInstance
)
922 * Register tty window class.
924 wndclass
.style
= 0; /* CS_NOCLOSE; */
925 wndclass
.lpfnWndProc
= PWndProc
;
926 wndclass
.cbClsExtra
= 0;
927 wndclass
.cbWndExtra
= sizeof (LONG
);
928 wndclass
.hInstance
= hInstance
;
929 /* In win16 we paint our own icon. */
930 wndclass
.hIcon
= LoadIcon (hInstance
, MAKEINTRESOURCE (ALPINEICON
));
931 wndclass
.hCursor
= LoadCursor (NULL
, IDC_ARROW
);
932 wndclass
.hbrBackground
= (HBRUSH
) (COLOR_WINDOW
+ 1);
933 wndclass
.lpszMenuName
= MAKEINTRESOURCE (ALPINEMENU
);
934 wndclass
.lpszClassName
= gszTTYClass
;
936 return (RegisterClass (&wndclass
));
940 /*---------------------------------------------------------------------------
941 * HWND InitInstance( HANDLE hInstance, int nCmdShow )
944 * Initializes instance specific information.
951 * How do we show the window?
953 /*--------------------------------------------------------------------------*/
955 InitInstance (HANDLE hInstance
, int nCmdShow
)
959 SCROLLINFO scrollInfo
;
962 if (mswin_debug
>= 5)
963 fprintf (mswin_debugfile
, "InitInstance::: entered, nCmdShow %d\n",
967 LoadString (hInstance
, IDS_APPNAME
, gszAppName
, sizeof(gszAppName
) / sizeof(TCHAR
));
969 /* create the TTY window */
970 hTTYWnd
= CreateWindow (gszTTYClass
, gszAppName
,
971 WS_OVERLAPPEDWINDOW
| WS_VSCROLL
,
972 CW_USEDEFAULT
, CW_USEDEFAULT
,
973 CW_USEDEFAULT
, CW_USEDEFAULT
,
974 HWND_DESKTOP
, NULL
, hInstance
, NULL
);
976 scrollInfo
.cbSize
= sizeof(SCROLLINFO
);
977 scrollInfo
.fMask
= SIF_DISABLENOSCROLL
| SIF_PAGE
| SIF_RANGE
| SIF_POS
;
980 scrollInfo
.nPage
= 1;
982 SetScrollInfo(hTTYWnd
, SB_VERT
, &scrollInfo
, FALSE
);
983 EnableScrollBar (hTTYWnd
, SB_VERT
, ESB_DISABLE_BOTH
);
990 ghNormalIcon
= LoadIcon (hInstance
, MAKEINTRESOURCE (ALPINEICON
));
991 ghNewMailIcon
= LoadIcon (hInstance
, MAKEINTRESOURCE (NEWMAILICON
));
992 ghMClosedIcon
= LoadIcon (hInstance
, MAKEINTRESOURCE (MCLOSEDICON
));
994 ghCursorArrow
= LoadCursor (NULL
, IDC_ARROW
);
995 ghCursorBusy
= LoadCursor (NULL
, IDC_WAIT
);
996 ghCursorIBeam
= LoadCursor (NULL
, IDC_IBEAM
);
998 ghCursorHand
= LoadCursor (NULL
, IDC_HAND
);
1000 ghCursorHand
= LoadCursor (hInstance
, MAKEINTRESOURCE( PICOHAND
));
1002 ghCursorCurrent
= ghCursorArrow
;
1004 MouseWheelMultiplier();
1011 * Load a resource with the name of the application. Compare to
1012 * known applications to determine who we are running under.
1013 * currently, only differentiation is the WINSOCK blocking hook.
1015 LoadString (hInstance
, IDS_APPIDENT
, appIdent
, sizeof(appIdent
) / sizeof(TCHAR
));
1016 if (_tcscmp (appIdent
, APP_PINE_IDENT
) == 0) {
1017 gAppIdent
= APP_PINE
;
1018 gWSBlockingProc
= MakeProcInstance ( (FARPROC
) NoMsgsAreSent
,
1021 else if (_tcscmp (appIdent
, APP_PICO_IDENT
) == 0)
1022 gAppIdent
= APP_PICO
;
1024 gAppIdent
= APP_UNKNOWN
;
1031 /*---------------------------------------------------------------------------
1035 * Build a standard C argc, argv pointers into the command line string.
1039 * cmdLine - Command line.
1040 * *argc - Count of words.
1041 * ***argc - Pointer to Pointer to array of pointers to
1044 *--------------------------------------------------------------------------*/
1046 MakeArgv (HINSTANCE hInstance
, char *cmdLine_utf8
, int *pargc
, CHAR
***pargv
)
1050 BOOL inWord
, inQuote
;
1052 #define CMD_PATH_LEN 128
1053 LPTSTR modPath_lptstr
;
1057 /* Count words in cmdLine. */
1061 for (c
= cmdLine_utf8
; *c
!= '\0'; ++c
) {
1063 if(*c
== '"' && (*(c
+1) == ' ' || *(c
+1) == '\t' || *(c
+1) == '\0')){
1064 inQuote
= inWord
= FALSE
;
1068 if(inWord
&& (*c
== ' ' || *c
== '\t' || *c
== '\0')){
1071 else if(!inWord
&& (*c
!= ' ' && *c
!= '\t')){
1080 ++wordCount
; /* One for program name. */
1081 argv
= (CHAR
**) MemAlloc (sizeof (CHAR
*) * (wordCount
+ 1));
1085 modPath_lptstr
= (LPTSTR
) MemAlloc (CMD_PATH_LEN
*sizeof(TCHAR
));
1086 mpLen
= GetModuleFileName (hInstance
, modPath_lptstr
, CMD_PATH_LEN
);
1088 *(modPath_lptstr
+ mpLen
) = '\0';
1089 *(argv
++) = (unsigned char *)lptstr_to_utf8(modPath_lptstr
);
1092 *(argv
++) = (unsigned char *)"Alpine/Pico";
1094 MemFree((void *)modPath_lptstr
);
1096 /* Now break up command line. */
1099 for (c
= cmdLine_utf8
; *c
!= '\0'; ++c
) {
1101 if(*c
== '"' && (*(c
+1) == ' ' || *(c
+1) == '\t' || *(c
+1) == '\0')){
1102 inQuote
= inWord
= FALSE
;
1107 if(inWord
&& (*c
== ' ' || *c
== '\t' || *c
== '\0')){
1111 else if(!inWord
&& (*c
!= ' ' && *c
!= '\t')){
1115 *(argv
++) = (unsigned char *)c
+1;
1118 *(argv
++) = (unsigned char *)c
;
1123 *argv
= NULL
; /* tie off argv */
1127 /*---------------------------------------------------------------------------
1128 * LRESULT FAR PASCAL __export PWndProc( HWND hWnd, UINT uMsg,
1129 * WPARAM wParam, LPARAM lParam )
1132 * This is the TTY Window Proc. This handles ALL messages
1133 * to the tty window.
1136 * As documented for Window procedures.
1138 /*--------------------------------------------------------------------------*/
1139 LRESULT FAR PASCAL __export
1140 PWndProc (HWND hWnd
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
1143 if (mswin_debug
> 12) {
1144 fprintf (mswin_debugfile
, "PWndProc:: uMsg = 0x%x\n", uMsg
);
1145 fflush (mswin_debugfile
);
1151 return (CreateTTYInfo (hWnd
));
1154 switch ((WORD
) wParam
) {
1156 case IDM_OPT_SETFONT
:
1157 SelectTTYFont (hWnd
);
1160 case IDM_OPT_FONTSAMEAS
:
1161 PrintFontSameAs (hWnd
);
1164 case IDM_OPT_TOOLBAR
:
1168 case IDM_OPT_TOOLBARPOS
:
1172 case IDM_OPT_USEDIALOGS
: {
1175 gfUseDialogs
= !gfUseDialogs
;
1176 pTTYInfo
= (PTTYINFO
)(LONG_PTR
)MyGetWindowLongPtr (hWnd
, GWL_PTTYINFO
);
1178 DidResize (pTTYInfo
);
1182 case IDM_OPT_ERASE_CREDENTIALS
:
1183 if(gEraseCredsCallback
)
1184 (*gEraseCredsCallback
)();
1187 case IDM_MI_VIEWINWIND
:
1188 if(gViewInWindCallback
)
1189 (*gViewInWindCallback
)();
1192 case IDM_OPT_IMAPTELEM
:
1193 mswin_tw_init(&gMswinIMAPTelem
, (int)LOWORD(wParam
),
1194 TEXT("IMAP Telemetry"));
1195 SetFocus (ghTTYWnd
);
1198 case IDM_OPT_NEWMAILWIN
:
1199 mswin_tw_init(&gMswinNewMailWin
, (int)LOWORD(wParam
),
1200 TEXT("New Mail View"));
1201 SetFocus (ghTTYWnd
);
1204 #ifdef ACCELERATORS_OPT
1205 case IDM_OPT_USEACCEL
:
1206 AccelCtl (hWnd
, ACCEL_TOGGLE
, TRUE
);
1210 case IDM_OPT_SETPRINTFONT
:
1211 PrintFontSelect (hWnd
);
1214 case IDM_OPT_CARETBLOCK
:
1215 CaretTTY(hWnd
, CaretBlock
);
1218 case IDM_OPT_CARETSMALLBLOCK
:
1219 CaretTTY(hWnd
, CaretSmallBlock
);
1222 case IDM_OPT_CARETVBAR
:
1223 CaretTTY(hWnd
, CaretVertBar
);
1226 case IDM_OPT_CARETHBAR
:
1227 CaretTTY(hWnd
, CaretHorizBar
);
1231 GoModalDialogBoxParam ( GET_HINST( hWnd
),
1232 MAKEINTRESOURCE( ABOUTDLGBOX
),
1234 (DLGPROC
)AboutDlgProc
, (LPARAM
) 0 ) ;
1245 case IDM_EDIT_COPY_APPEND
:
1249 case IDM_EDIT_PASTE
:
1252 UpdateAccelerators (hWnd
);
1256 case IDM_EDIT_CANCEL_PASTE
:
1259 UpdateAccelerators (hWnd
);
1263 case IDM_EDIT_SEL_ALL
:
1268 MSWHelpShow (gHelpCallback
);
1271 case IDM_MI_GENERALHELP
:
1272 MSWHelpShow (gHelpGenCallback
);
1275 case IDM_MI_WHEREIS
:
1276 CQAdd (gpTTYInfo
->menuItems
[KS_WHEREIS
- KS_RANGESTART
].miKey
, 0);
1279 case IDM_MI_SORTSUBJECT
:
1280 case IDM_MI_SORTARRIVAL
:
1281 case IDM_MI_SORTSIZE
:
1282 case IDM_MI_SORTFROM
:
1283 case IDM_MI_SORTTO
:
1284 case IDM_MI_SORTCC
:
1285 case IDM_MI_SORTDATE
:
1286 case IDM_MI_SORTORDERSUB
:
1287 case IDM_MI_SORTSCORE
:
1288 case IDM_MI_SORTTHREAD
:
1289 SortHandler((int)(wParam
- IDM_MI_SORTSUBJECT
), 0);
1292 case IDM_MI_SORTREVERSE
:
1296 case IDM_MI_FLAGIMPORTANT
:
1297 case IDM_MI_FLAGNEW
:
1298 case IDM_MI_FLAGANSWERED
:
1299 case IDM_MI_FLAGDELETED
:
1300 FlagHandler((int)(wParam
- IDM_MI_FLAGIMPORTANT
), 0);
1304 /* value falling within the menu item range are handled here. */
1305 if (wParam
>= KS_RANGESTART
&& wParam
<= KS_RANGEEND
){
1306 ProcessMenuItem (hWnd
, wParam
);
1314 ScrollTTY (hWnd
, LOWORD(wParam
), HIWORD(wParam
), (HWND
) lParam
);
1318 MouseWheelTTY (hWnd
, LOWORD(lParam
), HIWORD(lParam
),
1319 LOWORD(wParam
), (short) HIWORD(wParam
));
1323 if (IsIconic (hWnd
))
1324 return (DefWindowProc (hWnd
, WM_ICONERASEBKGND
, wParam
, lParam
));
1326 EraseTTY (hWnd
, (HDC
) wParam
);
1329 case WM_QUERYDRAGICON
:
1330 return ((LRESULT
)ghNormalIcon
);
1336 case WM_GETMINMAXINFO
:
1337 GetMinMaxInfoTTY (hWnd
, (MINMAXINFO __far
*)lParam
);
1341 SizeTTY (hWnd
, (int)wParam
, HIWORD(lParam
), LOWORD(lParam
));
1345 return(SizingTTY(hWnd
, (int)wParam
, (LPRECT
) lParam
));
1348 /* MoveTTY (hWnd, (int) LOWORD(lParam), (int) HIWORD(lParam)); */
1351 case WM_WINDOWPOSCHANGING
:
1352 /* Allows us to adjust new size of window. */
1353 AboutToSizeTTY (hWnd
, (WINDOWPOS FAR
*) lParam
);
1357 case TASKBAR_ICON_MESSAGE
:
1358 /* Notification of a mouse event in the task bar tray.
1359 * If they are clicking on it we will restore the window. */
1360 if (lParam
== WM_LBUTTONDOWN
){
1361 if(gpTTYInfo
->fMinimized
)
1362 ShowWindow (hWnd
, SW_RESTORE
);
1364 SetForegroundWindow(hWnd
);
1371 * WM_KEYDOWN is sent for every "key press" and reports on the
1372 * keyboard key, with out processing shift and control keys.
1373 * WM_CHAR is a synthetic event, created from KEYDOWN and KEYUP
1374 * events. It includes processing or control and shift characters.
1375 * But does not get generated for extended keys suchs as arrow
1377 * I'm going to try to use KEYDOWN for processing just extended keys
1378 * and let CHAR handle the the rest.
1380 * The only key combo that is special is ^-space. For that, I'll use
1381 * WM_KEYDOWN and WM_KEYUP to track the state of the control key.
1385 * If the windows cursor is visible and we have keyboard input
1386 * then hide the windows cursor
1388 mswin_showcursor(FALSE
);
1389 ProcessTTYCharacter (hWnd
, (TCHAR
)wParam
);
1393 if (ProcessTTYKeyDown (hWnd
, (TCHAR
) wParam
))
1396 return( DefWindowProc( hWnd
, uMsg
, wParam
, lParam
) ) ;
1399 if (gFkeyCallback
&& (*gFkeyCallback
)(0, 0)
1400 && LOBYTE (wParam
) == VK_F10
){
1401 ProcessTTYCharacter (hWnd
, (TCHAR
)wParam
);
1405 return( DefWindowProc( hWnd
, uMsg
, wParam
, lParam
) ) ;
1409 * lParam specifies the context code. Bit 29 is 1 if the ALT key is down
1410 * while the key is pressed.
1412 if (!(lParam
& (1<<29))
1413 && gFkeyCallback
&& (*gFkeyCallback
)(0, 0)
1414 && LOBYTE (wParam
) == VK_F10
1415 && ProcessTTYKeyDown (hWnd
, (TCHAR
) wParam
))
1418 return( DefWindowProc( hWnd
, uMsg
, wParam
, lParam
) ) ;
1421 case WM_LBUTTONDOWN
:
1422 ProcessTTYMouse (hWnd
, M_EVENT_DOWN
, M_BUTTON_LEFT
, LOWORD (lParam
),
1423 HIWORD (lParam
), wParam
);
1427 if (ProcessTTYMouse (hWnd
, M_EVENT_UP
, M_BUTTON_LEFT
, LOWORD (lParam
),
1428 HIWORD (lParam
), wParam
))
1432 case WM_MBUTTONDOWN
:
1433 ProcessTTYMouse (hWnd
, M_EVENT_DOWN
, M_BUTTON_MIDDLE
, LOWORD (lParam
),
1434 HIWORD (lParam
), wParam
);
1438 ProcessTTYMouse (hWnd
, M_EVENT_UP
, M_BUTTON_MIDDLE
, LOWORD (lParam
),
1439 HIWORD (lParam
), wParam
);
1442 case WM_RBUTTONDOWN
:
1443 ProcessTTYMouse (hWnd
, M_EVENT_DOWN
, M_BUTTON_RIGHT
, LOWORD (lParam
),
1444 HIWORD (lParam
), wParam
);
1448 ProcessTTYMouse (hWnd
, M_EVENT_UP
, M_BUTTON_RIGHT
, LOWORD (lParam
),
1449 HIWORD (lParam
), wParam
);
1453 ProcessTTYMouse (hWnd
, M_EVENT_TRACK
, 0, LOWORD (lParam
),
1454 HIWORD (lParam
), wParam
);
1457 case WM_NCMOUSEMOVE
:
1458 mswin_showcursor(TRUE
);
1459 goto callDef
; /* pretend it never happened */
1466 KillTTYFocus (hWnd
);
1470 /* Set cursor. If in client, leave as is. Otherwise, pass to
1472 if (LOWORD(lParam
) == HTCLIENT
) {
1473 SetCursor (ghCursorCurrent
);
1477 return( DefWindowProc( hWnd
, uMsg
, wParam
, lParam
) ) ;
1484 /* Really just used so that we continue to receive messages even while
1485 * in background. Causes mswin_getc() to process message and return
1486 * to caller so that it can get some periodic processing in. */
1490 case WM_QUERYENDSESSION
:
1491 /* Returns non-zero if I can exit, otherwize zero, and the end
1492 * session operation stops. */
1493 return ((LRESULT
)ConfirmExit ());
1496 KillTimer (hWnd
, MY_TIMER_ID
);
1497 DestroyTTYInfo (hWnd
);
1498 PostQuitMessage (0);
1503 if(ProcessTTYFileDrop((HANDLE
) wParam
) == TRUE
)
1504 SetForegroundWindow(hWnd
);
1510 /* If the quit menu is active then insert the quit command
1511 * Otherwise, abort. */
1512 if (gpTTYInfo
->menuItems
[KS_EXIT
- KS_RANGESTART
].miActive
) {
1513 CQAdd (gpTTYInfo
->menuItems
[KS_EXIT
- KS_RANGESTART
].miKey
, 0);
1515 else if (gSignalHUP
!= SIG_DFL
&& gSignalHUP
!= SIG_IGN
) {
1516 if (MessageBox (hWnd
,
1517 TEXT("Abort PINE/PICO, possibly losing current work?"),
1518 gszAppName
, MB_OKCANCEL
| MB_ICONQUESTION
) == IDOK
)
1526 return( DefWindowProc( hWnd
, uMsg
, wParam
, lParam
) ) ;
1530 } /* end of PWndProc() */
1533 /*---------------------------------------------------------------------------
1534 * LRESULT NEAR CreateTTYInfo( HWND hWnd )
1537 * Creates the tty information structure and sets
1538 * menu option availability. Returns -1 if unsuccessful.
1542 * Handle to main window.
1544 *-------------------------------------------------------------------------*/
1546 CreateTTYInfo (HWND hWnd
)
1555 if (mswin_debug
>= 5)
1556 fprintf (mswin_debugfile
, "CreateTTYInfo::: entered\n");
1559 hDC
= GetDC (ghTTYWnd
);
1560 ppi
= GetDeviceCaps (hDC
, LOGPIXELSY
);
1561 ReleaseDC (ghTTYWnd
, hDC
);
1563 pTTYInfo
= (PTTYINFO
) MemAlloc (sizeof (TTYINFO
));
1564 if (pTTYInfo
== NULL
)
1565 return ((LRESULT
) - 1);
1566 gpTTYInfo
= pTTYInfo
;
1568 /* initialize TTY info structure */
1569 memset (pTTYInfo
, 0, sizeof (TTYINFO
));
1570 /* Shown but not focused. */
1571 pTTYInfo
->cCaretStyle
= CaretBlock
;
1572 pTTYInfo
->fMinimized
= FALSE
;
1573 pTTYInfo
->fMaximized
= FALSE
;
1574 pTTYInfo
->fFocused
= FALSE
;
1575 pTTYInfo
->fNewLine
= FALSE
;
1576 pTTYInfo
->fMassiveUpdate
= FALSE
;
1577 pTTYInfo
->fNewMailIcon
= FALSE
;
1578 pTTYInfo
->fMClosedIcon
= FALSE
;
1579 pTTYInfo
->autoWrap
= WRAP_NO_SCROLL
;
1580 pTTYInfo
->xOffset
= MARGINE_LEFT
;
1581 pTTYInfo
->yOffset
= MARGINE_TOP
;
1582 pTTYInfo
->fDesiredSize
= FALSE
;
1583 pTTYInfo
->fCursorOn
= TRUE
;
1588 pico_set_normal_color();
1589 pTTYInfo
->toolBarTop
= TRUE
;
1590 pTTYInfo
->curToolBarID
= IDD_TOOLBAR
;
1592 /* Clear menu item array. */
1593 pTTYInfo
->curWinMenu
= ALPINEMENU
;
1594 for (i
= 0; i
< KS_COUNT
; ++i
)
1595 pTTYInfo
->menuItems
[i
].miActive
= FALSE
;
1596 pTTYInfo
->menuItemsCurrent
= FALSE
;
1598 /* Clear resize callback procs. */
1599 for (i
= 0; i
< RESIZE_CALLBACK_ARRAY_SIZE
; ++i
)
1600 pTTYInfo
->resizer
[i
] = NULL
;
1603 /* clear screen space */
1604 pTTYInfo
->pScreen
= NULL
;
1605 pTTYInfo
->pCellWidth
= NULL
;
1606 pTTYInfo
->pAttrib
= NULL
;
1608 /* setup default font information */
1610 newFont
.lfHeight
= -MulDiv(12, ppi
, 72);
1611 newFont
.lfWidth
= 0;
1612 newFont
.lfEscapement
= 0;
1613 newFont
.lfOrientation
= 0;
1614 newFont
.lfWeight
= 0;
1615 newFont
.lfItalic
= 0;
1616 newFont
.lfUnderline
= 0;
1617 newFont
.lfStrikeOut
= 0;
1618 newFont
.lfCharSet
= FONT_CHARSET_FONT
;
1619 newFont
.lfOutPrecision
= OUT_DEFAULT_PRECIS
;
1620 newFont
.lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
1621 newFont
.lfQuality
= DEFAULT_QUALITY
;
1622 newFont
.lfPitchAndFamily
= FIXED_PITCH
| FF_MODERN
;
1623 _sntprintf(newFont
.lfFaceName
, LF_FACESIZE
, TEXT("%s"), TEXT("Courier New"));
1624 testFont
= CreateFontIndirect(&newFont
);
1625 if(NULL
== testFont
)
1626 newFont
.lfFaceName
[0] = '\0';
1628 DeleteObject(testFont
);
1630 /* set TTYInfo handle before any further message processing. */
1632 MySetWindowLongPtr (hWnd
, GWL_PTTYINFO
, pTTYInfo
);
1634 /* reset the character information, etc. */
1636 ResetTTYFont (hWnd
, pTTYInfo
, &newFont
);
1640 hMenu
= GetMenu (hWnd
);
1641 EnableMenuItem (hMenu
, IDM_EDIT_CUT
, MF_BYCOMMAND
| MF_GRAYED
);
1642 EnableMenuItem (hMenu
, IDM_EDIT_COPY
, MF_BYCOMMAND
| MF_GRAYED
);
1643 EnableMenuItem (hMenu
, IDM_EDIT_COPY_APPEND
, MF_BYCOMMAND
| MF_GRAYED
);
1644 EnableMenuItem (hMenu
, IDM_EDIT_PASTE
, MF_BYCOMMAND
| MF_GRAYED
);
1645 return ((LRESULT
) TRUE
);
1649 /*---------------------------------------------------------------------------
1650 * BOOL NEAR DestroyTTYInfo( HWND hWnd )
1653 * Destroys block associated with TTY window handle.
1657 * handle to TTY window
1659 *-------------------------------------------------------------------------*/
1661 DestroyTTYInfo (HWND hWnd
)
1665 pTTYInfo
= (PTTYINFO
) MyGetWindowLongPtr (hWnd
, GWL_PTTYINFO
);
1666 if (pTTYInfo
== NULL
)
1670 if(pTTYInfo
->hAccel
){
1671 DestroyAcceleratorTable(pTTYInfo
->hAccel
);
1672 pTTYInfo
->hAccel
= NULL
;
1673 pTTYInfo
->fAccel
= EM_NONE
;
1677 if(pTTYInfo
->hTBWnd
!= NULL
)
1678 DestroyWindow (pTTYInfo
->hTBWnd
);
1680 if(pTTYInfo
->hTBBrush
!= NULL
)
1681 DeleteObject(pTTYInfo
->hTBBrush
);
1683 DeleteObject (pTTYInfo
->hTTYFont
);
1690 /*---------------------------------------------------------------------------
1691 * void ResizeTTYScreen( HWND hWnd, PTTYINFO pTTYInfo,
1692 * int newNrow, int newNColumn);
1695 * Resize the screen to new size, copying data.
1699 * pointer to TTY info structure
1700 * newNCo.umn, newNRow
1701 * new size of screen.
1703 /*--------------------------------------------------------------------------*/
1705 ResizeTTYScreen (HWND hWnd
, PTTYINFO pTTYInfo
, int newNRow
, int newNColumn
)
1707 CharAttrib
*pNewAttrib
, tmpAttrib
, *pSourceAtt
, *pDestAtt
;
1708 TCHAR
*pNewScreen
, *pSource
, *pDest
;
1709 int *pNewCW
, *pSourceCW
, *pDestCW
;
1716 if (newNColumn
< MINNCOLUMN
)
1717 newNColumn
= MINNCOLUMN
;
1718 if (newNRow
< MINNROW
)
1722 if (mswin_debug
>= 5)
1723 fprintf (mswin_debugfile
, "ResizeTTYScreen::: entered, new row %d, col %d\n",
1724 newNRow
, newNColumn
);
1729 cells
= newNColumn
* newNRow
;
1730 pNewScreen
= (TCHAR
*)MemAlloc (cells
* sizeof (TCHAR
));
1731 if (pNewScreen
== NULL
)
1734 pNewCW
= (int *)MemAlloc(cells
* sizeof(int));
1736 MemFree((void *)pNewScreen
);
1740 pNewAttrib
= (CharAttrib
*)MemAlloc (cells
* sizeof (CharAttrib
));
1741 if (pNewAttrib
== NULL
) {
1742 MemFree ((void *)pNewScreen
);
1743 MemFree ((void *)pNewCW
);
1752 for(i
= 0; i
< cells
; i
++){
1753 pNewScreen
[i
] = ' ';
1754 pNewCW
[i
] = pTTYInfo
->xChar
; /* xChar set yet ? */
1757 tmpAttrib
.style
= CHAR_ATTR_NORM
;
1758 tmpAttrib
.rgbFG
= pTTYInfo
->rgbFGColor
;
1759 tmpAttrib
.rgbBG
= pTTYInfo
->rgbBGColor
;
1760 for(r
= 0; r
< cells
; r
++)
1761 pNewAttrib
[r
] = tmpAttrib
;
1764 * Copy old screen onto new screen.
1766 if (pTTYInfo
->pScreen
!= NULL
) {
1768 for (r
= 1; r
<= newNRow
&& r
<= pTTYInfo
->actNRow
; ++r
) {
1769 pSource
= pTTYInfo
->pScreen
+ ((pTTYInfo
->actNRow
- r
) *
1770 pTTYInfo
->actNColumn
);
1771 pDest
= pNewScreen
+ ((newNRow
- r
) * newNColumn
);
1772 len
= MIN (newNColumn
, pTTYInfo
->actNColumn
);
1773 for(i
= 0; i
< len
; i
++)
1774 pDest
[i
] = pSource
[i
];
1776 pSourceCW
= pTTYInfo
->pCellWidth
1777 + ((pTTYInfo
->actNRow
- r
) * pTTYInfo
->actNColumn
);
1778 pDestCW
= pNewCW
+ ((newNRow
- r
) * newNColumn
);
1779 memcpy(pDestCW
, pSourceCW
, len
* sizeof(int));
1781 pSourceAtt
= pTTYInfo
->pAttrib
1782 + ((pTTYInfo
->actNRow
- r
) * pTTYInfo
->actNColumn
);
1783 pDestAtt
= pNewAttrib
+ ((newNRow
- r
) * newNColumn
);
1784 len
= MIN (newNColumn
, pTTYInfo
->actNColumn
);
1785 memcpy (pDestAtt
, pSourceAtt
, len
* sizeof(CharAttrib
));
1788 pTTYInfo
->nColumn
= (CORD
)MIN (pTTYInfo
->nColumn
, newNColumn
);
1789 pTTYInfo
->nRow
= (CORD
)MAX (0,
1790 pTTYInfo
->nRow
+ (newNRow
- pTTYInfo
->actNRow
));
1791 MemFree (pTTYInfo
->pScreen
);
1792 MemFree (pTTYInfo
->pCellWidth
);
1793 MemFree (pTTYInfo
->pAttrib
);
1796 pTTYInfo
->nColumn
= (CORD
)MIN (pTTYInfo
->nColumn
, newNColumn
);
1797 pTTYInfo
->nRow
= (CORD
)MIN (pTTYInfo
->nRow
, newNRow
);
1800 pTTYInfo
->pScreen
= pNewScreen
;
1801 pTTYInfo
->pCellWidth
= pNewCW
;
1802 pTTYInfo
->pAttrib
= pNewAttrib
;
1803 pTTYInfo
->actNColumn
= newNColumn
;
1804 pTTYInfo
->actNRow
= newNRow
;
1807 /* Repaint whole screen. */
1808 pTTYInfo
->screenDirty
= TRUE
;
1809 pTTYInfo
->eraseScreen
= TRUE
;
1810 InvalidateRect (hWnd
, NULL
, FALSE
);
1814 /* Pico specific. */
1815 if (term
.t_nrow
== 0) {
1816 term
.t_nrow
= (short)(newNRow
- 1);
1817 term
.t_ncol
= (short)newNColumn
;
1825 /*---------------------------------------------------------------------------
1826 * BOOL ResetTTYFont( HWND hWnd, PTTYINFO pTTYInfo, LOGFONT *newFont)
1829 * Resets the TTY character information and causes the
1830 * screen to resize to update the scroll information.
1834 * pointer to TTY info structure
1836 /*--------------------------------------------------------------------------*/
1838 ResetTTYFont (HWND hWnd
, PTTYINFO pTTYInfo
, LOGFONT
*newFont
)
1849 if (mswin_debug
>= 5)
1850 fprintf (mswin_debugfile
, "ResetTTYFont::: entered, curent window size X %d, Y %d\n",
1851 pTTYInfo
->xSize
, pTTYInfo
->ySize
);
1855 if (NULL
== pTTYInfo
)
1863 hFont
= CreateFontIndirect (newFont
);
1867 SelectObject (hDC
, hFont
);
1868 GetTextMetrics (hDC
, &tm
);
1869 ReleaseDC (hWnd
, hDC
);
1875 if (NULL
!= pTTYInfo
->hTTYFont
)
1876 DeleteObject (pTTYInfo
->hTTYFont
);
1877 pTTYInfo
->hTTYFont
= hFont
;
1878 memcpy (&pTTYInfo
->lfTTYFont
, newFont
, sizeof (LOGFONT
));
1881 /* Update the char cell size. */
1882 pTTYInfo
->xChar
= (CORD
)tm
.tmAveCharWidth
;
1883 pTTYInfo
->yChar
= (CORD
)(tm
.tmHeight
+ tm
.tmExternalLeading
);
1885 /* Update the current number of rows and cols. Don't allow
1886 * either to be less than zero. */
1887 newNRow
= MAX (MINNROW
,
1889 (pTTYInfo
->ySize
- pTTYInfo
->toolBarSize
- (2 * MARGINE_TOP
))/
1891 newNColumn
= MAX (MINNCOLUMN
,
1892 MIN (MAXNCOLUMN
, (pTTYInfo
->xSize
- (2 * pTTYInfo
->xOffset
))/
1895 newsize
= newNRow
!= pTTYInfo
->actNRow
||
1896 newNColumn
!= pTTYInfo
->actNColumn
;
1898 ResizeTTYScreen (hWnd
, pTTYInfo
, newNRow
, newNColumn
);
1900 /* Resize the caret as well. */
1901 if(pTTYInfo
->fCaretOn
)
1905 CaretCreateTTY (hWnd
);
1907 /* Redraw screen and, if the "size" changed, tell the upper layers. */
1908 pTTYInfo
->screenDirty
= TRUE
;
1909 pTTYInfo
->eraseScreen
= TRUE
;
1910 InvalidateRect (hWnd
, NULL
, FALSE
);
1912 /* Always call the resize functions - even if the screen size
1913 * has not changed, the font style may have. */
1914 DidResize (pTTYInfo
);
1920 /*---------------------------------------------------------------------------
1921 * BOOL EraseTTY (HWND hWnd, HDC hDC)
1924 * Erase the tty background.
1929 * handle to TTY window (as always)
1931 /*--------------------------------------------------------------------------*/
1933 EraseTTY (HWND hWnd
, HDC hDC
)
1939 GetClientRect (hWnd
, &erect
);
1940 hBrush
= CreateSolidBrush (gpTTYInfo
->rgbBGColor
);
1941 if (hBrush
!= NULL
) {
1942 FillRect (hDC
, &erect
, hBrush
);
1943 DeleteObject (hBrush
);
1949 /*---------------------------------------------------------------------------
1950 * BOOL PaintTTY( HWND hWnd )
1953 * Paints the rectangle determined by the paint struct of
1958 * handle to TTY window (as always)
1960 /*--------------------------------------------------------------------------*/
1962 PaintTTY (HWND hWnd
)
1964 int nRow
, nCol
; /* Top left corner of update. */
1965 int nEndRow
, nEndCol
; /* lower right corner of update. */
1966 int nHorzPos
, nVertPos
; /* Position of each text write. */
1967 int col
; /* start col of run of similar attr */
1968 int count
; /* count of run of similar attrib. */
1969 int endCount
; /* How far to count. */
1970 CharAttrib
*pAttrib
;
1973 HFONT hOrigFont
, hOldFont
= NULL
, hTmpFont
;
1979 long offset
; /* Offset into pScreen array */
1980 long endoffset
; /* Offset of nEndCol in each row array */
1981 CharAttrib
*pLastAttrib
; /* Attributes of last text write. */
1982 CharAttrib
*pNewAttrib
; /* Attributes of this text write. */
1986 if (mswin_debug
>= 9)
1987 fprintf (mswin_debugfile
, "PaintTTY::: entered\n");
1991 pTTYInfo
= (PTTYINFO
) MyGetWindowLongPtr (hWnd
, GWL_PTTYINFO
);
1992 if (pTTYInfo
== NULL
)
1995 if (IsIconic (hWnd
))
1998 hDC
= BeginPaint (hWnd
, &ps
);
2001 hOrigFont
= SelectObject (hDC
, pTTYInfo
->hTTYFont
);
2002 SetTextColor (hDC
, pTTYInfo
->rgbFGColor
);
2003 SetBkColor (hDC
, pTTYInfo
->rgbBGColor
);
2004 SetBkMode (hDC
, OPAQUE
);
2006 nRow
= (rect
.top
- pTTYInfo
->yOffset
) / pTTYInfo
->yChar
;
2007 CONSTRAIN (nRow
, 0, pTTYInfo
->actNRow
- 1);
2009 nEndRow
= MIN(pTTYInfo
->actNRow
- 1,
2010 ((rect
.bottom
- pTTYInfo
->yOffset
- 1) / pTTYInfo
->yChar
));
2011 nCol
= MIN(pTTYInfo
->actNColumn
- 1,
2012 MAX(0, (rect
.left
- pTTYInfo
->xOffset
) / pTTYInfo
->xChar
));
2013 nEndCol
= MIN(pTTYInfo
->actNColumn
- 1,
2014 ((rect
.right
- pTTYInfo
->xOffset
- 1) / pTTYInfo
->xChar
));
2018 /* Erase screen if necessary. */
2019 if (pTTYInfo
->eraseScreen
) {
2022 erect
.bottom
= pTTYInfo
->ySize
;
2023 erect
.right
= pTTYInfo
->xSize
;
2024 hBrush
= CreateSolidBrush (pTTYInfo
->rgbBGColor
);
2025 if (hBrush
!= NULL
) {
2026 FillRect (hDC
, &erect
, hBrush
);
2027 DeleteObject (hBrush
);
2029 pTTYInfo
->eraseScreen
= FALSE
;
2033 /* Paint an inset frame around the text region. */
2034 if (pTTYInfo
->toolBarSize
== 0) {
2036 erect
.bottom
= pTTYInfo
->ySize
;
2038 else if (pTTYInfo
->toolBarTop
) {
2039 erect
.top
= pTTYInfo
->toolBarSize
;
2040 erect
.bottom
= pTTYInfo
->ySize
;
2044 erect
.bottom
= pTTYInfo
->ySize
- pTTYInfo
->toolBarSize
;
2047 erect
.right
= pTTYInfo
->xSize
;
2048 FrameRect3D (hDC
, &erect
, FRAME_3D_SIZE
, FALSE
);
2050 /* Paint rows of text. */
2051 for (; nRow
<= nEndRow
; nRow
++) {
2052 nVertPos
= (nRow
* pTTYInfo
->yChar
) + pTTYInfo
->yOffset
;
2053 rect
.top
= nVertPos
;
2054 rect
.bottom
= nVertPos
+ pTTYInfo
->yChar
;
2056 /* Paint runs of similar attributes. */
2057 col
= nCol
; /* Start at left. */
2059 if(col
== 0 && MSWIconPaint(nRow
, hDC
))
2063 * col is the column on the screen, not the index
2066 while (col
<= nEndCol
) { /* While not past right. */
2068 /* Starting with Character at nRow, col, what is its attribute? */
2070 /* offset is an index into the array */
2071 offset
= pscreen_offset_from_cord(nRow
, col
, pTTYInfo
);
2072 pNewAttrib
= pTTYInfo
->pAttrib
+ offset
;
2076 && pNewAttrib
->style
== pLastAttrib
->style
2077 && pNewAttrib
->rgbFG
== pLastAttrib
->rgbFG
2078 && pNewAttrib
->rgbBG
== pLastAttrib
->rgbBG
)) {
2083 || (pNewAttrib
->style
& CHAR_ATTR_ULINE
)
2084 != (pLastAttrib
->style
& CHAR_ATTR_ULINE
)){
2085 if(pNewAttrib
->style
& CHAR_ATTR_ULINE
){
2087 * Find suitable attribute font...
2089 memcpy (&tmpFont
, &pTTYInfo
->lfTTYFont
,
2092 tmpFont
.lfHeight
= - pTTYInfo
->yChar
;
2093 tmpFont
.lfWidth
= - pTTYInfo
->xChar
;
2095 tmpFont
.lfUnderline
= (BYTE
)((pNewAttrib
->style
2097 == CHAR_ATTR_ULINE
);
2099 hTmpFont
= CreateFontIndirect (&tmpFont
);
2101 hOldFont
= SelectObject (hDC
, hTmpFont
);
2106 * Set new color attributes. If Reverse or Selected, then
2107 * show in reverse colors. But if neither, or both, then
2110 if(pNewAttrib
->style
& CHAR_ATTR_SEL
){
2111 SetTextColor (hDC
, pNewAttrib
->rgbBG
);
2112 SetBkColor (hDC
, pNewAttrib
->rgbFG
);
2116 && pNewAttrib
->rgbFG
== pLastAttrib
->rgbFG
)
2117 || (pLastAttrib
->style
& CHAR_ATTR_SEL
))
2118 SetTextColor (hDC
, pNewAttrib
->rgbFG
);
2121 && pNewAttrib
->rgbBG
== pLastAttrib
->rgbBG
)
2122 || (pLastAttrib
->style
& CHAR_ATTR_SEL
))
2123 SetBkColor (hDC
, pNewAttrib
->rgbBG
);
2127 /* Find run of similar attributes. */
2129 pAttrib
= pTTYInfo
->pAttrib
+ (offset
+ 1);
2130 /* endoffset is an index into the pScreen array */
2131 endoffset
= pscreen_offset_from_cord(nRow
, nEndCol
, pTTYInfo
);
2132 endCount
= endoffset
- offset
;
2133 while (count
<= endCount
2134 && pAttrib
->style
== pNewAttrib
->style
2135 && pAttrib
->rgbFG
== pNewAttrib
->rgbFG
2136 && pAttrib
->rgbBG
== pNewAttrib
->rgbBG
){
2141 if(hTmpFont
!= NULL
){
2142 /* BUG: compute new offsets based on hTmpFont font if required */
2143 nHorzPos
= (col
* pTTYInfo
->xChar
) + pTTYInfo
->xOffset
;
2144 rect
.left
= nHorzPos
;
2145 rect
.right
= nHorzPos
+ pTTYInfo
->xChar
* scrwidth(pTTYInfo
->pScreen
+offset
, count
);
2148 /* Paint run of characters from nRow, col to nRow, col + count
2149 * rect.top and rect.bottom have already been calculated. */
2150 nHorzPos
= (col
* pTTYInfo
->xChar
) + pTTYInfo
->xOffset
;
2151 rect
.left
= nHorzPos
;
2152 rect
.right
= nHorzPos
+ pTTYInfo
->xChar
* scrwidth(pTTYInfo
->pScreen
+offset
, count
);
2155 ExtTextOut (hDC
, nHorzPos
, nVertPos
, ETO_OPAQUE
| ETO_CLIPPED
,
2156 &rect
, (LPTSTR
) (pTTYInfo
->pScreen
+ offset
),
2157 count
, (int *)(pTTYInfo
->pCellWidth
+offset
));
2159 /* Overstrike bold chars by hand to preserve char cell size */
2160 if(pNewAttrib
->style
& CHAR_ATTR_BOLD
){
2161 int old_mode
= GetBkMode(hDC
);
2162 SetBkMode (hDC
, TRANSPARENT
);
2163 ExtTextOut (hDC
, nHorzPos
+ 1, nVertPos
, 0,
2164 &rect
, (LPTSTR
) (pTTYInfo
->pScreen
+ offset
),
2165 count
, (int *)(pTTYInfo
->pCellWidth
+offset
));
2167 SetBkMode (hDC
, old_mode
);
2170 /* Move pointer to end of this span of characters. */
2171 col
+= MAX(scrwidth(pTTYInfo
->pScreen
+offset
, count
), 1);
2172 pLastAttrib
= pNewAttrib
;
2174 if(hTmpFont
!= NULL
){
2175 SelectObject(hDC
, hOldFont
);
2176 DeleteObject(hTmpFont
);
2181 SelectObject (hDC
, hOrigFont
);
2182 EndPaint (hWnd
, &ps
);
2183 MoveTTYCursor (hWnd
);
2184 pTTYInfo
->screenDirty
= FALSE
;
2193 * FillRectColor is similar to PatB in toolbar.c
2195 * Code based on MFC source code, so presumably efficient.
2199 FillRectColor(HDC hDC
, RECT
* pRC
, COLORREF color
)
2201 SetBkColor(hDC
, color
);
2202 ExtTextOut(hDC
, 0, 0, ETO_OPAQUE
, pRC
, NULL
, 0, NULL
);
2211 * pRC - pointer to rectangle
2212 * width - width for frame (usually one)
2213 * raised - TRUE for raised effect, FALSE for sunken effect
2222 * Draws a frame with a 3D effect.
2224 * If 'raised' is true, the rectangle will look raised (like
2225 * a button); otherwise, the rectangle will look sunk.
2229 FrameRect3D(HDC hdc
, RECT
* pRC
, int width
, BOOL raised
)
2231 COLORREF hilite
, shadow
;
2234 shadow
= GetSysColor(COLOR_BTNSHADOW
);
2235 hilite
= GetSysColor(COLOR_BTNHIGHLIGHT
);
2239 rcTemp
.right
= rcTemp
.left
+ width
;
2240 FillRectColor(hdc
, &rcTemp
, raised
? hilite
: shadow
);
2241 rcTemp
.right
= pRC
->right
;
2243 rcTemp
.bottom
= rcTemp
.top
+ width
;
2244 FillRectColor(hdc
, &rcTemp
, raised
? hilite
: shadow
);
2245 rcTemp
.bottom
= pRC
->bottom
;
2247 rcTemp
.left
= rcTemp
.right
- width
;
2248 FillRectColor(hdc
, &rcTemp
, raised
? shadow
: hilite
);
2249 rcTemp
.left
= pRC
->left
;
2251 rcTemp
.top
= rcTemp
.bottom
- width
;
2252 FillRectColor(hdc
, &rcTemp
, raised
? shadow
: hilite
);
2256 /*---------------------------------------------------------------------------
2257 * BOOL GetMinMaxInfoTTY (HWND hWnd, (MINMAXINFO __far *)lParam)
2260 * Return the min and max size that the window can be.
2264 * handle to TTY window
2267 * Info structure that Windows would like us to fill.
2269 /*--------------------------------------------------------------------------*/
2271 GetMinMaxInfoTTY (HWND hWnd
, MINMAXINFO __far
*lpmmi
)
2277 if (mswin_debug
>= 5)
2278 fprintf (mswin_debugfile
, "GetMinMaxInfoTTY::: entered\n");
2282 pTTYInfo
= (PTTYINFO
) MyGetWindowLongPtr (hWnd
, GWL_PTTYINFO
);
2283 if (pTTYInfo
== NULL
)
2286 lpmmi
->ptMaxTrackSize
.x
= lpmmi
->ptMaxSize
.x
= MIN (lpmmi
->ptMaxSize
.x
,
2287 pTTYInfo
->xChar
* MAXNCOLUMN
+ WIN_X_BORDER_SIZE
);
2288 lpmmi
->ptMaxTrackSize
.y
= lpmmi
->ptMaxSize
.y
= MIN (lpmmi
->ptMaxSize
.y
,
2289 pTTYInfo
->yChar
* MAXNROW
+ WIN_Y_BORDER_SIZE
);
2291 lpmmi
->ptMinTrackSize
.x
= MAX (WIN_MIN_X_SIZE
,
2292 pTTYInfo
->xChar
* MINNCOLUMN
+ WIN_X_BORDER_SIZE
);
2293 lpmmi
->ptMinTrackSize
.y
= MAX (WIN_MIN_Y_SIZE
,
2294 pTTYInfo
->yChar
* MINNROW
+ WIN_Y_BORDER_SIZE
);
2299 /*---------------------------------------------------------------------------
2300 * BOOL AboutToSizeTTY (HWND hWnd, WINDOWPOS *winPos)
2303 * Called just before Windows resizes our window. We can change the
2304 * values in 'winPos' to change the new size of the window.
2306 * If mswin_setwindow() was called when the window was minimized we
2307 * set the new size here.
2311 * handle to TTY window
2317 * new horizontal size
2319 /*--------------------------------------------------------------------------*/
2321 AboutToSizeTTY (HWND hWnd
, WINDOWPOS
*winPos
)
2326 pTTYInfo
= (PTTYINFO
) MyGetWindowLongPtr (hWnd
, GWL_PTTYINFO
);
2327 if (pTTYInfo
== NULL
)
2331 if (mswin_debug
>= 5)
2332 fprintf (mswin_debugfile
, "AboutToSizeTTY::: After x%lx, pos %d, %d, size %d, %d, flags x%x\n",
2333 winPos
->hwndInsertAfter
, winPos
->x
, winPos
->y
, winPos
->cx
,
2334 winPos
->cy
, winPos
->flags
);
2339 * Was the window minimized AND is there a desired new size for it?
2340 * AND is this a call that specifies a new size and position.
2342 if (pTTYInfo
->fMinimized
&& pTTYInfo
->fDesiredSize
&&
2343 (winPos
->flags
& (SWP_NOSIZE
| SWP_NOMOVE
)) == 0) {
2345 if (mswin_debug
>= 5)
2346 fprintf (mswin_debugfile
, "AboutToSizeTTY::: substitue pos (%d, %d), size (%d, %d)\n",
2347 pTTYInfo
->xDesPos
, pTTYInfo
->yDesPos
,
2348 pTTYInfo
->xDesSize
, pTTYInfo
->yDesSize
);
2350 pTTYInfo
->fDesiredSize
= FALSE
;
2351 winPos
->x
= pTTYInfo
->xDesPos
;
2352 winPos
->y
= pTTYInfo
->yDesPos
;
2353 winPos
->cx
= pTTYInfo
->xDesSize
;
2354 winPos
->cy
= pTTYInfo
->yDesSize
;
2360 /*---------------------------------------------------------------------------
2361 * BOOL SizeTTY( HWND hWnd, int fwSizeType, CORD wVertSize,
2365 * Sizes TTY and sets up scrolling regions.
2369 * handle to TTY window
2375 * new horizontal size
2377 /*--------------------------------------------------------------------------*/
2379 SizeTTY (HWND hWnd
, int fwSizeType
, CORD wVertSize
, CORD wHorzSize
)
2387 if (mswin_debug
>= 5)
2388 fprintf (mswin_debugfile
, "SizeTTY::: entered, sizeType %d, New screen size %d, %d pixels\n",
2389 fwSizeType
, wHorzSize
, wVertSize
);
2392 pTTYInfo
= (PTTYINFO
) MyGetWindowLongPtr (hWnd
, GWL_PTTYINFO
);
2393 if (pTTYInfo
== NULL
)
2398 * Is the window being minimized or maximized?
2400 switch (fwSizeType
) {
2401 case SIZE_MINIMIZED
:
2402 pTTYInfo
->fMinimized
= TRUE
;
2403 pTTYInfo
->fMaximized
= FALSE
;
2405 case SIZE_MAXIMIZED
:
2406 pTTYInfo
->fMinimized
= FALSE
;
2407 pTTYInfo
->fMaximized
= TRUE
;
2410 pTTYInfo
->fMinimized
= pTTYInfo
->fMaximized
= FALSE
;
2414 pTTYInfo
->ySize
= (CORD
) wVertSize
;
2415 newNRow
= MAX(MINNROW
, MIN(MAXNROW
,
2416 (pTTYInfo
->ySize
- pTTYInfo
->toolBarSize
- (2 * MARGINE_TOP
)) /
2418 if (pTTYInfo
->toolBarTop
)
2419 pTTYInfo
->yOffset
= MARGINE_TOP
+ pTTYInfo
->toolBarSize
;
2421 pTTYInfo
->yOffset
= MARGINE_TOP
;
2424 pTTYInfo
->xSize
= (CORD
) wHorzSize
;
2425 newNColumn
= MAX(MINNCOLUMN
,
2426 MIN(MAXNCOLUMN
, (pTTYInfo
->xSize
- (2 * MARGINE_LEFT
)) /
2428 pTTYInfo
->xOffset
= MARGINE_LEFT
;
2430 if(newNRow
== pTTYInfo
->actNRow
&& newNColumn
== pTTYInfo
->actNColumn
)
2433 ResizeTTYScreen (hWnd
, pTTYInfo
, newNRow
, newNColumn
);
2434 pTTYInfo
->screenDirty
= TRUE
;
2435 pTTYInfo
->eraseScreen
= TRUE
;
2436 InvalidateRect (hWnd
, NULL
, FALSE
);
2438 if (pTTYInfo
->hTBWnd
) {
2439 if (pTTYInfo
->toolBarTop
)
2440 /* Position at top of window. */
2441 SetWindowPos (pTTYInfo
->hTBWnd
, HWND_TOP
,
2443 wHorzSize
, pTTYInfo
->toolBarSize
,
2444 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_SHOWWINDOW
);
2446 /* Position at bottom of window. */
2447 SetWindowPos (pTTYInfo
->hTBWnd
, HWND_TOP
,
2448 0, pTTYInfo
->ySize
- pTTYInfo
->toolBarSize
,
2449 wHorzSize
, pTTYInfo
->toolBarSize
,
2450 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_SHOWWINDOW
);
2454 DidResize (pTTYInfo
);
2460 /*---------------------------------------------------------------------------
2461 * BOOL SizingTTY( HWND hWnd, int fwSide, LPRECT pRect)
2464 * Snaps the drag rectangle to char width/height boundaries
2468 * handle to TTY window
2471 * edge of window being sized
2474 * screen coords of drag rectangle in and desired size on return
2476 /*--------------------------------------------------------------------------*/
2478 SizingTTY (HWND hWnd
, int fwSide
, LPRECT pRect
)
2481 int newNRow
, newNCol
, xClient
, yClient
,
2482 xSys
, ySys
, xDiff
, yDiff
;
2484 pTTYInfo
= (PTTYINFO
) MyGetWindowLongPtr (hWnd
, GWL_PTTYINFO
);
2485 if (pTTYInfo
== NULL
)
2488 xSys
= (2 * GetSystemMetrics(SM_CXSIZEFRAME
))
2489 + GetSystemMetrics(SM_CXVSCROLL
);
2490 ySys
= (2 * GetSystemMetrics(SM_CYSIZEFRAME
))
2491 + GetSystemMetrics(SM_CYCAPTION
)
2492 + GetSystemMetrics(SM_CYMENU
);
2494 newNCol
= (((pRect
->right
- pRect
->left
) - xSys
)
2495 - (2 * MARGINE_LEFT
)) / pTTYInfo
->xChar
;
2496 newNRow
= (((pRect
->bottom
- pRect
->top
) - ySys
) - (2 * MARGINE_TOP
)
2497 - pTTYInfo
->toolBarSize
) / pTTYInfo
->yChar
;
2499 xClient
= (newNCol
* pTTYInfo
->xChar
) + (2 * MARGINE_LEFT
);
2500 yClient
= (newNRow
* pTTYInfo
->yChar
) + (2 * MARGINE_TOP
)
2501 + pTTYInfo
->toolBarSize
;
2503 xDiff
= (pRect
->left
+ xClient
+ xSys
) - pRect
->right
;
2504 yDiff
= (pRect
->top
+ yClient
+ ySys
) - pRect
->bottom
;
2506 if(!(xDiff
|| yDiff
))
2510 case WMSZ_BOTTOM
: /* Bottom edge */
2511 pRect
->bottom
+= yDiff
;
2514 case WMSZ_BOTTOMLEFT
: /*Bottom-left corner */
2515 pRect
->bottom
+= yDiff
;
2516 pRect
->left
-= xDiff
;
2519 case WMSZ_BOTTOMRIGHT
: /* Bottom-right corner */
2520 pRect
->bottom
+= yDiff
;
2521 pRect
->right
+= xDiff
;
2524 case WMSZ_LEFT
: /* Left edge */
2525 pRect
->left
-= xDiff
;
2528 case WMSZ_RIGHT
: /* Right edge */
2529 pRect
->right
+= xDiff
;
2532 case WMSZ_TOP
: /* Top edge */
2533 pRect
->top
-= yDiff
;
2536 case WMSZ_TOPLEFT
: /* Top-left corner */
2537 pRect
->top
-= yDiff
;
2538 pRect
->left
-= xDiff
;
2541 case WMSZ_TOPRIGHT
: /* Top-right corner */
2542 pRect
->top
-= yDiff
;
2543 pRect
->right
+= xDiff
;
2550 if(!(newNRow
== pTTYInfo
->actNRow
&& newNCol
== pTTYInfo
->actNColumn
))
2551 SizeTTY(hWnd
, SIZE_RESTORED
, (CORD
) yClient
, (CORD
) xClient
);
2557 /*---------------------------------------------------------------------------
2558 * BOOL MoveTTY (HWND hWnd, int xPos, int yPos)
2561 * Notes the fact that the window has moved.
2562 * Only real purpose is so we can tell pine which can the write the
2563 * new window position to the 'pinerc' file.
2567 * handle to TTY window
2570 * New position of the top left corner.
2573 /*--------------------------------------------------------------------------*/
2575 MoveTTY (HWND hWnd
, int xPos
, int yPos
)
2578 if (mswin_debug
>= 5)
2579 fprintf (mswin_debugfile
, "MoveTTY::: entered\n");
2582 DidResize (gpTTYInfo
);
2587 /*---------------------------------------------------------------------------
2591 * Respond to a scroll message by either calling the scroll
2592 * callback or inserting a scroll character into the input
2595 * Scrolling in the TTY window is complicated by the way pine
2596 * process events. Normal windows applications are entirly event
2597 * driven. The top level does nothing but dispatch events. In
2598 * pine, the top level implements the logic. Events are only
2599 * dispatched by the lowest levels.
2601 * In normal applications, mouse down in the scroll bar causes
2602 * an internal scroll function to be entered. It tracks the
2603 * mouse and issues scroll messages as needed. If the
2604 * application redraws the screen the scroll function also
2605 * dispatches the WM_PAINT message to the application. The
2606 * important thing is that this internal scroll function does
2607 * not exit until the mouse is released.
2609 * We implement two methods for pine's screen managers to deal
2610 * with scroll events. They can receive scroll events as
2611 * characters in the normal input stream or they can register a
2612 * callback function.
2614 * In the "insert a character in the queue" mode, the scroll
2615 * event never gets process until the mouse is release. Auto
2616 * repeat scroll events (generated as the mouse is held down)
2617 * will cause multiple chars to be inserted in the queue, none
2618 * of which will get processed till the mouse is release. In a
2619 * compromise, we allow only one scroll char in the queue,
2620 * which prevents makes for a more friendly and controllable
2623 * In the callback mode, the callback repaints the screen, and
2624 * then it calls mswin_flush() which PROCESSES EVENTS! The
2625 * Windows internal scroll function does NOT expect that. This
2626 * behavior can confuses the scroll function, causing it to
2627 * miss mouse up events. We avoid this by setting gScrolling TRUE
2628 * when this routine is entered and FALSE when this routine exits
2629 * All PeekMessage processors avoid processing any message when
2630 * gScrolling is TRUE.
2632 /*--------------------------------------------------------------------------*/
2634 ScrollTTY (HWND hWnd
, int wScrollCode
, int nPos
, HWND hScroll
)
2638 long scroll_pos
= 0;
2639 BOOL noAction
= FALSE
;
2641 FARPROC prevBlockingProc
;
2645 pTTYInfo
= (PTTYINFO
) MyGetWindowLongPtr (hWnd
, GWL_PTTYINFO
);
2647 if (pTTYInfo
== NULL
|| gScrolling
)
2651 if (gWSBlockingProc
!= NULL
)
2652 prevBlockingProc
= WSASetBlockingHook (gWSBlockingProc
);
2657 switch (wScrollCode
) {
2659 cmd
= MSWIN_KEY_SCROLLTO
;
2660 scroll_pos
= pTTYInfo
->scrollTo
= 0;
2664 cmd
= MSWIN_KEY_SCROLLTO
;
2665 scroll_pos
= pTTYInfo
->scrollTo
= pTTYInfo
->scrollRange
;
2669 cmd
= MSWIN_KEY_SCROLLDOWNLINE
;
2674 cmd
= MSWIN_KEY_SCROLLUPLINE
;
2679 cmd
= MSWIN_KEY_SCROLLDOWNPAGE
;
2684 cmd
= MSWIN_KEY_SCROLLUPPAGE
;
2689 case SB_THUMBPOSITION
:
2690 cmd
= MSWIN_KEY_SCROLLTO
;
2691 scroll_pos
= pTTYInfo
->scrollTo
= (long) ((float)nPos
);
2701 * If there is a scroll callback call that. If there is no scroll
2702 * callback or the callback says it did not handle the event (returned,
2703 * FALSE) queue the scroll cmd.
2708 if (gScrollCallback
!= NULL
) {
2709 /* Call scrolling callback. Set blocking hook to our routine
2710 * which prevents messages from being dispatched. */
2711 if (gWSBlockingProc
!= NULL
)
2712 WSASetBlockingHook (gWSBlockingProc
);
2713 didScroll
= gScrollCallback (cmd
, scroll_pos
);
2714 if (gWSBlockingProc
!= NULL
)
2715 WSAUnhookBlockingHook ();
2718 * If no callback or callback did not do the scrolling operation,
2719 * insert a scroll cmd in the input stream.
2722 CQAddUniq ((UCS
)cmd
, 0);
2732 /*---------------------------------------------------------------------------
2733 * void MouseWheelTTY ()
2736 * Respond to a WM_MOUSEWHEEL event by calling scroll callback
2740 /*--------------------------------------------------------------------------*/
2742 MouseWheelTTY (HWND hWnd
, int xPos
, int yPos
, int fwKeys
, int zDelta
)
2747 FARPROC prevBlockingProc
;
2748 SCROLLINFO scrollInfo
;
2749 static int zDelta_accumulated
;
2751 pTTYInfo
= (PTTYINFO
) MyGetWindowLongPtr (hWnd
, GWL_PTTYINFO
);
2753 if (pTTYInfo
== NULL
|| gScrolling
)
2756 scrollInfo
.cbSize
= sizeof(SCROLLINFO
);
2757 scrollInfo
.fMask
= SIF_POS
| SIF_RANGE
;
2758 GetScrollInfo(hWnd
, SB_VERT
, &scrollInfo
);
2759 if((zDelta
< 0 && scrollInfo
.nPos
< scrollInfo
.nMin
)
2760 || (zDelta
> 0 && scrollInfo
.nPos
>= scrollInfo
.nMax
))
2764 if (gWSBlockingProc
!= NULL
)
2765 prevBlockingProc
= WSASetBlockingHook (gWSBlockingProc
);
2767 if(fwKeys
== MK_MBUTTON
)
2768 zDelta
*= 2; /* double the effect! */
2770 if(abs(zDelta
+= zDelta_accumulated
) < WHEEL_DELTA
){
2771 zDelta_accumulated
= zDelta
;
2774 /* Remember any partial increments */
2775 zDelta_accumulated
= zDelta
% WHEEL_DELTA
;
2777 scroll_pos
= (long)(gsMWMultiplier
* abs((zDelta
/ WHEEL_DELTA
)));
2779 cmd
= (zDelta
< 0) ? MSWIN_KEY_SCROLLDOWNLINE
: MSWIN_KEY_SCROLLUPLINE
;
2782 if (gScrollCallback
!= NULL
) {
2783 /* Call scrolling callback. Set blocking hook to our routine
2784 * which prevents messages from being dispatched. */
2785 if (gWSBlockingProc
!= NULL
)
2786 WSASetBlockingHook (gWSBlockingProc
);
2787 (void) gScrollCallback (cmd
, scroll_pos
);
2788 if (gWSBlockingProc
!= NULL
)
2789 WSAUnhookBlockingHook ();
2799 MouseWheelMultiplier()
2802 DWORD llen
= sizeof(lines
)/sizeof(TCHAR
);
2804 /* HKEY_CURRENT_USER\Control Panel\Desktop holds the key */
2805 gsMWMultiplier
= (MSWRPeek(HKEY_CURRENT_USER
, TEXT("Control Panel\\Desktop"),
2806 TEXT("WheelScrollLines"), lines
, &llen
) == TRUE
)
2807 ? (short)_ttoi(lines
) : 1;
2812 /*---------------------------------------------------------------------------
2813 * void CaretTTY (HWND hWnd, CARETS cStyle)
2816 * Adjusts the Caret to the user supplied style
2820 * handle to TTY window
2823 * New style to take on
2825 /*--------------------------------------------------------------------------*/
2827 CaretTTY (HWND hWnd
, CARETS cStyle
)
2831 if(pTTYInfo
= (PTTYINFO
) MyGetWindowLongPtr (hWnd
, GWL_PTTYINFO
)){
2832 pTTYInfo
->cCaretStyle
= cStyle
;
2833 CaretCreateTTY (hWnd
);
2834 DidResize (gpTTYInfo
);
2839 /*---------------------------------------------------------------------------
2840 * void CaretCreateTTY (HWND hWnd, BOOL wPosition)
2843 * Adjusts the Caret to the user supplied style
2847 * handle to TTY window
2850 * whether or not to position it too
2852 /*--------------------------------------------------------------------------*/
2854 CaretCreateTTY (HWND hWnd
)
2858 if(pTTYInfo
= (PTTYINFO
) MyGetWindowLongPtr (hWnd
, GWL_PTTYINFO
)){
2861 switch(pTTYInfo
->cCaretStyle
){
2862 case CaretHorizBar
:
2863 x
= pTTYInfo
->xChar
;
2864 y
= pTTYInfo
->yChar
/ 5;
2865 n
= pTTYInfo
->yChar
- y
;
2869 x
= pTTYInfo
->xChar
/ 4;
2870 y
= pTTYInfo
->yChar
;
2873 case CaretSmallBlock
:
2874 x
= pTTYInfo
->xChar
;
2875 y
= pTTYInfo
->yChar
/ 2;
2876 n
= pTTYInfo
->yChar
- y
;
2880 x
= pTTYInfo
->xChar
;
2881 y
= pTTYInfo
->yChar
;
2885 CreateCaret (hWnd
, NULL
, x
, y
);
2886 pTTYInfo
->yCurOffset
= n
;
2888 if(pTTYInfo
->fCaretOn
){
2890 MoveTTYCursor(hWnd
);
2897 * This routine is inserted as the winsock blocking hook. It's main perpos
2898 * is to NOT dispatch messages.
2900 BOOL CALLBACK __export
2901 NoMsgsAreSent (void)
2907 /*---------------------------------------------------------------------------
2908 * BOOL SetTTYFocus( HWND hWnd )
2911 * Sets the focus to the TTY window also creates caret.
2915 * handle to TTY window
2917 /*--------------------------------------------------------------------------*/
2919 SetTTYFocus (HWND hWnd
)
2924 if (mswin_debug
>= 5)
2925 fprintf (mswin_debugfile
, "SetTTYFocus::: entered\n");
2928 pTTYInfo
= (PTTYINFO
) MyGetWindowLongPtr (hWnd
, GWL_PTTYINFO
);
2929 if (pTTYInfo
== NULL
)
2932 mswin_showcursor(TRUE
);
2934 pTTYInfo
->fFocused
= TRUE
;
2936 CaretCreateTTY (hWnd
);
2938 MoveTTYCursor (hWnd
);
2943 /*---------------------------------------------------------------------------
2944 * BOOL KillTTYFocus( HWND hWnd )
2947 * Kills TTY focus and destroys the caret.
2951 * handle to TTY window
2953 /*--------------------------------------------------------------------------*/
2955 KillTTYFocus (HWND hWnd
)
2960 if (mswin_debug
>= 5)
2961 fprintf (mswin_debugfile
, "KillTTYFocus::: entered\n");
2963 pTTYInfo
= (PTTYINFO
) MyGetWindowLongPtr (hWnd
, GWL_PTTYINFO
);
2964 if (pTTYInfo
== NULL
)
2967 mswin_showcursor(TRUE
);
2969 if(pTTYInfo
->fCaretOn
)
2974 pTTYInfo
->fFocused
= FALSE
;
2980 /*---------------------------------------------------------------------------
2981 * BOOL MoveTTYCursor( HWND hWnd )
2984 * Moves caret to current position.
2988 * handle to TTY window
2990 /*--------------------------------------------------------------------------*/
2992 MoveTTYCursor (HWND hWnd
)
2996 pTTYInfo
= (PTTYINFO
) MyGetWindowLongPtr (hWnd
, GWL_PTTYINFO
);
2997 if (pTTYInfo
== NULL
)
3000 if(pTTYInfo
->fCaretOn
&& !pTTYInfo
->fMassiveUpdate
) {
3002 SetCaretPos ((pTTYInfo
->nColumn
* pTTYInfo
->xChar
) + pTTYInfo
->xOffset
,
3003 (pTTYInfo
->nRow
* pTTYInfo
->yChar
)
3004 + pTTYInfo
->yCurOffset
+ pTTYInfo
->yOffset
);
3012 /*---------------------------------------------------------------------------
3013 * BOOL ProcessTTYKeyDown ( HWND hWnd, WORD bOut )
3016 * Called to process MW_KEYDOWN message. We are only interested in
3017 * virtual keys that pico/pine use. All others get passed on to
3018 * the default message handler. Regular key presses will return
3019 * latter as a WM_CHAR message, with SHIFT and CONTROL processing
3022 * We do watch for VK_CONTROL to keep track of it's state such
3023 * that we can implement ^_space.
3027 * handle to TTY window
3032 /*--------------------------------------------------------------------------*/
3034 ProcessTTYKeyDown (HWND hWnd
, TCHAR key
)
3037 BOOL fKeyControlDown
= GetKeyState(VK_CONTROL
) < 0;
3038 BOOL fKeyAltDown
= GetKeyState(VK_MENU
) < 0;
3040 // If the alt key is down, let Windows handle the message. This will
3041 // allow the Ctrl+Alt (AltGr) processing to work.
3050 case VK_UP
: myKey
= KEY_UP
; break;
3051 case VK_DOWN
: myKey
= KEY_DOWN
; break;
3053 /* Ctrl-@ is used to advance to the next word. */
3054 myKey
= fKeyControlDown
? '@': KEY_RIGHT
;
3057 /* Ctrl-left is used to advance to the previous word. */
3061 /* Ctrl-home is used to advance to the beginning of buffer. */
3065 /* Ctrl-end is used to advance to the end of buffer. */
3068 case VK_PRIOR
: myKey
= KEY_PGUP
; break;
3069 case VK_NEXT
: myKey
= KEY_PGDN
; break;
3070 case VK_DELETE
: myKey
= KEY_DEL
; break;
3071 case VK_F1
: myKey
= F1
; break;
3072 case VK_F2
: myKey
= F2
; break;
3073 case VK_F3
: myKey
= F3
; break;
3074 case VK_F4
: myKey
= F4
; break;
3075 case VK_F5
: myKey
= F5
; break;
3076 case VK_F6
: myKey
= F6
; break;
3077 case VK_F7
: myKey
= F7
; break;
3078 case VK_F8
: myKey
= F8
; break;
3079 case VK_F9
: myKey
= F9
; break;
3080 case VK_F10
: myKey
= F10
; break;
3081 case VK_F11
: myKey
= F11
; break;
3082 case VK_F12
: myKey
= F12
; break;
3085 if(fKeyControlDown
&& !(GetKeyState(VK_SHIFT
) < 0)) {
3088 * Ctrl-^ is used to set and clear the mark in the
3089 * composer (pico) On most other systems Ctrl-6 does the
3090 * same thing. Allow that on windows too.
3094 } else if(key
== '2') {
3095 /* Ctrl-@ is used to advance to the next word. */
3101 return (FALSE
); /* Message NOT handled.*/
3104 CQAdd (myKey
, fKeyControlDown
);
3106 set_time_of_last_input();
3108 return (TRUE
); /* Message handled .*/
3116 static char timestring
[23];
3118 struct _timeb timebuffer
;
3120 timestring
[0] = '\0';
3121 t
= time((time_t *) 0);
3122 _ftime(&timebuffer
);
3123 snprintf(timestring
, sizeof(timestring
), "%.8s.%03ld", ctime(&t
)+11, timebuffer
.millitm
);
3130 /*---------------------------------------------------------------------------
3131 * BOOL ProcessTTYCharacter( HWND hWnd, WORD bOut )
3134 * Place the character into a queue.
3138 * handle to TTY window
3141 * byte from keyboard
3143 /*--------------------------------------------------------------------------*/
3145 ProcessTTYCharacter (HWND hWnd
, TCHAR bOut
)
3147 // Only check for control key being down if the alt key isn't also down.
3148 // Windows uses Ctrl+Alt as AltGr.
3149 BOOL fKeyAltDown
= GetKeyState(VK_MENU
) < 0;
3150 BOOL fKeyControlDown
= fKeyAltDown
?
3151 FALSE
: (GetKeyState(VK_CONTROL
) < 0);
3153 if(fKeyControlDown
) {
3160 CQAdd ((UCS
)bOut
, fKeyControlDown
);
3163 UpdateAccelerators (hWnd
);
3166 set_time_of_last_input();
3168 return (TRUE
); /* Message handled. */
3172 /*---------------------------------------------------------------------------
3173 * BOOL ProcessTTYMouse(HWND hWnd, int mevent, int button,
3174 * int xPos, int yPos, WPARAM keys)
3177 * This is the central control for all mouse events. Every event
3178 * gets put into a queue to wait for the upper layer.
3180 * The upper's input routine calls checkmouse() which pulls the
3181 * mouse event off the input queue. checkmouse() has a list of
3182 * of screen regions. Some regions correspond to a "menu" item
3183 * (text button at bottom of screen). There is generally one
3184 * region for the central region of the screen.
3186 * Because pine/pico do not interpret mouse drags, we do that here.
3187 * When the user presses the button and drags the mouse across the
3188 * screen this select the text in the region defined by the drag.
3189 * The operation is local to mswin.c, and can only get what text
3192 * The one exception is that now pico interprets mouse drag events
3193 * in the body. pico signals that it wants to track the mouse
3194 * by calling mswin_allowmousetrack(). This will 1) turn off
3195 * our mouse tracking and 2) cause mouse movement events to
3196 * be put on the mouse queue.
3201 * handle to TTY window
3204 * byte from keyboard
3206 /*--------------------------------------------------------------------------*/
3208 ProcessTTYMouse (HWND hWnd
, int mevent
, int button
,
3209 CORD xPos
, CORD yPos
, WPARAM winkeys
)
3216 * Convert to cell position.
3218 nColumn
= (xPos
- gpTTYInfo
->xOffset
) / gpTTYInfo
->xChar
;
3219 if (xPos
< gpTTYInfo
->xOffset
)
3221 nRow
= (yPos
- gpTTYInfo
->yOffset
) / gpTTYInfo
->yChar
;
3222 if (yPos
< gpTTYInfo
->yOffset
)
3226 * Convert window's keys.
3229 if (winkeys
& MK_CONTROL
)
3230 keys
|= M_KEY_CONTROL
;
3231 if (winkeys
& MK_SHIFT
)
3232 keys
|= M_KEY_SHIFT
;
3234 /* Adjust the cursor */
3235 if((unsigned long) mevent
!= M_EVENT_UP
){
3237 mswin_setcursor(MSWIN_CURSOR_IBEAM
);
3238 else if(ghCursorCurrent
== ghCursorBusy
)
3239 mswin_setcursor(MSWIN_CURSOR_BUSY
);
3240 else if(mouse_on_key(nRow
, nColumn
))
3241 mswin_setcursor(MSWIN_CURSOR_HAND
);
3242 else if(gMouseTrackCallback
)
3243 mswin_setcursor((*gMouseTrackCallback
)(nColumn
, (long) nRow
));
3245 mswin_setcursor(MSWIN_CURSOR_ARROW
);
3249 * Tracking event or mouse up/down?
3251 if ((unsigned long) mevent
== M_EVENT_TRACK
) {
3253 * Who is doing the tracking?
3255 if (gAllowMouseTrack
) {
3256 /* For tracking, Button info is different. */
3257 if (keys
& MK_LBUTTON
)
3258 button
= M_BUTTON_LEFT
;
3259 else if (keys
& MK_MBUTTON
)
3260 button
= M_BUTTON_MIDDLE
;
3261 else if (keys
& MK_RBUTTON
)
3262 button
= M_BUTTON_RIGHT
;
3263 MQAdd (mevent
, button
, nRow
, nColumn
, keys
,
3264 MSWIN_MF_REPLACING
);
3267 SelTrackMouse (nRow
, nColumn
);
3271 * Tracking. Only start tracking mouse down in the text region
3272 * But allow mouse up anywhere.
3274 if ( (nRow
>= 0 && nRow
< gpTTYInfo
->actNRow
&&
3275 nColumn
>= 0 && nColumn
< gpTTYInfo
->actNColumn
)
3276 || (unsigned long) mevent
== M_EVENT_UP
) {
3279 * Mouse tracking. When the mouse goes down we start
3280 * capturing all mouse movement events. If no one else wants
3281 * them we will start defining a text selection.
3283 if ((unsigned long) mevent
== M_EVENT_DOWN
) {
3284 gMouseTracking
= TRUE
;
3285 SetCapture (ghTTYWnd
);
3286 if (!gAllowMouseTrack
&& button
== M_BUTTON_LEFT
)
3287 SelStart (nRow
, nColumn
);
3291 if (!gAllowMouseTrack
&& button
== M_BUTTON_LEFT
)
3292 SelFinish (nRow
, nColumn
);
3293 gMouseTracking
= FALSE
;
3296 * If right mouse button, toss pop-up menu offering
3299 if(button
== M_BUTTON_RIGHT
&& SelAvailable()){
3300 UINT fAllowed
= (EM_CP
| EM_CP_APPEND
);
3305 if(CopyCutPopup(hWnd
, fAllowed
) == TRUE
)
3306 mevent
= M_EVENT_TRACK
; /* don't add to input queue! */
3311 * Insert event into queue.
3313 if((unsigned long) mevent
!= M_EVENT_TRACK
)
3314 MQAdd (mevent
, button
, nRow
, nColumn
, keys
, 0);
3318 mswin_showcursor(TRUE
); /* make sure it's visible */
3321 UpdateAccelerators (hWnd
);
3324 set_time_of_last_input();
3326 return (0); /* Message handled. */
3330 /*---------------------------------------------------------------------------
3331 * BOOL ProcessTimer ()
3334 * Process the periodic timer calls.
3340 /*--------------------------------------------------------------------------*/
3344 /* Time to deliver an alarm signal? */
3345 if (gAlarmTimeout
!= 0 && GetTickCount () / 1000 > gAlarmTimeout
)
3348 /* Time to make the periodic callback. */
3349 if (gPeriodicCallback
!= NULL
&&
3350 GetTickCount() / 1000 > gPeriodicCBTimeout
) {
3351 gPeriodicCBTimeout
= GetTickCount() / 1000 +
3353 gPeriodicCallback ();
3357 * If tracking the mouse, insert a fake mouse tracking message
3358 * At the last know location of the mouse.
3360 if (gAllowMouseTrack
) {
3361 gMTEvent
.event
= M_EVENT_TRACK
;
3362 MQAdd (gMTEvent
.event
, gMTEvent
.button
, gMTEvent
.nRow
,
3363 gMTEvent
.nColumn
, gMTEvent
.keys
, MSWIN_MF_REPLACING
);
3368 /*---------------------------------------------------------------------------
3369 * BOOL WriteTTYBlock( HWND hWnd, LPSTR lpBlock, int nLength )
3372 * Writes block to TTY screen. Nothing fancy - just
3377 * handle to TTY window
3380 * far pointer to block of data
3385 /*--------------------------------------------------------------------------*/
3387 WriteTTYBlock (HWND hWnd
, LPTSTR lpBlock
, int nLength
)
3395 pTTYInfo
= (PTTYINFO
) MyGetWindowLongPtr (hWnd
, GWL_PTTYINFO
);
3396 if (pTTYInfo
== NULL
)
3399 for (i
= 0 ; i
< nLength
; i
++) {
3400 switch (lpBlock
[i
]) {
3411 /* Backspace over a whole character */
3412 offset
= pscreen_offset_from_cord(pTTYInfo
->nRow
, pTTYInfo
->nColumn
, pTTYInfo
);
3413 width
= (offset
> pTTYInfo
->nRow
* pTTYInfo
->actNColumn
)
3414 ? scrwidth(pTTYInfo
->pScreen
+offset
-1, 1) : 0;
3416 if(pTTYInfo
->nColumn
> 0)
3417 pTTYInfo
->nColumn
= (CORD
)(pTTYInfo
->nColumn
- width
);
3419 MoveTTYCursor (hWnd
);
3423 /* Carriage return */
3424 pTTYInfo
->nColumn
= 0 ;
3425 MoveTTYCursor (hWnd
);
3426 if (!pTTYInfo
->fNewLine
)
3433 if (++pTTYInfo
->nRow
== pTTYInfo
->actNRow
) {
3435 /* Scroll the Screen. */
3437 /* slide rows 1 - n-1 up to row 0 */
3438 memmove ((LPTSTR
)pTTYInfo
->pScreen
,
3439 (LPTSTR
) (pTTYInfo
->pScreen
+ pTTYInfo
->actNColumn
),
3440 (pTTYInfo
->actNRow
- 1) * pTTYInfo
->actNColumn
* sizeof (TCHAR
));
3442 /* initialize new row n-1 */
3443 for(j
= (pTTYInfo
->actNRow
- 1) * pTTYInfo
->actNColumn
;
3444 j
< pTTYInfo
->actNColumn
; j
++)
3445 pTTYInfo
->pScreen
[j
] = (TCHAR
) ' ';
3448 /* Scroll the Cell Widths */
3449 memmove ((int *)pTTYInfo
->pCellWidth
,
3450 (int *) (pTTYInfo
->pCellWidth
+ pTTYInfo
->actNColumn
),
3451 (pTTYInfo
->actNRow
- 1) * pTTYInfo
->actNColumn
* sizeof (int));
3452 for(j
= (pTTYInfo
->actNRow
- 1) * pTTYInfo
->actNColumn
;
3453 j
< pTTYInfo
->actNColumn
; j
++)
3454 pTTYInfo
->pCellWidth
[j
] = pTTYInfo
->xChar
; /* xChar set yet ? */
3456 /* Scroll the Attributes. */
3458 /* slide rows 1 - n-1 up to row 0 */
3459 memmove ((CharAttrib
*) pTTYInfo
->pAttrib
,
3460 (CharAttrib
*) (pTTYInfo
->pAttrib
+ pTTYInfo
->actNColumn
),
3461 (pTTYInfo
->actNRow
- 1) * pTTYInfo
->actNColumn
* sizeof(CharAttrib
));
3463 /* initialize new row n-1 to zero */
3464 memset ((CharAttrib
*) (pTTYInfo
->pAttrib
+
3465 (pTTYInfo
->actNRow
- 1) * pTTYInfo
->actNColumn
),
3466 0, pTTYInfo
->actNColumn
*sizeof(CharAttrib
));
3468 pTTYInfo
->screenDirty
= TRUE
;
3469 pTTYInfo
->eraseScreen
= TRUE
;
3470 InvalidateRect (hWnd
, NULL
, FALSE
);
3474 MoveTTYCursor (hWnd
);
3478 offset
= pscreen_offset_from_cord(pTTYInfo
->nRow
, pTTYInfo
->nColumn
, pTTYInfo
);
3479 pTTYInfo
->pScreen
[offset
] = lpBlock
[i
];
3480 pTTYInfo
->pCellWidth
[offset
] = wcellwidth((UCS
)lpBlock
[i
]) * pTTYInfo
->xChar
;
3481 pTTYInfo
->pAttrib
[offset
] = pTTYInfo
->curAttrib
;
3482 rect
.left
= (pTTYInfo
->nColumn
* pTTYInfo
->xChar
) +
3484 rect
.right
= rect
.left
+ pTTYInfo
->xChar
;
3485 rect
.top
= (pTTYInfo
->nRow
* pTTYInfo
->yChar
) +
3487 rect
.bottom
= rect
.top
+ pTTYInfo
->yChar
;
3488 pTTYInfo
->screenDirty
= TRUE
;
3489 InvalidateRect (hWnd
, &rect
, FALSE
);
3492 if (pTTYInfo
->nColumn
< pTTYInfo
->actNColumn
- 1)
3493 pTTYInfo
->nColumn
++ ;
3494 else if (pTTYInfo
->autoWrap
== WRAP_ON
||
3495 (pTTYInfo
->autoWrap
== WRAP_NO_SCROLL
&&
3496 pTTYInfo
->nRow
< pTTYInfo
->actNRow
- 1)) {
3497 fNewLine
= pTTYInfo
->fNewLine
;
3498 pTTYInfo
->fNewLine
= FALSE
;
3499 WriteTTYBlock (hWnd
, TEXT("\r\n"), 2);
3500 pTTYInfo
->fNewLine
= fNewLine
;
3509 /*---------------------------------------------------------------------------
3510 * BOOL WriteTTYText ( HWND hWnd, LPSTR lpBlock, int nLength )
3513 * Like WriteTTYBlock but optimized for strings that are text only,
3514 * no carrage control characters.
3518 * handle to TTY window
3521 * far pointer to block of data
3526 /*--------------------------------------------------------------------------*/
3528 WriteTTYText (HWND hWnd
, LPTSTR lpText
, int nLength
)
3533 long offset
, endOffset
;
3539 pTTYInfo
= (PTTYINFO
) MyGetWindowLongPtr (hWnd
, GWL_PTTYINFO
);
3540 if (pTTYInfo
== NULL
)
3544 /* Calculate offset of cursor, end of current column, and end of screen */
3545 offset
= pscreen_offset_from_cord(pTTYInfo
->nRow
, pTTYInfo
->nColumn
, pTTYInfo
);
3547 colEnd
= (pTTYInfo
->nRow
+ 1) * pTTYInfo
->actNColumn
;
3548 screenEnd
= pTTYInfo
->actNRow
* pTTYInfo
->actNColumn
;
3551 /* Text is allowed to wrap around to subsequent lines, but not past end
3553 endOffset
= offset
+ nLength
;
3554 if (endOffset
>= screenEnd
) {
3555 nLength
= screenEnd
- offset
;
3556 endOffset
= offset
+ nLength
- 1; /* Last cell, not one past last */
3560 /* Calculate bounding rectangle. */
3561 if (endOffset
<= colEnd
) {
3564 screenwidth
= scrwidth(lpText
, nLength
);
3566 rect
.left
= (pTTYInfo
->nColumn
* pTTYInfo
->xChar
) + pTTYInfo
->xOffset
;
3567 rect
.right
= rect
.left
+ (pTTYInfo
->xChar
* screenwidth
);
3568 rect
.top
= (pTTYInfo
->nRow
* pTTYInfo
->yChar
) + pTTYInfo
->yOffset
;
3569 rect
.bottom
= rect
.top
+ pTTYInfo
->yChar
;
3570 /* Advance cursor on cur line but not past end. */
3571 pTTYInfo
->nColumn
= (CORD
)MIN(pTTYInfo
->nColumn
+ screenwidth
,
3572 pTTYInfo
->actNColumn
- 1);
3575 /* Wraps across multiple lines. Calculate one rect to cover all
3578 rect
.right
= pTTYInfo
->xSize
;
3579 rect
.top
= (pTTYInfo
->nRow
* pTTYInfo
->yChar
) + pTTYInfo
->yOffset
;
3580 rect
.bottom
= ((((offset
+ nLength
) / pTTYInfo
->actNColumn
) + 1) *
3581 pTTYInfo
->yChar
) + pTTYInfo
->yOffset
;
3582 pTTYInfo
->nRow
= (CORD
)(endOffset
/ pTTYInfo
->actNColumn
);
3583 pTTYInfo
->nColumn
= (CORD
)(endOffset
% pTTYInfo
->actNColumn
);
3587 /* Apply text and attributes to screen in one smooth motion. */
3588 for(i
= 0; i
< nLength
; i
++)
3589 (pTTYInfo
->pScreen
+offset
)[i
] = lpText
[i
];
3590 for(i
= 0; i
< nLength
; i
++)
3591 (pTTYInfo
->pCellWidth
+offset
)[i
] = wcellwidth((UCS
)lpText
[i
]) * pTTYInfo
->xChar
;
3592 for(i
= 0; i
< nLength
; i
++)
3593 pTTYInfo
->pAttrib
[offset
+i
] = pTTYInfo
->curAttrib
;
3595 /* Invalidate rectangle */
3596 pTTYInfo
->screenDirty
= TRUE
;
3597 InvalidateRect (hWnd
, &rect
, FALSE
);
3602 /*---------------------------------------------------------------------------
3603 * BOOL WriteTTYChar (HWND hWnd, char ch)
3606 * Write a single character to the cursor position and advance the
3607 * cursor. Does not handle carage control.
3611 * handle to TTY window
3614 * character being written.
3616 /*--------------------------------------------------------------------------*/
3618 WriteTTYChar (HWND hWnd
, TCHAR ch
)
3625 pTTYInfo
= (PTTYINFO
) MyGetWindowLongPtr (hWnd
, GWL_PTTYINFO
);
3626 if (pTTYInfo
== NULL
)
3629 offset
= (pTTYInfo
->nRow
* pTTYInfo
->actNColumn
) +
3632 *(pTTYInfo
->pScreen
+ offset
) = ch
;
3633 pTTYInfo
->pCellWidth
[offset
] = wcellwidth((UCS
)ch
) * pTTYInfo
->xChar
;
3634 pTTYInfo
->pAttrib
[offset
] = pTTYInfo
->curAttrib
;
3636 rect
.left
= (pTTYInfo
->nColumn
* pTTYInfo
->xChar
) + pTTYInfo
->xOffset
;
3637 rect
.right
= rect
.left
+ pTTYInfo
->xChar
;
3638 rect
.top
= (pTTYInfo
->nRow
* pTTYInfo
->yChar
) + pTTYInfo
->yOffset
;
3639 rect
.bottom
= rect
.top
+ pTTYInfo
->yChar
;
3640 pTTYInfo
->screenDirty
= TRUE
;
3641 InvalidateRect (hWnd
, &rect
, FALSE
);
3646 if (pTTYInfo
->nColumn
< pTTYInfo
->actNColumn
- 1)
3647 pTTYInfo
->nColumn
++ ;
3648 else if ((pTTYInfo
->autoWrap
== WRAP_ON
||
3649 pTTYInfo
->autoWrap
== WRAP_NO_SCROLL
) &&
3650 pTTYInfo
->nRow
< pTTYInfo
->actNRow
- 1) {
3652 pTTYInfo
->nColumn
= 0;
3658 /*---------------------------------------------------------------------------
3659 * VOID GoModalDialogBoxParam( HINSTANCE hInstance,
3660 * LPTSTR lpszTemplate, HWND hWnd,
3661 * DLGPROC lpDlgProc, LPARAM lParam )
3664 * It is a simple utility function that simply performs the
3665 * MPI and invokes the dialog box with a DWORD paramter.
3668 * similar to that of DialogBoxParam() with the exception
3669 * that the lpDlgProc is not a procedure instance
3671 /*--------------------------------------------------------------------------*/
3673 GoModalDialogBoxParam( HINSTANCE hInstance
, LPTSTR lpszTemplate
,
3674 HWND hWnd
, DLGPROC lpDlgProc
, LPARAM lParam
)
3676 DLGPROC lpProcInstance
;
3678 lpProcInstance
= (DLGPROC
) MakeProcInstance( (FARPROC
) lpDlgProc
,
3680 DialogBoxParam( hInstance
, lpszTemplate
, hWnd
, lpProcInstance
, lParam
) ;
3681 FreeProcInstance( (FARPROC
) lpProcInstance
) ;
3685 /*---------------------------------------------------------------------------
3686 * BOOL FAR PASCAL __export AboutDlgProc( HWND hDlg, UINT uMsg,
3687 * WPARAM wParam, LPARAM lParam )
3690 * Simulates the Windows System Dialog Box.
3693 * Same as standard dialog procedures.
3695 /*--------------------------------------------------------------------------*/
3696 BOOL FAR PASCAL __export
3697 AboutDlgProc (HWND hDlg
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
3704 /* sets up version number for PINE */
3705 GetDlgItemText (hDlg
, IDD_VERSION
, szTemp
, sizeof(szTemp
)/sizeof(TCHAR
));
3706 /* szTemp is unicode, mswin_compilation_date etc are cast as %S in mswin.rc */
3707 _sntprintf (TempBuf
, sizeof(TempBuf
)/sizeof(TCHAR
), szTemp
, mswin_specific_winver(),
3708 mswin_majorver(), mswin_minorver(),
3709 mswin_compilation_remarks(),
3710 mswin_compilation_date());
3711 SetDlgItemText (hDlg
, IDD_VERSION
, (LPTSTR
) TempBuf
);
3714 LoadString (GET_HINST (hDlg
), IDS_BYLINE
, TempBuf
,
3715 sizeof(TempBuf
) / sizeof(TCHAR
));
3716 SetDlgItemText (hDlg
, IDD_BYLINE
, TempBuf
);
3722 EndDialog( hDlg
, TRUE
) ;
3726 switch((WORD
) wParam
){
3728 EndDialog( hDlg
, TRUE
) ;
3739 } /* end of AboutDlgProc() */
3742 /*---------------------------------------------------------------------------
3745 * Simulates the Windows System Dialog Box.
3748 * Same as standard dialog procedures.
3750 /*--------------------------------------------------------------------------*/
3751 BOOL FAR PASCAL __export
3752 SplashDlgProc (HWND hDlg
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
3754 static HBITMAP hbmpSplash
;
3758 if(hbmpSplash
= LoadBitmap(GET_HINST(hDlg
),
3759 MAKEINTRESOURCE(ALPINESPLASH
))){
3763 cx
= GetSystemMetrics(SM_CXSCREEN
);
3764 cy
= GetSystemMetrics(SM_CYSCREEN
);
3765 GetObject(hbmpSplash
, sizeof(BITMAP
), &stBitmap
);
3767 SetWindowPos(hDlg
, HWND_TOPMOST
,
3768 (cx
- stBitmap
.bmWidth
) / 2,
3769 (cy
- stBitmap
.bmHeight
) / 2,
3770 stBitmap
.bmWidth
, stBitmap
.bmHeight
,
3771 SWP_NOCOPYBITS
/* | SWP_SHOWWINDOW */);
3776 case WM_CTLCOLORDLG
:
3779 case WM_ERASEBKGND
:
3786 if((hMemDC
= CreateCompatibleDC((HDC
) wParam
)) != NULL
){
3787 hObject
= SelectObject(hMemDC
, hbmpSplash
);
3788 SetMapMode(hMemDC
, GetMapMode((HDC
) wParam
));
3790 GetObject(hbmpSplash
, sizeof(BITMAP
), &stBitmap
);
3791 stPoint
.x
= stBitmap
.bmWidth
;
3792 stPoint
.y
= stBitmap
.bmHeight
;
3793 DPtoLP((HDC
) wParam
, &stPoint
, 1);
3795 BitBlt((HDC
) wParam
,
3796 0, 0, stPoint
.x
, stPoint
.y
,
3797 hMemDC
, 0, 0, SRCCOPY
);
3798 SelectObject(hMemDC
, hObject
);
3808 DestroyWindow(hDlg
);
3813 DeleteObject(hbmpSplash
);
3817 case WM_COMMAND
: /* No commands! */
3818 DestroyWindow(hDlg
);
3829 SelectTTYFontHook(HWND hDlg
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
3832 case WM_INITDIALOG
:
3835 * Deactivate the Style combo box...
3837 HWND hWnd
= GetDlgItem(hDlg
, cmb2
);
3838 EnableWindow(hWnd
, FALSE
);
3839 SetWindowPos(hWnd
, NULL
, 0, 0, 0, 0, SWP_HIDEWINDOW
);
3846 switch ((WORD
) wParam
) {
3851 SendMessage(hDlg
, WM_CHOOSEFONT_GETLOGFONT
,
3852 0, (LPARAM
) &curfont
);
3853 ResetTTYFont (ghTTYWnd
, gpTTYInfo
, &curfont
);
3874 /*---------------------------------------------------------------------------
3875 * BOOL SelectTTYFont( HWND hDlg )
3878 * Selects the current font for the TTY screen.
3879 * Uses the Common Dialog ChooseFont() API.
3883 * handle to settings dialog
3885 /*--------------------------------------------------------------------------*/
3887 SelectTTYFont (HWND hWnd
)
3889 CHOOSEFONT cfTTYFont
;
3890 LOGFONT newFont
, origFont
;
3893 pTTYInfo
= (PTTYINFO
) MyGetWindowLongPtr (hWnd
, GWL_PTTYINFO
);
3894 if (pTTYInfo
== NULL
)
3897 memcpy (&newFont
, &gpTTYInfo
->lfTTYFont
, sizeof (LOGFONT
));
3898 memcpy (&origFont
, &gpTTYInfo
->lfTTYFont
, sizeof (LOGFONT
));
3900 cfTTYFont
.lStructSize
= sizeof (CHOOSEFONT
);
3901 cfTTYFont
.hwndOwner
= hWnd
;
3902 cfTTYFont
.hDC
= NULL
;
3903 cfTTYFont
.lpLogFont
= &newFont
;
3904 cfTTYFont
.Flags
= CF_SCREENFONTS
| CF_FIXEDPITCHONLY
|
3905 CF_INITTOLOGFONTSTRUCT
|
3907 CF_FORCEFONTEXIST
| CF_LIMITSIZE
|
3908 CF_ENABLEHOOK
| CF_APPLY
;
3910 CF_FORCEFONTEXIST
| CF_LIMITSIZE
;
3912 cfTTYFont
.nSizeMin
= FONT_MIN_SIZE
;
3913 cfTTYFont
.nSizeMax
= FONT_MAX_SIZE
;
3914 cfTTYFont
.lCustData
= (long) 0 ;
3916 cfTTYFont
.lpfnHook
= SelectTTYFontHook
;
3918 cfTTYFont
.lpfnHook
= NULL
;
3920 cfTTYFont
.lpTemplateName
= NULL
;
3921 cfTTYFont
.hInstance
= GET_HINST (hWnd
);
3925 if (ChooseFont (&cfTTYFont
)) {
3926 ResetTTYFont (hWnd
, pTTYInfo
, &newFont
);
3930 ResetTTYFont (hWnd
, pTTYInfo
, &origFont
);
3939 * Set a specific color (forground, background, reverse, normal) to
3940 * the color specified by name.
3943 SetColorAttribute (COLORREF
*cf
, char *colorName
)
3945 /* color name not in table. Try converting RGB string. */
3946 ConvertRGBString (colorName
, cf
);
3948 /* Redraw screen. */
3949 gpTTYInfo
->screenDirty
= TRUE
;
3950 gpTTYInfo
->eraseScreen
= TRUE
;
3951 InvalidateRect (ghTTYWnd
, NULL
, FALSE
);
3956 * Set current color attribute to reverse color
3962 gpTTYInfo
->curAttrib
.rgbFG
= gpTTYInfo
->rgbRFGColor
;
3963 gpTTYInfo
->curAttrib
.rgbBG
= gpTTYInfo
->rgbRBGColor
;
3968 * Convert a string to an integer.
3971 ScanInt (char *str
, int min
, int max
, int *val
)
3978 if (str
== NULL
) return (FALSE
);
3979 if (*str
== '\0' || strlen (str
) > 9) return (FALSE
);
3981 /* Check for a negative sign. */
3987 /* Check for all digits. */
3988 for (c
= str
; *c
!= '\0'; ++c
) {
3989 if (!isdigit((unsigned char)*c
))
3993 /* Convert from ascii to int. */
3994 v
= atoi (str
) * neg
;
3996 /* Check constraints. */
3997 if (v
< min
|| v
> max
)
4005 * Convert a RGB string to a color ref. The string should look like:
4007 * where rrr, ggg, and bbb are numbers between 0 and 255 that represent
4008 * red, gree, and blue values. Must be comma seperated.
4010 * TRUE - Successfully converted string.
4011 * FALSE - Bad format, 'cf' unchanged.
4014 ConvertRGBString (char *colorName
, COLORREF
*cf
)
4016 int i
, j
, n
, rgb
[3];
4022 /* Is the name in the global color table? */
4023 for(ct
= MSWINColorTable
; ct
->colorName
; ct
++)
4024 if(!struncmp(ct
->colorName
, colorName
, (int)strlen(ct
->colorName
))){
4029 /* Not a named color, try RRR,GGG,BBB */
4030 for(i
= 0; i
< 3; i
++){
4031 if(i
&& *colorName
++ != ',')
4034 for(rgb
[i
] = 0, j
= 0; j
< 3; j
++)
4035 if((n
= *colorName
++ - '0') < 0 || n
> 9)
4038 rgb
[i
] = (rgb
[i
] * 10) + n
;
4041 *cf
= RGB (rgb
[0], rgb
[1], rgb
[2]);
4047 ConvertStringRGB(char *colorName
, size_t ncolorName
, COLORREF colorRef
)
4051 for(cf
= MSWINColorTable
;
4052 cf
->colorName
&& cf
->colorRef
!= colorRef
;
4057 strncpy(colorName
, cf
->colorName
, ncolorName
);
4058 colorName
[ncolorName
-1] = '\0';
4061 snprintf(colorName
, ncolorName
, "%.3d,%.3d,%.3d",
4062 GetRValue(colorRef
), GetGValue(colorRef
), GetBValue(colorRef
));
4069 * Map from integer color value to canonical color name.
4075 static char cbuf
[RGBLEN
+1];
4077 if(color
< fullColorTableSize
){
4078 ct
= &MSWINColorTable
[color
];
4079 if(ct
->canonicalName
)
4080 return(ct
->canonicalName
);
4083 /* not supposed to get here */
4084 snprintf(cbuf
, sizeof(cbuf
), "color%03.3d", color
);
4090 * Argument is a color name which could be an RGB string, a name like "blue",
4091 * or a name like "color011".
4093 * Returns a pointer to the canonical name of the color.
4096 color_to_canonical_name(char *s
)
4098 int i
, j
, n
, rgb
[3];
4101 static char cn
[RGBLEN
+1];
4106 if(!struncmp(s
, MATCH_NORM_COLOR
, RGBLEN
) || !struncmp(s
, MATCH_NONE_COLOR
, RGBLEN
))
4109 for(ct
= MSWINColorTable
; ct
->colorName
; ct
++)
4110 if(!struncmp(ct
->colorName
, s
, (int)strlen(ct
->colorName
)))
4114 return(ct
->canonicalName
);
4116 /* maybe it is RGB? */
4117 for(i
= 0; i
< 3; i
++){
4118 if(i
&& *s
++ != ',')
4121 for(rgb
[i
] = 0, j
= 0; j
< 3; j
++)
4122 if((n
= *s
++ - '0') < 0 || n
> 9)
4125 rgb
[i
] = (rgb
[i
] * 10) + n
;
4128 cr
= RGB(rgb
[0], rgb
[1], rgb
[2]);
4131 * Now compare that RGB against the color table RGBs. If it is
4132 * in the table, return the canonical name, else return the RGB string.
4134 for(ct
= MSWINColorTable
; ct
->colorName
; ct
++)
4135 if(ct
->colorRef
== cr
)
4139 return(ct
->canonicalName
);
4141 snprintf(cn
, sizeof(cn
), "%.3d,%.3d,%.3d",
4142 GetRValue(cr
), GetGValue(cr
), GetBValue(cr
));
4148 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4150 * Toolbar setup routines.
4152 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
4154 TBToggle (HWND hWnd
)
4159 pTTYInfo
= (PTTYINFO
) MyGetWindowLongPtr (hWnd
, GWL_PTTYINFO
);
4160 if (pTTYInfo
== NULL
)
4163 if (pTTYInfo
->toolBarSize
> 0)
4171 TBPosToggle (HWND hWnd
)
4176 pTTYInfo
= (PTTYINFO
) MyGetWindowLongPtr (hWnd
, GWL_PTTYINFO
);
4177 if (pTTYInfo
== NULL
)
4180 pTTYInfo
->toolBarTop
= !pTTYInfo
->toolBarTop
;
4181 if(pTTYInfo
->hTBWnd
){
4195 pTTYInfo
= (PTTYINFO
) MyGetWindowLongPtr (hWnd
, GWL_PTTYINFO
);
4196 if (pTTYInfo
== NULL
)
4201 * Make sure the tool bar not already shown.
4203 if (pTTYInfo
->toolBarSize
> 0)
4209 * Make procinstance for dialog funciton.
4212 if (gToolBarProc
== NULL
)
4213 gToolBarProc
= (DLGPROC
) MakeProcInstance( (FARPROC
) ToolBarProc
,
4215 if (gTBBtnProc
== NULL
)
4216 gTBBtnProc
= (WNDPROC
) MakeProcInstance( (FARPROC
) TBBtnProc
,
4221 * Create the dialog box.
4223 pTTYInfo
->hTBWnd
= CreateDialog (ghInstance
,
4224 MAKEINTRESOURCE (pTTYInfo
->curToolBarID
),
4227 if (pTTYInfo
->hTBWnd
== NULL
) {
4236 * Adjust the window size.
4238 GetWindowRect (pTTYInfo
->hTBWnd
, &rc
); /* Get Toolbar size. */
4239 pTTYInfo
->toolBarSize
= (CORD
)(rc
.bottom
- rc
.top
);
4241 GetClientRect (hWnd
, &rc
); /* Get TTY window size. */
4242 SizeTTY (hWnd
, 0, (CORD
)rc
.bottom
, (CORD
)rc
.right
);
4253 pTTYInfo
= (PTTYINFO
) MyGetWindowLongPtr (hWnd
, GWL_PTTYINFO
);
4254 if (pTTYInfo
== NULL
)
4258 if (pTTYInfo
->toolBarSize
== 0)
4261 DestroyWindow (pTTYInfo
->hTBWnd
);
4262 pTTYInfo
->hTBWnd
= NULL
;
4263 if (pTTYInfo
->toolBarBtns
!= NULL
)
4264 MemFree (pTTYInfo
->toolBarBtns
);
4265 pTTYInfo
->toolBarBtns
= NULL
;
4269 * Adjust the window size.
4271 pTTYInfo
->toolBarSize
= 0;
4272 GetClientRect (hWnd
, &rc
);
4273 SizeTTY (hWnd
, 0, (CORD
)rc
.bottom
, (CORD
)rc
.right
);
4278 TBSwap (HWND hWnd
, int newID
)
4283 pTTYInfo
= (PTTYINFO
) MyGetWindowLongPtr (hWnd
, GWL_PTTYINFO
);
4284 if (pTTYInfo
== NULL
)
4287 if (pTTYInfo
->toolBarSize
== 0 || pTTYInfo
->curToolBarID
== newID
)
4291 * Dispose of old tool bar window.
4295 DestroyWindow (pTTYInfo
->hTBWnd
);
4296 pTTYInfo
->hTBWnd
= NULL
;
4297 if (pTTYInfo
->toolBarBtns
!= NULL
)
4298 MemFree (pTTYInfo
->toolBarBtns
);
4299 pTTYInfo
->toolBarBtns
= NULL
;
4304 * Create the new dialog box.
4306 pTTYInfo
->hTBWnd
= CreateDialog (ghInstance
,
4307 MAKEINTRESOURCE (newID
),
4310 if (pTTYInfo
->hTBWnd
== NULL
) {
4314 pTTYInfo
->curToolBarID
= newID
;
4315 SetFocus (hWnd
); /* Return focus to parent. */
4319 * Fit new tool bar into old tool bars position. This assumes that
4320 * all tool bars are about the same height.
4322 GetClientRect (hWnd
, &rc
); /* Get TTY window size. */
4323 if (pTTYInfo
->toolBarTop
)
4324 /* Position at top of window. */
4325 SetWindowPos (pTTYInfo
->hTBWnd
, HWND_TOP
,
4327 rc
.right
, pTTYInfo
->toolBarSize
,
4328 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_SHOWWINDOW
);
4330 /* Position at bottom of window. */
4331 SetWindowPos (pTTYInfo
->hTBWnd
, HWND_TOP
,
4332 0, pTTYInfo
->ySize
- pTTYInfo
->toolBarSize
,
4333 rc
.right
, pTTYInfo
->toolBarSize
,
4334 SWP_NOZORDER
| SWP_NOACTIVATE
| SWP_SHOWWINDOW
);
4340 BOOL FAR PASCAL __export
4341 ToolBarProc (HWND hWnd
, UINT msg
, WPARAM wParam
, LPARAM lParam
)
4353 pTTYInfo
= gpTTYInfo
;
4359 /* Fit dialog to window. */
4360 GetWindowRect (hWnd
, &rc
);
4361 height
= rc
.bottom
- rc
.top
;
4362 GetClientRect (GetParent (hWnd
), &rc
);
4363 SetWindowPos (hWnd
, HWND_TOP
, 0, 0, rc
.right
, height
,
4364 SWP_NOZORDER
| SWP_NOACTIVATE
);
4366 /* Count child windows.*/
4368 for (hCld
= GetWindow (hWnd
, GW_CHILD
);
4370 hCld
= GetWindow (hCld
, GW_HWNDNEXT
))
4373 /* Allocate a list of previous child procs. */
4374 if (pTTYInfo
->toolBarBtns
!= NULL
)
4375 MemFree (pTTYInfo
->toolBarBtns
);
4376 pTTYInfo
->toolBarBtns
= MemAlloc (sizeof (BtnList
) * (btnCount
+ 1));
4378 /* Subclass all child windows. */
4379 for (i
= 0, hCld
= GetWindow (hWnd
, GW_CHILD
);
4381 ++i
, hCld
= GetWindow (hCld
, GW_HWNDNEXT
)) {
4382 pTTYInfo
->toolBarBtns
[i
].wndID
= GET_ID (hCld
);
4383 pTTYInfo
->toolBarBtns
[i
].wndProc
=
4384 (WNDPROC
)(LONG_PTR
)MyGetWindowLongPtr (hCld
,
4386 MySetWindowLongPtr (hCld
, GWLP_WNDPROC
, (void *)(LONG_PTR
)TBBtnProc
);
4388 pTTYInfo
->toolBarBtns
[i
].wndID
= 0;
4389 pTTYInfo
->toolBarBtns
[i
].wndProc
= NULL
;
4396 if (wParam
>= KS_RANGESTART
&& wParam
<= KS_RANGEEND
){
4397 ProcessMenuItem (GetParent (hWnd
), wParam
);
4398 /* Set input focus back to parent. */
4399 SetFocus (GetParent (hWnd
));
4406 case WM_CTLCOLORBTN
:
4410 if (HIWORD (lParam
) == CTLCOLOR_DLG
) {
4411 if(pTTYInfo
->hTBBrush
!= NULL
){
4412 DeleteObject(pTTYInfo
->hTBBrush
);
4413 pTTYInfo
->hTBBrush
= NULL
;
4416 hBrush
= CreateSolidBrush (GetSysColor (COLOR_ACTIVEBORDER
));
4417 return ((BOOL
)!!(pTTYInfo
->hTBBrush
= hBrush
));
4425 * Subclass toolbar button windows.
4427 * These buttons will automatically return the input focus to
4428 * the toolbar's parent
4430 LRESULT FAR PASCAL __export
4431 TBBtnProc (HWND hBtn
, UINT uMsg
, WPARAM wParam
, LPARAM lParam
)
4442 * Find previous window proc.
4444 pTTYInfo
= gpTTYInfo
;
4446 for (i
= 0; pTTYInfo
->toolBarBtns
[i
].wndID
!= 0; ++i
)
4447 if (pTTYInfo
->toolBarBtns
[i
].wndID
== id
)
4449 /* Whoops! Didn't find window, don't know how to pass message. */
4454 wndProc
= pTTYInfo
->toolBarBtns
[i
].wndProc
;
4458 if (uMsg
== WM_LBUTTONUP
|| uMsg
== WM_MBUTTONUP
|| uMsg
== WM_RBUTTONUP
) {
4460 * On mouse button up restore input focus to IDC_RESPONCE, which
4461 * processes keyboard input.
4463 ret
= CallWindowProc (wndProc
, hBtn
, uMsg
, wParam
, lParam
);
4464 hPrnt
= GetParent (GetParent (hBtn
));
4470 return (CallWindowProc (wndProc
, hBtn
, uMsg
, wParam
, lParam
));
4475 * return bitmap of allowed Edit Menu items
4478 UpdateEditAllowed(HWND hWnd
)
4481 UINT fAccel
= EM_NONE
;
4483 if((pTTYInfo
= (PTTYINFO
) MyGetWindowLongPtr (hWnd
, GWL_PTTYINFO
)) != NULL
){
4484 if(EditPasteAvailable())
4485 fAccel
|= (EM_PST
| EM_PST_ABORT
);
4486 else if(IsClipboardFormatAvailable (CF_UNICODETEXT
) && gPasteEnabled
)
4490 fAccel
|= (EM_CP
| EM_CP_APPEND
);
4497 fAccel
|= (EM_CP
| EM_CP_APPEND
);
4500 if (pTTYInfo
->menuItems
[KS_WHEREIS
- KS_RANGESTART
].miActive
)
4508 #ifdef ACCELERATORS_OPT
4509 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4511 * Accelorator key routines.
4513 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
4515 AccelCtl (HWND hWnd
, int ctl
, BOOL saveChange
)
4521 pTTYInfo
= (PTTYINFO
) MyGetWindowLongPtr (hWnd
, GWL_PTTYINFO
);
4522 if (pTTYInfo
== NULL
)
4533 load
= pTTYInfo
->hAccel
== NULL
;
4541 if (load
&& pTTYInfo
->hAccel
== NULL
) {
4543 pTTYInfo
->hAccel
= LoadAccelerators (ghInstance
,
4544 MAKEINTRESOURCE (IDR_ACCEL_PINE
));
4547 else if(!load
&& pTTYInfo
->hAccel
) {
4549 FreeResource (pTTYInfo
->hAccel
);
4550 pTTYInfo
->hAccel
= NULL
;
4554 if (changed
&& saveChange
)
4555 DidResize (pTTYInfo
);
4560 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4562 * Accelorator key routines.
4564 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
4566 AccelManage (HWND hWnd
, long accels
)
4569 ACCEL accelarray
[EM_MAX_ACCEL
];
4571 static ACCEL am_cp
= {
4572 FVIRTKEY
| FCONTROL
| FSHIFT
| FNOINVERT
, 'C', IDM_EDIT_COPY
4574 static ACCEL am_cp_append
= {
4575 FVIRTKEY
| FCONTROL
| FALT
| FNOINVERT
, 'C', IDM_EDIT_COPY_APPEND
4577 static ACCEL am_find
= {
4578 FVIRTKEY
| FCONTROL
| FSHIFT
| FNOINVERT
, 'F', IDM_MI_WHEREIS
4580 static ACCEL am_pst
= {
4581 FVIRTKEY
| FCONTROL
| FSHIFT
| FNOINVERT
, 'V', IDM_EDIT_PASTE
4583 static ACCEL am_pst_abort
= {
4584 FVIRTKEY
| FCONTROL
| FALT
| FNOINVERT
, 'V', IDM_EDIT_CANCEL_PASTE
4586 static ACCEL am_cut
= {
4587 FVIRTKEY
| FCONTROL
| FSHIFT
| FNOINVERT
, 'X', IDM_EDIT_CUT
4590 pTTYInfo
= (PTTYINFO
) MyGetWindowLongPtr (hWnd
, GWL_PTTYINFO
);
4591 if (pTTYInfo
== NULL
|| pTTYInfo
->fAccel
== (UINT
)accels
)
4594 if(pTTYInfo
->hAccel
){
4595 DestroyAcceleratorTable(pTTYInfo
->hAccel
);
4596 pTTYInfo
->hAccel
= NULL
;
4597 pTTYInfo
->fAccel
= EM_NONE
;
4603 accelarray
[n
++] = am_cp
;
4605 if(accels
& EM_CP_APPEND
)
4606 accelarray
[n
++] = am_cp_append
;
4608 if(accels
& EM_FIND
)
4609 accelarray
[n
++] = am_find
;
4612 accelarray
[n
++] = am_pst
;
4614 if(accels
& EM_PST_ABORT
)
4615 accelarray
[n
++] = am_pst_abort
;
4618 accelarray
[n
++] = am_cut
;
4621 if(n
&& (pTTYInfo
->hAccel
= CreateAcceleratorTable(accelarray
, n
)))
4622 pTTYInfo
->fAccel
= accels
;
4624 pTTYInfo
->fAccel
= EM_NONE
;
4629 UpdateAccelerators (HWND hWnd
)
4631 AccelManage (hWnd
, UpdateEditAllowed(hWnd
));
4636 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4638 * Mouse Selection routines
4640 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
4642 LOCAL BOOL SelSelected
= FALSE
;
4643 LOCAL BOOL SelTracking
= FALSE
;
4644 LOCAL
int SelAnchorRow
;
4645 LOCAL
int SelAnchorCol
;
4646 LOCAL
int SelPointerRow
;
4647 LOCAL
int SelPointerCol
;
4655 SelRSet (int oStart
, int oEnd
)
4659 for (pca
= gpTTYInfo
->pAttrib
+ oStart
; oStart
< oEnd
; ++pca
, ++oStart
)
4660 pca
->style
|= CHAR_ATTR_SEL
;
4665 SelRClear (int oStart
, int oEnd
)
4669 for (pca
= gpTTYInfo
->pAttrib
+ oStart
; oStart
< oEnd
; ++pca
, ++oStart
)
4670 pca
->style
&= ~CHAR_ATTR_SEL
;
4675 SelRInvalidate (int oStart
, int oEnd
)
4681 sRow
= oStart
/ gpTTYInfo
->actNColumn
;
4682 sCol
= oStart
% gpTTYInfo
->actNColumn
;
4683 eRow
= oEnd
/ gpTTYInfo
->actNColumn
;
4684 eCol
= oEnd
% gpTTYInfo
->actNColumn
;
4686 rect
.top
= (sRow
* gpTTYInfo
->yChar
) + gpTTYInfo
->yOffset
;
4687 rect
.bottom
= ((eRow
+1) * gpTTYInfo
->yChar
) + gpTTYInfo
->yOffset
;
4689 rect
.left
= (sCol
* gpTTYInfo
->xChar
) + gpTTYInfo
->xOffset
;
4690 rect
.right
= ((eCol
+1) * gpTTYInfo
->xChar
) + gpTTYInfo
->xOffset
;
4692 rect
.left
= gpTTYInfo
->xOffset
;
4693 rect
.right
= (gpTTYInfo
->actNColumn
* gpTTYInfo
->xChar
) +
4696 InvalidateRect (ghTTYWnd
, &rect
, FALSE
);
4701 * Start a mouse selection.
4704 SelStart (int nRow
, int nColumn
)
4709 SelPointerRow
= SelAnchorRow
= nRow
;
4710 SelPointerCol
= SelAnchorCol
= nColumn
;
4716 * Finish a mouse selection.
4719 SelFinish (int nRow
, int nColumn
)
4721 if (nRow
== SelAnchorRow
&& nColumn
== SelAnchorCol
) {
4722 /* Mouse up in same place it went down - no selection. */
4726 /* Update screen selection and set final position of mouse
4727 * then turn of mouse tracking. Selection remains in effect
4728 * until SelClear is called. */
4729 SelTrackMouse (nRow
, nColumn
);
4730 SelTracking
= FALSE
;
4744 /* Convert the anchor and point coordinates to offsets then
4745 * order the offsets. */
4746 a
= (SelAnchorRow
* gpTTYInfo
->actNColumn
) + SelAnchorCol
;
4747 p
= (SelPointerRow
* gpTTYInfo
->actNColumn
) + SelPointerCol
;
4756 /* Clear selected attribute of those cells in range. */
4758 SelRInvalidate (s
, e
);
4759 SelSelected
= FALSE
;
4760 SelTracking
= FALSE
;
4765 * Update the position of the mouse point.
4768 SelTrackXYMouse (int xPos
, int yPos
)
4773 nColumn
= (xPos
- gpTTYInfo
->xOffset
) / gpTTYInfo
->xChar
;
4774 nRow
= (yPos
- gpTTYInfo
->yOffset
) / gpTTYInfo
->yChar
;
4776 SelTrackMouse (nRow
, nColumn
);
4781 * Update the position of the mouse point.
4784 SelTrackMouse (int nRow
, int nColumn
)
4791 /* Constrain the cel position to be on the screen. But allow
4792 * for the Column to be one past the right edge of the screen so
4793 * the user can select the right most cel of a row. */
4794 nColumn
= MAX(0, nColumn
);
4795 nColumn
= MIN(gpTTYInfo
->actNColumn
, nColumn
);
4796 nRow
= MAX(0, nRow
);
4797 nRow
= MIN(gpTTYInfo
->actNRow
-1, nRow
);
4800 /* Convert the anchor, previous mouse position, and new mouse
4801 * position to offsets. */
4802 a
= (SelAnchorRow
* gpTTYInfo
->actNColumn
) + SelAnchorCol
;
4803 p
= (SelPointerRow
* gpTTYInfo
->actNColumn
) + SelPointerCol
;
4804 n
= (nRow
* gpTTYInfo
->actNColumn
) + nColumn
;
4806 /* If previous position same as current position, do nothing. */
4810 /* there are six possible orderings of the points, each with
4811 * a different action:
4812 * order clear set redraw
4815 * p a n p - a a - n p - n
4818 * n a p a - p n - a n - p
4824 SelRInvalidate (n
, p
);
4827 SelRInvalidate (p
, n
);
4832 SelRInvalidate (p
, n
);
4838 SelRInvalidate (p
, n
);
4841 SelRInvalidate (n
, p
);
4846 SelRInvalidate (n
, p
);
4850 /* Set new pointer. */
4851 SelPointerRow
= nRow
;
4852 SelPointerCol
= nColumn
;
4859 return (SelSelected
);
4864 * Copy screen data to clipboard. Actually appends data from screen to
4865 * existing handle so as we can implement a "Copy Append" to append to
4866 * existing clipboard data.
4868 * The screen does not have real line terminators. We decide where the
4869 * actual screen data ends by scanning the line (row) from end backwards
4870 * to find the first non-space.
4872 * I don't know how many bytes of data I'll be appending to the clipboard.
4873 * So I implemented in two passes. The first finds all the row starts
4874 * and length while the second copies the data.
4877 SelDoCopy (HANDLE hCB
, DWORD lenCB
)
4879 HANDLE newCB
; /* Used in reallocation. */
4880 TCHAR
*pCB
; /* Points to CB data. */
4881 TCHAR
*p2
; /* Temp pointer to screen data. */
4882 int sRow
, eRow
; /* Start and End Rows. */
4883 int sCol
, eCol
; /* Start and End columns. */
4884 int row
, c1
, c2
; /* temp row and column indexes. */
4885 int totalLen
; /* total len of new data. */
4886 CopyRow
*rowTable
, *rp
; /* pointers to table of rows. */
4887 BOOL noLastCRLF
= FALSE
;
4890 if (OpenClipboard (ghTTYWnd
)) { /* ...and we get the CB. */
4891 if (EmptyClipboard ()) { /* ...and clear previous CB.*/
4894 /* Find the start and end row and column. */
4895 if ( (SelAnchorRow
* gpTTYInfo
->actNColumn
) + SelAnchorCol
<
4896 (SelPointerRow
* gpTTYInfo
->actNColumn
) + SelPointerCol
) {
4897 sRow
= SelAnchorRow
;
4898 sCol
= SelAnchorCol
;
4899 eRow
= SelPointerRow
;
4900 eCol
= SelPointerCol
;
4903 sRow
= SelPointerRow
;
4904 sCol
= SelPointerCol
;
4905 eRow
= SelAnchorRow
;
4906 eCol
= SelAnchorCol
;
4909 /* Allocate a table in which we store info on rows. */
4910 rowTable
= (CopyRow
*) MemAlloc (sizeof (CopyRow
) * (eRow
-sRow
+1));
4911 if (rowTable
== NULL
)
4914 /* Find the start and length of each row. */
4916 for (row
= sRow
, rp
= rowTable
; row
<= eRow
; ++row
, ++rp
) {
4917 /* Find beginning and end columns, which depends on if
4918 * this is the first or last row in the selection. */
4919 c1
= (row
== sRow
? sCol
: 0);
4920 c2
= (row
== eRow
? eCol
: gpTTYInfo
->actNColumn
);
4922 /* Calculate pointer to beginning of this line. */
4923 rp
->pRow
= gpTTYInfo
->pScreen
+
4924 ((row
* gpTTYInfo
->actNColumn
) + c1
);
4926 /* Back down from end column to find first non space.
4927 * noLastCRLF indicates if it looks like the selection
4928 * should include a CRLF on the end of the line. It
4929 * gets set for each line, but only the setting for the
4930 * last line in the selection is remembered (which is all
4931 * we're interested in). */
4932 p2
= gpTTYInfo
->pScreen
+
4933 ((row
* gpTTYInfo
->actNColumn
) + c2
);
4936 if (*(p2
-1) != (TCHAR
)' ')
4943 /* Calculate size of line, then increment totalLen plus 2 for
4944 * the CRLF which will terminate each line. */
4946 totalLen
+= rp
->len
+ 2;
4949 /* Reallocate the memory block. Add one byte for null terminator. */
4950 newCB
= GlobalReAlloc (hCB
, (lenCB
+ totalLen
+ 1)*sizeof(TCHAR
), 0);
4955 pCB
= GlobalLock (hCB
);
4959 /* Append each of the rows, deliminated by a CRLF. */
4961 for (row
= sRow
, rp
= rowTable
; row
<= eRow
; ++row
, ++rp
) {
4963 memcpy (pCB
, rp
->pRow
, rp
->len
* sizeof(TCHAR
));
4966 if (row
< eRow
|| !noLastCRLF
) {
4967 *pCB
++ = (TCHAR
)ASCII_CR
;
4968 *pCB
++ = (TCHAR
)ASCII_LF
;
4971 *pCB
= (TCHAR
)'\0'; /* Null terminator. */
4975 /* Attempt to pass the data to the clipboard, then release clipboard
4976 * and exit function. */
4977 if (SetClipboardData (CF_UNICODETEXT
, hCB
) == NULL
)
4978 /* Failed! Free the data. */
4987 Fail2
: MemFree (rowTable
);
4988 Fail1
: GlobalFree (hCB
);
4995 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
4997 * Upper Layer Screen routines.
4999 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
5002 * Flush the write accumulator buffer.
5005 FlushWriteAccum (void)
5007 if (gpTTYInfo
->writeAccumCount
> 0) {
5008 WriteTTYText (ghTTYWnd
, gpTTYInfo
->writeAccum
,
5009 gpTTYInfo
->writeAccumCount
);
5010 gpTTYInfo
->writeAccumCount
= 0;
5016 * Set window's title
5019 mswin_settitle(char *utf8_title
)
5022 LPTSTR lptstr_title
;
5024 lptstr_title
= utf8_to_lptstr(utf8_title
);
5025 _sntprintf(buf
, 256, TEXT("%.*s - Alpine"), 80, lptstr_title
);
5026 fs_give((void **) &lptstr_title
);
5028 SetWindowText(ghTTYWnd
, buf
);
5033 * Return the application instance.
5036 mswin_gethinstance ()
5038 return ((WINHAND
)ghInstance
);
5045 return ((WINHAND
)ghTTYWnd
);
5050 * destroy splash screen
5055 if(ghSplashWnd
!= NULL
){
5056 DestroyWindow(ghSplashWnd
);
5063 * Called to get mouse event.
5066 mswin_getmouseevent (MEvent
* pMouse
)
5068 return (MQGet (pMouse
));
5073 * Make a pop-up menu and track it
5076 mswin_popup(MPopup
*members
)
5083 if(members
&& (hMenu
= CreatePopupMenu())){
5085 PopupConfig(hMenu
, members
, &n
);
5086 if(GetCursorPos(&point
)
5087 && (n
= TrackPopupMenu(hMenu
,
5088 TPM_LEFTALIGN
| TPM_TOPALIGN
5089 | TPM_RIGHTBUTTON
| TPM_LEFTBUTTON
5090 | TPM_NONOTIFY
| TPM_RETURNCMD
,
5091 point
.x
, point
.y
, 0, ghTTYWnd
, NULL
))
5092 && (mp
= PopupId(members
, n
))){
5093 /* Find the member with the internal.id of n */
5094 n
= mp
->internal
.id
- 1; /* item's "selectable" index */
5097 CQAdd (mp
->data
.val
, 0);
5101 SendMessage(ghTTYWnd
, WM_COMMAND
, mp
->data
.msg
, 0);
5109 n
= -1; /* error or nothing selected; same diff */
5121 PopupConfig(HMENU hMenu
, MPopup
*members
, int *n
)
5127 for(index
= 0; members
->type
!= tTail
; members
++, index
++){
5128 memset(&mitem
, 0, sizeof(MENUITEMINFO
));
5129 mitem
.cbSize
= sizeof(MENUITEMINFO
);
5130 mitem
.fMask
= MIIM_TYPE
;
5132 if(members
->type
== tSubMenu
){
5133 mitem
.fMask
|= MIIM_SUBMENU
;
5134 mitem
.fType
= MFT_STRING
;
5135 if(mitem
.hSubMenu
= CreatePopupMenu()){
5136 /* members->label.string is still just a char * */
5137 _sntprintf(tcbuf
, sizeof(tcbuf
)/sizeof(TCHAR
),
5138 TEXT("%S"), members
->label
.string
);
5139 mitem
.dwTypeData
= tcbuf
;
5140 mitem
.cch
= (UINT
)_tcslen(tcbuf
);
5141 InsertMenuItem(hMenu
, index
, TRUE
, &mitem
);
5143 PopupConfig(mitem
.hSubMenu
, members
->data
.submenu
, n
);
5147 switch(members
->type
){
5149 mitem
.fType
= MFT_SEPARATOR
;
5153 mitem
.fMask
|= MIIM_ID
;
5154 mitem
.wID
= members
->internal
.id
= (*n
)++;
5155 switch(members
->label
.style
){
5157 mitem
.fMask
|= MIIM_STATE
;
5158 mitem
.fState
= MFS_CHECKED
;
5162 mitem
.fMask
|= MIIM_STATE
;
5163 mitem
.fState
= MFS_GRAYED
;
5171 mitem
.fType
= MFT_STRING
;
5172 _sntprintf(tcbuf
, sizeof(tcbuf
)/sizeof(TCHAR
),
5173 TEXT("%S"), members
->label
.string
);
5174 mitem
.dwTypeData
= tcbuf
;
5175 mitem
.cch
= (UINT
)_tcslen(tcbuf
);
5179 InsertMenuItem(hMenu
, index
, TRUE
, &mitem
);
5186 PopupId(MPopup
*members
, int id
)
5190 for(; members
->type
!= tTail
; members
++)
5191 switch(members
->type
){
5193 if(mp
= PopupId(members
->data
.submenu
, id
))
5202 if(members
->internal
.id
== id
)
5213 * Make a pop-up offering Copy/Cut/Paste menu and track it
5216 CopyCutPopup(HWND hWnd
, UINT fAllowed
)
5225 * If nothing to do just silently return
5227 if(fAllowed
!= EM_NONE
&& (hMenu
= CreatePopupMenu())){
5228 if(fAllowed
& EM_CUT
){
5229 /* Insert a "Copy" option */
5230 memset(&mitem
, 0, sizeof(MENUITEMINFO
));
5231 mitem
.cbSize
= sizeof(MENUITEMINFO
);
5232 mitem
.fMask
= MIIM_TYPE
| MIIM_ID
;
5233 mitem
.wID
= IDM_EDIT_CUT
;
5234 mitem
.fType
= MFT_STRING
;
5235 mitem
.dwTypeData
= TEXT("Cut");
5237 InsertMenuItem(hMenu
, ++n
, FALSE
, &mitem
);
5240 if(fAllowed
& EM_CP
){
5241 /* Insert a "Copy" option */
5242 memset(&mitem
, 0, sizeof(MENUITEMINFO
));
5243 mitem
.cbSize
= sizeof(MENUITEMINFO
);
5244 mitem
.fMask
= MIIM_TYPE
| MIIM_ID
;
5245 mitem
.wID
= IDM_EDIT_COPY
;
5246 mitem
.fType
= MFT_STRING
;
5247 mitem
.dwTypeData
= TEXT("Copy");
5249 InsertMenuItem(hMenu
, ++n
, FALSE
, &mitem
);
5252 if(fAllowed
& EM_CP_APPEND
){
5253 /* Insert a "Copy Append" option */
5254 memset(&mitem
, 0, sizeof(MENUITEMINFO
));
5255 mitem
.cbSize
= sizeof(MENUITEMINFO
);
5256 mitem
.fMask
= MIIM_TYPE
| MIIM_ID
;
5257 mitem
.wID
= IDM_EDIT_COPY_APPEND
;
5258 mitem
.fType
= MFT_STRING
;
5259 mitem
.dwTypeData
= TEXT("Copy Append");
5261 InsertMenuItem(hMenu
, ++n
, FALSE
, &mitem
);
5264 if(fAllowed
& EM_PST
){
5265 /* Insert a "Paste" option */
5266 memset(&mitem
, 0, sizeof(MENUITEMINFO
));
5267 mitem
.cbSize
= sizeof(MENUITEMINFO
);
5268 mitem
.fMask
= MIIM_TYPE
| MIIM_ID
;
5269 mitem
.wID
= IDM_EDIT_PASTE
;
5270 mitem
.fType
= MFT_STRING
;
5271 mitem
.dwTypeData
= TEXT("Paste");
5273 InsertMenuItem(hMenu
, ++n
, FALSE
, &mitem
);
5276 if((fAllowed
& EM_SEL_ALL
) && !(fAllowed
& (EM_CP
| EM_CP_APPEND
))){
5277 /* Insert a "Select All" option */
5278 memset(&mitem
, 0, sizeof(MENUITEMINFO
));
5279 mitem
.cbSize
= sizeof(MENUITEMINFO
);
5280 mitem
.fMask
= MIIM_TYPE
| MIIM_ID
;
5281 mitem
.wID
= IDM_EDIT_SEL_ALL
;
5282 mitem
.fType
= MFT_STRING
;
5283 mitem
.dwTypeData
= TEXT("Select &All");
5285 InsertMenuItem(hMenu
, ++n
, FALSE
, &mitem
);
5288 if(n
>= 0 && GetCursorPos(&point
)){
5289 TrackPopupMenu(hMenu
,
5290 TPM_LEFTALIGN
| TPM_TOPALIGN
5291 | TPM_RIGHTBUTTON
| TPM_LEFTBUTTON
,
5292 point
.x
, point
.y
, 0, hWnd
, NULL
);
5317 * If nothing to do just silently return
5319 if(hMenu
= CreatePopupMenu()){
5321 if((fAllow
= UpdateEditAllowed(ghTTYWnd
)) != EM_NONE
){
5322 /* Insert a "Cut" option */
5323 memset(&mitem
, 0, sizeof(MENUITEMINFO
));
5324 mitem
.cbSize
= sizeof(MENUITEMINFO
);
5325 mitem
.fMask
= MIIM_TYPE
| MIIM_ID
| MIIM_STATE
;
5326 mitem
.wID
= IDM_EDIT_CUT
;
5327 mitem
.fState
= (fAllow
& EM_CUT
) ? MFS_ENABLED
: MFS_GRAYED
;
5328 mitem
.fType
= MFT_STRING
;
5329 mitem
.dwTypeData
= TEXT("Cut");
5331 InsertMenuItem(hMenu
, ++n
, FALSE
, &mitem
);
5333 /* Insert a "Copy" option */
5334 memset(&mitem
, 0, sizeof(MENUITEMINFO
));
5335 mitem
.cbSize
= sizeof(MENUITEMINFO
);
5336 mitem
.fMask
= MIIM_TYPE
| MIIM_ID
| MIIM_STATE
;
5337 mitem
.wID
= IDM_EDIT_COPY
;
5338 mitem
.fState
= (fAllow
& EM_CP
) ? MFS_ENABLED
: MFS_GRAYED
;
5339 mitem
.fType
= MFT_STRING
;
5340 mitem
.dwTypeData
= TEXT("Copy");
5342 InsertMenuItem(hMenu
, ++n
, FALSE
, &mitem
);
5344 /* Insert a "Copy Append" option */
5345 memset(&mitem
, 0, sizeof(MENUITEMINFO
));
5346 mitem
.cbSize
= sizeof(MENUITEMINFO
);
5347 mitem
.fMask
= MIIM_TYPE
| MIIM_ID
| MIIM_STATE
;
5348 mitem
.wID
= IDM_EDIT_COPY_APPEND
;
5349 mitem
.fState
= (fAllow
& EM_CP_APPEND
) ? MFS_ENABLED
: MFS_GRAYED
;
5350 mitem
.fType
= MFT_STRING
;
5351 mitem
.dwTypeData
= TEXT("Copy Append");
5353 InsertMenuItem(hMenu
, ++n
, FALSE
, &mitem
);
5355 /* Insert a "Paste" option */
5356 memset(&mitem
, 0, sizeof(MENUITEMINFO
));
5357 mitem
.cbSize
= sizeof(MENUITEMINFO
);
5358 mitem
.fMask
= MIIM_TYPE
| MIIM_ID
| MIIM_STATE
;
5359 mitem
.wID
= IDM_EDIT_PASTE
;
5360 mitem
.fType
= MFT_STRING
;
5361 mitem
.dwTypeData
= TEXT("Paste");
5362 mitem
.fState
= (fAllow
& EM_PST
) ? MFS_ENABLED
: MFS_GRAYED
;
5364 InsertMenuItem(hMenu
, ++n
, FALSE
, &mitem
);
5367 /* Insert a "Select All" option */
5368 memset(&mitem
, 0, sizeof(MENUITEMINFO
));
5369 mitem
.cbSize
= sizeof(MENUITEMINFO
);
5370 mitem
.fMask
= MIIM_TYPE
| MIIM_ID
| MIIM_STATE
;
5371 mitem
.wID
= IDM_EDIT_SEL_ALL
;
5372 mitem
.fType
= MFT_STRING
;
5373 mitem
.fState
= (fAllow
& (EM_CP
| EM_CP_APPEND
))
5374 ? MFS_GRAYED
: MFS_ENABLED
;
5375 mitem
.dwTypeData
= TEXT("Select &All");
5377 InsertMenuItem(hMenu
, ++n
, FALSE
, &mitem
);
5379 if(n
>= 0 && GetCursorPos(&point
))
5380 TrackPopupMenu(hMenu
,
5381 TPM_LEFTALIGN
| TPM_TOPALIGN
5382 | TPM_RIGHTBUTTON
| TPM_LEFTBUTTON
,
5383 point
.x
, point
.y
, 0, ghTTYWnd
, NULL
);
5404 * If nothing to do just silently return
5406 if(hMenu
= CreatePopupMenu()){
5408 if((fAllow
= UpdateEditAllowed(ghTTYWnd
)) != EM_NONE
){
5409 /* Insert a "Paste" option */
5410 memset(&mitem
, 0, sizeof(MENUITEMINFO
));
5411 mitem
.cbSize
= sizeof(MENUITEMINFO
);
5412 mitem
.fMask
= MIIM_TYPE
| MIIM_ID
| MIIM_STATE
;
5413 mitem
.wID
= IDM_EDIT_PASTE
;
5414 mitem
.fType
= MFT_STRING
;
5415 mitem
.dwTypeData
= TEXT("Paste");
5416 mitem
.fState
= (fAllow
& EM_PST
) ? MFS_ENABLED
: MFS_GRAYED
;
5418 InsertMenuItem(hMenu
, ++n
, FALSE
, &mitem
);
5420 if(n
>= 0 && GetCursorPos(&point
))
5421 TrackPopupMenu(hMenu
,
5422 TPM_LEFTALIGN
| TPM_TOPALIGN
5423 | TPM_RIGHTBUTTON
| TPM_LEFTBUTTON
,
5424 point
.x
, point
.y
, 0, ghTTYWnd
, NULL
);
5434 mswin_keymenu_popup()
5436 HMENU hBarMenu
, hMenu
;
5443 * run thru menubar from left to right and down each list building
5444 * a popup of all active members. we run down the menu's rather
5445 * than thru the menuItems array so we can preserve order...
5447 if((hMenu
= CreatePopupMenu())){
5448 if(hBarMenu
= GetMenu(ghTTYWnd
)){
5449 /* For each possible index, look for matching registered key */
5450 for(n
= 0, i
= 1; i
<= KS_COUNT
; i
++)
5451 for(j
= 0; j
< KS_COUNT
; j
++)
5452 if(gpTTYInfo
->menuItems
[j
].miIndex
== i
){
5453 if(gpTTYInfo
->menuItems
[j
].miActive
== TRUE
5454 && gpTTYInfo
->menuItems
[j
].miLabel
){
5455 mitem
.cbSize
= sizeof(MENUITEMINFO
);
5456 mitem
.fMask
= MIIM_ID
| MIIM_STATE
| MIIM_TYPE
;
5457 mitem
.wID
= j
+ KS_RANGESTART
;
5458 mitem
.fState
= MFS_ENABLED
;
5459 mitem
.fType
= MFT_STRING
;
5460 /* miLabel is still plain old char *, not utf8 */
5461 _sntprintf(tcbuf
, sizeof(tcbuf
)/sizeof(TCHAR
),
5462 TEXT("%S"), gpTTYInfo
->menuItems
[j
].miLabel
);
5463 mitem
.dwTypeData
= tcbuf
;
5464 mitem
.cch
= (UINT
)_tcslen(tcbuf
);
5465 InsertMenuItem(hMenu
, n
++, TRUE
, &mitem
);
5467 if(j
+ KS_RANGESTART
== IDM_MI_SCREENHELP
5469 mitem
.cbSize
= sizeof(MENUITEMINFO
);
5470 mitem
.fMask
= MIIM_ID
| MIIM_STATE
| MIIM_TYPE
;
5471 mitem
.wID
= IDM_HELP
;
5472 mitem
.fState
= MFS_ENABLED
;
5473 mitem
.fType
= MFT_STRING
;
5474 _sntprintf(tcbuf
, sizeof(tcbuf
)/sizeof(TCHAR
),
5475 TEXT("%S"), "Help in New Window");
5476 mitem
.dwTypeData
= tcbuf
;
5477 mitem
.cch
= (UINT
)_tcslen(tcbuf
);
5478 InsertMenuItem(hMenu
, n
++, TRUE
, &mitem
);
5485 if(n
> 0 && GetCursorPos(&point
)){
5486 TrackPopupMenu(hMenu
,
5487 TPM_LEFTALIGN
| TPM_TOPALIGN
5488 | TPM_RIGHTBUTTON
| TPM_LEFTBUTTON
,
5489 point
.x
, point
.y
, 0, ghTTYWnd
, NULL
);
5503 mswin_registericon(int row
, int id
, char *utf8_file
)
5510 /* Turn this off until it can get tuned */
5513 /* Already registered? */
5514 for(pIcon
= gIconList
; pIcon
; pIcon
= pIcon
->next
)
5515 if(pIcon
->id
== id
){
5516 pIcon
->row
= (short)row
;
5520 sPathCopy
= utf8_to_lptstr(utf8_file
);
5522 if(hIcon
= ExtractAssociatedIcon(ghInstance
, sPathCopy
, &iIcon
))
5523 MSWIconAddList(row
, id
, hIcon
);
5525 fs_give((void **) &sPathCopy
);
5530 mswin_destroyicons()
5532 MSWIconFree(&gIconList
);
5537 MSWIconAddList(int row
, int id
, HICON hIcon
)
5541 for(ppIcon
= &gIconList
; *ppIcon
; ppIcon
= &(*ppIcon
)->next
)
5544 *ppIcon
= (IconList
*) MemAlloc (sizeof (IconList
));
5545 memset(*ppIcon
, 0, sizeof(IconList
));
5546 (*ppIcon
)->hIcon
= hIcon
;
5548 (*ppIcon
)->row
= (short)row
;
5553 MSWIconPaint(int row
, HDC hDC
)
5558 for(pIcon
= gIconList
; pIcon
&& pIcon
->row
!= row
; pIcon
= pIcon
->next
)
5562 /* Invalidate rectange covering singel character. */
5563 DrawIconEx(hDC
, 0, (row
* gpTTYInfo
->yChar
) + gpTTYInfo
->yOffset
,
5564 pIcon
->hIcon
, 2 * gpTTYInfo
->xChar
, gpTTYInfo
->yChar
,
5565 0, NULL
, DI_NORMAL
);
5575 MSWIconFree(IconList
**ppIcon
)
5577 if(ppIcon
&& *ppIcon
){
5579 MSWIconFree(&(*ppIcon
)->next
);
5581 DestroyIcon((*ppIcon
)->hIcon
);
5589 * Set up debugging stuff.
5592 mswin_setdebug (int debug
, FILE *debugfile
)
5594 /* Accept new file only if we don't already have a file. */
5595 if (mswin_debugfile
== 0) {
5596 mswin_debug
= debug
;
5597 mswin_debugfile
= debugfile
;
5598 MemDebug (debug
, mswin_debugfile
);
5604 mswin_setnewmailwidth (int width
)
5607 gNMW_width
= gNMW_width
< 20 ? 20 : gNMW_width
;
5608 gNMW_width
= gNMW_width
> 170 ? 170 : gNMW_width
;
5613 * Event handler to deal with File Drop events
5616 ProcessTTYFileDrop (HANDLE wDrop
)
5618 HDROP hDrop
= wDrop
;
5624 if(!gpTTYInfo
->dndhandler
)
5627 /* translate drop point to character cell */
5628 DragQueryPoint(hDrop
, &pos
);
5629 col
= (pos
.x
- gpTTYInfo
->xOffset
) / gpTTYInfo
->xChar
;
5630 if (pos
.x
< gpTTYInfo
->xOffset
)
5632 row
= (pos
.y
- gpTTYInfo
->yOffset
) / gpTTYInfo
->yChar
;
5633 if (pos
.y
< gpTTYInfo
->yOffset
)
5636 for(n
= DragQueryFile(hDrop
, (UINT
)-1, NULL
, 0), i
= 0; i
< n
; i
++){
5637 DragQueryFile(hDrop
, i
, fname
, 1024);
5638 utf8_fname
= lptstr_to_utf8(fname
);
5639 gpTTYInfo
->dndhandler (row
, col
, utf8_fname
);
5640 fs_give((void **) &utf8_fname
);
5645 set_time_of_last_input();
5652 * Set a callback to deal with Drag 'N Drop events
5655 mswin_setdndcallback (int (*cb
)())
5657 if(gpTTYInfo
->dndhandler
)
5658 gpTTYInfo
->dndhandler
= NULL
;
5661 gpTTYInfo
->dndhandler
= cb
;
5662 DragAcceptFiles(ghTTYWnd
, TRUE
);
5670 * Clear previously installed callback to handle Drag 'N Drop
5674 mswin_cleardndcallback ()
5676 gpTTYInfo
->dndhandler
= NULL
;
5677 DragAcceptFiles(ghTTYWnd
, FALSE
);
5683 * Set a callback for function 'ch'
5686 mswin_setresizecallback (int (*cb
)())
5693 * Look through whole array for this call back function. Don't
5694 * insert duplicate. Also look for empty slot.
5697 for (i
= 0; i
< RESIZE_CALLBACK_ARRAY_SIZE
; ++i
) {
5698 if (gpTTYInfo
->resizer
[i
] == cb
)
5700 if (e
== -1 && gpTTYInfo
->resizer
[i
] == NULL
)
5705 * Insert in empty slot or return an error.
5708 gpTTYInfo
->resizer
[e
] = cb
;
5716 * Clear all instances of the callback function 'cb'
5719 mswin_clearresizecallback (int (*cb
)())
5725 for (i
= 0; i
< RESIZE_CALLBACK_ARRAY_SIZE
; ++i
) {
5726 if (gpTTYInfo
->resizer
[i
] == cb
) {
5727 gpTTYInfo
->resizer
[i
] = NULL
;
5736 mswin_beginupdate (void)
5738 gpTTYInfo
->fMassiveUpdate
= TRUE
;
5743 mswin_endupdate (void)
5745 gpTTYInfo
->fMassiveUpdate
= FALSE
;
5746 MoveTTYCursor (ghTTYWnd
);
5751 mswin_charsetid2string(LPTSTR fontCharSet
, size_t nfontCharSet
, BYTE lfCharSet
)
5757 case DEFAULT_CHARSET
:
5760 _tcsncpy(buf
, TEXT("ANSI_CHARSET"), sizeof(buf
)/sizeof(TCHAR
));
5763 _tcsncpy(buf
, TEXT("OEM_CHARSET"), sizeof(buf
)/sizeof(TCHAR
));
5765 case BALTIC_CHARSET
:
5766 _tcsncpy(buf
, TEXT("BALTIC_CHARSET"), sizeof(buf
)/sizeof(TCHAR
));
5768 case CHINESEBIG5_CHARSET
:
5769 _tcsncpy(buf
, TEXT("CHINESE_CHARSET"), sizeof(buf
)/sizeof(TCHAR
));
5771 case EASTEUROPE_CHARSET
:
5772 _tcsncpy(buf
, TEXT("EASTEUROPE_CHARSET"), sizeof(buf
)/sizeof(TCHAR
));
5774 case GB2312_CHARSET
:
5775 _tcsncpy(buf
, TEXT("GF2312_CHARSET"), sizeof(buf
)/sizeof(TCHAR
));
5778 _tcsncpy(buf
, TEXT("GREEK_CHARSET"), sizeof(buf
)/sizeof(TCHAR
));
5780 case HANGUL_CHARSET
:
5781 _tcsncpy(buf
, TEXT("HANGUL_CHARSET"), sizeof(buf
)/sizeof(TCHAR
));
5784 _tcsncpy(buf
, TEXT("MAC_CHARSET"), sizeof(buf
)/sizeof(TCHAR
));
5786 case RUSSIAN_CHARSET
:
5787 _tcsncpy(buf
, TEXT("RUSSIAN_CHARSET"), sizeof(buf
)/sizeof(TCHAR
));
5789 case SHIFTJIS_CHARSET
:
5790 _tcsncpy(buf
, TEXT("SHIFTJIS_CHARSET"), sizeof(buf
)/sizeof(TCHAR
));
5792 case SYMBOL_CHARSET
:
5793 _tcsncpy(buf
, TEXT("SYMBOL_CHARSET"), sizeof(buf
)/sizeof(TCHAR
));
5795 case TURKISH_CHARSET
:
5796 _tcsncpy(buf
, TEXT("TURKISH_CHARSET"), sizeof(buf
)/sizeof(TCHAR
));
5798 case VIETNAMESE_CHARSET
:
5799 _tcsncpy(buf
, TEXT("VIETNAMESE_CHARSET"), sizeof(buf
)/sizeof(TCHAR
));
5802 _tcsncpy(buf
, TEXT("JOHAB_CHARSET"), sizeof(buf
)/sizeof(TCHAR
));
5804 case ARABIC_CHARSET
:
5805 _tcsncpy(buf
, TEXT("ARABIC_CHARSET"), sizeof(buf
)/sizeof(TCHAR
));
5807 case HEBREW_CHARSET
:
5808 _tcsncpy(buf
, TEXT("HEBREW_CHARSET"), sizeof(buf
)/sizeof(TCHAR
));
5811 _tcsncpy(buf
, TEXT("THAI_CHARSET"), sizeof(buf
)/sizeof(TCHAR
));
5814 /* default char set if we can't figure it out */
5818 buf
[sizeof(buf
)/sizeof(TCHAR
) - 1] = '\0';
5820 _tcsncpy(fontCharSet
, buf
, nfontCharSet
);
5821 fontCharSet
[nfontCharSet
-1] = '\0';
5828 mswin_string2charsetid(LPTSTR str
)
5832 if(!str
|| (lstrlen(str
) >= 1024))
5833 return DEFAULT_CHARSET
;
5835 if((lstrlen(str
) > lstrlen(TEXT("_CHARSET")))
5836 && (tcsucmp(str
+ lstrlen(str
) - lstrlen(TEXT("_CHARSET")), TEXT("_CHARSET")) == 0)){
5837 _tcsncpy(tstr
, str
, 1024);
5838 tstr
[lstrlen(str
) - lstrlen(TEXT("_CHARSET"))] = '\0';
5839 tstr
[1024-1] = '\0';
5840 if(tcsucmp(tstr
, TEXT("ANSI")) == 0)
5841 return ANSI_CHARSET
;
5842 else if(tcsucmp(tstr
, TEXT("DEFAULT")) == 0)
5843 return DEFAULT_CHARSET
;
5844 else if(tcsucmp(tstr
, TEXT("OEM")) == 0)
5846 else if(tcsucmp(tstr
, TEXT("BALTIC")) == 0)
5847 return BALTIC_CHARSET
;
5848 else if(tcsucmp(tstr
, TEXT("CHINESEBIG5")) == 0)
5849 return CHINESEBIG5_CHARSET
;
5850 else if(tcsucmp(tstr
, TEXT("EASTEUROPE")) == 0)
5851 return EASTEUROPE_CHARSET
;
5852 else if(tcsucmp(tstr
, TEXT("GB2312")) == 0)
5853 return GB2312_CHARSET
;
5854 else if(tcsucmp(tstr
, TEXT("GREEK")) == 0)
5855 return GREEK_CHARSET
;
5856 else if(tcsucmp(tstr
, TEXT("HANGUL")) == 0)
5857 return HANGUL_CHARSET
;
5858 else if(tcsucmp(tstr
, TEXT("MAC")) == 0)
5860 else if(tcsucmp(tstr
, TEXT("RUSSIAN")) == 0)
5861 return RUSSIAN_CHARSET
;
5862 else if(tcsucmp(tstr
, TEXT("SHIFTJIS")) == 0)
5863 return SHIFTJIS_CHARSET
;
5864 else if(tcsucmp(tstr
, TEXT("SYMBOL")) == 0)
5865 return SYMBOL_CHARSET
;
5866 else if(tcsucmp(tstr
, TEXT("TURKISH")) == 0)
5867 return TURKISH_CHARSET
;
5868 else if(tcsucmp(tstr
, TEXT("VIETNAMESE")) == 0)
5869 return VIETNAMESE_CHARSET
;
5870 else if(tcsucmp(tstr
, TEXT("JOHAB")) == 0)
5871 return JOHAB_CHARSET
;
5872 else if(tcsucmp(tstr
, TEXT("ARABIC")) == 0)
5873 return ARABIC_CHARSET
;
5874 else if(tcsucmp(tstr
, TEXT("HEBREW")) == 0)
5875 return HEBREW_CHARSET
;
5876 else if(tcsucmp(tstr
, TEXT("THAI")) == 0)
5877 return THAI_CHARSET
;
5879 return DEFAULT_CHARSET
;
5883 return((BYTE
)(_tstoi(str
)));
5885 return DEFAULT_CHARSET
;
5891 mswin_setwindow(char *fontName_utf8
, char *fontSize_utf8
, char *fontStyle_utf8
,
5892 char *windowPosition
, char *caretStyle
, char *fontCharSet_utf8
)
5898 RECT wndRect
, cliRect
;
5902 BOOL toolBar
= FALSE
;
5903 BOOL toolBarTop
= TRUE
;
5904 int wColumns
, wRows
;
5906 int wXBorder
, wYBorder
;
5908 char wp
[WIN_POS_STR_MAX_LEN
+ 1];
5910 LPTSTR fontName_lpt
= NULL
;
5911 LPTSTR fontCharSet_lpt
;
5914 if (mswin_debug
>= 5)
5915 fprintf (mswin_debugfile
, "mswin_setwindow::: entered, minimized: %d\n",
5916 gpTTYInfo
->fMinimized
);
5919 /* Require a font name to set font info. */
5920 if(fontName_utf8
!= NULL
&& *fontName_utf8
!= '\0' &&
5921 (fontName_lpt
= utf8_to_lptstr(fontName_utf8
)) &&
5922 _tcslen(fontName_lpt
) <= LF_FACESIZE
- 1){
5924 hDC
= GetDC(ghTTYWnd
);
5925 ppi
= GetDeviceCaps(hDC
, LOGPIXELSY
);
5926 ReleaseDC(ghTTYWnd
, hDC
);
5928 /* Default height, then examin the requested fontSize. */
5929 newFont
.lfHeight
= -MulDiv(12, ppi
, 72);
5930 if(ScanInt(fontSize_utf8
, FONT_MIN_SIZE
, FONT_MAX_SIZE
, &newHeight
)){
5931 newHeight
= abs(newHeight
);
5932 newFont
.lfHeight
= -MulDiv(newHeight
, ppi
, 72);
5935 /* Default font style, then read requested style. */
5936 newFont
.lfWeight
= 0;
5937 newFont
.lfItalic
= 0;
5938 if(fontStyle_utf8
!= NULL
){
5939 _strlwr(fontStyle_utf8
);
5940 if(strstr(fontStyle_utf8
, "bold"))
5941 newFont
.lfWeight
= FW_BOLD
;
5942 if(strstr(fontStyle_utf8
, "italic"))
5943 newFont
.lfItalic
= 1;
5946 /* Everything else takes the default. */
5947 newFont
.lfWidth
= 0;
5948 newFont
.lfEscapement
= 0;
5949 newFont
.lfOrientation
= 0;
5950 newFont
.lfUnderline
= 0;
5951 newFont
.lfStrikeOut
= 0;
5952 fontCharSet_lpt
= utf8_to_lptstr(fontCharSet_utf8
);
5953 if(fontCharSet_lpt
){
5954 newFont
.lfCharSet
= mswin_string2charsetid(fontCharSet_lpt
);
5955 fs_give((void **) &fontCharSet_lpt
);
5958 newFont
.lfOutPrecision
= OUT_DEFAULT_PRECIS
;
5959 newFont
.lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
5960 newFont
.lfQuality
= DEFAULT_QUALITY
;
5961 newFont
.lfPitchAndFamily
= FIXED_PITCH
;
5962 _sntprintf(newFont
.lfFaceName
, LF_FACESIZE
, TEXT("%s"), fontName_lpt
);
5963 ResetTTYFont (ghTTYWnd
, gpTTYInfo
, &newFont
);
5967 fs_give((void **) &fontName_lpt
);
5970 * Set window position. String format is: CxR+X+Y
5971 * Where C is the number of columns, R is the number of rows,
5972 * and X and Y specify the top left corner of the window.
5974 if(windowPosition
!= NULL
&& *windowPosition
!= '\0'){
5975 if(strlen(windowPosition
) > sizeof(wp
)-1)
5978 strncpy(wp
, windowPosition
, sizeof(wp
));
5979 wp
[sizeof(wp
)-1] = '\0';
5982 * Flag characters are at the end of the string. Strip them
5983 * off till we get to a number.
5985 i
= (int)strlen(wp
) - 1;
5986 while(i
> 0 && (*(wp
+i
) < '0' || *(wp
+i
) > '9')){
5987 if(*(wp
+i
) == 't' || *(wp
+i
) == 'b'){
5989 toolBarTop
= (*(wp
+i
) == 't');
5993 gfUseDialogs
= TRUE
;
5995 #ifdef ACCELERATORS_OPT
5997 AccelCtl(ghTTYWnd
, ACCEL_LOAD
, FALSE
);
6004 if(strcmp(wp
, "MIN0") == 0){
6007 ShowWindow(ghTTYWnd
, SW_MINIMIZE
);
6009 gpTTYInfo
->toolBarTop
= toolBarTop
;
6014 /* Look for Columns, deliminated by 'x'. */
6015 c
= strchr (wp
, 'x');
6020 if(!ScanInt(wp
, -999, 9999, &wColumns
))
6023 /* Look for Rows, deliminated by '+'. */
6030 if(!ScanInt(n
, -999, 9999, &wRows
))
6033 /* Look for X position, deliminated by '+'. */
6040 if(!ScanInt(n
, -999, 9999, &wXPos
))
6043 /* And get Y position, deliminated by end of string. */
6045 if(!ScanInt(n
, -999, 9999, &wYPos
))
6049 /* Constrain the window position and size. */
6056 GetWindowRect(GetDesktopWindow(), &wndRect
);
6057 if(wXPos
> wndRect
.right
- 20)
6058 wXPos
= wndRect
.right
- 100;
6060 if(wYPos
> wndRect
.bottom
- 20)
6061 wYPos
= wndRect
.bottom
- 100;
6063 /* Get the current window rect and client area. */
6064 GetWindowRect(ghTTYWnd
, &wndRect
);
6065 GetClientRect(ghTTYWnd
, &cliRect
);
6067 /* Calculate boarder sizes. */
6068 wXBorder
= wndRect
.right
- wndRect
.left
- cliRect
.right
;
6069 wYBorder
= wndRect
.bottom
- wndRect
.top
- cliRect
.bottom
;
6071 /* Show toolbar before calculating content size. */
6073 gpTTYInfo
->toolBarTop
= toolBarTop
;
6077 /* Calculate new window pos and size. */
6078 wXSize
= wXBorder
+ (wColumns
* gpTTYInfo
->xChar
) +
6079 (2 * gpTTYInfo
->xOffset
);
6080 wYSize
= wYBorder
+ (wRows
* gpTTYInfo
->yChar
) +
6081 gpTTYInfo
->toolBarSize
+ (2 * MARGINE_TOP
);
6082 if(!gpTTYInfo
->fMinimized
)
6083 MoveWindow(ghTTYWnd
, wXPos
, wYPos
, wXSize
, wYSize
, TRUE
);
6085 gpTTYInfo
->fDesiredSize
= TRUE
;
6086 gpTTYInfo
->xDesPos
= (CORD
)wXPos
;
6087 gpTTYInfo
->yDesPos
= (CORD
)wYPos
;
6088 gpTTYInfo
->xDesSize
= (CORD
)wXSize
;
6089 gpTTYInfo
->yDesSize
= (CORD
)wYSize
;
6094 if(caretStyle
!= NULL
&& *caretStyle
!= '\0')
6095 for(i
= 0; MSWinCaretTable
[i
].name
; i
++)
6096 if(!strucmp(MSWinCaretTable
[i
].name
, caretStyle
)){
6097 CaretTTY(ghTTYWnd
, MSWinCaretTable
[i
].style
);
6109 ShowWindow (ghTTYWnd
, SW_SHOWNORMAL
);
6110 UpdateWindow (ghTTYWnd
);
6117 * Retreive the current font name, font size, and window position
6118 * These get stored in the pinerc file and will be passed to
6119 * mswin_setwindow() when pine starts up. See pinerc for comments
6123 mswin_getwindow(char *fontName_utf8
, size_t nfontName
,
6124 char *fontSize_utf8
, size_t nfontSize
,
6125 char *fontStyle_utf8
, size_t nfontStyle
,
6126 char *windowPosition
, size_t nwindowPosition
,
6127 char *foreColor
, size_t nforeColor
,
6128 char *backColor
, size_t nbackColor
,
6129 char *caretStyle
, size_t ncaretStyle
,
6130 char *fontCharSet_utf8
, size_t nfontCharSet
)
6137 if(fontName_utf8
!= NULL
){
6138 t
= lptstr_to_utf8(gpTTYInfo
->lfTTYFont
.lfFaceName
);
6139 if(strlen(t
) < nfontName
)
6140 snprintf(fontName_utf8
, nfontName
, "%s", t
);
6142 fs_give((void **) &t
);
6145 if(fontCharSet_utf8
!= NULL
){
6148 lpt
= (LPTSTR
) fs_get(nfontCharSet
* sizeof(TCHAR
));
6151 mswin_charsetid2string(lpt
, nfontCharSet
, gpTTYInfo
->lfTTYFont
.lfCharSet
);
6152 t
= lptstr_to_utf8(lpt
);
6153 if(strlen(t
) < nfontCharSet
)
6154 snprintf(fontCharSet_utf8
, nfontCharSet
, "%s", t
);
6156 fs_give((void **) &t
);
6158 fs_give((void **) &lpt
);
6162 if(fontSize_utf8
!= NULL
){
6163 hDC
= GetDC(ghTTYWnd
);
6164 ppi
= GetDeviceCaps(hDC
, LOGPIXELSY
);
6165 ReleaseDC(ghTTYWnd
, hDC
);
6166 snprintf(fontSize_utf8
, nfontSize
, "%d", MulDiv(-gpTTYInfo
->lfTTYFont
.lfHeight
, 72, ppi
));
6169 if(fontStyle_utf8
!= NULL
){
6170 char *sep
[] = {"", ", "};
6173 *fontStyle_utf8
= '\0';
6174 if(gpTTYInfo
->lfTTYFont
.lfWeight
>= FW_BOLD
){
6175 strncpy(fontStyle_utf8
, "bold", nfontStyle
);
6176 fontStyle_utf8
[nfontStyle
-1] = '\0';
6180 if(gpTTYInfo
->lfTTYFont
.lfItalic
){
6181 strncat(fontStyle_utf8
, sep
[iSep
], nfontStyle
-strlen(fontStyle_utf8
)-1);
6182 fontStyle_utf8
[nfontStyle
-1] = '\0';
6183 strncat(fontStyle_utf8
, "italic", nfontStyle
-strlen(fontStyle_utf8
)-1);
6184 fontStyle_utf8
[nfontStyle
-1] = '\0';
6188 if(windowPosition
!= NULL
){
6189 if(gpTTYInfo
->fMinimized
){
6190 strncpy(windowPosition
, "MIN0", nwindowPosition
);
6191 windowPosition
[nwindowPosition
-1] = '\0';
6195 * Get the window position. Constrain the top left corner
6196 * to be on the screen.
6198 GetWindowRect(ghTTYWnd
, &wndRect
);
6199 if(wndRect
.left
< 0)
6205 snprintf(windowPosition
, nwindowPosition
, "%dx%d+%d+%d", gpTTYInfo
->actNColumn
,
6206 gpTTYInfo
->actNRow
, wndRect
.left
, wndRect
.top
);
6209 if(gpTTYInfo
->toolBarSize
> 0){
6210 strncat(windowPosition
, gpTTYInfo
->toolBarTop
? "t" : "b",
6211 nwindowPosition
-strlen(windowPosition
)-1);
6212 windowPosition
[nwindowPosition
-1] = '\0';
6216 strncat(windowPosition
, "d", nwindowPosition
-strlen(windowPosition
)-1);
6217 windowPosition
[nwindowPosition
-1] = '\0';
6220 if(gpTTYInfo
->hAccel
){
6221 strncat(windowPosition
, "a", nwindowPosition
-strlen(windowPosition
)-1);
6222 windowPosition
[nwindowPosition
-1] = '\0';
6225 if(gpTTYInfo
->fMaximized
){
6226 strncat(windowPosition
, "!", nwindowPosition
-strlen(windowPosition
)-1);
6227 windowPosition
[nwindowPosition
-1] = '\0';
6231 if(foreColor
!= NULL
)
6232 ConvertStringRGB(foreColor
, nforeColor
, gpTTYInfo
->rgbFGColor
);
6234 if(backColor
!= NULL
)
6235 ConvertStringRGB(backColor
, nbackColor
, gpTTYInfo
->rgbBGColor
);
6237 if(caretStyle
!= NULL
){
6240 for(i
= 0; MSWinCaretTable
[i
].name
; i
++)
6241 if(MSWinCaretTable
[i
].style
== gpTTYInfo
->cCaretStyle
){
6242 strncpy(caretStyle
, MSWinCaretTable
[i
].name
, ncaretStyle
);
6243 caretStyle
[ncaretStyle
-1] = '\0';
6253 mswin_noscrollupdate(int flag
)
6255 gpTTYInfo
->noScrollUpdate
= (flag
!= 0);
6256 if(flag
== 0 && gpTTYInfo
->scrollRangeChanged
){
6257 mswin_setscrollrange(gpTTYInfo
->noSUpdatePage
, gpTTYInfo
->noSUpdateRange
);
6258 gpTTYInfo
->noSUpdatePage
= gpTTYInfo
->noSUpdateRange
= 0;
6259 gpTTYInfo
->scrollRangeChanged
= 0;
6265 * Set the scroll range.
6268 mswin_setscrollrange (long page
, long max
)
6270 SCROLLINFO scrollInfo
;
6272 if(gpTTYInfo
->noScrollUpdate
){
6273 gpTTYInfo
->noSUpdatePage
= page
;
6274 gpTTYInfo
->noSUpdateRange
= max
;
6275 gpTTYInfo
->scrollRangeChanged
= 1;
6278 if (max
!= gpTTYInfo
->scrollRange
) {
6279 scrollInfo
.cbSize
= sizeof(SCROLLINFO
);
6280 scrollInfo
.fMask
= SIF_DISABLENOSCROLL
| SIF_PAGE
| SIF_RANGE
;
6281 scrollInfo
.nMin
= 0;
6284 scrollInfo
.nMax
= (int) max
;
6285 scrollInfo
.nPage
= page
;
6286 SetScrollInfo(ghTTYWnd
, SB_VERT
, &scrollInfo
, TRUE
);
6287 EnableScrollBar (ghTTYWnd
, SB_VERT
, ESB_ENABLE_BOTH
);
6291 scrollInfo
.cbSize
= sizeof(SCROLLINFO
);
6292 scrollInfo
.fMask
|= SIF_POS
;
6293 scrollInfo
.nMax
= 1;
6294 scrollInfo
.nPos
= 0;
6295 SetScrollInfo(ghTTYWnd
, SB_VERT
, &scrollInfo
, TRUE
);
6296 EnableScrollBar (ghTTYWnd
, SB_VERT
, ESB_DISABLE_BOTH
);
6297 gpTTYInfo
->scrollPos
= 0;
6299 gpTTYInfo
->scrollRange
= (int)max
;
6305 * Set the current scroll position.
6308 mswin_setscrollpos (long pos
)
6310 SCROLLINFO scrollInfo
;
6312 if (pos
!= gpTTYInfo
->scrollPos
) {
6313 scrollInfo
.cbSize
= sizeof(SCROLLINFO
);
6314 scrollInfo
.fMask
= SIF_PAGE
| SIF_RANGE
;
6316 GetScrollInfo(ghTTYWnd
, SB_VERT
, &scrollInfo
);
6318 scrollInfo
.fMask
|= SIF_POS
;
6319 scrollInfo
.nPos
= (int) pos
;
6320 SetScrollInfo(ghTTYWnd
, SB_VERT
, &scrollInfo
, TRUE
);
6322 gpTTYInfo
->scrollPos
= pos
;
6328 * retreive the current scroll postion.
6331 mswin_getscrollpos (void)
6333 return ((long)((float)GetScrollPos (ghTTYWnd
, SB_VERT
)));
6338 * retreive the latest scroll to position.
6341 mswin_getscrollto (void)
6343 return (gpTTYInfo
->scrollTo
);
6347 * install function to deal with LINEDOWN events
6350 mswin_setscrollcallback (cbarg_t cbfunc
)
6352 gScrollCallback
= cbfunc
;
6357 * install function to deal with sort menu messages
6360 mswin_setsortcallback (cbarg_t cbfunc
)
6362 gSortCallback
= cbfunc
;
6367 * install function to deal with sort menu messages
6370 mswin_setflagcallback (cbarg_t cbfunc
)
6372 gFlagCallback
= cbfunc
;
6377 mswin_set_erasecreds_callback (cbvoid_t cbfunc
)
6379 gEraseCredsCallback
= cbfunc
;
6383 * install function to deal with header mode flipping
6386 mswin_sethdrmodecallback (cbarg_t cbfunc
)
6388 gHdrCallback
= cbfunc
;
6393 * install function to deal with view in new window messages
6396 mswin_setviewinwindcallback (cbvoid_t cbfunc
)
6398 gViewInWindCallback
= cbfunc
;
6403 * install function to deal with zoom mode flipping
6406 mswin_setzoomodecallback (cbarg_t cbfunc
)
6408 gZoomCallback
= cbfunc
;
6413 * install function to deal with function key mode flipping
6416 mswin_setfkeymodecallback (cbarg_t cbfunc
)
6418 gFkeyCallback
= cbfunc
;
6423 * install function to deal with apply mode flipping
6426 mswin_setselectedcallback (cbarg_t cbfunc
)
6428 gSelectedCallback
= cbfunc
;
6433 * return 1 if new mail window is being used
6436 mswin_newmailwinon (void)
6438 return(gMswinNewMailWin
.hwnd
? 1 : 0);
6445 mswin_setdebugoncallback (cbvoid_t cbfunc
)
6447 gIMAPDebugONCallback
= cbfunc
;
6452 mswin_setdebugoffcallback (cbvoid_t cbfunc
)
6454 gIMAPDebugOFFCallback
= cbfunc
;
6459 mswin_setconfigcallback (cbvoid_t cffunc
)
6461 gConfigScreenCallback
= cffunc
;
6467 * Set the printer font
6470 mswin_setprintfont(char *fontName
, char *fontSize
,
6471 char *fontStyle
, char *fontCharSet
)
6473 LPTSTR fn
= NULL
, fstyle
= NULL
, fc
= NULL
;
6476 fn
= utf8_to_lptstr(fontName
);
6479 fstyle
= utf8_to_lptstr(fontStyle
);
6482 fc
= utf8_to_lptstr(fontCharSet
);
6484 /* Require a font name to set font info. */
6485 if(fn
!= NULL
&& *fn
!= '\0' && lstrlen(fn
) <= LF_FACESIZE
- 1){
6487 _tcsncpy(gPrintFontName
, fn
, sizeof(gPrintFontName
)/sizeof(TCHAR
));
6488 gPrintFontName
[sizeof(gPrintFontName
)/sizeof(TCHAR
)-1] = 0;
6490 _tcsncpy(gPrintFontStyle
, fstyle
, sizeof(gPrintFontStyle
)/sizeof(TCHAR
));
6491 gPrintFontStyle
[sizeof(gPrintFontStyle
)/sizeof(TCHAR
)-1] = 0;
6492 _tcslwr(gPrintFontStyle
); /* Lower case font style. */
6496 _tcsncpy(gPrintFontCharSet
, fc
, sizeof(gPrintFontCharSet
)/sizeof(TCHAR
));
6497 gPrintFontCharSet
[sizeof(gPrintFontCharSet
)/sizeof(TCHAR
)-1] = 0;
6500 gPrintFontSize
= 12;
6501 if(ScanInt(fontSize
, FONT_MIN_SIZE
, FONT_MAX_SIZE
, &gPrintFontSize
))
6502 gPrintFontSize
= abs(gPrintFontSize
);
6504 gPrintFontSameAs
= FALSE
;
6507 gPrintFontName
[0] = '\0';
6508 gPrintFontSameAs
= TRUE
;
6512 fs_give((void **) &fn
);
6515 fs_give((void **) &fstyle
);
6518 fs_give((void **) &fc
);
6523 mswin_getprintfont(char *fontName_utf8
, size_t nfontName
,
6524 char *fontSize_utf8
, size_t nfontSize
,
6525 char *fontStyle_utf8
, size_t nfontStyle
,
6526 char *fontCharSet_utf8
, size_t nfontCharSet
)
6528 if(gPrintFontName
[0] == '\0' || gPrintFontSameAs
){
6529 if(fontName_utf8
!= NULL
)
6530 *fontName_utf8
= '\0';
6531 if(fontSize_utf8
!= NULL
)
6532 *fontSize_utf8
= '\0';
6533 if(fontStyle_utf8
!= NULL
)
6534 *fontStyle_utf8
= '\0';
6535 if(fontCharSet_utf8
!= NULL
)
6536 *fontCharSet_utf8
= '\0';
6541 if(fontName_utf8
!= NULL
){
6542 u
= lptstr_to_utf8(gPrintFontName
);
6544 strncpy(fontName_utf8
, u
, nfontName
);
6545 fontName_utf8
[nfontName
-1] = 0;
6546 fs_give((void **) &u
);
6550 if(fontSize_utf8
!= NULL
)
6551 snprintf(fontSize_utf8
, nfontSize
, "%d", gPrintFontSize
);
6554 if(fontStyle_utf8
!= NULL
){
6555 u
= lptstr_to_utf8(gPrintFontStyle
);
6557 strncpy(fontStyle_utf8
, u
, nfontStyle
);
6558 fontStyle_utf8
[nfontStyle
-1] = 0;
6559 fs_give((void **) &u
);
6563 if(fontCharSet_utf8
!= NULL
){
6564 u
= lptstr_to_utf8(gPrintFontCharSet
);
6566 strncpy(fontCharSet_utf8
, u
, nfontCharSet
);
6567 fontCharSet_utf8
[nfontCharSet
-1] = 0;
6568 fs_give((void **) &u
);
6576 * Set the window help text. Add or delete the Help menu item as needed.
6579 mswin_sethelptextcallback(cbstr_t cbfunc
)
6583 gHelpCallback
= cbfunc
;
6585 hMenu
= GetMenu (ghTTYWnd
);
6589 return(MSWHelpSetMenu (hMenu
));
6595 * Set the window help text. Add or delete the Help menu item as needed.
6598 mswin_setgenhelptextcallback(cbstr_t cbfunc
)
6602 gHelpGenCallback
= cbfunc
;
6604 hMenu
= GetMenu (ghTTYWnd
);
6608 return(MSWHelpSetMenu (hMenu
));
6614 MSWHelpSetMenu(HMENU hMenu
)
6620 * Find menu and update it.
6622 count
= GetMenuItemCount (hMenu
);
6626 hMenu
= GetSubMenu (hMenu
, count
- 1);
6631 * Insert or delete generic help item
6633 if (gHelpGenCallback
== NULL
){
6634 if (gfHelpGenMenu
) {
6635 brc
= DeleteMenu (hMenu
, IDM_MI_GENERALHELP
, MF_BYCOMMAND
);
6636 DrawMenuBar (ghTTYWnd
);
6638 gfHelpGenMenu
= FALSE
;
6641 if (!gfHelpGenMenu
) {
6642 brc
= InsertMenu (hMenu
, 0,
6643 MF_BYPOSITION
| MF_STRING
,
6644 IDM_MI_GENERALHELP
, TEXT("&General Help"));
6645 DrawMenuBar (ghTTYWnd
);
6647 gfHelpGenMenu
= TRUE
;
6651 * Insert or delete screen help item
6653 if (gHelpCallback
== NULL
){
6655 brc
= DeleteMenu (hMenu
, IDM_HELP
, MF_BYCOMMAND
);
6656 DrawMenuBar (ghTTYWnd
);
6662 brc
= InsertMenu (hMenu
, gHelpGenCallback
? 2 : 1,
6663 MF_BYPOSITION
| MF_STRING
,
6664 IDM_HELP
, TEXT("Screen Help in &New Window"));
6665 DrawMenuBar (ghTTYWnd
);
6675 * Set the text displayed when someone tries to close the application
6679 mswin_setclosetext (char *pCloseText
)
6681 gpCloseText
= pCloseText
;
6686 * Called when upper layer is in a busy loop. Allows us to yeild to
6687 * Windows and perhaps process some events. Does not yeild control
6688 * to other applications.
6700 start
= GetTickCount ();
6702 if (mswin_debug
> 16)
6703 fprintf (mswin_debugfile
, "mswin_yeild:: Entered\n");
6705 if (PeekMessage (&msg
, NULL
, 0, 0, PM_REMOVE
)) {
6706 if (gpTTYInfo
->hAccel
== NULL
||
6707 !TranslateAccelerator (ghTTYWnd
, gpTTYInfo
->hAccel
, &msg
)) {
6708 TranslateMessage (&msg
);
6709 DispatchMessage (&msg
);
6714 if (mswin_debug
> 16)
6715 fprintf (mswin_debugfile
, "mswin_yeild:: Delay %ld msec\n",
6716 GetTickCount () - start
);
6723 * Called to see if we can process input.
6724 * We can't process input when we are in a scrolling mode.
6727 mswin_caninput (void)
6729 return (!gScrolling
&& !gMouseTracking
);
6734 * Called to see if there is a character available.
6737 mswin_charavail (void)
6745 RestoreMouseCursor();
6748 * If there are no windows messages waiting for this app, GetMessage
6749 * can take a long time. So before calling GetMessage check if
6750 * there is anything I should be doing. If there is, then only
6752 * BUT! Don't let too much time elapse between calls to GetMessage
6753 * or we'll shut out other windows.
6755 ca
= CQAvailable ();
6756 pa
= EditPasteAvailable ();
6758 start
= GetTickCount ();
6759 if (mswin_debug
> 16)
6760 fprintf (mswin_debugfile
, "%s mswin_charavail:: Entered, ca %d, pa %d\n",dtime(),ca
,pa
);
6762 if ((ca
|| pa
) && GetTickCount () < gGMLastCall
+ GM_MAX_TIME
)
6763 ma
= PeekMessage (&msg
, NULL
, 0, 0, PM_NOYIELD
| PM_REMOVE
);
6765 ma
= GetMessage (&msg
, NULL
, 0, 0);
6766 gGMLastCall
= GetTickCount ();
6769 if (gpTTYInfo
->hAccel
== NULL
||
6770 !TranslateAccelerator (ghTTYWnd
, gpTTYInfo
->hAccel
, &msg
)) {
6771 TranslateMessage (&msg
);
6772 DispatchMessage (&msg
);
6776 if (mswin_debug
> 16)
6777 fprintf (mswin_debugfile
, "%s mswin_charavail:: Delay %ld msec\n",
6778 dtime(), GetTickCount () - start
);
6781 return (pa
|| ca
|| CQAvailable ());
6786 * Call to get next character. Dispatch one message.
6797 RestoreMouseCursor();
6803 * If there are no windows messages waiting for this app, GetMessage
6804 * can take a long time. So before calling GetMessage check if
6805 * there is anything I should be doing. If there is, then only
6808 ca
= CQAvailable ();
6809 pa
= EditPasteAvailable ();
6811 if (mswin_debug
> 16) {
6812 start
= GetTickCount ();
6813 fprintf (mswin_debugfile
, "mswin_getc:: Entered, ca %d pa %d\n", ca
, pa
);
6816 if ((ca
|| pa
) && GetTickCount () < gGMLastCall
+ GM_MAX_TIME
)
6817 ma
= PeekMessage (&msg
, NULL
, 0, 0, PM_NOYIELD
| PM_REMOVE
);
6819 ma
= GetMessage (&msg
, NULL
, 0, 0);
6820 gGMLastCall
= GetTickCount ();
6823 if (gpTTYInfo
->hAccel
== NULL
||
6824 !TranslateAccelerator (ghTTYWnd
, gpTTYInfo
->hAccel
, &msg
)) {
6825 TranslateMessage (&msg
);
6826 DispatchMessage (&msg
);
6830 if (mswin_debug
> 16)
6831 fprintf (mswin_debugfile
, "mswin_getc:: Delay %ld msec\n",
6832 GetTickCount () - start
);
6838 return (EditPasteGet ());
6840 if (ca
|| CQAvailable ()) {
6842 return ((UCS
)(CQGet ()));
6850 * Like mswin_getc, but don't yield control. Returns a CTRL key values
6851 * where, for example, ctrl+c --> CTRL|'C'.
6854 mswin_getc_fast (void)
6856 RestoreMouseCursor();
6858 if (EditPasteAvailable ()) {
6860 return (EditPasteGet ());
6862 if (CQAvailable ()) {
6864 return ((UCS
)CQGet ());
6872 * Flush the character input queue.
6875 mswin_flush_input(void)
6878 * GetQueueStatus tells us if there are any input messages in the message
6879 * queue. If there are, we call mswin_getc which will retrieve the
6880 * next message (which may or may not be an input message) and process
6881 * it. We do that until all the input messages are gone.
6885 while(GetQueueStatus(QS_INPUT
))
6886 (void) mswin_getc();
6888 /* And we clear Pine's character input queue, too. */
6894 * ibmmove - Move cursor to...
6897 mswin_move (int row
, int column
)
6901 if (row
< 0 || row
>= gpTTYInfo
->actNRow
)
6903 if (column
< 0 || column
>= gpTTYInfo
->actNColumn
)
6905 gpTTYInfo
->nRow
= (CORD
)row
;
6906 gpTTYInfo
->nColumn
= (CORD
)column
;
6907 MoveTTYCursor (ghTTYWnd
);
6913 mswin_getpos (int *row
, int *column
)
6916 if (row
== NULL
|| column
== NULL
)
6918 *row
= gpTTYInfo
->nRow
;
6919 *column
= gpTTYInfo
->nColumn
;
6925 mswin_getscreensize (int *row
, int *column
)
6927 if (row
== NULL
|| column
== NULL
)
6929 *row
= gpTTYInfo
->actNRow
;
6930 *column
= gpTTYInfo
->actNColumn
;
6932 if (mswin_debug
>= 5)
6933 fprintf (mswin_debugfile
, "mswin_getscreensize::: reported size %d, %d\n",
6937 *column
= MIN(*column
, NLINE
-1);
6946 if (!gpTTYInfo
->fMinimized
)
6947 ShowWindow(ghTTYWnd
, SW_MINIMIZE
);
6952 mswin_showcursor (int show
)
6954 int was_shown
= gpTTYInfo
->fCursorOn
;
6957 /* if the cursor was not already show, show it now. */
6959 gpTTYInfo
->fCursorOn
= TRUE
;
6964 /* If the cursor is shown, hide it. */
6966 gpTTYInfo
->fCursorOn
= FALSE
;
6976 mswin_showcaret (int show
)
6978 int was_shown
= gpTTYInfo
->fCaretOn
;
6981 /* if the caret was not already show, show it now. */
6983 gpTTYInfo
->fCaretOn
= TRUE
;
6984 ShowCaret(ghTTYWnd
);
6988 /* If the caret is shown, hide it. */
6990 gpTTYInfo
->fCaretOn
= FALSE
;
6991 HideCaret(ghTTYWnd
);
7000 mswin_puts (char *utf8_str
)
7006 if (utf8_str
== NULL
)
7008 if(!(lptstr_str
= utf8_to_lptstr(utf8_str
)))
7010 strLen
= (int)_tcslen (lptstr_str
);
7012 WriteTTYText (ghTTYWnd
, lptstr_str
, strLen
);
7014 fs_give((void **) &lptstr_str
);
7020 mswin_puts_n (char *utf8_str
, int n
)
7022 LPTSTR lptstr_str
, lptstr_p
;
7025 if (utf8_str
== NULL
)
7027 lptstr_str
= utf8_to_lptstr(utf8_str
);
7028 if(n
< _tcslen(lptstr_str
))
7029 lptstr_str
[n
] = '\0';
7030 for (lptstr_p
= lptstr_str
; n
> 0 && *lptstr_p
; n
--, lptstr_p
++)
7032 if (lptstr_p
> lptstr_str
)
7033 WriteTTYText (ghTTYWnd
, lptstr_str
, (int)(lptstr_p
- lptstr_str
));
7035 fs_give((void **) &lptstr_str
);
7041 mswin_putblock (char *utf8_str
, int strLen
)
7046 if (utf8_str
== NULL
)
7048 lptstr_str
= utf8_to_lptstr(utf8_str
);
7050 WriteTTYText (ghTTYWnd
, lptstr_str
, strLen
);
7051 fs_give((void **) &lptstr_str
);
7057 * mswin_putc - put a character at the current position in the
7061 mswin_putc (UCS ucs
)
7063 TCHAR cc
= (TCHAR
)ucs
;
7064 if(ucs
== ARABIC_LRM
|| ucs
== ARABIC_RLM
){
7066 WriteTTYBlock (ghTTYWnd
, &cc
, 1);
7069 if (ucs
>= (UCS
)(' ')) {
7070 /* Not carriage control. */
7071 gpTTYInfo
->writeAccum
[gpTTYInfo
->writeAccumCount
++] = (TCHAR
)ucs
;
7072 if (gpTTYInfo
->writeAccumCount
== WRITE_ACCUM_SIZE
)
7076 /* Carriage control. Need to flush write accumulator and
7077 * write this char. */
7079 WriteTTYBlock (ghTTYWnd
, &cc
, 1);
7086 * ibmoutc - output a single character with the right attributes, but
7087 * don't advance the cursor
7105 /* Do nothing for these screen motion characters. */
7110 /* Paint character to screen. */
7111 offset
= (gpTTYInfo
->nRow
* gpTTYInfo
->actNColumn
) + gpTTYInfo
->nColumn
;
7112 gpTTYInfo
->pScreen
[offset
] = c
;
7113 gpTTYInfo
->pCellWidth
[offset
] = wcellwidth((UCS
)c
) * gpTTYInfo
->xChar
;
7114 gpTTYInfo
->pAttrib
[offset
] = gpTTYInfo
->curAttrib
;
7116 /* Invalidate rectange covering singel character. */
7117 rect
.left
= (gpTTYInfo
->nColumn
* gpTTYInfo
->xChar
) +
7119 rect
.right
= rect
.left
+ gpTTYInfo
->xChar
;
7120 rect
.top
= (gpTTYInfo
->nRow
* gpTTYInfo
->yChar
) +
7122 rect
.bottom
= rect
.top
+ gpTTYInfo
->yChar
;
7123 gpTTYInfo
->screenDirty
= TRUE
;
7124 InvalidateRect (ghTTYWnd
, &rect
, FALSE
);
7131 * ibmrev - change reverse video state
7134 mswin_rev (int state
)
7136 int curState
= (gpTTYInfo
->curAttrib
.style
& CHAR_ATTR_REV
) != 0;
7138 if (state
!= curState
){
7141 gpTTYInfo
->curAttrib
.style
|= CHAR_ATTR_REV
;
7145 gpTTYInfo
->curAttrib
.style
&= ~CHAR_ATTR_REV
;
7146 pico_set_normal_color();
7155 * Get current reverse video state.
7158 mswin_getrevstate (void)
7160 return ((gpTTYInfo
->curAttrib
.style
& CHAR_ATTR_REV
) != 0);
7165 * ibmrev - change reverse video state
7168 mswin_bold (int state
)
7170 int curState
= (gpTTYInfo
->curAttrib
.style
& CHAR_ATTR_BOLD
) != 0;
7172 if (state
!= curState
){
7175 gpTTYInfo
->curAttrib
.style
|= CHAR_ATTR_BOLD
;
7177 gpTTYInfo
->curAttrib
.style
&= ~CHAR_ATTR_BOLD
;
7185 * ibmrev - change reverse video state
7188 mswin_uline (int state
)
7190 int curState
= (gpTTYInfo
->curAttrib
.style
& CHAR_ATTR_ULINE
) != 0;
7192 if (state
!= curState
){
7195 gpTTYInfo
->curAttrib
.style
|= CHAR_ATTR_ULINE
;
7197 gpTTYInfo
->curAttrib
.style
&= ~CHAR_ATTR_ULINE
;
7205 * ibmeeol - erase to the end of the line
7218 /* From current position to end of line. */
7219 length
= gpTTYInfo
->actNColumn
- gpTTYInfo
->nColumn
;
7221 cStart
= gpTTYInfo
->pScreen
+ (gpTTYInfo
->nRow
* gpTTYInfo
->actNColumn
)
7222 + gpTTYInfo
->nColumn
;
7223 cwStart
= gpTTYInfo
->pCellWidth
+ (gpTTYInfo
->nRow
* gpTTYInfo
->actNColumn
)
7224 + gpTTYInfo
->nColumn
;
7225 for(i
= 0; i
< length
; i
++){
7226 cStart
[i
] = (TCHAR
)(' ');
7227 cwStart
[i
] = gpTTYInfo
->xChar
;
7230 aStart
= gpTTYInfo
->pAttrib
7231 + (gpTTYInfo
->nRow
* gpTTYInfo
->actNColumn
)
7232 + gpTTYInfo
->nColumn
;
7233 for(; length
> 0; length
--, aStart
++){
7234 aStart
->style
= CHAR_ATTR_NORM
;
7235 aStart
->rgbFG
= gpTTYInfo
->curAttrib
.rgbFG
;
7236 aStart
->rgbBG
= gpTTYInfo
->curAttrib
.rgbBG
;
7239 rect
.left
= (gpTTYInfo
->nColumn
* gpTTYInfo
->xChar
) +
7241 rect
.right
= gpTTYInfo
->xSize
;
7242 rect
.top
= (gpTTYInfo
->nRow
* gpTTYInfo
->yChar
) +
7244 rect
.bottom
= rect
.top
+ gpTTYInfo
->yChar
;
7245 gpTTYInfo
->screenDirty
= TRUE
;
7246 InvalidateRect (ghTTYWnd
, &rect
, FALSE
);
7253 * ibmeeop - clear from cursor to end of page
7265 /* From current position to end of screen. */
7267 cStart
= gpTTYInfo
->pScreen
+ (gpTTYInfo
->nRow
* gpTTYInfo
->actNColumn
)
7268 + gpTTYInfo
->nColumn
;
7269 cwStart
= gpTTYInfo
->pCellWidth
+ (gpTTYInfo
->nRow
* gpTTYInfo
->actNColumn
)
7270 + gpTTYInfo
->nColumn
;
7271 length
= (long)((gpTTYInfo
->pScreen
7272 + (gpTTYInfo
->actNColumn
* gpTTYInfo
->actNRow
))
7274 for(i
= 0; i
< length
; i
++){
7275 cStart
[i
] = (TCHAR
)(' ');
7276 cwStart
[i
] = gpTTYInfo
->xChar
;
7279 aStart
= gpTTYInfo
->pAttrib
7280 + (gpTTYInfo
->nRow
* gpTTYInfo
->actNColumn
)
7281 + gpTTYInfo
->nColumn
;
7283 for(; length
-- > 0; aStart
++){
7284 aStart
->style
= CHAR_ATTR_NORM
;
7285 aStart
->rgbFG
= gpTTYInfo
->curAttrib
.rgbFG
;
7286 aStart
->rgbBG
= gpTTYInfo
->curAttrib
.rgbBG
;
7289 /* Invalidate a rectangle that includes all of the current line down
7290 * to the bottom of the window. */
7292 rect
.right
= gpTTYInfo
->xSize
;
7293 rect
.top
= (gpTTYInfo
->nRow
* gpTTYInfo
->yChar
) +
7295 rect
.bottom
= gpTTYInfo
->ySize
;
7296 gpTTYInfo
->screenDirty
= TRUE
;
7297 InvalidateRect (ghTTYWnd
, &rect
, FALSE
);
7304 * ibmbeep - system beep...
7309 MessageBeep (MB_OK
);
7315 * pause - wait in function for specified number of seconds.
7318 mswin_pause (int seconds
)
7322 stoptime
= GetTickCount () + (DWORD
) seconds
* 1000;
7323 while (stoptime
> GetTickCount ())
7329 * ibmflush - Flush output to screen.
7337 * Flush cached changes, then update the window.
7340 UpdateWindow (ghTTYWnd
);
7347 * A replacement for fflush
7348 * relies on #define fflush mswin_fflush
7352 mswin_fflush (FILE *f
)
7368 mswin_setcursor (int newcursor
)
7373 case MSWIN_CURSOR_BUSY
:
7374 hNewCursor
= ghCursorBusy
;
7375 mswin_showcursor(TRUE
);
7378 case MSWIN_CURSOR_IBEAM
:
7379 hNewCursor
= ghCursorIBeam
;
7382 case MSWIN_CURSOR_HAND
:
7383 if(hNewCursor
= ghCursorHand
)
7385 /* ELSE fall thru to normal cursor */
7387 case MSWIN_CURSOR_ARROW
:
7389 hNewCursor
= ghCursorArrow
;
7393 /* If new cursor requested, select it. */
7394 if (ghCursorCurrent
!= hNewCursor
)
7395 SetCursor (ghCursorCurrent
= hNewCursor
);
7400 RestoreMouseCursor()
7402 if(ghCursorCurrent
== ghCursorBusy
)
7403 mswin_setcursor(MSWIN_CURSOR_ARROW
);
7408 * Display message in windows dialog box.
7411 mswin_messagebox (char *msg_utf8
, int err
)
7417 msg_lptstr
= utf8_to_lptstr(msg_utf8
);
7418 MessageBox (NULL
, msg_lptstr
, gszAppName
,
7419 MB_OK
| ((err
) ? MB_ICONSTOP
: MB_ICONINFORMATION
));
7420 fs_give((void **) &msg_lptstr
);
7425 * Signals whether or not Paste should be turned on in the
7429 mswin_allowpaste (int on
)
7431 static short stackp
= 0;
7432 static unsigned long stack
= 0L;
7435 case MSWIN_PASTE_DISABLE
:
7436 if(stackp
){ /* previous state? */
7437 if((stackp
-= 2) < 0)
7440 gPasteEnabled
= ((stack
>> stackp
) & 0x03);
7443 gPasteEnabled
= MSWIN_PASTE_DISABLE
;
7447 case MSWIN_PASTE_FULL
:
7448 case MSWIN_PASTE_LINE
:
7449 if(gPasteEnabled
){ /* current state? */
7450 stack
|= ((unsigned long) gPasteEnabled
<< stackp
);
7459 UpdateAccelerators(ghTTYWnd
);
7465 * Signals whether or not Copy/Cut should be turned on in the
7469 mswin_allowcopy (getc_t copyfunc
)
7471 gCopyCutFunction
= copyfunc
;
7472 gAllowCopy
= (copyfunc
!= NULL
);
7474 UpdateAccelerators(ghTTYWnd
);
7480 * Signals whether or not Copy/Cut should be turned on in the
7484 mswin_allowcopycut (getc_t copyfunc
)
7486 gCopyCutFunction
= copyfunc
;
7487 gAllowCopy
= gAllowCut
= (copyfunc
!= NULL
);
7489 UpdateAccelerators(ghTTYWnd
);
7495 * Replace the clipboard's contents with the given string
7498 mswin_addclipboard(char *s
)
7504 if(s
&& (sSize
= strlen(s
))){
7505 if (OpenClipboard (ghTTYWnd
)) { /* ...and we get the CB. */
7506 if (EmptyClipboard ()
7507 && (hCB
= GlobalAlloc (GMEM_MOVEABLE
, sSize
+2))){
7508 pCB
= GlobalLock (hCB
);
7509 memcpy (pCB
, s
, sSize
);
7510 pCB
[sSize
] = '\0'; /* tie it off */
7514 if (SetClipboardData (CF_TEXT
, hCB
) == NULL
)
7515 /* Failed! Free the data. */
7526 * Signals if the upper layer wants to track the mouse.
7529 mswin_allowmousetrack (int b
)
7531 gAllowMouseTrack
= b
;
7539 * register's callback to warn
7542 mswin_mousetrackcallback(cbarg_t cbfunc
)
7544 if(!(gMouseTrackCallback
= cbfunc
))
7545 mswin_setcursor (MSWIN_CURSOR_ARROW
);
7550 * Add text to the new mail icon.
7551 * Nothing done in win 3.1 (consider changing the program name?)
7552 * For win95 we add some tool tip text to the tray icon.
7555 mswin_newmailtext (char *t_utf8
)
7560 * If we're given text, then blip the icon to let the user know.
7561 * (NOTE: the new shell also gets an updated tooltip.)
7562 * Otherwise, we're being asked to resume our normal state...
7566 * Change the appearance of minimized icon so user knows there's new
7567 * mail waiting for them. On win 3.1 systems we redraw the icon.
7568 * on win95 systems we update the icon in the task bar,
7569 * and possibly udpate the small icon in the taskbar tool tray.
7571 t_lptstr
= utf8_to_lptstr(t_utf8
);
7572 UpdateTrayIcon(NIM_MODIFY
, ghNewMailIcon
, t_lptstr
);
7573 fs_give((void **) &t_lptstr
);
7574 PostMessage(ghTTYWnd
,WM_SETICON
,ICON_BIG
,(LPARAM
) ghNewMailIcon
);
7575 PostMessage(ghTTYWnd
,WM_SETICON
,ICON_SMALL
,(LPARAM
) ghNewMailIcon
);
7577 gpTTYInfo
->fNewMailIcon
= TRUE
;
7579 else if(gpTTYInfo
->fNewMailIcon
) {
7580 UpdateTrayIcon(NIM_MODIFY
, ghNormalIcon
, TEXT("Alpine"));
7581 PostMessage(ghTTYWnd
,WM_SETICON
,ICON_BIG
,(LPARAM
) ghNormalIcon
);
7582 PostMessage(ghTTYWnd
,WM_SETICON
,ICON_SMALL
,(LPARAM
) ghNormalIcon
);
7584 gpTTYInfo
->fNewMailIcon
= FALSE
;
7590 mswin_mclosedtext (char *t_utf8
)
7594 if(t_utf8
&& gpTTYInfo
->fMClosedIcon
== FALSE
){
7596 * Change the appearance of minimized icon so user knows
7597 * the mailbox closed.
7599 t_lptstr
= utf8_to_lptstr(t_utf8
);
7600 UpdateTrayIcon(NIM_MODIFY
, ghMClosedIcon
, t_lptstr
);
7601 fs_give((void **) &t_lptstr
);
7602 PostMessage(ghTTYWnd
,WM_SETICON
,ICON_BIG
,(LPARAM
) ghMClosedIcon
);
7603 PostMessage(ghTTYWnd
,WM_SETICON
,ICON_SMALL
,(LPARAM
) ghMClosedIcon
);
7605 gpTTYInfo
->fMClosedIcon
= TRUE
;
7607 else if(t_utf8
== NULL
&& gpTTYInfo
->fMClosedIcon
) {
7608 /* only go from yellow to green */
7609 UpdateTrayIcon(NIM_MODIFY
, ghNormalIcon
, TEXT("Alpine"));
7610 PostMessage(ghTTYWnd
,WM_SETICON
,ICON_BIG
,(LPARAM
) ghNormalIcon
);
7611 PostMessage(ghTTYWnd
,WM_SETICON
,ICON_SMALL
,(LPARAM
) ghNormalIcon
);
7613 gpTTYInfo
->fMClosedIcon
= FALSE
;
7618 mswin_trayicon(int show
)
7621 if(!gpTTYInfo
->fTrayIcon
){
7622 UpdateTrayIcon(NIM_ADD
, ghNormalIcon
, TEXT("Alpine"));
7623 gpTTYInfo
->fTrayIcon
= TRUE
;
7627 if(gpTTYInfo
->fTrayIcon
){
7628 UpdateTrayIcon(NIM_DELETE
, 0, NULL
);
7629 gpTTYInfo
->fTrayIcon
= FALSE
;
7636 UpdateTrayIcon(DWORD dwMsg
, HICON hIcon
, LPTSTR tip
)
7640 nt
.cbSize
= sizeof (nt
);
7642 nt
.uID
= TASKBAR_ICON_NEWMAIL
;
7648 case NIM_ADD
: /* send msg to add icon to tray */
7649 nt
.uFlags
= NIF_ICON
| NIF_MESSAGE
| NIF_TIP
;
7650 nt
.uCallbackMessage
= TASKBAR_ICON_MESSAGE
;
7653 _tcsncpy (nt
.szTip
, tip
, 63);
7654 nt
.szTip
[63] = '\0';
7661 case NIM_MODIFY
: /* send msg to modify icon in tray */
7662 nt
.uFlags
= NIF_ICON
| NIF_TIP
;
7664 _tcsncpy (nt
.szTip
, tip
, 63);
7665 nt
.szTip
[63] = '\0';
7676 Shell_NotifyIcon (dwMsg
, &nt
);
7681 /*---------------------------------------------------------------------------
7683 * Client level menu item stuff.
7685 * These are menu items that activate commands in the "client" program.
7686 * Generally, the client calls us to tell us which menu items are active
7687 * and what key stroke they generate. When such an item is selected it's
7688 * key stroke is injected into the character queue as if it was typed by
7691 *-------------------------------------------------------------------------*/
7694 * Clear active status of all "menu items".
7697 mswin_menuitemclear (void)
7703 for (i
= 0; i
< KS_COUNT
; ++i
) {
7704 gpTTYInfo
->menuItems
[i
].miActive
= FALSE
;
7705 if (gpTTYInfo
->toolBarSize
> 0) {
7706 hWnd
= GetDlgItem(gpTTYInfo
->hTBWnd
, i
+ KS_RANGESTART
);
7708 EnableWindow(hWnd
, FALSE
);
7712 gpTTYInfo
->menuItemsCurrent
= FALSE
;
7713 gpTTYInfo
->menuItemsIndex
= 1;
7714 for(i
= 0; i
< KS_COUNT
; i
++)
7715 gpTTYInfo
->menuItems
[i
].miIndex
= 0;
7720 * Add an item to the cmdmenu
7723 mswin_menuitemadd (UCS key
, char *label
, int menuitem
, int flags
)
7728 if (menuitem
>= KS_RANGESTART
&& menuitem
<= KS_RANGEEND
) {
7730 gpTTYInfo
->menuItemsCurrent
= FALSE
;
7732 i
= menuitem
- KS_RANGESTART
;
7733 gpTTYInfo
->menuItems
[i
].miActive
= TRUE
;
7734 gpTTYInfo
->menuItems
[i
].miKey
= key
;
7735 if(!gpTTYInfo
->menuItems
[i
].miIndex
){
7736 gpTTYInfo
->menuItems
[i
].miLabel
= label
;
7737 gpTTYInfo
->menuItems
[i
].miIndex
= gpTTYInfo
->menuItemsIndex
++;
7740 if (gpTTYInfo
->toolBarSize
> 0) {
7741 hWnd
= GetDlgItem(gpTTYInfo
->hTBWnd
, menuitem
);
7743 EnableWindow(hWnd
, TRUE
);
7750 * Called when a menu command arrives with an unknown ID. If it is
7751 * within the range of the additional menu items, insert the
7752 * corresponding character into the char input queue.
7755 ProcessMenuItem (HWND hWnd
, WPARAM wParam
)
7760 pTTYInfo
= (PTTYINFO
) MyGetWindowLongPtr (hWnd
, GWL_PTTYINFO
);
7761 if (pTTYInfo
== NULL
)
7765 if (wParam
>= KS_RANGESTART
&& wParam
<= KS_RANGEEND
) {
7766 i
= (int)(wParam
- KS_RANGESTART
);
7767 if (pTTYInfo
->menuItems
[i
].miActive
)
7768 CQAdd (pTTYInfo
->menuItems
[i
].miKey
, 0);
7774 * Called to set a new menu.
7777 mswin_setwindowmenu (int menu
)
7784 oldmenu
= gpTTYInfo
->curWinMenu
;
7785 holdmenu
= GetMenu (ghTTYWnd
);
7786 if (gpTTYInfo
->curWinMenu
!= menu
) {
7788 hmenu
= LoadMenu (ghInstance
, MAKEINTRESOURCE (menu
));
7789 if (hmenu
!= NULL
) {
7790 if (SetMenu (ghTTYWnd
, hmenu
) != 0) {
7791 DestroyMenu (holdmenu
);
7792 gfHelpMenu
= gfHelpGenMenu
= FALSE
;
7793 gpTTYInfo
->curWinMenu
= menu
;
7797 if(menu
== MENU_DEFAULT
){
7798 TBSwap (ghTTYWnd
, IDD_TOOLBAR
);
7800 (void) MSWHelpSetMenu(hmenu
);
7803 TBSwap (ghTTYWnd
, IDD_COMPOSER_TB
);
7811 /*---------------------------------------------------------------------------
7815 *-------------------------------------------------------------------------*/
7820 LOCAL HDC P_PrintDC
; /* Printer device context. */
7821 LOCAL
int P_PageRows
; /* Number of rows we put on a page. */
7822 LOCAL
int P_PageColumns
; /* Number of columns we put on a page. */
7823 LOCAL
int P_RowHeight
; /* Hight of a row in printer pixels. */
7824 LOCAL
int P_CurRow
; /* Current row, starting at zero */
7825 LOCAL
int P_CurCol
; /* Current col, starting at zero. */
7826 LOCAL
int P_TopOffset
; /* Top Margin offset, in pixels. */
7827 LOCAL
int P_LeftOffset
; /* Top Margin offset, in pixels. */
7828 LOCAL HFONT P_hFont
; /* Handle to printing font. */
7829 LPTSTR P_LineText
; /* Pointer to line buffer. */
7835 * Define the margin as number of lines at top and bottom of page.
7836 * (might be better to define as a percent of verticle page size)
7838 #define VERTICLE_MARGIN 3 /* lines at top and bottom of page. */
7839 #define HORIZONTAL_MARGIN 1 /* margine at left & right in chars */
7842 * Several errors that can be reported.
7844 #define PE_DIALOG_FAILED 1
7845 #define PE_USER_CANCEL 2
7846 #define PE_CANT_START_DOC 3
7847 #define PE_CANT_FINISH_DOC 4
7848 #define PE_OUT_OF_MEMORY 5
7849 #define PE_GENERAL_ERROR 6
7850 #define PE_OUT_OF_DISK 7
7851 #define PE_PRINTER_NOT_FOUND 8
7852 #define PE_PINE_INTERNAL 9
7853 #define PE_FONT_FAILED 10
7856 LOCAL
struct pe_error_message
{
7858 char *error_message
;
7859 } P_ErrorMessages
[] = {
7860 { PE_DIALOG_FAILED
, "Print Dialog Failed"},
7861 { PE_USER_CANCEL
, "User canceled" },
7862 { PE_CANT_START_DOC
, "Can't start document" },
7863 { PE_OUT_OF_MEMORY
, "Out of memory" },
7864 { PE_CANT_FINISH_DOC
, "Can't finish document" },
7865 { PE_OUT_OF_MEMORY
, "Out of memory" },
7866 { PE_OUT_OF_DISK
, "Out of disk space" },
7867 { PE_PRINTER_NOT_FOUND
, "Printer not found" },
7868 { PE_PINE_INTERNAL
, "Pine internal error" },
7869 { PE_FONT_FAILED
, "Failed to create font" },
7875 * Send text in the line buffer to the printer.
7876 * Advance to next page if necessary.
7879 _print_send_line (void)
7885 TextOut (P_PrintDC
, P_LeftOffset
,
7886 P_TopOffset
+ (P_CurRow
* P_RowHeight
),
7887 P_LineText
, P_CurCol
);
7889 if (++P_CurRow
>= P_PageRows
)
7890 status
= _print_send_page ();
7901 _print_send_page (void)
7905 if((status
= EndPage (P_PrintDC
)) > 0){
7907 if((status
= StartPage (P_PrintDC
)) > 0){
7908 SelectObject (P_PrintDC
, P_hFont
);
7915 return(PE_GENERAL_ERROR
);
7918 case SP_USERABORT
: return (PE_USER_CANCEL
);
7919 case SP_OUTOFDISK
: return (PE_OUT_OF_DISK
);
7920 case SP_OUTOFMEMORY
: return (PE_OUT_OF_MEMORY
);
7922 case SP_ERROR
: break;
7925 return (PE_GENERAL_ERROR
);
7931 * Map errors reported to my own error set.
7934 _print_map_dlg_error (DWORD error
)
7937 case 0: return (PE_USER_CANCEL
);
7938 case CDERR_MEMALLOCFAILURE
:
7939 case CDERR_MEMLOCKFAILURE
:
7940 return (PE_OUT_OF_MEMORY
);
7941 case PDERR_PRINTERNOTFOUND
:
7942 case PDERR_NODEVICES
:
7943 return (PE_PRINTER_NOT_FOUND
);
7944 case CDERR_STRUCTSIZE
:
7945 return (PE_PINE_INTERNAL
);
7947 return (PE_GENERAL_ERROR
);
7953 * This is used for converting from UTF-8 to UCS and is
7954 * global so that mswin_print_ready can initialize it.
7956 static CBUF_S print_cb
;
7959 * Get the printer ready. Returns ZERO for success, or an error code that
7960 * can be passed to mswin_print_error() to get a text message.
7963 mswin_print_ready(WINHAND hWnd
, LPTSTR docDesc
)
7969 int fontSize
; /* Size in Points. */
7970 int ppi
; /* Pixels per inch in device. */
7980 print_cb
.cbufp
= print_cb
.cbuf
;
7983 * Show print dialog.
7985 memset(&pd
, 0, sizeof(PRINTDLG
));
7986 pd
.lStructSize
= sizeof (PRINTDLG
);
7987 pd
.hwndOwner
= (hWnd
? (HWND
) hWnd
: ghTTYWnd
);
7989 pd
.hDevNames
= NULL
;
7990 pd
.Flags
= PD_ALLPAGES
| PD_NOSELECTION
| PD_NOPAGENUMS
|
7991 PD_HIDEPRINTTOFILE
| PD_RETURNDC
;
7993 if(PrintDlg (&pd
) == 0)
7994 return(_print_map_dlg_error (CommDlgExtendedError()));
7997 * Returns the device name which we could use to remember what printer
7998 * they selected. But instead, we just toss them.
8001 GlobalFree (pd
.hDevNames
);
8003 GlobalFree (pd
.hDevMode
);
8006 * Get the device drawing context.
8007 * (does PringDlg() ever return success but fail to return a DC?)
8012 status
= PE_DIALOG_FAILED
;
8019 memset(&di
, 0, sizeof (DOCINFO
));
8020 di
.cbSize
= sizeof (DOCINFO
);
8021 di
.lpszDocName
= docDesc
; /* This appears in the print manager*/
8022 di
.lpszOutput
= NULL
; /* Could suply a file name to print
8024 if(StartDoc(P_PrintDC
, &di
) <= 0) {
8026 status
= PE_CANT_START_DOC
;
8027 DeleteDC (P_PrintDC
);
8033 * Printer font is either same as window font, or is it's own
8036 if (gPrintFontSameAs
) {
8039 * Get the current font size in points, then create a new font
8040 * of same size for printer. Do the calculation using the actual
8041 * screen resolution instead of the logical resolution so that
8042 * we get pretty close to the same font size on the printer
8043 * as we see on the screen.
8045 hDC
= GetDC (ghTTYWnd
); /* Temp screen DC. */
8046 ppi
= (int) ((float)GetDeviceCaps (hDC
, VERTRES
) /
8047 ((float) GetDeviceCaps (hDC
, VERTSIZE
) / 25.3636));
8049 if (mswin_debug
>= 8) {
8050 fprintf (mswin_debugfile
, "mswin_print_ready: Screen res %d ppi, font height %d pixels\n",
8051 ppi
, -gpTTYInfo
->lfTTYFont
.lfHeight
);
8052 fprintf (mswin_debugfile
, " Screen height %d pixel, %d mm\n",
8053 GetDeviceCaps (hDC
, VERTRES
), GetDeviceCaps (hDC
, VERTSIZE
));
8056 ReleaseDC (ghTTYWnd
, hDC
);
8058 /* Convert from screen pixels to points. */
8059 fontSize
= MulDiv (-gpTTYInfo
->lfTTYFont
.lfHeight
, 72, ppi
);
8060 ++fontSize
; /* Fudge a little. */
8063 /* Get printer resolution and convert form points to printer pixels. */
8064 ppi
= GetDeviceCaps (P_PrintDC
, LOGPIXELSY
);
8065 newFont
.lfHeight
= -MulDiv (fontSize
, ppi
, 72);
8066 _tcsncpy(newFont
.lfFaceName
, gpTTYInfo
->lfTTYFont
.lfFaceName
, LF_FACESIZE
);
8067 newFont
.lfFaceName
[LF_FACESIZE
-1] = 0;
8068 newFont
.lfItalic
= gpTTYInfo
->lfTTYFont
.lfItalic
;
8069 newFont
.lfWeight
= gpTTYInfo
->lfTTYFont
.lfWeight
;
8070 newFont
.lfCharSet
= gpTTYInfo
->lfTTYFont
.lfCharSet
;
8074 if (mswin_debug
>= 8) {
8075 fprintf (mswin_debugfile
, " font Size %d points\n",
8077 fprintf (mswin_debugfile
, " printer res %d ppi, font height %d pixels\n",
8078 ppi
, -newFont
.lfHeight
);
8079 fprintf (mswin_debugfile
, " paper height %d pixel, %d mm\n",
8080 GetDeviceCaps (P_PrintDC
, VERTRES
),
8081 GetDeviceCaps (P_PrintDC
, VERTSIZE
));
8086 ppi
= GetDeviceCaps (P_PrintDC
, LOGPIXELSY
);
8087 newFont
.lfHeight
= -MulDiv (gPrintFontSize
, ppi
, 72);
8088 _tcsncpy(newFont
.lfFaceName
, gPrintFontName
, LF_FACESIZE
);
8089 newFont
.lfFaceName
[LF_FACESIZE
-1] = 0;
8090 newFont
.lfWeight
= 0;
8091 if(_tcsstr(gPrintFontStyle
, TEXT("bold")))
8092 newFont
.lfWeight
= FW_BOLD
;
8094 newFont
.lfItalic
= 0;
8095 if(_tcsstr(gPrintFontStyle
, TEXT("italic")))
8096 newFont
.lfItalic
= 1;
8098 newFont
.lfCharSet
= mswin_string2charsetid(gPrintFontCharSet
);
8102 /* Fill out rest of font description and request font. */
8103 newFont
.lfWidth
= 0;
8104 newFont
.lfEscapement
= 0;
8105 newFont
.lfOrientation
= 0;
8106 newFont
.lfUnderline
= 0;
8107 newFont
.lfStrikeOut
= 0;
8108 newFont
.lfOutPrecision
= OUT_DEFAULT_PRECIS
;
8109 newFont
.lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
8110 newFont
.lfQuality
= DEFAULT_QUALITY
;
8111 newFont
.lfPitchAndFamily
= FIXED_PITCH
;
8112 P_hFont
= CreateFontIndirect (&newFont
);
8113 if (P_hFont
== NULL
) {
8114 status
= PE_FONT_FAILED
;
8115 DeleteDC (P_PrintDC
);
8122 * Must select font for each page or it returns to default.
8123 * Windows seems good about maping selected font to a font that
8124 * will actually print on the printer.
8126 StartPage (P_PrintDC
);
8127 oldFont
= SelectObject (P_PrintDC
, P_hFont
);
8131 * Find out about the font we got and set up page size and margins.
8132 * This assumes all pages are the same size - which seems reasonable.
8134 GetTextMetrics (P_PrintDC
, &tm
);
8135 xChar
= tm
.tmAveCharWidth
;
8136 P_RowHeight
= tm
.tmHeight
+ tm
.tmExternalLeading
;
8138 /* HORZRES and VERTRES report size of page in printer pixels. */
8139 P_PageColumns
= GetDeviceCaps (P_PrintDC
, HORZRES
) / xChar
;
8140 P_PageRows
= GetDeviceCaps (P_PrintDC
, VERTRES
) / P_RowHeight
;
8142 /* We allow a margin at top and bottom measured in text rows. */
8143 P_PageRows
-= VERTICLE_MARGIN
* 2;
8144 P_TopOffset
= VERTICLE_MARGIN
* P_RowHeight
;
8146 /* And allow for a left and right margine measured in characters. */
8147 P_PageColumns
-= HORIZONTAL_MARGIN
* 2;
8148 P_LeftOffset
= HORIZONTAL_MARGIN
* xChar
;
8150 P_CurRow
= 0; /* Start counting at row 0. */
8151 P_CurCol
= 0; /* At character 0. */
8152 P_LineText
= (LPTSTR
) MemAlloc((P_PageColumns
+ 1) * sizeof(TCHAR
));
8153 if(P_LineText
== NULL
){
8154 if(EndDoc (P_PrintDC
) <= 0)
8157 DeleteObject (P_hFont
);
8159 DeleteDC (P_PrintDC
);
8161 status
= PE_OUT_OF_MEMORY
;
8172 * Called when printing is done.
8173 * xxx what happens if there is an error? Will this get called?
8176 mswin_print_done(void)
8178 if(P_PrintDC
!= NULL
){
8179 if(P_LineText
!= NULL
)
8180 MemFree((void *) P_LineText
);
8182 if(EndPage (P_PrintDC
) <= 0 || EndDoc (P_PrintDC
) <= 0)
8185 DeleteObject(P_hFont
);
8187 DeleteDC(P_PrintDC
);
8196 * Return ponter to a text string that describes the erorr.
8199 mswin_print_error(int error_code
)
8203 for(i
= 0; P_ErrorMessages
[i
].error_message
!= NULL
; ++i
)
8204 if(P_ErrorMessages
[i
].error_code
== error_code
)
8205 return(P_ErrorMessages
[i
].error_message
);
8207 return("(Unknown error)");
8212 * Add a single character to the current line.
8213 * Only handles CRLF carrage control.
8216 mswin_print_char(TCHAR c
)
8223 return(_print_send_line());
8227 if(P_CurCol
== P_PageColumns
)
8228 return(_print_send_line());
8230 *(P_LineText
+ P_CurCol
++) = ' ';
8232 while(P_CurCol
% PRINT_TAB_SIZE
!= 0);
8236 if(P_CurCol
== P_PageColumns
){
8239 if((status
= _print_send_line()) != 0)
8243 *(P_LineText
+ P_CurCol
++) = c
;
8250 mswin_print_char_utf8(int c
)
8256 if(utf8_to_ucs4_oneatatime(c
, &print_cb
, &ucs
, NULL
)){
8257 /* bogus conversion ignores UTF-16 */
8259 ret
= mswin_print_char(tc
);
8267 * Send a string to the printer.
8270 mswin_print_text(LPTSTR text
)
8276 if((status
= mswin_print_char(*(text
++))) != 0)
8284 mswin_print_text_utf8(char *text_utf8
)
8290 text_lpt
= utf8_to_lptstr(text_utf8
);
8292 ret
= mswin_print_text(text_lpt
);
8293 fs_give((void **) &text_lpt
);
8301 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8303 * File dialog boxes.
8305 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
8307 LOCAL TCHAR gHomeDir
[PATH_MAX
];
8308 LOCAL TCHAR gLastDir
[PATH_MAX
];
8311 * Keep track of the last dir visited. Most of the time pine just passes us
8312 * the "home directory", which usually is not where the user wants to start.
8313 * Assume that the first time we are called we are being passed the home
8317 FillInitialDir (LPCTSTR
*iDir
, LPTSTR targDir
)
8319 if (_tcslen (gHomeDir
) == 0) {
8320 _tcscpy (gHomeDir
, targDir
);
8323 else if (_tcscmp (gHomeDir
, targDir
) == 0 && *gLastDir
)
8332 * Display a save file dialog box.
8334 * dir_utf8 > directory to start search in
8335 * < directory finished in.
8336 * fName_utf8 < Name of file selected
8337 * nMaxDName length of dir_utf8
8338 * nMaxFName length of fName_utf8.
8340 * Possible return values:
8341 * 0 no file selected
8343 * -1 some sort of error
8346 mswin_savefile(char *dir_utf8
, int nMaxDName
, char *fName_utf8
, int nMaxFName
)
8349 TCHAR filters
[128], moniker
[128];
8351 LPTSTR p
, extlist_lpt
;
8352 LPTSTR fName_lpt
, f
, dir_lpt
;
8355 /* convert fName_utf8 to LPTSTR */
8356 fName_lpt
= (LPTSTR
) fs_get(nMaxFName
* sizeof(TCHAR
));
8357 fName_lpt
[0] = '\0';
8358 if(fName_utf8
&& fName_utf8
[0]){
8359 f
= utf8_to_lptstr(fName_utf8
);
8361 _tcsncpy(fName_lpt
, f
, nMaxFName
);
8362 fName_lpt
[nMaxFName
-1] = '\0';
8363 fs_give((void **) &f
);
8367 dir_lpt
= (LPTSTR
) fs_get(nMaxDName
* sizeof(TCHAR
));
8369 if(dir_utf8
&& dir_utf8
[0]){
8370 f
= utf8_to_lptstr(dir_utf8
);
8372 _tcsncpy(dir_lpt
, f
, nMaxDName
);
8373 dir_lpt
[nMaxDName
-1] = '\0';
8374 fs_give((void **) &f
);
8378 for(extlist_lpt
= NULL
, p
= _tcschr(fName_lpt
, '.'); p
; p
= _tcschr(++p
, '.'))
8381 len
= sizeof(moniker
)/sizeof(TCHAR
);
8382 if(extlist_lpt
&& MSWRPeek(HKEY_CLASSES_ROOT
, extlist_lpt
, NULL
, moniker
, &len
) == TRUE
){
8383 len
= sizeof(filters
)/sizeof(TCHAR
);
8385 if(MSWRPeek(HKEY_CLASSES_ROOT
, moniker
, NULL
, filters
, &len
) == TRUE
)
8386 _sntprintf(filters
+ _tcslen(filters
),
8387 sizeof(filters
)/sizeof(TCHAR
) - _tcslen(filters
),
8388 TEXT(" (*%s)#*%s#"), extlist_lpt
, extlist_lpt
);
8390 _sntprintf(filters
, sizeof(filters
)/sizeof(TCHAR
),
8391 TEXT("%s (*%s)#*%s#"), moniker
, extlist_lpt
, extlist_lpt
);
8396 _tcsncat(filters
, TEXT("Text Files (*.txt)#*.txt#All Files (*.*)#*.*#"),
8397 sizeof(filters
)/sizeof(TCHAR
));
8398 filters
[sizeof(filters
)/sizeof(TCHAR
) - 1] = '\0';
8400 for(p
= filters
; *p
!= '\0'; ++p
)
8404 /* Set up the BIG STRUCTURE. */
8405 memset (&ofn
, 0, sizeof(ofn
));
8407 * sizeof(OPENFILENAME) used to work but doesn't work now with
8408 * pre-Windows 2000. This is supposed to be the magic constant to
8409 * make it work in both cases, according to MSDN.
8411 ofn
.lStructSize
= OPENFILENAME_SIZE_VERSION_400
;
8412 ofn
.hwndOwner
= ghTTYWnd
;
8413 ofn
.lpstrFilter
= filters
;
8414 ofn
.lpstrCustomFilter
= NULL
;
8415 ofn
.nFilterIndex
= 1;
8416 ofn
.lpstrFile
= fName_lpt
;
8417 ofn
.nMaxFile
= nMaxFName
;
8418 ofn
.lpstrFileTitle
= NULL
;
8419 ofn
.nMaxFileTitle
= 0;
8420 FillInitialDir (&ofn
.lpstrInitialDir
, dir_lpt
);
8421 ofn
.lpstrTitle
= TEXT("Save To File");
8422 ofn
.Flags
= OFN_NOREADONLYRETURN
| OFN_OVERWRITEPROMPT
| OFN_PATHMUSTEXIST
;
8423 ofn
.lpstrDefExt
= TEXT("txt");
8425 if(GetSaveFileName(&ofn
)){
8426 if(ofn
.nFileOffset
> nMaxDName
-1){
8428 fs_give((void **) &fName_lpt
);
8431 fs_give((void **) &dir_lpt
);
8436 /* Copy directory name to dir_lpt. */
8437 _tcsncpy(dir_lpt
, fName_lpt
, nMaxDName
-1);
8438 dir_lpt
[nMaxDName
-1] = '\0';
8439 if(dir_lpt
[ofn
.nFileOffset
-1] == '\\'
8440 && !(ofn
.nFileOffset
== 3 && _istalpha(dir_lpt
[0]) && dir_lpt
[1] == ':'))
8441 dir_lpt
[ofn
.nFileOffset
-1] = '\0';
8443 dir_lpt
[ofn
.nFileOffset
] = '\0';
8445 /* Remember last dir visited. */
8446 _tcsncpy(gLastDir
, dir_lpt
, PATH_MAX
);
8447 gLastDir
[PATH_MAX
-1] = '\0';
8449 /* convert back to UTF-8 */
8450 cp
= lptstr_to_utf8(dir_lpt
);
8452 strncpy(dir_utf8
, cp
, nMaxDName
-1);
8453 dir_utf8
[nMaxDName
-1] = '\0';
8454 fs_give((void **) &cp
);
8457 p
= fName_lpt
+ ofn
.nFileOffset
;
8459 /* convert fName back to UTF-8 */
8460 cp
= lptstr_to_utf8(p
);
8462 strncpy(fName_utf8
, cp
, nMaxFName
-1);
8463 fName_utf8
[nMaxFName
-1] = '\0';
8464 fs_give((void **) &cp
);
8468 fs_give((void **) &fName_lpt
);
8471 fs_give((void **) &dir_lpt
);
8477 fs_give((void **) &fName_lpt
);
8480 fs_give((void **) &dir_lpt
);
8482 rc
= CommDlgExtendedError();
8483 return(rc
? -1 : 0);
8491 * Display an open file dialog box.
8493 * dir_utf8 > directory to start search in
8494 * < directory finished in.
8495 * fName_utf8 < Name of file selected
8496 * nMaxDName length of dir_utf8
8497 * nMaxFName length of fName_utf8.
8499 * Possible return values:
8500 * 0 no file selected
8502 * -1 some sort of error +++++++++++++
8505 mswin_openfile(char *dir_utf8
, int nMaxDName
, char *fName_utf8
,
8506 int nMaxFName
, char *extlist_utf8
)
8509 TCHAR filters
[1024];
8512 LPTSTR extlist_lpt
= NULL
;
8513 LPTSTR fName_lpt
, f
, dir_lpt
;
8518 extlist_lpt
= utf8_to_lptstr(extlist_utf8
);
8521 * Set filters array. (pairs of null terminated strings, terminated
8522 * by a double null).
8524 _sntprintf(filters
, sizeof(filters
)/sizeof(TCHAR
),
8525 TEXT("%s%sAll Files (*.*)#*.*#"),
8526 extlist_lpt
? extlist_lpt
: TEXT(""), extlist_lpt
? TEXT("#") : TEXT(""));
8529 fs_give((void **) &extlist_lpt
);
8531 for(p
= filters
; *p
!= '\0'; ++p
)
8535 /* Set up the BIG STRUCTURE. */
8536 memset(&ofn
, 0, sizeof(ofn
));
8538 /* convert fName_utf8 to LPTSTR */
8539 fName_lpt
= (LPTSTR
) fs_get(nMaxFName
* sizeof(TCHAR
));
8540 fName_lpt
[0] = '\0';
8541 if(fName_utf8
&& fName_utf8
[0]){
8542 f
= utf8_to_lptstr(fName_utf8
);
8544 _tcsncpy(fName_lpt
, f
, nMaxFName
);
8545 fName_lpt
[nMaxFName
-1] = '\0';
8546 fs_give((void **) &f
);
8550 dir_lpt
= (LPTSTR
) fs_get(nMaxDName
* sizeof(TCHAR
));
8552 if(dir_utf8
&& dir_utf8
[0]){
8553 f
= utf8_to_lptstr(dir_utf8
);
8555 _tcsncpy(dir_lpt
, f
, nMaxDName
);
8556 dir_lpt
[nMaxDName
-1] = '\0';
8557 fs_give((void **) &f
);
8562 * sizeof(OPENFILENAME) used to work but doesn't work now with
8563 * pre-Windows 2000. This is supposed to be the magic constant to
8564 * make it work in both cases, according to MSDN.
8566 ofn
.lStructSize
= OPENFILENAME_SIZE_VERSION_400
;
8567 ofn
.hwndOwner
= ghTTYWnd
;
8568 ofn
.lpstrFilter
= filters
;
8569 ofn
.lpstrCustomFilter
= NULL
;
8570 ofn
.nFilterIndex
= 1;
8571 ofn
.lpstrFile
= fName_lpt
;
8572 ofn
.nMaxFile
= nMaxFName
;
8573 ofn
.lpstrFileTitle
= NULL
;
8574 ofn
.nMaxFileTitle
= 0;
8575 FillInitialDir(&ofn
.lpstrInitialDir
, dir_lpt
);
8576 ofn
.lpstrTitle
= TEXT("Select File");
8577 ofn
.Flags
= OFN_HIDEREADONLY
| OFN_FILEMUSTEXIST
| OFN_PATHMUSTEXIST
;
8578 ofn
.lpstrDefExt
= TEXT("txt");
8580 if(GetOpenFileName(&ofn
)){
8581 if(ofn
.nFileOffset
> nMaxDName
-1){
8583 fs_give((void **) &fName_lpt
);
8586 fs_give((void **) &dir_lpt
);
8591 /* Copy directory name to dir_lpt. */
8592 _tcsncpy(dir_lpt
, fName_lpt
, nMaxDName
-1);
8593 dir_lpt
[nMaxDName
-1] = '\0';
8594 if(dir_lpt
[ofn
.nFileOffset
-1] == '\\'
8595 && !(ofn
.nFileOffset
== 3 && _istalpha(dir_lpt
[0]) && dir_lpt
[1] == ':'))
8596 dir_lpt
[ofn
.nFileOffset
-1] = '\0';
8598 dir_lpt
[ofn
.nFileOffset
] = '\0';
8600 /* Remember last dir visited. */
8601 _tcsncpy(gLastDir
, dir_lpt
, PATH_MAX
);
8602 gLastDir
[PATH_MAX
-1] = '\0';
8604 /* convert back to UTF-8 */
8605 cp
= lptstr_to_utf8(dir_lpt
);
8607 strncpy(dir_utf8
, cp
, nMaxDName
-1);
8608 dir_utf8
[nMaxDName
-1] = '\0';
8609 fs_give((void **) &cp
);
8612 p
= fName_lpt
+ ofn
.nFileOffset
;
8614 /* convert fName back to UTF-8 */
8615 cp
= lptstr_to_utf8(p
);
8617 strncpy(fName_utf8
, cp
, nMaxFName
-1);
8618 fName_utf8
[nMaxFName
-1] = '\0';
8619 fs_give((void **) &cp
);
8623 fs_give((void **) &fName_lpt
);
8626 fs_give((void **) &dir_lpt
);
8632 fs_give((void **) &fName_lpt
);
8635 fs_give((void **) &dir_lpt
);
8637 rc
= CommDlgExtendedError();
8638 return(rc
? -1 : 0);
8644 * Display an open file dialog box.
8645 * Allow selection of multiple files.
8647 * dir_utf8 > directory to start search in
8648 * < directory finished in.
8649 * fName_utf8 < Names of files selected
8650 * nMaxDName length of dir_utf8
8651 * nMaxFName length of fName_utf8.
8653 * Possible return values:
8654 * 0 no file selected
8656 * -1 some sort of error
8659 mswin_multopenfile(char *dir_utf8
, int nMaxDName
, char *fName_utf8
,
8660 int nMaxFName
, char *extlist_utf8
)
8663 TCHAR filters
[1024];
8666 LPTSTR extlist_lpt
= NULL
;
8667 LPTSTR fName_lpt
, f
, dir_lpt
;
8672 extlist_lpt
= utf8_to_lptstr(extlist_utf8
);
8675 * Set filters array. (pairs of null terminated strings, terminated
8676 * by a double null).
8678 _sntprintf(filters
, sizeof(filters
)/sizeof(TCHAR
),
8679 TEXT("%s%sAll Files (*.*)#*.*#"),
8680 extlist_lpt
? extlist_lpt
: TEXT(""), extlist_lpt
? TEXT("#") : TEXT(""));
8683 fs_give((void **) &extlist_lpt
);
8685 for(p
= filters
; *p
!= '\0'; ++p
)
8689 /* Set up the BIG STRUCTURE. */
8690 memset (&ofn
, 0, sizeof(ofn
));
8692 /* convert fName_utf8 to LPTSTR */
8693 fName_lpt
= (LPTSTR
) fs_get(nMaxFName
* sizeof(TCHAR
));
8694 memset(fName_lpt
, 0, nMaxFName
* sizeof(TCHAR
));
8695 if(fName_utf8
&& fName_utf8
[0]){
8696 f
= utf8_to_lptstr(fName_utf8
);
8698 _tcsncpy(fName_lpt
, f
, nMaxFName
);
8699 fName_lpt
[nMaxFName
-1] = '\0';
8700 fs_give((void **) &f
);
8704 dir_lpt
= (LPTSTR
) fs_get(nMaxDName
* sizeof(TCHAR
));
8705 memset(dir_lpt
, 0, nMaxDName
* sizeof(TCHAR
));
8706 if(dir_utf8
&& dir_utf8
[0]){
8707 f
= utf8_to_lptstr(dir_utf8
);
8709 _tcsncpy(dir_lpt
, f
, nMaxDName
);
8710 dir_lpt
[nMaxDName
-1] = '\0';
8711 fs_give((void **) &f
);
8716 * sizeof(OPENFILENAME) used to work but doesn't work now with
8717 * pre-Windows 2000. This is supposed to be the magic constant to
8718 * make it work in both cases, according to MSDN.
8720 ofn
.lStructSize
= OPENFILENAME_SIZE_VERSION_400
;
8721 ofn
.hwndOwner
= ghTTYWnd
;
8722 ofn
.lpstrFilter
= filters
;
8723 ofn
.lpstrCustomFilter
= NULL
;
8724 ofn
.nFilterIndex
= 1;
8725 ofn
.lpstrFile
= fName_lpt
;
8726 ofn
.nMaxFile
= nMaxFName
;
8727 ofn
.lpstrFileTitle
= NULL
;
8728 ofn
.nMaxFileTitle
= 0;
8729 FillInitialDir(&ofn
.lpstrInitialDir
, dir_lpt
);
8730 ofn
.lpstrTitle
= TEXT("Select Files");
8731 ofn
.Flags
= OFN_ALLOWMULTISELECT
| OFN_EXPLORER
|
8732 OFN_HIDEREADONLY
| OFN_FILEMUSTEXIST
| OFN_PATHMUSTEXIST
;
8733 ofn
.lpstrDefExt
= TEXT("txt");
8735 if(GetOpenFileName(&ofn
)){
8736 if(ofn
.nFileOffset
> nMaxDName
-1){
8738 fs_give((void **) &fName_lpt
);
8741 fs_give((void **) &dir_lpt
);
8746 /* Copy directory name to dir_lpt. */
8747 _tcsncpy(dir_lpt
, fName_lpt
, nMaxDName
-1);
8748 dir_lpt
[nMaxDName
-1] = '\0';
8749 if(dir_lpt
[ofn
.nFileOffset
-1] == '\\'
8750 && !(ofn
.nFileOffset
== 3 && _istalpha(dir_lpt
[0]) && dir_lpt
[1] == ':'))
8751 dir_lpt
[ofn
.nFileOffset
-1] = '\0';
8753 dir_lpt
[ofn
.nFileOffset
] = '\0';
8755 /* Remember last dir visited. */
8756 _tcsncpy(gLastDir
, dir_lpt
, PATH_MAX
);
8757 gLastDir
[PATH_MAX
-1] = '\0';
8759 /* convert back to UTF-8 */
8760 cp
= lptstr_to_utf8(dir_lpt
);
8762 strncpy(dir_utf8
, cp
, nMaxDName
-1);
8763 dir_utf8
[nMaxDName
-1] = '\0';
8764 fs_give((void **) &cp
);
8768 * The file names are all in the same directory and are separated
8769 * by '\0' characters and terminated by double '\0'.
8770 * This fact depends on the OFN_EXPLORER bit being set in the flags
8773 * This is complicated because we need to convert all of these file
8776 for(q
=fName_utf8
, p
=fName_lpt
+ ofn
.nFileOffset
; *p
; p
+= _tcslen(p
)+1){
8777 cp
= lptstr_to_utf8(p
);
8779 sstrncpy(&q
, cp
, (int)(nMaxFName
-(q
-fName_utf8
)));
8780 if(q
-fName_utf8
< nMaxFName
){
8782 if(q
-fName_utf8
< nMaxFName
)
8783 *q
= '\0'; /* the double null if this is the end */
8786 fName_utf8
[nMaxFName
-1] = '\0';
8788 fs_give((void **) &cp
);
8792 fName_utf8
[nMaxFName
-1] = fName_utf8
[nMaxFName
-2] = '\0';
8795 fs_give((void **) &fName_lpt
);
8798 fs_give((void **) &dir_lpt
);
8804 fs_give((void **) &fName_lpt
);
8807 fs_give((void **) &dir_lpt
);
8809 rc
= CommDlgExtendedError();
8810 return(rc
? -1 : 0);
8815 /*---------------------------------------------------------------------------
8819 * pico_XXcolor() - each function sets a particular attribute
8822 pico_nfcolor(char *s
)
8827 SetColorAttribute (&gpTTYInfo
->rgbFGColor
, s
);
8828 pico_set_nfg_color();
8830 if(the_normal_color
){
8831 strncpy(the_normal_color
->fg
,
8832 ConvertStringRGB(cbuf
, sizeof(cbuf
), gpTTYInfo
->rgbFGColor
),
8834 the_normal_color
->fg
[MAXCOLORLEN
] = '\0';
8838 gpTTYInfo
->rgbFGColor
= GetSysColor (COLOR_WINDOWTEXT
);
8839 if(the_normal_color
)
8840 free_color_pair(&the_normal_color
);
8843 // Update all textwindows with the new FG color.
8844 mswin_tw_setcolor((MSWIN_TEXTWINDOW
*)-1,
8845 gpTTYInfo
->rgbFGColor
, gpTTYInfo
->rgbBGColor
);
8850 pico_nbcolor(char *s
)
8855 SetColorAttribute (&gpTTYInfo
->rgbBGColor
, s
);
8856 pico_set_nbg_color();
8858 if(the_normal_color
){
8859 strncpy(the_normal_color
->bg
,
8860 ConvertStringRGB(cbuf
, sizeof(cbuf
), gpTTYInfo
->rgbBGColor
),
8862 the_normal_color
->fg
[MAXCOLORLEN
] = '\0';
8866 gpTTYInfo
->rgbBGColor
= GetSysColor (COLOR_WINDOW
);
8867 if(the_normal_color
)
8868 free_color_pair(&the_normal_color
);
8871 // Update all textwindows with the new BG color.
8872 mswin_tw_setcolor((MSWIN_TEXTWINDOW
*)-1,
8873 gpTTYInfo
->rgbFGColor
, gpTTYInfo
->rgbBGColor
);
8878 pico_rfcolor(char *s
)
8883 SetColorAttribute (&gpTTYInfo
->rgbRFGColor
, s
);
8886 strncpy(the_rev_color
->fg
,
8887 ConvertStringRGB(cbuf
, sizeof(cbuf
), gpTTYInfo
->rgbRFGColor
),
8889 the_rev_color
->fg
[MAXCOLORLEN
] = '\0';
8893 gpTTYInfo
->rgbRFGColor
= GetSysColor (COLOR_HIGHLIGHTTEXT
);
8895 free_color_pair(&the_rev_color
);
8901 pico_rbcolor(char *s
)
8906 SetColorAttribute (&gpTTYInfo
->rgbRBGColor
, s
);
8909 strncpy(the_rev_color
->bg
,
8910 ConvertStringRGB(cbuf
, sizeof(cbuf
), gpTTYInfo
->rgbRBGColor
),
8912 the_rev_color
->bg
[MAXCOLORLEN
] = '\0';
8916 gpTTYInfo
->rgbRBGColor
= GetSysColor (COLOR_HIGHLIGHT
);
8918 free_color_pair(&the_rev_color
);
8931 pico_count_in_color_table()
8933 return(visibleColorTableSize
);
8938 * Return a pointer to an rgb string for the input color. The output is 11
8939 * characters long and looks like rrr,ggg,bbb.
8941 * Args colorName -- The color to convert to ascii rgb.
8943 * Returns Pointer to a static buffer containing the rgb string.
8946 color_to_asciirgb(char *colorName
)
8948 static char c_to_a_buf
[3][RGBLEN
+1];
8949 static int whichbuf
= 0;
8953 whichbuf
= (whichbuf
+ 1) % 3;
8955 if(ConvertRGBString(colorName
, &cf
)){
8956 snprintf(c_to_a_buf
[whichbuf
], sizeof(c_to_a_buf
[0]), "%.3d,%.3d,%.3d",
8957 GetRValue(cf
), GetGValue(cf
), GetBValue(cf
));
8961 * If we didn't find the color it could be that it is the
8962 * normal color (MATCH_NORM_COLOR) or the none color
8963 * (MATCH_NONE_COLOR). If that is the case, this strncpy thing
8964 * will work out correctly because those two strings are
8965 * RGBLEN long. Otherwise we're in a bit of trouble. This
8966 * most likely means that the user is using the same pinerc on
8967 * two terminals, one with more colors than the other. We didn't
8968 * find a match because this color isn't present on this terminal.
8969 * Since the return value of this function is assumed to be
8970 * RGBLEN long, we'd better make it that long.
8971 * It still won't work correctly because colors will be screwed up,
8972 * but at least the embedded colors in filter.c will get properly
8973 * sucked up when they're encountered.
8975 strncpy(c_to_a_buf
[whichbuf
], "xxxxxxxxxxx", RGBLEN
);
8976 l
= (int)strlen(colorName
);
8977 strncpy(c_to_a_buf
[whichbuf
], colorName
, (l
< RGBLEN
) ? l
: RGBLEN
);
8978 c_to_a_buf
[whichbuf
][RGBLEN
] = '\0';
8981 return(c_to_a_buf
[whichbuf
]);
8986 pico_set_nfg_color()
8989 gpTTYInfo
->curAttrib
.rgbFG
= gpTTYInfo
->rgbFGColor
;
8993 pico_set_nbg_color()
8996 gpTTYInfo
->curAttrib
.rgbBG
= gpTTYInfo
->rgbBGColor
;
9000 pico_set_normal_color()
9002 pico_set_nfg_color();
9003 pico_set_nbg_color();
9007 pico_get_rev_color()
9009 char fgbuf
[MAXCLEN
], bgbuf
[MAXCLEN
];
9013 new_color_pair(ConvertStringRGB(fgbuf
,sizeof(fgbuf
),gpTTYInfo
->rgbRFGColor
),
9014 ConvertStringRGB(bgbuf
,sizeof(bgbuf
),gpTTYInfo
->rgbRBGColor
));
9015 return(the_rev_color
);
9019 pico_get_normal_color()
9021 char fgbuf
[MAXCLEN
], bgbuf
[MAXCLEN
];
9023 if(!the_normal_color
)
9025 new_color_pair(ConvertStringRGB(fgbuf
,sizeof(fgbuf
),gpTTYInfo
->rgbFGColor
),
9026 ConvertStringRGB(bgbuf
,sizeof(bgbuf
),gpTTYInfo
->rgbBGColor
));
9027 return(the_normal_color
);
9031 * Sets color to (fg,bg).
9032 * Flags == PSC_NONE No alternate default if fg,bg fails.
9033 * == PSC_NORM Set it to Normal color on failure.
9034 * == PSC_REV Set it to Reverse color on failure.
9036 * If flag PSC_RET is set, returns an allocated copy of the previous
9037 * color pair, otherwise returns NULL.
9040 pico_set_colors(char *fg
, char *bg
, int flags
)
9042 COLOR_PAIR
*cp
= NULL
;
9045 cp
= pico_get_cur_color();
9047 if(!(fg
&& bg
&& pico_set_fg_color(fg
) && pico_set_bg_color(bg
))){
9049 if(flags
& PSC_NORM
)
9050 pico_set_normal_color();
9051 else if(flags
& PSC_REV
)
9060 pico_is_good_color(char *colorName
)
9064 if(!struncmp(colorName
, MATCH_NORM_COLOR
, RGBLEN
)
9065 || !struncmp(colorName
, MATCH_NONE_COLOR
, RGBLEN
))
9068 return(ConvertRGBString(colorName
, &cf
));
9073 pico_set_fg_color(char *colorName
)
9075 char fgbuf
[MAXCLEN
];
9079 if(!struncmp(colorName
, MATCH_NORM_COLOR
, RGBLEN
)){
9080 ConvertStringRGB(fgbuf
,sizeof(fgbuf
),gpTTYInfo
->rgbFGColor
);
9083 else if(!struncmp(colorName
, MATCH_NONE_COLOR
, RGBLEN
))
9086 return(ConvertRGBString(colorName
, &gpTTYInfo
->curAttrib
.rgbFG
));
9091 pico_set_bg_color(char *colorName
)
9093 char bgbuf
[MAXCLEN
];
9097 if(!struncmp(colorName
, MATCH_NORM_COLOR
, RGBLEN
)){
9098 ConvertStringRGB(bgbuf
,sizeof(bgbuf
),gpTTYInfo
->rgbBGColor
);
9101 else if(!struncmp(colorName
, MATCH_NONE_COLOR
, RGBLEN
))
9104 return(ConvertRGBString(colorName
, &gpTTYInfo
->curAttrib
.rgbBG
));
9109 pico_get_last_fg_color()
9116 pico_get_last_bg_color()
9123 pico_get_color_options()
9125 return((unsigned)0);
9130 pico_set_color_options(unsigned int opts
)
9136 pico_get_cur_color()
9138 char fgbuf
[MAXCLEN
], bgbuf
[MAXCLEN
];
9140 return(new_color_pair(ConvertStringRGB(fgbuf
,sizeof(fgbuf
),gpTTYInfo
->curAttrib
.rgbFG
),
9141 ConvertStringRGB(bgbuf
,sizeof(bgbuf
),gpTTYInfo
->curAttrib
.rgbBG
)));
9146 mswin_rgbchoice(char *pOldRGB
)
9149 static COLORREF custColors
[16] = {
9163 memset(&cc
, 0, sizeof(CHOOSECOLOR
));
9165 cc
.lStructSize
= sizeof(CHOOSECOLOR
);
9166 cc
.hwndOwner
= ghTTYWnd
;
9167 cc
.Flags
= CC_ANYCOLOR
;
9168 cc
.lpCustColors
= &custColors
[0];
9173 ConvertRGBString (pOldRGB
, &cc
.rgbResult
);
9174 cc
.Flags
|= CC_RGBINIT
;
9176 for(i
= 0; i
< 11 && custColors
[i
] != cc
.rgbResult
; i
++)
9180 custColors
[i
] = cc
.rgbResult
;
9181 cc
.Flags
|= CC_FULLOPEN
;
9186 if(ChooseColor(&cc
)){
9187 char rgbbuf
[MAXCLEN
], *p
;
9189 ConvertStringRGB(rgbbuf
, sizeof(rgbbuf
), cc
.rgbResult
);
9190 if(p
= MemAlloc(MAXCLEN
* sizeof(char))){
9191 strncpy(p
, rgbbuf
, MAXCLEN
);
9192 p
[MAXCLEN
-1] = '\0';
9203 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9205 * Signal and alarm functions
9207 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
9210 * Provide a rough implementation of the SIGALRM and alarm functions
9217 * Set a new handler for a signal.
9219 void (__cdecl
* __cdecl
signal (int sig
,void (__cdecl
*hndlr
)(int)))(int)
9222 SignalType oldValue
;
9226 oldValue
= gSignalAlarm
;
9227 gSignalAlarm
= hndlr
;
9231 oldValue
= gSignalHUP
;
9235 /* All other's are always ignored. */
9246 * Set the alarm expiration time (in seconds)
9249 mswin_alarm (int seconds
)
9253 prevtime
= gAlarmTimeout
? (gAlarmTimeout
- (GetTickCount () / 1000)): 0;
9254 gAlarmTimeout
= seconds
? (GetTickCount() / 1000) + seconds
: 0;
9262 * Deliver and clear the alarm.
9267 if (gSignalAlarm
!= SIG_DFL
&& gSignalAlarm
!= SIG_IGN
) {
9268 /* Clear AlarmTimeout BEFORE calling handler. handler may call back
9269 * to reset timeout. */
9272 gSignalAlarm (SIGALRM
);
9282 gSignalHUP (SIGHUP
);
9290 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9292 * Printer font selection menu
9294 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
9297 * Set the print font to be the same as the window font.
9301 PrintFontSameAs (HWND hWnd
)
9308 pTTYInfo
= (PTTYINFO
) MyGetWindowLongPtr (hWnd
, GWL_PTTYINFO
);
9309 if (pTTYInfo
== NULL
)
9312 if (gPrintFontSameAs
) {
9314 /* No longer same as window font. Use window font as starting point
9315 * for new printer font. User may later modify printer font. */
9317 ppi
= GetDeviceCaps (hDC
, LOGPIXELSY
);
9318 ReleaseDC (ghTTYWnd
, hDC
);
9319 ExtractFontInfo(&pTTYInfo
->lfTTYFont
,
9320 gPrintFontName
, sizeof(gPrintFontName
)/sizeof(TCHAR
),
9322 gPrintFontStyle
, sizeof(gPrintFontStyle
)/sizeof(TCHAR
),
9324 gPrintFontCharSet
, sizeof(gPrintFontCharSet
)/sizeof(TCHAR
));
9325 gPrintFontSameAs
= FALSE
;
9329 /* Set to be same as the printer font. Destroy printer font info
9330 * and set "sameAs" flag to TRUE. */
9331 gPrintFontName
[0] = '\0';
9332 gPrintFontSameAs
= TRUE
;
9334 DidResize (gpTTYInfo
);
9342 PrintFontSelect (HWND hWnd
)
9344 CHOOSEFONT cfTTYFont
;
9353 ppi
= GetDeviceCaps (hDC
, LOGPIXELSY
);
9354 ReleaseDC (ghTTYWnd
, hDC
);
9357 newFont
.lfHeight
= -MulDiv (gPrintFontSize
, ppi
, 72);
9358 _tcsncpy(newFont
.lfFaceName
, gPrintFontName
, LF_FACESIZE
);
9359 newFont
.lfFaceName
[LF_FACESIZE
-1] = 0;
9360 newFont
.lfWeight
= 0;
9361 if(_tcsstr(gPrintFontStyle
, TEXT("bold")))
9362 newFont
.lfWeight
= FW_BOLD
;
9364 newFont
.lfItalic
= 0;
9365 if(_tcsstr(gPrintFontStyle
, TEXT("italic")))
9366 newFont
.lfItalic
= 1;
9368 newFont
.lfWidth
= 0;
9369 newFont
.lfEscapement
= 0;
9370 newFont
.lfOrientation
= 0;
9371 newFont
.lfUnderline
= 0;
9372 newFont
.lfStrikeOut
= 0;
9373 newFont
.lfCharSet
= mswin_string2charsetid(gPrintFontCharSet
);
9374 newFont
.lfOutPrecision
= OUT_DEFAULT_PRECIS
;
9375 newFont
.lfClipPrecision
= CLIP_DEFAULT_PRECIS
;
9376 newFont
.lfQuality
= DEFAULT_QUALITY
;
9377 newFont
.lfPitchAndFamily
= FIXED_PITCH
;
9380 cfTTYFont
.lStructSize
= sizeof (CHOOSEFONT
);
9381 cfTTYFont
.hwndOwner
= hWnd
;
9382 cfTTYFont
.hDC
= NULL
;
9383 cfTTYFont
.rgbColors
= 0;
9384 cfTTYFont
.lpLogFont
= &newFont
;
9385 cfTTYFont
.Flags
= CF_BOTH
| CF_FIXEDPITCHONLY
|
9386 CF_INITTOLOGFONTSTRUCT
| CF_ANSIONLY
|
9387 CF_FORCEFONTEXIST
| CF_LIMITSIZE
;
9388 cfTTYFont
.nSizeMin
= FONT_MIN_SIZE
;
9389 cfTTYFont
.nSizeMax
= FONT_MAX_SIZE
;
9390 cfTTYFont
.lCustData
= 0 ;
9391 cfTTYFont
.lpfnHook
= NULL
;
9392 cfTTYFont
.lpTemplateName
= NULL
;
9393 cfTTYFont
.hInstance
= GET_HINST (hWnd
);
9396 if (ChooseFont (&cfTTYFont
)) {
9397 ExtractFontInfo(&newFont
,
9398 gPrintFontName
, sizeof(gPrintFontName
)/sizeof(TCHAR
),
9400 gPrintFontStyle
, sizeof(gPrintFontStyle
)/sizeof(TCHAR
),
9402 gPrintFontCharSet
, sizeof(gPrintFontCharSet
)/sizeof(TCHAR
));
9403 DidResize (gpTTYInfo
);
9406 /* So I can see with the debugger. */
9407 drc
= CommDlgExtendedError();
9412 ExtractFontInfo(LOGFONT
*pFont
, LPTSTR fontName
, size_t nfontName
,
9413 int *fontSize
, LPTSTR fontStyle
, size_t nfontStyle
,
9414 int ppi
, LPTSTR fontCharSet
, size_t nfontCharSet
)
9416 TCHAR
*sep
[] = {TEXT(""), TEXT(", ")};
9420 _tcsncpy(fontName
, pFont
->lfFaceName
, nfontName
);
9421 fontName
[nfontName
-1] = '\0';
9424 if(pFont
->lfWeight
>= FW_BOLD
) {
9425 _tcsncpy(fontStyle
, TEXT("bold"), nfontStyle
);
9426 fontStyle
[nfontStyle
-1] = '\0';
9430 if(pFont
->lfItalic
){
9431 _tcsncat(fontStyle
, sep
[iSep
], nfontStyle
- _tcslen(fontStyle
));
9432 fontStyle
[nfontStyle
-1] = '\0';
9434 _tcsncat(fontStyle
, TEXT("italic"), nfontStyle
- _tcslen(fontStyle
));
9435 fontStyle
[nfontStyle
-1] = '\0';
9438 mswin_charsetid2string(fontCharSet
, nfontCharSet
, pFont
->lfCharSet
);
9441 *fontSize
= MulDiv(-pFont
->lfHeight
, 72, ppi
);
9446 DidResize (PTTYINFO pTTYInfo
)
9450 for (i
= 0; i
< RESIZE_CALLBACK_ARRAY_SIZE
; ++i
) {
9451 if (pTTYInfo
->resizer
[i
] != NULL
)
9452 pTTYInfo
->resizer
[i
] (pTTYInfo
->actNRow
, pTTYInfo
->actNColumn
);
9455 * Put a null character into the input queue so that the data input
9456 * loops stop and return to their callers who will then re-calculate the
9457 * mouse regions so that the user can click on the new regions of the
9458 * screen and have the right thing happen.
9466 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
9468 * Cut, Copy, and Paste operations
9470 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
9474 * Gets called right before the menu is displayed so we can make
9475 * any last minute adjustments.
9478 UpdateMenu (HWND hWnd
)
9484 UINT fAccel
= EM_NONE
;
9487 pTTYInfo
= (PTTYINFO
) MyGetWindowLongPtr (hWnd
, GWL_PTTYINFO
);
9488 if (pTTYInfo
== NULL
)
9491 hMenu
= GetMenu (hWnd
);
9496 /* Currently pasting so disable paste and enable cancel paste. */
9497 EnableMenuItem (hMenu
, IDM_EDIT_PASTE
, MF_BYCOMMAND
|MF_GRAYED
);
9498 EnableMenuItem (hMenu
, IDM_EDIT_CANCEL_PASTE
, MF_BYCOMMAND
|MF_ENABLED
);
9500 fAccel
|= (EM_PST
| EM_PST_ABORT
);
9505 * Not pasting. If text is available on clipboard and we are
9506 * at a place where we can paste, enable past menu option.
9508 if (IsClipboardFormatAvailable (CF_UNICODETEXT
) && gPasteEnabled
){
9509 EnableMenuItem (hMenu
, IDM_EDIT_PASTE
, MF_BYCOMMAND
|MF_ENABLED
);
9515 EnableMenuItem (hMenu
, IDM_EDIT_PASTE
, MF_BYCOMMAND
|MF_GRAYED
);
9517 EnableMenuItem (hMenu
, IDM_EDIT_CANCEL_PASTE
, MF_BYCOMMAND
|MF_GRAYED
);
9520 if (SelAvailable ()) {
9521 EnableMenuItem (hMenu
, IDM_EDIT_CUT
, MF_BYCOMMAND
|MF_GRAYED
);
9522 EnableMenuItem (hMenu
, IDM_EDIT_COPY
, MF_BYCOMMAND
|MF_ENABLED
);
9523 EnableMenuItem (hMenu
, IDM_EDIT_COPY_APPEND
, MF_BYCOMMAND
|MF_ENABLED
);
9525 fAccel
|= (EM_CP
| EM_CP_APPEND
);
9530 EnableMenuItem (hMenu
, IDM_EDIT_CUT
, MF_BYCOMMAND
| MF_ENABLED
);
9536 EnableMenuItem (hMenu
, IDM_EDIT_CUT
, MF_BYCOMMAND
| MF_GRAYED
);
9539 EnableMenuItem (hMenu
, IDM_EDIT_COPY
, MF_BYCOMMAND
| MF_ENABLED
);
9540 EnableMenuItem (hMenu
, IDM_EDIT_COPY_APPEND
,
9541 MF_BYCOMMAND
| MF_ENABLED
);
9543 fAccel
|= (EM_CP
| EM_CP_APPEND
);
9547 EnableMenuItem (hMenu
, IDM_EDIT_COPY
, MF_BYCOMMAND
| MF_GRAYED
);
9548 EnableMenuItem (hMenu
, IDM_EDIT_COPY_APPEND
,
9549 MF_BYCOMMAND
| MF_GRAYED
);
9554 * Set up Font selection menu
9556 if (gPrintFontName
[0] == '\0') {
9557 CheckMenuItem (hMenu
, IDM_OPT_FONTSAMEAS
, MF_BYCOMMAND
| MF_CHECKED
);
9558 EnableMenuItem (hMenu
, IDM_OPT_SETPRINTFONT
,
9559 MF_BYCOMMAND
| MF_GRAYED
);
9562 CheckMenuItem (hMenu
, IDM_OPT_FONTSAMEAS
,
9563 MF_BYCOMMAND
| MF_UNCHECKED
);
9564 EnableMenuItem (hMenu
, IDM_OPT_SETPRINTFONT
,
9565 MF_BYCOMMAND
| MF_ENABLED
);
9569 * Setup Caret selection menu
9571 EnableMenuItem (hMenu
, IDM_OPT_CARETBLOCK
, MF_BYCOMMAND
| MF_ENABLED
);
9572 EnableMenuItem (hMenu
, IDM_OPT_CARETSMALLBLOCK
, MF_BYCOMMAND
| MF_ENABLED
);
9573 EnableMenuItem (hMenu
, IDM_OPT_CARETHBAR
, MF_BYCOMMAND
| MF_ENABLED
);
9574 EnableMenuItem (hMenu
, IDM_OPT_CARETVBAR
, MF_BYCOMMAND
| MF_ENABLED
);
9575 CheckMenuRadioItem(hMenu
, IDM_OPT_CARETBLOCK
, IDM_OPT_CARETVBAR
,
9576 IDM_OPT_CARETBLOCK
+ pTTYInfo
->cCaretStyle
,
9580 * Check toolbar menu.
9582 EnableMenuItem (hMenu
, IDM_OPT_TOOLBAR
, MF_BYCOMMAND
| MF_ENABLED
);
9583 CheckMenuItem (hMenu
, IDM_OPT_TOOLBAR
, MF_BYCOMMAND
|
9584 (pTTYInfo
->toolBarSize
> 0 ? MF_CHECKED
: MF_UNCHECKED
));
9585 EnableMenuItem (hMenu
, IDM_OPT_TOOLBARPOS
, MF_BYCOMMAND
| MF_ENABLED
);
9586 CheckMenuItem (hMenu
, IDM_OPT_TOOLBARPOS
, MF_BYCOMMAND
|
9587 (pTTYInfo
->toolBarTop
> 0 ? MF_CHECKED
: MF_UNCHECKED
));
9592 * Check the dialogs menu.
9594 /* xxx EnableMenuItem (hMenu, IDM_OPT_USEDIALOGS, MF_BYCOMMAND | MF_ENABLED);*/
9595 CheckMenuItem (hMenu
, IDM_OPT_USEDIALOGS
, MF_BYCOMMAND
|
9596 (gfUseDialogs
? MF_CHECKED
: MF_UNCHECKED
));
9599 * Enable the Erase Credentials menu
9601 EnableMenuItem (hMenu
, IDM_OPT_ERASE_CREDENTIALS
,
9602 MF_BYCOMMAND
| (gEraseCredsCallback
? MF_ENABLED
: MF_GRAYED
));
9605 * Enable the View in New Window menu item
9607 EnableMenuItem (hMenu
, IDM_MI_VIEWINWIND
,
9608 MF_BYCOMMAND
| (gViewInWindCallback
? MF_ENABLED
: MF_GRAYED
));
9610 #ifdef ACCELERATORS_OPT
9611 CheckMenuItem (hMenu
, IDM_OPT_USEACCEL
, MF_BYCOMMAND
|
9612 (pTTYInfo
->hAccel
? MF_CHECKED
: MF_UNCHECKED
));
9616 * Setup the sort menu...
9619 i
= (*gSortCallback
)(0, 0);
9621 /* NOTE: this func's args are dependent on definition order
9624 CheckMenuRadioItem(hMenu
, IDM_MI_SORTSUBJECT
, IDM_MI_SORTTHREAD
,
9625 IDM_MI_SORTSUBJECT
+ (i
& 0x00ff), MF_BYCOMMAND
);
9626 CheckMenuItem(hMenu
, IDM_MI_SORTREVERSE
,
9627 MF_BYCOMMAND
|((i
& 0x0100) ? MF_CHECKED
: MF_UNCHECKED
));
9630 CheckMenuRadioItem(hMenu
, IDM_MI_SORTSUBJECT
, IDM_MI_SORTTHREAD
,
9631 IDM_MI_SORTARRIVAL
, MF_BYCOMMAND
);
9632 CheckMenuItem(hMenu
, IDM_MI_SORTREVERSE
, MF_BYCOMMAND
| MF_UNCHECKED
);
9636 * Setup the flag menu...
9639 int flags
= (*gFlagCallback
)(0, 0);
9640 for(i
= IDM_MI_FLAGIMPORTANT
; i
<= IDM_MI_FLAGDELETED
; i
++)
9641 CheckMenuItem(hMenu
, i
, MF_BYCOMMAND
9642 | (((flags
>> (i
- IDM_MI_FLAGIMPORTANT
)) & 0x0001)
9643 ? MF_CHECKED
: MF_UNCHECKED
));
9650 i
= (*gHdrCallback
)(0, 0);
9651 CheckMenuItem(hMenu
, IDM_MI_HDRMODE
,
9652 MF_BYCOMMAND
|((i
!= 0) ? MF_CHECKED
: MF_UNCHECKED
));
9659 i
= (*gZoomCallback
)(0, 0);
9660 CheckMenuItem(hMenu
, IDM_MI_ZOOM
,
9661 MF_BYCOMMAND
| (i
? MF_CHECKED
: MF_UNCHECKED
));
9664 * Set up command menu.
9666 if (!pTTYInfo
->menuItemsCurrent
) {
9667 for (i
= 0; i
< KS_COUNT
; ++i
)
9668 if(i
+ KS_RANGESTART
!= KS_GENERALHELP
)
9669 EnableMenuItem (hMenu
, i
+ KS_RANGESTART
,
9670 MF_BYCOMMAND
| ((pTTYInfo
->menuItems
[i
].miActive
)
9671 ? MF_ENABLED
: MF_GRAYED
));
9674 * Special command-specific knowledge here
9676 for(i
= IDM_MI_SORTSUBJECT
; i
<= IDM_MI_SORTREVERSE
; i
++)
9677 EnableMenuItem (hMenu
, i
,
9679 | ((pTTYInfo
->menuItems
[KS_SORT
-KS_RANGESTART
].miActive
)
9680 ? MF_ENABLED
: MF_GRAYED
));
9682 for(i
= IDM_MI_FLAGIMPORTANT
; i
<= IDM_MI_FLAGDELETED
; i
++)
9683 EnableMenuItem (hMenu
, i
,
9685 | ((pTTYInfo
->menuItems
[KS_FLAG
- KS_RANGESTART
].miActive
)
9686 ? MF_ENABLED
: MF_GRAYED
));
9691 * deal with any callback state dependent enabling
9693 if(pTTYInfo
->menuItems
[IDM_MI_APPLY
- KS_RANGESTART
].miActive
)
9694 EnableMenuItem(hMenu
, IDM_MI_APPLY
,
9695 MF_BYCOMMAND
| ((gSelectedCallback
9696 && (*gSelectedCallback
)(0, 0))
9697 ? MF_ENABLED
: MF_GRAYED
));
9699 if(pTTYInfo
->menuItems
[IDM_MI_ZOOM
- KS_RANGESTART
].miActive
)
9700 EnableMenuItem(hMenu
, IDM_MI_ZOOM
,
9701 MF_BYCOMMAND
| ((gSelectedCallback
9702 && (*gSelectedCallback
)(0, 0))
9703 ? MF_ENABLED
: MF_GRAYED
));
9706 if(pTTYInfo
->menuItems
[KS_WHEREIS
- KS_RANGESTART
].miActive
)
9709 AccelManage (hWnd
, fAccel
);
9712 pTTYInfo
->menuItemsCurrent
= TRUE
;
9718 * Cut region to kill buffer.
9725 if(gCopyCutFunction
== (getc_t
)kremove
){
9726 hCB
= GlobalAlloc (GMEM_MOVEABLE
, 0);
9728 kdelete(); /* Clear current kill buffer. */
9729 killregion (1, 0); /* Kill Region (and copy to clipboard). */
9730 update (); /* And update the screen */
9738 * This function copies the kill buffer to the window's clip board.
9739 * (actually, it can copy any buffer for which a copyfunc is provided).
9740 * Called from ldelete().
9743 mswin_killbuftoclip (getc_t copyfunc
)
9748 /* Save old copy function. */
9749 oldfunc
= gCopyCutFunction
;
9750 gCopyCutFunction
= copyfunc
;
9752 /* Allocate clip buffer. */
9753 hCB
= GlobalAlloc (GMEM_MOVEABLE
, 0);
9755 EditDoCopyData (hCB
, 0);
9758 /* restore copy function. */
9759 gCopyCutFunction
= oldfunc
;
9765 * Copy region to kill buffer.
9772 if (SelAvailable()) {
9773 /* This is a copy of the windows selection. */
9774 hCB
= GlobalAlloc (GMEM_MOVEABLE
, 0);
9780 /* Otherwise, it's a Pico/Pine copy. */
9781 if(gCopyCutFunction
== (getc_t
)kremove
){
9782 kdelete(); /* Clear current kill buffer. */
9786 hCB
= GlobalAlloc (GMEM_MOVEABLE
, 0);
9788 EditDoCopyData (hCB
, 0);
9795 * Called in responce to "Copy Append" menu command, when there is an active
9796 * Windows selection on the screen.
9799 EditCopyAppend (void)
9807 /* Attempt to copy clipboard data to my own handle. */
9809 if (OpenClipboard (ghTTYWnd
)) { /* And can get clipboard. */
9810 hCB
= GetClipboardData (CF_UNICODETEXT
);
9811 if (hCB
!= NULL
) { /* And can get data. */
9812 pCB
= GlobalLock (hCB
);
9813 cbSize
= _tcslen (pCB
); /* It's a null term string. */
9814 hMyCopy
= GlobalAlloc (GMEM_MOVEABLE
, (cbSize
+1)*sizeof(*pCB
));
9815 if (hMyCopy
!= NULL
) { /* And can get memory. */
9816 pMyCopy
= GlobalLock (hMyCopy
);
9817 if (pMyCopy
!= NULL
) {
9818 memcpy (pMyCopy
, pCB
, cbSize
*sizeof(*pCB
)); /* Copy data. */
9819 GlobalUnlock (hMyCopy
);
9822 GlobalFree (hMyCopy
);
9827 } /* GetClipboardData. */
9829 } /* OpenClipboard. */
9833 /* Now, if I got a copy, append current selection to that
9834 * and stuff it back into the clipboard. */
9835 if (hMyCopy
!= NULL
) {
9836 if (SelAvailable ()) {
9837 SelDoCopy (hMyCopy
, (DWORD
)cbSize
);
9840 if(gCopyCutFunction
== (getc_t
)kremove
) {
9841 kdelete(); /* Clear current kill buffer. */
9844 EditDoCopyData (hMyCopy
, (DWORD
)cbSize
);
9851 * Copy data from the kill buffer to the clipboard. Handle LF->CRLF
9852 * translation if necessary.
9855 EditDoCopyData (HANDLE hCB
, DWORD lenCB
)
9859 long c
; /* would be TCHAR but needs -1 retval from callback */
9860 TCHAR lastc
= (TCHAR
)'\0';
9861 DWORD cbSize
; /* Allocated size of hCB. */
9863 #define BUF_INC 4096
9865 if (gCopyCutFunction
!= NULL
) { /* If there really is data. */
9866 if (OpenClipboard (ghTTYWnd
)) { /* ...and we get the CB. */
9867 if (EmptyClipboard ()) { /* ...and clear previous CB.*/
9868 pCB
= GlobalLock (hCB
);
9871 /* Copy it. (BUG: change int arg) */
9872 for(i
= 0L; (c
= (*gCopyCutFunction
)((int)i
)) != -1; i
++){
9874 * Rather than fix every function that might
9875 * get called for character retrieval to supply
9876 * CRLF EOLs, let's just fix it here. The downside
9877 * is a much slower copy for large buffers, but
9878 * hey, what do they want?
9880 if(lenCB
+ 2L >= cbSize
){
9883 hCB
= GlobalReAlloc (hCB
, cbSize
*sizeof(TCHAR
), GMEM_MOVEABLE
);
9887 pCB
= GlobalLock (hCB
);
9891 if(c
== (TCHAR
)ASCII_LF
&& lastc
!= (TCHAR
)ASCII_CR
) {
9892 *p
++ = (TCHAR
)ASCII_CR
; /* insert CR before LF */
9896 *p
++ = lastc
= (TCHAR
)c
;
9900 /* Only if we got some data. */
9905 if (SetClipboardData (CF_UNICODETEXT
, hCB
) == NULL
)
9906 /* Failed! Free the data. */
9910 /* There was no data copied. */
9922 * Get a handle to the current (text) clipboard and make my own copy.
9923 * Keep my copy locked because I'll be using it to read bytes from.
9933 if (ghPaste
== NULL
) { /* If we are not already pasting. */
9934 if (OpenClipboard (ghTTYWnd
)) { /* And can get clipboard. */
9935 hCB
= GetClipboardData (CF_UNICODETEXT
);
9936 if (hCB
!= NULL
) { /* And can get data. */
9937 pCB
= GlobalLock (hCB
);
9938 cbSize
= _tcslen (pCB
); /* It's a null term string. */
9939 ghPaste
= GlobalAlloc (GMEM_MOVEABLE
, (cbSize
+1)*sizeof(TCHAR
));
9940 if (ghPaste
!= NULL
) { /* And can get memory. */
9941 gpPasteNext
= GlobalLock (ghPaste
);
9942 memcpy (gpPasteNext
, pCB
, (cbSize
+1)*sizeof(TCHAR
)); /* Copy data. */
9943 /* Keep ghPaste locked. */
9946 * If we're paste is enabled but limited to the first
9947 * line of the clipboard, prune the paste buffer...
9949 if(gPasteEnabled
== MSWIN_PASTE_LINE
9950 && (pPaste
= _tcschr(gpPasteNext
, (TCHAR
)ASCII_CR
))){
9951 *pPaste
= (TCHAR
)'\0';
9952 cbSize
= _tcslen(gpPasteNext
);
9956 * If there is a selection (gCopyCutFunction != NULL)
9957 * then delete it so that it will be replaced by
9960 if (gCopyCutFunction
!= NULL
)
9961 deleteregion (1, 0);
9963 gPasteBytesRemain
= cbSize
;
9964 gPasteWasCR
= FALSE
;
9966 if (mswin_debug
> 8)
9967 fprintf (mswin_debugfile
, "EditPaste:: Paste %d bytes\n",
9984 * Cancel an active paste operation.
9987 EditCancelPaste (void)
9989 if (ghPaste
!= NULL
) { /* Must be pasting. */
9990 GlobalUnlock (ghPaste
); /* Then Unlock... */
9991 GlobalFree (ghPaste
); /* ...and free the paste buffer. */
9992 ghPaste
= NULL
; /* Indicates no paste data. */
9993 gpPasteNext
= NULL
; /* Just being tidy. */
9994 gPasteBytesRemain
= 0; /* ditto. */
9996 if (mswin_debug
> 8)
9997 fprintf (mswin_debugfile
, "EditCancelPaste:: Free Paste Data\n");
10004 * Get the next byte from the paste buffer. If all bytes have been
10005 * retreived, free the paste buffer.
10006 * Map all CRLF sequence to a single CR.
10009 EditPasteGet (void)
10013 if (ghPaste
!= NULL
) { /* ghPaste tells if we are pasting. */
10014 if (gPasteBytesRemain
> 0) { /* Just in case... */
10015 /* Get one byte and move pointer. */
10016 b
= (TCHAR
) *gpPasteNext
++;
10017 --gPasteBytesRemain
; /* one less. */
10018 if (gPasteWasCR
&& b
== (TCHAR
)ASCII_LF
) {
10019 if (gPasteBytesRemain
) {
10021 b
= (TCHAR
) *gpPasteNext
++;
10022 --gPasteBytesRemain
;
10025 b
= NODATA
; /* Ignore last LF. */
10027 gPasteWasCR
= (b
== (TCHAR
)ASCII_CR
);
10029 if (mswin_debug
> 8)
10030 fprintf (mswin_debugfile
, "EditPasteGet:: char %c, gPasteWasCR %d, gPasteBytesRemain %d\n",
10031 b
, gPasteWasCR
, gPasteBytesRemain
);
10034 if (gPasteBytesRemain
<= 0) { /* All Done? */
10035 GlobalUnlock (ghPaste
); /* Then Unlock... */
10036 GlobalFree (ghPaste
); /* ...and free the paste buffer. */
10037 ghPaste
= NULL
; /* Indicates no paste data. */
10038 gpPasteNext
= NULL
; /* Just being tidy. */
10039 gPasteBytesRemain
= 0; /* ditto. */
10041 if (mswin_debug
> 8)
10042 fprintf (mswin_debugfile
, "EditPasteGet:: Free Paste Data\n");
10057 * Return true if Paste data is available. If gpPaste != NULL then there
10061 EditPasteAvailable (void)
10063 return (ghPaste
!= NULL
);
10069 * Select everything in the buffer
10074 if(ComposerEditing
){
10080 update (); /* And update the screen */
10086 SortHandler(int order
, int reverse
)
10088 int old
= (*gSortCallback
)(0, 0);
10091 old
^= 0x0100; /* flip reverse bit */
10092 (*gSortCallback
)(1, old
);
10095 (*gSortCallback
)(1, order
| (old
& 0x0100));
10100 FlagHandler(int index
, int args
)
10103 (void) (*gFlagCallback
)(index
+ 1, 0L);
10108 MSWHelpShow (cbstr_t fpHelpCallback
)
10110 if (fpHelpCallback
!= NULL
){
10111 char title
[256], *help
;
10113 if(help
= (*fpHelpCallback
) (title
))
10114 mswin_displaytext (title
, help
, strlen(help
), NULL
, NULL
, 0);
10122 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
10124 * Adjust the timer frequency as needed.
10126 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
10132 /* Decide on period to use. */
10133 if (gAllowMouseTrack
)
10134 period
= MY_TIMER_EXCEEDINGLY_SHORT_PERIOD
;
10136 period
= my_timer_period
;
10138 if (period
!= gTimerCurrentPeriod
) {
10139 if (SetTimer (ghTTYWnd
, MY_TIMER_ID
, period
, NULL
) == 0)
10140 MessageBox (ghTTYWnd
, TIMER_FAIL_MESSAGE
, NULL
,
10141 MB_OK
| MB_ICONINFORMATION
);
10143 gTimerCurrentPeriod
= period
;
10152 mswin_setperiodiccallback (cbvoid_t periodiccb
, long period
)
10154 if (periodiccb
!= NULL
&& period
> 0) {
10155 gPeriodicCallback
= periodiccb
;
10156 gPeriodicCBTime
= period
;
10157 gPeriodicCBTimeout
= GetTickCount () / 1000 + gPeriodicCBTime
;
10160 gPeriodicCallback
= NULL
;
10165 * Structure for variables used by mswin_exec_and_wait which need to be
10166 * freed in multiple places.
10168 typedef struct MSWIN_EXEC_DATA
{
10171 LPTSTR lptstr_whatsit
;
10172 LPTSTR lptstr_command
;
10173 LPTSTR lptstr_infile
;
10174 LPTSTR lptstr_outfile
;
10175 MSWIN_TEXTWINDOW
*mswin_tw
;
10179 mswin_exec_data_init(MSWIN_EXEC_DATA
*exec_data
)
10181 memset(exec_data
, 0, sizeof(MSWIN_EXEC_DATA
));
10182 exec_data
->infd
= INVALID_HANDLE_VALUE
;
10183 exec_data
->outfd
= INVALID_HANDLE_VALUE
;
10187 mswin_exec_data_free(MSWIN_EXEC_DATA
*exec_data
, BOOL delete_outfile
)
10189 if(exec_data
->infd
!= INVALID_HANDLE_VALUE
)
10190 CloseHandle(exec_data
->infd
);
10192 if(exec_data
->outfd
!= INVALID_HANDLE_VALUE
) {
10193 CloseHandle(exec_data
->outfd
);
10195 _tunlink(exec_data
->lptstr_outfile
);
10198 if(exec_data
->lptstr_infile
)
10199 fs_give((void **) &exec_data
->lptstr_infile
);
10200 if(exec_data
->lptstr_outfile
)
10201 fs_give((void **) &exec_data
->lptstr_outfile
);
10202 if(exec_data
->lptstr_whatsit
)
10203 fs_give((void **) &exec_data
->lptstr_whatsit
);
10204 if(exec_data
->lptstr_command
)
10205 fs_give((void **) &exec_data
->lptstr_command
);
10207 if(exec_data
->mswin_tw
) {
10209 * Set the out_file is zero. We don't need mswin_tw
10210 * to save the file anymore since we're bailing.
10212 exec_data
->mswin_tw
->out_file
= NULL
;
10215 * If the window is still open, then set the id to 0 so
10216 * mswin_tw_close_callback() will free the memory whenever
10217 * the window closes. Otherwise free it now.
10219 if(exec_data
->mswin_tw
->hwnd
)
10220 exec_data
->mswin_tw
->id
= 0;
10222 MemFree(exec_data
->mswin_tw
);
10227 * Execute command and wait for the child to exit
10229 * whatsit - description of reason exec being called
10230 * command - command to run
10231 * infile - name of file to pass as stdin
10232 * outfile - name of file to pass as stdout
10233 * exit_val - where to store return value of the process
10235 * MSWIN_EAW_CAPT_STDERR - capture stderr along with stdout
10236 * MSWIN_EAW_CTRL_C_CANCELS - if user presses ctrl-c, detach child
10237 * Returns: 0, successfully completed program
10238 * -1, errors occurred
10239 * -2, user chose to stop waiting for program before it finished
10242 mswin_exec_and_wait (char *utf8_whatsit
, char *utf8_command
,
10243 char *utf8_infile
, char *utf8_outfile
,
10244 int *exit_val
, unsigned mswe_flags
)
10249 TCHAR waitingFor
[256];
10250 PROCESS_INFORMATION proc_info
;
10252 MSWIN_EXEC_DATA exec_data
;
10254 BOOL b_use_mswin_tw
;
10257 mswin_exec_data_init(&exec_data
);
10259 memset(&proc_info
, 0, sizeof(proc_info
));
10263 exec_data
.lptstr_infile
= utf8_infile
? utf8_to_lptstr(utf8_infile
) : NULL
;
10264 exec_data
.lptstr_outfile
= utf8_outfile
? utf8_to_lptstr(utf8_outfile
) : NULL
;
10266 exec_data
.lptstr_command
= utf8_to_lptstr(utf8_command
);
10267 exec_data
.lptstr_whatsit
= utf8_to_lptstr(utf8_whatsit
);
10270 /* If the command is '.', then use mswin_tw to open the file. */
10271 b_use_mswin_tw
= utf8_command
&&
10272 utf8_command
[0] == '.' && utf8_command
[1] == '\0';
10274 if(b_use_mswin_tw
) {
10276 proc_info
.hThread
= INVALID_HANDLE_VALUE
;
10277 proc_info
.hProcess
= INVALID_HANDLE_VALUE
;
10279 exec_data
.mswin_tw
= mswin_tw_displaytext_lptstr(
10280 exec_data
.lptstr_whatsit
, exec_data
.lptstr_infile
, 4, NULL
,
10281 exec_data
.mswin_tw
, MSWIN_DT_FILLFROMFILE
);
10283 if(exec_data
.mswin_tw
) {
10284 mswin_set_readonly(exec_data
.mswin_tw
, FALSE
);
10286 /* Tell mswin_tw to write the edit contents to this file. */
10287 exec_data
.mswin_tw
->out_file
= exec_data
.lptstr_outfile
;
10289 /* Make sure mswin_tw isn't freed behind our back. */
10290 exec_data
.mswin_tw
->id
= (UINT
)-1;
10298 #endif /* ALTED_DOT */
10300 SECURITY_ATTRIBUTES atts
;
10301 STARTUPINFO start_info
;
10303 memset(&atts
, 0, sizeof(atts
));
10304 memset(&start_info
, 0, sizeof(start_info
));
10306 /* set file attributes of temp files*/
10307 atts
.nLength
= sizeof(SECURITY_ATTRIBUTES
);
10308 atts
.bInheritHandle
= TRUE
;
10309 atts
.lpSecurityDescriptor
= NULL
;
10311 /* open files if asked for */
10313 && ((exec_data
.infd
= CreateFile(exec_data
.lptstr_infile
,
10314 GENERIC_READ
, 0, &atts
,
10315 OPEN_EXISTING
, FILE_ATTRIBUTE_READONLY
, NULL
))
10316 == INVALID_HANDLE_VALUE
)){
10318 mswin_exec_data_free(&exec_data
, TRUE
);
10323 && ((exec_data
.outfd
= CreateFile(exec_data
.lptstr_outfile
,
10324 GENERIC_WRITE
, 0, &atts
,
10325 OPEN_ALWAYS
, FILE_ATTRIBUTE_NORMAL
, NULL
))
10326 == INVALID_HANDLE_VALUE
)){
10328 mswin_exec_data_free(&exec_data
, TRUE
);
10332 start_info
.dwFlags
= STARTF_FORCEONFEEDBACK
| STARTF_USESHOWWINDOW
;
10333 start_info
.wShowWindow
= (utf8_infile
|| utf8_outfile
) ? SW_SHOWMINNOACTIVE
: SW_SHOWNA
;
10335 /* set up i/o redirection */
10337 start_info
.hStdInput
= exec_data
.infd
;
10339 start_info
.hStdOutput
= exec_data
.outfd
;
10340 if(utf8_outfile
&& (mswe_flags
& MSWIN_EAW_CAPT_STDERR
))
10341 start_info
.hStdError
= exec_data
.outfd
;
10342 if(utf8_infile
|| utf8_outfile
)
10343 start_info
.dwFlags
|= STARTF_USESTDHANDLES
;
10345 brc
= CreateProcess(NULL
, exec_data
.lptstr_command
, NULL
, NULL
,
10346 (utf8_infile
|| utf8_outfile
) ? TRUE
: FALSE
,
10347 CREATE_NEW_CONSOLE
| CREATE_NEW_PROCESS_GROUP
,
10348 NULL
, NULL
, &start_info
, &proc_info
);
10352 _sntprintf(waitingFor
, sizeof(waitingFor
)/sizeof(TCHAR
),
10353 TEXT("%s is currently waiting for the %s (%s) to complete. Click \"Cancel\" to stop waiting, or \"OK\" to continue waiting."),
10354 gszAppName
, exec_data
.lptstr_whatsit
, exec_data
.lptstr_command
);
10356 if(proc_info
.hThread
!= INVALID_HANDLE_VALUE
) {
10357 /* Don't need the thread handle, close it now. */
10358 CloseHandle (proc_info
.hThread
);
10362 * Go into holding pattern until the other application terminates
10363 * or we are told to stop waiting.
10370 if(!exec_data
.mswin_tw
)
10373 exit_code
= exec_data
.mswin_tw
->hwnd
&& exec_data
.mswin_tw
->out_file
?
10377 #endif /* ALTED_DOT */
10379 if(GetExitCodeProcess(proc_info
.hProcess
, &exit_code
) == FALSE
)
10383 if(exit_code
== STILL_ACTIVE
){
10385 brc
= mswin_getmouseevent (&mouse
);
10387 if (rc
!= NODATA
||
10388 (brc
&& mouse
.event
== M_EVENT_DOWN
)) {
10389 if(mswe_flags
& MSWIN_EAW_CTRL_C_CANCELS
){
10390 if(rc
== (CTRL
|'C'))
10394 rc
= MessageBox (ghTTYWnd
, waitingFor
, exec_data
.lptstr_whatsit
,
10395 MB_ICONSTOP
| MB_OKCANCEL
);
10398 if (rc
== IDCANCEL
){
10399 /* terminate message to child ? */
10400 mswin_exec_data_free(&exec_data
, TRUE
);
10406 if(proc_info
.hProcess
!= INVALID_HANDLE_VALUE
) {
10407 /* do something about child's exit status */
10408 CloseHandle (proc_info
.hProcess
);
10411 *exit_val
= exit_code
;
10416 if (gpTTYInfo
->fMinimized
)
10417 ShowWindow (ghTTYWnd
, SW_SHOWNORMAL
);
10420 * If we're using a mswin_tw and we're not capturing the output, we
10421 * just bailed immediately. If that's the case, don't bring the main
10422 * window up over the top of the textwindow we just brought up.
10425 if(!b_use_mswin_tw
|| !exec_data
.mswin_tw
|| exec_data
.mswin_tw
->out_file
)
10426 #endif /* ALTED_DOT */
10427 BringWindowToTop (ghTTYWnd
);
10429 mswin_exec_data_free(&exec_data
, FALSE
);
10433 mswin_exec_data_free(&exec_data
, TRUE
);
10434 return((rc
= (int) GetLastError()) ? rc
: -1); /* hack */
10443 mswin_shell_exec(char *command_utf8
, HINSTANCE
*pChildProc
)
10446 SHELLEXECUTEINFO shell_info
;
10447 LPTSTR command_lpt
, free_command_lpt
;
10448 LPTSTR p
, q
, parm
= NULL
;
10454 free_command_lpt
= command_lpt
= utf8_to_lptstr(command_utf8
);
10461 * Pick first arg apart by whitespace until what's to the left
10462 * is no longer a valid path/file. Everything else is then an
10463 * command line arg...
10465 if(*(p
= command_lpt
) == '\"'){
10466 p
= ++command_lpt
; /* don't include quote */
10472 if(!quoted
&& _istspace(*p
)){
10476 buf_utf8
= lptstr_to_utf8(buf
);
10477 if(*buf
== '*' || (buf_utf8
&& fexist(buf_utf8
, "x", (off_t
*) NULL
) == FIOSUC
)){
10480 fs_give((void **) &buf_utf8
);
10486 fs_give((void **) &buf_utf8
);
10488 else if(quoted
&& *p
== '\"'){
10492 else if(!(*q
++ = *p
++)){
10497 if(*command_lpt
&& parm
){
10500 while(*parm
&& _istspace((unsigned char) *parm
));
10504 * HACK -- since star is very unlikely to actually appear
10505 * in a command name thats launched via a shell command line,
10506 * a leading one indicates special handling.
10508 if(command_lpt
[0] == '*'){
10509 if(!_tcsncmp(command_lpt
+ 1, TEXT("Shell*"), 8)){
10510 /* Leave it to ShellExecute magic to "open" the thing */
10511 command_lpt
= parm
;
10517 if(free_command_lpt
)
10518 fs_give((void **) &free_command_lpt
);
10523 memset(&shell_info
, 0, sizeof(SHELLEXECUTEINFO
));
10524 shell_info
.cbSize
= sizeof(SHELLEXECUTEINFO
);
10525 shell_info
.fMask
= SEE_MASK_DOENVSUBST
10526 | SEE_MASK_NOCLOSEPROCESS
10527 | SEE_MASK_FLAG_DDEWAIT
;
10528 shell_info
.hwnd
= ghTTYWnd
;
10529 shell_info
.lpFile
= command_lpt
;
10530 shell_info
.lpParameters
= parm
;
10531 shell_info
.lpDirectory
= NULL
; /* default is current directory */
10532 shell_info
.nShow
= SW_SHOWNORMAL
;
10534 ShellExecuteEx(&shell_info
);
10536 if((int)(LONG_PTR
)shell_info
.hInstApp
> 32){
10538 *pChildProc
= shell_info
.hProcess
;
10540 if(free_command_lpt
)
10541 fs_give((void **) &free_command_lpt
);
10543 return(0); /* success! */
10546 if(free_command_lpt
)
10547 fs_give((void **) &free_command_lpt
);
10554 * Generate an error message for a failed windows exec or loadlibrary.
10557 mswin_exec_err_msg(char *what
, int status
, char *buf
, size_t buflen
)
10562 snprintf(buf
, buflen
, "%s not found.", what
);
10566 snprintf(buf
, buflen
, "Not enough memory to run %s.", what
);
10570 snprintf(buf
, buflen
, "Error %d starting %s.", status
, what
);
10577 mswin_set_quit_confirm (int confirm
)
10579 gConfirmExit
= (confirm
!= 0);
10585 * Called when Windows is in shutting down. Before actually shutting down
10586 * Windows goes around to all the applications and asks if it is OK with
10587 * them to shut down (WM_QUERYENDSESSION).
10588 * If gConfirmExit is set, ask the user if they want to exit.
10589 * Returning zero will stop the shutdown, non-zero allows it to proceed.
10598 _sntprintf(msg
, sizeof(msg
)/sizeof(TCHAR
),
10599 TEXT("Exiting may cause you to lose work in %s, Exit?"),
10601 rc
= MessageBox (ghTTYWnd
, msg
, gszAppName
, MB_ICONSTOP
| MB_OKCANCEL
);
10610 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
10612 * Registry access functions
10614 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
10619 #define MSWR_KEY_MAX 128
10620 #define MSWR_VAL_MAX 128
10621 #define MSWR_CLASS_MAX 128
10622 #define MSWR_DATA_MAX 1024
10625 #define MSWR_ROOT TEXT("Software\\University of Washington\\Alpine\\1.0")
10626 #define MSWR_CAPABILITIES TEXT("Software\\University of Washington\\Alpine\\1.0\\Capabilities")
10627 #define MSWR_APPNAME TEXT("Alpine")
10628 #define MSWR_DLLPATH TEXT("DLLPath")
10629 #define MSWR_DLLNAME TEXT("pmapi32.dll")
10630 #define MSWRDBUF 1152
10633 struct mswin_reg_key
{
10634 HKEY rhk
; /* root key (HKEY_LOCAL_MACHINE, ...) */
10635 LPTSTR
*knames
; /* NULL terminated list of keys */
10638 LPTSTR mswin_pine_hklm_regs
[] = {
10640 TEXT("Software\\Clients\\Mail\\Alpine"),
10641 TEXT("Software\\Clients\\News\\Alpine"),
10642 TEXT("Software\\Classes\\Alpine.Url.Mailto"),
10643 TEXT("Software\\Classes\\Alpine.Url.News"),
10644 TEXT("Software\\Classes\\Alpine.Url.Nntp"),
10645 TEXT("Software\\Classes\\Alpine.Url.Imap"),
10649 LPTSTR mswin_pine_hkcu_regs
[] = {
10654 static struct mswin_reg_key mswin_pine_regs
[] = {
10655 {HKEY_LOCAL_MACHINE
, mswin_pine_hklm_regs
},
10656 {HKEY_CURRENT_USER
, mswin_pine_hkcu_regs
},
10662 * data: unitialized buffer, could be null
10665 mswin_reg(int op
, int tree
, char *data_utf8
, size_t size
)
10667 LPTSTR data_lptstr
= NULL
;
10672 /* size is zero when op & MSWR_OP_SET */
10673 data_lptstr
= utf8_to_lptstr(data_utf8
);
10676 data_lptstr
= (LPTSTR
)MemAlloc(size
* sizeof(TCHAR
));
10677 data_lptstr
[0] = '\0';
10681 rv
= mswin_reg_lptstr(op
, tree
, data_lptstr
, size
);
10683 if(data_utf8
&& data_lptstr
){
10686 t_utf8str
= lptstr_to_utf8(data_lptstr
);
10687 strncpy(data_utf8
, t_utf8str
, size
);
10688 data_utf8
[size
-1] = '\0';
10689 MemFree((void *)t_utf8str
);
10691 MemFree((void *)data_lptstr
);
10697 mswin_reg_lptstr(int op
, int tree
, LPTSTR data_lptstr
, size_t size
)
10699 if(op
& MSWR_OP_SET
){
10701 case MSWR_PINE_RC
:
10702 MSWRAlpineSet(HKEY_CURRENT_USER
, NULL
,
10703 TEXT("PineRC"), op
& MSWR_OP_FORCE
, data_lptstr
);
10706 case MSWR_PINE_CONF
:
10707 MSWRAlpineSet(HKEY_CURRENT_USER
, NULL
,
10708 TEXT("PineConf"), op
& MSWR_OP_FORCE
, data_lptstr
);
10711 case MSWR_PINE_AUX
:
10712 MSWRAlpineSet(HKEY_CURRENT_USER
, NULL
,
10713 TEXT("PineAux"), op
& MSWR_OP_FORCE
, data_lptstr
);
10716 case MSWR_PINE_DIR
:
10717 MSWRAlpineSet(HKEY_LOCAL_MACHINE
, NULL
,
10718 TEXT("Pinedir"), op
& MSWR_OP_FORCE
, data_lptstr
);
10719 MSWRAlpineSetHandlers(op
& MSWR_OP_FORCE
, data_lptstr
);
10722 case MSWR_PINE_EXE
:
10723 MSWRAlpineSet(HKEY_LOCAL_MACHINE
, NULL
,
10724 TEXT("PineEXE"), op
& MSWR_OP_FORCE
, data_lptstr
);
10727 case MSWR_PINE_POS
:
10728 MSWRAlpineSet(HKEY_CURRENT_USER
, NULL
,
10729 TEXT("PinePos"), op
& MSWR_OP_FORCE
, data_lptstr
);
10736 else if(op
& MSWR_OP_GET
){
10738 case MSWR_PINE_RC
:
10739 return(MSWRAlpineGet(HKEY_CURRENT_USER
, NULL
,
10740 TEXT("PineRC"), data_lptstr
, size
));
10741 case MSWR_PINE_CONF
:
10742 return(MSWRAlpineGet(HKEY_CURRENT_USER
, NULL
,
10743 TEXT("PineConf"), data_lptstr
, size
));
10744 case MSWR_PINE_AUX
:
10745 return(MSWRAlpineGet(HKEY_CURRENT_USER
, NULL
,
10746 TEXT("PineAux"), data_lptstr
, size
));
10747 case MSWR_PINE_DIR
:
10748 return(MSWRAlpineGet(HKEY_LOCAL_MACHINE
, NULL
,
10749 TEXT("Pinedir"), data_lptstr
, size
));
10750 case MSWR_PINE_EXE
:
10751 return(MSWRAlpineGet(HKEY_LOCAL_MACHINE
, NULL
,
10752 TEXT("PineEXE"), data_lptstr
, size
));
10753 case MSWR_PINE_POS
:
10754 return(MSWRAlpineGet(HKEY_CURRENT_USER
, NULL
,
10755 TEXT("PinePos"), data_lptstr
, size
));
10760 else if(op
& MSWR_OP_BLAST
){
10763 for(i
= 0; mswin_pine_regs
[i
].rhk
; i
++){
10764 for(j
= 0; mswin_pine_regs
[i
].knames
[j
]; j
++)
10765 MSWRClear(mswin_pine_regs
[i
].rhk
, mswin_pine_regs
[i
].knames
[j
]);
10769 /* else, ignore unknown op? */
10776 MSWRAlpineSet(HKEY hRootKey
, LPTSTR subkey
, LPTSTR val
, int update
, LPTSTR data
)
10779 TCHAR keybuf
[MSWR_KEY_MAX
+1];
10781 _sntprintf(keybuf
, MSWR_KEY_MAX
+1, TEXT("%s%s%s"), MSWR_ROOT
,
10782 (subkey
&& *subkey
!= '\\') ? TEXT("\\") : TEXT(""),
10783 (subkey
) ? TEXT("\\") : TEXT(""));
10785 if(RegCreateKeyEx(hRootKey
, keybuf
, 0, TEXT("REG_SZ"),
10786 REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
,
10787 NULL
, &hKey
, NULL
) == ERROR_SUCCESS
){
10788 if(update
|| RegQueryValueEx(hKey
, val
, NULL
, NULL
,
10789 NULL
, NULL
) != ERROR_SUCCESS
)
10790 RegSetValueEx(hKey
, val
, 0, REG_SZ
, (LPBYTE
)data
, (DWORD
)(_tcslen(data
)+1)*sizeof(TCHAR
));
10799 MSWRAlpineGet(HKEY hKey
, LPTSTR subkey
, LPTSTR val
, LPTSTR data_lptstr
, size_t len
)
10801 TCHAR keybuf
[MSWR_KEY_MAX
+1];
10802 DWORD dlen
= (DWORD
)len
;
10804 _sntprintf(keybuf
, MSWR_KEY_MAX
+1, TEXT("%s%s%s"), MSWR_ROOT
,
10805 (subkey
&& *subkey
!= '\\') ? TEXT("\\") : TEXT(""),
10806 (subkey
) ? TEXT("\\") : TEXT(""));
10808 return(MSWRPeek(hKey
, keybuf
, val
, data_lptstr
, &dlen
) == TRUE
);
10814 MSWRAlpineSetHandlers(int update
, LPTSTR path_lptstr
)
10816 HKEY hKey
, hSubKey
;
10818 BYTE tmp_b
[MSWR_DATA_MAX
];
10819 unsigned long tmplen
= MSWR_DATA_MAX
, tmp_lptstr_tcharlen
= MSWR_DATA_MAX
/sizeof(TCHAR
);
10821 LPTSTR tmp_lptstr
= (LPTSTR
)tmp_b
;
10823 /* Register as a mail client on this system */
10824 if(RegOpenKeyEx(HKEY_LOCAL_MACHINE
,
10825 MSWR_ROOT
, 0, KEY_ALL_ACCESS
,
10826 &hKey
) == ERROR_SUCCESS
){
10827 if(RegCreateKeyEx(HKEY_LOCAL_MACHINE
, MSWR_CAPABILITIES
, 0, TEXT("REG_SZ"),
10828 REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
,
10829 NULL
, &hSubKey
, &dwDisp
) == ERROR_SUCCESS
){
10830 MSWRPoke(hSubKey
, NULL
, TEXT("ApplicationDescription"),
10831 TEXT("Alpine - A program for sending, receiving, and filing email and news, whether stored locally or accessed over the network via IMAP, POP3, or NNTP. Alpine is the successor to Pine, and also is maintained by the University of Washington."));
10832 MSWRPoke(hSubKey
, NULL
, TEXT("ApplicationName"),
10834 _sntprintf(tmp_lptstr
, tmp_lptstr_tcharlen
, TEXT("%salpine.exe,0"), path_lptstr
);
10835 MSWRPoke(hSubKey
, NULL
, TEXT("ApplicationIcon"), tmp_lptstr
);
10836 MSWRPoke(hSubKey
, TEXT("UrlAssociations"), TEXT("mailto"), TEXT("Alpine.Url.Mailto"));
10837 MSWRPoke(hSubKey
, TEXT("UrlAssociations"), TEXT("news"), TEXT("Alpine.Url.News"));
10838 MSWRPoke(hSubKey
, TEXT("UrlAssociations"), TEXT("nntp"), TEXT("Alpine.Url.Nntp"));
10839 MSWRPoke(hSubKey
, TEXT("UrlAssociations"), TEXT("imap"), TEXT("Alpine.Url.Imap"));
10840 RegCloseKey(hSubKey
);
10843 if(RegOpenKeyEx(HKEY_LOCAL_MACHINE
, TEXT("Software\\RegisteredApplications"), 0,
10844 KEY_ALL_ACCESS
, &hKey
) == ERROR_SUCCESS
){
10845 MSWRPoke(hKey
, NULL
, TEXT("Alpine"), MSWR_CAPABILITIES
);
10848 if(RegOpenKeyEx(HKEY_LOCAL_MACHINE
,
10849 TEXT("Software\\Classes"), 0, KEY_ALL_ACCESS
, &hKey
) == ERROR_SUCCESS
){
10850 if(RegCreateKeyEx(hKey
, TEXT("Alpine.Url.Mailto"), 0, TEXT("REG_SZ"),
10851 REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
,
10852 NULL
, &hSubKey
, &dwDisp
) == ERROR_SUCCESS
){
10853 MSWRProtocolSet(hSubKey
, MSWR_SDC_MAIL
, path_lptstr
);
10854 RegCloseKey(hSubKey
);
10856 if(RegCreateKeyEx(hKey
, TEXT("Alpine.Url.Nntp"), 0, TEXT("REG_SZ"),
10857 REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
,
10858 NULL
, &hSubKey
, &dwDisp
) == ERROR_SUCCESS
){
10859 MSWRProtocolSet(hSubKey
, MSWR_SDC_NNTP
, path_lptstr
);
10860 RegCloseKey(hSubKey
);
10862 if(RegCreateKeyEx(hKey
, TEXT("Alpine.Url.News"), 0, TEXT("REG_SZ"),
10863 REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
,
10864 NULL
, &hSubKey
, &dwDisp
) == ERROR_SUCCESS
){
10865 MSWRProtocolSet(hSubKey
, MSWR_SDC_NEWS
, path_lptstr
);
10866 RegCloseKey(hSubKey
);
10868 if(RegCreateKeyEx(hKey
, TEXT("Alpine.Url.Imap"), 0, TEXT("REG_SZ"),
10869 REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
,
10870 NULL
, &hSubKey
, &dwDisp
) == ERROR_SUCCESS
){
10871 MSWRProtocolSet(hSubKey
, MSWR_SDC_IMAP
, path_lptstr
);
10872 RegCloseKey(hSubKey
);
10878 if((exists
= RegOpenKeyEx(HKEY_LOCAL_MACHINE
,
10879 TEXT("SOFTWARE\\Clients\\Mail\\Alpine"),
10880 0, KEY_ALL_ACCESS
, &hKey
) == ERROR_SUCCESS
)
10881 || RegCreateKeyEx(HKEY_LOCAL_MACHINE
,
10882 TEXT("SOFTWARE\\Clients\\Mail\\Alpine"),
10884 REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
,
10885 NULL
, &hKey
, &dwDisp
) == ERROR_SUCCESS
){
10886 if(update
|| !exists
){
10888 char *tmp_utf8str
= NULL
;
10890 MSWRPoke(hKey
, NULL
, NULL
, MSWR_APPNAME
);
10891 /* set up MAPI dll stuff */
10893 RegQueryValueEx(hKey
, MSWR_DLLPATH
, NULL
, &dType
, tmp_b
, &tmplen
);
10894 tmp_lptstr
= (LPTSTR
)tmp_b
;
10896 || (can_access(tmp_utf8str
= lptstr_to_utf8(tmp_lptstr
), ACCESS_EXISTS
) != 0)){
10898 RegDeleteValue(hKey
, MSWR_DLLPATH
);
10900 MemFree((void *)tmp_utf8str
);
10902 _sntprintf(tmp_lptstr
, tmp_lptstr_tcharlen
,
10903 TEXT("%s%s"), path_lptstr
, MSWR_DLLNAME
);
10905 if(can_access(tmp_utf8str
= lptstr_to_utf8(tmp_lptstr
), ACCESS_EXISTS
) == 0)
10906 MSWRPoke(hKey
, NULL
, MSWR_DLLPATH
, tmp_lptstr
);
10909 MemFree((void *)tmp_utf8str
);
10910 /* Set "mailto" handler */
10911 if(RegCreateKeyEx(hKey
, TEXT("Protocols\\Mailto"), 0, TEXT("REG_SZ"),
10912 REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
,
10913 NULL
, &hSubKey
, &dwDisp
) == ERROR_SUCCESS
){
10914 MSWRProtocolSet(hSubKey
, MSWR_SDC_MAIL
, path_lptstr
);
10915 RegCloseKey(hSubKey
);
10918 /* Set normal handler */
10919 _sntprintf(tmp_lptstr
, tmp_lptstr_tcharlen
,
10920 TEXT("\"%salpine.exe\""), path_lptstr
);
10921 MSWRPoke(hKey
, TEXT("shell\\open\\command"), NULL
, tmp_lptstr
);
10927 /* Register as a news client on this system */
10928 if((exists
= RegOpenKeyEx(HKEY_LOCAL_MACHINE
,
10929 TEXT("SOFTWARE\\Clients\\News\\Alpine"),
10930 0, KEY_ALL_ACCESS
, &hKey
) == ERROR_SUCCESS
)
10931 || RegCreateKeyEx(HKEY_LOCAL_MACHINE
,
10932 TEXT("SOFTWARE\\Clients\\News\\Alpine"),
10933 0, TEXT("REG_SZ"), REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
,
10934 NULL
, &hKey
, &dwDisp
) == ERROR_SUCCESS
){
10935 if(update
|| !exists
){
10936 MSWRPoke(hKey
, NULL
, NULL
, MSWR_APPNAME
);
10938 /* Set "news" handler */
10939 if(RegCreateKeyEx(hKey
, TEXT("Protocols\\news"), 0, TEXT("REG_SZ"),
10940 REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
,
10941 NULL
, &hSubKey
, &dwDisp
) == ERROR_SUCCESS
){
10942 MSWRProtocolSet(hSubKey
, MSWR_SDC_NEWS
, path_lptstr
);
10943 RegCloseKey(hSubKey
);
10945 /* Set "nntp" handler */
10946 if(RegCreateKeyEx(hKey
, TEXT("Protocols\\nntp"), 0, TEXT("REG_SZ"),
10947 REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
,
10948 NULL
, &hSubKey
, &dwDisp
) == ERROR_SUCCESS
){
10949 MSWRProtocolSet(hSubKey
, MSWR_SDC_NNTP
, path_lptstr
);
10950 RegCloseKey(hSubKey
);
10953 /* Set normal handler */
10954 _sntprintf(tmp_lptstr
, tmp_lptstr_tcharlen
,
10955 TEXT("\"%salpine.exe\""), path_lptstr
);
10956 MSWRPoke(hKey
, TEXT("shell\\open\\command"), NULL
, tmp_lptstr
);
10962 /* Register as a IMAP url handler */
10963 if((exists
= RegOpenKeyEx(HKEY_CLASSES_ROOT
, TEXT("imap"),
10964 0, KEY_ALL_ACCESS
, &hKey
) == ERROR_SUCCESS
)
10965 || RegCreateKeyEx(HKEY_CLASSES_ROOT
, TEXT("imap"), 0, TEXT("REG_SZ"),
10966 REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
,
10967 NULL
, &hKey
, &dwDisp
) == ERROR_SUCCESS
){
10968 if(update
|| !exists
)
10969 MSWRProtocolSet(hKey
, MSWR_SDC_IMAP
, path_lptstr
);
10978 mswin_reg_default_browser(char *url_utf8
)
10980 TCHAR scheme
[MSWR_KEY_MAX
+1], *p
;
10982 char cmdbuf
[MSWR_DATA_MAX
], *cmd
= NULL
;
10984 url_lptstr
= utf8_to_lptstr(url_utf8
);
10986 if(url_lptstr
&& (p
= _tcschr(url_lptstr
, ':')) && p
- url_lptstr
< MSWR_KEY_MAX
){
10987 _tcsncpy(scheme
, url_lptstr
, p
- url_lptstr
);
10988 scheme
[p
-url_lptstr
] = '\0';
10990 if(MSWRShellCanOpen(scheme
, cmdbuf
, MSWR_DATA_MAX
, 0)){
10993 len
= strlen(cmdbuf
) + 2;
10994 cmd
= (char *) fs_get((len
+1) * sizeof(char));
10996 if(strchr(cmdbuf
, '*'))
10997 snprintf(cmd
, len
+1, "\"%s\"", cmdbuf
);
10999 strncpy(cmd
, cmdbuf
, len
);
11006 MemFree((void *)url_lptstr
);
11013 mswin_is_def_client(int type
)
11015 TCHAR buf
[MSWR_KEY_MAX
+1];
11016 DWORD buflen
= MSWR_KEY_MAX
;
11018 if(type
!= MSWR_SDC_MAIL
&& type
!= MSWR_SDC_NEWS
)
11021 if(MSWRPeek(HKEY_CURRENT_USER
,
11022 type
== MSWR_SDC_MAIL
? TEXT("Software\\Clients\\Mail")
11023 : TEXT("Software\\Clients\\News"), NULL
,
11024 buf
, &buflen
) && !_tcscmp(buf
, TEXT("Alpine")))
11026 buflen
= MSWR_KEY_MAX
;
11027 if(MSWRPeek(HKEY_LOCAL_MACHINE
,
11028 type
== MSWR_SDC_MAIL
? TEXT("Software\\Clients\\Mail")
11029 : TEXT("Software\\Clients\\News"), NULL
,
11030 buf
, &buflen
) && !_tcscmp(buf
, TEXT("Alpine")))
11036 mswin_set_def_client(int type
)
11039 int successful_set
= 0;
11040 TCHAR path_lptstr
[MSWR_DATA_MAX
];
11043 if(type
!= MSWR_SDC_MAIL
&& type
!= MSWR_SDC_NEWS
)
11045 if(RegOpenKeyEx(HKEY_CURRENT_USER
,
11046 type
== MSWR_SDC_MAIL
? TEXT("Software\\Clients\\Mail")
11047 : TEXT("Software\\Clients\\News"),
11048 0, KEY_ALL_ACCESS
, &hKey
) == ERROR_SUCCESS
){
11049 successful_set
= MSWRPoke(hKey
, NULL
, NULL
, TEXT("Alpine"));
11052 else if(RegOpenKeyEx(HKEY_LOCAL_MACHINE
,
11053 type
== MSWR_SDC_MAIL
? TEXT("Software\\Clients\\Mail")
11054 : TEXT("Software\\Clients\\News"),
11055 0, KEY_ALL_ACCESS
, &hKey
) == ERROR_SUCCESS
){
11056 successful_set
= MSWRPoke(hKey
, NULL
, NULL
, TEXT("Alpine"));
11059 if(successful_set
){
11060 mswin_reg_lptstr(MSWR_OP_GET
, MSWR_PINE_DIR
, path_lptstr
, sizeof(path_lptstr
)/sizeof(TCHAR
));
11061 if(type
== MSWR_SDC_MAIL
){
11062 MSWRClear(HKEY_CLASSES_ROOT
, TEXT("mailto"));
11063 if(RegCreateKeyEx(HKEY_CLASSES_ROOT
, TEXT("mailto"), 0, TEXT("REG_SZ"),
11064 REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
,
11065 NULL
, &hKey
, &dwDisp
) == ERROR_SUCCESS
){
11066 MSWRProtocolSet(hKey
, MSWR_SDC_MAIL
, path_lptstr
);
11070 else if(type
== MSWR_SDC_NEWS
){
11071 MSWRClear(HKEY_CLASSES_ROOT
, TEXT("news"));
11072 if(RegCreateKeyEx(HKEY_CLASSES_ROOT
, TEXT("news"), 0, TEXT("REG_SZ"),
11073 REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
,
11074 NULL
, &hKey
, &dwDisp
) == ERROR_SUCCESS
){
11075 MSWRProtocolSet(hKey
, MSWR_SDC_NEWS
, path_lptstr
);
11078 MSWRClear(HKEY_CLASSES_ROOT
, TEXT("nntp"));
11079 if(RegCreateKeyEx(HKEY_CLASSES_ROOT
, TEXT("nntp"), 0, TEXT("REG_SZ"),
11080 REG_OPTION_NON_VOLATILE
, KEY_ALL_ACCESS
,
11081 NULL
, &hKey
, &dwDisp
) == ERROR_SUCCESS
){
11082 MSWRProtocolSet(hKey
, MSWR_SDC_NNTP
, path_lptstr
);
11091 MSWRProtocolSet(HKEY hKey
, int type
, LPTSTR path_lptstr
)
11093 TCHAR tmp_lptstr
[MSWR_DATA_MAX
];
11095 unsigned long tmp_lptstr_len
= MSWR_DATA_MAX
;
11097 if(type
!= MSWR_SDC_MAIL
&& type
!= MSWR_SDC_NEWS
11098 && type
!= MSWR_SDC_NNTP
&& type
!= MSWR_SDC_IMAP
)
11100 MSWRPoke(hKey
, NULL
, NULL
, type
== MSWR_SDC_MAIL
11101 ? TEXT("URL:MailTo Protocol")
11102 : type
== MSWR_SDC_NEWS
? TEXT("URL:News Protocol")
11103 : type
== MSWR_SDC_NNTP
? TEXT("URL:NNTP Protocol")
11104 : TEXT("URL:IMAP Prototcol"));
11105 MSWRPoke(hKey
, NULL
, TEXT("URL Protocol"), TEXT(""));
11107 EditFlags
[0] = 0x02;
11108 EditFlags
[1] = EditFlags
[2] = EditFlags
[3] = 0;
11110 (void) RegDeleteValue(hKey
, TEXT("EditFlags"));
11111 (void) RegSetValueEx(hKey
, TEXT("EditFlags"), 0, REG_BINARY
,
11112 EditFlags
, (DWORD
) 4);
11114 _sntprintf(tmp_lptstr
, tmp_lptstr_len
,
11115 TEXT("%salpine.exe,0"), path_lptstr
);
11116 MSWRPoke(hKey
, TEXT("DefaultIcon"), NULL
, tmp_lptstr
);
11118 _sntprintf(tmp_lptstr
, tmp_lptstr_len
,
11119 TEXT("\"%salpine.exe\" -url \"%%1\""), path_lptstr
);
11120 MSWRPoke(hKey
, TEXT("shell\\open\\command"), NULL
, tmp_lptstr
);
11125 /* cmdbuf can stay char * since it's our string */
11127 MSWRShellCanOpen(LPTSTR key
, char *cmdbuf
, int clen
, int allow_noreg
)
11132 /* See if Shell provides a method to open the thing... */
11133 if(RegOpenKeyEx(HKEY_CLASSES_ROOT
, key
,
11134 0, KEY_READ
, &hKey
) == ERROR_SUCCESS
){
11137 strncpy(cmdbuf
, "*Shell*", clen
);
11138 cmdbuf
[clen
-1] = '\0';
11145 else if(allow_noreg
&& cmdbuf
){
11146 strncpy(cmdbuf
, "*Shell*", clen
);
11147 cmdbuf
[clen
-1] = '\0';
11156 * Fundamental registry access function that queries for particular values.
11159 MSWRPeek(HKEY hRootKey
, LPTSTR subkey
, LPTSTR valstr
, LPTSTR data_lptstr
, DWORD
*dlen
)
11162 DWORD dtype
, dlen_bytes
= (dlen
? *dlen
: 0) * sizeof(TCHAR
);
11163 LONG rv
= !ERROR_SUCCESS
;
11165 if(RegOpenKeyEx(hRootKey
, subkey
, 0, KEY_READ
, &hKey
) == ERROR_SUCCESS
){
11166 rv
= RegQueryValueEx(hKey
, valstr
, NULL
, &dtype
, (LPBYTE
)data_lptstr
, &dlen_bytes
);
11168 (*dlen
) = dlen_bytes
;
11172 return(rv
== ERROR_SUCCESS
);
11177 * Fundamental registry access function that sets particular values.
11180 MSWRPoke(HKEY hKey
, LPTSTR subkey
, LPTSTR valstr
, LPTSTR data_lptstr
)
11182 DWORD dtype
, dwDisp
, dlen
= MSWR_DATA_MAX
;
11183 BYTE olddata
[MSWR_DATA_MAX
];
11187 || RegCreateKeyEx(hKey
, subkey
,
11188 0, TEXT("REG_SZ"), REG_OPTION_NON_VOLATILE
,
11189 KEY_ALL_ACCESS
, NULL
,
11190 &hKey
, &dwDisp
) == ERROR_SUCCESS
){
11192 if(RegQueryValueEx(hKey
, valstr
, NULL
, &dtype
,
11193 olddata
, &dlen
) != ERROR_SUCCESS
11194 || _tcscmp((LPTSTR
)olddata
, data_lptstr
)){
11195 (void) RegDeleteValue(hKey
, valstr
);
11196 rv
= RegSetValueEx(hKey
, valstr
, 0, REG_SZ
,
11197 (LPBYTE
)data_lptstr
,
11198 (DWORD
)(_tcslen(data_lptstr
) + 1)*sizeof(TCHAR
)) == ERROR_SUCCESS
;
11210 MSWRLineBufAdd(MSWR_LINE_BUFFER_S
*lpLineBuf
, LPTSTR line
)
11212 if(lpLineBuf
->offset
>= lpLineBuf
->size
){
11213 /* this probably won't happen, but just in case */
11214 lpLineBuf
->size
*= 2;
11215 lpLineBuf
->linep
= (char **)MemRealloc(lpLineBuf
->linep
,
11216 (lpLineBuf
->size
+ 1)*sizeof(char *));
11219 lpLineBuf
->linep
[lpLineBuf
->offset
++] = lptstr_to_utf8(line
);
11220 lpLineBuf
->linep
[lpLineBuf
->offset
] = NULL
;
11224 * Dump all of the registry values from a list of keys into an array
11225 * of UTF8-formatted strings.
11228 mswin_reg_dump(void)
11230 MSWR_LINE_BUFFER_S lineBuf
;
11231 unsigned long initial_size
= 256;
11234 lineBuf
.linep
= (char **)MemAlloc((initial_size
+1)*sizeof(char *));
11235 lineBuf
.size
= initial_size
;
11236 lineBuf
.offset
= 0;
11238 MSWRLineBufAdd(&lineBuf
, TEXT("Registry values for Alpine:"));
11239 MSWRLineBufAdd(&lineBuf
, TEXT(""));
11241 for(i
= 0; mswin_pine_regs
[i
].rhk
; i
++){
11242 MSWRLineBufAdd(&lineBuf
, mswin_pine_regs
[i
].rhk
== HKEY_LOCAL_MACHINE
11243 ? TEXT("HKEY_LOCAL_MACHINE")
11244 : TEXT("HKEY_CURRENT_USER"));
11245 for(j
= 0; mswin_pine_regs
[i
].knames
[j
]; j
++)
11246 MSWRDump(mswin_pine_regs
[i
].rhk
,
11247 mswin_pine_regs
[i
].knames
[j
],
11251 return(lineBuf
.linep
);
11256 * Recursive function to crawl a registry hierarchy and print the contents.
11261 MSWRDump(HKEY hKey
, LPTSTR pSubKey
, int keyDepth
, MSWR_LINE_BUFFER_S
*lpLineBuf
)
11264 TCHAR KeyBuf
[MSWR_KEY_MAX
+1];
11265 TCHAR ValBuf
[MSWR_VAL_MAX
+1];
11266 BYTE DataBuf
[MSWR_DATA_MAX
+1];
11267 DWORD dwKeyIndex
, dwKeyLen
;
11268 DWORD dwValIndex
, dwValLen
, dwDataLen
;
11270 FILETIME ftKeyTime
;
11271 TCHAR new_buf
[1024];
11272 unsigned int new_buf_len
= 1024;
11273 int i
, j
, k
, tab_width
= 4;
11275 /* open the passed subkey */
11276 if(RegOpenKeyEx(hKey
, pSubKey
, 0,
11277 KEY_READ
, &hSubKey
) == ERROR_SUCCESS
){
11279 /* print out key name here */
11280 for(i
= 0, k
= 0; i
< keyDepth
% 8; i
++)
11281 for(j
= 0; j
< tab_width
; j
++)
11282 new_buf
[k
++] = ' ';
11283 _sntprintf(new_buf
+k
, new_buf_len
- k
, TEXT("%s"), pSubKey
);
11284 new_buf
[new_buf_len
- 1] = '\0';
11285 MSWRLineBufAdd(lpLineBuf
, new_buf
);
11289 /* Loop through the string values and print their data */
11290 for(dwValIndex
= 0L, dwValLen
= MSWR_VAL_MAX
+ 1, dwDataLen
= MSWR_DATA_MAX
+ 1;
11291 RegEnumValue(hSubKey
, dwValIndex
, ValBuf
, &dwValLen
, NULL
, &dwType
,
11292 DataBuf
, &dwDataLen
) == ERROR_SUCCESS
;
11293 dwValIndex
++, dwValLen
= MSWR_VAL_MAX
+ 1, dwDataLen
= MSWR_DATA_MAX
+ 1){
11295 /* print out value here */
11296 for(i
= 0, k
= 0; i
< keyDepth
% 8; i
++)
11297 for(j
= 0; j
< tab_width
; j
++)
11298 new_buf
[k
++] = ' ';
11299 _sntprintf(new_buf
+k
, new_buf_len
- k
,
11300 TEXT("%.*s = %.*s"),
11301 dwValLen
? dwValLen
: 128,
11302 dwValLen
? ValBuf
: TEXT("(Default)"),
11303 dwType
== REG_SZ
&& dwDataLen
? dwDataLen
/sizeof(TCHAR
) : 128,
11305 ? (dwDataLen
? (LPTSTR
)DataBuf
: TEXT("(No data)"))
11306 : TEXT("(Some non-string data)")));
11307 new_buf
[new_buf_len
- 1] = '\0';
11308 MSWRLineBufAdd(lpLineBuf
, new_buf
);
11311 /* Loop through the subkeys and recursively print their data */
11312 for(dwKeyIndex
= 0L, dwKeyLen
= MSWR_KEY_MAX
+ 1;
11313 RegEnumKeyEx(hSubKey
, dwKeyIndex
, KeyBuf
, &dwKeyLen
,
11314 NULL
, NULL
, NULL
, &ftKeyTime
) == ERROR_SUCCESS
;
11315 dwKeyIndex
++, dwKeyLen
= MSWR_KEY_MAX
+ 1){
11316 MSWRDump(hSubKey
, KeyBuf
, keyDepth
, lpLineBuf
);
11320 /* Couldn't open the key. Must not be defined. */
11321 for(i
= 0, k
= 0; i
< keyDepth
% 8; i
++)
11322 for(j
= 0; j
< tab_width
; j
++)
11323 new_buf
[k
++] = ' ';
11324 _sntprintf(new_buf
+k
, new_buf_len
- k
, TEXT("%s - Not Defined"), pSubKey
);
11325 new_buf
[new_buf_len
- 1] = '\0';
11326 MSWRLineBufAdd(lpLineBuf
, new_buf
);
11334 * Fundamental registry access function that removes a registry key
11335 * and all its subkeys, their values and data
11338 MSWRClear(HKEY hKey
, LPTSTR pSubKey
)
11341 TCHAR KeyBuf
[MSWR_KEY_MAX
+1];
11342 DWORD dwKeyIndex
, dwKeyLen
;
11343 FILETIME ftKeyTime
;
11346 if(RegOpenKeyEx(hKey
, pSubKey
, 0,
11347 KEY_READ
, &hSubKey
) == ERROR_SUCCESS
){
11348 RegCloseKey(hSubKey
);
11349 if(RegOpenKeyEx(hKey
, pSubKey
, 0,
11350 KEY_ALL_ACCESS
, &hSubKey
) == ERROR_SUCCESS
){
11351 for(dwKeyIndex
= 0L, dwKeyLen
= MSWR_KEY_MAX
+ 1;
11352 RegEnumKeyEx(hSubKey
, dwKeyIndex
, KeyBuf
, &dwKeyLen
,
11353 NULL
, NULL
, NULL
, &ftKeyTime
) == ERROR_SUCCESS
;
11354 dwKeyLen
= MSWR_KEY_MAX
+ 1)
11355 if(MSWRClear(hSubKey
, KeyBuf
)!= 0){
11359 RegCloseKey(hSubKey
);
11360 if(RegDeleteKey(hKey
, pSubKey
) != ERROR_SUCCESS
|| rv
)
11370 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11372 * Text display Windows.
11374 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11377 * Show a help message.
11378 * Help text comes as a null terminated array of pointers to lines of
11379 * text. Stuff these into a buffer and pass that to MessageBox.
11382 mswin_showhelpmsg(WINHAND wnd
, char **helplines
)
11385 char *helptext_utf8
, *p
;
11388 LPTSTR helptext_lpt
;
11395 for(l
= helplines
; *l
!= NULL
; ++l
)
11396 buflen
+= (strlen(*l
)+1);
11398 helptext_utf8
= (char *) fs_get((buflen
+ 1) * sizeof(char));
11399 if(helptext_utf8
== NULL
)
11402 *helptext_utf8
= '\0';
11405 for(l
= helplines
; *l
!= NULL
; ++l
){
11406 snprintf(p
, buflen
+1-(p
-helptext_utf8
), "%s%s", (p
== helptext_utf8
) ? "" : " ", *l
);
11410 helptext_lpt
= utf8_to_lptstr(helptext_utf8
);
11412 MessageBox(hWnd
, helptext_lpt
, TEXT("Help"),
11413 MB_APPLMODAL
| MB_ICONINFORMATION
| MB_OK
);
11415 fs_give((void **) &helptext_utf8
);
11416 fs_give((void **) &helptext_lpt
);
11420 * Callback for when new mail or imap telem window gets canned.
11423 mswin_tw_close_imap_telem_or_new_mail(MSWIN_TEXTWINDOW
*mswin_tw
)
11427 if((mswin_tw
->id
== IDM_OPT_IMAPTELEM
) && gIMAPDebugOFFCallback
)
11428 (*gIMAPDebugOFFCallback
)();
11430 if(hMenu
= GetMenu(ghTTYWnd
))
11431 CheckMenuItem (hMenu
, mswin_tw
->id
, MF_BYCOMMAND
| MF_UNCHECKED
);
11435 * Callback for when new mail or imap telem window gets cleared.
11438 mswin_tw_clear_imap_telem_or_new_mail(MSWIN_TEXTWINDOW
*mswin_tw
)
11441 time_t now
= time((time_t *)0);
11442 LPCTSTR desc
= (mswin_tw
->id
== IDM_OPT_IMAPTELEM
) ?
11443 TEXT("IMAP telemetry recorder") :
11444 TEXT("New Mail window");
11446 tmtxt
= ctime(&now
);
11448 mswin_tw_printf(mswin_tw
, TEXT("%s started at %.*S"),
11449 desc
, MIN(100, strlen(tmtxt
)-1), tmtxt
);
11451 if(mswin_tw
->id
== IDM_OPT_NEWMAILWIN
)
11454 int fromlen
, subjlen
, foldlen
, len
;
11457 foldlen
= (int)(.18 * gNMW_width
);
11458 foldlen
= foldlen
> 5 ? foldlen
: 5;
11459 fromlen
= (int)(.28 * gNMW_width
);
11460 subjlen
= gNMW_width
- 2 - foldlen
- fromlen
;
11462 mswin_tw_printf(mswin_tw
,
11463 TEXT(" %-*s%-*s%-*s"),
11464 fromlen
, TEXT("From:"),
11465 subjlen
, TEXT("Subject:"),
11466 foldlen
, TEXT("Folder:"));
11468 len
= 2 + fromlen
+ subjlen
+ foldlen
;
11469 if(len
>= ARRAYSIZE(ring2
) + 1)
11470 len
= ARRAYSIZE(ring2
) - 2;
11471 for(i
= 0; i
< len
; i
++)
11474 mswin_tw_puts_lptstr(mswin_tw
, ring2
);
11479 * Init new mail or imap telem window
11482 mswin_tw_init(MSWIN_TEXTWINDOW
*mswin_tw
, int id
, LPCTSTR title
)
11484 if(mswin_tw
->hwnd
){
11486 mswin_tw_close(mswin_tw
);
11492 mswin_tw
->hInstance
= ghInstance
;
11493 mswin_tw
->print_callback
= mswin_tw_print_callback
;
11494 mswin_tw
->close_callback
= mswin_tw_close_imap_telem_or_new_mail
;
11495 mswin_tw
->clear_callback
= mswin_tw_clear_imap_telem_or_new_mail
;
11497 // If the rcSize rect is empty, then init it to something resembling
11498 // the size of the current Pine window. Otherwise we just re-use
11499 // whatever the last position/size was.
11500 if(IsRectEmpty(&mswin_tw
->rcSize
))
11505 GetClientRect(ghTTYWnd
, &cliRect
);
11506 sizeRect
.left
= CW_USEDEFAULT
;
11507 sizeRect
.top
= CW_USEDEFAULT
;
11508 sizeRect
.right
= cliRect
.right
;
11509 sizeRect
.bottom
= cliRect
.bottom
;
11510 mswin_tw
->rcSize
= sizeRect
;
11513 if(!mswin_tw_create(mswin_tw
, title
))
11516 mswin_tw_setfont(mswin_tw
, gpTTYInfo
->hTTYFont
);
11517 mswin_tw_setcolor(mswin_tw
, gpTTYInfo
->rgbFGColor
, gpTTYInfo
->rgbBGColor
);
11519 mswin_tw_clear(mswin_tw
);
11521 if(id
== IDM_OPT_IMAPTELEM
)
11523 if(gIMAPDebugONCallback
)
11524 (*gIMAPDebugONCallback
)();
11526 mswin_tw_showwindow(mswin_tw
, SW_SHOWNA
);
11528 else if(id
== IDM_OPT_NEWMAILWIN
){
11529 mswin_tw_showwindow(mswin_tw
, SW_SHOW
);
11532 if(hMenu
= GetMenu(ghTTYWnd
))
11533 CheckMenuItem (hMenu
, mswin_tw
->id
, MF_BYCOMMAND
| MF_CHECKED
);
11540 * Display text in a window.
11543 * title - Title of window.
11544 * pText - address of text to display.
11545 * textLen - Length of text, in bytes. Limited to 64K.
11546 * pLines - Array of pointers to lines of text. Each
11547 * line is a sepreate allocation block. The
11548 * entry in the array of pointers should be a
11551 * The text can be supplied as a buffer (pText and textLen) in which
11552 * lines are terminated by CRLF (including the last line in buffer).
11553 * This buffer should be NULL terminated, too.
11554 * Or it can be supplied as a NULL terminated array of pointers to
11555 * lines. Each entry points to a separately allocated memory block
11556 * containing a null terminated string.
11558 * If the function succeeds the memory containing the text will be
11559 * used until the user closes the window, at which point it will be
11563 * mswin_tw - SUCCESS
11567 mswin_displaytext(char *title_utf8
, char *pText_utf8
, size_t npText
,
11568 char **pLines_utf8
, MSWIN_TEXTWINDOW
*mswin_tw
, int flags
)
11570 LPTSTR title_lpt
= NULL
, pText_lpt
= NULL
, *pLines_lpt
= NULL
;
11572 size_t pText_lpt_len
= 0;
11575 if(pLines_utf8
!= NULL
){
11576 for(count
=0, l
= pLines_utf8
; *l
!= NULL
; ++l
)
11579 pLines_lpt
= (LPTSTR
*) fs_get((count
+ 1) * sizeof(LPTSTR
));
11580 memset(pLines_lpt
, 0, (count
+ 1) * sizeof(LPTSTR
));
11581 for(i
=0, l
= pLines_utf8
; *l
!= NULL
&& i
< count
; ++l
, ++i
)
11582 pLines_lpt
[i
] = utf8_to_lptstr(*l
);
11584 /*caller expects this to be freed */
11585 if(!(flags
& MSWIN_DT_NODELETE
)){
11586 for(l
= pLines_utf8
; *l
!= NULL
; ++l
)
11587 fs_give((void **) l
);
11589 fs_give((void **) &pLines_utf8
);
11593 if(pText_utf8
!= NULL
&& npText
> 0){
11594 pText_lpt
= utf8_to_lptstr(pText_utf8
);
11595 pText_lpt_len
= lstrlen(pText_lpt
);
11597 /*caller expects this to be freed */
11598 if(!(flags
& MSWIN_DT_NODELETE
))
11599 fs_give((void **) &pText_utf8
);
11602 if(title_utf8
!= NULL
)
11603 title_lpt
= utf8_to_lptstr(title_utf8
);
11605 mswin_tw
= mswin_tw_displaytext_lptstr(title_lpt
, pText_lpt
, pText_lpt_len
,
11606 pLines_lpt
, mswin_tw
, flags
);
11608 if(pLines_lpt
!= NULL
){
11609 for(i
=0; i
< count
; ++i
)
11611 fs_give((void **) &pLines_lpt
[i
]);
11613 fs_give((void **) &pLines_lpt
);
11616 if(pText_lpt
!= NULL
)
11617 fs_give((void **) &pText_lpt
);
11619 if(title_lpt
!= NULL
)
11620 fs_give((void **) &title_lpt
);
11626 * Callback for when a generic mswin_tw gets killed.
11629 mswin_tw_close_callback(MSWIN_TEXTWINDOW
*mswin_tw
)
11631 if(mswin_tw
->id
!= -1)
11636 * Create a new mswin_tw window. If the MSWIN_DT_USEALTWINDOW flag is set,
11637 * then (re)use gMswinAltWin.
11639 LOCAL MSWIN_TEXTWINDOW
*
11640 mswin_tw_displaytext_lptstr (LPTSTR title
, LPTSTR pText
, size_t textLen
, LPTSTR
*pLines
,
11641 MSWIN_TEXTWINDOW
*mswin_tw
, int flags
)
11643 if (pText
== NULL
&& pLines
== NULL
)
11646 /* Was a valid existing window supplied? */
11649 int ctrl_down
= GetKeyState(VK_CONTROL
) < 0;
11651 if((flags
& MSWIN_DT_USEALTWINDOW
) && !ctrl_down
)
11653 mswin_tw
= &gMswinAltWin
;
11654 mswin_tw
->id
= (UINT
)-1; // Tell mswin_tw_close_callback not
11655 // to free this buffer.
11659 mswin_tw
= (MSWIN_TEXTWINDOW
*)MemAlloc (sizeof (MSWIN_TEXTWINDOW
));
11663 memset(mswin_tw
, 0, sizeof(MSWIN_TEXTWINDOW
));
11667 mswin_tw
->hInstance
= ghInstance
;
11668 mswin_tw
->print_callback
= mswin_tw_print_callback
;
11669 mswin_tw
->close_callback
= mswin_tw_close_callback
;
11670 mswin_tw
->clear_callback
= NULL
;
11673 /* Create a new window. */
11674 if (!mswin_tw
->hwnd
) {
11676 if(IsRectEmpty(&mswin_tw
->rcSize
))
11681 GetClientRect(ghTTYWnd
, &cliRect
);
11682 sizeRect
.left
= CW_USEDEFAULT
;
11683 sizeRect
.top
= CW_USEDEFAULT
;
11684 sizeRect
.right
= cliRect
.right
;
11685 sizeRect
.bottom
= cliRect
.bottom
;
11686 mswin_tw
->rcSize
= sizeRect
;
11689 if(!mswin_tw_create(mswin_tw
, title
)) {
11690 MemFree (mswin_tw
);
11694 mswin_tw_setfont(mswin_tw
, gpTTYInfo
->hTTYFont
);
11695 mswin_tw_setcolor(mswin_tw
, gpTTYInfo
->rgbFGColor
, gpTTYInfo
->rgbBGColor
);
11698 /* Invalidate whole window, change title, and move to top. */
11699 SetWindowText (mswin_tw
->hwnd
, title
);
11700 SetWindowPos (mswin_tw
->hwnd
, HWND_TOP
, 0, 0, 0, 0, SWP_NOMOVE
| SWP_NOSIZE
);
11703 mswin_tw_clear(mswin_tw
);
11706 * How was text supplied?
11708 if (pLines
!= NULL
) {
11711 /* Array of pointers to lines supplied. Count lines. */
11712 for (l
= pLines
; *l
!= NULL
; ++l
){
11713 mswin_tw_puts_lptstr(mswin_tw
, *l
);
11718 if(flags
& MSWIN_DT_FILLFROMFILE
)
11719 mswin_tw_fill_from_file(mswin_tw
, pText
);
11721 #endif /* ALTED_DOT */
11722 /* Pointer to block of text supplied. */
11723 mswin_tw_puts_lptstr(mswin_tw
, pText
);
11726 mswin_tw_setsel(mswin_tw
, 0, 0);
11728 mswin_tw_showwindow(mswin_tw
, SW_SHOW
);
11733 mswin_enableimaptelemetry(int state
)
11736 MENUITEMINFO mitem
;
11740 hMenu
= GetMenu (ghTTYWnd
);
11745 * Make sure hMenu's the right menubar
11747 mitem
.cbSize
= sizeof(MENUITEMINFO
);
11748 mitem
.fMask
= (MIIM_SUBMENU
| MIIM_TYPE
);
11749 mitem
.fType
= MFT_STRING
;
11750 mitem
.dwTypeData
= buf
;
11752 if(GetMenuItemCount(hMenu
) == 7
11753 && GetMenuItemInfo(hMenu
, 5, TRUE
, &mitem
)){
11754 if(mitem
.fType
== MFT_STRING
11755 && !_tcscmp(mitem
.dwTypeData
, TEXT("&Config")))
11756 hMenu
= mitem
.hSubMenu
;
11763 i
= GetMenuItemCount(hMenu
);
11764 if(state
== TRUE
&& i
< 10){
11765 mitem
.fMask
= MIIM_TYPE
;
11766 mitem
.fType
= MFT_SEPARATOR
;
11767 InsertMenuItem (hMenu
, 8, TRUE
, &mitem
);
11769 mitem
.fMask
= (MIIM_TYPE
| MIIM_ID
);
11770 mitem
.fType
= MFT_STRING
;
11771 mitem
.wID
= IDM_OPT_IMAPTELEM
;
11772 mitem
.dwTypeData
= TEXT("&IMAP Telemetry");
11774 InsertMenuItem (hMenu
, 9, TRUE
, &mitem
);
11776 DrawMenuBar (ghTTYWnd
);
11778 else if(state
== FALSE
&& i
== 10){
11779 DeleteMenu (hMenu
, 8, MF_BYPOSITION
);
11780 DeleteMenu (hMenu
, IDM_OPT_IMAPTELEM
, MF_BYCOMMAND
);
11781 DrawMenuBar (ghTTYWnd
);
11786 mswin_imaptelemetry(char *msg
)
11788 if(gMswinIMAPTelem
.hwnd
){
11790 msg_lptstr
= utf8_to_lptstr(msg
);
11791 mswin_tw_puts_lptstr(&gMswinIMAPTelem
, msg_lptstr
);
11792 fs_give((void **) &msg_lptstr
);
11800 * The newmail window has a format proportional to screen width.
11801 * At this point, we've figured out the sizes of the fields, now
11802 * we fill that field to it's desired column size. This used to
11803 * be a lot eaier when it was one char per column, but in the
11804 * unicode world it's not that easy. This code does make the
11805 * assumption that ASCII characters are 1 column.
11808 format_newmail_string(LPTSTR orig_lptstr
, int format_len
)
11813 new_lptstr
= (LPTSTR
)MemAlloc((format_len
+1)*sizeof(TCHAR
));
11816 * Fill up string till we reach the format_len, we can backtrack
11817 * if we need elipses.
11819 for(i
= 0, colLen
= 0;
11820 i
< format_len
&& colLen
< format_len
&& orig_lptstr
&& orig_lptstr
[i
];
11822 new_lptstr
[i
] = orig_lptstr
[i
];
11823 colLen
+= wcellwidth(new_lptstr
[i
]);
11826 if(colLen
> format_len
|| (colLen
== format_len
&& orig_lptstr
[i
])){
11828 * If we hit the edge of the format and there's still stuff
11829 * to write, go back and add ".."
11832 if(wcellwidth(new_lptstr
[i
]) > 1){
11833 colLen
-= wcellwidth(new_lptstr
[i
]);
11836 colLen
-= wcellwidth(new_lptstr
[i
]);
11838 colLen
-= wcellwidth(new_lptstr
[i
]);
11840 while(colLen
< format_len
&& i
< format_len
){
11841 new_lptstr
[i
++] = '.';
11847 * If we've hit the end of the string, add spaces until
11848 * we get to the correct length.
11850 for(; colLen
< format_len
&& i
< format_len
; i
++, colLen
++){
11851 new_lptstr
[i
] = ' ';
11855 if(i
<= format_len
)
11856 new_lptstr
[i
] = '\0';
11858 new_lptstr
[format_len
] = '\0';
11860 return(new_lptstr
);
11864 * We're passed the relevant fields, now format them according to window with
11865 * and put up for display
11868 mswin_newmailwin(int is_us
, char *from_utf8
, char *subject_utf8
, char *folder_utf8
)
11871 int foldlen
, fromlen
, subjlen
;
11872 LPTSTR from_lptstr
= NULL
, subject_lptstr
= NULL
, folder_lptstr
= NULL
;
11873 LPTSTR from_format
, subject_format
, folder_format
;
11875 if(!gMswinNewMailWin
.hwnd
)
11879 from_lptstr
= utf8_to_lptstr(from_utf8
);
11881 subject_lptstr
= utf8_to_lptstr(subject_utf8
);
11883 folder_lptstr
= utf8_to_lptstr(folder_utf8
);
11886 foldlen
= (int)(.18 * gNMW_width
);
11887 foldlen
= foldlen
> 5 ? foldlen
: 5;
11888 fromlen
= (int)(.28 * gNMW_width
);
11889 subjlen
= gNMW_width
- 2 - foldlen
- fromlen
;
11892 from_format
= format_newmail_string(from_lptstr
11893 ? from_lptstr
: TEXT(""),
11895 subject_format
= format_newmail_string(subject_lptstr
11896 ? subject_lptstr
: TEXT("(no subject)"),
11898 folder_format
= format_newmail_string(folder_lptstr
11899 ? folder_lptstr
: TEXT("INBOX"),
11902 _sntprintf(tcbuf
, 256, TEXT("%c %s %s %s"), is_us
? '+' : ' ',
11903 from_format
, subject_format
, folder_format
);
11906 fs_give((void **) &from_lptstr
);
11908 fs_give((void **) &subject_lptstr
);
11910 fs_give((void **) &folder_lptstr
);
11911 MemFree((void *)from_format
);
11912 MemFree((void *)subject_format
);
11913 MemFree((void *)folder_format
);
11915 mswin_tw_puts_lptstr(&gMswinNewMailWin
, tcbuf
);
11920 * Mouse up, end selection
11924 mswin_tw_print_callback(MSWIN_TEXTWINDOW
*mswin_tw
)
11929 #define DESC_LEN 180
11930 TCHAR description
[DESC_LEN
+1];
11932 GetWindowText(mswin_tw
->hwnd
, description
, DESC_LEN
);
11934 rc
= mswin_print_ready((WINHAND
)mswin_tw
->hwnd
, description
);
11936 if (rc
!= PE_USER_CANCEL
) {
11939 e
= utf8_to_lptstr(mswin_print_error(rc
));
11941 _sntprintf(description
, DESC_LEN
+1, TEXT("Printing failed: %s"), e
);
11942 fs_give((void **) &e
);
11945 MessageBox(mswin_tw
->hwnd
, description
, TEXT("Print Failed"),
11946 MB_OK
| MB_ICONEXCLAMATION
);
11951 text_len
= mswin_tw_gettextlength(mswin_tw
);
11952 text
= (LPTSTR
) fs_get(text_len
* sizeof(TCHAR
));
11953 mswin_tw_gettext(mswin_tw
, text
, text_len
);
11954 mswin_print_text(text
);
11955 fs_give((void **)&text
);
11957 mswin_print_done();
11961 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
11965 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
11969 BOOL fKeyControlDown
;
11970 UCS c
; /* Bigger than TCHAR for CTRL and MENU setting */
11973 LOCAL CQEntry CQBuffer
[CHARACTER_QUEUE_LENGTH
];
11979 /*---------------------------------------------------------------------------
11983 * Initialize the Character queue.
11988 /*--------------------------------------------------------------------------*/
11998 /*---------------------------------------------------------------------------
11999 * BOOL CQAvailable (void)
12002 * Return TRUE if there are characters in the queue.
12007 /*--------------------------------------------------------------------------*/
12012 return (CQCount
> 0);
12017 /*---------------------------------------------------------------------------
12018 * BOOL CQAdd (WORD c, DWORC keyData)
12021 * Add 'c' to the end of the character queue.
12024 * return true if successfull.
12026 /*--------------------------------------------------------------------------*/
12029 CQAdd (UCS c
, BOOL fKeyControlDown
)
12031 if (CQCount
== CHARACTER_QUEUE_LENGTH
)
12034 CQBuffer
[CQTail
].fKeyControlDown
= fKeyControlDown
;
12035 CQBuffer
[CQTail
].c
= c
;
12036 CQTail
= (CQTail
+ 1) % CHARACTER_QUEUE_LENGTH
;
12043 /*---------------------------------------------------------------------------
12044 * BOOL CQAddUniq (WORD c, DWORC keyData)
12047 * Add 'c' to the end of the character queue, only if
12048 * there is no other 'c' in the queue
12051 * return true if successfull.
12053 /*--------------------------------------------------------------------------*/
12056 CQAddUniq (UCS c
, BOOL fKeyControlDown
)
12061 if (CQCount
== CHARACTER_QUEUE_LENGTH
)
12065 for (i
= 0; i
< CQCount
; ++i
) {
12066 if (CQBuffer
[pos
].c
== c
)
12068 pos
= (pos
+ 1) % CHARACTER_QUEUE_LENGTH
;
12070 return (CQAdd (c
, fKeyControlDown
));
12076 /*---------------------------------------------------------------------------
12080 * Return the next byte from the head of the queue. If there is
12081 * no byte available, returns 0, which is indistinquishable from
12082 * '\0'. So it is a good idea to call CQAvailable first.
12087 /*--------------------------------------------------------------------------*/
12097 c
= CQBuffer
[CQHead
].c
;
12099 if(CQBuffer
[CQHead
].fKeyControlDown
)
12107 CQHead
= (CQHead
+ 1) % CHARACTER_QUEUE_LENGTH
;
12114 /*+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
12116 * Mouse Event Queue
12118 *++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*/
12122 LOCAL MEvent MQBuffer
[MOUSE_QUEUE_LENGTH
];
12128 /*---------------------------------------------------------------------------
12132 * Initialize the Character queue.
12137 /*--------------------------------------------------------------------------*/
12147 /*---------------------------------------------------------------------------
12148 * BOOL MQAvailable (void)
12151 * Return TRUE if there are characters in the queue.
12156 /*--------------------------------------------------------------------------*/
12161 return (MQCount
> 0);
12166 /*---------------------------------------------------------------------------
12170 * Add 'c' to the end of the character queue.
12173 * return true if successfull.
12175 /*--------------------------------------------------------------------------*/
12178 MQAdd (int mevent
, int button
, int nRow
, int nColumn
, int keys
, int flags
)
12182 BOOL found
= FALSE
;
12186 * Find a queue insertion point.
12188 if (flags
& MSWIN_MF_REPLACING
) {
12189 /* Search for same event on queue. */
12190 for ( i
= MQHead
, c
= MQCount
;
12192 i
= (i
+ 1) % MOUSE_QUEUE_LENGTH
, --c
) {
12193 if (MQBuffer
[i
].event
== mevent
) {
12200 if (MQCount
== MOUSE_QUEUE_LENGTH
)
12203 MQTail
= (MQTail
+ 1) % MOUSE_QUEUE_LENGTH
;
12211 MQBuffer
[i
].event
= mevent
;
12212 MQBuffer
[i
].button
= button
;
12213 MQBuffer
[i
].nRow
= nRow
;
12214 MQBuffer
[i
].nColumn
= nColumn
;
12215 MQBuffer
[i
].keys
= keys
;
12216 MQBuffer
[i
].flags
= flags
;
12219 * Keep record of last mouse position.
12221 gMTEvent
= MQBuffer
[i
];
12230 /*---------------------------------------------------------------------------
12234 * Return the next byte from the head of the queue. If there is
12235 * no byte available, returns 0, which is indistinquishable from
12236 * '\0'. So it is a good idea to call MQAvailable first.
12241 /*--------------------------------------------------------------------------*/
12244 MQGet (MEvent
* pMouse
)
12250 *pMouse
= MQBuffer
[MQHead
];
12251 MQHead
= (MQHead
+ 1) % MOUSE_QUEUE_LENGTH
;
12265 void *lpMsgBuf
= NULL
;
12266 status
= GetLastError();
12269 FORMAT_MESSAGE_ALLOCATE_BUFFER
| FORMAT_MESSAGE_FROM_SYSTEM
,
12272 MAKELANGID(LANG_NEUTRAL
,SUBLANG_DEFAULT
),
12273 (LPTSTR
) &lpMsgBuf
, 0, NULL
);
12278 msg
= lptstr_to_utf8(lpMsgBuf
);
12280 mswin_messagebox(msg
, 1);
12281 fs_give((void **) &msg
);
12284 LocalFree(lpMsgBuf
);
12292 * Called by mswin to scroll text in window in responce to the scrollbar.
12294 * Args: cmd - what type of scroll operation.
12295 * scroll_pos - paramter for operation.
12296 * used as position for SCROLL_TO operation.
12298 * Returns: TRUE - did the scroll operation.
12299 * FALSE - was not able to do the scroll operation.
12302 pico_scroll_callback (int cmd
, long scroll_pos
)
12305 case MSWIN_KEY_SCROLLUPLINE
:
12306 scrollupline (0, 1);
12309 case MSWIN_KEY_SCROLLDOWNLINE
:
12310 scrolldownline (0, 1);
12313 case MSWIN_KEY_SCROLLUPPAGE
:
12317 case MSWIN_KEY_SCROLLDOWNPAGE
:
12321 case MSWIN_KEY_SCROLLTO
:
12331 * sleep the given number of seconds
12336 time_t out
= (time_t)t
+ time((long *) 0);
12337 while(out
> time((long *) 0))
12343 tcsucmp(LPTSTR o
, LPTSTR r
)
12345 return(o
? (r
? _tcsicmp(o
, r
) : 1) : (r
? -1 : 0));
12349 tcsruncmp(LPTSTR o
, LPTSTR r
, int n
)
12351 return(o
? (r
? _tcsnicmp(o
, r
, n
) : 1) : (r
? -1 : 0));
12355 strucmp(char *o
, char *r
)
12357 return(o
? (r
? stricmp(o
, r
) : 1) : (r
? -1 : 0));
12362 struncmp(char *o
, char *r
, int n
)
12364 return(o
? (r
? strnicmp(o
, r
, n
) : 1) : (r
? -1 : 0));
12369 * Returns screen width of len characters of lpText.
12370 * The width is in character cells. That is, an ascii "A" has
12371 * width 1 but a CJK character probably has width 2.
12374 scrwidth(LPTSTR lpText
, int len
)
12378 int i
, thislen
, offset
;
12383 thislen
= MIN(len
, 1000);
12384 for(i
= 0; i
< thislen
; i
++)
12385 ubuf
[i
] = lpText
[offset
+i
];
12387 w
+= ucs4_str_width_ptr_to_ptr(&ubuf
[0], &ubuf
[thislen
]);
12398 * Returns the index into pScreen given the row,col location
12399 * on the screen, taking into account characters with widths
12400 * other than 1 cell.
12403 pscreen_offset_from_cord(int row
, int col
, PTTYINFO pTTYInfo
)
12405 int offset_due_to_row
, offset_due_to_col
, width
;
12408 * Each row starts at a specific offset into pScreen.
12410 offset_due_to_row
= row
* pTTYInfo
->actNColumn
;
12413 * Start with col (all chars single width) and go from there.
12414 * We need to find the offset that makes the string col wide.
12415 * Hopefully we won't ever get a rectange that causes us to
12416 * draw half characters, but in case we do we need to err on the
12417 * side of too much width instead of not enough. It's a little
12418 * tricky because we want to include following zero-width
12420 * fewer characters it would be <= desired width, one more would
12421 * be greater than desired width, this one is >= desired width.
12424 /* first go to some offset where width is > col */
12425 offset_due_to_col
= col
;
12426 width
= scrwidth(pTTYInfo
->pScreen
+offset_due_to_row
, offset_due_to_col
);
12427 while(width
<= col
&& offset_due_to_col
< pTTYInfo
->actNColumn
-1){
12428 offset_due_to_col
++;
12429 width
= scrwidth(pTTYInfo
->pScreen
+offset_due_to_row
, offset_due_to_col
);
12432 /* Now back up until width is no longer > col */
12433 while(width
> col
){
12434 offset_due_to_col
--;
12435 width
= scrwidth(pTTYInfo
->pScreen
+offset_due_to_row
, offset_due_to_col
);
12438 /* But, if we're now less than col, go forward one again. */
12439 if(width
< col
&& offset_due_to_col
< pTTYInfo
->actNColumn
-1)
12440 offset_due_to_col
++;
12442 return(offset_due_to_row
+ offset_due_to_col
);
12448 * 1 if store pass prompt is set in the registry to on
12450 * -1 if not set to anything
12453 mswin_store_pass_prompt(void)
12456 * We shouldn't need to prompt anymore, but always return 1