Message-Id: <2.2.32.19960428000927.006a36d8@tulsa.dowell.slb.com>
X-Sender: brydon@tulsa.dowell.slb.com
X-Mailer: Windows Eudora Pro Version 2.2 (32)
Mime-Version: 1.0
Content-Type: multipart/mixed; boundary="=====================_830668167==_"
Date: Sat, 27 Apr 1996 19:09:27 -0500
To: DUMOULIN@TITAN.KSC.NASA.GOV
From: Harvey Brydon <brydon@tulsa.dowell.slb.com>
Subject: WinVN submission - Article Action newsgroup filter
Cc: brydon@tulsa.dowell.slb.com,vev@michvhf.com
X-Attachments: D:\share\winvn\HB998B2\WINVN.RC;
  D:\share\winvn\HB998B2\WVCLASS.H; D:\share\winvn\HB998B2\wvglob.h;
  D:\share\winvn\HB998B2\wvsckgen.c; D:\share\winvn\HB998B2\wvstates.h;
  D:\share\winvn\HB998B2\wvutil.cpp;D:\share\winvn\HB998B2\WVAction.cpp;

--=====================_830668167==_
Content-Type: text/plain; charset="us-ascii"

Reasons for submission:
- Add support for "newsgroups" as selection/kill criteria.



--=====================_830668167==_
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: attachment; filename="WINVN.RC"

//Microsoft Visual C++ generated resource script.
//
#include "resource.h"

#define APSTUDIO_READONLY_SYMBOLS
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 2 resource.
//
#define APSTUDIO_HIDDEN_SYMBOLS
#include <windows.h>
#undef APSTUDIO_HIDDEN_SYMBOLS
#include "winvn.h"
#include "winsock.h"
#include "wvstates.h"
#include "gensock/gensock.h"
#define RCSVERSION "$Id: winvn.rc 1.79 1995/11/09 00:24:11 dumoulin Exp $"

/////////////////////////////////////////////////////////////////////////////
#undef APSTUDIO_READONLY_SYMBOLS


/////////////////////////////////////////////////////////////////////////////
//
// Icon
//

WINVN                   ICON    DISCARDABLE     "ICOBMP/WINVN.ICO"
WVGROUP                 ICON    DISCARDABLE     "ICOBMP/WVGROUP.ICO"
WVART                   ICON    DISCARDABLE     "ICOBMP/WVART.ICO"
WVPOST                  ICON    DISCARDABLE     "ICOBMP/WVPOST.ICO"
WVMAIL                  ICON    DISCARDABLE     "ICOBMP/WVMAIL.ICO"
WVDISH                  ICON    DISCARDABLE     "ICOBMP/DISH.ICO"
WVCSTAT2                ICON    DISCARDABLE     "ICOBMP/WVCSTAT2.ICO"
WVDEBUGC                ICON    DISCARDABLE     "ICOBMP/WVDEBUGC.ICO"
WVCSTAT1                ICON    DISCARDABLE     "ICOBMP/WVCSTAT1.ICO"

/////////////////////////////////////////////////////////////////////////////
//
// Menu
//

CONFMENU MENU DISCARDABLE 
BEGIN
    POPUP "&Network"
    BEGIN
        MENUITEM "&Connect to Server",          IDM_CONNECT
        MENUITEM "&Disconnect from Server",     IDM_DISCONNECT
        MENUITEM "&Reconnect to Server",        IDM_RECONNECT
        MENUITEM SEPARATOR
        MENUITEM "&Reset Server Protocol",      IDM_RESET
        MENUITEM "&Quit without Saving",        IDM_QUIT
        MENUITEM SEPARATOR
        MENUITEM "Mail &Logout",                IDM_LOGOUT
        MENUITEM "E&xit\tAlt+F4",               IDM_EXIT
    END
    POPUP "&Group"
    BEGIN
        MENUITEM "&Find...\tCtrl+F",            IDM_FIND
        MENUITEM "Find &Next\tF3",              IDM_FIND_NEXT_SAME
        MENUITEM SEPARATOR
        MENUITEM "&Subscribe Selected Groups",  IDM_SUBSCRIBE
        MENUITEM "&Unsubscribe Selected Groups", IDM_UNSUBSCRIBE
        MENUITEM SEPARATOR
        MENUITEM "&Move Selected Groups to Top", IDM_GROUP_TOP
        MENUITEM "Sort Selected &Groups",       IDM_SORT_SELECTED
        MENUITEM "S&elect All",                 IDM_SELECT_ALL
        MENUITEM "&Deselect All",               IDM_UNSEL_ALL
        MENUITEM SEPARATOR
        MENUITEM "S&ave NewsRC File",           IDM_SAVE_NEWSRC
    END
    POPUP "&Utilities"
    BEGIN
        MENUITEM "New &Article\tCtrl+L",        IDM_POST
        MENUITEM "&Compose Mail\tCtrl+O",       IDM_MAIL
        MENUITEM SEPARATOR
        POPUP "&Batch Send"
        BEGIN
            MENUITEM "&Posts",                      IDM_SEND_ALL_POST
            MENUITEM "&Mails",                      IDM_SEND_ALL_MAIL
        END
        MENUITEM SEPARATOR
        MENUITEM "&Decode a File...",           IDM_DECODE_FILE
        MENUITEM "&Encode a File...",           IDM_ENCODE_FILE
    END
    POPUP "&Config"
    BEGIN
        MENUITEM "&Communications...",          IDM_COMMOPTIONS
        MENUITEM "&Personal Info...",           IDM_CONFIG_PERSONAL
        MENUITEM "&Logging...",                 IDM_CONFIG_LOG
        MENUITEM "&Smart Filer...",             IDM_CONFIG_SMART_FILER
        MENUITEM "C&onfirmations...",           IDM_CONFIG_CONFIRMATIONS
        MENUITEM SEPARATOR
        MENUITEM "&Group List...",              IDM_CONFIG_GROUPLIST
        MENUITEM "A&rticle List...",            IDM_CONFIG_ARTLIST
        MENUITEM "Ar&ticle...",                 IDM_CONFIG_ARTICLE
        MENUITEM "&Execute...",                 IDM_CONFIG_EXECUTE
        MENUITEM "Co&mpositions...",            IDM_COMPOSE_PREFS
        MENUITEM "&Attachments...",             IDM_ATTACH_PREFS
        MENUITEM "&Decoding...",                IDM_CONFIG_CODING
        MENUITEM SEPARATOR
        POPUP "&Fonts"
        BEGIN
            MENUITEM "&WinVN System",               IDM_FONT_WINVNSYSTEM
            MENUITEM "Group/Article &List",         IDM_FONT_GROUPLIST
            MENUITEM "&Article Text",               IDM_FONT_ARTICLE_TEXT
            MENUITEM "&Composition Text",           IDM_FONT_COMPOSITION
            MENUITEM "&Status Text",                IDM_FONT_STATUS_TEXT
            MENUITEM "&Print Text",                 IDM_FONT_PRINT_TEXT
        END
        POPUP "C&olor"
        BEGIN
            MENUITEM "&Unsubscribed Group",         IDM_COLOR_UNSUBSCRIBED
            MENUITEM "&Subscribed Group",           IDM_COLOR_SUBSCRIBED
            MENUITEM SEPARATOR
            MENUITEM "Unseen &Article",             IDM_COLOR_UNSEEN
            MENUITEM "Seen A&rticle",               IDM_COLOR_SEEN
            MENUITEM "&Marked Seen Article",        IDM_COLOR_KILLED
            MENUITEM SEPARATOR
            MENUITEM "&List Background",            IDM_COLOR_LIST_BACKGROUND

            MENUITEM "Article &Background",         IDM_COLOR_ARTICLE_BACKGROUND

            MENUITEM "Arti&cle Text",               IDM_COLOR_ARTICLE_TEXT
            MENUITEM "S&tatus Background",          IDM_COLOR_STATUS_BACKGROUND

            MENUITEM "Status Te&xt",                IDM_COLOR_STATUS_TEXT
            MENUITEM SEPARATOR
            MENUITEM "True &Inverse Selections",    IDM_TRUE_INVERSE_SELECTIONS

        END
        MENUITEM SEPARATOR
        MENUITEM "Sa&ve Configuration",         IDM_SAVE_CONFIG
    END
    POPUP "&Window"
    BEGIN
        MENUITEM "&Cascade",                    IDM_WINDOW_CASCADE
        POPUP "C&lose"
        BEGIN
            MENUITEM "&Articles",                   IDM_CLOSE_ALL_ARTICLE
            MENUITEM "&Groups",                     IDM_CLOSE_ALL_GROUP
            MENUITEM "&Compositions",               IDM_CLOSE_ALL_COMPOSE
            MENUITEM "&Status",                     IDM_CLOSE_ALL_STATUS
            MENUITEM SEPARATOR
            MENUITEM "All &Windows",                IDM_CLOSE_ALL
        END
        POPUP "&Minimize"
        BEGIN
            MENUITEM "&Articles",                   IDM_MINIMIZE_ALL_ARTICLE
            MENUITEM "&Groups",                     IDM_MINIMIZE_ALL_GROUP
            MENUITEM "&Compositions",               IDM_MINIMIZE_ALL_COMPOSE
            MENUITEM "&Status",                     IDM_MINIMIZE_ALL_STATUS
            MENUITEM SEPARATOR
            MENUITEM "All &Windows",                IDM_MINIMIZE_ALL
        END
        MENUITEM "&Restore All",                IDM_RESTORE_ALL
        MENUITEM SEPARATOR
        MENUITEM "&Save Window positions",      IDM_SAVE_WINDOW
    END
    POPUP "&Help"
    BEGIN
        MENUITEM "&Index",                      IDM_HELP
        MENUITEM SEPARATOR
        MENUITEM "&Show Version",               IDM_SHOW_VERSION
        MENUITEM "&About...",                   ID_ABOUT
    END
END

VIEWMENU MENU DISCARDABLE 
BEGIN
    POPUP "&Articles"
    BEGIN
        MENUITEM "New &Article\tCtrl+L",        IDM_POST
        MENUITEM "&Compose Mail\tCtrl+O",       IDM_MAIL
        MENUITEM "Update from Server\tCtrl+U",  IDM_UPDATE
        MENUITEM SEPARATOR
        POPUP "Select/Deselect Article Menu"
        BEGIN
            MENUITEM "&Select All Articles\tCtrl+A", IDM_SELECT_ALL
            MENUITEM "Select All S&een Articles",   IDM_MARK_READ_ARTICLES
            MENUITEM "Select All &Unseen Articles", IDM_MARK_UNREAD_ARTICLES
            MENUITEM "Select Articles &Containing String...", 
                                                    IDM_SELECT_MATCH
            MENUITEM SEPARATOR
            MENUITEM "&Deselect All Articles",      IDM_DESELECT_ALL
            MENUITEM "Deselect &All Seen Articles", IDM_UNMARK_READ_ARTICLES
            MENUITEM "Deselect All U&nseen Articles", 
                                                    IDM_UNMARK_UNREAD_ARTICLES

            MENUITEM "Deselect Articles C&ontaining String", 
                                                    IDM_DESELECT_MATCH
        END
        MENUITEM "&Save Selected Articles...",  IDM_SAVE_SELECTED
        MENUITEM "D&ecode Selected Articles...", IDM_DECODE_SELECTED
        MENUITEM "Read Selected Articles\tF5",  IDM_READ_SELECTED
        MENUITEM SEPARATOR
        MENUITEM "&Mark Selected Articles As Seen", IDM_MARK_SELECTED
        MENUITEM "Mark Selected Articles As &Unseen", IDM_UNMARK_SELECTED
        MENUITEM SEPARATOR
        MENUITEM "&Preferences...",             IDM_CONFIG_ARTLIST
        MENUITEM SEPARATOR
        MENUITEM "Ca&tch-Up and Exit",          IDM_MARK_ALL
        MENUITEM "E&xit",                       IDV_EXIT
    END
    POPUP "&View"
    BEGIN
        MENUITEM "&Filters...",                 IDM_VIEW_ACTION
        MENUITEM SEPARATOR
        MENUITEM "Sort by &Date",               IDM_SORT_DATE
        MENUITEM "Sort by &Subject",            IDM_SORT_SUBJECT
        MENUITEM "Sort by # &Lines",            IDM_SORT_LINES
        MENUITEM "Sort by &Threads (strict)",   IDM_SORT_THREADS
        MENUITEM "Sort by Thread/S&ubject",     IDM_SORT_THREADSUB
        MENUITEM "Sort by Article &Number",     IDM_SORT_ARTNUM
        MENUITEM "Sort by &Author",             IDM_SORT_FROM
    END
    POPUP "&Search"
    BEGIN
        MENUITEM "&Find...\tCtrl+F",            IDM_FIND
        MENUITEM "Find &Next\tF3",              IDM_FIND_NEXT_SAME
    END
END

ARTMENU MENU DISCARDABLE 
BEGIN
    POPUP "&File"
    BEGIN
        MENUITEM "&Save",                       IDM_SAVE
        MENUITEM "Save &As...",                 IDM_SAVEAS
        MENUITEM "&Print",                      IDM_PRINT
        MENUITEM "P&rint Setup...",             IDM_PRINT_SETUP
        MENUITEM "&Decode Article...",          IDM_DECODE_ARTICLE
        MENUITEM "&Cancel Article",             IDM_CANCELART
        MENUITEM SEPARATOR
        MENUITEM "Pre&ferences...",             IDM_CONFIG_ARTICLE
        MENUITEM SEPARATOR
        MENUITEM "E&xit",                       IDV_EXIT
    END
    POPUP "&Edit"
    BEGIN
        MENUITEM "&Copy\tCtrl+C",               IDM_COPY, GRAYED
        MENUITEM "&Deselect All\tCtrl+D",       IDM_DESELECT_ALL, GRAYED
        MENUITEM "Select &All\tCtrl+A",         IDM_SELECT_ALL
    END
    POPUP "&Search"
    BEGIN
        MENUITEM "&Find...\tCtrl+F",            IDM_SEARCH
        MENUITEM "Find &Next",                  IDM_SEARCH_NEXT
    END
    POPUP "&View"
    BEGIN
        MENUITEM "&Next Article\tCtrl+N",       IDM_NEXT_ARTICLE
        MENUITEM "Next &Unseen\tF2",            IDM_FIND_NEXT_UNSEEN
        MENUITEM "Next with same &Subject\tF3", IDM_NEXT_SAME_SUBJ
        MENUITEM "Next S&elected\tF5",          IDM_FIND_NEXT_SELECTED
        MENUITEM "&Previous Article\tCtrl+P",   IDM_PREV_ARTICLE
        MENUITEM "&ROT13\tCtrl+R",              IDM_ROT13
    END
    POPUP "&Respond"
    BEGIN
        MENUITEM "Fo&llowup Article\tCtrl+L",   IDM_POST
        MENUITEM "F&ollowup Mail\tCtrl+O",      IDM_MAIL
        MENUITEM SEPARATOR
        MENUITEM "Forward Article\tCtrl+B",     IDM_FORWARD
    END
END

COMPOSEMENU MENU DISCARDABLE 
BEGIN
    POPUP "&File"
    BEGIN
        MENUITEM "&Send\tCtrl+S",               IDM_SEND
        MENUITEM "&Attach...",                  IDM_ATTACH
        MENUITEM "&Read File...",               IDM_READ_FILE
        MENUITEM SEPARATOR
        POPUP "&Preferences"
        BEGIN
            MENUITEM "&Composition...",             IDM_COMPOSE_PREFS
            MENUITEM "&Attachments...",             IDM_ATTACH_PREFS
        END
        MENUITEM SEPARATOR
        MENUITEM "A&bort Posting",              IDM_CANCEL
    END
    POPUP "&Edit"
    BEGIN
        MENUITEM "&Undo\tCtrl+Z",               IDM_UNDO
        MENUITEM SEPARATOR
        MENUITEM "Cu&t\tCtrl+X",                IDM_CUT
        MENUITEM "&Copy\tCtrl+C",               IDM_COPY
        MENUITEM "&Paste\tCtrl+V",              IDM_PASTE
        MENUITEM "&Delete\tDel",                IDM_DEL
        MENUITEM SEPARATOR
        MENUITEM "&Select All\tCtrl+A",         IDM_SELECT_ALL
        MENUITEM SEPARATOR
        MENUITEM "&ROT13\tCtrl+R",              IDM_ROT13
        MENUITEM "&Word Wrap",                  IDM_WORDWRAP
    END
END


/////////////////////////////////////////////////////////////////////////////
//
// Accelerator
//

WINVNACCEL ACCELERATORS MOVEABLE PURE 
BEGIN
    VK_BACK,        IDM_UNDO,               VIRTKEY, ALT, NOINVERT
    VK_DELETE,      IDM_CUT,                VIRTKEY, SHIFT, NOINVERT
    VK_F1,          IDM_HELP,               VIRTKEY, NOINVERT
    VK_F2,          IDM_FIND_NEXT_UNSEEN,   VIRTKEY, NOINVERT
    VK_F3,          IDM_FIND_NEXT_SAME,     VIRTKEY, NOINVERT
    VK_INSERT,      IDM_COPY,               VIRTKEY, CONTROL, NOINVERT
    VK_INSERT,      IDM_PASTE,              VIRTKEY, SHIFT, NOINVERT
    "^A",           IDM_SELECT_ALL,         ASCII,  NOINVERT
    "^B",           IDM_FORWARD,            ASCII,  NOINVERT
    "^C",           IDM_COPY,               ASCII,  NOINVERT
    "^D",           IDM_DESELECT_ALL,       ASCII,  NOINVERT
    "^F",           IDM_FIND,               ASCII,  NOINVERT
    "^L",           IDM_POST,               ASCII,  NOINVERT
    "^N",           IDM_NEXT_ARTICLE,       ASCII,  NOINVERT
    "^O",           IDM_MAIL,               ASCII,  NOINVERT
    "^P",           IDM_PREV_ARTICLE,       ASCII,  NOINVERT
    "^R",           IDM_ROT13,              ASCII,  NOINVERT
    "^S",           IDM_SEND,               ASCII,  NOINVERT
    "^T",           IDM_ATTACH,             ASCII,  NOINVERT
    "^U",           IDM_UPDATE,             ASCII,  NOINVERT
    "^V",           IDM_PASTE,              ASCII,  NOINVERT
    "^X",           IDM_CUT,                ASCII,  NOINVERT
    "^Z",           IDM_UNDO,               ASCII,  NOINVERT
END


/////////////////////////////////////////////////////////////////////////////
//
// Data
//

DLGINCLUDE RCDATA DISCARDABLE 
BEGIN
    "WVDLG.H\0"
END


/////////////////////////////////////////////////////////////////////////////
//
// Dialog
//

WINVNSAVEART DIALOG DISCARDABLE  26, 39, 257, 82
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION
CAPTION "Save Article to File"
FONT 8, "MS Sans Serif"
BEGIN
    EDITTEXT        IDD_FILENAME,18,28,172,12,ES_AUTOHSCROLL
    CHECKBOX        "&Append to this file",IDD_APPEND,18,45,88,12
    DEFPUSHBUTTON   "&OK",IDOK,208,12,33,16
    PUSHBUTTON      "&Browse",ID_BROWSE,208,32,33,16
    PUSHBUTTON      "&Cancel",ID_CANCEL,208,52,33,16
    LTEXT           "Please enter a file name for the saved article:",400,18,
                    15,152,8,NOT WS_GROUP
END

WINVNSAVEARTS DIALOG DISCARDABLE  26, 39, 259, 86
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION
CAPTION "Save Articles to File"
FONT 8, "MS Sans Serif"
BEGIN
    EDITTEXT        IDD_FILENAME,18,28,172,12,ES_AUTOHSCROLL
    CHECKBOX        "&Append to this file",IDD_APPEND,18,45,88,12
    CONTROL         "&Keep Current Article Header Visible",
                    IDD_KEEP_HEADER_VISIBLE,"Button",BS_AUTOCHECKBOX | 
                    WS_TABSTOP,18,57,131,10
    DEFPUSHBUTTON   "&OK",IDOK,206,7,33,16
    PUSHBUTTON      "&Browse",ID_BROWSE,206,27,33,16
    PUSHBUTTON      "&Cancel",ID_CANCEL,206,47,33,16
    LTEXT           "Please enter a file name for the saved articles:",400,
                    18,15,156,8,NOT WS_GROUP
END

WINVNFIND DIALOG DISCARDABLE  83, 36, 131, 60
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION
CAPTION "Search for String"
FONT 8, "MS Sans Serif"
BEGIN
    LTEXT           "Search for:",550,10,5,57,8,NOT WS_GROUP
    EDITTEXT        IDD_SEARCH_STRING,9,18,108,12,ES_AUTOHSCROLL
    DEFPUSHBUTTON   "&OK",IDOK,25,39,32,15
    PUSHBUTTON      "&Cancel",ID_CANCEL,73,39,32,15
END

WINVNGROUPLIST DIALOG DISCARDABLE  98, 23, 325, 193
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION
CAPTION "New Newsgroups"
FONT 8, "MS Sans Serif"
BEGIN
    LTEXT           "Select the groups to which you want to subscribe.\nDouble-click on an unsubscribed group to subscribe.\nDouble-click on a subscribed group to unsubscribe.",
                    508,138,22,173,30,NOT WS_GROUP
    LISTBOX         IDD_HIERARCHY_LISTBOX,10,17,120,44,LBS_SORT | WS_VSCROLL | 
                    WS_TABSTOP
    LTEXT           "Subscribed Groups:",IDC_STATIC,163,73,87,8
    LISTBOX         IDD_SUBSCRIBED_GROUP_LISTBOX,162,83,153,84,LBS_SORT | 
                    LBS_DISABLENOSCROLL | WS_VSCROLL | WS_HSCROLL | 
                    WS_TABSTOP
    LTEXT           "Unsubscribed Groups:",IDC_STATIC,6,73,90,8
    DEFPUSHBUTTON   "&OK",IDOK,119,172,35,15
    PUSHBUTTON      "&Cancel",ID_CANCEL,168,172,35,15
    GROUPBOX        "Top Level Hierarchy",IDC_STATIC,5,3,312,64
    LISTBOX         IDD_UNSUBSCRIBED_GROUP_LISTBOX,5,83,153,84,LBS_SORT | 
                    LBS_DISABLENOSCROLL | WS_VSCROLL | WS_HSCROLL | 
                    WS_TABSTOP
END

WINVNPERSONAL DIALOG DISCARDABLE  11, 16, 214, 108
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION
CAPTION "Personal Information"
FONT 8, "MS Sans Serif"
BEGIN
    EDITTEXT        ID_CONFIG_NAME,85,15,122,12,ES_AUTOHSCROLL
    EDITTEXT        ID_CONFIG_EMAIL,85,29,122,12,ES_AUTOHSCROLL
    EDITTEXT        IDD_REPLY_TO,85,43,122,12,ES_AUTOHSCROLL
    EDITTEXT        ID_CONFIG_ORG,85,57,122,12,ES_AUTOHSCROLL
    DEFPUSHBUTTON   "&OK",IDOK,58,84,43,15
    PUSHBUTTON      "&Cancel",ID_CANCEL,118,84,38,15
    RTEXT           "Your name",-1,13,17,68,8,NOT WS_GROUP
    RTEXT           "Your email address",-1,13,31,68,8,NOT WS_GROUP
    RTEXT           "Organization name",-1,13,59,68,8,NOT WS_GROUP
    RTEXT           "Reply-to email address",-1,3,44,78,8,NOT WS_GROUP
END

WINVNCOMM DIALOG DISCARDABLE  40, 41, 281, 262
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Communications Options"
FONT 8, "MS Sans Serif"
BEGIN
    EDITTEXT        ID_CONFIG_NNTP_SERVER,82,16,91,12,ES_AUTOHSCROLL
    CONTROL         "Co&nnect at startup",ID_CONFIG_CONNECT_AT_START,
                    "Button",BS_AUTOCHECKBOX | WS_TABSTOP,180,17,73,9
    EDITTEXT        ID_CONFIG_NNTP_PORT,82,32,26,12
    EDITTEXT        ID_CONFIG_AUTH_USERNAME,89,64,91,12,ES_AUTOHSCROLL
    EDITTEXT        ID_CONFIG_AUTH_PASSWORD,89,81,91,12,ES_PASSWORD | 
                    ES_AUTOHSCROLL
    CONTROL         "Save &password",IDD_SAVEPASSWORD,"Button",
                    BS_AUTOCHECKBOX | WS_TABSTOP,186,81,65,12
    EDITTEXT        ID_CONFIG_SMTP_SERVER,82,144,91,12,ES_AUTOHSCROLL
    EDITTEXT        ID_CONFIG_TIMEZONE,34,186,48,12,ES_AUTOHSCROLL
    CONTROL         "&Disabled",IDD_MAIL_SELECT_NONE,"Button",
                    BS_AUTORADIOBUTTON,194,152,47,10
    CONTROL         "Use &SMTP",IDD_MAIL_SELECT_SMTP,"Button",
                    BS_AUTORADIOBUTTON,194,164,54,10
    CONTROL         "Use &MAPI",IDD_MAIL_SELECT_MAPI,"Button",
                    BS_AUTORADIOBUTTON,194,176,53,10
    CONTROL         "&Auto Select",IDD_MAIL_SELECT_AUTO,"Button",
                    BS_AUTORADIOBUTTON,194,187,59,10
    CONTROL         "MAPI demand &logon",IDD_DEMANDLOGON,"Button",
                    BS_AUTOCHECKBOX | WS_TABSTOP,184,208,80,12
    DEFPUSHBUTTON   "&OK",IDOK,88,239,38,18
    PUSHBUTTON      "&Cancel",ID_CANCEL,147,239,38,18
    RTEXT           "NNTP Server",IDC_STATIC,7,18,72,8,NOT WS_GROUP
    RTEXT           "TCP port",IDC_STATIC,42,33,37,8,NOT WS_GROUP
    RTEXT           "SMTP Server",IDC_STATIC,14,145,64,8,NOT WS_GROUP
    LTEXT           "NOTE:  Use ONLY if you are sure this is required by your News Server",
                    520,25,100,235,12
    RTEXT           "Username",105,51,66,34,8
    RTEXT           "Password",106,53,82,33,8
    GROUPBOX        "News",IDC_STATIC,4,4,268,119
    GROUPBOX        "Mail",IDC_STATIC,4,132,264,102
    GROUPBOX        "Mail Transport",IDC_STATIC,189,139,72,63,WS_GROUP
    GROUPBOX        "Authorization Information",IDC_STATIC,14,51,248,62
    RTEXT           "IE:  New Zealand Time",IDC_STATIC,34,202,80,8
    RTEXT           "Eastern Standard Time",IDC_STATIC,34,210,80,8
    LTEXT           "=  EST5EDT",IDC_STATIC,114,210,52,7
    LTEXT           "=  NZS-12NZD",IDC_STATIC,114,202,52,9
    GROUPBOX        "Time Zone",IDC_STATIC,26,174,148,52
    EDITTEXT        ID_CONFIG_MAPI_PREFIX,82,159,91,12,ES_AUTOHSCROLL
    RTEXT           "MAPI Prefix",IDC_STATIC,14,161,64,8,NOT WS_GROUP
END

PRINTDIALOG DIALOG DISCARDABLE  56, 61, 194, 73
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Print"
FONT 8, "Helv"
BEGIN
    CTEXT           "",IDD_PRINTSTATUS,6,7,182,8,NOT WS_GROUP
    CTEXT           "",IDD_PRINTSUBJECT,5,18,182,8,NOT WS_GROUP
    CTEXT           "",IDD_PRINTDEVICE,5,30,184,8,NOT WS_GROUP
END

THRESHOLD DIALOG DISCARDABLE  58, 66, 187, 97
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "How many articles do you want?"
FONT 8, "MS Sans Serif"
BEGIN
    EDITTEXT        IDD_ARTS_TO_GRAB,14,22,57,12,ES_AUTOHSCROLL
    PUSHBUTTON      "Latest &Unseen",ID_THRESHOLD_UNREAD,97,20,57,14
    PUSHBUTTON      "&100",ID_100_ARTS,14,41,37,14
    PUSHBUTTON      "&250",ID_250_ARTS,56,42,37,14
    PUSHBUTTON      "&500",ID_500_ARTS,96,41,37,14
    PUSHBUTTON      "&All ",ID_THRESHOLD_ALL,136,41,37,14
    DEFPUSHBUTTON   "&OK",IDOK,48,73,32,14
    PUSHBUTTON      "&Cancel",ID_CANCEL,106,73,32,14
    GROUPBOX        "Number to Fetch",IDC_STATIC,5,5,177,60
END

WINVNATTACHPREFS DIALOG DISCARDABLE  0, 0, 281, 223
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Attachment Preferences"
FONT 8, "MS Sans Serif"
BEGIN
    COMBOBOX        IDD_ARTICLE_SPLIT_LENGTH,8,20,98,46,CBS_DROPDOWN | 
                    CBS_SORT | WS_VSCROLL | WS_TABSTOP
    COMBOBOX        IDD_CODING_TYPE,8,52,98,60,CBS_DROPDOWNLIST | WS_VSCROLL | 
                    WS_TABSTOP
    EDITTEXT        IDD_CUSTOM_TABLE,8,80,263,12,ES_AUTOHSCROLL
    EDITTEXT        IDD_SUBJECT_TEMPLATE,8,120,263,12,ES_AUTOHSCROLL
    CONTROL         "Generate &MIME headers",IDD_GENERATE_MIME,"Button",
                    BS_AUTOCHECKBOX | WS_TABSTOP,16,154,98,9
    CONTROL         "Enable MIME &usage suggestions",
                    IDD_MIME_USAGE_SUGGESTIONS,"Button",BS_AUTOCHECKBOX | 
                    WS_TABSTOP,135,154,124,9
    COMBOBOX        IDD_CONTENT_TYPE,16,181,111,60,CBS_DROPDOWN | CBS_SORT | 
                    WS_VSCROLL | WS_TABSTOP
    EDITTEXT        IDD_MIME_BOUNDARY,135,180,124,12,ES_AUTOHSCROLL | NOT 
                    WS_VISIBLE
    DEFPUSHBUTTON   "&OK",IDOK,75,205,50,14
    PUSHBUTTON      "&Cancel",ID_CANCEL,149,205,50,14
    LTEXT           "Default Encoding Type",-1,8,42,91,8
    LTEXT           "Article Split Length",-1,8,11,73,8
    LTEXT           "Custom Encoding Table",-1,8,70,90,8
    LTEXT           "MIME Boundary",-1,140,170,90,8,NOT WS_VISIBLE
    LTEXT           "Subject Line Template for Multi-part Compositions",-1,8,
                    101,237,8
    LTEXT           "(%s = original subject, %f = file name , %[0]p = part #, %t = total # parts)",
                    -1,8,110,263,10
    LTEXT           "Default Content Type",-1,16,171,122,8
    GROUPBOX        "MIME",-1,8,141,263,59
    CONTROL         "Start attachments in new article by default",
                    IDD_ATTACH_NEXT,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,
                    117,22,156,9
END

WINVNENCODE DIALOG DISCARDABLE  0, 0, 286, 123
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION
CAPTION "Encode To File"
FONT 8, "MS Sans Serif"
BEGIN
    EDITTEXT        IDD_FILENAME,8,30,191,12,ES_AUTOHSCROLL
    COMBOBOX        IDD_CODING_TYPE,8,59,110,60,CBS_DROPDOWNLIST | 
                    WS_VSCROLL | WS_TABSTOP
    CONTROL         "Make default",IDD_MAKE_DEFAULT_ENCODING,"Button",
                    BS_AUTOCHECKBOX | WS_TABSTOP,67,48,60,9
    EDITTEXT        IDD_CUSTOM_TABLE,8,96,263,12,ES_AUTOHSCROLL
    DEFPUSHBUTTON   "&OK...",IDOK,234,16,37,20
    PUSHBUTTON      "&Browse",ID_BROWSE,234,41,37,20
    PUSHBUTTON      "&Cancel",ID_CANCEL,234,66,37,20
    LTEXT           "Custom Encoding Table",-1,8,85,90,8
    LTEXT           "Encoding Type",-1,8,48,54,8
    LTEXT           "Please enter the name of the file to encode:",400,8,19,
                    173,9,NOT WS_GROUP
END

WINVNDECODEARTS DIALOG DISCARDABLE  26, 39, 262, 118
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Decode Selected Articles"
FONT 8, "MS Sans Serif"
BEGIN
    EDITTEXT        IDD_DECODE_PATH,17,28,182,12,ES_AUTOHSCROLL
    CONTROL         "&Execute decoded files",IDD_EXECUTE_DECODED,"Button",
                    BS_AUTOCHECKBOX | WS_TABSTOP,17,44,87,10
    CONTROL         "&Keep current article header visible",
                    IDD_KEEP_HEADER_VISIBLE,"Button",BS_AUTOCHECKBOX | 
                    WS_TABSTOP,17,55,131,10
    CONTROL         "&Include any open articles in decode",
                    IDD_INCLUDE_OPEN_ARTS,"Button",BS_AUTOCHECKBOX | 
                    WS_TABSTOP,17,66,131,10
    CONTROL         "&Auto-minimize decoding status windows",
                    IDD_MINIMIZE_CODING_STATUS,"Button",BS_AUTOCHECKBOX | 
                    WS_TABSTOP,17,77,169,9
    CONTROL         "&Verbose status windows",IDD_VERBOSE_STATUS,"Button",
                    BS_AUTOCHECKBOX | WS_TABSTOP,17,88,100,10
    CONTROL         "&Dumb decode",IDD_DUMB_DECODE,"Button",BS_AUTOCHECKBOX | 
                    WS_TABSTOP,17,99,57,10
    DEFPUSHBUTTON   "&OK...",IDOK,209,26,44,16
    PUSHBUTTON      "&Browse",ID_BROWSE,209,48,44,16
    PUSHBUTTON      "&Cancel",ID_CANCEL,209,70,44,16
    PUSHBUTTON      "Smart &Filer",IDD_SMART_FILER,209,92,44,16
    LTEXT           "Please enter the path in which to save the decoded files:",
                    400,18,15,195,8,NOT WS_GROUP
END

WINVNEXIT DIALOG DISCARDABLE  0, 0, 141, 78
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Exit WinVn"
FONT 8, "MS Sans Serif"
BEGIN
    CONTROL         "Save &Newsrc File",IDD_SAVE_NEWSRC,"Button",
                    BS_AUTOCHECKBOX | WS_TABSTOP,23,13,88,9
    CONTROL         "Save WinVN &Configuration",IDD_SAVE_CONFIG,"Button",
                    BS_AUTOCHECKBOX | WS_TABSTOP,23,29,101,9
    PUSHBUTTON      "&Exit",IDOK,19,53,46,14
    DEFPUSHBUTTON   "&Cancel",ID_CANCEL,77,53,46,14
    GROUPBOX        "",-1,15,3,112,42
END

ABOUTBOX DIALOG DISCARDABLE  25, 30, 189, 290
STYLE DS_MODALFRAME | WS_POPUP
FONT 8, "MS Sans Serif"
BEGIN
    CTEXT           "WinVN",IDD_VERSION_NUMBER,67,3,56,8
    CTEXT           "Public Domain Usenet News Reader",IDC_STATIC,26,12,137,
                    8
    DEFPUSHBUTTON   "OK",IDOK,74,263,32,14,WS_GROUP
    RTEXT           "Matt Bretherton",101,4,146,64,8,NOT WS_GROUP
    CTEXT           "Original Author:",107,57,63,75,8
    RTEXT           "Harvey Brydon",888,4,182,64,8,NOT WS_GROUP
    RTEXT           "John S. Cooper",109,4,120,64,8,NOT WS_GROUP
    RTEXT           "Michael Downs",103,4,209,64,8,NOT WS_GROUP
    RTEXT           "Jim Dumoulin",889,4,101,64,8,NOT WS_GROUP
    RTEXT           "Michael Finken",102,4,173,64,8,NOT WS_GROUP
    RTEXT           "Don Gardner",890,4,191,64,8,NOT WS_GROUP
    RTEXT           "Jody Glasser",891,4,155,64,8,NOT WS_GROUP
    RTEXT           "Masaki Ishido",892,4,200,64,8,NOT WS_GROUP
    RTEXT           "Conor Nolan",108,4,164,64,8,NOT WS_GROUP
    RTEXT           "Sam Rushing",105,4,110,64,8,NOT WS_GROUP
    LTEXT           "MBretherton@labyrinth.net.au",110,73,146,109,8,NOT 
                    WS_GROUP
    LTEXT           "brydon@tulsa.dowell.slb.com",925,73,182,109,8,NOT 
                    WS_GROUP
    LTEXT           "jcooper@planetz.com",920,73,119,109,9,NOT WS_GROUP
    LTEXT           "mdowns@eos.arc.nasa.gov",111,73,209,109,8,NOT WS_GROUP
    LTEXT           "dumoulin@titan.ksc.nasa.gov",112,73,101,109,8,NOT 
                    WS_GROUP
    LTEXT           "finken@conware.de",114,73,173,109,8,NOT WS_GROUP
    LTEXT           "Don.Gardner-1@ksc.nasa.gov",921,73,191,109,8,NOT 
                    WS_GROUP
    LTEXT           "jglas@tdycont.com",922,73,155,109,8,NOT WS_GROUP
    LTEXT           "ishidou@yhp.hp.com",923,73,200,109,8,NOT WS_GROUP
    LTEXT           "cnolan@tcd.ie",115,73,164,109,8,NOT WS_GROUP
    LTEXT           "rushing@nightmare.com",113,73,110,109,8,NOT WS_GROUP
    RTEXT           "Jim Martin",104,4,218,64,8,NOT WS_GROUP
    LTEXT           "jim@noc.rutgers.edu",116,73,218,109,8,NOT WS_GROUP
    RTEXT           "Roger Pearse",117,4,227,64,8,NOT WS_GROUP
    LTEXT           "pearse_w_r@bt-web.bt.co.uk",118,73,227,109,8,NOT 
                    WS_GROUP
    RTEXT           "Tom Menshik",119,4,236,64,8,NOT WS_GROUP
    LTEXT           "tmenshik@hpcvitlm.cv.hp.com",120,73,236,109,8,NOT 
                    WS_GROUP
    CTEXT           "Contributing Authors:",924,43,135,103,8,NOT WS_GROUP
    CTEXT           "Major Authors/System Integrators:",929,21,90,140,8,NOT 
                    WS_GROUP
    RTEXT           "Mark Riordan",125,4,73,64,8,NOT WS_GROUP
    LTEXT           "riordanm@supranet.com",126,73,73,109,8,NOT WS_GROUP
    ICON            "WINVN",IDC_STATIC,84,34,18,20
    LTEXT           "Coordinated by NASA - Kennedy Space Center",IDC_STATIC,
                    11,20,167,7
    RTEXT           "Vince Vielhaber",IDC_STATIC,5,245,62,10
    LTEXT           "vev@mail.msen.com",IDC_STATIC,73,245,99,9
