OFONT.cpp 37 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370
  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 : OFONT.CPP
  21. //Description : Font Object
  22. #include <string.h>
  23. #include <ALL.h>
  24. #include <IMGFUN.h>
  25. #include <OVGA.h>
  26. #include <OSTR.h>
  27. #include <OSYS.h>
  28. #include <ORES.h>
  29. #include <OINFO.h>
  30. #include <OGAME.h>
  31. #include <OMOUSE.h>
  32. #include <OTRANSL.h>
  33. #include <ONATION.h>
  34. #include <OGAME.h>
  35. #include <OHELP.h>
  36. #include <OFONT.h>
  37. //--------------------------------------------------------//
  38. // A font resource file is composed of three parts :
  39. //
  40. // one FontHeader;
  41. // one FontInfo for each character;
  42. // Bitmap data.
  43. //--------------------------------------------------------//
  44. //-------- Define struct FontHeader -------//
  45. #pragma pack(1)
  46. struct FontHeader
  47. {
  48. unsigned short max_width;
  49. unsigned short max_height;
  50. unsigned short std_height;
  51. unsigned short first_char; // ascii code of the first character
  52. unsigned short last_char; // ascii code of the last character
  53. };
  54. #pragma pack()
  55. //-------- Define struct FontInfo -------//
  56. #pragma pack(1)
  57. struct FontInfo // info for each character
  58. {
  59. char offset_y;
  60. unsigned char width;
  61. unsigned char height;
  62. long bitmap_offset; // file offset relative to bitmap data
  63. };
  64. #pragma pack()
  65. //--------- Define macro constant ------------//
  66. #define HYPER_FIELD_COLOR V_LIGHT_BLUE
  67. //--------- German character table -------//
  68. //#ifdef GERMAN
  69. //#define GERMAN_CHAR_COUNT 7
  70. // their DOS ascii characters: ü ä ß ö Ä Ü Ö
  71. //static short german_ascii_array[] = { 252, 228, 223, 246, 196, 220, 214 };
  72. //static short german_bmp_id_array[] = { 121, 100, 95, 116, 128, 151, 145 };
  73. //#endif
  74. //------- Define static member variable --------//
  75. short Font::hyper_field_count;
  76. HyperField Font::hyper_field_array[MAX_HYPER_FIELD];
  77. static int text_line_count; // used by text_width() & text_height() only
  78. //----------- Begin of function Font Constructor -------//
  79. Font::Font(char* fontName)
  80. {
  81. memset( this, 0, sizeof(Font) );
  82. if( fontName )
  83. init(fontName);
  84. }
  85. //------------- End of function Font Constructor -------//
  86. //----------- Begin of function Font Destructor -------//
  87. Font::~Font()
  88. {
  89. deinit();
  90. }
  91. //------------- End of function Font Destructor -------//
  92. //-------- Begin of function Font::init -----------//
  93. //
  94. // <char*> fontName = name of the font type.
  95. // (e.g. "STD" will load "FNT_STD.RES" )
  96. //
  97. // [int] interCharSpace = inter-character space
  98. // (default:1)
  99. //
  100. // [int] italicShift = horzontal back shifting for italic font
  101. // (default:0)
  102. //
  103. // Return : 1 - succeed;
  104. // 0 - reading palette file error
  105. //
  106. void Font::init(char* fontName, int interCharSpace, int italicShift)
  107. {
  108. if( init_flag )
  109. deinit();
  110. inter_char_space = interCharSpace;
  111. //---------- open the font file -----------//
  112. File fontFile;
  113. String str;
  114. str = DIR_RES;
  115. str += "FNT_";
  116. str += fontName;
  117. str += ".RES";
  118. fontFile.file_open(str);
  119. //-------- read in the font header ---------//
  120. FontHeader fontHeader;
  121. fontFile.file_read( &fontHeader, sizeof(FontHeader) );
  122. max_font_width = fontHeader.max_width;
  123. max_font_height = fontHeader.max_height;
  124. std_font_height = fontHeader.std_height;
  125. font_height = std_font_height; // its default is std_font_height, but can be set to max_font_height
  126. first_char = fontHeader.first_char;
  127. last_char = fontHeader.last_char;
  128. //----------- read in font info ------------//
  129. int infoArraySize = sizeof(FontInfo) * (last_char-first_char+1);
  130. font_info_array = (FontInfo*) mem_add( infoArraySize );
  131. fontFile.file_read( font_info_array, infoArraySize );
  132. //------- process italic shift --------//
  133. if( italicShift )
  134. {
  135. for( int i=0 ; i<last_char-first_char+1 ; i++ )
  136. font_info_array[i].width -= italicShift;
  137. }
  138. //---------- read in bitmap data ----------//
  139. int bitmapBufSize = fontFile.file_size() - sizeof(FontHeader) - infoArraySize;
  140. font_bitmap_buf = mem_add( bitmapBufSize);
  141. fontFile.file_read( font_bitmap_buf, bitmapBufSize );
  142. //---- get the width of the space character ----//
  143. //
  144. // since in some font, the space char is too narrow,
  145. // we use the width of 't' as space instead
  146. //
  147. //----------------------------------------------//
  148. space_width = font_info_array['t'-first_char].width;
  149. //----------------------------------------------//
  150. fontFile.file_close();
  151. init_flag = 1;
  152. }
  153. //---------- End of function Font::init ----------//
  154. //----------- Start of function Font::deinit ---------//
  155. //
  156. void Font::deinit()
  157. {
  158. if( font_info_array )
  159. {
  160. mem_del( font_info_array );
  161. font_info_array = NULL;
  162. }
  163. if( font_bitmap_buf )
  164. {
  165. mem_del( font_bitmap_buf );
  166. font_bitmap_buf = NULL;
  167. }
  168. init_flag = 0;
  169. }
  170. //------------- End of function Font::deinit ---------//
  171. //--------- Start of function Font::put ---------//
  172. //
  173. // write text with pre-inited fonts
  174. //
  175. // int x,y = location of the font
  176. // char* text = the text to be put on screen
  177. // [int] clearBack = clear background with back_color or not
  178. // (default : 0)
  179. // [int] x2 = display font up to the right border x2 and also
  180. // clear the area between the last character and right border
  181. //
  182. // Return : <int> lastX, the x coordination of the last pixel of last font
  183. //
  184. int Font::put(int x,int y,char* textPtr, char clearBack, int x2 )
  185. {
  186. err_when( x<0 || y<0 );
  187. if( !init_flag )
  188. return x;
  189. //-------- process translation ---------//
  190. short textChar;
  191. textPtr = translate.process(textPtr);
  192. //-------------------------------------//
  193. int textPtrLen = strlen(textPtr);
  194. if( x2 < 0 ) // default
  195. x2 = x+max_font_width*textPtrLen;
  196. x2 = min( x2, VGA_WIDTH-1 );
  197. if( !Vga::use_back_buf )
  198. mouse.hide_area( x, y, x2, y+font_height );
  199. int y2 = y+font_height-1;
  200. //-------------------------------------//
  201. FontInfo* fontInfo;
  202. for( int lenCount=1 ; *textPtr && lenCount<=textPtrLen ; textPtr++, lenCount++ )
  203. {
  204. textChar = *((unsigned char*)textPtr); // textChar is <unsiged char>
  205. //#ifdef GERMAN
  206. // textChar = translate_german_char(textChar);
  207. //#endif
  208. //--------------- space character ------------------//
  209. if( textChar == ' ' )
  210. {
  211. if( x+space_width > x2 )
  212. break;
  213. if( clearBack && !Vga::use_back_buf ) // copy texture from the back buffer as the background color
  214. vga.blt_buf( x, y, x+space_width-1, y+font_height-1, 0 );
  215. x += space_width;
  216. }
  217. //####### patch begin Gilbert 28/2 ########//
  218. // --------- control char: FIRST_NATION_COLOR_CODE_IN_TEXT -----------//
  219. else if( textChar >= FIRST_NATION_COLOR_CODE_IN_TEXT && textChar <= LAST_NATION_COLOR_CODE_IN_TEXT ) // display nation color bar in text
  220. {
  221. if( x2 >= 0 && x+NATION_COLOR_BAR_WIDTH-1 > x2 ) // exceed right border x2
  222. break;
  223. char colorCode = game.color_remap_array[textChar-FIRST_NATION_COLOR_CODE_IN_TEXT].main_color;
  224. nation_array.disp_nation_color(x, y+2, colorCode);
  225. x += NATION_COLOR_BAR_WIDTH;
  226. }
  227. //####### end begin Gilbert 28/2 ########//
  228. //------------- normal character ----------------//
  229. else if( textChar >= first_char && textChar <= last_char )
  230. {
  231. fontInfo = font_info_array+textChar-first_char;
  232. if( x+fontInfo->width > x2 )
  233. break;
  234. if( fontInfo->width > 0 )
  235. {
  236. if( clearBack && !Vga::use_back_buf )
  237. {
  238. if( fontInfo->offset_y > 0 ) // clear the upper space areas of the character
  239. IMGcopy( vga_front.buf_ptr(), vga_front.buf_pitch(), vga_back.buf_ptr(), vga_back.buf_pitch(),
  240. x, y, x+fontInfo->width-1, y+fontInfo->offset_y-1 );
  241. IMGjoinTrans( vga_front.buf_ptr(), vga_front.buf_pitch(),
  242. vga_back.buf_ptr(), vga_back.buf_pitch(), x, y+fontInfo->offset_y,
  243. font_bitmap_buf + fontInfo->bitmap_offset );
  244. int ty = y+fontInfo->offset_y+fontInfo->height-1;
  245. if( ty < y2 ) // clear the lower space areas of the character
  246. IMGcopy( vga_front.buf_ptr(), vga_front.buf_pitch(),
  247. vga_back.buf_ptr(), vga_back.buf_pitch(), x, ty+1, x+fontInfo->width-1, y2 );
  248. }
  249. else
  250. {
  251. IMGbltTrans( Vga::active_buf->buf_ptr(), Vga::active_buf->buf_pitch(),
  252. x, y+fontInfo->offset_y, font_bitmap_buf + fontInfo->bitmap_offset );
  253. }
  254. x += fontInfo->width; // inter-character space
  255. }
  256. }
  257. else
  258. {
  259. //------ tab or unknown character -------//
  260. if( textChar == '\t' ) // Tab
  261. x += space_width*8; // one tab = 8 space chars
  262. else
  263. x += space_width;
  264. }
  265. //--------- inter-character space ---------//
  266. if( clearBack && !Vga::use_back_buf ) // copy texture from the back buffer as the background color
  267. vga.blt_buf( x, y, x+inter_char_space-1, y+font_height-1, 0 );
  268. x+=inter_char_space;
  269. }
  270. //------ clear remaining area -------//
  271. if( clearBack && !Vga::use_back_buf ) // copy texture from the back buffer as the background color
  272. vga.blt_buf( x, y, x2, y+font_height-1, 0 );
  273. if( !Vga::use_back_buf )
  274. mouse.show_area();
  275. return x-1;
  276. }
  277. //----------- End of function Font::put ---------//
  278. //#ifdef GERMAN
  279. //--------- Start of function Font::translate_german_char ---------//
  280. //
  281. // <char> textChar = the character to be translated
  282. //
  283. //short Font::translate_german_char(short textChar)
  284. //{
  285. // for( int i=0 ; i<GERMAN_CHAR_COUNT ; i++ )
  286. // {
  287. // if( german_ascii_array[i] == textChar )
  288. // return first_char + german_bmp_id_array[i];
  289. // }
  290. // return textChar;
  291. //}
  292. //----------- End of function Font::translate_german_char ---------//
  293. //#endif
  294. //--------- Start of function Font::put_char ---------//
  295. //
  296. // <int> x, y = the position of the character
  297. // <char> textChar = the character
  298. //
  299. void Font::put_char(int x, int y, unsigned short textChar)
  300. {
  301. if( textChar >= first_char && textChar <= last_char )
  302. {
  303. FontInfo* fontInfo = font_info_array+textChar-first_char;
  304. IMGbltTrans( Vga::active_buf->buf_ptr(), Vga::active_buf->buf_pitch(),
  305. x, y + fontInfo->offset_y, font_bitmap_buf + fontInfo->bitmap_offset );
  306. }
  307. }
  308. //----------- End of function Font::put_char ---------//
  309. //--------- Start of function Font::right_put ---------//
  310. //
  311. // Display a string in right-justified format.
  312. //
  313. // <int> x, y = the right end position of displaying the string
  314. // <char*> textPtr = the character
  315. //
  316. void Font::right_put(int x, int y, char* textPtr)
  317. {
  318. int textWidth = text_width(textPtr);
  319. put( x-textWidth, y, textPtr );
  320. }
  321. //----------- End of function Font::right_put ---------//
  322. //--------- Begin of function Font::text_width ----//
  323. //
  324. // Given the textPtr string, then calculate the width (unit:pixel).
  325. //
  326. // char* textPtr = the textPtr to be put on screen
  327. // [int] textPtrLen = the length of the textPtr to be put
  328. // (default : -1, until NULL character)
  329. // [int] maxDispWidth = the maximum width can be displayed
  330. // the textPtr width cannot > maxDispWidth
  331. //
  332. // Note : static var text_line_count is used to pass value to text_height()
  333. //
  334. // Return : <int> the screen width of the textPtr display using this font
  335. //
  336. int Font::text_width(char* textPtr, int textPtrLen, int maxDispWidth)
  337. {
  338. int charWidth, x=0, lenCount, maxLen=0, wordWidth=0;
  339. short textChar;
  340. if( !init_flag )
  341. return x;
  342. textPtr = translate.process(textPtr);
  343. if( textPtrLen < 0 )
  344. textPtrLen = strlen(textPtr);
  345. text_line_count=1;
  346. //-------------------------------------//
  347. for( lenCount=1 ; *textPtr && lenCount<=textPtrLen ; textPtr++, lenCount++, x+=inter_char_space )
  348. {
  349. textChar = *((unsigned char*)textPtr);
  350. //#ifdef GERMAN
  351. // textChar = translate_german_char(textChar);
  352. //#endif
  353. //-- if the line exceed the given max width, advance to next line --//
  354. if( maxDispWidth && x > maxDispWidth )
  355. {
  356. maxLen = maxDispWidth;
  357. x = wordWidth; // the last word of the prev line wraps to next line
  358. text_line_count++;
  359. }
  360. //--- if the textPtr has more than 1 line, get the longest line ---//
  361. if( textChar == '\n' )
  362. {
  363. if( x>maxLen )
  364. maxLen=x;
  365. x=0;
  366. wordWidth=0;
  367. text_line_count++;
  368. continue; // next character
  369. }
  370. //-------- control char: FIRST_NATION_COLOR_CODE_IN_TEXT -----------//
  371. else if( textChar >= FIRST_NATION_COLOR_CODE_IN_TEXT && textChar <= LAST_NATION_COLOR_CODE_IN_TEXT ) // display nation color bar in text
  372. {
  373. x += NATION_COLOR_BAR_WIDTH;
  374. wordWidth = 0;
  375. }
  376. //--- add the width of the character to the total line width ---//
  377. else if( textChar == ' ' )
  378. {
  379. x += space_width;
  380. wordWidth = 0;
  381. }
  382. else if( textChar >= first_char && textChar <= last_char )
  383. {
  384. charWidth = font_info_array[textChar-first_char].width;
  385. x += charWidth;
  386. wordWidth += charWidth;
  387. }
  388. else
  389. {
  390. x += space_width;
  391. wordWidth += space_width;
  392. }
  393. if( maxDispWidth && wordWidth > maxDispWidth )
  394. {
  395. x -= wordWidth - maxDispWidth;
  396. wordWidth = maxDispWidth;
  397. }
  398. }
  399. //-------------------------------------------//
  400. if( maxDispWidth && x > maxDispWidth )
  401. text_line_count++;
  402. if( textPtr[-1] == '\n' ) // if last character is line feed, don't count double
  403. text_line_count--;
  404. return max(maxLen,x);
  405. }
  406. //----------- End of function Font::text_width ----//
  407. //--------- Begin of function Font::text_height ----//
  408. //
  409. // text_width() must first be called, this function use the result
  410. // from text_width() to calc the textPtr height.
  411. //
  412. // [int] lineSpace = space between lines
  413. // ( default : DEFAULT_LINE_SPACE )
  414. //
  415. // Return : <int> the screen height of the textPtr display using this font
  416. //
  417. int Font::text_height(int lineSpace)
  418. {
  419. return font_height * text_line_count +
  420. lineSpace * (text_line_count-1);
  421. }
  422. //----------- End of function Font::text_height ----//
  423. //--------- Begin of function Font::put_paragraph ------//
  424. //
  425. // Put a paragraph of textPtr on screen
  426. // Given the area of the paragraph
  427. // Automatical word wrap is available
  428. //
  429. // If the background color of the font is set, the area of the paragraph
  430. // will be filled with the background color first.
  431. //
  432. // int x1,y1,x2,y2 = area of the textPtr
  433. //
  434. // char* textPtr = the textPtr to be put on screen
  435. //
  436. // [int lineSpace] = no. of pixel space between lines
  437. // ( default : 2 )
  438. //
  439. // [int] startLine = start display at which line
  440. // ( default : 1, first line)
  441. //
  442. // [float wordPause] = time pause between words
  443. // ( default : 0 )
  444. //
  445. // [char dispFlag] = display the textPtr or not, if called by count_line(),
  446. // this would be 0.
  447. // ( default : 1 )
  448. //
  449. //-------------------------------------------------------//
  450. //
  451. // It will store resulting paramteres :
  452. //
  453. // <char*> next_text_ptr = point to the textPtr just after this paragraph
  454. // which has been put to the screen.
  455. //
  456. // <int> next_textPtr_y = the endding y position of the paragraph and which
  457. // is the y position which next paragraph can be put
  458. //
  459. // <int> line_count = the no. of lines has been displayed in current
  460. // put_paragraph() session.
  461. //
  462. // <HyperField> hyper_field_array[] = an array of hyper-textPtred field
  463. //
  464. //-------------------------------------------------------//
  465. void Font::put_paragraph(int x1, int y1, int x2, int y2, char *textPtr,
  466. int lineSpace, int startLine, char dispFlag)
  467. {
  468. if( !init_flag || y1+font_height-1 > y2 )
  469. return;
  470. textPtr = translate.process(textPtr);
  471. //--------- define vars ---------------//
  472. int x,y,wordX;
  473. int newWord;
  474. short textChar;
  475. char *wordPtr;
  476. char flag_under_line=0; // attribute control flags
  477. char flag_hyper_field=0;
  478. int under_line_x1; // parameters for drawing under line
  479. HyperField* hyper_field_ptr = hyper_field_array;
  480. FontInfo* fontInfo;
  481. //--------- initialize vars ---------------//
  482. x = x1;
  483. y = y1;
  484. wordX = x1; // the x of the start of the word
  485. wordPtr = textPtr;
  486. newWord = 0;
  487. line_count=0;
  488. hyper_field_count = 0;
  489. //---------- prepare for display font ----------//
  490. if( dispFlag )
  491. {
  492. err_when( x1>x2 || y1>y2 || x1<0 || y1<0 || x2>=VGA_WIDTH || y2>=VGA_HEIGHT );
  493. if( !Vga::use_back_buf ) // if not say word by word, turn off mouse one time, otherwise turn off mouse one word at a time
  494. mouse.hide_area( x1,y1,x2,y2 ); // if the mouse cursor is in that area, hide it
  495. }
  496. //--------- loop for displaying textPtr ----------//
  497. while(1)
  498. {
  499. //------ space appear, process the previous word ------//
  500. if ( newWord )
  501. {
  502. if( x-1 > x2 ) // it is still okay if x-1==x2 because x is the next pixel, not the last displayed pixel
  503. {
  504. if( line_count >= startLine-1 ) // startLine start from 1
  505. {
  506. y += font_height + lineSpace;
  507. if ( y + font_height - 1 > y2 ) // no further space for printing textPtr, end
  508. break;
  509. }
  510. x = x1;
  511. line_count++;
  512. }
  513. else
  514. {
  515. x = wordX;
  516. }
  517. //--------- Process current word ----------//
  518. for( ; wordPtr < textPtr && *wordPtr ; wordPtr++, x+=inter_char_space ) // wordPtr point to the current word which will be printed
  519. {
  520. textChar = *((unsigned char*)wordPtr); // textChar is <unsiged char>
  521. //#ifdef GERMAN
  522. // textChar = translate_german_char(textChar);
  523. //#endif
  524. //---------- control char: '_' -------------//
  525. if( textChar == '_' ) // e.g. _Title_, a line will be drawn under the word "Title"
  526. {
  527. if( flag_under_line ) // current '_' is the closing one, the open '_' has appeared previously
  528. {
  529. if( dispFlag && line_count >= startLine-1 ) // startLine start from 1
  530. IMGbar(Vga::active_buf->buf_ptr(), Vga::active_buf->buf_pitch(),
  531. under_line_x1, y+font_height, x, y+font_height, HYPER_FIELD_COLOR );
  532. }
  533. else
  534. under_line_x1 = x;
  535. flag_under_line = !flag_under_line;
  536. continue;
  537. }
  538. //-------- control char: '~' -----------//
  539. else if( textChar == '~' ) // e.g. ~Captial~, the word "Capital" is a hyper-textPtred field, pressing on it will link to the topic "Capital"
  540. {
  541. if( !flag_hyper_field ) // current '~' is the opening one
  542. {
  543. hyper_field_ptr->x1 = x;
  544. hyper_field_ptr->y1 = y;
  545. hyper_field_ptr->text_ptr = (wordPtr+1); // skip current '~'
  546. }
  547. else // current '~' is the closing one
  548. {
  549. hyper_field_ptr->x2 = x;
  550. hyper_field_ptr->y2 = y+font_height;
  551. hyper_field_ptr->text_len = wordPtr - hyper_field_ptr->text_ptr;
  552. hyper_field_count++;
  553. hyper_field_ptr++;
  554. err_when( hyper_field_count >= MAX_HYPER_FIELD );
  555. }
  556. flag_hyper_field = !flag_hyper_field;
  557. continue;
  558. }
  559. //-------- control char: FIRST_NATION_COLOR_CODE_IN_TEXT -----------//
  560. else if( textChar >= FIRST_NATION_COLOR_CODE_IN_TEXT && textChar <= LAST_NATION_COLOR_CODE_IN_TEXT ) // display nation color bar in text
  561. {
  562. if( x2 >= 0 && x+NATION_COLOR_BAR_WIDTH-1 > x2 ) // exceed right border x2
  563. break;
  564. char colorCode = game.color_remap_array[textChar-FIRST_NATION_COLOR_CODE_IN_TEXT].main_color;
  565. nation_array.disp_nation_color(x, y+2, colorCode);
  566. x += NATION_COLOR_BAR_WIDTH;
  567. }
  568. //--------------- space character ------------------//
  569. else if( textChar == ' ' )
  570. {
  571. if( x+space_width > x2 )
  572. break;
  573. x += space_width;
  574. }
  575. //----------- display char ------------//
  576. else if( textChar >= first_char && textChar <= last_char )
  577. {
  578. fontInfo = font_info_array+textChar-first_char;
  579. // character width = offset of next character - current offset
  580. if( x2 >= 0 && x+fontInfo->width-1 > x2 ) // exceed right border x2
  581. break;
  582. if( fontInfo->width > 0 )
  583. {
  584. if( dispFlag && line_count >= startLine-1 ) // startLine start from 1
  585. {
  586. // if( flag_hyper_field )
  587. // mainColor = HYPER_FIELD_COLOR;
  588. IMGbltTrans( Vga::active_buf->buf_ptr(), Vga::active_buf->buf_pitch(),
  589. x, y+fontInfo->offset_y, font_bitmap_buf + fontInfo->bitmap_offset );
  590. }
  591. x += fontInfo->width;
  592. }
  593. }
  594. }
  595. //--------- next line ----------------------//
  596. if( *textPtr == '\n' ) // next line
  597. {
  598. if( line_count >= startLine-1 ) // startLine start from 1
  599. {
  600. y += font_height + lineSpace;
  601. if ( y + font_height - 1 > y2 ) // no further space for printing textPtr, end
  602. break;
  603. }
  604. x = x1;
  605. textPtr++;
  606. line_count++;
  607. }
  608. if( *textPtr == NULL ) // all paragraph has been printed
  609. break;
  610. wordPtr = textPtr;
  611. wordX = x;
  612. newWord = 0;
  613. }
  614. //------------ process spacing -------------//
  615. if( *textPtr == ' ' || *textPtr == '\n' || *textPtr == NULL ) // not space
  616. newWord = 1;
  617. else
  618. {
  619. textChar = *((unsigned char*)textPtr); // textChar is <unsiged char>
  620. //#ifdef GERMAN
  621. // textChar = translate_german_char(textChar);
  622. //#endif
  623. if( textChar >= first_char && textChar <= last_char )
  624. {
  625. fontInfo = font_info_array+textChar-first_char;
  626. if( textChar >= FIRST_NATION_COLOR_CODE_IN_TEXT && textChar <= LAST_NATION_COLOR_CODE_IN_TEXT ) // display nation color bar in text
  627. x += NATION_COLOR_BAR_WIDTH;
  628. else if( textChar == ' ' )
  629. x+=space_width;
  630. else if( fontInfo->width > 0 ) // current font width
  631. x+=fontInfo->width;
  632. else
  633. x+=space_width;
  634. }
  635. else
  636. {
  637. x+=space_width;
  638. }
  639. x+=inter_char_space;
  640. }
  641. if( *textPtr && *textPtr != '\n' ) // when finished, remain as NULL for next cycle to detect
  642. textPtr++;
  643. }
  644. //------------ finish displaying ----------------//
  645. if( dispFlag )
  646. {
  647. if( !Vga::use_back_buf )
  648. mouse.show_area();
  649. }
  650. // while( *textPtr == '\n' || *textPtr == '\r' )
  651. // textPtr++;
  652. next_text_ptr = textPtr; // the current pointer in the textPtr
  653. next_text_y = y + font_height + lineSpace;
  654. line_count++;
  655. }
  656. //---------- End of function Font::put_paragraph ------//
  657. //--------- Begin of function Font::count_line ------//
  658. //
  659. // Count the no. of lines of textPtr can be displayed on the given area.
  660. //
  661. // int x1,y1,x2,y2 = area of the textPtr
  662. // char* textPtr = the textPtr to be put on screen
  663. //
  664. // <int lineSpace> = no. of pixel space between lines
  665. // ( default : 0 )
  666. //
  667. // <int& dispLines> = no. of lines can be displayed in the textPtr area
  668. // <int& totalLines> = total no. of lines of the textPtr
  669. //
  670. void Font::count_line(int x1, int y1, int x2, int y2, char *textPtr,
  671. int lineSpace , int& dispLines, int& totalLines)
  672. {
  673. dispLines =0;
  674. totalLines=0;
  675. while( *textPtr ) // if *textPtr==NULL means EOF
  676. {
  677. put_paragraph(x1, y1, x2, y2, textPtr, lineSpace, 1, 0); // last 0-means don't display the textPtr, only returning the parameters for our calculating of line counts
  678. if( !dispLines ) // only set once at the first time
  679. dispLines = line_count;
  680. totalLines += line_count;
  681. textPtr = next_text_ptr;
  682. }
  683. }
  684. //---------- End of function Font::count_line ------//
  685. //-------- Begin of function Font::d3_put --------//
  686. //
  687. // Display field description and field value
  688. //
  689. // <int> x1,y1 = the coordination of the spinner description
  690. // <char*> desStr = the spinner description
  691. //
  692. // Return : <int> lastX, the x coordination of the last pixel of last font
  693. //
  694. int Font::d3_put(int x1, int y1, char* desStr )
  695. {
  696. int marginSpace = font_height/5;
  697. int x2 = x1+text_width(desStr)+marginSpace*2-1;
  698. vga.d3_panel_up( x1, y1, x2, y1+font_height+marginSpace*2-1 );
  699. put( x1+marginSpace, y1+marginSpace, desStr);
  700. return x2;
  701. }
  702. //--------- End of function Font::d3_put ---------//
  703. //-------- Begin of function Font::d3_put --------//
  704. //
  705. // Display field description and field value.
  706. // It will display the description on the center of the panel
  707. //
  708. // <int> x1,y1 = the coordination of the panel
  709. // <int> x2,y2 =
  710. // <char*> desStr = the spinner description
  711. //
  712. void Font::d3_put(int x1, int y1, int x2, int y2, char* desStr)
  713. {
  714. int tx = x1 + ((x2-x1+1) - text_width(desStr))/2;
  715. int ty = y1 + ((y2-y1+1) - font_height)/2+1;
  716. vga.d3_panel_up( x1, y1, x2, y2);
  717. if( tx<x1+2 )
  718. tx=x1+2;
  719. put( tx, ty, desStr, 0, x2-2 );
  720. }
  721. //--------- End of function Font::d3_put ---------//
  722. //-------- Begin of function Font::center_put --------//
  723. //
  724. // Display the textPtr on the center of the given area
  725. //
  726. // <int> x1,y1 = the coordination of the panel
  727. // <int> x2,y2 =
  728. // <char*> desStr = the spinner description
  729. // [char] clearBack = clear background with back_color or not
  730. // (default : 0)
  731. //
  732. // Return : <int> lastX, the x coordination of the last pixel of last font
  733. //
  734. int Font::center_put(int x1, int y1, int x2, int y2, char* desStr, char clearBack)
  735. {
  736. int tx = x1 + ((x2-x1+1) - text_width(desStr))/2;
  737. int ty = y1 + ((y2-y1+1) - font_height)/2;
  738. if( tx<0 )
  739. tx=0;
  740. if( clearBack && !Vga::use_back_buf && tx>x1 ) // copy texture from the back buffer as the background color
  741. vga.blt_buf( x1, y1, tx-1, y2, 0 );
  742. return put( tx, ty, desStr, clearBack, x2 );
  743. }
  744. //--------- End of function Font::center_put ---------//
  745. //-------- Begin of function Font::put_field --------//
  746. //
  747. // Display field description and field value
  748. //
  749. // format - "Field : 999999" e.g. "List price : $92,232"
  750. //
  751. // <int> x1,y1 = the coordination of the spinner description
  752. // <char*> desStr = the spinner description
  753. // <int> x2 = the coordination of the spinner variable
  754. // <int> value = value
  755. //
  756. // [int] format = 1 - 1,000,000 normal, with thousand separator
  757. // 2 - $1,000,000 add dollar sign, with thousand separator
  758. // 3 - 100% percentage
  759. // (default : 1 )
  760. //
  761. void Font::put_field(int x1, int y1, char* desStr, int x2, int value, int format )
  762. {
  763. vga.d3_panel_up( x1, y1, x2, y1+font_height+3 );
  764. put( x1+2, y1+2, desStr);
  765. put( x2+4, y1+2, m.format(value,format) );
  766. }
  767. //--------- End of function Font::put_field ---------//
  768. //-------- Begin of function Font::update_field --------//
  769. //
  770. // Update the value of the field which is previously displayed by
  771. // Font::put_field()
  772. //
  773. // <int> x1,y1 = the coordination of the field variable
  774. // <int> value = value
  775. //
  776. // <int> format = 1 - 1,000,000 normal, with thousand separator
  777. // 2 - $1,000,000 add dollar sign, with thousand separator
  778. // 3 - 100% percentage
  779. // (default : 1 )
  780. //
  781. // <int> x2 = the x2 (right border) of the field
  782. //
  783. void Font::update_field(int x1, int y1, int value, int format, int x2)
  784. {
  785. if( x2<0 )
  786. x2 = x1+80;
  787. put( x1+4, y1+2, m.format(value,format), 1, x2 );
  788. }
  789. //--------- End of function Font::update_field ---------//
  790. //-------- Begin of function Font::field --------//
  791. //
  792. // Combine the function of put_field() and update_field()
  793. // depending on the refreshFlag passed
  794. //
  795. // format - "Field : 999999" e.g. "List price : $92,232"
  796. //
  797. // <int> x1,y1 = the coordination of the spinner description
  798. // <char*> desStr = the spinner description
  799. // <int> x2 = the coordination of the spinner variable
  800. // <int> value = value
  801. //
  802. // <int> format = 1 - 1,000,000 normal, with thousand separator
  803. // 2 - $1,000,000 add dollar sign, with thousand separator
  804. // 3 - 100% percentage
  805. //
  806. // <int> x2 = the x2 (right border) of the field
  807. // <int> refreshFlag = refresh flag, either INFO_REPAINT or INFO_UPDATE
  808. // [char*] helpCode = help code
  809. //
  810. void Font::field(int xDes, int y1, char* desStr, int xValue, int value,
  811. int format, int xEnd, int refreshFlag, char* helpCode)
  812. {
  813. int x2;
  814. if( refreshFlag == INFO_REPAINT )
  815. {
  816. vga.d3_panel_up( xDes, y1, xValue, y1+font_height+3 );
  817. put( xDes+2 , y1+2, desStr);
  818. x2 = put( xValue+4, y1+2, m.format(value,format) );
  819. }
  820. else
  821. {
  822. x2 = put( xValue+4, y1+2, m.format(value,format), 1, xEnd );
  823. }
  824. if( helpCode )
  825. help.set_help(xDes, y1, x2, y1+font_height+3, helpCode );
  826. }
  827. //--------- End of function Font::field ---------//
  828. //-------- Begin of function Font::put_field --------//
  829. //
  830. // Display field description and field value
  831. //
  832. // format - "Field : 999999" e.g. "List price : $92,232"
  833. //
  834. // <int> x1,y1 = the coordination of the spinner description
  835. // <char*> desStr = the spinner description
  836. // <int> x2 = the coordination of the spinner variable
  837. // <double> value = value
  838. //
  839. // [int] format = 1 - 1,000,000 normal, with thousand separator
  840. // 2 - $1,000,000 add dollar sign, with thousand separator
  841. // 3 - 100% percentage
  842. // (default : 1 )
  843. //
  844. void Font::put_field(int x1, int y1, char* desStr, int x2, double value, int format)
  845. {
  846. vga.d3_panel_up( x1, y1, x2, y1+font_height+3 );
  847. put( x1+2, y1+2, desStr);
  848. put( x2+4, y1+2, m.format(value,format) );
  849. }
  850. //--------- End of function Font::put_field ---------//
  851. //-------- Begin of function Font::update_field --------//
  852. //
  853. // Update the value of the field which is previously displayed by
  854. // Font::put_field()
  855. //
  856. // <int> x1,y1 = the coordination of the field variable
  857. // <double> value = value
  858. //
  859. // <int> format = 1 - 1,000,000 normal, with thousand separator
  860. // 2 - $1,000,000 add dollar sign, with thousand separator
  861. // 3 - 100% percentage
  862. // (default : 1 )
  863. //
  864. // <int> x2 = the x2 (right border) of the field
  865. //
  866. void Font::update_field(int x1, int y1, double value, int format, int x2)
  867. {
  868. if( x2<0 )
  869. x2 = x1+80;
  870. put( x1+4, y1+2, m.format(value,format), 1, x2 );
  871. }
  872. //--------- End of function Font::update_field ---------//
  873. //-------- Begin of function Font::field --------//
  874. //
  875. // Combine the function of put_field() and update_field()
  876. // depending on the refreshFlag passed
  877. //
  878. // format - "Field : 999999" e.g. "List price : $92,232"
  879. //
  880. // <int> x1,y1 = the coordination of the spinner description
  881. // <char*> desStr = the spinner description
  882. // <int> x2 = the coordination of the spinner variable
  883. // <double> value = value
  884. //
  885. // <int> format = 1 - 1,000,000 normal, with thousand separator
  886. // 2 - $1,000,000 add dollar sign, with thousand separator
  887. // 3 - 100% percentage
  888. //
  889. // <int> x2 = the x2 (right border) of the field
  890. // <int> refreshFlag = refresh flag, either INFO_REPAINT or INFO_UPDATE
  891. // [char*] helpCode = help code
  892. //
  893. void Font::field(int xDes, int y1, char* desStr, int xValue, double value,
  894. int format, int xEnd, int refreshFlag, char* helpCode )
  895. {
  896. int x2;
  897. if( refreshFlag == INFO_REPAINT )
  898. {
  899. vga.d3_panel_up( xDes, y1, xValue, y1+font_height+3 );
  900. put( xDes+2 , y1+2, desStr);
  901. x2 = put( xValue+4, y1+2, m.format(value,format) );
  902. }
  903. else
  904. {
  905. x2 = put( xValue+4, y1+2, m.format(value,format), 1, xEnd );
  906. }
  907. if( helpCode )
  908. help.set_help(xDes, y1, x2, y1+font_height+3, helpCode );
  909. }
  910. //--------- End of function Font::field ---------//
  911. //-------- Begin of function Font::put_field --------//
  912. //
  913. // Display field description and field value
  914. //
  915. // format - "Field : 999999" e.g. "List price : $92,232"
  916. //
  917. // <int> x1,y1 = the coordination of the spinner description
  918. // <char*> desStr = the spinner description
  919. // <int> x2 = the coordination of the spinner variable
  920. // <char*> value = value
  921. //
  922. void Font::put_field(int x1, int y1, char* desStr, int x2, char* value)
  923. {
  924. vga.d3_panel_up( x1, y1, x2, y1+font_height+3 );
  925. put( x1+2, y1+2, desStr);
  926. put( x2+4, y1+2, value);
  927. }
  928. //--------- End of function Font::put_field ---------//
  929. //-------- Begin of function Font::update_field --------//
  930. //
  931. // Update the value of the field which is previously displayed by
  932. // Font::put_field()
  933. //
  934. // <int> x1,y1 = the coordination of the field variable
  935. // <char*> value = value
  936. // <int> x2 = the x2 (right border) of the field
  937. //
  938. void Font::update_field(int x1, int y1, char* value, int x2)
  939. {
  940. if( x2<0 )
  941. x2 = x1+80;
  942. put( x1+4, y1+2, value, 1, x2 );
  943. }
  944. //--------- End of function Font::update_field ---------//
  945. //-------- Begin of function Font::field --------//
  946. //
  947. // Combine the function of put_field() and update_field()
  948. // depending on the refreshFlag passed
  949. //
  950. // format - "Field : 999999" e.g. "List price : $92,232"
  951. //
  952. // <int> x1,y1 = the coordination of the spinner description
  953. // <char*> desStr = the spinner description
  954. // <int> x2 = the coordination of the spinner variable
  955. // <char*> value = value
  956. //
  957. // <int> x3 = the x3 (right border) of the field
  958. // <int> refreshFlag = refresh flag, either INFO_REPAINT or INFO_UPDATE
  959. // [char*] helpCode = help code
  960. //
  961. void Font::field(int xDes, int y1, char* desStr, int xValue, char* value,
  962. int xEnd, int refreshFlag, char* helpCode )
  963. {
  964. int x2;
  965. if( refreshFlag == INFO_REPAINT )
  966. {
  967. vga.d3_panel_up( xDes, y1, xValue, y1+font_height+3 );
  968. put( xDes+2 , y1+2, desStr);
  969. x2 = put( xValue+4, y1+2, value );
  970. }
  971. else
  972. {
  973. x2 = put( xValue+4, y1+2, value, 1, xEnd );
  974. }
  975. if( helpCode )
  976. help.set_help(xDes, y1, x2, y1+font_height+3, helpCode );
  977. }
  978. //--------- End of function Font::field ---------//
  979. //-------- Begin of function Font::disp --------//
  980. //
  981. // Display a value and clear the background
  982. //
  983. // <int> x1,y1 = the coordination of the field variable
  984. // <int> value = value
  985. //
  986. // <int> format = 1 - 1,000,000 normal, with thousand separator
  987. // 2 - $1,000,000 add dollar sign, with thousand separator
  988. // 3 - 100% percentage
  989. // (default : 1 )
  990. //
  991. // <int> x2 = the x2 (right border) of the field
  992. //
  993. // Return : <int> lastX, the x coordination of the last pixel of last font
  994. //
  995. int Font::disp(int x1, int y1, int value, int format, int x2)
  996. {
  997. if( x2<0 )
  998. x2 = x1+80;
  999. int lastX = put( x1, y1, m.format(value,format), 1, x2 );
  1000. return lastX;
  1001. }
  1002. //--------- End of function Font::disp ---------//
  1003. //-------- Begin of function Font::disp --------//
  1004. //
  1005. // Display a value and clear the background
  1006. //
  1007. // <int> x1,y1 = the coordination of the field variable
  1008. // <double> value = value
  1009. //
  1010. // <int> format = 1 - 1,000,000 normal, with thousand separator
  1011. // 2 - $1,000,000 add dollar sign, with thousand separator
  1012. // 3 - 100% percentage
  1013. // (default : 1 )
  1014. //
  1015. // <int> x2 = the x2 (right border) of the field
  1016. //
  1017. // Return : <int> lastX, the x coordination of the last pixel of last font
  1018. //
  1019. int Font::disp(int x1, int y1, double value, int format, int x2)
  1020. {
  1021. if( x2<0 )
  1022. x2 = x1+80;
  1023. int lastX = put( x1, y1, m.format(value,format), 1, x2 );
  1024. return lastX;
  1025. }
  1026. //--------- End of function Font::disp ---------//
  1027. //-------- Begin of function Font::disp --------//
  1028. //
  1029. // Display a value and clear the background
  1030. //
  1031. // <int> x1,y1 = the coordination of the field variable
  1032. // <char*> textPtr = pointer to the textPtr
  1033. // <int> x2 = the x2 (right border) of the field
  1034. //
  1035. // Return : <int> lastX, the x coordination of the last pixel of last font
  1036. //
  1037. int Font::disp(int x1, int y1, char* textPtr, int x2)
  1038. {
  1039. if( x2<0 )
  1040. x2 = x1+80;
  1041. int lastX = put( x1, y1, textPtr, 1, x2 );
  1042. return lastX;
  1043. }
  1044. //--------- End of function Font::disp ---------//
  1045. //--------- Begin of function Font::put_char_to_buffer ---------//
  1046. void Font::put_char_to_buffer(char* dest, int destPitch, int x, int y, unsigned short textChar)
  1047. {
  1048. if( textChar >= first_char && textChar <= last_char )
  1049. {
  1050. FontInfo* fontInfo = font_info_array+textChar-first_char;
  1051. char *fontBitmap = font_bitmap_buf + fontInfo->bitmap_offset;
  1052. IMGbltTrans( dest, destPitch, x, y + fontInfo->offset_y, fontBitmap );
  1053. }
  1054. }
  1055. //--------- End of function Font::put_char_to_buffer ---------//
  1056. //--------- Begin of function Font::put_to_buffer ---------//
  1057. void Font::put_to_buffer(char* dest, int destPitch, int x1, int y1, char *text)
  1058. {
  1059. int x2 = destPitch; // width of buffer
  1060. while( *text != '\0' && x1 < x2)
  1061. {
  1062. int charSize = sizeof(unsigned char); // 1 for byte character, 2 for word character
  1063. unsigned short textChar = *(unsigned char *)text;
  1064. //#ifdef GERMAN
  1065. // textChar = translate_german_char(textChar);
  1066. //#endif
  1067. //if( // unicode or a word character )
  1068. //{
  1069. // textChar = *(unsigned short *)buffer; // unicode
  1070. // textChar = *(unsigned char *)text << 8 + *(1+(unsigned char *)text); // big-5...
  1071. // charSize = sizeof(unsigned short);
  1072. //}
  1073. // --------- advance to next character------------//
  1074. int charWidth = textChar == ' ' ? space_width :
  1075. (font_info_array+textChar-first_char)->width;
  1076. if( x1 + charWidth <= x2 )
  1077. put_char_to_buffer( dest, destPitch, x1, y1, textChar);
  1078. x1 += charWidth;
  1079. text += charSize;
  1080. }
  1081. }
  1082. //--------- End of function Font::put_to_buffer ---------//
  1083. //--------- Begin of function Font::center_put_to_buffer ---------//
  1084. void Font::center_put_to_buffer(char* dest, int destPitch, int x1, int y1, int x2, int y2, char *desStr)
  1085. {
  1086. int tx = x1 + ((x2-x1) - text_width(desStr))/2;
  1087. int ty = y1 + ((y2-y1) - font_height)/2;
  1088. if( tx<0 )
  1089. tx=0;
  1090. put_to_buffer( dest, destPitch, tx, ty, desStr);
  1091. }
  1092. //--------- End of function Font::center_put_to_buffer ---------//