Exemple #1
0
static void
parse_path(ShapeInfo *info, const char *path_str, DiaSvgStyle *s, const char* filename)
{
  GArray *points;
  gchar *pathdata = (gchar *)path_str, *unparsed;
  gboolean closed = FALSE;
  Point current_point = {0.0, 0.0};

  points = g_array_new(FALSE, FALSE, sizeof(BezPoint));
  g_array_set_size(points, 0);
  do {
    if (!dia_svg_parse_path (points, pathdata, &unparsed, &closed, &current_point))
      break;

    if (points->len > 0) {
      if (g_array_index(points, BezPoint, 0).type != BEZ_MOVE_TO) {
        message_warning (_("The file '%s' has invalid path data.\n"
	                   "svg:path data must start with moveto."),
			   dia_message_filename(filename));
      } else if (closed) {
        /* if there is some unclosed commands, add them as a GE_SHAPE */
	GraphicElementPath *el = g_malloc(sizeof(GraphicElementPath) +
					    points->len * sizeof(BezPoint));
	el->type = GE_SHAPE;
	dia_svg_style_init (&el->s, s);
	el->npoints = points->len;
	memcpy((char *)el->points, points->data, points->len*sizeof(BezPoint));
	info->display_list = g_list_append(info->display_list, el);
      } else {
        /* if there is some unclosed commands, add them as a GE_PATH */
	GraphicElementPath *el = g_malloc(sizeof(GraphicElementPath) +
				          points->len * sizeof(BezPoint));
	el->type = GE_PATH;
	dia_svg_style_init (&el->s, s);
	el->npoints = points->len;
	memcpy((char *)el->points, points->data, points->len*sizeof(BezPoint));
	info->display_list = g_list_append(info->display_list, el);
      }
      g_array_set_size (points, 0);
    }
    pathdata = unparsed;
    unparsed = NULL;
  } while (pathdata);

  g_array_free (points, TRUE);
}
Exemple #2
0
/** Return an absolute filename from an absolute or relative filename.
 * @param filename A relative or absolute filename.
 * @return Absolute and canonicalized filename as a newly allocated string.
 */
gchar *
dia_get_absolute_filename (const gchar *filename)
{
  gchar *current_dir;
  gchar *fullname;
  gchar *canonical;
  if (filename == NULL) return NULL;
  if (g_path_is_absolute(filename)) return dia_get_canonical_path(filename);
  current_dir = g_get_current_dir();
  fullname = g_build_filename(current_dir, filename, NULL);
  g_free(current_dir);
  if (strchr(fullname, '.') == NULL) return fullname;
  canonical = dia_get_canonical_path(fullname);
  if (canonical == NULL) {
    message_warning(_("Too many \"..\"s in filename %s\n"),
                    dia_message_filename(filename));
    return g_strdup(filename);
  }
  g_free(fullname);
  return canonical;
}
Exemple #3
0
/** If all files produced by dia were good XML files, we wouldn't have to do
 *  this little gymnastic. Alas, during the libxml1 days, we were outputting
 *  files with no encoding specification (which means UTF-8 if we're in an
 *  asciish encoding) and strings encoded in local charset (so, we wrote
 *  broken files).
 *
 *  The following logic finds if we have a broken file, and attempts to fix
 *  it if it's possible. If the file is correct or is unrecognisable, we pass
 *  it untouched to libxml2.
 * @param filename The name of the file to check.
 * @param default_enc The default encoding to use if none is given.
 * @return The filename given if it seems ok, or the name of a new file
 *          with fixed contents, or NULL if we couldn't read the file.  The
 *          caller should free this string and unlink the file if it is not
 *          the same as `filename'.
 * @bug The many gzclose-g_free-return sequences should be refactored into
 *       an "exception handle" (goto+label). At least for people who think goto is
 *       better than this. I dont. --hb
 */
