/*
   Windows 3.0 Bitmap Loader

   Version 1.00

   Started:    February 28, 1992
   Finished:

   Developer : Jim Huang
*/

#include <windows.h>
#include <stdlib.h>
#include <direct.h>
#include <time.h>
#include <dos.h>

#include "bmploadr.h"

        /* Windows Function - Prototyping */
long FAR PASCAL WndProc         (HWND, WORD, WORD, LONG);
BOOL FAR PASCAL AboutDlgProc    (HWND, WORD, WORD, LONG);
BOOL FAR PASCAL FileDlgProc     (HWND, WORD, WORD, LONG);
BOOL FAR PASCAL SetupDlgProc     (HWND, WORD, WORD, LONG);

BOOL extern FAR PASCAL SetDeskWallPaper (LPSTR);

void SetNextBMP (LPSTR);

HANDLE hInst;                 /* Handle to Windows instances   */
char   szAppName[] = "BMP",   /* Application Name              */
       szFileName[96],
       szCurDir[96],
       Random[4], AutoLoad[4];

int PASCAL WinMain (HANDLE hInstance, HANDLE hPrevInstance,
            LPSTR lpszCmdLine, int nCmdShow)
    {
    HWND     hwnd;       /* Handle to the main Window            */
    MSG      msg;        /* MSG structure to store your messages */
    WNDCLASS wndclass;   /* Windows class structure              */
    HANDLE   hAccel;     /* Handle to the accelerator keys       */

    hInst = hInstance;   /* Handle for Windows instances     */

    /* Create the application window */
    if (!hPrevInstance)
       {
       wndclass.style         = CS_HREDRAW | CS_VREDRAW | CS_BYTEALIGNWINDOW;
       wndclass.lpfnWndProc   = WndProc;
       wndclass.cbClsExtra    = 0;
       wndclass.cbWndExtra    = 0;
       wndclass.hInstance     = hInst;
       wndclass.hIcon         = LoadIcon (hInstance, szAppName);
       wndclass.hCursor       = LoadCursor (NULL, IDC_ARROW);
       wndclass.hbrBackground = GetStockObject (WHITE_BRUSH);
       wndclass.lpszMenuName  = szAppName;
       wndclass.lpszClassName = szAppName;

       RegisterClass (&wndclass);
       }


     /* Create the application windows */
    hwnd = CreateWindow (szAppName, "Bitmap Loader",
          WS_CAPTION      | WS_SYSMENU      |
          WS_MINIMIZEBOX  | WS_CLIPCHILDREN | WS_OVERLAPPED,
          0, 0, 190, 40, NULL, NULL, hInstance, NULL);

    ShowWindow (hwnd, nCmdShow);
    UpdateWindow (hwnd);

    /* Load the accelerator table */
    hAccel = LoadAccelerators (hInstance, szAppName);

    /* Message Handling Loop */
    while (GetMessage (&msg, NULL, 0, 0))
    {
    if (!TranslateAccelerator (hwnd, hAccel, &msg))
      {
      TranslateMessage (&msg) ;
      DispatchMessage (&msg) ;
      }
    }

    return msg.wParam;
}

