Crossfire Client, Trunk  R20693
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 
441  gtk_widget_hide(login_window);
442  gtk_widget_hide(add_character_window);
443  gtk_widget_hide(create_account_window);
444  gtk_widget_show(choose_char_window);
445 
446  /* Store any old/stale entries */
447  gtk_list_store_clear(character_store);
448 }
449 
458  gtk_widget_show(choose_char_window);
459 }
460 
461 
466 static void play_character(const char *name) {
467  SockList sl;
468  guint8 buf[MAX_BUF];
469 
470  SockList_Init(&sl, buf);
471  SockList_AddString(&sl, "accountplay ");
472  SockList_AddString(&sl, name);
473  SockList_Send(&sl, csocket.fd);
474 }
475 
482 void
483 on_button_play_character_clicked(GtkButton *button, gpointer user_data) {
484  GtkTreeSelection *selected;
485  GtkTreeModel *model;
486  GtkTreeIter iter;
487  char *name;
488 
489  selected = gtk_tree_view_get_selection(GTK_TREE_VIEW(
491 
492  if (gtk_tree_selection_get_selected(selected, &model, &iter)) {
493  gtk_tree_model_get(model, &iter, CHAR_NAME, &name, -1);
494  play_character(name);
495  }
496 }
497 
503 void
504 on_button_create_character_clicked(GtkButton *button, gpointer user_data) {
505  gtk_widget_hide(choose_char_window);
506  if (serverloginmethod >= 2) {
508  } else {
509  gtk_widget_show(new_character_window);
510  gtk_entry_set_text(GTK_ENTRY(entry_new_character_name), "");
511  }
512 }
513 
520 void
521 on_button_add_character_clicked(GtkButton *button, gpointer user_data) {
522  gtk_widget_hide(choose_char_window);
523  gtk_widget_show(add_character_window);
524  gtk_entry_set_text(GTK_ENTRY(entry_character_name), "");
525  gtk_entry_set_text(GTK_ENTRY(entry_character_password), "");
526  gtk_widget_grab_focus(entry_character_name);
527 }
528 
535 void
536 on_button_return_login_clicked(GtkButton *button, gpointer user_data) {
537  gtk_widget_hide(choose_char_window);
538  gtk_widget_show(login_window);
539 }
540 
547 void
548 on_button_account_password_clicked(GtkButton *button, gpointer user_data) {
549  gtk_widget_hide(choose_char_window);
550  gtk_widget_show(account_password_window);
551  /* reset previous values */
552  gtk_entry_set_text(GTK_ENTRY(entry_account_password_current), "");
553  gtk_entry_set_text(GTK_ENTRY(entry_account_password_new), "");
554  gtk_entry_set_text(GTK_ENTRY(entry_account_password_confirm), "");
555 }
556 
571 void update_character_choose(const char *name, const char *class,
572  const char *race, const char *face,
573  const char *party, const char *map,
574  int level, int faceno) {
575  GtkTreeIter iter;
576 
577  gtk_list_store_append(character_store, &iter);
578 
579  /* If this pixmap matches pixmap[0], it means we are caching images and
580  * this image hasn't been set up. It looks better in this case to just
581  * leave that area of the window blank vs drawing a question mark there.
582  */
583  if (pixmaps[faceno] == pixmaps[0]) {
584  gtk_list_store_set(character_store, &iter,
585  CHAR_NAME, name,
586  CHAR_CLASS, class,
587  CHAR_RACE, race,
588  CHAR_IMAGE, face,
589  CHAR_PARTY, party,
590  CHAR_MAP, map,
591  CHAR_LEVEL, level,
592  -1);
593  } else {
594  gtk_list_store_set(character_store, &iter,
595  CHAR_ICON, pixmaps[faceno]->icon_image,
596  CHAR_NAME, name,
597  CHAR_CLASS, class,
598  CHAR_RACE, race,
599  CHAR_IMAGE, face,
600  CHAR_PARTY, party,
601  CHAR_MAP, map,
602  CHAR_LEVEL, level,
603  -1);
604  }
605 }
606 
607 static void init_choose_char_window() {
608  GtkTextIter end;
609  GtkCellRenderer *renderer;
610  GtkTreeViewColumn *column;
611 
613  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "choose_character_window"));
614 
615  gtk_window_set_transient_for(
616  GTK_WINDOW(choose_char_window), GTK_WINDOW(window_root));
617 
619  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_play_character"));
621  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_create_character"));
623  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_add_character"));
625  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_return_login"));
627  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_account_password"));
628  login_pane[TEXTVIEW_RULES_CHAR].textview =
629  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "textview_rules_char"));
630 
632  gtk_text_view_get_buffer(
633  GTK_TEXT_VIEW(login_pane[TEXTVIEW_RULES_CHAR].textview));
634 
636  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "treeview_choose_character"));
637 
640  add_style_to_textbuffer(&login_pane[TEXTVIEW_RULES_CHAR], NULL);
641  gtk_text_buffer_get_end_iter(
642  login_pane[TEXTVIEW_RULES_CHAR].textbuffer, &end);
643  login_pane[TEXTVIEW_RULES_CHAR].textmark =
644  gtk_text_buffer_create_mark(
645  login_pane[TEXTVIEW_RULES_CHAR].textbuffer, NULL, &end, FALSE);
646 
647  g_signal_connect((gpointer) choose_char_window, "delete_event",
648  G_CALLBACK(on_window_delete_event), NULL);
649  g_signal_connect((gpointer) button_play_character, "clicked",
650  G_CALLBACK(on_button_play_character_clicked), NULL);
651  g_signal_connect((gpointer) button_create_character, "clicked",
652  G_CALLBACK(on_button_create_character_clicked), NULL);
653  g_signal_connect((gpointer) button_add_character, "clicked",
654  G_CALLBACK(on_button_add_character_clicked), NULL);
655  g_signal_connect((gpointer) button_return_login, "clicked",
656  G_CALLBACK(on_button_return_login_clicked), NULL);
657  g_signal_connect((gpointer) button_account_password, "clicked",
658  G_CALLBACK(on_button_account_password_clicked), NULL);
659  g_signal_connect((gpointer) treeview_choose_character, "row_activated",
660  G_CALLBACK(on_button_play_character_clicked), NULL);
661 
662  character_store = gtk_list_store_new(CHAR_NUM_COLUMNS,
663  G_TYPE_STRING, G_TYPE_STRING,
664  G_TYPE_STRING, G_TYPE_STRING,
665  G_TYPE_INT, G_TYPE_STRING,
666  G_TYPE_STRING, G_TYPE_OBJECT);
667  gtk_tree_view_set_model(GTK_TREE_VIEW(treeview_choose_character),
668  GTK_TREE_MODEL(character_store));
669 
670  renderer = gtk_cell_renderer_pixbuf_new();
671  column = gtk_tree_view_column_new_with_attributes("?", renderer,
672  "pixbuf", CHAR_ICON,
673  NULL);
674 
675  gtk_tree_view_column_set_min_width(column, image_size);
676  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_choose_character), column);
677 
678  renderer = gtk_cell_renderer_text_new();
679  column = gtk_tree_view_column_new_with_attributes("Character Name", renderer,
680  "text", CHAR_NAME, NULL);
681  gtk_tree_view_column_set_sort_column_id(column, CHAR_NAME);
682  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_choose_character), column);
683 
684  renderer = gtk_cell_renderer_text_new();
685  column = gtk_tree_view_column_new_with_attributes("Class", renderer,
686  "text", CHAR_CLASS, NULL);
687  gtk_tree_view_column_set_sort_column_id(column, CHAR_CLASS);
688  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_choose_character), column);
689 
690  renderer = gtk_cell_renderer_text_new();
691  column = gtk_tree_view_column_new_with_attributes("Race", renderer,
692  "text", CHAR_RACE, NULL);
693  gtk_tree_view_column_set_sort_column_id(column, CHAR_RACE);
694  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_choose_character), column);
695 
696  renderer = gtk_cell_renderer_text_new();
697  column = gtk_tree_view_column_new_with_attributes("Level", renderer,
698  "text", CHAR_LEVEL, NULL);
699  gtk_tree_view_column_set_sort_column_id(column, CHAR_LEVEL);
700  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_choose_character), column);
701 
702  renderer = gtk_cell_renderer_text_new();
703  column = gtk_tree_view_column_new_with_attributes("Party", renderer,
704  "text", CHAR_PARTY, NULL);
705  gtk_tree_view_column_set_sort_column_id(column, CHAR_PARTY);
706  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_choose_character), column);
707 
708  renderer = gtk_cell_renderer_text_new();
709  column = gtk_tree_view_column_new_with_attributes("Map", renderer,
710  "text", CHAR_MAP, NULL);
711  gtk_tree_view_column_set_sort_column_id(column, CHAR_MAP);
712  gtk_tree_view_append_column(GTK_TREE_VIEW(treeview_choose_character), column);
713 }
714 
715 /******************************************************************************
716  * create_account_window
717  ******************************************************************************/
718 
724 void account_creation_failure(char *message) {
725  gtk_label_set_text(GTK_LABEL(label_create_account_status), message);
726 }
727 
740 static void do_account_create(const char *name, const char *p1,
741  const char *p2) {
742  SockList sl;
743  guint8 buf[MAX_BUF];
744 
745  if (strcmp(p1, p2)) {
746  gtk_label_set_text(GTK_LABEL(label_create_account_status),
747  "The passwords you entered do not match!");
748  return;
749  } else {
750  gtk_label_set_text(GTK_LABEL(label_create_account_status), "");
751  SockList_Init(&sl, buf);
752  SockList_AddString(&sl, "accountnew ");
753  SockList_AddChar(&sl, strlen(name));
754  SockList_AddString(&sl, name);
755  SockList_AddChar(&sl, strlen(p1));
756  SockList_AddString(&sl, p1);
757  SockList_Send(&sl, csocket.fd);
758  /* Store password away for new character creation */
759  snprintf(account_password, sizeof(account_password), "%s", p1);
760  }
761 }
762 
769 void
770 on_button_new_create_account_clicked(GtkButton *button, gpointer user_data) {
771  const char *password1, *password2, *name;
772 
773  password1 = gtk_entry_get_text(GTK_ENTRY(entry_new_account_password));
774  password2 = gtk_entry_get_text(GTK_ENTRY(entry_new_confirm_password));
775  name = gtk_entry_get_text(GTK_ENTRY(entry_new_account_name));
776 
777  if (name && name[0] && password1 && password1[0] && password2 && password2[0]) {
778  do_account_create(name, password1, password2);
779  } else {
780  gtk_label_set_text(GTK_LABEL(label_create_account_status),
781  "You must fill in all three entries!");
782  }
783 }
784 
790 void
791 on_button_new_cancel_clicked(GtkButton *button, gpointer user_data) {
792  gtk_widget_hide(create_account_window);
793  gtk_widget_show(login_window);
794 }
795 
805 void
806 on_entry_new_account(GtkEntry *entry, gpointer user_data) {
807 
808  const char *password1, *password2, *name, *cp;
809 
810  password1 = gtk_entry_get_text(GTK_ENTRY(entry_new_account_password));
811  password2 = gtk_entry_get_text(GTK_ENTRY(entry_new_confirm_password));
812  name = gtk_entry_get_text(GTK_ENTRY(entry_new_account_name));
813  if (name && name[0] && password1 && password1[0] && password2 && password2[0]) {
814  do_account_create(name, password1, password2);
815  } else {
816  /* In this case, one, or more, of the fields is blank. If there were
817  * more than 3 widgets, I might but them into an array to make cycling
818  * easier
819  */
820 
821  /* First case - if the currently active one is blank, no reason to
822  * move onward.
823  */
824  cp = gtk_entry_get_text(entry);
825  if (!cp || !cp[0]) {
826  return;
827  }
828 
829  /* I'm not sure if it would make more sense to advance to the first
830  * NULL entry - but in that case, the pointer may hop in non intuitive
831  * ways - in this case, the user may just need to hit return a few
832  * times - MSW 2010/03/29
833  */
834  if (entry == GTK_ENTRY(entry_new_account_name)) {
835  gtk_widget_grab_focus(entry_new_account_password);
836  } else if (entry == GTK_ENTRY(entry_new_account_password)) {
837  gtk_widget_grab_focus(entry_new_confirm_password);
838  } else if (entry == GTK_ENTRY(entry_new_confirm_password)) {
839  gtk_widget_grab_focus(entry_new_account_name);
840  }
841  }
842 }
843 
849  GtkTextIter end;
850 
852  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "create_account_window"));
853 
854  gtk_window_set_transient_for(
855  GTK_WINDOW(create_account_window), GTK_WINDOW(window_root));
856 
858  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_new_create_account"));
860  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_new_cancel"));
861  login_pane[TEXTVIEW_RULES_ACCOUNT].textview =
862  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "textview_rules_account"));
863 
865  gtk_text_view_get_buffer(
866  GTK_TEXT_VIEW(login_pane[TEXTVIEW_RULES_ACCOUNT].textview));
867 
869  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "entry_new_account_name"));
871  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "entry_new_account_password"));
873  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "entry_new_confirm_password"));
875  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "label_create_account_status"));
876 
879  add_style_to_textbuffer(&login_pane[TEXTVIEW_RULES_ACCOUNT], NULL);
880  gtk_text_buffer_get_end_iter(
881  login_pane[TEXTVIEW_RULES_ACCOUNT].textbuffer, &end);
882  login_pane[TEXTVIEW_RULES_ACCOUNT].textmark =
883  gtk_text_buffer_create_mark(
884  login_pane[TEXTVIEW_RULES_ACCOUNT].textbuffer, NULL, &end, FALSE);
885 
886  g_signal_connect((gpointer) create_account_window, "delete_event",
887  G_CALLBACK(on_window_delete_event), NULL);
888  g_signal_connect((gpointer) button_new_create_account, "clicked",
889  G_CALLBACK(on_button_new_create_account_clicked), NULL);
890  g_signal_connect((gpointer) button_new_cancel, "clicked",
891  G_CALLBACK(on_button_new_cancel_clicked), NULL);
892  g_signal_connect((gpointer) entry_new_account_name, "activate",
893  G_CALLBACK(on_entry_new_account), NULL);
894  g_signal_connect((gpointer) entry_new_account_password, "activate",
895  G_CALLBACK(on_entry_new_account), NULL);
896  g_signal_connect((gpointer) entry_new_confirm_password, "activate",
897  G_CALLBACK(on_entry_new_account), NULL);
898 }
899 
900 /*****************************************************************************
901  * login_window
902  *****************************************************************************/
903 
909 void account_login_failure(char *message) {
910  gtk_label_set_text(GTK_LABEL(label_account_login_status), message);
911 }
912 
919 void
920 on_button_create_account_clicked(GtkButton *button, gpointer user_data) {
921  gtk_widget_hide(login_window);
922  gtk_label_set_text(GTK_LABEL(label_create_account_status), "");
923  gtk_entry_set_text(GTK_ENTRY(entry_new_account_name), "");
924  gtk_entry_set_text(GTK_ENTRY(entry_new_account_password), "");
925  gtk_entry_set_text(GTK_ENTRY(entry_new_confirm_password), "");
926  gtk_widget_show(create_account_window);
927 }
928 
936 void
937 on_button_go_metaserver_clicked(GtkButton *button, gpointer user_data) {
939 }
940 
946 void on_button_exit_client_clicked(GtkButton *button, gpointer user_data) {
947 #ifdef WIN32
948  script_killall();
949 #endif
950  exit(0);
951 }
952 
960 static void do_account_login(const char *name, const char *password) {
961  SockList sl;
962  guint8 buf[MAX_BUF];
963 
964  if (!name || !password || *name == 0 || *password == 0) {
965  gtk_label_set_text(GTK_LABEL(label_account_login_status),
966  "You must enter both a name and password!");
967  } else {
968  gtk_label_set_text(GTK_LABEL(label_account_login_status), "");
969 
970  SockList_Init(&sl, buf);
971  SockList_AddString(&sl, "accountlogin ");
972  SockList_AddChar(&sl, strlen(name));
973  SockList_AddString(&sl, name);
974  SockList_AddChar(&sl, strlen(password));
975  SockList_AddString(&sl, password);
976  SockList_Send(&sl, csocket.fd);
977  /* Store password away for new character creation */
978  snprintf(account_password, sizeof(account_password), "%s", password);
979  }
980 }
981 
987 void
988 on_button_login_clicked(GtkButton *button, gpointer user_data) {
989  do_account_login(gtk_entry_get_text(GTK_ENTRY(entry_account_name)),
990  gtk_entry_get_text(GTK_ENTRY(entry_account_password)));
991 }
992 
998 void on_entry_account_name_activate(GtkEntry* entry, gpointer user_data) {
999  gtk_widget_grab_focus(entry_account_password);
1000 }
1001 
1006 static void init_login_window() {
1007  GtkTextIter end;
1008 
1009  login_window = GTK_WIDGET(gtk_builder_get_object(dialog_xml, "login_window"));
1010  if (!login_window) {
1011  error_dialog("Failed to open dialogs.", "Did you run `make install`?");
1012  exit(1);
1013  }
1014 
1015  g_signal_connect(login_window, "delete_event",
1016  G_CALLBACK(on_button_exit_client_clicked), NULL);
1017 
1018  gtk_window_set_transient_for(
1019  GTK_WINDOW(login_window), GTK_WINDOW(window_root));
1020  button_login =
1021  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_login"));
1023  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_create_account"));
1025  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "button_go_metaserver"));
1027  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "label_account_login_status"));
1028  login_pane[TEXTVIEW_MOTD].textview =
1029  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "textview_motd"));
1030 
1031  textbuf_motd =
1032  gtk_text_view_get_buffer(
1033  GTK_TEXT_VIEW(login_pane[TEXTVIEW_MOTD].textview));
1034 
1036  add_style_to_textbuffer(&login_pane[TEXTVIEW_MOTD], NULL);
1037  gtk_text_buffer_get_end_iter(login_pane[TEXTVIEW_MOTD].textbuffer, &end);
1038  login_pane[TEXTVIEW_MOTD].textmark =
1039  gtk_text_buffer_create_mark(
1040  login_pane[TEXTVIEW_MOTD].textbuffer, NULL, &end, FALSE);
1041 
1042  login_pane[TEXTVIEW_NEWS].textview =
1043  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "textview_news"));
1044 
1045  textbuf_news =
1046  gtk_text_view_get_buffer(
1047  GTK_TEXT_VIEW(login_pane[TEXTVIEW_NEWS].textview));
1048 
1050  add_style_to_textbuffer(&login_pane[TEXTVIEW_NEWS], NULL);
1051  gtk_text_buffer_get_end_iter(login_pane[TEXTVIEW_NEWS].textbuffer, &end);
1052  login_pane[TEXTVIEW_NEWS].textmark =
1053  gtk_text_buffer_create_mark(
1054  login_pane[TEXTVIEW_NEWS].textbuffer, NULL, &end, FALSE);
1055 
1057  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "entry_account_name"));
1059  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "entry_account_password"));
1060 
1061  g_signal_connect((gpointer) login_window, "delete_event",
1062  G_CALLBACK(on_window_delete_event), NULL);
1063  g_signal_connect((gpointer) entry_account_name, "activate",
1064  G_CALLBACK(on_entry_account_name_activate), NULL);
1065  // entry_account_password is the default action in GtkBuilder
1066  g_signal_connect((gpointer) button_login, "clicked",
1067  G_CALLBACK(on_button_login_clicked), NULL);
1068  g_signal_connect((gpointer) button_create_account, "clicked",
1069  G_CALLBACK(on_button_create_account_clicked), NULL);
1070  g_signal_connect((gpointer) button_go_metaserver, "clicked",
1071  G_CALLBACK(on_button_go_metaserver_clicked), NULL);
1072 }
1073 
1074 /*****************************************************************************
1075  * Account password change
1076  ****************************************************************************/
1077 
1090 static void do_account_change(const char *old, const char *p1, const char *p2) {
1091  SockList sl;
1092  guint8 buf[MAX_BUF];
1093 
1094  if (strcmp(p1, p2)) {
1095  gtk_label_set_text(GTK_LABEL(label_account_password_status),
1096  "The passwords you entered do not match!");
1097  return;
1098  } else {
1099  gtk_label_set_text(GTK_LABEL(label_account_password_status), "");
1100  SockList_Init(&sl, buf);
1101  SockList_AddString(&sl, "accountpw ");
1102  SockList_AddChar(&sl, strlen(old));
1103  SockList_AddString(&sl, old);
1104  SockList_AddChar(&sl, strlen(p1));
1105  SockList_AddString(&sl, p1);
1106  SockList_Send(&sl, csocket.fd);
1107  /* Store password away for new character creation */
1108  snprintf(account_password, sizeof(account_password), "%s", p1);
1109  }
1110 }
1111 
1118 void
1120  gpointer user_data) {
1121  gtk_widget_hide(account_password_window);
1122  gtk_widget_show(choose_char_window);
1123 }
1124 
1130 void
1132  gpointer user_data) {
1133  do_account_change(gtk_entry_get_text(GTK_ENTRY(entry_account_password_current)),
1134  gtk_entry_get_text(GTK_ENTRY(entry_account_password_new)),
1135  gtk_entry_get_text(GTK_ENTRY(entry_account_password_confirm)));
1136 }
1137 
1147 void
1148 on_entry_account_password(GtkEntry *entry, gpointer user_data) {
1149 
1150  const char *old, *password1, *password2, *cp;
1151 
1152  old = gtk_entry_get_text(GTK_ENTRY(entry_account_password_current));
1153  password1 = gtk_entry_get_text(GTK_ENTRY(entry_account_password_new));
1154  password2 = gtk_entry_get_text(GTK_ENTRY(entry_account_password_confirm));
1155  if (old && old[0] && password1 && password1[0] && password2 && password2[0]) {
1156  do_account_change(old, password1, password2);
1157  } else {
1158  /* In this case, one, or more, of the fields is blank. If there were
1159  * more than 3 widgets, I might but them into an array to make cycling
1160  * easier
1161  */
1162 
1163  /* First case - if the currently active one is blank, no reason to
1164  * move onward.
1165  */
1166  cp = gtk_entry_get_text(entry);
1167  if (!cp || !cp[0]) {
1168  return;
1169  }
1170 
1171  if (entry == GTK_ENTRY(entry_account_password_current)) {
1172  gtk_widget_grab_focus(entry_account_password_new);
1173  } else if (entry == GTK_ENTRY(entry_account_password_new)) {
1174  gtk_widget_grab_focus(entry_account_password_confirm);
1175  } else if (entry == GTK_ENTRY(entry_account_password_confirm)) {
1176  gtk_widget_grab_focus(entry_account_password_current);
1177  }
1178  }
1179 }
1180 
1181 void account_change_password_failure(char *message) {
1182  gtk_label_set_text(GTK_LABEL(label_account_password_status), message);
1183 }
1184 
1191  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "account_password_window"));
1192 
1193  gtk_window_set_transient_for(
1194  GTK_WINDOW(account_password_window), GTK_WINDOW(window_root));
1195 
1197  GTK_WIDGET(gtk_builder_get_object(dialog_xml,
1198  "button_account_password_confirm"));
1200  GTK_WIDGET(gtk_builder_get_object(dialog_xml,
1201  "button_account_password_cancel"));
1202 
1204  GTK_WIDGET(gtk_builder_get_object(dialog_xml,
1205  "entry_account_password_current"));
1207  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "entry_account_password_new"));
1209  GTK_WIDGET(gtk_builder_get_object(dialog_xml,
1210  "entry_account_password_confirm"));
1212  GTK_WIDGET(gtk_builder_get_object(dialog_xml, "label_account_password_status"));
1213 
1214  g_signal_connect((gpointer) account_password_window, "delete_event",
1215  G_CALLBACK(on_window_delete_event), NULL);
1216  g_signal_connect((gpointer) button_account_password_confirm, "clicked",
1217  G_CALLBACK(on_button_account_password_confirm_clicked), NULL);
1218  g_signal_connect((gpointer) button_account_password_cancel, "clicked",
1219  G_CALLBACK(on_button_account_password_cancel_clicked), NULL);
1220  g_signal_connect((gpointer) entry_account_password_current, "activate",
1221  G_CALLBACK(on_entry_account_password), NULL);
1222  g_signal_connect((gpointer) entry_account_password_new, "activate",
1223  G_CALLBACK(on_entry_account_password), NULL);
1224  g_signal_connect((gpointer) entry_account_password_confirm, "activate",
1225  G_CALLBACK(on_entry_account_password), NULL);
1226 }
1227 
1228 
1229 /*****************************************************************************
1230  * Common/generic functions
1231  ****************************************************************************/
1232 
1240 void update_login_info(int type) {
1241  if (!has_init) {
1242  return;
1243  }
1244 
1245  /* In all cases, we clear the buffer, and if we have data, then set it to
1246  * that data. This routine could be smarter an
1247  */
1248  if (type == INFO_NEWS) {
1249  gtk_text_buffer_set_text(textbuf_news, "", 0);
1250  if (news) {
1251  /* the format of the news entry is special - there are a series of
1252  * %entries, and they are in reverse older (newest last) we want
1253  * to get rid of the %, make them more visible (convert them to
1254  * bold) and reverse the order.
1255  */
1256  char *mynews, *cp, *el, big_buf[BIG_BUF], *cp1;
1257 
1258  mynews = g_strdup(news);
1259  /* We basically work from the end of the string going towards the
1260  * start looking for % characters. If we find one, we have to
1261  * make sure it is at the start of the line or start of the buffer
1262  */
1263  for (cp = mynews + strlen(mynews); cp > mynews; cp--) {
1264  if (*cp == '%' && (*(cp - 1) == '\n' || cp == mynews)) {
1265  /* Find the end of the line */
1266  el = strchr(cp, '\n');
1267  /* null out the newline, put el one char beyond it */
1268  if (el) {
1269  *el = 0;
1270  el++;
1271  }
1272  /* There isn't a clear standard - % news may be valid, as
1273  * might be %news. If % news is used, it looks better to
1274  * get rid of that leading space.
1275  */
1276  cp1 = cp + 1;
1277  while (isspace(*cp1)) {
1278  cp1++;
1279  }
1280 
1281  /* since we've null out the newline, this snprintf will
1282  * only get the % line and that is it. Mark it up
1283  */
1284  snprintf(big_buf, BIG_BUF, "[b]%s[/b]", cp1);
1285  add_marked_text_to_pane(&login_pane[TEXTVIEW_NEWS], big_buf, 0, 0, 0);
1286  /* Now we draw the text that goes with it, if it exists */
1287  if (el) {
1288  add_marked_text_to_pane(&login_pane[TEXTVIEW_NEWS], el, 0, 0, 0);
1289  }
1290 
1291  /* Now we wipe the % out. In this way, the news buffer is
1292  * shorter, so when it draws the ext, there will just be
1293  * that between the % and the one we just wiped out.
1294  */
1295  *cp = 0;
1296  }
1297  }
1298  /* If there are remnants left over, or perhaps the news file isn't
1299  * formatted with % headers, display what we have got.
1300  */
1301  if (*mynews != 0) {
1302  add_marked_text_to_pane(&login_pane[TEXTVIEW_NEWS], mynews, 0, 0, 0);
1303  }
1304  }
1305  } else if (type == INFO_MOTD) {
1306  gtk_text_buffer_set_text(textbuf_motd, "", 0);
1307  if (motd) {
1308  add_marked_text_to_pane(&login_pane[TEXTVIEW_MOTD], motd, 0, 0, 0);
1309  }
1310  } else if (type == INFO_RULES) {
1311  gtk_text_buffer_set_text(textbuf_rules_account, "", 0);
1312  gtk_text_buffer_set_text(textbuf_rules_char, "", 0);
1313 
1314  if (rules) {
1315  add_marked_text_to_pane(&login_pane[TEXTVIEW_RULES_ACCOUNT], rules, 0, 0, 0);
1316  add_marked_text_to_pane(&login_pane[TEXTVIEW_RULES_CHAR], rules, 0, 0, 0);
1317  }
1318  }
1319 }
1320 
1329 void start_login(int method) {
1330  /* Store this away - if method is only 1, we can not do smart character
1331  * creation.
1332  */
1333  serverloginmethod = method;
1334 
1335  if (!has_init) {
1336  /* Since there are 4 windows associated with account and character
1337  * login, to make life a little easier, each section here does all the
1338  * work for one window, so it is easier to see that everything for a
1339  * window is done - don't need to hunt through what would otherwise be
1340  * a long routine looking for entries.
1341  */
1343 
1345 
1347 
1349 
1351 
1353 
1354  has_init = 1;
1355 
1356  /* In case we have gotten news/motd/rules before getting here, update
1357  * it now.
1358  */
1362  }
1363 
1364  gtk_entry_set_text(GTK_ENTRY(entry_account_name), "");
1365  gtk_entry_set_text(GTK_ENTRY(entry_account_password), "");
1366  /* We set focus to account name - this makes the most sense if user is
1367  * logging in again - it is possible that the password is active, but both
1368  * fields are blank, which is not what is expected.
1369  */
1370  gtk_widget_grab_focus(entry_account_name);
1371  gtk_widget_show(login_window);
1372 }
1373 
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:1119
void choose_char_window_show()
Definition: account.c:457
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:1131
void on_button_create_character_clicked(GtkButton *button, gpointer user_data)
Definition: account.c:504
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:521
static void init_login_window()
Definition: account.c:1006
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:848
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:571
#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:770
#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:1148
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:960
void start_login(int method)
Definition: account.c:1329
void account_login_failure(char *message)
Definition: account.c:909
void account_change_password_failure(char *message)
Definition: account.c:1181
void client_disconnect()
Definition: client.c:180
void hide_main_client()
Definition: main.c:420
#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:920
static void play_character(const char *name)
Definition: account.c:466
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:483
void on_button_login_clicked(GtkButton *button, gpointer user_data)
Definition: account.c:988
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:937
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:1189
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:740
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:1090
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:946
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:806
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:724
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:607
static GtkWidget * choose_char_window
Definition: account.c:33
void on_button_return_login_clicked(GtkButton *button, gpointer user_data)
Definition: account.c:536
#define TEXTVIEW_RULES_CHAR
Definition: account.c:88
void on_button_new_cancel_clicked(GtkButton *button, gpointer user_data)
Definition: account.c:791
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:548
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:998
char * motd
Definition: client.h:555
void update_login_info(int type)
Definition: account.c:1240
static GtkWidget * label_new_char_status
Definition: account.c:52
static item * map
Definition: item.c:28