Crossfire Client, Trunk
account.c
Go to the documentation of this file.
1 /*
2  * Crossfire -- cooperative multi-player graphical RPG and adventure game
3  *
4  * Copyright (c) 1999-2013 Mark Wedel and the Crossfire Development Team
5  * Copyright (c) 1992 Frank Tore Johansen
6  *
7  * Crossfire is free software and comes with ABSOLUTELY NO WARRANTY. You are
8  * welcome to redistribute it under certain conditions. For details, see the
9  * 'LICENSE' and 'COPYING' files.
10  *
11  * The authors can be reached via e-mail to crossfire-devel@real-time.com
12  */
13 
19 #include "client.h"
20 
21 #include <ctype.h>
22 #include <gtk/gtk.h>
23 
24 #include "image.h"
25 #include "main.h"
26 #include "metaserver.h"
27 #include "gtk2proto.h"
28 #include "script.h"
29 
30 /* These are in the login_window */
33 
34 /* These are in the create_account_window */
39 
40 /* These are in the choose_character window */
44 
45 /* These are in the new_character window */
49 
50 /* These are in the account_password window */
54 
55 GtkListStore *character_store;
56 
57 /* create_char.c also uses this */
58 char account_password[256];
59 
60 /* This enum just maps the columns in the list store to their position.
61  */
64  };
65 #define CHAR_NUM_COLUMNS 8
66 
67 /* These are in the add_character window */
68 static GtkWidget *button_do_add_character,
71 
74 
75 /* These are used as offsets for num_text_views - we share the drawing code in
76  * info.c if more textviews are added, note that NUM_TEXT_VIEWS in info.c
77  * needs to be increased.
78  */
79 #define TEXTVIEW_MOTD 0
80 #define TEXTVIEW_NEWS 1
81 #define TEXTVIEW_RULES_ACCOUNT 2
82 #define TEXTVIEW_RULES_CHAR 3
83 
85 
86 extern int num_text_views;
87 
88 static int has_init = 0;
89 
97  extern GtkWidget *treeview_look;
98  gtk_widget_hide(connect_window);
99 
100  if (has_init) {
101  /* If we have not initialized, nothing to hide */
102  gtk_widget_hide(new_character_window);
103  create_character_window_hide(); /* create_char.c */
104 
105  /* If the player has started playing (this function being called from
106  * AddMeSuccess), we want to make sure that the extended command entry
107  * widget is not activated - we want normal command entry. Where this
108  * shows up is if the player was playing before and uses a savebed -
109  * now the last thing activated is that entry widget.
110  */
111  gtk_widget_grab_focus(GTK_WIDGET(treeview_look));
112  }
113 }
114 
123 gboolean on_window_delete_event(GtkWidget *window, gpointer *user_data) {
124  return TRUE;
125 }
126 
127 /*****************************************************************************
128  * New character window functions
129  *****************************************************************************/
130 
142 void create_new_character_failure(char *message) {
144  GtkWidget *dialog;
145 
146  dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_DESTROY_WITH_PARENT,
147  GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK,
148  "Error: %s", message);
149  gtk_dialog_run(GTK_DIALOG(dialog));
150  gtk_widget_destroy(dialog);
151 }
152 
153 static void create_new_character() {
154  const char *name;
155  guint8 buf[MAX_BUF];
156  SockList sl;
157 
158  SockList_Init(&sl, buf);
159 
160  name = gtk_entry_get_text(GTK_ENTRY(entry_new_character_name));
161 
162  if (!name || *name == 0) {
163  gtk_label_set_text(GTK_LABEL(label_new_char_status),
164  "You must enter a character name.");
165  return;
166  } else {
167  gtk_label_set_text(GTK_LABEL(label_new_char_status), "");
168 
169  SockList_AddString(&sl, "createplayer ");
170  SockList_AddChar(&sl, strlen(name));
171  SockList_AddString(&sl, name);
172  SockList_AddChar(&sl, strlen(account_password));
174  SockList_Send(&sl, csocket.fd);
175  }
176 }
177 
183 void
184 on_button_create_new_char_clicked(GtkButton *button, gpointer user_data) {
186 }
187 
194 void on_entry_new_character_name(GtkEntry *entry, gpointer user_data) {
196 }
197 
204 void
205 on_button_new_char_cancel_clicked(GtkButton *button, gpointer user_data) {
206  gtk_widget_hide(new_character_window);
208 }
209 
215  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "create_character_window"));
216 
217  gtk_window_set_transient_for(
218  GTK_WINDOW(new_character_window), GTK_WINDOW(window_root));
219 
221  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_create_character"));
223  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_cc_cancel"));
225  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "cc_entry_new_character_name"));
227  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "label_cc_status_update"));
228 
229  g_signal_connect((gpointer) new_character_window, "delete_event",
230  G_CALLBACK(on_window_delete_event), NULL);
231  g_signal_connect((gpointer) button_create_new_char, "clicked",
232  G_CALLBACK(on_button_create_new_char_clicked), NULL);
233  g_signal_connect((gpointer) button_new_char_cancel, "clicked",
234  G_CALLBACK(on_button_new_char_cancel_clicked), NULL);
235  g_signal_connect((gpointer) entry_new_character_name, "activate",
236  G_CALLBACK(on_entry_new_character_name), NULL);
237 }
238 
239 /******************************************************************************
240  * add_character_window functions
241  *****************************************************************************/
242 
249 static void add_character_to_account(const char *name, const char *password,
250  int force) {
251  SockList sl;
252  guint8 buf[MAX_BUF];
253 
254  if (!name || !password || *name == 0 || *password == 0) {
255  gtk_label_set_text(GTK_LABEL(label_add_status),
256  "You must enter both a name and password!");
257  } else {
258  gtk_label_set_text(GTK_LABEL(label_add_status), "");
259 
260  SockList_Init(&sl, buf);
261  SockList_AddString(&sl, "accountaddplayer ");
262  SockList_AddChar(&sl, force);
263  SockList_AddChar(&sl, strlen(name));
264  SockList_AddString(&sl, name);
265  SockList_AddChar(&sl, strlen(password));
266  SockList_AddString(&sl, password);
267  SockList_Send(&sl, csocket.fd);
268  }
269 }
270 
282 void account_add_character_failure(char *message) {
283  char *cp;
284  int retry;
285 
286  retry = atoi(message);
287  cp = strchr(message, ' ');
288  if (cp) {
289  cp++;
290  } else {
291  cp = message;
292  }
293 
294  if (!retry) {
295  gtk_label_set_text(GTK_LABEL(label_add_status), cp);
296  } else {
297  /* In this case, we can retry it and it should work if we set force.
298  * So bring up a dialog, as the user what to do - if they enter yes,
299  * we use force. If not, we clear the entry fields and just continue
300  * onward.
301  */
302  GtkWidget *dialog;
303  int result;
304  const char *name, *password;
305 
306  /* Bring up a dialog window */
307  dialog =
308  gtk_message_dialog_new(NULL, GTK_DIALOG_DESTROY_WITH_PARENT,
309  GTK_MESSAGE_QUESTION,
310  GTK_BUTTONS_YES_NO, "%s\n%s", cp, "Apply anyways?");
311  result = gtk_dialog_run(GTK_DIALOG(dialog));
312  gtk_widget_destroy(dialog);
313 
314  if (result == GTK_RESPONSE_YES) {
315  name = gtk_entry_get_text(GTK_ENTRY(entry_character_name));
316  password = gtk_entry_get_text(GTK_ENTRY(entry_character_password));
317  add_character_to_account(name, password, 1);
318  } else {
319  gtk_entry_set_text(GTK_ENTRY(entry_character_name), "");
320  gtk_entry_set_text(GTK_ENTRY(entry_character_password), "");
321  gtk_widget_grab_focus(entry_character_name);
322  }
323  }
324 }
325 
333 void
334 on_button_do_add_character_clicked(GtkButton *button, gpointer user_data) {
336  gtk_entry_get_text(GTK_ENTRY(entry_character_name)),
337  gtk_entry_get_text(GTK_ENTRY(entry_character_password)), 0);
338 }
339 
347 void
349  gpointer user_data) {
350  gtk_notebook_set_current_page(main_notebook, 3);
351 }
352 
361 void on_entry_character(GtkEntry *entry, gpointer user_data) {
362  const char *name, *password;
363 
364  name = gtk_entry_get_text(GTK_ENTRY(entry_character_name));
365  password = gtk_entry_get_text(GTK_ENTRY(entry_character_password));
366 
367  if (name && name[0] && password && password[0]) {
368  add_character_to_account(name, password, 0);
369  } else {
370  const char *cp;
371 
372  /* First case - this widget is empty - do nothing */
373  cp = gtk_entry_get_text(entry);
374  if (!cp || !cp[0]) {
375  return;
376  }
377 
378  /* In this case, this widget is not empty - means the other one is.
379  */
380  if (entry == GTK_ENTRY(entry_character_name)) {
381  gtk_widget_grab_focus(entry_character_password);
382  } else {
383  gtk_widget_grab_focus(entry_character_name);
384  }
385  }
386 }
387 
390  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_do_add_character"));
392  GTK_WIDGET(gtk_builder_get_object(dialog_xml,
393  "button_return_character_select"));
395  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "entry_character_name"));
397  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "entry_character_password"));
399  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "label_add_status"));
400 
401  g_signal_connect((gpointer) button_do_add_character, "clicked",
402  G_CALLBACK(on_button_do_add_character_clicked), NULL);
403  g_signal_connect((gpointer) button_return_character_select, "clicked",
405  g_signal_connect((gpointer) entry_character_name, "activate",
406  G_CALLBACK(on_entry_character), NULL);
407  g_signal_connect((gpointer) entry_character_password, "activate",
408  G_CALLBACK(on_entry_character), NULL);
409 }
410 
411 /*****************************************************************************
412  * choose_char_window
413  ****************************************************************************/
414 
424 
425  /* Store any old/stale entries */
426  gtk_list_store_clear(character_store);
427 }
428 
437  gtk_notebook_set_current_page(main_notebook, 3);
438 }
439 
440 
445 static void play_character(const char *name) {
446  SockList sl;
447  guint8 buf[MAX_BUF];
448 
449  SockList_Init(&sl, buf);
450  SockList_AddString(&sl, "accountplay ");
451  SockList_AddString(&sl, name);
452  SockList_Send(&sl, csocket.fd);
453 }
454 
461 void
462 on_button_play_character_clicked(GtkButton *button, gpointer user_data) {
463  GtkTreeSelection *selected;
464  GtkTreeModel *model;
465  GtkTreeIter iter;
466  char *name;
467 
468  selected = gtk_tree_view_get_selection(GTK_TREE_VIEW(
470 
471  if (gtk_tree_selection_get_selected(selected, &model, &iter)) {
472  gtk_tree_model_get(model, &iter, CHAR_NAME, &name, -1);
474  play_character(name);
475  }
476 }
477 
483 void
484 on_button_create_character_clicked(GtkButton *button, gpointer user_data) {
485  if (serverloginmethod >= 2) {
487  } else {
488  gtk_widget_show(new_character_window);
489  gtk_entry_set_text(GTK_ENTRY(entry_new_character_name), "");
490  }
491 }
492 
499 void
500 on_button_add_character_clicked(GtkButton *button, gpointer user_data) {
501  gtk_notebook_set_current_page(main_notebook, 5);
502  gtk_entry_set_text(GTK_ENTRY(entry_character_name), "");
503  gtk_entry_set_text(GTK_ENTRY(entry_character_password), "");
504  gtk_widget_grab_focus(entry_character_name);
505 }
506 
513 void
514 on_button_return_login_clicked(GtkButton *button, gpointer user_data) {
515  gtk_notebook_set_current_page(main_notebook, 1);
516 }
517 
524 void
525 on_button_account_password_clicked(GtkButton *button, gpointer user_data) {
526  gtk_notebook_set_current_page(main_notebook, 4);
527  /* reset previous values */
528  gtk_entry_set_text(GTK_ENTRY(entry_account_password_current), "");
529  gtk_entry_set_text(GTK_ENTRY(entry_account_password_new), "");
530  gtk_entry_set_text(GTK_ENTRY(entry_account_password_confirm), "");
531 }
532 
547 void update_character_choose(const char *name, const char *class,
548  const char *race, const char *face,
549  const char *party, const char *map,
550  int level, int faceno) {
551  GtkTreeIter iter;
552 
553  gtk_list_store_append(character_store, &iter);
554 
555  /* If this pixmap matches pixmap[0], it means we are caching images and
556  * this image hasn't been set up. It looks better in this case to just
557  * leave that area of the window blank vs drawing a question mark there.
558  */
559  if (pixmaps[faceno] == pixmaps[0]) {
560  gtk_list_store_set(character_store, &iter,
561  CHAR_NAME, name,
562  CHAR_CLASS, class,
563  CHAR_RACE, race,
564  CHAR_IMAGE, face,
565  CHAR_PARTY, party,
566  CHAR_MAP, map,
567  CHAR_LEVEL, level,
568  -1);
569  } else {
570  gtk_list_store_set(character_store, &iter,
571  CHAR_ICON, pixmaps[faceno]->icon_image,
572  CHAR_NAME, name,
573  CHAR_CLASS, class,
574  CHAR_RACE, race,
575  CHAR_IMAGE, face,
576  CHAR_PARTY, party,
577  CHAR_MAP, map,
578  CHAR_LEVEL, level,
579  -1);
580  }
581 }
582 
583 static void init_choose_char_window() {
584  GtkTextIter end;
585  GtkCellRenderer *renderer;
586  GtkTreeViewColumn *column;
587 
589  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_play_character"));
591  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_create_character"));
593  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_add_character"));
595  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_return_login"));
597  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_account_password"));
599  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "textview_rules_char"));
600 
602  gtk_text_view_get_buffer(
603  GTK_TEXT_VIEW(login_pane[TEXTVIEW_RULES_CHAR].textview));
604 
606  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "treeview_choose_character"));
607 
611  gtk_text_buffer_get_end_iter(
612  login_pane[TEXTVIEW_RULES_CHAR].textbuffer, &end);
614  gtk_text_buffer_create_mark(
615  login_pane[TEXTVIEW_RULES_CHAR].textbuffer, NULL, &end, FALSE);
616 
617  g_signal_connect((gpointer) button_play_character, "clicked",
618  G_CALLBACK(on_button_play_character_clicked), NULL);
619  g_signal_connect((gpointer) button_create_character, "clicked",
620  G_CALLBACK(on_button_create_character_clicked), NULL);
621  g_signal_connect((gpointer) button_add_character, "clicked",
622  G_CALLBACK(on_button_add_character_clicked), NULL);
623  g_signal_connect((gpointer) button_return_login, "clicked",
624  G_CALLBACK(on_button_return_login_clicked), NULL);
625  g_signal_connect((gpointer) button_account_password, "clicked",
626  G_CALLBACK(on_button_account_password_clicked), NULL);
627  g_signal_connect((gpointer) treeview_choose_character, "row_activated",
628  G_CALLBACK(on_button_play_character_clicked), NULL);
629 
630  character_store = gtk_list_store_new(CHAR_NUM_COLUMNS,
631  G_TYPE_STRING, G_TYPE_STRING,
632  G_TYPE_STRING, G_TYPE_STRING,
633  G_TYPE_INT, G_TYPE_STRING,
634  G_TYPE_STRING, G_TYPE_OBJECT);
635  gtk_tree_view_set_model(GTK_TREE_VIEW(treeview_choose_character),
636  GTK_TREE_MODEL(character_store));
637 
638  renderer = gtk_cell_renderer_pixbuf_new();
639  column = gtk_tree_view_column_new_with_attributes("?", renderer,
640  "pixbuf", CHAR_ICON,
641  NULL);
642 
643  gtk_tree_view_column_set_min_width(column, image_size);
644  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_choose_character), column);
645 
646  renderer = gtk_cell_renderer_text_new();
647  column = gtk_tree_view_column_new_with_attributes("Character Name", renderer,
648  "text", CHAR_NAME, NULL);
649  gtk_tree_view_column_set_sort_column_id(column, CHAR_NAME);
650  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_choose_character), column);
651 
652  renderer = gtk_cell_renderer_text_new();
653  column = gtk_tree_view_column_new_with_attributes("Class", renderer,
654  "text", CHAR_CLASS, NULL);
655  gtk_tree_view_column_set_sort_column_id(column, CHAR_CLASS);
656  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_choose_character), column);
657 
658  renderer = gtk_cell_renderer_text_new();
659  column = gtk_tree_view_column_new_with_attributes("Race", renderer,
660  "text", CHAR_RACE, NULL);
661  gtk_tree_view_column_set_sort_column_id(column, CHAR_RACE);
662  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_choose_character), column);
663 
664  renderer = gtk_cell_renderer_text_new();
665  column = gtk_tree_view_column_new_with_attributes("Level", renderer,
666  "text", CHAR_LEVEL, NULL);
667  gtk_tree_view_column_set_sort_column_id(column, CHAR_LEVEL);
668  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_choose_character), column);
669 
670  renderer = gtk_cell_renderer_text_new();
671  column = gtk_tree_view_column_new_with_attributes("Party", renderer,
672  "text", CHAR_PARTY, NULL);
673  gtk_tree_view_column_set_sort_column_id(column, CHAR_PARTY);
674  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_choose_character), column);
675 
676  renderer = gtk_cell_renderer_text_new();
677  column = gtk_tree_view_column_new_with_attributes("Map", renderer,
678  "text", CHAR_MAP, NULL);
679  gtk_tree_view_column_set_sort_column_id(column, CHAR_MAP);
680  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_choose_character), column);
681 }
682 
683 /******************************************************************************
684  * create_account_window
685  ******************************************************************************/
686 
692 void account_creation_failure(char *message) {
693  gtk_label_set_text(GTK_LABEL(label_create_account_status), message);
694 }
695 
708 static void do_account_create(const char *name, const char *p1,
709  const char *p2) {
710  SockList sl;
711  guint8 buf[MAX_BUF];
712 
713  if (strcmp(p1, p2)) {
714  gtk_label_set_text(GTK_LABEL(label_create_account_status),
715  "The passwords you entered do not match!");
716  return;
717  } else {
718  gtk_label_set_text(GTK_LABEL(label_create_account_status), "");
719  SockList_Init(&sl, buf);
720  SockList_AddString(&sl, "accountnew ");
721  SockList_AddChar(&sl, strlen(name));
722  SockList_AddString(&sl, name);
723  SockList_AddChar(&sl, strlen(p1));
724  SockList_AddString(&sl, p1);
725  SockList_Send(&sl, csocket.fd);
726  /* Store password away for new character creation */
727  snprintf(account_password, sizeof(account_password), "%s", p1);
728  }
729 }
730 
737 void
738 on_button_new_create_account_clicked(GtkButton *button, gpointer user_data) {
739  const char *password1, *password2, *name;
740 
741  password1 = gtk_entry_get_text(GTK_ENTRY(entry_new_account_password));
742  password2 = gtk_entry_get_text(GTK_ENTRY(entry_new_confirm_password));
743  name = gtk_entry_get_text(GTK_ENTRY(entry_new_account_name));
744 
745  if (name && name[0] && password1 && password1[0] && password2 && password2[0]) {
746  do_account_create(name, password1, password2);
747  } else {
748  gtk_label_set_text(GTK_LABEL(label_create_account_status),
749  "You must fill in all three entries!");
750  }
751 }
752 
758 void
759 on_button_new_cancel_clicked(GtkButton *button, gpointer user_data) {
760  gtk_notebook_set_current_page(main_notebook, 1);
761 }
762 
772 void
773 on_entry_new_account(GtkEntry *entry, gpointer user_data) {
774 
775  const char *password1, *password2, *name, *cp;
776 
777  password1 = gtk_entry_get_text(GTK_ENTRY(entry_new_account_password));
778  password2 = gtk_entry_get_text(GTK_ENTRY(entry_new_confirm_password));
779  name = gtk_entry_get_text(GTK_ENTRY(entry_new_account_name));
780  if (name && name[0] && password1 && password1[0] && password2 && password2[0]) {
781  do_account_create(name, password1, password2);
782  } else {
783  /* In this case, one, or more, of the fields is blank. If there were
784  * more than 3 widgets, I might but them into an array to make cycling
785  * easier
786  */
787 
788  /* First case - if the currently active one is blank, no reason to
789  * move onward.
790  */
791  cp = gtk_entry_get_text(entry);
792  if (!cp || !cp[0]) {
793  return;
794  }
795 
796  /* I'm not sure if it would make more sense to advance to the first
797  * NULL entry - but in that case, the pointer may hop in non intuitive
798  * ways - in this case, the user may just need to hit return a few
799  * times - MSW 2010/03/29
800  */
801  if (entry == GTK_ENTRY(entry_new_account_name)) {
802  gtk_widget_grab_focus(entry_new_account_password);
803  } else if (entry == GTK_ENTRY(entry_new_account_password)) {
804  gtk_widget_grab_focus(entry_new_confirm_password);
805  } else if (entry == GTK_ENTRY(entry_new_confirm_password)) {
806  gtk_widget_grab_focus(entry_new_account_name);
807  }
808  }
809 }
810 
816  GtkTextIter end;
817 
819  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_new_create_account"));
821  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_new_cancel"));
823  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "textview_rules_account"));
824 
826  gtk_text_view_get_buffer(
827  GTK_TEXT_VIEW(login_pane[TEXTVIEW_RULES_ACCOUNT].textview));
828 
830  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "entry_new_account_name"));
832  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "entry_new_account_password"));
834  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "entry_new_confirm_password"));
836  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "label_create_account_status"));
837 
841  gtk_text_buffer_get_end_iter(
842  login_pane[TEXTVIEW_RULES_ACCOUNT].textbuffer, &end);
844  gtk_text_buffer_create_mark(
845  login_pane[TEXTVIEW_RULES_ACCOUNT].textbuffer, NULL, &end, FALSE);
846 
847  g_signal_connect((gpointer) button_new_create_account, "clicked",
848  G_CALLBACK(on_button_new_create_account_clicked), NULL);
849  g_signal_connect((gpointer) button_new_cancel, "clicked",
850  G_CALLBACK(on_button_new_cancel_clicked), NULL);
851  g_signal_connect((gpointer) entry_new_account_name, "activate",
852  G_CALLBACK(on_entry_new_account), NULL);
853  g_signal_connect((gpointer) entry_new_account_password, "activate",
854  G_CALLBACK(on_entry_new_account), NULL);
855  g_signal_connect((gpointer) entry_new_confirm_password, "activate",
856  G_CALLBACK(on_entry_new_account), NULL);
857 }
858 
859 /*****************************************************************************
860  * login_window
861  *****************************************************************************/
862 
868 void account_login_failure(char *message) {
869  gtk_label_set_text(GTK_LABEL(label_account_login_status), message);
870 }
871 
878 void
879 on_button_create_account_clicked(GtkButton *button, gpointer user_data) {
880  gtk_label_set_text(GTK_LABEL(label_create_account_status), "");
881  gtk_entry_set_text(GTK_ENTRY(entry_new_account_name), "");
882  gtk_entry_set_text(GTK_ENTRY(entry_new_account_password), "");
883  gtk_entry_set_text(GTK_ENTRY(entry_new_confirm_password), "");
884  gtk_notebook_set_current_page(main_notebook, 2);
885 }
886 
894 void
895 on_button_go_metaserver_clicked(GtkButton *button, gpointer user_data) {
897 }
898 
904 void on_button_exit_client_clicked(GtkButton *button, gpointer user_data) {
905  script_killall();
906  exit(0);
907 }
908 
916 static void do_account_login(const char *name, const char *password) {
917  SockList sl;
918  guint8 buf[MAX_BUF];
919 
920  if (!name || !password || *name == 0 || *password == 0) {
921  gtk_label_set_text(GTK_LABEL(label_account_login_status),
922  "You must enter both a name and password!");
923  } else {
924  gtk_label_set_text(GTK_LABEL(label_account_login_status), "");
925 
926  SockList_Init(&sl, buf);
927  SockList_AddString(&sl, "accountlogin ");
928  SockList_AddChar(&sl, strlen(name));
929  SockList_AddString(&sl, name);
930  SockList_AddChar(&sl, strlen(password));
931  SockList_AddString(&sl, password);
932  SockList_Send(&sl, csocket.fd);
933  /* Store password away for new character creation */
934  snprintf(account_password, sizeof(account_password), "%s", password);
935  }
936 }
937 
943 void
944 on_button_login_clicked(GtkButton *button, gpointer user_data) {
945  do_account_login(gtk_entry_get_text(GTK_ENTRY(entry_account_name)),
946  gtk_entry_get_text(GTK_ENTRY(entry_account_password)));
947 }
948 
954 void on_entry_account_name_activate(GtkEntry* entry, gpointer user_data) {
955  gtk_widget_grab_focus(entry_account_password);
956 }
957 
962 static void init_login_window() {
963  GtkTextIter end;
964 
965  button_login =
966  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_login"));
968  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_create_account"));
970  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_go_metaserver"));
972  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "label_account_login_status"));
974  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "textview_motd"));
975 
976  textbuf_motd =
977  gtk_text_view_get_buffer(
978  GTK_TEXT_VIEW(login_pane[TEXTVIEW_MOTD].textview));
979 
982  gtk_text_buffer_get_end_iter(login_pane[TEXTVIEW_MOTD].textbuffer, &end);
984  gtk_text_buffer_create_mark(
985  login_pane[TEXTVIEW_MOTD].textbuffer, NULL, &end, FALSE);
986 
988  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "textview_news"));
989 
990  textbuf_news =
991  gtk_text_view_get_buffer(
992  GTK_TEXT_VIEW(login_pane[TEXTVIEW_NEWS].textview));
993 
996  gtk_text_buffer_get_end_iter(login_pane[TEXTVIEW_NEWS].textbuffer, &end);
998  gtk_text_buffer_create_mark(
999  login_pane[TEXTVIEW_NEWS].textbuffer, NULL, &end, FALSE);
1000 
1002  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "entry_account_name"));
1004  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "entry_account_password"));
1005 
1006  g_signal_connect((gpointer) entry_account_name, "activate",
1007  G_CALLBACK(on_entry_account_name_activate), NULL);
1008  // entry_account_password is the default action in GtkBuilder
1009  g_signal_connect((gpointer) button_login, "clicked",
1010  G_CALLBACK(on_button_login_clicked), NULL);
1011  g_signal_connect((gpointer) button_create_account, "clicked",
1012  G_CALLBACK(on_button_create_account_clicked), NULL);
1013  g_signal_connect((gpointer) button_go_metaserver, "clicked",
1014  G_CALLBACK(on_button_go_metaserver_clicked), NULL);
1015 }
1016 
1017 /*****************************************************************************
1018  * Account password change
1019  ****************************************************************************/
1020 
1033 static void do_account_change(const char *old, const char *p1, const char *p2) {
1034  SockList sl;
1035  guint8 buf[MAX_BUF];
1036 
1037  if (strcmp(p1, p2)) {
1038  gtk_label_set_text(GTK_LABEL(label_account_password_status),
1039  "The passwords you entered do not match!");
1040  return;
1041  } else {
1042  gtk_label_set_text(GTK_LABEL(label_account_password_status), "");
1043  SockList_Init(&sl, buf);
1044  SockList_AddString(&sl, "accountpw ");
1045  SockList_AddChar(&sl, strlen(old));
1046  SockList_AddString(&sl, old);
1047  SockList_AddChar(&sl, strlen(p1));
1048  SockList_AddString(&sl, p1);
1049  SockList_Send(&sl, csocket.fd);
1050  /* Store password away for new character creation */
1051  snprintf(account_password, sizeof(account_password), "%s", p1);
1052  }
1053 }
1054 
1061 void
1063  gpointer user_data) {
1064  gtk_notebook_set_current_page(main_notebook, 3);
1065 }
1066 
1072 void
1074  gpointer user_data) {
1075  do_account_change(gtk_entry_get_text(GTK_ENTRY(entry_account_password_current)),
1076  gtk_entry_get_text(GTK_ENTRY(entry_account_password_new)),
1077  gtk_entry_get_text(GTK_ENTRY(entry_account_password_confirm)));
1078 }
1079 
1089 void
1090 on_entry_account_password(GtkEntry *entry, gpointer user_data) {
1091 
1092  const char *old, *password1, *password2, *cp;
1093 
1094  old = gtk_entry_get_text(GTK_ENTRY(entry_account_password_current));
1095  password1 = gtk_entry_get_text(GTK_ENTRY(entry_account_password_new));
1096  password2 = gtk_entry_get_text(GTK_ENTRY(entry_account_password_confirm));
1097  if (old && old[0] && password1 && password1[0] && password2 && password2[0]) {
1098  do_account_change(old, password1, password2);
1099  } else {
1100  /* In this case, one, or more, of the fields is blank. If there were
1101  * more than 3 widgets, I might but them into an array to make cycling
1102  * easier
1103  */
1104 
1105  /* First case - if the currently active one is blank, no reason to
1106  * move onward.
1107  */
1108  cp = gtk_entry_get_text(entry);
1109  if (!cp || !cp[0]) {
1110  return;
1111  }
1112 
1113  if (entry == GTK_ENTRY(entry_account_password_current)) {
1114  gtk_widget_grab_focus(entry_account_password_new);
1115  } else if (entry == GTK_ENTRY(entry_account_password_new)) {
1116  gtk_widget_grab_focus(entry_account_password_confirm);
1117  } else if (entry == GTK_ENTRY(entry_account_password_confirm)) {
1118  gtk_widget_grab_focus(entry_account_password_current);
1119  }
1120  }
1121 }
1122 
1123 void account_change_password_failure(char *message) {
1124  gtk_label_set_text(GTK_LABEL(label_account_password_status), message);
1125 }
1126 
1133  GTK_WIDGET(gtk_builder_get_object(dialog_xml,
1134  "button_account_password_confirm"));
1136  GTK_WIDGET(gtk_builder_get_object(dialog_xml,
1137  "button_account_password_cancel"));
1138 
1140  GTK_WIDGET(gtk_builder_get_object(dialog_xml,
1141  "entry_account_password_current"));
1143  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "entry_account_password_new"));
1145  GTK_WIDGET(gtk_builder_get_object(dialog_xml,
1146  "entry_account_password_confirm"));
1148  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "label_account_password_status"));
1149 
1150  g_signal_connect((gpointer) button_account_password_confirm, "clicked",
1151  G_CALLBACK(on_button_account_password_confirm_clicked), NULL);
1152  g_signal_connect((gpointer) button_account_password_cancel, "clicked",
1153  G_CALLBACK(on_button_account_password_cancel_clicked), NULL);
1154  g_signal_connect((gpointer) entry_account_password_current, "activate",
1155  G_CALLBACK(on_entry_account_password), NULL);
1156  g_signal_connect((gpointer) entry_account_password_new, "activate",
1157  G_CALLBACK(on_entry_account_password), NULL);
1158  g_signal_connect((gpointer) entry_account_password_confirm, "activate",
1159  G_CALLBACK(on_entry_account_password), NULL);
1160 }
1161 
1162 
1163 /*****************************************************************************
1164  * Common/generic functions
1165  ****************************************************************************/
1166 
1174 void update_login_info(int type) {
1175  if (!has_init) {
1176  return;
1177  }
1178 
1179  /* In all cases, we clear the buffer, and if we have data, then set it to
1180  * that data. This routine could be smarter an
1181  */
1182  if (type == INFO_NEWS) {
1183  gtk_text_buffer_set_text(textbuf_news, "", 0);
1184  if (news) {
1185  /* the format of the news entry is special - there are a series of
1186  * %entries, and they are in reverse older (newest last) we want
1187  * to get rid of the %, make them more visible (convert them to
1188  * bold) and reverse the order.
1189  */
1190  char *mynews, *cp, *el, big_buf[BIG_BUF], *cp1;
1191 
1192  mynews = g_strdup(news);
1193  /* We basically work from the end of the string going towards the
1194  * start looking for % characters. If we find one, we have to
1195  * make sure it is at the start of the line or start of the buffer
1196  */
1197  for (cp = mynews + strlen(mynews); cp > mynews; cp--) {
1198  if (*cp == '%' && (*(cp - 1) == '\n' || cp == mynews)) {
1199  /* Find the end of the line */
1200  el = strchr(cp, '\n');
1201  /* null out the newline, put el one char beyond it */
1202  if (el) {
1203  *el = 0;
1204  el++;
1205  }
1206  /* There isn't a clear standard - % news may be valid, as
1207  * might be %news. If % news is used, it looks better to
1208  * get rid of that leading space.
1209  */
1210  cp1 = cp + 1;
1211  while (isspace(*cp1)) {
1212  cp1++;
1213  }
1214 
1215  /* since we've null out the newline, this snprintf will
1216  * only get the % line and that is it. Mark it up
1217  */
1218  snprintf(big_buf, BIG_BUF, "[b]%s[/b]", cp1);
1219  add_marked_text_to_pane(&login_pane[TEXTVIEW_NEWS], big_buf, 0, 0, 0);
1220  /* Now we draw the text that goes with it, if it exists */
1221  if (el) {
1223  }
1224 
1225  /* Now we wipe the % out. In this way, the news buffer is
1226  * shorter, so when it draws the ext, there will just be
1227  * that between the % and the one we just wiped out.
1228  */
1229  *cp = 0;
1230  }
1231  }
1232  /* If there are remnants left over, or perhaps the news file isn't
1233  * formatted with % headers, display what we have got.
1234  */
1235  if (*mynews != 0) {
1236  add_marked_text_to_pane(&login_pane[TEXTVIEW_NEWS], mynews, 0, 0, 0);
1237  }
1238  }
1239  } else if (type == INFO_MOTD) {
1240  gtk_text_buffer_set_text(textbuf_motd, "", 0);
1241  if (motd) {
1243  }
1244  } else if (type == INFO_RULES) {
1245  gtk_text_buffer_set_text(textbuf_rules_account, "", 0);
1246  gtk_text_buffer_set_text(textbuf_rules_char, "", 0);
1247 
1248  if (rules) {
1251  }
1252  }
1253 }
1254 
1263 void start_login(int method) {
1264  /* Store this away - if method is only 1, we can not do smart character
1265  * creation.
1266  */
1267  serverloginmethod = method;
1268 
1269  if (!has_init) {
1270  /* Since there are 4 windows associated with account and character
1271  * login, to make life a little easier, each section here does all the
1272  * work for one window, so it is easier to see that everything for a
1273  * window is done - don't need to hunt through what would otherwise be
1274  * a long routine looking for entries.
1275  */
1277 
1279 
1281 
1283 
1285 
1287 
1288  has_init = 1;
1289 
1290  /* In case we have gotten news/motd/rules before getting here, update
1291  * it now.
1292  */
1296  }
1297 
1298  gtk_entry_set_text(GTK_ENTRY(entry_account_name), "");
1299  gtk_entry_set_text(GTK_ENTRY(entry_account_password), "");
1300 }
1301 
1303  gtk_notebook_set_current_page(main_notebook, 1);
1304  /* We set focus to account name - this makes the most sense if user is
1305  * logging in again - it is possible that the password is active, but both
1306  * fields are blank, which is not what is expected.
1307  */
1308  gtk_widget_grab_focus(entry_account_name);
1309  gtk_widget_grab_default(button_login);
1310 }
update_login_info
void update_login_info(int type)
Definition: account.c:1174
on_button_account_password_cancel_clicked
void on_button_account_password_cancel_clicked(GtkButton *button, gpointer user_data)
Definition: account.c:1062
choose_char_window_show
void choose_char_window_show()
Definition: account.c:436
CHAR_ICON
@ CHAR_ICON
Definition: account.c:63
on_button_return_character_select_clicked
void on_button_return_character_select_clicked(GtkButton *button, gpointer user_data)
Definition: account.c:348
entry_new_account_password
static GtkWidget * entry_new_account_password
Definition: account.c:37
news
char * news
Definition: client.h:545
init_new_character_window
static void init_new_character_window()
Definition: account.c:213
script_killall
void script_killall(void)
Definition: script.c:541
on_button_new_char_cancel_clicked
void on_button_new_char_cancel_clicked(GtkButton *button, gpointer user_data)
Definition: account.c:205
metaserver.h
BIG_BUF
#define BIG_BUF
Definition: client.h:41
SockList_Init
void SockList_Init(SockList *sl, guint8 *buf)
Definition: newsocket.c:32
Info_Pane::textview
GtkWidget * textview
Definition: info.h:57
button_new_create_account
static GtkWidget * button_new_create_account
Definition: account.c:35
on_button_account_password_confirm_clicked
void on_button_account_password_confirm_clicked(GtkButton *button, gpointer user_data)
Definition: account.c:1073
on_button_create_character_clicked
void on_button_create_character_clicked(GtkButton *button, gpointer user_data)
Definition: account.c:484
CHAR_CLASS
@ CHAR_CLASS
Definition: account.c:62
textbuf_rules_char
GtkTextBuffer * textbuf_rules_char
Definition: account.c:73
TEXTVIEW_NEWS
#define TEXTVIEW_NEWS
Definition: account.c:80
client_disconnect
void client_disconnect()
Definition: client.c:175
ClientSocket::fd
GSocketConnection * fd
Definition: client.h:124
button_go_metaserver
static GtkWidget * button_go_metaserver
Definition: account.c:31
button_create_character
static GtkWidget * button_create_character
Definition: account.c:41
login_pane
Info_Pane login_pane[4]
Definition: account.c:84
num_text_views
int num_text_views
CHAR_MAP
@ CHAR_MAP
Definition: account.c:63
button_create_new_char
static GtkWidget * button_create_new_char
Definition: account.c:47
CHAR_PARTY
@ CHAR_PARTY
Definition: account.c:62
main_notebook
GtkNotebook * main_notebook
Definition: main.c:104
SockList_Send
int SockList_Send(SockList *sl, GSocketConnection *c)
Definition: newsocket.c:112
pixmaps
PixmapInfo * pixmaps[MAXPIXMAPNUM]
Definition: image.c:34
entry_character_name
static GtkWidget * entry_character_name
Definition: account.c:69
on_button_create_new_char_clicked
void on_button_create_new_char_clicked(GtkButton *button, gpointer user_data)
Definition: account.c:184
button_play_character
static GtkWidget * button_play_character
Definition: account.c:41
TEXTVIEW_MOTD
#define TEXTVIEW_MOTD
Definition: account.c:79
label_create_account_status
static GtkWidget * label_create_account_status
Definition: account.c:38
create_character_window_hide
void create_character_window_hide()
Definition: create_char.c:195
SockList_AddChar
void SockList_AddChar(SockList *sl, char c)
Definition: newsocket.c:43
on_button_add_character_clicked
void on_button_add_character_clicked(GtkButton *button, gpointer user_data)
Definition: account.c:500
account_password
char account_password[256]
Definition: account.c:58
create_character_window_show
void create_character_window_show()
Definition: create_char.c:152
init_login_window
static void init_login_window()
Definition: account.c:962
on_entry_account_password
void on_entry_account_password(GtkEntry *entry, gpointer user_data)
Definition: account.c:1090
entry_new_character_name
static GtkWidget * entry_new_character_name
Definition: account.c:46
treeview_look
GtkWidget * treeview_look
Definition: inventory.c:38
init_create_account_window
static void init_create_account_window()
Definition: account.c:815
CHAR_NAME
@ CHAR_NAME
Definition: account.c:62
label_account_login_status
static GtkWidget * label_account_login_status
Definition: account.c:32
treeview_choose_character
static GtkWidget * treeview_choose_character
Definition: account.c:43
update_character_choose
void update_character_choose(const char *name, const char *class, const char *race, const char *face, const char *party, const char *map, int level, int faceno)
Definition: account.c:547
CHAR_NUM_COLUMNS
#define CHAR_NUM_COLUMNS
Definition: account.c:65
start_login
void start_login(int method)
Definition: account.c:1263
do_account_login
static void do_account_login(const char *name, const char *password)
Definition: account.c:916
on_button_new_create_account_clicked
void on_button_new_create_account_clicked(GtkButton *button, gpointer user_data)
Definition: account.c:738
account_login_failure
void account_login_failure(char *message)
Definition: account.c:868
CHAR_LEVEL
@ CHAR_LEVEL
Definition: account.c:62
create_new_character
static void create_new_character()
Definition: account.c:153
add_character_to_account
static void add_character_to_account(const char *name, const char *password, int force)
Definition: account.c:249
button_new_cancel
static GtkWidget * button_new_cancel
Definition: account.c:35
MAX_BUF
#define MAX_BUF
Definition: client.h:40
label_add_status
static GtkWidget * label_add_status
Definition: account.c:70
textbuf_news
GtkTextBuffer * textbuf_news
Definition: account.c:72
account_change_password_failure
void account_change_password_failure(char *message)
Definition: account.c:1123
label_account_password_status
static GtkWidget * label_account_password_status
Definition: account.c:53
on_button_create_account_clicked
void on_button_create_account_clicked(GtkButton *button, gpointer user_data)
Definition: account.c:879
TEXTVIEW_RULES_ACCOUNT
#define TEXTVIEW_RULES_ACCOUNT
Definition: account.c:81
on_entry_new_character_name
void on_entry_new_character_name(GtkEntry *entry, gpointer user_data)
Definition: account.c:194
on_button_do_add_character_clicked
void on_button_do_add_character_clicked(GtkButton *button, gpointer user_data)
Definition: account.c:334
new_character_window
static GtkWidget * new_character_window
Definition: account.c:46
hide_main_client
void hide_main_client()
Definition: main.c:477
SockList_AddString
void SockList_AddString(SockList *sl, const char *str)
Definition: newsocket.c:98
on_button_play_character_clicked
void on_button_play_character_clicked(GtkButton *button, gpointer user_data)
Definition: account.c:462
gtk2proto.h
Info_Pane::textmark
GtkTextMark * textmark
Definition: info.h:60
button_login
static GtkWidget * button_login
Definition: account.c:31
button_return_login
static GtkWidget * button_return_login
Definition: account.c:42
account_add_character_failure
void account_add_character_failure(char *message)
Definition: account.c:282
play_character
static void play_character(const char *name)
Definition: account.c:445
on_window_delete_event
gboolean on_window_delete_event(GtkWidget *window, gpointer *user_data)
Definition: account.c:123
textbuf_rules_account
GtkTextBuffer * textbuf_rules_account
Definition: account.c:72
button_new_char_cancel
static GtkWidget * button_new_char_cancel
Definition: account.c:48
create_new_character_failure
void create_new_character_failure(char *message)
Definition: account.c:142
csocket
ClientSocket csocket
Definition: client.c:70
image.h
hide_all_login_windows
void hide_all_login_windows()
Definition: account.c:96
on_button_login_clicked
void on_button_login_clicked(GtkButton *button, gpointer user_data)
Definition: account.c:944
button_create_account
static GtkWidget * button_create_account
Definition: account.c:31
on_button_go_metaserver_clicked
void on_button_go_metaserver_clicked(GtkButton *button, gpointer user_data)
Definition: account.c:895
add_tags_to_textbuffer
void add_tags_to_textbuffer(Info_Pane *pane, GtkTextBuffer *textbuf)
Definition: info.c:355
entry_account_password_confirm
static GtkWidget * entry_account_password_confirm
Definition: account.c:52
image_size
int image_size
Definition: image.c:30
button_account_password_confirm
static GtkWidget * button_account_password_confirm
Definition: account.c:52
entry_account_password_new
static GtkWidget * entry_account_password_new
Definition: account.c:51
init_account_password_window
static void init_account_password_window()
Definition: account.c:1131
Info_Pane
Definition: info.h:55
add_style_to_textbuffer
void add_style_to_textbuffer(Info_Pane *pane, GtkStyle *base_style)
Definition: info.c:409
dialog_xml
GtkBuilder * dialog_xml
Definition: main.c:102
do_account_create
static void do_account_create(const char *name, const char *p1, const char *p2)
Definition: account.c:708
choose_character_init
void choose_character_init()
Definition: account.c:421
CHAR_RACE
@ CHAR_RACE
Definition: account.c:62
map
static item * map
Definition: item.c:27
entry_new_confirm_password
static GtkWidget * entry_new_confirm_password
Definition: account.c:37
textbuf_motd
GtkTextBuffer * textbuf_motd
Definition: account.c:72
on_entry_character
void on_entry_character(GtkEntry *entry, gpointer user_data)
Definition: account.c:361
on_entry_new_account
void on_entry_new_account(GtkEntry *entry, gpointer user_data)
Definition: account.c:773
init_add_character_window
static void init_add_character_window()
Definition: account.c:388
main.h
account_creation_failure
void account_creation_failure(char *message)
Definition: account.c:692
do_account_change
static void do_account_change(const char *old, const char *p1, const char *p2)
Definition: account.c:1033
add_marked_text_to_pane
void add_marked_text_to_pane(Info_Pane *pane, const char *message, int type, int subtype, int orig_color)
Definition: info.c:802
entry_new_account_name
static GtkWidget * entry_new_account_name
Definition: account.c:36
INFO_MOTD
#define INFO_MOTD
Definition: client.h:625
has_init
static int has_init
Definition: account.c:88
character_store
GtkListStore * character_store
Definition: account.c:55
on_button_exit_client_clicked
void on_button_exit_client_clicked(GtkButton *button, gpointer user_data)
Definition: account.c:904
on_button_return_login_clicked
void on_button_return_login_clicked(GtkButton *button, gpointer user_data)
Definition: account.c:514
TEXTVIEW_RULES_CHAR
#define TEXTVIEW_RULES_CHAR
Definition: account.c:82
show_main_client
void show_main_client(void)
Definition: main.c:466
button_return_character_select
static GtkWidget * button_return_character_select
Definition: account.c:69
rules
char * rules
Definition: client.h:545
motd
char * motd
Definition: client.h:546
button_add_character
static GtkWidget * button_add_character
Definition: account.c:42
script.h
account_show_login
void account_show_login()
Definition: account.c:1302
entry_account_password
static GtkWidget * entry_account_password
Definition: account.c:32
button_account_password_cancel
static GtkWidget * button_account_password_cancel
Definition: account.c:53
init_choose_char_window
static void init_choose_char_window()
Definition: account.c:583
on_entry_account_name_activate
void on_entry_account_name_activate(GtkEntry *entry, gpointer user_data)
Definition: account.c:954
window_root
GtkWidget * window_root
Definition: main.c:103
on_button_new_cancel_clicked
void on_button_new_cancel_clicked(GtkButton *button, gpointer user_data)
Definition: account.c:759
on_button_account_password_clicked
void on_button_account_password_clicked(GtkButton *button, gpointer user_data)
Definition: account.c:525
button_do_add_character
static GtkWidget * button_do_add_character
Definition: account.c:68
label_new_char_status
static GtkWidget * label_new_char_status
Definition: account.c:47
serverloginmethod
int serverloginmethod
Definition: client.c:62
CHAR_IMAGE
@ CHAR_IMAGE
Definition: account.c:62
connect_window
GtkWidget * connect_window
Definition: main.c:103
SockList
Definition: newclient.h:651
entry_account_name
static GtkWidget * entry_account_name
Definition: account.c:32
client.h
entry_account_password_current
static GtkWidget * entry_account_password_current
Definition: account.c:51
INFO_NEWS
#define INFO_NEWS
Definition: client.h:624
entry_character_password
static GtkWidget * entry_character_password
Definition: account.c:70
button_account_password
static GtkWidget * button_account_password
Definition: account.c:42
INFO_RULES
#define INFO_RULES
Definition: client.h:626