/*SDOC*************************************************************




WW      WW DDDDDDDDD  NN      NN 
WW      WW DDDDDDDDDD NNN     NN 
WW      WW DD      DD NNNN    NN 
WW      WW DD      DD NNNNN   NN 
WW      WW DD      DD NN NNN  NN 
WW  WW  WW DD      DD NN  NNN NN 
WW WWWW WW DD      DD NN   NNNNN 
WWWWWWWWWW DD      DD NN    NNNN 
WWWW  WWWW DDDDDDDDDD NN     NNN 
WWW    WWW DDDDDDDDD  NN      NN 

	$Header$

	Module: WDN

	Author:	Pat Beirne

	Copyright 1990 Corel Systems Corp.

	Description: 
		Windows version of DIRNOTES

	Things to do:
		all done....

*************************************************************EDOC*/

/*SDOC*************************************************************

  Revision Record

	Rev	Date		Auth	Changes
	===	====		====	=======

	0.0	26/11/90	pb  	start
	0.2	30/11/90 pb		internal release
	1.0	04/12/90 pb		release 1

*************************************************************EDOC*/


/*
**
**	 Includes
**
*/
#include <windows.h>
#include <stdio.h>
#include <io.h>
#include <dos.h>
#include <stdlib.h>
#include <fcntl.h>
#include <ctype.h>
#include <string.h>
#include <direct.h>

#include "wdn.h"

#ifndef DEBUG
#define MessageBeep(x) 
#define DD ;/##/ 
#else
#define DD DbugShow
#endif

/*::defn
**
**	 Defines
**
*/


#define MAX_BUF 2048		// the file read buffer

#define BROWN RGB(180,100,0)	// the text colors
#define BLACK RGB(30,50,0)


	/* ASCII */
#define BS  8
#define TAB  9
#define LF  10
#define FF  12
#define CR  13
#define ESC  27
#define TAB_SIZE 4

#define HMEM HANDLE

typedef struct tagDirEntry
{
	char	sName[9];		// always ends in space; left justified
	char	sExt[4];			// always ends in space; left justified
	char	sSize[8];		// in ascii decimal, right justified
	char 	sPad[2];
	char	sDate[8];
	char	sPad1[2];
	char	sTime[6];
	char	sNew[2];			// is either "U " or "  "
	char	sComment[38];	// pad out to 80 chars
	char	sCRLF[2];		// always CR/LF
} DIRENTRY;
#define POS_SIZE 13
#define POS_COMMENTS 41
#define LINE_LENGTH 81		// DOS converts CR/LF to CR only
/*::end*/


/*::decl
**
**	 Global Variables
**
*/

char szFrame[] = APP_NAME;
int 	hInst;		// the instance
HWND hWnd;			// the main (and only) window
HWND hListBox;		// the directory list box
HWND hEditBox;		// the edit control
char szBuf[LINE_LENGTH+1];
char szBuf2[LINE_LENGTH+1];

int 	fDirty = FALSE;	// set once the file has been modified
int	fLocalDirty = FALSE; // set onece the line has been modified
int	nCharWidth, nCharHeight;		// from the system font
int	nLBCharWidth, nLBCharHeight;	// from the mono-spaced system font
int	nScrollWidth;		// the width of the vscroll bar
OFSTRUCT ofs;						// holds the full name of the notes file
char	szFileName[_MAX_FNAME + _MAX_EXT + 1];	// the file to match to formated "nnnnnnnn eee"
char	szNoteFile[_MAX_FNAME + _MAX_EXT + 1];	// the file that holds the notes form "nnnnnnnn.eee"
char	szFName[_MAX_FNAME];		// scratch
char	szExt[_MAX_EXT];			// scratch
char	szDrive[_MAX_DRIVE];		// the path we're working on
char	szDir[_MAX_DIR];			// the drive we're working on

