📄 gui.c
字号:
m.chow.cpos = the_game->tile - tsp->tile; break; case Pair: m.type = PMsgPair; break; case ClosedPung: m.type = PMsgFormClosedPung; m.formclosedpung.tile = tsp->tile; break; case ClosedChow: m.type = PMsgFormClosedChow; m.formclosedchow.tile = tsp->tile; break; case ClosedPair: m.type = PMsgFormClosedPair; m.formclosedpair.tile = tsp->tile; break; case Empty: /* can't happen, just to suppress warning */ case ClosedKong: /* ditto */ ; } send_packet(&m); } } } /* now deal with the display. There are basically two sorts of things to do: some triggered by a message, such as displaying draws, claims, etc; and some depending only on game state, such as making sure the right dialogs are up. We'll deal with message-dependent things first. */ switch ( m->type ) { case CMsgError: /* this has been dealt with above, and cannot happen */ warn("Error message in impossible place"); break; case CMsgPlayerOptionSet: /* this has been dealt with above, and cannot happen */ warn("PlayerOptionSet message in impossible place"); break; case CMsgStopPlay: { char buf[512]; strcpy(buf,"Server has suspended play because:\n"); strcat(buf,(m->stopplay.reason)); error_dialog_popup(buf); } break; case CMsgGameOption: /* update the timeout value */ if ( m->gameoption.optentry.option == GOTimeout ) { ptimeout = 1000*m->gameoption.optentry.value.optint; } /* if this is the Flowers option, recreate the declaring specials dialog */ if ( m->gameoption.optentry.option == GOFlowers ) { ds_dialog_init(); } /* and refresh the game option panel */ game_option_panel = build_or_refresh_option_panel(&the_game->option_table,game_option_panel); break; case CMsgGame: /* now we know the seating order: make the userdata field of each player point to the appropriate pdisp */ our_seat = game_id_to_seat(the_game,our_id); for ( i = 0; i < NUM_SEATS; i++ ) { set_player_userdata(the_game->players[i], (void *)&pdisps[game_to_board(i)]); /* and make the pdisp point to the player */ pdisps[game_to_board(i)].player = the_game->players[i]; } /* zap the game option dialog, because the option table has been reset */ game_option_panel = build_or_refresh_option_panel(NULL,game_option_panel); /* ask what the current options are */ { PMsgListGameOptionsMsg plgom; plgom.type = PMsgListGameOptions; plgom.include_disabled = 0; send_packet(&plgom); } /* and enable the menu item */ gtk_widget_set_sensitive(gameoptionsmenuentry,1); /* set the info on the scoring window */ for ( i=0; i < 4; i++ ) { gtk_label_set_text(GTK_LABEL(textlabels[i]), the_game->players[board_to_game(i)]->name); } break; case CMsgNewRound: /* update seat when it might change */ our_seat = game_id_to_seat(the_game,our_id); break; case CMsgNewHand: /* update seat when it might change */ our_seat = game_id_to_seat(the_game,our_id); /* After a new hand message, clear the display */ for ( i=0; i < 4; i++ ) { playerdisp_update(&pdisps[i],m); } discard_history.count = 0; /* need to set wallstart even if not showing wall, in case we change options */ wallstart = m->newhand.start_wall*(the_game->wall.size/4) + m->newhand.start_stack*2; gextras(the_game)->orig_live_end = the_game->wall.live_end; if ( showwall ) { create_wall(); adjust_wall_loose(the_game->wall.dead_end); /* set the loose tiles in place */ } break; case CMsgPlayerDiscards: /* if calling declaration, set flag */ if ( m->playerdiscards.calling ) calling = 1; /* and then update */ case CMsgPlayerFormsClosedPung: case CMsgPlayerDeclaresClosedKong: case CMsgPlayerAddsToPung: case CMsgPlayerFormsClosedChow: case CMsgPlayerFormsClosedPair: case CMsgPlayerShowsTiles: case CMsgPlayerFormsClosedSpecialSet: case CMsgPlayerDraws: case CMsgPlayerDrawsLoose: case CMsgPlayerDeclaresSpecial: case CMsgPlayerPairs: case CMsgPlayerChows: case CMsgPlayerPungs: case CMsgPlayerKongs: case CMsgPlayerSpecialSet: case CMsgPlayerClaimsPung: case CMsgPlayerClaimsKong: case CMsgPlayerClaimsChow: case CMsgPlayerClaimsMahJong: case CMsgSwapTile: playerdisp_update((PlayerDisp *)game_id_to_player(the_game,id)->userdata,m); break; case CMsgPlayerRobsKong: /* we need to update the victim */ playerdisp_update(&pdisps[game_to_board(the_game->supplier)],m); break; case CMsgGameOver: close_connection(); /* this has to come first, so that status_showraise doesn't try to update status info*/ status_showraise(); /* increment and save the game count */ if ( completed_games >= 0 ) { completed_games++; read_or_update_rcfile(NULL,XmjrcNone,XmjrcAll); }#ifndef WIN32 if ( nag_state == 0 && completed_games % 10 == 0 ) nag_popup();#endif return; /* in the following case, we need do nothing (in this switch) */ case CMsgInfoTiles: case CMsgConnectReply: case CMsgPlayer: case CMsgPause: case CMsgPlayerReady: case CMsgClaimDenied: case CMsgPlayerDoesntClaim: case CMsgDangerousDiscard: case CMsgCanMahJong: case CMsgHandScore: case CMsgSettlement: case CMsgChangeManager: case CMsgWall: case CMsgComment: break; case CMsgStateSaved: { static char buf[512]; strcpy(buf,"Game state saved in "); strncat(buf,m->statesaved.filename,512-strlen(buf)-2); info_dialog_popup(buf); break; } case CMsgStartPlay: /* If this is a new game, try to apply our option preferences */ if ( the_game->state == HandComplete && the_game->round == EastWind && the_game->players[east]->id == the_game->firsteast && the_game->hands_as_east == 0 && (the_game->manager == 0 || the_game->manager == our_id ) ) apply_game_prefs(); break; case CMsgMessage: { gtk_text_insert(GTK_TEXT(messagetext),0,0,0, "\n",-1); gtk_text_insert(GTK_TEXT(messagetext),0,0,0, m->message.sender == 0 ? "CONTROLLER" : game_id_to_player(the_game,m->message.sender)->name,-1); gtk_text_insert(GTK_TEXT(messagetext),0,0,0, "> ",-1); gtk_text_insert(GTK_TEXT(messagetext),0,0,0, m->message.text,-1); if ( !nopopups && !info_windows_in_main) { showraise(messagewindow); } } break; case CMsgPlayerMahJongs: /* this could be from hand. Clear all the texts in the scoring displays. Unselect tiles (if we're about to claim the discard, it's visually confusing seeing the first tile get selected; so instead, we'll select the first tile when we pop up the "declare closed sets" dialog. */ { int i; if ( the_game->player == our_seat ) conc_callback(NULL,NULL); for (i=0;i<5;i++) gtk_editable_delete_text(GTK_EDITABLE(textpages[i]),0,-1); } playerdisp_update((PlayerDisp *)game_id_to_player(the_game,id)->userdata,m); break; case CMsgWashOut: /* display a message in every window of the scoring info */ { CMsgWashOutMsg *wom = (CMsgWashOutMsg *)m; int i,npos=0; char text[1024] = "This hand is a WASH-OUT:\n"; text[1023] = 0; if ( wom->reason ) { strncat(text,wom->reason,1023-strlen(text)); } for (i=0;i<5;i++) { npos=0; gtk_editable_delete_text(GTK_EDITABLE(textpages[i]),0,-1); gtk_editable_insert_text(GTK_EDITABLE(textpages[i]), text,strlen(text),&npos); } if (!nopopups) { showraise(textwindow); } } } /* check the state of all the dialogs */ /* As a special case, if the message was a Message, we won't check the dialog state, since that forces focus to the control dialogs. If we send a message from a chat window incorporated into the main table, we probably do not expect to lose focus when our message arrives */ if ( m->type != CMsgMessage ) { setup_dialogs(); } /* after a HandScore message, stick the text in the display */ if ( m->type == CMsgHandScore || m->type == CMsgSettlement ) { static char bigbuf[8192]; CMsgHandScoreMsg *hsm = (CMsgHandScoreMsg *)m; CMsgSettlementMsg *sm = (CMsgSettlementMsg *)m; int pos,npos=0; char *text; if ( m->type == CMsgHandScore ) { pos = (game_id_to_seat(the_game,hsm->id)+NUM_SEATS-our_seat)%NUM_SEATS; text = hsm->explanation; } else { pos = 4; text = sm->explanation; } expand_protocol_text(bigbuf,text,8192); gtk_editable_insert_text(GTK_EDITABLE(textpages[pos]), bigbuf,strlen(bigbuf),&npos); if ( m->type == CMsgSettlement ) { if ( ! nopopups ) { gtk_widget_show(textwindow); gdk_window_show(textwindow->window); /* uniconify */ } } }}/* setup the dialogs appropriate to the game state */void setup_dialogs(void) { if ( ! the_game ) { gtk_widget_hide(discard_dialog->widget); /* that might have been left up */ return; } /* in the discarded state, the dialog box should be up if somebody else discarded and we haven't claimed. If we've claimed, it should be down. Further, if we have a chowclaim in and the chowpending flag is set, the chow dialog should be up. */ if ( the_game->state == Discarded && the_game->player != our_seat ) { int s; /* which player display is it? */ s = the_game->player; /* seat */ s = (s+NUM_SEATS-our_seat)%NUM_SEATS; /* posn relative to us */ if ( the_game->active && !the_game->paused && the_game->claims[our_seat] == UnknownClaim ) discard_dialog_popup(the_game->tile,s,0); else gtk_widget_hide(discard_dialog->widget); if ( the_game->active && !the_game->paused && the_game->claims[our_seat] == ChowClaim && the_game->chowpending ) do_chow(NULL,(gpointer)AnyPos); } /* check whether to pop down the claim windows */ { int i; for (i=0;i<4;i++) { if ( ! pdisps[i].claimw || ! GTK_WIDGET_VISIBLE(pdisps[i].claimw) ) continue; check_claim_window(&pdisps[i]); } } /* in discarded or mahjonging states, the turn dialog should be down */ if ( the_game->state == Discarded || the_game->state == MahJonging ) gtk_widget_hide(turn_dialog); /* in the discarding state, make sure the chow and ds dialogs are down. If it's our turn, the turn dialog should be up (unless we are in a konging state, when we're waiting for other claims), otherwise down. If there's a kong in progress, and we haven't claimed, the discard dialog should be up */ if ( the_game->state == Discarding ) { gtk_widget_hide(chow_dialog); gtk_widget_hide(ds_dialog); if ( the_game->active && !the_game->paused && the_game->player == our_seat && ! the_game->konging ) turn_dialog_popup(); else gtk_widget_hide(turn_dialog); if ( the_game->active && !the_game->paused && the_game->player != our_seat && the_game->konging && ! querykong /* wait till we know whether we can claim */ && the_game->claims[our_seat] == UnknownClaim ) { seats s; /* which player display is it? */ s = the_game->player; /* seat */ s = (s+NUM_SEATS-our_seat)%NUM_SEATS; /* posn relative to us */ discard_dialog_popup(the_game->tile,s,2); } else gtk_widget_hide(discard_dialog->widget); } /* If it is declaring specials time, and our turn, make sure the ds dialog is up. If it's not our turn, make sure it's down. Also make sure the turn and discard dialogs are down If somebody else has a kong in progress, and we haven't claimed, then the claim box should be up. */ if ( the_game->active && !the_game->paused && the_game->state == DeclaringSpecials ) { if ( the_game->player == our_seat ) { if ( !playing_auto_declare_specials || may_declare_kong ) ds_dialog_popup(); } else { gtk_widget_hide(ds_dialog); } gtk_widget_hide(turn_dialog); if ( the_game->konging && the_game->player != our_seat && the_game->claims[our_seat] == UnknownClaim ) { seats s; /* which player display is it? */ s = the_game->player; /* seat */ s = (s+NUM_SEATS-our_seat)%NUM_SEATS; /* posn relative to us */ discard_dialog_popup(the_game->tile,s,2); } else gtk_widget_hide(discard_dialog->widget); } else gtk_widget_hide(ds_dialog); /* In the mahjonging state, if we're the winner: If the pending flag is set, pop up the discard dialog if the chowpending is not set, otherwise the chowdialog. Otherwise, pop down both it and the chow dialog. Pop down the turn dialog. */ if ( the_game->state == MahJonging && the_game->player == our_seat ) { gtk_widget_hide(turn_dialog); if ( the_game->active && !the_game->paused && the_game->mjpending ) { int s; /* which player display is it? */ s = the_game->supplier; s = (s+NUM_SEATS-our_seat)%NUM_SEATS; /* posn relative to us */ if ( the_game->chowpending ) { do_chow(NULL,(gpointer)AnyPos); } else { discard_dialog_popup(the_game->tile,s,1); } } else { gtk_widget_hide(discard_dialog->widget); gtk_widget_hide(chow_dialog); }
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -