]> jfr.im git - irc/evilnet/x3.git/blobdiff - src/helpfile.c
Changed/improved 'silent' gline support
[irc/evilnet/x3.git] / src / helpfile.c
index a08c7b7316f0a7abcbb3d8bb1014deb61fa25e91..31aa342cf282be3df369914a95c6d8ebffadfbe8 100644 (file)
@@ -1,9 +1,9 @@
 /* helpfile.c - Help file loading and display
  * Copyright 2000-2004 srvx Development Team
  *
- * This file is part of srvx.
+ * This file is part of x3.
  *
- * srvx is free software; you can redistribute it and/or modify
+ * x3 is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License as published by
  * the Free Software Foundation; either version 2 of the License, or
  * (at your option) any later version.
@@ -23,6 +23,7 @@
 #include "log.h"
 #include "modcmd.h"
 #include "nickserv.h"
+#include "spamserv.h"
 
 #if defined(HAVE_DIRENT_H)
 #include <dirent.h>
@@ -41,7 +42,7 @@ static const struct message_entry msgtab[] = {
 #define DEFAULT_LINE_SIZE      MAX_LINE_SIZE
 #define DEFAULT_TABLE_SIZE      80
 
-extern struct userNode *global, *chanserv, *opserv, *nickserv;
+extern struct userNode *global, *chanserv, *opserv, *nickserv, *spamserv;
 struct userNode *message_dest;
 struct userNode *message_source;
 struct language *lang_C;
@@ -171,8 +172,10 @@ static struct language *language_read(const char *name)
 
     /* Open the directory stream; if we can't, fail. */
     snprintf(filename, sizeof(filename), "languages/%s", name);
-    if (!(dir = opendir(filename)))
+    if (!(dir = opendir(filename))) {
+        log_module(MAIN_LOG, LOG_ERROR, "Unable to open language directory languages/%s: %s", name, strerror(errno));
         return NULL;
+    }
     if (!(lang = dict_find(languages, name, NULL)))
         lang = language_alloc(name);
 
