1 /* $Header: /home/jcb/MahJong/newmj/RCS/gui.h,v 12.7 2020/05/23 10:07:46 jcb Exp $ 2 * gui.h 3 * type defns and forward declarations for the gui module. 4 */ 5 /****************** COPYRIGHT STATEMENT ********************** 6 * This file is Copyright (c) 2000 by J. C. Bradfield. * 7 * Distribution and use is governed by the LICENCE file that * 8 * accompanies this file. * 9 * The moral rights of the author are asserted. * 10 * * 11 ***************** DISCLAIMER OF WARRANTY ******************** 12 * This code is not warranted fit for any purpose. See the * 13 * LICENCE file for further information. * 14 * * 15 *************************************************************/ 16 17 #include <gtk/gtk.h> 18 #include <gdk/gdkkeysyms.h> 19 #include "lazyfixed.h" 20 #include "vlazyfixed.h" 21 #include "sysdep.h" 22 #include <errno.h> 23 #include "client.h" 24 #include <math.h> 25 26 /********************* 27 TYPE DEFINITIONS 28 *********************/ 29 30 /* a tilesetbox is a TileSet and a widget that boxes it. 31 The TileSet is stored to avoid unnecessary updating of the box 32 */ 33 typedef struct _TileSetBox { 34 TileSet set; 35 GtkWidget *widget; /* the widget itself */ 36 GtkWidget *tiles[4]; /* the children buttons */ 37 } TileSetBox; 38 39 /* This struct represents the display of a player. It gives 40 access to relevant widgets without requiring excessive casting 41 and pointer chasing. 42 */ 43 typedef struct _PlayerDisp { 44 PlayerP player; /* pointer to the game player structure */ 45 /* this is the whole box representing the player */ 46 GtkWidget *widget; 47 /* the orientation says which way round tiles go 48 (equivalently, which player we are in the table). 49 The tilepixmaps are those appropriate assuming that players 50 look at their own tiles. If the players politely display 51 their sets to be readable by the others, then the orientation 52 of exposed tiles is flipped from these. 53 that the orientations are: 54 0: upright (for our own tiles) 55 1: top to left: player to the right (south, when we're east) 56 2: upside down (player opposite) 57 3: top to right (north). 58 */ 59 int orientation; 60 /* and accordingly the following macro can be used if concealed 61 and exposed tiles are oriented differently */ 62 /* # define flipori(ori) ((ori+2)%4) */ 63 #define flipori(ori) ori 64 /* this is an array of buttons representing the concealed tiles. 65 For initial size calculation, it should be filled with blanks. 66 (Ideally, unmapped, but I can't see how to do that.) 67 They appear from the left in the "concealed" row. 68 */ 69 GtkWidget *conc[MAX_CONCEALED]; 70 /* This is an array representing the declared specials 71 that have overflowed into the concealed row. 72 Initially, exactly five of these should be shown: that makes 73 the whole "concealed" row 19 tiles wide, which gives enough 74 room for reasonable collections of specials, and makes the "exposed" 75 row big enough for four kongs and a pair. 76 They appear to the right of the concealed row. 77 */ 78 GtkWidget *extras[8]; 79 /* These are the specials that have found room where we want 80 them, at the end of the exposed row */ 81 GtkWidget *spec[8]; 82 /* each of these is a box representing a declared set. 83 Each set is packed into the exposed row, from the left, 84 with a 1/4 tile spacing between them (thus fitting 85 4 kongs and a pair in exactly). 86 Size is determined by the concealed row, so there is 87 no need to show these initially. 88 */ 89 /* This is the tong box. It appears to the right of the exposed row specials*/ 90 GtkWidget *tongbox; 91 TileSetBox esets[MAX_TILESETS]; 92 /* each of these is a box representing a concealed set. 93 They appear to the left of the concealed tile set, with 94 the 1/4 tile spacing. They are initially hidden, and 95 appear only in scoring. 96 */ 97 TileSetBox csets[MAX_TILESETS]; 98 99 /* these is not actually in the player area, but to do with 100 discards */ 101 GtkWidget *discards[32]; /* buttons for this player's discards */ 102 int dx[32], dy[32]; /* save calculated posns of discard tiles */ 103 int num_discards; 104 gint16 x,y; /* x and y for next discard */ 105 int row; /* which row is next discard in */ 106 gint16 xmin[5],xmax[5]; /* in each row, first point used, leftmost point free*/ 107 int plane; /* if desperate, we start stacking tiles */ 108 109 /* This is the window for pung! claims etc. */ 110 GtkWidget *claimw; 111 GtkWidget *claimlab; /* and the label inside it */ 112 GtkWidget *thinkbox; /* and the box holding the ... for thinking */ 113 int claim_serial; /* the discard for which this window was popped up */ 114 int claim_time; /* time popped up (in millisecs since start of program) */ 115 116 /* this is a label widget which is put the right of each player when 117 the wall is shown, to use the otherwise empty space. It displays the 118 same info as the info window. It's only used in GTK2, because in order to 119 make it clear which label goes with which, we use rotated text. */ 120 GtkLabel *infolab; 121 } PlayerDisp; 122 123 /* This is a one use structure representing the dialog box 124 used for claiming discards. It has two personalities: 125 normally it shows buttons 126 Noclaim Chow Pung Kong MahJong 127 but after a mahjong claim it shows 128 Eyes Chow Pung Special Hand 129 */ 130 typedef struct { 131 GtkWidget *widget; /* the box itself */ 132 GtkWidget *tilename; /* the label for the tile name */ 133 GtkWidget *tiles[4]; /* the buttons for the tiles as discarded 134 by each player. Element 0 is unused. */ 135 /* the various buttons */ 136 GtkWidget *noclaim; 137 GtkWidget *eyes; 138 GtkWidget *chow; 139 GtkWidget *pung; 140 GtkWidget *special; 141 GtkWidget *kong; 142 GtkWidget *mahjong; 143 GtkWidget *robkong; 144 int mode; /* 0 normally, 1 in mahjong mode, 2 for robbing kongs */ 145 } DiscardDialog; 146 147 /* this is used by functions that display or remove tiles to pass 148 back information to the animation routines. The structure contains 149 information about the tiles. 150 */ 151 typedef struct { 152 GtkWidget *target; /* the widget to which this information refers, 153 if it is being newly displayed. In this case, 154 the widget is not shown, and it is the animator's 155 job to show it at the end of animation. 156 If target is null, then the widget is being 157 undisplayed. */ 158 Tile t; /* the tile displayed by the widget */ 159 int ori; /* and its orientation */ 160 int x, y; /* x and y coordinates relative to the boardframe */ 161 } AnimInfo; 162 163 /* enums used in the dialog popup function to specify position */ 164 typedef enum { 165 DPCentred, /* centered over main window */ 166 DPOnDiscard, /* bottom left corner in same place as discard dialog */ 167 DPErrorPos, /* for error dialogs: centred over top of main window */ 168 DPNone, /* don't touch the positioning at all */ 169 DPCentredOnce, /* centre it on first popup, then don't fiddle */ 170 DPOnDiscardOnce, /* on discard dialog first time, then don't fiddle */ 171 } DPPosn; 172 173 /* Where to put the dialog boxes */ 174 typedef enum { 175 DialogsUnspecified = 0, 176 DialogsCentral = 1, 177 DialogsBelow = 2, 178 DialogsPopup = 3 } DialogPosition; 179 180 /* when to sort the tiles in our hand */ 181 typedef enum { 182 SortAlways = 0, 183 SortDeal = 1, 184 SortNever = 2, 185 } SortTiles; 186 187 /* Whether to file fault reports over the network */ 188 typedef enum { 189 DebugReportsUnspecified = 0, 190 DebugReportsNever = 1, 191 DebugReportsAsk = 2, 192 DebugReportsAlways = 3 } DebugReports; 193 194 /* The rcfile is used to store assorted persistent data. We often 195 need to read or update only selected parts of it. This set of 196 flag bits identifies the groups that can be independently 197 read or updated. */ 198 typedef enum { 199 XmjrcNone = 0x00, 200 XmjrcDisplay = 0x01, /* preferences regarding the display */ 201 XmjrcPlayer = 0x02, /* player option settings */ 202 XmjrcGame = 0x04, /* game option preferences */ 203 XmjrcMisc = 0x08, /* odds and sods */ 204 XmjrcOpen = 0x10, /* sticky fields in the connection dialogs */ 205 XmjrcPlaying = 0x20, /* playing preferences */ 206 XmjrcAll = 0xFFFFFFFF /* everything */ 207 } XmjrcGroup; 208 209 /* extra data in the game */ 210 typedef struct { 211 int orig_live_end; /* value of wall.live_end at start of hand */ 212 } GameExtras; 213 #define gextras(g) ((GameExtras *)(g->userdata)) 214 215 /***************** 216 FORWARD DECLARATIONS 217 *****************/ 218 219 /* FUNCTIONS */ 220 221 void apply_game_prefs(void); 222 GtkWidget *build_or_refresh_option_panel(GameOptionTable *got,GtkWidget *panel); 223 GtkWidget *build_or_refresh_prefs_panel(GameOptionTable *got,GtkWidget *panel); 224 void button_set_tile(GtkWidget *b, Tile t, int ori); 225 void chow_dialog_init(void); 226 void close_connection(int keepconnection); 227 void close_saving_posn(GtkWidget *w); 228 void conc_callback(GtkWidget *w, gpointer data); 229 void continue_dialog_init(void); 230 void continue_dialog_popup(void); 231 void control_server_processing(int on); 232 void create_dialogs(void); 233 void create_display(void); 234 void debug_options_dialog_popup(void); 235 void destroy_dialogs(void); 236 void destroy_display(void); 237 void dialog_popup(GtkWidget *dialog, DPPosn posn); 238 void disc_callback(GtkWidget *w, gpointer data); 239 void discard_dialog_init(void); 240 void discard_dialog_popup(Tile t, int ori, int mode); 241 void do_chow(GtkWidget *w, gpointer data); 242 gint doubleclicked(GtkWidget *w, GdkEventButton *eb,gpointer data); 243 void ds_dialog_init(void); 244 void ds_dialog_popup(void); 245 void end_dialog_init(void); 246 void end_dialog_popup(void); 247 void error_dialog_init(void); 248 void error_dialog_popup(char *msg); 249 void game_option_init(void); 250 void game_prefs_init(void); 251 void info_dialog_popup(char *msg); 252 GtkWidget *menubar_create(void); 253 GtkWidget *make_or_refresh_option_updater(GameOptionEntry *goe, int prefsp); 254 void messagewindow_init(void); 255 void nag_popup(void); 256 void option_reset_callback(GtkWidget *w, gpointer data); 257 void option_updater_callback(GtkWidget *w, gpointer data); 258 void open_connection(GtkWidget *w UNUSED, gpointer data, int fd, char *newaddr); 259 void open_dialog_init(char *idt, char *nt); 260 void open_dialog_popup(GtkWidget *w UNUSED, gpointer data); 261 void password_showraise(void); 262 void playing_prefs_init(void); 263 void prefs_updater_callback(GtkWidget *w, gpointer data); 264 int read_or_update_rcfile(char *rcfile, 265 XmjrcGroup read_groups, 266 XmjrcGroup update_groups); 267 void scorehistory_init(void); 268 void scoring_dialog_init(void); 269 void scoring_dialog_popup(void); 270 void set_dialog_posn(DialogPosition p); 271 void set_animation(int a); 272 void setup_dialogs(void); 273 void showraise(GtkWidget *w); 274 void status_init(void); 275 void status_showraise(void); 276 void status_update(int game_over); 277 void textwindow_init(void); 278 void tilesetbox_highlight_nth(TileSetBox *tb,int n); 279 void tilesetbox_init(TileSetBox *tb, int ori,GtkSignalFunc func,gpointer func_data); 280 void tilesetbox_set(TileSetBox *tb, const TileSet *ts, int ori); 281 void turn_dialog_init(void); 282 void turn_dialog_popup(void); 283 void usage(char *pname,char *msg); 284 void warningwindow_init(void); 285 int log_msg_add(LogLevel l,char *warning); 286 void warning_clear(void); 287 /* Convenience function */ 288 #define send_packet(m) client_send_packet(the_game,(PMsgMsg *)m) 289 290 /* VARIABLES */ 291 292 extern const char *windnames[]; 293 extern const char *shortwindnames[]; 294 295 extern int debug; 296 extern int server_pversion; /* protocol version that server speaks 297 (independently of game) */ 298 extern PlayerP our_player; 299 extern int our_id; 300 extern seats our_seat; /* our seat in the game */ 301 extern Game *the_game; 302 extern int selected_button; /* the index of the user's selected 303 tile, or -1 if none */ 304 305 extern int ptimeout; /* claim timeout time in milliseconds */ 306 extern int local_timeouts; /* are we handling timeouts ourselves? */ 307 308 extern int monitor; /* if 1, send no messages other than in direct 309 response to user action. Used for monitoring 310 a stream in debugging. */ 311 312 extern int game_over; /* if the game is over, but we're waiting for the user 313 to confirm the disconnect. In this state, we do 314 not close our connection when the other end closes. 315 */ 316 317 extern int closed_set_in_progress; /* Set when the user clicks a button 318 to declare a closed set in scoring. 319 Cleared by the receipt of a 320 FormClosed... message, or by an Error 321 message. */ 322 323 extern GdkPixmap **tilepixmaps[]; /* pixmaps for the tiles */ 324 325 extern GtkWidget *topwindow; /* main window */ 326 extern GtkWidget *menubar; /* menubar */ 327 extern GtkWidget *board; /* the table area itself */ 328 extern GtkWidget *boardframe; /* fixed widget wrapping the board */ 329 extern GtkWidget *outerframe; /* the outermost frame widget */ 330 extern GtkStyle *tablestyle; /* for the dark green stuff */ 331 extern GtkStyle *highlightstyle; /* to highlight tiles */ 332 extern GtkWidget *highlittile; /* the unique highlighted tile */ 333 extern GdkFont *fixed_font; /* a fixed width font */ 334 extern GdkFont *big_font; /* big font for claim windows */ 335 336 extern GtkWidget *dialoglowerbox; /* encloses dialogs when dialogs are below */ 337 338 /* Why an array? So I can pass pointers around */ 339 extern DiscardDialog discard_dialog[1]; 340 341 /* dialog box for specifying chows */ 342 extern GtkWidget *chow_dialog; 343 344 /* dialog box for declaring specials */ 345 extern GtkWidget *ds_dialog; 346 347 /* dialog box for continuing with next hand */ 348 extern GtkWidget *continue_dialog; 349 350 /* dialog box for disconnect at end of game */ 351 extern GtkWidget *end_dialog; 352 353 /* dialog for opening connection */ 354 extern GtkWidget *open_dialog; 355 extern GtkWidget *openmenuentry, *newgamemenuentry, *resumegamemenuentry, 356 *savemenuentry, *saveasmenuentry, *closemenuentry, *gameoptionsmenuentry; 357 extern GtkWidget *openallowdisconnectbutton,*opensaveonexitbutton,*openrandomseatsbutton, 358 *openplayercheckboxes[3],*openplayernames[3],*openplayeroptions[3],*opentimeoutspinbutton; 359 360 /* dialog box for action when it's our turn. 361 Actions: Discard Kong Add to Pung Mah Jong 362 */ 363 extern GtkWidget *turn_dialog; 364 365 /* dialog box for closed sets when scoring. 366 Actions: Eyes Chow Pung Done 367 */ 368 extern GtkWidget *scoring_dialog; 369 370 /* window for game status display */ 371 extern GtkWidget *status_window; 372 373 /* an array of text widgets for displaying scores etc. 374 Element 4 is for settlements. 375 The others are for each player: currently, I think 376 these should be table relative. 377 */ 378 extern GtkWidget *scoring_notebook; 379 extern GtkWidget *textpages[5]; 380 extern GtkWidget *textlabels[5]; /* labels for the pages */ 381 extern GtkWidget *textwindow; /* and the window for it */ 382 383 /* a window for keeping the score history */ 384 extern GtkWidget *scorehistorywindow; 385 extern GtkWidget *scorehistorytext; 386 387 /* option stuff */ 388 extern char robot_names[3][128]; 389 extern char robot_options[3][128]; 390 391 /* The window for messages, and the display text widget */ 392 extern GtkWidget *messagewindow, *messagetext; 393 /* and for warnings */ 394 extern GtkWidget *warningwindow, *warningtext; 395 extern GtkWidget *info_box; /* box to hold info windows */ 396 /* completed games, for nagging */ 397 extern int completed_games; 398 extern int nag_state; /* has user been nagged to pay? */ 399 /* window to nag for donations */ 400 extern GtkWidget *nag_window; 401 402 /* This gives the width of a player display in units 403 of tiles */ 404 405 extern int pdispwidth; 406 extern int display_size; /* and this is the preference value for pdispwidth */ 407 extern int square_aspect; /* force a square table */ 408 extern char address[]; /* server address */ 409 extern char name[]; /* player's name */ 410 extern char main_font_name[]; /* font used in all dialogs etc */ 411 extern char text_font_name[]; /* font used for text in windows */ 412 extern char fallback_text_font_name[]; /* one that worked */ 413 #ifdef GTK2 414 extern int use_system_gtkrc; /* as it says */ 415 extern char gtk2_rcfile[512]; /* gtkrc file to use */ 416 #endif 417 extern char table_colour_name[]; /* colour of the table background */ 418 extern int animate; /* do fancy animation */ 419 extern int nopopups; /* suppress automatic popup of message/scoring windows */ 420 extern int tiletips; /* show tiletips constantly */ 421 extern int rotatelabels; /* rotate player info labels on table */ 422 extern int showwall; /* show the wall or not */ 423 extern int sort_tiles; /* when to sort tiles */ 424 extern int info_windows_in_main; /* should the message and game info windows 425 be included in the main window, or 426 be separate popups ? */ 427 extern int iconify_dialogs_with_main; /* as it says ... */ 428 extern int thinking_claim; /* show ... before players have noclaimed */ 429 extern int alert_mahjong; /* pop up notice when can mahjong */ 430 extern char *tileset, *tileset_path; /* tile sets */ 431 extern int pref_showwall; /* preferred value of showwall */ 432 433 /* playing options */ 434 extern int playing_auto_declare_specials; 435 extern int playing_auto_declare_losing; 436 extern int playing_auto_declare_winning; 437 438 /* debug options */ 439 extern DebugReports debug_reports; /* send debugging reports? */ 440 441 /* the player display areas */ 442 extern PlayerDisp pdisps[NUM_SEATS]; 443 444 extern int calling; /* disgusting global flag */ 445 446 /* the widget in which we put discards */ 447 extern GtkWidget *discard_area; 448 /* This is an allocation structure in which we 449 note its allocated size, at some point when we 450 know the allocation is valid. 451 */ 452 extern GtkAllocation discard_area_alloc; 453 454 extern GtkWidget *just_doubleclicked; /* yech yech yech. See doubleclicked */ 455 456 /* space round edge of dialog boxes */ 457 extern const gint dialog_border_width; 458 /* horiz space between buttons */ 459 extern const gint dialog_button_spacing; 460 /* vert space between text and buttons etc */ 461 extern const gint dialog_vert_spacing; 462 463 /* space around player boxes. N.B. this should only 464 apply to the outermost boxes */ 465 extern const int player_border_width; 466 467 extern DialogPosition dialogs_position; 468 469 /* in gui-dial.c */ 470 extern GtkWidget *openfile, *openhost, *openport, 471 *openfiletext, *openhosttext, *openporttext, *openidtext, *opennametext, *opengamefiletext; 472 extern GtkWidget *display_option_dialog; 473 extern GtkWidget *game_option_dialog; 474 extern GtkWidget *game_prefs_dialog; 475 extern GtkWidget *game_option_panel; 476 extern GtkWidget *game_prefs_panel; 477 extern GameOptionTable prefs_table; 478 extern GtkWidget *playing_prefs_dialog; 479 /* static for each module */ 480 #include "version.h" 481 482