File o_net_basic.c
******************

File header
===========

     <<o_net_basic.c : *>>=
     <<o_net_basic.c : copyright and license -- o_net_basic.c - copyright and license>>

     /* DO NOT read or edit this file ! Use ../noweb/o_net_basic.nw instead */

     <<o_net_basic.c : include directives -- o_net_basic.c - include directives>>
     <<o_net_basic.c : get_net_bounds() -- o_net_basic.c - get_net_bounds()>>
     <<o_net_basic.c : world_get_net_bounds() -- o_net_basic.c - world_get_net_bounds()>>
     <<o_net_basic.c : o_net_add() -- o_net_basic.c - o_net_add()>>
     <<o_net_basic.c : o_net_recalc() -- o_net_basic.c - o_net_recalc()>>
     <<o_net_basic.c : o_net_read() -- o_net_basic.c - o_net_read()>>
     <<o_net_basic.c : o_net_save() -- o_net_basic.c - o_net_save()>>
     <<o_net_basic.c : o_net_translate() -- o_net_basic.c - o_net_translate()>>
     <<o_net_basic.c : o_net_translate_world() -- o_net_basic.c - o_net_translate_world()>>
     <<o_net_basic.c : o_net_copy() -- o_net_basic.c - o_net_copy()>>
     <<o_net_basic.c : o_net_print() -- o_net_basic.c - o_net_print()>>
     <<o_net_basic.c : o_net_image_write() -- o_net_basic.c - o_net_image_write()>>
     <<o_net_basic.c : o_net_rotate() -- o_net_basic.c - o_net_rotate()>>
     <<o_net_basic.c : o_net_rotate_world() -- o_net_basic.c - o_net_rotate_world()>>
     <<o_net_basic.c : o_net_mirror() -- o_net_basic.c - o_net_mirror()>>
     <<o_net_basic.c : o_net_mirror_world() -- o_net_basic.c - o_net_mirror_world()>>
     <<o_net_basic.c : o_net_orientation() -- o_net_basic.c - o_net_orientation()>>
     <<o_net_basic.c : o_net_consolidate_lowlevel() -- o_net_basic.c - o_net_consolidate_lowlevel()>>
     <<o_net_basic.c : o_net_consolidate_nomidpoint() -- o_net_basic.c - o_net_consolidate_nomidpoint()>>
     <<o_net_basic.c : o_net_consolidate_segments() -- o_net_basic.c - o_net_consolidate_segments()>>
     <<o_net_basic.c : o_net_consolidate() -- o_net_basic.c - o_net_consolidate()>>
     <<o_net_basic.c : o_net_modify() -- o_net_basic.c - o_net_modify()>>

     <<o_net_basic.c : copyright and license>>=
     /* 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
      */

     <<o_net_basic.c : include directives>>=
     #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

Function get_net_bounds()
=========================

 -- Function: get_net_bounds w_current line left top right bottom

     <<o_net_basic.c : get_net_bounds()>>=
     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;
     }

          Defines :
          get_net_bounds,
           -- o_net_basic.c - o_net_add(),
           -- o_net_basic.c - o_net_recalc(),
           -- o_net_basic.c - o_net_translate_world(),
           -- o_net_basic.c - o_net_modify().

     }

Function world_get_net_bounds()
===============================

 -- Function: world_get_net_bounds w_current line left top right bottom

     <<o_net_basic.c : world_get_net_bounds()>>=
     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];

     }

          Defines :
          .

     }

Function o_net_add()
====================

 -- Function: o_net_add w_current object_list type color x1 y1 x2 y2

     <<o_net_basic.c : o_net_add()>>=
     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);
     }

          Defines :
          o_net_add,
           -- o_net_basic.c - o_net_copy(),
           -- o_net_basic.c - o_net_read().

          Uses :
          get_net_bounds,  -- o_net_basic.c - get_net_bounds().

     }

Function o_net_recalc()
=======================

 -- Function: o_net_recalc w_current o_current

     <<o_net_basic.c : o_net_recalc()>>=
     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;

     }

          Defines :
          o_net_recalc,
           -- o_net_basic.c - o_net_consolidate_segments().

          Uses :
          get_net_bounds,  -- o_net_basic.c - get_net_bounds().

     }

Function o_net_read()
=====================

 -- Function: o_net_read w_current object_list buf version

     <<o_net_basic.c : o_net_read()>>=
     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);
     }

          Defines :
          .

          Uses :
          o_net_add,  -- o_net_basic.c - o_net_add().

     }

Function o_net_save()
=====================

 -- Function: o_net_save buf object

     <<o_net_basic.c : o_net_save()>>=
     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);
     }

          Defines :
          .

     }

Function o_net_translate()
==========================

 -- Function: o_net_translate w_current dx dy object

     <<o_net_basic.c : o_net_translate()>>=
     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);
     }

          Defines :
          .

     }

Function o_net_translate_world()
================================

 -- Function: o_net_translate_world w_current x1 y1 object

     <<o_net_basic.c : o_net_translate_world()>>=
     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);
     }

          Defines :
          o_net_translate_world,
           -- o_net_basic.c - o_net_rotate_world(),
           -- o_net_basic.c - o_net_rotate(),
           -- o_net_basic.c - o_net_mirror(),
           -- o_net_basic.c - o_net_mirror_world().

          Uses :
          get_net_bounds,  -- o_net_basic.c - get_net_bounds().

     }

