📄 text.c
字号:
/* X-Chat * Copyright (C) 1998 Peter Zelezny. * * This program 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. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA */#include <stdlib.h>#include <stdio.h>#include <string.h>#include <unistd.h>#include <ctype.h>#include <time.h>#include <sys/types.h>#include <fcntl.h>#include <sys/stat.h>#include "xchat.h"#include "cfgfiles.h"#include "plugin.h"#include "fe.h"#include "util.h"#include "outbound.h"#include "perlc.h"#include "xchatc.h"#include "text.h"#ifdef USE_HEBREWstatic inline int iswhitespace(const char ch){ return (ch == ' ' || ch == 8);}static inline int isheb(const char ch){ return (((unsigned char)ch) >= 0xE0 && ((unsigned char)ch) <= 0xFA);}static inline int iseng(const char ch){ return ((ch >= 'A' && ch <= 'z') || (ch >= 'a' && ch <= 'z'));}/* this is already in ctype.h *//*static inline int isdigit(const char ch){ return (ch >= '0' && ch <= '9');}*/static char *strhebpatch(char *dest, const char *src){ short int mode = 0, imode; const char *hmark = NULL, *lmark, *nmark, *nlmark; char ch; if (!dest || !src) return NULL; for (;;) { if (mode == 0) { if (isheb(*src)) { hmark = src; mode = 1; } else *dest++ = *src; } else if (mode == 1) { if (*src == 0 || iseng(*src)) { lmark = src-1; while (!isheb(*lmark)) lmark--; src = lmark; imode = 0; nmark = NULL; while (lmark >= hmark) { ch = *lmark; if (imode == 0) switch (ch) { case '(': ch = ')'; break; case ')': ch = '('; break; case '{': ch = '}'; break; case '}': ch = '{'; break; case '[': ch = ']'; break; case ']': ch = '['; break; } if (imode == 0) { if (isdigit(ch)) { imode = 1; nmark = lmark; } else *dest++ = ch; } else if (imode == 1 && (isheb(ch) || iswhitespace(ch))) { nlmark = lmark+1; while (nlmark <= nmark) *dest++ = *nlmark++; imode = 0; lmark++; } lmark--; } hmark = NULL; mode = 0; } } if (!*src++) break; } return dest;}#endif /* !USE_HEBREW */voidPrintText (struct session *sess, unsigned char *text){ if (!sess) { if (!sess_list) return; sess = (struct session *) sess_list->data; } if (sess->logfd != -1 && prefs.logging) { time_t timval = time (0); char *temp = strip_color (text); char *tim = malloc (32); strftime (tim, 32, prefs.timestamp_log_format, localtime (&timval)); if (prefs.timestamp || prefs.timestamp_logs) write (sess->logfd, tim, strlen(tim)); write (sess->logfd, temp, strlen (temp)); free (temp); free (tim); }#ifdef USE_HEBREW if (prefs.hebrew) { const char *orgtext = NULL; if (text) { orgtext = text; text = strdup(text); strhebpatch (text, orgtext); } fe_print_text (sess, text); if (orgtext) free(text); } else {#endif fe_print_text (sess, text);#ifdef USE_HEBREW }#endif}voidend_logging (int fd){ char obuf[512]; time_t currenttime; currenttime = time (NULL); write (fd, obuf, snprintf (obuf, 510, _("**** ENDING LOGGING AT %s\n"), ctime (¤ttime))); close (fd);}static intopen_log_file (char *servname, char *channame){ char buf[512], fn[256]; char *dir, *sep; int fd, pathlen=510, c=0; time_t currenttime; if (!strcasecmp (channame, servname)) { channame = strdup ("server"); } else { channame = strdup (channame); tolowerStr (channame);#ifdef WIN32 /* win32 can't handle filenames with the '|' character */ dir = channame; while (*dir) { if (*dir == '|') *dir = '_'; dir++; }#endif } snprintf (buf, 510, "%s/xchatlogs", get_xdir ()); if (access (buf, F_OK) != 0)#ifdef WIN32 mkdir (buf);#else mkdir (buf, S_IRUSR | S_IWUSR | S_IXUSR);#endif auto_insert (fn, prefs.logmask, NULL, NULL, "", channame, "", "", "", servname); snprintf (buf, 510, "%s/xchatlogs/%s", get_xdir (), fn); /* The following code handles subdirectories in logpath and creates * them, if they don't exist. Useful with logmasks like "%c/%y.log" in * ~/.xchat/xchat.conf. * -- patch by tvk <tvk@von-koch.com> */ if (access (buf, F_OK) != 0) { snprintf (buf, 510, "%s/xchatlogs/", get_xdir ()); pathlen -= strlen(buf); /* how many sub-directories do we have? */ sep = fn; while (*sep++) if (*sep=='/') c++; if (c) { /* create each sub-directory */ sep = strdup(fn); dir = strtok(sep, "/"); while (c-- && dir != NULL) { strncat (buf, dir, pathlen); strcat (buf, "/"); pathlen -= strlen(dir); if (access (buf, F_OK) != 0)#ifdef WIN32 mkdir (buf);#else mkdir (buf, S_IRUSR | S_IWUSR | S_IXUSR);#endif dir = strtok(NULL, "/"); } /* append the filename */ strncat (buf, strrchr(fn, '/')+1, pathlen); free (sep); } else { strncat (buf, fn, pathlen); } } free (channame); fd = open (buf, O_CREAT | O_APPEND | O_WRONLY | OFLAGS, 0644); if (fd < 0) return -1; currenttime = time (NULL); write (fd, buf, snprintf (buf, 510, _("**** BEGIN LOGGING AT %s\n"), ctime (¤ttime))); return fd;}voidsetup_logging (struct session *sess){ if (sess->logfd != -1) end_logging (sess->logfd); sess->logfd = open_log_file (sess->server->servername, sess->channel);}/* Print Events stuff here --AGL *//* Consider the following a NOTES file: The main upshot of this is: * Plugins and Perl scripts (when I get round to signaling perl.c) can intercept text events and do what they like * The default text engine can be config'ed By default it should appear *exactly* the same (I'm working hard not to change the default style) but if you go into Settings->Edit Event Texts you can change the text's. The format is thus: The normal %Cx (color) and %B (bold) etc work $x is replaced with the data in var x (e.g. $1 is often the nick) $axxx is replace with a single byte of value xxx (in base 10) AGL (990507) *//* These lists are thus: pntevts_text[] are the strings the user sees (WITH %x etc) pntevts[] are the data strings with \000 etc evtnames[] are the names of the events *//* To add a new event: Think up a name (like JOIN) Make up a pevt_name_help struct (with a NULL at the end) add a struct to the end of te with, {"Name", help_struct, "Default text", num_of_args, NULL} Open up plugin.h add one to NUM_XP add a #define XP_TE_NAME with a value of +1 on the last XP_ *//* As of 990528 this code is in BETA --AGL *//* Internals: On startup ~/.xchat/printevents.conf is loaded if it doesn't exist the defaults are loaded. Any missing events are filled from defaults. Each event is parsed by pevt_build_string and a binary output is produced which looks like: (byte) value: 0 = { (int) numbers of bytes (char []) that number of byte to be memcpy'ed into the buffer } 1 = (byte) number of varable to insert 2 = end of buffer Each XP_TE_* signal is hard coded to call textsignal_handler which calls display_event which decodes the data This means that this system *should be faster* than snprintf because it always 'knows' that format of the string (basically is preparses much of the work) --AGL */char **pntevts_text;char **pntevts;static char *pevt_join_help[] = { N_("The nick of the joining person"), N_("The channel being joined"), N_("The host of the person"), NULL};static char *pevt_chanaction_help[] = { N_("Nickname"), N_("The action"), NULL};static char *pevt_chanmsg_help[] = { N_("Nickname"), N_("The text"), N_("Mode char"), NULL};static char *pevt_privmsg_help[] = { N_("Nickname"), N_("The message"), NULL};static char *pevt_changenick_help[] = { N_("Old nickname"), N_("New nickname"), NULL};static char *pevt_newtopic_help[] = { N_("Nick of person who changed the topic"), N_("Topic"), N_("Channel"), NULL};static char *pevt_topic_help[] = { N_("Channel"), N_("Topic"), NULL};static char *pevt_kick_help[] = { N_("The nickname of the kicker"), N_("The person being kicked"), N_("The channel"), N_("The reason"), NULL};static char *pevt_part_help[] = { N_("The nick of the person leaving"), N_("The host of the person"), N_("The channel"), NULL};static char *pevt_chandate_help[] = { N_("The channel"), N_("The time"), NULL};static char *pevt_topicdate_help[] = { N_("The channel"), N_("The creator"), N_("The time"), NULL};static char *pevt_quit_help[] = { N_("Nick"), N_("Reason"), N_("Host"), NULL};static char *pevt_pingrep_help[] = { N_("Who it's from"), N_("The time in x.x format (see below)"), NULL};static char *pevt_notice_help[] = { N_("Who it's from"), N_("The message"), NULL};static char *pevt_channotice_help[] = { N_("Who it's from"), N_("The Channel it's going to"), N_("The message"), NULL};static char *pevt_dprivmsg_help[] = { N_("Nickname"), N_("The message"), NULL};static char *pevt_uchangenick_help[] = { N_("Old nickname"), N_("New nickname"), NULL};static char *pevt_ukick_help[] = { N_("The person being kicked"), N_("The channel"), N_("The nickname of the kicker"), N_("The reason"), NULL};static char *pevt_partreason_help[] = { N_("The nick of the person leaving"), N_("The host of the person"), N_("The channel"), N_("The reason"), NULL};static char *pevt_ctcpsnd_help[] = { N_("The sound"), N_("The nick of the person"), NULL};static char *pevt_ctcpgen_help[] = { N_("The CTCP event"), N_("The nick of the person"), NULL};static char *pevt_ctcpgenc_help[] = { N_("The CTCP event"), N_("The nick of the person"), N_("The Channel it's going to"), NULL};static char *pevt_chansetkey_help[] = { N_("The nick of the person who set the key"), N_("The key"), NULL};static char *pevt_chansetlimit_help[] = { N_("The nick of the person who set the limit"), N_("The limit"), NULL};static char *pevt_chanop_help[] = { N_("The nick of the person who has been op'ed"), N_("The nick of the person of did the op'ing"), NULL};static char *pevt_chanhop_help[] = { N_("The nick of the person who has been halfop'ed"), N_("The nick of the person of did the halfop'ing"), NULL};static char *pevt_chanvoice_help[] = { N_("The nick of the person who has been voice'ed"), N_("The nick of the person of did the voice'ing"), NULL};static char *pevt_chanban_help[] = { N_("The nick of the person who did the banning"), N_("The ban mask"), NULL};static char *pevt_chanrmkey_help[] = { N_("The nick who removed the key"), NULL};static char *pevt_chanrmlimit_help[] = { N_("The nick who removed the limit"), NULL};static char *pevt_chandeop_help[] = { N_("The nick of the person of did the deop'ing"), N_("The nick of the person who has been deop'ed"), NULL};static char *pevt_chandehop_help[] = { N_("The nick of the person of did the dehalfop'ing"), N_("The nick of the person who has been dehalfop'ed"), NULL};static char *pevt_chandevoice_help[] = { N_("The nick of the person of did the devoice'ing"), N_("The nick of the person who has been devoice'ed"), NULL};static char *pevt_chanunban_help[] = { N_("The nick of the person of did the unban'ing"), N_("The ban mask"), NULL};static char *pevt_chanexempt_help[] = { N_("The nick of the person who did the exempt"), N_("The exempt mask"), NULL};static char *pevt_chanrmexempt_help[] = { N_("The nick of the person removed the exempt"), N_("The exempt mask"), NULL};static char *pevt_chaninvite_help[] = { N_("The nick of the person who did the invite"), N_("The invite mask"), NULL};static char *pevt_chanrminvite_help[] = { N_("The nick of the person removed the invite"), N_("The invite mask"), NULL};static char *pevt_chanmodegen_help[] = { N_("The nick of the person setting the mode"), N_("The mode's sign (+/-)"), N_("The mode letter"), N_("The channel it's being set on"), NULL};
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -