OHELP.cpp 13 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577
  1. /*
  2. * Seven Kingdoms: Ancient Adversaries
  3. *
  4. * Copyright 1997,1998 Enlight Software Ltd.
  5. *
  6. * This program is free software: you can redistribute it and/or modify
  7. * it under the terms of the GNU General Public License as published by
  8. * the Free Software Foundation, either version 2 of the License, or
  9. * (at your option) any later version.
  10. *
  11. * This program is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  14. * GNU General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU General Public License
  17. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  18. *
  19. */
  20. //Filename : OHELP.CPP
  21. //Description : Object Help
  22. #include <ALL.h>
  23. #include <OSYS.h>
  24. #include <OSTR.h>
  25. #include <OVGA.h>
  26. #include <OMUSIC.h>
  27. #include <OFONT.h>
  28. #include <OINFO.h>
  29. #include <OGAME.h>
  30. #include <OUNIT.h>
  31. #include <OBOX.h>
  32. #include <OMOUSE.h>
  33. #include <OVBROWSE.h>
  34. #include <OFILETXT.h>
  35. #include <OHELP.h>
  36. //---------- Define constant -------------//
  37. #define HELP_BOX_COLOR (VGA_GRAY+5)
  38. #define HELP_INACTIVE_TIME ((float) 0.8) // when the mouse is inactive for one second, display help
  39. enum { HELP_SCR_BUF_WIDTH = 400, // 400
  40. HELP_SCR_BUF_HEIGHT = 200, // 300
  41. HELP_SCR_BUF_SIZE = HELP_SCR_BUF_WIDTH * HELP_SCR_BUF_HEIGHT };
  42. enum { MSG_LINE_SPACE = 4 };
  43. enum { X_MARGIN = 10,
  44. Y_MARGIN = 6 };
  45. enum { MSG_WIN_WIDTH = 390,
  46. MSG_HEAD_HEIGHT = 16 };
  47. //------- Begin of function Help::Help ----------//
  48. Help::Help()
  49. {
  50. memset( this, 0, sizeof(Help) );
  51. help_info_array = (HelpInfo*) mem_add( sizeof(HelpInfo) * MAX_HELP_INFO );
  52. save_scr_x1 = -1;
  53. }
  54. //------- Begin of function Help::Help ----------//
  55. //------- Begin of function Help::~Help ----------//
  56. Help::~Help()
  57. {
  58. deinit();
  59. }
  60. //------- Begin of function Help::~Help ----------//
  61. //------- Begin of function Help::init ----------//
  62. void Help::init(char* resName)
  63. {
  64. String str;
  65. str = DIR_RES;
  66. str += resName;
  67. load( str );
  68. save_scr_buf = mem_add(HELP_SCR_BUF_SIZE);
  69. }
  70. //------- Begin of function Help::init ----------//
  71. //------- Begin of function Help::deinit ----------//
  72. void Help::deinit()
  73. {
  74. if( save_scr_buf )
  75. {
  76. mem_del( save_scr_buf );
  77. save_scr_buf = NULL;
  78. }
  79. if( help_info_array )
  80. {
  81. mem_del( help_info_array );
  82. help_info_array = NULL;
  83. }
  84. if( help_text_buf )
  85. {
  86. mem_del( help_text_buf );
  87. help_text_buf = NULL;
  88. }
  89. }
  90. //------- Begin of function Help::deinit ----------//
  91. //------- Begin of function Help::load ----------//
  92. //
  93. // <char*> helpFileName = name of the help file.
  94. //
  95. void Help::load(char* helpFileName)
  96. {
  97. //------ Open the file and allocate buffer -----//
  98. FileTxt fileTxt( helpFileName );
  99. int dataSize = fileTxt.file_size();
  100. if( dataSize > help_text_buf_size )
  101. {
  102. help_text_buf = mem_resize( help_text_buf, dataSize ); // allocate a buffer larger than we need for the largest size possible
  103. help_text_buf_size = dataSize;
  104. }
  105. //-------- read in help info one by one --------//
  106. HelpInfo* iptr = help_info_array;
  107. char* textPtr = help_text_buf;
  108. int readLen, totalReadLen=0; // total length of text read into the help_text_buf
  109. int loopCount=0;
  110. char* tokenStr;
  111. help_info_count=0;
  112. while( !fileTxt.is_eof() )
  113. {
  114. err_when( loopCount++ > 10000 );
  115. tokenStr = fileTxt.get_token(0); // don't advance the pointer
  116. if( !tokenStr )
  117. break;
  118. //--------- if it's a help code ----------//
  119. if( tokenStr[0] >= 'A' && tokenStr[0] <= 'Z' )
  120. {
  121. strncpy( iptr->help_code, tokenStr, iptr->HELP_CODE_LEN );
  122. iptr->help_code[iptr->HELP_CODE_LEN] = NULL;
  123. }
  124. //------ if it's a help area position ------//
  125. else if( tokenStr[0] >= '0' && tokenStr[0] <= '9' )
  126. {
  127. iptr->area_x1 = (short) fileTxt.get_num();
  128. iptr->area_y1 = (short) fileTxt.get_num();
  129. iptr->area_x2 = (short) fileTxt.get_num();
  130. iptr->area_y2 = (short) fileTxt.get_num();
  131. }
  132. else
  133. err_here();
  134. //---------- next line -----------//
  135. fileTxt.next_line();
  136. if( fileTxt.is_eof() )
  137. break;
  138. //--------------------------------------------//
  139. // get help title
  140. //--------------------------------------------//
  141. fileTxt.read_line( iptr->help_title, iptr->HELP_TITLE_LEN );
  142. //---------------------------------------------------------//
  143. // get help description
  144. //---------------------------------------------------------//
  145. readLen = fileTxt.read_paragraph(textPtr, help_text_buf_size-totalReadLen);
  146. iptr->help_text_ptr = textPtr;
  147. iptr->help_text_len = readLen;
  148. textPtr += readLen;
  149. totalReadLen += readLen;
  150. err_when( totalReadLen>help_text_buf_size );
  151. //----------- next help block -------------//
  152. fileTxt.next_line(); // pass the page break line
  153. help_info_count++;
  154. iptr++;
  155. err_when( help_info_count >= MAX_HELP_INFO );
  156. }
  157. }
  158. //--------- End of function Help::load ----------//
  159. //---------- Begin of function Help::save_scr ---------//
  160. //
  161. // Save the specified porton of the screen
  162. //
  163. // <int> x1,y1,x2,y2 = the area of the screen
  164. //
  165. void Help::save_scr(int x1, int y1, int x2, int y2)
  166. {
  167. if( save_scr_x1 >= 0 ) // there is already a screen saved
  168. return;
  169. err_when( x1>x2 || y1>y2 || x1<0 || y1<0 || x2>=VGA_WIDTH || y2>=VGA_HEIGHT );
  170. long saveSize = (long)(x2-x1+1) * (y2-y1+1);
  171. err_when( saveSize > HELP_SCR_BUF_SIZE );
  172. save_scr_x1 = x1;
  173. save_scr_y1 = y1;
  174. save_scr_x2 = x2;
  175. save_scr_y2 = y2;
  176. mouse.hide_area( x1, y1, x2, y2 );
  177. vga_front.read_bitmap( x1, y1, x2, y2, save_scr_buf );
  178. mouse.show_area();
  179. }
  180. //------------ End of function Help::save_scr ---------//
  181. //----------- Begin of function Help::rest_scr --------//
  182. //
  183. // Restore previously saved screen
  184. //
  185. void Help::rest_scr()
  186. {
  187. if( save_scr_x1 < 0 ) // already restored, or not saved yet
  188. return;
  189. err_when( save_scr_x1>save_scr_x2 || save_scr_y1>save_scr_y2 ||
  190. save_scr_x1<0 || save_scr_y1<0 || save_scr_x2>=VGA_WIDTH || save_scr_y2>=VGA_HEIGHT );
  191. // mouse.hide_area( save_scr_x1, save_scr_y1, save_scr_x2, save_scr_y2 );
  192. vga_front.put_bitmap( save_scr_x1, save_scr_y1, save_scr_buf );
  193. sys.blt_virtual_buf();
  194. // mouse.show_area();
  195. mouse.show();
  196. save_scr_x1 = -1; // state that it has been restored.
  197. }
  198. //------------ End of function Help::rest_scr ----------//
  199. //----------- Begin of function Help::disp --------//
  200. //
  201. // Display help message on the given screen location.
  202. //
  203. void Help::disp()
  204. {
  205. //---- first check if we should disp the help now ------//
  206. if( !should_disp() )
  207. {
  208. help_code[0] = NULL; // reset it everytime after displaying, if the mouse is still on the button, help_code will be set again.
  209. custom_help_title[0] = NULL;
  210. return;
  211. }
  212. //-------- button help ---------//
  213. if( help_code[0] )
  214. {
  215. //--------- locate the help and display it ----------//
  216. int i;
  217. HelpInfo* helpInfo = help_info_array;
  218. for( i=0 ; i<help_info_count ; i++, helpInfo++ )
  219. {
  220. if( helpInfo->help_code[0] == help_code[0] &&
  221. strcmp( helpInfo->help_code, help_code )==0 )
  222. {
  223. disp_help( help_x, help_y,
  224. helpInfo->help_title, helpInfo->help_text_ptr );
  225. break;
  226. }
  227. }
  228. help_code[0] = NULL; // reset it everytime after displaying, if the mouse is still on the button, help_code will be set again.
  229. }
  230. //-------- custom help ---------//
  231. else if( custom_help_title[0] )
  232. {
  233. disp_help(help_x, help_y, custom_help_title, custom_help_detail);
  234. custom_help_title[0] = NULL;
  235. }
  236. //-------- other interface help ---------//
  237. else
  238. {
  239. //--------- locate the help and display it ----------//
  240. int i;
  241. HelpInfo* helpInfo = help_info_array;
  242. int spotX = mouse.cur_x;
  243. int spotY = mouse.cur_y;
  244. for( i=0 ; i<help_info_count ; i++, helpInfo++ )
  245. {
  246. if( spotX >= helpInfo->area_x1 && spotY >= helpInfo->area_y1 &&
  247. spotX <= helpInfo->area_x2 && spotY <= helpInfo->area_y2 )
  248. {
  249. disp_help( (helpInfo->area_x1+helpInfo->area_x2)/2,
  250. (helpInfo->area_y1+helpInfo->area_y2)/2,
  251. helpInfo->help_title, helpInfo->help_text_ptr );
  252. break;
  253. }
  254. }
  255. }
  256. }
  257. //------------ End of function Help::disp ----------//
  258. //---------- Begin of function Help::disp_help ----------//
  259. //
  260. // <int> centerX, centerY - the center position of the help area.
  261. // <char*> helpTitle - title of the help
  262. // [char*] helpDetail - detail of the help.
  263. //
  264. void Help::disp_help(int centerX, int centerY, char* helpTitle, char* helpDetail)
  265. {
  266. if( config.help_mode == NO_HELP )
  267. return;
  268. mouse.hide();
  269. //------ calculate the position of the help box ------//
  270. int winWidth, winHeight, dispHelpDetail=0;
  271. if( helpDetail && helpDetail[0] && // with detailed help
  272. config.help_mode == DETAIL_HELP ) // Detailed Help
  273. {
  274. winWidth = font_san.text_width(helpDetail, -1, MSG_WIN_WIDTH-X_MARGIN*2) + X_MARGIN*2;
  275. winHeight = Y_MARGIN*2 + font_san.height() + 8 + font_san.text_height(MSG_LINE_SPACE); // text_width() must be called before calling text_height()
  276. dispHelpDetail = 1;
  277. }
  278. else // Help title only
  279. {
  280. winWidth = font_san.text_width(helpTitle, -1, MSG_WIN_WIDTH-X_MARGIN*2) + X_MARGIN*2;
  281. winHeight = Y_MARGIN*2 + font_san.height();
  282. }
  283. //--- if the text is bigger than one text box can hold, use a scrollable text box ---//
  284. int x1, y1, x2, y2;
  285. if( winWidth * winHeight > HELP_SCR_BUF_SIZE )
  286. {
  287. x1 = max( 2, centerX - HELP_SCR_BUF_WIDTH / 2 );
  288. y1 = max( 2, centerY - HELP_SCR_BUF_HEIGHT / 2 );
  289. x2 = x1 + HELP_SCR_BUF_WIDTH - 1;
  290. y2 = y1 + HELP_SCR_BUF_HEIGHT - 1;
  291. }
  292. else
  293. {
  294. x1 = max( 2, centerX - winWidth / 2 );
  295. y1 = max( 2, centerY - winHeight / 2 );
  296. x2 = x1 + winWidth - 1;
  297. y2 = y1 + winHeight - 1;
  298. }
  299. if( x2 >= VGA_WIDTH )
  300. {
  301. x2 = VGA_WIDTH-10;
  302. x1 = x2-winWidth+1;
  303. }
  304. if( y2 >= VGA_HEIGHT )
  305. {
  306. y2 = VGA_HEIGHT-3;
  307. y1 = y2-winHeight+1;
  308. }
  309. //------------- save the area --------------//
  310. help.save_scr( x1, y1, x2, y2 ); // save the screen to the private buffer in Help
  311. //------- Draw box (and arrow if specified object) ------//
  312. vga_front.bar( x1, y1, x2, y2, V_WHITE );
  313. vga_front.bar( x1, y1, x2, y1+1, HELP_BOX_COLOR ); // Top border
  314. vga_front.bar( x1, y2-1, x2, y2, HELP_BOX_COLOR ); // Bottom border
  315. vga_front.bar( x1, y1, x1+1, y2, HELP_BOX_COLOR ); // Left border
  316. vga_front.bar( x2-1, y1, x2, y2, HELP_BOX_COLOR ); // Right border
  317. //--------- disp help detail -----------//
  318. font_san.put( x1+X_MARGIN, y1+Y_MARGIN, helpTitle );
  319. if( dispHelpDetail )
  320. {
  321. int y = y1 + Y_MARGIN + font_san.height() + 4;
  322. vga_front.bar( x1, y, x2, y+1, HELP_BOX_COLOR ); // line between description and help text
  323. font_san.put_paragraph( x1+X_MARGIN, y+4, x2-X_MARGIN, y2-Y_MARGIN, helpDetail, MSG_LINE_SPACE );
  324. }
  325. if( sys.debug_session )
  326. sys.blt_virtual_buf();
  327. //--- in a single player game, pause the game when a help message is disp_helplayed ---//
  328. while( help.should_disp() )
  329. {
  330. sys.yield();
  331. music.yield();
  332. mouse.get_event();
  333. }
  334. help.rest_scr();
  335. }
  336. //--------- End of function Help::disp_help ----------//
  337. //--------- Begin of function Help::should_disp --------//
  338. //
  339. int Help::should_disp()
  340. {
  341. if( config.help_mode == NO_HELP )
  342. return 0;
  343. if( VBrowse::press_record )
  344. return 0;
  345. if( last_mouse_x==mouse.cur_x && last_mouse_y==mouse.cur_y &&
  346. !mouse.left_press && !mouse.right_press && !mouse.any_click(2) )
  347. {
  348. if( m.get_time() >= mouse_still_time + HELP_INACTIVE_TIME * 1000 )
  349. {
  350. return 1;
  351. }
  352. }
  353. else
  354. {
  355. last_mouse_x = mouse.cur_x;
  356. last_mouse_y = mouse.cur_y;
  357. mouse_still_time = m.get_time();
  358. }
  359. return 0;
  360. }
  361. //---------- End of function Help::should_disp ---------//
  362. //--------- Begin of function Help::set_help --------//
  363. //
  364. void Help::set_help(int x1, int y1, int x2, int y2, char* helpCode)
  365. {
  366. err_when( strlen(helpCode) > 8 );
  367. if( !mouse.in_area(x1, y1, x2, y2) )
  368. return;
  369. strcpy( help_code, helpCode );
  370. help_x = (x1+x2)/2;
  371. help_y = (y1+y2)/2;
  372. }
  373. //---------- End of function Help::set_help ---------//
  374. //--------- Begin of function Help::set_unit_help --------//
  375. //
  376. void Help::set_unit_help(int unitId, int rankId, int x1, int y1, int x2, int y2)
  377. {
  378. if( !mouse.in_area(x1, y1, x2, y2) )
  379. return;
  380. //-------- compose the help string --------//
  381. static String str;
  382. #if(defined(SPANISH) || defined(FRENCH))
  383. str = "";
  384. if( rankId==RANK_KING )
  385. str = translate.process("King ");
  386. else if( rankId==RANK_GENERAL )
  387. str = translate.process("General ");
  388. str += unit_res[unitId]->name;
  389. #else
  390. str = unit_res[unitId]->name;
  391. #if( !defined(GERMAN) && !defined(FRENCH) && !defined(SPANISH) ) // english
  392. if( rankId>=RANK_GENERAL && unitId==UNIT_MAYA )
  393. str += "n"; // "Mayan"
  394. #endif
  395. if( rankId==RANK_KING )
  396. {
  397. str += " ";
  398. str += translate.process( "King" );
  399. }
  400. else if( rankId==RANK_GENERAL )
  401. {
  402. str += " ";
  403. str += translate.process( "General" );
  404. }
  405. #endif
  406. set_custom_help( x1, y1, x2, y2, str );
  407. }
  408. //---------- End of function Help::set_unit_help ---------//
  409. //--------- Begin of function Help::set_custom_help --------//
  410. //
  411. // <int> x1, y1, x2, y2 - the coordination of the help
  412. // <char*> helpTitle - the title of the help
  413. // [char*] helpDetail - the detailed text of the help
  414. //
  415. void Help::set_custom_help(int x1, int y1, int x2, int y2, char* helpTitle, char* helpDetail)
  416. {
  417. if( !mouse.in_area(x1, y1, x2, y2) )
  418. return;
  419. help_x = (x1+x2)/2;
  420. help_y = (y1+y2)/2;
  421. strncpy( custom_help_title, helpTitle, CUSTOM_HELP_TITLE_LEN );
  422. custom_help_title[CUSTOM_HELP_TITLE_LEN] = NULL;
  423. if( helpDetail )
  424. {
  425. strncpy( custom_help_detail, helpDetail, CUSTOM_HELP_DETAIL_LEN );
  426. custom_help_detail[CUSTOM_HELP_DETAIL_LEN] = NULL;
  427. }
  428. else
  429. {
  430. custom_help_detail[0] = NULL;
  431. }
  432. }
  433. //---------- End of function Help::set_custom_help ---------//