
/*---------------------------------------------------------------------------*/
/*                                                                           */
/*          WEDL(tm) - Windows Enhanced Dialog Library                       */
/*          Copyright (c) 1991-1992, Nemisoft, Inc.                          */
/*          All Rights Reserved                                              */
/*          Module:  DEMO.C                                                  */
/*                                                                           */
/*---------------------------------------------------------------------------*/

#include <windows.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "wedl.h"
#include "demo.h"
#include "demohelp.h"

/*---------------------------------------------------------------------------*/

/* general function prototypes */

int FAR PASCAL AboutDlgProc( HWND hDlg, unsigned message, WORD wParam,
                             LONG lParam );
int FAR PASCAL AlbumDlgProc( HWND hDlg, unsigned message, WORD wParam,
                             LONG lParam );
int FAR PASCAL EmployeeDlgProc( HWND hDlg, unsigned message, WORD wParam,
                                LONG lParam );
int FAR PASCAL check_date( HFORM hform, HFIELD hfield, LPSTR pbuf );
int FAR PASCAL check_file_name( HFORM hform, HFIELD hfield, LPSTR pbuf );
int FAR PASCAL check_state( HFORM hform, HFIELD hfield, LPSTR pbuf );
int FAR PASCAL check_zip_code( HFORM hform, HFIELD hfield, LPSTR pbuf );
BOOL FAR PASCAL error_func( HFORM hform, HFIELD hfield, int error_value,
                            int error_position, int error_event );
static BOOL initialize_application( HANDLE hInstance );
static BOOL initialize_instance( HANDLE hInstance, int nCmdShow );
long FAR PASCAL MainWndProc( HWND hWnd, unsigned message, WORD wParam,
                             LONG lParam );
int FAR PASCAL NumericDlgProc( HWND hDlg, unsigned message, WORD wParam,
                               LONG lParam );
int FAR PASCAL UploadDlgProc( HWND hDlg, unsigned message, WORD wParam,
                             LONG lParam );

/*---------------------------------------------------------------------------*/

/* static variables (global to this file) */

static HINSTANCE hInst;
static HBITMAP hBitmap;
static BITMAP bitmap;
static char szClassName[] = "WEDL_DEMO";
static char tbuf[512];
static PVALFUNC pcheck_date, pcheck_state, pcheck_zip_code, pcheck_file_name;
static PERRFUNC perror_func;

/*---------------------------------------------------------------------------*/

int PASCAL WinMain( HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine,
                    int nCmdShow )
{
    MSG msg;

    if( hPrevInstance == NULL )
        if( !initialize_application( hInstance ) ) return( FALSE );

    if( !initialize_instance( hInstance, nCmdShow ) ) return( FALSE );

    while( GetMessage( &msg, NULL, 0, 0 ) ) {
        TranslateMessage( &msg );
        DispatchMessage( &msg );
    }

    DeleteObject( hBitmap );

    return( msg.wParam );
}

/*---------------------------------------------------------------------------*/

long FAR PASCAL MainWndProc( HWND hWnd, unsigned message, WORD wParam,
                             LONG lParam )
{
    FARPROC pdialog_proc;
    HDC hDC, hMemDC;
    PAINTSTRUCT paint;

    switch( message ) {

        case WM_PAINT:
            hDC     = BeginPaint( hWnd, &paint );
            hMemDC  = CreateCompatibleDC( hDC );
            SelectObject( hMemDC, hBitmap );
            BitBlt( hDC, 0, 0, bitmap.bmWidth, bitmap.bmHeight, hMemDC,
                    0, 0, SRCCOPY );
            DeleteDC( hMemDC );
            EndPaint( hWnd, &paint );
            break;

        case WM_COMMAND:
            switch( wParam ) {
                case IDM_EMPLOYEE:
                    pdialog_proc    = MakeProcInstance( EmployeeDlgProc, hInst );
                    pcheck_date     = (PVALFUNC) MakeProcInstance( check_date, hInst );
                    pcheck_state    = (PVALFUNC) MakeProcInstance( check_state, hInst );
                    pcheck_zip_code = (PVALFUNC) MakeProcInstance( check_zip_code, hInst );
                    perror_func     = (PERRFUNC) MakeProcInstance( error_func, hInst );
                    DialogBox( hInst, "EmployeeInfo", hWnd, pdialog_proc );
                    FreeProcInstance( perror_func );
                    FreeProcInstance( pcheck_zip_code );
                    FreeProcInstance( pcheck_state );
                    FreeProcInstance( pcheck_date );
                    FreeProcInstance( pdialog_proc );
                    break;
                case IDM_ALBUM:
                    pdialog_proc = MakeProcInstance( AlbumDlgProc, hInst );
                    DialogBox( hInst, "AlbumDatabase", hWnd, pdialog_proc );
                    FreeProcInstance( pdialog_proc );
                    break;
                case IDM_UPLOAD:
                    pdialog_proc     = MakeProcInstance( UploadDlgProc,   hInst );
                    pcheck_file_name = (PVALFUNC) MakeProcInstance( check_file_name, hInst );
                    perror_func      = (PERRFUNC) MakeProcInstance( error_func,      hInst );
                    DialogBox( hInst, "UploadFile", hWnd, pdialog_proc );
                    FreeProcInstance( perror_func );
                    FreeProcInstance( pcheck_file_name );
                    FreeProcInstance( pdialog_proc );
                    break;
                case IDM_NUMERIC:
                    pdialog_proc = MakeProcInstance( NumericDlgProc, hInst );
                    DialogBox( hInst, "NumericFields", hWnd, pdialog_proc );
                    FreeProcInstance( pdialog_proc );
                    break;
                case IDM_EXIT:
                    SendMessage( hWnd, WM_CLOSE, 0, 0 );
                    break;
                case IDM_ABOUT:
                    pdialog_proc = MakeProcInstance( AboutDlgProc, hInst );
                    DialogBox( hInst, "AboutWEDL", hWnd, pdialog_proc );
                    FreeProcInstance( pdialog_proc );
                    break;
            }
            break;
        case WM_DESTROY:
            PostQuitMessage( 0 );
            break;
        default:
            return( DefWindowProc( hWnd, message, wParam, lParam ) );
    }
    return( 0 );
}

