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

viewerdnd.c

#include <stdio.h>
#include <string.h>
#include <gtk/gtk.h>

#include "../include/string.h"
#include "../include/strexp.h"

#include "guiutils.h"
#include "cdialog.h"

#include "editor.h"
#include "editordnd.h"
#include "editorop.h"
#include "viewer.h"
#include "viewerfio.h"
#include "viewerdnd.h"

#include "manedit.h"
#include "config.h"


/* DND data command string parsing */
void ViewerIndexCTreeDNDParseCmd(
      const gchar *string,
      viewer_struct **viewer_ptr,
      GtkCTreeNode ***branch, gint *total_branches
);

/* DND handling */
void ViewerIndexCTreeDNDDataRequestCB(
      GtkWidget *widget, GdkDragContext *dc,
      GtkSelectionData *selection_data, guint info, guint t,
      gpointer data
);
void ViewerViewTextDNDDataRecievedCB(
      GtkWidget *widget,
      GdkDragContext *dc,
      gint x, gint y,
      GtkSelectionData *selection_data,
      guint info, guint t,
      gpointer data
);
void ViewerDNDDataDeleteCB(
      GtkWidget *widget, GdkDragContext *dc, gpointer data
);


#define ATOI(s)         (((s) != NULL) ? atoi(s) : 0)
#define ATOL(s)         (((s) != NULL) ? atol(s) : 0)
#define ATOF(s)         (((s) != NULL) ? atof(s) : 0.0f)
#define STRDUP(s) (((s) != NULL) ? g_strdup(s) : NULL)

#define MAX(a,b)  (((a) > (b)) ? (a) : (b))
#define MIN(a,b)  (((a) < (b)) ? (a) : (b))
#define CLIP(a,l,h)     (MIN(MAX((a),(l)),(h)))
#define STRLEN(s) (((s) != NULL) ? strlen(s) : 0)
#define STRISEMPTY(s)   (((s) != NULL) ? (*(s) == '\0') : TRUE)


/*
 *      Parses the given string which should have been recieved as
 *      a DND command.
 *
 *    The only the returned array of branches should be deleted.
 */
void ViewerIndexCTreeDNDParseCmd(
      const gchar *string,
      viewer_struct **viewer_ptr,
      GtkCTreeNode ***branch, gint *total_branches
)
{
      guint32 addr_val;
      gint i, n, strc;
      gchar **strv;

      /* Reset returns */
      if(viewer_ptr != NULL)
          *viewer_ptr = NULL;
      if(branch != NULL)
          *branch = NULL;
      if(total_branches != NULL)
          *total_branches = 0;

      if(string == NULL)
          return;

      if(g_strcasepfx(string, "error"))
          return;

      /* Parse command, format is as follows:
       *
       * <viewer_ptr> <branch_ptr...>
       */
      strv = strexp(string, &strc);
      if(strv == NULL)
          return;

      /* Get viewer_ptr (format in hex with no "0x" prefix) */
      if(strc > 0)
          i = sscanf(strv[0], "%x", (guint32 *)&addr_val);
      else
          i = 0;
      if((i > 0) && (viewer_ptr != NULL))
          (*viewer_ptr) = (viewer_struct *)addr_val;

      /* Get list of branch pointers which should be branches
       * on the parsed viewer's index GtkCTree
       */
      if((branch != NULL) && (total_branches != NULL))
      {
          const gchar *s;

          /* Start at parsed argument number 1 */
          for(i = 1; i < strc; i++)
          {
            s = strv[i];
            if(s == NULL)
                continue;

            n = *total_branches;
            *total_branches = n + 1;
            *branch = (GtkCTreeNode **)realloc(
                *branch,
                (*total_branches) * sizeof(GtkCTreeNode *)
            );
            if(*branch == NULL)
            {
                *total_branches = 0;
                break;
            }
            else
            {
                i = sscanf(s, "%x", (guint32 *)&addr_val);
                if(i > 0)
                  (*branch)[n] = (GtkCTreeNode *)addr_val;
                else
                  (*branch)[n] = NULL;
            }
          }
      }

      /* Delete exploded strings */
      strlistfree(strv, strc);
}


/*
 *    Viewer index ctree data request callback.
 */