FARPROC lpEditProc;				// holds the sub-classed edit proc
FARPROC lpEditSubClassProc;
FARPROC lpDirsProc;				// holds the sub-classed dir listbox proc
FARPROC lpDirsSubClassProc;
/*::end*/


/*::fnproto
**
**	 Function Prototypes
**
*/
void Paint(HWND hwnd);
LONG FAR PASCAL FrameWndProc (HWND hwnd, WORD msg,WORD wParam, LONG lParam );
void cdecl far DbugShow(HWND hWind,char *szFormat,...);
HWND WakeUp(HANDLE hInst, int nStartup);
int  Init(void);
WORD FillListBox(HWND hListBox);
void LocateChildWindows(HWND hWnd);
BOOL CommandLine(LPSTR lpCmdLine);
BOOL SaveFile(HWND hWnd);
void CopyComments(HWND hListBox, HWND hEditBox);
int  SearchForGivenFile(HWND hLB);
char *StripWhiteSpace(char *str);
void NewDir(HWND hwnd,HWND hDirs);
BOOL ParseAndFill(HWND hWnd, LPSTR lpCmdLine);
BOOL FAR PASCAL AboutBox(HWND hDlg, WORD message, WORD wParam, LONG lParam);
LONG FAR PASCAL EditSubClassProc(HWND hEdit, WORD message, WORD wParam, LONG lParam);
LONG FAR PASCAL DirsSubClassProc(HWND hList, WORD message, WORD wParam, LONG lParam);

/*::end*/


/*
**
**	 Local Variables
**
*/





/*SDOC*************************************************************

	Name: WinMain

	Action: 1) wake up the instance; create the class, if required
			2) parse the command line; try to find the file
			3) wake up the main window
			4) message loop

	Returns: when user quits

*************************************************************EDOC*/

extern int __argc;
extern char **__argv;


int NEAR PASCAL WinMain(hInstance, hPrevInstance, lpszCmdLine, nCmdShow)

HANDLE hInstance;
HANDLE hPrevInstance;
LPSTR  lpszCmdLine;
int    nCmdShow;
{
	MSG msg;
	HWND hWnd;

    hInst = hInstance;
    /* If this is the first instance of the app. register window classes */
    if (!hPrevInstance)
		if (!Init()) return FALSE;


	hWnd = WakeUp(hInstance,nCmdShow);
	if (!hWnd) return 1;

	if (!ParseAndFill(hWnd,lpszCmdLine))
		return 1;

    /* Enter main message loop */
    while (GetMessage (&msg, NULL, 0, 0))
		{
		if (!IsDialogMessage(hWnd,&msg))
			{
		   TranslateMessage (&msg);
		   DispatchMessage (&msg);
			}
	   }

	if (lpEditSubClassProc) FreeProcInstance(lpEditSubClassProc);
	if (lpDirsSubClassProc) FreeProcInstance(lpDirsSubClassProc);

    return 0;
}