/*---------------------------------------------------------------------------*/

int FAR PASCAL AboutDlgProc( HWND hDlg, unsigned message, WORD wParam,
                             LONG lParam )
{
    switch( message ) {
        case WM_INITDIALOG:
            return( TRUE );
        case WM_COMMAND:
            if( wParam == IDOK || wParam == IDCANCEL ) {
                EndDialog( hDlg, TRUE );
                return( TRUE );
            }
            break;
    }
    return( FALSE );
}

/*---------------------------------------------------------------------------*/

static BOOL initialize_application( HANDLE hInstance )
{
    WNDCLASS wc;

    wc.style         = NULL;
    wc.lpfnWndProc   = (WNDPROC) MainWndProc;
    wc.cbClsExtra    = 0;
    wc.cbWndExtra    = 0;
    wc.hInstance     = hInstance;
    wc.hIcon         = LoadIcon( hInstance, "WEDL" );
    wc.hCursor       = LoadCursor( NULL, IDC_ARROW );
    wc.hbrBackground = GetStockObject( NULL_BRUSH );
    wc.lpszMenuName  = "MainMenu";
    wc.lpszClassName = szClassName;

    return( RegisterClass( &wc ) );
}

/*---------------------------------------------------------------------------*/

static BOOL initialize_instance( HANDLE hInstance, int nCmdShow )
{
    HWND hWnd;
    int ht_border, ht_caption, ht_menu, wd_border;

    hInst = hInstance;

    wd_border  = GetSystemMetrics( SM_CXBORDER );
    ht_border  = GetSystemMetrics( SM_CYBORDER );
    ht_caption = GetSystemMetrics( SM_CYCAPTION );
    ht_menu    = GetSystemMetrics( SM_CYMENU );

    hBitmap = LoadBitmap( hInstance, "WEDL" );
    GetObject( hBitmap, sizeof( BITMAP ), (LPSTR) &bitmap );

    hWnd = CreateWindow(
                szClassName, "WEDL Demonstration Program",
                WS_OVERLAPPED | WS_SYSMENU | WS_CAPTION  | WS_MINIMIZEBOX,
                65, 35, bitmap.bmWidth + wd_border + wd_border,
                bitmap.bmHeight + ht_border + ht_border + ht_caption + ht_menu,
                NULL, NULL, hInstance, NULL );

    if( hWnd == NULL ) return( FALSE );

    ShowWindow( hWnd, nCmdShow );
    UpdateWindow( hWnd );
    return( TRUE );
}

/*---------------------------------------------------------------------------*/

BOOL FAR PASCAL error_func( HFORM hform, HFIELD hfield, int error_value,
                            int error_position, int error_event )
{
    HWND hDlg;

    hDlg = form_get_hdlg( hform );
    switch( error_value ) {
        case BAD_DATE:
            MessageBox( hDlg, "Date Is Invalid", NULL, MB_OK );
            break;
        case BAD_STATE:
            MessageBox( hDlg, "Invalid State Code", NULL, MB_OK );
            break;
        case BAD_ZIP:
            MessageBox( hDlg, error_position > 1 ? "Zip Code is incomplete"
                        : "Zip code is invalid for given State", NULL, MB_OK );
            break;
        case BAD_FILENAME:
            MessageBox( hDlg, "File Not In Directory", NULL, MB_OK );
            break;
        default:
            return( FALSE );        /* error wasn't handled */
    }
    return( TRUE );                 /* error was handled */
}

