Crossfire Server, Branch 1.12
R12190
|
00001 /* 00002 CrossFire, A Multiplayer game for X-windows 00003 00004 Copyright (C) 2008 Crossfire Development Team 00005 Copyright (C) 1992 Frank Tore Johansen 00006 00007 This program is free software; you can redistribute it and/or modify 00008 it under the terms of the GNU General Public License as published by 00009 the Free Software Foundation; either version 2 of the License, or 00010 (at your option) any later version. 00011 00012 This program is distributed in the hope that it will be useful, 00013 but WITHOUT ANY WARRANTY; without even the implied warranty of 00014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00015 GNU General Public License for more details. 00016 00017 You should have received a copy of the GNU General Public License 00018 along with this program; if not, write to the Free Software 00019 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 00020 00021 The authors can be reached via e-mail at crossfire-devel@real-time.com 00022 */ 00023 00029 #include <string.h> 00030 #include "global.h" 00031 #include "define.h" 00032 #include "object.h" 00033 #include "dialog.h" 00034 00039 void free_dialog_information(object *op) { 00040 struct_dialog_message *current, *next; 00041 struct_dialog_reply *currep, *nextrep; 00042 00043 if (!QUERY_FLAG(op, FLAG_DIALOG_PARSED)) 00044 return; 00045 00046 CLEAR_FLAG(op, FLAG_DIALOG_PARSED); 00047 if (!op->dialog_information) 00048 return; 00049 00050 current = op->dialog_information->all_messages; 00051 while (current) { 00052 next = current->next; 00053 free(current->match); 00054 free(current->message); 00055 currep = current->replies; 00056 while (currep) { 00057 nextrep = currep->next; 00058 free(currep->reply); 00059 free(currep->message); 00060 currep = nextrep; 00061 } 00062 free(current); 00063 current = next; 00064 } 00065 00066 currep = op->dialog_information->all_replies; 00067 while (currep) { 00068 nextrep = currep->next; 00069 free(currep->reply); 00070 free(currep->message); 00071 free(currep); 00072 currep = nextrep; 00073 } 00074 00075 free(op->dialog_information); 00076 op->dialog_information = NULL; 00077 } 00078 00086 static int matches(const char *exp, const char *text) { 00087 char *pipe, *save, *msg; 00088 int match = 0; 00089 00090 if (exp[0] == '*') 00091 return 1; 00092 00093 msg = strdup(exp); 00094 00095 pipe = strtok_r(msg, "|", &save); 00096 while (pipe) { 00097 if (re_cmp(text, pipe)) { 00098 match = 1; 00099 break; 00100 } 00101 pipe = strtok_r(NULL, "|", &save); 00102 } 00103 00104 free(msg); 00105 return match; 00106 } 00107 00114 static void parse_dialog_information(object *op) { 00115 struct_dialog_message *message = NULL, *last = NULL; 00116 struct_dialog_reply *reply = NULL; 00117 char *current, *save, *msg, *cp; 00118 int len; 00119 /* Used for constructing message with */ 00120 char *tmp = NULL; 00121 size_t tmplen = 0; 00122 00123 if (QUERY_FLAG(op, FLAG_DIALOG_PARSED)) 00124 return; 00125 SET_FLAG(op, FLAG_DIALOG_PARSED); 00126 00127 op->dialog_information = (struct_dialog_information *)calloc(1, sizeof(struct_dialog_information)); 00128 00129 if (!op->msg) 00130 return; 00131 00132 msg = strdup(op->msg); 00133 current = strtok_r(msg, "\n", &save); 00134 00135 while (current) { 00136 if (strncmp(current, "@match ", 7) == 0) { 00137 if (message) { 00138 message->message = tmp; 00139 tmp = NULL; 00140 tmplen = 0; 00141 } 00142 00143 message = (struct_dialog_message *)calloc(1, sizeof(struct_dialog_message)); 00144 if (last) 00145 last->next = message; 00146 else 00147 op->dialog_information->all_messages = message; 00148 last = message; 00149 00150 message->match = strdup(current+7); 00151 } else if ((strncmp(current, "@reply ", 7) == 0 && (len = 7)) || (strncmp(current, "@question ", 10) == 0 && (len = 10))) { 00152 if (message) { 00153 reply = (struct_dialog_reply *)calloc(1, sizeof(struct_dialog_reply)); 00154 reply->type = (len == 7 ? rt_reply : rt_question); 00155 cp = strchr(current+len, ' '); 00156 if (cp) { 00157 *cp = '\0'; 00158 reply->reply = strdup(current+len); 00159 reply->message = strdup(cp+1); 00160 } else { 00161 reply->reply = strdup(current+len); 00162 reply->message = strdup(reply->reply); 00163 LOG(llevDebug, "Warning: @reply/@question without message for %s!\n", op->name); 00164 } 00165 reply->next = message->replies; 00166 message->replies = reply; 00167 00168 reply = (struct_dialog_reply *)calloc(1, sizeof(struct_dialog_reply)); 00169 reply->reply = strdup(message->replies->reply); 00170 reply->message = strdup(message->replies->message); 00171 reply->type = message->replies->type; 00172 reply->next = op->dialog_information->all_replies; 00173 op->dialog_information->all_replies = reply; 00174 } else 00175 LOG(llevDebug, "Warning: @reply not in @match block for %s!\n", op->name); 00176 } else if (message) { 00177 /* Needed to set initial \0 */ 00178 int wasnull = FALSE; 00179 tmplen += strlen(current)+2; 00180 if (!tmp) 00181 wasnull = TRUE; 00182 tmp = realloc(tmp, tmplen*sizeof(char)); 00183 if (!tmp) 00184 fatal(OUT_OF_MEMORY); 00185 if (wasnull) 00186 tmp[0] = 0; 00187 strncat(tmp, current, tmplen-strlen(tmp)-1); 00188 strncat(tmp, "\n", tmplen-strlen(tmp)-1); 00189 } 00190 current = strtok_r(NULL, "\n", &save); 00191 } 00192 00193 if (message) { 00194 if (!tmp) 00195 message->message = strdup(""); 00196 else 00197 message->message = tmp; 00198 tmp = NULL; 00199 tmplen = 0; 00200 } 00201 00202 free(msg); 00203 } 00204 00214 int get_dialog_message(object *op, const char *text, struct_dialog_message **message, struct_dialog_reply **reply) { 00215 if (!QUERY_FLAG(op, FLAG_DIALOG_PARSED)) 00216 parse_dialog_information(op); 00217 00218 for (*message = op->dialog_information->all_messages; *message; *message = (*message)->next) { 00219 if (matches((*message)->match, text)) { 00220 break; 00221 } 00222 } 00223 if (!*message) 00224 return 0; 00225 00226 for (*reply = op->dialog_information->all_replies; *reply; *reply = (*reply)->next) { 00227 if (strcmp((*reply)->reply, text) == 0) 00228 break; 00229 } 00230 00231 return 1; 00232 }