LONG FAR PASCAL FrameWndProc ( hwnd, msg, wParam, lParam )
register HWND	 hwnd;
WORD		 msg;
register WORD	 wParam;
LONG		 lParam;
{
	switch(msg)
		{
		case WM_SIZE:
			LocateChildWindows(hwnd);
			break;

		case WM_DESTROY:
			if (fDirty)
				{
				CopyComments(hListBox,hEditBox);
				SaveFile(hwnd);
				}
			PostQuitMessage(0);
			break;

		case WM_SETFOCUS:
			SetFocus(hEditBox);
			break;


		case WM_INITMENU:
			if ((HMENU)wParam != GetMenu(hwnd)) break;
			EnableMenuItem((HMENU)wParam,
					WM_UNDO,
					(SendMessage(hEditBox,EM_CANUNDO,0,0L))
						? 	MF_ENABLED : MF_GRAYED);
			OpenClipboard(hwnd);
			EnableMenuItem((HMENU)wParam,
					WM_PASTE,
					(IsClipboardFormatAvailable(CF_TEXT))
						? 	MF_ENABLED : MF_GRAYED);
			CloseClipboard();
				{
				long sel = 
					(SendMessage(hEditBox,EM_GETSEL,0,0L));
				EnableMenuItem((HMENU)wParam,
					WM_CUT,
					HIWORD(sel) != LOWORD(sel) 
						? 	MF_ENABLED : MF_GRAYED);
				EnableMenuItem((HMENU)wParam,
					WM_COPY,
					HIWORD(sel) != LOWORD(sel) 
						? 	MF_ENABLED : MF_GRAYED);
				}
			break;

		case WM_COMMAND:
//			DD(hwnd,"got a message from a child %d %lx",wParam,lParam);
			switch (wParam)
				{
				case CM_FILE_QUIT:
					fDirty = FALSE;		// mark for abort and fall through
				case CM_FILE_EXIT:
					DestroyWindow(hwnd);
					break;
				case CDD_LISTBOX:
//					DD(hwnd,"list box message %lx",lParam);
					if (HIWORD(lParam) == LBN_SELCHANGE)
						CopyComments(hListBox,hEditBox);
					break;
				case CDD_EDIT:
						// if the comment changes, and the abort flag not set...
					if (HIWORD(lParam) == EN_CHANGE)
						fDirty = fLocalDirty = TRUE;
					break;
				case CDD_DIRS:
					DD(hwnd,"message from dir box %x %lx",wParam,lParam);
					switch(HIWORD(lParam))
						{
						case LBN_DBLCLK:
//						case LBN_SELCHANGE:
							NewDir(hwnd,(HWND) LOWORD(lParam));
							break;
						}
					break;
				case WM_CUT:
				case WM_COPY:
				case WM_PASTE:
				case WM_UNDO:
					SendMessage(hEditBox,wParam,wParam,lParam);
					break;
				case CM_FILE_ABOUT:
					{
					FARPROC lpProc;

					lpProc = MakeProcInstance( AboutBox, hInst );
					DialogBox(hInst,"WDN_ABOUT", hWnd, lpProc);
					FreeProcInstance(lpProc);
					}
					break;
				}
			break;
		default:
			return DefWindowProc(hwnd,msg,wParam,lParam);
			break;
		}
	return 0L;
}


int Init(void)
{
   WNDCLASS	wc;

  	/* Register the frame class */
   wc.style	     = NULL;
   wc.lpfnWndProc   = FrameWndProc;
   wc.cbClsExtra    = 0;
   wc.cbWndExtra    = DLGWINDOWEXTRA;
   wc.hInstance     = hInst;
   wc.hIcon	     = LoadIcon(hInst,MAKEINTRESOURCE(IDPREVIEW));
   wc.hCursor	     = LoadCursor(NULL,IDC_ARROW);
//   wc.hbrBackground = COLOR_APPWORKSPACE+1;
   wc.hbrBackground = COLOR_WINDOW+1;
   wc.lpszMenuName  = NULL;
   wc.lpszClassName = szFrame;

   if (!RegisterClass (&wc) )
	return FALSE;

}