static const gchar *
xml_file_check_encoding(const gchar *filename, const gchar *default_enc)
{
  int fd = g_open (filename, O_RDONLY, 0);
  gzFile zf = gzdopen(fd,"rb");
  gchar *buf;
  gchar *p,*pmax;
  int len;
  gchar *tmp,*res;
  int uf;
  gboolean well_formed_utf8;

  static char magic_xml[] =
  {0x3c,0x3f,0x78,0x6d,0x6c,0x00}; /* "<?xml" in ASCII */

  if (!zf) {
    dia_log_message("%s can not be opened for encoding check (%s)", filename, fd > 0 ? "gzdopen" : "g_open");
    /* XXX perhaps we can just chicken out to libxml ? -- CC */
    return filename;
  }
  p = buf = g_malloc0(BUFLEN);
  len = gzread(zf,buf,BUFLEN);
  pmax = p + len;

  /* first, we expect the magic <?xml string */
  if ((0 != strncmp(p,magic_xml,5)) || (len < 5)) {
    gzclose(zf);
    g_free(buf);
    return filename; /* let libxml figure out what this is. */
  }
  /* now, we're sure we have some asciish XML file. */
  p += 5;
  while (((*p == 0x20)||(*p == 0x09)||(*p == 0x0d)||(*p == 0x0a))
         && (p<pmax)) p++;
  if (p>=pmax) { /* whoops ? */
    gzclose(zf);
    g_free(buf);
    return filename;
  }
  if (0 != strncmp(p,"version=\"",9)) {
    gzclose(zf); /* chicken out. */
    g_free(buf);
    return filename;
  }
  p += 9;
  /* The header is rather well formed. */
  if (p>=pmax) { /* whoops ? */
    gzclose(zf);
    g_free(buf);
    return filename;
  }
  while ((*p != '"') && (p < pmax)) p++;
  p++;
  while (((*p == 0x20)||(*p == 0x09)||(*p == 0x0d)||(*p == 0x0a))
         && (p<pmax)) p++;
  if (p>=pmax) { /* whoops ? */
    gzclose(zf);
    g_free(buf);
    return filename;
  }
  if (0 == strncmp(p,"encoding=\"",10)) {
    gzclose(zf); /* this file has an encoding string. Good. */
    g_free(buf);
    return filename;
  }
  /* now let's read the whole file, to see if there are offending bits.
   * We can call it well formed UTF-8 if the highest isn't used
   */
  well_formed_utf8 = TRUE;
  do {
    int i;
    for (i = 0; i < len; i++)
      if (buf[i] & 0x80 || buf[i] == '&')
        well_formed_utf8 = FALSE;
    len = gzread(zf,buf,BUFLEN);
  } while (len > 0 && well_formed_utf8);
  if (well_formed_utf8) {
    gzclose(zf); /* this file is utf-8 compatible  */
    g_free(buf);
    return filename;
  } else {
    gzclose(zf); /* poor man's fseek */
    fd = g_open (filename, O_RDONLY, 0);
    zf = gzdopen(fd,"rb");
    len = gzread(zf,buf,BUFLEN);
  }

  if (0 != strcmp(default_enc,"UTF-8")) {
    message_warning(_("The file %s has no encoding specification;\n"
                      "assuming it is encoded in %s"),
		    dia_message_filename(filename), default_enc);
  } else {
    gzclose(zf); /* we apply the standard here. */
    g_free(buf);
    return filename;
  }

  tmp = getenv("TMP");
  if (!tmp) tmp = getenv("TEMP");
  if (!tmp) tmp = "/tmp";

  res = g_strconcat(tmp,G_DIR_SEPARATOR_S,"dia-xml-fix-encodingXXXXXX",NULL);
  uf = g_mkstemp(res);
  write(uf,buf,p-buf);
  write(uf," encoding=\"",11);
  write(uf,default_enc,strlen(default_enc));
  write(uf,"\" ",2);
  write(uf,p,pmax - p);

  while (1) {
    len = gzread(zf,buf,BUFLEN);
    if (len <= 0) break;
    write(uf,buf,len);
  }
  gzclose(zf);
  close(uf);
  g_free(buf);
  return res; /* caller frees the name and unlinks the file. */
}
Exemple #4
0
/**
 * A button hit in the Export Dialog
 */