long FAR PASCAL WndProc (HWND hwnd, WORD message, WORD wParam, LONG lParam)
    {
    static HANDLE hInstance;    /* handle for each instances    */
    static HCURSOR hCursor;     /* handle for the cursor        */
    static HICON  hIcon;        /* handle for the icon          */

          /* Variables determining the position of the scroll bar */
    FARPROC   lpfn;                     /* Far Pointer for each dialog box       */
    HDC       hdc;                      /* handle for the display device         */
    HMENU     hmenu;                    /* handle for the menu                   */
    PAINTSTRUCT   ps;                   /* holds PAINT information               */
    char      szBuffer[80];
    short i;
    switch (message)
     {
     case WM_CREATE:
         /* The WM_CREATE message is sent once to a window when the */
         /* window is created.  The window procedure for the new window */
         /* receives this message after the window is created, but      */
         /* before the window becomes visible.                          */
         /*                                                             */
         /* Parameters:                                                 */
         /*                                                             */
         /*    lParam  -  Points to a CREATESTRUCT structure with       */
         /*               the following form:                           */
         /*                                                             */
         /*    typedef struct                                           */
         /*              {                                              */
         /*               LPSTR     lpCreateParams;                     */
         /*               HANDLE    hInst;                              */
         /*               HANDLE    hMenu;                              */
         /*               HWND      hwndParent;                         */
         /*               int       cy;                                 */
         /*               int       cx;                                 */
         /*               int       y;                                  */
         /*               int       x;                                  */
         /*               LONG      style;                              */
         /*               LPSTR     lpszName;                           */
         /*               LPSTR     lpszClass;                          */
         /*               DWORD     dwExStyle;                          */
         /*      }  CREATESTRUCT;                                       */

         hIcon = LoadIcon (hInstance, szAppName);
         hInstance = ((LPCREATESTRUCT) lParam)->hInstance;

         GetProfileString (szAppName, "BMPSource", NULL, szCurDir, sizeof (szCurDir));
         GetProfileString (szAppName, "Wallpaper", NULL, szFileName, sizeof (szFileName));
         GetProfileString (szAppName, "AutoLoad", NULL, AutoLoad, sizeof (AutoLoad));
         GetProfileString (szAppName, "Random", NULL, Random, sizeof (Random));

         if (lstrlen (szFileName)) {
           lstrcpy (szBuffer, szCurDir);
           lstrcat (szBuffer, "\\");
           lstrcat (szBuffer, szFileName);
           if (SetDeskWallPaper (szBuffer)) {
             SetWindowText (hwnd, szFileName);
             InvalidateRect (GetDesktopWindow(), NULL, TRUE);
           }
         }

         if (!lstrcmpi (Random, "On"))
           SetNextBMP (szCurDir);

         if (!lstrlen (szCurDir))
           SendMessage (hwnd, WM_COMMAND, IDM_SETUP, 0L);

         return 0;

     case WM_COMMAND:
         /* The Windows messages for action bar and pulldown menu items */
         /* are processed here.                                         */
         /* The WM_COMMAND message contains the message ID in its first */
         /* parameter (wParam). This routine is programmed to SWITCH on */
         /* the #define values for the menu items in the application's  */
         /* header (*.H) file. The ID values have the format, IDM_itemname. */
         /* The service routines for the various menu items follow      */
         /* the CASE statements up to the generated BREAK statements.   */

         /* Get the menu handle */
         hmenu = GetMenu (hwnd);

         switch (wParam) {
           case IDM_ABOUT:
             lpfn = MakeProcInstance (AboutDlgProc, hInstance);
             DialogBox (hInstance, "AboutDlg", hwnd, lpfn);
             FreeProcInstance (lpfn);
             return 0;

           case IDM_OPEN:
             lpfn = MakeProcInstance (FileDlgProc, hInstance);
             DialogBox (hInstance, "FileDlg", hwnd, lpfn);
             FreeProcInstance (lpfn);

             SetWindowText (hwnd, szFileName);

             return 0;

           case IDM_SETUP:
             lpfn = MakeProcInstance (SetupDlgProc, hInstance);
             DialogBox (hInstance, "SetupDlg", hwnd, lpfn);
             FreeProcInstance (lpfn);

             return 0;

           case IDM_EXIT:
             SendMessage (hwnd, WM_CLOSE, 0, 0L);
             return 0;
         }
         break;

     case WM_PAINT:
     /* Obtain a handle to the device context                       */
     /* BeginPaint will sends WM_ERASEBKGND if appropriate          */

       hdc = BeginPaint (hwnd, &ps);

       EndPaint (hwnd, &ps);

       return 0;

     /* Tell Window to close the application window.  Destroy the window */
     case WM_CLOSE:
       DestroyWindow (hwnd);
       return 0;

         /* Destroys the window */
     case WM_DESTROY:
       PostQuitMessage (0);
       return 0;
     }
     return DefWindowProc (hwnd, message, wParam, lParam);
}