/*****************************************************************************/
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*------------------------/                           \----------------------*/
/*------------------------ Employee Information Dialog ----------------------*/
/*------------------------\                           /----------------------*/
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*****************************************************************************/

#define IDHELP 998

/*---------------------------------------------------------------------------*/

/* state/ZIP code table */

struct states_t {
    PSTR state_code;
    int zip_low;
    int zip_high;
};

static struct states_t states[] = {
    { "AK", 995, 999 },     /* Alaska               */
    { "AL", 350, 369 },     /* Alabama              */
    { "AR", 716, 729 },     /* Arkansas             */
    { "AZ", 850, 865 },     /* Arizona              */
    { "CA", 900, 961 },     /* California           */
    { "CO", 800, 816 },     /* Colorado             */
    { "CT",  60,  69 },     /* Connecticut          */
    { "DE", 197, 199 },     /* Delaware             */
    { "FL", 320, 349 },     /* Florida              */
    { "GA", 300, 319 },     /* Georgia              */
    { "HI", 967, 968 },     /* Hawaii               */
    { "IA", 500, 528 },     /* Iowa                 */
    { "ID", 832, 847 },     /* Idaho                */
    { "IL", 600, 629 },     /* Illinois             */
    { "IN", 460, 479 },     /* Indiana              */
    { "KS", 641, 679 },     /* Kansas               */
    { "KY", 400, 427 },     /* Kentucky             */
    { "LA", 700, 714 },     /* Louisiana            */
    { "MA",  10,  27 },     /* Massachusetts        */
    { "MD", 206, 219 },     /* Maryland             */
    { "ME",  39,  49 },     /* Maine                */
    { "MI", 480, 499 },     /* Michigan             */
    { "MN", 550, 567 },     /* Minnesota            */
    { "MO", 630, 658 },     /* Missouri             */
    { "MS", 386, 397 },     /* Mississippi          */
    { "MT", 590, 599 },     /* Montana              */
    { "NC", 270, 289 },     /* North Carolina       */
    { "ND", 580, 588 },     /* North Dakota         */
    { "NE", 680, 693 },     /* Nebraska             */
    { "NH",  30,  38 },     /* New Hampshire        */
    { "NJ",  70,  89 },     /* New Jersey           */
    { "NM", 870, 884 },     /* New Mexico           */
    { "NV", 889, 898 },     /* Nevada               */
    { "NY", 100, 149 },     /* New York             */
    { "OH", 430, 458 },     /* Ohio                 */
    { "OK", 730, 749 },     /* Oklahoma             */
    { "OR", 970, 979 },     /* Oregon               */
    { "PA", 150, 196 },     /* Pennsylvania         */
    { "RI",  27,  29 },     /* Rhode Island         */
    { "SC", 290, 299 },     /* South Carolina       */
    { "SD", 570, 577 },     /* South Dakota         */
    { "TN", 370, 385 },     /* Tennessee            */
    { "TX", 750, 885 },     /* Texas                */
    { "UT", 840, 847 },     /* Utah                 */
    { "VA", 220, 246 },     /* Virginia             */
    { "VT",  50,  59 },     /* Vermont              */
    { "WA", 980, 994 },     /* Washington           */
    { "WI", 530, 549 },     /* Wisconsin            */
    { "WV", 247, 268 },     /* West Virginia        */
    { "WY", 820, 831 },     /* Wyoming              */
    { "DC", 200, 205 },     /* District of Columbia */
    { "GU",   0, 999 },     /* Guam                 */
    { "PR",   0, 999 },     /* Puerto Rico          */
    { "VI",   0, 999 },     /* Virgin Islands       */
    { "ON",   0, 999 },     /* Ontario              */
    { "PQ",   0, 999 },     /* Quebec               */
    { "BC",   0, 999 },     /* British Columbia     */
    { "AB",   0, 999 },     /* Alberta              */
    { "SK",   0, 999 },     /* Saskatchewan         */
    { "MB",   0, 999 },     /* Manitoba             */
    { "NS",   0, 999 },     /* Nova Scotia          */
    { "NB",   0, 999 },     /* New Brunswick        */
    { "NF",   0, 999 },     /* Newfoundland         */
    { "PE",   0, 999 },     /* Prince Edward Island */
    { NULL,   0,   0 }      /* --- end of table --- */
};