END

WINVNLOGOPTS DIALOG DISCARDABLE  0, 0, 202, 115
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Logging Options"
FONT 8, "MS Sans Serif"
BEGIN
    EDITTEXT        IDD_POSTNAME,10,29,142,12
    CONTROL         "&Enable",IDD_POSTLOG,"Button",BS_AUTOCHECKBOX | 
                    WS_TABSTOP,116,18,35,9
    PUSHBUTTON      "&Browse",ID_BROWSEPOST,159,27,33,14
    EDITTEXT        IDD_MAILNAME,11,66,142,12
    CONTROL         "E&nable",IDD_MAILLOG,"Button",BS_AUTOCHECKBOX | 
                    WS_TABSTOP,116,55,35,9
    PUSHBUTTON      "B&rowse",ID_BROWSEMAIL,159,64,33,14
    DEFPUSHBUTTON   "&OK",IDOK,63,90,33,16
    PUSHBUTTON      "&Cancel",IDCANCEL,106,90,33,16
    LTEXT           "Posting Log File",-1,11,19,60,8
    LTEXT           "Mail Log File",-1,11,56,60,8
END

WINVNSMARTFILER DIALOG DISCARDABLE  0, 0, 245, 227
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Smart Filer Preferences"
FONT 8, "MS Sans Serif"
BEGIN
    EDITTEXT        IDD_MAX_NAME_LEN,78,7,21,12,ES_AUTOHSCROLL
    EDITTEXT        IDD_MAX_EXT_LEN,165,7,21,12,ES_AUTOHSCROLL
    EDITTEXT        IDD_SOURCE_EXT,11,55,72,12,ES_AUTOHSCROLL
    EDITTEXT        IDD_DOS_EXT,92,55,72,12,ES_AUTOHSCROLL
    CONTROL         "&Enable",IDD_ENABLE_CONVERSION,"Button",BS_AUTOCHECKBOX | 
                    WS_TABSTOP,186,55,39,10
    LISTBOX         IDD_EXT_MAP_LIST,11,71,162,75,LBS_USETABSTOPS | 
                    LBS_NOINTEGRALHEIGHT | LBS_DISABLENOSCROLL | WS_VSCROLL | 
                    WS_TABSTOP
    PUSHBUTTON      "&Add",IDD_ADD,186,84,38,14
    PUSHBUTTON      "&Delete",IDD_DELETE,186,100,38,14
    COMBOBOX        IDD_AVOID_DUPES,11,171,161,50,CBS_DROPDOWNLIST | 
                    WS_VSCROLL | WS_TABSTOP
    COMBOBOX        IDD_NAME_SHORTEN,11,199,161,50,CBS_DROPDOWNLIST | 
                    WS_VSCROLL | WS_TABSTOP
    DEFPUSHBUTTON   "&OK",IDOK,186,172,38,14
    PUSHBUTTON      "&Cancel",IDCANCEL,186,194,38,14
    LTEXT           "Source Extension ",IDC_STATIC,11,41,64,10
    LTEXT           "New Extension",IDC_STATIC,95,41,56,10
    LTEXT           "On Duplicate Name...",IDC_STATIC,11,159,104,8
    LTEXT           "On Name or Extension Too Long...",IDC_STATIC,11,188,130,
                    8
    RTEXT           "Max Name Length",IDC_STATIC,12,9,61,10
    RTEXT           "Max Ext Length",IDC_STATIC,104,9,57,10
    GROUPBOX        "Extension conversion",IDC_STATIC,2,27,235,127
    LTEXT           "-->>",IDC_STATIC,77,41,15,10
END

WINVNMAIL DIALOG DISCARDABLE  0, 0, 299, 163
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Mail Address List"
FONT 8, "MS Sans Serif"
BEGIN
    EDITTEXT        IDD_MAIL_DEST,12,21,199,12,ES_AUTOHSCROLL
    LISTBOX         IDD_MAIL_LIST,12,38,199,116,LBS_SORT | LBS_EXTENDEDSEL | 
                    WS_VSCROLL | WS_TABSTOP
    DEFPUSHBUTTON   "&OK",IDOK,227,20,59,14
    PUSHBUTTON      "&Cancel",IDCANCEL,227,40,59,14
    PUSHBUTTON      "&Add to list",IDD_ADD,227,86,59,14
    PUSHBUTTON      "&Delete from list",IDD_DELETE,227,106,59,14
    LTEXT           "Select address(es) by double-clicking in list or typing:",
                    -1,13,7,223,8
END

WINVNVERSIONLIST DIALOG DISCARDABLE  98, 23, 287, 146
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "WinVN Version Information"
FONT 8, "MS Sans Serif"
BEGIN
    CTEXT           " ",IDD_VERSION_NUMBER,42,7,205,8,NOT WS_GROUP
    LISTBOX         508,7,22,274,93,NOT LBS_NOTIFY | LBS_SORT | LBS_NOREDRAW | 
                    LBS_MULTIPLESEL | LBS_USETABSTOPS | WS_VSCROLL | 
                    WS_TABSTOP
    DEFPUSHBUTTON   "OK",IDOK,127,122,33,16
END

WINVNSELECTPATH DIALOG DISCARDABLE  0, 0, 209, 134
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Select Path"
FONT 8, "MS Sans Serif"
BEGIN
    LISTBOX         ID_DIRECTORYLIST,10,17,129,77,LBS_OWNERDRAWFIXED | 
                    LBS_HASSTRINGS | WS_VSCROLL | WS_TABSTOP
    COMBOBOX        ID_DRIVELIST,10,102,129,55,CBS_DROPDOWNLIST | 
                    CBS_OWNERDRAWFIXED | CBS_HASSTRINGS | WS_VSCROLL | 
                    WS_TABSTOP
    DEFPUSHBUTTON   "&OK",IDOK,146,16,50,14,WS_GROUP
    PUSHBUTTON      "&Cancel",IDCANCEL,146,35,50,14,WS_GROUP
    LTEXT           "&Directories:",-1,10,5,92,9
    LTEXT           "Dri&ves:",-1,10,91,92,9
    LISTBOX         ID_TEMPLIST,210,6,110,100,LBS_SORT | WS_VSCROLL
END

WINVNATTACH DIALOG DISCARDABLE  0, 0, 246, 120
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Attach"
FONT 8, "MS Sans Serif"
BEGIN
    EDITTEXT        IDD_FILENAME,7,26,176,12,ES_AUTOHSCROLL
    COMBOBOX        IDD_CODING_TYPE,7,53,110,60,CBS_DROPDOWNLIST | 
                    WS_VSCROLL | WS_TABSTOP
    CONTROL         "Make default",IDD_MAKE_DEFAULT_ENCODING,"Button",
                    BS_AUTOCHECKBOX | WS_TABSTOP,66,42,60,9
    COMBOBOX        IDD_CONTENT_TYPE,7,83,111,60,CBS_DROPDOWN | CBS_SORT | 
                    WS_VSCROLL | WS_TABSTOP
    CONTROL         "Make default",IDD_MAKE_DEFAULT_CONTENT,"Button",
                    BS_AUTOCHECKBOX | WS_TABSTOP,66,72,60,9
    DEFPUSHBUTTON   "&OK",IDOK,201,19,37,20
    PUSHBUTTON      "&Browse",ID_BROWSE,201,50,37,20
    PUSHBUTTON      "&Cancel",ID_CANCEL,201,81,37,20
    LTEXT           "Encoding Type",-1,7,43,53,8
    LTEXT           "Content Type",-1,7,73,53,8
    LTEXT           "Please enter the name of the file to attach:",400,7,15,
                    173,9,NOT WS_GROUP
    CONTROL         "Start this attachment in new article",IDD_ATTACH_NEXT,
                    "Button",BS_AUTOCHECKBOX | WS_TABSTOP,7,103,135,9
END

WINVNCONFIRMATIONS DIALOG DISCARDABLE  0, 0, 189, 96
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Confirmation Options"
FONT 8, "MS Sans Serif"
BEGIN
    CONTROL         "Confirm &batch send/close operations",
                    ID_CONFIG_CONFIRM_BATCH,"Button",BS_AUTOCHECKBOX | 
                    WS_TABSTOP,10,10,144,9
    CONTROL         "Confirm &disconnect",ID_CONFIRM_DISCONNECT,"Button",
                    BS_AUTOCHECKBOX | WS_TABSTOP,10,22,115,9
    CONTROL         "Confirm use of &reply-to when replying to message",
                    ID_CONFIG_CONFIRM_REPLY_TO,"Button",BS_AUTOCHECKBOX | 
                    WS_TABSTOP,10,34,175,9
    CONTROL         "Confirm &save on exit",ID_CONFIG_CONFIRM_EXIT,"Button",
                    BS_AUTOCHECKBOX | WS_TABSTOP,10,46,115,9
    DEFPUSHBUTTON   "&OK",IDOK,37,70,48,15
    PUSHBUTTON      "&Cancel",ID_CANCEL,104,70,48,15
END

WINVNCOMPOSEPREFS DIALOG DISCARDABLE  0, 0, 351, 193
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Composition Options"
FONT 8, "MS Sans Serif"
BEGIN
    CONTROL         "&Word wrap in composition body text",IDD_WORD_WRAP,
                    "Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,18,144,11
    CONTROL         "&Prefill 'Cc:' address in followup postings",
                    IDD_PREFILL_CC,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,10,
                    29,145,11
    CONTROL         "Show &from header",IDD_SHOW_FROM_HDR,"Button",
                    BS_AUTOCHECKBOX | WS_TABSTOP,11,54,114,11
    CONTROL         "Show &organization header",IDD_SHOW_ORG_HDR,"Button",
                    BS_AUTOCHECKBOX | WS_TABSTOP,11,65,114,11
    CONTROL         "Show &reply-to header",IDD_SHOW_REPLYTO_HDR,"Button",
                    BS_AUTOCHECKBOX | WS_TABSTOP,11,75,114,11
    CONTROL         "Show &keywords header",IDD_SHOW_KEYWORDS_HDR,"Button",
                    BS_AUTOCHECKBOX | WS_TABSTOP,11,86,114,11
    CONTROL         "Show &summary header (posting only)",
                    IDD_SHOW_SUMMARY_HDR,"Button",BS_AUTOCHECKBOX | 
                    WS_TABSTOP,11,97,145,11
    CONTROL         "Show &distribution header (posting only)",
                    IDD_SHOW_DISTRIBUTION_HDR,"Button",BS_AUTOCHECKBOX | 
                    WS_TABSTOP,11,109,142,11
    CONTROL         "&Enable",IDD_ENABLE_SIG,"Button",BS_AUTOCHECKBOX | 
                    WS_TABSTOP,10,153,49,10
    EDITTEXT        IDD_FILENAME,10,166,147,12,ES_AUTOHSCROLL
    PUSHBUTTON      "&Browse",ID_BROWSE,162,165,38,15
    EDITTEXT        IDD_FOLLOWUP_TEMPLATE,170,78,170,12,ES_AUTOHSCROLL
    EDITTEXT        IDD_REPLY_TEMPLATE,170,106,170,12,ES_AUTOHSCROLL
    DEFPUSHBUTTON   "&OK",IDOK,253,149,48,15
    PUSHBUTTON      "&Cancel",ID_CANCEL,253,168,48,15
    LTEXT           "%i = article ID, %d = date, %a = address, ",IDC_STATIC,
                    171,27,175,10
    LTEXT           "Follow-up 'says' template ",IDC_STATIC,171,65,149,10
    LTEXT           "Reply 'says' template ",IDC_STATIC,171,96,149,10
    GROUPBOX        "Says Templates",IDC_STATIC,162,10,185,126
    GROUPBOX        "Signature File",IDC_STATIC,3,140,206,45
    GROUPBOX        "",IDC_STATIC,4,48,153,88
    GROUPBOX        "",IDC_STATIC,5,10,152,35
    LTEXT           "%n = name, %% is literal percent",IDC_STATIC,170,36,175,
                    10
    CONTROL         "Show &followup-to header (posting only)",
                    IDD_SHOW_FOLLOWUPTO_HDR,"Button",BS_AUTOCHECKBOX | 
                    WS_TABSTOP,11,121,142,11
END

WINVNARTICLELISTPREFS DIALOG DISCARDABLE  0, 0, 166, 235
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Article List Options"
FONT 8, "MS Sans Serif"
BEGIN
    EDITTEXT        IDD_ART_THRESHOLD,73,20,33,12,ES_AUTOHSCROLL
    EDITTEXT        IDD_MIN_TO_READ,73,36,33,12,ES_AUTOHSCROLL
    CONTROL         "&Automatically retrieve latest unseen",
                    ID_CONFIG_SHOWUNREADONLY,"Button",BS_AUTOCHECKBOX | 
                    WS_TABSTOP,11,55,132,9
    CONTROL         "&New window for each group (article list)",
                    ID_CONFIG_NEW_WND_GROUP,"Button",BS_AUTOCHECKBOX | 
                    WS_TABSTOP,11,79,149,9
    CONTROL         "&Use shift/control-selections",ID_CONFIG_MULTI_SELECT,
                    "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,91,122,9
    CONTROL         "&Full 'from' name in article list",
                    ID_CONFIG_FULLNAMEFROM,"Button",BS_AUTOCHECKBOX | 
                    WS_TABSTOP,11,103,134,9
    CONTROL         "&Compute threads in article list",ID_CONFIG_THREADS,
                    "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,115,132,9
    CONTROL         "&Show full subject in threads",
                    ID_CONFIG_THREADS_FULL_SUBJECT,"Button",BS_AUTOCHECKBOX | 
                    WS_TABSTOP,11,127,118,9
    CONTROL         "S&ave Newsrc on Closing Group",
                    ID_CONFIG_SAVE_NEWSRC_ON_CLOSE,"Button",BS_AUTOCHECKBOX | 
                    WS_TABSTOP,11,138,118,9
    CONTROL         "&Track Seen Subscribed Crosspostings",
                    ID_CONFIG_CROSSPOST,"Button",BS_AUTOCHECKBOX | 
                    WS_TABSTOP,11,149,134,9
    CONTROL         "T&rack Seen UnSubscribed Crosspostings",
                    ID_CONFIG_CROSSPOST_UNSUB,"Button",BS_AUTOCHECKBOX | 
                    WS_TABSTOP,11,160,145,9
    EDITTEXT        ID_THREAD_DEPTH_INDICATOR,89,190,20,12,ES_AUTOHSCROLL
    DEFPUSHBUTTON   "&OK",IDOK,28,209,38,18
    PUSHBUTTON      "&Cancel",ID_CANCEL,88,209,38,18
    RTEXT           "Ask if more than",105,17,23,53,8,NOT WS_GROUP
    GROUPBOX        "Article list retrieval",104,7,7,143,65,WS_GROUP
    LTEXT           "articles",103,109,23,25,8,NOT WS_GROUP
    RTEXT           "Fetch at least",106,17,39,53,8,NOT WS_GROUP
    LTEXT           "articles",107,109,39,25,8,NOT WS_GROUP
    RTEXT           "Thread depth indicator:",IDC_STATIC,6,192,80,8
    CONTROL         "&Enable Article Actions / Kill File",ID_ENABLE_KILLFILE,
                    "Button",BS_AUTOCHECKBOX | WS_TABSTOP,11,172,145,9
END

WINVNGROUPLISTPREFS DIALOG DISCARDABLE  0, 0, 161, 108
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Group List Options"
FONT 8, "MS Sans Serif"
BEGIN
    CONTROL         "Yes",ID_DOLIST_YES,"Button",BS_AUTORADIOBUTTON | 
                    WS_TABSTOP,33,20,26,12
    CONTROL         "No",ID_DOLIST_BASE,"Button",BS_AUTORADIOBUTTON | 
                    WS_TABSTOP,66,20,21,12
    CONTROL         "Ask",ID_DOLIST_ASK,"Button",BS_AUTORADIOBUTTON | 
                    WS_TABSTOP,94,20,25,12
    GROUPBOX        "Retrieve group list on connect?",IDC_STATIC,18,7,127,30,
                    WS_TABSTOP
    CONTROL         "&Use shift/control-selections",ID_CONFIG_MULTI_SELECT,
                    "Button",BS_AUTOCHECKBOX | WS_TABSTOP,24,44,122,9
    CONTROL         "&Show unsubscribed groups",ID_CONFIG_SHOWUNSUB,"Button",
                    BS_AUTOCHECKBOX | WS_TABSTOP,24,57,113,9
    DEFPUSHBUTTON   "&OK",IDOK,32,79,38,18
    PUSHBUTTON      "&Cancel",ID_CANCEL,91,79,38,18
END

WINVNARTICLEPREFS DIALOG DISCARDABLE  0, 0, 167, 142
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Article Options"
FONT 8, "MS Sans Serif"
BEGIN
    CONTROL         "&Wrap article text to",ID_WRAP_INCOMING_TEXT,"Button",
                    BS_AUTOCHECKBOX | WS_TABSTOP,17,22,76,9
    EDITTEXT        ID_WRAP_INCOMING_TEXT_LIMIT,94,20,21,12,ES_AUTOHSCROLL
    CONTROL         "&Trim headers during article retrieval",ID_TRIM_HEADERS,
                    "Button",BS_AUTOCHECKBOX | WS_TABSTOP,17,35,130,9
    CONTROL         "&New window for each article",ID_CONFIG_NEW_WND_ARTICLE,
                    "Button",BS_AUTOCHECKBOX | WS_TABSTOP,16,61,118,9
    CONTROL         "&Scroll past headers after retrieval",
                    ID_SCROLL_PAST_HEADERS,"Button",BS_AUTOCHECKBOX | 
                    WS_TABSTOP,16,74,133,9
    CONTROL         "&Italicize quotes in article window",
                    ID_QUOTES_IN_ITALICS,"Button",BS_AUTOCHECKBOX | 
                    WS_TABSTOP,16,86,125,9
    DEFPUSHBUTTON   "&OK",IDOK,35,110,38,18
    PUSHBUTTON      "&Cancel",ID_CANCEL,94,110,38,18
    LTEXT           "chars",IDC_STATIC,119,23,28,9
    GROUPBOX        "Article retrieval",IDC_STATIC,12,8,137,47
END

WINVNCODINGPREFS DIALOG DISCARDABLE  0, 0, 181, 146
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Decode Preferences"
FONT 8, "MS Sans Serif"
BEGIN
    CONTROL         "&Block coding status window always on top",
                    ID_STATUSALWAYSONTOP,"Button",BS_AUTOCHECKBOX | 
                    WS_TABSTOP,17,12,160,9
    CONTROL         "&Verbose decoding status windows",IDD_VERBOSE_STATUS,
                    "Button",BS_AUTOCHECKBOX | WS_TABSTOP,17,24,150,9
    CONTROL         "&Auto-minimize decoding status windows",
                    IDD_MINIMIZE_CODING_STATUS,"Button",BS_AUTOCHECKBOX | 
                    WS_TABSTOP,17,36,148,9
    CONTROL         "&Execute decoded files",IDD_EXECUTE_DECODED,"Button",
                    BS_AUTOCHECKBOX | WS_TABSTOP,17,53,87,10
    CONTROL         "&Keep current article header visible",
                    IDD_KEEP_HEADER_VISIBLE,"Button",BS_AUTOCHECKBOX | 
                    WS_TABSTOP,17,65,131,10
    CONTROL         "&Include open articles in decodes",
                    IDD_INCLUDE_OPEN_ARTS,"Button",BS_AUTOCHECKBOX | 
                    WS_TABSTOP,17,77,131,10
    CONTROL         "Use &dumb decode",IDD_DUMB_DECODE,"Button",
                    BS_AUTOCHECKBOX | WS_TABSTOP,17,89,97,10
    DEFPUSHBUTTON   "&OK",IDOK,36,115,38,18
    PUSHBUTTON      "&Cancel",ID_CANCEL,95,115,38,18
END

WINVNEXECUTE DIALOG DISCARDABLE  11, 16, 214, 194
STYLE DS_MODALFRAME | WS_POPUP | WS_CAPTION
CAPTION "Uniform Resource Locator (URL) Execute Setup"
FONT 8, "MS Sans Serif"
BEGIN
    EDITTEXT        ID_CONFIG_URL_HTTP,84,8,122,12,ES_AUTOHSCROLL
    EDITTEXT        ID_CONFIG_URL_FTP,84,22,122,12,ES_AUTOHSCROLL
    EDITTEXT        ID_CONFIG_URL_GOPHER,84,36,122,12,ES_AUTOHSCROLL
    EDITTEXT        ID_CONFIG_URL_WAIS,84,50,122,12,ES_AUTOHSCROLL
    DEFPUSHBUTTON   "&OK",IDOK,53,173,43,15
    PUSHBUTTON      "&Cancel",ID_CANCEL,113,173,38,15
    RTEXT           "WWW Browser",IDC_STATIC,15,11,68,8,NOT WS_GROUP
    RTEXT           "FTP Browser",IDC_STATIC,12,24,68,8,NOT WS_GROUP
    RTEXT           "WAIS Browser",IDC_STATIC,12,52,68,8,NOT WS_GROUP
    RTEXT           "Gopher Browser",IDC_STATIC,19,38,61,8,NOT WS_GROUP
    LTEXT           "Enter the command line necessary to start an application.  Environment variables (seperated by %'s) can be used.   Other expansions are also supported:",
                    IDC_STATIC,9,67,200,28
    LTEXT           "%u  Expands to the URL that was clicked \n %p  Expands to the protocol used \n %h  Expands to the hostname specified in the URL \n%f   Expands to the filename specified in the URL",
                    IDC_STATIC,29,95,175,32
    LTEXT           "WWW   %windir%\\mosaic %u \n FTP      c:\\internet\\ws_ftp %h:%f",
                    IDC_STATIC,56,142,113,19
    GROUPBOX        "Example",IDC_STATIC,47,130,126,37
END

ACTIONDLG DIALOG DISCARDABLE  0, 0, 241, 194
STYLE DS_MODALFRAME | WS_POPUP | WS_VISIBLE | WS_CAPTION | WS_SYSMENU
CAPTION "Article Actions"
FONT 8, "MS Sans Serif"
BEGIN
    DEFPUSHBUTTON   "OK",IDOK,180,15,50,14
    PUSHBUTTON      "Cancel",IDCANCEL,180,35,50,14,NOT WS_TABSTOP
    GROUPBOX        "Apply to articles in:",IDC_STATIC,10,10,160,40
    CONTROL         "All newsgroups",IDC_AA_RADIO_GLOBAL,"Button",
                    BS_AUTORADIOBUTTON | WS_GROUP,15,20,150,10
    CONTROL         "(apply to this newsgroup only)",IDC_AA_RADIO_GROUP,
                    "Button",BS_AUTORADIOBUTTON,15,35,150,10
    GROUPBOX        "Article Filter",IDC_STATIC,5,60,230,80,WS_GROUP
    LTEXT           "Header:",IDC_STATIC,10,80,30,8
    COMBOBOX        IDC_AA_HEADER,45,80,100,80,CBS_DROPDOWNLIST | CBS_SORT | 
                    WS_VSCROLL | WS_TABSTOP
    COMBOBOX        IDC_AA_HDRFILTER,45,100,100,65,CBS_DROPDOWNLIST | 
                    CBS_SORT | WS_VSCROLL | WS_TABSTOP
    EDITTEXT        IDC_AA_TEXT,10,120,220,13,ES_AUTOHSCROLL
    PUSHBUTTON      "New",IDC_AA_NEW,180,75,50,14
    PUSHBUTTON      "Delete",IDC_AA_DELETE,180,95,50,14
    LTEXT           "Action:",IDC_STATIC,10,150,30,8
    COMBOBOX        IDC_AA_ACTION,46,150,110,50,CBS_DROPDOWNLIST | CBS_SORT | 
                    WS_VSCROLL | WS_TABSTOP
    PUSHBUTTON      "Edit Prev",IDC_AA_EDIT_PREV,5,175,50,14
    PUSHBUTTON      "Edit Next",IDC_AA_EDIT_NEXT,60,175,50,14
    PUSHBUTTON      "Move Prev",IDC_AA_MOVE_PREV,130,175,50,14
    PUSHBUTTON      "Move Next",IDC_AA_MOVE_NEXT,185,175,50,14
END


/////////////////////////////////////////////////////////////////////////////
//
// Bitmap
//

IDB_ARTTOOLBAR          BITMAP  MOVEABLE PURE   "ICOBMP/ART_TBAR.BMP"
IDB_TOOLBAR             BITMAP  MOVEABLE PURE   "ICOBMP/WVTOOLBR.BMP"
IDB_VIEWTOOLBAR         BITMAP  MOVEABLE PURE   "ICOBMP/VIEWTBAR.BMP"
IDB_DRIVEFLOPPY         BITMAP  MOVEABLE PURE   "ICOBMP/FLOPPY.BMP"
IDB_DRIVEHARD           BITMAP  MOVEABLE PURE   "ICOBMP/HARDDRV.BMP"
IDB_DRIVENETWORK        BITMAP  MOVEABLE PURE   "ICOBMP/NETDRIVE.BMP"
IDB_DRIVECDROM          BITMAP  MOVEABLE PURE   "ICOBMP/CDROM.BMP"
IDB_DRIVERAM            BITMAP  MOVEABLE PURE   "ICOBMP/RAMDRIVE.BMP"
IDB_FOLDERCLOSED        BITMAP  MOVEABLE PURE   "ICOBMP/FLDCLOSE.BMP"
IDB_FOLDEROPEN          BITMAP  MOVEABLE PURE   "ICOBMP/FLDOPEN.BMP"
IDB_FOLDEROPENSELECT    BITMAP  MOVEABLE PURE   "ICOBMP/FLDSEL.BMP"

#ifdef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// TEXTINCLUDE
//

1 TEXTINCLUDE DISCARDABLE 
BEGIN
    "resource.h\0"
END

2 TEXTINCLUDE DISCARDABLE 
BEGIN
    "#define APSTUDIO_HIDDEN_SYMBOLS\r\n"
    "#include <windows.h>\r\n"
    "#undef APSTUDIO_HIDDEN_SYMBOLS\r\n"
    "#include ""winvn.h""\r\n"
    "#include ""winsock.h""\r\n"
    "#include ""wvstates.h""\r\n"
    "#include ""gensock/gensock.h""\r\n"
    "#define RCSVERSION ""$Id: winvn.rc 1.79 1995/11/09 00:24:11 dumoulin Exp $""\r\n"
    "\0"
END

3 TEXTINCLUDE DISCARDABLE 
BEGIN
    "\r\n"
    "\0"
END

/////////////////////////////////////////////////////////////////////////////
#endif    // APSTUDIO_INVOKED


/////////////////////////////////////////////////////////////////////////////
//
// String Table
//

STRINGTABLE DISCARDABLE 
BEGIN
    IDS_FILTERSTRING        "All Files|*.*|Documents|*.wri;*.doc;*.rtf|Images|*.jpg;*.gif;*.tif;*.bmp|Video|*.avi;*.mpg|Sounds|*.wav;*.mid;*.mod;*.au|Text Files|*.txt|Archives|*.zip;*.lzh;*.arj;*.arc|C Code Files|*.c;*.h;*.def;*.mak;*.pjt;*.rc;*.ide|"
    IDM_COPY                "Copy selected text to clipboard"
END

STRINGTABLE DISCARDABLE 
BEGIN
    ERR_CANT_MALLOC         "Invalid argument"
    ERR_SENDING_DATA        "Error sending data"
    ERR_INITIALIZING        "Error initializing"
    ERR_VER_NOT_SUPPORTED   "Socket library version not supported"
    ERR_EINVAL              "Invalid Argument"
    ERR_SYS_NOT_READY       "System not ready"
    ERR_CANT_RESOLVE_HOSTNAME "Can't resolve hostname"
    ERR_CANT_GET_SOCKET     "Can't get socket"
    ERR_READING_SOCKET      "Error reading socket"
    ERR_NOT_A_SOCKET        "Not a socket"
    ERR_BUSY                "socket is busy"
    ERR_CLOSING             "error closing socket"
    WAIT_A_BIT              "wait a bit"
    ERR_CANT_RESOLVE_SERVICE "can't resolve service"
    ERR_CANT_CONNECT        "can't connect"
END

STRINGTABLE DISCARDABLE 
BEGIN
    ERR_NOT_CONNECTED       "not connected"
    ERR_CONNECTION_REFUSED  "connection refused"
END

STRINGTABLE DISCARDABLE 
BEGIN
    IDM_DECODE_FILE         "Decode a file"
    IDM_ENCODE_FILE         "Encode a file"
    IDM_SUBSCRIBE           "Subscribe to the selected groups"
    IDM_UNSUBSCRIBE         "Unsubscribe to the selected groups"
    IDM_RESET               "Reset server protocol"
    IDM_CONNECT             "Connect to news server"
    IDM_DISCONNECT          "Disconnect from news server"
    IDM_RECONNECT           "Disconnect, then reconnect to news server"
END

STRINGTABLE DISCARDABLE 
BEGIN
    IDM_SAVE_WINDOW         "Save window positions"
    IDM_SAVE_CONFIG         "Save configuration"
    IDB_TOGGLE_CONNECT      "Toggle connection to news server"
    IDB_TOGGLE_VIEW_UNSUB   "View/hide unsubscribed groups"
    IDB_FASTEXIT            "Save configuration and exit WinVN"
    IDM_HELP                "Display help"
END

STRINGTABLE DISCARDABLE 
BEGIN
    ST_CHECK_AUTHINFO_USERNAME "Checking authorization username..."
    ST_CHECK_AUTHINFO_PASSWORD "Checking authorization password..."
    ST_END_AUTHINFO         "Authorization received..."
    IDM_VIEW_ACTION         "Apply selection filters to articles"
END

STRINGTABLE DISCARDABLE 
BEGIN
    IDM_SEARCH              "Search for text"
    IDM_SEARCH_NEXT         "Find next occurrence of text"
    IDM_FIND_NEXT_UNSEEN    "View next unseen article"
    IDM_NEXT_SAME_SUBJ      "View next article with the same subject"
    IDM_MAIL                "Create a mail message"
    IDM_LOGOUT              "Logout from mail server"
    IDM_ROT13               "View ROT13"
END

STRINGTABLE DISCARDABLE 
BEGIN
    IDM_UPDATE              "Update article header list"
    IDM_FORWARD             "Forward article via mail"
    IDM_DISPLAY_SEEN_ARTS   "Display/hide articles that have been previously seen"
    IDM_DISPLAY_KILLED_ARTS "Display/hide articles that have been marked 'seen'"
    IDM_SORT_THREADSUB      "Sort article list by threads and subject"
    IDM_SORT_DATE           "Sort article list by date"
    IDM_SORT_SUBJECT        "Sort article list by subject"
    IDM_SORT_LINES          "Sort article list by number of lines"
    IDM_SORT_THREADS        "Sort article list by thread"
END

STRINGTABLE DISCARDABLE 
BEGIN
    ID_ABOUT                "Display the about dialog box"
    IDM_UNSEL_ALL           "Deselect all groups"
    IDM_EXIT                "Exit WinVN"
    IDM_QUIT                "Quit without saving NewsRC or WINVN.INI File"
    IDM_GROUP_TOP           "Move selected groups to top of list"
    IDM_CONFIG_LOG          "Configure logging options"
    IDM_COMMOPTIONS         "Configure communication options"
    IDM_CONFIG_PERSONAL     "Configure personal information"
END

STRINGTABLE DISCARDABLE 
BEGIN
    IDM_POST                "Create a new article"
    IDM_COMPOSE_PREFS       "Configure composition options"
    IDM_ATTACH_PREFS        "Configure attachment options"
    IDM_FIND                "Search for text"
    IDM_FIND_NEXT_SAME      "Find next occurrence of text"
END

STRINGTABLE DISCARDABLE 
BEGIN
    IDM_WINDOW_CASCADE      "Arrange windows so that they overlap"
    IDM_CLOSE_ALL_GROUP     "Close all group windows"
    IDM_CLOSE_ALL_ARTICLE   "Close all article windows"
    IDM_CLOSE_ALL_COMPOSE   "Close all composition windows"
    IDM_CLOSE_ALL_STATUS    "Close all status windows"
    IDM_CLOSE_ALL           "Close all open WinVN windows"
    IDM_MINIMIZE_ALL_GROUP  "Minimize all group windows"
    IDM_MINIMIZE_ALL_ARTICLE "Minimize all article windows"
    IDM_MINIMIZE_ALL_COMPOSE "Minimize all composition windows"
    IDM_MINIMIZE_ALL_STATUS "Minimize all status windows"
    IDM_MINIMIZE_ALL        "Minimize all open WinVN windows"
    IDM_RESTORE_ALL         "Restore the window to normal size"
END

STRINGTABLE DISCARDABLE 
BEGIN
    IDM_SEND_ALL_POST       "Send all pending posts"
    IDM_SEND_ALL_MAIL       "Send all pending mail"
END

STRINGTABLE DISCARDABLE 
BEGIN
    IDM_SAVE_NEWSRC         "Save Newsgroup/Article List information"
    IDM_CONFIG_SMART_FILER  "Configure smart filer options"
    IDM_CONFIG_CONFIRMATIONS "Configure confirmations"
    IDM_CONFIG_GROUPLIST    "Configure group list options"
    IDM_CONFIG_ARTLIST      "Configure article list options"
    IDM_CONFIG_ARTICLE      "Configure article options"
    IDM_CONFIG_CODING       "Configure decoding options"
    IDM_CONFIG_EXECUTE      "Configure Universal Resource Relocator (URL) execute options"
    IDM_SORT_SELECTED       "Sort all selected groups in alphabetical order"
END

STRINGTABLE DISCARDABLE 
BEGIN
    IDM_FONT_WINVNSYSTEM    "Set WinVN system font"
    IDM_FONT_COMPOSITION    "Set font used in composition text"
    IDM_FONT_GROUPLIST      "Set font used in list windows"
    IDM_FONT_ARTICLE_TEXT   "Set font used in article windows"
    IDM_FONT_PRINT_TEXT     "Set font used for printing"
    IDM_FONT_STATUS_TEXT    "Set font used in status windows"
    IDM_COLOR_UNSUBSCRIBED  "Set text color for unsubscribed groups"
    IDM_COLOR_SUBSCRIBED    "Set text color for subscribed groups"
END

STRINGTABLE DISCARDABLE 
BEGIN
    IDM_COLOR_UNSEEN        "Set text color for unseen articles"
    IDM_COLOR_SEEN          "Set text color for seen articles"
    IDM_COLOR_KILLED        "Set text color for marked seen (""killed"") articles"
    IDM_COLOR_LIST_BACKGROUND "Set background color in list windows"
    IDM_COLOR_ARTICLE_BACKGROUND "Set background color in article windows"
    IDM_COLOR_STATUS_BACKGROUND "Set background color in status windows"
    IDM_COLOR_ARTICLE_TEXT  "Set text color for article text"
    IDM_COLOR_STATUS_TEXT   "Set text color for status windows"
    IDM_TRUE_INVERSE_SELECTIONS "True inverse or always black selections"
    IDM_USE_SPLASH          "Show splash screen on startup"
    IDM_SHOW_VERSION        "Display version dialog"
END

STRINGTABLE DISCARDABLE 
BEGIN
    IDM_SORT_ARTNUM         "Sort article list by article number"
    IDM_SORT_FROM           "Sort article list by author"
    IDM_SELECT_ALL          "Select all articles"
    IDM_MARK_READ_ARTICLES  "Select all articles you have seen or marked 'seen'"
    IDM_MARK_UNREAD_ARTICLES 
                            "Select all articles you have not seen or marked 'unseen'"
    IDM_SELECT_MATCH        "Select all articles containing string in the subject"
    IDM_DESELECT_ALL        "Deselect all articles"
    IDM_UNMARK_READ_ARTICLES 
                            "Deselect all articles you have seen or marked 'seen'"
    IDM_UNMARK_UNREAD_ARTICLES 
                            "Deselect all articles you have not seen or marked 'unseen'"
    IDM_DESELECT_MATCH      "Deselect all articles containing a string in the subject"
    IDM_SAVE_SELECTED       "Save selected articles"
    IDM_DECODE_SELECTED     "Decode selected articles"
END