static void
file_export_response_callback(GtkWidget *fs, 
                              gint       response, 
                              gpointer   user_data)
{
  char *filename;
  Diagram *dia;
  DiaExportFilter *ef;
  struct stat statbuf;

  dia = g_object_get_data (G_OBJECT (fs), "user_data");
  g_assert (dia);

  if (response == GTK_RESPONSE_ACCEPT) {
    gint index;

    diagram_update_extents(dia);

    filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(fs));

    if (g_stat(filename, &statbuf) == 0) {
      GtkWidget *dialog = NULL;

      dialog = gtk_message_dialog_new (GTK_WINDOW(fs),
				       GTK_DIALOG_MODAL | GTK_DIALOG_DESTROY_WITH_PARENT, 
				       GTK_MESSAGE_QUESTION,
				       GTK_BUTTONS_YES_NO,
				       _("File already exists"));
      gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(dialog),
        _("The file '%s' already exists.\n"
        "Do you want to overwrite it?"), dia_message_filename(filename));
      gtk_dialog_set_default_response (GTK_DIALOG (dialog), GTK_RESPONSE_YES);

      if (gtk_dialog_run (GTK_DIALOG (dialog)) != GTK_RESPONSE_YES) {
	/* if not overwrite allow to select another filename */
	gtk_widget_destroy(dialog);
	g_free (filename);
	return;
      }
      gtk_widget_destroy(dialog);
    }

    index = gtk_combo_box_get_active (GTK_COMBO_BOX(user_data));
    if (index >= 0)
      persistence_set_integer ("export-filter", index);
    ef = efilter_by_index (index - 1, NULL);
    if (!ef)
      ef = filter_guess_export_filter(filename);
    if (ef) {
      DiaContext *ctx = dia_context_new (_("Export"));

      g_object_ref(dia->data);
      dia_context_set_filename (ctx, filename);
      ef->export_func(dia->data, ctx,
		      filename, dia->filename, ef->user_data);
      g_object_unref(dia->data);
      dia_context_release (ctx);
    } else
      message_error(_("Could not determine which export filter\n"
		      "to use to save '%s'"), dia_message_filename(filename));
    g_free (filename);
  }
  g_object_unref (dia); /* drop our diagram reference */
  gtk_widget_destroy(exportdlg);
}
Exemple #5
0
/** Initializes a diagram with standard info and sets it to be called
 * 'filename'.  
 * Returns TRUE if everything went ok, FALSE otherwise.
 * Will return FALSE if filename is not a legal string in the current
 * encoding.
 */
