Team Fortress 2 Source Code as on 22/4/2020
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.

703 lines
19 KiB

  1. //========= Copyright Valve Corporation, All rights reserved. ============//
  2. //
  3. //=============================================================================
  4. // Valve includes
  5. #include "filesystem.h"
  6. #include "itemtest/itemtest.h"
  7. #include "tier0/icommandline.h"
  8. #include "tier2/p4helpers.h"
  9. // Local includes
  10. #include "itemtestapp.h"
  11. // Last include
  12. #include <tier0/memdbgon.h>
  13. //-----------------------------------------------------------------------------
  14. //
  15. //-----------------------------------------------------------------------------
  16. char CItemTestApp::s_szName[] = "itemtest";
  17. char CItemTestApp::s_szDesc[] =
  18. "itemtest is a command line utility to assist with packaging data "
  19. "intended to be submitted to Valve.";
  20. char *CItemTestApp::s_pszFlags[][4] = {
  21. { "-h", "-help", NULL, "Print this information." },
  22. { "-s", "-steamid", NULL, "Print the itemtest steam id for the current user or \"<unknown>\" and exit" },
  23. { "-b", "-batch", NULL, "Run in batch mode, i.e. no GUI, all parameters must be specified on the command line." },
  24. { "-c", "-class", "<class>", "Specify the class of the item. One of: demo, engineer, heavy, medic, pyro, scout, sniper, soldier, spy" },
  25. { "-n", "-name", "<name>", "Specify the name of the item" },
  26. { "-d", "-dev", NULL, "Turn on dev mode" },
  27. { "-nop4", "-nop4", NULL, "If -dev mode is specified optionally turn off perforce. NOTE: Perforce is only enabled in dev mode." },
  28. { "-as", "-autoskin", NULL, "Turn on auto skinning of the geometry to bip_head." },
  29. { "-l", "-lod", "<file>", "Specify the LOD, can be specified multiple times, first is LOD0, 2nd is LOD1, etc.." },
  30. { "-lm", "-listmats", NULL, "If some lod files are specified and this option is specified, the names of the materials found in the LOD files are printed to stdout and the program exits, all texture flags are ignored. The material names are the arguments needed to -mat" },
  31. { "-m", "-mat", "<name>", "Specify a material. <name> is the name of the material from the geometry file" },
  32. { "-mt", "-mattype", "<type>", "Category of previously specified material, one of: primary, secondary, duplicate_primary, duplicate_secondary" },
  33. { "-t", "-tex", "<file>", "Specify a texture to use with the previously specified material" },
  34. { "-tt", "-textype", "<type>", "Category of previously specified texture, one of: common, red, blue, normal" },
  35. { "-at", "-alphatype", "<type>", "Category of alpha data of previously specified texture, one of: none, transparency, paintable, spec" },
  36. { "-v", "-view", NULL, "Run hlmv on the compiled model if successful" },
  37. { "-ex", "-explore", NULL, "Open explorer window on the compiled zip if successful" },
  38. { "-o", "-output", "<file>", "Save output to a specific file" }
  39. };
  40. //-----------------------------------------------------------------------------
  41. //
  42. //-----------------------------------------------------------------------------
  43. bool CItemTestApp::PreInit()
  44. {
  45. // This just has to go in the right scope so it can access kFlagsCount
  46. COMPILE_TIME_ASSERT( kFlagsCount == ARRAYSIZE( s_pszFlags ) );
  47. if ( !BaseClass::PreInit() )
  48. return false;
  49. MathLib_Init();
  50. // Set Dev mode appropriately
  51. DoDevMode();
  52. CUtlString sSourceSDKPath, sSourceSDKBin;
  53. {
  54. CUtlString sSteamAppInstallLocation;
  55. // See if we have to do special initialization because TF & the SourceSDK are configured oddly
  56. // GetSourceSDKFromExe() will fail if it's not that specific configuration and so normal
  57. // initialization will proceed in that case
  58. // TODO: These are specific values for TF but hopefully this code will only be needed for TF & SourceSDK
  59. const char *pszMod = "tf";
  60. const int nAppId = 440;
  61. if ( CItemUpload::GetSourceSDKFromExe( sSourceSDKPath, sSourceSDKBin ) && CItemUpload::GetSteamAppInstallLocation( sSteamAppInstallLocation, nAppId ) )
  62. {
  63. char szGameDir[ MAX_PATH ] = "";
  64. V_ComposeFileName( sSteamAppInstallLocation.String(), pszMod, szGameDir, ARRAYSIZE( szGameDir ) );
  65. if ( !SetupSearchPaths( szGameDir, true, true ) )
  66. {
  67. return false;
  68. }
  69. }
  70. else if ( !SetupSearchPaths( NULL, false, true ) )
  71. {
  72. return false;
  73. }
  74. }
  75. const char *pszGameInfoPath = GetGameInfoPath();
  76. char szGameInfoParent[ MAX_PATH ] = "";
  77. V_ExtractFilePath( pszGameInfoPath, szGameInfoParent, ARRAYSIZE( szGameInfoParent ) );
  78. char szPlatformDir[ MAX_PATH ] = "";
  79. V_ComposeFileName( szGameInfoParent, "platform", szPlatformDir, ARRAYSIZE( szPlatformDir ) );
  80. g_pFullFileSystem->AddSearchPath( szPlatformDir, "PLATFORM" );
  81. if ( !sSourceSDKPath.IsEmpty() )
  82. {
  83. V_ComposeFileName( sSourceSDKPath.String(), "platform", szPlatformDir, ARRAYSIZE( szPlatformDir ) );
  84. g_pFullFileSystem->AddSearchPath( szPlatformDir, "PLATFORM" );
  85. }
  86. // This bit of hackery allows us to access files on the harddrive
  87. g_pFullFileSystem->AddSearchPath( "", "LOCAL", PATH_ADD_TO_HEAD );
  88. CreateInterfaceFn factory = GetFactory();
  89. if ( !ConnectDataModel( factory ) )
  90. return false;
  91. const InitReturnVal_t nRetVal = InitDataModel();
  92. #ifdef _DEBUG
  93. {
  94. g_pFullFileSystem->PrintSearchPaths();
  95. Msg( "// itemtest paths:\n" );
  96. CUtlString sTmp;
  97. if ( CItemUpload::GetVProjectDir( sTmp ) )
  98. {
  99. Msg( "// VProject: %s\n", sTmp.String() );
  100. }
  101. if ( CItemUpload::GetVMod( sTmp ) )
  102. {
  103. Msg( "// Mod: %s\n", sTmp.String() );
  104. }
  105. if ( CItemUpload::GetContentDir( sTmp ) )
  106. {
  107. Msg( "// Content: %s\n", sTmp.String() );
  108. }
  109. if ( CItemUpload::GetBinDirectory( sTmp ) )
  110. {
  111. Msg( "// Bin: %s\n", sTmp.String() );
  112. }
  113. }
  114. #endif // _DEBUG
  115. return ( nRetVal == INIT_OK );
  116. }
  117. //-----------------------------------------------------------------------------
  118. //
  119. //-----------------------------------------------------------------------------
  120. void CItemTestApp::PostShutdown()
  121. {
  122. ShutdownDataModel();
  123. DisconnectDataModel();
  124. BaseClass::PostShutdown();
  125. }
  126. //-----------------------------------------------------------------------------
  127. //
  128. //-----------------------------------------------------------------------------
  129. void CItemTestApp::DoDevMode()
  130. {
  131. if ( FindParam( kDev ) )
  132. {
  133. CItemUpload::SetDevMode( true );
  134. const bool bP4DLLExists = g_pFullFileSystem->FileExists( "p4lib.dll", "EXECUTABLE_PATH" );
  135. // No p4 mode if specified on the command line or no p4lib.dll found
  136. if ( !bP4DLLExists || FindParam( kNoP4 ) )
  137. {
  138. g_p4factory->SetDummyMode( true );
  139. CItemUpload::SetP4( false );
  140. }
  141. else
  142. {
  143. CItemUpload::SetP4( true );
  144. }
  145. // Set the named changelist
  146. g_p4factory->SetOpenFileChangeList( "itemtest Auto Checkout" );
  147. }
  148. }
  149. //-----------------------------------------------------------------------------
  150. //
  151. //-----------------------------------------------------------------------------
  152. bool CItemTestApp::ProcessCommandLine( CAsset *pAsset, bool bDoListMats )
  153. {
  154. const char *pszName = ParmValue( kName );
  155. if ( pszName )
  156. {
  157. pAsset->SetName( pszName );
  158. }
  159. CAssetTF *pAssetTF = dynamic_cast< CAssetTF * >( pAsset );
  160. if ( pAssetTF )
  161. {
  162. const char *pszUserClass = ParmValue( kClass );
  163. const char *pszClass = GetClassString( pszUserClass );
  164. if ( pszClass )
  165. {
  166. pAssetTF->SetClass( pszClass );
  167. }
  168. }
  169. const char *pszOutput = ParmValue( kOutput );
  170. if ( pszOutput )
  171. {
  172. pAsset->SetArchivePath( pszOutput );
  173. }
  174. else
  175. {
  176. CUtlString sFileName;
  177. pAsset->GetName( sFileName );
  178. char pszWorkshopPath[ MAX_PATH ];
  179. if ( g_pFullFileSystem->RelativePathToFullPath( "workshop", "GAME", pszWorkshopPath, sizeof(pszWorkshopPath) ) && !sFileName.IsEmpty() )
  180. {
  181. sFileName += ".zip";
  182. V_ComposeFileName( pszWorkshopPath, sFileName, pszWorkshopPath, sizeof(pszWorkshopPath) );
  183. pAsset->SetArchivePath( pszWorkshopPath );
  184. }
  185. }
  186. pAsset->SetSkinToBipHead( FindParam( kAutoSkin ) > 0 );
  187. ICommandLine *pCmdLine = CommandLine();
  188. const int nParamCount = pCmdLine->ParmCount();
  189. for ( int i = 0; i < nParamCount; ++i )
  190. {
  191. const char *pszFlag = pCmdLine->GetParm( i );
  192. if ( !V_stricmp( pszFlag, s_pszFlags[kLod][kShortFlag] ) || !V_stricmp( pszFlag, s_pszFlags[kLod][kLongFlag] ) )
  193. {
  194. if ( i + 1 < nParamCount )
  195. {
  196. const char *pszLod = pCmdLine->GetParm( i + 1 );
  197. pAsset->AddTargetDMX( pszLod );
  198. }
  199. else
  200. {
  201. Warning( "Error! Command line switch \"%s\" specified without parameter value\n", pszFlag );
  202. }
  203. }
  204. }
  205. if ( bDoListMats )
  206. {
  207. bool bRetVal = false;
  208. if ( pAsset->TargetDMXCount() <= 0 )
  209. {
  210. Warning( "Error! %s specified but no no geometry files specified via %s\n", s_pszFlags[kListMats][kLongFlag], s_pszFlags[kLod][kLongFlag] );
  211. }
  212. else
  213. {
  214. const int nTargetVMTCount = pAsset->GetTargetVMTCount();
  215. if ( nTargetVMTCount <= 0 )
  216. {
  217. Warning( "Error! %s specified but no materials found in specified LODs\n", s_pszFlags[kListMats][kLongFlag] );
  218. }
  219. else
  220. {
  221. CUtlString sTargetVMT;
  222. for ( int i = 0; i < nTargetVMTCount; ++i )
  223. {
  224. pAsset->GetTargetVMT( i )->GetMaterialId( sTargetVMT );
  225. Msg( "Material: %s\n", sTargetVMT.String() );
  226. }
  227. bRetVal = true;
  228. }
  229. }
  230. return bRetVal;
  231. }
  232. CSmartPtr< CTargetVMT > pTargetVmt = NULL;
  233. int nTexParmIndex = -1;
  234. bool bTexNormal = false;
  235. for ( int i = 0; i < nParamCount; ++i )
  236. {
  237. const char *pszFlag = pCmdLine->GetParm( i );
  238. if ( !V_stricmp( pszFlag, s_pszFlags[kMat][kShortFlag] ) || !V_stricmp( pszFlag, s_pszFlags[kMat][kLongFlag] ) )
  239. {
  240. if ( i + 1 < nParamCount )
  241. {
  242. const char *pszMatName = pCmdLine->GetParm( i + 1 );
  243. pTargetVmt = pAsset->FindOrAddMaterial( pszMatName, CItemUpload::Manifest()->GetDefaultMaterialType() );
  244. nTexParmIndex = -1;
  245. bTexNormal = false;
  246. }
  247. else
  248. {
  249. Warning( "Error! Command line switch \"%s\" specified without parameter value\n", pszFlag );
  250. }
  251. }
  252. else if ( !V_stricmp( pszFlag, s_pszFlags[kMatType][kShortFlag] ) || !V_stricmp( pszFlag, s_pszFlags[kMatType][kLongFlag] ) )
  253. {
  254. if ( !pTargetVmt )
  255. {
  256. Warning( "Error! No -mat specified before \"%s\"\n", pszFlag );
  257. continue;
  258. }
  259. const char *pszMatType = GetParm( i + 1 );
  260. if ( !pszMatType )
  261. {
  262. Warning( "Error! Command line switch \"%s\" specified without parameter value\n", pszFlag );
  263. continue;
  264. }
  265. bool bDuplicate = false;
  266. if ( StringHasPrefix( pszMatType, "duplicate_" ) )
  267. {
  268. pszMatType += 10;
  269. bDuplicate = true;
  270. }
  271. else if ( StringHasPrefix( pszMatType, "d" ) )
  272. {
  273. pszMatType += 1;
  274. bDuplicate = true;
  275. }
  276. int nMatType = CTargetVMT::StringToMaterialType( pszMatType );
  277. if ( nMatType != kInvalidMaterialType )
  278. {
  279. if ( bDuplicate )
  280. {
  281. pTargetVmt->SetDuplicate( nMatType );
  282. }
  283. else
  284. {
  285. pTargetVmt->SetMaterialType( nMatType );
  286. }
  287. }
  288. else
  289. {
  290. Warning( "Error! Invalid Parameter Value: \"%s\" \"%s\", expected one of primary, secondary, duplicate_primary, duplicate_secondary\n", pszFlag, pszMatType );
  291. }
  292. }
  293. else if ( !V_stricmp( pszFlag, s_pszFlags[kTex][kShortFlag] ) || !V_stricmp( pszFlag, s_pszFlags[kTex][kLongFlag] ) )
  294. {
  295. if ( !pTargetVmt )
  296. {
  297. Warning( "Error! No -mat specified before \"%s\"\n", pszFlag );
  298. continue;
  299. }
  300. if ( pTargetVmt->GetDuplicate() )
  301. {
  302. Warning( "Error! Previous material specified as duplicate before \"%s\", ignoring\n", pszFlag );
  303. continue;
  304. }
  305. const char *pszTex = GetParm( i + 1 );
  306. if ( !pszTex )
  307. {
  308. Warning( "Error! Command line switch \"%s\" specified without parameter value\n", pszFlag );
  309. continue;
  310. }
  311. nTexParmIndex = i + 1;
  312. }
  313. else if ( !V_stricmp( pszFlag, s_pszFlags[kTexType][kShortFlag] ) || !V_stricmp( pszFlag, s_pszFlags[kTexType][kLongFlag] ) )
  314. {
  315. if ( !pTargetVmt )
  316. {
  317. Warning( "Error! No -mat specified before \"%s\"\n", pszFlag );
  318. continue;
  319. }
  320. if ( pTargetVmt->GetDuplicate() )
  321. {
  322. Warning( "Error! Previous material specified as duplicate before \"%s\", ignoring\n", pszFlag );
  323. continue;
  324. }
  325. const char *pszTex = GetParm( nTexParmIndex );
  326. if ( !pszTex )
  327. {
  328. Warning( "Error! No -tex specified before \"%s\"\n", pszFlag );
  329. continue;
  330. }
  331. const char *pszTexType = GetParm( i + 1 );
  332. if ( !pszTex )
  333. {
  334. Warning( "Error! Command line switch \"%s\" specified without parameter value\n", pszFlag );
  335. continue;
  336. }
  337. if ( StringHasPrefix( pszTexType, "C" ) )
  338. {
  339. pTargetVmt->SetTargetVTF( "_color", pszTex ); // Comes from texture_types in manifest
  340. }
  341. else if ( StringHasPrefix( pszTexType, "N" ) )
  342. {
  343. pTargetVmt->SetTargetVTF( "_normal", pszTex ); // Comes from texture_types in manifest
  344. bTexNormal = true;
  345. }
  346. else if ( StringHasPrefix( pszTexType, "R" ) )
  347. {
  348. pTargetVmt->SetTargetVTF( "_color", pszTex, CItemUpload::Manifest()->GetMaterialSkin( "red" ) ); // Comes from texture_types in manifest
  349. }
  350. else if ( StringHasPrefix( pszTexType, "B" ) )
  351. {
  352. pTargetVmt->SetTargetVTF( "_color", pszTex, CItemUpload::Manifest()->GetMaterialSkin( "blue" ) ); // Comes from texture_types in manifest
  353. }
  354. }
  355. else if ( !V_stricmp( pszFlag, s_pszFlags[kAlphaType][kShortFlag] ) || !V_stricmp( pszFlag, s_pszFlags[kAlphaType][kLongFlag] ) )
  356. {
  357. if ( !pTargetVmt )
  358. {
  359. Warning( "Error! No -mat specified before \"%s\"\n", pszFlag );
  360. continue;
  361. }
  362. if ( pTargetVmt->GetDuplicate() )
  363. {
  364. Warning( "Error! Previous material specified as duplicate before \"%s\", ignoring\n", pszFlag );
  365. continue;
  366. }
  367. const char *pszTex = GetParm( nTexParmIndex );
  368. if ( !pszTex )
  369. {
  370. Warning( "Error! No -tex specified before \"%s\"\n", pszFlag );
  371. continue;
  372. }
  373. const char *pszTexType = GetParm( i + 1 );
  374. if ( !pszTex )
  375. {
  376. Warning( "Error! Command line switch \"%s\" specified without parameter value\n", pszFlag );
  377. continue;
  378. }
  379. if ( StringHasPrefix( pszTexType, "N" ) )
  380. {
  381. if ( bTexNormal )
  382. {
  383. pTargetVmt->SetNormalAlphaType( CTargetVMT::kNoNormalAlpha );
  384. }
  385. else
  386. {
  387. pTargetVmt->SetColorAlphaType( CTargetVMT::kNoColorAlpha );
  388. }
  389. }
  390. else if ( StringHasPrefix( pszTexType, "T" ) )
  391. {
  392. if ( bTexNormal )
  393. {
  394. Warning( "Error! Command line switch \"%s\" \"%s\" specified after a \"normal\" texture, only applies to color textures\n", pszFlag, pszTexType );
  395. continue;
  396. }
  397. else
  398. {
  399. pTargetVmt->SetColorAlphaType( CTargetVMT::kTransparency );
  400. }
  401. }
  402. else if ( StringHasPrefix( pszTexType, "P" ) )
  403. {
  404. if ( bTexNormal )
  405. {
  406. Warning( "Error! Command line switch \"%s\" \"%s\" specified after a \"normal\" texture, only applies to color textures\n", pszFlag, pszTexType );
  407. continue;
  408. }
  409. else
  410. {
  411. pTargetVmt->SetColorAlphaType( CTargetVMT::kPaintable );
  412. }
  413. }
  414. else if ( StringHasPrefix( pszTexType, "S" ) )
  415. {
  416. if ( bTexNormal )
  417. {
  418. pTargetVmt->SetNormalAlphaType( CTargetVMT::kNormalSpecPhong );
  419. }
  420. else
  421. {
  422. pTargetVmt->SetColorAlphaType( CTargetVMT::kColorSpecPhong );
  423. }
  424. }
  425. }
  426. }
  427. return true;
  428. }
  429. //-----------------------------------------------------------------------------
  430. //
  431. //-----------------------------------------------------------------------------
  432. void CItemTestApp::PrintHelp()
  433. {
  434. // TODO: Find with of current output device
  435. static const int nLineLength = 79;
  436. Msg( "\n" );
  437. Msg( "\n" "NAME" "\n" );
  438. CUtlString sLine = " ";
  439. CUtlString sWord;
  440. sLine += s_szName;
  441. CFmtStr sFmt;
  442. CFmtStr sIndent;
  443. sFmt.sprintf( "%%%ds", sLine.Length() + 1 );
  444. sIndent.sprintf( sFmt, " " );
  445. for ( int i = 0; i < kFlagsCount; ++i )
  446. {
  447. const int nSpaceLeft = nLineLength - sLine.Length();
  448. sWord = "[";
  449. sWord += s_pszFlags[i][kShortFlag];
  450. sWord += " | ";
  451. sWord += s_pszFlags[i][kLongFlag];
  452. if ( s_pszFlags[i][kArgDesc] )
  453. {
  454. sWord += " ";
  455. sWord += s_pszFlags[i][kArgDesc];
  456. }
  457. sWord += "]";
  458. const int nWordWidth = sWord.Length();
  459. if ( nWordWidth > nSpaceLeft )
  460. {
  461. Msg( "%s\n", sLine.Get() );
  462. sLine = sIndent;
  463. }
  464. else
  465. {
  466. sLine += " ";
  467. }
  468. sLine += sWord;
  469. }
  470. if ( sLine.Length() )
  471. {
  472. Msg( "%s\n", sLine.Get() );
  473. }
  474. Msg( "\n" "DESCRIPTION" "\n" );
  475. sIndent = " ";
  476. sLine = " "; // One less space than indent to start because space gets added below
  477. CUtlVector< char *, CUtlMemory< char *, int > > outStrings;
  478. const char *pszSeparators[] = { " ", "\t", "\n", "\r", "\v", "\f" };
  479. V_SplitString2( s_szDesc, pszSeparators, ARRAYSIZE( pszSeparators ), outStrings );
  480. for ( int j = 0; j < outStrings.Count(); ++j )
  481. {
  482. const int nSpaceLeft = nLineLength - sLine.Length();
  483. const int nWordWidth = V_strlen( outStrings[j] ) + 1;
  484. if ( nWordWidth > nSpaceLeft )
  485. {
  486. Msg( "%s\n", sLine.Get() );
  487. sLine = sIndent;
  488. }
  489. else
  490. {
  491. sLine += " ";
  492. }
  493. sLine += outStrings[j];
  494. }
  495. if ( sLine.Length() )
  496. {
  497. Msg( "%s\n", sLine.Get() );
  498. }
  499. Msg( "\n" "OPTIONS" "\n" );
  500. int nLineLen[ kFlagsCount ];
  501. int nMaxLen = 0;
  502. for ( int i = 0; i < kFlagsCount; ++i )
  503. {
  504. nLineLen[i] = 3; // Space prefix
  505. nLineLen[i] += V_strlen( s_pszFlags[i][kShortFlag] ); // Short flag
  506. nLineLen[i] += 3; // " | "
  507. nLineLen[i] += V_strlen( s_pszFlags[i][kLongFlag] ); // Long flag
  508. nLineLen[i] += s_pszFlags[i][kArgDesc] ? V_strlen( s_pszFlags[i][kArgDesc] ) + 1 : 0; // Optional parameter
  509. nMaxLen = MAX( nMaxLen, nLineLen[i] );
  510. }
  511. nMaxLen += 2;
  512. char szElipsis[ BUFSIZ ];
  513. CFmtStr sFlags;
  514. for ( int i = 0; i < kFlagsCount; ++i )
  515. {
  516. int nParmsLen = nMaxLen - nLineLen[i];
  517. if ( nParmsLen % 2 == 0 )
  518. {
  519. V_snprintf( szElipsis, nParmsLen, ". . . . . . . . . . . . ." );
  520. }
  521. else
  522. {
  523. V_snprintf( szElipsis, nParmsLen, " . . . . . . . . . . . . ." );
  524. }
  525. sFmt.sprintf( " %%s | %%s%%s%%s %-s", szElipsis );
  526. sFlags.sprintf( sFmt, s_pszFlags[i][kShortFlag], s_pszFlags[i][kLongFlag], s_pszFlags[i][kArgDesc] ? " " : "", s_pszFlags[i][kArgDesc] ? s_pszFlags[i][kArgDesc] : "" );
  527. sLine = sFlags;
  528. sFmt.sprintf( "%%%ds", sLine.Length() + 1 );
  529. sIndent.sprintf( sFmt, " " );
  530. V_SplitString2( s_pszFlags[i][kFlagDesc], pszSeparators, ARRAYSIZE( pszSeparators ), outStrings );
  531. for ( int j = 0; j < outStrings.Count(); ++j )
  532. {
  533. const int nSpaceLeft = nLineLength - sLine.Length();
  534. const int nWordWidth = V_strlen( outStrings[j] ) + 1;
  535. if ( nWordWidth > nSpaceLeft )
  536. {
  537. Msg( "%s\n", sLine.Get() );
  538. sLine = sIndent;
  539. }
  540. else
  541. {
  542. sLine += " ";
  543. }
  544. sLine += outStrings[j];
  545. }
  546. if ( sLine.Length() )
  547. {
  548. Msg( "%s\n", sLine.Get() );
  549. }
  550. }
  551. Msg( "\n" );
  552. }
  553. //-----------------------------------------------------------------------------
  554. //
  555. //-----------------------------------------------------------------------------
  556. int CItemTestApp::FindParam( Flags_t nFlag )
  557. {
  558. int nRet = CommandLine()->FindParm( s_pszFlags[nFlag][kShortFlag] );
  559. if ( nRet )
  560. return nRet;
  561. return CommandLine()->FindParm( s_pszFlags[nFlag][kLongFlag] );
  562. }
  563. //-----------------------------------------------------------------------------
  564. //
  565. //-----------------------------------------------------------------------------
  566. const char *CItemTestApp::ParmValue( Flags_t nFlag )
  567. {
  568. const char *pszParmValue = CommandLine()->ParmValue( s_pszFlags[nFlag][kShortFlag] );
  569. if ( pszParmValue )
  570. return pszParmValue;
  571. return CommandLine()->ParmValue( s_pszFlags[nFlag][kLongFlag] );
  572. }
  573. //-----------------------------------------------------------------------------
  574. //
  575. //-----------------------------------------------------------------------------
  576. const char *CItemTestApp::GetParm( int nParmIndex )
  577. {
  578. if ( nParmIndex >= 0 || nParmIndex < CommandLine()->ParmCount() )
  579. return CommandLine()->GetParm( nParmIndex );
  580. return NULL;
  581. }