Crossfire Client, Branch  R11627
help.c
Go to the documentation of this file.
00001 /*
00002     Crossfire client, a client program for the crossfire program.
00003 
00004     Copyright (C) 2001-2005 Mark Wedel & Crossfire Development Team
00005 
00006     This program is free software; you can redistribute it and/or modify
00007     it under the terms of the GNU General Public License as published by
00008     the Free Software Foundation; either version 2 of the License, or
00009     (at your option) any later version.
00010 
00011     This program is distributed in the hope that it will be useful,
00012     but WITHOUT ANY WARRANTY; without even the implied warranty of
00013     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00014     GNU General Public License for more details.
00015 
00016     You should have received a copy of the GNU General Public License
00017     along with this program; if not, write to the Free Software
00018     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019 
00020     The author can be reached via e-mail to crossfire-devel@real-time.com
00021 */
00022 
00023 
00024 #include <gtk/gtk.h>
00025 #include "client-types.h"
00026 #include "../common/p_cmd.h"
00027 
00028 static GtkWidget *chelptext = NULL; /* HACK */
00029 
00030 static void replace_text(const char * new_text) {
00031     gtk_text_set_point(GTK_TEXT(chelptext), 0);
00032     gtk_text_forward_delete(GTK_TEXT(chelptext), gtk_text_get_length(GTK_TEXT(chelptext)) );
00033     gtk_text_insert(GTK_TEXT(chelptext), NULL, &chelptext->style->black, NULL, new_text, -1);
00034 }
00035 
00036 #define CLIENTHELP_LONG_LIST
00037 /* Wossname. */
00038 #define assumed_wrap 120
00039 #define COLOSSAL_BUF 8192
00040 
00041 /* HACK Mostly duplicated from common/p_cmd.c. */
00042 static void set_default_text(void) {
00043     char out_buf[COLOSSAL_BUF];
00044     char tmp_buf[COLOSSAL_BUF];
00045     ConsoleCommand ** array_cc;
00046     ConsoleCommand * cc;
00047     int i;
00048     CommCat current_cat = COMM_CAT_MISC;
00049 #ifndef CLIENTHELP_LONG_LIST
00050     size_t name_len;
00051     char line_buf[MAX_BUF];
00052     size_t line_len;
00053 
00054     line_buf[0] = '\0';
00055     line_len = 0;
00056 #endif
00057 
00058 /* HACK */
00059 #define LINE(x) strncpy(tmp_buf, out_buf, COLOSSAL_BUF - 1); snprintf(out_buf, COLOSSAL_BUF - 1, "%s%s\n", tmp_buf, x);
00060 
00061     strcpy(out_buf,
00062         "To get help on one of the commands listed below, enter the name in the text entry "
00063         "box below, and press Enter. To get back to this list, clear the text box and press "
00064         "Enter.\n"
00065         "\n"
00066         " === Client Side Command List === \n"
00067     );
00068 
00069     array_cc = get_cat_sorted_commands();
00070 
00071     for (i = 0; i < get_num_commands(); i++) {
00072         cc = array_cc[i];
00073         if (cc->cat != current_cat) {
00074             char buf[MAX_BUF];
00075 
00076 #ifndef CLIENTHELP_LONG_LIST
00077             if (line_len > 0) {
00078                 LINE(line_buf);
00079                 line_buf[0] = '\0';
00080                 line_len = 0;
00081             }
00082 #endif
00083 
00084             snprintf(buf, MAX_BUF - 1, "%s Commands:", get_category_name(cc->cat));
00085             LINE(buf);
00086             current_cat = cc->cat;
00087         }
00088 
00089 #ifdef CLIENTHELP_LONG_LIST
00090         if (cc->desc != NULL) {
00091             char buf[MAX_BUF];
00092             snprintf(buf, MAX_BUF - 1, "%s - %s", cc->name, cc->desc);
00093             LINE(buf);
00094         } else {
00095             LINE(cc->name);
00096         }
00097 #else
00098         name_len = strlen(cc->name);
00099 
00100         if (strlen(cc->name) > MAX_BUF) {
00101             LINE(cc->name);
00102         } else if (name_len > assumed_wrap) {
00103             LINE(line_buf);
00104             LINE(cc->name);
00105             line_len = 0;
00106         } else if (line_len + name_len > assumed_wrap) {
00107             LINE(line_buf);
00108             strncpy(line_buf, cc->name, name_len + 1);
00109             line_len = name_len;
00110         } else {
00111             if (line_len > 0) {
00112                 strncat(line_buf, " ", 2);
00113                 line_len += 1;
00114             }
00115             strncat(line_buf, cc->name, name_len + 1);
00116             line_len += name_len;
00117         }
00118 #endif
00119     }
00120 
00121 #ifndef CLIENTHELP_LONG_LIST
00122     /* Dump dangling commands. Been there, got the fencepost.
00123     Or is it a gap? */
00124     if (line_len > 0) {
00125         LINE(line_buf);
00126     }
00127 #endif
00128 
00129     replace_text(out_buf);
00130 }
00131 
00132 static void chelp_entry_callback(GtkWidget * cargo_cult_ignored, GtkWidget * topic_entry) {
00133     char buf[MAX_BUF];
00134     const gchar * topic;
00135     const ConsoleCommand * cc;
00136     /* LOG(LOG_INFO, "chelp_entry_callback", "Got %s", gtk_entry_get_text(GTK_ENTRY(topic_entry))); */
00137 
00138     topic = gtk_entry_get_text(GTK_ENTRY(topic_entry));
00139     /* TODO Select it, in case typing replaces selection. */
00140 
00141     if (topic == NULL || strlen(topic) <= 0) {
00142          set_default_text();
00143          return;
00144     }
00145 
00146     cc = find_command(topic);
00147 
00148     if (cc == NULL) {
00149         snprintf(buf, MAX_BUF - 1, "No command '%s' found.", topic);
00150         replace_text(buf);
00151     } else {
00152         char out_buf[COLOSSAL_BUF];
00153         const char * extended;
00154 
00155         if (cc->desc != NULL) {
00156             snprintf(buf, MAX_BUF - 1, "%s - %s",
00157                 cc->name,
00158                 cc->desc);
00159         } else {
00160             snprintf(buf, MAX_BUF - 1, cc->name);
00161         }
00162 
00163         if (cc->helpfunc == NULL) {
00164             extended = "This command is undocumented.";
00165         } else {
00166             extended = cc->helpfunc();
00167             if (extended == NULL) {
00168                 extended = "This command is not yet documented.";
00169             }
00170         }
00171 
00172         snprintf(out_buf, COLOSSAL_BUF - 1, "%s Command:\n%s\n\n%s",
00173             get_category_name(cc->cat),
00174             buf,
00175             extended);
00176         replace_text(out_buf);
00177     }
00178 }
00179 
00180 static GtkWidget *gtkwin_chelp = NULL;
00181 
00182 void chelpdialog(GtkWidget *widget) {
00183   GtkWidget *vbox;
00184   GtkWidget *hbox;
00185   GtkWidget *helpbutton;
00186   GtkWidget *vscrollbar;
00187   GtkWidget * topic_entry;
00188   GtkWidget * lblCommand;
00189   /*  GtkStyle *style;*/
00190 
00191 
00192   if(gtkwin_chelp == NULL) {
00193 
00194     gtkwin_chelp = gtk_window_new (GTK_WINDOW_DIALOG);
00195     gtk_window_position (GTK_WINDOW (gtkwin_chelp), GTK_WIN_POS_CENTER);
00196     gtk_widget_set_usize (gtkwin_chelp,400,300);
00197     gtk_window_set_title (GTK_WINDOW (gtkwin_chelp), "Crossfire Client-Side Command Help");
00198     gtk_window_set_policy (GTK_WINDOW (gtkwin_chelp), TRUE, TRUE, FALSE);
00199 
00200     gtk_signal_connect (GTK_OBJECT (gtkwin_chelp), "destroy", GTK_SIGNAL_FUNC(gtk_widget_destroyed), &gtkwin_chelp);
00201 
00202     gtk_container_border_width (GTK_CONTAINER (gtkwin_chelp), 1);
00203     vbox = gtk_vbox_new(FALSE, 2);
00204     gtk_container_add (GTK_CONTAINER(gtkwin_chelp),vbox);
00205     hbox = gtk_hbox_new(FALSE, 2);
00206     gtk_box_pack_start (GTK_BOX (vbox), hbox, TRUE, TRUE, 0);
00207 
00208     chelptext = gtk_text_new (NULL, NULL);
00209     gtk_text_set_editable (GTK_TEXT (chelptext), FALSE);
00210     gtk_box_pack_start (GTK_BOX (hbox),chelptext, TRUE, TRUE, 0);
00211     gtk_widget_show (chelptext);
00212 
00213     vscrollbar = gtk_vscrollbar_new (GTK_TEXT (chelptext)->vadj);
00214     gtk_box_pack_start (GTK_BOX (hbox),vscrollbar, FALSE, FALSE, 0);
00215 
00216     gtk_widget_show (vscrollbar);
00217     gtk_widget_show (hbox);
00218 
00219     hbox = gtk_hbox_new(FALSE, 2);
00220     lblCommand = gtk_label_new("Command: ");
00221     gtk_box_pack_start(GTK_BOX(hbox), lblCommand, FALSE, FALSE, 0);
00222 
00223     topic_entry = gtk_entry_new ();
00224     gtk_box_pack_start (GTK_BOX (hbox), topic_entry, TRUE, TRUE, 0);
00225     gtk_signal_connect(GTK_OBJECT(topic_entry), "activate",
00226                      GTK_SIGNAL_FUNC(chelp_entry_callback),
00227                      topic_entry);
00228     /* TODO Make it a combo box? No? */
00229 
00230     helpbutton = gtk_button_new_with_label ("Close");
00231     gtk_signal_connect_object (GTK_OBJECT (helpbutton), "clicked",
00232                                GTK_SIGNAL_FUNC(gtk_widget_destroy),
00233                                GTK_OBJECT (gtkwin_chelp));
00234     gtk_box_pack_end (GTK_BOX (hbox), helpbutton, FALSE, FALSE, 0);
00235     gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
00236     gtk_widget_show (lblCommand);
00237     gtk_widget_show (topic_entry);
00238     gtk_widget_show (helpbutton);
00239     gtk_widget_show (hbox);
00240 
00241     gtk_widget_show (vbox);
00242     gtk_widget_show (gtkwin_chelp);
00243     set_default_text();
00244   }
00245   else {
00246     gdk_window_raise (gtkwin_chelp->window);
00247   }
00248 }