/*SDOC*************************************************************

	Name: WakeUp

	Action: creates the main app, and the windows within it

	Returns: the handle to the main app window

*************************************************************EDOC*/
HWND WakeUp(HANDLE hInst, int nCmdShow)
{
	HMENU hMenu;
	HWND hWnd;
	HFONT hFont;
	TEXTMETRIC tm;
	HDC	hDC;
	HWND 	hDirs;

	DD(122,"just about to create 4 windows");
	DD(122,"premenu load");
	hMenu = LoadMenu(hInst,"WDN_MENU");
	DD(122,"menu loaded");

	hWnd = CreateDialog(hInst,"WDN",0,NULL);
	hListBox = GetDlgItem(hWnd,CDD_LISTBOX);
	hEditBox = GetDlgItem(hWnd,CDD_EDIT);
MessageBeep(5);
DD(hWnd,"did the CreateDialog() create");

	if (!hEditBox || !hListBox || !hWnd)
		return NULL;

	// get the dimensions of the two fonts
	// new version
	nCharWidth = LOWORD(GetDialogBaseUnits());
	nCharHeight = HIWORD(GetDialogBaseUnits());
	// old version
//	GetTextMetrics(hDC,&tm);
//	nCharWidth = tm.tmAveCharWidth;
//	nCharHeight = tm.tmHeight;
	hDC = GetDC(hWnd);
	hFont = GetStockObject(SYSTEM_FIXED_FONT);
	if (!hFont) hFont = GetStockObject(ANSI_FIXED_FONT);
DD(hWnd,"located the fixed font %x",hFont);
	SelectObject(hDC,hFont);
	GetTextMetrics(hDC, &tm);
	ReleaseDC(hWnd,hDC);
	nLBCharWidth = tm.tmAveCharWidth;
	nLBCharHeight = tm.tmHeight;
	nScrollWidth = GetSystemMetrics(SM_CXVSCROLL);

	SendMessage(hEditBox,EM_LIMITTEXT,LINE_LENGTH-POS_COMMENTS-2,0L);
	DD(hWnd,"edit window created %x",hEditBox);

	SendMessage(hListBox,WM_SETFONT,hFont,0L);
DD(hListBox,"listbox uses font %x instead of %x",(int)SendMessage(hListBox,WM_GETFONT,0,0L),hFont);
//MessageBox(hWnd,"test","test",MB_OK);

	LocateChildWindows(hWnd);

	lpEditProc = (FARPROC) GetWindowLong(hEditBox,GWL_WNDPROC);
	lpEditSubClassProc = MakeProcInstance((FARPROC)EditSubClassProc,hInst);
	SetWindowLong(hEditBox,GWL_WNDPROC,(LONG)lpEditSubClassProc);

	hDirs = GetDlgItem(hWnd,CDD_DIRS);
	lpDirsProc = (FARPROC) GetWindowLong(hDirs,GWL_WNDPROC);
	lpDirsSubClassProc = MakeProcInstance((FARPROC)DirsSubClassProc,hInst);
	SetWindowLong(hDirs,GWL_WNDPROC,(LONG)lpDirsSubClassProc);

	return hWnd;
}


