1 /***********************************************************************
2 Freeciv - Copyright (C) 1996-2006 - Freeciv Development Team
3 This program is free software; you can redistribute it and/or modify
4 it under the terms of the GNU General Public License as published by
5 the Free Software Foundation; either version 2, or (at your option)
6 any later version.
7
8 This program is distributed in the hope that it will be useful,
9 but WITHOUT ANY WARRANTY; without even the implied warranty of
10 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11 GNU General Public License for more details.
12 ***********************************************************************/
13
14 #ifdef HAVE_CONFIG_H
15 #include <fc_config.h>
16 #endif
17
18 /* utility */
19 #include "astring.h"
20 #include "fcintl.h"
21 #include "log.h"
22
23 /* common */
24 #include "actions.h"
25 #include "game.h"
26 #include "movement.h"
27 #include "research.h"
28 #include "traderoutes.h"
29 #include "unitlist.h"
30
31 /* client */
32 #include "client_main.h"
33 #include "climisc.h"
34 #include "control.h"
35 #include "text.h"
36
37 /* client/gui-sdl2 */
38 #include "citydlg.h"
39 #include "colors.h"
40 #include "dialogs.h"
41 #include "graphics.h"
42 #include "gui_id.h"
43 #include "gui_tilespec.h"
44 #include "mapview.h"
45 #include "repodlgs.h"
46 #include "themespec.h"
47 #include "widget.h"
48
49 #include "dialogs_g.h"
50
51 typedef int (*act_func)(struct widget *);
52
53 struct diplomat_dialog {
54 int actor_unit_id;
55 int target_ids[ATK_COUNT];
56 struct ADVANCED_DLG *pdialog;
57 };
58
59 struct small_diplomat_dialog {
60 int actor_unit_id;
61 int target_id;
62 struct SMALL_DLG *pdialog;
63 };
64
65 extern bool is_unit_move_blocked;
66
67 void popdown_diplomat_dialog(void);
68 void popdown_incite_dialog(void);
69 void popdown_bribe_dialog(void);
70
71
72 static struct diplomat_dialog *pDiplomat_Dlg = NULL;
73 static bool is_more_user_input_needed = FALSE;
74 static bool did_not_decide = FALSE;
75
76 /**************************************************************************
77 The action selection is done.
78 **************************************************************************/
act_sel_done_primary(int actor_unit_id)79 static void act_sel_done_primary(int actor_unit_id)
80 {
81 if (!is_more_user_input_needed) {
82 /* The client isn't waiting for information for any unanswered follow
83 * up questions. */
84
85 struct unit *actor_unit;
86
87 if ((actor_unit = game_unit_by_number(actor_unit_id))) {
88 /* The action selection dialog wasn't closed because the actor unit
89 * was lost. */
90
91 /* The probabilities didn't just disappear, right? */
92 fc_assert_action(actor_unit->client.act_prob_cache,
93 client_unit_init_act_prob_cache(actor_unit));
94
95 FC_FREE(actor_unit->client.act_prob_cache);
96 }
97
98 /* The action selection process is over, at least for now. */
99 action_selection_no_longer_in_progress(actor_unit_id);
100
101 if (did_not_decide) {
102 /* The action selection dialog was closed but the player didn't
103 * decide what the unit should do. */
104
105 /* Reset so the next action selection dialog does the right thing. */
106 did_not_decide = FALSE;
107 } else {
108 /* An action, or no action at all, was selected. */
109 action_decision_clear_want(actor_unit_id);
110 action_selection_next_in_focus(actor_unit_id);
111 }
112 }
113 }
114
115 /**************************************************************************
116 A follow up question about the selected action is done.
117 **************************************************************************/
act_sel_done_secondary(int actor_unit_id)118 static void act_sel_done_secondary(int actor_unit_id)
119 {
120 /* Stop blocking. */
121 is_more_user_input_needed = FALSE;
122 act_sel_done_primary(actor_unit_id);
123 }
124
125 /**************************************************************************
126 Let the non shared client code know that the action selection process
127 no longer is in progress for the specified unit.
128
129 This allows the client to clean up any client specific assumptions.
130 **************************************************************************/
action_selection_no_longer_in_progress_gui_specific(int actor_id)131 void action_selection_no_longer_in_progress_gui_specific(int actor_id)
132 {
133 /* Stop assuming the answer to a follow up question will arrive. */
134 is_more_user_input_needed = FALSE;
135 }
136
137 /* ====================================================================== */
138 /* ============================ CARAVAN DIALOG ========================== */
139 /* ====================================================================== */
140
141 /****************************************************************
142 User selected that caravan should enter marketplace.
143 *****************************************************************/
caravan_marketplace_callback(struct widget * pWidget)144 static int caravan_marketplace_callback(struct widget *pWidget)
145 {
146 if (PRESSED_EVENT(Main.event)) {
147 if (NULL != game_city_by_number(
148 pDiplomat_Dlg->target_ids[ATK_CITY])
149 && NULL != game_unit_by_number(pDiplomat_Dlg->actor_unit_id)) {
150 request_do_action(ACTION_MARKETPLACE,
151 pDiplomat_Dlg->actor_unit_id,
152 pDiplomat_Dlg->target_ids[ATK_CITY],
153 0);
154 }
155
156 popdown_diplomat_dialog();
157 }
158
159 return -1;
160 }
161
162 /****************************************************************
163 User selected that caravan should establish traderoute.
164 *****************************************************************/
caravan_establish_trade_callback(struct widget * pWidget)165 static int caravan_establish_trade_callback(struct widget *pWidget)
166 {
167 if (PRESSED_EVENT(Main.event)) {
168 if (NULL != game_city_by_number(
169 pDiplomat_Dlg->target_ids[ATK_CITY])
170 && NULL != game_unit_by_number(pDiplomat_Dlg->actor_unit_id)) {
171 request_do_action(ACTION_TRADE_ROUTE,
172 pDiplomat_Dlg->actor_unit_id,
173 pDiplomat_Dlg->target_ids[ATK_CITY],
174 0);
175 }
176
177 popdown_diplomat_dialog();
178 }
179
180 return -1;
181 }
182
183 /****************************************************************
184 User selected that caravan should help in wonder building.
185 *****************************************************************/
caravan_help_build_wonder_callback(struct widget * pWidget)186 static int caravan_help_build_wonder_callback(struct widget *pWidget)
187 {
188 if (PRESSED_EVENT(Main.event)) {
189 if (NULL != game_city_by_number(
190 pDiplomat_Dlg->target_ids[ATK_CITY])
191 && NULL != game_unit_by_number(pDiplomat_Dlg->actor_unit_id)) {
192 request_do_action(ACTION_HELP_WONDER,
193 pDiplomat_Dlg->actor_unit_id,
194 pDiplomat_Dlg->target_ids[ATK_CITY],
195 0);
196 }
197
198 popdown_diplomat_dialog();
199 }
200
201 return -1;
202 }
203
204 /* ====================================================================== */
205 /* ============================ DIPLOMAT DIALOG ========================= */
206 /* ====================================================================== */
207
208 /****************************************************************
209 User interacted with diplomat dialog.
210 *****************************************************************/
diplomat_dlg_window_callback(struct widget * pWindow)211 static int diplomat_dlg_window_callback(struct widget *pWindow)
212 {
213 if (PRESSED_EVENT(Main.event)) {
214 move_window_group(pDiplomat_Dlg->pdialog->pBeginWidgetList, pWindow);
215 }
216
217 return -1;
218 }
219
220 /****************************************************************
221 User clicked "Establish Embassy"
222 *****************************************************************/
diplomat_embassy_callback(struct widget * pWidget)223 static int diplomat_embassy_callback(struct widget *pWidget)
224 {
225 if (PRESSED_EVENT(Main.event)) {
226 if (NULL != game_city_by_number(
227 pDiplomat_Dlg->target_ids[ATK_CITY])
228 && NULL != game_unit_by_number(pDiplomat_Dlg->actor_unit_id)) {
229 request_do_action(ACTION_ESTABLISH_EMBASSY,
230 pDiplomat_Dlg->actor_unit_id,
231 pDiplomat_Dlg->target_ids[ATK_CITY],
232 0);
233 }
234
235 popdown_diplomat_dialog();
236 }
237
238 return -1;
239 }
240
241 /****************************************************************
242 User clicked "Investigate City"
243 *****************************************************************/
diplomat_investigate_callback(struct widget * pWidget)244 static int diplomat_investigate_callback(struct widget *pWidget)
245 {
246 if (PRESSED_EVENT(Main.event)) {
247 if (NULL != game_unit_by_number(pDiplomat_Dlg->actor_unit_id)
248 && NULL != game_city_by_number(
249 pDiplomat_Dlg->target_ids[ATK_CITY])) {
250 request_do_action(ACTION_SPY_INVESTIGATE_CITY,
251 pDiplomat_Dlg->actor_unit_id,
252 pDiplomat_Dlg->target_ids[ATK_CITY],
253 0);
254 }
255
256 /* FIXME: Wait for the city display in stead? */
257 popdown_diplomat_dialog();
258 }
259
260 return -1;
261 }
262
263 /****************************************************************
264 User clicked "Poison City"
265 *****************************************************************/
spy_poison_callback(struct widget * pWidget)266 static int spy_poison_callback(struct widget *pWidget)
267 {
268 if (PRESSED_EVENT(Main.event)) {
269 if (NULL != game_unit_by_number(pDiplomat_Dlg->actor_unit_id)
270 && NULL != game_city_by_number(
271 pDiplomat_Dlg->target_ids[ATK_CITY])) {
272 request_do_action(ACTION_SPY_POISON, pDiplomat_Dlg->actor_unit_id,
273 pDiplomat_Dlg->target_ids[ATK_CITY],
274 0);
275 }
276
277 popdown_diplomat_dialog();
278 }
279
280 return -1;
281 }
282
283 /********************************************************************
284 User clicked "Steal Gold"
285 ********************************************************************/
spy_steal_gold_callback(struct widget * pWidget)286 static int spy_steal_gold_callback(struct widget *pWidget)
287 {
288 if (PRESSED_EVENT(Main.event)) {
289 if (NULL != game_unit_by_number(pDiplomat_Dlg->actor_unit_id)
290 && NULL != game_city_by_number(
291 pDiplomat_Dlg->target_ids[ATK_CITY])) {
292 request_do_action(ACTION_SPY_STEAL_GOLD,
293 pDiplomat_Dlg->actor_unit_id,
294 pDiplomat_Dlg->target_ids[ATK_CITY],
295 0);
296 }
297
298 popdown_diplomat_dialog();
299 }
300
301 return -1;
302 }
303
304 /****************************************************************
305 Requests up-to-date list of improvements, the return of
306 which will trigger the popup_sabotage_dialog() function.
307 *****************************************************************/
spy_sabotage_request(struct widget * pWidget)308 static int spy_sabotage_request(struct widget *pWidget)
309 {
310 if (NULL != game_unit_by_number(pDiplomat_Dlg->actor_unit_id)
311 && NULL != game_city_by_number(
312 pDiplomat_Dlg->target_ids[ATK_CITY])) {
313 request_action_details(ACTION_SPY_TARGETED_SABOTAGE_CITY,
314 pDiplomat_Dlg->actor_unit_id,
315 pDiplomat_Dlg->target_ids[ATK_CITY]);
316 is_more_user_input_needed = TRUE;
317 popdown_diplomat_dialog();
318 } else {
319 popdown_diplomat_dialog();
320 }
321
322 return -1;
323 }
324
325 /****************************************************************
326 User clicked "Sabotage City" for diplomat (not spy)
327 *****************************************************************/
diplomat_sabotage_callback(struct widget * pWidget)328 static int diplomat_sabotage_callback(struct widget *pWidget)
329 {
330 if (PRESSED_EVENT(Main.event)) {
331 if (NULL != game_unit_by_number(pDiplomat_Dlg->actor_unit_id)
332 && NULL != game_city_by_number(
333 pDiplomat_Dlg->target_ids[ATK_CITY])) {
334 request_do_action(ACTION_SPY_SABOTAGE_CITY,
335 pDiplomat_Dlg->actor_unit_id,
336 pDiplomat_Dlg->target_ids[ATK_CITY],
337 B_LAST + 1);
338 }
339
340 popdown_diplomat_dialog();
341 }
342
343 return -1;
344 }
345
346 /* --------------------------------------------------------- */
347
348 /****************************************************************
349 User interacted with spy's steal dialog window.
350 *****************************************************************/
spy_steal_dlg_window_callback(struct widget * pWindow)351 static int spy_steal_dlg_window_callback(struct widget *pWindow)
352 {
353 if (PRESSED_EVENT(Main.event)) {
354 move_window_group(pDiplomat_Dlg->pdialog->pBeginWidgetList, pWindow);
355 }
356
357 return -1;
358 }
359
360 /****************************************************************
361 Exit spy's steal or sabotage dialog.
362 *****************************************************************/
exit_spy_tgt_dlg_callback(struct widget * pWidget)363 static int exit_spy_tgt_dlg_callback(struct widget *pWidget)
364 {
365 if (PRESSED_EVENT(Main.event)) {
366 int actor_id = pDiplomat_Dlg->actor_unit_id;
367
368 fc_assert(is_more_user_input_needed);
369 popdown_diplomat_dialog();
370 act_sel_done_secondary(actor_id);
371 }
372
373 return -1;
374 }
375
376 /****************************************************************
377 User selected which tech spy steals.
378 *****************************************************************/
spy_steal_callback(struct widget * pWidget)379 static int spy_steal_callback(struct widget *pWidget)
380 {
381 if (PRESSED_EVENT(Main.event)) {
382 int steal_advance = MAX_ID - pWidget->ID;
383 int actor_id = pDiplomat_Dlg->actor_unit_id;
384
385 if (NULL != game_unit_by_number(pDiplomat_Dlg->actor_unit_id)
386 && NULL != game_city_by_number(
387 pDiplomat_Dlg->target_ids[ATK_CITY])) {
388 if (steal_advance == A_UNSET) {
389 /* This is the untargeted version. */
390 request_do_action(ACTION_SPY_STEAL_TECH,
391 pDiplomat_Dlg->actor_unit_id,
392 pDiplomat_Dlg->target_ids[ATK_CITY],
393 steal_advance);
394 } else {
395 /* This is the targeted version. */
396 request_do_action(ACTION_SPY_TARGETED_STEAL_TECH,
397 pDiplomat_Dlg->actor_unit_id,
398 pDiplomat_Dlg->target_ids[ATK_CITY],
399 steal_advance);
400 }
401 }
402
403 fc_assert(is_more_user_input_needed);
404 popdown_diplomat_dialog();
405 act_sel_done_secondary(actor_id);
406 }
407
408 return -1;
409 }
410
411 /**************************************************************************
412 Popup spy tech stealing dialog.
413 **************************************************************************/
spy_steal_popup(struct widget * pWidget)414 static int spy_steal_popup(struct widget *pWidget)
415 {
416 const struct research *presearch, *vresearch;
417 struct city *pVcity = pWidget->data.city;
418 int id = MAX_ID - pWidget->ID;
419 struct player *pVictim = NULL;
420 struct CONTAINER *pCont;
421 struct widget *pBuf = NULL;
422 struct widget *pWindow;
423 utf8_str *pstr;
424 SDL_Surface *pSurf;
425 int max_col, max_row, col, count = 0;
426 int tech, idx;
427 SDL_Rect area;
428
429 struct unit *actor_unit = game_unit_by_number(id);
430
431 is_more_user_input_needed = TRUE;
432 popdown_diplomat_dialog();
433
434 if (pVcity) {
435 pVictim = city_owner(pVcity);
436 }
437
438 fc_assert_ret_val_msg(!pDiplomat_Dlg, 1, "Diplomat dialog already open");
439
440 if (!pVictim) {
441 act_sel_done_secondary(id);
442 return 1;
443 }
444
445 count = 0;
446 presearch = research_get(client_player());
447 vresearch = research_get(pVictim);
448 advance_index_iterate(A_FIRST, i) {
449 if (research_invention_gettable(presearch, i,
450 game.info.tech_steal_allow_holes)
451 && TECH_KNOWN == research_invention_state(vresearch, i)
452 && TECH_KNOWN != research_invention_state(presearch, i)) {
453 count++;
454 }
455 } advance_index_iterate_end;
456
457 if (!count) {
458 /* if there is no known tech to steal then
459 * send steal order at Spy's Discretion */
460 int target_id = pVcity->id;
461
462 request_do_action(ACTION_SPY_STEAL_TECH,
463 id, target_id, A_UNSET);
464
465 act_sel_done_secondary(id);
466
467 return -1;
468 }
469
470 pCont = fc_calloc(1, sizeof(struct CONTAINER));
471 pCont->id0 = pVcity->id;
472 pCont->id1 = id;/* spy id */
473
474 pDiplomat_Dlg = fc_calloc(1, sizeof(struct diplomat_dialog));
475 pDiplomat_Dlg->actor_unit_id = id;
476 pDiplomat_Dlg->target_ids[ATK_CITY] = pVcity->id;
477 pDiplomat_Dlg->pdialog = fc_calloc(1, sizeof(struct ADVANCED_DLG));
478
479 pstr = create_utf8_from_char(_("Select Advance to Steal"), adj_font(12));
480 pstr->style |= TTF_STYLE_BOLD;
481
482 pWindow = create_window_skeleton(NULL, pstr, 0);
483
484 pWindow->action = spy_steal_dlg_window_callback;
485 set_wstate(pWindow , FC_WS_NORMAL);
486
487 add_to_gui_list(ID_DIPLOMAT_DLG_WINDOW, pWindow);
488 pDiplomat_Dlg->pdialog->pEndWidgetList = pWindow;
489
490 area = pWindow->area;
491 area.w = MAX(area.w, adj_size(8));
492
493 /* ------------------ */
494 /* exit button */
495 pBuf = create_themeicon(current_theme->Small_CANCEL_Icon, pWindow->dst,
496 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
497 pBuf->info_label = create_utf8_from_char(_("Close Dialog (Esc)"),
498 adj_font(12));
499 area.w += pBuf->size.w + adj_size(10);
500 pBuf->action = exit_spy_tgt_dlg_callback;
501 set_wstate(pBuf, FC_WS_NORMAL);
502 pBuf->key = SDLK_ESCAPE;
503
504 add_to_gui_list(ID_TERRAIN_ADV_DLG_EXIT_BUTTON, pBuf);
505 /* ------------------------- */
506
507 if (action_prob_possible(
508 actor_unit->client.act_prob_cache[ACTION_SPY_STEAL_TECH])) {
509 /* count + at Spy's Discretion */
510 count++;
511 }
512
513 /* max col - 104 is steal tech widget width */
514 max_col = (main_window_width() - (pWindow->size.w - pWindow->area.w) - adj_size(2)) / adj_size(104);
515 /* max row - 204 is steal tech widget height */
516 max_row = (main_window_height() - (pWindow->size.h - pWindow->area.h)) / adj_size(204);
517
518 /* make space on screen for scrollbar */
519 if (max_col * max_row < count) {
520 max_col--;
521 }
522
523 if (count < max_col + 1) {
524 col = count;
525 } else {
526 if (count < max_col + adj_size(3)) {
527 col = max_col - adj_size(2);
528 } else {
529 if (count < max_col + adj_size(5)) {
530 col = max_col - 1;
531 } else {
532 col = max_col;
533 }
534 }
535 }
536
537 pstr = create_utf8_str(NULL, 0, adj_font(10));
538 pstr->style |= (TTF_STYLE_BOLD | SF_CENTER);
539
540 count = 0;
541 advance_index_iterate(A_FIRST, i) {
542 if (research_invention_gettable(presearch, i,
543 game.info.tech_steal_allow_holes)
544 && TECH_KNOWN == research_invention_state(vresearch, i)
545 && TECH_KNOWN != research_invention_state(presearch, i)) {
546 count++;
547
548 copy_chars_to_utf8_str(pstr, advance_name_translation(advance_by_number(i)));
549 pSurf = create_select_tech_icon(pstr, i, FULL_MODE);
550 pBuf = create_icon2(pSurf, pWindow->dst,
551 WF_FREE_THEME | WF_RESTORE_BACKGROUND);
552
553 set_wstate(pBuf, FC_WS_NORMAL);
554 pBuf->action = spy_steal_callback;
555 pBuf->data.cont = pCont;
556
557 add_to_gui_list(MAX_ID - i, pBuf);
558
559 if (count > (col * max_row)) {
560 set_wflag(pBuf, WF_HIDDEN);
561 }
562 }
563 } advance_index_iterate_end;
564
565 /* Get Spy tech to use for "At Spy's Discretion" -- this will have the
566 * side effect of displaying the unit's icon */
567 tech = advance_number(unit_type_get(actor_unit)->require_advance);
568
569 if (action_prob_possible(
570 actor_unit->client.act_prob_cache[ACTION_SPY_STEAL_TECH])) {
571 struct astring str = ASTRING_INIT;
572
573 /* TRANS: %s is a unit name, e.g., Spy */
574 astr_set(&str, _("At %s's Discretion"),
575 unit_name_translation(actor_unit));
576 copy_chars_to_utf8_str(pstr, astr_str(&str));
577 astr_free(&str);
578
579 pSurf = create_select_tech_icon(pstr, tech, FULL_MODE);
580
581 pBuf = create_icon2(pSurf, pWindow->dst,
582 (WF_FREE_THEME | WF_RESTORE_BACKGROUND
583 | WF_FREE_DATA));
584 set_wstate(pBuf, FC_WS_NORMAL);
585 pBuf->action = spy_steal_callback;
586 pBuf->data.cont = pCont;
587
588 add_to_gui_list(MAX_ID - A_UNSET, pBuf);
589 count++;
590 }
591
592 /* --------------------------------------------------------- */
593 FREEUTF8STR(pstr);
594 pDiplomat_Dlg->pdialog->pBeginWidgetList = pBuf;
595 pDiplomat_Dlg->pdialog->pBeginActiveWidgetList = pDiplomat_Dlg->pdialog->pBeginWidgetList;
596 pDiplomat_Dlg->pdialog->pEndActiveWidgetList = pDiplomat_Dlg->pdialog->pEndWidgetList->prev->prev;
597
598 /* -------------------------------------------------------------- */
599
600 idx = 0;
601 if (count > col) {
602 count = (count + (col - 1)) / col;
603 if (count > max_row) {
604 pDiplomat_Dlg->pdialog->pActiveWidgetList = pDiplomat_Dlg->pdialog->pEndActiveWidgetList;
605 count = max_row;
606 idx = create_vertical_scrollbar(pDiplomat_Dlg->pdialog, col, count, TRUE, TRUE);
607 }
608 } else {
609 count = 1;
610 }
611
612 area.w = MAX(area.w, (col * pBuf->size.w + adj_size(2) + idx));
613 area.h = count * pBuf->size.h + adj_size(2);
614
615 /* alloca window theme and win background buffer */
616 pSurf = theme_get_background(theme, BACKGROUND_SPYSTEALDLG);
617 if (resize_window(pWindow, pSurf, NULL,
618 (pWindow->size.w - pWindow->area.w) + area.w,
619 (pWindow->size.h - pWindow->area.h) + area.h)) {
620 FREESURFACE(pSurf);
621 }
622
623 area = pWindow->area;
624
625 widget_set_position(pWindow,
626 (main_window_width() - pWindow->size.w) / 2,
627 (main_window_height() - pWindow->size.h) / 2);
628
629 /* exit button */
630 pBuf = pWindow->prev;
631 pBuf->size.x = area.x + area.w - pBuf->size.w - 1;
632 pBuf->size.y = pWindow->size.y + adj_size(2);
633
634 setup_vertical_widgets_position(col, area.x + 1,
635 area.y, 0, 0,
636 pDiplomat_Dlg->pdialog->pBeginActiveWidgetList,
637 pDiplomat_Dlg->pdialog->pEndActiveWidgetList);
638
639 if (pDiplomat_Dlg->pdialog->pScroll) {
640 setup_vertical_scrollbar_area(pDiplomat_Dlg->pdialog->pScroll,
641 area.x + area.w, area.y,
642 area.h, TRUE);
643 }
644
645 redraw_group(pDiplomat_Dlg->pdialog->pBeginWidgetList, pWindow, FALSE);
646 widget_mark_dirty(pWindow);
647
648 return -1;
649 }
650
651 /****************************************************************
652 Technology stealing dialog, diplomat (not spy) version
653 *****************************************************************/
diplomat_steal_callback(struct widget * pWidget)654 static int diplomat_steal_callback(struct widget *pWidget)
655 {
656 if (PRESSED_EVENT(Main.event)) {
657 if (NULL != game_unit_by_number(pDiplomat_Dlg->actor_unit_id)
658 && NULL != game_city_by_number(
659 pDiplomat_Dlg->target_ids[ATK_CITY])) {
660 request_do_action(ACTION_SPY_STEAL_TECH,
661 pDiplomat_Dlg->actor_unit_id,
662 pDiplomat_Dlg->target_ids[ATK_CITY],
663 A_UNSET);
664 }
665
666 popdown_diplomat_dialog();
667 }
668
669 return -1;
670 }
671
672 /****************************************************************
673 ... Ask the server how much the revolt is going to cost us
674 *****************************************************************/
diplomat_incite_callback(struct widget * pWidget)675 static int diplomat_incite_callback(struct widget *pWidget)
676 {
677 if (PRESSED_EVENT(Main.event)) {
678 if (NULL != game_unit_by_number(pDiplomat_Dlg->actor_unit_id)
679 && NULL != game_city_by_number(
680 pDiplomat_Dlg->target_ids[ATK_CITY])) {
681 request_action_details(ACTION_SPY_INCITE_CITY,
682 pDiplomat_Dlg->actor_unit_id,
683 pDiplomat_Dlg->target_ids[ATK_CITY]);
684 is_more_user_input_needed = TRUE;
685 popdown_diplomat_dialog();
686 } else {
687 popdown_diplomat_dialog();
688 }
689 }
690
691 return -1;
692 }
693
694 /********************************************************************
695 Callback from action selection dialog for "keep moving".
696 (This should only occur when entering a tile with an allied city
697 or an allied unit.)
698 *********************************************************************/
act_sel_keep_moving_callback(struct widget * pWidget)699 static int act_sel_keep_moving_callback(struct widget *pWidget)
700 {
701 if (PRESSED_EVENT(Main.event)) {
702 struct unit *punit;
703
704 if ((punit = game_unit_by_number(pDiplomat_Dlg->actor_unit_id))
705 && !same_pos(unit_tile(punit), pWidget->data.tile)) {
706 request_unit_non_action_move(punit, pWidget->data.tile);
707 }
708
709 popdown_diplomat_dialog();
710 }
711
712 return -1;
713 }
714
715 /********************************************************************
716 Delay selection of what action to take.
717 *********************************************************************/
act_sel_wait_callback(struct widget * pWidget)718 static int act_sel_wait_callback(struct widget *pWidget)
719 {
720 if (PRESSED_EVENT(Main.event)) {
721 key_unit_wait();
722
723 /* The dialog was popped down when key_unit_wait() resulted in
724 * action_selection_close() being called. */
725 }
726
727 return -1;
728 }
729
730 /****************************************************************
731 ... Ask the server how much the bribe is
732 *****************************************************************/
diplomat_bribe_callback(struct widget * pWidget)733 static int diplomat_bribe_callback(struct widget *pWidget)
734 {
735 if (PRESSED_EVENT(Main.event)) {
736 if (NULL != game_unit_by_number(pDiplomat_Dlg->actor_unit_id)
737 && NULL !=
738 game_unit_by_number(pDiplomat_Dlg->target_ids[ATK_UNIT])) {
739 request_action_details(ACTION_SPY_BRIBE_UNIT,
740 pDiplomat_Dlg->actor_unit_id,
741 pDiplomat_Dlg->target_ids[ATK_UNIT]);
742 is_more_user_input_needed = TRUE;
743 popdown_diplomat_dialog();
744 } else {
745 popdown_diplomat_dialog();
746 }
747 }
748
749 return -1;
750 }
751
752 /****************************************************************
753 User clicked "Sabotage Unit"
754 *****************************************************************/
spy_sabotage_unit_callback(struct widget * pWidget)755 static int spy_sabotage_unit_callback(struct widget *pWidget)
756 {
757 if (PRESSED_EVENT(Main.event)) {
758 int diplomat_id = MAX_ID - pWidget->ID;
759 int target_id = pWidget->data.unit->id;
760
761 popdown_diplomat_dialog();
762 request_do_action(ACTION_SPY_SABOTAGE_UNIT,
763 diplomat_id, target_id, 0);
764 }
765
766 return -1;
767 }
768
769 /****************************************************************
770 Close diplomat dialog.
771 *****************************************************************/
diplomat_close_callback(struct widget * pWidget)772 static int diplomat_close_callback(struct widget *pWidget)
773 {
774 if (PRESSED_EVENT(Main.event)) {
775 popdown_diplomat_dialog();
776 }
777
778 return -1;
779 }
780
781 /**************************************************************************
782 Popdown a dialog giving a diplomatic unit some options when moving into
783 the target tile.
784 **************************************************************************/
popdown_diplomat_dialog(void)785 void popdown_diplomat_dialog(void)
786 {
787 if (pDiplomat_Dlg) {
788 act_sel_done_primary(pDiplomat_Dlg->actor_unit_id);
789
790 is_unit_move_blocked = FALSE;
791 popdown_window_group_dialog(pDiplomat_Dlg->pdialog->pBeginWidgetList,
792 pDiplomat_Dlg->pdialog->pEndWidgetList);
793 FC_FREE(pDiplomat_Dlg->pdialog->pScroll);
794 FC_FREE(pDiplomat_Dlg->pdialog);
795 FC_FREE(pDiplomat_Dlg);
796 queue_flush();
797 }
798 }
799
800 /* Mapping from an action to the function to call when its button is
801 * pushed. */
802 static const act_func af_map[ACTION_COUNT] = {
803 /* Unit acting against a city target. */
804 [ACTION_ESTABLISH_EMBASSY] = diplomat_embassy_callback,
805 [ACTION_SPY_INVESTIGATE_CITY] = diplomat_investigate_callback,
806 [ACTION_SPY_POISON] = spy_poison_callback,
807 [ACTION_SPY_STEAL_GOLD] = spy_steal_gold_callback,
808 [ACTION_SPY_SABOTAGE_CITY] = diplomat_sabotage_callback,
809 [ACTION_SPY_TARGETED_SABOTAGE_CITY] = spy_sabotage_request,
810 [ACTION_SPY_STEAL_TECH] = diplomat_steal_callback,
811 [ACTION_SPY_TARGETED_STEAL_TECH] = spy_steal_popup,
812 [ACTION_SPY_INCITE_CITY] = diplomat_incite_callback,
813 [ACTION_TRADE_ROUTE] = caravan_establish_trade_callback,
814 [ACTION_MARKETPLACE] = caravan_marketplace_callback,
815 [ACTION_HELP_WONDER] = caravan_help_build_wonder_callback,
816
817 /* Unit acting against a unit target. */
818 [ACTION_SPY_BRIBE_UNIT] = diplomat_bribe_callback,
819 [ACTION_SPY_SABOTAGE_UNIT] = spy_sabotage_unit_callback
820 };
821
822 /**************************************************************************
823 Add an entry for an action in the action choice dialog.
824 **************************************************************************/
action_entry(const enum gen_action act,const struct act_prob * act_probs,struct unit * act_unit,struct city * tgt_city,struct unit * tgt_unit,struct widget * pWindow,SDL_Rect * area)825 static void action_entry(const enum gen_action act,
826 const struct act_prob *act_probs,
827 struct unit *act_unit,
828 struct city *tgt_city,
829 struct unit *tgt_unit,
830 struct widget *pWindow,
831 SDL_Rect *area)
832 {
833 struct widget *pBuf;
834 utf8_str *pstr;
835 const char *ui_name;
836
837 const char *custom = get_act_sel_action_custom_text(action_by_number(act),
838 act_probs[act],
839 act_unit,
840 tgt_city);
841
842 if (act == ACTION_SPY_SABOTAGE_CITY
843 && action_prob_possible(
844 act_probs[ACTION_SPY_TARGETED_SABOTAGE_CITY])) {
845 /* The player can select Sabotage City from the target selection dialog
846 * of Targeted Sabotage City. */
847 return;
848 }
849
850 if (act == ACTION_SPY_STEAL_TECH
851 && action_prob_possible(
852 act_probs[ACTION_SPY_TARGETED_STEAL_TECH])) {
853 /* The player can select Steal Tech from the target selection dialog of
854 * Targeted Steal Tech. */
855 return;
856 }
857
858 /* Don't show disabled actions */
859 if (!action_prob_possible(act_probs[act])) {
860 return;
861 }
862
863 ui_name = action_prepare_ui_name(act, "",
864 act_probs[act], custom);
865
866 create_active_iconlabel(pBuf, pWindow->dst, pstr,
867 ui_name, af_map[act]);
868
869 switch(action_id_get_target_kind(act)) {
870 case ATK_CITY:
871 pBuf->data.city = tgt_city;
872 break;
873 case ATK_UNIT:
874 pBuf->data.unit = tgt_unit;
875 break;
876 case ATK_COUNT:
877 fc_assert_msg(FALSE, "Unsupported target kind");
878 }
879
880 set_wstate(pBuf, FC_WS_NORMAL);
881
882 add_to_gui_list(MAX_ID - act_unit->id, pBuf);
883
884 area->w = MAX(area->w, pBuf->size.w);
885 area->h += pBuf->size.h;
886 }
887
888 /**************************************************************************
889 Popup a dialog that allows the player to select what action a unit
890 should take.
891 **************************************************************************/
popup_action_selection(struct unit * actor_unit,struct city * target_city,struct unit * target_unit,struct tile * target_tile,const struct act_prob * act_probs)892 void popup_action_selection(struct unit *actor_unit,
893 struct city *target_city,
894 struct unit *target_unit,
895 struct tile *target_tile,
896 const struct act_prob *act_probs)
897 {
898 struct widget *pWindow = NULL, *pBuf = NULL;
899 utf8_str *pstr;
900 SDL_Rect area;
901
902 fc_assert_ret_msg(!pDiplomat_Dlg, "Diplomat dialog already open");
903
904 /* Could be caused by the server failing to reply to a request for more
905 * information or a bug in the client code. */
906 fc_assert_msg(!is_more_user_input_needed,
907 "Diplomat queue problem. Is another diplomat window open?");
908
909 /* No extra input is required as no action has been chosen yet. */
910 is_more_user_input_needed = FALSE;
911
912 is_unit_move_blocked = TRUE;
913
914 pDiplomat_Dlg = fc_calloc(1, sizeof(struct diplomat_dialog));
915 pDiplomat_Dlg->actor_unit_id = actor_unit->id;
916 pDiplomat_Dlg->pdialog = fc_calloc(1, sizeof(struct ADVANCED_DLG));
917
918 /* window */
919 if (target_city) {
920 struct astring title = ASTRING_INIT;
921
922 /* TRANS: %s is a unit name, e.g., Spy */
923 astr_set(&title, _("Choose Your %s's Strategy"),
924 unit_name_translation(actor_unit));
925 pstr = create_utf8_from_char(astr_str(&title), adj_font(12));
926 astr_free(&title);
927 } else {
928 pstr = create_utf8_from_char(_("Subvert Enemy Unit"), adj_font(12));
929 }
930
931 pstr->style |= TTF_STYLE_BOLD;
932
933 pWindow = create_window_skeleton(NULL, pstr, 0);
934
935 pWindow->action = diplomat_dlg_window_callback;
936 set_wstate(pWindow, FC_WS_NORMAL);
937
938 add_to_gui_list(ID_CARAVAN_DLG_WINDOW, pWindow);
939 pDiplomat_Dlg->pdialog->pEndWidgetList = pWindow;
940
941 area = pWindow->area;
942 area.w = MAX(area.w, adj_size(8));
943 area.h = MAX(area.h, adj_size(2));
944
945 if (target_city) {
946 pDiplomat_Dlg->target_ids[ATK_CITY] = target_city->id;
947 } else {
948 pDiplomat_Dlg->target_ids[ATK_CITY] = IDENTITY_NUMBER_ZERO;
949 }
950
951 if (target_unit) {
952 pDiplomat_Dlg->target_ids[ATK_UNIT] = target_unit->id;
953 } else {
954 pDiplomat_Dlg->target_ids[ATK_UNIT] = IDENTITY_NUMBER_ZERO;
955 }
956
957 /* ---------- */
958 /* Unit acting against a city */
959
960 action_iterate(act) {
961 if (action_id_get_actor_kind(act) == AAK_UNIT
962 && action_id_get_target_kind(act) == ATK_CITY) {
963 action_entry(act, act_probs,
964 actor_unit, target_city, NULL,
965 pWindow, &area);
966 }
967 } action_iterate_end;
968
969 /* Unit acting against another unit */
970
971 action_iterate(act) {
972 if (action_id_get_actor_kind(act) == AAK_UNIT
973 && action_id_get_target_kind(act) == ATK_UNIT) {
974 action_entry(act, act_probs,
975 actor_unit, NULL, target_unit,
976 pWindow, &area);
977 }
978 } action_iterate_end;
979
980 /* ---------- */
981 if (unit_can_move_to_tile(actor_unit, target_tile, FALSE)
982 || (is_military_unit(actor_unit) || is_attack_unit(actor_unit))
983 || (can_unit_bombard(actor_unit) && !is_ocean_tile(target_tile))
984 || (!target_city && unit_has_type_flag(actor_unit, UTYF_CAPTURER))) {
985 create_active_iconlabel(pBuf, pWindow->dst, pstr,
986 _("Keep moving"),
987 act_sel_keep_moving_callback);
988
989 pBuf->data.tile = target_tile;
990
991 set_wstate(pBuf, FC_WS_NORMAL);
992
993 add_to_gui_list(MAX_ID - actor_unit->id, pBuf);
994
995 area.w = MAX(area.w, pBuf->size.w);
996 area.h += pBuf->size.h;
997 }
998
999 /* ---------- */
1000 create_active_iconlabel(pBuf, pWindow->dst, pstr,
1001 _("Wait"), act_sel_wait_callback);
1002
1003 pBuf->data.tile = target_tile;
1004
1005 set_wstate(pBuf, FC_WS_NORMAL);
1006
1007 add_to_gui_list(MAX_ID - actor_unit->id, pBuf);
1008
1009 area.w = MAX(area.w, pBuf->size.w);
1010 area.h += pBuf->size.h;
1011
1012 /* ---------- */
1013 create_active_iconlabel(pBuf, pWindow->dst, pstr,
1014 _("Cancel"), diplomat_close_callback);
1015
1016 set_wstate(pBuf , FC_WS_NORMAL);
1017 pBuf->key = SDLK_ESCAPE;
1018
1019 add_to_gui_list(ID_LABEL , pBuf);
1020
1021 area.w = MAX(area.w, pBuf->size.w);
1022 area.h += pBuf->size.h;
1023 /* ---------- */
1024 pDiplomat_Dlg->pdialog->pBeginWidgetList = pBuf;
1025
1026 /* setup window size and start position */
1027
1028 resize_window(pWindow, NULL, NULL,
1029 (pWindow->size.w - pWindow->area.w) + area.w,
1030 (pWindow->size.h - pWindow->area.h) + area.h);
1031
1032 area = pWindow->area;
1033
1034 auto_center_on_focus_unit();
1035 put_window_near_map_tile(pWindow, pWindow->size.w, pWindow->size.h,
1036 unit_tile(actor_unit));
1037
1038 /* setup widget size and start position */
1039
1040 pBuf = pWindow->prev;
1041 setup_vertical_widgets_position(1,
1042 area.x,
1043 area.y + 1, area.w, 0,
1044 pDiplomat_Dlg->pdialog->pBeginWidgetList, pBuf);
1045
1046 /* --------------------- */
1047 /* redraw */
1048 redraw_group(pDiplomat_Dlg->pdialog->pBeginWidgetList, pWindow, 0);
1049
1050 widget_flush(pWindow);
1051
1052 /* Give follow up questions access to action probabilities. */
1053 client_unit_init_act_prob_cache(actor_unit);
1054 action_iterate(act) {
1055 actor_unit->client.act_prob_cache[act] = act_probs[act];
1056 } action_iterate_end;
1057 }
1058
1059 /**************************************************************************
1060 Returns the id of the actor unit currently handled in action selection
1061 dialog when the action selection dialog is open.
1062 Returns IDENTITY_NUMBER_ZERO if no action selection dialog is open.
1063 **************************************************************************/
action_selection_actor_unit(void)1064 int action_selection_actor_unit(void)
1065 {
1066 if (!pDiplomat_Dlg) {
1067 return IDENTITY_NUMBER_ZERO;
1068 }
1069
1070 return pDiplomat_Dlg->actor_unit_id;
1071 }
1072
1073 /**************************************************************************
1074 Returns id of the target city of the actions currently handled in action
1075 selection dialog when the action selection dialog is open and it has a
1076 city target. Returns IDENTITY_NUMBER_ZERO if no action selection dialog
1077 is open or no city target is present in the action selection dialog.
1078 **************************************************************************/
action_selection_target_city(void)1079 int action_selection_target_city(void)
1080 {
1081 if (!pDiplomat_Dlg) {
1082 return IDENTITY_NUMBER_ZERO;
1083 }
1084
1085 return pDiplomat_Dlg->target_ids[ATK_CITY];
1086 }
1087
1088 /**************************************************************************
1089 Returns id of the target unit of the actions currently handled in action
1090 selection dialog when the action selection dialog is open and it has a
1091 unit target. Returns IDENTITY_NUMBER_ZERO if no action selection dialog
1092 is open or no unit target is present in the action selection dialog.
1093 **************************************************************************/
action_selection_target_unit(void)1094 int action_selection_target_unit(void)
1095 {
1096 if (!pDiplomat_Dlg) {
1097 return IDENTITY_NUMBER_ZERO;
1098 }
1099
1100 return pDiplomat_Dlg->target_ids[ATK_UNIT];
1101 }
1102
1103 /**************************************************************************
1104 Updates the action selection dialog with new information.
1105 **************************************************************************/
action_selection_refresh(struct unit * actor_unit,struct city * target_city,struct unit * target_unit,struct tile * target_tile,const struct act_prob * act_probs)1106 void action_selection_refresh(struct unit *actor_unit,
1107 struct city *target_city,
1108 struct unit *target_unit,
1109 struct tile *target_tile,
1110 const struct act_prob *act_probs)
1111 {
1112 action_selection_close();
1113 popup_action_selection(actor_unit,
1114 target_city, target_unit,
1115 target_tile,
1116 act_probs);
1117 }
1118
1119 /****************************************************************
1120 Closes the action selection dialog
1121 ****************************************************************/
action_selection_close(void)1122 void action_selection_close(void)
1123 {
1124 did_not_decide = TRUE;
1125 popdown_diplomat_dialog();
1126 }
1127
1128 /* ====================================================================== */
1129 /* ============================ SABOTAGE DIALOG ========================= */
1130 /* ====================================================================== */
1131
1132 /****************************************************************
1133 User selected what to sabotage.
1134 ****************************************************************/
sabotage_impr_callback(struct widget * pWidget)1135 static int sabotage_impr_callback(struct widget *pWidget)
1136 {
1137 if (PRESSED_EVENT(Main.event)) {
1138 int sabotage_improvement = MAX_ID - pWidget->ID;
1139 int diplomat_target_id = pWidget->data.cont->id0;
1140 int diplomat_id = pWidget->data.cont->id1;
1141
1142 fc_assert(is_more_user_input_needed);
1143 popdown_diplomat_dialog();
1144
1145 if (sabotage_improvement == 1000) {
1146 sabotage_improvement = -1;
1147 }
1148
1149 if (NULL != game_unit_by_number(diplomat_id)
1150 && NULL != game_city_by_number(diplomat_target_id)) {
1151 if (sabotage_improvement == B_LAST) {
1152 /* This is the untargeted version. */
1153 request_do_action(ACTION_SPY_SABOTAGE_CITY, diplomat_id,
1154 diplomat_target_id, sabotage_improvement + 1);
1155 } else {
1156 /* This is the targeted version. */
1157 request_do_action(ACTION_SPY_TARGETED_SABOTAGE_CITY, diplomat_id,
1158 diplomat_target_id, sabotage_improvement + 1);
1159 }
1160 }
1161
1162 act_sel_done_secondary(diplomat_id);
1163 }
1164
1165 return -1;
1166 }
1167
1168 /*************************************************************************
1169 Pops-up the Spy sabotage dialog, upon return of list of
1170 available improvements requested by the above function.
1171 **************************************************************************/
popup_sabotage_dialog(struct unit * actor,struct city * pCity)1172 void popup_sabotage_dialog(struct unit *actor, struct city *pCity)
1173 {
1174 struct widget *pWindow = NULL, *pBuf = NULL , *pLast = NULL;
1175 struct CONTAINER *pCont;
1176 utf8_str *pstr;
1177 SDL_Rect area, area2;
1178 int n, w = 0, h, imp_h = 0, y;
1179
1180 fc_assert_ret_msg(!pDiplomat_Dlg, "Diplomat dialog already open");
1181
1182 /* Should be set before sending request to the server. */
1183 fc_assert(is_more_user_input_needed);
1184
1185 if (!actor) {
1186 act_sel_done_secondary(IDENTITY_NUMBER_ZERO);
1187 return;
1188 }
1189
1190 is_unit_move_blocked = TRUE;
1191
1192 pDiplomat_Dlg = fc_calloc(1, sizeof(struct diplomat_dialog));
1193 pDiplomat_Dlg->actor_unit_id = actor->id;
1194 pDiplomat_Dlg->target_ids[ATK_CITY] = pCity->id;
1195 pDiplomat_Dlg->pdialog = fc_calloc(1, sizeof(struct ADVANCED_DLG));
1196
1197 pCont = fc_calloc(1, sizeof(struct CONTAINER));
1198 pCont->id0 = pCity->id;
1199 pCont->id1 = actor->id; /* spy id */
1200
1201 pstr = create_utf8_from_char(_("Select Improvement to Sabotage") , adj_font(12));
1202 pstr->style |= TTF_STYLE_BOLD;
1203
1204 pWindow = create_window_skeleton(NULL, pstr, 0);
1205
1206 pWindow->action = diplomat_dlg_window_callback;
1207 set_wstate(pWindow, FC_WS_NORMAL);
1208
1209 add_to_gui_list(ID_TERRAIN_ADV_DLG_WINDOW, pWindow);
1210 pDiplomat_Dlg->pdialog->pEndWidgetList = pWindow;
1211
1212 area = pWindow->area;
1213 area.h = MAX(area.h, adj_size(2));
1214
1215 /* ---------- */
1216 /* exit button */
1217 pBuf = create_themeicon(current_theme->Small_CANCEL_Icon, pWindow->dst,
1218 WF_WIDGET_HAS_INFO_LABEL | WF_RESTORE_BACKGROUND);
1219 pBuf->info_label = create_utf8_from_char(_("Close Dialog (Esc)"),
1220 adj_font(12));
1221 area.w += pBuf->size.w + adj_size(10);
1222 pBuf->action = exit_spy_tgt_dlg_callback;
1223 set_wstate(pBuf, FC_WS_NORMAL);
1224 pBuf->key = SDLK_ESCAPE;
1225
1226 add_to_gui_list(ID_TERRAIN_ADV_DLG_EXIT_BUTTON, pBuf);
1227 /* ---------- */
1228
1229 create_active_iconlabel(pBuf, pWindow->dst, pstr,
1230 _("City Production"), sabotage_impr_callback);
1231 pBuf->data.cont = pCont;
1232 set_wstate(pBuf, FC_WS_NORMAL);
1233 set_wflag(pBuf, WF_FREE_DATA);
1234 add_to_gui_list(MAX_ID - 1000, pBuf);
1235
1236 area.w = MAX(area.w, pBuf->size.w);
1237 area.h += pBuf->size.h;
1238
1239 /* separator */
1240 pBuf = create_iconlabel(NULL, pWindow->dst, NULL, WF_FREE_THEME);
1241
1242 add_to_gui_list(ID_SEPARATOR, pBuf);
1243 area.h += pBuf->next->size.h;
1244
1245 pDiplomat_Dlg->pdialog->pEndActiveWidgetList = pBuf;
1246
1247 /* ------------------ */
1248 n = 0;
1249 city_built_iterate(pCity, pImprove) {
1250 if (pImprove->sabotage > 0) {
1251 create_active_iconlabel(pBuf, pWindow->dst, pstr,
1252 (char *) city_improvement_name_translation(pCity, pImprove),
1253 sabotage_impr_callback);
1254 pBuf->data.cont = pCont;
1255 set_wstate(pBuf, FC_WS_NORMAL);
1256
1257 add_to_gui_list(MAX_ID - improvement_number(pImprove), pBuf);
1258
1259 area.w = MAX(area.w , pBuf->size.w);
1260 imp_h += pBuf->size.h;
1261
1262 if (n > 9) {
1263 set_wflag(pBuf, WF_HIDDEN);
1264 }
1265
1266 n++;
1267 /* ----------- */
1268 }
1269 } city_built_iterate_end;
1270
1271 pDiplomat_Dlg->pdialog->pBeginActiveWidgetList = pBuf;
1272
1273 if (n > 0 && action_prob_possible(
1274 actor->client.act_prob_cache[ACTION_SPY_SABOTAGE_CITY])) {
1275 /* separator */
1276 pBuf = create_iconlabel(NULL, pWindow->dst, NULL, WF_FREE_THEME);
1277
1278 add_to_gui_list(ID_SEPARATOR, pBuf);
1279 area.h += pBuf->next->size.h;
1280 /* ------------------ */
1281 }
1282
1283 if (action_prob_possible(
1284 actor->client.act_prob_cache[ACTION_SPY_SABOTAGE_CITY])) {
1285 struct astring str = ASTRING_INIT;
1286
1287 /* TRANS: %s is a unit name, e.g., Spy */
1288 astr_set(&str, _("At %s's Discretion"), unit_name_translation(actor));
1289 create_active_iconlabel(pBuf, pWindow->dst, pstr, astr_str(&str),
1290 sabotage_impr_callback);
1291 astr_free(&str);
1292
1293 pBuf->data.cont = pCont;
1294 set_wstate(pBuf, FC_WS_NORMAL);
1295
1296 add_to_gui_list(MAX_ID - B_LAST, pBuf);
1297
1298 area.w = MAX(area.w, pBuf->size.w);
1299 area.h += pBuf->size.h;
1300 }
1301
1302 /* ----------- */
1303
1304 pLast = pBuf;
1305 pDiplomat_Dlg->pdialog->pBeginWidgetList = pLast;
1306 pDiplomat_Dlg->pdialog->pActiveWidgetList = pDiplomat_Dlg->pdialog->pEndActiveWidgetList;
1307
1308 /* ---------- */
1309 if (n > 10) {
1310 imp_h = 10 * pBuf->size.h;
1311
1312 n = create_vertical_scrollbar(pDiplomat_Dlg->pdialog,
1313 1, 10, TRUE, TRUE);
1314 area.w += n;
1315 } else {
1316 n = 0;
1317 }
1318 /* ---------- */
1319
1320 area.h += imp_h;
1321
1322 resize_window(pWindow, NULL, NULL,
1323 (pWindow->size.w - pWindow->area.w) + area.w,
1324 (pWindow->size.h - pWindow->area.h) + area.h);
1325
1326 area = pWindow->area;
1327
1328 auto_center_on_focus_unit();
1329 put_window_near_map_tile(pWindow, pWindow->size.w, pWindow->size.h,
1330 unit_tile(actor));
1331
1332 w = area.w;
1333
1334 /* exit button */
1335 pBuf = pWindow->prev;
1336 pBuf->size.x = area.x + area.w - pBuf->size.w - 1;
1337 pBuf->size.y = pWindow->size.y + adj_size(2);
1338
1339 /* Production sabotage */
1340 pBuf = pBuf->prev;
1341
1342 pBuf->size.x = area.x;
1343 pBuf->size.y = y = area.y + 1;
1344 pBuf->size.w = w;
1345 h = pBuf->size.h;
1346
1347 area2.x = adj_size(10);
1348 area2.h = adj_size(2);
1349
1350 pBuf = pBuf->prev;
1351 while (pBuf) {
1352 if (pBuf == pDiplomat_Dlg->pdialog->pEndActiveWidgetList) {
1353 w -= n;
1354 }
1355
1356 pBuf->size.w = w;
1357 pBuf->size.x = pBuf->next->size.x;
1358 pBuf->size.y = y = y + pBuf->next->size.h;
1359
1360 if (pBuf->ID == ID_SEPARATOR) {
1361 FREESURFACE(pBuf->theme);
1362 pBuf->size.h = h;
1363 pBuf->theme = create_surf(w, h, SDL_SWSURFACE);
1364
1365 area2.y = pBuf->size.h / 2 - 1;
1366 area2.w = pBuf->size.w - adj_size(20);
1367
1368 SDL_FillRect(pBuf->theme , &area2, map_rgba(pBuf->theme->format, *get_theme_color(COLOR_THEME_SABOTAGEDLG_SEPARATOR)));
1369 }
1370
1371 if (pBuf == pLast) {
1372 break;
1373 }
1374
1375 if (pBuf == pDiplomat_Dlg->pdialog->pBeginActiveWidgetList) {
1376 /* Reset to end of scrolling area */
1377 y = MIN(y, pDiplomat_Dlg->pdialog->pEndActiveWidgetList->size.y
1378 + 9 * pBuf->size.h);
1379 w += n;
1380 }
1381 pBuf = pBuf->prev;
1382 }
1383
1384 if (pDiplomat_Dlg->pdialog->pScroll) {
1385 setup_vertical_scrollbar_area(pDiplomat_Dlg->pdialog->pScroll,
1386 area.x + area.w,
1387 pDiplomat_Dlg->pdialog->pEndActiveWidgetList->size.y,
1388 pDiplomat_Dlg->pdialog->pBeginActiveWidgetList->prev->size.y
1389 - pDiplomat_Dlg->pdialog->pEndActiveWidgetList->size.y,
1390 TRUE);
1391 }
1392
1393 /* -------------------- */
1394 /* redraw */
1395 redraw_group(pDiplomat_Dlg->pdialog->pBeginWidgetList, pWindow, 0);
1396
1397 widget_flush(pWindow);
1398 }
1399
1400 /* ====================================================================== */
1401 /* ============================== INCITE DIALOG ========================= */
1402 /* ====================================================================== */
1403 static struct small_diplomat_dialog *pIncite_Dlg = NULL;
1404
1405 /****************************************************************
1406 User interacted with Incite Revolt dialog window.
1407 *****************************************************************/
incite_dlg_window_callback(struct widget * pWindow)1408 static int incite_dlg_window_callback(struct widget *pWindow)
1409 {
1410 if (PRESSED_EVENT(Main.event)) {
1411 move_window_group(pIncite_Dlg->pdialog->pBeginWidgetList, pWindow);
1412 }
1413
1414 return -1;
1415 }
1416
1417 /****************************************************************
1418 User confirmed incite
1419 *****************************************************************/
diplomat_incite_yes_callback(struct widget * pWidget)1420 static int diplomat_incite_yes_callback(struct widget *pWidget)
1421 {
1422 if (PRESSED_EVENT(Main.event)) {
1423 if (NULL != game_unit_by_number(pIncite_Dlg->actor_unit_id)
1424 && NULL != game_city_by_number(pIncite_Dlg->target_id)) {
1425 request_do_action(ACTION_SPY_INCITE_CITY, pIncite_Dlg->actor_unit_id,
1426 pIncite_Dlg->target_id, 0);
1427 }
1428
1429 popdown_incite_dialog();
1430 }
1431
1432 return -1;
1433 }
1434
1435 /****************************************************************
1436 Close incite dialog.
1437 *****************************************************************/
exit_incite_dlg_callback(struct widget * pWidget)1438 static int exit_incite_dlg_callback(struct widget *pWidget)
1439 {
1440 if (PRESSED_EVENT(Main.event)) {
1441 popdown_incite_dialog();
1442 }
1443
1444 return -1;
1445 }
1446
1447 /**************************************************************************
1448 Popdown a window asking a diplomatic unit if it wishes to incite the
1449 given enemy city.
1450 **************************************************************************/
popdown_incite_dialog(void)1451 void popdown_incite_dialog(void)
1452 {
1453 if (pIncite_Dlg) {
1454 act_sel_done_secondary(pIncite_Dlg->actor_unit_id);
1455
1456 is_unit_move_blocked = FALSE;
1457 popdown_window_group_dialog(pIncite_Dlg->pdialog->pBeginWidgetList,
1458 pIncite_Dlg->pdialog->pEndWidgetList);
1459 FC_FREE(pIncite_Dlg->pdialog);
1460 FC_FREE(pIncite_Dlg);
1461 flush_dirty();
1462 }
1463 }
1464
1465 /**************************************************************************
1466 Popup a window asking a diplomatic unit if it wishes to incite the
1467 given enemy city.
1468 **************************************************************************/
popup_incite_dialog(struct unit * actor,struct city * pCity,int cost)1469 void popup_incite_dialog(struct unit *actor, struct city *pCity, int cost)
1470 {
1471 struct widget *pWindow = NULL, *pBuf = NULL;
1472 utf8_str *pstr;
1473 char tBuf[255], cBuf[255];
1474 bool exit = FALSE;
1475 SDL_Rect area;
1476
1477 if (pIncite_Dlg) {
1478 return;
1479 }
1480
1481 /* Should be set before sending request to the server. */
1482 fc_assert(is_more_user_input_needed);
1483
1484 if (!actor || !unit_can_do_action(actor, ACTION_SPY_INCITE_CITY)) {
1485 act_sel_done_secondary(actor ? actor->id : IDENTITY_NUMBER_ZERO);
1486 return;
1487 }
1488
1489 is_unit_move_blocked = TRUE;
1490
1491 pIncite_Dlg = fc_calloc(1, sizeof(struct small_diplomat_dialog));
1492 pIncite_Dlg->actor_unit_id = actor->id;
1493 pIncite_Dlg->target_id = pCity->id;
1494 pIncite_Dlg->pdialog = fc_calloc(1, sizeof(struct SMALL_DLG));
1495
1496 fc_snprintf(tBuf, ARRAY_SIZE(tBuf), PL_("Treasury contains %d gold.",
1497 "Treasury contains %d gold.",
1498 client_player()->economic.gold),
1499 client_player()->economic.gold);
1500
1501 /* window */
1502 pstr = create_utf8_from_char(_("Incite a Revolt!"), adj_font(12));
1503
1504 pstr->style |= TTF_STYLE_BOLD;
1505
1506 pWindow = create_window_skeleton(NULL, pstr, 0);
1507
1508 pWindow->action = incite_dlg_window_callback;
1509 set_wstate(pWindow, FC_WS_NORMAL);
1510
1511 add_to_gui_list(ID_INCITE_DLG_WINDOW, pWindow);
1512 pIncite_Dlg->pdialog->pEndWidgetList = pWindow;
1513
1514 area = pWindow->area;
1515 area.w =MAX(area.w, adj_size(8));
1516 area.h = MAX(area.h, adj_size(2));
1517
1518 if (INCITE_IMPOSSIBLE_COST == cost) {
1519 /* exit button */
1520 pBuf = create_themeicon(current_theme->Small_CANCEL_Icon, pWindow->dst,
1521 WF_WIDGET_HAS_INFO_LABEL
1522 | WF_RESTORE_BACKGROUND);
1523 pBuf->info_label = create_utf8_from_char(_("Close Dialog (Esc)"),
1524 adj_font(12));
1525 area.w += pBuf->size.w + adj_size(10);
1526 pBuf->action = exit_incite_dlg_callback;
1527 set_wstate(pBuf, FC_WS_NORMAL);
1528 pBuf->key = SDLK_ESCAPE;
1529
1530 add_to_gui_list(ID_INCITE_DLG_EXIT_BUTTON, pBuf);
1531 exit = TRUE;
1532 /* --------------- */
1533
1534 fc_snprintf(cBuf, sizeof(cBuf), _("You can't incite a revolt in %s."),
1535 city_name_get(pCity));
1536
1537 create_active_iconlabel(pBuf, pWindow->dst, pstr, cBuf, NULL);
1538
1539 add_to_gui_list(ID_LABEL , pBuf);
1540
1541 area.w = MAX(area.w , pBuf->size.w);
1542 area.h += pBuf->size.h;
1543 /*------------*/
1544 create_active_iconlabel(pBuf, pWindow->dst, pstr,
1545 _("City can't be incited!"), NULL);
1546
1547 add_to_gui_list(ID_LABEL, pBuf);
1548
1549 area.w = MAX(area.w, pBuf->size.w);
1550 area.h += pBuf->size.h;
1551
1552 } else if (cost <= client_player()->economic.gold) {
1553 fc_snprintf(cBuf, sizeof(cBuf),
1554 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
1555 PL_("Incite a revolt for %d gold?\n%s",
1556 "Incite a revolt for %d gold?\n%s", cost), cost, tBuf);
1557
1558 create_active_iconlabel(pBuf, pWindow->dst, pstr, cBuf, NULL);
1559
1560 add_to_gui_list(ID_LABEL, pBuf);
1561
1562 area.w = MAX(area.w, pBuf->size.w);
1563 area.h += pBuf->size.h;
1564
1565 /*------------*/
1566 create_active_iconlabel(pBuf, pWindow->dst, pstr,
1567 _("Yes") , diplomat_incite_yes_callback);
1568
1569 pBuf->data.city = pCity;
1570 set_wstate(pBuf, FC_WS_NORMAL);
1571
1572 add_to_gui_list(MAX_ID - actor->id, pBuf);
1573
1574 area.w = MAX(area.w, pBuf->size.w);
1575 area.h += pBuf->size.h;
1576 /* ------- */
1577 create_active_iconlabel(pBuf, pWindow->dst, pstr,
1578 _("No") , exit_incite_dlg_callback);
1579
1580 set_wstate(pBuf, FC_WS_NORMAL);
1581 pBuf->key = SDLK_ESCAPE;
1582
1583 add_to_gui_list(ID_LABEL, pBuf);
1584
1585 area.w = MAX(area.w, pBuf->size.w);
1586 area.h += pBuf->size.h;
1587
1588 } else {
1589 /* exit button */
1590 pBuf = create_themeicon(current_theme->Small_CANCEL_Icon, pWindow->dst,
1591 WF_WIDGET_HAS_INFO_LABEL
1592 | WF_RESTORE_BACKGROUND);
1593 pBuf->info_label = create_utf8_from_char(_("Close Dialog (Esc)"),
1594 adj_font(12));
1595 area.w += pBuf->size.w + adj_size(10);
1596 pBuf->action = exit_incite_dlg_callback;
1597 set_wstate(pBuf, FC_WS_NORMAL);
1598 pBuf->key = SDLK_ESCAPE;
1599
1600 add_to_gui_list(ID_INCITE_DLG_EXIT_BUTTON, pBuf);
1601 exit = TRUE;
1602 /* --------------- */
1603
1604 fc_snprintf(cBuf, sizeof(cBuf),
1605 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
1606 PL_("Inciting a revolt costs %d gold.\n%s",
1607 "Inciting a revolt costs %d gold.\n%s", cost), cost, tBuf);
1608
1609 create_active_iconlabel(pBuf, pWindow->dst, pstr, cBuf, NULL);
1610
1611 add_to_gui_list(ID_LABEL, pBuf);
1612
1613 area.w = MAX(area.w, pBuf->size.w);
1614 area.h += pBuf->size.h;
1615
1616 /*------------*/
1617 create_active_iconlabel(pBuf, pWindow->dst, pstr,
1618 _("Traitors Demand Too Much!"), NULL);
1619
1620 add_to_gui_list(ID_LABEL, pBuf);
1621
1622 area.w = MAX(area.w, pBuf->size.w);
1623 area.h += pBuf->size.h;
1624 }
1625 pIncite_Dlg->pdialog->pBeginWidgetList = pBuf;
1626
1627 /* setup window size and start position */
1628
1629 resize_window(pWindow, NULL, NULL,
1630 (pWindow->size.w - pWindow->area.w) + area.w,
1631 (pWindow->size.h - pWindow->area.h) + area.h);
1632
1633 area = pWindow->area;
1634
1635 auto_center_on_focus_unit();
1636 put_window_near_map_tile(pWindow, pWindow->size.w, pWindow->size.h,
1637 pCity->tile);
1638
1639 /* setup widget size and start position */
1640 pBuf = pWindow;
1641
1642 if (exit) {
1643 /* exit button */
1644 pBuf = pBuf->prev;
1645 pBuf->size.x = area.x + area.w - pBuf->size.w - 1;
1646 pBuf->size.y = pWindow->size.y + adj_size(2);
1647 }
1648
1649 pBuf = pBuf->prev;
1650 setup_vertical_widgets_position(1,
1651 area.x,
1652 area.y + 1, area.w, 0,
1653 pIncite_Dlg->pdialog->pBeginWidgetList, pBuf);
1654
1655 /* --------------------- */
1656 /* redraw */
1657 redraw_group(pIncite_Dlg->pdialog->pBeginWidgetList, pWindow, 0);
1658
1659 widget_flush(pWindow);
1660 }
1661
1662 /* ====================================================================== */
1663 /* ============================ BRIBE DIALOG ========================== */
1664 /* ====================================================================== */
1665 static struct small_diplomat_dialog *pBribe_Dlg = NULL;
1666
1667 /**************************************************************************
1668 User interacted with bribe dialog window.
1669 **************************************************************************/
bribe_dlg_window_callback(struct widget * pWindow)1670 static int bribe_dlg_window_callback(struct widget *pWindow)
1671 {
1672 if (PRESSED_EVENT(Main.event)) {
1673 move_window_group(pBribe_Dlg->pdialog->pBeginWidgetList, pWindow);
1674 }
1675
1676 return -1;
1677 }
1678
1679 /**************************************************************************
1680 User confirmed bribe.
1681 **************************************************************************/
diplomat_bribe_yes_callback(struct widget * pWidget)1682 static int diplomat_bribe_yes_callback(struct widget *pWidget)
1683 {
1684 if (PRESSED_EVENT(Main.event)) {
1685 if (NULL != game_unit_by_number(pBribe_Dlg->actor_unit_id)
1686 && NULL != game_unit_by_number(pBribe_Dlg->target_id)) {
1687 request_do_action(ACTION_SPY_BRIBE_UNIT, pBribe_Dlg->actor_unit_id,
1688 pBribe_Dlg->target_id, 0);
1689 }
1690 popdown_bribe_dialog();
1691 }
1692
1693 return -1;
1694 }
1695
1696 /**************************************************************************
1697 Close bribe dialog.
1698 **************************************************************************/
exit_bribe_dlg_callback(struct widget * pWidget)1699 static int exit_bribe_dlg_callback(struct widget *pWidget)
1700 {
1701 if (PRESSED_EVENT(Main.event)) {
1702 popdown_bribe_dialog();
1703 }
1704
1705 return -1;
1706 }
1707
1708 /**************************************************************************
1709 Popdown a dialog asking a diplomatic unit if it wishes to bribe the
1710 given enemy unit.
1711 **************************************************************************/
popdown_bribe_dialog(void)1712 void popdown_bribe_dialog(void)
1713 {
1714 if (pBribe_Dlg) {
1715 act_sel_done_secondary(pBribe_Dlg->actor_unit_id);
1716
1717 is_unit_move_blocked = FALSE;
1718 popdown_window_group_dialog(pBribe_Dlg->pdialog->pBeginWidgetList,
1719 pBribe_Dlg->pdialog->pEndWidgetList);
1720 FC_FREE(pBribe_Dlg->pdialog);
1721 FC_FREE(pBribe_Dlg);
1722 flush_dirty();
1723 }
1724 }
1725
1726 /**************************************************************************
1727 Popup a dialog asking a diplomatic unit if it wishes to bribe the
1728 given enemy unit.
1729 **************************************************************************/
popup_bribe_dialog(struct unit * actor,struct unit * pUnit,int cost)1730 void popup_bribe_dialog(struct unit *actor, struct unit *pUnit, int cost)
1731 {
1732 struct widget *pWindow = NULL, *pBuf = NULL;
1733 utf8_str *pstr;
1734 char tBuf[255], cBuf[255];
1735 bool exit = FALSE;
1736 SDL_Rect area;
1737
1738 if (pBribe_Dlg) {
1739 return;
1740 }
1741
1742 /* Should be set before sending request to the server. */
1743 fc_assert(is_more_user_input_needed);
1744
1745 if (!actor || !unit_can_do_action(actor, ACTION_SPY_BRIBE_UNIT)) {
1746 act_sel_done_secondary(actor ? actor->id : IDENTITY_NUMBER_ZERO);
1747 return;
1748 }
1749
1750 is_unit_move_blocked = TRUE;
1751
1752 pBribe_Dlg = fc_calloc(1, sizeof(struct small_diplomat_dialog));
1753 pBribe_Dlg->actor_unit_id = actor->id;
1754 pBribe_Dlg->target_id = pUnit->id;
1755 pBribe_Dlg->pdialog = fc_calloc(1, sizeof(struct SMALL_DLG));
1756
1757 fc_snprintf(tBuf, ARRAY_SIZE(tBuf), PL_("Treasury contains %d gold.",
1758 "Treasury contains %d gold.",
1759 client_player()->economic.gold),
1760 client_player()->economic.gold);
1761
1762 /* window */
1763 pstr = create_utf8_from_char(_("Bribe Enemy Unit"), adj_font(12));
1764
1765 pstr->style |= TTF_STYLE_BOLD;
1766
1767 pWindow = create_window_skeleton(NULL, pstr, 0);
1768
1769 pWindow->action = bribe_dlg_window_callback;
1770 set_wstate(pWindow, FC_WS_NORMAL);
1771
1772 add_to_gui_list(ID_BRIBE_DLG_WINDOW, pWindow);
1773 pBribe_Dlg->pdialog->pEndWidgetList = pWindow;
1774
1775 area = pWindow->area;
1776 area.w = MAX(area.w, adj_size(8));
1777 area.h = MAX(area.h, adj_size(2));
1778
1779 if (cost <= client_player()->economic.gold) {
1780 fc_snprintf(cBuf, sizeof(cBuf),
1781 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
1782 PL_("Bribe unit for %d gold?\n%s",
1783 "Bribe unit for %d gold?\n%s", cost), cost, tBuf);
1784
1785 create_active_iconlabel(pBuf, pWindow->dst, pstr, cBuf, NULL);
1786
1787 add_to_gui_list(ID_LABEL, pBuf);
1788
1789 area.w = MAX(area.w, pBuf->size.w);
1790 area.h += pBuf->size.h;
1791
1792 /*------------*/
1793 create_active_iconlabel(pBuf, pWindow->dst, pstr,
1794 _("Yes"), diplomat_bribe_yes_callback);
1795 pBuf->data.unit = pUnit;
1796 set_wstate(pBuf, FC_WS_NORMAL);
1797
1798 add_to_gui_list(MAX_ID - actor->id, pBuf);
1799
1800 area.w = MAX(area.w, pBuf->size.w);
1801 area.h += pBuf->size.h;
1802 /* ------- */
1803 create_active_iconlabel(pBuf, pWindow->dst, pstr,
1804 _("No") , exit_bribe_dlg_callback);
1805
1806 set_wstate(pBuf, FC_WS_NORMAL);
1807 pBuf->key = SDLK_ESCAPE;
1808
1809 add_to_gui_list(ID_LABEL, pBuf);
1810
1811 area.w = MAX(area.w, pBuf->size.w);
1812 area.h += pBuf->size.h;
1813
1814 } else {
1815 /* exit button */
1816 pBuf = create_themeicon(current_theme->Small_CANCEL_Icon, pWindow->dst,
1817 WF_WIDGET_HAS_INFO_LABEL
1818 | WF_RESTORE_BACKGROUND);
1819 pBuf->info_label = create_utf8_from_char(_("Close Dialog (Esc)"),
1820 adj_font(12));
1821 area.w += pBuf->size.w + adj_size(10);
1822 pBuf->action = exit_bribe_dlg_callback;
1823 set_wstate(pBuf, FC_WS_NORMAL);
1824 pBuf->key = SDLK_ESCAPE;
1825
1826 add_to_gui_list(ID_BRIBE_DLG_EXIT_BUTTON, pBuf);
1827 exit = TRUE;
1828 /* --------------- */
1829
1830 fc_snprintf(cBuf, sizeof(cBuf),
1831 /* TRANS: %s is pre-pluralised "Treasury contains %d gold." */
1832 PL_("Bribing the unit costs %d gold.\n%s",
1833 "Bribing the unit costs %d gold.\n%s", cost), cost, tBuf);
1834
1835 create_active_iconlabel(pBuf, pWindow->dst, pstr, cBuf, NULL);
1836
1837 add_to_gui_list(ID_LABEL, pBuf);
1838
1839 area.w = MAX(area.w, pBuf->size.w);
1840 area.h += pBuf->size.h;
1841
1842 /*------------*/
1843 create_active_iconlabel(pBuf, pWindow->dst, pstr,
1844 _("Traitors Demand Too Much!"), NULL);
1845
1846 add_to_gui_list(ID_LABEL, pBuf);
1847
1848 area.w = MAX(area.w, pBuf->size.w);
1849 area.h += pBuf->size.h;
1850 }
1851 pBribe_Dlg->pdialog->pBeginWidgetList = pBuf;
1852
1853 /* setup window size and start position */
1854
1855 resize_window(pWindow, NULL, NULL,
1856 (pWindow->size.w - pWindow->area.w) + area.w,
1857 (pWindow->size.h - pWindow->area.h) + area.h);
1858
1859 area = pWindow->area;
1860
1861 auto_center_on_focus_unit();
1862 put_window_near_map_tile(pWindow, pWindow->size.w, pWindow->size.h,
1863 unit_tile(actor));
1864
1865 /* setup widget size and start position */
1866 pBuf = pWindow;
1867
1868 if (exit) {
1869 /* exit button */
1870 pBuf = pBuf->prev;
1871 pBuf->size.x = area.x + area.w - pBuf->size.w - 1;
1872 pBuf->size.y = pWindow->size.y + adj_size(2);
1873 }
1874
1875 pBuf = pBuf->prev;
1876 setup_vertical_widgets_position(1,
1877 area.x,
1878 area.y + 1, area.w, 0,
1879 pBribe_Dlg->pdialog->pBeginWidgetList, pBuf);
1880
1881 /* --------------------- */
1882 /* redraw */
1883 redraw_group(pBribe_Dlg->pdialog->pBeginWidgetList, pWindow, 0);
1884
1885 widget_flush(pWindow);
1886 }
1887