[comp.sources.x] v08i087: tgif, Patch3, Part01/03

william@CS.UCLA.EDU (William Cheng) (08/21/90)

Submitted-by: william@CS.UCLA.EDU (William Cheng)
Posting-number: Volume 8, Issue 87
Archive-name: tgif/patch3.01
Patch-To: Volume 7, Issue 56-76 (original: tgif-1.2)
Patch-To: Volume 8, Issue 46-48 (Patch1: tgif-1.2 => tgif-1.9)
Patch-To: Volume 8, Issue 58-60 (Patch2: tgif-1.9 => tgif-1.12)

Patch3 of tgif takes tgif-1.12 to tgif-1.13.  Below is a list of
added features/bug fixes, followed by the actual patch.

tgif-1.12 => tgif-1.13

1) Fix a bug to set the font of the active cursor correctly when adding
   or deleting points.
2) Fix a bug for ``prtgif'' so that it works correctly when the page
   style is not portrait.
3) Every object can have attributes, and attribute's name field can be empty.
4) Add copy and paste operations.  Support copy and paste between multiple
   tgifs.  Thanks to Kouichi Matsuda@NEC in Japan for his contribution to
   the code.

---------------------------------> cut here <---------------------------------
*** attr.c.orig	Fri Aug 17 13:45:27 1990
--- attr.c	Fri Aug 17 13:45:29 1990
***************
*** 6,10 ****
  #ifndef lint
  static char RCSid[] =
!       "@(#)$Header: /n/kona/u/tangram/u/william/X11/TGIF/RCS/attr.c,v 1.6 90/07/30 11:09:21 william Exp $";
  #endif
  
--- 6,10 ----
  #ifndef lint
  static char RCSid[] =
!       "@(#)$Header: /n/kona/u/tangram/u/william/X11/TGIF/RCS/attr.c,v 1.9 90/08/13 09:23:13 william Exp $";
  #endif
  
***************
*** 75,93 ****
     own_ptr = AttrPtr->owner;
   
!    if (own_ptr->type == OBJ_POLY)
!    {
!       top_attr_ad = &(own_ptr->detail.p->fattr);
!       bot_attr_ad = &(own_ptr->detail.p->lattr);
!    }
!    else
!    {
!       top_attr_ad = &(own_ptr->detail.r->fattr);
!       bot_attr_ad = &(own_ptr->detail.r->lattr);
!    }
       
     if (*top_attr_ad == AttrPtr)
!          *top_attr_ad = AttrPtr->next;
!       else
!          AttrPtr->prev->next = AttrPtr->next;
  
     if (*bot_attr_ad == AttrPtr)
--- 75,85 ----
     own_ptr = AttrPtr->owner;
   
!    top_attr_ad = &(own_ptr->fattr);
!    bot_attr_ad = &(own_ptr->lattr);
       
     if (*top_attr_ad == AttrPtr)
!       *top_attr_ad = AttrPtr->next;
!    else
!       AttrPtr->prev->next = AttrPtr->next;
  
     if (*bot_attr_ad == AttrPtr)
***************
*** 106,110 ****
  
  static
! short ParseAttrStr(Str, name, s)
     char	* Str, * name, * s;
  {
--- 98,102 ----
  
  static
! void ParseAttrStr(Str, name, s)
     char	* Str, * name, * s;
  {
***************
*** 134,142 ****
  
        *ptr = '\0';
-        
-       return (TRUE);
     }
     else
!       return (FALSE);
  } 
  
--- 126,135 ----
  
        *ptr = '\0';
     }
     else
!    {
!       *name = '\0';
!       strcpy (s, Str);
!    }
  } 
  
***************
*** 267,278 ****
  
     topAttr = botAttr = NULL;
!    switch (ToObjPtr->type)
!    {
!       case OBJ_POLY: from_attr_ptr = FromObjPtr->detail.p->fattr; break;
! 
!       case OBJ_SYM:
!       case OBJ_GROUP:
!       case OBJ_ICON: from_attr_ptr = FromObjPtr->detail.r->fattr; break;
!    }
     for ( ; from_attr_ptr != NULL; from_attr_ptr = from_attr_ptr->next)
     {
--- 260,264 ----
  
     topAttr = botAttr = NULL;
!    from_attr_ptr = FromObjPtr->fattr;
     for ( ; from_attr_ptr != NULL; from_attr_ptr = from_attr_ptr->next)
     {
***************
*** 282,302 ****
        LinkInAttr (NULL, topAttr, to_attr_ptr);
     }
!    switch (ToObjPtr->type)
!    {
!       case OBJ_POLY:
!          ToObjPtr->detail.p->fattr = topAttr;
!          ToObjPtr->detail.p->lattr = botAttr;
!          break;
!       case OBJ_SYM:
!       case OBJ_GROUP:
!       case OBJ_ICON:
!          ToObjPtr->detail.r->fattr = topAttr;
!          ToObjPtr->detail.r->lattr = botAttr;
!          break;
!    }
  }
  
  static
! int AddAttr(ObjPtr, TextObjPtr)
     struct ObjRec	* ObjPtr, * TextObjPtr;
  {
--- 268,277 ----
        LinkInAttr (NULL, topAttr, to_attr_ptr);
     }
!    ToObjPtr->fattr = topAttr;
!    ToObjPtr->lattr = botAttr;
  }
  
  static
! void AddAttr(ObjPtr, TextObjPtr)
     struct ObjRec	* ObjPtr, * TextObjPtr;
  {
***************
*** 309,351 ****
     text_ptr = TextObjPtr->detail.t; 
  
!    if (ParseAttrStr(text_ptr->first->s, name, value))
!    {
!       switch (ObjPtr->type)
!       {
!          case OBJ_POLY:
!             topAttr = ObjPtr->detail.p->fattr;
!             botAttr = ObjPtr->detail.p->lattr;
!             break;
!          case OBJ_SYM:
!          case OBJ_GROUP:
!          case OBJ_ICON:
!             topAttr = ObjPtr->detail.r->fattr;
!             botAttr = ObjPtr->detail.r->lattr;
!             break;
!       }
  
!       UnlinkObj (TextObjPtr);
!       TextObjPtr->next = TextObjPtr->prev = NULL;
!       attr_ptr = NewAttr (ObjPtr, TextObjPtr, FALSE); 
!       UpdateAttr (text_ptr, attr_ptr); 
!       LinkInAttr (NULL, topAttr, attr_ptr);
  
!       switch (ObjPtr->type)
!       {
!          case OBJ_POLY:
!             ObjPtr->detail.p->fattr = topAttr;
!             ObjPtr->detail.p->lattr = botAttr;
!             break;
!          case OBJ_SYM:
!          case OBJ_GROUP:
!          case OBJ_ICON:
!             ObjPtr->detail.r->fattr = topAttr;
!             ObjPtr->detail.r->lattr = botAttr;
!             break;
!       }
!       return (TRUE);
!    }
!    else
!       return (FALSE);
  }
  
--- 284,299 ----
     text_ptr = TextObjPtr->detail.t; 
  
!    ParseAttrStr(text_ptr->first->s, name, value);
!    topAttr = ObjPtr->fattr;
!    botAttr = ObjPtr->lattr;
  
!    UnlinkObj (TextObjPtr);
!    TextObjPtr->next = TextObjPtr->prev = NULL;
!    attr_ptr = NewAttr (ObjPtr, TextObjPtr, FALSE); 
!    UpdateAttr (text_ptr, attr_ptr); 
!    LinkInAttr (NULL, topAttr, attr_ptr);
  
!    ObjPtr->fattr = topAttr;
!    ObjPtr->lattr = botAttr;
  }
  
***************
*** 354,367 ****
     struct AttrRec	* attr_ptr;
     struct ObjRec	* owner_ptr = NULL, * attr_obj_ptr;
!    struct SelRec	* sel_ptr, * tmp_top_sel = NULL, * tmp_bot_sel = NULL;
!    struct SelRec	* new_sel_ptr;
!    int			still_valid = TRUE, text_count = 0;
!    int			sel_ltx, sel_lty, sel_rbx, sel_rby;
  
