Exemple #1
0
/*! \brief Re-poll a library command for symbols.
 *  \par Function Description
 *  Runs a library command, requesting a list of available symbols,
 *  and updates the source with the new list.
 *
 *  Private function used only in s_clib.c.
 */
static void refresh_command (CLibSource *source)
{
  gchar *cmdout;
  TextBuffer *tb;
  const gchar *line;
  CLibSymbol *symbol;
  gchar *name;

  g_return_if_fail (source != NULL);
  g_return_if_fail (source->type == CLIB_CMD);

  /* Clear the current symbol list */
  g_list_foreach (source->symbols, (GFunc) free_symbol, NULL);
  g_list_free (source->symbols);
  source->symbols = NULL;

  /* Run the command to get the list of symbols */
  cmdout = run_source_command (source->list_cmd);
  if (cmdout == NULL) return;

  /* Use a TextBuffer to help reading out the lines of the output */
  tb = s_textbuffer_new (cmdout, -1, "s_clib.c::refresh_command()");

  while (1) {
    line = s_textbuffer_next_line (tb);
    if (line == NULL) break;
    if (line[0] == '.') continue;  /* TODO is this sane? */

    name = geda_string_get_first_line (g_strdup(line));

    /* skip symbols already known about */
    if (source_has_symbol (source, name) != NULL) {
      g_free (name);
      continue;
    }

    symbol = g_new0 (CLibSymbol, 1);
    symbol->source = source;
    symbol->name = name;

    /* Prepend because it's faster and it doesn't matter what order we
     * add them. */
    source->symbols = g_list_prepend (source->symbols, symbol);
  }

  s_textbuffer_free (tb);
  g_free (cmdout);

  /* Sort all symbols by name. */
  source->symbols = g_list_sort (source->symbols,
				 (GCompareFunc) compare_symbol_name);

  s_clib_flush_search_cache();
  s_clib_flush_symbol_cache();
}
/*! \brief Create path OBJECT from character string.
 *  \par Function Description
 *  This function creates a path OBJECT from the character string
 *  <B>*buf</B> and a number of lines following that describing the
 *  path, read from <B>*tb</B>.
 *
 *  Depending on <B>*version</B>, the correct file format is considered.
 *  Currently two file format revisions are supported :
 *  <DL>
 *    <DT>*</DT><DD>the file format used until 20010704 release.
 *    <DT>*</DT><DD>the file format used for the releases after 20010704.
 *  </DL>
 *
 *  \param [in]  toplevel       The TOPLEVEL object.
 *  \param [in]  first_line      Character string with path description.
 *  \param [in]  tb              Text buffer containing the path string.
 *  \param [in]  release_ver     libgeda release version number.
 *  \param [in]  fileformat_ver  libgeda file format version number.
 *  \return A pointer to the new path object, or NULL on error;
 */