/*---------------------------------------------------------------------------*/

int FAR PASCAL EmployeeDlgProc( HWND hDlg, unsigned message, WORD wParam,
                                LONG lParam )
{
    static HFORM hform = NULL;
    static char first_name[16]="", mid_init[2]="", last_name[21]="";
    static char address[31]="", city[16]="", state[3]="", zip_code[10]="";
    static char soc_sec_no[10]="", phone_num[11]="", hire_date[9]="";
    static double wage = 0.0;

    switch( message ) {
        case WM_INITDIALOG:
            hform = form_begin( hDlg, FMF_NOSELECT | FMF_VKEYPRES |
                                FMF_VLEAVFLD | FMF_UPDATE | FMF_OVERTYPE,
                                perror_func );
            form_set_help( hform, "demohelp.hlp", 0 );
            field_define( hform, IDD_SSN, soc_sec_no, FDT_STRING,
                          "<0..7>99'-'99'-'9(4)", FDF_NOTBLANK | FDF_COMPLETE,
                          NULL, 0, IDH_SSN );
            field_define( hform, IDD_FNAME, first_name, FDT_STRING,
                          "A(15)", FDF_PROPER,
                          NULL, 0, IDH_FNAME );
            field_define( hform, IDD_MIDINIT, mid_init, FDT_STRING,
                          "A(1)'.'",  FDF_UPPER, NULL, 0, IDH_MIDINIT );
            field_define( hform, IDD_LNAME, last_name, FDT_STRING,
                          "<A..Z>A(19)", FDF_PROPER,
                          NULL, 0, IDH_LNAME );
            field_define( hform, IDD_ADDRESS, address, FDT_STRING,
                          "?(30)", FDF_PROPER,
                          NULL, 0, IDH_ADDRESS );
            field_define( hform, IDD_CITY, city, FDT_STRING,
                          "?(15)", FDF_PROPER,
                          NULL, 0, IDH_CITY );
            field_define( hform, IDD_STATE, state, FDT_STRING,
                          "A(2)", FDF_COMPLETE | FDF_UPPER,
                          pcheck_state, BAD_STATE, IDH_STATE );
            field_define( hform, IDD_ZIP, zip_code, FDT_STRING,
                          "<0..9>(5)'-'9(4)", FDF_NONE,
                          pcheck_zip_code, BAD_ZIP, IDH_ZIP );
            field_define( hform, IDD_PHONE, phone_num, FDT_STRING,
                          "'('999') '999'-'9999", FDF_COMPLETE,
                          NULL, 0, IDH_PHONE );
            field_define( hform, IDD_HIREDATE, hire_date, FDT_STRING,
                          " <01> 9 / <0123> 9 / <89> 9 ", FDF_COMPLETE |
                          FDF_PHYSICAL, pcheck_date, BAD_DATE, IDH_HIREDATE );
            field_define( hform, IDD_WAGE, &wage, FDT_DOUBLE,
                          "'$'999999.99", FDF_NUMERIC | FDF_BLNKZERO |
                          FDF_BLNKNEZ, NULL, 0, IDH_WAGE );
            keystat_define( hform, IDD_INSERT, KSM_INSERT, "Insert: On",
                            "Insert: Off" );
            generic_define( hform, IDHELP, 0 );
            form_end( hform );
            return( TRUE );

        case WM_COMMAND:
            switch( wParam ) {
                case IDOK:
                    form_ok( hform );
                    EndDialog( hDlg, TRUE );
                    sprintf( tbuf, "Soc Sec No.\t= %s\n"
                             "Name\t\t= %s %s. %s\nAddress\t\t= %s\n"
                             "\t\t= %s, %s %.5s-%s\nPhone No.\t= %s\n"
                             "Hire Date\t= %s\nWage/Salary\t= %.2lf",
                             soc_sec_no, first_name, mid_init, last_name,
                             address, city, state, zip_code, zip_code+5,
                             phone_num, hire_date, wage );
                    MessageBox( NULL, tbuf, "Field Contents", MB_OK );
                    return( TRUE );
                case IDCANCEL:
                    form_cancel( hform );
                    EndDialog( hDlg, TRUE );
                    return( TRUE );
                case IDHELP:
                    WinHelp( hDlg, "demohelp.hlp", HELP_INDEX, NULL );
                    return( TRUE );
            }
            break;

        case WM_CLOSE:
            SendMessage( hDlg, WM_COMMAND, IDCANCEL, 0 );
            return( TRUE );
    }
    return( FALSE );
}

/*---------------------------------------------------------------------------*/