/* ***************************************************************************** */

void SetNextBMP (LPSTR dir)
{
  char szBuffer[80];
  short i = 0, nextbmp, j;
  struct _find_t findt;

  lstrcpy (szBuffer, dir);
  lstrcat (szBuffer, "\\");
  lstrcat (szBuffer, "*.BMP");
  srand ((unsigned)time(NULL));
  nextbmp = rand();

  if (!_dos_findfirst (szBuffer, _A_NORMAL, &findt)) {
    i++;
    while (!_dos_findnext (&findt))
      i++;

    _dos_findfirst (szBuffer, _A_NORMAL, &findt);
    if (i == 0)
       WriteProfileString (szAppName, "Wallpaper", findt.name);
    else {
       for (j = 0; j < nextbmp % i; j++)
         _dos_findnext (&findt);
       WriteProfileString (szAppName, "Wallpaper", findt.name);
    }
  }
}


LPSTR lstrchr (LPSTR str, char ch)
{
  while (*str)
    {
    if (ch == *str)
    return str;

    str = AnsiNext (str);
    }

  return NULL;
}

LPSTR lstrrchr (LPSTR str, char ch)
{
  LPSTR strl = str + lstrlen (str);

  do {
    if (ch == *strl)
    return strl;

    strl = AnsiPrev (str, strl);
  } while (strl > str);

  return NULL;
}


/* ***************************************************************************** */


BOOL FAR PASCAL AboutDlgProc (HWND hDlg, WORD message, WORD wParam, LONG lParam)
{
   switch (message)
     {
     case WM_INITDIALOG:
       SetDlgItemText (hDlg, IDD_VER, "Version 1.00a");
       SetDlgItemText (hDlg, IDD_NAME, "Written by: Jim Huang");
       SetDlgItemText (hDlg, IDD_DATE, "Copyright ©1992");

       return TRUE;

     case WM_COMMAND:
       switch (wParam)
         {
         case IDOK:
           EndDialog (hDlg, 0);
           return TRUE;
         }
       break;
     }
   return FALSE;
}