/*SDOC*************************************************************

	Name: FillListBox

	Action: searches the current drive and fills the listbox with dir data

	Returns: the number of entries in the list box

*************************************************************EDOC*/
WORD FillListBox(HWND hListBox)
{
	int	cNumber = 0;
	struct 	find_t ff;
	int	hFile;

	SendMessage(hListBox,WM_SETREDRAW,0,0L);
	SendMessage(hListBox,LB_RESETCONTENT,0,0L);

	_makepath(szBuf,szDrive,szDir,"*",".*");

	if (!_dos_findfirst(szBuf,_A_NORMAL | _A_SUBDIR | _A_RDONLY | _A_ARCH,&ff))
		{
		do
			{
			char *ext;
			char name[13];
			strncpy(name,ff.name,13);
			if (name[0]=='.') continue;	// skip the dot directories
			if (ext=strchr(name,'.'))
				*(ext++) = '\0';
			else ext = "   ";
		 	wsprintf(szBuf2,"%-8.8s %-3.3s %8ld  %2d-%2.2d-%2.2d  %2d:%2.2d%c%c ",
					(LPSTR) name, (LPSTR) ext,
					ff.size,
					(ff.wr_date >> 5)&0xf, (ff.wr_date & 0x1f), 80 + (ff.wr_date >> 9),
					((ff.wr_time >>11)+11)%12+1 ,(ff.wr_time >>5) & 0x3f,(WORD)ff.wr_time > 0x6000 ? 'p' : 'a',
					'U');
			if (ff.attrib & _A_SUBDIR)
				memmove(szBuf2+POS_SIZE,"<DIR>    ",9);
			SendMessage(hListBox,LB_ADDSTRING,0,(DWORD) (LPSTR)szBuf2);
//DD(hListBox,t);
			}
		while (!_dos_findnext(&ff) && ++cNumber<500);

		}

	// now, try to open the notes file
	hFile = OpenFile(NULL,&ofs,OF_REOPEN | OF_READWRITE);
	if (hFile != -1)
		{
		int	iSearch = 0;
		int	iFound;
		char	szFile[POS_SIZE+1];
		
DD(123,"opened the file %s",ofs.szPathName);
		// read it in, a line at a time
		while(read(hFile,szBuf,LINE_LENGTH) > 0)
			{
//DD(hListBox,"just read in the line <%s>",szBuf);

			StripWhiteSpace(szBuf);
			strncpy(szFile,szBuf,POS_SIZE);
			szFile[POS_SIZE]='\0';
			iFound = (int)SendMessage(hListBox,LB_FINDSTRING,iSearch,(LONG)(LPSTR)szFile);

			if (iFound!=LB_ERR)
				{
				BOOL fChanged = FALSE;

					// suck the list box stuff into szBuf2
 				SendMessage(hListBox,LB_GETTEXT,iFound,(LONG)(LPSTR)szBuf2);
					// check for matching size and date
				if (!strncmp(szBuf+POS_SIZE,szBuf2+POS_SIZE,POS_COMMENTS-POS_SIZE-2))
					{
					szBuf2[POS_COMMENTS-2]=' ';
					fChanged = TRUE;
					}

					// if there's comments
				if (strlen(szBuf) > POS_COMMENTS)
					{
					strncpy(szBuf2+POS_COMMENTS,szBuf+POS_COMMENTS,LINE_LENGTH-POS_COMMENTS-2);
					fChanged = TRUE;
					}

					// put then new stuff back in the list box
				if (fChanged)
					{
					// NOTE the order: don't delete first; it screws up list boxes
					// especially if the last item is selected
					SendMessage(hListBox,LB_INSERTSTRING,iFound,(LONG)(LPSTR)szBuf2);
					SendMessage(hListBox,LB_DELETESTRING,iFound+1,0L);
//DD(hListBox,"insert %d comment <%s>",iFound,szBuf2);
					}
				iSearch=iFound;
				}
			}
		close(hFile);
		}
	SendMessage(hListBox,WM_SETREDRAW,1,0L);
	InvalidateRect(hListBox,NULL,TRUE);
DD(hListBox,"there are %d entries",SendMessage(hListBox,LB_GETCOUNT,0,0L));

	return cNumber;
}

/*SDOC*************************************************************

	Name: LocateChildWindows

	Action: resizes the listbox to match the window

	Returns: void

*************************************************************EDOC*/
void LocateChildWindows(HWND hWnd)
{
	RECT rClient;
	GetClientRect(hWnd,&rClient);
	MoveWindow(hListBox,
		nCharWidth,10*nCharHeight/2,
		min((LINE_LENGTH)*nLBCharWidth+nScrollWidth,
			(rClient.right-2*nCharWidth)),
		rClient.bottom-11*nCharHeight/2,
		TRUE);
}