OBJECT *o_path_read (TOPLEVEL *toplevel,
                     const char *first_line, TextBuffer *tb,
                     unsigned int release_ver, unsigned int fileformat_ver, GError **err)
{
  OBJECT *new_obj;
  char type;
  int color;
  int line_width, line_space, line_length;
  int line_end;
  int line_type;
  int fill_type, fill_width, angle1, pitch1, angle2, pitch2;
  int num_lines = 0;
  int i;
  char *string;
  GString *pathstr;

  /*
   * The current path format to describe a line is a space separated
   * list of characters and numbers in plain ASCII on a single path.
   * The meaning of each item is described in the file format documentation.
   */
  /* Allocate enough space */
  if (sscanf (first_line, "%c %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
	      &type, &color, &line_width, &line_end, &line_type,
	      &line_length, &line_space, &fill_type, &fill_width, &angle1,
	      &pitch1, &angle2, &pitch2, &num_lines) != 14) {
    g_set_error(err, EDA_ERROR, EDA_ERROR_PARSE, _("Failed to parse path object"));
    return NULL;
  }

  /*
   * Checks if the required color is valid.
   */
  if (color < 0 || color > MAX_COLORS) {
    s_log_message (_("Found an invalid color [ %1$s ]"), first_line);
    s_log_message (_("Setting color to default color."));
    color = DEFAULT_COLOR;
  }

  /*
   * A path is internally described by its two ends. A new object is
   * allocated, initialized and added to the list of objects. Its path
   * type is set according to the values of the fields on the path.
   */

  pathstr = g_string_new ("");
  for (i = 0; i < num_lines; i++) {
    const gchar *line;

    line = s_textbuffer_next_line (tb);

    if (line == NULL) {
      g_set_error (err, EDA_ERROR, EDA_ERROR_PARSE, _("Unexpected end-of-file when reading path"));
      return NULL;
    }

    pathstr = g_string_append (pathstr, line);
  }

  /* retrieve the character string from the GString */
  string = g_string_free (pathstr, FALSE);
  string = geda_string_remove_ending_newline (string);

  /* create a new path */
  new_obj = geda_path_object_new (toplevel, type, color, string);
  g_free (string);

  /* set its line options */
  o_set_line_options (toplevel,
                      new_obj,
                      (OBJECT_END) line_end,
                      (OBJECT_TYPE) line_type,
                      line_width,
                      line_length,
                      line_space);
  /* set its fill options */
  o_set_fill_options (toplevel,
                      new_obj,
                      (OBJECT_FILLING) fill_type,
                      fill_width,
                      pitch1,
                      angle1,
                      pitch2,
                      angle2);

  return new_obj;
}
Exemple #3
0
/*! \brief Read attributes from a buffer.
 *  \par Function Description
 *  Read attributes from a TextBuffer.
 *
 *  \param [in]  toplevel               The TOPLEVEL object.
 *  \param [in]  object_to_get_attribs  Object which gets these attribs.
 *  \param [in]  tb                     The text buffer to read from.
 *  \param [in]  release_ver            libgeda release version number.
 *  \param [in]  fileformat_ver         file format version number.
 *  \return GList of attributes read, or NULL on error.
 */