static gboolean
diagram_init(Diagram *dia, const char *filename)
{
  gchar *newfilename = NULL;
  GError *error = NULL;
 
  dia->data = &dia->parent_instance; /* compatibility */

  dia->pagebreak_color = prefs.new_diagram.pagebreak_color;
  
  get_paper_info (&dia->data->paper, -1, &prefs.new_diagram);

  dia->grid.width_x = prefs.grid.x;
  dia->grid.width_y = prefs.grid.y;
  dia->grid.width_w = prefs.grid.w;
  dia->grid.hex_size = 1.0;
  dia->grid.colour = prefs.new_diagram.grid_color;
  dia->grid.hex = prefs.grid.hex;
  dia->grid.visible_x = prefs.grid.vis_x;
  dia->grid.visible_y = prefs.grid.vis_y;
  dia->grid.dynamic = prefs.grid.dynamic;
  dia->grid.major_lines = prefs.grid.major_lines;

  dia->guides.nhguides = 0;
  dia->guides.hguides = NULL;
  dia->guides.nvguides = 0;
  dia->guides.vguides = NULL;

  if (dia->filename != NULL)
    g_free(dia->filename);
  /* Make sure the filename is absolute */
  if (!g_path_is_absolute(filename)) {
    gchar *pwd = g_get_current_dir();

    newfilename = g_build_filename(pwd, filename, NULL);
    g_free(pwd);
    filename = newfilename;
  }
  /* All Diagram functions assumes filename in filesystem encoding */
  
  dia->filename = g_filename_to_utf8(filename, -1, NULL, NULL, &error);
  if (error != NULL) {
    message_error(_("Couldn't convert filename '%s' to UTF-8: %s\n"),
		  dia_message_filename(filename), error->message);
    g_error_free(error);
    dia->filename = g_strdup(_("Error"));
    return FALSE;
  }

  dia->unsaved = TRUE;
  dia->mollified = FALSE;
  dia->autosavefilename = NULL;

  if (dia->undo)
    undo_destroy(dia->undo);
  dia->undo = new_undo_stack(dia);

  if (!g_list_find(open_diagrams, dia))
    open_diagrams = g_list_prepend(open_diagrams, dia);

  if (app_is_interactive())
    layer_dialog_update_diagram_list();

  g_free(newfilename);

  g_signal_connect (G_OBJECT(dia), "object_add", G_CALLBACK(_object_add), dia);
  g_signal_connect (G_OBJECT(dia), "object_remove", G_CALLBACK(_object_remove), dia);

  return TRUE;
}
Exemple #6
0
static DiaSvgRenderer *
new_shape_renderer(DiagramData *data, const char *filename)
{
  ShapeRenderer *shape_renderer;
  DiaSvgRenderer *renderer;
  FILE *file;
  char *point;
  xmlNsPtr name_space;
  xmlNodePtr xml_node_ptr;
  gint i;
  gchar *png_filename;
  char *shapename, *dirname, *fullname;
  char *sheetname;

  file = g_fopen(filename, "w");

  if (file==NULL) {
      message_error(_("Can't open output file %s: %s\n"), 
		    dia_message_filename(filename), strerror(errno));
    return NULL;
  }
  fclose(file);

  shape_renderer = g_object_new(SHAPE_TYPE_RENDERER, NULL);
  renderer = DIA_SVG_RENDERER (shape_renderer);

  renderer->filename = g_strdup(filename);

  renderer->dash_length = 1.0;
  renderer->dot_length = 0.2;
  renderer->saved_line_style = LINESTYLE_SOLID;
  /* keep everything unscaled, i.e. in Dia's scale default */
  renderer->scale = 1.0;

  /* set up the root node */
  renderer->doc = xmlNewDoc((const xmlChar *)"1.0");
  renderer->doc->encoding = xmlStrdup((const xmlChar *)"UTF-8");
  renderer->root = xmlNewDocNode(renderer->doc, NULL, (const xmlChar *)"shape", NULL);
  name_space = xmlNewNs(renderer->root,
                        (const xmlChar *)"http://www.daa.com.au/~james/dia-shape-ns", NULL);

  renderer->svg_name_space = xmlNewNs(renderer->root,
                                      (const xmlChar *)"http://www.w3.org/2000/svg", (const xmlChar *)"svg");
  renderer->doc->xmlRootNode = renderer->root;

  dirname = g_path_get_dirname(filename);
  sheetname = g_path_get_basename(dirname);
  shapename = g_strndup(g_basename(filename), strlen(g_basename(filename))-6);
  fullname = g_strdup_printf ("%s - %s", sheetname, shapename);
  g_free(dirname);
  g_free(sheetname);
  g_free(shapename);

  xmlNewChild(renderer->root, NULL, (const xmlChar *)"name", (xmlChar *) fullname);
  g_free(fullname);
  point = strrchr(filename, '.');
  i = (int)(point-filename);
  point = g_strndup(filename, i);
  png_filename = g_strdup_printf("%s.png",point);
  g_free(point);
  xmlNewChild(renderer->root, NULL, (const xmlChar *)"icon", (xmlChar *) g_basename(png_filename));
  g_free(png_filename);
  shape_renderer->connection_root = xmlNewChild(renderer->root, NULL, (const xmlChar *)"connections", NULL);
  xml_node_ptr = xmlNewChild(renderer->root, NULL, (const xmlChar *)"aspectratio",NULL);
  xmlSetProp(xml_node_ptr, (const xmlChar *)"type", (const xmlChar *)"fixed");
  renderer->root = xmlNewChild(renderer->root, renderer->svg_name_space, (const xmlChar *)"svg", NULL);
    
  return renderer;
}
Exemple #7
0
static DiaSvgRenderer *
new_svg_renderer(DiagramData *data, const char *filename)
{
  DiaSvgRenderer *renderer;
  SvgRenderer *svg_renderer;
  FILE *file;
  gchar buf[512];
  time_t time_now;
  Rectangle *extent;
  const char *name;
  xmlDtdPtr dtd;
 
  file = g_fopen(filename, "w");

  if (file==NULL) {
    message_error(_("Can't open output file %s: %s\n"), 
		  dia_message_filename(filename), strerror(errno));
    return NULL;
  }
  fclose(file);

  /* we need access to our base object */
  renderer = DIA_SVG_RENDERER (g_object_new(SVG_TYPE_RENDERER, NULL));

  renderer->filename = g_strdup(filename);

  renderer->dash_length = 1.0;
  renderer->dot_length = 0.2;
  renderer->saved_line_style = LINESTYLE_SOLID;
  /* apparently most svg readers don't like small values, especially not in the viewBox attribute */
  renderer->scale = 20.0;

  /* set up the root node */
  renderer->doc = xmlNewDoc((const xmlChar *)"1.0");
  renderer->doc->encoding = xmlStrdup((const xmlChar *)"UTF-8");
  renderer->doc->standalone = FALSE;
  dtd = xmlCreateIntSubset(renderer->doc, (const xmlChar *)"svg",
		     (const xmlChar *)"-//W3C//DTD SVG 1.0//EN",
		     (const xmlChar *)"http://www.w3.org/TR/2001/PR-SVG-20010719/DTD/svg10.dtd");
  xmlAddChild((xmlNodePtr) renderer->doc, (xmlNodePtr) dtd);
  renderer->root = xmlNewDocNode(renderer->doc, NULL, (const xmlChar *)"svg", NULL);
  xmlAddSibling(renderer->doc->children, (xmlNodePtr) renderer->root);

  /* add namespaces to make strict parsers happy, e.g. Firefox */
  svg_renderer = SVG_RENDERER (renderer);

  /* set the extents of the SVG document */
  extent = &data->extents;
  g_snprintf(buf, sizeof(buf), "%dcm",
	     (int)ceil((extent->right - extent->left)));
  xmlSetProp(renderer->root, (const xmlChar *)"width", (xmlChar *) buf);
  g_snprintf(buf, sizeof(buf), "%dcm",
	     (int)ceil((extent->bottom - extent->top)));
  xmlSetProp(renderer->root, (const xmlChar *)"height", (xmlChar *) buf);
  g_snprintf(buf, sizeof(buf), "%d %d %d %d",
	     (int)floor(extent->left  * renderer->scale), (int)floor(extent->top * renderer->scale),
	     (int)ceil((extent->right - extent->left) * renderer->scale),
	     (int)ceil((extent->bottom - extent->top) * renderer->scale));
  xmlSetProp(renderer->root, (const xmlChar *)"viewBox", (xmlChar *) buf);
  xmlSetProp(renderer->root,(const xmlChar *)"xmlns", (const xmlChar *)"http://www.w3.org/2000/svg");
  xmlSetProp(renderer->root,(const xmlChar *)"xmlns", (const xmlChar *)"http://www.w3.org/2000/svg");
  xmlSetProp(renderer->root,(const xmlChar *)"xmlns:xlink", (const xmlChar *)"http://www.w3.org/1999/xlink");

  time_now = time(NULL);
  name = g_get_user_name();

#if 0
  /* some comments at the top of the file ... */
  xmlAddChild(renderer->root, xmlNewText("\n"));
  xmlAddChild(renderer->root, xmlNewComment("Dia-Version: "VERSION));
  xmlAddChild(renderer->root, xmlNewText("\n"));
  g_snprintf(buf, sizeof(buf), "File: %s", dia->filename);
  xmlAddChild(renderer->root, xmlNewComment(buf));
  xmlAddChild(renderer->root, xmlNewText("\n"));
  g_snprintf(buf, sizeof(buf), "Date: %s", ctime(&time_now));
  buf[strlen(buf)-1] = '\0'; /* remove the trailing new line */
  xmlAddChild(renderer->root, xmlNewComment(buf));
  xmlAddChild(renderer->root, xmlNewText("\n"));
  g_snprintf(buf, sizeof(buf), "For: %s", name);
  xmlAddChild(renderer->root, xmlNewComment(buf));
  xmlAddChild(renderer->root, xmlNewText("\n\n"));

  xmlNewChild(renderer->root, NULL, "title", dia->filename);
#endif
  
  return renderer;
}
/**
 * @param filename the file to load from or NULL for default
 * @param create_lazy if FALSE creates default objects for
 *             every known type. Otherwise default objects
 *             are created on demand
 *
 * Create all the default objects.
 */