/*SDOC*************************************************************

	Name: CommandLine

	Action: parse the given command line
		use OpenFile() to parse the command line and resolve the real path
		separate the path
			use the path to define the default notes name
		look at the file name; if it conforms, use it as the notes name
			if it doesn't conform, save it for the wakeup search
		form the full notes name and run OpenFile() to parse it

	Returns: TRUE if everything ok
		on the way, it sets
			szDrive		the displayed disk
			szDir			the displayed directory
			szFName		the notes file
			szExt			the notes file
			ofs			the notes file
			szNoteFile	the notes file (file+ext only)
			szFileName	the file to match

*************************************************************EDOC*/
BOOL	CommandLine(LPSTR lpCmdLine)
{
	char	szTemp[_MAX_PATH];
	char	*pWalk;

		// copy down the text from the far string
	if (lstrlen(lpCmdLine) > _MAX_PATH) return FALSE;
	lstrcpy(szTemp, lpCmdLine);
//DD(123,"got the command line <%s>",szTemp);

	strupr(szTemp);
	OpenFile(szTemp,&ofs,OF_PARSE);
	_splitpath(ofs.szPathName,szDrive,szDir,szFName,szExt);

		// create the default notes file name
	strcpy(szNoteFile,"DIRN----.DAT");
//DD(123,"made the plain note file name <%s>",szNoteFile);
//DD(123,"after the split, the ext is <%s>",szExt);
//DD(123,"after the split, the dir is <%s> at %x",szDir,szDir);

		// point to the last name in the path list
	strcpy(szTemp,szDir);			// use the scratch pad
	pWalk=strrchr(szTemp,'\\');	// strip the last slash
	if (pWalk)
		{
		*pWalk = '\0';					// walk back to the prev slash
		pWalk=strrchr(szTemp,'\\');
		}
	if (!pWalk) pWalk=szDir;
	if (*(++pWalk))
		{szNoteFile[5]=*pWalk;
		if (pWalk[1])
			{szNoteFile[6]=pWalk[1];
			if (pWalk[2]) szNoteFile[7]=pWalk[2];
			}
		}
DD(123,"overwrote the note file name <%s>",szNoteFile);

		// is it not conforming file name?? if so, save it
		// 	for a file match and overwrite it with the default name
	if (strncmp(szFName,"DIRN-",5) || (strcmp(szExt,".DAT") && strcmp(szExt,".WDN")))
		{
		wsprintf(szFileName,"%-8.8s %-3.3s",(LPSTR)szFName,(LPSTR)szExt+1);
DD(123,"saved the search file <%s>",szFileName);
		strncpy(szFName,szNoteFile,8);
		szFName[8]='\0';
		strcpy(szExt,szNoteFile+8);
		}
	else
		szFileName[0]='\0';	// clear the match file

		// now reform the full notes name
	_makepath(szTemp,szDrive,szDir,szFName,szExt);
DD(123,"just made the full notes name %s",szTemp);
		// and parse it for the open
	OpenFile(szTemp,&ofs,OF_PARSE);

	return TRUE;
}



/*SDOC*************************************************************

	Name: SaveFile

	Action: read the list box and spit the stuff out to file

	Returns: TRUE if everything ok

*************************************************************EDOC*/
BOOL SaveFile(HWND hWnd)
{
	int	hFile;
	int	i,n;

//	MessageBox(hWnd,"saving","saving",MB_OK);

	hFile = OpenFile(NULL, &ofs, OF_REOPEN | OF_WRITE);
	if (hFile==-1)
		hFile = OpenFile(NULL, &ofs, OF_REOPEN | OF_CREATE | OF_WRITE);

	if (hFile==-1)
		{
		wsprintf(szBuf,"error: could not create the file %s",(LPSTR)ofs.szPathName);
		MessageBox(hWnd,szBuf,APP_NAME,MB_OK);
		}
	else
		{
		SendMessage(hListBox,WM_SETREDRAW,0,0L);
		n = (int) SendMessage(hListBox,LB_GETCOUNT,0,0L);
		for (i=0; i<n; i++)
			{
			int len;
			if (SendMessage(hListBox,LB_GETTEXTLEN,i,0L) > LINE_LENGTH)
				{
				MessageBox(hWnd,"line too long; skipping",APP_NAME,MB_OK);
				continue;
				}
			SendMessage(hListBox,LB_GETTEXT,i,(LONG)(LPSTR)szBuf);
			StripWhiteSpace(szBuf);
			len = strlen(szBuf);
			if (len==0) // MessageBox(hWnd,"error","error",MB_OK);
				continue;
			while (len < LINE_LENGTH-2) szBuf[len++]=' ';
			szBuf[len++]='\r';
			szBuf[len]='\n';
			write(hFile,szBuf,LINE_LENGTH);
//DD(hListBox,">%s",szBuf);
			}
DD(hListBox,"done the write");
		close(hFile);
		SendMessage(hListBox,WM_SETREDRAW,1,0L);
		return TRUE;
		}
	return FALSE;
}


