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