diff options
author | Vadim Dashevskiy <watcherhd@gmail.com> | 2013-04-02 13:54:21 +0000 |
---|---|---|
committer | Vadim Dashevskiy <watcherhd@gmail.com> | 2013-04-02 13:54:21 +0000 |
commit | ff5a775b94465b30897964630af600fe5915fc51 (patch) | |
tree | f79e36c79faf7095ca6f02f6b7fea0f6e81bf085 /plugins/!NotAdopted/VypressChat/chanlist.c | |
parent | 8d3307adf7ba64b75fb4de363f873c97286b0e9b (diff) |
VypressChat added (not adopted)
git-svn-id: http://svn.miranda-ng.org/main/trunk@4285 1316c22d-e87f-b044-9b9b-93d7a3e3ba9c
Diffstat (limited to 'plugins/!NotAdopted/VypressChat/chanlist.c')
-rw-r--r-- | plugins/!NotAdopted/VypressChat/chanlist.c | 390 |
1 files changed, 390 insertions, 0 deletions
diff --git a/plugins/!NotAdopted/VypressChat/chanlist.c b/plugins/!NotAdopted/VypressChat/chanlist.c new file mode 100644 index 0000000000..6634afeba3 --- /dev/null +++ b/plugins/!NotAdopted/VypressChat/chanlist.c @@ -0,0 +1,390 @@ +/*
+ * Miranda-IM Vypress Chat/quickChat plugins
+ * Copyright (C) Saulius Menkevicius
+ *
+ * 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
+ *
+ * $Id: chanlist.c,v 1.10 2005/03/07 14:26:54 bobas Exp $
+ */
+
+#include "miranda.h"
+
+#include "main.h"
+#include "chanlist.h"
+
+/* internal routines
+ */
+
+/* chanlist_find_channel:
+ * Returns a pointer to channel in a channel list
+ * (or a NULL, if not found)
+ * *p_cl_len will be set to the length of channel list.
+ * *p_ch_len will be set to the length of a channel without the '#'.
+ */
+static const char *
+chanlist_find_channel(
+ const char * chanlist, const char * channel,
+ int * p_cl_len, int * p_ch_len)
+{
+ char * cl_channel;
+ int cl_len, ch_len;
+
+ if(!chanlist)
+ return NULL;
+
+ /* get chanlist and channel lengths */
+ cl_len = strlen(chanlist);
+ ASSERT_RETURNVALIFFAIL(cl_len >= 2 && chanlist[0]=='#', NULL);
+ if(p_cl_len)
+ *p_cl_len = cl_len;
+
+ ch_len = strlen(channel);
+ ASSERT_RETURNVALIFFAIL(ch_len!=0, NULL);
+ if(p_ch_len)
+ *p_ch_len = ch_len;
+
+ /* the list doesn't contain a channel if it's smaller than
+ * the channel itself
+ */
+ if(cl_len-1 < ch_len)
+ return NULL;
+
+ /* find the channel in the list */
+ cl_channel = strstr(chanlist, channel);
+
+ /* there must be a '#' before channel name */
+ if(cl_channel==NULL || *(cl_channel - 1) != '#')
+ return NULL;
+
+ /* and it must be last on the channel list, or end up with '#' */
+ if(cl_channel[ch_len]!='\0' && cl_channel[ch_len]!='#')
+ return NULL;
+
+ /* ok, the channel was found */
+ return cl_channel;
+}
+
+/* exported routines
+ */
+
+/* chanlist_is_valid:
+ * returns if the chanlist is in valid format
+ */
+int chanlist_is_valid(const char * chanlist, int no_empty_channels)
+{
+ int cl_len;
+
+ /* chanlist can be empty -- NULL */
+ if(chanlist==NULL)
+ return 1;
+
+ /* non-empty chanlist must be with length >= 0,
+ * and must begin with a '#'
+ */
+ cl_len = strlen(chanlist);
+ if(cl_len < 2 || chanlist[0]!='#')
+ return 0;
+
+ if(no_empty_channels) {
+ /* check that there are no 0-length channel names
+ * in the list
+ */
+ const char * prev = chanlist, * next;
+ do {
+ next = strchr(prev + 1, '#');
+ if(next && (next - prev) == 1)
+ return 0;
+
+ prev = next;
+ } while(next);
+ }
+
+ return 1; /* this chanlist is supposedly valid */
+}
+
+/* chanlist_add:
+ * Creates a channel list (if chanlist==NULL) with a new channel
+ * or add a new one to the end.
+ * Checks if the channel is already in the list.
+ * The result channel list string should look like:
+ * "#channel1#channel2...#channelN".
+ * An empty channel list is a (char*)NULL.
+ */
+char * chanlist_add(char * chanlist, const char * channel)
+{
+ char * new_chanlist;
+ int cl_len, ch_len;
+
+ ASSERT_RETURNVALIFFAIL(VALIDPTR(channel), chanlist);
+
+ if(chanlist_find_channel(chanlist, channel, NULL, NULL))
+ return chanlist;
+
+ /* the chanlist doesn't contain the new channel:
+ * append it to the end
+ */
+
+ ch_len = strlen(channel);
+ ASSERT_RETURNVALIFFAIL(ch_len!=0, chanlist);
+
+ if(chanlist) {
+ /* get the length of channel list, note that an empty chanlist
+ * MUST be (char*)NULL, and an non-empty chanlist must be at
+ * least 2 chars in length ("#a") and have '#' at the beginning
+ */
+ cl_len = strlen(chanlist);
+ ASSERT_RETURNVALIFFAIL(
+ cl_len >= 2 && chanlist[0]=='#', chanlist);
+ } else {
+ cl_len = 0;
+ }
+
+ /* allocate space for a previous channel list, plus a # character
+ * and new channel, and a terminator
+ */
+ new_chanlist = malloc((cl_len + ch_len + 1 + 1) * sizeof(char));
+ ASSERT_RETURNVALIFFAIL(new_chanlist!=NULL, chanlist);
+
+ if(chanlist) {
+ /* strcpy(new_chanlist, chanlist); */
+ memcpy(new_chanlist, chanlist, cl_len);
+ free(chanlist);
+ }
+
+ new_chanlist[cl_len] = '#'; /* strcat(new_chanlist, "#"); */
+
+ /* strcat(new_chanlist, channel); */
+ memcpy(new_chanlist + cl_len + 1, channel, ch_len + 1);
+
+ return new_chanlist;
+}
+
+/* chanlist_remove:
+ * Removes a channel from chanlist and frees the resulting
+ * chanlist, if it becomes empty (thus returning the (char*)NULL)
+ */
+char * chanlist_remove(char * chanlist, const char * channel)
+{
+ char * cl_channel;
+ int cl_len, ch_len;
+
+ ASSERT_RETURNVALIFFAIL(VALIDPTR(channel), chanlist);
+
+ if(chanlist==NULL)
+ return NULL;
+
+ cl_channel = (char*)chanlist_find_channel(
+ chanlist, channel, &cl_len, &ch_len);
+
+ if(cl_channel == NULL)
+ return chanlist;
+
+ /* check if we need to free the list, (if it was the only channel) */
+ if(cl_len == ch_len + 1) {
+ free(chanlist);
+ return NULL;
+ }
+
+ /* if the channel was the last on the list, we put a terminator '\0'
+ * and we're finished */
+ if((cl_channel - chanlist) + ch_len == cl_len) {
+ *(cl_channel - 1) = '\0'; /* put '\0' on channel's '#' char */
+ return chanlist;
+ }
+
+ /* we need to move channels after cl_channel in the chanlist
+ * to the place of cl_channel (including the '\0' terminator) */
+ memcpy(cl_channel, cl_channel + ch_len + 1,
+ cl_len - (cl_channel - chanlist) - ch_len);
+
+ return chanlist;
+}
+
+/* chanlist_shift:
+ * removes the first channel from the list and returns
+ * the chanlist without the channel
+ *
+ * params:
+ * @p_chanlist - chanlist to shift the channel off
+ * returns:
+ * NULL, if the chanlist is empty
+ * malloc'ed channel name shifted from the chanlist
+ */
+char * chanlist_shift(char ** p_chanlist)
+{
+ char * next, * new_chanlist, * channel;
+
+ /* check that the channel is valid */
+ ASSERT_RETURNVALIFFAIL(VALIDPTR(p_chanlist), NULL);
+ if(!chanlist_is_valid(*p_chanlist, 0))
+ return NULL;
+
+ /* check if chanlist is empty */
+ if(*p_chanlist==NULL) return NULL;
+
+ /* get pointer to the next channel in the list */
+ next = strchr(*p_chanlist + 1, '#');
+
+ /* make a copy of the rest as new chanlist */
+ new_chanlist = chanlist_copy(next);
+
+ /* finish channel name with a '\0' */
+ if(next) *next = '\0';
+ channel = *p_chanlist;
+ memmove(channel, channel + 1, strlen(channel));
+
+ *p_chanlist = new_chanlist;
+ return channel;
+}
+
+/* chanlist_merge:
+ * Merges two chanlists, the result adds to chanlist_dst
+ * and it is what returns.
+ *
+ * Note that chanlist_src might get modified in the process
+ * thus it is non-const, but it is kept unmodified after return.
+ */
+static int
+chanlist_merge_enum_fn(const char * channel, void * enum_data)
+{
+ char ** p_dst_chanlist = (char **)enum_data;
+
+ ASSERT_RETURNVALIFFAIL(VALIDPTR(channel), 0);
+ ASSERT_RETURNVALIFFAIL(VALIDPTR(p_dst_chanlist), 0);
+
+ *p_dst_chanlist = chanlist_add(*p_dst_chanlist, channel);
+
+ return 1; /* keep enumerating */
+}
+
+char * chanlist_merge(char * chanlist_dst, const char * chanlist_src)
+{
+ chanlist_enum(chanlist_src, chanlist_merge_enum_fn, &chanlist_dst);
+
+ return chanlist_dst;
+}
+
+/* chanlist_contains:
+ * Returns non-0, if the chanlist contains the specified channel.
+ */
+int chanlist_contains(const char * chanlist, const char * channel)
+{
+ ASSERT_RETURNVALIFFAIL(VALIDPTR(channel), 0);
+
+ return chanlist_find_channel(chanlist, channel, NULL, NULL) != NULL;
+}
+
+/* chanlist_enum:
+ * Enumerates chanlist.
+ * The enum function should return non-0 to keep enumeration going,
+ * or 0 to stop enumeration.
+ */
+void chanlist_enum(
+ const char * orig_chanlist, chanlist_enum_fn enum_fn,
+ void * enum_data)
+{
+ char * cl_channel, * cl_next_block;
+ int cl_len;
+ char * chanlist = chanlist_copy(orig_chanlist);
+
+ ASSERT_RETURNIFFAIL(enum_fn!=NULL);
+
+ /* do no enumeration if chanlist is empty */
+ if(chanlist == NULL)
+ return;
+
+ /* get chanlist length */
+ cl_len = strlen(chanlist);
+
+ /* the length must be at least 2 chars ("#a"), and begin with a '#' */
+ ASSERT_RETURNIFFAIL(cl_len >= 2 && chanlist[0]=='#');
+
+ /* ok, walk the channel list.. */
+ cl_channel = chanlist + 1;
+ do {
+ /* get address of the next channel's '#' character */
+ cl_next_block = strchr(cl_channel, '#');
+ if(cl_next_block) {
+ /* temporary add a terminator and invoke the callback */
+ *cl_next_block = '\0';
+ enum_fn(cl_channel, enum_data);
+
+ /* remove the terminator */
+ *cl_next_block = '#';
+ } else {
+ /* the channel is the last on the list: invoke cb */
+ enum_fn(cl_channel, enum_data);
+ }
+
+ /* skip to next channel */
+ if(cl_next_block)
+ cl_channel = cl_next_block + 1;
+ else cl_channel = NULL;
+
+ } while(cl_channel);
+
+ /* free the chanlist copy */
+ chanlist_free(chanlist);
+}
+
+/* chanlist_make_vqp_chanlist:
+ * allocates a vqp chanlist (the same as chanlist, only with '#' at the end)
+ * and always non-NULL
+ */
+char * chanlist_make_vqp_chanlist(const char * chanlist)
+{
+ int cl_len;
+ char * vqp_chanlist;
+
+ cl_len = chanlist ? strlen(chanlist): 0;
+
+ vqp_chanlist = malloc(cl_len + 2);
+ ASSERT_RETURNVALIFFAIL(VALIDPTR(vqp_chanlist), NULL);
+
+ if(chanlist)
+ memcpy(vqp_chanlist, chanlist, cl_len);
+
+ /* append the '#' and '\0' terminator at the end */
+ vqp_chanlist[cl_len] = '#';
+ vqp_chanlist[cl_len + 1] = '\0';
+
+ return vqp_chanlist;
+}
+
+/* chanlist_parse_vqp_chanlist:
+ * makes a chanlist from vqp chanlist format
+ */
+char * chanlist_parse_vqp_chanlist(const char * vqp_chanlist)
+{
+ int vqp_cl_len;
+ char * chanlist;
+
+ ASSERT_RETURNVALIFFAIL(VALIDPTR(vqp_chanlist), NULL);
+
+ vqp_cl_len = strlen(vqp_chanlist);
+ ASSERT_RETURNVALIFFAIL(vqp_cl_len != 0, NULL);
+
+ /* vqp_chanlist must begin and end with '#' */
+ ASSERT_RETURNVALIFFAIL(
+ vqp_chanlist[0]=='#' && vqp_chanlist[vqp_cl_len-1]=='#', NULL);
+
+ /* make the chanlist (copy everything, except the last '#') */
+ chanlist = malloc(vqp_cl_len);
+ memcpy(chanlist, vqp_chanlist, vqp_cl_len - 1);
+ chanlist[vqp_cl_len - 1] ='\0';
+
+ return chanlist;
+}
+
|