void ViewerIndexCTreeDNDDataRequestCB(
      GtkWidget *widget, GdkDragContext *dc,
      GtkSelectionData *selection_data, guint info, guint t,
      gpointer data
)
{
      gchar *buf;
      GtkCTreeNode *branch_ptr;
      viewer_struct *v = VIEWER(data);
      if((widget == NULL) || (v == NULL) || (dc == NULL))
          return;

      if(!v->initialized)
          return;

      if(widget != v->index_ctree)
      {
          g_printerr(
"ViewerIndexCTreeDNDDataRequestCB(): widget != v->index_ctree\n"
          );
          return;
      }

      /* Get selected branch on viewer's index GtkCTree
       *
       * Note currently we only allow one selected branch at a time
       */
      branch_ptr = v->selected_index_branch;

      /* No need to apply values to branch_ptr */

      /* Format buffer in the following format:
       *
       * <viewer_ptr> <branch_ptr...>
       */
      if(branch_ptr != NULL)
          buf = g_strdup_printf(
            "%.8x %.8x",
            (guint32)v,
            (guint32)branch_ptr
          );
      else
          buf = g_strdup_printf(
            "%.8x",
            (guint32)v
          );

      /* Send out data */
      gtk_selection_data_set(
          selection_data,
          GDK_SELECTION_TYPE_STRING,
          8,                  /* 8 bits per character */
          buf, strlen(buf)
      );

      g_free(buf);
}


/*
 *    Viewer view text widget drop recieved callback.
 */
