Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

1288 lines
39 KiB

/*
* Notepad application
*
* Copyright (C) 1984-2000 Microsoft Corporation
*
* NPInit - One time init for notepad.
*/
#include "precomp.h"
TCHAR chPageText[2][PT_LEN]; /* Strings to hold PageSetup items. */
TCHAR chPageTextTemp[2][PT_LEN];
TCHAR szPrinterName[256]; /* String to hold printername for PrintTo verb */
static UINT cpDefault;
static INT fSaveWindowPositions=0; /* true if we are to save window position */
static INT g_WPtop,g_WPleft,g_WPDX,g_WPDY; /* initial window positions */
/* routines to handle saving and restoring information in the registry.
*
* SaveGlobals - saves interesting globals to the registry
*
* GetGlobals - gets interesting globals from the registry
*
* Interesting Globals:
*
* FontStruct information include calculated pointsize
* Codepage
*
* If we want to save PageSetup info, save the margins in some
* units (cm for example) and convert on input and output.
*/
/* name of section to save into -- never internationalize */
#define OURKEYNAME TEXT("Software\\Microsoft\\Notepad")
// RegWriteInt - write an integer to the registry
VOID RegWriteInt( HKEY hKey, PTCHAR pszKey, INT iValue )
{
RegSetValueEx( hKey, pszKey, 0, REG_DWORD, (BYTE*)&iValue, sizeof(INT) );
}
// RegWriteString - write a string to the registry
VOID RegWriteString( HKEY hKey, PTCHAR pszKey, PTCHAR pszValue )
{
INT len; // length of string with null in bytes
len= (lstrlen( pszValue )+1) * sizeof(TCHAR);
RegSetValueEx( hKey, pszKey, 0, REG_SZ, (BYTE*)pszValue, len );
}
// RegGetInt - Get integer from registry
DWORD RegGetInt( HKEY hKey, PTCHAR pszKey, DWORD dwDefault )
{
DWORD dwResult= !ERROR_SUCCESS;
LONG lStatus= ERROR_SUCCESS;
DWORD dwSize= sizeof(DWORD);
DWORD dwType= 0;
if( hKey )
{
lStatus= RegQueryValueEx( hKey,
pszKey,
NULL,
&dwType,
(BYTE*) &dwResult,
&dwSize );
}
if( lStatus != ERROR_SUCCESS || dwType != REG_DWORD )
{
dwResult= dwDefault;
}
return( dwResult );
}
// RegGetString - get string from registry
VOID RegGetString( HKEY hKey, PTCHAR pszKey, PTCHAR pszDefault, PTCHAR pszResult, INT iCharLen )
{
LONG lStatus= !ERROR_SUCCESS;
DWORD dwSize; // size of buffer
DWORD dwType= REG_NONE;
dwSize= iCharLen * sizeof(TCHAR);
if( hKey )
{
lStatus= RegQueryValueEx( hKey,
pszKey,
NULL,
&dwType,
(BYTE*) pszResult,
&dwSize );
}
if( lStatus != ERROR_SUCCESS || dwType != REG_SZ )
{
CopyMemory( pszResult, pszDefault, iCharLen*sizeof(TCHAR) );
}
}
// lfHeight is calculated using PointSize
// lfWidth set by font mapper
VOID SaveGlobals(VOID)
{
HKEY hKey; // key to our registry root
LONG lStatus; // status from RegCreateKey
WINDOWPLACEMENT wp;
lStatus= RegCreateKey( HKEY_CURRENT_USER, OURKEYNAME, &hKey );
if( lStatus != ERROR_SUCCESS )
{
return; // just return quietly
}
RegWriteInt( hKey, TEXT("lfEscapement"), FontStruct.lfEscapement);
RegWriteInt( hKey, TEXT("lfOrientation"), FontStruct.lfOrientation);
RegWriteInt( hKey, TEXT("lfWeight"), FontStruct.lfWeight);
RegWriteInt( hKey, TEXT("lfItalic"), FontStruct.lfItalic);
RegWriteInt( hKey, TEXT("lfUnderline"), FontStruct.lfUnderline);
RegWriteInt( hKey, TEXT("lfStrikeOut"), FontStruct.lfStrikeOut);
RegWriteInt( hKey, TEXT("lfCharSet"), FontStruct.lfCharSet);
RegWriteInt( hKey, TEXT("lfOutPrecision"), FontStruct.lfOutPrecision);
RegWriteInt( hKey, TEXT("lfClipPrecision"), FontStruct.lfClipPrecision);
RegWriteInt( hKey, TEXT("lfQuality"), FontStruct.lfQuality);
RegWriteInt( hKey, TEXT("lfPitchAndFamily"), FontStruct.lfPitchAndFamily);
RegWriteInt( hKey, TEXT("iPointSize"), iPointSize);
RegWriteInt( hKey, TEXT("fWrap"), fWrap);
RegWriteInt( hKey, TEXT("StatusBar"), fStatus);
RegWriteInt( hKey, TEXT("fSaveWindowPositions"),fSaveWindowPositions );
RegWriteString( hKey, TEXT("lfFaceName"), FontStruct.lfFaceName);
RegWriteString( hKey, TEXT("szHeader"), chPageText[HEADER] );
RegWriteString( hKey, TEXT("szTrailer"), chPageText[FOOTER] );
RegWriteInt( hKey, TEXT("iMarginTop"), g_PageSetupDlg.rtMargin.top );
RegWriteInt( hKey, TEXT("iMarginBottom"), g_PageSetupDlg.rtMargin.bottom );
RegWriteInt( hKey, TEXT("iMarginLeft"), g_PageSetupDlg.rtMargin.left );
RegWriteInt( hKey, TEXT("iMarginRight"), g_PageSetupDlg.rtMargin.right );
wp.length= sizeof(wp);
if( GetWindowPlacement( hwndNP, &wp ) )
{
RegWriteInt( hKey, TEXT("iWindowPosX"), wp.rcNormalPosition.left);
RegWriteInt( hKey, TEXT("iWindowPosY"), wp.rcNormalPosition.top);
RegWriteInt( hKey, TEXT("iWindowPosDX"), wp.rcNormalPosition.right - wp.rcNormalPosition.left);
RegWriteInt( hKey, TEXT("iWindowPosDY"), wp.rcNormalPosition.bottom - wp.rcNormalPosition.top);
}
RegCloseKey( hKey );
}
// GetGlobals
//
// Pick up font information etc that may be saved in the registry.
//
// We are called pretty early in setup and don't have things like hwndNP valid yet.
//
VOID GetGlobals( VOID )
{
LOGFONT lfDef; // default logical font
HFONT hFixedFont; // standard font to use
LONG lStatus; // status from RegCreateKey
HKEY hKey; // key into registry
//
// quickly get a reasonable set of default parameters
// for the default font if we need it.
//
hFixedFont= GetStockObject( SYSTEM_FIXED_FONT );
if ( hFixedFont )
{
GetObject( hFixedFont, sizeof(LOGFONT), &lfDef );
}
else
{
ZeroMemory( &lfDef, sizeof(lfDef) );
}
lStatus= RegCreateKey( HKEY_CURRENT_USER, OURKEYNAME, &hKey );
if( lStatus != ERROR_SUCCESS )
{
hKey= NULL; // later calls to RegGet... will return defaults
}
FontStruct.lfWidth= 0;
FontStruct.lfEscapement= (LONG)RegGetInt( hKey, TEXT("lfEscapement"), lfDef.lfEscapement);
FontStruct.lfOrientation= (LONG)RegGetInt( hKey, TEXT("lfOrientation"), lfDef.lfOrientation);
FontStruct.lfWeight= (LONG)RegGetInt( hKey, TEXT("lfWeight"), lfDef.lfWeight);
FontStruct.lfItalic= (BYTE)RegGetInt( hKey, TEXT("lfItalic"), lfDef.lfItalic);
FontStruct.lfUnderline= (BYTE)RegGetInt( hKey, TEXT("lfUnderline"), lfDef.lfUnderline);
FontStruct.lfStrikeOut= (BYTE)RegGetInt( hKey, TEXT("lfStrikeOut"), lfDef.lfStrikeOut);
//
// We have to preserve lfCharSet because some fonts (symbol, marlett) don't handle
// 0 (ANSI_CHARSET) or 1 (DEFAULT_CHARSET), and the font mapper will map to a
// different facename. Later we will see if the CreateFont has the same FaceName
// and get a more appropriate lfCharSet if need be.
//
FontStruct.lfCharSet= (BYTE)RegGetInt( hKey, TEXT("lfCharSet"), lfDef.lfCharSet);
FontStruct.lfOutPrecision= (BYTE)RegGetInt( hKey, TEXT("lfOutPrecision"), lfDef.lfOutPrecision);
FontStruct.lfClipPrecision= (BYTE)RegGetInt( hKey, TEXT("lfClipPrecision"), lfDef.lfClipPrecision);
FontStruct.lfQuality= (BYTE)RegGetInt( hKey, TEXT("lfQuality"), lfDef.lfQuality);
FontStruct.lfPitchAndFamily= (BYTE)RegGetInt( hKey, TEXT("lfPitchAndFamily"), lfDef.lfPitchAndFamily);
//
// If there is no FaceName in the registry, use the default "Lucida Console"
// This will show off most of the glyphs except in the FE locales.
// For FE, we can't font link fonts with the glyphs because they would have to have
// the exact width as lucida console, or the console/csrss will AV (July 9, 1999)
//
RegGetString( hKey, TEXT("lfFaceName"), TEXT("Lucida Console"), FontStruct.lfFaceName, LF_FACESIZE);
iPointSize= RegGetInt( hKey, TEXT("iPointSize"), 100);
fWrap= RegGetInt( hKey, TEXT("fWrap"), 0);
fStatus= RegGetInt( hKey, TEXT("StatusBar"), 0);
fSaveWindowPositions= RegGetInt( hKey, TEXT("fSaveWindowPositions"), 0 );
// if page settings not in registry, we will use defaults
RegGetString( hKey, TEXT("szHeader"), chPageText[HEADER], chPageText[HEADER], PT_LEN );
RegGetString( hKey, TEXT("szTrailer"), chPageText[FOOTER], chPageText[FOOTER], PT_LEN );
g_PageSetupDlg.rtMargin.top= (LONG)RegGetInt( hKey, TEXT("iMarginTop"), g_PageSetupDlg.rtMargin.top );
g_PageSetupDlg.rtMargin.bottom= (LONG)RegGetInt( hKey, TEXT("iMarginBottom"), g_PageSetupDlg.rtMargin.bottom );
g_PageSetupDlg.rtMargin.left= (LONG)RegGetInt( hKey, TEXT("iMarginLeft"), g_PageSetupDlg.rtMargin.left );
g_PageSetupDlg.rtMargin.right= (LONG)RegGetInt( hKey, TEXT("iMarginRight"), g_PageSetupDlg.rtMargin.right );
// if window positions in registry use them, otherwise us defaults
g_WPtop= (INT) RegGetInt( hKey, TEXT("iWindowPosY"), (DWORD) CW_USEDEFAULT );
g_WPleft= (INT) RegGetInt( hKey, TEXT("iWindowPosX"), (DWORD) CW_USEDEFAULT );
g_WPDX= (INT) RegGetInt( hKey, TEXT("iWindowPosDX"), (DWORD) CW_USEDEFAULT );
g_WPDY= (INT) RegGetInt( hKey, TEXT("iWindowPosDY"), (DWORD) CW_USEDEFAULT );
if( hKey )
{
RegCloseKey( hKey );
}
}
void GetLocaleCodepages(LCID lcid, UINT* pcpANSI, UINT* pcpOEM)
{
// FEATURE: don't check returns? Not likely; fix later
GetLocaleInfoW(lcid,
LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER,
(LPTSTR) pcpANSI,
sizeof(*pcpANSI));
GetLocaleInfoW(lcid,
LOCALE_IDEFAULTCODEPAGE | LOCALE_RETURN_NUMBER,
(LPTSTR) pcpOEM,
sizeof(*pcpOEM));
// LOCALE_IDEFAULTMACCODEPAGE ?
// LOCALE_IDEFAULTEBCDICCODEPAGE ?
}
void GetKeyboardCodepages(LANGID langid)
{
GetLocaleCodepages(langid, &g_cpKeyboardANSI, &g_cpKeyboardOEM);
}
void GetSystemCodepages(void)
{
g_cpANSI = GetACP();
g_cpOEM = GetOEMCP();
}
void GetUserLocaleCodepages(void)
{
GetLocaleCodepages(GetUserDefaultUILanguage(), &g_cpUserLocaleANSI, &g_cpUserLocaleOEM);
GetLocaleCodepages(GetUserDefaultLCID(), &g_cpUserLocaleANSI, &g_cpUserLocaleOEM);
}
/*
* lstrncmpi( str1, str2, len )
* compares two strings, str1 and str2, up
* to length 'len' ignoring case. If they
* are equal, we will return 0. Otherwise not 0.
*/
static
INT lstrncmpi( PTCHAR sz1, PTCHAR sz2 )
{
TCHAR ch1, ch2;
while( *sz1 )
{
ch1= (TCHAR) (INT_PTR) CharUpper( (LPTSTR) (INT_PTR) *sz1++ );
ch2= (TCHAR) (INT_PTR) CharUpper( (LPTSTR) (INT_PTR) *sz2++ );
if( ch1 != ch2 )
return 1;
}
return 0; // they are equal
}
static int NPRegister (HANDLE hInstance);
/* GetFileName
*
* Parse off filename from command line and put
* into lpFileName
*/
LPTSTR GetFileName( LPTSTR lpFileName, LPTSTR lpCmdLine )
{
LPTSTR lpTemp = lpFileName;
HANDLE hFindFile;
WIN32_FIND_DATA info;
/*
** Allow for filenames surrounded by double and single quotes
** like in longfilenames.
*/
if( *lpCmdLine == TEXT('\"') || *lpCmdLine == TEXT('\'') )
{
TCHAR chMatch = *lpCmdLine;
DWORD dwSize=0;
// Copy over filename
while( *(++lpCmdLine) && (*lpCmdLine != chMatch) && (dwSize<MAX_PATH) )
{
*lpTemp++ = *lpCmdLine;
dwSize++;
}
// NULL terminate the filename (no embedded quotes allowed in filenames)
*lpTemp = TEXT('\0');
}
else
{
lstrcpyn(lpFileName, lpCmdLine,MAX_PATH);
}
/*
** Check to see if the unaltered filename exists. If it does then don't
** append a default extension.
*/
hFindFile= FindFirstFile( lpFileName, &info );
if( hFindFile != INVALID_HANDLE_VALUE )
{
FindClose( hFindFile );
}
else
{
/*
** Add default extension and try again
*/
AddExt( lpFileName );
hFindFile= FindFirstFile( lpFileName, &info );
if( hFindFile != INVALID_HANDLE_VALUE )
{
FindClose( hFindFile );
}
}
// return the pointer to the end of the filename.
return lpCmdLine;
}
/* SizeStrings - Get the total size of the resource strings */
/* returns size in 'chars' or zero if failure */
/* we do this in case the international people really change */
/* the size of resources. */
/* Read all the strings into a buffer to size them. Since we */
/* don't know the maximum size of string resource, we may have */
/* to change the size of the read buffer. This is done with */
/* a simple doubling algorithm. */
INT SizeStrings(HANDLE hInstance)
{
INT iElementSize=350; // current max size of string
INT total; // total size of resources
PTCHAR Buf; // buffer to try putting resources into
INT ids; // identifier number for resource
INT len; // length of one resource
while( TRUE ) // keep looping til all strings can be read
{
Buf= LocalAlloc( LPTR, ByteCountOf(iElementSize) );
if( !Buf )
{
return 0; // failure
}
for( ids=0, total=0; rgsz[ids] != NULL; ids++ )
{
len= LoadString( hInstance, (UINT) (UINT_PTR) (*rgsz[ids]), Buf, iElementSize );
if( len >= iElementSize-1 )
{
#if DBG
ODS(TEXT("notepad: resource string too long!\n"));
#endif
break;
}
total += len+1; // account for null terminator
}
LocalFree( Buf );
if( rgsz[ids] == NULL ) break;
iElementSize= iElementSize*2;
}
return( total );
}
/* InitStrings - Get all text strings from resource file */
BOOL InitStrings (HANDLE hInstance)
{
TCHAR* pch;
INT cchRemaining;
INT ids, cch;
// allocate memory and lock it down forever. we have pointers into it.
// the localrealloc() function will not work well for freeing
// unused memory because it may (and did) move memory.
cchRemaining= SizeStrings( hInstance );
if( !cchRemaining )
return( FALSE ); // fail because we are out of memory
pch= LocalAlloc( LPTR, ByteCountOf(cchRemaining) );
if( !pch )
return( FALSE );
cchRemaining= (INT)LocalSize( pch ) / sizeof(TCHAR);
if( cchRemaining == 0 ) // can't alloc memory - failure
return( FALSE );
for( ids = 0; rgsz[ids] != NULL; ids++ )
{
cch= 1 + LoadString( hInstance, (UINT) (UINT_PTR) (*rgsz[ids]), pch, cchRemaining );
*rgsz[ids]= pch;
pch += cch;
if( cch > cchRemaining ) // should never happen
{
MessageBox( NULL, TEXT("Out of RC string space!!"),
TEXT("DEV Error!"), MB_OK);
return( FALSE );
}
cchRemaining -= cch;
}
/* Get header and footer strings */
lstrcpyn( chPageText[HEADER], szHeader, PT_LEN );
lstrcpyn( chPageText[FOOTER], szFooter, PT_LEN );
chMerge= *szMerge;
return (TRUE);
}
/*
* SkipBlanks( pszText )
* skips blanks or tabs to either next character or EOL
* returns pointer to same.
*/
PTCHAR SkipBlanks( PTCHAR pszText )
{
while( *pszText == TEXT(' ') || *pszText == TEXT('\t') )
pszText++;
return pszText;
}
// if /.SETUP option exists in the command line process it.
BOOL ProcessSetupOption (LPTSTR lpszCmdLine)
{
INT iSta= 0;
/* Search for /.SETUP in the command line */
if( !lstrncmpi( TEXT("/.SETUP"), lpszCmdLine ) )
{
fRunBySetup = TRUE;
/* Save system menu handle for INITMENUPOPUP message */
hSysMenuSetup =GetSystemMenu(hwndNP, FALSE);
/* Allow exit on ^C, ^D and ^Z */
/* Note that LoadAccelerators must be called before */
/* TranslateAccelerator is called, true here */
hAccel = LoadAccelerators(hInstanceNP, TEXT("SlipUpAcc"));
lpszCmdLine += 7;
}
else
return FALSE;
/* Don't offer a minimize button */
SetWindowLong( hwndNP, GWL_STYLE,
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU |
WS_THICKFRAME | WS_MAXIMIZEBOX |
WS_VSCROLL | WS_HSCROLL);
/* skip blanks again to get to filename */
lpszCmdLine= SkipBlanks( lpszCmdLine );
if (*lpszCmdLine)
{
TCHAR szFile[MAX_PATH];
/* Get the filename. */
GetFileName(szFile, lpszCmdLine);
fp= CreateFile( szFile, // filename
GENERIC_READ, // access mode
FILE_SHARE_READ|FILE_SHARE_WRITE, // share mode
NULL, // security descriptor
OPEN_EXISTING, // how to create
FILE_ATTRIBUTE_NORMAL, //file attributes
NULL); // hnd of file attrs
if( fp == INVALID_HANDLE_VALUE )
{
DWORD dwErr;
// Check GetLastError to see why we failed
dwErr = GetLastError ();
switch (dwErr)
{
case ERROR_ACCESS_DENIED:
iSta= AlertBox( hwndNP, szNN, szACCESSDENY, szFile,
MB_APPLMODAL | MB_OKCANCEL | MB_ICONWARNING);
break;
case ERROR_FILE_NOT_FOUND:
iSta= AlertBox(hwndNP, szNN, szFNF, szFile,
MB_APPLMODAL | MB_YESNOCANCEL | MB_ICONWARNING);
if( iSta == IDYES )
{
fp= CreateFile( szFile, // filename
GENERIC_READ|GENERIC_WRITE, // access
FILE_SHARE_READ|FILE_SHARE_WRITE, // share
NULL, // security descrp
OPEN_ALWAYS, // how to create
FILE_ATTRIBUTE_NORMAL, // file attributes
NULL); // hnd of file attrs
}
break;
case ERROR_INVALID_NAME:
iSta= AlertBox( hwndNP, szNN, szNVF, szFile,
MB_APPLMODAL | MB_OKCANCEL | MB_ICONWARNING);
break;
default:
iSta= AlertBox(hwndNP, szNN, szDiskError, szFile,
MB_APPLMODAL | MB_OKCANCEL | MB_ICONWARNING);
break;
}
}
if (fp == INVALID_HANDLE_VALUE)
return (FALSE);
LoadFile(szFile, FALSE); // load setup file
}
if( iSta == IDCANCEL )
return( IDCANCEL );
else
return( IDYES );
}
/*
* ProcessShellOptions(lpszCmdLine)
*
* If the command line has any options specified by the shell
* process them.
* Currently /P <filename> - prints the given file
* /PT "filename" "printer name" "Driver dll" "port"
*/
BOOL ProcessShellOptions (LPTSTR lpszCmdLine, int cmdShow)
{
BOOL bDefPrinter = TRUE;
LPTSTR lpszAfterFileName;
INT i = 0;
TCHAR szFile[MAX_PATH];
// Is it PrintTo ?
if( lstrncmpi( TEXT("/PT"), lpszCmdLine ) == 0)
{
lpszCmdLine= SkipBlanks( lpszCmdLine+3 );
bDefPrinter = FALSE;
}
// Or is it Print ?
else if ( lstrncmpi( TEXT("/P"), lpszCmdLine ) == 0)
{
lpszCmdLine= SkipBlanks( lpszCmdLine+2 );
}
else
return FALSE;
if (!*lpszCmdLine)
return FALSE;
/* Added as per Bug #10923 declaring that the window should show up
* and then the printing should begin. 29 July 1991 Clark Cyr
*/
ShowWindow(hwndNP, cmdShow);
/* Get the filename; have the pointer to the end of the filename */
lpszAfterFileName = GetFileName(szFile, lpszCmdLine) + 1;
if (!bDefPrinter)
{
/* extract the printer name from the command line. */
if (!*lpszAfterFileName)
return FALSE;
lpszAfterFileName = SkipBlanks( lpszAfterFileName );
/* (since we are passing multiple arguments here, the filename, */
/* the printername have to be in quotes. */
if( *lpszAfterFileName != TEXT('\"') )
return FALSE;
// Copy over printername
while( *(++lpszAfterFileName) && *lpszAfterFileName != TEXT('\"') )
{
szPrinterName[i++] = *lpszAfterFileName;
}
// NULL terminate the printername (no embedded quotes allowed in printernames)
szPrinterName[i] = TEXT('\0');
}
fp= CreateFile( szFile, // filename
GENERIC_READ, // access mode
FILE_SHARE_READ|FILE_SHARE_WRITE, // share mode
NULL, // security descriptor
OPEN_EXISTING, // how to create
FILE_ATTRIBUTE_NORMAL, // file attributes
NULL); // hnd of file attrs to copy
if( fp == INVALID_HANDLE_VALUE )
{
TCHAR* pszMsg;
// select reasonable error message based on GetLastError
switch( GetLastError() )
{
case ERROR_ACCESS_DENIED:
case ERROR_NETWORK_ACCESS_DENIED:
pszMsg= szACCESSDENY;
break;
case ERROR_FILE_NOT_FOUND:
pszMsg= szFNF;
break;
case ERROR_INVALID_NAME:
pszMsg= szNVF;
break;
default:
pszMsg= szDiskError;
break;
}
AlertBox(hwndNP, szNN, pszMsg, szFile,
MB_APPLMODAL | MB_OK | MB_ICONWARNING);
return (TRUE);
}
// Load the file into the edit control
LoadFile(szFile, g_fSelectEncoding); // get print file
// Print the file
if (bDefPrinter)
{
PrintIt( DoNotUseDialog );
}
else
{
PrintIt( NoDialogNonDefault );
}
return (TRUE);
}
/* CreateFilter
*
* Creates filters for GetOpenFileName.
*
*/
VOID CreateFilter(BOOL fOpen, PTCHAR szFilterSpec)
{
PTCHAR pszFilterSpec;
/* construct default filter string in the required format for
* the new FileOpen and FileSaveAs dialogs
* if you add to this, make sure CCHFILTERMAX is large enough.
*/
pszFilterSpec = szFilterSpec;
// .txt first for compatibility
lstrcpy(pszFilterSpec, szTextFiles);
pszFilterSpec += lstrlen(pszFilterSpec) + 1;
lstrcpy(pszFilterSpec, TEXT("*.txt"));
pszFilterSpec += lstrlen(pszFilterSpec) + 1;
lstrcpy(pszFilterSpec, szHtmlFiles);
pszFilterSpec += lstrlen(pszFilterSpec) + 1;
lstrcpy(pszFilterSpec, TEXT("*.htm;*.html"));
pszFilterSpec += lstrlen(pszFilterSpec) + 1;
lstrcpy(pszFilterSpec, szXmlFiles);
pszFilterSpec += lstrlen(pszFilterSpec) + 1;
lstrcpy(pszFilterSpec, TEXT("*.xml"));
pszFilterSpec += lstrlen(pszFilterSpec) + 1;
if (fOpen)
{
lstrcpy(pszFilterSpec, szEncodedText);
pszFilterSpec += lstrlen(pszFilterSpec) + 1;
lstrcpy(pszFilterSpec, TEXT("*.txt"));
pszFilterSpec += lstrlen(pszFilterSpec) + 1;
}
// and last, all files
lstrcpy(pszFilterSpec, szAllFiles);
pszFilterSpec += lstrlen(pszFilterSpec) + 1;
lstrcpy(pszFilterSpec, TEXT("*.*"));
pszFilterSpec += lstrlen(pszFilterSpec) + 1;
*pszFilterSpec = TEXT('\0');
}
// EnumProc
//
// Callback function for EnumFonts
//
// Purpose: sets lfCharSet in passed logfont to a valid lfCharSet
// and terminates enumeration.
//
int CALLBACK EnumProc(
LOGFONT* pLf,
TEXTMETRIC* pTm,
DWORD dwType,
LPARAM lpData )
{
((LOGFONT*) lpData)-> lfCharSet= pLf->lfCharSet;
return( 0 ); // stop enumeration
UNREFERENCED_PARAMETER( pTm );
UNREFERENCED_PARAMETER( dwType );
}
/* One time initialization */
INT NPInit (HANDLE hInstance, HANDLE hPrevInstance,
LPTSTR lpCmdLine, INT cmdShow)
{
HDC hDisplayDC; /* screen DC */
RECT rcT1; /* for sizing edit window */
RECT rcStatus; /* rect for the status window */
INT iSta;
WINDOWPLACEMENT wp; /* structure to place window at the correct position */
INT iParts[2];
LANGID langid;
/* determine the message number to be used for communication with
* Find dialog
*/
wFRMsg= RegisterWindowMessage( (LPTSTR)FINDMSGSTRING );
if( !wFRMsg )
{
return FALSE;
}
wHlpMsg= RegisterWindowMessage( (LPTSTR)HELPMSGSTRING );
if( !wHlpMsg )
{
return FALSE;
}
/* open a global DC to the display */
hDisplayDC= GetDC(NULL);
if( !hDisplayDC )
return FALSE;
/* Go load strings */
if (!InitStrings (hInstance))
return FALSE;
InitLocale(); // localize strings etc.
/* Load the arrow and hourglass cursors. */
hStdCursor= LoadCursor( NULL,
(LPTSTR) (INT_PTR) (GetSystemMetrics(SM_PENWINDOWS) ? IDC_ARROW : IDC_IBEAM ));
hWaitCursor= LoadCursor( NULL, IDC_WAIT );
/* Load accelerators. */
hAccel= LoadAccelerators(hInstance, TEXT("MainAcc"));
if( !hWaitCursor || !hAccel )
return FALSE;
if( !hPrevInstance )
{
if( !NPRegister( hInstance ) )
return (FALSE);
}
hInstanceNP= hInstance;
/* init. fields of PRINTDLG struct.. */
/* Inserted here since command line print statements are valid. */
g_PageSetupDlg.lStructSize = sizeof(PAGESETUPDLG);
g_PageSetupDlg.hDevMode = NULL;
g_PageSetupDlg.hDevNames = NULL;
g_PageSetupDlg.hInstance = hInstance;
SetPageSetupDefaults();
//
// Pick up information saved in registry
//
GetGlobals();
// Determine the codepages associated with the user's various system settings
GetSystemCodepages();
hwndNP= CreateWindow( szNotepad,
TEXT(""),
WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU |
WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | 0,
g_WPleft, // x
g_WPtop, // y
g_WPDX, // width
g_WPDY, // height
(HWND)NULL, // parent or owner
(HMENU)NULL, // menu or child window
hInstance, // application instance
NULL); // window creation data
g_PageSetupDlg.hwndOwner = hwndNP;
if( !hwndNP )
return FALSE;
// On multimon machines, the previous position stored of notepad may
// not be in the display area. call SetWindowPlacement to fix this.
// If the information specified in WINDOWPLACEMENT would result in a window
// that is completely off the screen, the system will automatically adjust
// the coordinates so that the window is visible, taking into account
// changes in screen resolution and multiple monitor configuration.
// g_WPDX and g_WPDY are CW_USEDEFAULT when notepad is started for the
// first time on the user machine.
if (g_WPDX != CW_USEDEFAULT && g_WPDY != CW_USEDEFAULT)
{
memset(&wp, 0, sizeof(wp));
wp.length = sizeof(wp);
wp.rcNormalPosition.left = g_WPleft;
wp.rcNormalPosition.right = g_WPleft + g_WPDX;
wp.rcNormalPosition.top = g_WPtop;
wp.rcNormalPosition.bottom = g_WPtop + g_WPDY;
// don't check the return value; if this call fails for any reason,
// just go on with the position of the notepad in the above CreateWindow() call.
SetWindowPlacement(hwndNP, &wp);
}
/* File Drag Drop support added 03/26/91 - prototype only. w-dougw */
/* All processing of drag/drop files is done the under WM_DROPFILES */
/* message. */
DragAcceptFiles( hwndNP,TRUE ); /* Process dragged and dropped files. */
GetClientRect( hwndNP, (LPRECT) &rcT1 );
hwndEdit= CreateWindowEx(
WS_EX_CLIENTEDGE,
TEXT("Edit"),
TEXT(""),
(fWrap) ? ES_STD : (ES_STD | WS_HSCROLL),
0, 0, rcT1.right, rcT1.bottom - 100,
hwndNP,
(HMENU)ID_EDIT,
hInstance,
(LPVOID)NULL );
if( !hwndEdit )
{
return FALSE;
}
// create a status window.
hwndStatus= CreateStatusWindow( (fStatus?WS_VISIBLE:0)|WS_BORDER|WS_CHILD|WS_CLIPSIBLINGS,
TEXT(""),
hwndNP,
ID_STATUS_WINDOW);
if ( !hwndStatus )
return FALSE;
GetClientRect( hwndStatus, (LPRECT) &rcStatus );
// determine height of statusbar window and save...
dyStatus = rcStatus.bottom - rcStatus.top;
iParts[0] = 3 * (rcStatus.right-rcStatus.left)/4;
iParts[1] = -1;
// Divide the status window into two parts
SendMessage(hwndStatus, SB_SETPARTS, (WPARAM) sizeof(iParts)/sizeof(INT), (LPARAM) &iParts);
// handle word wrap now if set in registry
SendMessage( hwndEdit, EM_FMTLINES, fWrap, 0L ); // tell MLE
FontStruct.lfHeight= -MulDiv(iPointSize,
GetDeviceCaps(hDisplayDC,LOGPIXELSY),
720);
hFont= CreateFontIndirect( &FontStruct );
//
// Make sure the font mapper gives us the same face name.
//
// If the locale changes, a font that use to work just fine gets mapped to
// a different facename because of support for the charset does not exist
// in the new locale.
//
// In this case, we will find one lfCharSet that does exist for this FaceName
// and use that for the CreateFontIndirect.
//
{
HFONT hPrev;
TCHAR szTextFace[LF_FACESIZE];
// Get the facename that was really used.
hPrev= SelectObject( hDisplayDC, hFont );
GetTextFace( hDisplayDC, sizeof(szTextFace)/sizeof(TCHAR), (LPTSTR) &szTextFace );
SelectObject( hDisplayDC, hPrev );
// if not the same, get a lfCharSet that does exist in this font
if( lstrcmpi( szTextFace, FontStruct.lfFaceName ) != 0 )
{
EnumFonts( hDisplayDC, FontStruct.lfFaceName, (FONTENUMPROC) EnumProc, (LPARAM) &FontStruct );
DeleteObject( hFont );
hFont= CreateFontIndirect( &FontStruct );
}
}
SendMessage (hwndEdit, WM_SETFONT, (WPARAM) hFont, MAKELPARAM(FALSE, 0));
ReleaseDC( NULL, hDisplayDC );
/* we will not verify that a unicode font is available until
** we actually need it. Perhaps we'll get lucky, and only deal
** with ascii files.
*/
szSearch[0] = (TCHAR) 0;
/*
* Win32s does not allow local memory handles to be passed to Win3.1.
* So, hEdit is used for transferring text to and from the edit control.
* Before reading text into it, it must be reallocated to a proper size.
*/
hEdit = LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT, ByteCountOf(1));
/* limit text for safety's sake. */
PostMessage( hwndEdit, EM_LIMITTEXT, (WPARAM)CCHNPMAX, 0L );
/* Get visible window on desktop; helps taskman find it */
SetFileName(NULL);
ShowWindow(hwndNP, cmdShow);
SetCursor(hStdCursor);
/* Scan for initial /A or /W to override automatic file typing for
* 'notepad /p file' or 'notepad file'
*/
lpCmdLine= SkipBlanks( lpCmdLine );
g_cpDefault = CP_AUTO;
if (!lstrncmpi(TEXT("/A"), lpCmdLine))
{
g_cpDefault = g_cpANSI;
lpCmdLine = SkipBlanks(lpCmdLine+2);
}
//
// user provided codepage
// In standard C format (1234 (decimal), x123 (hex), 010 (octal)
// if 0, then use ANSI codepage
// if 1, then use OEM codepage
else if (!lstrncmpi(TEXT("/CP:"), lpCmdLine))
{
BOOL fValid;
// scan off the code page. Base==0 means the syntax determines the base
// "10" == 10, "x10" == 16, "010" == 8
g_cpDefault = wcstoul(lpCmdLine+4, &lpCmdLine, 0);
if ((*lpCmdLine != TEXT('\0')) && (*lpCmdLine != TEXT(' ')) && (*lpCmdLine != TEXT('\t')))
{
fValid = FALSE;
}
else
{
if (g_cpDefault == CP_ACP)
{
g_cpDefault = GetACP();
}
else if (g_cpDefault == CP_OEMCP)
{
g_cpDefault = GetOEMCP();
}
fValid = FValidateCodepage(hwndNP, g_cpDefault);
}
if (!fValid)
{
AlertBox(hwndNP, szNN, szInvalidCP, NULL, MB_APPLMODAL | MB_OK | MB_ICONERROR);
return FALSE;
}
lpCmdLine = SkipBlanks(lpCmdLine);
}
else if (!lstrncmpi(TEXT("/E:"), lpCmdLine))
{
const TCHAR *rgchEncoding = lpCmdLine = lpCmdLine+3;
while ((*lpCmdLine != TEXT('\0')) && (*lpCmdLine != TEXT(' ')) && (*lpCmdLine != TEXT('\t')))
{
lpCmdLine++;
}
if (!FLookupCodepageNameW(rgchEncoding, (UINT) (lpCmdLine - rgchEncoding), &g_cpDefault))
{
AlertBox(hwndNP, szNN, szInvalidIANA, NULL, MB_APPLMODAL | MB_OK | MB_ICONERROR);
return FALSE;
}
if (!FValidateCodepage(hwndNP, g_cpDefault))
{
AlertBox(hwndNP, szNN, szInvalidCP, NULL, MB_APPLMODAL | MB_OK | MB_ICONERROR);
return FALSE;
}
lpCmdLine = SkipBlanks(lpCmdLine);
}
else if (!lstrncmpi(TEXT("/W"), lpCmdLine))
{
g_cpDefault = CP_UTF16;
lpCmdLine = SkipBlanks(lpCmdLine+2);
}
if (!lstrncmpi(TEXT("/SELECTENCODING"), lpCmdLine))
{
g_fSelectEncoding = TRUE;
lpCmdLine = SkipBlanks(lpCmdLine+15);
}
// Set encoding of new document or if LoadFile fails
g_cpOpened = g_cpDefault;
if (g_cpOpened == CP_AUTO)
{
g_cpOpened = g_cpANSI;
}
g_wbOpened = wbDefault;
/* check for /.SETUP option first.
if /.SETUP absent, check for SHELL options /P
Whenever a SHELL option is processed, post a WM_CLOSE msg.
*/
iSta= ProcessSetupOption( lpCmdLine );
if( iSta )
{
if( iSta == IDCANCEL )
{
return( FALSE );
}
}
else if( ProcessShellOptions( lpCmdLine, cmdShow ) )
{
PostMessage( hwndNP, WM_CLOSE, 0, 0L );
return TRUE;
}
else if( *lpCmdLine )
{
TCHAR szFile[MAX_PATH];
/* Get the filename. */
GetFileName(szFile, lpCmdLine);
fp = CreateFile(szFile, // filename
GENERIC_READ, // access mode
FILE_SHARE_READ|FILE_SHARE_WRITE, // share mode
NULL, // security descriptor
OPEN_EXISTING, // how to create
FILE_ATTRIBUTE_NORMAL, // file attributes
NULL); // hnd of file attrs to copy
if( fp == INVALID_HANDLE_VALUE )
{
// If the file can't be opened, maybe the user wants a new
// one created.
if( GetLastError() == ERROR_FILE_NOT_FOUND )
{
INT AlertStatus;
AlertStatus= AlertBox( hwndNP, szNN, szFNF, szFile,
MB_APPLMODAL | MB_YESNOCANCEL | MB_ICONWARNING);
if( AlertStatus == IDCANCEL )
{
return( FALSE );
}
if( AlertStatus == IDYES )
{
fp = CreateFile(szFile, // filename
GENERIC_READ|GENERIC_WRITE, // access
FILE_SHARE_READ|FILE_SHARE_WRITE, // share
NULL, // security descrp
OPEN_ALWAYS, // how to create
FILE_ATTRIBUTE_NORMAL, // file attributes
NULL); // hnd of file attrs
}
}
else
{
AlertUser_FileFail(szFile);
}
}
if (fp != INVALID_HANDLE_VALUE)
{
LoadFile(szFile, g_fSelectEncoding); // get file specified on command line
}
}
CreateFilter(TRUE, szOpenFilterSpec);
CreateFilter(FALSE, szSaveFilterSpec);
/* init. some fields of the OPENFILENAME struct used by fileopen and
* filesaveas, but NEVER changed.
*/
memset( &OFN, 0, sizeof(OFN) );
OFN.lStructSize = sizeof(OPENFILENAME);
OFN.hwndOwner = hwndNP;
OFN.nMaxFile = MAX_PATH;
OFN.hInstance = hInstance;
/* init.fields of the FINDREPLACE struct used by FindText() */
memset( &FR, 0, sizeof(FR) );
FR.lStructSize = sizeof(FINDREPLACE); /* Don't hard code it */
FR.hwndOwner = hwndNP;
/* Force a scroll to current selection (which could be at eof if
we loaded a log file.) */
{
DWORD dwStart, dwEnd;
SendMessage( hwndEdit, EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwEnd );
SendMessage( hwndEdit, EM_SETSEL, dwStart, dwEnd );
SendMessage( hwndEdit, EM_SCROLLCARET, 0, 0 );
}
langid = LOWORD((DWORD) (INT_PTR) GetKeyboardLayout(0));
GetKeyboardCodepages(langid);
if (PRIMARYLANGID(langid) == LANG_JAPANESE) {
/*
* If current HKL is Japanese, handle the result string at once.
*/
SendMessage(hwndEdit, EM_SETIMESTATUS,
EMSIS_COMPOSITIONSTRING, EIMES_GETCOMPSTRATONCE);
}
return TRUE;
}
/* ** Notepad class registration proc */
BOOL NPRegister (HANDLE hInstance)
{
WNDCLASSEX NPClass;
PWNDCLASSEX pNPClass = &NPClass;
/* Bug 12191: If Pen Windows is running, make the background cursor an
* arrow instead of the edit control ibeam. This way the user will know
* where they can use the pen for writing vs. what will be considered a
* mouse action. 18 October 1991 Clark Cyr
*/
pNPClass->cbSize = sizeof(NPClass);
pNPClass->hCursor = LoadCursor(NULL, GetSystemMetrics(SM_PENWINDOWS)
? IDC_ARROW : IDC_IBEAM);
pNPClass->hIcon = LoadIcon(hInstance,
(LPTSTR) MAKEINTRESOURCE(ID_ICON));
pNPClass->hIconSm = LoadImage(hInstance,
MAKEINTRESOURCE(ID_ICON),
IMAGE_ICON, 16, 16,
LR_DEFAULTCOLOR);
pNPClass->lpszMenuName = (LPTSTR) MAKEINTRESOURCE(ID_MENUBAR);
pNPClass->hInstance = hInstance;
pNPClass->lpszClassName = szNotepad;
pNPClass->lpfnWndProc = NPWndProc;
pNPClass->hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
pNPClass->style = 0; // was CS_BYTEALIGNCLIENT (obsolete)
pNPClass->cbClsExtra = 0;
pNPClass->cbWndExtra = 0;
if (!RegisterClassEx((LPWNDCLASSEX)pNPClass))
return (FALSE);
return (TRUE);
}
/* Get Locale info from the Registry, and initialize global vars */
void InitLocale(void)
{
GetUserLocaleCodepages();
}