int FAR PASCAL check_date( HFORM hform, HFIELD hfield, LPSTR pbuf )
{
    char date[10];
    int month, day, year;

    if( !str_is_blank( pbuf ) ) {

        /* parse year, day, and month from buffer */
        lstrcpy( date, pbuf );
        year = 1900 + atoi( date+4 );
        *( date+4 ) = '\0';
        day = atoi( date+2 );
        *( date+2 ) = '\0';
        month = atoi( date );

        /* validate month */
        if( month > 12 ) return( 1 );

        /* validate day and month */
        if( day < 1 ) return( 3 );
        switch( month ) {
            case 2:
                if( year%4 ) {
                    if( day > 29 ) return( 3 );
                }
                else {
                    if( day > 28 ) return( 3 );
                }
                break;
            case 1:
            case 3:
            case 5:
            case 7:
            case 8:
            case 10:
            case 12:
                if( day > 31 ) return( 3 );
                break;
            case 4:
            case 6:
            case 9:
            case 11:
                if( day > 30 ) return( 3 );
                break;
            default:
                return( 1 );
        }
    }

    /* return zero indicating no error */
    return( 0 );
}

/*---------------------------------------------------------------------------*/

int FAR PASCAL check_state( HFORM hform, HFIELD hfield, LPSTR pbuf )
{
    int i;

    /* allow state to be blank */
    if( str_is_blank( pbuf ) ) return( 0 );

    /* do for all state codes in the table */
    for( i = 0 ; states[i].state_code != NULL ; i++ )

        /* if state code was found, then no error */
        if( !lstrcmp( states[i].state_code, pbuf ) ) return( 0 );

    /* not a legal 2-letter state code */
    return( 1 );
}

/*---------------------------------------------------------------------------*/

int FAR PASCAL check_zip_code( HFORM hform, HFIELD hfield, LPSTR pbuf )
{
    LPSTR p;
    int i, num_spaces;
    long zip, zip_low, zip_high;

    /* allow zip code to be blank */
    if( str_is_blank( pbuf ) ) return( 0 );

    /* count spaces in the extended portion of the 9-digit zip code */
    num_spaces = 0;
    for( p = pbuf + 5 ; *p != '\0' ; p++ ) if( *p == ' ' ) num_spaces++;

    /* if zip code isn't exactly 5 or 9 digits, then there's an error */
    if( num_spaces != 0 && num_spaces != 4 ) return( 6 );

    *( pbuf+5 ) = '\0';
    field_log_to_data( hfield, pbuf, &zip, FDT_LONG );

    /* find matching state */
    hfield = field_get_from_ctrl_id( hform, IDD_STATE );
    field_get_text( hfield, tbuf, FALSE );
    for( i = 0 ; states[i].state_code != NULL ; i++ ) {
        if( !lstrcmp( tbuf, states[i].state_code ) ) break;
    }
    if( states[i].state_code == NULL ) return( 0 );

    /* test zip code */
    zip_low  = ( (long) ( states[i].zip_low ) ) * 100L;
    zip_high = ( (long) ( states[i].zip_high ) ) * 100L;
    if( zip >= zip_low && zip <= zip_high ) return( 0 );
    return( 1 );
}

/*****************************************************************************/
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*------------------------/                          \-----------------------*/
/*------------------------    Album Database Dialog   -----------------------*/
/*------------------------\                          /-----------------------*/
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*****************************************************************************/

/* prototypes for Album Database dialog */

static void fill_media_list_box( HWND hDlg );
static int get_record( int recno );
static BOOL okay_to_save_changes( HWND hDlg );
static void update_record( int recno );

/*---------------------------------------------------------------------------*/

/* albums "file" */

struct albums_t {
    char artist[25+1];
    char title[30+1];
    char label[15+1];
    int copyright;
    char media[15+1];
};

static struct albums_t albums[] = {
    { "Aerosmith", "Pump", "Geffen", 1989, "Compact Disc" },
    { "Bell Biv Devoe", "Poison", "MCA", 1990, "Cassette" },
    { "The Cure", "Disintegration", "Elektra", 1989, "Compact Disc" },
    { "Front 242", "Front by Front", "Wax Trax", 1988, "Compact Disc" },
    { "INXS", "Kick", "Atlantic", 1987, "Cassette" },
    { "Janet Jackson", "Control", "A&M", 1986, "Cassette" },
    { "Kenny G", "Live", "Arista", 1989, "Compact Disc" },
    { "R.E.M.", "Out of Time", "Warner Bros.", 1991, "Cassette" },
    { "Sex Pistols", "Never Mind the Bollocks", "Warner Bros.", 1977, "Record" },
    { "Van Halen", "OU812", "Warner Bros.", 1988, "Compact Disc" },
};

