[Author Prev][Author Next][Thread Prev][Thread Next][Author Index][Thread Index]
gEDA-cvs: CVS update: Makefile.am
User: ahvezda
Date: 06/07/04 23:13:40
Modified: . Makefile.am
Added: . a_basic.c f_basic.c f_image.c f_print.c g_basic.c
g_rc.c g_register.c g_smob.c gdk-pixbuf-hacks.c
i_vars.c libgeda.c m_basic.c o_arc_basic.c
o_attrib.c o_basic.c o_box_basic.c o_bus_basic.c
o_circle_basic.c o_complex_basic.c o_image.c
o_line_basic.c o_list.c o_net_basic.c o_picture.c
o_pin_basic.c o_selection.c o_text_basic.c
s_attrib.c s_basic.c s_clib.c s_color.c s_conn.c
s_cue.c s_encoding.c s_hierarchy.c s_log.c s_menu.c
s_page.c s_papersizes.c s_slib.c s_stretch.c
s_tile.c s_toplevel.c s_undo.c u_basic.c
Log:
First checkin to new gaf toplevel directory. Integrated noweb removal
patch by Jason Childs.
Revision Changes Path
1.56 +14 -32 eda/geda/gaf/libgeda/src/Makefile.am
(In the diff below, changes in quantity of whitespace are not shown.)
Index: Makefile.am
===================================================================
RCS file: /home/cvspsrv/cvsroot/eda/geda/gaf/libgeda/src/Makefile.am,v
retrieving revision 1.55
retrieving revision 1.56
diff -u -b -r1.55 -r1.56
--- Makefile.am 21 May 2006 13:19:56 -0000 1.55
+++ Makefile.am 5 Jul 2006 03:13:38 -0000 1.56
@@ -1,18 +1,14 @@
-# $Id: Makefile.am,v 1.55 2006/05/21 13:19:56 werner Exp $
+# $Id: Makefile.am,v 1.56 2006/07/05 03:13:38 ahvezda Exp $
#
# NOTE: Don't forget that in the libtool distribution, files in this
# directory are distributed by the demo_distfiles variable in the top
# level Makefile.
AUTOMAKE_OPTIONS = foreign
-NOTANGLE= @NOTANGLE@
-NOTANGLEROOT= @NOTANGLEROOT@
-NOTANGLEFLAGS= @NOTANGLEFLAGS@
-
INDENTBIN= @INDENT@
INDENTFLAG= -kr -i2
-VPATH = ../noweb:../include:src
+VPATH = ../include:src
if CCISGCC
AM_CFLAGS = -Wall
@@ -21,39 +17,26 @@
# Build a libtool library, libhello.la for installation in libdir.
lib_LTLIBRARIES = libgeda.la
-BUILT_SOURCES = \
- a_basic.nw f_basic.nw f_print.nw f_image.nw g_basic.nw m_basic.nw \
- o_arc_basic.nw o_attrib.nw o_basic.nw o_box_basic.nw \
- o_circle_basic.nw o_complex_basic.nw o_line_basic.nw o_list.nw \
- o_net_basic.nw o_selection.nw o_bus_basic.nw o_text_basic.nw \
- o_pin_basic.nw o_image.nw u_basic.nw s_attrib.nw s_basic.nw \
- s_clib.nw s_encoding.nw s_hierarchy.nw s_papersizes.nw s_stretch.nw \
- s_log.nw \
- s_page.nw s_slib.nw s_color.nw s_undo.nw s_conn.nw \
- s_cue.nw s_tile.nw s_menu.nw s_toplevel.nw g_smob.nw libgeda.nw \
- g_register.nw g_rc.nw i_vars.nw o_picture.nw gdk-pixbuf-hacks.nw
-
-libgeda_la_SOURCES = $(BUILT_SOURCES:.nw=.c)
+libgeda_la_SOURCES = \
+ a_basic.c f_basic.c f_print.c f_image.c g_basic.c m_basic.c \
+ o_arc_basic.c o_attrib.c o_basic.c o_box_basic.c \
+ o_circle_basic.c o_complex_basic.c o_line_basic.c o_list.c \
+ o_net_basic.c o_selection.c o_bus_basic.c o_text_basic.c \
+ o_pin_basic.c o_image.c u_basic.c s_attrib.c s_basic.c \
+ s_clib.c s_encoding.c s_hierarchy.c s_papersizes.c s_stretch.c \
+ s_log.c \
+ s_page.c s_slib.c s_color.c s_undo.c s_conn.c \
+ s_cue.c s_tile.c s_menu.c s_toplevel.c g_smob.c libgeda.c \
+ g_register.c g_rc.c i_vars.c o_picture.c gdk-pixbuf-hacks.c
INCLUDES = -I$(top_srcdir)/include @LIBGEDA_CFLAGS@
libgeda_la_LDFLAGS = @LIBTOOL_FLAGS@ @LIBGEDA_LDFLAGS@
-
EXTRA_DIST = create_proto
-TEXIFILES = $(BUILT_SOURCES:.nw=.texi)
-
src: $(libgeda_la_SOURCES)
@echo Finished building the C source
-SUFFIXES = .nw
-
-.nw.c:
- $(NOTANGLE) $(NOTANGLEFLAGS) $(NOTANGLEROOT)'$@ : *' $< > ../src/$@.tmp
- mv -f ../src/$@.tmp ../src/$@
-# $(INDENTBIN) $(INDENTFLAG) ../src/$@
- rm -f ../src/$@~
-
CPROTO = cproto
CPROTOCFLAGS = $(INCLUDES) -I. -I.. -I../include
ALES_HACK = -D__GNUC__
@@ -69,8 +52,7 @@
CLEANFILES = *.log core FILE *~ prototype.bak
DISTCLEANFILES = *.log core FILE *~ prototype.bak
MAINTAINERCLEANFILES = *.log core FILE *~ prototype.bak prototype.h \
- Makefile.in configure \
- *.c
+ Makefile.in configure
# Unfortunately, in order to test libtool thoroughly, we need access
# to its private directory.
1.19 +478 -347 eda/geda/gaf/libgeda/src/a_basic.c
(In the diff below, changes in quantity of whitespace are not shown.)
Index: a_basic.c
===================================================================
RCS file: a_basic.c
diff -N a_basic.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ a_basic.c 5 Jul 2006 03:13:38 -0000 1.19
@@ -0,0 +1,572 @@
+/* gEDA - GPL Electronic Design Automation
+ * libgeda - gEDA's library
+ * Copyright (C) 1998-2000 Ales V. Hvezda
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+#include <config.h>
+
+#include <stdio.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <libguile.h>
+
+#include "defines.h"
+#include "struct.h"
+#include "globals.h"
+#include "o_types.h"
+#include "colors.h"
+
+#include "../include/prototype.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+/*! \brief Current version string */
+#define VERSION_20020825 20020825
+
+/*! \brief Save embedded attributes to current file
+ * \par Function Description
+ * This function will save all embedded attributes to a file.
+ *
+ * \param [in,out] w_current
+ * \param [in] object_list The list of attributes to write to file
+ * \param [in] fp The file to write to.
+ */
+void o_save_embedded(TOPLEVEL *w_current, OBJECT *object_list, FILE *fp)
+{
+ OBJECT *o_current=NULL;
+ char *out;
+
+ /* make sure you init net_consolide to false (default) in all */
+ /* programs */
+ if (w_current->net_consolidate == TRUE) {
+ o_net_consolidate(w_current);
+ }
+
+ o_current = object_list;
+
+ while ( o_current != NULL ) {
+
+ if (o_current->type != OBJ_HEAD) {
+
+ if (o_current->attribute == 0) {
+
+ switch (o_current->type) {
+
+ case(OBJ_LINE):
+ out = (char *) o_line_save(o_current);
+ break;
+
+ case(OBJ_NET):
+ out = (char *) o_net_save(o_current);
+ break;
+
+ case(OBJ_BUS):
+ out = (char *) o_bus_save(o_current);
+ break;
+
+ case(OBJ_BOX):
+ out = (char *) o_box_save(o_current);
+ break;
+
+ case(OBJ_CIRCLE):
+ out = (char *) o_circle_save(o_current);
+ break;
+
+ case(OBJ_COMPLEX):
+ out = (char *) o_complex_save(o_current);
+ if (strncmp(o_current->complex_clib, "EMBEDDED", 8) == 0) {
+ fprintf(fp, "[\n");
+
+ o_save_embedded(
+ w_current,
+ o_current->
+ complex->prim_objs,
+ fp);
+
+ fprintf(fp, "]\n");
+ }
+ break;
+
+ case(OBJ_PLACEHOLDER): /* new type by SDB 1.20.2005 */
+ out = (char *) o_complex_save(o_current);
+ break;
+
+ case(OBJ_TEXT):
+ out = (char *) o_text_save(o_current);
+ break;
+
+ case(OBJ_PIN):
+ out = (char *) o_pin_save(o_current);
+ break;
+
+ case(OBJ_ARC):
+ out = (char *) o_arc_save(o_current);
+ break;
+
+ case(OBJ_PICTURE):
+ out = (char *) o_picture_save(o_current);
+ break;
+
+ default:
+ fprintf(stderr, "Error type!\n");
+ exit(-1);
+ break;
+ }
+
+ /* output the line */
+ fprintf(fp, "%s\n", out);
+ free(out);
+
+ /* save those attributes */
+ if (o_current->attribs != NULL) {
+ if (o_current->attribs->next != NULL) {
+ o_save_attribs(fp, o_current->attribs->next);
+ }
+ }
+
+ }
+ }
+ o_current = o_current->next;
+ }
+}
+
+/*! \brief Write libgeda file header
+ * \par Function Description
+ * This function simply prints the VERSION and FILEFORMAT_VERSION
+ * definitions to the file.
+ *
+ * \param [in] fp The file to write the header to.
+ */
+void o_save_write_header(FILE *fp)
+{
+ fprintf(fp, "v %s %u\n", VERSION, FILEFORMAT_VERSION);
+}
+
+/*! \brief Save a file
+ * \par Function Description
+ * This function saves the data in a libgeda format to a file
+ * \param [in] w_current The data to save to file.
+ * \param [in] filename The filename to save the data to.
+ * \return 1 on success, 0 on failure.
+ */
+int o_save(TOPLEVEL *w_current, const char *filename)
+{
+ OBJECT *o_current=NULL;
+ FILE *fp;
+ char *out;
+ int already_wrote=0;
+
+ fp = fopen(filename, "w");
+
+ if (fp == NULL) {
+ s_log_message("o_save: Could not open [%s]\n", filename);
+ return 0;
+ }
+
+
+ o_current = w_current->page_current->object_head;
+
+ /* make sure you init net_consolide to false (default) in all */
+ /* programs */
+ if (w_current->net_consolidate == TRUE) {
+ o_net_consolidate(w_current);
+ }
+
+ o_save_write_header(fp);
+
+ while ( o_current != NULL ) {
+
+ if (o_current->type != OBJ_HEAD) {
+
+ if (o_current->attribute == 0) {
+
+ switch (o_current->type) {
+
+ case(OBJ_LINE):
+ out = (char *) o_line_save(o_current);
+ break;
+
+ case(OBJ_NET):
+ out = (char *) o_net_save(o_current);
+ break;
+
+ case(OBJ_BUS):
+ out = (char *) o_bus_save(o_current);
+ break;
+
+ case(OBJ_BOX):
+ out = (char *) o_box_save(o_current);
+ break;
+
+ case(OBJ_CIRCLE):
+ out = (char *) o_circle_save(o_current);
+ break;
+
+ case(OBJ_COMPLEX):
+ out = (char *) o_complex_save(o_current);
+ fprintf(fp, "%s\n", out);
+ already_wrote=1;
+ if (strncmp(o_current->complex_clib, "EMBEDDED", 8) == 0) {
+ fprintf(fp, "[\n");
+
+ o_save_embedded(
+ w_current,
+ o_current->
+ complex->prim_objs,
+ fp);
+
+ fprintf(fp, "]\n");
+ }
+ break;
+
+ case(OBJ_PLACEHOLDER): /* new type by SDB 1.20.2005 */
+ out = (char *) o_complex_save(o_current);
+ break;
+
+ case(OBJ_TEXT):
+ out = (char *) o_text_save(o_current);
+ break;
+
+ case(OBJ_PIN):
+ out = (char *) o_pin_save(o_current);
+ break;
+
+ case(OBJ_ARC):
+ out = (char *) o_arc_save(o_current);
+ break;
+
+ case(OBJ_PICTURE):
+ out = (char *) o_picture_save(o_current);
+ break;
+
+ default:
+ fprintf(stderr, "Error type!\n");
+ exit(-1);
+ break;
+ }
+
+ /* output the line */
+ if (!already_wrote) {
+ fprintf(fp, "%s\n", out);
+ free(out);
+ } else {
+ already_wrote=0;
+ }
+
+ /* save those attributes */
+ if (o_current->attribs != NULL) {
+ if (o_current->attribs->next != NULL) {
+ o_save_attribs(fp, o_current->attribs->next);
+ }
+ }
+
+ }
+ }
+ o_current = o_current->next;
+ }
+
+ fclose(fp);
+ return 1;
+}
+
+/*! \brief Read a file
+ * \par Function Description
+ * This function reads a file in libgead format.
+ *
+ * \param [in,out] w_current The current TOPLEVEL structure.
+ * \param [in] object_list The object_list to read data to.
+ * \param [in] filename The filename to read from.
+ * \return object_list if successful read, or NULL on error.
+ */
+OBJECT *o_read(TOPLEVEL *w_current, OBJECT *object_list, char *filename)
+{
+ FILE *fp;
+ char buf[1024];
+ char objtype;
+ OBJECT *object_list_save=NULL;
+ OBJECT *temp_tail=NULL;
+ OBJECT *temp_parent=NULL;
+ OBJECT *object_before_attr=NULL;
+ unsigned int release_ver;
+ unsigned int fileformat_ver;
+ unsigned int current_fileformat_ver;
+ int found_pin = 0;
+ OBJECT* last_complex = NULL;
+ int itemsread = 0;
+
+ /* fill version with default file format version (the current one) */
+ current_fileformat_ver = FILEFORMAT_VERSION;
+
+ fp = fopen(filename, "r");
+
+ if (fp == NULL) {
+ s_log_message("o_read: Could not open [%s]\n", filename);
+ return(NULL);
+ }
+
+ while ( fgets(buf, 1024, fp) != NULL) {
+
+ sscanf(buf, "%c", &objtype);
+
+ /* Do we need to check the symbol version? Yes, but only if */
+ /* 1) the last object read was a complex and */
+ /* 2) the next object isn't the start of attributes. */
+ /* If the next object is the start of attributes, then check the */
+ /* symbol version after the attributes have been read in, see the */
+ /* STARTATTACH_ATTR case */
+ if (last_complex && objtype != STARTATTACH_ATTR)
+ {
+ /* yes */
+ /* verify symbol version (not file format but rather contents) */
+ o_complex_check_symversion(w_current, last_complex);
+ last_complex = NULL; /* no longer need to check */
+ }
+
+ switch (objtype) {
+
+ case(OBJ_LINE):
+ object_list = (OBJECT *) o_line_read(w_current, object_list, buf,
+ release_ver, fileformat_ver);
+ break;
+
+
+ case(OBJ_NET):
+ object_list = (OBJECT *) o_net_read(w_current, object_list, buf,
+ release_ver, fileformat_ver);
+ break;
+
+ case(OBJ_BUS):
+ object_list = (OBJECT *) o_bus_read(w_current, object_list, buf,
+ release_ver, fileformat_ver);
+ break;
+
+ case(OBJ_BOX):
+ object_list = (OBJECT *) o_box_read(w_current, object_list, buf,
+ release_ver, fileformat_ver);
+ break;
+
+ case(OBJ_PICTURE):
+ object_list = (OBJECT *) o_picture_read(w_current, object_list, buf,
+ fp,
+ release_ver, fileformat_ver);
+ break;
+
+ case(OBJ_CIRCLE):
+ object_list = (OBJECT *) o_circle_read(w_current, object_list, buf,
+ release_ver, fileformat_ver);
+ break;
+
+ case(OBJ_COMPLEX):
+ case(OBJ_PLACEHOLDER):
+ object_list = (OBJECT *) o_complex_read(w_current, object_list, buf,
+ release_ver, fileformat_ver);
+
+ /* this is necessary because complex may add attributes which float */
+ /* needed now? */
+ object_list = (OBJECT *) return_tail(object_list);
+
+ /* last_complex is used for verifying symversion attribute */
+ last_complex = object_list;
+ break;
+
+ case(OBJ_TEXT):
+ /* fgets(string, 1024, fp); string lines are now read inside: */
+ object_list = (OBJECT *) o_text_read(w_current, object_list, buf,
+ fp,
+ release_ver, fileformat_ver);
+ break;
+
+ case(OBJ_PIN):
+ object_list = (OBJECT *) o_pin_read(w_current, object_list, buf,
+ release_ver, fileformat_ver);
+ found_pin++;
+ break;
+
+ case(OBJ_ARC):
+ object_list = (OBJECT *) o_arc_read(w_current, object_list, buf,
+ release_ver, fileformat_ver);
+ break;
+
+ case(STARTATTACH_ATTR):
+ object_before_attr = object_list;
+ /* first is the fp */
+ /* 2nd is the object to get the attributes */
+ object_list = (OBJECT *) o_read_attribs(w_current, fp, object_list,
+ release_ver, fileformat_ver);
+
+ /* by now we have finished reading all the attributes */
+ /* did we just finish attaching to a complex object? */
+ if (last_complex)
+ {
+ /* yes */
+ /* verify symbol version (not file format but rather contents) */
+ o_complex_check_symversion(w_current, last_complex);
+ last_complex = NULL;
+ }
+
+ /* slots only apply to complex objects */
+ if (object_before_attr->type == OBJ_COMPLEX ||
+ object_before_attr->type == OBJ_PLACEHOLDER) {
+ o_attrib_slot_update(w_current, object_before_attr);
+ }
+
+ /* need this? nope */
+ /*object_list = return_tail(object_list);*/
+ object_before_attr = NULL;
+ break;
+
+ case(START_EMBEDDED):
+ object_list_save = object_list;
+ object_list = object_list_save->complex->
+ prim_objs;
+
+ temp_tail =
+ w_current->page_current->object_tail;
+ temp_parent =
+ w_current->page_current->object_parent;
+ w_current->page_current->object_parent =
+ object_list;
+ break;
+
+ case(END_EMBEDDED):
+ object_list = object_list_save;
+ /* don't do this since objects are already
+ * stored/read translated
+ * o_complex_world_translate(w_current, object_list->x,
+ * object_list->y, object_list->complex);
+ */
+ w_current->page_current->object_tail = temp_tail;
+ w_current->page_current->object_parent = temp_parent;
+ break;
+
+ case(ENDATTACH_ATTR):
+ /* this case is never hit, since the } is consumed by o_read_attribs */
+ break;
+
+ case(INFO_FONT):
+ o_text_set_info_font(buf);
+ break;
+
+ case(COMMENT):
+ /* do nothing */
+ break;
+
+ case(VERSION_CHAR):
+ itemsread = sscanf(buf, "v %u %u\n", &release_ver, &fileformat_ver);
+
+ /* 20030921 was the last version which did not have a fileformat */
+ /* version. The below latter test should not happen, but it is here */
+ /* just in in case. */
+ if (release_ver <= VERSION_20030921 || itemsread == 1)
+ {
+ fileformat_ver = 0;
+ }
+
+ if (fileformat_ver < current_fileformat_ver)
+ {
+ s_log_message("Read an old format sym/sch file!\n"
+ "Please run g[sym|sch]update on:\n[%s]\n", filename);
+ }
+ break;
+
+ default:
+ fprintf(stderr, "Read garbage in [%s] :\n>>\n%s<<\n",
+ filename, buf);
+ break;
+ }
+
+ }
+ fclose(fp);
+
+ /* Was the very last thing we read a complex and has it not been checked */
+ /* yet? This would happen if the complex is at the very end of the file */
+ /* and had no attached attributes */
+ if (last_complex)
+ {
+ o_complex_check_symversion(w_current, last_complex);
+ last_complex = NULL; /* no longer need to check */
+ }
+
+ if (found_pin) {
+ if (release_ver <= VERSION_20020825) {
+ o_pin_update_whichend(w_current, return_head(object_list), found_pin);
+ }
+ }
+
+ return(object_list);
+}
+
+/*! \brief Scale a set of lines.
+ * \par Function Description
+ * This function takes a list of lines and scales them
+ * by the values of x_scale and y_scale.
+ *
+ * \param [in] w_current The current TOPLEVEL object.
+ * \param [in,out] list The list with lines to scale.
+ * \param [in] x_scale The x scale value for the lines.
+ * \param [in] y_scale The y scale value for the lines.
+ *
+ * \todo this really doesn't belong here. you need more of a core routine
+ * first. yes.. this is the core routine, just strip out the drawing
+ * stuff
+ * move it to o_complex_scale
+ */
+void o_scale(TOPLEVEL *w_current, OBJECT *list, int x_scale, int y_scale)
+{
+ OBJECT *o_current;
+
+ /* this is okay if you just hit scale and have nothing selected */
+ if (list == NULL) {
+ /* w_current->event_state = SELECT;*/
+ /* i_update_status(w_current, "Select Mode"); not here */
+ /* w_current->inside_action = 0;*/
+ return;
+ }
+
+
+ o_current = list;
+
+
+ while (o_current != NULL) {
+
+ switch(o_current->type) {
+
+ case(OBJ_LINE):
+ /* erase the current selection */
+ w_current->override_color =
+ w_current->background_color;
+ o_redraw_single(w_current, o_current);
+ /* o_line_draw(w_current, o_current);*/
+ w_current->override_color = -1;
+
+ o_line_scale_world(w_current,
+ x_scale, y_scale, o_current);
+ break;
+ }
+
+ o_current = o_current->next;
+ }
+
+ /* don't do this at this level */
+ /* w_current->page_current->CHANGED=1;*/
+}
+
+
1.18 +443 -50 eda/geda/gaf/libgeda/src/f_basic.c
(In the diff below, changes in quantity of whitespace are not shown.)
Index: f_basic.c
===================================================================
RCS file: f_basic.c
diff -N f_basic.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ f_basic.c 5 Jul 2006 03:13:38 -0000 1.18
@@ -0,0 +1,489 @@
+/* gEDA - GPL Electronic Design Automation
+ * libgeda - gEDA's library
+ * Copyright (C) 1998-2000 Ales V. Hvezda
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+#include <config.h>
+
+#include <stdio.h>
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <sys/param.h>
+#include <stdlib.h>
+#include <time.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include <gtk/gtk.h>
+#include <libguile.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include "defines.h"
+#include "struct.h"
+#include "globals.h"
+
+#include "../include/prototype.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+/*! \brief Opens the schematic file.
+ * \par Function Description
+ * Opens the schematic file. Before it reads the schematic, it tries to
+ * open and read the local gafrc file.
+ *
+ * \param [in,out] w_current The TOPLEVEL object to load the schematic into.
+ * \param [in] filename A character string containing the file name
+ * to open.
+ * \return 0 on failure, 1 on success.
+ */
+int f_open(TOPLEVEL *w_current, char *filename)
+{
+ int opened=FALSE;
+ char *full_filename = NULL;
+ char *full_rcfilename = NULL;
+ char *file_directory = NULL;
+ char *saved_cwd = NULL;
+ char *backup_filename = NULL;
+ char load_backup_file = 0;
+
+ /* has the head been freed yet? */
+ /* probably not hack PAGE */
+
+ set_window(w_current, w_current->page_current,
+ w_current->init_left, w_current->init_right,
+ w_current->init_top, w_current->init_bottom);
+
+
+ /*
+ * If we are only opening a preview window, we don't want to
+ * change the directory. Therefore, if this is only a preview window,
+ * we cache the cwd so we can restore it later.
+ */
+ if (w_current->wid == -1) {
+ saved_cwd = getcwd(NULL, 1024);
+ }
+
+ /* get full, absolute path to file */
+ full_filename = f_normalize_filename(filename);
+
+ /* write full, absolute filename into page_current->page_filename */
+ if (w_current->page_current->page_filename) {
+ free(w_current->page_current->page_filename);
+ }
+ w_current->page_current->page_filename = g_strdup(full_filename);
+
+ /* Before we open the page, let's load the corresponding gafrc. */
+ /* First cd into file's directory. */
+ file_directory = g_dirname (full_filename);
+
+ full_rcfilename = g_strconcat (file_directory,
+ G_DIR_SEPARATOR_S,
+ "gafrc",
+ NULL);
+ if (file_directory) {
+ chdir(file_directory);
+ /* Probably should do some checking of chdir return values */
+ }
+ /* If directory is not found, we should do something . . . . */
+
+ /* Now open RC and process file */
+ g_rc_parse_specified_rc(w_current, full_rcfilename);
+
+ /* Check if there is a newer autosave backup file */
+ backup_filename = g_strdup_printf("%s%c"AUTOSAVE_BACKUP_FILENAME_STRING,
+ file_directory, G_DIR_SEPARATOR,
+ g_path_get_basename(full_filename));
+
+ g_free (file_directory);
+
+ if ( g_file_test (backup_filename, G_FILE_TEST_EXISTS) &&
+ (! g_file_test (backup_filename, G_FILE_TEST_IS_DIR))) {
+ /* An autosave backup file exists. Check if it's newer */
+ struct stat stat_backup;
+ struct stat stat_file;
+ char error_stat = 0;
+ GString *message;
+
+ if (stat (backup_filename, &stat_backup) != 0) {
+ s_log_message ("f_open: Unable to get stat information of backup file %s.",
+ backup_filename);
+ error_stat = 1 ;
+ }
+ if (stat (full_filename, &stat_file) != 0) {
+ s_log_message ("f_open: Unable to get stat information of file %s.",
+ full_filename);
+ error_stat = 1;
+ }
+ if ((difftime (stat_file.st_ctime, stat_backup.st_ctime) < 0) ||
+ (error_stat == 1))
+ {
+ /* Found an autosave backup. It's newer if error_stat is 0 */
+ message = g_string_new ("");
+ g_string_append_printf(message, "\nWARNING: Found an autosave backup file:\n %s.\n\n", backup_filename);
+ if (error_stat == 1) {
+ g_string_append(message, "I could not guess if it is newer, so you have to"
+ "do it manually.\n");
+ }
+ else {
+ g_string_append(message, "The backup copy is newer than the schematic, so it seems you should load it instead of the original file.\n");
+ }
+ g_string_append (message, "Gschem usually makes backup copies automatically, and this situation happens when it crashed or it was forced to exit abruptely.\n");
+ if (w_current->page_current->load_newer_backup_func == NULL) {
+ s_log_message(message->str);
+ s_log_message("\nRun gschem and correct the situation.\n\n");
+ fprintf(stderr, message->str);
+ fprintf(stderr, "\nRun gschem and correct the situation.\n\n");
+ }
+ else {
+ /* Ask the user if load the backup or the original file */
+ if (w_current->page_current->load_newer_backup_func
+ (w_current, message)) {
+ /* Load the backup file */
+ load_backup_file = 1;
+ }
+ }
+ g_string_free (message, TRUE);
+ }
+ }
+
+ /* Now that we have set the current directory and read
+ * the RC file, it's time to read in the file. */
+ if (load_backup_file == 1) {
+ /* Load the backup file */
+ w_current->page_current->object_tail = (OBJECT *)
+ o_read(w_current, w_current->page_current->object_tail,
+ backup_filename);
+ }
+ else {
+ /* Load the original file */
+ w_current->page_current->object_tail = (OBJECT *)
+ o_read(w_current, w_current->page_current->object_tail,
+ full_filename);
+ }
+
+ g_free (backup_filename);
+
+ if (w_current->page_current->object_tail != NULL) {
+ s_log_message("Opened file [%s]\n", full_filename);
+ opened = TRUE;
+
+ } else {
+ /* Failed to open page */
+ opened = FALSE;
+ }
+
+
+ w_current->page_current->object_tail = (OBJECT *)
+ return_tail(w_current->page_current->object_head);
+
+ /* make sure you init net_consolide to false (default) in all */
+ /* programs */
+ if (w_current->net_consolidate == TRUE) {
+ o_net_consolidate(w_current);
+ }
+
+ if (load_backup_file == 0) {
+ /* If it's not the backup file */
+ w_current->page_current->CHANGED=0; /* added 4/7/98 */
+ }
+ else {
+ /* We are loading the backup file, so gschem should ask
+ the user if save it or not when closing the page. */
+ w_current->page_current->CHANGED=1;
+ }
+
+ free(full_filename);
+ free(full_rcfilename);
+
+ /* If this was a preview window, reset the directory to the
+ * value it had when f_open was called. Also get rid of component
+ * libraries opened while opening preview window. If the component
+ * is actually selected, they will be re-read later. */
+ if (w_current->wid == -1) {
+ chdir(saved_cwd);
+ free(saved_cwd);
+ }
+
+ if (!opened) {
+ return (FALSE);
+ } else {
+ return (TRUE);
+ }
+}
+
+/*! \brief Closes the schematic file
+ * \par Function Description
+ * Does nothing
+ *
+ * \param [in,out] w_current The TOPLEVEL object with schematic to be closed.
+ */
+void f_close(TOPLEVEL *w_current)
+{
+
+}
+
+/*! \brief Save schematic file and close
+ * \par Function Description
+ * This function will save the current schematic file before closing it.
+ * It also deletes the page_current item in the TOPLEVEL structure.
+ *
+ * \param [in,out] w_current The TOPLEVEL object containing the schematic.
+ * \param [in] filename The file name to save the schematic to.
+ */
+void f_save_close(TOPLEVEL *w_current, char *filename)
+{
+ o_save(w_current, filename);
+ s_page_delete (w_current, w_current->page_current);
+}
+
+/*! \brief Save the schematic file
+ * \par Function Description
+ * This function saves the current schematic file in the w_current object.
+ *
+ * \param [in,out] w_current The TOPLEVEL object containing the schematic.
+ * \param [in] filename The file name to save the schematic to.
+ * \return 1 on success, 0 on failure.
+ */
+int f_save(TOPLEVEL *w_current, const char *filename)
+{
+ gchar *backup_filename;
+ gchar *real_filename;
+ gchar *only_filename;
+ gchar *dirname;
+ mode_t saved_umask, mask;
+ struct stat st;
+
+ /* Get the real filename and file permissions */
+ real_filename = follow_symlinks (filename, NULL);
+
+ if (real_filename == NULL) {
+ s_log_message ("Can't get the real filename of %s.", filename);
+ fprintf (stderr, "Can't get the real filename of %s.\n", filename);
+ return 0;
+ }
+
+ /* Get the directory in which the real filename lives */
+ dirname = g_path_get_dirname (real_filename);
+ only_filename = g_path_get_basename(real_filename);
+
+ /* Do a backup if it's not an undo file backup and it was never saved. */
+ if (w_current->page_current->saved_since_first_loaded == 0) {
+ if ( (g_file_test (real_filename, G_FILE_TEST_EXISTS)) &&
+ (!g_file_test(real_filename, G_FILE_TEST_IS_DIR)) )
+ {
+ backup_filename = g_strdup_printf("%s%c%s~", dirname,
+ G_DIR_SEPARATOR, only_filename);
+
+ /* Make the backup file read-write before saving a new one */
+ if ( g_file_test (backup_filename, G_FILE_TEST_EXISTS) &&
+ (! g_file_test (backup_filename, G_FILE_TEST_IS_DIR))) {
+ if (chmod(backup_filename, S_IREAD|S_IWRITE) != 0) {
+ s_log_message ("Could NOT set previous backup file [%s] read-write\n",
+ backup_filename);
+ }
+ }
+
+ if (rename(real_filename, backup_filename) != 0) {
+ s_log_message ("Can't save backup file: %s.", backup_filename);
+ fprintf (stderr, "Can't save backup file: %s.", backup_filename);
+ }
+ else {
+ /* Make the backup file readonly so a 'rm *' command will ask
+ the user before deleting it */
+ saved_umask = umask(0);
+ mask = (S_IWRITE|S_IWGRP|S_IEXEC|S_IXGRP|S_IXOTH);
+ mask = (~mask)&0777;
+ mask &= ((~saved_umask) & 0777);
+ if (chmod(backup_filename, mask) != 0) {
+ s_log_message ("Could NOT set backup file [%s] readonly\n",
+ backup_filename);
+ }
+ umask(saved_umask);
+ }
+
+ g_free(backup_filename);
+ }
+ }
+ /* If there is not an existing file with that name, compute the
+ * permissions and uid/gid that we will use for the newly-created file.
+ */
+
+ if (stat (real_filename, &st) != 0)
+ {
+ struct stat dir_st;
+ int result;
+
+ /* Use default permissions */
+ saved_umask = umask(0);
+ st.st_mode = 0666 & ~saved_umask;
+ umask(saved_umask);
+ st.st_uid = getuid ();
+
+ result = stat (dirname, &dir_st);
+
+ if (result == 0 && (dir_st.st_mode & S_ISGID))
+ st.st_gid = dir_st.st_gid;
+ else
+ st.st_gid = getgid ();
+ }
+ g_free (dirname);
+ g_free (only_filename);
+
+ if (o_save(w_current, real_filename)) {
+
+ w_current->page_current->saved_since_first_loaded = 1;
+
+ /* Reset the last saved timer */
+ g_get_current_time (&w_current->page_current->last_load_or_save_time);
+ w_current->page_current->ops_since_last_backup = 0;
+ w_current->page_current->do_autosave_backup = 0;
+
+ /* Restore permissions. */
+ chmod (real_filename, st.st_mode);
+ chown (real_filename, st.st_uid, st.st_gid);
+
+ g_free (real_filename);
+ return 1;
+ }
+ else {
+ g_free (real_filename);
+ return 0;
+ }
+}
+
+/*! \brief Reformats a filename as an absolute resolved filename
+ * \par Function Description
+ * Given a filename in any format, this returns the full, absolute
+ * resolved filename.
+ *
+ * \param [in] filename A character string containing the file
+ * name to resolve.
+ * \return A character string with the resolved filename.
+ */
+char* f_normalize_filename(const gchar *filename)
+{
+ char filename_buffer[MAXPATHLEN]; /* nasty hack for realpath */
+ char *full_filename;
+
+ /* Check for pathological case */
+ if (filename == NULL) {
+ return NULL;
+ }
+
+ realpath(filename, filename_buffer); /* places reult in filename_buffer */
+ full_filename = g_strdup (filename_buffer);
+
+#ifdef DEBUG
+ printf("In f_normalize_filename, returning full_filename= %s \n", full_filename);
+#endif
+
+ return full_filename;
+}
+
+/*! \brief Follow symlinks until a real file is found
+ * \par Function Description
+ * Does readlink() recursively until we find a real filename.
+ *
+ * \param [in] filename The filename to search for.
+ * \param [out] error Unused, set to NULL
+ * \return The path to real file on success, NULL otherwise.
+ *
+ * \note Taken from gedit's source code.
+ */
+char *follow_symlinks (const gchar *filename, GError **error)
+{
+ gchar *followed_filename;
+ gint link_count;
+
+ g_return_val_if_fail (filename != NULL, NULL);
+
+ g_return_val_if_fail (strlen (filename) + 1 <= MAXPATHLEN, NULL);
+
+ followed_filename = g_strdup (filename);
+ link_count = 0;
+
+ while (link_count < MAX_LINK_LEVEL) {
+ struct stat st;
+
+ if (lstat (followed_filename, &st) != 0)
+ /* We could not access the file, so perhaps it does not
+ * exist. Return this as a real name so that we can
+ * attempt to create the file.
+ */
+ return followed_filename;
+
+ if (S_ISLNK (st.st_mode)) {
+ gint len;
+ gchar linkname[MAXPATHLEN];
+
+ link_count++;
+
+ len = readlink (followed_filename, linkname, MAXPATHLEN - 1);
+
+ if (len == -1) {
+ s_log_message("Could not read symbolic link information for %s", followed_filename);
+ fprintf(stderr, "Could not read symbolic link information for %s", followed_filename);
+ g_free (followed_filename);
+ return NULL;
+ }
+
+ linkname[len] = '\0';
+
+ /* If the linkname is not an absolute path name, append
+ * it to the directory name of the followed filename. E.g.
+ * we may have /foo/bar/baz.lnk -> eek.txt, which really
+ * is /foo/bar/eek.txt.
+ */
+
+ if (linkname[0] != G_DIR_SEPARATOR) {
+ gchar *slashpos;
+ gchar *tmp;
+
+ slashpos = strrchr (followed_filename, G_DIR_SEPARATOR);
+
+ if (slashpos)
+ *slashpos = '\0';
+ else {
+ tmp = g_strconcat ("./", followed_filename, NULL);
+ g_free (followed_filename);
+ followed_filename = tmp;
+ }
+
+ tmp = g_build_filename (followed_filename, linkname, NULL);
+ g_free (followed_filename);
+ followed_filename = tmp;
+ } else {
+ g_free (followed_filename);
+ followed_filename = g_strdup (linkname);
+ }
+ } else
+ return followed_filename;
+ }
+
+ /* Too many symlinks */
+
+ s_log_message("The file has too many symbolic links.");
+ fprintf(stderr, "The file has too many symbolic links.");
+
+ return NULL;
+}
1.18 +141 -135 eda/geda/gaf/libgeda/src/f_image.c
(In the diff below, changes in quantity of whitespace are not shown.)
Index: f_image.c
===================================================================
RCS file: f_image.c
diff -N f_image.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ f_image.c 5 Jul 2006 03:13:38 -0000 1.18
@@ -0,0 +1,222 @@
+/* gEDA - GPL Electronic Design Automation
+ * libgeda - gEDA's library
+ * Copyright (C) 1998-2000 Ales V. Hvezda
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+#include <config.h>
+
+#include <stdio.h>
+#include <math.h>
+
+#include <gtk/gtk.h>
+#include <libguile.h>
+
+#ifdef HAS_LIBGDGEDA
+#include <gdgeda/gd.h>
+#endif
+
+#include "defines.h"
+#include "struct.h"
+#include "globals.h"
+#include "o_types.h"
+#include "colors.h"
+
+#include "../include/prototype.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+#ifdef HAS_LIBGDGEDA
+/*! \todo Finish function description!!!
+ * \brief
+ * \par Function Description
+ *
+ * \param [in,out] w_current The TOPLEVEL object to write to.
+ * \param [in,out] head The object to read image from.
+ * \param [in] start_x X Offset to start from.
+ * \param [in] start_y Y Offset to start from.
+ * \param [in] color_mode
+ *
+ * \todo what happens if snap is off? hack deal with this !!!!!!!!
+ */
+void f_image_write_objects(TOPLEVEL *w_current, OBJECT *head,
+ int start_x, int start_y,
+ float scale, int color_mode)
+{
+ OBJECT *o_current=NULL;
+ int origin_x, origin_y;
+
+ if (head == NULL) {
+ return;
+ }
+
+ origin_x = 0;
+ origin_y = 0;
+
+ o_current = head;
+
+
+ while ( o_current != NULL ) {
+
+ if (o_current->type != OBJ_HEAD) {
+
+ switch (o_current->type) {
+ case(OBJ_LINE):
+ o_line_image_write(w_current, o_current,
+ origin_x, origin_y, color_mode);
+ break;
+
+ case(OBJ_PIN):
+ o_pin_image_write(w_current, o_current,
+ origin_x, origin_y, color_mode);
+ break;
+
+ case(OBJ_COMPLEX):
+ case(OBJ_PLACEHOLDER):
+
+ f_image_write_objects(w_current,
+ o_current->complex->prim_objs,
+ origin_x, origin_y, scale, color_mode);
+ break;
+
+ case(OBJ_TEXT):
+ if (o_current->visibility == VISIBLE) {
+
+ /*if (w_current->text_output == VECTOR_FONTS) { */
+ f_image_write_objects(w_current,
+ o_current->text->
+ prim_objs,
+ origin_x, origin_y, scale, color_mode);
+ /*} else {*/
+#if 0
+ o_text_image_write(w_current, fp,
+ o_current,
+ origin_x, origin_y);
+
+ /*}*/
+#endif
+
+ }
+ break;
+
+ case(OBJ_NET):
+ o_net_image_write(w_current, o_current,
+ origin_x, origin_y, color_mode);
+
+ break;
+
+ case(OBJ_BUS):
+ o_bus_image_write(w_current, o_current,
+ origin_x, origin_y, color_mode);
+ break;
+
+ case(OBJ_CIRCLE):
+ o_circle_image_write(w_current,
+ o_current,
+ origin_x, origin_y, color_mode);
+ break;
+
+ case(OBJ_ARC):
+ o_arc_image_write(w_current, o_current,
+ origin_x, origin_y, color_mode);
+ break;
+
+ case(OBJ_BOX):
+ o_box_image_write(w_current, o_current,
+ origin_x, origin_y, color_mode);
+ break;
+
+ case(OBJ_PICTURE):
+ /*! \todo FIXME: Implement this */
+ fprintf(stderr, "f_image_write_objects: o_picture_image_write not implemented yet\n");
+ /* out = NULL; */
+ /* out = (char *) o_picture_image_write(w_current, o_current,
+ origin_x, origin_y, color_mode); */
+ break;
+
+ default:
+ fprintf(stderr, "Error type!\n");
+ exit(-1);
+ break;
+ }
+
+ }
+ o_current = o_current->next;
+ }
+
+ s_cue_output_all(w_current, head, NULL, PNG);
+
+ return;
+}
+#endif
+
+/*! \todo Finish function description!!!
+ * \brief Write image to file from w_current
+ * \par Function Description
+ *
+ * \param [in,out] w_current The TOPLEVEL object to read image from.
+ * \param [in] filename The name of the file to write image to.
+ * \param [in] width The width of the image to write
+ * \param [in] height The height of the image to write
+ * \param [in] color_mode
+ */
+void f_image_write(TOPLEVEL *w_current, const char *filename,
+ int width, int height,
+ int color_mode)
+{
+
+#ifdef HAS_LIBGDGEDA
+ int origin_x, origin_y, bottom, right;
+ float scale=0.0;
+
+ /* dots are breaking my filename selection hack hack !!!! */
+
+
+ /* printf("%d %d\n", w_current->paper_width, w_current->paper_height);*/
+
+ world_get_complex_bounds(w_current,
+ w_current->page_current->object_head,
+ &origin_x, &origin_y,
+ &right, &bottom);
+
+ o_image_create(width, height, color_mode);
+
+ f_image_write_objects(w_current,
+ w_current->page_current->object_head,
+ w_current->page_current->left,
+ w_current->page_current->top, scale, color_mode);
+
+ o_image_write(filename);
+ o_image_close();
+#else
+ fprintf(stderr, "f_image_write: Called this function without libgdgeda support.\n");
+ s_log_message("f_image_write: Called this function without libgdgeda support.\n");
+#endif
+
+}
+
+/*! \brief Sets the image output type
+ * \par Function Description
+ * This function will set the image output type in the TOPLEVEL object.
+ *
+ * \param [in,out] w_current The TOPLEVEL object to set image type in.
+ * \param [in] type The image type to set
+ */
+void f_image_set_type(TOPLEVEL *w_current, int type)
+{
+ w_current->image_output_type = type;
+}
1.23 +5001 -405 eda/geda/gaf/libgeda/src/f_print.c
(In the diff below, changes in quantity of whitespace are not shown.)
Index: f_print.c
===================================================================
RCS file: f_print.c
diff -N f_print.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ f_print.c 5 Jul 2006 03:13:38 -0000 1.23
@@ -0,0 +1,5081 @@
+/* gEDA - GPL Electronic Design Automation
+ * libgeda - gEDA's library
+ * Copyright (C) 1998-2000 Ales V. Hvezda
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+#include <config.h>
+
+#include <stdio.h>
+#include <unistd.h>
+#include <time.h>
+#include <math.h>
+
+#include <gtk/gtk.h>
+#include <libguile.h>
+
+#include "defines.h"
+#include "struct.h"
+#include "globals.h"
+#include "o_types.h"
+#include "funcs.h"
+#include "colors.h"
+
+#include "../include/prototype.h"
+
+/*! \brief Hashtable storing mapping between character and
+ * postscript glyph name
+ */
+GHashTable *unicode_char_to_glyph = NULL;
+
+static int f_print_get_unicode_chars(TOPLEVEL * w_current, OBJECT * head,
+ int count, gunichar * table);
+static void f_print_unicode_map(FILE * fp, int count, gunichar * table);
+
+/*! \brief Prints the line width in mils to a postscript document.
+ * \par Function Description
+ * This function writes the line width in mils to the specified
+ * postscript document.
+ *
+ * \param [in] fp The postscript document to write to.
+ * \param [in] width The width of the line in mils to set.
+ */
+void f_print_set_line_width(FILE *fp, int width)
+{
+ if (width > 0) {
+ fprintf(fp, "%d mils setlinewidth\n", width);
+ }
+}
+
+/*! \brief Prints the color to a postscript document
+ * \par Function Description
+ * This function converts the color number passed to a string
+ * and prints it to the postscript document provided.
+ *
+ * \param [in] fp The postscript document to print the color to.
+ * \param [in] color Integer color to convert and print.
+ */
+void f_print_set_color(FILE *fp, int color)
+{
+ char *string;
+
+ /* DO NOT free string... it's a reference to a malloced */
+ /* string, there is *no* memory leak here */
+ string = s_color_ps_string(color);
+
+ if (string) {
+ fprintf(fp, "%s setrgbcolor\n", string);
+ } else {
+ fprintf(fp, "0 0 0 setrgbcolor\n");
+ }
+}
+
+/*! \brief Prints the header to a postscript document.
+ * \par Function Description
+ * This function will print a document preamble and header
+ * for a postscript document.
+ *
+ * \param [in] w_current The TOPLEVEL object to create document for.
+ * \param [in] fp The postscript document to write to.
+ * \param [in] paper_size_x The width of the document on paper in inches.
+ * \param [in] paper_size_y The height of the document on paper in inches.
+ * \return 1 on success, 0 on failure.
+ */
+int f_print_header(TOPLEVEL *w_current, FILE *fp,
+ int paper_size_x, int paper_size_y)
+{
+ char *buf;
+ FILE *prolog;
+ size_t bytes;
+ int llx,lly,urx,ury;
+ time_t current_time,time_rc;
+
+ /* Compute bounding box */
+ llx=0; /* So, right now, the box starts at (0,0) */
+ lly=0;
+ urx=((float)paper_size_y * 72.0)/1000;
+ ury=((float)paper_size_x * 72.0)/1000;
+
+ /* Get Time of day for creation date */
+ time_rc = time(¤t_time);
+ if(time_rc == (time_t)-1) {
+ s_log_message("Unable to get time of day in f_print_header()\n");
+ current_time=0; /* Just set it to 1970... */
+ }
+
+ /* Output the DSC comments at the beginning of the document */
+ fprintf(fp, "%%!PS-Adobe-3.0\n"
+ "%%%%Creator: gEDA gschem %s\n"
+ "%%%%CreationDate: %s"
+ "%%%%Title: %s\n"
+ "%%%%Author: %s\n"
+ "%%%%BoundingBox: %d %d %d %d\n"
+ "%%%%Pages: 1\n"
+ "%%%%Endcomments\n"
+ "%%%%BeginProlog\n",
+ VERSION,
+ ctime(¤t_time),
+ w_current->page_current->page_filename,
+ getlogin(),
+ llx, lly, urx, ury
+ );
+
+ /* Fetch and insert the Postscript prolog from disk here */
+
+ /* Allocate a buffer to use during copy */
+#define PROLOG_BUFFER_SIZE 8192
+ buf = malloc(PROLOG_BUFFER_SIZE);
+ if(buf == NULL) {
+ s_log_message("Unable to allocate %d bytes in f_print_header()\n"
+ "Giving up on printing.\n",PROLOG_BUFFER_SIZE);
+ return 0;
+ }
+ /* Open the prolog file */
+ prolog = fopen(w_current->postscript_prolog,"r");
+ if(prolog == NULL) {
+ s_log_message("Unable to open the prolog file `%s' for reading "
+ "in f_print_header()\n"
+ "Giving up on printing\n", w_current->postscript_prolog);
+ free(buf); /* If we got to here, the buffer was allocated. */
+ return 0;
+ }
+ /* Loop while reading file into buffer and dump it
+ * back out to the supplied file handle
+ */
+ do {
+ bytes = fread(buf, 1, PROLOG_BUFFER_SIZE, prolog);
+ if(ferror(prolog)) break;
+ fwrite(buf, 1, bytes, fp);
+ } while(!feof(prolog) && !ferror(prolog) && !ferror(fp));
+
+ if(ferror(prolog)) {
+ s_log_message("Error during reading of the prolog file `%s' "
+ "in f_print_header()\n"
+ "Giving up on printing\n", w_current->postscript_prolog);
+ free(buf); /* If we got to here, the buffer was allocated. */
+ return 0;
+ }
+
+ if(ferror(fp)) {
+ s_log_message("Error during writing of the output postscript file "
+ "in f_print_header()\n"
+ "Giving up on printing\n");
+ free(buf); /* If we got to here, the buffer was allocated. */
+ return 0;
+ }
+ free(buf); /* If we got to here, the buffer was allocated. */
+
+ fprintf(fp,"%%%%EndProlog\n"
+ "%%%%Page: 1 1\n"); /* Just name it `page 1' for now */
+
+ /* These go after the prolog ends because they affect the graphics
+ * state
+ */
+
+ return 0;
+}
+
+/*! \brief Prints the footer to a postscript document
+ * \par Function Description
+ * This function will print a document footer and end
+ * a postscript document.
+ *
+ * \param [in] fp The postscript document to write footer to.
+ */
+void f_print_footer(FILE *fp)
+{
+ fprintf(fp,"showpage\n"
+ "%%%%End\n");
+}
+
+/*! \brief Print all objects from the w_current TOPLEVEL object.
+ * \par Function Description
+ * This function will parse the head parameter for all objects
+ * and write the to the postscript document.
+ *
+ * \param [in] w_current The current TOPLEVEL object.
+ * \param [in] fp The postscript document to print to.
+ * \param [in] head Container for objects to be printed.
+ * \param [in] start_x X origin on page to start printing objects.
+ * \param [in] start_y Y origin on page to start printing objects.
+ * \param [in] scale Scale factor for object output.
+ * \param [in] unicode_count Number of items in unicode table.
+ * \param [in] unicode_table Table of unicode items.
+ * \return void
+ *
+ * \todo what happens if snap is off? hack deal with this !!!!!!!!
+ */
+void f_print_objects(TOPLEVEL *w_current, FILE *fp, OBJECT *head,
+ int start_x, int start_y, float scale,
+ int unicode_count, gunichar *unicode_table)
+{
+ OBJECT *o_current=NULL;
+ int origin_x, origin_y;
+
+ origin_x = start_x;
+ origin_y = start_y;
+
+ if (head == NULL) {
+ return;
+ }
+
+ /* Apply a translation to move the origin to where we want it */
+ if (origin_x != 0 && origin_y != 0) {
+ fprintf(fp, "%d %d translate\n", -origin_x, -origin_y);
+ }
+
+
+ /* no longer change the coords, the postscript translate takes care
+ * of this */
+ origin_x = 0;
+ origin_y = 0;
+
+ o_current = head;
+
+ while ( o_current != NULL ) {
+
+ if (o_current->type != OBJ_HEAD) {
+
+ switch (o_current->type) {
+ case(OBJ_LINE):
+ o_line_print(w_current, fp, o_current,
+ origin_x, origin_y);
+ break;
+
+ case(OBJ_NET):
+ o_net_print(w_current, fp, o_current,
+ origin_x, origin_y);
+ break;
+
+ case(OBJ_BUS):
+ o_bus_print(w_current, fp, o_current,
+ origin_x, origin_y);
+ break;
+
+ case(OBJ_BOX):
+ o_box_print(w_current, fp, o_current,
+ origin_x, origin_y);
+ break;
+
+ case(OBJ_CIRCLE):
+ o_circle_print(w_current, fp, o_current,
+ origin_x, origin_y);
+ break;
+
+ case(OBJ_COMPLEX):
+ case(OBJ_PLACEHOLDER): /* new object -- 1.20.2005 SDB */
+ fprintf(fp, "gsave\n");
+
+ f_print_objects(w_current, fp,
+ o_current->complex->prim_objs,
+ origin_x, origin_y, scale,
+ unicode_count, unicode_table);
+ fprintf(fp, "grestore\n");
+ break;
+
+ case(OBJ_TEXT):
+ if (o_current->visibility == VISIBLE) {
+ int vectors = 0;
+
+ /* Look at flags and determine if vector text should
+ * be used for output.
+ */
+ if(w_current->text_output == VECTOR_FONTS) {
+ vectors = 1;
+ } else if( (w_current->print_vector_threshold > 0)
+ && ( o_text_num_lines(o_current->text->string) >
+ w_current->print_vector_threshold)) {
+ vectors = 1;
+ }
+
+ fprintf(fp, "gsave\n");
+
+ if (vectors)
+ {
+ /* Output vectors */
+ f_print_objects(w_current,
+ fp,
+ o_current->text->
+ prim_objs,
+ origin_x, origin_y,
+ scale, unicode_count, unicode_table);
+ } else {
+ /* Output text */
+ o_text_print(w_current, fp,
+ o_current,
+ origin_x, origin_y, unicode_count, unicode_table);
+ }
+
+ fprintf(fp, "grestore\n");
+ }
+ break;
+
+
+ case(OBJ_PIN):
+ o_pin_print(w_current, fp, o_current,
+ origin_x, origin_y);
+ break;
+
+ case(OBJ_ARC):
+ o_arc_print(w_current, fp, o_current,
+ origin_x, origin_y);
+ break;
+
+ case(OBJ_PICTURE):
+ o_picture_print(w_current, fp, o_current,
+ origin_x, origin_y);
+ break;
+
+ default:
+ fprintf(stderr, "Error type!\n");
+ exit(-1);
+ break;
+ }
+
+ }
+ o_current = o_current->next;
+ }
+
+ s_cue_output_all(w_current, head, fp, POSTSCRIPT);
+ return;
+}
+
+/*! \brief Print the current TOPLEVEL object to a postscript document.
+ * \par Function Description
+ *
+ * \param [in] w_current The TOPLEVEL object to print.
+ * \param [in] filename The file name of the output postscript document.
+ * \return 0 on success, -1 on failure.
+ */
+int f_print(TOPLEVEL *w_current, const char *filename)
+{
+ FILE *fp;
+ int origin_x, origin_y, bottom, right;
+ int margin_x, margin_y;
+ int dx,dy;
+ float scale;
+ int unicode_count;
+ gunichar unicode_table [128]; /* to contain the list of unicode
+ characters that need mapping */
+
+
+ /* Unicode support */
+ f_print_initialize_glyph_table(); /* Fill up unicode map */
+
+ /* Find all the unicode characters */
+ unicode_count = f_print_get_unicode_chars(w_current,
+ w_current->page_current->object_head,
+ 0, unicode_table);
+
+
+ /* dots are breaking my filename selection hack hack !!!! */
+ fp = fopen(filename, "w");
+
+ /* check to see if it worked */
+ if (fp == NULL) {
+ s_log_message("Could not open [%s] for printing\n", filename);
+ return(-1);
+ }
+
+ /* printf("%d %d\n", w_current->paper_width, w_current->paper_height);*/
+
+ world_get_complex_bounds(w_current,
+ w_current->page_current->object_head,
+ &origin_x, &origin_y,
+ &right, &bottom);
+
+ /* Calculate scale factor that will make the image fit on the page */
+ dx = 0; dy = 0;
+ margin_x = 0; margin_y = 0;
+ switch (w_current->print_output_type) {
+ case EXTENTS:
+ dx = right - origin_x;
+ dy = bottom - origin_y;
+
+ /* Add a 10% margin */
+ margin_x = dx/10;
+ margin_y = dy/10;
+ dx = dx + margin_x;
+ dy = dy + margin_y;
+ break;
+
+ case WINDOW:
+ dx = w_current->page_current->right - w_current->page_current->left;
+ dy = w_current->page_current->bottom - w_current->page_current->top;
+ origin_x = w_current->page_current->left;
+ origin_y = w_current->page_current->top;
+ right = w_current->page_current->right;
+ bottom = w_current->page_current->bottom;
+ break;
+
+ case EXTENTS_NOMARGINS:
+ dx = right - origin_x;
+ dy = bottom - origin_y;
+ break;
+
+ default:
+ break;
+
+ }
+
+ scale = 0.0;
+ if(w_current->print_orientation == LANDSCAPE) {
+ /* First attempt to fit in x direction. */
+ scale = w_current->paper_width / (float)dx;
+ if((w_current->paper_height / (float)dy) < scale ) {
+ /* Else fit with y direction */
+ scale = (w_current->paper_height / (float)dy);
+ }
+ } else { /* portrait */
+ /* First attempt to fit in y direction. */
+ scale = w_current->paper_width / (float) dy;
+ if((w_current->paper_height / (float)dx) < scale ) {
+ /* Else fit with x direction */
+ scale = (w_current->paper_height / (float)dx);
+ }
+ }
+
+#if 0
+ /* Debug */
+ printf("dx: %d dy:%d, origin_x:%d origin_y:%d, right:%d bottom:%d\n",
+ dx,dy,origin_x,origin_y,right,bottom);
+ printf("scale:%f\n",scale);
+#endif
+
+ /* Output the header */
+ f_print_header(w_current, fp,
+ w_current->paper_width,
+ w_current->paper_height);
+
+ /* Output font re-encoding */
+ if (unicode_count) {
+ f_print_unicode_map(fp, unicode_count, unicode_table);
+ /* output font re-encodeing command, use our re-encoding */
+ fprintf(fp,"/gEDAFont UTFencoding /Helvetica RE\n");
+ } else {
+ /* Otherwise, use LATIN1 extended encoding from prolog */
+ fprintf(fp,"/gEDAFont ISOLatin1Extended /Helvetica RE\n");
+ }
+
+
+ /* XXX - Do page orientation selection */
+
+/* if (w_current->setpagedevice_orientation) { */
+/* if (w_current->print_orientation == LANDSCAPE) { */
+/* fprintf(fp, "%c%c /Orientation 1 %c%c setpagedevice\n\n", '<', '<', */
+/* '>', '>'); */
+/* } else { */
+/* fprintf(fp, "%c%c /Orientation 0 %c%c setpagedevice\n\n", '<', '<', */
+/* '>', '>'); */
+/* } */
+/* } */
+
+ /* the height and width are in the right order here, since they were
+ * specified in landscape order in the system-gschemrc file.
+ * \074 is '<', \076 is '>' */
+ if (w_current->setpagedevice_pagesize) {
+ fprintf(fp, "\074\074 /PageSize [%d %d] \076\076 setpagedevice\n",
+ (w_current->paper_height * 72) / MILS_PER_INCH,
+ (w_current->paper_width * 72) / MILS_PER_INCH);
+ }
+
+
+ /* Set line end style */
+ if (w_current->print_output_capstyle == BUTT_CAP) {
+ fprintf(fp, "0 setlinecap\n");
+ } else if (w_current->print_output_capstyle == SQUARE_CAP) {
+ fprintf(fp, "2 setlinecap\n");
+ } else if (w_current->print_output_capstyle == ROUND_CAP) {
+ fprintf(fp, "1 setlinecap\n");
+ }
+
+ /* Apply mils to postscript native units scaling to CTM */
+ fprintf(fp,"%f %f scale\n",
+ 72.0 / 1000.0 , 72.0 / 1000.0);
+
+ /* Now the output is defined in terms of mils */
+ /* Draw a box with the background colour covering the whole page */
+ if (w_current->print_color) {
+ f_print_set_color(fp, w_current->print_color_background);
+ fprintf(fp,"%d %d 0 0 fbox\n",
+ w_current->paper_height,
+ w_current->paper_width);
+ }
+
+ /* Now rotate and translate the graphics to fit onto the desired
+ * page with the orientation we want. Center it too */
+ if(w_current->print_orientation == LANDSCAPE) {
+ fprintf(fp,
+ "%d %d translate 90 rotate\n",
+ (int)((w_current->paper_height + ( dy-margin_y) * scale)/2.0),
+ (int)((w_current->paper_width + (-dx+margin_x) * scale)/2.0));
+ } else { /* portrait */
+ fprintf(fp,"%d %d translate\n",
+ (int)((w_current->paper_height + (-dx + margin_x) * scale)/2.0),
+ (int)((w_current->paper_width + (-dy + margin_y) * scale)/2.0));
+
+ }
+
+ /* Now apply final mils to output scaling factor */
+ fprintf(fp,"%f %f scale\n",
+ scale, scale);
+
+ /* Print the objects */
+ f_print_objects(w_current, fp,
+ w_current->page_current->object_head,
+ origin_x, origin_y, scale, unicode_count, unicode_table);
+
+ f_print_footer(fp);
+
+ fclose(fp);
+ return(0);
+}
+
+/*! \brief Sets the current TOPLEVEL object output type
+ * \par Function Description
+ * Sets the current TOPLEVEL object output type.
+ *
+ * \param [in,out] w_current The TOPLEVEL object to set output type in.
+ * \param [in] type The print type to set.
+ */
+void f_print_set_type(TOPLEVEL *w_current, int type)
+{
+ w_current->print_output_type = type;
+}
+
+/*! \brief Converts all text strings to unicode format.
+ * \par Function Description
+ * Converts all text strings to unicode format.
+ *
+ * \param [in,out] w_current The output TOPLEVEL element to store converted
+ * strings in.
+ * \param [in] head The object containing strings for conversion.
+ * \param [in] count The number of elements in the unicode table.
+ * \param [in] table The unicode table.
+ * \return count on success, 0 otherwise.
+ */
+static int f_print_get_unicode_chars(TOPLEVEL *w_current, OBJECT *head,
+ int count, gunichar *table)
+{
+ OBJECT *o_current = NULL;
+ gchar *aux;
+ gunichar current_char;
+ int i, found;
+
+ if (head == NULL) {
+ return(0);
+ }
+
+ o_current = head;
+
+ while (o_current != NULL) {
+
+ if (o_current->type != OBJ_HEAD) {
+
+ switch (o_current->type) {
+
+ case (OBJ_COMPLEX):
+ case (OBJ_PLACEHOLDER): /* new object -- 1.20.2005 SDB */
+
+ count = f_print_get_unicode_chars(w_current,
+ o_current->complex->prim_objs,
+ count, table);
+ break;
+
+ case (OBJ_TEXT):
+ if (o_current->visibility == VISIBLE) {
+
+ aux = o_current->text->string;
+ while (aux && ((gunichar) (*aux) != 0)) {
+ current_char = g_utf8_get_char_validated(aux, -1);
+ if (current_char >= 127) {
+ found = 0;
+ i = 0;
+ while (i < count) {
+ if (table[i] == current_char)
+ found = 1;
+ i++;
+ }
+ if (!found) {
+ if (count < 128)
+ table[count++] = current_char;
+ else
+ s_log_message("Too many UTF-8 characters, cannot print\n");
+ }
+ }
+ aux = g_utf8_find_next_char(aux, NULL);
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+ }
+ o_current = o_current->next;
+ }
+ return (count);
+}
+
+/*! \brief Prints unicode map to postscript document.
+ * \par Function Description
+ * Prints unicode map to postscript document.
+ *
+ * \param [in] fp The postscript document to write unicode map to.
+ * \param [in] count Size of unicode map table.
+ * \param [in] table The unicode map to write.
+ */
+static void f_print_unicode_map(FILE * fp, int count, gunichar * table)
+{
+ unsigned int i;
+ int line_count;
+ char *glyph_map[256]; /* To contain the postscript remapping */
+
+ /* update the glyph map, undefine everything */
+ for(i=0; i<256; i++) glyph_map[i]="/.notdef";
+
+ /* Now fill in the active characters */
+ for (i=0; i<128; i++) { /* Copy in the regular latin chars */
+ glyph_map[i] = g_hash_table_lookup (unicode_char_to_glyph,
+ GUINT_TO_POINTER (i));
+ }
+ /* Finish by using up the rest of the spares */
+ for (i=128; i<(count+128); i++) {
+ if(i < (count+128)) {
+ glyph_map[i] = g_hash_table_lookup (unicode_char_to_glyph,
+ GUINT_TO_POINTER (table[i-128]));
+ }
+ }
+
+ fprintf(fp, "%%%%BeginResource: encoding UTFencoding\n");
+ fprintf(fp, "/UTFencoding [\n");
+
+ /* Output the re-encoding vector, prettily */
+ line_count = 0;
+ for (i=0; i<256; i++) {
+ line_count += fprintf(fp, "%s ", glyph_map[i]);
+ if(line_count > 60) {
+ line_count = 0;
+ fprintf(fp, "\n");
+ }
+ }
+
+ fprintf(fp, "] def\n");
+ fprintf(fp, "%%%%EndResource\n");
+}
+
+
+/*! \brief */
+static struct glyph_list {
+ gpointer key;
+ gpointer name;
+} glyphs[] = {
+ { GUINT_TO_POINTER (0x0000), "/.notdef" },
+ { GUINT_TO_POINTER (0x0041), "/A" },
+ { GUINT_TO_POINTER (0x00C6), "/AE" },
+ { GUINT_TO_POINTER (0x01FC), "/AEacute" },
+ { GUINT_TO_POINTER (0x01E2), "/AEmacron" },
+ { GUINT_TO_POINTER (0xF7E6), "/AEsmall" },
+ { GUINT_TO_POINTER (0x00C1), "/Aacute" },
+ { GUINT_TO_POINTER (0xF7E1), "/Aacutesmall" },
+ { GUINT_TO_POINTER (0x0102), "/Abreve" },
+ { GUINT_TO_POINTER (0x1EAE), "/Abreveacute" },
+ { GUINT_TO_POINTER (0x04D0), "/Abrevecyrillic" },
+ { GUINT_TO_POINTER (0x1EB6), "/Abrevedotbelow" },
+ { GUINT_TO_POINTER (0x1EB0), "/Abrevegrave" },
+ { GUINT_TO_POINTER (0x1EB2), "/Abrevehookabove" },
+ { GUINT_TO_POINTER (0x1EB4), "/Abrevetilde" },
+ { GUINT_TO_POINTER (0x01CD), "/Acaron" },
+ { GUINT_TO_POINTER (0x24B6), "/Acircle" },
+ { GUINT_TO_POINTER (0x00C2), "/Acircumflex" },
+ { GUINT_TO_POINTER (0x1EA4), "/Acircumflexacute" },
+ { GUINT_TO_POINTER (0x1EAC), "/Acircumflexdotbelow" },
+ { GUINT_TO_POINTER (0x1EA6), "/Acircumflexgrave" },
+ { GUINT_TO_POINTER (0x1EA8), "/Acircumflexhookabove" },
+ { GUINT_TO_POINTER (0xF7E2), "/Acircumflexsmall" },
+ { GUINT_TO_POINTER (0x1EAA), "/Acircumflextilde" },
+ { GUINT_TO_POINTER (0xF6C9), "/Acute" },
+ { GUINT_TO_POINTER (0xF7B4), "/Acutesmall" },
+ { GUINT_TO_POINTER (0x0410), "/Acyrillic" },
+ { GUINT_TO_POINTER (0x0200), "/Adblgrave" },
+ { GUINT_TO_POINTER (0x00C4), "/Adieresis" },
+ { GUINT_TO_POINTER (0x04D2), "/Adieresiscyrillic" },
+ { GUINT_TO_POINTER (0x01DE), "/Adieresismacron" },
+ { GUINT_TO_POINTER (0xF7E4), "/Adieresissmall" },
+ { GUINT_TO_POINTER (0x1EA0), "/Adotbelow" },
+ { GUINT_TO_POINTER (0x01E0), "/Adotmacron" },
+ { GUINT_TO_POINTER (0x00C0), "/Agrave" },
+ { GUINT_TO_POINTER (0xF7E0), "/Agravesmall" },
+ { GUINT_TO_POINTER (0x1EA2), "/Ahookabove" },
+ { GUINT_TO_POINTER (0x04D4), "/Aiecyrillic" },
+ { GUINT_TO_POINTER (0x0202), "/Ainvertedbreve" },
+ { GUINT_TO_POINTER (0x0391), "/Alpha" },
+ { GUINT_TO_POINTER (0x0386), "/Alphatonos" },
+ { GUINT_TO_POINTER (0x0100), "/Amacron" },
+ { GUINT_TO_POINTER (0xFF21), "/Amonospace" },
+ { GUINT_TO_POINTER (0x0104), "/Aogonek" },
+ { GUINT_TO_POINTER (0x00C5), "/Aring" },
+ { GUINT_TO_POINTER (0x01FA), "/Aringacute" },
+ { GUINT_TO_POINTER (0x1E00), "/Aringbelow" },
+ { GUINT_TO_POINTER (0xF7E5), "/Aringsmall" },
+ { GUINT_TO_POINTER (0xF761), "/Asmall" },
+ { GUINT_TO_POINTER (0x00C3), "/Atilde" },
+ { GUINT_TO_POINTER (0xF7E3), "/Atildesmall" },
+ { GUINT_TO_POINTER (0x0531), "/Aybarmenian" },
+ { GUINT_TO_POINTER (0x0042), "/B" },
+ { GUINT_TO_POINTER (0x24B7), "/Bcircle" },
+ { GUINT_TO_POINTER (0x1E02), "/Bdotaccent" },
+ { GUINT_TO_POINTER (0x1E04), "/Bdotbelow" },
+ { GUINT_TO_POINTER (0x0411), "/Becyrillic" },
+ { GUINT_TO_POINTER (0x0532), "/Benarmenian" },
+ { GUINT_TO_POINTER (0x0392), "/Beta" },
+ { GUINT_TO_POINTER (0x0181), "/Bhook" },
+ { GUINT_TO_POINTER (0x1E06), "/Blinebelow" },
+ { GUINT_TO_POINTER (0xFF22), "/Bmonospace" },
+ { GUINT_TO_POINTER (0xF6F4), "/Brevesmall" },
+ { GUINT_TO_POINTER (0xF762), "/Bsmall" },
+ { GUINT_TO_POINTER (0x0182), "/Btopbar" },
+ { GUINT_TO_POINTER (0x0043), "/C" },
+ { GUINT_TO_POINTER (0x053E), "/Caarmenian" },
+ { GUINT_TO_POINTER (0x0106), "/Cacute" },
+ { GUINT_TO_POINTER (0xF6CA), "/Caron" },
+ { GUINT_TO_POINTER (0xF6F5), "/Caronsmall" },
+ { GUINT_TO_POINTER (0x010C), "/Ccaron" },
+ { GUINT_TO_POINTER (0x00C7), "/Ccedilla" },
+ { GUINT_TO_POINTER (0x1E08), "/Ccedillaacute" },
+ { GUINT_TO_POINTER (0xF7E7), "/Ccedillasmall" },
+ { GUINT_TO_POINTER (0x24B8), "/Ccircle" },
+ { GUINT_TO_POINTER (0x0108), "/Ccircumflex" },
+ { GUINT_TO_POINTER (0x010A), "/Cdot" },
+ { GUINT_TO_POINTER (0x010A), "/Cdotaccent" },
+ { GUINT_TO_POINTER (0xF7B8), "/Cedillasmall" },
+ { GUINT_TO_POINTER (0x0549), "/Chaarmenian" },
+ { GUINT_TO_POINTER (0x04BC), "/Cheabkhasiancyrillic" },
+ { GUINT_TO_POINTER (0x0427), "/Checyrillic" },
+ { GUINT_TO_POINTER (0x04BE), "/Chedescenderabkhasiancyrillic" },
+ { GUINT_TO_POINTER (0x04B6), "/Chedescendercyrillic" },
+ { GUINT_TO_POINTER (0x04F4), "/Chedieresiscyrillic" },
+ { GUINT_TO_POINTER (0x0543), "/Cheharmenian" },
+ { GUINT_TO_POINTER (0x04CB), "/Chekhakassiancyrillic" },
+ { GUINT_TO_POINTER (0x04B8), "/Cheverticalstrokecyrillic" },
+ { GUINT_TO_POINTER (0x03A7), "/Chi" },
+ { GUINT_TO_POINTER (0x0187), "/Chook" },
+ { GUINT_TO_POINTER (0xF6F6), "/Circumflexsmall" },
+ { GUINT_TO_POINTER (0xFF23), "/Cmonospace" },
+ { GUINT_TO_POINTER (0x0551), "/Coarmenian" },
+ { GUINT_TO_POINTER (0xF763), "/Csmall" },
+ { GUINT_TO_POINTER (0x0044), "/D" },
+ { GUINT_TO_POINTER (0x01F1), "/DZ" },
+ { GUINT_TO_POINTER (0x01C4), "/DZcaron" },
+ { GUINT_TO_POINTER (0x0534), "/Daarmenian" },
+ { GUINT_TO_POINTER (0x0189), "/Dafrican" },
+ { GUINT_TO_POINTER (0x010E), "/Dcaron" },
+ { GUINT_TO_POINTER (0x1E10), "/Dcedilla" },
+ { GUINT_TO_POINTER (0x24B9), "/Dcircle" },
+ { GUINT_TO_POINTER (0x1E12), "/Dcircumflexbelow" },
+ { GUINT_TO_POINTER (0x0110), "/Dcroat" },
+ { GUINT_TO_POINTER (0x1E0A), "/Ddotaccent" },
+ { GUINT_TO_POINTER (0x1E0C), "/Ddotbelow" },
+ { GUINT_TO_POINTER (0x0414), "/Decyrillic" },
+ { GUINT_TO_POINTER (0x03EE), "/Deicoptic" },
+ { GUINT_TO_POINTER (0x2206), "/Delta" },
+ { GUINT_TO_POINTER (0x0394), "/Deltagreek" },
+ { GUINT_TO_POINTER (0x018A), "/Dhook" },
+ { GUINT_TO_POINTER (0xF6CB), "/Dieresis" },
+ { GUINT_TO_POINTER (0xF6CC), "/DieresisAcute" },
+ { GUINT_TO_POINTER (0xF6CD), "/DieresisGrave" },
+ { GUINT_TO_POINTER (0xF7A8), "/Dieresissmall" },
+ { GUINT_TO_POINTER (0x03DC), "/Digammagreek" },
+ { GUINT_TO_POINTER (0x0402), "/Djecyrillic" },
+ { GUINT_TO_POINTER (0x1E0E), "/Dlinebelow" },
+ { GUINT_TO_POINTER (0xFF24), "/Dmonospace" },
+ { GUINT_TO_POINTER (0xF6F7), "/Dotaccentsmall" },
+ { GUINT_TO_POINTER (0x0110), "/Dslash" },
+ { GUINT_TO_POINTER (0xF764), "/Dsmall" },
+ { GUINT_TO_POINTER (0x018B), "/Dtopbar" },
+ { GUINT_TO_POINTER (0x01F2), "/Dz" },
+ { GUINT_TO_POINTER (0x01C5), "/Dzcaron" },
+ { GUINT_TO_POINTER (0x04E0), "/Dzeabkhasiancyrillic" },
+ { GUINT_TO_POINTER (0x0405), "/Dzecyrillic" },
+ { GUINT_TO_POINTER (0x040F), "/Dzhecyrillic" },
+ { GUINT_TO_POINTER (0x0045), "/E" },
+ { GUINT_TO_POINTER (0x00C9), "/Eacute" },
+ { GUINT_TO_POINTER (0xF7E9), "/Eacutesmall" },
+ { GUINT_TO_POINTER (0x0114), "/Ebreve" },
+ { GUINT_TO_POINTER (0x011A), "/Ecaron" },
+ { GUINT_TO_POINTER (0x1E1C), "/Ecedillabreve" },
+ { GUINT_TO_POINTER (0x0535), "/Echarmenian" },
+ { GUINT_TO_POINTER (0x24BA), "/Ecircle" },
+ { GUINT_TO_POINTER (0x00CA), "/Ecircumflex" },
+ { GUINT_TO_POINTER (0x1EBE), "/Ecircumflexacute" },
+ { GUINT_TO_POINTER (0x1E18), "/Ecircumflexbelow" },
+ { GUINT_TO_POINTER (0x1EC6), "/Ecircumflexdotbelow" },
+ { GUINT_TO_POINTER (0x1EC0), "/Ecircumflexgrave" },
+ { GUINT_TO_POINTER (0x1EC2), "/Ecircumflexhookabove" },
+ { GUINT_TO_POINTER (0xF7EA), "/Ecircumflexsmall" },
+ { GUINT_TO_POINTER (0x1EC4), "/Ecircumflextilde" },
+ { GUINT_TO_POINTER (0x0404), "/Ecyrillic" },
+ { GUINT_TO_POINTER (0x0204), "/Edblgrave" },
+ { GUINT_TO_POINTER (0x00CB), "/Edieresis" },
+ { GUINT_TO_POINTER (0xF7EB), "/Edieresissmall" },
+ { GUINT_TO_POINTER (0x0116), "/Edot" },
+ { GUINT_TO_POINTER (0x0116), "/Edotaccent" },
+ { GUINT_TO_POINTER (0x1EB8), "/Edotbelow" },
+ { GUINT_TO_POINTER (0x0424), "/Efcyrillic" },
+ { GUINT_TO_POINTER (0x00C8), "/Egrave" },
+ { GUINT_TO_POINTER (0xF7E8), "/Egravesmall" },
+ { GUINT_TO_POINTER (0x0537), "/Eharmenian" },
+ { GUINT_TO_POINTER (0x1EBA), "/Ehookabove" },
+ { GUINT_TO_POINTER (0x2167), "/Eightroman" },
+ { GUINT_TO_POINTER (0x0206), "/Einvertedbreve" },
+ { GUINT_TO_POINTER (0x0464), "/Eiotifiedcyrillic" },
+ { GUINT_TO_POINTER (0x041B), "/Elcyrillic" },
+ { GUINT_TO_POINTER (0x216A), "/Elevenroman" },
+ { GUINT_TO_POINTER (0x0112), "/Emacron" },
+ { GUINT_TO_POINTER (0x1E16), "/Emacronacute" },
+ { GUINT_TO_POINTER (0x1E14), "/Emacrongrave" },
+ { GUINT_TO_POINTER (0x041C), "/Emcyrillic" },
+ { GUINT_TO_POINTER (0xFF25), "/Emonospace" },
+ { GUINT_TO_POINTER (0x041D), "/Encyrillic" },
+ { GUINT_TO_POINTER (0x04A2), "/Endescendercyrillic" },
+ { GUINT_TO_POINTER (0x014A), "/Eng" },
+ { GUINT_TO_POINTER (0x04A4), "/Enghecyrillic" },
+ { GUINT_TO_POINTER (0x04C7), "/Enhookcyrillic" },
+ { GUINT_TO_POINTER (0x0118), "/Eogonek" },
+ { GUINT_TO_POINTER (0x0190), "/Eopen" },
+ { GUINT_TO_POINTER (0x0395), "/Epsilon" },
+ { GUINT_TO_POINTER (0x0388), "/Epsilontonos" },
+ { GUINT_TO_POINTER (0x0420), "/Ercyrillic" },
+ { GUINT_TO_POINTER (0x018E), "/Ereversed" },
+ { GUINT_TO_POINTER (0x042D), "/Ereversedcyrillic" },
+ { GUINT_TO_POINTER (0x0421), "/Escyrillic" },
+ { GUINT_TO_POINTER (0x04AA), "/Esdescendercyrillic" },
+ { GUINT_TO_POINTER (0x01A9), "/Esh" },
+ { GUINT_TO_POINTER (0xF765), "/Esmall" },
+ { GUINT_TO_POINTER (0x0397), "/Eta" },
+ { GUINT_TO_POINTER (0x0538), "/Etarmenian" },
+ { GUINT_TO_POINTER (0x0389), "/Etatonos" },
+ { GUINT_TO_POINTER (0x00D0), "/Eth" },
+ { GUINT_TO_POINTER (0xF7F0), "/Ethsmall" },
+ { GUINT_TO_POINTER (0x1EBC), "/Etilde" },
+ { GUINT_TO_POINTER (0x1E1A), "/Etildebelow" },
+ { GUINT_TO_POINTER (0x20AC), "/Euro" },
+ { GUINT_TO_POINTER (0x01B7), "/Ezh" },
+ { GUINT_TO_POINTER (0x01EE), "/Ezhcaron" },
+ { GUINT_TO_POINTER (0x01B8), "/Ezhreversed" },
+ { GUINT_TO_POINTER (0x0046), "/F" },
+ { GUINT_TO_POINTER (0x24BB), "/Fcircle" },
+ { GUINT_TO_POINTER (0x1E1E), "/Fdotaccent" },
+ { GUINT_TO_POINTER (0x0556), "/Feharmenian" },
+ { GUINT_TO_POINTER (0x03E4), "/Feicoptic" },
+ { GUINT_TO_POINTER (0x0191), "/Fhook" },
+ { GUINT_TO_POINTER (0x0472), "/Fitacyrillic" },
+ { GUINT_TO_POINTER (0x2164), "/Fiveroman" },
+ { GUINT_TO_POINTER (0xFF26), "/Fmonospace" },
+ { GUINT_TO_POINTER (0x2163), "/Fourroman" },
+ { GUINT_TO_POINTER (0xF766), "/Fsmall" },
+ { GUINT_TO_POINTER (0x0047), "/G" },
+ { GUINT_TO_POINTER (0x3387), "/GBsquare" },
+ { GUINT_TO_POINTER (0x01F4), "/Gacute" },
+ { GUINT_TO_POINTER (0x0393), "/Gamma" },
+ { GUINT_TO_POINTER (0x0194), "/Gammaafrican" },
+ { GUINT_TO_POINTER (0x03EA), "/Gangiacoptic" },
+ { GUINT_TO_POINTER (0x011E), "/Gbreve" },
+ { GUINT_TO_POINTER (0x01E6), "/Gcaron" },
+ { GUINT_TO_POINTER (0x0122), "/Gcedilla" },
+ { GUINT_TO_POINTER (0x24BC), "/Gcircle" },
+ { GUINT_TO_POINTER (0x011C), "/Gcircumflex" },
+ { GUINT_TO_POINTER (0x0122), "/Gcommaaccent" },
+ { GUINT_TO_POINTER (0x0120), "/Gdot" },
+ { GUINT_TO_POINTER (0x0120), "/Gdotaccent" },
+ { GUINT_TO_POINTER (0x0413), "/Gecyrillic" },
+ { GUINT_TO_POINTER (0x0542), "/Ghadarmenian" },
+ { GUINT_TO_POINTER (0x0494), "/Ghemiddlehookcyrillic" },
+ { GUINT_TO_POINTER (0x0492), "/Ghestrokecyrillic" },
+ { GUINT_TO_POINTER (0x0490), "/Gheupturncyrillic" },
+ { GUINT_TO_POINTER (0x0193), "/Ghook" },
+ { GUINT_TO_POINTER (0x0533), "/Gimarmenian" },
+ { GUINT_TO_POINTER (0x0403), "/Gjecyrillic" },
+ { GUINT_TO_POINTER (0x1E20), "/Gmacron" },
+ { GUINT_TO_POINTER (0xFF27), "/Gmonospace" },
+ { GUINT_TO_POINTER (0xF6CE), "/Grave" },
+ { GUINT_TO_POINTER (0xF760), "/Gravesmall" },
+ { GUINT_TO_POINTER (0xF767), "/Gsmall" },
+ { GUINT_TO_POINTER (0x029B), "/Gsmallhook" },
+ { GUINT_TO_POINTER (0x01E4), "/Gstroke" },
+ { GUINT_TO_POINTER (0x0048), "/H" },
+ { GUINT_TO_POINTER (0x25CF), "/H18533" },
+ { GUINT_TO_POINTER (0x25AA), "/H18543" },
+ { GUINT_TO_POINTER (0x25AB), "/H18551" },
+ { GUINT_TO_POINTER (0x25A1), "/H22073" },
+ { GUINT_TO_POINTER (0x33CB), "/HPsquare" },
+ { GUINT_TO_POINTER (0x04A8), "/Haabkhasiancyrillic" },
+ { GUINT_TO_POINTER (0x04B2), "/Hadescendercyrillic" },
+ { GUINT_TO_POINTER (0x042A), "/Hardsigncyrillic" },
+ { GUINT_TO_POINTER (0x0126), "/Hbar" },
+ { GUINT_TO_POINTER (0x1E2A), "/Hbrevebelow" },
+ { GUINT_TO_POINTER (0x1E28), "/Hcedilla" },
+ { GUINT_TO_POINTER (0x24BD), "/Hcircle" },
+ { GUINT_TO_POINTER (0x0124), "/Hcircumflex" },
+ { GUINT_TO_POINTER (0x1E26), "/Hdieresis" },
+ { GUINT_TO_POINTER (0x1E22), "/Hdotaccent" },
+ { GUINT_TO_POINTER (0x1E24), "/Hdotbelow" },
+ { GUINT_TO_POINTER (0xFF28), "/Hmonospace" },
+ { GUINT_TO_POINTER (0x0540), "/Hoarmenian" },
+ { GUINT_TO_POINTER (0x03E8), "/Horicoptic" },
+ { GUINT_TO_POINTER (0xF768), "/Hsmall" },
+ { GUINT_TO_POINTER (0xF6CF), "/Hungarumlaut" },
+ { GUINT_TO_POINTER (0xF6F8), "/Hungarumlautsmall" },
+ { GUINT_TO_POINTER (0x3390), "/Hzsquare" },
+ { GUINT_TO_POINTER (0x0049), "/I" },
+ { GUINT_TO_POINTER (0x042F), "/IAcyrillic" },
+ { GUINT_TO_POINTER (0x0132), "/IJ" },
+ { GUINT_TO_POINTER (0x042E), "/IUcyrillic" },
+ { GUINT_TO_POINTER (0x00CD), "/Iacute" },
+ { GUINT_TO_POINTER (0xF7ED), "/Iacutesmall" },
+ { GUINT_TO_POINTER (0x012C), "/Ibreve" },
+ { GUINT_TO_POINTER (0x01CF), "/Icaron" },
+ { GUINT_TO_POINTER (0x24BE), "/Icircle" },
+ { GUINT_TO_POINTER (0x00CE), "/Icircumflex" },
+ { GUINT_TO_POINTER (0xF7EE), "/Icircumflexsmall" },
+ { GUINT_TO_POINTER (0x0406), "/Icyrillic" },
+ { GUINT_TO_POINTER (0x0208), "/Idblgrave" },
+ { GUINT_TO_POINTER (0x00CF), "/Idieresis" },
+ { GUINT_TO_POINTER (0x1E2E), "/Idieresisacute" },
+ { GUINT_TO_POINTER (0x04E4), "/Idieresiscyrillic" },
+ { GUINT_TO_POINTER (0xF7EF), "/Idieresissmall" },
+ { GUINT_TO_POINTER (0x0130), "/Idot" },
+ { GUINT_TO_POINTER (0x0130), "/Idotaccent" },
+ { GUINT_TO_POINTER (0x1ECA), "/Idotbelow" },
+ { GUINT_TO_POINTER (0x04D6), "/Iebrevecyrillic" },
+ { GUINT_TO_POINTER (0x0415), "/Iecyrillic" },
+ { GUINT_TO_POINTER (0x2111), "/Ifraktur" },
+ { GUINT_TO_POINTER (0x00CC), "/Igrave" },
+ { GUINT_TO_POINTER (0xF7EC), "/Igravesmall" },
+ { GUINT_TO_POINTER (0x1EC8), "/Ihookabove" },
+ { GUINT_TO_POINTER (0x0418), "/Iicyrillic" },
+ { GUINT_TO_POINTER (0x020A), "/Iinvertedbreve" },
+ { GUINT_TO_POINTER (0x0419), "/Iishortcyrillic" },
+ { GUINT_TO_POINTER (0x012A), "/Imacron" },
+ { GUINT_TO_POINTER (0x04E2), "/Imacroncyrillic" },
+ { GUINT_TO_POINTER (0xFF29), "/Imonospace" },
+ { GUINT_TO_POINTER (0x053B), "/Iniarmenian" },
+ { GUINT_TO_POINTER (0x0401), "/Iocyrillic" },
+ { GUINT_TO_POINTER (0x012E), "/Iogonek" },
+ { GUINT_TO_POINTER (0x0399), "/Iota" },
+ { GUINT_TO_POINTER (0x0196), "/Iotaafrican" },
+ { GUINT_TO_POINTER (0x03AA), "/Iotadieresis" },
+ { GUINT_TO_POINTER (0x038A), "/Iotatonos" },
+ { GUINT_TO_POINTER (0xF769), "/Ismall" },
+ { GUINT_TO_POINTER (0x0197), "/Istroke" },
+ { GUINT_TO_POINTER (0x0128), "/Itilde" },
+ { GUINT_TO_POINTER (0x1E2C), "/Itildebelow" },
+ { GUINT_TO_POINTER (0x0474), "/Izhitsacyrillic" },
+ { GUINT_TO_POINTER (0x0476), "/Izhitsadblgravecyrillic" },
+ { GUINT_TO_POINTER (0x004A), "/J" },
+ { GUINT_TO_POINTER (0x0541), "/Jaarmenian" },
+ { GUINT_TO_POINTER (0x24BF), "/Jcircle" },
+ { GUINT_TO_POINTER (0x0134), "/Jcircumflex" },
+ { GUINT_TO_POINTER (0x0408), "/Jecyrillic" },
+ { GUINT_TO_POINTER (0x054B), "/Jheharmenian" },
+ { GUINT_TO_POINTER (0xFF2A), "/Jmonospace" },
+ { GUINT_TO_POINTER (0xF76A), "/Jsmall" },
+ { GUINT_TO_POINTER (0x004B), "/K" },
+ { GUINT_TO_POINTER (0x3385), "/KBsquare" },
+ { GUINT_TO_POINTER (0x33CD), "/KKsquare" },
+ { GUINT_TO_POINTER (0x04A0), "/Kabashkircyrillic" },
+ { GUINT_TO_POINTER (0x1E30), "/Kacute" },
+ { GUINT_TO_POINTER (0x041A), "/Kacyrillic" },
+ { GUINT_TO_POINTER (0x049A), "/Kadescendercyrillic" },
+ { GUINT_TO_POINTER (0x04C3), "/Kahookcyrillic" },
+ { GUINT_TO_POINTER (0x039A), "/Kappa" },
+ { GUINT_TO_POINTER (0x049E), "/Kastrokecyrillic" },
+ { GUINT_TO_POINTER (0x049C), "/Kaverticalstrokecyrillic" },
+ { GUINT_TO_POINTER (0x01E8), "/Kcaron" },
+ { GUINT_TO_POINTER (0x0136), "/Kcedilla" },
+ { GUINT_TO_POINTER (0x24C0), "/Kcircle" },
+ { GUINT_TO_POINTER (0x0136), "/Kcommaaccent" },
+ { GUINT_TO_POINTER (0x1E32), "/Kdotbelow" },
+ { GUINT_TO_POINTER (0x0554), "/Keharmenian" },
+ { GUINT_TO_POINTER (0x053F), "/Kenarmenian" },
+ { GUINT_TO_POINTER (0x0425), "/Khacyrillic" },
+ { GUINT_TO_POINTER (0x03E6), "/Kheicoptic" },
+ { GUINT_TO_POINTER (0x0198), "/Khook" },
+ { GUINT_TO_POINTER (0x040C), "/Kjecyrillic" },
+ { GUINT_TO_POINTER (0x1E34), "/Klinebelow" },
+ { GUINT_TO_POINTER (0xFF2B), "/Kmonospace" },
+ { GUINT_TO_POINTER (0x0480), "/Koppacyrillic" },
+ { GUINT_TO_POINTER (0x03DE), "/Koppagreek" },
+ { GUINT_TO_POINTER (0x046E), "/Ksicyrillic" },
+ { GUINT_TO_POINTER (0xF76B), "/Ksmall" },
+ { GUINT_TO_POINTER (0x004C), "/L" },
+ { GUINT_TO_POINTER (0x01C7), "/LJ" },
+ { GUINT_TO_POINTER (0xF6BF), "/LL" },
+ { GUINT_TO_POINTER (0x0139), "/Lacute" },
+ { GUINT_TO_POINTER (0x039B), "/Lambda" },
+ { GUINT_TO_POINTER (0x013D), "/Lcaron" },
+ { GUINT_TO_POINTER (0x013B), "/Lcedilla" },
+ { GUINT_TO_POINTER (0x24C1), "/Lcircle" },
+ { GUINT_TO_POINTER (0x1E3C), "/Lcircumflexbelow" },
+ { GUINT_TO_POINTER (0x013B), "/Lcommaaccent" },
+ { GUINT_TO_POINTER (0x013F), "/Ldot" },
+ { GUINT_TO_POINTER (0x013F), "/Ldotaccent" },
+ { GUINT_TO_POINTER (0x1E36), "/Ldotbelow" },
+ { GUINT_TO_POINTER (0x1E38), "/Ldotbelowmacron" },
+ { GUINT_TO_POINTER (0x053C), "/Liwnarmenian" },
+ { GUINT_TO_POINTER (0x01C8), "/Lj" },
+ { GUINT_TO_POINTER (0x0409), "/Ljecyrillic" },
+ { GUINT_TO_POINTER (0x1E3A), "/Llinebelow" },
+ { GUINT_TO_POINTER (0xFF2C), "/Lmonospace" },
+ { GUINT_TO_POINTER (0x0141), "/Lslash" },
+ { GUINT_TO_POINTER (0xF6F9), "/Lslashsmall" },
+ { GUINT_TO_POINTER (0xF76C), "/Lsmall" },
+ { GUINT_TO_POINTER (0x004D), "/M" },
+ { GUINT_TO_POINTER (0x3386), "/MBsquare" },
+ { GUINT_TO_POINTER (0xF6D0), "/Macron" },
+ { GUINT_TO_POINTER (0xF7AF), "/Macronsmall" },
+ { GUINT_TO_POINTER (0x1E3E), "/Macute" },
+ { GUINT_TO_POINTER (0x24C2), "/Mcircle" },
+ { GUINT_TO_POINTER (0x1E40), "/Mdotaccent" },
+ { GUINT_TO_POINTER (0x1E42), "/Mdotbelow" },
+ { GUINT_TO_POINTER (0x0544), "/Menarmenian" },
+ { GUINT_TO_POINTER (0xFF2D), "/Mmonospace" },
+ { GUINT_TO_POINTER (0xF76D), "/Msmall" },
+ { GUINT_TO_POINTER (0x019C), "/Mturned" },
+ { GUINT_TO_POINTER (0x039C), "/Mu" },
+ { GUINT_TO_POINTER (0x004E), "/N" },
+ { GUINT_TO_POINTER (0x01CA), "/NJ" },
+ { GUINT_TO_POINTER (0x0143), "/Nacute" },
+ { GUINT_TO_POINTER (0x0147), "/Ncaron" },
+ { GUINT_TO_POINTER (0x0145), "/Ncedilla" },
+ { GUINT_TO_POINTER (0x24C3), "/Ncircle" },
+ { GUINT_TO_POINTER (0x1E4A), "/Ncircumflexbelow" },
+ { GUINT_TO_POINTER (0x0145), "/Ncommaaccent" },
+ { GUINT_TO_POINTER (0x1E44), "/Ndotaccent" },
+ { GUINT_TO_POINTER (0x1E46), "/Ndotbelow" },
+ { GUINT_TO_POINTER (0x019D), "/Nhookleft" },
+ { GUINT_TO_POINTER (0x2168), "/Nineroman" },
+ { GUINT_TO_POINTER (0x01CB), "/Nj" },
+ { GUINT_TO_POINTER (0x040A), "/Njecyrillic" },
+ { GUINT_TO_POINTER (0x1E48), "/Nlinebelow" },
+ { GUINT_TO_POINTER (0xFF2E), "/Nmonospace" },
+ { GUINT_TO_POINTER (0x0546), "/Nowarmenian" },
+ { GUINT_TO_POINTER (0xF76E), "/Nsmall" },
+ { GUINT_TO_POINTER (0x00D1), "/Ntilde" },
+ { GUINT_TO_POINTER (0xF7F1), "/Ntildesmall" },
+ { GUINT_TO_POINTER (0x039D), "/Nu" },
+ { GUINT_TO_POINTER (0x004F), "/O" },
+ { GUINT_TO_POINTER (0x0152), "/OE" },
+ { GUINT_TO_POINTER (0xF6FA), "/OEsmall" },
+ { GUINT_TO_POINTER (0x00D3), "/Oacute" },
+ { GUINT_TO_POINTER (0xF7F3), "/Oacutesmall" },
+ { GUINT_TO_POINTER (0x04E8), "/Obarredcyrillic" },
+ { GUINT_TO_POINTER (0x04EA), "/Obarreddieresiscyrillic" },
+ { GUINT_TO_POINTER (0x014E), "/Obreve" },
+ { GUINT_TO_POINTER (0x01D1), "/Ocaron" },
+ { GUINT_TO_POINTER (0x019F), "/Ocenteredtilde" },
+ { GUINT_TO_POINTER (0x24C4), "/Ocircle" },
+ { GUINT_TO_POINTER (0x00D4), "/Ocircumflex" },
+ { GUINT_TO_POINTER (0x1ED0), "/Ocircumflexacute" },
+ { GUINT_TO_POINTER (0x1ED8), "/Ocircumflexdotbelow" },
+ { GUINT_TO_POINTER (0x1ED2), "/Ocircumflexgrave" },
+ { GUINT_TO_POINTER (0x1ED4), "/Ocircumflexhookabove" },
+ { GUINT_TO_POINTER (0xF7F4), "/Ocircumflexsmall" },
+ { GUINT_TO_POINTER (0x1ED6), "/Ocircumflextilde" },
+ { GUINT_TO_POINTER (0x041E), "/Ocyrillic" },
+ { GUINT_TO_POINTER (0x0150), "/Odblacute" },
+ { GUINT_TO_POINTER (0x020C), "/Odblgrave" },
+ { GUINT_TO_POINTER (0x00D6), "/Odieresis" },
+ { GUINT_TO_POINTER (0x04E6), "/Odieresiscyrillic" },
+ { GUINT_TO_POINTER (0xF7F6), "/Odieresissmall" },
+ { GUINT_TO_POINTER (0x1ECC), "/Odotbelow" },
+ { GUINT_TO_POINTER (0xF6FB), "/Ogoneksmall" },
+ { GUINT_TO_POINTER (0x00D2), "/Ograve" },
+ { GUINT_TO_POINTER (0xF7F2), "/Ogravesmall" },
+ { GUINT_TO_POINTER (0x0555), "/Oharmenian" },
+ { GUINT_TO_POINTER (0x2126), "/Ohm" },
+ { GUINT_TO_POINTER (0x1ECE), "/Ohookabove" },
+ { GUINT_TO_POINTER (0x01A0), "/Ohorn" },
+ { GUINT_TO_POINTER (0x1EDA), "/Ohornacute" },
+ { GUINT_TO_POINTER (0x1EE2), "/Ohorndotbelow" },
+ { GUINT_TO_POINTER (0x1EDC), "/Ohorngrave" },
+ { GUINT_TO_POINTER (0x1EDE), "/Ohornhookabove" },
+ { GUINT_TO_POINTER (0x1EE0), "/Ohorntilde" },
+ { GUINT_TO_POINTER (0x0150), "/Ohungarumlaut" },
+ { GUINT_TO_POINTER (0x01A2), "/Oi" },
+ { GUINT_TO_POINTER (0x020E), "/Oinvertedbreve" },
+ { GUINT_TO_POINTER (0x014C), "/Omacron" },
+ { GUINT_TO_POINTER (0x1E52), "/Omacronacute" },
+ { GUINT_TO_POINTER (0x1E50), "/Omacrongrave" },
+ { GUINT_TO_POINTER (0x2126), "/Omega" },
+ { GUINT_TO_POINTER (0x0460), "/Omegacyrillic" },
+ { GUINT_TO_POINTER (0x03A9), "/Omegagreek" },
+ { GUINT_TO_POINTER (0x047A), "/Omegaroundcyrillic" },
+ { GUINT_TO_POINTER (0x047C), "/Omegatitlocyrillic" },
+ { GUINT_TO_POINTER (0x038F), "/Omegatonos" },
+ { GUINT_TO_POINTER (0x039F), "/Omicron" },
+ { GUINT_TO_POINTER (0x038C), "/Omicrontonos" },
+ { GUINT_TO_POINTER (0xFF2F), "/Omonospace" },
+ { GUINT_TO_POINTER (0x2160), "/Oneroman" },
+ { GUINT_TO_POINTER (0x01EA), "/Oogonek" },
+ { GUINT_TO_POINTER (0x01EC), "/Oogonekmacron" },
+ { GUINT_TO_POINTER (0x0186), "/Oopen" },
+ { GUINT_TO_POINTER (0x00D8), "/Oslash" },
+ { GUINT_TO_POINTER (0x01FE), "/Oslashacute" },
+ { GUINT_TO_POINTER (0xF7F8), "/Oslashsmall" },
+ { GUINT_TO_POINTER (0xF76F), "/Osmall" },
+ { GUINT_TO_POINTER (0x01FE), "/Ostrokeacute" },
+ { GUINT_TO_POINTER (0x047E), "/Otcyrillic" },
+ { GUINT_TO_POINTER (0x00D5), "/Otilde" },
+ { GUINT_TO_POINTER (0x1E4C), "/Otildeacute" },
+ { GUINT_TO_POINTER (0x1E4E), "/Otildedieresis" },
+ { GUINT_TO_POINTER (0xF7F5), "/Otildesmall" },
+ { GUINT_TO_POINTER (0x0050), "/P" },
+ { GUINT_TO_POINTER (0x1E54), "/Pacute" },
+ { GUINT_TO_POINTER (0x24C5), "/Pcircle" },
+ { GUINT_TO_POINTER (0x1E56), "/Pdotaccent" },
+ { GUINT_TO_POINTER (0x041F), "/Pecyrillic" },
+ { GUINT_TO_POINTER (0x054A), "/Peharmenian" },
+ { GUINT_TO_POINTER (0x04A6), "/Pemiddlehookcyrillic" },
+ { GUINT_TO_POINTER (0x03A6), "/Phi" },
+ { GUINT_TO_POINTER (0x01A4), "/Phook" },
+ { GUINT_TO_POINTER (0x03A0), "/Pi" },
+ { GUINT_TO_POINTER (0x0553), "/Piwrarmenian" },
+ { GUINT_TO_POINTER (0xFF30), "/Pmonospace" },
+ { GUINT_TO_POINTER (0x03A8), "/Psi" },
+ { GUINT_TO_POINTER (0x0470), "/Psicyrillic" },
+ { GUINT_TO_POINTER (0xF770), "/Psmall" },
+ { GUINT_TO_POINTER (0x0051), "/Q" },
+ { GUINT_TO_POINTER (0x24C6), "/Qcircle" },
+ { GUINT_TO_POINTER (0xFF31), "/Qmonospace" },
+ { GUINT_TO_POINTER (0xF771), "/Qsmall" },
+ { GUINT_TO_POINTER (0x0052), "/R" },
+ { GUINT_TO_POINTER (0x054C), "/Raarmenian" },
+ { GUINT_TO_POINTER (0x0154), "/Racute" },
+ { GUINT_TO_POINTER (0x0158), "/Rcaron" },
+ { GUINT_TO_POINTER (0x0156), "/Rcedilla" },
+ { GUINT_TO_POINTER (0x24C7), "/Rcircle" },
+ { GUINT_TO_POINTER (0x0156), "/Rcommaaccent" },
+ { GUINT_TO_POINTER (0x0210), "/Rdblgrave" },
+ { GUINT_TO_POINTER (0x1E58), "/Rdotaccent" },
+ { GUINT_TO_POINTER (0x1E5A), "/Rdotbelow" },
+ { GUINT_TO_POINTER (0x1E5C), "/Rdotbelowmacron" },
+ { GUINT_TO_POINTER (0x0550), "/Reharmenian" },
+ { GUINT_TO_POINTER (0x211C), "/Rfraktur" },
+ { GUINT_TO_POINTER (0x03A1), "/Rho" },
+ { GUINT_TO_POINTER (0xF6FC), "/Ringsmall" },
+ { GUINT_TO_POINTER (0x0212), "/Rinvertedbreve" },
+ { GUINT_TO_POINTER (0x1E5E), "/Rlinebelow" },
+ { GUINT_TO_POINTER (0xFF32), "/Rmonospace" },
+ { GUINT_TO_POINTER (0xF772), "/Rsmall" },
+ { GUINT_TO_POINTER (0x0281), "/Rsmallinverted" },
+ { GUINT_TO_POINTER (0x02B6), "/Rsmallinvertedsuperior" },
+ { GUINT_TO_POINTER (0x0053), "/S" },
+ { GUINT_TO_POINTER (0x250C), "/SF010000" },
+ { GUINT_TO_POINTER (0x2514), "/SF020000" },
+ { GUINT_TO_POINTER (0x2510), "/SF030000" },
+ { GUINT_TO_POINTER (0x2518), "/SF040000" },
+ { GUINT_TO_POINTER (0x253C), "/SF050000" },
+ { GUINT_TO_POINTER (0x252C), "/SF060000" },
+ { GUINT_TO_POINTER (0x2534), "/SF070000" },
+ { GUINT_TO_POINTER (0x251C), "/SF080000" },
+ { GUINT_TO_POINTER (0x2524), "/SF090000" },
+ { GUINT_TO_POINTER (0x2500), "/SF100000" },
+ { GUINT_TO_POINTER (0x2502), "/SF110000" },
+ { GUINT_TO_POINTER (0x2561), "/SF190000" },
+ { GUINT_TO_POINTER (0x2562), "/SF200000" },
+ { GUINT_TO_POINTER (0x2556), "/SF210000" },
+ { GUINT_TO_POINTER (0x2555), "/SF220000" },
+ { GUINT_TO_POINTER (0x2563), "/SF230000" },
+ { GUINT_TO_POINTER (0x2551), "/SF240000" },
+ { GUINT_TO_POINTER (0x2557), "/SF250000" },
+ { GUINT_TO_POINTER (0x255D), "/SF260000" },
+ { GUINT_TO_POINTER (0x255C), "/SF270000" },
+ { GUINT_TO_POINTER (0x255B), "/SF280000" },
+ { GUINT_TO_POINTER (0x255E), "/SF360000" },
+ { GUINT_TO_POINTER (0x255F), "/SF370000" },
+ { GUINT_TO_POINTER (0x255A), "/SF380000" },
+ { GUINT_TO_POINTER (0x2554), "/SF390000" },
+ { GUINT_TO_POINTER (0x2569), "/SF400000" },
+ { GUINT_TO_POINTER (0x2566), "/SF410000" },
+ { GUINT_TO_POINTER (0x2560), "/SF420000" },
+ { GUINT_TO_POINTER (0x2550), "/SF430000" },
+ { GUINT_TO_POINTER (0x256C), "/SF440000" },
+ { GUINT_TO_POINTER (0x2567), "/SF450000" },
+ { GUINT_TO_POINTER (0x2568), "/SF460000" },
+ { GUINT_TO_POINTER (0x2564), "/SF470000" },
+ { GUINT_TO_POINTER (0x2565), "/SF480000" },
+ { GUINT_TO_POINTER (0x2559), "/SF490000" },
+ { GUINT_TO_POINTER (0x2558), "/SF500000" },
+ { GUINT_TO_POINTER (0x2552), "/SF510000" },
+ { GUINT_TO_POINTER (0x2553), "/SF520000" },
+ { GUINT_TO_POINTER (0x256B), "/SF530000" },
+ { GUINT_TO_POINTER (0x256A), "/SF540000" },
+ { GUINT_TO_POINTER (0x015A), "/Sacute" },
+ { GUINT_TO_POINTER (0x1E64), "/Sacutedotaccent" },
+ { GUINT_TO_POINTER (0x03E0), "/Sampigreek" },
+ { GUINT_TO_POINTER (0x0160), "/Scaron" },
+ { GUINT_TO_POINTER (0x1E66), "/Scarondotaccent" },
+ { GUINT_TO_POINTER (0xF6FD), "/Scaronsmall" },
+ { GUINT_TO_POINTER (0x015E), "/Scedilla" },
+ { GUINT_TO_POINTER (0x018F), "/Schwa" },
+ { GUINT_TO_POINTER (0x04D8), "/Schwacyrillic" },
+ { GUINT_TO_POINTER (0x04DA), "/Schwadieresiscyrillic" },
+ { GUINT_TO_POINTER (0x24C8), "/Scircle" },
+ { GUINT_TO_POINTER (0x015C), "/Scircumflex" },
+ { GUINT_TO_POINTER (0x0218), "/Scommaaccent" },
+ { GUINT_TO_POINTER (0x1E60), "/Sdotaccent" },
+ { GUINT_TO_POINTER (0x1E62), "/Sdotbelow" },
+ { GUINT_TO_POINTER (0x1E68), "/Sdotbelowdotaccent" },
+ { GUINT_TO_POINTER (0x054D), "/Seharmenian" },
+ { GUINT_TO_POINTER (0x2166), "/Sevenroman" },
+ { GUINT_TO_POINTER (0x0547), "/Shaarmenian" },
+ { GUINT_TO_POINTER (0x0428), "/Shacyrillic" },
+ { GUINT_TO_POINTER (0x0429), "/Shchacyrillic" },
+ { GUINT_TO_POINTER (0x03E2), "/Sheicoptic" },
+ { GUINT_TO_POINTER (0x04BA), "/Shhacyrillic" },
+ { GUINT_TO_POINTER (0x03EC), "/Shimacoptic" },
+ { GUINT_TO_POINTER (0x03A3), "/Sigma" },
+ { GUINT_TO_POINTER (0x2165), "/Sixroman" },
+ { GUINT_TO_POINTER (0xFF33), "/Smonospace" },
+ { GUINT_TO_POINTER (0x042C), "/Softsigncyrillic" },
+ { GUINT_TO_POINTER (0xF773), "/Ssmall" },
+ { GUINT_TO_POINTER (0x03DA), "/Stigmagreek" },
+ { GUINT_TO_POINTER (0x0054), "/T" },
+ { GUINT_TO_POINTER (0x03A4), "/Tau" },
+ { GUINT_TO_POINTER (0x0166), "/Tbar" },
+ { GUINT_TO_POINTER (0x0164), "/Tcaron" },
+ { GUINT_TO_POINTER (0x0162), "/Tcedilla" },
+ { GUINT_TO_POINTER (0x24C9), "/Tcircle" },
+ { GUINT_TO_POINTER (0x1E70), "/Tcircumflexbelow" },
+ { GUINT_TO_POINTER (0x0162), "/Tcommaaccent" },
+ { GUINT_TO_POINTER (0x1E6A), "/Tdotaccent" },
+ { GUINT_TO_POINTER (0x1E6C), "/Tdotbelow" },
+ { GUINT_TO_POINTER (0x0422), "/Tecyrillic" },
+ { GUINT_TO_POINTER (0x04AC), "/Tedescendercyrillic" },
+ { GUINT_TO_POINTER (0x2169), "/Tenroman" },
+ { GUINT_TO_POINTER (0x04B4), "/Tetsecyrillic" },
+ { GUINT_TO_POINTER (0x0398), "/Theta" },
+ { GUINT_TO_POINTER (0x01AC), "/Thook" },
+ { GUINT_TO_POINTER (0x00DE), "/Thorn" },
+ { GUINT_TO_POINTER (0xF7FE), "/Thornsmall" },
+ { GUINT_TO_POINTER (0x2162), "/Threeroman" },
+ { GUINT_TO_POINTER (0xF6FE), "/Tildesmall" },
+ { GUINT_TO_POINTER (0x054F), "/Tiwnarmenian" },
+ { GUINT_TO_POINTER (0x1E6E), "/Tlinebelow" },
+ { GUINT_TO_POINTER (0xFF34), "/Tmonospace" },
+ { GUINT_TO_POINTER (0x0539), "/Toarmenian" },
+ { GUINT_TO_POINTER (0x01BC), "/Tonefive" },
+ { GUINT_TO_POINTER (0x0184), "/Tonesix" },
+ { GUINT_TO_POINTER (0x01A7), "/Tonetwo" },
+ { GUINT_TO_POINTER (0x01AE), "/Tretroflexhook" },
+ { GUINT_TO_POINTER (0x0426), "/Tsecyrillic" },
+ { GUINT_TO_POINTER (0x040B), "/Tshecyrillic" },
+ { GUINT_TO_POINTER (0xF774), "/Tsmall" },
+ { GUINT_TO_POINTER (0x216B), "/Twelveroman" },
+ { GUINT_TO_POINTER (0x2161), "/Tworoman" },
+ { GUINT_TO_POINTER (0x0055), "/U" },
+ { GUINT_TO_POINTER (0x00DA), "/Uacute" },
+ { GUINT_TO_POINTER (0xF7FA), "/Uacutesmall" },
+ { GUINT_TO_POINTER (0x016C), "/Ubreve" },
+ { GUINT_TO_POINTER (0x01D3), "/Ucaron" },
+ { GUINT_TO_POINTER (0x24CA), "/Ucircle" },
+ { GUINT_TO_POINTER (0x00DB), "/Ucircumflex" },
+ { GUINT_TO_POINTER (0x1E76), "/Ucircumflexbelow" },
+ { GUINT_TO_POINTER (0xF7FB), "/Ucircumflexsmall" },
+ { GUINT_TO_POINTER (0x0423), "/Ucyrillic" },
+ { GUINT_TO_POINTER (0x0170), "/Udblacute" },
+ { GUINT_TO_POINTER (0x0214), "/Udblgrave" },
+ { GUINT_TO_POINTER (0x00DC), "/Udieresis" },
+ { GUINT_TO_POINTER (0x01D7), "/Udieresisacute" },
+ { GUINT_TO_POINTER (0x1E72), "/Udieresisbelow" },
+ { GUINT_TO_POINTER (0x01D9), "/Udieresiscaron" },
+ { GUINT_TO_POINTER (0x04F0), "/Udieresiscyrillic" },
+ { GUINT_TO_POINTER (0x01DB), "/Udieresisgrave" },
+ { GUINT_TO_POINTER (0x01D5), "/Udieresismacron" },
+ { GUINT_TO_POINTER (0xF7FC), "/Udieresissmall" },
+ { GUINT_TO_POINTER (0x1EE4), "/Udotbelow" },
+ { GUINT_TO_POINTER (0x00D9), "/Ugrave" },
+ { GUINT_TO_POINTER (0xF7F9), "/Ugravesmall" },
+ { GUINT_TO_POINTER (0x1EE6), "/Uhookabove" },
+ { GUINT_TO_POINTER (0x01AF), "/Uhorn" },
+ { GUINT_TO_POINTER (0x1EE8), "/Uhornacute" },
+ { GUINT_TO_POINTER (0x1EF0), "/Uhorndotbelow" },
+ { GUINT_TO_POINTER (0x1EEA), "/Uhorngrave" },
+ { GUINT_TO_POINTER (0x1EEC), "/Uhornhookabove" },
+ { GUINT_TO_POINTER (0x1EEE), "/Uhorntilde" },
+ { GUINT_TO_POINTER (0x0170), "/Uhungarumlaut" },
+ { GUINT_TO_POINTER (0x04F2), "/Uhungarumlautcyrillic" },
+ { GUINT_TO_POINTER (0x0216), "/Uinvertedbreve" },
+ { GUINT_TO_POINTER (0x0478), "/Ukcyrillic" },
+ { GUINT_TO_POINTER (0x016A), "/Umacron" },
+ { GUINT_TO_POINTER (0x04EE), "/Umacroncyrillic" },
+ { GUINT_TO_POINTER (0x1E7A), "/Umacrondieresis" },
+ { GUINT_TO_POINTER (0xFF35), "/Umonospace" },
+ { GUINT_TO_POINTER (0x0172), "/Uogonek" },
+ { GUINT_TO_POINTER (0x03A5), "/Upsilon" },
+ { GUINT_TO_POINTER (0x03D2), "/Upsilon1" },
+ { GUINT_TO_POINTER (0x03D3), "/Upsilonacutehooksymbolgreek" },
+ { GUINT_TO_POINTER (0x01B1), "/Upsilonafrican" },
+ { GUINT_TO_POINTER (0x03AB), "/Upsilondieresis" },
+ { GUINT_TO_POINTER (0x03D4), "/Upsilondieresishooksymbolgreek" },
+ { GUINT_TO_POINTER (0x03D2), "/Upsilonhooksymbol" },
+ { GUINT_TO_POINTER (0x038E), "/Upsilontonos" },
+ { GUINT_TO_POINTER (0x016E), "/Uring" },
+ { GUINT_TO_POINTER (0x040E), "/Ushortcyrillic" },
+ { GUINT_TO_POINTER (0xF775), "/Usmall" },
+ { GUINT_TO_POINTER (0x04AE), "/Ustraightcyrillic" },
+ { GUINT_TO_POINTER (0x04B0), "/Ustraightstrokecyrillic" },
+ { GUINT_TO_POINTER (0x0168), "/Utilde" },
+ { GUINT_TO_POINTER (0x1E78), "/Utildeacute" },
+ { GUINT_TO_POINTER (0x1E74), "/Utildebelow" },
+ { GUINT_TO_POINTER (0x0056), "/V" },
+ { GUINT_TO_POINTER (0x24CB), "/Vcircle" },
+ { GUINT_TO_POINTER (0x1E7E), "/Vdotbelow" },
+ { GUINT_TO_POINTER (0x0412), "/Vecyrillic" },
+ { GUINT_TO_POINTER (0x054E), "/Vewarmenian" },
+ { GUINT_TO_POINTER (0x01B2), "/Vhook" },
+ { GUINT_TO_POINTER (0xFF36), "/Vmonospace" },
+ { GUINT_TO_POINTER (0x0548), "/Voarmenian" },
+ { GUINT_TO_POINTER (0xF776), "/Vsmall" },
+ { GUINT_TO_POINTER (0x1E7C), "/Vtilde" },
+ { GUINT_TO_POINTER (0x0057), "/W" },
+ { GUINT_TO_POINTER (0x1E82), "/Wacute" },
+ { GUINT_TO_POINTER (0x24CC), "/Wcircle" },
+ { GUINT_TO_POINTER (0x0174), "/Wcircumflex" },
+ { GUINT_TO_POINTER (0x1E84), "/Wdieresis" },
+ { GUINT_TO_POINTER (0x1E86), "/Wdotaccent" },
+ { GUINT_TO_POINTER (0x1E88), "/Wdotbelow" },
+ { GUINT_TO_POINTER (0x1E80), "/Wgrave" },
+ { GUINT_TO_POINTER (0xFF37), "/Wmonospace" },
+ { GUINT_TO_POINTER (0xF777), "/Wsmall" },
+ { GUINT_TO_POINTER (0x0058), "/X" },
+ { GUINT_TO_POINTER (0x24CD), "/Xcircle" },
+ { GUINT_TO_POINTER (0x1E8C), "/Xdieresis" },
+ { GUINT_TO_POINTER (0x1E8A), "/Xdotaccent" },
+ { GUINT_TO_POINTER (0x053D), "/Xeharmenian" },
+ { GUINT_TO_POINTER (0x039E), "/Xi" },
+ { GUINT_TO_POINTER (0xFF38), "/Xmonospace" },
+ { GUINT_TO_POINTER (0xF778), "/Xsmall" },
+ { GUINT_TO_POINTER (0x0059), "/Y" },
+ { GUINT_TO_POINTER (0x00DD), "/Yacute" },
+ { GUINT_TO_POINTER (0xF7FD), "/Yacutesmall" },
+ { GUINT_TO_POINTER (0x0462), "/Yatcyrillic" },
+ { GUINT_TO_POINTER (0x24CE), "/Ycircle" },
+ { GUINT_TO_POINTER (0x0176), "/Ycircumflex" },
+ { GUINT_TO_POINTER (0x0178), "/Ydieresis" },
+ { GUINT_TO_POINTER (0xF7FF), "/Ydieresissmall" },
+ { GUINT_TO_POINTER (0x1E8E), "/Ydotaccent" },
+ { GUINT_TO_POINTER (0x1EF4), "/Ydotbelow" },
+ { GUINT_TO_POINTER (0x042B), "/Yericyrillic" },
+ { GUINT_TO_POINTER (0x04F8), "/Yerudieresiscyrillic" },
+ { GUINT_TO_POINTER (0x1EF2), "/Ygrave" },
+ { GUINT_TO_POINTER (0x01B3), "/Yhook" },
+ { GUINT_TO_POINTER (0x1EF6), "/Yhookabove" },
+ { GUINT_TO_POINTER (0x0545), "/Yiarmenian" },
+ { GUINT_TO_POINTER (0x0407), "/Yicyrillic" },
+ { GUINT_TO_POINTER (0x0552), "/Yiwnarmenian" },
+ { GUINT_TO_POINTER (0xFF39), "/Ymonospace" },
+ { GUINT_TO_POINTER (0xF779), "/Ysmall" },
+ { GUINT_TO_POINTER (0x1EF8), "/Ytilde" },
+ { GUINT_TO_POINTER (0x046A), "/Yusbigcyrillic" },
+ { GUINT_TO_POINTER (0x046C), "/Yusbigiotifiedcyrillic" },
+ { GUINT_TO_POINTER (0x0466), "/Yuslittlecyrillic" },
+ { GUINT_TO_POINTER (0x0468), "/Yuslittleiotifiedcyrillic" },
+ { GUINT_TO_POINTER (0x005A), "/Z" },
+ { GUINT_TO_POINTER (0x0536), "/Zaarmenian" },
+ { GUINT_TO_POINTER (0x0179), "/Zacute" },
+ { GUINT_TO_POINTER (0x017D), "/Zcaron" },
+ { GUINT_TO_POINTER (0xF6FF), "/Zcaronsmall" },
+ { GUINT_TO_POINTER (0x24CF), "/Zcircle" },
+ { GUINT_TO_POINTER (0x1E90), "/Zcircumflex" },
+ { GUINT_TO_POINTER (0x017B), "/Zdot" },
+ { GUINT_TO_POINTER (0x017B), "/Zdotaccent" },
+ { GUINT_TO_POINTER (0x1E92), "/Zdotbelow" },
+ { GUINT_TO_POINTER (0x0417), "/Zecyrillic" },
+ { GUINT_TO_POINTER (0x0498), "/Zedescendercyrillic" },
+ { GUINT_TO_POINTER (0x04DE), "/Zedieresiscyrillic" },
+ { GUINT_TO_POINTER (0x0396), "/Zeta" },
+ { GUINT_TO_POINTER (0x053A), "/Zhearmenian" },
+ { GUINT_TO_POINTER (0x04C1), "/Zhebrevecyrillic" },
+ { GUINT_TO_POINTER (0x0416), "/Zhecyrillic" },
+ { GUINT_TO_POINTER (0x0496), "/Zhedescendercyrillic" },
+ { GUINT_TO_POINTER (0x04DC), "/Zhedieresiscyrillic" },
+ { GUINT_TO_POINTER (0x1E94), "/Zlinebelow" },
+ { GUINT_TO_POINTER (0xFF3A), "/Zmonospace" },
+ { GUINT_TO_POINTER (0xF77A), "/Zsmall" },
+ { GUINT_TO_POINTER (0x01B5), "/Zstroke" },
+ { GUINT_TO_POINTER (0x0061), "/a" },
+ { GUINT_TO_POINTER (0x0986), "/aabengali" },
+ { GUINT_TO_POINTER (0x00E1), "/aacute" },
+ { GUINT_TO_POINTER (0x0906), "/aadeva" },
+ { GUINT_TO_POINTER (0x0A86), "/aagujarati" },
+ { GUINT_TO_POINTER (0x0A06), "/aagurmukhi" },
+ { GUINT_TO_POINTER (0x0A3E), "/aamatragurmukhi" },
+ { GUINT_TO_POINTER (0x3303), "/aarusquare" },
+ { GUINT_TO_POINTER (0x09BE), "/aavowelsignbengali" },
+ { GUINT_TO_POINTER (0x093E), "/aavowelsigndeva" },
+ { GUINT_TO_POINTER (0x0ABE), "/aavowelsigngujarati" },
+ { GUINT_TO_POINTER (0x055F), "/abbreviationmarkarmenian" },
+ { GUINT_TO_POINTER (0x0970), "/abbreviationsigndeva" },
+ { GUINT_TO_POINTER (0x0985), "/abengali" },
+ { GUINT_TO_POINTER (0x311A), "/abopomofo" },
+ { GUINT_TO_POINTER (0x0103), "/abreve" },
+ { GUINT_TO_POINTER (0x1EAF), "/abreveacute" },
+ { GUINT_TO_POINTER (0x04D1), "/abrevecyrillic" },
+ { GUINT_TO_POINTER (0x1EB7), "/abrevedotbelow" },
+ { GUINT_TO_POINTER (0x1EB1), "/abrevegrave" },
+ { GUINT_TO_POINTER (0x1EB3), "/abrevehookabove" },
+ { GUINT_TO_POINTER (0x1EB5), "/abrevetilde" },
+ { GUINT_TO_POINTER (0x01CE), "/acaron" },
+ { GUINT_TO_POINTER (0x24D0), "/acircle" },
+ { GUINT_TO_POINTER (0x00E2), "/acircumflex" },
+ { GUINT_TO_POINTER (0x1EA5), "/acircumflexacute" },
+ { GUINT_TO_POINTER (0x1EAD), "/acircumflexdotbelow" },
+ { GUINT_TO_POINTER (0x1EA7), "/acircumflexgrave" },
+ { GUINT_TO_POINTER (0x1EA9), "/acircumflexhookabove" },
+ { GUINT_TO_POINTER (0x1EAB), "/acircumflextilde" },
+ { GUINT_TO_POINTER (0x00B4), "/acute" },
+ { GUINT_TO_POINTER (0x0317), "/acutebelowcmb" },
+ { GUINT_TO_POINTER (0x0301), "/acutecmb" },
+ { GUINT_TO_POINTER (0x0301), "/acutecomb" },
+ { GUINT_TO_POINTER (0x0954), "/acutedeva" },
+ { GUINT_TO_POINTER (0x02CF), "/acutelowmod" },
+ { GUINT_TO_POINTER (0x0341), "/acutetonecmb" },
+ { GUINT_TO_POINTER (0x0430), "/acyrillic" },
+ { GUINT_TO_POINTER (0x0201), "/adblgrave" },
+ { GUINT_TO_POINTER (0x0A71), "/addakgurmukhi" },
+ { GUINT_TO_POINTER (0x0905), "/adeva" },
+ { GUINT_TO_POINTER (0x00E4), "/adieresis" },
+ { GUINT_TO_POINTER (0x04D3), "/adieresiscyrillic" },
+ { GUINT_TO_POINTER (0x01DF), "/adieresismacron" },
+ { GUINT_TO_POINTER (0x1EA1), "/adotbelow" },
+ { GUINT_TO_POINTER (0x01E1), "/adotmacron" },
+ { GUINT_TO_POINTER (0x00E6), "/ae" },
+ { GUINT_TO_POINTER (0x01FD), "/aeacute" },
+ { GUINT_TO_POINTER (0x3150), "/aekorean" },
+ { GUINT_TO_POINTER (0x01E3), "/aemacron" },
+ { GUINT_TO_POINTER (0x2015), "/afii00208" },
+ { GUINT_TO_POINTER (0x20A4), "/afii08941" },
+ { GUINT_TO_POINTER (0x0410), "/afii10017" },
+ { GUINT_TO_POINTER (0x0411), "/afii10018" },
+ { GUINT_TO_POINTER (0x0412), "/afii10019" },
+ { GUINT_TO_POINTER (0x0413), "/afii10020" },
+ { GUINT_TO_POINTER (0x0414), "/afii10021" },
+ { GUINT_TO_POINTER (0x0415), "/afii10022" },
+ { GUINT_TO_POINTER (0x0401), "/afii10023" },
+ { GUINT_TO_POINTER (0x0416), "/afii10024" },
+ { GUINT_TO_POINTER (0x0417), "/afii10025" },
+ { GUINT_TO_POINTER (0x0418), "/afii10026" },
+ { GUINT_TO_POINTER (0x0419), "/afii10027" },
+ { GUINT_TO_POINTER (0x041A), "/afii10028" },
+ { GUINT_TO_POINTER (0x041B), "/afii10029" },
+ { GUINT_TO_POINTER (0x041C), "/afii10030" },
+ { GUINT_TO_POINTER (0x041D), "/afii10031" },
+ { GUINT_TO_POINTER (0x041E), "/afii10032" },
+ { GUINT_TO_POINTER (0x041F), "/afii10033" },
+ { GUINT_TO_POINTER (0x0420), "/afii10034" },
+ { GUINT_TO_POINTER (0x0421), "/afii10035" },
+ { GUINT_TO_POINTER (0x0422), "/afii10036" },
+ { GUINT_TO_POINTER (0x0423), "/afii10037" },
+ { GUINT_TO_POINTER (0x0424), "/afii10038" },
+ { GUINT_TO_POINTER (0x0425), "/afii10039" },
+ { GUINT_TO_POINTER (0x0426), "/afii10040" },
+ { GUINT_TO_POINTER (0x0427), "/afii10041" },
+ { GUINT_TO_POINTER (0x0428), "/afii10042" },
+ { GUINT_TO_POINTER (0x0429), "/afii10043" },
+ { GUINT_TO_POINTER (0x042A), "/afii10044" },
+ { GUINT_TO_POINTER (0x042B), "/afii10045" },
+ { GUINT_TO_POINTER (0x042C), "/afii10046" },
+ { GUINT_TO_POINTER (0x042D), "/afii10047" },
+ { GUINT_TO_POINTER (0x042E), "/afii10048" },
+ { GUINT_TO_POINTER (0x042F), "/afii10049" },
+ { GUINT_TO_POINTER (0x0490), "/afii10050" },
+ { GUINT_TO_POINTER (0x0402), "/afii10051" },
+ { GUINT_TO_POINTER (0x0403), "/afii10052" },
+ { GUINT_TO_POINTER (0x0404), "/afii10053" },
+ { GUINT_TO_POINTER (0x0405), "/afii10054" },
+ { GUINT_TO_POINTER (0x0406), "/afii10055" },
+ { GUINT_TO_POINTER (0x0407), "/afii10056" },
+ { GUINT_TO_POINTER (0x0408), "/afii10057" },
+ { GUINT_TO_POINTER (0x0409), "/afii10058" },
+ { GUINT_TO_POINTER (0x040A), "/afii10059" },
+ { GUINT_TO_POINTER (0x040B), "/afii10060" },
+ { GUINT_TO_POINTER (0x040C), "/afii10061" },
+ { GUINT_TO_POINTER (0x040E), "/afii10062" },
+ { GUINT_TO_POINTER (0xF6C4), "/afii10063" },
+ { GUINT_TO_POINTER (0xF6C5), "/afii10064" },
+ { GUINT_TO_POINTER (0x0430), "/afii10065" },
+ { GUINT_TO_POINTER (0x0431), "/afii10066" },
+ { GUINT_TO_POINTER (0x0432), "/afii10067" },
+ { GUINT_TO_POINTER (0x0433), "/afii10068" },
+ { GUINT_TO_POINTER (0x0434), "/afii10069" },
+ { GUINT_TO_POINTER (0x0435), "/afii10070" },
+ { GUINT_TO_POINTER (0x0451), "/afii10071" },
+ { GUINT_TO_POINTER (0x0436), "/afii10072" },
+ { GUINT_TO_POINTER (0x0437), "/afii10073" },
+ { GUINT_TO_POINTER (0x0438), "/afii10074" },
+ { GUINT_TO_POINTER (0x0439), "/afii10075" },
+ { GUINT_TO_POINTER (0x043A), "/afii10076" },
+ { GUINT_TO_POINTER (0x043B), "/afii10077" },
+ { GUINT_TO_POINTER (0x043C), "/afii10078" },
+ { GUINT_TO_POINTER (0x043D), "/afii10079" },
+ { GUINT_TO_POINTER (0x043E), "/afii10080" },
+ { GUINT_TO_POINTER (0x043F), "/afii10081" },
+ { GUINT_TO_POINTER (0x0440), "/afii10082" },
+ { GUINT_TO_POINTER (0x0441), "/afii10083" },
+ { GUINT_TO_POINTER (0x0442), "/afii10084" },
+ { GUINT_TO_POINTER (0x0443), "/afii10085" },
+ { GUINT_TO_POINTER (0x0444), "/afii10086" },
+ { GUINT_TO_POINTER (0x0445), "/afii10087" },
+ { GUINT_TO_POINTER (0x0446), "/afii10088" },
+ { GUINT_TO_POINTER (0x0447), "/afii10089" },
+ { GUINT_TO_POINTER (0x0448), "/afii10090" },
+ { GUINT_TO_POINTER (0x0449), "/afii10091" },
+ { GUINT_TO_POINTER (0x044A), "/afii10092" },
+ { GUINT_TO_POINTER (0x044B), "/afii10093" },
+ { GUINT_TO_POINTER (0x044C), "/afii10094" },
+ { GUINT_TO_POINTER (0x044D), "/afii10095" },
+ { GUINT_TO_POINTER (0x044E), "/afii10096" },
+ { GUINT_TO_POINTER (0x044F), "/afii10097" },
+ { GUINT_TO_POINTER (0x0491), "/afii10098" },
+ { GUINT_TO_POINTER (0x0452), "/afii10099" },
+ { GUINT_TO_POINTER (0x0453), "/afii10100" },
+ { GUINT_TO_POINTER (0x0454), "/afii10101" },
+ { GUINT_TO_POINTER (0x0455), "/afii10102" },
+ { GUINT_TO_POINTER (0x0456), "/afii10103" },
+ { GUINT_TO_POINTER (0x0457), "/afii10104" },
+ { GUINT_TO_POINTER (0x0458), "/afii10105" },
+ { GUINT_TO_POINTER (0x0459), "/afii10106" },
+ { GUINT_TO_POINTER (0x045A), "/afii10107" },
+ { GUINT_TO_POINTER (0x045B), "/afii10108" },
+ { GUINT_TO_POINTER (0x045C), "/afii10109" },
+ { GUINT_TO_POINTER (0x045E), "/afii10110" },
+ { GUINT_TO_POINTER (0x040F), "/afii10145" },
+ { GUINT_TO_POINTER (0x0462), "/afii10146" },
+ { GUINT_TO_POINTER (0x0472), "/afii10147" },
+ { GUINT_TO_POINTER (0x0474), "/afii10148" },
+ { GUINT_TO_POINTER (0xF6C6), "/afii10192" },
+ { GUINT_TO_POINTER (0x045F), "/afii10193" },
+ { GUINT_TO_POINTER (0x0463), "/afii10194" },
+ { GUINT_TO_POINTER (0x0473), "/afii10195" },
+ { GUINT_TO_POINTER (0x0475), "/afii10196" },
+ { GUINT_TO_POINTER (0xF6C7), "/afii10831" },
+ { GUINT_TO_POINTER (0xF6C8), "/afii10832" },
+ { GUINT_TO_POINTER (0x04D9), "/afii10846" },
+ { GUINT_TO_POINTER (0x200E), "/afii299" },
+ { GUINT_TO_POINTER (0x200F), "/afii300" },
+ { GUINT_TO_POINTER (0x200D), "/afii301" },
+ { GUINT_TO_POINTER (0x066A), "/afii57381" },
+ { GUINT_TO_POINTER (0x060C), "/afii57388" },
+ { GUINT_TO_POINTER (0x0660), "/afii57392" },
+ { GUINT_TO_POINTER (0x0661), "/afii57393" },
+ { GUINT_TO_POINTER (0x0662), "/afii57394" },
+ { GUINT_TO_POINTER (0x0663), "/afii57395" },
+ { GUINT_TO_POINTER (0x0664), "/afii57396" },
+ { GUINT_TO_POINTER (0x0665), "/afii57397" },
+ { GUINT_TO_POINTER (0x0666), "/afii57398" },
+ { GUINT_TO_POINTER (0x0667), "/afii57399" },
+ { GUINT_TO_POINTER (0x0668), "/afii57400" },
+ { GUINT_TO_POINTER (0x0669), "/afii57401" },
+ { GUINT_TO_POINTER (0x061B), "/afii57403" },
+ { GUINT_TO_POINTER (0x061F), "/afii57407" },
+ { GUINT_TO_POINTER (0x0621), "/afii57409" },
+ { GUINT_TO_POINTER (0x0622), "/afii57410" },
+ { GUINT_TO_POINTER (0x0623), "/afii57411" },
+ { GUINT_TO_POINTER (0x0624), "/afii57412" },
+ { GUINT_TO_POINTER (0x0625), "/afii57413" },
+ { GUINT_TO_POINTER (0x0626), "/afii57414" },
+ { GUINT_TO_POINTER (0x0627), "/afii57415" },
+ { GUINT_TO_POINTER (0x0628), "/afii57416" },
+ { GUINT_TO_POINTER (0x0629), "/afii57417" },
+ { GUINT_TO_POINTER (0x062A), "/afii57418" },
+ { GUINT_TO_POINTER (0x062B), "/afii57419" },
+ { GUINT_TO_POINTER (0x062C), "/afii57420" },
+ { GUINT_TO_POINTER (0x062D), "/afii57421" },
+ { GUINT_TO_POINTER (0x062E), "/afii57422" },
+ { GUINT_TO_POINTER (0x062F), "/afii57423" },
+ { GUINT_TO_POINTER (0x0630), "/afii57424" },
+ { GUINT_TO_POINTER (0x0631), "/afii57425" },
+ { GUINT_TO_POINTER (0x0632), "/afii57426" },
+ { GUINT_TO_POINTER (0x0633), "/afii57427" },
+ { GUINT_TO_POINTER (0x0634), "/afii57428" },
+ { GUINT_TO_POINTER (0x0635), "/afii57429" },
+ { GUINT_TO_POINTER (0x0636), "/afii57430" },
+ { GUINT_TO_POINTER (0x0637), "/afii57431" },
+ { GUINT_TO_POINTER (0x0638), "/afii57432" },
+ { GUINT_TO_POINTER (0x0639), "/afii57433" },
+ { GUINT_TO_POINTER (0x063A), "/afii57434" },
+ { GUINT_TO_POINTER (0x0640), "/afii57440" },
+ { GUINT_TO_POINTER (0x0641), "/afii57441" },
+ { GUINT_TO_POINTER (0x0642), "/afii57442" },
+ { GUINT_TO_POINTER (0x0643), "/afii57443" },
+ { GUINT_TO_POINTER (0x0644), "/afii57444" },
+ { GUINT_TO_POINTER (0x0645), "/afii57445" },
+ { GUINT_TO_POINTER (0x0646), "/afii57446" },
+ { GUINT_TO_POINTER (0x0648), "/afii57448" },
+ { GUINT_TO_POINTER (0x0649), "/afii57449" },
+ { GUINT_TO_POINTER (0x064A), "/afii57450" },
+ { GUINT_TO_POINTER (0x064B), "/afii57451" },
+ { GUINT_TO_POINTER (0x064C), "/afii57452" },
+ { GUINT_TO_POINTER (0x064D), "/afii57453" },
+ { GUINT_TO_POINTER (0x064E), "/afii57454" },
+ { GUINT_TO_POINTER (0x064F), "/afii57455" },
+ { GUINT_TO_POINTER (0x0650), "/afii57456" },
+ { GUINT_TO_POINTER (0x0651), "/afii57457" },
+ { GUINT_TO_POINTER (0x0652), "/afii57458" },
+ { GUINT_TO_POINTER (0x0647), "/afii57470" },
+ { GUINT_TO_POINTER (0x06A4), "/afii57505" },
+ { GUINT_TO_POINTER (0x067E), "/afii57506" },
+ { GUINT_TO_POINTER (0x0686), "/afii57507" },
+ { GUINT_TO_POINTER (0x0698), "/afii57508" },
+ { GUINT_TO_POINTER (0x06AF), "/afii57509" },
+ { GUINT_TO_POINTER (0x0679), "/afii57511" },
+ { GUINT_TO_POINTER (0x0688), "/afii57512" },
+ { GUINT_TO_POINTER (0x0691), "/afii57513" },
+ { GUINT_TO_POINTER (0x06BA), "/afii57514" },
+ { GUINT_TO_POINTER (0x06D2), "/afii57519" },
+ { GUINT_TO_POINTER (0x06D5), "/afii57534" },
+ { GUINT_TO_POINTER (0x20AA), "/afii57636" },
+ { GUINT_TO_POINTER (0x05BE), "/afii57645" },
+ { GUINT_TO_POINTER (0x05C3), "/afii57658" },
+ { GUINT_TO_POINTER (0x05D0), "/afii57664" },
+ { GUINT_TO_POINTER (0x05D1), "/afii57665" },
+ { GUINT_TO_POINTER (0x05D2), "/afii57666" },
+ { GUINT_TO_POINTER (0x05D3), "/afii57667" },
+ { GUINT_TO_POINTER (0x05D4), "/afii57668" },
+ { GUINT_TO_POINTER (0x05D5), "/afii57669" },
+ { GUINT_TO_POINTER (0x05D6), "/afii57670" },
+ { GUINT_TO_POINTER (0x05D7), "/afii57671" },
+ { GUINT_TO_POINTER (0x05D8), "/afii57672" },
+ { GUINT_TO_POINTER (0x05D9), "/afii57673" },
+ { GUINT_TO_POINTER (0x05DA), "/afii57674" },
+ { GUINT_TO_POINTER (0x05DB), "/afii57675" },
+ { GUINT_TO_POINTER (0x05DC), "/afii57676" },
+ { GUINT_TO_POINTER (0x05DD), "/afii57677" },
+ { GUINT_TO_POINTER (0x05DE), "/afii57678" },
+ { GUINT_TO_POINTER (0x05DF), "/afii57679" },
+ { GUINT_TO_POINTER (0x05E0), "/afii57680" },
+ { GUINT_TO_POINTER (0x05E1), "/afii57681" },
+ { GUINT_TO_POINTER (0x05E2), "/afii57682" },
+ { GUINT_TO_POINTER (0x05E3), "/afii57683" },
+ { GUINT_TO_POINTER (0x05E4), "/afii57684" },
+ { GUINT_TO_POINTER (0x05E5), "/afii57685" },
+ { GUINT_TO_POINTER (0x05E6), "/afii57686" },
+ { GUINT_TO_POINTER (0x05E7), "/afii57687" },
+ { GUINT_TO_POINTER (0x05E8), "/afii57688" },
+ { GUINT_TO_POINTER (0x05E9), "/afii57689" },
+ { GUINT_TO_POINTER (0x05EA), "/afii57690" },
+ { GUINT_TO_POINTER (0xFB2A), "/afii57694" },
+ { GUINT_TO_POINTER (0xFB2B), "/afii57695" },
+ { GUINT_TO_POINTER (0xFB4B), "/afii57700" },
+ { GUINT_TO_POINTER (0xFB1F), "/afii57705" },
+ { GUINT_TO_POINTER (0x05F0), "/afii57716" },
+ { GUINT_TO_POINTER (0x05F1), "/afii57717" },
+ { GUINT_TO_POINTER (0x05F2), "/afii57718" },
+ { GUINT_TO_POINTER (0xFB35), "/afii57723" },
+ { GUINT_TO_POINTER (0x05B4), "/afii57793" },
+ { GUINT_TO_POINTER (0x05B5), "/afii57794" },
+ { GUINT_TO_POINTER (0x05B6), "/afii57795" },
+ { GUINT_TO_POINTER (0x05BB), "/afii57796" },
+ { GUINT_TO_POINTER (0x05B8), "/afii57797" },
+ { GUINT_TO_POINTER (0x05B7), "/afii57798" },
+ { GUINT_TO_POINTER (0x05B0), "/afii57799" },
+ { GUINT_TO_POINTER (0x05B2), "/afii57800" },
+ { GUINT_TO_POINTER (0x05B1), "/afii57801" },
+ { GUINT_TO_POINTER (0x05B3), "/afii57802" },
+ { GUINT_TO_POINTER (0x05C2), "/afii57803" },
+ { GUINT_TO_POINTER (0x05C1), "/afii57804" },
+ { GUINT_TO_POINTER (0x05B9), "/afii57806" },
+ { GUINT_TO_POINTER (0x05BC), "/afii57807" },
+ { GUINT_TO_POINTER (0x05BD), "/afii57839" },
+ { GUINT_TO_POINTER (0x05BF), "/afii57841" },
+ { GUINT_TO_POINTER (0x05C0), "/afii57842" },
+ { GUINT_TO_POINTER (0x02BC), "/afii57929" },
+ { GUINT_TO_POINTER (0x2105), "/afii61248" },
+ { GUINT_TO_POINTER (0x2113), "/afii61289" },
+ { GUINT_TO_POINTER (0x2116), "/afii61352" },
+ { GUINT_TO_POINTER (0x202C), "/afii61573" },
+ { GUINT_TO_POINTER (0x202D), "/afii61574" },
+ { GUINT_TO_POINTER (0x202E), "/afii61575" },
+ { GUINT_TO_POINTER (0x200C), "/afii61664" },
+ { GUINT_TO_POINTER (0x066D), "/afii63167" },
+ { GUINT_TO_POINTER (0x02BD), "/afii64937" },
+ { GUINT_TO_POINTER (0x00E0), "/agrave" },
+ { GUINT_TO_POINTER (0x0A85), "/agujarati" },
+ { GUINT_TO_POINTER (0x0A05), "/agurmukhi" },
+ { GUINT_TO_POINTER (0x3042), "/ahiragana" },
+ { GUINT_TO_POINTER (0x1EA3), "/ahookabove" },
+ { GUINT_TO_POINTER (0x0990), "/aibengali" },
+ { GUINT_TO_POINTER (0x311E), "/aibopomofo" },
+ { GUINT_TO_POINTER (0x0910), "/aideva" },
+ { GUINT_TO_POINTER (0x04D5), "/aiecyrillic" },
+ { GUINT_TO_POINTER (0x0A90), "/aigujarati" },
+ { GUINT_TO_POINTER (0x0A10), "/aigurmukhi" },
+ { GUINT_TO_POINTER (0x0A48), "/aimatragurmukhi" },
+ { GUINT_TO_POINTER (0x0639), "/ainarabic" },
+ { GUINT_TO_POINTER (0xFECA), "/ainfinalarabic" },
+ { GUINT_TO_POINTER (0xFECB), "/aininitialarabic" },
+ { GUINT_TO_POINTER (0xFECC), "/ainmedialarabic" },
+ { GUINT_TO_POINTER (0x0203), "/ainvertedbreve" },
+ { GUINT_TO_POINTER (0x09C8), "/aivowelsignbengali" },
+ { GUINT_TO_POINTER (0x0948), "/aivowelsigndeva" },
+ { GUINT_TO_POINTER (0x0AC8), "/aivowelsigngujarati" },
+ { GUINT_TO_POINTER (0x30A2), "/akatakana" },
+ { GUINT_TO_POINTER (0xFF71), "/akatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x314F), "/akorean" },
+ { GUINT_TO_POINTER (0x05D0), "/alef" },
+ { GUINT_TO_POINTER (0x0627), "/alefarabic" },
+ { GUINT_TO_POINTER (0xFB30), "/alefdageshhebrew" },
+ { GUINT_TO_POINTER (0xFE8E), "/aleffinalarabic" },
+ { GUINT_TO_POINTER (0x0623), "/alefhamzaabovearabic" },
+ { GUINT_TO_POINTER (0xFE84), "/alefhamzaabovefinalarabic" },
+ { GUINT_TO_POINTER (0x0625), "/alefhamzabelowarabic" },
+ { GUINT_TO_POINTER (0xFE88), "/alefhamzabelowfinalarabic" },
+ { GUINT_TO_POINTER (0x05D0), "/alefhebrew" },
+ { GUINT_TO_POINTER (0xFB4F), "/aleflamedhebrew" },
+ { GUINT_TO_POINTER (0x0622), "/alefmaddaabovearabic" },
+ { GUINT_TO_POINTER (0xFE82), "/alefmaddaabovefinalarabic" },
+ { GUINT_TO_POINTER (0x0649), "/alefmaksuraarabic" },
+ { GUINT_TO_POINTER (0xFEF0), "/alefmaksurafinalarabic" },
+ { GUINT_TO_POINTER (0xFEF3), "/alefmaksurainitialarabic" },
+ { GUINT_TO_POINTER (0xFEF4), "/alefmaksuramedialarabic" },
+ { GUINT_TO_POINTER (0xFB2E), "/alefpatahhebrew" },
+ { GUINT_TO_POINTER (0xFB2F), "/alefqamatshebrew" },
+ { GUINT_TO_POINTER (0x2135), "/aleph" },
+ { GUINT_TO_POINTER (0x224C), "/allequal" },
+ { GUINT_TO_POINTER (0x03B1), "/alpha" },
+ { GUINT_TO_POINTER (0x03AC), "/alphatonos" },
+ { GUINT_TO_POINTER (0x0101), "/amacron" },
+ { GUINT_TO_POINTER (0xFF41), "/amonospace" },
+ { GUINT_TO_POINTER (0x0026), "/ampersand" },
+ { GUINT_TO_POINTER (0xFF06), "/ampersandmonospace" },
+ { GUINT_TO_POINTER (0xF726), "/ampersandsmall" },
+ { GUINT_TO_POINTER (0x33C2), "/amsquare" },
+ { GUINT_TO_POINTER (0x3122), "/anbopomofo" },
+ { GUINT_TO_POINTER (0x3124), "/angbopomofo" },
+ { GUINT_TO_POINTER (0x0E5A), "/angkhankhuthai" },
+ { GUINT_TO_POINTER (0x2220), "/angle" },
+ { GUINT_TO_POINTER (0x3008), "/anglebracketleft" },
+ { GUINT_TO_POINTER (0xFE3F), "/anglebracketleftvertical" },
+ { GUINT_TO_POINTER (0x3009), "/anglebracketright" },
+ { GUINT_TO_POINTER (0xFE40), "/anglebracketrightvertical" },
+ { GUINT_TO_POINTER (0x2329), "/angleleft" },
+ { GUINT_TO_POINTER (0x232A), "/angleright" },
+ { GUINT_TO_POINTER (0x212B), "/angstrom" },
+ { GUINT_TO_POINTER (0x0387), "/anoteleia" },
+ { GUINT_TO_POINTER (0x0952), "/anudattadeva" },
+ { GUINT_TO_POINTER (0x0982), "/anusvarabengali" },
+ { GUINT_TO_POINTER (0x0902), "/anusvaradeva" },
+ { GUINT_TO_POINTER (0x0A82), "/anusvaragujarati" },
+ { GUINT_TO_POINTER (0x0105), "/aogonek" },
+ { GUINT_TO_POINTER (0x3300), "/apaatosquare" },
+ { GUINT_TO_POINTER (0x249C), "/aparen" },
+ { GUINT_TO_POINTER (0x055A), "/apostrophearmenian" },
+ { GUINT_TO_POINTER (0x02BC), "/apostrophemod" },
+ { GUINT_TO_POINTER (0xF8FF), "/apple" },
+ { GUINT_TO_POINTER (0x2250), "/approaches" },
+ { GUINT_TO_POINTER (0x2248), "/approxequal" },
+ { GUINT_TO_POINTER (0x2252), "/approxequalorimage" },
+ { GUINT_TO_POINTER (0x2245), "/approximatelyequal" },
+ { GUINT_TO_POINTER (0x318E), "/araeaekorean" },
+ { GUINT_TO_POINTER (0x318D), "/araeakorean" },
+ { GUINT_TO_POINTER (0x2312), "/arc" },
+ { GUINT_TO_POINTER (0x1E9A), "/arighthalfring" },
+ { GUINT_TO_POINTER (0x00E5), "/aring" },
+ { GUINT_TO_POINTER (0x01FB), "/aringacute" },
+ { GUINT_TO_POINTER (0x1E01), "/aringbelow" },
+ { GUINT_TO_POINTER (0x2194), "/arrowboth" },
+ { GUINT_TO_POINTER (0x21E3), "/arrowdashdown" },
+ { GUINT_TO_POINTER (0x21E0), "/arrowdashleft" },
+ { GUINT_TO_POINTER (0x21E2), "/arrowdashright" },
+ { GUINT_TO_POINTER (0x21E1), "/arrowdashup" },
+ { GUINT_TO_POINTER (0x21D4), "/arrowdblboth" },
+ { GUINT_TO_POINTER (0x21D3), "/arrowdbldown" },
+ { GUINT_TO_POINTER (0x21D0), "/arrowdblleft" },
+ { GUINT_TO_POINTER (0x21D2), "/arrowdblright" },
+ { GUINT_TO_POINTER (0x21D1), "/arrowdblup" },
+ { GUINT_TO_POINTER (0x2193), "/arrowdown" },
+ { GUINT_TO_POINTER (0x2199), "/arrowdownleft" },
+ { GUINT_TO_POINTER (0x2198), "/arrowdownright" },
+ { GUINT_TO_POINTER (0x21E9), "/arrowdownwhite" },
+ { GUINT_TO_POINTER (0x02C5), "/arrowheaddownmod" },
+ { GUINT_TO_POINTER (0x02C2), "/arrowheadleftmod" },
+ { GUINT_TO_POINTER (0x02C3), "/arrowheadrightmod" },
+ { GUINT_TO_POINTER (0x02C4), "/arrowheadupmod" },
+ { GUINT_TO_POINTER (0xF8E7), "/arrowhorizex" },
+ { GUINT_TO_POINTER (0x2190), "/arrowleft" },
+ { GUINT_TO_POINTER (0x21D0), "/arrowleftdbl" },
+ { GUINT_TO_POINTER (0x21CD), "/arrowleftdblstroke" },
+ { GUINT_TO_POINTER (0x21C6), "/arrowleftoverright" },
+ { GUINT_TO_POINTER (0x21E6), "/arrowleftwhite" },
+ { GUINT_TO_POINTER (0x2192), "/arrowright" },
+ { GUINT_TO_POINTER (0x21CF), "/arrowrightdblstroke" },
+ { GUINT_TO_POINTER (0x279E), "/arrowrightheavy" },
+ { GUINT_TO_POINTER (0x21C4), "/arrowrightoverleft" },
+ { GUINT_TO_POINTER (0x21E8), "/arrowrightwhite" },
+ { GUINT_TO_POINTER (0x21E4), "/arrowtableft" },
+ { GUINT_TO_POINTER (0x21E5), "/arrowtabright" },
+ { GUINT_TO_POINTER (0x2191), "/arrowup" },
+ { GUINT_TO_POINTER (0x2195), "/arrowupdn" },
+ { GUINT_TO_POINTER (0x21A8), "/arrowupdnbse" },
+ { GUINT_TO_POINTER (0x21A8), "/arrowupdownbase" },
+ { GUINT_TO_POINTER (0x2196), "/arrowupleft" },
+ { GUINT_TO_POINTER (0x21C5), "/arrowupleftofdown" },
+ { GUINT_TO_POINTER (0x2197), "/arrowupright" },
+ { GUINT_TO_POINTER (0x21E7), "/arrowupwhite" },
+ { GUINT_TO_POINTER (0xF8E6), "/arrowvertex" },
+ { GUINT_TO_POINTER (0x005E), "/asciicircum" },
+ { GUINT_TO_POINTER (0xFF3E), "/asciicircummonospace" },
+ { GUINT_TO_POINTER (0x007E), "/asciitilde" },
+ { GUINT_TO_POINTER (0xFF5E), "/asciitildemonospace" },
+ { GUINT_TO_POINTER (0x0251), "/ascript" },
+ { GUINT_TO_POINTER (0x0252), "/ascriptturned" },
+ { GUINT_TO_POINTER (0x3041), "/asmallhiragana" },
+ { GUINT_TO_POINTER (0x30A1), "/asmallkatakana" },
+ { GUINT_TO_POINTER (0xFF67), "/asmallkatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x002A), "/asterisk" },
+ { GUINT_TO_POINTER (0x066D), "/asteriskaltonearabic" },
+ { GUINT_TO_POINTER (0x066D), "/asteriskarabic" },
+ { GUINT_TO_POINTER (0x2217), "/asteriskmath" },
+ { GUINT_TO_POINTER (0xFF0A), "/asteriskmonospace" },
+ { GUINT_TO_POINTER (0xFE61), "/asterisksmall" },
+ { GUINT_TO_POINTER (0x2042), "/asterism" },
+ { GUINT_TO_POINTER (0xF6E9), "/asuperior" },
+ { GUINT_TO_POINTER (0x2243), "/asymptoticallyequal" },
+ { GUINT_TO_POINTER (0x0040), "/at" },
+ { GUINT_TO_POINTER (0x00E3), "/atilde" },
+ { GUINT_TO_POINTER (0xFF20), "/atmonospace" },
+ { GUINT_TO_POINTER (0xFE6B), "/atsmall" },
+ { GUINT_TO_POINTER (0x0250), "/aturned" },
+ { GUINT_TO_POINTER (0x0994), "/aubengali" },
+ { GUINT_TO_POINTER (0x3120), "/aubopomofo" },
+ { GUINT_TO_POINTER (0x0914), "/audeva" },
+ { GUINT_TO_POINTER (0x0A94), "/augujarati" },
+ { GUINT_TO_POINTER (0x0A14), "/augurmukhi" },
+ { GUINT_TO_POINTER (0x09D7), "/aulengthmarkbengali" },
+ { GUINT_TO_POINTER (0x0A4C), "/aumatragurmukhi" },
+ { GUINT_TO_POINTER (0x09CC), "/auvowelsignbengali" },
+ { GUINT_TO_POINTER (0x094C), "/auvowelsigndeva" },
+ { GUINT_TO_POINTER (0x0ACC), "/auvowelsigngujarati" },
+ { GUINT_TO_POINTER (0x093D), "/avagrahadeva" },
+ { GUINT_TO_POINTER (0x0561), "/aybarmenian" },
+ { GUINT_TO_POINTER (0x05E2), "/ayin" },
+ { GUINT_TO_POINTER (0xFB20), "/ayinaltonehebrew" },
+ { GUINT_TO_POINTER (0x05E2), "/ayinhebrew" },
+ { GUINT_TO_POINTER (0x0062), "/b" },
+ { GUINT_TO_POINTER (0x09AC), "/babengali" },
+ { GUINT_TO_POINTER (0x005C), "/backslash" },
+ { GUINT_TO_POINTER (0xFF3C), "/backslashmonospace" },
+ { GUINT_TO_POINTER (0x092C), "/badeva" },
+ { GUINT_TO_POINTER (0x0AAC), "/bagujarati" },
+ { GUINT_TO_POINTER (0x0A2C), "/bagurmukhi" },
+ { GUINT_TO_POINTER (0x3070), "/bahiragana" },
+ { GUINT_TO_POINTER (0x0E3F), "/bahtthai" },
+ { GUINT_TO_POINTER (0x30D0), "/bakatakana" },
+ { GUINT_TO_POINTER (0x007C), "/bar" },
+ { GUINT_TO_POINTER (0xFF5C), "/barmonospace" },
+ { GUINT_TO_POINTER (0x3105), "/bbopomofo" },
+ { GUINT_TO_POINTER (0x24D1), "/bcircle" },
+ { GUINT_TO_POINTER (0x1E03), "/bdotaccent" },
+ { GUINT_TO_POINTER (0x1E05), "/bdotbelow" },
+ { GUINT_TO_POINTER (0x266C), "/beamedsixteenthnotes" },
+ { GUINT_TO_POINTER (0x2235), "/because" },
+ { GUINT_TO_POINTER (0x0431), "/becyrillic" },
+ { GUINT_TO_POINTER (0x0628), "/beharabic" },
+ { GUINT_TO_POINTER (0xFE90), "/behfinalarabic" },
+ { GUINT_TO_POINTER (0xFE91), "/behinitialarabic" },
+ { GUINT_TO_POINTER (0x3079), "/behiragana" },
+ { GUINT_TO_POINTER (0xFE92), "/behmedialarabic" },
+ { GUINT_TO_POINTER (0xFC9F), "/behmeeminitialarabic" },
+ { GUINT_TO_POINTER (0xFC08), "/behmeemisolatedarabic" },
+ { GUINT_TO_POINTER (0xFC6D), "/behnoonfinalarabic" },
+ { GUINT_TO_POINTER (0x30D9), "/bekatakana" },
+ { GUINT_TO_POINTER (0x0562), "/benarmenian" },
+ { GUINT_TO_POINTER (0x05D1), "/bet" },
+ { GUINT_TO_POINTER (0x03B2), "/beta" },
+ { GUINT_TO_POINTER (0x03D0), "/betasymbolgreek" },
+ { GUINT_TO_POINTER (0xFB31), "/betdagesh" },
+ { GUINT_TO_POINTER (0xFB31), "/betdageshhebrew" },
+ { GUINT_TO_POINTER (0x05D1), "/bethebrew" },
+ { GUINT_TO_POINTER (0xFB4C), "/betrafehebrew" },
+ { GUINT_TO_POINTER (0x09AD), "/bhabengali" },
+ { GUINT_TO_POINTER (0x092D), "/bhadeva" },
+ { GUINT_TO_POINTER (0x0AAD), "/bhagujarati" },
+ { GUINT_TO_POINTER (0x0A2D), "/bhagurmukhi" },
+ { GUINT_TO_POINTER (0x0253), "/bhook" },
+ { GUINT_TO_POINTER (0x3073), "/bihiragana" },
+ { GUINT_TO_POINTER (0x30D3), "/bikatakana" },
+ { GUINT_TO_POINTER (0x0298), "/bilabialclick" },
+ { GUINT_TO_POINTER (0x0A02), "/bindigurmukhi" },
+ { GUINT_TO_POINTER (0x3331), "/birusquare" },
+ { GUINT_TO_POINTER (0x25CF), "/blackcircle" },
+ { GUINT_TO_POINTER (0x25C6), "/blackdiamond" },
+ { GUINT_TO_POINTER (0x25BC), "/blackdownpointingtriangle" },
+ { GUINT_TO_POINTER (0x25C4), "/blackleftpointingpointer" },
+ { GUINT_TO_POINTER (0x25C0), "/blackleftpointingtriangle" },
+ { GUINT_TO_POINTER (0x3010), "/blacklenticularbracketleft" },
+ { GUINT_TO_POINTER (0xFE3B), "/blacklenticularbracketleftvertical" },
+ { GUINT_TO_POINTER (0x3011), "/blacklenticularbracketright" },
+ { GUINT_TO_POINTER (0xFE3C), "/blacklenticularbracketrightvertical" },
+ { GUINT_TO_POINTER (0x25E3), "/blacklowerlefttriangle" },
+ { GUINT_TO_POINTER (0x25E2), "/blacklowerrighttriangle" },
+ { GUINT_TO_POINTER (0x25AC), "/blackrectangle" },
+ { GUINT_TO_POINTER (0x25BA), "/blackrightpointingpointer" },
+ { GUINT_TO_POINTER (0x25B6), "/blackrightpointingtriangle" },
+ { GUINT_TO_POINTER (0x25AA), "/blacksmallsquare" },
+ { GUINT_TO_POINTER (0x263B), "/blacksmilingface" },
+ { GUINT_TO_POINTER (0x25A0), "/blacksquare" },
+ { GUINT_TO_POINTER (0x2605), "/blackstar" },
+ { GUINT_TO_POINTER (0x25E4), "/blackupperlefttriangle" },
+ { GUINT_TO_POINTER (0x25E5), "/blackupperrighttriangle" },
+ { GUINT_TO_POINTER (0x25B4), "/blackuppointingsmalltriangle" },
+ { GUINT_TO_POINTER (0x25B2), "/blackuppointingtriangle" },
+ { GUINT_TO_POINTER (0x2423), "/blank" },
+ { GUINT_TO_POINTER (0x1E07), "/blinebelow" },
+ { GUINT_TO_POINTER (0x2588), "/block" },
+ { GUINT_TO_POINTER (0xFF42), "/bmonospace" },
+ { GUINT_TO_POINTER (0x0E1A), "/bobaimaithai" },
+ { GUINT_TO_POINTER (0x307C), "/bohiragana" },
+ { GUINT_TO_POINTER (0x30DC), "/bokatakana" },
+ { GUINT_TO_POINTER (0x249D), "/bparen" },
+ { GUINT_TO_POINTER (0x33C3), "/bqsquare" },
+ { GUINT_TO_POINTER (0xF8F4), "/braceex" },
+ { GUINT_TO_POINTER (0x007B), "/braceleft" },
+ { GUINT_TO_POINTER (0xF8F3), "/braceleftbt" },
+ { GUINT_TO_POINTER (0xF8F2), "/braceleftmid" },
+ { GUINT_TO_POINTER (0xFF5B), "/braceleftmonospace" },
+ { GUINT_TO_POINTER (0xFE5B), "/braceleftsmall" },
+ { GUINT_TO_POINTER (0xF8F1), "/bracelefttp" },
+ { GUINT_TO_POINTER (0xFE37), "/braceleftvertical" },
+ { GUINT_TO_POINTER (0x007D), "/braceright" },
+ { GUINT_TO_POINTER (0xF8FE), "/bracerightbt" },
+ { GUINT_TO_POINTER (0xF8FD), "/bracerightmid" },
+ { GUINT_TO_POINTER (0xFF5D), "/bracerightmonospace" },
+ { GUINT_TO_POINTER (0xFE5C), "/bracerightsmall" },
+ { GUINT_TO_POINTER (0xF8FC), "/bracerighttp" },
+ { GUINT_TO_POINTER (0xFE38), "/bracerightvertical" },
+ { GUINT_TO_POINTER (0x005B), "/bracketleft" },
+ { GUINT_TO_POINTER (0xF8F0), "/bracketleftbt" },
+ { GUINT_TO_POINTER (0xF8EF), "/bracketleftex" },
+ { GUINT_TO_POINTER (0xFF3B), "/bracketleftmonospace" },
+ { GUINT_TO_POINTER (0xF8EE), "/bracketlefttp" },
+ { GUINT_TO_POINTER (0x005D), "/bracketright" },
+ { GUINT_TO_POINTER (0xF8FB), "/bracketrightbt" },
+ { GUINT_TO_POINTER (0xF8FA), "/bracketrightex" },
+ { GUINT_TO_POINTER (0xFF3D), "/bracketrightmonospace" },
+ { GUINT_TO_POINTER (0xF8F9), "/bracketrighttp" },
+ { GUINT_TO_POINTER (0x02D8), "/breve" },
+ { GUINT_TO_POINTER (0x032E), "/brevebelowcmb" },
+ { GUINT_TO_POINTER (0x0306), "/brevecmb" },
+ { GUINT_TO_POINTER (0x032F), "/breveinvertedbelowcmb" },
+ { GUINT_TO_POINTER (0x0311), "/breveinvertedcmb" },
+ { GUINT_TO_POINTER (0x0361), "/breveinverteddoublecmb" },
+ { GUINT_TO_POINTER (0x032A), "/bridgebelowcmb" },
+ { GUINT_TO_POINTER (0x033A), "/bridgeinvertedbelowcmb" },
+ { GUINT_TO_POINTER (0x00A6), "/brokenbar" },
+ { GUINT_TO_POINTER (0x0180), "/bstroke" },
+ { GUINT_TO_POINTER (0xF6EA), "/bsuperior" },
+ { GUINT_TO_POINTER (0x0183), "/btopbar" },
+ { GUINT_TO_POINTER (0x3076), "/buhiragana" },
+ { GUINT_TO_POINTER (0x30D6), "/bukatakana" },
+ { GUINT_TO_POINTER (0x2022), "/bullet" },
+ { GUINT_TO_POINTER (0x25D8), "/bulletinverse" },
+ { GUINT_TO_POINTER (0x2219), "/bulletoperator" },
+ { GUINT_TO_POINTER (0x25CE), "/bullseye" },
+ { GUINT_TO_POINTER (0x0063), "/c" },
+ { GUINT_TO_POINTER (0x056E), "/caarmenian" },
+ { GUINT_TO_POINTER (0x099A), "/cabengali" },
+ { GUINT_TO_POINTER (0x0107), "/cacute" },
+ { GUINT_TO_POINTER (0x091A), "/cadeva" },
+ { GUINT_TO_POINTER (0x0A9A), "/cagujarati" },
+ { GUINT_TO_POINTER (0x0A1A), "/cagurmukhi" },
+ { GUINT_TO_POINTER (0x3388), "/calsquare" },
+ { GUINT_TO_POINTER (0x0981), "/candrabindubengali" },
+ { GUINT_TO_POINTER (0x0310), "/candrabinducmb" },
+ { GUINT_TO_POINTER (0x0901), "/candrabindudeva" },
+ { GUINT_TO_POINTER (0x0A81), "/candrabindugujarati" },
+ { GUINT_TO_POINTER (0x21EA), "/capslock" },
+ { GUINT_TO_POINTER (0x2105), "/careof" },
+ { GUINT_TO_POINTER (0x02C7), "/caron" },
+ { GUINT_TO_POINTER (0x032C), "/caronbelowcmb" },
+ { GUINT_TO_POINTER (0x030C), "/caroncmb" },
+ { GUINT_TO_POINTER (0x21B5), "/carriagereturn" },
+ { GUINT_TO_POINTER (0x3118), "/cbopomofo" },
+ { GUINT_TO_POINTER (0x010D), "/ccaron" },
+ { GUINT_TO_POINTER (0x00E7), "/ccedilla" },
+ { GUINT_TO_POINTER (0x1E09), "/ccedillaacute" },
+ { GUINT_TO_POINTER (0x24D2), "/ccircle" },
+ { GUINT_TO_POINTER (0x0109), "/ccircumflex" },
+ { GUINT_TO_POINTER (0x0255), "/ccurl" },
+ { GUINT_TO_POINTER (0x010B), "/cdot" },
+ { GUINT_TO_POINTER (0x010B), "/cdotaccent" },
+ { GUINT_TO_POINTER (0x33C5), "/cdsquare" },
+ { GUINT_TO_POINTER (0x00B8), "/cedilla" },
+ { GUINT_TO_POINTER (0x0327), "/cedillacmb" },
+ { GUINT_TO_POINTER (0x00A2), "/cent" },
+ { GUINT_TO_POINTER (0x2103), "/centigrade" },
+ { GUINT_TO_POINTER (0xF6DF), "/centinferior" },
+ { GUINT_TO_POINTER (0xFFE0), "/centmonospace" },
+ { GUINT_TO_POINTER (0xF7A2), "/centoldstyle" },
+ { GUINT_TO_POINTER (0xF6E0), "/centsuperior" },
+ { GUINT_TO_POINTER (0x0579), "/chaarmenian" },
+ { GUINT_TO_POINTER (0x099B), "/chabengali" },
+ { GUINT_TO_POINTER (0x091B), "/chadeva" },
+ { GUINT_TO_POINTER (0x0A9B), "/chagujarati" },
+ { GUINT_TO_POINTER (0x0A1B), "/chagurmukhi" },
+ { GUINT_TO_POINTER (0x3114), "/chbopomofo" },
+ { GUINT_TO_POINTER (0x04BD), "/cheabkhasiancyrillic" },
+ { GUINT_TO_POINTER (0x2713), "/checkmark" },
+ { GUINT_TO_POINTER (0x0447), "/checyrillic" },
+ { GUINT_TO_POINTER (0x04BF), "/chedescenderabkhasiancyrillic" },
+ { GUINT_TO_POINTER (0x04B7), "/chedescendercyrillic" },
+ { GUINT_TO_POINTER (0x04F5), "/chedieresiscyrillic" },
+ { GUINT_TO_POINTER (0x0573), "/cheharmenian" },
+ { GUINT_TO_POINTER (0x04CC), "/chekhakassiancyrillic" },
+ { GUINT_TO_POINTER (0x04B9), "/cheverticalstrokecyrillic" },
+ { GUINT_TO_POINTER (0x03C7), "/chi" },
+ { GUINT_TO_POINTER (0x3277), "/chieuchacirclekorean" },
+ { GUINT_TO_POINTER (0x3217), "/chieuchaparenkorean" },
+ { GUINT_TO_POINTER (0x3269), "/chieuchcirclekorean" },
+ { GUINT_TO_POINTER (0x314A), "/chieuchkorean" },
+ { GUINT_TO_POINTER (0x3209), "/chieuchparenkorean" },
+ { GUINT_TO_POINTER (0x0E0A), "/chochangthai" },
+ { GUINT_TO_POINTER (0x0E08), "/chochanthai" },
+ { GUINT_TO_POINTER (0x0E09), "/chochingthai" },
+ { GUINT_TO_POINTER (0x0E0C), "/chochoethai" },
+ { GUINT_TO_POINTER (0x0188), "/chook" },
+ { GUINT_TO_POINTER (0x3276), "/cieucacirclekorean" },
+ { GUINT_TO_POINTER (0x3216), "/cieucaparenkorean" },
+ { GUINT_TO_POINTER (0x3268), "/cieuccirclekorean" },
+ { GUINT_TO_POINTER (0x3148), "/cieuckorean" },
+ { GUINT_TO_POINTER (0x3208), "/cieucparenkorean" },
+ { GUINT_TO_POINTER (0x321C), "/cieucuparenkorean" },
+ { GUINT_TO_POINTER (0x25CB), "/circle" },
+ { GUINT_TO_POINTER (0x2297), "/circlemultiply" },
+ { GUINT_TO_POINTER (0x2299), "/circleot" },
+ { GUINT_TO_POINTER (0x2295), "/circleplus" },
+ { GUINT_TO_POINTER (0x3036), "/circlepostalmark" },
+ { GUINT_TO_POINTER (0x25D0), "/circlewithlefthalfblack" },
+ { GUINT_TO_POINTER (0x25D1), "/circlewithrighthalfblack" },
+ { GUINT_TO_POINTER (0x02C6), "/circumflex" },
+ { GUINT_TO_POINTER (0x032D), "/circumflexbelowcmb" },
+ { GUINT_TO_POINTER (0x0302), "/circumflexcmb" },
+ { GUINT_TO_POINTER (0x2327), "/clear" },
+ { GUINT_TO_POINTER (0x01C2), "/clickalveolar" },
+ { GUINT_TO_POINTER (0x01C0), "/clickdental" },
+ { GUINT_TO_POINTER (0x01C1), "/clicklateral" },
+ { GUINT_TO_POINTER (0x01C3), "/clickretroflex" },
+ { GUINT_TO_POINTER (0x2663), "/club" },
+ { GUINT_TO_POINTER (0x2663), "/clubsuitblack" },
+ { GUINT_TO_POINTER (0x2667), "/clubsuitwhite" },
+ { GUINT_TO_POINTER (0x33A4), "/cmcubedsquare" },
+ { GUINT_TO_POINTER (0xFF43), "/cmonospace" },
+ { GUINT_TO_POINTER (0x33A0), "/cmsquaredsquare" },
+ { GUINT_TO_POINTER (0x0581), "/coarmenian" },
+ { GUINT_TO_POINTER (0x003A), "/colon" },
+ { GUINT_TO_POINTER (0x20A1), "/colonmonetary" },
+ { GUINT_TO_POINTER (0xFF1A), "/colonmonospace" },
+ { GUINT_TO_POINTER (0x20A1), "/colonsign" },
+ { GUINT_TO_POINTER (0xFE55), "/colonsmall" },
+ { GUINT_TO_POINTER (0x02D1), "/colontriangularhalfmod" },
+ { GUINT_TO_POINTER (0x02D0), "/colontriangularmod" },
+ { GUINT_TO_POINTER (0x002C), "/comma" },
+ { GUINT_TO_POINTER (0x0313), "/commaabovecmb" },
+ { GUINT_TO_POINTER (0x0315), "/commaaboverightcmb" },
+ { GUINT_TO_POINTER (0xF6C3), "/commaaccent" },
+ { GUINT_TO_POINTER (0x060C), "/commaarabic" },
+ { GUINT_TO_POINTER (0x055D), "/commaarmenian" },
+ { GUINT_TO_POINTER (0xF6E1), "/commainferior" },
+ { GUINT_TO_POINTER (0xFF0C), "/commamonospace" },
+ { GUINT_TO_POINTER (0x0314), "/commareversedabovecmb" },
+ { GUINT_TO_POINTER (0x02BD), "/commareversedmod" },
+ { GUINT_TO_POINTER (0xFE50), "/commasmall" },
+ { GUINT_TO_POINTER (0xF6E2), "/commasuperior" },
+ { GUINT_TO_POINTER (0x0312), "/commaturnedabovecmb" },
+ { GUINT_TO_POINTER (0x02BB), "/commaturnedmod" },
+ { GUINT_TO_POINTER (0x263C), "/compass" },
+ { GUINT_TO_POINTER (0x2245), "/congruent" },
+ { GUINT_TO_POINTER (0x222E), "/contourintegral" },
+ { GUINT_TO_POINTER (0x2303), "/control" },
+ { GUINT_TO_POINTER (0x0006), "/controlACK" },
+ { GUINT_TO_POINTER (0x0007), "/controlBEL" },
+ { GUINT_TO_POINTER (0x0008), "/controlBS" },
+ { GUINT_TO_POINTER (0x0018), "/controlCAN" },
+ { GUINT_TO_POINTER (0x000D), "/controlCR" },
+ { GUINT_TO_POINTER (0x0011), "/controlDC1" },
+ { GUINT_TO_POINTER (0x0012), "/controlDC2" },
+ { GUINT_TO_POINTER (0x0013), "/controlDC3" },
+ { GUINT_TO_POINTER (0x0014), "/controlDC4" },
+ { GUINT_TO_POINTER (0x007F), "/controlDEL" },
+ { GUINT_TO_POINTER (0x0010), "/controlDLE" },
+ { GUINT_TO_POINTER (0x0019), "/controlEM" },
+ { GUINT_TO_POINTER (0x0005), "/controlENQ" },
+ { GUINT_TO_POINTER (0x0004), "/controlEOT" },
+ { GUINT_TO_POINTER (0x001B), "/controlESC" },
+ { GUINT_TO_POINTER (0x0017), "/controlETB" },
+ { GUINT_TO_POINTER (0x0003), "/controlETX" },
+ { GUINT_TO_POINTER (0x000C), "/controlFF" },
+ { GUINT_TO_POINTER (0x001C), "/controlFS" },
+ { GUINT_TO_POINTER (0x001D), "/controlGS" },
+ { GUINT_TO_POINTER (0x0009), "/controlHT" },
+ { GUINT_TO_POINTER (0x000A), "/controlLF" },
+ { GUINT_TO_POINTER (0x0015), "/controlNAK" },
+ { GUINT_TO_POINTER (0x001E), "/controlRS" },
+ { GUINT_TO_POINTER (0x000F), "/controlSI" },
+ { GUINT_TO_POINTER (0x000E), "/controlSO" },
+ { GUINT_TO_POINTER (0x0002), "/controlSOT" },
+ { GUINT_TO_POINTER (0x0001), "/controlSTX" },
+ { GUINT_TO_POINTER (0x001A), "/controlSUB" },
+ { GUINT_TO_POINTER (0x0016), "/controlSYN" },
+ { GUINT_TO_POINTER (0x001F), "/controlUS" },
+ { GUINT_TO_POINTER (0x000B), "/controlVT" },
+ { GUINT_TO_POINTER (0x00A9), "/copyright" },
+ { GUINT_TO_POINTER (0xF8E9), "/copyrightsans" },
+ { GUINT_TO_POINTER (0xF6D9), "/copyrightserif" },
+ { GUINT_TO_POINTER (0x300C), "/cornerbracketleft" },
+ { GUINT_TO_POINTER (0xFF62), "/cornerbracketlefthalfwidth" },
+ { GUINT_TO_POINTER (0xFE41), "/cornerbracketleftvertical" },
+ { GUINT_TO_POINTER (0x300D), "/cornerbracketright" },
+ { GUINT_TO_POINTER (0xFF63), "/cornerbracketrighthalfwidth" },
+ { GUINT_TO_POINTER (0xFE42), "/cornerbracketrightvertical" },
+ { GUINT_TO_POINTER (0x337F), "/corporationsquare" },
+ { GUINT_TO_POINTER (0x33C7), "/cosquare" },
+ { GUINT_TO_POINTER (0x33C6), "/coverkgsquare" },
+ { GUINT_TO_POINTER (0x249E), "/cparen" },
+ { GUINT_TO_POINTER (0x20A2), "/cruzeiro" },
+ { GUINT_TO_POINTER (0x0297), "/cstretched" },
+ { GUINT_TO_POINTER (0x22CF), "/curlyand" },
+ { GUINT_TO_POINTER (0x22CE), "/curlyor" },
+ { GUINT_TO_POINTER (0x00A4), "/currency" },
+ { GUINT_TO_POINTER (0xF6D1), "/cyrBreve" },
+ { GUINT_TO_POINTER (0xF6D2), "/cyrFlex" },
+ { GUINT_TO_POINTER (0xF6D4), "/cyrbreve" },
+ { GUINT_TO_POINTER (0xF6D5), "/cyrflex" },
+ { GUINT_TO_POINTER (0x0064), "/d" },
+ { GUINT_TO_POINTER (0x0564), "/daarmenian" },
+ { GUINT_TO_POINTER (0x09A6), "/dabengali" },
+ { GUINT_TO_POINTER (0x0636), "/dadarabic" },
+ { GUINT_TO_POINTER (0x0926), "/dadeva" },
+ { GUINT_TO_POINTER (0xFEBE), "/dadfinalarabic" },
+ { GUINT_TO_POINTER (0xFEBF), "/dadinitialarabic" },
+ { GUINT_TO_POINTER (0xFEC0), "/dadmedialarabic" },
+ { GUINT_TO_POINTER (0x05BC), "/dagesh" },
+ { GUINT_TO_POINTER (0x05BC), "/dageshhebrew" },
+ { GUINT_TO_POINTER (0x2020), "/dagger" },
+ { GUINT_TO_POINTER (0x2021), "/daggerdbl" },
+ { GUINT_TO_POINTER (0x0AA6), "/dagujarati" },
+ { GUINT_TO_POINTER (0x0A26), "/dagurmukhi" },
+ { GUINT_TO_POINTER (0x3060), "/dahiragana" },
+ { GUINT_TO_POINTER (0x30C0), "/dakatakana" },
+ { GUINT_TO_POINTER (0x062F), "/dalarabic" },
+ { GUINT_TO_POINTER (0x05D3), "/dalet" },
+ { GUINT_TO_POINTER (0xFB33), "/daletdagesh" },
+ { GUINT_TO_POINTER (0xFB33), "/daletdageshhebrew" },
+ { GUINT_TO_POINTER (0x05D3), "/dalethatafpatah" },
+ { GUINT_TO_POINTER (0x05B2), "/dalethatafpatah" },
+ { GUINT_TO_POINTER (0x05D3), "/dalethatafpatahhebrew" },
+ { GUINT_TO_POINTER (0x05B2), "/dalethatafpatahhebrew" },
+ { GUINT_TO_POINTER (0x05D3), "/dalethatafsegol" },
+ { GUINT_TO_POINTER (0x05B1), "/dalethatafsegol" },
+ { GUINT_TO_POINTER (0x05D3), "/dalethatafsegolhebrew" },
+ { GUINT_TO_POINTER (0x05B1), "/dalethatafsegolhebrew" },
+ { GUINT_TO_POINTER (0x05D3), "/dalethebrew" },
+ { GUINT_TO_POINTER (0x05D3), "/dalethiriq" },
+ { GUINT_TO_POINTER (0x05B4), "/dalethiriq" },
+ { GUINT_TO_POINTER (0x05D3), "/dalethiriqhebrew" },
+ { GUINT_TO_POINTER (0x05B4), "/dalethiriqhebrew" },
+ { GUINT_TO_POINTER (0x05D3), "/daletholam" },
+ { GUINT_TO_POINTER (0x05B9), "/daletholam" },
+ { GUINT_TO_POINTER (0x05D3), "/daletholamhebrew" },
+ { GUINT_TO_POINTER (0x05B9), "/daletholamhebrew" },
+ { GUINT_TO_POINTER (0x05D3), "/daletpatah" },
+ { GUINT_TO_POINTER (0x05B7), "/daletpatah" },
+ { GUINT_TO_POINTER (0x05D3), "/daletpatahhebrew" },
+ { GUINT_TO_POINTER (0x05B7), "/daletpatahhebrew" },
+ { GUINT_TO_POINTER (0x05D3), "/daletqamats" },
+ { GUINT_TO_POINTER (0x05B8), "/daletqamats" },
+ { GUINT_TO_POINTER (0x05D3), "/daletqamatshebrew" },
+ { GUINT_TO_POINTER (0x05B8), "/daletqamatshebrew" },
+ { GUINT_TO_POINTER (0x05D3), "/daletqubuts" },
+ { GUINT_TO_POINTER (0x05BB), "/daletqubuts" },
+ { GUINT_TO_POINTER (0x05D3), "/daletqubutshebrew" },
+ { GUINT_TO_POINTER (0x05BB), "/daletqubutshebrew" },
+ { GUINT_TO_POINTER (0x05D3), "/daletsegol" },
+ { GUINT_TO_POINTER (0x05B6), "/daletsegol" },
+ { GUINT_TO_POINTER (0x05D3), "/daletsegolhebrew" },
+ { GUINT_TO_POINTER (0x05B6), "/daletsegolhebrew" },
+ { GUINT_TO_POINTER (0x05D3), "/daletsheva" },
+ { GUINT_TO_POINTER (0x05B0), "/daletsheva" },
+ { GUINT_TO_POINTER (0x05D3), "/daletshevahebrew" },
+ { GUINT_TO_POINTER (0x05B0), "/daletshevahebrew" },
+ { GUINT_TO_POINTER (0x05D3), "/dalettsere" },
+ { GUINT_TO_POINTER (0x05B5), "/dalettsere" },
+ { GUINT_TO_POINTER (0x05D3), "/dalettserehebrew" },
+ { GUINT_TO_POINTER (0x05B5), "/dalettserehebrew" },
+ { GUINT_TO_POINTER (0xFEAA), "/dalfinalarabic" },
+ { GUINT_TO_POINTER (0x064F), "/dammaarabic" },
+ { GUINT_TO_POINTER (0x064F), "/dammalowarabic" },
+ { GUINT_TO_POINTER (0x064C), "/dammatanaltonearabic" },
+ { GUINT_TO_POINTER (0x064C), "/dammatanarabic" },
+ { GUINT_TO_POINTER (0x0964), "/danda" },
+ { GUINT_TO_POINTER (0x05A7), "/dargahebrew" },
+ { GUINT_TO_POINTER (0x05A7), "/dargalefthebrew" },
+ { GUINT_TO_POINTER (0x0485), "/dasiapneumatacyrilliccmb" },
+ { GUINT_TO_POINTER (0xF6D3), "/dblGrave" },
+ { GUINT_TO_POINTER (0x300A), "/dblanglebracketleft" },
+ { GUINT_TO_POINTER (0xFE3D), "/dblanglebracketleftvertical" },
+ { GUINT_TO_POINTER (0x300B), "/dblanglebracketright" },
+ { GUINT_TO_POINTER (0xFE3E), "/dblanglebracketrightvertical" },
+ { GUINT_TO_POINTER (0x032B), "/dblarchinvertedbelowcmb" },
+ { GUINT_TO_POINTER (0x21D4), "/dblarrowleft" },
+ { GUINT_TO_POINTER (0x21D2), "/dblarrowright" },
+ { GUINT_TO_POINTER (0x0965), "/dbldanda" },
+ { GUINT_TO_POINTER (0xF6D6), "/dblgrave" },
+ { GUINT_TO_POINTER (0x030F), "/dblgravecmb" },
+ { GUINT_TO_POINTER (0x222C), "/dblintegral" },
+ { GUINT_TO_POINTER (0x2017), "/dbllowline" },
+ { GUINT_TO_POINTER (0x0333), "/dbllowlinecmb" },
+ { GUINT_TO_POINTER (0x033F), "/dbloverlinecmb" },
+ { GUINT_TO_POINTER (0x02BA), "/dblprimemod" },
+ { GUINT_TO_POINTER (0x2016), "/dblverticalbar" },
+ { GUINT_TO_POINTER (0x030E), "/dblverticallineabovecmb" },
+ { GUINT_TO_POINTER (0x3109), "/dbopomofo" },
+ { GUINT_TO_POINTER (0x33C8), "/dbsquare" },
+ { GUINT_TO_POINTER (0x010F), "/dcaron" },
+ { GUINT_TO_POINTER (0x1E11), "/dcedilla" },
+ { GUINT_TO_POINTER (0x24D3), "/dcircle" },
+ { GUINT_TO_POINTER (0x1E13), "/dcircumflexbelow" },
+ { GUINT_TO_POINTER (0x0111), "/dcroat" },
+ { GUINT_TO_POINTER (0x09A1), "/ddabengali" },
+ { GUINT_TO_POINTER (0x0921), "/ddadeva" },
+ { GUINT_TO_POINTER (0x0AA1), "/ddagujarati" },
+ { GUINT_TO_POINTER (0x0A21), "/ddagurmukhi" },
+ { GUINT_TO_POINTER (0x0688), "/ddalarabic" },
+ { GUINT_TO_POINTER (0xFB89), "/ddalfinalarabic" },
+ { GUINT_TO_POINTER (0x095C), "/dddhadeva" },
+ { GUINT_TO_POINTER (0x09A2), "/ddhabengali" },
+ { GUINT_TO_POINTER (0x0922), "/ddhadeva" },
+ { GUINT_TO_POINTER (0x0AA2), "/ddhagujarati" },
+ { GUINT_TO_POINTER (0x0A22), "/ddhagurmukhi" },
+ { GUINT_TO_POINTER (0x1E0B), "/ddotaccent" },
+ { GUINT_TO_POINTER (0x1E0D), "/ddotbelow" },
+ { GUINT_TO_POINTER (0x066B), "/decimalseparatorarabic" },
+ { GUINT_TO_POINTER (0x066B), "/decimalseparatorpersian" },
+ { GUINT_TO_POINTER (0x0434), "/decyrillic" },
+ { GUINT_TO_POINTER (0x00B0), "/degree" },
+ { GUINT_TO_POINTER (0x05AD), "/dehihebrew" },
+ { GUINT_TO_POINTER (0x3067), "/dehiragana" },
+ { GUINT_TO_POINTER (0x03EF), "/deicoptic" },
+ { GUINT_TO_POINTER (0x30C7), "/dekatakana" },
+ { GUINT_TO_POINTER (0x232B), "/deleteleft" },
+ { GUINT_TO_POINTER (0x2326), "/deleteright" },
+ { GUINT_TO_POINTER (0x03B4), "/delta" },
+ { GUINT_TO_POINTER (0x018D), "/deltaturned" },
+ { GUINT_TO_POINTER (0x09F8), "/denominatorminusonenumeratorbengali" },
+ { GUINT_TO_POINTER (0x02A4), "/dezh" },
+ { GUINT_TO_POINTER (0x09A7), "/dhabengali" },
+ { GUINT_TO_POINTER (0x0927), "/dhadeva" },
+ { GUINT_TO_POINTER (0x0AA7), "/dhagujarati" },
+ { GUINT_TO_POINTER (0x0A27), "/dhagurmukhi" },
+ { GUINT_TO_POINTER (0x0257), "/dhook" },
+ { GUINT_TO_POINTER (0x0385), "/dialytikatonos" },
+ { GUINT_TO_POINTER (0x0344), "/dialytikatonoscmb" },
+ { GUINT_TO_POINTER (0x2666), "/diamond" },
+ { GUINT_TO_POINTER (0x2662), "/diamondsuitwhite" },
+ { GUINT_TO_POINTER (0x00A8), "/dieresis" },
+ { GUINT_TO_POINTER (0xF6D7), "/dieresisacute" },
+ { GUINT_TO_POINTER (0x0324), "/dieresisbelowcmb" },
+ { GUINT_TO_POINTER (0x0308), "/dieresiscmb" },
+ { GUINT_TO_POINTER (0xF6D8), "/dieresisgrave" },
+ { GUINT_TO_POINTER (0x0385), "/dieresistonos" },
+ { GUINT_TO_POINTER (0x3062), "/dihiragana" },
+ { GUINT_TO_POINTER (0x30C2), "/dikatakana" },
+ { GUINT_TO_POINTER (0x3003), "/dittomark" },
+ { GUINT_TO_POINTER (0x00F7), "/divide" },
+ { GUINT_TO_POINTER (0x2223), "/divides" },
+ { GUINT_TO_POINTER (0x2215), "/divisionslash" },
+ { GUINT_TO_POINTER (0x0452), "/djecyrillic" },
+ { GUINT_TO_POINTER (0x2593), "/dkshade" },
+ { GUINT_TO_POINTER (0x1E0F), "/dlinebelow" },
+ { GUINT_TO_POINTER (0x3397), "/dlsquare" },
+ { GUINT_TO_POINTER (0x0111), "/dmacron" },
+ { GUINT_TO_POINTER (0xFF44), "/dmonospace" },
+ { GUINT_TO_POINTER (0x2584), "/dnblock" },
+ { GUINT_TO_POINTER (0x0E0E), "/dochadathai" },
+ { GUINT_TO_POINTER (0x0E14), "/dodekthai" },
+ { GUINT_TO_POINTER (0x3069), "/dohiragana" },
+ { GUINT_TO_POINTER (0x30C9), "/dokatakana" },
+ { GUINT_TO_POINTER (0x0024), "/dollar" },
+ { GUINT_TO_POINTER (0xF6E3), "/dollarinferior" },
+ { GUINT_TO_POINTER (0xFF04), "/dollarmonospace" },
+ { GUINT_TO_POINTER (0xF724), "/dollaroldstyle" },
+ { GUINT_TO_POINTER (0xFE69), "/dollarsmall" },
+ { GUINT_TO_POINTER (0xF6E4), "/dollarsuperior" },
+ { GUINT_TO_POINTER (0x20AB), "/dong" },
+ { GUINT_TO_POINTER (0x3326), "/dorusquare" },
+ { GUINT_TO_POINTER (0x02D9), "/dotaccent" },
+ { GUINT_TO_POINTER (0x0307), "/dotaccentcmb" },
+ { GUINT_TO_POINTER (0x0323), "/dotbelowcmb" },
+ { GUINT_TO_POINTER (0x0323), "/dotbelowcomb" },
+ { GUINT_TO_POINTER (0x30FB), "/dotkatakana" },
+ { GUINT_TO_POINTER (0x0131), "/dotlessi" },
+ { GUINT_TO_POINTER (0xF6BE), "/dotlessj" },
+ { GUINT_TO_POINTER (0x0284), "/dotlessjstrokehook" },
+ { GUINT_TO_POINTER (0x22C5), "/dotmath" },
+ { GUINT_TO_POINTER (0x25CC), "/dottedcircle" },
+ { GUINT_TO_POINTER (0xFB1F), "/doubleyodpatah" },
+ { GUINT_TO_POINTER (0xFB1F), "/doubleyodpatahhebrew" },
+ { GUINT_TO_POINTER (0x031E), "/downtackbelowcmb" },
+ { GUINT_TO_POINTER (0x02D5), "/downtackmod" },
+ { GUINT_TO_POINTER (0x249F), "/dparen" },
+ { GUINT_TO_POINTER (0xF6EB), "/dsuperior" },
+ { GUINT_TO_POINTER (0x0256), "/dtail" },
+ { GUINT_TO_POINTER (0x018C), "/dtopbar" },
+ { GUINT_TO_POINTER (0x3065), "/duhiragana" },
+ { GUINT_TO_POINTER (0x30C5), "/dukatakana" },
+ { GUINT_TO_POINTER (0x01F3), "/dz" },
+ { GUINT_TO_POINTER (0x02A3), "/dzaltone" },
+ { GUINT_TO_POINTER (0x01C6), "/dzcaron" },
+ { GUINT_TO_POINTER (0x02A5), "/dzcurl" },
+ { GUINT_TO_POINTER (0x04E1), "/dzeabkhasiancyrillic" },
+ { GUINT_TO_POINTER (0x0455), "/dzecyrillic" },
+ { GUINT_TO_POINTER (0x045F), "/dzhecyrillic" },
+ { GUINT_TO_POINTER (0x0065), "/e" },
+ { GUINT_TO_POINTER (0x00E9), "/eacute" },
+ { GUINT_TO_POINTER (0x2641), "/earth" },
+ { GUINT_TO_POINTER (0x098F), "/ebengali" },
+ { GUINT_TO_POINTER (0x311C), "/ebopomofo" },
+ { GUINT_TO_POINTER (0x0115), "/ebreve" },
+ { GUINT_TO_POINTER (0x090D), "/ecandradeva" },
+ { GUINT_TO_POINTER (0x0A8D), "/ecandragujarati" },
+ { GUINT_TO_POINTER (0x0945), "/ecandravowelsigndeva" },
+ { GUINT_TO_POINTER (0x0AC5), "/ecandravowelsigngujarati" },
+ { GUINT_TO_POINTER (0x011B), "/ecaron" },
+ { GUINT_TO_POINTER (0x1E1D), "/ecedillabreve" },
+ { GUINT_TO_POINTER (0x0565), "/echarmenian" },
+ { GUINT_TO_POINTER (0x0587), "/echyiwnarmenian" },
+ { GUINT_TO_POINTER (0x24D4), "/ecircle" },
+ { GUINT_TO_POINTER (0x00EA), "/ecircumflex" },
+ { GUINT_TO_POINTER (0x1EBF), "/ecircumflexacute" },
+ { GUINT_TO_POINTER (0x1E19), "/ecircumflexbelow" },
+ { GUINT_TO_POINTER (0x1EC7), "/ecircumflexdotbelow" },
+ { GUINT_TO_POINTER (0x1EC1), "/ecircumflexgrave" },
+ { GUINT_TO_POINTER (0x1EC3), "/ecircumflexhookabove" },
+ { GUINT_TO_POINTER (0x1EC5), "/ecircumflextilde" },
+ { GUINT_TO_POINTER (0x0454), "/ecyrillic" },
+ { GUINT_TO_POINTER (0x0205), "/edblgrave" },
+ { GUINT_TO_POINTER (0x090F), "/edeva" },
+ { GUINT_TO_POINTER (0x00EB), "/edieresis" },
+ { GUINT_TO_POINTER (0x0117), "/edot" },
+ { GUINT_TO_POINTER (0x0117), "/edotaccent" },
+ { GUINT_TO_POINTER (0x1EB9), "/edotbelow" },
+ { GUINT_TO_POINTER (0x0A0F), "/eegurmukhi" },
+ { GUINT_TO_POINTER (0x0A47), "/eematragurmukhi" },
+ { GUINT_TO_POINTER (0x0444), "/efcyrillic" },
+ { GUINT_TO_POINTER (0x00E8), "/egrave" },
+ { GUINT_TO_POINTER (0x0A8F), "/egujarati" },
+ { GUINT_TO_POINTER (0x0567), "/eharmenian" },
+ { GUINT_TO_POINTER (0x311D), "/ehbopomofo" },
+ { GUINT_TO_POINTER (0x3048), "/ehiragana" },
+ { GUINT_TO_POINTER (0x1EBB), "/ehookabove" },
+ { GUINT_TO_POINTER (0x311F), "/eibopomofo" },
+ { GUINT_TO_POINTER (0x0038), "/eight" },
+ { GUINT_TO_POINTER (0x0668), "/eightarabic" },
+ { GUINT_TO_POINTER (0x09EE), "/eightbengali" },
+ { GUINT_TO_POINTER (0x2467), "/eightcircle" },
+ { GUINT_TO_POINTER (0x2791), "/eightcircleinversesansserif" },
+ { GUINT_TO_POINTER (0x096E), "/eightdeva" },
+ { GUINT_TO_POINTER (0x2471), "/eighteencircle" },
+ { GUINT_TO_POINTER (0x2485), "/eighteenparen" },
+ { GUINT_TO_POINTER (0x2499), "/eighteenperiod" },
+ { GUINT_TO_POINTER (0x0AEE), "/eightgujarati" },
+ { GUINT_TO_POINTER (0x0A6E), "/eightgurmukhi" },
+ { GUINT_TO_POINTER (0x0668), "/eighthackarabic" },
+ { GUINT_TO_POINTER (0x3028), "/eighthangzhou" },
+ { GUINT_TO_POINTER (0x266B), "/eighthnotebeamed" },
+ { GUINT_TO_POINTER (0x3227), "/eightideographicparen" },
+ { GUINT_TO_POINTER (0x2088), "/eightinferior" },
+ { GUINT_TO_POINTER (0xFF18), "/eightmonospace" },
+ { GUINT_TO_POINTER (0xF738), "/eightoldstyle" },
+ { GUINT_TO_POINTER (0x247B), "/eightparen" },
+ { GUINT_TO_POINTER (0x248F), "/eightperiod" },
+ { GUINT_TO_POINTER (0x06F8), "/eightpersian" },
+ { GUINT_TO_POINTER (0x2177), "/eightroman" },
+ { GUINT_TO_POINTER (0x2078), "/eightsuperior" },
+ { GUINT_TO_POINTER (0x0E58), "/eightthai" },
+ { GUINT_TO_POINTER (0x0207), "/einvertedbreve" },
+ { GUINT_TO_POINTER (0x0465), "/eiotifiedcyrillic" },
+ { GUINT_TO_POINTER (0x30A8), "/ekatakana" },
+ { GUINT_TO_POINTER (0xFF74), "/ekatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x0A74), "/ekonkargurmukhi" },
+ { GUINT_TO_POINTER (0x3154), "/ekorean" },
+ { GUINT_TO_POINTER (0x043B), "/elcyrillic" },
+ { GUINT_TO_POINTER (0x2208), "/element" },
+ { GUINT_TO_POINTER (0x246A), "/elevencircle" },
+ { GUINT_TO_POINTER (0x247E), "/elevenparen" },
+ { GUINT_TO_POINTER (0x2492), "/elevenperiod" },
+ { GUINT_TO_POINTER (0x217A), "/elevenroman" },
+ { GUINT_TO_POINTER (0x2026), "/ellipsis" },
+ { GUINT_TO_POINTER (0x22EE), "/ellipsisvertical" },
+ { GUINT_TO_POINTER (0x0113), "/emacron" },
+ { GUINT_TO_POINTER (0x1E17), "/emacronacute" },
+ { GUINT_TO_POINTER (0x1E15), "/emacrongrave" },
+ { GUINT_TO_POINTER (0x043C), "/emcyrillic" },
+ { GUINT_TO_POINTER (0x2014), "/emdash" },
+ { GUINT_TO_POINTER (0xFE31), "/emdashvertical" },
+ { GUINT_TO_POINTER (0xFF45), "/emonospace" },
+ { GUINT_TO_POINTER (0x055B), "/emphasismarkarmenian" },
+ { GUINT_TO_POINTER (0x2205), "/emptyset" },
+ { GUINT_TO_POINTER (0x3123), "/enbopomofo" },
+ { GUINT_TO_POINTER (0x043D), "/encyrillic" },
+ { GUINT_TO_POINTER (0x2013), "/endash" },
+ { GUINT_TO_POINTER (0xFE32), "/endashvertical" },
+ { GUINT_TO_POINTER (0x04A3), "/endescendercyrillic" },
+ { GUINT_TO_POINTER (0x014B), "/eng" },
+ { GUINT_TO_POINTER (0x3125), "/engbopomofo" },
+ { GUINT_TO_POINTER (0x04A5), "/enghecyrillic" },
+ { GUINT_TO_POINTER (0x04C8), "/enhookcyrillic" },
+ { GUINT_TO_POINTER (0x2002), "/enspace" },
+ { GUINT_TO_POINTER (0x0119), "/eogonek" },
+ { GUINT_TO_POINTER (0x3153), "/eokorean" },
+ { GUINT_TO_POINTER (0x025B), "/eopen" },
+ { GUINT_TO_POINTER (0x029A), "/eopenclosed" },
+ { GUINT_TO_POINTER (0x025C), "/eopenreversed" },
+ { GUINT_TO_POINTER (0x025E), "/eopenreversedclosed" },
+ { GUINT_TO_POINTER (0x025D), "/eopenreversedhook" },
+ { GUINT_TO_POINTER (0x24A0), "/eparen" },
+ { GUINT_TO_POINTER (0x03B5), "/epsilon" },
+ { GUINT_TO_POINTER (0x03AD), "/epsilontonos" },
+ { GUINT_TO_POINTER (0x003D), "/equal" },
+ { GUINT_TO_POINTER (0xFF1D), "/equalmonospace" },
+ { GUINT_TO_POINTER (0xFE66), "/equalsmall" },
+ { GUINT_TO_POINTER (0x207C), "/equalsuperior" },
+ { GUINT_TO_POINTER (0x2261), "/equivalence" },
+ { GUINT_TO_POINTER (0x3126), "/erbopomofo" },
+ { GUINT_TO_POINTER (0x0440), "/ercyrillic" },
+ { GUINT_TO_POINTER (0x0258), "/ereversed" },
+ { GUINT_TO_POINTER (0x044D), "/ereversedcyrillic" },
+ { GUINT_TO_POINTER (0x0441), "/escyrillic" },
+ { GUINT_TO_POINTER (0x04AB), "/esdescendercyrillic" },
+ { GUINT_TO_POINTER (0x0283), "/esh" },
+ { GUINT_TO_POINTER (0x0286), "/eshcurl" },
+ { GUINT_TO_POINTER (0x090E), "/eshortdeva" },
+ { GUINT_TO_POINTER (0x0946), "/eshortvowelsigndeva" },
+ { GUINT_TO_POINTER (0x01AA), "/eshreversedloop" },
+ { GUINT_TO_POINTER (0x0285), "/eshsquatreversed" },
+ { GUINT_TO_POINTER (0x3047), "/esmallhiragana" },
+ { GUINT_TO_POINTER (0x30A7), "/esmallkatakana" },
+ { GUINT_TO_POINTER (0xFF6A), "/esmallkatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x212E), "/estimated" },
+ { GUINT_TO_POINTER (0xF6EC), "/esuperior" },
+ { GUINT_TO_POINTER (0x03B7), "/eta" },
+ { GUINT_TO_POINTER (0x0568), "/etarmenian" },
+ { GUINT_TO_POINTER (0x03AE), "/etatonos" },
+ { GUINT_TO_POINTER (0x00F0), "/eth" },
+ { GUINT_TO_POINTER (0x1EBD), "/etilde" },
+ { GUINT_TO_POINTER (0x1E1B), "/etildebelow" },
+ { GUINT_TO_POINTER (0x0591), "/etnahtafoukhhebrew" },
+ { GUINT_TO_POINTER (0x0591), "/etnahtafoukhlefthebrew" },
+ { GUINT_TO_POINTER (0x0591), "/etnahtahebrew" },
+ { GUINT_TO_POINTER (0x0591), "/etnahtalefthebrew" },
+ { GUINT_TO_POINTER (0x01DD), "/eturned" },
+ { GUINT_TO_POINTER (0x3161), "/eukorean" },
+ { GUINT_TO_POINTER (0x20AC), "/euro" },
+ { GUINT_TO_POINTER (0x09C7), "/evowelsignbengali" },
+ { GUINT_TO_POINTER (0x0947), "/evowelsigndeva" },
+ { GUINT_TO_POINTER (0x0AC7), "/evowelsigngujarati" },
+ { GUINT_TO_POINTER (0x0021), "/exclam" },
+ { GUINT_TO_POINTER (0x055C), "/exclamarmenian" },
+ { GUINT_TO_POINTER (0x203C), "/exclamdbl" },
+ { GUINT_TO_POINTER (0x00A1), "/exclamdown" },
+ { GUINT_TO_POINTER (0xF7A1), "/exclamdownsmall" },
+ { GUINT_TO_POINTER (0xFF01), "/exclammonospace" },
+ { GUINT_TO_POINTER (0xF721), "/exclamsmall" },
+ { GUINT_TO_POINTER (0x2203), "/existential" },
+ { GUINT_TO_POINTER (0x0292), "/ezh" },
+ { GUINT_TO_POINTER (0x01EF), "/ezhcaron" },
+ { GUINT_TO_POINTER (0x0293), "/ezhcurl" },
+ { GUINT_TO_POINTER (0x01B9), "/ezhreversed" },
+ { GUINT_TO_POINTER (0x01BA), "/ezhtail" },
+ { GUINT_TO_POINTER (0x0066), "/f" },
+ { GUINT_TO_POINTER (0x095E), "/fadeva" },
+ { GUINT_TO_POINTER (0x0A5E), "/fagurmukhi" },
+ { GUINT_TO_POINTER (0x2109), "/fahrenheit" },
+ { GUINT_TO_POINTER (0x064E), "/fathaarabic" },
+ { GUINT_TO_POINTER (0x064E), "/fathalowarabic" },
+ { GUINT_TO_POINTER (0x064B), "/fathatanarabic" },
+ { GUINT_TO_POINTER (0x3108), "/fbopomofo" },
+ { GUINT_TO_POINTER (0x24D5), "/fcircle" },
+ { GUINT_TO_POINTER (0x1E1F), "/fdotaccent" },
+ { GUINT_TO_POINTER (0x0641), "/feharabic" },
+ { GUINT_TO_POINTER (0x0586), "/feharmenian" },
+ { GUINT_TO_POINTER (0xFED2), "/fehfinalarabic" },
+ { GUINT_TO_POINTER (0xFED3), "/fehinitialarabic" },
+ { GUINT_TO_POINTER (0xFED4), "/fehmedialarabic" },
+ { GUINT_TO_POINTER (0x03E5), "/feicoptic" },
+ { GUINT_TO_POINTER (0x2640), "/female" },
+ { GUINT_TO_POINTER (0xFB00), "/ff" },
+ { GUINT_TO_POINTER (0xFB03), "/ffi" },
+ { GUINT_TO_POINTER (0xFB04), "/ffl" },
+ { GUINT_TO_POINTER (0xFB01), "/fi" },
+ { GUINT_TO_POINTER (0x246E), "/fifteencircle" },
+ { GUINT_TO_POINTER (0x2482), "/fifteenparen" },
+ { GUINT_TO_POINTER (0x2496), "/fifteenperiod" },
+ { GUINT_TO_POINTER (0x2012), "/figuredash" },
+ { GUINT_TO_POINTER (0x25A0), "/filledbox" },
+ { GUINT_TO_POINTER (0x25AC), "/filledrect" },
+ { GUINT_TO_POINTER (0x05DA), "/finalkaf" },
+ { GUINT_TO_POINTER (0xFB3A), "/finalkafdagesh" },
+ { GUINT_TO_POINTER (0xFB3A), "/finalkafdageshhebrew" },
+ { GUINT_TO_POINTER (0x05DA), "/finalkafhebrew" },
+ { GUINT_TO_POINTER (0x05DA), "/finalkafqamats" },
+ { GUINT_TO_POINTER (0x05B8), "/finalkafqamats" },
+ { GUINT_TO_POINTER (0x05DA), "/finalkafqamatshebrew" },
+ { GUINT_TO_POINTER (0x05B8), "/finalkafqamatshebrew" },
+ { GUINT_TO_POINTER (0x05DA), "/finalkafsheva" },
+ { GUINT_TO_POINTER (0x05B0), "/finalkafsheva" },
+ { GUINT_TO_POINTER (0x05DA), "/finalkafshevahebrew" },
+ { GUINT_TO_POINTER (0x05B0), "/finalkafshevahebrew" },
+ { GUINT_TO_POINTER (0x05DD), "/finalmem" },
+ { GUINT_TO_POINTER (0x05DD), "/finalmemhebrew" },
+ { GUINT_TO_POINTER (0x05DF), "/finalnun" },
+ { GUINT_TO_POINTER (0x05DF), "/finalnunhebrew" },
+ { GUINT_TO_POINTER (0x05E3), "/finalpe" },
+ { GUINT_TO_POINTER (0x05E3), "/finalpehebrew" },
+ { GUINT_TO_POINTER (0x05E5), "/finaltsadi" },
+ { GUINT_TO_POINTER (0x05E5), "/finaltsadihebrew" },
+ { GUINT_TO_POINTER (0x02C9), "/firsttonechinese" },
+ { GUINT_TO_POINTER (0x25C9), "/fisheye" },
+ { GUINT_TO_POINTER (0x0473), "/fitacyrillic" },
+ { GUINT_TO_POINTER (0x0035), "/five" },
+ { GUINT_TO_POINTER (0x0665), "/fivearabic" },
+ { GUINT_TO_POINTER (0x09EB), "/fivebengali" },
+ { GUINT_TO_POINTER (0x2464), "/fivecircle" },
+ { GUINT_TO_POINTER (0x278E), "/fivecircleinversesansserif" },
+ { GUINT_TO_POINTER (0x096B), "/fivedeva" },
+ { GUINT_TO_POINTER (0x215D), "/fiveeighths" },
+ { GUINT_TO_POINTER (0x0AEB), "/fivegujarati" },
+ { GUINT_TO_POINTER (0x0A6B), "/fivegurmukhi" },
+ { GUINT_TO_POINTER (0x0665), "/fivehackarabic" },
+ { GUINT_TO_POINTER (0x3025), "/fivehangzhou" },
+ { GUINT_TO_POINTER (0x3224), "/fiveideographicparen" },
+ { GUINT_TO_POINTER (0x2085), "/fiveinferior" },
+ { GUINT_TO_POINTER (0xFF15), "/fivemonospace" },
+ { GUINT_TO_POINTER (0xF735), "/fiveoldstyle" },
+ { GUINT_TO_POINTER (0x2478), "/fiveparen" },
+ { GUINT_TO_POINTER (0x248C), "/fiveperiod" },
+ { GUINT_TO_POINTER (0x06F5), "/fivepersian" },
+ { GUINT_TO_POINTER (0x2174), "/fiveroman" },
+ { GUINT_TO_POINTER (0x2075), "/fivesuperior" },
+ { GUINT_TO_POINTER (0x0E55), "/fivethai" },
+ { GUINT_TO_POINTER (0xFB02), "/fl" },
+ { GUINT_TO_POINTER (0x0192), "/florin" },
+ { GUINT_TO_POINTER (0xFF46), "/fmonospace" },
+ { GUINT_TO_POINTER (0x3399), "/fmsquare" },
+ { GUINT_TO_POINTER (0x0E1F), "/fofanthai" },
+ { GUINT_TO_POINTER (0x0E1D), "/fofathai" },
+ { GUINT_TO_POINTER (0x0E4F), "/fongmanthai" },
+ { GUINT_TO_POINTER (0x2200), "/forall" },
+ { GUINT_TO_POINTER (0x0034), "/four" },
+ { GUINT_TO_POINTER (0x0664), "/fourarabic" },
+ { GUINT_TO_POINTER (0x09EA), "/fourbengali" },
+ { GUINT_TO_POINTER (0x2463), "/fourcircle" },
+ { GUINT_TO_POINTER (0x278D), "/fourcircleinversesansserif" },
+ { GUINT_TO_POINTER (0x096A), "/fourdeva" },
+ { GUINT_TO_POINTER (0x0AEA), "/fourgujarati" },
+ { GUINT_TO_POINTER (0x0A6A), "/fourgurmukhi" },
+ { GUINT_TO_POINTER (0x0664), "/fourhackarabic" },
+ { GUINT_TO_POINTER (0x3024), "/fourhangzhou" },
+ { GUINT_TO_POINTER (0x3223), "/fourideographicparen" },
+ { GUINT_TO_POINTER (0x2084), "/fourinferior" },
+ { GUINT_TO_POINTER (0xFF14), "/fourmonospace" },
+ { GUINT_TO_POINTER (0x09F7), "/fournumeratorbengali" },
+ { GUINT_TO_POINTER (0xF734), "/fouroldstyle" },
+ { GUINT_TO_POINTER (0x2477), "/fourparen" },
+ { GUINT_TO_POINTER (0x248B), "/fourperiod" },
+ { GUINT_TO_POINTER (0x06F4), "/fourpersian" },
+ { GUINT_TO_POINTER (0x2173), "/fourroman" },
+ { GUINT_TO_POINTER (0x2074), "/foursuperior" },
+ { GUINT_TO_POINTER (0x246D), "/fourteencircle" },
+ { GUINT_TO_POINTER (0x2481), "/fourteenparen" },
+ { GUINT_TO_POINTER (0x2495), "/fourteenperiod" },
+ { GUINT_TO_POINTER (0x0E54), "/fourthai" },
+ { GUINT_TO_POINTER (0x02CB), "/fourthtonechinese" },
+ { GUINT_TO_POINTER (0x24A1), "/fparen" },
+ { GUINT_TO_POINTER (0x2044), "/fraction" },
+ { GUINT_TO_POINTER (0x20A3), "/franc" },
+ { GUINT_TO_POINTER (0x0067), "/g" },
+ { GUINT_TO_POINTER (0x0997), "/gabengali" },
+ { GUINT_TO_POINTER (0x01F5), "/gacute" },
+ { GUINT_TO_POINTER (0x0917), "/gadeva" },
+ { GUINT_TO_POINTER (0x06AF), "/gafarabic" },
+ { GUINT_TO_POINTER (0xFB93), "/gaffinalarabic" },
+ { GUINT_TO_POINTER (0xFB94), "/gafinitialarabic" },
+ { GUINT_TO_POINTER (0xFB95), "/gafmedialarabic" },
+ { GUINT_TO_POINTER (0x0A97), "/gagujarati" },
+ { GUINT_TO_POINTER (0x0A17), "/gagurmukhi" },
+ { GUINT_TO_POINTER (0x304C), "/gahiragana" },
+ { GUINT_TO_POINTER (0x30AC), "/gakatakana" },
+ { GUINT_TO_POINTER (0x03B3), "/gamma" },
+ { GUINT_TO_POINTER (0x0263), "/gammalatinsmall" },
+ { GUINT_TO_POINTER (0x02E0), "/gammasuperior" },
+ { GUINT_TO_POINTER (0x03EB), "/gangiacoptic" },
+ { GUINT_TO_POINTER (0x310D), "/gbopomofo" },
+ { GUINT_TO_POINTER (0x011F), "/gbreve" },
+ { GUINT_TO_POINTER (0x01E7), "/gcaron" },
+ { GUINT_TO_POINTER (0x0123), "/gcedilla" },
+ { GUINT_TO_POINTER (0x24D6), "/gcircle" },
+ { GUINT_TO_POINTER (0x011D), "/gcircumflex" },
+ { GUINT_TO_POINTER (0x0123), "/gcommaaccent" },
+ { GUINT_TO_POINTER (0x0121), "/gdot" },
+ { GUINT_TO_POINTER (0x0121), "/gdotaccent" },
+ { GUINT_TO_POINTER (0x0433), "/gecyrillic" },
+ { GUINT_TO_POINTER (0x3052), "/gehiragana" },
+ { GUINT_TO_POINTER (0x30B2), "/gekatakana" },
+ { GUINT_TO_POINTER (0x2251), "/geometricallyequal" },
+ { GUINT_TO_POINTER (0x059C), "/gereshaccenthebrew" },
+ { GUINT_TO_POINTER (0x05F3), "/gereshhebrew" },
+ { GUINT_TO_POINTER (0x059D), "/gereshmuqdamhebrew" },
+ { GUINT_TO_POINTER (0x00DF), "/germandbls" },
+ { GUINT_TO_POINTER (0x059E), "/gershayimaccenthebrew" },
+ { GUINT_TO_POINTER (0x05F4), "/gershayimhebrew" },
+ { GUINT_TO_POINTER (0x3013), "/getamark" },
+ { GUINT_TO_POINTER (0x0998), "/ghabengali" },
+ { GUINT_TO_POINTER (0x0572), "/ghadarmenian" },
+ { GUINT_TO_POINTER (0x0918), "/ghadeva" },
+ { GUINT_TO_POINTER (0x0A98), "/ghagujarati" },
+ { GUINT_TO_POINTER (0x0A18), "/ghagurmukhi" },
+ { GUINT_TO_POINTER (0x063A), "/ghainarabic" },
+ { GUINT_TO_POINTER (0xFECE), "/ghainfinalarabic" },
+ { GUINT_TO_POINTER (0xFECF), "/ghaininitialarabic" },
+ { GUINT_TO_POINTER (0xFED0), "/ghainmedialarabic" },
+ { GUINT_TO_POINTER (0x0495), "/ghemiddlehookcyrillic" },
+ { GUINT_TO_POINTER (0x0493), "/ghestrokecyrillic" },
+ { GUINT_TO_POINTER (0x0491), "/gheupturncyrillic" },
+ { GUINT_TO_POINTER (0x095A), "/ghhadeva" },
+ { GUINT_TO_POINTER (0x0A5A), "/ghhagurmukhi" },
+ { GUINT_TO_POINTER (0x0260), "/ghook" },
+ { GUINT_TO_POINTER (0x3393), "/ghzsquare" },
+ { GUINT_TO_POINTER (0x304E), "/gihiragana" },
+ { GUINT_TO_POINTER (0x30AE), "/gikatakana" },
+ { GUINT_TO_POINTER (0x0563), "/gimarmenian" },
+ { GUINT_TO_POINTER (0x05D2), "/gimel" },
+ { GUINT_TO_POINTER (0xFB32), "/gimeldagesh" },
+ { GUINT_TO_POINTER (0xFB32), "/gimeldageshhebrew" },
+ { GUINT_TO_POINTER (0x05D2), "/gimelhebrew" },
+ { GUINT_TO_POINTER (0x0453), "/gjecyrillic" },
+ { GUINT_TO_POINTER (0x01BE), "/glottalinvertedstroke" },
+ { GUINT_TO_POINTER (0x0294), "/glottalstop" },
+ { GUINT_TO_POINTER (0x0296), "/glottalstopinverted" },
+ { GUINT_TO_POINTER (0x02C0), "/glottalstopmod" },
+ { GUINT_TO_POINTER (0x0295), "/glottalstopreversed" },
+ { GUINT_TO_POINTER (0x02C1), "/glottalstopreversedmod" },
+ { GUINT_TO_POINTER (0x02E4), "/glottalstopreversedsuperior" },
+ { GUINT_TO_POINTER (0x02A1), "/glottalstopstroke" },
+ { GUINT_TO_POINTER (0x02A2), "/glottalstopstrokereversed" },
+ { GUINT_TO_POINTER (0x1E21), "/gmacron" },
+ { GUINT_TO_POINTER (0xFF47), "/gmonospace" },
+ { GUINT_TO_POINTER (0x3054), "/gohiragana" },
+ { GUINT_TO_POINTER (0x30B4), "/gokatakana" },
+ { GUINT_TO_POINTER (0x24A2), "/gparen" },
+ { GUINT_TO_POINTER (0x33AC), "/gpasquare" },
+ { GUINT_TO_POINTER (0x2207), "/gradient" },
+ { GUINT_TO_POINTER (0x0060), "/grave" },
+ { GUINT_TO_POINTER (0x0316), "/gravebelowcmb" },
+ { GUINT_TO_POINTER (0x0300), "/gravecmb" },
+ { GUINT_TO_POINTER (0x0300), "/gravecomb" },
+ { GUINT_TO_POINTER (0x0953), "/gravedeva" },
+ { GUINT_TO_POINTER (0x02CE), "/gravelowmod" },
+ { GUINT_TO_POINTER (0xFF40), "/gravemonospace" },
+ { GUINT_TO_POINTER (0x0340), "/gravetonecmb" },
+ { GUINT_TO_POINTER (0x003E), "/greater" },
+ { GUINT_TO_POINTER (0x2265), "/greaterequal" },
+ { GUINT_TO_POINTER (0x22DB), "/greaterequalorless" },
+ { GUINT_TO_POINTER (0xFF1E), "/greatermonospace" },
+ { GUINT_TO_POINTER (0x2273), "/greaterorequivalent" },
+ { GUINT_TO_POINTER (0x2277), "/greaterorless" },
+ { GUINT_TO_POINTER (0x2267), "/greateroverequal" },
+ { GUINT_TO_POINTER (0xFE65), "/greatersmall" },
+ { GUINT_TO_POINTER (0x0261), "/gscript" },
+ { GUINT_TO_POINTER (0x01E5), "/gstroke" },
+ { GUINT_TO_POINTER (0x3050), "/guhiragana" },
+ { GUINT_TO_POINTER (0x00AB), "/guillemotleft" },
+ { GUINT_TO_POINTER (0x00BB), "/guillemotright" },
+ { GUINT_TO_POINTER (0x2039), "/guilsinglleft" },
+ { GUINT_TO_POINTER (0x203A), "/guilsinglright" },
+ { GUINT_TO_POINTER (0x30B0), "/gukatakana" },
+ { GUINT_TO_POINTER (0x3318), "/guramusquare" },
+ { GUINT_TO_POINTER (0x33C9), "/gysquare" },
+ { GUINT_TO_POINTER (0x0068), "/h" },
+ { GUINT_TO_POINTER (0x04A9), "/haabkhasiancyrillic" },
+ { GUINT_TO_POINTER (0x06C1), "/haaltonearabic" },
+ { GUINT_TO_POINTER (0x09B9), "/habengali" },
+ { GUINT_TO_POINTER (0x04B3), "/hadescendercyrillic" },
+ { GUINT_TO_POINTER (0x0939), "/hadeva" },
+ { GUINT_TO_POINTER (0x0AB9), "/hagujarati" },
+ { GUINT_TO_POINTER (0x0A39), "/hagurmukhi" },
+ { GUINT_TO_POINTER (0x062D), "/haharabic" },
+ { GUINT_TO_POINTER (0xFEA2), "/hahfinalarabic" },
+ { GUINT_TO_POINTER (0xFEA3), "/hahinitialarabic" },
+ { GUINT_TO_POINTER (0x306F), "/hahiragana" },
+ { GUINT_TO_POINTER (0xFEA4), "/hahmedialarabic" },
+ { GUINT_TO_POINTER (0x332A), "/haitusquare" },
+ { GUINT_TO_POINTER (0x30CF), "/hakatakana" },
+ { GUINT_TO_POINTER (0xFF8A), "/hakatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x0A4D), "/halantgurmukhi" },
+ { GUINT_TO_POINTER (0x0621), "/hamzaarabic" },
+ { GUINT_TO_POINTER (0x0621), "/hamzadammaarabic" },
+ { GUINT_TO_POINTER (0x064F), "/hamzadammaarabic" },
+ { GUINT_TO_POINTER (0x0621), "/hamzadammatanarabic" },
+ { GUINT_TO_POINTER (0x064C), "/hamzadammatanarabic" },
+ { GUINT_TO_POINTER (0x0621), "/hamzafathaarabic" },
+ { GUINT_TO_POINTER (0x064E), "/hamzafathaarabic" },
+ { GUINT_TO_POINTER (0x0621), "/hamzafathatanarabic" },
+ { GUINT_TO_POINTER (0x064B), "/hamzafathatanarabic" },
+ { GUINT_TO_POINTER (0x0621), "/hamzalowarabic" },
+ { GUINT_TO_POINTER (0x0621), "/hamzalowkasraarabic" },
+ { GUINT_TO_POINTER (0x0650), "/hamzalowkasraarabic" },
+ { GUINT_TO_POINTER (0x0621), "/hamzalowkasratanarabic" },
+ { GUINT_TO_POINTER (0x064D), "/hamzalowkasratanarabic" },
+ { GUINT_TO_POINTER (0x0621), "/hamzasukunarabic" },
+ { GUINT_TO_POINTER (0x0652), "/hamzasukunarabic" },
+ { GUINT_TO_POINTER (0x3164), "/hangulfiller" },
+ { GUINT_TO_POINTER (0x044A), "/hardsigncyrillic" },
+ { GUINT_TO_POINTER (0x21BC), "/harpoonleftbarbup" },
+ { GUINT_TO_POINTER (0x21C0), "/harpoonrightbarbup" },
+ { GUINT_TO_POINTER (0x33CA), "/hasquare" },
+ { GUINT_TO_POINTER (0x05B2), "/hatafpatah" },
+ { GUINT_TO_POINTER (0x05B2), "/hatafpatah16" },
+ { GUINT_TO_POINTER (0x05B2), "/hatafpatah23" },
+ { GUINT_TO_POINTER (0x05B2), "/hatafpatah2f" },
+ { GUINT_TO_POINTER (0x05B2), "/hatafpatahhebrew" },
+ { GUINT_TO_POINTER (0x05B2), "/hatafpatahnarrowhebrew" },
+ { GUINT_TO_POINTER (0x05B2), "/hatafpatahquarterhebrew" },
+ { GUINT_TO_POINTER (0x05B2), "/hatafpatahwidehebrew" },
+ { GUINT_TO_POINTER (0x05B3), "/hatafqamats" },
+ { GUINT_TO_POINTER (0x05B3), "/hatafqamats1b" },
+ { GUINT_TO_POINTER (0x05B3), "/hatafqamats28" },
+ { GUINT_TO_POINTER (0x05B3), "/hatafqamats34" },
+ { GUINT_TO_POINTER (0x05B3), "/hatafqamatshebrew" },
+ { GUINT_TO_POINTER (0x05B3), "/hatafqamatsnarrowhebrew" },
+ { GUINT_TO_POINTER (0x05B3), "/hatafqamatsquarterhebrew" },
+ { GUINT_TO_POINTER (0x05B3), "/hatafqamatswidehebrew" },
+ { GUINT_TO_POINTER (0x05B1), "/hatafsegol" },
+ { GUINT_TO_POINTER (0x05B1), "/hatafsegol17" },
+ { GUINT_TO_POINTER (0x05B1), "/hatafsegol24" },
+ { GUINT_TO_POINTER (0x05B1), "/hatafsegol30" },
+ { GUINT_TO_POINTER (0x05B1), "/hatafsegolhebrew" },
+ { GUINT_TO_POINTER (0x05B1), "/hatafsegolnarrowhebrew" },
+ { GUINT_TO_POINTER (0x05B1), "/hatafsegolquarterhebrew" },
+ { GUINT_TO_POINTER (0x05B1), "/hatafsegolwidehebrew" },
+ { GUINT_TO_POINTER (0x0127), "/hbar" },
+ { GUINT_TO_POINTER (0x310F), "/hbopomofo" },
+ { GUINT_TO_POINTER (0x1E2B), "/hbrevebelow" },
+ { GUINT_TO_POINTER (0x1E29), "/hcedilla" },
+ { GUINT_TO_POINTER (0x24D7), "/hcircle" },
+ { GUINT_TO_POINTER (0x0125), "/hcircumflex" },
+ { GUINT_TO_POINTER (0x1E27), "/hdieresis" },
+ { GUINT_TO_POINTER (0x1E23), "/hdotaccent" },
+ { GUINT_TO_POINTER (0x1E25), "/hdotbelow" },
+ { GUINT_TO_POINTER (0x05D4), "/he" },
+ { GUINT_TO_POINTER (0x2665), "/heart" },
+ { GUINT_TO_POINTER (0x2665), "/heartsuitblack" },
+ { GUINT_TO_POINTER (0x2661), "/heartsuitwhite" },
+ { GUINT_TO_POINTER (0xFB34), "/hedagesh" },
+ { GUINT_TO_POINTER (0xFB34), "/hedageshhebrew" },
+ { GUINT_TO_POINTER (0x06C1), "/hehaltonearabic" },
+ { GUINT_TO_POINTER (0x0647), "/heharabic" },
+ { GUINT_TO_POINTER (0x05D4), "/hehebrew" },
+ { GUINT_TO_POINTER (0xFBA7), "/hehfinalaltonearabic" },
+ { GUINT_TO_POINTER (0xFEEA), "/hehfinalalttwoarabic" },
+ { GUINT_TO_POINTER (0xFEEA), "/hehfinalarabic" },
+ { GUINT_TO_POINTER (0xFBA5), "/hehhamzaabovefinalarabic" },
+ { GUINT_TO_POINTER (0xFBA4), "/hehhamzaaboveisolatedarabic" },
+ { GUINT_TO_POINTER (0xFBA8), "/hehinitialaltonearabic" },
+ { GUINT_TO_POINTER (0xFEEB), "/hehinitialarabic" },
+ { GUINT_TO_POINTER (0x3078), "/hehiragana" },
+ { GUINT_TO_POINTER (0xFBA9), "/hehmedialaltonearabic" },
+ { GUINT_TO_POINTER (0xFEEC), "/hehmedialarabic" },
+ { GUINT_TO_POINTER (0x337B), "/heiseierasquare" },
+ { GUINT_TO_POINTER (0x30D8), "/hekatakana" },
+ { GUINT_TO_POINTER (0xFF8D), "/hekatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x3336), "/hekutaarusquare" },
+ { GUINT_TO_POINTER (0x0267), "/henghook" },
+ { GUINT_TO_POINTER (0x3339), "/herutusquare" },
+ { GUINT_TO_POINTER (0x05D7), "/het" },
+ { GUINT_TO_POINTER (0x05D7), "/hethebrew" },
+ { GUINT_TO_POINTER (0x0266), "/hhook" },
+ { GUINT_TO_POINTER (0x02B1), "/hhooksuperior" },
+ { GUINT_TO_POINTER (0x327B), "/hieuhacirclekorean" },
+ { GUINT_TO_POINTER (0x321B), "/hieuhaparenkorean" },
+ { GUINT_TO_POINTER (0x326D), "/hieuhcirclekorean" },
+ { GUINT_TO_POINTER (0x314E), "/hieuhkorean" },
+ { GUINT_TO_POINTER (0x320D), "/hieuhparenkorean" },
+ { GUINT_TO_POINTER (0x3072), "/hihiragana" },
+ { GUINT_TO_POINTER (0x30D2), "/hikatakana" },
+ { GUINT_TO_POINTER (0xFF8B), "/hikatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x05B4), "/hiriq" },
+ { GUINT_TO_POINTER (0x05B4), "/hiriq14" },
+ { GUINT_TO_POINTER (0x05B4), "/hiriq21" },
+ { GUINT_TO_POINTER (0x05B4), "/hiriq2d" },
+ { GUINT_TO_POINTER (0x05B4), "/hiriqhebrew" },
+ { GUINT_TO_POINTER (0x05B4), "/hiriqnarrowhebrew" },
+ { GUINT_TO_POINTER (0x05B4), "/hiriqquarterhebrew" },
+ { GUINT_TO_POINTER (0x05B4), "/hiriqwidehebrew" },
+ { GUINT_TO_POINTER (0x1E96), "/hlinebelow" },
+ { GUINT_TO_POINTER (0xFF48), "/hmonospace" },
+ { GUINT_TO_POINTER (0x0570), "/hoarmenian" },
+ { GUINT_TO_POINTER (0x0E2B), "/hohipthai" },
+ { GUINT_TO_POINTER (0x307B), "/hohiragana" },
+ { GUINT_TO_POINTER (0x30DB), "/hokatakana" },
+ { GUINT_TO_POINTER (0xFF8E), "/hokatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x05B9), "/holam" },
+ { GUINT_TO_POINTER (0x05B9), "/holam19" },
+ { GUINT_TO_POINTER (0x05B9), "/holam26" },
+ { GUINT_TO_POINTER (0x05B9), "/holam32" },
+ { GUINT_TO_POINTER (0x05B9), "/holamhebrew" },
+ { GUINT_TO_POINTER (0x05B9), "/holamnarrowhebrew" },
+ { GUINT_TO_POINTER (0x05B9), "/holamquarterhebrew" },
+ { GUINT_TO_POINTER (0x05B9), "/holamwidehebrew" },
+ { GUINT_TO_POINTER (0x0E2E), "/honokhukthai" },
+ { GUINT_TO_POINTER (0x0309), "/hookabovecomb" },
+ { GUINT_TO_POINTER (0x0309), "/hookcmb" },
+ { GUINT_TO_POINTER (0x0321), "/hookpalatalizedbelowcmb" },
+ { GUINT_TO_POINTER (0x0322), "/hookretroflexbelowcmb" },
+ { GUINT_TO_POINTER (0x3342), "/hoonsquare" },
+ { GUINT_TO_POINTER (0x03E9), "/horicoptic" },
+ { GUINT_TO_POINTER (0x2015), "/horizontalbar" },
+ { GUINT_TO_POINTER (0x031B), "/horncmb" },
+ { GUINT_TO_POINTER (0x2668), "/hotsprings" },
+ { GUINT_TO_POINTER (0x2302), "/house" },
+ { GUINT_TO_POINTER (0x24A3), "/hparen" },
+ { GUINT_TO_POINTER (0x02B0), "/hsuperior" },
+ { GUINT_TO_POINTER (0x0265), "/hturned" },
+ { GUINT_TO_POINTER (0x3075), "/huhiragana" },
+ { GUINT_TO_POINTER (0x3333), "/huiitosquare" },
+ { GUINT_TO_POINTER (0x30D5), "/hukatakana" },
+ { GUINT_TO_POINTER (0xFF8C), "/hukatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x02DD), "/hungarumlaut" },
+ { GUINT_TO_POINTER (0x030B), "/hungarumlautcmb" },
+ { GUINT_TO_POINTER (0x0195), "/hv" },
+ { GUINT_TO_POINTER (0x002D), "/hyphen" },
+ { GUINT_TO_POINTER (0xF6E5), "/hypheninferior" },
+ { GUINT_TO_POINTER (0xFF0D), "/hyphenmonospace" },
+ { GUINT_TO_POINTER (0xFE63), "/hyphensmall" },
+ { GUINT_TO_POINTER (0xF6E6), "/hyphensuperior" },
+ { GUINT_TO_POINTER (0x2010), "/hyphentwo" },
+ { GUINT_TO_POINTER (0x0069), "/i" },
+ { GUINT_TO_POINTER (0x00ED), "/iacute" },
+ { GUINT_TO_POINTER (0x044F), "/iacyrillic" },
+ { GUINT_TO_POINTER (0x0987), "/ibengali" },
+ { GUINT_TO_POINTER (0x3127), "/ibopomofo" },
+ { GUINT_TO_POINTER (0x012D), "/ibreve" },
+ { GUINT_TO_POINTER (0x01D0), "/icaron" },
+ { GUINT_TO_POINTER (0x24D8), "/icircle" },
+ { GUINT_TO_POINTER (0x00EE), "/icircumflex" },
+ { GUINT_TO_POINTER (0x0456), "/icyrillic" },
+ { GUINT_TO_POINTER (0x0209), "/idblgrave" },
+ { GUINT_TO_POINTER (0x328F), "/ideographearthcircle" },
+ { GUINT_TO_POINTER (0x328B), "/ideographfirecircle" },
+ { GUINT_TO_POINTER (0x323F), "/ideographicallianceparen" },
+ { GUINT_TO_POINTER (0x323A), "/ideographiccallparen" },
+ { GUINT_TO_POINTER (0x32A5), "/ideographiccentrecircle" },
+ { GUINT_TO_POINTER (0x3006), "/ideographicclose" },
+ { GUINT_TO_POINTER (0x3001), "/ideographiccomma" },
+ { GUINT_TO_POINTER (0xFF64), "/ideographiccommaleft" },
+ { GUINT_TO_POINTER (0x3237), "/ideographiccongratulationparen" },
+ { GUINT_TO_POINTER (0x32A3), "/ideographiccorrectcircle" },
+ { GUINT_TO_POINTER (0x322F), "/ideographicearthparen" },
+ { GUINT_TO_POINTER (0x323D), "/ideographicenterpriseparen" },
+ { GUINT_TO_POINTER (0x329D), "/ideographicexcellentcircle" },
+ { GUINT_TO_POINTER (0x3240), "/ideographicfestivalparen" },
+ { GUINT_TO_POINTER (0x3296), "/ideographicfinancialcircle" },
+ { GUINT_TO_POINTER (0x3236), "/ideographicfinancialparen" },
+ { GUINT_TO_POINTER (0x322B), "/ideographicfireparen" },
+ { GUINT_TO_POINTER (0x3232), "/ideographichaveparen" },
+ { GUINT_TO_POINTER (0x32A4), "/ideographichighcircle" },
+ { GUINT_TO_POINTER (0x3005), "/ideographiciterationmark" },
+ { GUINT_TO_POINTER (0x3298), "/ideographiclaborcircle" },
+ { GUINT_TO_POINTER (0x3238), "/ideographiclaborparen" },
+ { GUINT_TO_POINTER (0x32A7), "/ideographicleftcircle" },
+ { GUINT_TO_POINTER (0x32A6), "/ideographiclowcircle" },
+ { GUINT_TO_POINTER (0x32A9), "/ideographicmedicinecircle" },
+ { GUINT_TO_POINTER (0x322E), "/ideographicmetalparen" },
+ { GUINT_TO_POINTER (0x322A), "/ideographicmoonparen" },
+ { GUINT_TO_POINTER (0x3234), "/ideographicnameparen" },
+ { GUINT_TO_POINTER (0x3002), "/ideographicperiod" },
+ { GUINT_TO_POINTER (0x329E), "/ideographicprintcircle" },
+ { GUINT_TO_POINTER (0x3243), "/ideographicreachparen" },
+ { GUINT_TO_POINTER (0x3239), "/ideographicrepresentparen" },
+ { GUINT_TO_POINTER (0x323E), "/ideographicresourceparen" },
+ { GUINT_TO_POINTER (0x32A8), "/ideographicrightcircle" },
+ { GUINT_TO_POINTER (0x3299), "/ideographicsecretcircle" },
+ { GUINT_TO_POINTER (0x3242), "/ideographicselfparen" },
+ { GUINT_TO_POINTER (0x3233), "/ideographicsocietyparen" },
+ { GUINT_TO_POINTER (0x3000), "/ideographicspace" },
+ { GUINT_TO_POINTER (0x3235), "/ideographicspecialparen" },
+ { GUINT_TO_POINTER (0x3231), "/ideographicstockparen" },
+ { GUINT_TO_POINTER (0x323B), "/ideographicstudyparen" },
+ { GUINT_TO_POINTER (0x3230), "/ideographicsunparen" },
+ { GUINT_TO_POINTER (0x323C), "/ideographicsuperviseparen" },
+ { GUINT_TO_POINTER (0x322C), "/ideographicwaterparen" },
+ { GUINT_TO_POINTER (0x322D), "/ideographicwoodparen" },
+ { GUINT_TO_POINTER (0x3007), "/ideographiczero" },
+ { GUINT_TO_POINTER (0x328E), "/ideographmetalcircle" },
+ { GUINT_TO_POINTER (0x328A), "/ideographmooncircle" },
+ { GUINT_TO_POINTER (0x3294), "/ideographnamecircle" },
+ { GUINT_TO_POINTER (0x3290), "/ideographsuncircle" },
+ { GUINT_TO_POINTER (0x328C), "/ideographwatercircle" },
+ { GUINT_TO_POINTER (0x328D), "/ideographwoodcircle" },
+ { GUINT_TO_POINTER (0x0907), "/ideva" },
+ { GUINT_TO_POINTER (0x00EF), "/idieresis" },
+ { GUINT_TO_POINTER (0x1E2F), "/idieresisacute" },
+ { GUINT_TO_POINTER (0x04E5), "/idieresiscyrillic" },
+ { GUINT_TO_POINTER (0x1ECB), "/idotbelow" },
+ { GUINT_TO_POINTER (0x04D7), "/iebrevecyrillic" },
+ { GUINT_TO_POINTER (0x0435), "/iecyrillic" },
+ { GUINT_TO_POINTER (0x3275), "/ieungacirclekorean" },
+ { GUINT_TO_POINTER (0x3215), "/ieungaparenkorean" },
+ { GUINT_TO_POINTER (0x3267), "/ieungcirclekorean" },
+ { GUINT_TO_POINTER (0x3147), "/ieungkorean" },
+ { GUINT_TO_POINTER (0x3207), "/ieungparenkorean" },
+ { GUINT_TO_POINTER (0x00EC), "/igrave" },
+ { GUINT_TO_POINTER (0x0A87), "/igujarati" },
+ { GUINT_TO_POINTER (0x0A07), "/igurmukhi" },
+ { GUINT_TO_POINTER (0x3044), "/ihiragana" },
+ { GUINT_TO_POINTER (0x1EC9), "/ihookabove" },
+ { GUINT_TO_POINTER (0x0988), "/iibengali" },
+ { GUINT_TO_POINTER (0x0438), "/iicyrillic" },
+ { GUINT_TO_POINTER (0x0908), "/iideva" },
+ { GUINT_TO_POINTER (0x0A88), "/iigujarati" },
+ { GUINT_TO_POINTER (0x0A08), "/iigurmukhi" },
+ { GUINT_TO_POINTER (0x0A40), "/iimatragurmukhi" },
+ { GUINT_TO_POINTER (0x020B), "/iinvertedbreve" },
+ { GUINT_TO_POINTER (0x0439), "/iishortcyrillic" },
+ { GUINT_TO_POINTER (0x09C0), "/iivowelsignbengali" },
+ { GUINT_TO_POINTER (0x0940), "/iivowelsigndeva" },
+ { GUINT_TO_POINTER (0x0AC0), "/iivowelsigngujarati" },
+ { GUINT_TO_POINTER (0x0133), "/ij" },
+ { GUINT_TO_POINTER (0x30A4), "/ikatakana" },
+ { GUINT_TO_POINTER (0xFF72), "/ikatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x3163), "/ikorean" },
+ { GUINT_TO_POINTER (0x02DC), "/ilde" },
+ { GUINT_TO_POINTER (0x05AC), "/iluyhebrew" },
+ { GUINT_TO_POINTER (0x012B), "/imacron" },
+ { GUINT_TO_POINTER (0x04E3), "/imacroncyrillic" },
+ { GUINT_TO_POINTER (0x2253), "/imageorapproximatelyequal" },
+ { GUINT_TO_POINTER (0x0A3F), "/imatragurmukhi" },
+ { GUINT_TO_POINTER (0xFF49), "/imonospace" },
+ { GUINT_TO_POINTER (0x2206), "/increment" },
+ { GUINT_TO_POINTER (0x221E), "/infinity" },
+ { GUINT_TO_POINTER (0x056B), "/iniarmenian" },
+ { GUINT_TO_POINTER (0x222B), "/integral" },
+ { GUINT_TO_POINTER (0x2321), "/integralbottom" },
+ { GUINT_TO_POINTER (0x2321), "/integralbt" },
+ { GUINT_TO_POINTER (0xF8F5), "/integralex" },
+ { GUINT_TO_POINTER (0x2320), "/integraltop" },
+ { GUINT_TO_POINTER (0x2320), "/integraltp" },
+ { GUINT_TO_POINTER (0x2229), "/intersection" },
+ { GUINT_TO_POINTER (0x3305), "/intisquare" },
+ { GUINT_TO_POINTER (0x25D8), "/invbullet" },
+ { GUINT_TO_POINTER (0x25D9), "/invcircle" },
+ { GUINT_TO_POINTER (0x263B), "/invsmileface" },
+ { GUINT_TO_POINTER (0x0451), "/iocyrillic" },
+ { GUINT_TO_POINTER (0x012F), "/iogonek" },
+ { GUINT_TO_POINTER (0x03B9), "/iota" },
+ { GUINT_TO_POINTER (0x03CA), "/iotadieresis" },
+ { GUINT_TO_POINTER (0x0390), "/iotadieresistonos" },
+ { GUINT_TO_POINTER (0x0269), "/iotalatin" },
+ { GUINT_TO_POINTER (0x03AF), "/iotatonos" },
+ { GUINT_TO_POINTER (0x24A4), "/iparen" },
+ { GUINT_TO_POINTER (0x0A72), "/irigurmukhi" },
+ { GUINT_TO_POINTER (0x3043), "/ismallhiragana" },
+ { GUINT_TO_POINTER (0x30A3), "/ismallkatakana" },
+ { GUINT_TO_POINTER (0xFF68), "/ismallkatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x09FA), "/issharbengali" },
+ { GUINT_TO_POINTER (0x0268), "/istroke" },
+ { GUINT_TO_POINTER (0xF6ED), "/isuperior" },
+ { GUINT_TO_POINTER (0x309D), "/iterationhiragana" },
+ { GUINT_TO_POINTER (0x30FD), "/iterationkatakana" },
+ { GUINT_TO_POINTER (0x0129), "/itilde" },
+ { GUINT_TO_POINTER (0x1E2D), "/itildebelow" },
+ { GUINT_TO_POINTER (0x3129), "/iubopomofo" },
+ { GUINT_TO_POINTER (0x044E), "/iucyrillic" },
+ { GUINT_TO_POINTER (0x09BF), "/ivowelsignbengali" },
+ { GUINT_TO_POINTER (0x093F), "/ivowelsigndeva" },
+ { GUINT_TO_POINTER (0x0ABF), "/ivowelsigngujarati" },
+ { GUINT_TO_POINTER (0x0475), "/izhitsacyrillic" },
+ { GUINT_TO_POINTER (0x0477), "/izhitsadblgravecyrillic" },
+ { GUINT_TO_POINTER (0x006A), "/j" },
+ { GUINT_TO_POINTER (0x0571), "/jaarmenian" },
+ { GUINT_TO_POINTER (0x099C), "/jabengali" },
+ { GUINT_TO_POINTER (0x091C), "/jadeva" },
+ { GUINT_TO_POINTER (0x0A9C), "/jagujarati" },
+ { GUINT_TO_POINTER (0x0A1C), "/jagurmukhi" },
+ { GUINT_TO_POINTER (0x3110), "/jbopomofo" },
+ { GUINT_TO_POINTER (0x01F0), "/jcaron" },
+ { GUINT_TO_POINTER (0x24D9), "/jcircle" },
+ { GUINT_TO_POINTER (0x0135), "/jcircumflex" },
+ { GUINT_TO_POINTER (0x029D), "/jcrossedtail" },
+ { GUINT_TO_POINTER (0x025F), "/jdotlessstroke" },
+ { GUINT_TO_POINTER (0x0458), "/jecyrillic" },
+ { GUINT_TO_POINTER (0x062C), "/jeemarabic" },
+ { GUINT_TO_POINTER (0xFE9E), "/jeemfinalarabic" },
+ { GUINT_TO_POINTER (0xFE9F), "/jeeminitialarabic" },
+ { GUINT_TO_POINTER (0xFEA0), "/jeemmedialarabic" },
+ { GUINT_TO_POINTER (0x0698), "/jeharabic" },
+ { GUINT_TO_POINTER (0xFB8B), "/jehfinalarabic" },
+ { GUINT_TO_POINTER (0x099D), "/jhabengali" },
+ { GUINT_TO_POINTER (0x091D), "/jhadeva" },
+ { GUINT_TO_POINTER (0x0A9D), "/jhagujarati" },
+ { GUINT_TO_POINTER (0x0A1D), "/jhagurmukhi" },
+ { GUINT_TO_POINTER (0x057B), "/jheharmenian" },
+ { GUINT_TO_POINTER (0x3004), "/jis" },
+ { GUINT_TO_POINTER (0xFF4A), "/jmonospace" },
+ { GUINT_TO_POINTER (0x24A5), "/jparen" },
+ { GUINT_TO_POINTER (0x02B2), "/jsuperior" },
+ { GUINT_TO_POINTER (0x006B), "/k" },
+ { GUINT_TO_POINTER (0x04A1), "/kabashkircyrillic" },
+ { GUINT_TO_POINTER (0x0995), "/kabengali" },
+ { GUINT_TO_POINTER (0x1E31), "/kacute" },
+ { GUINT_TO_POINTER (0x043A), "/kacyrillic" },
+ { GUINT_TO_POINTER (0x049B), "/kadescendercyrillic" },
+ { GUINT_TO_POINTER (0x0915), "/kadeva" },
+ { GUINT_TO_POINTER (0x05DB), "/kaf" },
+ { GUINT_TO_POINTER (0x0643), "/kafarabic" },
+ { GUINT_TO_POINTER (0xFB3B), "/kafdagesh" },
+ { GUINT_TO_POINTER (0xFB3B), "/kafdageshhebrew" },
+ { GUINT_TO_POINTER (0xFEDA), "/kaffinalarabic" },
+ { GUINT_TO_POINTER (0x05DB), "/kafhebrew" },
+ { GUINT_TO_POINTER (0xFEDB), "/kafinitialarabic" },
+ { GUINT_TO_POINTER (0xFEDC), "/kafmedialarabic" },
+ { GUINT_TO_POINTER (0xFB4D), "/kafrafehebrew" },
+ { GUINT_TO_POINTER (0x0A95), "/kagujarati" },
+ { GUINT_TO_POINTER (0x0A15), "/kagurmukhi" },
+ { GUINT_TO_POINTER (0x304B), "/kahiragana" },
+ { GUINT_TO_POINTER (0x04C4), "/kahookcyrillic" },
+ { GUINT_TO_POINTER (0x30AB), "/kakatakana" },
+ { GUINT_TO_POINTER (0xFF76), "/kakatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x03BA), "/kappa" },
+ { GUINT_TO_POINTER (0x03F0), "/kappasymbolgreek" },
+ { GUINT_TO_POINTER (0x3171), "/kapyeounmieumkorean" },
+ { GUINT_TO_POINTER (0x3184), "/kapyeounphieuphkorean" },
+ { GUINT_TO_POINTER (0x3178), "/kapyeounpieupkorean" },
+ { GUINT_TO_POINTER (0x3179), "/kapyeounssangpieupkorean" },
+ { GUINT_TO_POINTER (0x330D), "/karoriisquare" },
+ { GUINT_TO_POINTER (0x0640), "/kashidaautoarabic" },
+ { GUINT_TO_POINTER (0x0640), "/kashidaautonosidebearingarabic" },
+ { GUINT_TO_POINTER (0x30F5), "/kasmallkatakana" },
+ { GUINT_TO_POINTER (0x3384), "/kasquare" },
+ { GUINT_TO_POINTER (0x0650), "/kasraarabic" },
+ { GUINT_TO_POINTER (0x064D), "/kasratanarabic" },
+ { GUINT_TO_POINTER (0x049F), "/kastrokecyrillic" },
+ { GUINT_TO_POINTER (0xFF70), "/katahiraprolongmarkhalfwidth" },
+ { GUINT_TO_POINTER (0x049D), "/kaverticalstrokecyrillic" },
+ { GUINT_TO_POINTER (0x310E), "/kbopomofo" },
+ { GUINT_TO_POINTER (0x3389), "/kcalsquare" },
+ { GUINT_TO_POINTER (0x01E9), "/kcaron" },
+ { GUINT_TO_POINTER (0x0137), "/kcedilla" },
+ { GUINT_TO_POINTER (0x24DA), "/kcircle" },
+ { GUINT_TO_POINTER (0x0137), "/kcommaaccent" },
+ { GUINT_TO_POINTER (0x1E33), "/kdotbelow" },
+ { GUINT_TO_POINTER (0x0584), "/keharmenian" },
+ { GUINT_TO_POINTER (0x3051), "/kehiragana" },
+ { GUINT_TO_POINTER (0x30B1), "/kekatakana" },
+ { GUINT_TO_POINTER (0xFF79), "/kekatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x056F), "/kenarmenian" },
+ { GUINT_TO_POINTER (0x30F6), "/kesmallkatakana" },
+ { GUINT_TO_POINTER (0x0138), "/kgreenlandic" },
+ { GUINT_TO_POINTER (0x0996), "/khabengali" },
+ { GUINT_TO_POINTER (0x0445), "/khacyrillic" },
+ { GUINT_TO_POINTER (0x0916), "/khadeva" },
+ { GUINT_TO_POINTER (0x0A96), "/khagujarati" },
+ { GUINT_TO_POINTER (0x0A16), "/khagurmukhi" },
+ { GUINT_TO_POINTER (0x062E), "/khaharabic" },
+ { GUINT_TO_POINTER (0xFEA6), "/khahfinalarabic" },
+ { GUINT_TO_POINTER (0xFEA7), "/khahinitialarabic" },
+ { GUINT_TO_POINTER (0xFEA8), "/khahmedialarabic" },
+ { GUINT_TO_POINTER (0x03E7), "/kheicoptic" },
+ { GUINT_TO_POINTER (0x0959), "/khhadeva" },
+ { GUINT_TO_POINTER (0x0A59), "/khhagurmukhi" },
+ { GUINT_TO_POINTER (0x3278), "/khieukhacirclekorean" },
+ { GUINT_TO_POINTER (0x3218), "/khieukhaparenkorean" },
+ { GUINT_TO_POINTER (0x326A), "/khieukhcirclekorean" },
+ { GUINT_TO_POINTER (0x314B), "/khieukhkorean" },
+ { GUINT_TO_POINTER (0x320A), "/khieukhparenkorean" },
+ { GUINT_TO_POINTER (0x0E02), "/khokhaithai" },
+ { GUINT_TO_POINTER (0x0E05), "/khokhonthai" },
+ { GUINT_TO_POINTER (0x0E03), "/khokhuatthai" },
+ { GUINT_TO_POINTER (0x0E04), "/khokhwaithai" },
+ { GUINT_TO_POINTER (0x0E5B), "/khomutthai" },
+ { GUINT_TO_POINTER (0x0199), "/khook" },
+ { GUINT_TO_POINTER (0x0E06), "/khorakhangthai" },
+ { GUINT_TO_POINTER (0x3391), "/khzsquare" },
+ { GUINT_TO_POINTER (0x304D), "/kihiragana" },
+ { GUINT_TO_POINTER (0x30AD), "/kikatakana" },
+ { GUINT_TO_POINTER (0xFF77), "/kikatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x3315), "/kiroguramusquare" },
+ { GUINT_TO_POINTER (0x3316), "/kiromeetorusquare" },
+ { GUINT_TO_POINTER (0x3314), "/kirosquare" },
+ { GUINT_TO_POINTER (0x326E), "/kiyeokacirclekorean" },
+ { GUINT_TO_POINTER (0x320E), "/kiyeokaparenkorean" },
+ { GUINT_TO_POINTER (0x3260), "/kiyeokcirclekorean" },
+ { GUINT_TO_POINTER (0x3131), "/kiyeokkorean" },
+ { GUINT_TO_POINTER (0x3200), "/kiyeokparenkorean" },
+ { GUINT_TO_POINTER (0x3133), "/kiyeoksioskorean" },
+ { GUINT_TO_POINTER (0x045C), "/kjecyrillic" },
+ { GUINT_TO_POINTER (0x1E35), "/klinebelow" },
+ { GUINT_TO_POINTER (0x3398), "/klsquare" },
+ { GUINT_TO_POINTER (0x33A6), "/kmcubedsquare" },
+ { GUINT_TO_POINTER (0xFF4B), "/kmonospace" },
+ { GUINT_TO_POINTER (0x33A2), "/kmsquaredsquare" },
+ { GUINT_TO_POINTER (0x3053), "/kohiragana" },
+ { GUINT_TO_POINTER (0x33C0), "/kohmsquare" },
+ { GUINT_TO_POINTER (0x0E01), "/kokaithai" },
+ { GUINT_TO_POINTER (0x30B3), "/kokatakana" },
+ { GUINT_TO_POINTER (0xFF7A), "/kokatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x331E), "/kooposquare" },
+ { GUINT_TO_POINTER (0x0481), "/koppacyrillic" },
+ { GUINT_TO_POINTER (0x327F), "/koreanstandardsymbol" },
+ { GUINT_TO_POINTER (0x0343), "/koroniscmb" },
+ { GUINT_TO_POINTER (0x24A6), "/kparen" },
+ { GUINT_TO_POINTER (0x33AA), "/kpasquare" },
+ { GUINT_TO_POINTER (0x046F), "/ksicyrillic" },
+ { GUINT_TO_POINTER (0x33CF), "/ktsquare" },
+ { GUINT_TO_POINTER (0x029E), "/kturned" },
+ { GUINT_TO_POINTER (0x304F), "/kuhiragana" },
+ { GUINT_TO_POINTER (0x30AF), "/kukatakana" },
+ { GUINT_TO_POINTER (0xFF78), "/kukatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x33B8), "/kvsquare" },
+ { GUINT_TO_POINTER (0x33BE), "/kwsquare" },
+ { GUINT_TO_POINTER (0x006C), "/l" },
+ { GUINT_TO_POINTER (0x09B2), "/labengali" },
+ { GUINT_TO_POINTER (0x013A), "/lacute" },
+ { GUINT_TO_POINTER (0x0932), "/ladeva" },
+ { GUINT_TO_POINTER (0x0AB2), "/lagujarati" },
+ { GUINT_TO_POINTER (0x0A32), "/lagurmukhi" },
+ { GUINT_TO_POINTER (0x0E45), "/lakkhangyaothai" },
+ { GUINT_TO_POINTER (0xFEFC), "/lamaleffinalarabic" },
+ { GUINT_TO_POINTER (0xFEF8), "/lamalefhamzaabovefinalarabic" },
+ { GUINT_TO_POINTER (0xFEF7), "/lamalefhamzaaboveisolatedarabic" },
+ { GUINT_TO_POINTER (0xFEFA), "/lamalefhamzabelowfinalarabic" },
+ { GUINT_TO_POINTER (0xFEF9), "/lamalefhamzabelowisolatedarabic" },
+ { GUINT_TO_POINTER (0xFEFB), "/lamalefisolatedarabic" },
+ { GUINT_TO_POINTER (0xFEF6), "/lamalefmaddaabovefinalarabic" },
+ { GUINT_TO_POINTER (0xFEF5), "/lamalefmaddaaboveisolatedarabic" },
+ { GUINT_TO_POINTER (0x0644), "/lamarabic" },
+ { GUINT_TO_POINTER (0x03BB), "/lambda" },
+ { GUINT_TO_POINTER (0x019B), "/lambdastroke" },
+ { GUINT_TO_POINTER (0x05DC), "/lamed" },
+ { GUINT_TO_POINTER (0xFB3C), "/lameddagesh" },
+ { GUINT_TO_POINTER (0xFB3C), "/lameddageshhebrew" },
+ { GUINT_TO_POINTER (0x05DC), "/lamedhebrew" },
+ { GUINT_TO_POINTER (0x05DC), "/lamedholam" },
+ { GUINT_TO_POINTER (0x05B9), "/lamedholam" },
+ { GUINT_TO_POINTER (0x05DC), "/lamedholamdagesh" },
+ { GUINT_TO_POINTER (0x05B9), "/lamedholamdagesh" },
+ { GUINT_TO_POINTER (0x05BC), "/lamedholamdagesh" },
+ { GUINT_TO_POINTER (0x05DC), "/lamedholamdageshhebrew" },
+ { GUINT_TO_POINTER (0x05B9), "/lamedholamdageshhebrew" },
+ { GUINT_TO_POINTER (0x05BC), "/lamedholamdageshhebrew" },
+ { GUINT_TO_POINTER (0x05DC), "/lamedholamhebrew" },
+ { GUINT_TO_POINTER (0x05B9), "/lamedholamhebrew" },
+ { GUINT_TO_POINTER (0xFEDE), "/lamfinalarabic" },
+ { GUINT_TO_POINTER (0xFCCA), "/lamhahinitialarabic" },
+ { GUINT_TO_POINTER (0xFEDF), "/laminitialarabic" },
+ { GUINT_TO_POINTER (0xFCC9), "/lamjeeminitialarabic" },
+ { GUINT_TO_POINTER (0xFCCB), "/lamkhahinitialarabic" },
+ { GUINT_TO_POINTER (0xFDF2), "/lamlamhehisolatedarabic" },
+ { GUINT_TO_POINTER (0xFEE0), "/lammedialarabic" },
+ { GUINT_TO_POINTER (0xFD88), "/lammeemhahinitialarabic" },
+ { GUINT_TO_POINTER (0xFCCC), "/lammeeminitialarabic" },
+ { GUINT_TO_POINTER (0xFEDF), "/lammeemjeeminitialarabic" },
+ { GUINT_TO_POINTER (0xFEE4), "/lammeemjeeminitialarabic" },
+ { GUINT_TO_POINTER (0xFEA0), "/lammeemjeeminitialarabic" },
+ { GUINT_TO_POINTER (0xFEDF), "/lammeemkhahinitialarabic" },
+ { GUINT_TO_POINTER (0xFEE4), "/lammeemkhahinitialarabic" },
+ { GUINT_TO_POINTER (0xFEA8), "/lammeemkhahinitialarabic" },
+ { GUINT_TO_POINTER (0x25EF), "/largecircle" },
+ { GUINT_TO_POINTER (0x019A), "/lbar" },
+ { GUINT_TO_POINTER (0x026C), "/lbelt" },
+ { GUINT_TO_POINTER (0x310C), "/lbopomofo" },
+ { GUINT_TO_POINTER (0x013E), "/lcaron" },
+ { GUINT_TO_POINTER (0x013C), "/lcedilla" },
+ { GUINT_TO_POINTER (0x24DB), "/lcircle" },
+ { GUINT_TO_POINTER (0x1E3D), "/lcircumflexbelow" },
+ { GUINT_TO_POINTER (0x013C), "/lcommaaccent" },
+ { GUINT_TO_POINTER (0x0140), "/ldot" },
+ { GUINT_TO_POINTER (0x0140), "/ldotaccent" },
+ { GUINT_TO_POINTER (0x1E37), "/ldotbelow" },
+ { GUINT_TO_POINTER (0x1E39), "/ldotbelowmacron" },
+ { GUINT_TO_POINTER (0x031A), "/leftangleabovecmb" },
+ { GUINT_TO_POINTER (0x0318), "/lefttackbelowcmb" },
+ { GUINT_TO_POINTER (0x003C), "/less" },
+ { GUINT_TO_POINTER (0x2264), "/lessequal" },
+ { GUINT_TO_POINTER (0x22DA), "/lessequalorgreater" },
+ { GUINT_TO_POINTER (0xFF1C), "/lessmonospace" },
+ { GUINT_TO_POINTER (0x2272), "/lessorequivalent" },
+ { GUINT_TO_POINTER (0x2276), "/lessorgreater" },
+ { GUINT_TO_POINTER (0x2266), "/lessoverequal" },
+ { GUINT_TO_POINTER (0xFE64), "/lesssmall" },
+ { GUINT_TO_POINTER (0x026E), "/lezh" },
+ { GUINT_TO_POINTER (0x258C), "/lfblock" },
+ { GUINT_TO_POINTER (0x026D), "/lhookretroflex" },
+ { GUINT_TO_POINTER (0x20A4), "/lira" },
+ { GUINT_TO_POINTER (0x056C), "/liwnarmenian" },
+ { GUINT_TO_POINTER (0x01C9), "/lj" },
+ { GUINT_TO_POINTER (0x0459), "/ljecyrillic" },
+ { GUINT_TO_POINTER (0xF6C0), "/ll" },
+ { GUINT_TO_POINTER (0x0933), "/lladeva" },
+ { GUINT_TO_POINTER (0x0AB3), "/llagujarati" },
+ { GUINT_TO_POINTER (0x1E3B), "/llinebelow" },
+ { GUINT_TO_POINTER (0x0934), "/llladeva" },
+ { GUINT_TO_POINTER (0x09E1), "/llvocalicbengali" },
+ { GUINT_TO_POINTER (0x0961), "/llvocalicdeva" },
+ { GUINT_TO_POINTER (0x09E3), "/llvocalicvowelsignbengali" },
+ { GUINT_TO_POINTER (0x0963), "/llvocalicvowelsigndeva" },
+ { GUINT_TO_POINTER (0x026B), "/lmiddletilde" },
+ { GUINT_TO_POINTER (0xFF4C), "/lmonospace" },
+ { GUINT_TO_POINTER (0x33D0), "/lmsquare" },
+ { GUINT_TO_POINTER (0x0E2C), "/lochulathai" },
+ { GUINT_TO_POINTER (0x2227), "/logicaland" },
+ { GUINT_TO_POINTER (0x00AC), "/logicalnot" },
+ { GUINT_TO_POINTER (0x2310), "/logicalnotreversed" },
+ { GUINT_TO_POINTER (0x2228), "/logicalor" },
+ { GUINT_TO_POINTER (0x0E25), "/lolingthai" },
+ { GUINT_TO_POINTER (0x017F), "/longs" },
+ { GUINT_TO_POINTER (0xFE4E), "/lowlinecenterline" },
+ { GUINT_TO_POINTER (0x0332), "/lowlinecmb" },
+ { GUINT_TO_POINTER (0xFE4D), "/lowlinedashed" },
+ { GUINT_TO_POINTER (0x25CA), "/lozenge" },
+ { GUINT_TO_POINTER (0x24A7), "/lparen" },
+ { GUINT_TO_POINTER (0x0142), "/lslash" },
+ { GUINT_TO_POINTER (0x2113), "/lsquare" },
+ { GUINT_TO_POINTER (0xF6EE), "/lsuperior" },
+ { GUINT_TO_POINTER (0x2591), "/ltshade" },
+ { GUINT_TO_POINTER (0x0E26), "/luthai" },
+ { GUINT_TO_POINTER (0x098C), "/lvocalicbengali" },
+ { GUINT_TO_POINTER (0x090C), "/lvocalicdeva" },
+ { GUINT_TO_POINTER (0x09E2), "/lvocalicvowelsignbengali" },
+ { GUINT_TO_POINTER (0x0962), "/lvocalicvowelsigndeva" },
+ { GUINT_TO_POINTER (0x33D3), "/lxsquare" },
+ { GUINT_TO_POINTER (0x006D), "/m" },
+ { GUINT_TO_POINTER (0x09AE), "/mabengali" },
+ { GUINT_TO_POINTER (0x00AF), "/macron" },
+ { GUINT_TO_POINTER (0x0331), "/macronbelowcmb" },
+ { GUINT_TO_POINTER (0x0304), "/macroncmb" },
+ { GUINT_TO_POINTER (0x02CD), "/macronlowmod" },
+ { GUINT_TO_POINTER (0xFFE3), "/macronmonospace" },
+ { GUINT_TO_POINTER (0x1E3F), "/macute" },
+ { GUINT_TO_POINTER (0x092E), "/madeva" },
+ { GUINT_TO_POINTER (0x0AAE), "/magujarati" },
+ { GUINT_TO_POINTER (0x0A2E), "/magurmukhi" },
+ { GUINT_TO_POINTER (0x05A4), "/mahapakhhebrew" },
+ { GUINT_TO_POINTER (0x05A4), "/mahapakhlefthebrew" },
+ { GUINT_TO_POINTER (0x307E), "/mahiragana" },
+ { GUINT_TO_POINTER (0xF895), "/maichattawalowleftthai" },
+ { GUINT_TO_POINTER (0xF894), "/maichattawalowrightthai" },
+ { GUINT_TO_POINTER (0x0E4B), "/maichattawathai" },
+ { GUINT_TO_POINTER (0xF893), "/maichattawaupperleftthai" },
+ { GUINT_TO_POINTER (0xF88C), "/maieklowleftthai" },
+ { GUINT_TO_POINTER (0xF88B), "/maieklowrightthai" },
+ { GUINT_TO_POINTER (0x0E48), "/maiekthai" },
+ { GUINT_TO_POINTER (0xF88A), "/maiekupperleftthai" },
+ { GUINT_TO_POINTER (0xF884), "/maihanakatleftthai" },
+ { GUINT_TO_POINTER (0x0E31), "/maihanakatthai" },
+ { GUINT_TO_POINTER (0xF889), "/maitaikhuleftthai" },
+ { GUINT_TO_POINTER (0x0E47), "/maitaikhuthai" },
+ { GUINT_TO_POINTER (0xF88F), "/maitholowleftthai" },
+ { GUINT_TO_POINTER (0xF88E), "/maitholowrightthai" },
+ { GUINT_TO_POINTER (0x0E49), "/maithothai" },
+ { GUINT_TO_POINTER (0xF88D), "/maithoupperleftthai" },
+ { GUINT_TO_POINTER (0xF892), "/maitrilowleftthai" },
+ { GUINT_TO_POINTER (0xF891), "/maitrilowrightthai" },
+ { GUINT_TO_POINTER (0x0E4A), "/maitrithai" },
+ { GUINT_TO_POINTER (0xF890), "/maitriupperleftthai" },
+ { GUINT_TO_POINTER (0x0E46), "/maiyamokthai" },
+ { GUINT_TO_POINTER (0x30DE), "/makatakana" },
+ { GUINT_TO_POINTER (0xFF8F), "/makatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x2642), "/male" },
+ { GUINT_TO_POINTER (0x3347), "/mansyonsquare" },
+ { GUINT_TO_POINTER (0x05BE), "/maqafhebrew" },
+ { GUINT_TO_POINTER (0x2642), "/mars" },
+ { GUINT_TO_POINTER (0x05AF), "/masoracirclehebrew" },
+ { GUINT_TO_POINTER (0x3383), "/masquare" },
+ { GUINT_TO_POINTER (0x3107), "/mbopomofo" },
+ { GUINT_TO_POINTER (0x33D4), "/mbsquare" },
+ { GUINT_TO_POINTER (0x24DC), "/mcircle" },
+ { GUINT_TO_POINTER (0x33A5), "/mcubedsquare" },
+ { GUINT_TO_POINTER (0x1E41), "/mdotaccent" },
+ { GUINT_TO_POINTER (0x1E43), "/mdotbelow" },
+ { GUINT_TO_POINTER (0x0645), "/meemarabic" },
+ { GUINT_TO_POINTER (0xFEE2), "/meemfinalarabic" },
+ { GUINT_TO_POINTER (0xFEE3), "/meeminitialarabic" },
+ { GUINT_TO_POINTER (0xFEE4), "/meemmedialarabic" },
+ { GUINT_TO_POINTER (0xFCD1), "/meemmeeminitialarabic" },
+ { GUINT_TO_POINTER (0xFC48), "/meemmeemisolatedarabic" },
+ { GUINT_TO_POINTER (0x334D), "/meetorusquare" },
+ { GUINT_TO_POINTER (0x3081), "/mehiragana" },
+ { GUINT_TO_POINTER (0x337E), "/meizierasquare" },
+ { GUINT_TO_POINTER (0x30E1), "/mekatakana" },
+ { GUINT_TO_POINTER (0xFF92), "/mekatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x05DE), "/mem" },
+ { GUINT_TO_POINTER (0xFB3E), "/memdagesh" },
+ { GUINT_TO_POINTER (0xFB3E), "/memdageshhebrew" },
+ { GUINT_TO_POINTER (0x05DE), "/memhebrew" },
+ { GUINT_TO_POINTER (0x0574), "/menarmenian" },
+ { GUINT_TO_POINTER (0x05A5), "/merkhahebrew" },
+ { GUINT_TO_POINTER (0x05A6), "/merkhakefulahebrew" },
+ { GUINT_TO_POINTER (0x05A6), "/merkhakefulalefthebrew" },
+ { GUINT_TO_POINTER (0x05A5), "/merkhalefthebrew" },
+ { GUINT_TO_POINTER (0x0271), "/mhook" },
+ { GUINT_TO_POINTER (0x3392), "/mhzsquare" },
+ { GUINT_TO_POINTER (0xFF65), "/middledotkatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x00B7), "/middot" },
+ { GUINT_TO_POINTER (0x3272), "/mieumacirclekorean" },
+ { GUINT_TO_POINTER (0x3212), "/mieumaparenkorean" },
+ { GUINT_TO_POINTER (0x3264), "/mieumcirclekorean" },
+ { GUINT_TO_POINTER (0x3141), "/mieumkorean" },
+ { GUINT_TO_POINTER (0x3170), "/mieumpansioskorean" },
+ { GUINT_TO_POINTER (0x3204), "/mieumparenkorean" },
+ { GUINT_TO_POINTER (0x316E), "/mieumpieupkorean" },
+ { GUINT_TO_POINTER (0x316F), "/mieumsioskorean" },
+ { GUINT_TO_POINTER (0x307F), "/mihiragana" },
+ { GUINT_TO_POINTER (0x30DF), "/mikatakana" },
+ { GUINT_TO_POINTER (0xFF90), "/mikatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x2212), "/minus" },
+ { GUINT_TO_POINTER (0x0320), "/minusbelowcmb" },
+ { GUINT_TO_POINTER (0x2296), "/minuscircle" },
+ { GUINT_TO_POINTER (0x02D7), "/minusmod" },
+ { GUINT_TO_POINTER (0x2213), "/minusplus" },
+ { GUINT_TO_POINTER (0x2032), "/minute" },
+ { GUINT_TO_POINTER (0x334A), "/miribaarusquare" },
+ { GUINT_TO_POINTER (0x3349), "/mirisquare" },
+ { GUINT_TO_POINTER (0x0270), "/mlonglegturned" },
+ { GUINT_TO_POINTER (0x3396), "/mlsquare" },
+ { GUINT_TO_POINTER (0x33A3), "/mmcubedsquare" },
+ { GUINT_TO_POINTER (0xFF4D), "/mmonospace" },
+ { GUINT_TO_POINTER (0x339F), "/mmsquaredsquare" },
+ { GUINT_TO_POINTER (0x3082), "/mohiragana" },
+ { GUINT_TO_POINTER (0x33C1), "/mohmsquare" },
+ { GUINT_TO_POINTER (0x30E2), "/mokatakana" },
+ { GUINT_TO_POINTER (0xFF93), "/mokatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x33D6), "/molsquare" },
+ { GUINT_TO_POINTER (0x0E21), "/momathai" },
+ { GUINT_TO_POINTER (0x33A7), "/moverssquare" },
+ { GUINT_TO_POINTER (0x33A8), "/moverssquaredsquare" },
+ { GUINT_TO_POINTER (0x24A8), "/mparen" },
+ { GUINT_TO_POINTER (0x33AB), "/mpasquare" },
+ { GUINT_TO_POINTER (0x33B3), "/mssquare" },
+ { GUINT_TO_POINTER (0xF6EF), "/msuperior" },
+ { GUINT_TO_POINTER (0x026F), "/mturned" },
+ { GUINT_TO_POINTER (0x00B5), "/mu" },
+ { GUINT_TO_POINTER (0x00B5), "/mu1" },
+ { GUINT_TO_POINTER (0x3382), "/muasquare" },
+ { GUINT_TO_POINTER (0x226B), "/muchgreater" },
+ { GUINT_TO_POINTER (0x226A), "/muchless" },
+ { GUINT_TO_POINTER (0x338C), "/mufsquare" },
+ { GUINT_TO_POINTER (0x03BC), "/mugreek" },
+ { GUINT_TO_POINTER (0x338D), "/mugsquare" },
+ { GUINT_TO_POINTER (0x3080), "/muhiragana" },
+ { GUINT_TO_POINTER (0x30E0), "/mukatakana" },
+ { GUINT_TO_POINTER (0xFF91), "/mukatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x3395), "/mulsquare" },
+ { GUINT_TO_POINTER (0x00D7), "/multiply" },
+ { GUINT_TO_POINTER (0x339B), "/mumsquare" },
+ { GUINT_TO_POINTER (0x05A3), "/munahhebrew" },
+ { GUINT_TO_POINTER (0x05A3), "/munahlefthebrew" },
+ { GUINT_TO_POINTER (0x266A), "/musicalnote" },
+ { GUINT_TO_POINTER (0x266B), "/musicalnotedbl" },
+ { GUINT_TO_POINTER (0x266D), "/musicflatsign" },
+ { GUINT_TO_POINTER (0x266F), "/musicsharpsign" },
+ { GUINT_TO_POINTER (0x33B2), "/mussquare" },
+ { GUINT_TO_POINTER (0x33B6), "/muvsquare" },
+ { GUINT_TO_POINTER (0x33BC), "/muwsquare" },
+ { GUINT_TO_POINTER (0x33B9), "/mvmegasquare" },
+ { GUINT_TO_POINTER (0x33B7), "/mvsquare" },
+ { GUINT_TO_POINTER (0x33BF), "/mwmegasquare" },
+ { GUINT_TO_POINTER (0x33BD), "/mwsquare" },
+ { GUINT_TO_POINTER (0x006E), "/n" },
+ { GUINT_TO_POINTER (0x09A8), "/nabengali" },
+ { GUINT_TO_POINTER (0x2207), "/nabla" },
+ { GUINT_TO_POINTER (0x0144), "/nacute" },
+ { GUINT_TO_POINTER (0x0928), "/nadeva" },
+ { GUINT_TO_POINTER (0x0AA8), "/nagujarati" },
+ { GUINT_TO_POINTER (0x0A28), "/nagurmukhi" },
+ { GUINT_TO_POINTER (0x306A), "/nahiragana" },
+ { GUINT_TO_POINTER (0x30CA), "/nakatakana" },
+ { GUINT_TO_POINTER (0xFF85), "/nakatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x0149), "/napostrophe" },
+ { GUINT_TO_POINTER (0x3381), "/nasquare" },
+ { GUINT_TO_POINTER (0x310B), "/nbopomofo" },
+ { GUINT_TO_POINTER (0x00A0), "/nbspace" },
+ { GUINT_TO_POINTER (0x0148), "/ncaron" },
+ { GUINT_TO_POINTER (0x0146), "/ncedilla" },
+ { GUINT_TO_POINTER (0x24DD), "/ncircle" },
+ { GUINT_TO_POINTER (0x1E4B), "/ncircumflexbelow" },
+ { GUINT_TO_POINTER (0x0146), "/ncommaaccent" },
+ { GUINT_TO_POINTER (0x1E45), "/ndotaccent" },
+ { GUINT_TO_POINTER (0x1E47), "/ndotbelow" },
+ { GUINT_TO_POINTER (0x306D), "/nehiragana" },
+ { GUINT_TO_POINTER (0x30CD), "/nekatakana" },
+ { GUINT_TO_POINTER (0xFF88), "/nekatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x20AA), "/newsheqelsign" },
+ { GUINT_TO_POINTER (0x338B), "/nfsquare" },
+ { GUINT_TO_POINTER (0x0999), "/ngabengali" },
+ { GUINT_TO_POINTER (0x0919), "/ngadeva" },
+ { GUINT_TO_POINTER (0x0A99), "/ngagujarati" },
+ { GUINT_TO_POINTER (0x0A19), "/ngagurmukhi" },
+ { GUINT_TO_POINTER (0x0E07), "/ngonguthai" },
+ { GUINT_TO_POINTER (0x3093), "/nhiragana" },
+ { GUINT_TO_POINTER (0x0272), "/nhookleft" },
+ { GUINT_TO_POINTER (0x0273), "/nhookretroflex" },
+ { GUINT_TO_POINTER (0x326F), "/nieunacirclekorean" },
+ { GUINT_TO_POINTER (0x320F), "/nieunaparenkorean" },
+ { GUINT_TO_POINTER (0x3135), "/nieuncieuckorean" },
+ { GUINT_TO_POINTER (0x3261), "/nieuncirclekorean" },
+ { GUINT_TO_POINTER (0x3136), "/nieunhieuhkorean" },
+ { GUINT_TO_POINTER (0x3134), "/nieunkorean" },
+ { GUINT_TO_POINTER (0x3168), "/nieunpansioskorean" },
+ { GUINT_TO_POINTER (0x3201), "/nieunparenkorean" },
+ { GUINT_TO_POINTER (0x3167), "/nieunsioskorean" },
+ { GUINT_TO_POINTER (0x3166), "/nieuntikeutkorean" },
+ { GUINT_TO_POINTER (0x306B), "/nihiragana" },
+ { GUINT_TO_POINTER (0x30CB), "/nikatakana" },
+ { GUINT_TO_POINTER (0xFF86), "/nikatakanahalfwidth" },
+ { GUINT_TO_POINTER (0xF899), "/nikhahitleftthai" },
+ { GUINT_TO_POINTER (0x0E4D), "/nikhahitthai" },
+ { GUINT_TO_POINTER (0x0039), "/nine" },
+ { GUINT_TO_POINTER (0x0669), "/ninearabic" },
+ { GUINT_TO_POINTER (0x09EF), "/ninebengali" },
+ { GUINT_TO_POINTER (0x2468), "/ninecircle" },
+ { GUINT_TO_POINTER (0x2792), "/ninecircleinversesansserif" },
+ { GUINT_TO_POINTER (0x096F), "/ninedeva" },
+ { GUINT_TO_POINTER (0x0AEF), "/ninegujarati" },
+ { GUINT_TO_POINTER (0x0A6F), "/ninegurmukhi" },
+ { GUINT_TO_POINTER (0x0669), "/ninehackarabic" },
+ { GUINT_TO_POINTER (0x3029), "/ninehangzhou" },
+ { GUINT_TO_POINTER (0x3228), "/nineideographicparen" },
+ { GUINT_TO_POINTER (0x2089), "/nineinferior" },
+ { GUINT_TO_POINTER (0xFF19), "/ninemonospace" },
+ { GUINT_TO_POINTER (0xF739), "/nineoldstyle" },
+ { GUINT_TO_POINTER (0x247C), "/nineparen" },
+ { GUINT_TO_POINTER (0x2490), "/nineperiod" },
+ { GUINT_TO_POINTER (0x06F9), "/ninepersian" },
+ { GUINT_TO_POINTER (0x2178), "/nineroman" },
+ { GUINT_TO_POINTER (0x2079), "/ninesuperior" },
+ { GUINT_TO_POINTER (0x2472), "/nineteencircle" },
+ { GUINT_TO_POINTER (0x2486), "/nineteenparen" },
+ { GUINT_TO_POINTER (0x249A), "/nineteenperiod" },
+ { GUINT_TO_POINTER (0x0E59), "/ninethai" },
+ { GUINT_TO_POINTER (0x01CC), "/nj" },
+ { GUINT_TO_POINTER (0x045A), "/njecyrillic" },
+ { GUINT_TO_POINTER (0x30F3), "/nkatakana" },
+ { GUINT_TO_POINTER (0xFF9D), "/nkatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x019E), "/nlegrightlong" },
+ { GUINT_TO_POINTER (0x1E49), "/nlinebelow" },
+ { GUINT_TO_POINTER (0xFF4E), "/nmonospace" },
+ { GUINT_TO_POINTER (0x339A), "/nmsquare" },
+ { GUINT_TO_POINTER (0x09A3), "/nnabengali" },
+ { GUINT_TO_POINTER (0x0923), "/nnadeva" },
+ { GUINT_TO_POINTER (0x0AA3), "/nnagujarati" },
+ { GUINT_TO_POINTER (0x0A23), "/nnagurmukhi" },
+ { GUINT_TO_POINTER (0x0929), "/nnnadeva" },
+ { GUINT_TO_POINTER (0x306E), "/nohiragana" },
+ { GUINT_TO_POINTER (0x30CE), "/nokatakana" },
+ { GUINT_TO_POINTER (0xFF89), "/nokatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x00A0), "/nonbreakingspace" },
+ { GUINT_TO_POINTER (0x0E13), "/nonenthai" },
+ { GUINT_TO_POINTER (0x0E19), "/nonuthai" },
+ { GUINT_TO_POINTER (0x0646), "/noonarabic" },
+ { GUINT_TO_POINTER (0xFEE6), "/noonfinalarabic" },
+ { GUINT_TO_POINTER (0x06BA), "/noonghunnaarabic" },
+ { GUINT_TO_POINTER (0xFB9F), "/noonghunnafinalarabic" },
+ { GUINT_TO_POINTER (0xFEE7), "/noonhehinitialarabic" },
+ { GUINT_TO_POINTER (0xFEEC), "/noonhehinitialarabic" },
+ { GUINT_TO_POINTER (0xFEE7), "/nooninitialarabic" },
+ { GUINT_TO_POINTER (0xFCD2), "/noonjeeminitialarabic" },
+ { GUINT_TO_POINTER (0xFC4B), "/noonjeemisolatedarabic" },
+ { GUINT_TO_POINTER (0xFEE8), "/noonmedialarabic" },
+ { GUINT_TO_POINTER (0xFCD5), "/noonmeeminitialarabic" },
+ { GUINT_TO_POINTER (0xFC4E), "/noonmeemisolatedarabic" },
+ { GUINT_TO_POINTER (0xFC8D), "/noonnoonfinalarabic" },
+ { GUINT_TO_POINTER (0x220C), "/notcontains" },
+ { GUINT_TO_POINTER (0x2209), "/notelement" },
+ { GUINT_TO_POINTER (0x2209), "/notelementof" },
+ { GUINT_TO_POINTER (0x2260), "/notequal" },
+ { GUINT_TO_POINTER (0x226F), "/notgreater" },
+ { GUINT_TO_POINTER (0x2271), "/notgreaternorequal" },
+ { GUINT_TO_POINTER (0x2279), "/notgreaternorless" },
+ { GUINT_TO_POINTER (0x2262), "/notidentical" },
+ { GUINT_TO_POINTER (0x226E), "/notless" },
+ { GUINT_TO_POINTER (0x2270), "/notlessnorequal" },
+ { GUINT_TO_POINTER (0x2226), "/notparallel" },
+ { GUINT_TO_POINTER (0x2280), "/notprecedes" },
+ { GUINT_TO_POINTER (0x2284), "/notsubset" },
+ { GUINT_TO_POINTER (0x2281), "/notsucceeds" },
+ { GUINT_TO_POINTER (0x2285), "/notsuperset" },
+ { GUINT_TO_POINTER (0x0576), "/nowarmenian" },
+ { GUINT_TO_POINTER (0x24A9), "/nparen" },
+ { GUINT_TO_POINTER (0x33B1), "/nssquare" },
+ { GUINT_TO_POINTER (0x207F), "/nsuperior" },
+ { GUINT_TO_POINTER (0x00F1), "/ntilde" },
+ { GUINT_TO_POINTER (0x03BD), "/nu" },
+ { GUINT_TO_POINTER (0x306C), "/nuhiragana" },
+ { GUINT_TO_POINTER (0x30CC), "/nukatakana" },
+ { GUINT_TO_POINTER (0xFF87), "/nukatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x09BC), "/nuktabengali" },
+ { GUINT_TO_POINTER (0x093C), "/nuktadeva" },
+ { GUINT_TO_POINTER (0x0ABC), "/nuktagujarati" },
+ { GUINT_TO_POINTER (0x0A3C), "/nuktagurmukhi" },
+ { GUINT_TO_POINTER (0x0023), "/numbersign" },
+ { GUINT_TO_POINTER (0xFF03), "/numbersignmonospace" },
+ { GUINT_TO_POINTER (0xFE5F), "/numbersignsmall" },
+ { GUINT_TO_POINTER (0x0374), "/numeralsigngreek" },
+ { GUINT_TO_POINTER (0x0375), "/numeralsignlowergreek" },
+ { GUINT_TO_POINTER (0x2116), "/numero" },
+ { GUINT_TO_POINTER (0x05E0), "/nun" },
+ { GUINT_TO_POINTER (0xFB40), "/nundagesh" },
+ { GUINT_TO_POINTER (0xFB40), "/nundageshhebrew" },
+ { GUINT_TO_POINTER (0x05E0), "/nunhebrew" },
+ { GUINT_TO_POINTER (0x33B5), "/nvsquare" },
+ { GUINT_TO_POINTER (0x33BB), "/nwsquare" },
+ { GUINT_TO_POINTER (0x099E), "/nyabengali" },
+ { GUINT_TO_POINTER (0x091E), "/nyadeva" },
+ { GUINT_TO_POINTER (0x0A9E), "/nyagujarati" },
+ { GUINT_TO_POINTER (0x0A1E), "/nyagurmukhi" },
+ { GUINT_TO_POINTER (0x006F), "/o" },
+ { GUINT_TO_POINTER (0x00F3), "/oacute" },
+ { GUINT_TO_POINTER (0x0E2D), "/oangthai" },
+ { GUINT_TO_POINTER (0x0275), "/obarred" },
+ { GUINT_TO_POINTER (0x04E9), "/obarredcyrillic" },
+ { GUINT_TO_POINTER (0x04EB), "/obarreddieresiscyrillic" },
+ { GUINT_TO_POINTER (0x0993), "/obengali" },
+ { GUINT_TO_POINTER (0x311B), "/obopomofo" },
+ { GUINT_TO_POINTER (0x014F), "/obreve" },
+ { GUINT_TO_POINTER (0x0911), "/ocandradeva" },
+ { GUINT_TO_POINTER (0x0A91), "/ocandragujarati" },
+ { GUINT_TO_POINTER (0x0949), "/ocandravowelsigndeva" },
+ { GUINT_TO_POINTER (0x0AC9), "/ocandravowelsigngujarati" },
+ { GUINT_TO_POINTER (0x01D2), "/ocaron" },
+ { GUINT_TO_POINTER (0x24DE), "/ocircle" },
+ { GUINT_TO_POINTER (0x00F4), "/ocircumflex" },
+ { GUINT_TO_POINTER (0x1ED1), "/ocircumflexacute" },
+ { GUINT_TO_POINTER (0x1ED9), "/ocircumflexdotbelow" },
+ { GUINT_TO_POINTER (0x1ED3), "/ocircumflexgrave" },
+ { GUINT_TO_POINTER (0x1ED5), "/ocircumflexhookabove" },
+ { GUINT_TO_POINTER (0x1ED7), "/ocircumflextilde" },
+ { GUINT_TO_POINTER (0x043E), "/ocyrillic" },
+ { GUINT_TO_POINTER (0x0151), "/odblacute" },
+ { GUINT_TO_POINTER (0x020D), "/odblgrave" },
+ { GUINT_TO_POINTER (0x0913), "/odeva" },
+ { GUINT_TO_POINTER (0x00F6), "/odieresis" },
+ { GUINT_TO_POINTER (0x04E7), "/odieresiscyrillic" },
+ { GUINT_TO_POINTER (0x1ECD), "/odotbelow" },
+ { GUINT_TO_POINTER (0x0153), "/oe" },
+ { GUINT_TO_POINTER (0x315A), "/oekorean" },
+ { GUINT_TO_POINTER (0x02DB), "/ogonek" },
+ { GUINT_TO_POINTER (0x0328), "/ogonekcmb" },
+ { GUINT_TO_POINTER (0x00F2), "/ograve" },
+ { GUINT_TO_POINTER (0x0A93), "/ogujarati" },
+ { GUINT_TO_POINTER (0x0585), "/oharmenian" },
+ { GUINT_TO_POINTER (0x304A), "/ohiragana" },
+ { GUINT_TO_POINTER (0x1ECF), "/ohookabove" },
+ { GUINT_TO_POINTER (0x01A1), "/ohorn" },
+ { GUINT_TO_POINTER (0x1EDB), "/ohornacute" },
+ { GUINT_TO_POINTER (0x1EE3), "/ohorndotbelow" },
+ { GUINT_TO_POINTER (0x1EDD), "/ohorngrave" },
+ { GUINT_TO_POINTER (0x1EDF), "/ohornhookabove" },
+ { GUINT_TO_POINTER (0x1EE1), "/ohorntilde" },
+ { GUINT_TO_POINTER (0x0151), "/ohungarumlaut" },
+ { GUINT_TO_POINTER (0x01A3), "/oi" },
+ { GUINT_TO_POINTER (0x020F), "/oinvertedbreve" },
+ { GUINT_TO_POINTER (0x30AA), "/okatakana" },
+ { GUINT_TO_POINTER (0xFF75), "/okatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x3157), "/okorean" },
+ { GUINT_TO_POINTER (0x05AB), "/olehebrew" },
+ { GUINT_TO_POINTER (0x014D), "/omacron" },
+ { GUINT_TO_POINTER (0x1E53), "/omacronacute" },
+ { GUINT_TO_POINTER (0x1E51), "/omacrongrave" },
+ { GUINT_TO_POINTER (0x0950), "/omdeva" },
+ { GUINT_TO_POINTER (0x03C9), "/omega" },
+ { GUINT_TO_POINTER (0x03D6), "/omega1" },
+ { GUINT_TO_POINTER (0x0461), "/omegacyrillic" },
+ { GUINT_TO_POINTER (0x0277), "/omegalatinclosed" },
+ { GUINT_TO_POINTER (0x047B), "/omegaroundcyrillic" },
+ { GUINT_TO_POINTER (0x047D), "/omegatitlocyrillic" },
+ { GUINT_TO_POINTER (0x03CE), "/omegatonos" },
+ { GUINT_TO_POINTER (0x0AD0), "/omgujarati" },
+ { GUINT_TO_POINTER (0x03BF), "/omicron" },
+ { GUINT_TO_POINTER (0x03CC), "/omicrontonos" },
+ { GUINT_TO_POINTER (0xFF4F), "/omonospace" },
+ { GUINT_TO_POINTER (0x0031), "/one" },
+ { GUINT_TO_POINTER (0x0661), "/onearabic" },
+ { GUINT_TO_POINTER (0x09E7), "/onebengali" },
+ { GUINT_TO_POINTER (0x2460), "/onecircle" },
+ { GUINT_TO_POINTER (0x278A), "/onecircleinversesansserif" },
+ { GUINT_TO_POINTER (0x0967), "/onedeva" },
+ { GUINT_TO_POINTER (0x2024), "/onedotenleader" },
+ { GUINT_TO_POINTER (0x215B), "/oneeighth" },
+ { GUINT_TO_POINTER (0xF6DC), "/onefitted" },
+ { GUINT_TO_POINTER (0x0AE7), "/onegujarati" },
+ { GUINT_TO_POINTER (0x0A67), "/onegurmukhi" },
+ { GUINT_TO_POINTER (0x0661), "/onehackarabic" },
+ { GUINT_TO_POINTER (0x00BD), "/onehalf" },
+ { GUINT_TO_POINTER (0x3021), "/onehangzhou" },
+ { GUINT_TO_POINTER (0x3220), "/oneideographicparen" },
+ { GUINT_TO_POINTER (0x2081), "/oneinferior" },
+ { GUINT_TO_POINTER (0xFF11), "/onemonospace" },
+ { GUINT_TO_POINTER (0x09F4), "/onenumeratorbengali" },
+ { GUINT_TO_POINTER (0xF731), "/oneoldstyle" },
+ { GUINT_TO_POINTER (0x2474), "/oneparen" },
+ { GUINT_TO_POINTER (0x2488), "/oneperiod" },
+ { GUINT_TO_POINTER (0x06F1), "/onepersian" },
+ { GUINT_TO_POINTER (0x00BC), "/onequarter" },
+ { GUINT_TO_POINTER (0x2170), "/oneroman" },
+ { GUINT_TO_POINTER (0x00B9), "/onesuperior" },
+ { GUINT_TO_POINTER (0x0E51), "/onethai" },
+ { GUINT_TO_POINTER (0x2153), "/onethird" },
+ { GUINT_TO_POINTER (0x01EB), "/oogonek" },
+ { GUINT_TO_POINTER (0x01ED), "/oogonekmacron" },
+ { GUINT_TO_POINTER (0x0A13), "/oogurmukhi" },
+ { GUINT_TO_POINTER (0x0A4B), "/oomatragurmukhi" },
+ { GUINT_TO_POINTER (0x0254), "/oopen" },
+ { GUINT_TO_POINTER (0x24AA), "/oparen" },
+ { GUINT_TO_POINTER (0x25E6), "/openbullet" },
+ { GUINT_TO_POINTER (0x2325), "/option" },
+ { GUINT_TO_POINTER (0x00AA), "/ordfeminine" },
+ { GUINT_TO_POINTER (0x00BA), "/ordmasculine" },
+ { GUINT_TO_POINTER (0x221F), "/orthogonal" },
+ { GUINT_TO_POINTER (0x0912), "/oshortdeva" },
+ { GUINT_TO_POINTER (0x094A), "/oshortvowelsigndeva" },
+ { GUINT_TO_POINTER (0x00F8), "/oslash" },
+ { GUINT_TO_POINTER (0x01FF), "/oslashacute" },
+ { GUINT_TO_POINTER (0x3049), "/osmallhiragana" },
+ { GUINT_TO_POINTER (0x30A9), "/osmallkatakana" },
+ { GUINT_TO_POINTER (0xFF6B), "/osmallkatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x01FF), "/ostrokeacute" },
+ { GUINT_TO_POINTER (0xF6F0), "/osuperior" },
+ { GUINT_TO_POINTER (0x047F), "/otcyrillic" },
+ { GUINT_TO_POINTER (0x00F5), "/otilde" },
+ { GUINT_TO_POINTER (0x1E4D), "/otildeacute" },
+ { GUINT_TO_POINTER (0x1E4F), "/otildedieresis" },
+ { GUINT_TO_POINTER (0x3121), "/oubopomofo" },
+ { GUINT_TO_POINTER (0x203E), "/overline" },
+ { GUINT_TO_POINTER (0xFE4A), "/overlinecenterline" },
+ { GUINT_TO_POINTER (0x0305), "/overlinecmb" },
+ { GUINT_TO_POINTER (0xFE49), "/overlinedashed" },
+ { GUINT_TO_POINTER (0xFE4C), "/overlinedblwavy" },
+ { GUINT_TO_POINTER (0xFE4B), "/overlinewavy" },
+ { GUINT_TO_POINTER (0x00AF), "/overscore" },
+ { GUINT_TO_POINTER (0x09CB), "/ovowelsignbengali" },
+ { GUINT_TO_POINTER (0x094B), "/ovowelsigndeva" },
+ { GUINT_TO_POINTER (0x0ACB), "/ovowelsigngujarati" },
+ { GUINT_TO_POINTER (0x0070), "/p" },
+ { GUINT_TO_POINTER (0x3380), "/paampssquare" },
+ { GUINT_TO_POINTER (0x332B), "/paasentosquare" },
+ { GUINT_TO_POINTER (0x09AA), "/pabengali" },
+ { GUINT_TO_POINTER (0x1E55), "/pacute" },
+ { GUINT_TO_POINTER (0x092A), "/padeva" },
+ { GUINT_TO_POINTER (0x21DF), "/pagedown" },
+ { GUINT_TO_POINTER (0x21DE), "/pageup" },
+ { GUINT_TO_POINTER (0x0AAA), "/pagujarati" },
+ { GUINT_TO_POINTER (0x0A2A), "/pagurmukhi" },
+ { GUINT_TO_POINTER (0x3071), "/pahiragana" },
+ { GUINT_TO_POINTER (0x0E2F), "/paiyannoithai" },
+ { GUINT_TO_POINTER (0x30D1), "/pakatakana" },
+ { GUINT_TO_POINTER (0x0484), "/palatalizationcyrilliccmb" },
+ { GUINT_TO_POINTER (0x04C0), "/palochkacyrillic" },
+ { GUINT_TO_POINTER (0x317F), "/pansioskorean" },
+ { GUINT_TO_POINTER (0x00B6), "/paragraph" },
+ { GUINT_TO_POINTER (0x2225), "/parallel" },
+ { GUINT_TO_POINTER (0x0028), "/parenleft" },
+ { GUINT_TO_POINTER (0xFD3E), "/parenleftaltonearabic" },
+ { GUINT_TO_POINTER (0xF8ED), "/parenleftbt" },
+ { GUINT_TO_POINTER (0xF8EC), "/parenleftex" },
+ { GUINT_TO_POINTER (0x208D), "/parenleftinferior" },
+ { GUINT_TO_POINTER (0xFF08), "/parenleftmonospace" },
+ { GUINT_TO_POINTER (0xFE59), "/parenleftsmall" },
+ { GUINT_TO_POINTER (0x207D), "/parenleftsuperior" },
+ { GUINT_TO_POINTER (0xF8EB), "/parenlefttp" },
+ { GUINT_TO_POINTER (0xFE35), "/parenleftvertical" },
+ { GUINT_TO_POINTER (0x0029), "/parenright" },
+ { GUINT_TO_POINTER (0xFD3F), "/parenrightaltonearabic" },
+ { GUINT_TO_POINTER (0xF8F8), "/parenrightbt" },
+ { GUINT_TO_POINTER (0xF8F7), "/parenrightex" },
+ { GUINT_TO_POINTER (0x208E), "/parenrightinferior" },
+ { GUINT_TO_POINTER (0xFF09), "/parenrightmonospace" },
+ { GUINT_TO_POINTER (0xFE5A), "/parenrightsmall" },
+ { GUINT_TO_POINTER (0x207E), "/parenrightsuperior" },
+ { GUINT_TO_POINTER (0xF8F6), "/parenrighttp" },
+ { GUINT_TO_POINTER (0xFE36), "/parenrightvertical" },
+ { GUINT_TO_POINTER (0x2202), "/partialdiff" },
+ { GUINT_TO_POINTER (0x05C0), "/paseqhebrew" },
+ { GUINT_TO_POINTER (0x0599), "/pashtahebrew" },
+ { GUINT_TO_POINTER (0x33A9), "/pasquare" },
+ { GUINT_TO_POINTER (0x05B7), "/patah" },
+ { GUINT_TO_POINTER (0x05B7), "/patah11" },
+ { GUINT_TO_POINTER (0x05B7), "/patah1d" },
+ { GUINT_TO_POINTER (0x05B7), "/patah2a" },
+ { GUINT_TO_POINTER (0x05B7), "/patahhebrew" },
+ { GUINT_TO_POINTER (0x05B7), "/patahnarrowhebrew" },
+ { GUINT_TO_POINTER (0x05B7), "/patahquarterhebrew" },
+ { GUINT_TO_POINTER (0x05B7), "/patahwidehebrew" },
+ { GUINT_TO_POINTER (0x05A1), "/pazerhebrew" },
+ { GUINT_TO_POINTER (0x3106), "/pbopomofo" },
+ { GUINT_TO_POINTER (0x24DF), "/pcircle" },
+ { GUINT_TO_POINTER (0x1E57), "/pdotaccent" },
+ { GUINT_TO_POINTER (0x05E4), "/pe" },
+ { GUINT_TO_POINTER (0x043F), "/pecyrillic" },
+ { GUINT_TO_POINTER (0xFB44), "/pedagesh" },
+ { GUINT_TO_POINTER (0xFB44), "/pedageshhebrew" },
+ { GUINT_TO_POINTER (0x333B), "/peezisquare" },
+ { GUINT_TO_POINTER (0xFB43), "/pefinaldageshhebrew" },
+ { GUINT_TO_POINTER (0x067E), "/peharabic" },
+ { GUINT_TO_POINTER (0x057A), "/peharmenian" },
+ { GUINT_TO_POINTER (0x05E4), "/pehebrew" },
+ { GUINT_TO_POINTER (0xFB57), "/pehfinalarabic" },
+ { GUINT_TO_POINTER (0xFB58), "/pehinitialarabic" },
+ { GUINT_TO_POINTER (0x307A), "/pehiragana" },
+ { GUINT_TO_POINTER (0xFB59), "/pehmedialarabic" },
+ { GUINT_TO_POINTER (0x30DA), "/pekatakana" },
+ { GUINT_TO_POINTER (0x04A7), "/pemiddlehookcyrillic" },
+ { GUINT_TO_POINTER (0xFB4E), "/perafehebrew" },
+ { GUINT_TO_POINTER (0x0025), "/percent" },
+ { GUINT_TO_POINTER (0x066A), "/percentarabic" },
+ { GUINT_TO_POINTER (0xFF05), "/percentmonospace" },
+ { GUINT_TO_POINTER (0xFE6A), "/percentsmall" },
+ { GUINT_TO_POINTER (0x002E), "/period" },
+ { GUINT_TO_POINTER (0x0589), "/periodarmenian" },
+ { GUINT_TO_POINTER (0x00B7), "/periodcentered" },
+ { GUINT_TO_POINTER (0xFF61), "/periodhalfwidth" },
+ { GUINT_TO_POINTER (0xF6E7), "/periodinferior" },
+ { GUINT_TO_POINTER (0xFF0E), "/periodmonospace" },
+ { GUINT_TO_POINTER (0xFE52), "/periodsmall" },
+ { GUINT_TO_POINTER (0xF6E8), "/periodsuperior" },
+ { GUINT_TO_POINTER (0x0342), "/perispomenigreekcmb" },
+ { GUINT_TO_POINTER (0x22A5), "/perpendicular" },
+ { GUINT_TO_POINTER (0x2030), "/perthousand" },
+ { GUINT_TO_POINTER (0x20A7), "/peseta" },
+ { GUINT_TO_POINTER (0x338A), "/pfsquare" },
+ { GUINT_TO_POINTER (0x09AB), "/phabengali" },
+ { GUINT_TO_POINTER (0x092B), "/phadeva" },
+ { GUINT_TO_POINTER (0x0AAB), "/phagujarati" },
+ { GUINT_TO_POINTER (0x0A2B), "/phagurmukhi" },
+ { GUINT_TO_POINTER (0x03C6), "/phi" },
+ { GUINT_TO_POINTER (0x03D5), "/phi1" },
+ { GUINT_TO_POINTER (0x327A), "/phieuphacirclekorean" },
+ { GUINT_TO_POINTER (0x321A), "/phieuphaparenkorean" },
+ { GUINT_TO_POINTER (0x326C), "/phieuphcirclekorean" },
+ { GUINT_TO_POINTER (0x314D), "/phieuphkorean" },
+ { GUINT_TO_POINTER (0x320C), "/phieuphparenkorean" },
+ { GUINT_TO_POINTER (0x0278), "/philatin" },
+ { GUINT_TO_POINTER (0x0E3A), "/phinthuthai" },
+ { GUINT_TO_POINTER (0x03D5), "/phisymbolgreek" },
+ { GUINT_TO_POINTER (0x01A5), "/phook" },
+ { GUINT_TO_POINTER (0x0E1E), "/phophanthai" },
+ { GUINT_TO_POINTER (0x0E1C), "/phophungthai" },
+ { GUINT_TO_POINTER (0x0E20), "/phosamphaothai" },
+ { GUINT_TO_POINTER (0x03C0), "/pi" },
+ { GUINT_TO_POINTER (0x3273), "/pieupacirclekorean" },
+ { GUINT_TO_POINTER (0x3213), "/pieupaparenkorean" },
+ { GUINT_TO_POINTER (0x3176), "/pieupcieuckorean" },
+ { GUINT_TO_POINTER (0x3265), "/pieupcirclekorean" },
+ { GUINT_TO_POINTER (0x3172), "/pieupkiyeokkorean" },
+ { GUINT_TO_POINTER (0x3142), "/pieupkorean" },
+ { GUINT_TO_POINTER (0x3205), "/pieupparenkorean" },
+ { GUINT_TO_POINTER (0x3174), "/pieupsioskiyeokkorean" },
+ { GUINT_TO_POINTER (0x3144), "/pieupsioskorean" },
+ { GUINT_TO_POINTER (0x3175), "/pieupsiostikeutkorean" },
+ { GUINT_TO_POINTER (0x3177), "/pieupthieuthkorean" },
+ { GUINT_TO_POINTER (0x3173), "/pieuptikeutkorean" },
+ { GUINT_TO_POINTER (0x3074), "/pihiragana" },
+ { GUINT_TO_POINTER (0x30D4), "/pikatakana" },
+ { GUINT_TO_POINTER (0x03D6), "/pisymbolgreek" },
+ { GUINT_TO_POINTER (0x0583), "/piwrarmenian" },
+ { GUINT_TO_POINTER (0x002B), "/plus" },
+ { GUINT_TO_POINTER (0x031F), "/plusbelowcmb" },
+ { GUINT_TO_POINTER (0x2295), "/pluscircle" },
+ { GUINT_TO_POINTER (0x00B1), "/plusminus" },
+ { GUINT_TO_POINTER (0x02D6), "/plusmod" },
+ { GUINT_TO_POINTER (0xFF0B), "/plusmonospace" },
+ { GUINT_TO_POINTER (0xFE62), "/plussmall" },
+ { GUINT_TO_POINTER (0x207A), "/plussuperior" },
+ { GUINT_TO_POINTER (0xFF50), "/pmonospace" },
+ { GUINT_TO_POINTER (0x33D8), "/pmsquare" },
+ { GUINT_TO_POINTER (0x307D), "/pohiragana" },
+ { GUINT_TO_POINTER (0x261F), "/pointingindexdownwhite" },
+ { GUINT_TO_POINTER (0x261C), "/pointingindexleftwhite" },
+ { GUINT_TO_POINTER (0x261E), "/pointingindexrightwhite" },
+ { GUINT_TO_POINTER (0x261D), "/pointingindexupwhite" },
+ { GUINT_TO_POINTER (0x30DD), "/pokatakana" },
+ { GUINT_TO_POINTER (0x0E1B), "/poplathai" },
+ { GUINT_TO_POINTER (0x3012), "/postalmark" },
+ { GUINT_TO_POINTER (0x3020), "/postalmarkface" },
+ { GUINT_TO_POINTER (0x24AB), "/pparen" },
+ { GUINT_TO_POINTER (0x227A), "/precedes" },
+ { GUINT_TO_POINTER (0x211E), "/prescription" },
+ { GUINT_TO_POINTER (0x02B9), "/primemod" },
+ { GUINT_TO_POINTER (0x2035), "/primereversed" },
+ { GUINT_TO_POINTER (0x220F), "/product" },
+ { GUINT_TO_POINTER (0x2305), "/projective" },
+ { GUINT_TO_POINTER (0x30FC), "/prolongedkana" },
+ { GUINT_TO_POINTER (0x2318), "/propellor" },
+ { GUINT_TO_POINTER (0x2282), "/propersubset" },
+ { GUINT_TO_POINTER (0x2283), "/propersuperset" },
+ { GUINT_TO_POINTER (0x2237), "/proportion" },
+ { GUINT_TO_POINTER (0x221D), "/proportional" },
+ { GUINT_TO_POINTER (0x03C8), "/psi" },
+ { GUINT_TO_POINTER (0x0471), "/psicyrillic" },
+ { GUINT_TO_POINTER (0x0486), "/psilipneumatacyrilliccmb" },
+ { GUINT_TO_POINTER (0x33B0), "/pssquare" },
+ { GUINT_TO_POINTER (0x3077), "/puhiragana" },
+ { GUINT_TO_POINTER (0x30D7), "/pukatakana" },
+ { GUINT_TO_POINTER (0x33B4), "/pvsquare" },
+ { GUINT_TO_POINTER (0x33BA), "/pwsquare" },
+ { GUINT_TO_POINTER (0x0071), "/q" },
+ { GUINT_TO_POINTER (0x0958), "/qadeva" },
+ { GUINT_TO_POINTER (0x05A8), "/qadmahebrew" },
+ { GUINT_TO_POINTER (0x0642), "/qafarabic" },
+ { GUINT_TO_POINTER (0xFED6), "/qaffinalarabic" },
+ { GUINT_TO_POINTER (0xFED7), "/qafinitialarabic" },
+ { GUINT_TO_POINTER (0xFED8), "/qafmedialarabic" },
+ { GUINT_TO_POINTER (0x05B8), "/qamats" },
+ { GUINT_TO_POINTER (0x05B8), "/qamats10" },
+ { GUINT_TO_POINTER (0x05B8), "/qamats1a" },
+ { GUINT_TO_POINTER (0x05B8), "/qamats1c" },
+ { GUINT_TO_POINTER (0x05B8), "/qamats27" },
+ { GUINT_TO_POINTER (0x05B8), "/qamats29" },
+ { GUINT_TO_POINTER (0x05B8), "/qamats33" },
+ { GUINT_TO_POINTER (0x05B8), "/qamatsde" },
+ { GUINT_TO_POINTER (0x05B8), "/qamatshebrew" },
+ { GUINT_TO_POINTER (0x05B8), "/qamatsnarrowhebrew" },
+ { GUINT_TO_POINTER (0x05B8), "/qamatsqatanhebrew" },
+ { GUINT_TO_POINTER (0x05B8), "/qamatsqatannarrowhebrew" },
+ { GUINT_TO_POINTER (0x05B8), "/qamatsqatanquarterhebrew" },
+ { GUINT_TO_POINTER (0x05B8), "/qamatsqatanwidehebrew" },
+ { GUINT_TO_POINTER (0x05B8), "/qamatsquarterhebrew" },
+ { GUINT_TO_POINTER (0x05B8), "/qamatswidehebrew" },
+ { GUINT_TO_POINTER (0x059F), "/qarneyparahebrew" },
+ { GUINT_TO_POINTER (0x3111), "/qbopomofo" },
+ { GUINT_TO_POINTER (0x24E0), "/qcircle" },
+ { GUINT_TO_POINTER (0x02A0), "/qhook" },
+ { GUINT_TO_POINTER (0xFF51), "/qmonospace" },
+ { GUINT_TO_POINTER (0x05E7), "/qof" },
+ { GUINT_TO_POINTER (0xFB47), "/qofdagesh" },
+ { GUINT_TO_POINTER (0xFB47), "/qofdageshhebrew" },
+ { GUINT_TO_POINTER (0x05E7), "/qofhatafpatah" },
+ { GUINT_TO_POINTER (0x05B2), "/qofhatafpatah" },
+ { GUINT_TO_POINTER (0x05E7), "/qofhatafpatahhebrew" },
+ { GUINT_TO_POINTER (0x05B2), "/qofhatafpatahhebrew" },
+ { GUINT_TO_POINTER (0x05E7), "/qofhatafsegol" },
+ { GUINT_TO_POINTER (0x05B1), "/qofhatafsegol" },
+ { GUINT_TO_POINTER (0x05E7), "/qofhatafsegolhebrew" },
+ { GUINT_TO_POINTER (0x05B1), "/qofhatafsegolhebrew" },
+ { GUINT_TO_POINTER (0x05E7), "/qofhebrew" },
+ { GUINT_TO_POINTER (0x05E7), "/qofhiriq" },
+ { GUINT_TO_POINTER (0x05B4), "/qofhiriq" },
+ { GUINT_TO_POINTER (0x05E7), "/qofhiriqhebrew" },
+ { GUINT_TO_POINTER (0x05B4), "/qofhiriqhebrew" },
+ { GUINT_TO_POINTER (0x05E7), "/qofholam" },
+ { GUINT_TO_POINTER (0x05B9), "/qofholam" },
+ { GUINT_TO_POINTER (0x05E7), "/qofholamhebrew" },
+ { GUINT_TO_POINTER (0x05B9), "/qofholamhebrew" },
+ { GUINT_TO_POINTER (0x05E7), "/qofpatah" },
+ { GUINT_TO_POINTER (0x05B7), "/qofpatah" },
+ { GUINT_TO_POINTER (0x05E7), "/qofpatahhebrew" },
+ { GUINT_TO_POINTER (0x05B7), "/qofpatahhebrew" },
+ { GUINT_TO_POINTER (0x05E7), "/qofqamats" },
+ { GUINT_TO_POINTER (0x05B8), "/qofqamats" },
+ { GUINT_TO_POINTER (0x05E7), "/qofqamatshebrew" },
+ { GUINT_TO_POINTER (0x05B8), "/qofqamatshebrew" },
+ { GUINT_TO_POINTER (0x05E7), "/qofqubuts" },
+ { GUINT_TO_POINTER (0x05BB), "/qofqubuts" },
+ { GUINT_TO_POINTER (0x05E7), "/qofqubutshebrew" },
+ { GUINT_TO_POINTER (0x05BB), "/qofqubutshebrew" },
+ { GUINT_TO_POINTER (0x05E7), "/qofsegol" },
+ { GUINT_TO_POINTER (0x05B6), "/qofsegol" },
+ { GUINT_TO_POINTER (0x05E7), "/qofsegolhebrew" },
+ { GUINT_TO_POINTER (0x05B6), "/qofsegolhebrew" },
+ { GUINT_TO_POINTER (0x05E7), "/qofsheva" },
+ { GUINT_TO_POINTER (0x05B0), "/qofsheva" },
+ { GUINT_TO_POINTER (0x05E7), "/qofshevahebrew" },
+ { GUINT_TO_POINTER (0x05B0), "/qofshevahebrew" },
+ { GUINT_TO_POINTER (0x05E7), "/qoftsere" },
+ { GUINT_TO_POINTER (0x05B5), "/qoftsere" },
+ { GUINT_TO_POINTER (0x05E7), "/qoftserehebrew" },
+ { GUINT_TO_POINTER (0x05B5), "/qoftserehebrew" },
+ { GUINT_TO_POINTER (0x24AC), "/qparen" },
+ { GUINT_TO_POINTER (0x2669), "/quarternote" },
+ { GUINT_TO_POINTER (0x05BB), "/qubuts" },
+ { GUINT_TO_POINTER (0x05BB), "/qubuts18" },
+ { GUINT_TO_POINTER (0x05BB), "/qubuts25" },
+ { GUINT_TO_POINTER (0x05BB), "/qubuts31" },
+ { GUINT_TO_POINTER (0x05BB), "/qubutshebrew" },
+ { GUINT_TO_POINTER (0x05BB), "/qubutsnarrowhebrew" },
+ { GUINT_TO_POINTER (0x05BB), "/qubutsquarterhebrew" },
+ { GUINT_TO_POINTER (0x05BB), "/qubutswidehebrew" },
+ { GUINT_TO_POINTER (0x003F), "/question" },
+ { GUINT_TO_POINTER (0x061F), "/questionarabic" },
+ { GUINT_TO_POINTER (0x055E), "/questionarmenian" },
+ { GUINT_TO_POINTER (0x00BF), "/questiondown" },
+ { GUINT_TO_POINTER (0xF7BF), "/questiondownsmall" },
+ { GUINT_TO_POINTER (0x037E), "/questiongreek" },
+ { GUINT_TO_POINTER (0xFF1F), "/questionmonospace" },
+ { GUINT_TO_POINTER (0xF73F), "/questionsmall" },
+ { GUINT_TO_POINTER (0x0022), "/quotedbl" },
+ { GUINT_TO_POINTER (0x201E), "/quotedblbase" },
+ { GUINT_TO_POINTER (0x201C), "/quotedblleft" },
+ { GUINT_TO_POINTER (0xFF02), "/quotedblmonospace" },
+ { GUINT_TO_POINTER (0x301E), "/quotedblprime" },
+ { GUINT_TO_POINTER (0x301D), "/quotedblprimereversed" },
+ { GUINT_TO_POINTER (0x201D), "/quotedblright" },
+ { GUINT_TO_POINTER (0x2018), "/quoteleft" },
+ { GUINT_TO_POINTER (0x201B), "/quoteleftreversed" },
+ { GUINT_TO_POINTER (0x201B), "/quotereversed" },
+ { GUINT_TO_POINTER (0x2019), "/quoteright" },
+ { GUINT_TO_POINTER (0x0149), "/quoterightn" },
+ { GUINT_TO_POINTER (0x201A), "/quotesinglbase" },
+ { GUINT_TO_POINTER (0x0027), "/quotesingle" },
+ { GUINT_TO_POINTER (0xFF07), "/quotesinglemonospace" },
+ { GUINT_TO_POINTER (0x0072), "/r" },
+ { GUINT_TO_POINTER (0x057C), "/raarmenian" },
+ { GUINT_TO_POINTER (0x09B0), "/rabengali" },
+ { GUINT_TO_POINTER (0x0155), "/racute" },
+ { GUINT_TO_POINTER (0x0930), "/radeva" },
+ { GUINT_TO_POINTER (0x221A), "/radical" },
+ { GUINT_TO_POINTER (0xF8E5), "/radicalex" },
+ { GUINT_TO_POINTER (0x33AE), "/radoverssquare" },
+ { GUINT_TO_POINTER (0x33AF), "/radoverssquaredsquare" },
+ { GUINT_TO_POINTER (0x33AD), "/radsquare" },
+ { GUINT_TO_POINTER (0x05BF), "/rafe" },
+ { GUINT_TO_POINTER (0x05BF), "/rafehebrew" },
+ { GUINT_TO_POINTER (0x0AB0), "/ragujarati" },
+ { GUINT_TO_POINTER (0x0A30), "/ragurmukhi" },
+ { GUINT_TO_POINTER (0x3089), "/rahiragana" },
+ { GUINT_TO_POINTER (0x30E9), "/rakatakana" },
+ { GUINT_TO_POINTER (0xFF97), "/rakatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x09F1), "/ralowerdiagonalbengali" },
+ { GUINT_TO_POINTER (0x09F0), "/ramiddlediagonalbengali" },
+ { GUINT_TO_POINTER (0x0264), "/ramshorn" },
+ { GUINT_TO_POINTER (0x2236), "/ratio" },
+ { GUINT_TO_POINTER (0x3116), "/rbopomofo" },
+ { GUINT_TO_POINTER (0x0159), "/rcaron" },
+ { GUINT_TO_POINTER (0x0157), "/rcedilla" },
+ { GUINT_TO_POINTER (0x24E1), "/rcircle" },
+ { GUINT_TO_POINTER (0x0157), "/rcommaaccent" },
+ { GUINT_TO_POINTER (0x0211), "/rdblgrave" },
+ { GUINT_TO_POINTER (0x1E59), "/rdotaccent" },
+ { GUINT_TO_POINTER (0x1E5B), "/rdotbelow" },
+ { GUINT_TO_POINTER (0x1E5D), "/rdotbelowmacron" },
+ { GUINT_TO_POINTER (0x203B), "/referencemark" },
+ { GUINT_TO_POINTER (0x2286), "/reflexsubset" },
+ { GUINT_TO_POINTER (0x2287), "/reflexsuperset" },
+ { GUINT_TO_POINTER (0x00AE), "/registered" },
+ { GUINT_TO_POINTER (0xF8E8), "/registersans" },
+ { GUINT_TO_POINTER (0xF6DA), "/registerserif" },
+ { GUINT_TO_POINTER (0x0631), "/reharabic" },
+ { GUINT_TO_POINTER (0x0580), "/reharmenian" },
+ { GUINT_TO_POINTER (0xFEAE), "/rehfinalarabic" },
+ { GUINT_TO_POINTER (0x308C), "/rehiragana" },
+ { GUINT_TO_POINTER (0x0631), "/rehyehaleflamarabic" },
+ { GUINT_TO_POINTER (0xFEF3), "/rehyehaleflamarabic" },
+ { GUINT_TO_POINTER (0xFE8E), "/rehyehaleflamarabic" },
+ { GUINT_TO_POINTER (0x0644), "/rehyehaleflamarabic" },
+ { GUINT_TO_POINTER (0x30EC), "/rekatakana" },
+ { GUINT_TO_POINTER (0xFF9A), "/rekatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x05E8), "/resh" },
+ { GUINT_TO_POINTER (0xFB48), "/reshdageshhebrew" },
+ { GUINT_TO_POINTER (0x05E8), "/reshhatafpatah" },
+ { GUINT_TO_POINTER (0x05B2), "/reshhatafpatah" },
+ { GUINT_TO_POINTER (0x05E8), "/reshhatafpatahhebrew" },
+ { GUINT_TO_POINTER (0x05B2), "/reshhatafpatahhebrew" },
+ { GUINT_TO_POINTER (0x05E8), "/reshhatafsegol" },
+ { GUINT_TO_POINTER (0x05B1), "/reshhatafsegol" },
+ { GUINT_TO_POINTER (0x05E8), "/reshhatafsegolhebrew" },
+ { GUINT_TO_POINTER (0x05B1), "/reshhatafsegolhebrew" },
+ { GUINT_TO_POINTER (0x05E8), "/reshhebrew" },
+ { GUINT_TO_POINTER (0x05E8), "/reshhiriq" },
+ { GUINT_TO_POINTER (0x05B4), "/reshhiriq" },
+ { GUINT_TO_POINTER (0x05E8), "/reshhiriqhebrew" },
+ { GUINT_TO_POINTER (0x05B4), "/reshhiriqhebrew" },
+ { GUINT_TO_POINTER (0x05E8), "/reshholam" },
+ { GUINT_TO_POINTER (0x05B9), "/reshholam" },
+ { GUINT_TO_POINTER (0x05E8), "/reshholamhebrew" },
+ { GUINT_TO_POINTER (0x05B9), "/reshholamhebrew" },
+ { GUINT_TO_POINTER (0x05E8), "/reshpatah" },
+ { GUINT_TO_POINTER (0x05B7), "/reshpatah" },
+ { GUINT_TO_POINTER (0x05E8), "/reshpatahhebrew" },
+ { GUINT_TO_POINTER (0x05B7), "/reshpatahhebrew" },
+ { GUINT_TO_POINTER (0x05E8), "/reshqamats" },
+ { GUINT_TO_POINTER (0x05B8), "/reshqamats" },
+ { GUINT_TO_POINTER (0x05E8), "/reshqamatshebrew" },
+ { GUINT_TO_POINTER (0x05B8), "/reshqamatshebrew" },
+ { GUINT_TO_POINTER (0x05E8), "/reshqubuts" },
+ { GUINT_TO_POINTER (0x05BB), "/reshqubuts" },
+ { GUINT_TO_POINTER (0x05E8), "/reshqubutshebrew" },
+ { GUINT_TO_POINTER (0x05BB), "/reshqubutshebrew" },
+ { GUINT_TO_POINTER (0x05E8), "/reshsegol" },
+ { GUINT_TO_POINTER (0x05B6), "/reshsegol" },
+ { GUINT_TO_POINTER (0x05E8), "/reshsegolhebrew" },
+ { GUINT_TO_POINTER (0x05B6), "/reshsegolhebrew" },
+ { GUINT_TO_POINTER (0x05E8), "/reshsheva" },
+ { GUINT_TO_POINTER (0x05B0), "/reshsheva" },
+ { GUINT_TO_POINTER (0x05E8), "/reshshevahebrew" },
+ { GUINT_TO_POINTER (0x05B0), "/reshshevahebrew" },
+ { GUINT_TO_POINTER (0x05E8), "/reshtsere" },
+ { GUINT_TO_POINTER (0x05B5), "/reshtsere" },
+ { GUINT_TO_POINTER (0x05E8), "/reshtserehebrew" },
+ { GUINT_TO_POINTER (0x05B5), "/reshtserehebrew" },
+ { GUINT_TO_POINTER (0x223D), "/reversedtilde" },
+ { GUINT_TO_POINTER (0x0597), "/reviahebrew" },
+ { GUINT_TO_POINTER (0x0597), "/reviamugrashhebrew" },
+ { GUINT_TO_POINTER (0x2310), "/revlogicalnot" },
+ { GUINT_TO_POINTER (0x027E), "/rfishhook" },
+ { GUINT_TO_POINTER (0x027F), "/rfishhookreversed" },
+ { GUINT_TO_POINTER (0x09DD), "/rhabengali" },
+ { GUINT_TO_POINTER (0x095D), "/rhadeva" },
+ { GUINT_TO_POINTER (0x03C1), "/rho" },
+ { GUINT_TO_POINTER (0x027D), "/rhook" },
+ { GUINT_TO_POINTER (0x027B), "/rhookturned" },
+ { GUINT_TO_POINTER (0x02B5), "/rhookturnedsuperior" },
+ { GUINT_TO_POINTER (0x03F1), "/rhosymbolgreek" },
+ { GUINT_TO_POINTER (0x02DE), "/rhotichookmod" },
+ { GUINT_TO_POINTER (0x3271), "/rieulacirclekorean" },
+ { GUINT_TO_POINTER (0x3211), "/rieulaparenkorean" },
+ { GUINT_TO_POINTER (0x3263), "/rieulcirclekorean" },
+ { GUINT_TO_POINTER (0x3140), "/rieulhieuhkorean" },
+ { GUINT_TO_POINTER (0x313A), "/rieulkiyeokkorean" },
+ { GUINT_TO_POINTER (0x3169), "/rieulkiyeoksioskorean" },
+ { GUINT_TO_POINTER (0x3139), "/rieulkorean" },
+ { GUINT_TO_POINTER (0x313B), "/rieulmieumkorean" },
+ { GUINT_TO_POINTER (0x316C), "/rieulpansioskorean" },
+ { GUINT_TO_POINTER (0x3203), "/rieulparenkorean" },
+ { GUINT_TO_POINTER (0x313F), "/rieulphieuphkorean" },
+ { GUINT_TO_POINTER (0x313C), "/rieulpieupkorean" },
+ { GUINT_TO_POINTER (0x316B), "/rieulpieupsioskorean" },
+ { GUINT_TO_POINTER (0x313D), "/rieulsioskorean" },
+ { GUINT_TO_POINTER (0x313E), "/rieulthieuthkorean" },
+ { GUINT_TO_POINTER (0x316A), "/rieultikeutkorean" },
+ { GUINT_TO_POINTER (0x316D), "/rieulyeorinhieuhkorean" },
+ { GUINT_TO_POINTER (0x221F), "/rightangle" },
+ { GUINT_TO_POINTER (0x0319), "/righttackbelowcmb" },
+ { GUINT_TO_POINTER (0x22BF), "/righttriangle" },
+ { GUINT_TO_POINTER (0x308A), "/rihiragana" },
+ { GUINT_TO_POINTER (0x30EA), "/rikatakana" },
+ { GUINT_TO_POINTER (0xFF98), "/rikatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x02DA), "/ring" },
+ { GUINT_TO_POINTER (0x0325), "/ringbelowcmb" },
+ { GUINT_TO_POINTER (0x030A), "/ringcmb" },
+ { GUINT_TO_POINTER (0x02BF), "/ringhalfleft" },
+ { GUINT_TO_POINTER (0x0559), "/ringhalfleftarmenian" },
+ { GUINT_TO_POINTER (0x031C), "/ringhalfleftbelowcmb" },
+ { GUINT_TO_POINTER (0x02D3), "/ringhalfleftcentered" },
+ { GUINT_TO_POINTER (0x02BE), "/ringhalfright" },
+ { GUINT_TO_POINTER (0x0339), "/ringhalfrightbelowcmb" },
+ { GUINT_TO_POINTER (0x02D2), "/ringhalfrightcentered" },
+ { GUINT_TO_POINTER (0x0213), "/rinvertedbreve" },
+ { GUINT_TO_POINTER (0x3351), "/rittorusquare" },
+ { GUINT_TO_POINTER (0x1E5F), "/rlinebelow" },
+ { GUINT_TO_POINTER (0x027C), "/rlongleg" },
+ { GUINT_TO_POINTER (0x027A), "/rlonglegturned" },
+ { GUINT_TO_POINTER (0xFF52), "/rmonospace" },
+ { GUINT_TO_POINTER (0x308D), "/rohiragana" },
+ { GUINT_TO_POINTER (0x30ED), "/rokatakana" },
+ { GUINT_TO_POINTER (0xFF9B), "/rokatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x0E23), "/roruathai" },
+ { GUINT_TO_POINTER (0x24AD), "/rparen" },
+ { GUINT_TO_POINTER (0x09DC), "/rrabengali" },
+ { GUINT_TO_POINTER (0x0931), "/rradeva" },
+ { GUINT_TO_POINTER (0x0A5C), "/rragurmukhi" },
+ { GUINT_TO_POINTER (0x0691), "/rreharabic" },
+ { GUINT_TO_POINTER (0xFB8D), "/rrehfinalarabic" },
+ { GUINT_TO_POINTER (0x09E0), "/rrvocalicbengali" },
+ { GUINT_TO_POINTER (0x0960), "/rrvocalicdeva" },
+ { GUINT_TO_POINTER (0x0AE0), "/rrvocalicgujarati" },
+ { GUINT_TO_POINTER (0x09C4), "/rrvocalicvowelsignbengali" },
+ { GUINT_TO_POINTER (0x0944), "/rrvocalicvowelsigndeva" },
+ { GUINT_TO_POINTER (0x0AC4), "/rrvocalicvowelsigngujarati" },
+ { GUINT_TO_POINTER (0xF6F1), "/rsuperior" },
+ { GUINT_TO_POINTER (0x2590), "/rtblock" },
+ { GUINT_TO_POINTER (0x0279), "/rturned" },
+ { GUINT_TO_POINTER (0x02B4), "/rturnedsuperior" },
+ { GUINT_TO_POINTER (0x308B), "/ruhiragana" },
+ { GUINT_TO_POINTER (0x30EB), "/rukatakana" },
+ { GUINT_TO_POINTER (0xFF99), "/rukatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x09F2), "/rupeemarkbengali" },
+ { GUINT_TO_POINTER (0x09F3), "/rupeesignbengali" },
+ { GUINT_TO_POINTER (0xF6DD), "/rupiah" },
+ { GUINT_TO_POINTER (0x0E24), "/ruthai" },
+ { GUINT_TO_POINTER (0x098B), "/rvocalicbengali" },
+ { GUINT_TO_POINTER (0x090B), "/rvocalicdeva" },
+ { GUINT_TO_POINTER (0x0A8B), "/rvocalicgujarati" },
+ { GUINT_TO_POINTER (0x09C3), "/rvocalicvowelsignbengali" },
+ { GUINT_TO_POINTER (0x0943), "/rvocalicvowelsigndeva" },
+ { GUINT_TO_POINTER (0x0AC3), "/rvocalicvowelsigngujarati" },
+ { GUINT_TO_POINTER (0x0073), "/s" },
+ { GUINT_TO_POINTER (0x09B8), "/sabengali" },
+ { GUINT_TO_POINTER (0x015B), "/sacute" },
+ { GUINT_TO_POINTER (0x1E65), "/sacutedotaccent" },
+ { GUINT_TO_POINTER (0x0635), "/sadarabic" },
+ { GUINT_TO_POINTER (0x0938), "/sadeva" },
+ { GUINT_TO_POINTER (0xFEBA), "/sadfinalarabic" },
+ { GUINT_TO_POINTER (0xFEBB), "/sadinitialarabic" },
+ { GUINT_TO_POINTER (0xFEBC), "/sadmedialarabic" },
+ { GUINT_TO_POINTER (0x0AB8), "/sagujarati" },
+ { GUINT_TO_POINTER (0x0A38), "/sagurmukhi" },
+ { GUINT_TO_POINTER (0x3055), "/sahiragana" },
+ { GUINT_TO_POINTER (0x30B5), "/sakatakana" },
+ { GUINT_TO_POINTER (0xFF7B), "/sakatakanahalfwidth" },
+ { GUINT_TO_POINTER (0xFDFA), "/sallallahoualayhewasallamarabic" },
+ { GUINT_TO_POINTER (0x05E1), "/samekh" },
+ { GUINT_TO_POINTER (0xFB41), "/samekhdagesh" },
+ { GUINT_TO_POINTER (0xFB41), "/samekhdageshhebrew" },
+ { GUINT_TO_POINTER (0x05E1), "/samekhhebrew" },
+ { GUINT_TO_POINTER (0x0E32), "/saraaathai" },
+ { GUINT_TO_POINTER (0x0E41), "/saraaethai" },
+ { GUINT_TO_POINTER (0x0E44), "/saraaimaimalaithai" },
+ { GUINT_TO_POINTER (0x0E43), "/saraaimaimuanthai" },
+ { GUINT_TO_POINTER (0x0E33), "/saraamthai" },
+ { GUINT_TO_POINTER (0x0E30), "/saraathai" },
+ { GUINT_TO_POINTER (0x0E40), "/saraethai" },
+ { GUINT_TO_POINTER (0xF886), "/saraiileftthai" },
+ { GUINT_TO_POINTER (0x0E35), "/saraiithai" },
+ { GUINT_TO_POINTER (0xF885), "/saraileftthai" },
+ { GUINT_TO_POINTER (0x0E34), "/saraithai" },
+ { GUINT_TO_POINTER (0x0E42), "/saraothai" },
+ { GUINT_TO_POINTER (0xF888), "/saraueeleftthai" },
+ { GUINT_TO_POINTER (0x0E37), "/saraueethai" },
+ { GUINT_TO_POINTER (0xF887), "/saraueleftthai" },
+ { GUINT_TO_POINTER (0x0E36), "/sarauethai" },
+ { GUINT_TO_POINTER (0x0E38), "/sarauthai" },
+ { GUINT_TO_POINTER (0x0E39), "/sarauuthai" },
+ { GUINT_TO_POINTER (0x3119), "/sbopomofo" },
+ { GUINT_TO_POINTER (0x0161), "/scaron" },
+ { GUINT_TO_POINTER (0x1E67), "/scarondotaccent" },
+ { GUINT_TO_POINTER (0x015F), "/scedilla" },
+ { GUINT_TO_POINTER (0x0259), "/schwa" },
+ { GUINT_TO_POINTER (0x04D9), "/schwacyrillic" },
+ { GUINT_TO_POINTER (0x04DB), "/schwadieresiscyrillic" },
+ { GUINT_TO_POINTER (0x025A), "/schwahook" },
+ { GUINT_TO_POINTER (0x24E2), "/scircle" },
+ { GUINT_TO_POINTER (0x015D), "/scircumflex" },
+ { GUINT_TO_POINTER (0x0219), "/scommaaccent" },
+ { GUINT_TO_POINTER (0x1E61), "/sdotaccent" },
+ { GUINT_TO_POINTER (0x1E63), "/sdotbelow" },
+ { GUINT_TO_POINTER (0x1E69), "/sdotbelowdotaccent" },
+ { GUINT_TO_POINTER (0x033C), "/seagullbelowcmb" },
+ { GUINT_TO_POINTER (0x2033), "/second" },
+ { GUINT_TO_POINTER (0x02CA), "/secondtonechinese" },
+ { GUINT_TO_POINTER (0x00A7), "/section" },
+ { GUINT_TO_POINTER (0x0633), "/seenarabic" },
+ { GUINT_TO_POINTER (0xFEB2), "/seenfinalarabic" },
+ { GUINT_TO_POINTER (0xFEB3), "/seeninitialarabic" },
+ { GUINT_TO_POINTER (0xFEB4), "/seenmedialarabic" },
+ { GUINT_TO_POINTER (0x05B6), "/segol" },
+ { GUINT_TO_POINTER (0x05B6), "/segol13" },
+ { GUINT_TO_POINTER (0x05B6), "/segol1f" },
+ { GUINT_TO_POINTER (0x05B6), "/segol2c" },
+ { GUINT_TO_POINTER (0x05B6), "/segolhebrew" },
+ { GUINT_TO_POINTER (0x05B6), "/segolnarrowhebrew" },
+ { GUINT_TO_POINTER (0x05B6), "/segolquarterhebrew" },
+ { GUINT_TO_POINTER (0x0592), "/segoltahebrew" },
+ { GUINT_TO_POINTER (0x05B6), "/segolwidehebrew" },
+ { GUINT_TO_POINTER (0x057D), "/seharmenian" },
+ { GUINT_TO_POINTER (0x305B), "/sehiragana" },
+ { GUINT_TO_POINTER (0x30BB), "/sekatakana" },
+ { GUINT_TO_POINTER (0xFF7E), "/sekatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x003B), "/semicolon" },
+ { GUINT_TO_POINTER (0x061B), "/semicolonarabic" },
+ { GUINT_TO_POINTER (0xFF1B), "/semicolonmonospace" },
+ { GUINT_TO_POINTER (0xFE54), "/semicolonsmall" },
+ { GUINT_TO_POINTER (0x309C), "/semivoicedmarkkana" },
+ { GUINT_TO_POINTER (0xFF9F), "/semivoicedmarkkanahalfwidth" },
+ { GUINT_TO_POINTER (0x3322), "/sentisquare" },
+ { GUINT_TO_POINTER (0x3323), "/sentosquare" },
+ { GUINT_TO_POINTER (0x0037), "/seven" },
+ { GUINT_TO_POINTER (0x0667), "/sevenarabic" },
+ { GUINT_TO_POINTER (0x09ED), "/sevenbengali" },
+ { GUINT_TO_POINTER (0x2466), "/sevencircle" },
+ { GUINT_TO_POINTER (0x2790), "/sevencircleinversesansserif" },
+ { GUINT_TO_POINTER (0x096D), "/sevendeva" },
+ { GUINT_TO_POINTER (0x215E), "/seveneighths" },
+ { GUINT_TO_POINTER (0x0AED), "/sevengujarati" },
+ { GUINT_TO_POINTER (0x0A6D), "/sevengurmukhi" },
+ { GUINT_TO_POINTER (0x0667), "/sevenhackarabic" },
+ { GUINT_TO_POINTER (0x3027), "/sevenhangzhou" },
+ { GUINT_TO_POINTER (0x3226), "/sevenideographicparen" },
+ { GUINT_TO_POINTER (0x2087), "/seveninferior" },
+ { GUINT_TO_POINTER (0xFF17), "/sevenmonospace" },
+ { GUINT_TO_POINTER (0xF737), "/sevenoldstyle" },
+ { GUINT_TO_POINTER (0x247A), "/sevenparen" },
+ { GUINT_TO_POINTER (0x248E), "/sevenperiod" },
+ { GUINT_TO_POINTER (0x06F7), "/sevenpersian" },
+ { GUINT_TO_POINTER (0x2176), "/sevenroman" },
+ { GUINT_TO_POINTER (0x2077), "/sevensuperior" },
+ { GUINT_TO_POINTER (0x2470), "/seventeencircle" },
+ { GUINT_TO_POINTER (0x2484), "/seventeenparen" },
+ { GUINT_TO_POINTER (0x2498), "/seventeenperiod" },
+ { GUINT_TO_POINTER (0x0E57), "/seventhai" },
+ { GUINT_TO_POINTER (0x00AD), "/sfthyphen" },
+ { GUINT_TO_POINTER (0x0577), "/shaarmenian" },
+ { GUINT_TO_POINTER (0x09B6), "/shabengali" },
+ { GUINT_TO_POINTER (0x0448), "/shacyrillic" },
+ { GUINT_TO_POINTER (0x0651), "/shaddaarabic" },
+ { GUINT_TO_POINTER (0xFC61), "/shaddadammaarabic" },
+ { GUINT_TO_POINTER (0xFC5E), "/shaddadammatanarabic" },
+ { GUINT_TO_POINTER (0xFC60), "/shaddafathaarabic" },
+ { GUINT_TO_POINTER (0x0651), "/shaddafathatanarabic" },
+ { GUINT_TO_POINTER (0x064B), "/shaddafathatanarabic" },
+ { GUINT_TO_POINTER (0xFC62), "/shaddakasraarabic" },
+ { GUINT_TO_POINTER (0xFC5F), "/shaddakasratanarabic" },
+ { GUINT_TO_POINTER (0x2592), "/shade" },
+ { GUINT_TO_POINTER (0x2593), "/shadedark" },
+ { GUINT_TO_POINTER (0x2591), "/shadelight" },
+ { GUINT_TO_POINTER (0x2592), "/shademedium" },
+ { GUINT_TO_POINTER (0x0936), "/shadeva" },
+ { GUINT_TO_POINTER (0x0AB6), "/shagujarati" },
+ { GUINT_TO_POINTER (0x0A36), "/shagurmukhi" },
+ { GUINT_TO_POINTER (0x0593), "/shalshelethebrew" },
+ { GUINT_TO_POINTER (0x3115), "/shbopomofo" },
+ { GUINT_TO_POINTER (0x0449), "/shchacyrillic" },
+ { GUINT_TO_POINTER (0x0634), "/sheenarabic" },
+ { GUINT_TO_POINTER (0xFEB6), "/sheenfinalarabic" },
+ { GUINT_TO_POINTER (0xFEB7), "/sheeninitialarabic" },
+ { GUINT_TO_POINTER (0xFEB8), "/sheenmedialarabic" },
+ { GUINT_TO_POINTER (0x03E3), "/sheicoptic" },
+ { GUINT_TO_POINTER (0x20AA), "/sheqel" },
+ { GUINT_TO_POINTER (0x20AA), "/sheqelhebrew" },
+ { GUINT_TO_POINTER (0x05B0), "/sheva" },
+ { GUINT_TO_POINTER (0x05B0), "/sheva115" },
+ { GUINT_TO_POINTER (0x05B0), "/sheva15" },
+ { GUINT_TO_POINTER (0x05B0), "/sheva22" },
+ { GUINT_TO_POINTER (0x05B0), "/sheva2e" },
+ { GUINT_TO_POINTER (0x05B0), "/shevahebrew" },
+ { GUINT_TO_POINTER (0x05B0), "/shevanarrowhebrew" },
+ { GUINT_TO_POINTER (0x05B0), "/shevaquarterhebrew" },
+ { GUINT_TO_POINTER (0x05B0), "/shevawidehebrew" },
+ { GUINT_TO_POINTER (0x04BB), "/shhacyrillic" },
+ { GUINT_TO_POINTER (0x03ED), "/shimacoptic" },
+ { GUINT_TO_POINTER (0x05E9), "/shin" },
+ { GUINT_TO_POINTER (0xFB49), "/shindagesh" },
+ { GUINT_TO_POINTER (0xFB49), "/shindageshhebrew" },
+ { GUINT_TO_POINTER (0xFB2C), "/shindageshshindot" },
+ { GUINT_TO_POINTER (0xFB2C), "/shindageshshindothebrew" },
+ { GUINT_TO_POINTER (0xFB2D), "/shindageshsindot" },
+ { GUINT_TO_POINTER (0xFB2D), "/shindageshsindothebrew" },
+ { GUINT_TO_POINTER (0x05C1), "/shindothebrew" },
+ { GUINT_TO_POINTER (0x05E9), "/shinhebrew" },
+ { GUINT_TO_POINTER (0xFB2A), "/shinshindot" },
+ { GUINT_TO_POINTER (0xFB2A), "/shinshindothebrew" },
+ { GUINT_TO_POINTER (0xFB2B), "/shinsindot" },
+ { GUINT_TO_POINTER (0xFB2B), "/shinsindothebrew" },
+ { GUINT_TO_POINTER (0x0282), "/shook" },
+ { GUINT_TO_POINTER (0x03C3), "/sigma" },
+ { GUINT_TO_POINTER (0x03C2), "/sigma1" },
+ { GUINT_TO_POINTER (0x03C2), "/sigmafinal" },
+ { GUINT_TO_POINTER (0x03F2), "/sigmalunatesymbolgreek" },
+ { GUINT_TO_POINTER (0x3057), "/sihiragana" },
+ { GUINT_TO_POINTER (0x30B7), "/sikatakana" },
+ { GUINT_TO_POINTER (0xFF7C), "/sikatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x05BD), "/siluqhebrew" },
+ { GUINT_TO_POINTER (0x05BD), "/siluqlefthebrew" },
+ { GUINT_TO_POINTER (0x223C), "/similar" },
+ { GUINT_TO_POINTER (0x05C2), "/sindothebrew" },
+ { GUINT_TO_POINTER (0x3274), "/siosacirclekorean" },
+ { GUINT_TO_POINTER (0x3214), "/siosaparenkorean" },
+ { GUINT_TO_POINTER (0x317E), "/sioscieuckorean" },
+ { GUINT_TO_POINTER (0x3266), "/sioscirclekorean" },
+ { GUINT_TO_POINTER (0x317A), "/sioskiyeokkorean" },
+ { GUINT_TO_POINTER (0x3145), "/sioskorean" },
+ { GUINT_TO_POINTER (0x317B), "/siosnieunkorean" },
+ { GUINT_TO_POINTER (0x3206), "/siosparenkorean" },
+ { GUINT_TO_POINTER (0x317D), "/siospieupkorean" },
+ { GUINT_TO_POINTER (0x317C), "/siostikeutkorean" },
+ { GUINT_TO_POINTER (0x0036), "/six" },
+ { GUINT_TO_POINTER (0x0666), "/sixarabic" },
+ { GUINT_TO_POINTER (0x09EC), "/sixbengali" },
+ { GUINT_TO_POINTER (0x2465), "/sixcircle" },
+ { GUINT_TO_POINTER (0x278F), "/sixcircleinversesansserif" },
+ { GUINT_TO_POINTER (0x096C), "/sixdeva" },
+ { GUINT_TO_POINTER (0x0AEC), "/sixgujarati" },
+ { GUINT_TO_POINTER (0x0A6C), "/sixgurmukhi" },
+ { GUINT_TO_POINTER (0x0666), "/sixhackarabic" },
+ { GUINT_TO_POINTER (0x3026), "/sixhangzhou" },
+ { GUINT_TO_POINTER (0x3225), "/sixideographicparen" },
+ { GUINT_TO_POINTER (0x2086), "/sixinferior" },
+ { GUINT_TO_POINTER (0xFF16), "/sixmonospace" },
+ { GUINT_TO_POINTER (0xF736), "/sixoldstyle" },
+ { GUINT_TO_POINTER (0x2479), "/sixparen" },
+ { GUINT_TO_POINTER (0x248D), "/sixperiod" },
+ { GUINT_TO_POINTER (0x06F6), "/sixpersian" },
+ { GUINT_TO_POINTER (0x2175), "/sixroman" },
+ { GUINT_TO_POINTER (0x2076), "/sixsuperior" },
+ { GUINT_TO_POINTER (0x246F), "/sixteencircle" },
+ { GUINT_TO_POINTER (0x09F9), "/sixteencurrencydenominatorbengali" },
+ { GUINT_TO_POINTER (0x2483), "/sixteenparen" },
+ { GUINT_TO_POINTER (0x2497), "/sixteenperiod" },
+ { GUINT_TO_POINTER (0x0E56), "/sixthai" },
+ { GUINT_TO_POINTER (0x002F), "/slash" },
+ { GUINT_TO_POINTER (0xFF0F), "/slashmonospace" },
+ { GUINT_TO_POINTER (0x017F), "/slong" },
+ { GUINT_TO_POINTER (0x1E9B), "/slongdotaccent" },
+ { GUINT_TO_POINTER (0x263A), "/smileface" },
+ { GUINT_TO_POINTER (0xFF53), "/smonospace" },
+ { GUINT_TO_POINTER (0x05C3), "/sofpasuqhebrew" },
+ { GUINT_TO_POINTER (0x00AD), "/softhyphen" },
+ { GUINT_TO_POINTER (0x044C), "/softsigncyrillic" },
+ { GUINT_TO_POINTER (0x305D), "/sohiragana" },
+ { GUINT_TO_POINTER (0x30BD), "/sokatakana" },
+ { GUINT_TO_POINTER (0xFF7F), "/sokatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x0338), "/soliduslongoverlaycmb" },
+ { GUINT_TO_POINTER (0x0337), "/solidusshortoverlaycmb" },
+ { GUINT_TO_POINTER (0x0E29), "/sorusithai" },
+ { GUINT_TO_POINTER (0x0E28), "/sosalathai" },
+ { GUINT_TO_POINTER (0x0E0B), "/sosothai" },
+ { GUINT_TO_POINTER (0x0E2A), "/sosuathai" },
+ { GUINT_TO_POINTER (0x0020), "/space" },
+ { GUINT_TO_POINTER (0x2660), "/spade" },
+ { GUINT_TO_POINTER (0x2660), "/spadesuitblack" },
+ { GUINT_TO_POINTER (0x2664), "/spadesuitwhite" },
+ { GUINT_TO_POINTER (0x24AE), "/sparen" },
+ { GUINT_TO_POINTER (0x033B), "/squarebelowcmb" },
+ { GUINT_TO_POINTER (0x33C4), "/squarecc" },
+ { GUINT_TO_POINTER (0x339D), "/squarecm" },
+ { GUINT_TO_POINTER (0x25A9), "/squarediagonalcrosshatchfill" },
+ { GUINT_TO_POINTER (0x25A4), "/squarehorizontalfill" },
+ { GUINT_TO_POINTER (0x338F), "/squarekg" },
+ { GUINT_TO_POINTER (0x339E), "/squarekm" },
+ { GUINT_TO_POINTER (0x33CE), "/squarekmcapital" },
+ { GUINT_TO_POINTER (0x33D1), "/squareln" },
+ { GUINT_TO_POINTER (0x33D2), "/squarelog" },
+ { GUINT_TO_POINTER (0x338E), "/squaremg" },
+ { GUINT_TO_POINTER (0x33D5), "/squaremil" },
+ { GUINT_TO_POINTER (0x339C), "/squaremm" },
+ { GUINT_TO_POINTER (0x33A1), "/squaremsquared" },
+ { GUINT_TO_POINTER (0x25A6), "/squareorthogonalcrosshatchfill" },
+ { GUINT_TO_POINTER (0x25A7), "/squareupperlefttolowerrightfill" },
+ { GUINT_TO_POINTER (0x25A8), "/squareupperrighttolowerleftfill" },
+ { GUINT_TO_POINTER (0x25A5), "/squareverticalfill" },
+ { GUINT_TO_POINTER (0x25A3), "/squarewhitewithsmallblack" },
+ { GUINT_TO_POINTER (0x33DB), "/srsquare" },
+ { GUINT_TO_POINTER (0x09B7), "/ssabengali" },
+ { GUINT_TO_POINTER (0x0937), "/ssadeva" },
+ { GUINT_TO_POINTER (0x0AB7), "/ssagujarati" },
+ { GUINT_TO_POINTER (0x3149), "/ssangcieuckorean" },
+ { GUINT_TO_POINTER (0x3185), "/ssanghieuhkorean" },
+ { GUINT_TO_POINTER (0x3180), "/ssangieungkorean" },
+ { GUINT_TO_POINTER (0x3132), "/ssangkiyeokkorean" },
+ { GUINT_TO_POINTER (0x3165), "/ssangnieunkorean" },
+ { GUINT_TO_POINTER (0x3143), "/ssangpieupkorean" },
+ { GUINT_TO_POINTER (0x3146), "/ssangsioskorean" },
+ { GUINT_TO_POINTER (0x3138), "/ssangtikeutkorean" },
+ { GUINT_TO_POINTER (0xF6F2), "/ssuperior" },
+ { GUINT_TO_POINTER (0x00A3), "/sterling" },
+ { GUINT_TO_POINTER (0xFFE1), "/sterlingmonospace" },
+ { GUINT_TO_POINTER (0x0336), "/strokelongoverlaycmb" },
+ { GUINT_TO_POINTER (0x0335), "/strokeshortoverlaycmb" },
+ { GUINT_TO_POINTER (0x2282), "/subset" },
+ { GUINT_TO_POINTER (0x228A), "/subsetnotequal" },
+ { GUINT_TO_POINTER (0x2286), "/subsetorequal" },
+ { GUINT_TO_POINTER (0x227B), "/succeeds" },
+ { GUINT_TO_POINTER (0x220B), "/suchthat" },
+ { GUINT_TO_POINTER (0x3059), "/suhiragana" },
+ { GUINT_TO_POINTER (0x30B9), "/sukatakana" },
+ { GUINT_TO_POINTER (0xFF7D), "/sukatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x0652), "/sukunarabic" },
+ { GUINT_TO_POINTER (0x2211), "/summation" },
+ { GUINT_TO_POINTER (0x263C), "/sun" },
+ { GUINT_TO_POINTER (0x2283), "/superset" },
+ { GUINT_TO_POINTER (0x228B), "/supersetnotequal" },
+ { GUINT_TO_POINTER (0x2287), "/supersetorequal" },
+ { GUINT_TO_POINTER (0x33DC), "/svsquare" },
+ { GUINT_TO_POINTER (0x337C), "/syouwaerasquare" },
+ { GUINT_TO_POINTER (0x0074), "/t" },
+ { GUINT_TO_POINTER (0x09A4), "/tabengali" },
+ { GUINT_TO_POINTER (0x22A4), "/tackdown" },
+ { GUINT_TO_POINTER (0x22A3), "/tackleft" },
+ { GUINT_TO_POINTER (0x0924), "/tadeva" },
+ { GUINT_TO_POINTER (0x0AA4), "/tagujarati" },
+ { GUINT_TO_POINTER (0x0A24), "/tagurmukhi" },
+ { GUINT_TO_POINTER (0x0637), "/taharabic" },
+ { GUINT_TO_POINTER (0xFEC2), "/tahfinalarabic" },
+ { GUINT_TO_POINTER (0xFEC3), "/tahinitialarabic" },
+ { GUINT_TO_POINTER (0x305F), "/tahiragana" },
+ { GUINT_TO_POINTER (0xFEC4), "/tahmedialarabic" },
+ { GUINT_TO_POINTER (0x337D), "/taisyouerasquare" },
+ { GUINT_TO_POINTER (0x30BF), "/takatakana" },
+ { GUINT_TO_POINTER (0xFF80), "/takatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x0640), "/tatweelarabic" },
+ { GUINT_TO_POINTER (0x03C4), "/tau" },
+ { GUINT_TO_POINTER (0x05EA), "/tav" },
+ { GUINT_TO_POINTER (0xFB4A), "/tavdages" },
+ { GUINT_TO_POINTER (0xFB4A), "/tavdagesh" },
+ { GUINT_TO_POINTER (0xFB4A), "/tavdageshhebrew" },
+ { GUINT_TO_POINTER (0x05EA), "/tavhebrew" },
+ { GUINT_TO_POINTER (0x0167), "/tbar" },
+ { GUINT_TO_POINTER (0x310A), "/tbopomofo" },
+ { GUINT_TO_POINTER (0x0165), "/tcaron" },
+ { GUINT_TO_POINTER (0x02A8), "/tccurl" },
+ { GUINT_TO_POINTER (0x0163), "/tcedilla" },
+ { GUINT_TO_POINTER (0x0686), "/tcheharabic" },
+ { GUINT_TO_POINTER (0xFB7B), "/tchehfinalarabic" },
+ { GUINT_TO_POINTER (0xFB7C), "/tchehinitialarabic" },
+ { GUINT_TO_POINTER (0xFB7D), "/tchehmedialarabic" },
+ { GUINT_TO_POINTER (0xFB7C), "/tchehmeeminitialarabic" },
+ { GUINT_TO_POINTER (0xFEE4), "/tchehmeeminitialarabic" },
+ { GUINT_TO_POINTER (0x24E3), "/tcircle" },
+ { GUINT_TO_POINTER (0x1E71), "/tcircumflexbelow" },
+ { GUINT_TO_POINTER (0x0163), "/tcommaaccent" },
+ { GUINT_TO_POINTER (0x1E97), "/tdieresis" },
+ { GUINT_TO_POINTER (0x1E6B), "/tdotaccent" },
+ { GUINT_TO_POINTER (0x1E6D), "/tdotbelow" },
+ { GUINT_TO_POINTER (0x0442), "/tecyrillic" },
+ { GUINT_TO_POINTER (0x04AD), "/tedescendercyrillic" },
+ { GUINT_TO_POINTER (0x062A), "/teharabic" },
+ { GUINT_TO_POINTER (0xFE96), "/tehfinalarabic" },
+ { GUINT_TO_POINTER (0xFCA2), "/tehhahinitialarabic" },
+ { GUINT_TO_POINTER (0xFC0C), "/tehhahisolatedarabic" },
+ { GUINT_TO_POINTER (0xFE97), "/tehinitialarabic" },
+ { GUINT_TO_POINTER (0x3066), "/tehiragana" },
+ { GUINT_TO_POINTER (0xFCA1), "/tehjeeminitialarabic" },
+ { GUINT_TO_POINTER (0xFC0B), "/tehjeemisolatedarabic" },
+ { GUINT_TO_POINTER (0x0629), "/tehmarbutaarabic" },
+ { GUINT_TO_POINTER (0xFE94), "/tehmarbutafinalarabic" },
+ { GUINT_TO_POINTER (0xFE98), "/tehmedialarabic" },
+ { GUINT_TO_POINTER (0xFCA4), "/tehmeeminitialarabic" },
+ { GUINT_TO_POINTER (0xFC0E), "/tehmeemisolatedarabic" },
+ { GUINT_TO_POINTER (0xFC73), "/tehnoonfinalarabic" },
+ { GUINT_TO_POINTER (0x30C6), "/tekatakana" },
+ { GUINT_TO_POINTER (0xFF83), "/tekatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x2121), "/telephone" },
+ { GUINT_TO_POINTER (0x260E), "/telephoneblack" },
+ { GUINT_TO_POINTER (0x05A0), "/telishagedolahebrew" },
+ { GUINT_TO_POINTER (0x05A9), "/telishaqetanahebrew" },
+ { GUINT_TO_POINTER (0x2469), "/tencircle" },
+ { GUINT_TO_POINTER (0x3229), "/tenideographicparen" },
+ { GUINT_TO_POINTER (0x247D), "/tenparen" },
+ { GUINT_TO_POINTER (0x2491), "/tenperiod" },
+ { GUINT_TO_POINTER (0x2179), "/tenroman" },
+ { GUINT_TO_POINTER (0x02A7), "/tesh" },
+ { GUINT_TO_POINTER (0x05D8), "/tet" },
+ { GUINT_TO_POINTER (0xFB38), "/tetdagesh" },
+ { GUINT_TO_POINTER (0xFB38), "/tetdageshhebrew" },
+ { GUINT_TO_POINTER (0x05D8), "/tethebrew" },
+ { GUINT_TO_POINTER (0x04B5), "/tetsecyrillic" },
+ { GUINT_TO_POINTER (0x059B), "/tevirhebrew" },
+ { GUINT_TO_POINTER (0x059B), "/tevirlefthebrew" },
+ { GUINT_TO_POINTER (0x09A5), "/thabengali" },
+ { GUINT_TO_POINTER (0x0925), "/thadeva" },
+ { GUINT_TO_POINTER (0x0AA5), "/thagujarati" },
+ { GUINT_TO_POINTER (0x0A25), "/thagurmukhi" },
+ { GUINT_TO_POINTER (0x0630), "/thalarabic" },
+ { GUINT_TO_POINTER (0xFEAC), "/thalfinalarabic" },
+ { GUINT_TO_POINTER (0xF898), "/thanthakhatlowleftthai" },
+ { GUINT_TO_POINTER (0xF897), "/thanthakhatlowrightthai" },
+ { GUINT_TO_POINTER (0x0E4C), "/thanthakhatthai" },
+ { GUINT_TO_POINTER (0xF896), "/thanthakhatupperleftthai" },
+ { GUINT_TO_POINTER (0x062B), "/theharabic" },
+ { GUINT_TO_POINTER (0xFE9A), "/thehfinalarabic" },
+ { GUINT_TO_POINTER (0xFE9B), "/thehinitialarabic" },
+ { GUINT_TO_POINTER (0xFE9C), "/thehmedialarabic" },
+ { GUINT_TO_POINTER (0x2203), "/thereexists" },
+ { GUINT_TO_POINTER (0x2234), "/therefore" },
+ { GUINT_TO_POINTER (0x03B8), "/theta" },
+ { GUINT_TO_POINTER (0x03D1), "/theta1" },
+ { GUINT_TO_POINTER (0x03D1), "/thetasymbolgreek" },
+ { GUINT_TO_POINTER (0x3279), "/thieuthacirclekorean" },
+ { GUINT_TO_POINTER (0x3219), "/thieuthaparenkorean" },
+ { GUINT_TO_POINTER (0x326B), "/thieuthcirclekorean" },
+ { GUINT_TO_POINTER (0x314C), "/thieuthkorean" },
+ { GUINT_TO_POINTER (0x320B), "/thieuthparenkorean" },
+ { GUINT_TO_POINTER (0x246C), "/thirteencircle" },
+ { GUINT_TO_POINTER (0x2480), "/thirteenparen" },
+ { GUINT_TO_POINTER (0x2494), "/thirteenperiod" },
+ { GUINT_TO_POINTER (0x0E11), "/thonangmonthothai" },
+ { GUINT_TO_POINTER (0x01AD), "/thook" },
+ { GUINT_TO_POINTER (0x0E12), "/thophuthaothai" },
+ { GUINT_TO_POINTER (0x00FE), "/thorn" },
+ { GUINT_TO_POINTER (0x0E17), "/thothahanthai" },
+ { GUINT_TO_POINTER (0x0E10), "/thothanthai" },
+ { GUINT_TO_POINTER (0x0E18), "/thothongthai" },
+ { GUINT_TO_POINTER (0x0E16), "/thothungthai" },
+ { GUINT_TO_POINTER (0x0482), "/thousandcyrillic" },
+ { GUINT_TO_POINTER (0x066C), "/thousandsseparatorarabic" },
+ { GUINT_TO_POINTER (0x066C), "/thousandsseparatorpersian" },
+ { GUINT_TO_POINTER (0x0033), "/three" },
+ { GUINT_TO_POINTER (0x0663), "/threearabic" },
+ { GUINT_TO_POINTER (0x09E9), "/threebengali" },
+ { GUINT_TO_POINTER (0x2462), "/threecircle" },
+ { GUINT_TO_POINTER (0x278C), "/threecircleinversesansserif" },
+ { GUINT_TO_POINTER (0x0969), "/threedeva" },
+ { GUINT_TO_POINTER (0x215C), "/threeeighths" },
+ { GUINT_TO_POINTER (0x0AE9), "/threegujarati" },
+ { GUINT_TO_POINTER (0x0A69), "/threegurmukhi" },
+ { GUINT_TO_POINTER (0x0663), "/threehackarabic" },
+ { GUINT_TO_POINTER (0x3023), "/threehangzhou" },
+ { GUINT_TO_POINTER (0x3222), "/threeideographicparen" },
+ { GUINT_TO_POINTER (0x2083), "/threeinferior" },
+ { GUINT_TO_POINTER (0xFF13), "/threemonospace" },
+ { GUINT_TO_POINTER (0x09F6), "/threenumeratorbengali" },
+ { GUINT_TO_POINTER (0xF733), "/threeoldstyle" },
+ { GUINT_TO_POINTER (0x2476), "/threeparen" },
+ { GUINT_TO_POINTER (0x248A), "/threeperiod" },
+ { GUINT_TO_POINTER (0x06F3), "/threepersian" },
+ { GUINT_TO_POINTER (0x00BE), "/threequarters" },
+ { GUINT_TO_POINTER (0xF6DE), "/threequartersemdash" },
+ { GUINT_TO_POINTER (0x2172), "/threeroman" },
+ { GUINT_TO_POINTER (0x00B3), "/threesuperior" },
+ { GUINT_TO_POINTER (0x0E53), "/threethai" },
+ { GUINT_TO_POINTER (0x3394), "/thzsquare" },
+ { GUINT_TO_POINTER (0x3061), "/tihiragana" },
+ { GUINT_TO_POINTER (0x30C1), "/tikatakana" },
+ { GUINT_TO_POINTER (0xFF81), "/tikatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x3270), "/tikeutacirclekorean" },
+ { GUINT_TO_POINTER (0x3210), "/tikeutaparenkorean" },
+ { GUINT_TO_POINTER (0x3262), "/tikeutcirclekorean" },
+ { GUINT_TO_POINTER (0x3137), "/tikeutkorean" },
+ { GUINT_TO_POINTER (0x3202), "/tikeutparenkorean" },
+ { GUINT_TO_POINTER (0x02DC), "/tilde" },
+ { GUINT_TO_POINTER (0x0330), "/tildebelowcmb" },
+ { GUINT_TO_POINTER (0x0303), "/tildecmb" },
+ { GUINT_TO_POINTER (0x0303), "/tildecomb" },
+ { GUINT_TO_POINTER (0x0360), "/tildedoublecmb" },
+ { GUINT_TO_POINTER (0x223C), "/tildeoperator" },
+ { GUINT_TO_POINTER (0x0334), "/tildeoverlaycmb" },
+ { GUINT_TO_POINTER (0x033E), "/tildeverticalcmb" },
+ { GUINT_TO_POINTER (0x2297), "/timescircle" },
+ { GUINT_TO_POINTER (0x0596), "/tipehahebrew" },
+ { GUINT_TO_POINTER (0x0596), "/tipehalefthebrew" },
+ { GUINT_TO_POINTER (0x0A70), "/tippigurmukhi" },
+ { GUINT_TO_POINTER (0x0483), "/titlocyrilliccmb" },
+ { GUINT_TO_POINTER (0x057F), "/tiwnarmenian" },
+ { GUINT_TO_POINTER (0x1E6F), "/tlinebelow" },
+ { GUINT_TO_POINTER (0xFF54), "/tmonospace" },
+ { GUINT_TO_POINTER (0x0569), "/toarmenian" },
+ { GUINT_TO_POINTER (0x3068), "/tohiragana" },
+ { GUINT_TO_POINTER (0x30C8), "/tokatakana" },
+ { GUINT_TO_POINTER (0xFF84), "/tokatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x02E5), "/tonebarextrahighmod" },
+ { GUINT_TO_POINTER (0x02E9), "/tonebarextralowmod" },
+ { GUINT_TO_POINTER (0x02E6), "/tonebarhighmod" },
+ { GUINT_TO_POINTER (0x02E8), "/tonebarlowmod" },
+ { GUINT_TO_POINTER (0x02E7), "/tonebarmidmod" },
+ { GUINT_TO_POINTER (0x01BD), "/tonefive" },
+ { GUINT_TO_POINTER (0x0185), "/tonesix" },
+ { GUINT_TO_POINTER (0x01A8), "/tonetwo" },
+ { GUINT_TO_POINTER (0x0384), "/tonos" },
+ { GUINT_TO_POINTER (0x3327), "/tonsquare" },
+ { GUINT_TO_POINTER (0x0E0F), "/topatakthai" },
+ { GUINT_TO_POINTER (0x3014), "/tortoiseshellbracketleft" },
+ { GUINT_TO_POINTER (0xFE5D), "/tortoiseshellbracketleftsmall" },
+ { GUINT_TO_POINTER (0xFE39), "/tortoiseshellbracketleftvertical" },
+ { GUINT_TO_POINTER (0x3015), "/tortoiseshellbracketright" },
+ { GUINT_TO_POINTER (0xFE5E), "/tortoiseshellbracketrightsmall" },
+ { GUINT_TO_POINTER (0xFE3A), "/tortoiseshellbracketrightvertical" },
+ { GUINT_TO_POINTER (0x0E15), "/totaothai" },
+ { GUINT_TO_POINTER (0x01AB), "/tpalatalhook" },
+ { GUINT_TO_POINTER (0x24AF), "/tparen" },
+ { GUINT_TO_POINTER (0x2122), "/trademark" },
+ { GUINT_TO_POINTER (0xF8EA), "/trademarksans" },
+ { GUINT_TO_POINTER (0xF6DB), "/trademarkserif" },
+ { GUINT_TO_POINTER (0x0288), "/tretroflexhook" },
+ { GUINT_TO_POINTER (0x25BC), "/triagdn" },
+ { GUINT_TO_POINTER (0x25C4), "/triaglf" },
+ { GUINT_TO_POINTER (0x25BA), "/triagrt" },
+ { GUINT_TO_POINTER (0x25B2), "/triagup" },
+ { GUINT_TO_POINTER (0x02A6), "/ts" },
+ { GUINT_TO_POINTER (0x05E6), "/tsadi" },
+ { GUINT_TO_POINTER (0xFB46), "/tsadidagesh" },
+ { GUINT_TO_POINTER (0xFB46), "/tsadidageshhebrew" },
+ { GUINT_TO_POINTER (0x05E6), "/tsadihebrew" },
+ { GUINT_TO_POINTER (0x0446), "/tsecyrillic" },
+ { GUINT_TO_POINTER (0x05B5), "/tsere" },
+ { GUINT_TO_POINTER (0x05B5), "/tsere12" },
+ { GUINT_TO_POINTER (0x05B5), "/tsere1e" },
+ { GUINT_TO_POINTER (0x05B5), "/tsere2b" },
+ { GUINT_TO_POINTER (0x05B5), "/tserehebrew" },
+ { GUINT_TO_POINTER (0x05B5), "/tserenarrowhebrew" },
+ { GUINT_TO_POINTER (0x05B5), "/tserequarterhebrew" },
+ { GUINT_TO_POINTER (0x05B5), "/tserewidehebrew" },
+ { GUINT_TO_POINTER (0x045B), "/tshecyrillic" },
+ { GUINT_TO_POINTER (0xF6F3), "/tsuperior" },
+ { GUINT_TO_POINTER (0x099F), "/ttabengali" },
+ { GUINT_TO_POINTER (0x091F), "/ttadeva" },
+ { GUINT_TO_POINTER (0x0A9F), "/ttagujarati" },
+ { GUINT_TO_POINTER (0x0A1F), "/ttagurmukhi" },
+ { GUINT_TO_POINTER (0x0679), "/tteharabic" },
+ { GUINT_TO_POINTER (0xFB67), "/ttehfinalarabic" },
+ { GUINT_TO_POINTER (0xFB68), "/ttehinitialarabic" },
+ { GUINT_TO_POINTER (0xFB69), "/ttehmedialarabic" },
+ { GUINT_TO_POINTER (0x09A0), "/tthabengali" },
+ { GUINT_TO_POINTER (0x0920), "/tthadeva" },
+ { GUINT_TO_POINTER (0x0AA0), "/tthagujarati" },
+ { GUINT_TO_POINTER (0x0A20), "/tthagurmukhi" },
+ { GUINT_TO_POINTER (0x0287), "/tturned" },
+ { GUINT_TO_POINTER (0x3064), "/tuhiragana" },
+ { GUINT_TO_POINTER (0x30C4), "/tukatakana" },
+ { GUINT_TO_POINTER (0xFF82), "/tukatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x3063), "/tusmallhiragana" },
+ { GUINT_TO_POINTER (0x30C3), "/tusmallkatakana" },
+ { GUINT_TO_POINTER (0xFF6F), "/tusmallkatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x246B), "/twelvecircle" },
+ { GUINT_TO_POINTER (0x247F), "/twelveparen" },
+ { GUINT_TO_POINTER (0x2493), "/twelveperiod" },
+ { GUINT_TO_POINTER (0x217B), "/twelveroman" },
+ { GUINT_TO_POINTER (0x2473), "/twentycircle" },
+ { GUINT_TO_POINTER (0x5344), "/twentyhangzhou" },
+ { GUINT_TO_POINTER (0x2487), "/twentyparen" },
+ { GUINT_TO_POINTER (0x249B), "/twentyperiod" },
+ { GUINT_TO_POINTER (0x0032), "/two" },
+ { GUINT_TO_POINTER (0x0662), "/twoarabic" },
+ { GUINT_TO_POINTER (0x09E8), "/twobengali" },
+ { GUINT_TO_POINTER (0x2461), "/twocircle" },
+ { GUINT_TO_POINTER (0x278B), "/twocircleinversesansserif" },
+ { GUINT_TO_POINTER (0x0968), "/twodeva" },
+ { GUINT_TO_POINTER (0x2025), "/twodotenleader" },
+ { GUINT_TO_POINTER (0x2025), "/twodotleader" },
+ { GUINT_TO_POINTER (0xFE30), "/twodotleadervertical" },
+ { GUINT_TO_POINTER (0x0AE8), "/twogujarati" },
+ { GUINT_TO_POINTER (0x0A68), "/twogurmukhi" },
+ { GUINT_TO_POINTER (0x0662), "/twohackarabic" },
+ { GUINT_TO_POINTER (0x3022), "/twohangzhou" },
+ { GUINT_TO_POINTER (0x3221), "/twoideographicparen" },
+ { GUINT_TO_POINTER (0x2082), "/twoinferior" },
+ { GUINT_TO_POINTER (0xFF12), "/twomonospace" },
+ { GUINT_TO_POINTER (0x09F5), "/twonumeratorbengali" },
+ { GUINT_TO_POINTER (0xF732), "/twooldstyle" },
+ { GUINT_TO_POINTER (0x2475), "/twoparen" },
+ { GUINT_TO_POINTER (0x2489), "/twoperiod" },
+ { GUINT_TO_POINTER (0x06F2), "/twopersian" },
+ { GUINT_TO_POINTER (0x2171), "/tworoman" },
+ { GUINT_TO_POINTER (0x01BB), "/twostroke" },
+ { GUINT_TO_POINTER (0x00B2), "/twosuperior" },
+ { GUINT_TO_POINTER (0x0E52), "/twothai" },
+ { GUINT_TO_POINTER (0x2154), "/twothirds" },
+ { GUINT_TO_POINTER (0x0075), "/u" },
+ { GUINT_TO_POINTER (0x00FA), "/uacute" },
+ { GUINT_TO_POINTER (0x0289), "/ubar" },
+ { GUINT_TO_POINTER (0x0989), "/ubengali" },
+ { GUINT_TO_POINTER (0x3128), "/ubopomofo" },
+ { GUINT_TO_POINTER (0x016D), "/ubreve" },
+ { GUINT_TO_POINTER (0x01D4), "/ucaron" },
+ { GUINT_TO_POINTER (0x24E4), "/ucircle" },
+ { GUINT_TO_POINTER (0x00FB), "/ucircumflex" },
+ { GUINT_TO_POINTER (0x1E77), "/ucircumflexbelow" },
+ { GUINT_TO_POINTER (0x0443), "/ucyrillic" },
+ { GUINT_TO_POINTER (0x0951), "/udattadeva" },
+ { GUINT_TO_POINTER (0x0171), "/udblacute" },
+ { GUINT_TO_POINTER (0x0215), "/udblgrave" },
+ { GUINT_TO_POINTER (0x0909), "/udeva" },
+ { GUINT_TO_POINTER (0x00FC), "/udieresis" },
+ { GUINT_TO_POINTER (0x01D8), "/udieresisacute" },
+ { GUINT_TO_POINTER (0x1E73), "/udieresisbelow" },
+ { GUINT_TO_POINTER (0x01DA), "/udieresiscaron" },
+ { GUINT_TO_POINTER (0x04F1), "/udieresiscyrillic" },
+ { GUINT_TO_POINTER (0x01DC), "/udieresisgrave" },
+ { GUINT_TO_POINTER (0x01D6), "/udieresismacron" },
+ { GUINT_TO_POINTER (0x1EE5), "/udotbelow" },
+ { GUINT_TO_POINTER (0x00F9), "/ugrave" },
+ { GUINT_TO_POINTER (0x0A89), "/ugujarati" },
+ { GUINT_TO_POINTER (0x0A09), "/ugurmukhi" },
+ { GUINT_TO_POINTER (0x3046), "/uhiragana" },
+ { GUINT_TO_POINTER (0x1EE7), "/uhookabove" },
+ { GUINT_TO_POINTER (0x01B0), "/uhorn" },
+ { GUINT_TO_POINTER (0x1EE9), "/uhornacute" },
+ { GUINT_TO_POINTER (0x1EF1), "/uhorndotbelow" },
+ { GUINT_TO_POINTER (0x1EEB), "/uhorngrave" },
+ { GUINT_TO_POINTER (0x1EED), "/uhornhookabove" },
+ { GUINT_TO_POINTER (0x1EEF), "/uhorntilde" },
+ { GUINT_TO_POINTER (0x0171), "/uhungarumlaut" },
+ { GUINT_TO_POINTER (0x04F3), "/uhungarumlautcyrillic" },
+ { GUINT_TO_POINTER (0x0217), "/uinvertedbreve" },
+ { GUINT_TO_POINTER (0x30A6), "/ukatakana" },
+ { GUINT_TO_POINTER (0xFF73), "/ukatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x0479), "/ukcyrillic" },
+ { GUINT_TO_POINTER (0x315C), "/ukorean" },
+ { GUINT_TO_POINTER (0x016B), "/umacron" },
+ { GUINT_TO_POINTER (0x04EF), "/umacroncyrillic" },
+ { GUINT_TO_POINTER (0x1E7B), "/umacrondieresis" },
+ { GUINT_TO_POINTER (0x0A41), "/umatragurmukhi" },
+ { GUINT_TO_POINTER (0xFF55), "/umonospace" },
+ { GUINT_TO_POINTER (0x005F), "/underscore" },
+ { GUINT_TO_POINTER (0x2017), "/underscoredbl" },
+ { GUINT_TO_POINTER (0xFF3F), "/underscoremonospace" },
+ { GUINT_TO_POINTER (0xFE33), "/underscorevertical" },
+ { GUINT_TO_POINTER (0xFE4F), "/underscorewavy" },
+ { GUINT_TO_POINTER (0x222A), "/union" },
+ { GUINT_TO_POINTER (0x2200), "/universal" },
+ { GUINT_TO_POINTER (0x0173), "/uogonek" },
+ { GUINT_TO_POINTER (0x24B0), "/uparen" },
+ { GUINT_TO_POINTER (0x2580), "/upblock" },
+ { GUINT_TO_POINTER (0x05C4), "/upperdothebrew" },
+ { GUINT_TO_POINTER (0x03C5), "/upsilon" },
+ { GUINT_TO_POINTER (0x03CB), "/upsilondieresis" },
+ { GUINT_TO_POINTER (0x03B0), "/upsilondieresistonos" },
+ { GUINT_TO_POINTER (0x028A), "/upsilonlatin" },
+ { GUINT_TO_POINTER (0x03CD), "/upsilontonos" },
+ { GUINT_TO_POINTER (0x031D), "/uptackbelowcmb" },
+ { GUINT_TO_POINTER (0x02D4), "/uptackmod" },
+ { GUINT_TO_POINTER (0x0A73), "/uragurmukhi" },
+ { GUINT_TO_POINTER (0x016F), "/uring" },
+ { GUINT_TO_POINTER (0x045E), "/ushortcyrillic" },
+ { GUINT_TO_POINTER (0x3045), "/usmallhiragana" },
+ { GUINT_TO_POINTER (0x30A5), "/usmallkatakana" },
+ { GUINT_TO_POINTER (0xFF69), "/usmallkatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x04AF), "/ustraightcyrillic" },
+ { GUINT_TO_POINTER (0x04B1), "/ustraightstrokecyrillic" },
+ { GUINT_TO_POINTER (0x0169), "/utilde" },
+ { GUINT_TO_POINTER (0x1E79), "/utildeacute" },
+ { GUINT_TO_POINTER (0x1E75), "/utildebelow" },
+ { GUINT_TO_POINTER (0x098A), "/uubengali" },
+ { GUINT_TO_POINTER (0x090A), "/uudeva" },
+ { GUINT_TO_POINTER (0x0A8A), "/uugujarati" },
+ { GUINT_TO_POINTER (0x0A0A), "/uugurmukhi" },
+ { GUINT_TO_POINTER (0x0A42), "/uumatragurmukhi" },
+ { GUINT_TO_POINTER (0x09C2), "/uuvowelsignbengali" },
+ { GUINT_TO_POINTER (0x0942), "/uuvowelsigndeva" },
+ { GUINT_TO_POINTER (0x0AC2), "/uuvowelsigngujarati" },
+ { GUINT_TO_POINTER (0x09C1), "/uvowelsignbengali" },
+ { GUINT_TO_POINTER (0x0941), "/uvowelsigndeva" },
+ { GUINT_TO_POINTER (0x0AC1), "/uvowelsigngujarati" },
+ { GUINT_TO_POINTER (0x0076), "/v" },
+ { GUINT_TO_POINTER (0x0935), "/vadeva" },
+ { GUINT_TO_POINTER (0x0AB5), "/vagujarati" },
+ { GUINT_TO_POINTER (0x0A35), "/vagurmukhi" },
+ { GUINT_TO_POINTER (0x30F7), "/vakatakana" },
+ { GUINT_TO_POINTER (0x05D5), "/vav" },
+ { GUINT_TO_POINTER (0xFB35), "/vavdagesh" },
+ { GUINT_TO_POINTER (0xFB35), "/vavdagesh65" },
+ { GUINT_TO_POINTER (0xFB35), "/vavdageshhebrew" },
+ { GUINT_TO_POINTER (0x05D5), "/vavhebrew" },
+ { GUINT_TO_POINTER (0xFB4B), "/vavholam" },
+ { GUINT_TO_POINTER (0xFB4B), "/vavholamhebrew" },
+ { GUINT_TO_POINTER (0x05F0), "/vavvavhebrew" },
+ { GUINT_TO_POINTER (0x05F1), "/vavyodhebrew" },
+ { GUINT_TO_POINTER (0x24E5), "/vcircle" },
+ { GUINT_TO_POINTER (0x1E7F), "/vdotbelow" },
+ { GUINT_TO_POINTER (0x0432), "/vecyrillic" },
+ { GUINT_TO_POINTER (0x06A4), "/veharabic" },
+ { GUINT_TO_POINTER (0xFB6B), "/vehfinalarabic" },
+ { GUINT_TO_POINTER (0xFB6C), "/vehinitialarabic" },
+ { GUINT_TO_POINTER (0xFB6D), "/vehmedialarabic" },
+ { GUINT_TO_POINTER (0x30F9), "/vekatakana" },
+ { GUINT_TO_POINTER (0x2640), "/venus" },
+ { GUINT_TO_POINTER (0x007C), "/verticalbar" },
+ { GUINT_TO_POINTER (0x030D), "/verticallineabovecmb" },
+ { GUINT_TO_POINTER (0x0329), "/verticallinebelowcmb" },
+ { GUINT_TO_POINTER (0x02CC), "/verticallinelowmod" },
+ { GUINT_TO_POINTER (0x02C8), "/verticallinemod" },
+ { GUINT_TO_POINTER (0x057E), "/vewarmenian" },
+ { GUINT_TO_POINTER (0x028B), "/vhook" },
+ { GUINT_TO_POINTER (0x30F8), "/vikatakana" },
+ { GUINT_TO_POINTER (0x09CD), "/viramabengali" },
+ { GUINT_TO_POINTER (0x094D), "/viramadeva" },
+ { GUINT_TO_POINTER (0x0ACD), "/viramagujarati" },
+ { GUINT_TO_POINTER (0x0983), "/visargabengali" },
+ { GUINT_TO_POINTER (0x0903), "/visargadeva" },
+ { GUINT_TO_POINTER (0x0A83), "/visargagujarati" },
+ { GUINT_TO_POINTER (0xFF56), "/vmonospace" },
+ { GUINT_TO_POINTER (0x0578), "/voarmenian" },
+ { GUINT_TO_POINTER (0x309E), "/voicediterationhiragana" },
+ { GUINT_TO_POINTER (0x30FE), "/voicediterationkatakana" },
+ { GUINT_TO_POINTER (0x309B), "/voicedmarkkana" },
+ { GUINT_TO_POINTER (0xFF9E), "/voicedmarkkanahalfwidth" },
+ { GUINT_TO_POINTER (0x30FA), "/vokatakana" },
+ { GUINT_TO_POINTER (0x24B1), "/vparen" },
+ { GUINT_TO_POINTER (0x1E7D), "/vtilde" },
+ { GUINT_TO_POINTER (0x028C), "/vturned" },
+ { GUINT_TO_POINTER (0x3094), "/vuhiragana" },
+ { GUINT_TO_POINTER (0x30F4), "/vukatakana" },
+ { GUINT_TO_POINTER (0x0077), "/w" },
+ { GUINT_TO_POINTER (0x1E83), "/wacute" },
+ { GUINT_TO_POINTER (0x3159), "/waekorean" },
+ { GUINT_TO_POINTER (0x308F), "/wahiragana" },
+ { GUINT_TO_POINTER (0x30EF), "/wakatakana" },
+ { GUINT_TO_POINTER (0xFF9C), "/wakatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x3158), "/wakorean" },
+ { GUINT_TO_POINTER (0x308E), "/wasmallhiragana" },
+ { GUINT_TO_POINTER (0x30EE), "/wasmallkatakana" },
+ { GUINT_TO_POINTER (0x3357), "/wattosquare" },
+ { GUINT_TO_POINTER (0x301C), "/wavedash" },
+ { GUINT_TO_POINTER (0xFE34), "/wavyunderscorevertical" },
+ { GUINT_TO_POINTER (0x0648), "/wawarabic" },
+ { GUINT_TO_POINTER (0xFEEE), "/wawfinalarabic" },
+ { GUINT_TO_POINTER (0x0624), "/wawhamzaabovearabic" },
+ { GUINT_TO_POINTER (0xFE86), "/wawhamzaabovefinalarabic" },
+ { GUINT_TO_POINTER (0x33DD), "/wbsquare" },
+ { GUINT_TO_POINTER (0x24E6), "/wcircle" },
+ { GUINT_TO_POINTER (0x0175), "/wcircumflex" },
+ { GUINT_TO_POINTER (0x1E85), "/wdieresis" },
+ { GUINT_TO_POINTER (0x1E87), "/wdotaccent" },
+ { GUINT_TO_POINTER (0x1E89), "/wdotbelow" },
+ { GUINT_TO_POINTER (0x3091), "/wehiragana" },
+ { GUINT_TO_POINTER (0x2118), "/weierstrass" },
+ { GUINT_TO_POINTER (0x30F1), "/wekatakana" },
+ { GUINT_TO_POINTER (0x315E), "/wekorean" },
+ { GUINT_TO_POINTER (0x315D), "/weokorean" },
+ { GUINT_TO_POINTER (0x1E81), "/wgrave" },
+ { GUINT_TO_POINTER (0x25E6), "/whitebullet" },
+ { GUINT_TO_POINTER (0x25CB), "/whitecircle" },
+ { GUINT_TO_POINTER (0x25D9), "/whitecircleinverse" },
+ { GUINT_TO_POINTER (0x300E), "/whitecornerbracketleft" },
+ { GUINT_TO_POINTER (0xFE43), "/whitecornerbracketleftvertical" },
+ { GUINT_TO_POINTER (0x300F), "/whitecornerbracketright" },
+ { GUINT_TO_POINTER (0xFE44), "/whitecornerbracketrightvertical" },
+ { GUINT_TO_POINTER (0x25C7), "/whitediamond" },
+ { GUINT_TO_POINTER (0x25C8), "/whitediamondcontainingblacksmalldiamond" },
+ { GUINT_TO_POINTER (0x25BF), "/whitedownpointingsmalltriangle" },
+ { GUINT_TO_POINTER (0x25BD), "/whitedownpointingtriangle" },
+ { GUINT_TO_POINTER (0x25C3), "/whiteleftpointingsmalltriangle" },
+ { GUINT_TO_POINTER (0x25C1), "/whiteleftpointingtriangle" },
+ { GUINT_TO_POINTER (0x3016), "/whitelenticularbracketleft" },
+ { GUINT_TO_POINTER (0x3017), "/whitelenticularbracketright" },
+ { GUINT_TO_POINTER (0x25B9), "/whiterightpointingsmalltriangle" },
+ { GUINT_TO_POINTER (0x25B7), "/whiterightpointingtriangle" },
+ { GUINT_TO_POINTER (0x25AB), "/whitesmallsquare" },
+ { GUINT_TO_POINTER (0x263A), "/whitesmilingface" },
+ { GUINT_TO_POINTER (0x25A1), "/whitesquare" },
+ { GUINT_TO_POINTER (0x2606), "/whitestar" },
+ { GUINT_TO_POINTER (0x260F), "/whitetelephone" },
+ { GUINT_TO_POINTER (0x3018), "/whitetortoiseshellbracketleft" },
+ { GUINT_TO_POINTER (0x3019), "/whitetortoiseshellbracketright" },
+ { GUINT_TO_POINTER (0x25B5), "/whiteuppointingsmalltriangle" },
+ { GUINT_TO_POINTER (0x25B3), "/whiteuppointingtriangle" },
+ { GUINT_TO_POINTER (0x3090), "/wihiragana" },
+ { GUINT_TO_POINTER (0x30F0), "/wikatakana" },
+ { GUINT_TO_POINTER (0x315F), "/wikorean" },
+ { GUINT_TO_POINTER (0xFF57), "/wmonospace" },
+ { GUINT_TO_POINTER (0x3092), "/wohiragana" },
+ { GUINT_TO_POINTER (0x30F2), "/wokatakana" },
+ { GUINT_TO_POINTER (0xFF66), "/wokatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x20A9), "/won" },
+ { GUINT_TO_POINTER (0xFFE6), "/wonmonospace" },
+ { GUINT_TO_POINTER (0x0E27), "/wowaenthai" },
+ { GUINT_TO_POINTER (0x24B2), "/wparen" },
+ { GUINT_TO_POINTER (0x1E98), "/wring" },
+ { GUINT_TO_POINTER (0x02B7), "/wsuperior" },
+ { GUINT_TO_POINTER (0x028D), "/wturned" },
+ { GUINT_TO_POINTER (0x01BF), "/wynn" },
+ { GUINT_TO_POINTER (0x0078), "/x" },
+ { GUINT_TO_POINTER (0x033D), "/xabovecmb" },
+ { GUINT_TO_POINTER (0x3112), "/xbopomofo" },
+ { GUINT_TO_POINTER (0x24E7), "/xcircle" },
+ { GUINT_TO_POINTER (0x1E8D), "/xdieresis" },
+ { GUINT_TO_POINTER (0x1E8B), "/xdotaccent" },
+ { GUINT_TO_POINTER (0x056D), "/xeharmenian" },
+ { GUINT_TO_POINTER (0x03BE), "/xi" },
+ { GUINT_TO_POINTER (0xFF58), "/xmonospace" },
+ { GUINT_TO_POINTER (0x24B3), "/xparen" },
+ { GUINT_TO_POINTER (0x02E3), "/xsuperior" },
+ { GUINT_TO_POINTER (0x0079), "/y" },
+ { GUINT_TO_POINTER (0x334E), "/yaadosquare" },
+ { GUINT_TO_POINTER (0x09AF), "/yabengali" },
+ { GUINT_TO_POINTER (0x00FD), "/yacute" },
+ { GUINT_TO_POINTER (0x092F), "/yadeva" },
+ { GUINT_TO_POINTER (0x3152), "/yaekorean" },
+ { GUINT_TO_POINTER (0x0AAF), "/yagujarati" },
+ { GUINT_TO_POINTER (0x0A2F), "/yagurmukhi" },
+ { GUINT_TO_POINTER (0x3084), "/yahiragana" },
+ { GUINT_TO_POINTER (0x30E4), "/yakatakana" },
+ { GUINT_TO_POINTER (0xFF94), "/yakatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x3151), "/yakorean" },
+ { GUINT_TO_POINTER (0x0E4E), "/yamakkanthai" },
+ { GUINT_TO_POINTER (0x3083), "/yasmallhiragana" },
+ { GUINT_TO_POINTER (0x30E3), "/yasmallkatakana" },
+ { GUINT_TO_POINTER (0xFF6C), "/yasmallkatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x0463), "/yatcyrillic" },
+ { GUINT_TO_POINTER (0x24E8), "/ycircle" },
+ { GUINT_TO_POINTER (0x0177), "/ycircumflex" },
+ { GUINT_TO_POINTER (0x00FF), "/ydieresis" },
+ { GUINT_TO_POINTER (0x1E8F), "/ydotaccent" },
+ { GUINT_TO_POINTER (0x1EF5), "/ydotbelow" },
+ { GUINT_TO_POINTER (0x064A), "/yeharabic" },
+ { GUINT_TO_POINTER (0x06D2), "/yehbarreearabic" },
+ { GUINT_TO_POINTER (0xFBAF), "/yehbarreefinalarabic" },
+ { GUINT_TO_POINTER (0xFEF2), "/yehfinalarabic" },
+ { GUINT_TO_POINTER (0x0626), "/yehhamzaabovearabic" },
+ { GUINT_TO_POINTER (0xFE8A), "/yehhamzaabovefinalarabic" },
+ { GUINT_TO_POINTER (0xFE8B), "/yehhamzaaboveinitialarabic" },
+ { GUINT_TO_POINTER (0xFE8C), "/yehhamzaabovemedialarabic" },
+ { GUINT_TO_POINTER (0xFEF3), "/yehinitialarabic" },
+ { GUINT_TO_POINTER (0xFEF4), "/yehmedialarabic" },
+ { GUINT_TO_POINTER (0xFCDD), "/yehmeeminitialarabic" },
+ { GUINT_TO_POINTER (0xFC58), "/yehmeemisolatedarabic" },
+ { GUINT_TO_POINTER (0xFC94), "/yehnoonfinalarabic" },
+ { GUINT_TO_POINTER (0x06D1), "/yehthreedotsbelowarabic" },
+ { GUINT_TO_POINTER (0x3156), "/yekorean" },
+ { GUINT_TO_POINTER (0x00A5), "/yen" },
+ { GUINT_TO_POINTER (0xFFE5), "/yenmonospace" },
+ { GUINT_TO_POINTER (0x3155), "/yeokorean" },
+ { GUINT_TO_POINTER (0x3186), "/yeorinhieuhkorean" },
+ { GUINT_TO_POINTER (0x05AA), "/yerahbenyomohebrew" },
+ { GUINT_TO_POINTER (0x05AA), "/yerahbenyomolefthebrew" },
+ { GUINT_TO_POINTER (0x044B), "/yericyrillic" },
+ { GUINT_TO_POINTER (0x04F9), "/yerudieresiscyrillic" },
+ { GUINT_TO_POINTER (0x3181), "/yesieungkorean" },
+ { GUINT_TO_POINTER (0x3183), "/yesieungpansioskorean" },
+ { GUINT_TO_POINTER (0x3182), "/yesieungsioskorean" },
+ { GUINT_TO_POINTER (0x059A), "/yetivhebrew" },
+ { GUINT_TO_POINTER (0x1EF3), "/ygrave" },
+ { GUINT_TO_POINTER (0x01B4), "/yhook" },
+ { GUINT_TO_POINTER (0x1EF7), "/yhookabove" },
+ { GUINT_TO_POINTER (0x0575), "/yiarmenian" },
+ { GUINT_TO_POINTER (0x0457), "/yicyrillic" },
+ { GUINT_TO_POINTER (0x3162), "/yikorean" },
+ { GUINT_TO_POINTER (0x262F), "/yinyang" },
+ { GUINT_TO_POINTER (0x0582), "/yiwnarmenian" },
+ { GUINT_TO_POINTER (0xFF59), "/ymonospace" },
+ { GUINT_TO_POINTER (0x05D9), "/yod" },
+ { GUINT_TO_POINTER (0xFB39), "/yoddagesh" },
+ { GUINT_TO_POINTER (0xFB39), "/yoddageshhebrew" },
+ { GUINT_TO_POINTER (0x05D9), "/yodhebrew" },
+ { GUINT_TO_POINTER (0x05F2), "/yodyodhebrew" },
+ { GUINT_TO_POINTER (0xFB1F), "/yodyodpatahhebrew" },
+ { GUINT_TO_POINTER (0x3088), "/yohiragana" },
+ { GUINT_TO_POINTER (0x3189), "/yoikorean" },
+ { GUINT_TO_POINTER (0x30E8), "/yokatakana" },
+ { GUINT_TO_POINTER (0xFF96), "/yokatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x315B), "/yokorean" },
+ { GUINT_TO_POINTER (0x3087), "/yosmallhiragana" },
+ { GUINT_TO_POINTER (0x30E7), "/yosmallkatakana" },
+ { GUINT_TO_POINTER (0xFF6E), "/yosmallkatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x03F3), "/yotgreek" },
+ { GUINT_TO_POINTER (0x3188), "/yoyaekorean" },
+ { GUINT_TO_POINTER (0x3187), "/yoyakorean" },
+ { GUINT_TO_POINTER (0x0E22), "/yoyakthai" },
+ { GUINT_TO_POINTER (0x0E0D), "/yoyingthai" },
+ { GUINT_TO_POINTER (0x24B4), "/yparen" },
+ { GUINT_TO_POINTER (0x037A), "/ypogegrammeni" },
+ { GUINT_TO_POINTER (0x0345), "/ypogegrammenigreekcmb" },
+ { GUINT_TO_POINTER (0x01A6), "/yr" },
+ { GUINT_TO_POINTER (0x1E99), "/yring" },
+ { GUINT_TO_POINTER (0x02B8), "/ysuperior" },
+ { GUINT_TO_POINTER (0x1EF9), "/ytilde" },
+ { GUINT_TO_POINTER (0x028E), "/yturned" },
+ { GUINT_TO_POINTER (0x3086), "/yuhiragana" },
+ { GUINT_TO_POINTER (0x318C), "/yuikorean" },
+ { GUINT_TO_POINTER (0x30E6), "/yukatakana" },
+ { GUINT_TO_POINTER (0xFF95), "/yukatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x3160), "/yukorean" },
+ { GUINT_TO_POINTER (0x046B), "/yusbigcyrillic" },
+ { GUINT_TO_POINTER (0x046D), "/yusbigiotifiedcyrillic" },
+ { GUINT_TO_POINTER (0x0467), "/yuslittlecyrillic" },
+ { GUINT_TO_POINTER (0x0469), "/yuslittleiotifiedcyrillic" },
+ { GUINT_TO_POINTER (0x3085), "/yusmallhiragana" },
+ { GUINT_TO_POINTER (0x30E5), "/yusmallkatakana" },
+ { GUINT_TO_POINTER (0xFF6D), "/yusmallkatakanahalfwidth" },
+ { GUINT_TO_POINTER (0x318B), "/yuyekorean" },
+ { GUINT_TO_POINTER (0x318A), "/yuyeokorean" },
+ { GUINT_TO_POINTER (0x09DF), "/yyabengali" },
+ { GUINT_TO_POINTER (0x095F), "/yyadeva" },
+ { GUINT_TO_POINTER (0x007A), "/z" },
+ { GUINT_TO_POINTER (0x0566), "/zaarmenian" },
+ { GUINT_TO_POINTER (0x017A), "/zacute" },
+ { GUINT_TO_POINTER (0x095B), "/zadeva" },
+ { GUINT_TO_POINTER (0x0A5B), "/zagurmukhi" },
+ { GUINT_TO_POINTER (0x0638), "/zaharabic" },
+ { GUINT_TO_POINTER (0xFEC6), "/zahfinalarabic" },
+ { GUINT_TO_POINTER (0xFEC7), "/zahinitialarabic" },
+ { GUINT_TO_POINTER (0x3056), "/zahiragana" },
+ { GUINT_TO_POINTER (0xFEC8), "/zahmedialarabic" },
+ { GUINT_TO_POINTER (0x0632), "/zainarabic" },
+ { GUINT_TO_POINTER (0xFEB0), "/zainfinalarabic" },
+ { GUINT_TO_POINTER (0x30B6), "/zakatakana" },
+ { GUINT_TO_POINTER (0x0595), "/zaqefgadolhebrew" },
+ { GUINT_TO_POINTER (0x0594), "/zaqefqatanhebrew" },
+ { GUINT_TO_POINTER (0x0598), "/zarqahebrew" },
+ { GUINT_TO_POINTER (0x05D6), "/zayin" },
+ { GUINT_TO_POINTER (0xFB36), "/zayindagesh" },
+ { GUINT_TO_POINTER (0xFB36), "/zayindageshhebrew" },
+ { GUINT_TO_POINTER (0x05D6), "/zayinhebrew" },
+ { GUINT_TO_POINTER (0x3117), "/zbopomofo" },
+ { GUINT_TO_POINTER (0x017E), "/zcaron" },
+ { GUINT_TO_POINTER (0x24E9), "/zcircle" },
+ { GUINT_TO_POINTER (0x1E91), "/zcircumflex" },
+ { GUINT_TO_POINTER (0x0291), "/zcurl" },
+ { GUINT_TO_POINTER (0x017C), "/zdot" },
+ { GUINT_TO_POINTER (0x017C), "/zdotaccent" },
+ { GUINT_TO_POINTER (0x1E93), "/zdotbelow" },
+ { GUINT_TO_POINTER (0x0437), "/zecyrillic" },
+ { GUINT_TO_POINTER (0x0499), "/zedescendercyrillic" },
+ { GUINT_TO_POINTER (0x04DF), "/zedieresiscyrillic" },
+ { GUINT_TO_POINTER (0x305C), "/zehiragana" },
+ { GUINT_TO_POINTER (0x30BC), "/zekatakana" },
+ { GUINT_TO_POINTER (0x0030), "/zero" },
+ { GUINT_TO_POINTER (0x0660), "/zeroarabic" },
+ { GUINT_TO_POINTER (0x09E6), "/zerobengali" },
+ { GUINT_TO_POINTER (0x0966), "/zerodeva" },
+ { GUINT_TO_POINTER (0x0AE6), "/zerogujarati" },
+ { GUINT_TO_POINTER (0x0A66), "/zerogurmukhi" },
+ { GUINT_TO_POINTER (0x0660), "/zerohackarabic" },
+ { GUINT_TO_POINTER (0x2080), "/zeroinferior" },
+ { GUINT_TO_POINTER (0xFF10), "/zeromonospace" },
+ { GUINT_TO_POINTER (0xF730), "/zerooldstyle" },
+ { GUINT_TO_POINTER (0x06F0), "/zeropersian" },
+ { GUINT_TO_POINTER (0x2070), "/zerosuperior" },
+ { GUINT_TO_POINTER (0x0E50), "/zerothai" },
+ { GUINT_TO_POINTER (0xFEFF), "/zerowidthjoiner" },
+ { GUINT_TO_POINTER (0x200C), "/zerowidthnonjoiner" },
+ { GUINT_TO_POINTER (0x200B), "/zerowidthspace" },
+ { GUINT_TO_POINTER (0x03B6), "/zeta" },
+ { GUINT_TO_POINTER (0x3113), "/zhbopomofo" },
+ { GUINT_TO_POINTER (0x056A), "/zhearmenian" },
+ { GUINT_TO_POINTER (0x04C2), "/zhebrevecyrillic" },
+ { GUINT_TO_POINTER (0x0436), "/zhecyrillic" },
+ { GUINT_TO_POINTER (0x0497), "/zhedescendercyrillic" },
+ { GUINT_TO_POINTER (0x04DD), "/zhedieresiscyrillic" },
+ { GUINT_TO_POINTER (0x3058), "/zihiragana" },
+ { GUINT_TO_POINTER (0x30B8), "/zikatakana" },
+ { GUINT_TO_POINTER (0x05AE), "/zinorhebrew" },
+ { GUINT_TO_POINTER (0x1E95), "/zlinebelow" },
+ { GUINT_TO_POINTER (0xFF5A), "/zmonospace" },
+ { GUINT_TO_POINTER (0x305E), "/zohiragana" },
+ { GUINT_TO_POINTER (0x30BE), "/zokatakana" },
+ { GUINT_TO_POINTER (0x24B5), "/zparen" },
+ { GUINT_TO_POINTER (0x0290), "/zretroflexhook" },
+ { GUINT_TO_POINTER (0x01B6), "/zstroke" },
+ { GUINT_TO_POINTER (0x305A), "/zuhiragana" },
+ { GUINT_TO_POINTER (0x30BA), "/zukatakana" },
+ { NULL, NULL }
+};
+
+/*! \brief Initializes the glyph translation table.
+ * \par Function Description
+ * Initializes the glyph translation table
+ *
+ * \return 0
+ */
+int f_print_initialize_glyph_table(void)
+{
+ struct glyph_list *g;
+
+ /* Is the hash already intialized? */
+ if(unicode_char_to_glyph != NULL) return 0;
+
+ /* No, allocate hash table */
+ unicode_char_to_glyph = g_hash_table_new_full (g_direct_hash,
+ g_direct_equal,
+ NULL,
+ NULL);
+
+ /* insert all the entries, from glyph name mapping table */
+ for(g = glyphs; g->name != NULL; g++) {
+ g_hash_table_insert(unicode_char_to_glyph, g->key, g->name);
+ }
+
+ return 0;
+}
1.11 +106 -95 eda/geda/gaf/libgeda/src/g_basic.c
(In the diff below, changes in quantity of whitespace are not shown.)
Index: g_basic.c
===================================================================
RCS file: g_basic.c
diff -N g_basic.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ g_basic.c 5 Jul 2006 03:13:38 -0000 1.11
@@ -0,0 +1,186 @@
+/* gEDA - GPL Electronic Design Automation
+ * libgeda - gEDA's library
+ * Copyright (C) 1998-2000 Ales V. Hvezda
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+#include <config.h>
+
+#include <stdio.h>
+#include <sys/stat.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_ASSERT_H
+#include <assert.h>
+#endif
+
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <libguile.h>
+
+#include "defines.h"
+#include "struct.h"
+#include "globals.h"
+#include "o_types.h"
+
+#include "../include/prototype.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+/* The following code was contributed by thi (with formating changes
+ * by Ales) Thanks!
+ * Later updated by spe
+ *
+ * This `load()' is modeled after libguile/load.c, load().
+ * Additionally, the most recent form read is saved in case something
+ * goes wrong.
+ */
+
+/*! \brief */
+static SCM most_recently_read_form = SCM_BOOL_F;
+
+/*! \todo Finish function description!!!
+ * \brief Loads a scheme file.
+ * \par Function Description
+ * Loads a scheme file.
+ *
+ * \param [in] data ????
+ * \return SCM_BOOL_T always.
+ */
+static SCM load (void *data)
+{
+ SCM load_port = (SCM)data;
+ SCM form;
+ int eof_found = 0;
+
+ while (!eof_found) {
+ form = scm_read(load_port);
+ if (SCM_EOF_OBJECT_P(form)) {
+ eof_found = 1;
+ } else {
+ most_recently_read_form = form;
+#ifdef HAVE_SCM_EVAL_X_MODULE
+ scm_eval_x (form, scm_current_module() );
+#else
+ scm_eval_x (form);
+#endif
+ }
+ }
+
+ most_recently_read_form = SCM_BOOL_F;
+
+ return SCM_BOOL_T;
+}
+
+/*! \todo Finish function description!!!
+ * \brief The error handler for load.
+ * \par Function Description
+ * The error handler for load
+ *
+ * \param [in] data
+ * \param [in] tag
+ * \param [in] throw_args
+ * \return SCM_BOOL_F always.
+ */
+static SCM load_error_handler(void *data, SCM tag, SCM throw_args)
+{
+ SCM cur_out = scm_current_output_port ();
+ SCM load_port = (SCM)data;
+ SCM filename = scm_port_filename(load_port);
+
+ /*
+ * If misc-error the column and line pointers points
+ * to end of file. Not necessary to confuse user.
+ */
+
+ if (!scm_eq_p (tag, scm_str2symbol ("misc-error"))) {
+ scm_display(scm_makfrom0str("Error : "), cur_out);
+ scm_display(tag, cur_out);
+
+ scm_display(scm_makfrom0str(" [C:"), cur_out);
+ scm_display(scm_port_column(load_port), cur_out );
+ scm_display(scm_makfrom0str(" L:"), cur_out);
+ scm_display(scm_port_line(load_port), cur_out );
+ scm_display(scm_makfrom0str("]"), cur_out);
+ } else {
+ scm_display(scm_makfrom0str("Probably parenthesis mismatch"),
+ cur_out);
+
+ }
+
+ scm_display(scm_makfrom0str(" in "), cur_out);
+ scm_display(filename, cur_out);
+ scm_newline(cur_out);
+
+ if (most_recently_read_form != SCM_BOOL_F) {
+ scm_display(scm_makfrom0str ("Most recently read form: "),
+ cur_out);
+ scm_display(most_recently_read_form, cur_out);
+ scm_newline(cur_out);
+ }
+
+ return SCM_BOOL_F;
+}
+
+
+/*! \brief Start reading a scheme file
+ * \par Function Description
+ * Start reading a scheme file
+ *
+ * \param [in] filename The file name to start reading from.
+ * \return 0 on success, -1 on failure.
+ */
+int g_read_file(const gchar *filename)
+{
+ SCM port;
+ SCM eval_result = SCM_BOOL_F;
+ char * full_filename;
+
+ if (filename == NULL) {
+ return(-1);
+ }
+
+ /* get full, absolute path to file */
+ full_filename = f_normalize_filename(filename);
+ if (full_filename == NULL) {
+ return(-1);
+ }
+
+ if (access(full_filename, R_OK) != 0) {
+ s_log_message("Could not find [%s] for interpretion\n",
+ full_filename);
+ return(-1);
+ }
+
+ port = scm_open_file(scm_makfrom0str(full_filename), scm_makfrom0str("r"));
+
+ eval_result = scm_internal_catch (SCM_BOOL_T,
+ (scm_t_catch_body)load,
+ (void*)port,
+ (scm_t_catch_handler)load_error_handler,
+ (void*)port);
+
+ scm_close_port(port);
+
+ free(full_filename);
+
+ return (eval_result == SCM_BOOL_T);
+}
1.1 eda/geda/gaf/libgeda/src/g_rc.c
Index: g_rc.c
===================================================================
/* gEDA - GPL Electronic Design Automation
* libgeda - gEDA's Library
* Copyright (C) 1998-2000 Ales V. Hvezda
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
*/
#include <config.h>
#include <stdio.h>
#include <sys/stat.h>
#include <ctype.h>
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_DIRENT_H
#include <dirent.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <gtk/gtk.h>
#include <libguile.h>
#include "defines.h"
#include "struct.h"
#include "globals.h"
#include "o_types.h"
#include "colors.h"
#include "../include/i_vars.h"
#include "../include/papersizes.h"
#include "../include/prototype.h"
#ifdef HAVE_LIBDMALLOC
#include <dmalloc.h>
#endif
extern GHashTable *font_char_to_file;
/*! \brief Reads the gafrc file.
* \par Function Description
* This is the function which actually reads in the RC file.
* First, it looks in a list of previously read RC files. If the file has
* already been read, it just says OK. After reading the file, it places
* the filename in the list of read files.
*
* \param [in] w_current The TOPLEVEL object.
* \param [in] fname RC file name to read.
* \param [in] ok_msg Message to print if file is read ok.
* \param [in] err_msg Message to print if file read error occurs
* \return 1 on success, 0 otherwise.
*/
gint g_rc_parse_general(TOPLEVEL *w_current,
const gchar *fname,
const gchar *ok_msg, const gchar *err_msg)
{
gint found_rc = FALSE;
GList *found_rc_filename_element;
/* First see if fname is in list of previously read RC files. */
found_rc_filename_element = g_list_find_custom(w_current->RC_list,
(gconstpointer) fname,
(GCompareFunc) strcmp);
if (found_rc_filename_element != NULL) {
/* We've already read this one in. */
s_log_message("RC file [%s] already read in.\n", fname);
return 0;
}
/* Now try to read in contents of RC file. */
if (access (fname, R_OK) == 0) {
g_read_file (fname);
found_rc = 1;
/* Everything was OK. Now add this file to list of read RC files. */
w_current->RC_list = g_list_append (w_current->RC_list,
g_strdup (fname));
s_log_message (ok_msg, fname);
} else {
found_rc = 0;
s_log_message (err_msg, fname);
}
return found_rc;
}
/*! \brief Read gEDA root path from RC file.
* \par Function Description
* This function will read the RC file and parse the root path for gEDA.
*
* \return String containing rc root path
*
* \warning Do not free the returned character string.
*/
const gchar* g_rc_parse_path(void)
{
const gchar *rc_path;
if (g_strcasecmp (GEDARCDIR, "none") == 0) {
/* rc dir not specified at configure time, so search for config in */
/* the normal GEDADATA directory */
rc_path = g_getenv ("GEDADATA");
} else {
/* rc path specified at configure time, always return specified path */
rc_path = GEDARCDIR;
}
return(rc_path);
}
/*! \brief Parses a system RC file.
* \par Function Description
* This function wil open and parse a system rc file.
*
* \param [in] w_current The TOPLEVEL object.
* \param [in] rcname System RC file name to parse.
* \return 1 on success, 0 on failure.
*/
gint g_rc_parse_system_rc(TOPLEVEL *w_current, const gchar *rcname)
{
const gchar *geda_data = g_getenv ("GEDADATA");
gint found_rc;
gchar *tmp;
char *filename;
gchar *ok_msg, *err_msg;
if (geda_data == NULL) {
fprintf(stderr, "You must set the GEDADATA environment variable!\n");
exit(-1);
}
tmp = g_strconcat (g_rc_parse_path (),
G_DIR_SEPARATOR_S,
"system-", rcname,
NULL);
filename = f_normalize_filename(tmp);
if (filename == NULL) {
return 0;
}
ok_msg = g_strdup_printf ("Read system-%s file [%%s]\n",
rcname);
err_msg = g_strdup_printf ("Did not find required system-%s file [%%s]\n",
rcname);
found_rc = g_rc_parse_general(w_current, filename, ok_msg, err_msg);
g_free (ok_msg);
g_free (err_msg);
g_free (tmp);
free(filename);
return found_rc;
}
/*! \brief Parse a RC file in users home directory.
* \par Function Description
* This function will open and parse a RC file in the users home directory.
*
* \param [in] w_current The TOPLEVEL object.
* \param [in] rcname User's RC file name.
* \return 1 on success, 0 on failure.
*/
gint g_rc_parse_home_rc(TOPLEVEL *w_current, const gchar *rcname)
{
const gchar *home = g_getenv ("HOME");
gint found_rc;
gchar *tmp;
char *filename;
gchar *ok_msg, *err_msg;
if (home == NULL) {
return 0;
}
tmp = g_strconcat (home,
G_DIR_SEPARATOR_S,
".gEDA",
G_DIR_SEPARATOR_S,
rcname,
NULL);
filename = f_normalize_filename(tmp);
if (filename == NULL) {
return 0;
}
ok_msg = g_strdup_printf ("Read ~/.gEDA/%s file [%%s]\n",
rcname);
err_msg = g_strdup_printf ("Did not find optional ~/.gEDA/%s file [%%s]\n",
rcname);
found_rc = g_rc_parse_general(w_current, filename, ok_msg, err_msg);
g_free (ok_msg);
g_free (err_msg);
g_free (tmp);
free(filename);
return found_rc;
}
/*! \brief Parse rc file in current working directory.
* \par Function Description
* This function will open and parse a RC file in the current working directory.
*
* \param [in] w_current The TOPLEVEL object.
* \param [in] rcname Local directory RC file name.
* \return 1 on success, 0 on failure.
*/
gint g_rc_parse_local_rc(TOPLEVEL *w_current, const gchar *rcname)
{
gint found_rc;
gchar *tmp;
char *filename;
gchar *ok_msg;
gchar *err_msg;
tmp = g_strconcat (".", G_DIR_SEPARATOR_S, rcname, NULL);
filename = f_normalize_filename (tmp);
if (filename == NULL) {
return 0;
}
ok_msg = g_strdup_printf ("Read local %s file [%%s]\n",
rcname);
err_msg = g_strdup_printf ("Did not find optional local %s file [%%s]\n",
rcname);
found_rc = g_rc_parse_general(w_current, filename, ok_msg, err_msg);
g_free (ok_msg);
g_free (err_msg);
g_free (tmp);
free(filename);
return found_rc;
}
/*! \brief Parse a RC file from a specified location.
* \par Function Description
* This function will open and parse a RC file from a specified location.
*
* \param [in] w_current The TOPLEVEL object.
* \param [in] rcname Specified location RC file name.
* \return 1 on success, 0 on failure.
*/
gint g_rc_parse_specified_rc(TOPLEVEL *w_current, const gchar *rcname)
{
gint found_rc = 0;
char *filename;
gchar *ok_msg;
gchar *err_msg;
if (rcname == NULL) {
return 0;
}
filename = f_normalize_filename (rcname);
ok_msg = g_strdup_printf ("Read specified %s file [%%s]\n",
rcname);
err_msg = g_strdup_printf ("Did not find specified %s file [%%s]\n",
rcname);
found_rc = g_rc_parse_general(w_current, filename, ok_msg, err_msg);
g_free(ok_msg);
g_free(err_msg);
free(filename);
return found_rc;
}
/*! \brief General RC file parsing function.
* \par Function Description
* This function will check for System, HOME and Local RC files matching
* the rcname input parameter. If none of those three are found it will
* search for the specified_rc_filename. When none are found it will
* call exit(-1) to terminate the program.
*
* \param [in] w_current The TOPLEVEL object.
* \param [in] rcname RC file name.
* \param [in] specified_rc_filename Specific location RC file name.
* \return calls exit(-1) when no RC file matching either rcname or
* specified_rc_filename is found.
*/
void g_rc_parse(TOPLEVEL *w_current,
const gchar *rcname, const gchar *specified_rc_filename)
{
gint found_rc = 0;
char *rc_path;
char *geda_rcdata;
/* set the GEDADATARC environment variable so that the rc files */
/* know where to look for others */
rc_path = f_normalize_filename (g_rc_parse_path ());
/* Reversion to putenv inspired by W. Hoch, 2.17.2005 */
/* g_setenv ("GEDADATARC", rc_path, TRUE); */ /*requires glib 2.4.x*/
geda_rcdata = g_strdup_printf("GEDADATARC=%s", rc_path);
putenv(geda_rcdata);
free (rc_path);
/* visit rc files in order */
/* Changed by SDB 1.2.2005 in response to Peter Kaiser's bug report.
* Read gafrc files first */
found_rc |= g_rc_parse_system_rc(w_current, "gafrc");
found_rc |= g_rc_parse_home_rc(w_current, "gafrc");
found_rc |= g_rc_parse_local_rc(w_current, "gafrc");
/* continue support for individual rc files for each program. */
found_rc |= g_rc_parse_system_rc(w_current, rcname);
found_rc |= g_rc_parse_home_rc(w_current, rcname);
found_rc |= g_rc_parse_local_rc(w_current, rcname);
/* New fcn introduced by SDB to consolidate this & make it available
* for other programs */
found_rc |= g_rc_parse_specified_rc(w_current, specified_rc_filename);
/* Oh well, I couldn't find any rcfile, exit! */
if (!found_rc) {
/*! \todo these two are basically the
* same. Inefficient!
*/
s_log_message("Could not find any %s file!\n", rcname);
fprintf(stderr, "Could not find a %s file\n", rcname);
exit(-1);
}
}
/*! \brief
* \par Function Description
*
* \param [in] path
* \return SCM_BOOL_T on success, SCM_BOOL_F otherwise.
*/
SCM g_rc_component_library(SCM path)
{
char *string;
SCM_ASSERT (SCM_NIMP (path) && SCM_STRINGP (path), path,
SCM_ARG1, "component-library");
string = g_strdup (SCM_STRING_CHARS (path));
/* take care of any shell variables */
string = expand_env_variables(string);
/* invalid path? */
if (!g_file_test (string, G_FILE_TEST_IS_DIR)) {
fprintf(stderr,
"Invalid path [%s] passed to component-library\n",
string);
free (string);
return SCM_BOOL_F;
}
if (g_path_is_absolute (string)) {
s_clib_add_directory (string);
} else {
gchar *cwd = g_get_current_dir ();
gchar *temp;
#ifdef __MINGW32__
u_basic_strip_trailing(cwd, G_DIR_SEPARATOR);
#endif
temp = g_strconcat (cwd, G_DIR_SEPARATOR_S, string, NULL);
s_clib_add_directory (temp);
g_free (temp);
g_free (cwd);
}
if (string) {
free(string);
}
return SCM_BOOL_T;
}
/*! \todo Finish function description!!!
* \brief
* \par Function Description
*
* \param [in] path
* \return SCM_BOOL_T on success, SCM_BOOL_F otherwise.
*/
SCM g_rc_component_library_search(SCM path)
{
char *string;
GDir *dir;
const gchar *entry;
SCM_ASSERT (SCM_NIMP (path) && SCM_STRINGP (path), path,
SCM_ARG1, "component-library-search");
string = g_strdup (SCM_STRING_CHARS (path));
/* take care of any shell variables */
string = expand_env_variables(string);
/* invalid path? */
if (!g_file_test (string, G_FILE_TEST_IS_DIR)) {
fprintf (stderr,
"Invalid path [%s] passed to component-library-search\n",
string);
free (string);
return SCM_BOOL_F;
}
dir = g_dir_open (string, 0, NULL);
if (dir == NULL) {
fprintf (stderr,
"Invalid path [%s] passed to component-library-search\n",
string);
free (string);
return SCM_BOOL_F;
}
while ((entry = g_dir_read_name (dir))) {
/* don't do . and .. and special case font */
if ((g_strcasecmp (entry, ".") != 0) &&
(g_strcasecmp (entry, "..") != 0) &&
(g_strcasecmp (entry, "font") != 0))
{
gchar *fullpath = g_strconcat (string,
G_DIR_SEPARATOR_S,
entry,
NULL);
if (g_file_test (fullpath, G_FILE_TEST_IS_DIR)) {
if (g_path_is_absolute (fullpath)) {
s_clib_add_directory (fullpath);
} else {
gchar *cwd = g_get_current_dir ();
gchar *temp;
#ifdef __MINGW32__
u_basic_strip_trailing(cwd, G_DIR_SEPARATOR);
#endif
temp = g_strconcat (cwd,
G_DIR_SEPARATOR_S,
fullpath,
NULL);
s_clib_add_directory (temp);
g_free (temp);
g_free (cwd);
}
}
g_free (fullpath);
}
}
if (string) {
free(string);
}
return SCM_BOOL_T;
}
/*! \todo Finish function description!!!
* \brief
* \par Function Description
*
* \param [in] path
* \return SCM_BOOL_T on success, SCM_BOOL_F otherwise.
*/
SCM g_rc_source_library(SCM path)
{
char *string;
SCM_ASSERT (SCM_NIMP (path) && SCM_STRINGP (path), path,
SCM_ARG1, "source-library");
string = g_strdup (SCM_STRING_CHARS (path));
/* take care of any shell variables */
string = expand_env_variables(string);
/* invalid path? */
if (!g_file_test (string, G_FILE_TEST_IS_DIR)) {
fprintf (stderr,
"Invalid path [%s] passed to source-library\n",
string);
free (string);
return SCM_BOOL_F;
}
if (g_path_is_absolute (string)) {
s_slib_add_entry (string);
} else {
gchar *cwd = g_get_current_dir ();
gchar *temp;
#ifdef __MINGW32__
u_basic_strip_trailing(cwd, G_DIR_SEPARATOR);
#endif
temp = g_strconcat (cwd,
G_DIR_SEPARATOR_S,
string,
NULL);
s_slib_add_entry (temp);
g_free (temp);
g_free (cwd);
}
if (string) {
free (string);
}
return SCM_BOOL_T;
}
/*! \todo Finish function description!!!
* \brief
* \par Function Description
*
* \param [in] path
* \return SCM_BOOL_T on success, SCM_BOOL_F otherwise.
*/
SCM g_rc_source_library_search(SCM path)
{
char *string;
GDir *dir;
const gchar *entry;
SCM_ASSERT (SCM_NIMP (path) && SCM_STRINGP (path), path,
SCM_ARG1, "source-library-search");
string = g_strdup (SCM_STRING_CHARS (path));
/* take care of any shell variables */
string = expand_env_variables(string);
/* invalid path? */
if (!g_file_test (string, G_FILE_TEST_IS_DIR)) {
fprintf (stderr,
"Invalid path [%s] passed to source-library-search\n",
string);
free (string);
return SCM_BOOL_F;
}
dir = g_dir_open (string, 0, NULL);
if (dir == NULL) {
fprintf (stderr,
"Invalid path [%s] passed to source-library-search\n",
string);
if (string) {
free (string);
}
return SCM_BOOL_F;
}
while ((entry = g_dir_read_name (dir))) {
/* don't do . and .. and special case font */
if ((g_strcasecmp (entry, ".") != 0) &&
(g_strcasecmp (entry, "..") != 0) &&
(g_strcasecmp (entry, "font") != 0))
{
gchar *fullpath = g_strconcat (string,
G_DIR_SEPARATOR_S,
entry,
NULL);
if (g_file_test (fullpath, G_FILE_TEST_IS_DIR)) {
if (s_slib_uniq (fullpath)) {
if (g_path_is_absolute (fullpath)) {
s_slib_add_entry (fullpath);
} else {
gchar *cwd = g_get_current_dir ();
gchar *temp;
#ifdef __MINGW32__
u_basic_strip_trailing(cwd, G_DIR_SEPARATOR);
#endif
temp = g_strconcat (cwd,
G_DIR_SEPARATOR_S,
fullpath,
NULL);
s_slib_add_entry (temp);
g_free (temp);
g_free (cwd);
}
}
}
g_free (fullpath);
}
}
if (string) {
free (string);
}
return SCM_BOOL_T;
}
/*! \todo Finish function description!!!
* \brief
* \par Function Description
*
* \param [in] width
* \param [in] height
* \param [in] border
* \return SCM_BOOL_T always.
*/
SCM g_rc_world_size(SCM width, SCM height, SCM border)
#define FUNC_NAME "world-size"
{
int i_width, i_height, i_border;
int init_right, init_bottom;
SCM_ASSERT (SCM_NIMP (width) && SCM_REALP (width), width,
SCM_ARG1, FUNC_NAME);
SCM_ASSERT (SCM_NIMP (height) && SCM_REALP (height), height,
SCM_ARG2, FUNC_NAME);
SCM_ASSERT (SCM_NIMP (border) && SCM_REALP (border), border,
SCM_ARG3, FUNC_NAME);
/* yes this is legit, we are casing the resulting double to an int */
i_width = (int) (SCM_NUM2DOUBLE (0, width) * MILS_PER_INCH);
i_height = (int) (SCM_NUM2DOUBLE (0, height) * MILS_PER_INCH);
i_border = (int) (SCM_NUM2DOUBLE (0, border) * MILS_PER_INCH);
PAPERSIZEtoWORLD(i_width, i_height, i_border,
&init_right, &init_bottom);
#if DEBUG
printf("%d %d\n", i_width, i_height);
printf("%d %d\n", init_right, init_bottom);
#endif
default_init_right = init_right;
default_init_bottom = init_bottom;
return SCM_BOOL_T;
}
#undef FUNC_NAME
/*! \todo Finish function description!!!
* \brief
* \par Function Description
*
* \param [in] name
* \return SCM_BOOL_T always.
*/
SCM g_rc_default_series_name(SCM name)
{
SCM_ASSERT (SCM_NIMP (name) && SCM_STRINGP (name), name,
SCM_ARG1, "default-series-name");
if (default_series_name) {
free (default_series_name);
}
default_series_name = g_strdup (SCM_STRING_CHARS (name));
return SCM_BOOL_T;
}
/*! \todo Finish function description!!!
* \brief
* \par Function Description
*
* \param [in] name
* \return SCM_BOOL_T always.
*/
SCM g_rc_untitled_name(SCM name)
{
SCM_ASSERT (SCM_NIMP (name) && SCM_STRINGP (name), name,
SCM_ARG1, "untitled-name");
if (default_untitled_name) {
free (default_untitled_name);
}
default_untitled_name = g_strdup (SCM_STRING_CHARS (name));
return SCM_BOOL_T;
}
/*! \todo Finish function description!!!
* \brief
* \par Function Description
*
* \param [in] path
* \return SCM_BOOL_T on success, SCM_BOOL_F otherwise.
*/
SCM g_rc_font_directory(SCM path)
{
char *string;
SCM_ASSERT (SCM_NIMP (path) && SCM_STRINGP (path), path,
SCM_ARG1, "font-directory");
string = g_strdup (SCM_STRING_CHARS (path));
/* take care of any shell variables */
string = expand_env_variables(string);
/* invalid path? */
if (!g_file_test (string, G_FILE_TEST_IS_DIR)) {
fprintf (stderr,
"Invalid path [%s] passed to font-directory\n",
string);
if (string) {
free (string);
}
return SCM_BOOL_F;
}
if (default_font_directory) {
free (default_font_directory);
}
default_font_directory = string;
return SCM_BOOL_T;
}
/*! \todo Finish function description!!!
* \brief
* \par Function Description
*
* \param [in] path
* \return SCM_BOOL_T on success, SCM_BOOL_F otherwise.
*/
SCM g_rc_scheme_directory(SCM path)
{
char *string;
SCM_ASSERT (SCM_NIMP (path) && SCM_STRINGP (path), path,
SCM_ARG1, "scheme-directory");
string = g_strdup (SCM_STRING_CHARS (path));
/* take care of any shell variables */
string = expand_env_variables(string);
/* invalid path? */
if (!g_file_test (string, G_FILE_TEST_IS_DIR)) {
fprintf (stderr,
"Invalid path [%s] passed to scheme-directory\n",
string);
if (string) {
free (string);
}
return SCM_BOOL_F;
}
if (default_scheme_directory) {
free (default_scheme_directory);
}
default_scheme_directory = string;
return SCM_BOOL_T;
}
/*! \todo Finish function description!!!
* \brief
* \par Function Description
*
* \param [in] path
* \return SCM_BOOL_T on success, SCM_BOOL_F otherwise.
*/
SCM g_rc_bitmap_directory(SCM path)
{
char *string;
SCM_ASSERT (SCM_NIMP (path) && SCM_STRINGP (path), path,
SCM_ARG1, "bitmap-directory");
string = g_strdup (SCM_STRING_CHARS (path));
/* take care of any shell variables */
string = expand_env_variables(string);
/* invalid path? */
if (!g_file_test (string, G_FILE_TEST_IS_DIR)) {
fprintf (stderr,
"Invalid path [%s] passed to bitmap-directory\n",
string);
if (string) {
free (string);
}
return SCM_BOOL_F;
}
if (default_bitmap_directory) {
free (default_bitmap_directory);
}
default_bitmap_directory = string;
return SCM_BOOL_T;
}
/*! \todo Finish function description!!!
* \brief
* \par Function Description
*
* \param [in] scmsymname
* \return SCM_BOOL_T always.
*/
SCM g_rc_bus_ripper_symname(SCM scmsymname)
{
SCM_ASSERT (SCM_NIMP (scmsymname) && SCM_STRINGP (scmsymname), scmsymname,
SCM_ARG1, "bus-ripper-symname");
if (default_bus_ripper_symname) {
free (default_bus_ripper_symname);
}
default_bus_ripper_symname = g_strdup (SCM_STRING_CHARS (scmsymname));
return SCM_BOOL_T;
}
/*! \todo Finish function description!!!
* \brief
* \par Function Description
*
* \param [in] scmsymname
* \return SCM_BOOL_T always.
*/
SCM g_rc_postscript_prolog(SCM scmsymname)
{
char *string;
SCM_ASSERT (SCM_NIMP (scmsymname) && SCM_STRINGP (scmsymname), scmsymname,
SCM_ARG1, "postsript-prolog");
if (default_postscript_prolog) {
free (default_postscript_prolog);
}
string = g_strdup (SCM_STRING_CHARS (scmsymname));
/* take care of any shell variables */
string = expand_env_variables(string);
default_postscript_prolog = g_strdup (string);
return SCM_BOOL_T;
}
/*! \todo Finish function description!!!
* \brief
* \par Function Description
*
* \return SCM_BOOL_T always.
*/
SCM g_rc_reset_component_library(void)
{
s_clib_init();
return SCM_BOOL_T;
}
/*! \todo Finish function description!!!
* \brief
* \par Function Description
*
* \return SCM_BOOL_T always.
*/
SCM g_rc_reset_source_library(void)
{
s_slib_free();
s_slib_init();
return SCM_BOOL_T;
}
/*! \todo Finish function description!!!
* \brief
* \par Function Description
*
* \param [in] scmcharstr
* \param [in] scmfilename
* \return SCM_BOOL_T on success, SCM_BOOL_F otherwise.
*/
SCM g_rc_map_font_character_to_file(SCM scmcharstr, SCM scmfilename)
{
gchar *charstr, *filename;
gunichar character;
SCM_ASSERT (SCM_STRINGP (scmcharstr), scmcharstr,
SCM_ARG1, "map-font-character-to-file");
SCM_ASSERT (SCM_STRINGP (scmfilename), scmfilename,
SCM_ARG2, "map-font-character-to-file");
charstr = SCM_STRING_CHARS (scmcharstr);
filename = SCM_STRING_CHARS (scmfilename);
if (charstr == NULL || filename == NULL) {
fprintf(stderr,
"%s requires two strings as parameters\n",
"map-font-character-to-file"
);
return SCM_BOOL_F;
}
/* take care of expansion of any shell variables in filename */
filename = expand_env_variables (g_strdup (filename));
character = g_utf8_get_char_validated (charstr, -1);
/* insert the new character declaration in the hash table */
g_hash_table_insert (font_char_to_file,
GUINT_TO_POINTER ((guint)character),
filename);
return SCM_BOOL_T;
}
/*! \todo Finish function description!!!
* \brief
* \par Function Description
*
* \param [in] scmsymname
* \return SCM_BOOL_T always.
*/
SCM g_rc_always_promote_attributes(SCM scmsymname)
{
SCM_ASSERT (SCM_NIMP (scmsymname) && SCM_STRINGP (scmsymname), scmsymname,
SCM_ARG1, "always-promote-attributes");
if (default_always_promote_attributes) {
free (default_always_promote_attributes);
}
default_always_promote_attributes =
g_strdup_printf(" %s ", SCM_STRING_CHARS (scmsymname));
return SCM_BOOL_T;
}
1.1 eda/geda/gaf/libgeda/src/g_register.c
Index: g_register.c
===================================================================
/* gEDA - GPL Electronic Design Automation
* libgeda - gEDA's Library
* Copyright (C) 1998-2004 Ales V. Hvezda
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
*/
#include <config.h>
#include <stdio.h>
#include <sys/stat.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_ASSERT_H
#include <assert.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include <gtk/gtk.h>
#include <libguile.h>
#include "defines.h"
#include "struct.h"
#include "globals.h"
#include "o_types.h"
#include "colors.h"
#include "i_vars.h"
#include "prototype.h"
#ifdef HAVE_LIBDMALLOC
#include <dmalloc.h>
#endif
/*! \brief */
struct gsubr_t {
char* name;
int req;
int opt;
int rst;
SCM (*fnc)();
};
/*! \brief */
static struct gsubr_t libgeda_funcs[] = {
{ "component-library", 1, 0, 0, g_rc_component_library },
{ "component-library-search", 1, 0, 0, g_rc_component_library_search },
{ "source-library", 1, 0, 0, g_rc_source_library },
{ "source-library-search", 1, 0, 0, g_rc_source_library_search },
{ "world-size", 3, 0, 0, g_rc_world_size },
{ "reset-component-library", 0, 0, 0, g_rc_reset_component_library },
{ "reset-source-library", 0, 0, 0, g_rc_reset_source_library },
{ "default-series-name", 1, 0, 0, g_rc_default_series_name },
{ "untitled-name", 1, 0, 0, g_rc_untitled_name },
{ "scheme-directory", 1, 0, 0, g_rc_scheme_directory },
{ "bitmap-directory", 1, 0, 0, g_rc_bitmap_directory },
{ "font-directory", 1, 0, 0, g_rc_font_directory },
{ "bus-ripper-symname", 1, 0, 0, g_rc_bus_ripper_symname },
{ "postscript-prolog", 1, 0, 0, g_rc_postscript_prolog },
{ "map-font-character-to-file", 2, 0, 0, g_rc_map_font_character_to_file },
{ "always-promote-attributes",1, 0, 0, g_rc_always_promote_attributes },
{ NULL, 0, 0, 0, NULL } };
/*! \brief Register all libgeda functions with scheme.
* \par Function Description
* Creates g_subr_t objects to make g_rc_* functions that are defined
* in g_rc.c visible to Scheme.
*/
void g_register_libgeda_funcs (void)
{
struct gsubr_t *tmp = libgeda_funcs;
while (tmp->name != NULL) {
scm_c_define_gsubr (tmp->name, tmp->req, tmp->opt, tmp->rst, tmp->fnc);
tmp++;
}
}
1.6 +343 -114 eda/geda/gaf/libgeda/src/g_smob.c
(In the diff below, changes in quantity of whitespace are not shown.)
Index: g_smob.c
===================================================================
RCS file: g_smob.c
diff -N g_smob.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ g_smob.c 5 Jul 2006 03:13:38 -0000 1.6
@@ -0,0 +1,412 @@
+/* gEDA - GPL Electronic Design Automation
+ * libgeda - gEDA's library
+ * Copyright (C) 1998-2000 Ales V. Hvezda
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+#include <config.h>
+
+#include <math.h>
+#include <stdio.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <libguile.h>
+
+#include "defines.h"
+#include "struct.h"
+#include "globals.h"
+
+#include "../include/prototype.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+static long attrib_smob_tag; /*! Attribute SMOB tag */
+static long object_smob_tag; /*! Object SMOB tag */
+
+/*! \brief Free attribute smob memory.
+ * \par Function Description
+ * Free the memory allocated by the attribute smob and return its size.
+ *
+ * \param [in] attrib_smob The attribute smob to free.
+ * \return Size of attribute smob.
+ */
+static scm_sizet g_free_attrib_smob(SCM attrib_smob)
+{
+ struct st_attrib_smob *attribute =
+ (struct st_attrib_smob *)SCM_CDR(attrib_smob);
+ scm_sizet size = sizeof(struct st_attrib_smob);
+
+ free(attribute);
+ return size;
+}
+
+/*! \brief Prints attribute smob to port.
+ * \par Function Description
+ * This function prints the given attribute smob to the port.
+ * It just prints a string showing it is an attribute and its string.
+ *
+ * \param [in] attrib_smob The attribute smob.
+ * \param [in] port The port to print to.
+ * \param [in] pstate Unused.
+ * \return non-zero means success.
+ */
+static int g_print_attrib_smob(SCM attrib_smob, SCM port,
+ scm_print_state *pstate)
+{
+ struct st_attrib_smob *attribute =
+ (struct st_attrib_smob *)SCM_CDR(attrib_smob);
+
+ if (attribute &&
+ attribute->attribute &&
+ attribute->attribute->object &&
+ attribute->attribute->object->text &&
+ attribute->attribute->object->text->string ) {
+ scm_puts("#<attribute ", port);
+ scm_display (scm_makfrom0str (attribute->attribute->object->text->string),
+ port);
+ scm_puts(">", port);
+ }
+
+ /* non-zero means success */
+ return 1;
+}
+
+
+/*! \brief Creates a name-value smob
+ * \par Function Description
+ * This function Creates and returns a new attribute smob,
+ * based on the given TOPLEVEL curr_w and attribute curr_attr.
+ *
+ * \param [in] curr_w The current TOPLEVEL object.
+ * \param [in] curr_attr The current attribute.
+ * \return SCM
+ */
+SCM g_make_attrib_smob(TOPLEVEL *curr_w, ATTRIB *curr_attr)
+{
+ struct st_attrib_smob *smob_attribute;
+
+ smob_attribute = (struct st_attrib_smob *)
+ scm_must_malloc(sizeof(struct st_attrib_smob),
+ "attribute");
+
+ smob_attribute->world = curr_w;
+ smob_attribute->attribute = curr_attr;
+
+ /* Assumes Guile version >= 1.3.2 */
+ SCM_RETURN_NEWSMOB(attrib_smob_tag, smob_attribute);
+}
+
+/*! \brief Get name and value of attribute.
+ * \par Function Description
+ * Returns a list with the name and value of the given attribute smob
+ *
+ * \param [in] attrib_smob The attribute smob to get name and value from.
+ * \return A list containing the name and value of the attribute.
+ */
+SCM g_get_attrib_name_value(SCM attrib_smob)
+{
+ struct st_attrib_smob *attribute;
+ char *name = NULL;
+ char *value = NULL;
+ SCM returned = SCM_EOL;
+
+ SCM_ASSERT ( SCM_NIMP(attrib_smob) &&
+ ((long) SCM_CAR(attrib_smob) == attrib_smob_tag),
+ attrib_smob, SCM_ARG1, "get-attribute-name-value");
+
+ attribute = (struct st_attrib_smob *)SCM_CDR(attrib_smob);
+
+ if (attribute &&
+ attribute->attribute &&
+ attribute->attribute->object &&
+ attribute->attribute->object->text->string ) {
+ o_attrib_get_name_value(attribute->attribute->object->text->string,
+ &name, &value );
+ returned = scm_cons (scm_makfrom0str (name),
+ scm_makfrom0str (value));
+ if (name) free(name);
+ if (value) free(value);
+ }
+
+ return returned;
+}
+
+/*! \brief Set the attribute value.
+ * \par Function Description
+ * This function puts the attribute smob name into a new_string and
+ * the new scm_value (attribute=value format). It also returns the
+ * TOPLEVEL and OBJECT pointers.
+ *
+ * \param [in] attrib_smob The attribute to update.
+ * \param [in] scm_value The new value of the attribute.
+ * \param [in,out] world The TOPLEVEL object.
+ * \param [in,out] o_attrib Pointer to the updated attribute smob.
+ * \param [in] new_string Returns the attribute=value format string for the
+ * updated attribute.
+ * \return Always SCM_UNDEFINED
+ */
+SCM g_set_attrib_value_internal(SCM attrib_smob, SCM scm_value,
+ TOPLEVEL **world, OBJECT **o_attrib,
+ char *new_string[])
+{
+ struct st_attrib_smob *attribute;
+ char *name = NULL;
+ char *value = NULL;
+ char *old_value = NULL;
+
+ SCM_ASSERT ( SCM_NIMP(attrib_smob) &&
+ ((long) SCM_CAR(attrib_smob) == attrib_smob_tag),
+ attrib_smob, SCM_ARG1, "set-attribute-value!");
+ SCM_ASSERT ( SCM_NIMP(scm_value) && SCM_STRINGP(scm_value),
+ scm_value, SCM_ARG2, "set-attribute-value!");
+
+ attribute = (struct st_attrib_smob *)SCM_CDR(attrib_smob);
+ value = SCM_STRING_CHARS (scm_value);
+
+ if (attribute &&
+ attribute->attribute &&
+ attribute->attribute->object &&
+ attribute->attribute->object->text &&
+ attribute->attribute->object->text->string ) {
+
+ o_attrib_get_name_value(attribute->attribute->object->text->string,
+ &name, &old_value );
+
+ *new_string = g_strconcat (name, "=", value, NULL);
+
+ *world = attribute->world;
+ *o_attrib = attribute->attribute->object;
+
+ if (name) free(name);
+ if (old_value) free(old_value);
+ }
+
+ return SCM_UNDEFINED;
+}
+
+/*! \brief Initialize the framework to support an attribute smob.
+ * \par Function Description
+ * Initialize the framework to support an attribute smob.
+ *
+ */
+void g_init_attrib_smob(void)
+{
+
+ attrib_smob_tag = scm_make_smob_type("attribute",
+ sizeof (struct st_attrib_smob));
+ scm_set_smob_mark(attrib_smob_tag, 0);
+ scm_set_smob_free(attrib_smob_tag, g_free_attrib_smob);
+ scm_set_smob_print(attrib_smob_tag, g_print_attrib_smob);
+
+ scm_c_define_gsubr("get-attribute-name-value", 1, 0, 0,
+ g_get_attrib_name_value);
+
+ return;
+}
+
+/*! \brief Free object smob memory.
+ * \par Function Description
+ * Free the memory allocated by the object smob and return its size.
+ *
+ * \param [in] object_smob The object smob to free.
+ * \return Size of object smob.
+ */
+static scm_sizet g_free_object_smob(SCM object_smob)
+{
+ struct st_object_smob *object =
+ (struct st_object_smob *)SCM_CDR(object_smob);
+ scm_sizet size = sizeof(struct st_object_smob);
+
+ free(object);
+ return size;
+}
+
+/*! \brief Prints object smob to port.
+ * \par Function Description
+ * This function prints the given object smob to the port.
+ * It just prints a string showing it is an object and the object name.
+ *
+ * \param [in] object_smob The object smob.
+ * \param [in] port The port to print to.
+ * \param [in] pstate Unused.
+ * \return non-zero means success.
+ */
+static int g_print_object_smob(SCM object_smob, SCM port,
+ scm_print_state *pstate)
+{
+ struct st_object_smob *object =
+ (struct st_object_smob *)SCM_CDR(object_smob);
+
+ if (object &&
+ object->object &&
+ object->object->name) {
+ scm_puts("#<object ", port);
+ scm_display (scm_makfrom0str (object->object->name),
+ port);
+ scm_puts(">", port);
+ }
+
+ /* non-zero means success */
+ return 1;
+}
+
+/*! \brief Creates a object smob
+ * \par Function Description
+ * This function creates and returns a new object smob,
+ * from the given TOPLEVEL curr_w and object pointers.
+ *
+ * \param [in] curr_w The current TOPLEVEL object.
+ * \param [in] object The current object.
+ * \return SCM
+ */
+SCM g_make_object_smob(TOPLEVEL *curr_w, OBJECT *object)
+{
+ struct st_object_smob *smob_object;
+
+ smob_object = (struct st_object_smob *)
+ scm_must_malloc(sizeof(struct st_object_smob), "object");
+
+ smob_object->world = curr_w;
+ smob_object->object = object;
+
+ /* Assumes Guile version >= 1.3.2 */
+ SCM_RETURN_NEWSMOB(object_smob_tag, smob_object);
+}
+
+/*! \brief Get all object attributes in a list.
+ * \par Function Description
+ * This function returns a list with all the attributes of a given object smob.
+ *
+ * \param [in] object_smob The object smob to get attributes from.
+ * \return A list of attributes associated with this object smob.
+ */
+SCM g_get_object_attributes(SCM object_smob)
+{
+ TOPLEVEL *w_current;
+ struct st_object_smob *object;
+ SCM returned = SCM_EOL;
+
+ SCM_ASSERT ( SCM_NIMP(object_smob) &&
+ ((long) SCM_CAR(object_smob) == object_smob_tag),
+ object_smob, SCM_ARG1, "get-object-attributes");
+
+ object = (struct st_object_smob *)SCM_CDR(object_smob);
+
+ if (object &&
+ object->object) {
+ ATTRIB *pointer;
+
+ pointer = object->object->attribs;
+ w_current = object->world;
+ while (pointer != NULL) {
+ if (pointer->object &&
+ pointer->object->text) {
+ returned = scm_cons (g_make_attrib_smob (w_current, pointer), returned);
+ }
+ pointer = pointer->next;
+ }
+ }
+
+ return returned;
+}
+
+/*! \brief Initialize the framework to support an object smob.
+ * \par Function Description
+ * Initialize the framework to support an object smob.
+ *
+ */
+void g_init_object_smob(void)
+{
+
+ object_smob_tag = scm_make_smob_type("object", sizeof (struct st_object_smob));
+ scm_set_smob_mark(object_smob_tag, 0);
+ scm_set_smob_free(object_smob_tag, g_free_object_smob);
+ scm_set_smob_print(object_smob_tag, g_print_object_smob);
+
+ scm_c_define_gsubr("get-object-attributes", 1, 0, 0, g_get_object_attributes);
+
+ return;
+}
+
+#if 0
+/*! \brief Gets the OBJECT data from the object smob.
+ * \par Function Description
+ * Get the OBJECT data from the object smob.
+ *
+ * \param [in] object_smob The object smob to get the OBJECT data from.
+ * \return The OBJECT data.
+ * \deprecated
+ * \todo check and remove?
+ */
+OBJECT *g_get_object_from_object_smob(SCM object_smob)
+{
+
+ SCM_ASSERT ( SCM_NIMP(object_smob) &&
+ (SCM_CAR(object_smob) == object_smob_tag),
+ object_smob, SCM_ARG1, "get_object_from_object_smob");
+ return ((OBJECT *) (((struct st_object_smob *)SCM_CDR(object_smob))->object));
+}
+
+/*! \brief Get the TOPLEVEL data from the object smob.
+ * \par Function Description
+ * Get the TOPLEVEL data from the object smob.
+ *
+ * \param [in] object_smob The object smob to get the TOPLEVEL data from.
+ * \return The TOPLEVEL data.
+ * \deprecated
+ * \todo check and remove?
+ */
+TOPLEVEL *g_get_toplevel_from_object_smob(SCM object_smob)
+{
+
+ SCM_ASSERT ( SCM_NIMP(object_smob) &&
+ (SCM_CAR(object_smob) == object_smob_tag),
+ object_smob, SCM_ARG1, "get_toplevel_from_object_smob");
+ return ((TOPLEVEL *) (((struct st_object_smob *)SCM_CDR(object_smob))->world));
+}
+#endif
+
+/*! \brief Get the TOPLEVEL and OBJECT data from an object smob.
+ * \par Function Description
+ * Get the TOPLEVEL and OBJECT data from an object smob.
+ *
+ * \param [in] object_smob The object smob to get data from.
+ * \param [out] toplevel The TOPLEVEL to write data to.
+ * \param [out] object The OBJECT to write data to.
+ * \return TRUE on success, FALSE otherwise
+ */
+gboolean g_get_data_from_object_smob(SCM object_smob, TOPLEVEL **toplevel,
+ OBJECT **object)
+{
+
+ if ( (!SCM_NIMP(object_smob)) ||
+ ((long) SCM_CAR(object_smob) != object_smob_tag) ) {
+ return(FALSE);
+ }
+ if (toplevel != NULL) {
+ *toplevel = (TOPLEVEL *)
+ (((struct st_object_smob *)SCM_CDR(object_smob))->world);
+ }
+ if (object != NULL) {
+ *object = (OBJECT *)
+ (((struct st_object_smob *)SCM_CDR(object_smob))->object);
+ }
+ return (TRUE);
+}
1.1 eda/geda/gaf/libgeda/src/gdk-pixbuf-hacks.c
Index: gdk-pixbuf-hacks.c
===================================================================
/* Functions gdk_pixbuf_rotate and gdk_pixbuf_add are taken from gtkam,
and is covered by this copyright. */
/*
* Copyright © 2001 Lutz Müller <lutz@xxxxxxxxxxxx>
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the
* Free Software Foundation, Inc., 59 Temple Place - Suite 330,
* Boston, MA 02111-1307, USA.
*/
/* Taken from gtkam's sources */
#include "config.h"
#ifndef HAS_GTK12
#include <gdk-pixbuf/gdk-pixbuf.h>
#endif
#ifndef HAS_GTK12
/*! \def COPY90 */
#define COPY90 \
if ((r2 < h1) && (c2 < w1)) { \
if ((w1 <= h1) && (r1 < h2)) \
for (i = 0; i < c; i++) \
new_pixels[r1 * rs2 + c1 * c + i] = \
pixels[r2 * rs1 + c2 * c + i]; \
if ((w1 > h1) && (c1 > (w1 - h2))) \
for (i = 0; i < c; i++) \
new_pixels[r1 * rs2 + (c1 - (w1 - h1)) * c + i] = \
pixels[r2 * rs1 + c2 * c + i]; \
}
/*! \def COPY270 */
#define COPY270 \
if ((r2 < h1) && (c2 < w1)) { \
if ((h1 > w1) && (r1 > (h1 - w1))) \
for (i = 0; i < c; i++) \
new_pixels[(r1 - (h1 - w1)) * rs2 + c1 * c + i] = \
pixels[r2 * rs1 + c2 * c + i]; \
if ((h1 <= w1) && (c1 < w2)) \
for (i = 0; i < c; i++) \
new_pixels[r1 * rs2 + c1 * c + i] = \
pixels[r2 * rs1 + c2 * c + i]; \
}
/*! \brief Rotate a GdkPixbuf by a given angle
* \par Function Description
* This function will take a GdkPixbuf and rotate it by the specified angle.
*
* \param [in] pixbuf The pixel buffer to rotate.
* \param [in] angle The rotation angle.
* \return The rotated pixbuf.
*/
GdkPixbuf *gdk_pixbuf_rotate (GdkPixbuf *pixbuf, guint angle)
{
GdkPixbuf *new = NULL;
guint row, col, w1, h1, w2, h2;
guint r1, r2, c1, c2;
guint rs1, rs2;
guint c;
guint i;
guchar *pixels, *new_pixels;
if (pixbuf == NULL) {
return NULL;
}
g_return_val_if_fail (GDK_IS_PIXBUF (pixbuf), NULL);
/* Swapped original definitions, so the picture turns counter-clockwise */
if (angle == 90)
angle = 270;
else if (angle == 270)
angle = 90;
switch (angle) {
case 0:
return (gdk_pixbuf_copy (pixbuf));
case 180:
new = gdk_pixbuf_new (
gdk_pixbuf_get_colorspace (pixbuf),
gdk_pixbuf_get_has_alpha (pixbuf),
gdk_pixbuf_get_bits_per_sample (pixbuf),
gdk_pixbuf_get_width (pixbuf),
gdk_pixbuf_get_height (pixbuf));
break;
case 90:
case 270:
new = gdk_pixbuf_new (
gdk_pixbuf_get_colorspace (pixbuf),
gdk_pixbuf_get_has_alpha (pixbuf),
gdk_pixbuf_get_bits_per_sample (pixbuf),
gdk_pixbuf_get_height (pixbuf),
gdk_pixbuf_get_width (pixbuf));
break;
default:
g_warning ("Rotation by %i not implemented.", angle);
break;
}
rs1 = gdk_pixbuf_get_rowstride (pixbuf);
rs2 = gdk_pixbuf_get_rowstride (new);
c = gdk_pixbuf_get_has_alpha (pixbuf) ? 4 : 3;
w1 = gdk_pixbuf_get_width (pixbuf);
h1 = gdk_pixbuf_get_height (pixbuf);
w2 = gdk_pixbuf_get_width (new);
h2 = gdk_pixbuf_get_height (new);
pixels = gdk_pixbuf_get_pixels (pixbuf);
new_pixels = gdk_pixbuf_get_pixels (new);
/*
* For rotation by 90 or 270, we assume the pixbuf to be a
* square and move (r2,c2) to (r1,c1):
*/
switch (angle) {
case 90:
for (row = 0; row < MAX (w1, h1) / 2; row++) {
for (col = row; col < MAX (w1, h1) - row - 1; col++) {
r1 = row;
c1 = col;
r2 = MAX (w1, h1) - col - 1;
c2 = row;
COPY90;
r1 = r2;
c1 = c2;
r2 = MAX (w1, h1) - row - 1;
c2 = MAX (w1, h1) - col - 1;
COPY90;
r1 = r2;
c1 = c2;
r2 = col;
c2 = MAX (w1, h1) - row - 1;
COPY90;
r1 = r2;
c1 = c2;
r2 = row;
c2 = col;
COPY90;
}
}
break;
case 270:
for (row = 0; row < MAX (w1, h1) / 2; row++) {
for (col = row; col < MAX (w1, h1) - row - 1; col++) {
r1 = row;
c1 = col;
r2 = col;
c2 = MAX (w1, h1) - row - 1;
COPY270;
r1 = r2;
c1 = c2;
r2 = MAX (w1, h1) - row - 1;
c2 = MAX (w1, h1) - col - 1;
COPY270;
r1 = r2;
c1 = c2;
r2 = MAX (w1, h1) - col - 1;
c2 = row;
COPY270;
r1 = r2;
c1 = c2;
r2 = row;
c2 = col;
COPY270;
}
}
break;
case 180:
for (row = 0; row < h1; row++) {
for (col = 0; col < w1; col++) {
r1 = row;
c1 = col;
r2 = h1 - row - 1;
c2 = w1 - col - 1;
for (i = 0; i < c; i++) {
new_pixels[r2 * rs2 + c2 * c + i] =
pixels[r1 * rs1 + c1 * c + i];
}
}
}
break;
default:
g_warning ("Rotation by %i not implemented.", angle);
break;
}
return (new);
}
/*! \brief Maps a GdkPixbuf at a given offset onto another GdkPixbuf.
* \par Function Description
* This function will take a GdkPixbuf and map it onto an existing one
* at the given x/y offset.
*
* \param [in,out] pixbuf The GdkPixbuf to map onto.
* \param [in] offset_x The x offset to start map operation.
* \param [in] offset_y The y offset to start map operation.
* \param [in] pixbuf_to_add The GdkPixbuf to map onto pixbuf.
* \return Updated GdkPixbuf is returned in pixbuf.
*/
void gdk_pixbuf_add (GdkPixbuf *pixbuf, int offset_x, int offset_y,
GdkPixbuf *pixbuf_to_add)
{
guchar *p1, *p2, a1, a2;
guint w1, h1, w2, h2, r1, r2;
guint row, col, i, pos1, pos2;
g_return_if_fail (pixbuf != NULL);
g_return_if_fail (pixbuf_to_add != NULL);
w1 = gdk_pixbuf_get_width (pixbuf);
h1 = gdk_pixbuf_get_height (pixbuf);
w2 = gdk_pixbuf_get_width (pixbuf_to_add);
h2 = gdk_pixbuf_get_height (pixbuf_to_add);
g_return_if_fail (w1 >= offset_x + w2);
g_return_if_fail (h1 >= offset_y + h2);
p1 = gdk_pixbuf_get_pixels (pixbuf);
p2 = gdk_pixbuf_get_pixels (pixbuf_to_add);
r1 = gdk_pixbuf_get_rowstride (pixbuf);
r2 = gdk_pixbuf_get_rowstride (pixbuf_to_add);
for (row = 0; row < h2; row++) {
for (col = 0; col < w2; col++) {
pos1 = (row + offset_y) * r1 + (col + offset_x) * 4;
pos2 = row * r2 + col * 4;
a1 = p1[pos1 + 3];
a2 = p2[pos2 + 3];
for (i = 0; i < 3; i++) {
p1[pos1 + i] *=
((gfloat) (0xff - a2) / (gfloat) 0xff);
p1[pos1 + i] += (p2[pos2 + i] *
((gfloat) a2 / (gfloat) 0xff));
}
p1[pos1 + 3] = MAX (a1, a2);
}
}
}
/*! \note
* The following function was taken from GQview, and is covered by this copyright.
* The name of the function was changed from pixbuf_copy_mirror to
* gdk_pixbuf_mirror_rotate.
*
* GQview
* (C) 2002 John Ellis
*
* Author: John Ellis
*
* This software is released under the GNU General Public License (GNU GPL).
* Please read the included file COPYING for more information.
* This software comes with no warranty of any kind, use at your own risk!
*/
/*! \brief Mirror and flip a GdkPixbuf.
* \par Function Description
* This function will mirror and/or flip the source GdkPixbuf.
* To do a 180 degree rotation, set both mirror and flip to TRUE.
* If mirror and flip are FALSE, the source image is copied.
*
* \param [in] src Source image to operate on.
* \param [in] mirror Mirror image if set to TRUE.
* \param [in] flip Flipped image if set to TRUE.
* \return Updated copy of source image with operations performed.
*/
GdkPixbuf *gdk_pixbuf_mirror_flip(GdkPixbuf *src, gint mirror, gint flip)
{
GdkPixbuf *dest;
gint has_alpha;
gint w, h, srs;
gint drs;
guchar *s_pix;
guchar *d_pix;
guchar *sp;
guchar *dp;
gint i, j;
gint a;
if (!src) return NULL;
w = gdk_pixbuf_get_width(src);
h = gdk_pixbuf_get_height(src);
has_alpha = gdk_pixbuf_get_has_alpha(src);
srs = gdk_pixbuf_get_rowstride(src);
s_pix = gdk_pixbuf_get_pixels(src);
dest = gdk_pixbuf_new(GDK_COLORSPACE_RGB, has_alpha, 8, w, h);
drs = gdk_pixbuf_get_rowstride(dest);
d_pix = gdk_pixbuf_get_pixels(dest);
a = has_alpha ? 4 : 3;
for (i = 0; i < h; i++)
{
sp = s_pix + (i * srs);
if (flip)
{
dp = d_pix + ((h - i - 1) * drs);
}
else
{
dp = d_pix + (i * drs);
}
if (mirror)
{
dp += (w - 1) * a;
for (j = 0; j < w; j++)
{
*(dp++) = *(sp++); /* r */
*(dp++) = *(sp++); /* g */
*(dp++) = *(sp++); /* b */
if (has_alpha) *(dp) = *(sp++); /* a */
dp -= (a + 3);
}
}
else
{
for (j = 0; j < w; j++)
{
*(dp++) = *(sp++); /* r */
*(dp++) = *(sp++); /* g */
*(dp++) = *(sp++); /* b */
if (has_alpha) *(dp++) = *(sp++); /* a */
}
}
}
return dest;
}
#endif
1.1 eda/geda/gaf/libgeda/src/i_vars.c
Index: i_vars.c
===================================================================
/* gEDA - GPL Electronic Design Automation
* libgeda - gEDA's Library
* Copyright (C) 1998-2000 Ales V. Hvezda
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
*/
#include <config.h>
#include <stdio.h>
#include <gtk/gtk.h>
#include <libguile.h>
#include "defines.h"
#include "struct.h"
#include "globals.h"
#include "o_types.h"
#include "colors.h"
#include "papersizes.h"
#include "i_vars.h"
#include "../include/prototype.h"
#ifdef HAVE_LIBDMALLOC
#include <dmalloc.h>
#endif
/*! \def INIT_STR(w, name, str) */
#define INIT_STR(w, name, str) { \
if ((w)->name) { \
free((w)->name); \
} \
(w)->name = g_strdup(((default_ ## name) != NULL) ? \
(default_ ## name) : (str)); \
}
/* \note
* Kazu Hirata <kazu@xxxxxxxx> on July 16, 1999 - Added these absolute
* defaults used when default_... is NULL.
*/
#define DEFAULT_SERIES_NAME "untitled"
#define DEFAULT_UNTITLED_NAME "untitled"
#define DEFAULT_SCHEME_DIRECTORY "./"
#define DEFAULT_FONT_DIRECTORY "../lib/sym/font"
#define DEFAULT_BITMAP_DIRECTORY "../lib/bitmaps"
#define DEFAULT_BUS_RIPPER_SYMNAME "busripper-1.sym"
#define DEFAULT_POSTSCRIPT_PROLOG "prolog.ps"
#define DEFAULT_ALWAYS_PROMOTE_ATTRIBUTES ""
int default_init_right = WIDTH_C;
int default_init_bottom = HEIGHT_C;
char *default_series_name = NULL;
char *default_untitled_name = NULL;
char *default_font_directory = NULL;
char *default_scheme_directory = NULL;
char *default_bitmap_directory = NULL;
char *default_bus_ripper_symname = NULL;
char *default_postscript_prolog = NULL;
char *default_always_promote_attributes = NULL;
/*! \brief Initialize variables in TOPLEVEL object
* \par Function Description
* This function will initialize variables to default values.
*
* \param [out] w_current The TOPLEVEL object to be updated.
*
*/
void i_vars_libgeda_set(TOPLEVEL *w_current)
{
w_current->init_right = default_init_right;
w_current->init_bottom = default_init_bottom;
/* you cannot free the default* strings here since new windows */
/* need them */
INIT_STR(w_current, series_name , DEFAULT_SERIES_NAME );
INIT_STR(w_current, untitled_name , DEFAULT_UNTITLED_NAME );
INIT_STR(w_current, font_directory , DEFAULT_FONT_DIRECTORY );
INIT_STR(w_current, scheme_directory, DEFAULT_SCHEME_DIRECTORY);
INIT_STR(w_current, bitmap_directory, DEFAULT_BITMAP_DIRECTORY);
INIT_STR(w_current, bus_ripper_symname, DEFAULT_BUS_RIPPER_SYMNAME);
INIT_STR(w_current, postscript_prolog, DEFAULT_POSTSCRIPT_PROLOG);
INIT_STR(w_current, always_promote_attributes, DEFAULT_ALWAYS_PROMOTE_ATTRIBUTES);
}
/*! \brief Set all names in TOPLEVEL object to default.
* \par Function Description
* This function will set all of the names in the TOPLEVEL w_current variable
* to their default.
*
* \param [out] w_current The TOPLEVEL object to set to defaults.
*
*/
void i_vars_setnames(TOPLEVEL *w_current)
{
w_current->series_name = g_strdup (DEFAULT_SERIES_NAME );
w_current->untitled_name = g_strdup (DEFAULT_UNTITLED_NAME );
w_current->font_directory = g_strdup (DEFAULT_FONT_DIRECTORY );
w_current->scheme_directory = g_strdup (DEFAULT_SCHEME_DIRECTORY);
w_current->bitmap_directory = g_strdup (DEFAULT_BITMAP_DIRECTORY);
w_current->bus_ripper_symname = g_strdup (DEFAULT_BUS_RIPPER_SYMNAME);
w_current->always_promote_attributes = g_strdup (DEFAULT_ALWAYS_PROMOTE_ATTRIBUTES);
}
/*! \brief Free default names
* \par Function Description
* This function will free all of the default variables for libgeda.
*
*/
void i_vars_freenames()
{
free(default_series_name);
free(default_untitled_name);
free(default_font_directory);
free(default_scheme_directory);
free(default_bitmap_directory);
free(default_bus_ripper_symname);
free(default_postscript_prolog);
free(default_always_promote_attributes);
}
1.1 eda/geda/gaf/libgeda/src/libgeda.c
Index: libgeda.c
===================================================================
/* gEDA - GPL Electronic Design Automation
* libgeda - gEDA's library
* Copyright (C) 1998, 1999, 2000 Kazu Hirata / Ales Hvezda
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
*/
#include <config.h>
#include <stdio.h>
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_STRARG_H
#include <stdarg.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#include <gtk/gtk.h>
#include <libguile.h>
#include "defines.h"
#include "struct.h"
#include "globals.h"
#include "../include/prototype.h"
#ifdef HAVE_LIBDMALLOC
#include <dmalloc.h>
#endif
/*! \brief Perform runtime initialization of libgeda library.
* \par Function Description
* This function is responsible for making sure that any runtime
* initialization is done for all the libgeda routines. It should
* be called before any other libgeda functions are called.
*
*/
void libgeda_init(void)
{
char *new_data=NULL;
char *geda_data = getenv("GEDADATA");
/* This stuff reverted on 2.17.2005 by SDB in response to W. Hoch. */
if (geda_data == NULL) {
new_data = g_strdup_printf("GEDADATA=%s", GEDADATADIR);
putenv(new_data);
/*free(new_data); putenv takes over the memory? */
/* We'll use this someday. . . . . */
/* g_setenv ("GEDADATA", GEDADATADIR, FALSE); */ /* requires glib-2.4.* */
}
s_toplevel_init ();
s_clib_init();
s_slib_init();
s_menu_init();
s_attrib_init();
s_color_init();
o_text_init();
g_register_libgeda_funcs();
}
1.12 +879 -678 eda/geda/gaf/libgeda/src/m_basic.c
(In the diff below, changes in quantity of whitespace are not shown.)
Index: m_basic.c
===================================================================
RCS file: m_basic.c
diff -N m_basic.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ m_basic.c 5 Jul 2006 03:13:38 -0000 1.12
@@ -0,0 +1,1105 @@
+/* gEDA - GPL Electronic Design Automation
+ * libgeda - gEDA's library
+ * Copyright (C) 1998-2000 Ales V. Hvezda
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+#include <config.h>
+
+#include <stdio.h>
+#include <math.h>
+
+#include <gtk/gtk.h>
+#include <libguile.h>
+
+#include "defines.h"
+#include "struct.h" /* why should I include these hack, just for prototype ? */
+#include "globals.h"
+
+#include "../include/prototype.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+/*! \brief Convert a x coordinate to mils.
+ * \par Function Description
+ * Convert a x coordinate to mils.
+ *
+ * \param [in] w_current The TOPLEVEL object
+ * \param [in] val The x coordinate to convert
+ * \return The coordinate value in mils.
+ */
+int mil_x(TOPLEVEL *w_current, int val)
+{
+ double i;
+ double fval;
+ int j;
+
+#if 0 /* removed for speed improvements */
+ double fw0,fw1,fw,fval;
+ fw1 = w_current->page_current->right;
+ fw0 = w_current->page_current->left;
+ fw = w_current->width;
+#endif
+
+ fval = val;
+ i = fval * w_current->page_current->to_world_x_constant +
+ w_current->page_current->left;
+
+ /* i -= mil_x_tw2;
+ i = ((i) / 100 ) * 100; I don't think we need this
+ i += mil_x_tw1;*/
+
+
+#ifdef HAS_RINT
+ j = rint(i);
+#else
+ j = i;
+#endif
+
+ return(j);
+}
+
+/*! \brief Convert a y coordinate to mils
+ * \par Function Description
+ * Convert a y coordinate to mils
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] val The y coordinate to convert.
+ * \return The coordinate value in mils.
+ */
+int mil_y(TOPLEVEL *w_current, int val)
+{
+ double i;
+ double fval;
+ int j;
+
+#if 0 /* removed for speed improvements */
+ double fw0,fw1,fw,fval;
+ fw1 = w_current->page_current->bottom;
+ fw0 = w_current->page_current->top;
+ fw = w_current->height;
+#endif
+
+ fval = w_current->height - val;
+ i = fval * w_current->page_current->to_world_y_constant +
+ w_current->page_current->top;
+
+ /* i = ((i) / 100 ) * 100; I don't think we need this */
+ /* i += mil_y_tw1; or this*/
+
+#ifdef HAS_RINT
+ j = rint(i);
+#else
+ j = i;
+#endif
+
+ return(j);
+}
+
+/*! \brief Convert a x coordinate to pixels.
+ * \par Function Description
+ * Convert a x coordinate to pixels.
+ *
+ * \param [in] w_current The TOPLEVEL object
+ * \param [in] val The x coordinate to convert
+ * \return The coordinate value in pixels.
+ */
+int pix_x(TOPLEVEL *w_current, int val)
+{
+
+ double i;
+ int j;
+
+#if 0 /* removed for speed */
+ double fs,f0,f1,f;
+ f0 = w_current->page_current->left;
+ f1 = w_current->page_current->right;
+ fs = w_current->width;
+ f = w_current->width / (f1 - f0);
+#endif
+
+
+ i = w_current->page_current->to_screen_x_constant *
+ (double)(val - w_current->page_current->left);
+
+#ifdef HAS_RINT
+ j = rint(i);
+#else
+ j = i;
+#endif
+
+ /* this is a temp solution to fix the wrapping associated with */
+ /* X coords being greated/less than than 2^15 */
+ if (j >= 32768) {
+ j = 32767;
+ }
+ if (j <= -32768) {
+ j = -32767;
+ }
+
+ return(j);
+}
+
+/*! \brief Convert a y coordinate to pixels.
+ * \par Function Description
+ * Convert a y coordinate to pixels.
+ *
+ * \param [in] w_current The TOPLEVEL object
+ * \param [in] val The y coordinate to convert
+ * \return The coordinate value in pixels.
+ */
+int pix_y(TOPLEVEL *w_current, int val)
+{
+ double i;
+ int j;
+
+#if 0 /* removed for speed */
+ double fs,f0,f1,f;
+ f0 = w_current->page_current->top;
+ f1 = w_current->page_current->bottom;
+ fs = w_current->height;
+ f = fs / (f1 - f0); /* fs was w_current->height */
+#endif
+ i = w_current->height - (
+ w_current->page_current->to_screen_y_constant *
+ (double)(val - w_current->page_current->top));
+
+#ifdef HAS_RINT
+ j = rint(i);
+#else
+ j = i;
+#endif
+
+ /* this is a temp solution to fix the wrapping associated with */
+ /* X coords being greated/less than than 2^15 */
+ if (j >= 32768) {
+ j = 32767;
+ }
+ if (j <= -32768) {
+ j = -32767;
+ }
+
+ return(j);
+}
+
+/*! \brief Transform WORLD coordinates to SCREEN coordinates
+ * \par Function Description
+ * This function takes in WORLD x/y coordinates and
+ * transforms them to SCREEN x/y coordinates.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] x The x coordinate in WORLD units.
+ * \param [in] y The y coordinate in WORLD units.
+ * \param [out] mil_x The x coordinate in SCREEN units.
+ * \param [out] mil_y The y coordinate in SCREEN units.
+ * \note Question: why are we returning in mil_x and mil_y
+ * if this is WORLD to SCREEN shouldn't SCREEN
+ * coordinates be returned in x and y?
+ */
+void WORLDtoSCREEN(TOPLEVEL *w_current, int x, int y, int *mil_x, int *mil_y)
+{
+ *mil_x = pix_x(w_current, x);
+ *mil_y = pix_y(w_current, y);
+}
+
+/*! \brief Transform WORLD coordinates to WORLD coordinates
+ * \par Function Description
+ * This function takes in SCREEN x/y coordinates and
+ * transforms them to WORLD x/y coordinates.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] mx The x coordinate in SCREEN units.
+ * \param [in] my The y coordinate in SCREEN units.
+ * \param [out] x The x coordinate in WORLD units.
+ * \param [out] y The y coordinate in WORLD units.
+ * \note Question: why are we returning in x and y
+ * if this is SCREEN to WORLD shouldn't WORLD
+ * coordinates be returned in mx and my?
+ */
+void SCREENtoWORLD(TOPLEVEL *w_current, int mx, int my, int *x, int *y)
+{
+ if (w_current->snap) {
+ *x = snap_grid(w_current, mil_x(w_current, mx));
+ *y = snap_grid(w_current, mil_y(w_current, my));
+ } else {
+ *x = mil_x(w_current, mx);
+ *y = mil_y(w_current, my);
+ }
+
+#if 0
+ *x = mil_x(w_current, mx);
+ *y = mil_y(w_current, my);
+#endif
+
+}
+
+/*! \brief Find the closest grid coordinate.
+ * \par Function Description
+ * This function snaps the current input coordinate to the
+ * closest grid coordinate.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] input The coordinate to snap.
+ * \return The closest grid coordinate to the input.
+ */
+int snap_grid(TOPLEVEL *w_current, int input)
+{
+ int p, m, n;
+ int sign, value, snap_grid;
+
+ if (!w_current->snap) {
+ return(input);
+ }
+
+
+ snap_grid = w_current->snap_size;
+
+ /* this code was inspired from killustrator, it's much simpler than mine */
+ sign = ( input < 0 ? -1 : 1 );
+ value = abs(input);
+
+ p = value / snap_grid;
+ m = value % snap_grid;
+ n = p * snap_grid;
+ if (m > snap_grid / 2)
+ n += snap_grid;
+
+#if DEBUG
+ printf("p: %d\n", p);
+ printf("m: %d\n", m);
+ printf("m > snap_grid / 2: %d\n", (m > snap_grid / 2));
+ printf("n: %d\n", n);
+ printf("n*s: %d\n", n*sign);
+#endif
+
+ return(sign*n);
+
+#if 0 /* working snap code, crude, slow */
+ int interm;
+ int final;
+ int power;
+ int itop;
+
+ power = snap_grid;
+ itop = input / power;
+ interm = abs(input % power);
+
+ if (interm > 0 && interm < snap_grid/2) {
+ interm = 0;
+ } else if (interm >= snap_grid/2 && interm <= snap_grid) {
+ interm = snap_grid;
+ }
+
+ if (input >= 0) {
+ final = itop*snap_grid+interm;
+ } else if (input < 0) {
+ final = itop*snap_grid-interm;
+ }
+
+ return(final);
+#endif
+
+}
+
+/*! \brief Get absolute SCREEN coordinate.
+ * \par Function Description
+ * Get absolute SCREEN coordinate.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] val The coordinate to convert.
+ * \return The converted SCREEN coordinate.
+ */
+int SCREENabs(TOPLEVEL *w_current, int val)
+{
+ double fs,f0,f1,f;
+
+ double i;
+ int j;
+
+ f0 = w_current->page_current->left;
+ f1 = w_current->page_current->right;
+ fs = w_current->width;
+ f = w_current->width / (f1 - f0);
+ i = f * (double)(val);
+
+#ifdef HAS_RINT
+ j = rint(i);
+#else
+ j = i;
+#endif
+
+ return(j);
+
+}
+
+/*! \brief Get absolute WORLD coordinate.
+ * \par Function Description
+ * Get absolute WORLD coordinate.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] val The coordinate to convert.
+ * \return The converted WORLD coordinate.
+ */
+int WORLDabs(TOPLEVEL *w_current, int val)
+{
+ double fw0,fw1,fw,fval;
+
+ double i;
+ int j;
+
+ fw1 = w_current->page_current->right;
+ fw0 = w_current->page_current->left;
+ fw = w_current->width;
+ fval = val;
+ i = fval * (fw1 - fw0) / fw;
+
+ /* i -= mil_x_tw2;
+ i = ((i) / 100 ) * 100; I don't think we need this
+ i += mil_x_tw1;*/
+
+
+#ifdef HAS_RINT
+ j = rint(i);
+#else
+ j = i;
+#endif
+
+ return(j);
+}
+
+/*! \brief Set the contraints for the current page.
+ * \par Function Description
+ * This function will set the current page constraints.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in,out] page The PAGE object to set constraints on.
+ * \param [in] xmin The minimum x coordinate for the page.
+ * \param [in] xmax The maximum x coordinate for the page.
+ * \param [in] ymin The minimum y coordinate for the page.
+ * \param [in] ymax The maximum y coordinate for the page.
+ */
+void set_window(TOPLEVEL *w_current, PAGE *page,
+ int xmin, int xmax, int ymin, int ymax)
+{
+ double fs,f0,f1;
+ double fw0,fw1,fw;
+
+ page->left = xmin;
+ page->right = xmax;
+ page->top = ymin;
+ page->bottom = ymax;
+
+ /* now do the constant setups */
+
+ /* pix_x */
+ f0 = page->left;
+ f1 = page->right;
+ fs = w_current->width;
+ page->to_screen_x_constant = fs / (f1 - f0);
+
+ /* pix_y */
+ f0 = page->top;
+ f1 = page->bottom;
+ fs = w_current->height;
+ page->to_screen_y_constant = fs / (f1 - f0);
+
+ /* mil_x */
+ fw1 = page->right;
+ fw0 = page->left;
+ fw = w_current->width;
+ page->to_world_x_constant = (fw1 - fw0) / fw;
+
+ /* mil_y */
+ fw1 = page->bottom;
+ fw0 = page->top;
+ fw = w_current->height;
+ page->to_world_y_constant = (fw1 - fw0) / fw;
+}
+
+
+/*! \brief Get the grid x coordinate for snap.
+ * \par Function Description
+ * Get the grid x coordinate for snap.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] in The x coordinate.
+ * \return The closest grid coordinate to in.
+ */
+int fix_x(TOPLEVEL *w_current, int in)
+{
+ int value;
+ int ret;
+
+ if (in > w_current->width) {
+ in = w_current->width;
+ }
+
+ if (!w_current->snap)
+ return(in);
+
+ value = mil_x(w_current, in);
+
+ ret = pix_x(w_current, snap_grid(w_current, value));
+ return(ret);
+}
+
+/*! \brief Get the grid y coordinate for snap.
+ * \par Function Description
+ * Get the grid y coordinate for snap.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] in The y coordinate.
+ * \return The closest grid coordinate to in.
+ */
+int fix_y(TOPLEVEL *w_current, int in)
+{
+ int value;
+ int ret;
+
+ if (in > w_current->height) {
+ in = w_current->height;
+ }
+
+ if (!w_current->snap)
+ return(in);
+
+
+ value = mil_y(w_current, in);
+ ret = pix_y(w_current, snap_grid(w_current, value));
+ return(ret);
+}
+
+/*! \brief Checks if a point is snapped.
+ * \par Function Description
+ * This function checks if a point is snapped.
+ *
+ * \param [in] val The point to check.
+ * \return 0 if point (x) is snapped, non-zero otherwise
+ *
+ * \note This function is unused for now.
+ */
+int on_snap(int val)
+{
+ return( (val / 100)*100 - val);
+}
+
+/*! \brief */
+typedef struct st_halfspace HALFSPACE;
+/*! \brief */
+typedef struct st_point sPOINT;
+
+/*! \brief */
+struct st_halfspace {
+ int left; /* these are booleans */
+ int top;
+ int right;
+ int bottom;
+};
+
+/*! \brief */
+struct st_point {
+ int x, y;
+};
+
+/* \note
+ * encode_halfspace and clip are part of the cohen-sutherland clipping
+ * algorithm. They are used to determine if an object is visible or not
+ */
+/*! \brief Encode SCREEN coordinates as halfspace matrix.
+ * \par Function Description
+ * This function takes a point and checks if it is in the bounds
+ * of the current TOPLEVEL object's page coordinates. It
+ * handles points with SCREEN coordinates.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] point The point in SCREEN coordinates to be checked.
+ * \param [out] halfspace The created HALFSPACE structure.
+ *
+ * \warning halfspace must be allocated before this function is called
+ */
+static void SCREENencode_halfspace(TOPLEVEL *w_current, sPOINT *point, HALFSPACE *halfspace)
+{
+ halfspace->left = point->x < 0;
+ halfspace->right = point->x > w_current->width;
+ halfspace->bottom = point->y > w_current->height;
+ halfspace->top = point->y < 0;
+}
+
+/*! \brief Encode WORLD coordinates as halfspace matrix.
+ * \par Function Description
+ * This function takes a point and checks if it is in the bounds
+ * of the current TOPLEVEL object's page coordinates. It
+ * handles points with WORLD coordinates.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] point The point in WORLD coordinates to be checked.
+ * \param [out] halfspace The created HALFSPACE structure.
+ *
+ * \warning halfspace must be allocated before this function is called
+ */
+static void WORLDencode_halfspace(TOPLEVEL *w_current, sPOINT *point, HALFSPACE *halfspace)
+{
+ halfspace->left = point->x < w_current->page_current->left;
+ halfspace->right = point->x > w_current->page_current->right;
+ halfspace->bottom = point->y > w_current->page_current->bottom;
+ halfspace->top = point->y < w_current->page_current->top;
+}
+
+/*! \brief Calculate the cliping region for a set of coordinates.
+ * \par Function Description
+ * This function will check the provided set of coordinates to see if
+ * they fall within a clipping region. If they do the coordinates will
+ * be changed to reflect only the region no covered by the clipping window.
+ * All coordinates should be in SCREEN units.
+ *
+ * \param [in] w_current The current TOPLEVEL object.
+ * \param [in,out] x1 x coordinate of the first screen point.
+ * \param [in,out] y1 y coordinate of the first screen point.
+ * \param [in,out] x2 x coordinate of the second screen point.
+ * \param [in,out] y2 y coordinate of the second screen point.
+ * \return TRUE if coordinates are now visible, FALSE otherwise.
+ */
+int SCREENclip_change(TOPLEVEL *w_current,int *x1, int *y1, int *x2, int *y2)
+{
+ HALFSPACE half1, half2;
+ HALFSPACE tmp_half;
+ sPOINT tmp_point;
+ sPOINT point1, point2;
+ float slope;
+ int in1, in2, done;
+ int visible;
+ int w_l, w_t, w_r, w_b;
+
+ point1.x = *x1;
+ point1.y = *y1;
+ point2.x = *x2;
+ point2.y = *y2;
+
+
+ w_l = 0;
+ w_t = 0;
+ w_r = w_current->width;
+ w_b = w_current->height;
+
+
+ done = FALSE;
+ visible = FALSE;
+
+ do {
+ SCREENencode_halfspace(w_current, &point1, &half1);
+ SCREENencode_halfspace(w_current, &point2, &half2);
+
+#if DEBUG
+ printf("starting loop\n");
+ printf("1 %d %d %d %d\n", half1.left, half1.top, half1.right, half1.bottom);
+ printf("2 %d %d %d %d\n", half2.left, half2.top, half2.right, half2.bottom);
+#endif
+
+ in1 = (!half1.left) &&
+ (!half1.top) &&
+ (!half1.right) &&
+ (!half1.bottom);
+
+ in2 = (!half2.left) &&
+ (!half2.top) &&
+ (!half2.right) &&
+ (!half2.bottom);
+
+
+ if (in1 && in2) { /* trivally accept */
+ done = TRUE;
+ visible = TRUE;
+ } else if ( ((half1.left && half2.left) ||
+ (half1.right && half2.right)) ||
+ ((half1.top && half2.top) ||
+ (half1.bottom && half2.bottom)) ) {
+ done = TRUE; /* trivially reject */
+ visible = FALSE;
+ } else { /* at least one point outside */
+ if (in1) {
+ tmp_half = half1;
+ half1 = half2;
+ half2 = tmp_half;
+
+ tmp_point = point1;
+ point1 = point2;
+ point2 = tmp_point;
+ }
+
+ if (point2.x == point1.x) { /* vertical line */
+ if (half1.top) {
+ point1.y = w_t;
+ } else if (half1.bottom) {
+ point1.y = w_b;
+ }
+ } else { /* not a vertical line */
+
+ /* possible fix for alpha core dumping */
+ /* assume the object is visible */
+ if ((point2.x - point1.x) == 0) {
+ return(TRUE);
+ }
+
+ slope = (float) (point2.y - point1.y) /
+ (float) (point2.x - point1.x);
+
+ /* possible fix for alpha core dumping */
+ /* assume the object is visible */
+ if (slope == 0.0) {
+ return(TRUE);
+ }
+
+ if (half1.left) {
+ point1.y = point1.y +
+ (w_l - point1.x) * slope;
+ point1.x = w_l;
+ } else if (half1.right) {
+ point1.y = point1.y +
+ (w_r - point1.x) * slope;
+ point1.x = w_r;
+ } else if (half1.bottom) {
+ point1.x = point1.x +
+ (w_b - point1.y) / slope;
+ point1.y = w_b;
+ } else if (half1.top) {
+ point1.x = point1.x +
+ (w_t - point1.y) / slope;
+ point1.y = w_t;
+ }
+ } /* end of not a vertical line */
+ } /* end of at least one outside */
+ } while (!done);
+
+ /*printf("after: %d %d %d %d\n", point1.x, point1.y, point2.x, point2.y);*/
+ *x1 = point1.x;
+ *y1 = point1.y;
+ *x2 = point2.x;
+ *y2 = point2.y;
+ return(visible);
+}
+
+/*! \brief Check if a set of coordinates are within a clipping region
+ * \par Function Description
+ * This function will check if the given set of coordinates
+ * are within a clipping region. No action will be taken to change
+ * the coordinates.
+ *
+ * \param [in] w_current The current TOPLEVEL object.
+ * \param [in,out] x1 x coordinate of the first screen point.
+ * \param [in,out] y1 y coordinate of the first screen point.
+ * \param [in,out] x2 x coordinate of the second screen point.
+ * \param [in,out] y2 y coordinate of the second screen point.
+ * \return TRUE if coordinates are now visible, FALSE otherwise.
+ */
+int clip_nochange(TOPLEVEL *w_current,int x1, int y1, int x2, int y2)
+{
+ HALFSPACE half1, half2;
+ HALFSPACE tmp_half;
+ sPOINT tmp_point;
+ sPOINT point1, point2;
+ float slope;
+ int in1, in2, done;
+ int visible;
+ int w_l, w_t, w_r, w_b;
+
+ point1.x = x1;
+ point1.y = y1;
+ point2.x = x2;
+ point2.y = y2;
+
+ /*printf("before: %d %d %d %d\n", x1, y1, x2, y2);*/
+
+ w_l = w_current->page_current->left;
+ w_t = w_current->page_current->top;
+ w_r = w_current->page_current->right;
+ w_b = w_current->page_current->bottom;
+
+ done = FALSE;
+ visible = FALSE;
+
+ do {
+ WORLDencode_halfspace(w_current, &point1, &half1);
+ WORLDencode_halfspace(w_current, &point2, &half2);
+
+#if DEBUG
+ printf("starting loop\n");
+ printf("1 %d %d %d %d\n", half1.left, half1.top, half1.right, half1.bottom);
+ printf("2 %d %d %d %d\n", half2.left, half2.top, half2.right, half2.bottom);
+#endif
+
+ in1 = (!half1.left) &&
+ (!half1.top) &&
+ (!half1.right) &&
+ (!half1.bottom);
+
+ in2 = (!half2.left) &&
+ (!half2.top) &&
+ (!half2.right) &&
+ (!half2.bottom);
+
+
+ if (in1 && in2) { /* trivally accept */
+ done = TRUE;
+ visible = TRUE;
+ } else if ( ((half1.left && half2.left) ||
+ (half1.right && half2.right)) ||
+ ((half1.top && half2.top) ||
+ (half1.bottom && half2.bottom)) ) {
+ done = TRUE; /* trivially reject */
+ visible = FALSE;
+ } else { /* at least one point outside */
+ if (in1) {
+ tmp_half = half1;
+ half1 = half2;
+ half2 = tmp_half;
+
+ tmp_point = point1;
+ point1 = point2;
+ point2 = tmp_point;
+ }
+
+ if (point2.x == point1.x) { /* vertical line */
+ if (half1.top) {
+ point1.y = w_t;
+ } else if (half1.bottom) {
+ point1.y = w_b;
+ }
+ } else { /* not a vertical line */
+
+ /* possible fix for alpha core dumping */
+ /* assume the object is visible */
+ if ((point2.x - point1.x) == 0) {
+ return(TRUE);
+ }
+
+ slope = (float) (point2.y - point1.y) /
+ (float) (point2.x - point1.x);
+
+ /* possible fix for alpha core dumping */
+ /* assume the object is visible */
+ if (slope == 0.0) {
+ return(TRUE);
+ }
+
+ if (half1.left) {
+ point1.y = point1.y +
+ (w_l - point1.x) * slope;
+ point1.x = w_l;
+ } else if (half1.right) {
+ point1.y = point1.y +
+ (w_r - point1.x) * slope;
+ point1.x = w_r;
+ } else if (half1.bottom) {
+ point1.x = point1.x +
+ (w_b - point1.y) / slope;
+ point1.y = w_b;
+ } else if (half1.top) {
+ point1.x = point1.x +
+ (w_t - point1.y) / slope;
+ point1.y = w_t;
+ }
+ } /* end of not a vertical line */
+ } /* end of at least one outside */
+ } while (!done);
+
+ return(visible);
+}
+
+/*! \brief Check if a bounding box is visible on the screen.
+ * \par Function Description
+ * This function checks if a given bounding box is visible on the screen.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] wleft Left coordinate of the bounding box.
+ * \param [in] wtop Top coordinate of the bounding box.
+ * \param [in] wright Right coordinate of the bounding box.
+ * \param [in] wbottom Bottom coordinate of the bounding box.
+ * \return TRUE if bounding box is visible, FALSE otherwise
+ */
+int visible(TOPLEVEL *w_current, int wleft, int wtop, int wright, int wbottom)
+{
+ int visible=FALSE;
+
+ /* don't do object clipping if this is false */
+ if (!w_current->object_clipping) {
+ return(TRUE);
+ }
+
+ visible = clip_nochange(w_current, wleft, wtop, wright, wtop);
+
+#if DEBUG
+ printf("vis1 %d\n", visible);
+#endif
+
+ if (!visible) {
+ visible = clip_nochange(w_current, wleft, wbottom, wright, wbottom);
+ } else {
+ return(visible);
+ }
+
+#if DEBUG
+ printf("vis2 %d\n", visible);
+#endif
+
+ if (!visible) {
+ visible = clip_nochange(w_current, wleft, wtop, wleft, wbottom);
+ } else {
+ return(visible);
+ }
+
+#if DEBUG
+ printf("vis3 %d\n", visible);
+#endif
+
+ if (!visible) {
+ visible = clip_nochange(w_current, wright, wtop, wright, wbottom);
+ } else {
+ return(visible);
+ }
+
+#if DEBUG
+ printf("vis4 %d\n", visible);
+#endif
+
+#if DEBUG
+ printf("%d %d %d\n", wleft, w_current->page_current->top, wright);
+ printf("%d %d %d\n", wtop, w_current->page_current->top, wbottom);
+ printf("%d %d %d\n", wleft, w_current->page_current->right, wright);
+ printf("%d %d %d\n", wtop, w_current->page_current->bottom, wbottom);
+#endif
+
+ /* now check to see if bounding box encompasses the entire viewport */
+ if (w_current->page_current->left >= wleft &&
+ w_current->page_current->left <= wright &&
+ w_current->page_current->top <= wtop &&
+ w_current->page_current->top >= wbottom ) {
+ /*w_current->page_current->right >= wleft &&
+ w_current->page_current->right <= wright &&
+ w_current->page_current->bottom <= wtop &&
+ w_current->page_current->bottom >= wbottom ) {*/
+ visible = 1;
+ }
+
+#if DEBUG
+ printf("vis5 %d\n", visible);
+#endif
+
+ return(visible);
+}
+
+/*! \brief Rotate a point by an arbitrary angle.
+ * \par Function Description
+ * This function will rotate a point coordinate by an arbitrary angle
+ * and return the new coordinate in the newx and newy parameters.
+ *
+ * \param [in] x Input point x coordinate.
+ * \param [in] y Input point y coordinate.
+ * \param [in] angle Angle to rotate in degrees.
+ * \param [out] newx Output point x coordinate.
+ * \param [out] newy Output point y coordinate.
+ */
+void rotate_point(int x, int y, int angle, int *newx, int *newy)
+{
+ double costheta, sintheta;
+ double rad;
+
+ rad = angle*M_PI/180;
+
+ costheta = cos(rad);
+ sintheta = sin(rad);
+
+ *newx = x * costheta - y * sintheta;
+ *newy = x * sintheta + y * costheta;
+}
+
+/*! \brief Rotate point in 90 degree increments only.
+ * \par Function Description
+ * This function takes a point coordinate and rotates it by
+ * 90 degrees at a time. The new point coordinate is returned
+ * in newx and newy.
+ *
+ * \param [in] x Input point x coordinate.
+ * \param [in] y Input point y coordinate.
+ * \param [in] angle Angle to rotate by (90 degree increments only).
+ * \param [out] newx Output point x coordinate.
+ * \param [out] newy Output point y coordinate.
+ */
+void rotate_point_90(int x, int y, int angle, int *newx, int *newy)
+{
+ double costheta=1;
+ double sintheta=0;
+
+ /* I could have used sine/cosine for this, but I want absolute
+ * accuracy */
+ switch(angle) {
+
+ case(0):
+ *newx = x;
+ *newy = y;
+ return;
+ break;
+
+ case(90):
+ costheta = 0;
+ sintheta = 1;
+ break;
+
+ case(180):
+ costheta = -1;
+ sintheta = 0;
+ break;
+
+ case(270):
+ costheta = 0;
+ sintheta = -1;
+ break;
+ }
+
+ *newx = x * costheta - y * sintheta;
+ *newy = x * sintheta + y * costheta;
+
+#if 0 /* fixed rotation */
+
+ *newx = -y ;
+ *newy = x ;
+#endif
+
+}
+
+/*! \brief Convert Paper size to World coordinates.
+ * \par Function Description
+ * This function takes the paper size and converts it to
+ * world coordinates. It supports landscape with a fixed aspect ratio.
+ *
+ * \param [in] width Paper width. (units?)
+ * \param [in] height Paper height. (units?)
+ * \param [in] border Paper border size. (units?)
+ * \param [out] right Right world coordinate. (units?)
+ * \param [out] bottom Bottom world coordinate. (units?)
+ *
+ * \todo Support more modes than just landscape only mode.
+ */
+void PAPERSIZEtoWORLD(int width, int height, int border, int *right, int *bottom)
+{
+ float aspect;
+
+ aspect = (float) width / (float) height;
+
+#if DEBUG
+ printf("%f\n", aspect);
+#endif
+
+ if (aspect < 1.333333333) {
+ /* is this rint really needed? */
+#ifdef HAS_RINT
+ *right = (int) rint(width+border +
+ ((height+border)*1.33333333 - (width+border)));
+#else
+ *right = (int) width+border +
+ ((height+border)*1.33333333 - (width+border));
+#endif
+ *bottom = height+border;
+ } else {
+ *right = (int) width+border;
+ *bottom = (int) height+border + ((width+border)/1.33333333 - (height+border));
+ }
+
+#if DEBUG
+ aspect = (float) *right / (float) *bottom;
+ printf("%f\n", aspect);
+#endif
+
+}
+
+/*! \deprecated
+ * \brief Get the number of zoom's done.
+ * \par Function Description
+ * This function returns the number of zoom's that have been done.
+ * It is computed from the zoom_factor since, the zoom_factor is
+ * actually the magnification level.
+ *
+ * \param [in] zoom_factor The current zoom factor being used.
+ * \return The number of zoom's done so far.
+ */
+#if 0 /* no longer used at all */
+int return_zoom_number(int zoom_factor)
+{
+ double check=0;
+ double factor;
+ int i=0;
+
+ if (zoom_factor != 0) {
+ factor = zoom_factor;
+ check = pow(2, i);
+ while( check != factor && check < factor) {
+ i++;
+ check = pow(2, i);
+ }
+ } else {
+ return(0);
+ }
+
+ return(i);
+
+#if 0 /* delete eventually */
+ if (zoom_factor > 0) {
+ return(log(zoom_factor)+2);
+ /* return(log(zoom_factor+1));*/
+ } else {
+ return(1);
+ }
+#endif
+}
+#endif
+
+/*! \brief Rounds numbers by a power of 10.
+ * \par Function Description
+ * This function will round numbers using a power of 10 method.
+ * For example:
+ * 1235 rounds to 1000
+ * 670 rounds to 500
+ * 0.234 rounds to 0.2
+ * integer values would be enough if there are no numbers smaller than 1 (hw)
+ *
+ * \param [in] unrounded The number to be rounded.
+ * \return The rounded number.
+ */
+/* rounds for example 1235 to 1000, 670 to 500, 0.234 to 0.2 ...
+int would be enough if there are no numbers smaller 1 (hw)*/
+double round_5_2_1(double unrounded)
+{
+ int digits;
+ double betw_1_10;
+
+ /*only using the automatic cast */
+ digits = log10(unrounded);
+ /* creates numbers between 1 and 10 */
+ betw_1_10 = unrounded / pow(10,digits);
+
+ if (betw_1_10 < 1.5) {
+ return(pow(10,digits));
+ }
+ if (betw_1_10 > 1.4 && betw_1_10 < 3.5 ) {
+ return(2*pow(10,digits));
+ }
+ if (betw_1_10 > 3.4 && betw_1_10 < 7.5 ) {
+ return(5*pow(10,digits));
+ }
+ else {
+ return(10*pow(10,digits));
+ }
+}
1.27 +1508 -1107eda/geda/gaf/libgeda/src/o_arc_basic.c
(In the diff below, changes in quantity of whitespace are not shown.)
Index: o_arc_basic.c
===================================================================
RCS file: o_arc_basic.c
diff -N o_arc_basic.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ o_arc_basic.c 5 Jul 2006 03:13:38 -0000 1.27
@@ -0,0 +1,1636 @@
+/* gEDA - GPL Electronic Design Automation
+ * libgeda - gEDA's library
+ * Copyright (C) 1998-2000 Ales V. Hvezda
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+#include <config.h>
+
+#include <stdio.h>
+#include <math.h>
+
+#include <gtk/gtk.h>
+#include <libguile.h>
+
+#ifdef HAS_LIBGDGEDA
+#include <gdgeda/gd.h>
+#endif
+
+#include "defines.h"
+#include "struct.h"
+#include "globals.h"
+#include "o_types.h"
+#include "colors.h"
+#include "funcs.h"
+
+#include "../include/prototype.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+/*! \brief
+ * \par Function Description
+ * The function creates a new object of type arc and links it
+ * with the object pointed by parameter object_list. As the
+ * new object is then the last object of the list, its pointer
+ * is returned to update the end of list pointer in the calling function.
+ * The arc is defined by its center in parameters x and y.
+ * The radius parameter specifies the radius of the arc. The start
+ * angle is given by start_angle and the end angle by end_angle.
+ * The line and fill type of the created arc are set to default.
+ *
+ * All dimensions are in world unit, except start_angle and
+ * end_angle in degrees.
+ *
+ * A new object of type OBJECT is allocated. Its type and color
+ * are initilized. The description of the arc characteristics
+ * are stored in a new ARC structure.
+ *
+ * Now fixed for world coordinates.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] object_list
+ * \param [in] type
+ * \param [in] color
+ * \param [in] x
+ * \param [in] y
+ * \param [in] radius
+ * \param [in] start_angle
+ * \param [in] end_angle
+ * \return
+ */
+OBJECT *o_arc_add(TOPLEVEL *w_current, OBJECT *object_list,
+ char type, int color,
+ int x, int y, int radius, int start_angle, int end_angle)
+{
+
+ OBJECT *new_node;
+
+ new_node = s_basic_init_object("arc");
+ new_node->type = type;
+ new_node->color = color;
+
+ new_node->arc = (ARC *) malloc(sizeof(ARC));
+
+ /*! \note
+ * The ARC structure is initialized with the parameters.
+ * A default initialization is performed for the line and
+ * fill type to avoid misunderstood.
+ *
+ * The functions relative to the use of the object are sets.
+ */
+
+ /* World coordinates */
+ new_node->arc->x = x;
+ new_node->arc->y = y;
+ new_node->arc->width = 2 * radius;
+ new_node->arc->height = 2 * radius;
+
+ /* PB : must check the sign of start_angle, end_angle ... */
+ if(end_angle < 0) {
+ start_angle = start_angle + end_angle;
+ end_angle = -end_angle;
+ }
+ if(start_angle < 0) start_angle = 360 + start_angle;
+
+ new_node->arc->start_angle = start_angle;
+ new_node->arc->end_angle = end_angle;
+
+ /* Default init */
+ o_set_line_options(w_current, new_node,
+ END_NONE, TYPE_SOLID, 0, -1, -1);
+ o_set_fill_options(w_current, new_node,
+ FILLING_HOLLOW, -1, -1, -1, -1, -1);
+
+ o_arc_recalc(w_current, new_node);
+
+ /* new_node->graphical = arc; eventually */
+
+ /* \todo questionable cast */
+ new_node->draw_func = (void *) arc_draw_func;
+ /* \todo questionable cast */
+ new_node->sel_func = (void *) select_func;
+
+ /* \note
+ * The new object is linked to the object given in parameter object_list
+ * and then returned as a pointer to the calling function.
+ */
+
+ object_list = (OBJECT *) s_basic_link_object(new_node, object_list);
+
+ return(object_list);
+}
+
+/*! \brief
+ * \par Function Description
+ * This function creates a new object representing an arc.
+ *
+ * The values of the <B>o_current</B> pointed OBJECT are then copied to the new object.
+ *
+ * The arc, the line options are initialized whereas the fill options are
+ * initialized to passive values - as an arc can not be filled.
+ *
+ * The new object is added to the end of the object list given by <B>list_tail</B>.
+ * A pointer on it is returned for update purpose in the calling function.
+ *
+ * \param [in] w_current The TOPLEVEL object
+ * \param [in] list_tail
+ * \param [in] o_current
+ * \return
+ */
+OBJECT *o_arc_copy(TOPLEVEL *w_current, OBJECT *list_tail,
+ OBJECT *o_current)
+{
+ OBJECT *new_obj;
+ ATTRIB *a_current;
+ int color;
+
+ if (o_current->saved_color == -1) {
+ color = o_current->color;
+ } else {
+ color = o_current->saved_color;
+ }
+
+ new_obj = o_arc_add(w_current, list_tail, OBJ_ARC, color,
+ o_current->arc->x, o_current->arc->y,
+ o_current->arc->width / 2,
+ o_current->arc->start_angle,
+ o_current->arc->end_angle);
+ o_set_line_options(w_current, new_obj,
+ o_current->line_end, o_current->line_type,
+ o_current->line_width,
+ o_current->line_length, o_current->line_space);
+ o_set_fill_options(w_current, new_obj,
+ FILLING_HOLLOW, -1, -1, -1, -1, -1);
+
+ a_current = o_current->attribs;
+ if (a_current) {
+ while (a_current) {
+
+ /* head attrib node has prev = NULL */
+ if (a_current->prev != NULL) {
+ a_current->copied_to = new_obj;
+ }
+ a_current = a_current->next;
+ }
+ }
+
+ return(new_obj);
+}
+
+/*! \brief
+ * \par Function Description
+ * This function modifies the internal values of the arc object
+ * *object according to the whichone parameter.
+ *
+ * The new values are given by <B>x</B> and/or <B>y</B>. Their meaning depends on the value of whichone.
+ *
+ * If <B>whichone</B> is equal to #ARC_CENTER, the (<B>x</B>,<B>y</B>) point is taken as the new center
+ * of the arc in world unit.
+ *
+ * If <B>whichone</B> is equal to #ARC_RADIUS, the <B>x</B> parameter is taken to be the radius
+ * of the arc in world unit. The <B>y</B> parameter is ignored.
+ *
+ * If <B>whichone</B> is equal to #ARC_START_ANGLE, the <B>x</B> parameter is the starting angle of the arc.
+ * <B>x</B> is in degrees. <B>y</B> is ignored.
+ *
+ * If <B>whichone</B> is equal to #ARC_END_ANGLE, the <B>x</B> parameter is the ending angle of the arc.
+ * <B>x</B> is in degrees. <B>y</B> is ignored.
+ *
+ * The screen coordinates of the arc and its bounding box are computed again
+ * after the change in world coordinates.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in,out] object
+ * \param [in] x
+ * \param [in] y
+ * \param [in] whichone
+ */
+void o_arc_modify(TOPLEVEL *w_current, OBJECT *object,
+ int x, int y, int whichone)
+{
+
+ switch(whichone) {
+ case ARC_CENTER:
+ /* modify the center of arc object */
+ object->arc->x = x;
+ object->arc->y = y;
+ break;
+
+ case ARC_RADIUS:
+ /* modify the radius of arc object */
+ object->arc->width = 2 * x;
+ object->arc->height = 2 * x;
+ break;
+
+ case ARC_START_ANGLE:
+ /* modify the start angle of the arc object */
+ object->arc->start_angle = x;
+ break;
+
+ case ARC_END_ANGLE:
+ /* modify the end angle of the arc object */
+ object->arc->end_angle = x;
+ break;
+
+ default:
+ break;
+ }
+
+ /* update the screen coords and the bounding box */
+ o_arc_recalc(w_current, object);
+
+}
+
+/*! \brief
+ * \par Function Description
+ * This function reads a formatted text buffer describing an arc
+ * in the gEDA file format and initializes the corresponding object.
+ * This arc is linked to the end of the <B>object_list</B> pointed list.
+ * Depending on the version of the file format the data extraction is
+ * performed differently : currently pre-20000704 and 20000704 on one
+ * hand and post-20000704 file format version on the other hand are supported.
+ * The version is specified in string pointed by <B>fileformat_ver</B>.
+ *
+ * To get information on the various file formats have a
+ * look to the fileformats.html document.
+ *
+ * The object is initialized with the functions #o_set_line_options() and #o_set_fill_options().
+ * The second one is only used to put initialize unused values for an arc as an arc can not be filled.
+ *
+ * The arc is allocated initialized and linked with the function #o_arc_add().
+ *
+ * A negative or null radius is not allowed.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] object_list
+ * \param [in] buf
+ * \param [in] release_ver
+ * \param [in] fileformat_ver
+ * \return
+ */
+OBJECT *o_arc_read(TOPLEVEL *w_current, OBJECT *object_list, char buf[],
+ unsigned int release_ver, unsigned int fileformat_ver)
+{
+ char type;
+ int x1, y1;
+ int radius;
+ int start_angle, end_angle;
+ int color;
+ int arc_width, arc_length, arc_space;
+ int arc_type;
+ int arc_end;
+
+ /*! \note
+ * Depending on the version of the file format used to describe this arc,
+ * the buffer is parsed differently. The unknown parameters of the less
+ * restrictive - the oldest - file format are set to common values
+ */
+ if(release_ver <= VERSION_20000704) {
+ sscanf(buf, "%c %d %d %d %d %d %d", &type,
+ &x1, &y1, &radius, &start_angle, &end_angle, &color);
+
+ arc_width = 0;
+ arc_end = END_NONE;
+ arc_type = TYPE_SOLID;
+ arc_space = -1;
+ arc_length= -1;
+ } else {
+ sscanf(buf, "%c %d %d %d %d %d %d %d %d %d %d %d", &type,
+ &x1, &y1, &radius, &start_angle, &end_angle, &color,
+ &arc_width, &arc_end, &arc_type, &arc_length, &arc_space);
+
+ }
+
+ /* Error check */
+ if (radius <= 0) {
+ fprintf(stderr,
+ "Found a zero radius arc [ %c %d, %d, %d, %d, %d, %d ]\n",
+ type, x1, y1, radius, start_angle, end_angle, color);
+ s_log_message
+ ("Found a zero radius arc [ %c %d, %d, %d, %d, %d, %d ]\n",
+ type, x1, y1, radius, start_angle, end_angle, color);
+ }
+
+ if (color < 0 || color > MAX_COLORS) {
+ fprintf(stderr, "Found an invalid color [ %s ]\n", buf);
+ s_log_message("Found an invalid color [ %s ]\n", buf);
+ s_log_message("Setting color to WHITE\n");
+ color = WHITE;
+ }
+
+ /* Allocation and initialization */
+ object_list = o_arc_add(w_current, object_list, OBJ_ARC, color,
+ x1, y1, radius, start_angle, end_angle);
+ o_set_line_options(w_current, object_list,
+ arc_end, arc_type, arc_width, arc_length,
+ arc_space);
+ o_set_fill_options(w_current, object_list,
+ FILLING_HOLLOW, -1, -1, -1,
+ -1, -1);
+
+ return(object_list);
+}
+
+/*! \brief
+ * \par Function Description
+ * This function formats a string in the buffer <B>*buff</B> to describe
+ * the arc object <B>*object</B>.
+ * It follows the post-20000704 release file format that handle the
+ * line type and filling options.
+ * A pointer to the new allocated and formated string is returned.
+ * The string must be freed at some point.
+ *
+ * \param [in] object
+ * \return
+ *
+ * \todo EEK! there is a nasty non-snap bug here!
+ * Basically the center isn't being snapped
+ * in complex objects only it seems...
+ */
+char *o_arc_save(OBJECT *object)
+{
+ int color;
+ int x, y, radius, start_angle, end_angle;
+ int arc_width, arc_length, arc_space;
+ char *buf;
+ OBJECT_END arc_end;
+ OBJECT_TYPE arc_type;
+
+ /* radius, center and angles of the arc */
+ radius = object->arc->width / 2;
+ x = object->arc->x;
+ y = object->arc->y;
+ start_angle = object->arc->start_angle;
+ end_angle = object->arc->end_angle;
+
+ /* line type parameters */
+ arc_width = object->line_width;
+ arc_end = object->line_end;
+ arc_type = object->line_type;
+ arc_length = object->line_length;
+ arc_space = object->line_space;
+
+ /* Save the right color */
+ if (object->saved_color == -1) {
+ color = object->color;
+ } else {
+ color = object->saved_color;
+ }
+
+ /* Describe a circle with post-20000704 file format */
+ buf = g_strdup_printf("%c %d %d %d %d %d %d %d %d %d %d %d", object->type,
+ x, y, radius, start_angle, end_angle, color,
+ arc_width, arc_end, arc_type, arc_length, arc_space);
+
+ return(buf);
+}
+
+
+/*! \brief
+ * \par Function Description
+ * This function translates the arc described in the <B>object</B>
+ * pointed structure by <B>dx</B> horizontally and <B>dy</B> vertically.
+ * <B>dx</B> and <B>dy</B> are in screen unit.
+ *
+ * The translation vector is converted in world unit. The translation
+ * is made with <B>o_arc_translate_world()</B> that also updates the
+ * screen coordinates and the bounding box.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] dx
+ * \param [in] dy
+ * \param [in] object
+ */
+void o_arc_translate(TOPLEVEL *w_current, int dx, int dy, OBJECT *object)
+{
+ int world_dx, world_dy;
+
+ if (object == NULL) {
+ return;
+ }
+
+ /* convert the translation vector in world unit */
+ world_dx = SCREENabs(w_current, dx);
+ world_dy = SCREENabs(w_current, dy);
+
+ /* translate the arc */
+ o_arc_translate_world(w_current, world_dx, world_dy, object);
+
+ /* screen coords and boundings are updated by _translate_world() */
+
+}
+
+/*! \brief
+ * \par Function Description
+ * This function applies a translation of (<B>dx</B>,<B>dy</B>)
+ * to the arc described in <B>*object</B>. <B>dx</B> and <B>dy</B> are in world unit.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] dx
+ * \param [in] dy
+ * \param [in] object
+ */
+void o_arc_translate_world(TOPLEVEL *w_current, int dx, int dy,
+ OBJECT *object)
+{
+ if (object == NULL) {
+ return;
+ }
+
+ /* Do world coords */
+ object->arc->x = object->arc->x + dx;
+ object->arc->y = object->arc->y + dy;
+
+
+ /* Recalculate screen coords from new world coords */
+ o_arc_recalc(w_current, object);
+}
+
+/*! \brief
+ * \par Function Description
+ * This function applies a rotation of center (<B>centerx</B>,<B>centery</B>)
+ * and angle <B>angle</B> to the arc object <B>*object</B>.
+ * The coordinates of the rotation center are in screen units.
+ * The angle is in degree.
+ *
+ * The rotation is made with th <B>o_arc_rotate_world()</B> function
+ * that perform a rotation of <B>angle</B> and center
+ * (<B>world_centerx</B>,<B>world_centery</B>) in world unit.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] centerx
+ * \param [in] centery
+ * \param [in] angle
+ * \param [in] object
+ */
+void o_arc_rotate(TOPLEVEL *w_current,
+ int centerx, int centery, int angle,
+ OBJECT *object)
+{
+ int world_centerx, world_centery;
+
+ /* convert the center of rotation to world unit */
+ SCREENtoWORLD(w_current,
+ centerx, centery,
+ &world_centerx, &world_centery);
+
+ /* rotate the arc */
+ o_arc_rotate_world(w_current,
+ world_centerx, world_centery, angle,
+ object);
+
+ /* screen coords and boundings are updated by _rotate_world() */
+
+}
+
+/*! \brief
+ * \par Function Description
+ * This function rotates the world coordinates of an arc of an angle
+ * specified by <B>angle</B>. The center of the rotation is given by
+ * (<B>world_centerx</B>,<B>world_centery</B>).
+ *
+ * The arc is translated in order to put the center of the rotation
+ * on the origin. The center of the arc is then rotated of the angle
+ * specified by <B>angle</B>. The start angle of the arc is incremented by <B>angle</B>.
+ *
+ * The arc is finally back translated to its previous location on the page.
+ *
+ * <B>world_centerx</B> and <B>world_centery</B> are in world units, <B>angle</B> is in degrees.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] world_centerx
+ * \param [in] world_centery
+ * \param [in] angle
+ * \param [in] object
+ */
+void o_arc_rotate_world(TOPLEVEL *w_current,
+ int world_centerx, int world_centery, int angle,
+ OBJECT *object)
+{
+ int x, y, newx, newy;
+
+ /* translate object to origin */
+ object->arc->x -= world_centerx;
+ object->arc->y -= world_centery;
+
+ /* get center, and rotate center */
+ x = object->arc->x;
+ y = object->arc->y;
+ if(angle % 90 == 0) {
+ rotate_point_90(x, y, angle % 360, &newx, &newy);
+ } else {
+ rotate_point(x, y, angle % 360, &newx, &newy);
+ }
+ object->arc->x = newx;
+ object->arc->y = newy;
+
+ /* apply rotation to angles */
+ object->arc->start_angle = (object->arc->start_angle + angle) % 360;
+ /* end_angle is unchanged as it is the sweep of the arc */
+ /* object->arc->end_angle = (object->arc->end_angle); */
+
+ /* translate object to its previous place */
+ object->arc->x += world_centerx;
+ object->arc->y += world_centery;
+
+ /* update the screen coords and the bounding box */
+ o_arc_recalc(w_current, object);
+
+}
+
+/*! \brief
+ * \par Function Description
+ * This function mirrors the screen coordinates of an arc.
+ * The symetry axis is given by the vertical line going
+ * through the point (<B>centerx</B>,<B>centery</B>).
+ *
+ * <B>centerx</B> and <B>centery</B> are in screen unit.
+ *
+ * The arc is translated in order to put the point (<B>centerx</B>,<B>centery</B>)
+ * on the origin. The center of the arc is then mirrored. The start angle of
+ * the arc and the sweep of the arc are also mirrored.
+ *
+ * The arc is finally back translated to its previous location on the page.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] centerx
+ * \param [in] centery
+ * \param [in] object
+ */
+void o_arc_mirror(TOPLEVEL *w_current,
+ int centerx, int centery,
+ OBJECT *object)
+{
+ int world_centerx, world_centery;
+
+ /* convert mirror origin in world unit */
+ SCREENtoWORLD(w_current, centerx, centery,
+ &world_centerx, &world_centery);
+
+ /* mirror the arc */
+ o_arc_mirror_world(w_current, world_centerx, world_centery, object);
+
+ /* screen coords and boundings are updated by _rotate_world() */
+
+}
+
+/*! \brief Mirror the WORLD coordinates of an ARC.
+ * \par Function Description
+ * This function mirrors the world coordinates of an arc.
+ * The symetry axis is given by the vertical line going through the point (<B>world_centerx</B>,<B>world_centery</B>).
+ *
+ * The arc is translated in order to put the point (<B>world_centerx</B>,<B>world_centery</B>)
+ * on the origin. The center of the arc is then mirrored. The start angle of the arc
+ * and the sweep of the arc are also mirrored.
+ *
+ * The arc is finally back translated to its previous location on the page.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] world_centerx
+ * \param [in] world_centery
+ * \param [in] object
+ */
+void o_arc_mirror_world(TOPLEVEL *w_current,
+ int world_centerx, int world_centery,
+ OBJECT *object)
+{
+ /* translate object to origin */
+ object->arc->x -= world_centerx;
+ object->arc->y -= world_centery;
+
+ /* get center, and mirror it (vertical mirror) */
+ object->arc->x = -object->arc->x;
+ object->arc->y = object->arc->y;
+
+ /* apply mirror to angles (vertical mirror) */
+ object->arc->start_angle = (180 - object->arc->start_angle) % 360;
+ /* pb20011125 - start_angle *MUST* be positive */
+ if(object->arc->start_angle < 0) object->arc->start_angle += 360;
+ object->arc->end_angle = -object->arc->end_angle;
+
+ /* translate object back to its previous position */
+ object->arc->x += world_centerx;
+ object->arc->y += world_centery;
+
+ /* update the screen coords and bounding box */
+ o_arc_recalc(w_current, object);
+
+}
+
+/*! \brief
+ * \par Function Description
+ * This function recalculates internal parameters in screen units
+ * of an object containing an arc. The object is given as parameters <B>o_current</B>.
+ * The calculation is done according to the zoom factor detailed in the <B>w_current</B>
+ * pointed structure.
+ * It also recalculates the <B>OBJECT</B> specific fields and the bounding box of the arc.
+ *
+ * The <B>OBJECT</B> specific fields are handled by the function <B>o_object_recalc()</B>
+ * whereas bounding box - in screen units - is recalculated with the <B>get_arc_bounds()</B> function.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] o_current
+ */
+void o_arc_recalc(TOPLEVEL *w_current, OBJECT *o_current)
+{
+ int screen_x1, screen_y1, screen_x2, screen_y2;
+ int left, right, top, bottom;
+
+ if (o_current->arc == NULL) {
+ return;
+ }
+
+ /* update the screen_x and screen_y fields of the arc */
+ WORLDtoSCREEN(w_current, o_current->arc->x, o_current->arc->y,
+ &screen_x1, &screen_y1);
+
+ o_current->arc->screen_x = screen_x1; /* x coord */
+ o_current->arc->screen_y = screen_y1; /* y coord */
+
+ /* update the screen_width and screen_height fields of the arc */
+ WORLDtoSCREEN(w_current,
+ o_current->arc->x + o_current->arc->width,
+ o_current->arc->y - o_current->arc->height,
+ &screen_x2, &screen_y2);
+
+ o_current->arc->screen_width = screen_x2 - screen_x1; /* width */
+ o_current->arc->screen_height = screen_y2 - screen_y1; /* height */
+
+ /* recalculates the line type information in o_current */
+ o_object_recalc(w_current, o_current);
+
+ /* recalculates the bounding box */
+ get_arc_bounds(w_current, o_current, &left, &top, &right, &bottom);
+ o_current->left = left;
+ o_current->top = top;
+ o_current->right = right;
+ o_current->bottom = bottom;
+
+}
+
+/*! \brief
+ * \par Function Description
+ * This function calculates the smallest rectangle the arc can be drawn into.
+ * The <B>OBJECT</B> pointed by object is assumed to be an arc.
+ * The <B>left</B>, <B>top</B>, <B>right</B> and <B>bottom</B> pointed integers define
+ * this rectangle at the end of the function. It is expressed in screen units.
+ *
+ * The process is divided into two steps : the first step is to calculate the
+ * coordinates of the two ends of the arc and the coordinates of the center.
+ * They form a first rectangle but (depending on the start angle and the sweep
+ * of the arc) not the right.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] object
+ * \param [out] left
+ * \param [out] top
+ * \param [out] right
+ * \param [out] bottom
+ */
+void get_arc_bounds(TOPLEVEL *w_current, OBJECT *object,
+ int *left, int *top, int *right, int *bottom)
+{
+ int x1, y1, x2, y2, x3, y3;
+ int radius, start_angle, end_angle;
+ int i, angle;
+
+ radius = object->arc->screen_width / 2;
+ start_angle = object->arc->start_angle % 360;
+ end_angle = object->arc->end_angle % 360;
+
+ x1 = object->arc->screen_x;
+ y1 = object->arc->screen_y;
+ x2 = x1 + radius * cos(start_angle * M_PI / 180);
+ y2 = y1 - radius * sin(start_angle * M_PI / 180);
+ x3 = x1 + radius * cos((start_angle + end_angle) * M_PI / 180);
+ y3 = y1 - radius * sin((start_angle + end_angle) * M_PI / 180);
+
+ *left = (x1 < x2) ? ((x1 < x3) ? x1 : x3) : ((x2 < x3) ? x2 : x3);
+ *right = (x1 > x2) ? ((x1 > x3) ? x1 : x3) : ((x2 > x3) ? x2 : x3);
+ *top = (y1 < y2) ? ((y1 < y3) ? y1 : y3) : ((y2 < y3) ? y2 : y3);
+ *bottom = (y1 > y2) ? ((y1 > y3) ? y1 : y3) : ((y2 > y3) ? y2 : y3);
+
+ /*! \note
+ * The previous rectangle is extended to the final one by checking
+ * whether the arc is over a main axis (vertical or horizontal).
+ * If so, the rectangle is extended in these directions.
+ */
+ angle = ((int) (start_angle / 90)) * 90;
+ for(i = 0; i < 4; i++) {
+ angle = angle + 90;
+ if(angle < start_angle + end_angle) {
+ if(angle % 360 == 0) *right = x1 + radius;
+ if(angle % 360 == 90) *top = y1 - radius;
+ if(angle % 360 == 180) *left = x1 - radius;
+ if(angle % 360 == 270) *bottom = y1 + radius;
+ } else {
+ break;
+ }
+ }
+
+ /* PB : bounding box has to take into account the width of the line it is
+ composed with, ie adding/substracting half the width to this box */
+ /* PB : but width is unknown here */
+
+}
+
+/*! \brief
+ * \par Function Description
+ * This function calculates the smallest rectangle the arc can be drawn into.
+ * The <B>OBJECT</B> pointed by object is assumed to be an arc.
+ * The <B>left</B>, <B>top</B>, <B>right</B> and <B>bottom</B> pointed integers define
+ * this rectangle at the end of the function. It is expressed in world units.
+ * The process is divided into two steps : the first step is to calculate the
+ * coordinates of the two ends of the arc and the coordinates of the center.
+ * They forms a first rectangle but (depending on the start angle and the
+ * sweep of the arc) not the right.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] object
+ * \param [out] left
+ * \param [out] top
+ * \param [out] right
+ * \param [out] bottom
+ */
+void world_get_arc_bounds(TOPLEVEL *w_current, OBJECT *object, int *left,
+ int *top, int *right, int *bottom)
+{
+ int x1, y1, x2, y2, x3, y3;
+ int radius, start_angle, end_angle;
+ int i, angle;
+
+ radius = object->arc->width / 2;
+ start_angle = object->arc->start_angle % 360;
+ end_angle = object->arc->end_angle % 360;
+
+ x1 = object->arc->x;
+ y1 = object->arc->y;
+ x2 = x1 + radius * cos(start_angle * M_PI / 180);
+ y2 = y1 + radius * sin(start_angle * M_PI / 180);
+ x3 = x1 + radius * cos((start_angle + end_angle) * M_PI / 180);
+ y3 = y1 + radius * sin((start_angle + end_angle) * M_PI / 180);
+
+ *left = (x1 < x2) ? ((x1 < x3) ? x1 : x3) : ((x2 < x3) ? x2 : x3);
+ *right = (x1 > x2) ? ((x1 > x3) ? x1 : x3) : ((x2 > x3) ? x2 : x3);
+ *bottom = (y1 < y2) ? ((y1 < y3) ? y1 : y3) : ((y2 < y3) ? y2 : y3);
+ *top = (y1 > y2) ? ((y1 > y3) ? y1 : y3) : ((y2 > y3) ? y2 : y3);
+
+ /*! \note
+ * The previous rectangle is extended to the final one
+ * by checking whether the arc is over a main axis (vertical or horizontal).
+ * If so, the rectangle is extended in these directions.
+ */
+ angle = ((int) (start_angle / 90)) * 90;
+ for(i = 0; i < 4; i++) {
+ angle = angle + 90;
+ if(angle < start_angle + end_angle) {
+ if(angle % 360 == 0) *right = x1 + radius;
+ if(angle % 360 == 90) *top = y1 + radius;
+ if(angle % 360 == 180) *left = x1 - radius;
+ if(angle % 360 == 270) *bottom = y1 - radius;
+ } else {
+ break;
+ }
+ }
+
+ /* PB : same problem as above */
+}
+
+
+/*! \brief
+ * \par Function Description
+ * This function writes in a postscript file the arc described by
+ * the <B>o_current</B> pointed object.
+ * The postscript resulting file is described by the <B>fp</B> file pointer.
+ *
+ * Parameters of the arc are extracted from object pointed by <B>o_current</B>
+ * and formatted to suit future calls to specialized arc printing functions.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] fp The postscript document to print to.
+ * \param [in] o_current
+ * \param [in] origin_x
+ * \param [in] origin_y
+ */
+void o_arc_print(TOPLEVEL *w_current, FILE *fp, OBJECT *o_current,
+ int origin_x, int origin_y)
+{
+ int x, y, radius, start_angle, end_angle;
+ int color;
+ int arc_width, space, length;
+ void (*outl_func)() = NULL;
+
+ if (o_current == NULL) {
+ printf("got null in o_arc_print\n");
+ return;
+ }
+
+ x = o_current->arc->x;
+ y = o_current->arc->y;
+ radius = o_current->arc->width / 2;
+ start_angle = o_current->arc->start_angle;
+ end_angle = o_current->arc->end_angle;
+ color = o_current->color;
+
+ /*! \note
+ * Depending on the type of the line for this particular arc, the
+ * appropriate function is chosen among #o_arc_print_solid(),
+ * #o_arc_print_dotted(), #o_arc_print_dashed(), #o_arc_print_center() and #o_arc_print_phantom().
+ *
+ * The needed parameters for each of these types are extracted from the <B>o_current</B> object.
+ * Depending on the type, unused parameters are set to -1.
+ *
+ * In the eventuality of a length and/or space null, the arc is printed solid to avoid and
+ * endless loop produced by other functions.
+ */
+
+#if 0 /* was causing arcs which are solid to be much thinner compared to */
+ /* lines, boxes, also of zero width */
+ if (o_current->line_width > 0) {
+ arc_width = o_current->line_width;
+ } else {
+ arc_width = 1;
+ }
+#endif
+ arc_width = o_current->line_width; /* Added instead of above */
+ if (arc_width <= 2) arc_width = 2;
+ length = o_current->line_length;
+ space = o_current->line_space;
+
+ switch(o_current->line_type) {
+ case(TYPE_SOLID):
+ length = -1; space = -1;
+ outl_func = (void *) o_arc_print_solid;
+ break;
+
+ case(TYPE_DOTTED):
+ length = -1;
+ outl_func = (void *) o_arc_print_dotted;
+ break;
+
+ case(TYPE_DASHED):
+ outl_func = (void *) o_arc_print_dashed;
+ break;
+
+ case(TYPE_CENTER):
+ outl_func = (void *) o_arc_print_center;
+ break;
+
+ case(TYPE_PHANTOM):
+ outl_func = (void *) o_arc_print_phantom;
+ break;
+
+ case(TYPE_ERASE):
+ /* Unused for now, print it solid */
+ length = -1; space = -1;
+ outl_func = (void *) o_arc_print_solid;
+ break;
+ }
+
+ if((space == 0) || (length == 0)) {
+ length = -1; space = -1;
+ outl_func = (void *) o_arc_print_solid;
+ }
+
+ (*outl_func)(w_current, fp,
+ x - origin_x, y - origin_x, radius,
+ start_angle, end_angle,
+ color, arc_width, length, space, origin_x, origin_y);
+}
+
+
+/*! \brief
+ * \par Function Description
+ * This function prints an arc when a solid line type is required.
+ * The arc is defined by its center in <B>x</B> and <B>y</B>, its radius
+ * in <B>radius</B> and the start and end angles of the arc on the circle.
+ * The postscript file is defined by the file pointer <B>fp</B>.
+ *
+ * The parameters <B>length</B> and <B>space</B> are ignored
+ * whereas <B>arc_width</B> specifies the width of the printed line.
+ *
+ * All dimensions are in mils, except <B>angle1</B> and <B>angle2</B> in degrees.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] fp FILE pointer to postscript document.
+ * \param [in] x
+ * \param [in] y
+ * \param [in] radius
+ * \param [in] angle1
+ * \param [in] angle2
+ * \param [in] color
+ * \param [in] arc_width
+ * \param [in] length
+ * \param [in] space
+ * \param [in] origin_x
+ * \param [in] origin_y
+ */
+void o_arc_print_solid(TOPLEVEL *w_current, FILE *fp,
+ int x, int y, int radius,
+ int angle1, int angle2,
+ int color,
+ int arc_width, int length, int space,
+ int origin_x, int origin_y)
+{
+ if (w_current->print_color) {
+ f_print_set_color(fp, color);
+ }
+
+ /* PB/AVH inverting angle2 if < 0 and changing angle1 accordingly */
+ if (angle2 < 0) {
+ angle1 = angle1 + angle2;
+ angle2 = -angle2;
+ }
+
+ fprintf(fp, "%d %d %d %d %d %d darc\n",
+ x,y, radius, angle1, angle1 + angle2,
+ arc_width);
+
+}
+
+/*! \brief
+ * \par Function Description
+ * This function prints an arc when a dotted line type is required.
+ * The arc is defined by its center in <B>x</B> and <B>y</B>, its
+ * radius in <B>radius</B> and the start and end angles of the arc on the circle.
+ * The postscript file is defined by the file pointer <B>fp</B>.
+ * The parameter <B>length</B> is ignored whereas <B>arc_width</B> specifies
+ * the diameter of the dots of the printed line and <B>space</B> the distance
+ * between two dots.
+ *
+ * A negative value for <B>space</B> leads to an endless loop.
+ *
+ * All dimensions are in mils, except <B>angle1</B> and <B>angle2</B> in degrees.
+ *
+ * The function sets the color the line will be printed with.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] fp FILE pointer to postscript document.
+ * \param [in] x
+ * \param [in] y
+ * \param [in] radius
+ * \param [in] angle1
+ * \param [in] angle2
+ * \param [in] color
+ * \param [in] arc_width
+ * \param [in] length
+ * \param [in] space
+ * \param [in] origin_x
+ * \param [in] origin_y
+ */
+void o_arc_print_dotted(TOPLEVEL *w_current, FILE *fp,
+ int x, int y, int radius,
+ int angle1, int angle2,
+ int color,
+ int arc_width, int length, int space,
+ int origin_x, int origin_y)
+{
+ int da, d;
+
+
+ if (w_current->print_color) {
+ f_print_set_color(fp, color);
+ }
+
+ /*! \note
+ * Depending on the radius of the arc, the <B>space</B> parameter is
+ * changed into a small angle <B>da</B>.
+ * Starting from <B>angle1</B> - the start angle - the dots are printed
+ * along the arc by increments of this new angle.
+ *
+ * As <B>da</B> is rounded as an integer, it can take a null value which
+ * will make the function enter an endless loop. In such a case, the arc
+ * is printed solid. The <B>da</B> variable should never be negative
+ * except if <B>space</B> is negative.
+ */
+
+ /* Inverting angle2 if < 0 and changing angle1 accordingly */
+ /* the loop test assume that da > 0 */
+ if (angle2 < 0) {
+ angle1 = angle1 + angle2;
+ angle2 = -angle2;
+ }
+ da = (int) ((space * 180) / (M_PI * ((double) radius)));
+
+ /* If da or db too small for arc to be displayed as dotted,
+ draw a solid arc */
+ if (da <= 0) {
+ o_arc_print_solid(w_current, fp,
+ x, y, radius,
+ angle1, angle2,
+ color,
+ arc_width, length, space, origin_x, origin_y);
+ return;
+ }
+
+ fprintf(fp,"[");
+ d = angle1;
+ while (d < (angle2 + angle1)) {
+ /*xa = ((double) x) + ((double) radius) * cos(d * M_PI / 180);
+ ya = ((double) y) + ((double) radius) * sin(d * M_PI / 180);
+ */
+ fprintf(fp,"[%d] ",d);
+
+
+#if 0
+ /*! \note
+ * A dot is represented by a filled circle.
+ * Position of the circle is (<B>xa</B>, <B>ya</B>) and its radius is the <B>arc_width</B> parameter.
+ */
+ /* PB : problem corrected : diameter of printed dots */
+ /*
+ fprintf(fp, "newpath\n");
+ fprintf(fp, "%d mils %d mils\n", (int) xa, (int) ya);
+ if (arc_width <= 1) {
+ fprintf(fp, "2 mils\n");
+ } else {
+ fprintf(fp, "%d mils\n", (int) arc_width/2);
+ }
+ fprintf(fp, "0 360 arc\n");
+ fprintf(fp, "fill\n");
+ */
+ /* PB : end */
+#endif
+ d = d + da;
+ }
+ fprintf(fp,"] %d %d %d %d dashedarc %% dotted\n",
+ x,y, radius, arc_width);
+}
+
+/*! \brief
+ * \par Function Description
+ * This function prints an arc when a dashed line type is required.
+ * The arc is defined by its center in <B>x</B> and <B>y</B>, its radius
+ * in <B>radius</B> and the start and end angles of the arc on the circle.
+ * The postscript file is defined by the file pointer <B>fp</B>.
+ * The parameter <B>arc_width</B> specifies the diameter of the dots of the printed line.
+ *
+ * A negative value for <B>space</B> or <B>length</B> leads to an endless loop.
+ *
+ * All dimensions are in mils, except <B>angle1</B> and <B>angle2</B> in degrees.
+ *
+ * The function sets the color the line will be printed with.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] fp FILE pointer to postscript document.
+ * \param [in] x
+ * \param [in] y
+ * \param [in] radius
+ * \param [in] angle1
+ * \param [in] angle2
+ * \param [in] color
+ * \param [in] arc_width
+ * \param [in] length
+ * \param [in] space
+ * \param [in] origin_x
+ * \param [in] origin_y
+ */
+void o_arc_print_dashed(TOPLEVEL *w_current, FILE *fp,
+ int x, int y, int radius,
+ int angle1, int angle2,
+ int color,
+ int arc_width, int length, int space,
+ int origin_x, int origin_y)
+{
+ int da, db, a1, a2, d;
+
+ if (w_current->print_color) {
+ f_print_set_color(fp, color);
+ }
+
+ /*! \note
+ * Depending on the radius of the arc, the <B>space</B> (resp. <B>length</B>)
+ * parameter is changed into a small angle <B>da</B> (resp. <B>db</B>).
+ * Starting from <B>angle1</B> - the start angle - the dashes are printed
+ * along the arc by increments of these new angles.
+ *
+ * As <B>da</B> (resp. <B>db</B>) is rounded as an integer, it can take a
+ * null value which will make the function enter an endless loop. In such a case,
+ * the arc is printed solid. The <B>da</B> (resp. <B>db</B>) variable should never
+ * be negative except if <B>space</B> (resp. <B>length</B>) is negative.
+ *
+ * It prints as many dashes of length <B>length</B> as possible.
+ */
+
+ /* Inverting angle2 if < 0 and changing angle1 accordingly */
+ /* the loop test assume that da > 0 */
+ if (angle2 < 0) {
+ angle1 = angle1 + angle2;
+ angle2 = -angle2;
+ }
+ da = (int) ((length * 180) / (M_PI * ((double) radius)));
+ db = (int) ((space * 180) / (M_PI * ((double) radius)));
+
+ /* If da or db too small for arc to be displayed as dotted,
+ draw a solid arc */
+ if ((da <= 0) || (db <= 0)) {
+ o_arc_print_solid(w_current, fp,
+ x, y, radius,
+ angle1, angle2,
+ color,
+ arc_width, length, space, origin_x, origin_y);
+ return;
+ }
+
+ fprintf(fp,"[");
+ d = angle1;
+ while ((d + da + db) < (angle1 + angle2)) {
+ a1 = d;
+ d = d + da;
+
+ fprintf(fp,"[%d %d] ",
+ a1, a1+da);
+
+ d = d + db;
+ }
+ /*! \note
+ * When the above condition is no more satisfied, then it is not
+ * possible to print a dash of length <B>length</B> and the following <B>space</B>.
+ * However it may be possible to print the complete dash or a shorter one.
+ */
+
+ if ((d + da) < (angle1 + angle2)) {
+ a1 = d;
+ a2 = da;
+ } else {
+ a1 = d;
+ a2 = (angle1 + angle2) - d;
+ }
+
+ fprintf(fp,"[%d %d] ",
+ a1, a1+da);
+
+
+ fprintf(fp,"] %d %d %d %d dashedarc %% dashed\n",
+ x,y, radius, arc_width);
+
+}
+
+/*! \brief
+ * \par Function Description
+ * This function prints an arc when a centered line type is required.
+ * The arc is defined by its center in <B>x</B> and <B>y</B>, its radius in
+ * <B>radius</B> and the start and end angles of the arc on the circle.
+ * The postscript file is defined by the file pointer <B>fp</B>.
+ * The parameter <B>arc_width</B> specifies the diameter of the dots and the width of the dashes of the printed line.
+ *
+ * A negative value for <B>space</B> or <B>length</B> leads to an endless loop.
+ *
+ * All dimensions are in mils, except <B>angle1</B> and <B>angle2</B> in degrees.
+ *
+ * The function sets the color in which the line will be printed with.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] fp FILE pointer to postscript document.
+ * \param [in] x
+ * \param [in] y
+ * \param [in] radius
+ * \param [in] angle1
+ * \param [in] angle2
+ * \param [in] color
+ * \param [in] arc_width
+ * \param [in] length
+ * \param [in] space
+ * \param [in] origin_x
+ * \param [in] origin_y
+ */
+void o_arc_print_center(TOPLEVEL *w_current, FILE *fp,
+ int x, int y, int radius,
+ int angle1, int angle2,
+ int color,
+ int arc_width, int length, int space,
+ int origin_x, int origin_y)
+{
+ int da, db, a1, a2, d;
+
+ if (w_current->print_color) {
+ f_print_set_color(fp, color);
+ }
+
+ /*! \note
+ * Depending on the radius of the arc, the <B>space</B> (resp. <B>length</B>)
+ * parameter is changed into a small angle <B>da</B> (resp. <B>db</B>).
+ * Starting from <B>angle1</B> - the start angle - the dashes are printed
+ * along the arc by increments of these new angles.
+ *
+ * As <B>da</B> (resp. <B>db</B>) is rounded as an integer, it can take a null
+ * value which will make the function enter an endless loop. In such a case,
+ * the arc is printed solid. The <B>da</B> (resp. <B>db</B>) variable should never
+ * be negative except if <B>space</B> (resp. <B>length</B>) is negative.
+ *
+ * It prints as many sets of dash-dot as possible.
+ */
+
+ /* Inverting angle2 if < 0 and changing angle1 accordingly */
+ /* the loop test assume that da > 0 */
+ if (angle2 < 0) {
+ angle1 = angle1 + angle2;
+ angle2 = -angle2;
+ }
+
+ da = (int) ((length * 180) / (M_PI * ((double) radius)));
+ db = (int) ((space * 180) / (M_PI * ((double) radius)));
+
+ /* If da or db too small to be displayed, draw an arc */
+ if ((da <= 0) || (db <= 0)) {
+ o_arc_print_solid(w_current, fp,
+ x, y, radius,
+ angle1, angle2,
+ color,
+ arc_width, length, space, origin_x, origin_y);
+ return;
+ }
+
+ fprintf(fp, "[");
+ d = angle1;
+ while ((d + da + 2 * db) < (angle1 + angle2)) {
+ a1 = d;
+ d = d + da;
+ fprintf(fp,"[%d %d] ",(int) a1, (int) a1 + da);
+
+ d = d + db;
+ /*
+ xa = ((double) x) + ((double) radius) * cos(d * (M_PI / 180));
+ ya = ((double) y) + ((double) radius) * sin(d * (M_PI / 180));
+ */
+ fprintf(fp,"[%d] ",d);
+ d = d + db;
+ }
+ /*! \note
+ * When the above condition is no more satisfied, then it is not
+ * possible to print a dash of length <B>length</B>. However two cases are possible :
+ * <DL>
+ * <DT>*</DT><DD>it is possible to print the dash and the dot
+ * <DT>*</DT><DD>it is possible to print the dash or a part of the original dash
+ * </DL>
+ */
+
+ if ((d + da) < (angle1 + angle2)) {
+ a1 = d;
+ a2 = da;
+
+ d = d + da;
+ } else {
+ a1 = d;
+ a2 = (angle1 + angle2) - d;
+
+ d = d + da;
+ }
+
+ fprintf(fp,"[%d %d] ",(int) a1, (int) a1 + da);
+
+
+ if ((d + db) < (angle1 + angle2)) {
+ /*
+ xa = ((double) x) + ((double) radius) * cos(d * (M_PI / 180));
+ ya = ((double) y) + ((double) radius) * sin(d * (M_PI / 180));
+ */
+ fprintf(fp,"[%d] ",d);
+
+ }
+
+ fprintf(fp,"] %d %d %d %d dashedarc %% center\n",
+ x,y, radius, arc_width);
+}
+
+/*! \note
+ * A dot is represented by a filled circle. Position of the circle is (<B>xa</B>, <B>ya</B>)
+ * and its radius is the <B>arc_width</B> parameter.
+ */
+
+/*! \brief
+ * \par Function Description
+ * This function prints an arc when a phantom line type is required.
+ * The arc is defined by its center in <B>x</B> and <B>y</B>, its radius
+ * in <B>radius</B> and the start and end angles of the arc on the circle.
+ * The postscript file is defined by the file pointer <B>fp</B>.
+ * The parameter <B>arc_width</B> specifies the diameter of the dots and the width of the dashes of the printed line.
+ *
+ * A negative value for <B>space</B> or <B>length</B> leads to an endless loop.
+ *
+ * All dimensions are in mils, except <B>angle1</B> and <B>angle2</B> in degrees.
+ *
+ * The function sets the color in which the line will be printed with.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] fp FILE pointer to postscript document.
+ * \param [in] x
+ * \param [in] y
+ * \param [in] radius
+ * \param [in] angle1
+ * \param [in] angle2
+ * \param [in] color
+ * \param [in] arc_width
+ * \param [in] length
+ * \param [in] space
+ * \param [in] origin_x
+ * \param [in] origin_y
+ */
+void o_arc_print_phantom(TOPLEVEL *w_current, FILE *fp,
+ int x, int y, int radius,
+ int angle1, int angle2,
+ int color,
+ int arc_width, int length, int space,
+ int origin_x, int origin_y)
+{
+ int da, db, a1, a2, d;
+
+ if (w_current->print_color) {
+ f_print_set_color(fp, color);
+ }
+
+ /*! \note
+ * Depending on the radius of the arc, the <B>space</B> (resp. <B>length</B>)
+ * parameter is changed into a small angle <B>da</B> (resp. <B>db</B>).
+ * Starting from <B>angle1</B> - the start angle - the dashes are printed
+ * along the arc by increments of these new angles.
+ *
+ * As <B>da</B> (resp. <B>db</B>) is rounded as an integer, it can take a
+ * null value which will make the function enter an endless loop. In such
+ * a case, the arc is printed solid. The <B>da</B> (resp. <B>db</B>) variable
+ * should never be negative except if <B>space</B> (resp. <B>length</B>) is negative.
+ *
+ * It prints as many sets of dash-dot-dot as possible.
+ */
+
+ /* Inverting angle2 if < 0 and changing angle1 accordingly */
+ /* the loop test assume that da > 0 */
+ if (angle2 < 0) {
+ angle1 = angle1 + angle2;
+ angle2 = -angle2;
+ }
+ da = (int) ((length * 180) / (((double) radius) * M_PI));
+ db = (int) ((space * 180) / (((double) radius) * M_PI));
+
+ /* If da or db too small for arc to be displayed as dotted,
+ draw a solid arc */
+ if ((da <= 0) || (db <= 0)) {
+ o_arc_print_solid(w_current, fp,
+ x, y, radius,
+ angle1, angle2,
+ color,
+ arc_width, length, space, origin_x, origin_y);
+ return;
+ }
+
+ fprintf(fp,"[");
+
+ d = angle1;
+ while ((d + da + 3 * db) < (angle1 + angle2)) {
+ a1 = d;
+ d = d + da;
+
+ fprintf(fp,"[%d %d] ",(int) a1, (int) a1 + da);
+
+ d = d + db;
+ /*
+ xa = ((double) x) + ((double) radius) * cos(d * (M_PI / 180));
+ ya = ((double) y) + ((double) radius) * sin(d * (M_PI / 180));
+ */
+ fprintf(fp,"[%d] ",d);
+
+ d = d + db;
+
+ /*
+ xa = ((double) x) + ((double) radius) * cos(d * (M_PI / 180));
+ ya = ((double) y) + ((double) radius) * sin(d * (M_PI / 180));
+ */
+ fprintf(fp,"[%d] ",d);
+
+ d = d + db;
+ }
+
+ /*! \note
+ * When the above condition is no more satisfied, then it is not
+ * possible to print a dash of length <B>length</B>.
+ * However three cases are possible :
+ * <DL>
+ * <DT>*</DT><DD>it is possible to print a dash and a dot and a dot
+ * <DT>*</DT><DD>it is possible to print a dash and a dot
+ * <DT>*</DT><DD>it is possible to print the dash or a part of the original dash
+ * </DL>
+ */
+
+ if ((d + da) < (angle1 + angle2)) {
+ a1 = d;
+ a2 = da;
+ d = d + da;
+ } else {
+ a1 = d;
+ a2 = (angle1 + angle2) - d;
+ d = d + da;
+ }
+
+ fprintf(fp,"[%d %d] ",(int) a1, (int) a1 + da);
+
+ if ((d + db) < (angle1 + angle2)) {
+ d = d + db;
+
+ /*
+ xa = ((double) x) + ((double) radius) * cos(d * (M_PI / 180));
+ ya = ((double) y) + ((double) radius) * sin(d * (M_PI / 180));
+ */
+ fprintf(fp,"[%d] ",d);
+
+ }
+
+ if ((d + db) < (angle1 + angle2)) {
+ d = d + db;
+
+ /*
+ xa = ((double) x) + ((double) radius) * cos(d * (M_PI / 180));
+ ya = ((double) y) + ((double) radius) * sin(d * (M_PI / 180));
+ */
+
+ fprintf(fp,"[%d] ",d);
+
+
+ }
+
+ fprintf(fp,"] %d %d %d %d dashedarc %% phantom\n",
+ x,y, radius, arc_width);
+}
+
+
+#if 0 /* original way of printing arcs, no longer used */
+
+/*! \deprecated
+ * \brief Print solid arc in a Postscript file.
+ * \par Function Description
+ * This function prints a solid arc in a Postscript file indepedentely of its line type.
+ * It is basically the old way to manage the arc printing.
+ * This function is now replaced by the #o_arc_print() function.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] fp FILE pointer to postscript document.
+ * \param [in] o_current
+ * \param [in] origin_x
+ * \param [in] origin_y
+ */
+void o_arc_print_old(TOPLEVEL *w_current, FILE *fp, OBJECT *o_current,
+ int origin_x, int origin_y)
+{
+ int radius;
+ int start_angle, end_angle;
+ int awidth, aheight;
+ int x, y;
+
+ if (o_current == NULL) {
+ printf("got null in o_arc_print\n");
+ return;
+ }
+
+ fprintf(fp, "gsave\n");
+ if (w_current->print_color) {
+ f_print_set_color(fp, o_current->color);
+ }
+
+ f_print_set_line_width(fp, o_current->line_width);
+
+ awidth = o_current->arc->width;
+ aheight = o_current->arc->height;
+
+ radius = abs(aheight - o_current->arc->y)/2;
+
+ /* hack hack hack */
+ /* the snap_grid here is a safety for arcs inside complex objects */
+ /* which are not snapped to the grid */
+ /* ALL arcs centers will be snapped to the center */
+ /* hack hack hack */
+ /* Geee I wish there was a better solution */
+ /* well for now, if you print the complex structure that's in memory */
+ /* then the arc will be properly snapped */
+ /*x = snap_grid(w_current, o_current->x+radius);
+ y = snap_grid(w_current, o_current->y-radius);*/
+
+ x = (o_current->arc->x+radius);
+ y = (o_current->arc->y-radius);
+
+ start_angle = o_current->arc->start_angle/64;
+ end_angle = o_current->arc->end_angle/64;
+
+ if ( end_angle < 0) {
+
+ if (end_angle >= 180) {
+ start_angle = (start_angle - (end_angle)) % 360;
+ } else {
+ start_angle = (start_angle + (end_angle)) % 360;
+ }
+
+ end_angle = abs(end_angle);
+
+ }
+
+ end_angle = start_angle + end_angle;
+
+
+ fprintf(fp, "newpath\n");
+ fprintf(fp, "%d %d\n", x-origin_x, y-origin_y);
+ fprintf(fp, "%d\n", radius);
+ fprintf(fp, "%d %d arc\n", start_angle, end_angle);
+ fprintf(fp, "stroke\n");
+ fprintf(fp, "grestore\n");
+}
+#endif
+
+/*! \brief Draw an arc in an image.
+ * \par Function Description
+ * This function draws an arc in an image with the libgdgeda function <B>gdImageArc()</B>.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] o_current
+ * \param [in] origin_x
+ * \param [in] origin_y
+ * \param [in] color_mode
+ */
+void
+o_arc_image_write(TOPLEVEL *w_current, OBJECT *o_current,
+ int origin_x, int origin_y, int color_mode)
+{
+ int start_angle, end_angle;
+ int width, height;
+ int color;
+ int x, y;
+
+ if (o_current == NULL) {
+ printf("got null in o_arc_image_write\n");
+ return;
+ }
+
+ if (color_mode == TRUE) {
+ color = o_image_geda2gd_color(o_current->color);
+ } else {
+ color = image_black;
+ }
+
+ start_angle = o_current->arc->start_angle;
+ end_angle = o_current->arc->end_angle;
+
+ if ( end_angle < 0) {
+
+ if (end_angle >= 180) {
+ start_angle = (start_angle - (end_angle)) % 360;
+ } else {
+ start_angle = (start_angle + (end_angle)) % 360;
+ }
+
+ end_angle = abs(end_angle);
+
+ }
+
+ end_angle = start_angle + end_angle;
+
+
+
+#if DEBUG
+ printf("%d %d -- %d %d -- %d %d\n",
+ o_current->arc->screen_x, o_current->arc->screen_y,
+ o_current->arc->screen_width-o_current->arc->screen_x,
+ o_current->arc->screen_height-o_current->arc->screen_y,
+ start_angle, end_angle);
+#endif
+
+ if (start_angle < end_angle) {
+
+ start_angle = start_angle + 360;
+ }
+
+#if DEBUG
+ printf("%d %d -- %d %d -- %d %d\n",
+ o_current->arc->screen_x, o_current->arc->screen_y,
+ o_current->arc->screen_width-o_current->arc->screen_x,
+ o_current->arc->screen_height-o_current->arc->screen_y,
+ start_angle, end_angle);
+#endif
+
+
+ width = o_current->arc->screen_width;
+ height = o_current->arc->screen_height;
+
+ x = o_current->arc->screen_x;
+ y = o_current->arc->screen_y;
+
+#ifdef HAS_LIBGDGEDA
+
+ gdImageSetThickness(current_im_ptr, SCREENabs(w_current,
+ o_current->line_width));
+
+ gdImageArc(current_im_ptr,
+ x, y, width, height, start_angle, end_angle, color);
+#endif
+
+}
1.35 +2132 -1668eda/geda/gaf/libgeda/src/o_attrib.c
(In the diff below, changes in quantity of whitespace are not shown.)
Index: o_attrib.c
===================================================================
RCS file: o_attrib.c
diff -N o_attrib.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ o_attrib.c 5 Jul 2006 03:13:38 -0000 1.35
@@ -0,0 +1,2492 @@
+/* gEDA - GPL Electronic Design Automation
+ * libgeda - gEDA's library
+ * Copyright (C) 1998-2000 Ales V. Hvezda
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+#include <config.h>
+
+#include <stdio.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#include <math.h>
+
+#include <gtk/gtk.h>
+#include <libguile.h>
+
+#include "defines.h"
+#include "struct.h"
+#include "globals.h"
+#include "o_types.h"
+#include "colors.h"
+
+#include "../include/prototype.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+/*! Basic string splitting delimiters */
+#define DELIMITERS ",; "
+
+/*! \note
+ * No special type for attributes
+ * You can only edit text attributes
+ *
+ * be sure in o_copy o_move o_delete you maintain the attributes
+ * delete is a bare, because you will have to unattach the other end
+ * and in o_save o_read as well
+ * and in o_select when selecting objects, select the attributes
+ *
+ * \todo there needs to be a modifier (in struct.h, such as a flag) which
+ * signifies that this is an attribute (really? why?)
+ *
+ * \note
+ * return pointer from attrib_list
+ */
+
+/*! \brief Update an attribute's uref.
+ * \par Function Description
+ * Update an attribute's uref.
+ *
+ * \param [in] w_current The TOPLEVEL object
+ * \param [in] o_current The object to update.
+ *
+ * \note
+ * Martin Benes' auto uref renumber code
+ */
+void o_attrib_update_urefBM (TOPLEVEL *w_current, OBJECT *o_current)
+{
+ OBJECT *list_head,*obj;
+ char *uref;
+ int i = -1, name_conflict,len;
+ char *index_list;
+ int index_list_len=1;
+
+ if (strncmp(o_current->text->string,"uref=",5)) /* deprecated */
+ return;
+
+ len=strlen(o_current->text->string);
+ uref=malloc(len+10);
+ strcpy(uref,o_current->text->string);
+
+ while (o_current->text->string[len-1]<='9' &&
+ o_current->text->string[len-1]>='0')
+ --len;
+
+ list_head=return_head(o_current);
+ for (obj=list_head->next;obj;obj=obj->next) {
+ if (obj->type==OBJ_TEXT && obj->attribute)
+ ++index_list_len;
+ }
+
+ index_list=calloc(index_list_len,1);
+ name_conflict=0;
+
+ for (obj=list_head->next;obj;obj=obj->next) {
+ if (obj->type==OBJ_TEXT && obj->attribute && obj!=o_current) {
+ if (strncmp(uref,obj->text->string,len)==0) {
+ if (strcmp(uref+len,obj->text->string+len)==0) {
+ name_conflict=1;
+ }
+ i=atoi(obj->text->string+len);
+ if (i<index_list_len)
+ index_list[i]=1;
+ }
+ }
+ }
+
+ if (name_conflict) {
+ for (i=0;index_list[i];++i);
+ sprintf(uref+len,"%d", i);
+ free(o_current->text->string);
+ o_current->text->string=uref;
+ o_text_recreate(w_current, o_current);
+ }
+
+ free(index_list);
+}
+
+/*! \brief Search for an item in an attribute list.
+ * \par Function Description
+ * Search for an item in an attribute list.
+ *
+ * \param [in] list ATTRIB pointer to the list to be searched.
+ * \param [in] item item to be found.
+ */
+ATTRIB *o_attrib_search(ATTRIB *list, OBJECT *item)
+{
+ ATTRIB *a_current;
+
+ if (item == NULL) {
+ return(NULL);
+ }
+
+ a_current = list;
+
+ while(a_current != NULL) {
+ if (a_current->object != NULL) {
+ if (item->sid == a_current->object->sid) {
+ return(a_current);
+ }
+ }
+
+ a_current = a_current->next;
+ }
+
+ return(NULL);
+}
+
+/*! \brief Get the last attribute in the list.
+ * \par Function Description
+ * Get the last attribute in the list.
+ *
+ * \param [in] head ATTRIB pointer to beginning of list.
+ * \return Returns an ATTRIB pointer to the last attribute in the list.
+ */
+ATTRIB *o_attrib_return_tail(ATTRIB *head)
+{
+ ATTRIB *a_current=NULL;
+ ATTRIB *current=NULL;
+
+ a_current = head;
+ while ( a_current != NULL ) { /* goto end of list */
+ current = a_current;
+ a_current = a_current->next;
+ }
+ return(current);
+}
+
+/*! \brief Create an attribute list head item.
+ * \par Function Description
+ * Create an attribute list head item.
+ *
+ * \param [in] parent OBJECT pointer that will become the parent
+ * of this new head item.
+ * \return Returns an ATTRIB pointer to the newly created head item.
+ *
+ * \todo Rename this function to be consistant.
+ */
+ATTRIB *add_attrib_head(OBJECT *parent)
+{
+ ATTRIB *head = NULL;
+
+ head = (ATTRIB *) malloc(sizeof(ATTRIB));
+ head->next = NULL;
+
+ /* highly experimental hack */
+ head->object = parent;
+ head->copied_to = NULL;
+ head->prev = NULL;
+
+ /* \todo
+ * why the grief? well everywhere a attribute is refered to
+ * you have to skip over the head, you really ought to robustify
+ * all references to this object pointer when talking to attributes
+ * hack of course I think this is okay now though
+ */
+
+ return(head);
+}
+
+/*! \brief Add an attribute to an existing attribute list.
+ * \par Function Description
+ * Add an attribute to an exsiting attribute list.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in,out] list_head The list where you want to add item to.
+ * \param [in] item The item you want to add as an attribute.
+ * \return An ATTRIB pointer to the newly created attribute.
+ */
+ATTRIB *o_attrib_add(TOPLEVEL *w_current, ATTRIB *list_head, OBJECT *item)
+{
+ ATTRIB *end = NULL;
+ ATTRIB *new = NULL;
+
+ /* get tail of list_head */
+ end = o_attrib_return_tail(list_head);
+
+ /* create an new st_attrib object */
+ new = (ATTRIB *) malloc(sizeof(ATTRIB));
+
+ /* fill item with correct data (mainly item) */
+ new->next = NULL;
+ new->prev = end;
+ new->object = item;
+ new->copied_to = NULL;
+ new->object->attribute = 1; /* Set the attribute to true, hack define */
+ /* Show that that item is an attribute */
+ new->object->color = w_current->attribute_color;
+
+ if (new->object->type == OBJ_TEXT) {
+ o_complex_set_color(new->object->text->prim_objs,
+ new->object->color);
+ } else if (new->object->type == OBJ_COMPLEX ||
+ new->object->type == OBJ_PLACEHOLDER) {
+ o_complex_set_color(new->object->complex->prim_objs,
+ new->object->color);
+ }
+
+ /* Add link from item to attrib listing */
+ new->object->attached_to = new;
+
+ /* set next of tail of end->attrib to item */
+ if (end) {
+ end->next = new;
+ return(new);
+ } else {
+ return(new);
+ }
+}
+
+/*! \brief Free single item in attribute list.
+ * \par Function Description
+ * Free single item in attribute list.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] current ATTRIB pointer to free.
+ *
+ * \note
+ * this routine is not nice to next and prev
+ * this routine is only called from free_all
+ */
+void o_attrib_free(TOPLEVEL *w_current, ATTRIB *current)
+{
+ if (current != NULL) {
+
+ /* \todo this makes me nervous... very nervous */
+ if (current->object != NULL && current->prev != NULL) {
+ current->object->attribute = 0;
+ current->object->attached_to=NULL;
+ current->object->color = w_current->detachedattr_color;
+
+ if (current->object->type == OBJ_TEXT) {
+ o_complex_set_color(current->object->text->prim_objs,
+ current->object->color);
+ } else {
+ printf("Tried to set the color on a complex!\nlibgeda/src/o_attrib_free 1\n");
+ }
+
+ /* \todo not sure on this */
+ if (current->object->saved_color != -1) {
+ if (current->object->type == OBJ_TEXT) {
+ o_complex_set_saved_color_only(
+ current->object->text->prim_objs,
+ w_current->detachedattr_color);
+ } else {
+ printf("Tried to set the color on a complex!\nlibgeda/src/o_attrib_free 2\n");
+ }
+ current->object->saved_color = w_current->
+ detachedattr_color;
+ }
+ }
+
+ /* \todo were do we detach the object->attached_to? above */
+ current->object=NULL;
+
+ free(current);
+
+ }
+}
+
+/*! \brief Attach existing attribute to an object.
+ * \par Function Description
+ * Attach existing attribute to an object.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] parent_list List where actual attribute objects live.
+ * \param [in] text_object The attribute to be added.
+ * \param [out] object The object where you want to add item as an attribute.
+ *
+ * \par IMPORTANT:
+ * Lists first then specific single item.
+ *
+ * \note
+ * typically parent_list is object_parent (object_head), but it is
+ * overridden in o_complex_add so that it points to head node of the complex
+ *
+ */
+void o_attrib_attach(TOPLEVEL *w_current, OBJECT *parent_list,
+ OBJECT *text_object, OBJECT *object)
+{
+ OBJECT *o_current = NULL;
+
+ ATTRIB *found = NULL;
+ OBJECT *found2 = NULL; /* object in main list */
+
+ o_current = text_object;
+
+ if (object == NULL) {
+ printf("ah.. object was not found in the parent list!\n");
+ return;
+ }
+
+ /* is the object already part of the list ? */
+ found = o_attrib_search(object->attribs, o_current);
+ if (!found) { /* no it's not, add it to the list */
+
+ found2 = (OBJECT *) o_list_search(parent_list, o_current);
+
+ /* check to see if found2 is not null hack */
+ if (found2) {
+ if (found2->type == OBJ_TEXT) {
+
+ if (object->attribs == NULL) {
+ object->attribs =
+ add_attrib_head(object);
+ }
+
+
+ if (found2->attached_to) {
+ fprintf(stderr, "You cannot attach this attribute [%s] to more than one object\n", found2->text->string);
+ } else {
+
+ o_attrib_add(w_current,
+ object->attribs,
+ found2);
+
+ o_current->color = w_current->
+ attribute_color;
+
+ o_complex_set_color(
+ o_current->text->prim_objs,
+ o_current->color);
+
+ if (o_current->saved_color != -1) {
+ o_complex_set_saved_color_only(
+ o_current->text->prim_objs,
+ o_current->color);
+ o_current->saved_color =
+ o_current->color;
+ }
+ /* can't do this here since just selecting something */
+ /* will cause this to be set */
+ /* w_current->page_current->CHANGED=1;*/
+
+#ifdef MARTIN_BENES
+ o_attrib_update_urefBM (w_current, o_current);
+#endif
+ }
+ } else {
+ fprintf(stderr, "You cannot attach non text items as attributes!\n");
+ }
+ }
+ } else {
+ if (o_current->text->string) {
+ printf("Attribute [%s] already attached\n",
+ o_current->text->string);
+ }
+ }
+}
+
+/*! \todo Empty function.
+ * \brief
+ * \par Function Description
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] list
+ * \param [in] items
+ */
+void
+o_attrib_detach_test(TOPLEVEL *w_current, OBJECT *list, OBJECT *items)
+{
+
+/* this all needs to be rethought out */
+ /* loop over items till NULL */
+ /* Search for item in object->attrib */
+ /* o_attrib_search(list->attribs, current_item) */
+ /* if found */
+ /*call o_attrib_remove(object->attributes, current_item->attrib_struct);*/
+ /* if not found */
+ /* do nothing */
+
+}
+
+/*! \todo Empty function.
+ * \brief
+ * \par Function Description
+ *
+ * \param [in] list
+ * \param [in] item
+ */
+/* only can edit a text, special case of edit text */
+void o_attrib_edit(OBJECT *list, OBJECT *item)
+{
+
+}
+
+/*! \todo Empty function.
+ * \brief
+ * \par Function Description
+ *
+ * \param [in] list
+ *
+ * \note
+ * should this be st_attrib or st_object?
+ */
+void o_attrib_select_draw(ATTRIB *list)
+{
+ /* draw list */
+ /* either white */
+ /* or a white bounding box? */
+}
+
+/*! \todo Empty function.
+ * \brief
+ * \par Function Description
+ *
+ * \param [in] list
+ *
+ * \note
+ * should this be st_attrib or st_object?
+ */
+void o_attrib_unselect_draw(ATTRIB *list)
+{
+ /* draw list */
+ /* either white */
+ /* or a white bounding box? */
+
+}
+
+/*! \brief Free all attribute items in a list.
+ * \par Function Description
+ * Free all attribute items in a list.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in,out] list The list to free.
+ *
+ * \note
+ * this routine uses o_attrib_free (which isn't nice to next, prev)
+ * so it should only be used when an object is being destroyed
+ * goes backwards
+ */
+void o_attrib_free_all(TOPLEVEL *w_current, ATTRIB *list)
+{
+ ATTRIB *a_current;
+ ATTRIB *a_next;
+
+ a_current = list;
+
+ while (a_current != NULL) {
+ a_next = a_current->next;
+ o_attrib_free(w_current, a_current);
+ a_current = a_next;
+ }
+}
+
+/*! \brief Print all attributes to a Postscript document.
+ * \par Function Description
+ * Print all attributes to a Postscript document.
+ *
+ * \param [in] attributes List of attributes to print.
+ */
+void o_attrib_print(ATTRIB *attributes)
+{
+ ATTRIB *a_current;
+
+ a_current = attributes;
+
+ while (a_current != NULL) {
+ printf("Attribute points to: %s\n", a_current->object->name);
+ if (a_current->object && a_current->object->text) {
+ printf("\tText is: %s\n", a_current->object->text->string);
+ }
+
+ if (!a_current->object) {
+ printf("oops found a null attrib object\n");
+ }
+ a_current = a_current->next;
+ }
+}
+
+/*! \brief Print all attributes in reverse order to a Postscript document.
+ * \par Function Description
+ * Print all attributes in reverse order to a Postscript document.
+ *
+ * \param [in] attributes List of attributes to print.
+ */
+void o_attrib_print_reverse(ATTRIB *attributes)
+{
+ ATTRIB *a_current;
+
+ a_current = o_attrib_return_tail(attributes);
+
+ while (a_current != NULL) {
+ printf("Attribute points to: %s\n", a_current->object->name);
+ if (a_current->object && a_current->object->text) {
+ printf("\tText is: %s\n", a_current->object->text->string);
+ }
+
+ if (!a_current->object) {
+ printf("oops found a null attrib object\n");
+ }
+ a_current = a_current->prev;
+ }
+}
+
+/*! \todo Empty function.
+ * \brief
+ * \par Function Description
+ *
+ * \param [in] list The attribute list to copy.
+ * \return Always NULL.
+ *
+ * \note
+ * very hard, I don't think we need it though
+ */
+ATTRIB *o_attrib_copy(ATTRIB *list)
+{
+ return(NULL);
+}
+
+/*! \brief Delete an attribute.
+ * \par Function Description
+ * This function goes out and removes the current attribute,
+ * while preserving the next, prev pointers.
+ * This function should be used when detaching an attribute.
+ *
+ * \param [in] a_current The attribute to be deleted.
+ */
+void o_attrib_delete(ATTRIB *a_current)
+{
+ if (a_current != NULL) {
+
+ if (a_current->next)
+ a_current->next->prev = a_current->prev;
+ else
+ a_current->next = NULL;
+
+ if (a_current->prev)
+ a_current->prev->next = a_current->next;
+ else
+ a_current->prev = NULL;
+
+ if (a_current->object) {
+ a_current->object->attribute=0;
+ a_current->object->attached_to=NULL;
+ }
+ a_current->object = NULL;
+
+ free(a_current);
+ }
+}
+
+/*! \todo Finish function.
+ * \brief Remove an attribute item from an attribute list.
+ * \par Function Description
+ * This function goes out and removes an attribute from a list.
+ * It searches for the attribute and then removes it using the
+ * good #o_attrib_delete() routine.
+ *
+ * \param [in] list ATTRIB list to remove attribute from.
+ * \param [in] remove The ATTRIB to remove from list.
+ *
+ * \note
+ * This function is the detach_all routine.
+ * It is not currently being used.
+ * It is not even done.
+ */
+void o_attrib_remove(ATTRIB *list, ATTRIB *remove)
+{
+ ATTRIB *a_current;
+
+ a_current = list;
+
+ while (a_current != NULL) {
+
+ if (a_current == remove) {
+
+ }
+ a_current = a_current->next;
+ }
+}
+
+/*! \todo Is this function used?
+ * \deprecated
+ * \brief Detach all attributes from a list.
+ * \par Function Description
+ * Detach all attributes from a list.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] object_list Attribute list to delete.
+ * \param [in] main_head The head of the attribute list.
+ */
+void o_attrib_detach_all(TOPLEVEL *w_current, OBJECT *object_list, OBJECT *main_head)
+{
+#if 0 /* not used */
+ OBJECT *o_current=NULL;
+
+ o_current = object_list;
+
+ while(o_current != NULL) {
+
+ X = (OBJECT *) o_list_search(main_head, o_current);
+
+ if (X) {
+ if (X->attribs != NULL) {
+ o_attrib_free_all(w_current, X->attribs);
+ X->attribs = NULL; /* leak possible? */
+ w_current->page_current->CHANGED=1;
+ }
+ }
+ o_current = o_current->next;
+ }
+#endif
+}
+
+/*! \brief Read attributes from a file.
+ * \par Function Description
+ * Read attributes from a file.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] fp FILE pointer to read from.
+ * \param [out] object_to_get_attribs Storage for attributes.
+ * \param [in] release_ver libgeda release version number.
+ * \param [in] fileformat_ver file format version number.
+ * \return Pointer to object_to_get_attribs.
+ */
+OBJECT *o_read_attribs(TOPLEVEL *w_current, FILE *fp, OBJECT *object_to_get_attribs,
+ unsigned int release_ver, unsigned int fileformat_ver)
+{
+ OBJECT *object_list=NULL;
+ char buf[1024];
+ char objtype;
+ int ATTACH=FALSE;
+ int saved_color = -1;
+
+ object_list = object_to_get_attribs;
+
+ while ( fgets(buf, 1024, fp) != NULL) {
+
+ sscanf(buf, "%c", &objtype);
+ switch (objtype) {
+
+ case(OBJ_LINE):
+ object_list = (OBJECT *) o_line_read(w_current,
+ object_list,
+ buf,
+ release_ver, fileformat_ver);
+ break;
+
+
+ case(OBJ_NET):
+ object_list = (OBJECT *) o_net_read(w_current,
+ object_list,
+ buf,
+ release_ver, fileformat_ver);
+ break;
+
+ case(OBJ_BUS):
+ object_list = (OBJECT *) o_bus_read(w_current,
+ object_list,
+ buf,
+ release_ver, fileformat_ver);
+ break;
+
+ case(OBJ_BOX):
+ object_list = (OBJECT *) o_box_read(w_current,
+ object_list,
+ buf,
+ release_ver, fileformat_ver);
+ break;
+
+ case(OBJ_CIRCLE):
+ object_list = (OBJECT *) o_circle_read(
+ w_current,
+ object_list,
+ buf,
+ release_ver, fileformat_ver);
+ break;
+
+ case(OBJ_COMPLEX):
+ case(OBJ_PLACEHOLDER):
+
+ object_list = (OBJECT *) o_complex_read(
+ w_current,
+ object_list,
+ buf,
+ release_ver, fileformat_ver);
+
+ /* this is necessary because complex may add
+ attributes which float */
+ /* still needed? */
+ object_list = (OBJECT *) return_tail(
+ object_list);
+ break;
+
+ case(OBJ_PIN):
+ object_list = (OBJECT *) o_pin_read(w_current,
+ object_list,
+ buf,
+ release_ver, fileformat_ver);
+ break;
+
+ case(OBJ_ARC):
+ object_list = (OBJECT *) o_arc_read(w_current,
+ object_list,
+ buf,
+ release_ver, fileformat_ver);
+ break;
+
+ case(OBJ_TEXT):
+ /* fgets(string, 1024, fp); text strings are now read inside: */
+ object_list = (OBJECT *) o_text_read(w_current,
+ object_list,
+ buf,
+ fp,
+ release_ver, fileformat_ver);
+ saved_color = object_list->color;
+ ATTACH=TRUE;
+
+ break;
+
+ case(ENDATTACH_ATTR):
+ return(object_list);
+ break;
+
+ }
+
+ if (ATTACH) {
+ o_attrib_attach(w_current,
+ w_current->page_current->object_parent,
+ object_list, object_to_get_attribs);
+ /* check color to set it to the right value */
+ if (object_list->color != saved_color) {
+ object_list->color = saved_color;
+
+ if (object_list->type == OBJ_TEXT) {
+ o_complex_set_color(
+ object_list->text->prim_objs,
+ object_list->color);
+ } else {
+ printf("Tried to set the color on a complex in libgeda/src/o_read_attribs\n");
+ }
+ }
+ ATTACH=FALSE;
+ } else {
+ fprintf(stderr, "Tried to attach a non-text item as an attribute\n");
+ }
+ }
+ return(object_list);
+}
+
+/*! \brief Save attributes to a file.
+ * \par Function Description
+ * Save attributes to a file.
+ *
+ * \param [in] fp FILE pointer to write attributes to.
+ * \param [in] attribs attributes to write.
+ * \todo
+ * this should be trimmed down to only save attributes which are text items
+ */
+void o_save_attribs(FILE *fp, ATTRIB *attribs)
+{
+ ATTRIB *a_current=NULL;
+ OBJECT *o_current=NULL;
+ char *out;
+
+ a_current = attribs;
+
+ fprintf(fp, "{\n");
+
+ while ( a_current != NULL ) {
+
+ o_current = a_current->object;
+
+ if (o_current->type != OBJ_HEAD) {
+
+#if DEBUG
+ printf("type: %d %c ref: %d %c\n", o_current->type, o_current->type,
+ OBJ_PIN, OBJ_PIN);
+#endif
+
+ switch (o_current->type) {
+
+ case(OBJ_LINE):
+ out = (char *) o_line_save(o_current);
+ break;
+
+ case(OBJ_NET):
+ out = (char *) o_net_save(o_current);
+ break;
+
+ case(OBJ_BUS):
+ out = (char *) o_bus_save(o_current);
+ break;
+
+ case(OBJ_BOX):
+ out = (char *) o_box_save(o_current);
+ break;
+
+ case(OBJ_CIRCLE):
+ out = (char *) o_circle_save(o_current);
+ break;
+
+ case(OBJ_COMPLEX):
+ case(OBJ_PLACEHOLDER): /* new type -- SDB 1.20.2005 */
+ out = (char *) o_complex_save(o_current);
+ break;
+
+ case(OBJ_TEXT):
+ out = (char *) o_text_save(o_current);
+ break;
+
+ case(OBJ_PIN):
+ out = (char *) o_pin_save(o_current);
+ break;
+
+ case(OBJ_ARC):
+ out = (char *) o_arc_save(o_current);
+ break;
+
+ case(OBJ_PICTURE):
+ out = (char *) o_picture_save(o_current);
+ break;
+
+ default:
+ fprintf(stderr, "Error type!\n");
+ exit(-1);
+ break;
+ }
+ /* output the line */
+ fprintf(fp, "%s\n", out);
+ free(out);
+ }
+ a_current = a_current->next;
+ }
+
+ fprintf(fp, "}\n");
+}
+
+/*! \brief Get name and value from name=value attribute.
+ * \par Function Description
+ * Get name and value from a name=value attribute.
+ *
+ * \param [in] string String to split into name/value pair.
+ * \param [out] name_ptr Name if found in string, NULL otherwise.
+ * \param [out] value_ptr Value if found in string, NULL otherwise.
+ * \return TRUE if string had equals in it, FALSE otherwise.
+ *
+ * \note
+ * both name and value must be pre allocated
+ * And if you get an invalid attribute (improper) with a name and no
+ * value, then it is NOT an attribute.
+ * Also, there cannot be any spaces beside the equals sign
+ * Changed: now it allocates memory for name and value strings.
+ * \warning
+ * Caller must free these strings when not needed.
+ */
+int o_attrib_get_name_value(char *string, char **name_ptr, char **value_ptr )
+{
+ char *equal_ptr;
+#ifdef HAS_GTK22
+ char **str_array;
+#else
+ int attribute_found=FALSE;
+ int i, j;
+ char *name, *value;
+#endif
+
+ if (name_ptr == NULL || value_ptr == NULL) {
+ return(FALSE);
+ }
+
+ *name_ptr = NULL; /* force these values to null */
+ *value_ptr = NULL;
+
+ if (!string) {
+ return(FALSE);
+ }
+
+ /* make sure there are no spaces in between equals */
+ equal_ptr = strchr(string, '=');
+ if (equal_ptr == NULL) {
+ return(FALSE);
+ }
+
+ if ( (*(equal_ptr + 1) == ' ') || (*(equal_ptr - 1) == ' ') ) {
+ /* sometimes you have text with an ='s in it, it shouldn't be */
+
+#if DEBUG
+ /* treated like an attribute */
+ s_log_message("Found attrib/text with spaces beside the ='s [%s]\n",
+ string);
+ s_log_message("You can ignore the above message if the text is not intended to be an attribute\n");
+ fprintf(stderr, "Found an attribute with spaces beside the ='s [%s]\n",
+ string);
+#endif
+
+ return(FALSE);
+ }
+
+#ifdef HAS_GTK22
+
+ /* can't use g_strsplit under glib/gtk+ 1.2 since it splits strings */
+ /* incorrectly! */
+ str_array = g_strsplit (string, "=", 2);
+
+ *name_ptr = g_strdup(str_array[0]);
+ *value_ptr = g_strdup(str_array[1]);
+ g_strfreev(str_array);
+
+#else
+
+ /* larger than needed... but this is okay for now. */
+ *name_ptr = g_strdup (string);
+ *value_ptr = g_strdup (string);
+
+ /* for convenience sake */
+ name = *name_ptr;
+ value = *value_ptr;
+
+ /* get the name */
+ i = 0;
+ while(string[i] != '\0' && !attribute_found) {
+ if (string[i] == '=') {
+ attribute_found = TRUE;
+ } else {
+ name[i] = string[i];
+ i++;
+ }
+ }
+
+ /* no = found */
+ if (!attribute_found) {
+ free(*name_ptr); *name_ptr = NULL;
+ free(*value_ptr); *value_ptr = NULL;
+ return(FALSE);
+ }
+
+ name[i] = '\0';
+ i++; /* skip over the ='s */
+
+ j = 0;
+ while(string[i] != '\0') {
+ value[j] = string[i];
+ i++;
+ j++;
+ }
+
+ value[j] = '\0';
+
+#endif
+
+ if (*value_ptr && (*value_ptr)[0] == '\0') {
+ s_log_message("Found an improper attribute: _%s_\n", string);
+#if 0 /* for now leak this memory till this is verified correct everywhere */
+ free(*name_ptr); *name_ptr = NULL;
+ free(*value_ptr); *value_ptr = NULL;
+#endif
+ return(FALSE);
+ } else {
+ return(TRUE);
+ }
+}
+
+/*! \brief Free the currently selected attribute.
+ * \par Function Description
+ * Free the currently selected attribute.
+ *
+ * \param [in] w_current The TOPLEVEL object containing current attribute.
+ *
+ */
+void o_attrib_free_current(TOPLEVEL *w_current)
+{
+ if (w_current->current_attribute) {
+ free(w_current->current_attribute);
+ }
+ w_current->current_attribute=NULL;
+}
+
+/*! \brief Set current show flag.
+ * \par Function Description
+ * Set current show flag.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] flag Any value which show_name_value takes.
+ * #SHOW_NAME_VALUE
+ * #SHOW_VALUE
+ * #SHOW_NAME
+ */
+void o_attrib_set_show(TOPLEVEL *w_current, int flag)
+{
+ w_current->current_show = flag;
+}
+
+/*! \brief Set current visibility flag.
+ * \par Function Description
+ * Set current visibility flag.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] flag Allowed values are:
+ * #VISIBLE
+ * #INVISIBLE
+ */
+void
+o_attrib_set_visible(TOPLEVEL *w_current, int flag)
+{
+ w_current->current_visible = flag;
+}
+
+/*! \brief Set an attribute's string.
+ * \par Function Description
+ * Set an attribute's string.
+ *
+ * \param [in] w_current The TOPLEVEL object that holds the attribute.
+ * \param [in] string The value to set attribute string to.
+ *
+ * \note
+ * The user of this function must free the
+ * <B>w_current->current_attribute</B> string after done using it.
+ * They must also free the input string.
+ */
+void o_attrib_set_string(TOPLEVEL *w_current, char *string)
+{
+ int len;
+
+ /* need to put an error messages here */
+ if (string == NULL) {
+ fprintf(stderr, "error! string in set_string was NULL\n");
+ return;
+ }
+
+ if (w_current->current_attribute != NULL) {
+ free(w_current->current_attribute);
+ w_current->current_attribute=NULL;
+ }
+
+ len = strlen(string);
+
+ w_current->current_attribute = (char *)
+ malloc(sizeof(char)*len+1);
+
+ strcpy(w_current->current_attribute,string);
+
+ /* be sure to free this string somewhere and free the input string */
+}
+
+/*! \brief Get the parent OBJECT of an attribute.
+ * \par Function Description
+ * Get the parent OBJECT of an attribute.
+ *
+ * \param [in] attribute ATTRIB pointer to get parent of.
+ * \return The parent OBJECT if it exists, otherwise NULL.
+ */
+OBJECT *o_attrib_return_parent(ATTRIB *attribute)
+{
+ ATTRIB *a_current;
+
+ a_current = attribute;
+
+ if (!a_current) {
+ return(NULL);
+ }
+
+ while (a_current->prev != NULL) {
+ a_current = a_current->prev;
+ }
+
+ /* should be pointing to the parent */
+
+ return(a_current->object);
+}
+
+/*! \brief Copy all attributes.
+ * \par Function Description
+ * This function will copy all attributes from the provided list
+ * by attaching them to the provided OBJECT list.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [out] attached_to OBJECT list to copy attributes to.
+ * \param [in] attributes ATTRIB list to copy attributes from.
+ * \return new attribute list.
+ */
+ATTRIB *o_attrib_copy_all(TOPLEVEL *w_current, OBJECT *attached_to,
+ ATTRIB *attributes)
+{
+ ATTRIB *a_current=NULL;
+ ATTRIB *a_head=NULL;
+ ATTRIB *a_new=NULL;
+ ATTRIB *a_prev=NULL;
+
+ a_current = attributes;
+
+ while (a_current != NULL) {
+
+ a_new = (ATTRIB *) malloc(sizeof(ATTRIB));
+
+ /* in the case of the head attrib node, object points to
+ * the parent which the attributes are attached to */
+ if (a_head == NULL) {
+ a_new->object = attached_to;
+ } else {
+ a_new->object = a_current->object;
+ }
+
+
+
+ /* object is not null and a_start is not null (ie we are not
+ * messing with the head attrib node)
+ */
+ if (a_new->object && a_head != NULL) {
+ a_new->object->attached_to = a_new;
+ }
+
+ a_new->copied_to = a_current->copied_to;
+
+ a_new->prev = a_prev;
+
+ /* set previous's next pointer */
+ /* if it's null that means we are at the first attrib */
+ if (a_prev) {
+ a_prev->next = a_new;
+ } else {
+ a_head = a_new;
+ }
+
+ a_new->next = NULL;
+ a_prev = a_new;
+ a_current = a_current->next;
+ }
+
+ /* should be pointing to the head node */
+ return(a_head);
+}
+
+/*! \brief Reattach attributes.
+ * \par Function Description
+ * Reattach attributes.
+ *
+ * \param [in] attributes ATTRIB list to reattach.
+ */
+void o_attrib_reattach(ATTRIB *attributes)
+{
+ ATTRIB *a_current=NULL;
+
+ a_current = attributes;
+
+ /* skip over head node */
+ if (a_current)
+ a_current = a_current->next;
+
+ while (a_current != NULL) {
+ if (a_current->object) {
+ a_current->object->attached_to = a_current;
+ a_current->object->attribute = 1;
+ }
+ a_current = a_current->next;
+ }
+}
+
+/*! \brief Set attribute color
+ * \par Function Description
+ * This function sets all attribute objects to the right
+ * color (attribute_color).
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in,out] attributes ATTRIB list to set colors on.
+ *
+ */
+void o_attrib_set_color(TOPLEVEL *w_current, ATTRIB *attributes)
+{
+ ATTRIB *a_current;
+
+ a_current = attributes;
+
+ /* skip over head */
+ if (a_current)
+ a_current = a_current->next;
+
+ while (a_current != NULL) {
+
+ if (a_current->object) {
+
+ if (a_current->object->type == OBJ_TEXT &&
+ a_current->object->text->prim_objs) {
+
+ /* I'm not terribly happy with this */
+
+ if (a_current->object->saved_color != -1) {
+
+ /* if the object is selected, make */
+ /* sure it it say selected */
+ o_complex_set_color(
+ a_current->object->text->prim_objs,
+ SELECT_COLOR);
+ a_current->object->color =
+ SELECT_COLOR;
+
+ o_complex_set_saved_color_only(
+ a_current->object->text->prim_objs,
+ w_current->attribute_color);
+ a_current->object->saved_color = w_current->
+ attribute_color;
+
+ } else {
+ o_complex_set_color(
+ a_current->object->text->prim_objs,
+ w_current->attribute_color);
+ a_current->object->color =
+ w_current->attribute_color;
+ }
+ }
+
+ a_current = a_current->next;
+ }
+ }
+}
+
+/*! \brief Search for attibute by name.
+ * \par Function Description
+ * Search for attribute by name.
+ *
+ * \warning
+ * The list is the top level list. Do not pass it an object_head list
+ * unless you know what you are doing.
+ *
+ * Counter is the n'th occurance of the attribute, and starts searching
+ * from zero. Zero is the first occurance of an attribute.
+ *
+ * \param [in] list OBJECT list to search.
+ * \param [in] name Character string with attribute name to search for.
+ * \param [in] counter Which occurance to return.
+ * \return Character string with attribute value, NULL otherwise.
+ *
+ * \warning
+ * Caller must free returned character string.
+ */
+char *o_attrib_search_name(OBJECT *list, char *name, int counter)
+{
+ OBJECT *o_current;
+ ATTRIB *a_current;
+ OBJECT *found;
+ int val;
+ int internal_counter=0;
+ char *found_name = NULL;
+ char *found_value = NULL;
+ char *return_string = NULL;
+
+ o_current = list;
+
+ while(o_current != NULL) {
+ if (o_current->attribs != NULL) {
+ a_current = o_current->attribs;
+
+ while(a_current != NULL) {
+ found = a_current->object;
+ if (found != NULL) {
+ if (found->type == OBJ_TEXT) {
+ val = o_attrib_get_name_value(found->text->string,
+ &found_name, &found_value);
+
+ if (val) {
+ if (strcmp(name, found_name) == 0) {
+ if (counter != internal_counter) {
+ internal_counter++;
+ } else {
+ return_string = (char *)
+ malloc(sizeof(char)*strlen(found_value)+1);
+ strcpy(return_string, found_value);
+ if (found_name) free(found_name);
+ if (found_value) free(found_value);
+ return(return_string);
+ }
+ }
+ if (found_name) { free(found_name); found_name = NULL; }
+ if (found_value) { free(found_value); found_value = NULL; }
+ }
+
+#if DEBUG
+ printf("0 _%s_\n", found->text->string);
+ printf("1 _%s_\n", found_name);
+ printf("2 _%s_\n", found_value);
+#endif
+ }
+ }
+ a_current=a_current->next;
+ }
+ }
+
+ /* search for attributes outside */
+
+ if (o_current->type == OBJ_TEXT) {
+ if (found_name) free(found_name);
+ if (found_value) free(found_value);
+ val = o_attrib_get_name_value(o_current->text->string,
+ &found_name, &found_value);
+ if (val) {
+ if (strcmp(name, found_name) == 0) {
+ if (counter != internal_counter) {
+ internal_counter++;
+ } else {
+ return_string = (char *)
+ malloc(
+ sizeof(char)*
+ strlen(found_value)+1);
+ strcpy(return_string, found_value);
+ if (found_name) free(found_name);
+ if (found_value) free(found_value);
+ return(return_string);
+ }
+ }
+ if (found_name) { free(found_name); found_name = NULL; }
+ if (found_value) { free(found_value); found_value = NULL; }
+ }
+ }
+
+ o_current=o_current->next;
+ }
+
+ if (found_name) free(found_name);
+ if (found_value) free(found_value);
+ return (NULL);
+}
+
+/*! \brief Search list for text string.
+ * \par Function Description
+ * Search list for text string.
+ *
+ * \warning
+ * The list is the top level list. Do not pass it an object_head list
+ * unless you know what you are doing.
+ *
+ * \param [in] list OBJECT list to search.
+ * \param [in] string Character string to search for.
+ * \return A matching OBJECT if found, NULL otherwise.
+ */
+OBJECT *o_attrib_search_string_list(OBJECT *list, char *string)
+{
+ OBJECT *o_current;
+ ATTRIB *a_current;
+ OBJECT *found;
+
+ o_current = list;
+
+ while(o_current != NULL) {
+ /* first search attribute list */
+ if (o_current->attribs != NULL) {
+ a_current = o_current->attribs;
+
+ while(a_current != NULL) {
+ found = a_current->object;
+ if (found != NULL) {
+ if (found->type == OBJ_TEXT) {
+ if (strcmp(string, found->text->string) == 0) {
+ return(found);
+ }
+ }
+ }
+ a_current=a_current->next;
+ }
+ }
+
+ /* search for attributes outside (ie the actual object) */
+ if (o_current->type == OBJ_TEXT) {
+ if (strcmp(string, o_current->text->string) == 0) {
+ return(o_current);
+ }
+ }
+
+ o_current=o_current->next;
+ }
+
+ return (NULL);
+}
+
+/*! \brief Search list for partial string match.
+ * \par Function Description
+ * Search list for partial string match.
+ *
+ * Counter is the n'th occurance of the attribute, and starts searching
+ * from zero. Zero is the first occurance of an attribute.
+ *
+ * \param [in] object The OBJECT list to search.
+ * \param [in] search_for Partial character string to search for.
+ * \param [in] counter Which occurance to return.
+ * \return Matching object value if found, NULL otherwise.
+ *
+ * \warning
+ * Caller must free returned character string.
+ */
+char *o_attrib_search_string_partial(OBJECT *object, char *search_for,
+ int counter)
+{
+ OBJECT *o_current;
+ int val;
+ int internal_counter=0;
+ char *found_name = NULL;
+ char *found_value = NULL;
+ char *return_string = NULL;
+
+ o_current = object;
+
+ if (o_current == NULL) {
+ return(NULL);
+ }
+
+ if (o_current->type == OBJ_TEXT) {
+ if (strstr(o_current->text->string, search_for)) {
+ if (counter != internal_counter) {
+ internal_counter++;
+ } else {
+ val = o_attrib_get_name_value(o_current->text->string,
+ &found_name, &found_value);
+ if (val) {
+ return_string = g_strdup(found_value);
+ if (found_name) free(found_name);
+ if (found_value) free(found_value);
+ return(return_string);
+ }
+ }
+ }
+ }
+
+ if (found_name) free(found_name);
+ if (found_value) free(found_value);
+ return (NULL);
+}
+
+/*! \brief Check if object matches string.
+ * \par Function Description
+ * This function will check if the text->string value of
+ * the passed OBJECT matches the <B>search_for</B> parameter.
+ *
+ * \param [in] object The OBJECT to compare.
+ * \param [in] search_for Character string to compare against.
+ * \return The OBJECT passed in <B>object</B> parameter, NULL otherwise.
+ */
+OBJECT *o_attrib_search_string_single(OBJECT *object, char *search_for)
+{
+ OBJECT *o_current;
+
+ o_current = object;
+
+ if (o_current == NULL) {
+ return(NULL);
+ }
+
+ if (o_current->type == OBJ_TEXT) {
+ if (strcmp(o_current->text->string, search_for) == 0) {
+ return(o_current);
+ }
+ }
+
+ return (NULL);
+}
+
+/*! \brief Search for attribute by value and name.
+ * \par Function Description
+ * Search for attribute by value and name.
+ *
+ * Counter is the n'th occurance of the attribute, and starts searching
+ * from zero. Zero is the first occurance of an attribute.
+ *
+ * The value is the primary search key, but name is checked before
+ * an OBJECT is returned to ensure the correct OBJECT has been found.
+ *
+ * \param [in] list The ATTRIB list to search.
+ * \param [in] value Character string with value to search for.
+ * \param [in] name Character string with name to compare.
+ * \param [in] counter Which occurance to return.
+ * \return The attribute OBJECT if found, NULL otherwise.
+ *
+ */
+OBJECT *o_attrib_search_attrib_value(ATTRIB *list, char *value, char *name,
+ int counter)
+{
+ OBJECT *found;
+ ATTRIB *a_current;
+ int val;
+ int internal_counter=0;
+ char *found_name = NULL;
+ char *found_value = NULL;
+
+ a_current = list;
+
+ if (!value)
+ return(NULL);
+
+ if (!name)
+ return(NULL);
+
+ while(a_current != NULL) {
+ found = a_current->object;
+ if (found != NULL) {
+ if (found->type == OBJ_TEXT) {
+ val = o_attrib_get_name_value(found->text->string,
+ &found_name, &found_value);
+
+ if (val) {
+#if DEBUG
+ printf("found value: %s\n", found_value);
+ printf("looking for: %s\n", value);
+#endif
+ if (strcmp(value, found_value) == 0) {
+ if (counter != internal_counter) {
+ internal_counter++;
+ } else {
+ if (strstr(found_name, name)) {
+ if (found_name) free(found_name);
+ if (found_value) free(found_value);
+ return(found);
+ }
+ }
+ }
+ if (found_name) { free(found_name); found_name = NULL; }
+ if (found_value) { free(found_value); found_value = NULL; }
+ }
+
+ }
+ }
+ a_current=a_current->next;
+ }
+
+ if (found_name) free(found_name);
+ if (found_value) free(found_value);
+ return (NULL);
+}
+
+/*! \brief Search for an attribute by name.
+ * \par Function Description
+ * Search for an attribute by name.
+ *
+ * Counter is the n'th occurance of the attribute, and starts searching
+ * from zero. Zero is the first occurance of an attribute.
+ *
+ * \param [in] list ATTRIB list to search.
+ * \param [in] name Character string with attribute name to search for.
+ * \param [in] counter Which occurance to return.
+ * \return Character string with attribute value, NULL otherwise.
+ *
+ * \warning
+ * Caller must free returned character string.
+ */
+char *
+o_attrib_search_attrib_name(ATTRIB *list, char *name, int counter)
+{
+ OBJECT *found;
+ ATTRIB *a_current;
+ int val;
+ int internal_counter=0;
+ char *found_name = NULL;
+ char *found_value = NULL;
+ char *return_string = NULL;
+
+ a_current = list;
+
+ while(a_current != NULL) {
+ found = a_current->object;
+ if (found != NULL) {
+ if (found->type == OBJ_TEXT) {
+ val = o_attrib_get_name_value(found->text->string,
+ &found_name, &found_value);
+
+ if (val) {
+#if DEBUG
+ printf("found name: %s\n", found_name);
+ printf("looking for: %s\n", name);
+#endif
+ if (strcmp(name, found_name) == 0) {
+ if (counter != internal_counter) {
+ internal_counter++;
+ } else {
+ return_string = (char *)
+ malloc(sizeof(char)*
+ strlen(found_value)+1);
+ strcpy(return_string, found_value);
+ if (found_name) free(found_name);
+ if (found_value) free(found_value);
+ return(return_string);
+ }
+ }
+ if (found_name) { free(found_name); found_name = NULL; }
+ if (found_value) { free(found_value); found_value = NULL; }
+ }
+ }
+ }
+ a_current=a_current->next;
+ }
+
+ if (found_name) free(found_name);
+ if (found_value) free(found_value);
+ return (NULL);
+}
+
+/*! \brief Search TOPLEVEL attributes.
+ * \par Function Description
+ * This function should only be used to search for TOPLEVEL attributes.
+ * \warning
+ * The list is the top level list. Do not pass it an object_head list
+ * unless you know what you are doing.
+ *
+ * Counter is the n'th occurance of the attribute, and starts searching
+ * from zero. Zero is the first occurance of an attribute.
+ *
+ * \param [in] list The OBJECT list to search (TOPLEVEL only).
+ * \param [in] name Character string of attribute name to search for.
+ * \param [in] counter Which occurance to return.
+ * \return Character string with attribute value, NULL otherwise.
+ *
+ * \warning
+ * Caller must free returned character string.
+ */
+char *o_attrib_search_toplevel(OBJECT *list, char *name, int counter)
+{
+ OBJECT *o_current;
+ int val;
+ int internal_counter=0;
+ char *found_name = NULL;
+ char *found_value = NULL;
+ char *return_string = NULL;
+
+ o_current = list;
+
+ while(o_current != NULL) {
+
+ /* search for attributes outside */
+
+ if (o_current->type == OBJ_TEXT) {
+ val = o_attrib_get_name_value(o_current->text->string,
+ &found_name, &found_value);
+ if (val) {
+ if (strcmp(name, found_name) == 0) {
+ if (counter != internal_counter) {
+ internal_counter++;
+ } else {
+ return_string = (char *)
+ malloc(sizeof(char)*
+ strlen(found_value)+1);
+ strcpy(return_string, found_value);
+ if (found_name) free(found_name);
+ if (found_value) free(found_value);
+ return(return_string);
+ }
+ }
+ if (found_name) { free(found_name); found_name = NULL; }
+ if (found_value) { free(found_value); found_value = NULL; }
+ }
+ }
+
+ o_current=o_current->next;
+ }
+
+ if (found_name) free(found_name);
+ if (found_value) free(found_value);
+ return (NULL);
+}
+
+/*! \brief Search for special attributes.
+ * \par Function Description
+ * This function will search an OBJECT list for the special
+ * attributes <EM>"gnd"</EM> and <EM>"vdd"</EM>.
+ *
+ * \param [in] o_current The OBJECT list to search.
+ * \return Character string with attribute value, NULL otherwise.
+ *
+ * \warning
+ * Caller must free returned character string.
+ */
+/* be sure caller free's return value */
+char *o_attrib_search_special(OBJECT *o_current)
+{
+ char *return_value;
+
+ return_value = o_attrib_search_name(o_current->complex->prim_objs,
+ "gnd", 0);
+
+ if (return_value) {
+ return(return_value);
+ }
+
+ return_value = o_attrib_search_name(o_current->complex->prim_objs,
+ "vdd", 0);
+
+ if (return_value) {
+ return(return_value);
+ }
+
+ return(NULL);
+}
+
+#line 1849 "../noweb/o_attrib.nw"
+/*! \brief Search for first occurance of a named attribute.
+ * \par Function Description
+ * Search for first occurance of a named attribute.
+ *
+ * \param [in] object The OBJECT list to search.
+ * \param [in] name Character string of attribute name to search for.
+ * \param [out] return_found Contains attribute OBJECT if found, NULL otherwise.
+ * \return Character string with attribute value, NULL otherwise.
+ *
+ * \warning
+ * Caller must free returned character string.
+ */
+char *o_attrib_search_name_single(OBJECT *object, char *name,
+ OBJECT **return_found)
+{
+ OBJECT *o_current;
+ ATTRIB *a_current;
+ OBJECT *found=NULL;
+ int val;
+ char *found_name = NULL;
+ char *found_value = NULL;
+ char *return_string = NULL;
+
+ o_current = object;
+
+ if (o_current == NULL) {
+ return(NULL);
+ }
+
+ if (o_current->attribs != NULL) {
+ a_current = o_current->attribs;
+
+ while(a_current != NULL) {
+ found = a_current->object;
+ if (found != NULL) {
+ if (found->type == OBJ_TEXT) {
+ val = o_attrib_get_name_value(found->text->string,
+ &found_name, &found_value);
+
+ if (val) {
+ if (strcmp(name, found_name) == 0) {
+ return_string = (char *)
+ malloc(sizeof(char)*
+ strlen(found_value)+1);
+ strcpy(return_string, found_value);
+ if (return_found) {
+ *return_found = found;
+ }
+ if (found_name) free(found_name);
+ if (found_value) free(found_value);
+ return(return_string);
+ }
+ if (found_name) { free(found_name); found_name = NULL; }
+ if (found_value) { free(found_value); found_value = NULL; }
+ }
+
+#if DEBUG
+ printf("0 _%s_\n", found->text->string);
+ printf("1 _%s_\n", found_name);
+ printf("2 _%s_\n", found_value);
+#endif
+ }
+ }
+ a_current=a_current->next;
+ }
+ }
+ /* search for attributes outside */
+
+ if (o_current->type == OBJ_TEXT) {
+ if (found_name) free(found_name);
+ if (found_value) free(found_value);
+ val = o_attrib_get_name_value(o_current->text->string,
+ &found_name, &found_value);
+
+ if (val) {
+ if (strcmp(name, found_name) == 0) {
+ return_string = (char *)
+ malloc(sizeof(char)*
+ strlen(found_value)+1);
+ strcpy(return_string, found_value);
+ if (return_found) {
+ *return_found = found;
+ }
+ if (found_name) free(found_name);
+ if (found_value) free(found_value);
+ return(return_string);
+ }
+ if (found_name) { free(found_name); found_name = NULL; }
+ if (found_value) { free(found_value); found_value = NULL; }
+ }
+ }
+
+ if (return_found) {
+ *return_found = NULL;
+ }
+
+ if (found_name) free(found_name);
+ if (found_value) free(found_value);
+ return (NULL);
+}
+
+/*! \brief Search for N'th occurance of a named attribute.
+ * \par Function Description
+ * Search for N'th occurance of a named attribute.
+ *
+ * \param [in] object The OBJECT list to search.
+ * \param [in] name Character string of attribute name to search for.
+ * \param [in] counter Which occurance to return.
+ * \return Character string with attribute value, NULL otherwise.
+ *
+ * \warning
+ * Caller must free returned character string.
+ */
+/* be sure caller free's return value */
+/* this function is like above, except that it returns the n'th occurance */
+/* of the attribute. counter starts counting at zero */
+char *o_attrib_search_name_single_count(OBJECT *object, char *name,
+ int counter)
+{
+ OBJECT *o_current;
+ ATTRIB *a_current;
+ OBJECT *found=NULL;
+ int val;
+ char *found_name = NULL;
+ char *found_value = NULL;
+ char *return_string = NULL;
+ int internal_counter=0;
+
+
+ o_current = object;
+
+ if (o_current == NULL) {
+ return(NULL);
+ }
+
+ if (o_current->attribs != NULL) {
+ a_current = o_current->attribs;
+
+ while(a_current != NULL) {
+ found = a_current->object;
+ if (found != NULL) {
+ if (found->type == OBJ_TEXT) {
+ val = o_attrib_get_name_value(found->text->string,
+ &found_name, &found_value);
+
+ if (val) {
+ if (strcmp(name, found_name) == 0) {
+ if (counter != internal_counter) {
+ internal_counter++;
+ } else {
+ return_string = (char *)
+ malloc(sizeof(char)*
+ strlen(found_value)+1);
+ strcpy(return_string, found_value);
+ if (found_name) free(found_name);
+ if (found_value) free(found_value);
+ return(return_string);
+ }
+ }
+ if (found_name) { free(found_name); found_name = NULL; }
+ if (found_value) { free(found_value); found_value = NULL; }
+ }
+
+#if DEBUG
+ printf("0 _%s_\n", found->text->string);
+ printf("1 _%s_\n", found_name);
+ printf("2 _%s_\n", found_value);
+#endif
+ }
+ }
+ a_current=a_current->next;
+ }
+
+ }
+ /* search for attributes outside */
+
+ if (o_current->type == OBJ_TEXT) {
+ if (found_name) free(found_name);
+ if (found_value) free(found_value);
+ val = o_attrib_get_name_value(o_current->text->string,
+ &found_name, &found_value);
+
+ if (val) {
+ if (strcmp(name, found_name) == 0) {
+ if (counter != internal_counter) {
+ internal_counter++;
+ } else {
+ return_string = (char *)
+ malloc(sizeof(char)*
+ strlen(found_value)+1);
+ strcpy(return_string, found_value);
+ if (found_name) free(found_name);
+ if (found_value) free(found_value);
+ return(return_string);
+ }
+ }
+ if (found_name) { free(found_name); found_name = NULL; }
+ if (found_value) { free(found_value); found_value = NULL; }
+ }
+ }
+
+ if (found_name) free(found_name);
+ if (found_value) free(found_value);
+ return (NULL);
+}
+
+/*! \brief Search for slot attribute.
+ * \par Function Description
+ * Search for slot attribute.
+ *
+ * \param [in] object OBJECT list to search.
+ * \param [in] return_found slot attribute if found, NULL otherwise.
+ * \return Character string with attribute value, NULL otherwise.
+ *
+ * \warning
+ * Caller must free returned character string
+ */
+char *o_attrib_search_slot(OBJECT *object, OBJECT **return_found)
+{
+ char *return_value;
+
+ /* search for default value attribute buried inside the complex */
+ return_value = o_attrib_search_name_single(object, "slot", return_found);
+
+ /* I'm confused here does the next if get ever called? */
+ if (return_value) {
+ return(return_value);
+ }
+
+ if (return_found) {
+ *return_found = NULL;
+ }
+ return(NULL);
+}
+
+/*! \brief Search for numslots attribute.
+ * \par Function Description
+ * Search for numslots attribute.
+ *
+ * \param [in] object OBJECT to search.
+ * \param [in] return_found numslots attribute if found, NULL otherwise.
+ * \return Character string with attribute value, NULL otherwise.
+ *
+ * \note
+ * Caller must free returned character string.
+ */
+char *o_attrib_search_numslots(OBJECT *object, OBJECT **return_found)
+{
+ char *return_value;
+
+ /* search for numslots attribute buried inside the complex */
+ return_value = o_attrib_search_name(object->complex->prim_objs,
+ "numslots", 0);
+
+ if (return_value) {
+ return(return_value);
+ }
+
+ if (return_found) {
+ *return_found = NULL;
+ }
+ return(NULL);
+}
+
+/*! \brief Search for default slot attribute.
+ * \par Function Description
+ * Search for default slot attribute.
+ *
+ * \param [in] object OBJECT list to search.
+ * \return Character string with attribute value, NULL otherwise.
+ *
+ * \warning
+ * Caller must free returned character string.
+ */
+char *o_attrib_search_default_slot(OBJECT *object)
+{
+ char *return_value;
+
+ /* search for default value attribute buried inside the complex */
+ return_value = o_attrib_search_name(object->complex->prim_objs,
+ "slot", 0);
+
+ if (return_value) {
+ return(return_value);
+ }
+
+ return(NULL);
+}
+
+/*! \brief Search pinseq attribute.
+ * \par Function Description
+ * Search pinseq attribute.
+ *
+ * \param [in] list OBJECT list to search.
+ * \param [in] pin_number pin number to search for.
+ * \return OBJECT containing pinseq data, NULL otherwise.
+ */
+OBJECT *o_attrib_search_pinseq(OBJECT *list, int pin_number)
+{
+ OBJECT *pinseq_text_object;
+ char *search_for;
+
+ /* The 9 is the number of digits plus null */
+ search_for = (char *) malloc(sizeof(char)*(strlen("pinseq=")+9));
+ sprintf(search_for, "pinseq=%d", pin_number);
+
+ pinseq_text_object = o_attrib_search_string_list(list, search_for);
+ free(search_for);
+
+ if (pinseq_text_object && pinseq_text_object->attached_to) {
+ return(o_attrib_return_parent(pinseq_text_object->attached_to));
+ }
+
+ return(NULL);
+}
+
+/*! \brief Search for slotdef attribute.
+ * \par Function Description
+ * Search for slotdef attribute.
+ *
+ * \param [in] object The OBJECT list to search.
+ * \param [in] slotnumber The slot number to search for.
+ * \return Character string with attribute value, NULL otherwise.
+ *
+ * \warning
+ * Caller must free returned character string.
+ */
+char *o_attrib_search_slotdef(OBJECT *object, int slotnumber)
+{
+ char *return_value=NULL;
+ char *search_for=NULL;
+ OBJECT *o_current;
+
+ /* The 9 is the number of digits plus null */
+ search_for = (char *) malloc(sizeof(char)*(strlen("slotdef=:")+9));
+
+ sprintf(search_for, "slotdef=%d:", slotnumber);
+
+ o_current = object->complex->prim_objs;
+ while (o_current != NULL) {
+ return_value = o_attrib_search_string_partial(o_current, search_for, 0);
+ if (return_value) {
+ break;
+ }
+ o_current = o_current->next;
+ }
+ free(search_for);
+
+ if (return_value) {
+ return(return_value);
+ }
+
+ return(NULL);
+}
+
+/*! \brief Search for component.
+ * \par Function Description
+ * Search for component.
+ *
+ * \param [in] object The OBJECT list to search.
+ * \param [in] name Character string containing component name to match.
+ * \return Character string with the component value, NULL otherwise.
+ */
+char *o_attrib_search_component(OBJECT *object, char *name)
+{
+ char *return_value = NULL;
+
+ if (!name) {
+ return(NULL);
+ }
+
+ if (object->type != OBJ_COMPLEX && object->type != OBJ_PLACEHOLDER) {
+ return(NULL);
+ }
+
+ /* first look inside the complex object */
+ return_value = o_attrib_search_name(object->complex->prim_objs,
+ name, 0);
+
+ if (return_value) {
+ return(return_value);
+ }
+
+ /* now look outside to see if it was attached externally */
+ return_value = o_attrib_search_name_single(object, name, NULL);
+
+ if (return_value) {
+ return(return_value);
+ }
+
+ return(NULL);
+}
+
+/*! \brief Update all slot attributes in an object.
+ * \par Function Description
+ * Update all slot attributes in an object.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in,out] object The OBJECT to update.
+ */
+void o_attrib_slot_update(TOPLEVEL *w_current, OBJECT *object)
+{
+ OBJECT *o_current;
+ OBJECT *o_slot_attrib;
+ OBJECT *o_pin_object;
+ OBJECT *o_pinnum_object;
+ char *string;
+ char *slotdef;
+ int slot;
+ int pin_counter;
+ char* current_pin;
+ char* cptr;
+
+ o_current = object;
+
+ string = o_attrib_search_slot(o_current, &o_slot_attrib);
+
+ if (!string) {
+ /* s_log_message("Did not find slot= attribute\n"); */
+ /* not a serious error */
+ return;
+ }
+ slot = atoi(string);
+ free(string);
+
+ slotdef = o_attrib_search_slotdef(o_current, slot);
+
+ if (!slotdef) {
+ s_log_message("Did not find slotdef=#:#,#,#... attribute\n");
+ return;
+ }
+
+ if (!strstr(slotdef, ":")) {
+ /*! \todo didn't proper slotdef=#:... TODO into log*/
+ return;
+ }
+
+ /* skip over slotdef number */
+ /* slotdef is in the form #:#,#,# */
+ /* this code skips first #: */
+ cptr = slotdef;
+ while (*cptr != '\0' && *cptr != ':') {
+ cptr++;
+ }
+ cptr++; /* skip colon */
+
+ if (*cptr == '\0') {
+ s_log_message("Did not find proper slotdef=#:#,#,#... attribute\n");
+ return;
+ }
+
+ pin_counter = 1;
+ current_pin = strtok(cptr, DELIMITERS);
+ while(current_pin != NULL) {
+
+ o_pin_object = o_attrib_search_pinseq(o_current->complex->prim_objs,
+ pin_counter);
+
+ if (o_pin_object) {
+
+ string = o_attrib_search_name_single(o_pin_object, "pinnumber",
+ &o_pinnum_object);
+
+ if (string && o_pinnum_object && o_pinnum_object->type == OBJ_TEXT &&
+ o_pinnum_object->text->string) {
+ free(string);
+ free(o_pinnum_object->text->string);
+
+ /* 9 is the size of one number plus null character */
+ o_pinnum_object->text->string = (char *)
+ malloc(sizeof(char)*(strlen("pinnumber=")+strlen(current_pin)+9));
+
+ /* removed _int from current_pin */
+ sprintf(o_pinnum_object->text->string, "pinnumber=%s", current_pin);
+
+ o_text_recreate(w_current, o_pinnum_object);
+ }
+
+ pin_counter++;
+ } else {
+ s_log_message("component missing pinseq= attribute\n");
+ }
+
+ current_pin = strtok(NULL, DELIMITERS);
+ }
+
+ free(slotdef);
+}
+
+/*! \brief Copy attributes from OBJECT to OBJECT.
+ * \par Function Description
+ * This function will perform a slot copy of the <B>original</B> OBJECT
+ * to the <B>target</B> OBJECT.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] original The original OBJECT to slot copy from.
+ * \param [out] target The target OBJECT to slot copy to.
+ */
+void o_attrib_slot_copy(TOPLEVEL *w_current, OBJECT *original, OBJECT *target)
+{
+
+ OBJECT *o_current;
+ OBJECT *o_slot_attrib;
+ OBJECT *o_pin_object;
+ OBJECT *o_pinnum_object;
+ char *string;
+ char *slotdef;
+ int slot;
+ int pin_counter;
+ char* current_pin;
+ char* cptr;
+
+ o_current = original;
+
+ string = o_attrib_search_slot(o_current, &o_slot_attrib);
+
+ if (!string) {
+ /* s_log_message("Did not find slot= attribute\n"); */
+ /* not a serious error */
+ return;
+ }
+ slot = atoi(string);
+ free(string);
+
+ slotdef = o_attrib_search_slotdef(o_current, slot);
+
+ if (!slotdef) {
+ s_log_message("Did not find slotdef=#:#,#,#... attribute\n");
+ return;
+ }
+
+ if (!strstr(slotdef, ":")) {
+ /*! \todo didn't proper slotdef=#:... TODO into log*/
+ return;
+ }
+
+ /* skip over slotdef number */
+ /* slotdef is in the form #:#,#,# */
+ /* this code skips first #: */
+ cptr = slotdef;
+ while (*cptr != '\0' && *cptr != ':') {
+ cptr++;
+ }
+ cptr++; /* skip colon */
+
+ if (*cptr == '\0') {
+ s_log_message("Did not find proper slotdef=#:#,#,#... attribute\n");
+ return;
+ }
+
+ pin_counter = 1;
+ current_pin = strtok(cptr, DELIMITERS);
+ while(current_pin != NULL) {
+
+ o_pin_object = o_attrib_search_pinseq(target->complex->prim_objs,
+ pin_counter);
+
+ if (o_pin_object) {
+
+ string = o_attrib_search_name_single(o_pin_object, "pinnumber",
+ &o_pinnum_object);
+
+ if (string && o_pinnum_object && o_pinnum_object->type == OBJ_TEXT &&
+ o_pinnum_object->text->string) {
+
+ free(string);
+ free(o_pinnum_object->text->string);
+
+ /* 9 is the size of one number plus null character */
+ o_pinnum_object->text->string = (char *)
+ malloc(sizeof(char)*(strlen("pinnumber=")+strlen(current_pin)+9));
+
+ /* removed _int from current_pin */
+ sprintf(o_pinnum_object->text->string, "pinnumber=%s", current_pin);
+
+ o_text_recreate(w_current, o_pinnum_object);
+ }
+
+ pin_counter++;
+ } else {
+ s_log_message("component missing pinseq= attribute\n");
+ }
+
+ current_pin = strtok(NULL, DELIMITERS);
+ }
+
+ free(slotdef);
+}
+
+/*! \brief Get the number of TOPLEVEL attributes in all loaded pages.
+ * \par Function Description
+ * This function will return the number of TOPLEVEL attributes
+ * in all loaded pages.
+ *
+ * \param [in] w_current The TOPLEVEL object to search.
+ * \param [in] name Attribute name to search for.
+ * \return Count of TOPLEVEL attributes in all loaded pages.
+ */
+/* returns the number of toplevel attributes in all loaded pages */
+int o_attrib_count_toplevel(TOPLEVEL *w_current, char *name)
+{
+ int ret_value=0;
+ int counter=0;
+ PAGE *p_current;
+ char *string;
+
+ p_current = w_current->page_head;
+
+ while(p_current != NULL) {
+
+ counter = 0;
+ string = o_attrib_search_name(p_current->object_head,
+ name, counter);
+ printf("%s %d\n", name, counter);
+ while(string) {
+ printf("inside\n");
+ ret_value++;
+ free(string);
+ string=NULL;
+ counter++;
+
+ string = o_attrib_search_name(p_current->object_head,
+ name, counter);
+ }
+
+ p_current=p_current->next;
+ }
+ return(ret_value);
+}
+
+/*! \brief Search for first TOPLEVEL attribute.
+ * \par Function Description
+ * This function searches all loaded pages for the first
+ * TOPLEVEL attribute found.
+ * The caller is responsible for freeing the returned value.
+ * See #o_attrib_search_toplevel() for other comments.
+ *
+ * \param [in] page_head PAGE head object to search through.
+ * \param [in] name Character string name to search for.
+ * \return Character string from the found attribute, NULL otherwise.
+ */
+char *o_attrib_search_toplevel_all(PAGE *page_head, char *name)
+{
+ PAGE *p_current;
+ char *ret_value=NULL;
+
+ p_current = page_head;
+
+ while (p_current != NULL) {
+
+
+ /* don't look into the head of page_head */
+ if (p_current->pid != -1) {
+
+ /* only look for first occurrance of the attribute */
+ ret_value = o_attrib_search_toplevel(
+ p_current->object_head,
+ name, 0);
+ }
+
+ if (ret_value != NULL) {
+ return(ret_value);
+ }
+
+ p_current = p_current->next;
+ }
+
+ return(NULL);
+}
+
+/*! \brief Get all attached attributes to specified OBJECT.
+ * \par Function Description
+ * This function returns all attached attribute objects to the
+ * specified object.
+ * The returned list is an array of objects and should be freed using the
+ * #o_attrib_free_returned() function.
+ * This function will only look for attached attributes and not
+ * unattached free floating attribs.
+ *
+ * \param [in] object_list OBJECT list to search.
+ * \param [in] sel_object OBJECT to search for.
+ * \return An array of objects that matched sel_object, NULL otherwise.
+ */
+OBJECT ** o_attrib_return_attribs(OBJECT *object_list, OBJECT *sel_object)
+{
+ OBJECT **found_objects;
+ int num_attribs=0;
+ int i=0;
+ ATTRIB *a_current;
+ OBJECT *o_current;
+ OBJECT *object;
+
+ object = (OBJECT *) o_list_search(object_list, sel_object);
+
+ if (!object) {
+ return(NULL);
+ }
+
+ if (!object->attribs) {
+ return(NULL);
+ }
+
+ if (!object->attribs->next) {
+ return(NULL);
+ }
+
+
+ /* first go through and count the number of attribs */
+ a_current = object->attribs->next;
+ while(a_current != NULL) {
+ num_attribs++;
+ a_current = a_current->next;
+ }
+
+ found_objects = (OBJECT **) malloc(sizeof(OBJECT *)*(num_attribs+1));
+
+ /* now actually fill the array of objects */
+ a_current = object->attribs->next;
+ while(a_current != NULL) {
+ if (a_current->object != NULL) {
+ o_current = a_current->object;
+ if (o_current->type == OBJ_TEXT &&
+ o_current->text->string) {
+ found_objects[i] = o_current;
+ i++;
+ }
+ }
+ a_current = a_current->next;
+ }
+
+ found_objects[i] = NULL;
+
+#if DEBUG
+ i=0;
+ while(found_objects[i] != NULL) {
+ /*for (i = 0 ; i < num_attribs; i++) {*/
+ printf("%d : %s\n", i, found_objects[i]->text->string);
+ i++;
+ }
+#endif
+
+ return(found_objects);
+}
+
+/*! \brief Free attached attribute list.
+ * \par Function Description
+ * Free attached attribute list. Use only on a list created
+ * by #o_attrib_return_attribs().
+ *
+ * \param [in] found_objects List returned by #o_attrib_return_attribs().
+ */
+void o_attrib_free_returned(OBJECT **found_objects)
+{
+ int i=0;
+
+ if (!found_objects) {
+ return;
+ }
+
+ /* don't free the insides of found_objects, since the contents are */
+ /* just pointers into the real object list */
+ while(found_objects[i] != NULL) {
+ found_objects[i] = NULL;
+ i++;
+ }
+
+ free(found_objects);
+}
1.14 +213 -116 eda/geda/gaf/libgeda/src/o_basic.c
(In the diff below, changes in quantity of whitespace are not shown.)
Index: o_basic.c
===================================================================
RCS file: o_basic.c
diff -N o_basic.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ o_basic.c 5 Jul 2006 03:13:38 -0000 1.14
@@ -0,0 +1,279 @@
+/* gEDA - GPL Electronic Design Automation
+ * libgeda - gEDA's library
+ * Copyright (C) 1998-2000 Ales V. Hvezda
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+#include <config.h>
+
+#include <stdio.h>
+
+/* instrumentation code */
+#if 0
+#include <sys/time.h>
+#include <unistd.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <libguile.h>
+
+#include "defines.h"
+#include "struct.h"
+#include "globals.h"
+#include "o_types.h"
+#include "colors.h"
+
+#include "../include/prototype.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+/* \todo
+ * Lots of Gross code... needs lots of cleanup
+ * mainly readability issues
+ */
+
+/*! \brief Check if point is inside a region
+ * \par Function Description
+ * This function takes a rectangular region and a point. It will check
+ * if the point is located in the region or not.
+ *
+ * \param [in] left Left coordinate of the region.
+ * \param [in] top Top coordinate of the region.
+ * \param [in] right Right coordinate of the region.
+ * \param [in] bottom Bottom coordinate of the region.
+ * \param [in] x x coordinate of the point to check.
+ * \param [in] y y coordinate of the point to check.
+ * \return 1 if the point is inside the region, 0 otherwise.
+ */
+int inside_region(int left, int top, int right, int bottom, int x, int y)
+{
+ return ((x >= left && x <= right && y >= top && y <= bottom) ? 1 : 0);
+}
+
+/*! \brief Redraw an object on the screen.
+ * \par Function Description
+ * This function will redraw a single object on the screen.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] o_current The OBJECT to redraw.
+ *
+ */
+void o_redraw_single(TOPLEVEL *w_current, OBJECT *o_current)
+{
+ if (o_current == NULL)
+ return;
+
+ if (w_current->DONT_REDRAW) /* highly experimental */
+ return;
+
+ if (o_current->draw_func != NULL && o_current->type != OBJ_HEAD) {
+ w_current->inside_redraw = 1;
+ (*o_current->draw_func)(w_current, o_current);
+ w_current->inside_redraw = 0;
+ }
+}
+
+/*! \brief Recalculate position of all objects.
+ * \par Function Description
+ * This function will take a list of objects and recalculate their
+ * positions on the screen.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in,out] object_list OBJECT list to recalculate.
+ *
+ */
+void o_recalc(TOPLEVEL *w_current, OBJECT *object_list)
+{
+ OBJECT *o_current;
+
+ if (object_list == NULL)
+ return;
+
+ o_current = object_list;
+ while (o_current != NULL) {
+ switch(o_current->type) {
+
+ case(OBJ_LINE):
+ o_line_recalc(w_current, o_current);
+ break;
+
+ case(OBJ_NET):
+ o_net_recalc(w_current, o_current);
+ break;
+
+ case(OBJ_BUS):
+ o_bus_recalc(w_current, o_current);
+ break;
+
+ case(OBJ_BOX):
+ o_box_recalc(w_current, o_current);
+ break;
+
+ case(OBJ_PICTURE):
+ o_picture_recalc(w_current, o_current);
+ break;
+
+ case(OBJ_CIRCLE):
+ o_circle_recalc(w_current, o_current);
+ break;
+
+ case(OBJ_COMPLEX):
+ case(OBJ_PLACEHOLDER):
+ o_complex_recalc(w_current, o_current);
+ break;
+
+ case(OBJ_PIN):
+ o_pin_recalc(w_current, o_current);
+ break;
+
+ case(OBJ_ARC):
+ o_arc_recalc(w_current, o_current);
+ break;
+ }
+
+ o_current = o_current->next;
+ }
+}
+
+/*! \brief Set an #OBJECT's line options.
+ * \par Function Description
+ * This function allows a line's end, type, width, length and space to be set.
+ * See #OBJECT_END and #OBJECT_TYPE for information on valid
+ * object end and type values.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in,out] o_current OBJECT to set line options on.
+ * \param [in] end An OBJECT_END.
+ * \param [in] type An OBJECT_TYPE.
+ * \param [in] width Line width.
+ * \param [in] length Line length.
+ * \param [in] space Spacing between dashes/dots. Cannot be negative.
+ *
+ * \todo Make space an unsigned int and check for a max value instead.
+ * If a max value is not required, then it would simplify the code.
+ */
+void o_set_line_options(TOPLEVEL *w_current, OBJECT *o_current,
+ OBJECT_END end, OBJECT_TYPE type,
+ int width, int length, int space)
+{
+ if(o_current == NULL) {
+ return;
+ }
+
+ /* do some error checking / correcting */
+ switch(type) {
+ case(TYPE_DOTTED):
+ if (space < 1) {
+ space = 100;
+ s_log_message ("Invalid space specified, setting to 100\n");
+ }
+ break;
+ case(TYPE_DASHED):
+ case(TYPE_CENTER):
+ case(TYPE_PHANTOM):
+ if (length < 1) {
+ length = 100;
+ s_log_message ("Invalid length specified, setting to 100\n");
+ }
+ if (space < 1) {
+ space = 100;
+ s_log_message ("Invalid space specified, setting to 100\n");
+ }
+ break;
+ default:
+
+ break;
+ }
+
+ o_current->line_width = width;
+ o_current->line_end = end;
+ o_current->line_type = type;
+
+ o_current->line_length = length;
+ o_current->line_space = space;
+}
+
+/*! \brief Set #OBJECT's fill options.
+ * \par Function Description
+ * This function allows an #OBJECT's fill options to be configured.
+ * See #OBJECT_FILLING for information on valid fill types.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in,out] o_current OBJECT to be updated.
+ * \param [in] type OBJECT_FILLING type.
+ * \param [in] width fill width.
+ * \param [in] pitch1 cross hatch???.
+ * \param [in] angle1 cross hatch???.
+ * \param [in] pitch2 cross hatch???.
+ * \param [in] angle2 cross hatch???.
+ *
+ */
+void o_set_fill_options(TOPLEVEL *w_current, OBJECT *o_current,
+ OBJECT_FILLING type, int width,
+ int pitch1, int angle1,
+ int pitch2, int angle2)
+{
+ if(o_current == NULL) {
+ return;
+ }
+
+ o_current->fill_type = type;
+ o_current->fill_width = width;
+
+ o_current->fill_pitch1 = pitch1;
+ o_current->fill_angle1 = angle1;
+
+ o_current->fill_pitch2 = pitch2;
+ o_current->fill_angle2 = angle2;
+
+}
+
+/*! \brief Recalculate a single OBJECT in screen coordinates.
+ * \par Function Description
+ * This function takes an OBJECT and converts it to SCREEN coordinates.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in,out] o_current OBJECT to recalculate.
+ *
+ */
+void o_object_recalc(TOPLEVEL *w_current, OBJECT *o_current)
+{
+ int width, length, space, pitch;
+
+ if(o_current == NULL) {
+ return;
+ }
+
+ width = SCREENabs(w_current, o_current->line_width);
+ o_current->screen_line_width = width;
+
+ length = SCREENabs(w_current, o_current->line_length);
+ o_current->screen_line_length = length;
+
+ space = SCREENabs(w_current, o_current->line_space);
+ o_current->screen_line_space = space;
+
+ width = SCREENabs(w_current, o_current->fill_width);
+ o_current->screen_fill_width = width;
+ pitch = SCREENabs(w_current, o_current->fill_pitch1);
+ o_current->screen_fill_pitch1 = pitch;
+ pitch = SCREENabs(w_current, o_current->fill_pitch2);
+ o_current->screen_fill_pitch2 = pitch;
+
+}
+
+
1.22 +1479 -1021eda/geda/gaf/libgeda/src/o_box_basic.c
(In the diff below, changes in quantity of whitespace are not shown.)
Index: o_box_basic.c
===================================================================
RCS file: o_box_basic.c
diff -N o_box_basic.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ o_box_basic.c 5 Jul 2006 03:13:38 -0000 1.22
@@ -0,0 +1,1703 @@
+/* gEDA - GPL Electronic Design Automation
+ * libgeda - gEDA's library
+ * Copyright (C) 1998-2000 Ales V. Hvezda
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+#include <config.h>
+#include <math.h>
+#include <stdio.h>
+
+#include <gtk/gtk.h>
+#include <libguile.h>
+
+#ifdef HAS_LIBGDGEDA
+#include <gdgeda/gd.h>
+#endif
+
+#include "defines.h"
+#include "struct.h"
+#include "globals.h"
+#include "o_types.h"
+#include "colors.h"
+#include "funcs.h"
+
+#include "../include/prototype.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+/* Kazu on July 16, 1999 - Added these macros to simplify the code */
+/*! \brief Returns the box width.
+ * Returns the box width.
+ */
+#define GET_BOX_WIDTH(w) \
+ abs((w)->last_x - (w)->start_x)
+/*! \brief Returns the box height.
+ * Returns the box height.
+ */
+#define GET_BOX_HEIGHT(w) \
+ abs((w)->last_y - (w)->start_y)
+/*! \brief Returns the box left coordinate.
+ * Returns the box left coordinate.
+ */
+#define GET_BOX_LEFT(w) \
+ min((w)->start_x, (w)->last_x);
+/*! \brief Returns the box left coordinate.
+ * Returns the box left coordinate.
+ */
+#define GET_BOX_TOP(w) \
+ min((w)->start_y, (w)->last_y);
+
+/*! \brief Create a BOX and add it to a list.
+ * \par Function Description
+ * This function creates a new object representing a box.
+ * This object is added to the end of the list <B>object_list</B>
+ * pointed object belongs to.
+ * The box is described by its upper left corner - <B>x1</B>, <B>y1</B> - and
+ * its lower right corner - <B>x2</B>, <B>y2</B>.
+ * The <B>type</B> parameter must be equal to <B>OBJ_BOX</B>. The <B>color</B>
+ * corresponds to the color the box will be drawn with.
+ * The <B>OBJECT</B> structure is allocated with the #s_basic_init_object()
+ * function. The structure describing the box is allocated and initialized
+ * with the parameters given to the function.
+ *
+ * Both the line type and the filling type are set to default values : solid
+ * line type with a width of 0, and no filling. It can be changed after
+ * with the #o_set_line_options() and #o_set_fill_options().
+ *
+ * The object is added to the end of the list described by the <B>object_list</B>
+ * parameter by the #s_basic_link_object().
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in,out] object_list OBJECT list to add box to.
+ * \param [in] type Box type.
+ * \param [in] color Box border color.
+ * \param [in] x1 Upper x coordinate.
+ * \param [in] y1 Upper y coordinate.
+ * \param [in] x2 Lower x coordinate.
+ * \param [in] y2 Lower y coordinate.
+ * \return A new pointer on the end of the <B>object_list</B>
+ */
+OBJECT *o_box_add(TOPLEVEL *w_current, OBJECT *object_list,
+ char type, int color,
+ int x1, int y1, int x2, int y2)
+{
+ OBJECT *new_node;
+ BOX *box;
+
+ /* create the object */
+ new_node = s_basic_init_object("box");
+ new_node->type = type;
+ new_node->color = color;
+
+ box = (BOX *) malloc(sizeof(BOX));
+ new_node->box = box;
+
+ /* describe the box with its upper left and lower right corner */
+ box->upper_x = x1;
+ box->upper_y = y1;
+ box->lower_x = x2;
+ box->lower_y = y2;
+
+ /* line type and filling initialized to default */
+ o_set_line_options(w_current, new_node,
+ END_NONE, TYPE_SOLID, 0, -1, -1);
+ o_set_fill_options(w_current, new_node,
+ FILLING_HOLLOW, -1, -1, -1, -1, -1);
+
+ /* \todo questionable cast */
+ new_node->draw_func = (void *) box_draw_func;
+ /* \todo questionable cast */
+ new_node->sel_func = (void *) select_func;
+
+ /* compute the bounding box */
+ o_box_recalc(w_current, new_node);
+
+ /* add the object to the list */
+ object_list = (OBJECT *) s_basic_link_object(new_node, object_list);
+
+ return(object_list);
+}
+
+/*! \brief Copy a box to a list.
+ * \par Function Description
+ * The function #o_box_copy() creates a verbatim copy of the object
+ * pointed by <B>o_current</B> describing a box. The new object is added at
+ * the end of the list, following the <B>list_tail</B> pointed object.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in,out] list_tail OBJECT list to copy to.
+ * \param [in] o_current BOX OBJECT to copy.
+ * \return A new pointer on the end of the OBJECT <B>list_tail</B>.
+ */
+OBJECT *o_box_copy(TOPLEVEL *w_current, OBJECT *list_tail, OBJECT *o_current)
+{
+ OBJECT *new_obj;
+ ATTRIB *a_current;
+ int color;
+
+ if (o_current->saved_color == -1) {
+ color = o_current->color;
+ } else {
+ color = o_current->saved_color;
+ }
+
+ /*
+ * A new box object is added at the end of the object list with
+ * #o_box_add(). Values for its fields are default and need to
+ * be modified.
+ */
+
+ /* create and link a new box object */
+ new_obj = o_box_add(w_current, list_tail,
+ OBJ_BOX, color,
+ 0, 0, 0, 0);
+
+ /*
+ * The dimensions of the new box are set with the ones of the original box.
+ * The two boxes have the same line type and the same filling options.
+ *
+ * The coordinates and the values in screen unit are computed with
+ * #o_box_recalc().
+ */
+
+ /* modifying */
+ /* pb20011002 - have to check if o_current is a box object */
+ new_obj->box->upper_x = o_current->box->upper_x;
+ new_obj->box->upper_y = o_current->box->upper_y;
+ new_obj->box->lower_x = o_current->box->lower_x;
+ new_obj->box->lower_y = o_current->box->lower_y;
+
+ o_set_line_options(w_current, new_obj, o_current->line_end,
+ o_current->line_type, o_current->line_width,
+ o_current->line_length, o_current->line_space);
+ o_set_fill_options(w_current, new_obj,
+ o_current->fill_type, o_current->fill_width,
+ o_current->fill_pitch1, o_current->fill_angle1,
+ o_current->fill_pitch2, o_current->fill_angle2);
+
+ o_box_recalc(w_current, new_obj);
+
+ /* new_obj->attribute = 0;*/
+ a_current = o_current->attribs;
+ if (a_current) {
+ while ( a_current ) {
+
+ /* head attrib node has prev = NULL */
+ if (a_current->prev != NULL) {
+ a_current->copied_to = new_obj;
+ }
+ a_current = a_current->next;
+ }
+ }
+
+ /* return the new tail of the object list */
+ return(new_obj);
+}
+
+/*! \brief Modify a BOX OBJECT's coordinates.
+ * \par Function Description
+ * This function modifies the coordinates of one of the four corner of
+ * the box. The new coordinates of the corner identified by <B>whichone</B>
+ * are given by <B>x</B> and <B>y</B> in world unit.
+ *
+ * The coordinates of the corner is modified in the world coordinate system.
+ * Screen coordinates and boundings are then updated.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in,out] object BOX OBJECT to be modified.
+ * \param [in] x x coordinate.
+ * \param [in] y y coordinate.
+ * \param [in] whichone coordinate to change.
+ *
+ * \note
+ * <B>whichone</B> can take the following values:
+ * <DL>
+ * <DT>*</DT><DD>BOX_UPPER_LEFT
+ * <DT>*</DT><DD>BOX_LOWER_LEFT
+ * <DT>*</DT><DD>BOX_UPPER_RIGHT
+ * <DT>*</DT><DD>BOX_LOWER_RIGHT
+ * </DL>
+ *
+ * \par Author's Note:
+ * pb20011002 - rewritten : old one did not used <B>x</B>, <B>y</B> and
+ * <B>whichone</B>
+ */
+void o_box_modify(TOPLEVEL *w_current, OBJECT *object,
+ int x, int y, int whichone)
+{
+ int tmp;
+
+ /* change the position of the selected corner */
+ switch(whichone) {
+ case BOX_UPPER_LEFT:
+ object->box->upper_x = x;
+ object->box->upper_y = y;
+ break;
+
+ case BOX_LOWER_LEFT:
+ object->box->upper_x = x;
+ object->box->lower_y = y;
+ break;
+
+ case BOX_UPPER_RIGHT:
+ object->box->lower_x = x;
+ object->box->upper_y = y;
+ break;
+
+ case BOX_LOWER_RIGHT:
+ object->box->lower_x = x;
+ object->box->lower_y = y;
+ break;
+
+ default:
+ return;
+ }
+
+ /* need to update the upper left and lower right corners */
+ if(object->box->upper_x > object->box->lower_x) {
+ tmp = object->box->upper_x;
+ object->box->upper_x = object->box->lower_x;
+ object->box->lower_x = tmp;
+ }
+
+ if(object->box->upper_y < object->box->lower_y) {
+ tmp = object->box->upper_y;
+ object->box->upper_y = object->box->lower_y;
+ object->box->lower_y = tmp;
+ }
+
+ /* recalculate the screen coords and the boundings */
+ o_box_recalc(w_current, object);
+
+}
+
+/*! \brief Create a box from a character string.
+ * \par Function Description
+ * This function gets the description of a box from the <B>*buf</B> character
+ * string. The new box is then added to the list of object of which
+ * <B>*object_list</B> is the last element before the call.
+ *
+ * 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 20000704 release
+ * <DT>*</DT><DD>the file format used for the releases after 2000704.
+ * </DL>
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in,out] object_list BOX OBJECT list to add new BOX to.
+ * \param [in] buf Character string with box description.
+ * \param [in] release_ver libgeda release version number.
+ * \param [in] fileformat_ver libgeda file format version number.
+ * \return The BOX OBJECT that was created.
+ */
+OBJECT *o_box_read(TOPLEVEL *w_current, OBJECT *object_list, char buf[],
+ unsigned int release_ver, unsigned int fileformat_ver)
+{
+ char type;
+ int x1, y1;
+ int width, height;
+ int d_x1, d_y1;
+ int d_x2, d_y2;
+ int color;
+ int box_width, box_space, box_length;
+ int fill_width, angle1, pitch1, angle2, pitch2;
+ int box_end;
+ int box_type;
+ int box_filling;
+
+ if(release_ver <= VERSION_20000704) {
+
+ /*! \note
+ * The old geda file format, i.e. releases 20000704 and older, does not
+ * handle the line type and the filling of the box object. They are set
+ * to default.
+ */
+
+ sscanf(buf, "%c %d %d %d %d %d\n",
+ &type, &x1, &y1, &width, &height, &color);
+
+ box_width = 0;
+ box_end = END_NONE;
+ box_type = TYPE_SOLID;
+ box_length = -1;
+ box_space = -1;
+
+ box_filling = FILLING_HOLLOW;
+ fill_width = 0;
+ angle1 = -1;
+ pitch1 = -1;
+ angle2 = -1;
+ pitch2 = -1;
+
+ } else {
+
+ /*! \note
+ * The current line format to describe a box is a space separated list of
+ * characters and numbers in plain ASCII on a single line. The meaning of
+ * each item is described in the file format documentation.
+ */
+ sscanf(buf, "%c %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
+ &type, &x1, &y1, &width, &height, &color,
+ &box_width, &box_end, &box_type, &box_length,
+ &box_space, &box_filling,
+ &fill_width, &angle1, &pitch1, &angle2, &pitch2);
+ }
+
+ if (width == 0 || height == 0) {
+ fprintf(stderr, "Found a zero width/height box [ %c %d %d %d %d %d ]\n",
+ type, x1, y1, width, height, color);
+ s_log_message("Found a zero width/height box [ %c %d %d %d %d %d ]\n",
+ type, x1, y1, width, height, color);
+ }
+
+ if (color < 0 || color > MAX_COLORS) {
+ fprintf(stderr, "Found an invalid color [ %s ]\n", buf);
+ s_log_message("Found an invalid color [ %s ]\n", buf);
+ s_log_message("Setting color to WHITE\n");
+ color = WHITE;
+ }
+
+ /*! \note
+ * A box is internally described by its lower right and upper left corner
+ * whereas the line describe it with the lower left corner and the width
+ * and height.
+ *
+ * A new object is allocated, initialized and added to the object list.
+ * Its filling and line type are set according to the values of the field
+ * on the line.
+ */
+
+ /* upper left corner of the box */
+ d_x1 = x1;
+ d_y1 = y1+height; /* move box origin to top left */
+
+ /* lower right corner of the box */
+ d_x2 = x1+width; /* end points of the box */
+ d_y2 = y1;
+
+ /* create and add the box to the list */
+ object_list = (OBJECT *) o_box_add(w_current, object_list,
+ type, color,
+ d_x1, d_y1, d_x2, d_y2);
+ /* set its line options */
+ o_set_line_options(w_current, object_list,
+ box_end, box_type, box_width,
+ box_length, box_space);
+ /* set its fill options */
+ o_set_fill_options(w_current, object_list,
+ box_filling, fill_width,
+ pitch1, angle1, pitch2, angle2);
+ return(object_list);
+}
+
+/*! \brief Create a character string representation of a BOX.
+ * \par Function Description
+ * This function formats a string in the buffer <B>*buff</B> to describe the
+ * box object <B>*object</B>.
+ * It follows the post-20000704 release file format that handle the line type
+ * and fill options.
+ *
+ * \param [in] object The BOX OBJECT to create string from.
+ * \return A pointer to the BOX character string.
+ *
+ * \warning
+ * Caller must free returned character string.
+ */
+char *o_box_save(OBJECT *object)
+{
+ int x1, y1;
+ int width, height;
+ int color;
+ int box_width, box_space, box_length;
+ int fill_width, angle1, pitch1, angle2, pitch2;
+ OBJECT_END box_end;
+ OBJECT_TYPE box_type;
+ OBJECT_FILLING box_fill;
+ char *buf;
+
+ /*! \note
+ * A box is internally represented by its lower right and upper left corner
+ * whereas it is described in the file format as its lower left corner and
+ * its width and height.
+ */
+
+ /* calculate the width and height of the box */
+ width = abs(object->box->lower_x - object->box->upper_x);
+ height = abs(object->box->upper_y - object->box->lower_y);
+
+ /* calculate the lower left corner of the box */
+ x1 = object->box->upper_x;
+ y1 = object->box->upper_y - height; /* move the origin to 0, 0*/
+
+#if DEBUG
+ printf("box: %d %d %d %d\n", x1, y1, width, height);
+#endif
+
+ /* description of the line type for the outline */
+ box_end = object->line_end;
+ box_width = object->line_width;
+ box_type = object->line_type;
+ box_length = object->line_length;
+ box_space = object->line_space;
+
+ /* description of the filling of the box */
+ box_fill = object->fill_type;
+ fill_width = object->fill_width;
+ angle1 = object->fill_angle1;
+ pitch1 = object->fill_pitch1;
+ angle2 = object->fill_angle2;
+ pitch2 = object->fill_pitch2;
+
+ /* Use the right color */
+ if (object->saved_color == -1) {
+ color = object->color;
+ } else {
+ color = object->saved_color;
+ }
+
+
+ buf = g_strdup_printf("%c %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d",
+ object->type,
+ x1, y1, width, height, color,
+ box_width, box_end, box_type, box_length, box_space,
+ box_fill,
+ fill_width, angle1, pitch1, angle2, pitch2);
+
+ return(buf);
+}
+
+/*! \brief Translate a BOX position by a delta.
+ * \par Function Description
+ * This function applies a translation of (<B>dx</B>,<B>dy</B>) to the box
+ * described by <B>*object</B>. <B>dx</B> and <B>dy</B> are in screen unit.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] dx x distance to move.
+ * \param [in] dy y distance to move.
+ * \param [in,out] object BOX OBJECT to translate.
+ */
+void o_box_translate(TOPLEVEL *w_current, int dx, int dy, OBJECT *object)
+{
+ int world_dx, world_dy;
+
+ if (object == NULL) printf("bt NO!\n");
+
+ /* convert the translation vector in world unit */
+ world_dx = SCREENabs(w_current, dx);
+ world_dy = SCREENabs(w_current, dy);
+
+ /* translate the box */
+ o_box_translate_world(w_current, world_dx, world_dy, object);
+
+ /* screen coords and boundings are updated by _translate_world */
+
+}
+
+/*! \brief Translate a BOX position in WORLD coordinates by a delta.
+ * \par Function Description
+ * This function applies a translation of (<B>x1</B>,<B>y1</B>) to the box
+ * described by <B>*object</B>. <B>x1</B> and <B>y1</B> are in world unit.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] x1 x distance to move.
+ * \param [in] y1 y distance to move.
+ * \param [in,out] object BOX OBJECT to translate.
+ */
+void o_box_translate_world(TOPLEVEL *w_current, int x1, int y1, OBJECT *object)
+{
+ if (object == NULL) printf("btw NO!\n");
+
+ /* Do world coords */
+ object->box->upper_x = object->box->upper_x + x1;
+ object->box->upper_y = object->box->upper_y + y1;
+ object->box->lower_x = object->box->lower_x + x1;
+ object->box->lower_y = object->box->lower_y + y1;
+
+ /* recalc the screen coords and the bounding box */
+ o_box_recalc(w_current, object);
+}
+
+/*! \brief Rotate a BOX OBJECT.
+ * \par Function Description
+ * This function applies a rotation of center (<B>centerx</B>, <B>centery</B>) and
+ * angle <B>angle</B> to the box object <B>*object</B>.
+ * The coordinates of the rotation center are in screen units.
+ * <B>angle</B> must be a 90 degree multiple. If not, no rotation is applied.
+ *
+ * The rotation is made with the #o_box_rotate_world() function that
+ * perform a rotation of angle <B>angle</B> and center (<B>world_centerx</B>,
+ * <B>world_centery</B>) in world unit.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] centerx Rotation center x coordinate in SCREEN units.
+ * \param [in] centery Rotation center y coordinate in SCREEN units.
+ * \param [in] angle Rotation angle in degrees (unused).
+ * \param [in,out] object BOX OBJECT to rotate.
+ *
+ * \note
+ * takes in screen coordinates for the centerx,y, and then does the rotate
+ * in world space
+ * also ignores angle argument... for now, rotate only in 90 degree
+ * increments
+ * fixed to 90 degrees... it's *not* general now
+ */
+void o_box_rotate(TOPLEVEL *w_current,
+ int centerx, int centery, int angle,
+ OBJECT *object)
+{
+ int world_centerx, world_centery;
+
+ /* convert the center of rotation to world unit */
+ SCREENtoWORLD(w_current,
+ centerx, centery,
+ &world_centerx, &world_centery);
+
+ /* rotate the box */
+ /* the check of the rotation angle is in o_box_rotate_world() */
+ o_box_rotate_world(w_current,
+ world_centerx, world_centery, angle,
+ object);
+
+ /* screen coords and boundings are updated by _rotate_world() */
+
+}
+
+/*! \brief Rotate BOX OBJECT using WORLD coordinates.
+ * \par Function Description
+ * The function #o_box_rotate_world() rotate the box described by
+ * <B>*object</B> around the (<B>world_centerx</B>, <B>world_centery</B>) point by
+ * <B>angle</B> degrees.
+ * The center of rotation is in world unit.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] world_centerx Rotation center x coordinate in WORLD units.
+ * \param [in] world_centery Rotation center y coordinate in WORLD units.
+ * \param [in] angle Rotation angle in degrees (See note below).
+ * \param [in,out] object BOX OBJECT to rotate.
+ *
+ */
+void o_box_rotate_world(TOPLEVEL *w_current,
+ int world_centerx, int world_centery, int angle,
+ OBJECT *object)
+{
+ int newx1, newy1;
+ int newx2, newy2;
+
+ /*! \note
+ * Only 90 degree multiple and positive angles are allowed.
+ */
+
+ /* angle must be positive */
+ if(angle < 0) angle = -angle;
+ /* angle must be a 90 multiple or no rotation performed */
+ if((angle % 90) != 0) return;
+
+ /*! \note
+ * The center of rotation (<B>world_centerx</B>, <B>world_centery</B>) is
+ * translated to the origin. The rotation of the upper left and lower right
+ * corner are then performed. Finally, the rotated box is translated back
+ * to its previous location.
+ */
+ /* translate object to origin */
+ object->box->upper_x -= world_centerx;
+ object->box->upper_y -= world_centery;
+ object->box->lower_x -= world_centerx;
+ object->box->lower_y -= world_centery;
+
+ /* rotate the upper left corner of the box */
+ rotate_point_90(object->box->upper_x, object->box->upper_y, angle,
+ &newx1, &newy1);
+
+ /* rotate the lower left corner of the box */
+ rotate_point_90(object->box->lower_x, object->box->lower_y, angle,
+ &newx2, &newy2);
+
+ /* reorder the corners after rotation */
+ object->box->upper_x = min(newx1,newx2);
+ object->box->upper_y = max(newy1,newy2);
+ object->box->lower_x = max(newx1,newx2);
+ object->box->lower_y = min(newy1,newy2);
+
+ /* translate object back to normal position */
+ object->box->upper_x += world_centerx;
+ object->box->upper_y += world_centery;
+ object->box->lower_x += world_centerx;
+ object->box->lower_y += world_centery;
+
+ /* recalc boundings and screen coords */
+ o_box_recalc(w_current, object);
+}
+
+/*! \brief Mirror a BOX.
+ * \par Function Description
+ * This function mirrors the box from the point (<B>centerx</B>,<B>centery</B>) in
+ * screen unit.
+ *
+ * The origin of the mirror in screen unit is converted in world unit. The
+ * box is mirrored with the function #o_box_mirror_world() for which the
+ * origin of the mirror must be given in world unit.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] centerx Origin x coordinate in WORLD units.
+ * \param [in] centery Origin y coordinate in WORLD units.
+ * \param [in,out] object BOX OBJECT to mirror.
+ */
+void o_box_mirror(TOPLEVEL *w_current,
+ int centerx, int centery,
+ OBJECT *object)
+{
+ int world_centerx, world_centery;
+
+ /* convert the origin of mirror */
+ SCREENtoWORLD(w_current, centerx, centery,
+ &world_centerx,
+ &world_centery);
+
+ /* apply the mirror in world coords */
+ o_box_mirror_world(w_current,
+ world_centerx, world_centery,
+ object);
+
+ /* screen coords and boundings are updated by _mirror_world() */
+
+}
+
+/*! \brief Mirror BOX using WORLD coordinates.
+ * \par Function Description
+ * This function mirrors the box from the point
+ * (<B>world_centerx</B>,<B>world_centery</B>) in world unit.
+ *
+ * The box is first translated to the origin, then mirrored and finally
+ * translated back at its previous position.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] world_centerx Origin x coordinate in WORLD units.
+ * \param [in] world_centery Origin y coordinate in WORLD units.
+ * \param [in,out] object BOX OBJECT to mirror.
+ */
+void o_box_mirror_world(TOPLEVEL *w_current,
+ int world_centerx, int world_centery,
+ OBJECT *object)
+{
+ int newx1, newy1;
+ int newx2, newy2;
+
+ /* translate object to origin */
+ object->box->upper_x -= world_centerx;
+ object->box->upper_y -= world_centery;
+ object->box->lower_x -= world_centerx;
+ object->box->lower_y -= world_centery;
+
+ /* mirror the corners */
+ newx1 = -object->box->upper_x;
+ newy1 = object->box->upper_y;
+ newx2 = -object->box->lower_x;
+ newy2 = object->box->lower_y;
+
+ /* reorder the corners */
+ object->box->upper_x = min(newx1,newx2);
+ object->box->upper_y = max(newy1,newy2);
+ object->box->lower_x = max(newx1,newx2);
+ object->box->lower_y = min(newy1,newy2);
+
+ /* translate back in position */
+ object->box->upper_x += world_centerx;
+ object->box->upper_y += world_centery;
+ object->box->lower_x += world_centerx;
+ object->box->lower_y += world_centery;
+
+ /* recalc boundings and screen coords */
+ o_box_recalc(w_current, object);
+
+}
+
+/*! \brief Recalculate BOX coordinates in SCREEN units.
+ * \par Function Description
+ * This function recalculates the screen coords of the <B>o_current</B> pointed
+ * box object from its world coords.
+ *
+ * The box coordinates and its bounding are recalculated as well as the
+ * OBJECT specific fields (line width, filling ...).
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in,out] o_current BOX OBJECT to be recalculated.
+ */
+void o_box_recalc(TOPLEVEL *w_current, OBJECT *o_current)
+{
+ int left, top, right, bottom;
+ int screen_x1, screen_y1;
+ int screen_x2, screen_y2;
+
+ if (o_current->box == NULL) {
+ return;
+ }
+
+ /* update the screen coords of the upper left corner of the box */
+ WORLDtoSCREEN(w_current,
+ o_current->box->upper_x, o_current->box->upper_y,
+ &screen_x1, &screen_y1);
+ o_current->box->screen_upper_x = screen_x1;
+ o_current->box->screen_upper_y = screen_y1;
+
+ /* update the screen coords of the lower right corner of the box */
+ WORLDtoSCREEN(w_current,
+ o_current->box->lower_x, o_current->box->lower_y,
+ &screen_x2, &screen_y2);
+ o_current->box->screen_lower_x = screen_x2;
+ o_current->box->screen_lower_y = screen_y2;
+
+ /* update the bounding box - screen unit */
+ get_box_bounds(w_current, o_current->box, &left, &top, &right, &bottom);
+ o_current->left = left;
+ o_current->top = top;
+ o_current->right = right;
+ o_current->bottom = bottom;
+
+ /* recalc OBJECT specific parameters */
+ o_object_recalc(w_current, o_current);
+}
+
+/*! \brief Get BOX bounding rectangle.
+ * \par Function Description
+ * This function sets the <B>left</B>, <B>top</B>, <B>right</B> and <B>bottom</B>
+ * parameters to the bounding rectangle of the box object described in
+ * <B>*box</B> in SCREEN units.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] box BOX OBJECT to read coordinates from.
+ * \param [out] left Left box coordinate in SCREEN units.
+ * \param [out] top Top box coordinate in SCREEN units.
+ * \param [out] right Right box coordinate in SCREEN units.
+ * \param [out] bottom Bottom box coordinate in SCREEN units.
+ */
+void get_box_bounds(TOPLEVEL *w_current, BOX *box,
+ int *left, int *top, int *right, int *bottom)
+{
+ *left = box->screen_upper_x;
+ *top = box->screen_upper_y;
+ *right = box->screen_lower_x;
+ *bottom = box->screen_lower_y;
+
+ /* PB : bounding box has to take into account the width of the line */
+ /* PB : but line width is unknown here */
+
+ *left = *left - 4;
+ *top = *top - 4;
+ *right = *right + 4;
+ *bottom = *bottom + 4;
+}
+
+/*! \brief Get BOX bounding rectangle in WORLD coordinates.
+ * \par Function Description
+ * This function sets the <B>left</B>, <B>top</B>, <B>right</B> and <B>bottom</B>
+ * parameters to the boundings of the box object described in <B>*box</B>
+ * in world units.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] box BOX OBJECT to read coordinates from.
+ * \param [out] left Left box coordinate in WORLD units.
+ * \param [out] top Top box coordinate in WORLD units.
+ * \param [out] right Right box coordinate in WORLD units.
+ * \param [out] bottom Bottom box coordinate in WORLD units.
+ */
+void world_get_box_bounds(TOPLEVEL *w_current, BOX *box,
+ int *left, int *top, int *right, int *bottom)
+{
+ /* pb20011002 - why using min and max here and not above ? */
+ *left = min(box->upper_x, box->lower_x);
+ *top = min(box->upper_y, box->lower_y);
+ *right = max(box->upper_x, box->lower_x);
+ *bottom = max(box->upper_y, box->lower_y);
+
+ /* PB : same as above here for width of edges */
+
+#if DEBUG
+ printf("box: %d %d %d %d\n", *left, *top, *right, *bottom);
+#endif
+
+}
+
+/*! \brief Print BOX to Postscript document.
+ * \par Function Description
+ * This function prints the box described by the <B>o_current</B>
+ * parameter to a Postscript document. It takes into account its line
+ * type and fill type.
+ * The Postscript document is descibed by the file pointer <B>fp</B>.
+ *
+ * The validity of the <B>o_current</B> parameter is verified : a null pointer
+ * causes an error message and a return.
+ *
+ * The description of the box is extracted from
+ * the <B>o_current</B> parameter :
+ * the coordinates of the box - upper left corner and width and
+ * height of the box -, its line type, its fill type.
+ *
+ * The outline and the inside of the box are successively handled by two
+ * differend sets of functions.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] fp FILE pointer to Postscript document.
+ * \param [in] o_current BOX OBJECT to write to document.
+ * \param [in] origin_x Page x coordinate to place BOX OBJECT.
+ * \param [in] origin_y Page y coordinate to place BOX OBJECT.
+ */
+void o_box_print(TOPLEVEL *w_current, FILE *fp, OBJECT *o_current,
+ int origin_x, int origin_y)
+{
+ int x, y, width, height;
+ int color;
+ int line_width, length, space;
+ int fill_width, angle1, pitch1, angle2, pitch2;
+ void (*outl_func)() = NULL;
+ void (*fill_func)() = NULL;
+
+ if (o_current == NULL) {
+ printf("got null in o_box_print\n");
+ return;
+ }
+
+ x = o_current->box->upper_x;
+ y = o_current->box->upper_y;
+ width = abs(o_current->box->lower_x - o_current->box->upper_x);
+ height = abs(o_current->box->lower_y - o_current->box->upper_y);
+ color = o_current->color;
+
+ /*! \note
+ * Depending on the type of the line for this particular box, the
+ * appropriate function is chosen among #o_box_print_solid(),
+ * #o_box_print_dotted(), #o_box_print_dashed(),
+ * #o_box_print_center() and #o_box_print_phantom().
+ *
+ * The needed parameters for each of these type is extracted from the
+ * <B>o_current</B> object. Depending on the type, unused parameters are
+ * set to -1.
+ *
+ * In the eventuality of a length and/or space null, the line is printed
+ * solid to avoid and endless loop produced by other functions in such a
+ * case.
+ */
+ line_width = o_current->line_width;
+ if(line_width <=2) line_width=2;
+ length = o_current->line_length;
+ space = o_current->line_space;
+
+ switch(o_current->line_type) {
+ case(TYPE_SOLID):
+ length = -1; space = -1;
+ outl_func = (void *) o_box_print_solid;
+ break;
+
+ case(TYPE_DOTTED):
+ length = -1;
+ outl_func = (void *) o_box_print_dotted;
+ break;
+
+ case(TYPE_DASHED):
+ outl_func = (void *) o_box_print_dashed;
+ break;
+
+ case(TYPE_CENTER):
+ outl_func = (void *) o_box_print_center;
+ break;
+
+ case(TYPE_PHANTOM):
+ outl_func = (void *) o_box_print_phantom;
+ break;
+
+ case(TYPE_ERASE):
+ /* Unused for now, print it solid */
+ length = -1; space = -1;
+ outl_func = (void *) o_box_print_solid;
+ break;
+ }
+
+ if((length == 0) || (space == 0)) {
+ length = -1; space = -1;
+ outl_func = (void *) o_box_print_solid;
+ }
+
+ (*outl_func)(w_current, fp,
+ x, y, width, height,
+ color,
+ line_width,
+ length, space,
+ origin_x, origin_y);
+
+ /*! \note
+ * If the filling type of the box is not <B>HOLLOW</B>, the appropriate
+ * function is chosen among #o_box_print_filled(), #o_box_print_mesh()
+ * and #o_box_print_hatch(). The corresponding parameters are extracted
+ * from the <B>o_current</B> object and corrected afterward.
+ *
+ * The case where <B>pitch1</B> and <B>pitch2</B> are null or negative is
+ * avoided as it leads to an endless loop in most of the called functions.
+ * In such a case, the box is printed filled. Unused parameters for each of
+ * these functions are set to -1 or any passive value.
+ */
+ if(o_current->fill_type != FILLING_HOLLOW) {
+ fill_width = o_current->fill_width;
+ angle1 = o_current->fill_angle1;
+ pitch1 = o_current->fill_pitch1;
+ angle2 = o_current->fill_angle2;
+ pitch2 = o_current->fill_pitch2;
+
+ switch(o_current->fill_type) {
+ case(FILLING_FILL):
+ angle1 = -1; pitch1 = 1;
+ angle2 = -1; pitch2 = 1;
+ fill_width = -1;
+ fill_func = (void *) o_box_print_filled;
+ break;
+
+ case(FILLING_MESH):
+ fill_func = (void *) o_box_print_mesh;
+ break;
+
+ case(FILLING_HATCH):
+ angle2 = -1; pitch2 = 1;
+ fill_func = (void *) o_box_print_hatch;
+ break;
+
+ case(FILLING_VOID):
+ /* Unused for now, print it filled */
+ angle1 = -1; pitch1 = 1;
+ angle2 = -1; pitch2 = 1;
+ fill_width = -1;
+ fill_func = (void *) o_box_print_filled;
+ break;
+ case(FILLING_HOLLOW):
+ /* nop */
+ break;
+
+ }
+
+ if((pitch1 <= 0) || (pitch2 <= 0)) {
+ angle1 = -1; pitch1 = 1;
+ angle2 = -1; pitch2 = 1;
+ fill_func = (void *) o_box_print_filled;
+ }
+
+ (*fill_func)(w_current, fp,
+ x, y, width, height,
+ color,
+ fill_width,
+ angle1, pitch1, angle2, pitch2,
+ origin_x, origin_y);
+ }
+}
+
+/*! \brief Print a solid BOX to Postscript document.
+ * \par Function Description
+ * This function prints the outline of a box when a solid line type is
+ * required. The box is defined by the coordinates of its upper left corner
+ * in (<B>x</B>,<B>y</B>) and its width and height given by the <B>width</B> and
+ * <B>height</B> parameters.
+ * The postscript file is defined by the file pointer <B>fp</B>.
+ * The parameters <B>length</B> and <B>space</B> are ignored.
+ *
+ * It uses the function #o_line_print_solid() to print the outline.
+ * It performs four calls to this function, one for each of its side.
+ *
+ * All dimensions are in mils.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] fp FILE pointer to Postscript document.
+ * \param [in] x Upper x coordinate of BOX.
+ * \param [in] y Upper y coordinate of BOX.
+ * \param [in] width Width of BOX.
+ * \param [in] height Height of BOX.
+ * \param [in] color BOX color.
+ * \param [in] line_width BOX Line width.
+ * \param [in] length Dashed line length.
+ * \param [in] space Amount of space between dashes.
+ * \param [in] origin_x Page x coordinate to place BOX OBJECT.
+ * \param [in] origin_y Page y coordinate to place BOX OBJECT.
+ *
+ * \par Author's Note
+ * PB : parameter filled removed
+ */
+void
+o_box_print_solid(TOPLEVEL *w_current, FILE *fp,
+ int x, int y,
+ int width, int height,
+ int color,
+ int line_width, int length, int space,
+ int origin_x, int origin_y)
+{
+ int x1, y1;
+
+ if (w_current->print_color) {
+ f_print_set_color(fp, color);
+ }
+
+ x1 = x;
+ y1 = y - height; /* move the origin to 0, 0*/
+
+ o_line_print_solid(w_current, fp,
+ x1, y1, x1 + width, y1,
+ color,
+ line_width, length, space,
+ origin_x, origin_y);
+ o_line_print_solid(w_current, fp,
+ x1 + width, y1, x1 + width, y1 + height,
+ color,
+ line_width, length, space,
+ origin_x, origin_y);
+ o_line_print_solid(w_current, fp,
+ x1 + width, y1 + height, x1, y1 + height,
+ color,
+ line_width, length, space,
+ origin_x, origin_y);
+ o_line_print_solid(w_current, fp,
+ x1, y1 + height, x1, y1,
+ color,
+ line_width, length, space,
+ origin_x, origin_y);
+}
+
+/*! \brief Print a dotted BOX to Postscript document.
+ * \par Function Description
+ * This function prints the outline of a box when a dotted line type is
+ * required. The box is defined by the coordinates of its upper left corner
+ * in (<B>x</B>,<B>y</B>) and its width and height given by the <B>width</B> and
+ * <B>height</B> parameters.
+ * The postscript file is defined by the file pointer <B>fp</B>.
+ * The parameters <B>length</B> is ignored.
+ *
+ * It uses the function #o_line_print_dotted() to print the outline.
+ * It performs four calls to this function, one for each of its side.
+ *
+ * All dimensions are in mils.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] fp FILE pointer to Postscript document.
+ * \param [in] x Upper x coordinate of BOX.
+ * \param [in] y Upper y coordinate of BOX.
+ * \param [in] width Width of BOX.
+ * \param [in] height Height of BOX.
+ * \param [in] color BOX color.
+ * \param [in] line_width BOX Line width.
+ * \param [in] length Dashed line length.
+ * \param [in] space Amount of space between dashes.
+ * \param [in] origin_x Page x coordinate to place BOX OBJECT.
+ * \param [in] origin_y Page y coordinate to place BOX OBJECT.
+ *
+ * \par Author's Note
+ * PB : parameter filled removed
+ * PB : parameter o_current removed
+ */
+void o_box_print_dotted(TOPLEVEL *w_current, FILE *fp,
+ int x, int y,
+ int width, int height,
+ int color,
+ int line_width, int length, int space,
+ int origin_x, int origin_y)
+{
+ int x1, y1;
+
+ if (w_current->print_color) {
+ f_print_set_color(fp, color);
+ }
+
+ x1 = x;
+ y1 = y - height; /* move the origin to 0, 0*/
+
+ o_line_print_dotted(w_current, fp,
+ x1, y1, x1 + width, y1,
+ color,
+ line_width, length, space,
+ origin_x, origin_y);
+ o_line_print_dotted(w_current, fp,
+ x1 + width, y1, x1 + width, y1 + height,
+ color,
+ line_width, length, space,
+ origin_x, origin_y);
+ o_line_print_dotted(w_current, fp,
+ x1 + width, y1 + height, x1, y1 + height,
+ color,
+ line_width, length, space,
+ origin_x, origin_y);
+ o_line_print_dotted(w_current, fp,
+ x1, y1 + height, x1, y1,
+ color,
+ line_width, length, space,
+ origin_x, origin_y);
+}
+
+/*! \brief Print a dashed BOX to Postscript document.
+ * \par Function Description
+ * This function prints the outline of a box when a dashed line type is
+ * required. The box is defined by the coordinates of its upper left corner
+ * in (<B>x</B>,<B>y</B>) and its width and height given by the <B>width</B> and
+ * <B>height</B> parameters.
+ * The postscript file is defined by the file pointer <B>fp</B>.
+ *
+ * It uses the function #o_line_print_dashed() to print the outline.
+ * It performs four calls to this function, one for each of its side.
+ *
+ * All dimensions are in mils.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] fp FILE pointer to Postscript document.
+ * \param [in] x Upper x coordinate of BOX.
+ * \param [in] y Upper y coordinate of BOX.
+ * \param [in] width Width of BOX.
+ * \param [in] height Height of BOX.
+ * \param [in] color BOX color.
+ * \param [in] line_width BOX Line width.
+ * \param [in] length Dashed line length.
+ * \param [in] space Amount of space between dashes.
+ * \param [in] origin_x Page x coordinate to place BOX OBJECT.
+ * \param [in] origin_y Page y coordinate to place BOX OBJECT.
+ *
+ * \par Author's Note
+ * PB : parameter filled removed
+ * PB : parameter o_current removed
+ */
+void o_box_print_dashed(TOPLEVEL *w_current, FILE *fp,
+ int x, int y,
+ int width, int height,
+ int color,
+ int line_width, int length, int space,
+ int origin_x, int origin_y)
+{
+ int x1, y1;
+
+ if (w_current->print_color) {
+ f_print_set_color(fp, color);
+ }
+
+
+ x1 = x;
+ y1 = y - height; /* move the origin to 0, 0*/
+
+ o_line_print_dashed(w_current, fp,
+ x1, y1, x1 + width, y1,
+ color,
+ line_width, length, space,
+ origin_x, origin_y);
+ o_line_print_dashed(w_current, fp,
+ x1 + width, y1, x1 + width, y1 + height,
+ color,
+ line_width, length, space,
+ origin_x, origin_y);
+ o_line_print_dashed(w_current, fp,
+ x1 + width, y1 + height, x1, y1 + height,
+ color,
+ line_width, length, space,
+ origin_x, origin_y);
+ o_line_print_dashed(w_current, fp,
+ x1, y1 + height, x1, y1,
+ color,
+ line_width, length, space,
+ origin_x, origin_y);
+}
+
+/*! \brief Print centered line type BOX to Postscript document.
+ * \par Function Description
+ * This function prints the outline of a box when a centered line type is
+ * required. The box is defined by the coordinates of its upper left corner
+ * in (<B>x</B>,<B>y</B>) and its width and height given by the <B>width</B> and
+ * <B>height</B> parameters.
+ * The postscript file is defined by the file pointer <B>fp</B>.
+ *
+ * It uses the function #o_line_print_center() to print the outline.
+ * It performs four calls to this function, one for each of its side.
+ *
+ * All dimensions are in mils.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] fp FILE pointer to Postscript document.
+ * \param [in] x Upper x coordinate of BOX.
+ * \param [in] y Upper y coordinate of BOX.
+ * \param [in] width Width of BOX.
+ * \param [in] height Height of BOX.
+ * \param [in] color BOX color.
+ * \param [in] line_width BOX Line width.
+ * \param [in] length Dashed line length.
+ * \param [in] space Amount of space between dashes.
+ * \param [in] origin_x Page x coordinate to place BOX OBJECT.
+ * \param [in] origin_y Page y coordinate to place BOX OBJECT.
+ *
+ * \par Author's note
+ * PB : parameter filled removed
+ * PB : parameter o_current removed
+ */
+void o_box_print_center(TOPLEVEL *w_current, FILE *fp,
+ int x, int y,
+ int width, int height,
+ int color,
+ int line_width, int length, int space,
+ int origin_x, int origin_y)
+{
+ int x1, y1;
+
+ if (w_current->print_color) {
+ f_print_set_color(fp, color);
+ }
+
+ x1 = x;
+ y1 = y - height; /* move the origin to 0, 0*/
+
+ o_line_print_center(w_current, fp,
+ x1, y1, x1 + width, y1,
+ color,
+ line_width, length, space,
+ origin_x, origin_y);
+ o_line_print_center(w_current, fp,
+ x1 + width, y1, x1 + width, y1 + height,
+ color,
+ line_width, length, space,
+ origin_x, origin_y);
+ o_line_print_center(w_current, fp,
+ x1 + width, y1 + height, x1, y1 + height,
+ color,
+ line_width, length, space,
+ origin_x, origin_y);
+ o_line_print_center(w_current, fp,
+ x1, y1 + height, x1, y1,
+ color,
+ line_width, length, space,
+ origin_x, origin_y);
+}
+
+/*! \brief Print phantom line type BOX to Postscript document.
+ * \par Function Description
+ * This function prints the outline of a box when a phantom line type is
+ * required. The box is defined by the coordinates of its upper left corner
+ * in (<B>x</B>,<B>y</B>) and its width and height given by the <B>width</B> and
+ * <B>height</B> parameters.
+ * The postscript file is defined by the file pointer <B>fp</B>.
+ *
+ * It uses the function #o_line_print_phantom() to print the outline.
+ * It performs four calls to this function, one for each of its side.
+ *
+ * All dimensions are in mils.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] fp FILE pointer to Postscript document.
+ * \param [in] x Upper x coordinate of BOX.
+ * \param [in] y Upper y coordinate of BOX.
+ * \param [in] width Width of BOX.
+ * \param [in] height Height of BOX.
+ * \param [in] color BOX color.
+ * \param [in] line_width BOX Line width.
+ * \param [in] length Dashed line length.
+ * \param [in] space Amount of space between dashes.
+ * \param [in] origin_x Page x coordinate to place BOX OBJECT.
+ * \param [in] origin_y Page y coordinate to place BOX OBJECT.
+ *
+ * \par Author's note
+ * PB : parameter filled removed
+ * PB : parameter o_current removed
+ */
+void o_box_print_phantom(TOPLEVEL *w_current, FILE *fp,
+ int x, int y,
+ int width, int height,
+ int color,
+ int line_width, int length, int space,
+ int origin_x, int origin_y)
+{
+ int x1, y1;
+
+ if (w_current->print_color) {
+ f_print_set_color(fp, color);
+ }
+
+ x1 = x;
+ y1 = y - height; /* move the origin to 0, 0*/
+
+ o_line_print_phantom(w_current, fp,
+ x1, y1, x1 + width, y1,
+ color,
+ line_width, length, space,
+ origin_x, origin_y);
+ o_line_print_phantom(w_current, fp,
+ x1 + width, y1, x1 + width, y1 + height,
+ color,
+ line_width, length, space,
+ origin_x, origin_y);
+ o_line_print_phantom(w_current, fp,
+ x1 + width, y1 + height, x1, y1 + height,
+ color,
+ line_width, length, space,
+ origin_x, origin_y);
+ o_line_print_phantom(w_current, fp,
+ x1, y1 + height, x1, y1,
+ color,
+ line_width, length, space,
+ origin_x, origin_y);
+}
+
+/*! \brief Print a solid pattern BOX to Postscript document.
+ * \par Function Description
+ * The function prints a filled box with a solid pattern. No outline is
+ * printed.
+ * The box is defined by the coordinates of its upper left corner in
+ * (<B>x</B>,<B>y</B>) and its width and height given by the <B>width</B> and
+ * <B>height</B> parameters. The postscript file is defined by the file
+ * pointer <B>fp</B>.
+ * <B>fill_width</B>, <B>angle1</B> and <B>pitch1</B>, <B>angle2</B> and <B>pitch2</B>
+ * parameters are ignored in this functions but kept for compatibility
+ * with other fill functions.
+ *
+ * It uses the fbox postscript function defined in the prolog to
+ * specify a filled box.
+ *
+ * All dimensions are in mils.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] fp FILE pointer to Postscript document.
+ * \param [in] x Upper x coordinate of BOX.
+ * \param [in] y Upper y coordinate of BOX.
+ * \param [in] width Width of BOX.
+ * \param [in] height Height of BOX.
+ * \param [in] color BOX color.
+ * \param [in] fill_width BOX fill width. (unused).
+ * \param [in] angle1 (unused).
+ * \param [in] pitch1 (unused).
+ * \param [in] angle2 (unused).
+ * \param [in] pitch2 (unused).
+ * \param [in] origin_x Page x coordinate to place BOX OBJECT.
+ * \param [in] origin_y Page y coordinate to place BOX OBJECT.
+ */
+void o_box_print_filled(TOPLEVEL *w_current, FILE *fp,
+ int x, int y,
+ int width, int height,
+ int color,
+ int fill_width,
+ int angle1, int pitch1,
+ int angle2, int pitch2,
+ int origin_x, int origin_y)
+{
+ int x1, y1;
+
+ if (w_current->print_color) {
+ f_print_set_color(fp, color);
+ }
+
+ x1 = x;
+ y1 = y-height; /* move the origin to 0, 0*/
+ fprintf(fp, "%d %d %d %d fbox\n",
+ width, height,
+ x1-origin_x, y1-origin_y);
+
+}
+
+/*! \brief Print a mesh pattern BOX to Postscript document.
+ * \par Function Description
+ * This function prints a meshed box. No outline is printed. The box is
+ * defined by the coordinates of its upper left corner in (<B>x</B>,<B>y</B>) and
+ * its width and height given by the <B>width</B> and <B>height</B> parameters.
+ * The postscript file is defined by the file pointer <B>fp</B>.
+ *
+ * The inside mesh is achieved by two successive call to the
+ * #o_box_print_hatch() function, given <B>angle1</B> and <B>pitch1</B> the first
+ * time and <B>angle2</B> and <B>pitch2</B> the second time.
+ *
+ * Negative or null values for <B>pitch1</B> and/or <B>pitch2</B> are not allowed
+ * as it leads to an endless loop in #o_box_print_hatch().
+ *
+ * All dimensions are in mils.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] fp FILE pointer to Postscript document.
+ * \param [in] x Upper x coordinate of BOX.
+ * \param [in] y Upper y coordinate of BOX.
+ * \param [in] width Width of BOX.
+ * \param [in] height Height of BOX.
+ * \param [in] color BOX color.
+ * \param [in] fill_width BOX fill width.
+ * \param [in] angle1 1st angle for mesh pattern.
+ * \param [in] pitch1 1st pitch for mesh pattern.
+ * \param [in] angle2 2nd angle for mesh pattern.
+ * \param [in] pitch2 2nd pitch for mesh pattern.
+ * \param [in] origin_x Page x coordinate to place BOX OBJECT.
+ * \param [in] origin_y Page y coordinate to place BOX OBJECT.
+ */
+void o_box_print_mesh(TOPLEVEL *w_current, FILE *fp,
+ int x, int y,
+ int width, int height,
+ int color,
+ int fill_width,
+ int angle1, int pitch1,
+ int angle2, int pitch2,
+ int origin_x, int origin_y)
+{
+ o_box_print_hatch(w_current, fp,
+ x, y, width, height,
+ color,
+ fill_width,
+ angle1, pitch1, -1, -1,
+ origin_x, origin_y);
+ o_box_print_hatch(w_current, fp,
+ x, y, width, height,
+ color,
+ fill_width,
+ angle2, pitch2, -1, -1,
+ origin_x, origin_y);
+
+}
+
+/*! \brief Print a hatch pattern BOX to Postscript document.
+ * \par Function Description
+ * The function prints a hatched box. No outline is printed. The box is
+ * defined by the coordinates of its upper left corner in (<B>x</B>,<B>y</B>) and
+ * its width and height given by the <B>width</B> and <B>height</B> parameters.
+ * The postscript file is defined by the file pointer <B>fp</B>.
+ * <B>fill_width</B>, <B>angle1</B>, <B>pitch1</B> parameters define the way the box
+ * has to be hatched.
+ * <B>angle2</B> and <B>pitch2</B> parameters are unused but kept for compatibility
+ * with other fill functions.
+ *
+ * Negative or null values for <B>pitch1</B> are not allowed as it leads to an
+ * endless loop.
+ *
+ * All dimensions are in mils.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] fp FILE pointer to Postscript document.
+ * \param [in] x Upper x coordinate of BOX.
+ * \param [in] y Upper y coordinate of BOX.
+ * \param [in] width Width of BOX.
+ * \param [in] height Height of BOX.
+ * \param [in] color BOX color.
+ * \param [in] fill_width BOX fill width.
+ * \param [in] angle1 Angle of hatch pattern.
+ * \param [in] pitch1 Pitch of hatch pattern.
+ * \param [in] angle2 (unused).
+ * \param [in] pitch2 (unused).
+ * \param [in] origin_x Page x coordinate to place BOX OBJECT.
+ * \param [in] origin_y Page y coordinate to place BOX OBJECT.
+ */
+void o_box_print_hatch(TOPLEVEL *w_current, FILE *fp,
+ int x, int y,
+ int width, int height,
+ int color,
+ int fill_width,
+ int angle1, int pitch1,
+ int angle2, int pitch2,
+ int origin_x, int origin_y)
+{
+ int x3, y3, x4, y4;
+ double cos_a_, sin_a_;
+ double x0, y0, r;
+ double x1, y1, x2, y2;
+ double amin, amax, a[4], min1, min2, max1, max2;
+
+ if (w_current->print_color) {
+ f_print_set_color(fp, color);
+ }
+
+ /* Avoid printing line widths too small */
+ if (fill_width <= 1) fill_width = 2;
+
+ /* The cosinus and sinus of <B>angle1</B> are computed once and reused later. */
+ cos_a_ = cos(((double) angle1) * M_PI/180);
+ sin_a_ = sin(((double) angle1) * M_PI/180);
+
+ /*! \note
+ * The function considers the smallest circle around the box. Its radius
+ * is given by the following relation. Its center is given by the point
+ * at the middle of the box horizontally and vertically (intersection of
+ * its two diagonals).
+ */
+ r = sqrt((double) (pow(width, 2) + pow(height, 2))) / 2;
+
+ /*
+ * When drawing a line in a circle there is two intersections. With the
+ * previously described circle, these intersections are out of the box.
+ * They can be easily calculated, the first by resolution of an equation
+ * and the second one by symetry in relation to the vertical axis going
+ * through the center of the circle.
+ *
+ * These two points are then rotated of angle <B>angle1</B> using the matrix
+ * previously mentioned.
+ */
+ y0 = 0;
+ while(y0 < r) {
+ x0 = pow(r, 2) - pow(y0, 2);
+ x0 = sqrt(x0);
+
+ x1 = (x0*cos_a_ - y0*sin_a_);
+ y1 = (x0*sin_a_ + y0*cos_a_);
+ x2 = ((-x0)*cos_a_ - y0*sin_a_);
+ y2 = ((-x0)*sin_a_ + y0*cos_a_);
+
+ /*
+ * It now parametrizes the segment : first intersection is given the
+ * value of 0 and the second is given the value of 1. The four values for
+ * each intersection of the segment and the four sides (vertical or
+ * horizontal) of the box are given by the following relations :
+ */
+ if((int) (x2 - x1) != 0) {
+ a[0] = ((-width/2) - x1) / (x2 - x1);
+ a[1] = ((width/2) - x1) / (x2 - x1);
+ } else {
+ a[0] = 0; a[1] = 1;
+ }
+
+ if((int) (y2 - y1) != 0) {
+ a[2] = ((-height/2) - y1) / (y2 - y1);
+ a[3] = ((height/2) - y1) / (y2 - y1);
+ } else {
+ a[2] = 0; a[3] = 1;
+ }
+
+ /*
+ * It now has to check which of these four values are for intersections
+ * with the sides of the box (some values may be for intersections out of
+ * the box). This is made by a min/max function.
+ */
+ if(a[0] < a[1]) {
+ min1 = a[0]; max1 = a[1];
+ } else {
+ min1 = a[1]; max1 = a[0];
+ }
+
+ if(a[2] < a[3]) {
+ min2 = a[2]; max2 = a[3];
+ } else {
+ min2 = a[3]; max2 = a[2];
+ }
+
+ amin = (min1 < min2) ? min2 : min1;
+ amin = (amin < 0) ? 0 : amin;
+
+ amax = (max1 < max2) ? max1 : max2;
+ amax = (amax < 1) ? amax : 1;
+
+ /*
+ * If the segment really go through the box it prints the line. It also
+ * takes the opportunity of the symetry in the box in relation to its
+ * center to print the second line at the same time.
+ *
+ * If there is no intersection of the segment with any of the sides, then
+ * there is no need to continue : there would be no more segment in the
+ * box to print.
+ */
+ if((amax > amin) && (amax != 1) && (amin != 0)) {
+ /* There is intersection between the line and the box edges */
+ x3 = (int) (x1 + amin*(x2 - x1));
+ y3 = (int) (y1 + amin*(y2 - y1));
+
+ x4 = (int) (x1 + amax*(x2 - x1));
+ y4 = (int) (y1 + amax*(y2 - y1));
+
+ fprintf(fp,"%d %d %d %d %d line\n",
+ x3 + (x + width/2), y3 + (y - height/2),
+ x4 + (x + width/2), y4 + (y - height/2),
+ fill_width);
+
+ fprintf(fp,"%d %d %d %d %d line\n",
+ -x3 + (x + width/2), -y3 + (y - height/2),
+ -x4 + (x + width/2), -y4 + (y - height/2),
+ fill_width);
+
+ } else {
+ break;
+ }
+
+ y0 = y0 + pitch1;
+ }
+}
+
+#if 0 /* original way of printing box, no longer used */
+/*! \brief Print BOX to Postscript document using old method.
+ * \par Function Description
+ * This function is the old function to print a box. It does not handle line
+ * type and filling of a box.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] fp FILE pointer to Postscript document.
+ * \param [in] origin_x Page x coordinate to place BOX OBJECT.
+ * \param [in] origin_y Page x coordinate to place BOX OBJECT.
+ */
+void o_box_print_old(TOPLEVEL *w_current, FILE *fp,
+ int origin_x, int origin_y)
+{
+ int width, height;
+ int x1, y1;
+ if (o_current == NULL) {
+ printf("got null in o_box_print\n");
+ return;
+ }
+
+ if (w_current->print_color) {
+ f_print_set_color(fp, o_current->color);
+ }
+
+
+ width = abs(o_current->line_points->x2 - o_current->line_points->x1);
+ height = abs(o_current->line_points->y1 - o_current->line_points->y2);
+
+ x1 = o_current->line_points->x1;
+ y1 = o_current->line_points->y1-height; /* move the origin to 0, 0*/
+
+ fprintf(fp, "newpath\n");
+ fprintf(fp, "%d mils %d mils moveto\n", x1-origin_x, y1-origin_y);
+ fprintf(fp, "%d mils %d mils box\n", width, height);
+
+}
+#endif
+
+/*! \brief Draw a box in an image.
+ * \par Function Description
+ * This function draws a box in an image with the libgdgeda function
+ * #gdImageRectangle().
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] o_current BOX OBJECT to draw.
+ * \param [in] origin_x (unused).
+ * \param [in] origin_y (unused).
+ * \param [in] color_mode Draw box in color if TRUE, B/W otherwise.
+ */
+void o_box_image_write(TOPLEVEL *w_current, OBJECT *o_current,
+ int origin_x, int origin_y, int color_mode)
+{
+ int color;
+
+
+ if (o_current == NULL) {
+ printf("got null in o_box_image_write\n");
+ return;
+ }
+
+
+ if (color_mode == TRUE) {
+ color = o_image_geda2gd_color(o_current->color);
+ } else {
+ color = image_black;
+ }
+
+ /* assumes screen coords are already calculated correctly */
+#ifdef HAS_LIBGDGEDA
+
+ gdImageSetThickness(current_im_ptr, SCREENabs(w_current,
+ o_current->line_width));
+
+ gdImageRectangle(current_im_ptr,
+ o_current->box->screen_upper_x,
+ o_current->box->screen_upper_y,
+ o_current->box->screen_lower_x,
+ o_current->box->screen_lower_y,
+ color);
+#endif
+
+}
1.13 +598 -523 eda/geda/gaf/libgeda/src/o_bus_basic.c
(In the diff below, changes in quantity of whitespace are not shown.)
Index: o_bus_basic.c
===================================================================
RCS file: o_bus_basic.c
diff -N o_bus_basic.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ o_bus_basic.c 5 Jul 2006 03:13:38 -0000 1.13
@@ -0,0 +1,841 @@
+/*! \todo No comments found in o_bus_basic.nw
+ * Finish file comments.
+ */
+/* gEDA - GPL Electronic Design Automation
+ * libgeda - gEDA's library
+ * Copyright (C) 1998-2000 Ales V. Hvezda
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+#include <config.h>
+#include <stdio.h>
+#include <math.h>
+
+#include <gtk/gtk.h>
+#include <libguile.h>
+
+#ifdef HAS_LIBGDGEDA
+#include <gdgeda/gd.h>
+#endif
+
+#include "defines.h"
+#include "struct.h"
+#include "globals.h"
+#include "o_types.h"
+#include "colors.h"
+#include "funcs.h"
+
+#include "../include/prototype.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+/* \brief
+ * \par Function Description
+ *
+ */
+void get_bus_bounds(TOPLEVEL *w_current, LINE *line, int *left, int *top,
+ int *right, int *bottom)
+{
+ *left = w_current->width;
+ *top = w_current->height;
+ *right = 0;
+ *bottom = 0;
+
+ if (line->screen_x[0] < *left) *left = line->screen_x[0];
+ if (line->screen_x[0] > *right) *right = line->screen_x[0];
+ if (line->screen_y[0] < *top) *top = line->screen_y[0];
+ if (line->screen_y[0] > *bottom) *bottom = line->screen_y[0];
+
+ if (line->screen_x[1] < *left) *left = line->screen_x[1];
+ if (line->screen_x[1] > *right) *right = line->screen_x[1];
+ if (line->screen_y[1] < *top) *top = line->screen_y[1];
+ if (line->screen_y[1] > *bottom) *bottom = line->screen_y[1];
+
+ *left = *left - 4;
+ *top = *top - 4;
+
+ *right = *right + 4;
+ *bottom = *bottom + 4;
+}
+
+/* \brief
+ * \par Function Description
+ *
+ */
+void world_get_bus_bounds(TOPLEVEL *w_current, LINE *line, int *left, int *top,
+ int *right, int *bottom)
+{
+ *left = w_current->init_right;
+ *top = w_current->init_bottom;
+ *right = 0;
+ *bottom = 0;
+
+ if (line->x[0] < *left) *left = line->x[0];
+ if (line->x[0] > *right) *right = line->x[0];
+ if (line->y[0] < *top) *top = line->y[0];
+ if (line->y[0] > *bottom) *bottom = line->y[0];
+
+ if (line->x[1] < *left) *left = line->x[1];
+ if (line->x[1] > *right) *right = line->x[1];
+ if (line->y[1] < *top) *top = line->y[1];
+ if (line->y[1] > *bottom) *bottom = line->y[1];
+
+}
+
+/* \brief
+ * \par Function Description
+ *
+ */
+OBJECT *o_bus_add(TOPLEVEL *w_current, OBJECT *object_list,
+ char type, int color,
+ int x1, int y1, int x2, int y2,
+ int bus_ripper_direction)
+{
+ int screen_x, screen_y;
+ int left, right, top, bottom;
+ OBJECT *new_node;
+
+ new_node = s_basic_init_object("bus");
+ new_node->type = type;
+ new_node->color = color;
+
+ new_node->line = (LINE *) malloc(sizeof(LINE));
+ /* check for null */
+
+ new_node->line->x[0] = x1;
+ new_node->line->y[0] = y1;
+ new_node->line->x[1] = x2;
+ new_node->line->y[1] = y2;
+
+ WORLDtoSCREEN(w_current,
+ new_node->line->x[0], new_node->line->y[0],
+ &screen_x,
+ &screen_y);
+
+ new_node->line->screen_x[0] = screen_x;
+ new_node->line->screen_y[0] = screen_y;
+
+ WORLDtoSCREEN(w_current,
+ new_node->line->x[1], new_node->line->y[1],
+ &screen_x,
+ &screen_y);
+
+ new_node->line->screen_x[1] = screen_x;
+ new_node->line->screen_y[1] = screen_y;
+
+ new_node->bus_ripper_direction = bus_ripper_direction;
+
+ get_bus_bounds(w_current, new_node->line, &left, &top, &right, &bottom);
+
+ new_node->left = left;
+ new_node->top = top;
+ new_node->right = right;
+ new_node->bottom = bottom;
+
+ /*! \todo questionable cast */
+ new_node->draw_func = (void *) bus_draw_func;
+ /*! \todo questionable cast */
+ new_node->sel_func = (void *) select_func;
+
+ object_list = (OBJECT *) s_basic_link_object(new_node, object_list);
+
+ s_tile_add_object(w_current, object_list,
+ new_node->line->x[0], new_node->line->y[0],
+ new_node->line->x[1], new_node->line->y[1]);
+
+ if (!w_current->ADDING_SEL) {
+ s_conn_update_object(w_current, object_list);
+ }
+
+ return(object_list);
+}
+
+/* \brief
+ * \par Function Description
+ *
+ */
+void o_bus_recalc(TOPLEVEL *w_current, OBJECT *o_current)
+{
+ int screen_x1, screen_y1;
+ int screen_x2, screen_y2;
+ int left, right, top, bottom;
+
+ if (o_current == NULL) {
+ return;
+ }
+
+ if (o_current->line == NULL) {
+ return;
+ }
+
+ WORLDtoSCREEN(w_current, o_current->line->x[0],
+ o_current->line->y[0],
+ &screen_x1,
+ &screen_y1);
+
+ o_current->line->screen_x[0] = screen_x1;
+ o_current->line->screen_y[0] = screen_y1;
+
+ WORLDtoSCREEN(w_current, o_current->line->x[1],
+ o_current->line->y[1],
+ &screen_x2,
+ &screen_y2);
+
+ o_current->line->screen_x[1] = screen_x2;
+ o_current->line->screen_y[1] = screen_y2;
+
+
+ get_bus_bounds(w_current, o_current->line, &left, &top, &right, &bottom);
+
+ o_current->left = left;
+ o_current->top = top;
+ o_current->right = right;
+ o_current->bottom = bottom;
+
+
+}
+
+/* \brief
+ * \par Function Description
+ *
+ */
+OBJECT *o_bus_read(TOPLEVEL *w_current, OBJECT *object_list, char buf[],
+ unsigned int release_ver, unsigned int fileformat_ver)
+{
+ char type;
+ int x1, y1;
+ int x2, y2;
+ int d_x1, d_y1;
+ int d_x2, d_y2;
+ int color;
+ int ripper_dir;
+
+ if(release_ver <= VERSION_20020825) {
+ sscanf(buf, "%c %d %d %d %d %d\n", &type, &x1, &y1, &x2, &y2, &color);
+ ripper_dir = 0;
+ } else {
+ sscanf(buf, "%c %d %d %d %d %d %d\n", &type, &x1, &y1, &x2, &y2, &color,
+ &ripper_dir);
+ }
+
+ d_x1 = x1;
+ d_y1 = y1;
+ d_x2 = x2;
+ d_y2 = y2;
+
+ if (x1 == x2 && y1 == y2) {
+ fprintf(stderr, "Found a zero length bus [ %c %d %d %d %d %d ]\n", type, x1, y1, x2, y2, color);
+ s_log_message("Found a zero length bus [ %c %d %d %d %d %d ]\n", type, x1, y1, x2, y2, color);
+ }
+
+ if (w_current->override_bus_color != -1) {
+ color = w_current->override_bus_color;
+ }
+
+ if (color < 0 || color > MAX_COLORS) {
+ fprintf(stderr, "Found an invalid color [ %s ]\n", buf);
+ s_log_message("Found an invalid color [ %s ]\n", buf);
+ s_log_message("Setting color to WHITE\n");
+ color = WHITE;
+ }
+
+ if (ripper_dir < -1 || ripper_dir > 1) {
+ fprintf(stderr, "Found an invalid bus ripper direction [ %s ]\n", buf);
+ s_log_message("Found an invalid bus ripper direction [ %s ]\n", buf);
+ s_log_message("Resetting direction to neutral (no direction)\n");
+ ripper_dir = 0;
+ }
+
+ object_list = o_bus_add(w_current, object_list, type, color,
+ d_x1, d_y1, d_x2, d_y2, ripper_dir);
+ return(object_list);
+}
+
+/* \brief
+ * \par Function Description
+ *
+ */
+char *o_bus_save(OBJECT *object)
+{
+ int x1, x2, y1, y2;
+ int color;
+ char *buf;
+
+ x1 = object->line->x[0];
+ y1 = object->line->y[0];
+ x2 = object->line->x[1];
+ y2 = object->line->y[1];
+
+ /* Use the right color */
+ if (object->saved_color == -1) {
+ color = object->color;
+ } else {
+ color = object->saved_color;
+ }
+
+ buf = g_strdup_printf("%c %d %d %d %d %d %d", object->type,
+ x1, y1, x2, y2, color, object->bus_ripper_direction);
+ return(buf);
+}
+
+/* \brief
+ * \par Function Description
+ *
+ */
+void o_bus_translate(TOPLEVEL *w_current, int dx, int dy, OBJECT *object)
+{
+ int x, y;
+
+ if (object == NULL) printf("nt NO!\n");
+
+
+ /* Do world coords */
+ object->line->screen_x[0] = object->line->screen_x[0] + dx;
+ object->line->screen_y[0] = object->line->screen_y[0] + dy;
+ object->line->screen_x[1] = object->line->screen_x[1] + dx;
+ object->line->screen_y[1] = object->line->screen_y[1] + dy;
+
+ /* do we want snap grid here? */
+ SCREENtoWORLD(w_current, object->line->screen_x[0],
+ object->line->screen_y[0],
+ &x,
+ &y);
+
+ object->line->x[0] = snap_grid(w_current, x);
+ object->line->y[0] = snap_grid(w_current, y);
+
+ SCREENtoWORLD(w_current, object->line->screen_x[1],
+ object->line->screen_y[1],
+ &x,
+ &y);
+
+ object->line->x[1] = snap_grid(w_current, x);
+ object->line->y[1] = snap_grid(w_current, y);
+
+ s_tile_update_object(w_current, object);
+}
+
+/* \brief
+ * \par Function Description
+ *
+ */
+void o_bus_translate_world(TOPLEVEL *w_current, int x1, int y1, OBJECT *object)
+{
+ int screen_x1, screen_y1;
+ int screen_x2, screen_y2;
+ int left, right, top, bottom;
+
+ if (object == NULL) printf("btw NO!\n");
+
+
+ /* Do world coords */
+ object->line->x[0] = object->line->x[0] + x1;
+ object->line->y[0] = object->line->y[0] + y1;
+ object->line->x[1] = object->line->x[1] + x1;
+ object->line->y[1] = object->line->y[1] + y1;
+
+ /* update screen coords */
+ WORLDtoSCREEN(w_current, object->line->x[0],
+ object->line->y[0],
+ &screen_x1,
+ &screen_y1);
+
+ object->line->screen_x[0] = screen_x1;
+ object->line->screen_y[0] = screen_y1;
+
+ WORLDtoSCREEN(w_current, object->line->x[1],
+ object->line->y[1],
+ &screen_x2,
+ &screen_y2);
+
+ object->line->screen_x[1] = screen_x2;
+ object->line->screen_y[1] = screen_y2;
+
+ /* update bounding box */
+ get_bus_bounds(w_current, object->line, &left, &top, &right, &bottom);
+
+ object->left = left;
+ object->top = top;
+ object->right = right;
+ object->bottom = bottom;
+
+ s_tile_update_object(w_current, object);
+}
+
+/* \brief
+ * \par Function Description
+ *
+ */
+OBJECT *o_bus_copy(TOPLEVEL *w_current, OBJECT *list_tail, OBJECT *o_current)
+{
+ OBJECT *new_obj;
+ ATTRIB *a_current;
+ int color;
+
+ if (o_current->saved_color == -1) {
+ color = o_current->color;
+ } else {
+ color = o_current->saved_color;
+ }
+
+ /* make sure you fix this in pin and bus as well */
+ /* still doesn't work... you need to pass in the new values */
+ /* or don't update and update later */
+ /* I think for now I'll disable the update and manually update */
+ new_obj = o_bus_add(w_current, list_tail, OBJ_BUS, color,
+ o_current->line->x[0], o_current->line->y[0],
+ o_current->line->x[1], o_current->line->y[1],
+ o_current->bus_ripper_direction);
+
+ new_obj->line->screen_x[0] = o_current->line->screen_x[0];
+ new_obj->line->screen_y[0] = o_current->line->screen_y[0];
+ new_obj->line->screen_x[1] = o_current->line->screen_x[1];
+ new_obj->line->screen_y[1] = o_current->line->screen_y[1];
+
+ new_obj->line->x[0] = o_current->line->x[0];
+ new_obj->line->y[0] = o_current->line->y[0];
+ new_obj->line->x[1] = o_current->line->x[1];
+ new_obj->line->y[1] = o_current->line->y[1];
+
+ a_current = o_current->attribs;
+
+ if (a_current) {
+ while ( a_current ) {
+
+ /* head attrib node has prev = NULL */
+ if (a_current->prev != NULL) {
+ a_current->copied_to = new_obj;
+ }
+ a_current = a_current->next;
+ }
+ }
+
+ return(new_obj);
+}
+
+/* \brief
+ * \par Function Description
+ *
+ */
+/* need to make this bus specific */
+void o_bus_print(TOPLEVEL *w_current, FILE *fp, OBJECT *o_current,
+ int origin_x, int origin_y)
+{
+ int offset, offset2;
+ int cross, bus_width;
+ int x1, y1;
+ int x2, y2;
+
+ if (o_current == NULL) {
+ printf("got null in o_bus_print\n");
+ return;
+ }
+
+ offset = 7*6;
+ offset2 = 7;
+
+ cross = offset;
+
+ if (w_current->print_color) {
+ f_print_set_color(fp, o_current->color);
+ }
+
+ bus_width = 2;
+ if (w_current->bus_style == THICK) {
+ bus_width = BUS_WIDTH;
+ }
+
+ x1 = o_current->line->x[0]-origin_x,
+ y1 = o_current->line->y[0]-origin_y;
+ x2 = o_current->line->x[1]-origin_x,
+ y2 = o_current->line->y[1]-origin_y;
+
+ fprintf(fp, "%d %d %d %d %d line\n",
+ x1,y1,x2,y2,bus_width);
+
+}
+
+/* \brief
+ * \par Function Description
+ *
+ */
+void o_bus_image_write(TOPLEVEL *w_current, OBJECT *o_current,
+ int origin_x, int origin_y, int color_mode)
+{
+ int offset, offset2;
+ int cross;
+ int x1, y1;
+ int x2, y2;
+ int color;
+
+ if (o_current == NULL) {
+ printf("got null in o_bus_image_write\n");
+ return;
+ }
+
+ if (color_mode == TRUE) {
+ color = o_image_geda2gd_color(o_current->color);
+ } else {
+ color = image_black;
+ }
+
+ offset = SCREENabs(w_current, BUS_WIDTH);
+
+ /*
+ offset = 7 * (float) w_current->height/ (float) w_current->width;
+ offset2 = 7 * (float) w_current->height/ (float) w_current->width*2;
+
+ printf("%f %d %d\n", (float) ( (float) w_current->height/ (float) w_current->width),
+ offset, offset2);
+ */
+
+ offset2 = offset*2;
+
+ cross = offset;
+
+ x1 = o_current->line->screen_x[0];
+ y1 = o_current->line->screen_y[0];
+ x2 = o_current->line->screen_x[1];
+ y2 = o_current->line->screen_y[1];
+
+ /* assumes screen coords are already calculated correctly */
+#ifdef HAS_LIBGDGEDA
+
+ gdImageSetThickness(current_im_ptr, SCREENabs(w_current, BUS_WIDTH));
+
+ gdImageLine(current_im_ptr, x1, y1, x2, y2, color);
+
+#endif
+
+}
+
+
+/* \brief
+ * \par Function Description
+ *
+ */
+/* takes in screen coordinates for the centerx,y, and then does the rotate
+ * in world space */
+/* also ignores angle argument... for now, rotate only in 90 degree
+ * increments */
+/* fully functional */
+void o_bus_rotate(TOPLEVEL *w_current, int centerx, int centery, int angle,
+ OBJECT *object)
+{
+ int world_centerx, world_centery;
+ int newx, newy;
+
+ SCREENtoWORLD(w_current, centerx, centery,
+ &world_centerx,
+ &world_centery);
+
+ /* change the bus ripper orientation when the rotation is 90 degrees */
+ /* yes it's okay to use o_net_orientation */
+ if (o_net_orientation(object) == VERTICAL && angle == 90) {
+ object->bus_ripper_direction = -object->bus_ripper_direction;
+ }
+
+ /* translate object to origin */
+ o_bus_translate_world(w_current, -world_centerx, -world_centery, object);
+
+ rotate_point_90(object->line->x[0], object->line->y[0], angle,
+ &newx, &newy);
+
+ object->line->x[0] = newx;
+ object->line->y[0] = newy;
+
+ rotate_point_90(object->line->x[1], object->line->y[1], angle,
+ &newx, &newy);
+
+ object->line->x[1] = newx;
+ object->line->y[1] = newy;
+
+ o_bus_translate_world(w_current, world_centerx, world_centery, object);
+
+}
+
+/* \brief
+ * \par Function Description
+ *
+ */
+void o_bus_rotate_world(TOPLEVEL *w_current,
+ int world_centerx, int world_centery, int angle,
+ OBJECT *object)
+{
+ int newx, newy;
+
+ if (angle == 0)
+ return;
+
+ /* translate object to origin */
+ o_bus_translate_world(w_current, -world_centerx, -world_centery, object);
+
+ rotate_point_90(object->line->x[0], object->line->y[0], angle,
+ &newx, &newy);
+
+ object->line->x[0] = newx;
+ object->line->y[0] = newy;
+
+ rotate_point_90(object->line->x[1], object->line->y[1], angle,
+ &newx, &newy);
+
+ object->line->x[1] = newx;
+ object->line->y[1] = newy;
+
+ o_bus_translate_world(w_current, world_centerx, world_centery, object);
+}
+
+/* \brief
+ * \par Function Description
+ *
+ */
+void o_bus_mirror(TOPLEVEL *w_current,
+ int centerx, int centery, OBJECT *object)
+{
+ int world_centerx, world_centery;
+
+ SCREENtoWORLD(w_current, centerx, centery,
+ &world_centerx,
+ &world_centery);
+
+ /* translate object to origin */
+ o_bus_translate_world(w_current, -world_centerx, -world_centery, object);
+
+ object->line->x[0] = -object->line->x[0];
+
+ object->line->x[1] = -object->line->x[1];
+
+ o_bus_translate_world(w_current, world_centerx, world_centery, object);
+}
+
+/* \brief
+ * \par Function Description
+ *
+ */
+void o_bus_mirror_world(TOPLEVEL *w_current,
+ int world_centerx, int world_centery, OBJECT *object)
+{
+ /* translate object to origin */
+ o_bus_translate_world(w_current, -world_centerx, -world_centery, object);
+
+ object->line->x[0] = -object->line->x[0];
+
+ object->line->x[1] = -object->line->x[1];
+
+ o_bus_translate_world(w_current, world_centerx, world_centery, object);
+}
+
+/* \brief
+ * \par Function Description
+ *
+ */
+int o_bus_orientation(OBJECT *object)
+{
+ if (object->line->y[0] == object->line->y[1]) {
+ return(HORIZONTAL);
+ }
+
+ if (object->line->x[0] == object->line->x[1]) {
+ return(VERTICAL);
+ }
+
+ return(NEITHER);
+}
+
+
+/* \brief
+ * \par Function Description
+ *
+ */
+/* this function does the actual work of making one net segment out of two */
+/* connected segments */
+/* The second object (del_object) is the object that should be deleted */
+/* needs to be bus specific */
+void o_bus_consolidate_lowlevel(OBJECT *object, OBJECT *del_object,
+ int orient)
+{
+ int temp1, temp2;
+ int final1, final2;
+ int changed=0;
+ ATTRIB *tail;
+
+#if DEBUG
+ printf("o %d %d %d %d\n", object->line->x[0], object->line->y[0], object->line->x[1], object->line->y[1]);
+ printf("d %d %d %d %d\n", del_object->line->x[0], del_object->line->y[0], del_object->line->x[1], del_object->line->y[1]);
+#endif
+
+
+ if (orient == HORIZONTAL) {
+
+ temp1 = min(object->line->x[0],
+ del_object->line->x[0]);
+ temp2 = min(object->line->x[1],
+ del_object->line->x[1]);
+
+ final1 = min(temp1, temp2);
+
+ temp1 = max(object->line->x[0],
+ del_object->line->x[0]);
+ temp2 = max(object->line->x[1],
+ del_object->line->x[1]);
+
+ final2 = max(temp1, temp2);
+
+ object->line->x[0] = final1;
+ object->line->x[1] = final2;
+ changed=1;
+ }
+
+ if (orient == VERTICAL) {
+ temp1 = min(object->line->y[0],
+ del_object->line->y[0]);
+ temp2 = min(object->line->y[1],
+ del_object->line->y[1]);
+
+ final1 = min(temp1, temp2);
+
+ temp1 = max(object->line->y[0],
+ del_object->line->y[0]);
+ temp2 = max(object->line->y[1],
+ del_object->line->y[1]);
+
+ final2 = max(temp1, temp2);
+
+ object->line->y[0] = final1;
+ object->line->y[1] = final2;
+ changed=1;
+ }
+
+#if DEBUG
+ printf("fo %d %d %d %d\n", object->line->x[0], object->line->y[0], object->line->x[1], object->line->y[1]);
+#endif
+
+ if (changed) {
+
+ /* first check for attributes */
+ if (del_object->attribs) {
+ printf("yeah... del object has attributes\n");
+ printf("reconnecting them to the right place\n");
+ if (object->attribs) {
+
+ printf("object DID have attributes\n");
+
+#if 0
+ printf("object->attribs\n");
+ o_attrib_print(object->attribs);
+ printf("--\n");
+ printf("del_object->attribs\n");
+ o_attrib_print(del_object->attribs);
+ printf("--\n");
+#endif
+ tail = o_attrib_return_tail(object->attribs);
+
+ /* skip over old attrib head */
+ tail->next = del_object->attribs->next;
+
+ /* step prev object to point to last object */
+ tail->next->prev = tail;
+
+
+ /* delete old attrib head */
+ /* and nothing else */
+ del_object->attribs->object=NULL;
+ del_object->attribs->next=NULL;
+ del_object->attribs->prev=NULL;
+ o_attrib_delete(del_object->attribs);
+
+ /* you don't need to free the attribs list */
+ /* since it's been relinked into object's */
+ /* attribs list */
+
+ del_object->attribs = NULL;
+#if 0
+ printf("\n\nfinal object->attribs\n");
+ o_attrib_print(object->attribs);
+ printf("--\n");
+#endif
+
+ } else {
+
+ printf("object didn't have any attributes\n");
+ object->attribs = del_object->attribs;
+ /*! \todo what should this be? */
+ object->attribs->prev = NULL;
+
+ /* setup parent attribute */
+ object->attribs->object = object;
+
+ /* you don't need to free the attribs list */
+ /* since it's been used by object */
+
+ del_object->attribs = NULL;
+ }
+ }
+ }
+
+}
+
+/* \brief
+ * \par Function Description
+ *
+ */
+/* needs to be bus specific */
+int o_bus_consolidate_segments(TOPLEVEL *w_current, OBJECT *object)
+{
+
+ return(0);
+}
+
+/* \brief
+ * \par Function Description
+ *
+ */
+void o_bus_consolidate(TOPLEVEL *w_current)
+{
+
+}
+
+/* \brief
+ * \par Function Description
+ *
+ */
+void o_bus_modify(TOPLEVEL *w_current, OBJECT *object,
+ int x, int y, int whichone)
+{
+ int screen_x, screen_y;
+ int left, right, top, bottom;
+
+ object->line->x[whichone] = x;
+ object->line->y[whichone] = y;
+
+ WORLDtoSCREEN(w_current,
+ object->line->x[whichone],
+ object->line->y[whichone],
+ &screen_x, &screen_y);
+
+ object->line->screen_x[whichone] = screen_x;
+ object->line->screen_y[whichone] = screen_y;
+
+ get_bus_bounds(w_current, object->line, &left, &top, &right, &bottom);
+
+ object->left = left;
+ object->top = top;
+ object->right = right;
+ object->bottom = bottom;
+}
+
+
1.23 +1269 -863 eda/geda/gaf/libgeda/src/o_circle_basic.c
(In the diff below, changes in quantity of whitespace are not shown.)
Index: o_circle_basic.c
===================================================================
RCS file: o_circle_basic.c
diff -N o_circle_basic.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ o_circle_basic.c 5 Jul 2006 03:13:38 -0000 1.23
@@ -0,0 +1,1424 @@
+/* gEDA - GPL Electronic Design Automation
+ * libgeda - gEDA's library
+ * Copyright (C) 1998-2000 Ales V. Hvezda
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+#include <config.h>
+#include <stdio.h>
+#include <math.h>
+
+#include <gtk/gtk.h>
+#include <libguile.h>
+
+#ifdef HAS_LIBGDGEDA
+#include <gdgeda/gd.h>
+#endif
+
+#include "defines.h"
+#include "struct.h"
+#include "globals.h"
+#include "o_types.h"
+
+#include "colors.h"
+#include "funcs.h"
+
+#include "../include/prototype.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+/*! \brief
+ * \par Function Description
+ *
+ */
+int dist(int x1, int y1, int x2, int y2)
+{
+ int dx1, dy1;
+ int dx2, dy2;
+ int ret;
+
+ dx1 = x1;
+ dy1 = y1;
+ dx2 = x2;
+ dy2 = y2;
+
+ ret = sqrt(pow(dx1-dx2,2)+pow(dy1-dy2,2)) ;
+ return( ret );
+}
+
+/*! \brief Create and add circle OBJECT to list.
+ * \par Function Description
+ * This function creates a new object representing a circle. This object is
+ * added to the end of the list <B>object_list</B> pointed object belongs to.
+ * The circle is described by its center (<B>x</B>,<B>y</B>) and its radius
+ * <B>radius</B>.
+ * The <B>type</B> parameter must be equal to <B>OBJ_CIRCLE</B>. The <B>color</B>
+ * corresponds to the color the box will be drawn with.
+ *
+ * The <B>OBJECT</B> structure is allocated with the #s_basic_init_object()
+ * function. The structure describing the circle is allocated and initialized
+ * with the parameters given to the function.
+ *
+ * Both the line type and the filling type are set to default values : solid
+ * line type with a width of 0, and no filling. It can be changed after
+ * with #o_set_line_options() and #o_set_fill_options().
+ *
+ * The object is added to the end of the list described by the
+ * <B>object_list</B> parameter with #s_basic_link_object().
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in,out] object_list OBJECT list to add circle to.
+ * \param [in] type Must be OBJ_CIRCLE.
+ * \param [in] color Circle line color.
+ * \param [in] x Center x coordinate.
+ * \param [in] y Center y coordinate.
+ * \param [in] radius Radius of new circle.
+ * \return A pointer to the new end of the object list.
+ */
+OBJECT *o_circle_add(TOPLEVEL *w_current, OBJECT *object_list,
+ char type, int color,
+ int x, int y, int radius)
+{
+ OBJECT *new_node;
+
+ /* create the object */
+ new_node = s_basic_init_object("circle");
+ new_node->type = type;
+ new_node->color = color;
+
+ new_node->circle = (CIRCLE *) malloc(sizeof(CIRCLE));
+
+ /* describe the circle with its center and radius */
+ new_node->circle->center_x = x;
+ new_node->circle->center_y = y;
+ new_node->circle->radius = radius;
+
+ /* line type and filling initialized to default */
+ o_set_line_options(w_current, new_node,
+ END_NONE, TYPE_SOLID, 0, -1, -1);
+ o_set_fill_options(w_current, new_node,
+ FILLING_HOLLOW, -1, -1, -1, -1, -1);
+
+ /* \todo questionable cast */
+ new_node->draw_func = (void *) circle_draw_func;
+ /* \todo questionable cast */
+ new_node->sel_func = (void *) select_func;
+
+ /* compute the bounding box and screen coords */
+ o_circle_recalc(w_current, new_node);
+
+ /* add the object to the list */
+ object_list = (OBJECT *) s_basic_link_object(new_node, object_list);
+
+ return(object_list);
+}
+
+/*! \brief Create a copy of a circle.
+ * \par Function Description
+ * The function #o_circle_copy() creates a verbatim copy of the object
+ * pointed by <B>o_current</B> describing a circle. The new object is added at
+ * the end of the list, following the <B>list_tail</B> pointed object.
+ *
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [out] list_tail OBJECT list to copy to.
+ * \param [in] o_current Circle OBJECT to copy.
+ * \return A new pointer to the end of the object list.
+ */
+OBJECT *o_circle_copy(TOPLEVEL *w_current, OBJECT *list_tail,
+ OBJECT *o_current)
+{
+ OBJECT *new_obj;
+ ATTRIB *a_current;
+ int color;
+
+ if (o_current->saved_color == -1) {
+ color = o_current->color;
+ } else {
+ color = o_current->saved_color;
+ }
+
+ /*
+ * A new circle object is added at the end of the object list with
+ * #o_circle_add(). Values for its fields are default and need to be
+ * modified.
+ */
+ /* create and link a new circle object */
+ new_obj = o_circle_add(w_current, list_tail, OBJ_CIRCLE,
+ color,
+ 0, 0, 0);
+
+ /*
+ * The parameters of the new circle are set with the ones of the original
+ * circle. The two circle have the same line type and the same filling
+ * options.
+ *
+ * The coordinates and the values in screen unit are computed with
+ * #o_circle_recalc().
+ */
+ /* modify */
+ new_obj->circle->center_x = o_current->circle->center_x;
+ new_obj->circle->center_y = o_current->circle->center_y;
+ new_obj->circle->radius = o_current->circle->radius;
+
+ o_set_line_options(w_current, new_obj, o_current->line_end,
+ o_current->line_type, o_current->line_width,
+ o_current->line_length, o_current->line_space);
+ o_set_fill_options(w_current, new_obj,
+ o_current->fill_type, o_current->fill_width,
+ o_current->fill_pitch1, o_current->fill_angle1,
+ o_current->fill_pitch2, o_current->fill_angle2);
+
+ o_circle_recalc(w_current, new_obj);
+
+ /* new_obj->attribute = 0;*/
+ a_current = o_current->attribs;
+ if (a_current) {
+ while ( a_current ) {
+
+ /* head attrib node has prev = NULL */
+ if (a_current->prev != NULL) {
+ a_current->copied_to = new_obj;
+ }
+ a_current = a_current->next;
+ }
+ }
+
+ return(new_obj);
+}
+
+/*! \brief Modify the description of a circle OBJECT.
+ * \par Function Description
+ * This function modifies the description of the circle object <B>*object</B>
+ * depending on <B>whichone</B> that give the meaning of the <B>x</B> and <B>y</B>
+ * parameters.
+ *
+ * If <B>whichone</B> is equal to <B>CIRCLE_CENTER</B>, the new center of the
+ * circle is given by (<B>x</B>,<B>y</B>) where <B>x</B> and <B>y</B> are in world units.
+ *
+ * If <B>whichone</B> is equal to <B>CIRCLE_RADIUS</B>, the radius is given by
+ * <B>x</B> - in world units. <B>y</B> is ignored.
+ *
+ * The screen coords and the bounding box of the circle object are updated
+ * after the modification of its parameters.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in,out] object Circle OBJECT to modify.
+ * \param [in] x New center x coordinate, or radius value.
+ * \param [in] y New center y coordinate.
+ * Unused if radius is being modified.
+ * \param [in] whichone Which circle parameter to modify.
+ *
+ * <B>whichone</B> can have the following values:
+ * <DL>
+ * <DT>*</DT><DD>CIRCLE_CENTER
+ * <DT>*</DT><DD>CIRCLE_RADIUS
+ * </DL>
+ */
+void o_circle_modify(TOPLEVEL *w_current, OBJECT *object,
+ int x, int y, int whichone)
+{
+ switch(whichone) {
+ case CIRCLE_CENTER:
+ /* modify the center of the circle */
+ object->circle->center_x = x;
+ object->circle->center_y = y;
+ break;
+ case CIRCLE_RADIUS:
+ /* modify the radius of the circle */
+ if (x == 0) {
+ s_log_message("Null radius circles are not allowed\n");
+ return;
+ }
+ object->circle->radius = x;
+ break;
+ default:
+ break;
+ }
+
+ /* recalculate the screen coords and the boundings */
+ o_circle_recalc(w_current, object);
+
+}
+
+/*! \brief Create circle OBJECT from character string.
+ * \par Function Description
+ * The #o_circle_read() function gets from the character string <B>*buff</B> the
+ * description of a circle. The new circle is then added to the list of
+ * objects of which <B>*object_list</B> is the last element before the call.
+ *
+ * Depending on <B>*version</B>, the right file format is considered.
+ * Currently two file format revisions are supported :
+ * <DL>
+ * <DT>*</DT><DD>the file format used until 2000704 release.
+ * <DT>*</DT><DD>the file format used for the releases after 20000704.
+ * </DL>
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [out] object_list OBJECT list to create circle in.
+ * \param [in] buf Character string with circle description.
+ * \param [in] release_ver libgeda release version number.
+ * \param [in] fileformat_ver libgeda file format version number.
+ * \return A pointer to the new circle object.
+ */
+OBJECT *o_circle_read(TOPLEVEL *w_current, OBJECT *object_list, char buf[],
+ unsigned int release_ver, unsigned int fileformat_ver)
+{
+ char type;
+ int x1, y1;
+ int radius;
+ int color;
+ int circle_width, circle_space, circle_length;
+ int fill_width, angle1, pitch1, angle2, pitch2;
+ int circle_end;
+ int circle_type;
+ int circle_fill;
+
+ if(release_ver <= VERSION_20000704) {
+ /*
+ * The old geda file format, i.e. releases 20000704 and older, does not
+ * handle the line type and the filling of the box object. They are set
+ * to default.
+ */
+ sscanf(buf, "%c %d %d %d %d\n", &type, &x1, &y1, &radius, &color);
+
+ circle_width = 0;
+ circle_end = END_NONE;
+ circle_type = TYPE_SOLID;
+ circle_length= -1;
+ circle_space = -1;
+
+ circle_fill = FILLING_HOLLOW;
+ fill_width = 0;
+ angle1 = -1;
+ pitch1 = -1;
+ angle2 = -1;
+ pitch2 = -1;
+
+ } else {
+
+ /*
+ * The current line format to describe a circle is a space separated
+ * list of characters and numbers in plain ASCII on a single line. The
+ * meaning of each item is described in the file format documentation.
+ */
+ sscanf(buf, "%c %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
+ &type, &x1, &y1, &radius, &color,
+ &circle_width, &circle_end, &circle_type,
+ &circle_length, &circle_space, &circle_fill,
+ &fill_width, &angle1, &pitch1, &angle2, &pitch2);
+ }
+
+
+ if (radius == 0) {
+ fprintf(stderr, "Found a zero radius circle [ %c %d %d %d %d ]\n",
+ type, x1, y1, radius, color);
+ s_log_message("Found a zero radius circle [ %c %d %d %d %d ]\n",
+ type, x1, y1, radius, color);
+
+ }
+
+ if (color < 0 || color > MAX_COLORS) {
+ fprintf(stderr, "Found an invalid color [ %s ]\n", buf);
+ s_log_message("Found an invalid color [ %s ]\n", buf);
+ s_log_message("Setting color to WHITE\n");
+ color = WHITE;
+ }
+
+ /*
+ * A circle is internally described by its center and its radius.
+ *
+ * A new object is allocated, initialized and added to the object list.
+ * Its filling and line type are set according to the values of the field
+ * on the line.
+ */
+ object_list = (OBJECT *) o_circle_add(w_current, object_list,
+ type, color, x1, y1, radius);
+ o_set_line_options(w_current, object_list,
+ circle_end, circle_type, circle_width,
+ circle_length, circle_space);
+ o_set_fill_options(w_current, object_list,
+ circle_fill, fill_width, pitch1, angle1, pitch2, angle2);
+
+ return(object_list);
+}
+
+/*! \brief Create a character string representation of a circle OBJECT.
+ * \par Function Description
+ * This function formats a string in the buffer <B>*buff</B> to describe the
+ * circle object <B>*object</B>.
+ * It follows the post-20000704 release file format that handle the line
+ * type and fill options.
+ *
+ * \param [in] object Circle OBJECT to create string from.
+ * \return A pointer to the circle OBJECT character string.
+ *
+ * \note
+ * Caller must free returned character string.
+ *
+ */
+char *o_circle_save(OBJECT *object)
+{
+ int x,y;
+ int radius;
+ int color;
+ int circle_width, circle_space, circle_length;
+ int fill_width, angle1, pitch1, angle2, pitch2;
+ char *buf;
+ OBJECT_END circle_end;
+ OBJECT_TYPE circle_type;
+ OBJECT_FILLING circle_fill;
+
+ /* circle center and radius */
+ x = object->circle->center_x;
+ y = object->circle->center_y;
+ radius = object->circle->radius;
+
+ /* line type parameters */
+ circle_width = object->line_width;
+ circle_end = object->line_end;
+ circle_type = object->line_type;
+ circle_length= object->line_length;
+ circle_space = object->line_space;
+
+ /* filling parameters */
+ circle_fill = object->fill_type;
+ fill_width = object->fill_width;
+ angle1 = object->fill_angle1;
+ pitch1 = object->fill_pitch1;
+ angle2 = object->fill_angle2;
+ pitch2 = object->fill_pitch2;
+
+ /* Use the right color */
+ if (object->saved_color == -1) {
+ color = object->color;
+ } else {
+ color = object->saved_color;
+ }
+
+#if 0 /* old system */
+ radius = abs(x2 - x1)/2;
+ if (radius == 0) {
+ radius = abs(y2 - y1)/2;
+ }
+
+ x = x1 + radius;
+ y = y1 - radius; /* careful */
+#endif
+
+ buf = g_strdup_printf("%c %d %d %d %d %d %d %d %d %d %d %d %d %d %d %d",
+ object->type, x, y, radius, color,
+ circle_width, circle_end, circle_type, circle_length,
+ circle_space, circle_fill,
+ fill_width, angle1, pitch1, angle2, pitch2);
+ return(buf);
+}
+
+/*! \brief Translate a circle position by a delta.
+ * \par Function Description
+ * This function applies a translation of (<B>dx</B>,<B>dy</B> to the circle
+ * described by <B>*object</B>. <B>dx</B> and <B>dy</B> are in screen unit.
+ *
+ * The translation vector is converted in world unit. The translation is
+ * made with #o_circle_translate_world().
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] dx x distance to move.
+ * \param [in] dy y distance to move.
+ * \param [in,out] object Circle OBJECT to translate.
+ */
+void o_circle_translate(TOPLEVEL *w_current, int dx, int dy, OBJECT *object)
+{
+ int world_dx, world_dy;
+
+ if (object == NULL) printf("ct NO!\n");
+
+ /* convert the translation vector in world unit */
+ world_dx = SCREENabs(w_current, dx);
+ world_dy = SCREENabs(w_current, dy);
+
+ /* translate the circle */
+ o_circle_translate_world(w_current, world_dx, world_dy, object);
+
+ /* screen coords and boundings are updated by _translate_world() */
+
+}
+
+/*! \brief Translate a circle position in WORLD coordinates by a delta.
+ * \par Function Description
+ * This function applies a translation of (<B>x1</B>,<B>y1</B>) to the circle
+ * described by <B>*object</B>. <B>x1</B> and <B>y1</B> are in world unit.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] x1 x distance to move.
+ * \param [in] y1 y distance to move.
+ * \param [in,out] object Circle OBJECT to translate.
+ */
+void o_circle_translate_world(TOPLEVEL *w_current,
+ int x1, int y1, OBJECT *object)
+{
+ if (object == NULL) printf("ctw NO!\n");
+
+ /* Do world coords */
+ object->circle->center_x = object->circle->center_x + x1;
+ object->circle->center_y = object->circle->center_y + y1;
+
+ /* recalc the screen coords and the bounding box */
+ o_circle_recalc(w_current, object);
+
+}
+
+/*! \brief Rotate a Circle OBJECT.
+ * \par Function Description
+ * The function #o_circle_rotate_world() rotate the circle described by
+ * <B>*object</B> around the (<B>world_centerx</B>,<B>world_centery</B>) point by
+ * angle <B>angle</B> degrees.
+ * The center of rotation is in world unit.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] centerx Rotation center x coordinate in SCREEN units.
+ * \param [in] centery Rotation center y coordinate in SCREEN units.
+ * \param [in] angle Rotation angle in degrees (unused).
+ * \param [in,out] object Circle OBJECT to rotate.
+ *
+ * \note
+ * takes in screen coordinates for the centerx,y, and then does the rotate
+ * in world space
+ * also ignores angle argument... for now, rotate only in 90 degree
+ * increments
+ */
+void o_circle_rotate(TOPLEVEL *w_current,
+ int centerx, int centery, int angle,
+ OBJECT *object)
+{
+ int world_centerx, world_centery;
+
+ /* convert the center of rotation to world unit */
+ SCREENtoWORLD(w_current,
+ centerx, centery,
+ &world_centerx, &world_centery);
+
+ /* rotate the circle */
+ o_circle_rotate_world(w_current,
+ world_centerx, world_centery, angle,
+ object);
+
+ /* screen coords and boundings are updated by _rotate_world() */
+
+}
+
+/*! \brief Rotate Circle OBJECT using WORLD coordinates.
+ * \par Function Description
+ * The function #o_circle_rotate_world() rotate the circle described by
+ * <B>*object</B> around the (<B>world_centerx</B>,<B>world_centery</B>) point by
+ * angle <B>angle</B> degrees.
+ * The center of rotation is in world unit.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] world_centerx Rotation center x coordinate in WORLD units.
+ * \param [in] world_centery Rotation center y coordinate in WORLD units.
+ * \param [in] angle Rotation angle in degrees (See note below).
+ * \param [in,out] object Circle OBJECT to rotate.
+ */
+void o_circle_rotate_world(TOPLEVEL *w_current,
+ int world_centerx, int world_centery, int angle,
+ OBJECT *object)
+{
+ int newx, newy;
+ int x, y;
+
+ /* Only 90 degree multiple and positive angles are allowed. */
+ /* angle must be positive */
+ if(angle < 0) angle = -angle;
+ /* angle must be a 90 multiple or no rotation performed */
+ if((angle % 90) != 0) return;
+
+ /*
+ * The center of rotation (<B>world_centerx</B>,<B>world_centery</B>) is
+ * translated to the origin. The rotation of the center around the origin
+ * is then performed. Finally, the rotated circle is translated back to
+ * its previous location.
+ */
+
+ /* translate object to origin */
+ object->circle->center_x -= world_centerx;
+ object->circle->center_y -= world_centery;
+
+ /* rotate the center of the circle around the origin */
+ x = object->circle->center_x;
+ y = object->circle->center_y;
+ rotate_point_90(x, y, angle, &newx, &newy);
+ object->circle->center_x = newx;
+ object->circle->center_y = newy;
+
+ /* translate back in position */
+ object->circle->center_x += world_centerx;
+ object->circle->center_y += world_centery;
+
+ o_circle_recalc(w_current, object);
+
+}
+
+/*! \brief Mirror a Circle.
+ * \par Function Description
+ * This function mirrors the circle from the point (<B>centerx</B>,<B>centery</B>)
+ * in screen unit.
+ *
+ * The origin of the mirror in screen unit is converted in world unit.
+ * The circle is mirrored with the function #o_circle_mirror_world()
+ * for which the origin of the mirror must be given in world unit.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] centerx Origin x coordinate in WORLD units.
+ * \param [in] centery Origin y coordinate in WORLD units.
+ * \param [in,out] object Circle OBJECT to mirror.
+ */
+void o_circle_mirror(TOPLEVEL *w_current,
+ int centerx, int centery,
+ OBJECT *object)
+{
+ int world_centerx, world_centery;
+
+ /* convert the origin of mirror */
+ SCREENtoWORLD(w_current,
+ centerx, centery,
+ &world_centerx, &world_centery);
+
+ /* apply the mirror in world coords */
+ o_circle_mirror_world(w_current,
+ world_centerx, world_centery,
+ object);
+
+ /* screen coords and boundings are updated by _mirror_world() */
+}
+
+/*! \brief Mirror circle using WORLD coordinates.
+ * \par Function Description
+ * This function recalculates the screen coords of the <B>o_current</B> pointed
+ * circle object from its world coords.
+ *
+ * The circle coordinates and its bounding are recalculated as well as the
+ * OBJECT specific (line width, filling ...).
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] world_centerx Origin x coordinate in WORLD units.
+ * \param [in] world_centery Origin y coordinate in WORLD units.
+ * \param [in,out] object Circle OBJECT to mirror.
+ */
+void o_circle_mirror_world(TOPLEVEL *w_current,
+ int world_centerx, int world_centery,
+ OBJECT *object)
+{
+ /* translate object to origin */
+ object->circle->center_x -= world_centerx;
+ object->circle->center_y -= world_centery;
+
+ /* mirror the center of the circle */
+ object->circle->center_x = -object->circle->center_x;
+ object->circle->center_y = object->circle->center_y;
+
+ /* translate back in position */
+ object->circle->center_x += world_centerx;
+ object->circle->center_y += world_centery;
+
+ /* recalc boundings and screen coords */
+ o_circle_recalc(w_current, object);
+
+}
+
+/*! \brief Recalculate circle coordinates in SCREEN units.
+ * \par Function Description
+ * This function recalculates the screen coords of the <B>o_current</B> pointed
+ * circle object from its world coords.
+ *
+ * The circle coordinates and its bounding are recalculated as well as the
+ * OBJECT specific (line width, filling ...).
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in,out] o_current Circle OBJECT to be recalculated.
+ */
+void o_circle_recalc(TOPLEVEL *w_current, OBJECT *o_current)
+{
+ int screen_x1, screen_y1;
+ int left, right, top, bottom;
+
+ if (o_current->circle == NULL) {
+ return;
+ }
+
+#if DEBUG
+ printf("drawing circle\n");
+#endif
+
+
+ /* update the screen coords of the center of the circle */
+ WORLDtoSCREEN(w_current,
+ o_current->circle->center_x, o_current->circle->center_y,
+ &screen_x1, &screen_y1);
+ o_current->circle->screen_x = screen_x1;
+ o_current->circle->screen_y = screen_y1;
+
+ /* update the value of the radius in screen unit */
+ o_current->circle->screen_radius = SCREENabs(w_current,
+ o_current->circle->radius);
+
+ /* update the bounding box - screen unit */
+ get_circle_bounds(w_current, o_current->circle,
+ &left, &top, &right, &bottom);
+ o_current->left = left;
+ o_current->top = top;
+ o_current->right = right;
+ o_current->bottom = bottom;
+
+ /* recalc OBJECT specific parameters */
+ o_object_recalc(w_current, o_current);
+
+}
+
+/*! \brief Get circle bounding rectangle.
+ * \par Function Description
+ * This function sets the <B>left</B>, <B>top</B>, <B>right</B>
+ * and <B>bottom</B> pointed variables to the boundings of the circle object
+ * described in <B>*circle</B> in screen unit.
+ *
+ * The function finds the smallest rectangle that cover this circle.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] circle Circle OBJECT to read coordinates from.
+ * \param [out] left Left circle coordinate in SCREEN units.
+ * \param [out] top Top circle coordinate in SCREEN units.
+ * \param [out] right Right circle coordinate in SCREEN units.
+ * \param [out] bottom Bottom circle coordinate in SCREEN units.
+ */
+void get_circle_bounds(TOPLEVEL *w_current, CIRCLE *circle,
+ int *left, int *top,
+ int *right, int *bottom)
+{
+ *left = circle->screen_x - circle->screen_radius;
+ *top = circle->screen_y - circle->screen_radius;
+ *right = circle->screen_x + circle->screen_radius;
+ *bottom = circle->screen_y + circle->screen_radius;
+
+ /* PB : need to take into account the width of the line */
+
+ /* out temp
+ *left = *left - 4;
+ *top = *top - 4;
+
+ *right = *right + 4;
+ *bottom = *bottom + 4;
+ */
+}
+
+/*! \brief Get circle bounding rectangle in WORLD coordinates.
+ * \par Function Description
+ * This function sets the <B>left</B>, <B>top</B>, <B>right</B> and <B>bottom</B>
+ * parameters to the boundings of the circle object described in <B>*circle</B>
+ * in world units.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] circle Circle OBJECT to read coordinates from.
+ * \param [out] left Left circle coordinate in WORLD units.
+ * \param [out] top Top circle coordinate in WORLD units.
+ * \param [out] right Right circle coordinate in WORLD units.
+ * \param [out] bottom Bottom circle coordinate in WORLD units.
+ */
+void world_get_circle_bounds(TOPLEVEL *w_current, CIRCLE *circle, int *left,
+ int *top, int *right, int *bottom)
+{
+
+ *left = w_current->init_right;
+ *top = w_current->init_bottom;
+ *right = 0;
+ *bottom = 0;
+
+
+ *left = circle->center_x - circle->radius;
+ *top = circle->center_y - circle->radius;
+ *right = circle->center_x + circle->radius;
+ *bottom = circle->center_y + circle->radius;
+
+ /*
+ *left = points->x1;
+ *top = points->y1;
+ *right = points->x1+(temp);
+ *bottom = points->y1-(temp);
+ */
+
+ /*
+ *left = min(circle->x1, circle->x1+temp);
+ *top = min(circle->y1, circle->y1-temp);
+ *right = max(circle->x1, circle->x1+temp);
+ *bottom = max(circle->y1, circle->y1-temp);*/
+
+#if DEBUG
+ printf("circle: %d %d %d %d\n", *left, *top, *right, *bottom);
+#endif
+
+}
+
+/*! \brief Print circle to Postscript document.
+ * \par Function Description
+ * This function prints the circle described by the <B>o_current</B>
+ * parameter to a Postscript document. It takes into account its line type
+ * and fill type.
+ * The Postscript document is descibed by the file pointer <B>fp</B>.
+ *
+ * The validity of the <B>o_current</B> pointer is checked :
+ * a null pointer causes an error message and a return.
+ *
+ * The description of the circle is extracted from the <B>o_current</B>
+ * parameter : the coordinates of the center of the circle, its radius,
+ * its line type, its fill type.
+ *
+ * The outline and the inside of the circle are successively handled by
+ * two differend sets of functions.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] fp FILE pointer to Postscript document.
+ * \param [in] o_current Circle OBJECT to write to document.
+ * \param [in] origin_x Page x coordinate to place circle OBJECT.
+ * \param [in] origin_y Page y coordinate to place circle OBJECT.
+ */
+void o_circle_print(TOPLEVEL *w_current, FILE *fp, OBJECT *o_current,
+ int origin_x, int origin_y)
+{
+ int x, y, radius;
+ int color;
+ int circle_width, length, space;
+ int fill_width, angle1, pitch1, angle2, pitch2;
+ void (*outl_func)() = NULL;
+ void (*fill_func)() = NULL;
+
+ if (o_current == NULL) {
+ printf("got null in o_circle_print\n");
+ return;
+ }
+
+ x = o_current->circle->center_x;
+ y = o_current->circle->center_y;
+ radius = o_current->circle->radius;
+
+ color = o_current->color;
+
+ /*
+ * Depending on the type of the line for this particular circle, the
+ * appropriate function is chosen among #o_circle_print_solid(),
+ * #o_circle_print_dotted(), #o_circle_print_dashed(),
+ * #o_circle_print_center() and #o_circle_print_phantom().
+ *
+ * The needed parameters for each of these type is extracted from the
+ * <B>o_current</B> object. Depending on the type, unused parameters are
+ * set to -1.
+ *
+ * In the eventuality of a length and/or space null, the line is
+ * printed solid to avoid and endless loop produced by other functions
+ * in such a case.
+ */
+ circle_width = o_current->line_width;
+ if(circle_width <= 2) circle_width=2;
+ length = o_current->line_length;
+ space = o_current->line_space;
+
+ switch(o_current->line_type) {
+ case(TYPE_SOLID):
+ length = -1; space = -1;
+ outl_func = (void *) o_circle_print_solid;
+ break;
+
+ case(TYPE_DOTTED):
+ length = -1;
+ outl_func = (void *) o_circle_print_dotted;
+ break;
+
+ case(TYPE_DASHED):
+ outl_func = (void *) o_circle_print_dashed;
+ break;
+
+ case(TYPE_CENTER):
+ outl_func = (void *) o_circle_print_center;
+ break;
+
+ case(TYPE_PHANTOM):
+ outl_func = (void *) o_circle_print_phantom;
+ break;
+
+ case(TYPE_ERASE):
+ /* Unused for now print it solid */
+ length = -1; space = -1;
+ outl_func = (void *) o_circle_print_solid;
+ break;
+ }
+
+ if((length == 0) || (space == 0)) {
+ length = -1; space = -1;
+ outl_func = (void *) o_circle_print_solid;
+ }
+
+ (*outl_func)(w_current, fp,
+ x - origin_x, y - origin_y,
+ radius,
+ color,
+ circle_width, length, space,
+ origin_x, origin_y);
+
+ /*
+ * If the filling type of the circle is not <B>HOLLOW</B>, the appropriate
+ * function is chosen among #o_circle_print_filled(), #o_circle_print_mesh()
+ * and #o_circle_print_hatch(). The corresponding parameters are extracted
+ * from the <B>o_current</B> object and corrected afterward.
+ *
+ * The case where <B>pitch1</B> and <B>pitch2</B> are null or negative is
+ * avoided as it leads to an endless loop in most of the called functions.
+ * In such a case, the circle is printed filled. Unused parameters for
+ * each of these functions are set to -1 or any passive value.
+ */
+ if(o_current->fill_type != FILLING_HOLLOW) {
+ fill_width = o_current->fill_width;
+ angle1 = o_current->fill_angle1;
+ pitch1 = o_current->fill_pitch1;
+ angle2 = o_current->fill_angle2;
+ pitch2 = o_current->fill_pitch2;
+
+ switch(o_current->fill_type) {
+ case(FILLING_FILL):
+ angle1 = -1; pitch1 = 1;
+ angle2 = -1; pitch2 = 1;
+ fill_width = -1;
+ fill_func = (void *) o_circle_print_filled;
+ break;
+
+ case(FILLING_MESH):
+ fill_func = (void *) o_circle_print_mesh;
+ break;
+
+ case(FILLING_HATCH):
+ angle2 = -1; pitch2 = 1;
+ fill_func = (void *) o_circle_print_hatch;
+ break;
+
+ case(FILLING_VOID):
+ /* Unused for now, print it filled */
+ angle1 = -1; pitch1 = 1;
+ angle2 = -1; pitch2 = 1;
+ fill_width = -1;
+ fill_func = (void *) o_circle_print_filled;
+ break;
+
+ case(FILLING_HOLLOW):
+ /* nop */
+ break;
+ }
+
+ if((pitch1 <= 0) || (pitch2 <= 0)) {
+ angle1 = -1; pitch1 = 1;
+ angle2 = -1; pitch2 = 1;
+ fill_func = (void *) o_circle_print_filled;
+ }
+
+ (*fill_func)(w_current, fp,
+ x, y, radius,
+ color,
+ fill_width,
+ angle1, pitch1, angle2, pitch2,
+ origin_x, origin_y);
+ }
+}
+
+/*! \brief Print a solid circle to Postscript document.
+ * \par Function Description
+ * This function prints the outline of a circle when a solid line type
+ * is required. The circle is defined by its center in (<B>x</B>, <B>y</B>)
+ * and its radius in <B>radius</B>. It is printed with the color given
+ * in <B>color</B>.
+ * The parameters <B>length</B> and <B>space</B> are ignored.
+ *
+ * It uses the function #o_arc_print_solid() to print the outline.
+ * Therefore it acts as an interface between the way a circle is defined
+ * and the way an arc is defined.
+ *
+ * All dimensions are in mils.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] fp FILE pointer to Postscript document.
+ * \param [in] x Center x coordinate of circle.
+ * \param [in] y Center y coordinate of circle.
+ * \param [in] radius Circle radius.
+ * \param [in] color Circle color.
+ * \param [in] circle_width Width of circle.
+ * \param [in] length (unused).
+ * \param [in] space (unused).
+ * \param [in] origin_x Page x coordinate to place circle OBJECT.
+ * \param [in] origin_y Page y coordinate to place circle OBJECT.
+ */
+void o_circle_print_solid(TOPLEVEL *w_current, FILE *fp,
+ int x, int y, int radius,
+ int color,
+ int circle_width, int length, int space,
+ int origin_x, int origin_y)
+{
+
+ o_arc_print_solid(w_current, fp,
+ x, y, radius,
+ 0, FULL_CIRCLE / 64,
+ color,
+ circle_width, -1, -1,
+ origin_x, origin_y);
+
+}
+
+
+/*! \brief Print a dotted circle to Postscript document.
+ * \par Function Description
+ * This function prints the outline of a circle when a dotted line
+ * type is required. The circle is defined by its center
+ * in (<B>x</B>, <B>y</B>) and its radius in <B>radius</B>. It is printed
+ * with the color given in <B>color</B>.
+ * The parameter <B>length</B> is ignored.
+ *
+ * It uses the function #o_arc_print_dotted() to print the outline.
+ * Therefore it acts as an interface between the way a circle is
+ * defined and the way an arc is defined.
+ *
+ * All dimensions are in mils.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] fp FILE pointer to Postscript document.
+ * \param [in] x Center x coordinate of circle.
+ * \param [in] y Center y coordinate of circle.
+ * \param [in] radius Circle radius.
+ * \param [in] color Circle color.
+ * \param [in] circle_width Width of circle.
+ * \param [in] length (unused).
+ * \param [in] space Space between dots.
+ * \param [in] origin_x Page x coordinate to place circle OBJECT.
+ * \param [in] origin_y Page y coordinate to place circle OBJECT.
+ */
+void o_circle_print_dotted(TOPLEVEL *w_current, FILE *fp,
+ int x, int y, int radius,
+ int color,
+ int circle_width, int length, int space,
+ int origin_x, int origin_y)
+{
+
+ o_arc_print_dotted(w_current, fp,
+ x, y, radius,
+ 0, FULL_CIRCLE / 64,
+ color,
+ circle_width, -1, space,
+ origin_x, origin_y);
+
+}
+
+/*! \brief Print a dashed circle to Postscript document.
+ * \par Function Description
+ * This function prints the outline of a circle when a dashed line type
+ * is required. The circle is defined by its center in
+ * (<B>x</B>, <B>y</B>) and its radius in <B>radius</B>. It is printed with the
+ * color given in <B>color</B>.
+ *
+ * It uses the function #o_arc_print_dashed() to print the outline.
+ * Therefore it acts as an interface between the way a circle is
+ * defined and the way an arc is defined.
+ *
+ * All dimensions are in mils.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] fp FILE pointer to Postscript document.
+ * \param [in] x Center x coordinate of circle.
+ * \param [in] y Center y coordinate of circle.
+ * \param [in] radius Circle radius.
+ * \param [in] color Circle color.
+ * \param [in] circle_width Width of circle.
+ * \param [in] length Length of dashed lines.
+ * \param [in] space Space between dashes.
+ * \param [in] origin_x Page x coordinate to place circle OBJECT.
+ * \param [in] origin_y Page y coordinate to place circle OBJECT.
+ */
+void o_circle_print_dashed(TOPLEVEL *w_current, FILE *fp,
+ int x, int y,
+ int radius,
+ int color,
+ int circle_width, int length, int space,
+ int origin_x, int origin_y)
+{
+
+ o_arc_print_dashed(w_current, fp,
+ x, y, radius,
+ 0, FULL_CIRCLE / 64,
+ color,
+ circle_width, length, space,
+ origin_x, origin_y);
+
+}
+
+/*! \brief Print a centered line type circle to Postscript document.
+ * \par Function Description
+ * This function prints the outline of a circle when a centered line
+ * type is required. The circle is defined by its center in
+ * (<B>x</B>, <B>y</B>) and its radius in <B>radius</B>. It is printed with the
+ * color given in <B>color</B>.
+ *
+ * It uses the function #o_arc_print_center() to print the outline.
+ * Therefore it acts as an interface between the way a circle is
+ * defined and the way an arc is defined.
+ *
+ * All dimensions are in mils.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] fp FILE pointer to Postscript document.
+ * \param [in] x Center x coordinate of circle.
+ * \param [in] y Center y coordinate of circle.
+ * \param [in] radius Circle radius.
+ * \param [in] color Circle color.
+ * \param [in] circle_width Width of circle.
+ * \param [in] length Length of dashed lines.
+ * \param [in] space Space between dashes.
+ * \param [in] origin_x Page x coordinate to place circle OBJECT.
+ * \param [in] origin_y Page y coordinate to place circle OBJECT.
+ */
+void o_circle_print_center(TOPLEVEL *w_current, FILE *fp,
+ int x, int y,
+ int radius,
+ int color,
+ int circle_width, int length, int space,
+ int origin_x, int origin_y)
+{
+
+ o_arc_print_center(w_current, fp,
+ x, y, radius,
+ 0, FULL_CIRCLE / 64,
+ color,
+ circle_width, length, space,
+ origin_x, origin_y);
+
+}
+
+/*! \brief Print a phantom line type circle to Postscript document.
+ * \par Function Description
+ * This function prints the outline of a circle when a phantom line type
+ * is required. The circle is defined by its center in
+ * (<B>x</B>, <B>y</B>) and its radius in <B>radius</B>. It is printed with the
+ * color given in <B>color</B>.
+ *
+ * It uses the function #o_arc_print_phantom() to print the outline.
+ * Therefore it acts as an interface between the way a circle is defined
+ * and the way an arc is defined.
+ *
+ * All dimensions are in mils.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] fp FILE pointer to Postscript document.
+ * \param [in] x Center x coordinate of circle.
+ * \param [in] y Center y coordinate of circle.
+ * \param [in] radius Circle radius.
+ * \param [in] color Circle color.
+ * \param [in] circle_width Width of circle.
+ * \param [in] length Length of dashed lines.
+ * \param [in] space Space between dashes.
+ * \param [in] origin_x Page x coordinate to place circle OBJECT.
+ * \param [in] origin_y Page y coordinate to place circle OBJECT.
+ */
+void o_circle_print_phantom(TOPLEVEL *w_current, FILE *fp,
+ int x, int y,
+ int radius,
+ int color,
+ int circle_width, int length, int space,
+ int origin_x, int origin_y)
+{
+
+ o_arc_print_phantom(w_current, fp,
+ x, y, radius,
+ 0, FULL_CIRCLE / 64,
+ color,
+ circle_width, length, space,
+ origin_x, origin_y);
+
+}
+
+/*! \brief Print a solid pattern circle to Postscript document.
+ * \par Function Description
+ * The function prints a filled circle with a solid pattern.
+ * No outline is printed.
+ * The circle is defined by the coordinates of its center in
+ * (<B>x</B>,<B>y</B>) and its radius given by the <B>radius</B> parameter.
+ * The postscript file is defined by the file pointer <B>fp</B>.
+ * <B>fill_width</B>, <B>angle1</B> and <B>pitch1</B>, <B>angle2</B>
+ * and <B>pitch2</B> parameters are ignored in this functions but
+ * kept for compatibility with other fill functions.
+ *
+ * All dimensions are in mils (except <B>angle1</B> and <B>angle2</B> in degree).
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] fp FILE pointer to Postscript document.
+ * \param [in] x Center x coordinate of circle.
+ * \param [in] y Center y coordinate of circle.
+ * \param [in] radius Radius of circle.
+ * \param [in] color Circle color.
+ * \param [in] fill_width Circle fill width. (unused).
+ * \param [in] angle1 (unused).
+ * \param [in] pitch1 (unused).
+ * \param [in] angle2 (unused).
+ * \param [in] pitch2 (unused).
+ * \param [in] origin_x Page x coordinate to place circle OBJECT.
+ * \param [in] origin_y Page y coordinate to place circle OBJECT.
+ */
+void o_circle_print_filled(TOPLEVEL *w_current, FILE *fp,
+ int x, int y, int radius,
+ int color,
+ int fill_width,
+ int angle1, int pitch1,
+ int angle2, int pitch2,
+ int origin_x, int origin_y)
+{
+ if (w_current->print_color) {
+ f_print_set_color(fp, color);
+ }
+
+ fprintf(fp, "%d %d %d dot\n",
+ x-origin_x, y-origin_y,
+ radius);
+
+}
+
+/*! \brief Print a mesh pattern circle to Postscript document.
+ * \par Function Description
+ * This function prints a meshed circle. No outline is printed.
+ * The circle is defined by the coordinates of its center in
+ * (<B>x</B>,<B>y</B>) and its radius by the <B>radius</B> parameter.
+ * The Postscript document is defined by the file pointer <B>fp</B>.
+ *
+ * The inside mesh is achieved by two successive call to the
+ * #o_circle_print_hatch() function, given <B>angle1</B> and <B>pitch1</B>
+ * the first time and <B>angle2</B> and <B>pitch2</B> the second time.
+ *
+ * Negative or null values for <B>pitch1</B> and/or <B>pitch2</B> are
+ * not allowed as it leads to an endless loop in #o_circle_print_hatch().
+ *
+ * All dimensions are in mils (except <B>angle1</B> and <B>angle2</B> in degree).
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] fp FILE pointer to Postscript document.
+ * \param [in] x Center x coordinate of circle.
+ * \param [in] y Center y coordinate of circle.
+ * \param [in] radius Radius of circle.
+ * \param [in] color Circle color.
+ * \param [in] fill_width Circle fill width.
+ * \param [in] angle1 1st angle for mesh pattern.
+ * \param [in] pitch1 1st pitch for mesh pattern.
+ * \param [in] angle2 2nd angle for mesh pattern.
+ * \param [in] pitch2 2nd pitch for mesh pattern.
+ * \param [in] origin_x Page x coordinate to place circle OBJECT.
+ * \param [in] origin_y Page y coordinate to place circle OBJECT.
+ */
+void o_circle_print_mesh(TOPLEVEL *w_current, FILE *fp,
+ int x, int y, int radius,
+ int color,
+ int fill_width,
+ int angle1, int pitch1,
+ int angle2, int pitch2,
+ int origin_x, int origin_y)
+{
+ o_circle_print_hatch(w_current, fp,
+ x, y, radius,
+ color,
+ fill_width,
+ angle1, pitch1,
+ -1, -1,
+ origin_x, origin_y);
+ o_circle_print_hatch(w_current, fp,
+ x, y, radius,
+ color,
+ fill_width,
+ angle2, pitch2,
+ -1, -1,
+ origin_x, origin_y);
+
+}
+
+/*! \brief Print a hatch pattern circle to Postscript document.
+ * \par Function Description
+ * The function prints a hatched circle. No outline is printed.
+ * The circle is defined by the coordinates of its center in
+ * (<B>x</B>,<B>y</B>) and its radius by the <B>radius</B> parameter.
+ * The Postscript document is defined by the file pointer <B>fp</B>.
+ * <B>angle2</B> and <B>pitch2</B> parameters are ignored in this
+ * functions but kept for compatibility with other fill functions.
+ *
+ * The only attribute of line here is its width from the parameter <B>width</B>.
+ *
+ * Negative or null values for <B>pitch1</B> is not allowed as it
+ * leads to an endless loop.
+ *
+ * All dimensions are in mils (except <B>angle1</B> is in degrees).
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] fp FILE pointer to Postscript document.
+ * \param [in] x Center x coordinate of circle.
+ * \param [in] y Center y coordinate of circle.
+ * \param [in] radius Radius of circle.
+ * \param [in] color Circle color.
+ * \param [in] fill_width Circle fill width.
+ * \param [in] angle1 Angle for hatch pattern.
+ * \param [in] pitch1 Pitch for hatch pattern.
+ * \param [in] angle2 (unused).
+ * \param [in] pitch2 (unused).
+ * \param [in] origin_x Page x coordinate to place circle OBJECT.
+ * \param [in] origin_y Page y coordinate to place circle OBJECT.
+ */
+void o_circle_print_hatch(TOPLEVEL *w_current, FILE *fp,
+ int x, int y, int radius,
+ int color,
+ int fill_width,
+ int angle1, int pitch1,
+ int angle2, int pitch2,
+ int origin_x, int origin_y)
+{
+ double x0, y0, x1, y1, x2, y2;
+ double cos_a_, sin_a_;
+
+ if (w_current->print_color) {
+ f_print_set_color(fp, color);
+ }
+
+ /*
+ * The values of the cosinus and sinus of the angle
+ * <B>angle1</B> are calculated for future usage (repetitive).
+ */
+ cos_a_ = cos(((double) angle1) * M_PI/180);
+ sin_a_ = sin(((double) angle1) * M_PI/180);
+
+ /*
+ * When printing a line in a circle there is two intersections.
+ * It looks for the coordinates of one of these points when the
+ * line is horizontal. The second one can be easily obtained by
+ * symmetry in relation to the vertical axis going through the
+ * centre of the circle.
+ *
+ * These two points are therefore rotated of angle <B>angle1</B>
+ * using the elements previously computed.
+ *
+ * The corresponding line can be printed providing that the
+ * coordinates are rounded.
+ *
+ * These operations are repeated for every horizontal line that
+ * can fit in the upper half of the circle (using and incrementing
+ * the variable #y0).
+ */
+ y0 = 0;
+ while(y0 < (double) radius) {
+ x0 = pow((double) radius, 2) - pow(y0, 2);
+ x0 = sqrt(x0);
+
+ x1 = (x0*cos_a_ - y0*sin_a_) + x;
+ y1 = y + (x0*sin_a_ + y0*cos_a_);
+ x2 = ((-x0)*cos_a_ - y0*sin_a_) + x;
+ y2 = y + ((-x0)*sin_a_ + y0*cos_a_);
+
+ fprintf(fp, "%d %d %d %d %d line\n",
+ (int) x1, (int) y1, (int) x2, (int) y2, fill_width);
+
+ /*
+ * The function uses the symetry in relation to the centre of the
+ * circle. It avoid repetitive computation for the second half of
+ * the surface of the circle.
+ */
+ x1 = x + (x0*cos_a_ - (-y0)*sin_a_);
+ y1 = y + (x0*sin_a_ + (-y0)*cos_a_);
+ x2 = x + ((-x0)*cos_a_ - (-y0)*sin_a_);
+ y2 = y + ((-x0)*sin_a_ + (-y0)*cos_a_);
+
+ fprintf(fp, "%d %d %d %d %d line\n",
+ (int) x1, (int) y1, (int) x2, (int) y2, fill_width);
+
+ y0 = y0 + pitch1;
+ }
+}
+
+#if 0 /* original way of printing circle, no longer used */
+/*! \brief Print Circle to Postscript document using old method.
+ * \par Function Description
+ * This function is the old function to print a circle.
+ * It does not handle line type and filling of a circle.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] fp FILE pointer to Postscript document.
+ * \param [in] o_current Circle object to print.
+ * \param [in] origin_x Page x coordinate to place circle OBJECT.
+ * \param [in] origin_y Page x coordinate to place circle OBJECT.
+ */
+void o_circle_print_old(TOPLEVEL *w_current, FILE *fp, OBJECT *o_current,
+ int origin_x, int origin_y)
+{
+ if (o_current == NULL) {
+ printf("got null in o_circle_print\n");
+ return;
+ }
+
+ o_arc_print_solid(w_current, fp,
+ o_current->circle->center_x,
+ o_current->circle->center_y,
+ o_current->circle->radius,
+ 0, FULL_CIRCLE / 64,
+ o_current->color),
+ o_current->line_width, -1, -1,
+ origin_x, origin_y);
+
+}
+#endif
+
+/*! \brief Draw a circle in an image.
+ * \par Function Description
+ * This function draws a circle in an image with the libgdgeda function
+ * #gdImageArc().
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] o_current Circle OBJECT to draw.
+ * \param [in] origin_x (unused).
+ * \param [in] origin_y (unused).
+ * \param [in] color_mode Draw circle in color if TRUE, B/W otherwise.
+ */
+void o_circle_image_write(TOPLEVEL *w_current, OBJECT *o_current,
+ int origin_x, int origin_y, int color_mode)
+{
+ int color;
+
+ if (o_current == NULL) {
+ printf("got null in o_circle_image_write\n");
+ return;
+ }
+
+ if (color_mode == TRUE) {
+ color = o_image_geda2gd_color(o_current->color);
+ } else {
+ color = image_black;
+ }
+
+#ifdef HAS_LIBGDGEDA
+
+ gdImageSetThickness(current_im_ptr, SCREENabs(w_current,
+ o_current->line_width));
+
+ gdImageArc(current_im_ptr,
+ o_current->circle->screen_x,
+ o_current->circle->screen_y,
+ SCREENabs(w_current, o_current->circle->radius)*2,
+ SCREENabs(w_current, o_current->circle->radius)*2,
+ 0, 360,
+ color);
+#endif
+}
1.24 +1582 -1091eda/geda/gaf/libgeda/src/o_complex_basic.c
(In the diff below, changes in quantity of whitespace are not shown.)
Index: o_complex_basic.c
===================================================================
RCS file: o_complex_basic.c
diff -N o_complex_basic.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ o_complex_basic.c 5 Jul 2006 03:13:38 -0000 1.24
@@ -0,0 +1,1794 @@
+/* gEDA - GPL Electronic Design Automation
+ * libgeda - gEDA's library
+ * Copyright (C) 1998-2000 Ales V. Hvezda
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+#include <config.h>
+
+#include <stdio.h>
+#include <math.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <libguile.h>
+
+#include "defines.h"
+#include "struct.h"
+#include "globals.h"
+#include "o_types.h"
+#include "colors.h"
+#include "funcs.h"
+
+#include "../include/prototype.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+/*! \brief
+ * \par Function Description
+ *
+ */
+void get_complex_bounds(TOPLEVEL *w_current, OBJECT *complex,
+ int *left, int *top, int *right, int *bottom)
+{
+ OBJECT *o_current=NULL;
+ int rleft, rtop, rright, rbottom;
+
+ *left = rleft = 999999;
+ *top = rtop = 9999999;
+ *right = rright = 0;
+ *bottom = rbottom = 0;
+
+
+
+ o_current = complex;
+
+ while ( o_current != NULL ) {
+ switch(o_current->type) {
+ case(OBJ_LINE):
+ get_line_bounds(w_current, o_current->line, &rleft, &rtop, &rright, &rbottom);
+ break;
+
+ case(OBJ_NET):
+ /* same as a line (diff name)*/
+ get_net_bounds(w_current, o_current->line, &rleft, &rtop, &rright, &rbottom);
+ break;
+
+ case(OBJ_BUS):
+ /* same as a line (diff name)*/
+ get_bus_bounds(w_current, o_current->line, &rleft, &rtop, &rright, &rbottom);
+ break;
+
+ case(OBJ_BOX):
+ get_box_bounds(w_current, o_current->box, &rleft, &rtop, &rright, &rbottom);
+ break;
+
+ case(OBJ_PICTURE):
+#ifndef HAS_GTK12
+ get_picture_bounds(w_current, o_current->picture, &rleft, &rtop, &rright, &rbottom);
+#endif
+ break;
+
+ case(OBJ_CIRCLE):
+ get_circle_bounds(w_current, o_current->circle, &rleft, &rtop, &rright, &rbottom);
+ break;
+
+ case(OBJ_COMPLEX):
+ case(OBJ_PLACEHOLDER):
+ /* recursive objects ?*/
+ get_complex_bounds(w_current, o_current->complex->prim_objs, &rleft, &rtop, &rright, &rbottom);
+ break;
+
+ case(OBJ_TEXT):
+ /* only do bounding boxes for visible or doing show_hidden_text*/
+ /* you might lose some attrs though */
+ if (o_current->visibility == VISIBLE ||
+ (o_current->visibility == INVISIBLE && w_current->show_hidden_text)) {
+ get_text_bounds(w_current, o_current, &rleft, &rtop, &rright, &rbottom);
+ }
+ break;
+
+ case(OBJ_PIN):
+ get_pin_bounds(w_current, o_current->line, &rleft, &rtop, &rright, &rbottom);
+ break;
+
+ case(OBJ_ARC):
+ get_arc_bounds(w_current, o_current, &rleft, &rtop, &rright, &rbottom);
+ break;
+
+ default:
+ break;
+ }
+
+ if (rleft < *left) *left = rleft;
+ if (rtop < *top) *top = rtop;
+ if (rright > *right) *right = rright;
+ if (rbottom > *bottom) *bottom = rbottom;
+
+
+ o_current=o_current->next;
+ }
+
+}
+
+/*! \brief
+ * \par Function Description
+ *
+ */
+void get_complex_bounds_selection(TOPLEVEL *w_current, SELECTION *head,
+ int *left, int *top, int *right, int *bottom)
+{
+ SELECTION *s_current=NULL;
+ OBJECT *o_current=NULL;
+ int rleft, rtop, rright, rbottom;
+
+ *left = rleft = 999999;
+ *top = rtop = 9999999;
+ *right = rright = 0;
+ *bottom = rbottom = 0;
+
+ s_current = head;
+
+ while ( s_current != NULL ) {
+
+ o_current = s_current->selected_object;
+
+ if (!o_current) {
+ fprintf(stderr, "Got NULL in get_complex_bounds_selection\n");
+ exit(-1);
+ }
+
+ switch(o_current->type) {
+ case(OBJ_LINE):
+ get_line_bounds(w_current, o_current->line, &rleft, &rtop, &rright, &rbottom);
+ break;
+
+ case(OBJ_NET):
+ /* same as a line (diff name)*/
+ get_net_bounds(w_current, o_current->line, &rleft, &rtop, &rright, &rbottom);
+ break;
+
+ case(OBJ_BUS):
+ /* same as a line (diff name)*/
+ get_bus_bounds(w_current, o_current->line, &rleft, &rtop, &rright, &rbottom);
+ break;
+
+ case(OBJ_BOX):
+ get_box_bounds(w_current, o_current->box, &rleft, &rtop, &rright, &rbottom);
+ break;
+
+ case(OBJ_PICTURE):
+#ifndef HAS_GTK12
+ get_picture_bounds(w_current, o_current->picture, &rleft, &rtop, &rright, &rbottom);
+#endif
+ break;
+
+ case(OBJ_CIRCLE):
+ get_circle_bounds(w_current, o_current->circle, &rleft, &rtop, &rright, &rbottom);
+ break;
+
+ case(OBJ_COMPLEX):
+ case(OBJ_PLACEHOLDER):
+ /* recursive objects ?*/
+ get_complex_bounds(w_current, o_current->complex->prim_objs, &rleft, &rtop, &rright, &rbottom);
+ break;
+
+ case(OBJ_TEXT):
+ /* only do bounding boxes for visible or doing show hidden text */
+ /* you might lose some attrs though */
+ if (o_current->visibility == VISIBLE ||
+ (o_current->visibility == INVISIBLE && w_current->show_hidden_text)) {
+ get_text_bounds(w_current, o_current, &rleft, &rtop, &rright, &rbottom);
+ }
+ break;
+
+ case(OBJ_PIN):
+ get_pin_bounds(w_current, o_current->line, &rleft, &rtop, &rright, &rbottom);
+ break;
+
+ case(OBJ_ARC):
+ get_arc_bounds(w_current, o_current, &rleft, &rtop, &rright, &rbottom);
+ break;
+
+ default:
+ break;
+ }
+
+ if (rleft < *left) *left = rleft;
+ if (rtop < *top) *top = rtop;
+ if (rright > *right) *right = rright;
+ if (rbottom > *bottom) *bottom = rbottom;
+
+
+ s_current=s_current->next;
+ }
+
+}
+
+/*! \brief
+ * \par Function Description
+ *
+ */
+void world_get_complex_bounds(TOPLEVEL *w_current, OBJECT *complex,
+ int *left, int *top, int *right, int *bottom)
+{
+ OBJECT *o_current=NULL;
+ int rleft, rtop, rright, rbottom;
+
+ *left = rleft = w_current->init_right;
+ *top = rtop = w_current->init_bottom;;
+ *right = rright = 0;
+ *bottom = rbottom = 0;
+
+ o_current = complex;
+
+ while ( o_current != NULL ) {
+ switch(o_current->type) {
+ case(OBJ_LINE):
+ world_get_line_bounds(w_current, o_current->line, &rleft, &rtop, &rright, &rbottom);
+ break;
+
+ case(OBJ_NET):
+ /* same as a line (diff name)*/
+ world_get_net_bounds(w_current, o_current->line, &rleft, &rtop, &rright, &rbottom);
+ break;
+
+ case(OBJ_BUS):
+ /* same as a line (diff name)*/
+ world_get_bus_bounds(w_current, o_current->line, &rleft, &rtop, &rright, &rbottom);
+ break;
+
+
+ case(OBJ_BOX):
+ world_get_box_bounds(w_current, o_current->box, &rleft, &rtop, &rright, &rbottom);
+ break;
+
+ case(OBJ_PICTURE):
+#ifndef HAS_GTK12
+ world_get_picture_bounds(w_current, o_current->picture, &rleft, &rtop, &rright, &rbottom);
+#endif
+ break;
+
+ case(OBJ_CIRCLE):
+ world_get_circle_bounds(w_current, o_current->circle, &rleft, &rtop, &rright, &rbottom);
+ break;
+
+ case(OBJ_COMPLEX):
+ case(OBJ_PLACEHOLDER):
+ /* recursive objects ?*/
+ world_get_complex_bounds(w_current, o_current->complex->prim_objs, &rleft, &rtop, &rright, &rbottom);
+ break;
+
+ case(OBJ_TEXT):
+ /* only do bounding boxes for visible or doing show hidden text */
+ /* you might lose some attrs though */
+ if (o_current->visibility == VISIBLE ||
+ (o_current->visibility == INVISIBLE && w_current->show_hidden_text)) {
+ world_get_text_bounds(w_current, o_current, &rleft, &rtop, &rright, &rbottom);
+ }
+ break;
+
+ case(OBJ_PIN):
+ world_get_pin_bounds(w_current, o_current->line, &rleft, &rtop, &rright, &rbottom);
+ break;
+
+ case(OBJ_ARC):
+ world_get_arc_bounds(w_current, o_current, &rleft, &rtop, &rright, &rbottom);
+ break;
+
+ default:
+ break;
+ }
+
+ if (rleft < *left) *left = rleft;
+ if (rtop < *top) *top = rtop;
+ if (rright > *right) *right = rright;
+ if (rbottom > *bottom) *bottom = rbottom;
+
+
+ o_current=o_current->next;
+ }
+
+}
+
+/*! \brief
+ * \par Function Description
+ *
+ */
+OBJECT *add_head(void)
+{
+ OBJECT *new_node=NULL;
+
+ new_node = s_basic_init_object("complex_head");
+
+ new_node->type = OBJ_HEAD; /* make this of head type hack */
+
+ /* don't need to do this for head nodes */
+ /* ret = (OBJECT *) s_basic_link_object(new_node, NULL);*/
+ return(new_node);
+}
+
+/*! \brief
+ * \par Function Description
+ *
+ */
+/* The promote_invisible flag is either TRUE or FALSE */
+/* It controls if invisible text is promoted (TRUE) or not (FALSE) */
+int o_complex_is_eligible_attribute (TOPLEVEL *w_current, OBJECT *object,
+ int promote_invisible)
+{
+ char *name = NULL;
+ char *value = NULL;
+ char *padded_name = NULL;
+ int promotableAttribute = FALSE;
+ char *ptr;
+
+ if (object->type != OBJ_TEXT || object->attribute || object->attached_to)
+ {
+ return FALSE; /* not a text item or is already attached */
+ }
+
+ /* Make sure text item is an attribute */
+ ptr = strchr(object->text->string, '=');
+ if (!ptr || ptr[1] == '\0' || ptr[1] == ' ')
+ {
+ return FALSE; /* not an attribute */
+ }
+
+ /* always promote symversion= attribute, even if it is invisible */
+ if (strncmp(object->text->string, "symversion=", 11) == 0)
+ {
+ return TRUE;
+ }
+
+ /* check list against attributes which can be promoted */
+ if (w_current->always_promote_attributes &&
+ (strlen(w_current->always_promote_attributes) != 0))
+ {
+ if (o_attrib_get_name_value(object->text->string, &name, &value))
+ {
+ padded_name = g_strdup_printf(" %s ", name);
+ if (strstr(w_current->always_promote_attributes, padded_name))
+ {
+ /* Yes the name of the attribute was in the always promote */
+ /* attributes list */
+ promotableAttribute = TRUE;
+ }
+
+ g_free(padded_name);
+ if (name) g_free(name);
+ if (value) g_free(value);
+ if (promotableAttribute)
+ return TRUE;
+ }
+ }
+
+ /* object is invisible and we do not want to promote invisible text */
+ if (object->visibility == INVISIBLE && promote_invisible == FALSE)
+ {
+ return FALSE; /* attribute not eligible for promotion */
+ }
+
+ /* yup, attribute can be promoted */
+ return TRUE;
+}
+
+/*! \brief
+ * \par Function Description
+ *
+ */
+int o_complex_is_embedded(OBJECT *o_current)
+{
+ if(o_current->complex == NULL)
+ return 0;
+
+ if (o_current->complex_clib &&
+ strncmp(o_current->complex_clib, "EMBEDDED", 8) == 0) {
+ return 1;
+ } else {
+ return 0;
+ }
+
+}
+
+/* Done */
+/*! \brief
+ * \par Function Description
+ *
+ */
+OBJECT *o_complex_add(TOPLEVEL *w_current, OBJECT *object_list, char type,
+ int color, int x, int y, int angle,
+ int mirror, char *clib,
+ char *basename, int selectable,
+ int attribute_promotion)
+{
+ OBJECT *new_node=NULL;
+ OBJECT *prim_objs=NULL;
+ OBJECT *temp_tail=NULL;
+ OBJECT *temp_parent=NULL;
+ int save_adding_sel = 0;
+ int loaded_normally = FALSE;
+
+ char *filename;
+
+ new_node = s_basic_init_object("complex");
+ new_node->type = type;
+
+ new_node->complex_basename = strdup(basename);
+ if (clib)
+ new_node->complex_clib = strdup(clib);
+ else
+ new_node->complex_clib = NULL;
+
+ new_node->color = color;
+
+ new_node->complex = (COMPLEX *) malloc(sizeof(COMPLEX));
+
+ new_node->complex->angle = angle;
+ new_node->complex->mirror = mirror;
+
+ new_node->complex->x = x;
+ new_node->complex->y = y;
+ WORLDtoSCREEN(w_current, x, y,
+ &new_node->complex->screen_x,
+ &new_node->complex->screen_y);
+
+ /*! \todo questionable caste? */
+ new_node->draw_func = (void *) complex_draw_func;
+
+ if (selectable) {
+ new_node->sel_func = (void *) select_func;
+ } else {
+ new_node->sel_func = NULL;
+ }
+
+ /* this was at the beginning and p_complex was = to complex */
+ prim_objs = (OBJECT *) add_head();
+
+ /* set the parent field now */
+ prim_objs->complex_parent = new_node;
+
+ /* is the bit with the temp and object_tail needed? */
+ /* I don't like this at all hack */
+ /* careful whenever you select, you get a read from disk */
+ /* for the objects, UGG! there foreattribs are being copied */
+ /* you need to override them if there are attached ones */
+ /* on the main list */
+ temp_tail = w_current->page_current->object_tail;
+ temp_parent = w_current->page_current->object_parent;
+ w_current->page_current->object_parent = prim_objs;
+ /* reason this works is because it has a head, see add_head above */
+
+ /* check for validity */
+ if (clib && basename)
+ filename = g_strdup_printf("%s%c%s", clib, G_DIR_SEPARATOR, basename);
+ else
+ filename = g_strdup("unknown");
+
+ save_adding_sel = w_current->ADDING_SEL;
+ w_current->ADDING_SEL = 1; /* name is hack, don't want to */
+
+ if (access(filename, R_OK)) {
+
+ OBJECT *save_prim_objs;
+ char *not_found_text = NULL;
+ int left, right, top, bottom;
+ int x_offset, y_offset;
+
+ if (clib == NULL) {
+ s_log_message("Component library was not found or specified\n");
+ } else if (basename == NULL) {
+ s_log_message("Basename (component) was not found or specified\n");
+ } else {
+ s_log_message("Could not open symbol file [%s]\n", filename);
+ }
+
+ /* filename was NOT found */
+ loaded_normally = FALSE;
+
+ /* save the prim_objs pointer, since the following code modifies it */
+ save_prim_objs = prim_objs;
+
+ /* Put placeholder into object list. Changed by SDB on
+ * 1.19.2005 to fix problem that symbols were silently
+ * deleted by gattrib when RC files were messed up. */
+ new_node->type = OBJ_PLACEHOLDER;
+
+ /* Mark the origin of the missing component */
+ prim_objs = o_line_add(w_current, prim_objs, OBJ_LINE,
+ DETACHED_ATTRIBUTE_COLOR,
+ x - 50, y, x + 50, y);
+ prim_objs = o_line_add(w_current, prim_objs, OBJ_LINE,
+ DETACHED_ATTRIBUTE_COLOR,
+ x, y + 50, x, y - 50);
+
+ /* Add some useful text */
+ not_found_text =
+ g_strdup_printf ("Component not found:\n %s", basename);
+ prim_objs = o_text_add(w_current, prim_objs,
+ OBJ_TEXT, DETACHED_ATTRIBUTE_COLOR,
+ x + NOT_FOUND_TEXT_X,
+ y + NOT_FOUND_TEXT_Y, LOWER_LEFT, 0,
+ not_found_text, 8,
+ VISIBLE, SHOW_NAME_VALUE);
+ free(not_found_text);
+
+ /* figure out where to put the hazard triangle */
+ world_get_text_bounds(w_current, prim_objs,
+ &left, &top, &right, &bottom);
+ x_offset = (right - left) / 4;
+ y_offset = bottom - top + 100; /* 100 is just an additional offset */
+
+ /* add hazard triangle */
+ prim_objs = o_line_add(w_current, prim_objs, OBJ_LINE,
+ DETACHED_ATTRIBUTE_COLOR,
+ x + NOT_FOUND_TEXT_X + x_offset,
+ y + NOT_FOUND_TEXT_Y + y_offset,
+ x + NOT_FOUND_TEXT_X + x_offset + 600,
+ y + NOT_FOUND_TEXT_Y + y_offset);
+ o_set_line_options(w_current, prim_objs, END_ROUND, TYPE_SOLID,
+ 50, -1, -1);
+ prim_objs = o_line_add(w_current, prim_objs, OBJ_LINE,
+ DETACHED_ATTRIBUTE_COLOR,
+ x + NOT_FOUND_TEXT_X + x_offset,
+ y + NOT_FOUND_TEXT_Y + y_offset,
+ x + NOT_FOUND_TEXT_X + x_offset + 300,
+ y + NOT_FOUND_TEXT_Y + y_offset + 500);
+ o_set_line_options(w_current, prim_objs, END_ROUND, TYPE_SOLID,
+ 50, -1, -1);
+ prim_objs = o_line_add(w_current, prim_objs, OBJ_LINE,
+ DETACHED_ATTRIBUTE_COLOR,
+ x + NOT_FOUND_TEXT_X + x_offset + 300,
+ y + NOT_FOUND_TEXT_Y + y_offset + 500,
+ x + NOT_FOUND_TEXT_X + x_offset + 600,
+ y + NOT_FOUND_TEXT_Y + y_offset);
+ o_set_line_options(w_current, prim_objs, END_ROUND, TYPE_SOLID,
+ 50, -1, -1);
+ prim_objs = o_text_add(w_current, prim_objs,
+ OBJ_TEXT, DETACHED_ATTRIBUTE_COLOR,
+ x + NOT_FOUND_TEXT_X + x_offset + 270,
+ y + NOT_FOUND_TEXT_Y + y_offset + 90,
+ LOWER_LEFT, 0, "!", 18,
+ VISIBLE, SHOW_NAME_VALUE);
+ prim_objs = save_prim_objs;
+
+ } else {
+
+ /* filename was found */
+ loaded_normally = TRUE;
+
+ /* add connections till translated */
+ o_read(w_current, prim_objs, filename);
+
+ }
+ w_current->ADDING_SEL = save_adding_sel;
+
+ if (w_current->attribute_promotion) { /* controlled through rc file */
+
+ OBJECT *tmp,*next;
+
+ for (tmp=prim_objs->next;tmp;tmp=next) {
+
+ next=tmp->next;
+
+ /* valid floating attrib? */
+ if (o_complex_is_eligible_attribute(w_current, tmp,
+ w_current->promote_invisible))
+ {
+ /* Is attribute promotion called for? (passed in parameter) */
+ if (attribute_promotion)
+ {
+ /* remove tmp from the complex list */
+ if (tmp->next)
+ tmp->next->prev=tmp->prev;
+ if (tmp->prev)
+ tmp->prev->next=tmp->next;
+
+ /* Isolate tmp completely, now that it's removed from list */
+ tmp->next=tmp->prev=NULL;
+
+ object_list = (OBJECT *) s_basic_link_object(tmp, object_list);
+ o_attrib_attach (w_current, object_list, tmp, new_node);
+ o_text_translate_world(w_current, x, y, tmp);
+
+ } else { /* not promoting now, but deal with floating attribs */
+
+ if (w_current->keep_invisible == TRUE) {
+ /* if we are not promoting invisible attribs, keep them */
+ /* around */
+ tmp->visibility = INVISIBLE;
+ } else {
+ /* else do the default behavior of deleting the original */
+ /* object */
+ s_delete(w_current, tmp);
+ }
+
+ }
+ }
+ }
+ }
+
+ w_current->page_current->object_tail = temp_tail;
+ w_current->page_current->object_parent = temp_parent;
+
+ object_list = (OBJECT *) s_basic_link_object(new_node, object_list);
+ object_list->complex->prim_objs = prim_objs;
+
+
+ /* do not mirror/rotate/translate/connect the primitive objects if the
+ * component was not loaded via o_read
+ */
+ if (loaded_normally == TRUE) {
+ if (mirror) {
+ o_complex_mirror_lowlevel(w_current, x, y, object_list);
+ }
+
+ o_complex_rotate_lowlevel(w_current, x, y, angle, angle, object_list);
+ o_complex_world_translate(w_current, x, y, prim_objs);
+
+ if (!w_current->ADDING_SEL) {
+ s_conn_update_complex(w_current, prim_objs);
+ }
+ }
+
+ free(filename);
+ return(object_list);
+}
+
+/*! \brief
+ * \par Function Description
+ *
+ */
+OBJECT *o_complex_add_embedded(TOPLEVEL *w_current, OBJECT *object_list,
+ char type, int color, int x, int y, int angle,
+ char *clib, char *basename, int selectable)
+{
+ OBJECT *prim_objs=NULL;
+ OBJECT *new_node=NULL;
+
+ new_node = s_basic_init_object("complex");
+ new_node->type = type;
+
+ new_node->complex = (COMPLEX *) malloc(sizeof(COMPLEX));
+ new_node->complex->x = x;
+ new_node->complex->y = y;
+ WORLDtoSCREEN(w_current, x, y,
+ &new_node->complex->screen_x,
+ &new_node->complex->screen_y);
+
+ new_node->complex->angle = angle;
+ new_node->complex->mirror = 0;
+
+ new_node->complex_basename = strdup(basename);
+ if (clib)
+ new_node->complex_clib = strdup(clib);
+ else
+ new_node->complex_clib = NULL;
+
+ new_node->color = color;
+
+ /*! \todo questionable cast */
+ new_node->draw_func = (void *) complex_draw_func;
+
+ /* (for a title block) an object that isn't selectable */
+ if (selectable) {
+ new_node->sel_func = (void *) select_func;
+ } else {
+ new_node->sel_func = NULL;
+ }
+
+ object_list = (OBJECT *) s_basic_link_object(new_node, object_list);
+
+ /* this was at the beginning and p_complex was = to complex */
+ prim_objs = (OBJECT *) add_head();
+ object_list->complex->prim_objs = prim_objs;
+
+ /* set the parent field now */
+ prim_objs->complex_parent = object_list;
+
+ /* don't have to translate/rotate/mirror here at all since the */
+ /* object is in place */
+ return(object_list);
+}
+
+/*! \brief
+ * \par Function Description
+ *
+ */
+void o_complex_recalc(TOPLEVEL *w_current, OBJECT *o_current)
+{
+ int left, right, top, bottom;
+
+ /* realc routine Add this somewhere */
+ /* libhack */
+ /* o_recalc(w_current, o_current->complex);*/
+
+ get_complex_bounds(w_current, o_current->complex->prim_objs, &left, &top, &right, &bottom);
+ o_current->left = left;
+ o_current->top = top;
+ o_current->right = right;
+ o_current->bottom = bottom;
+
+ WORLDtoSCREEN(w_current,
+ o_current->complex->x,
+ o_current->complex->y,
+ &o_current->complex->screen_x,
+ &o_current->complex->screen_y);
+}
+
+/*! \brief
+ * \par Function Description
+ *
+ */
+OBJECT *o_complex_read(TOPLEVEL *w_current, OBJECT *object_list,
+ char buf[], unsigned int release_ver,
+ unsigned int fileformat_ver)
+{
+ char type;
+ int x1, y1;
+ int angle;
+
+ char basename[256]; /* hack */
+ char *clib=NULL;
+
+ int selectable;
+ int mirror;
+
+ sscanf(buf, "%c %d %d %d %d %d %s\n",
+ &type, &x1, &y1, &selectable, &angle, &mirror, basename);
+
+ switch(angle) {
+
+ case(0):
+ case(90):
+ case(180):
+ case(270):
+ break;
+
+ default:
+ fprintf(stderr, "Found a component with an invalid rotation [ %c %d %d %d %d %d %s ]\n", type, x1, y1, selectable, angle, mirror, basename);
+ s_log_message("Found a component with an invalid rotation [ %c %d %d %d %d %d %s ]\n", type, x1, y1, selectable, angle, mirror, basename);
+ break;
+ }
+
+ switch(mirror) {
+
+ case(0):
+ case(1):
+
+ break;
+
+ default:
+ fprintf(stderr, "Found a component with an invalid mirror flag [ %c %d %d %d %d %d %s ]\n", type, x1, y1, selectable, angle, mirror, basename);
+ s_log_message("Found a component with an invalid mirror flag [ %c %d %d %d %d %d %s ]\n", type, x1, y1, selectable, angle, mirror, basename);
+ break;
+ }
+ if (strncmp(basename, "EMBEDDED", 8) == 0) {
+
+ object_list = o_complex_add_embedded(w_current,
+ object_list, type,
+ WHITE, x1, y1, angle,
+ "EMBEDDED", basename,
+ selectable);
+ } else {
+ const GSList *clibs = s_clib_search_basename (basename);
+ if (clibs == NULL) {
+ s_log_message("Component [%s] was not found in any component library\n",
+ basename);
+ fprintf(stderr,
+ "Component [%s] was not found in any component library\n",
+ basename);
+ clib = NULL;
+ } else {
+ if (g_slist_next (clibs)) {
+ s_log_message ("More than one component found with name [%s]\n",
+ basename);
+ /* PB: for now, use the first directory in clibs */
+ /* PB: maybe open a dialog to select the right one? */
+ }
+ clib = (gchar*)clibs->data;
+ }
+
+ object_list = o_complex_add(w_current, object_list, type,
+ WHITE,
+ x1, y1,
+ angle, mirror,
+ clib, basename, selectable, FALSE);
+ }
+
+ return object_list;
+}
+
+/*! \brief
+ * \par Function Description
+ *
+ */
+char *o_complex_save(OBJECT *object)
+{
+ int selectable;
+ char *buf = NULL;
+
+ if (object->sel_func != NULL)
+ selectable = 1;
+ else
+ selectable = 0;
+
+ if (object->type == OBJ_COMPLEX) {
+ buf = g_strdup_printf("%c %d %d %d %d %d %s", object->type,
+ object->complex->x, object->complex->y, selectable,
+ object->complex->angle, object->complex->mirror,
+ object->complex_basename);
+ } else if (object->type == OBJ_PLACEHOLDER) {
+ buf = g_strdup_printf("C %d %d %d %d %d %s",
+ object->complex->x, object->complex->y, selectable,
+ object->complex->angle, object->complex->mirror,
+ object->complex_basename); /* write 'C' manually */
+ }
+
+ return(buf);
+}
+
+/*! \brief
+ * \par Function Description
+ *
+ */
+void o_complex_set_filename(TOPLEVEL *w_current, char *clib, char *basename)
+{
+ int len;
+
+ if (basename == NULL) {
+ fprintf(stderr, "Got NULL basename in o_complex_set_filename!\n");
+ exit(-1);
+ }
+
+ if (clib == NULL) {
+ fprintf(stderr, "Got NULL clib in o_complex_set_filename!\n");
+ exit(-1);
+ }
+
+ if (w_current->internal_basename) {
+ free(w_current->internal_basename);
+ }
+
+ if (w_current->internal_clib) {
+ free(w_current->internal_clib);
+ }
+
+ len = strlen(basename);
+ w_current->internal_basename = (char *) malloc(sizeof(char)*len+1);
+
+ len = strlen(clib) + 1;
+ w_current->internal_clib = (char *) malloc(sizeof(char)*len+1);
+
+ strcpy(w_current->internal_basename, basename);
+ strcpy(w_current->internal_clib, clib);
+}
+
+/*! \brief
+ * \par Function Description
+ *
+ */
+void o_complex_free_filename(TOPLEVEL *w_current)
+{
+ if (w_current->internal_basename) {
+ free(w_current->internal_basename);
+ }
+
+ if (w_current->internal_clib) {
+ free(w_current->internal_clib);
+ }
+}
+
+/*! \brief
+ * \par Function Description
+ *
+ */
+/* now I think it works fine */
+/* no there is a bug with snap locking. Basically if you don't snap/lock in */
+/* PCtoW, then this doesn't work... :( I don't know why yet */
+void o_complex_translate(TOPLEVEL *w_current, int dx, int dy, OBJECT *object)
+{
+ int x, y;
+ int prevx, prevy;
+
+ if (object == NULL) {
+ printf("cmpt NO!\n");
+ return;
+ }
+
+ object->complex->screen_x = object->complex->screen_x + dx;
+ object->complex->screen_y = object->complex->screen_y + dy;
+
+
+ /* this fixing makes me nervious hack */
+ SCREENtoWORLD(w_current, object->complex->screen_x,
+ object->complex->screen_y, &x, &y);
+
+ prevx = object->complex->x;
+ prevy = object->complex->y;
+ object->complex->x = snap_grid(w_current, x);
+ object->complex->y = snap_grid(w_current, y);
+
+ o_complex_world_translate(w_current, x - prevx,y - prevy,
+ object->complex->prim_objs);
+}
+
+/*! \brief
+ * \par Function Description
+ *
+ */
+/* this needs work remove display stuff */
+/* libhack */
+/* and recalc stuff */
+/* this function takes in a complex list */
+void o_complex_world_translate(TOPLEVEL *w_current, int x1, int y1,
+ OBJECT *prim_objs)
+{
+ OBJECT *o_current=NULL;
+ OBJECT *one=NULL;
+ OBJECT *two=NULL;
+ unsigned long temp_color;
+
+ o_current = prim_objs;
+
+ while ( o_current != NULL ) {
+ switch(o_current->type) {
+ case(OBJ_LINE):
+ o_line_translate_world(w_current, x1, y1, o_current);
+ break;
+
+ case(OBJ_NET):
+ /* same as a line, don't do this */
+ o_line_translate_world(w_current, x1, y1, o_current);
+ temp_color = w_current->override_color;
+ w_current->override_color = -1;
+ o_redraw_single(w_current, one); /* trying loop? hack*/
+ o_redraw_single(w_current, two);
+ w_current->override_color = temp_color;
+ break;
+
+ case(OBJ_BUS):
+ /* same as a line, don't do this */
+ o_line_translate_world(w_current, x1, y1, o_current);
+ temp_color = w_current->override_color;
+ w_current->override_color = -1;
+ o_redraw_single(w_current, one); /* trying loop? hack*/
+ o_redraw_single(w_current, two);
+ w_current->override_color = temp_color;
+ break;
+
+ case(OBJ_BOX):
+ o_box_translate_world(w_current, x1, y1, o_current);
+ break;
+
+ case(OBJ_PICTURE):
+ o_picture_translate_world(w_current, x1, y1, o_current);
+ break;
+
+ case(OBJ_CIRCLE):
+ o_circle_translate_world(w_current, x1, y1, o_current);
+ break;
+
+ case(OBJ_COMPLEX):
+ case(OBJ_PLACEHOLDER):
+ o_complex_world_translate_toplevel(w_current, x1, y1, o_current);
+ break;
+
+ case(OBJ_TEXT):
+ o_text_translate_world(w_current, x1, y1, o_current);
+ break;
+
+ /* same note as above */
+ case(OBJ_PIN):
+ o_pin_translate_world(w_current, x1, y1, o_current);
+ break;
+
+ case(OBJ_ARC):
+ o_arc_translate_world(w_current, x1, y1, o_current);
+ break;
+ }
+ o_current=o_current->next;
+ }
+}
+
+/*! \brief
+ * \par Function Description
+ *
+ */
+/* this function takes the toplevel object and then also translates the
+ * complex */
+void o_complex_world_translate_toplevel(TOPLEVEL *w_current,
+ int x1, int y1, OBJECT *object)
+{
+ int left, right, top, bottom;
+
+ object->complex->x = object->complex->x + x1;
+ object->complex->y = object->complex->y + y1;
+
+ WORLDtoSCREEN(w_current, object->complex->x,
+ object->complex->y,
+ &object->complex->screen_x,
+ &object->complex->screen_y);
+
+ o_complex_world_translate(w_current, x1, y1,
+ object->complex->prim_objs);
+
+ get_complex_bounds(w_current, object->complex->prim_objs,
+ &left, &top, &right, &bottom);
+
+ object->left = left;
+ object->top = top;
+ object->right = right;
+ object->bottom = bottom;
+}
+
+/*! \brief
+ * \par Function Description
+ *
+ */
+OBJECT *o_complex_copy(TOPLEVEL *w_current, OBJECT *list_tail,
+ OBJECT *o_current)
+{
+ OBJECT *new_obj=NULL;
+ ATTRIB *a_current;
+ int color;
+ int selectable;
+
+ if (o_current->saved_color == -1) {
+ color = o_current->color;
+ } else {
+ color = o_current->saved_color;
+ }
+
+ if (o_current->sel_func) {
+ selectable = TRUE;
+ } else {
+ selectable = FALSE;
+ }
+
+ new_obj = o_complex_add(w_current, list_tail, o_current->type, color,
+ o_current->complex->x, o_current->complex->y,
+ o_current->complex->angle, o_current->complex->mirror,
+ o_current->complex_clib, o_current->complex_basename,
+ selectable, FALSE);
+
+ o_attrib_slot_copy(w_current, o_current, new_obj);
+
+ /* deal with stuff that has changed */
+
+ /* here you need to create a list of attributes which need to be
+ * connected to the new list, probably make an attribute list and
+ * fill it with sid's of the attributes */
+ a_current = o_current->attribs;
+ if (a_current) {
+ while ( a_current ) {
+
+ /* head attrib node has prev = NULL */
+ if (a_current->prev != NULL) {
+ a_current->copied_to = new_obj;
+ }
+
+ a_current = a_current->next;
+ }
+ }
+
+ return(new_obj);
+}
+
+/*! \brief
+ * \par Function Description
+ *
+ */
+OBJECT *o_complex_copy_embedded(TOPLEVEL *w_current, OBJECT *list_tail,
+ OBJECT *o_current)
+{
+ OBJECT *new_obj=NULL;
+ OBJECT *temp_list;
+ ATTRIB *a_current;
+ int color;
+ int selectable;
+
+ if (o_current->saved_color == -1) {
+ color = o_current->color;
+ } else {
+ color = o_current->saved_color;
+ }
+
+ if (o_current->sel_func) {
+ selectable = TRUE;
+ } else {
+ selectable = FALSE;
+ }
+
+ new_obj = o_complex_add_embedded(w_current, list_tail, o_current->type,
+ color,
+ o_current->complex->x, o_current->complex->y,
+ o_current->complex->angle,
+ o_current->complex_clib,
+ o_current->complex_basename,
+ selectable);
+ /* deal with stuff that has changed */
+
+ temp_list = o_list_copy_all(w_current,
+ o_current->complex->prim_objs->next,
+ new_obj->complex->prim_objs,
+ NORMAL_FLAG);
+
+ new_obj->complex->prim_objs = return_head(temp_list);
+
+ /* here you need to create a list of attributes which need to be
+ * connected to the new list, probably make an attribute list and
+ * fill it with sid's of the attributes */
+ a_current = o_current->attribs;
+ if (a_current) {
+ while ( a_current ) {
+
+ /* head attrib node has prev = NULL */
+ if (a_current->prev != NULL) {
+ a_current->copied_to = new_obj;
+ }
+
+ a_current = a_current->next;
+ }
+ }
+
+ return(new_obj);
+}
+
+/*! \brief
+ * \par Function Description
+ *
+ */
+void o_complex_delete(TOPLEVEL *w_current, OBJECT *delete)
+{
+ /* first remove complex pointer */
+ if (delete->complex) {
+ if (delete->complex->prim_objs) {
+ s_delete_list_fromstart(w_current,
+ delete->complex->prim_objs);
+ }
+ delete->complex->prim_objs = NULL;
+ }
+
+ /* then remove the actual node */
+ s_delete(w_current, delete);
+ delete = NULL;
+ w_current->page_current->object_tail = (OBJECT *)
+ return_tail(w_current->page_current->object_head);
+}
+
+/*! \brief
+ * \par Function Description
+ *
+ */
+void o_complex_set_color(OBJECT *prim_objs, int color)
+{
+ OBJECT *o_current=NULL;
+
+ o_current = prim_objs;
+
+ while ( o_current != NULL ) {
+ switch(o_current->type) {
+ case(OBJ_LINE):
+ case(OBJ_NET):
+ case(OBJ_BUS):
+ case(OBJ_BOX):
+ case(OBJ_PICTURE):
+ case(OBJ_CIRCLE):
+ case(OBJ_PIN):
+ case(OBJ_ARC):
+ o_current->color = color;
+ break;
+
+ case(OBJ_TEXT):
+ o_current->color = color;
+ o_complex_set_color(o_current->text->prim_objs, color);
+ break;
+
+ case(OBJ_COMPLEX):
+ case(OBJ_PLACEHOLDER):
+ o_current->color = color;
+ o_complex_set_color(o_current->complex->prim_objs, color);
+ break;
+
+ }
+ o_current=o_current->next;
+ }
+}
+
+/*! \brief
+ * \par Function Description
+ *
+ */
+void o_complex_set_color_single(OBJECT *o_current, int color)
+{
+ switch(o_current->type) {
+ case(OBJ_LINE):
+ case(OBJ_NET):
+ case(OBJ_BUS):
+ case(OBJ_BOX):
+ case(OBJ_PICTURE):
+ case(OBJ_CIRCLE):
+ case(OBJ_PIN):
+ case(OBJ_ARC):
+ o_current->color = color;
+ break;
+
+ case(OBJ_TEXT):
+ o_current->color = color;
+ o_complex_set_color(o_current->text->prim_objs, color);
+ break;
+
+ case(OBJ_COMPLEX):
+ case(OBJ_PLACEHOLDER):
+ o_current->color = color;
+ o_complex_set_color(o_current->complex->prim_objs,
+ color);
+ break;
+
+ }
+}
+
+/*! \brief
+ * \par Function Description
+ *
+ */
+void o_complex_set_color_save(OBJECT *complex, int color)
+{
+ OBJECT *o_current=NULL;
+
+ o_current = complex;
+
+ while ( o_current != NULL ) {
+ switch(o_current->type) {
+ case(OBJ_LINE):
+ case(OBJ_NET):
+ case(OBJ_BUS):
+ case(OBJ_BOX):
+ case(OBJ_PICTURE):
+ case(OBJ_CIRCLE):
+ case(OBJ_PIN):
+ case(OBJ_ARC):
+ o_current->saved_color = o_current->color;
+ o_current->color = color;
+ break;
+
+ case(OBJ_TEXT):
+ o_current->saved_color = o_current->color;
+ o_current->color = color;
+ o_complex_set_color_save(
+ o_current->text->prim_objs,
+ color);
+ break;
+
+ case(OBJ_COMPLEX):
+ case(OBJ_PLACEHOLDER):
+ o_current->saved_color = o_current->color;
+ o_current->color = color;
+ o_complex_set_color_save(o_current->complex->
+ prim_objs,
+ color);
+ break;
+
+ }
+ o_current=o_current->next;
+ }
+}
+
+/*! \brief
+ * \par Function Description
+ *
+ */
+void o_complex_unset_color(OBJECT *complex)
+{
+ OBJECT *o_current=NULL;
+
+ o_current = complex;
+
+ while ( o_current != NULL ) {
+ switch(o_current->type) {
+ case(OBJ_LINE):
+ case(OBJ_NET):
+ case(OBJ_BUS):
+ case(OBJ_BOX):
+ case(OBJ_PICTURE):
+ case(OBJ_CIRCLE):
+ case(OBJ_PIN):
+ case(OBJ_ARC):
+ o_current->color = o_current->saved_color;
+ o_current->saved_color = -1;
+ break;
+
+ case(OBJ_TEXT):
+ o_current->color = o_current->saved_color;
+ o_current->saved_color = -1;
+ o_complex_unset_color(o_current->text->prim_objs);
+ break;
+
+ case(OBJ_COMPLEX):
+ case(OBJ_PLACEHOLDER):
+ o_current->color = o_current->saved_color;
+ o_current->saved_color = -1;
+ o_complex_unset_color(o_current->complex->
+ prim_objs);
+
+ break;
+
+ }
+ o_current=o_current->next;
+ }
+}
+
+/*! \brief
+ * \par Function Description
+ *
+ */
+void o_complex_unset_color_single(OBJECT *o_current)
+{
+ switch(o_current->type) {
+ case(OBJ_LINE):
+ case(OBJ_NET):
+ case(OBJ_BUS):
+ case(OBJ_BOX):
+ case(OBJ_PICTURE):
+ case(OBJ_CIRCLE):
+ case(OBJ_PIN):
+ case(OBJ_ARC):
+ o_current->color = o_current->saved_color;
+ o_current->saved_color = -1;
+ break;
+
+ case(OBJ_TEXT):
+ o_current->color = o_current->saved_color;
+ o_current->saved_color = -1;
+ o_complex_unset_color(o_current->text->prim_objs);
+ break;
+
+ case(OBJ_COMPLEX):
+ case(OBJ_PLACEHOLDER):
+ o_current->color = o_current->saved_color;
+ o_current->saved_color = -1;
+ o_complex_unset_color(o_current->complex->prim_objs);
+
+ break;
+ }
+}
+
+/*! \brief
+ * \par Function Description
+ *
+ */
+void o_complex_set_saved_color_only(OBJECT *complex, int color)
+{
+ OBJECT *o_current=NULL;
+
+ o_current = complex;
+
+ while ( o_current != NULL ) {
+ switch(o_current->type) {
+ case(OBJ_LINE):
+ case(OBJ_NET):
+ case(OBJ_BUS):
+ case(OBJ_BOX):
+ case(OBJ_PICTURE):
+ case(OBJ_CIRCLE):
+ case(OBJ_PIN):
+ case(OBJ_ARC):
+ o_current->saved_color = color;
+ break;
+
+ case(OBJ_TEXT):
+ o_current->saved_color = color;
+ o_complex_set_saved_color_only(o_current->text->prim_objs, color);
+ break;
+
+ case(OBJ_COMPLEX):
+ case(OBJ_PLACEHOLDER):
+ o_current->saved_color = color;
+ o_complex_set_saved_color_only(o_current->complex->prim_objs, color);
+ break;
+
+ }
+ o_current=o_current->next;
+ }
+}
+
+/*! \brief
+ * \par Function Description
+ *
+ */
+/* returns the counter'th pin in o_list */
+/* NULL if there is no more pins */
+OBJECT *o_complex_return_nth_pin(OBJECT *o_list, int counter)
+{
+ OBJECT *o_current;
+ int internal_counter=0;
+
+ o_current = o_list;
+
+ while (o_current != NULL) {
+ if (o_current->type == OBJ_PIN) {
+
+ if (counter == internal_counter) {
+ return(o_current);
+ } else {
+ internal_counter++;
+ }
+ }
+ o_current = o_current->next;
+ }
+
+ return(NULL);
+}
+
+/*! \brief
+ * \par Function Description
+ *
+ */
+/* pass in top level object */
+void o_complex_rotate_lowlevel(TOPLEVEL *w_current, int world_centerx,
+ int world_centery,
+ int angle,
+ int angle_change,
+ OBJECT *object)
+{
+ OBJECT *o_current=NULL;
+
+#if DEBUG
+ printf("------- a %d ac %d\n", angle, angle_change);
+#endif
+
+ /* do individual complex objects */
+ o_current = object->complex->prim_objs;
+
+ while ( o_current != NULL ) {
+ switch(o_current->type) {
+ case(OBJ_LINE):
+ o_line_rotate_world(w_current, 0, 0, angle_change, o_current);
+ break;
+
+ case(OBJ_NET):
+ o_net_rotate_world(w_current, 0, 0, angle_change, o_current);
+ break;
+
+ case(OBJ_BUS):
+ o_bus_rotate_world(w_current, 0, 0, angle_change, o_current);
+ break;
+
+ case(OBJ_BOX):
+ o_box_rotate_world(w_current, 0, 0, angle_change, o_current);
+ break;
+
+ case(OBJ_PICTURE):
+#ifndef HAS_GTK12
+ o_picture_rotate_world(w_current, 0, 0, angle_change, o_current);
+#endif
+ break;
+
+ case(OBJ_CIRCLE):
+ o_circle_rotate_world(w_current, 0, 0, angle_change, o_current);
+ break;
+
+ case(OBJ_PIN):
+ o_pin_rotate_world(w_current, 0, 0, angle_change, o_current);
+ break;
+
+ case(OBJ_ARC):
+ o_arc_rotate_world(w_current, 0, 0, angle_change, o_current);
+ break;
+
+ case(OBJ_COMPLEX):
+ case(OBJ_PLACEHOLDER):
+ o_complex_rotate_lowlevel(w_current, 0, 0, angle, angle_change, o_current);
+ break;
+
+ case(OBJ_TEXT):
+ o_text_rotate_world(w_current, 0, 0, angle, angle_change, o_current);
+ break;
+
+ }
+ o_current=o_current->next;
+ }
+}
+
+/*! \brief
+ * \par Function Description
+ *
+ */
+/* pass in top level object */
+void o_complex_mirror_lowlevel(TOPLEVEL *w_current,
+ int world_centerx, int world_centery,
+ OBJECT *object)
+{
+ OBJECT *o_current=NULL;
+
+ /* do individual complex objects */
+ o_current = object->complex->prim_objs;
+
+ while ( o_current != NULL ) {
+ switch(o_current->type) {
+ case(OBJ_LINE):
+ o_line_mirror_world(w_current, 0, 0, o_current);
+ break;
+
+ case(OBJ_NET):
+ o_net_mirror_world(w_current, 0, 0, o_current);
+ break;
+
+ case(OBJ_BUS):
+ o_bus_mirror_world(w_current, 0, 0, o_current);
+ break;
+
+ case(OBJ_BOX):
+ o_box_mirror_world(w_current, 0, 0, o_current);
+ break;
+
+ case(OBJ_PICTURE):
+#ifndef HAS_GTK12
+ o_picture_mirror_world(w_current, 0, 0, o_current);
+#endif
+ break;
+
+ case(OBJ_CIRCLE):
+ o_circle_mirror_world(w_current, 0, 0, o_current);
+ break;
+
+ case(OBJ_PIN):
+ o_pin_mirror_world(w_current, 0, 0, o_current);
+ break;
+
+ case(OBJ_ARC):
+ o_arc_mirror_world(w_current, 0, 0, o_current);
+ break;
+
+ case(OBJ_COMPLEX):
+ case(OBJ_PLACEHOLDER):
+ o_complex_mirror_lowlevel(w_current, 0, 0, o_current);
+ break;
+
+ case(OBJ_TEXT):
+ o_text_mirror_world(w_current, 0, 0, o_current);
+ break;
+
+ }
+ o_current=o_current->next;
+ }
+
+ /* mirror origin point */
+ /* object->x = -object->x;*/
+}
+
+/*! \brief
+ * \par Function Description
+ *
+ */
+/* pass in top level object */
+OBJECT *o_complex_return_pin_object(OBJECT *object, char *pin)
+{
+ OBJECT *o_current=NULL;
+ OBJECT *found;
+
+ /* go inside complex objects */
+ o_current = object->complex->prim_objs;
+
+ while ( o_current != NULL ) {
+ switch(o_current->type) {
+ case(OBJ_PIN):
+
+ /* Search for the pin making sure that */
+ /* any found attribute starts with "pinnumber" */
+ found = o_attrib_search_attrib_value(o_current->attribs, pin,
+ "pinnumber", 0);
+ if (found) {
+#if DEBUG
+ printf("%s: %s\n", found->name,
+ found->text->string);
+#endif
+ return(o_current);
+ }
+ break;
+ }
+ o_current=o_current->next;
+ }
+ return(NULL);
+}
+
+#line 1849 "../noweb/o_complex_basic.nw"
+void
+o_complex_check_symversion(TOPLEVEL* w_current, OBJECT* object)
+{
+ char *inside = NULL;
+ char *outside = NULL;
+ char *refdes = NULL;
+ double inside_value = -1.0;
+ double outside_value = -1.0;
+ char *err_check = NULL;
+ int inside_present = FALSE;
+ int outside_present = FALSE;
+ double inside_major, inside_minor;
+ double outside_major, outside_minor;
+
+ if (object->type != OBJ_COMPLEX && object->type != OBJ_PLACEHOLDER)
+ {
+ return;
+ }
+
+ /* first look on the inside for the symversion= attribute */
+ inside = o_attrib_search_name(object->complex->prim_objs, "symversion", 0);
+
+ /* now look for the symversion= attached to object */
+ outside = o_attrib_search_attrib_name(object->attribs, "symversion", 0);
+
+ /* get the uref for future use */
+ refdes = o_attrib_search_attrib_name(object->attribs, "refdes", 0);
+ if (!refdes)
+ {
+ refdes = g_strdup ("unknown");
+ }
+
+ if (inside)
+ {
+ inside_value = strtod(inside, &err_check);
+ if (inside_value == 0 && inside == err_check)
+ {
+ if (inside)
+ {
+ s_log_message("WARNING: Symbol version parse error on refdes %s:\n"
+ "\tCould not parse symbol file symversion=%s\n",
+ refdes, inside);
+ } else {
+ s_log_message("WARNING: Symbol version parse error on refdes %s:\n"
+ "\tCould not parse symbol file symversion=\n",
+ refdes);
+ }
+ goto done;
+ }
+ inside_present = TRUE;
+ } else {
+ inside_present = FALSE; /* attribute not inside */
+ }
+
+ if (outside)
+ {
+ outside_value = strtod(outside, &err_check);
+ if (outside_value == 0 && outside == err_check)
+ {
+ s_log_message("WARNING: Symbol version parse error on refdes %s:\n"
+ "\tCould not parse attached symversion=%s\n",
+ refdes, outside);
+ goto done;
+ }
+ outside_present = TRUE;
+ } else {
+ outside_present = FALSE; /* attribute not outside */
+ }
+
+#if DEBUG
+ printf("%s:\n\tinside: %.1f outside: %.1f\n\n", object->name,
+ inside_value, outside_value);
+#endif
+
+ /* symversion= is not present anywhere */
+ if (!inside_present && !outside_present)
+ {
+ /* symbol is legacy and versioned okay */
+ goto done;
+ }
+
+ /* No symversion inside, but a version is outside, this is a weird case */
+ if (!inside_present && outside_present)
+ {
+ s_log_message("WARNING: Symbol version oddity on refdes %s:\n"
+ "\tsymversion=%s attached to instantiated symbol, "
+ "but no symversion= inside symbol file\n",
+ refdes, outside);
+ goto done;
+ }
+
+ /* inside & not outside is a valid case, means symbol in library is newer */
+ /* also if inside_value is greater than outside_value, then symbol in */
+ /* library is newer */
+ if ((inside_present && !outside_present) ||
+ ((inside_present && outside_present) && (inside_value > outside_value)))
+ {
+
+ fprintf(stderr, "WARNING: Symbol version mismatch on refdes %s (%s):\n"
+ "\tSymbol in library is newer than "
+ "instantiated symbol\n",
+ refdes, object->complex_basename);
+ s_log_message("WARNING: Symbol version mismatch on refdes %s (%s):\n"
+ "\tSymbol in library is newer than "
+ "instantiated symbol\n",
+ refdes, object->complex_basename);
+
+ /* break up the version values into major.minor numbers */
+ inside_major = floor(inside_value);
+ inside_minor = inside_value - inside_major;
+
+ if (outside_present)
+ {
+ outside_major = floor(outside_value);
+ outside_minor = outside_value - outside_major;
+ } else {
+ /* symversion was not attached to the symbol, set all to zero */
+ outside_major = 0.0;
+ outside_minor = 0.0;
+ outside_value = 0.0;
+ }
+
+#if DEBUG
+ printf("i: %f %f %f\n", inside_value, inside_major, inside_minor);
+ printf("o: %f %f %f\n", outside_value, outside_major, outside_minor);
+#endif
+
+ if (inside_major > outside_major)
+ {
+ char* refdes_copy;
+ fprintf(stderr, "\tMAJOR VERSION CHANGE (file %.3f, "
+ "instantiated %.3f, %s)!\n",
+ inside_value, outside_value, refdes);
+ s_log_message("\tMAJOR VERSION CHANGE (file %.3f, "
+ "instantiated %.3f)!\n",
+ inside_value, outside_value);
+
+ /* add the refdes to the major_changed_refdes GList */
+ /* make sure refdes_copy is freed somewhere */
+ refdes_copy = g_strconcat (refdes, " (",
+ object->complex_basename,
+ ")", NULL);
+ w_current->major_changed_refdes =
+ g_list_append(w_current->major_changed_refdes, refdes_copy);
+
+ /* don't bother checking minor changes if there are major ones*/
+ goto done;
+ }
+
+ if (inside_minor > outside_minor)
+ {
+ fprintf(stderr, "\tMinor version change (file %.3f, "
+ "instantiated %.3f)\n",
+ inside_value, outside_value);
+ s_log_message("\tMinor version change (file %.3f, "
+ "instantiated %.3f)\n",
+ inside_value, outside_value);
+ }
+
+ goto done;
+ }
+
+ /* outside value is greater than inside value, this is weird case */
+ if ((inside_present && outside_present) && (outside_value > inside_value))
+ {
+ s_log_message("WARNING: Symbol version oddity on refdes %s:\n"
+ "\tInstanciated symbol is newer than "
+ "symbol in library\n",
+ refdes);
+ goto done;
+ }
+
+ /* if inside_value and outside_value match, then symbol versions are okay */
+
+done:
+ if (inside) free(inside);
+ if (outside) free(outside);
+ if (refdes) free(refdes);
+}
1.19 +76 -59 eda/geda/gaf/libgeda/src/o_image.c
(In the diff below, changes in quantity of whitespace are not shown.)
Index: o_image.c
===================================================================
RCS file: o_image.c
diff -N o_image.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ o_image.c 5 Jul 2006 03:13:38 -0000 1.19
@@ -0,0 +1,159 @@
+/* gEDA - GPL Electronic Design Automation
+ * libgeda - gEDA's library
+ * Copyright (C) 1998-2000 Ales V. Hvezda
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+#include <config.h>
+
+#include <stdio.h>
+
+#include <gtk/gtk.h>
+#include <libguile.h>
+
+#ifdef HAS_LIBGDGEDA
+#include <gdgeda/gd.h>
+#endif
+
+#include "defines.h"
+#include "struct.h"
+#include "globals.h"
+#include "o_types.h"
+#include "funcs.h"
+#include "colors.h"
+
+#include "../include/prototype.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+int image_black;
+int image_white;
+#if 0
+int image_red;
+int image_green;
+int image_blue;
+int image_yellow;
+int image_cyan;
+int image_grey;
+#endif
+
+#ifdef HAS_LIBGDGEDA
+
+extern COLOR colors[MAX_COLORS];
+
+/*! \brief
+ *
+ */
+gdImagePtr current_im_ptr;
+
+/*! \brief
+ * \par Function Description
+ *
+ */
+void o_image_init(void)
+{
+
+}
+
+/*! \brief
+ * \par Function Description
+ *
+ * \param [in] x
+ * \param [in] y
+ * \param [in] color_mode
+ */
+/* background color ? */
+void o_image_create(int x, int y, int color_mode)
+{
+ gdImagePtr im_ptr;
+
+ im_ptr = gdImageCreate(x, y);
+
+ if (color_mode == TRUE) {
+ /* You can change the background color which is outputed */
+ if (colors[BACKGROUND_COLOR].image_red != -1 &&
+ colors[BACKGROUND_COLOR].image_green != -1 &&
+ colors[BACKGROUND_COLOR].image_blue != -1) {
+ image_black = gdImageColorAllocate(im_ptr,
+ colors[BACKGROUND_COLOR].image_red,
+ colors[BACKGROUND_COLOR].image_green,
+ colors[BACKGROUND_COLOR].image_blue);
+ } else {
+ image_black = gdImageColorAllocate(im_ptr, 0, 0, 0);
+ }
+ image_white = gdImageColorAllocate(im_ptr, 255, 255, 255);
+ } else {
+ /* set the background to white */
+ image_white = gdImageColorAllocate(im_ptr, 255, 255, 255);
+ image_black = gdImageColorAllocate(im_ptr, 0, 0, 0);
+ }
+
+ current_im_ptr = im_ptr;
+
+ s_color_gdcolor_init();
+}
+
+/*! \brief
+ * \par Function Description
+ *
+ */
+void o_image_close(void)
+{
+ gdImageDestroy(current_im_ptr);
+}
+
+/*! \brief
+ * \par Function Description
+ *
+ */
+int o_image_write(const char *filename)
+{
+ FILE *out;
+
+ if (filename == NULL) {
+ return(-1);
+ }
+
+ gdImageInterlace(current_im_ptr, 1);
+
+ out = fopen(filename, "wb");
+
+ if (out == NULL) {
+ s_log_message("Could not open [%s] for image writting\n", filename);
+ return(-1);
+ }
+
+ gdImagePng(current_im_ptr, out);
+
+ fclose(out);
+ return(0);
+}
+#endif
+
+/*! \brief
+ * \par Function Description
+ *
+ */
+/* this can stay in even if libgdgeda doesn't exist */
+int o_image_geda2gd_color(int color)
+{
+ int value;
+ value = s_color_image_int(color);
+ return(value);
+}
+
+
1.22 +1308 -1008eda/geda/gaf/libgeda/src/o_line_basic.c
(In the diff below, changes in quantity of whitespace are not shown.)
Index: o_line_basic.c
===================================================================
RCS file: o_line_basic.c
diff -N o_line_basic.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ o_line_basic.c 5 Jul 2006 03:13:38 -0000 1.22
@@ -0,0 +1,1531 @@
+/* gEDA - GPL Electronic Design Automation
+ * libgeda - gEDA's library
+ * Copyright (C) 1998-2000 Ales V. Hvezda
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+#include <config.h>
+
+#include <stdio.h>
+#include <math.h>
+
+#include <gtk/gtk.h>
+#include <libguile.h>
+
+#ifdef HAS_LIBGDGEDA
+#include <gdgeda/gd.h>
+#endif
+
+#include "defines.h"
+#include "struct.h"
+#include "globals.h"
+#include "o_types.h"
+#include "colors.h"
+#include "funcs.h"
+
+#include "../include/prototype.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+/*! \brief Create and add line OBJECT to list.
+ * \par Function Description
+ * This function creates a new object representing a line.
+ * This object is added to the end of the list <B>object_list</B>
+ * pointed object belongs to.
+ * The line is described by its two ends - <B>x1</B>,<B>y1</B> and
+ * <B>x2</B>,<B>y2</B>.
+ * The <B>type</B> parameter must be equal to #OBJ_LINE.
+ * The <B>color</B> parameter corresponds to the color the box
+ * will be drawn with.
+ *
+ * The #OBJECT structure is allocated with the
+ * #s_basic_init_object() function. The structure describing
+ * the line is allocated and initialized with the parameters given
+ * to the function.
+ *
+ * Both the line type and the filling type are set to default
+ * values : solid line type with a width of 0, and no filling.
+ * It can be changed after with the #o_set_line_options() and
+ * #o_set_fill_options().
+ *
+ * The object is added to the end of the list described by the
+ * <B>object_list</B> parameter by the #s_basic_link_object().
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in,out] object_list OBJECT list to add line to.
+ * \param [in] type Must be OBJ_LINE.
+ * \param [in] color Circle line color.
+ * \param [in] x1 Upper x coordinate.
+ * \param [in] y1 Upper y coordinate.
+ * \param [in] x2 Lower x coordinate.
+ * \param [in] y2 Lower y coordinate.
+ * \return A pointer to the new end of the object list.
+ */
+OBJECT *o_line_add(TOPLEVEL *w_current, OBJECT *object_list,
+ char type, int color,
+ int x1, int y1, int x2, int y2)
+{
+ OBJECT *new_node;
+
+ /* create the object */
+ new_node = s_basic_init_object("line");
+ new_node->type = type;
+ new_node->color = color;
+
+ new_node->line = (LINE *) malloc(sizeof(LINE));
+
+ /* describe the line with its two ends */
+ new_node->line->x[0] = x1;
+ new_node->line->y[0] = y1;
+ new_node->line->x[1] = x2;
+ new_node->line->y[1] = y2;
+
+ /* line type and filling initialized to default */
+ o_set_line_options(w_current, new_node,
+ END_NONE, TYPE_SOLID, 0, -1, -1);
+ o_set_fill_options(w_current, new_node,
+ FILLING_HOLLOW, -1, -1, -1, -1, -1);
+
+ /* \todo questionable cast */
+ new_node->draw_func = (void *) line_draw_func;
+ /* \todo questionable cast */
+ new_node->sel_func = (void *) select_func;
+
+ /* compute bounding box and screen coords */
+ o_line_recalc(w_current, new_node);
+
+ object_list = (OBJECT *) s_basic_link_object(new_node, object_list);
+
+ return(object_list);
+}
+
+/*! \brief Create a copy of a line.
+ * \par Function Description
+ * This function creates a verbatim copy of the
+ * object pointed by <B>o_current</B> describing a line. The new object
+ * is added at the end of the list following the <B>list_tail</B>
+ * parameter.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [out] list_tail OBJECT list to copy to.
+ * \param [in] o_current Line OBJECT to copy.
+ * \return A new pointer to the end of the object list.
+ */
+OBJECT *o_line_copy(TOPLEVEL *w_current, OBJECT *list_tail, OBJECT *o_current)
+{
+ OBJECT *new_obj;
+ ATTRIB *a_current;
+ int color;
+
+ if (o_current->saved_color == -1) {
+ color = o_current->color;
+ } else {
+ color = o_current->saved_color;
+ }
+
+ /*
+ * A new line object is added a the end of the object list with
+ * #o_line_add(). Values for its fields are default and need to
+ * be modified.
+ */
+ new_obj = o_line_add(w_current, list_tail,
+ OBJ_LINE, color,
+ 0, 0, 0, 0);
+
+ /*
+ * The coordinates of the ends of the new line are set with the ones
+ * of the original line. The two lines have the sale line type and
+ * filling options.
+ *
+ * The coordinates and the values in screen unit are computed with
+ * #o_line_recalc().
+ */
+
+ /* modify the line ends of the new line */
+ new_obj->line->x[0] = o_current->line->x[0];
+ new_obj->line->y[0] = o_current->line->y[0];
+ new_obj->line->x[1] = o_current->line->x[1];
+ new_obj->line->y[1] = o_current->line->y[1];
+
+ /* copy the line type and filling options */
+ o_set_line_options(w_current, new_obj, o_current->line_end,
+ o_current->line_type, o_current->line_width,
+ o_current->line_length, o_current->line_space);
+ o_set_fill_options(w_current, new_obj,
+ o_current->fill_type, o_current->fill_width,
+ o_current->fill_pitch1, o_current->fill_angle1,
+ o_current->fill_pitch2, o_current->fill_angle2);
+
+ /* calc the screen coords */
+ o_line_recalc(w_current, o_current);
+
+ /* new_obj->attribute = 0;*/
+ a_current = o_current->attribs;
+ if (a_current) {
+ while ( a_current ) {
+ /* head attrib node has prev = NULL */
+ if (a_current->prev != NULL) {
+ a_current->copied_to = new_obj;
+ }
+ a_current = a_current->next;
+ }
+ }
+
+ /* return the new tail of the object list */
+ return(new_obj);
+}
+
+/*! \brief Modify the description of a line OBJECT.
+ * \par Function Description
+ * This function modifies the coordinates of one of the two ends of
+ * the line described by <B>*object</B>. The new coordinates of this end,
+ * identified by <B>whichone</B>, are given by <B>x</B> and <B>y</B>
+ * in world unit.
+ *
+ * The coordinates of the end of line is modified in the world
+ * coordinate system. Screen coordinates and boundings are then updated.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in,out] object Line OBJECT to modify.
+ * \param [in] x New x coordinate.
+ * \param [in] y New y coordinate.
+ * \param [in] whichone Which line parameter to modify.
+ *
+ * <B>whichone</B> can have the following values:
+ * <DL>
+ * <DT>*</DT><DD>LINE_END1
+ * <DT>*</DT><DD>LINE_END2
+ * </DL>
+ *
+ * \par Author's note
+ * pb20011009 - modified
+ */
+void o_line_modify(TOPLEVEL *w_current, OBJECT *object,
+ int x, int y, int whichone)
+{
+ /* change one of the end of the line */
+ switch(whichone) {
+ case LINE_END1:
+ object->line->x[0] = x;
+ object->line->y[0] = y;
+ break;
+
+ case LINE_END2:
+ object->line->x[1] = x;
+ object->line->y[1] = y;
+ break;
+
+ default:
+ return;
+ }
+
+ /* recalculate the screen coords and the boundings */
+ o_line_recalc(w_current, object);
+
+}
+
+/*! \brief Create line OBJECT from character string.
+ * \par Function Description
+ * This function creates a line OBJECT from the character string
+ * <B>*buf</B> the description of a box. The new box is added to the
+ * list of objects of which <B>*object_list</B> is the last element
+ * before the call.
+ * The function returns a pointer on the new last element, that is
+ * the added line object.
+ *
+ * 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] w_current The TOPLEVEL object.
+ * \param [out] object_list OBJECT list to create line in.
+ * \param [in] buf Character string with line description.
+ * \param [in] release_ver libgeda release version number.
+ * \param [in] fileformat_ver libgeda file format version number.
+ * \return A pointer to the new line object.
+ */
+OBJECT *o_line_read(TOPLEVEL *w_current, OBJECT *object_list, char buf[],
+ unsigned int release_ver, unsigned int fileformat_ver)
+{
+ char type;
+ int x1, y1;
+ int x2, y2;
+ int d_x1, d_y1;
+ int d_x2, d_y2;
+ int line_width, line_space, line_length;
+ int line_end;
+ int line_type;
+ int color;
+
+ if(release_ver <= VERSION_20000704) {
+ /*
+ * The old geda file format, i.e. releases 20000704 and older, does
+ * not handle the line type and the filling - here filling is irrelevant.
+ * They are set to default.
+ */
+ sscanf(buf, "%c %d %d %d %d %d\n", &type,
+ &x1, &y1, &x2, &y2, &color);
+
+ line_width = 0;
+ line_end = END_NONE;
+ line_type = TYPE_SOLID;
+ line_length= -1;
+ line_space = -1;
+ } else {
+ /*
+ * The current line format to describe a line is a space separated
+ * list of characters and numbers in plain ASCII on a single line.
+ * The meaning of each item is described in the file format documentation.
+ */
+ sscanf(buf, "%c %d %d %d %d %d %d %d %d %d %d\n", &type,
+ &x1, &y1, &x2, &y2, &color,
+ &line_width, &line_end, &line_type, &line_length, &line_space);
+ }
+
+ d_x1 = x1; /* \todo PB : Needed ? */
+ d_y1 = y1;
+ d_x2 = x2;
+ d_y2 = y2;
+
+ /*
+ * Null length line are not allowed. If such a line is detected a
+ * message is issued.
+ *
+ * It also checks is the required color is valid.
+ */
+ if (x1 == x2 && y1 == y2) {
+ fprintf(stderr, "Found a zero length line [ %c %d %d %d %d %d ]\n",
+ type, x1, y1, x2, y2, color);
+ s_log_message("Found a zero length line [ %c %d %d %d %d %d ]\n",
+ type, x1, y1, x2, y2, color);
+ }
+
+ if (color < 0 || color > MAX_COLORS) {
+ fprintf(stderr, "Found an invalid color [ %s ]\n", buf);
+ s_log_message("Found an invalid color [ %s ]\n", buf);
+ s_log_message("Setting color to WHITE\n");
+ color = WHITE;
+ }
+
+ /*
+ * A line is internally described by its two ends. A new object is
+ * allocated, initialized and added to the list of objects. Its line
+ * type is set according to the values of the fields on the line.
+ */
+ /* create and add the line to the list */
+ object_list = o_line_add(w_current, object_list,
+ type, color, d_x1, d_y1, d_x2, d_y2);
+ /* set its line options */
+ o_set_line_options(w_current, object_list,
+ line_end, line_type, line_width, line_length,
+ line_space);
+ /* filling is irrelevant for line, just set to default */
+ o_set_fill_options(w_current, object_list,
+ FILLING_HOLLOW, -1, -1, -1, -1, -1);
+
+ return(object_list);
+}
+
+/*! \brief Create a character string representation of a line OBJECT.
+ * \par Function Description
+ * The function formats a string in the buffer <B>*buff</B> to describe
+ * the box object <B>*object</B>.
+ * It follows the post-20000704 release file format that handle the
+ * line type and fill options - filling is irrelevant here.
+ *
+ * \param [in] object Line OBJECT to create string from.
+ * \return A pointer to the line OBJECT character string.
+ *
+ * \note
+ * Caller must free returned character string.
+ *
+ */
+char *o_line_save(OBJECT *object)
+{
+ int x1, x2, y1, y2;
+ int color;
+ int line_width, line_space, line_length;
+ char *buf;
+ OBJECT_END line_end;
+ OBJECT_TYPE line_type;
+
+ /* get the two ends */
+ x1 = object->line->x[0];
+ y1 = object->line->y[0];
+ x2 = object->line->x[1];
+ y2 = object->line->y[1];
+
+ /* description of the line type */
+ line_width = object->line_width;
+ line_end = object->line_end;
+ line_type = object->line_type;
+ line_length= object->line_length;
+ line_space = object->line_space;
+
+ /* Use the right color */
+ if (object->saved_color == -1) {
+ color = object->color;
+ } else {
+ color = object->saved_color;
+ }
+
+ buf = g_strdup_printf("%c %d %d %d %d %d %d %d %d %d %d", object->type,
+ x1, y1, x2, y2, color,
+ line_width, line_end, line_type,
+ line_length, line_space);
+
+ return(buf);
+}
+
+/*! \brief Translate a line position by a delta.
+ * \par Function Description
+ * This function applies a translation of (<B>dx</B>,<B>dy</B>) to the
+ * line described by <B>*object</B>. <B>dx</B> and <B>dy</B> are in
+ * screen unit.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] dx x distance to move.
+ * \param [in] dy y distance to move.
+ * \param [in,out] object Line OBJECT to translate.
+ */
+void o_line_translate(TOPLEVEL *w_current, int dx, int dy, OBJECT *object)
+{
+ int x, y;
+
+ if (object == NULL) printf("lt NO!\n");
+
+ /* Do screen coords */
+ object->line->screen_x[0] = object->line->screen_x[0] + dx;
+ object->line->screen_y[0] = object->line->screen_y[0] + dy;
+ object->line->screen_x[1] = object->line->screen_x[1] + dx;
+ object->line->screen_y[1] = object->line->screen_y[1] + dy;
+
+ /* do we want snap grid here? hack */
+ SCREENtoWORLD(w_current,
+ object->line->screen_x[0], object->line->screen_y[0],
+ &x, &y);
+ object->line->x[0] = snap_grid(w_current, x);
+ object->line->y[0] = snap_grid(w_current, y);
+
+ SCREENtoWORLD(w_current,
+ object->line->screen_x[1], object->line->screen_y[1],
+ &x, &y);
+ object->line->x[1] = snap_grid(w_current, x);
+ object->line->y[1] = snap_grid(w_current, y);
+
+}
+
+/*! \brief Translate a line position in WORLD coordinates by a delta.
+ * \par Function Description
+ * This function applies a translation of (<B>x1</B>,<B>y1</B>) to the line
+ * described by <B>*object</B>. <B>x1</B> and <B>y1</B> are in world unit.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] x1 x distance to move.
+ * \param [in] y1 y distance to move.
+ * \param [in,out] object Line OBJECT to translate.
+ */
+void o_line_translate_world(TOPLEVEL *w_current,
+ int x1, int y1, OBJECT *object)
+{
+ int screen_x1, screen_y1;
+ int screen_x2, screen_y2;
+ int left, right, top, bottom;
+
+ if (object == NULL) printf("ltw NO!\n");
+
+ /* Do world coords */
+ object->line->x[0] = object->line->x[0] + x1;
+ object->line->y[0] = object->line->y[0] + y1;
+ object->line->x[1] = object->line->x[1] + x1;
+ object->line->y[1] = object->line->y[1] + y1;
+
+ /* update screen coords */
+ WORLDtoSCREEN(w_current, object->line->x[0],
+ object->line->y[0],
+ &screen_x1,
+ &screen_y1);
+ object->line->screen_x[0] = screen_x1;
+ object->line->screen_y[0] = screen_y1;
+
+ WORLDtoSCREEN(w_current, object->line->x[1],
+ object->line->y[1],
+ &screen_x2,
+ &screen_y2);
+ object->line->screen_x[1] = screen_x2;
+ object->line->screen_y[1] = screen_y2;
+
+ /* update bounding box */
+ get_line_bounds(w_current, object->line, &left, &top, &right, &bottom);
+
+ object->left = left;
+ object->top = top;
+ object->right = right;
+ object->bottom = bottom;
+
+}
+
+/*! \brief Rotate a line OBJECT.
+ * \par Function Description
+ * This function applies a rotation of center (<B>centerx</B>,<B>centery</B>)
+ * and angle <B>angle</B> to the line object <B>*object</B>.
+ * The coordinates of the rotation center are in screen units.
+ * <B>angle</B> mst be a 90 degree multiple. If not, no rotation is applied.
+ *
+ * The rotation is made by the #o_line_rotate_world() function
+ * that perform a rotation of angle <B>angle</B> and center
+ * (<B>world_centerx</B>,<B>world_centery</B>) in world unit.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] centerx Rotation center x coordinate in SCREEN units.
+ * \param [in] centery Rotation center y coordinate in SCREEN units.
+ * \param [in] angle Rotation angle in degrees (unused).
+ * \param [in,out] object Line OBJECT to rotate.
+ *
+ * \note
+ * takes in screen coordinates for the centerx,y, and then does the rotate
+ * in world space
+ * also ignores angle argument... for now, rotate only in 90 degree
+ * increments
+ */
+void o_line_rotate(TOPLEVEL *w_current, int centerx, int centery, int angle,
+ OBJECT *object)
+{
+ int world_centerx, world_centery;
+
+ /* convert the center of rotation to world unit */
+ SCREENtoWORLD(w_current, centerx, centery,
+ &world_centerx,
+ &world_centery);
+
+ /* rotate the line */
+ /* the check on the rotation angle is in o_line_rotate_world() */
+ o_line_rotate_world(w_current,
+ world_centerx, world_centery, angle,
+ object);
+
+}
+
+/*! \brief Rotate Line OBJECT using WORLD coordinates.
+ * \par Function Description
+ * This function rotates the line described by
+ * <B>*object</B> around the (<B>world_centerx</B>,<B>world_centery</B>)
+ * point by <B>angle</B> degrees.
+ * The center of rotation is in world units.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] world_centerx Rotation center x coordinate in WORLD units.
+ * \param [in] world_centery Rotation center y coordinate in WORLD units.
+ * \param [in] angle Rotation angle in degrees (See note below).
+ * \param [in,out] object Line OBJECT to rotate.
+ */
+void o_line_rotate_world(TOPLEVEL *w_current,
+ int world_centerx, int world_centery, int angle,
+ OBJECT *object)
+{
+ int newx, newy;
+
+ if (angle == 0)
+ return;
+
+ /* angle must be positive */
+ if(angle < 0) angle = -angle;
+ /* angle must be 90 multiple or no rotation performed */
+ if((angle % 90) != 0) return;
+
+ /*
+ * The center of rotation (<B>world_centerx</B>,<B>world_centery</B>)
+ * is translated to the origin. The rotation of the two ends of
+ * the line is performed. FInally, the rotated line is translated
+ * back to its previous location.
+ */
+ /* translate object to origin */
+ o_line_translate_world(w_current, -world_centerx, -world_centery, object);
+
+ /* rotate line end 1 */
+ rotate_point_90(object->line->x[0], object->line->y[0], angle,
+ &newx, &newy);
+
+ object->line->x[0] = newx;
+ object->line->y[0] = newy;
+
+ /* rotate line end 2 */
+ rotate_point_90(object->line->x[1], object->line->y[1], angle,
+ &newx, &newy);
+
+ object->line->x[1] = newx;
+ object->line->y[1] = newy;
+
+ /* translate object back to normal position */
+ o_line_translate_world(w_current, world_centerx, world_centery, object);
+
+}
+
+/*! \brief Mirror a Line.
+ * \par Function Description
+ * This function mirrors the line from the point
+ * (<B>centerx</B>,<B>centery</B>) in screen unit.
+ *
+ * The origin of the mirror in screen unit is converted in world unit.
+ * The line is mirrored with the function #o_line_mirror_world()
+ * for which the origin of the mirror must be given in world unit.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] centerx Origin x coordinate in WORLD units.
+ * \param [in] centery Origin y coordinate in WORLD units.
+ * \param [in,out] object Line OBJECT to mirror.
+ */
+void o_line_mirror(TOPLEVEL *w_current,
+ int centerx, int centery,
+ OBJECT *object)
+{
+ int world_centerx, world_centery;
+
+ /* convert the origin of mirror */
+ SCREENtoWORLD(w_current, centerx, centery,
+ &world_centerx,
+ &world_centery);
+
+ /* apply the mirror in world coords */
+ o_line_mirror_world(w_current,
+ world_centerx, world_centery,
+ object);
+
+}
+
+/*! \brief Mirror a line using WORLD coordinates.
+ * \par Function Description
+ * This function mirrors the line from the point
+ * (<B>world_centerx</B>,<B>world_centery</B>) in world unit.
+ *
+ * The line if first translated to the origin, then mirrored
+ * and finally translated back at its previous position.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] world_centerx Origin x coordinate in WORLD units.
+ * \param [in] world_centery Origin y coordinate in WORLD units.
+ * \param [in,out] object Line OBJECT to mirror.
+ */
+void o_line_mirror_world(TOPLEVEL *w_current, int world_centerx,
+ int world_centery, OBJECT *object)
+{
+ /* translate object to origin */
+ o_line_translate_world(w_current, -world_centerx, -world_centery, object);
+
+ /* mirror the line ends */
+ object->line->x[0] = -object->line->x[0];
+ object->line->x[1] = -object->line->x[1];
+
+ /* translate back in position */
+ o_line_translate_world(w_current, world_centerx, world_centery, object);
+
+}
+
+/*! \brief Recalculate line coordinates in SCREEN units.
+ * \par Function Description
+ * This function recalculate the screen coords of the <B>o_current</B>
+ * pointed line object from its world coords.
+ *
+ * The line ends coordinates and its bounding box are recalculated
+ * as well as the OBJECT specific fields (line width, filling ...).
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in,out] o_current Line OBJECT to be recalculated.
+ */
+void o_line_recalc(TOPLEVEL *w_current, OBJECT *o_current)
+{
+ int screen_x1, screen_y1;
+ int screen_x2, screen_y2;
+ int left, right, top, bottom;
+
+ if (o_current->line == NULL) {
+ return;
+ }
+
+ /* update the screen coords of end 1 of the line */
+ WORLDtoSCREEN(w_current,
+ o_current->line->x[0], o_current->line->y[0],
+ &screen_x1, &screen_y1);
+ o_current->line->screen_x[0] = screen_x1;
+ o_current->line->screen_y[0] = screen_y1;
+
+ /* update the screen coords of end 2 of the line */
+ WORLDtoSCREEN(w_current,
+ o_current->line->x[1], o_current->line->y[1],
+ &screen_x2, &screen_y2);
+ o_current->line->screen_x[1] = screen_x2;
+ o_current->line->screen_y[1] = screen_y2;
+
+ /* update the bounding box - screen unit */
+ get_line_bounds(w_current, o_current->line,
+ &left, &top, &right, &bottom);
+ o_current->left = left;
+ o_current->top = top;
+ o_current->right = right;
+ o_current->bottom = bottom;
+
+ /* recalc OBJECT specific parameters */
+ o_object_recalc(w_current, o_current);
+
+}
+
+/*! \brief Get line bounding rectangle.
+ * \par Function Description
+ * This function sets the <B>left</B>, <B>top</B>, <B>right</B> and
+ * <B>bottom</B> parameters to the boundings of the line object described
+ * by <B>*line</B> in screen units.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] line line OBJECT to read coordinates from.
+ * \param [out] left Left line coordinate in SCREEN units.
+ * \param [out] top Top line coordinate in SCREEN units.
+ * \param [out] right Right line coordinate in SCREEN units.
+ * \param [out] bottom Bottom line coordinate in SCREEN units.
+ */
+void get_line_bounds(TOPLEVEL *w_current, LINE *line, int *left, int *top,
+ int *right, int *bottom)
+{
+ *left = w_current->width;
+ *top = w_current->height;
+ *right = 0;
+ *bottom = 0;
+
+ if (line->screen_x[0] < *left) *left = line->screen_x[0];
+ if (line->screen_x[0] > *right) *right = line->screen_x[0];
+ if (line->screen_y[0] < *top) *top = line->screen_y[0];
+ if (line->screen_y[0] > *bottom) *bottom = line->screen_y[0];
+
+ if (line->screen_x[1] < *left) *left = line->screen_x[1];
+ if (line->screen_x[1] > *right) *right = line->screen_x[1];
+ if (line->screen_y[1] < *top) *top = line->screen_y[1];
+ if (line->screen_y[1] > *bottom) *bottom = line->screen_y[1];
+
+ /* PB : bounding box has to take into account the width of the line */
+ /* PB : but line width is unknown here */
+
+ *left = *left - 4;
+ *top = *top - 4;
+ *right = *right + 4;
+ *bottom = *bottom + 4;
+}
+
+/*! \brief Get line bounding rectangle in WORLD coordinates.
+ * \par Function Description
+ * This function sets the <B>left</B>, <B>top</B>, <B>right</B> and
+ * <B>bottom</B> parameters to the boundings of the line object described
+ * in <B>*line</B> in world units.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] line Line OBJECT to read coordinates from.
+ * \param [out] left Left line coordinate in WORLD units.
+ * \param [out] top Top line coordinate in WORLD units.
+ * \param [out] right Right line coordinate in WORLD units.
+ * \param [out] bottom Bottom line coordinate in WORLD units.
+ */
+void world_get_line_bounds(TOPLEVEL *w_current, LINE *line,
+ int *left, int *top, int *right, int *bottom)
+{
+ *left = w_current->init_right;
+ *top = w_current->init_bottom;
+ *right = 0;
+ *bottom = 0;
+
+ if (line->x[0] < *left) *left = line->x[0];
+ if (line->x[0] > *right) *right = line->x[0];
+ if (line->y[0] < *top) *top = line->y[0];
+ if (line->y[0] > *bottom) *bottom = line->y[0];
+
+ if (line->x[1] < *left) *left = line->x[1];
+ if (line->x[1] > *right) *right = line->x[1];
+ if (line->y[1] < *top) *top = line->y[1];
+ if (line->y[1] > *bottom) *bottom = line->y[1];
+
+}
+
+/*! \brief Print line to Postscript document.
+ * \par Function Description
+ * This function prints the line described by the <B>o_current</B>
+ * parameter to a Postscript document.
+ * The Postscript document is described by the <B>fp</B> file pointer.
+ *
+ * Parameters of the line are extracted from object pointed by
+ * <B>o_current</B>.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] fp FILE pointer to Postscript document.
+ * \param [in] o_current Line OBJECT to write to document.
+ * \param [in] origin_x Page x coordinate to place line OBJECT.
+ * \param [in] origin_y Page y coordinate to place line OBJECT.
+ */
+void o_line_print(TOPLEVEL *w_current, FILE *fp, OBJECT *o_current,
+ int origin_x, int origin_y)
+{
+ int x1, y1, x2, y2;
+ int color;
+ int line_width, length, space;
+ void (*outl_func)() = NULL;
+
+ if (o_current == NULL) {
+ printf("got null in o_line_print\n");
+ return;
+ }
+
+ x1 = o_current->line->x[0];
+ y1 = o_current->line->y[0];
+ x2 = o_current->line->x[1];
+ y2 = o_current->line->y[1];
+ color = o_current->color;
+
+ /*
+ * Depending on the type of the line for this particular line, the
+ * appropriate function is chosen among
+ * #o_line_print_solid(), #o_line_print_dotted()#, #o_line_print_dashed(),
+ * #o_line_print_center() and #o_line_print_phantom().
+ *
+ * The needed parameters for each of these types are extracted from the
+ * <B>o_current</B> object. Depending on the type, unused parameters are
+ * set to -1.
+ *
+ * In the eventuality of a length and/or space null, the line is printed
+ * solid to avoid and endless loop produced by other functions.
+ */
+ line_width = o_current->line_width;
+ if(line_width <= 2) line_width = 2;
+ length = o_current->line_length;
+ space = o_current->line_space;
+
+ switch(o_current->line_type) {
+ case(TYPE_SOLID):
+ length = -1; space = -1;
+ outl_func = (void *) o_line_print_solid;
+ break;
+
+ case(TYPE_DOTTED):
+ length = -1;
+ outl_func = (void *) o_line_print_dotted;
+ break;
+
+ case(TYPE_DASHED):
+ outl_func = (void *) o_line_print_dashed;
+ break;
+
+ case(TYPE_CENTER):
+ outl_func = (void *) o_line_print_center;
+ break;
+
+ case(TYPE_PHANTOM):
+ outl_func = (void *) o_line_print_phantom;
+ break;
+
+ case(TYPE_ERASE):
+ /* Unused for now, print it solid */
+ length = -1; space = -1;
+ outl_func = (void *) o_line_print_solid;
+ break;
+ }
+
+ if((length == 0) || (space == 0)) {
+ length = -1; space = -1;
+ outl_func = (void *) o_line_print_solid;
+ }
+
+ (*outl_func)(w_current, fp,
+ x1 - origin_x, y1 - origin_y,
+ x2 - origin_x, y2 - origin_y,
+ color,
+ line_width, length, space,
+ origin_x, origin_y);
+}
+
+/*! \brief Print a solid line to Postscript document.
+ * \par Function Description
+ * This function prints a line when a solid line type is required.
+ * The line is defined by the coordinates of its two ends in
+ * (<B>x1</B>,<B>y1</B>) and (<B>x2</B>,<B>y2</B>).
+ * The Postscript document is defined by the file pointer <B>fp</B>.
+ * The parameters <B>length</B> and <B>space</B> are ignored whereas
+ * <B>line_width</B> specifies the width of the printed line.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] fp FILE pointer to Postscript document.
+ * \param [in] x1 Upper x coordinate.
+ * \param [in] y1 Upper y coordinate.
+ * \param [in] x2 Lower x coordinate.
+ * \param [in] y2 Lower y coordinate.
+ * \param [in] color Line color.
+ * \param [in] line_width Width of line.
+ * \param [in] length (unused).
+ * \param [in] space (unused).
+ * \param [in] origin_x Page x coordinate to place line OBJECT.
+ * \param [in] origin_y Page y coordinate to place line OBJECT.
+ */
+void o_line_print_solid(TOPLEVEL *w_current, FILE *fp,
+ int x1, int y1, int x2, int y2,
+ int color,
+ int line_width, int length, int space,
+ int origin_x, int origin_y)
+{
+ if (w_current->print_color) {
+ f_print_set_color(fp, color);
+ }
+
+ fprintf(fp,"%d %d %d %d %d line\n",
+ x1,y1,x2,y2, line_width);
+}
+
+/*! \brief Print a dotted line to Postscript document.
+ * \par Function Description
+ * This function prints a line when a dotted line type is required.
+ * The line is defined by the coordinates of its two ends in
+ * (<B>x1</B>,<B>y1</B>) and (<B>x2</B>,<B>y2</B>).
+ * The Postscript document is defined by the file pointer <B>fp</B>.
+ * The parameter <B>length</B> is ignored whereas <B>line_width</B>
+ * specifies the diameter of the dots and <B>space</B> the distance
+ * between two dots.
+ *
+ * A negative value for <B>space</B> leads to an endless loop.
+ *
+ * All dimensions are in mils.
+ *
+ * The function sets the color in which the line will be printed with.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] fp FILE pointer to Postscript document.
+ * \param [in] x1 Upper x coordinate.
+ * \param [in] y1 Upper y coordinate.
+ * \param [in] x2 Lower x coordinate.
+ * \param [in] y2 Lower y coordinate.
+ * \param [in] color Line color.
+ * \param [in] line_width Width of line.
+ * \param [in] length (unused).
+ * \param [in] space Space between dots.
+ * \param [in] origin_x Page x coordinate to place line OBJECT.
+ * \param [in] origin_y Page y coordinate to place line OBJECT.
+ */
+void o_line_print_dotted(TOPLEVEL *w_current, FILE *fp,
+ int x1, int y1, int x2, int y2,
+ int color,
+ int line_width, int length, int space,
+ int origin_x, int origin_y)
+{
+ double dx, dy, l, d;
+ double dx1, dy1;
+ double xa, ya;
+
+ if (w_current->print_color) {
+ f_print_set_color(fp, color);
+ }
+
+ /* The dotted line command takes an array of dots so print out the
+ * beginnings of the array
+ */
+ fprintf(fp,"[");
+ /* PB : is the width relevant for a dot (circle) ? */
+ /* f_print_set_line_width(fp, line_width); */
+
+ /*
+ * Depending on the slope of the line the space parameter is
+ * projected on each of the two directions x and y resulting
+ * in <B>dx1</B> and <B>dy1</B>. Starting from one end by increments
+ * of space the dots are printed.
+ *
+ * A dot is represented by a filled circle. Position of the
+ * circle is (<B>xa</B>, <B>ya</B>) and its radius is the <B>line_width</B>
+ * parameter.
+ */
+
+ dx = (double) (x2 - x1);
+ dy = (double) (y2 - y1);
+ l = sqrt((dx * dx) + (dy * dy));
+
+ dx1 = (dx * space) / l;
+ dy1 = (dy * space) / l;
+
+ d = 0;
+ xa = x1; ya = y1;
+ while(d < l) {
+
+ fprintf(fp,"[%d %d] ",
+ (int)xa, (int)ya);
+ d = d + space;
+ xa = xa + dx1;
+ ya = ya + dy1;
+ }
+
+ fprintf(fp,"] %d dashed\n",line_width);
+
+}
+
+
+/*! \brief Print a dashed line to Postscript document.
+ * \par Function Description
+ * This function prints a line when a dashed line type is required.
+ * The line is defined by the coordinates of its two ends in
+ * (<B>x1</B>,<B>y1</B>) and (<B>x2</B>,<B>y2</B>).
+ * The postscript file is defined by the file pointer <B>fp</B>.
+ *
+ * A negative value for <B>space</B> or <B>length</B> leads to an
+ * endless loop.
+ *
+ * All dimensions are in mils.
+ *
+ * The function sets the color in which the line will be printed and
+ * the width of the line - that is the width of the dashes.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] fp FILE pointer to Postscript document.
+ * \param [in] x1 Upper x coordinate.
+ * \param [in] y1 Upper y coordinate.
+ * \param [in] x2 Lower x coordinate.
+ * \param [in] y2 Lower y coordinate.
+ * \param [in] color Line color.
+ * \param [in] line_width Width of line.
+ * \param [in] length Length of a dash.
+ * \param [in] space Space between dashes.
+ * \param [in] origin_x Page x coordinate to place line OBJECT.
+ * \param [in] origin_y Page y coordinate to place line OBJECT.
+ */
+void o_line_print_dashed(TOPLEVEL *w_current, FILE *fp,
+ int x1, int y1, int x2, int y2,
+ int color,
+ int line_width, int length, int space,
+ int origin_x, int origin_y)
+{
+ double dx, dy, l, d;
+ double dx1, dy1, dx2, dy2;
+ double xa, ya, xb, yb;
+
+ if (w_current->print_color) {
+ f_print_set_color(fp, color);
+ }
+
+ /* the dashed line function takes an array of start-finish pairs
+ * output the beginnings of the array now
+ */
+ fprintf(fp,"[");
+
+ /*
+ * Depending on the slope of the line the <B>length</B> (resp. <B>space</B>)
+ * parameter is projected on each of the two directions x and y
+ * resulting in <B>dx1</B> and <B>dy1</B> (resp. <B>dx2</B> and <B>dy2</B>).
+ * Starting from one end and incrementing alternatively by <B>space</B>
+ * and <B>length</B> the dashes are printed.
+ *
+ * It prints as many dashes of length <B>length</B> as possible.
+ */
+ dx = (double) (x2 - x1);
+ dy = (double) (y2 - y1);
+ l = sqrt((dx * dx) + (dy * dy));
+
+ dx1 = (dx * length) / l;
+ dy1 = (dy * length) / l;
+
+ dx2 = (dx * space) / l;
+ dy2 = (dy * space) / l;
+
+ d = 0;
+ xa = x1; ya = y1;
+ while((d + length + space) < l) {
+ d = d + length;
+ xb = xa + dx1;
+ yb = ya + dy1;
+
+ fprintf(fp, "[%d %d %d %d] ",
+ (int) xa, (int) ya,
+ (int) xb, (int) yb);
+
+ d = d + space;
+ xa = xb + dx2;
+ ya = yb + dy2;
+ }
+ /*
+ * When the above condition is no more satisfied, then it is not possible
+ * to print a dash of length <B>length</B>. However it may be possible to
+ * print the complete dash or a shorter one.
+ */
+
+ if((d + length) < l) {
+ d = d + length;
+ xb = xa + dx1;
+ yb = ya + dy1;
+ } else {
+ xb = x2;
+ yb = y2;
+ }
+
+ fprintf(fp, "[%d %d %d %d] ",
+ (int) xa, (int) ya,
+ (int) xb, (int) yb);
+
+ fprintf(fp,"] %d dashed\n", line_width);
+}
+
+
+/*! \brief Print a centered line type line to Postscript document.
+ * \par Function Description
+ * This function prints a line when a centered line type is required.
+ * The line is defined by the coordinates of its two ends in
+ * (<B>x1</B>,<B>y1</B>) and (<B>x2</B>,<B>y2</B>).
+ * The Postscript document is defined by the file pointer <B>fp</B>.
+ *
+ * A negative value for <B>space</B> or <B>length</B> leads to an
+ * endless loop.
+ *
+ * All dimensions are in mils.
+ *
+ * The function sets the color in which the line will be printed and the
+ * width of the line - that is the width of the dashes and the diameter
+ * of the dots.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] fp FILE pointer to Postscript document.
+ * \param [in] x1 Upper x coordinate.
+ * \param [in] y1 Upper y coordinate.
+ * \param [in] x2 Lower x coordinate.
+ * \param [in] y2 Lower y coordinate.
+ * \param [in] color Line color.
+ * \param [in] line_width Width of line.
+ * \param [in] length Length of a dash.
+ * \param [in] space Space between dashes.
+ * \param [in] origin_x Page x coordinate to place line OBJECT.
+ * \param [in] origin_y Page y coordinate to place line OBJECT.
+ */
+void o_line_print_center(TOPLEVEL *w_current, FILE *fp,
+ int x1, int y1, int x2, int y2,
+ int color,
+ int line_width, int length, int space,
+ int origin_x, int origin_y)
+{
+ double dx, dy, l, d;
+ double dx1, dy1, dx2, dy2;
+ double xa, ya, xb, yb;
+
+ if (w_current->print_color) {
+ f_print_set_color(fp, color);
+ }
+
+ fprintf(fp, "[");
+
+ /*
+ * Depending on the slope of the line the <B>length</B> (resp. <B>space</B>)
+ * parameter is projected on each of the two directions x and y resulting
+ * in <B>dx1</B> and <B>dy1</B> (resp. <B>dx2</B> and <B>dy2</B>).
+ * Starting from one end and incrementing alternatively by <B>space</B>
+ * and <B>length</B> the dashes and dots are printed.
+ *
+ * It prints as many sets of dash and dot as possible.
+ */
+ dx = (double) (x2 - x1);
+ dy = (double) (y2 - y1);
+ l = sqrt((dx * dx) + (dy * dy));
+
+ dx1 = (dx * length) / l;
+ dy1 = (dy * length) / l;
+
+ dx2 = (dx * space) / l;
+ dy2 = (dy * space) / l;
+
+ d = 0;
+ xa = x1; ya = y1;
+ while((d + length + 2 * space) < l) {
+ d = d + length;
+ xb = xa + dx1;
+ yb = ya + dy1;
+
+ fprintf(fp, "[%d %d %d %d] ",
+ (int) xa, (int) ya,
+ (int) xb, (int) yb);
+
+ d = d + space;
+ xa = xb + dx2;
+ ya = yb + dy2;
+
+ fprintf(fp,"[%d %d] ",(int) xa, (int) ya);
+
+ d = d + space;
+ xa = xa + dx2;
+ ya = ya + dy2;
+ }
+ /*
+ * When the above condition is no more satisfied, then it is not possible
+ * to print a dash of length <B>length</B>.
+ * However two cases are possible :
+ * <DL>
+ * <DT>*</DT><DD>it is possible to print the dash and the dot.
+ * <DT>*</DT><DD>it is possible to print the dash or a part
+ * of the original dash.
+ * </DL>
+ */
+
+ if((d + length + space) < l) {
+ d = d + length;
+ xb = xa + dx1;
+ yb = ya + dy1;
+
+ fprintf(fp, "[%d %d %d %d] ",
+ (int) xa, (int) ya,
+ (int) xb, (int) yb);
+
+ d = d + space;
+ xa = xb + dx2;
+ ya = yb + dy2;
+
+ fprintf(fp,"[%d %d] ",(int) xa, (int) ya);
+
+ } else {
+ if(d + length < l) {
+ xb = xa + dx1;
+ yb = ya + dy1;
+ } else {
+ xb = x2;
+ yb = y2;
+ }
+
+ fprintf(fp, "[%d %d %d %d] ",
+ (int) xa, (int) ya,
+ (int) xb, (int) yb);
+
+ }
+
+ fprintf(fp,"] %d dashed\n", line_width);
+
+ /*
+ * A dot is represented by a filled circle. Position of the circle is
+ * (<B>xa</B>, <B>ya</B>) and its radius by the <B>line_width</B> parameter.
+ */
+}
+
+/*! \brief Print a phantom line type line to Postscript document.
+ * \par Function Description
+ * This function prints a line when a phantom line type is required.
+ * The line is defined by the coordinates of its two ends in
+ * (<B>x1</B>,<B>y1</B>) and (<B>x2</B>,<B>y2</B>).
+ * The Postscript document is defined by the file pointer <B>fp</B>.
+ *
+ * A negative value for <B>space</B> or <B>length</B> leads to an
+ * endless loop.
+ *
+ * All dimensions are in mils.
+ *
+ * The function sets the color in which the line will be printed and the
+ * width of the line - that is the width of the dashes and the diameter
+ * of the dots.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] fp FILE pointer to Postscript document.
+ * \param [in] x1 Upper x coordinate.
+ * \param [in] y1 Upper y coordinate.
+ * \param [in] x2 Lower x coordinate.
+ * \param [in] y2 Lower y coordinate.
+ * \param [in] color Line color.
+ * \param [in] line_width Width of line.
+ * \param [in] length Length of a dash.
+ * \param [in] space Space between dashes.
+ * \param [in] origin_x Page x coordinate to place line OBJECT.
+ * \param [in] origin_y Page y coordinate to place line OBJECT.
+ */
+void o_line_print_phantom(TOPLEVEL *w_current, FILE *fp,
+ int x1, int y1, int x2, int y2,
+ int color,
+ int line_width, int length, int space,
+ int origin_x, int origin_y)
+{
+ double dx, dy, l, d;
+ double dx1, dy1, dx2, dy2;
+ double xa, ya, xb, yb;
+
+ if (w_current->print_color) {
+ f_print_set_color(fp, color);
+ }
+
+ fprintf(fp,"[");
+
+ /*
+ * Depending on the slope of the line the <B>length</B> (resp. <B>space</B>)
+ * parameter is projected on each of the two directions x and y resulting
+ * in <B>dx1</B> and <B>dy1</B> (resp. <B>dx2</B> and <B>dy2</B>).
+ * Starting from one end and incrementing alternatively by <B>space</B>
+ * and <B>length</B> the dashes and dots are printed.
+ *
+ * It prints as many sets of dash-dot-dot as possible.
+ */
+ dx = (double) (x2 - x1);
+ dy = (double) (y2 - y1);
+ l = sqrt((dx * dx) + (dy * dy));
+
+ dx1 = (dx * length) / l;
+ dy1 = (dy * length) / l;
+
+ dx2 = (dx * space) / l;
+ dy2 = (dy * space) / l;
+
+ d = 0;
+ xa = x1; ya = y1;
+ while((d + length + 3 * space) < l) {
+ d = d + length;
+ xb = xa + dx1;
+ yb = ya + dy1;
+
+ fprintf(fp,"[%d %d %d %d] ",
+ (int) xa, (int)ya,
+ (int) xb, (int)yb);
+
+ d = d + space;
+ xa = xb + dx2;
+ ya = yb + dy2;
+
+ fprintf(fp,"[%d %d] ",(int) xa, (int) ya);
+
+ d = d + space;
+ xa = xa + dx2;
+ ya = ya + dy2;
+
+ fprintf(fp,"[%d %d] ",(int) xa, (int) ya);
+
+ d = d + space;
+ xa = xa + dx2;
+ ya = ya + dy2;
+ }
+ /*
+ * When the above condition is no more satisfied, then it is not possible
+ * to print a complete set of dash-dot-dot.
+ * However three cases are possible :
+ * <DL>
+ * <DT>*</DT><DD>it is possible to print a dash and a dot and a dot.
+ * <DT>*</DT><DD>it is possible to print a dash and a dot.
+ * <DT>*</DT><DD>it is possible to print the dash or a part
+ * of the original dash.
+ * </DL>
+ */
+
+ if((d + length + 2 * space) < l) {
+ d = d + length;
+ xb = xa + dx1;
+ yb = ya + dy1;
+
+ fprintf(fp,"[%d %d %d %d] ",
+ (int) xa, (int)ya,
+ (int) xb, (int)yb);
+
+ d = d + space;
+ xa = xb + dx2;
+ ya = yb + dy2;
+
+ fprintf(fp,"[%d %d] ",(int) xa, (int)ya);
+
+ d = d + space;
+ xa = xb + dx2;
+ ya = yb + dy2;
+
+ fprintf(fp,"[%d %d] ",(int) xa, (int)ya);
+
+ } else {
+ if(d + length + space < l) {
+ d = d + length;
+ xb = xa + dx1;
+ yb = ya + dy1;
+
+ fprintf(fp,"[%d %d %d %d] ",
+ (int) xa, (int)ya,
+ (int) xb, (int)yb);
+
+ d = d + space;
+ xa = xb + dx2;
+ ya = yb + dy2;
+
+ fprintf(fp,"[%d %d] ",(int) xa, (int)ya);
+
+ } else {
+ if(d + length < l) {
+ xb = xa + dx1;
+ yb = ya + dy1;
+ } else {
+ xb = x2;
+ yb = y2;
+ }
+
+ fprintf(fp,"[%d %d %d %d] ",
+ (int) xa, (int)ya,
+ (int) xb, (int)yb);
+
+ }
+ }
+
+ fprintf(fp,"] %d dashed\n", line_width);
+}
+
+#if 0 /* original way of printing line, no longer used */
+/*! \brief Print line to Postscript document using old method.
+ * \par Function Description
+ * This function is the old function to print a line.
+ * It does not handle line type.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] fp FILE pointer to Postscript document.
+ * \param [in] o_current Line object to print.
+ * \param [in] origin_x Page x coordinate to place line OBJECT.
+ * \param [in] origin_y Page x coordinate to place line OBJECT.
+ */
+void o_line_print_old(TOPLEVEL *w_current, FILE *fp, OBJECT *o_current,
+ int origin_x, int origin_y)
+{
+ if (o_current == NULL) {
+ printf("got null in o_line_print\n");
+ return;
+ }
+
+ if (w_current->print_color) {
+ f_print_set_color(fp, o_current->color);
+ }
+
+ fprintf(fp, "newpath\n");
+
+ fprintf(fp, "%d mils %d mils moveto\n",
+ o_current->line_points->x1-origin_x,
+ o_current->line_points->y1-origin_y);
+ fprintf(fp, "%d mils %d mils lineto\n",
+ o_current->line_points->x2-origin_x,
+ o_current->line_points->y2-origin_y);
+ fprintf(fp, "stroke\n");
+
+}
+#endif
+
+/*! \brief Draw a line in an image.
+ * \par Function Description
+ * This function draws a line in an image with the libgdgeda function
+ * #gdImageLine().
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] o_current Line OBJECT to draw.
+ * \param [in] origin_x (unused).
+ * \param [in] origin_y (unused).
+ * \param [in] color_mode Draw line in color if TRUE, B/W otherwise.
+ */
+
+void o_line_image_write(TOPLEVEL *w_current, OBJECT *o_current,
+ int origin_x, int origin_y, int color_mode)
+{
+ int color;
+
+ if (o_current == NULL) {
+ printf("got null in o_line_print\n");
+ return;
+ }
+
+ if (color_mode == TRUE) {
+ color = o_image_geda2gd_color(o_current->color);
+ } else {
+ color = image_black;
+ }
+
+ /* assumes screen coords are already calculated correctly */
+#ifdef HAS_LIBGDGEDA
+
+ gdImageSetThickness(current_im_ptr, SCREENabs(w_current,
+ o_current->line_width));
+
+ gdImageLine(current_im_ptr,
+ o_current->line->screen_x[0],
+ o_current->line->screen_y[0],
+ o_current->line->screen_x[1],
+ o_current->line->screen_y[1],
+ color);
+#endif
+}
+
+/*! \brief
+ * \par Function Description
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] x_scale
+ * \param [in] y_scale
+ * \param [in] object
+ */
+void o_line_scale_world(TOPLEVEL *w_current, int x_scale, int y_scale,
+ OBJECT *object)
+{
+ if (object == NULL) printf("lsw NO!\n");
+
+ /* scale the line world coords */
+ object->line->x[0] = object->line->x[0] * x_scale;
+ object->line->y[0] = object->line->y[0] * y_scale;
+ object->line->x[1] = object->line->x[1] * x_scale;
+ object->line->y[1] = object->line->y[1] * y_scale;
+
+ /* update screen coords */
+ o_line_recalc(w_current, object);
+
+}
+
+/*! \brief
+ * \par Function Description
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] line
+ * \param [in] x1
+ * \param [in] y1
+ * \param [in] x2
+ * \param [in] y2
+ * \return int
+ */
+int o_line_visible(TOPLEVEL *w_current, LINE *line,
+ int *x1, int *y1, int *x2, int *y2)
+{
+ int visible=0;
+
+
+ /* don't do clipping if this is false */
+ if (!w_current->object_clipping) {
+ return(TRUE);
+ }
+
+ *x1 = line->screen_x[0];
+ *y1 = line->screen_y[0];
+ *x2 = line->screen_x[1];
+ *y2 = line->screen_y[1];
+
+ visible = SCREENclip_change(w_current, x1, y1, x2, y2);
+
+ return(visible);
+}
+
+/*! \brief
+ * \par Function Description
+ *
+ * \param [in] object
+ * \return double
+ */
+double o_line_length(OBJECT *object)
+{
+ double length;
+ double dx, dy;
+
+ if (!object->line) {
+ return 0.0;
+ }
+
+ dx = object->line->x[0]-object->line->x[1];
+ dy = object->line->y[0]-object->line->y[1];
+
+ length = sqrt((dx*dx) + (dy*dy));
+
+ return(length);
+}
1.18 +340 -285 eda/geda/gaf/libgeda/src/o_list.c
(In the diff below, changes in quantity of whitespace are not shown.)
Index: o_list.c
===================================================================
RCS file: o_list.c
diff -N o_list.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ o_list.c 5 Jul 2006 03:13:38 -0000 1.18
@@ -0,0 +1,438 @@
+/* gEDA - GPL Electronic Design Automation
+ * libgeda - gEDA's library
+ * Copyright (C) 1998-2000 Ales V. Hvezda
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+#include <config.h>
+
+#include <stdio.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <libguile.h>
+
+#include "defines.h"
+#include "struct.h"
+#include "globals.h"
+#include "o_types.h"
+#include "colors.h"
+
+#include "../include/prototype.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+/*! global which is used in o_list_copy_all */
+extern int global_sid;
+
+/*! \todo Finish documentation!!!!
+ * \brief
+ * \par Function Description
+ * returns head !!!!!!!!!!!!!!!!!!!
+ * look at above.. this returns what was passed in!!!!
+ * copies selected to list_head (!! returns new list)
+ * flag is either NORMAL_FLAG or SELECTION_FLAG
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] list_head
+ * \param [in] selected
+ * \param [in] flag
+ * \param [out] return_end
+ * \return OBJECT pointer.
+ */
+OBJECT *o_list_copy_to(TOPLEVEL *w_current, OBJECT *list_head,
+ OBJECT *selected, int flag, OBJECT **return_end)
+{
+ OBJECT *end=NULL;
+
+ /* are we adding a selection or the real object list */
+ w_current->ADDING_SEL = flag;
+
+ end = (OBJECT *) return_tail(list_head);
+
+ switch(selected->type) {
+
+ case(OBJ_LINE):
+ /* do we do anything with the return value) ? */
+ end = (OBJECT *) o_line_copy(w_current, end, selected);
+ break;
+
+ case(OBJ_NET):
+ end = (OBJECT *) o_net_copy(w_current, end, selected);
+ break;
+
+ case(OBJ_BUS):
+ end = (OBJECT *) o_bus_copy(w_current, end, selected);
+ break;
+
+ case(OBJ_BOX):
+ end = (OBJECT *) o_box_copy(w_current, end, selected);
+ break;
+
+ case(OBJ_PICTURE):
+ end = (OBJECT *) o_picture_copy(w_current, end, selected);
+ break;
+
+ case(OBJ_CIRCLE):
+ end = (OBJECT *) o_circle_copy(w_current, end, selected);
+ break;
+
+ case(OBJ_COMPLEX):
+ case(OBJ_PLACEHOLDER):
+ if (selected->complex_clib &&
+ strncmp(selected->complex_clib, "EMBEDDED", 8) == 0) {
+ end = (OBJECT *) o_complex_copy_embedded(w_current, end, selected);
+ } else {
+ end = (OBJECT *) o_complex_copy(w_current, end, selected);
+ }
+ break;
+
+ case(OBJ_TEXT):
+ end = (OBJECT *) o_text_copy(w_current, end, selected);
+ if (selected->attribute &&
+ selected->visibility == INVISIBLE) {
+ end->visibility = INVISIBLE;
+ }
+ break;
+
+ case(OBJ_PIN):
+ end = (OBJECT *) o_pin_copy(w_current, end, selected);
+ break;
+
+ case(OBJ_ARC):
+ end = (OBJECT *) o_arc_copy(w_current, end, selected);
+ break;
+ }
+
+ if (list_head == NULL)
+ list_head = end;
+
+ /* make sure sid is the same! */
+ if (selected) {
+ end->sid = selected->sid;
+ }
+
+ /* I don't think this is a good idea at all */
+ /* w_current->ADDING_SEL = 0; */
+
+ if (return_end) {
+ *return_end = end;
+ }
+
+ return(list_head);
+}
+
+/*! \todo Finish function description!!!
+ * \brief
+ * \par Function Description
+ * you need to pass in a head_node for dest_list_head
+ * flag is either NORMAL_FLAG or SELECTION_FLAG
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] src_list_head
+ * \param [in] dest_list_head
+ * \param [in] flag
+ * \return OBJECT pointer.
+ */
+OBJECT *o_list_copy_all(TOPLEVEL *w_current, OBJECT *src_list_head,
+ OBJECT *dest_list_head, int flag)
+{
+ OBJECT *src;
+ OBJECT *dest;
+ OBJECT *temp_parent=NULL;
+ int adding_sel_save;
+
+ src = src_list_head;
+ dest = dest_list_head;
+ temp_parent = w_current->page_current->object_parent;
+ w_current->page_current->object_parent = dest_list_head;
+
+ if (dest == NULL) {
+ w_current->page_current->object_parent = temp_parent;
+ return(NULL);
+ }
+
+ if (src == NULL) {
+ w_current->page_current->object_parent = temp_parent;
+ return(NULL);
+ }
+
+ adding_sel_save = w_current->ADDING_SEL;
+
+ /* first do all NON text items */
+ while(src != NULL) {
+
+ if (src->type != OBJ_TEXT) {
+ dest->next = o_list_copy_to(w_current, NULL, src, flag,
+ NULL);
+
+ dest->next->prev = dest;
+ dest = dest->next;
+ dest->sid = global_sid++;
+ }
+
+ src = src->next;
+ }
+
+ src = src_list_head;
+ /*dest = dest_list_head; out since we want to add to the end */
+
+ if (dest == NULL) {
+ w_current->page_current->object_parent = temp_parent;
+ return(NULL);
+ }
+
+ if (src == NULL) {
+ w_current->page_current->object_parent = temp_parent;
+ return(NULL);
+ }
+
+ /* then do all text items */
+ while(src != NULL) {
+
+ if (src->type == OBJ_TEXT) {
+ dest->next = o_list_copy_to(w_current, NULL, src, flag,
+ NULL);
+
+ dest->next->prev = dest;
+ dest = dest->next;
+ dest->sid = global_sid++;
+
+ if (src->attached_to /*&& !w_current->ADDING_SEL*/) {
+ if (src->attached_to->copied_to) {
+ o_attrib_attach(w_current,
+ w_current->page_current->object_parent,
+ dest, src->attached_to->copied_to);
+
+ /* satisfied copy request */
+ src->attached_to->copied_to = NULL;
+ }
+ }
+ }
+
+ src = src->next;
+ }
+
+ w_current->ADDING_SEL = adding_sel_save;
+ w_current->page_current->object_parent = temp_parent;
+
+ return(dest);
+}
+
+/*! \todo Finish function description!!!
+ * \brief
+ * \par Function Description
+ * you need to pass in a head_node for dest_list_head
+ * flag is either NORMAL_FLAG or SELECTION_FLAG
+ * this function copies the objects in the src SELECTION list
+ * to the OBJECT list in dest_list_head
+ * this routine assumes that objects in src_list_head are selected
+ * objects are unselected before they are copied and then reselected
+ * this is necessary to preserve the color info
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] src_list_head
+ * \param [in] dest_list_head
+ * \param [in] flag
+ * \return OBJECT pointer.
+ */
+OBJECT *o_list_copy_all_selection2(TOPLEVEL *w_current,
+ SELECTION *src_list_head,
+ OBJECT *dest_list_head, int flag)
+{
+ SELECTION *src;
+ OBJECT *object;
+ OBJECT *dest;
+ OBJECT *temp_parent=NULL;
+ int adding_sel_save;
+
+ src = src_list_head;
+ dest = dest_list_head;
+
+ temp_parent = w_current->page_current->object_parent;
+ w_current->page_current->object_parent = dest_list_head;
+
+ if (dest == NULL) {
+ w_current->page_current->object_parent = temp_parent;
+ return(NULL);
+ }
+
+ if (src == NULL) {
+ w_current->page_current->object_parent = temp_parent;
+ return(NULL);
+ }
+
+ adding_sel_save = w_current->ADDING_SEL;
+
+ /* first do all NON text items */
+ while(src != NULL) {
+
+ object = src->selected_object;
+
+ /* unselect the object before the copy */
+ o_selection_unselect(object);
+
+ if (object->type != OBJ_TEXT && object->type != OBJ_HEAD) {
+ dest->next = o_list_copy_to(w_current, NULL, object,
+ flag, NULL);
+ dest->next->prev = dest;
+ dest = dest->next;
+ dest->sid = global_sid++;
+ }
+
+ /* reselect it */
+ o_selection_select(object, SELECT_COLOR);
+
+ src = src->next;
+ }
+
+ src = src_list_head;
+ /*dest = dest_list_head; out since we want to add to the end */
+
+ if (dest == NULL) {
+ w_current->page_current->object_parent = temp_parent;
+ return(NULL);
+ }
+
+ if (src == NULL) {
+ w_current->page_current->object_parent = temp_parent;
+ return(NULL);
+ }
+
+ /* then do all text items */
+ while(src != NULL) {
+
+ object = src->selected_object;
+
+ /* unselect the object before the copy */
+ o_selection_unselect(object);
+
+ if (object->type == OBJ_TEXT) {
+ dest->next = o_list_copy_to(w_current, NULL, object,
+ flag, NULL);
+
+ dest->next->prev = dest;
+ dest = dest->next;
+ dest->sid = global_sid++;
+
+ if (object->attached_to /*&& !w_current->ADDING_SEL*/) {
+ if (object->attached_to->copied_to) {
+ o_attrib_attach(w_current,
+ w_current->page_current->object_parent,
+ dest, object->attached_to->copied_to);
+ /* satisfied copy request */
+ object->attached_to->copied_to = NULL;
+ }
+ }
+ }
+
+ /* reselect it */
+ o_selection_select(object, SELECT_COLOR);
+
+ src = src->next;
+ }
+
+ w_current->ADDING_SEL = adding_sel_save;
+ w_current->page_current->object_parent = temp_parent;
+
+ return(dest);
+}
+
+/*! \todo Finish function description!!!
+ * \brief
+ * \par Function Description
+ * returns entry in the list
+ *
+ * \param [in] list
+ * \param [in] current
+ * \return OBJECT pointer.
+ */
+OBJECT *o_list_search(OBJECT *list, OBJECT *current)
+{
+ OBJECT *o_current;
+
+ o_current = list ;
+
+ if (current == NULL) {
+ return(NULL);
+ }
+
+ if (list == NULL) {
+ return(NULL);
+ }
+
+ while(o_current != NULL) {
+ /* look for uniq sid */
+ if (current->sid == o_current->sid) {
+ return(o_current);
+ }
+ o_current = o_current->next;
+ }
+ return(NULL);
+}
+
+/*! \todo Finish function description!!!
+ * \brief
+ * \par Function Description
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] list
+ * \param [in] delete
+ */
+void o_list_delete(TOPLEVEL *w_current, OBJECT *list, OBJECT *delete)
+{
+ OBJECT *find;
+
+ find = o_list_search(list, delete);
+
+ if (find != NULL)
+ s_delete(w_current, find);
+
+}
+
+/*! \todo Finish function description!!!
+ * \brief
+ * \par Function Description
+ * assuming list is head
+ * head will NOT be deleted
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] list
+ */
+void o_list_delete_rest(TOPLEVEL *w_current, OBJECT *list)
+{
+ OBJECT *o_current=NULL;
+ OBJECT *o_prev=NULL;
+
+ o_current = (OBJECT *) return_tail(list);
+
+ w_current->REMOVING_SEL = 1;
+ /* remove list backwards */
+ while(o_current != NULL) {
+ if (o_current->type != OBJ_HEAD) {
+ o_prev = o_current->prev;
+ s_delete(w_current, o_current);
+ o_current = o_prev;
+ } else {
+ o_current->next = NULL; /* set sel_head->next to be empty */
+ o_current = NULL;
+ }
+ }
+ w_current->REMOVING_SEL = 0;
+}
1.29 +684 -569 eda/geda/gaf/libgeda/src/o_net_basic.c
(In the diff below, changes in quantity of whitespace are not shown.)
Index: o_net_basic.c
===================================================================
RCS file: o_net_basic.c
diff -N o_net_basic.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ o_net_basic.c 5 Jul 2006 03:13:38 -0000 1.29
@@ -0,0 +1,1012 @@
+/* gEDA - GPL Electronic Design Automation
+ * libgeda - gEDA's library
+ * Copyright (C) 1998-2000 Ales V. Hvezda
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+#include <config.h>
+
+#include <stdio.h>
+#include <math.h>
+
+#include <gtk/gtk.h>
+#include <libguile.h>
+
+#ifdef HAS_LIBGDGEDA
+#include <gdgeda/gd.h>
+#endif
+
+#include "defines.h"
+#include "struct.h"
+#include "globals.h"
+#include "o_types.h"
+#include "colors.h"
+#include "funcs.h"
+
+#include "../include/prototype.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] line
+ * \param [out] left
+ * \param [out] top
+ * \param [out] right
+ * \param [out] bottom
+ */
+void get_net_bounds(TOPLEVEL *w_current, LINE *line, int *left, int *top,
+ int *right, int *bottom)
+{
+ *left = w_current->width;
+ *top = w_current->height;
+ *right = 0;
+ *bottom = 0;
+
+ if (line->screen_x[0] < *left)
+ *left = line->screen_x[0];
+ if (line->screen_x[0] > *right)
+ *right = line->screen_x[0];
+ if (line->screen_y[0] < *top)
+ *top = line->screen_y[0];
+ if (line->screen_y[0] > *bottom)
+ *bottom = line->screen_y[0];
+
+ if (line->screen_x[1] < *left)
+ *left = line->screen_x[1];
+ if (line->screen_x[1] > *right)
+ *right = line->screen_x[1];
+ if (line->screen_y[1] < *top)
+ *top = line->screen_y[1];
+ if (line->screen_y[1] > *bottom)
+ *bottom = line->screen_y[1];
+
+ *left = *left - 4;
+ *top = *top - 4;
+
+ *right = *right + 4;
+ *bottom = *bottom + 4;
+}
+
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] line
+ * \param [out] left
+ * \param [out] top
+ * \param [out] right
+ * \param [out] bottom
+ */
+void world_get_net_bounds(TOPLEVEL *w_current, LINE *line, int *left,
+ int *top, int *right, int *bottom)
+{
+ *left = w_current->init_right;
+ *top = w_current->init_bottom;
+ *right = 0;
+ *bottom = 0;
+
+ if (line->x[0] < *left)
+ *left = line->x[0];
+ if (line->x[0] > *right)
+ *right = line->x[0];
+ if (line->y[0] < *top)
+ *top = line->y[0];
+ if (line->y[0] > *bottom)
+ *bottom = line->y[0];
+
+ if (line->x[1] < *left)
+ *left = line->x[1];
+ if (line->x[1] > *right)
+ *right = line->x[1];
+ if (line->y[1] < *top)
+ *top = line->y[1];
+ if (line->y[1] > *bottom)
+ *bottom = line->y[1];
+
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in,out] object_list
+ * \param [in] type
+ * \param [in] color
+ * \param [in] x1
+ * \param [in] y1
+ * \param [in] x2
+ * \param [in] y2
+ * \return OBJECT *
+ */
+OBJECT *o_net_add(TOPLEVEL *w_current, OBJECT *object_list, char type,
+ int color, int x1, int y1, int x2, int y2)
+{
+ int screen_x, screen_y;
+ int left, right, top, bottom;
+ OBJECT *new_node;
+
+ new_node = s_basic_init_object("net");
+ new_node->type = type;
+ new_node->color = color;
+
+ new_node->line = (LINE *) malloc(sizeof(LINE));
+ /* check for null */
+
+ new_node->line->x[0] = x1;
+ new_node->line->y[0] = y1;
+ new_node->line->x[1] = x2;
+ new_node->line->y[1] = y2;
+
+ WORLDtoSCREEN(w_current,
+ new_node->line->x[0], new_node->line->y[0],
+ &screen_x, &screen_y);
+
+ new_node->line->screen_x[0] = screen_x;
+ new_node->line->screen_y[0] = screen_y;
+
+ WORLDtoSCREEN(w_current,
+ new_node->line->x[1], new_node->line->y[1],
+ &screen_x, &screen_y);
+
+ new_node->line->screen_x[1] = screen_x;
+ new_node->line->screen_y[1] = screen_y;
+
+ get_net_bounds(w_current, new_node->line, &left, &top, &right,
+ &bottom);
+
+ new_node->left = left;
+ new_node->top = top;
+ new_node->right = right;
+ new_node->bottom = bottom;
+
+ /* \todo questionable cast */
+ new_node->draw_func = (void *) net_draw_func;
+ /* \todo questionable cast */
+ new_node->sel_func = (void *) select_func;
+
+ object_list = (OBJECT *) s_basic_link_object(new_node, object_list);
+
+
+ if (!w_current->ADDING_SEL) {
+ s_tile_add_object(w_current, object_list,
+ new_node->line->x[0], new_node->line->y[0],
+ new_node->line->x[1], new_node->line->y[1]);
+ s_conn_update_object(w_current, object_list);
+ }
+
+ return (object_list);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ *
+ */
+void o_net_recalc(TOPLEVEL *w_current, OBJECT *o_current)
+{
+ int screen_x1, screen_y1;
+ int screen_x2, screen_y2;
+ int left, right, top, bottom;
+
+ if (o_current == NULL) {
+ return;
+ }
+
+ if (o_current->line == NULL) {
+ return;
+ }
+
+ WORLDtoSCREEN(w_current, o_current->line->x[0],
+ o_current->line->y[0], &screen_x1, &screen_y1);
+
+ o_current->line->screen_x[0] = screen_x1;
+ o_current->line->screen_y[0] = screen_y1;
+
+ WORLDtoSCREEN(w_current, o_current->line->x[1],
+ o_current->line->y[1], &screen_x2, &screen_y2);
+
+ o_current->line->screen_x[1] = screen_x2;
+ o_current->line->screen_y[1] = screen_y2;
+
+ get_net_bounds(w_current, o_current->line, &left, &top, &right,
+ &bottom);
+
+ o_current->left = left;
+ o_current->top = top;
+ o_current->right = right;
+ o_current->bottom = bottom;
+
+
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ *
+ */
+OBJECT *o_net_read(TOPLEVEL *w_current, OBJECT *object_list, char buf[],
+ unsigned int release_ver, unsigned int fileformat_ver)
+{
+ char type;
+ int x1, y1;
+ int x2, y2;
+ int d_x1, d_y1;
+ int d_x2, d_y2;
+ int color;
+
+ sscanf(buf, "%c %d %d %d %d %d\n", &type, &x1, &y1, &x2, &y2, &color);
+ d_x1 = x1;
+ d_y1 = y1;
+ d_x2 = x2;
+ d_y2 = y2;
+
+ if (x1 == x2 && y1 == y2) {
+ fprintf(stderr, "Found a zero length net [ %c %d %d %d %d %d ]\n",
+ type, x1, y1, x2, y2, color);
+ s_log_message("Found a zero length net [ %c %d %d %d %d %d ]\n",
+ type, x1, y1, x2, y2, color);
+ }
+
+
+ if (w_current->override_net_color != -1) {
+ color = w_current->override_net_color;
+ }
+
+ if (color < 0 || color > MAX_COLORS) {
+ fprintf(stderr, "Found an invalid color [ %s ]\n", buf);
+ s_log_message("Found an invalid color [ %s ]\n", buf);
+ s_log_message("Setting color to WHITE\n");
+ color = WHITE;
+ }
+
+ object_list =
+ o_net_add(w_current, object_list, type, color, d_x1, d_y1, d_x2,
+ d_y2);
+ return (object_list);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ *
+ */
+char *o_net_save(OBJECT *object)
+{
+ int x1, x2, y1, y2;
+ int color;
+ char *buf;
+
+ x1 = object->line->x[0];
+ y1 = object->line->y[0];
+ x2 = object->line->x[1];
+ y2 = object->line->y[1];
+
+ /* Use the right color */
+ if (object->saved_color == -1) {
+ color = object->color;
+ } else {
+ color = object->saved_color;
+ }
+
+ buf = g_strdup_printf("%c %d %d %d %d %d", object->type, x1, y1, x2, y2, color);
+ return (buf);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ *
+ */
+void o_net_translate(TOPLEVEL *w_current, int dx, int dy, OBJECT *object)
+{
+ int x, y;
+
+ if (object == NULL)
+ printf("nt NO!\n");
+
+
+ /* Do world coords */
+ object->line->screen_x[0] = object->line->screen_x[0] + dx;
+ object->line->screen_y[0] = object->line->screen_y[0] + dy;
+ object->line->screen_x[1] = object->line->screen_x[1] + dx;
+ object->line->screen_y[1] = object->line->screen_y[1] + dy;
+
+ /* do we want snap grid here? */
+ SCREENtoWORLD(w_current, object->line->screen_x[0],
+ object->line->screen_y[0], &x, &y);
+
+ object->line->x[0] = snap_grid(w_current, x);
+ object->line->y[0] = snap_grid(w_current, y);
+
+ SCREENtoWORLD(w_current, object->line->screen_x[1],
+ object->line->screen_y[1], &x, &y);
+
+ object->line->x[1] = snap_grid(w_current, x);
+ object->line->y[1] = snap_grid(w_current, y);
+
+ s_tile_update_object(w_current, object);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ *
+ */
+void o_net_translate_world(TOPLEVEL *w_current, int x1, int y1,
+ OBJECT *object)
+{
+ int screen_x1, screen_y1;
+ int screen_x2, screen_y2;
+ int left, right, top, bottom;
+
+ if (object == NULL)
+ printf("ntw NO!\n");
+
+
+ /* Do world coords */
+ object->line->x[0] = object->line->x[0] + x1;
+ object->line->y[0] = object->line->y[0] + y1;
+ object->line->x[1] = object->line->x[1] + x1;
+ object->line->y[1] = object->line->y[1] + y1;
+
+ /* update screen coords */
+ WORLDtoSCREEN(w_current, object->line->x[0],
+ object->line->y[0], &screen_x1, &screen_y1);
+
+ object->line->screen_x[0] = screen_x1;
+ object->line->screen_y[0] = screen_y1;
+
+ WORLDtoSCREEN(w_current, object->line->x[1],
+ object->line->y[1], &screen_x2, &screen_y2);
+
+ object->line->screen_x[1] = screen_x2;
+ object->line->screen_y[1] = screen_y2;
+
+ /* update bounding box */
+ get_net_bounds(w_current, object->line, &left, &top, &right, &bottom);
+
+ object->left = left;
+ object->top = top;
+ object->right = right;
+ object->bottom = bottom;
+
+ s_tile_update_object(w_current, object);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ *
+ */
+OBJECT *o_net_copy(TOPLEVEL *w_current, OBJECT *list_tail,
+ OBJECT *o_current)
+{
+ OBJECT *new_obj;
+ ATTRIB *a_current;
+ int color;
+
+ if (o_current->saved_color == -1) {
+ color = o_current->color;
+ } else {
+ color = o_current->saved_color;
+ }
+
+ /* make sure you fix this in pin and bus as well */
+ /* still doesn't work... you need to pass in the new values */
+ /* or don't update and update later */
+ /* I think for now I'll disable the update and manually update */
+ new_obj = o_net_add(w_current, list_tail, OBJ_NET, color,
+ o_current->line->x[0], o_current->line->y[0],
+ o_current->line->x[1], o_current->line->y[1]);
+
+ new_obj->line->screen_x[0] = o_current->line->screen_x[0];
+ new_obj->line->screen_y[0] = o_current->line->screen_y[0];
+ new_obj->line->screen_x[1] = o_current->line->screen_x[1];
+ new_obj->line->screen_y[1] = o_current->line->screen_y[1];
+
+ new_obj->line->x[0] = o_current->line->x[0];
+ new_obj->line->y[0] = o_current->line->y[0];
+ new_obj->line->x[1] = o_current->line->x[1];
+ new_obj->line->y[1] = o_current->line->y[1];
+
+ a_current = o_current->attribs;
+
+ if (a_current) {
+ while (a_current) {
+
+ /* head attrib node has prev = NULL */
+ if (a_current->prev != NULL) {
+ a_current->copied_to = new_obj;
+ }
+ a_current = a_current->next;
+ }
+ }
+
+ return (new_obj);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ *
+ */
+void o_net_print(TOPLEVEL *w_current, FILE *fp, OBJECT *o_current,
+ int origin_x, int origin_y)
+{
+ int offset, offset2;
+ int cross, net_width;
+ int x1, y1;
+ int x2, y2;
+
+ if (o_current == NULL) {
+ printf("got null in o_net_print\n");
+ return;
+ }
+
+ offset = 7 * 6;
+ offset2 = 7;
+
+ cross = offset;
+
+ if (w_current->print_color) {
+ f_print_set_color(fp, o_current->color);
+ }
+
+ net_width = 2;
+ if (w_current->net_style == THICK) {
+ net_width = NET_WIDTH;
+ }
+
+ x1 = o_current->line->x[0] - origin_x,
+ y1 = o_current->line->y[0] - origin_y;
+ x2 = o_current->line->x[1] - origin_x,
+ y2 = o_current->line->y[1] - origin_y;
+
+ fprintf(fp, "%d %d %d %d %d line\n", x1,y1,x2,y2,net_width);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ *
+ */
+void o_net_image_write(TOPLEVEL *w_current, OBJECT *o_current,
+ int origin_x, int origin_y, int color_mode)
+{
+ int offset, offset2;
+ int cross;
+ int x1, y1;
+ int x2, y2;
+ int endpoint_color;
+ int color;
+
+ if (o_current == NULL) {
+ printf("got null in o_net_image_write\n");
+ return;
+ }
+
+ if (color_mode == TRUE) {
+ color = o_image_geda2gd_color(o_current->color);
+ } else {
+ color = image_black;
+ }
+
+ offset = SCREENabs(w_current, NET_WIDTH);
+
+ /*
+ offset = 7 * (float) w_current->height/ (float) w_current->width;
+ offset2 = 7 * (float) w_current->height/ (float) w_current->width*2;
+
+ printf("%f %d %d\n", (float) ( (float) w_current->height/ (float) w_current->width),
+ offset, offset2);
+ */
+
+ offset2 = offset * 2;
+
+ cross = offset;
+
+ x1 = o_current->line->screen_x[0];
+ y1 = o_current->line->screen_y[0];
+ x2 = o_current->line->screen_x[1];
+ y2 = o_current->line->screen_y[1];
+
+ /* assumes screen coords are already calculated correctly */
+#ifdef HAS_LIBGDGEDA
+
+ if (w_current->net_style == THICK) {
+ gdImageSetThickness(current_im_ptr, SCREENabs(w_current,
+ NET_WIDTH));
+ } else {
+ gdImageSetThickness(current_im_ptr, 0);
+ }
+
+ gdImageLine(current_im_ptr, x1, y1, x2, y2, color);
+#endif
+
+ if (color_mode == TRUE) {
+ endpoint_color =
+ o_image_geda2gd_color(w_current->net_endpoint_color);
+ } else {
+ endpoint_color = image_black;
+ }
+
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ * takes in screen coordinates for the centerx,y, and then does the rotate
+ * in world space
+ * also ignores angle argument... for now, rotate only in 90 degree
+ * increments
+ * fully functional
+ */
+void o_net_rotate(TOPLEVEL *w_current, int centerx, int centery, int angle,
+ OBJECT *object)
+{
+ int world_centerx, world_centery;
+ int newx, newy;
+
+ SCREENtoWORLD(w_current, centerx, centery,
+ &world_centerx, &world_centery);
+
+ /* translate object to origin */
+ o_net_translate_world(w_current, -world_centerx, -world_centery,
+ object);
+
+ rotate_point_90(object->line->x[0], object->line->y[0], angle,
+ &newx, &newy);
+
+ object->line->x[0] = newx;
+ object->line->y[0] = newy;
+
+ rotate_point_90(object->line->x[1], object->line->y[1], angle,
+ &newx, &newy);
+
+ object->line->x[1] = newx;
+ object->line->y[1] = newy;
+
+ o_net_translate_world(w_current, world_centerx, world_centery, object);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ *
+ */
+void o_net_rotate_world(TOPLEVEL *w_current,
+ int world_centerx, int world_centery, int angle,
+ OBJECT *object)
+{
+ int newx, newy;
+
+ if (angle == 0)
+ return;
+
+ /* translate object to origin */
+ o_net_translate_world(w_current, -world_centerx, -world_centery,
+ object);
+
+ rotate_point_90(object->line->x[0], object->line->y[0], angle,
+ &newx, &newy);
+
+ object->line->x[0] = newx;
+ object->line->y[0] = newy;
+
+ rotate_point_90(object->line->x[1], object->line->y[1], angle,
+ &newx, &newy);
+
+ object->line->x[1] = newx;
+ object->line->y[1] = newy;
+
+ o_net_translate_world(w_current, world_centerx, world_centery, object);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ *
+ */
+void o_net_mirror(TOPLEVEL *w_current, int centerx, int centery,
+ OBJECT *object)
+{
+ int world_centerx, world_centery;
+
+ SCREENtoWORLD(w_current, centerx, centery,
+ &world_centerx, &world_centery);
+
+ /* translate object to origin */
+ o_net_translate_world(w_current, -world_centerx, -world_centery,
+ object);
+
+ object->line->x[0] = -object->line->x[0];
+
+ object->line->x[1] = -object->line->x[1];
+
+ o_net_translate_world(w_current, world_centerx, world_centery, object);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ *
+ */
+void o_net_mirror_world(TOPLEVEL *w_current, int world_centerx,
+ int world_centery, OBJECT *object)
+{
+ /* translate object to origin */
+ o_net_translate_world(w_current, -world_centerx, -world_centery,
+ object);
+
+ object->line->x[0] = -object->line->x[0];
+
+ object->line->x[1] = -object->line->x[1];
+
+ o_net_translate_world(w_current, world_centerx, world_centery, object);
+}
+
+int o_net_orientation(OBJECT *object)
+{
+ if (object->line->y[0] == object->line->y[1]) {
+ return (HORIZONTAL);
+ }
+
+ if (object->line->x[0] == object->line->x[1]) {
+ return (VERTICAL);
+ }
+
+ return (NEITHER);
+}
+
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ * this function does the actual work of making one net segment out of two
+ * connected segments
+ * The second object (del_object) is the object that should be deleted
+ */
+void o_net_consolidate_lowlevel(OBJECT *object, OBJECT *del_object,
+ int orient)
+{
+ int temp1, temp2;
+ int final1, final2;
+ int changed = 0;
+ ATTRIB *tail;
+
+#if DEBUG
+ printf("o %d %d %d %d\n", object->line->x[0], object->line->y[0],
+ object->line->x[1], object->line->y[1]);
+ printf("d %d %d %d %d\n", del_object->line->x[0],
+ del_object->line->y[0], del_object->line->x[1],
+ del_object->line->y[1]);
+#endif
+
+
+ if (orient == HORIZONTAL) {
+
+ temp1 = min(object->line->x[0], del_object->line->x[0]);
+ temp2 = min(object->line->x[1], del_object->line->x[1]);
+
+ final1 = min(temp1, temp2);
+
+ temp1 = max(object->line->x[0], del_object->line->x[0]);
+ temp2 = max(object->line->x[1], del_object->line->x[1]);
+
+ final2 = max(temp1, temp2);
+
+ object->line->x[0] = final1;
+ object->line->x[1] = final2;
+ changed = 1;
+ }
+
+ if (orient == VERTICAL) {
+ temp1 = min(object->line->y[0], del_object->line->y[0]);
+ temp2 = min(object->line->y[1], del_object->line->y[1]);
+
+ final1 = min(temp1, temp2);
+
+ temp1 = max(object->line->y[0], del_object->line->y[0]);
+ temp2 = max(object->line->y[1], del_object->line->y[1]);
+
+ final2 = max(temp1, temp2);
+
+ object->line->y[0] = final1;
+ object->line->y[1] = final2;
+ changed = 1;
+ }
+#if DEBUG
+ printf("fo %d %d %d %d\n", object->line->x[0], object->line->y[0],
+ object->line->x[1], object->line->y[1]);
+#endif
+
+ if (changed) {
+
+ /* first check for attributes */
+ if (del_object->attribs) {
+#if DEBUG
+ printf("yeah... del object has attributes\n");
+ printf("reconnecting them to the right place\n");
+#endif
+ if (object->attribs) {
+
+#if DEBUG
+ printf("object DID have attributes\n");
+#endif
+
+
+ /* NEWSEL, this corrupts the selection / object_head badly */
+ /* fix it, because you can't just go around deleting objects */
+ /* this whole net conslidate needs to be re thought.. since you */
+ /* don't really del the del_object */
+#if 0
+ printf("object->attribs\n");
+ o_attrib_print(object->attribs);
+ printf("--\n");
+ printf("del_object->attribs\n");
+ o_attrib_print(del_object->attribs);
+ printf("--\n");
+#endif
+ tail = o_attrib_return_tail(object->attribs);
+
+ /* skip over old attrib head */
+ tail->next = del_object->attribs->next;
+
+ /* step prev object to point to last object */
+ if (tail->next) {
+ tail->next->prev = tail;
+ }
+
+ /* delete old attrib head */
+ /* and nothing else */
+ del_object->attribs->object = NULL;
+ del_object->attribs->next = NULL;
+ del_object->attribs->prev = NULL;
+ o_attrib_delete(del_object->attribs);
+
+ /* you don't need to free the attribs list */
+ /* since it's been relinked into object's */
+ /* attribs list */
+
+ del_object->attribs = NULL;
+#if 0
+ printf("\n\nfinal object->attribs\n");
+ o_attrib_print(object->attribs);
+ printf("--\n");
+#endif
+
+ } else {
+
+#if DEBUG
+ printf("object didn't have any attributes\n");
+#endif
+ object->attribs = del_object->attribs;
+ /*! \todo what should this be? */
+ object->attribs->prev = NULL;
+
+ /* setup parent attribute */
+ object->attribs->object = object;
+
+ /* you don't need to free the attribs list */
+ /* since it's been used by object */
+
+ del_object->attribs = NULL;
+ }
+ }
+ }
+
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ * check to see if this connection also causes a midpoint
+ * if so, return false, else return true
+ */
+int o_net_consolidate_nomidpoint(OBJECT *object, int x, int y)
+{
+ GList *c_current;
+ CONN *conn;
+
+ c_current = object->conn_list;
+ while(c_current != NULL) {
+ conn = (CONN *) c_current->data;
+ if (conn->other_object) {
+ if (conn->other_object->sid != object->sid &&
+ conn->x == x && conn->y == y &&
+ conn->type == CONN_MIDPOINT) {
+#if DEBUG
+ printf("Found one! %s\n", conn->other_object->name);
+#endif
+ return(FALSE);
+ }
+ }
+
+ c_current = c_current->next;
+ }
+
+ return(TRUE);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ *
+ */
+int o_net_consolidate_segments(TOPLEVEL *w_current, OBJECT *object)
+{
+ int object_orient;
+ int other_orient;
+ GList *c_current;
+ CONN *conn;
+ OBJECT *other_object;
+ int changed = 0;
+ int reselect_new=FALSE;
+
+ if (object == NULL) {
+ return(0);
+ }
+
+ if (object->type != OBJ_NET) {
+ return(0);
+ }
+
+ object_orient = o_net_orientation(object);
+
+ /*screen_x = object->line->screen_x[j];
+ screen_y = object->line->screen_y[i];*/
+
+ c_current = object->conn_list;
+ while(c_current != NULL) {
+ conn = (CONN *) c_current->data;
+ other_object = conn->other_object;
+
+ /* only look at end points which have a valid end on the other side */
+ if (other_object != NULL && conn->type == CONN_ENDPOINT &&
+ conn->other_whichone != -1 && conn->whichone != -1 &&
+ o_net_consolidate_nomidpoint(object, conn->x, conn->y) ) {
+
+ if (other_object->type == OBJ_NET) {
+ other_orient = o_net_orientation(other_object);
+
+ /* - both objects have the same orientation (either vert or horiz) */
+ /* - it's not the same object */
+ if (object_orient == other_orient &&
+ object->sid != other_object->sid &&
+ other_orient != NEITHER) {
+
+#if DEBUG
+ printf("consolidating %s to %s\n", object->name, other_object->name);
+#endif
+
+ o_net_consolidate_lowlevel(object, other_object, other_orient);
+
+ changed++;
+ if (other_object->selected == TRUE ) {
+ o_selection_remove(w_current->page_current->selection2_head,
+ other_object);
+ reselect_new=TRUE;
+ }
+
+ if (reselect_new == TRUE) {
+ o_selection_remove(w_current->page_current->selection2_head,
+ object);
+
+ o_selection_add(w_current->page_current->selection2_head,
+ object);
+ }
+
+ s_conn_remove(w_current, other_object);
+ s_delete(w_current, other_object);
+ o_net_recalc(w_current, object);
+ s_tile_update_object(w_current, object);
+ s_conn_update_object(w_current, object);
+ w_current->page_current->object_tail =
+ return_tail(w_current->page_current->object_head);
+ return(-1);
+ }
+ }
+
+ }
+
+ c_current = c_current->next;
+ }
+
+ return(0);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ *
+ */
+void o_net_consolidate(TOPLEVEL *w_current)
+{
+ OBJECT *o_current;
+ int status = 0;
+
+ o_current = w_current->page_current->object_head;
+
+ while (o_current != NULL) {
+
+ if (o_current->type == OBJ_NET) {
+ status = o_net_consolidate_segments(w_current, o_current);
+ }
+
+ if (status == -1) {
+ o_current = w_current->page_current->object_head;
+ status = 0;
+ } else {
+ o_current = o_current->next;
+ }
+ }
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ *
+ */
+void o_net_modify(TOPLEVEL *w_current, OBJECT *object,
+ int x, int y, int whichone)
+{
+ int screen_x, screen_y;
+ int left, right, top, bottom;
+
+ object->line->x[whichone] = x;
+ object->line->y[whichone] = y;
+
+ WORLDtoSCREEN(w_current,
+ object->line->x[whichone],
+ object->line->y[whichone], &screen_x, &screen_y);
+
+ object->line->screen_x[whichone] = screen_x;
+ object->line->screen_y[whichone] = screen_y;
+
+ get_net_bounds(w_current, object->line, &left, &top, &right, &bottom);
+
+ object->left = left;
+ object->top = top;
+ object->right = right;
+ object->bottom = bottom;
+
+ s_tile_update_object(w_current, object);
+}
1.1 eda/geda/gaf/libgeda/src/o_picture.c
Index: o_picture.c
===================================================================
/* gEDA - GPL Electronic Design Automation
* libgeda - gEDA's library
* Copyright (C) 1998-2000 Ales V. Hvezda
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
*/
#include <config.h>
#include <stdio.h>
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#include <math.h>
#include <gtk/gtk.h>
#include <guile/gh.h>
#ifndef HAS_GTK12
#include <gdk/gdk.h>
#include <gdk-pixbuf/gdk-pixbuf.h>
#include <gdk-pixbuf/gdk-pixdata.h>
#endif
#include "defines.h"
#include "struct.h"
#include "globals.h"
#include "o_types.h"
#include "colors.h"
#include "funcs.h"
#include "../include/prototype.h"
#ifndef HAS_GTK12
/*! \brief Create picture OBJECT from character string.
* \par Function Description
* This function will get the description of a picture from the character
* string <B>*buf</B>. The new picture is then added to the list of object of
* which <B>*object_list</B> is the last element before the call.
* The function returns the new last element, that is the added
* picture object.
*
* \param [in] w_current The TOPLEVEL object.
* \param [out] object_list OBJECT list to create picture in.
* \param [in] buf Character string with picture description.
* \param [in] fp Picture file to read.
* \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 *w_current, OBJECT *object_list,
char buf[], FILE *fp,
unsigned int release_ver,unsigned int fileformat_ver)
{
int x1, y1;
int width, height, angle;
gchar mirrored, embedded;
int num_conv;
gchar type;
gchar buffer[MAX_TEXT_LINE_LENGTH];
gchar *filename;
GdkPixbuf *pixbuf;
static char gdk_initialized=0;
/* Initialize GDK first if it isn't a graphic app */
/* i.e: it has no main window */
if ( (w_current->main_window == NULL) &&
(gdk_initialized == 0)) {
gdk_init(NULL, NULL);
gdk_initialized = 1;
}
num_conv = sscanf(buf, "%c %d %d %d %d %d %c %c\n",
&type, &x1, &y1, &width, &height, &angle, &mirrored, &embedded);
if (num_conv != 8) {
fprintf(stderr, "Error reading picture definition line: %s.\n", buf);
s_log_message ("Error reading picture definition line: %s.\n", buf);
}
/* 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) {
fprintf(stderr, "Found a zero width/height picture [ %c %d %d %d %d ]\n",
type, x1, y1, width, height);
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)) {
fprintf(stderr, "Found a picture with a wrong 'mirrored' parameter: %c.\n",
mirrored);
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)) {
fprintf(stderr, "Found a picture with a wrong 'embedded' parameter: %c.\n",
embedded);
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:
fprintf(stderr, "Found an unsupported picture angle [ %d ]\n", angle);
s_log_message("Found an unsupported picture angle [ %d ]\n", angle);
s_log_message("Setting angle to 0\n");
angle=0;
break;
}
fgets(buffer, 1024, fp);
filename = g_strdup (buffer);
filename = remove_last_nl(filename);
pixbuf = NULL;
if (embedded == 0) {
#ifndef HAS_GTK12
pixbuf = gdk_pixbuf_new_from_file (filename, NULL);
if (pixbuf == NULL) {
fprintf(stderr, "Error loading picture from file: %s.\n", filename);
s_log_message( "Error loading picture from file: %s.\n", filename);
}
#endif
}
else {
GString *encoded_picture=g_string_new("");
GdkPixdata pixdata;
guint pixdata_serialized_length;
gchar *pixdata_serialized_data;
char finished = 0;
/* Read the encoded picture */
do {
finished = 0;
fgets(buffer, 1024, fp);
if (g_strcasecmp(buffer, ".\n") != 0) {
encoded_picture=g_string_append (encoded_picture, buffer);
encoded_picture=g_string_append (encoded_picture, "\n");
}
else {
finished = 1;
}
} while (finished == 0);
/* Decode the picture */
pixdata_serialized_data=s_encoding_base64_decode(encoded_picture->str,
encoded_picture->len,
&pixdata_serialized_length);
if (pixdata_serialized_data == NULL) {
fprintf(stderr, "Error decoding picture.\n");
s_log_message ("Error decoding picture.\n");
}
else {
/* Deserialize the picture */
if (!gdk_pixdata_deserialize(&pixdata,pixdata_serialized_length,
(guint8 *) pixdata_serialized_data, NULL)) {
fprintf(stderr, "Error deserializing picture.\n");
}
else {
pixbuf = gdk_pixbuf_from_pixdata (&pixdata,TRUE, NULL);
}
}
if (pixdata_serialized_data != NULL) {
free (pixdata_serialized_data);
}
if (encoded_picture != NULL) {
g_string_free (encoded_picture, TRUE);
}
}
if (pixbuf == NULL) {
/* If the pixbuf couldn't be loaded, then try to load a warning picture */
char *temp_filename;
fprintf(stderr, "Loading warning picture.\n");
s_log_message ("Loading warning picture.\n");
temp_filename = g_strconcat(w_current->bitmap_directory,
G_DIR_SEPARATOR_S, "gschem-warning.png", NULL);
pixbuf = gdk_pixbuf_new_from_file (temp_filename, NULL);
if (pixbuf == NULL) {
fprintf(stderr, "Error loading picture from file: %s.\n", temp_filename);
s_log_message( "Error loading picture from file: %s.\n", temp_filename);
}
free (temp_filename);
}
/* create and add the picture to the list */
/* The picture is described by its upper left and lower right corner */
object_list = (OBJECT *) o_picture_add(w_current, object_list,
pixbuf, filename,
(double) (height/width),
type,
x1, y1+height, x1+width, y1,
angle, mirrored, embedded);
if (object_list->picture->filename) {
free(object_list->picture->filename);
}
object_list->picture->filename = g_strdup(filename);
free (filename);
return(object_list);
}
/*! \brief Create a character string representation of a picture OBJECT.
* \par Function Description
* This function formats a string in the buffer <B>*buff</B> to describe
* the picture object <B>*object</B>.
*
* \param [in] object Picture OBJECT to create string from.
* \return A pointer to the picture OBJECT character string.
*
* \note
* Caller must free returned character string.
*
*/
char *o_picture_save(OBJECT *object)
{
int width, height, x1, y1;
gchar *encoded_picture=NULL;
gchar *out=NULL;
gchar *pixdata_serialized_data=NULL;
guint pixdata_serialized_stream_length;
guint encoded_picture_length;
/* calculate the width and height of the box */
width = abs(object->picture->lower_x - object->picture->upper_x);
height = abs(object->picture->upper_y - object->picture->lower_y);
/* calculate the lower left corner of the box */
x1 = object->picture->upper_x;
y1 = object->picture->upper_y - height; /* move the origin to 0, 0*/
#if DEBUG
printf("picture: %d %d %d %d\n", x1, y1, width, height);
#endif
/* Encode the picture if it's embedded */
if (object->picture->embedded == 1) {
GdkPixdata pixdata;
/* Serialize the picture data */
gdk_pixdata_from_pixbuf (&pixdata, object->picture->original_picture, FALSE);
pixdata_serialized_data = (gchar *) gdk_pixdata_serialize(&pixdata,
&pixdata_serialized_stream_length);
if (pixdata_serialized_data == NULL) {
fprintf (stderr, "ERROR: o_picture_save: failed to create serialized data from picture\n");
s_log_message ("ERROR: o_picture_save: failed to create serialized data from picture\n");
}
else {
/* Encode the picture */
encoded_picture = s_encoding_base64_encode(pixdata_serialized_data,
pixdata_serialized_stream_length,
&encoded_picture_length, TRUE);
if (encoded_picture == NULL) {
fprintf(stderr, "ERROR: o_picture_save: unable to encode the picture.\n");
s_log_message("ERROR: o_picture_save: unable to encode the picture.\n");
}
}
}
if (object->picture->embedded==1) {
out = g_strdup_printf("%c %d %d %d %d %d %c %c\n%s\n%s\n%s",
object->type,
x1, y1, width, height,
object->picture->angle,
/* Convert the (0,1) chars to ASCII */
(object->picture->mirrored)+0x30,
object->picture->embedded+0x30,
object->picture->filename,
encoded_picture,
".");
}
else {
out = g_strdup_printf("%c %d %d %d %d %d %c %c\n%s",
object->type,
x1, y1, width, height,
object->picture->angle,
/* Convert the (0,1) chars to ASCII */
(object->picture->mirrored)+0x30,
object->picture->embedded+0x30,
object->picture->filename);
}
if (encoded_picture != NULL) {
free(encoded_picture);
}
if (pixdata_serialized_data != NULL) {
free(pixdata_serialized_data);
}
return(out);
}
/*! \todo Finish function documentation!!!
* \brief
* \par Function Description
*
* \param [in] w_current The TOPLEVEL object.
* \param [in] pixbuf
* \param [in] filename
*/
void o_picture_set_pixbuf(TOPLEVEL *w_current,
GdkPixbuf *pixbuf, char *filename)
{
/* need to put an error messages here */
if (pixbuf == NULL) {
fprintf(stderr, "error! picture in set pixbuf was NULL\n");
return;
}
if (w_current->current_pixbuf != NULL) {
free(w_current->current_pixbuf);
w_current->current_pixbuf=NULL;
}
if (w_current->pixbuf_filename != NULL) {
free(w_current->pixbuf_filename);
w_current->pixbuf_filename=NULL;
}
w_current->current_pixbuf = pixbuf;
w_current->pixbuf_filename = (char *) g_strdup(filename);
w_current->pixbuf_wh_ratio = (double) gdk_pixbuf_get_width(pixbuf) /
gdk_pixbuf_get_height(pixbuf);
/* be sure to free this pixbuf somewhere */
}
/*! \brief Create and add picture OBJECT to list.
* \par Function Description
* This function creates a new object representing a picture.
* This object is added to the end of the list <B>object_list</B> pointed
* object belongs to.
* The picture is described by its upper left corner - <B>x1</B>, <B>y1</B> -
* and its lower right corner - <B>x2</B>, <B>y2</B>.
* The <B>type</B> parameter must be equal to #OBJ_PICTURE.
*
* The #OBJECT structure is allocated with the
* #s_basic_init_object() function. The structure describing the
* picture is allocated and initialized with the parameters given to the
* function.
*
* The object is added to the end of the list described by the
* <B>object_list</B> parameter by the #s_basic_link_object().
*
* \param [in] w_current The TOPLEVEL object.
* \param [in,out] object_list OBJECT list to add line to.
* \param [in] pixbuf The GdkPixbuf picture to add.
* \param [in] filename File name to read picture from.
* \param [in] ratio Picture height to width ratio.
* \param [in] type Must be OBJ_PICTURE.
* \param [in] x1 Upper x coordinate.
* \param [in] y1 Upper y coordinate.
* \param [in] x2 Lower x coordinate.
* \param [in] y2 Lower y coordinate.
* \param [in] angle Picture rotation angle.
* \param [in] mirrored Whether the image should be mirrored or not.
* \param [in] embedded ???
* \return A pointer to the new end of the object list.
*/
OBJECT *o_picture_add(TOPLEVEL *w_current, OBJECT *object_list,
GdkPixbuf * pixbuf, char *filename, double ratio,
char type,
int x1, int y1, int x2, int y2, int angle, char mirrored,
char embedded)
{
OBJECT *new_node;
PICTURE *picture;
/* create the object */
new_node = s_basic_init_object("picture");
new_node->type = type;
picture = (PICTURE *) malloc(sizeof(PICTURE));
new_node->picture = picture;
/* describe the picture with its upper left and lower right corner */
picture->upper_x = x1;
picture->upper_y = y1;
picture->lower_x = x2;
picture->lower_y = y2;
/* Fill the picture data */
/* Create a copy of the pixbuf */
picture->original_picture = gdk_pixbuf_rotate(pixbuf, 0);
picture->filename = (char *) g_strdup(filename);
picture->ratio = ratio;
picture->displayed_picture = NULL;
picture->angle = angle;
picture->mirrored = mirrored;
picture->embedded = embedded;
if (picture->original_picture == NULL) {
fprintf(stderr, "new picture: Couldn't get enough memory for the new picture\n");
}
/* Clean w_current variables */
/* \bug This should be done when canceling the action. */
/* Pixbuf filename is not freed because we want to
remember the last directory
*/
/*
if (w_current->current_pixbuf != NULL) {
free (w_current->current_pixbuf);
}
w_current->current_pixbuf = NULL;
w_current->pixbuf_wh_ratio = 0;
*/
/* \todo questionable cast */
new_node->draw_func = (void *) picture_draw_func;
/* \todo questionable cast */
new_node->sel_func = (void *) select_func;
/* compute the bounding picture */
o_picture_recalc(w_current, new_node);
/* add the object to the list */
object_list = (OBJECT *) s_basic_link_object(new_node, object_list);
return(object_list);
}
/*! \brief Recalculate picture coordinates in SCREEN units.
* \par Function Description
* This function recalculates the screen coords of the <B>o_current</B>
* parameter picture object from its world coords.
*
* The picture coordinates and its bounding are recalculated as well
* as the #OBJECT specific fields (line width, filling ...).
*
* \param [in] w_current The TOPLEVEL object.
* \param [in,out] o_current Picture OBJECT to be recalculated.
*/
void o_picture_recalc(TOPLEVEL *w_current, OBJECT *o_current)
{
int left, top, right, bottom;
int screen_x1, screen_y1;
int screen_x2, screen_y2;
if (o_current->picture == NULL) {
return;
}
/* update the screen coords of the upper left corner of the picture */
WORLDtoSCREEN(w_current,
o_current->picture->upper_x, o_current->picture->upper_y,
&screen_x1, &screen_y1);
o_current->picture->screen_upper_x = screen_x1;
o_current->picture->screen_upper_y = screen_y1;
/* update the screen coords of the lower right corner of the picture */
WORLDtoSCREEN(w_current,
o_current->picture->lower_x, o_current->picture->lower_y,
&screen_x2, &screen_y2);
o_current->picture->screen_lower_x = screen_x2;
o_current->picture->screen_lower_y = screen_y2;
/* update the bounding picture - screen unit */
get_picture_bounds(w_current, o_current->picture,
&left, &top, &right, &bottom);
o_current->left = left;
o_current->top = top;
o_current->right = right;
o_current->bottom = bottom;
/* recalc OBJECT specific parameters */
o_object_recalc(w_current, o_current);
}
/*! \brief Get picture bounding rectangle.
* \par Function Description
* This function sets the <B>left</B>, <B>top</B>, <B>right</B> and
* <B>bottom</B> parameters to the boundings of the picture object described
* in <B>*picture</B> in SCREEN units.
*
* \param [in] w_current The TOPLEVEL object.
* \param [in] picture Picture OBJECT to read coordinates from.
* \param [out] left Left picture coordinate in SCREEN units.
* \param [out] top Top picture coordinate in SCREEN units.
* \param [out] right Right pircture coordinate in SCREEN units.
* \param [out] bottom Bottom picture coordinate in SCREEN units.
*/
void get_picture_bounds(TOPLEVEL *w_current, PICTURE *picture,
int *left, int *top, int *right, int *bottom)
{
*left = picture->screen_upper_x;
*top = picture->screen_upper_y;
*right = picture->screen_lower_x;
*bottom = picture->screen_lower_y;
}
/*! \brief Get picture bounding rectangle in WORLD coordinates.
* \par Function Description
* This function sets the <B>left</B>, <B>top</B>, <B>right</B> and
* <B>bottom</B> parameters to the boundings of the picture object
* described in <B>*picture</B> in WORLD units.
*
* \param [in] w_current The TOPLEVEL object.
* \param [in] picture Picture OBJECT to read coordinates from.
* \param [out] left Left picture coordinate in WORLD units.
* \param [out] top Top picture coordinate in WORLD units.
* \param [out] right Right picture coordinate in WORLD units.
* \param [out] bottom Bottom picture coordinate in WORLD units.
*/
void world_get_picture_bounds(TOPLEVEL *w_current, PICTURE *picture,
int *left, int *top, int *right, int *bottom)
{
/* pb20011002 - why using min and max here and not above ? */
*left = min(picture->upper_x, picture->lower_x);
*top = min(picture->upper_y, picture->lower_y);
*right = max(picture->upper_x, picture->lower_x);
*bottom = max(picture->upper_y, picture->lower_y);
/* PB : same as above here for width of edges */
#if DEBUG
printf("picture: %d %d %d %d\n", *left, *top, *right, *bottom);
#endif
}
/*! \brief Modify the description of a picture OBJECT.
* \par Function Description
* This function modifies the coordinates of one of the four corner of
* the picture. The new coordinates of the corner identified by
* <B>whichone</B> are given by <B>x</B> and <B>y</B> in world unit.
*
* The coordinates of the corner is modified in the world coordinate system.
* Screen coordinates and boundings are then updated.
*
* \param [in] w_current The TOPLEVEL object.
* \param [in,out] object Picture OBJECT to modify.
* \param [in] x New x coordinate.
* \param [in] y New y coordinate.
* \param [in] whichone Which picture parameter to modify.
*
* <B>whichone</B> can have the following values:
* <DL>
* <DT>*</DT><DD>PICTURE_UPPER_LEFT
* <DT>*</DT><DD>PICTURE_LOWER_LEFT
* <DT>*</DT><DD>PICTURE_UPPER_RIGHT
* <DT>*</DT><DD>PICTURE_LOWER_RIGHT
* </DL>
*
* \par Author's note
* pb20011002 - rewritten : old one did not used x, y and whichone
*/
void o_picture_modify(TOPLEVEL *w_current, OBJECT *object,
int x, int y, int whichone)
{
int tmp;
/* change the position of the selected corner */
switch(whichone) {
case PICTURE_UPPER_LEFT:
object->picture->upper_x = x;
tmp = abs(object->picture->upper_x - object->picture->lower_x) /
object->picture->ratio;
if (y < object->picture->lower_y) {
tmp = -tmp;
}
object->picture->upper_y = object->picture->lower_y + tmp;
break;
case PICTURE_LOWER_LEFT:
object->picture->upper_x = x;
tmp = abs(object->picture->upper_x - object->picture->lower_x) /
object->picture->ratio;
if (y > object->picture->upper_y) {
tmp = -tmp;
}
object->picture->lower_y = object->picture->upper_y - tmp;
break;
case PICTURE_UPPER_RIGHT:
object->picture->lower_x = x;
tmp = abs(object->picture->upper_x - object->picture->lower_x) /
object->picture->ratio;
if (y < object->picture->lower_y) {
tmp = -tmp;
}
object->picture->upper_y = object->picture->lower_y + tmp;
break;
case PICTURE_LOWER_RIGHT:
object->picture->lower_x = x;
tmp = abs(object->picture->upper_x - object->picture->lower_x) /
object->picture->ratio;
if (y > object->picture->upper_y) {
tmp = -tmp;
}
object->picture->lower_y = object->picture->upper_y - tmp;
break;
default:
return;
}
/* need to update the upper left and lower right corners */
if(object->picture->upper_x > object->picture->lower_x) {
tmp = object->picture->upper_x;
object->picture->upper_x = object->picture->lower_x;
object->picture->lower_x = tmp;
}
if(object->picture->upper_y < object->picture->lower_y) {
tmp = object->picture->upper_y;
object->picture->upper_y = object->picture->lower_y;
object->picture->lower_y = tmp;
}
/* recalculate the screen coords and the boundings */
o_picture_recalc(w_current, object);
}
/*! \brief Rotate a picture OBJECT.
* \par Function Description
* This function applies a rotation of center (<B>centerx</B>, <B>centery</B>)
* and angle <B>angle</B> to the picture object <B>*object</B>.
* The coordinates of the rotation center are in screen units.
* <B>angle</B> must be a 90 degree multiple. If not, no rotation is applied.
*
* The rotation is made with the #o_picture_rotate_world() function
* that perform a rotation of angle <B>angle</B> and center
* (<B>world_centerx</B>, <B>world_centery</B>) in world unit.
*
* \param [in] w_current The TOPLEVEL object.
* \param [in] centerx Rotation center x coordinate in SCREEN units.
* \param [in] centery Rotation center y coordinate in SCREEN units.
* \param [in] angle Rotation angle in degrees (unused).
* \param [in,out] object Picture OBJECT to rotate.
*
* \note
* takes in screen coordinates for the centerx,y, and then does the rotate
* in world space
* also ignores angle argument... for now, rotate only in 90 degree
* increments
* fixed to 90 degrees... it's *not* general now
*/
void o_picture_rotate(TOPLEVEL *w_current,
int centerx, int centery, int angle,
OBJECT *object)
{
int world_centerx, world_centery;
/* convert the center of rotation to world unit */
SCREENtoWORLD(w_current,
centerx, centery,
&world_centerx, &world_centery);
/* rotate the picture */
/* the check of the rotation angle is in o_picture_rotate_world() */
o_picture_rotate_world(w_current,
world_centerx, world_centery, angle,
object);
/* screen coords and boundings are updated by _rotate_world() */
}
/*! \brief Rotate picture OBJECT using WORLD coordinates.
* \par Function Description
* This function rotates the picture described by <B>*object</B> around
* the (<B>world_centerx</B>, <B>world_centery</B>) point by <B>angle</B>
* degrees.
* The center of rotation is in world units.
*
* \param [in] w_current The TOPLEVEL object.
* \param [in] world_centerx Rotation center x coordinate in
* WORLD units.
* \param [in] world_centery Rotation center y coordinate in
* WORLD units.
* \param [in] angle Rotation angle in degrees (See note below).
* \param [in,out] object Picture OBJECT to rotate.
*/
void o_picture_rotate_world(TOPLEVEL *w_current,
int world_centerx, int world_centery, int angle,
OBJECT *object)
{
int newx1, newy1;
int newx2, newy2;
/* Only 90 degree multiple and positive angles are allowed. */
/* angle must be positive */
if(angle < 0) angle = -angle;
/* angle must be a 90 multiple or no rotation performed */
if((angle % 90) != 0) return;
object->picture->angle = ( object->picture->angle + angle ) % 360;
/* The center of rotation (<B>world_centerx</B>, <B>world_centery</B>) is
* translated to the origin. The rotation of the upper left and lower
* right corner are then performed. Finally, the rotated picture is
* translated back to its previous location.
*/
/* translate object to origin */
object->picture->upper_x -= world_centerx;
object->picture->upper_y -= world_centery;
object->picture->lower_x -= world_centerx;
object->picture->lower_y -= world_centery;
/* rotate the upper left corner of the picture */
rotate_point_90(object->picture->upper_x, object->picture->upper_y, angle,
&newx1, &newy1);
/* rotate the lower left corner of the picture */
rotate_point_90(object->picture->lower_x, object->picture->lower_y, angle,
&newx2, &newy2);
/* reorder the corners after rotation */
object->picture->upper_x = min(newx1,newx2);
object->picture->upper_y = max(newy1,newy2);
object->picture->lower_x = max(newx1,newx2);
object->picture->lower_y = min(newy1,newy2);
/* translate object back to normal position */
object->picture->upper_x += world_centerx;
object->picture->upper_y += world_centery;
object->picture->lower_x += world_centerx;
object->picture->lower_y += world_centery;
/* recalc boundings and screen coords */
o_picture_recalc(w_current, object);
}
/*! \brief Mirror a picture.
* \par Function Description
* This function mirrors the picture from the point
* (<B>centerx</B>,<B>centery</B>) in screen unit.
*
* The origin of the mirror in screen unit is converted in world unit.
* The picture is mirrored with the function #o_picture_mirror_world()
* for which the origin of the mirror must be given in world unit.
*
* \param [in] w_current The TOPLEVEL object.
* \param [in] centerx Origin x coordinate in WORLD units.
* \param [in] centery Origin y coordinate in WORLD units.
* \param [in,out] object Picture OBJECT to mirror.
*/
void o_picture_mirror(TOPLEVEL *w_current,
int centerx, int centery,
OBJECT *object)
{
int world_centerx, world_centery;
/* convert the origin of mirror */
SCREENtoWORLD(w_current, centerx, centery,
&world_centerx,
&world_centery);
/* apply the mirror in world coords */
o_picture_mirror_world(w_current,
world_centerx, world_centery,
object);
/* screen coords and boundings are updated by _mirror_world() */
}
/*! \brief Mirror a picture using WORLD coordinates.
* \par Function Description
* This function mirrors the picture from the point
* (<B>world_centerx</B>,<B>world_centery</B>) in world unit.
*
* The picture is first translated to the origin, then mirrored and
* finally translated back at its previous position.
*
* \param [in] w_current The TOPLEVEL object.
* \param [in] world_centerx Origin x coordinate in WORLD units.
* \param [in] world_centery Origin y coordinate in WORLD units.
* \param [in,out] object Picture OBJECT to mirror.
*/
void o_picture_mirror_world(TOPLEVEL *w_current,
int world_centerx, int world_centery,
OBJECT *object)
{
int newx1, newy1;
int newx2, newy2;
/* Set info in object */
object->picture->mirrored = (object->picture->mirrored ^ 1) & 1;
/* translate object to origin */
object->picture->upper_x -= world_centerx;
object->picture->upper_y -= world_centery;
object->picture->lower_x -= world_centerx;
object->picture->lower_y -= world_centery;
/* mirror the corners */
newx1 = -object->picture->upper_x;
newy1 = object->picture->upper_y;
newx2 = -object->picture->lower_x;
newy2 = object->picture->lower_y;
/* reorder the corners */
object->picture->upper_x = min(newx1,newx2);
object->picture->upper_y = max(newy1,newy2);
object->picture->lower_x = max(newx1,newx2);
object->picture->lower_y = min(newy1,newy2);
/* translate back in position */
object->picture->upper_x += world_centerx;
object->picture->upper_y += world_centery;
object->picture->lower_x += world_centerx;
object->picture->lower_y += world_centery;
/* recalc boundings and screen coords */
o_picture_recalc(w_current, object);
}
/*! \brief Translate a picture position by a delta.
* \par Function Description
* This function applies a translation of (<B>dx</B>,<B>dy</B>) to the picture
* described by <B>*object</B>. <B>dx</B> and <B>dy</B> are in screen units.
*
* The translation vector is converted in world unit. The translation is
* made with #o_picture_translate_world().
*
* \param [in] w_current The TOPLEVEL object.
* \param [in] dx x distance to move.
* \param [in] dy y distance to move.
* \param [in,out] object Picture OBJECT to translate.
*/
void o_picture_translate(TOPLEVEL *w_current, int dx, int dy, OBJECT *object)
{
int world_dx, world_dy;
if (object == NULL) printf("bt NO!\n");
/* convert the translation vector in world unit */
world_dx = SCREENabs(w_current, dx);
world_dy = SCREENabs(w_current, dy);
/* translate the picture */
o_picture_translate_world(w_current, world_dx, world_dy, object);
/* screen coords and boundings are updated by _translate_world */
}
/*! \brief Translate a picture position in WORLD coordinates by a delta.
* \par Function Description
* This function applies a translation of (<B>x1</B>,<B>y1</B>) to the picture
* described by <B>*object</B>. <B>x1</B> and <B>y1</B> are in world units.
*
* \param [in] w_current The TOPLEVEL object.
* \param [in] x1 x distance to move.
* \param [in] y1 y distance to move.
* \param [in,out] object Picture OBJECT to translate.
*/
void o_picture_translate_world(TOPLEVEL *w_current,
int x1, int y1, OBJECT *object)
{
if (object == NULL) printf("btw NO!\n");
/* Do world coords */
object->picture->upper_x = object->picture->upper_x + x1;
object->picture->upper_y = object->picture->upper_y + y1;
object->picture->lower_x = object->picture->lower_x + x1;
object->picture->lower_y = object->picture->lower_y + y1;
/* recalc the screen coords and the bounding picture */
o_picture_recalc(w_current, object);
}
/*! \brief Create a copy of a picture.
* \par Function Description
* This function creates a verbatim copy of the object pointed by
* <B>o_current</B> describing a picture. The new object is added at the
* end of the list, following the <B>list_tail</B> pointed object.
*
* \param [in] w_current The TOPLEVEL object.
* \param [out] list_tail OBJECT list to copy to.
* \param [in] o_current Picture OBJECT to copy.
* \return A new pointer to the end of the object list.
*/
OBJECT *o_picture_copy(TOPLEVEL *w_current, OBJECT *list_tail,
OBJECT *o_current)
{
OBJECT *new_obj;
ATTRIB *a_current;
int color;
if (o_current->saved_color == -1) {
color = o_current->color;
} else {
color = o_current->saved_color;
}
/* A new picture object is added at the end of the object list with
* #o_picture_add(). Values for its fields are default and need to
* be modified.
*/
/* create and link a new picture object */
new_obj = o_picture_add(w_current, list_tail,
w_current->current_pixbuf,
w_current->pixbuf_filename,
w_current->pixbuf_wh_ratio,
OBJ_PICTURE,
0, 0, 0, 0, 0, FALSE, FALSE);
/* The dimensions of the new picture are set with the ones of the
* original picture. The two picturees have the same line type and
* the same filling options.
*
* The coordinates and the values in screen unit are computed with
* #o_picture_recalc().
*/
/* modifying */
/* pb20011002 - have to check if o_current is a picture object */
new_obj->picture->upper_x = o_current->picture->upper_x;
new_obj->picture->upper_y = o_current->picture->upper_y;
new_obj->picture->lower_x = o_current->picture->lower_x;
new_obj->picture->lower_y = o_current->picture->lower_y;
/* Copy the picture data */
new_obj->picture->original_picture =
gdk_pixbuf_scale_simple(o_current->picture->original_picture,
gdk_pixbuf_get_width (o_current->picture->original_picture),
gdk_pixbuf_get_height (o_current->picture->original_picture),
GDK_INTERP_BILINEAR);
new_obj->picture->displayed_picture =
gdk_pixbuf_scale_simple(o_current->picture->displayed_picture,
gdk_pixbuf_get_width (o_current->picture->displayed_picture),
gdk_pixbuf_get_height (o_current->picture->displayed_picture),
GDK_INTERP_BILINEAR);
new_obj->picture->ratio = o_current->picture->ratio;
new_obj->picture->filename = g_strdup(o_current->picture->filename);
new_obj->picture->angle = o_current->picture->angle;
new_obj->picture->mirrored = o_current->picture->mirrored;
o_picture_recalc(w_current, new_obj);
/* new_obj->attribute = 0;*/
a_current = o_current->attribs;
if (a_current) {
while ( a_current ) {
/* head attrib node has prev = NULL */
if (a_current->prev != NULL) {
a_current->copied_to = new_obj;
}
a_current = a_current->next;
}
}
/* return the new tail of the object list */
return(new_obj);
}
/*! \brief Get RGB data from image.
* \par Function Description
* This function returns the RGB data of the given image.
* Function taken from the DIA source code (http://www.gnome.org/projects/dia)
* and licensed under the GNU GPL version 2.
*
* \param [in] image GdkPixbuf image to read RGB data from.
* \return Array of rgb data from image.
*
* \note
* Caller must free returned guint8 array.
*/
guint8 *o_picture_rgb_data(GdkPixbuf *image)
{
int width = gdk_pixbuf_get_width(image);
int height = gdk_pixbuf_get_height(image);
int rowstride = gdk_pixbuf_get_rowstride(image);
int size = height*rowstride;
guint8 *rgb_pixels = g_malloc(size);
if (gdk_pixbuf_get_has_alpha(image)) {
guint8 *pixels = gdk_pixbuf_get_pixels(image);
int i, j;
for (i = 0; i < height; i++) {
for (j = 0; j < width; j++) {
rgb_pixels[i*rowstride+j*3] = pixels[i*rowstride+j*4];
rgb_pixels[i*rowstride+j*3+1] = pixels[i*rowstride+j*4+1];
rgb_pixels[i*rowstride+j*3+2] = pixels[i*rowstride+j*4+2];
}
}
return rgb_pixels;
} else {
guint8 *pixels = gdk_pixbuf_get_pixels(image);
g_memmove(rgb_pixels, pixels, height*rowstride);
return rgb_pixels;
}
}
/*! \brief Get mask data from image.
* \par Function Description
* This function returns the mask data of the given image.
* Function taken from the DIA source code (http://www.gnome.org/projects/dia)
* and licensed under the GNU GPL version 2.
*
* \param [in] image GdkPixbuf image to get mask data from.
* \return Array of mask data from image.
*
* \note
* Caller must free returned guint8 array.
*/
guint8 *o_picture_mask_data(GdkPixbuf *image)
{
guint8 *pixels;
guint8 *mask;
int i, size;
if (!gdk_pixbuf_get_has_alpha(image)) {
return NULL;
}
pixels = gdk_pixbuf_get_pixels(image);
size = gdk_pixbuf_get_width(image)*
gdk_pixbuf_get_height(image);
mask = g_malloc(size);
/* Pick every fourth byte (the alpha channel) into mask */
for (i = 0; i < size; i++)
mask[i] = pixels[i*4+3];
return mask;
}
/*! \brief Print picture to Postscript document.
* \par Function Description
* This function prints a picture object. The picture is defined by the
* coordinates of its upper left corner in (<B>x</B>,<B>y</B>) and its width
* and height given by the <B>width</B> and <B>height</B> parameters.
* The Postscript document is defined by the file pointer <B>fp</B>.
* Function based on the DIA source code (http://www.gnome.org/projects/dia)
* and licensed under the GNU GPL version 2.
*
* All dimensions are in mils.
*
* \param [in] w_current The TOPLEVEL object.
* \param [in] fp FILE pointer to Postscript document.
* \param [in] o_current Picture OBJECT to write to document.
* \param [in] origin_x Page x coordinate to place picture OBJECT.
* \param [in] origin_y Page y coordinate to place picture OBJECT.
*/
void o_picture_print(TOPLEVEL *w_current, FILE *fp, OBJECT *o_current,
int origin_x, int origin_y)
{
int x1, y1, x, y;
int height, width;
GdkPixbuf* image = o_current->picture->displayed_picture;
int img_width, img_height, img_rowstride;
double ratio;
guint8 *rgb_data;
guint8 *mask_data;
/* calculate the width and height of the box */
width = abs(o_current->picture->lower_x - o_current->picture->upper_x);
height = abs(o_current->picture->upper_y - o_current->picture->lower_y);
/* calculate the origin of the box */
x1 = o_current->picture->upper_x;
y1 = o_current->picture->upper_y;
img_width = gdk_pixbuf_get_width(image);
img_rowstride = gdk_pixbuf_get_rowstride(image);
img_height = gdk_pixbuf_get_height(image);
rgb_data = o_picture_rgb_data(image);
mask_data = o_picture_mask_data(image);
ratio = height/width;
fprintf(fp, "gsave\n");
/* color output only */
fprintf(fp, "/pix %i string def\n", img_width * 3);
fprintf(fp, "%i %i 8\n", img_width, img_height);
fprintf(fp, "%i %i translate\n", x1, y1);
fprintf(fp, "%i %i scale\n", width, height);
fprintf(fp, "[%i 0 0 -%i 0 0]\n", img_width, img_height);
fprintf(fp, "{currentfile pix readhexstring pop}\n");
fprintf(fp, "false 3 colorimage\n");
fprintf(fp, "\n");
if (mask_data) {
for (y = 0; y < img_height; y++) {
for (x = 0; x < img_width; x++) {
int i = y*img_rowstride+x*3;
int m = y*img_width+x;
fprintf(fp, "%02x", 255-(mask_data[m]*(255-rgb_data[i])/255));
fprintf(fp, "%02x", 255-(mask_data[m]*(255-rgb_data[i+1])/255));
fprintf(fp, "%02x", 255-(mask_data[m]*(255-rgb_data[i+2])/255));
}
fprintf(fp, "\n");
}
} else {
for (y = 0; y < img_height; y++) {
for (x = 0; x < img_width; x++) {
int i = y*img_rowstride+x*3;
fprintf(fp, "%02x", (int)(rgb_data[i]));
fprintf(fp, "%02x", (int)(rgb_data[i+1]));
fprintf(fp, "%02x", (int)(rgb_data[i+2]));
}
fprintf(fp, "\n");
}
}
fprintf(fp, "grestore\n");
fprintf(fp, "\n");
g_free(rgb_data);
g_free(mask_data);
}
#endif
1.21 +704 -457 eda/geda/gaf/libgeda/src/o_pin_basic.c
(In the diff below, changes in quantity of whitespace are not shown.)
Index: o_pin_basic.c
===================================================================
RCS file: o_pin_basic.c
diff -N o_pin_basic.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ o_pin_basic.c 5 Jul 2006 03:13:38 -0000 1.21
@@ -0,0 +1,804 @@
+/* gEDA - GPL Electronic Design Automation
+ * libgeda - gEDA's library
+ * Copyright (C) 1998-2000 Ales V. Hvezda
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+#include <config.h>
+
+#include <stdio.h>
+#include <math.h>
+
+#include <gtk/gtk.h>
+#include <libguile.h>
+
+#ifdef HAS_LIBGDGEDA
+#include <gdgeda/gd.h>
+#endif
+
+#include "defines.h"
+#include "struct.h"
+#include "globals.h"
+#include "o_types.h"
+#include "colors.h"
+#include "funcs.h"
+
+#include "../include/prototype.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void get_pin_bounds(TOPLEVEL *w_current, LINE *line, int *left, int *top,
+ int *right, int *bottom)
+{
+ *left = w_current->width;
+ *top = w_current->height;
+ *right = 0;
+ *bottom = 0;
+
+ if (line->screen_x[0] < *left) *left = line->screen_x[0];
+ if (line->screen_x[0] > *right) *right = line->screen_x[0];
+ if (line->screen_y[0] < *top) *top = line->screen_y[0];
+ if (line->screen_y[0] > *bottom) *bottom = line->screen_y[0];
+
+ if (line->screen_x[1] < *left) *left = line->screen_x[1];
+ if (line->screen_x[1] > *right) *right = line->screen_x[1];
+ if (line->screen_y[1] < *top) *top = line->screen_y[1];
+ if (line->screen_y[1] > *bottom) *bottom = line->screen_y[1];
+
+ *left = *left - 4;
+ *top = *top - 4;
+
+ *right = *right + 4;
+ *bottom = *bottom + 4;
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void world_get_pin_bounds(TOPLEVEL *w_current, LINE *line, int *left, int *top,
+ int *right, int *bottom)
+{
+ *left = w_current->init_right;
+ *top = w_current->init_bottom;
+ *right = 0;
+ *bottom = 0;
+
+ if (line->x[0] < *left) *left = line->x[0];
+ if (line->x[0] > *right) *right = line->x[0];
+ if (line->y[0] < *top) *top = line->y[0];
+ if (line->y[0] > *bottom) *bottom = line->y[0];
+
+ if (line->x[1] < *left) *left = line->x[1];
+ if (line->x[1] > *right) *right = line->x[1];
+ if (line->y[1] < *top) *top = line->y[1];
+ if (line->y[1] > *bottom) *bottom = line->y[1];
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+OBJECT *o_pin_add(TOPLEVEL *w_current, OBJECT *object_list,
+ char type, int color,
+ int x1, int y1, int x2, int y2, int pin_type, int whichend)
+{
+ int screen_x, screen_y;
+ int left, right, top, bottom;
+ OBJECT *new_node;
+
+ new_node = s_basic_init_object("pin");
+ new_node->type = type;
+ new_node->color = color;
+
+ new_node->line = (LINE *) malloc(sizeof(LINE));
+
+ new_node->line->x[0] = x1;
+ new_node->line->y[0] = y1;
+ new_node->line->x[1] = x2;
+ new_node->line->y[1] = y2;
+
+ WORLDtoSCREEN(w_current,
+ new_node->line->x[0], new_node->line->y[0],
+ &screen_x,
+ &screen_y);
+
+ new_node->line->screen_x[0] = screen_x;
+ new_node->line->screen_y[0] = screen_y;
+
+ WORLDtoSCREEN(w_current,
+ new_node->line->x[1], new_node->line->y[1],
+ &screen_x,
+ &screen_y);
+
+ new_node->line->screen_x[1] = screen_x;
+ new_node->line->screen_y[1] = screen_y;
+
+ get_pin_bounds(w_current, new_node->line, &left, &top, &right, &bottom);
+
+ new_node->left = left;
+ new_node->top = top;
+ new_node->right = right;
+ new_node->bottom = bottom;
+
+ /*! \todo questionable cast */
+ new_node->draw_func = (void *) pin_draw_func;
+ /*! \todo questionable cast */
+ new_node->sel_func = (void *) select_func;
+
+ new_node->pin_type = pin_type;
+ new_node->whichend = whichend;
+
+ object_list = (OBJECT *) s_basic_link_object(new_node, object_list);
+
+ /* this mod causes shadow pins to appear at 0,0 if you copy a complex
+ * that has pins...
+ * This mod was added so that you could draw pins to nets and have
+ * the dangling cue go away
+ * There is a complementary one in o_nets, but it doesn't work
+ * completely either... hack */
+#if 0
+ /* ifed out 3/15/98 due to above */
+ if (!adding_sel) {
+ o_pin_conn_recalc(w_current, object_list); /* old conn system */
+ /*o_net_conn_recalc(object_list); */
+ }
+#endif
+
+
+ if (!w_current->ADDING_SEL) {
+ s_tile_add_object(w_current, object_list,
+ new_node->line->x[0], new_node->line->y[0],
+ new_node->line->x[1], new_node->line->y[1]);
+ s_conn_update_object(w_current, object_list);
+ }
+
+ return(object_list);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void o_pin_recalc(TOPLEVEL *w_current, OBJECT *o_current)
+{
+ int screen_x1, screen_y1;
+ int screen_x2, screen_y2;
+ int left, right, top, bottom;
+
+ if (o_current->line == NULL) {
+ return;
+ }
+
+
+ WORLDtoSCREEN(w_current, o_current->line->x[0],
+ o_current->line->y[0],
+ &screen_x1,
+ &screen_y1);
+
+ o_current->line->screen_x[0] = screen_x1;
+ o_current->line->screen_y[0] = screen_y1;
+
+ WORLDtoSCREEN(w_current, o_current->line->x[1],
+ o_current->line->y[1],
+ &screen_x2,
+ &screen_y2);
+
+ o_current->line->screen_x[1] = screen_x2;
+ o_current->line->screen_y[1] = screen_y2;
+
+ get_pin_bounds(w_current, o_current->line, &left, &top, &right, &bottom);
+
+ o_current->left = left;
+ o_current->top = top;
+ o_current->right = right;
+ o_current->bottom = bottom;
+
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+OBJECT *o_pin_read(TOPLEVEL *w_current, OBJECT *object_list, char buf[],
+ unsigned int release_ver, unsigned int fileformat_ver)
+{
+ char type;
+ int x1, y1;
+ int x2, y2;
+ int d_x1, d_y1;
+ int d_x2, d_y2;
+ int color;
+ int pin_type;
+ int whichend;
+
+ if(release_ver <= VERSION_20020825) {
+ sscanf(buf, "%c %d %d %d %d %d\n", &type, &x1, &y1, &x2, &y2, &color);
+ pin_type = PIN_TYPE_NET;
+ whichend = -1;
+ } else {
+ sscanf(buf, "%c %d %d %d %d %d %d %d\n", &type, &x1, &y1, &x2, &y2,
+ &color, &pin_type, &whichend);
+ }
+
+ if (whichend == -1) {
+ fprintf(stderr,
+ "Found a pin which did not have the whichone field set.\nVerify and correct manually.\n");
+ s_log_message("Found a pin which did not have the whichone field set.\nVerify and correct manully.\n");
+ } else if (whichend < -1 || whichend > 1) {
+ fprintf(stderr,
+ "Found an invalid whichend on a pin (reseting to zero): %d\n",
+ whichend);
+ s_log_message("Found an invalid whichend on a pin (reseting to zero): %d\n",
+ whichend);
+ whichend = 0;
+ }
+
+ d_x1 = x1;
+ d_y1 = y1;
+ d_x2 = x2;
+ d_y2 = y2;
+
+ if (x1 == x2 && y1 == y2) {
+ fprintf(stderr, "Found a zero length pin: [ %s ]\n", buf);
+ s_log_message("Found a zero length pin: [ %s ]\n", buf);
+ }
+
+ if (color < 0 || color > MAX_COLORS) {
+ fprintf(stderr, "Found an invalid color [ %s ]\n", buf);
+ s_log_message("Found an invalid color [ %s ]\n", buf);
+ s_log_message("Setting color to WHITE\n");
+ color = WHITE;
+ }
+
+ if (w_current->override_pin_color != -1) {
+ color = w_current->override_pin_color;
+ }
+
+ object_list = o_pin_add(w_current, object_list, type, color, d_x1, d_y1,
+ d_x2, d_y2, pin_type, whichend);
+ return(object_list);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+char *o_pin_save(OBJECT *object)
+{
+ int x1, x2, y1, y2;
+ int color;
+ int pin_type, whichend;
+ char *buf;
+
+ x1 = object->line->x[0];
+ y1 = object->line->y[0];
+ x2 = object->line->x[1];
+ y2 = object->line->y[1];
+
+ /* Use the right color */
+ if (object->saved_color == -1) {
+ color = object->color;
+ } else {
+ color = object->saved_color;
+ }
+
+ pin_type = object->pin_type;
+ whichend = object->whichend;
+
+ buf = g_strdup_printf("%c %d %d %d %d %d %d %d", object->type,
+ x1, y1, x2, y2, color, pin_type, whichend);
+ return(buf);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void o_pin_translate(TOPLEVEL *w_current, int dx, int dy, OBJECT *object)
+{
+ int x, y;
+
+ if (object == NULL) printf("pt NO!\n");
+
+
+ /* Do screen coords */
+ object->line->screen_x[0] = object->line->screen_x[0] + dx;
+ object->line->screen_y[0] = object->line->screen_y[0] + dy;
+ object->line->screen_x[1] = object->line->screen_x[1] + dx;
+ object->line->screen_y[1] = object->line->screen_y[1] + dy;
+
+ /* do we want snap grid here? */
+ SCREENtoWORLD(w_current, object->line->screen_x[0],
+ object->line->screen_y[0],
+ &x,
+ &y);
+
+ object->line->x[0] = snap_grid(w_current, x);
+ object->line->y[0] = snap_grid(w_current, y);
+
+ SCREENtoWORLD(w_current, object->line->screen_x[1],
+ object->line->screen_y[1],
+ &x,
+ &y);
+
+ object->line->x[1] = snap_grid(w_current, x);
+ object->line->y[1] = snap_grid(w_current, y);
+
+ s_tile_update_object(w_current, object);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void o_pin_translate_world(TOPLEVEL *w_current, int x1, int y1, OBJECT *object)
+{
+ int screen_x1, screen_y1;
+ int screen_x2, screen_y2;
+ int left, right, top, bottom;
+
+ if (object == NULL) printf("ptw NO!\n");
+
+
+ /* Do world coords */
+ object->line->x[0] = object->line->x[0] + x1;
+ object->line->y[0] = object->line->y[0] + y1;
+ object->line->x[1] = object->line->x[1] + x1;
+ object->line->y[1] = object->line->y[1] + y1;
+
+ /* update screen coords */
+ WORLDtoSCREEN(w_current, object->line->x[0],
+ object->line->y[0],
+ &screen_x1,
+ &screen_y1);
+
+ object->line->screen_x[0] = screen_x1;
+ object->line->screen_y[0] = screen_y1;
+
+ WORLDtoSCREEN(w_current, object->line->x[1],
+ object->line->y[1],
+ &screen_x2,
+ &screen_y2);
+
+ object->line->screen_x[1] = screen_x2;
+ object->line->screen_y[1] = screen_y2;
+
+ /* update bounding box */
+ get_pin_bounds(w_current, object->line, &left, &top, &right, &bottom);
+
+ object->left = left;
+ object->top = top;
+ object->right = right;
+ object->bottom = bottom;
+
+ s_tile_update_object(w_current, object);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+OBJECT *o_pin_copy(TOPLEVEL *w_current, OBJECT *list_tail, OBJECT *o_current)
+{
+ OBJECT *new_obj;
+ ATTRIB *a_current;
+ int color;
+
+ if (o_current->saved_color == -1) {
+ color = o_current->color;
+ } else {
+ color = o_current->saved_color;
+ }
+
+ new_obj = o_pin_add(w_current, list_tail, OBJ_PIN, color,
+ o_current->line->x[0], o_current->line->y[0],
+ o_current->line->x[1], o_current->line->y[1],
+ o_current->pin_type, o_current->whichend);
+
+ /* why is this here ? */
+ /* because they all have it, and it is used during outline actions */
+ new_obj->line->screen_x[0] = o_current->line->screen_x[0];
+ new_obj->line->screen_y[0] = o_current->line->screen_y[0];
+ new_obj->line->screen_x[1] = o_current->line->screen_x[1];
+ new_obj->line->screen_y[1] = o_current->line->screen_y[1];
+
+
+ new_obj->line->x[0] = o_current->line->x[0];
+ new_obj->line->y[0] = o_current->line->y[0];
+ new_obj->line->x[1] = o_current->line->x[1];
+ new_obj->line->y[1] = o_current->line->y[1];
+
+ /* new_obj->attribute = 0;*/
+ a_current = o_current->attribs;
+ if (a_current) {
+ while ( a_current ) {
+
+ /* head attrib node has prev = NULL */
+ if (a_current->prev != NULL) {
+ a_current->copied_to = new_obj;
+ }
+ a_current = a_current->next;
+ }
+ }
+
+ return(new_obj);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void o_pin_print(TOPLEVEL *w_current, FILE *fp, OBJECT *o_current,
+ int origin_x, int origin_y)
+{
+ int pin_width;
+ int x1, y1;
+ int x2, y2;
+
+ if (o_current == NULL) {
+ printf("got null in o_pin_print\n");
+ return;
+ }
+
+ if (w_current->print_color) {
+ f_print_set_color(fp, o_current->color);
+ }
+
+ x1 = o_current->line->x[0] - origin_x;
+ y1 = o_current->line->y[0] - origin_y;
+ x2 = o_current->line->x[1] - origin_x;
+ y2 = o_current->line->y[1] - origin_y;
+ pin_width = 2;
+ if(w_current->pin_style == THICK) {
+ pin_width = PIN_WIDTH;
+ }
+
+ fprintf(fp, "%d %d %d %d %d line\n",x1,y1,x2,y2,pin_width);
+
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void o_pin_image_write(TOPLEVEL *w_current, OBJECT *o_current,
+ int origin_x, int origin_y, int color_mode)
+{
+ int color;
+
+ if (o_current == NULL) {
+ printf("got null in o_pin_image_write\n");
+ return;
+ }
+
+ if (color_mode == TRUE) {
+ color = o_image_geda2gd_color(o_current->color);
+ } else {
+ color = image_black;
+ }
+
+ /* assumes screen coords are already calculated correctly */
+#ifdef HAS_LIBGDGEDA
+
+ if (w_current->pin_style == THICK) {
+ gdImageSetThickness(current_im_ptr, SCREENabs(w_current,
+ PIN_WIDTH));
+ } else {
+ gdImageSetThickness(current_im_ptr, 0);
+ }
+
+ gdImageLine(current_im_ptr,
+ o_current->line->screen_x[0],
+ o_current->line->screen_y[0],
+ o_current->line->screen_x[1],
+ o_current->line->screen_y[1],
+ color);
+#endif
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void o_pin_rotate(TOPLEVEL *w_current, int centerx, int centery, int angle,
+ OBJECT *object)
+{
+ int world_centerx, world_centery;
+ int newx, newy;
+
+ SCREENtoWORLD(w_current, centerx, centery,
+ &world_centerx,
+ &world_centery);
+
+ /* translate object to origin */
+ o_pin_translate_world(w_current, -world_centerx, -world_centery, object);
+
+ rotate_point_90(object->line->x[0], object->line->y[0], angle,
+ &newx, &newy);
+
+ object->line->x[0] = newx;
+ object->line->y[0] = newy;
+
+ rotate_point_90(object->line->x[1], object->line->y[1], angle,
+ &newx, &newy);
+
+ object->line->x[1] = newx;
+ object->line->y[1] = newy;
+
+ o_pin_translate_world(w_current, world_centerx, world_centery, object);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void o_pin_rotate_world(TOPLEVEL *w_current, int world_centerx,
+ int world_centery, int angle,
+ OBJECT *object)
+{
+ int newx, newy;
+
+ if (angle == 0)
+ return;
+
+ /* translate object to origin */
+ o_pin_translate_world(w_current, -world_centerx, -world_centery, object);
+
+ rotate_point_90(object->line->x[0], object->line->y[0], angle,
+ &newx, &newy);
+
+ object->line->x[0] = newx;
+ object->line->y[0] = newy;
+
+ rotate_point_90(object->line->x[1], object->line->y[1], angle,
+ &newx, &newy);
+
+ object->line->x[1] = newx;
+ object->line->y[1] = newy;
+
+ o_pin_translate_world(w_current, world_centerx, world_centery, object);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void o_pin_mirror(TOPLEVEL *w_current,
+ int centerx, int centery, OBJECT *object)
+{
+ int world_centerx, world_centery;
+
+ SCREENtoWORLD(w_current, centerx, centery,
+ &world_centerx,
+ &world_centery);
+
+ /* translate object to origin */
+ o_pin_translate_world(w_current, -world_centerx, -world_centery, object);
+
+ object->line->x[0] = -object->line->x[0];
+
+ object->line->x[1] = -object->line->x[1];
+
+ o_pin_translate_world(w_current, world_centerx, world_centery, object);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void o_pin_mirror_world(TOPLEVEL *w_current,
+ int world_centerx, int world_centery, OBJECT *object)
+{
+ /* translate object to origin */
+ o_pin_translate_world(w_current, -world_centerx, -world_centery, object);
+
+ object->line->x[0] = -object->line->x[0];
+
+ object->line->x[1] = -object->line->x[1];
+
+ o_pin_translate_world(w_current, world_centerx, world_centery, object);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void o_pin_modify(TOPLEVEL *w_current, OBJECT *object,
+ int x, int y, int whichone)
+{
+ int screen_x, screen_y;
+ int left, right, top, bottom;
+
+ object->line->x[whichone] = x;
+ object->line->y[whichone] = y;
+
+ WORLDtoSCREEN(w_current,
+ object->line->x[whichone],
+ object->line->y[whichone],
+ &screen_x, &screen_y);
+
+ object->line->screen_x[whichone] = screen_x;
+ object->line->screen_y[whichone] = screen_y;
+
+ get_pin_bounds(w_current, object->line, &left, &top, &right, &bottom);
+
+ object->left = left;
+ object->top = top;
+ object->right = right;
+ object->bottom = bottom;
+
+ s_tile_update_object(w_current, object);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void o_pin_update_whichend(TOPLEVEL *w_current,
+ OBJECT *object_list, int num_pins)
+{
+ OBJECT *o_current;
+ int top, left;
+ int right, bottom;
+ int d1, d2, d3, d4;
+ int min0, min1;
+ int min0_whichend, min1_whichend;
+ int rleft, rtop, rright, rbottom;
+
+ if (object_list && num_pins) {
+ if (num_pins == 1 || w_current->force_boundingbox) {
+ world_get_complex_bounds(w_current, object_list,
+ &left, &top, &right, &bottom);
+ } else {
+ left = rleft = w_current->init_right;
+ top = rtop = w_current->init_bottom;;
+ right = rright = 0;
+ bottom = rbottom = 0;
+
+ /* only look at the pins to calculate bounds of the symbol */
+ o_current = object_list;
+ while (o_current != NULL) {
+ if (o_current->type == OBJ_PIN) {
+ world_get_pin_bounds(w_current, o_current->line,
+ &rleft, &rtop, &rright, &rbottom);
+ }
+
+ if (rleft < left) left = rleft;
+ if (rtop < top) top = rtop;
+ if (rright > right) right = rright;
+ if (rbottom > bottom) bottom = rbottom;
+
+ o_current=o_current->next;
+ }
+
+
+ }
+ } else {
+ return;
+ }
+
+ o_current = object_list;
+ while (o_current != NULL) {
+ if (o_current->type == OBJ_PIN && o_current->whichend == -1) {
+ if (o_current->line->y[0] == o_current->line->y[1]) {
+ /* horizontal */
+
+ if (o_current->line->x[0] == left) {
+ o_current->whichend = 0;
+ } else if (o_current->line->x[1] == left) {
+ o_current->whichend = 1;
+ } else if (o_current->line->x[0] == right) {
+ o_current->whichend = 0;
+ } else if (o_current->line->x[1] == right) {
+ o_current->whichend = 1;
+ } else {
+
+ d1 = abs(o_current->line->x[0] - left);
+ d2 = abs(o_current->line->x[1] - left);
+ d3 = abs(o_current->line->x[0] - right);
+ d4 = abs(o_current->line->x[1] - right);
+
+ if (d1 <= d2) {
+ min0 = d1;
+ min0_whichend = 0;
+ } else {
+ min0 = d2;
+ min0_whichend = 1;
+ }
+
+ if (d3 <= d4) {
+ min1 = d3;
+ min1_whichend = 0;
+ } else {
+ min1 = d4;
+ min1_whichend = 1;
+ }
+
+ if (min0 <= min1) {
+ o_current->whichend = min0_whichend;
+ } else {
+ o_current->whichend = min1_whichend;
+ }
+ }
+
+ } else if (o_current->line->x[0] == o_current->line->x[1]) {
+ /* vertical */
+
+ if (o_current->line->y[0] == top) {
+ o_current->whichend = 0;
+ } else if (o_current->line->y[1] == top) {
+ o_current->whichend = 1;
+ } else if (o_current->line->x[0] == bottom) {
+ o_current->whichend = 0;
+ } else if (o_current->line->x[1] == bottom) {
+ o_current->whichend = 1;
+ } else {
+
+ d1 = abs(o_current->line->y[0] - top);
+ d2 = abs(o_current->line->y[1] - top);
+ d3 = abs(o_current->line->y[0] - bottom);
+ d4 = abs(o_current->line->y[1] - bottom);
+
+ if (d1 <= d2) {
+ min0 = d1;
+ min0_whichend = 0;
+ } else {
+ min0 = d2;
+ min0_whichend = 1;
+ }
+
+ if (d3 <= d4) {
+ min1 = d3;
+ min1_whichend = 0;
+ } else {
+ min1 = d4;
+ min1_whichend = 1;
+ }
+
+ if (min0 <= min1) {
+ o_current->whichend = min0_whichend;
+ } else {
+ o_current->whichend = min1_whichend;
+ }
+ }
+ }
+ }
+ o_current = o_current->next;
+ }
+}
1.6 +304 -226 eda/geda/gaf/libgeda/src/o_selection.c
(In the diff below, changes in quantity of whitespace are not shown.)
Index: o_selection.c
===================================================================
RCS file: o_selection.c
diff -N o_selection.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ o_selection.c 5 Jul 2006 03:13:38 -0000 1.6
@@ -0,0 +1,387 @@
+/* gEDA - GPL Electronic Design Automation
+ * libgeda - gEDA's library
+ * Copyright (C) 1998-2000 Ales V. Hvezda
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+#include <config.h>
+
+#include <stdio.h>
+#include <ctype.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_ASSERT_H
+#include <assert.h>
+#endif
+#ifndef HAVE_VSNPRINTF
+#include <stdarg.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <libguile.h>
+
+#include "defines.h"
+#include "struct.h"
+#include "defines.h"
+#include "globals.h"
+#include "o_types.h"
+#include "colors.h"
+
+#include "../include/prototype.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+SELECTION *o_selection_return_tail(SELECTION *head)
+{
+ SELECTION *s_current=NULL;
+ SELECTION *ret_struct=NULL;
+
+ s_current = head;
+ while ( s_current != NULL ) { /* goto end of list */
+ ret_struct = s_current;
+ s_current = s_current->next;
+ }
+
+ return(ret_struct);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+SELECTION *o_selection_return_head(SELECTION *tail)
+{
+ SELECTION *s_current=NULL;
+ SELECTION *ret_struct=NULL;
+
+ s_current = tail;
+ while ( s_current != NULL ) { /* goto end of list */
+ ret_struct = s_current;
+ s_current = s_current->prev;
+ }
+
+ return(ret_struct);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+SELECTION *o_selection_new_head(void)
+{
+ SELECTION *s_new;
+
+ s_new = (SELECTION *) malloc(sizeof(SELECTION));
+ s_new->selected_object = NULL;
+ s_new->prev = NULL;
+ s_new->next = NULL;
+
+ return(s_new);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void o_selection_destroy_head(SELECTION *s_head)
+{
+ free(s_head);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+/* also does the needed work to make the object visually selected */
+SELECTION *o_selection_add(SELECTION *head, OBJECT *o_selected)
+{
+ SELECTION *tail;
+ SELECTION *s_new;
+
+ s_new = (SELECTION *) malloc(sizeof(SELECTION));
+
+ if (o_selected != NULL) {
+ s_new->selected_object = o_selected;
+ } else {
+ fprintf(stderr, "Got NULL passed to o_selection_new\n");
+ }
+
+ o_selection_select(o_selected, SELECT_COLOR);
+
+ if (head == NULL) {
+ s_new->prev = NULL; /* setup previous link */
+ s_new->next = NULL;
+ return(s_new);
+ } else {
+ tail = o_selection_return_tail(head);
+ s_new->prev = tail; /* setup previous link */
+ s_new->next = NULL;
+ tail->next = s_new;
+ return(tail->next);
+ }
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+/* it's okay to call this with an o_selected which is not necessarily */
+/* selected */
+void o_selection_remove(SELECTION *head, OBJECT *o_selected)
+{
+ SELECTION *s_current;
+
+ if (o_selected == NULL) {
+ fprintf(stderr, "Got NULL for o_selected in o_selection_remove\n");
+ return;
+ }
+
+ s_current = head;
+
+ while (s_current != NULL) {
+ if (s_current->selected_object == o_selected) {
+ if (s_current->next)
+ s_current->next->prev = s_current->prev;
+ else
+ s_current->next = NULL;
+
+ if (s_current->prev)
+ s_current->prev->next = s_current->next;
+ else
+ s_current->prev = NULL;
+
+ o_selection_unselect(s_current->selected_object);
+
+ s_current->selected_object = NULL;
+ free(s_current);
+ return;
+ }
+ s_current = s_current->next;
+ }
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+/* removes all but the head node */
+void o_selection_remove_most(TOPLEVEL *w_current, SELECTION *head)
+{
+ SELECTION *s_current;
+ SELECTION *s_prev;
+
+ s_current = o_selection_return_tail(head);
+
+ while (s_current != NULL) {
+ if (s_current->selected_object != NULL) {
+ s_prev = s_current->prev;
+
+ o_selection_unselect(s_current->selected_object);
+
+ o_redraw_single(w_current,
+ s_current->selected_object);
+
+ s_current->selected_object = NULL;
+ free(s_current);
+ s_current = s_prev;
+ } else {
+ break;
+ }
+ }
+
+ /* clear out any dangling pointers */
+ head->next=NULL;
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void o_selection_print_all( SELECTION *head )
+{
+ SELECTION *s_current;
+
+ s_current = head;
+
+ printf("START printing selection ********************\n");
+ while(s_current != NULL) {
+ if (s_current->selected_object) {
+ printf("Selected object: %d\n",
+ s_current->selected_object->sid);
+ }
+ s_current = s_current->next;
+ }
+ printf("DONE printing selection ********************\n");
+ printf("\n");
+
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void o_selection_destroy_all(SELECTION *head)
+{
+ SELECTION *s_current;
+ SELECTION *s_prev;
+
+ s_current = o_selection_return_tail(head);
+
+ while (s_current != NULL) {
+ s_prev = s_current->prev;
+ s_current->selected_object = NULL;
+ free(s_current);
+ s_current = s_prev;
+ }
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+/* this sets the select flag, saves the color, and then sets the color */
+void o_selection_select(OBJECT *object, int color)
+{
+ if (object->selected == TRUE) {
+ printf("object already selected == TRUE\n");
+ return;
+ }
+
+ if (object->saved_color != -1) {
+ printf("object already saved_color != -1\n");
+ return;
+ }
+
+ object->selected = TRUE;
+ object->draw_grips = TRUE;
+ object->saved_color = object->color;
+ object->color = color;
+ if (object->type == OBJ_COMPLEX || object->type == OBJ_PLACEHOLDER) {
+ o_complex_set_color_save(object->complex->prim_objs, color);
+ } else if (object->type == OBJ_TEXT) {
+ o_complex_set_color_save(object->text->prim_objs, color);
+ }
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+/* this unsets the select flag and restores the original color */
+/* this function should not be called by anybody outside of this file */
+void o_selection_unselect(OBJECT *object)
+{
+ object->selected = FALSE;
+ /* object->draw_grips = FALSE; can't do this here... */
+ /* draw_grips is cleared in the individual draw functions after the */
+ /* grips are erase */
+ object->color = object->saved_color;
+ if (object->type == OBJ_COMPLEX || object->type == OBJ_PLACEHOLDER) {
+ o_complex_unset_color(object->complex->prim_objs);
+ } else if (object->type == OBJ_TEXT) {
+ o_complex_unset_color(object->text->prim_objs);
+ }
+
+ object->saved_color = -1;
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+OBJECT *o_selection_return_first_object(SELECTION *head)
+{
+ if (!head)
+ return(NULL);
+
+ if (!head->next)
+ return(NULL);
+
+ if (!head->next->selected_object)
+ return(NULL);
+
+ return(head->next->selected_object);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+/* Nth starts counting a ZERO */
+/* doesn't consider the head node an object */
+OBJECT *o_selection_return_nth_object(SELECTION *head, int count)
+{
+ int internal_counter = 0;
+ SELECTION *s_current;
+
+ s_current = head->next;
+
+ while (s_current != NULL) {
+ if (internal_counter == count) {
+ if (s_current->selected_object) {
+ return(s_current->selected_object);
+ }
+ }
+ internal_counter++;
+
+ s_current = s_current->next;
+ }
+ return(NULL);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+int o_selection_return_num(SELECTION *head)
+{
+ int counter = 0;
+ SELECTION *s_current;
+
+ if (!head) {
+ return 0;
+ }
+
+ /* skip over head */
+ s_current = head->next;
+
+ while (s_current != NULL) {
+ counter++;
+ s_current = s_current->next;
+ }
+
+ return(counter);
+}
1.19 +2300 -1979eda/geda/gaf/libgeda/src/o_text_basic.c
(In the diff below, changes in quantity of whitespace are not shown.)
Index: o_text_basic.c
===================================================================
RCS file: o_text_basic.c
diff -N o_text_basic.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ o_text_basic.c 5 Jul 2006 03:13:38 -0000 1.19
@@ -0,0 +1,2433 @@
+/* gEDA - GPL Electronic Design Automation
+ * libgeda - gEDA's library
+ * Copyright (C) 1998-2000 Ales V. Hvezda
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+#include <config.h>
+
+#include <stdio.h>
+#include <math.h>
+#include <sys/stat.h>
+#include <assert.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <libguile.h>
+
+#include "defines.h"
+#include "struct.h"
+#include "globals.h"
+#include "o_types.h"
+#include "colors.h"
+#include "funcs.h"
+
+#include "../include/prototype.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+#line 117 "../noweb/o_text_basic.nw"
+#define WINONLY 1
+#define BACKING 2
+
+/*! \note
+ * font storage and friends are staying global so that all can access
+ */
+
+/*! Hashtable storing font_character (string) as a key, and pointer to data */
+GHashTable *font_loaded = NULL;
+
+/*! Hashtable storing mapping between character and font definition file */
+GHashTable *font_char_to_file = NULL;
+
+/*! Size of a tab in characters */
+int tab_in_chars = 8;
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void get_text_bounds(TOPLEVEL *w_current, OBJECT *o_current,
+ int *left, int *top, int *right, int *bottom)
+{
+ get_complex_bounds(w_current, o_current->text->prim_objs, left, top,
+ right, bottom);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void world_get_text_bounds(TOPLEVEL *w_current, OBJECT *o_current, int *left,
+ int *top, int *right, int *bottom)
+{
+ world_get_complex_bounds(w_current, o_current->text->prim_objs,
+ left, top, right, bottom);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+OBJECT *o_text_add_head(void)
+{
+ OBJECT *new_node=NULL;
+
+ new_node = s_basic_init_object("text_head");
+ new_node->type = OBJ_HEAD;
+
+ /* don't need to do this for head nodes */
+ /* ret = s_basic_link_object(new_node, NULL);*/
+ return(new_node);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void o_text_init(void)
+{
+ if (font_loaded == NULL) {
+ font_loaded = g_hash_table_new_full (g_direct_hash,
+ g_direct_equal,
+ NULL,
+ g_free);
+ } else {
+ fprintf (stderr, "o_text_init: Tried to initialize an already initialized font_loaded hash table!!\n");
+ }
+ if (font_char_to_file == NULL) {
+ font_char_to_file = g_hash_table_new_full (g_direct_hash,
+ g_direct_equal,
+ NULL,
+ g_free);
+ }
+ else {
+ fprintf (stderr, "o_text_init: Tried to initialize an already initialized font_char_to_file hash table!!\n");
+ }
+
+ return;
+
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void o_text_print_set(void)
+{
+ OBJECT *o_current, *o_font_set;
+ char i;
+
+ for (i = 'A' ; i < 'Z'+1; i++) {
+ o_font_set = g_hash_table_lookup (font_loaded,
+ GUINT_TO_POINTER ((gunichar)i));
+ if (o_font_set != NULL) {
+ printf("%c: LOADED\n", i);
+ for (o_current=return_tail(o_font_set->font_prim_objs); o_current;
+ o_current=o_current->prev)
+ {
+ printf(" %s\n", o_current->name);
+ }
+ } else {
+ printf("%c: unloaded\n", i);
+ }
+ }
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+OBJECT *o_text_load_font(TOPLEVEL *w_current, gunichar needed_char)
+{
+ gchar *temp_string = NULL;
+ OBJECT *temp_parent, *o_font_set;
+ int not_found = FALSE;
+ gchar *aux_str2;
+
+ /* retrieve the name of the file where the char is defined */
+ aux_str2 = g_hash_table_lookup (font_char_to_file,
+ GUINT_TO_POINTER (needed_char));
+ if (aux_str2 == NULL) {
+ /* this is needed since WinNT file systems are
+ * case insensitive, and cannot tell the difference
+ * between A.sym and a.sym. So we create a_.sym -
+ * z_.sym, this loads up the chars
+ */
+ if (needed_char >= 'a' && needed_char <= 'z') {
+ temp_string = g_strdup_printf("%s%c%c_.sym",
+ w_current->font_directory, G_DIR_SEPARATOR,
+ needed_char);
+ } else {
+ temp_string = g_strdup_printf("%s%c%c.sym",
+ w_current->font_directory, G_DIR_SEPARATOR,
+ needed_char);
+ }
+ } else {
+ temp_string = g_strdup_printf("%s", aux_str2);
+ }
+ aux_str2 = NULL;
+
+ if ( access(temp_string, R_OK) != 0 ) {
+ gchar outbuf[7];
+ gint l;
+
+ /* convert needed_char to a utf-8 string */
+ l = g_unichar_to_utf8 (needed_char, outbuf);
+ outbuf[l] = '\0';
+ s_log_message("Could not find character '%s' definition.\n", outbuf);
+
+ g_free (temp_string);
+ temp_string = g_strdup_printf("%s%cquest.sym", w_current->font_directory, G_DIR_SEPARATOR);
+ if ( access(temp_string, R_OK) != 0 ) {
+ fprintf(stderr, "Could not load question font char -- check font-directory keyword\n");
+ exit(-1);
+ }
+ not_found = TRUE;
+ }
+
+ /* Make new object for the font set list */
+ o_font_set = (OBJECT*)g_new (OBJECT, 1);
+
+ o_font_set->font_prim_objs = NULL;
+ o_font_set->font_text_size = 100;
+
+ o_font_set->name = g_strdup_printf ("%c", needed_char);
+ o_font_set->font_prim_objs = o_text_add_head();
+
+ /* Add it to the list and hash table. Some functions will need it */
+ g_hash_table_insert (font_loaded,
+ GUINT_TO_POINTER (needed_char), o_font_set);
+
+ if (not_found == TRUE) {
+ /* set the font text size (width) to the question mark's size */
+ /* yes, the question mark character was loaded instead of the real char */
+ /* 63 == question mark character */
+
+ OBJECT *aux_obj;
+
+ aux_obj = g_hash_table_lookup (font_loaded,
+ GUINT_TO_POINTER ((gunichar)'?'));
+ if (aux_obj == NULL) {
+ o_text_load_font(w_current, (gunichar) '?');
+ aux_obj = g_hash_table_lookup (font_loaded,
+ GUINT_TO_POINTER ((gunichar)'?'));
+ }
+
+ o_font_set->font_text_size = aux_obj->font_text_size;
+ }
+
+
+ temp_parent = w_current->page_current->object_parent;
+ /* set the addition of attributes to the head node */
+ w_current->page_current->object_parent = o_font_set->font_prim_objs;
+
+ o_font_set->font_prim_objs = o_read(w_current, o_font_set->font_prim_objs,
+ temp_string);
+ w_current->page_current->object_parent = temp_parent;
+
+ o_font_set->font_prim_objs = return_head(o_font_set->font_prim_objs);
+
+ return(o_font_set->font_prim_objs);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+int o_text_num_lines(char *string)
+{
+ int line_count = 0;
+ gchar *aux;
+ gunichar current_char;
+
+ if (string == NULL) {
+ return 0;
+ }
+
+ /* if it's not null, then we have at least one line */
+ line_count++;
+ /* Count how many \n are in the string */
+ aux = string;
+ while (aux && ((gunichar) (*aux) != 0) ) {
+ current_char = g_utf8_get_char_validated(aux, -1);
+ if (current_char == '\n')
+ line_count++;
+ aux = g_utf8_find_next_char(aux, NULL);
+ }
+
+ return (line_count);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+/* You do not need to divide the size in half here. */
+int o_text_height(char *string, int size)
+{
+ int line_count = 0;
+
+ if (string == NULL) {
+ return 0;
+ }
+
+ /* Get the number of lines in the string */
+ line_count = o_text_num_lines(string);
+
+ /* 26 is the height of a single char (in mils) */
+ /* which represents a character which is 2 pts high */
+ /* So size has to be divided in half */
+ /* and it's added the LINE_SPACING*character_height of each line */
+ return(26*size/2*(1+LINE_SPACING*(line_count-1)));
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+/* You need to divide the size in half here. */
+/*! \todo FIXME consistancy. */
+int o_text_width(TOPLEVEL *w_current, char *string, int size)
+{
+ int width=0, max_width=0;
+ int size_of_tab_in_coord;
+ OBJECT *o_font_set;
+ gchar *ptr;
+ gunichar previous_char;
+ gunichar c = 0;
+ if (string == NULL) {
+ return 0;
+ }
+
+ /* Make sure TAB_CHAR_MODEL is loaded before trying to use its text */
+ /* size */
+ o_font_set = g_hash_table_lookup (
+ font_loaded, GUINT_TO_POINTER ((gunichar)TAB_CHAR_MODEL[0]));
+ if (o_font_set == NULL) {
+ o_text_load_font(w_current, (gunichar) TAB_CHAR_MODEL[0]);
+ o_font_set = (OBJECT *) g_hash_table_lookup (
+ font_loaded, GUINT_TO_POINTER ((gunichar)TAB_CHAR_MODEL[0]));
+ }
+
+ /* Get the maximum tab width's in coordinates */
+ size_of_tab_in_coord = tab_in_chars * size * o_font_set->font_text_size;
+
+ for (ptr = string;
+ ptr != NULL && *ptr != 0;
+ ptr = g_utf8_find_next_char (ptr, NULL))
+ {
+ previous_char = c;
+ c = g_utf8_get_char_validated (ptr, -1);
+
+ if ( (c == (gunichar) '\\') &&
+ (previous_char != (gunichar) '\\') ) {
+ continue;
+ }
+ if ( (c == (gunichar) '_') &&
+ (previous_char == (gunichar) '\\') ) {
+ continue;
+ }
+ switch (c) {
+ case ((gunichar)'\n'):
+ width = 0;
+ break;
+ case ((gunichar)'\t'):
+ width += (size_of_tab_in_coord - (width % size_of_tab_in_coord));
+ break;
+ default:
+ /* find current_char */
+ o_font_set = g_hash_table_lookup (font_loaded,
+ GUINT_TO_POINTER (c));
+ if (o_font_set == NULL) {
+ o_text_load_font (w_current, (gunichar)c);
+ /* let do a new search for character c */
+ o_font_set = g_hash_table_lookup (font_loaded,
+ GUINT_TO_POINTER (c));
+ }
+
+ if (o_font_set != NULL) {
+ width = width + size*o_font_set->font_text_size;
+ }
+
+ if (width > max_width) {
+ max_width = width;
+ }
+ }
+ }
+
+ /* the size is a fudge factor */
+ /* Changed the return value according to a suggestion of Ales. */
+ /* Yes, the -size*10 fudge factor should be removed. */
+ /* return(max_width - size*10); */
+ return max_width;
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+OBJECT *o_text_create_string(TOPLEVEL *w_current, OBJECT *object_list,
+ char *string, int size, int color, int x, int y,
+ int alignment, int angle)
+{
+ OBJECT *temp_tail=NULL;
+ OBJECT *temp_list;
+ OBJECT *start_of_char;
+ int x_offset;
+ int y_offset;
+ int text_width;
+ int text_height;
+ int char_height;
+ int line_start_x, line_start_y;
+ int sign=1;
+ int overbar_startx=0, overbar_starty=0;
+ int overbar_endx=0, overbar_endy=0;
+ int overbar_height_offset = 0;
+ int last_char_width;
+ gboolean overbar_started = FALSE;
+ gchar *ptr;
+ gchar *aux_string;
+ OBJECT *o_font_set;
+ gunichar c=0, previous_char = 0, next_char = 0;
+ int escapes_counter = 0;
+
+ temp_list = object_list;
+
+
+ /* error condition hack */
+ if (string == NULL) {
+ return(NULL);
+ }
+
+ /* now read in the chars */
+ temp_tail = w_current->page_current->object_tail;
+
+ text_height = o_text_height(string, size);
+ char_height = o_text_height("a", size);
+ text_width = o_text_width(w_current, string, size/2);
+
+ switch(angle) {
+ case(0):
+ sign = -1;
+ break;
+ case(90):
+ sign = 1;
+ break;
+ case(180):
+ sign = 1;
+ break;
+ case(270):
+ sign = -1;
+ break;
+ }
+
+ if (angle == 0 || angle == 180) {
+ y = y - o_text_height("a", size) + text_height;
+
+ switch(alignment) {
+
+ case(LOWER_LEFT):
+ x_offset = x;
+ y_offset = y;
+ break;
+
+ case(MIDDLE_LEFT):
+ x_offset = x;
+ y_offset = y + sign*0.5*text_height;
+ break;
+
+ case(UPPER_LEFT):
+ x_offset = x;
+ y_offset = y + sign*text_height;
+ break;
+
+ case(LOWER_MIDDLE):
+ x_offset = x + sign*0.5*text_width;
+ y_offset = y;
+ break;
+
+ case(MIDDLE_MIDDLE):
+ x_offset = x + sign*0.5*text_width;
+ y_offset = y + sign*0.5*text_height;
+ break;
+
+ case(UPPER_MIDDLE):
+ x_offset = x + sign*0.5*text_width;
+ y_offset = y + sign*text_height;
+
+ break;
+
+ case(LOWER_RIGHT):
+ x_offset = x + sign*text_width;
+ y_offset = y;
+ break;
+
+ case(MIDDLE_RIGHT):
+ x_offset = x + sign*text_width;
+ y_offset = y + sign*0.5*text_height;
+ break;
+
+ case(UPPER_RIGHT):
+ x_offset = x + sign*text_width;
+ y_offset = y + sign*text_height;
+ break;
+
+ default:
+ fprintf(stderr, "Got an invalid text alignment [%d]\n",
+ alignment);
+ fprintf(stderr, "Defaulting to Lower Left");
+ alignment = LOWER_LEFT;
+ x_offset = x;
+ y_offset = y;
+ break;
+ }
+ } else { /* angle is 90 or 270 */
+ x = x + sign*(o_text_height("a", size) - text_height);
+
+ switch(alignment) {
+
+ case(LOWER_LEFT):
+ x_offset = x;
+ y_offset = y;
+ break;
+
+ case(MIDDLE_LEFT):
+ x_offset = x + sign*0.5*text_height;
+ y_offset = y;
+ break;
+
+ case(UPPER_LEFT):
+ x_offset = x + sign*text_height;
+ y_offset = y;
+ break;
+
+ case(LOWER_MIDDLE):
+ x_offset = x;
+ y_offset = y - sign*0.5*text_width;
+ break;
+
+ case(MIDDLE_MIDDLE):
+ x_offset = x + sign*0.5*text_height;
+ y_offset = y - sign*0.5*text_width;
+ break;
+
+ case(UPPER_MIDDLE):
+ x_offset = x + sign*text_height;
+ y_offset = y - sign*0.5*text_width;
+
+ break;
+
+ case(LOWER_RIGHT):
+ x_offset = x;
+ y_offset = y - sign*text_width;
+ break;
+
+ case(MIDDLE_RIGHT):
+ x_offset = x + sign*0.5*text_height;
+ y_offset = y - sign*text_width;
+ break;
+
+ case(UPPER_RIGHT):
+ x_offset = x + sign*text_height;
+ y_offset = y - sign*text_width;
+ break;
+
+ default:
+ fprintf(stderr, "Got an invalid text alignment [%d]\n",
+ alignment);
+ fprintf(stderr, "Defaulting to Lower Left");
+ alignment = LOWER_LEFT;
+ x_offset = x;
+ y_offset = y;
+ break;
+ }
+
+ }
+
+ switch(angle) {
+ case(180):
+ x_offset = x_offset - text_width;
+ y_offset = y_offset - text_height;
+ angle = 0;
+ break;
+ }
+
+#if DEBUG
+ printf("width: %d\n", o_text_width(w_current, string, size/2));
+ printf("1 %d %d\n", x_offset, y_offset);
+#endif
+
+ line_start_x = x_offset;
+ line_start_y = y_offset;
+
+ for (ptr = string;
+ ptr != NULL && *ptr != 0;
+ previous_char =
+ g_utf8_get_char_validated (ptr, -1),
+ ptr = g_utf8_find_next_char (ptr, NULL),
+ next_char = g_utf8_get_char_validated(g_utf8_find_next_char (ptr, NULL),-1)) {
+ /* Keep track of the previous character and its width.
+ They will be used in the overbar and escape characters */
+ aux_string = g_strdup_printf("%c", previous_char);
+ last_char_width = o_text_width(w_current, aux_string, size/2);
+ g_free(aux_string);
+
+ c = g_utf8_get_char_validated (ptr, -1);
+
+ o_font_set = g_hash_table_lookup (font_loaded, GUINT_TO_POINTER (c));
+ if (o_font_set == NULL) {
+ o_text_load_font(w_current, (gunichar) c);
+ o_font_set = g_hash_table_lookup (font_loaded, GUINT_TO_POINTER (c));
+ }
+
+ start_of_char = temp_list;
+
+ if (o_font_set->font_prim_objs->next != NULL) {
+ int rel_char_coord;
+ int size_of_tab_in_coord;
+ OBJECT *o_font_set_aux;
+
+ /* Make sure TAB_CHAR_MODEL is loaded before trying to use its text */
+ /* size */
+ o_font_set_aux = g_hash_table_lookup (
+ font_loaded, GUINT_TO_POINTER ((gunichar)TAB_CHAR_MODEL[0]));
+ if (o_font_set_aux == NULL) {
+ o_text_load_font(w_current, (gunichar) TAB_CHAR_MODEL[0]);
+ o_font_set_aux = g_hash_table_lookup (
+ font_loaded, GUINT_TO_POINTER ((gunichar)TAB_CHAR_MODEL[0]));
+ }
+
+ /* Get the maximum tab width's in coordinates */
+ size_of_tab_in_coord = tab_in_chars *
+ o_text_width(w_current, TAB_CHAR_MODEL, size/2);
+
+ /* Count escape characters. Notice it includes the current character */
+ if (c == '\\') {
+ escapes_counter++;
+ }
+
+ /* Ignore escape characters */
+ if ( ((c == '\\') && (previous_char != '\\')) ||
+ ((c == '\\') && (escapes_counter == 1)) )
+ continue;
+
+ if (c != '\n' && c != '\t') {
+ /* only add the character if it is not a newline, a tab character
+ a escape character or the overbar delimiter escape sequence.
+ Add it if it is the escaped escape character */
+ if ( ( (c != '\\') &&
+ (!(previous_char == '\\' && c == '_')) ) ||
+ (previous_char == '\\' && c == '\\' && (escapes_counter > 1)) ) {
+ temp_list = o_list_copy_all(w_current,
+ o_font_set->font_prim_objs->next,
+ temp_list, NORMAL_FLAG);
+ if (start_of_char != NULL)
+ start_of_char = start_of_char->next;
+ /* does not get here if the character was a newline, tab, or
+ special character.
+ This is correct. */
+ o_complex_set_color(start_of_char, color);
+ o_scale(w_current, start_of_char, size/2, size/2);
+
+ /* do this if you want to stack chars */
+ /* we don't want to do that for now */
+ /* Rotate and translate the character to its world position */
+ o_text_rotate_lowlevel(w_current, x, y, angle, start_of_char);
+ o_complex_world_translate(w_current,
+ x_offset, y_offset,
+ start_of_char);
+
+ /* Reset the escapes counter after being processed. Otherwise,
+ if the next character is also a backslash, it will
+ be processed as if were also escaped */
+ if (previous_char == '\\' && c == '\\') {
+ escapes_counter = 0;
+ }
+ }
+ }
+
+ /* Now check for special characters */
+
+ if ( (c == '_' && previous_char == '\\') ||
+ (c == '\n' && overbar_started) ||
+ (previous_char == '\n' && overbar_started) ||
+ (overbar_started && next_char == 0) ) {
+ /* Found the overbar delimiter sequence
+ If the character is the newline and the overbar was started,
+ then end it and start it again in the next character, after
+ processing the newline. */
+ overbar_height_offset = char_height + (char_height >> 2);
+ if ( (!overbar_started) ||
+ (overbar_started && previous_char == '\n') ){
+ /* Start point of the overbar */
+ overbar_started = TRUE;
+ switch (angle) {
+ case 0:
+ overbar_startx = x_offset;
+ overbar_starty = y_offset + overbar_height_offset;
+ break;
+ case 90:
+ overbar_startx = x_offset - overbar_height_offset;
+ overbar_starty = y_offset;
+ break;
+ case 180:
+ overbar_startx = x_offset;
+ overbar_starty = y_offset - overbar_height_offset;
+ break;
+ case 270:
+ overbar_startx = x_offset + overbar_height_offset;
+ overbar_starty = y_offset;
+ break;
+ default:
+ fprintf(stderr, "o_text_create_string: Angle not supported\n");
+ break;
+ }
+ } else {
+ /* Then this is the end point of the overbar */
+ if (overbar_started && next_char == 0 &&
+ !(c == '_' && previous_char == '\\')) {
+ /* Instead of ending in the last character, end the overbar
+ after the current character (its width is
+ size/2*o_font_set->font_text_size */
+ last_char_width = -size/2*o_font_set->font_text_size;
+ }
+ switch (angle) {
+ case 0:
+ overbar_endx = x_offset - last_char_width;
+ overbar_endy = y_offset + overbar_height_offset;
+ break;
+ case 90:
+ overbar_endx = x_offset - overbar_height_offset;
+ overbar_endy = y_offset - last_char_width;
+ break;
+ case 180:
+ overbar_endx = x_offset + last_char_width;
+ overbar_endy = y_offset - overbar_height_offset;
+ break;
+ case 270:
+ overbar_endx = x_offset + overbar_height_offset;
+ overbar_endy = y_offset + last_char_width;
+ break;
+ default:
+ fprintf(stderr, "o_text_create_string: Angle not supported\n");
+ break;
+ }
+ /* Now add the overbar (if it is not a zero length overbar) */
+ if ( (overbar_startx != overbar_endx) ||
+ (overbar_starty != overbar_endy) ) {
+ temp_list = o_line_add(w_current, temp_list, OBJ_LINE, color,
+ overbar_startx, overbar_starty,
+ overbar_endx, overbar_endy);
+ }
+
+ if (!((c == '\n') && (overbar_started))) {
+ /* If it's the newline character, keep the overbar started, since
+ we have to end this one & start another one in the next line */
+ overbar_started = FALSE;
+ }
+ }
+ if (c != '\n')
+ continue;
+ }
+
+ /* If the character is a newline or tab, this code will "continue" */
+ switch (c) {
+ case '\n':
+ /* The character is a newline. Calcule the start of the next line */
+ switch (angle) {
+ case 0:
+ x_offset = line_start_x;
+ y_offset = line_start_y - char_height * LINE_SPACING;
+ line_start_x = x_offset;
+ line_start_y = y_offset;
+ continue;
+ break;
+ case 90:
+ x_offset = line_start_x + char_height * LINE_SPACING;
+ y_offset = line_start_y;
+ line_start_x = x_offset;
+ line_start_y = y_offset;
+ continue;
+ break;
+ case 180:
+ x_offset = line_start_x;
+ y_offset = line_start_y + char_height * LINE_SPACING;
+ line_start_x = x_offset;
+ line_start_y = y_offset;
+ continue;
+ break;
+ case 270:
+ x_offset = line_start_x - char_height * LINE_SPACING;
+ y_offset = line_start_y;
+ line_start_x = x_offset;
+ line_start_y = y_offset;
+ continue;
+ break;
+ default:
+ fprintf(stderr, "o_text_create_string: Angle not supported\n");
+ break;
+ }
+ case '\t':
+#if DEBUG
+ printf("Found tab character.\n");
+ printf("Tab size in coord: %i\n", size_of_tab_in_coord);
+ printf("Line start: %i,%i\n", line_start_x, line_start_y);
+ printf("Position: %i, %i\n", x_offset, y_offset);
+#endif
+ switch (angle) {
+ case 0:
+ case 180:
+ rel_char_coord = x_offset - line_start_x;
+#if DEBUG
+ printf("Add: %i\n", (size_of_tab_in_coord - (rel_char_coord % size_of_tab_in_coord)));
+#endif
+ x_offset += (size_of_tab_in_coord - (rel_char_coord % size_of_tab_in_coord));
+ continue;
+ break;
+ case 90:
+ rel_char_coord = y_offset - line_start_y;
+#if DEBUG
+ printf("Add: %i\n", (size_of_tab_in_coord - (rel_char_coord % size_of_tab_in_coord)));
+#endif
+ y_offset += (size_of_tab_in_coord - (rel_char_coord % size_of_tab_in_coord));
+ continue;
+ break;
+ case 270:
+ rel_char_coord = line_start_y - y_offset;
+#if DEBUG
+ printf("Add: %i\n", (size_of_tab_in_coord - (rel_char_coord % size_of_tab_in_coord)));
+#endif
+ y_offset -= (size_of_tab_in_coord - (rel_char_coord % size_of_tab_in_coord));
+ continue;
+ break;
+ default:
+ fprintf(stderr, "o_text_create_string: Angle not supported\n");
+ break;
+ }
+ }
+ }
+
+ /* Calcule the position of the next character */
+ switch(angle) {
+ case(0):
+ x_offset = (x_offset) +
+ size/2*o_font_set->font_text_size;
+ break;
+
+ case(90):
+ y_offset = (y_offset) +
+ size/2*o_font_set->font_text_size;
+ break;
+
+ case(180):
+ x_offset = (x_offset) -
+ size/2*o_font_set->font_text_size;
+ break;
+
+ case(270):
+ y_offset = (y_offset) -
+ size/2*o_font_set->font_text_size;
+ break;
+ }
+ }
+
+ /* don't set the head */
+
+ w_current->page_current->object_tail = temp_tail;
+
+#if DEBUG
+ printf("2 %d %d\n", x_offset, y_offset);
+#endif
+ return(object_list);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+OBJECT *o_text_add(TOPLEVEL *w_current, OBJECT *object_list,
+ char type, int color, int x, int y, int alignment,
+ int angle, char *string, int size,
+ int visibility, int show_name_value)
+{
+ OBJECT *new_node=NULL;
+ OBJECT *temp_list=NULL;
+ OBJECT *temp_parent=NULL;
+ TEXT *text;
+ int left, right, top, bottom;
+ char *name = NULL;
+ char *value = NULL;
+ char *output_string = NULL;
+
+ if (string == NULL) {
+ return(NULL);
+ }
+
+ new_node = s_basic_init_object("text");
+ new_node->type = type;
+
+ text = (TEXT *) malloc(sizeof(TEXT));
+
+ text->string = g_strdup (string);
+ text->length = strlen(string);
+ text->size = size;
+ text->alignment = alignment;
+ text->x = x;
+ text->y = y;
+ WORLDtoSCREEN(w_current, x, y, &text->screen_x, &text->screen_y);
+ text->angle = angle;
+
+ new_node->text = text;
+
+ /* \todo questionable cast */
+ new_node->draw_func = (void *) text_draw_func;
+ /* \todo questionable cast */
+ new_node->sel_func = (void *) select_func;
+
+ new_node->color = color;
+ new_node->visibility = visibility;
+ new_node->show_name_value = show_name_value;
+
+ /* create the object in the main list */
+ /* object_list points to the object */
+ /* I use it below as a sanity check to make sure it was linked */
+ /* properly */
+ object_list = (OBJECT *) s_basic_link_object(new_node, object_list);
+
+ /* fix up actual string here */
+ if (o_attrib_get_name_value(string, &name, &value)) {
+
+ switch(show_name_value) {
+ case(SHOW_NAME_VALUE):
+ output_string = g_strdup(string);
+ break;
+
+ case(SHOW_NAME):
+ if (name[0] != '\0') {
+ output_string = g_strdup(name);
+ } else {
+ /* you probably can remove this now... */
+ /* since improper attributes will never get here */
+ fprintf(stderr,
+ "Got an improper attribute: %s\n",
+ string);
+ output_string = g_strdup("invalid");
+
+ }
+ break;
+
+ case(SHOW_VALUE):
+ if (value[0] != '\0') {
+ output_string = g_strdup (value);
+ } else {
+ /* you probably can remove this now... */
+ /* since improper attributes will never get here */
+ fprintf(stderr,
+ "Got an improper attribute: %s\n",
+ string);
+ output_string = g_strdup("invalid");
+ }
+ break;
+ }
+ } else {
+ output_string = g_strdup(string);
+ }
+
+
+ /* now start working on the complex */
+ temp_list = o_text_add_head();
+
+ temp_parent = w_current->page_current->object_parent;
+ /* set the addition of attributes to the head node */
+ w_current->page_current->object_parent = temp_list;
+
+ if (visibility == VISIBLE ||
+ (visibility == INVISIBLE && w_current->show_hidden_text)) {
+ object_list->text->prim_objs =
+ o_text_create_string(w_current, temp_list,
+ output_string, size, color,
+ x, y, alignment, angle);
+ object_list->text->displayed_width = o_text_width(w_current,
+ output_string, size/2);
+ object_list->text->displayed_height = o_text_height(output_string, size);
+ } else {
+ object_list->text->prim_objs = NULL;
+ object_list->text->displayed_width = 0;
+ object_list->text->displayed_height = 0;
+ s_delete(w_current, temp_list);
+ }
+
+ w_current->page_current->object_parent = temp_parent;
+
+ get_text_bounds(w_current, object_list, &left, &top, &right, &bottom);
+
+ /* set the new object's bounding box */
+ object_list->left = left;
+ object_list->top = top;
+ object_list->right = right;
+ object_list->bottom = bottom;
+
+ if (name) free(name);
+ if (value) free(value);
+ if (output_string) free(output_string);
+ return(object_list);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void o_text_recalc(TOPLEVEL *w_current, OBJECT *o_current)
+{
+ int left, right, top, bottom;
+
+ if (o_current->visibility == INVISIBLE && !w_current->show_hidden_text) {
+ return;
+ }
+
+ get_complex_bounds(w_current, o_current->text->prim_objs,
+ &left, &top, &right, &bottom);
+ o_current->left = left;
+ o_current->top = top;
+ o_current->right = right;
+ o_current->bottom = bottom;
+
+ WORLDtoSCREEN(w_current, o_current->text->x,
+ o_current->text->y,
+ &o_current->text->screen_x,
+ &o_current->text->screen_y);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+OBJECT *o_text_read(TOPLEVEL *w_current, OBJECT *object_list,
+ char buf[], FILE *fp, unsigned int release_ver,
+ unsigned int fileformat_ver)
+{
+ 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) {
+ sscanf(buf, "%c %d %d %d %d %d %d %d %d %d\n", &type, &x, &y,
+ &color, &size,
+ &visibility, &show_name_value,
+ &angle, &alignment, &num_lines);
+ } else if (release_ver < VERSION_20000220) {
+ /* yes, above less than (not less than and equal) is correct. The format */
+ /* change occurred in 20000220 */
+ sscanf(buf, "%c %d %d %d %d %d %d %d\n", &type, &x, &y,
+ &color, &size,
+ &visibility, &show_name_value,
+ &angle);
+ alignment = LOWER_LEFT; /* older versions didn't have this */
+ num_lines = 1; /* only support a single line */
+ } else {
+ sscanf(buf, "%c %d %d %d %d %d %d %d %d\n", &type, &x, &y,
+ &color, &size,
+ &visibility, &show_name_value,
+ &angle, &alignment);
+ num_lines = 1; /* only support a single line */
+ }
+
+ if (size == 0) {
+ fprintf(stderr, "Found a zero size text string [ %c %d %d %d %d %d %d %d %d ]\n", type, x, y, color, size, visibility, show_name_value, angle, alignment);
+ s_log_message("Found a zero size text string [ %c %d %d %d %d %d %d %d %d ]\n", type, x, y, color, size, visibility, show_name_value, angle, alignment);
+ }
+
+ switch(angle) {
+
+ case(0):
+ case(90):
+ case(180):
+ case(270):
+ break;
+
+ default:
+ fprintf(stderr, "Found an unsupported text angle [ %c %d %d %d %d %d %d %d %d ]\n", type, x, y, color, size, visibility, show_name_value, angle, alignment);
+ s_log_message("Found an unsupported text angle [ %c %d %d %d %d %d %d %d %d ]\n", type, x, y, color, size, visibility, show_name_value, angle, alignment);
+ s_log_message("Setting angle to 0\n");
+ angle=0;
+ break;
+
+ }
+
+ 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:
+ fprintf(stderr, "Found an unsupported text alignment [ %c %d %d %d %d %d %d %d %d ]\n", type, x, y, color, size, visibility, show_name_value, angle, alignment);
+ s_log_message("Found an unsupported text alignment [ %c %d %d %d %d %d %d %d %d ]\n", type, x, y, color, size, visibility, show_name_value, angle, alignment);
+ s_log_message("Setting alignment to LOWER_LEFT\n");
+ alignment = LOWER_LEFT;
+ break;
+ }
+
+ if (color < 0 || color > MAX_COLORS) {
+ fprintf(stderr, "Found an invalid color [ %s ]\n", buf);
+ s_log_message("Found an invalid color [ %s ]\n", buf);
+ s_log_message("Setting color to WHITE\n");
+ color = WHITE;
+ }
+
+ assert(num_lines && num_lines > 0);
+
+ textstr = g_string_new ("");
+ for (i = 0; i < num_lines; i++) {
+ gchar buffer[MAX_TEXT_LINE_LENGTH];
+
+ fgets (buffer, MAX_TEXT_LINE_LENGTH, fp);
+
+ textstr = g_string_append (textstr, buffer);
+ }
+ /* retrieve the character string from the GString */
+ string = g_string_free (textstr, FALSE);
+
+ string = remove_last_nl(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: %s.\n",
+ string);
+ } else {
+ /* successfully converted string, now use tmp as string */
+ g_free (string);
+ string = tmp;
+ }
+ }
+
+ object_list = o_text_add(w_current, object_list, type, color, x, y,
+ alignment, angle, string,
+ size, visibility, show_name_value);
+ g_free(string);
+
+ return(object_list);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void o_text_set_info_font(char buf[])
+{
+ char type;
+ int width;
+ gunichar character=0;
+ gchar *buf_ptr;
+ int special=0;
+ char *string;
+ OBJECT *o_font_set;
+
+ string = remove_nl (buf);
+
+ /* parse the font info: */
+ buf_ptr = (gchar*)string;
+ /* - type */
+ type = *buf_ptr++;
+ g_assert (type == INFO_FONT);
+ while (buf_ptr != NULL && *buf_ptr == ' ') buf_ptr++;
+ /* - character */
+ if (buf_ptr != NULL && *buf_ptr != '\0') {
+ character = g_utf8_get_char_validated (buf_ptr, -1);
+ if (character == (gunichar)-1) {
+ s_log_message (
+ "Failed to validate utf-8 character in font definition: \"%s\".\n",
+ string);
+ return;
+ }
+ /* move buf_ptr just after character */
+ buf_ptr = g_utf8_find_next_char (buf_ptr, NULL);
+ }
+ while (buf_ptr != NULL && *buf_ptr == ' ') buf_ptr++;
+ /* - width and special */
+ if (buf_ptr != NULL) {
+ sscanf (buf_ptr, "%d %d\n", &width, &special);
+ }
+
+ /* deal with special characters */
+ if (special == 1) {
+ switch (character) {
+ case ((gunichar)'_'):
+ /* space */
+ character = (gunichar)' ';
+ break;
+ case ((gunichar)'n'):
+ /* newline */
+ character = (gunichar)'\n';
+ break;
+ }
+ }
+
+ o_font_set = g_hash_table_lookup (font_loaded,
+ GUINT_TO_POINTER ((gunichar)character));
+ if (o_font_set != NULL) {
+ o_font_set->font_text_size = width;
+ } else {
+ gchar outbuf[7];
+ gint l = g_unichar_to_utf8 (character, outbuf);
+ outbuf[l] = '\0';
+ fprintf(stderr,
+ "o_text_set_info_font: character %s not found!!!\n", outbuf);
+ }
+
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+char *o_text_save(OBJECT *object)
+{
+ int x, y;
+ int color;
+ int size;
+ char *string;
+ char *buf;
+ int num_lines;
+
+ x = object->text->x;
+ y = object->text->y;
+
+ string = object->text->string;
+ size = object->text->size;
+
+ /* Use the right color */
+ if (object->saved_color == -1) {
+ color = object->color;
+ } else {
+ color = object->saved_color;
+ }
+
+ /* string can have multiple lines (seperated by \n's) */
+ num_lines = o_text_num_lines(string);
+
+ buf = g_strdup_printf("%c %d %d %d %d %d %d %d %d %d\n%s", object->type,
+ x, y, color, size, object->visibility,
+ object->show_name_value, object->text->angle,
+ object->text->alignment, num_lines, string);
+
+ return(buf);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void o_text_recreate(TOPLEVEL *w_current, OBJECT *o_current)
+{
+ OBJECT *temp_parent;
+ char *name = NULL;
+ char *value = NULL;
+ char *output_string = NULL;
+
+ if (o_attrib_get_name_value(o_current->text->string, &name, &value)) {
+ switch(o_current->show_name_value) {
+ case(SHOW_NAME_VALUE):
+ output_string = g_strdup(o_current->text->string);
+ break;
+
+ case(SHOW_NAME):
+ if (name[0] != '\0') {
+ output_string = g_strdup(name);
+ } else {
+ /* you probably can remove this now... */
+ /* since improper attributes will never get here */
+ fprintf(stderr,
+ "Got an improper attribute: %s\n",
+ o_current->text->string);
+ output_string = g_strdup("invalid");
+ }
+ break;
+
+ case(SHOW_VALUE):
+ if (value[0] != '\0') {
+ output_string = g_strdup(value);
+ } else {
+ /* you probably can remove this now... */
+ /* since improper attributes will never get here */
+ fprintf(stderr,
+ "Got an improper attribute: %s\n",
+ o_current->text->string);
+ output_string = g_strdup("invalid");
+ }
+ break;
+ }
+ } else {
+ output_string = g_strdup(o_current->text->string);
+ }
+
+ o_list_delete_rest(w_current, o_current->text->prim_objs);
+
+ temp_parent = w_current->page_current->object_parent;
+ /* set the addition of attributes to the head node */
+ w_current->page_current->object_parent = o_current->text->prim_objs;
+
+ if (o_current->visibility == VISIBLE ||
+ (o_current->visibility == INVISIBLE && w_current->show_hidden_text)) {
+
+ /* need to create that head node if complex is null */
+ if (o_current->text->prim_objs == NULL) {
+ o_current->text->prim_objs = o_text_add_head();
+ }
+
+ o_current->text->prim_objs =
+ o_text_create_string(w_current,
+ o_current->text->prim_objs,
+ output_string,
+ o_current->text->size,
+ o_current->color,
+ o_current->text->x,
+ o_current->text->y,
+ o_current->text->alignment,
+ o_current->text->angle);
+
+ o_complex_set_saved_color_only(o_current->text->prim_objs,
+ o_current->saved_color);
+ o_current->text->displayed_width = o_text_width(w_current,
+ output_string,
+ o_current->text->size/2);
+ o_current->text->displayed_height = o_text_height(output_string,
+ o_current->text->size);
+ } else {
+ /* make sure list is truely free */
+ s_delete_list_fromstart(w_current, o_current->text->prim_objs);
+ o_current->text->prim_objs = NULL;
+ o_current->text->displayed_width = 0;
+ o_current->text->displayed_height = 0;
+ }
+
+ w_current->page_current->object_parent = temp_parent;
+ if (name) free(name);
+ if (value) free(value);
+ if (output_string) free(output_string);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void o_text_translate_world(TOPLEVEL *w_current,
+ int x1, int y1, OBJECT *o_current)
+{
+ int screen_x, screen_y;
+ int left, right, top, bottom;
+
+
+ o_current->text->x = o_current->text->x + x1;
+ o_current->text->y = o_current->text->y + y1;
+
+ /* update screen coords */
+ WORLDtoSCREEN(w_current, o_current->text->x, o_current->text->y,
+ &screen_x, &screen_y);
+
+ o_current->text->screen_x = screen_x;
+ o_current->text->screen_y = screen_y;
+
+ o_complex_world_translate(w_current, x1, y1, o_current->text->prim_objs);
+
+ /* update bounding box */
+ /* do it */
+ get_text_bounds(w_current, o_current, &left, &top, &right, &bottom);
+
+ o_current->left = left;
+ o_current->top = top;
+ o_current->right = right;
+ o_current->bottom = bottom;
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+OBJECT *o_text_copy(TOPLEVEL *w_current, OBJECT *list_tail, OBJECT *o_current)
+{
+ OBJECT *new_obj;
+ int color;
+
+ if (o_current->saved_color == -1) {
+ color = o_current->color;
+ } else {
+ color = o_current->saved_color;
+ }
+
+ new_obj = o_text_add(w_current, list_tail, OBJ_TEXT,
+ color,
+ o_current->text->x, o_current->text->y,
+ o_current->text->alignment,
+ o_current->text->angle,
+ o_current->text->string,
+ o_current->text->size,
+ o_current->visibility,
+ o_current->show_name_value);
+
+ return(new_obj);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+static gboolean delete_font_set (gpointer key, gpointer value,
+ gpointer user_data)
+{
+ OBJECT *tmp = (OBJECT*)value;
+ TOPLEVEL *toplevel = (TOPLEVEL*)user_data;
+
+ if (tmp != NULL) {
+ if (tmp->font_prim_objs != NULL) {
+ s_delete_list_fromstart (toplevel, tmp->font_prim_objs);
+ tmp->font_prim_objs = NULL;
+ }
+ /* do not use s_delete() as tmp is not fully initialized */
+ g_free (tmp->name);
+
+ /* Do not free tmp here since it will be freed with the function */
+ /* that was specified when the hash table was created. */
+ }
+
+ return TRUE;
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void o_text_freeallfonts(TOPLEVEL *w_current)
+{
+ /* destroy the char-to-objects hastable */
+ g_hash_table_foreach_remove (font_loaded,
+ delete_font_set,
+ w_current);
+ g_hash_table_destroy (font_loaded);
+ font_loaded = NULL;
+
+ /* destroy the font-to-filename hashtable */
+ g_hash_table_destroy (font_char_to_file);
+ font_char_to_file = NULL;
+
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void o_text_print_text_width(FILE *fp, char *output_string)
+{
+ int len, i, j;
+ int starting_character = 0;
+ int num_lines, line_number;
+ int max_len = -1;
+ char *single_line = NULL;
+ char *max_length_line = NULL;
+ int single_len;
+
+ /* break up the string and find the longest string */
+ num_lines = o_text_num_lines(output_string);
+ single_line = g_strdup (output_string); /* larger than needed */
+ len = strlen(output_string);
+ for (line_number = 0; line_number < num_lines; line_number++)
+ {
+ j = 0;
+ /* break up the string into lines */
+ for (i = starting_character; i < len; i++)
+ {
+ if (output_string[i] != '\n' && output_string[i] != '\0')
+ {
+ single_line[j] = output_string[i];
+ }
+ else
+ {
+ starting_character = i + 1;
+ break;
+ }
+ j++;
+ }
+ single_line[j] = '\0';
+
+ single_len = strlen(single_line);
+ if (single_len > max_len)
+ {
+ max_len = strlen(single_line);
+ if (max_length_line) free(max_length_line);
+ max_length_line = g_strdup (single_line);
+ }
+ }
+
+
+ fprintf(fp, "(");
+ len = strlen(max_length_line);
+ for (i = 0 ; i < len; i++) {
+ if (max_length_line[i] == '(' || max_length_line[i] == ')' || max_length_line[i] == '\\' ) {
+ fprintf(fp, "\\");
+ }
+
+ fprintf(fp, "%c", max_length_line[i]);
+ }
+
+ /* convert width to mils */
+ /* .95 is a fudge factor */
+ fprintf(fp, ") stringwidth pop\n");
+
+ if (single_line) free(single_line);
+ if (max_length_line) free(max_length_line);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void o_text_print_text_height(FILE *fp, int size)
+{
+ fprintf(fp, "%f\n", (float) size);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void o_text_print_text_height_full(FILE *fp, char *string, int size)
+{
+ int num_lines = o_text_num_lines(string);
+ fprintf(fp, "%f\n", (float) (size*num_lines +
+ size * LINE_SPACING * (num_lines - 1)));
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void o_text_print_text_string(FILE *fp, char *string, int unicode_count,
+ gunichar *unicode_table)
+{
+ int len, j;
+ gchar *aux;
+ gunichar current_char, c;
+
+ if (!string)
+ {
+ return;
+ }
+
+ aux = string;
+ len = g_utf8_strlen(string, -1);
+
+ fprintf(fp, "(");
+
+ while (aux && ((gunichar) (*aux) != 0)) {
+ current_char = g_utf8_get_char_validated(aux, -1);
+ if (current_char == '(' || current_char == ')' || current_char == '\\') {
+ fprintf(fp, "\\");
+ }
+
+ c = current_char;
+ if (c >= 128) {
+ current_char = '?';
+ if (unicode_count) {
+ for (j = 0; j < unicode_count; j++)
+ if (c == unicode_table[j]) {
+ current_char = j + 128;
+ break;
+ }
+ }
+ }
+ fprintf(fp, "%c", current_char);
+ aux = g_utf8_find_next_char(aux, NULL);
+ }
+
+ fprintf(fp,") ");
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void o_text_print(TOPLEVEL *w_current, FILE *fp, OBJECT *o_current,
+ int origin_x, int origin_y,
+ int unicode_count, gunichar *unicode_table)
+{
+ char *centering_control = NULL;
+ char *p,*s;
+ char *output_string = NULL;
+ char *name = NULL;
+ char *value = NULL;
+ int x, y, angle, len, char_height;
+ float font_size;
+
+ if (!o_current->text->string) {
+ return;
+ }
+
+ if (w_current->print_color) {
+ f_print_set_color(fp, o_current->color);
+ }
+
+
+ if (o_attrib_get_name_value(o_current->text->string, &name, &value)) {
+ switch(o_current->show_name_value) {
+ case(SHOW_NAME_VALUE):
+ output_string = g_strdup(o_current->text->string);
+ break;
+
+ case(SHOW_NAME):
+ if (name[0] != '\0') {
+ output_string = g_strdup(name);
+ } else {
+ fprintf(stderr,
+ "Got an improper attribute: %s\n",
+ o_current->text->string);
+ output_string = g_strdup("invalid");
+ }
+ break;
+
+ case(SHOW_VALUE):
+ if (value[0] != '\0') {
+ output_string = g_strdup(value);
+ } else {
+ /* you probably can remove this now... */
+ /* since improper attributes will never get here */
+ fprintf(stderr,
+ "Got an improper attribute: %s\n",
+ o_current->text->string);
+ output_string = g_strdup("invalid");
+ }
+ break;
+ }
+ } else {
+ output_string = g_strdup(o_current->text->string);
+ }
+
+
+ /* Create an appropriate control string for the centering. */
+ switch(o_current->text->alignment) {
+ /* hcenter rjustify vcenter vjustify */
+ case(LOWER_LEFT): centering_control = "false false false false";
+ break;
+ case(MIDDLE_LEFT): centering_control = "false false true false";
+ break;
+ case(UPPER_LEFT): centering_control = "false false false true";
+ break;
+ case(LOWER_MIDDLE): centering_control = "true false false false";
+ break;
+ case(MIDDLE_MIDDLE): centering_control = "true false true false";
+ break;
+ case(UPPER_MIDDLE): centering_control = "true false false true";
+ break;
+ case(LOWER_RIGHT): centering_control = "false true false false";
+ break;
+ case(MIDDLE_RIGHT): centering_control = "false true true false";
+ break;
+ case(UPPER_RIGHT): centering_control = "false true false true";
+ break;
+ }
+
+ char_height = o_text_height("a", o_current->text->size);
+ fprintf(fp,"%s %f [",centering_control,(float)(char_height*LINE_SPACING));
+
+ /* split the line at each newline and print them */
+ p = output_string; /* Current point */
+ s = output_string; /* Start of the current string */
+ len = strlen(output_string)+1;
+ while(len != 0) {
+ /* Have we reached the end of a line? */
+ if((*p == '\n') || (*p == '\0')) {
+ /* Yes, replace the newline with a NULL and output the string */
+ *p = '\0';
+ o_text_print_text_string(fp,s,unicode_count,unicode_table);
+ /* Update output string start for next string */
+ s = p+1; /* One past the current character. */
+ }
+ p++; /* Advance to next character */
+ len--; /* Keep track of how many characters left to process */
+ }
+
+ /* Finish up with the rest of the text print command */
+ /* Collect pertinent info about the text location */
+ x = o_current->text->x;
+ y = o_current->text->y;
+ angle = o_current->text->angle;
+ font_size = (float) o_current->text->size/72.0*1000.0;
+ fprintf(fp,"] %d %d %d %f text\n",angle,x,y,font_size);
+
+
+ if (output_string) free(output_string);
+ if (name) free(name);
+ if (value) free(value);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+/* takes world coords as the center point as well as a true angle */
+void o_text_rotate_lowlevel(TOPLEVEL *w_current, int world_centerx,
+ int world_centery, int angle, OBJECT *object)
+{
+ OBJECT *o_current=NULL;
+
+ /* translate object to origin */
+ /* o_text_translate_world(w_current, -world_centerx, -world_centery, object);*/
+
+ /* rotate_point_90(object->text->x, object->text->y, &newx, &newy);*/
+
+ /* o_text_translate_world(w_current, world_centerx, world_centery, object);*/
+
+ o_current = object;
+
+ while ( o_current != NULL ) {
+ switch(o_current->type) {
+ case(OBJ_LINE):
+ o_line_rotate_world(w_current, 0, 0, angle, o_current);
+ break;
+ }
+ o_current=o_current->next;
+ }
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void o_text_rotate_world(TOPLEVEL *w_current,
+ int world_centerx, int world_centery,
+ int angle, int angle_change, OBJECT *object)
+{
+ int newx, newy;
+ int origx, origy;
+ int x, y;
+
+ origx = object->text->x;
+ origy = object->text->y;
+
+ object->text->angle = ( object->text->angle + angle_change ) % 360;
+
+#if DEBUG
+ printf("rotating text angle: %d\n", angle);
+ printf("rotating text angle_change: %d\n", angle_change);
+ printf("final text angle: %d\n", object->text->angle);
+#endif
+
+ x = origx + (-world_centerx);
+ y = origy + (-world_centery);
+
+ rotate_point_90(x, y, angle_change, &newx, &newy);
+
+ x = newx + (world_centerx);
+ y = newy + (world_centery);
+
+ o_text_translate_world(w_current, x-object->text->x, y-object->text->y, object);
+
+ o_text_recreate(w_current, object);
+}
+
+void o_text_rotate(TOPLEVEL *w_current, int centerx, int centery, int angle,
+ int angle_change, OBJECT *object)
+{
+ int newx, newy;
+ int origx, origy;
+ int world_centerx, world_centery;
+ int x, y;
+
+ SCREENtoWORLD(w_current, centerx, centery,
+ &world_centerx,
+ &world_centery);
+
+
+ origx = object->text->x;
+ origy = object->text->y;
+
+ object->text->angle = angle;
+
+ x = origx + (-world_centerx);
+ y = origy + (-world_centery);
+
+ rotate_point_90(x, y, angle_change, &newx, &newy);
+
+ x = newx + (world_centerx);
+ y = newy + (world_centery);
+
+ o_text_translate_world(w_current, x-object->text->x, y-object->text->y, object);
+
+ o_text_recreate(w_current, object);
+}
+
+#if 0 /* code which is no longer needed, replaced by new functions below */
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void o_text_mirror_old(TOPLEVEL *w_current, int centerx, int centery,
+ OBJECT *object)
+{
+ int newx=0, newy=0;
+ int origx, origy;
+ int world_centerx, world_centery;
+ int x, y;
+ char *output_string = NULL;
+ char *name = NULL;
+ char *value = NULL;
+ int height_mod=0;
+ int sign=1;
+
+ SCREENtoWORLD(w_current, centerx, centery,
+ &world_centerx,
+ &world_centery);
+
+ origx = object->text->x;
+ origy = object->text->y;
+
+ x = origx + (-world_centerx);
+ y = origy + (-world_centery);
+
+ if (o_attrib_get_name_value(object->text->string, &name, &value)) {
+ switch(object->show_name_value) {
+ case(SHOW_NAME_VALUE):
+ output_string = g_strdup(object->text->string);
+ break;
+
+ case(SHOW_NAME):
+ if (name[0] != '\0') {
+ output_string = g_strdup(name);
+ } else {
+ /* you probably can remove this now... */
+ /* since improper attributes will never get here */
+ fprintf(stderr,
+ "Got an improper attribute: %s\n",
+ object->text->string);
+ output_string = g_strdup("invalid");
+ }
+ break;
+
+ case(SHOW_VALUE):
+ if (value[0] != '\0') {
+ output_string = g_strdup(value);
+ } else {
+ /* you probably can remove this now... */
+ /* since improper attributes will never get here */
+ fprintf(stderr,
+ "Got an improper attribute: %s\n",
+ object->text->string);
+ output_string = g_strdup("invalid");
+ }
+ break;
+ }
+ } else {
+ output_string = g_strdup(object->text->string);
+ }
+
+ switch(object->text->alignment) {
+ case(LOWER_LEFT):
+ if (object->text->angle == 0 || object->text->angle == 180) {
+ sign = 1;
+ height_mod = 0;
+ } else if (object->text->angle == 90 || object->text->angle == 270) {
+ height_mod = 0;
+ }
+ break;
+
+ case(MIDDLE_LEFT):
+ if (object->text->angle == 0 || object->text->angle == 180) {
+ sign = 1;
+ height_mod = 0;
+ } else if (object->text->angle == 90 || object->text->angle == 270) {
+ height_mod = o_text_height(object->text->string,
+ object->text->size);
+ }
+ break;
+
+ case(UPPER_LEFT):
+ if (object->text->angle == 0 || object->text->angle == 180) {
+ sign = 1;
+ height_mod = 0;
+ } else if (object->text->angle == 90 || object->text->angle == 270) {
+ height_mod = 2*o_text_height(object->text->string,
+ object->text->size);
+ }
+ break;
+
+ case(LOWER_MIDDLE):
+ if (object->text->angle == 0 || object->text->angle == 180) {
+ sign = 0.5;
+ height_mod = 0;
+ } else if (object->text->angle == 90 || object->text->angle == 270) {
+ sign = 1;
+ height_mod = 0;
+ }
+ break;
+
+ case(MIDDLE_MIDDLE):
+ if (object->text->angle == 0 || object->text->angle == 180) {
+ sign = 0.5;
+ height_mod = 0;
+ } else if (object->text->angle == 90 || object->text->angle == 270) {
+ sign = 1;
+ height_mod = o_text_height(object->text->string,
+ object->text->size);
+ }
+ break;
+
+ case(UPPER_MIDDLE):
+ if (object->text->angle == 0 || object->text->angle == 180) {
+ sign = 0.5;
+ height_mod = 0;
+ } else if (object->text->angle == 90 || object->text->angle == 270) {
+ sign = 1;
+ height_mod = 2*o_text_height(object->text->string,
+ object->text->size);
+ }
+ break;
+
+ case(LOWER_RIGHT):
+ if (object->text->angle == 0 || object->text->angle == 180) {
+ sign = -1;
+ height_mod = 0;
+ } else if (object->text->angle == 90 || object->text->angle == 270) {
+ sign = 1;
+ height_mod = 0;
+ }
+ break;
+
+ case(MIDDLE_RIGHT):
+ if (object->text->angle == 0 || object->text->angle == 180) {
+ sign = -1;
+ height_mod = 0;
+ } else if (object->text->angle == 90 || object->text->angle == 270) {
+ sign = 1;
+ height_mod = o_text_height(object->text->string,
+ object->text->size);
+ }
+ break;
+
+ case(UPPER_RIGHT):
+ if (object->text->angle == 0 || object->text->angle == 180) {
+ sign = -1;
+ height_mod = 0;
+ } else if (object->text->angle == 90 || object->text->angle == 270) {
+ sign = 1;
+ height_mod = 2*o_text_height(object->text->string,
+ object->text->size);
+ }
+ break;
+ }
+
+ switch (object->text->angle) {
+
+ case(0):
+ newx = -(x + sign*o_text_width(w_current,
+ output_string,
+ object->text->size/2));
+ break;
+
+ case(90):
+ newx = -(x - sign*o_text_height(object->text->string,
+ object->text->size)+
+ height_mod);
+ break;
+
+ case(180):
+ newx = -(x - sign*o_text_width(w_current,
+ output_string,
+ object->text->size/2));
+ break;
+
+ case(270):
+ newx = -(x + sign*o_text_height(object->text->string,
+ object->text->size)-
+ height_mod);
+ break;
+
+
+ default:
+ fprintf(stderr, "Invalid angle specified!\n");
+ return;
+ break;
+
+ }
+
+ newy = y;
+
+ x = newx + (world_centerx);
+ y = newy + (world_centery);
+
+ /* don't know if this is needed? */
+ o_text_translate_world(w_current, x-object->text->x, y-object->text->y, object);
+
+ o_text_recreate(w_current, object);
+ if (output_string) free(output_string);
+ if (name) free(name);
+ if (value) free(value);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void o_text_mirror_world_old(TOPLEVEL *w_current, int world_centerx,
+ int world_centery, OBJECT *object)
+{
+ int newx=0, newy=0;
+ int origx, origy;
+ int x, y;
+ char *output_string = NULL;
+ char *name = NULL;
+ char *value = NULL;
+ int sign=1;
+ int height_mod=0;
+
+ origx = object->text->x;
+ origy = object->text->y;
+
+ /* translate to origin */
+ x = origx + (-world_centerx);
+ y = origy + (-world_centery);
+
+
+ if (o_attrib_get_name_value(object->text->string, &name, &value)) {
+ switch(object->show_name_value) {
+ case(SHOW_NAME_VALUE):
+ output_string = g_strdup(object->text->string);
+ break;
+
+ case(SHOW_NAME):
+ if (name[0] != '\0') {
+ output_string = g_strdup(name);
+ } else {
+ /* you probably can remove this now... */
+ /* since improper attributes will never get here */
+ fprintf(stderr,
+ "Got an improper attribute: %s\n",
+ object->text->string);
+ output_string = g_strdup("invalid");
+ }
+ break;
+
+ case(SHOW_VALUE):
+ if (value[0] != '\0') {
+ output_string = g_strdup(value);
+ } else {
+ /* you probably can remove this now... */
+ /* since improper attributes will never get here */
+ fprintf(stderr,
+ "Got an improper attribute: %s\n",
+ object->text->string);
+ output_string = g_strdup("invalid");
+ }
+ break;
+ }
+ } else {
+ output_string = g_strdup(object->text->string);
+ }
+
+ switch(object->text->alignment) {
+ case(LOWER_LEFT):
+ if (object->text->angle == 0 || object->text->angle == 180) {
+ sign = 1;
+ height_mod = 0;
+ } else if (object->text->angle == 90 || object->text->angle == 270) {
+ height_mod = 0;
+ }
+ break;
+
+ case(MIDDLE_LEFT):
+ if (object->text->angle == 0 || object->text->angle == 180) {
+ sign = 1;
+ height_mod = 0;
+ } else if (object->text->angle == 90 || object->text->angle == 270) {
+ height_mod = o_text_height(object->text->string,
+ object->text->size);
+ }
+ break;
+
+ case(UPPER_LEFT):
+ if (object->text->angle == 0 || object->text->angle == 180) {
+ sign = 1;
+ height_mod = 0;
+ } else if (object->text->angle == 90 || object->text->angle == 270) {
+ height_mod = 2*o_text_height(object->text->string,
+ object->text->size);
+ }
+ break;
+
+ case(LOWER_MIDDLE):
+ if (object->text->angle == 0 || object->text->angle == 180) {
+ sign = 0.5;
+ height_mod = 0;
+ } else if (object->text->angle == 90 || object->text->angle == 270) {
+ sign = 1;
+ height_mod = 0;
+ }
+ break;
+
+ case(MIDDLE_MIDDLE):
+ if (object->text->angle == 0 || object->text->angle == 180) {
+ sign = 0.5;
+ height_mod = 0;
+ } else if (object->text->angle == 90 || object->text->angle == 270) {
+ sign = 1;
+ height_mod = o_text_height(object->text->string,
+ object->text->size);
+ }
+ break;
+
+ case(UPPER_MIDDLE):
+ if (object->text->angle == 0 || object->text->angle == 180) {
+ sign = 0.5;
+ height_mod = 0;
+ } else if (object->text->angle == 90 || object->text->angle == 270) {
+ sign = 1;
+ height_mod = 2*o_text_height(object->text->string,
+ object->text->size);
+ }
+ break;
+
+ case(LOWER_RIGHT):
+ if (object->text->angle == 0 || object->text->angle == 180) {
+ sign = -1;
+ height_mod = 0;
+ } else if (object->text->angle == 90 || object->text->angle == 270) {
+ sign = 1;
+ height_mod = 0;
+ }
+ break;
+
+ case(MIDDLE_RIGHT):
+ if (object->text->angle == 0 || object->text->angle == 180) {
+ sign = -1;
+ height_mod = 0;
+ } else if (object->text->angle == 90 || object->text->angle == 270) {
+ sign = 1;
+ height_mod = o_text_height(object->text->string,
+ object->text->size);
+ }
+ break;
+
+ case(UPPER_RIGHT):
+ if (object->text->angle == 0 || object->text->angle == 180) {
+ sign = -1;
+ height_mod = 0;
+ } else if (object->text->angle == 90 || object->text->angle == 270) {
+ sign = 1;
+ height_mod = 2*o_text_height(object->text->string,
+ object->text->size);
+ }
+ break;
+ }
+
+ switch (object->text->angle) {
+
+ case(0):
+ newx = -(x + sign*o_text_width(w_current,
+ output_string,
+ object->text->size/2));
+
+ break;
+
+ case(90):
+ newx = -(x - sign*o_text_height(object->text->string,
+ object->text->size)+height_mod);
+ break;
+
+ case(180):
+ newx = -(x - sign*o_text_width(w_current,
+ output_string,
+ object->text->size/2));
+ break;
+
+ case(270):
+ newx = -(x + sign*o_text_height(object->text->string,
+ object->text->size)+height_mod);
+ break;
+
+ default:
+ fprintf(stderr, "Invalid angle specified!\n");
+ return;
+ break;
+
+ }
+
+ newy = y;
+
+ x = newx + (world_centerx);
+ y = newy + (world_centery);
+
+ object->text->x = x;
+ object->text->y = y;
+
+ /* don't know if this is needed ?*/
+ /* o_text_translate_world(w_current, x-object->text->x, y-object->text->y, object);*/
+ o_text_recreate(w_current, object);
+ if (output_string) free(output_string);
+ if (name) free(name);
+ if (value) free(value);
+}
+#endif
+
+#if 0 /* interesting, but currently unused code */
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void o_text_return_center(TOPLEVEL *w_current, OBJECT *o_current,
+ int *centerx, int *centery)
+{
+ int text_height;
+ int text_width;
+
+ text_height = o_text_height(o_current->text->string,
+ o_current->text->size);
+
+ /* this will NOT NOT NOT work with attributes */
+ text_width = o_text_width(w_current, o_current->text->string,
+ o_current->text->size/2);
+
+ switch(o_current->text->angle) {
+ case(0):
+ *centerx = o_current->text->x + text_width/2;
+ *centery = o_current->text->y + text_height/2;
+ break;
+
+ case(90):
+ *centerx = o_current->text->x - text_height/2;
+ *centery = o_current->text->y + text_width/2;
+ break;
+
+ case(180):
+ *centerx = o_current->text->x - text_width/2;
+ *centery = o_current->text->y - text_height/2;
+ break;
+
+ case(270):
+ *centerx = o_current->text->x + text_height/2;
+ *centery = o_current->text->y - text_width/2;
+ break;
+ }
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+/* the complex here is the complex of a complex object */
+void o_text_change_angle(TOPLEVEL *w_current, OBJECT *prim_objs, int new_angle)
+{
+ OBJECT *o_current;
+ int centerx, centery;
+
+ o_current = prim_objs;
+
+ while (o_current != NULL) {
+ if (o_current->type == OBJ_TEXT) {
+ o_current->text->angle = new_angle;
+
+ /* change world to non */
+ o_text_return_center(w_current, o_current, ¢erx, ¢ery);
+
+ o_text_translate_world(w_current,
+ -centerx, -centery, o_current);
+
+ o_text_mirror_world(w_current, 0, 0,
+ o_current);
+ /*
+ o_text_rotate_world(w_current, 0, 0,
+ new_angle, 180, o_current);
+ */
+
+ /* o_text_rotate_world(w_current, 0, 0, new_angle,
+ 180, o_current)*/
+
+ o_text_translate_world(w_current,
+ centerx, centery, o_current);
+
+ /* o_text_rotate_lowlevel(w_current,
+ 0, 0, new_angle, 180, o_current->text->prim_objs);*/
+
+#if 0
+ w_current->override_color =
+ w_current->background_color;
+ o_text_draw(w_current, o_current);
+ w_current->override_color = -1;
+#endif
+
+ o_text_recreate(w_current, o_current);
+ }
+ o_current = o_current->next;
+ }
+}
+#endif
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void o_text_mirror_world(TOPLEVEL *w_current,
+ int world_centerx, int world_centery,
+ OBJECT *object)
+{
+ int origx, origy;
+ int x, y;
+
+ origx = object->text->x;
+ origy = object->text->y;
+
+ x = origx + (-world_centerx);
+ y = origy + (-world_centery);
+
+ if ((object->text->angle%180)==0) {
+ switch(object->text->alignment) {
+ case(LOWER_LEFT):
+ object->text->alignment=LOWER_RIGHT;
+ break;
+
+ case(MIDDLE_LEFT):
+ object->text->alignment=MIDDLE_RIGHT;
+ break;
+
+ case(UPPER_LEFT):
+ object->text->alignment=UPPER_RIGHT;
+ break;
+
+ case(LOWER_RIGHT):
+ object->text->alignment=LOWER_LEFT;
+ break;
+
+ case(MIDDLE_RIGHT):
+ object->text->alignment=MIDDLE_LEFT;
+ break;
+
+ case(UPPER_RIGHT):
+ object->text->alignment=UPPER_LEFT;
+ break;
+
+ default:
+ break;
+ }
+ } else {
+ switch(object->text->alignment) {
+ case(LOWER_LEFT):
+ object->text->alignment=UPPER_LEFT;
+ break;
+
+ case(UPPER_LEFT):
+ object->text->alignment=LOWER_LEFT;
+ break;
+
+ case(LOWER_RIGHT):
+ object->text->alignment=UPPER_RIGHT;
+ break;
+
+ case(UPPER_RIGHT):
+ object->text->alignment=LOWER_RIGHT;
+ break;
+
+ case(LOWER_MIDDLE):
+ object->text->alignment=UPPER_MIDDLE;
+ break;
+
+ case(UPPER_MIDDLE):
+ object->text->alignment=LOWER_MIDDLE;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ object->text->x = -x + (world_centerx);
+ object->text->y = y + (world_centery);
+
+ o_text_recreate(w_current, object);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void o_text_mirror(TOPLEVEL *w_current,
+ int centerx, int centery, OBJECT *object)
+{
+ int world_centerx, world_centery;
+
+ SCREENtoWORLD(w_current, centerx, centery,
+ &world_centerx,
+ &world_centery);
+
+ o_text_mirror_world(w_current, world_centerx, world_centery, object);
+}
1.10 +89 -59 eda/geda/gaf/libgeda/src/s_attrib.c
(In the diff below, changes in quantity of whitespace are not shown.)
Index: s_attrib.c
===================================================================
RCS file: s_attrib.c
diff -N s_attrib.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ s_attrib.c 5 Jul 2006 03:13:38 -0000 1.10
@@ -0,0 +1,158 @@
+/* gEDA - GPL Electronic Design Automation
+ * libgeda - gEDA's library
+ * Copyright (C) 1998-2000 Ales V. Hvezda
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+#include <config.h>
+
+#include <stdio.h>
+#include <sys/types.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <libguile.h>
+
+#include "defines.h"
+#include "struct.h"
+#include "globals.h"
+
+#include "../include/prototype.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+#define MAX_ATTRIBS 128
+
+/*! \brief */
+struct st_attrib_names {
+ char *attrib_name;
+};
+
+/*! \brief */
+static int attrib_index=0;
+
+/*! \brief */
+/* and eventually make this unlimited */
+/* hack hack */
+static struct st_attrib_names attrib[MAX_ATTRIBS];
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+int s_attrib_add_entry(char *new_attrib)
+{
+ if (new_attrib == NULL) {
+ return(-1);
+ }
+
+ if (attrib_index >= MAX_ATTRIBS) {
+ return(-1);
+ }
+
+ attrib[attrib_index].attrib_name = (char *) malloc(sizeof(char)*strlen(new_attrib)+1);
+
+ strcpy(attrib[attrib_index].attrib_name, new_attrib);
+
+ attrib_index++;
+ return(attrib_index);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_attrib_print()
+{
+ int i;
+
+ for (i = 0; i < attrib_index; i++) {
+ printf("%s\n", attrib[i].attrib_name);
+ }
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+/* true for uniqueness, zero for duplication */
+int s_attrib_uniq(char *name)
+{
+ int i;
+
+ for (i = 0; i < attrib_index; i++) {
+ if (strcmp(attrib[i].attrib_name, name) == 0) {
+ return(0);
+ }
+ }
+
+ return(1);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_attrib_free()
+{
+ int i;
+
+ for (i = 0; i < attrib_index; i++) {
+ if (attrib[i].attrib_name)
+ free(attrib[i].attrib_name);
+ }
+
+ attrib_index=0;
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_attrib_init()
+{
+ int i;
+ for (i = 0; i < MAX_ATTRIBS; i++) {
+ attrib[i].attrib_name = NULL;
+ }
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+char *s_attrib_get(int counter)
+{
+ if (counter < attrib_index) {
+ return(attrib[counter].attrib_name);
+ } else {
+ return(NULL);
+ }
+
+ return(NULL);
+}
1.21 +755 -582 eda/geda/gaf/libgeda/src/s_basic.c
(In the diff below, changes in quantity of whitespace are not shown.)
Index: s_basic.c
===================================================================
RCS file: s_basic.c
diff -N s_basic.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ s_basic.c 5 Jul 2006 03:13:38 -0000 1.21
@@ -0,0 +1,946 @@
+/* gEDA - GPL Electronic Design Automation
+ * libgeda - gEDA's library
+ * Copyright (C) 1998-2000 Ales V. Hvezda
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+#include <config.h>
+
+#include <stdio.h>
+#include <ctype.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_ASSERT_H
+#include <assert.h>
+#endif
+#ifndef HAVE_VSNPRINTF
+#include <stdarg.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <libguile.h>
+
+#include "defines.h"
+#include "struct.h"
+#include "defines.h"
+#include "globals.h"
+#include "o_types.h"
+#include "colors.h"
+
+#include "../include/prototype.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+/*! this is modified here and in o_list.c */
+int global_sid=0;
+
+#define NUMCOLORS 9 /*!< */
+
+/*! \brief */
+struct st_old_colors {
+ char *name;
+ int value;
+};
+
+/*! \brief
+ * Colors must be in alphabetical order
+ * be sure that you update above define
+ */
+struct st_old_colors old_colors[] = {
+ { "black", 0 },
+ { "blue", 4 },
+ { "cyan", 6 },
+ { "green", 3 },
+ { "grey", 7 },
+ { "grey90", 8 },
+ { "red", 2 },
+ { "white", 1 },
+ { "yellow", 5 },
+};
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void error_if_called(void)
+{
+ fprintf(stderr, "Somebody called error_if_called!\n");
+ assert(0);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void exit_if_null(void *ptr)
+{
+ if (ptr == NULL) {
+ fprintf(stderr, "gEDA: Got NULL ptr!, please e-mail maintainer\n");
+ assert(0);
+ exit(-1);
+ }
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+/* hack rename this to be s_return_tail */
+/* update object_tail or any list of that matter */
+OBJECT *return_tail(OBJECT *head)
+{
+ OBJECT *o_current=NULL;
+ OBJECT *ret_struct=NULL;
+
+ o_current = head;
+ while ( o_current != NULL ) { /* goto end of list */
+ ret_struct = o_current;
+ o_current = o_current->next;
+ }
+
+ return(ret_struct);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+/* hack rename this to be s_return_head */
+/* update object_tail or any list of that matter */
+OBJECT *return_head(OBJECT *tail)
+{
+ OBJECT *o_current=NULL;
+ OBJECT *ret_struct=NULL;
+
+ o_current = tail;
+ while ( o_current != NULL ) { /* goto end of list */
+ ret_struct = o_current;
+ o_current = o_current->prev;
+ }
+
+ return(ret_struct);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+OBJECT *s_basic_init_object( char *name )
+{
+ OBJECT *new_node;
+
+ new_node = (OBJECT *) malloc(sizeof(OBJECT));
+
+ if (new_node == NULL) {
+ fprintf(stderr, "Could not perform malloc; something is broken or increase your process limits\n");
+ exit(-1);
+ }
+
+ /* setup sid */
+ new_node->sid = global_sid++;
+ new_node->type = -1;
+
+ /* Setup the name */
+ /*! \todo get rid of magic number 16 that's the size of new_node->sid, */
+ new_node->name = (char *) malloc(sizeof(char)*(strlen(name)+16));
+ sprintf(new_node->name, "%s.%d", name, new_node->sid);
+
+ /* Setup the bounding box */
+ new_node->top = 999999;
+ new_node->left = 999999;
+ new_node->right = 0;
+ new_node->bottom = 0;
+
+ /* Setup line/circle structs */
+ new_node->line = NULL;
+ new_node->circle = NULL;
+ new_node->arc = NULL;
+ new_node->box = NULL;
+ new_node->picture = NULL;
+ new_node->text = NULL;
+ new_node->complex = NULL;
+
+ new_node->tile_locs = NULL;
+
+ new_node->conn_list = NULL;
+
+ new_node->visited = 0;
+
+ new_node->complex_basename = NULL;
+ new_node->complex_clib = NULL;
+ new_node->complex_parent = NULL;
+
+ /* Setup the color */
+ new_node->color = WHITE;
+ new_node->saved_color = -1;
+ new_node->selected = FALSE;
+ new_node->locked_color = -1;
+ new_node->draw_grips = FALSE;
+
+ new_node->bus_ripper_direction = 0;
+
+ new_node->action_func = error_if_called;
+ new_node->sel_func = error_if_called;
+ new_node->draw_func = error_if_called;
+
+ new_node->line_end = END_NONE;
+ new_node->line_type = TYPE_SOLID;
+ new_node->line_width = 0;
+ new_node->screen_line_width = 0;
+ new_node->line_space = 0;
+ new_node->screen_line_space = 0;
+ new_node->line_length = 0;
+ new_node->screen_line_length = 0;
+ new_node->fill_width = 0;
+ new_node->screen_fill_width = 0;
+ new_node->fill_angle1 = 0;
+ new_node->fill_angle2 = 0;
+ new_node->fill_pitch1 = 0;
+ new_node->screen_fill_pitch1 = 0;
+ new_node->fill_pitch2 = 0;
+ new_node->screen_fill_pitch2 = 0;
+
+ new_node->attribs = NULL;
+ new_node->attached_to = NULL;
+ new_node->attribute = 0;
+ new_node->show_name_value = SHOW_NAME_VALUE;
+ new_node->visibility = VISIBLE;
+
+ new_node->pin_type = PIN_TYPE_NET;
+ new_node->whichend = -1;
+
+ /* Setup link list stuff */
+ new_node->prev = NULL;
+ new_node->next = NULL;
+
+ return(new_node);
+}
+
+OBJECT *s_basic_link_object( OBJECT *new_node, OBJECT *ptr )
+{
+ /* should never happen, but could */
+ if (new_node == NULL) {
+ fprintf(stderr, "Got a null new_node in link_object\n");
+ return(ptr);
+ }
+
+ if (ptr == NULL) {
+ new_node->prev = NULL; /* setup previous link */
+ return(new_node);
+ } else {
+ new_node->prev = ptr; /* setup previous link */
+ ptr->next = new_node;
+ return(ptr->next);
+ }
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void print_struct_forw(OBJECT *ptr)
+{
+ OBJECT *o_current=NULL;
+ ATTRIB *attr=NULL;
+ int i;
+
+ o_current = ptr;
+
+ if (o_current == NULL) {
+
+ printf("AGGGGGGGGGGG NULLLLL PRINT\n");
+ }
+ printf("TRYING to PRINT\n");
+ while (o_current != NULL) {
+ printf("Name: %s\n", o_current->name);
+ printf("Type: %d\n", o_current->type);
+ printf("Sid: %d\n", o_current->sid);
+
+ if (o_current->type == OBJ_COMPLEX || o_current->type == OBJ_PLACEHOLDER) {
+ print_struct_forw(o_current->complex->prim_objs);
+ }
+
+
+ if (o_current->attribs) {
+ attr = o_current->attribs;
+ i = 0;
+ while (attr != NULL) {
+ if (attr->object != NULL)
+ printf("%d attribute %s\n", i, attr->object->name);
+ attr = attr->next;
+ }
+ }
+
+ printf("----\n");
+ o_current = o_current->next;
+ }
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void print_struct_back(OBJECT *ptr)
+{
+ OBJECT *o_current=NULL;
+
+ o_current = ptr;
+
+ while (o_current != NULL) {
+ printf("Name: %s\n", o_current->name);
+ printf("Type: %d\n", o_current->type);
+ printf("Sid: %d\n", o_current->sid);
+ printf("----\n");
+ o_current = o_current->prev;
+ }
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void print_struct(OBJECT *ptr)
+{
+ OBJECT *o_current=NULL;
+ ATTRIB *attr=NULL;
+ int i;
+
+ o_current = ptr;
+
+ if (o_current != NULL) {
+ printf("Name: %s\n", o_current->name);
+ printf("Type: %d\n", o_current->type);
+ printf("Sid: %d\n", o_current->sid);
+ if (o_current->line != NULL) {
+ printf("Line points.x1: %d\n", o_current->line->x[0]);
+ printf("Line points.y1: %d\n", o_current->line->y[0]);
+ printf("Line points.x2: %d\n", o_current->line->x[1]);
+ printf("Line points.y2: %d\n", o_current->line->y[1]);
+ }
+
+ if (o_current->attribs) {
+ attr = o_current->attribs;
+ i = 0;
+ while (attr != NULL) {
+ printf("%d attribute %s\n", i, attr->object->name);
+ attr = attr->next;
+ }
+
+ }
+ printf("----\n");
+ }
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_delete(TOPLEVEL *w_current, OBJECT *o_current)
+{
+ if (o_current != NULL) {
+
+
+#if DEBUG
+ printf("sdel: %s\n", o_current->name);
+ printf("sdel: %d\n", o_current->sid);
+#endif
+
+ if (o_current->next)
+ o_current->next->prev = o_current->prev;
+ else
+ o_current->next = NULL;
+
+ if (o_current->prev)
+ o_current->prev->next = o_current->next;
+ else
+ o_current->prev = NULL;
+
+ s_conn_remove(w_current, o_current);
+
+ /* second half of if is odd that we need it? hack */
+ /* need to do this early so we can do the printfs */
+ if (o_current->attached_to != NULL && o_current->attribute == 1) {
+ if (o_current->attached_to->object) {
+ /*printf("removing %s\n", o_current->attached_to->object->name);*/
+ } else {
+ printf("found a null I didn't expect!!!!!!!!!\n");
+ }
+
+ /* do the actual remove */
+ o_attrib_delete(o_current->attached_to);
+ }
+
+ if (w_current->page_current->object_lastplace == o_current) {
+ w_current->page_current->object_lastplace = NULL;
+ }
+
+ if (o_current->line) {
+ /* printf("sdeleting line\n");*/
+ free(o_current->line);
+
+ /* yes this object might be in the tile system */
+ s_tile_remove_object_all(w_current,
+ w_current->page_current,
+ o_current);
+ }
+ o_current->line = NULL;
+
+ if (o_current->circle) {
+ /* printf("sdeleting circle\n");*/
+ free(o_current->circle);
+ }
+ o_current->circle = NULL;
+
+ if (o_current->arc) {
+ /* printf("sdeleting arc\n");*/
+ free(o_current->arc);
+ }
+ o_current->arc = NULL;
+
+ if (o_current->box) {
+ /* printf("sdeleting box\n");*/
+ free(o_current->box);
+ }
+ o_current->box = NULL;
+
+ if (o_current->picture) {
+ /* printf("sdeleting picture\n");*/
+#ifndef HAS_GTK12
+ if (o_current->picture->original_picture)
+ free(o_current->picture->original_picture);
+ if (o_current->picture->displayed_picture)
+ free(o_current->picture->displayed_picture);
+#endif
+ if (o_current->picture->filename)
+ free(o_current->picture->filename);
+ free(o_current->picture);
+ }
+ o_current->picture = NULL;
+
+ if (o_current->text) {
+ if (o_current->text->string) {
+ /*printf("sdeleting text->string\n");*/
+ free(o_current->text->string);
+ }
+ o_current->text->string = NULL;
+
+ if (o_current->text->prim_objs) {
+ /*printf("sdeleting text complex\n");*/
+ s_delete_list_fromstart(w_current,
+ o_current->text->prim_objs);
+ }
+ o_current->text->prim_objs = NULL;
+
+ /* printf("sdeleting text\n");*/
+ free(o_current->text);
+ }
+ o_current->text = NULL;
+
+ if (o_current->name) {
+ /* printf("sdeleting name\n");*/
+ free(o_current->name);
+ }
+ o_current->name = NULL;
+
+
+ if (o_current->complex_basename) {
+ /* printf("sdeleting complex_basename\n");*/
+ free(o_current->complex_basename);
+ }
+ o_current->complex_basename = NULL;
+
+ if (o_current->complex_clib) {
+ /* printf("sdeleting complex_clib\n");*/
+ free(o_current->complex_clib);
+ }
+ o_current->complex_clib = NULL;
+
+ if (o_current->complex) {
+
+ if (o_current->complex->prim_objs) {
+ /* printf("sdeleting complex->primitive_objects\n");*/
+ s_delete_list_fromstart(w_current,
+ o_current->complex->prim_objs);
+ }
+ o_current->complex->prim_objs = NULL;
+
+ free(o_current->complex);
+ o_current->complex = NULL;
+ }
+
+ if (o_current->attribs) {
+ o_attrib_free_all(w_current, o_current->attribs);
+ }
+ o_current->attribs = NULL;
+
+
+ free(o_current); /* assuming it is not null */
+
+ o_current=NULL; /* misc clean up */
+ }
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+/* deletes everything include the head */
+void s_delete_list_fromstart(TOPLEVEL *w_current, OBJECT *start)
+{
+ OBJECT *temp=NULL; /* literally is a temp */
+ OBJECT *current=NULL; /* ugg... you have both o_current and current? */
+ OBJECT *o_current=NULL; /* hack */
+
+ temp = start;
+ current = return_tail(start);
+
+ /* do the delete backwards */
+ /*while(current != NULL && current->type != OBJ_HEAD ) {*/
+ while(current != NULL) {
+ o_current = current->prev;
+ s_delete(w_current, current);
+ current = o_current;
+ }
+
+ /* now delete the head node */
+ /* might not need this but what the hell */
+ /* no longer needed, since it's deleted above */
+ /*s_delete_head(w_current, start);*/
+}
+
+#if 0 /* old way of doing this */
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_delete_list_fromstart(OBJECT *start)
+{
+ OBJECT *traverse=NULL;
+ OBJECT *o_current=NULL;
+
+ for (traverse = start; traverse ; traverse = o_current) {
+ o_current = traverse->next;
+ if (traverse->type != OBJ_HEAD) /* don't delete any head nodes */
+ s_delete(traverse);
+ else
+ break; /* found a head node */
+ }
+ s_delete(traverse);
+}
+#endif
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ * This function removes one object pointed by parameter <B>object</B> from
+ * a list as far as it does not represents a head. If so the function returns
+ * NULL. If not it returns the pointer on the object, i.e. the same as the
+ * parameter.
+ *
+ * This function must be followed by a call to #return_tail() on the
+ * list it belonged to as it can be the last object. Therefore the tail
+ * of the list is modified.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] object
+ * \return OBJECT *
+ */
+OBJECT *s_remove(TOPLEVEL *w_current, OBJECT *object)
+{
+ if(object->type == OBJ_HEAD)
+ return NULL;
+
+ if(object->prev != NULL)
+ object->prev->next = object->next;
+ if(object->next != NULL)
+ object->next->prev = object->prev;
+
+ object->next = NULL;
+ object->prev = NULL;
+
+ return object;
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+/* Done */
+void string_toupper(char *in, char *out)
+{
+ int len;
+ int i;
+
+ len = strlen(in);
+
+ for (i = 0 ; i < len ; i++) {
+ out[i] = toupper(in[i]);
+ }
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void string_tolower(char *in, char *out)
+{
+ int len;
+ int i;
+
+ len = strlen(in);
+
+ for (i = 0 ; i < len ; i++) {
+ out[i] = tolower(in[i]);
+ }
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+int colornametovalue(char *string)
+{
+
+ int lower = 0;
+ int upper = NUMCOLORS - 1;
+ int middle;
+ int val;
+ struct st_old_colors *ptr=NULL;
+
+ if (!string) {
+ return(-1);
+ }
+
+ string_tolower(string, string);
+ while (lower <= upper) {
+ middle = (lower + upper) / 2;
+
+ ptr = &old_colors[middle];
+ val = strcmp (ptr->name, string);
+
+ if (val < 0) {
+ lower = middle + 1;
+ } else if (val == 0) {
+ return(ptr->value);
+ } else {
+ upper = middle - 1;
+ }
+ }
+ return(-1);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+/* used by o_text_read */
+char *remove_nl(char *string)
+{
+ int i;
+
+ if (!string)
+ return NULL;
+
+ i = 0;
+ while(string[i] != '\0' && string[i] != '\n' && string[i] != '\r') {
+ i++;
+ }
+
+ string[i] = '\0';
+
+ return(string);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+/* used by o_text_read */
+char *remove_last_nl(char *string)
+{
+ int len;
+
+ if (!string)
+ return NULL;
+
+ len = strlen(string);
+ if (string[len-1] == '\n' || string[len-1] == '\r')
+ string[len-1] = '\0';
+
+ return(string);
+}
+
+#ifndef HAVE_VSNPRINTF
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void vsnprintf(char *buff, size_t bufsiz, const char *fmt, va_list ap)
+{
+ char *tmpbuf = buff;
+
+ vsprintf(tmpbuf, fmt, ap);
+}
+#endif
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+/* this function is called by expand_env_variables */
+/* changes and returns new string, frees the one that was passed in */
+char *remove_string(char *string, int start, int end)
+{
+ char *return_string;
+ int i;
+ int len;
+ int j;
+
+ if (!string) {
+ return(NULL);
+ }
+
+ len = strlen(string);
+
+ return_string = (char *) malloc(sizeof(char)*(len+1));
+
+ j = 0;
+ for (i = 0 ; i < len; i++) {
+ if (i >= start && i <= end) {
+ /* do nothing */
+ /* removing characters */
+ } else {
+ return_string[j] = string[i];
+ j++;
+ }
+ }
+ return_string[j] = '\0';
+
+ /* free original string */
+ free(string);
+
+ return(return_string);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+/* this function is called by expand_env_variables */
+/* changes and returns new string, frees the one that was passed in */
+char *insert_string(char *string, int start, char *insert_string)
+{
+ char *new_string=NULL;
+ int i;
+ int len;
+ int insert_len;
+ int total_len;
+ int j;
+ int orig_count=0;
+
+ /* this should never happen */
+ if (!insert_string) {
+ return(NULL);
+ }
+
+ /* this should never happen either */
+ if (!string) {
+ return(NULL);
+ }
+
+ len = strlen(string);
+ insert_len = strlen(insert_string);
+ total_len = len+insert_len;
+
+ new_string = (char *) malloc(sizeof(char)*(total_len+1));
+
+ i = 0;
+ while (i < total_len) {
+ if (i == start) {
+ for (j = 0 ; j < insert_len; j++) {
+ new_string[i+j] = insert_string[j];
+ }
+ i = j+i;
+ } else {
+ new_string[i] = string[orig_count];
+ i++;
+ orig_count++;
+ }
+ }
+
+ new_string[i] = '\0';
+
+ /* now free the original string */
+ free(string);
+
+ return(new_string);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+/* this function changes and then returns the string which has the
+ * expanded environment variables, frees passed in string */
+/* Environment variables MUST be in the form ${variable_name} */
+/* $variable_name is not valid here */
+char *expand_env_variables(char *string)
+{
+ char wanted_var[80]; /* size is hack */
+ char *return_string=NULL;
+ char *environment_string=NULL;
+ int changed=1;
+ int found_dollar=0;
+ int found_lbrac=0;
+ int found_rbrac=0;
+ int start_of_variable= -1;
+ int end_of_variable= -1;
+ int count=0;
+ int i,j;
+
+ if (!string) {
+ return(NULL);
+ }
+
+ return_string = string;
+
+ while(changed) {
+
+ changed=0;
+ j=0;
+ for (i = 0 ; i < strlen(return_string); i++) {
+
+ switch(return_string[i]) {
+
+ case('$'):
+
+#if DEBUG
+ printf("found a $\n");
+#endif
+ found_dollar=1;
+ start_of_variable=i;
+ break;
+
+ case('{'):
+ if (found_dollar) {
+ found_lbrac=1;
+ count=1;
+ }
+ break;
+
+ case('}'):
+ if (found_dollar) {
+ found_rbrac=1;
+ /* ends filling of wanted_var */
+ found_lbrac=0;
+ end_of_variable=i;
+ }
+ break;
+
+ }
+
+ /* the > 1 bit is so that we don't store the { */
+ if (found_dollar && found_lbrac && (count > 1)) {
+ wanted_var[j] = return_string[i];
+ j++; /* check for size */
+ }
+
+ /* skip over initial { */
+ count++;
+
+ if (found_rbrac && !found_lbrac) {
+ wanted_var[j] = '\0';
+#if DEBUG
+ printf("variable wanted: _%s_\n", wanted_var);
+ printf("Between index: %d and %d\n",
+ start_of_variable,
+ end_of_variable);
+#endif
+
+
+ environment_string = getenv(wanted_var);
+
+#if DEBUG
+ if (environment_string) {
+ printf("%s = _%s_\n", wanted_var,
+ environment_string);
+ }
+#endif
+
+ return_string = remove_string(return_string,
+ start_of_variable,
+ end_of_variable);
+
+#if DEBUG
+ printf("removed string: _%s_\n", return_string);
+#endif
+
+ if (environment_string) {
+ return_string = insert_string(
+ return_string,
+ start_of_variable,
+ environment_string);
+
+ }
+
+#if DEBUG
+ printf("final string: _%s_\n", return_string);
+#endif
+ changed=1;
+
+ /* end of search */
+ found_dollar=0;
+ found_rbrac=0;
+ count=0;
+ start_of_variable= -1;
+ end_of_variable= -1;
+
+ break;
+ }
+ }
+ }
+
+ if (found_dollar) {
+ fprintf(stderr, "Found malformed environment variable (use ${varname})!\n");
+ }
+
+ return(return_string);
+}
1.18 +221 -494 eda/geda/gaf/libgeda/src/s_clib.c
(In the diff below, changes in quantity of whitespace are not shown.)
Index: s_clib.c
===================================================================
RCS file: s_clib.c
diff -N s_clib.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ s_clib.c 5 Jul 2006 03:13:38 -0000 1.18
@@ -0,0 +1,253 @@
+/* gEDA - GPL Electronic Design Automation
+ * libgeda - gEDA's library
+ * Copyright (C) 1998-2000 Ales V. Hvezda
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+/*! \file s_clib.c
+ * <B>clib</B> stands for component library.
+ *
+ * A component library is made of several directories gathering
+ * component files.
+ *
+ * It must first be initialized with #s_clib_init(). When it is no more
+ * useful, use #s_clib_free() to free memory and reset the component
+ * library.
+ *
+ * To add a directory to the library, use #s_clib_add_directory().
+ *
+ * To retrieve a list of the directories that make the library, use
+ * #s_clib_get_directories(). For a list of component files in a
+ * directory of the library, use #s_clib_get_files().
+ *
+ * #s_clib_search_basename() let you find a specific component from
+ * its name. Please note that it returns a list of directories as there
+ * may be several places that contains a component with this name.
+ */
+
+#include <config.h>
+
+#include <glib.h>
+
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+#include "defines.h"
+
+
+void s_clib_free (void);
+
+static GSList *clib_directories = NULL;
+
+static GHashTable *clib_cache = NULL;
+
+/*! \brief Initializes the component library handling code.
+ * \par Function Description
+ * Initializes the component library handling code.
+ * \warning This function must be called before any other function
+ * of this file.
+ */
+void s_clib_init (void)
+{
+ if (clib_directories != NULL || clib_cache != NULL) {
+ s_clib_free ();
+ }
+
+ clib_cache = g_hash_table_new (g_str_hash, g_str_equal);
+
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+static void clib_free_cache_entry (gpointer key, gpointer value,
+ gpointer user_data)
+{
+ g_free (key);
+ if (value != NULL) {
+ /* value is a singly-linked list of strings */
+ g_slist_foreach (value, (GFunc)g_free, NULL);
+ g_slist_free ((GSList*)value);
+ }
+}
+
+/*! \brief Frees memory used by the component library.
+ * \par Function Description
+ * Frees memory used by the component library.
+ */
+void s_clib_free (void)
+{
+ if (clib_directories != NULL) {
+ g_slist_foreach (clib_directories, (GFunc)g_free, NULL);
+ g_slist_free (clib_directories);
+ clib_directories = NULL;
+ }
+
+ if (clib_cache != NULL) {
+ g_hash_table_foreach (clib_cache, clib_free_cache_entry, NULL);
+ g_hash_table_destroy (clib_cache);
+ clib_cache = NULL;
+ }
+
+}
+
+/*! \brief Adds a new directory to the component library.
+ * \par Function Description
+ * Adds <B>directory</B> as a new directory for the component library.
+ *
+ * \param [in] directory Character string with the new directory name.
+ */
+void s_clib_add_directory (const gchar *directory)
+{
+ /* search for directory in clib_directories */
+ if (!g_slist_find_custom (clib_directories,
+ directory,
+ (GCompareFunc) g_strcasecmp))
+ {
+ /* directory not yet in the list of known directories */
+ /* add directory to list */
+ clib_directories = g_slist_append (clib_directories,
+ g_strdup (directory));
+ }
+
+}
+
+/*! \brief Get list of component library directories.
+ * \par Function Description
+ * This function returns the list of directories part of
+ * the component library.
+ *
+ * \return Global libgead #clib_directories variable.
+ * \warning
+ * The returned value is owned by libgeda and must not be modified or freed.
+ *
+ */
+const GSList *s_clib_get_directories()
+{
+ return clib_directories;
+}
+
+/*! \brief Get a list of files found a directory.
+ * \par Function Description
+ * This function returns a list of file names found in <B>directory</B> and
+ * that match <B>filter</B>
+ *
+ * \param [in] directory Character string with the path to search.
+ * \param [in] filter Character string to compare file names against.
+ * \return List of file name that matched <B>filter</B>, NULL otherwise.
+ */
+GSList *s_clib_get_files (const gchar *directory, const gchar *filter)
+{
+ GDir *dir;
+ const gchar *entry;
+ GSList *ret = NULL;
+
+ /* check directory is in clib_directories */
+ if (g_slist_find_custom (clib_directories,
+ directory,
+ (GCompareFunc) g_strcasecmp) == NULL)
+ {
+ /* no, unknown directory: report an error */
+ s_log_message ("Directory [%s] is not part of the component library\n",
+ directory);
+ return NULL;
+ }
+
+ /* open the directory */
+ dir = g_dir_open (directory, 0, NULL);
+ if (dir == NULL) {
+ s_log_message ("Failed to open directory [%s]\n", directory);
+ return NULL;
+ }
+
+ /* now read the entire directory */
+ /* and build a list of filenames in directory that match filter */
+ while ((entry = g_dir_read_name (dir)) != NULL) {
+ /* skip .'s */
+ if (entry[0] == '.') {
+ continue;
+ }
+
+ /* identify filter-matching filenames */
+ if (strstr (entry, filter)) {
+ ret = g_slist_append (ret, (gpointer)g_strdup (entry));
+ }
+
+ }
+
+ /* finished: close the directory stream */
+ g_dir_close (dir);
+
+ /* sort the list alphabetically */
+ ret = g_slist_sort (ret, (GCompareFunc)g_strcasecmp);
+
+ /* and return the sorted list of filenames */
+ return ret;
+}
+
+/*! \brief Search for a symbol file in the component library.
+ * \par Function Description
+ * Searches in component library for a symbol file with name <B>basename</B>.
+ *
+ * \param [in] basename Character string with base symbol name to search for.
+ * \return List of directories where symbol file with this name was found,
+ * NULL otherwise.
+ *
+ * \warning
+ * The returned value is owned by libgeda and must not be modified or freed.
+ *
+ */
+const GSList *s_clib_search_basename(const gchar *basename)
+{
+ GSList *ret, *tmp;
+
+ /* first check if basename is in cache */
+ ret = g_hash_table_lookup (clib_cache, basename);
+ if (ret != NULL) {
+ /* yes, found basename in cache, nothing more to do */
+ return ret;
+ }
+
+ /* looks like we have to search for basename in the library */
+ for (tmp = clib_directories; tmp != NULL; tmp = g_slist_next (tmp)) {
+ gchar *dir_name = (gchar*)tmp->data;
+ gchar *file_name = g_strconcat (dir_name,
+ G_DIR_SEPARATOR_S,
+ basename,
+ NULL);
+
+ if (g_file_test (file_name, G_FILE_TEST_EXISTS)) {
+ /* add directory name to the list */
+ ret = g_slist_append (ret, g_strdup (dir_name));
+ }
+
+ g_free (file_name);
+ }
+
+ /* have we found something? */
+ if (ret != NULL) {
+ /* yes, add the result to cache */
+ g_hash_table_insert (clib_cache, g_strdup (basename), ret);
+ }
+
+ return ret;
+}
1.8 +194 -141 eda/geda/gaf/libgeda/src/s_color.c
(In the diff below, changes in quantity of whitespace are not shown.)
Index: s_color.c
===================================================================
RCS file: s_color.c
diff -N s_color.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ s_color.c 5 Jul 2006 03:13:38 -0000 1.8
@@ -0,0 +1,247 @@
+/* gEDA - GPL Electronic Design Automation
+ * libgeda - gEDA's library
+ * Copyright (C) 1998-2000 Ales V. Hvezda
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+#include <config.h>
+
+#include <stdio.h>
+#include <math.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <libguile.h>
+
+#include "defines.h"
+#include "struct.h"
+#include "globals.h"
+
+#include "../include/prototype.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+COLOR colors[MAX_COLORS];
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_color_init(void)
+{
+ int i;
+
+ for (i = 0; i < MAX_COLORS; i++) {
+ colors[i].color_name = NULL;
+ colors[i].outline_color_name = NULL;
+ colors[i].ps_color_string = NULL;
+ colors[i].image_red = -1;
+ colors[i].image_green = -1;
+ colors[i].image_blue = -1;
+ colors[i].gtk_color = NULL;
+ colors[i].image_color = 0;
+ }
+
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+/* you are allowed to call this function with the same color index again and */
+/* and again, last call is the final color request */
+int s_color_request(int color_index, char *color_name,
+ char *outline_color_name, char *ps_color_string,
+ int image_red, int image_green, int image_blue)
+{
+
+#if 0
+ if (colors[color_index].color_name) {
+ return;
+ }
+#endif
+
+ if (color_index > MAX_COLORS) {
+ fprintf(stderr, "Cannot allocate specified color, increase MAX_COLORS\n");
+ return(-1);
+ }
+
+ /* search for the color name see if it's already been alloced */
+
+ if (colors[color_index].color_name) {
+ free(colors[color_index].color_name);
+ }
+
+ colors[color_index].color_name = g_strdup (color_name);
+
+ if (strcmp(outline_color_name, "null") != 0) {
+ colors[color_index].outline_color_name = g_strdup (outline_color_name);
+ } else {
+ colors[color_index].outline_color_name = NULL;
+ }
+
+ if (strcmp(ps_color_string, "null") != 0) {
+ colors[color_index].ps_color_string = g_strdup( ps_color_string);
+ } else {
+ colors[color_index].ps_color_string = NULL;
+ }
+
+ colors[color_index].image_red = image_red;
+ colors[color_index].image_green = image_green;
+ colors[color_index].image_blue = image_blue;
+ return(0);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_color_destroy_all(void)
+{
+ int i;
+
+ for (i = 0; i < MAX_COLORS; i++) {
+ if (colors[i].color_name) {
+ free(colors[i].color_name);
+ }
+ if (colors[i].outline_color_name) {
+ free(colors[i].outline_color_name);
+ }
+ if (colors[i].ps_color_string) {
+ free(colors[i].ps_color_string);
+ }
+ colors[i].image_red = -1;
+ colors[i].image_green = -1;
+ colors[i].image_blue = -1;
+ colors[i].image_color = 0;
+ /* free the colors */
+ }
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+char *s_color_ps_string(int color)
+{
+ if (colors[color].ps_color_string) {
+ return(colors[color].ps_color_string);
+ } else {
+ return(NULL);
+ }
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+int s_color_image_int(int color)
+{
+ if (colors[color].image_color != -1) {
+ return(colors[color].image_color);
+ } else {
+ return(0);
+ }
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+/* \bug I have no idea if this causes a memory leak or not */
+void s_color_gdcolor_init(void)
+{
+ int i;
+
+ for (i = 0; i < MAX_COLORS; i++) {
+
+ if (colors[i].image_red != -1 && colors[i].image_green != -1 &&
+ colors[i].image_blue != -1) {
+#ifdef HAS_LIBGDGEDA
+ colors[i].image_color = gdImageColorAllocate(
+ current_im_ptr,
+ colors[i].image_red,
+ colors[i].image_green,
+ colors[i].image_blue);
+#endif
+
+#if DEBUG
+ printf("%d) %d %d %d -> %d\n", i,
+ colors[i].image_red,
+ colors[i].image_green,
+ colors[i].image_blue, colors[i].image_color);
+#endif
+ }
+ }
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+int s_color_get_name(int index, char *string)
+{
+ if (index > MAX_COLORS) {
+ return(FALSE);
+ }
+
+ /* only if these two variables are not null is the color settable */
+ if (colors[index].color_name && colors[index].outline_color_name) {
+ if (string) {
+ strcpy(string, colors[index].color_name);
+ }
+ return(TRUE);
+ }
+
+ string[0] = '\0';
+ /* didn't find a color, but there still might be more */
+ return(-1);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ * \return The index of the given color name, -1 if index was not found.
+ */
+int s_color_get_index(char *string)
+{
+ int index;
+
+ if (string == NULL) {
+ return(-1);
+ }
+
+ for (index = 0; index < MAX_COLORS; index++) {
+ if (strcasecmp(string, colors[index].color_name) == 0) {
+ return (index);
+ }
+ }
+
+ /* If the color was not found, return -1 */
+ return (-1);
+
+}
1.4 +508 -192 eda/geda/gaf/libgeda/src/s_conn.c
(In the diff below, changes in quantity of whitespace are not shown.)
Index: s_conn.c
===================================================================
RCS file: s_conn.c
diff -N s_conn.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ s_conn.c 5 Jul 2006 03:13:38 -0000 1.4
@@ -0,0 +1,847 @@
+/* gEDA - GPL Electronic Design Automation
+ * libgeda - gEDA's library
+ * Copyright (C) 1998-2000 Ales V. Hvezda
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+#include <config.h>
+
+#include <stdio.h>
+#include <ctype.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_ASSERT_H
+#include <assert.h>
+#endif
+#ifndef HAVE_VSNPRINTF
+#include <stdarg.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <libguile.h>
+
+#include "defines.h"
+#include "struct.h"
+#include "defines.h"
+#include "globals.h"
+#include "colors.h"
+#include "o_types.h"
+
+#include "../include/prototype.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+CONN *s_conn_return_new(OBJECT * other_object, int type, int x, int y,
+ int whichone, int other_whichone)
+{
+ CONN *new_conn;
+
+ new_conn = (CONN *) malloc(sizeof(CONN));
+
+#if DEBUG
+ printf("** creating: %s %d %d\n", other_object->name, x, y);
+#endif
+
+ new_conn->other_object = other_object;
+ new_conn->type = type;
+ new_conn->x = x;
+ new_conn->y = y;
+ new_conn->whichone = whichone;
+ new_conn->other_whichone = other_whichone;
+
+ return (new_conn);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ * \return TRUE if the CONN structure is unique, FALSE otherwise.
+ */
+int s_conn_uniq(GList * conn_list, CONN * input_conn)
+{
+ GList *c_current;
+ CONN *conn;
+
+ c_current = conn_list;
+ while (c_current != NULL) {
+ conn = (CONN *) c_current->data;
+
+ if (conn->other_object == input_conn->other_object &&
+ conn->x == input_conn->x && conn->y == input_conn->y &&
+ conn->type == input_conn->type) {
+ return (FALSE);
+ }
+
+ c_current = c_current->next;
+ }
+
+ return (TRUE);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+int s_conn_remove_other(TOPLEVEL * w_current, OBJECT * other_object,
+ OBJECT * to_remove)
+{
+ GList *c_current = NULL;
+ CONN *conn = NULL;
+
+ c_current = other_object->conn_list;
+ while (c_current != NULL) {
+ conn = (CONN *) c_current->data;
+
+ if (conn->other_object == to_remove) {
+ other_object->conn_list =
+ g_list_remove(other_object->conn_list, conn);
+
+#if DEBUG
+ printf("Found other_object in remove_other\n");
+ printf("Freeing other: %s %d %d\n", conn->other_object->name,
+ conn->x, conn->y);
+#endif
+
+ c_current->data = NULL;
+ free(conn);
+
+#if 0 /* this does not work right */
+ if (other_object->type == OBJ_BUS &&
+ other_object->conn_list == NULL) {
+ other_object->bus_ripper_direction = 0;
+ }
+#endif
+
+ return (TRUE);
+ }
+
+ c_current = c_current->next;
+ }
+
+ return (FALSE);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_conn_remove(TOPLEVEL * w_current, OBJECT * to_remove)
+{
+ GList *c_current;
+ CONN *conn;
+
+ if (to_remove->type != OBJ_PIN && to_remove->type != OBJ_NET &&
+ to_remove->type != OBJ_BUS) {
+ return;
+ }
+
+ c_current = to_remove->conn_list;
+ while (c_current != NULL) {
+ conn = (CONN *) c_current->data;
+
+#if DEBUG
+ printf("Removing: %s\n", conn->other_object->name);
+#endif
+
+ /* keep calling this till it returns false (all refs removed) */
+ /* there is NO body to this while loop */
+ while (s_conn_remove_other
+ (w_current, conn->other_object, to_remove));
+
+#if DEBUG
+ printf("returned from remove_other\n");
+ printf("Freeing: %s %d %d\n", conn->other_object->name, conn->x,
+ conn->y);
+#endif
+ c_current->data = NULL;
+ free(conn);
+ c_current = c_current->next;
+ }
+
+#if DEBUG
+ printf("length: %d\n", g_list_length(to_remove->conn_list));
+#endif
+ g_list_free(to_remove->conn_list);
+ to_remove->conn_list = NULL; /*! \todo Memory leak? TODO hack */
+
+#if 0 /* this does not work right either */
+ if (to_remove->type == OBJ_BUS)
+ {
+ to_remove->bus_ripper_direction = 0;
+ }
+#endif
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_conn_remove_complex(TOPLEVEL * w_current, OBJECT * to_remove)
+{
+ OBJECT *o_current;
+
+ if (to_remove->type != OBJ_COMPLEX && to_remove->type != OBJ_PLACEHOLDER) {
+ return;
+ }
+
+ o_current = to_remove->complex->prim_objs;
+ while (o_current != NULL) {
+ switch (o_current->type) {
+ case (OBJ_NET):
+ case (OBJ_PIN):
+ case (OBJ_BUS):
+ s_conn_remove(w_current, o_current);
+ break;
+
+ }
+ o_current = o_current->next;
+ }
+
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+OBJECT *s_conn_check_midpoint(OBJECT *o_current, int x, int y)
+{
+ int min_x, min_y, max_x, max_y;
+
+ switch(o_current->type) {
+ case(OBJ_NET):
+ case(OBJ_PIN):
+ case(OBJ_BUS):
+ min_y = min(o_current->line->y[0],
+ o_current->line->y[1]);
+ max_y = max(o_current->line->y[0],
+ o_current->line->y[1]);
+
+ /* vertical */
+ if ( (o_current->line->x[0] == x) &&
+ (y > min_y) && (y < max_y) &&
+ (o_current->line->x[0] ==
+ o_current->line->x[1]) ) {
+#if DEBUG
+ printf("Found vertical point\n");
+#endif
+ return(o_current);
+ }
+
+ min_x = min(o_current->line->x[0],
+ o_current->line->x[1]);
+ max_x = max(o_current->line->x[0],
+ o_current->line->x[1]);
+
+ /* horizontal */
+ if ( (o_current->line->y[0] == y) &&
+ (x > min_x) && (x < max_x) &&
+ (o_current->line->y[0] ==
+ o_current->line->y[1]) ) {
+#if DEBUG
+ printf("Found horizontal point\n");
+#endif
+ return(o_current);
+ }
+
+ break;
+ }
+ return(NULL);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_conn_update_object(TOPLEVEL * w_current, OBJECT * object)
+{
+ TILE *t_current;
+ TILE_LOC *tl_current;
+ GList *tloc_list;
+ GList *object_list;
+ OBJECT *other_object;
+ OBJECT *found;
+ CONN *new_conn;
+ int i, j;
+ int k;
+ int add_conn;
+
+ /* loop over all tiles which object appears in */
+ tloc_list = object->tile_locs;
+ while (tloc_list != NULL) {
+ tl_current = (TILE_LOC *) tloc_list->data;
+
+ add_conn = FALSE;
+
+ i = tl_current->i;
+ j = tl_current->j;
+
+#if DEBUG
+ printf("\nInside tile: %d %d\n\n", i, j);
+#endif
+
+ t_current = &w_current->page_current->world_tiles[i][j];
+ object_list = t_current->objects;
+ while (object_list != NULL) {
+ other_object = (OBJECT *) object_list->data;
+
+#if DEBUG
+ printf("Tile has object: %s\n", other_object->name);
+#endif
+
+ /* here is where you check the end points */
+ for (k = 0; k < 2; k++) {
+ /* do first end point */
+
+ if (object->line->x[0] == other_object->line->x[k] &&
+ object->line->y[0] == other_object->line->y[k] &&
+ object != other_object) {
+
+ if (object->type == OBJ_PIN) {
+ if (0 == object->whichend) {
+ if (other_object->type == OBJ_PIN && /* new addition */
+ k != other_object->whichend ) { /* was 0 */
+ add_conn = FALSE;
+ } else {
+ add_conn = TRUE;
+ }
+ } else {
+ add_conn = FALSE;
+ }
+ } else if (other_object->type == OBJ_PIN) {
+ if (k == other_object->whichend) {
+ if (object->type == OBJ_PIN && /* new addition */
+ k != object->whichend ) {
+ add_conn = FALSE;
+ } else {
+ add_conn = TRUE;
+ }
+ } else {
+ add_conn = FALSE;
+ }
+ } else {
+ add_conn = TRUE;
+ }
+
+ /* check for pin / bus compatibility */
+ /* you cannot connect pins and buses at all */
+ if (add_conn) {
+ if ((object->type == OBJ_PIN && other_object->type == OBJ_BUS) ||
+ (object->type == OBJ_BUS && other_object->type == OBJ_PIN)) {
+ add_conn = FALSE;
+ } else {
+ add_conn = TRUE;
+ }
+ }
+
+ /* check for net / bus compatibility */
+ /* you cannot connect the endpoint of a bus to a net */
+ /* and the reverse is true as well */
+ if (add_conn) {
+ if ((object->type == OBJ_NET && other_object->type == OBJ_BUS) ||
+ (object->type == OBJ_BUS && other_object->type == OBJ_NET)) {
+ add_conn = FALSE;
+ } else {
+ add_conn = TRUE;
+ }
+ }
+
+#if DEBUG
+ if (add_conn) {
+ printf("0\n");
+ printf("k: %d\n", k);
+ printf("object: %d\n", object->whichend);
+ printf("other: %d\n\n", other_object->whichend);
+ }
+#endif
+
+ if (add_conn) {
+ new_conn =
+ s_conn_return_new(other_object, CONN_ENDPOINT,
+ other_object->line->x[k],
+ other_object->line->y[k], 0, k);
+
+ /* do uniqness check */
+ if (s_conn_uniq(object->conn_list, new_conn)) {
+ object->conn_list =
+ g_list_append(object->conn_list, new_conn);
+ } else {
+ free(new_conn);
+ }
+
+ new_conn = s_conn_return_new(object, CONN_ENDPOINT,
+ object->line->x[0],
+ object->line->y[0], k, 0);
+
+ /* do uniqness check */
+ if (s_conn_uniq(other_object->conn_list, new_conn)) {
+ other_object->conn_list =
+ g_list_append(other_object->conn_list,
+ new_conn);
+ } else {
+ free(new_conn);
+ }
+
+#if DEBUG
+ printf("first end point -> %d\n", k);
+#endif
+ }
+ }
+
+ /* do second end point */
+ if (object->line->x[1] == other_object->line->x[k] &&
+ object->line->y[1] == other_object->line->y[k] &&
+ object != other_object) {
+
+ if (object->type == OBJ_PIN) {
+ if (1 == object->whichend) {
+ if (other_object->type == OBJ_PIN && /* new addition */
+ k != other_object->whichend ) { /* was 1 */
+ add_conn = FALSE;
+ } else {
+ add_conn = TRUE;
+ }
+ } else {
+ add_conn = FALSE;
+ }
+ } else if (other_object->type == OBJ_PIN) {
+ if (k == other_object->whichend) {
+ if (object->type == OBJ_PIN && /* new addition */
+ k != object->whichend ) {
+ add_conn = FALSE;
+ } else {
+ add_conn = TRUE;
+ }
+ } else {
+ add_conn = FALSE;
+ }
+ } else {
+ add_conn = TRUE;
+ }
+
+ /* check for pin / bus compatibility */
+ /* you cannot connect pins and buses at all */
+ if (add_conn) {
+ if ((object->type == OBJ_PIN && other_object->type == OBJ_BUS) ||
+ (object->type == OBJ_BUS && other_object->type == OBJ_PIN)) {
+ add_conn = FALSE;
+ } else {
+ add_conn = TRUE;
+ }
+ }
+
+ /* check for net / bus compatibility */
+ /* you cannot connect the endpoint of a bus to a net */
+ /* and the reverse is true as well */
+ if (add_conn) {
+ if ((object->type == OBJ_NET && other_object->type == OBJ_BUS) ||
+ (object->type == OBJ_BUS && other_object->type == OBJ_NET)) {
+ add_conn = FALSE;
+ } else {
+ add_conn = TRUE;
+ }
+ }
+
+#if DEBUG
+ if (add_conn) {
+ printf("1\n");
+ printf("k: %d\n", k);
+ printf("object: %d\n", object->whichend);
+ printf("other: %d\n\n", other_object->whichend);
+ }
+#endif
+
+ if (add_conn) {
+ new_conn =
+ s_conn_return_new(other_object, CONN_ENDPOINT,
+ other_object->line->x[k],
+ other_object->line->y[k], 1, k);
+
+ /* do uniqness check */
+ if (s_conn_uniq(object->conn_list, new_conn)) {
+ object->conn_list =
+ g_list_append(object->conn_list, new_conn);
+ } else {
+ free(new_conn);
+ }
+
+ new_conn = s_conn_return_new(object, CONN_ENDPOINT,
+ object->line->x[1],
+ object->line->y[1], k, 1);
+
+ /* do uniqness check */
+ if (s_conn_uniq(other_object->conn_list, new_conn)) {
+ other_object->conn_list =
+ g_list_append(other_object->conn_list,
+ new_conn);
+ } else {
+ free(new_conn);
+ }
+
+#if DEBUG
+ printf("second end point -> %d\n", k);
+#endif
+ }
+ }
+
+
+ /* check for midpoint of other object, k endpoint of current obj*/
+ found = s_conn_check_midpoint(other_object,
+ object->line->x[k],
+ object->line->y[k]);
+
+ /* pins are not allowed midpoint connections (on them) */
+ /* pins can cause midpoint connections (via their endpoints) */
+ if (found && other_object->type != OBJ_PIN) { /* found midpoint */
+ /* have to add it to the current object and other object */
+#if DEBUG
+ printf("%d endpoint to %s midpoint of: %s\n", k, object->name,
+ found->name);
+#endif
+
+ if (object->type == OBJ_PIN) {
+ if (k == object->whichend) {
+ add_conn = TRUE;
+ } else {
+ add_conn = FALSE;
+ }
+ } else {
+ add_conn = TRUE;
+ }
+
+ /* check for pin / bus compatibility */
+ /* you cannot connect pins and buses at all */
+ if (add_conn) {
+ if ((object->type == OBJ_PIN && other_object->type == OBJ_BUS) ||
+ (object->type == OBJ_BUS && other_object->type == OBJ_PIN)) {
+ add_conn = FALSE;
+ } else {
+ add_conn = TRUE;
+ }
+ }
+
+ /* check for bus / net compatibility */
+ /* you cannot have the middle of bus connect to nets */
+ if (add_conn) {
+ if (object->type == OBJ_BUS && other_object->type == OBJ_NET) {
+ add_conn = FALSE;
+ } else {
+ add_conn = TRUE;
+ }
+ }
+
+ if (add_conn) {
+ /* First do the other object and put it in the current */
+ /* object list */
+ new_conn =
+ s_conn_return_new(other_object, CONN_MIDPOINT,
+ object->line->x[k],
+ object->line->y[k], k, -1);
+
+ /* do uniqness check */
+ if (s_conn_uniq(object->conn_list, new_conn)) {
+ object->conn_list =
+ g_list_append(object->conn_list, new_conn);
+ } else {
+ free(new_conn);
+ }
+
+ /* Next do the current object and put it into the other */
+ /* object list */
+ new_conn = s_conn_return_new(object, CONN_MIDPOINT,
+ object->line->x[k],
+ object->line->y[k], -1, k);
+
+ /* do uniqness check */
+ if (s_conn_uniq(other_object->conn_list, new_conn)) {
+ other_object->conn_list =
+ g_list_append(other_object->conn_list,
+ new_conn);
+ } else {
+ free(new_conn);
+ }
+
+ }
+ }
+
+ /****/
+
+ /* do object's endpoints cross the middle of other_object? */
+ /* check for midpoint of other object, k endpoint of current obj*/
+ found = s_conn_check_midpoint(object,
+ other_object->line->x[k],
+ other_object->line->y[k]);
+
+ /* pins are not allowed midpoint connections (on them) */
+ /* pins can cause midpoint connections (via their endpoints) */
+ if (found && object->type != OBJ_PIN) { /* found midpoint */
+ /* have to add it to the current object and other object */
+#if DEBUG
+ printf("SECOND! %d endpoint to %s midpoint of: %s\n", k,
+ other_object->name,
+ found->name);
+#endif
+
+ if (other_object->type == OBJ_PIN) {
+ if (k == other_object->whichend) {
+ add_conn = TRUE;
+ } else {
+ add_conn = FALSE;
+ }
+ } else {
+ add_conn = TRUE;
+ }
+
+
+ /* check for pin / bus compatibility */
+ /* you cannot connect pins and buses at all */
+ if (add_conn) {
+ if ((object->type == OBJ_PIN && other_object->type == OBJ_BUS) ||
+ (object->type == OBJ_BUS && other_object->type == OBJ_PIN)) {
+ add_conn = FALSE;
+ } else {
+ add_conn = TRUE;
+ }
+ }
+
+ /* check for bus / net compatibility */
+ /* you cannot have the middle of bus connect to nets */
+ if (add_conn) {
+ if (object->type == OBJ_NET && other_object->type == OBJ_BUS) {
+ add_conn = FALSE;
+ } else {
+ add_conn = TRUE;
+ }
+ }
+
+
+ if (add_conn) {
+ /* First do the other object and put it in the current */
+ /* object list */
+ new_conn =
+ s_conn_return_new(other_object, CONN_MIDPOINT,
+ other_object->line->x[k],
+ other_object->line->y[k], -1, k);
+
+ /* do uniqness check */
+ if (s_conn_uniq(object->conn_list, new_conn)) {
+ object->conn_list =
+ g_list_append(object->conn_list, new_conn);
+ } else {
+ free(new_conn);
+ }
+
+ /* Next do the current object and put it into the other */
+ /* object list */
+ new_conn = s_conn_return_new(object, CONN_MIDPOINT,
+ other_object->line->x[k],
+ other_object->line->y[k], k, -1);
+
+ /* do uniqness check */
+ if (s_conn_uniq(other_object->conn_list, new_conn)) {
+ other_object->conn_list =
+ g_list_append(other_object->conn_list,
+ new_conn);
+ } else {
+ free(new_conn);
+ }
+
+ }
+ /* **** */
+
+ } /* found midpoint */
+
+ } /* end of for over endpoints */
+
+ object_list = object_list->next;
+ }
+
+ tloc_list = tloc_list->next;
+ }
+
+#if DEBUG
+ s_conn_print(object->conn_list);
+#endif
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_conn_update_complex(TOPLEVEL * w_current, OBJECT * complex)
+{
+ OBJECT *o_current;
+
+ o_current = complex;
+ while (o_current != NULL) {
+ switch (o_current->type) {
+ case (OBJ_PIN):
+ case (OBJ_NET):
+ case (OBJ_BUS):
+ s_conn_update_object(w_current, o_current);
+ break;
+
+ }
+ o_current = o_current->next;
+ }
+
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_conn_print(GList * conn_list)
+{
+ CONN *conn;
+ GList *cl_current;
+
+ printf("\nStarting s_conn_print\n");
+ cl_current = conn_list;
+ while (cl_current != NULL) {
+
+ conn = (CONN *) cl_current->data;
+ printf("-----------------------------------\n");
+ printf("other object: %s\n", conn->other_object->name);
+ printf("type: %d\n", conn->type);
+ printf("x: %d y: %d\n", conn->x, conn->y);
+ printf("whichone: %d\n", conn->whichone);
+ printf("other_whichone: %d\n", conn->other_whichone);
+ printf("-----------------------------------\n");
+
+ cl_current = cl_current->next;
+ }
+
+}
+
+/*! \brief Search for net in existing connections.
+ * \par Function Description
+ * This method searches the connection list for the first matching
+ * connection with the given x, y, and whichone endpoint.
+ *
+ * \param [in] new_net Net OBJECT to compare to.
+ * \param [in] whichone The connection number to check.
+ * \param [in] conn_list List of existing connections to compare
+ * <B>new_net</B> to.
+ * \return TRUE if a matching connection is found, FALSE otherwise.
+ */
+int s_conn_net_search(OBJECT* new_net, int whichone, GList * conn_list)
+{
+ CONN *conn;
+ GList *cl_current;
+
+ cl_current = conn_list;
+ while (cl_current != NULL) {
+
+ conn = (CONN *) cl_current->data;
+ if (conn != NULL && conn->whichone == whichone &&
+ conn->x == new_net->line->x[whichone] &&
+ conn->y == new_net->line->y[whichone])
+ {
+ return TRUE;
+ }
+
+ cl_current = cl_current->next;
+ }
+
+ return FALSE;
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ * \warning
+ * Caller must free returned GList pointer.
+ * Do not free individual data items in list.
+ */
+GList *s_conn_return_others(GList *input_list, OBJECT *object)
+{
+ CONN *conn;
+ GList *cl_current;
+ GList *return_list=NULL;
+
+ return_list = input_list;
+
+ cl_current = object->conn_list;
+ while (cl_current != NULL) {
+
+ conn = (CONN *) cl_current->data;
+
+ if (conn->other_object && conn->other_object != object) {
+ return_list = g_list_append(return_list, conn->other_object);
+ }
+
+ cl_current = cl_current->next;
+ }
+
+ return(return_list);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ * \warning
+ * Caller must free returned GList pointer.
+ * Do not free individual data items in list.
+ */
+GList *s_conn_return_complex_others(GList *input_list, OBJECT *object)
+{
+ OBJECT *o_current;
+ CONN *conn;
+ GList *cl_current;
+ GList *return_list=NULL;
+
+ if (object->type != OBJ_COMPLEX && object->type != OBJ_PLACEHOLDER) {
+ return(NULL);
+ }
+
+ return_list = input_list;
+
+ o_current = object->complex->prim_objs;
+ while(o_current != NULL) {
+ cl_current = o_current->conn_list;
+ while (cl_current != NULL) {
+
+ conn = (CONN *) cl_current->data;
+
+ if (conn->other_object && conn->other_object != o_current) {
+ return_list = g_list_append(return_list, conn->other_object);
+ }
+
+ cl_current = cl_current->next;
+ }
+
+ o_current = o_current->next;
+ }
+
+ return(return_list);
+}
1.4 +285 -192 eda/geda/gaf/libgeda/src/s_cue.c
(In the diff below, changes in quantity of whitespace are not shown.)
Index: s_cue.c
===================================================================
RCS file: s_cue.c
diff -N s_cue.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ s_cue.c 5 Jul 2006 03:13:38 -0000 1.4
@@ -0,0 +1,387 @@
+/* gEDA - GPL Electronic Design Automation
+ * libgeda - gEDA's library
+ * Copyright (C) 1998-2000 Ales V. Hvezda
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+#include <config.h>
+
+#include <stdio.h>
+#include <ctype.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_ASSERT_H
+#include <assert.h>
+#endif
+#ifndef HAVE_VSNPRINTF
+#include <stdarg.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <libguile.h>
+
+#include "defines.h"
+#include "struct.h"
+#include "defines.h"
+#include "globals.h"
+#include "o_types.h"
+#include "colors.h"
+
+#include "../include/prototype.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_cue_postscript_fillbox(TOPLEVEL * w_current, FILE * fp, int x,
+ int y)
+{
+ int offset;
+ int offset2;
+
+ /* hard coded values */
+ offset = CUE_BOX_SIZE;
+ offset2 = offset*2;
+
+ if (w_current->print_color) {
+ f_print_set_color(fp, w_current->net_endpoint_color);
+ }
+
+ fprintf(fp, "%d %d %d %d fbox\n",
+ offset2, offset2, x-offset, y-offset);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_cue_postscript_fillcircle(TOPLEVEL * w_current, FILE * fp,
+ int x, int y, int size_flag)
+{
+ int offset2;
+
+ if (!size_flag) {
+ offset2 = CUE_CIRCLE_LARGE_SIZE;
+ } else {
+ offset2 = CUE_CIRCLE_SMALL_SIZE;
+ }
+
+ if (w_current->print_color) {
+ f_print_set_color(fp, w_current->net_endpoint_color);
+ }
+
+ fprintf(fp, "newpath\n");
+ fprintf(fp, "%d %d\n", x, y);
+ fprintf(fp, "%d\n", offset2 / 2);
+ fprintf(fp, "0 360 arc\n");
+ fprintf(fp, "fill\n");
+}
+
+#ifdef HAS_LIBGDGEDA
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_cue_image_fillbox(TOPLEVEL * w_current, OBJECT * object, int world_x,
+ int world_y)
+{
+ int endpoint_color;
+ int offset, offset2;
+ int x, y;
+
+ if (w_current->image_color == TRUE) {
+ endpoint_color =
+ o_image_geda2gd_color(w_current->net_endpoint_color);
+ } else {
+ endpoint_color = image_black;
+ }
+
+ WORLDtoSCREEN(w_current, world_x, world_y, &x, &y);
+
+ offset = SCREENabs(w_current, CUE_BOX_SIZE);
+ offset2 = offset * 2;
+
+ gdImageFilledRectangle(current_im_ptr,
+ x - offset, y - offset, x - offset + offset2,
+ y - offset + offset2, endpoint_color);
+
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_cue_image_fillcircle(TOPLEVEL * w_current, int world_x, int world_y,
+ int size_flag)
+{
+ int endpoint_color;
+ int offset, offset2;
+ int i;
+ int x, y;
+
+ if (w_current->image_color == TRUE) {
+ endpoint_color =
+ o_image_geda2gd_color(w_current->net_endpoint_color);
+ } else {
+ endpoint_color = image_black;
+ }
+
+ WORLDtoSCREEN(w_current, world_x, world_y, &x, &y);
+
+ /* this needs to be rewritten to be much cleaner */
+ if (!size_flag) {
+ offset = SCREENabs(w_current, 30); /* large size */
+ } else {
+ offset = SCREENabs(w_current, 10); /* small size */
+ }
+ offset2 = offset * 2;
+
+ gdImageArc(current_im_ptr, x, y,
+ offset2 * 1.25, offset2 * 1.25, 0, 360, endpoint_color);
+
+ for (i = 0; i < offset2 * 1.25; i++) {
+ gdImageArc(current_im_ptr, x, y, i, i, 0, 360, endpoint_color);
+ }
+
+}
+#endif
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_cue_output_all(TOPLEVEL * w_current, OBJECT * head, FILE * fp,
+ int type)
+{
+ OBJECT *o_current;
+
+ o_current = head;
+ while (o_current != NULL) {
+ switch (o_current->type) {
+ case (OBJ_NET):
+ case (OBJ_BUS):
+ case (OBJ_PIN):
+ s_cue_output_single(w_current, o_current, fp, type);
+ break;
+
+ case (OBJ_COMPLEX):
+ case (OBJ_PLACEHOLDER):
+ s_cue_output_all(w_current, o_current->complex->prim_objs, fp,
+ type);
+ break;
+
+ }
+
+ o_current = o_current->next;
+ }
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_cue_output_lowlevel(TOPLEVEL * w_current, OBJECT * object, int whichone,
+ FILE * fp, int output_type)
+{
+ int x, y;
+ GList *cl_current;
+ CONN *conn;
+ int type, count = 0;
+ int done = FALSE;
+ int bus_involved = FALSE;
+
+ x = object->line->x[whichone];
+ y = object->line->y[whichone];
+
+ type = CONN_ENDPOINT;
+
+ cl_current = object->conn_list;
+ while (cl_current != NULL && !done) {
+ conn = (CONN *) cl_current->data;
+
+ if (conn->x == x && conn->y == y) {
+ switch (conn->type) {
+
+ case (CONN_ENDPOINT):
+ count++;
+ if (conn->other_object &&
+ ((object->type == OBJ_NET &&
+ conn->other_object->type == OBJ_BUS) ||
+ (object->type == OBJ_BUS &&
+ conn->other_object->type == OBJ_NET))) {
+ bus_involved=TRUE;
+ }
+ break;
+
+ case (CONN_MIDPOINT):
+ type = CONN_MIDPOINT;
+ done = TRUE;
+ count = 0;
+ if (conn->other_object &&
+ ((object->type == OBJ_NET &&
+ conn->other_object->type == OBJ_BUS) ||
+ (object->type == OBJ_BUS &&
+ conn->other_object->type == OBJ_NET))) {
+ bus_involved=TRUE;
+ }
+ break;
+ }
+ }
+
+ cl_current = cl_current->next;
+ }
+
+#if DEBUG
+ printf("type: %d count: %d\n", type, count);
+#endif
+
+ switch (type) {
+
+ case (CONN_ENDPOINT):
+ if (object->type == OBJ_NET) { /* only nets have these cues */
+ if (count < 1) { /* Didn't find anything connected there */
+ if (output_type == POSTSCRIPT) {
+ s_cue_postscript_fillbox(w_current, fp, x, y);
+#ifdef HAS_LIBGDGEDA
+ } else if (output_type == PNG) {
+ s_cue_image_fillbox(w_current, object, x, y);
+#endif
+ }
+
+
+ } else if (count >= 2) {
+ if (output_type == POSTSCRIPT) {
+ if (!bus_involved) {
+ s_cue_postscript_fillcircle(w_current, fp, x, y, FALSE);
+ } else {
+ s_cue_postscript_fillcircle(w_current, fp, x, y, TRUE);
+ }
+#ifdef HAS_LIBGDGEDA
+ } else if (output_type == PNG) {
+ if (!bus_involved) {
+ s_cue_image_fillcircle(w_current, x, y, FALSE);
+ } else {
+ s_cue_image_fillcircle(w_current, x, y, TRUE);
+ }
+#endif
+ }
+ }
+ }
+ break;
+
+ case (CONN_MIDPOINT):
+ if (output_type == POSTSCRIPT) {
+ if (!bus_involved) {
+ s_cue_postscript_fillcircle(w_current, fp, x, y, FALSE);
+ } else {
+ s_cue_postscript_fillcircle(w_current, fp, x, y, TRUE);
+ }
+#ifdef HAS_LIBGDGEDA
+ } else if (output_type == PNG) {
+ if (!bus_involved) {
+ s_cue_image_fillcircle(w_current, x, y, FALSE);
+ } else {
+ s_cue_image_fillcircle(w_current, x, y, TRUE);
+ }
+#endif
+ }
+ }
+
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_cue_output_lowlevel_midpoints(TOPLEVEL * w_current, OBJECT * object,
+ FILE * fp, int output_type)
+{
+ int x, y;
+ GList *cl_current;
+ CONN *conn;
+ int size_flag;
+
+ cl_current = object->conn_list;
+ while (cl_current != NULL) {
+ conn = (CONN *) cl_current->data;
+
+ switch (conn->type) {
+ case (CONN_MIDPOINT):
+
+ x = conn->x;
+ y = conn->y;
+
+ if (conn->other_object &&
+ ( (object->type == OBJ_BUS &&
+ conn->other_object->type == OBJ_NET) ||
+ (object->type == OBJ_NET &&
+ conn->other_object->type == OBJ_BUS))) {
+ size_flag = TRUE;
+ } else {
+ size_flag = FALSE;
+ }
+
+
+ if (output_type == POSTSCRIPT) {
+ s_cue_postscript_fillcircle(w_current, fp, x, y, size_flag);
+#ifdef HAS_LIBGDGEDA
+ } else if (output_type == PNG) {
+ s_cue_image_fillcircle(w_current, x, y, size_flag);
+#endif
+ }
+ break;
+ }
+
+
+ cl_current = cl_current->next;
+ }
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_cue_output_single(TOPLEVEL * w_current, OBJECT * object, FILE * fp,
+ int type)
+{
+ if (!object) {
+ return;
+ }
+
+ if (object->type != OBJ_NET && object->type != OBJ_PIN &&
+ object->type != OBJ_BUS) {
+ return;
+ }
+
+ s_cue_output_lowlevel(w_current, object, 0, fp, type);
+ s_cue_output_lowlevel(w_current, object, 1, fp, type);
+ s_cue_output_lowlevel_midpoints(w_current, object, fp, type);
+}
+
+
+
1.1 eda/geda/gaf/libgeda/src/s_encoding.c
Index: s_encoding.c
===================================================================
/*! \verbatim
***********************************************************************
* _ _ __ _ _
* __ _ _ __ ___| |_ | |__ __ _ ___ ___ / /_ | || |
* / _` | '_ \ / _ \ __| | '_ \ / _` / __|/ _ \ '_ \| || |_
* | (_| | | | | __/ |_ | |_) | (_| \__ \ __/ (_) |__ _|
* \__, |_| |_|\___|\__| |_.__/ \__,_|___/\___|\___/ |_|
* |___/
*
* created by Alfred Reibenschuh <alfredreibenschuh@xxxxxxx>,
* under the ``GNU Library General Public License´´ (see below).
*
***********************************************************************
*
* Copyright (C) 2003 Free Software Foundation
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*
***********************************************************************
\endverbatim
*
* Taken from gnet's sources
* Modified the name of the functions and some variables
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#include <ctype.h>
#include <glib.h>
#ifdef HAVE_STRING_H
#include <string.h>
#endif
static gchar s_encoding_Base64[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
#define s_encoding_Pad64 '='
static guchar s_encoding_Base64_rank[256] = {
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, /* 0x00-0x0f */
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, /* 0x10-0x1f */
255,255,255,255,255,255,255,255,255,255,255, 62,255,255,255, 63, /* 0x20-0x2f */
52, 53, 54, 55, 56, 57, 58, 59, 60, 61,255,255,255,255,255,255, /* 0x30-0x3f */
255, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, /* 0x40-0x4f */
15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25,255,255,255,255,255, /* 0x50-0x5f */
255, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, /* 0x60-0x6f */
41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51,255,255,255,255,255, /* 0x70-0x7f */
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, /* 0x80-0x8f */
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, /* 0x90-0x9f */
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, /* 0xa0-0xaf */
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, /* 0xb0-0xbf */
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, /* 0xc0-0xcf */
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, /* 0xd0-0xdf */
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, /* 0xe0-0xef */
255,255,255,255,255,255,255,255,255,255,255,255,255,255,255,255, /* 0xf0-0xff */
};
/*! \brief Convert a buffer from binary to base64 representation.
* \par Function Description
* Convert a buffer from binary to base64 representation. Set
* <B>strict</B> to TRUE to insert a newline every 72th character. This is
* required by RFC 2045, but some applications don't require this.
*
* \param [in] src Source buffer.
* \param [in] srclen Length of source buffer.
* \param [out] dstlenp Length of buffer returned
* (including the terminating \\0).
* \param [in] strict Insert new lines as required by RFC 2045.
* \return Caller owned buffer containing base64 representation.
*/
gchar* s_encoding_base64_encode (gchar* src, guint srclen,
guint* dstlenp, gboolean strict)
{
gchar* dst;
guint dstpos;
guchar input[3];
guchar output[4];
guint ocnt;
guint i;
if (srclen == 0)
return NULL; /* FIX: Or return ""? */
/* Calculate required length of dst. 4 bytes of dst are needed for
every 3 bytes of src. */
*dstlenp = (((srclen + 2) / 3) * 4)+5;
if (strict)
*dstlenp += (*dstlenp / 72); /* Handle trailing \n */
dst = g_new(gchar, *dstlenp );
/* bulk encoding */
dstpos = 0;
ocnt = 0;
while (srclen >= 3)
{
/*
Convert 3 bytes of src to 4 bytes of output
output[0] = input[0] 7:2
output[1] = input[0] 1:0 input[1] 7:4
output[2] = input[1] 3:0 input[2] 7:6
output[3] = input[1] 5:0
*/
input[0] = *src++;
input[1] = *src++;
input[2] = *src++;
srclen -= 3;
output[0] = (input[0] >> 2);
output[1] = ((input[0] & 0x03) << 4) +
(input[1] >> 4);
output[2] = ((input[1] & 0x0f) << 2) +
(input[2] >> 6);
output[3] = (input[2] & 0x3f);
g_assert ((dstpos + 4) < *dstlenp);
/* Map output to the Base64 alphabet */
dst[dstpos++] = s_encoding_Base64[(guint) output[0]];
dst[dstpos++] = s_encoding_Base64[(guint) output[1]];
dst[dstpos++] = s_encoding_Base64[(guint) output[2]];
dst[dstpos++] = s_encoding_Base64[(guint) output[3]];
/* Add a newline if strict and */
if (strict)
if ((++ocnt % (72/4)) == 0)
dst[dstpos++] = '\n';
}
/* Now worry about padding with remaining 1 or 2 bytes */
if (srclen != 0)
{
input[0] = input[1] = input[2] = '\0';
for (i = 0; i < srclen; i++)
input[i] = *src++;
output[0] = (input[0] >> 2);
output[1] = ((input[0] & 0x03) << 4) +
(input[1] >> 4);
output[2] = ((input[1] & 0x0f) << 2) +
(input[2] >> 6);
g_assert ((dstpos + 4) < *dstlenp);
dst[dstpos++] = s_encoding_Base64[(guint) output[0]];
dst[dstpos++] = s_encoding_Base64[(guint) output[1]];
if (srclen == 1)
dst[dstpos++] = s_encoding_Pad64;
else
dst[dstpos++] = s_encoding_Base64[(guint) output[2]];
dst[dstpos++] = s_encoding_Pad64;
}
g_assert (dstpos <= *dstlenp);
dst[dstpos] = '\0';
*dstlenp = dstpos + 1;
return dst;
}
/*! \brief Convert a buffer from base64 to binary representation.
* \par Function Description
* Convert a buffer from base64 to binary representation. This
* function is liberal in what it will accept. It ignores non-base64
* symbols.
*
* \param [in] src Source buffer.
* \param [in] srclen Length of the source buffer.
* \param [out] dstlenp Pointer to length of the destination buffer
* \return Caller-owned buffer with binary representation.
* The integer pointed to by <B>dstlenp</B> is set to the length
* of that buffer.
*/
gchar *s_encoding_base64_decode (gchar* src, guint srclen, guint* dstlenp)
{
gchar* dst;
guint dstidx, state, ch = 0;
gchar res;
guchar pos;
if (srclen == 0)
srclen = strlen(src);
state = 0;
dstidx = 0;
res = 0;
dst = g_new(gchar, srclen+1);
*dstlenp = srclen+1;
while (srclen-- > 0)
{
ch = *src++;
if (s_encoding_Base64_rank[ch]==255) /* Skip any non-base64 anywhere */
continue;
if (ch == s_encoding_Pad64)
break;
pos = s_encoding_Base64_rank[ch];
switch (state)
{
case 0:
if (dst != NULL)
{
dst[dstidx] = (pos << 2);
}
state = 1;
break;
case 1:
if (dst != NULL)
{
dst[dstidx] |= (pos >> 4);
res = ((pos & 0x0f) << 4);
}
dstidx++;
state = 2;
break;
case 2:
if (dst != NULL)
{
dst[dstidx] = res | (pos >> 2);
res = (pos & 0x03) << 6;
}
dstidx++;
state = 3;
break;
case 3:
if (dst != NULL)
{
dst[dstidx] = res | pos;
}
dstidx++;
state = 0;
break;
default:
break;
}
}
/*
* We are done decoding Base-64 chars. Let's see if we ended
* on a byte boundary, and/or with erroneous trailing characters.
*/
if (ch == s_encoding_Pad64) /* We got a pad char. */
{
switch (state)
{
case 0: /* Invalid = in first position */
case 1: /* Invalid = in second position */
return NULL;
case 2: /* Valid, means one byte of info */
/* Skip any number of spaces. */
while (srclen-- > 0)
{
ch = *src++;
if (s_encoding_Base64_rank[ch] != 255) break;
}
/* Make sure there is another trailing = sign. */
if (ch != s_encoding_Pad64)
{
g_free(dst);
*dstlenp = 0;
return NULL;
}
/* FALLTHROUGH */
case 3: /* Valid, means two bytes of info */
/*
* We know this char is an =. Is there anything but
* whitespace after it?
*/
while (srclen-- > 0)
{
ch = *src++;
if (s_encoding_Base64_rank[ch] != 255)
{
g_free(dst);
*dstlenp = 0;
return NULL;
}
}
/*
* Now make sure for cases 2 and 3 that the "extra"
* bits that slopped past the last full byte were
* zeros. If we don't check them, they become a
* subliminal channel.
*/
if (dst != NULL && res != 0)
{
g_free(dst);
*dstlenp = 0;
return NULL;
}
default:
break;
}
} else
{
/*
* We ended by seeing the end of the string. Make sure we
* have no partial bytes lying around.
*/
if (state != 0)
{
g_free(dst);
*dstlenp = 0;
return NULL;
}
}
dst[dstidx]=0;
*dstlenp = dstidx;
return dst;
}
1.13 +353 -190 eda/geda/gaf/libgeda/src/s_hierarchy.c
(In the diff below, changes in quantity of whitespace are not shown.)
Index: s_hierarchy.c
===================================================================
RCS file: s_hierarchy.c
diff -N s_hierarchy.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ s_hierarchy.c 5 Jul 2006 03:13:39 -0000 1.13
@@ -0,0 +1,430 @@
+/* gEDA - GPL Electronic Design Automation
+ * libgeda - gEDA's library
+ * Copyright (C) 1998-2000 Ales V. Hvezda
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+#include <config.h>
+
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_ASSERT_H
+#include <assert.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <libguile.h>
+
+#include "defines.h"
+#include "struct.h"
+#include "defines.h"
+#include "globals.h"
+#include "o_types.h"
+
+#include "../include/prototype.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+/*! \brief */
+static int page_control_counter=0;
+
+/*! \todo Finish function documentation!!!
+ * \brief Search for schematic associated source files and load them.
+ * \par Function Description
+ * This function searches the associated source file refered by the
+ * <B>filename</B> and loads it. If the <B>flag</B> is set to
+ * <B>HIERARCHY_NORMAL_LOAD</B> and the page is allready in the list of
+ * pages it will return the <B>pid</B> of that page.
+ * If the <B>flag</B> is set to <B>HIERARCHY_FORCE_LOAD</B> then this
+ * function will load the page again with a new page id. The second case
+ * is mainly used by gnetlist where pushed down schematics MUST be unique.
+ *
+ * \param [in] w_current The TOPLEVEL object.
+ * \param [in] filename Schematic file name.
+ * \param [in] parent The parent page of the schematic.
+ * \param [in] page_control
+ * \param [in] flag
+ * \return The number of pages loaded, -1 otherwise.
+ *
+ * \note
+ * This function goes and finds the associated source files and
+ * loads all up
+ * It only works for schematic files though
+ * this is basically push
+ * flag can either be HIERARCHY_NORMAL_LOAD or HIERARCHY_FORCE_LOAD
+ * flag is mainly used by gnetlist where pushed down schematics MUST be unique
+ */
+int s_hierarchy_down_schematic_single(TOPLEVEL *w_current,
+ const gchar *filename, PAGE *parent,
+ int page_control, int flag)
+{
+ gchar *string;
+ PAGE *found;
+ PAGE *forbear;
+
+ string = s_slib_search_single(filename);
+ if (string == NULL) {
+ return -1;
+ }
+
+ switch (flag) {
+ case HIERARCHY_NORMAL_LOAD:
+ {
+ found = s_page_search (w_current, string);
+
+ if (found) {
+ /* check whether this page is in the parents list */
+ for (forbear = parent;
+ forbear != NULL && found->pid != forbear->pid && forbear->up >= 0;
+ forbear = s_page_search_pid(w_current, forbear->up))
+ ; /* void */
+
+ if (found->pid == forbear->pid) {
+ s_log_message("hierarchy loop detected while visiting page:\n"
+ " \"%s\"\n",found->page_filename);
+ return -1; /* error signal */
+ }
+ s_page_goto (w_current, found);
+ if (page_control != 0) {
+ found->page_control = page_control;
+ }
+ found->up = parent->pid;
+ g_free (string);
+ return found->page_control;
+ }
+
+ found = s_page_new (w_current, string);
+ s_page_goto (w_current, found);
+
+ f_open (w_current, found->page_filename);
+ }
+ break;
+
+ case HIERARCHY_FORCE_LOAD:
+ {
+ PAGE *page = s_page_new (w_current, string);
+ s_page_goto (w_current, page);
+ f_open (w_current, page->page_filename);
+ }
+ break;
+ }
+
+ if (page_control == 0) {
+ page_control_counter++;
+ w_current->page_current->page_control = page_control_counter;
+ } else {
+ w_current->page_current->page_control = page_control;
+ }
+
+ w_current->page_current->up = parent->pid;
+
+ s_page_goto(w_current, w_current->page_current);
+
+ g_free (string);
+
+ return(page_control_counter);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ * \note
+ * This function goes and finds the associated source files and loads ALL up
+ * only works for schematic files though
+ * this is basically push
+ */
+void s_hierarchy_down_schematic_multiple (TOPLEVEL *w_current,
+ const gchar *filename, PAGE *parent)
+{
+ char *string=NULL;
+ PAGE *save_first_page=NULL;
+ PAGE *found;
+ int loaded_schematics=0;
+
+ s_slib_search (NULL, SLIB_SEARCH_START);
+
+ string = s_slib_search (filename, SLIB_SEARCH_NEXT);
+ while (string != NULL) {
+
+ found = s_page_new(w_current, string);
+
+ if (found) {
+ w_current->page_current = found;
+ s_page_goto(w_current, found);
+ if (string)
+ free(string);
+ return;
+ }
+
+ f_open(w_current, w_current->page_current->page_filename);
+
+ if (loaded_schematics == 0) {
+ page_control_counter++;
+ save_first_page = w_current->page_current;
+ /* parent->down = w_current->page_current; not needed */
+ w_current->page_current->page_control =
+ page_control_counter;
+ loaded_schematics=1;
+ } else {
+ w_current->page_current->page_control =
+ page_control_counter;
+ }
+
+ w_current->page_current->up = parent->pid;
+ /* w_current->page_current->down = NULL; not needed */
+
+ if (string)
+ free(string);
+
+ string = s_slib_search(filename, SLIB_SEARCH_NEXT);
+ }
+
+ s_slib_search(NULL, SLIB_SEARCH_DONE);
+
+ g_free (string);
+
+ if (loaded_schematics) {
+ w_current->page_current = save_first_page;
+ }
+
+ s_page_goto (w_current, w_current->page_current);
+
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_hierarchy_down_symbol (TOPLEVEL *w_current,
+ const gchar *filename, PAGE *parent)
+{
+ PAGE *page;
+
+ page = s_page_search (w_current, filename);
+ if (page) {
+ s_page_goto (w_current, page);
+ return;
+ }
+
+ page = s_page_new (w_current, filename);
+ s_page_goto (w_current, page);
+
+ f_open(w_current, page->page_filename);
+
+ page->up = parent->pid;
+ page_control_counter++;
+ page->page_control = page_control_counter;
+
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_hierarchy_up(TOPLEVEL *w_current, int pid)
+{
+ PAGE *p_current;
+
+ if (pid < 0) {
+ s_log_message("There are no schematics above the current one!\n");
+ return;
+ }
+
+ p_current = s_hierarchy_find_page(w_current->page_head, pid);
+
+ if (p_current) {
+ s_page_goto(w_current, p_current);
+ } else {
+ s_log_message("Cannot find any schematics above the current one!\n");
+ s_log_message("Maybe toplevel schematic page was closed/discarded?\n");
+ }
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ * This function traverses the hierarchy tree of pages and returns a flat
+ * list of pages that are below the current page. There are two
+ * <B>flags</B>: <B>HIERARCHY_NODUPS</B>: returns a list without
+ * duplicate pages
+ * <B>HIERARCHY_POSTORDER</B>: traverses the hierarchy tree and
+ * returns a postorder list instead of preorder.
+ *
+ * \return A GList of PAGE pointers.
+ *
+ * \warning
+ * Call must free returned GList.
+ */
+GList *s_hierarchy_traversepages(TOPLEVEL *w_current,
+ gint flags)
+{
+ PAGE *p_current;
+ OBJECT *o_current;
+ char *filename = NULL;
+ gint page_control = 0;
+ static GList *pages = NULL;
+
+ /* init static variables the first time*/
+ if (!(flags & HIERARCHY_INNERLOOP)) {
+ pages = NULL;
+ }
+
+ p_current = w_current->page_current;
+
+ /* preorder traversing */
+ if (!(flags & HIERARCHY_POSTORDER)) {
+ /* check whether we already visited this page */
+ if ((flags & HIERARCHY_NODUPS)
+ && (g_list_find(pages, p_current) != NULL)) {
+ return pages; /* drop the page subtree */
+ }
+ pages = g_list_append(pages, p_current);
+ }
+
+ /* walk throught the page objects and search for underlaying schematics */
+ for (o_current = p_current->object_head;
+ o_current != NULL ;
+ o_current = o_current->next) {
+
+ /* only complex things like symbols can contain attributes */
+ if (o_current->type == OBJ_COMPLEX) {
+ filename = o_attrib_search_name_single_count(o_current,
+ "source", 0);
+
+ /* if above is NULL, then look inside symbol */
+ if (filename == NULL) {
+ filename = o_attrib_search_name(o_current->
+ complex->prim_objs, "source", 0);
+ }
+
+ if (filename != NULL) {
+ /* we got a schematic source attribute
+ lets load the page and dive into it */
+ page_control =s_hierarchy_down_schematic_single(w_current,
+ filename,
+ p_current,
+ 0,
+ HIERARCHY_NORMAL_LOAD);
+ if (page_control != -1) {
+ /* call the recursive function */
+ s_hierarchy_traversepages(w_current,
+ flags | HIERARCHY_INNERLOOP);
+ s_hierarchy_up(w_current, w_current->page_current->up);
+ }
+ else {
+ s_log_message("ERROR in s_hierarchy_traverse: "
+ "schematic not found: %s\n",
+ filename);
+ }
+
+ g_free(filename);
+ filename = NULL;
+ }
+ }
+ }
+
+ /* postorder traversing */
+ if (flags & HIERARCHY_POSTORDER) {
+ /* check whether we already visited this page */
+ if ((flags & HIERARCHY_NODUPS)
+ && (g_list_find(pages, p_current) != NULL)) {
+ return pages; /* don't append it */
+ }
+ pages = g_list_append(pages, p_current);
+ }
+
+ return pages;
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ * \note
+ * Test function which only prints the name of a page and it's number.
+ */
+gint s_hierarchy_print_page(PAGE *p_current, void * data)
+{
+ printf("pagefilename: %s pageid: %d\n",
+ p_current->page_filename, p_current->pid);
+ return 0;
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+PAGE *s_hierarchy_find_prev_page (PAGE *p_start, int page_control)
+{
+ PAGE *p_current;
+
+ for (p_current = p_start->prev;
+ p_current != NULL;
+ p_current = p_current->prev) {
+ if (p_current->page_control == page_control) {
+ return p_current;
+ }
+ }
+
+ return NULL;
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+PAGE *s_hierarchy_find_next_page (PAGE *p_start, int page_control)
+{
+ PAGE *p_current;
+
+ for (p_current = p_start->next;
+ p_current != NULL;
+ p_current = p_current->next) {
+ if (p_current->page_control == page_control) {
+ return p_current;
+ }
+ }
+
+ return NULL;
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+PAGE *s_hierarchy_find_page (PAGE *p_start, int pid)
+{
+ PAGE *p_current = p_start;
+
+ for (p_current = p_start;
+ p_current != NULL;
+ p_current = p_current->next) {
+ if (p_current->pid == pid) {
+ return p_current;
+ }
+ }
+
+ return NULL;
+}
1.12 +149 -83 eda/geda/gaf/libgeda/src/s_log.c
(In the diff below, changes in quantity of whitespace are not shown.)
Index: s_log.c
===================================================================
RCS file: s_log.c
diff -N s_log.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ s_log.c 5 Jul 2006 03:13:39 -0000 1.12
@@ -0,0 +1,200 @@
+/* gEDA - GPL Electronic Design Automation
+ * libgeda - gEDA's library
+ * Copyright (C) 1998-2000 Ales V. Hvezda
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+#include <config.h>
+
+#include <stdio.h>
+#include <sys/stat.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_ASSERT_H
+#include <assert.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#endif
+#ifdef HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#ifdef HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <libguile.h>
+
+#include "defines.h"
+#include "struct.h"
+#include "defines.h"
+#include "globals.h"
+#include "funcs.h"
+#include "o_types.h"
+
+#include "../include/prototype.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+
+static void s_log_handler (const gchar *log_domain,
+ GLogLevelFlags log_level,
+ const gchar *message,
+ gpointer user_data);
+
+static int logfile_fd = -1;
+
+static guint log_handler_id;
+
+/*! \brief Initialize libgeda logging feature.
+ * \par Function Description
+ * This function opens the file <B>filename</B> to log to and registers the
+ * handler to redirect log message to this file.
+ *
+ * \param [in] filename Character string with file name to log to.
+ */
+void s_log_init (const gchar *filename)
+{
+ if (do_logging == FALSE) {
+ logfile_fd = -1;
+ return;
+ }
+
+ /* create log file */
+ logfile_fd = open (filename, O_RDWR|O_CREAT|O_TRUNC, 0600);
+ if (logfile_fd == -1) {
+ fprintf(stderr, "Could not open log file: %s\n", filename);
+ fprintf(stderr, "Errno was: %d\n", errno);
+ return;
+ }
+
+ /* install the log handler */
+ log_handler_id = g_log_set_handler (NULL,
+ G_LOG_LEVEL_MESSAGE,
+ s_log_handler,
+ NULL);
+
+}
+
+/*! \brief Terminates the logging of messages.
+ * \par Function Description
+ * This function deregisters the handler for redirection to the log file
+ * and closes it.
+ */
+void s_log_close (void)
+{
+ do_logging = FALSE; /* subsequent messages are lost after the close */
+
+ if (logfile_fd == -1)
+ {
+ return;
+ }
+
+ /* remove the handler */
+ g_log_remove_handler (NULL, log_handler_id);
+
+ /* close the file */
+ if (logfile_fd != -1) {
+ close (logfile_fd);
+ logfile_fd = -1;
+ }
+
+}
+
+/*! \brief Reads the current log file and returns its contents.
+ * \par Function Description
+ * This function reads the current log file and returns its contents.
+ *
+ * \return Character string with current log's contents.
+ *
+ */
+gchar *s_log_read (void)
+{
+ gboolean tmp;
+#define BUFSIZE 200
+ gchar buf[BUFSIZE];
+ GString *contents;
+ gint len;
+
+ if (logfile_fd == -1) {
+ return NULL;
+ }
+
+ tmp = do_logging;
+ do_logging = FALSE;
+
+ /* rewind the file */
+ lseek(logfile_fd, 0, SEEK_SET);
+
+ /* read its contents and build a string */
+ contents = g_string_new ("");
+ while ((len = read (logfile_fd, &buf, BUFSIZE)) != 0) {
+ contents = g_string_append_len (contents, buf, len);
+ }
+
+ do_logging = tmp;
+
+ return g_string_free (contents, FALSE);
+}
+
+/*! \brief Write a message to the current log file.
+ * \par Function Description
+ * Writes <B>message</B> to the current log file whose file descriptor
+ * is <B>logfile_fd</B>.
+ *
+ * It also sends <B>message</B> to the optional function <B>x_log_update</B>
+ * for further use.
+ *
+ * \param [in] log_domain (unused).
+ * \param [in] log_level (unused).
+ * \param [in] message Character string containing message to
+ * write to log.
+ * \param [in] user_data (unused).
+ *
+ */
+static void s_log_handler (const gchar *log_domain,
+ GLogLevelFlags log_level,
+ const gchar *message,
+ gpointer user_data)
+{
+ int status;
+
+ if (do_logging == FALSE) {
+ return;
+ }
+ g_assert (logfile_fd != -1);
+
+ status = write (logfile_fd, message, strlen (message));
+ if (status == -1) {
+ fprintf(stderr, "Could not write message to log file\n");
+ fprintf(stderr, "Message was: %s\n", message);
+ fprintf(stderr, "Errno was: %d\n", errno);
+ }
+
+ if (x_log_update_func) {
+ (*x_log_update_func) (message);
+ }
+
+}
1.1 eda/geda/gaf/libgeda/src/s_menu.c
Index: s_menu.c
===================================================================
/* gEDA - GPL Electronic Design Automation
* libgeda - gEDA's library
* Copyright (C) 1998-2000 Ales V. Hvezda
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
*/
#include <config.h>
#include <stdio.h>
#include <sys/types.h>
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#if defined(HAVE_DIRENT_H)
#include <dirent.h>
#endif
#include <gtk/gtk.h>
#include <libguile.h>
#include "defines.h"
#include "struct.h"
#include "globals.h"
#include "../include/prototype.h"
#ifdef HAVE_LIBDMALLOC
#include <dmalloc.h>
#endif
/*! \brief */
struct st_menu {
char *menu_name;
SCM menu_items;
};
static int menu_index=0;
#define MAX_MENUS 32
/* and eventually make this unlimited */
/* hack hack */
static struct st_menu menu[MAX_MENUS];
/*! \todo Finish function documentation!!!
* \brief
* \par Function Description
*
*/
int s_menu_return_num(void)
{
return(menu_index);
}
/*! \todo Finish function documentation!!!
* \brief
* \par Function Description
*
*/
SCM s_menu_return_entry(int index, char **menu_name)
{
if (menu_name == NULL) {
return SCM_BOOL_F;
}
if (index > MAX_MENUS || index < 0) {
*menu_name = NULL;
return SCM_BOOL_F;
}
*menu_name = menu[index].menu_name;
return(menu[index].menu_items);
}
/*! \todo Finish function documentation!!!
* \brief
* \par Function Description
*
*/
int s_menu_add_entry(char *new_menu, SCM menu_items)
{
if (new_menu == NULL) {
return(-1);
}
if (menu_index >= MAX_MENUS) {
return(-1);
}
menu[menu_index].menu_name = g_strdup (new_menu);
menu[menu_index].menu_items = menu_items;
menu_index++;
return(menu_index);
}
/*! \todo Finish function documentation!!!
* \brief
* \par Function Description
*
*/
void s_menu_print()
{
int i;
for (i = 0; i < menu_index; i++) {
printf("Name; %s\n", menu[i].menu_name);
scm_display (menu[i].menu_items, scm_current_output_port ());
printf("\n");
}
}
/*! \todo Finish function documentation!!!
* \brief
* \par Function Description
*
*/
void s_menu_free()
{
int i;
for (i = 0; i < menu_index; i++) {
if (menu[i].menu_name) {
free(menu[i].menu_name);
menu[i].menu_name = NULL;
}
}
menu_index=0;
}
/*! \todo Finish function documentation!!!
* \brief
* \par Function Description
*
*/
void s_menu_init()
{
int i;
for (i = 0; i < MAX_MENUS; i++) {
menu[i].menu_name = NULL;
}
}
1.23 +521 -396 eda/geda/gaf/libgeda/src/s_page.c
(In the diff below, changes in quantity of whitespace are not shown.)
Index: s_page.c
===================================================================
RCS file: s_page.c
diff -N s_page.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ s_page.c 5 Jul 2006 03:13:39 -0000 1.23
@@ -0,0 +1,571 @@
+/* gEDA - GPL Electronic Design Automation
+ * libgeda - gEDA's library
+ * Copyright (C) 1998-2000 Ales V. Hvezda
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+#include <config.h>
+
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#ifdef HAVE_ASSERT_H
+#include <assert.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <glib.h>
+#include <libguile.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <unistd.h>
+
+#include "defines.h"
+#include "struct.h"
+#include "globals.h"
+#include "o_types.h"
+#include "funcs.h"
+
+#include "../include/prototype.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+static gint global_pid = 0;
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ * Creates a new page and add it to <B>toplevel</B>'s list of pages.
+ *
+ * It initializes the #PAGE structure and set its <B>page_filename</B>
+ * to <B>filename</B>. <B>toplevel</B>'s current page is not changed by
+ * this function.
+ */
+PAGE *s_page_new (TOPLEVEL *toplevel, const gchar *filename)
+{
+ PAGE *page;
+
+ /* Now create a blank page */
+ page = (PAGE*)g_new (PAGE, 1);
+
+ page->pid = global_pid++;
+
+ page->CHANGED = 0;
+
+ /* big assumption here that page_filename isn't null */
+ if (g_path_is_absolute (filename)) {
+ page->page_filename = g_strdup (filename);
+ } else {
+ gchar *pwd = g_get_current_dir ();
+ page->page_filename = g_strconcat (pwd,
+ G_DIR_SEPARATOR_S,
+ filename,
+ NULL);
+ g_free (pwd);
+ }
+
+ g_assert (toplevel->init_bottom != 0);
+ page->coord_aspectratio = (
+ ((float) toplevel->init_right) / ((float) toplevel->init_bottom));
+
+ page->up = -2;
+ page->page_control = 0;
+
+ /* Init tile array */
+ s_tile_init (toplevel, page);
+
+ /* First one to setup head */
+ page->object_head = s_basic_init_object("object_head");
+ page->object_head->type = OBJ_HEAD;
+
+ /* new selection mechanism */
+ page->selection2_head = page->selection2_tail =
+ o_selection_new_head();
+
+ /* net/pin/bus stretch when doing moves */
+ page->stretch_head = page->stretch_tail = s_stretch_new_head();
+
+ page->complex_place_tail = page->complex_place_head =
+ s_basic_init_object("complex_place_head");
+ page->complex_place_tail->type = OBJ_HEAD;
+
+ /* add p_attrib and p_attached_to */
+ page->attrib_place_tail = page->attrib_place_head =
+ s_basic_init_object("attrib_place_head");
+ page->attrib_place_tail->type = OBJ_HEAD;
+
+ /* do this just to be sure that object tail is truely correct */
+ page->object_tail = return_tail(page->object_head);
+
+ /* setup parent to point to list */
+ /* this is used for attributes so */
+ /* that we know which list to search */
+ page->object_parent = page->object_head;
+
+ /* init undo struct pointers */
+ s_undo_init(page);
+
+ page->object_lastplace = NULL;
+ page->object_selected = NULL;
+
+ set_window (toplevel, page,
+ toplevel->init_left, toplevel->init_right,
+ toplevel->init_top, toplevel->init_bottom);
+
+ /* Backup variables */
+ g_get_current_time (&page->last_load_or_save_time);
+ page->ops_since_last_backup = 0;
+ page->saved_since_first_loaded = 0;
+ page->do_autosave_backup = 0;
+
+ page->load_newer_backup_func = load_newer_backup_func;
+
+ /* now append page to page list of toplevel */
+ toplevel->page_tail->next = page;
+ page->prev = toplevel->page_tail;
+ page->next = NULL;
+ toplevel->page_tail = page;
+
+ return page;
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ * Deletes a single page <B>page</B> from <B>toplevel</B>'s list of pages.
+ *
+ * This function is not appropriate for deleting page head.
+ * See #s_page_delete_list() for that.
+ *
+ * If the current page of toplevel is given as parameter <B>page</B>,
+ * the function sets the field <B>page_current</B> of the TOPLEVEL
+ * struct to NULL.
+ */
+void s_page_delete (TOPLEVEL *toplevel, PAGE *page)
+{
+ PAGE *tmp;
+ gchar *backup_filename;
+ gchar *real_filename;
+ gchar *only_filename;
+ gchar *dirname;
+
+ g_assert (page->pid != -1);
+
+ /* we need to play with page_current because s_delete_list_fromstart() */
+ /* make use of it (see s_tile_remove_object_all) */
+
+ /* save page_current and switch to page */
+ if (page == toplevel->page_current) {
+ tmp = NULL;
+ } else {
+ tmp = toplevel->page_current;
+ s_page_goto (toplevel, page);
+ }
+
+ /* Get the real filename and file permissions */
+ real_filename = follow_symlinks (page->page_filename, NULL);
+
+ if (real_filename == NULL) {
+ s_log_message ("s_page_delete: Can't get the real filename of %s.", page->page_filename);
+ fprintf (stderr, "s_page_delete: Can't get the real filename of %s.\n", page->page_filename);
+ }
+ else {
+ /* Get the directory in which the real filename lives */
+ dirname = g_path_get_dirname (real_filename);
+ only_filename = g_path_get_basename(real_filename);
+
+ backup_filename = g_strdup_printf("%s%c"AUTOSAVE_BACKUP_FILENAME_STRING,
+ dirname, G_DIR_SEPARATOR, only_filename);
+
+ /* Delete the backup file */
+ if ( (g_file_test (backup_filename, G_FILE_TEST_EXISTS)) &&
+ (!g_file_test(backup_filename, G_FILE_TEST_IS_DIR)) )
+ {
+ if (unlink(backup_filename) != 0) {
+ s_log_message("s_page_delete: Unable to delete backup file %s.", backup_filename); }
+ }
+ g_free (dirname);
+ g_free (only_filename);
+ g_free (backup_filename);
+ }
+ g_free(real_filename);
+
+ /* first delete objects of page */
+ s_delete_list_fromstart (toplevel, page->object_head);
+
+ toplevel->REMOVING_SEL = 1;
+ s_delete_list_fromstart (toplevel, page->complex_place_head);
+ s_delete_list_fromstart (toplevel, page->attrib_place_head);
+ o_selection_destroy_all (page->selection2_head);
+ toplevel->REMOVING_SEL = 0;
+
+#if DEBUG
+ printf("Freeing page: %s\n", page->page_filename);
+ s_tile_print(toplevel);
+#endif
+ s_tile_free_all (page);
+
+ s_stretch_destroy_all (page->stretch_head);
+
+ /* free current page undo structs */
+ s_undo_free_all (toplevel, page);
+
+ /* ouch, deal with parents going away and the children still around */
+ page->up = -2;
+ /* p_current->down = NULL; not needed */
+
+ g_free (page->page_filename);
+
+ /* now unlink page from its list */
+ if (page->next) {
+ page->next->prev = page->prev;
+ } else {
+ /* page if the tail of page list: update toplevel */
+ g_assert (toplevel->page_tail == page);
+ toplevel->page_tail = page->prev;
+ }
+ if (page->prev) {
+ page->prev->next = page->next;
+ }
+
+#if DEBUG
+ s_tile_print (toplevel);
+#endif
+
+ g_free (page);
+
+#if 0 /* don't do this for now hack */ /* this is a per window free */
+ o_attrib_free_current(w_current);
+ o_complex_free_filename(w_current);
+#endif
+
+ /* restore page_current */
+ if (tmp != NULL) {
+ s_page_goto (toplevel, tmp);
+ } else {
+ /* page was page_current */
+ toplevel->page_current = NULL;
+ /* page_current must be updated by calling function */
+ }
+
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief Initializes <B>toplevel</B>'s list of pages.
+ * \par Function Description
+ * This function creates a head page and set the toplevel fields relative
+ * to page management.
+ */
+void s_page_init_list (TOPLEVEL *toplevel)
+{
+ PAGE *head;
+
+ g_assert (toplevel->page_head == NULL);
+
+ head = (PAGE*)g_new (PAGE, 1);
+
+ head->pid = -1;
+ head->CHANGED = 0;
+ head->page_filename = g_strdup ("page_head");
+ head->prev = NULL;
+ head->next = NULL;
+ /* this is important so that page_next and page_prev ignore the
+ * page head node
+ */
+ head->page_control = -1;
+
+ /* add head as page head of toplevel */
+ toplevel->page_head = toplevel->page_tail = head;
+
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief Deletes the list of pages of <B>toplevel</B>.
+ * \par Function Description
+ * Deletes the list of pages of <B>toplevel</B>.
+ * This function should only be called when you are finishing up.
+ */
+void s_page_delete_list(TOPLEVEL *toplevel)
+{
+ PAGE *p_current, *p_prev;
+
+ p_current = toplevel->page_tail;
+
+ while (p_current != NULL && p_current->pid != -1) {
+ p_prev = p_current->prev;
+ s_page_delete (toplevel, p_current);
+ p_current = p_prev;
+ }
+
+ g_assert (p_current->pid == -1 &&
+ p_current->prev == NULL && p_current->next == NULL);
+
+ /* Now free the head */
+ g_free (p_current->page_filename);
+ g_free (p_current);
+
+ /* reset toplevel fields */
+ toplevel->page_head = NULL;
+ toplevel->page_tail = NULL;
+ toplevel->page_current = NULL;
+
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief Changes the current page in <B>toplevel</B> to be <B>p_new</B>.
+ * \par Function Description
+ * Changes the current page in <B>toplevel</B> to be <B>p_new</B>.
+ *
+ */
+void s_page_goto (TOPLEVEL *toplevel, PAGE *p_new)
+{
+ gchar *dirname;
+
+ toplevel->page_current = p_new;
+
+ dirname = g_dirname (p_new->page_filename);
+ chdir (dirname);
+ g_free (dirname);
+
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief Search for pages by filename.
+ * \par Function Description
+ * Searches in <B>toplevel</B>'s list of pages for a page with a filename
+ * equal to <B>filename</B>.
+ *
+ * \return PAGE pointer to a matching page, NULL otherwise.
+ */
+PAGE *s_page_search (TOPLEVEL *toplevel, const gchar *filename)
+{
+ PAGE *p_current;
+
+ for (p_current = toplevel->page_head;
+ p_current != NULL;
+ p_current = p_current->next) {
+ if (g_strcasecmp (p_current->page_filename, filename) == 0) {
+ return p_current;
+ }
+ }
+
+ return NULL;
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief Search for pages by page id.
+ * \par Function Description
+ * This function tries to find a page refered by its <B>page_id</B>.
+ *
+ * \return PAGE pointer to matching page, NULL otherwise.
+ */
+PAGE *s_page_search_pid(TOPLEVEL * toplevel, gint page_id)
+{
+ PAGE* p_current;
+
+ for (p_current = toplevel->page_head;
+ p_current != NULL;
+ p_current = p_current->next) {
+ if (p_current->pid == page_id)
+ return p_current;
+ }
+
+ return NULL;
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+gint s_page_search_row(TOPLEVEL *toplevel, PAGE *p_findme)
+{
+ PAGE *p_current;
+
+ for (p_current = toplevel->page_head;
+ p_current != NULL;
+ p_current = p_current->next) {
+ if (p_current->clist_row == p_findme->clist_row) {
+ return p_current->clist_row;
+ }
+ }
+
+ return 0; /* can't find page... well just select row 0 */
+}
+
+/*! \brief Print full TOPLEVEL structure.
+ * \par Function Description
+ * This function prints the internal structure of <B>toplevel</B>'s
+ * list of pages.
+ *
+ * \param [in] toplevel The TOPLEVEL object to print.
+ */
+void s_page_print_all (TOPLEVEL *toplevel)
+{
+ PAGE *p_current;
+
+ g_assert (toplevel->page_head != NULL &&
+ toplevel->page_head->pid == -1);
+
+ for (p_current = toplevel->page_head->next;
+ p_current != NULL;
+ p_current = p_current->next) {
+ printf ("FILENAME: %s\n", p_current->page_filename);
+ print_struct_forw (p_current->object_head);
+ }
+
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief Saves all the pages of a TOPLEVEL object.
+ * \par Function Description
+ * Saves all the pages in the <B>toplevel</B> parameter.
+ *
+ * \param [in] toplevel The TOPLEVEL to save pages from.
+ * \return The number of failed tries to save a page.
+ */
+gint s_page_save_all (TOPLEVEL *toplevel)
+{
+ PAGE *p_save, *p_current;
+ gint status = 0;
+
+ g_assert (toplevel->page_head != NULL &&
+ toplevel->page_head->pid == -1);
+
+ /* save current page */
+ p_save = toplevel->page_current;
+
+ for (p_current = toplevel->page_head->next;
+ p_current != NULL;
+ p_current = p_current->next) {
+ /* make p_current the current page of toplevel */
+ s_page_goto (toplevel, p_current);
+
+ if (f_save (toplevel, p_current->page_filename)) {
+ s_log_message ("Saved [%s]\n",
+ toplevel->page_current->page_filename);
+ /* reset the CHANGED flag of p_current */
+ p_current->CHANGED = 0;
+
+ } else {
+ s_log_message ("Could NOT save [%s]\n",
+ toplevel->page_current->page_filename);
+ /* increase the error counter */
+ status++;
+ }
+
+ }
+
+ /* restore current page */
+ s_page_goto (toplevel, p_save);
+
+ return status;
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief Check if CHANGED flag is set for any page in list.
+ * \par Function Description
+ * This function checks the CHANGED flag for all pages in the <B>head</B>
+ * object.
+ *
+ * \param [in] head PAGES list to check CHANGED flag in.
+ * \return 1 if any page has the CHANGED flag set, 0 otherwise.
+ */
+gboolean s_page_check_changed (PAGE *head)
+{
+ PAGE *p_current;
+
+ for (p_current = head;
+ p_current != NULL;
+ p_current = p_current->next) {
+ if (p_current->CHANGED) {
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+/*! \brief Reset the CHANGED flag of all pages.
+ * \par Function Description
+ * This function resets the CHANGED flag of each page following <B>head</B>.
+ *
+ * \param [in,out] head PAGE list to set CHANGED flags in.
+ */
+void s_page_clear_changed (PAGE *head)
+{
+ PAGE *p_current;
+
+ for (p_current = head;
+ p_current != NULL;
+ p_current = p_current->next) {
+ p_current->CHANGED = 0;
+ }
+
+}
+
+/*! \brief Autosave callback function.
+ * \par Function Description
+ * This function is a callback of the glib g_timeout functions.
+ * It is called every "interval" milliseconds and it sets a flag to save
+ * a backup copy of the opened pages.
+ *
+ * \param [in] toplevel The TOPLEVEL object.
+ * \return The length in milliseconds to set for next interval.
+ */
+gint s_page_autosave (TOPLEVEL *toplevel)
+{
+ PAGE *p_current;
+
+ if (toplevel == NULL) {
+ return 0;
+ }
+
+ /* Do nothing if the interval is 0 */
+ if (toplevel->auto_save_interval == 0) {
+ return toplevel->auto_save_interval;
+ }
+
+ /* In which situation can be page_head = NULL?
+ Should we just disable the autosave timeout returning 0 or
+ just wait for more pages to be added? */
+ if ( (toplevel->page_head == NULL) ||
+ (toplevel->page_head->next == NULL) ) {
+ return (toplevel->auto_save_interval);
+ }
+
+ for (p_current = toplevel->page_head->next;
+ p_current != NULL;
+ p_current = p_current->next) {
+
+ if (p_current->ops_since_last_backup != 0) {
+ /* Real autosave is done in o_undo_savestate */
+ p_current->do_autosave_backup = 1;
+ }
+
+ }
+
+ return toplevel->auto_save_interval;
+
+}
1.10 +113 -78 eda/geda/gaf/libgeda/src/s_papersizes.c
(In the diff below, changes in quantity of whitespace are not shown.)
Index: s_papersizes.c
===================================================================
RCS file: s_papersizes.c
diff -N s_papersizes.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ s_papersizes.c 5 Jul 2006 03:13:39 -0000 1.10
@@ -0,0 +1,184 @@
+/* gEDA - GPL Electronic Design Automation
+ * libgeda - gEDA's library
+ * Copyright (C) 1998-2000 Ales V. Hvezda
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+#include <config.h>
+
+#include <stdio.h>
+#include <sys/types.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <libguile.h>
+
+#include "defines.h"
+#include "struct.h"
+#include "globals.h"
+
+#include "../include/prototype.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+/*! \brief */
+struct st_papersizes_names {
+ char *papersize_name;
+ int width, height;
+};
+
+/*! \brief */
+static int papersizes_index=0;
+
+/*! \brief */
+#define MAX_PAGESIZES 60
+
+/*! \brief
+ * and eventually make this unlimited
+ * hack hack
+ */
+static struct st_papersizes_names papersizes[MAX_PAGESIZES];
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ * width and height in portrait mode
+ */
+int s_papersizes_add_entry(char *new_papersize, int width, int height)
+{
+ if (new_papersize == NULL) {
+ return(-1);
+ }
+
+ if (papersizes_index >= MAX_PAGESIZES) {
+ return(-1);
+ }
+
+ papersizes[papersizes_index].papersize_name = (char *) malloc(sizeof(char)*strlen(new_papersize)+1);
+
+ strcpy(papersizes[papersizes_index].papersize_name, new_papersize);
+
+ papersizes[papersizes_index].width = width;
+ papersizes[papersizes_index].height = height;
+
+ papersizes_index++;
+ return(papersizes_index);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_papersizes_print()
+{
+ int i;
+
+ for (i = 0; i < papersizes_index; i++) {
+ printf("%s\n", papersizes[i].papersize_name);
+ }
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ * true for uniqueness, zero for duplication
+ */
+int s_papersizes_uniq(char *name)
+{
+ int i;
+
+ for (i = 0; i < papersizes_index; i++) {
+ if (strcmp(papersizes[i].papersize_name, name) == 0) {
+ return(0);
+ }
+ }
+
+ return(1);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_papersizes_free()
+{
+ int i;
+
+ for (i = 0; i < papersizes_index; i++) {
+ if (papersizes[i].papersize_name)
+ free(papersizes[i].papersize_name);
+ }
+
+ papersizes_index=0;
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_papersizes_init()
+{
+ int i;
+ for (i = 0; i < MAX_PAGESIZES; i++) {
+ papersizes[i].papersize_name = NULL;
+ }
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+char *s_papersizes_get(int counter)
+{
+ if (counter < papersizes_index) {
+ return(papersizes[counter].papersize_name);
+ } else {
+ return(NULL);
+ }
+
+ return(NULL);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_papersizes_get_size(char *string, int *width, int *height)
+{
+ int i;
+
+ for (i = 0; i < papersizes_index; i++) {
+ if (strcmp(papersizes[i].papersize_name, string) == 0) {
+ *width = papersizes[i].width;
+ *height = papersizes[i].height;
+ return;
+ }
+ }
+
+ *width = 0;
+ *height = 0;
+}
1.16 +531 -447 eda/geda/gaf/libgeda/src/s_slib.c
(In the diff below, changes in quantity of whitespace are not shown.)
Index: s_slib.c
===================================================================
RCS file: s_slib.c
diff -N s_slib.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ s_slib.c 5 Jul 2006 03:13:39 -0000 1.16
@@ -0,0 +1,659 @@
+/* gEDA - GPL Electronic Design Automation
+ * libgeda - gEDA's library
+ * Copyright (C) 1998-2000 Ales V. Hvezda
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+/*! slib stands for source (project/schematic/hdl/model source) library */
+
+#include <config.h>
+
+#include <stdio.h>
+#include <sys/types.h>
+#include <ctype.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_DIRENT_H
+#include <dirent.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <libguile.h>
+
+#include "defines.h"
+#include "struct.h"
+#include "globals.h"
+
+#include "../include/prototype.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+/* need to test everything at boundary conditions (exceed cache size etc...) */
+
+/*! \brief */
+struct st_slib {
+ char *dir_name;
+};
+
+/*! \brief */
+static int slib_index=0;
+
+/*! \brief */
+#define MAX_SLIBS 128
+
+/*! \brief
+ * and eventually make this unlimited
+ * hack hack
+ */
+static struct st_slib slib[MAX_SLIBS];
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+int s_slib_add_entry(char *new_path)
+{
+ if (new_path == NULL) {
+ return(-1);
+ }
+
+ if (slib_index >= MAX_SLIBS) {
+ return(-1);
+ }
+
+ slib[slib_index].dir_name = (char *) malloc(sizeof(char)*strlen(new_path)+1);
+
+ strcpy(slib[slib_index].dir_name, new_path);
+
+ slib_index++;
+ return(slib_index);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ * \return 1 if directory is found, zero otherwise.
+ */
+int s_slib_search_for_dirname(char *dir_name)
+{
+ int i;
+
+ for (i = 0; i < slib_index; i++) {
+ if (strcmp(slib[i].dir_name, dir_name) == 0) {
+ return(1);
+ }
+ }
+
+ return(0);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ * \warning
+ * Caller must free returned pointer.
+ */
+char *s_slib_search_dirs(const char *basename)
+{
+ int i;
+ int len;
+ DIR *ptr=NULL;
+ struct dirent *dptr;
+ char *slib_path=NULL;
+
+ /* search slib paths backwards */
+ for (i = slib_index-1 ; i >= 0; i--) {
+ /* for (i = 0 ; i < slib_index; i++) {*/
+
+#if DEBUG
+ printf("searching: %d %s\n", i, slib[i].dir_name);
+#endif
+
+ ptr = opendir(slib[i].dir_name);
+
+ if (ptr == NULL) {
+ fprintf(stderr, "Oops got a null dir_name!\n");
+ exit(-1);
+ }
+
+ dptr = readdir(ptr);
+
+ while(dptr != NULL) {
+
+ /* Do a substring comp for a match */
+ if (strstr(dptr->d_name, basename) != NULL) {
+ len = strlen(slib[i].dir_name);
+ slib_path = (char *) malloc(sizeof(char)*len+1);
+ strcpy(slib_path, slib[i].dir_name);
+
+ if (ptr) {
+ closedir(ptr);
+ ptr = NULL;
+ }
+
+ return(slib_path);
+ }
+ dptr = readdir(ptr);
+ }
+
+ if (ptr) {
+ closedir(ptr);
+ ptr = NULL;
+ }
+
+ }
+
+ if (ptr) {
+ closedir(ptr);
+ ptr = NULL;
+ }
+
+ return(NULL);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ * \warning
+ * Caller must free returned pointer.
+ */
+char *s_slib_search_lowlevel(const char *basename)
+{
+ char *slib_path=NULL;
+ char *full_path=NULL;
+ int len;
+
+ slib_path = s_slib_search_dirs(basename);
+
+ if (slib_path) {
+ /* return type */
+
+ s_log_message("Found [%s]\n", basename);
+ /* s_log_message("Found [%s] in [%s]\n", basename, slib_path);*/
+
+ len = strlen(basename)+strlen(slib_path);
+
+ /* The 2 is for NULL char and the slash inbetween the two */
+ /* strings */
+ full_path = (char *) malloc(sizeof(char)*(len+2));
+
+ sprintf(full_path, "%s%c%s", slib_path, G_DIR_SEPARATOR, basename);
+
+ free(slib_path);
+
+ return(full_path);
+ } else {
+
+ s_log_message("Could not find [%s] in any SourceLibrary\n", basename);
+
+#if DEBUG
+ fprintf(stderr, "Could not find [%s] in any SourceLibrary\n", basename);
+#endif
+ return(NULL);
+ }
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief Get the base file name from a raw file name string.
+ * \par Function Description
+ * This function takes a raw file name and returns a processed file name.
+ * It takes the raw file name and copies everything up to the first period
+ * and removes any _# (where # is any number of digits.
+ *
+ * \param [in] rawname Character string with the raw file name to parse.
+ * \return The base file name in a character string.
+ *
+ * \warning
+ * Caller must free returned pointer.
+ */
+char *s_slib_getbasename(const char *rawname)
+{
+ char *return_filename;
+ char *copy;
+ int i;
+ int done=0;
+ int lastchar;
+ int valid=0;
+ int len;
+ int seen_underscore=0;
+
+ if (!rawname)
+ return(NULL);
+
+ len = strlen(rawname)+1;
+
+ return_filename = (char *) malloc(sizeof(char)*len);
+
+ i = 0;
+ /* first get everything up to the leading dot */
+ while(rawname[i] != '\0' && rawname[i] != '.') {
+ return_filename[i] = rawname[i];
+ i++;
+ }
+
+
+ return_filename[i] = '\0';
+
+
+ /* keep filename for safe keeping */
+ copy = return_filename;
+
+ /* skip null terminator */
+ i--;
+
+ lastchar=i;
+
+ /* this is a quick and dirty state machine to */
+ /* go back and strip off any _#'s */
+ /* if there is a better way let me know */
+ while (i >= 0 && !done) {
+
+ /* first we need to check to see if we have seen the first '_' */
+ /* if we have then we already removing chars, continue with that */
+ if ( seen_underscore ) {
+ if (return_filename[i] == '_') {
+ done = 1;
+ }
+
+ return_filename[i] = '\0';
+ } else {
+ /* we are still searching for the first underscore */
+
+ /* first make sure char is a number */
+ if (isdigit((int) return_filename[i])) {
+ valid=1;
+ } else if (return_filename[i] == '_' && valid) {
+ /* yes it is okay to delete the chars */
+ seen_underscore=1;
+ /* incremented, since it is then */
+ /* decremented */
+ i = lastchar+1;
+ } else {
+ valid = 0;
+ done = 1;
+ }
+ }
+
+ i--;
+ }
+
+ /* be sure to free this somewhere */
+ return(return_filename);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief Search SLIB for a particular file name.
+ * \par Function Description
+ * This function will search the SLIB for a particular file name starting
+ * at a location specified by the <B>flag</B> parameter.
+ *
+ * \param [in] filename Character string with file name to search for.
+ * \param [in] flag Specifies search start location. (See below...)
+ *
+ * The <B>flag</B> parameter can be one of the following values:
+ * <DL>
+ * <DT>SLIB_SEARCH_START</DT><DD>Starts a new search for a source file.
+ * <DT>SLIB_SEARCH_NEXT</DT><DD>Returns the next instance of the file if
+ * one exists.
+ * <DT>SLIB_SEARCH_DONE</DT><DD>Finish searching.
+ * </DL>
+ *
+ * Filename is the raw symbol/whatever file name. This function does all the
+ * required stripping (up to the first period).
+ *
+ * \warning
+ * Caller must free returned pointer.
+ */
+char *s_slib_search(const char *filename, int flag)
+{
+ char *processed_name=NULL;
+ char *new_filename=NULL;
+ char *string=NULL;
+ char *number_suffix;
+ int len;
+ int len2;
+ static int count;
+
+ switch(flag) {
+ case(SLIB_SEARCH_START):
+ count = 0;
+ string=NULL;
+ break;
+
+ case(SLIB_SEARCH_NEXT):
+ count++;
+
+ /* be sure to free processed_name */
+ processed_name = s_slib_getbasename(filename);
+
+#if DEBUG
+ printf("proced: %s\n", processed_name);
+#endif
+
+ len = strlen(processed_name);
+
+ /* for now only look for .sch's */
+ /* this needs to be *MUCH* more flexible */
+ /* number_suffix is large enough ? */
+ number_suffix = g_strdup_printf("_%d.sch", count);
+ len2 = strlen(number_suffix);
+ new_filename = (char *)
+ malloc (sizeof(char)*(len+len2+1));
+
+ sprintf(new_filename, "%s%s", processed_name, number_suffix);
+ string = s_slib_search_lowlevel(new_filename);
+
+ free(new_filename);
+ free(number_suffix);
+ break;
+
+ case(SLIB_SEARCH_DONE):
+ count = 0;
+ string=NULL;
+ break;
+ }
+
+ if (processed_name)
+ free(processed_name);
+
+ /* don't forget to free this string */
+ return(string);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief Search SLIB for a particular file name.
+ * \par Function Description
+ * This function will search the SLIB for a particular file name starting
+ * at a location specified by the <B>flag</B> parameter.
+ *
+ * \param [in] filename Character string with file name to search for.
+ *
+ * Filename is the raw symbol/whatever file name. This function only looks
+ * for the file name as is and does no other changes to it.
+ *
+ * \warning
+ * Caller must free returned pointer.
+ */
+char *s_slib_search_single(const char *filename)
+{
+ char *string=NULL;
+
+ string = s_slib_search_lowlevel(filename);
+
+ /* don't forget to free this string */
+ return(string);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_slib_free()
+{
+ int i;
+
+ for (i = 0; i < slib_index; i++) {
+ if (slib[i].dir_name)
+ free(slib[i].dir_name);
+ }
+
+ slib_index=0;
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_slib_init()
+{
+ int i;
+ for (i = 0; i < MAX_SLIBS; i++) {
+ slib[i].dir_name = NULL;
+ }
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ * \warning
+ * Caller must free returned pointer.
+ */
+/* returns slibs */
+char *s_slib_getdir(int index)
+{
+ if (slib[index].dir_name != NULL)
+ return(slib[index].dir_name);
+ else
+ return(NULL);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ * \param [in] directory Character string with directory to get files from.
+ * \param [in] flag Search control flag. (See below...)
+ * \return A file name if one is found, NULL otherwise.
+ *
+ * \warning
+ * Caller must free returned pointer.
+ *
+ * The flag parameter can be one of the following values:
+ * <DL>
+ * <DT>OPEN_DIR</DT><DD>Opens the directory and returns NULL.
+ * <DT>READ_DIR</DT><DD>Returns the next non "." entry.
+ * <DT>CLOSE_DIR</DT><DD>Closes the directory.
+ * </DL>
+ * \bug This is TOTTALLY BROKEN!
+ * statics are not allowed anymore
+ * \warning
+ * this function is not reentrant
+ */
+char *s_slib_getfiles(char *directory, int flag)
+{
+ static DIR *ptr;
+ static struct dirent *dptr;
+ static char *whole_dir[256]; /* make this dynamic hack */
+ static int count=0;
+ static int current=0;
+
+ int j;
+ int len;
+
+ switch(flag) {
+
+ case(CLOSE_DIR):
+ if (ptr) {
+ closedir(ptr);
+ }
+
+ ptr = NULL;
+
+ for (j = 0 ; j < count ;j++) {
+ if (whole_dir[j])
+ free(whole_dir[j]);
+ }
+ count = current = 0 ;
+
+ return(NULL);
+ break;
+
+ /* open the directory and return first element (after if) */
+ case(OPEN_DIR):
+
+ if (ptr) {
+ closedir(ptr);
+ }
+
+ ptr = NULL;
+
+ for (j = 0 ; j < count ;j++) {
+ if (whole_dir[j])
+ free(whole_dir[j]);
+ }
+ count = current = 0 ;
+
+ ptr = opendir(directory); /* hack check for existance */
+
+ if (ptr == NULL)
+ return(NULL);
+
+
+ /* now read the entire directory */
+ dptr = readdir(ptr);
+
+ while (dptr != NULL) {
+
+ /* skip .'s */
+ while (dptr != NULL) {
+ if (dptr->d_name[0] == '.') {
+ dptr = readdir(ptr);
+ } else {
+ break;
+ }
+ }
+
+ if (dptr == NULL) {
+ break;
+ }
+
+ if (dptr->d_name != NULL) {
+ len = strlen(dptr->d_name);
+
+ /* hack */
+ if (count < 256) {
+
+ whole_dir[count] = (char *)
+ malloc(sizeof(char)*len+1);
+ strcpy(whole_dir[count],
+ dptr->d_name);
+ count++;
+ } else {
+ fprintf(stderr,
+ "uggg. too many files in s_slib_getfiles!\n");
+ exit(-1);
+ }
+ }
+
+ dptr = readdir(ptr);
+ }
+ return(NULL);
+
+ break;
+
+ case(READ_DIR):
+
+
+ if (whole_dir[current] && current < count) {
+ return(whole_dir[current++]);
+ } else {
+ return(NULL);
+ }
+
+ break;
+
+ default:
+ return(NULL);
+ }
+
+#if DEBUG
+ for (j = 0;j < count; j++) {
+ printf("string: %s\n", whole_dir[j]);
+ }
+#endif
+
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_slib_print(void)
+{
+ int i;
+
+ for (i = 0; i < slib_index; i++) {
+ printf("%s\n", slib[i].dir_name);
+ }
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+int s_slib_uniq(char *path)
+{
+ if (s_slib_search_for_dirname(path)) {
+
+#if DEBUG
+ printf("found\n");
+#endif
+ return(0);
+ } else {
+
+#if DEBUG
+ printf("NOT found\n");
+#endif
+
+ return(1);
+ }
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_slib_print_dirs(void)
+{
+ int i;
+ char *string;
+ char *file;
+
+ i = 0;
+ string = s_slib_getdir(i);
+ while(string != NULL) {
+
+ s_slib_getfiles(string, OPEN_DIR);
+ printf("Opened %s\n", string);
+
+ file = (char *) s_slib_getfiles(string, READ_DIR);
+
+ while(file != NULL) {
+ printf("file: %s\n", file);
+ file = (char *) s_slib_getfiles(string, READ_DIR);
+ }
+
+ printf("Closed %s\n", string);
+ s_slib_getfiles(string, CLOSE_DIR);
+ i++;
+ string = s_slib_getdir(i);
+ }
+}
1.4 +216 -179 eda/geda/gaf/libgeda/src/s_stretch.c
(In the diff below, changes in quantity of whitespace are not shown.)
Index: s_stretch.c
===================================================================
RCS file: s_stretch.c
diff -N s_stretch.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ s_stretch.c 5 Jul 2006 03:13:39 -0000 1.4
@@ -0,0 +1,294 @@
+/* gEDA - GPL Electronic Design Automation
+ * libgeda - gEDA's library
+ * Copyright (C) 1998-2000 Ales V. Hvezda
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+#include <config.h>
+
+#include <stdio.h>
+#include <ctype.h>
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if HAVE_ASSERT_H
+#include <assert.h>
+#endif
+#ifndef HAVE_VSNPRINTF
+#include <stdarg.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <libguile.h>
+
+#include "defines.h"
+#include "struct.h"
+#include "defines.h"
+#include "globals.h"
+#include "o_types.h"
+#include "colors.h"
+
+#include "../include/prototype.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+STRETCH *s_stretch_return_tail(STRETCH *head)
+{
+ STRETCH *s_current=NULL;
+ STRETCH *ret_struct=NULL;
+
+ s_current = head;
+ while ( s_current != NULL ) { /* goto end of list */
+ ret_struct = s_current;
+ s_current = s_current->next;
+ }
+
+ return(ret_struct);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+STRETCH *s_stretch_return_head(STRETCH *tail)
+{
+ STRETCH *s_current=NULL;
+ STRETCH *ret_struct=NULL;
+
+ s_current = tail;
+ while ( s_current != NULL ) { /* goto end of list */
+ ret_struct = s_current;
+ s_current = s_current->prev;
+ }
+
+ return(ret_struct);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+STRETCH *s_stretch_new_head(void)
+{
+ STRETCH *s_new;
+
+ s_new = (STRETCH *) malloc(sizeof(STRETCH));
+
+ s_new->object = NULL;
+ s_new->connection = NULL;
+ s_new->whichone = -1;
+
+ s_new->prev = NULL;
+ s_new->next = NULL;
+
+ return(s_new);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_stretch_destroy_head(STRETCH *s_head)
+{
+ free(s_head);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+/*! \todo also does the needed work to make the object visually selected */
+STRETCH *s_stretch_add(STRETCH *head, OBJECT *object,
+ CONN *connection, int whichone)
+{
+ STRETCH *tail;
+ STRETCH *s_new;
+ STRETCH *s_current;
+
+ s_current = head;
+ while (s_current != NULL) {
+ if (s_current->object) {
+ /*printf("%d %d\n", s_current->object->sid, object->sid);*/
+ if (s_current->object->sid == object->sid) {
+ /* printf("already inside\n");*/
+ return(s_stretch_return_tail(head));
+ }
+ }
+
+ s_current = s_current->next;
+ }
+ /*printf("Adding: %s\n", object->name);*/
+
+ s_new = (STRETCH *) malloc(sizeof(STRETCH));
+ s_new->object = object;
+ s_new->connection = connection;
+ s_new->whichone = whichone;
+
+ if (head == NULL) {
+ s_new->prev = NULL; /* setup previous link */
+ s_new->next = NULL;
+ return(s_new);
+ } else {
+ tail = s_stretch_return_tail(head);
+ s_new->prev = tail; /* setup previous link */
+ s_new->next = NULL;
+ tail->next = s_new;
+ return(tail->next);
+ }
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+/*! \note
+ * it's okay to call this with an o_selected which is not necessarily
+ * selected
+ */
+void s_stretch_remove(STRETCH *head, OBJECT *object)
+{
+ STRETCH *s_current;
+
+ if (object == NULL) {
+ fprintf(stderr, "Got NULL for s_stretch in s_stretch_remove\n");
+ return;
+ }
+
+ s_current = head;
+
+ while (s_current != NULL) {
+ if (s_current->object == object) {
+ if (s_current->next)
+ s_current->next->prev = s_current->prev;
+ else
+ s_current->next = NULL;
+
+ if (s_current->prev)
+ s_current->prev->next = s_current->next;
+ else
+ s_current->prev = NULL;
+
+ s_current->object = NULL;
+ s_current->connection = NULL;
+ s_current->whichone = -1;
+
+ free(s_current);
+ return;
+ }
+ s_current = s_current->next;
+ }
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+/*! \note removes all but the head node */
+void s_stretch_remove_most(TOPLEVEL *w_current, STRETCH *head)
+{
+ STRETCH *s_current;
+ STRETCH *s_prev;
+
+ s_current = s_stretch_return_tail(head);
+
+ while (s_current != NULL) {
+ if (s_current->object != NULL) {
+ s_prev = s_current->prev;
+
+ s_current->object = NULL;
+ s_current->connection = NULL;
+ s_current->whichone = -1;
+
+ free(s_current);
+ s_current = s_prev;
+ } else {
+ break;
+ }
+ }
+
+ /* clear out any dangling pointers */
+ head->next=NULL;
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_stretch_print_all( STRETCH *head )
+{
+ STRETCH *s_current;
+
+ s_current = head;
+
+ printf("START printing stretch ********************\n");
+ while(s_current != NULL) {
+ if (s_current->object) {
+ printf("Object: %s\n", s_current->object->name);
+ } else {
+ printf("Object is NULL\n");
+ }
+
+ if (s_current->object) {
+ printf("Connection type: %d\n", s_current->connection->type);
+ } else {
+ printf("Connection is NULL\n");
+ }
+
+ printf("which one: %d\n", s_current->whichone);
+
+ s_current = s_current->next;
+ }
+ printf("DONE printing stretch ********************\n");
+ printf("\n");
+
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_stretch_destroy_all(STRETCH *head)
+{
+ STRETCH *s_current;
+ STRETCH *s_prev;
+
+ s_current = s_stretch_return_tail(head);
+
+ while (s_current != NULL) {
+ s_prev = s_current->prev;
+
+ s_current->object = NULL;
+ s_current->connection = NULL;
+ s_current->whichone = -1;
+
+ free(s_current);
+ s_current = s_prev;
+ }
+}
1.4 +94 -50 eda/geda/gaf/libgeda/src/s_tile.c
(In the diff below, changes in quantity of whitespace are not shown.)
Index: s_tile.c
===================================================================
RCS file: s_tile.c
diff -N s_tile.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ s_tile.c 5 Jul 2006 03:13:39 -0000 1.4
@@ -0,0 +1,497 @@
+/* gEDA - GPL Electronic Design Automation
+ * libgeda - gEDA's library
+ * Copyright (C) 1998-2000 Ales V. Hvezda
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+#include <config.h>
+
+#include <stdio.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_ASSERT_H
+#include <assert.h>
+#endif
+#include <ctype.h>
+#include <math.h>
+#ifndef HAVE_VSNPRINTF
+#include <stdarg.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <libguile.h>
+
+#include "defines.h"
+#include "struct.h"
+#include "defines.h"
+#include "globals.h"
+#include "o_types.h"
+#include "colors.h"
+
+#include "../include/prototype.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_tile_init(TOPLEVEL * w_current, PAGE * p_current)
+{
+ int i, j;
+ TILE *t_current;
+ int x_size = w_current->init_right / MAX_TILES_X;
+ int y_size = w_current->init_bottom / MAX_TILES_Y;
+ int x_sum = 0;
+ int y_sum = 0;
+
+#if DEBUG
+ printf("X, Y: %d %d\n", x_size, y_size);
+#endif
+
+ for (j = 0; j < MAX_TILES_Y; j++) {
+ for (i = 0; i < MAX_TILES_X; i++) {
+ t_current = &p_current->world_tiles[i][j];
+
+ t_current->objects = NULL;
+
+ t_current->left = x_sum;
+ t_current->right = x_sum + x_size;
+
+ t_current->top = y_sum;
+ t_current->bottom = y_sum + y_size;
+
+ x_sum = x_sum + x_size;
+ }
+ x_sum = 0;
+ y_sum = y_sum + y_size;
+ }
+
+#if DEBUG
+ for (j = 0; j < MAX_TILES_Y; j++) {
+ for (i = 0; i < MAX_TILES_X; i++) {
+ t_current = &p_current->world_tiles[i][j];
+ printf("\n%d %d\n", i, j);
+ printf("----------------\n");
+ printf("left %d top %d\n", t_current->left, t_current->top);
+ printf("right %d bottom %d\n", t_current->right,
+ t_current->bottom);
+ }
+ }
+#endif
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+TILE_LOC *s_tile_new_loc(int i, int j)
+{
+ TILE_LOC *tile_loc;
+
+ tile_loc = (TILE_LOC *) malloc(sizeof(TILE_LOC));
+
+ tile_loc->i = i;
+ tile_loc->j = j;
+
+ return (tile_loc);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_tile_add_object(TOPLEVEL * w_current, OBJECT * object, int world_x1,
+ int world_y1, int world_x2, int world_y2)
+{
+ TILE *t_current;
+ PAGE *p_current;
+ GList *found;
+ TILE_LOC *tile_loc;
+ int i, j;
+ int v, w;
+ double x1, y1, x2, y2;
+ double bottom;
+ double m, b;
+ double x_size, y_size;
+ double x, y;
+ int start, end;
+
+#if DEBUG
+ printf("name: %s\n", object->name);
+#endif
+
+ if (w_current->ADDING_SEL) {
+#if DEBUG
+ printf("s_tile_add_object, adding sel TRUE\n");
+#endif
+ return;
+ }
+
+ x_size = (double) w_current->init_right / (double) MAX_TILES_X;
+ y_size = (double) w_current->init_bottom / (double) MAX_TILES_Y;
+
+ x1 = (int) (world_x1 / x_size);
+ x2 = (int) (world_x2 / x_size);
+ y1 = (int) (world_y1 / y_size);
+ y2 = (int) (world_y2 / y_size);
+
+ bottom = x2 - x1;
+ p_current = w_current->page_current;
+
+ if (bottom != 0.0) {
+ m = (double) (y2 - y1) / bottom;
+ b = y1 - m * x1;
+
+ start = min((int) x1, (int) x2);
+ end = max((int) x1, (int) x2);
+ for (i = start; i <= end; i++) {
+ x = i;
+ y = m * x + b;
+ if (floor(y) != ceil(y)) {
+
+ v = (int) x;
+ w = (int) floor(y);
+ if (v < 0 || w < 0 || v > MAX_TILES_X-1 || w > MAX_TILES_Y-1) {
+ return;
+ }
+ /* assert(v < MAX_TILES_X && w < MAX_TILES_Y && v >= 0 && w >= 0); */
+ t_current = &p_current->world_tiles[v][w];
+ found = g_list_find(t_current->objects, object);
+
+ if (!found) {
+ /*printf("%d %d\n", v, w);*/
+ t_current->objects = g_list_append(t_current->objects,
+ object);
+
+ tile_loc = s_tile_new_loc(v, w);
+ object->tile_locs = g_list_append(object->tile_locs,
+ tile_loc);
+ }
+
+ v = (int) x;
+ w = (int) ceil(y);
+ if (v < 0 || w < 0 || v > MAX_TILES_X-1 || w > MAX_TILES_Y-1) {
+ return;
+ }
+ /*assert(v < MAX_TILES_X && w < MAX_TILES_Y && v >= 0 && w >= 0);*/
+ t_current = &p_current->world_tiles[v][w];
+ found = g_list_find(t_current->objects, object);
+
+ if (!found) {
+ /*printf("%d %d\n", v, w);*/
+ t_current->objects = g_list_append(t_current->objects,
+ object);
+ tile_loc = s_tile_new_loc(v, w);
+ object->tile_locs = g_list_append(object->tile_locs,
+ tile_loc);
+ }
+
+ } else {
+ v = (int) x;
+ w = (int) floor(y);
+ if (v < 0 || w < 0 || v > MAX_TILES_X-1 || w > MAX_TILES_Y-1) {
+ return;
+ }
+ /*assert(v < MAX_TILES_X && w < MAX_TILES_Y && v >= 0 && w >= 0);*/
+ t_current = &p_current->world_tiles[v][w];
+ found = g_list_find(t_current->objects, object);
+
+ if (!found) {
+ /*printf("%d %d\n", v, w);*/
+ t_current->objects = g_list_append(t_current->objects,
+ object);
+ tile_loc = s_tile_new_loc(v, w);
+ object->tile_locs = g_list_append(object->tile_locs,
+ tile_loc);
+ }
+ }
+ }
+
+ if (m != 0.0) {
+ start = min((int) y1, (int) y2);
+ end = max((int) y1, (int) y2);
+ for (j = start; j <= end; j++) {
+ y = j;
+ x = (y - b) / m;
+ if (floor(x) != ceil(x)) {
+ w = (int) y;
+ v = (int) floor(x);
+ if (v < 0 || w < 0 || v > MAX_TILES_X-1 || w > MAX_TILES_Y-1) {
+ return;
+ }
+ /*assert(v < MAX_TILES_X && w < MAX_TILES_Y &&
+ v >= 0 && w >= 0);*/
+ t_current = &p_current->world_tiles[v][w];
+ found = g_list_find(t_current->objects, object);
+
+ if (!found) {
+ /*printf("%d %d\n", v, w);*/
+ t_current->objects =
+ g_list_append(t_current->objects, object);
+ tile_loc = s_tile_new_loc(v, w);
+ object->tile_locs =
+ g_list_append(object->tile_locs, tile_loc);
+ }
+
+ w = (int) y;
+ v = (int) ceil(x);
+ if (v < 0 || w < 0 || v > MAX_TILES_X-1 || w > MAX_TILES_Y-1) {
+ return;
+ }
+ /* assert(v < MAX_TILES_X && w < MAX_TILES_Y &&
+ v >= 0 && w >= 0);*/
+ t_current = &p_current->world_tiles[v][w];
+ found = g_list_find(t_current->objects, object);
+
+ if (!found) {
+ /*printf("%d %d\n", v, w);*/
+ t_current->objects =
+ g_list_append(t_current->objects, object);
+ tile_loc = s_tile_new_loc(v, w);
+ object->tile_locs =
+ g_list_append(object->tile_locs, tile_loc);
+ }
+
+ } else {
+ w = (int) y;
+ v = (int) floor(x);
+ if (v < 0 || w < 0 || v > MAX_TILES_X-1 || w > MAX_TILES_Y-1) {
+ return;
+ }
+ /*assert(v < MAX_TILES_X && w < MAX_TILES_Y &&
+ v >= 0 && w >= 0);*/
+ t_current = &p_current->world_tiles[v][w];
+ found = g_list_find(t_current->objects, object);
+
+ if (!found) {
+ /*printf("%d %d\n", v, w);*/
+ t_current->objects =
+ g_list_append(t_current->objects, object);
+ tile_loc = s_tile_new_loc(v, w);
+ object->tile_locs =
+ g_list_append(object->tile_locs, tile_loc);
+ }
+ }
+ }
+ }
+ } else {
+ start = min((int) y1, (int) y2);
+ end = max((int) y1, (int) y2);
+ for (j = start; j <= end; j++) {
+
+ y = j;
+ x = x1;
+ v = (int) x;
+ w = (int) y;
+ if (v < 0 || w < 0 || v > MAX_TILES_X-1 || w > MAX_TILES_Y-1) {
+ return;
+ }
+ /*assert(v < MAX_TILES_X && w < MAX_TILES_Y &&
+ v >= 0 && w >= 0);*/
+ t_current = &p_current->world_tiles[v][w];
+ found = g_list_find(t_current->objects, object);
+
+ if (!found) {
+ /*printf("%d %d\n", v, w);*/
+ t_current->objects = g_list_append(t_current->objects,
+ object);
+ tile_loc = s_tile_new_loc(v, w);
+ object->tile_locs = g_list_append(object->tile_locs,
+ tile_loc);
+ }
+
+ }
+ }
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_tile_remove_object_all_crude(TOPLEVEL * w_current, OBJECT * object)
+{
+ TILE *t_current;
+
+ int i, j;
+
+ for (j = 0; j < MAX_TILES_Y; j++) {
+ for (i = 0; i < MAX_TILES_X; i++) {
+#if 0 /* this checks for existance */
+ t_current = &w_current->page_current->world_tiles[i][j];
+ found = g_list_find(t_current->objects, object);
+
+ if (found) {
+ printf("found object %s in %d, %d\n", object->name, i, j);
+ t_current->objects = g_list_remove(t_current->objects,
+ object);
+ }
+#endif
+
+ /* this just does the remove if the object is found */
+#if 1
+ t_current = &w_current->page_current->world_tiles[i][j];
+ t_current->objects = g_list_remove(t_current->objects, object);
+#endif
+ }
+ }
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ * \bug
+ * this is still wrong, p_current needs to be the page the object is on
+ * doesn't work if the current page isn't where the object lives
+ */
+void s_tile_remove_object_all(TOPLEVEL * w_current, PAGE *p_current,
+ OBJECT * object)
+{
+ TILE *t_current;
+ TILE_LOC *tl_current;
+ GList *tloc_list;
+ GList *found;
+ int i, j;
+
+ tloc_list = object->tile_locs;
+ while (tloc_list != NULL) {
+
+ tl_current = (TILE_LOC *) tloc_list->data;
+
+ i = tl_current->i;
+ j = tl_current->j;
+
+ free(tl_current);
+
+ t_current = &p_current->world_tiles[i][j];
+ t_current->objects = g_list_remove(t_current->objects, object);
+
+#if 1
+ found = g_list_find(t_current->objects, object);
+ if (found) {
+ printf("found an object left over %s in %d, %d\nPlease e-mail ahvezda@xxxxxxxxxxxxx with this error message and .sch\n", object->name, i, j);
+ }
+#endif
+
+ tloc_list = tloc_list->next;
+ }
+
+ g_list_free(tloc_list);
+ object->tile_locs = NULL;
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_tile_update_object(TOPLEVEL * w_current, OBJECT * object)
+{
+ s_tile_remove_object_all(w_current, w_current->page_current, object);
+ s_tile_add_object(w_current, object,
+ object->line->x[0], object->line->y[0],
+ object->line->x[1], object->line->y[1]);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_tile_print(TOPLEVEL * w_current)
+{
+ TILE *t_current;
+ GList *temp;
+ GList *temp2;
+ OBJECT *o_current;
+ TILE_LOC *tloc;
+ int i, j;
+
+ for (j = 0; j < MAX_TILES_Y; j++) {
+ for (i = 0; i < MAX_TILES_X; i++) {
+ printf("\nTile %d %d\n", i, j);
+
+ t_current = &w_current->page_current->world_tiles[i][j];
+
+ temp = t_current->objects;
+ while (temp) {
+ o_current = (OBJECT *) temp->data;
+
+ printf("%s\n", o_current->name);
+ temp2 = o_current->tile_locs;
+ while (temp2 != NULL) {
+ tloc = (TILE_LOC *) temp2->data;
+ printf(" %d %d\n", tloc->i, tloc->j);
+ temp2 = temp2->next;
+ }
+
+ temp = temp->next;
+ }
+
+ printf("------------------\n");
+ }
+ }
+
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_tile_free_all(PAGE * p_current)
+{
+ int i, j;
+ TILE *t_current;
+
+ for (j = 0; j < MAX_TILES_Y; j++) {
+ for (i = 0; i < MAX_TILES_X; i++) {
+ t_current = &p_current->world_tiles[i][j];
+ if (g_list_length(t_current->objects) != 0) {
+ fprintf(stderr,
+ "OOPS! t_current->objects had something in it when it was freed!\n");
+ fprintf(stderr, "Length: %d\n", g_list_length(t_current->objects));
+
+
+#if DEBUG
+ printf("%s %d %d\n", p_current->page_filename, i, j);
+ objects = t_current->objects;
+ while(objects != NULL) {
+ real_object = (OBJECT *) objects->data;
+ printf("yes %s\n", real_object->name);
+ objects = objects->next;
+ }
+
+ if (t_current->objects == NULL) {
+ printf("yes null\n");
+ }
+#endif
+
+ }
+ g_list_free(t_current->objects);
+ }
+ }
+}
+
+
+
1.1 eda/geda/gaf/libgeda/src/s_toplevel.c
Index: s_toplevel.c
===================================================================
/* gEDA - GPL Electronic Design Automation
* libgeda - gEDA's library
* Copyright (C) 1998, 1999, 2000 Kazu Hirata / Ales Hvezda
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
*/
#include <config.h>
#include <stdio.h>
#ifdef HAVE_STRING_H
#include <string.h>
#endif
#ifdef HAVE_STRARG_H
#include <stdarg.h>
#endif
#ifdef HAVE_STDLIB_H
#include <stdlib.h>
#endif
#include <gtk/gtk.h>
#include <libguile.h>
#include "defines.h"
#include "struct.h"
#include "globals.h"
#include "funcs.h"
#include "../include/prototype.h"
#ifdef HAVE_LIBDMALLOC
#include <dmalloc.h>
#endif
/* global_wid always increments, it needs to be unique per run */
static int global_wid = 0;
/* head pointer to toplevel structure, this points to all the toplevels that
currently exist */
static TOPLEVEL *toplevel_head = NULL;
/*! \todo Finish function documentation!!!
* \brief
* \par Function Description
*
*/
void s_toplevel_init (void)
{
toplevel_head = (TOPLEVEL*)g_new (TOPLEVEL, 1);
toplevel_head->wid = -1;
toplevel_head->next = NULL;
}
/*! \todo Finish function documentation!!!
* \brief
* \par Function Description
*
*/
TOPLEVEL *s_toplevel_new (void)
{
TOPLEVEL *toplevel, *tmp;
toplevel = (TOPLEVEL*)g_new (TOPLEVEL, 1);
toplevel->wid = global_wid++;
toplevel->num_untitled = 0;
toplevel->start_x = -1;
toplevel->start_y = -1;
toplevel->save_x = -1;
toplevel->save_y = -1;
toplevel->last_x = -1;
toplevel->last_y = -1;
toplevel->loc_x = -1;
toplevel->loc_y = -1;
toplevel->distance = -1;
toplevel->current_attribute = NULL;
toplevel->current_visible = -1; /* not sure on these */
toplevel->current_show = -1;
toplevel->internal_basename = NULL;
toplevel->internal_clib = NULL;
toplevel->RC_list = NULL;
toplevel->series_name = NULL;
toplevel->untitled_name = NULL;
toplevel->font_directory = NULL;
toplevel->scheme_directory = NULL;
toplevel->bitmap_directory = NULL;
toplevel->event_state = -1;
toplevel->inside_action = 0;
toplevel->init_left = 0;
toplevel->init_top = 0;
/* init_right and _bottom are set before this function is called */
toplevel->win_width = 0;
toplevel->win_height = 0;
toplevel->width = 1;
toplevel->height = 1;
toplevel->image_width = 0;
toplevel->image_height = 0;
toplevel->snap = 1;
toplevel->grid = 1;
toplevel->min_zoom = 0;
toplevel->max_zoom = 8;
toplevel->starting_width = 0;
toplevel->text_alignment = 0;
toplevel->line_type = 0;
toplevel->fill_type = 0;
toplevel->override_color = -1;
toplevel->inside_redraw = 0;
toplevel->window_aspectratio = 0;
toplevel->display_height = 0;
toplevel->display_width = 0;
toplevel->DONT_DRAW_CONN = 0;
toplevel->DONT_RESIZE = 0;
toplevel->DONT_EXPOSE = 0;
toplevel->DONT_REDRAW = 0;
toplevel->DONT_RECALC = 0;
toplevel->FORCE_CONN_UPDATE = 0;
toplevel->ADDING_SEL = 0;
toplevel->REMOVING_SEL = 0;
toplevel->drawbounding_action_mode = FREE;
toplevel->last_drawb_mode = -1;
toplevel->CONTROLKEY = 0;
toplevel->SHIFTKEY = 0;
toplevel->ALTKEY = 0;
toplevel->doing_pan = 0;
/* Put head node on page list... */
toplevel->page_head = NULL;
s_page_init_list (toplevel);
toplevel->page_current = NULL;
toplevel->buffer_number = 0;
toplevel->show_hidden_text = 0;
toplevel->complex_rotate = 0;
toplevel->last_callback = NULL;
toplevel->cwd = NULL;
toplevel->major_changed_refdes = NULL;
toplevel->main_window = NULL;
toplevel->drawing_area = NULL;
toplevel->menubar = NULL;
toplevel->popup_menu = NULL;
toplevel->h_scrollbar = NULL;
toplevel->v_scrollbar = NULL;
toplevel->h_adjustment = NULL;
toplevel->v_adjustment = NULL;
toplevel->left_label = NULL;
toplevel->middle_label = NULL;
toplevel->right_label = NULL;
toplevel->filename_label = NULL;
toplevel->status_label = NULL;
toplevel->toolbar_select = NULL;
toplevel->toolbar_net = NULL;
toplevel->toolbar_bus = NULL;
toplevel->toolbar_edit = NULL;
toplevel->toolbar_move = NULL;
toplevel->toolbar_copy = NULL;
toplevel->toolbar_delete = NULL;
toplevel->toolbar_rotate = NULL;
toplevel->toolbar_mirror = NULL;
toplevel->fowindow = NULL;
toplevel->fswindow = NULL;
toplevel->sowindow = NULL;
toplevel->saveas_flag = 0;
toplevel->aswindow = NULL;
toplevel->attr_list = NULL;
toplevel->asentry_name = NULL;
toplevel->asentry_value = NULL;
toplevel->cswindow = NULL;
toplevel->clib_list = NULL;
toplevel->basename_list = NULL;
toplevel->current_clib = NULL;
/* toplevel->current_basename */
/* toplevel->fileselect */
toplevel->pwindow = NULL;
toplevel->plib_list = NULL;
toplevel->pfilename_entry = NULL;
toplevel->iwindow = NULL;
toplevel->ifilename_entry = NULL;
toplevel->pswindow = NULL;
toplevel->page_clist = NULL;
toplevel->clist_sig = 0;
toplevel->tiwindow = NULL;
toplevel->tewindow = NULL;
toplevel->teentry = NULL;
toplevel->ltwindow = NULL;
toplevel->ftwindow = NULL;
toplevel->sewindow = NULL;
toplevel->seentry = NULL;
toplevel->exwindow = NULL;
toplevel->aawindow = NULL;
toplevel->mawindow = NULL;
toplevel->aewindow = NULL;
toplevel->aaentry_start = NULL;
toplevel->aaentry_sweep = NULL;
toplevel->trwindow = NULL;
toplevel->trentry = NULL;
toplevel->tswindow = NULL;
toplevel->tsentry = NULL;
toplevel->abwindow = NULL;
toplevel->hkwindow = NULL;
toplevel->cowindow = NULL;
toplevel->coord_world = NULL;
toplevel->coord_screen = NULL;
toplevel->pfswindow = NULL;
toplevel->pcfswindow = NULL;
#ifndef HAS_GTK12
toplevel->current_pixbuf = NULL;
#endif
toplevel->pixbuf_filename = NULL;
toplevel->pixbuf_wh_ratio = 0;
toplevel->clwindow = NULL;
toplevel->edit_color = 0;
toplevel->window = NULL;
toplevel->gc = NULL;
toplevel->xor_gc = NULL;
toplevel->outline_xor_gc = NULL;
toplevel->bounding_xor_gc = NULL;
toplevel->bus_gc = NULL;
toplevel->backingstore = NULL;
toplevel->graphic_color = 0;
toplevel->pin_color = 0;
toplevel->text_color = 0;
toplevel->logic_bubble_color = 0;
toplevel->zoom_box_color = 0;
toplevel->text_caps = 0;
toplevel->attribute_color = 0;
toplevel->detachedattr_color = 0;
toplevel->text_size = 0;
toplevel->snap_size = 100;
toplevel->grid_color = 0;
toplevel->background_color = 0;
toplevel->select_color = 0;
toplevel->bb_color = 0;
toplevel->lock_color = 0;
toplevel->net_endpoint_color = 0;
toplevel->net_color = 0;
toplevel->bus_color = 0;
toplevel->override_net_color = -1;
toplevel->override_bus_color = -1;
toplevel->override_pin_color = -1;
toplevel->pin_style = 0;
toplevel->net_style = 0;
toplevel->bus_style = 0;
toplevel->zoom_with_pan = 0;
toplevel->actionfeedback_mode = OUTLINE;
toplevel->text_feedback = 0;
toplevel->text_display_zoomfactor = 0;
toplevel->net_endpoint_mode = NONE;
toplevel->net_midpoint_mode = NONE;
toplevel->object_clipping = 0;
toplevel->embed_complex = 0;
toplevel->include_complex = 0;
toplevel->text_output = 0;
toplevel->scrollbars_flag = 0;
toplevel->print_orientation = 0;
toplevel->image_color = FALSE;
toplevel->print_color = FALSE;
toplevel->print_color_background = 0;
toplevel->setpagedevice_orientation = FALSE;
toplevel->setpagedevice_pagesize = FALSE;
toplevel->postscript_prolog = NULL;
toplevel->stroke_color = 0;
toplevel->log_window = 0;
toplevel->log_window_type = 0;
toplevel->third_button = 0;
toplevel->middle_button = 0;
toplevel->net_consolidate = FALSE;
toplevel->file_preview = 0;
toplevel->enforce_hierarchy = 0;
toplevel->text_origin_marker = 0;
toplevel->fast_mousepan = 0;
toplevel->raise_dialog_boxes = 0;
/* The following is an attempt at getting (deterministic) defaults */
/* for the following variables */
toplevel->attribute_promotion = FALSE;
toplevel->promote_invisible = FALSE;
toplevel->keep_invisible = FALSE;
toplevel->continue_component_place = 0;
toplevel->undo_levels = 0;
toplevel->undo_control = 0;
toplevel->undo_type = 0;
toplevel->draw_grips = 0;
toplevel->netconn_rubberband = 0;
toplevel->sort_component_library = 0;
toplevel->warp_cursor = 0;
toplevel->toolbars = 0;
toplevel->handleboxes = 0;
toplevel->print_output_type = 0;
toplevel->print_output_capstyle = BUTT_CAP;
toplevel->image_output_type = 0;
toplevel->paper_width = 0;
toplevel->paper_height = 0;
toplevel->bus_ripper_size = 0;
toplevel->bus_ripper_type = 0;
toplevel->bus_ripper_symname = NULL;
toplevel->bus_ripper_rotation = 0;
toplevel->force_boundingbox = FALSE;
toplevel->grid_dot_size = 1;
toplevel->grid_mode = GRID_VARIABLE_MODE;
toplevel->grid_fixed_threshold = 10;
toplevel->print_vector_threshold = 3;
toplevel->add_attribute_offset = 50;
toplevel->drag_can_move = TRUE;
toplevel->always_promote_attributes = NULL;
toplevel->net_naming_priority = 0;
toplevel->hierarchy_traversal = 0;
toplevel->hierarchy_uref_mangle = 0;
toplevel->hierarchy_netname_mangle = 0;
toplevel->hierarchy_netattrib_mangle = 0;
toplevel->hierarchy_uref_separator = NULL;
toplevel->hierarchy_netname_separator = NULL;
toplevel->hierarchy_netattrib_separator = NULL;
toplevel->hierarchy_netattrib_order = 0;
toplevel->hierarchy_netname_order = 0;
toplevel->hierarchy_uref_order = 0;
toplevel->unnamed_netname = NULL;
/* Auto-save interval */
toplevel->auto_save_interval = 0;
/* set the rest of the variables */
if (variable_set_func) {
(*variable_set_func) (toplevel);
}
/* disable the events */
toplevel->DONT_DRAW_CONN = 1;
toplevel->DONT_RESIZE = 1;
toplevel->DONT_EXPOSE = 1;
toplevel->DONT_RECALC = 1;
toplevel->DONT_REDRAW = 1;
/* now append toplevel to this list: */
/* - find the tail of the toplevel list */
for (tmp = toplevel_head; tmp->next != NULL; tmp = tmp->next);
/* - link toplevel with tmp */
tmp->next = toplevel;
toplevel->prev = tmp;
toplevel->next = NULL;
return toplevel;
}
/*! \todo Finish function documentation!!!
* \brief
* \par Function Description
*
*/
void s_toplevel_delete (TOPLEVEL *toplevel)
{
if (toplevel->wid == -1) {
/* do no delete head */
return;
}
g_free (toplevel->series_name);
g_free (toplevel->untitled_name);
g_free (toplevel->font_directory);
g_free (toplevel->scheme_directory);
g_free (toplevel->bitmap_directory);
g_free (toplevel->bus_ripper_symname);
/* free all fonts */
/* if you close a window, then you free the font set... */
/* this is probably a bad idea... */
/* The font set can ONLY be freed when exiting!!! */
/* o_text_freeallfonts (toplevel); */
/* delete all pages */
s_page_delete_list (toplevel);
/* unlink toplevel from toplevel list */
toplevel->prev->next = toplevel->next;
if (toplevel->next != NULL) {
toplevel->next->prev = toplevel->prev;
}
g_free (toplevel);
}
1.5 +270 -226 eda/geda/gaf/libgeda/src/s_undo.c
(In the diff below, changes in quantity of whitespace are not shown.)
Index: s_undo.c
===================================================================
RCS file: s_undo.c
diff -N s_undo.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ s_undo.c 5 Jul 2006 03:13:39 -0000 1.5
@@ -0,0 +1,352 @@
+/* gEDA - GPL Electronic Design Automation
+ * libgeda - gEDA's library
+ * Copyright (C) 1998-2000 Ales V. Hvezda
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+#include <config.h>
+
+#include <stdio.h>
+#include <ctype.h>
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#ifdef HAVE_ASSERT_H
+#include <assert.h>
+#endif
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <libguile.h>
+
+#include "defines.h"
+#include "struct.h"
+#include "defines.h"
+#include "globals.h"
+#include "colors.h"
+#include "o_types.h"
+
+#include "../include/prototype.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+UNDO *s_undo_return_tail(UNDO *head)
+{
+ UNDO *u_current=NULL;
+ UNDO *ret_struct=NULL;
+
+ u_current = head;
+ while ( u_current != NULL ) { /* goto end of list */
+ ret_struct = u_current;
+ u_current = u_current->next;
+ }
+
+ return(ret_struct);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+UNDO *s_undo_return_head(UNDO *tail)
+{
+ UNDO *u_current=NULL;
+ UNDO *ret_struct=NULL;
+
+ u_current = tail;
+ while ( u_current != NULL ) { /* goto end of list */
+ ret_struct = u_current;
+ u_current = u_current->prev;
+ }
+
+ return(ret_struct);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+UNDO *s_undo_new_head(void)
+{
+ UNDO *u_new;
+
+ u_new = (UNDO *) malloc(sizeof(UNDO));
+ u_new->type = -1;
+ u_new->filename = NULL;
+ u_new->object_head = NULL;
+ u_new->left = u_new->right = u_new->top = u_new->bottom = -1;
+
+ u_new->page_control = 0;
+ u_new->up = -2;
+
+ u_new->prev = NULL;
+ u_new->next = NULL;
+
+ return(u_new);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_undo_destroy_head(UNDO *u_head)
+{
+ free(u_head);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+UNDO *s_undo_add(UNDO *head, int type, char *filename, OBJECT *object_head,
+ int left, int top, int right, int bottom, int page_control,
+ int up)
+{
+ UNDO *tail;
+ UNDO *u_new;
+
+ u_new = (UNDO *) malloc(sizeof(UNDO));
+
+ u_new->filename = g_strdup (filename);
+
+ if (object_head != NULL) {
+ u_new->object_head = object_head;
+ } else {
+ u_new->object_head = NULL;
+ }
+
+ u_new->type = type;
+
+ u_new->left = left;
+ u_new->top = top;
+ u_new->right = right;
+ u_new->bottom = bottom;
+
+ u_new->page_control = page_control;
+ u_new->up = up;
+
+ if (head == NULL) {
+ u_new->prev = NULL; /* setup previous link */
+ u_new->next = NULL;
+ return(u_new);
+ } else {
+ tail = s_undo_return_tail(head);
+ u_new->prev = tail; /* setup previous link */
+ u_new->next = NULL;
+ tail->next = u_new;
+ return(tail->next);
+ }
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_undo_print_all( UNDO *head )
+{
+ UNDO *u_current;
+
+ u_current = head;
+
+ printf("START printing undo ********************\n");
+ printf("BOTTOM\n");
+ while(u_current != NULL) {
+
+ if (u_current->filename) printf("%s\n", u_current->filename);
+
+ if (u_current->object_head) {
+ printf("%s\n", u_current->object_head->name);
+ print_struct_forw(u_current->object_head);
+ }
+
+ printf("\t%d %d %d %d\n", u_current->left, u_current->top,
+ u_current->right, u_current->bottom);
+ u_current = u_current->next;
+ }
+ printf("TOS\n");
+ printf("Number of levels: %d\n", s_undo_levels(head));
+ printf("DONE printing undo ********************\n");
+ printf("\n");
+
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_undo_destroy_all(TOPLEVEL *w_current, UNDO *head)
+{
+ UNDO *u_current;
+ UNDO *u_prev;
+
+ u_current = s_undo_return_tail(head);
+
+ while (u_current != NULL) {
+ u_prev = u_current->prev;
+ if (u_current->filename) free(u_current->filename);
+
+ if (u_current->object_head) {
+ w_current->REMOVING_SEL = 1;
+ s_delete_list_fromstart(w_current,
+ u_current->object_head);
+ w_current->REMOVING_SEL = 0;
+ u_current->object_head = NULL;
+ }
+
+ free(u_current);
+ u_current = u_prev;
+ }
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_undo_remove(TOPLEVEL *w_current, UNDO *head, UNDO *u_tos)
+{
+ UNDO *u_current;
+
+ if (u_tos == NULL) {
+ fprintf(stderr, "Got NULL for u_tos in s_undo_remove\n");
+ return;
+ }
+
+ u_current = head;
+
+ while (u_current != NULL) {
+ if (u_current == u_tos) {
+ if (u_current->next)
+ u_current->next->prev = u_current->prev;
+ else
+ u_current->next = NULL;
+
+ if (u_current->prev)
+ u_current->prev->next = u_current->next;
+ else
+ u_current->prev = NULL;
+
+ if (u_current->filename) {
+ free(u_current->filename);
+ }
+
+ if (u_current->object_head) {
+ /*w_current->REMOVING_SEL = 1; */
+ s_delete_list_fromstart(w_current,
+ u_current->object_head);
+ /*w_current->REMOVING_SEL = 0;*/
+ u_current->object_head = NULL;
+ }
+
+ free(u_current);
+ return;
+ }
+ u_current = u_current->next;
+ }
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_undo_remove_rest(TOPLEVEL *w_current, UNDO *head)
+{
+ UNDO *u_current;
+ UNDO *u_next;
+
+ u_current = head;
+
+ while (u_current != NULL) {
+ u_next = u_current->next;
+
+ if (u_current->filename) {
+ unlink(u_current->filename);
+ free(u_current->filename);
+ }
+
+ if (u_current->object_head) {
+ w_current->REMOVING_SEL = 1;
+ s_delete_list_fromstart(w_current,
+ u_current->object_head);
+ w_current->REMOVING_SEL = 0;
+ u_current->object_head = NULL;
+ }
+
+ free(u_current);
+ u_current = u_next;
+ }
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+int s_undo_levels(UNDO *head)
+{
+ UNDO *u_current;
+ int count = 0;
+
+ u_current = head;
+ while (u_current != NULL) {
+ if (u_current->filename || u_current->object_head) {
+ count++;
+ }
+
+ u_current = u_current->next;
+ }
+
+ return(count);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_undo_init(PAGE *p_current)
+{
+ p_current->undo_tos = p_current->undo_bottom = NULL;
+ p_current->undo_current = NULL;
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void s_undo_free_all(TOPLEVEL *w_current, PAGE *p_current)
+{
+ s_undo_destroy_all(w_current, p_current->undo_bottom);
+ p_current->undo_bottom = NULL;
+ p_current->undo_tos = NULL;
+ p_current->undo_current = NULL;
+}
1.10 +131 -103 eda/geda/gaf/libgeda/src/u_basic.c
(In the diff below, changes in quantity of whitespace are not shown.)
Index: u_basic.c
===================================================================
RCS file: u_basic.c
diff -N u_basic.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ u_basic.c 5 Jul 2006 03:13:39 -0000 1.10
@@ -0,0 +1,167 @@
+/* gEDA - GPL Electronic Design Automation
+ * libgeda - gEDA's library
+ * Copyright (C) 1998, 1999, 2000 Kazu Hirata / Ales Hvezda
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111 USA
+ */
+#include <config.h>
+
+#include <stdio.h>
+#ifdef HAVE_STRING_H
+#include <string.h>
+#endif
+#ifdef HAVE_STDARG_H
+#include <stdarg.h>
+#endif
+#ifdef HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+
+#include <gtk/gtk.h>
+#include <libguile.h>
+
+#include "defines.h"
+#include "struct.h"
+#include "globals.h"
+
+#include "../include/prototype.h"
+
+#ifdef HAVE_LIBDMALLOC
+#include <dmalloc.h>
+#endif
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+/* the delimiter is what is passed in or spaces */
+/* count starts at zero */
+char *u_basic_breakup_string(char *string, char delimiter, int count)
+{
+ int i=0, j=0;
+ int internal_counter=0;
+ int done=FALSE;
+ char *return_value;
+
+ /* skip over any leading white space */
+ while(string[i] == ' ' && !string[i]) {
+ i++;
+ }
+
+ /* Allocate space for temp string storage (+1 for null character) */
+ return_value = malloc(sizeof(char)*(strlen(string) + 1));
+
+ while(!done) {
+
+ /* oops, ran out of string before we found what we were */
+ /* looking for */
+ if (i > strlen(string)) {
+ free(return_value);
+ return(NULL);
+ }
+
+ /* skip over any leading white space */
+ while(string[i] == ' ' && string[i] != '\0') {
+ i++;
+ }
+
+ j = 0;
+
+ /* Old forgiving parsing */
+ /* while(string[i] != ',' && string[i] != ';' && */
+ /* string[i] != ' ' && string[i] != '\0') {*/
+
+ while(string[i] != delimiter && string[i] != '\0') {
+ return_value[j] = string[i];
+ i++; j++;
+ }
+
+ if (internal_counter == count) {
+ done = TRUE;
+ } else {
+ internal_counter++;
+ i++; /* skip the offending character */
+ }
+ }
+
+ return_value[j] = '\0';
+ return(return_value);
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+void u_basic_strip_trailing(char *string, char c)
+{
+ if (string) {
+ int len = strlen(string) - 1; /* point to last char */
+ if (string[len] == c) {
+ string[len] = '\0';
+ }
+ }
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+int u_basic_has_trailing(char *string, char c)
+{
+ if (string) {
+ int len = strlen(string) - 1; /* point to last char */
+ if (string[len] == c) {
+ return TRUE;
+ }
+ }
+ return FALSE;
+}
+
+/*! \todo Finish function documentation!!!
+ * \brief
+ * \par Function Description
+ *
+ */
+/*
+ * This fcn counts the number of occurances of the character
+ * "character" in the string "string".
+ * 1.23.2005 -- SDB
+ */
+int u_basic_count_char(const char *string, char character)
+{
+ int count = 0;
+ int i=0;
+
+#ifdef DEBUG
+ printf("In u_basic_count_char, looking for char \"%c\" in string \"%s\".\n",
+ character, string);
+#endif
+
+ while (string[i] != '\0') {
+ if (string[i] == character) {
+ count++;
+ }
+ i++;
+ }
+#ifdef DEBUG
+ printf(". . . . . Found it %d times.\n",
+ count);
+#endif
+
+return count;
+}
_______________________________________________
geda-cvs mailing list
geda-cvs@xxxxxxxxxxxxxx
http://www.seul.org/cgi-bin/mailman/listinfo/geda-cvs