void ViewerViewTextDNDDataRecievedCB(
      GtkWidget *widget, GdkDragContext *dc, gint x, gint y,
      GtkSelectionData *selection_data, guint info, guint t,
      gpointer data
)
{
      gboolean need_delete = FALSE;
      gint viewer_num;
      gboolean same;
      GtkWidget *source_widget;
      GtkEditable *editable;
      medit_core_struct *core_ptr;
      viewer_struct *v = VIEWER(data);
      if((widget == NULL) || (v == NULL) || (dc == NULL))
            return;

      if(!v->initialized)
          return;

      /* Important, check if we got data */
      if(selection_data == NULL)
          return;
      if(selection_data->length < 0)
          return;

      /* Source and target same? */
      source_widget = gtk_drag_get_source_widget(dc);
      same = ((source_widget == widget) ? TRUE : FALSE);

      /* Check if data needs to be deleted by testing if this
       * drag operation is not a copy.
       */
      if(dc->action != GDK_ACTION_COPY)
          need_delete = TRUE;

      /* Get viewer view text widget */
      editable = (GtkEditable *)v->view_text;

      /* Check if viewer view text widget matches the destination
       * widget. If it does not then set editable to NULL so no further
       * processing is done.
       */
      if((void *)editable != (void *)widget)
          editable = NULL;

      /* Get pointer to core structure */
      core_ptr = (medit_core_struct *)v->core_ptr;
      if(core_ptr == NULL)
          return;

      /* Get viewer number */
      for(viewer_num = 0; viewer_num < core_ptr->total_viewers; viewer_num++)
      {
          if(v == core_ptr->viewer[viewer_num])
            break;
      }
      if(viewer_num >= core_ptr->total_viewers)
          viewer_num = -1;


      if(editable != NULL)
      {
          /* Editor layout ctree branch node transfer command? */
          if(info == MEDIT_DND_TYPE_INFO_EDITOR_BRANCH_CMD)
          {
            gint i;
            editor_struct *src_editor = NULL;
            GtkCTreeNode **branch = NULL;
            gint total_branches = 0;
            gboolean    is_branch_file = FALSE,
                        is_branch_header = FALSE,
                        is_branch_section = FALSE;


            /* Parse command string */
            EditorDNDParseCmd(
                (const gchar *)selection_data->data,
                &src_editor,
                &branch, &total_branches
            );

            /* Is source editor valid? */
            if(src_editor != NULL)
            {
                editor_item_struct *item;

                /* Check what types of branch item data types we
                 * just got
                 */
                for(i = 0; i < total_branches; i++)
                {
                  item = EditorBranchGetData(
                      (GtkCTree *)src_editor->layout_ctree, branch[i]
                  );
                  if(item == NULL)
                      continue;

                  /* Check item type */
                  switch(item->type)
                  {
                    case EditorItemTypeFile:
                      is_branch_file = TRUE;
                      break;
            
                    case EditorItemTypeHeader:
                      is_branch_header = TRUE;
                      break;

                   case EditorItemTypeSection:  
                      is_branch_section = TRUE;
                      break;
                  }
                }   
                /* `No operation' check */
                if(same)
                {
                  /* No such check possible when droping to the
                   * view text widget on a viewer.
                   */
                }

                /* ************************************************ */
                /* Handle by branch item data type */
                /* File (which implies trunk)? */
                if(is_branch_file)
                {
                  /* Unset delete, we don't want to delete anything
                   * for this operation.
                   */
                  need_delete = FALSE;

                  /* Handle only the first branch */
                  if(total_branches > 0)
                  {
                      /* Call editor's preview procedure on source
                       * editor so that it first saves the loaded
                       * data before loading it into the viewer.
                       */
                      EditorDoPreview(
                        src_editor,
                        branch[0],
                        viewer_num
                      );
                  }
                }
                /* ************************************************ */
                /* Header or section? */
                else if(is_branch_header || is_branch_section)
                {
                  /* Unset delete, we don't want to delete anything
                   * for this operation.
                   */
                  need_delete = FALSE;

                  /* Handle only the first branch */
                  if(total_branches > 0)
                  {
                      GtkCTreeNode *trunk;


                      /* Get toplevel trunk branch for first
                       * transfered branch.
                       */
                      trunk = EditorItemGetToplevel(
                        src_editor, branch[0]
                      );

                      /* Call editor's preview procedure on source
                       * editor so that it first saves the loaded
                       * data before loading it into the viewer.
                       */
                      EditorDoPreview(
                        src_editor,
                        trunk,
                        viewer_num
                      );
                  }
                }
                /* ************************************************ */
                /* Add support for other types here */
            }

            /* Free only list of branches from source editor */
            g_free(branch);
            branch = NULL;
            total_branches = 0;
          }
          /* ******************************************************** */
          /* Viewer index ctree branch node transfer command? */
          else if(info == MEDIT_DND_TYPE_INFO_VIEWER_BRANCH_CMD)
          {
            viewer_struct *src_viewer = NULL;
            GtkCTreeNode **branch = NULL;
            gint total_branches = 0;


            /* Parse command string. Value of src_viewer points to
             * the source viewer and branch and total_branches are
             * the selected branch(es) on the source viewer's index
             * ctree.
             */   
            ViewerIndexCTreeDNDParseCmd(
                (const gchar *)selection_data->data,
                &src_viewer,
                &branch, &total_branches
            );

            /* Is source viewer valid? */
            if((src_viewer != NULL) ?
                (src_viewer->index_ctree != NULL) : FALSE
            )
            {
                GtkCTree *ctree = GTK_CTREE(src_viewer->index_ctree);
                viewer_index_item_struct *item;

                /* Handle only the first branch */
                if(total_branches > 0)
                {
                  /* Get index item */
                  if(branch[0] != NULL)
                      item = VIEWER_INDEX_ITEM(
                        gtk_ctree_node_get_row_data(ctree, branch[0])
                      );
                  else
                      item = NULL;

                  /* Check if source viewer's index item is valid
                   * and of the currect type
                   */
                  if((item != NULL) ?
                      (item->type == ViewerIndexItemTypeManualPage) : FALSE
                  )
                  {
                      /* Load manual page into target viewer's
                       * view text
                       */
                      ViewerSetBusy(v);
                      ViewerViewTextRecordScrollPositions(v);
                      ViewerTextDelete(v, 0, -1);
                      ViewerTextInsertPosition(v, 0);
                      ViewerLoadFile(
                        v,
                        item->full_path,
                        item->full_path
                      );
                      ViewerSetReady(v);
                  }
                } 

           
                /* Delete branches that came from source editor
                 * as needed
                 */
                if(need_delete)
                {
                  /* Do not delete branches on source viewer's
                   * index GtkCTree
                   */
                }
            }

            /* Delete only list of branches from source viewer's
             * index GtkCTree
             */
            g_free(branch);
            branch = NULL;  
            total_branches = 0;
          }
          /* Other standard DND target types? */
          else if((info == MEDIT_DND_TYPE_INFO_TEXT_PLAIN) ||
                (info == MEDIT_DND_TYPE_INFO_TEXT_URI_LIST) ||
                (info == MEDIT_DND_TYPE_INFO_STRING)
          )
          {
            gchar *path = EditorDNDParseURL(
                selection_data->data, selection_data->length
            );

            /* Load manual page into target viewer's view text */
            ViewerSetBusy(v);
            ViewerViewTextRecordScrollPositions(v);
            ViewerTextDelete(v, 0, -1);
            ViewerTextInsertPosition(v, 0);
            ViewerLoadFile(v, path, path);
            ViewerSetReady(v);

            g_free(path);
          }

          /* ******************************************************** */
          /* Add support for other types of DND here */


      }
}

/*
 *      Viewer DND data delete callback.
 *
 *      This deletes the selected item on viewer's layout ctree.
 */
void ViewerDNDDataDeleteCB(
      GtkWidget *widget, GdkDragContext *dc, gpointer data
)
{
      /* Function no longer used */
      return;
}

Generated by  Doxygen 1.6.0   Back to index