/*---------------------------------------------------------------------------*/

/* buffer area to use for editing Albums "file" */

static char artist[25+1];
static char title[30+1];
static char label[15+1];
static int  copyright;
static char media[15+1];

/*---------------------------------------------------------------------------*/

/* media type table */

static PSTR media_types[] = { "Compact Disc", "Cassette", "Record", "DAT",
                              "Mini Disc", "DCC", "Open Reel", "8-Track",
                              NULL };

/*---------------------------------------------------------------------------*/

int FAR PASCAL AlbumDlgProc( HWND hDlg, unsigned message, WORD wParam,
                             LONG lParam )
{
    static HFORM hform = NULL;
    static int curr_rec = 0;
    int new_rec;

    switch( message ) {
        case WM_INITDIALOG:
            curr_rec = get_record( 1 );
            hform = form_begin( hDlg, FMF_UPDATE, NULL );
            form_set_help( hform, "demohelp.hlp", 0 );
            field_define( hform, IDD_RECNO, &curr_rec, FDT_INTEGER, "999",
                          FDF_NOTEDIT, NULL, 0, IDH_RECNO );
            field_define( hform, IDD_ARTIST, artist, FDT_STRING, "?(25)",
                          FDF_NOTBLANK, NULL, 0, IDH_ARTIST );
            field_define( hform, IDD_TITLE, title, FDT_STRING, "?(30)",
                          FDF_NONE, NULL, 0, IDH_TITLE );
            field_define( hform, IDD_LABEL, label, FDT_STRING, "?(15)",
                          FDF_NONE, NULL, 0, IDH_LABEL );
            field_define( hform, IDD_COPYRIGHT, &copyright, FDT_INTEGER, "<1><9>99",
                          FDF_COMPLETE, NULL, 0, IDH_COPR );
            field_define( hform, IDD_MEDIA, media, FDT_STRING, "?(15)",
                          FDF_COMBO | FDF_NOTBLANK, NULL, 0, IDH_MEDIA );
            keystat_define( hform, IDD_INSERT,   KSM_INSERT,   "[Ins]",  "" );
            keystat_define( hform, IDD_CAPSLOCK, KSM_CAPSLOCK, "[Caps]", "" );
            keystat_define( hform, IDD_NUMLOCK,  KSM_NUMLOCK,  "[Num]",  "" );
            form_end( hform );
            fill_media_list_box( hDlg );
            return( TRUE );

        case WM_COMMAND:
            switch( wParam ) {
                case IDOK:
                    form_ok( hform );
                    EndDialog( hDlg, TRUE );
                    return( TRUE );
                case IDCANCEL:
                    form_cancel( hform );
                    EndDialog( hDlg, TRUE );
                    return( TRUE );
                case IDD_PREVIOUS:
                case IDD_NEXT:
                    if( form_validate( hform ) != NULL ) return( TRUE );
                    if( form_has_changed( hform ) ) {
                        if( okay_to_save_changes( hDlg ) ) {
                            form_save( hform );
                            update_record( curr_rec );
                        }
                    }
                    new_rec = ( wParam == IDD_PREVIOUS )
                                 ? ( curr_rec - 1 ) : ( curr_rec + 1 );
                    new_rec = get_record( new_rec );
                    if( new_rec == -1 )
                        MessageBeep( 0 );
                    else
                        curr_rec = new_rec;
                    form_load( hform );
                    PostMessage( hDlg, WM_COMMAND, GOTO_ARTIST, 0 );
                    return( TRUE );
                case GOTO_ARTIST:
                    SetFocus( GetDlgItem( hDlg, IDD_ARTIST ) );
                    return( TRUE );
            }
            break;
        case WM_CLOSE:
            SendMessage( hDlg, WM_COMMAND, IDCANCEL, 0 );
            return( TRUE );
    }
    return( FALSE );
}

/*---------------------------------------------------------------------------*/

static void fill_media_list_box( HWND hDlg )
{
    int i;
    for( i = 0 ; media_types[i] != NULL ; i++ ) {
        SendMessage( GetDlgItem( hDlg, IDD_MEDIA ), CB_ADDSTRING, 0,
                     (LONG) ( (LPSTR) media_types[i] ) );
    }
}

/*---------------------------------------------------------------------------*/

/* gets a record from the Albums "file" */

static int get_record( int recno )
{
    int last_rec, ofs;

    last_rec = sizeof( albums ) / sizeof( albums[0] );
    if( recno < 1 || recno > last_rec ) return( -1 );
    ofs = recno - 1;
    lstrcpy( artist, albums[ofs].artist );
    lstrcpy( title,  albums[ofs].title );
    lstrcpy( label,  albums[ofs].label );
    copyright = albums[ofs].copyright;
    lstrcpy( media,  albums[ofs].media );
    return( recno );
}

