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 
21 //Filename    : OR_NAT.CPP
22 //Description : Nation Report
23 
24 #include <stdlib.h>
25 #include <KEY.h>
26 #include <OCONFIG.h>
27 #include <OVGA.h>
28 #include <vga_util.h>
29 #include <OFONT.h>
30 #include <OSTR.h>
31 #include <OGETA.h>
32 #include <ODATE.h>
33 #include <OMOUSE.h>
34 #include <OIMGRES.h>
35 #include <OVBROWIF.h>
36 #include <OBUTTON.h>
37 #include <OSYS.h>
38 #include <ONATION.h>
39 #include <OTALKRES.h>
40 #include <OINFO.h>
41 #include <OREMOTE.h>
42 #include <locale.h>
43 #include "gettext.h"
44 
45 //------------- Define coordinations -----------//
46 
47 enum { REPORT_BROWSE_X1 = ZOOM_X1+6,
48 		 REPORT_BROWSE_Y1 = ZOOM_Y1+6,
49 		 REPORT_BROWSE_X2 = ZOOM_X2-6,
50 		 REPORT_BROWSE_Y2 = REPORT_BROWSE_Y1+206,
51 
52 		 REPORT_BUTTON_X1 = ZOOM_X1+8,
53 		 REPORT_BUTTON_Y1 = REPORT_BROWSE_Y2+6,
54 		 REPORT_BUTTON_WIDTH = 135,
55 		 REPORT_BUTTON_Y2 = REPORT_BUTTON_Y1+20,
56 		 REPORT_BUTTON_X_SPACE = 130,
57 
58 		 REPORT_DET_X1 = ZOOM_X1+6,
59 		 REPORT_DET_Y1 = REPORT_BUTTON_Y2+4,
60 		 REPORT_DET_X2 = ZOOM_X2-6,
61 		 REPORT_DET_Y2 = ZOOM_Y2-6,
62 		 REPORT_TALK_Y2 = ZOOM_Y2-86,		// use a shorter height for the diplomacy menu as it needs to let the player looks at the messages received.
63 	 };
64 
65 //---------- Define report mode strings ---------//
66 
67 static const char* report_mode_str_array[MAX_NATION_REPORT_MODE] =
68 {
69 	N_("Information"),
70 	N_("Diplomacy"),
71 	N_("Chat"),
72 	N_("Diplomatic Log"),
73 	N_("Debug"),
74 };
75 
76 //---------- Define chat receiver str strings ---------//
77 
78 static const char* chat_receiver_str_array[MAX_CHAT_RECEIVER_TYPE] =
79 {
80 	N_("Send to the selected kingdom"),
81 	N_("Send to all allied human controlled kingdoms"),
82 	N_("Send to all human controlled kingdoms"),
83 };
84 
85 //----------- Define static variables ----------//
86 
87 static VBrowseIF 	 browse_nation, browse_talk_msg;
88 static ButtonGroup button_allow_attack(2);
89 static ButtonGroup button_chat_receiver(MAX_CHAT_RECEIVER_TYPE);
90 static int init_get_chat = 0;
91 static GetA 		 get_chat;
92 
93 //----------- Define static functions ----------//
94 
95 static void put_nation_rec(int recNo, int x, int y, int refreshFlag);
96 static void put_talk_msg_rec(int recNo, int x, int y, int refreshFlag);
97 static int  nation_filter(int recNo=0);
98 static void disp_button();
99 static int  detect_button();
100 static void disp_detail(int refreshFlag);
101 static void detect_detail();
102 static void disp_nation_info();
103 static void detect_nation_info();
104 static void disp_debug_info();
105 static void disp_nation_talk();
106 static void detect_nation_talk();
107 static void disp_nation_chat(int refreshFlag);
108 static void detect_nation_chat();
109 static void disp_talk_msg_sent(int refreshFlag);
110 
111 static int  sort_talk_msg( const void *a, const void *b );
112 
113 static void put_heading(char justify, int x1, int y1, int x2, int y2, const char *textPtr);
114 static char* nation_color_code_str(int nationRecno);
115 
116 #define J_L Font::LEFT_JUSTIFY
117 #define J_C Font::CENTER_JUSTIFY
118 #define J_R Font::RIGHT_JUSTIFY
119 
120 
121 //--------- Begin of function Info::disp_nation ---------//
122 //
123 // <int> refreshFlag - INFO_REPAINT - the user has just switched
124 //												  to this report.
125 //							  INFO_UPDATE  - the report is already in this mode,
126 //												  just keep displaying and updating.
127 //
disp_nation(int refreshFlag)128 void Info::disp_nation(int refreshFlag)
129 {
130 	//--------- Create nation income and expenses browsers -------//
131 
132 	int x=REPORT_BROWSE_X1+9, y=REPORT_BROWSE_Y1+4;
133 
134 	vga_back.d3_panel_up(REPORT_BROWSE_X1, REPORT_BROWSE_Y1, REPORT_BROWSE_X2, REPORT_BROWSE_Y1+33 );
135 
136 	put_heading( J_L, x    , y, x+185, y+29, _("Kingdom") );
137 
138 	put_heading( J_C, x+185, y, x+275, y+29, _("Reputation") );
139 	put_heading( J_L, x+275, y, x+345, y+29, _("Status") );
140 
141 
142 #if(defined(SPANISH))
143 	font_san.put( x+335, y   , "Allow" );
144 	font_san.put( x+335, y+13, "Attack" );
145 
146 	font_san.put( x+395, y,    "Acuerdo" );
147 	font_san.put( x+395, y+13, "Comerc." );
148 
149 	font_san.put( x+468, y   , "Cantidad" );
150 	font_san.put( x+468, y+13, "Comerciada" );
151 #elif(defined(FRENCH))
152 	font_san.put( x+335, y   , "Allow" );
153 	font_san.put( x+335, y+13, "Attack" );
154 
155 	font_san.put( x+395, y,    "Accord" );
156 	font_san.put( x+395, y+13, "Commercial" );
157 
158 	font_san.put( x+473, y   , "Montant" );
159 	font_san.put( x+473, y+13, "Commercial" );
160 #elif(defined(GERMAN))
161 	font_san.put( x+345, y   , "Allow" );
162 	font_san.put( x+343, y+13, "Attack" );
163 
164 	font_san.put( x+405, y   , "Handels-" );
165 	font_san.put( x+405, y+13, "Vertrag" );
166 
167 	font_san.put( x+465, y   , "Handels-" );
168 	font_san.put( x+465, y+13, "Betrag" );
169 #else
170 	put_heading( J_L, x+345, y   , x+405, y+29, _("Allow Attack") );
171 
172 	put_heading( J_L, x+405, y   , x+465, y+29, _("Trade Treaty") );
173 
174 	put_heading( J_L, x+465, y   , REPORT_BROWSE_X2-20, y+29, _("Trade Amount") );
175 #endif
176 
177 
178 	if( refreshFlag == INFO_REPAINT )
179 	{
180 		browse_nation.init( REPORT_BROWSE_X1, REPORT_BROWSE_Y1+35, REPORT_BROWSE_X2, REPORT_BROWSE_Y2,
181 								  0, 20, nation_filter(), put_nation_rec, 1 );
182 
183 		browse_nation.open(browse_nation_recno);
184 	}
185 	else
186 	{
187 		browse_nation.paint();
188 		browse_nation.open(browse_nation_recno, nation_filter());
189 	}
190 
191 	browse_nation_recno = browse_nation.recno();
192 
193 	//------- disp report buttons --------//
194 
195 	disp_button();
196 
197 	//--------- display detail info --------//
198 
199 	if( refreshFlag==INFO_REPAINT )
200 	{
201 		info.last_talk_nation_recno = 0;
202 		browse_talk_msg_recno = 1;
203 	}
204 
205 	disp_detail(refreshFlag);
206 }
207 //----------- End of function Info::disp_nation -----------//
208 
209 
210 //--------- Begin of function Info::detect_nation ---------//
211 //
detect_nation()212 void Info::detect_nation()
213 {
214 	//------- detect nation browser ------//
215 
216 	if( browse_nation.detect() )
217 	{
218 		browse_nation_recno = browse_nation.recno();
219 		return;
220 	}
221 
222 	//------- detect report buttons --------//
223 
224 	if( detect_button() )
225 		return;
226 
227 	//--------- detect detail info -------//
228 
229 	detect_detail();
230 }
231 //----------- End of function Info::detect_nation -----------//
232 
233 
234 //--------- Begin of function Info::init_player_reply ---------//
235 //
236 // This function is called by TalkRes::player_reply() when the
237 // player is going to reply to a diplomatic message from another
238 // nation.
239 //
240 // <int> talkToNationRecno - recno of the nation the player is
241 //									  going to talk to.
242 //
init_player_reply(int talkToNationRecno)243 void Info::init_player_reply(int talkToNationRecno)
244 {
245 	nation_report_mode = NATION_REPORT_TALK;
246 
247 	info.player_reply_mode = 1;
248 
249 	//--- go to the nation in the browser which the player is going to talk to ---//
250 
251 	int nationCount = nation_filter();
252 
253 	int i;
254 	for( i=1 ; i<=nationCount ; i++ )
255 	{
256 		if( nation_filter(i) == talkToNationRecno )
257 		{
258 			browse_nation_recno = i;
259 			break;
260 		}
261 	}
262 
263 	err_when( i>nationCount );
264 
265 	//----- if currently it's in nation report mode -----//
266 
267 	if( sys.view_mode == MODE_NATION )
268 		browse_nation.refresh(browse_nation_recno);
269 }
270 //----------- End of function Info::init_player_reply -----------//
271 
272 
273 //-------- Begin of static function nation_filter --------//
274 //
275 // This function has dual purpose :
276 //
277 // 1. when <int> recNo is not given :
278 //    - return the total no. of nations of this nation
279 //
280 // 2. when <int> recNo is given :
281 //    - return the nation recno in nation_array of the given recno.
282 //
nation_filter(int recNo)283 static int nation_filter(int recNo)
284 {
285 	int    	i, nationCount=0;
286 	Nation*  viewingNation = nation_array[info.viewing_nation_recno];
287 
288 	for( i=1 ; i<=nation_array.size() ; i++ )
289 	{
290 		if( nation_array.is_deleted(i) )
291 			continue;
292 
293 		if( i==info.viewing_nation_recno ||
294 			 viewingNation->get_relation(i)->has_contact )
295 		{
296 			nationCount++;
297 		}
298 
299 		if( recNo && nationCount==recNo )
300 			return i;
301 	}
302 
303 	err_when( recNo );   // the recNo is not found, it is out of range
304 
305 	return nationCount;
306 }
307 //----------- End of static function nation_filter -----------//
308 
309 
310 //-------- Begin of static function put_nation_rec --------//
311 //
put_nation_rec(int recNo,int x,int y,int refreshFlag)312 static void put_nation_rec(int recNo, int x, int y, int refreshFlag)
313 {
314 	int	  nationRecno = nation_filter(recNo);
315 	Nation* nationPtr   = nation_array[nationRecno];
316 	Nation* viewingNation = nation_array[info.viewing_nation_recno];
317 	NationRelation* nationRelation = viewingNation->get_relation(nationRecno);
318 
319 	x+=3;
320 	y+=5;
321 
322 	nationPtr->disp_nation_color(x, y+1);
323 
324 	font_san.put( x+20 , y, nationPtr->nation_name(), 0, x+215 );
325 	font_san.put( x+220, y, misc.format((int) nationPtr->reputation) );
326 
327 	//------- display relation parameters --------//
328 
329 	if( nationRecno != info.viewing_nation_recno )
330 	{
331 		font_san.put( x+272, y, nationRelation->status_str() );
332 		font_san.put( x+355, y, nationRelation->should_attack ? (char*)_("Yes") : (char*)_("No") );
333 		font_san.put( x+412, y, nationRelation->trade_treaty ? (char*)_("Yes") : (char*)_("No") );
334 		font_san.put( x+465, y, misc.format( (int) viewingNation->total_year_trade(nationRecno),2) );
335 
336 		if( config.show_ai_info )
337 		{
338 			font_san.put( x+510, y, misc.format(nationPtr->get_relation(info.viewing_nation_recno)->ai_relation_level) );
339 			font_san.put( x+180, y, misc.format( (int) nationPtr->get_relation(info.viewing_nation_recno)->good_relation_duration_rating) );
340 		}
341 	}
342 }
343 //----------- End of static function put_nation_rec -----------//
344 
345 
346 //--------- Begin of static function disp_button ---------//
347 //
disp_button()348 static void disp_button()
349 {
350 	int x=REPORT_BUTTON_X1;
351 
352 	for( int i=1 ; i<=MAX_NATION_REPORT_MODE ; i++ )
353 	{
354 		if( i==NATION_REPORT_DEBUG )
355 		{
356 			if( remote.is_enable() ||
357 				 ( !sys.debug_session && !sys.testing_session ) )
358 			{
359 				continue;
360 			}
361 		}
362 		else if( !sys.debug_session && i==NATION_REPORT_CHAT )
363 		{
364 			if( !remote.is_enable() )
365 				continue;
366 		}
367 
368 		//-----------------------------------------//
369 
370 		if( info.nation_report_mode == i )
371 			vga_util.d3_panel_down( x, REPORT_BUTTON_Y1, x+REPORT_BUTTON_WIDTH-1, REPORT_BUTTON_Y2 );
372 		else
373 			vga_util.d3_panel_up( x, REPORT_BUTTON_Y1, x+REPORT_BUTTON_WIDTH-1, REPORT_BUTTON_Y2 );
374 
375 		font_san.center_put( x, REPORT_BUTTON_Y1, x+REPORT_BUTTON_WIDTH-1, REPORT_BUTTON_Y2, _(report_mode_str_array[i-1]) );
376 
377 		x+=REPORT_BUTTON_WIDTH;
378 	}
379 }
380 //----------- End of static function disp_button -----------//
381 
382 
383 //--------- Begin of static function detect_button ---------//
384 //
detect_button()385 static int detect_button()
386 {
387 	int x=REPORT_BUTTON_X1;
388 
389 	for( int i=1 ; i<=MAX_NATION_REPORT_MODE ; i++ )
390 	{
391 		if( i==NATION_REPORT_DEBUG )
392 		{
393 			if( remote.is_enable() ||
394 				 ( !sys.debug_session && !sys.testing_session ) )
395 			{
396 				continue;
397 			}
398 		}
399 		else if( !sys.debug_session && i==NATION_REPORT_CHAT )
400 		{
401 			if( !remote.is_enable() )
402 				continue;
403 		}
404 
405 		//-----------------------------------------//
406 
407 		if( mouse.single_click( x, REPORT_BUTTON_Y1, x+REPORT_BUTTON_WIDTH-1, REPORT_BUTTON_Y2 ) )
408 		{
409 			info.nation_report_mode = i;
410 			if( info.nation_report_mode == NATION_REPORT_CHAT )
411 				SDL_StartTextInput();
412 			else
413 				SDL_StopTextInput();
414 			return 1;
415 		}
416 
417 		x+=REPORT_BUTTON_WIDTH;
418 	}
419 
420 	return 0;
421 }
422 //----------- End of static function detect_button -----------//
423 
424 
425 //--------- Begin of static function disp_detail ---------//
426 //
disp_detail(int refreshFlag)427 static void disp_detail(int refreshFlag)
428 {
429 	if( browse_nation.recno()==0 )		// no records in the list
430 		return;
431 
432 	switch( info.nation_report_mode )
433 	{
434 		case NATION_REPORT_INFO:
435 			disp_nation_info();
436 			break;
437 
438 		case NATION_REPORT_TALK:
439 			disp_nation_talk();
440 			break;
441 
442 		case NATION_REPORT_CHAT:
443 			disp_nation_chat(refreshFlag);
444 			break;
445 
446 		case NATION_REPORT_TALK_LOG:
447 			disp_talk_msg_sent(refreshFlag);
448 			break;
449 
450 		case NATION_REPORT_DEBUG:
451 			disp_debug_info();
452 			break;
453 	}
454 }
455 //----------- End of static function disp_detail -----------//
456 
457 
458 //--------- Begin of static function detect_detail ---------//
459 //
detect_detail()460 static void detect_detail()
461 {
462 	switch( info.nation_report_mode )
463 	{
464 		case NATION_REPORT_INFO:
465 			detect_nation_info();
466 			break;
467 
468 		case NATION_REPORT_TALK:
469 			detect_nation_talk();
470 			break;
471 
472 		case NATION_REPORT_CHAT:
473 			detect_nation_chat();
474 			break;
475 
476 		case NATION_REPORT_TALK_LOG:
477 			if( browse_talk_msg.detect() )
478 				info.browse_talk_msg_recno = browse_talk_msg.recno();
479 			break;
480 	}
481 }
482 //----------- End of static function detect_detail -----------//
483 
484 
485 //--------- Begin of static function disp_nation_info ---------//
486 //
disp_nation_info()487 static void disp_nation_info()
488 {
489 	vga_util.d3_panel_down( REPORT_DET_X1, REPORT_DET_Y1, REPORT_DET_X2, REPORT_DET_Y2 );
490 
491 	//----------- display info ------------//
492 
493 	int	  nationRecno  = nation_filter(browse_nation.recno());
494 	Nation* nationPtr    = nation_array[nationRecno];
495 	Nation* viewingNation = nation_array[info.viewing_nation_recno];
496 	NationRelation* nationRelation = viewingNation->get_relation(nationRecno);
497 
498 	int x1=REPORT_DET_X1+6, x2=REPORT_DET_X1+340, x3=REPORT_DET_X2-10;
499 	int y=REPORT_DET_Y1+6;
500 
501 	//-------- display economic data ----------//
502 
503 	String str;
504 	char xstr[MAX_STR_LEN+1] = {0};
505 
506 	if( nationRecno == info.viewing_nation_recno )
507 	{
508 		font_san.put_field( x1, y, _("Your Food"), x2, nationPtr->food_str() );
509 
510 		str  = "$";
511 		str += nationPtr->cash_str();
512 
513 		font_san.put_field( x1, y+=16, _("Your Treasure"), x2, str );
514 
515 		font_san.field( x1, y+=16, _("Your Continuous Peace Time"), x2, nationPtr->peace_duration_str(), x3, INFO_REPAINT, "PEACE" );
516 	}
517 	else
518 	{
519 		// TRANSLATORS: Your Yearly Import from <King>'s Kingdom
520 		str = _("Your Yearly Import from %s's Kingdom");
521 		snprintf( xstr, MAX_STR_LEN+1, str, nationPtr->king_name(1) );
522 
523 		font_san.field( x1, y    , xstr, x2, (int) viewingNation->get_relation(nationRecno)->import_365days(IMPORT_TOTAL), 2, x3, INFO_REPAINT, "IMPORT" );
524 
525 		// TRANSLATORS: Your Yearly Export to <King>'s Kingdom
526 		str = _("Your Yearly Export to %s's Kingdom");
527 		snprintf( xstr, MAX_STR_LEN+1, str, nationPtr->king_name(1) );
528 
529 		font_san.field( x1, y+=16, xstr, x2, (int) nationPtr->get_relation(info.viewing_nation_recno)->import_365days(IMPORT_TOTAL), 2, x3, INFO_REPAINT, "EXPORT" );
530 
531 		// TRANSLATORS: Continuous Peace Time of <King>'s Kingdom
532 		str = _("Continuous Peace Time of %s's Kingdom");
533 		snprintf( xstr, MAX_STR_LEN+1, str, nationPtr->king_name(1) );
534 
535 		font_san.field( x1, y+=16, xstr, x2, nationPtr->peace_duration_str(), x3, INFO_REPAINT, "PEACE" );
536 
537 		//--------- duration of current status ----------//
538 
539 		font_san.field( x1, y+=16, nationRelation->duration_of_status_str(), x2, nationRelation->status_duration_str(), x3, INFO_REPAINT, "STATTIME" );
540 
541 		//------- display the allow_attack field --------//
542 
543 		// TRANSLATORS: Allow Your Units to Attack <Kings>'s Kingdom
544 		str = _("Allow Your Units to Attack %s's Kingdom");
545 		snprintf( xstr, MAX_STR_LEN+1, str, nationPtr->king_name(1) );
546 
547 		font_san.field( x1, y+=16, xstr, x2, "", x3, INFO_REPAINT, "ALLOWATK" );
548 
549 		button_allow_attack[1].create_text( x2+6 , y, x2+50 , y+15, _("Yes") );
550 		button_allow_attack[0].create_text( x2+54, y, x2+100, y+15, _("No")  );
551 
552 		button_allow_attack.paint( viewingNation->get_relation(nationRecno)->should_attack );
553 
554 		//---- if this nation is our ally, display its cash and food ----//
555 
556 		if( viewingNation->get_relation(nationRecno)->status == NATION_ALLIANCE )
557 		{
558 			// TRANSLATORS: <King>'s Kingdom's Treasure
559 			str = _("%s's Kingdom's Treasure");
560 			snprintf( xstr, MAX_STR_LEN+1, str, nationPtr->king_name(1) );
561 
562 			font_san.field( x1, y+=16, xstr, x2, nationPtr->cash, 2, x3, INFO_REPAINT );
563 
564 			// TRANSLATORS: <King>'s Kingdom's Food
565 			str = _("%s's Kingdom's Food");
566 			snprintf( xstr, MAX_STR_LEN+1, str, nationPtr->king_name(1) );
567 
568 			font_san.field( x1, y+=16, xstr, x2, nationPtr->food, 2, x3, INFO_REPAINT );
569 		}
570 	}
571 
572 	y+=26;
573 
574 	//----- display its relation status with other nations -----//
575 
576 	if( info.viewing_nation_recno != nationRecno )
577 	{
578 		String str;
579 
580 		// TRANSLATORS: <King>'s Kingdom's Diplomatic Status with Other Kingdoms:
581 		str = _("%s's Kingdom's Diplomatic Status with Other Kingdoms:");
582 		snprintf( xstr, MAX_STR_LEN+1, str, nationPtr->king_name(1) );
583 
584 		nationPtr->disp_nation_color(x1, y+1);
585 		font_san.put(x1+20, y, xstr);
586 		y+=20;
587 
588 		for( int i=1 ; i<=nation_array.size() ; i++ )
589 		{
590 			if( nation_array.is_deleted(i) ||
591 				 i == nationRecno ||
592 				 i == info.viewing_nation_recno )
593 			{
594 				continue;
595 			}
596 
597 			nation_array[i]->disp_nation_color(x1, y+1);
598 
599 			font_san.put( x1+20, y, nation_array[i]->nation_name() );
600 			font_san.put( x1+240, y, nationPtr->get_relation(i)->status_str() );
601 
602 			if( nationPtr->get_relation(i)->trade_treaty )
603 			{
604 				font_san.put( x1+330, y, _("Trade Treaty") );
605 #if(defined(FRENCH))
606 				font_san.put( x1+460, y, misc.format((int)nationPtr->total_year_trade(i),2) );
607 #else
608 				// German and US
609 				font_san.put( x1+450, y, misc.format((int)nationPtr->total_year_trade(i),2) );
610 #endif
611 			}
612 
613 			if( config.show_ai_info )
614 			{
615 				font_san.put( x1+500, y, nationPtr->get_relation(i)->ai_relation_level );
616 				font_san.put( x1+530, y, (int) nationPtr->get_relation(i)->good_relation_duration_rating );
617 			}
618 
619 			y+=16;
620 		}
621 	}
622 }
623 //----------- End of static function disp_nation_info -----------//
624 
625 
626 //--------- Begin of static function detect_nation_info ---------//
627 //
detect_nation_info()628 static void detect_nation_info()
629 {
630 	int nationRecno = nation_filter(browse_nation.recno());
631 
632 	Nation* viewingNation = nation_array[info.viewing_nation_recno];
633 
634 	if( button_allow_attack.detect() >= 0 )
635 		viewingNation->set_relation_should_attack(nationRecno, button_allow_attack.button_pressed, COMMAND_PLAYER);
636 }
637 //----------- End of static function detect_nation_info -----------//
638 
639 
640 //--------- Begin of static function disp_debug_info ---------//
641 //
disp_debug_info()642 static void disp_debug_info()
643 {
644 	vga_util.d3_panel_down( REPORT_DET_X1, REPORT_DET_Y1, REPORT_DET_X2, REPORT_DET_Y2 );
645 
646 	//----------- display info ------------//
647 
648 	int	  nationRecno  = nation_filter(browse_nation.recno());
649 	Nation* nationPtr    = nation_array[nationRecno];
650 
651 	int x1=REPORT_DET_X1+6, x2=REPORT_DET_X1+160;
652 	int y=REPORT_DET_Y1+6;
653 
654 	int refreshFlag = INFO_REPAINT;
655 
656 	//------------ display AI info ----------//
657 
658 	font_san.put_field( x1, y    , "Food    ", x2, nationPtr->food_str() );
659 	font_san.put_field( x1, y+=16, "Treasure", x2, nationPtr->cash_str() );
660 	font_san.put_field( x1, y+=16, "ai_capture_enemy_town_recno", x2, nationPtr->ai_capture_enemy_town_recno, 1 );
661 	font_san.put_field( x1, y+=16, "Surplus supply rating", x2, nationPtr->surplus_supply_rating() );
662 	y+=48;
663 
664 	//--------- display AI preference ----------//
665 
666 	x2 += 60;
667 
668 	font_san.put_field( x1, y+=16, "Unit Chase Distance"     , x2, nationPtr->pref_unit_chase_distance     , 1 );
669 	font_san.put_field( x1, y+=16, "Military Development"	   , x2, nationPtr->pref_military_development	 , 1 );
670 	font_san.put_field( x1, y+=16, "Economic Development"	   , x2, nationPtr->pref_economic_development	 , 1 );
671 	font_san.put_field( x1, y+=16, "Increase Pop by Capture" , x2, nationPtr->pref_inc_pop_by_capture      , 1 );
672 	font_san.put_field( x1, y+=16, "Increase Pop by Growth"  , x2, nationPtr->pref_inc_pop_by_growth   	 , 1 );
673 	font_san.put_field( x1, y+=16, "Peacefulness" 		      , x2, nationPtr->pref_peacefulness        	 , 1 );
674 	font_san.put_field( x1, y+=16, "Military Courage"    	   , x2, nationPtr->pref_military_courage    	 , 1 );
675 	font_san.put_field( x1, y+=16, "Territorial Cohesiveness", x2, nationPtr->pref_territorial_cohesiveness, 1 );
676 	font_san.put_field( x1, y+=16, "Trading Tendency"        , x2, nationPtr->pref_trading_tendency        , 1 );
677 
678 	x1 += (REPORT_DET_X2-REPORT_DET_X1)/2;
679 	x2 += (REPORT_DET_X2-REPORT_DET_X1)/2;
680 
681 	y=REPORT_DET_Y1+6;
682 
683 	font_san.put_field( x1, y    , "Allying Tendency"        , x2, nationPtr->pref_allying_tendency        , 1 );
684 	font_san.put_field( x1, y+=16, "Honesty"                 , x2, nationPtr->pref_honesty                 , 1 );
685 	font_san.put_field( x1, y+=16, "Town Harmony"         	, x2, nationPtr->pref_town_harmony			    , 1 );
686 	font_san.put_field( x1, y+=16, "Citizen Loyalty Concern" , x2, nationPtr->pref_loyalty_concern  		 , 1 );
687 	font_san.put_field( x1, y+=16, "Forgiveness"             , x2, nationPtr->pref_forgiveness      		 , 1 );
688 	font_san.put_field( x1, y+=16, "Collect Tax Tendency"    , x2, nationPtr->pref_collect_tax      		 , 1 );
689 	font_san.put_field( x1, y+=16, "Build Inn Tendency"      , x2, nationPtr->pref_hire_unit       		    , 1 );
690 	font_san.put_field( x1, y+=16, "Use Weapon Tendency"     , x2, nationPtr->pref_use_weapon       		 , 1 );
691 	font_san.put_field( x1, y+=16, "Keep Generals Tendency"  , x2, nationPtr->pref_keep_general            , 1 );
692 	font_san.put_field( x1, y+=16, "Keep Skilled Units Tendency", x2, nationPtr->pref_keep_skilled_unit    , 1 );
693 	font_san.put_field( x1, y+=16, "Attack Monster"          , x2, nationPtr->pref_attack_monster          , 1 );
694 	font_san.put_field( x1, y+=16, "Use Spies"               , x2, nationPtr->pref_spy                     , 1 );
695 	font_san.put_field( x1, y+=16, "Use Counter Spies"       , x2, nationPtr->pref_counter_spy             , 1 );
696 	font_san.put_field( x1, y+=16, "Food Reserve"            , x2, nationPtr->pref_food_reserve            , 1 );
697 	font_san.put_field( x1, y+=16, "Cash Reserve"            , x2, nationPtr->pref_cash_reserve            , 1 );
698 	font_san.put_field( x1, y+=16, "Use Marine"              , x2, nationPtr->pref_use_marine              , 1 );
699 }
700 //----------- End of static function disp_debug_info -----------//
701 
702 
703 //--------- Begin of static function disp_nation_talk ---------//
704 //
disp_nation_talk()705 static void disp_nation_talk()
706 {
707 	int nationRecno = nation_filter(info.browse_nation_recno);
708 
709 	//----- if the selected nation is the viewing nation ----//
710 
711 	if( nationRecno != info.viewing_nation_recno &&
712 		 info.viewing_nation_recno == nation_array.player_recno )
713 	{
714 		vga_util.d3_panel_down( REPORT_DET_X1, REPORT_DET_Y1, REPORT_DET_X2, REPORT_TALK_Y2 );
715 
716 		if( info.last_talk_nation_recno != nationRecno && !info.player_reply_mode )
717 			talk_res.init_conversion(nationRecno);
718 
719 		info.player_reply_mode = 0;
720 		info.last_talk_nation_recno = nationRecno;
721 
722 		talk_res.disp_talk();
723 	}
724 }
725 //----------- End of static function disp_nation_talk -----------//
726 
727 
728 //--------- Begin of static function detect_nation_talk ---------//
729 //
detect_nation_talk()730 static void detect_nation_talk()
731 {
732 	int nationRecno = nation_filter(info.browse_nation_recno);
733 
734 	//----- if the selected nation is the viewing nation ----//
735 
736 	if( nationRecno != info.viewing_nation_recno &&
737 		 info.viewing_nation_recno == nation_array.player_recno )
738 	{
739 		talk_res.detect_talk();
740 	}
741 }
742 //----------- End of static function detect_nation_talk -----------//
743 
744 
745 //--------- Begin of static function disp_talk_msg_sent ---------//
746 //
disp_talk_msg_sent(int refreshFlag)747 static void disp_talk_msg_sent(int refreshFlag)
748 {
749 	//--- filter out talk messages sent by this nation and sort them by date ---//
750 
751 	TalkMsg* 	talkMsg;
752 	TalkMsgDisp talkMsgDisp;
753 
754 	static short lastNationRecno=0;
755 	int nationRecno = nation_filter(info.browse_nation_recno);
756 
757 	if( lastNationRecno != nationRecno )
758 	{
759 		info.browse_talk_msg_recno = 1;		// reset the browser recno of the viewing nation has been changed
760 		lastNationRecno = nationRecno;
761 	}
762 
763 	//--------------------------------------------//
764 
765 	info.talk_msg_disp_array.zap();
766 
767 	for( short i=1 ; i<=talk_res.talk_msg_count() ; i++ )
768 	{
769 		if( talk_res.is_talk_msg_deleted(i) )
770 			continue;
771 
772 		talkMsg = talk_res.get_talk_msg(i);
773 
774 		if( !talkMsg->is_valid_to_disp() )		// don't link it out, otherwise it may cause multiplayer sync problem.
775 			continue;
776 
777 		if( talkMsg->from_nation_recno == nationRecno ||
778 			 talkMsg->to_nation_recno == nationRecno )
779 		{
780 			if( talkMsg->from_nation_recno == info.viewing_nation_recno ||
781 				 talkMsg->to_nation_recno == info.viewing_nation_recno )
782 			{
783 				if( !nation_array.is_deleted(talkMsg->from_nation_recno) &&
784 					 !nation_array.is_deleted(talkMsg->to_nation_recno) )
785 				{
786 					talkMsgDisp.recno = i;
787 					talkMsgDisp.date  = talkMsg->date;
788 					talkMsgDisp.is_reply = 0;
789 
790 					info.talk_msg_disp_array.linkin(&talkMsgDisp);
791 
792 					if( talkMsg->reply_date )
793 					{
794 						talkMsgDisp.recno = i;
795 						talkMsgDisp.date  = talkMsg->reply_date;
796 						talkMsgDisp.is_reply = 1;
797 
798 						info.talk_msg_disp_array.linkin(&talkMsgDisp);
799 					}
800 				}
801 			}
802 		}
803 	}
804 
805 	if( info.talk_msg_disp_array.size() > 0 )
806 		info.talk_msg_disp_array.quick_sort(sort_talk_msg);
807 
808 	//----- display a browser of the talk msg sent -----//
809 
810 	if( refreshFlag == INFO_REPAINT || !browse_talk_msg.init_flag )
811 	{
812 		browse_talk_msg.init( REPORT_DET_X1, REPORT_DET_Y1, REPORT_DET_X2, REPORT_DET_Y2,
813 									 0, 30, info.talk_msg_disp_array.size(), put_talk_msg_rec, 1 );
814 
815 		browse_talk_msg.open(info.browse_talk_msg_recno);
816 	}
817 	else
818 	{
819 		browse_talk_msg.paint();
820 		browse_talk_msg.open(info.browse_talk_msg_recno, info.talk_msg_disp_array.size());
821 	}
822 
823 	info.browse_talk_msg_recno = browse_talk_msg.recno();
824 }
825 //----------- End of static function disp_talk_msg_sent -----------//
826 
827 
828 //------ Begin of function sort_talk_msg ------//
829 //
sort_talk_msg(const void * a,const void * b)830 static int sort_talk_msg( const void *a, const void *b )
831 {
832 	if( ((TalkMsgDisp*)b)->recno == ((TalkMsgDisp*)a)->recno )
833 		return ((TalkMsgDisp*)b)->is_reply ? 1 : -1;
834 
835 	return ((TalkMsgDisp*)b)->date - ((TalkMsgDisp*)a)->date;
836 }
837 //------- End of function sort_talk_msg ------//
838 
839 
840 //-------- Begin of static function put_talk_msg_rec --------//
841 //
put_talk_msg_rec(int recNo,int x1,int y,int refreshFlag)842 static void put_talk_msg_rec(int recNo, int x1, int y, int refreshFlag)
843 {
844 	TalkMsgDisp* talkMsgDisp = (TalkMsgDisp*) info.talk_msg_disp_array.get(recNo);
845 	TalkMsg*		 talkMsg = talk_res.get_talk_msg(talkMsgDisp->recno);
846 
847 	int x=x1, isTo;
848 
849 	x+=3;
850 	y+=2;
851 
852 	if( !talkMsgDisp->is_reply )		// if not a replying message
853 		isTo = talkMsg->from_nation_recno == info.viewing_nation_recno;	// you send a message to a nation
854 	else
855 		isTo = talkMsg->from_nation_recno != info.viewing_nation_recno;
856 
857 	//---------------------------------------//
858 
859 	String str;
860 	char *nation_color, *date_str;
861 
862 	if( talkMsg->from_nation_recno == info.viewing_nation_recno )
863 		nation_color = nation_color_code_str(talkMsg->to_nation_recno);
864 	else
865 		nation_color = nation_color_code_str(talkMsg->from_nation_recno);
866 
867 	if( talkMsgDisp->is_reply )
868 		date_str = date.date_str(talkMsg->reply_date);
869 	else
870 		date_str = date.date_str(talkMsg->date);
871 
872 	if( isTo )
873 		// TRANSLATORS: To<Nation color> on <Date> :
874 		snprintf(str, MAX_STR_LEN+1, _("To%s on %s :"), nation_color, date_str);
875 	else
876 		// TRANSLATORS: From<Nation color> on <Date> :
877 		snprintf(str, MAX_STR_LEN+1, _("From%s on %s :"), nation_color, date_str);
878 
879 	font_san.put( x , y, str );
880 
881 	//---------------------------------------//
882 
883 	font_san.put( x1, y+13, talkMsg->msg_str(info.viewing_nation_recno, talkMsgDisp->is_reply), 0, browse_talk_msg.ix2 );
884 }
885 //----------- End of static function put_talk_msg_rec -----------//
886 
887 
888 //--------- Begin of static function disp_nation_chat ---------//
889 //
disp_nation_chat(int refreshFlag)890 static void disp_nation_chat(int refreshFlag)
891 {
892 	int nationRecno = nation_filter(info.browse_nation_recno);
893 
894 	//----- if the selected nation is the viewing nation ----//
895 
896 	if( !(sys.debug_session || nation_array[nationRecno]->nation_type == NATION_REMOTE &&
897 		 info.viewing_nation_recno == nation_array.player_recno ) )
898 	{
899 		return;
900 	}
901 
902 	//-------- display the chat get control -------//
903 
904 	vga_util.d3_panel_down( REPORT_DET_X1, REPORT_DET_Y1, REPORT_DET_X2, REPORT_TALK_Y2 );
905 
906 	font_san.put( REPORT_DET_X1+10, REPORT_DET_Y1+10,
907 					  _("Please enter your chat message and press <Enter> to send.") );
908 
909 	// ###### begin Gilbert 15/10 #######//
910 	if( !init_get_chat )
911 	{
912 		get_chat.init( REPORT_DET_X1+10, REPORT_DET_Y1+30, REPORT_DET_X2-10,
913 			info.player_chat_str, CHAT_STR_LEN, &font_san, 0, 0 );
914 		get_chat.clear();
915 		init_get_chat = 1;
916 	}
917 	// ###### end Gilbert 15/10 #######//
918 
919 	int vgaUseBack = vga.use_back_buf;
920 
921 	vga.use_back();
922 	get_chat.paint(1);			// 1-paint cursor
923 
924 	if( !vgaUseBack )
925 		vga.use_front();
926 
927 	//-------- display receiver type buttons ---------//
928 
929 	int y=REPORT_TALK_Y2-70;
930 
931 	for( int i=1 ; i<=MAX_CHAT_RECEIVER_TYPE ; i++, y+=22 )
932 	{
933 		if( info.chat_receiver_type == i )
934 			vga_util.d3_panel_down( REPORT_DET_X1+10, y, REPORT_DET_X2-10, y+20 );
935 		else
936 			vga_util.d3_panel_up( REPORT_DET_X1+10, y, REPORT_DET_X2-10, y+20 );
937 
938 		font_san.center_put( REPORT_DET_X1+10, y, REPORT_DET_X2-10, y+20, _(chat_receiver_str_array[i-1]) );
939 	}
940 }
941 //----------- End of static function disp_nation_chat -----------//
942 
943 
944 //--------- Begin of static function detect_nation_chat ---------//
945 //
detect_nation_chat()946 static void detect_nation_chat()
947 {
948 	int nationRecno = nation_filter(info.browse_nation_recno);
949 
950 	//----- if the selected nation is the viewing nation ----//
951 
952 	if( sys.debug_session || nation_array[nationRecno]->nation_type == NATION_REMOTE &&
953 		 info.viewing_nation_recno == nation_array.player_recno )
954 	{
955 		// ###### begin Gilbert 15/10 #######//
956 		if( !init_get_chat )
957 		{
958 			get_chat.init( REPORT_DET_X1+10, REPORT_DET_Y1+30, REPORT_DET_X2-10,
959 				info.player_chat_str, CHAT_STR_LEN, &font_san, 0, 0 );
960 			get_chat.clear();
961 			init_get_chat = 1;
962 		}
963 		// ###### end Gilbert 15/10 #######//
964 
965 		for( int i=0 ; i<5 ; i++ )
966 		{
967 			int keyCode = get_chat.detect();
968 
969 			if( !keyCode )
970 				break;
971 
972 			//---- press <Enter> to send the chat message ----//
973 
974 			if( keyCode == KEY_RETURN && info.player_chat_str[0] != '\0')
975 			{
976 				if( remote.is_enable() )
977 				{
978 					// packet structure : <to nation recno> <from nation recno> <char[CHAT_STR_LEN+1]>
979 					short *shortPtr = (short *)remote.new_send_queue_msg(MSG_CHAT, 2*sizeof(short) + strlen(info.player_chat_str)+1 );
980 
981 					switch( info.chat_receiver_type )
982 					{
983 					case 1:		// selected
984 						shortPtr[0] = nationRecno;
985 						break;
986 					case 2:		// all allies
987 						shortPtr[0] = -1;
988 						break;
989 					case 3:		// all human
990 						shortPtr[0] = 0;
991 						break;
992 					}
993 					shortPtr[1] = info.viewing_nation_recno;
994 
995 					strcpy(2*sizeof(short)+(char *)shortPtr, info.player_chat_str);
996 				}
997 
998 				get_chat.clear();
999 				break;
1000 			}
1001 
1002 			mouse.get_event();
1003 		}
1004 	}
1005 
1006 	//-------- detect receiver type buttons ---------//
1007 
1008 	int y=REPORT_TALK_Y2-70;
1009 
1010 	for( int i=1 ; i<=MAX_CHAT_RECEIVER_TYPE ; i++, y+=22 )
1011 	{
1012 		if( mouse.single_click( REPORT_DET_X1+10, y, REPORT_DET_X2-50, y+20 ) )
1013 		{
1014 			info.chat_receiver_type = i;
1015 			return;
1016 		}
1017 	}
1018 }
1019 //----------- End of static function detect_nation_chat -----------//
1020 
1021 
1022 //------- Begin of function Info::player_reply_chat --------//
1023 //
1024 // <int> withNationRecno - player reply a chat message to this nation.
1025 //
player_reply_chat(int withNationRecno)1026 void Info::player_reply_chat(int withNationRecno)
1027 {
1028 	nation_report_mode = NATION_REPORT_CHAT;
1029 
1030 	//--- go to the nation in the browser which the player is going to talk to ---//
1031 
1032 	int nationCount = nation_filter();
1033 
1034 	int i;
1035 	for( i=1 ; i<=nationCount ; i++ )
1036 	{
1037 		if( nation_filter(i) == withNationRecno )
1038 		{
1039 			browse_nation_recno = i;
1040 			break;
1041 		}
1042 	}
1043 
1044 	err_when( i>nationCount );
1045 
1046 	sys.set_view_mode(MODE_NATION);
1047 }
1048 //-------- End of function Info::player_reply_chat ---------//
1049 
1050 
1051 //-------- Begin of static function put_heading --------//
1052 //
put_heading(char justify,int x1,int y1,int x2,int y2,const char * textPtr)1053 static void put_heading(char justify, int x1, int y1, int x2, int y2, const char *textPtr)
1054 {
1055 	int dispLines=0;
1056 	int totalLines=0;
1057 	font_san.count_line(x1,y1,x2,y2,textPtr,0,dispLines,totalLines);
1058 	if( dispLines > 1 )
1059 		font_san.put_paragraph(x1,y1,x2,y2,textPtr,-1,1,1,justify);
1060 	else if( y1+7<y2 )
1061 		font_san.put_paragraph(x1,y1+7,x2,y2,textPtr,-1,1,1,justify);
1062 }
1063 //----------- End of static function put_heading -----------//
1064 
1065 
1066 #define ASCII_ZERO 0x30
1067 //----- Begin of static function nation_color_code_str ------//
1068 //
nation_color_code_str(int nationRecno)1069 static char* nation_color_code_str(int nationRecno)
1070 {
1071 	static char colorCodeStr[] = " @COL0";
1072 
1073 	colorCodeStr[5] = ASCII_ZERO + nation_array[nationRecno]->color_scheme_id;
1074 	return colorCodeStr;
1075 }
1076 //------- End of static function nation_color_code_str ------//
1077