Crossfire Client, Trunk  R20612
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 
29 #ifdef WIN32
30 # include "script.h"
31 #endif
32 
35 
36 /* These are in the login_window */
39 
40 /* These are in the create_account_window */
45 
46 /* These are in the choose_character window */
50 
51 /* These are in the new_character window */
55 
56 /* These are in the account_password window */
60 
61 GtkListStore *character_store;
62 
63 /* create_char.c also uses this */
64 char account_password[256];
65 
66 /* This enum just maps the columns in the list store to their position.
67  */
70  };
71 #define CHAR_NUM_COLUMNS 8
72 
73 /* These are in the add_character window */
74 static GtkWidget *button_do_add_character,
77 
80 
81 /* These are used as offsets for num_text_views - we share the drawing code in
82  * info.c if more textviews are added, note that NUM_TEXT_VIEWS in info.c
83  * needs to be increased.
84  */
85 #define TEXTVIEW_MOTD 0
86 #define TEXTVIEW_NEWS 1
87 #define TEXTVIEW_RULES_ACCOUNT 2
88 #define TEXTVIEW_RULES_CHAR 3
89 
91 
92 extern int num_text_views;
93 
94 static int has_init = 0;
95 
103  extern GtkWidget *treeview_look;
104 
105  if (has_init) {
106  /* If we have not initialized, nothing to hide */
107  gtk_widget_hide(login_window);
108  gtk_widget_hide(add_character_window);
109  gtk_widget_hide(choose_char_window);
110  gtk_widget_hide(create_account_window);
111  gtk_widget_hide(new_character_window);
112  gtk_widget_hide(account_password_window);
113  create_character_window_hide(); /* create_char.c */
114 
115  /* If the player has started playing (this function being called from
116  * AddMeSuccess), we want to make sure that the extended command entry
117  * widget is not activated - we want normal command entry. Where this
118  * shows up is if the player was playing before and uses a savebed -
119  * now the last thing activated is that entry widget.
120  */
121  gtk_widget_grab_focus(GTK_WIDGET(treeview_look));
122  }
123 }
124 
133 gboolean on_window_delete_event(GtkWidget *window, gpointer *user_data) {
134  return TRUE;
135 }
136 
137 /*****************************************************************************
138  * New character window functions
139  *****************************************************************************/
140 
152 void create_new_character_failure(char *message) {
153  GtkWidget *dialog;
154 
155  dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_DESTROY_WITH_PARENT,
156  GTK_MESSAGE_QUESTION, GTK_BUTTONS_OK,
157  "Error: %s", message);
158  gtk_dialog_run(GTK_DIALOG(dialog));
159  gtk_widget_destroy(dialog);
160 }
161 
162 static void create_new_character() {
163  const char *name;
164  guint8 buf[MAX_BUF];
165  SockList sl;
166 
167  SockList_Init(&sl, buf);
168 
169  name = gtk_entry_get_text(GTK_ENTRY(entry_new_character_name));
170 
171  if (!name || *name == 0) {
172  gtk_label_set_text(GTK_LABEL(label_new_char_status),
173  "You must enter a character name.");
174  return;
175  } else {
176  gtk_label_set_text(GTK_LABEL(label_new_char_status), "");
177 
178  SockList_AddString(&sl, "createplayer ");
179  SockList_AddChar(&sl, strlen(name));
180  SockList_AddString(&sl, name);
181  SockList_AddChar(&sl, strlen(account_password));
183  SockList_Send(&sl, csocket.fd);
184  }
185 }
186 
192 void
193 on_button_create_new_char_clicked(GtkButton *button, gpointer user_data) {
195 }
196 
203 void on_entry_new_character_name(GtkEntry *entry, gpointer user_data) {
205 }
206 
213 void
214 on_button_new_char_cancel_clicked(GtkButton *button, gpointer user_data) {
215  gtk_widget_hide(new_character_window);
216  gtk_widget_show(choose_char_window);
217 }
218 
224  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "create_character_window"));
225 
226  gtk_window_set_transient_for(
227  GTK_WINDOW(new_character_window), GTK_WINDOW(window_root));
228 
230  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_create_character"));
232  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_cc_cancel"));
234  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "cc_entry_new_character_name"));
236  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "label_cc_status_update"));
237 
238  g_signal_connect((gpointer) new_character_window, "delete_event",
239  G_CALLBACK(on_window_delete_event), NULL);
240  g_signal_connect((gpointer) button_create_new_char, "clicked",
241  G_CALLBACK(on_button_create_new_char_clicked), NULL);
242  g_signal_connect((gpointer) button_new_char_cancel, "clicked",
243  G_CALLBACK(on_button_new_char_cancel_clicked), NULL);
244  g_signal_connect((gpointer) entry_new_character_name, "activate",
245  G_CALLBACK(on_entry_new_character_name), NULL);
246 }
247 
248 /******************************************************************************
249  * add_character_window functions
250  *****************************************************************************/
251 
258 static void add_character_to_account(const char *name, const char *password,
259  int force) {
260  SockList sl;
261  guint8 buf[MAX_BUF];
262 
263  if (!name || !password || *name == 0 || *password == 0) {
264  gtk_label_set_text(GTK_LABEL(label_add_status),
265  "You must enter both a name and password!");
266  } else {
267  gtk_label_set_text(GTK_LABEL(label_add_status), "");
268 
269  SockList_Init(&sl, buf);
270  SockList_AddString(&sl, "accountaddplayer ");
271  SockList_AddChar(&sl, force);
272  SockList_AddChar(&sl, strlen(name));
273  SockList_AddString(&sl, name);
274  SockList_AddChar(&sl, strlen(password));
275  SockList_AddString(&sl, password);
276  SockList_Send(&sl, csocket.fd);
277  }
278 }
279 
291 void account_add_character_failure(char *message) {
292  char *cp;
293  int retry;
294 
295  retry = atoi(message);
296  cp = strchr(message, ' ');
297  if (cp) {
298  cp++;
299  } else {
300  cp = message;
301  }
302 
303  if (!retry) {
304  gtk_label_set_text(GTK_LABEL(label_add_status), cp);
305  } else {
306  /* In this case, we can retry it and it should work if we set force.
307  * So bring up a dialog, as the user what to do - if they enter yes,
308  * we use force. If not, we clear the entry fields and just continue
309  * onward.
310  */
311  GtkWidget *dialog;
312  int result;
313  const char *name, *password;
314 
315  /* Bring up a dialog window */
316  dialog =
317  gtk_message_dialog_new(NULL, GTK_DIALOG_DESTROY_WITH_PARENT,
318  GTK_MESSAGE_QUESTION,
319  GTK_BUTTONS_YES_NO, "%s\n%s", cp, "Apply anyways?");
320  result = gtk_dialog_run(GTK_DIALOG(dialog));
321  gtk_widget_destroy(dialog);
322 
323  if (result == GTK_RESPONSE_YES) {
324  name = gtk_entry_get_text(GTK_ENTRY(entry_character_name));
325  password = gtk_entry_get_text(GTK_ENTRY(entry_character_password));
326  add_character_to_account(name, password, 1);
327  } else {
328  gtk_entry_set_text(GTK_ENTRY(entry_character_name), "");
329  gtk_entry_set_text(GTK_ENTRY(entry_character_password), "");
330  gtk_widget_grab_focus(entry_character_name);
331  }
332  }
333 }
334 
342 void
343 on_button_do_add_character_clicked(GtkButton *button, gpointer user_data) {
345  gtk_entry_get_text(GTK_ENTRY(entry_character_name)),
346  gtk_entry_get_text(GTK_ENTRY(entry_character_password)), 0);
347 }
348 
356 void
358  gpointer user_data) {
359  gtk_widget_hide(add_character_window);
360  gtk_widget_show(choose_char_window);
361 }
362 
371 void on_entry_character(GtkEntry *entry, gpointer user_data) {
372  const char *name, *password;
373 
374  name = gtk_entry_get_text(GTK_ENTRY(entry_character_name));
375  password = gtk_entry_get_text(GTK_ENTRY(entry_character_password));
376 
377  if (name && name[0] && password && password[0]) {
378  add_character_to_account(name, password, 0);
379  } else {
380  const char *cp;
381 
382  /* First case - this widget is empty - do nothing */
383  cp = gtk_entry_get_text(entry);
384  if (!cp || !cp[0]) {
385  return;
386  }
387 
388  /* In this case, this widget is not empty - means the other one is.
389  */
390  if (entry == GTK_ENTRY(entry_character_name)) {
391  gtk_widget_grab_focus(entry_character_password);
392  } else {
393  gtk_widget_grab_focus(entry_character_name);
394  }
395  }
396 }
397 
400  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "add_character_window"));
401 
402  gtk_window_set_transient_for(
403  GTK_WINDOW(add_character_window), GTK_WINDOW(window_root));
404 
406  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_do_add_character"));
408  GTK_WIDGET(gtk_builder_get_object(dialog_xml,
409  "button_return_character_select"));
411  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "entry_character_name"));
413  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "entry_character_password"));
415  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "label_add_status"));
416 
417  g_signal_connect((gpointer) add_character_window, "delete_event",
418  G_CALLBACK(on_window_delete_event), NULL);
419  g_signal_connect((gpointer) button_do_add_character, "clicked",
420  G_CALLBACK(on_button_do_add_character_clicked), NULL);
421  g_signal_connect((gpointer) button_return_character_select, "clicked",
423  g_signal_connect((gpointer) entry_character_name, "activate",
424  G_CALLBACK(on_entry_character), NULL);
425  g_signal_connect((gpointer) entry_character_password, "activate",
426  G_CALLBACK(on_entry_character), NULL);
427 }
428 
429 /*****************************************************************************
430  * choose_char_window
431  ****************************************************************************/
432 
440  gtk_widget_hide(login_window);
441  gtk_widget_hide(add_character_window);
442  gtk_widget_hide(create_account_window);
443  gtk_widget_show(choose_char_window);
444 
445  /* Store any old/stale entries */
446  gtk_list_store_clear(character_store);
447 }
448 
457  gtk_widget_show(choose_char_window);
458 }
459 
460 
465 static void play_character(const char *name) {
466  SockList sl;
467  guint8 buf[MAX_BUF];
468 
469  SockList_Init(&sl, buf);
470  SockList_AddString(&sl, "accountplay ");
471  SockList_AddString(&sl, name);
472  SockList_Send(&sl, csocket.fd);
473 }
474 
481 void
482 on_button_play_character_clicked(GtkButton *button, gpointer user_data) {
483  GtkTreeSelection *selected;
484  GtkTreeModel *model;
485  GtkTreeIter iter;
486  char *name;
487 
488  selected = gtk_tree_view_get_selection(GTK_TREE_VIEW(
490 
491  if (gtk_tree_selection_get_selected(selected, &model, &iter)) {
492  gtk_tree_model_get(model, &iter, CHAR_NAME, &name, -1);
493 
495  play_character(name);
496  }
497 }
498 
504 void
505 on_button_create_character_clicked(GtkButton *button, gpointer user_data) {
506  gtk_widget_hide(choose_char_window);
507  if (serverloginmethod >= 2) {
509  } else {
510  gtk_widget_show(new_character_window);
511  gtk_entry_set_text(GTK_ENTRY(entry_new_character_name), "");
512  }
513 }
514 
521 void
522 on_button_add_character_clicked(GtkButton *button, gpointer user_data) {
523  gtk_widget_hide(choose_char_window);
524  gtk_widget_show(add_character_window);
525  gtk_entry_set_text(GTK_ENTRY(entry_character_name), "");
526  gtk_entry_set_text(GTK_ENTRY(entry_character_password), "");
527  gtk_widget_grab_focus(entry_character_name);
528 }
529 
536 void
537 on_button_return_login_clicked(GtkButton *button, gpointer user_data) {
538  gtk_widget_hide(choose_char_window);
539  gtk_widget_show(login_window);
540 }
541 
548 void
549 on_button_account_password_clicked(GtkButton *button, gpointer user_data) {
550  gtk_widget_hide(choose_char_window);
551  gtk_widget_show(account_password_window);
552  /* reset previous values */
553  gtk_entry_set_text(GTK_ENTRY(entry_account_password_current), "");
554  gtk_entry_set_text(GTK_ENTRY(entry_account_password_new), "");
555  gtk_entry_set_text(GTK_ENTRY(entry_account_password_confirm), "");
556 }
557 
572 void update_character_choose(const char *name, const char *class,
573  const char *race, const char *face,
574  const char *party, const char *map,
575  int level, int faceno) {
576  GtkTreeIter iter;
577 
578  gtk_list_store_append(character_store, &iter);
579 
580  /* If this pixmap matches pixmap[0], it means we are caching images and
581  * this image hasn't been set up. It looks better in this case to just
582  * leave that area of the window blank vs drawing a question mark there.
583  */
584  if (pixmaps[faceno] == pixmaps[0]) {
585  gtk_list_store_set(character_store, &iter,
586  CHAR_NAME, name,
587  CHAR_CLASS, class,
588  CHAR_RACE, race,
589  CHAR_IMAGE, face,
590  CHAR_PARTY, party,
591  CHAR_MAP, map,
592  CHAR_LEVEL, level,
593  -1);
594  } else {
595  gtk_list_store_set(character_store, &iter,
596  CHAR_ICON, pixmaps[faceno]->icon_image,
597  CHAR_NAME, name,
598  CHAR_CLASS, class,
599  CHAR_RACE, race,
600  CHAR_IMAGE, face,
601  CHAR_PARTY, party,
602  CHAR_MAP, map,
603  CHAR_LEVEL, level,
604  -1);
605  }
606 }
607 
608 static void init_choose_char_window() {
609  GtkTextIter end;
610  GtkCellRenderer *renderer;
611  GtkTreeViewColumn *column;
612 
614  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "choose_character_window"));
615 
616  gtk_window_set_transient_for(
617  GTK_WINDOW(choose_char_window), GTK_WINDOW(window_root));
618 
620  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_play_character"));
622  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_create_character"));
624  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_add_character"));
626  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_return_login"));
628  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_account_password"));
629  login_pane[TEXTVIEW_RULES_CHAR].textview =
630  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "textview_rules_char"));
631 
633  gtk_text_view_get_buffer(
634  GTK_TEXT_VIEW(login_pane[TEXTVIEW_RULES_CHAR].textview));
635 
637  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "treeview_choose_character"));
638 
641  add_style_to_textbuffer(&login_pane[TEXTVIEW_RULES_CHAR], NULL);
642  gtk_text_buffer_get_end_iter(
643  login_pane[TEXTVIEW_RULES_CHAR].textbuffer, &end);
644  login_pane[TEXTVIEW_RULES_CHAR].textmark =
645  gtk_text_buffer_create_mark(
646  login_pane[TEXTVIEW_RULES_CHAR].textbuffer, NULL, &end, FALSE);
647 
648  g_signal_connect((gpointer) choose_char_window, "delete_event",
649  G_CALLBACK(on_window_delete_event), NULL);
650  g_signal_connect((gpointer) button_play_character, "clicked",
651  G_CALLBACK(on_button_play_character_clicked), NULL);
652  g_signal_connect((gpointer) button_create_character, "clicked",
653  G_CALLBACK(on_button_create_character_clicked), NULL);
654  g_signal_connect((gpointer) button_add_character, "clicked",
655  G_CALLBACK(on_button_add_character_clicked), NULL);
656  g_signal_connect((gpointer) button_return_login, "clicked",
657  G_CALLBACK(on_button_return_login_clicked), NULL);
658  g_signal_connect((gpointer) button_account_password, "clicked",
659  G_CALLBACK(on_button_account_password_clicked), NULL);
660  g_signal_connect((gpointer) treeview_choose_character, "row_activated",
661  G_CALLBACK(on_button_play_character_clicked), NULL);
662 
663  character_store = gtk_list_store_new(CHAR_NUM_COLUMNS,
664  G_TYPE_STRING, G_TYPE_STRING,
665  G_TYPE_STRING, G_TYPE_STRING,
666  G_TYPE_INT, G_TYPE_STRING,
667  G_TYPE_STRING, G_TYPE_OBJECT);
668  gtk_tree_view_set_model(GTK_TREE_VIEW(treeview_choose_character),
669  GTK_TREE_MODEL(character_store));
670 
671  renderer = gtk_cell_renderer_pixbuf_new();
672  column = gtk_tree_view_column_new_with_attributes("?", renderer,
673  "pixbuf", CHAR_ICON,
674  NULL);
675 
676  gtk_tree_view_column_set_min_width(column, image_size);
677  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_choose_character), column);
678 
679  renderer = gtk_cell_renderer_text_new();
680  column = gtk_tree_view_column_new_with_attributes("Character Name", renderer,
681  "text", CHAR_NAME, NULL);
682  gtk_tree_view_column_set_sort_column_id(column, CHAR_NAME);
683  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_choose_character), column);
684 
685  renderer = gtk_cell_renderer_text_new();
686  column = gtk_tree_view_column_new_with_attributes("Class", renderer,
687  "text", CHAR_CLASS, NULL);
688  gtk_tree_view_column_set_sort_column_id(column, CHAR_CLASS);
689  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_choose_character), column);
690 
691  renderer = gtk_cell_renderer_text_new();
692  column = gtk_tree_view_column_new_with_attributes("Race", renderer,
693  "text", CHAR_RACE, NULL);
694  gtk_tree_view_column_set_sort_column_id(column, CHAR_RACE);
695  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_choose_character), column);
696 
697  renderer = gtk_cell_renderer_text_new();
698  column = gtk_tree_view_column_new_with_attributes("Level", renderer,
699  "text", CHAR_LEVEL, NULL);
700  gtk_tree_view_column_set_sort_column_id(column, CHAR_LEVEL);
701  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_choose_character), column);
702 
703  renderer = gtk_cell_renderer_text_new();
704  column = gtk_tree_view_column_new_with_attributes("Party", renderer,
705  "text", CHAR_PARTY, NULL);
706  gtk_tree_view_column_set_sort_column_id(column, CHAR_PARTY);
707  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_choose_character), column);
708 
709  renderer = gtk_cell_renderer_text_new();
710  column = gtk_tree_view_column_new_with_attributes("Map", renderer,
711  "text", CHAR_MAP, NULL);
712  gtk_tree_view_column_set_sort_column_id(column, CHAR_MAP);
713  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_choose_character), column);
714 }
715 
716 /******************************************************************************
717  * create_account_window
718  ******************************************************************************/
719 
725 void account_creation_failure(char *message) {
726  gtk_label_set_text(GTK_LABEL(label_create_account_status), message);
727 }
728 
741 static void do_account_create(const char *name, const char *p1,
742  const char *p2) {
743  SockList sl;
744  guint8 buf[MAX_BUF];
745 
746  if (strcmp(p1, p2)) {
747  gtk_label_set_text(GTK_LABEL(label_create_account_status),
748  "The passwords you entered do not match!");
749  return;
750  } else {
751  gtk_label_set_text(GTK_LABEL(label_create_account_status), "");
752  SockList_Init(&sl, buf);
753  SockList_AddString(&sl, "accountnew ");
754  SockList_AddChar(&sl, strlen(name));
755  SockList_AddString(&sl, name);
756  SockList_AddChar(&sl, strlen(p1));
757  SockList_AddString(&sl, p1);
758  SockList_Send(&sl, csocket.fd);
759  /* Store password away for new character creation */
760  snprintf(account_password, sizeof(account_password), "%s", p1);
761  }
762 }
763 
770 void
771 on_button_new_create_account_clicked(GtkButton *button, gpointer user_data) {
772  const char *password1, *password2, *name;
773 
774  password1 = gtk_entry_get_text(GTK_ENTRY(entry_new_account_password));
775  password2 = gtk_entry_get_text(GTK_ENTRY(entry_new_confirm_password));
776  name = gtk_entry_get_text(GTK_ENTRY(entry_new_account_name));
777 
778  if (name && name[0] && password1 && password1[0] && password2 && password2[0]) {
779  do_account_create(name, password1, password2);
780  } else {
781  gtk_label_set_text(GTK_LABEL(label_create_account_status),
782  "You must fill in all three entries!");
783  }
784 }
785 
791 void
792 on_button_new_cancel_clicked(GtkButton *button, gpointer user_data) {
793  gtk_widget_hide(create_account_window);
794  gtk_widget_show(login_window);
795 }
796 
806 void
807 on_entry_new_account(GtkEntry *entry, gpointer user_data) {
808 
809  const char *password1, *password2, *name, *cp;
810 
811  password1 = gtk_entry_get_text(GTK_ENTRY(entry_new_account_password));
812  password2 = gtk_entry_get_text(GTK_ENTRY(entry_new_confirm_password));
813  name = gtk_entry_get_text(GTK_ENTRY(entry_new_account_name));
814  if (name && name[0] && password1 && password1[0] && password2 && password2[0]) {
815  do_account_create(name, password1, password2);
816  } else {
817  /* In this case, one, or more, of the fields is blank. If there were
818  * more than 3 widgets, I might but them into an array to make cycling
819  * easier
820  */
821 
822  /* First case - if the currently active one is blank, no reason to
823  * move onward.
824  */
825  cp = gtk_entry_get_text(entry);
826  if (!cp || !cp[0]) {
827  return;
828  }
829 
830  /* I'm not sure if it would make more sense to advance to the first
831  * NULL entry - but in that case, the pointer may hop in non intuitive
832  * ways - in this case, the user may just need to hit return a few
833  * times - MSW 2010/03/29
834  */
835  if (entry == GTK_ENTRY(entry_new_account_name)) {
836  gtk_widget_grab_focus(entry_new_account_password);
837  } else if (entry == GTK_ENTRY(entry_new_account_password)) {
838  gtk_widget_grab_focus(entry_new_confirm_password);
839  } else if (entry == GTK_ENTRY(entry_new_confirm_password)) {
840  gtk_widget_grab_focus(entry_new_account_name);
841  }
842  }
843 }
844 
850  GtkTextIter end;
851 
853  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "create_account_window"));
854 
855  gtk_window_set_transient_for(
856  GTK_WINDOW(create_account_window), GTK_WINDOW(window_root));
857 
859  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_new_create_account"));
861  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_new_cancel"));
862  login_pane[TEXTVIEW_RULES_ACCOUNT].textview =
863  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "textview_rules_account"));
864 
866  gtk_text_view_get_buffer(
867  GTK_TEXT_VIEW(login_pane[TEXTVIEW_RULES_ACCOUNT].textview));
868 
870  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "entry_new_account_name"));
872  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "entry_new_account_password"));
874  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "entry_new_confirm_password"));
876  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "label_create_account_status"));
877 
880  add_style_to_textbuffer(&login_pane[TEXTVIEW_RULES_ACCOUNT], NULL);
881  gtk_text_buffer_get_end_iter(
882  login_pane[TEXTVIEW_RULES_ACCOUNT].textbuffer, &end);
883  login_pane[TEXTVIEW_RULES_ACCOUNT].textmark =
884  gtk_text_buffer_create_mark(
885  login_pane[TEXTVIEW_RULES_ACCOUNT].textbuffer, NULL, &end, FALSE);
886 
887  g_signal_connect((gpointer) create_account_window, "delete_event",
888  G_CALLBACK(on_window_delete_event), NULL);
889  g_signal_connect((gpointer) button_new_create_account, "clicked",
890  G_CALLBACK(on_button_new_create_account_clicked), NULL);
891  g_signal_connect((gpointer) button_new_cancel, "clicked",
892  G_CALLBACK(on_button_new_cancel_clicked), NULL);
893  g_signal_connect((gpointer) entry_new_account_name, "activate",
894  G_CALLBACK(on_entry_new_account), NULL);
895  g_signal_connect((gpointer) entry_new_account_password, "activate",
896  G_CALLBACK(on_entry_new_account), NULL);
897  g_signal_connect((gpointer) entry_new_confirm_password, "activate",
898  G_CALLBACK(on_entry_new_account), NULL);
899 }
900 
901 /*****************************************************************************
902  * login_window
903  *****************************************************************************/
904 
910 void account_login_failure(char *message) {
911  gtk_label_set_text(GTK_LABEL(label_account_login_status), message);
912 }
913 
920 void
921 on_button_create_account_clicked(GtkButton *button, gpointer user_data) {
922  gtk_widget_hide(login_window);
923  gtk_label_set_text(GTK_LABEL(label_create_account_status), "");
924  gtk_entry_set_text(GTK_ENTRY(entry_new_account_name), "");
925  gtk_entry_set_text(GTK_ENTRY(entry_new_account_password), "");
926  gtk_entry_set_text(GTK_ENTRY(entry_new_confirm_password), "");
927  gtk_widget_show(create_account_window);
928 }
929 
937 void
938 on_button_go_metaserver_clicked(GtkButton *button, gpointer user_data) {
940 }
941 
947 void on_button_exit_client_clicked(GtkButton *button, gpointer user_data) {
948 #ifdef WIN32
949  script_killall();
950 #endif
951  exit(0);
952 }
953 
961 static void do_account_login(const char *name, const char *password) {
962  SockList sl;
963  guint8 buf[MAX_BUF];
964 
965  if (!name || !password || *name == 0 || *password == 0) {
966  gtk_label_set_text(GTK_LABEL(label_account_login_status),
967  "You must enter both a name and password!");
968  } else {
969  gtk_label_set_text(GTK_LABEL(label_account_login_status), "");
970 
971  SockList_Init(&sl, buf);
972  SockList_AddString(&sl, "accountlogin ");
973  SockList_AddChar(&sl, strlen(name));
974  SockList_AddString(&sl, name);
975  SockList_AddChar(&sl, strlen(password));
976  SockList_AddString(&sl, password);
977  SockList_Send(&sl, csocket.fd);
978  /* Store password away for new character creation */
979  snprintf(account_password, sizeof(account_password), "%s", password);
980  }
981 }
982 
988 void
989 on_button_login_clicked(GtkButton *button, gpointer user_data) {
990  do_account_login(gtk_entry_get_text(GTK_ENTRY(entry_account_name)),
991  gtk_entry_get_text(GTK_ENTRY(entry_account_password)));
992 }
993 
999 void on_entry_account_name_activate(GtkEntry* entry, gpointer user_data) {
1000  gtk_widget_grab_focus(entry_account_password);
1001 }
1002 
1007 static void init_login_window() {
1008  GtkTextIter end;
1009 
1010  login_window = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "login_window"));
1011  if (!login_window) {
1012  error_dialog("Failed to open dialogs.", "Did you run `make install`?");
1013  exit(1);
1014  }
1015 
1016  g_signal_connect(login_window, "delete_event",
1017  G_CALLBACK(on_button_exit_client_clicked), NULL);
1018 
1019  gtk_window_set_transient_for(
1020  GTK_WINDOW(login_window), GTK_WINDOW(window_root));
1021  button_login =
1022  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_login"));
1024  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_create_account"));
1026  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_go_metaserver"));
1028  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "label_account_login_status"));
1029  login_pane[TEXTVIEW_MOTD].textview =
1030  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "textview_motd"));
1031 
1032  textbuf_motd =
1033  gtk_text_view_get_buffer(
1034  GTK_TEXT_VIEW(login_pane[TEXTVIEW_MOTD].textview));
1035 
1037  add_style_to_textbuffer(&login_pane[TEXTVIEW_MOTD], NULL);
1038  gtk_text_buffer_get_end_iter(login_pane[TEXTVIEW_MOTD].textbuffer, &end);
1039  login_pane[TEXTVIEW_MOTD].textmark =
1040  gtk_text_buffer_create_mark(
1041  login_pane[TEXTVIEW_MOTD].textbuffer, NULL, &end, FALSE);
1042 
1043  login_pane[TEXTVIEW_NEWS].textview =
1044  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "textview_news"));
1045 
1046  textbuf_news =
1047  gtk_text_view_get_buffer(
1048  GTK_TEXT_VIEW(login_pane[TEXTVIEW_NEWS].textview));
1049 
1051  add_style_to_textbuffer(&login_pane[TEXTVIEW_NEWS], NULL);
1052  gtk_text_buffer_get_end_iter(login_pane[TEXTVIEW_NEWS].textbuffer, &end);
1053  login_pane[TEXTVIEW_NEWS].textmark =
1054  gtk_text_buffer_create_mark(
1055  login_pane[TEXTVIEW_NEWS].textbuffer, NULL, &end, FALSE);
1056 
1058  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "entry_account_name"));
1060  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "entry_account_password"));
1061 
1062  g_signal_connect((gpointer) login_window, "delete_event",
1063  G_CALLBACK(on_window_delete_event), NULL);
1064  g_signal_connect((gpointer) entry_account_name, "activate",
1065  G_CALLBACK(on_entry_account_name_activate), NULL);
1066  // entry_account_password is the default action in GtkBuilder
1067  g_signal_connect((gpointer) button_login, "clicked",
1068  G_CALLBACK(on_button_login_clicked), NULL);
1069  g_signal_connect((gpointer) button_create_account, "clicked",
1070  G_CALLBACK(on_button_create_account_clicked), NULL);
1071  g_signal_connect((gpointer) button_go_metaserver, "clicked",
1072  G_CALLBACK(on_button_go_metaserver_clicked), NULL);
1073 }
1074 
1075 /*****************************************************************************
1076  * Account password change
1077  ****************************************************************************/
1078 
1091 static void do_account_change(const char *old, const char *p1, const char *p2) {
1092  SockList sl;
1093  guint8 buf[MAX_BUF];
1094 
1095  if (strcmp(p1, p2)) {
1096  gtk_label_set_text(GTK_LABEL(label_account_password_status),
1097  "The passwords you entered do not match!");
1098  return;
1099  } else {
1100  gtk_label_set_text(GTK_LABEL(label_account_password_status), "");
1101  SockList_Init(&sl, buf);
1102  SockList_AddString(&sl, "accountpw ");
1103  SockList_AddChar(&sl, strlen(old));
1104  SockList_AddString(&sl, old);
1105  SockList_AddChar(&sl, strlen(p1));
1106  SockList_AddString(&sl, p1);
1107  SockList_Send(&sl, csocket.fd);
1108  /* Store password away for new character creation */
1109  snprintf(account_password, sizeof(account_password), "%s", p1);
1110  }
1111 }
1112 
1119 void
1121  gpointer user_data) {
1122  gtk_widget_hide(account_password_window);
1123  gtk_widget_show(choose_char_window);
1124 }
1125 
1131 void
1133  gpointer user_data) {
1134  do_account_change(gtk_entry_get_text(GTK_ENTRY(entry_account_password_current)),
1135  gtk_entry_get_text(GTK_ENTRY(entry_account_password_new)),
1136  gtk_entry_get_text(GTK_ENTRY(entry_account_password_confirm)));
1137 }
1138 
1148 void
1149 on_entry_account_password(GtkEntry *entry, gpointer user_data) {
1150 
1151  const char *old, *password1, *password2, *cp;
1152 
1153  old = gtk_entry_get_text(GTK_ENTRY(entry_account_password_current));
1154  password1 = gtk_entry_get_text(GTK_ENTRY(entry_account_password_new));
1155  password2 = gtk_entry_get_text(GTK_ENTRY(entry_account_password_confirm));
1156  if (old && old[0] && password1 && password1[0] && password2 && password2[0]) {
1157  do_account_change(old, password1, password2);
1158  } else {
1159  /* In this case, one, or more, of the fields is blank. If there were
1160  * more than 3 widgets, I might but them into an array to make cycling
1161  * easier
1162  */
1163 
1164  /* First case - if the currently active one is blank, no reason to
1165  * move onward.
1166  */
1167  cp = gtk_entry_get_text(entry);
1168  if (!cp || !cp[0]) {
1169  return;
1170  }
1171 
1172  if (entry == GTK_ENTRY(entry_account_password_current)) {
1173  gtk_widget_grab_focus(entry_account_password_new);
1174  } else if (entry == GTK_ENTRY(entry_account_password_new)) {
1175  gtk_widget_grab_focus(entry_account_password_confirm);
1176  } else if (entry == GTK_ENTRY(entry_account_password_confirm)) {
1177  gtk_widget_grab_focus(entry_account_password_current);
1178  }
1179  }
1180 }
1181 
1182 void account_change_password_failure(char *message) {
1183  gtk_label_set_text(GTK_LABEL(label_account_password_status), message);
1184 }
1185 
1192  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "account_password_window"));
1193 
1194  gtk_window_set_transient_for(
1195  GTK_WINDOW(account_password_window), GTK_WINDOW(window_root));
1196 
1198  GTK_WIDGET(gtk_builder_get_object(dialog_xml,
1199  "button_account_password_confirm"));
1201  GTK_WIDGET(gtk_builder_get_object(dialog_xml,
1202  "button_account_password_cancel"));
1203 
1205  GTK_WIDGET(gtk_builder_get_object(dialog_xml,
1206  "entry_account_password_current"));
1208  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "entry_account_password_new"));
1210  GTK_WIDGET(gtk_builder_get_object(dialog_xml,
1211  "entry_account_password_confirm"));
1213  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "label_account_password_status"));
1214 
1215  g_signal_connect((gpointer) account_password_window, "delete_event",
1216  G_CALLBACK(on_window_delete_event), NULL);
1217  g_signal_connect((gpointer) button_account_password_confirm, "clicked",
1218  G_CALLBACK(on_button_account_password_confirm_clicked), NULL);
1219  g_signal_connect((gpointer) button_account_password_cancel, "clicked",
1220  G_CALLBACK(on_button_account_password_cancel_clicked), NULL);
1221  g_signal_connect((gpointer) entry_account_password_current, "activate",
1222  G_CALLBACK(on_entry_account_password), NULL);
1223  g_signal_connect((gpointer) entry_account_password_new, "activate",
1224  G_CALLBACK(on_entry_account_password), NULL);
1225  g_signal_connect((gpointer) entry_account_password_confirm, "activate",
1226  G_CALLBACK(on_entry_account_password), NULL);
1227 }
1228 
1229 
1230 /*****************************************************************************
1231  * Common/generic functions
1232  ****************************************************************************/
1233 
1241 void update_login_info(int type) {
1242  if (!has_init) {
1243  return;
1244  }
1245 
1246  /* In all cases, we clear the buffer, and if we have data, then set it to
1247  * that data. This routine could be smarter an
1248  */
1249  if (type == INFO_NEWS) {
1250  gtk_text_buffer_set_text(textbuf_news, "", 0);
1251  if (news) {
1252  /* the format of the news entry is special - there are a series of
1253  * %entries, and they are in reverse older (newest last) we want
1254  * to get rid of the %, make them more visible (convert them to
1255  * bold) and reverse the order.
1256  */
1257  char *mynews, *cp, *el, big_buf[BIG_BUF], *cp1;
1258 
1259  mynews = g_strdup(news);
1260  /* We basically work from the end of the string going towards the
1261  * start looking for % characters. If we find one, we have to
1262  * make sure it is at the start of the line or start of the buffer
1263  */
1264  for (cp = mynews + strlen(mynews); cp > mynews; cp--) {
1265  if (*cp == '%' && (*(cp - 1) == '\n' || cp == mynews)) {
1266  /* Find the end of the line */
1267  el = strchr(cp, '\n');
1268  /* null out the newline, put el one char beyond it */
1269  if (el) {
1270  *el = 0;
1271  el++;
1272  }
1273  /* There isn't a clear standard - % news may be valid, as
1274  * might be %news. If % news is used, it looks better to
1275  * get rid of that leading space.
1276  */
1277  cp1 = cp + 1;
1278  while (isspace(*cp1)) {
1279  cp1++;
1280  }
1281 
1282  /* since we've null out the newline, this snprintf will
1283  * only get the % line and that is it. Mark it up
1284  */
1285  snprintf(big_buf, BIG_BUF, "[b]%s[/b]", cp1);
1286  add_marked_text_to_pane(&login_pane[TEXTVIEW_NEWS], big_buf, 0, 0, 0);
1287  /* Now we draw the text that goes with it, if it exists */
1288  if (el) {
1289  add_marked_text_to_pane(&login_pane[TEXTVIEW_NEWS], el, 0, 0, 0);
1290  }
1291 
1292  /* Now we wipe the % out. In this way, the news buffer is
1293  * shorter, so when it draws the ext, there will just be
1294  * that between the % and the one we just wiped out.
1295  */
1296  *cp = 0;
1297  }
1298  }
1299  /* If there are remnants left over, or perhaps the news file isn't
1300  * formatted with % headers, display what we have got.
1301  */
1302  if (*mynews != 0) {
1303  add_marked_text_to_pane(&login_pane[TEXTVIEW_NEWS], mynews, 0, 0, 0);
1304  }
1305  }
1306  } else if (type == INFO_MOTD) {
1307  gtk_text_buffer_set_text(textbuf_motd, "", 0);
1308  if (motd) {
1309  add_marked_text_to_pane(&login_pane[TEXTVIEW_MOTD], motd, 0, 0, 0);
1310  }
1311  } else if (type == INFO_RULES) {
1312  gtk_text_buffer_set_text(textbuf_rules_account, "", 0);
1313  gtk_text_buffer_set_text(textbuf_rules_char, "", 0);
1314 
1315  if (rules) {
1316  add_marked_text_to_pane(&login_pane[TEXTVIEW_RULES_ACCOUNT], rules, 0, 0, 0);
1317  add_marked_text_to_pane(&login_pane[TEXTVIEW_RULES_CHAR], rules, 0, 0, 0);
1318  }
1319  }
1320 }
1321 
1330 void start_login(int method) {
1331  /* Store this away - if method is only 1, we can not do smart character
1332  * creation.
1333  */
1334  serverloginmethod = method;
1335 
1336  if (!has_init) {
1337  /* Since there are 4 windows associated with account and character
1338  * login, to make life a little easier, each section here does all the
1339  * work for one window, so it is easier to see that everything for a
1340  * window is done - don't need to hunt through what would otherwise be
1341  * a long routine looking for entries.
1342  */
1344 
1346 
1348 
1350 
1352 
1354 
1355  has_init = 1;
1356 
1357  /* In case we have gotten news/motd/rules before getting here, update
1358  * it now.
1359  */
1363  }
1364 
1365  gtk_entry_set_text(GTK_ENTRY(entry_account_name), "");
1366  gtk_entry_set_text(GTK_ENTRY(entry_account_password), "");
1367  /* We set focus to account name - this makes the most sense if user is
1368  * logging in again - it is possible that the password is active, but both
1369  * fields are blank, which is not what is expected.
1370  */
1371  gtk_widget_grab_focus(entry_account_name);
1372  gtk_widget_show(login_window);
1373 }
1374 
static void init_new_character_window()
Definition: account.c:222
void error_dialog(char *description, char *information)
Definition: main.c:263
static GtkWidget * entry_account_password_current
Definition: account.c:57
char * news
Definition: client.h:555
GtkWidget * textview
Definition: info.h:57
static GtkWidget * button_account_password
Definition: account.c:47
static GtkWidget * button_new_create_account
Definition: account.c:41
GtkTextBuffer * textbuf_rules_char
Definition: account.c:78
#define TEXTVIEW_NEWS
Definition: account.c:86
int image_size
Definition: image.c:36
GSocketConnection * fd
Definition: client.h:120
static GtkWidget * button_go_metaserver
Definition: account.c:37
void on_button_account_password_cancel_clicked(GtkButton *button, gpointer user_data)
Definition: account.c:1120
void choose_char_window_show()
Definition: account.c:456
Info_Pane login_pane[4]
Definition: account.c:90
static GtkWidget * entry_new_account_password
Definition: account.c:41
void on_button_return_character_select_clicked(GtkButton *button, gpointer user_data)
Definition: account.c:357
static GtkWidget * button_create_new_char
Definition: account.c:52
static GtkWidget * add_character_window
Definition: account.c:33
void on_button_new_char_cancel_clicked(GtkButton *button, gpointer user_data)
Definition: account.c:214
void on_button_account_password_confirm_clicked(GtkButton *button, gpointer user_data)
Definition: account.c:1132
void on_button_create_character_clicked(GtkButton *button, gpointer user_data)
Definition: account.c:505
void add_marked_text_to_pane(Info_Pane *pane, const char *message, int type, int subtype, int orig_color)
Definition: info.c:819
char * rules
Definition: client.h:555
void on_button_add_character_clicked(GtkButton *button, gpointer user_data)
Definition: account.c:522
static void init_login_window()
Definition: account.c:1007
static GtkWidget * entry_new_character_name
Definition: account.c:52
static GtkWidget * button_create_character
Definition: account.c:47
int num_text_views
static void init_create_account_window()
Definition: account.c:849
void add_tags_to_textbuffer(Info_Pane *pane, GtkTextBuffer *textbuf)
Definition: info.c:372
static GtkWidget * label_account_login_status
Definition: account.c:37
ClientSocket csocket
Definition: client.c:69
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:572
#define CHAR_NUM_COLUMNS
Definition: account.c:71
static GtkWidget * entry_character_name
Definition: account.c:74
void on_button_create_new_char_clicked(GtkButton *button, gpointer user_data)
Definition: account.c:193
static GtkWidget * button_play_character
Definition: account.c:47
void on_button_new_create_account_clicked(GtkButton *button, gpointer user_data)
Definition: account.c:771
#define TEXTVIEW_MOTD
Definition: account.c:85
static GtkWidget * label_create_account_status
Definition: account.c:41
GtkWidget * treeview_look
Definition: inventory.c:38
char account_password[256]
Definition: account.c:64
void on_entry_account_password(GtkEntry *entry, gpointer user_data)
Definition: account.c:1149
int serverloginmethod
Definition: client.c:59
static GtkWidget * treeview_choose_character
Definition: account.c:47
static GtkWidget * create_account_window
Definition: account.c:33
static void add_character_to_account(const char *name, const char *password, int force)
Definition: account.c:258
static void do_account_login(const char *name, const char *password)
Definition: account.c:961
void start_login(int method)
Definition: account.c:1330
void account_login_failure(char *message)
Definition: account.c:910
void account_change_password_failure(char *message)
Definition: account.c:1182
void client_disconnect()
Definition: client.c:180
#define INFO_NEWS
Definition: client.h:633
GtkWidget * window_root
Definition: main.c:87
static void create_new_character()
Definition: account.c:162
static GtkWidget * button_new_cancel
Definition: account.c:41
static GtkWidget * label_add_status
Definition: account.c:74
GtkTextBuffer * textbuf_news
Definition: account.c:78
int SockList_Send(SockList *sl, GSocketConnection *c)
Definition: newsocket.c:112
static GtkWidget * label_account_password_status
Definition: account.c:57
void on_button_create_account_clicked(GtkButton *button, gpointer user_data)
Definition: account.c:921
static void play_character(const char *name)
Definition: account.c:465
gboolean on_window_delete_event(GtkWidget *window, gpointer *user_data)
Definition: account.c:133
#define TEXTVIEW_RULES_ACCOUNT
Definition: account.c:87
GtkTextBuffer * textbuf_rules_account
Definition: account.c:78
void on_entry_new_character_name(GtkEntry *entry, gpointer user_data)
Definition: account.c:203
static GtkWidget * new_character_window
Definition: account.c:52
void on_button_do_add_character_clicked(GtkButton *button, gpointer user_data)
Definition: account.c:343
void on_button_play_character_clicked(GtkButton *button, gpointer user_data)
Definition: account.c:482
void on_button_login_clicked(GtkButton *button, gpointer user_data)
Definition: account.c:989
static GtkWidget * button_create_account
Definition: account.c:37
void add_style_to_textbuffer(Info_Pane *pane, GtkStyle *base_style)
Definition: info.c:426
void on_button_go_metaserver_clicked(GtkButton *button, gpointer user_data)
Definition: account.c:938
void SockList_AddString(SockList *sl, const char *str)
Definition: newsocket.c:98
#define MAX_BUF
Definition: client.h:40
GtkTextMark * textmark
Definition: info.h:60
#define INFO_MOTD
Definition: client.h:634
static GtkWidget * button_login
Definition: account.c:37
static GtkWidget * entry_account_password_confirm
Definition: account.c:57
static GtkWidget * button_return_login
Definition: account.c:47
void account_add_character_failure(char *message)
Definition: account.c:291
static void init_account_password_window()
Definition: account.c:1190
static GtkWidget * button_new_char_cancel
Definition: account.c:52
void create_new_character_failure(char *message)
Definition: account.c:152
static void do_account_create(const char *name, const char *p1, const char *p2)
Definition: account.c:741
void hide_all_login_windows()
Definition: account.c:102
void create_character_window_show()
Definition: create_char.c:153
static void do_account_change(const char *old, const char *p1, const char *p2)
Definition: account.c:1091
static GtkWidget * button_account_password_confirm
Definition: account.c:57
void SockList_AddChar(SockList *sl, char c)
Definition: newsocket.c:43
static GtkWidget * entry_account_password_new
Definition: account.c:57
Definition: info.h:55
#define INFO_RULES
Definition: client.h:635
static int has_init
Definition: account.c:94
GtkListStore * character_store
Definition: account.c:61
void on_button_exit_client_clicked(GtkButton *button, gpointer user_data)
Definition: account.c:947
void choose_character_init()
Definition: account.c:439
#define BIG_BUF
Definition: client.h:41
void create_character_window_hide()
Definition: create_char.c:196
static GtkWidget * button_return_character_select
Definition: account.c:74
GtkTextBuffer * textbuf_motd
Definition: account.c:78
static GtkWidget * entry_new_confirm_password
Definition: account.c:41
static GtkWidget * button_add_character
Definition: account.c:47
void on_entry_character(GtkEntry *entry, gpointer user_data)
Definition: account.c:371
void on_entry_new_account(GtkEntry *entry, gpointer user_data)
Definition: account.c:807
static void init_add_character_window()
Definition: account.c:398
static GtkWidget * account_password_window
Definition: account.c:33
void account_creation_failure(char *message)
Definition: account.c:725
static GtkWidget * entry_new_account_name
Definition: account.c:41
static GtkWidget * entry_account_password
Definition: account.c:37
void SockList_Init(SockList *sl, guint8 *buf)
Definition: newsocket.c:32
static GtkWidget * button_account_password_cancel
Definition: account.c:57
PixmapInfo * pixmaps[MAXPIXMAPNUM]
Definition: image.c:47
static void init_choose_char_window()
Definition: account.c:608
static GtkWidget * choose_char_window
Definition: account.c:33
void on_button_return_login_clicked(GtkButton *button, gpointer user_data)
Definition: account.c:537
#define TEXTVIEW_RULES_CHAR
Definition: account.c:88
void on_button_new_cancel_clicked(GtkButton *button, gpointer user_data)
Definition: account.c:792
static GtkWidget * login_window
Definition: account.c:33
char * name
Definition: image.c:39
void on_button_account_password_clicked(GtkButton *button, gpointer user_data)
Definition: account.c:549
static GtkWidget * button_do_add_character
Definition: account.c:74
static GtkWidget * entry_account_name
Definition: account.c:37
GtkBuilder * dialog_xml
Definition: main.c:86
static GtkWidget * entry_character_password
Definition: account.c:74
void on_entry_account_name_activate(GtkEntry *entry, gpointer user_data)
Definition: account.c:999
char * motd
Definition: client.h:555
void update_login_info(int type)
Definition: account.c:1241
static GtkWidget * label_new_char_status
Definition: account.c:52
static item * map
Definition: item.c:28