!    for (sel_ptr = topSel; (sel_ptr!=NULL) && (still_valid);
!          sel_ptr = sel_ptr->next)
        switch (sel_ptr->obj->type)
        {
           case OBJ_TEXT: text_count++; break;
           case OBJ_POLY:
           case OBJ_SYM:
--- 302,316 ----
     struct AttrRec	* attr_ptr;
     struct ObjRec	* owner_ptr = NULL, * attr_obj_ptr;
!    struct SelRec	* sel_ptr, * new_sel_ptr;
!    int			text_count = 0, sel_ltx, sel_lty, sel_rbx, sel_rby;
  
!    for (sel_ptr = topSel; sel_ptr != NULL; sel_ptr = sel_ptr->next)
        switch (sel_ptr->obj->type)
        {
           case OBJ_TEXT: text_count++; break;
+ 
+          case OBJ_BOX:
+          case OBJ_OVAL:
+          case OBJ_POLYGON:
           case OBJ_POLY:
           case OBJ_SYM:
***************
*** 368,442 ****
           case OBJ_GROUP:
           case OBJ_ICON:
!             if (owner_ptr == NULL)
!                owner_ptr = sel_ptr->obj;
!             else
              {
!                still_valid = FALSE;
!                Msg("Too many icon, group, symbol, or poly objects selected.");
              }
              break; 
-          case OBJ_BOX:
-          case OBJ_OVAL:
-          case OBJ_POLYGON:
-             still_valid = FALSE;
-             Msg("Only icons, groups, symbols, and polys can have attributes");
-             break;
        }
   
!    if (still_valid)
     {
!       if (text_count == 0)
!          Msg("No text objects selected to add as attributes.");
!       else
!       {
!          if (owner_ptr != NULL)
!          {
!             HighLightReverse ();
!             sel_ltx = selLtX; sel_lty = selLtY;
!             sel_rbx = selRbX; sel_rby = selRbY;
  
!             for (sel_ptr = botSel;  sel_ptr != NULL; sel_ptr = sel_ptr->prev)
!                if (sel_ptr->obj->type == OBJ_TEXT)
!                   if (!AddAttr(owner_ptr, sel_ptr->obj))
!                   { /* bad format for the text to be an attribute */
!                      new_sel_ptr = (struct SelRec *) calloc (1,
!                            sizeof(struct SelRec));
!                      new_sel_ptr->obj = sel_ptr->obj;
  
!                      new_sel_ptr->prev = NULL;
!                      new_sel_ptr->next = tmp_top_sel;
!                      if (tmp_top_sel == NULL)
!                         tmp_bot_sel = new_sel_ptr;
!                      else
!                         tmp_top_sel->prev = new_sel_ptr;
!                      tmp_top_sel = new_sel_ptr;
!                   }
  
!             RemoveAllSel ();
!             UnlinkObj (owner_ptr);
!             AddObj (NULL, topObj, owner_ptr);
!             topSel = botSel = (struct SelRec *) calloc (1,
!                   sizeof(struct SelRec));
!             topSel->obj = owner_ptr;
!             topSel->prev = NULL;
!             botSel->next = tmp_top_sel;
!             if (tmp_top_sel != NULL)
!             {
!                tmp_top_sel->prev = topSel;
!                botSel = tmp_bot_sel;
!             }
!             AdjObjBBox (owner_ptr);
!             UpdSelBBox ();
!             RedrawAreas (botObj, sel_ltx-(1<<zoomScale), sel_lty-(1<<zoomScale),
!                   sel_rbx+(1<<zoomScale), sel_rby+(1<<zoomScale),
!                   selLtX-(1<<zoomScale), selLtY-(1<<zoomScale),
!                   selRbX+(1<<zoomScale), selRbY+(1<<zoomScale));
!             HighLightForward ();
!             justDupped = FALSE;
!          } 
!          else
!             Msg("No icon, group, symbol, poly objects selected.");
!       }
!    }
  }
  
--- 317,363 ----
           case OBJ_GROUP:
           case OBJ_ICON:
!             if (owner_ptr != NULL)
              {
!                Msg("Too non-text objects selected.");
!                return;
              }
+             owner_ptr = sel_ptr->obj;
              break; 
        }
   
!    if (text_count == 0)
     {
!       Msg("No text objects selected to add as attributes.");
!       return;
!    }
!    if (owner_ptr == NULL)
!    {
!       Msg("No objects (other than TEXT objects) selected.");
!       return;
!    }
  
!    HighLightReverse ();
!    sel_ltx = selLtX; sel_lty = selLtY;
!    sel_rbx = selRbX; sel_rby = selRbY;
  
!    for (sel_ptr = botSel;  sel_ptr != NULL; sel_ptr = sel_ptr->prev)
!       if (sel_ptr->obj->type == OBJ_TEXT)
!          AddAttr(owner_ptr, sel_ptr->obj);
  
!    RemoveAllSel ();
!    UnlinkObj (owner_ptr);
!    AddObj (NULL, topObj, owner_ptr);
!    topSel = botSel = (struct SelRec *) calloc (1, sizeof(struct SelRec));
!    topSel->obj = owner_ptr;
!    topSel->prev = NULL;
!    botSel->next = NULL;
!    AdjObjBBox (owner_ptr);
!    UpdSelBBox ();
!    RedrawAreas (botObj, sel_ltx-(1<<zoomScale), sel_lty-(1<<zoomScale),
!          sel_rbx+(1<<zoomScale), sel_rby+(1<<zoomScale),
!          selLtX-(1<<zoomScale), selLtY-(1<<zoomScale),
!          selRbX+(1<<zoomScale), selRbY+(1<<zoomScale));
!    HighLightForward ();
!    justDupped = FALSE;
  }
  