gboolean
dia_object_defaults_load (const gchar *filename, gboolean create_lazy)
{
    xmlDocPtr doc;
    xmlNsPtr name_space;
    ObjectNode obj_node, layer_node;

    object_default_create_lazy = create_lazy;

    if (!defaults_hash)
    {
        defaults_hash = g_hash_table_new_full(g_str_hash, g_str_equal,
                                              NULL, _obj_destroy);

        if (!create_lazy)
            object_registry_foreach (_obj_create, defaults_hash);
    }


    /* overload properties from file */
    if (!filename)
    {
        gchar *default_filename = dia_config_filename("defaults.dia");

        if (g_file_test(default_filename, G_FILE_TEST_EXISTS))
            doc = xmlDiaParseFile(default_filename);
        else
            doc = NULL;
        g_free (default_filename);
    }
    else
        doc = xmlDiaParseFile(filename);

    if (!doc)
        return FALSE;

    name_space = xmlSearchNs(doc, doc->xmlRootNode, (const xmlChar *)"dia");
    if (xmlStrcmp (doc->xmlRootNode->name, (const xmlChar *)"diagram")
            || (name_space == NULL))
    {
        message_error(_("Error loading defaults '%s'.\n"
                        "Not a Dia diagram file."),
                      dia_message_filename(filename));
        xmlFreeDoc (doc);
        return FALSE;
    }

    layer_node = doc->xmlRootNode->xmlChildrenNode;
    while (layer_node)
    {
        if (   !xmlIsBlankNode(layer_node)
                && 0 == xmlStrcmp(layer_node->name, (const xmlChar *)"layer"))
        {
            obj_node = layer_node->xmlChildrenNode;
            while (obj_node)
            {
                if (!xmlIsBlankNode(obj_node)
                        && 0 == xmlStrcmp(obj_node->name, (const xmlChar *)"object"))
                {
                    char *typestr = (char *) xmlGetProp(obj_node, (const xmlChar *)"type");
                    char *version = (char *) xmlGetProp(obj_node, (const xmlChar *)"version");
                    if (typestr)
                    {
                        DiaObject *obj = g_hash_table_lookup (defaults_hash, typestr);
                        if (!obj)
                        {
                            if (!create_lazy)
                                g_warning ("Unknown object '%s' while reading '%s'",
                                           typestr, filename);
                            else
                            {
                                DiaObjectType *type = object_get_type (typestr);
                                if (type)
                                    obj = type->ops->load (
                                              obj_node,
                                              0,
                                              filename);
                                if (obj)
                                    g_hash_table_insert (defaults_hash,
                                                         obj->type->name, obj);
                            }
                        }
                        else
                        {
#if 0 /* lots of complaining about missing attributes */
                            object_load_props(obj, obj_node); /* leaks ?? */
#else
                            DiaObject *def_obj;
                            def_obj = obj->type->ops->load (
                                          obj_node,
                                          /*version ? atoi(version) : 0,*/0,
                                          filename);
                            if (def_obj->ops->set_props)
                            {
                                object_copy_props (obj, def_obj, TRUE);
                                def_obj->ops->destroy (def_obj);
                            }
                            else
                            {
                                /* can't copy props */
                                g_hash_table_replace (defaults_hash,
                                                      def_obj->type->name, def_obj);
                            }
#endif
                        }
                        if (version)
                            xmlFree (version);
                        xmlFree (typestr);
                    }
                }
                obj_node = obj_node->next;
            }
        }
        layer_node = layer_node->next;
    }

    xmlFreeDoc(doc);
    return TRUE;
}