@@ -222,28 +225,25 @@ static struct language *language_read(const char *name)
 
 static void language_read_list(void)
 {
+    struct stat sbuf;
     struct dirent *dirent;
     DIR *dir;
+    char namebuf[MAXLEN];
 
     if (!(dir = opendir("languages")))
         return;
     while ((dirent = readdir(dir))) {
         if (dirent->d_name[0] == '.')
             continue;
-#ifdef HAVE_DIRENT_D_TYPE
-        if (dirent->d_type != DT_DIR)
+        snprintf(namebuf, sizeof(namebuf), "languages/%s", dirent->d_name);
+        if (stat(namebuf, &sbuf) < 0) {
+            log_module(MAIN_LOG, LOG_INFO, "Skipping language entry '%s' (unable to stat).", dirent->d_name);
+            continue;
+        }
+        if (!S_ISDIR(sbuf.st_mode)) {
+            log_module(MAIN_LOG, LOG_INFO, "Skipping language entry '%s' (not directory).", dirent->d_name);
             continue;
-#else
-        {
-            char namebuf[MAXLEN];
-            struct stat sbuf;
-            snprintf(namebuf, sizeof(namebuf), "languages/%s", dirent->d_name);
-            if (stat(namebuf, &sbuf) < 0)
-                continue;
-            if (!S_ISDIR(sbuf.st_mode))
-                continue;
         }
-#endif
         language_alloc(dirent->d_name);
     }
     closedir(dir);
@@ -261,11 +261,22 @@ const char *language_find_message(struct language *lang, const char *msgid) {
     return NULL;
 }
 
+int strlen_vis(char *str)
+{
+    int count;
+    for(count=0;*str;str++)
+        if(!iscntrl(*str))
+            count++;
+    return count;
+}
+
 void
 table_send(struct userNode *from, const char *to, unsigned int size, irc_send_func irc_send, struct helpfile_table table) {
     unsigned int ii, jj, len, nreps, reps, tot_width, pos, spaces, *max_width;
     char line[MAX_LINE_SIZE+1];
     struct handle_info *hi;
+    char *sepstr = NULL;
+    int sepsize = 0;
 
     if (IsChannelName(to) || *to == '$') {
         message_dest = NULL;
@@ -334,12 +345,14 @@ table_send(struct userNode *from, const char *to, unsigned int size, irc_send_fu
         for (pos=ii=0; ii<((table.flags & TABLE_REPEAT_HEADERS)?nreps:1); ii++) {
             for (jj=0; 1; ) {
                 len = strlen(table.contents[0][jj]);
+                //line[pos++] = '\02'; /* bold header */
                 spaces = max_width[jj] - len;
                 if (table.flags & TABLE_PAD_LEFT)
                     while (spaces--)
                         line[pos++] = ' ';
                 memcpy(line+pos, table.contents[0][jj], len);
                 pos += len;
+                //line[pos++] = '\02'; /* end bold header */
                 if (++jj == table.width)
                     break;
                 if (!(table.flags & TABLE_PAD_LEFT))
@@ -349,7 +362,15 @@ table_send(struct userNode *from, const char *to, unsigned int size, irc_send_fu
             }
         }
         line[pos] = 0;
-        irc_send(from, to, line);
+        sepsize = strlen_vis(line);
+        sepstr = malloc(sepsize + 1);
+        memset(sepstr, '-', sepsize);
+        sepstr[sepsize] = 0;
+        if(hi && hi->userlist_style != HI_STYLE_CLEAN)
+            irc_send(from, to, sepstr); /* ----------------- */
+        irc_send(from, to, line);   /* alpha  beta   roe */
+        if(hi && hi->userlist_style != HI_STYLE_CLEAN)
+            irc_send(from, to, sepstr); /* ----------------- */
         ii = 1;
     }
     /* Send the table. */
@@ -376,6 +397,20 @@ table_send(struct userNode *from, const char *to, unsigned int size, irc_send_fu
             line[pos++] = ' ';
         }
     }
+    if (!(table.flags & TABLE_NO_HEADERS)) {
+        /* Send end bar & free its memory */
+        if(sepsize > 5)
+        {
+           sepstr[sepsize/2-1] = 'E';
+           sepstr[sepsize/2] = 'n';
+           sepstr[sepsize/2+1]= 'd';
+        }
+
+        if(hi && hi->userlist_style != HI_STYLE_CLEAN)
+            irc_send(from, to, sepstr);
+        free(sepstr);
+    }
+
     if (!(table.flags & TABLE_NO_FREE)) {
         /* Deallocate table memory (but not the string memory). */
         for (ii=0; ii<table.length; ii++)
@@ -407,7 +442,8 @@ vsend_message(const char *dest, struct userNode *src, struct handle_info *handle
 #endif
     }
     message_source = src;
-    if (!(msg_type & 4) && !(format = handle_find_message(handle, format)))
+    if (!(msg_type & MSG_TYPE_NOXLATE)
+        && !(format = handle_find_message(handle, format)))
         return 0;
     /* fill in a buffer with the string */
     input.used = 0;
@@ -424,7 +460,7 @@ vsend_message(const char *dest, struct userNode *src, struct handle_info *handle
         size = sizeof(line);
         use_color = 1;
     }
-    if (!size)
+    if (!size || !(msg_type & MSG_TYPE_MULTILINE))
         size = DEFAULT_LINE_SIZE;
     switch (msg_type & 3) {
         case 0:
@@ -525,13 +561,27 @@ vsend_message(const char *dest, struct userNode *src, struct handle_info *handle
        case 'N':
             value = nickserv ? nickserv->nick : "NickServ";
             break;
+        case 'X':
+            value = spamserv ? spamserv->nick : "SpamServ";
+            break;
         case 's':
             value = self->name;
             break;
        case 'H':
            value = handle ? handle->handle : "Account";
            break;
-#define SEND_LINE() do { line[pos] = 0; if (pos > 0) irc_send(src, dest, line); chars_sent += pos; pos = 0; newline_ipos = ipos; } while (0)
+#define SEND_LINE(TRUNCED) do { \
+    line[pos] = 0; \
+    if (pos > 0) { \
+        if (!(msg_type & MSG_TYPE_MULTILINE) && (pos > 1) && TRUNCED) \
+            line[pos-2] = line[pos-1] = '.'; \
+        irc_send(src, dest, line); \
+    } \
+    chars_sent += pos; \
+    pos = 0; \
+    newline_ipos = ipos; \
+    if (!(msg_type & MSG_TYPE_MULTILINE)) return chars_sent; \
+} while (0)
        /* Custom expansion handled by helpfile-specific function. */
        case '{':
        case '(': {
@@ -568,7 +618,7 @@ vsend_message(const char *dest, struct userNode *src, struct handle_info *handle
                 break;
             case HF_TABLE:
                 /* Must send current line, then emit table. */
-                SEND_LINE();
+                SEND_LINE(0);
                 table_send(src, (message_dest ? message_dest->nick : dest), 0, irc_send, exp.value.table);
                 value = "";
                 break;
@@ -606,7 +656,7 @@ vsend_message(const char *dest, struct userNode *src, struct handle_info *handle
                 /* word to send is too big to send now.. what to do? */
                 if (pos > 0) {
                     /* try to put it on a separate line */
-                    SEND_LINE();
+                    SEND_LINE(1);
                 } else {
                     /* already at start of line; only send part of it */
                     strncpy(line, value, avail);
@@ -619,7 +669,7 @@ vsend_message(const char *dest, struct userNode *src, struct handle_info *handle
             }
             /* if we're looking at a newline, send the accumulated text */
             if (*value == '\n') {
-                SEND_LINE();
+                SEND_LINE(0);
                 value++;
             }
         }
@@ -636,7 +686,7 @@ vsend_message(const char *dest, struct userNode *src, struct handle_info *handle
       send_line:
         expand_pos = pos;
         expand_ipos = ipos;
-        SEND_LINE();
+        SEND_LINE(0);
 #undef SEND_LINE
     }
     return chars_sent;
@@ -686,7 +736,7 @@ _send_help(struct userNode *dest, struct userNode *src, expand_func_t expand, co
 
     va_list ap;
     va_start(ap, format);
-    res = vsend_message(dest->nick, src, dest->handle_info, 4, expand, format, ap);
+    res = vsend_message(dest->nick, src, dest->handle_info, 12, expand, format, ap);
     va_end(ap);
     return res;
 }
@@ -698,6 +748,42 @@ send_help(struct userNode *dest, struct userNode *src, struct helpfile *hf, cons
     struct record_data *rec;
     struct language *curr;
 
+    if (!topic)
+        topic = "<index>";
+    if (!hf) {
+        _send_help(dest, src, NULL, "HFMSG_MISSING_HELPFILE");
+        return false;
+    }
+    for (curr = (dest->handle_info ? dest->handle_info->language : lang_C);
+         curr;
+         curr = curr->parent) {
+        lang_hf = dict_find(curr->helpfiles, hf->name, NULL);
+        if (!lang_hf)
+            continue;
+        rec = dict_find(lang_hf->db, topic, NULL);
+        if (rec && rec->type == RECDB_QSTRING) {
+            _send_help(dest, src, hf->expand, rec->d.qstring);
+            return true;
+        }
+    }
+    rec = dict_find(hf->db, "<missing>", NULL);
+    if (!rec)
+        return false;
+    if (rec->type != RECDB_QSTRING) { 
+        send_message(dest, src, "HFMSG_HELP_NOT_STRING");
+       return false; 
+    }
+    _send_help(dest, src, hf->expand, rec->d.qstring);
+    return true;
+}
+
+int
+send_help_brief(struct userNode *dest, struct userNode *src, struct helpfile *hf, const char *topic)
+{
+    struct helpfile *lang_hf;
+    struct record_data *rec;
+    struct language *curr;
+
     if (!topic)
         topic = "<index>";
     if (!hf) {
@@ -712,13 +798,24 @@ send_help(struct userNode *dest, struct userNode *src, struct helpfile *hf, cons
             continue;
         rec = dict_find(lang_hf->db, topic, NULL);
         if (rec && rec->type == RECDB_QSTRING)
-            return _send_help(dest, src, hf->expand, rec->d.qstring);
+        {
+            char* buf;
+            int res;
+
+            buf = malloc(strlen(rec->d.qstring) + 1);
+            strcpy(buf, rec->d.qstring);
+            *strchr(buf, '\n') = 0;
+
+            res = _send_help(dest, src, hf->expand, buf);
+            free(buf);
+            return res;
+        }
     }
     rec = dict_find(hf->db, "<missing>", NULL);
     if (!rec)
-        return send_message(dest, src, "MSG_TOPIC_UNKNOWN");
+        return 0; /* send_message(dest, src, "MSG_TOPIC_UNKNOWN"); */
     if (rec->type != RECDB_QSTRING)
-       return send_message(dest, src, "HFMSG_HELP_NOT_STRING");
+       return 0; /* send_message(dest, src, "HFMSG_HELP_NOT_STRING"); */
     return _send_help(dest, src, hf->expand, rec->d.qstring);
 }
 
@@ -794,7 +891,7 @@ helpfile_eval_identifier(const char *start, const char **end)
         *end = start + 5;
         return 0;
     } else {
-        log_module(MAIN_LOG, LOG_FATAL, "Unexpected helpfile identifier '%.*s'.", *end-start, start);
+        log_module(MAIN_LOG, LOG_FATAL, "Unexpected helpfile identifier '%.*s'.", (int)(*end-start), start);
         return -1;
     }
 }
@@ -826,7 +923,7 @@ helpfile_eval_atomicexpr(const char *start, const char **end)
     while (isspace(*sep) && (sep < *end))
         sep++;
     if ((sep == *end) || (sep[0] != ')')) {
-        log_module(MAIN_LOG, LOG_FATAL, "Expected close parenthesis at '%.*s'.", *end-sep, sep);
+        log_module(MAIN_LOG, LOG_FATAL, "Expected close parenthesis at '%.*s'.", (int)(*end-sep), sep);
         return -1;
     }
 
@@ -863,7 +960,7 @@ helpfile_eval_expr(const char *start, const char **end)
         sep += len;
     }
     if (op == OP_INVALID) {
-        log_module(MAIN_LOG, LOG_FATAL, "Unrecognized helpfile operator at '%.*s'.", *end-sep, sep);
+        log_module(MAIN_LOG, LOG_FATAL, "Unrecognized helpfile operator at '%.*s'.", (int)(*end-sep), sep);
         return -1;
     }
 
@@ -877,7 +974,7 @@ helpfile_eval_expr(const char *start, const char **end)
     while (isspace(*sep2) && (sep2 < *end))
         sep2++;
     if (sep2 != *end) {
-        log_module(MAIN_LOG, LOG_FATAL, "Trailing garbage in helpfile expression: '%.*s'.", *end-sep2, sep2);
+        log_module(MAIN_LOG, LOG_FATAL, "Trailing garbage in helpfile expression: '%.*s'.", (int)(*end-sep2), sep2);
         return -1;
     }
 
@@ -904,7 +1001,7 @@ helpfile_eval_condition(const char *start, const char **end)
     for (term = start; isalnum(*term) && (term < *end); ++term) ;
     if (term != start) {
         if ((term + 2 >= *end) || (term[0] != ':') || (term[1] != ' ')) {
-            log_module(MAIN_LOG, LOG_FATAL, "In helpfile condition '%.*s' expected prefix to end with ': '.", *end-start, start);
+            log_module(MAIN_LOG, LOG_FATAL, "In helpfile condition '%.*s' expected prefix to end with ': '.",(int)(*end-start), start);
             return -1;
         }
         start = term + 2;