blender/extern/verse/dist/vs_node_text.c
2006-10-02 13:29:17 +00:00

275 lines
7.6 KiB
C

/*
**
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "v_cmd_gen.h"
#if !defined V_GENERATE_FUNC_MODE
#include "verse.h"
#include "vs_server.h"
#define VS_TEXT_CHUNK_SIZE 4096
typedef struct {
char name[16];
char *text;
size_t length;
size_t allocated;
VSSubscriptionList *subscribers;
} VSTextBuffer;
typedef struct {
VSNodeHead head;
char language[512];
VSTextBuffer *buffer;
unsigned int buffer_count;
} VSNodeText;
VSNodeText * vs_t_create_node(unsigned int owner)
{
VSNodeText *node;
char name[48];
unsigned int i;
node = malloc(sizeof *node);
vs_add_new_node(&node->head, V_NT_TEXT);
sprintf(name, "Text_Node_%u", node->head.id);
create_node_head(&node->head, name, owner);
node->language[0] = 0;
node->buffer_count = 16;
node->buffer = malloc((sizeof *node->buffer) * node->buffer_count);
for(i = 0; i < node->buffer_count; i++)
node->buffer[i].name[0] = 0;
return node;
}
void vs_t_destroy_node(VSNodeText *node)
{
unsigned int i;
destroy_node_head(&node->head);
for(i = 0; i < node->buffer_count; i++)
{
if(node->buffer[i].name[0] != 0)
{
free(node->buffer[i].text);
vs_destroy_subscription_list(node->buffer[i].subscribers);
}
}
free(node->buffer);
free(node);
}
void vs_t_subscribe(VSNodeText *node)
{
unsigned int i;
verse_send_t_language_set(node->head.id, node->language);
for(i = 0; i < node->buffer_count; i++)
if(node->buffer[i].name[0] != 0)
verse_send_t_buffer_create(node->head.id, i, node->buffer[i].name);
}
void vs_t_unsubscribe(VSNodeText *node)
{
unsigned int i;
for(i = 0; i < node->buffer_count; i++)
if(node->buffer[i].name[0] != 0)
vs_remove_subscriptor(node->buffer[i].subscribers);
}
static void callback_send_t_language_set(void *user, VNodeID node_id, char *language)
{
VSNodeText *node;
unsigned int i, count;
node = (VSNodeText *)vs_get_node(node_id, V_NT_TEXT);
if(node == NULL)
return;
for(i = 0; i < 511 && language[i]; i++)
node->language[i] = language[i];
node->language[i] = 0;
count = vs_get_subscript_count(node->head.subscribers);
for(i = 0; i < count; i++)
{
vs_set_subscript_session(node->head.subscribers, i);
verse_send_t_language_set(node_id, language);
}
vs_reset_subscript_session();
}
static void callback_send_t_buffer_create(void *user, VNodeID node_id, VBufferID buffer_id, const char *name)
{
VSNodeText *node;
unsigned int i, count;
node = (VSNodeText *)vs_get_node(node_id, V_NT_TEXT);
if(node == NULL)
return;
if(buffer_id >= node->buffer_count || node->buffer[buffer_id].name[0] != 0)
{
for(buffer_id = 0; buffer_id < node->buffer_count && node->buffer[buffer_id].name[0] != 0; buffer_id++)
;
if(buffer_id == node->buffer_count)
{
node->buffer = realloc(node->buffer, (sizeof *node->buffer) * node->buffer_count);
for(i = node->buffer_count; i < node->buffer_count + 16; i++)
node->buffer[i].name[0] = 0;
node->buffer_count = i;
}
}
if(node->buffer[buffer_id].name[0] == 0)
{
node->buffer[buffer_id].allocated = VS_TEXT_CHUNK_SIZE;
node->buffer[buffer_id].text = malloc(node->buffer[buffer_id].allocated);
node->buffer[buffer_id].length = 0;
node->buffer[buffer_id].subscribers = vs_create_subscription_list();
}
for(i = 0; i < 15 && name[i] != 0; i++)
node->buffer[buffer_id].name[i] = name[i];
node->buffer[buffer_id].name[i] = 0;
count = vs_get_subscript_count(node->head.subscribers);
for(i = 0; i < count; i++)
{
vs_set_subscript_session(node->head.subscribers, i);
verse_send_t_buffer_create(node_id, buffer_id, name);
}
vs_reset_subscript_session();
}
void callback_send_t_buffer_destroy(void *user, VNodeID node_id, VBufferID buffer_id)
{
VSNodeText *node;
unsigned int i, count;
node = (VSNodeText *)vs_get_node(node_id, V_NT_TEXT);
if(node == NULL)
return;
if(buffer_id >= node->buffer_count || node->buffer[buffer_id].name[0] == 0)
return;
node->buffer[buffer_id].name[0] = 0;
free(node->buffer[buffer_id].text);
vs_destroy_subscription_list(node->buffer[buffer_id].subscribers);
count = vs_get_subscript_count(node->head.subscribers);
for(i = 0; i < count; i++)
{
vs_set_subscript_session(node->head.subscribers, i);
verse_send_t_buffer_destroy(node_id, buffer_id);
}
vs_reset_subscript_session();
}
static void callback_send_t_buffer_subscribe(void *user, VNodeID node_id, VBufferID buffer_id)
{
VSNodeText *node;
unsigned int i;
node = (VSNodeText *)vs_get_node(node_id, V_NT_TEXT);
if(node == NULL)
return;
if(buffer_id >= node->buffer_count || node->buffer[buffer_id].name[0] == 0)
return;
if(vs_add_new_subscriptor(node->buffer[buffer_id].subscribers) == 0)
return;
for(i = 0; i < node->buffer[buffer_id].length; i += VN_T_MAX_TEXT_CMD_SIZE)
{
if(i + VN_T_MAX_TEXT_CMD_SIZE > node->buffer[buffer_id].length)
verse_send_t_text_set(node_id, buffer_id, i, node->buffer[buffer_id].length - i, &node->buffer[buffer_id].text[i]);
else
verse_send_t_text_set(node_id, buffer_id, i, VN_T_MAX_TEXT_CMD_SIZE, &node->buffer[buffer_id].text[i]);
}
}
static void callback_send_t_buffer_unsubscribe(void *user, VNodeID node_id, VBufferID buffer_id)
{
VSNodeText *node;
node = (VSNodeText *)vs_get_node(node_id, V_NT_TEXT);
if(node == NULL)
return;
if(buffer_id >= node->buffer_count || node->buffer[buffer_id].name[0] == 0)
return;
vs_remove_subscriptor(node->buffer[buffer_id].subscribers);
}
static void callback_send_t_text_set(void *user, VNodeID node_id, VBufferID buffer_id, uint32 pos, uint32 length, const char *text)
{
VSNodeText *node;
VSTextBuffer *tb;
unsigned int i, count, text_length;
char *buf;
node = (VSNodeText *) vs_get_node(node_id, V_NT_TEXT);
if(node == NULL)
return;
if(buffer_id >= node->buffer_count || node->buffer[buffer_id].name[0] == 0)
return;
tb = &node->buffer[buffer_id];
text_length = strlen(text);
/* Clamp position and length of deleted region. */
if(pos > tb->length)
pos = tb->length;
if(pos + length > tb->length)
length = tb->length - pos;
buf = tb->text;
if(tb->length + text_length - length > tb->allocated)
{
buf = realloc(buf, tb->length + text_length - length + VS_TEXT_CHUNK_SIZE);
tb->allocated = tb->length + text_length - length + VS_TEXT_CHUNK_SIZE;
}
if(text_length < length) /* Insert smaller than delete? */
{
memmove(buf + pos + text_length, buf + pos + length, tb->length - (pos + length));
memcpy(buf + pos, text, text_length);
}
else /* Insert is larger than delete. */
{
memmove(buf + pos + text_length, buf + pos + length, tb->length - pos);
memcpy(buf + pos, text, text_length);
}
tb->length += (int) text_length - length;
buf[tb->length] = '\0';
/* Buffer very much larger than content? Then shrink it. */
if(tb->allocated > VS_TEXT_CHUNK_SIZE * 8 && tb->allocated * 2 > tb->length)
{
buf = realloc(buf, tb->length + VS_TEXT_CHUNK_SIZE);
tb->allocated = tb->length + VS_TEXT_CHUNK_SIZE;
}
tb->text = buf;
count = vs_get_subscript_count(tb->subscribers);
for(i = 0; i < count; i++)
{
vs_set_subscript_session(tb->subscribers, i);
verse_send_t_text_set(node_id, buffer_id, pos, length, text);
}
vs_reset_subscript_session();
}
void vs_t_callback_init(void)
{
verse_callback_set(verse_send_t_language_set, callback_send_t_language_set, NULL);
verse_callback_set(verse_send_t_buffer_create, callback_send_t_buffer_create, NULL);
verse_callback_set(verse_send_t_buffer_destroy, callback_send_t_buffer_destroy, NULL);
verse_callback_set(verse_send_t_buffer_subscribe, callback_send_t_buffer_subscribe, NULL);
verse_callback_set(verse_send_t_buffer_unsubscribe, callback_send_t_buffer_unsubscribe, NULL);
verse_callback_set(verse_send_t_text_set, callback_send_t_text_set, NULL);
}
#endif