***************
*** 446,452 ****
     struct AttrRec	* AttrPtr;
  {
- /* fprintf (FP, "attr(\"%s\", \"%s\", %1d, %1d, %1d,\n", */
- /*       AttrPtr->name, AttrPtr->s, AttrPtr->shown, */
- /*       AttrPtr->nameshown, AttrPtr->inherited); */
     fprintf (FP, "attr(\"");
     SaveString (FP, AttrPtr->name);
--- 367,370 ----
***************
*** 542,547 ****
  
  static
! int ShowAndUpdAttrNames ()
!    /* returns TRUE if any attribute names are updated */
     /* This routine concatinate the 'name' and 's' first of every        */
     /*    attribute of the selected object and assign that to the        */
--- 460,468 ----
  
  static
! int ShowAndUpdAttrNames (Force)
!    int	Force;
!    /* Force will force attribute name to be shown whether the attribute */
!    /*    is inherited or not.                                           */
!    /* returns TRUE if any attribute names are updated                   */
     /* This routine concatinate the 'name' and 's' first of every        */
     /*    attribute of the selected object and assign that to the        */
***************
*** 551,555 ****
     struct ObjRec	* obj_ptr;
     struct AttrRec	* attr_ptr;
!    int			has_attr, picture_changed = FALSE, obj_changed;
     int			len1, len2;
     char			* s, msg[80];
--- 472,476 ----
     struct ObjRec	* obj_ptr;
     struct AttrRec	* attr_ptr;
!    int			picture_changed = FALSE, obj_changed;
     int			len1, len2;
     char			* s, msg[80];
***************
*** 558,576 ****
     {
        obj_ptr = sel_ptr->obj;
!       has_attr = TRUE;
!       switch (obj_ptr->type)
        {
-          case OBJ_POLY: attr_ptr = obj_ptr->detail.p->fattr; break;
-          case OBJ_GROUP:
-          case OBJ_SYM:
-          case OBJ_ICON: attr_ptr = obj_ptr->detail.r->fattr; break;
-          default: has_attr = FALSE;
-       }
-       if (has_attr && attr_ptr != NULL)
-       {
           obj_changed = FALSE;
           for ( ; attr_ptr != NULL; attr_ptr = attr_ptr->next)
           {
!             if (!(attr_ptr->nameshown))
              {
                 s = attr_ptr->obj->detail.t->first->s;
--- 479,489 ----
     {
        obj_ptr = sel_ptr->obj;
!       attr_ptr = obj_ptr->fattr;
!       if (attr_ptr != NULL)
        {
           obj_changed = FALSE;
           for ( ; attr_ptr != NULL; attr_ptr = attr_ptr->next)
           {
!             if (!(attr_ptr->nameshown) && (Force || !(attr_ptr->inherited)))
              {
                 s = attr_ptr->obj->detail.t->first->s;
***************
*** 601,605 ****
  void ShowAllAttrNames ()
  {
!    if (ShowAndUpdAttrNames ())
     {
        HighLightReverse ();
--- 514,518 ----
  void ShowAllAttrNames ()
  {
!    if (ShowAndUpdAttrNames (TRUE))
     {
        HighLightReverse ();
***************
*** 621,625 ****
     struct ObjRec	* obj_ptr;
     struct AttrRec	* attr_ptr;
!    int			has_attr, picture_changed = FALSE, obj_changed;
     char			* s;
  
--- 534,538 ----
     struct ObjRec	* obj_ptr;
     struct AttrRec	* attr_ptr;
!    int			picture_changed = FALSE, obj_changed;
     char			* s;
  
***************
*** 627,649 ****
     {
        obj_ptr = sel_ptr->obj;
!       has_attr = TRUE;
!       switch (obj_ptr->type)
        {
-          case OBJ_POLY: attr_ptr = obj_ptr->detail.p->fattr; break;
-          case OBJ_GROUP:
-          case OBJ_SYM:
-          case OBJ_ICON: attr_ptr = obj_ptr->detail.r->fattr; break;
-          default: has_attr = FALSE;
-       }
-       if (has_attr && attr_ptr != NULL)
-       {
           obj_changed = FALSE;
           for ( ; attr_ptr != NULL; attr_ptr = attr_ptr->next)
           {
!             if (attr_ptr->nameshown)
              {
                 s = attr_ptr->obj->detail.t->first->s;
                 strcpy (s, attr_ptr->s);
-                attr_ptr->nameshown = FALSE;
                 UpdTextBBox (attr_ptr->obj);
                 if (attr_ptr->shown) obj_changed = picture_changed = TRUE;
--- 540,554 ----
     {
        obj_ptr = sel_ptr->obj;
!       attr_ptr = obj_ptr->fattr;
!       if (attr_ptr != NULL)
        {
           obj_changed = FALSE;
           for ( ; attr_ptr != NULL; attr_ptr = attr_ptr->next)
           {
!             if (attr_ptr->nameshown && *(attr_ptr->name) != '\0')
              {
+                attr_ptr->nameshown = FALSE;
                 s = attr_ptr->obj->detail.t->first->s;
                 strcpy (s, attr_ptr->s);
                 UpdTextBBox (attr_ptr->obj);
                 if (attr_ptr->shown) obj_changed = picture_changed = TRUE;
***************
*** 677,681 ****
     struct SelRec	* * TopSelPtr, * * BotSelPtr;
  {
!    struct AttrRec	* attr_ptr = ObjPtr->detail.r->fattr;
     struct SelRec	* new_sel_ptr;
     int			len1, len2;
--- 582,586 ----
     struct SelRec	* * TopSelPtr, * * BotSelPtr;
  {
!    struct AttrRec	* attr_ptr = ObjPtr->fattr;
     struct SelRec	* new_sel_ptr;
     int			len1, len2;
***************
*** 735,743 ****
     struct ObjRec	* obj_ptr;
     struct AttrRec	* attr_ptr, * attr_ptr_next;
!    int			has_attr, picture_changed, obj_changed;
     char			* s;
  
     HighLightReverse ();
!    picture_changed = ShowAndUpdAttrNames ();
  
     for (sel_ptr = topSel; sel_ptr != NULL; sel_ptr = sel_ptr->next)
--- 640,648 ----
     struct ObjRec	* obj_ptr;
     struct AttrRec	* attr_ptr, * attr_ptr_next;
!    int			picture_changed, obj_changed;
     char			* s;
  
     HighLightReverse ();
!    picture_changed = ShowAndUpdAttrNames (FALSE);
  
     for (sel_ptr = topSel; sel_ptr != NULL; sel_ptr = sel_ptr->next)
***************
*** 744,758 ****
     {
        obj_ptr = sel_ptr->obj;
!       has_attr = TRUE;
!       switch (obj_ptr->type)
        {
-          case OBJ_POLY: attr_ptr = obj_ptr->detail.p->fattr; break;
-          case OBJ_GROUP:
-          case OBJ_SYM:
-          case OBJ_ICON: attr_ptr = obj_ptr->detail.r->fattr; break;
-          default: has_attr = FALSE;
-       }
-       if (has_attr && attr_ptr != NULL)
-       {
           topAttr = botAttr = NULL;
           for ( ; attr_ptr != NULL; attr_ptr = attr_ptr_next)
--- 649,655 ----
     {
        obj_ptr = sel_ptr->obj;
!       attr_ptr = obj_ptr->fattr;
!       if (attr_ptr != NULL)
        {
           topAttr = botAttr = NULL;
           for ( ; attr_ptr != NULL; attr_ptr = attr_ptr_next)
***************
*** 773,789 ****
              cfree (attr_ptr);
           }
!          switch (obj_ptr->type)
!          {
!             case OBJ_POLY:
!                obj_ptr->detail.p->fattr = topAttr;
!                obj_ptr->detail.p->lattr = botAttr;
!                break;
!             case OBJ_GROUP:
!             case OBJ_SYM:
!             case OBJ_ICON:
!                obj_ptr->detail.r->fattr = topAttr;
!                obj_ptr->detail.r->lattr = botAttr;
!                break;
!          }
           AdjObjBBox (obj_ptr);
        }
--- 670,675 ----
              cfree (attr_ptr);
           }
!          obj_ptr->fattr = topAttr;
!          obj_ptr->lattr = botAttr;
           AdjObjBBox (obj_ptr);
        }
***************
*** 906,910 ****
                 break;
              case Button2:
!                AttrPtr->nameshown = !AttrPtr->nameshown;
                 UpdAttr (AttrPtr);
                 if (AttrPtr->shown)
--- 792,797 ----
                 break;
              case Button2:
!                if (!(AttrPtr->nameshown) || *(AttrPtr->name) != '\0')
!                   AttrPtr->nameshown = !AttrPtr->nameshown;
                 UpdAttr (AttrPtr);
                 if (AttrPtr->shown)
***************
*** 1012,1016 ****
     struct ObjRec	* obj_ptr;
     struct AttrRec	* attr_ptr, * attr_ptr1;
!    int			has_attr = TRUE, num_attrs = 0, i, index, x, y;
     int			picture_changed, sel_ltx, sel_lty, sel_rbx, sel_rby;
     int			* fore_colors, * pixel_ptr, * valid, * flag_ptr;
--- 899,903 ----
     struct ObjRec	* obj_ptr;
     struct AttrRec	* attr_ptr, * attr_ptr1;
!    int			num_attrs = 0, i, index, x, y;
     int			picture_changed, sel_ltx, sel_lty, sel_rbx, sel_rby;
     int			* fore_colors, * pixel_ptr, * valid, * flag_ptr;
***************
*** 1023,1037 ****
  
     obj_ptr = topSel->obj;
!    has_attr = TRUE;
!    switch (obj_ptr->type)
!    {
!       case OBJ_POLY: attr_ptr1 = attr_ptr = obj_ptr->detail.p->fattr; break;
!       case OBJ_GROUP:
!       case OBJ_SYM:
!       case OBJ_ICON: attr_ptr1 = attr_ptr = obj_ptr->detail.r->fattr; break;
!       default: has_attr = FALSE;
!    }
!    if (!has_attr)
!    { Msg ("Please select one poly, group, symbol, or icon object."); return; }
  
     for ( ; attr_ptr1 != NULL; attr_ptr1 = attr_ptr1->next, num_attrs++) ;
--- 910,914 ----
  
     obj_ptr = topSel->obj;
!    attr_ptr1 = attr_ptr = obj_ptr->fattr;
  
     for ( ; attr_ptr1 != NULL; attr_ptr1 = attr_ptr1->next, num_attrs++) ;
*** box.c.orig	Fri Aug 17 13:45:37 1990
--- box.c	Fri Aug 17 13:45:38 1990
***************
*** 6,10 ****
  #ifndef lint
  static char RCSid[] =
!       "@(#)$Header: /n/kona/u/tangram/u/william/X11/TGIF/RCS/box.c,v 1.5 90/07/16 10:29:15 william Exp $";
  #endif
  
--- 6,10 ----
  #ifndef lint
  static char RCSid[] =
!       "@(#)$Header: /n/kona/u/tangram/u/william/X11/TGIF/RCS/box.c,v 1.7 90/08/13 09:23:32 william Exp $";
  #endif
  
***************
*** 247,251 ****
--- 247,254 ----
     obj_ptr->type = OBJ_BOX;
     obj_ptr->color = colorIndex;
+    obj_ptr->id = objId++;
+    obj_ptr->dirty = FALSE;
     obj_ptr->detail.b = box_ptr;
+    obj_ptr->fattr = obj_ptr->lattr = NULL;
     AddObj (NULL, topObj, obj_ptr);
  }
***************
*** 339,345 ****
  {
     fprintf (FP, "box(%s,", colorMenuItems[ObjPtr->color]);
!    fprintf (FP, "%1d,%1d,%1d,%1d,%1d,%1d,%1d)", ObjPtr->obbox.ltx,
           ObjPtr->obbox.lty, ObjPtr->obbox.rbx, ObjPtr->obbox.rby,
!          ObjPtr->detail.b->fill, ObjPtr->detail.b->width, ObjPtr->detail.b->pen);
  }
  
--- 342,351 ----
  {
     fprintf (FP, "box(%s,", colorMenuItems[ObjPtr->color]);
!    fprintf (FP, "%1d,%1d,%1d,%1d,%1d,%1d,%1d,%1d,", ObjPtr->obbox.ltx,
           ObjPtr->obbox.lty, ObjPtr->obbox.rbx, ObjPtr->obbox.rby,
!          ObjPtr->detail.b->fill, ObjPtr->detail.b->width,
!          ObjPtr->detail.b->pen, ObjPtr->id);
!    SaveAttrs (FP, ObjPtr->lattr);
!    fprintf (FP, ")");
  }
  
***************
*** 366,373 ****
           case 2: width = 6; break;
        }
     }
!    else
        sscanf (s, "%d , %d , %d , %d , %d , %d , %d",
              &ltx, &lty, &rbx, &rby, &fill, &width, &pen);
  
     box_ptr->fill = fill;
--- 372,389 ----
           case 2: width = 6; break;
        }
+       (*ObjPtr)->id = objId++;
     }
!    else if (fileVersion <= 7)
!    {
        sscanf (s, "%d , %d , %d , %d , %d , %d , %d",
              &ltx, &lty, &rbx, &rby, &fill, &width, &pen);
+       (*ObjPtr)->id = objId++;
+    }
+    else
+    {
+       sscanf (s, "%d , %d , %d , %d , %d , %d , %d , %d",
+             &ltx, &lty, &rbx, &rby, &fill, &width, &pen, &((*ObjPtr)->id));
+       if ((*ObjPtr)->id >= objId) objId = (*ObjPtr)->id + 1;
+    }
  
     box_ptr->fill = fill;
***************
*** 377,380 ****
--- 393,397 ----
     (*ObjPtr)->y = lty;
     (*ObjPtr)->color = FindColorIndex (color_str);
+    (*ObjPtr)->dirty = FALSE;
     (*ObjPtr)->type = OBJ_BOX;
     (*ObjPtr)->obbox.ltx = ltx;
*** choice.c.orig	Fri Aug 17 13:45:45 1990
--- choice.c	Fri Aug 17 13:45:46 1990
***************
*** 6,10 ****
  #ifndef lint
  static char RCSid[] =
!       "@(#)$Header: /n/kona/u/tangram/u/william/X11/TGIF/RCS/choice.c,v 1.5 90/06/26 15:22:27 william Exp $";
  #endif
  
--- 6,10 ----
  #ifndef lint
  static char RCSid[] =
!       "@(#)$Header: /n/kona/u/tangram/u/william/X11/TGIF/RCS/choice.c,v 1.6 90/08/15 16:01:40 william Exp $";
  #endif
  
*** copypaste.c.orig	Fri Aug 17 13:45:49 1990
--- copypaste.c	Fri Aug 17 13:45:51 1990
***************
*** 0 ****
--- 1,298 ----
+ /*
+  * Author:	Kou1 Ma2da (matsuda@ccs.mt.nec.co.jp)
+  * Modified By:	William Chia-Wei Cheng (william@cs.ucla.edu)
+  *
+  * Copyright (C) 1990, William Cheng.
+  */
+ #ifndef lint
+ static char RCSid[] =
+       "@(#)$Header: /n/kona/u/tangram/u/william/X11/TGIF/RCS/copypaste.c,v 1.7 90/08/16 13:32:44 william Exp $";
+ #endif
+ 
+ #include <sys/types.h>
+ #include <sys/stat.h>
+ #include <stdio.h>
+ #include <X11/Xlib.h>
+ #include "const.h"
+ #include "types.h"
+ 
+ #include "choice.e"
+ #include "color.e"
+ #include "dup.e"
+ #include "file.e"
+ #include "font.e"
+ #include "obj.e"
+ #include "pattern.e"
+ #include "select.e"
+ #include "setup.e"
+ #include "special.e"
+ #include "text.e"
+ 
+ #define TGIF_HEADER 0x80
+ 
+ extern char * mktemp();
+ 
+ static char * cutBuffer = NULL;
+ 
+ void CopyToCutBuffer ()
+ {
+    FILE				* fp;
+    register struct SelRec 	* sel_ptr;
+    struct ObjRec		* obj_ptr, * top_obj, * bot_obj;
+    char 			* tmpfile, message[MAXSTRING];
+    struct stat 			stat;
+    unsigned char 		header = TGIF_HEADER;
+    int level;
+     
+    if (topSel == NULL)
+    {
+       Msg ("No object selected for the COPY operation.");
+       return;
+    }
+    tmpfile = mktemp ("/tmp/TgifXXXXXX");
+    if ((fp = fopen (tmpfile, "w+")) == NULL)
+    {
+       sprintf (message, "Can not open %s.", tmpfile);
+       Msg (message);
+       return;
+    }
+ 
+    write (fileno(fp), &header, 1);
+ 
+    top_obj = bot_obj = NULL;
+    for (sel_ptr = botSel; sel_ptr != NULL; sel_ptr = sel_ptr->prev)
+    {
+       obj_ptr = DupObj (sel_ptr->obj);
+ 
+       obj_ptr->prev = NULL;
+       obj_ptr->next = top_obj;
+ 
+       if (top_obj == NULL)
+          bot_obj = obj_ptr;
+       else
+          top_obj->prev = obj_ptr;
+       top_obj = obj_ptr;
+    }
+    Save (fp, bot_obj, 0);
+ 
+    fflush (fp);
+    if (fstat (fileno(fp), &stat) < 0)
+    {
+       fclose (fp);
+       unlink (tmpfile);
+       sprintf (message, "FSTAT error in %s.  Copy aborted!", tmpfile);
+       Msg (message);
+       return;
+    }
+ 
+    if (cutBuffer != NULL) cfree (cutBuffer);
+    cutBuffer = (char *) calloc (stat.st_size, sizeof(char));
+ 
+    if (rewind (fp) < 0)
+    {
+       sprintf (message, "Error in rewinding %s.  Copy aborted!", tmpfile);
+       Msg (message);
+    }
+    else if (read (fileno(fp), cutBuffer, stat.st_size) < stat.st_size)
+    {
+       sprintf (message, "READ error in %s.  Copy aborted!", tmpfile);
+       Msg (message);
+    }
+    else
+    {
+       XStoreBytes (mainDisplay, cutBuffer, stat.st_size);
+       Msg ("Copy buffer updated.");
+    }
+    fclose (fp);
+    unlink (tmpfile);
+ }
+ 
+ static
+ void PasteString (CutBuffer)
+    char	* CutBuffer;
+ {
+    register char	* c_ptr, * dest_c_ptr;
+    int			x, y, w, num_lines, char_count, max_len = 0;
+    int			root_x, root_y, grid_x, grid_y;
+    unsigned int		status;
+    char			line[MAXSTRING], msg[MAXSTRING];
+    struct StrRec	* first_str, * last_str, *str_ptr;
+    struct ObjRec	* obj_ptr;
+    struct TextRec	* text_ptr;
+    Window		root_win, child_win;
+ 
+    if (*CutBuffer == '\0') { Msg ("Cut buffer is empty"); return; }
+ 
+    TieLooseEnds ();
+    SetCurChoice (NOTHING);
+    if (topSel != NULL) { HighLightReverse (); RemoveAllSel (); }
+ 
+    Msg ("Paste from a non-tgif tool.");
+ 
+    XQueryPointer (mainDisplay, drawWindow, &root_win, &child_win,
+          &root_x, &root_y, &x, &y, &status);
+    GridXY (x, y, &grid_x, &grid_y);
+ 
+    text_ptr = (struct TextRec *) calloc (1, sizeof(struct TextRec));
+    text_ptr->font = curFont;
+    text_ptr->dpi = curFontDPI;
+    text_ptr->style = curStyle;
+    text_ptr->attr = NULL;
+    text_ptr->size = curSize;
+    text_ptr->just = textJust;
+    text_ptr->rotate = curRotate;
+    text_ptr->pen = penPat;
+ 
+    first_str = last_str = NULL;
+    for (c_ptr = CutBuffer, num_lines = 0; *c_ptr != '\0'; num_lines++)
+    {
+       str_ptr = (struct StrRec *) calloc (1, sizeof(struct StrRec));
+ 
+       char_count = 0;
+       dest_c_ptr = str_ptr->s;
+       while (*c_ptr != '\0' && *c_ptr != '\n' && *c_ptr != '\r')
+       {
+          *dest_c_ptr++ = *c_ptr++;
+          if (++char_count == MAXSTRING)
+          {
+             sprintf (msg, "String length exceeds $1d.  String truncated.",
+                   MAXSTRING);
+             Msg (msg);
+             while (*c_ptr != '\0' && *c_ptr != '\n' && *c_ptr != '\r') c_ptr++;
+             break;
+          }
+       }
+       *dest_c_ptr = '\0';
+ 
+       str_ptr->prev = last_str;
+       str_ptr->next = NULL;
+       if (last_str == NULL)
+          first_str = str_ptr;
+       else
+          last_str->next = str_ptr;
+       last_str = str_ptr;
+ 
+       w = XTextWidth (canvasFontPtr, str_ptr->s, strlen (str_ptr->s));
+       if (w > max_len) max_len = w;
+ 
+       if (*c_ptr == '\n' || *c_ptr == '\r') c_ptr++;
+    }
+ 
+    text_ptr->lines = num_lines;
+    text_ptr->first = first_str;
+    text_ptr->last = last_str;
+ 
+    obj_ptr = (struct ObjRec *) calloc (1, sizeof(struct ObjRec));
+    obj_ptr->x = grid_x;
+    obj_ptr->y = grid_y;
+    obj_ptr->type = OBJ_TEXT;
+    obj_ptr->color = colorIndex;
+    obj_ptr->id = objId++;;
+    obj_ptr->dirty = FALSE;
+    obj_ptr->detail.t = text_ptr;
+    obj_ptr->fattr = obj_ptr->lattr = NULL;
+ 
+    SetTextBBox (obj_ptr, textJust, max_len, num_lines*textCursorH, curRotate);
+ 
+    AddObj (NULL, topObj, obj_ptr);
+    AdjObjBBox (obj_ptr);
+    PlaceTopObj ();
+    if (topObj != NULL) SelectTopObj ();
+    SetFileModified (TRUE);
+    justDupped = FALSE;
+ }
+ 
+ void PasteFromCutBuffer ()
+ {
+    FILE 		* fp;
+    int 			len;
+    register char 	* d;
+    char 		* tmpfile, * cut_buffer, message[MAXSTRING];
+    unsigned char 	header = TGIF_HEADER;
+    struct ObjRec	* obj_ptr, * saved_top_obj, * saved_bot_obj;
+ 
+    cut_buffer = (char *) XFetchBytes (mainDisplay, &len);
+    if (len == 0)
+    {
+       Msg ("Cut buffer is empty");
+       return;
+    }
+    if (((unsigned char)(*cut_buffer)) != header)
+    {
+       PasteString (cut_buffer);
+       return;
+    }
+ #ifdef KANJI
+       myPasteKanji (cut_buffer, len);
+ #endif
+    cut_buffer++;
+    len--;
+ 
+    tmpfile = mktemp ("/tmp/TgifXXXXXX");
+    if ((fp = fopen (tmpfile, "w+")) == NULL)
+    {
+       sprintf (message, "Can not open %s for write.", tmpfile);
+       Msg (message);
+       return;
+    }
+    if (write (fileno(fp), cut_buffer, len) < len)
+    {
+       fclose (fp);
+       unlink (tmpfile);
+       sprintf (message, "FWRITE error in writing to %s.  Paste aborted!",
+             tmpfile);
+       Msg (message);
+       return;
+    }
+    fflush (fp);
+    if (rewind (fp) < 0)
+    {
+       fclose (fp);
+       unlink (tmpfile);
+       sprintf (message, "Error in rewinding %s.  Paste aborted!", tmpfile);
+       Msg (message);
+       return;
+    }
+ 
+    TieLooseEnds ();
+    SetCurChoice (NOTHING);
+ 
+    saved_top_obj = topObj;
+    saved_bot_obj = botObj;
+    topObj = botObj = NULL;
+     
+    importingFile = TRUE;
+    while (ReadObj (fp, &obj_ptr, FALSE))
+       if (obj_ptr != NULL)
+          AddObj (NULL, topObj, obj_ptr);
+     
+    fclose (fp);
+    importingFile = FALSE;
+    if (topObj != NULL) SetFileModified (TRUE);
+     
+    RedrawDrawWindow (botObj);
+    SelAllObj ();
+     
+    if (botObj != NULL)
+       botObj->next = saved_top_obj;
+    else
+       topObj = saved_top_obj;
+ 
+    if (saved_top_obj != NULL)
+    {
+       saved_top_obj->prev = botObj;
+       botObj = saved_bot_obj;
+    }
+    unlink (tmpfile);
+    Msg ("Objects pasted from tgif.");
+ }        
+ 
+ void CleanUpCutBuffer ()
+ {
+    if (cutBuffer != NULL)
+    {
+       *cutBuffer = '\0';
+       cfree (cutBuffer);
+       cutBuffer = NULL;
+    }
+ }
*** drawing.c.orig	Fri Aug 17 13:46:02 1990
--- drawing.c	Fri Aug 17 13:46:04 1990
***************
*** 6,10 ****
  #ifndef lint
  static char RCSid[] =
!       "@(#)$Header: /n/kona/u/tangram/u/william/X11/TGIF/RCS/drawing.c,v 1.8 90/07/29 15:34:38 william Exp $";
  #endif
  
--- 6,10 ----
  #ifndef lint
  static char RCSid[] =
!       "@(#)$Header: /n/kona/u/tangram/u/william/X11/TGIF/RCS/drawing.c,v 1.11 90/08/16 09:34:54 william Exp $";
  #endif
  
***************
*** 19,22 ****
--- 19,23 ----
  #include "box.e"
  #include "choice.e"
+ #include "copypaste.e"
  #include "cursor.e"
  #include "dialog.e"
***************
*** 143,152 ****
        case OBJ_POLY:
           DrawPolyObj (Win, drawOrigX, drawOrigY, ObjPtr); 
!          DrawAttrs(Win, drawOrigX, drawOrigY, ObjPtr->detail.p->fattr);
           break;
!       case OBJ_BOX: DrawBoxObj (Win, drawOrigX, drawOrigY, ObjPtr); break;
!       case OBJ_OVAL: DrawOvalObj (Win, drawOrigX, drawOrigY, ObjPtr); break;
        case OBJ_TEXT: DrawTextObj (Win, drawOrigX, drawOrigY, ObjPtr); break;
!       case OBJ_POLYGON: DrawPolygonObj (Win, drawOrigX, drawOrigY, ObjPtr);
           break;
  
--- 144,161 ----
        case OBJ_POLY:
           DrawPolyObj (Win, drawOrigX, drawOrigY, ObjPtr); 
!          DrawAttrs(Win, drawOrigX, drawOrigY, ObjPtr->fattr);
           break;
!       case OBJ_BOX:
!          DrawBoxObj (Win, drawOrigX, drawOrigY, ObjPtr);
!          DrawAttrs(Win, drawOrigX, drawOrigY, ObjPtr->fattr);
!          break;
!       case OBJ_OVAL:
!          DrawOvalObj (Win, drawOrigX, drawOrigY, ObjPtr);
!          DrawAttrs(Win, drawOrigX, drawOrigY, ObjPtr->fattr);
!          break;
        case OBJ_TEXT: DrawTextObj (Win, drawOrigX, drawOrigY, ObjPtr); break;
!       case OBJ_POLYGON:
!          DrawPolygonObj (Win, drawOrigX, drawOrigY, ObjPtr);
!          DrawAttrs(Win, drawOrigX, drawOrigY, ObjPtr->fattr);
           break;
  
***************
*** 158,164 ****
              if (BBoxIntersect (obj_ptr->bbox, drawWinBBox))
                 DrawObj (Win, obj_ptr);
!          if (ObjPtr->type == OBJ_ICON && ObjPtr->detail.r->dirty)
           {
!             attr_ptr = ObjPtr->detail.r->fattr;
              for ( ; attr_ptr != NULL; attr_ptr = attr_ptr->next)
                 UpdTextBBox (attr_ptr->obj);
--- 167,173 ----
              if (BBoxIntersect (obj_ptr->bbox, drawWinBBox))
                 DrawObj (Win, obj_ptr);
!          if (ObjPtr->type == OBJ_ICON && ObjPtr->dirty)
           {
!             attr_ptr = ObjPtr->fattr;
              for ( ; attr_ptr != NULL; attr_ptr = attr_ptr->next)
                 UpdTextBBox (attr_ptr->obj);
***************
*** 165,171 ****
              AdjObjBBox (ObjPtr);
              UpdSelBBox ();
!             ObjPtr->detail.r->dirty = FALSE;
           }
!          DrawAttrs(Win, drawOrigX, drawOrigY, ObjPtr->detail.r->fattr);
           if (ObjPtr->type == OBJ_SYM) DrawSymOutline (Win, drawOrigX, drawOrigY,
                 ObjPtr);
--- 174,180 ----
              AdjObjBBox (ObjPtr);
              UpdSelBBox ();
!             ObjPtr->dirty = FALSE;
           }
!          DrawAttrs(Win, drawOrigX, drawOrigY, ObjPtr->fattr);
           if (ObjPtr->type == OBJ_SYM) DrawSymOutline (Win, drawOrigX, drawOrigY,
                 ObjPtr);
***************
*** 480,484 ****
              case '\027': /*^W*/ SetCurChoice (DRAWTEXT); break;
              case '\030': /*^X*/ DelAllSelObj (); break;
!             case '\031': /*^Y*/ break;
              case '\032': /*^Z*/ return (AnimateProc ()); break;
              case ',': /*^,*/ ScrollLeft (); break;
--- 489,493 ----
              case '\027': /*^W*/ SetCurChoice (DRAWTEXT); break;
              case '\030': /*^X*/ DelAllSelObj (); break;
!             case '\031': /*^Y*/ CopyToCutBuffer (); break;
              case '\032': /*^Z*/ return (AnimateProc ()); break;
              case ',': /*^,*/ ScrollLeft (); break;
***************
*** 554,558 ****
              case '\027': /*^#W*/ ToggleAllSelLineType (); break;
              case '\030': /*^#X*/ break;
!             case '\031': /*^#Y*/ break;
              case '\032': /*^#Z*/ break;
           }
--- 563,567 ----
              case '\027': /*^#W*/ ToggleAllSelLineType (); break;
              case '\030': /*^#X*/ break;
!             case '\031': /*^#Y*/ PasteFromCutBuffer (); break;
              case '\032': /*^#Z*/ break;
           }
***************
*** 569,573 ****
  
     for ( ; obj_ptr != NULL; obj_ptr = obj_ptr->next)
!       if (obj_ptr->type == OBJ_ICON && obj_ptr->detail.r->dirty)
           return (TRUE);
     return (FALSE);
--- 578,582 ----
  
     for ( ; obj_ptr != NULL; obj_ptr = obj_ptr->next)
!       if (obj_ptr->type == OBJ_ICON && obj_ptr->dirty)
           return (TRUE);
     return (FALSE);
*** dup.c.orig	Fri Aug 17 13:46:11 1990
--- dup.c	Fri Aug 17 13:46:12 1990
***************
*** 6,10 ****
  #ifndef lint
  static char RCSid[] =
!       "@(#)$Header: /n/kona/u/tangram/u/william/X11/TGIF/RCS/dup.c,v 1.3 90/07/08 00:29:43 william Exp $";
  #endif
  
--- 6,10 ----
  #ifndef lint
  static char RCSid[] =
!       "@(#)$Header: /n/kona/u/tangram/u/william/X11/TGIF/RCS/dup.c,v 1.6 90/08/16 09:35:11 william Exp $";
  #endif
  
***************
*** 20,23 ****
--- 20,25 ----
  #include "setup.e"
  
+ extern struct ObjRec	* DupObj ();
+ 
  int	justDupped = FALSE;
  int	dupDx = INVALID, dupDy = INVALID;
***************
*** 29,32 ****
--- 31,36 ----
     ToObjPtr->y = FromObjPtr->y;
     ToObjPtr->color = FromObjPtr->color;
+    ToObjPtr->id = objId++;
+    ToObjPtr->dirty = FALSE;
     ToObjPtr->type = FromObjPtr->type;
     ToObjPtr->bbox.ltx = FromObjPtr->bbox.ltx;
***************
*** 62,66 ****
     poly_ptr->pen = PolyPtr->pen;
     poly_ptr->fill = PolyPtr->fill;
-    poly_ptr->id = objId++;
     if ((poly_ptr->curved = PolyPtr->curved) == LT_SPLINE)
     {
--- 66,69 ----
***************
*** 173,176 ****
--- 176,180 ----
  
     text_ptr->font = TextPtr->font;
+    text_ptr->dpi = TextPtr->dpi;
     text_ptr->style = TextPtr->style;
     text_ptr->size = TextPtr->size;
***************
*** 190,194 ****
     struct ObjRec		* top_obj, * bot_obj;
     struct ObjRec		* from_obj_ptr, * to_obj_ptr;
-    static struct ObjRec		* DupObj ();
  
     group_ptr = (struct GroupRec *) calloc (1, sizeof(struct GroupRec));
--- 194,197 ----
***************
*** 211,215 ****
  }
  
- static
  struct ObjRec * DupObj (ObjPtr)
     struct ObjRec	* ObjPtr;
--- 214,217 ----
***************
*** 226,233 ****
           DupAttrs (ObjPtr, obj_ptr);
           break;
!       case OBJ_BOX: DupBoxObj (ObjPtr->detail.b, obj_ptr); break;
!       case OBJ_OVAL: DupOvalObj (ObjPtr->detail.o, obj_ptr); break;
        case OBJ_TEXT: DupTextObj (ObjPtr->detail.t, obj_ptr); break;
!       case OBJ_POLYGON: DupPolygonObj (ObjPtr->detail.g, obj_ptr); break;
        case OBJ_SYM:
        case OBJ_GROUP:
--- 228,244 ----
           DupAttrs (ObjPtr, obj_ptr);
           break;
!       case OBJ_BOX:
!          DupBoxObj (ObjPtr->detail.b, obj_ptr);
!          DupAttrs (ObjPtr, obj_ptr);
!          break;
!       case OBJ_OVAL:
!          DupOvalObj (ObjPtr->detail.o, obj_ptr);
!          DupAttrs (ObjPtr, obj_ptr);
!          break;
        case OBJ_TEXT: DupTextObj (ObjPtr->detail.t, obj_ptr); break;
!       case OBJ_POLYGON:
!          DupPolygonObj (ObjPtr->detail.g, obj_ptr);
!          DupAttrs (ObjPtr, obj_ptr);
!          break;
        case OBJ_SYM:
        case OBJ_GROUP:
***************
*** 234,242 ****
        case OBJ_ICON:
           DupGroupObj (ObjPtr->detail.r, obj_ptr);
-          if (ObjPtr->type == OBJ_ICON)
-          {
-             obj_ptr->detail.r->id = objId++;
-             obj_ptr->detail.r->dirty = FALSE;
-          }
           DupAttrs (ObjPtr, obj_ptr);
           if (obj_ptr->type == OBJ_ICON)
--- 245,248 ----
*** edit.c.orig	Fri Aug 17 13:46:32 1990
--- edit.c	Fri Aug 17 13:46:34 1990
***************
*** 6,10 ****
  #ifndef lint
  static char RCSid[] =
!       "@(#)$Header: /n/kona/u/tangram/u/william/X11/TGIF/RCS/edit.c,v 1.6 90/07/13 12:51:58 william Exp $";
  #endif
  
--- 6,10 ----
  #ifndef lint
  static char RCSid[] =
!       "@(#)$Header: /n/kona/u/tangram/u/william/X11/TGIF/RCS/edit.c,v 1.9 90/08/16 09:35:06 william Exp $";
  #endif
  
***************
*** 17,20 ****
--- 17,21 ----
  #include "align.e"
  #include "color.e"
+ #include "copypaste.e"
  #include "cursor.e"
  #include "drawing.e"
***************
*** 45,50 ****
  #define EDIT_DEL_POINT 5
  #define EDIT_ADD_POINT 6
  
! #define MAXEDITMENUS 7
  
  static char * editMenuStr[] =
--- 46,53 ----
  #define EDIT_DEL_POINT 5
  #define EDIT_ADD_POINT 6
+ #define EDIT_COPY 7
+ #define EDIT_PASTE 8
  
! #define MAXEDITMENUS 9
  
  static char * editMenuStr[] =
***************
*** 55,59 ****
          "UndoDelete   #U",
          "DeletePoint ^#D",
!         "AddPoint    ^#A"
        };
  
--- 58,64 ----
          "UndoDelete   #U",
          "DeletePoint ^#D",
!         "AddPoint    ^#A",
!         "Copy         ^Y",
!         "Paste       ^#Y"
        };
  
***************
*** 91,94 ****
--- 96,100 ----
     XQueryPointer (mainDisplay, drawWindow, &root_win, &child_win,
           &root_x, &root_y, &old_x, &old_y, &status);
+    XSetFont (mainDisplay, revDefaultGC, defaultFontPtr->fid);
     XDrawString (mainDisplay, drawWindow, revDefaultGC,
           old_x+4, old_y+defaultFontAsc, "DEL", 3);
***************
*** 613,616 ****
--- 619,623 ----
     XQueryPointer (mainDisplay, drawWindow, &root_win, &child_win,
           &root_x, &root_y, &old_x, &old_y, &status);
+    XSetFont (mainDisplay, revDefaultGC, defaultFontPtr->fid);
     XDrawString (mainDisplay, drawWindow, revDefaultGC,
           old_x+4, old_y+defaultFontAsc, "ADD", 3);
***************
*** 679,682 ****
--- 686,691 ----
        case EDIT_DEL_POINT: DeletePoint (); break;
        case EDIT_ADD_POINT: AddPoint (); break;
+       case EDIT_COPY: CopyToCutBuffer (); break;
+       case EDIT_PASTE: PasteFromCutBuffer (); break;
     }
  }
*** file.c.orig	Fri Aug 17 13:47:13 1990
--- file.c	Fri Aug 17 13:47:14 1990
***************
*** 6,10 ****
  #ifndef lint
  static char RCSid[] =
!       "@(#)$Header: /n/kona/u/tangram/u/william/X11/TGIF/RCS/file.c,v 1.28 90/07/30 16:08:30 william Exp $";
  #endif
  
--- 6,10 ----
  #ifndef lint
  static char RCSid[] =
!       "@(#)$Header: /n/kona/u/tangram/u/william/X11/TGIF/RCS/file.c,v 1.32 90/08/15 16:00:43 william Exp $";
  #endif
  
***************
*** 46,50 ****
  #include "text.e"
  
! #define CUR_VERSION 7
  
  char	curFileName[MAXPATHLENGTH];
--- 46,51 ----
  #include "text.e"
  
! #define CUR_VERSION 8
! #define START_HAVING_ATTRS 8
  
  char	curFileName[MAXPATHLENGTH];
***************
*** 102,107 ****
        fprintf (FP, "%1d,%1d,%1d,", horiAlign, vertAlign, lineWidth);
        fprintf (FP, "%1d,%1d,%1d,%1d,", curSpline, lineStyle, objFill, penPat);
!       fprintf (FP, "%1d,%1d,%1d,%1d", textJust, curFont, curStyle, curSize);
!       fprintf (FP, ").\n");
     }
  
--- 103,108 ----
        fprintf (FP, "%1d,%1d,%1d,", horiAlign, vertAlign, lineWidth);
        fprintf (FP, "%1d,%1d,%1d,%1d,", curSpline, lineStyle, objFill, penPat);
!       fprintf (FP, "%1d,%1d,%1d,%1d,", textJust, curFont, curStyle, curSize);
!       fprintf (FP, "%1d).\n", curFontDPI);
     }
  
***************
*** 374,378 ****
        sscanf (s, "%d", &fileVersion);
  
!    if (PRTGIF) return;
  
     if (!importingFile)
--- 375,383 ----
        sscanf (s, "%d", &fileVersion);
  
!    if (PRTGIF)
!    {
!       pageStyle = page_style;
!       return;
!    }
  
     if (!importingFile)
***************
*** 396,401 ****
              else
                 curSpline = LT_STRAIGHT;
           }
!          else
           {
              sscanf (s, "%d , %d , %d , %d , %d , %d , %d , %d , %d , \
--- 401,407 ----
              else
                 curSpline = LT_STRAIGHT;
+             curFontDPI = FONT_DPI_75;
           }
!          else if (fileVersion <= 7)
           {
              sscanf (s, "%d , %d , %d , %d , %d , %d , %d , %d , %d , \
***************
*** 405,409 ****
--- 411,425 ----
                    &lineStyle, &objFill, &penPat, &textJust, &curFont,
                    &curStyle, &curSize);
+             curFontDPI = FONT_DPI_75;
           }
+          else
+          {
+             sscanf (s, "%d , %d , %d , %d , %d , %d , %d , %d , %d , \
+                   %d , %d , %d , %d , %d , %d , %d , %d , %d",
+                   &drawOrigX, &drawOrigY, &zoomScale, &xyGrid, &gridOn,
+                   &colorIndex, &horiAlign, &vertAlign, &lineWidth, &curSpline,
+                   &lineStyle, &objFill, &penPat, &textJust, &curFont,
+                   &curStyle, &curSize, &curFontDPI);
+          }
           if (colorIndex >= maxColors)
           {
***************
*** 426,429 ****
--- 442,470 ----
  }
  
+ void ReadObjAttrs (MinFileVersion, FP, ObjPtr, PRTGIF)
+    FILE			* FP;
+    struct ObjRec	* * ObjPtr;
+    int			PRTGIF;
+ {
+    struct AttrRec	* top_attr = NULL, * bot_attr = NULL, * attr_ptr;
+ 
+    if (fileVersion <= MinFileVersion) return;
+ 
+    while (ReadAttr (FP, &attr_ptr, PRTGIF))
+    {
+       attr_ptr->owner = *ObjPtr;
+       attr_ptr->prev = NULL;
+       attr_ptr->next = top_attr;
+       if (top_attr == NULL)
+          bot_attr = attr_ptr;
+       else
+          top_attr->prev = attr_ptr;
+       top_attr = attr_ptr;
+    }
+    if (bot_attr != NULL) bot_attr->next = NULL;
+    (*ObjPtr)->fattr = top_attr;
+    (*ObjPtr)->lattr = bot_attr;
+ }
+ 
  int ReadObj (FP, ObjPtr, PRTGIF)
     FILE			* FP;
***************
*** 434,438 ****
     char			* line = NULL, * c_ptr, * s, * s1;
     int			len, id, cur_size, done = FALSE, allocated = FALSE;
-    struct AttrRec	* top_attr = NULL, * bot_attr = NULL, * attr_ptr;
  
     while (fgets (inbuf, MAXSTRING, FP) != NULL)
--- 475,478 ----
***************
*** 482,500 ****
        {
           ReadPolyObj (line, ObjPtr);
!          if (fileVersion != INVALID)
!             while (ReadAttr (FP, &attr_ptr, PRTGIF))
!             {
!                attr_ptr->owner = *ObjPtr;
!                attr_ptr->prev = NULL;
!                attr_ptr->next = top_attr;
!                if (top_attr == NULL)
!                   bot_attr = attr_ptr;
!                else
!                   top_attr->prev = attr_ptr;
!                top_attr = attr_ptr;
!             }
!          if (bot_attr != NULL) bot_attr->next = NULL;
!          (*ObjPtr)->detail.p->fattr = top_attr;
!          (*ObjPtr)->detail.p->lattr = bot_attr;
           AdjObjBBox (*ObjPtr);
           if (allocated) cfree (line);
--- 522,526 ----
        {
           ReadPolyObj (line, ObjPtr);
!          ReadObjAttrs (INVALID, FP, ObjPtr, PRTGIF);
           AdjObjBBox (*ObjPtr);
           if (allocated) cfree (line);
***************
*** 504,507 ****
--- 530,535 ----
        {
           ReadBoxObj (line, ObjPtr);
+          ReadObjAttrs (START_HAVING_ATTRS-1, FP, ObjPtr, PRTGIF);
+          AdjObjBBox (*ObjPtr);
           if (allocated) cfree (line);
           return (TRUE);
***************
*** 510,513 ****
--- 538,543 ----
        {
           ReadOvalObj (line, ObjPtr);
+          ReadObjAttrs (START_HAVING_ATTRS-1, FP, ObjPtr, PRTGIF);
+          AdjObjBBox (*ObjPtr);
           if (allocated) cfree (line);
           return (TRUE);
***************
*** 522,525 ****
--- 552,557 ----
        {
           ReadPolygonObj (line, ObjPtr);
+          ReadObjAttrs (START_HAVING_ATTRS-1, FP, ObjPtr, PRTGIF);
+          AdjObjBBox (*ObjPtr);
           if (allocated) cfree (line);
           return (TRUE);
***************
*** 528,546 ****
        {
           ReadGroupObj (FP, ObjPtr, PRTGIF);
!          if (fileVersion != INVALID)
!             while (ReadAttr (FP, &attr_ptr, PRTGIF))
!             {
!                attr_ptr->owner = *ObjPtr;
!                attr_ptr->prev = NULL;
!                attr_ptr->next = top_attr;
!                if (top_attr == NULL)
!                   bot_attr = attr_ptr;
!                else
!                   top_attr->prev = attr_ptr;
!                top_attr = attr_ptr;
!             }
!          if (bot_attr != NULL) bot_attr->next = NULL;
!          (*ObjPtr)->detail.r->fattr = top_attr;
!          (*ObjPtr)->detail.r->lattr = bot_attr;
           AdjObjBBox (*ObjPtr);
           if (allocated) cfree (line);
--- 560,564 ----
        {
           ReadGroupObj (FP, ObjPtr, PRTGIF);
!          ReadObjAttrs (INVALID, FP, ObjPtr, PRTGIF);
           AdjObjBBox (*ObjPtr);
           if (allocated) cfree (line);
***************
*** 551,569 ****
           ReadGroupObj (FP, ObjPtr, PRTGIF);
           (*ObjPtr)->type = OBJ_SYM;
!          if (fileVersion != INVALID)
!             while (ReadAttr (FP, &attr_ptr, PRTGIF))
!             {
!                attr_ptr->owner = *ObjPtr;
!                attr_ptr->prev = NULL;
!                attr_ptr->next = top_attr;
!                if (top_attr == NULL)
!                   bot_attr = attr_ptr;
!                else
!                   top_attr->prev = attr_ptr;
!                top_attr = attr_ptr;
!             }
!          if (bot_attr != NULL) bot_attr->next = NULL;
!          (*ObjPtr)->detail.r->fattr = top_attr;
!          (*ObjPtr)->detail.r->lattr = bot_attr;
           AdjObjBBox (*ObjPtr);
           if (allocated) cfree (line);
--- 569,573 ----
           ReadGroupObj (FP, ObjPtr, PRTGIF);
           (*ObjPtr)->type = OBJ_SYM;
!          ReadObjAttrs (INVALID, FP, ObjPtr, PRTGIF);
           AdjObjBBox (*ObjPtr);
           if (allocated) cfree (line);
***************
*** 587,610 ****
              sscanf (s1, "%d", &id);
              if (id >= objId) objId = id+1;
!             (*ObjPtr)->detail.r->id = id;
           }
!          (*ObjPtr)->detail.r->dirty = FALSE;
           *(--s) = '\0';
           strcpy ((*ObjPtr)->detail.r->s, tmp_str);
!          if (fileVersion != INVALID)
!             while (ReadAttr (FP, &attr_ptr, PRTGIF))
!             {
!                attr_ptr->owner = *ObjPtr;
!                attr_ptr->prev = NULL;
!                attr_ptr->next = top_attr;
!                if (top_attr == NULL)
!                   bot_attr = attr_ptr;
!                else
!                   top_attr->prev = attr_ptr;
!                top_attr = attr_ptr;
!             }
!          if (bot_attr != NULL) bot_attr->next = NULL;
!          (*ObjPtr)->detail.r->fattr = top_attr;
!          (*ObjPtr)->detail.r->lattr = bot_attr;
           AdjObjBBox (*ObjPtr);
           if (allocated) cfree (line);
--- 591,600 ----
              sscanf (s1, "%d", &id);
              if (id >= objId) objId = id+1;
!             (*ObjPtr)->id = id;
           }
!          (*ObjPtr)->dirty = FALSE;
           *(--s) = '\0';
           strcpy ((*ObjPtr)->detail.r->s, tmp_str);
!          ReadObjAttrs (INVALID, FP, ObjPtr, PRTGIF);
           AdjObjBBox (*ObjPtr);
           if (allocated) cfree (line);
***************
*** 820,829 ****
        case OBJ_POLY:
           DumpPolyObj (FP, ObjPtr);
!          DumpAttrs (FP, ObjPtr->detail.p->lattr, PRTGIF);
           break;
!       case OBJ_BOX: DumpBoxObj (FP, ObjPtr); break;
!       case OBJ_OVAL: DumpOvalObj (FP, ObjPtr); break;
        case OBJ_TEXT: DumpTextObj (FP, ObjPtr, PRTGIF); break;
!       case OBJ_POLYGON: DumpPolygonObj (FP, ObjPtr); break;
        case OBJ_SYM:
        case OBJ_ICON:
--- 810,828 ----
        case OBJ_POLY:
           DumpPolyObj (FP, ObjPtr);
!          DumpAttrs (FP, ObjPtr->lattr, PRTGIF);
           break;
!       case OBJ_BOX:
!          DumpBoxObj (FP, ObjPtr);
!          DumpAttrs (FP, ObjPtr->lattr, PRTGIF);
!          break;
!       case OBJ_OVAL:
!          DumpOvalObj (FP, ObjPtr);
!          DumpAttrs (FP, ObjPtr->lattr, PRTGIF);
!          break;
        case OBJ_TEXT: DumpTextObj (FP, ObjPtr, PRTGIF); break;
!       case OBJ_POLYGON:
!          DumpPolygonObj (FP, ObjPtr);
!          DumpAttrs (FP, ObjPtr->lattr, PRTGIF);
!          break;
        case OBJ_SYM:
        case OBJ_ICON:
***************
*** 832,836 ****
           for ( ; obj_ptr != NULL; obj_ptr = obj_ptr->prev)
              DumpAllObj (FP, obj_ptr, PRTGIF);
!          DumpAttrs (FP, ObjPtr->detail.r->lattr, PRTGIF);
           if (ObjPtr->type == OBJ_SYM) DumpSymOutline (FP, ObjPtr);
           break;
--- 831,835 ----
           for ( ; obj_ptr != NULL; obj_ptr = obj_ptr->prev)
              DumpAllObj (FP, obj_ptr, PRTGIF);
!          DumpAttrs (FP, ObjPtr->lattr, PRTGIF);
           if (ObjPtr->type == OBJ_SYM) DumpSymOutline (FP, ObjPtr);
           break;
---------------------------------> cut here <---------------------------------
--
Bill Cheng // UCLA Computer Science Department // (213) 206-7135
3277 Boelter Hall // Los Angeles, California 90024 // USA
william@CS.UCLA.EDU      ...!{uunet|ucbvax}!cs.ucla.edu!william

dan
----------------------------------------------------
O'Reilly && Associates   argv@sun.com / argv@ora.com
Opinions expressed reflect those of the author only.