STRINGTABLE DISCARDABLE 
BEGIN
    IDM_READ_SELECTED       "Read Selected Articles"
    IDM_MARK_SELECTED       "Mark selected articles as 'seen'"
    IDM_UNMARK_SELECTED     "Mark selected articles as 'unseen'"
END

STRINGTABLE DISCARDABLE 
BEGIN
    IDM_MARK_ALL            "Mark all articles as 'seen', and close window"
END

STRINGTABLE DISCARDABLE 
BEGIN
    IDV_EXIT                "Close window"
END

STRINGTABLE DISCARDABLE 
BEGIN
    IDM_NEXT_ARTICLE        "View next article"
    IDM_PREV_ARTICLE        "View previous article"
    IDM_DECODE_ARTICLE      "Decode article in window"
    IDM_ALWAYSONTOP         "Keep window on top"
    IDM_CANCELART           "Cancel the current article"
    IDM_SAVE                "Save article, appended to previous save"
    IDM_SAVEAS              "Save article to a new file"
    IDM_PRINT               "Print article"
    IDM_PRINT_SETUP         "Printer setup"
END

STRINGTABLE DISCARDABLE 
BEGIN
    ST_NONE                 "No connection to host"
    ST_ESTABLISH_COMM       "Establishing communications..."
    ST_GROUP_RESP           "Retrieving article numbers..."
    ST_XHDR_SUBJECT_START   "Retrieving article subjects"
    ST_XHDR_SUBJECT_DATA    "Retrieving article subjects..."
    ST_IN_GROUP             "State: ST_IN_GROUP"
    ST_ARTICLE_RESP         "Retrieving article text..."
    ST_REC_ARTICLE          "Retrieving article text..."
    ST_POST_WAIT_PERMISSION "Verifying permission to post..."
    ST_POST_WAIT_END        "Waiting for news server acknowledgement..."
    ST_GROUP_REJOIN         "Switching groups..."
    ST_LIST_RESP            "Retrieving list of groups..."
    ST_LIST_GROUPLINE       "Retrieving list of groups..."
END

STRINGTABLE DISCARDABLE 
BEGIN

    ST_XHDR_NEWSGROUPS_START "Retrieving article newsgroups..."
    ST_XHDR_NEWSGROUPS_DATA  "Retrieving article newsgroups..."
    ST_XHDR_FROM_START      "Retrieving article authors..."
    ST_XHDR_FROM_DATA       "Retrieving article authors..."
    ST_XHDR_SUBJ_START      "Retrieving article subjects..."
    ST_XHDR_SUBJ_DATA       "Retrieving article subjects..."
    ST_XHDR_REF_START       "Retrieving article references"
    ST_XHDR_REF_DATA        "Retrieving article references..."
    ST_XHDR_MID_START       "Retrieving article message ids"
    ST_XHDR_MID_DATA        "Retrieving article message ids..."
    ST_XHDR_DATE_START      "Retrieving article dates..."
    ST_XHDR_DATE_DATA       "Retrieving article dates..."
    ST_XHDR_LINES_START     "Retrieving article line count"
    ST_XHDR_LINES_DATA      "Retrieving article line count..."
    ST_XOVER_START          "Retrieving article XOVER data..."
    ST_XOVER_DATA           "Retrieving article XOVER data..."
END

STRINGTABLE DISCARDABLE 
BEGIN
    ST_XOVER_CHECK          "Checking for XOVER support..."
    ST_REC_ARTICLE_HEADER   "Receiving article text..."
END

STRINGTABLE DISCARDABLE 
BEGIN
    ST_CLOSED_COMM          "Communication closed by host"
END

STRINGTABLE DISCARDABLE 
BEGIN
    IDM_NETWORK_MENU        "Network operations and exiting"
    IDM_GROUP_MENU          "Find, subscribe to,  or move groups"
    IDM_UTILITIES_MENU      "Post, mail, and encode/decode operations"
END

STRINGTABLE DISCARDABLE 
BEGIN
    IDM_BATCH_MENU          "Batch send posts and mail"
    IDM_CONFIG_MENU         "Configuration options"
    IDM_FONT_MENU           "Select fonts"
    IDM_COLOR_MENU          "Select colors"
    IDM_WINDOW_MENU         "Window arrangement"
    IDM_CLOSE_MENU          "Window close operations"
    IDM_MINIMIZE_MENU       "Window minimize operations"
    IDM_HELP_MENU           "Help commands"
    IDM_ARTICLE_MENU        "Article operations"
    IDM_SORT_MENU           "Change header sort order"
    IDM_SEARCH_MENU         "Search operations"
    IDM_FILE_MENU           "Save, print or decode article"
    IDM_EDIT_MENU           "Edit operations"
    IDM_ARTSEARCH_MENU      "Search operations"
    IDM_VIEW_MENU           "View operations"
    IDM_RESPOND_MENU        "Respond to article"
END

STRINGTABLE DISCARDABLE 
BEGIN
    61456                   "Change the window position"
END

STRINGTABLE DISCARDABLE 
BEGIN
    61440                   "Change the window size"
END

STRINGTABLE DISCARDABLE 
BEGIN
    61472                   "Reduce the window to an icon"
END

STRINGTABLE DISCARDABLE 
BEGIN
    61488                   "Enlarge the window to full size"
END

STRINGTABLE DISCARDABLE 
BEGIN
    61536                   "Close this window"
END

STRINGTABLE DISCARDABLE 
BEGIN
    61744                   "Switch to another task"
END


#ifndef APSTUDIO_INVOKED
/////////////////////////////////////////////////////////////////////////////
//
// Generated from the TEXTINCLUDE 3 resource.
//


/////////////////////////////////////////////////////////////////////////////
#endif    // not APSTUDIO_INVOKED


--=====================_830668167==_
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: attachment; filename="WVCLASS.H"

/*
 * $Id: wvclass.h 1.2 1995/11/07 22:52:03 brydon Exp $
 */

/*
 *
 *  WinVN C++ class definitions
 *
 */

#ifndef WVCLASS_H
#define WVCLASS_H

// Action/Killfile constants
#define AA_NOACTION_MASK               1
#define AA_LT_MASK                     2
#define AA_EQ_MASK                     3
#define AA_GT_MASK                     4
#define AA_IS_MASK                     5
#define AA_CONTAINS_MASK               6
#define AA_SELECT_MASK            0x1000
#define AA_MODULO                 0x0010

#define NO_ACTION                      1
#define MARK_SEEN_ART_LINES_BASE       1 * AA_MODULO  // 0x10/16
#define MARK_SEEN_ART_LINES_LT          MARK_SEEN_ART_LINES_BASE + AA_LT_MASK
#define MARK_SEEN_ART_LINES_EQ          MARK_SEEN_ART_LINES_BASE + AA_EQ_MASK
#define MARK_SEEN_ART_LINES_GT          MARK_SEEN_ART_LINES_BASE + AA_GT_MASK
#define MARK_SEEN_ART_FROM_BASE        2 * AA_MODULO  // 0x20/32
#define MARK_SEEN_ART_FROM_IS           MARK_SEEN_ART_FROM_BASE + AA_IS_MASK
#define MARK_SEEN_ART_FROM_CONTAINS     MARK_SEEN_ART_FROM_BASE + AA_CONTAINS_MASK
#define MARK_SEEN_ART_EMAIL_BASE       3 * AA_MODULO  // 0x30/48
#define MARK_SEEN_ART_EMAIL_IS          MARK_SEEN_ART_EMAIL_BASE + AA_IS_MASK
#define MARK_SEEN_ART_EMAIL_CONTAINS    MARK_SEEN_ART_EMAIL_BASE + AA_CONTAINS_MASK
#define MARK_SEEN_ART_SUBJ_BASE        4 * AA_MODULO  // 0x40/64
#define MARK_SEEN_ART_SUBJ_IS           MARK_SEEN_ART_SUBJ_BASE + AA_IS_MASK
#define MARK_SEEN_ART_SUBJ_CONTAINS     MARK_SEEN_ART_SUBJ_BASE + AA_CONTAINS_MASK
#define MARK_SEEN_ART_MSGID_BASE       5 * AA_MODULO  // 0x50/80
#define MARK_SEEN_ART_MSGID_IS          MARK_SEEN_ART_MSGID_BASE + AA_IS_MASK
#define MARK_SEEN_ART_MSGID_CONTAINS    MARK_SEEN_ART_MSGID_BASE + AA_CONTAINS_MASK
#define MARK_SEEN_ART_REF_BASE         6 * AA_MODULO  // 0x60/96
//#define MARK_SEEN_ART_REF_IS            MARK_SEEN_ART_REF_BASE + AA_IS_MASK
#define MARK_SEEN_ART_REF_CONTAINS      MARK_SEEN_ART_REF_BASE + AA_CONTAINS_MASK
#define MARK_SEEN_NGROUP_BASE          7 * AA_MODULO  // 0x70/112
//#define MARK_SEEN_NGROUP_IS             MARK_SEEN_NGROUP_BASE + AA_IS_MASK
#define MARK_SEEN_NGROUP_CONTAINS       MARK_SEEN_NGROUP_BASE + AA_CONTAINS_MASK
#define SELECT_ART_LINES_BASE           AA_SELECT_MASK + MARK_SEEN_ART_LINES_BASE
#define SELECT_ART_LINES_LT             AA_SELECT_MASK + MARK_SEEN_ART_LINES_LT
#define SELECT_ART_LINES_EQ             AA_SELECT_MASK + MARK_SEEN_ART_LINES_EQ
#define SELECT_ART_LINES_GT             AA_SELECT_MASK + MARK_SEEN_ART_LINES_GT
#define SELECT_ART_FROM_BASE            AA_SELECT_MASK + MARK_SEEN_ART_FROM_BASE
#define SELECT_ART_FROM_IS              AA_SELECT_MASK + MARK_SEEN_ART_FROM_IS
#define SELECT_ART_FROM_CONTAINS        AA_SELECT_MASK + MARK_SEEN_ART_FROM_CONTAINS
#define SELECT_ART_EMAIL_BASE           AA_SELECT_MASK + MARK_SEEN_ART_EMAIL_BASE
#define SELECT_ART_EMAIL_IS             AA_SELECT_MASK + MARK_SEEN_ART_EMAIL_IS
#define SELECT_ART_EMAIL_CONTAINS       AA_SELECT_MASK + MARK_SEEN_ART_EMAIL_CONTAINS
#define SELECT_ART_SUBJ_BASE            AA_SELECT_MASK + MARK_SEEN_ART_SUBJ_BASE
#define SELECT_ART_SUBJ_IS              AA_SELECT_MASK + MARK_SEEN_ART_SUBJ_IS
#define SELECT_ART_SUBJ_CONTAINS        AA_SELECT_MASK + MARK_SEEN_ART_SUBJ_CONTAINS
#define SELECT_ART_MSGID_BASE           AA_SELECT_MASK + MARK_SEEN_ART_MSGID_BASE
#define SELECT_ART_MSGID_IS             AA_SELECT_MASK + MARK_SEEN_ART_MSGID_IS
#define SELECT_ART_MSGID_CONTAINS       AA_SELECT_MASK + MARK_SEEN_ART_MSGID_CONTAINS
#define SELECT_ART_REF_BASE             AA_SELECT_MASK + MARK_SEEN_ART_REF_BASE
//#define SELECT_ART_REF_IS               AA_SELECT_MASK + MARK_SEEN_ART_REF_IS
#define SELECT_ART_REF_CONTAINS         AA_SELECT_MASK + MARK_SEEN_ART_REF_CONTAINS
#define SELECT_NGROUP_BASE              AA_SELECT_MASK + MARK_SEEN_NGROUP_BASE
//#define SELECT_NGROUP_IS                AA_SELECT_MASK + MARK_SEEN_NGROUP_IS
#define SELECT_NGROUP_CONTAINS          AA_SELECT_MASK + MARK_SEEN_NGROUP_CONTAINS

typedef struct tag_ad
{
  int iAction;
  long int iParam;
  char *sParam;
} ACTIONDATA, FAR *LPACTIONDATA;

struct Node
{
  Node * Flink;
  Node * Blink;
  ACTIONDATA ad;
};

// WVArticleAction - 'killfile' et al
class WVArticleAction
{
public:
protected:
  Node *m_Head;
  Node *m_Tail;
  Node *m_Current;
  char m_ProfSect[128];
private:
public:
  WVArticleAction();
  WVArticleAction(WVArticleAction*wv);
  ~WVArticleAction();
  void SetIParam(int i);
  void SetParamText(char*sP);
  void ResetCurrent(){m_Current = m_Head;};
  void ReadActions(char*sGroup);
  void WriteActions();
  Node*GetCurrent(){return m_Current;};
  void Append(int iA, long int iP, char*sP);
  void DeleteNode(Node* pN);
  void DeleteAll();
  void GoToNext();
  void GoToPrev();
  void Switch(Node*nA, Node*nB);
  void Switchwith(WVArticleAction*nB);
  void ActOnArticles(TypGroup far *Group, header_p headers);
protected:
private:
};

extern WVArticleAction g_action;

#endif WVCLASS_H

--=====================_830668167==_
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: attachment; filename="wvglob.h"

/*---- Module WVGLOB.H  -------------------------------------------- */
/* WVGLOB.H contains all the global types and variables for WinVN.   */
/* Stylistically, this should probably be separated into several     */
/* header files, but this is what you've got for now.                */
/* cf WVDOC.C -- it describes some of these structures.              */
/*

 * $Id: wvglob.h 1.78 1995/11/09 00:09:37 dumoulin Exp $
 */
#ifndef __WVGLOB__
#define __WVGLOB__


#ifdef _WIN32
#ifndef WIN32
#define WIN32
#endif
#endif

#ifdef WIN32
#ifndef _WIN32
#define _WIN32
#endif
#endif

/* these are supposed be defined in windowsx.h, but they aren't in mine! */
#ifndef GET_WM_COMMAND_CMD
#ifdef WIN32
#define GET_WM_COMMAND_CMD(wp, lp)  HIWORD(wp)
#define GET_WM_COMMAND_ID(wp, lp)   LOWORD(wp)
#define GET_WM_COMMAND_HWND(wp, lp) (HWND)lp)
#else
#define GET_WM_COMMAND_CMD(wp, lp)  HIWORD(lp)
#define GET_WM_COMMAND_ID(wp, lp)   (wp)
#define GET_WM_COMMAND_HWND(wp, lp) ((HWND)LOWORD(lp))
#endif
#endif

#ifdef WIN32
#define huge far
#define LOPEN_READ	OF_READ
#define LOPEN_WRITE	OF_WRITE
#else
/*#define _int16 int */ /* (not defined in any 16 bit MSVC or MSVCNT 1.10) */
#define LOPEN_READ	READ
#define LOPEN_WRITE	WRITE
#endif

#ifndef _int16
#define _int16 short int
#endif

#ifndef _int32
#define _int32 long int
#endif

#define int16 _int16
#define int32 _int32
#define uint16 unsigned _int16
#define uint32 unsigned _int32

#define USE_3D_CONTROLS			/* define this to use 3d controls (ctl3d.dll) */

#define COMM_TIMER_INTERVAL 250	/* in milliseconds */

#define BUFSIZE			1024
#define TEMPBUFSIZE		1240
#define MAXHEADERLINE		800
#define MAXFINDSTRING		80
#define MAXDIALOGSTRING		255
#define MAXFILENAME		255
#define MAXENVVAR       40
#define MAXGROUPFILTERSIZE 1500

/* this has been increased for XOVER - some lines are *very* long */
#define MAXCOMMLINE		1536
#define MAXINTERNALLINE		180
#define MAXOUTLINE		255
#define MAXPOSTLENGTH		60000	/* max length for a posting/mail edit window */
#define MAXBOUNDARYLEN		70	/* max length for MIME boundary  */
#define MAXNEWGROUPSASK		200	/* limit of groups in newgroups dialog box */
#define MAXENCODINGTYPELEN	24	/* max len for encoding type - i.e. Base-64 */
#define MAXCONTENTTYPELEN	48	/* max len for content type - i.e. Application/Postscript */
#define MAXBOUNDARYLINE		70	/* max len for MIME boundary */
#define TOOLBARHEIGHT		27	/* height of toolbar */
#define MAXSTATBARTEXT		60	/* maximum number of chars in status bar text  */
#define MAXTBBUTTONS		20	/* maximum number of tool bar buttons */