/*---------------------------------------------------------------------------*/

static BOOL okay_to_save_changes( HWND hDlg )
{
    return( MessageBox( hDlg, "Record has changed.  Save changes?",
                        "Record Has Changed",
                        MB_ICONQUESTION | MB_YESNO ) == IDYES );
}

/*---------------------------------------------------------------------------*/

/* updates a record in the Albums "file" */

static void update_record( int recno )
{
    int ofs;

    ofs = recno - 1;
    lstrcpy( albums[ofs].artist, artist );
    lstrcpy( albums[ofs].title, title );
    lstrcpy( albums[ofs].label, label );
    albums[ofs].copyright = copyright;
    lstrcpy( albums[ofs].media, media );
}

/*****************************************************************************/
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*------------------------/                          \-----------------------*/
/*------------------------    Upload File Dialog      -----------------------*/
/*------------------------\                          /-----------------------*/
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*****************************************************************************/

/* prototypes for Upload File dialog */

static void fill_list_boxes( HWND hDlg, PSTR pathspec );

/*---------------------------------------------------------------------------*/

/* protocol name table */

static PSTR protocols[] = { "Xmodem", "Ymodem", "Zmodem" };

/*---------------------------------------------------------------------------*/

int FAR PASCAL UploadDlgProc( HWND hDlg, unsigned message, WORD wParam,
                              LONG lParam )
{
    static HFORM hform = NULL;
    static int protocol = 0, hangup;
    static char path_spec[81], file_name[13];
    static HFIELD hfile_name;

    switch( message ) {
        case WM_INITDIALOG:
            hform = form_begin( hDlg, FMF_NONE, perror_func );
            form_set_help( hform, "demohelp.hlp", 0 );
            hfile_name = field_define( hform, IDD_FILENAME, file_name,
                                       FDT_STRING, "F(12)", FDF_NOTBLANK,
                                       pcheck_file_name, BAD_FILENAME,
                                       IDH_FILENAME );
            form_set_enable_link( hform, (HANDLE) hfile_name, ELC_BLANK, IDOK,
                                  FALSE );
            generic_define( hform, IDD_FILEBOX, IDH_FILEBOX );
            generic_define( hform, IDD_DIRBOX, IDH_DIRBOX );
            button_define( hform, IDD_XMODEM, &protocol, 1, 0, 0,
                           BTF_UPDATE, IDH_XMODEM );
            button_define( hform, IDD_YMODEM, &protocol, 1, 1, 0,
                           BTF_UPDATE, IDH_YMODEM );
            button_define( hform, IDD_ZMODEM, &protocol, 1, 2, 0,
                           BTF_UPDATE, IDH_ZMODEM );
            button_define( hform, IDD_HANGUP, &hangup, 0, TRUE, FALSE,
                           BTF_NONE, IDH_HANGUP );
            form_end( hform );
            fill_list_boxes( hDlg, "*.*" );
            return( TRUE );

        case WM_COMMAND:
            switch( wParam ) {
                case IDOK:
                    form_ok( hform );
                    GetDlgItemText( hDlg, IDD_PATHSPEC, path_spec, 80 );
                    EndDialog( hDlg, TRUE );
                    wsprintf( tbuf, "Uploading the file:  %s%s%s\n"
                              "Using the %s protocol.\n"
                              "Will %shang up after transfer.",
                              (LPSTR) path_spec,
                              *( path_spec + lstrlen( path_spec ) - 1 )
                              == '\\' ? (LPSTR) "" : (LPSTR) "\\",
                              (LPSTR) file_name,
                              (LPSTR) protocols[protocol],
                              hangup ? (LPSTR) "" : (LPSTR) "not " );
                    MessageBox( NULL, tbuf, "Upload File", MB_OK );
                    return( TRUE );

                case IDCANCEL:
                    form_cancel( hform );
                    EndDialog( hDlg, TRUE );
                    return( TRUE );

                case IDD_FILEBOX:
                    if( HIWORD( lParam ) == LBN_SELCHANGE ) {
                        SendDlgItemMessage( hDlg, IDD_FILEBOX, LB_GETTEXT,
                                            (int) SendDlgItemMessage( hDlg,
                                            IDD_FILEBOX, LB_GETCURSEL, 0, 0 ),
                                            (LONG) ( (LPSTR) tbuf ) );
                        field_set_text( hfile_name, tbuf, TRUE );
                        return( TRUE );
                    }
                    if( HIWORD( lParam ) == LBN_DBLCLK ) {
                        PostMessage( hDlg, WM_COMMAND, IDOK,
                                     (LONG) GetDlgItem( hDlg, IDOK ) );
                        return( TRUE );
                    }
                    break;

                case IDD_DIRBOX:
                    if( HIWORD( lParam ) == LBN_DBLCLK ) {
                        DlgDirSelect( hDlg, path_spec, IDD_DIRBOX );
                        field_set_text( hfile_name, "", TRUE );
                        lstrcat( path_spec, "*.*" );
                        fill_list_boxes( hDlg, path_spec );
                        return( TRUE );
                    }
                    break;
            }
            break;
        case WM_CLOSE:
            SendMessage( hDlg, WM_COMMAND, IDCANCEL, 0 );
            return( TRUE );
    }
    return( FALSE );
}