/*SDOC*************************************************************

	Name: CopyComments

	Action: moves any comments from the edit box, stores it in the list
			box
		reads the comments from the current selection into the
			edit box
		the flush flag is used when we're changing the list box

	Returns: void

*************************************************************EDOC*/
void CopyComments(HWND hListBox, HWND hEditBox)
{
	int 	iNewSel;
	static iOldSel=-1;
	int	fDirtyTemp;

	iNewSel = (int) SendMessage(hListBox,LB_GETCURSEL,0,0L);
		 
	if (fLocalDirty)
		{
		SendMessage(hListBox,WM_SETREDRAW,		0,0L);
		SendMessage(hListBox,LB_GETTEXT,			iOldSel,(LONG)(LPSTR)szBuf);
		SendMessage(hEditBox,WM_GETTEXT,			LINE_LENGTH-POS_COMMENTS,
															(LONG)(LPSTR)szBuf+POS_COMMENTS);
DD(hEditBox,"sucked out the edit box <%s>",szBuf+POS_COMMENTS);
		SendMessage(hListBox,LB_INSERTSTRING,	iOldSel,(LONG)(LPSTR)szBuf);
		SendMessage(hListBox,WM_SETREDRAW,		1,0L);
		SendMessage(hListBox,LB_DELETESTRING,	iOldSel+1,(LONG)(LPSTR)szBuf);
		}

	SendMessage(hListBox,LB_GETTEXT,			max(iNewSel,0), (LONG)(LPSTR)szBuf);
	StripWhiteSpace(szBuf);
		// since setting the text will set the fDirty, push & pop it here
	fDirtyTemp = fDirty;
	SetWindowText(hEditBox,szBuf+POS_COMMENTS);
	fDirty = fDirtyTemp;
	SendMessage(hListBox,LB_SETCURSEL,		iNewSel,0L);
	iOldSel = iNewSel;
	fLocalDirty = FALSE;
}


/*SDOC*************************************************************

	Name: StripWhiteSpace

	Action: removes trailing white space and CR/LF

	Returns: the pointer to the string

*************************************************************EDOC*/
char *StripWhiteSpace(char *str)
{
	char *p = str+strlen(str);
	p--;
	while (p>=str && isspace(*p)) *(p--)='\0';
	return str;
}

/*SDOC*************************************************************

	Name: NewDir

	Action: use the contents of the combo box to search to a new dir

	Returns: 

*************************************************************EDOC*/
void NewDir(HWND hWnd,HWND hDirs)
{
	BOOL fDisk;
	char	szTemp[_MAX_FNAME+_MAX_EXT];

	if (fDirty)
		{
		CopyComments(hListBox,hEditBox);
		SaveFile(hWnd);
		}
	fDirty = fLocalDirty = FALSE;

	fDisk = DlgDirSelect(hWnd,szTemp,CDD_DIRS);
DD(hWnd,"DlgDir returned <%s> %d",szTemp,fDisk);
	if (szTemp[1]==':')
		{
		strcpy(szDrive,szTemp);
		_getdcwd(toupper(szTemp[0])-'A'+1,szDir,_MAX_DIR);
		strcpy(szDir,szDir+2);	//RISKY!!
DD(hWnd,"using the drive %s path %s",szDrive,szDir);
		}
	else
		strcat(szDir,szTemp);
	_makepath(szBuf,szDrive,szDir,"*",".*");

	ParseAndFill(hWnd, szBuf);

}
/*SDOC*************************************************************

	Name: ParseAndFill

	Action: reads a command line,
		determines the notes file name,
		fills the list box,
		changes the window title bar,
		fills the combo box,
		and searches for the first file that matches the command line

	Returns: TRUE if everything went ok

*************************************************************EDOC*/
BOOL ParseAndFill(HWND hWnd, LPSTR lpCmdLine)
{

MessageBeep(5);
		// parse the command line, find the notes file and match file
	if (!CommandLine(lpCmdLine)) return FALSE;
MessageBeep(5);

		// fill the list with real files, merge with old comments
	FillListBox(hListBox);
MessageBeep(5);

		// search for the match file
	SearchForGivenFile(hListBox);

		// fill the edit box with comments on this file
	CopyComments(hListBox,hEditBox);

		// prep the combo box
	_makepath(szBuf,szDrive,szDir,"*",".*");
DD(hWnd,"just made the new search dir for combo box");
DD(hWnd,"      <%s>",szBuf);
	DlgDirList(hWnd,szBuf,CDD_DIRS,CDD_PATH,0xC010);
	SetFocus(hEditBox);

		// set the caption line
	strcpy(szBuf,APP_NAME);
	strcat(szBuf,": ");
	strcat(szBuf,ofs.szPathName);
	SetWindowText(hWnd,szBuf);

	return TRUE;
}