GList *o_read_attribs (TOPLEVEL *toplevel,
                       OBJECT *object_to_get_attribs,
                       TextBuffer *tb,
                       unsigned int release_ver, unsigned int fileformat_ver, GError ** err)
{
  GList *object_list = NULL;
  OBJECT *new_obj;
  const char *line = NULL;
  char objtype;
  int ATTACH=FALSE;

  while (1) {

    line = s_textbuffer_next_line (tb);
    if (line == NULL) break;

    sscanf(line, "%c", &objtype);
    switch (objtype) {

      case(OBJ_LINE):
        if ((new_obj = o_line_read (toplevel, line, release_ver, fileformat_ver, err)) == NULL)
          goto error;
        object_list = g_list_prepend (object_list, new_obj);
        break;


      case(OBJ_NET):
        if ((new_obj = o_net_read (toplevel, line, release_ver, fileformat_ver, err)) == NULL)
          goto error;
        object_list = g_list_prepend (object_list, new_obj);
        break;

      case(OBJ_BUS):
        if ((new_obj = o_bus_read (toplevel, line, release_ver, fileformat_ver, err)) == NULL)
          goto error;
        object_list = g_list_prepend (object_list, new_obj);
        break;

      case(OBJ_BOX):
        if ((new_obj = o_box_read (toplevel, line, release_ver, fileformat_ver, err)) == NULL)
          goto error;
        object_list = g_list_prepend (object_list, new_obj);
        break;

      case(OBJ_CIRCLE):
        if ((new_obj = o_circle_read (toplevel, line, release_ver, fileformat_ver, err)) == NULL)
          goto error;
        object_list = g_list_prepend (object_list, new_obj);
        break;

      case(OBJ_COMPLEX):
      case(OBJ_PLACEHOLDER):
        if ((new_obj = o_complex_read (toplevel, line, release_ver, fileformat_ver, err)) == NULL)
          goto error;
        object_list = g_list_prepend (object_list, new_obj);
        break;

      case(OBJ_PATH):
        new_obj = o_path_read (toplevel, line, tb, release_ver, fileformat_ver, err);
        if (new_obj == NULL)
          goto error;
        object_list = g_list_prepend (object_list, new_obj);
        break;

      case(OBJ_PIN):
        if ((new_obj = o_pin_read (toplevel, line, release_ver, fileformat_ver, err)) == NULL)
          goto error;
        object_list = g_list_prepend (object_list, new_obj);
        break;

      case(OBJ_ARC):
        if ((new_obj = o_arc_read (toplevel, line, release_ver, fileformat_ver, err)) == NULL)
          goto error;
        object_list = g_list_prepend (object_list, new_obj);
        break;

      case(OBJ_TEXT):
        new_obj = o_text_read (toplevel, line, tb, release_ver, fileformat_ver, err);
        if (new_obj == NULL)
          goto error;
        object_list = g_list_prepend (object_list, new_obj);
        ATTACH=TRUE;

        break;

      case(ENDATTACH_ATTR):
        return object_list;
        break;
    }

    if (ATTACH) {
      o_attrib_attach (toplevel, new_obj, object_to_get_attribs, FALSE);
      ATTACH=FALSE;
    } else {
      g_set_error(err, EDA_ERROR, EDA_ERROR_PARSE, _("Tried to attach a non-text item as an attribute"));
      goto error;
    }
  }

  /* The attribute list wasn't terminated, so it's a parse error! */
  g_set_error (err, EDA_ERROR, EDA_ERROR_PARSE,
               _("Unexpected end-of-file in attribute list"));

error:
  s_delete_object_glist(toplevel, object_list);
  return NULL;
}
Exemple #4
0
/*! \brief Read attributes from a buffer.
 *  \par Function Description
 *  Read attributes from a TextBuffer.
 *
 *  \param [in]  toplevel               The TOPLEVEL object.
 *  \param [out] list                   Storage for attributes.
 *  \param [in]  object_to_get_attribs  Object which gets these attribs.
 *  \param [in]  tb                     The text buffer to read from.
 *  \param [in]  release_ver            libgeda release version number.
 *  \param [in]  fileformat_ver         file format version number.
 *  \return GList of attributes read.
 */
GList *o_read_attribs (TOPLEVEL *toplevel,
                       GList *list,
                       OBJECT *object_to_get_attribs,
                       TextBuffer *tb,
                       unsigned int release_ver, unsigned int fileformat_ver)
{
  GList *object_list;
  OBJECT *new_obj;
  char *line = NULL;
  char objtype;
  int ATTACH=FALSE;

  object_list = g_list_reverse (list);

  while (1) {

    line = s_textbuffer_next_line (tb);
    if (line == NULL) break;

    sscanf(line, "%c", &objtype);
    switch (objtype) {

      case(OBJ_LINE):
        new_obj = o_line_read (toplevel, line, release_ver, fileformat_ver);
        object_list = g_list_prepend (object_list, new_obj);
        break;


      case(OBJ_NET):
        new_obj = o_net_read (toplevel, line, release_ver, fileformat_ver);
        object_list = g_list_prepend (object_list, new_obj);
        break;

      case(OBJ_BUS):
        new_obj = o_bus_read (toplevel, line, release_ver, fileformat_ver);
        object_list = g_list_prepend (object_list, new_obj);
        break;

      case(OBJ_BOX):
        new_obj = o_box_read (toplevel, line, release_ver, fileformat_ver);
        object_list = g_list_prepend (object_list, new_obj);
        break;

      case(OBJ_CIRCLE):
        new_obj = o_circle_read (toplevel, line, release_ver, fileformat_ver);
        object_list = g_list_prepend (object_list, new_obj);
        break;

      case(OBJ_COMPLEX):
      case(OBJ_PLACEHOLDER):
        new_obj = o_complex_read (toplevel, line, release_ver, fileformat_ver);
        object_list = g_list_prepend (object_list, new_obj);
        break;

      case(OBJ_PATH):
        line = g_strdup (line);
        new_obj = o_path_read (toplevel, line, tb, release_ver, fileformat_ver);
        g_free (line);
        object_list = g_list_prepend (object_list, new_obj);
        break;

      case(OBJ_PIN):
        new_obj = o_pin_read (toplevel, line, release_ver, fileformat_ver);
        object_list = g_list_prepend (object_list, new_obj);
        break;

      case(OBJ_ARC):
        new_obj = o_arc_read (toplevel, line, release_ver, fileformat_ver);
        object_list = g_list_prepend (object_list, new_obj);
        break;

      case(OBJ_TEXT):
        line = g_strdup (line);
        new_obj = o_text_read (toplevel, line, tb, release_ver, fileformat_ver);
        g_free (line);
        object_list = g_list_prepend (object_list, new_obj);
        ATTACH=TRUE;

        break;

      case(ENDATTACH_ATTR): 
        object_list = g_list_reverse (object_list);
        return(object_list);
        break;

    }

    if (ATTACH) {
      o_attrib_attach (toplevel, new_obj, object_to_get_attribs, FALSE);
      ATTACH=FALSE;
    } else {
      fprintf(stderr, "Tried to attach a non-text item as an attribute\n");
    }
  }
  object_list = g_list_reverse (object_list);
  return(object_list);
}
Exemple #5
0
/*! \brief Create picture OBJECT from character string.
 *  \par Function Description
 *  This function will get the description of a picture from the
 *  character string <B>*first_line</B>.
 *
 *  \param [in]  toplevel       The TOPLEVEL object.
 *  \param [in]  first_line      Character string with picture description.
 *  \param [in]  tb              Text buffer to load embedded data from.
 *  \param [in]  release_ver     libgeda release version number.
 *  \param [in]  fileformat_ver  libgeda file format version number.
 *  \return A pointer to the new picture object.
 */