/*---------------------------------------------------------------------------*/

int FAR PASCAL check_file_name( HFORM hform, HFIELD hfield, LPSTR pbuf )
{
    char file_name[13];

    lstrcpy( file_name, pbuf );
    str_trim_spaces( file_name );
    return( ( SendDlgItemMessage( GetParent( GetFocus() ), IDD_FILEBOX,
            LB_FINDSTRING, (WPARAM) -1, (LONG) ( (LPSTR) file_name ) ) == LB_ERR )
            ? 1 : 0 );
}

/*---------------------------------------------------------------------------*/

static void fill_list_boxes( HWND hDlg, PSTR pathspec )
{
    DlgDirList( hDlg, pathspec, IDD_FILEBOX, 0, 0x0001 | 0x0020 );
    DlgDirList( hDlg, pathspec, IDD_DIRBOX, IDD_PATHSPEC, 0x0010 | 0x4000 |
                0x8000 );
}

/*****************************************************************************/
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*------------------------/                          \-----------------------*/
/*------------------------   Numeric Fields Dialog     ----------------------*/
/*------------------------\                          /-----------------------*/
/*---------------------------------------------------------------------------*/
/*---------------------------------------------------------------------------*/
/*****************************************************************************/

int FAR PASCAL NumericDlgProc( HWND hDlg, unsigned message, WORD wParam,
                              LONG lParam )
{
    static HFORM hform = NULL;
    static long std = 0;
    static unsigned long zerofill = 0;
    static unsigned int calc = 0;
    static double stddec = 0.0, calcdec = 0.0, real= 0.0;

    switch( message ) {

        case WM_INITDIALOG:
            hform = form_begin( hDlg, FMF_OVERTYPE | FMF_NOSELECT | FMF_UPDATE,
                                NULL );
            field_define( hform, IDD_STD, &std, FDT_LONG,
                          "N(7)", FDF_NUMERIC, NULL, 0, 0 );
            field_define( hform, IDD_STDDEC, &stddec, FDT_DOUBLE,
                          "9(5).99", FDF_NUMERIC, NULL, 0, 0 );
            field_define( hform, IDD_ZEROFILL, &zerofill, FDT_ULONG,
                          "9(9)", FDF_NUMERIC | FDF_ZEROFILL, NULL, 0, 0 );
            field_define( hform, IDD_CALC, &calc, FDT_UNSIGNED,
                          "<0123456 >9(4)", FDF_CALCNUM | FDF_VLEAVFLD,
                          NULL, 0, 0 );
            field_define( hform, IDD_CALCDEC, &calcdec, FDT_DOUBLE,
                          "N,NNN,NNN.NN", FDF_CALCNUM, NULL, 0, 0 );
            field_define( hform, IDD_REAL, &real, FDT_DOUBLE,
                          "#(9)", FDF_NUMERIC, NULL, 0, 0 );
            keystat_define( hform, IDD_INSERT, KSM_INSERT, "(Ins)", "(Ovr)" );
            form_end( hform );
            return( TRUE );

        case WM_COMMAND:
            switch( wParam ) {
                case IDOK:
                    form_ok( hform );
                    EndDialog( hDlg, TRUE );
                    sprintf( tbuf, "%ld\t%.2lf\n%lu\t%u\n%.2lf\n%le\n", std,
                             stddec, zerofill, calc, calcdec, real );
                    MessageBox( NULL, tbuf, "Field Contents", MB_OK );
                    return( TRUE );
                case IDCANCEL:
                    form_cancel( hform );
                    EndDialog( hDlg, TRUE );
                    return( TRUE );
            }
            break;

        case WM_CLOSE:
            SendMessage( hDlg, WM_COMMAND, IDCANCEL, 0 );
            return( TRUE );

    }
    return( FALSE );
}