#ifdef __cplusplus
extern "C" {
#endif

#include <time.h>
#include <commdlg.h>

/* Profile section headings */
#define OLD				"Winvn"
#define ADMIN			"Admin"
#define COMM 			"Communications"
#define AUTH 			"Authorization"
#define INTERFACE		"Interface"
#define PERSONAL 		"Personal"
#define CONFIRM 		"Confirmation"
#define LOGGING 		"Logging"
#define MAIL_ADDRESSES	"Mail Addresses"
#define SMARTFILER 		"Smart Filer"
#define SEARCHES 		"Searches"
#define GROUPLIST   	"Group List"
#define ARTLIST			"Article List"
#define ARTICLE			"Article"
#define COMPOSE			"Compose"
#define CODING 			"Coding"
#define ATTACH			"Attachments"
#define INTERNATIONAL 	"intl"
#define EXECUTE         "URL Execute" 

/* Group sort choices */
#define STR_SORT_DATE      "Date"
#define STR_SORT_SUBJECT   "Subject"
#define STR_SORT_LINES     "Lines"
#define STR_SORT_THREADS   "Threads (strict)"
#define STR_SORT_THREADSUB "Thread/Subject"
#define STR_SORT_ARTNUM    "Article Number"
#define STR_SORT_FROM      "Author"


typedef long TypLineID;

typedef struct structtextselect {
  int LineNum;					/* Line number when selecting text -- Line Ord  */
  int CharNum;					/* Character number when selecting text         */
  /* The 1st LineNum in the Doc and the 1st CharNum in the line are 0   */
} TextSelect;

typedef struct structdoc {
  HANDLE hFirstBlock;			/* handle to first textblock in doc.        */
  HANDLE hLastBlock;			/* unused.                                  */
  unsigned int TotalLines;		/* total # of lines in doc.                 */
  unsigned int LongestLine;		/* # of bytes in the longest line of doc    */
  unsigned int HeaderLines;		/* total number of lines in header of doc
								   (incl. blank line) */
  unsigned int ActiveLines;		/* # of selected or otherwise active lines  */
  unsigned int CountedLines;	/* # of counted lines, as in subscr. groups */
  unsigned int BlockSize;		/* # of bytes in a textblock                */
  unsigned int SplitSize;		/* textblock split point in bytes           */
  HANDLE hCurAddBlock;			/* hBlock to point at which to add lines.   */
  unsigned int AddOffset;		/* offset in bytes for point to add lines   */
  TypLineID AddLineID;			/* LineID of place to add lines.            */
  HANDLE hCurTopScBlock;		/* hBlock of current top line of window     */
  unsigned int TopScOffset;
  TypLineID TopScLineID;
  unsigned int TopLineOrd;		/* ordinal in doc of top line in window     */
  HANDLE hLastSeenBlock;
  unsigned int LastSeenOffset;
  TypLineID LastSeenLineID;
  HANDLE hFindBlock;			/* location of place to start next search   */
  unsigned int FindOffset;		/* for "SearchStr"                          */
  TypLineID FindLineID;
  unsigned int FindTextOffset;
  char SearchStr[MAXFINDSTRING];	/* Search string for current search    */
  unsigned int ScXOffset;		/* # of chars offset for horizontal scroll  */
  unsigned int ScXChars;		/* # of chars/line for current window size  */
  unsigned int ScYLines;		/* # of lines that fit in current window    */
  unsigned int ScXWidth;		/* current size of client area of window    */
  unsigned int ScYHeight;
  HWND hDocWnd;
  struct structdoc *ParentDoc;	/* pointer to parent document            */
  HANDLE hParentBlock;			/* points to line in parent doc          */
  unsigned int ParentOffset;	/* that corresponds to/describes this    */
  TypLineID ParentLineID;		/* document                              */
  unsigned int OffsetToText;
  BOOL InUse;					/* TRUE if this TypDoc in use.           */
  int DocType;					/* DOCTYPE_xxx                           */
  BOOL TextSelected;			/* Indicates text selected               */
  TextSelect BeginSelect;		/* Line and Char where selection began   */
  TextSelect EndSelect;			/* Line and Char where selection ended   */
  /*  jlg - toolbar support  */
  HWND hWndTB;					/* Handle of the toolbar child window    */
  HWND hWndFrame;				/* Handle of the parent frame window     */
  /* add status bar text string here */
  char szStatBarText[MAXSTATBARTEXT];	/* status bar text string        */
  int  StatBarPercent;			/* 0 - 100 for thermometer in status bar */		
  /*  jlg - active line in multi-select list box */
  TypLineID ActiveLineID;		/* Line ID of the "active" line in list  */
  TypLineID AnchorLineID;		/* Line ID of the "anchor" line in list  */
  unsigned int SelectedLines;	/* num lines selected (jsc) */
  char ThumbTracking;			/* = TRUE if currently thumb tracking (jsc) */
  int numArtsSaved;				/* used when saving selected articles */
  int savingArtIndex;           /* used when saving/decoding selected articles */
} TypDoc;

typedef struct structblock {
  HANDLE hPrevBlock;			/* handle of previous block, or 0               */
  HANDLE hNextBlock;			/* handle of next block in document, or 0       */
  HANDLE hCurBlock;				/* handle of this block                         */
  int LWAp1;					/* # of used data bytes in block, inc header    */
  int NumLines;					/* # of lines in this block                     */
  int NumActiveLines;			/* # of active lines in this block.             */
  TypDoc *OwnerDoc;				/* pointer to document this block is in.        */
  int eob;						/* end-of-block; must be just before 1st line.  */
  /* Text lines */
  /* Another EOB marker */
} TypBlock;

typedef struct structline {
  int length;					/* Total # of bytes in line, all-inclusive    */
  TypLineID LineID;				/* Unique identifier for this line.           */
  int active;					/* =1 if line should be displayed, else 0     */
  /* Bytes of text */
  /* Another copy of length */
} TypLine;

typedef struct structtext {
  int NameLen;					/* # of bytes of text                          */
} TypText;

typedef struct structgroup {
  char Subscribed;				/* =TRUE if subscribed to this group.   */
  char Selected;				/* =TRUE if selected                    */
  char Determined;				/* =TRUE if group info has been retrieved */
  char Threaded;				/* =TRUE if has thread references */
  int NameLen;					/* # of bytes in group name             */
  TypDoc *SubjDoc;				/* points to doc containing subjs       */
  unsigned long ServerEstNum;	/* est # of arts in server              */
  unsigned long ServerFirst;	/* # of first art that server has.      */
  unsigned long ServerLast;		/* # of last art that server has.       */
  unsigned long HighestPrevSeen;	/* # of highest art server had in last  */
  /* session, from "s<num>" newsrc field  */
  HANDLE header_handle;			/* handle to global block of header array mem */
  HANDLE thread_handle;			/* handle to global block of thread ind. pointers */
  long int total_headers;		/* total # of headers in array */
  unsigned long NumUnread;		/* num unseen arts (jsc) */
  unsigned int nRanges;			/* # of TypRanges describing seen arts  */
  unsigned int nSpareRanges;    /* # of extra ranges to overflow before a forced regrow */
  /* Name of group *//* name of group, zero-terminated       */
  /* Ranges of articles seen *//* array of TypRanges, of seen articles */
  /* Spare Range area so nRanges array can grow if necessary */ 
} TypGroup;

typedef struct structarticle {
  unsigned long Number;			/* Server's number for this article    */
  char Seen;					/* =TRUE if article seen               */
  char Selected;				/* =TRUE if article selected           */
  TypDoc *ArtDoc;				/* points to doc with actual article   */
  int NameLen;					/* # of bytes in subject line */
  /* Subject line of article */
} TypArticle;

#define HEADER_SUBJECT_LENGTH	105
#define HEADER_FROM_LENGTH	74
#define HEADER_EMAIL_LENGTH	74

#define HEADER_MESSAGE_ID_LENGTH 100
#define HEADER_FROBREFLIST_LENGTH 277
#define HEADER_NEWSGROUPS_LENGTH 277

/* Offset used to calculate offset for LongestLine */
#define ARTICLE_SUBJECT_OFFSET	40
#define GROUP_NAME_OFFSET	10

/* the size of this struct *must* be a power of two for win16.  'huge' */
/* arrays require this. */
/* (+ 1 1 1 105 4 2 4 74 74 100 100 277 277 4) => 1024 */

typedef struct {
  char Seen;
  char Selected;
  char thread_depth;
  char subject[HEADER_SUBJECT_LENGTH];
  unsigned long number;
  unsigned int lines;
  /*   char date[9];     JD 6/25/93  */
  time_t date;
  char from[HEADER_FROM_LENGTH];
  char email[HEADER_EMAIL_LENGTH];
  char message_id[HEADER_MESSAGE_ID_LENGTH];
  char best_ref[HEADER_MESSAGE_ID_LENGTH];
  char frob_ref_list[HEADER_FROBREFLIST_LENGTH];
  char newsgroups[HEADER_NEWSGROUPS_LENGTH];
  TypDoc *ArtDoc;
} TypHeader;

typedef struct LATESTSTRUCT {
  unsigned int lines;
  char from[HEADER_FROM_LENGTH];
  char email[HEADER_EMAIL_LENGTH];
  char subject[HEADER_SUBJECT_LENGTH];
  char message_id[HEADER_MESSAGE_ID_LENGTH];
  char newsgroups[HEADER_NEWSGROUPS_LENGTH];
} LATEST;

typedef TypHeader huge *header_p;

typedef long huge *thread_array;

typedef thread_array huge *thread_array_p;

typedef char huge *char_p;

typedef struct structrange {
  unsigned long int First;
  unsigned long int Last;
} TypRange;

/* TypMRRFile is used to describe a file; I use it because Windows */
/* doesn't provide much in the way of disk I/O support.  */

typedef struct structMRRfile {
  HFILE hFile;					/* handle to file                            */
  OFSTRUCT of;
  char buf[BUFSIZE];			/* my I/O buffer.                            */
  int bufidx;					/* Index to next place in buf                */
  int bytesread;				/* for reads, # of bytes read in last read   */
  int mode;						/* mode in which to open file.               */
  int eofflag;					/* whether we have reached EOF (read)        */
} TypMRRFile;

#define CtoX(c) (c*CharWidth + SideSpace)
#define LtoY(l) (l*LineHeight + TopSpace)
#define EDITID   1				/* ID of edit box, to identify for return values */
#define MAXMEMONAME 15			/* Number of chars in memo name */
#define MEMONAMECHARS (MAXMEMONAME+2)
#define MAXVIEWS 10
#define END_OF_BLOCK (-1)
#define BLOCK_SIZE  4096
/*  RangeOffset gives the number of bytes from the beginning of
 *  a Group structure to the first Range field, given the length
 *  of the name entry.
 */

// Modified by Holger Liebig (Holger.Liebig@mch.sni.de) to support WinVN compiling
// on MIPS platform.  was: #define RangeOffset(nlen) (((nlen+2)/2)*2 + sizeof(TypGroup))

#define RangeOffset(nlen) (((nlen+sizeof(int))/sizeof(int))*sizeof(int)+sizeof(TypGroup))
#define GetGroup(LinePtr) (TypGroup far *) (((char far *) LinePtr) + sizeof (TypLine))
#define GetGroupName(LinePtr) (char far *) (((char far *) LinePtr) + sizeof (TypLine) + sizeof (TypGroup))
#define GetRangePtr(Group) (TypRange far *) ((char far *) Group + RangeOffset (Group->NameLen))
#define GetSpareRangePtr(Group) (TypRange far *) ((char far *) Group + RangeOffset (Group->NameLen) + sizeof (TypRange) * (Group->nRanges))
#define CalcGroupLen(Group) (sizeof (TypLine) + RangeOffset (Group->NameLen) + sizeof (TypRange) * (Group->nRanges) + sizeof (TypRange) * (Group->nSpareRanges) + sizeof (int))
#define GroupLenPtr(LinePtr) (*(int *) ((char *) LinePtr + LinePtr->length - sizeof (int)))
#define GetTextPtr(LinePtr) (char far *) ((char far *) (LinePtr) + sizeof (TypLine) + sizeof (TypText))
#define GetTextLen(LinePtr) ((TypText far *) ((char far *) (LinePtr) + sizeof (TypLine)))->NameLen

#ifdef WINMAIN
#define DEF
#else
#define DEF extern
#endif

DEF TypDoc NetDoc;
DEF LATEST Latest;

#define MRR_SCROLL_LINEUP    0
#define MRR_SCROLL_LINEDOWN  1
#define MRR_SCROLL_PAGEUP    2
#define MRR_SCROLL_PAGEDOWN  3

/* This structure maps between keystrokes and mouse events.
 * From an idea on p. 137 of Charles Petzold's book.
 * If you change the definition, be sure to update NUMKEYS.
 */
#define NUMKEYS 6
#ifndef MAC
DEF struct {
  WORD wVirtKey;
  int CtlState;
  int iMessage;
  WPARAM wRequest;
} key2scroll[NUMKEYS]

#ifdef WINMAIN
=
{
  VK_PRIOR, 0, WM_VSCROLL, SB_PAGEUP,
	VK_NEXT, 0, WM_VSCROLL, SB_PAGEDOWN,
	VK_UP, 0, WM_VSCROLL, SB_LINEUP,
	VK_DOWN, 0, WM_VSCROLL, SB_LINEDOWN,
	VK_LEFT, 0, WM_HSCROLL, SB_LINEUP,
	VK_RIGHT, 0, WM_HSCROLL, SB_LINEDOWN
}

#endif
;
#endif

DEF BOOL Initializing;
#define INIT_DONE                0
#define INIT_READING_NEWSRC      1
#define INIT_ESTAB_CONN          2
#define INIT_SCANNING_NETDOC     3
#define INIT_GETTING_LIST        4
#define INIT_NOT_CONNECTED       5
#define INIT_READY               6

#define MAXGROUPWNDS   4
#define MAXARTICLEWNDS 4
#define MAXPOSTWNDS    4
#define MAXMAILWNDS    4

DEF TypDoc GroupDocs[MAXGROUPWNDS];
DEF TypDoc ArticleDocs[MAXARTICLEWNDS];
DEF int NumGroupWnds;
DEF int NumArticleWnds;

typedef struct textBlockStruct {
  HWND hTextWnd;
  BOOL IsBusy;
  unsigned long numLines;
  unsigned long maxLines;
  unsigned long numBytes;
  unsigned long maxBytes;
  unsigned int maxLineLen;
  char huge *text;				/* big text of all lines */
  unsigned long huge *offset;	/* array of offsets into text array */
} TypTextBlock;

typedef struct _attachmentStruct {
  char fileName[MAXFILENAME];
  char contentType[32];
  char encodingType[16];
  unsigned long numBytes;		/* this is size of fileName */
  BOOL attachInNewArt;
} TypAttachment;

#define HDR_NUM_CONTROLS 12
/* these are indexes into the UI control array */
#define HDR_TO			0		/* has a browse button */
#define HDR_GROUPS		1
#define HDR_SUBJECT		2
#define HDR_FROM		3
#define HDR_ORG			4
#define HDR_REPLYTO		5
#define HDR_CC			6		/* has a browse button */
#define HDR_KEYWORDS	7
#define HDR_SUMMARY		8
#define HDR_DIST		9
#define HDR_FOLLOWTO	10
#define HDR_ATTACH	 	11

#define HDR_NUM_BUTTONS	2
/* these are indexes into the button control array */
#define BTN_TO			0
#define BTN_CC			1

typedef struct _HeaderControlStruct {
  HWND title[HDR_NUM_CONTROLS];
  HWND UI[HDR_NUM_CONTROLS];
  HWND button[HDR_NUM_BUTTONS];
  int yEdge;					/* y-coordinate of bottom of last control */
} TypHeaderControls;

DEF BOOL PrefillCcAddress;
DEF BOOL ShowFromHdr;
DEF BOOL ShowOrgHdr;
DEF BOOL ShowReplyToHdr;
DEF BOOL ShowKeywordsHdr;
DEF BOOL ShowSummaryHdr;
DEF BOOL ShowDistributionHdr;
DEF BOOL ShowFollowupToHdr;

#define MAX_NUM_ATTACHMENTS 10
typedef struct WndEditStruct {
  HWND hWnd;
  HWND hWndEdit;
  int composeType;				/* a doctype.  lets us tell if it's MAIL or FORWARD */
  char dirty;
  char busy;					/* TRUE if busy sending */
  unsigned long bodyOffset;		/* # bytes to skip in body for extra headers */
  TypDoc *Doc;
  TypHeaderControls *headerControls;
  TypAttachment *attachment[MAX_NUM_ATTACHMENTS];
  TypTextBlock *extraHeaders;
  HWND hLastFocusWnd;
  int numAttachments;
  int nextBatchIndex;	    /* for batch post/mails */
} WndEdit;

#define DT_CLEAN 0
#define DT_DIRTY 1

DEF WndEdit WndPosts[MAXPOSTWNDS];
DEF WndEdit WndMails[MAXMAILWNDS];
DEF int NumPostWnds;
DEF int NumMailWnds;

#define DOCTYPE_UNKNOWN  0
#define DOCTYPE_NET      1
#define DOCTYPE_GROUP    2
#define DOCTYPE_ARTICLE  4
#define DOCTYPE_POSTING  8
#define DOCTYPE_MAIL     16
#define DOCTYPE_FORWARD  32
#define DOCTYPE_CANCEL   64

/* Temp buffer for trace info */
#ifdef _DEBUG
DEF char szDebugBuffer[120];
#endif

/* Variables and constants for handling the FSA used to deal with    */
/* talking to the NNTP server.                                       */

DEF int CommState;				/* current state in comm FSA */
DEF BOOL CommBusy;				/* =TRUE if comm line busy interacting w/ server */
DEF BOOL CommDecoding;			/* =TRUE if comm line busy decoding lines from server */
DEF TypDoc *CommDoc;			/* Document currently receiving lines from server   */
DEF HWND hVerDlgList;			/* Handle to info in the Version Dialog Box */

DEF char CommLineIn[MAXCOMMLINE];	/* current input line being built by FSA   */
DEF char *CommLinePtr;			/* pointer to next place to put char in CommLineIn  */
DEF char *CommLineLWAp1;		/* if we get this far, we're at end of buffer       */
DEF char IgnoreCommCh;			/* char to ignore when reading from server          */
DEF char EOLCommCh;				/* char that indicates end of line upon input       */
DEF TypDoc *ActiveGroupDoc;
DEF TypDoc *ActiveArticleDoc;
DEF WndEdit *ComposeWnd;		/* active compose window */

DEF BOOL SendingMail, SendingPost;

#define MAXGROUPNAME 80
DEF char CurrentGroup[MAXGROUPNAME];	/* name of group currently selected on
										   server */
DEF int iSortOption;            /* Article sorting option */

DEF BOOL UsingSocket;			/* =TRUE if using PC/TCP rather than serial I/O     */

DEF BOOL threadp;
DEF BOOL xoverp;
DEF BOOL force_xhdr;

#define MAXNNTPSIZE 40
#define MAXPREFIXSIZE 40
#define MAXTZONESIZE 20
DEF char NNTPHost[MAXNNTPSIZE];
DEF char NNTPService[MAXNNTPSIZE];
DEF char SMTPHost[MAXNNTPSIZE];
DEF char NNTPUserName[MAXNNTPSIZE];
DEF char NNTPPasswordEncrypted[2 * MAXNNTPSIZE];
DEF char TimeZone[MAXTZONESIZE];
DEF char MAPIPrefix[MAXPREFIXSIZE];
DEF BOOL NNTPSavePassword;
DEF BOOL AuthReqPost;			/* TRUE if we may not post at all unless authenticated */
DEF BOOL AuthReqMail;			/* TRUE if we may not send mail unless authenticated */
DEF BOOL Authenticated			/* TRUE if we've been authenticated by NNTP server */
#ifdef WINMAIN
= FALSE
#endif
 ;
/* This is the name that was successfully authenticated by the NNTP server.
 * It might not be the same as NNTPUserName, if the user has changed the
 * username since the beginning of the session.
 */
DEF char AuthenticatedName[MAXNNTPSIZE];

#define MAILLEN 256
DEF char MailAddress[MAILLEN];
DEF char ReplyTo[MAILLEN];
DEF char UserName[MAILLEN];
DEF char Organization[MAILLEN];

DEF char GenSockDLL[MAXFILENAME];
DEF int ConnectAtStartup;

DEF BOOL EnableGroupFilter;
DEF char *GroupFilter;

/* moved state defns to a separate include file to associate stringtable (jlg) */
#include "wvstates.h"

#define LFN_HELP "WINVN.HLP"

/* variables used in an ad hoc attempt to optimize updating of windows
 * by the input cracking FSA. */

#define UPDATE_TITLE_FREQ	10
#define UPDATE_ART_FREQ		12
#define MAX_IMMEDIATE_UPDATE	2
#define STATUS_UPDATE_FREQ	20

DEF unsigned int RcvLineCount;

DEF TypLineID NextLineID		/* LineID to assign to next created line */
#ifdef WINMAIN
= 10664L
#endif
 ;

DEF HINSTANCE hInst;
DEF HWND hWndConf;
//DEF HWND hWndSk;
//DEF HWND hDosWnd;
//DEF HWND hWndDebugComm;       /* handle to Debug Comm window */
//DEF int CommDevice;       /* comm device ID, if using serial I/O */

DEF HANDLE hAccel;				/* handle to main accelerator table */
DEF MSG MainMsg;				/* message returned from GetMessage */


DEF char str[255];				/* general-purpose string buffer */


DEF HCURSOR hSaveCursor;		/* handle to current cursor      */
DEF HCURSOR hHourGlass;			/* handle to hourglass cursor    */


//DEF int X, Y;         /* last cursor position          */
DEF int DragMouseAction;		/* mouse action for dragging      */

#define DRAG_NONE                  0
#define DRAG_SELECT                1
#define DRAG_DESELECT              2
#define SEEN_SELECT                3
#define SEEN_DESELECT              4

DEF POINT ptCursor;				/* x and y coordinates of cursor */

DEF int ViewNew;
DEF int NewArticleWindow;
DEF int SelectAll;
DEF int DoList;
DEF int did_list;
DEF unsigned long article_threshold;
DEF unsigned long min_to_retrieve;
DEF unsigned long est_num_unread;
DEF unsigned long arts_to_retrieve;

// DEF int savingArtIndex; 		/* get rid of global to stop GPF's when multi-tasking */
// DEF int numArtsSaved;        /* now in TypeDoc structure JD 10/30/95 */
// DEF int nextBatchIndex;	    /* for batch post/mails */

DEF BOOL FullNameFrom;
DEF BOOL TrimHeaders;
DEF BOOL ScrollPastHeaders;
DEF BOOL ItalicizeQuotes;
DEF BOOL WrapIncomingArticleText;
DEF int WrapIncomingArticleTextLength;
DEF BOOL WordWrap;
DEF BOOL ConfirmBatchOps;
DEF BOOL ConfirmSaveOnExit;
DEF BOOL ConfirmReplyTo;
DEF BOOL ConfirmDisconnect;
DEF BOOL ShowUnsubscribed;
//DEF BOOL ShowReadArticles;
DEF BOOL DebugComm;
DEF BOOL ShowUnreadOnly;
DEF BOOL SaveNewsrc;
DEF BOOL NewsrcDirty;
DEF BOOL SaveConfig;
DEF BOOL bEnableArticleAction;
DEF char LastArticleTextFind[MAXFINDSTRING];
DEF char LastArticleHeaderFind[MAXFINDSTRING];
DEF char LastGroupNameFind[MAXFINDSTRING];

#define THREAD_COMPLETE    1
#define THREAD_INCOMPLETE  2

/* AskComm says whether to put up the communications dialog box
 * upon starting up.  Options are never, always, and yes, because
 * this is the first time the program has been run.
 #define ASK_COMM_NEVER    0
 #define ASK_COMM_ALWAYS   1
 #define ASK_COMM_INITIAL  2
 DEF int AskComm;
 */
DEF BOOL ArticleFixedFont;

DEF int xScreen, yScreen;
DEF int CaptionHeight;
DEF HFONT hWinVnFont;			/* handle to font for WinVN status bar/etc */
DEF HFONT hCompositionFont;		/* handle to font for Composition body text */
DEF HFONT hListFont;			/* handle to font used in group/art lists */
DEF HFONT hFontArtNormal;		/* handle to font used in Article window - normal
								   text mode. */
DEF HFONT hFontArtQuote;		/* handle to font used in Article window - 
								   comments == Italics. */
DEF HFONT hFontPrint;			/* handle to font used for printing. */
DEF HFONT hFontPrintB;			/* handle to font used for bold printing. */
DEF HFONT hFontPrintS;			/* handle to font used for printing Subject line. */
DEF HFONT hFontPrintI;			/* handle to font used for printing Quoted lines. */
DEF HFONT hStatusFont;			/* handle to font used in status windows */

DEF int WinVnFontSize;
DEF char WinVnFontFace[32];
DEF char WinVnFontStyle[32];
DEF int WinVnLineHeight, WinVnCharWidth;	/* # of windows units for WinVn font */

DEF int CompositionFontSize;
DEF char CompositionFontFace[32];
DEF char CompositionFontStyle[32];
DEF int CompositionLineHeight, CompositionCharWidth;

DEF int ListFontSize;
DEF char ListFontFace[32];
DEF char ListFontStyle[32];
DEF int LineHeight, CharWidth;	/* # of window units for list font */
DEF int TopSpace, SideSpace;	/* # of window units to leave at top and side  */
							   /* of window (for aesthetic purposes)          */

DEF int ArticleFontSize;
DEF char ArticleFontFace[32];
DEF char ArticleFontStyle[32];
DEF int ArtLineHeight, ArtCharWidth;	/* # of windows units for article font */
DEF int ArtTopSpace, ArtSideSpace;	/* # of window units to leave at top and side  */

DEF int PrintFontSize;
DEF char PrintFontFace[32];

DEF int StatusFontSize;
DEF char StatusFontFace[32];
DEF char StatusFontStyle[32];
DEF int StatusLineHeight, StatusCharWidth;	/* # of window units for status font */

DEF int StartPen;				/* Similar to TopSpace; where to start pen 1st row */
DEF int ScreenYPixels;			/* used in converting points to logical units */
DEF int PrinterYPixels;			/* used in converting points to logical units */
DEF COLORREF OldTextColor, OldBkColor;
DEF COLORREF NetUnSubscribedColor;	/* color to use for unsubscribed groups  */
DEF COLORREF NetSubscribedColor;	/* color to use for subscribed groups  */
DEF COLORREF ArticleSeenColor;	/* color to use for articles that have been seen */
DEF COLORREF ArticleKilledColor;	/* color for unseen articles that have been marked seen */
DEF COLORREF ArticleUnSeenColor;	/* color to use for articles that have not been seen */
DEF COLORREF ArticleTextColor;	/* color to use for article/post text */
DEF COLORREF StatusTextColor;	/* Color to use for status text */
DEF COLORREF ListBackgroundColor;	/* background color for group/article listings */
DEF COLORREF ArticleBackgroundColor;	/* background color for article/post windows */
DEF COLORREF StatusBackgroundColor;		/* background color for status windows */
DEF COLORREF CustomColors[16];	/* Custom colors definable by user in ChooseColor */
DEF HBRUSH hListBackgroundBrush;
DEF HBRUSH hArticleBackgroundBrush;
DEF HBRUSH hStatusBackgroundBrush;
DEF BOOL LimitedColor;
DEF BOOL UseInverseSelections;
DEF BOOL ShowSplashScreen;

DEF int ReverseVideo;
DEF BOOL ThumbTrack;

DEF BOOL MailDemandLogon;		/* FALSE = permanent logon
								   TRUE  = logon on send mail */
DEF int MailForceType;			/*  Force Mail Type to valid value where
								   Less then zero means
								   default negotiation */
DEF int MailLog;				/* True means append to log files */
DEF int PostLog;				/* where XXXXLogFile is file name */


DEF char MailLogFile[MAXFILENAME];
DEF char PostLogFile[MAXFILENAME];

DEF int fmtDaysB4Mth;
DEF char fmtDateDelim[2];


#define QuoteLineInd  '>'

DEF DLGPROC lpfnWinVnArticleActionDlg;
DEF DLGPROC lpfnWinVnSaveArtDlg;
DEF DLGPROC lpfnWinVnSaveArtsDlg;
DEF DLGPROC lpfnWinVnFindDlg;
DEF DLGPROC lpfnWinVnGenericDlg;
DEF DLGPROC lpfnWinVnSubjectDlg;
DEF DLGPROC lpfnWinVnCommDlg;
DEF DLGPROC lpfnWinVnAuthDlg;
DEF DLGPROC lpfnWinVnDoListDlg;
DEF DLGPROC lpfnWinVnPersonalInfoDlg;
DEF DLGPROC lpfnWinVnExecuteInfoDlg;
DEF DLGPROC lpfnWinVnConfirmationDlg;
DEF DLGPROC lpfnWinVnAppearanceDlg;
DEF DLGPROC lpfnWinVnControlSubclass;
DEF DLGPROC lpfnWinVnThresholdDlg;
DEF DLGPROC lpfnWinVnLogOptDlg;
DEF DLGPROC lpfnWinVnDecodeArtsDlg;
DEF DLGPROC lpfnWinVnAttachDlg;
DEF DLGPROC lpfnWinVnComposePrefsDlg;
DEF DLGPROC lpfnWinVnAttachPrefsDlg;
DEF DLGPROC lpfnWinVnEncodeDlg;
DEF DLGPROC lpfnWinVnExitDlg;
DEF DLGPROC lpfnWinVnMailDlg;
DEF DLGPROC lpfnWinVnSmartFilerDlg;
DEF DLGPROC lpfnWinVnSelectPathDlg;
DEF DLGPROC lpfnWinVnVersionListDlg;
DEF DLGPROC lpfnWinVnArticleDlg;
DEF DLGPROC lpfnWinVnCodingPrefsDlg;
DEF DLGPROC lpfnWinVnArtListDlg;
DEF DLGPROC lpfnWinVnGroupListDlg;

DEF char *szAppName;
DEF char szAppProFile[MAXFILENAME];
DEF char szNewsSrc[MAXFILENAME];

DEF char SaveArtFileName[MAXFILENAME];
DEF char DecodePathName[MAXFILENAME];
DEF char DialogString[MAXDIALOGSTRING];
DEF char AddressString[MAXDIALOGSTRING];
DEF char NameString[MAXDIALOGSTRING];
DEF char CcAddress[MAXDIALOGSTRING];
DEF BOOL CcByMail;
DEF int SaveArtAppend;
DEF BOOL SaveNewsrcOnClose;
DEF int ThreadFullSubject;
DEF char ThreadDepthIndicator[2];
DEF BOOL GroupListMultiSelect;
DEF BOOL ArtListMultiSelect;
DEF int SpareRanges;
DEF BOOL TrackSubscribedCrossposts;
DEF BOOL TrackUnsubscribedCrossposts;

DEF TypDoc *FindDoc;
DEF char *NewsgroupsPtr;		/* Used to pass pointer to newsgroup of new posting. */

/* For each new group detected, we create an entry in the following
 * array, NewGroupTable.  Each entry contains a far pointer to a
 * dynamically-allocated global data structure containing a line
 * containing information on this group, in the exact same format
 * as used in the NetDoc.
 */
DEF void huge *huge * NewGroupTable;	/* array of pointers to new group lines */
DEF HANDLE hNewGroupTable;		/* Handle to the above array */
DEF int nNewGroups;
DEF HANDLE hNewGroupData;
DEF void huge *NewGroupData;
DEF unsigned int HashTableSize;
DEF unsigned int LinesInRC;

typedef struct structHier {
  HANDLE hName;
  int Start;
  int NumGroups;
  HANDLE hNext;
} TypHier;

#define ADD_SUBSCRIBED_END_OF_SUB	0
#define ADD_SUBSCRIBED_TOP_OF_DOC	1
#define ADD_FIRST_SELECTED       	2

#define LINE_FLAG_SET			0

#define GROUP_ACTION_SUBSCRIBE		0
#define GROUP_ACTION_UNSUBSCRIBE	1
#define GROUP_ACTION_CHECK_ACTIVE	2
#define GROUP_ACTION_GET_GROUPNAMES 3
#define GROUP_ACTION_SELECTED       4	

#define ARTICLE_ACTION_SAVE		0
#define EXTEND				2
#define COMPARE				1
#define NO_COMPARE			0
#define SHOW				1
#define NO_SHOW				0
#define NO_ID				NULL
#define REUSE				1
#define NO_REUSE			0
#define SELECT				1
#define DESELECT			0
#define ENABLE				1
#define DISABLE				0
#define BLOCK_ACTION_SET_ACTIVE		0

DEF int il, ic;
DEF int irow;
DEF int imemo;
DEF int ih;

#if 0
#define MAXCOMMSPEEDCHARS 7
DEF int CommPortID;				/* IDD_COM1 or IDD_COM2 */
DEF int CommParityID;			/* IDD_7EVEN or IDD_8NONE  */
DEF char pszCommSpeed[MAXCOMMSPEEDCHARS];	/* character version of comm speed */
#endif

DEF int idTimer;				/* timer ID            */

#define IncPtr(ptr,byint) (char far *) ptr += byint

/* the MailCtrl global variable is scoped globally after the main window is
   created and is only modified at creation during MailInit in wvmail.c */
DEF struct MailCtrlStruct {
  int MailType;
  int enableMail;
  int enableLogout;
  int enableForward;
  int (*fnMlInit) (HWND hWnd);
  int (*fnMlLogout) (HWND hWnd);
  int (*fnMlClose) (HWND hWnd);
  int (*fnMlWinCreate) (HWND hWnd, TypDoc * Doc, int DocType);
} MailCtrl;

#define MT_NONE 0
#define MT_MAPI 1
#define MT_SMTP 2

#define INACTIVE		0		/* values for CodingState      */
#define DECODE_ACTIVE		1	/* values for Decoding must be */
#define DECODE_SKIPPING		2	/* a contiguous range          */
#define DECODE_PROCESSING	3
#define DECODE_GET_TABLE	4
#define ATTACH_PROCESSING	10	/* Encodes must be > decodes   */
#define ATTACH_SENDING		11
#define ATTACH_READFILE		12
#define ATTACH_WAITING      13

#define CODINGTABLESIZE		64

#define BASE_BLOCK_SIZE		16384	/* base size for the huge data */
typedef struct structcoded {
  char name[MAXFILENAME];		/* original file name from begin line */
  char ident[MAXINTERNALLINE];	/* based on article subject line + author */
  BOOL beginFlag;				/* =TRUE this block is begin of the complete binary */
  BOOL endFlag;					/* =TRUE this block is end of the complete binary */
  int sequence;					/* =-1 if unknown, or # in mult-part file */
  int seqConfidence;			/* confidence of sequence info */
  long estNumLines;				/* info obtained from Lines: header during decode */
  unsigned long numLines;		/* num lines read so far (for status window */
  unsigned long numBytes;		/* # of bytes used in this coded data block */
  unsigned long maxBytes;		/* max # of bytes in this coded data block */
  char huge *data;				/* the huge data array */
  HWND hParentWnd;				/* handle to group wnd that started this */
} TypCoded;

#define MAX_DECODE_BLOCKS  256	/* max # of parts for a decode file */
#define MAX_DECODE_THREADS 75	/* max # of files in one batch decode */
typedef struct decodeThreadStruct {
  char name[MAXFILENAME];		/* original file name from begin line */
  char ident[MAXINTERNALLINE];	/* thread ID based on article subject line */
  char dosFileName[MAXFILENAME];	/* workable DOS file name */
  char contentType[MAXCONTENTTYPELEN];	/* MIME content type */
  char contentDesc[80];			/* MIME content description */
  char customTable[100];		/* custom coding table (if CODE_CUSTOM) */
  int contentEncoding;			/* MIME content-transfer-encoding */
  int numBlocksWritten;			/* number of blocks written to disk, so far */
  int mode;						/* 2nd field of begin header, don't use in DOS */
  int numBlocks;				/* number of coded blocks used in list */
  int expectedNumBlocks;		/* 0 if unknown, or a # if found in headers */
  unsigned long totalBytes;		/* total # of bytes for entire file */
  TypCoded *codedBlockList[MAX_DECODE_BLOCKS];	/* list of ptrs to decode
												   objects */
  TypTextBlock *statusText;		/* buffers for thread status text window */
} TypDecodeThread;

#define CODE_BASE64   1
#define CODE_UU       2
#define CODE_XX       3
#define CODE_CUSTOM   4
#define CODE_QP       5
#define CODE_UNKNOWN  6
#define CODE_NONE     0

#define ENCODE_LINE_LEN  45

/* these correspond to the # members in the static arrays of strings */
/* defined in wvattach.c */
#define NUM_ENCODING_TYPES 5
#define NUM_CONTENT_TYPES 10

/* coding and attachment globals  */
DEF char xxMap[128], uuMap[128], base64Map[128], customMap[128];
DEF char *CodingMap[7];			/* N+1 for N coding types */
DEF int CodingState;
DEF TypCoded *currentCoded;
DEF TypTextBlock *CodingStatusText[MAX_DECODE_THREADS];
DEF int NumStatusTexts;
DEF char *ContentTypes[NUM_CONTENT_TYPES];
DEF char *EncodingTypes[NUM_ENCODING_TYPES];
DEF char uuTable[CODINGTABLESIZE+1]
#ifdef WVCODING
  = "`!\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_"
#endif
;
DEF char xxTable[CODINGTABLESIZE+1]
#ifdef WVCODING
  = "+-0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
#endif
;
DEF char base64Table[CODINGTABLESIZE+1]
#ifdef WVCODING
  = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/"
#endif
;

DEF BOOL CodingStatusVerbose;
DEF BOOL BlockCodingStatusAlwaysOnTop;
DEF BOOL MinimizeStatusWindows;
DEF BOOL DumbDecode;
DEF BOOL ExecuteDecodedFiles;
DEF BOOL KeepArticleHeaderVisible;
DEF BOOL AlsoDecodeOpenArticles;
DEF BOOL UseSmartFiler;
DEF HWND hCodedBlockWnd;		/* the block coding status window (top center of screen) */
DEF char UserCodingTable[CODINGTABLESIZE + 1];
#define STATUSWIDTH (85*StatusCharWidth)
#define STATUSHEIGHT (8*StatusLineHeight)

DEF char DefaultEncodingType[MAXENCODINGTYPELEN];
DEF int DefaultAttachInNewArt;
DEF char DefaultContentType[MAXCONTENTTYPELEN];
DEF char SubjectTemplate[MAXINTERNALLINE];

DEF char FollowupSaysTemplate[MAXINTERNALLINE];
DEF char ReplySaysTemplate[MAXINTERNALLINE];

DEF long ArticleSplitLength;
DEF char MIMEUUType[MAXENCODINGTYPELEN];		/* experimental types used in MIME header gen */
DEF char MIMEXXType[MAXENCODINGTYPELEN];
DEF char MIMECustomType[MAXENCODINGTYPELEN];

DEF char MIMECharset[80];

DEF BOOL GenerateMIME;
DEF BOOL MIMEUsageSuggestions;
DEF BOOL ReviewAttach;
DEF char* MIMEBoundary;

DEF BOOL UsingMIME;					/* = TRUE if found MIME Version header in incoming art */

#define CUT_HERE_TEXT  "BEGIN --- CUT HERE --- Cut Here --- cut here ---"

#define FAIL  -1
#define SUCCESS   0
#define ABORT 2
#define CONTINUE 3

#define MIME_VERSION "1.0"
#define ADD_TO_EDIT 1			/* used for AddEndedLineToBlock  */
#define ADD_TO_POST 2
#define ADD_TO_FILE 3
#define ADD_PLAIN   0

/* Signature File globals */
DEF int EnableSig;
DEF char SigFileName[MAXFILENAME];
DEF TypTextBlock *Signature;
#define BIG_SIG_FILE 40			/* warning if sig file > this many lines */
#define SIG_DELIMITER "-- "		/* delimiter as defined in Spencer rfc1036++ */

/* Mail List globals  */
DEF TypTextBlock *MailList;
DEF int MailListOrigNum;

/* Smart Filer globals */
DEF TypTextBlock *ExtMapSourceList;
DEF TypTextBlock *ExtMapDosList;
DEF int ExtListOrigNum;
DEF BOOL EnableExtensionConversion;
DEF unsigned int MaxFileNameLen;
DEF unsigned int MaxFileExtLen;
DEF int OnDupeName;
DEF int OnNameTooLong;

#define DUPE_AVOID_NONE			0	/* dupe avoidance list.  these numbers */
#define DUPE_AVOID_NUMBER_EXT	1	/* correspond with posn in droplist */
#define DUPE_AVOID_PREPEND_NUM	2
#define DUPE_AVOID_APPEND_NUM	3

#define SHORTEN_NONE			0	/* name shotrening list.  these numbers */
#define SHORTEN_TRUNCATE		1	/* correspond with posn in droplist */
#define SHORTEN_SKIP_VOWELS		2

/* bitmaps */
DEF HBITMAP DiskBitmaps[5];
DEF HBITMAP FolderBitmaps[3];

/* Printing Globals  */
DEF PRINTDLG pd;				/* Global structure to hold printer defaults */

/* globals for status bar */
typedef struct {
  int dyBorder;					/* System Border Width/Height       */
  int dyBorderx2;				/* System Border Width/Height * 2   */
  int dyBorderx3;				/* System Border Width/Height * 3   */
  int dyBorderx4;				/* System Border Width/Height * 4   */
  int dyBorderx8;				/* System Border Width/Height * 8   */
  int dyBorderx9;				/* System Border Width/Height * 9   */
  int dyBorderx10;				/* System Border Width/Height * 10  */
  int dyStatbar;				/* Status Bar height                */
  int dxStates;					/* Width reserved for State Info    */
  HFONT hFontStatbar;			/* Font used in status bar */
} STATUSPAINT;
DEF STATUSPAINT StatbarPntData;	/* dimensions used in status bar */

/* macros added by jsc */
/* why is there no uitoa!? */
#define uitoa(x,s,b) ultoa((unsigned long)(x),(s),(b))
#define atoui(s) (unsigned int)atol((s))
#define Decoding (CodingState >= DECODE_ACTIVE && CodingState <= DECODE_GET_TABLE)
#define TextBlockLine(b, n) &(b->text[b->offset[n]])
#define IsBright(c) (GetRValue(c) > 180 && GetGValue(c) > 180 && GetBValue(c) > 180)
#define IsDark(c) (GetRValue(c) < 40 && GetGValue(c) < 40 && GetBValue(c) < 40)
#define RectWidth(r) (r.right - r.left)
#define RectHeight(r) (r.bottom - r.top)

#define ENABLE_MENU   MF_BYCOMMAND|MF_ENABLED
#define DISABLE_MENU  MF_BYCOMMAND|MF_DISABLED|MF_GRAYED

/* this is the static system color for light gray (C0,C0,C0) */
#define GRAY_COLOR RGB(192,192,192)
#define BLACK_COLOR RGB(0,0,0)

/* WWW Client & FTP Client */
DEF char HttpClient[MAXFILENAME];    //shimomai
DEF char FtpClient[MAXFILENAME];     //shimomai
DEF char GopherClient[MAXFILENAME];  //dumoulin
DEF char WaisClient[MAXFILENAME];    //dumoulin

/* Table of mappings between value and string */
struct ValStrTable
{
  int value;
  char *text;
};

#include <string.h>
#include <stdio.h>				/* sprintf, etc... */

#ifdef __cplusplus
}
#endif

/*--- Last line of WVGLOB.H -------------------------------------------- */

#endif

/*
 * Local Variables:
 * tab-width: 2
 * end:
 */

--=====================_830668167==_
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: attachment; filename="wvsckgen.c"

/* Interface to GENSOCK module */
/* $Id: wvsckgen.c 1.28 1995/06/06 04:12:22 ishido Exp $ */

#include <windows.h>
#include <windowsx.h>
#include "wvglob.h"
#include "winvn.h"
#pragma hdrstop
#include <stdlib.h>
#include <stdio.h>				/* for sprintf */
#include <stdarg.h>				/* for varargs stuff */
#include <ctype.h>				/* for isspace */
#define MAXSENDLEN 32767
#define COMMBUFSIZE	1600

/* generic socket DLL support */
#include "gensock\\gensock.h"

char CommBuff[COMMBUFSIZE];
int CommBuffIdx = COMMBUFSIZE + 1;
int CharsInCommBuff = 0;

socktag NNTPSock = 0;
socktag SMTPSock = 0;
char my_hostname[256];

/* functions the rest of winvn expects to see */
void PutCommLine (char *line);
void PutCommData (char *data, unsigned int length);

int MRRReadComm (void);
void MRRCloseComm (void);
int MRRInitComm (void);

/* internal to this file */
int open_smtp_socket (void);
void smtp_error (char *message);
int finish_smtp_message (void);
int get_smtp_line (void);
int put_smtp_line (socktag sock, char far * line, unsigned int nchars);

HINSTANCE gensock_lib = 0;

int (FAR PASCAL * pgensock_connect) (char FAR * hostname, char FAR * service, socktag FAR * pst);
int (FAR PASCAL * pgensock_getchar) (socktag st, int wait, char FAR * ch);
int (FAR PASCAL * pgensock_put_data) (socktag st, char FAR * data, unsigned long length);
int (FAR PASCAL * pgensock_close) (socktag st);
int (FAR PASCAL * pgensock_gethostname) (char FAR * name, int namelen);
int (FAR PASCAL * pgensock_put_data_buffered) (socktag st, char FAR * data, unsigned long length);
int (FAR PASCAL * pgensock_put_data_flush) (socktag st);


/*-- function MRRReadComm ---------------------------------------
 *
 *  Reads characters from the NNTP Socket
 */

#define ERROR_BUFFER_SIZE 1024

void
complain (int err, char *function, char *fmt,...)
{
  va_list marker;
  char message[ERROR_BUFFER_SIZE];
  char message1[100];
  int done = 0;
  static int messageOnScreen = FALSE; /* avoid cascading errors --> stack crash */

  /* Write text to a string and output the string. */
  if (!messageOnScreen) {
    va_start (marker, fmt);
    _vsnprintf (message, ERROR_BUFFER_SIZE, fmt, marker);
    va_end (marker);
	if (err >=0)
	   wsprintf (message1, "Error %d - Function '%s'",err,function);
	else
	   wsprintf (message1, "WinVN Function '%s'",function);
	messageOnScreen = TRUE;
    MessageBox (NetDoc.hDocWnd, message, message1, MB_OK);
	messageOnScreen = FALSE;
  }
}

void
gensock_error (char *function, int retval)
{
  char error_string[512];
  int len;

  len = LoadString (hInst, retval, error_string, sizeof (error_string));
  complain (retval,function,"%s",
			len == 0 ? "[couldn't get error string]" : error_string);
}

int 
MRRReadComm ()
{
  int retval;
  unsigned char ch;

  /* we set wait = 1, sortof non-blocking */
  if (NNTPSock && (retval = (*pgensock_getchar) (NNTPSock, 1, (char FAR *)&ch))) {
	switch (retval) {
	case WAIT_A_BIT:
	case ERR_BUSY:
	  break;
	case ERR_NOT_CONNECTED:
	  Initializing = INIT_NOT_CONNECTED;
	  SendMessage (NetDoc.hDocWnd, (UINT) WM_COMMAND,
				   (WPARAM) IDM_DISCONNECT, (LPARAM) 0);
	  Disconnect ();
	  complain (-1,"MRRReadComm","NNTP server has closed the connection");
	  return (-1);
	  break;
	default:
	  gensock_error ("gensock_getchar", retval);
	}
	return (-1);
  }
  else
	return ((int) ch);
}

int
putline_internal (socktag sock, char *line, unsigned int nchars)
{
  int retval;

  if (sock && (retval =
	   (*pgensock_put_data) (sock,
							 (char FAR *) line,
							 (unsigned long) nchars))) {
	switch (retval) {
	case ERR_NOT_CONNECTED:
	  Initializing = INIT_NOT_CONNECTED;
	  SendMessage (NetDoc.hDocWnd, (UINT) WM_COMMAND,
				   (WPARAM) IDM_DISCONNECT, (LPARAM) 0);
	  Disconnect ();
	  complain (-1,"PutLine_Internal","NNTP server has closed the connection");
	  return (-1);
	  break;

	default:
	  gensock_error ("gensock_put_data", retval);
	}
	return (-1);
  }
  return (0);
}

/* PutCommLine takes a string, sends it, followed by
 * \r\n.  All one-line sends in winvn should use this.
 */

void
PutCommLine (char *line)
{
  putline_internal (NNTPSock, line, lstrlen (line));
  putline_internal (NNTPSock, "\r\n", 2);
}

/* Use this function for sending larger chunks of data.
 * the text data from an Edit class window can be sent
 * using this function
 */

void
PutCommData (char *data, unsigned int length)
{
  putline_internal (NNTPSock, data, length);
}

/*-- function MRRCloseComm -----------------------------------------
 *
 *  Close the communications port, serial or TCP.
 */
void 
MRRCloseComm ()
{
  if (NNTPSock) {
	(*pgensock_close) (NNTPSock);
	NNTPSock = (socktag) 0;
  }
  if (!SMTPSock && gensock_lib) {
	FreeLibrary (gensock_lib);
	gensock_lib = 0;
  }
  CommState = ST_CLOSED_COMM;
  SetStatbarText (NetDoc.hWndFrame, "", &NetDoc, TRUE, TRUE);
  InvalidateRect (NetDoc.hDocWnd, NULL, TRUE);
}

