Logo Search packages:      
Sourcecode: blender version File versions  Download package

vs_node_text.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

Generated by  Doxygen 1.6.0   Back to index