BOOL FAR PASCAL FileDlgProc (HWND hDlg, WORD message, WORD wParam, LONG lParam)
{
    static char cLastChar, szFName[96] = "*.BMP", szFileSpec[16];
    char szBuffer[96];
    short nEditLen, count;
    WORD  wFileAttr;

    switch (message)
       {
       case WM_INITDIALOG:
         lstrcpy (szBuffer, szCurDir);
         SendDlgItemMessage (hDlg, IDD_FNAME, EM_LIMITTEXT, 80, 0L) ;
         DlgDirList (hDlg, szBuffer, IDD_DLIST, IDD_FPATH, 0x0010 | 0x4000 | 0x8000);
         DlgDirList (hDlg, "*.BMP", IDD_FLIST, IDD_FPATH, 0);
         SetDlgItemText (hDlg, IDD_FNAME, szFName);
         return TRUE;

       case WM_COMMAND:
         switch (wParam)
           {
           case IDD_FLIST:
             switch (HIWORD (lParam))
               {
               case LBN_SELCHANGE:
                 if (DlgDirSelect (hDlg, szFileName, IDD_FLIST))
                   lstrcat (szFileName, szFileSpec);
                 SetDlgItemText (hDlg, IDD_FNAME, szFileName);
                 return TRUE;

               case LBN_DBLCLK:
                 if (DlgDirSelect (hDlg, szFileName, IDD_FLIST)) {
                   lstrcat (szFileName, szFileSpec);
                   DlgDirList (hDlg, "*.BMP", IDD_FLIST, IDD_FPATH, 0);
                   SetDlgItemText (hDlg, IDD_FNAME, szFileSpec);
                 }
                 else {
                   SetDlgItemText (hDlg, IDD_FNAME, szFileName);
                   SendMessage (hDlg, WM_COMMAND, IDOK, 0L);
                 }
                 return TRUE ;
               }
             break;

           case IDD_DLIST:
             switch (HIWORD (lParam))
               {
               case LBN_DBLCLK:
                 if (DlgDirSelect (hDlg, szFileName, IDD_DLIST)) {
                   lstrcat (szFileName, szFileSpec);
                   DlgDirList (hDlg, szFileName, IDD_DLIST, IDD_FPATH, 0x0010 | 0x4000 | 0x8000);
                   DlgDirList (hDlg, "*.BMP", IDD_FLIST, IDD_FPATH, 0);
                 }
                 return TRUE ;
               }
             break;

           case IDD_FNAME:
             if (HIWORD (lParam) == EN_CHANGE)
                EnableWindow (GetDlgItem (hDlg, IDOK), (BOOL) SendMessage (LOWORD (lParam),
                              WM_GETTEXTLENGTH, 0, 0L));
             return TRUE;

           case IDOK:
             GetDlgItemText (hDlg, IDD_FNAME, szFileName, 80);

             nEditLen = lstrlen (szFileName);
             cLastChar = *AnsiPrev (szFileName, szFileName + nEditLen);

             if (cLastChar == '\\' || cLastChar == ':')
               lstrcat (szFileName, szFileSpec);

             if (lstrchr (szFileName, '*') || lstrchr (szFileName, '?')) {
               if (DlgDirList (hDlg, szFileName, IDD_FLIST, IDD_FPATH, wFileAttr)) {
                 lstrcpy (szFileSpec, szFileName);
                 SetDlgItemText (hDlg, IDD_FNAME, szFileSpec);
               }
               else
                 MessageBeep (0);

               return TRUE;
             }

             lstrcat (lstrcat (szFileName, "\\"), szFileSpec);

             if (DlgDirList (hDlg, szFileName, IDD_FLIST, IDD_FPATH, wFileAttr)) {
               lstrcpy (szFileSpec, szFileName);
               SetDlgItemText (hDlg, IDD_FNAME, szFileSpec);
               return TRUE;
             }

             szFileName[nEditLen] = '\0';

             if (SetDeskWallPaper (szFileName)) {
               WriteProfileString (szAppName, "Wallpaper", szFileName);
               WriteProfileString ("windows", "Wallpaper", "(None)");
               InvalidateRect (GetDesktopWindow(), NULL, TRUE);
             }

           case IDCANCEL :
             EndDialog (hDlg, FALSE);
             return TRUE;
           }
       }

    return FALSE;
}

BOOL FAR PASCAL SetupDlgProc (HWND hDlg, WORD message, WORD wParam, LONG lParam)
{
   switch (message)
     {
     case WM_INITDIALOG:
          if (lstrlen (szCurDir))
            SetDlgItemText (hDlg, IDD_DIRECTORY, szCurDir);

          if (!lstrcmpi (AutoLoad, "On"))
            CheckDlgButton (hDlg, IDD_CHECK1, 1);

          if (!lstrcmpi (Random, "On"))
            CheckDlgButton (hDlg, IDD_CHECK2, 1);

       return TRUE;

     case WM_COMMAND:
       switch (wParam)
         {
         case IDOK:
           GetDlgItemText (hDlg, IDD_DIRECTORY, szCurDir, sizeof (szCurDir));

           if (!lstrlen (szCurDir)) {
             MessageBox (hDlg, "Please Specify the BitMap Directory", NULL, MB_OK | MB_ICONSTOP);
             return FALSE;
           }

           WriteProfileString (szAppName, "BMPSource", szCurDir);

           if (IsDlgButtonChecked (hDlg, IDD_CHECK1))
             WriteProfileString (szAppName, "AutoLoad", "On");
           else
             WriteProfileString (szAppName, "AutoLoad", "Off");

           if (IsDlgButtonChecked (hDlg, IDD_CHECK2))
             WriteProfileString (szAppName, "Random", "On");
           else
             WriteProfileString (szAppName, "Random", "Off");

         case IDCANCEL:
           EndDialog (hDlg, 0);
           return TRUE;
         }
       break;
     }
   return FALSE;
}

