1 /***********************************************************************
2 Freeciv - Copyright (C) 1996 - A Kjeldberg, L Gregersen, P Unold
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)
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 ***********************************************************************/
14 /***********************************************************************
15 gui_main.c - description
17 begin : Sun Jun 30 2002
18 copyright : (C) 2002 by Rafał Bursig
19 email : Rafał Bursig <bursig@poczta.fm>
20 ***********************************************************************/
23 #include <fc_config.h>
26 #include "fc_prehdrs.h"
42 #include "fc_cmdline.h"
52 #include "client_main.h"
55 #include "editgui_g.h"
57 #include "update_queue.h"
66 #include "gui_mouse.h"
67 #include "gui_tilespec.h"
72 #include "messagewin.h"
73 #include "optiondlg.h"
75 #include "themespec.h"
76 #include "spaceshipdlg.h"
81 #define UNITS_TIMER_INTERVAL 128 /* milliseconds */
82 #define MAP_SCROLL_TIMER_INTERVAL 500
84 const char *client_string
= "gui-sdl";
86 /* The real GUI character encoding is UTF-16 which is not supported by
87 * fciconv code at this time. Conversion between UTF-8 and UTF-16 is done
89 const char * const gui_character_encoding
= "UTF-8";
90 const bool gui_use_transliteration
= FALSE
;
92 Uint32 SDL_Client_Flags
= 0;
94 Uint32 widget_info_counter
= 0;
95 int MOVE_STEP_X
= DEFAULT_MOVE_STEP
;
96 int MOVE_STEP_Y
= DEFAULT_MOVE_STEP
;
97 extern bool draw_goto_patrol_lines
;
98 SDL_Event
*pFlush_User_Event
= NULL
;
99 bool is_unit_move_blocked
;
105 int city_names_font_size
= 12;
106 int city_productions_font_size
= 12;
108 /* ================================ Private ============================ */
109 static int net_socket
= -1;
110 static bool autoconnect
= FALSE
;
111 static bool is_map_scrolling
= FALSE
;
112 static enum direction8 scroll_dir
;
114 static struct mouse_button_behavior button_behavior
;
116 static SDL_Event
*pNet_User_Event
= NULL
;
117 static SDL_Event
*pAnim_User_Event
= NULL
;
118 static SDL_Event
*pInfo_User_Event
= NULL
;
119 static SDL_Event
*pMap_Scroll_User_Event
= NULL
;
121 static void print_usage(void);
122 static void parse_options(int argc
, char **argv
);
123 static int check_scroll_area(int x
, int y
);
130 SHOW_WIDGET_INFO_LABBEL
,
137 void (*callback
)(void *data
);
141 #define SPECLIST_TAG callback
142 #define SPECLIST_TYPE struct callback
143 #include "speclist.h"
145 struct callback_list
*callbacks
;
147 /* =========================================================== */
149 /****************************************************************************
150 Called by the tileset code to set the font size that should be used to
151 draw the city names and productions.
152 ****************************************************************************/
153 void set_city_names_font_sizes(int my_city_names_font_size
,
154 int my_city_productions_font_size
)
156 city_names_font_size
= my_city_names_font_size
;
157 city_productions_font_size
= my_city_productions_font_size
;
160 /**************************************************************************
161 Print extra usage information, including one line help on each option,
163 **************************************************************************/
164 static void print_usage(void)
166 /* add client-specific usage information here */
168 _(" -f, --fullscreen\tStart Client in Fullscreen mode\n"));
169 fc_fprintf(stderr
, _(" -e, --eventthread\tInit Event Subsystem in "
170 "other thread (only Linux and BeOS)\n"));
171 fc_fprintf(stderr
, _(" -t, --theme THEME\tUse GUI theme THEME\n"));
173 /* TRANS: No full stop after the URL, could cause confusion. */
174 fc_fprintf(stderr
, _("Report bugs at %s\n"), BUG_URL
);
177 /**************************************************************************
178 Search for command line options. right now, it's just help
179 semi-useless until we have options that aren't the same across all clients.
180 **************************************************************************/
181 static void parse_options(int argc
, char **argv
)
187 if (is_option("--help", argv
[i
])) {
190 } else if (is_option("--fullscreen", argv
[i
])) {
191 gui_options
.gui_sdl_fullscreen
= TRUE
;
192 } else if (is_option("--eventthread", argv
[i
])) {
193 /* init events in other thread ( only linux and BeOS ) */
194 SDL_InitSubSystem(SDL_INIT_EVENTTHREAD
);
195 } else if ((option
= get_option_malloc("--theme", argv
, &i
, argc
, FALSE
))) {
196 sz_strlcpy(gui_options
.gui_sdl_default_theme_name
, option
);
199 fc_fprintf(stderr
, _("Unrecognized option: \"%s\"\n"), argv
[i
]);
207 /**************************************************************************
208 Main handler for key presses
209 **************************************************************************/
210 static Uint16
main_key_down_handler(SDL_keysym Key
, void *pData
)
212 static struct widget
*pWidget
;
213 if ((pWidget
= find_next_widget_for_key(NULL
, Key
)) != NULL
) {
214 return widget_pressed_action(pWidget
);
216 if (Key
.sym
== SDLK_TAB
) {
220 if (map_event_handler(Key
)
221 && C_S_RUNNING
== client_state()) {
225 if (LSHIFT
|| RSHIFT
) {
226 disable_focus_animation();
231 if (NULL
!= (pUnit
= head_of_units_in_focus()) &&
232 (pCity
= tile_city(unit_tile(pUnit
))) != NULL
&&
233 city_owner(pCity
) == client
.conn
.playing
) {
234 popup_city_dialog(pCity
);
240 units_report_dialog_popup(FALSE
);
244 city_report_dialog_popup(FALSE
);
248 send_report_request(REPORT_WONDERS_OF_THE_WORLD
);
252 send_report_request(REPORT_TOP_5_CITIES
);
256 if (meswin_dialog_is_open()) {
257 meswin_dialog_popdown();
259 meswin_dialog_popup(TRUE
);
265 send_report_request(REPORT_DEMOGRAPHIC
);
269 popup_spaceship_dialog(client
.conn
.playing
);
273 send_report_request(REPORT_ACHIEVEMENTS
);
286 /**************************************************************************
287 Main key release handler.
288 **************************************************************************/
289 static Uint16
main_key_up_handler(SDL_keysym Key
, void *pData
)
291 if(pSellected_Widget
) {
292 unsellect_widget_action();
297 /**************************************************************************
298 Main mouse click handler.
299 **************************************************************************/
300 static Uint16
main_mouse_button_down_handler(SDL_MouseButtonEvent
*pButtonEvent
, void *pData
)
302 struct widget
*pWidget
;
304 if ((pWidget
= find_next_widget_at_pos(NULL
,
306 pButtonEvent
->y
)) != NULL
) {
307 if (!(get_wstate(pWidget
) == FC_WS_DISABLED
)) {
308 return widget_pressed_action(pWidget
);
311 /* no visible widget at this position -> map click */
313 if (!check_scroll_area(pButtonEvent
->x
, pButtonEvent
->y
)) {
315 if (!button_behavior
.counting
) {
317 button_behavior
.counting
= TRUE
;
318 button_behavior
.button_down_ticks
= SDL_GetTicks();
319 *button_behavior
.event
= *pButtonEvent
;
320 button_behavior
.hold_state
= MB_HOLD_SHORT
;
321 button_behavior
.ptile
= canvas_pos_to_tile(pButtonEvent
->x
, pButtonEvent
->y
);
330 /**************************************************************************
331 Main mouse button release handler.
332 **************************************************************************/
333 static Uint16
main_mouse_button_up_handler(SDL_MouseButtonEvent
*pButtonEvent
, void *pData
)
335 if (button_behavior
.button_down_ticks
/* button wasn't pressed over a widget */
336 && !find_next_widget_at_pos(NULL
, pButtonEvent
->x
, pButtonEvent
->y
)) {
337 *button_behavior
.event
= *pButtonEvent
;
338 button_up_on_map(&button_behavior
);
341 button_behavior
.counting
= FALSE
;
342 button_behavior
.button_down_ticks
= 0;
344 is_map_scrolling
= FALSE
;
350 #define SCROLL_MAP_AREA 8
352 #define SCROLL_MAP_AREA 1
355 /**************************************************************************
356 Main handler for mouse movement handling.
357 **************************************************************************/
358 static Uint16
main_mouse_motion_handler(SDL_MouseMotionEvent
*pMotionEvent
, void *pData
)
360 static struct widget
*pWidget
;
363 /* stop evaluating button hold time when moving to another tile in medium
364 * hold state or above */
365 if (button_behavior
.counting
&& (button_behavior
.hold_state
>= MB_HOLD_MEDIUM
)) {
366 ptile
= canvas_pos_to_tile(pMotionEvent
->x
, pMotionEvent
->y
);
367 if (tile_index(ptile
) != tile_index(button_behavior
.ptile
)) {
368 button_behavior
.counting
= FALSE
;
372 if(draw_goto_patrol_lines
) {
373 update_line(pMotionEvent
->x
, pMotionEvent
->y
);
377 if (gui_options
.gui_sdl_fullscreen
) {
378 check_scroll_area(pMotionEvent
->x
, pMotionEvent
->y
);
380 #endif /* UNDER_CE */
382 if ((pWidget
= find_next_widget_at_pos(NULL
,
384 pMotionEvent
->y
)) != NULL
) {
385 update_mouse_cursor(CURSOR_DEFAULT
);
386 if (!(get_wstate(pWidget
) == FC_WS_DISABLED
)) {
387 widget_sellected_action(pWidget
);
390 if (pSellected_Widget
) {
391 unsellect_widget_action();
393 control_mouse_cursor(canvas_pos_to_tile(pMotionEvent
->x
, pMotionEvent
->y
));
402 /**************************************************************************
403 this is called every TIMER_INTERVAL milliseconds whilst we are in
404 gui_main_loop() (which is all of the time) TIMER_INTERVAL needs to be .5s
405 **************************************************************************/
406 static void update_button_hold_state(void)
409 if (button_behavior
.counting
) {
410 if (((SDL_GetTicks() - button_behavior
.button_down_ticks
) >= MB_MEDIUM_HOLD_DELAY
)
411 && ((SDL_GetTicks() - button_behavior
.button_down_ticks
) < MB_LONG_HOLD_DELAY
)) {
413 if (button_behavior
.hold_state
!= MB_HOLD_MEDIUM
) {
414 button_behavior
.hold_state
= MB_HOLD_MEDIUM
;
415 button_down_on_map(&button_behavior
);
418 } else if (((SDL_GetTicks() - button_behavior
.button_down_ticks
)
419 >= MB_LONG_HOLD_DELAY
)) {
421 if (button_behavior
.hold_state
!= MB_HOLD_LONG
) {
422 button_behavior
.hold_state
= MB_HOLD_LONG
;
423 button_down_on_map(&button_behavior
);
432 /**************************************************************************
433 Check if coordinate is in scroll area.
434 **************************************************************************/
435 static int check_scroll_area(int x
, int y
) {
437 SDL_Rect rect_north
= {0, 0, Main
.map
->w
, SCROLL_MAP_AREA
};
438 SDL_Rect rect_east
= {Main
.map
->w
- SCROLL_MAP_AREA
, 0, SCROLL_MAP_AREA
, Main
.map
->h
};
439 SDL_Rect rect_south
= {0, Main
.map
->h
- SCROLL_MAP_AREA
, Main
.map
->w
, SCROLL_MAP_AREA
};
440 SDL_Rect rect_west
= {0, 0, SCROLL_MAP_AREA
, Main
.map
->h
};
442 if (is_in_rect_area(x
, y
, rect_north
)) {
443 is_map_scrolling
= TRUE
;
444 if (is_in_rect_area(x
, y
, rect_west
)) {
445 scroll_dir
= DIR8_NORTHWEST
;
446 } else if (is_in_rect_area(x
, y
, rect_east
)) {
447 scroll_dir
= DIR8_NORTHEAST
;
449 scroll_dir
= DIR8_NORTH
;
451 } else if (is_in_rect_area(x
, y
, rect_south
)) {
452 is_map_scrolling
= TRUE
;
453 if (is_in_rect_area(x
, y
, rect_west
)) {
454 scroll_dir
= DIR8_SOUTHWEST
;
455 } else if (is_in_rect_area(x
, y
, rect_east
)) {
456 scroll_dir
= DIR8_SOUTHEAST
;
458 scroll_dir
= DIR8_SOUTH
;
460 } else if (is_in_rect_area(x
, y
, rect_east
)) {
461 is_map_scrolling
= TRUE
;
462 scroll_dir
= DIR8_EAST
;
463 } else if (is_in_rect_area(x
, y
, rect_west
)) {
464 is_map_scrolling
= TRUE
;
465 scroll_dir
= DIR8_WEST
;
467 is_map_scrolling
= FALSE
;
470 return is_map_scrolling
;
473 /* ============================ Public ========================== */
475 /**************************************************************************
476 Instruct event loop to exit.
477 **************************************************************************/
478 void force_exit_from_event_loop(void)
482 Event
.type
= SDL_USEREVENT
;
483 Event
.user
.code
= EXIT_FROM_EVENT_LOOP
;
484 Event
.user
.data1
= NULL
;
485 Event
.user
.data2
= NULL
;
487 SDL_PushEvent(&Event
);
490 /**************************************************************************
491 Filter out mouse motion events for too small movement to react to.
492 This function may run in a separate event thread.
493 **************************************************************************/
494 int FilterMouseMotionEvents(const SDL_Event
*event
)
496 if (event
->type
== SDL_MOUSEMOTION
) {
497 static int x
= 0, y
= 0;
498 if ( ((MOVE_STEP_X
> 0) && (abs(event
->motion
.x
- x
) >= MOVE_STEP_X
)) ||
499 ((MOVE_STEP_Y
> 0) && (abs(event
->motion
.y
- y
) >= MOVE_STEP_Y
)) ) {
502 return(1); /* Catch it */
504 return(0); /* Drop it, we've handled it */
510 /**************************************************************************
511 SDL-client main loop.
512 **************************************************************************/
513 Uint16
gui_event_loop(void *pData
,
514 void (*loop_action
)(void *pData
),
515 Uint16 (*key_down_handler
)(SDL_keysym Key
, void *pData
),
516 Uint16 (*key_up_handler
)(SDL_keysym Key
, void *pData
),
517 Uint16 (*mouse_button_down_handler
)(SDL_MouseButtonEvent
*pButtonEvent
, void *pData
),
518 Uint16 (*mouse_button_up_handler
)(SDL_MouseButtonEvent
*pButtonEvent
, void *pData
),
519 Uint16 (*mouse_motion_handler
)(SDL_MouseMotionEvent
*pMotionEvent
, void *pData
))
522 static fc_timeval tv
;
523 static fd_set civfdset
;
524 Uint32 t_current
, t_last_unit_anim
, t_last_map_scrolling
;
525 Uint32 real_timer_next_call
;
526 static int result
, schot_nr
= 0;
527 static char schot
[32];
530 t_last_map_scrolling
= t_last_unit_anim
= real_timer_next_call
= SDL_GetTicks();
531 while (ID
== ID_ERROR
) {
532 /* ========================================= */
533 /* net check with 10ms delay event loop */
534 if (net_socket
>= 0) {
537 if (net_socket
>= 0) {
538 FD_SET(net_socket
, &civfdset
);
542 tv
.tv_usec
= 10000;/* 10ms */
544 result
= fc_select(net_socket
+ 1, &civfdset
, NULL
, NULL
, &tv
);
546 if (errno
!= EINTR
) {
553 if ((net_socket
>= 0) && FD_ISSET(net_socket
, &civfdset
)) {
554 SDL_PushEvent(pNet_User_Event
);
558 } else { /* if connection is not establish */
561 /* ========================================= */
563 t_current
= SDL_GetTicks();
565 if (t_current
> real_timer_next_call
) {
566 real_timer_next_call
= t_current
+ (real_timer_callback() * 1000);
569 if ((t_current
- t_last_unit_anim
) > UNITS_TIMER_INTERVAL
) {
571 widget_info_counter
++;
572 SDL_PushEvent(pAnim_User_Event
);
574 SDL_PushEvent(pAnim_User_Event
);
577 t_last_unit_anim
= SDL_GetTicks();
580 if (is_map_scrolling
) {
581 if ((t_current
- t_last_map_scrolling
) > MAP_SCROLL_TIMER_INTERVAL
) {
582 SDL_PushEvent(pMap_Scroll_User_Event
);
583 t_last_map_scrolling
= SDL_GetTicks();
586 t_last_map_scrolling
= SDL_GetTicks();
589 if (widget_info_counter
> 0) {
590 SDL_PushEvent(pInfo_User_Event
);
591 widget_info_counter
= 0;
594 /* ========================================= */
600 /* ========================================= */
602 while (SDL_PollEvent(&Main
.event
) == 1) {
604 switch (Main
.event
.type
) {
611 switch (Main
.event
.key
.keysym
.sym
) {
612 /* find if Shifts are released */
630 ID
= key_up_handler(Main
.event
.key
.keysym
, pData
);
637 switch(Main
.event
.key
.keysym
.sym
) {
639 fc_snprintf(schot
, sizeof(schot
), "fc_%05d.bmp", schot_nr
++);
640 log_normal(_("Making screenshot %s"), schot
);
641 SDL_SaveBMP(Main
.screen
, schot
);
645 /* Right Shift is Pressed */
650 /* Left Shift is Pressed */
655 /* Left CTRL is Pressed */
660 /* Right CTRL is Pressed */
665 /* Left ALT is Pressed */
670 if(key_down_handler
) {
671 ID
= key_down_handler(Main
.event
.key
.keysym
, pData
);
677 case SDL_MOUSEBUTTONDOWN
:
678 if(mouse_button_down_handler
) {
679 ID
= mouse_button_down_handler(&Main
.event
.button
, pData
);
683 case SDL_MOUSEBUTTONUP
:
684 if(mouse_button_up_handler
) {
685 ID
= mouse_button_up_handler(&Main
.event
.button
, pData
);
689 case SDL_MOUSEMOTION
:
690 if(mouse_motion_handler
) {
691 ID
= mouse_motion_handler(&Main
.event
.motion
, pData
);
696 switch(Main
.event
.user
.code
) {
698 input_from_server(net_socket
);
701 update_button_hold_state();
702 animate_mouse_cursor();
705 case SHOW_WIDGET_INFO_LABBEL
:
706 draw_widget_info_label();
708 case TRY_AUTO_CONNECT
:
709 if (try_to_autoconnect()) {
710 pInfo_User_Event
->user
.code
= SHOW_WIDGET_INFO_LABBEL
;
718 scroll_mapview(scroll_dir
);
720 case EXIT_FROM_EVENT_LOOP
:
731 if (ID
== ID_ERROR
) {
732 if (callbacks
&& callback_list_size(callbacks
) > 0) {
733 struct callback
*cb
= callback_list_get(callbacks
, 0);
734 callback_list_remove(callbacks
, cb
);
735 (cb
->callback
)(cb
->data
);
744 /* ============ Freeciv native game function =========== */
746 /**************************************************************************
747 Do any necessary pre-initialization of the UI, if necessary.
748 **************************************************************************/
752 /* struct widget *pInit_String = NULL;*/
756 button_behavior
.counting
= FALSE
;
757 button_behavior
.button_down_ticks
= 0;
758 button_behavior
.hold_state
= MB_HOLD_SHORT
;
759 button_behavior
.event
= fc_calloc(1, sizeof(SDL_MouseButtonEvent
));
761 SDL_Client_Flags
= 0;
762 iSDL_Flags
= SDL_INIT_VIDEO
| SDL_INIT_NOPARACHUTE
;
764 /* auto center new windows in X enviroment */
765 putenv((char *)"SDL_VIDEO_CENTERED=yes");
767 init_sdl(iSDL_Flags
);
769 log_normal(_("Using Video Output: %s"),
770 SDL_VideoDriverName(device
, sizeof(device
)));
772 /* create splash screen */
775 SDL_Surface
*pTmpSurf
= load_surf(fileinfoname(get_data_dirs(),
777 pBgd
= zoomSurface(pTmpSurf
, DEFAULT_ZOOM
, DEFAULT_ZOOM
, 0);
778 FREESURFACE(pTmpSurf
);
780 #else /* SMALL_SCREEN */
781 pBgd
= load_surf(fileinfoname(get_data_dirs(), "misc/intro.png"));
782 #endif /* SMALL_SCREEN */
784 if (pBgd
&& SDL_GetVideoInfo()->wm_available
) {
785 set_video_mode(pBgd
->w
, pBgd
->h
, SDL_SWSURFACE
| SDL_ANYFORMAT
);
788 * call this for other than X enviroments - currently not supported.
790 center_main_window_on_screen();
792 alphablit(pBgd
, NULL
, Main
.map
, NULL
);
794 0, 0, Main
.map
->w
- 1, Main
.map
->h
- 1,
795 &(SDL_Color
){255, 255, 255, 255});
797 SDL_WM_SetCaption(_("SDL Client for Freeciv"), _("Freeciv"));
801 set_video_mode(640, 480, SDL_SWSURFACE
| SDL_ANYFORMAT
);
802 #else /* SMALL_SCREEN */
803 set_video_mode(320, 240, SDL_SWSURFACE
| SDL_ANYFORMAT
);
804 #endif /* SMALL_SCREEN */
807 blit_entire_src(pBgd
, Main
.map
, (Main
.map
->w
- pBgd
->w
) / 2,
808 (Main
.map
->h
- pBgd
->h
) / 2);
811 SDL_FillRect(Main
.map
, NULL
, SDL_MapRGB(Main
.map
->format
, 0, 0, 128));
812 SDL_WM_SetCaption(_("SDL Client for Freeciv"), _("Freeciv"));
817 /* create label beackground */
818 pBgd
= create_surf_alpha(adj_size(350), adj_size(50), SDL_SWSURFACE
);
820 SDL_FillRect(pBgd
, NULL
, SDL_MapRGBA(pBgd
->format
, 255, 255, 255, 128));
821 putframe(pBgd
, 0, 0, pBgd
->w
- 1, pBgd
->h
- 1, SDL_MapRGB(pBgd
->format
, 0, 0, 0));
823 pInit_String
= create_iconlabel(pBgd
, Main
.gui
,
824 create_str16_from_char(_("Initializing Client"), adj_font(20)),
825 WF_ICON_CENTER
|WF_FREE_THEME
);
826 pInit_String
->string16
->style
|= SF_CENTER
;
828 draw_label(pInit_String
,
829 (Main
.screen
->w
- pInit_String
->size
.w
) / 2,
830 (Main
.screen
->h
- pInit_String
->size
.h
) / 2);
834 copy_chars_to_string16(pInit_String
->string16
,
835 _("Waiting for the beginning of the game"));
842 /****************************************************************************
843 Really resize the main window.
844 ****************************************************************************/
845 static void real_resize_window_callback(void *data
)
847 struct widget
*widget
;
848 Uint32 flags
= Main
.screen
->flags
;
850 if (gui_options
.gui_sdl_fullscreen
) {
851 flags
|= SDL_FULLSCREEN
;
853 flags
&= ~SDL_FULLSCREEN
;
855 set_video_mode(gui_options
.gui_sdl_screen
.width
, gui_options
.gui_sdl_screen
.height
,
858 if (C_S_RUNNING
== client_state()) {
859 /* Move units window to botton-right corner. */
860 set_new_unitinfo_window_pos();
861 /* Move minimap window to botton-left corner. */
862 set_new_minimap_window_pos();
864 /* Move cooling/warming icons to botton-right corner. */
865 widget
= get_widget_pointer_form_main_list(ID_WARMING_ICON
);
866 widget_set_position(widget
, (Main
.screen
->w
- adj_size(10)
867 - (widget
->size
.w
* 2)), widget
->size
.y
);
869 widget
= get_widget_pointer_form_main_list(ID_COOLING_ICON
);
870 widget_set_position(widget
, (Main
.screen
->w
- adj_size(10)
871 - widget
->size
.w
), widget
->size
.y
);
873 map_canvas_resized(Main
.screen
->w
, Main
.screen
->h
);
875 update_unit_info_label(get_units_in_focus());
876 center_on_something(); /* With redrawing full map. */
877 update_order_widgets();
885 /****************************************************************************
886 Resize the main window.
887 ****************************************************************************/
888 static void resize_window_callback(struct option
*poption
)
890 update_queue_add(real_resize_window_callback
, NULL
);
893 /****************************************************************************
894 Extra initializers for client options. Here we make set the callback
895 for the specific gui-sdl options.
896 ****************************************************************************/
897 void options_extra_init(void)
899 struct option
*poption
;
901 #define option_var_set_callback(var, callback) \
902 if ((poption = optset_option_by_name(client_optset, #var))) { \
903 option_set_changed_callback(poption, callback); \
905 log_error("Didn't find option %s!", #var); \
908 option_var_set_callback(gui_sdl_fullscreen
, resize_window_callback
);
909 option_var_set_callback(gui_sdl_screen
, resize_window_callback
);
910 #undef option_var_set_callback
913 /**************************************************************************
914 Remove double messages caused by message configured to both MW_MESSAGES
916 **************************************************************************/
917 static void clear_double_messages_call(void)
920 /* clear double call */
921 for(i
= 0; i
<= event_type_max(); i
++) {
922 if (messages_where
[i
] & MW_MESSAGES
) {
923 messages_where
[i
] &= ~MW_OUTPUT
;
928 /**************************************************************************
929 Entry point for freeciv client program. SDL has macro magic to turn
930 this in to function named SDL_main() and it provides actual main()
932 **************************************************************************/
933 int main(int argc
, char **argv
)
935 return client_main(argc
, argv
);
938 /**************************************************************************
939 The main loop for the UI. This is called from main(), and when it
940 exits the client will exit.
941 **************************************************************************/
942 void ui_main(int argc
, char *argv
[])
944 SDL_Event __Net_User_Event
;
945 SDL_Event __Anim_User_Event
;
946 SDL_Event __Info_User_Event
;
947 SDL_Event __Flush_User_Event
;
948 SDL_Event __pMap_Scroll_User_Event
;
950 parse_options(argc
, argv
);
952 __Net_User_Event
.type
= SDL_USEREVENT
;
953 __Net_User_Event
.user
.code
= NET
;
954 __Net_User_Event
.user
.data1
= NULL
;
955 __Net_User_Event
.user
.data2
= NULL
;
956 pNet_User_Event
= &__Net_User_Event
;
958 __Anim_User_Event
.type
= SDL_USEREVENT
;
959 __Anim_User_Event
.user
.code
= EVENT_ERROR
;
960 __Anim_User_Event
.user
.data1
= NULL
;
961 __Anim_User_Event
.user
.data2
= NULL
;
962 pAnim_User_Event
= &__Anim_User_Event
;
964 __Info_User_Event
.type
= SDL_USEREVENT
;
965 __Info_User_Event
.user
.code
= SHOW_WIDGET_INFO_LABBEL
;
966 __Info_User_Event
.user
.data1
= NULL
;
967 __Info_User_Event
.user
.data2
= NULL
;
968 pInfo_User_Event
= &__Info_User_Event
;
970 __Flush_User_Event
.type
= SDL_USEREVENT
;
971 __Flush_User_Event
.user
.code
= FLUSH
;
972 __Flush_User_Event
.user
.data1
= NULL
;
973 __Flush_User_Event
.user
.data2
= NULL
;
974 pFlush_User_Event
= &__Flush_User_Event
;
976 __pMap_Scroll_User_Event
.type
= SDL_USEREVENT
;
977 __pMap_Scroll_User_Event
.user
.code
= MAP_SCROLL
;
978 __pMap_Scroll_User_Event
.user
.data1
= NULL
;
979 __pMap_Scroll_User_Event
.user
.data2
= NULL
;
980 pMap_Scroll_User_Event
= &__pMap_Scroll_User_Event
;
982 is_unit_move_blocked
= FALSE
;
984 SDL_Client_Flags
|= (CF_DRAW_PLAYERS_NEUTRAL_STATUS
|
985 CF_DRAW_PLAYERS_WAR_STATUS
|
986 CF_DRAW_PLAYERS_CEASEFIRE_STATUS
|
987 CF_DRAW_PLAYERS_PEACE_STATUS
|
988 CF_DRAW_PLAYERS_ALLIANCE_STATUS
);
990 tileset_init(tileset
);
991 tileset_load_tiles(tileset
);
992 tileset_use_preferred_theme(tileset
);
996 callbacks
= callback_list_new();
998 diplomacy_dialog_init();
1001 clear_double_messages_call();
1003 setup_auxiliary_tech_icons();
1005 if (gui_options
.gui_sdl_fullscreen
) {
1008 /* set 320x240 fullscreen */
1009 set_video_mode(gui_options
.gui_sdl_screen
.width
,
1010 gui_options
.gui_sdl_screen
.height
,
1011 SDL_SWSURFACE
| SDL_ANYFORMAT
| SDL_FULLSCREEN
);
1012 #else /* UNDER_CE */
1013 /* small screen on desktop -> don't set 320x240 fullscreen mode */
1014 set_video_mode(gui_options
.gui_sdl_screen
.width
,
1015 gui_options
.gui_sdl_screen
.height
,
1016 SDL_SWSURFACE
| SDL_ANYFORMAT
);
1017 #endif /* UNDER_CE */
1018 #else /* SMALL_SCREEN */
1019 set_video_mode(gui_options
.gui_sdl_screen
.width
,
1020 gui_options
.gui_sdl_screen
.height
,
1021 SDL_SWSURFACE
| SDL_ANYFORMAT
| SDL_FULLSCREEN
);
1022 #endif /* SMALL_SCREEN */
1028 set_video_mode(gui_options
.gui_sdl_screen
.width
,
1029 gui_options
.gui_sdl_screen
.height
,
1030 SDL_SWSURFACE
| SDL_ANYFORMAT
);
1031 #else /* UNDER_CE */
1032 set_video_mode(gui_options
.gui_sdl_screen
.width
,
1033 gui_options
.gui_sdl_screen
.height
,
1034 SDL_SWSURFACE
| SDL_ANYFORMAT
);
1035 #endif /* UNDER_CE */
1036 #else /* SMALL_SCREEN */
1037 set_video_mode(gui_options
.gui_sdl_screen
.width
,
1038 gui_options
.gui_sdl_screen
.height
,
1039 SDL_SWSURFACE
| SDL_ANYFORMAT
);
1040 #endif /* SMALL_SCREEN */
1044 * call this for other that X enviroments - currently not supported.
1046 center_main_window_on_screen();
1050 /* SDL_WM_SetCaption(_("SDL Client for Freeciv"), _("Freeciv")); */
1052 /* this need correct Main.screen size */
1053 init_mapcanvas_and_overview();
1055 set_client_state(C_S_DISCONNECTED
);
1057 /* Main game loop */
1058 gui_event_loop(NULL
, NULL
, main_key_down_handler
, main_key_up_handler
,
1059 main_mouse_button_down_handler
, main_mouse_button_up_handler
,
1060 main_mouse_motion_handler
);
1064 /**************************************************************************
1065 Do any necessary UI-specific cleanup
1066 **************************************************************************/
1070 #if defined UNDER_CE && defined SMALL_SCREEN
1071 /* change back to window mode to restore the title bar */
1072 set_video_mode(320, 240, SDL_SWSURFACE
| SDL_ANYFORMAT
);
1075 free_mapcanvas_and_overview();
1077 free_auxiliary_tech_icons();
1078 free_intro_radar_sprites();
1080 diplomacy_dialog_done();
1081 intel_dialog_done();
1083 callback_list_destroy(callbacks
);
1087 FC_FREE(button_behavior
.event
);
1089 meswin_dialog_popdown();
1099 /**************************************************************************
1101 **************************************************************************/
1102 enum gui_type
get_gui_type(void)
1107 /**************************************************************************
1108 Make a bell noise (beep). This provides low-level sound alerts even
1109 if there is no real sound support.
1110 **************************************************************************/
1111 void sound_bell(void)
1113 log_debug("sound_bell : PORT ME");
1116 /**************************************************************************
1117 Show Focused Unit Animation.
1118 **************************************************************************/
1119 void enable_focus_animation(void)
1121 pAnim_User_Event
->user
.code
= ANIM
;
1122 SDL_Client_Flags
|= CF_FOCUS_ANIMATION
;
1125 /**************************************************************************
1126 Don't show Focused Unit Animation.
1127 **************************************************************************/
1128 void disable_focus_animation(void)
1130 SDL_Client_Flags
&= ~CF_FOCUS_ANIMATION
;
1133 /**************************************************************************
1134 Wait for data on the given socket. Call input_from_server() when data
1135 is ready to be read.
1136 **************************************************************************/
1137 void add_net_input(int sock
)
1139 log_debug("Connection UP (%d)", sock
);
1141 autoconnect
= FALSE
;
1142 enable_focus_animation();
1145 /**************************************************************************
1146 Stop waiting for any server network data. See add_net_input().
1147 **************************************************************************/
1148 void remove_net_input(void)
1150 log_debug("Connection DOWN... ");
1152 disable_focus_animation();
1153 draw_goto_patrol_lines
= FALSE
;
1154 update_mouse_cursor(CURSOR_DEFAULT
);
1157 /****************************************************************************
1158 Enqueue a callback to be called during an idle moment. The 'callback'
1159 function should be called sometimes soon, and passed the 'data' pointer
1161 ****************************************************************************/
1162 void add_idle_callback(void (callback
)(void *), void *data
)
1164 struct callback
*cb
= fc_malloc(sizeof(*cb
));
1166 cb
->callback
= callback
;
1169 callback_list_prepend(callbacks
, cb
);
1172 /****************************************************************************
1173 Stub for editor function
1174 ****************************************************************************/
1175 void editgui_tileset_changed(void)
1178 /****************************************************************************
1179 Stub for editor function
1180 ****************************************************************************/
1181 void editgui_refresh(void)
1184 /****************************************************************************
1185 Stub for editor function
1186 ****************************************************************************/
1187 void editgui_popup_properties(const struct tile_list
*tiles
, int objtype
)
1190 /****************************************************************************
1191 Stub for editor function
1192 ****************************************************************************/
1193 void editgui_popdown_all(void)
1196 /****************************************************************************
1197 Stub for editor function
1198 ****************************************************************************/
1199 void editgui_notify_object_changed(int objtype
, int object_id
, bool removal
)
1202 /****************************************************************************
1203 Stub for editor function
1204 ****************************************************************************/
1205 void editgui_notify_object_created(int tag
, int id
)
1208 /**************************************************************************
1209 Updates a gui font style.
1210 **************************************************************************/
1211 void gui_update_font(const char *font_name
, const char *font_value
)
1216 /**************************************************************************
1217 Insert build information to help
1218 **************************************************************************/
1219 void insert_client_build_info(char *outbuf
, size_t outlen
)
1224 /**************************************************************************
1225 Make dynamic adjustments to first-launch default options.
1226 **************************************************************************/
1227 void adjust_default_options(void)
1229 /* Nothing in case of this gui */