* Update to version 2.19.5
[alpine.git] / alpine / osdep / termout.wnt.c
blob8913d578a8c4b182fb7e000c5ad4beafd8f1b327
1 #if !defined(lint) && !defined(DOS)
2 static char rcsid[] = "$Id: termout.unx.c 159 2006-10-02 22:00:13Z hubert@u.washington.edu $";
3 #endif
5 /*
6 * ========================================================================
7 * Copyright 2006-2007 University of Washington
8 * Copyright 2013-2014 Eduardo Chappa
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * ========================================================================
18 #include <system.h>
19 #include <general.h>
21 #include "../../c-client/mail.h" /* for MAILSTREAM and friends */
22 #include "../../c-client/osdep.h"
23 #include "../../c-client/rfc822.h" /* for soutr_t and such */
24 #include "../../c-client/misc.h" /* for cpystr proto */
25 #include "../../c-client/utf8.h" /* for CHARSET and such*/
26 #include "../../c-client/imap4r1.h"
28 #include "../../pith/osdep/color.h"
30 #include "../../pith/charconv/filesys.h"
32 #include "../../pith/debug.h"
33 #include "../../pith/conf.h"
34 #include "../../pith/newmail.h"
36 #include "../../pico/estruct.h"
37 #include "../../pico/pico.h"
38 #include "../../pico/keydefs.h"
40 #include "../../pico/osdep/mswin.h"
41 #include "../../pico/osdep/color.h"
43 #include "../flagmaint.h"
44 #include "../status.h"
45 #include "../keymenu.h"
46 #include "../titlebar.h"
48 #include "termout.gen.h"
49 #include "termout.wnt.h"
51 /*======================================================================
52 Routines for painting the screen
53 - figure out what the terminal type is
54 - deal with screen size changes
55 - save special output sequences
56 - the usual screen clearing, cursor addressing and scrolling
59 This library gives programs the ability to easily access the
60 termcap information and write screen oriented and raw input
61 programs. The routines can be called as needed, except that
62 to use the cursor / screen routines there must be a call to
63 InitScreen() first. The 'Raw' input routine can be used
64 independently, however. (Elm comment)
66 Not sure what the original source of this code was. It got to be
67 here as part of ELM. It has been changed significantly from the
68 ELM version to be more robust in the face of inconsistent terminal
69 autowrap behaviour. Also, the unused functions were removed, it was
70 made to pay attention to the window size, and some code was made nicer
71 (in my opinion anyways). It also outputs the terminal initialization
72 strings and provides for minimal scrolling and detects terminals
73 with out enough capabilities. (Pine comment, 1990)
77 #define PUTLINE_BUFLEN 256
79 static int _lines, _columns;
81 BOOL CALLBACK __export
82 args_dialog_proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
84 BOOL CALLBACK __export
85 login_dialog_proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
87 BOOL CALLBACK __export
88 flag_dialog_proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
90 BOOL CALLBACK __export
91 sort_dialog_proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
93 BOOL CALLBACK __export
94 config_vars_dialog_proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
96 BOOL CALLBACK __export
97 config_dialog_proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
99 void
100 init_screen(void)
103 * If we want to show it, turn it on. If we don't care, put it back
104 * to the way it was originally.
106 mswin_showcaret(F_ON(F_SHOW_CURSOR, ps_global));
107 mswin_trayicon(F_ON(F_ENABLE_TRAYICON, ps_global));
108 return; /* NO OP */
111 void
112 end_screen(char *message, int exit_val)
114 int footer_rows_was_one = 0;
116 if(panicking())
117 return;
119 if(FOOTER_ROWS(ps_global) == 1){
120 footer_rows_was_one++;
121 FOOTER_ROWS(ps_global) = 3;
122 mark_status_unknown();
125 flush_status_messages(exit_val ? 0 : 1);
127 blank_keymenu(_lines - 2, 0);
129 if(message){
130 StartInverse();
131 PutLine0(_lines - 2, 0, message);
134 EndInverse();
136 MoveCursor(_lines - 1, 0);
138 mswin_showcaret(F_ON(F_SHOW_CURSOR, ps_global));
140 if(footer_rows_was_one){
141 FOOTER_ROWS(ps_global) = 1;
142 mark_status_unknown();
146 /*----------------------------------------------------------------------
147 Initialize the screen for output, set terminal type, etc
149 Args: tt -- Pointer to variable to store the tty output structure.
151 Result: terminal size is discovered and set pine state
152 termcap entry is fetched and stored in local variables
153 make sure terminal has adequate capabilites
154 evaluate scrolling situation
155 returns status of indicating the state of the screen/termcap entry
157 Returns:
158 -1 indicating no terminal name associated with this shell,
159 -2..-n No termcap for this terminal type known
160 -3 Can't open termcap file
161 -4 Terminal not powerful enough - missing clear to eoln or screen
162 or cursor motion
164 ----*/
166 config_screen(struct ttyo **tt)
168 struct ttyo *ttyo;
170 _line = 0; /* where are we right now?? */
171 _col = 0; /* assume zero, zero... */
173 mswin_getscreensize(&_lines, &_columns);
174 if (_lines > MAX_SCREEN_ROWS)
175 _lines = MAX_SCREEN_ROWS;
176 if (_columns > MAX_SCREEN_COLS)
177 _columns = MAX_SCREEN_COLS;
179 ttyo = (struct ttyo *)fs_get(sizeof(struct ttyo));
180 ttyo->screen_cols = _columns;
181 ttyo->screen_rows = _lines ;
182 ttyo->header_rows = 2;
183 ttyo->footer_rows = 3;
185 *tt = ttyo;
187 return(0);
190 /*----------------------------------------------------------------------
191 Get the current window size
193 Args: ttyo -- pointer to structure to store window size in
195 NOTE: we don't override the given values unless we know better
196 ----*/
198 get_windsize(struct ttyo *ttyo)
200 char fontName[LF_FACESIZE+1];
201 char fontSize[12];
202 char fontStyle[64];
203 char fontCharSet[256];
204 char windowPosition[32], windowPositionReg[32];
205 char foreColor[64], backColor[64];
206 int newRows, newCols;
207 char cursorStyle[32];
209 cursorStyle[0] = '\0';
211 /* Get the new window parameters and update the 'pinerc' variables. */
212 mswin_getwindow(fontName, sizeof(fontName), fontSize, sizeof(fontSize),
213 fontStyle, sizeof(fontStyle),
214 windowPosition, sizeof(windowPosition),
215 foreColor, sizeof(foreColor),
216 backColor, sizeof(backColor),
217 cursorStyle, sizeof(cursorStyle),
218 fontCharSet, sizeof(fontCharSet));
220 if(!ps_global->VAR_FONT_NAME
221 || strucmp(ps_global->VAR_FONT_NAME, fontName))
222 set_variable(V_FONT_NAME, fontName, 1, 0,
223 ps_global->ew_for_except_vars);
225 if(!ps_global->VAR_FONT_SIZE
226 || strucmp(ps_global->VAR_FONT_SIZE, fontSize))
227 set_variable(V_FONT_SIZE, fontSize, 1, 0,
228 ps_global->ew_for_except_vars);
230 if(!ps_global->VAR_FONT_STYLE
231 || strucmp(ps_global->VAR_FONT_STYLE, fontStyle))
232 set_variable(V_FONT_STYLE, fontStyle, 1, 0,
233 ps_global->ew_for_except_vars);
235 if(!ps_global->VAR_FONT_CHAR_SET
236 || strucmp(ps_global->VAR_FONT_CHAR_SET, fontCharSet))
237 set_variable(V_FONT_CHAR_SET, fontCharSet, 1, 0,
238 ps_global->ew_for_except_vars);
240 if(strnicmp(windowPosition, "MIN0", 4) && !strchr(windowPosition, '!')){
241 if(F_ON(F_STORE_WINPOS_IN_CONFIG, ps_global)){
242 if(!ps_global->VAR_WINDOW_POSITION
243 || strucmp(ps_global->VAR_WINDOW_POSITION, windowPosition))
244 set_variable(V_WINDOW_POSITION, windowPosition, 1, 0,
245 ps_global->ew_for_except_vars);
247 else{
249 * Get the window position stored in the registry.
251 * If current window position is not in the registry or is
252 * different from what is there, save it.
254 if((!mswin_reg(MSWR_OP_GET, MSWR_PINE_POS, windowPositionReg,
255 sizeof(windowPositionReg)) ||
256 strucmp(windowPositionReg, windowPosition))
257 && (ps_global->update_registry != UREG_NEVER_SET))
258 mswin_reg(MSWR_OP_SET | MSWR_OP_FORCE, MSWR_PINE_POS, windowPosition,
259 (size_t)NULL);
263 mswin_getprintfont(fontName, sizeof(fontName),
264 fontSize, sizeof(fontSize),
265 fontStyle, sizeof(fontStyle),
266 fontCharSet, sizeof(fontCharSet));
267 if(!ps_global->VAR_PRINT_FONT_NAME
268 || strucmp(ps_global->VAR_PRINT_FONT_NAME, fontName))
269 set_variable(V_PRINT_FONT_NAME, fontName, 1, 0,
270 ps_global->ew_for_except_vars);
272 if(!ps_global->VAR_PRINT_FONT_SIZE
273 || strucmp(ps_global->VAR_PRINT_FONT_SIZE, fontSize))
274 set_variable(V_PRINT_FONT_SIZE, fontSize, 1, 0,
275 ps_global->ew_for_except_vars);
277 if(!ps_global->VAR_PRINT_FONT_STYLE
278 || strucmp(ps_global->VAR_PRINT_FONT_STYLE, fontStyle))
279 set_variable(V_PRINT_FONT_STYLE, fontStyle, 1, 0,
280 ps_global->ew_for_except_vars);
282 if(!ps_global->VAR_PRINT_FONT_CHAR_SET
283 || strucmp(ps_global->VAR_PRINT_FONT_CHAR_SET, fontCharSet))
284 set_variable(V_PRINT_FONT_CHAR_SET, fontCharSet, 1, 0,
285 ps_global->ew_for_except_vars);
287 if(!ps_global->VAR_NORM_FORE_COLOR
288 || strucmp(ps_global->VAR_NORM_FORE_COLOR, foreColor))
289 set_variable(V_NORM_FORE_COLOR, foreColor, 1, 0,
290 ps_global->ew_for_except_vars);
292 if(!ps_global->VAR_NORM_BACK_COLOR
293 || strucmp(ps_global->VAR_NORM_BACK_COLOR, backColor))
294 set_variable(V_NORM_BACK_COLOR, backColor, 1, 0,
295 ps_global->ew_for_except_vars);
297 if(cursorStyle[0] && !ps_global->VAR_CURSOR_STYLE
298 || strucmp(ps_global->VAR_CURSOR_STYLE, cursorStyle))
299 set_variable(V_CURSOR_STYLE, cursorStyle, 1, 0,
300 ps_global->ew_for_except_vars);
302 /* Get new window size. Compare to old. The window may have just
303 * moved, in which case we don't bother updating the size. */
304 mswin_getscreensize(&newRows, &newCols);
305 if (newRows == ttyo->screen_rows && newCols == ttyo->screen_cols)
306 return (NO_OP_COMMAND);
308 /* True resize. */
309 ttyo->screen_rows = newRows;
310 ttyo->screen_cols = newCols;
312 if (ttyo->screen_rows > MAX_SCREEN_ROWS)
313 ttyo->screen_rows = MAX_SCREEN_ROWS;
314 if (ttyo->screen_cols > MAX_SCREEN_COLS)
315 ttyo->screen_cols = MAX_SCREEN_COLS;
317 return(KEY_RESIZE);
320 /*----------------------------------------------------------------------
321 Move the cursor to the row and column number
322 Input: row number
323 column number
325 Result: Cursor moves
326 internal position updated
327 ----------------------------------------------------------------------*/
328 void
329 MoveCursor(int row, int col)
331 /** move cursor to the specified row column on the screen.
332 0,0 is the top left! **/
334 if(ps_global->in_init_seq)
335 return;
338 * This little hack is here for screen readers, for example, a screen
339 * reader associated with a braille display. If we flash the cursor off
340 * and on in the same position, the reader will be drawn to it. Since we
341 * are calling MoveCursor every time through the message viewing loops we
342 * need to suppress the calls if they aren't really doing anything.
343 * However, mswin_move actually does more than just move the cursor.
344 * It also call FlushAccum(), which is necessary in some cases. For
345 * example, in optionally_enter the user is typing characters in and
346 * the FlushAccum() allows them to show up on the screen. The putblock
347 * call is a quick hack to get the Flush_Accum() call, which is all
348 * the putblock does when the arg is NULL.
350 if(row == _line && col == _col){
351 mswin_putblock(NULL, 0);
352 return;
355 mswin_move(row, col);
356 _line = row;
357 _col = col;
361 /*----------------------------------------------------------------------
362 Write a character to the screen, keeping track of cursor position
364 Input: charater to write
366 Result: character output
367 cursor position variables updated
368 ----------------------------------------------------------------------*/
369 void
370 Writewchar(UCS ucs)
372 int width;
374 if(ps_global->in_init_seq)
375 return;
377 switch(ucs){
378 case LINE_FEED :
379 _line = min(_line+1,ps_global->ttyo->screen_rows);
380 _col =0;
381 mswin_move(_line, _col);
382 break;
384 case RETURN : /* move to column 0 */
385 _col = 0;
386 mswin_move(_line, _col);
388 case BACKSPACE : /* move back a space if not in column 0 */
389 if(_col > 0)
390 mswin_move(_line, --_col);
392 break;
394 case BELL : /* ring the bell but don't advance _col */
395 mswin_beep(); /* libpico call */
396 break;
398 case TAB: /* if a tab, output it */
400 mswin_putc(' ');
401 while(((++_col)&0x07) != 0);
402 break;
404 default:
405 /* pass_ctrl_chars is always 1 for Windows */
406 width = wcellwidth(ucs);
407 if(width < 0){
408 mswin_putc('?');
409 _col++;
411 else if(_col + width > ps_global->ttyo->screen_cols){
412 int i;
414 i = ps_global->ttyo->screen_cols - _col - 1;
415 while(i-- > 0)
416 mswin_putc(' ');
418 _col = ps_global->ttyo->screen_cols - 1;
419 mswin_move(_line, _col);
420 mswin_putc('>');
421 _col++;
423 else{
424 mswin_putc(ucs);
425 _col += width;
429 if(_col >= ps_global->ttyo->screen_cols){
430 _col = ps_global->ttyo->screen_cols;
431 mswin_move(_line, _col);
434 return;
438 /*----------------------------------------------------------------------
439 Printf style write directly to the terminal at current position
441 Input: printf style control string
442 number of printf style arguments
443 up to three printf style arguments
445 Result: Line written to the screen
446 ----------------------------------------------------------------------*/
447 void
448 Write_to_screen(char *string)
450 if(ps_global->in_init_seq)
451 return;
453 mswin_puts (string);
456 * mswin_puts does not keep track of where we are. Simple fix is to
457 * reset _line and _col to unknown so that the next MoveCursor will
458 * do a real move. We could check for a simple string and actually
459 * keep track. Is that useful? I don't think so.
461 * There are other places where we lose track, but by comparing with
462 * the termout.unx code where we also lose track it would seem we don't
463 * really need to keep track in those other cases.
465 _line = FARAWAY;
466 _col = FARAWAY;
469 void
470 Write_to_screen_n(char *string, int n)
472 if(ps_global->in_init_seq)
473 return;
475 mswin_puts_n (string, n);
476 _line = FARAWAY;
477 _col = FARAWAY;
481 /*----------------------------------------------------------------------
482 Clear the terminal screen
483 ----------------------------------------------------------------------*/
484 void
485 ClearScreen(void)
487 _line = 0; /* clear leaves us at top... */
488 _col = 0;
490 if(ps_global->in_init_seq)
491 return;
493 mark_status_unknown();
494 mark_keymenu_dirty();
495 mark_titlebar_dirty();
497 mswin_move(0, 0);
498 mswin_eeop();
501 /*----------------------------------------------------------------------
502 Clear screen to end of line on current line
503 ----------------------------------------------------------------------*/
504 void
505 CleartoEOLN(void)
507 mswin_eeol();
511 /*----------------------------------------------------------------------
512 function to output string such that it becomes icon text
514 Args: s -- string to write
516 Result: string indicated become our "icon" text
517 ----*/
518 void
519 icon_text(char *s, int type)
521 if(type == IT_MCLOSED)
522 mswin_mclosedtext (s);
523 else /* IT_NEWMAIL */
524 mswin_newmailtext (s);
527 /* Scroll stuff */
530 * Set the current position of the scroll bar.
532 void
533 scroll_setpos(long newpos)
535 mswin_setscrollpos (newpos);
539 * Set the range of the scroll bar.
540 * zero disables the scroll bar.
542 void
543 scroll_setrange (long pagelen, long rangeend)
545 if(rangeend < pagelen)
546 mswin_setscrollrange (0L, 0L);
547 else
548 mswin_setscrollrange (pagelen, rangeend + pagelen - 1L);
551 void
552 EndScroll(void)
557 ScrollRegion(int lines)
559 return(-1);
563 BeginScroll(int top, int bottom)
565 static int __t, __b;
567 __t = top;
568 __b = bottom;
569 return(-1);
573 /* Dialog stuff */
574 #define WINDOW_USER_DATA GWL_USERDATA
576 /*===========================================================================
578 * Dialog Data
580 * The following structures hold the state data for dialogs.
582 typedef struct DLG_TYPEMAP {
583 int pineid;
584 int rsrcid;
585 } DLG_TYPEMAP;
587 typedef struct DLG_SORTDATA {
588 DLG_SORTPARAM *sortsel; /* parameter structure. */
589 int sortcount; /* Number of different sorts. */
590 DLG_TYPEMAP types[20]; /* Map pine sort types to ctrl ids. */
591 } DLG_SORTDATA;
593 typedef struct DLG_LOGINDATA {
594 NETMBX *mb;
595 LPTSTR user;
596 int userlen;
597 LPTSTR pwd;
598 int pwdlen;
599 int pwc; /* set if we're using passfiles and we don't know user yet */
600 int fixuser;
601 int prespass; /* if user wants to preserve the password */
602 int rv;
603 } DLG_LOGINDATA;
605 typedef struct DLG_CONFIGDATA {
606 char *confpath; /* UTF-8 path */
607 int confpathlen;
608 int setreg;
609 int nopinerc;
610 int rv;
611 } DLG_CONFIGDATA;
613 typedef struct installvars {
614 char *pname;
615 char *userid;
616 char *domain;
617 char *inboxpath;
618 char *smtpserver;
619 unsigned defmailclient:1;
620 unsigned defnewsclient:1;
621 } INSTALLVARS_S;
623 typedef struct DLG_CONGIGVARSDATA {
624 INSTALLVARS_S *ivars;
625 int rv;
626 } DLG_CONFIGVARSDATA;
628 typedef struct DLG_FLAGDATA {
629 struct flag_table *ftbl;
630 int flagcount;
631 HINSTANCE hInstance;
632 HWND hTextWnd;
633 } DLG_FLAGDATA;
635 int os_config_vars_dialog(INSTALLVARS_S *);
636 static void GetBtnPos (HWND, HWND, RECT *);
639 init_install_get_vars(void)
641 INSTALLVARS_S ivars;
642 struct pine *ps = ps_global;
643 char *p;
645 memset((void *)&ivars, 0, sizeof(INSTALLVARS_S));
646 if(ps->vars[V_PERSONAL_NAME].main_user_val.p)
647 ivars.pname = cpystr(ps->vars[V_PERSONAL_NAME].main_user_val.p);
648 if(ps->vars[V_USER_ID].main_user_val.p)
649 ivars.userid = cpystr(ps->vars[V_USER_ID].main_user_val.p);
650 if(ps->vars[V_USER_DOMAIN].main_user_val.p)
651 ivars.domain = cpystr(ps->vars[V_USER_DOMAIN].main_user_val.p);
652 if(ps->vars[V_INBOX_PATH].main_user_val.p)
653 ivars.inboxpath = cpystr(ps->vars[V_INBOX_PATH].main_user_val.p);
654 else if(ps->prc && ps->prc->name && (*ps->prc->name == '{')
655 && (p = strindex(ps->prc->name, '}'))){
656 ivars.inboxpath = cpystr(ps->prc->name);
657 if(p = strindex(ivars.inboxpath, '}'))
658 *(p+1) = '\0';
660 if(ps->vars[V_SMTP_SERVER].main_user_val.l
661 && *ps->vars[V_SMTP_SERVER].main_user_val.l)
662 ivars.smtpserver = cpystr(ps->vars[V_SMTP_SERVER].main_user_val.l[0]);
663 ivars.defmailclient = mswin_is_def_client(MSWR_SDC_MAIL);
664 ivars.defnewsclient = mswin_is_def_client(MSWR_SDC_NEWS);
666 if(os_config_vars_dialog(&ivars) == 0){
667 set_variable(V_PERSONAL_NAME, ivars.pname, 0, 0, Main);
668 set_variable(V_USER_ID, ivars.userid, 0, 0, Main);
669 set_variable(V_USER_DOMAIN, ivars.domain, 0, 0, Main);
670 set_variable(V_INBOX_PATH, ivars.inboxpath, 0, 0, Main);
671 if(ivars.smtpserver){
672 if(ps->vars[V_SMTP_SERVER].main_user_val.l){
673 fs_give((void **)&ps->vars[V_SMTP_SERVER].main_user_val.l[0]);
674 ps->vars[V_SMTP_SERVER].main_user_val.l[0]
675 = cpystr(ivars.smtpserver);
676 set_current_val(&ps->vars[V_SMTP_SERVER], TRUE, FALSE);
678 else {
679 char *tstrlist[2];
681 tstrlist[0] = ivars.smtpserver;
682 tstrlist[1] = NULL;
683 set_variable_list(V_SMTP_SERVER, tstrlist, 0, Main);
686 write_pinerc(ps_global, Main, WRP_NONE);
687 if(ivars.defmailclient)
688 mswin_set_def_client(MSWR_SDC_MAIL);
689 if(ivars.defnewsclient)
690 mswin_set_def_client(MSWR_SDC_NEWS);
692 /* Tell Windows that stuff has changed */
693 if(ivars.defmailclient || ivars.defnewsclient)
694 SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE,
695 (WPARAM)NULL, (LPARAM)NULL,
696 SMTO_NORMAL, 1000, NULL);
699 if(ivars.pname)
700 fs_give((void **)&ivars.pname);
701 if(ivars.userid)
702 fs_give((void **)&ivars.userid);
703 if(ivars.domain)
704 fs_give((void **)&ivars.domain);
705 if(ivars.inboxpath)
706 fs_give((void **)&ivars.inboxpath);
707 if(ivars.smtpserver)
708 fs_give((void **)&ivars.smtpserver);
709 return 0;
713 * Show args dialog
716 os_argsdialog (char **arg_text)
718 DLGPROC dlgprc;
719 HINSTANCE hInst;
720 HWND hWnd;
722 hInst = (HINSTANCE) mswin_gethinstance ();
723 hWnd = (HWND) mswin_gethwnd ();
725 mswin_killsplash();
727 dlgprc = args_dialog_proc;
729 DialogBoxParam (hInst, MAKEINTRESOURCE (IDD_ARGLIST), hWnd,
730 dlgprc, (LPARAM) arg_text);
732 return(1);
736 * Prompt for username and password
739 os_login_dialog (NETMBX *mb, char *user_utf8, int userlen,
740 char *pwd_utf8, int pwdlen, int pwc, int fixuser, int *prespass)
742 DLGPROC dlgprc;
743 HINSTANCE hInst;
744 HWND hWnd;
745 DLG_LOGINDATA dlgpw;
746 LPTSTR user_lptstr, pwd_lptstr;
747 char *tuser_utf8, *tpwd_utf8;
749 mswin_killsplash();
750 hInst = (HINSTANCE) mswin_gethinstance ();
751 hWnd = (HWND) mswin_gethwnd ();
753 dlgpw.mb = mb;
755 dlgpw.user = (LPTSTR)fs_get(userlen*sizeof(TCHAR));
756 user_lptstr = utf8_to_lptstr(user_utf8);
757 _tcsncpy(dlgpw.user, user_lptstr, userlen - 1);
758 dlgpw.user[userlen - 1] = '\0';
759 fs_give((void **) &user_lptstr);
760 dlgpw.userlen = userlen;
762 dlgpw.pwd = (LPTSTR)fs_get(pwdlen*sizeof(TCHAR));
763 pwd_lptstr = utf8_to_lptstr(pwd_utf8);
764 _tcsncpy(dlgpw.pwd, pwd_lptstr, pwdlen - 1);
765 dlgpw.pwd[pwdlen - 1] = '\0';
766 fs_give((void **) &pwd_lptstr);
767 dlgpw.pwdlen = pwdlen;
769 dlgpw.fixuser = fixuser;
770 dlgpw.pwc = pwc;
771 dlgpw.rv = 0;
773 dlgprc = login_dialog_proc;
775 DialogBoxParam (hInst, MAKEINTRESOURCE (ps_global->install_flag
776 ? IDD_LOGINDLG2 : IDD_LOGINDLG),
777 NULL, dlgprc, (LPARAM)&dlgpw);
779 if(dlgpw.rv == 0){
780 tuser_utf8 = lptstr_to_utf8(dlgpw.user);
781 if(tuser_utf8){
782 strncpy(user_utf8, tuser_utf8, userlen - 1);
783 user_utf8[userlen - 1] = '\0';
784 fs_give((void **) &tuser_utf8);
787 tpwd_utf8 = lptstr_to_utf8(dlgpw.pwd);
788 if(tpwd_utf8){
789 strncpy(pwd_utf8, tpwd_utf8, pwdlen - 1);
790 pwd_utf8[pwdlen - 1] = '\0';
791 fs_give((void **) &tpwd_utf8);
793 if(prespass)
794 (*prespass) = dlgpw.prespass;
797 return(dlgpw.rv);
801 * Select message flags.
804 os_flagmsgdialog (struct flag_table *ftbl)
806 DLGPROC dlgprc;
807 HINSTANCE hInst;
808 HWND hWnd;
809 DLG_FLAGDATA dlgflag;
810 int rval;
812 hInst = (HINSTANCE) mswin_gethinstance ();
813 hWnd = (HWND) mswin_gethwnd ();
815 dlgflag.ftbl = ftbl;
816 dlgflag.hInstance = hInst;
817 dlgflag.hTextWnd = hWnd;
819 dlgprc = flag_dialog_proc;
821 rval = DialogBoxParam (hInst, MAKEINTRESOURCE (IDD_SELECTFLAG), hWnd,
822 dlgprc, (LPARAM)&dlgflag);
824 return (rval);
828 * Select a sort type.
832 os_sortdialog (DLG_SORTPARAM *sortsel)
834 DLGPROC dlgprc;
835 HINSTANCE hInst;
836 HWND hWnd;
837 int i;
838 DLG_SORTDATA dlgsort;
840 hInst = (HINSTANCE) mswin_gethinstance ();
841 hWnd = (HWND) mswin_gethwnd ();
844 /* Build a map of pine sort types to the resource types. */
845 i = 0;
846 dlgsort.types[i].pineid = SortArrival;
847 dlgsort.types[i++].rsrcid = IDC_SORTARRIVAL;
848 dlgsort.types[i].pineid = SortDate;
849 dlgsort.types[i++].rsrcid = IDC_SORTDATE;
850 dlgsort.types[i].pineid = SortFrom;
851 dlgsort.types[i++].rsrcid = IDC_SORTFROM;
852 dlgsort.types[i].pineid = SortSubject;
853 dlgsort.types[i++].rsrcid = IDC_SORTSUBJECT;
854 dlgsort.types[i].pineid = SortSubject2;
855 dlgsort.types[i++].rsrcid = IDC_SORTORDERSUB;
856 dlgsort.types[i].pineid = SortTo;
857 dlgsort.types[i++].rsrcid = IDC_SORTTO;
858 dlgsort.types[i].pineid = SortCc;
859 dlgsort.types[i++].rsrcid = IDC_SORTCC;
860 dlgsort.types[i].pineid = SortSize;
861 dlgsort.types[i++].rsrcid = IDC_SORTSIZE;
862 dlgsort.types[i].pineid = SortThread;
863 dlgsort.types[i++].rsrcid = IDC_SORTTHREAD;
864 dlgsort.types[i].pineid = SortScore;
865 dlgsort.types[i++].rsrcid = IDC_SORTSCORE;
866 dlgsort.sortcount = i;
867 dlgsort.sortsel = sortsel;
869 dlgprc = sort_dialog_proc;
871 DialogBoxParam (hInst, MAKEINTRESOURCE (IDD_SELECTSORT), hWnd,
872 dlgprc, (LPARAM)&dlgsort);
874 return(1);
879 * Dialog proc to handle index sort selection.
881 * Configures the dialog box on init and retrieves the settings on exit.
883 BOOL CALLBACK __export
884 args_dialog_proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
886 BOOL ret = FALSE;
887 long i, j, block_size;
888 char **args_text;
889 LPTSTR args_text_lptstr, args_block_lptstr;
892 switch (uMsg) {
893 case WM_INITDIALOG:
895 args_text = (char **)lParam;
898 * First convert char *'s over to one big block of
899 * Unicode
901 i = 0;
902 while(args_text && *args_text){
903 i += strlen(*args_text++);
904 i += 2;
906 block_size = i;
908 args_block_lptstr = (LPTSTR)fs_get((block_size+1)*sizeof(TCHAR));
910 args_text = (char **)lParam;
911 i = 0;
912 j = 0;
913 while(args_text && *args_text){
914 args_text_lptstr = utf8_to_lptstr(*args_text++);
915 while(args_text_lptstr[i] && j < block_size){
916 args_block_lptstr[j++] = args_text_lptstr[i++];
918 args_block_lptstr[j++] = '\r';
919 args_block_lptstr[j++] = '\n';
920 fs_give((void **) &args_text_lptstr);
921 i = 0;
923 args_block_lptstr[j] = '\0';
925 /* and replace everything selected with args_text */
926 SendDlgItemMessage(hDlg, IDC_ARGTEXT, WM_SETTEXT, (WPARAM) 0,
927 (LPARAM) args_block_lptstr);
928 fs_give((void **)&args_block_lptstr);
930 return (1);
932 case WM_CLOSE :
933 ret = TRUE;
934 EndDialog (hDlg, TRUE);
935 break;
938 case WM_COMMAND:
939 switch (wParam) {
940 case IDOK:
941 ret = TRUE;
942 EndDialog (hDlg, TRUE);
943 break;
945 break;
949 return (ret);
953 * Dialog proc to handle login
955 * Configures the dialog box on init and retrieves the settings on exit.
957 BOOL CALLBACK __export
958 login_dialog_proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
960 DLG_LOGINDATA *dlglogin;
961 BOOL ret = FALSE;
962 TCHAR tcbuf[1024];
963 NETMBX *mb;
964 LPTSTR user, pwd;
965 LPTSTR host_lptstr;
967 switch (uMsg) {
968 case WM_INITDIALOG:
970 dlglogin = (DLG_LOGINDATA *)lParam;
971 mb = dlglogin->mb;
972 user = dlglogin->user;
973 pwd = dlglogin->pwd;
974 SetWindowLong (hDlg, WINDOW_USER_DATA, (LONG) dlglogin);
976 host_lptstr = utf8_to_lptstr(mb->host);
977 _sntprintf(tcbuf, sizeof(tcbuf), TEXT("Host: %.100s%s"), host_lptstr,
978 !mb->sslflag && !mb->tlsflag ? TEXT(" (INSECURE)") : TEXT(""));
979 fs_give((void **) &host_lptstr);
981 if(mb->sslflag || mb->tlsflag)
982 SetWindowText(hDlg, TEXT("Alpine Login +"));
983 else
984 SetWindowText(hDlg, TEXT("Alpine Insecure Login"));
986 if(dlglogin->pwc){
987 EnableWindow(GetDlgItem(hDlg, IDC_RPASSWORD),0);
988 EnableWindow(GetDlgItem(hDlg, IDC_RPWTEXT),0);
989 EnableWindow(GetDlgItem(hDlg, IDC_PRESPASS),0);
991 if(mb->user && *mb->user){
992 LPTSTR user_lptstr;
994 user_lptstr = utf8_to_lptstr(mb->user);
995 SetDlgItemText(hDlg, IDC_RLOGINE, user_lptstr);
996 if((mb->user && *mb->user) || dlglogin->fixuser)
997 EnableWindow(GetDlgItem(hDlg, IDC_RLOGINE), 0);
998 fs_give((void **) &user_lptstr);
1000 else if(user){
1001 SetDlgItemText(hDlg, IDC_RLOGINE, user);
1002 if(dlglogin->fixuser)
1003 EnableWindow(GetDlgItem(hDlg, IDC_RLOGINE), 0);
1005 SetDlgItemText(hDlg, IDC_PROMPT, tcbuf);
1006 return (1);
1009 case WM_COMMAND:
1010 dlglogin = (DLG_LOGINDATA *) GetWindowLong (hDlg, WINDOW_USER_DATA);
1011 switch (wParam) {
1012 case IDOK:
1013 /* Retrieve the new username/passwd. */
1014 user = dlglogin->user;
1015 pwd = dlglogin->pwd;
1016 GetDlgItemText(hDlg, IDC_RLOGINE, user, dlglogin->userlen - 1);
1017 GetDlgItemText(hDlg, IDC_RPASSWORD, pwd, dlglogin->pwdlen - 1);
1018 user[dlglogin->userlen - 1] = '\0';
1019 pwd[dlglogin->pwdlen - 1] = '\0';
1020 dlglogin->prespass = (IsDlgButtonChecked(hDlg, IDC_PRESPASS) == BST_CHECKED);
1022 EndDialog (hDlg, LOWORD(wParam));
1023 dlglogin->rv = 0;
1024 ret = TRUE;
1025 break;
1027 case IDCANCEL:
1028 dlglogin->rv = 1;
1029 ret = TRUE;
1030 EndDialog (hDlg, LOWORD(wParam));
1031 break;
1033 break;
1035 return (ret);
1039 * Dialog proc to handle flag selection.
1041 * Configures the dialog box on init, adding buttons as needed for
1042 * an unknown number of flags.
1043 * Retrieves the settings on exit.
1045 BOOL CALLBACK __export
1046 flag_dialog_proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
1048 DLG_FLAGDATA *dlgflag;
1049 BOOL ret = FALSE;
1050 int i;
1051 struct flag_table *fp;
1052 HWND hRB[2], hBtn;
1053 RECT rb[2];
1054 UINT bheight, bwidth, bvertSpace;
1055 UINT btnOKHeight;
1056 int base, line;
1057 int bstate;
1058 HFONT btnFont;
1063 switch (uMsg) {
1064 case WM_INITDIALOG:
1065 dlgflag = (DLG_FLAGDATA *)lParam;
1066 SetWindowLong (hDlg, WINDOW_USER_DATA, (LONG) dlgflag);
1068 /* Count buttons */
1069 dlgflag->flagcount = 0;
1070 for (fp = dlgflag->ftbl; fp && fp->name; ++fp)
1071 ++dlgflag->flagcount;
1073 /* Get the positions of the current buttons. */
1074 for (i = 0; i < 2; ++i) {
1075 hRB[i] = GetDlgItem (hDlg, IDC_FLAGCOL1 + i);
1076 GetBtnPos (hDlg, hRB[i], &rb[i]);
1078 bheight = rb[0].bottom - rb[0].top;
1079 bwidth = rb[0].right - rb[0].left;
1080 bvertSpace = bheight + 5;
1081 btnFont = (HFONT) SendMessage (hRB[0], WM_GETFONT, 0, 0);
1083 for (i = 0; i < dlgflag->flagcount; ++i) {
1084 LPTSTR fp_name_lptstr;
1086 fp = &dlgflag->ftbl[i];
1088 fp_name_lptstr = utf8_to_lptstr(fp->name);
1089 if (i < 2) {
1090 hBtn = hRB[i];
1091 SetWindowText (hBtn, fp_name_lptstr);
1093 else {
1094 base = i % 2;
1095 line = i / 2;
1096 hBtn = CreateWindow (TEXT("BUTTON"), fp_name_lptstr,
1097 WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
1098 rb[base].left, rb[base].top + bvertSpace * line,
1099 bwidth, bheight,
1100 hDlg, (HMENU)NULL, dlgflag->hInstance, NULL);
1101 SetWindowLong (hBtn, GWL_ID, IDC_FLAGCOL1 + i);
1102 SendMessage (hBtn, WM_SETFONT, (WPARAM)btnFont,
1103 MAKELPARAM (0, 0));
1106 fs_give((void **) &fp_name_lptstr);
1107 if (fp->ukn)
1108 SendMessage (hBtn, BM_SETSTYLE,
1109 (WPARAM)(BS_CHECKBOX | BS_AUTO3STATE), 0);
1110 SendMessage (hBtn, BM_SETCHECK,
1111 (WPARAM) fp->set == CMD_FLAG_UNKN ? 2 : fp->set ? 1 : 0,
1113 ShowWindow (hBtn, SW_SHOW);
1114 EnableWindow (hBtn, TRUE);
1117 /* Position the OK and Cancel buttons. */
1118 line = (dlgflag->flagcount + 1) / 2;
1119 for (i = 0; i < 2; ++i) {
1120 hRB[1] = GetDlgItem (hDlg, i == 0 ? IDOK : IDCANCEL);
1121 GetBtnPos (hDlg, hRB[1], &rb[1]);
1122 MoveWindow (hRB[1], rb[1].left, rb[0].top + bvertSpace * line,
1123 rb[1].right - rb[1].left, rb[1].bottom - rb[1].top,
1124 FALSE);
1125 btnOKHeight = rb[1].bottom - rb[1].top;
1129 /* Resize whole dialog window. */
1130 GetWindowRect (hDlg, &rb[1]);
1131 rb[1].right -= rb[1].left;
1132 rb[1].bottom = rb[0].top + bvertSpace * line + btnOKHeight + 10 +
1133 GetSystemMetrics (SM_CYCAPTION);
1134 MoveWindow (hDlg, rb[1].left, rb[1].top, rb[1].right,
1135 rb[1].bottom, TRUE);
1136 return (1);
1139 case WM_COMMAND:
1140 dlgflag = (DLG_FLAGDATA *) GetWindowLong (hDlg, WINDOW_USER_DATA);
1141 switch (wParam) {
1143 case IDOK:
1144 /* Retrieve the button states. */
1145 for (i = 0; i < dlgflag->flagcount; ++i) {
1146 fp = &dlgflag->ftbl[i];
1147 bstate = SendMessage (GetDlgItem (hDlg, IDC_FLAGCOL1 + i),
1148 BM_GETCHECK, 0, 0);
1149 switch (bstate) {
1150 case 2: fp->set = CMD_FLAG_UNKN; break;
1151 case 1: fp->set = CMD_FLAG_SET; break;
1152 case 0: fp->set = CMD_FLAG_CLEAR; break;
1155 EndDialog (hDlg, TRUE);
1156 ret = TRUE;
1157 break;
1159 case IDCANCEL:
1160 EndDialog (hDlg, FALSE);
1161 ret = TRUE;
1162 break;
1164 break;
1168 return (ret);
1172 * Dialog proc to handle index sort selection.
1174 * Configures the dialog box on init and retrieves the settings on exit.
1176 BOOL CALLBACK __export
1177 sort_dialog_proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
1179 DLG_SORTDATA *dlgsort;
1180 BOOL ret = FALSE;
1181 int cursort;
1182 int i;
1185 switch (uMsg) {
1186 case WM_INITDIALOG:
1187 dlgsort = (DLG_SORTDATA *)lParam;
1188 SetWindowLong (hDlg, WINDOW_USER_DATA, (LONG) dlgsort);
1190 /* Set the reversed button state. */
1191 CheckDlgButton (hDlg, IDC_SORTREVERSE, dlgsort->sortsel->reverse);
1193 /* Set the current sort type radio button.*/
1194 cursort = IDC_SORTARRIVAL;
1195 for (i = 0; i < dlgsort->sortcount; ++i) {
1196 if (dlgsort->types[i].pineid == dlgsort->sortsel->cursort) {
1197 cursort = dlgsort->types[i].rsrcid;
1198 break;
1201 CheckRadioButton (hDlg, IDC_SORTFIRSTBUTTON, IDC_SORTLASTBUTTON,
1202 cursort);
1204 EnableWindow (GetDlgItem (hDlg, IDC_GETHELP),
1205 (dlgsort->sortsel->helptext != NULL));
1206 return (1);
1209 case WM_COMMAND:
1210 dlgsort = (DLG_SORTDATA *) GetWindowLong (hDlg, WINDOW_USER_DATA);
1211 switch (wParam) {
1212 case IDC_GETHELP:
1213 if (dlgsort->sortsel->helptext)
1214 mswin_showhelpmsg ((WINHAND)hDlg, dlgsort->sortsel->helptext);
1215 ret = TRUE;
1216 break;
1218 case IDOK:
1219 dlgsort->sortsel->rval = 1;
1221 /* Retrieve the reverse sort state. */
1222 dlgsort->sortsel->reverse = (IsDlgButtonChecked (hDlg, IDC_SORTREVERSE) == 1);
1224 /* Retrieve the new sort type. */
1225 for (i = 0; i < dlgsort->sortcount; ++i) {
1226 if (IsDlgButtonChecked (hDlg, dlgsort->types[i].rsrcid)) {
1227 dlgsort->sortsel->cursort = dlgsort->types[i].pineid;
1228 break;
1231 EndDialog (hDlg, dlgsort->sortsel->rval);
1232 ret = TRUE;
1233 break;
1235 case IDCANCEL:
1236 dlgsort->sortsel->rval = 0;
1237 ret = TRUE;
1238 EndDialog (hDlg, dlgsort->sortsel->rval);
1239 break;
1241 break;
1245 return (ret);
1249 os_config_vars_dialog (INSTALLVARS_S *ivars)
1251 DLGPROC dlgprc;
1252 HINSTANCE hInst;
1253 HWND hWnd;
1254 DLG_CONFIGVARSDATA dlgcv;
1256 mswin_killsplash();
1257 hInst = (HINSTANCE) mswin_gethinstance ();
1258 hWnd = (HWND) mswin_gethwnd ();
1260 dlgcv.ivars = ivars;
1261 dlgcv.rv = 0;
1263 dlgprc = config_vars_dialog_proc;
1265 DialogBoxParam (hInst, MAKEINTRESOURCE (IDD_CFVARSDLG), NULL,
1266 dlgprc, (LPARAM)&dlgcv);
1268 return(dlgcv.rv);
1272 * Dialog proc to handle login
1274 * Configures the dialog box on init and retrieves the settings on exit.
1276 BOOL CALLBACK __export
1277 config_vars_dialog_proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
1279 DLG_CONFIGVARSDATA *dlgcv;
1280 BOOL ret = FALSE;
1281 int usepop = 0;
1282 char buf[2*MAXPATH+1], *p;
1283 int buflen = 2*MAXPATH;
1284 #define TCBUFLEN (2*MAXPATH)
1285 TCHAR tcbuf[TCBUFLEN+1];
1286 LPTSTR tmp_lptstr;
1287 char *u;
1289 switch (uMsg) {
1290 case WM_INITDIALOG:
1291 dlgcv = (DLG_CONFIGVARSDATA *)lParam;
1292 SetWindowLong (hDlg, WINDOW_USER_DATA, (LONG) dlgcv);
1293 if(dlgcv->ivars->pname){
1294 tmp_lptstr = utf8_to_lptstr(dlgcv->ivars->pname);
1295 if(tmp_lptstr){
1296 SetDlgItemText(hDlg, IDC_CFV_PNAME, tmp_lptstr);
1297 fs_give((void **) &tmp_lptstr);
1301 if(dlgcv->ivars->userid && dlgcv->ivars->domain){
1302 snprintf(buf, sizeof(buf), "%.*s@%.*s", MAXPATH, dlgcv->ivars->userid,
1303 MAXPATH, dlgcv->ivars->domain);
1304 buf[buflen-1] = '\0';
1305 tmp_lptstr = utf8_to_lptstr(buf);
1306 if(tmp_lptstr){
1307 SetDlgItemText(hDlg, IDC_CFV_EMAILADR, tmp_lptstr);
1308 fs_give((void **) &tmp_lptstr);
1312 if(dlgcv->ivars->inboxpath){
1313 char *mbx;
1315 mbx = dlgcv->ivars->inboxpath;
1316 if(*mbx == '{' && (p = strindex(mbx, '}'))
1317 && ((*(p+1) == '\0') || !strucmp(p+1, "inbox"))){
1318 char srvbuf[MAXPATH+1], tuser[MAXPATH+1];
1319 int i, j, k;
1321 srvbuf[0] = '\0';
1322 tuser[0] = '\0';
1323 strncpy(buf, mbx+1, min(buflen, (int)(p - (mbx+1))));
1324 buf[min(buflen-1, (int)(p - (mbx+1)))] = '\0';
1325 for(i = 0, j = 0; buf[i] && j < MAXPATH; i++){
1326 if(buf[i] == '/'){
1327 if(!struncmp("/user=", buf+i, 6)){
1328 i += 6;
1329 for(k = 0; k < MAXPATH && buf[i]
1330 && buf[i] != '/'; i++)
1331 tuser[k++] = buf[i];
1332 tuser[k] = '\0';
1333 i--;
1335 else if(!struncmp("/pop3", buf+i, 5)
1336 && (!*(buf+5) || (*(buf+5) == '/'))){
1337 usepop = 1;
1338 i += 4;
1340 else
1341 srvbuf[j++] = buf[i];
1343 else
1344 srvbuf[j++] = buf[i];
1346 srvbuf[j] = '\0';
1347 if(*srvbuf){
1348 tmp_lptstr = utf8_to_lptstr(srvbuf);
1349 if(tmp_lptstr){
1350 SetDlgItemText(hDlg, IDC_CFV_MSERVER, tmp_lptstr);
1351 fs_give((void **) &tmp_lptstr);
1355 if(*tuser){
1356 tmp_lptstr = utf8_to_lptstr(tuser);
1357 if(tmp_lptstr){
1358 SetDlgItemText(hDlg, IDC_CFV_LOGIN, tmp_lptstr);
1359 fs_give((void **) &tmp_lptstr);
1363 else {
1364 tmp_lptstr = utf8_to_lptstr(mbx);
1365 if(tmp_lptstr){
1366 SetDlgItemText(hDlg, IDC_CFV_MSERVER, tmp_lptstr);
1367 fs_give((void **) &tmp_lptstr);
1370 if(*mbx != '{' && *mbx != '#')
1371 EnableWindow(GetDlgItem(hDlg, IDC_CFV_MSERVER), 0);
1374 CheckRadioButton (hDlg, IDC_CFV_IMAP, IDC_CFV_POP3,
1375 usepop ? IDC_CFV_POP3 : IDC_CFV_IMAP);
1376 if(dlgcv->ivars->smtpserver){
1377 tmp_lptstr = utf8_to_lptstr(dlgcv->ivars->smtpserver);
1378 if(tmp_lptstr){
1379 SetDlgItemText(hDlg, IDC_CFV_SMTPSERVER, tmp_lptstr);
1380 fs_give((void **) &tmp_lptstr);
1384 if(dlgcv->ivars->defmailclient)
1385 CheckDlgButton(hDlg, IDC_CFV_DEFMAILER, BST_CHECKED);
1386 if(dlgcv->ivars->defnewsclient)
1387 CheckDlgButton(hDlg, IDC_CFV_DEFNEWSRDR, BST_CHECKED);
1389 return (1);
1390 break;
1392 case WM_COMMAND:
1393 dlgcv = (DLG_CONFIGVARSDATA *) GetWindowLong (hDlg, WINDOW_USER_DATA);
1394 switch (wParam) {
1395 case IDOK:
1396 /* personal name */
1397 GetDlgItemText(hDlg, IDC_CFV_PNAME, tcbuf, TCBUFLEN);
1398 tcbuf[TCBUFLEN] = '\0';
1399 u = lptstr_to_utf8(tcbuf);
1400 if(u){
1401 removing_leading_and_trailing_white_space(u);
1402 if(dlgcv->ivars->pname)
1403 fs_give((void **)&dlgcv->ivars->pname);
1405 if(*u){
1406 dlgcv->ivars->pname = u;
1407 u = NULL;
1410 if(u)
1411 fs_give((void **) &u);
1414 /* user-id and domain */
1415 GetDlgItemText(hDlg, IDC_CFV_EMAILADR, tcbuf, TCBUFLEN);
1416 tcbuf[TCBUFLEN] = '\0';
1417 u = lptstr_to_utf8(tcbuf);
1418 if(u){
1419 removing_leading_and_trailing_white_space(u);
1420 if(p = strindex(u, '@')){
1421 *(p++) = '\0';
1422 if(dlgcv->ivars->userid)
1423 fs_give((void **)&dlgcv->ivars->userid);
1425 if(dlgcv->ivars->domain)
1426 fs_give((void **)&dlgcv->ivars->domain);
1428 if(*u){
1429 dlgcv->ivars->userid = u;
1430 u = NULL;
1433 if(*p)
1434 dlgcv->ivars->domain = cpystr(p);
1436 else{
1437 MessageBox(hDlg, TEXT("Invalid email address. Should be username@domain"),
1438 TEXT("Alpine"), MB_ICONWARNING | MB_OK);
1439 return(TRUE);
1442 if(u)
1443 fs_give((void **) &u);
1446 /* inbox-path */
1447 GetDlgItemText(hDlg, IDC_CFV_MSERVER, tcbuf, TCBUFLEN);
1448 tcbuf[TCBUFLEN] = '\0';
1449 u = lptstr_to_utf8(tcbuf);
1450 if(u){
1451 removing_leading_and_trailing_white_space(u);
1452 if(*u == '{' || *u == '#'
1453 || !IsWindowEnabled(GetDlgItem(hDlg, IDC_CFV_MSERVER))){
1454 if(dlgcv->ivars->inboxpath)
1455 fs_give((void **)&dlgcv->ivars->inboxpath);
1457 dlgcv->ivars->inboxpath = u;
1458 u = NULL;
1460 else if(*u){
1461 char tsrvr[4*MAXPATH+1];
1462 int tsrvrlen = 4*MAXPATH;
1464 if(dlgcv->ivars->inboxpath)
1465 fs_give((void **)&dlgcv->ivars->inboxpath);
1467 snprintf(tsrvr, sizeof(tsrvr), "{%s%s", u,
1468 IsDlgButtonChecked(hDlg, IDC_CFV_POP3)
1469 == BST_CHECKED ? "/pop3" : "");
1471 if(u)
1472 fs_give((void **) &u);
1474 GetDlgItemText(hDlg, IDC_CFV_LOGIN, tcbuf, TCBUFLEN);
1475 tcbuf[TCBUFLEN] = '\0';
1476 u = lptstr_to_utf8(tcbuf);
1477 if(u){
1478 removing_leading_and_trailing_white_space(u);
1479 if(*u){
1480 strncat(tsrvr, "/user=", sizeof(tsrvr)-strlen(tsrvr)-1);
1481 strncat(tsrvr, u, sizeof(tsrvr)-strlen(tsrvr)-1);
1484 strncat(tsrvr, "}inbox", sizeof(tsrvr)-strlen(tsrvr)-1);
1485 tsrvr[sizeof(tsrvr)-1] = '\0';
1486 dlgcv->ivars->inboxpath = cpystr(tsrvr);
1490 if(u)
1491 fs_give((void **) &u);
1494 /* smtp-server */
1495 GetDlgItemText(hDlg, IDC_CFV_SMTPSERVER, tcbuf, TCBUFLEN);
1496 tcbuf[TCBUFLEN] = '\0';
1497 u = lptstr_to_utf8(tcbuf);
1498 if(u){
1499 removing_leading_and_trailing_white_space(u);
1500 if(dlgcv->ivars->smtpserver)
1501 fs_give((void **)&dlgcv->ivars->smtpserver);
1503 if(*u){
1504 dlgcv->ivars->smtpserver = u;
1505 u = NULL;
1508 if(u)
1509 fs_give((void **) &u);
1512 dlgcv->ivars->defmailclient =
1513 (IsDlgButtonChecked(hDlg, IDC_CFV_DEFMAILER)
1514 == BST_CHECKED);
1515 dlgcv->ivars->defnewsclient =
1516 (IsDlgButtonChecked(hDlg, IDC_CFV_DEFNEWSRDR)
1517 == BST_CHECKED);
1519 EndDialog (hDlg, LOWORD(wParam));
1520 dlgcv->rv = 0;
1521 ret = TRUE;
1522 break;
1524 case IDCANCEL:
1525 dlgcv->rv = 1;
1526 ret = TRUE;
1527 EndDialog (hDlg, LOWORD(wParam));
1528 break;
1530 break;
1534 return (ret);
1538 * Prompt for config location
1542 os_config_dialog (char *utf8_buf, int utf8_buflen,
1543 int *regset, int nopinerc)
1545 DLGPROC dlgprc;
1546 HINSTANCE hInst;
1547 HWND hWnd;
1548 DLG_CONFIGDATA dlgcfg;
1550 mswin_killsplash();
1551 hInst = (HINSTANCE) mswin_gethinstance ();
1552 hWnd = (HWND) mswin_gethwnd ();
1554 dlgcfg.confpath = utf8_buf;
1555 dlgcfg.confpathlen = utf8_buflen;
1556 dlgcfg.setreg = 0;
1557 dlgcfg.nopinerc = nopinerc;
1558 dlgcfg.rv = 0;
1560 dlgprc = config_dialog_proc;
1562 DialogBoxParam (hInst, MAKEINTRESOURCE (IDD_CONFIGDLG), NULL,
1563 dlgprc, (LPARAM)&dlgcfg);
1565 *regset = dlgcfg.setreg;
1566 return(dlgcfg.rv);
1571 * Dialog proc to handle login
1573 * Configures the dialog box on init and retrieves the settings on exit.
1575 BOOL CALLBACK __export
1576 config_dialog_proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
1578 DLG_CONFIGDATA *dlgcfg;
1579 BOOL ret = FALSE;
1580 int checked, def_rem_fldr = 1, def_diff_fldr = 0;
1582 switch (uMsg) {
1583 case WM_INITDIALOG:
1585 dlgcfg = (DLG_CONFIGDATA *)lParam;
1586 SetWindowLong (hDlg, WINDOW_USER_DATA, (LONG) dlgcfg);
1587 if(ps_global->install_flag)
1588 SetDlgItemText(hDlg, IDC_CONFTEXT, TEXT("Please specify where Alpine should create (or look for) your personal configuration file."));
1589 SetDlgItemText(hDlg, IDC_CONFEFLDRNAME, TEXT("remote_pinerc"));
1590 if(*dlgcfg->confpath){
1591 if(dlgcfg->confpath[0] == '{'){
1592 LPTSTR tfldr, p, tfldr2, p2, user;
1594 tfldr = utf8_to_lptstr((LPSTR)(dlgcfg->confpath+1));
1595 if(p = _tcschr(tfldr, '}')){
1596 *p++ = '\0';
1597 if(_tcscmp(TEXT("remote_pinerc"), p)){
1598 SetDlgItemText(hDlg, IDC_CONFEFLDRNAME, p);
1599 def_diff_fldr = 1;
1602 tfldr2 = _tcsdup(tfldr);
1603 for(p = tfldr, p2 = tfldr2; *p; p++)
1604 if(*p == '/' && !_tcsnicmp(p, TEXT("/user="), 6)){
1605 p += 6;
1606 for(user = p; *p && *p != '/'; p++);
1607 if(*p){
1608 *p2++ = *p;
1609 *p = '\0';
1611 else
1612 p--;
1613 SetDlgItemText(hDlg, IDC_CONFEUSERNAME, user);
1615 else
1616 *p2++ = *p;
1617 *p2 = '\0';
1618 SetDlgItemText(hDlg, IDC_CONFESERVER, tfldr2);
1619 if(tfldr2)
1620 MemFree((void *)tfldr2);
1623 if(tfldr)
1624 fs_give((void **) &tfldr);
1626 else{
1627 LPTSTR local_file;
1629 local_file = utf8_to_lptstr((LPSTR)dlgcfg->confpath);
1630 SetDlgItemText(hDlg, IDC_CONFEFN, local_file);
1631 if(!dlgcfg->nopinerc)
1632 def_rem_fldr = 0;
1634 fs_give((void **) &local_file);
1637 CheckRadioButton (hDlg, IDC_CONFRRADIO, IDC_CONFLRADIO,
1638 def_rem_fldr ? IDC_CONFRRADIO : IDC_CONFLRADIO);
1639 if(def_rem_fldr){
1640 EnableWindow(GetDlgItem(hDlg, IDC_CONFFNTXT), 0);
1641 EnableWindow(GetDlgItem(hDlg, IDC_CONFEFN), 0);
1642 EnableWindow(GetDlgItem(hDlg, IDC_CONFBROWSE), 0);
1643 if(!def_diff_fldr){
1644 CheckDlgButton(hDlg, IDC_CONFDFLTFLDR, BST_CHECKED);
1645 EnableWindow(GetDlgItem(hDlg, IDC_CONFEFLDRNAME), 0);
1647 EnableWindow(GetDlgItem(hDlg, IDC_CONFFLDRTXT), 0);
1649 else {
1650 EnableWindow(GetDlgItem(hDlg, IDC_CONFSRVRTXT), 0);
1651 EnableWindow(GetDlgItem(hDlg, IDC_CONFESERVER), 0);
1652 EnableWindow(GetDlgItem(hDlg, IDC_CONFUNTXT), 0);
1653 EnableWindow(GetDlgItem(hDlg, IDC_CONFEUSERNAME), 0);
1654 CheckDlgButton(hDlg, IDC_CONFDFLTFLDR, BST_CHECKED);
1655 EnableWindow(GetDlgItem(hDlg, IDC_CONFDFLTFLDR), 0);
1656 EnableWindow(GetDlgItem(hDlg, IDC_CONFFLDRTXT), 0);
1657 EnableWindow(GetDlgItem(hDlg, IDC_CONFEFLDRNAME), 0);
1659 if(ps_global->install_flag)
1660 CheckDlgButton(hDlg, IDC_CONFDFLTSET, BST_CHECKED);
1662 return (1);
1665 case WM_COMMAND:
1666 dlgcfg = (DLG_CONFIGDATA *) GetWindowLong (hDlg, WINDOW_USER_DATA);
1667 switch (wParam) {
1668 case IDC_CONFDFLTFLDR:
1669 checked = (IsDlgButtonChecked(hDlg, IDC_CONFDFLTFLDR) == BST_CHECKED);
1670 EnableWindow(GetDlgItem(hDlg, IDC_CONFFLDRTXT), checked ? 0 : 1);
1671 EnableWindow(GetDlgItem(hDlg, IDC_CONFEFLDRNAME), checked ? 0 : 1);
1672 if(checked)
1673 SetDlgItemText(hDlg, IDC_CONFEFLDRNAME, TEXT("remote_pinerc"));
1674 break;
1675 case IDC_CONFRRADIO:
1676 case IDC_CONFLRADIO:
1677 CheckRadioButton (hDlg, IDC_CONFRRADIO, IDC_CONFLRADIO, wParam);
1678 EnableWindow(GetDlgItem(hDlg, IDC_CONFFNTXT), wParam == IDC_CONFRRADIO ? 0 : 1);
1679 EnableWindow(GetDlgItem(hDlg, IDC_CONFEFN), wParam == IDC_CONFRRADIO ? 0 : 1);
1680 EnableWindow(GetDlgItem(hDlg, IDC_CONFBROWSE), wParam == IDC_CONFRRADIO ? 0 : 1);
1681 EnableWindow(GetDlgItem(hDlg, IDC_CONFSRVRTXT), wParam == IDC_CONFRRADIO ? 1 : 0);
1682 EnableWindow(GetDlgItem(hDlg, IDC_CONFESERVER), wParam == IDC_CONFRRADIO ? 1 : 0);
1683 EnableWindow(GetDlgItem(hDlg, IDC_CONFUNTXT), wParam == IDC_CONFRRADIO ? 1 : 0);
1684 EnableWindow(GetDlgItem(hDlg, IDC_CONFEUSERNAME), wParam == IDC_CONFRRADIO ? 1 : 0);
1685 EnableWindow(GetDlgItem(hDlg, IDC_CONFDFLTFLDR), wParam == IDC_CONFRRADIO ? 1 : 0);
1686 if(wParam == IDC_CONFRRADIO && IsDlgButtonChecked(hDlg, IDC_CONFDFLTFLDR) == BST_UNCHECKED){
1687 EnableWindow(GetDlgItem(hDlg, IDC_CONFFLDRTXT), 1);
1688 EnableWindow(GetDlgItem(hDlg, IDC_CONFEFLDRNAME), 1);
1690 else if(wParam == IDC_CONFLRADIO){
1691 EnableWindow(GetDlgItem(hDlg, IDC_CONFFLDRTXT), 0);
1692 EnableWindow(GetDlgItem(hDlg, IDC_CONFEFLDRNAME), 0);
1694 break;
1695 case IDC_CONFBROWSE:
1696 if(1){
1697 TCHAR fn[MAXPATH+1];
1698 OPENFILENAME ofn;
1700 fn[0] = '\0';
1702 /* Set up the BIG STRUCTURE. see mswin.c */
1703 memset (&ofn, 0, sizeof(ofn));
1704 ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
1705 ofn.hwndOwner = hDlg;
1706 ofn.lpstrFilter = NULL;
1707 ofn.lpstrCustomFilter = NULL;
1708 ofn.nFilterIndex = 0;
1709 ofn.lpstrFile = fn;
1710 ofn.nMaxFile = MAXPATH;
1711 ofn.lpstrFileTitle = NULL;
1712 ofn.nMaxFileTitle = 0;
1713 ofn.lpstrInitialDir = NULL;
1714 ofn.lpstrTitle = TEXT("Select File");
1715 ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST;
1716 ofn.lpstrDefExt = NULL;
1718 if (GetOpenFileName (&ofn)) {
1719 SetDlgItemText(hDlg, IDC_CONFEFN, fn);
1722 break;
1723 case IDOK:
1724 /* Retrieve the new username/passwd. */
1725 if(IsDlgButtonChecked(hDlg, IDC_CONFDFLTSET) == BST_CHECKED)
1726 dlgcfg->setreg = 1;
1727 else
1728 dlgcfg->setreg = 0;
1729 if(IsDlgButtonChecked(hDlg, IDC_CONFRRADIO) == BST_CHECKED){
1730 TCHAR lptstr_buf[MAXPATH+1];
1731 char *utf8_srvr, *utf8_username, *utf8_fldrname;
1733 GetDlgItemText(hDlg, IDC_CONFESERVER, lptstr_buf, MAXPATH);
1734 lptstr_buf[MAXPATH] = '\0';
1735 utf8_srvr = lptstr_to_utf8(lptstr_buf);
1736 removing_leading_and_trailing_white_space(utf8_srvr);
1737 if(!*utf8_srvr){
1738 MessageBox(hDlg, TEXT("IMAP Server field empty"),
1739 TEXT("Alpine"), MB_ICONWARNING | MB_OK);
1740 if(utf8_srvr)
1741 fs_give((void **) &utf8_srvr);
1743 return(TRUE);
1746 GetDlgItemText(hDlg, IDC_CONFEUSERNAME, lptstr_buf, MAXPATH);
1747 lptstr_buf[MAXPATH] = '\0';
1748 utf8_username = lptstr_to_utf8(lptstr_buf);
1749 removing_leading_and_trailing_white_space(utf8_username);
1750 if(IsDlgButtonChecked(hDlg, IDC_CONFDFLTFLDR) == BST_CHECKED){
1751 utf8_fldrname = cpystr("remote_pinerc");
1753 else{
1754 GetDlgItemText(hDlg, IDC_CONFEFLDRNAME, lptstr_buf, MAXPATH);
1755 lptstr_buf[MAXPATH] = '\0';
1756 utf8_fldrname = lptstr_to_utf8(lptstr_buf);
1757 removing_leading_and_trailing_white_space(utf8_fldrname);
1758 if(!*utf8_fldrname){
1759 MessageBox(hDlg, TEXT("Configuration Folder Name field empty"),
1760 TEXT("Alpine"), MB_ICONWARNING | MB_OK);
1761 if(utf8_srvr)
1762 fs_give((void **) &utf8_srvr);
1764 if(utf8_username)
1765 fs_give((void **) &utf8_username);
1767 if(utf8_fldrname)
1768 fs_give((void **) &utf8_fldrname);
1770 return(TRUE);
1773 if((strlen(utf8_srvr)
1774 + strlen(utf8_username)
1775 + strlen(utf8_fldrname)
1776 + 11) > dlgcfg->confpathlen){
1777 MessageBox(hDlg, TEXT("Config path too long"),
1778 TEXT("Alpine"), MB_ICONWARNING | MB_OK);
1779 if(utf8_srvr)
1780 fs_give((void **) &utf8_srvr);
1782 if(utf8_username)
1783 fs_give((void **) &utf8_username);
1785 if(utf8_fldrname)
1786 fs_give((void **) &utf8_fldrname);
1788 return(TRUE);
1791 snprintf(dlgcfg->confpath, dlgcfg->confpathlen, "{%s%s%s}%s", utf8_srvr,
1792 *utf8_username ? "/user=" : "",
1793 utf8_username, utf8_fldrname);
1794 if(utf8_srvr)
1795 fs_give((void **) &utf8_srvr);
1797 if(utf8_username)
1798 fs_give((void **) &utf8_username);
1800 if(utf8_fldrname)
1801 fs_give((void **) &utf8_fldrname);
1803 else{
1804 TCHAR lptstr_fn[MAXPATH+1];
1805 char *utf8_fn;
1807 GetDlgItemText(hDlg, IDC_CONFEFN, lptstr_fn, MAXPATH);
1808 lptstr_fn[MAXPATH] = '\0';
1809 utf8_fn = lptstr_to_utf8(lptstr_fn);
1810 removing_leading_and_trailing_white_space(utf8_fn);
1811 if(!*utf8_fn){
1812 MessageBox(hDlg, TEXT("Configuration File Name field empty"),
1813 TEXT("Alpine"), MB_ICONWARNING | MB_OK);
1814 if(utf8_fn)
1815 fs_give((void **) &utf8_fn);
1817 return(TRUE);
1820 if(strlen(utf8_fn) >= dlgcfg->confpathlen){
1821 MessageBox(hDlg, TEXT("Config path too long"),
1822 TEXT("Alpine"), MB_ICONWARNING | MB_OK);
1823 if(utf8_fn)
1824 fs_give((void **) &utf8_fn);
1826 return(TRUE);
1829 strncpy(dlgcfg->confpath, utf8_fn, dlgcfg->confpathlen);
1830 dlgcfg->confpath[dlgcfg->confpathlen-1] = '\0';
1831 if(utf8_fn)
1832 fs_give((void **) &utf8_fn);
1835 EndDialog (hDlg, LOWORD(wParam));
1836 dlgcfg->rv = 0;
1837 ret = TRUE;
1838 break;
1840 case IDCANCEL:
1841 dlgcfg->rv = 1;
1842 ret = TRUE;
1843 EndDialog (hDlg, LOWORD(wParam));
1844 break;
1846 break;
1850 return (ret);
1854 * Get a button position in the parent's coordinate space.
1856 static void
1857 GetBtnPos (HWND hPrnt, HWND hWnd, RECT *r)
1859 GetWindowRect (hWnd, r);
1860 ScreenToClient (hPrnt, (POINT *) r);
1861 ScreenToClient (hPrnt, (POINT *) &r->right);