int
load_gensock ()
{
  int result = 0;

#ifdef WIN32
  if ((gensock_lib = LoadLibrary (GenSockDLL)) == NULL) {
#else
  if ((gensock_lib = LoadLibrary (GenSockDLL)) < HINSTANCE_ERROR) {
#endif
	char message[256];
	wsprintf (message, "Couldn't load '%s'", GenSockDLL);
	complain (-1,"Load_Gensock",message);
	gensock_lib = 0;
	return (-1);
  }

  if (!result && (pgensock_connect =
          (int (FAR PASCAL *) (char FAR *, char FAR *, socktag FAR *))
				  GetProcAddress (gensock_lib, "gensock_connect")) == NULL) {
	complain (-1,"Load_Gensock","couldn't getprocaddress for gensock_connect");
	result = -1;
  }

  if (!result && (pgensock_getchar =
          (int (FAR PASCAL *) (socktag, int, char FAR *))
				  GetProcAddress (gensock_lib, "gensock_getchar")) == NULL) {
	complain (-1,"Load_Gensock","couldn't getprocaddress for gensock_getchar");
	result = -1;
  }

  if (!result && (pgensock_put_data =
        (int (FAR PASCAL *) (socktag, char FAR *, unsigned long))
				GetProcAddress (gensock_lib, "gensock_put_data")) == NULL) {
	complain (-1,"Load_Gensock","couldn't getprocaddress for gensock_put_data");
	result = -1;
  }

  if (!result && (pgensock_close =
          (int (FAR PASCAL *) (socktag))
				  GetProcAddress (gensock_lib, "gensock_close")) == NULL) {
	complain (-1,"Load_Gensock","couldn't getprocaddress for gensock_close");
	result = -1;
  }

  if (!result && (pgensock_gethostname =
       (int (FAR PASCAL *) (char FAR *, int))
			 GetProcAddress (gensock_lib, "gensock_gethostname")) == NULL) {
	complain (-1,"Load_Gensock","couldn't getprocaddress for gensock_gethostname");
	result = -1;
  }

  if (!result && (pgensock_put_data_buffered =
     (int (FAR PASCAL *) (socktag, char FAR *, unsigned long))
	   GetProcAddress (gensock_lib, "gensock_put_data_buffered")) == NULL) {
	complain (-1,"Load_Gensock","couldn't getprocaddress for gensock_put_data_buffered");
	result = -1;
  }

  if (!result && (pgensock_put_data_flush =
      (int (FAR PASCAL *) (socktag))
		  GetProcAddress (gensock_lib, "gensock_put_data_flush")) == NULL) {
	complain (-1,"Load_Gensock","couldn't getprocaddress for gensock_put_data_flush");
	result = -1;
  }

  if (result) {
	FreeLibrary (gensock_lib);
	gensock_lib = 0;
  }
  return (result);
}

int
MRRInitComm ()
{
  int retval;

  /* load the library if it's not loaded */
  if (!gensock_lib) {
	if ((retval = load_gensock ())) {
	  return (retval);
	}
  }

  /* to keep our sanity, we will quietly try '119' in case it fails */
  if ((retval = (*pgensock_connect) ((LPSTR) NNTPHost,
									 (LPSTR) NNTPService,
									 &NNTPSock))) {
	if (retval == ERR_CANT_RESOLVE_SERVICE) {
	  if ((retval = (*pgensock_connect) ((LPSTR) NNTPHost,
										 (LPSTR) "119",
										 &NNTPSock))) {
		gensock_error ("gensock_connect", retval);
		return (-1);
	  }
	}
	/* error other than can't resolve service */
	else {
	  gensock_error ("gensock_connect", retval);
	  return (-1);
	}
  }

  IgnoreCommCh = '\r';
  EOLCommCh = '\n';

  CommLinePtr = CommLineIn;
  CommState = ST_ESTABLISH_COMM;
  CommBusy = FALSE;
  return (0);
}

/* ---------------------------------------------------------------------------
 * open/close SMTP socket
 */

void 
abort_mail_socket ()
{
  /* in case we're _not_ connected to a NNTP server, and
   * we just used SMTP mail only, then we probably want to
   * close the library...
   */
  SMTPSock = 0;
  if (!NNTPSock && gensock_lib) {
	FreeLibrary (gensock_lib);
	gensock_lib = 0;
  }
}

int 
open_smtp_socket ()
{
  int retval;

  if (gensock_lib && SMTPSock)	// already open

	return 0;

  /* load the library if it's not loaded */
  if (!gensock_lib) {
	if ((retval = load_gensock ())) {
	  return (retval);
	}
  }

  if ((retval = (*pgensock_connect) ((LPSTR) SMTPHost,
									 (LPSTR) "smtp",
									 &SMTPSock))) {
	if (retval == ERR_CANT_RESOLVE_SERVICE ||
		retval == ERR_NO_ERROR_CODE) {		/* Chameleon is bad, it fails but sets no error code. */
	  if ((retval = (*pgensock_connect) ((LPSTR) SMTPHost,
										 (LPSTR) "25",
										 &SMTPSock))) {
		gensock_error ("gensock_connect", retval);
		abort_mail_socket ();
		return (-1);
	  }
	}
	/* error other than can't resolve service */
	else {
	  gensock_error ("gensock_connect", retval);
	  abort_mail_socket ();
	  return (-1);
	}
  }

  /* we wait to do this until here because WINSOCK is
   * guaranteed to be already initialized at this point.
   */

  /* get the local hostname (needed by SMTP) */
  if ((retval = (*pgensock_gethostname) (my_hostname, sizeof (my_hostname)))) {
    /* This is failing very often, I hope no smtp server complains too loudly */
    strcpy (my_hostname, "idunnomyownname");
#if 0
    gensock_error ("gensock_gethostname", retval);
    abort_mail_socket ();
    return (-1);
#endif
  }
  return 0;
}

int 
close_smtp_socket ()
{
  int retval = 0;

  if (SMTPSock) {
	if ((retval = (*pgensock_close) (SMTPSock))) {
	  gensock_error ("gensock_close", retval);
	}
  }
  abort_mail_socket ();

  return (retval);
}

/* ---------------------------------------------------------------------------
 * internal SMTP functions
 */

int 
get_smtp_line ()
{
  char ch = '.';
  char in_data[MAXOUTLINE];
  char *index;
  int retval = 0;

  index = in_data;

  while (ch != '\n') {
	if ((retval = (*pgensock_getchar) (SMTPSock, 0, &ch))) {
	  gensock_error ("gensock_getchar", retval);
	  return (-1);
	}
	else {
	  *index = ch;
	  index++;
	}
  }

  /* this is to support multi-line responses, common with */
  /* servers that speak ESMTP */

  /* I know, I know, it's a hack 8^) */
  if (in_data[3] == '-')
	return (get_smtp_line ());
  else
	return (atoi (in_data));
}

int 
put_smtp_line (socktag sock, char far * line, unsigned int nchars)
{
  int retval;

  if (!sock || (retval = (*pgensock_put_data) (sock, line, (unsigned long) nchars))) {
	gensock_error ("gensock_put_data", retval);
	return (-1);
  }
  return (0);
}

int 
finish_smtp_message ()
{
  int retval;

  if ((retval = (*pgensock_put_data_flush) (SMTPSock))) {
	return (retval);
  }
  return (put_smtp_line (SMTPSock, "QUIT\r\n", 6));
}

void 
smtp_error (char *message)
{
  MessageBox (NetDoc.hDocWnd, message, "WinVN", MB_OK);
  put_smtp_line (SMTPSock, "QUIT\r\n", 6);
  close_smtp_socket ();
}

/* ---------------------------------------------------------------------------
 * The following are entry points
 * all return 0 on success or non-zero on fail
 */

int
end_post ()
{
  int retval;

  if ((retval = (*pgensock_put_data_buffered) (NNTPSock, ".\r\n", 3))) {
	return (retval);
  }
  if ((retval = (*pgensock_put_data_flush) (NNTPSock))) {
	return (retval);
  }
  return 0;
}

int
end_send_smtp ()
{
  int retval;

  if ((retval = (*pgensock_put_data_buffered) (SMTPSock, ".\r\n", 3))) {
	return (retval);
  }

  if ((retval = (*pgensock_put_data_flush) (SMTPSock))) {
	return (retval);
  }

  retval = get_smtp_line ();
  if (retval != 250 && retval != 251) {
	smtp_error ("Message not accepted by server");
	return -1;
  }
  finish_smtp_message ();
  close_smtp_socket ();

  return 0;
}


int
send_smtp_line (char *str, unsigned long len)
{
  int retval;

  if (*str == '.' &&			/* if line starts with dot, send two dots */
	  (retval = (*pgensock_put_data_buffered) (SMTPSock, str, 1))) {
	return (retval);
  }
  return ((*pgensock_put_data_buffered) (SMTPSock, str, len));
}

int
post_line (char *str, unsigned long len)
{
  int retval;

  if (*str == '.' &&			/* if line starts with dot, send two dots */
	  (retval = (*pgensock_put_data_buffered) (NNTPSock, str, 1))) {
	return (retval);
  }
  return ((*pgensock_put_data_buffered) (NNTPSock, str, len));
}

/* prepare_smtp_message
 * headers is a textblock containing the header lines for this mail
 * grab the From, To and any Cc from here to generate From: and RCPT:
 * SMTP commands
 */
int
prepare_smtp_message (TypTextBlock * headers)
{
  char out_data[MAXOUTLINE], address[MAXHEADERLINE];
  char *ptr, *line;
  int len, startLen, result;
  unsigned long i;

  if (open_smtp_socket ())
	return (-1);

  if (get_smtp_line () != 220) {
	smtp_error ("SMTP server error");
	return (-1);
  }

  sprintf (out_data, "HELO %s\r\n", my_hostname);
  put_smtp_line (SMTPSock, out_data, strlen (out_data));

  if (get_smtp_line () != 250) {
	smtp_error ("SMTP server error");
	return (-1);
  }

  for (i = 0; i < headers->numLines; i++) {
	line = TextBlockLine (headers, i);
	if (!_strnicmp (line, "from: ", 6))
	  break;
  }
  if (i < headers->numLines)
	ParseAddress (&line[6], address, MAXHEADERLINE, str, MAXINTERNALLINE);
  else
	strcpy (address, MailAddress);

  ptr = &address[strlen (address) - 1];
  while (isspace (*ptr))
	*ptr-- = '\0';				/* strip trailing space */
  sprintf (out_data, "MAIL From:<%s>\r\n", address);
  put_smtp_line (SMTPSock, out_data, strlen (out_data));

  if (get_smtp_line () != 250) {
	smtp_error ("The mail server doesn't like the sender name, "
				"have you set your mail address correctly?");
	return (-1);
  }

  /* do a series of RCPT lines for all To: addresses and Cc: address */
  for (i = 0; i < headers->numLines; i++) {
	line = TextBlockLine (headers, i);

	if (!_strnicmp (line, "to: ", 4) || !_strnicmp (line, "cc: ", 4)) {
	  ptr = strcpy (address, &line[4]);
	  while (*ptr) {
		// if there's only one token left, then len will = startLen,
		// and we'll iterate once only
		startLen = strlen (ptr);
		if ((len = strcspn (ptr, " ,\n\t\r")) != startLen) {
		  ptr[len++] = '\0';	// replace delim with NULL char

		  while (isspace (ptr[len]) || ptr[len] == ',')		// eat white space

			ptr[len++] = '\0';
		}

		sprintf (out_data, "RCPT To: <%s>\r\n", ptr);
		putline_internal (SMTPSock, out_data, strlen (out_data));

		result = get_smtp_line ();
		if (result != 250 && result != 251) {
		  sprintf (str, "The mail server doesn't like the name %s.  "
				   "Have you set the 'To: ' field correctly?", ptr);
		  smtp_error (str);
		  return (-1);
		}

		if (len == startLen)	// last token, we're done

		  break;

		ptr += len;
	  }							/* RCPT loop */
	}							/* if To: or Cc: */
  }								/* for header lines */

  sprintf (out_data, "DATA\r\n");
  put_smtp_line (SMTPSock, out_data, strlen (out_data));

  if (get_smtp_line () != 354) {
	smtp_error ("Mail server error accepting message data");
	return (-1);
  }

  return (0);

}

/* prepare_cc_smtp_message
 * destination is the address(es) to forward to
 * headers is a textblock containing the header lines for mail to be forwarded
 */
int 
prepare_cc_smtp_message (char *destination, TypTextBlock * headers)
{
  register unsigned long i;
  char toLine[MAXOUTLINE], *fromLine;
  TypTextBlock *tempHeader;
  int retval;

  /* create temporary header block containing only a To: and a From: 
   * to make prepare_smtp_message happy
   */
  if ((tempHeader = InitTextBlock (NetDoc.hDocWnd)) == NULL)
	return 1;

  _snprintf (toLine, MAXOUTLINE, "To: %s\r\n", destination);
  retval = AddLineToTextBlock (tempHeader, toLine);

  if (!retval) {
	/* copy From: line from real headers */
	for (i = 0; i < headers->numLines; i++) {
	  fromLine = TextBlockLine (headers, i);
	  if (!_strnicmp (TextBlockLine (headers, i), "from: ", 6))
		break;
	}
	if (i < headers->numLines) {
	  retval = AddLineToTextBlock (tempHeader, fromLine);
	}
  }

  retval = retval ||
	prepare_smtp_message (tempHeader) ||
	put_smtp_line (SMTPSock, toLine, lstrlen (toLine));

  FreeTextBlock (tempHeader);
  return (retval);
}

#ifdef OLD_STUFF
int send_smtp_message (TypTextBlock * headers, char *message);
int cc_smtp_message (char *destination, TypTextBlock * headers, char *editstr);
int post_edit_data (char *edit_data);
int post_unended_edit_data (char *edit_data);
int send_smtp_edit_data (char *edit_data);
int send_smtp_unended_edit_data (char *edit_data);
int post_textblock (TypTextBlock * textBlock);
int send_smtp_textblock (TypTextBlock * textBlock);

int forward_smtp_message (char *destination, TypDoc * Doc);
int send_smtp_article (char *destination, TypDoc * Doc);
int send_textblock_internal (socktag sock, TypTextBlock * textBlock);
int prepare_smtp_message (TypTextBlock * headers);


/* ---------------------------------------------------------------------------
 * transform_and_send_edit_data
 */

int 
transform_and_send_edit_data (socktag sock, char *editptr)
{
  char *index;
  char previous_char = 'x';
  unsigned int send_len;
  int retval;
  BOOL done = 0;

  send_len = lstrlen (editptr);
  index = editptr;

  while (!done) {
	/* room for extra char for double dot on end case */
	while ((unsigned int) (index - editptr) < send_len) {
	  switch (*index) {
	  case '.':
		if (previous_char == '\n') {
		  /* send _two_ dots... */
		  if ((retval = (*pgensock_put_data_buffered) (sock, index, 1))) {
			return (retval);
		  }
		}
		if ((retval = (*pgensock_put_data_buffered) (sock, index, 1))) {
		  return (retval);
		}
		break;
	  case '\r':
		if (previous_char != '\r') {
		  if ((retval = (*pgensock_put_data_buffered) (sock, index, 1))) {
			return (retval);
		  }
		}
		/* soft line-break (see EM_FMTLINES), skip extra CR */
		break;

	  default:
		if ((retval = (*pgensock_put_data_buffered) (sock, index, 1))) {
		  return (retval);
		}
	  }
	  previous_char = *index;
	  index++;
	}
	if ((unsigned int) (index - editptr) == send_len) {
	  done = 1;
	}
  }

  /* this handles the case where the user doesn't end the last
   * line with a <return>
   */

  if (editptr[send_len - 1] != '\n') {
	if ((retval = (*pgensock_put_data_buffered) (sock, "\r\n", 2))) {
	  return (retval);
	}
  }

  /* now make sure it's all sent... */
  if ((retval = (*pgensock_put_data_flush) (sock))) {
	return (retval);
  }
  return (0);
}

int
post_edit_data (char *edit_data)
{
  int retval;
  if ((retval = transform_and_send_edit_data (NNTPSock, edit_data))) {
	return (retval);
  }
  return (end_post ());
}

int
post_unended_edit_data (char *edit_data)
{
  int retval;
  if ((retval = transform_and_send_edit_data (NNTPSock, edit_data))) {
	return (retval);
  }
  return (0);
}

int
send_smtp_edit_data (char *edit_data)
{
  int retval;
  if ((retval = transform_and_send_edit_data (SMTPSock, edit_data))) {
	return (retval);
  }
  return (end_send_smtp ());
}

int
send_smtp_unended_data (char *edit_data)
{
  int retval;
  if ((retval = transform_and_send_edit_data (SMTPSock, edit_data))) {
	return (retval);
  }
  return (0);
}

/* send_smtp_message
 * headers is a textblock containing the header lines for this mail
 * message is a pointer to the text content of an edit control
 */
int
send_smtp_message (TypTextBlock * headers, char *message)
{
  result = FAIL;
  if (!prepare_smtp_message (headers) &&
	  !send_smtp_textblock (headers) &&
	  !send_smtp_edit_data (message) &&
	  !finish_smtp_message ()) {
	result = SUCCESS;
  }

  close_smtp_socket ();
  return (result);
}

int
send_textblock_internal (socktag sock, TypTextBlock * textBlock)
{
  register unsigned long i;
  char *line;
  int retval;

  for (i = 0; i < textBlock->numLines; i++) {
	line = TextBlockLine (textBlock, i);
	/* if line starts with dot, send two dots */
	if (*line == '.' &&
		(retval = (*pgensock_put_data_buffered) (sock, line, 1))) {
	  return (retval);
	}
	if ((retval = (*pgensock_put_data_buffered) (sock, line, strlen (line)))) {
	  return (retval);
	}
  }

  /* now make sure it's all sent... */
  if ((retval = (*pgensock_put_data_flush) (sock))) {
	return (retval);
  }
  return (0);
}

int
post_textblock (TypTextBlock * textBlock)
{
  return send_textblock_internal (NNTPSock, textBlock);
}

int
send_smtp_textblock (TypTextBlock * textBlock)
{
  return send_textblock_internal (SMTPSock, textBlock);
}

int 
forward_smtp_message (char *destination, TypDoc * Doc)
{
  int retval;

  if ((retval = prepare_smtp_message (destination))) {
	complain (-1,"Prepare_SMTP_Message","Return Code - %d\r\n", retval);
	return (retval);
  }
  else if ((retval = send_smtp_article (destination, Doc))) {
	complain (-1,"Send_SMTP_Message","Return Code - %d\r\n", retval);
	return (retval);
  }
  else if ((retval = finish_smtp_message ())) {
	complain (-1,"Finish_SMTP_Message","Return Code - %d\r\n", retval);
	close_smtp_socket ();
	return (retval);
  }
  close_smtp_socket ();
  return (1);
}

// testing new buffered stuff...

int 
send_smtp_article (char *destination, TypDoc * Doc)
{
  HANDLE hBlock;
  unsigned int Offset;
  TypLineID MyLineID;
  TypBlock far *BlockPtr;
  TypLine far *LinePtr;
  int retval;
  char line[MAXOUTLINE], temp[MAXOUTLINE];

  _snprintf (line,
			 MAXOUTLINE,
			 "From: %s (%s)\r\n",
			 MailAddress,
			 UserName);


  if ((retval =
	   (*pgensock_put_data_buffered) (SMTPSock, line, lstrlen (line)))) {
	return (retval);
  }

  _snprintf (line,
			 MAXOUTLINE,
			 "To: %s\r\n",
			 destination);


  if ((retval =
	   (*pgensock_put_data_buffered) (SMTPSock, line, lstrlen (line)))) {
	return (retval);
  }

  /* find the subject line */
  TopOfDoc (Doc, &BlockPtr, &LinePtr);
  *line = '\0';
  while (ExtractTextLine (Doc, LinePtr, temp, MAXOUTLINE - 1)) {
	if (!_strnicmp (temp, "subject:", 8)) {
	  _snprintf (line,
				 MAXOUTLINE,
				 "Subject: %s (fwd)\r\n",
				 &temp[8]);
	  break;
	}
	if (!NextLine (&BlockPtr, &LinePtr))
	  break;
  }
  if (*line && (retval =
		  (*pgensock_put_data_buffered) (SMTPSock, line, lstrlen (line)))) {
	return (retval);
  }

  _snprintf (line,
			 MAXOUTLINE,
			 "\r\n[article forwarded from %s (%s)]\r\n\r\n",
			 UserName,
			 MailAddress);

  if ((retval =
	   (*pgensock_put_data_buffered) (SMTPSock, line, lstrlen (line)))) {
	return (retval);
  }

  TopOfDoc (Doc, &BlockPtr, &LinePtr);
  while (ExtractTextLine (Doc, LinePtr, line, MAXOUTLINE - 1)) {
	/* double a leading dot */
	if (line[0] == '.') {
	  if ((retval = (*pgensock_put_data_buffered) (SMTPSock, ".", 1))) {
		return (retval);
	  }
	}
	strcat (line, "\r\n");

	if ((retval =
		 (*pgensock_put_data_buffered) (SMTPSock, line, strlen (line)))) {
	  return (retval);
	}

	if (!NextLine (&BlockPtr, &LinePtr))
	  break;
  }
  UnlockLine (BlockPtr, LinePtr, &hBlock, &Offset, &MyLineID);

  if ((retval =
	   (*pgensock_put_data_buffered) (SMTPSock, "\r\n.\r\n", 5))) {
	return (retval);
  }
  if ((retval =
	   (*pgensock_put_data_flush) (SMTPSock))) {
	return (retval);
  }

  if ((retval = get_smtp_line ()) != 250) {
	complain (-1,"Send_SMTP_Article", Send Failed. get_smtp_line() returned %d\r\n", retval);
  }

  return (0);
}
#endif

/* this is for emacs
 * Local variables:
 * tab-width: 2
 * end:
 */

--=====================_830668167==_
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: attachment; filename="wvstates.h"

/* wvstates.h

 * States in the FSA that cracks input lines from the server.
 *
 * $Id: wvstates.h 1.3 1994/11/21 21:20:46 jcooper Exp $
 */

#define ST_NONE                    800
#define ST_ESTABLISH_COMM          801
#define ST_GROUP_RESP              802
#define ST_XHDR_SUBJECT_START      803
#define ST_XHDR_SUBJECT_DATA       804
#define ST_IN_GROUP                805
#define ST_ARTICLE_RESP            806
#define ST_REC_ARTICLE             807
#define ST_POST_WAIT_PERMISSION    808
#define ST_POST_WAIT_END           809
#define ST_GROUP_REJOIN            810
#define ST_LIST_RESP               811
#define ST_LIST_GROUPLINE          812
//#define ST_MAIL_WAIT_PERMISSION    813
//#define ST_MAIL_WAIT_END           814
#define ST_CHECK_AUTHINFO_USERNAME 820
#define ST_CHECK_AUTHINFO_PASSWORD 821
#define ST_END_AUTHINFO            822
#define ST_XHDR_NEWSGROUPS_START   848
#define ST_XHDR_NEWSGROUPS_DATA    849
#define ST_XHDR_FROM_START         850
#define ST_XHDR_FROM_DATA          851
#define ST_XHDR_SUBJ_START         852
#define ST_XHDR_SUBJ_DATA          853
#define ST_XHDR_REF_START          854
#define ST_XHDR_REF_DATA           855
#define ST_XHDR_MID_START          856
#define ST_XHDR_MID_DATA           857
#define ST_XHDR_DATE_START         858
#define ST_XHDR_DATE_DATA          859
#define ST_XHDR_LINES_START        860
#define ST_XHDR_LINES_DATA         861
#define ST_XOVER_START             862
#define ST_XOVER_DATA              863
#define ST_XOVER_CHECK             864
#define ST_REC_ARTICLE_HEADER      865
#define ST_QUIT_RESP               866
#define ST_CLOSED_COMM             899

--=====================_830668167==_
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: attachment; filename="wvutil.cpp"

// -*- C++ -*-
/*
 * $Id: wvutil.cpp 1.97 1995/11/10 12:07:49 dumoulin Exp $
 *
 */

/*-- WVUTIL.C -- File containing utility routines.
 */

#include <windows.h>
#include <windowsx.h>			// for GlobalFreePtr (JSC)
extern "C"
{
#include "wvglob.h"
#include "winvn.h"
}
#pragma hdrstop
#include "WVClass.h"
#include <commdlg.h>			// for GetOpenFileName dialog (JSC)
#include <ctype.h>
#include <stdlib.h>
#include <time.h>
#ifndef WIN32
#include <dos.h>				// for _dos_getdiskfree
#endif
#include <io.h>					// for _open etc
#include <fcntl.h>

char far *mylstrcpy (char_p ptr1, char far * ptr2);
char *get_xhdr_line (char *line);
time_t parse_usenet_date (char *date);
void finish_header_retrieval ();
void GenerateFileFilters (HWND hParentWnd, char *filters);

BOOL TrimHeader (char *header);
void AddCommLineToDoc (char *line);
void WrapAddCommLineToDoc (char *line);

// please update this if you modify XHDR retrieval
// This will now be either 5 or 7, depending on whether threading
// is enabled via 'threadp'.
unsigned int total_xhdrs = 5;

/*--- function GetNum --------------------------------------------
 *
 *  Cracks off a positive integer number from a string.
 *
 *  Entry    *ptr  is the character position to start scanning
 *                 for an integer
 *
 *  Exit     *ptr  is the character position at which we stopped
 *                 scanning (because of a non-digit).
 *           *num  is the cracked off number.
 *           Returns TRUE iff we got a number.
 */
BOOL
GetNum (char **ptr, unsigned long int *num)
{
  BOOL gotit = FALSE;

  /* Skip initial spaces                                            */

  while ((**ptr) && **ptr == ' ')
	(*ptr)++;

  *num = 0;
  while (**ptr && isdigit (**ptr)) {
	*num = 10 * (*num) + (**ptr - '0');
	gotit = TRUE;
	(*ptr)++;
  }
  return (gotit);
}

char *
get_xhdr_line (char *line)
{
  char *cptr;
/* skip past the art # and space */
  for (cptr = line; isdigit (*cptr); cptr++);
  for (; *cptr == ' '; cptr++);
  return (cptr);
}

#if 0
MRB already did this
void
make_neat_from (char far * in, char far * out)
{
  char far *left, far * right;

  /* this is controlled from .ini */
  if (FullNameFrom) {
	left = strchr (in, '(');
	right = strrchr (in, ')');

	if ((left && right) && (left < right)) {
	  strncpy (out, left + 1, (size_t) (right - left - 1));
	  out[(right - left - 1)] = (char) 0;
	}
	else						/* No name in parens */
	  strcpy (out, in);
  }
  else							/* !FullNameFrom */
	strcpy (out, in);
}
#endif

/*-- function StrToRGB -------------------------------------------------
 *
 *  Takes an ASCII string of the form "r,g,b" where r, g, and b are
 *  decimal ASCII numbers, and converts it to an RGB color number.
 */
COLORREF
StrToRGB (char *cstring)
{
  BYTE red, green, blue;
  unsigned long int lred, lgreen, lblue;

  GetNum (&cstring, &lred);
  cstring++;
  GetNum (&cstring, &lgreen);
  cstring++;
  GetNum (&cstring, &lblue);
  red = (BYTE) lred;
  green = (BYTE) lgreen;
  blue = (BYTE) lblue;

  return (RGB (red, green, blue));
}

/*-- function RGBToStr -------------------------------------------------
 *
 *  Takes an RGB color ref and converts to a string of the form "r,g,b"
 *  result is placed in buf
 *  (JSC)
 */
char *
RGBToStr (char *buf, DWORD rgbVal)
{
  sprintf (buf, "%u,%u,%u", GetRValue (rgbVal),
		   GetGValue (rgbVal),
		   GetBValue (rgbVal));
  return (buf);
}

/* This was lifted from ANU news. */

time_t
parse_usenet_date (char *s)
{
  struct tm datetime;
  char *cp, mon[80];
  int dom = 0, yr = 0, hr = 0, mn = 0, sc = 0, mth = 0;
  static char fmtMonthTable[37] = "janfebmaraprmayjunjulaugsepoctnovdec";

  if (!s || !*s)
	return (0);
  if (cp = strchr (s, ','))
	s = ++cp;
  while (isspace (*s))
	s++;
  *mon = '\0';
  if (isdigit (*s)) {
	sscanf (s, "%d %s %d %d:%d:%d", &dom, mon, &yr, &hr, &mn, &sc);
	if (yr < 100)
	  yr += 1900;
  }
  else
	sscanf (s, "%*s %s %d %d:%d:%d %d", mon, &dom, &hr, &mn, &sc, &yr);

  if (!dom || !yr || !*(cp = mon))
	return (0);
  if ((dom <= 0) || (dom >= 32))
	return (0);
  if ((yr < 1980) || (yr > 2020))
	return (0);
  if (strlen (mon) > 10)
	return (0);
  if ((hr < 0) || (hr > 23))
	return (0);
  if ((mn < 0) || (mn > 59))
	return (0);
  if ((sc < 0) || (sc > 59))
	return (0);

  for (cp = mon; *cp; cp++)
	*cp = tolower (*cp);

  if (cp = strstr (fmtMonthTable, mon))
	mth = (cp - fmtMonthTable) / 3;

/*  Setup a Posix time structure and calculate time in absolute
   time (seconds since midnight, Jan 1, 1970    JD 06/25/93 */

  memset (&datetime, 0, sizeof (struct tm));
  datetime.tm_year = yr - 1900;
  datetime.tm_mon = mth;
  datetime.tm_mday = dom;
  datetime.tm_hour = hr;
  datetime.tm_min = mn;
  datetime.tm_sec = sc;

  return (mktime (&datetime));
}

/*-- function StringDate ----------------*/
char *
StringDate (char *s, time_t time)
{
  struct tm *datetime;
  if (time != 0) {
	datetime = localtime (&time);

	if (fmtDaysB4Mth) {
	  sprintf (s, "%02d%s%02d", datetime->tm_mday, fmtDateDelim, datetime->tm_mon + 1);
	}
	else {
	  sprintf (s, "%02d%s%02d", datetime->tm_mon + 1, fmtDateDelim, datetime->tm_mday);
	}
	return (s);
  }
  else
	return ("-----");
}

/*-- function DoCommInput ---------------------------------------
 *
 *
 */
void
DoCommInput ()
{
  int ch;

  while ((CommState != ST_CLOSED_COMM) && ((ch = MRRReadComm ()) >= 0)) {
	if (ch == IgnoreCommCh) {
	}
	else if (ch == EOLCommCh) {
	  *CommLinePtr = '\0';
	  DoCommState ();
	  CommLinePtr = CommLineIn;
	}
	else {
	  *(CommLinePtr++) = (char) ch;
	  if (CommLinePtr == CommLineLWAp1)
		CommLinePtr--;
	}
  }
}

void
update_window_title (HWND hwnd,
					 char *group_name,
					 unsigned long line_number,
					 unsigned long total_lines)
{
  char title[200];
  static int prevPercent, newPercent;
  // to avoid flicker, update percent only if it has changed more than 1%

  line_number *= 100;
  if (newPercent < prevPercent)
	prevPercent = 0;

  if ((line_number % UPDATE_TITLE_FREQ) == 0) {
	newPercent = (int) (line_number / total_lines);
	if (newPercent != prevPercent && newPercent - prevPercent > 1) {
	  sprintf (title, "Retrieving headers for '%s' : %d%%", group_name, newPercent);
	  SetWindowText (hwnd, title);
     SetStatbarPercent(hwnd, newPercent, CommDoc, TRUE);
	  prevPercent = newPercent;
	}
  }
}

int
check_server_code (int retcode)
{
  HWND hAlertWnd;
  int iClass = retcode / 100;

  if (ComposeWnd) {
	hAlertWnd = ComposeWnd->hWnd;
  }
  else if (CommDoc) {
	hAlertWnd = CommDoc->hWndFrame;
  }
  else {
	hAlertWnd = NetDoc.hWndFrame;
  }

  switch (iClass) {
  case 5:
	CommBusy = FALSE;
	CommState = ST_NONE;
	MessageBox (hAlertWnd, "Error On News Server", "WinVN", MB_OK | MB_ICONHAND);
	return (1);
	break;
  case 4:
	CommBusy = FALSE;
	CommState = ST_NONE;
	MessageBox (hAlertWnd, CommLineIn, "Message From News Server", MB_OK | MB_ICONHAND);
	switch (iClass) {
	case 400:
	  /* service discontinued */
//      MRRCloseComm ();
	  //      PostQuitMessage (0);
	  Disconnect ();
	  break;
	default:
	  break;
	}
	return (1);
	break;
  }
  return (0);
}

/*  Function sync_artnum

   Normally XREF returns lists of the same length for each header type
   but some servers have errors that could cause these lists to get
   out of sync. This function tries to find the proper location in the
   headers array and returns that location.  If the article number isn't
   found, it returns -1.  JD 6/19/93 */

long
sync_artnum (unsigned long artnum,
			 unsigned long activenum,
			 header_p headers, TypGroup far * GroupDoc)
{
  long headerloc = CommDoc->ActiveLines;
  if (artnum == activenum)
	return (headerloc);
  else if (artnum < activenum) {
	while ((artnum != activenum) && (headerloc > 0)) {
	  headerloc--;
	  if ((header_elt (headers, headerloc))->number == artnum)
		return (headerloc);
	}
	return (-1);
  }
  else {
	while ((artnum != activenum) && (headerloc < GroupDoc->total_headers - 1)) {
	  headerloc++;
	  if ((header_elt (headers, headerloc))->number == artnum)
		return (headerloc);
	}
	return (-1);
  }
}

char * get_best_reference (char * refer)
{
  char * start, * end;
  start = strrchr (refer, '<');
  if (!start) {
	// no valid ref here without a '<'
	return NULL;
  } else {
	start++;
	end = strrchr (start, '>');
	if (!end) {
	  // the last ref is not complete, recurse
	  *(start-1) = (char)0;
	  return (get_best_reference (refer));
	} else {
	  *end = 0; // was: *(end+1) = (char)0;  HAB 19951229
	  return start;
	}
  }
}


// Some Usenet voting software is generating obscenely long message-id's
// with non-unique front-parts 30 chars or greater... this was throwing
// off winvn in an interesting way.
// We solve this by replacing the last 4 characters of
// mid's longer than HEADER_MESSAGE_ID_LENGTH with a 4-char hex hash value
// string of the entire mid.

// This must be done to all references _and_ mid's in order for threading
// to be able to match 'em.

// slightly modified version of 'HashGroup' from wvlist.c

void
copy_message_id_with_frob (char * dest, const char * source)
{
  int pos;

  if(source && ('<' == *source)) // chop leading '<'
    source++;
  strncpy(dest, source, HEADER_MESSAGE_ID_LENGTH-1);
  pos = strcspn(dest, "> \t" );  // chop trailing whitespace and '>'
  if(pos)
  {
    dest[pos] = 0;
  }

  // only frob if we need to
  if (strlen(dest) >= HEADER_MESSAGE_ID_LENGTH - 2) {
	unsigned long sum = 0;
	const char * p;
	for (p = source; *p; p++) {
	  sum = (sum << 1) + *p;
	}
	sprintf (dest+HEADER_MESSAGE_ID_LENGTH-9, "%08x", sum);
  }
}


// clear out the latest header info
void ClearLatestInfo()
{
  memset(&Latest, 0, sizeof(Latest));
}


// store detailed info on the latest header read
void StoreHeaderInfo(const char* line)
{
  const char* sTmp = line;

  if(!sTmp) return;
  while(*sTmp && !isspace(*sTmp)) // find first whitespace
    sTmp++;
  while(*sTmp && isspace(*sTmp)) // find first char following whitespace
    sTmp++;

  if(!_strnicmp ("subject:", line, 8))
  {
//    if(!_strnicmp("Re: ", sTmp, 4))
//      sTmp += 4;
    mylstrncpy(Latest.subject, sTmp, sizeof(Latest.subject));
  }
  else if(!_strnicmp ("from:", line, 5))
  {
	  ParseAddress(sTmp,
	               Latest.email, sizeof(Latest.email),
	               Latest.from, sizeof(Latest.from));
  }
  else if(!_strnicmp ("lines:", line, 6))
  {
    Latest.lines = atoi(sTmp);
  }

  else if(!_strnicmp ("newsgroups:", line, 11))
  {
    mylstrncpy(Latest.newsgroups, sTmp, sizeof(Latest.newsgroups));
  }

  else if(!_strnicmp ("message-id:", line, 11))
  {
    copy_message_id_with_frob(Latest.message_id, sTmp);
  }
}


//   Build a list of frobbed references
void build_ref_list(char*dest, const char*src)
{
  char sRetval[HEADER_FROBREFLIST_LENGTH + HEADER_MESSAGE_ID_LENGTH + 2];
  char sTmpMsgId[HEADER_MESSAGE_ID_LENGTH];
  char*start;

  dest[0] = 0;
  if(src[0])
  {
    sRetval[0] = 0;
    start = strchr(src, '<');
    while(start && strlen(sRetval) < HEADER_FROBREFLIST_LENGTH)
    {
      copy_message_id_with_frob(sTmpMsgId, start);
      strcat(sRetval, sTmpMsgId);
      strcat(sRetval, " ");
      start = strchr(++start, '<');
    }
    mylstrncpy(dest, sRetval, HEADER_FROBREFLIST_LENGTH);
  }
}



/*-- function DoCommState ----------------------------------------------
 *
 *  Function to implement an FSA to process incoming lines from
 *  the server.
 *  This function is called once for each line from the server.
 *
 *    Entry    CommLineIn  is a zero-terminated line received from
 *                         the server.
 *             CommState   is the current state of the FSA.
 */
void
DoCommState ()
{
  TypLine far *LinePtr;
  TypBlock far *BlockPtr;
  HANDLE hBlock;
  unsigned int Offset;
  TypLineID MyLineID;
  int retcode;
  int found;
  static unsigned long first, last;
  unsigned long estnum, artnum;
  long syncnum;
  int mylen;
  BOOL done = FALSE;
  BOOL DlgStatus = FALSE;
  BOOL dolist, do_authinfo;
  static char group[MAXINTERNALLINE];
  char mybuf[MAXINTERNALLINE];
  char mybuf2[MAXINTERNALLINE];
  char far *lpsz;
  HANDLE header_handle;
  HANDLE thread_handle;
  header_p headers;
  header_p header;
  TypGroup far *GroupDoc;
  TypRange *RangePtr;
  static int PrevState = ST_NONE;
  char szStatBarText[MAXSTATBARTEXT];
  TypDoc *statDoc;

  /* CommDoc is !NULL if retrieving group list, article headers or articles */
  /* CommDecoding is true if retrieving article in decode mode (not to a doc) */
  /* PostEdit !NULL if we are posting (this is from an edit, no doc involved) */
  if (CommDoc || CommDecoding || SendingPost) {
	if (CommState != PrevState) {
	  PrevState = CommState;
	  statDoc = CommDoc ? CommDoc : &NetDoc;
	  if (LoadString (hInst, CommState, szStatBarText, MAXSTATBARTEXT) != 0)
		SetStatbarText (statDoc->hWndFrame, szStatBarText, statDoc, TRUE, TRUE);
	}

	switch (CommState) {
	case ST_NONE:
	  break;

	case ST_ESTABLISH_COMM:
	  if (!sscanf (CommLineIn, "%u", &retcode))
		break;
	  /* check for innd, send 'mode reader' command */
	  /* this is only necessary in unusual cases... */
	  /* ... at least until someone ports INN to NT 8^) */
	  if (strstr (CommLineIn, "InterNetNews") &&
	      !strstr (CommLineIn, "NNRP")) {
	    PutCommLine ("mode reader");
	    break;
	  }
	  
	  if (retcode == 200 || retcode == 201) {	/* was 500 from induced error */
		CommBusy = TRUE;
		do_authinfo = FALSE;
		Authenticated = FALSE;
		if (strlen (NNTPUserName)) {
		  /* We have the AUTHINFO username.  Do we have the password? */
		  if (!strlen (NNTPPasswordEncrypted)) {
			/* Get the news server user password from the user */
			if (DialogBox (hInst, (LPCSTR) "WinVnComm", NetDoc.hDocWnd, (DLGPROC) lpfnWinVnCommDlg)
				&& strlen (NNTPPasswordEncrypted)) {
			  do_authinfo = TRUE;
			}
		  }
		  else {
			do_authinfo = TRUE;
		  }
		}
		if (do_authinfo) {
		  sprintf (mybuf, "AUTHINFO user %s", NNTPUserName);
		  CommState = ST_CHECK_AUTHINFO_USERNAME;
		  PutCommLine (mybuf);
		}
		else {
		  goto End_Authinfo;
		}

	  }
	  else {
		/*      MRRCloseComm (); */
		/*        PostQuitMessage (0); */
		Disconnect ();
		InvalidateRect (NetDoc.hDocWnd, NULL, TRUE);
		MessageBox (NetDoc.hDocWnd, CommLineIn, "Access Problem", MB_OK);
	  }
	  break;

	case ST_CHECK_AUTHINFO_USERNAME:
	  retcode = 0;
	  sscanf (CommLineIn, "%u", &retcode);
	  if (!retcode)
		break;
	  if (retcode >= 500) {
		Disconnect ();
		InvalidateRect (NetDoc.hDocWnd, NULL, TRUE);
		MessageBox (NetDoc.hDocWnd,
		  "Error authorizing your username with the News Server.\n"
		  "\n"
		  "Try an anonymous connection by removing your username/password from the\n"
		  "\"Config->Communications...\" dialog box",
		  "WinVN", MB_OK | MB_ICONHAND);
		break;
	  }
	  MRRDecrypt (NNTPPasswordEncrypted, (unsigned char *) mybuf2, MAXINTERNALLINE);
	  sprintf (mybuf, "AUTHINFO pass %s", mybuf2);
	  CommState = ST_CHECK_AUTHINFO_PASSWORD;
	  PutCommLine (mybuf);
	  break;

	case ST_CHECK_AUTHINFO_PASSWORD:
	  retcode = 0;
	  if (sscanf (CommLineIn, "%u", &retcode) <= 0)
		break;
	  if (retcode < 200 || retcode > 299) {
		Disconnect ();
		InvalidateRect (NetDoc.hDocWnd, NULL, TRUE);
		sprintf (mybuf,
		  "Error authorizing your password with the News Server:\n"
          "\n"
		  "  %s.\n"
          "\n"
		  "Try an anonymous connection by removing your username/password from the\n"
		  "\"Config->Communications...\" dialog box.", CommLineIn);
		MessageBox (NetDoc.hDocWnd, mybuf, "WinVN", MB_OK | MB_ICONHAND);
		break;
	  }
	  else {
		/* Authentication was successful.  Store this fact, and the name under
		 * which the user was authenticated.
		 */
		Authenticated = TRUE;
		strntcpy (AuthenticatedName, NNTPUserName, MAXNNTPSIZE - 1);
	  }
	  goto End_Authinfo;


	case ST_END_AUTHINFO:
	End_Authinfo:;
	  /* allow exit now... */
	  SendMessage (NetDoc.hWndFrame, WM_MYINITMENU, (WPARAM) 0, (LPARAM) 0);

	  /* now check for the XOVER command */
	  CommState = ST_XOVER_CHECK;
	  PutCommLine ("XOVER");
	  break;

	case ST_XOVER_CHECK:
	  retcode = 0;
	  sscanf (CommLineIn, "%u", &retcode);
	  if (retcode == 412 && !force_xhdr)	/* 412 == 'not in a newsgroup' */
		xoverp = 1;
	  else						/* 500 == 'command not understood' */
		xoverp = 0;

	  dolist = DoList;
	  if (dolist == ID_DOLIST_ASK - ID_DOLIST_BASE)
		if (MessageBox (NetDoc.hDocWnd, "Request the latest group list from server?\n(This can be time consuming)",
						"Request LIST from server?", MB_ICONQUESTION | MB_YESNO | MB_DEFBUTTON2) == IDNO)
		  dolist = 0;

	  /* may have lost connection while dialog box up... */
	  if (Initializing == INIT_NOT_CONNECTED) {
	  	break;
	  }
	  if (dolist) {
		StartList ();
		did_list = 1;
	  }
	  else {
		did_list = 0;
		CommState = ST_NONE;
		CommBusy = FALSE;
		Initializing = INIT_READY;
		SetStatbarText (CommDoc->hWndFrame, "", CommDoc, TRUE, TRUE);
		InvalidateRect (NetDoc.hDocWnd, NULL, FALSE);
	  }
	  InvalidateRect (NetDoc.hDocWnd, NULL, FALSE);
	  break;

	case ST_LIST_RESP:
	  retcode = 0;
	  sscanf (CommLineIn, "%u", &retcode);
	  if (retcode != 215) {
		check_server_code (retcode);
		break;
	  }

	  CommState = ST_LIST_GROUPLINE;
	  RcvLineCount = 0;
	  break;

	case ST_LIST_GROUPLINE:
	  if (strcmp (CommLineIn, ".") == 0) {
		CommState = ST_NONE;
		CommBusy = FALSE;
		Initializing = INIT_READY;
		SetStatbarText (CommDoc->hWndFrame, "", CommDoc, TRUE, TRUE);
		InvalidateRect (NetDoc.hDocWnd, NULL, FALSE);

		ProcEndList ();
	  }
	  else if (!EnableGroupFilter || MatchFilter (CommLineIn, GroupFilter)) {
		ProcListLine ((unsigned char *) CommLineIn);
	  }
	  break;

	case ST_GROUP_RESP:
	  retcode = 0;
	  sscanf (CommLineIn, "%u", &retcode);
	  switch (retcode) {
	  case 411:
		/* abort the fledgling group window */
		DestroyWindow (CommDoc->hWndFrame);
		CommBusy = FALSE;
		CommState = ST_NONE;
		MessageBox (NetDoc.hDocWnd, "No Such Newsgroup", "Error", MB_OK | MB_ICONHAND);
		return;
		break;
	  case 502:
		/* abort the fledgling group window */
		DestroyWindow (CommDoc->hWndFrame);
		CommBusy = FALSE;
		CommState = ST_NONE;
		MessageBox (NetDoc.hDocWnd, "Restricted Access", "WinVN", MB_OK | MB_ICONHAND);
		return;
		break;
	  default:
		if (check_server_code (retcode))
		  return;
		break;
	  }

	  sscanf (CommLineIn, "%u %lu %lu %lu %s", &retcode, &estnum, &first, &last, group);

	  LockLine (CommDoc->hParentBlock, CommDoc->ParentOffset,
				CommDoc->ParentLineID, &BlockPtr, &LinePtr);
	  GroupDoc = GetGroup(LinePtr);
	  RangePtr = GetRangePtr(GroupDoc);
	  GroupDoc->Determined = TRUE;
	  GroupDoc->ServerLast = last;
	  GroupDoc->ServerFirst = first;
	  GroupDoc->ServerEstNum = estnum;

	  /* we don't want to grab *that* many! */
	  if (estnum >= article_threshold) {
		if (!ShowUnreadOnly) {
		  arts_to_retrieve = estnum;
		  if (GroupDoc->nRanges)
		    est_num_unread = CalcNumUnread(GroupDoc);
		  else
			est_num_unread = arts_to_retrieve;

		  DlgStatus = DialogBox (hInst, (LPCSTR) "THRESHOLD", CommDoc->hDocWnd, (DLGPROC) lpfnWinVnThresholdDlg);
		  if (CommDoc && (DlgStatus == FALSE)) {
			DestroyWindow (CommDoc->hWndFrame);
			CommBusy = FALSE;
			CommState = ST_NONE;
			GroupDoc->ServerFirst = GroupDoc->ServerLast;
			GroupDoc->ServerEstNum = estnum;
			return;
		  }
		}
		else
		  arts_to_retrieve = ID_THRESHOLD_UNREAD;

		if ((DlgStatus == TRUE) &&
		    (last >= arts_to_retrieve) &&
		    ((last - arts_to_retrieve) > first)) {
		  first = (last - arts_to_retrieve) + 1;
		}
		else if (DlgStatus == ID_THRESHOLD_ALL)		/* they clicked 'all of them' */
		  arts_to_retrieve = estnum;
		/* added by jlg */
		else if ((DlgStatus == ID_THRESHOLD_UNREAD)		/* they clicked 'unseen' */
				 ||(ShowUnreadOnly)) {
		  if (GroupDoc->nRanges) {

      if (RangePtr[GroupDoc->nRanges - 1].Last <= last)
        first = max (first, (unsigned long) RangePtr[0].Last + 1);

			arts_to_retrieve = (last - first) + 1;
			if (arts_to_retrieve < min_to_retrieve) {
			  arts_to_retrieve = min_to_retrieve;
			  if (last < min_to_retrieve)
			     first = 1;
			  else
			     first = last - (min_to_retrieve - 1);
			}
			if (arts_to_retrieve == 0) {
			  /* abort the fledgling group window */
			  DestroyWindow (CommDoc->hWndFrame);
			  CommBusy = FALSE;
			  CommState = ST_NONE;
			  MessageBox (NetDoc.hDocWnd, "No Articles to Retrieve", "WinVN", MB_OK | MB_ICONHAND);
			  return;
			}
		  }
		  else
			arts_to_retrieve = estnum;
		}
	  }
	  else {
		if (estnum > 0)
		  arts_to_retrieve = estnum;
		else {
		  /* abort the fledgling group window */
		  DestroyWindow (CommDoc->hWndFrame);
		  CommBusy = FALSE;
		  CommState = ST_NONE;
		  GroupDoc->ServerFirst = GroupDoc->ServerLast;
		  GroupDoc->ServerEstNum = 0;
		  MessageBox (NetDoc.hDocWnd, "Empty Newsgroup", "WinVN", MB_OK | MB_ICONHAND);
		  return;
		}
	  }

	  CommDoc->TotalLines = (unsigned int) arts_to_retrieve;

	  if (arts_to_retrieve > 0) {
		header_handle =
		  GlobalAlloc (GMEM_MOVEABLE, (long)
					   ((sizeof (TypHeader)) *
						arts_to_retrieve) + sizeof (thread_array *));

		/* allocate space for the header_array index table */
		thread_handle =
		  GlobalAlloc (GMEM_MOVEABLE,
					   (long) ((sizeof (long)) * arts_to_retrieve));

		GroupDoc->header_handle = header_handle;
		GroupDoc->thread_handle = thread_handle;

	  }

	  /* stick nulls and 0's, etc.. in case display code get mis-threaded */
	  initialize_header_array (header_handle, thread_handle, arts_to_retrieve);

	  GroupDoc = GetGroup(LinePtr);
	  GroupDoc->ServerEstNum = estnum;
	  GroupDoc->ServerFirst = first;
	  GroupDoc->Threaded = xoverp || threadp;
	  GlobalUnlock (BlockPtr->hCurBlock);

	  if (xoverp) {
		mylen = sprintf (mybuf, "XOVER %ld-%ld", first, last);
		CommState = ST_XOVER_START;
		PutCommLine (mybuf);
	  }
	  else {
		mylen = sprintf (mybuf, "XHDR from %ld-%ld", first, last);
		CommState = ST_XHDR_FROM_START;
		PutCommLine (mybuf);
	  }

	  break;

	  /* use XOVER if its available */
	case ST_XOVER_START:
	  retcode = 0;
		ClearLatestInfo();
		
	  sscanf (CommLineIn, "%d", &retcode);
	  if (retcode == 224) {
		CommState = ST_XOVER_DATA;
		CommDoc->ActiveLines = 0;
	  }
	  else {
		mylen = sprintf (mybuf, "XHDR from %ld-%ld", first, last);
		CommState = ST_XHDR_FROM_START;
		PutCommLine (mybuf);
	  }
	  break;

	case ST_XOVER_DATA:
	  if (strcmp (CommLineIn, ".") == 0) {
		/* this is a yuck way to do this */
		CommState = ST_IN_GROUP;
		CommBusy = FALSE;
		finish_header_retrieval();
		SetStatbarText (CommDoc->hWndFrame, "", CommDoc, TRUE, TRUE);
	  }
	  else if (*CommLineIn) {	/* avoid blank XOVER lines (peterk@borland.com) */
		char *this_hop, *next_hop;
		char *best_reference;

		LockLine (CommDoc->hParentBlock, CommDoc->ParentOffset,
				  CommDoc->ParentLineID, &BlockPtr, &LinePtr);
		GroupDoc = GetGroup(LinePtr);
		header_handle = GroupDoc->header_handle;
		thread_handle = GroupDoc->thread_handle;
		GlobalUnlock (BlockPtr->hCurBlock);

		/* Lock the header data */
		headers = lock_headers (header_handle, thread_handle);
		header = header_elt (headers, CommDoc->ActiveLines);
		this_hop = CommLineIn;

		/* article number */
		next_hop = strchr (this_hop, '\t');
		*(next_hop++) = (char) NULL;
		header->number = atol (this_hop);

		/* subject */
		this_hop = next_hop;
		next_hop = strchr (this_hop, '\t');
		*(next_hop++) = (char) NULL;

		mylstrncpy (header->subject, this_hop, HEADER_SUBJECT_LENGTH);
		CommDoc->LongestLine = max (CommDoc->LongestLine,
									ARTICLE_SUBJECT_OFFSET +
									(unsigned) lstrlen (header->subject));
		/* author */
		this_hop = next_hop;
		next_hop = strchr (this_hop, '\t');
		*(next_hop++) = (char) NULL;

		ParseAddress (this_hop,
					  AddressString, MAXDIALOGSTRING,
					  NameString, MAXDIALOGSTRING);

		if (FullNameFrom)
		  mylstrncpy (header->from, NameString, HEADER_FROM_LENGTH);
		else
		  mylstrncpy (header->from, this_hop, HEADER_FROM_LENGTH);
    mylstrncpy(header->email, AddressString, HEADER_EMAIL_LENGTH);

		/* date */
		this_hop = next_hop;
		next_hop = strchr (this_hop, '\t');
		*(next_hop++) = (char) NULL;

		header->date = parse_usenet_date (this_hop);

		/* message-id */
		this_hop = next_hop;
		next_hop = strchr (this_hop, '\t');
		*(next_hop++) = (char) NULL;

		copy_message_id_with_frob (header->message_id, this_hop+1);

		/* references */
		this_hop = next_hop;
		next_hop = strchr (this_hop, '\t');
		*(next_hop++) = (char) NULL;

		build_ref_list(header->frob_ref_list, this_hop);
		best_reference = get_best_reference (this_hop);
		if (best_reference) {
		  copy_message_id_with_frob (header->best_ref, best_reference);
		}

		/* bytes (ignored) */
		this_hop = next_hop;
		next_hop = strchr (this_hop, '\t');
		*(next_hop++) = (char) NULL;

		/* lines (last one doesn't have to have the tab */
		this_hop = next_hop;
		header->lines = atoi (this_hop);

		/* set other header fields */
		header->Selected = FALSE;
		header->ArtDoc = (TypDoc *) NULL;
		header->Seen = WasArtSeen (header->number, GroupDoc);

		unlock_headers (header_handle, thread_handle);

		CommDoc->ActiveLines++;

		update_window_title (CommDoc->hWndFrame, group,
							 RcvLineCount++,
							 CommDoc->TotalLines);
	  }

	  break;


	  /* The next few cases handle retrieval of XHDR information for display */
	  /* in the group window.  If you change the number of XHDR's retrieved */
	  /* (such as adding 'XHDR References' back into the state machine), you */
	  /* need to reflect that change in the variable total_xhdrs. */

	  /* the current flow is FROM -> DATE -> NEWSGROUPS -> LINES -> SUBJECT */
	  /* (threadp) FROM -> DATE -> NEWSGROUPS -> LINES -> REF -> ID -> SUBJECT */

	  /* this will now be done dynamically, depending on the state of */
	  /* the 'threadp' variable */

	case ST_XHDR_FROM_START:
	  retcode = 0;
	  sscanf (CommLineIn, "%d", &retcode);
	  total_xhdrs = threadp ? 7 : 5;	/* we do this here to allow */
	                                  /* mid-session change-of-mind  */
	  if (retcode < 100)
		break;
	  CommState = ST_XHDR_FROM_DATA;
	  CommDoc->ActiveLines = 0;
		ClearLatestInfo();
	  break;

	case ST_XHDR_FROM_DATA:
	  if (strcmp (CommLineIn, ".") == 0) {
		LockLine (CommDoc->hParentBlock, CommDoc->ParentOffset,
				  CommDoc->ParentLineID, &BlockPtr, &LinePtr);

		GroupDoc = GetGroup(LinePtr);
		GroupDoc->total_headers = CommDoc->ActiveLines;

		first = GroupDoc->ServerFirst;
		last = GroupDoc->ServerLast;

		GlobalUnlock (BlockPtr->hCurBlock);
		CommDoc->ActiveLines = 0;

		/* Now ask for the date lines */
		mylen = sprintf (mybuf, "XHDR date %ld-%ld", first, last);
		CommState = ST_XHDR_DATE_START;
		PutCommLine (mybuf);
	  }
	  else {
		/*      char neat_from [80]; */
		/* Access the Group struct, get HANDLE for header data */
		LockLine (CommDoc->hParentBlock, CommDoc->ParentOffset,
				  CommDoc->ParentLineID, &BlockPtr, &LinePtr);

		GroupDoc = GetGroup(LinePtr);
		header_handle = GroupDoc->header_handle;
		thread_handle = GroupDoc->thread_handle;
		GlobalUnlock (BlockPtr->hCurBlock);

		/* Lock the header data */
		headers = lock_headers (header_handle, thread_handle);
		sscanf (CommLineIn, "%ld", &artnum);
		header = header_elt (headers, CommDoc->ActiveLines);
		header->number = artnum;

		/* now use some of our nice formatting of email addresses */
		ParseAddress (get_xhdr_line (CommLineIn),
					  AddressString, MAXDIALOGSTRING,
					  NameString, MAXDIALOGSTRING);

		/* copy that into headers[].from */
		if (FullNameFrom)
		  mylstrncpy (header->from, NameString, HEADER_FROM_LENGTH);
		else
		  mylstrncpy (header->from, AddressString, HEADER_FROM_LENGTH);
    mylstrncpy(header->email, AddressString, HEADER_FROM_LENGTH);

		unlock_headers (header_handle, thread_handle);
		CommDoc->ActiveLines++;
		update_window_title (CommDoc->hWndFrame, group,
							 RcvLineCount++,
							 CommDoc->TotalLines * total_xhdrs);
	  }

	  break;

	case ST_XHDR_DATE_START:
	  retcode = 0;
	  sscanf (CommLineIn, "%d", &retcode);
	  if (check_server_code (retcode))
		break;
	  CommState = ST_XHDR_DATE_DATA;
	  CommDoc->ActiveLines = 0;
	  break;

	case ST_XHDR_DATE_DATA:
	  if ((strcmp (CommLineIn, ".") == 0) &&
		  LockLine (CommDoc->hParentBlock, CommDoc->ParentOffset,
				    CommDoc->ParentLineID, &BlockPtr, &LinePtr))	 {

		GroupDoc = GetGroup(LinePtr);
		GroupDoc->total_headers = CommDoc->ActiveLines;
			
		first = GroupDoc->ServerFirst;
		last = GroupDoc->ServerLast;
		GlobalUnlock (BlockPtr->hCurBlock);
		CommDoc->ActiveLines = 0;

			/* Now ask for the newsgroups */
		mylen = sprintf (mybuf, "XHDR newsgroups %ld-%ld", first, last);
		CommState = ST_XHDR_NEWSGROUPS_START;
		PutCommLine (mybuf);
	  }
	  else {

		/* Access the Group struct, get HANDLE for header data */
		if (LockLine (CommDoc->hParentBlock, CommDoc->ParentOffset,
				  	  CommDoc->ParentLineID, &BlockPtr, &LinePtr)) {
		  GroupDoc = GetGroup(LinePtr);
		  header_handle = GroupDoc->header_handle;
		  thread_handle = GroupDoc->thread_handle;
		  GlobalUnlock (BlockPtr->hCurBlock);

		  /* Lock the header data */
		  headers = lock_headers (header_handle, thread_handle);
	  	  syncnum = sync_artnum (atol (CommLineIn),
		  			     (header_elt (headers, CommDoc->ActiveLines))->number,
							     headers,
							     GroupDoc);
		  if (syncnum >= 0)
		   (header_elt (headers, syncnum))->date
			  = parse_usenet_date (get_xhdr_line (CommLineIn));

		  unlock_headers (header_handle, thread_handle);

		  CommDoc->ActiveLines++;
	  	  update_window_title (CommDoc->hWndFrame, group,
							   RcvLineCount++,
							   CommDoc->TotalLines * total_xhdrs);
		}
	  }

	  break;

	case ST_XHDR_NEWSGROUPS_START:
    retcode = 0;
    sscanf(CommLineIn, "%d", &retcode);
    if(check_server_code(retcode))
      break;
    CommState = ST_XHDR_NEWSGROUPS_DATA;
    CommDoc->ActiveLines = 0;
    break;

	case ST_XHDR_NEWSGROUPS_DATA:
    if((strcmp(CommLineIn, ".") == 0) &&
       (LockLine(CommDoc->hParentBlock, CommDoc->ParentOffset,
                 CommDoc->ParentLineID, &BlockPtr, &LinePtr)))
    {
      GroupDoc = GetGroup(LinePtr);
      GroupDoc->total_headers = CommDoc->ActiveLines;
      first = GroupDoc->ServerFirst;
      last = GroupDoc->ServerLast;
      GlobalUnlock (BlockPtr->hCurBlock);
      CommDoc->ActiveLines = 0;

      /* Now ask for the #of lines */
      mylen = sprintf (mybuf, "XHDR lines %ld-%ld", first, last);
      CommState = ST_XHDR_LINES_START;
      PutCommLine (mybuf);
    }
    else
    {
      /* Access the Group struct, get HANDLE for header data */
      if(LockLine(CommDoc->hParentBlock, CommDoc->ParentOffset,
         CommDoc->ParentLineID, &BlockPtr, &LinePtr))
      {
        GroupDoc = GetGroup(LinePtr);
        header_handle = GroupDoc->header_handle;
        thread_handle = GroupDoc->thread_handle;
        GlobalUnlock(BlockPtr->hCurBlock);

        /* Lock the header data */
        headers = lock_headers(header_handle, thread_handle);
        syncnum = sync_artnum(atol(CommLineIn),
                              (header_elt(headers, CommDoc->ActiveLines))->number,
                              headers, GroupDoc);
        if(syncnum >= 0)
        {
          header = header_elt (headers, syncnum);
          mylstrncpy(header->newsgroups,
                     get_xhdr_line(CommLineIn), HEADER_NEWSGROUPS_LENGTH);
//          strcpy(Latest.newsgroups, header->newsgroups);
        }
        unlock_headers(header_handle, thread_handle);

        CommDoc->ActiveLines++;
        update_window_title(CommDoc->hWndFrame, group,
                            RcvLineCount++, CommDoc->TotalLines * total_xhdrs);
      }
    }
    break;

	case ST_XHDR_LINES_START:
	  retcode = 0;
	  sscanf (CommLineIn, "%d", &retcode);
	  if (check_server_code (retcode))
		break;
	  CommState = ST_XHDR_LINES_DATA;
	  CommDoc->ActiveLines = 0;
	  break;

	case ST_XHDR_LINES_DATA:
	  if ((strcmp (CommLineIn, ".") == 0) &&
		  LockLine (CommDoc->hParentBlock, CommDoc->ParentOffset,
				    CommDoc->ParentLineID, &BlockPtr, &LinePtr))  {

		GroupDoc = GetGroup(LinePtr);
		GroupDoc->total_headers = CommDoc->ActiveLines;

		first = GroupDoc->ServerFirst;
		last = GroupDoc->ServerLast;

		GlobalUnlock (BlockPtr->hCurBlock);
		CommDoc->ActiveLines = 0;

		/* Check for threading option, if enabled, go to REF & ID */
		/* states first */

		if (threadp) {
		  CommState = ST_XHDR_REF_START;
		  mylen = sprintf (mybuf, "XHDR references %ld-%ld", first, last);
		  PutCommLine (mybuf);
		}
		else {
		  CommState = ST_XHDR_SUBJECT_START;
		  mylen = sprintf (mybuf, "XHDR subject %ld-%ld", first, last);
		  PutCommLine (mybuf);
		}
	  }

	  else {

		/* Access the Group struct, get HANDLE for header data */
		if (LockLine (CommDoc->hParentBlock, CommDoc->ParentOffset,
				  	  CommDoc->ParentLineID, &BlockPtr, &LinePtr)) {
		  GroupDoc = GetGroup(LinePtr);
		  header_handle = GroupDoc->header_handle;
		  thread_handle = GroupDoc->thread_handle;
	  	  GlobalUnlock (BlockPtr->hCurBlock);

		  /* Lock the header data */
		  headers = lock_headers (header_handle, thread_handle);

		  syncnum = sync_artnum (atol (CommLineIn),
					     (header_elt (headers, CommDoc->ActiveLines))->number,
							     headers,
							     GroupDoc);
		  if (syncnum >= 0)
		    sscanf (CommLineIn, "%ld %Fd", &artnum, &((header_elt (headers, syncnum))->lines));

		  unlock_headers (header_handle, thread_handle);
		  CommDoc->ActiveLines++;
		  update_window_title (CommDoc->hWndFrame, group,
							   RcvLineCount++,
							   CommDoc->TotalLines * total_xhdrs);
		}
	  }

	  break;

	case ST_XHDR_REF_START:
	  retcode = 0;
	  sscanf (CommLineIn, "%d", &retcode);
	  if (check_server_code (retcode))
		break;
	  CommState = ST_XHDR_REF_DATA;
	  CommDoc->ActiveLines = 0;
	  break;

	case ST_XHDR_REF_DATA:
	  if ((strcmp (CommLineIn, ".") == 0) &&
		  (LockLine (CommDoc->hParentBlock, CommDoc->ParentOffset,
				     CommDoc->ParentLineID, &BlockPtr, &LinePtr))) {

		GroupDoc = GetGroup(LinePtr);
		GroupDoc->total_headers = CommDoc->ActiveLines;
		first = GroupDoc->ServerFirst;
		last = GroupDoc->ServerLast;
		GlobalUnlock (BlockPtr->hCurBlock);
		CommDoc->ActiveLines = 0;

		/* Now ask for the message-id lines */
		mylen = sprintf (mybuf, "XHDR message-id %ld-%ld", first, last);
		CommState = ST_XHDR_MID_START;
		PutCommLine (mybuf);
	  }
	  else {
    header_p header;
    char temp_frob_ref_list[HEADER_FROBREFLIST_LENGTH];
		char far *refer;		/* , far * end,far * bracket1,far *bracket2; */
		/*      int bracket_len; */

		/* Access the Group struct, get HANDLE for header data */
		if (LockLine (CommDoc->hParentBlock, CommDoc->ParentOffset,
				      CommDoc->ParentLineID, &BlockPtr, &LinePtr)){
			GroupDoc = GetGroup(LinePtr);
			header_handle = GroupDoc->header_handle;
			thread_handle = GroupDoc->thread_handle;
			GlobalUnlock (BlockPtr->hCurBlock);

			/* Lock the header data */
			headers = lock_headers (header_handle, thread_handle);
      header = header_elt (headers, CommDoc->ActiveLines);

			/* for now, we only pay attention to first (whole) referral */
			refer = get_xhdr_line (CommLineIn);
      build_ref_list(temp_frob_ref_list, refer);
			refer = get_best_reference (refer);

			if (refer) {
		  	/* Patch to check for bad info from server JD 6/19/93 */
		  	syncnum = sync_artnum (atol (CommLineIn),
									 (header_elt (headers, CommDoc->ActiveLines))->number,
								 				headers, GroupDoc);
		  	if (syncnum >= 0) {
        header = header_elt (headers, syncnum);
        strcpy(header->frob_ref_list, temp_frob_ref_list);
				copy_message_id_with_frob (header->best_ref, refer);
		  	}
			}

			unlock_headers (header_handle, thread_handle);

			CommDoc->ActiveLines++;
			update_window_title (CommDoc->hWndFrame, group,
							 	RcvLineCount++,
							 	CommDoc->TotalLines * total_xhdrs);
			}

	  }

	  break;


	case ST_XHDR_MID_START:
	  retcode = 0;
	  sscanf (CommLineIn, "%d", &retcode);
	  if (check_server_code (retcode))
		break;
	  CommState = ST_XHDR_MID_DATA;
	  CommDoc->ActiveLines = 0;
	  break;

	case ST_XHDR_MID_DATA:
	  if ((strcmp (CommLineIn, ".") == 0) &&
		  (LockLine (CommDoc->hParentBlock, CommDoc->ParentOffset,
		             CommDoc->ParentLineID, &BlockPtr, &LinePtr))) {

		GroupDoc = GetGroup(LinePtr);
		GroupDoc->total_headers = CommDoc->ActiveLines;
		first = GroupDoc->ServerFirst;
		last = GroupDoc->ServerLast;
		GlobalUnlock (BlockPtr->hCurBlock);
		CommDoc->ActiveLines = 0;

		/* Now ask for the subject lines */
		mylen = sprintf (mybuf, "XHDR subject %ld-%ld", first, last);
		CommState = ST_XHDR_SUBJECT_START;
		PutCommLine (mybuf);
	  }
	  else {
		/* Access the Group struct, get HANDLE for header data */
		if (LockLine (CommDoc->hParentBlock, CommDoc->ParentOffset,
				      CommDoc->ParentLineID, &BlockPtr, &LinePtr)) {

			GroupDoc = GetGroup(LinePtr);
			header_handle = GroupDoc->header_handle;
			thread_handle = GroupDoc->thread_handle;
			GlobalUnlock (BlockPtr->hCurBlock);

		/* Lock the header data */
			headers = lock_headers (header_handle, thread_handle);
			syncnum = sync_artnum (atol (CommLineIn),
					   	(header_elt (headers, CommDoc->ActiveLines))->number,
							   	headers,
							   	GroupDoc);
			if (syncnum >= 0) {
		 	 copy_message_id_with_frob ((header_elt (headers, syncnum))->message_id,
										 (char far *) (get_xhdr_line (CommLineIn)+1));
			}
			unlock_headers (header_handle, thread_handle);

			CommDoc->ActiveLines++;
			update_window_title (CommDoc->hWndFrame, group,
								 RcvLineCount++,
								 CommDoc->TotalLines * total_xhdrs);
		  }

	  	}

	  break;


	case ST_XHDR_SUBJECT_START:
	  retcode = 0;
	  sscanf (CommLineIn, "%d", &retcode);
	  if (check_server_code (retcode))
		break;
	  CommState = ST_XHDR_SUBJECT_DATA;
	  break;

	case ST_XHDR_SUBJECT_DATA:

	  if (strcmp (CommLineIn, ".") == 0) {
		CommState = ST_IN_GROUP;
		CommBusy = FALSE;
		finish_header_retrieval();
		SetStatbarText (CommDoc->hWndFrame, "", CommDoc, TRUE, TRUE);
	  }
	  else {

		artnum = 0;
		sscanf (CommLineIn, "%ld", &artnum);
		if (artnum &&
		    (LockLine (CommDoc->hParentBlock, CommDoc->ParentOffset,
					   CommDoc->ParentLineID, &BlockPtr, &LinePtr))) {

		  GroupDoc = GetGroup(LinePtr);
		  header_handle = GroupDoc->header_handle;
		  thread_handle = GroupDoc->thread_handle;
		  headers = lock_headers (header_handle, thread_handle);

		  /* update the seen thing. */
		  syncnum = sync_artnum (atol (CommLineIn),
					   (header_elt (headers, CommDoc->ActiveLines))->number,
								 headers,
								 GroupDoc);
		  if (syncnum >= 0)
			header = header_elt (headers, syncnum);
		  else
			header = header_elt (headers, CommDoc->ActiveLines);

		  header->Selected = FALSE;
		  header->ArtDoc = (TypDoc *) NULL;
		  header->Seen = WasArtSeen (artnum, GetGroup(LinePtr));
		  UnlockLine (BlockPtr, LinePtr, &(CommDoc->hParentBlock),
					  &(CommDoc->ParentOffset), &(CommDoc->ParentLineID));
		  mylstrncpy (header->subject,
					  get_xhdr_line (CommLineIn), HEADER_SUBJECT_LENGTH);
//		  strcpy(Latest.subject, header->subject);
		  CommDoc->LongestLine = max (CommDoc->LongestLine,
									  ARTICLE_SUBJECT_OFFSET +
									  (unsigned) lstrlen (header->subject));

		  unlock_headers (header_handle, thread_handle);
		  CommDoc->ActiveLines++;
		  update_window_title (CommDoc->hWndFrame, group,
							   RcvLineCount++,
							   CommDoc->TotalLines * total_xhdrs);

		}
	  }

	  break;

	case ST_IN_GROUP:
	  break;

	case ST_ARTICLE_RESP:
	  retcode = 0;
	  sscanf (CommLineIn, "%d", &retcode);
	  if (check_server_code (retcode)) {
		if (CommDoc->hDocWnd)
		  DestroyWindow (CommDoc->hWndFrame);
		break;
	  }
	  ClearLatestInfo();
	  CommState = ST_REC_ARTICLE_HEADER;
	  UsingMIME = FALSE;		/* new article, init to no MIME */
	  break;

	case ST_REC_ARTICLE_HEADER:
//	  if (strcmp (CommLineIn, ".") == 0) {
//		;						/* error: empty article (end in middle of header) */
//	  }
	  if (IsBlankStr (CommLineIn)) {	/* headers end in blank line */
		CommState = ST_REC_ARTICLE;
	  }
	  if (!TrimHeader (CommLineIn))
	  {
  		WrapAddCommLineToDoc (CommLineIn);
      StoreHeaderInfo(CommLineIn);
	  }
	  break;

	case ST_REC_ARTICLE:
	  if (strcmp (CommLineIn, ".") != 0) {
		WrapAddCommLineToDoc (CommLineIn);
	  }
	  else {
	    if (CommDoc) {			/* Handle aborted condition JD 10/26/95 */
			/* article receive complete */
			CommState = ST_IN_GROUP;
			CommBusy = FALSE;

			if (CommDecoding) {
		 	 SendMessage (currentCoded->hParentWnd, (UINT) WM_COMMAND,
						   (WPARAM) ID_ARTICLE_RETRIEVE_COMPLETE, 0L);
		 	 break;
			}
			else {
		  	SendMessage (CommDoc->hWndFrame, (UINT) WM_COMMAND,
						   (WPARAM) ID_ARTICLE_RETRIEVE_COMPLETE, 0L);
			}

			if ((CommDoc->ParentDoc) &&
				(LockLine (CommDoc->ParentDoc->hParentBlock,
						  CommDoc->ParentDoc->ParentOffset,
						  CommDoc->ParentDoc->ParentLineID,
						  &BlockPtr, &LinePtr))) {

				GroupDoc = GetGroup(LinePtr);
				header_handle = GroupDoc->header_handle;
				thread_handle = GroupDoc->thread_handle;
				headers = lock_headers (header_handle, thread_handle);
				lpsz = (char far *) ((header_elt (headers, CommDoc->LastSeenLineID))->subject);
				unlock_headers (header_handle, thread_handle);

				SetStatbarText (CommDoc->hWndFrame, "", CommDoc, TRUE, TRUE);
				mylstrncpy (group, lpsz, MAXGROUPNAME);
				sprintf (mybuf, "%s (%u lines)", group, CommDoc->TotalLines);
				SetWindowText (CommDoc->hWndFrame, mybuf);
				InvalidateRect (CommDoc->hDocWnd, NULL, FALSE);
				GlobalUnlock (BlockPtr->hCurBlock);

			/* Skip to the first line of the text of the article
			 * and make sure it's visible on the screen.  This is
			 * so that the user doesn't have to have the first
			 * screen filled with a lengthy, worthless header.
			 *
			 * and save number of header lines (on display)
			 * for later (Bretherton)
			 */
				if (TopOfDoc (CommDoc, &BlockPtr, &LinePtr) &&
				    ScrollPastHeaders) {
		 		  found = FALSE;
		 		  do {
					lpsz = ((char far *) LinePtr + sizeof (TypLine) + sizeof (TypText));
					if (IsBlankStr (lpsz)) {
				 	 found = TRUE;
				  	CommDoc->HeaderLines = WhatLine (BlockPtr, LinePtr);
				 	 break;
					}
					if (!NextLine (&BlockPtr, &LinePtr))
			  		break;
			  	}
			  	while (!found);
			 	 NextLine (&BlockPtr, &LinePtr);

		 	 /* If the line is in the last screen's worth of lines, back
		 	  * up the pointer so it points to the first line of the last
		 	  * screen.
		  	 */
			  	if (found && CommDoc->TotalLines > CommDoc->ScYLines &&
				 	 !CommDoc->TopScLineID)
					AdjustTopSc (BlockPtr, LinePtr);

			  	UnlockLine (BlockPtr, LinePtr, &hBlock, &Offset, &MyLineID);
				}
	  		}
		  }
	  	}
	  break;

	case ST_POST_WAIT_PERMISSION:

	  /*      WndPost = getWndEdit(WndPosts,CommWnd,MAXPOSTWNDS) ; */
	  /*      found = (WndPost != NULL) ; */

	  retcode = 0;
	  sscanf (CommLineIn, "%u", &retcode);

	  SetStatbarText (NetDoc.hWndFrame, "", &NetDoc, TRUE, TRUE);
	  InvalidateRect (NetDoc.hDocWnd, NULL, TRUE);
	  if (retcode == 340) {
		DoSend (CONTINUE);
	  }
	  else {
		check_server_code (retcode);
		AbortSendPost (ComposeWnd->hWnd);
		DoSend (CONTINUE);		/* allow any sendmail to continue */
	  }
	  break;

	case ST_POST_WAIT_END:

	  /*      WndPost = getWndEdit(WndPosts,CommWnd,MAXPOSTWNDS) ; */
	  /*      found = (WndPost != NULL) ; */

	  /* no check for failure to find posting documents */
	  retcode = 0;
	  sscanf (CommLineIn, "%d", &retcode);
	  if (retcode == 240) {
		DoSend (CONTINUE);
	  }
	  else if (check_server_code (retcode)) {
		/* cut down on winvn mailing list torture */
		if (strcmp (CommLineIn,
					"441 Article not posted -- more included text than new text") == 0) {
		  MessageBox (NetDoc.hDocWnd,
					  "Your news server has rejected\n"
					  "the article because it contains\n"
					  "more quoted lines than new.\n"
					  "You can either:\n"
					  "1) Rephrase your article with fewer\n"
					  "       quotations\n"
					  "2) Use a character other than '>' to\n"
					  "       indicate quoted passages, or\n"
					  "3) send email to 'usenet' on your news\n"
					  "       server and ask them to rebuild\n"
					  "       INN with CHECK_INCLUDED_TEXT\n"
					  "       set to DONT.",
					  "WinVN", MB_OK | MB_ICONHAND);
		}
		
		/*
		 * if we have an error, and did not lose the connection, abort send.
		 * (if connection was lost the send was already aborted)
		 */

		if (Initializing != INIT_NOT_CONNECTED) {
		  AbortSendPost (ComposeWnd->hWnd);
		  DoSend (CONTINUE);	/* allow any sendmail to continue */
		}
	  }
	  break;

	  /* the following code is for an MRR-hacked nntp server */

	case ST_GROUP_REJOIN:
	  CommState = ST_ARTICLE_RESP;
	  break;
	}
  }
}

BOOL
isLineQuotation (char *textptr)
{
  char *loc;
  loc = (char*) memchr (textptr, QuoteLineInd, 2);
  if (!loc)
	loc = (char*) memchr (textptr, '|', 2);
  if (!loc)
	loc = (char*) memchr (textptr, ':', 2);
  return (loc != NULL);
}


/*-- function AddCommLineToDoc ---------------------------------------
 *  Adds the given line to the comm doc, wrapping if necessary
 *  uses AddCommLineToDocHelp
 */
void
AddCommLineToDoc (char *line)
{
  TypLine far *LinePtr;
  TypBlock far *BlockPtr;
  char *cptr, *cdest;
  int mylen;
  unsigned int col, maxlen;
  char artline[MAXHEADERLINE];
  int PercentDone;

  if (CommState == ST_REC_ARTICLE_HEADER) {
  	maxlen = MAXHEADERLINE;
  } else {
  	maxlen = MAXINTERNALLINE;
  }

  /* Copy this line into an image of a textblock line,
   * expanding tabs.
   */
  cptr = line;
  cdest = artline + sizeof (TypLine) + sizeof (TypText);
  for (col = 0;
  *cptr && col < (maxlen - 3 * sizeof (TypLine) - sizeof (TypText));
	   cptr++) {
	if (*cptr == '\t') {
	  do {
		*(cdest++) = ' ';
	  }
	  while (++col & 7);
	}
	else {
	  *(cdest++) = *cptr;
	  col++;
	}
  }
  *(cdest++) = '\0';

  ((TypLine *) artline)->LineID = NextLineID++;
  if (LockLine (CommDoc->hCurAddBlock, CommDoc->AddOffset, 
                CommDoc->AddLineID, &BlockPtr, &LinePtr)) {
  	mylen = (cdest - artline) + sizeof (int);

  // changed by Holger.Liebig@mch.sni.de to have correct
  // allignment on MIPS processors.
  // was:  mylen += mylen % 2;
  	if (mylen % sizeof(int)){
    	 mylen += sizeof(int) - (mylen % sizeof(int));
  	}

  	((TypText *) (artline + sizeof (TypLine)))->NameLen =
		(cdest - 1) - (artline + sizeof (TypLine) + sizeof (TypText));
  	((TypLine *) artline)->length = mylen;
  	((TypLine *) artline)->active = TRUE;
  	*((int *) (artline + mylen - sizeof (int))) = mylen;
  	AddLine ((TypLine *) artline, &BlockPtr, &LinePtr);
  	CommDoc->LongestLine = max (CommDoc->LongestLine, (unsigned int) col);
  	CommDoc->ActiveLines++;
  	UnlockLine (BlockPtr, LinePtr, &(CommDoc->hCurAddBlock),
			  	&(CommDoc->AddOffset), &(CommDoc->AddLineID));
	}

  if (CommDoc->CountedLines > 0) {
    PercentDone = MulDiv(CommDoc->ActiveLines, 100, CommDoc->CountedLines);
    SetStatbarPercent(CommDoc->hWndFrame, (int) PercentDone, CommDoc, TRUE);
  }

  if ((CommDoc->TotalLines % UPDATE_ART_FREQ) == 0)
	InvalidateRect (CommDoc->hDocWnd, NULL, FALSE);
}

void
WrapAddCommLineToDoc (char *line)
{
  char *start, *end;
  int thisLen, lenToGo;
  char saveChar;

  /* special case for lines starting with '..' */
  if (strncmp (CommLineIn, "..", 2)) {
	start = CommLineIn;
  }
  else {
	start = CommLineIn + 1;
  }
  if (CommDecoding) {
	DecodeLine (currentCoded, start);
  }
  else if (!WrapIncomingArticleText || CommState == ST_REC_ARTICLE_HEADER || 
  			*start == '\0') {
	AddCommLineToDoc (start);
  }
  else {
	lenToGo = strlen (start);
	while (*start) {
	  thisLen = min (lenToGo, WrapIncomingArticleTextLength);
	  lenToGo -= thisLen;

	  end = start + thisLen;	/* save char at end of this line */
	  saveChar = *end;
	  *end = '\0';

	  AddCommLineToDoc (start);

	  *end = saveChar;			/* restore char at end of this line */
	  start = end;
	}
  }
}

/*-- function TrimHeader ---------------------------------------------
 *
 * If TrimHeaders is deactivated, or if we are decoding, then 
 * always return false (don't trim header).
 * else, if this header line should be skipped, return TRUE
 *
 * jsc 9/24/94
 */
BOOL
TrimHeader (char *line)
{
  if (TrimHeaders && !CommDecoding) {
	if (!IsBlankStr (line) &&
		_strnicmp ("to:", line, 3) &&
		_strnicmp ("subject:", line, 8) &&
		_strnicmp ("date:", line, 5) &&
		_strnicmp ("from:", line, 5) &&
		_strnicmp ("reply-to:", line, 9) &&
		_strnicmp ("newsgroups:", line, 11) &&
		_strnicmp ("references:", line, 11) &&
		_strnicmp ("summary:", line, 8) &&
		_strnicmp ("distribution:", line, 13) &&
		_strnicmp ("message-id", line, 10) &&	/* need this for article replies */
		_strnicmp ("keywords:", line, 9)) {
	  return TRUE;				/* matches none of above, so trim it */
	}
  }
  return FALSE;					/* don't trim it */
}

/*-- function WasArtSeen ---------------------------------------------
 *
 *  Determines whether (according to the information in a TypGroup entry)
 *  a given article number was seen.
 *
 *  Returns ART_SEEN iff the article has been seen.
 */
char
WasArtSeen(unsigned long ArtNum, TypGroup far *GroupPtr)
{
  TypRange far *RangePtr = GetRangePtr(GroupPtr);
  unsigned int nr;

  for (nr = 0; nr < GroupPtr->nRanges; nr++) {
	if (ArtNum >= (unsigned long) RangePtr->First &&
		ArtNum <= (unsigned long) RangePtr->Last) {
	  return (ART_SEEN);
	}
	else {
	  RangePtr++;
	}
  }
  return (ART_UNSEEN);
}

/*-- function CalcNumUnread ---------------------------------------------
 *
 *  Determines number of unseen articles in a group
 *
 *  jsc 11/12/94
 */
unsigned long 
CalcNumUnread(TypGroup far *GroupPtr)
{
	TypRange far *RangePtr = (TypRange far *) ((char far *)
						GroupPtr + RangeOffset (GroupPtr->NameLen));
	unsigned int i;
	unsigned long numUnseen, prev;
	
	if ((GroupPtr->nRanges == 1 && RangePtr->First == 0 && RangePtr->Last == 0) ||
		(unsigned long)(RangePtr[GroupPtr->nRanges - 1].Last) < GroupPtr->ServerFirst) {
		return min(GroupPtr->ServerEstNum, (GroupPtr->ServerLast - GroupPtr->ServerFirst + 1));
	}
	if (RangePtr->First != 1) {	/* this should never happen */
		RangePtr->First = 1;
	}

	prev = GroupPtr->ServerFirst;
	numUnseen = 0L;
	for (i = 0; i < GroupPtr->nRanges; i++) {
    	if ((unsigned long)RangePtr->First > prev) {
    		numUnseen += ((unsigned long)RangePtr->First - prev - 1);
    	}
    	if ((unsigned long)RangePtr->Last > prev) {
    		prev = (unsigned long)RangePtr->Last;
		}
    	if (i + 1 < GroupPtr->nRanges) {
    		RangePtr++;
    	}
	}

	if (GroupPtr->ServerLast > (unsigned long)RangePtr->Last) {
		numUnseen += (GroupPtr->ServerLast - (unsigned long)RangePtr->Last);
	} 
	
	return numUnseen;
}

/*--- function mylstrncmp -----------------------------------------------
 *
 *   Just like strncmp, except takes long pointers.
 */
int mylstrncmp(char far *ptr1, char far *ptr2, int len)
{
  for (; len--; ptr1++, ptr2++) {
	if (*ptr1 > *ptr2) {
	  return (1);
	}
	else if (*ptr1 < *ptr2) {
	  return (-1);
	}
  }
  return (0);
}

/*--- function mylstrncpy -----------------------------------------------
 *
 *   Just like strncpy, except takes long pointers.
 */
char far * mylstrncpy(char far *ptr1, const char far *ptr2, int len)
{
  char far *targ = ptr1;

  for (; --len && *ptr2; ptr1++, ptr2++) {
	*ptr1 = *ptr2;
  }
  *ptr1 = '\0';
  return (targ);
}

/* this is a temporary test... */
char far * mylstrcpy(char_p ptr1, char far *ptr2)
{
  char far *targ = ptr1;
  for (; *ptr2; ptr1++, ptr2++) {
	*ptr1 = *ptr2;
  }
  *ptr1 = '\0';
  return (targ);
}

#if 0
/*--- function lstrcmpnoblank ------------------------------------------
 *
 *   Like strcmp, except takes long pointers and also stops at
 *   the first blank.
 */
int
lstrcmpnoblank(char far **str1, char far **str2)
{
  register char far *s1 = *str1, far * s2 = *str2;

  for (; *s1 && *s2 && *s1 != ' ' && *s2 != ' '; s1++, s2++) {
	if (*s1 > *s2) {
	  return (1);
	}
	else if (*s1 < *s2) {
	  return (-1);
	}
  }
  if (*s1 == *s2) {
	return (0);
  }
  else if (*s1) {
	return (1);
  }
  else {
	return (-1);
  }
}
#endif

void
finish_header_retrieval ()
{
  char *sSortDef;
  TypLine far *LinePtr;
  TypBlock far *BlockPtr;
  TypGroup far *GroupDoc;
  HANDLE header_handle, thread_handle;
  thread_array thread_index;
  char mybuf[MAXINTERNALLINE];
  header_p headers, hp;
  uint32 i;

  /* release the mouse that is captured to the usenet window */
  ReleaseCapture ();

  CommDoc->TotalLines = CommDoc->ActiveLines;
  /* Disabled by MRR so that ActiveLines is the number of lines
   * we should display in the Group window.  Eventually, will
   * change it so that ActiveLines will count only unseen articles
   * if the user desires.
   */
  /* CommDoc->ActiveLines = 0; */
  /* Fetch this group's line in NetDoc so we can get the
   * group's name for the window's title bar.
   */
  if (LockLine (CommDoc->hParentBlock, CommDoc->ParentOffset,
			    CommDoc->ParentLineID, &BlockPtr, &LinePtr)) {

  	GroupDoc = GetGroup(LinePtr);
  	header_handle = GroupDoc->header_handle;
  	thread_handle = GroupDoc->thread_handle;
  	headers = lock_headers (header_handle, thread_handle);
  	thread_index = *((thread_array_p) ((char_p) headers - sizeof (char_p)));
    
    GroupDoc->total_headers = CommDoc->TotalLines;  // needed in ActOnArticles()

    if(bEnableArticleAction)
    {
      WVArticleAction aa;
      aa.ReadActions(CurrentGroup);  /* Get article action list */
      aa.ActOnArticles(GroupDoc, headers);  /* Perform article actions */
    }

    if (CommDoc->TotalLines > 0)
    {
      CommDoc->SelectedLines = 0;
      for(i = 0; i < CommDoc->TotalLines; i++)
      {
        hp = header_elt(headers, i);
        if(ART_SELECTED & hp->Selected)
          CommDoc->SelectedLines++;
      }
    }

//  	iSortOption = IDM_SORT_ARTNUM;
    sSortDef = STR_SORT_ARTNUM;
  	if (threadp) {
		SetWindowText (CommDoc->hWndFrame, "sorting headers...");
//    	iSortOption = IDM_SORT_THREADSUB; // we're testing this as the default.
      sSortDef = STR_SORT_THREADSUB;
  	}

//  	lstrcpy(szTmp,"G: ");
//  	lstrcat(szTmp, CurrentGroup);
//  	iSortOption = GetPrivateProfileInt(szTmp, "SortOption", iSortOption, szAppProFile);
    iSortOption = ReadSortOption(sSortDef, CurrentGroup);

/*  TRACE2("WVUtil: Newsgroup <%s>, iSortOption: %d\n", CurrentGroup, iSortOption); */
  	sort_by_option(headers, thread_index, threadp, CommDoc->TotalLines,
        	header_handle, thread_handle);

  	unlock_headers (header_handle, thread_handle);
  }

  sprintf (mybuf, "%s (%u articles)", CurrentGroup, CommDoc->TotalLines);
  SetWindowText (CommDoc->hWndFrame, mybuf);

  /* If we have information from NEWSRC on the highest-
   * numbered article previously seen, position the window
   * so the new articles can be seen without scrolling.
   */
  {
	unsigned int i;

	if (LockLine (CommDoc->hParentBlock, CommDoc->ParentOffset,
			      CommDoc->ParentLineID, &BlockPtr, &LinePtr)) {

	  /* inside the lock, can access the GroupStruct */
	  GroupDoc = GetGroup(LinePtr);
	  header_handle = GroupDoc->header_handle;
	  thread_handle = GroupDoc->thread_handle;
	  headers = lock_headers (header_handle, thread_handle);

  /* skip to FIRST unseen article (jsc) */
	  if (CommDoc->TotalLines > 0) {
	    for (i = 0;
		     (i < CommDoc->TotalLines && (header_elt (headers, i))->Seen);
		     i++);
	  }

	  CommDoc->TopLineOrd =
	    (CommDoc->TotalLines > i && CommDoc->ScYLines > 0 &&
	     CommDoc->TotalLines - i < CommDoc->ScYLines - 1) ? 
		   (CommDoc->TotalLines - CommDoc->ScYLines) + 1 : 
		     (i > 5 && CommDoc->TotalLines > CommDoc->ScYLines) ? i - 4 : 0; 
	
	  CommDoc->ActiveLineID = i;

	  CommDoc->ThumbTracking = FALSE;	/* if thumb tracking, release it */
	
	  unlock_headers (header_handle, thread_handle);
	  }
    }

  SendMessage (CommDoc->hWndFrame, (UINT) WM_COMMAND, (WPARAM) ID_RETRIEVE_COMPLETE, 0L);
  InvalidateRect (CommDoc->hDocWnd, NULL, TRUE);
  UpdateWindow (CommDoc->hDocWnd);
}

/*
 * Look through the MAIL or Post edits and return the edit with
 * matching window handle Consider - centralising initial window
 * location in wvmail and wndpost using a single array (save passing
 * structure and size into this module)
 *
 */

WndEdit *
getWndEdit (WndEdit * WndEdits, HWND hWnd, int numEntries)
{
  int ih;

  for (ih = 0; ih < numEntries; ih++) {
	if (WndEdits[ih].hWnd == hWnd) {
	  return &WndEdits[ih];
	}
  }

  /*MessageBox(0,"getWndEditFound Nothing","mrb debug", MB_OK | MB_ICONHAND); */

  return (WndEdit *) NULL;
}

WndEdit *
GetComposeWnd (HWND hWnd)
{
  WndEdit *compWnd;

  compWnd = getWndEdit (WndPosts, hWnd, MAXPOSTWNDS);
  if (!compWnd) {
	compWnd = getWndEdit (WndMails, hWnd, MAXMAILWNDS);
  }
  return compWnd;
}
/* ------------------------------------------------------------------------
 * Replace any white space at end of string with NULL's
 * JSC 11/1/93
 */
void
RemoveTrailingWhiteSpace (char *str)
{
  register int i;

  for (i = strlen (str) - 1; i > 0 && isspace (str[i]); i--)
	str[i] = '\0';
}

/*------------------------------------------------------------------------------
 * IsBlankStr
 * Returns true if the string is entirely whitespace, else false
 * JSC 12/6/93
 */
BOOL
IsBlankStr (char *temp)
{
  register char *ptr;
  for (ptr = temp; *ptr; ptr++)
	if (!isspace (*ptr))
	  return (FALSE);
  return (TRUE);
}

/*------------------------------------------------------------------------------
 * isnumber
 * Returns true if the string is a all digits
 * JSC 12/6/93
 */
BOOL
isnumber (char *str)
{
  char *ptr;

  for (ptr = str; *ptr != '\0'; ptr++)
	if (!isdigit (*ptr))
	  return (FALSE);
  return (TRUE);
}

/* ------------------------------------------------------------------------
 * strntcpy is strncpy, but also terminates the dest str
 * jsc 9/28/94
 */
char *
strntcpy (char *dest, char *src, int len)
{
  register char *d = dest;
  register char *s = src;
  register int l = 0;

  while (l < len && (*d++ = *s++)) {
	l++;
  }
  if (l == len) {
	*d = '\0';
  }
  return dest;
}


/* ------------------------------------------------------------------------
 *    Open the common font dialog
 *      Place resulting selection name and size in face,style and size
 *      Note: to select a printer font, send style as "Printer"
 *      printer font selection ignores any chosen style
 *      (JSC 1/9/94)
 */
BOOL
AskForFont (HWND hParentWnd, char *face, int *size, char *style)
{
  LOGFONT lf;
  CHOOSEFONT cf;
  HDC hDC;

  memset (&lf, 0, sizeof (LOGFONT));
  strcpy (lf.lfFaceName, face);
  /* convert points to logical units (1 pt = 1/72 inch) */
  /* For printer fonts, use ScreenYPixels here anyway - the choosefont */
  /* dialog appears to require the lfHeight to be in screen units */
  /* we will convert point size to PrinterUnits in InitPrinterFonts() */
  lf.lfHeight = -MulDiv (*size, ScreenYPixels, 72);

  memset (&cf, 0, sizeof (CHOOSEFONT));
  cf.lStructSize = sizeof (CHOOSEFONT);
  cf.hwndOwner = hParentWnd;
  cf.lpLogFont = &lf;
  if (!stricmp (style, "Printer")) {
	cf.nFontType = PRINTER_FONTTYPE;
	hDC = GetPrinterDC (hParentWnd);
	cf.hDC = hDC;
	cf.Flags = CF_PRINTERFONTS | CF_INITTOLOGFONTSTRUCT | CF_FORCEFONTEXIST;
  }
  else {
	cf.nFontType = SCREEN_FONTTYPE;
	cf.Flags = CF_SCREENFONTS | CF_INITTOLOGFONTSTRUCT | CF_USESTYLE | CF_FORCEFONTEXIST;
	cf.lpszStyle = style;
  }
  if (!ChooseFont (&cf))
	return (FAIL);

/*      if (!stricmp (style, "Printer"))      // commented out JD 6/17/94 */
  /*         ReleaseDC (NetDoc.hDocWnd, hDC);  */

/*      if (!stricmp (style, "Printer")) */
  /*         DeletePrinterDC (hDC); */

  *size = cf.iPointSize / 10;	/* iPointSize is in tenths of a point */

  strcpy (face, lf.lfFaceName);
  return (SUCCESS);
}

/* ------------------------------------------------------------------------
 *    Open the common color dialog
 *      (JSC 1/9/94)
 */
BOOL
AskForColor (HWND hParentWnd, COLORREF * color)
{
  CHOOSECOLOR cc;
  COLORREF nearC;
  HDC hDC;

  memset (&cc, 0, sizeof (CHOOSECOLOR));
  cc.lStructSize = sizeof (CHOOSECOLOR);
  cc.hwndOwner = hParentWnd;
  cc.rgbResult = *color;
  cc.lpCustColors = CustomColors;
  cc.Flags = CC_RGBINIT;

  if (!ChooseColor (&cc))
	return (FAIL);

  /* until we figure out how to deal with dithered colors, force */
  /* the color to the nearest physical color */
  hDC = GetDC (hParentWnd);
  nearC = GetNearestColor (hDC, cc.rgbResult);
  if (cc.rgbResult != nearC)
	MessageBox (hParentWnd, "WinVN does not currently support dithered (non-solid) colors.\nThe nearest physical solid color has been selected.",
				"Sorry", MB_OK | MB_ICONINFORMATION);
  *color = nearC;
  ReleaseDC (hParentWnd, hDC);
  return (SUCCESS);
}

/* ------------------------------------------------------------------------
 * This should be used instead of EM_GETHANDLE on global edit buf
 * Returns a string containing the contents of an edit wnd
 * It is the reponsibility of the caller to GlobalFreePtr the string
 * (JSC)
 */
char *
GetEditText (HWND hWndEdit)
{
  unsigned int size;
  char *newText;

#define EDIT_PAD 2

  SendMessage (hWndEdit, EM_FMTLINES, (WPARAM) WordWrap, 0L);

  size = (unsigned int) SendMessage (hWndEdit, WM_GETTEXTLENGTH, 0, 0L) + EDIT_PAD;

  if ((newText = (char *) GlobalAllocPtr (GMEM_MOVEABLE, size * sizeof (char))) == NULL) {
	MessageBox (hWndEdit, "Memory allocation failure", "Edit Text", MB_OK);
	return (NULL);
  }
  *newText = '\0';

  if (SendMessage (hWndEdit, WM_GETTEXT, size, (LPARAM) (LPCSTR) newText) != (long) (size - EDIT_PAD)) {
	MessageBox (hWndEdit, "Failed to get text", "Edit Text", MB_OK);
	return (NULL);
  }

  return (newText);
}
LRESULT
SetEditText (HWND hWndEdit, char *editMem)
{
  return (SendMessage (hWndEdit, WM_SETTEXT, 0, (LPARAM) (LPCSTR) editMem));
}

/* ------------------------------------------------------------------------
 *    Write an integer to the private profile
 */
BOOL
WritePrivateProfileInt (char far * lpAppName, char far * lpKeyName, int val, char far * lpProFile)
{
  char buf[20];

  itoa (val, buf, 10);
  return (WritePrivateProfileString (lpAppName, lpKeyName, buf, lpProFile));
}

/* ------------------------------------------------------------------------
 *    Get/Write an unsigned integers and longs to the private profile
 *      (JSC 1/8/94)
 */
BOOL
WritePrivateProfileUInt (char far * lpAppName, char far * lpKeyName, unsigned int val, char far * lpProFile)
{
  char buf[20];

  uitoa (val, buf, 10);
  return (WritePrivateProfileString (lpAppName, lpKeyName, buf, lpProFile));
}

unsigned int
GetPrivateProfileUInt (char far * lpAppName, char far * lpKeyName, unsigned int val, char far * lpProFile)
{
  char buf[20];

  GetPrivateProfileString (lpAppName, lpKeyName, "", buf, 20, lpProFile);

  if (*buf)
	return (atoui (buf));
  else
	return (val);
}

BOOL
WritePrivateProfileLong (char far * lpAppName, char far * lpKeyName, long val, char far * lpProFile)
{
  char buf[20];

  ltoa (val, buf, 10);
  return (WritePrivateProfileString (lpAppName, lpKeyName, buf, lpProFile));
}

long
GetPrivateProfileLong (char far * lpAppName, char far * lpKeyName, long val, char far * lpProFile)
{
  char buf[20];

  GetPrivateProfileString (lpAppName, lpKeyName, "", buf, 20, lpProFile);

  if (*buf)
	return (atol (buf));
  else
	return (val);
}
/* ------------------------------------------------------------------------
 *    Refresh Window functions
 *      Called after a font/color selection has changed to affect all
 *      windows of a certain type (group/article/status)
 *      (JSC 1/9/94)
 */
void
RefreshGroupWnds ()
{
  register int i;
  for (i = 0; i < MAXGROUPWNDS; i++)
	if (GroupDocs[i].InUse && GroupDocs[i].hDocWnd) {
	  SetHandleBkBrush (GroupDocs[i].hDocWnd, hListBackgroundBrush);
	  SendMessage (GroupDocs[i].hWndFrame, WM_SIZE, 0, 0L);
	  InvalidateRect (GroupDocs[i].hWndFrame, NULL, TRUE);
	  InvalidateRect (GroupDocs[i].hDocWnd, NULL, TRUE);
	  UpdateWindow (GroupDocs[i].hWndFrame);
	}
}

void
RefreshArticleWnds ()
{
  register int i;

  for (i = 0; i < MAXARTICLEWNDS; i++)
	if (ArticleDocs[i].InUse && ArticleDocs[i].hDocWnd) {
	  SetHandleBkBrush (ArticleDocs[i].hDocWnd, hArticleBackgroundBrush);
	  SendMessage (ArticleDocs[i].hWndFrame, WM_SIZE, 0, 0L);
	  InvalidateRect (ArticleDocs[i].hWndFrame, NULL, TRUE);
	  InvalidateRect (ArticleDocs[i].hDocWnd, NULL, TRUE);
	  UpdateWindow (ArticleDocs[i].hWndFrame);
	}
}

void
RefreshComposeWnds ()
{
  register int i;

  for (i = 0; i < MAXPOSTWNDS; i++)
	if (WndPosts[i].hWnd) {
	  ResizeComposeControls (&WndPosts[i], 0, 0);
	}

  for (i = 0; i < MAXMAILWNDS; i++)
	if (WndMails[i].hWnd) {
	  ResizeComposeControls (&WndMails[i], 0, 0);
	}
}

void
RefreshStatusWnds ()
{
  register int i;

  for (i = 0; i < NumStatusTexts; i++)
	if (CodingStatusText[i]->hTextWnd) {
	  SetHandleBkBrush (CodingStatusText[i]->hTextWnd, hStatusBackgroundBrush);
	  SendMessage (CodingStatusText[i]->hTextWnd, WM_SIZE, 0, 0L);
	  InvalidateRect (CodingStatusText[i]->hTextWnd, NULL, TRUE);
	}
  if (hCodedBlockWnd) {
	RefreshCodedBlockWnd ();
  }

}
/* ------------------------------------------------------------------------
 *    Close Window functions
 *      Batch operation, close all windows of a certain type
 *      (group/article/status)
 *      (JSC 1/18/94)
 */
void
CloseWindows ()
{
  CloseArticleWnds ();
  CloseGroupWnds ();
  CloseComposeWnds ();
  CloseStatusWnds ();
}

void
CloseGroupWnds ()
{
  register int i;
  for (i = 0; i < MAXGROUPWNDS; i++)
	if (GroupDocs[i].InUse && GroupDocs[i].hDocWnd && (!CommBusy || &GroupDocs[i] != CommDoc))
	  SendMessage (GroupDocs[i].hWndFrame, WM_CLOSE, 0, 0L);
}

void
CloseArticleWnds ()
{
  register int i;

  for (i = 0; i < MAXARTICLEWNDS; i++)
	if (ArticleDocs[i].InUse && ArticleDocs[i].hDocWnd && (!CommBusy || &ArticleDocs[i] != CommDoc))
	  SendMessage (ArticleDocs[i].hWndFrame, WM_CLOSE, 0, 0L);
}

void
CloseComposeWnds ()
{
  register int i;

  for (i = 0; i < MAXPOSTWNDS; i++)
	if (WndPosts[i].hWnd && !WndPosts[i].busy)
	  SendMessage (WndPosts[i].hWnd, WM_CLOSE, 0, 0L);

  for (i = 0; i < MAXMAILWNDS; i++)
	if (WndMails[i].hWnd && !WndMails[i].busy)
	  SendMessage (WndMails[i].hWnd, WM_CLOSE, 0, 0L);
}

void
CloseStatusWnds ()
{
  /* destroying a coding status text is like popping from a stack */
  /* so we just loop while the top of the stack still exists */
  int numSkipped = 0;
  while (numSkipped < NumStatusTexts && CodingStatusText[numSkipped]->hTextWnd)
	if (!CodingStatusText[numSkipped]->IsBusy)
	  SendMessage (CodingStatusText[numSkipped]->hTextWnd, WM_CLOSE, 0, 0L);
	else
	  numSkipped++;
#if 0
  if (CodingState) {
	MessageBox (CodingStatusText[0]->hTextWnd,
				"Please wait until en/decoding is complete",
				"Cannot close status window", MB_OK | MB_ICONSTOP);
	break;
  }
  else
	SendMessage (CodingStatusText[0]->hTextWnd, WM_CLOSE, 0, 0L);
#endif
}

/* ------------------------------------------------------------------------
 *    CascadeWindows (and helper CascadeWnd)
 *      cascade em
 *      jsc 9/18/94
 */
HWND
CascadeWnd (HWND hWnd, HWND prevWnd, int nthWnd, int width, int height, int maxX, int maxY)
{
  short x, y;

//  if (IsMaximized(hWnd))
  //     ShowWindow(hWnd, SW_SHOWNORMAL);

  x = (nthWnd * 12) % maxX;
  y = (nthWnd * (CaptionHeight + 2)) % maxY;
  SetWindowPos (hWnd, prevWnd, x, y, width, height, SWP_DRAWFRAME);

  return hWnd;
}

void
WinVNCascadeWindows ()
{
  register int i;
  int nthWnd, width, height, maxX, maxY;
  HWND prevWnd;

  width = (int) (xScreen >> 1);
  height = (int) (yScreen >> 1);
  maxX = 3 * (width >> 1);		/* 3/4 screen width  */
  maxY = 3 * (height >> 1);		/* 3/4 screen height */

  prevWnd = CascadeWnd (NetDoc.hWndFrame, (HWND) NULL, 1, width, height, maxX, maxY);
  nthWnd = 2;
  for (i = 0; i < MAXGROUPWNDS; i++)
	if (GroupDocs[i].InUse && GroupDocs[i].hWndFrame && !IsMinimized (GroupDocs[i].hWndFrame)) {
	  prevWnd = CascadeWnd (GroupDocs[i].hWndFrame, prevWnd, nthWnd, width, height, maxX, maxY);
	  nthWnd++;
	}

  for (i = 0; i < MAXARTICLEWNDS; i++)
	if (ArticleDocs[i].InUse && ArticleDocs[i].hWndFrame && !IsMinimized (ArticleDocs[i].hWndFrame)) {
	  prevWnd = CascadeWnd (ArticleDocs[i].hWndFrame, prevWnd, nthWnd, width, height, maxX, maxY);
	  nthWnd++;
	}

  for (i = 0; i < MAXPOSTWNDS; i++)
	if (WndPosts[i].hWnd && !IsMinimized (WndPosts[i].hWnd)) {
	  prevWnd = CascadeWnd (WndPosts[i].hWnd, prevWnd, nthWnd, width, height, maxX, maxY);
	  nthWnd++;
	}

  for (i = 0; i < MAXMAILWNDS; i++)
	if (WndMails[i].hWnd && !IsMinimized (WndMails[i].hWnd)) {
	  prevWnd = CascadeWnd (WndMails[i].hWnd, prevWnd, nthWnd, width, height, maxX, maxY);
	  nthWnd++;
	}

  for (i = 0; i < NumStatusTexts; i++)
	if (CodingStatusText[i]->hTextWnd && !IsMinimized (CodingStatusText[i]->hTextWnd)) {
	  prevWnd = CascadeWnd (CodingStatusText[i]->hTextWnd, prevWnd, nthWnd, width, height, maxX, maxY);
	  nthWnd++;
	}

  /* move coded block status window to top center */
  if (hCodedBlockWnd && !IsMinimized (hCodedBlockWnd)) {
	SetWindowPos (hCodedBlockWnd, (HWND) NULL, (xScreen - STATUSWIDTH) >> 1, 1, STATUSWIDTH, STATUSHEIGHT, SWP_DRAWFRAME);
  }
}

/* ------------------------------------------------------------------------
 *    MinimizeWindows
 *      jsc 10/18/94
 */
void
MinimizeWindows ()
{
  ShowWindow (NetDoc.hWndFrame, SW_MINIMIZE);
  MinimizeGroupWnds ();
  MinimizeArticleWnds ();
  MinimizeComposeWnds ();
  MinimizeStatusWnds ();
}

void
MinimizeGroupWnds ()
{
  register int i;

  for (i = 0; i < MAXGROUPWNDS; i++)
	if (GroupDocs[i].InUse && GroupDocs[i].hDocWnd && !IsMinimized (GroupDocs[i].hWndFrame)) {
	  ShowWindow (GroupDocs[i].hWndFrame, SW_MINIMIZE);
	}
}

void
MinimizeArticleWnds ()
{
  register int i;

  for (i = 0; i < MAXARTICLEWNDS; i++)
	if (ArticleDocs[i].InUse && ArticleDocs[i].hDocWnd && !IsMinimized (ArticleDocs[i].hWndFrame)) {
	  ShowWindow (ArticleDocs[i].hWndFrame, SW_MINIMIZE);
	}
}

void
MinimizeComposeWnds ()
{
  register int i;

  for (i = 0; i < MAXPOSTWNDS; i++)
	if (WndPosts[i].hWnd && !IsMinimized (WndPosts[i].hWnd)) {
	  ShowWindow (WndPosts[i].hWnd, SW_MINIMIZE);
	}

  for (i = 0; i < MAXMAILWNDS; i++)
	if (WndMails[i].hWnd && !IsMinimized (WndMails[i].hWnd)) {
	  ShowWindow (WndMails[i].hWnd, SW_MINIMIZE);
	}
}

void
MinimizeStatusWnds ()
{
  register int i;

  for (i = 0; i < NumStatusTexts; i++)
	if (CodingStatusText[i]->hTextWnd && !IsMinimized (CodingStatusText[i]->hTextWnd)) {
	  ShowWindow (CodingStatusText[i]->hTextWnd, SW_MINIMIZE);
	}

  if (hCodedBlockWnd) {
	ShowWindow (hCodedBlockWnd, SW_MINIMIZE);
  }
}

/* ------------------------------------------------------------------------
 *    RestoreWindows from minimized state
 *      jsc 1/18/95
 */

void
RestoreWindows ()
{
  register int i;

  if (IsMinimized(NetDoc.hWndFrame)) {
  	ShowWindow (NetDoc.hWndFrame, SW_RESTORE);
  }

  for (i = 0; i < MAXGROUPWNDS; i++)
	if (GroupDocs[i].InUse && GroupDocs[i].hDocWnd && IsMinimized (GroupDocs[i].hWndFrame)) {
	  ShowWindow (GroupDocs[i].hWndFrame, SW_RESTORE);
	}
  for (i = 0; i < MAXARTICLEWNDS; i++)
	if (ArticleDocs[i].InUse && ArticleDocs[i].hDocWnd && IsMinimized (ArticleDocs[i].hWndFrame)) {
	  ShowWindow (ArticleDocs[i].hWndFrame, SW_RESTORE);
	}
  for (i = 0; i < MAXPOSTWNDS; i++)
	if (WndPosts[i].hWnd && IsMinimized (WndPosts[i].hWnd)) {
	  ShowWindow (WndPosts[i].hWnd, SW_RESTORE);
	}

  for (i = 0; i < MAXMAILWNDS; i++)
	if (WndMails[i].hWnd && IsMinimized (WndMails[i].hWnd)) {
	  ShowWindow (WndMails[i].hWnd, SW_RESTORE);
	}
  for (i = 0; i < NumStatusTexts; i++)
	if (CodingStatusText[i]->hTextWnd && IsMinimized (CodingStatusText[i]->hTextWnd)) {
	  ShowWindow (CodingStatusText[i]->hTextWnd, SW_RESTORE);
	}

  if (hCodedBlockWnd) {
	ShowWindow (hCodedBlockWnd, SW_RESTORE);
  }
}

/* ------------------------------------------------------------------------
 *    BatchSend
 *      type is DOCTYPE_MAIL or _POST
 *      Increments nextBatchIndex and initiates mail/post
 *      Note: on entry nextBatchIndex is the index we will use for this send
 *      on exit, nextBatchIndex is either 0 (no more to send) or the index
 *      of the next mail/post to send
 *      (JSC 1/18/94)
 */
void
BatchSend (int type)
{
  int thisSend;
  int maxWnds;
  WndEdit *WndEdits;

  if (type == DOCTYPE_POSTING) {
	WndEdits = WndPosts;
	maxWnds = MAXPOSTWNDS;
  }
  else {
	WndEdits = WndMails;
	maxWnds = MAXMAILWNDS;
  }

//  Variable being used without initialization JD 11/10/95?
//  thisSend = WndEdits[thisSend].nextBatchIndex;
  thisSend = WndEdits[0].nextBatchIndex;
  if (thisSend == 0) {			/* find first in batch (if any) */
	while (thisSend < maxWnds)
	  if (WndEdits[thisSend].hWnd)
		break;
	  else
		thisSend++;

	if (thisSend == maxWnds)
	  return;					/* no open windows.  cancel */

	WndEdits[thisSend].nextBatchIndex = thisSend;
  }

  /* find next in batch (if any) */
  while (++WndEdits[thisSend].nextBatchIndex < maxWnds)
	if (WndEdits[WndEdits[thisSend].nextBatchIndex].hWnd)
	  break;

  if (WndEdits[thisSend].nextBatchIndex == maxWnds)
	WndEdits[thisSend].nextBatchIndex = 0;			/* no more */

  SendComposition (&WndEdits[thisSend]);
}

/* ------------------------------------------------------------------------
 *    Test busy functions
 *      Called to test if a comm or decoding is busy
 *      Returns true if busy, false if not busy
 *      (JSC 1/9/94)
 */
BOOL
TestCommBusy (HWND hParentWnd, char *msg)
{
  if (CommBusy) {
	MessageBox (hParentWnd,
				"Sorry, WinVN is busy communicating with the news server.\n"
				"Try again in a little while.", msg,
				MB_OK | MB_ICONASTERISK);
	return (TRUE);
  }
  else
	return (FALSE);
}

BOOL
TestCodingBusy (HWND hParentWnd, char *msg)
{
  if (CodingState != INACTIVE) {
	MessageBox (hParentWnd,
			 "Sorry, I can only handle one en/decoding session at a time.\n"
				"Try again in a little while.", msg,
				MB_OK | MB_ICONASTERISK);
	return (TRUE);
  }
  else
	return (FALSE);
}

/* ------------------------------------------------------------------------
 *        Update the mail menus -- called on mail transport change
 *      jsc 9/9/94
 */
void
UpdateAllMailMenus ()
{
  register int i;

  SetMainMailMenu (&NetDoc);
  for (i = 0; i < MAXARTICLEWNDS; i++)
	if (ArticleDocs[i].hDocWnd &&
		(!CommBusy || CommDoc != &ArticleDocs[i]))
	  SetArticleMailMenu (&ArticleDocs[i]);

  for (i = 0; i < MAXGROUPWNDS; i++)
	if (GroupDocs[i].hDocWnd)
	  SetGroupMailMenu (&GroupDocs[i]);
}

/* ------------------------------------------------------------------------
 *        GetFreeDiskSpace in bytes, given a drive name (i.e. "c:\\")
 *      jsc 9/29/94
 */
unsigned long 
GetFreeDiskSpace (char *drive)
{
#ifdef WIN32
  DWORD sectorsPerCluster, bytesPerSector, freeClusters, totalClusters;
  if (GetDiskFreeSpace (drive, &sectorsPerCluster, &bytesPerSector,
						&freeClusters, &totalClusters) == FALSE) {
	return 0L;
  }
  return (unsigned long) (sectorsPerCluster * bytesPerSector * freeClusters);
#else
  struct _diskfree_t d;
  if (_dos_getdiskfree (tolower (*drive) - 'a', &d) != 0) {
	return 0L;
  }
  return (unsigned long) d.avail_clusters *
	(unsigned long) d.sectors_per_cluster *
	(unsigned long) d.bytes_per_sector;
#endif
}

/* ------------------------------------------------------------------------
 *        GetFileLength in bytes  given a file name
 *      jsc 9/29/94
 */
unsigned long 
GetFileLength (char *fileName)
{
  int fh;
  long len;

  if ((fh = _open (fileName, _O_RDONLY)) < 0) {
	return 0L;
  }
  if ((len = _filelength (fh)) < 0) {
	len = 0L;
  }
  _close (fh);
  return (unsigned long) len;
}

//
// Local variables:
// tab-width: 2
// end:
//

--=====================_830668167==_
Content-Type: text/plain; charset="us-ascii"
Content-Disposition: attachment; filename="WVAction.cpp"

/*********************************************************************
 *
 * Module: WVAction.CPP
 *
 * Purpose: Support for action on articles and threads, including
 *          "killfile" and message selection.
 *
 *********************************************************************/

#include <windows.h>
#include <windowsx.h>
#include "wvglob.h"
#include "winvn.h"
#pragma hdrstop
#include <stdlib.h>  // atoi()
#include "WVClass.h"


static struct ValStrTable ActionTable[] =
{
  NO_ACTION,                    "NULL",
  MARK_SEEN_ART_LINES_LT,       "MSLT",
  MARK_SEEN_ART_LINES_LT,       "SALT",
  MARK_SEEN_ART_LINES_EQ,       "MSEQ",
  MARK_SEEN_ART_LINES_EQ,       "SAEQ",
  MARK_SEEN_ART_LINES_GT,       "MSGT",
  MARK_SEEN_ART_LINES_GT,       "SAGT",
  MARK_SEEN_ART_FROM_IS,        "MSFI",
  MARK_SEEN_ART_FROM_IS,        "SAFI",
  MARK_SEEN_ART_FROM_CONTAINS,  "MSFC",
  MARK_SEEN_ART_FROM_CONTAINS,  "SAFC",
  MARK_SEEN_ART_EMAIL_IS,       "MSEI",
  MARK_SEEN_ART_EMAIL_CONTAINS, "MSEC",
  MARK_SEEN_ART_SUBJ_IS,        "MSSI",
  MARK_SEEN_ART_SUBJ_IS,        "SASI",
  MARK_SEEN_ART_SUBJ_CONTAINS,  "MSSC",
  MARK_SEEN_ART_SUBJ_CONTAINS,  "SASC",
  MARK_SEEN_ART_MSGID_IS,       "MSMI",
  MARK_SEEN_ART_MSGID_IS,       "SAMI",
  MARK_SEEN_ART_MSGID_CONTAINS, "MSMC",
  MARK_SEEN_ART_MSGID_CONTAINS, "SAMC",
  MARK_SEEN_ART_REF_CONTAINS,   "MSRC",
  MARK_SEEN_ART_REF_CONTAINS,   "SARC",
  MARK_SEEN_NGROUP_CONTAINS,    "MSNC",
  SELECT_ART_LINES_LT,          "SLLT",
  SELECT_ART_LINES_EQ,          "SLEQ",
  SELECT_ART_LINES_GT,          "SLGT",
  SELECT_ART_FROM_IS,           "SLFI",
  SELECT_ART_FROM_CONTAINS,     "SLFC",
  SELECT_ART_EMAIL_IS,          "SLEI",
  SELECT_ART_EMAIL_CONTAINS,    "SLEC",
  SELECT_ART_SUBJ_IS,           "SLSI",
  SELECT_ART_SUBJ_CONTAINS,     "SLSC",
  SELECT_ART_MSGID_IS,          "SLMI",
  SELECT_ART_MSGID_CONTAINS,    "SLMC",
  SELECT_ART_REF_CONTAINS,      "SLRC",
  SELECT_NGROUP_CONTAINS,       "SLNC"
  };

#define ACTIONTABLESIZE (sizeof(ActionTable) / sizeof(ActionTable[0]))

#define WM_DATA_TO_DLG          WM_USER + 250
#define WM_DLG_TO_DATA          WM_USER + 251
#define WM_SETFILTER_OPTIONS    WM_USER + 260
#define WM_PROCESS_TEXT         WM_USER + 261

#define STR_HEADER_LINES   "Lines"
#define STR_HEADER_FROM    "From"
#define STR_HEADER_EMAIL   "email"
#define STR_HEADER_SUBJ    "Subject"
#define STR_HEADER_MSGID   "Message Id"
#define STR_HEADER_REF     "References"
#define STR_HEADER_NGROUP  "Newsgroup"

#define STR_HDFILT_LT    "< (non-zero)"
#define STR_HDFILT_EQ    "="
#define STR_HDFILT_GT    ">"
#define STR_HDFILT_EQCS  "Equals" // "Is exactly (incl case)"
//#define STR_HDFILT_EQNS  "Is exactly (ignore case)"
#define STR_HDFILT_CONT  "Contains" // "Contains (incl case)"

//#define STR_ACTION_NOOP   "(no action)"
#define STR_ACTION_MARK   "Mark article as 'seen'"
#define STR_ACTION_SELECT "Select article"

WVArticleAction g_action;  // global variable for 'all groups'


// Perform the article action requested
void DoAction(header_p header, LPACTIONDATA ad)
{
  switch(ad->iAction)
  {
  case MARK_SEEN_ART_LINES_LT:
    if(header->lines && (header->lines < (unsigned int) ad->iParam))
      header->Seen = ART_KILLED;
    break;
  case MARK_SEEN_ART_LINES_EQ:
    if(header->lines == (unsigned int) ad->iParam)
      header->Seen = ART_KILLED;
    break;
  case MARK_SEEN_ART_LINES_GT:
    if(header->lines > (unsigned int) ad->iParam)
      header->Seen = ART_KILLED;
    break;
  case MARK_SEEN_ART_FROM_IS:
    if(!_stricmp(header->from, ad->sParam))
      header->Seen = ART_KILLED;
    break;
  case MARK_SEEN_ART_FROM_CONTAINS:
    if(strstr(header->from, ad->sParam))
      header->Seen = ART_KILLED;
    break;
  case MARK_SEEN_ART_EMAIL_IS:
    if(!_stricmp(header->email, ad->sParam))
      header->Seen = ART_KILLED;
    break;
  case MARK_SEEN_ART_EMAIL_CONTAINS:
    if(strstr(header->email, ad->sParam))
      header->Seen = ART_KILLED;
    break;
  case MARK_SEEN_ART_SUBJ_IS:
    if(!_stricmp(header->subject, ad->sParam))
      header->Seen = ART_KILLED;
    break;
  case MARK_SEEN_ART_SUBJ_CONTAINS:
    if(strstr(header->subject, ad->sParam))
      header->Seen = ART_KILLED;
    break;
  case MARK_SEEN_ART_MSGID_IS:
    if(!strcmp(header->message_id, ad->sParam))
      header->Seen = ART_KILLED;
    break;
  case MARK_SEEN_ART_MSGID_CONTAINS:
    if(strstr(header->message_id, ad->sParam))
      header->Seen = ART_KILLED;
    break;
  case MARK_SEEN_ART_REF_CONTAINS:
    if(strstr(header->frob_ref_list, ad->sParam))
      header->Seen = ART_KILLED;
    break;
  case MARK_SEEN_NGROUP_CONTAINS:
    if(strstr(header->newsgroups, ad->sParam))
      header->Seen = ART_KILLED;
    break;
  case SELECT_ART_LINES_LT:
    if(header->lines && (header->lines < (unsigned int) ad->iParam))
      header->Selected = ART_SELECTED;
    break;
  case SELECT_ART_LINES_EQ:
    if(header->lines == (unsigned int) ad->iParam)
      header->Selected = ART_SELECTED;
    break;
  case SELECT_ART_LINES_GT:
    if(header->lines > (unsigned int) ad->iParam)
      header->Selected = ART_SELECTED;
    break;
  case SELECT_ART_FROM_IS:
    if(!_stricmp(header->from, ad->sParam))
      header->Selected = ART_SELECTED;
    break;
  case SELECT_ART_FROM_CONTAINS:
    if(strstr(header->from, ad->sParam))
      header->Selected = ART_SELECTED;
    break;
  case SELECT_ART_EMAIL_IS:
    if(!_stricmp(header->email, ad->sParam))
      header->Selected = ART_SELECTED;
    break;
  case SELECT_ART_EMAIL_CONTAINS:
    if(strstr(header->email, ad->sParam))
      header->Selected = ART_SELECTED;
    break;
  case SELECT_ART_SUBJ_IS:
    if(!_stricmp(header->subject, ad->sParam))
      header->Selected = ART_SELECTED;
    break;
  case SELECT_ART_SUBJ_CONTAINS:
    if(strstr(header->subject, ad->sParam))
      header->Selected = ART_SELECTED;
    break;
  case SELECT_ART_MSGID_IS:
    if(!strcmp(header->message_id, ad->sParam))
      header->Selected = ART_SELECTED;
    break;
  case SELECT_ART_MSGID_CONTAINS:
    if(strstr(header->message_id, ad->sParam))
      header->Selected = ART_SELECTED;
    break;
  case SELECT_ART_REF_CONTAINS:
    if(strstr(header->frob_ref_list, ad->sParam))
      header->Selected = ART_SELECTED;
    break;
  case SELECT_NGROUP_CONTAINS:
    if(strstr(header->newsgroups, ad->sParam))
      header->Selected = ART_SELECTED;
    break;
  case NO_ACTION:
    break;
  default:
    TRACE1("Unknown action handler: %u\n", ad->iAction);
    DEBUG_BREAK;
    break;
  }
}


WVArticleAction::WVArticleAction()
{
  m_Head = NULL;
  m_Tail = NULL;
  m_Current = NULL;
  m_ProfSect[0] = 0;
}


WVArticleAction::WVArticleAction(WVArticleAction*wv)
{
  m_Head = NULL;
  m_Tail = NULL;
  m_Current = NULL;
  if(wv->m_ProfSect[0])
    strcpy(m_ProfSect, wv->m_ProfSect);
  else
    m_ProfSect[0] = 0;
  if(wv->m_Head == NULL)
    return;
  Node*n = wv->m_Head;
  do
  {
    Append(n->ad.iAction, n->ad.iParam, n->ad.sParam);
    n = n->Flink;
  } while(n != NULL);
}


WVArticleAction::~WVArticleAction()
{
  DeleteAll();
}


// Append a new entry to the end of the list
void WVArticleAction::Append(int iA, long int iP, char*sP)
{
  Node * n = new Node;
  if(n)
  {
    if(m_Tail == NULL)
    {
      m_Head = n;
      n->Blink = NULL;
    }
    else
    {
      m_Tail->Flink = n;
      n->Blink = m_Tail;
    }
    m_Tail = n;
    m_Current = n;
    n->Flink = NULL;
    n->ad.iAction = iA;
    n->ad.iParam = iP;
    n->ad.sParam = NULL;
    SetParamText(sP);
  }
}


void WVArticleAction::DeleteNode(Node* pN)
{
  if(pN == NULL)
    return;
  Node*pF = pN->Flink;
  Node*pB = pN->Blink;

  if(pN->Blink && pN->Flink) // any node in middle of list
  {
    pF->Blink = pB;
    pB->Flink = pF;
  }
  else
  {
    if(pN->Blink == NULL) // first node in list
    {
      m_Head = pN->Flink;
      if(pN->Flink != NULL)
      {
        pF->Blink = NULL;
      }
    }
    if(pN->Flink == NULL) // last node in list
    {
      m_Tail = pN->Blink;
      if(pN->Blink != NULL)
      {
        pB->Flink = NULL;
      }
    }
  }
  delete pN;
  m_Current = pB ? pB : pF;
}


// Set the iParam value
void WVArticleAction::SetIParam(int i)
{
  if(!m_Current)
  {
    TRACE0("SetIParam() error: NULL pointer\n");
    DEBUG_BREAK;
  }
  else
  {
    m_Current->ad.iParam = i;
  }
}



// Set the sParam text, adjusting string size if necessary
void WVArticleAction::SetParamText(char*sP)
{
  if(!m_Current)
  {
    TRACE0("SetParamText() error: NULL pointer\n");
    DEBUG_BREAK;
  }
  else
  {
    if((NULL == sP) || !*sP)
    {
      if(NULL != m_Current->ad.sParam)
      {
        delete m_Current->ad.sParam;
        m_Current->ad.sParam = NULL;
      }
    }
    else
    {
      if(NULL != m_Current->ad.sParam)
      {
        if(strlen(m_Current->ad.sParam) < strlen(sP))
        {
          delete m_Current->ad.sParam;
          m_Current->ad.sParam = NULL;
        }
      }
      if(NULL == m_Current->ad.sParam)
      {
        m_Current->ad.sParam = new char[strlen(sP) + 1];
      }
      strcpy(m_Current->ad.sParam, sP);
    }
  }
}



// Delete all entries on the list
void WVArticleAction::DeleteAll()
{
  m_Current = m_Head;
  while(m_Current != NULL)
  {
    m_Head = m_Current->Flink;
    delete m_Current->ad.sParam;
    m_Current->ad.sParam = NULL;
    m_Current->Flink = NULL;
    m_Current->Blink = NULL;
    delete m_Current;
    m_Current = m_Head;
  }
  m_Head = NULL;
  m_Tail = NULL;
  m_Current = NULL;
}


// Go to the next node in the linked list
void WVArticleAction::GoToNext()
{
  if(m_Current != NULL)
  {
    m_Current = m_Current->Flink;
  }
}


// Go to the previous node in the linked list
void WVArticleAction::GoToPrev()
{
  if(m_Current != NULL)
  {
    m_Current = m_Current->Blink;
  }
}


// Switch two nodes in the linked list
void WVArticleAction::Switch(Node*nA, Node*nB)
{
  long int iTmp;
  char*sTmp;

  if(!nA)
    return;
  if(!nB)
    return;
  iTmp = nA->ad.iAction;
  nA->ad.iAction = nB->ad.iAction;
  nB->ad.iAction = (int) iTmp;
  iTmp = nA->ad.iParam;
  nA->ad.iParam = nB->ad.iParam;
  nB->ad.iParam = iTmp;
  sTmp = nA->ad.sParam;
  nA->ad.sParam = nB->ad.sParam;
  nB->ad.sParam = sTmp;
}


// Switch two complete lists
void WVArticleAction::Switchwith(WVArticleAction*pA)
{
  Node*pWTmp;

  if(!pA)
    return;
  pWTmp = this->m_Head;
  this->m_Head = pA->m_Head;
  pA->m_Head = pWTmp;
  pWTmp = this->m_Tail;
  this->m_Tail = pA->m_Tail;
  pA->m_Tail = pWTmp;
  pWTmp = this->m_Current;
  this->m_Current = pA->m_Current;
  pA->m_Current = pWTmp;
}


// Read the list of actions from the .ini file
void WVArticleAction::ReadActions(char*sGroup)
{
  long int iTmp;
  char ProfEntry[32];
  char ProfValue[MAXINTERNALLINE];
  char *pParam;
  
  if(sGroup)
    sprintf(m_ProfSect, "G: %s", sGroup);
  else
    sprintf(m_ProfSect, "N: %s", NNTPHost);

#ifdef _DEBUG
  if(strlen(m_ProfSect) > sizeof(m_ProfSect))
    DEBUG_BREAK;
#endif

  for(int ind = 1; ind < 100; ind++)
  {
    sprintf(ProfEntry, "Action%02d", ind);
    
    if(!GetPrivateProfileString(m_ProfSect, ProfEntry, "", 
            ProfValue, sizeof(ProfValue), szAppProFile))
      return;

    pParam = strchr(ProfValue, ' ');
    if(pParam)
    {
      *pParam++ = '\0';
      for(int i = 1; i < ACTIONTABLESIZE; i++) // skip 'no action' item
      {
        if(!strcmp(ProfValue, ActionTable[i].text))
        {
          iTmp = atoi(pParam);
          Append(ActionTable[i].value, iTmp, pParam);
          break;
        }
      }
    }
  }
}


// Save the action list back to the .ini file
void WVArticleAction::WriteActions()
{
  int ind = 0;
  Node* cur;
  char ProfEntry[32];
  char ProfValue[MAXINTERNALLINE];
  
  ResetCurrent();
  
  while(cur = GetCurrent())
  {
    if(cur->ad.sParam)
    {
      for(int i = 0; i < ACTIONTABLESIZE; i++)
      {
        if(cur->ad.iAction == ActionTable[i].value)
        {
          sprintf(ProfEntry, "Action%02d", ++ind);
          sprintf(ProfValue, "%s %s", ActionTable[i].text, cur->ad.sParam);
#ifdef _DEBUG
          if(strlen(ProfValue) >= sizeof(ProfValue)) // bozo programmer filter
            DEBUG_BREAK;
#endif
          ProfValue[sizeof(ProfValue)-1] = 0;
          WritePrivateProfileString(m_ProfSect, ProfEntry,
            ProfValue, szAppProFile);
          break;
        }
      }
    }
    GoToNext();
  }
  sprintf(ProfEntry, "Action%02d", ++ind);
  // TODO: if WIN32, use the Registry...
  WritePrivateProfileString(m_ProfSect, ProfEntry, NULL, szAppProFile);
}


// Do the requested action for each article
void WVArticleAction::ActOnArticles(TypGroup far *Group, header_p headers)
{
  int artindex;
  header_p header;
  
  for(artindex = 0; artindex < Group->total_headers; artindex++)
  {
    header = header_elt(headers, artindex);
    if((ART_UNSEEN == header->Seen) &&
       (ART_UNSELECTED == header->Selected))
    {
      g_action.ResetCurrent();
      while((NULL != g_action.GetCurrent()) &&
            (ART_UNSEEN == header->Seen) &&
            (ART_UNSELECTED == header->Selected))
      {
        DoAction(header, &g_action.GetCurrent()->ad);
        g_action.GoToNext();
      }
      if((ART_UNSEEN == header->Seen) &&
         (ART_UNSELECTED == header->Selected))
      {
        ResetCurrent();
        while((NULL != GetCurrent()) &&
              (ART_UNSEEN == header->Seen) &&
              (ART_UNSELECTED == header->Selected))
        {
          DoAction(header, &GetCurrent()->ad);
          GoToNext();
        }
      }
    }
  }
}


BOOL AddEQCSChoice(const char*s)
{
  if(strcmp(s, STR_HEADER_REF))
    return FALSE;
  if(strcmp(s, STR_HEADER_NGROUP))
    return FALSE;
  return TRUE;
}


LRESULT FAR PASCAL
WinVnArticleActionDlg(HWND hDlg, unsigned iMessage, WPARAM wParam, LPARAM lParam)
{
  int iSelect = 0;
  int cOffset;
  int cBase;
  WORD wID;
  WORD wCode;
  static int iSaveGroupRadio = 0;
  static WVArticleAction *pGrp = NULL;
  static WVArticleAction *pGlob = NULL;
  static WVArticleAction *pAA = NULL;
  static Node *pAD = NULL;
  char sTmp[512];

  wID = LOWORD(wParam);
#ifdef WIN32
  HWND hCtl = (HWND)(UINT) lParam;
  wCode = HIWORD(wParam);
#else
  int hCtl = LOWORD(lParam);
  wCode = HIWORD(lParam);
#endif
  switch(iMessage)
  {
  case WM_INITDIALOG:
    pGrp  = new WVArticleAction();
    pGrp->ReadActions(CurrentGroup);
    pGlob = new WVArticleAction(&g_action);
    pAA = pGrp;
    pAA->ResetCurrent();
    pAD = pAA->GetCurrent();
    SendDlgItemMessage(hDlg, IDC_AA_HEADER, CB_ADDSTRING, 0,
      (LPARAM) (LPSTR) STR_HEADER_FROM);
    SendDlgItemMessage(hDlg, IDC_AA_HEADER, CB_ADDSTRING, 0,
      (LPARAM) (LPSTR) STR_HEADER_EMAIL);
    SendDlgItemMessage(hDlg, IDC_AA_HEADER, CB_ADDSTRING, 0,
      (LPARAM) (LPSTR) STR_HEADER_LINES);
    SendDlgItemMessage(hDlg, IDC_AA_HEADER, CB_ADDSTRING, 0,
      (LPARAM) (LPSTR) STR_HEADER_SUBJ);
    SendDlgItemMessage(hDlg, IDC_AA_HEADER, CB_ADDSTRING, 0,
      (LPARAM) (LPSTR) STR_HEADER_MSGID);
    SendDlgItemMessage(hDlg, IDC_AA_HEADER, CB_ADDSTRING, 0,
      (LPARAM) (LPSTR) STR_HEADER_REF);
    SendDlgItemMessage(hDlg, IDC_AA_HEADER, CB_ADDSTRING, 0,
      (LPARAM) (LPSTR) STR_HEADER_NGROUP);

//    SendDlgItemMessage(hDlg, IDC_AA_ACTION, CB_ADDSTRING, 0,
//      (LPARAM) (LPSTR) STR_ACTION_NOOP);
    SendDlgItemMessage(hDlg, IDC_AA_ACTION, CB_ADDSTRING, 0,
      (LPARAM) (LPSTR) STR_ACTION_MARK);
    SendDlgItemMessage(hDlg, IDC_AA_ACTION, CB_ADDSTRING, 0,
      (LPARAM) (LPSTR) STR_ACTION_SELECT);

    iSaveGroupRadio = IDC_AA_RADIO_GROUP;
    SendMessage(hDlg, WM_DATA_TO_DLG, 0, 0);
    return TRUE;

  case WM_DESTROY:
    delete pGrp;
    pGrp = NULL;
    delete pGlob;
    pGlob = NULL;
    break;

  case WM_DLG_TO_DATA: // Update data from dialog
    pAD = pAA->GetCurrent();
    if(pAD != NULL)
    {
      pAD->ad.iAction = NO_ACTION;
      GetDlgItemText(hDlg, IDC_AA_TEXT, sTmp, sizeof(sTmp));
      pAA->SetParamText(sTmp);
      pAD->ad.iParam = atoi(sTmp);
      SendDlgItemMessage(hDlg, IDC_AA_ACTION, CB_GETLBTEXT,
          (WPARAM) iSelect, (LPARAM) (LPSTR) sTmp);
      iSelect = (int) SendDlgItemMessage(hDlg, IDC_AA_HEADER, CB_GETCURSEL, 0, 0);
      if(iSelect == CB_ERR)
        DEBUG_BREAK;
      else
      {
        SendDlgItemMessage(hDlg, IDC_AA_HEADER, CB_GETLBTEXT,
            (WPARAM) iSelect, (LPARAM) (LPSTR) sTmp);
        if(!strcmp(sTmp, STR_HEADER_LINES))
          pAD->ad.iAction = MARK_SEEN_ART_LINES_BASE;
        else if(!strcmp(sTmp, STR_HEADER_FROM))
          pAD->ad.iAction = MARK_SEEN_ART_FROM_BASE;
        else if(!strcmp(sTmp, STR_HEADER_EMAIL))
          pAD->ad.iAction = MARK_SEEN_ART_EMAIL_BASE;
        else if(!strcmp(sTmp, STR_HEADER_SUBJ))
          pAD->ad.iAction = MARK_SEEN_ART_SUBJ_BASE;
        else if(!strcmp(sTmp, STR_HEADER_MSGID))
          pAD->ad.iAction = MARK_SEEN_ART_MSGID_BASE;
        else if(!strcmp(sTmp, STR_HEADER_REF))
          pAD->ad.iAction = MARK_SEEN_ART_REF_BASE;
        else if(!strcmp(sTmp, STR_HEADER_NGROUP))
          pAD->ad.iAction = MARK_SEEN_NGROUP_BASE;
        else
        {
          TRACE0("No header item selected\n");
          DEBUG_BREAK;
          pAD->ad.iAction = NO_ACTION;
        }

        iSelect = (int) SendDlgItemMessage(hDlg, IDC_AA_ACTION, CB_GETCURSEL, 0, 0);
        if(iSelect == CB_ERR)
          DEBUG_BREAK;
        else
        {
          SendDlgItemMessage(hDlg, IDC_AA_ACTION, CB_GETLBTEXT,
            (WPARAM) iSelect, (LPARAM) (LPSTR) sTmp);
          if(!strcmp(sTmp, STR_ACTION_SELECT))
          {
            pAD->ad.iAction |= AA_SELECT_MASK;
          }

          iSelect = (int) SendDlgItemMessage(hDlg, IDC_AA_HDRFILTER, CB_GETCURSEL, 0, 0);
          if(iSelect == CB_ERR)
            DEBUG_BREAK;
          else
          {
            SendDlgItemMessage(hDlg, IDC_AA_HDRFILTER, CB_GETLBTEXT,
                (WPARAM) iSelect, (LPARAM) (LPSTR) sTmp);
            if(!strcmp(sTmp, STR_HDFILT_LT))
            {
              pAD->ad.iAction |= AA_LT_MASK;
              sscanf(pAD->ad.sParam, "%u", &pAD->ad.iParam);
            }
            else if(!strcmp(sTmp, STR_HDFILT_EQ))
            {
              pAD->ad.iAction |= AA_EQ_MASK;
              sscanf(pAD->ad.sParam, "%u", &pAD->ad.iParam);
            }
            else if(!strcmp(sTmp, STR_HDFILT_GT))
            {
              pAD->ad.iAction |= AA_GT_MASK;
              sscanf(pAD->ad.sParam, "%u", &pAD->ad.iParam);
            }
            else if(!strcmp(sTmp, STR_HDFILT_EQCS))
            {
              pAD->ad.iAction |= AA_IS_MASK;
            }
            else if(!strcmp(sTmp, STR_HDFILT_CONT))
            {
              pAD->ad.iAction |= AA_CONTAINS_MASK;
            }
          }
        }
      }
//    TRACE3("WM_DLG_TO_DATA iAction = %lu, iParam = %lu, sParam = <%s>\n",
//      pAD->ad.iAction, pAD->ad.iParam, pAD->ad.sParam ? pAD->ad.sParam : "");
    }
    return 0; // WM_DLG_TO_DATA

  case WM_DATA_TO_DLG:  // Update dialog from current data
    pAD = pAA->GetCurrent();
    SetDlgItemText(hDlg, IDC_AA_RADIO_GROUP, CurrentGroup);
    CheckRadioButton (hDlg, IDC_AA_RADIO_GLOBAL, IDC_AA_RADIO_GROUP,
      iSaveGroupRadio);
    SendDlgItemMessage(hDlg, IDC_AA_HDRFILTER, CB_RESETCONTENT, 0, 0);
    EnableWindow(GetDlgItem(hDlg, IDC_AA_EDIT_PREV), FALSE);
    EnableWindow(GetDlgItem(hDlg, IDC_AA_EDIT_NEXT), FALSE);
    EnableWindow(GetDlgItem(hDlg, IDC_AA_MOVE_PREV), FALSE);
    EnableWindow(GetDlgItem(hDlg, IDC_AA_MOVE_NEXT), FALSE);

    if(pAD == NULL)
    {
      SetDlgItemText(hDlg, IDC_AA_TEXT, "");
      EnableWindow(GetDlgItem(hDlg, IDC_AA_HEADER),    FALSE);
      EnableWindow(GetDlgItem(hDlg, IDC_AA_HDRFILTER), FALSE);
      EnableWindow(GetDlgItem(hDlg, IDC_AA_TEXT),      FALSE);
      EnableWindow(GetDlgItem(hDlg, IDC_AA_ACTION),    FALSE);
      EnableWindow(GetDlgItem(hDlg, IDC_AA_DELETE),    FALSE);
    }
    else
    {
//      TRACE3("WM_DATA_TO_DLG iAction = %lu, iParam = %lu, sParam = <%s>\n",
//        pAD->ad.iAction, pAD->ad.iParam, pAD->ad.sParam ? pAD->ad.sParam : "");
      cOffset = pAD->ad.iAction % AA_MODULO;
      cBase = (pAD->ad.iAction / AA_MODULO) * AA_MODULO;
      if(cBase >= AA_SELECT_MASK)
        cBase &= ~AA_SELECT_MASK;

      EnableWindow(GetDlgItem(hDlg, IDC_AA_HEADER),    TRUE);
      EnableWindow(GetDlgItem(hDlg, IDC_AA_HDRFILTER), TRUE);
      EnableWindow(GetDlgItem(hDlg, IDC_AA_TEXT),      TRUE);
      EnableWindow(GetDlgItem(hDlg, IDC_AA_ACTION),    TRUE);

      if(pAD->ad.iAction & AA_SELECT_MASK)
      {
        SendDlgItemMessage(hDlg, IDC_AA_ACTION, CB_SELECTSTRING,
                  (WPARAM) -1, (LPARAM)(LPSTR) STR_ACTION_SELECT);
      }
      else
      {
        SendDlgItemMessage(hDlg, IDC_AA_ACTION, CB_SELECTSTRING,
                  (WPARAM) -1, (LPARAM)(LPSTR) STR_ACTION_MARK);
      }
      switch(cBase)
      {
      case MARK_SEEN_ART_LINES_BASE:
        SendDlgItemMessage(hDlg, IDC_AA_HEADER, CB_SELECTSTRING,
                  (WPARAM) -1, (LPARAM)(LPSTR) STR_HEADER_LINES);
        sprintf(sTmp, "%lu lines", pAD->ad.iParam);
        pAA->SetParamText(sTmp);
        break;
      case MARK_SEEN_ART_FROM_BASE:
        SendDlgItemMessage(hDlg, IDC_AA_HEADER, CB_SELECTSTRING,
                  (WPARAM) -1, (LPARAM)(LPSTR) STR_HEADER_FROM);
        break;
      case MARK_SEEN_ART_EMAIL_BASE:
        SendDlgItemMessage(hDlg, IDC_AA_HEADER, CB_SELECTSTRING,
                  (WPARAM) -1, (LPARAM)(LPSTR) STR_HEADER_EMAIL);
        break;
      case MARK_SEEN_ART_SUBJ_BASE:
        SendDlgItemMessage(hDlg, IDC_AA_HEADER, CB_SELECTSTRING,
                  (WPARAM) -1, (LPARAM)(LPSTR) STR_HEADER_SUBJ);
        break;
      case MARK_SEEN_ART_MSGID_BASE:
        SendDlgItemMessage(hDlg, IDC_AA_HEADER, CB_SELECTSTRING,
                  (WPARAM) -1, (LPARAM)(LPSTR) STR_HEADER_MSGID);
        break;
      case MARK_SEEN_ART_REF_BASE:
        SendDlgItemMessage(hDlg, IDC_AA_HEADER, CB_SELECTSTRING,
                  (WPARAM) -1, (LPARAM)(LPSTR) STR_HEADER_REF);
        break;
      case MARK_SEEN_NGROUP_BASE:
        SendDlgItemMessage(hDlg, IDC_AA_HEADER, CB_SELECTSTRING,
                  (WPARAM) -1, (LPARAM)(LPSTR) STR_HEADER_NGROUP);
        break;
      default:
        TRACE1("**** Unknown cBase value: %lu\n", cBase);
        DEBUG_BREAK;
        break;
      }
      SendMessage(hDlg, WM_SETFILTER_OPTIONS, 0, 0);
      SetDlgItemText(hDlg, IDC_AA_TEXT, pAD->ad.sParam);
      switch(cOffset)
      {
      case AA_LT_MASK:
        SendDlgItemMessage(hDlg, IDC_AA_HDRFILTER, CB_SELECTSTRING,
                  (WPARAM) -1, (LPARAM)(LPSTR) STR_HDFILT_LT);
        break;
      case AA_EQ_MASK:
        SendDlgItemMessage(hDlg, IDC_AA_HDRFILTER, CB_SELECTSTRING,
                  (WPARAM) -1, (LPARAM)(LPSTR) STR_HDFILT_EQ);
        break;
      case AA_GT_MASK:
        SendDlgItemMessage(hDlg, IDC_AA_HDRFILTER, CB_SELECTSTRING,
                  (WPARAM) -1, (LPARAM)(LPSTR) STR_HDFILT_GT);
        break;
      case AA_IS_MASK:
        SendDlgItemMessage(hDlg, IDC_AA_HDRFILTER, CB_SELECTSTRING,
                  (WPARAM) -1, (LPARAM)(LPSTR) STR_HDFILT_EQCS);
        break;
      case AA_CONTAINS_MASK:
        SendDlgItemMessage(hDlg, IDC_AA_HDRFILTER, CB_SELECTSTRING,
                  (WPARAM) -1, (LPARAM)(LPSTR) STR_HDFILT_CONT);
        break;

      default:
        TRACE1("**** Unknown cOffset value: %lu\n", cOffset);
        DEBUG_BREAK;
        break;
      }
      EnableWindow(GetDlgItem(hDlg, IDC_AA_EDIT_PREV),
                   pAA->GetCurrent()->Blink ? TRUE : FALSE);
      EnableWindow(GetDlgItem(hDlg, IDC_AA_EDIT_NEXT),
                   pAA->GetCurrent()->Flink ? TRUE : FALSE);
      EnableWindow(GetDlgItem(hDlg, IDC_AA_MOVE_PREV),
                   pAA->GetCurrent()->Blink ? TRUE : FALSE);
      EnableWindow(GetDlgItem(hDlg, IDC_AA_MOVE_NEXT),
                   pAA->GetCurrent()->Flink ? TRUE : FALSE);
      EnableWindow(GetDlgItem(hDlg, IDC_AA_DELETE), TRUE);
    }
    return 0;  // WM_DLG_TO_DATA

  case WM_SETFILTER_OPTIONS: // Set filter listbox options based on header selection
    SendDlgItemMessage(hDlg, IDC_AA_HDRFILTER, CB_RESETCONTENT, 0, 0);
    iSelect = (int) SendDlgItemMessage(hDlg, IDC_AA_HEADER, CB_GETCURSEL, 0, 0);
    if(iSelect != CB_ERR)
    {
      SendDlgItemMessage(hDlg, IDC_AA_HEADER, CB_GETLBTEXT,
          (WPARAM) iSelect, (LPARAM) (LPSTR) sTmp);

      if(!strcmp(sTmp, STR_HEADER_LINES))
      {
        SendDlgItemMessage(hDlg, IDC_AA_HDRFILTER,
                    CB_ADDSTRING, 0, (LPARAM)(LPSTR) STR_HDFILT_LT);
        SendDlgItemMessage(hDlg, IDC_AA_HDRFILTER,
                    CB_ADDSTRING, 0, (LPARAM)(LPSTR) STR_HDFILT_EQ);
        SendDlgItemMessage(hDlg, IDC_AA_HDRFILTER,
                    CB_ADDSTRING, 0, (LPARAM)(LPSTR) STR_HDFILT_GT);
      }
      else
      {
//        if(strcmp(sTmp, STR_HEADER_REF))
        if(AddEQCSChoice(sTmp))
        {
          SendDlgItemMessage(hDlg, IDC_AA_HDRFILTER,
                      CB_ADDSTRING, 0, (LPARAM)(LPSTR) STR_HDFILT_EQCS);
        }
//        SendDlgItemMessage (hDlg, IDC_AA_HDRFILTER,
//                    CB_ADDSTRING, 0, (LPARAM)(LPSTR) STR_HDFILT_EQNS);
        SendDlgItemMessage(hDlg, IDC_AA_HDRFILTER,
                    CB_ADDSTRING, 0, (LPARAM)(LPSTR) STR_HDFILT_CONT);
      }
      SendDlgItemMessage(hDlg, IDC_AA_HDRFILTER, CB_SETCURSEL, 0, 0);
    }
    return 0;  // WM_SETFILTER_OPTIONS

  case WM_COMMAND:
    pAD = pAA->GetCurrent();
    switch(wID)
    {
    case IDC_AA_HEADER:
      if(pAD && (CBN_SELCHANGE == wCode))
      {
        iSelect = (int) SendDlgItemMessage(hDlg, IDC_AA_HEADER, CB_GETCURSEL, 0, 0);
        if(iSelect != CB_ERR)
        {
          SendMessage(hDlg, WM_SETFILTER_OPTIONS, 0, 0);
          if(!pAD->ad.sParam)
          {
            SendDlgItemMessage(hDlg, IDC_AA_HEADER, CB_GETLBTEXT,
                (WPARAM) iSelect, (LPARAM) (LPSTR) sTmp);
            if(!strcmp(sTmp, STR_HEADER_LINES))
            {
              sprintf(sTmp, "%lu lines", Latest.lines);
              SetDlgItemText(hDlg, IDC_AA_TEXT, sTmp);
            }
            else if(!strcmp(sTmp, STR_HEADER_FROM))
            {
              SetDlgItemText(hDlg, IDC_AA_TEXT, Latest.from);
            }
            else if(!strcmp(sTmp, STR_HEADER_EMAIL))
            {
              SetDlgItemText(hDlg, IDC_AA_TEXT, Latest.email);
            }
            else if(!strcmp(sTmp, STR_HEADER_SUBJ))
            {
              SetDlgItemText(hDlg, IDC_AA_TEXT, Latest.subject);
            }
            else if(!strcmp(sTmp, STR_HEADER_MSGID))
            {
              SetDlgItemText(hDlg, IDC_AA_TEXT, Latest.message_id);
            }
            else if(!strcmp(sTmp, STR_HEADER_REF))
            {
              SetDlgItemText(hDlg, IDC_AA_TEXT, Latest.message_id);
            }
            else if(!strcmp(sTmp, STR_HEADER_NGROUP))
            {
              SetDlgItemText(hDlg, IDC_AA_TEXT, Latest.newsgroups);
            }
          }
        }
        return 0;
      }
      break;
    
    case IDOK:
      SendMessage(hDlg, WM_DLG_TO_DATA, 0, 0);
      pGrp->WriteActions();
      pGlob->WriteActions();
      g_action.Switchwith(pGlob);
      EndDialog(hDlg, TRUE);
      pAA = NULL;
      return 0;

    case IDCANCEL:
      EndDialog (hDlg, FALSE);
      pAA = NULL;
      return 0;

    case IDC_AA_NEW:
      SendMessage(hDlg, WM_DLG_TO_DATA, 0, 0);
      pAA->Append(MARK_SEEN_ART_SUBJ_CONTAINS, 0, "");
      SendMessage(hDlg, WM_DATA_TO_DLG, 0, 0);
      SetDlgItemText(hDlg, IDC_AA_TEXT, Latest.subject);
      return 0;

    case IDC_AA_DELETE:
      pAA->DeleteNode(pAD);
      SendMessage(hDlg, WM_DATA_TO_DLG, 0, 0);
      return 0;
    
    case IDC_AA_RADIO_GLOBAL:
      SendMessage(hDlg, WM_DLG_TO_DATA, 0, 0);
      iSaveGroupRadio = IDC_AA_RADIO_GLOBAL;
      CheckRadioButton(hDlg, IDC_AA_RADIO_GLOBAL, IDC_AA_RADIO_GROUP,
          iSaveGroupRadio);
      pAA = pGlob;
      pAA->ResetCurrent();
      pAD = pAA->GetCurrent();
      SendMessage(hDlg, WM_DATA_TO_DLG, 0, 0);
      return 0;

    case IDC_AA_RADIO_GROUP:
      SendMessage(hDlg, WM_DLG_TO_DATA, 0, 0);
      iSaveGroupRadio = IDC_AA_RADIO_GROUP;
      CheckRadioButton(hDlg, IDC_AA_RADIO_GLOBAL, IDC_AA_RADIO_GROUP,
          iSaveGroupRadio);
      pAA = pGrp;
      pAA->ResetCurrent();
      pAD = pAA->GetCurrent();
      SendMessage(hDlg, WM_DATA_TO_DLG, 0, 0);
      return 0;

    case IDC_AA_EDIT_NEXT:
      SendMessage(hDlg, WM_DLG_TO_DATA, 0, 0);
      pAA->GoToNext();
      SendMessage(hDlg, WM_DATA_TO_DLG, 0, 0);
      return 0;

    case IDC_AA_EDIT_PREV:
      SendMessage(hDlg, WM_DLG_TO_DATA, 0, 0);
      pAA->GoToPrev();
      SendMessage(hDlg, WM_DATA_TO_DLG, 0, 0);
      return 0;

    case IDC_AA_MOVE_NEXT:
      SendMessage(hDlg, WM_DLG_TO_DATA, 0, 0);
      pAA->Switch(pAA->GetCurrent(), pAA->GetCurrent()->Flink);
      SendMessage(hDlg, WM_DATA_TO_DLG, 0, 0);
      return 0;

    case IDC_AA_MOVE_PREV:
      SendMessage(hDlg, WM_DLG_TO_DATA, 0, 0);
      pAA->Switch(pAA->GetCurrent(), pAA->GetCurrent()->Blink);
      SendMessage(hDlg, WM_DATA_TO_DLG, 0, 0);
      return 0;

    default:
      break;
    }  // switch(wID)
    break;  // WM_COMMAND
  
  default:
    return FALSE;
    break;
  }  // switch(iMessage)
  return DefWindowProc (hDlg, iMessage, wParam, lParam);
}


--=====================_830668167==_
Content-Type: text/plain; charset="us-ascii"

-- 
Harvey Brydon         Internet: hab@slb.com or brydon@tulsa.dowell.slb.com
Schlumberger Dowell   Phone:    (918)250-4312
O-

--=====================_830668167==_--

