* New version 2.26
[alpine.git] / alpine / osdep / termout.wnt.c
blob8d608d7ce33c505359bc6ee92d1a5000e27cd802
1 /*
2 * ========================================================================
3 * Copyright 2006-2007 University of Washington
4 * Copyright 2013-2022 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 * ========================================================================
14 #include <system.h>
15 #include <general.h>
17 #include "../../c-client/mail.h" /* for MAILSTREAM and friends */
18 #include "../../c-client/osdep.h"
19 #include "../../c-client/rfc822.h" /* for soutr_t and such */
20 #include "../../c-client/misc.h" /* for cpystr proto */
21 #include "../../c-client/utf8.h" /* for CHARSET and such*/
22 #include "../../c-client/imap4r1.h"
24 #include "../../pith/osdep/color.h"
26 #include "../../pith/charconv/filesys.h"
28 #include "../../pith/debug.h"
29 #include "../../pith/conf.h"
30 #include "../../pith/newmail.h"
32 #include "../../pico/estruct.h"
33 #include "../../pico/pico.h"
34 #include "../../pico/keydefs.h"
36 #include "../../pico/osdep/mswin.h"
37 #include "../../pico/osdep/color.h"
39 #include "../flagmaint.h"
40 #include "../status.h"
41 #include "../keymenu.h"
42 #include "../titlebar.h"
44 #include "termout.gen.h"
45 #include "termout.wnt.h"
47 /*======================================================================
48 Routines for painting the screen
49 - figure out what the terminal type is
50 - deal with screen size changes
51 - save special output sequences
52 - the usual screen clearing, cursor addressing and scrolling
55 This library gives programs the ability to easily access the
56 termcap information and write screen oriented and raw input
57 programs. The routines can be called as needed, except that
58 to use the cursor / screen routines there must be a call to
59 InitScreen() first. The 'Raw' input routine can be used
60 independently, however. (Elm comment)
62 Not sure what the original source of this code was. It got to be
63 here as part of ELM. It has been changed significantly from the
64 ELM version to be more robust in the face of inconsistent terminal
65 autowrap behaviour. Also, the unused functions were removed, it was
66 made to pay attention to the window size, and some code was made nicer
67 (in my opinion anyways). It also outputs the terminal initialization
68 strings and provides for minimal scrolling and detects terminals
69 with out enough capabilities. (Pine comment, 1990)
73 #define PUTLINE_BUFLEN 256
75 static int _lines, _columns;
77 BOOL CALLBACK __export
78 args_dialog_proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
80 BOOL CALLBACK __export
81 login_dialog_proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
83 BOOL CALLBACK __export
84 flag_dialog_proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
86 BOOL CALLBACK __export
87 sort_dialog_proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
89 BOOL CALLBACK __export
90 config_vars_dialog_proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
92 BOOL CALLBACK __export
93 config_dialog_proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
95 void
96 init_screen(void)
99 * If we want to show it, turn it on. If we don't care, put it back
100 * to the way it was originally.
102 mswin_showcaret(F_ON(F_SHOW_CURSOR, ps_global));
103 mswin_trayicon(F_ON(F_ENABLE_TRAYICON, ps_global));
104 return; /* NO OP */
107 void
108 end_screen(char *message, int exit_val)
110 int footer_rows_was_one = 0;
112 if(panicking())
113 return;
115 if(FOOTER_ROWS(ps_global) == 1){
116 footer_rows_was_one++;
117 FOOTER_ROWS(ps_global) = 3;
118 mark_status_unknown();
121 flush_status_messages(exit_val ? 0 : 1);
123 blank_keymenu(_lines - 2, 0);
125 if(message){
126 StartInverse();
127 PutLine0(_lines - 2, 0, message);
130 EndInverse();
132 MoveCursor(_lines - 1, 0);
134 mswin_showcaret(F_ON(F_SHOW_CURSOR, ps_global));
136 if(footer_rows_was_one){
137 FOOTER_ROWS(ps_global) = 1;
138 mark_status_unknown();
142 /*----------------------------------------------------------------------
143 Initialize the screen for output, set terminal type, etc
145 Args: tt -- Pointer to variable to store the tty output structure.
147 Result: terminal size is discovered and set pine state
148 termcap entry is fetched and stored in local variables
149 make sure terminal has adequate capabilities
150 evaluate scrolling situation
151 returns status of indicating the state of the screen/termcap entry
153 Returns:
154 -1 indicating no terminal name associated with this shell,
155 -2..-n No termcap for this terminal type known
156 -3 Can't open termcap file
157 -4 Terminal not powerful enough - missing clear to eoln or screen
158 or cursor motion
160 ----*/
162 config_screen(struct ttyo **tt)
164 struct ttyo *ttyo;
166 _line = 0; /* where are we right now?? */
167 _col = 0; /* assume zero, zero... */
169 mswin_getscreensize(&_lines, &_columns);
170 if (_lines > MAX_SCREEN_ROWS)
171 _lines = MAX_SCREEN_ROWS;
172 if (_columns > MAX_SCREEN_COLS)
173 _columns = MAX_SCREEN_COLS;
175 ttyo = (struct ttyo *)fs_get(sizeof(struct ttyo));
176 ttyo->screen_cols = _columns;
177 ttyo->screen_rows = _lines ;
178 ttyo->header_rows = 2;
179 ttyo->footer_rows = 3;
181 *tt = ttyo;
183 return(0);
186 /*----------------------------------------------------------------------
187 Get the current window size
189 Args: ttyo -- pointer to structure to store window size in
191 NOTE: we don't override the given values unless we know better
192 ----*/
194 get_windsize(struct ttyo *ttyo)
196 char fontName[LF_FACESIZE+1];
197 char fontSize[12];
198 char fontStyle[64];
199 char fontCharSet[256];
200 char windowPosition[32], windowPositionReg[32];
201 char foreColor[64], backColor[64];
202 int newRows, newCols;
203 char cursorStyle[32];
205 cursorStyle[0] = '\0';
207 /* Get the new window parameters and update the 'pinerc' variables. */
208 mswin_getwindow(fontName, sizeof(fontName), fontSize, sizeof(fontSize),
209 fontStyle, sizeof(fontStyle),
210 windowPosition, sizeof(windowPosition),
211 foreColor, sizeof(foreColor),
212 backColor, sizeof(backColor),
213 cursorStyle, sizeof(cursorStyle),
214 fontCharSet, sizeof(fontCharSet));
216 if(!ps_global->VAR_FONT_NAME
217 || strucmp(ps_global->VAR_FONT_NAME, fontName))
218 set_variable(V_FONT_NAME, fontName, 1, 0,
219 ps_global->ew_for_except_vars);
221 if(!ps_global->VAR_FONT_SIZE
222 || strucmp(ps_global->VAR_FONT_SIZE, fontSize))
223 set_variable(V_FONT_SIZE, fontSize, 1, 0,
224 ps_global->ew_for_except_vars);
226 if(!ps_global->VAR_FONT_STYLE
227 || strucmp(ps_global->VAR_FONT_STYLE, fontStyle))
228 set_variable(V_FONT_STYLE, fontStyle, 1, 0,
229 ps_global->ew_for_except_vars);
231 if(!ps_global->VAR_FONT_CHAR_SET
232 || strucmp(ps_global->VAR_FONT_CHAR_SET, fontCharSet))
233 set_variable(V_FONT_CHAR_SET, fontCharSet, 1, 0,
234 ps_global->ew_for_except_vars);
236 if(strnicmp(windowPosition, "MIN0", 4) && !strchr(windowPosition, '!')){
237 if(F_ON(F_STORE_WINPOS_IN_CONFIG, ps_global)){
238 if(!ps_global->VAR_WINDOW_POSITION
239 || strucmp(ps_global->VAR_WINDOW_POSITION, windowPosition))
240 set_variable(V_WINDOW_POSITION, windowPosition, 1, 0,
241 ps_global->ew_for_except_vars);
243 else{
245 * Get the window position stored in the registry.
247 * If current window position is not in the registry or is
248 * different from what is there, save it.
250 if((!mswin_reg(MSWR_OP_GET, MSWR_PINE_POS, windowPositionReg,
251 sizeof(windowPositionReg)) ||
252 strucmp(windowPositionReg, windowPosition))
253 && (ps_global->update_registry != UREG_NEVER_SET))
254 mswin_reg(MSWR_OP_SET | MSWR_OP_FORCE, MSWR_PINE_POS, windowPosition,
255 (size_t)NULL);
259 mswin_getprintfont(fontName, sizeof(fontName),
260 fontSize, sizeof(fontSize),
261 fontStyle, sizeof(fontStyle),
262 fontCharSet, sizeof(fontCharSet));
263 if(!ps_global->VAR_PRINT_FONT_NAME
264 || strucmp(ps_global->VAR_PRINT_FONT_NAME, fontName))
265 set_variable(V_PRINT_FONT_NAME, fontName, 1, 0,
266 ps_global->ew_for_except_vars);
268 if(!ps_global->VAR_PRINT_FONT_SIZE
269 || strucmp(ps_global->VAR_PRINT_FONT_SIZE, fontSize))
270 set_variable(V_PRINT_FONT_SIZE, fontSize, 1, 0,
271 ps_global->ew_for_except_vars);
273 if(!ps_global->VAR_PRINT_FONT_STYLE
274 || strucmp(ps_global->VAR_PRINT_FONT_STYLE, fontStyle))
275 set_variable(V_PRINT_FONT_STYLE, fontStyle, 1, 0,
276 ps_global->ew_for_except_vars);
278 if(!ps_global->VAR_PRINT_FONT_CHAR_SET
279 || strucmp(ps_global->VAR_PRINT_FONT_CHAR_SET, fontCharSet))
280 set_variable(V_PRINT_FONT_CHAR_SET, fontCharSet, 1, 0,
281 ps_global->ew_for_except_vars);
283 if(!ps_global->VAR_NORM_FORE_COLOR
284 || strucmp(ps_global->VAR_NORM_FORE_COLOR, foreColor))
285 set_variable(V_NORM_FORE_COLOR, foreColor, 1, 0,
286 ps_global->ew_for_except_vars);
288 if(!ps_global->VAR_NORM_BACK_COLOR
289 || strucmp(ps_global->VAR_NORM_BACK_COLOR, backColor))
290 set_variable(V_NORM_BACK_COLOR, backColor, 1, 0,
291 ps_global->ew_for_except_vars);
293 if(cursorStyle[0] && !ps_global->VAR_CURSOR_STYLE
294 || strucmp(ps_global->VAR_CURSOR_STYLE, cursorStyle))
295 set_variable(V_CURSOR_STYLE, cursorStyle, 1, 0,
296 ps_global->ew_for_except_vars);
298 /* Get new window size. Compare to old. The window may have just
299 * moved, in which case we don't bother updating the size. */
300 mswin_getscreensize(&newRows, &newCols);
301 if (newRows == ttyo->screen_rows && newCols == ttyo->screen_cols)
302 return (NO_OP_COMMAND);
304 /* True resize. */
305 ttyo->screen_rows = newRows;
306 ttyo->screen_cols = newCols;
308 if (ttyo->screen_rows > MAX_SCREEN_ROWS)
309 ttyo->screen_rows = MAX_SCREEN_ROWS;
310 if (ttyo->screen_cols > MAX_SCREEN_COLS)
311 ttyo->screen_cols = MAX_SCREEN_COLS;
313 return(KEY_RESIZE);
316 /*----------------------------------------------------------------------
317 Move the cursor to the row and column number
318 Input: row number
319 column number
321 Result: Cursor moves
322 internal position updated
323 ----------------------------------------------------------------------*/
324 void
325 MoveCursor(int row, int col)
327 /** move cursor to the specified row column on the screen.
328 0,0 is the top left! **/
330 if(ps_global->in_init_seq)
331 return;
334 * This little hack is here for screen readers, for example, a screen
335 * reader associated with a braille display. If we flash the cursor off
336 * and on in the same position, the reader will be drawn to it. Since we
337 * are calling MoveCursor every time through the message viewing loops we
338 * need to suppress the calls if they aren't really doing anything.
339 * However, mswin_move actually does more than just move the cursor.
340 * It also call FlushAccum(), which is necessary in some cases. For
341 * example, in optionally_enter the user is typing characters in and
342 * the FlushAccum() allows them to show up on the screen. The putblock
343 * call is a quick hack to get the Flush_Accum() call, which is all
344 * the putblock does when the arg is NULL.
346 if(row == _line && col == _col){
347 mswin_putblock(NULL, 0);
348 return;
351 mswin_move(row, col);
352 _line = row;
353 _col = col;
357 /*----------------------------------------------------------------------
358 Write a character to the screen, keeping track of cursor position
360 Input: character to write
362 Result: character output
363 cursor position variables updated
364 ----------------------------------------------------------------------*/
365 void
366 Writewchar(UCS ucs)
368 int width;
370 if(ps_global->in_init_seq)
371 return;
373 switch(ucs){
374 case LINE_FEED :
375 _line = min(_line+1,ps_global->ttyo->screen_rows);
376 _col =0;
377 mswin_move(_line, _col);
378 break;
380 case RETURN : /* move to column 0 */
381 _col = 0;
382 mswin_move(_line, _col);
384 case BACKSPACE : /* move back a space if not in column 0 */
385 if(_col > 0)
386 mswin_move(_line, --_col);
388 break;
390 case BELL : /* ring the bell but don't advance _col */
391 mswin_beep(); /* libpico call */
392 break;
394 case TAB: /* if a tab, output it */
396 mswin_putc(' ');
397 while(((++_col)&0x07) != 0);
398 break;
400 default:
401 /* pass_ctrl_chars is always 1 for Windows */
402 width = wcellwidth(ucs);
403 if(width < 0){
404 mswin_putc('?');
405 _col++;
407 else if(_col + width > ps_global->ttyo->screen_cols){
408 int i;
410 i = ps_global->ttyo->screen_cols - _col - 1;
411 while(i-- > 0)
412 mswin_putc(' ');
414 _col = ps_global->ttyo->screen_cols - 1;
415 mswin_move(_line, _col);
416 mswin_putc('>');
417 _col++;
419 else{
420 mswin_putc(ucs);
421 _col += width;
425 if(_col >= ps_global->ttyo->screen_cols){
426 _col = ps_global->ttyo->screen_cols;
427 mswin_move(_line, _col);
430 return;
434 /*----------------------------------------------------------------------
435 Printf style write directly to the terminal at current position
437 Input: printf style control string
438 number of printf style arguments
439 up to three printf style arguments
441 Result: Line written to the screen
442 ----------------------------------------------------------------------*/
443 void
444 Write_to_screen(char *string)
446 if(ps_global->in_init_seq)
447 return;
449 mswin_puts (string);
452 * mswin_puts does not keep track of where we are. Simple fix is to
453 * reset _line and _col to unknown so that the next MoveCursor will
454 * do a real move. We could check for a simple string and actually
455 * keep track. Is that useful? I don't think so.
457 * There are other places where we lose track, but by comparing with
458 * the termout.unx code where we also lose track it would seem we don't
459 * really need to keep track in those other cases.
461 _line = FARAWAY;
462 _col = FARAWAY;
465 void
466 Write_to_screen_n(char *string, int n)
468 if(ps_global->in_init_seq)
469 return;
471 mswin_puts_n (string, n);
472 _line = FARAWAY;
473 _col = FARAWAY;
477 /*----------------------------------------------------------------------
478 Clear the terminal screen
479 ----------------------------------------------------------------------*/
480 void
481 ClearScreen(void)
483 _line = 0; /* clear leaves us at top... */
484 _col = 0;
486 if(ps_global->in_init_seq)
487 return;
489 mark_status_unknown();
490 mark_keymenu_dirty();
491 mark_titlebar_dirty();
493 mswin_move(0, 0);
494 mswin_eeop();
497 /*----------------------------------------------------------------------
498 Clear screen to end of line on current line
499 ----------------------------------------------------------------------*/
500 void
501 CleartoEOLN(void)
503 mswin_eeol();
507 /*----------------------------------------------------------------------
508 function to output string such that it becomes icon text
510 Args: s -- string to write
512 Result: string indicated become our "icon" text
513 ----*/
514 void
515 icon_text(char *s, int type)
517 if(type == IT_MCLOSED)
518 mswin_mclosedtext (s);
519 else /* IT_NEWMAIL */
520 mswin_newmailtext (s);
523 /* Scroll stuff */
526 * Set the current position of the scroll bar.
528 void
529 scroll_setpos(long newpos)
531 mswin_setscrollpos (newpos);
535 * Set the range of the scroll bar.
536 * zero disables the scroll bar.
538 void
539 scroll_setrange (long pagelen, long rangeend)
541 if(rangeend < pagelen)
542 mswin_setscrollrange (0L, 0L);
543 else
544 mswin_setscrollrange (pagelen, rangeend + pagelen - 1L);
547 void
548 EndScroll(void)
553 ScrollRegion(int lines)
555 return(-1);
559 BeginScroll(int top, int bottom)
561 static int __t, __b;
563 __t = top;
564 __b = bottom;
565 return(-1);
569 /* Dialog stuff */
570 #define WINDOW_USER_DATA GWL_USERDATA
572 /*===========================================================================
574 * Dialog Data
576 * The following structures hold the state data for dialogs.
578 typedef struct DLG_TYPEMAP {
579 int pineid;
580 int rsrcid;
581 } DLG_TYPEMAP;
583 typedef struct DLG_SORTDATA {
584 DLG_SORTPARAM *sortsel; /* parameter structure. */
585 int sortcount; /* Number of different sorts. */
586 DLG_TYPEMAP types[20]; /* Map pine sort types to ctrl ids. */
587 } DLG_SORTDATA;
589 typedef struct DLG_LOGINDATA {
590 NETMBX *mb;
591 LPTSTR user;
592 int userlen;
593 LPTSTR pwd;
594 int pwdlen;
595 int pwc; /* set if we're using passfiles and we don't know user yet */
596 int fixuser;
597 int prespass; /* if user wants to preserve the password */
598 int rv;
599 } DLG_LOGINDATA;
601 typedef struct DLG_CONFIGDATA {
602 char *confpath; /* UTF-8 path */
603 int confpathlen;
604 int setreg;
605 int nopinerc;
606 int rv;
607 } DLG_CONFIGDATA;
609 typedef struct installvars {
610 char *pname;
611 char *userid;
612 char *domain;
613 char *inboxpath;
614 char *smtpserver;
615 unsigned defmailclient:1;
616 unsigned defnewsclient:1;
617 } INSTALLVARS_S;
619 typedef struct DLG_CONGIGVARSDATA {
620 INSTALLVARS_S *ivars;
621 int rv;
622 } DLG_CONFIGVARSDATA;
624 typedef struct DLG_FLAGDATA {
625 struct flag_table *ftbl;
626 int flagcount;
627 HINSTANCE hInstance;
628 HWND hTextWnd;
629 } DLG_FLAGDATA;
631 int os_config_vars_dialog(INSTALLVARS_S *);
632 static void GetBtnPos (HWND, HWND, RECT *);
635 init_install_get_vars(void)
637 INSTALLVARS_S ivars;
638 struct pine *ps = ps_global;
639 char *p;
641 memset((void *)&ivars, 0, sizeof(INSTALLVARS_S));
642 if(ps->vars[V_PERSONAL_NAME].main_user_val.p)
643 ivars.pname = cpystr(ps->vars[V_PERSONAL_NAME].main_user_val.p);
644 if(ps->vars[V_USER_ID].main_user_val.p)
645 ivars.userid = cpystr(ps->vars[V_USER_ID].main_user_val.p);
646 if(ps->vars[V_USER_DOMAIN].main_user_val.p)
647 ivars.domain = cpystr(ps->vars[V_USER_DOMAIN].main_user_val.p);
648 if(ps->vars[V_INBOX_PATH].main_user_val.p)
649 ivars.inboxpath = cpystr(ps->vars[V_INBOX_PATH].main_user_val.p);
650 else if(ps->prc && ps->prc->name && (*ps->prc->name == '{')
651 && (p = strindex(ps->prc->name, '}'))){
652 ivars.inboxpath = cpystr(ps->prc->name);
653 if(p = strindex(ivars.inboxpath, '}'))
654 *(p+1) = '\0';
656 if(ps->vars[V_SMTP_SERVER].main_user_val.l
657 && *ps->vars[V_SMTP_SERVER].main_user_val.l)
658 ivars.smtpserver = cpystr(ps->vars[V_SMTP_SERVER].main_user_val.l[0]);
659 ivars.defmailclient = mswin_is_def_client(MSWR_SDC_MAIL);
660 ivars.defnewsclient = mswin_is_def_client(MSWR_SDC_NEWS);
662 if(os_config_vars_dialog(&ivars) == 0){
663 set_variable(V_PERSONAL_NAME, ivars.pname, 0, 0, Main);
664 set_variable(V_USER_ID, ivars.userid, 0, 0, Main);
665 set_variable(V_USER_DOMAIN, ivars.domain, 0, 0, Main);
666 set_variable(V_INBOX_PATH, ivars.inboxpath, 0, 0, Main);
667 if(ivars.smtpserver){
668 if(ps->vars[V_SMTP_SERVER].main_user_val.l){
669 fs_give((void **)&ps->vars[V_SMTP_SERVER].main_user_val.l[0]);
670 ps->vars[V_SMTP_SERVER].main_user_val.l[0]
671 = cpystr(ivars.smtpserver);
672 set_current_val(&ps->vars[V_SMTP_SERVER], TRUE, FALSE);
674 else {
675 char *tstrlist[2];
677 tstrlist[0] = ivars.smtpserver;
678 tstrlist[1] = NULL;
679 set_variable_list(V_SMTP_SERVER, tstrlist, 0, Main);
682 write_pinerc(ps_global, Main, WRP_NONE);
683 if(ivars.defmailclient)
684 mswin_set_def_client(MSWR_SDC_MAIL);
685 if(ivars.defnewsclient)
686 mswin_set_def_client(MSWR_SDC_NEWS);
688 /* Tell Windows that stuff has changed */
689 if(ivars.defmailclient || ivars.defnewsclient)
690 SendMessageTimeout(HWND_BROADCAST, WM_SETTINGCHANGE,
691 (WPARAM)NULL, (LPARAM)NULL,
692 SMTO_NORMAL, 1000, NULL);
695 if(ivars.pname)
696 fs_give((void **)&ivars.pname);
697 if(ivars.userid)
698 fs_give((void **)&ivars.userid);
699 if(ivars.domain)
700 fs_give((void **)&ivars.domain);
701 if(ivars.inboxpath)
702 fs_give((void **)&ivars.inboxpath);
703 if(ivars.smtpserver)
704 fs_give((void **)&ivars.smtpserver);
705 return 0;
709 * Show args dialog
712 os_argsdialog (char **arg_text)
714 DLGPROC dlgprc;
715 HINSTANCE hInst;
716 HWND hWnd;
718 hInst = (HINSTANCE) mswin_gethinstance ();
719 hWnd = (HWND) mswin_gethwnd ();
721 mswin_killsplash();
723 dlgprc = args_dialog_proc;
725 DialogBoxParam (hInst, MAKEINTRESOURCE (IDD_ARGLIST), hWnd,
726 dlgprc, (LPARAM) arg_text);
728 return(1);
732 * Prompt for username and password
735 os_login_dialog (NETMBX *mb, char *user_utf8, int userlen,
736 char **pwd_utf8, int pwdlen, int pwc, int fixuser, int *prespass)
738 DLGPROC dlgprc;
739 HINSTANCE hInst;
740 HWND hWnd;
741 DLG_LOGINDATA dlgpw;
742 LPTSTR user_lptstr, pwd_lptstr;
743 char *tuser_utf8, *tpwd_utf8;
745 mswin_killsplash();
746 hInst = (HINSTANCE) mswin_gethinstance ();
747 hWnd = (HWND) mswin_gethwnd ();
749 dlgpw.mb = mb;
751 dlgpw.user = (LPTSTR)fs_get(userlen*sizeof(TCHAR));
752 user_lptstr = utf8_to_lptstr(user_utf8);
753 _tcsncpy(dlgpw.user, user_lptstr, userlen - 1);
754 dlgpw.user[userlen - 1] = '\0';
755 fs_give((void **) &user_lptstr);
756 dlgpw.userlen = userlen;
758 dlgpw.pwd = (LPTSTR)fs_get(pwdlen*sizeof(TCHAR));
759 pwd_lptstr = utf8_to_lptstr(*pwd_utf8);
760 _tcsncpy(dlgpw.pwd, pwd_lptstr, pwdlen - 1);
761 dlgpw.pwd[pwdlen - 1] = '\0';
762 fs_give((void **) &pwd_lptstr);
763 dlgpw.pwdlen = pwdlen;
765 dlgpw.fixuser = fixuser;
766 dlgpw.pwc = pwc;
767 dlgpw.rv = 0;
769 dlgprc = login_dialog_proc;
771 DialogBoxParam (hInst, MAKEINTRESOURCE (ps_global->install_flag
772 ? IDD_LOGINDLG2 : IDD_LOGINDLG),
773 NULL, dlgprc, (LPARAM)&dlgpw);
775 if(dlgpw.rv == 0){
776 tuser_utf8 = lptstr_to_utf8(dlgpw.user);
777 if(tuser_utf8){
778 strncpy(user_utf8, tuser_utf8, userlen - 1);
779 user_utf8[userlen - 1] = '\0';
780 fs_give((void **) &tuser_utf8);
783 tpwd_utf8 = lptstr_to_utf8(dlgpw.pwd);
784 if(tpwd_utf8){
785 *pwd_utf8 = cpystr(tpwd_utf8);
786 fs_give((void **) &tpwd_utf8);
788 if(prespass)
789 (*prespass) = dlgpw.prespass;
792 return(dlgpw.rv);
796 * Select message flags.
799 os_flagmsgdialog (struct flag_table *ftbl)
801 DLGPROC dlgprc;
802 HINSTANCE hInst;
803 HWND hWnd;
804 DLG_FLAGDATA dlgflag;
805 int rval;
807 hInst = (HINSTANCE) mswin_gethinstance ();
808 hWnd = (HWND) mswin_gethwnd ();
810 dlgflag.ftbl = ftbl;
811 dlgflag.hInstance = hInst;
812 dlgflag.hTextWnd = hWnd;
814 dlgprc = flag_dialog_proc;
816 rval = DialogBoxParam (hInst, MAKEINTRESOURCE (IDD_SELECTFLAG), hWnd,
817 dlgprc, (LPARAM)&dlgflag);
819 return (rval);
823 * Select a sort type.
827 os_sortdialog (DLG_SORTPARAM *sortsel)
829 DLGPROC dlgprc;
830 HINSTANCE hInst;
831 HWND hWnd;
832 int i;
833 DLG_SORTDATA dlgsort;
835 hInst = (HINSTANCE) mswin_gethinstance ();
836 hWnd = (HWND) mswin_gethwnd ();
839 /* Build a map of pine sort types to the resource types. */
840 i = 0;
841 dlgsort.types[i].pineid = SortArrival;
842 dlgsort.types[i++].rsrcid = IDC_SORTARRIVAL;
843 dlgsort.types[i].pineid = SortDate;
844 dlgsort.types[i++].rsrcid = IDC_SORTDATE;
845 dlgsort.types[i].pineid = SortFrom;
846 dlgsort.types[i++].rsrcid = IDC_SORTFROM;
847 dlgsort.types[i].pineid = SortSubject;
848 dlgsort.types[i++].rsrcid = IDC_SORTSUBJECT;
849 dlgsort.types[i].pineid = SortSubject2;
850 dlgsort.types[i++].rsrcid = IDC_SORTORDERSUB;
851 dlgsort.types[i].pineid = SortTo;
852 dlgsort.types[i++].rsrcid = IDC_SORTTO;
853 dlgsort.types[i].pineid = SortCc;
854 dlgsort.types[i++].rsrcid = IDC_SORTCC;
855 dlgsort.types[i].pineid = SortSize;
856 dlgsort.types[i++].rsrcid = IDC_SORTSIZE;
857 dlgsort.types[i].pineid = SortThread;
858 dlgsort.types[i++].rsrcid = IDC_SORTTHREAD;
859 dlgsort.types[i].pineid = SortScore;
860 dlgsort.types[i++].rsrcid = IDC_SORTSCORE;
861 dlgsort.sortcount = i;
862 dlgsort.sortsel = sortsel;
864 dlgprc = sort_dialog_proc;
866 DialogBoxParam (hInst, MAKEINTRESOURCE (IDD_SELECTSORT), hWnd,
867 dlgprc, (LPARAM)&dlgsort);
869 return(1);
874 * Dialog proc to handle index sort selection.
876 * Configures the dialog box on init and retrieves the settings on exit.
878 BOOL CALLBACK __export
879 args_dialog_proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
881 BOOL ret = FALSE;
882 long i, j, block_size;
883 char **args_text;
884 LPTSTR args_text_lptstr, args_block_lptstr;
887 switch (uMsg) {
888 case WM_INITDIALOG:
890 args_text = (char **)lParam;
893 * First convert char *'s over to one big block of
894 * Unicode
896 i = 0;
897 while(args_text && *args_text){
898 i += strlen(*args_text++);
899 i += 2;
901 block_size = i;
903 args_block_lptstr = (LPTSTR)fs_get((block_size+1)*sizeof(TCHAR));
905 args_text = (char **)lParam;
906 i = 0;
907 j = 0;
908 while(args_text && *args_text){
909 args_text_lptstr = utf8_to_lptstr(*args_text++);
910 while(args_text_lptstr[i] && j < block_size){
911 args_block_lptstr[j++] = args_text_lptstr[i++];
913 args_block_lptstr[j++] = '\r';
914 args_block_lptstr[j++] = '\n';
915 fs_give((void **) &args_text_lptstr);
916 i = 0;
918 args_block_lptstr[j] = '\0';
920 /* and replace everything selected with args_text */
921 SendDlgItemMessage(hDlg, IDC_ARGTEXT, WM_SETTEXT, (WPARAM) 0,
922 (LPARAM) args_block_lptstr);
923 fs_give((void **)&args_block_lptstr);
925 return (1);
927 case WM_CLOSE :
928 ret = TRUE;
929 EndDialog (hDlg, TRUE);
930 break;
933 case WM_COMMAND:
934 switch (wParam) {
935 case IDOK:
936 ret = TRUE;
937 EndDialog (hDlg, TRUE);
938 break;
940 break;
944 return (ret);
948 * Dialog proc to handle login
950 * Configures the dialog box on init and retrieves the settings on exit.
952 BOOL CALLBACK __export
953 login_dialog_proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
955 DLG_LOGINDATA *dlglogin;
956 BOOL ret = FALSE;
957 TCHAR tcbuf[1024];
958 NETMBX *mb;
959 LPTSTR user, pwd;
960 LPTSTR host_lptstr;
962 switch (uMsg) {
963 case WM_INITDIALOG:
965 dlglogin = (DLG_LOGINDATA *)lParam;
966 mb = dlglogin->mb;
967 user = dlglogin->user;
968 pwd = dlglogin->pwd;
969 SetWindowLong (hDlg, WINDOW_USER_DATA, (LONG) dlglogin);
971 host_lptstr = utf8_to_lptstr(mb->host);
972 _sntprintf(tcbuf, sizeof(tcbuf), TEXT("Host: %.100s%s"), host_lptstr,
973 !mb->sslflag && !mb->tlsflag ? TEXT(" (INSECURE)") : TEXT(""));
974 fs_give((void **) &host_lptstr);
976 if(mb->sslflag || mb->tlsflag)
977 SetWindowText(hDlg, TEXT("Alpine Login +"));
978 else
979 SetWindowText(hDlg, TEXT("Alpine Insecure Login"));
981 if(dlglogin->pwc){
982 EnableWindow(GetDlgItem(hDlg, IDC_RPASSWORD),0);
983 EnableWindow(GetDlgItem(hDlg, IDC_RPWTEXT),0);
984 EnableWindow(GetDlgItem(hDlg, IDC_PRESPASS),0);
986 if(mb->user && *mb->user){
987 LPTSTR user_lptstr;
989 user_lptstr = utf8_to_lptstr(mb->user);
990 SetDlgItemText(hDlg, IDC_RLOGINE, user_lptstr);
991 if((mb->user && *mb->user) || dlglogin->fixuser)
992 EnableWindow(GetDlgItem(hDlg, IDC_RLOGINE), 0);
993 fs_give((void **) &user_lptstr);
995 else if(user){
996 SetDlgItemText(hDlg, IDC_RLOGINE, user);
997 if(dlglogin->fixuser)
998 EnableWindow(GetDlgItem(hDlg, IDC_RLOGINE), 0);
1000 SetDlgItemText(hDlg, IDC_PROMPT, tcbuf);
1001 return (1);
1004 case WM_COMMAND:
1005 dlglogin = (DLG_LOGINDATA *) GetWindowLong (hDlg, WINDOW_USER_DATA);
1006 switch (wParam) {
1007 case IDOK:
1008 /* Retrieve the new username/passwd. */
1009 user = dlglogin->user;
1010 pwd = dlglogin->pwd;
1011 GetDlgItemText(hDlg, IDC_RLOGINE, user, dlglogin->userlen - 1);
1012 GetDlgItemText(hDlg, IDC_RPASSWORD, pwd, dlglogin->pwdlen - 1);
1013 user[dlglogin->userlen - 1] = '\0';
1014 pwd[dlglogin->pwdlen - 1] = '\0';
1015 dlglogin->prespass = (IsDlgButtonChecked(hDlg, IDC_PRESPASS) == BST_CHECKED);
1017 EndDialog (hDlg, LOWORD(wParam));
1018 dlglogin->rv = 0;
1019 ret = TRUE;
1020 break;
1022 case IDCANCEL:
1023 dlglogin->rv = 1;
1024 ret = TRUE;
1025 EndDialog (hDlg, LOWORD(wParam));
1026 break;
1028 break;
1030 return (ret);
1034 * Dialog proc to handle flag selection.
1036 * Configures the dialog box on init, adding buttons as needed for
1037 * an unknown number of flags.
1038 * Retrieves the settings on exit.
1040 BOOL CALLBACK __export
1041 flag_dialog_proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
1043 DLG_FLAGDATA *dlgflag;
1044 BOOL ret = FALSE;
1045 int i;
1046 struct flag_table *fp;
1047 HWND hRB[2], hBtn;
1048 RECT rb[2];
1049 UINT bheight, bwidth, bvertSpace;
1050 UINT btnOKHeight;
1051 int base, line;
1052 int bstate;
1053 HFONT btnFont;
1058 switch (uMsg) {
1059 case WM_INITDIALOG:
1060 dlgflag = (DLG_FLAGDATA *)lParam;
1061 SetWindowLong (hDlg, WINDOW_USER_DATA, (LONG) dlgflag);
1063 /* Count buttons */
1064 dlgflag->flagcount = 0;
1065 for (fp = dlgflag->ftbl; fp && fp->name; ++fp)
1066 ++dlgflag->flagcount;
1068 /* Get the positions of the current buttons. */
1069 for (i = 0; i < 2; ++i) {
1070 hRB[i] = GetDlgItem (hDlg, IDC_FLAGCOL1 + i);
1071 GetBtnPos (hDlg, hRB[i], &rb[i]);
1073 bheight = rb[0].bottom - rb[0].top;
1074 bwidth = rb[0].right - rb[0].left;
1075 bvertSpace = bheight + 5;
1076 btnFont = (HFONT) SendMessage (hRB[0], WM_GETFONT, 0, 0);
1078 for (i = 0; i < dlgflag->flagcount; ++i) {
1079 LPTSTR fp_name_lptstr;
1081 fp = &dlgflag->ftbl[i];
1083 fp_name_lptstr = utf8_to_lptstr(fp->name);
1084 if (i < 2) {
1085 hBtn = hRB[i];
1086 SetWindowText (hBtn, fp_name_lptstr);
1088 else {
1089 base = i % 2;
1090 line = i / 2;
1091 hBtn = CreateWindow (TEXT("BUTTON"), fp_name_lptstr,
1092 WS_CHILD | WS_VISIBLE | BS_AUTOCHECKBOX,
1093 rb[base].left, rb[base].top + bvertSpace * line,
1094 bwidth, bheight,
1095 hDlg, (HMENU)NULL, dlgflag->hInstance, NULL);
1096 SetWindowLong (hBtn, GWL_ID, IDC_FLAGCOL1 + i);
1097 SendMessage (hBtn, WM_SETFONT, (WPARAM)btnFont,
1098 MAKELPARAM (0, 0));
1101 fs_give((void **) &fp_name_lptstr);
1102 if (fp->ukn)
1103 SendMessage (hBtn, BM_SETSTYLE,
1104 (WPARAM)(BS_CHECKBOX | BS_AUTO3STATE), 0);
1105 SendMessage (hBtn, BM_SETCHECK,
1106 (WPARAM) fp->set == CMD_FLAG_UNKN ? 2 : fp->set ? 1 : 0,
1108 ShowWindow (hBtn, SW_SHOW);
1109 EnableWindow (hBtn, TRUE);
1112 /* Position the OK and Cancel buttons. */
1113 line = (dlgflag->flagcount + 1) / 2;
1114 for (i = 0; i < 2; ++i) {
1115 hRB[1] = GetDlgItem (hDlg, i == 0 ? IDOK : IDCANCEL);
1116 GetBtnPos (hDlg, hRB[1], &rb[1]);
1117 MoveWindow (hRB[1], rb[1].left, rb[0].top + bvertSpace * line,
1118 rb[1].right - rb[1].left, rb[1].bottom - rb[1].top,
1119 FALSE);
1120 btnOKHeight = rb[1].bottom - rb[1].top;
1124 /* Resize whole dialog window. */
1125 GetWindowRect (hDlg, &rb[1]);
1126 rb[1].right -= rb[1].left;
1127 rb[1].bottom = rb[0].top + bvertSpace * line + btnOKHeight + 10 +
1128 GetSystemMetrics (SM_CYCAPTION);
1129 MoveWindow (hDlg, rb[1].left, rb[1].top, rb[1].right,
1130 rb[1].bottom, TRUE);
1131 return (1);
1134 case WM_COMMAND:
1135 dlgflag = (DLG_FLAGDATA *) GetWindowLong (hDlg, WINDOW_USER_DATA);
1136 switch (wParam) {
1138 case IDOK:
1139 /* Retrieve the button states. */
1140 for (i = 0; i < dlgflag->flagcount; ++i) {
1141 fp = &dlgflag->ftbl[i];
1142 bstate = SendMessage (GetDlgItem (hDlg, IDC_FLAGCOL1 + i),
1143 BM_GETCHECK, 0, 0);
1144 switch (bstate) {
1145 case 2: fp->set = CMD_FLAG_UNKN; break;
1146 case 1: fp->set = CMD_FLAG_SET; break;
1147 case 0: fp->set = CMD_FLAG_CLEAR; break;
1150 EndDialog (hDlg, TRUE);
1151 ret = TRUE;
1152 break;
1154 case IDCANCEL:
1155 EndDialog (hDlg, FALSE);
1156 ret = TRUE;
1157 break;
1159 break;
1163 return (ret);
1167 * Dialog proc to handle index sort selection.
1169 * Configures the dialog box on init and retrieves the settings on exit.
1171 BOOL CALLBACK __export
1172 sort_dialog_proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
1174 DLG_SORTDATA *dlgsort;
1175 BOOL ret = FALSE;
1176 int cursort;
1177 int i;
1180 switch (uMsg) {
1181 case WM_INITDIALOG:
1182 dlgsort = (DLG_SORTDATA *)lParam;
1183 SetWindowLong (hDlg, WINDOW_USER_DATA, (LONG) dlgsort);
1185 /* Set the reversed button state. */
1186 CheckDlgButton (hDlg, IDC_SORTREVERSE, dlgsort->sortsel->reverse);
1188 /* Set the current sort type radio button.*/
1189 cursort = IDC_SORTARRIVAL;
1190 for (i = 0; i < dlgsort->sortcount; ++i) {
1191 if (dlgsort->types[i].pineid == dlgsort->sortsel->cursort) {
1192 cursort = dlgsort->types[i].rsrcid;
1193 break;
1196 CheckRadioButton (hDlg, IDC_SORTFIRSTBUTTON, IDC_SORTLASTBUTTON,
1197 cursort);
1199 EnableWindow (GetDlgItem (hDlg, IDC_GETHELP),
1200 (dlgsort->sortsel->helptext != NULL));
1201 return (1);
1204 case WM_COMMAND:
1205 dlgsort = (DLG_SORTDATA *) GetWindowLong (hDlg, WINDOW_USER_DATA);
1206 switch (wParam) {
1207 case IDC_GETHELP:
1208 if (dlgsort->sortsel->helptext)
1209 mswin_showhelpmsg ((WINHAND)hDlg, dlgsort->sortsel->helptext);
1210 ret = TRUE;
1211 break;
1213 case IDOK:
1214 dlgsort->sortsel->rval = 1;
1216 /* Retrieve the reverse sort state. */
1217 dlgsort->sortsel->reverse = (IsDlgButtonChecked (hDlg, IDC_SORTREVERSE) == 1);
1219 /* Retrieve the new sort type. */
1220 for (i = 0; i < dlgsort->sortcount; ++i) {
1221 if (IsDlgButtonChecked (hDlg, dlgsort->types[i].rsrcid)) {
1222 dlgsort->sortsel->cursort = dlgsort->types[i].pineid;
1223 break;
1226 EndDialog (hDlg, dlgsort->sortsel->rval);
1227 ret = TRUE;
1228 break;
1230 case IDCANCEL:
1231 dlgsort->sortsel->rval = 0;
1232 ret = TRUE;
1233 EndDialog (hDlg, dlgsort->sortsel->rval);
1234 break;
1236 break;
1240 return (ret);
1244 os_config_vars_dialog (INSTALLVARS_S *ivars)
1246 DLGPROC dlgprc;
1247 HINSTANCE hInst;
1248 HWND hWnd;
1249 DLG_CONFIGVARSDATA dlgcv;
1251 mswin_killsplash();
1252 hInst = (HINSTANCE) mswin_gethinstance ();
1253 hWnd = (HWND) mswin_gethwnd ();
1255 dlgcv.ivars = ivars;
1256 dlgcv.rv = 0;
1258 dlgprc = config_vars_dialog_proc;
1260 DialogBoxParam (hInst, MAKEINTRESOURCE (IDD_CFVARSDLG), NULL,
1261 dlgprc, (LPARAM)&dlgcv);
1263 return(dlgcv.rv);
1267 * Dialog proc to handle login
1269 * Configures the dialog box on init and retrieves the settings on exit.
1271 BOOL CALLBACK __export
1272 config_vars_dialog_proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
1274 DLG_CONFIGVARSDATA *dlgcv;
1275 BOOL ret = FALSE;
1276 int usepop = 0;
1277 char buf[2*MAXPATH+1], *p;
1278 int buflen = 2*MAXPATH;
1279 #define TCBUFLEN (2*MAXPATH)
1280 TCHAR tcbuf[TCBUFLEN+1];
1281 LPTSTR tmp_lptstr;
1282 char *u;
1284 switch (uMsg) {
1285 case WM_INITDIALOG:
1286 dlgcv = (DLG_CONFIGVARSDATA *)lParam;
1287 SetWindowLong (hDlg, WINDOW_USER_DATA, (LONG) dlgcv);
1288 if(dlgcv->ivars->pname){
1289 tmp_lptstr = utf8_to_lptstr(dlgcv->ivars->pname);
1290 if(tmp_lptstr){
1291 SetDlgItemText(hDlg, IDC_CFV_PNAME, tmp_lptstr);
1292 fs_give((void **) &tmp_lptstr);
1296 if(dlgcv->ivars->userid && dlgcv->ivars->domain){
1297 snprintf(buf, sizeof(buf), "%.*s@%.*s", MAXPATH, dlgcv->ivars->userid,
1298 MAXPATH, dlgcv->ivars->domain);
1299 buf[buflen-1] = '\0';
1300 tmp_lptstr = utf8_to_lptstr(buf);
1301 if(tmp_lptstr){
1302 SetDlgItemText(hDlg, IDC_CFV_EMAILADR, tmp_lptstr);
1303 fs_give((void **) &tmp_lptstr);
1307 if(dlgcv->ivars->inboxpath){
1308 char *mbx;
1310 mbx = dlgcv->ivars->inboxpath;
1311 if(*mbx == '{' && (p = strindex(mbx, '}'))
1312 && ((*(p+1) == '\0') || !strucmp(p+1, "inbox"))){
1313 char srvbuf[MAXPATH+1], tuser[MAXPATH+1];
1314 int i, j, k;
1316 srvbuf[0] = '\0';
1317 tuser[0] = '\0';
1318 strncpy(buf, mbx+1, min(buflen, (int)(p - (mbx+1))));
1319 buf[min(buflen-1, (int)(p - (mbx+1)))] = '\0';
1320 for(i = 0, j = 0; buf[i] && j < MAXPATH; i++){
1321 if(buf[i] == '/'){
1322 if(!struncmp("/user=", buf+i, 6)){
1323 i += 6;
1324 for(k = 0; k < MAXPATH && buf[i]
1325 && buf[i] != '/'; i++)
1326 tuser[k++] = buf[i];
1327 tuser[k] = '\0';
1328 i--;
1330 else if(!struncmp("/pop3", buf+i, 5)
1331 && (!*(buf+5) || (*(buf+5) == '/'))){
1332 usepop = 1;
1333 i += 4;
1335 else
1336 srvbuf[j++] = buf[i];
1338 else
1339 srvbuf[j++] = buf[i];
1341 srvbuf[j] = '\0';
1342 if(*srvbuf){
1343 tmp_lptstr = utf8_to_lptstr(srvbuf);
1344 if(tmp_lptstr){
1345 SetDlgItemText(hDlg, IDC_CFV_MSERVER, tmp_lptstr);
1346 fs_give((void **) &tmp_lptstr);
1350 if(*tuser){
1351 tmp_lptstr = utf8_to_lptstr(tuser);
1352 if(tmp_lptstr){
1353 SetDlgItemText(hDlg, IDC_CFV_LOGIN, tmp_lptstr);
1354 fs_give((void **) &tmp_lptstr);
1358 else {
1359 tmp_lptstr = utf8_to_lptstr(mbx);
1360 if(tmp_lptstr){
1361 SetDlgItemText(hDlg, IDC_CFV_MSERVER, tmp_lptstr);
1362 fs_give((void **) &tmp_lptstr);
1365 if(*mbx != '{' && *mbx != '#')
1366 EnableWindow(GetDlgItem(hDlg, IDC_CFV_MSERVER), 0);
1369 CheckRadioButton (hDlg, IDC_CFV_IMAP, IDC_CFV_POP3,
1370 usepop ? IDC_CFV_POP3 : IDC_CFV_IMAP);
1371 if(dlgcv->ivars->smtpserver){
1372 tmp_lptstr = utf8_to_lptstr(dlgcv->ivars->smtpserver);
1373 if(tmp_lptstr){
1374 SetDlgItemText(hDlg, IDC_CFV_SMTPSERVER, tmp_lptstr);
1375 fs_give((void **) &tmp_lptstr);
1379 if(dlgcv->ivars->defmailclient)
1380 CheckDlgButton(hDlg, IDC_CFV_DEFMAILER, BST_CHECKED);
1381 if(dlgcv->ivars->defnewsclient)
1382 CheckDlgButton(hDlg, IDC_CFV_DEFNEWSRDR, BST_CHECKED);
1384 return (1);
1385 break;
1387 case WM_COMMAND:
1388 dlgcv = (DLG_CONFIGVARSDATA *) GetWindowLong (hDlg, WINDOW_USER_DATA);
1389 switch (wParam) {
1390 case IDOK:
1391 /* personal name */
1392 GetDlgItemText(hDlg, IDC_CFV_PNAME, tcbuf, TCBUFLEN);
1393 tcbuf[TCBUFLEN] = '\0';
1394 u = lptstr_to_utf8(tcbuf);
1395 if(u){
1396 removing_leading_and_trailing_white_space(u);
1397 if(dlgcv->ivars->pname)
1398 fs_give((void **)&dlgcv->ivars->pname);
1400 if(*u){
1401 dlgcv->ivars->pname = u;
1402 u = NULL;
1405 if(u)
1406 fs_give((void **) &u);
1409 /* user-id and domain */
1410 GetDlgItemText(hDlg, IDC_CFV_EMAILADR, tcbuf, TCBUFLEN);
1411 tcbuf[TCBUFLEN] = '\0';
1412 u = lptstr_to_utf8(tcbuf);
1413 if(u){
1414 removing_leading_and_trailing_white_space(u);
1415 if(p = strindex(u, '@')){
1416 *(p++) = '\0';
1417 if(dlgcv->ivars->userid)
1418 fs_give((void **)&dlgcv->ivars->userid);
1420 if(dlgcv->ivars->domain)
1421 fs_give((void **)&dlgcv->ivars->domain);
1423 if(*u){
1424 dlgcv->ivars->userid = u;
1425 u = NULL;
1428 if(*p)
1429 dlgcv->ivars->domain = cpystr(p);
1431 else{
1432 MessageBox(hDlg, TEXT("Invalid email address. Should be username@domain"),
1433 TEXT("Alpine"), MB_ICONWARNING | MB_OK);
1434 return(TRUE);
1437 if(u)
1438 fs_give((void **) &u);
1441 /* inbox-path */
1442 GetDlgItemText(hDlg, IDC_CFV_MSERVER, tcbuf, TCBUFLEN);
1443 tcbuf[TCBUFLEN] = '\0';
1444 u = lptstr_to_utf8(tcbuf);
1445 if(u){
1446 removing_leading_and_trailing_white_space(u);
1447 if(*u == '{' || *u == '#'
1448 || !IsWindowEnabled(GetDlgItem(hDlg, IDC_CFV_MSERVER))){
1449 if(dlgcv->ivars->inboxpath)
1450 fs_give((void **)&dlgcv->ivars->inboxpath);
1452 dlgcv->ivars->inboxpath = u;
1453 u = NULL;
1455 else if(*u){
1456 char tsrvr[4*MAXPATH+1];
1457 int tsrvrlen = 4*MAXPATH;
1459 if(dlgcv->ivars->inboxpath)
1460 fs_give((void **)&dlgcv->ivars->inboxpath);
1462 snprintf(tsrvr, sizeof(tsrvr), "{%s%s", u,
1463 IsDlgButtonChecked(hDlg, IDC_CFV_POP3)
1464 == BST_CHECKED ? "/pop3" : "");
1466 if(u)
1467 fs_give((void **) &u);
1469 GetDlgItemText(hDlg, IDC_CFV_LOGIN, tcbuf, TCBUFLEN);
1470 tcbuf[TCBUFLEN] = '\0';
1471 u = lptstr_to_utf8(tcbuf);
1472 if(u){
1473 removing_leading_and_trailing_white_space(u);
1474 if(*u){
1475 strncat(tsrvr, "/user=", sizeof(tsrvr)-strlen(tsrvr)-1);
1476 strncat(tsrvr, u, sizeof(tsrvr)-strlen(tsrvr)-1);
1479 strncat(tsrvr, "}inbox", sizeof(tsrvr)-strlen(tsrvr)-1);
1480 tsrvr[sizeof(tsrvr)-1] = '\0';
1481 dlgcv->ivars->inboxpath = cpystr(tsrvr);
1485 if(u)
1486 fs_give((void **) &u);
1489 /* smtp-server */
1490 GetDlgItemText(hDlg, IDC_CFV_SMTPSERVER, tcbuf, TCBUFLEN);
1491 tcbuf[TCBUFLEN] = '\0';
1492 u = lptstr_to_utf8(tcbuf);
1493 if(u){
1494 removing_leading_and_trailing_white_space(u);
1495 if(dlgcv->ivars->smtpserver)
1496 fs_give((void **)&dlgcv->ivars->smtpserver);
1498 if(*u){
1499 dlgcv->ivars->smtpserver = u;
1500 u = NULL;
1503 if(u)
1504 fs_give((void **) &u);
1507 dlgcv->ivars->defmailclient =
1508 (IsDlgButtonChecked(hDlg, IDC_CFV_DEFMAILER)
1509 == BST_CHECKED);
1510 dlgcv->ivars->defnewsclient =
1511 (IsDlgButtonChecked(hDlg, IDC_CFV_DEFNEWSRDR)
1512 == BST_CHECKED);
1514 EndDialog (hDlg, LOWORD(wParam));
1515 dlgcv->rv = 0;
1516 ret = TRUE;
1517 break;
1519 case IDCANCEL:
1520 dlgcv->rv = 1;
1521 ret = TRUE;
1522 EndDialog (hDlg, LOWORD(wParam));
1523 break;
1525 break;
1529 return (ret);
1533 * Prompt for config location
1537 os_config_dialog (char *utf8_buf, int utf8_buflen,
1538 int *regset, int nopinerc)
1540 DLGPROC dlgprc;
1541 HINSTANCE hInst;
1542 HWND hWnd;
1543 DLG_CONFIGDATA dlgcfg;
1545 mswin_killsplash();
1546 hInst = (HINSTANCE) mswin_gethinstance ();
1547 hWnd = (HWND) mswin_gethwnd ();
1549 dlgcfg.confpath = utf8_buf;
1550 dlgcfg.confpathlen = utf8_buflen;
1551 dlgcfg.setreg = 0;
1552 dlgcfg.nopinerc = nopinerc;
1553 dlgcfg.rv = 0;
1555 dlgprc = config_dialog_proc;
1557 DialogBoxParam (hInst, MAKEINTRESOURCE (IDD_CONFIGDLG), NULL,
1558 dlgprc, (LPARAM)&dlgcfg);
1560 *regset = dlgcfg.setreg;
1561 return(dlgcfg.rv);
1566 * Dialog proc to handle login
1568 * Configures the dialog box on init and retrieves the settings on exit.
1570 BOOL CALLBACK __export
1571 config_dialog_proc (HWND hDlg, UINT uMsg, WPARAM wParam, LPARAM lParam)
1573 DLG_CONFIGDATA *dlgcfg;
1574 BOOL ret = FALSE;
1575 int checked, def_rem_fldr = 1, def_diff_fldr = 0;
1577 switch (uMsg) {
1578 case WM_INITDIALOG:
1580 dlgcfg = (DLG_CONFIGDATA *)lParam;
1581 SetWindowLong (hDlg, WINDOW_USER_DATA, (LONG) dlgcfg);
1582 if(ps_global->install_flag)
1583 SetDlgItemText(hDlg, IDC_CONFTEXT, TEXT("Please specify where Alpine should create (or look for) your personal configuration file."));
1584 SetDlgItemText(hDlg, IDC_CONFEFLDRNAME, TEXT("remote_pinerc"));
1585 if(*dlgcfg->confpath){
1586 if(dlgcfg->confpath[0] == '{'){
1587 LPTSTR tfldr, p, tfldr2, p2, user;
1589 tfldr = utf8_to_lptstr((LPSTR)(dlgcfg->confpath+1));
1590 if(p = _tcschr(tfldr, '}')){
1591 *p++ = '\0';
1592 if(_tcscmp(TEXT("remote_pinerc"), p)){
1593 SetDlgItemText(hDlg, IDC_CONFEFLDRNAME, p);
1594 def_diff_fldr = 1;
1597 tfldr2 = _tcsdup(tfldr);
1598 for(p = tfldr, p2 = tfldr2; *p; p++)
1599 if(*p == '/' && !_tcsnicmp(p, TEXT("/user="), 6)){
1600 p += 6;
1601 for(user = p; *p && *p != '/'; p++);
1602 if(*p){
1603 *p2++ = *p;
1604 *p = '\0';
1606 else
1607 p--;
1608 SetDlgItemText(hDlg, IDC_CONFEUSERNAME, user);
1610 else
1611 *p2++ = *p;
1612 *p2 = '\0';
1613 SetDlgItemText(hDlg, IDC_CONFESERVER, tfldr2);
1614 if(tfldr2)
1615 MemFree((void *)tfldr2);
1618 if(tfldr)
1619 fs_give((void **) &tfldr);
1621 else{
1622 LPTSTR local_file;
1624 local_file = utf8_to_lptstr((LPSTR)dlgcfg->confpath);
1625 SetDlgItemText(hDlg, IDC_CONFEFN, local_file);
1626 if(!dlgcfg->nopinerc)
1627 def_rem_fldr = 0;
1629 fs_give((void **) &local_file);
1632 CheckRadioButton (hDlg, IDC_CONFRRADIO, IDC_CONFLRADIO,
1633 def_rem_fldr ? IDC_CONFRRADIO : IDC_CONFLRADIO);
1634 if(def_rem_fldr){
1635 EnableWindow(GetDlgItem(hDlg, IDC_CONFFNTXT), 0);
1636 EnableWindow(GetDlgItem(hDlg, IDC_CONFEFN), 0);
1637 EnableWindow(GetDlgItem(hDlg, IDC_CONFBROWSE), 0);
1638 if(!def_diff_fldr){
1639 CheckDlgButton(hDlg, IDC_CONFDFLTFLDR, BST_CHECKED);
1640 EnableWindow(GetDlgItem(hDlg, IDC_CONFEFLDRNAME), 0);
1642 EnableWindow(GetDlgItem(hDlg, IDC_CONFFLDRTXT), 0);
1644 else {
1645 EnableWindow(GetDlgItem(hDlg, IDC_CONFSRVRTXT), 0);
1646 EnableWindow(GetDlgItem(hDlg, IDC_CONFESERVER), 0);
1647 EnableWindow(GetDlgItem(hDlg, IDC_CONFUNTXT), 0);
1648 EnableWindow(GetDlgItem(hDlg, IDC_CONFEUSERNAME), 0);
1649 CheckDlgButton(hDlg, IDC_CONFDFLTFLDR, BST_CHECKED);
1650 EnableWindow(GetDlgItem(hDlg, IDC_CONFDFLTFLDR), 0);
1651 EnableWindow(GetDlgItem(hDlg, IDC_CONFFLDRTXT), 0);
1652 EnableWindow(GetDlgItem(hDlg, IDC_CONFEFLDRNAME), 0);
1654 if(ps_global->install_flag)
1655 CheckDlgButton(hDlg, IDC_CONFDFLTSET, BST_CHECKED);
1657 return (1);
1660 case WM_COMMAND:
1661 dlgcfg = (DLG_CONFIGDATA *) GetWindowLong (hDlg, WINDOW_USER_DATA);
1662 switch (wParam) {
1663 case IDC_CONFDFLTFLDR:
1664 checked = (IsDlgButtonChecked(hDlg, IDC_CONFDFLTFLDR) == BST_CHECKED);
1665 EnableWindow(GetDlgItem(hDlg, IDC_CONFFLDRTXT), checked ? 0 : 1);
1666 EnableWindow(GetDlgItem(hDlg, IDC_CONFEFLDRNAME), checked ? 0 : 1);
1667 if(checked)
1668 SetDlgItemText(hDlg, IDC_CONFEFLDRNAME, TEXT("remote_pinerc"));
1669 break;
1670 case IDC_CONFRRADIO:
1671 case IDC_CONFLRADIO:
1672 CheckRadioButton (hDlg, IDC_CONFRRADIO, IDC_CONFLRADIO, wParam);
1673 EnableWindow(GetDlgItem(hDlg, IDC_CONFFNTXT), wParam == IDC_CONFRRADIO ? 0 : 1);
1674 EnableWindow(GetDlgItem(hDlg, IDC_CONFEFN), wParam == IDC_CONFRRADIO ? 0 : 1);
1675 EnableWindow(GetDlgItem(hDlg, IDC_CONFBROWSE), wParam == IDC_CONFRRADIO ? 0 : 1);
1676 EnableWindow(GetDlgItem(hDlg, IDC_CONFSRVRTXT), wParam == IDC_CONFRRADIO ? 1 : 0);
1677 EnableWindow(GetDlgItem(hDlg, IDC_CONFESERVER), wParam == IDC_CONFRRADIO ? 1 : 0);
1678 EnableWindow(GetDlgItem(hDlg, IDC_CONFUNTXT), wParam == IDC_CONFRRADIO ? 1 : 0);
1679 EnableWindow(GetDlgItem(hDlg, IDC_CONFEUSERNAME), wParam == IDC_CONFRRADIO ? 1 : 0);
1680 EnableWindow(GetDlgItem(hDlg, IDC_CONFDFLTFLDR), wParam == IDC_CONFRRADIO ? 1 : 0);
1681 if(wParam == IDC_CONFRRADIO && IsDlgButtonChecked(hDlg, IDC_CONFDFLTFLDR) == BST_UNCHECKED){
1682 EnableWindow(GetDlgItem(hDlg, IDC_CONFFLDRTXT), 1);
1683 EnableWindow(GetDlgItem(hDlg, IDC_CONFEFLDRNAME), 1);
1685 else if(wParam == IDC_CONFLRADIO){
1686 EnableWindow(GetDlgItem(hDlg, IDC_CONFFLDRTXT), 0);
1687 EnableWindow(GetDlgItem(hDlg, IDC_CONFEFLDRNAME), 0);
1689 break;
1690 case IDC_CONFBROWSE:
1691 if(1){
1692 TCHAR fn[MAXPATH+1];
1693 OPENFILENAME ofn;
1695 fn[0] = '\0';
1697 /* Set up the BIG STRUCTURE. see mswin.c */
1698 memset (&ofn, 0, sizeof(ofn));
1699 ofn.lStructSize = OPENFILENAME_SIZE_VERSION_400;
1700 ofn.hwndOwner = hDlg;
1701 ofn.lpstrFilter = NULL;
1702 ofn.lpstrCustomFilter = NULL;
1703 ofn.nFilterIndex = 0;
1704 ofn.lpstrFile = fn;
1705 ofn.nMaxFile = MAXPATH;
1706 ofn.lpstrFileTitle = NULL;
1707 ofn.nMaxFileTitle = 0;
1708 ofn.lpstrInitialDir = NULL;
1709 ofn.lpstrTitle = TEXT("Select File");
1710 ofn.Flags = OFN_HIDEREADONLY | OFN_PATHMUSTEXIST;
1711 ofn.lpstrDefExt = NULL;
1713 if (GetOpenFileName (&ofn)) {
1714 SetDlgItemText(hDlg, IDC_CONFEFN, fn);
1717 break;
1718 case IDOK:
1719 /* Retrieve the new username/passwd. */
1720 if(IsDlgButtonChecked(hDlg, IDC_CONFDFLTSET) == BST_CHECKED)
1721 dlgcfg->setreg = 1;
1722 else
1723 dlgcfg->setreg = 0;
1724 if(IsDlgButtonChecked(hDlg, IDC_CONFRRADIO) == BST_CHECKED){
1725 TCHAR lptstr_buf[MAXPATH+1];
1726 char *utf8_srvr, *utf8_username, *utf8_fldrname;
1728 GetDlgItemText(hDlg, IDC_CONFESERVER, lptstr_buf, MAXPATH);
1729 lptstr_buf[MAXPATH] = '\0';
1730 utf8_srvr = lptstr_to_utf8(lptstr_buf);
1731 removing_leading_and_trailing_white_space(utf8_srvr);
1732 if(!*utf8_srvr){
1733 MessageBox(hDlg, TEXT("IMAP Server field empty"),
1734 TEXT("Alpine"), MB_ICONWARNING | MB_OK);
1735 if(utf8_srvr)
1736 fs_give((void **) &utf8_srvr);
1738 return(TRUE);
1741 GetDlgItemText(hDlg, IDC_CONFEUSERNAME, lptstr_buf, MAXPATH);
1742 lptstr_buf[MAXPATH] = '\0';
1743 utf8_username = lptstr_to_utf8(lptstr_buf);
1744 removing_leading_and_trailing_white_space(utf8_username);
1745 if(IsDlgButtonChecked(hDlg, IDC_CONFDFLTFLDR) == BST_CHECKED){
1746 utf8_fldrname = cpystr("remote_pinerc");
1748 else{
1749 GetDlgItemText(hDlg, IDC_CONFEFLDRNAME, lptstr_buf, MAXPATH);
1750 lptstr_buf[MAXPATH] = '\0';
1751 utf8_fldrname = lptstr_to_utf8(lptstr_buf);
1752 removing_leading_and_trailing_white_space(utf8_fldrname);
1753 if(!*utf8_fldrname){
1754 MessageBox(hDlg, TEXT("Configuration Folder Name field empty"),
1755 TEXT("Alpine"), MB_ICONWARNING | MB_OK);
1756 if(utf8_srvr)
1757 fs_give((void **) &utf8_srvr);
1759 if(utf8_username)
1760 fs_give((void **) &utf8_username);
1762 if(utf8_fldrname)
1763 fs_give((void **) &utf8_fldrname);
1765 return(TRUE);
1768 if((strlen(utf8_srvr)
1769 + strlen(utf8_username)
1770 + strlen(utf8_fldrname)
1771 + 11) > dlgcfg->confpathlen){
1772 MessageBox(hDlg, TEXT("Config path too long"),
1773 TEXT("Alpine"), MB_ICONWARNING | MB_OK);
1774 if(utf8_srvr)
1775 fs_give((void **) &utf8_srvr);
1777 if(utf8_username)
1778 fs_give((void **) &utf8_username);
1780 if(utf8_fldrname)
1781 fs_give((void **) &utf8_fldrname);
1783 return(TRUE);
1786 snprintf(dlgcfg->confpath, dlgcfg->confpathlen, "{%s%s%s}%s", utf8_srvr,
1787 *utf8_username ? "/user=" : "",
1788 utf8_username, utf8_fldrname);
1789 if(utf8_srvr)
1790 fs_give((void **) &utf8_srvr);
1792 if(utf8_username)
1793 fs_give((void **) &utf8_username);
1795 if(utf8_fldrname)
1796 fs_give((void **) &utf8_fldrname);
1798 else{
1799 TCHAR lptstr_fn[MAXPATH+1];
1800 char *utf8_fn;
1802 GetDlgItemText(hDlg, IDC_CONFEFN, lptstr_fn, MAXPATH);
1803 lptstr_fn[MAXPATH] = '\0';
1804 utf8_fn = lptstr_to_utf8(lptstr_fn);
1805 removing_leading_and_trailing_white_space(utf8_fn);
1806 if(!*utf8_fn){
1807 MessageBox(hDlg, TEXT("Configuration File Name field empty"),
1808 TEXT("Alpine"), MB_ICONWARNING | MB_OK);
1809 if(utf8_fn)
1810 fs_give((void **) &utf8_fn);
1812 return(TRUE);
1815 if(strlen(utf8_fn) >= dlgcfg->confpathlen){
1816 MessageBox(hDlg, TEXT("Config path too long"),
1817 TEXT("Alpine"), MB_ICONWARNING | MB_OK);
1818 if(utf8_fn)
1819 fs_give((void **) &utf8_fn);
1821 return(TRUE);
1824 strncpy(dlgcfg->confpath, utf8_fn, dlgcfg->confpathlen);
1825 dlgcfg->confpath[dlgcfg->confpathlen-1] = '\0';
1826 if(utf8_fn)
1827 fs_give((void **) &utf8_fn);
1830 EndDialog (hDlg, LOWORD(wParam));
1831 dlgcfg->rv = 0;
1832 ret = TRUE;
1833 break;
1835 case IDCANCEL:
1836 dlgcfg->rv = 1;
1837 ret = TRUE;
1838 EndDialog (hDlg, LOWORD(wParam));
1839 break;
1841 break;
1845 return (ret);
1849 * Get a button position in the parent's coordinate space.
1851 static void
1852 GetBtnPos (HWND hPrnt, HWND hWnd, RECT *r)
1854 GetWindowRect (hWnd, r);
1855 ScreenToClient (hPrnt, (POINT *) r);
1856 ScreenToClient (hPrnt, (POINT *) &r->right);