OBJECT *o_picture_read (TOPLEVEL *toplevel,
		       const char *first_line,
		       TextBuffer *tb,
		       unsigned int release_ver,
		       unsigned int fileformat_ver)
{
  OBJECT *new_obj;
  int x1, y1;
  int width, height, angle;
  gchar mirrored, embedded;
  int num_conv;
  gchar type;
  gchar *line = NULL;
  gchar *filename;
  GdkPixbuf *pixbuf = NULL;
  gchar *file_content = NULL;
  guint file_length = 0;
  GError *err = NULL;

  num_conv = sscanf(first_line, "%c %d %d %d %d %d %c %c\n",
	 &type, &x1, &y1, &width, &height, &angle, &mirrored, &embedded);
  
  if (num_conv != 8) {
    s_log_message (_("Error reading picture definition line: %s.\n"),
                   first_line);
  }

  /* Convert from ascii character to number */
  if (g_ascii_isdigit(mirrored)) {
    mirrored -= 0x30;
  }

  if (g_ascii_isdigit(embedded)) {
    embedded -= 0x30;
  }

  if (width == 0 || height == 0) {
    s_log_message(_("Found a zero width/height picture [ %c %d %d %d %d ]\n"),
                  type, x1, y1, width, height);
  }

  if ( (mirrored > 1) || (mirrored < 0)) {
    s_log_message(_("Found a picture with a wrong 'mirrored' parameter: %c.\n"),
	    mirrored);
    s_log_message(_("Setting mirrored to 0\n"));
    mirrored = 0;
  }

  if ( (embedded > 1) || (embedded < 0)) {
    s_log_message(_("Found a picture with a wrong 'embedded' parameter: %c.\n"),
	    embedded);
    s_log_message(_("Setting embedded to 0\n"));
    embedded = 0;
  }
  switch(angle) {
	
    case(0):
    case(90):
    case(180):
    case(270):
    break;

    default:
      s_log_message(_("Found an unsupported picture angle [ %d ]\n"), angle);
      s_log_message(_("Setting angle to 0\n"));
      angle=0;
      break;

  }

  filename = g_strdup(s_textbuffer_next_line(tb));
  filename = remove_last_nl(filename);	

  if (embedded == 1) {
    GString *encoded_picture=g_string_new("");
    char finished = 0;

    /* Read the encoded picture */
    do {

      line = s_textbuffer_next_line(tb);
      if (line == NULL) break;

      if (g_strcasecmp(line, ".\n") != 0) {
        encoded_picture = g_string_append (encoded_picture, line);
      } else {
        finished = 1;
      }
    } while (finished == 0);

    /* Decode the picture */
    file_content = s_encoding_base64_decode(encoded_picture->str,
                                            encoded_picture->len,
                                            &file_length);
    if (encoded_picture != NULL) {
      g_string_free (encoded_picture, TRUE);
    }

    if (file_content == NULL) {
      s_log_message (_("Failed to load image from embedded data [%s]: %s\n"),
                     filename, _("Base64 decoding failed."));
      s_log_message (_("Falling back to file loading. Picture unembedded.\n"));
      embedded = 0;
    }
  }

  /* If we have embedded data, try loading from the decoded buffer */
  if (file_content != NULL) {
    pixbuf = o_picture_pixbuf_from_buffer (file_content, file_length, &err);
    if (err != NULL) {
      s_log_message (_("Failed to load image from embedded data [%s]: %s\n"),
                     filename, err->message);
      s_log_message (_("Falling back to file loading. Picture unembedded.\n"));
      g_error_free (err);
      err = NULL;
      embedded = 0;
    }
  }

  /* If we haven't loaded the pixbuf above, try loading from file */
  if (pixbuf == NULL) {
    pixbuf = gdk_pixbuf_new_from_file (filename, &err);
    if (err != NULL) {
      s_log_message (_("Failed to load image from file [%s]: %s\n"),
                     filename, err->message);
      g_error_free (err);
      err = NULL;
    }
  }

  /* If the pixbuf couldn't be loaded, then try to load a warning picture */
  if (pixbuf == NULL) {
    char *temp_filename;

    s_log_message (_("Loading warning picture.\n"));
    
    temp_filename = g_build_filename (toplevel->bitmap_directory,
                                      "gschem-warning.png", NULL);
    pixbuf = gdk_pixbuf_new_from_file (temp_filename, NULL);
    if (pixbuf == NULL) {
      s_log_message( _("Error loading picture from file: %s.\n"),
                     temp_filename);
    }      
    g_free (temp_filename);
  }
  
  /* create the picture */
  /* The picture is described by its upper left and lower right corner */
  new_obj = o_picture_new(toplevel, pixbuf,
                          file_content, file_length, filename,
                          (double)width / (double)height,
                          type,
                          x1, y1+height, x1+width, y1,
                          angle, mirrored, embedded);

  /* Don't free file_content, it is now owned by the picture object */

  return new_obj;
}
/*! \brief Create picture OBJECT from character string.
 *  \par Function Description
 *  Parses \a first_line and subsequent lines from \a tb, and returns
 *  a newly-created picture #OBJECT.
 *
 *  \param [in]  toplevel       The TOPLEVEL object.
 *  \param [in]  first_line      Character string with picture description.
 *  \param [in]  tb              Text buffer to load embedded data from.
 *  \param [in]  release_ver     libgeda release version number.
 *  \param [in]  fileformat_ver  libgeda file format version number.
 *  \return A pointer to the new picture object, or NULL on error.
 */