Function o_net_copy()
=====================

 -- Function: o_net_copy w_current list_tail o_current

     <<o_net_basic.c : o_net_copy()>>=
     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);
     }

          Defines :
          .

          Uses :
          o_net_add,  -- o_net_basic.c - o_net_add().

     }

Function o_net_print()
======================

 -- Function: o_net_print w_current fp o_current origin_x origin_y

     <<o_net_basic.c : o_net_print()>>=
     void
     o_net_print(TOPLEVEL * w_current, FILE * fp, OBJECT * o_current,
                 int origin_x, int origin_y)
     {
       int offset, offset2;
       int cross;
       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);
       }

       fprintf(fp, "gsave\n");
       fprintf(fp, "newpath\n");
       if (w_current->net_style == THICK) {
         fprintf(fp, "%d mils setlinewidth\n", 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 mils %d mils moveto\n", x1, y1);
       fprintf(fp, "%d mils %d mils lineto\n", x2, y2);

       fprintf(fp, "stroke\n");

     #if 0 /* is this completely redundant, not sure why this is here */
       /* maybe move this inside, so it doesn't clutter the ps file */
       if (w_current->print_color) {
         f_print_set_color(fp, w_current->net_endpoint_color);
       }
     #endif

       fprintf(fp, "grestore\n");
     }

          Defines :
          .

     }

Function o_net_image_write()
============================

 -- Function: o_net_image_write w_current o_current origin_x origin_y color_mode

     <<o_net_basic.c : o_net_image_write()>>=
     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;
       }

     }

          Defines :
          .

     }

Function o_net_rotate()
=======================

 -- Function: o_net_rotate w_current centerx centery angle object

     <<o_net_basic.c : o_net_rotate()>>=
     /* 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);
     }

          Defines :
          .

          Uses :
          o_net_translate_world,  -- o_net_basic.c - o_net_translate_world().

     }

Function o_net_rotate_world()
=============================

 -- Function: o_net_rotate_world w_current world_centerx world_centery angle object

     <<o_net_basic.c : o_net_rotate_world()>>=
     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);
     }

          Defines :
          .

          Uses :
          o_net_translate_world,  -- o_net_basic.c - o_net_translate_world().

     }

Function o_net_mirror()
=======================

 -- Function: o_net_mirror w_current centerx centery object

     <<o_net_basic.c : o_net_mirror()>>=
     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);
     }

          Defines :
          .

          Uses :
          o_net_translate_world,  -- o_net_basic.c - o_net_translate_world().

     }

Function o_net_mirror_world()
=============================

 -- Function: o_net_mirror_world w_current world_centerx world_centery object

     <<o_net_basic.c : o_net_mirror_world()>>=
     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);
     }

          Defines :
          .

          Uses :
          o_net_translate_world,  -- o_net_basic.c - o_net_translate_world().

     }

Function o_net_orientation()
============================

 -- Function: o_net_orientation object

     <<o_net_basic.c : o_net_orientation()>>=
     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);
     }

          Defines :
          o_net_orientation,
           -- o_net_basic.c - o_net_consolidate_segments().

     }

Function o_net_consolidate_lowlevel()
=====================================

 -- Function: o_net_consolidate_lowlevel object del_object orient

     <<o_net_basic.c : o_net_consolidate_lowlevel()>>=
     /* 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;
           }
         }
       }

     }

          Defines :
          o_net_consolidate_lowlevel,
           -- o_net_basic.c - o_net_consolidate_segments().

     }

Function o_net_consolidate_nomidpoint()
=======================================

 -- Function: o_net_consolidate_nomidpoint object x y

     <<o_net_basic.c : o_net_consolidate_nomidpoint()>>=
     /* 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);
     }

          Defines :
          o_net_consolidate_nomidpoint,
           -- o_net_basic.c - o_net_consolidate_segments().

     }

Function o_net_consolidate_segments()
=====================================

 -- Function: o_net_consolidate_segments w_current object

     <<o_net_basic.c : o_net_consolidate_segments()>>=
     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);
     }

          Defines :
          o_net_consolidate_segments,
           -- o_net_basic.c - o_net_consolidate().

          Uses :
          o_net_consolidate_lowlevel,  -- o_net_basic.c - o_net_consolidate_lowlevel().
          o_net_consolidate_nomidpoint,  -- o_net_basic.c - o_net_consolidate_nomidpoint().
          o_net_orientation,  -- o_net_basic.c - o_net_orientation().
          o_net_recalc,  -- o_net_basic.c - o_net_recalc().

     }

Function o_net_consolidate()
============================

 -- Function: o_net_consolidate w_current

     <<o_net_basic.c : o_net_consolidate()>>=
     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;
         }
       }
     }

          Defines :
          .

          Uses :
          o_net_consolidate_segments,  -- o_net_basic.c - o_net_consolidate_segments().

     }

Function o_net_modify()
=======================

 -- Function: o_net_modify w_current object x y whichone

     <<o_net_basic.c : o_net_modify()>>=
     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);
     }

          Defines :
          .

          Uses :
          get_net_bounds,  -- o_net_basic.c - get_net_bounds().

     }