/*SDOC*************************************************************

	Name: SearchForGivenFile

	Action: uses the global szFileName to search the list box
		if it is found, the selection is set

	Returns: index of the file in the listbox

*************************************************************EDOC*/
int	SearchForGivenFile(HWND hLB)
{
	int i=-1;

	if (*szFileName)
		i = (int) SendMessage(hLB,LB_SELECTSTRING,-1,(LONG)(LPSTR)szFileName);
DD(hLB,"search against <%s> returned %d",szFileName,i);
	return i;
}

/*SDOC*************************************************************

	Name: AboutBox

	Action: just displays the about box

	Returns: void

*************************************************************EDOC*/
BOOL FAR PASCAL AboutBox(HWND hDlg, WORD message, WORD wParam, LONG lParam)
{
	lParam;
	switch (message)
		{
		case WM_COMMAND:
			if (wParam==IDOK)
				EndDialog(hDlg,TRUE);
			break;
		case WM_INITDIALOG:
			break;
		default:
			return FALSE;
		}
	return TRUE;
}


/*SDOC*************************************************************

	Name: EditSubClassProc

	Action: traps any vertical key messages for the edit box, and
		directs them to the list box
		up, down, page up, page down, Ctrl PgUp and Ctrl PgDn

	Returns: the window proc

*************************************************************EDOC*/
LONG FAR PASCAL EditSubClassProc(HWND hEdit, WORD message, WORD wParam, LONG lParam)
{
	if (message==WM_KEYDOWN || message==WM_KEYUP)
		{
		switch (wParam)
			{
			case VK_UP:
			case VK_DOWN:
			case VK_PRIOR:
			case VK_NEXT:
				return SendMessage(hListBox,message,wParam,lParam);
			}
		}
 	return CallWindowProc(lpEditProc,hEdit,message,wParam,lParam);
}


/*SDOC*************************************************************

	Name: DirsSubClassProc

	Action: traps the enter key, and simulate a 
		double click back to the parent

	Returns: the window proc

*************************************************************EDOC*/
LONG FAR PASCAL DirsSubClassProc(HWND hDirs, WORD message, WORD wParam, LONG lParam)
{
DD(hDirs,"dirs box got message %x wParam %x, %lx",message,wParam,lParam);
	switch (message)
		{
		case WM_KEYDOWN:
			switch (wParam)
				{
				case VK_SPACE:
				case VK_RETURN:
					PostMessage(GetParent(hDirs),
							WM_COMMAND,
							CDD_DIRS,
							MAKELONG(hDirs,LBN_DBLCLK));
				}
			break;
		case WM_GETDLGCODE:
			return (LONG) (DLGC_WANTCHARS |
					CallWindowProc(lpDirsProc,hDirs,message,wParam,lParam));
		}
 	return CallWindowProc(lpDirsProc,hDirs,message,wParam,lParam);
}