OBJECT *o_picture_read (TOPLEVEL *toplevel,
                        const char *first_line,
                        TextBuffer *tb,
                        unsigned int release_ver,
                        unsigned int fileformat_ver,
                        GError **err)
{
  OBJECT *new_obj;
  int x1, y1;
  int width, height, angle;
  int mirrored, embedded;
  int num_conv;
  gchar type;
  const gchar *line = NULL;
  gchar *filename;
  gchar *file_content = NULL;
  guint file_length = 0;

  num_conv = sscanf(first_line, "%c %d %d %d %d %d %d %d\n",
                    &type, &x1, &y1, &width, &height, &angle, &mirrored, &embedded);

  if (num_conv != 8) {
    g_set_error(err, EDA_ERROR, EDA_ERROR_PARSE, _("Failed to parse picture definition"));
    return NULL;
  }

  if (width == 0 || height == 0) {
    s_log_message(_("Found a zero width/height picture "
                    "[ %1$c %2$d %3$d %4$d %5$d ]"),
                  type, x1, y1, width, height);
  }

  if ( (mirrored > 1) || (mirrored < 0)) {
    s_log_message(_("Found a picture with a wrong 'mirrored' parameter: %1$d."),
                  mirrored);
    s_log_message(_("Setting mirrored to 0."));
    mirrored = 0;
  }

  if ( (embedded > 1) || (embedded < 0)) {
    s_log_message(_("Found a picture with a wrong 'embedded' parameter: %1$d."),
                  embedded);
    s_log_message(_("Setting embedded to 0."));
    embedded = 0;
  }

  switch(angle) {

    case(0):
    case(90):
    case(180):
    case(270):
    break;

    default:
      s_log_message(_("Found an unsupported picture angle [ %1$d ]"), angle);
      s_log_message(_("Setting angle to 0."));
      angle=0;
      break;

  }

  filename = g_strdup(s_textbuffer_next_line(tb));
  filename = geda_string_remove_ending_newline (filename);

  /* Handle empty filenames */
  if (strlen (filename) == 0) {
    s_log_message (_("Found an image with no filename."));
    g_free (filename);
    filename = NULL;
  }

  if (embedded == 1) {
    GString *encoded_picture=g_string_new("");
    char finished = 0;

    /* Read the encoded picture */
    do {

      line = s_textbuffer_next_line(tb);
      if (line == NULL) break;

      if (strcmp (line, ".\n") != 0) {
        encoded_picture = g_string_append (encoded_picture, line);
      } else {
        finished = 1;
      }
    } while (finished == 0);

    /* Decode the picture */
    if (encoded_picture != NULL) {
      file_content = s_encoding_base64_decode(encoded_picture->str,
                                              encoded_picture->len,
                                              &file_length);
      g_string_free (encoded_picture, TRUE);
    }

    if (file_content == NULL) {
      s_log_message (_("Failed to load image from embedded data [%1$s]: %2$s"),
                     filename, _("Base64 decoding failed."));
      s_log_message (_("Falling back to file loading. Picture unembedded."));
      embedded = 0;
    }
  }

  /* create the picture */
  /* The picture is described by its upper left and lower right corner */
  new_obj = o_picture_new (toplevel, file_content, file_length, filename,
                           type,
                           x1, y1+height, x1+width, y1,
                           angle, mirrored, embedded);

  g_free (file_content);
  g_free (filename);

  return new_obj;
}
Exemple #7
0
/*! \brief read a text object from a char buffer
 *  \par Function Description
 *  This function reads a text object from the textbuffer \a tb and
 *  the text starting with the line \a firstline.
 *  If the line object was read successfully, a new object is
 *  create and appended to the \a object_list.
 *
 *  \param [in] toplevel     The TOPLEVEL object
 *  \param [in] first_line   the first line of the text
 *  \param [in] tb           a text buffer (usually a line of a schematic file)
 *  \param [in] release_ver  The release number gEDA
 *  \param [in] fileformat_ver a integer value of the file format
 *  \return The object list, or NULL on error.
 */
