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

  1. /*
  2. * Notepad application
  3. *
  4. * Copyright (C) 1984-2000 Microsoft Corporation
  5. *
  6. * NPInit - One time init for notepad.
  7. */
  8. #include "precomp.h"
  9. TCHAR chPageText[2][PT_LEN]; /* Strings to hold PageSetup items. */
  10. TCHAR chPageTextTemp[2][PT_LEN];
  11. TCHAR szPrinterName[256]; /* String to hold printername for PrintTo verb */
  12. static UINT cpDefault;
  13. static INT fSaveWindowPositions=0; /* true if we are to save window position */
  14. static INT g_WPtop,g_WPleft,g_WPDX,g_WPDY; /* initial window positions */
  15. /* routines to handle saving and restoring information in the registry.
  16. *
  17. * SaveGlobals - saves interesting globals to the registry
  18. *
  19. * GetGlobals - gets interesting globals from the registry
  20. *
  21. * Interesting Globals:
  22. *
  23. * FontStruct information include calculated pointsize
  24. * Codepage
  25. *
  26. * If we want to save PageSetup info, save the margins in some
  27. * units (cm for example) and convert on input and output.
  28. */
  29. /* name of section to save into -- never internationalize */
  30. #define OURKEYNAME TEXT("Software\\Microsoft\\Notepad")
  31. // RegWriteInt - write an integer to the registry
  32. VOID RegWriteInt( HKEY hKey, PTCHAR pszKey, INT iValue )
  33. {
  34. RegSetValueEx( hKey, pszKey, 0, REG_DWORD, (BYTE*)&iValue, sizeof(INT) );
  35. }
  36. // RegWriteString - write a string to the registry
  37. VOID RegWriteString( HKEY hKey, PTCHAR pszKey, PTCHAR pszValue )
  38. {
  39. INT len; // length of string with null in bytes
  40. len= (lstrlen( pszValue )+1) * sizeof(TCHAR);
  41. RegSetValueEx( hKey, pszKey, 0, REG_SZ, (BYTE*)pszValue, len );
  42. }
  43. // RegGetInt - Get integer from registry
  44. DWORD RegGetInt( HKEY hKey, PTCHAR pszKey, DWORD dwDefault )
  45. {
  46. DWORD dwResult= !ERROR_SUCCESS;
  47. LONG lStatus= ERROR_SUCCESS;
  48. DWORD dwSize= sizeof(DWORD);
  49. DWORD dwType= 0;
  50. if( hKey )
  51. {
  52. lStatus= RegQueryValueEx( hKey,
  53. pszKey,
  54. NULL,
  55. &dwType,
  56. (BYTE*) &dwResult,
  57. &dwSize );
  58. }
  59. if( lStatus != ERROR_SUCCESS || dwType != REG_DWORD )
  60. {
  61. dwResult= dwDefault;
  62. }
  63. return( dwResult );
  64. }
  65. // RegGetString - get string from registry
  66. VOID RegGetString( HKEY hKey, PTCHAR pszKey, PTCHAR pszDefault, PTCHAR pszResult, INT iCharLen )
  67. {
  68. LONG lStatus= !ERROR_SUCCESS;
  69. DWORD dwSize; // size of buffer
  70. DWORD dwType= REG_NONE;
  71. dwSize= iCharLen * sizeof(TCHAR);
  72. if( hKey )
  73. {
  74. lStatus= RegQueryValueEx( hKey,
  75. pszKey,
  76. NULL,
  77. &dwType,
  78. (BYTE*) pszResult,
  79. &dwSize );
  80. }
  81. if( lStatus != ERROR_SUCCESS || dwType != REG_SZ )
  82. {
  83. CopyMemory( pszResult, pszDefault, iCharLen*sizeof(TCHAR) );
  84. }
  85. }
  86. // lfHeight is calculated using PointSize
  87. // lfWidth set by font mapper
  88. VOID SaveGlobals(VOID)
  89. {
  90. HKEY hKey; // key to our registry root
  91. LONG lStatus; // status from RegCreateKey
  92. WINDOWPLACEMENT wp;
  93. lStatus= RegCreateKey( HKEY_CURRENT_USER, OURKEYNAME, &hKey );
  94. if( lStatus != ERROR_SUCCESS )
  95. {
  96. return; // just return quietly
  97. }
  98. RegWriteInt( hKey, TEXT("lfEscapement"), FontStruct.lfEscapement);
  99. RegWriteInt( hKey, TEXT("lfOrientation"), FontStruct.lfOrientation);
  100. RegWriteInt( hKey, TEXT("lfWeight"), FontStruct.lfWeight);
  101. RegWriteInt( hKey, TEXT("lfItalic"), FontStruct.lfItalic);
  102. RegWriteInt( hKey, TEXT("lfUnderline"), FontStruct.lfUnderline);
  103. RegWriteInt( hKey, TEXT("lfStrikeOut"), FontStruct.lfStrikeOut);
  104. RegWriteInt( hKey, TEXT("lfCharSet"), FontStruct.lfCharSet);
  105. RegWriteInt( hKey, TEXT("lfOutPrecision"), FontStruct.lfOutPrecision);
  106. RegWriteInt( hKey, TEXT("lfClipPrecision"), FontStruct.lfClipPrecision);
  107. RegWriteInt( hKey, TEXT("lfQuality"), FontStruct.lfQuality);
  108. RegWriteInt( hKey, TEXT("lfPitchAndFamily"), FontStruct.lfPitchAndFamily);
  109. RegWriteInt( hKey, TEXT("iPointSize"), iPointSize);
  110. RegWriteInt( hKey, TEXT("fWrap"), fWrap);
  111. RegWriteInt( hKey, TEXT("StatusBar"), fStatus);
  112. RegWriteInt( hKey, TEXT("fSaveWindowPositions"),fSaveWindowPositions );
  113. RegWriteString( hKey, TEXT("lfFaceName"), FontStruct.lfFaceName);
  114. RegWriteString( hKey, TEXT("szHeader"), chPageText[HEADER] );
  115. RegWriteString( hKey, TEXT("szTrailer"), chPageText[FOOTER] );
  116. RegWriteInt( hKey, TEXT("iMarginTop"), g_PageSetupDlg.rtMargin.top );
  117. RegWriteInt( hKey, TEXT("iMarginBottom"), g_PageSetupDlg.rtMargin.bottom );
  118. RegWriteInt( hKey, TEXT("iMarginLeft"), g_PageSetupDlg.rtMargin.left );
  119. RegWriteInt( hKey, TEXT("iMarginRight"), g_PageSetupDlg.rtMargin.right );
  120. wp.length= sizeof(wp);
  121. if( GetWindowPlacement( hwndNP, &wp ) )
  122. {
  123. RegWriteInt( hKey, TEXT("iWindowPosX"), wp.rcNormalPosition.left);
  124. RegWriteInt( hKey, TEXT("iWindowPosY"), wp.rcNormalPosition.top);
  125. RegWriteInt( hKey, TEXT("iWindowPosDX"), wp.rcNormalPosition.right - wp.rcNormalPosition.left);
  126. RegWriteInt( hKey, TEXT("iWindowPosDY"), wp.rcNormalPosition.bottom - wp.rcNormalPosition.top);
  127. }
  128. RegCloseKey( hKey );
  129. }
  130. // GetGlobals
  131. //
  132. // Pick up font information etc that may be saved in the registry.
  133. //
  134. // We are called pretty early in setup and don't have things like hwndNP valid yet.
  135. //
  136. VOID GetGlobals( VOID )
  137. {
  138. LOGFONT lfDef; // default logical font
  139. HFONT hFixedFont; // standard font to use
  140. LONG lStatus; // status from RegCreateKey
  141. HKEY hKey; // key into registry
  142. //
  143. // quickly get a reasonable set of default parameters
  144. // for the default font if we need it.
  145. //
  146. hFixedFont= GetStockObject( SYSTEM_FIXED_FONT );
  147. if ( hFixedFont )
  148. {
  149. GetObject( hFixedFont, sizeof(LOGFONT), &lfDef );
  150. }
  151. else
  152. {
  153. ZeroMemory( &lfDef, sizeof(lfDef) );
  154. }
  155. lStatus= RegCreateKey( HKEY_CURRENT_USER, OURKEYNAME, &hKey );
  156. if( lStatus != ERROR_SUCCESS )
  157. {
  158. hKey= NULL; // later calls to RegGet... will return defaults
  159. }
  160. FontStruct.lfWidth= 0;
  161. FontStruct.lfEscapement= (LONG)RegGetInt( hKey, TEXT("lfEscapement"), lfDef.lfEscapement);
  162. FontStruct.lfOrientation= (LONG)RegGetInt( hKey, TEXT("lfOrientation"), lfDef.lfOrientation);
  163. FontStruct.lfWeight= (LONG)RegGetInt( hKey, TEXT("lfWeight"), lfDef.lfWeight);
  164. FontStruct.lfItalic= (BYTE)RegGetInt( hKey, TEXT("lfItalic"), lfDef.lfItalic);
  165. FontStruct.lfUnderline= (BYTE)RegGetInt( hKey, TEXT("lfUnderline"), lfDef.lfUnderline);
  166. FontStruct.lfStrikeOut= (BYTE)RegGetInt( hKey, TEXT("lfStrikeOut"), lfDef.lfStrikeOut);
  167. //
  168. // We have to preserve lfCharSet because some fonts (symbol, marlett) don't handle
  169. // 0 (ANSI_CHARSET) or 1 (DEFAULT_CHARSET), and the font mapper will map to a
  170. // different facename. Later we will see if the CreateFont has the same FaceName
  171. // and get a more appropriate lfCharSet if need be.
  172. //
  173. FontStruct.lfCharSet= (BYTE)RegGetInt( hKey, TEXT("lfCharSet"), lfDef.lfCharSet);
  174. FontStruct.lfOutPrecision= (BYTE)RegGetInt( hKey, TEXT("lfOutPrecision"), lfDef.lfOutPrecision);
  175. FontStruct.lfClipPrecision= (BYTE)RegGetInt( hKey, TEXT("lfClipPrecision"), lfDef.lfClipPrecision);
  176. FontStruct.lfQuality= (BYTE)RegGetInt( hKey, TEXT("lfQuality"), lfDef.lfQuality);
  177. FontStruct.lfPitchAndFamily= (BYTE)RegGetInt( hKey, TEXT("lfPitchAndFamily"), lfDef.lfPitchAndFamily);
  178. //
  179. // If there is no FaceName in the registry, use the default "Lucida Console"
  180. // This will show off most of the glyphs except in the FE locales.
  181. // For FE, we can't font link fonts with the glyphs because they would have to have
  182. // the exact width as lucida console, or the console/csrss will AV (July 9, 1999)
  183. //
  184. RegGetString( hKey, TEXT("lfFaceName"), TEXT("Lucida Console"), FontStruct.lfFaceName, LF_FACESIZE);
  185. iPointSize= RegGetInt( hKey, TEXT("iPointSize"), 100);
  186. fWrap= RegGetInt( hKey, TEXT("fWrap"), 0);
  187. fStatus= RegGetInt( hKey, TEXT("StatusBar"), 0);
  188. fSaveWindowPositions= RegGetInt( hKey, TEXT("fSaveWindowPositions"), 0 );
  189. // if page settings not in registry, we will use defaults
  190. RegGetString( hKey, TEXT("szHeader"), chPageText[HEADER], chPageText[HEADER], PT_LEN );
  191. RegGetString( hKey, TEXT("szTrailer"), chPageText[FOOTER], chPageText[FOOTER], PT_LEN );
  192. g_PageSetupDlg.rtMargin.top= (LONG)RegGetInt( hKey, TEXT("iMarginTop"), g_PageSetupDlg.rtMargin.top );
  193. g_PageSetupDlg.rtMargin.bottom= (LONG)RegGetInt( hKey, TEXT("iMarginBottom"), g_PageSetupDlg.rtMargin.bottom );
  194. g_PageSetupDlg.rtMargin.left= (LONG)RegGetInt( hKey, TEXT("iMarginLeft"), g_PageSetupDlg.rtMargin.left );
  195. g_PageSetupDlg.rtMargin.right= (LONG)RegGetInt( hKey, TEXT("iMarginRight"), g_PageSetupDlg.rtMargin.right );
  196. // if window positions in registry use them, otherwise us defaults
  197. g_WPtop= (INT) RegGetInt( hKey, TEXT("iWindowPosY"), (DWORD) CW_USEDEFAULT );
  198. g_WPleft= (INT) RegGetInt( hKey, TEXT("iWindowPosX"), (DWORD) CW_USEDEFAULT );
  199. g_WPDX= (INT) RegGetInt( hKey, TEXT("iWindowPosDX"), (DWORD) CW_USEDEFAULT );
  200. g_WPDY= (INT) RegGetInt( hKey, TEXT("iWindowPosDY"), (DWORD) CW_USEDEFAULT );
  201. if( hKey )
  202. {
  203. RegCloseKey( hKey );
  204. }
  205. }
  206. void GetLocaleCodepages(LCID lcid, UINT* pcpANSI, UINT* pcpOEM)
  207. {
  208. // FEATURE: don't check returns? Not likely; fix later
  209. GetLocaleInfoW(lcid,
  210. LOCALE_IDEFAULTANSICODEPAGE | LOCALE_RETURN_NUMBER,
  211. (LPTSTR) pcpANSI,
  212. sizeof(*pcpANSI));
  213. GetLocaleInfoW(lcid,
  214. LOCALE_IDEFAULTCODEPAGE | LOCALE_RETURN_NUMBER,
  215. (LPTSTR) pcpOEM,
  216. sizeof(*pcpOEM));
  217. // LOCALE_IDEFAULTMACCODEPAGE ?
  218. // LOCALE_IDEFAULTEBCDICCODEPAGE ?
  219. }
  220. void GetKeyboardCodepages(LANGID langid)
  221. {
  222. GetLocaleCodepages(langid, &g_cpKeyboardANSI, &g_cpKeyboardOEM);
  223. }
  224. void GetSystemCodepages(void)
  225. {
  226. g_cpANSI = GetACP();
  227. g_cpOEM = GetOEMCP();
  228. }
  229. void GetUserLocaleCodepages(void)
  230. {
  231. GetLocaleCodepages(GetUserDefaultUILanguage(), &g_cpUserLocaleANSI, &g_cpUserLocaleOEM);
  232. GetLocaleCodepages(GetUserDefaultLCID(), &g_cpUserLocaleANSI, &g_cpUserLocaleOEM);
  233. }
  234. /*
  235. * lstrncmpi( str1, str2, len )
  236. * compares two strings, str1 and str2, up
  237. * to length 'len' ignoring case. If they
  238. * are equal, we will return 0. Otherwise not 0.
  239. */
  240. static
  241. INT lstrncmpi( PTCHAR sz1, PTCHAR sz2 )
  242. {
  243. TCHAR ch1, ch2;
  244. while( *sz1 )
  245. {
  246. ch1= (TCHAR) (INT_PTR) CharUpper( (LPTSTR) (INT_PTR) *sz1++ );
  247. ch2= (TCHAR) (INT_PTR) CharUpper( (LPTSTR) (INT_PTR) *sz2++ );
  248. if( ch1 != ch2 )
  249. return 1;
  250. }
  251. return 0; // they are equal
  252. }
  253. static int NPRegister (HANDLE hInstance);
  254. /* GetFileName
  255. *
  256. * Parse off filename from command line and put
  257. * into lpFileName
  258. */
  259. LPTSTR GetFileName( LPTSTR lpFileName, LPTSTR lpCmdLine )
  260. {
  261. LPTSTR lpTemp = lpFileName;
  262. HANDLE hFindFile;
  263. WIN32_FIND_DATA info;
  264. /*
  265. ** Allow for filenames surrounded by double and single quotes
  266. ** like in longfilenames.
  267. */
  268. if( *lpCmdLine == TEXT('\"') || *lpCmdLine == TEXT('\'') )
  269. {
  270. TCHAR chMatch = *lpCmdLine;
  271. DWORD dwSize=0;
  272. // Copy over filename
  273. while( *(++lpCmdLine) && (*lpCmdLine != chMatch) && (dwSize<MAX_PATH) )
  274. {
  275. *lpTemp++ = *lpCmdLine;
  276. dwSize++;
  277. }
  278. // NULL terminate the filename (no embedded quotes allowed in filenames)
  279. *lpTemp = TEXT('\0');
  280. }
  281. else
  282. {
  283. lstrcpyn(lpFileName, lpCmdLine,MAX_PATH);
  284. }
  285. /*
  286. ** Check to see if the unaltered filename exists. If it does then don't
  287. ** append a default extension.
  288. */
  289. hFindFile= FindFirstFile( lpFileName, &info );
  290. if( hFindFile != INVALID_HANDLE_VALUE )
  291. {
  292. FindClose( hFindFile );
  293. }
  294. else
  295. {
  296. /*
  297. ** Add default extension and try again
  298. */
  299. AddExt( lpFileName );
  300. hFindFile= FindFirstFile( lpFileName, &info );
  301. if( hFindFile != INVALID_HANDLE_VALUE )
  302. {
  303. FindClose( hFindFile );
  304. }
  305. }
  306. // return the pointer to the end of the filename.
  307. return lpCmdLine;
  308. }
  309. /* SizeStrings - Get the total size of the resource strings */
  310. /* returns size in 'chars' or zero if failure */
  311. /* we do this in case the international people really change */
  312. /* the size of resources. */
  313. /* Read all the strings into a buffer to size them. Since we */
  314. /* don't know the maximum size of string resource, we may have */
  315. /* to change the size of the read buffer. This is done with */
  316. /* a simple doubling algorithm. */
  317. INT SizeStrings(HANDLE hInstance)
  318. {
  319. INT iElementSize=350; // current max size of string
  320. INT total; // total size of resources
  321. PTCHAR Buf; // buffer to try putting resources into
  322. INT ids; // identifier number for resource
  323. INT len; // length of one resource
  324. while( TRUE ) // keep looping til all strings can be read
  325. {
  326. Buf= LocalAlloc( LPTR, ByteCountOf(iElementSize) );
  327. if( !Buf )
  328. {
  329. return 0; // failure
  330. }
  331. for( ids=0, total=0; rgsz[ids] != NULL; ids++ )
  332. {
  333. len= LoadString( hInstance, (UINT) (UINT_PTR) (*rgsz[ids]), Buf, iElementSize );
  334. if( len >= iElementSize-1 )
  335. {
  336. #if DBG
  337. ODS(TEXT("notepad: resource string too long!\n"));
  338. #endif
  339. break;
  340. }
  341. total += len+1; // account for null terminator
  342. }
  343. LocalFree( Buf );
  344. if( rgsz[ids] == NULL ) break;
  345. iElementSize= iElementSize*2;
  346. }
  347. return( total );
  348. }
  349. /* InitStrings - Get all text strings from resource file */
  350. BOOL InitStrings (HANDLE hInstance)
  351. {
  352. TCHAR* pch;
  353. INT cchRemaining;
  354. INT ids, cch;
  355. // allocate memory and lock it down forever. we have pointers into it.
  356. // the localrealloc() function will not work well for freeing
  357. // unused memory because it may (and did) move memory.
  358. cchRemaining= SizeStrings( hInstance );
  359. if( !cchRemaining )
  360. return( FALSE ); // fail because we are out of memory
  361. pch= LocalAlloc( LPTR, ByteCountOf(cchRemaining) );
  362. if( !pch )
  363. return( FALSE );
  364. cchRemaining= (INT)LocalSize( pch ) / sizeof(TCHAR);
  365. if( cchRemaining == 0 ) // can't alloc memory - failure
  366. return( FALSE );
  367. for( ids = 0; rgsz[ids] != NULL; ids++ )
  368. {
  369. cch= 1 + LoadString( hInstance, (UINT) (UINT_PTR) (*rgsz[ids]), pch, cchRemaining );
  370. *rgsz[ids]= pch;
  371. pch += cch;
  372. if( cch > cchRemaining ) // should never happen
  373. {
  374. MessageBox( NULL, TEXT("Out of RC string space!!"),
  375. TEXT("DEV Error!"), MB_OK);
  376. return( FALSE );
  377. }
  378. cchRemaining -= cch;
  379. }
  380. /* Get header and footer strings */
  381. lstrcpyn( chPageText[HEADER], szHeader, PT_LEN );
  382. lstrcpyn( chPageText[FOOTER], szFooter, PT_LEN );
  383. chMerge= *szMerge;
  384. return (TRUE);
  385. }
  386. /*
  387. * SkipBlanks( pszText )
  388. * skips blanks or tabs to either next character or EOL
  389. * returns pointer to same.
  390. */
  391. PTCHAR SkipBlanks( PTCHAR pszText )
  392. {
  393. while( *pszText == TEXT(' ') || *pszText == TEXT('\t') )
  394. pszText++;
  395. return pszText;
  396. }
  397. // if /.SETUP option exists in the command line process it.
  398. BOOL ProcessSetupOption (LPTSTR lpszCmdLine)
  399. {
  400. INT iSta= 0;
  401. /* Search for /.SETUP in the command line */
  402. if( !lstrncmpi( TEXT("/.SETUP"), lpszCmdLine ) )
  403. {
  404. fRunBySetup = TRUE;
  405. /* Save system menu handle for INITMENUPOPUP message */
  406. hSysMenuSetup =GetSystemMenu(hwndNP, FALSE);
  407. /* Allow exit on ^C, ^D and ^Z */
  408. /* Note that LoadAccelerators must be called before */
  409. /* TranslateAccelerator is called, true here */
  410. hAccel = LoadAccelerators(hInstanceNP, TEXT("SlipUpAcc"));
  411. lpszCmdLine += 7;
  412. }
  413. else
  414. return FALSE;
  415. /* Don't offer a minimize button */
  416. SetWindowLong( hwndNP, GWL_STYLE,
  417. WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU |
  418. WS_THICKFRAME | WS_MAXIMIZEBOX |
  419. WS_VSCROLL | WS_HSCROLL);
  420. /* skip blanks again to get to filename */
  421. lpszCmdLine= SkipBlanks( lpszCmdLine );
  422. if (*lpszCmdLine)
  423. {
  424. TCHAR szFile[MAX_PATH];
  425. /* Get the filename. */
  426. GetFileName(szFile, lpszCmdLine);
  427. fp= CreateFile( szFile, // filename
  428. GENERIC_READ, // access mode
  429. FILE_SHARE_READ|FILE_SHARE_WRITE, // share mode
  430. NULL, // security descriptor
  431. OPEN_EXISTING, // how to create
  432. FILE_ATTRIBUTE_NORMAL, //file attributes
  433. NULL); // hnd of file attrs
  434. if( fp == INVALID_HANDLE_VALUE )
  435. {
  436. DWORD dwErr;
  437. // Check GetLastError to see why we failed
  438. dwErr = GetLastError ();
  439. switch (dwErr)
  440. {
  441. case ERROR_ACCESS_DENIED:
  442. iSta= AlertBox( hwndNP, szNN, szACCESSDENY, szFile,
  443. MB_APPLMODAL | MB_OKCANCEL | MB_ICONWARNING);
  444. break;
  445. case ERROR_FILE_NOT_FOUND:
  446. iSta= AlertBox(hwndNP, szNN, szFNF, szFile,
  447. MB_APPLMODAL | MB_YESNOCANCEL | MB_ICONWARNING);
  448. if( iSta == IDYES )
  449. {
  450. fp= CreateFile( szFile, // filename
  451. GENERIC_READ|GENERIC_WRITE, // access
  452. FILE_SHARE_READ|FILE_SHARE_WRITE, // share
  453. NULL, // security descrp
  454. OPEN_ALWAYS, // how to create
  455. FILE_ATTRIBUTE_NORMAL, // file attributes
  456. NULL); // hnd of file attrs
  457. }
  458. break;
  459. case ERROR_INVALID_NAME:
  460. iSta= AlertBox( hwndNP, szNN, szNVF, szFile,
  461. MB_APPLMODAL | MB_OKCANCEL | MB_ICONWARNING);
  462. break;
  463. default:
  464. iSta= AlertBox(hwndNP, szNN, szDiskError, szFile,
  465. MB_APPLMODAL | MB_OKCANCEL | MB_ICONWARNING);
  466. break;
  467. }
  468. }
  469. if (fp == INVALID_HANDLE_VALUE)
  470. return (FALSE);
  471. LoadFile(szFile, FALSE); // load setup file
  472. }
  473. if( iSta == IDCANCEL )
  474. return( IDCANCEL );
  475. else
  476. return( IDYES );
  477. }
  478. /*
  479. * ProcessShellOptions(lpszCmdLine)
  480. *
  481. * If the command line has any options specified by the shell
  482. * process them.
  483. * Currently /P <filename> - prints the given file
  484. * /PT "filename" "printer name" "Driver dll" "port"
  485. */
  486. BOOL ProcessShellOptions (LPTSTR lpszCmdLine, int cmdShow)
  487. {
  488. BOOL bDefPrinter = TRUE;
  489. LPTSTR lpszAfterFileName;
  490. INT i = 0;
  491. TCHAR szFile[MAX_PATH];
  492. // Is it PrintTo ?
  493. if( lstrncmpi( TEXT("/PT"), lpszCmdLine ) == 0)
  494. {
  495. lpszCmdLine= SkipBlanks( lpszCmdLine+3 );
  496. bDefPrinter = FALSE;
  497. }
  498. // Or is it Print ?
  499. else if ( lstrncmpi( TEXT("/P"), lpszCmdLine ) == 0)
  500. {
  501. lpszCmdLine= SkipBlanks( lpszCmdLine+2 );
  502. }
  503. else
  504. return FALSE;
  505. if (!*lpszCmdLine)
  506. return FALSE;
  507. /* Added as per Bug #10923 declaring that the window should show up
  508. * and then the printing should begin. 29 July 1991 Clark Cyr
  509. */
  510. ShowWindow(hwndNP, cmdShow);
  511. /* Get the filename; have the pointer to the end of the filename */
  512. lpszAfterFileName = GetFileName(szFile, lpszCmdLine) + 1;
  513. if (!bDefPrinter)
  514. {
  515. /* extract the printer name from the command line. */
  516. if (!*lpszAfterFileName)
  517. return FALSE;
  518. lpszAfterFileName = SkipBlanks( lpszAfterFileName );
  519. /* (since we are passing multiple arguments here, the filename, */
  520. /* the printername have to be in quotes. */
  521. if( *lpszAfterFileName != TEXT('\"') )
  522. return FALSE;
  523. // Copy over printername
  524. while( *(++lpszAfterFileName) && *lpszAfterFileName != TEXT('\"') )
  525. {
  526. szPrinterName[i++] = *lpszAfterFileName;
  527. }
  528. // NULL terminate the printername (no embedded quotes allowed in printernames)
  529. szPrinterName[i] = TEXT('\0');
  530. }
  531. fp= CreateFile( szFile, // filename
  532. GENERIC_READ, // access mode
  533. FILE_SHARE_READ|FILE_SHARE_WRITE, // share mode
  534. NULL, // security descriptor
  535. OPEN_EXISTING, // how to create
  536. FILE_ATTRIBUTE_NORMAL, // file attributes
  537. NULL); // hnd of file attrs to copy
  538. if( fp == INVALID_HANDLE_VALUE )
  539. {
  540. TCHAR* pszMsg;
  541. // select reasonable error message based on GetLastError
  542. switch( GetLastError() )
  543. {
  544. case ERROR_ACCESS_DENIED:
  545. case ERROR_NETWORK_ACCESS_DENIED:
  546. pszMsg= szACCESSDENY;
  547. break;
  548. case ERROR_FILE_NOT_FOUND:
  549. pszMsg= szFNF;
  550. break;
  551. case ERROR_INVALID_NAME:
  552. pszMsg= szNVF;
  553. break;
  554. default:
  555. pszMsg= szDiskError;
  556. break;
  557. }
  558. AlertBox(hwndNP, szNN, pszMsg, szFile,
  559. MB_APPLMODAL | MB_OK | MB_ICONWARNING);
  560. return (TRUE);
  561. }
  562. // Load the file into the edit control
  563. LoadFile(szFile, g_fSelectEncoding); // get print file
  564. // Print the file
  565. if (bDefPrinter)
  566. {
  567. PrintIt( DoNotUseDialog );
  568. }
  569. else
  570. {
  571. PrintIt( NoDialogNonDefault );
  572. }
  573. return (TRUE);
  574. }
  575. /* CreateFilter
  576. *
  577. * Creates filters for GetOpenFileName.
  578. *
  579. */
  580. VOID CreateFilter(BOOL fOpen, PTCHAR szFilterSpec)
  581. {
  582. PTCHAR pszFilterSpec;
  583. /* construct default filter string in the required format for
  584. * the new FileOpen and FileSaveAs dialogs
  585. * if you add to this, make sure CCHFILTERMAX is large enough.
  586. */
  587. pszFilterSpec = szFilterSpec;
  588. // .txt first for compatibility
  589. lstrcpy(pszFilterSpec, szTextFiles);
  590. pszFilterSpec += lstrlen(pszFilterSpec) + 1;
  591. lstrcpy(pszFilterSpec, TEXT("*.txt"));
  592. pszFilterSpec += lstrlen(pszFilterSpec) + 1;
  593. lstrcpy(pszFilterSpec, szHtmlFiles);
  594. pszFilterSpec += lstrlen(pszFilterSpec) + 1;
  595. lstrcpy(pszFilterSpec, TEXT("*.htm;*.html"));
  596. pszFilterSpec += lstrlen(pszFilterSpec) + 1;
  597. lstrcpy(pszFilterSpec, szXmlFiles);
  598. pszFilterSpec += lstrlen(pszFilterSpec) + 1;
  599. lstrcpy(pszFilterSpec, TEXT("*.xml"));
  600. pszFilterSpec += lstrlen(pszFilterSpec) + 1;
  601. if (fOpen)
  602. {
  603. lstrcpy(pszFilterSpec, szEncodedText);
  604. pszFilterSpec += lstrlen(pszFilterSpec) + 1;
  605. lstrcpy(pszFilterSpec, TEXT("*.txt"));
  606. pszFilterSpec += lstrlen(pszFilterSpec) + 1;
  607. }
  608. // and last, all files
  609. lstrcpy(pszFilterSpec, szAllFiles);
  610. pszFilterSpec += lstrlen(pszFilterSpec) + 1;
  611. lstrcpy(pszFilterSpec, TEXT("*.*"));
  612. pszFilterSpec += lstrlen(pszFilterSpec) + 1;
  613. *pszFilterSpec = TEXT('\0');
  614. }
  615. // EnumProc
  616. //
  617. // Callback function for EnumFonts
  618. //
  619. // Purpose: sets lfCharSet in passed logfont to a valid lfCharSet
  620. // and terminates enumeration.
  621. //
  622. int CALLBACK EnumProc(
  623. LOGFONT* pLf,
  624. TEXTMETRIC* pTm,
  625. DWORD dwType,
  626. LPARAM lpData )
  627. {
  628. ((LOGFONT*) lpData)-> lfCharSet= pLf->lfCharSet;
  629. return( 0 ); // stop enumeration
  630. UNREFERENCED_PARAMETER( pTm );
  631. UNREFERENCED_PARAMETER( dwType );
  632. }
  633. /* One time initialization */
  634. INT NPInit (HANDLE hInstance, HANDLE hPrevInstance,
  635. LPTSTR lpCmdLine, INT cmdShow)
  636. {
  637. HDC hDisplayDC; /* screen DC */
  638. RECT rcT1; /* for sizing edit window */
  639. RECT rcStatus; /* rect for the status window */
  640. INT iSta;
  641. WINDOWPLACEMENT wp; /* structure to place window at the correct position */
  642. INT iParts[2];
  643. LANGID langid;
  644. /* determine the message number to be used for communication with
  645. * Find dialog
  646. */
  647. wFRMsg= RegisterWindowMessage( (LPTSTR)FINDMSGSTRING );
  648. if( !wFRMsg )
  649. {
  650. return FALSE;
  651. }
  652. wHlpMsg= RegisterWindowMessage( (LPTSTR)HELPMSGSTRING );
  653. if( !wHlpMsg )
  654. {
  655. return FALSE;
  656. }
  657. /* open a global DC to the display */
  658. hDisplayDC= GetDC(NULL);
  659. if( !hDisplayDC )
  660. return FALSE;
  661. /* Go load strings */
  662. if (!InitStrings (hInstance))
  663. return FALSE;
  664. InitLocale(); // localize strings etc.
  665. /* Load the arrow and hourglass cursors. */
  666. hStdCursor= LoadCursor( NULL,
  667. (LPTSTR) (INT_PTR) (GetSystemMetrics(SM_PENWINDOWS) ? IDC_ARROW : IDC_IBEAM ));
  668. hWaitCursor= LoadCursor( NULL, IDC_WAIT );
  669. /* Load accelerators. */
  670. hAccel= LoadAccelerators(hInstance, TEXT("MainAcc"));
  671. if( !hWaitCursor || !hAccel )
  672. return FALSE;
  673. if( !hPrevInstance )
  674. {
  675. if( !NPRegister( hInstance ) )
  676. return (FALSE);
  677. }
  678. hInstanceNP= hInstance;
  679. /* init. fields of PRINTDLG struct.. */
  680. /* Inserted here since command line print statements are valid. */
  681. g_PageSetupDlg.lStructSize = sizeof(PAGESETUPDLG);
  682. g_PageSetupDlg.hDevMode = NULL;
  683. g_PageSetupDlg.hDevNames = NULL;
  684. g_PageSetupDlg.hInstance = hInstance;
  685. SetPageSetupDefaults();
  686. //
  687. // Pick up information saved in registry
  688. //
  689. GetGlobals();
  690. // Determine the codepages associated with the user's various system settings
  691. GetSystemCodepages();
  692. hwndNP= CreateWindow( szNotepad,
  693. TEXT(""),
  694. WS_OVERLAPPED | WS_CAPTION | WS_SYSMENU |
  695. WS_THICKFRAME | WS_MINIMIZEBOX | WS_MAXIMIZEBOX | 0,
  696. g_WPleft, // x
  697. g_WPtop, // y
  698. g_WPDX, // width
  699. g_WPDY, // height
  700. (HWND)NULL, // parent or owner
  701. (HMENU)NULL, // menu or child window
  702. hInstance, // application instance
  703. NULL); // window creation data
  704. g_PageSetupDlg.hwndOwner = hwndNP;
  705. if( !hwndNP )
  706. return FALSE;
  707. // On multimon machines, the previous position stored of notepad may
  708. // not be in the display area. call SetWindowPlacement to fix this.
  709. // If the information specified in WINDOWPLACEMENT would result in a window
  710. // that is completely off the screen, the system will automatically adjust
  711. // the coordinates so that the window is visible, taking into account
  712. // changes in screen resolution and multiple monitor configuration.
  713. // g_WPDX and g_WPDY are CW_USEDEFAULT when notepad is started for the
  714. // first time on the user machine.
  715. if (g_WPDX != CW_USEDEFAULT && g_WPDY != CW_USEDEFAULT)
  716. {
  717. memset(&wp, 0, sizeof(wp));
  718. wp.length = sizeof(wp);
  719. wp.rcNormalPosition.left = g_WPleft;
  720. wp.rcNormalPosition.right = g_WPleft + g_WPDX;
  721. wp.rcNormalPosition.top = g_WPtop;
  722. wp.rcNormalPosition.bottom = g_WPtop + g_WPDY;
  723. // don't check the return value; if this call fails for any reason,
  724. // just go on with the position of the notepad in the above CreateWindow() call.
  725. SetWindowPlacement(hwndNP, &wp);
  726. }
  727. /* File Drag Drop support added 03/26/91 - prototype only. w-dougw */
  728. /* All processing of drag/drop files is done the under WM_DROPFILES */
  729. /* message. */
  730. DragAcceptFiles( hwndNP,TRUE ); /* Process dragged and dropped files. */
  731. GetClientRect( hwndNP, (LPRECT) &rcT1 );
  732. hwndEdit= CreateWindowEx(
  733. WS_EX_CLIENTEDGE,
  734. TEXT("Edit"),
  735. TEXT(""),
  736. (fWrap) ? ES_STD : (ES_STD | WS_HSCROLL),
  737. 0, 0, rcT1.right, rcT1.bottom - 100,
  738. hwndNP,
  739. (HMENU)ID_EDIT,
  740. hInstance,
  741. (LPVOID)NULL );
  742. if( !hwndEdit )
  743. {
  744. return FALSE;
  745. }
  746. // create a status window.
  747. hwndStatus= CreateStatusWindow( (fStatus?WS_VISIBLE:0)|WS_BORDER|WS_CHILD|WS_CLIPSIBLINGS,
  748. TEXT(""),
  749. hwndNP,
  750. ID_STATUS_WINDOW);
  751. if ( !hwndStatus )
  752. return FALSE;
  753. GetClientRect( hwndStatus, (LPRECT) &rcStatus );
  754. // determine height of statusbar window and save...
  755. dyStatus = rcStatus.bottom - rcStatus.top;
  756. iParts[0] = 3 * (rcStatus.right-rcStatus.left)/4;
  757. iParts[1] = -1;
  758. // Divide the status window into two parts
  759. SendMessage(hwndStatus, SB_SETPARTS, (WPARAM) sizeof(iParts)/sizeof(INT), (LPARAM) &iParts);
  760. // handle word wrap now if set in registry
  761. SendMessage( hwndEdit, EM_FMTLINES, fWrap, 0L ); // tell MLE
  762. FontStruct.lfHeight= -MulDiv(iPointSize,
  763. GetDeviceCaps(hDisplayDC,LOGPIXELSY),
  764. 720);
  765. hFont= CreateFontIndirect( &FontStruct );
  766. //
  767. // Make sure the font mapper gives us the same face name.
  768. //
  769. // If the locale changes, a font that use to work just fine gets mapped to
  770. // a different facename because of support for the charset does not exist
  771. // in the new locale.
  772. //
  773. // In this case, we will find one lfCharSet that does exist for this FaceName
  774. // and use that for the CreateFontIndirect.
  775. //
  776. {
  777. HFONT hPrev;
  778. TCHAR szTextFace[LF_FACESIZE];
  779. // Get the facename that was really used.
  780. hPrev= SelectObject( hDisplayDC, hFont );
  781. GetTextFace( hDisplayDC, sizeof(szTextFace)/sizeof(TCHAR), (LPTSTR) &szTextFace );
  782. SelectObject( hDisplayDC, hPrev );
  783. // if not the same, get a lfCharSet that does exist in this font
  784. if( lstrcmpi( szTextFace, FontStruct.lfFaceName ) != 0 )
  785. {
  786. EnumFonts( hDisplayDC, FontStruct.lfFaceName, (FONTENUMPROC) EnumProc, (LPARAM) &FontStruct );
  787. DeleteObject( hFont );
  788. hFont= CreateFontIndirect( &FontStruct );
  789. }
  790. }
  791. SendMessage (hwndEdit, WM_SETFONT, (WPARAM) hFont, MAKELPARAM(FALSE, 0));
  792. ReleaseDC( NULL, hDisplayDC );
  793. /* we will not verify that a unicode font is available until
  794. ** we actually need it. Perhaps we'll get lucky, and only deal
  795. ** with ascii files.
  796. */
  797. szSearch[0] = (TCHAR) 0;
  798. /*
  799. * Win32s does not allow local memory handles to be passed to Win3.1.
  800. * So, hEdit is used for transferring text to and from the edit control.
  801. * Before reading text into it, it must be reallocated to a proper size.
  802. */
  803. hEdit = LocalAlloc(LMEM_MOVEABLE | LMEM_ZEROINIT, ByteCountOf(1));
  804. /* limit text for safety's sake. */
  805. PostMessage( hwndEdit, EM_LIMITTEXT, (WPARAM)CCHNPMAX, 0L );
  806. /* Get visible window on desktop; helps taskman find it */
  807. SetFileName(NULL);
  808. ShowWindow(hwndNP, cmdShow);
  809. SetCursor(hStdCursor);
  810. /* Scan for initial /A or /W to override automatic file typing for
  811. * 'notepad /p file' or 'notepad file'
  812. */
  813. lpCmdLine= SkipBlanks( lpCmdLine );
  814. g_cpDefault = CP_AUTO;
  815. if (!lstrncmpi(TEXT("/A"), lpCmdLine))
  816. {
  817. g_cpDefault = g_cpANSI;
  818. lpCmdLine = SkipBlanks(lpCmdLine+2);
  819. }
  820. //
  821. // user provided codepage
  822. // In standard C format (1234 (decimal), x123 (hex), 010 (octal)
  823. // if 0, then use ANSI codepage
  824. // if 1, then use OEM codepage
  825. else if (!lstrncmpi(TEXT("/CP:"), lpCmdLine))
  826. {
  827. BOOL fValid;
  828. // scan off the code page. Base==0 means the syntax determines the base
  829. // "10" == 10, "x10" == 16, "010" == 8
  830. g_cpDefault = wcstoul(lpCmdLine+4, &lpCmdLine, 0);
  831. if ((*lpCmdLine != TEXT('\0')) && (*lpCmdLine != TEXT(' ')) && (*lpCmdLine != TEXT('\t')))
  832. {
  833. fValid = FALSE;
  834. }
  835. else
  836. {
  837. if (g_cpDefault == CP_ACP)
  838. {
  839. g_cpDefault = GetACP();
  840. }
  841. else if (g_cpDefault == CP_OEMCP)
  842. {
  843. g_cpDefault = GetOEMCP();
  844. }
  845. fValid = FValidateCodepage(hwndNP, g_cpDefault);
  846. }
  847. if (!fValid)
  848. {
  849. AlertBox(hwndNP, szNN, szInvalidCP, NULL, MB_APPLMODAL | MB_OK | MB_ICONERROR);
  850. return FALSE;
  851. }
  852. lpCmdLine = SkipBlanks(lpCmdLine);
  853. }
  854. else if (!lstrncmpi(TEXT("/E:"), lpCmdLine))
  855. {
  856. const TCHAR *rgchEncoding = lpCmdLine = lpCmdLine+3;
  857. while ((*lpCmdLine != TEXT('\0')) && (*lpCmdLine != TEXT(' ')) && (*lpCmdLine != TEXT('\t')))
  858. {
  859. lpCmdLine++;
  860. }
  861. if (!FLookupCodepageNameW(rgchEncoding, (UINT) (lpCmdLine - rgchEncoding), &g_cpDefault))
  862. {
  863. AlertBox(hwndNP, szNN, szInvalidIANA, NULL, MB_APPLMODAL | MB_OK | MB_ICONERROR);
  864. return FALSE;
  865. }
  866. if (!FValidateCodepage(hwndNP, g_cpDefault))
  867. {
  868. AlertBox(hwndNP, szNN, szInvalidCP, NULL, MB_APPLMODAL | MB_OK | MB_ICONERROR);
  869. return FALSE;
  870. }
  871. lpCmdLine = SkipBlanks(lpCmdLine);
  872. }
  873. else if (!lstrncmpi(TEXT("/W"), lpCmdLine))
  874. {
  875. g_cpDefault = CP_UTF16;
  876. lpCmdLine = SkipBlanks(lpCmdLine+2);
  877. }
  878. if (!lstrncmpi(TEXT("/SELECTENCODING"), lpCmdLine))
  879. {
  880. g_fSelectEncoding = TRUE;
  881. lpCmdLine = SkipBlanks(lpCmdLine+15);
  882. }
  883. // Set encoding of new document or if LoadFile fails
  884. g_cpOpened = g_cpDefault;
  885. if (g_cpOpened == CP_AUTO)
  886. {
  887. g_cpOpened = g_cpANSI;
  888. }
  889. g_wbOpened = wbDefault;
  890. /* check for /.SETUP option first.
  891. if /.SETUP absent, check for SHELL options /P
  892. Whenever a SHELL option is processed, post a WM_CLOSE msg.
  893. */
  894. iSta= ProcessSetupOption( lpCmdLine );
  895. if( iSta )
  896. {
  897. if( iSta == IDCANCEL )
  898. {
  899. return( FALSE );
  900. }
  901. }
  902. else if( ProcessShellOptions( lpCmdLine, cmdShow ) )
  903. {
  904. PostMessage( hwndNP, WM_CLOSE, 0, 0L );
  905. return TRUE;
  906. }
  907. else if( *lpCmdLine )
  908. {
  909. TCHAR szFile[MAX_PATH];
  910. /* Get the filename. */
  911. GetFileName(szFile, lpCmdLine);
  912. fp = CreateFile(szFile, // filename
  913. GENERIC_READ, // access mode
  914. FILE_SHARE_READ|FILE_SHARE_WRITE, // share mode
  915. NULL, // security descriptor
  916. OPEN_EXISTING, // how to create
  917. FILE_ATTRIBUTE_NORMAL, // file attributes
  918. NULL); // hnd of file attrs to copy
  919. if( fp == INVALID_HANDLE_VALUE )
  920. {
  921. // If the file can't be opened, maybe the user wants a new
  922. // one created.
  923. if( GetLastError() == ERROR_FILE_NOT_FOUND )
  924. {
  925. INT AlertStatus;
  926. AlertStatus= AlertBox( hwndNP, szNN, szFNF, szFile,
  927. MB_APPLMODAL | MB_YESNOCANCEL | MB_ICONWARNING);
  928. if( AlertStatus == IDCANCEL )
  929. {
  930. return( FALSE );
  931. }
  932. if( AlertStatus == IDYES )
  933. {
  934. fp = CreateFile(szFile, // filename
  935. GENERIC_READ|GENERIC_WRITE, // access
  936. FILE_SHARE_READ|FILE_SHARE_WRITE, // share
  937. NULL, // security descrp
  938. OPEN_ALWAYS, // how to create
  939. FILE_ATTRIBUTE_NORMAL, // file attributes
  940. NULL); // hnd of file attrs
  941. }
  942. }
  943. else
  944. {
  945. AlertUser_FileFail(szFile);
  946. }
  947. }
  948. if (fp != INVALID_HANDLE_VALUE)
  949. {
  950. LoadFile(szFile, g_fSelectEncoding); // get file specified on command line
  951. }
  952. }
  953. CreateFilter(TRUE, szOpenFilterSpec);
  954. CreateFilter(FALSE, szSaveFilterSpec);
  955. /* init. some fields of the OPENFILENAME struct used by fileopen and
  956. * filesaveas, but NEVER changed.
  957. */
  958. memset( &OFN, 0, sizeof(OFN) );
  959. OFN.lStructSize = sizeof(OPENFILENAME);
  960. OFN.hwndOwner = hwndNP;
  961. OFN.nMaxFile = MAX_PATH;
  962. OFN.hInstance = hInstance;
  963. /* init.fields of the FINDREPLACE struct used by FindText() */
  964. memset( &FR, 0, sizeof(FR) );
  965. FR.lStructSize = sizeof(FINDREPLACE); /* Don't hard code it */
  966. FR.hwndOwner = hwndNP;
  967. /* Force a scroll to current selection (which could be at eof if
  968. we loaded a log file.) */
  969. {
  970. DWORD dwStart, dwEnd;
  971. SendMessage( hwndEdit, EM_GETSEL, (WPARAM)&dwStart, (LPARAM)&dwEnd );
  972. SendMessage( hwndEdit, EM_SETSEL, dwStart, dwEnd );
  973. SendMessage( hwndEdit, EM_SCROLLCARET, 0, 0 );
  974. }
  975. langid = LOWORD((DWORD) (INT_PTR) GetKeyboardLayout(0));
  976. GetKeyboardCodepages(langid);
  977. if (PRIMARYLANGID(langid) == LANG_JAPANESE) {
  978. /*
  979. * If current HKL is Japanese, handle the result string at once.
  980. */
  981. SendMessage(hwndEdit, EM_SETIMESTATUS,
  982. EMSIS_COMPOSITIONSTRING, EIMES_GETCOMPSTRATONCE);
  983. }
  984. return TRUE;
  985. }
  986. /* ** Notepad class registration proc */
  987. BOOL NPRegister (HANDLE hInstance)
  988. {
  989. WNDCLASSEX NPClass;
  990. PWNDCLASSEX pNPClass = &NPClass;
  991. /* Bug 12191: If Pen Windows is running, make the background cursor an
  992. * arrow instead of the edit control ibeam. This way the user will know
  993. * where they can use the pen for writing vs. what will be considered a
  994. * mouse action. 18 October 1991 Clark Cyr
  995. */
  996. pNPClass->cbSize = sizeof(NPClass);
  997. pNPClass->hCursor = LoadCursor(NULL, GetSystemMetrics(SM_PENWINDOWS)
  998. ? IDC_ARROW : IDC_IBEAM);
  999. pNPClass->hIcon = LoadIcon(hInstance,
  1000. (LPTSTR) MAKEINTRESOURCE(ID_ICON));
  1001. pNPClass->hIconSm = LoadImage(hInstance,
  1002. MAKEINTRESOURCE(ID_ICON),
  1003. IMAGE_ICON, 16, 16,
  1004. LR_DEFAULTCOLOR);
  1005. pNPClass->lpszMenuName = (LPTSTR) MAKEINTRESOURCE(ID_MENUBAR);
  1006. pNPClass->hInstance = hInstance;
  1007. pNPClass->lpszClassName = szNotepad;
  1008. pNPClass->lpfnWndProc = NPWndProc;
  1009. pNPClass->hbrBackground = (HBRUSH)(COLOR_WINDOW+1);
  1010. pNPClass->style = 0; // was CS_BYTEALIGNCLIENT (obsolete)
  1011. pNPClass->cbClsExtra = 0;
  1012. pNPClass->cbWndExtra = 0;
  1013. if (!RegisterClassEx((LPWNDCLASSEX)pNPClass))
  1014. return (FALSE);
  1015. return (TRUE);
  1016. }
  1017. /* Get Locale info from the Registry, and initialize global vars */
  1018. void InitLocale(void)
  1019. {
  1020. GetUserLocaleCodepages();
  1021. }