OBJECT*
o_text_read (TOPLEVEL *toplevel,
             const char *first_line,
             TextBuffer *tb,
             unsigned int release_ver,
             unsigned int fileformat_ver,
             GError **err)
{
  OBJECT *new_obj;
  char type;
  int x, y;
  int color;
  int size;
  int visibility;
  int show_name_value;
  int angle;
  int alignment;
  int num_lines = 0;
  int i;
  char* string = NULL;
  GString *textstr;

  if (fileformat_ver >= 1) {
    if (sscanf(first_line, "%c %d %d %d %d %d %d %d %d %d\n", &type, &x, &y,
	       &color, &size,
	       &visibility, &show_name_value,
	       &angle, &alignment, &num_lines) != 10) {
      g_set_error(err, EDA_ERROR, EDA_ERROR_PARSE, _("Failed to parse text object"));
      return NULL;
    }
  } else if (release_ver < VERSION_20000220) {
    /* yes, above less than (not less than and equal) is correct. The format */
    /* change occurred in 20000220 */
    if (sscanf(first_line, "%c %d %d %d %d %d %d %d\n", &type, &x, &y,
	       &color, &size,
	       &visibility, &show_name_value,
	       &angle) != 8) {
      g_set_error(err, EDA_ERROR, EDA_ERROR_PARSE, _("Failed to parse text object"));
      return NULL;
    }
    alignment = LOWER_LEFT; /* older versions didn't have this */
    num_lines = 1; /* only support a single line */
  } else {
    if (sscanf(first_line, "%c %d %d %d %d %d %d %d %d\n", &type, &x, &y,
	       &color, &size,
	       &visibility, &show_name_value,
           &angle, &alignment) != 9) {
      g_set_error (err, EDA_ERROR, EDA_ERROR_PARSE, _("Failed to parse text object"));
      return NULL;
    }
    num_lines = 1; /* only support a single line */
  }

  if (size < MINIMUM_TEXT_SIZE) {
    s_log_message (_("Found an invalid text size [ %1$s ]"), first_line);
    size = DEFAULT_TEXT_SIZE;
    s_log_message (_("Setting text size to %1$d."), size);
  }

  if (!geda_angle_is_ortho (angle)) {
    s_log_message (_("Found an unsupported text angle [ %1$s ]"), first_line);
    angle = geda_angle_make_ortho (angle);
    s_log_message (_("Setting angle to %1$d."), angle);
  }

  switch(alignment) {
    case(LOWER_LEFT):
    case(MIDDLE_LEFT):
    case(UPPER_LEFT):
    case(LOWER_MIDDLE):
    case(MIDDLE_MIDDLE):
    case(UPPER_MIDDLE):
    case(LOWER_RIGHT):
    case(MIDDLE_RIGHT):
    case(UPPER_RIGHT):

    break;

    default:
      s_log_message (_("Found an unsupported text alignment [ %1$s ]"),
                     first_line);
      alignment = LOWER_LEFT;
      s_log_message(_("Setting alignment to LOWER_LEFT."));
      break;
  }

  if (color < 0 || color > MAX_COLORS) {
    s_log_message(_("Found an invalid color [ %1$s ]"), first_line);
    color = DEFAULT_COLOR;
    s_log_message(_("Setting color to default color."));
  }

  g_assert(num_lines && num_lines > 0);

  textstr = g_string_new ("");
  for (i = 0; i < num_lines; i++) {
    const gchar *line;

    line = s_textbuffer_next_line (tb);

    if (line == NULL) {
      g_string_free (textstr, TRUE);
      g_set_error(err, EDA_ERROR, EDA_ERROR_PARSE, _("Unexpected end-of-file after %1$d lines"), i);
      return NULL;
    }

    textstr = g_string_append (textstr, line);
  }
  /* retrieve the character string from the GString */
  string = g_string_free (textstr, FALSE);

  string = geda_string_remove_ending_newline (string);

  /* convert the character string to UTF-8 if necessary */
  if (!g_utf8_validate (string, -1, NULL)) {
    /* if it is not utf-8, it is ISO_8859-15 */
    gchar *tmp = g_convert (string, strlen (string),
                            "UTF-8", "ISO_8859-15",
                            NULL, NULL, NULL);
    if (tmp == NULL) {
      fprintf (stderr, "Failed to convert text string to UTF-8: %1$s.\n",
               string);
    } else {
      /* successfully converted string, now use tmp as string */
      g_free (string);
      string = tmp;
    }
  }

  new_obj = geda_text_object_new (toplevel,
                                  color,
                                  x,
                                  y,
                                  alignment,
                                  angle,
                                  string,
                                  size,
                                  visibility,
                                  show_name_value);
  g_free(string);

  return new_obj;
}