*** attr.c.orig	Tue Apr 18 17:12:32 2000
--- attr.c	Tue Apr 18 17:12:32 2000
***************
*** 130,133 ****
--- 130,143 ----
  }
  
+ void UpdAttrOwner(first_attr, owner_obj)
+    struct AttrRec *first_attr;
+    struct ObjRec *owner_obj;
+ {
+    while (first_attr != NULL) {
+       first_attr->owner = owner_obj;
+       first_attr = first_attr->next;
+    }
+ }
+ 
  static
  char *FindEqual(s)
***************
*** 1367,1374 ****
  }
  
! TgMenu *CreateAttrMenu(parent_menu, x, y, num_items, menu_strings, pixels)
     TgMenu *parent_menu;
     int x, y, num_items, *pixels;
!    char **menu_strings;
  {
     int i=0;
--- 1377,1385 ----
  }
  
! TgMenu *CreateAttrMenu(parent_menu, x, y, num_items, menu_strings,
!       status_strings, pixels)
     TgMenu *parent_menu;
     int x, y, num_items, *pixels;
!    char **menu_strings, **status_strings;
  {
     int i=0;
***************
*** 1386,1389 ****
--- 1397,1404 ----
        item_info->menu_str = UtilStrDup(menu_strings[i]);
        if (item_info->menu_str == NULL) FailAllocMessage();
+       if (status_strings != NULL && status_strings[i] != NULL) {
+          item_info->status_str = UtilStrDup(status_strings[i]);
+          if (item_info->status_str == NULL) FailAllocMessage();
+       }
        item_info->submenu_info = NULL;
        item_info->cmdid = INVALID;
***************
*** 1398,1401 ****
--- 1413,1419 ----
      */
     menu = TgCreateMenuFromMenuInfo(parent_menu, x, y, &stMenuInfo, TRUE);
+    for (item_info=stMenuInfo.items, i=0; i < num_items; item_info++, i++) {
+       UtilFree(item_info->status_str);
+    }
     memset(stMenuInfo.items, 0, (num_items+1)*sizeof(TgMenuItemInfo));
     free(stMenuInfo.items);
***************
*** 1409,1415 ****
           TgMenuItem *menu_item=(&menu->menuitems[i]);
  
!          stMenuItem.multicolor_pixel = pixels[i];
!          if (!TgSetMenuItemInfo(menu_item, TGMU_MASK_MULTICOLOR, &stMenuItem)) {
!             return TgDestroyMenu(menu, TRUE);
           }
           menu_item->menu_str_allocated = TRUE;
--- 1427,1436 ----
           TgMenuItem *menu_item=(&menu->menuitems[i]);
  
!          if (pixels != NULL) {
!             stMenuItem.multicolor_pixel = pixels[i];
!             if (!TgSetMenuItemInfo(menu_item, TGMU_MASK_MULTICOLOR,
!                   &stMenuItem)) {
!                return TgDestroyMenu(menu, TRUE);
!             }
           }
           menu_item->menu_str_allocated = TRUE;
***************
*** 1423,1428 ****
     /* pEditAttrInfo will also be freed before returning */
  {
!    int i=0, num_attrs=0, *fore_colors=NULL;
     char **attr_names=NULL, **attr_values=NULL, **attr_strings=NULL;
  
     if (pEditAttrInfo == NULL) return;
--- 1444,1450 ----
     /* pEditAttrInfo will also be freed before returning */
  {
!    int i=0, num_attrs=0, *fore_colors=NULL, *attr_indices=NULL;
     char **attr_names=NULL, **attr_values=NULL, **attr_strings=NULL;
+    char **status_strings=NULL;
  
     if (pEditAttrInfo == NULL) return;
***************
*** 1430,1447 ****
     num_attrs = pEditAttrInfo->num_attrs;
     fore_colors = pEditAttrInfo->fore_colors;
     attr_names = pEditAttrInfo->attr_names;
     attr_values = pEditAttrInfo->attr_values;
     attr_strings = pEditAttrInfo->attr_strings;
  
!    free(pEditAttrInfo->fore_colors);
  
     for (i=0; i < num_attrs; i++) {
!       UtilFree(attr_names[i]);
!       UtilFree(attr_values[i]);
!       UtilFree(attr_strings[i]);
     }
!    free(pEditAttrInfo->attr_names);
!    free(pEditAttrInfo->attr_values);
!    free(pEditAttrInfo->attr_strings);
  
     free(pEditAttrInfo);
--- 1452,1474 ----
     num_attrs = pEditAttrInfo->num_attrs;
     fore_colors = pEditAttrInfo->fore_colors;
+    attr_indices = pEditAttrInfo->attr_indices;
     attr_names = pEditAttrInfo->attr_names;
     attr_values = pEditAttrInfo->attr_values;
     attr_strings = pEditAttrInfo->attr_strings;
+    status_strings = pEditAttrInfo->status_strings;
  
!    if (pEditAttrInfo->fore_colors != NULL) free(pEditAttrInfo->fore_colors);
!    if (pEditAttrInfo->attr_indices != NULL) free(pEditAttrInfo->attr_indices);
  
     for (i=0; i < num_attrs; i++) {
!       if (attr_names != NULL) UtilFree(attr_names[i]);
!       if (attr_values != NULL) UtilFree(attr_values[i]);
!       if (attr_strings != NULL) UtilFree(attr_strings[i]);
!       if (status_strings != NULL) UtilFree(status_strings[i]);
     }
!    if (attr_names != NULL) free(attr_names);
!    if (attr_values != NULL) free(attr_values);
!    if (attr_strings != NULL) free(attr_strings);
!    if (status_strings != NULL) free(status_strings);
  
     free(pEditAttrInfo);
***************
*** 1448,1458 ****
  }
  
  EditAttrInfo *CreateEditAttrInfo(obj_ptr)
     struct ObjRec *obj_ptr;
  {
!    int i=0, num_attrs=0, *fore_colors=NULL, *pixel_ptr=NULL;
!    struct AttrRec *attr_ptr=NULL, *attr_ptr1=NULL;
     EditAttrInfo *pEditAttrInfo=NULL;
     char **attr_names=NULL, **attr_values=NULL, **attr_strings=NULL;
  
     pEditAttrInfo = (EditAttrInfo*)malloc(sizeof(EditAttrInfo));
--- 1475,1588 ----
  }
  
+ int HasEditAttrsInContextMenu(obj_ptr, pp_name_attr)
+    struct ObjRec *obj_ptr;
+    struct AttrRec **pp_name_attr;
+ {
+    struct AttrRec *attr_ptr=NULL;
+ 
+    if (pp_name_attr != NULL) *pp_name_attr = NULL;
+    for (attr_ptr=obj_ptr->lattr; attr_ptr!=NULL; attr_ptr=attr_ptr->prev) {
+       if (strcmp(attr_ptr->attr_name.s, "edit_attrs_in_context_menu=") == 0) {
+          if (pp_name_attr != NULL) *pp_name_attr = attr_ptr;
+          return TRUE;
+       }
+    }
+    return FALSE;
+ }
+ 
+ static
+ void FreeRestrictedAttrNames(ppsz_restricted, num_restricted)
+    char **ppsz_restricted;
+    int num_restricted;
+ {
+    if (ppsz_restricted != NULL) {
+       int i=0;
+ 
+       for (i=0; i < num_restricted; i++) {
+          if (ppsz_restricted[i] != NULL) {
+             UtilFree(ppsz_restricted[i]);
+          }
+       }
+       free(ppsz_restricted);
+    }
+ }
+ 
+ static
+ void GetRestrictedAttrNames(restricted_attr_obj, pppsz_restricted,
+       pn_num_restricted)
+    struct ObjRec *restricted_attr_obj;
+    char ***pppsz_restricted;
+    int *pn_num_restricted;
+ {
+    MiniLinesInfo *minilines=(&restricted_attr_obj->detail.t->minilines);
+    MiniLineInfo *miniline=minilines->first->next;
+    char **ppsz_restricted=NULL;
+    int num_restricted=0, index=0;
+ 
+    if (pppsz_restricted != NULL) (*pppsz_restricted) = NULL;
+    if (pn_num_restricted != NULL) (*pn_num_restricted) = 0;
+    if (miniline == NULL) return;
+ 
+    for ( ; miniline != NULL; miniline=miniline->next, num_restricted++) {
+    }
+    ppsz_restricted = (char**)malloc(num_restricted*sizeof(char*));
+    if (ppsz_restricted == NULL) FailAllocMessage();
+    memset(ppsz_restricted, 0, num_restricted*sizeof(char*));
+ 
+    miniline = minilines->first->next;
+    for ( ; miniline != NULL; miniline=miniline->next) {
+       int need_to_free_tmp_buf=FALSE;
+       char *tmp_buf=ConvertMiniLineToString(miniline, &need_to_free_tmp_buf);
+ 
+       if (tmp_buf != NULL) {
+          UtilTrimBlanks(tmp_buf);
+          if (*tmp_buf == '\0') {
+             num_restricted--;
+          } else {
+             int len=strlen(tmp_buf)+2; /* extra char for '=' */
+ 
+             ppsz_restricted[index] = (char*)malloc((len+1)*sizeof(char));
+             if (ppsz_restricted[index] == NULL) FailAllocMessage();
+             sprintf(ppsz_restricted[index], "%s=", tmp_buf);
+             index++;
+          }
+          if (need_to_free_tmp_buf) UtilFree(tmp_buf);
+       } else {
+          num_restricted--;
+       }
+       if (num_restricted <= 0) break;
+    }
+    if (num_restricted <= 0) {
+       free(pppsz_restricted);
+    } else {
+       if (pppsz_restricted != NULL) (*pppsz_restricted) = ppsz_restricted;
+       if (pn_num_restricted != NULL) (*pn_num_restricted) = num_restricted;
+    }
+ }
+ 
+ static
+ int IsRestrictedAttr(attr_name, ppsz_restricted, num_restricted)
+    char *attr_name, **ppsz_restricted;
+    int num_restricted;
+ {
+    int i=0;
+ 
+    for (i=0; i < num_restricted; i++) {
+       if (strcmp(attr_name, ppsz_restricted[i]) == 0) {
+          return TRUE;
+       }
+    }
+    return FALSE;
+ }
+ 
  EditAttrInfo *CreateEditAttrInfo(obj_ptr)
     struct ObjRec *obj_ptr;
  {
!    int i=0, num_attrs=0, *fore_colors=NULL, *pixel_ptr=NULL, restricted=FALSE;
!    int num_restricted=0, num_created=0, *attr_indices=NULL;
!    struct AttrRec *attr_ptr=NULL, *attr_ptr1=NULL, *restricted_attr=NULL;
     EditAttrInfo *pEditAttrInfo=NULL;
     char **attr_names=NULL, **attr_values=NULL, **attr_strings=NULL;
+    char **status_strings=NULL, **ppsz_restricted=NULL;
  
     pEditAttrInfo = (EditAttrInfo*)malloc(sizeof(EditAttrInfo));
***************
*** 1467,1476 ****
        return NULL;
     }
     attr_names = (char**)malloc(num_attrs*sizeof(char*));
     attr_values = (char**)malloc(num_attrs*sizeof(char*));
     attr_strings = (char**)malloc(num_attrs*sizeof(char*));
     fore_colors = pixel_ptr = (int*)malloc(num_attrs*sizeof(int));
     if (attr_names == NULL || attr_values == NULL || attr_strings == NULL ||
!          fore_colors == NULL) {
        FailAllocMessage();
     }
--- 1597,1618 ----
        return NULL;
     }
+    restricted = HasEditAttrsInContextMenu(obj_ptr, &restricted_attr);
+    if (restricted) {
+       GetRestrictedAttrNames(restricted_attr->obj, &ppsz_restricted,
+             &num_restricted);
+       if (ppsz_restricted == NULL || num_restricted <= 0) {
+          free(pEditAttrInfo);
+          return NULL;
+       }
+    }
     attr_names = (char**)malloc(num_attrs*sizeof(char*));
     attr_values = (char**)malloc(num_attrs*sizeof(char*));
     attr_strings = (char**)malloc(num_attrs*sizeof(char*));
+    status_strings = (char**)malloc(num_attrs*sizeof(char*));
     fore_colors = pixel_ptr = (int*)malloc(num_attrs*sizeof(int));
+    attr_indices = (int*)malloc(num_attrs*sizeof(int));
     if (attr_names == NULL || attr_values == NULL || attr_strings == NULL ||
!          status_strings == NULL || fore_colors == NULL ||
!          attr_indices == NULL) {
        FailAllocMessage();
     }
***************
*** 1484,1504 ****
              &need_to_free_tmp_buf);
  
!       attr_names[i] = UtilStrDup(attr_ptr1->attr_name.s);
!       attr_values[i] = UtilStrDup(attr_ptr1->attr_value.s);
!       attr_strings[i] = UtilStrDup(tmp_buf);
!       if (attr_names[i] == NULL || attr_values[i] == NULL ||
!             attr_strings[i] == NULL) {
           FailAllocMessage();
        }
!       *pixel_ptr++ = colorPixels[minilines->first->first_block->seg->color];
  
        if (need_to_free_tmp_buf) UtilFree(tmp_buf);
     }
!    pEditAttrInfo->num_attrs = num_attrs;
     pEditAttrInfo->fore_colors = fore_colors;
     pEditAttrInfo->attr_names = attr_names;
     pEditAttrInfo->attr_values = attr_values;
     pEditAttrInfo->attr_strings = attr_strings;
  
     return pEditAttrInfo;
  }
--- 1626,1664 ----
              &need_to_free_tmp_buf);
  
!       if (restricted) {
!          if (!IsRestrictedAttr(attr_ptr1->attr_name.s, ppsz_restricted,
!                num_restricted)) {
!             if (need_to_free_tmp_buf) UtilFree(tmp_buf);
!             continue;
!          }
!       }
!       attr_names[num_created] = UtilStrDup(attr_ptr1->attr_name.s);
!       attr_values[num_created] = UtilStrDup(attr_ptr1->attr_value.s);
!       attr_strings[num_created] = UtilStrDup(tmp_buf);
!       sprintf(gszMsgBox, TgLoadCachedString(CSTID_EDIT_ATTR_IN_EDITOR),
!             tmp_buf);
!       status_strings[num_created] = UtilStrDup(gszMsgBox);
!       if (attr_names[num_created] == NULL || attr_values[num_created] == NULL ||
!             attr_strings[num_created] == NULL ||
!             status_strings[num_created] == NULL) {
           FailAllocMessage();
        }
!       pixel_ptr[num_created] =
!             colorPixels[minilines->first->first_block->seg->color];
!       attr_indices[num_created] = i;
  
        if (need_to_free_tmp_buf) UtilFree(tmp_buf);
+       num_created++;
     }
!    pEditAttrInfo->num_attrs = num_created;
     pEditAttrInfo->fore_colors = fore_colors;
+    pEditAttrInfo->attr_indices = attr_indices;
     pEditAttrInfo->attr_names = attr_names;
     pEditAttrInfo->attr_values = attr_values;
     pEditAttrInfo->attr_strings = attr_strings;
+    pEditAttrInfo->status_strings = status_strings;
  
+    FreeRestrictedAttrNames(ppsz_restricted, num_restricted);
+ 
     return pEditAttrInfo;
  }
***************
*** 1553,1557 ****
     activeMenu = INVALID;
     if (button == Button1 || button == Button2) {
!       TgMenu *menu=CreateAttrMenu(NULL, x, y, num_attrs, attr_strings,
              fore_colors);
  
--- 1713,1717 ----
     activeMenu = INVALID;
     if (button == Button1 || button == Button2) {
!       TgMenu *menu=CreateAttrMenu(NULL, x, y, num_attrs, attr_strings, NULL,
              fore_colors);
  
*** choose.c.orig	Tue Apr 18 17:12:33 2000
--- choose.c	Tue Apr 18 17:12:33 2000
***************
*** 52,55 ****
--- 52,56 ----
  #include "rect.e"
  #include "remote.e"
+ #include "ruler.e"
  #include "scroll.e"
  #include "setup.e"
***************
*** 2116,2119 ****
--- 2117,2122 ----
     if (!CreateNamesWindows(win_name)) return INVALID;
  
+    EndMeasureTooltip(FALSE);
+ 
     pni->userdata = p_void;
  
*** color.c.orig	Tue Apr 18 17:12:34 2000
--- color.c	Tue Apr 18 17:12:34 2000
***************
*** 604,608 ****
  
        myBlackPixel = myWhitePixel = myLtGryPixel = myDkGryPixel = INVALID;
!       myVryLtPixel = INVALID;
        memset(&color, 0, sizeof(XColor));
        if (ParseAndAllocColorByName("black", &color, NULL, NULL, NULL)) {
--- 604,608 ----
  
        myBlackPixel = myWhitePixel = myLtGryPixel = myDkGryPixel = INVALID;
!       myVryLtPixel = myYellowPixel = INVALID;
        memset(&color, 0, sizeof(XColor));
        if (ParseAndAllocColorByName("black", &color, NULL, NULL, NULL)) {
***************
*** 612,615 ****
--- 612,618 ----
           myWhitePixel = color.pixel;
        }
+       if (ParseAndAllocColorByName("#ffff00", &color, NULL, NULL, NULL)) {
+          myYellowPixel = color.pixel;
+       }
        if ((c_ptr=XGetDefault(mainDisplay,TOOL_NAME,"LightGrayColor")) != NULL) {
           if (ParseAndAllocColorByName(c_ptr, &color, NULL, NULL, NULL)) {
***************
*** 650,654 ****
        if (myBlackPixel == INVALID || myWhitePixel == INVALID ||
              myLtGryPixel == INVALID || myDkGryPixel == INVALID ||
!             (initVryLtPixel && myVryLtPixel == INVALID)) {
           fprintf(stderr, "%s\n", TgLoadString(STID_FAIL_TO_ALLOC_3D_COLORS));
           threeDLook = FALSE;
--- 653,658 ----
        if (myBlackPixel == INVALID || myWhitePixel == INVALID ||
              myLtGryPixel == INVALID || myDkGryPixel == INVALID ||
!             (initVryLtPixel && myVryLtPixel == INVALID) ||
!             myYellowPixel == INVALID) {
           fprintf(stderr, "%s\n", TgLoadString(STID_FAIL_TO_ALLOC_3D_COLORS));
           threeDLook = FALSE;
*** cutpaste.c.orig	Tue Apr 18 17:12:35 2000
--- cutpaste.c	Tue Apr 18 17:12:35 2000
***************
*** 38,41 ****
--- 38,42 ----
  #include "arc.e"
  #include "auxtext.e"
+ #include "attr.e"
  #include "box.e"
  #include "choice.e"
***************
*** 69,72 ****
--- 70,74 ----
  #include "poly.e"
  #include "polygon.e"
+ #include "raster.e"
  #include "rcbox.e"
  #include "remote.e"
***************
*** 459,513 ****
  }
  
! int PasteFromCutBuffer()
!    /* returns FALSE if pasting in text mode and non-tgif bytes are */
!    /*    in the cut buffer -- this is interpreted as an attempt to */
!    /*    paste into the current text */
  {
-    FILE *fp=NULL;
-    int len, ltx, lty, rbx, rby, dx, dy, read_status, paste_string=FALSE;
-    char tmpfile[MAXSTRING], *cut_buffer=NULL, *orig_cut_buffer=NULL;
     unsigned char header=TGIF_HEADER;
-    struct ObjRec *obj_ptr=NULL, *tmp_obj=NULL, *partial_text_obj_ptr=NULL;
-    struct ObjRec *saved_top_obj=NULL, *saved_bot_obj=NULL;
-    struct ObjRec *tmp_top_obj=NULL, *tmp_bot_obj=NULL;
  
!    orig_cut_buffer = cut_buffer = (char*)FetchCutBuffer(&len);
!    if (len == 0) {
!       MsgBox(TgLoadString(STID_CUT_BUFFER_EMPTY), TOOL_NAME, INFO_MB);
!       return TRUE;
!    }
!    if (((unsigned char)(*cut_buffer)) != header) {
!       paste_string = TRUE;
!    } else if (strncmp(&cut_buffer[1], "%TGIF", 5) == 0) {
!       paste_string = FALSE;
!    } else if (strncmp(&cut_buffer[1], "state(", 6) == 0) {
!       /* very old tgif format (even before tgif-2.12) */
!       paste_string = FALSE;
!    } else {
!       paste_string = TRUE;
!    }
!    if (paste_string) {
!       if (curChoice == DRAWTEXT) {
!          XEvent ev;
! 
!          XFree(cut_buffer);
!          pasteInDrawTextMode = TRUE;
!          ev.type = KeyPress;
!          DrawText(&ev);
!          return FALSE;
        }
! #ifndef _NO_KINPUT
!       if (copyAndPasteJIS) {
!          CvtJisToEuc(cut_buffer, cut_buffer);
!       }
! #endif /* ~_NO_KINPUT */
!       Msg(TgLoadString(STID_PASTE_FROM_NON_TGIF));
!       PasteString(cut_buffer);
!       XFree(cut_buffer);
!       return TRUE;
     }
!    cut_buffer++;
!    len--;
  
     sprintf(tmpfile, "%sTgifXXXXXX", TMP_DIR);
     mktemp(tmpfile);
--- 461,500 ----
  }
  
! #define CBF_NON_TGIF 0
! #define CBF_TGIF_STRING 1
! #define CBF_TGIF_OBJ 2
! 
! static
! int CutBufferType(cut_buffer)
!    char *cut_buffer;
  {
     unsigned char header=TGIF_HEADER;
  
!    if (((unsigned char)(*cut_buffer)) == header) {
!       if (strncmp(&cut_buffer[1], "%TGIF", 5) == 0) {
!          return CBF_TGIF_OBJ;
!       } else if (strncmp(&cut_buffer[1], "state(", 6) == 0) {
!          /* very old tgif format (even before tgif-2.12) */
!          return CBF_TGIF_OBJ;
        }
!       return CBF_TGIF_STRING;
     }
!    return CBF_NON_TGIF;
! }
  
+ static
+ int GetObjsFromCutBuffer(cut_buffer, len, pp_top_obj, pp_bot_obj)
+    char *cut_buffer;
+    int len;
+    struct ObjRec **pp_top_obj, **pp_bot_obj;
+    /* the cut_buffer is the original cut buffer shifted one byte */
+ {
+    FILE *fp=NULL;
+    int read_status=0;
+    char tmpfile[MAXSTRING];
+    struct ObjRec *obj_ptr=NULL, *saved_top_obj=NULL, *saved_bot_obj=NULL;
+ 
+    (*pp_top_obj) = (*pp_bot_obj) = NULL;
+ 
     sprintf(tmpfile, "%sTgifXXXXXX", TMP_DIR);
     mktemp(tmpfile);
***************
*** 516,521 ****
              tmpfile);
        MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
!       XFree(orig_cut_buffer);
!       return TRUE;
     }
     writeFileFailed = FALSE;
--- 503,507 ----
              tmpfile);
        MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
!       return FALSE;
     }
     writeFileFailed = FALSE;
***************
*** 526,535 ****
              tmpfile);
        MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
!       XFree(orig_cut_buffer);
!       return TRUE;
     }
     fflush(fp);
     rewind(fp);
-    XFree(orig_cut_buffer);
  
     SetWatchCursor(drawWindow);
--- 512,519 ----
              tmpfile);
        MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
!       return FALSE;
     }
     fflush(fp);
     rewind(fp);
  
     SetWatchCursor(drawWindow);
***************
*** 536,545 ****
     SetWatchCursor(mainWindow);
  
-    if (curChoice == DRAWTEXT) {
-       partial_text_obj_ptr = NULL;
-       SaveCursorPositionInCurText();
-    } else {
-       MakeQuiescent();
-    }
     saved_top_obj = topObj;
     saved_bot_obj = botObj;
--- 520,523 ----
***************
*** 573,582 ****
              fileVersion);
        MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
        return TRUE;
     }
     if (curChoice == DRAWTEXT && textCursorShown && topObj != NULL &&
           topObj == botObj && topObj->type == OBJ_TEXT) {
        /* we are pasting minilines and not object */
!       partial_text_obj_ptr = topObj;
        RestoreCursorPositionInCurText();
        curPage->top = topObj = saved_top_obj;
--- 551,624 ----
              fileVersion);
        MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
+       return FALSE;
+    }
+    (*pp_top_obj) = topObj;
+    (*pp_bot_obj) = botObj;
+ 
+    curPage->top = topObj = saved_top_obj;
+    curPage->bot = botObj = saved_bot_obj;
+     
+    return TRUE;
+ }
+ 
+ int PasteFromCutBuffer()
+    /* returns FALSE if pasting in text mode and non-tgif bytes are */
+    /*    in the cut buffer -- this is interpreted as an attempt to */
+    /*    paste into the current text */
+ {
+    int len=0, ltx=0, lty=0, rbx=0, rby=0, dx=0, dy=0;
+    char *cut_buffer=NULL, *orig_cut_buffer=NULL;
+    struct ObjRec *obj_ptr=NULL, *tmp_obj=NULL;
+    struct ObjRec *saved_top_obj=NULL, *saved_bot_obj=NULL;
+    struct ObjRec *pasted_top_obj=NULL, *pasted_bot_obj=NULL;
+    struct ObjRec *tmp_top_obj=NULL, *tmp_bot_obj=NULL;
+ 
+    orig_cut_buffer = cut_buffer = (char*)FetchCutBuffer(&len);
+    if (len == 0) {
+       MsgBox(TgLoadString(STID_CUT_BUFFER_EMPTY), TOOL_NAME, INFO_MB);
        return TRUE;
     }
+    if (CutBufferType(cut_buffer) != CBF_TGIF_OBJ) {
+       if (curChoice == DRAWTEXT) {
+          XEvent ev;
+ 
+          XFree(cut_buffer);
+          pasteInDrawTextMode = TRUE;
+          ev.type = KeyPress;
+          DrawText(&ev);
+          return FALSE;
+       }
+ #ifndef _NO_KINPUT
+       if (copyAndPasteJIS) {
+          CvtJisToEuc(cut_buffer, cut_buffer);
+       }
+ #endif /* ~_NO_KINPUT */
+       Msg(TgLoadString(STID_PASTE_FROM_NON_TGIF));
+       PasteString(cut_buffer);
+       XFree(cut_buffer);
+       return TRUE;
+    }
+    if (curChoice == DRAWTEXT) {
+       SaveCursorPositionInCurText();
+    } else {
+       MakeQuiescent();
+    }
+    if (!GetObjsFromCutBuffer(&cut_buffer[1], len-1, &pasted_top_obj,
+          &pasted_bot_obj)) {
+       XFree(orig_cut_buffer);
+       return TRUE;
+    }
+    XFree(orig_cut_buffer);
+ 
+    saved_top_obj = topObj;
+    saved_bot_obj = botObj;
+    curPage->top = topObj = pasted_top_obj;
+    curPage->bot = botObj = pasted_bot_obj;
+     
     if (curChoice == DRAWTEXT && textCursorShown && topObj != NULL &&
           topObj == botObj && topObj->type == OBJ_TEXT) {
        /* we are pasting minilines and not object */
!       struct ObjRec *partial_text_obj_ptr=topObj;
! 
        RestoreCursorPositionInCurText();
        curPage->top = topObj = saved_top_obj;
***************
*** 665,670 ****
  {
     char file_name[MAXPATHLENGTH+1];
!    FILE *fp;
!    char inbuf[MAXSTRING+1], * cut_buffer=NULL;
     int size=0, pos=0;
  
--- 707,712 ----
  {
     char file_name[MAXPATHLENGTH+1];
!    FILE *fp=NULL;
!    char inbuf[MAXSTRING+1], *cut_buffer=NULL;
     int size=0, pos=0;
  
***************
*** 1313,1319 ****
  
  static
! void DoPasteAProperty(lWhich, nPasteSel, pProp)
     long lWhich;
-    int nPasteSel;
     struct PropertiesRec *pProp;
  {
--- 1355,1360 ----
  
  static
! void DoPasteAProperty(lWhich, pProp)
     long lWhich;
     struct PropertiesRec *pProp;
  {
***************
*** 1385,1388 ****
--- 1426,1504 ----
  }
  
+ static
+ void DoGetAProperty(lWhich, pProp)
+    long lWhich;
+    struct PropertiesRec *pProp;
+ {
+    char szBuf[MAXSTRING];
+    int index=0, new_alloc=FALSE;
+ 
+    switch (lWhich) {
+    case PROP_MASK_COLOR:
+       index = QuickFindColorIndex(NULL, pProp->color_str, &new_alloc, FALSE);
+       if (index == INVALID) {
+          sprintf(gszMsgBox, TgLoadString(STID_FAIL_ALLOC_NAMED_COLOR),
+                pProp->color_str);
+          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
+          return;
+       } else {
+          ChangeAllSelColor(index, TRUE);
+       }
+       break;
+    case PROP_MASK_WIDTH_INDEX:
+       ChangeAllSelLineWidth(pProp->width_index, TRUE);
+       break;
+    case PROP_MASK_WIDTH:
+       ChangeAllSelRealLineWidth(CHANGE_WIDTH, pProp->width, (-1), (-1),
+             pProp->width_spec, NULL, NULL, TRUE);
+       break;
+    case PROP_MASK_AW:
+       ChangeAllSelRealLineWidth(CHANGE_AW, (-1), pProp->aw, (-1),
+             NULL, pProp->aw_spec, NULL, TRUE);
+       break;
+    case PROP_MASK_AH:
+       ChangeAllSelRealLineWidth(CHANGE_AH, (-1), (-1), pProp->ah,
+             NULL, NULL, pProp->ah_spec, TRUE);
+       break;
+ 
+    case PROP_MASK_TRANSPAT: ChangeAllSelTransPat(pProp->trans_pat, TRUE); break;
+    case PROP_MASK_FILL: ChangeAllSelFill(pProp->fill, TRUE); break;
+    case PROP_MASK_PEN: ChangeAllSelPen(pProp->pen, TRUE); break;
+    case PROP_MASK_DASH: ChangeAllSelLineDash(pProp->dash, TRUE); break;
+    case PROP_MASK_ARROW_STYLE:
+       ChangeAllSelLineStyle(pProp->arrow_style, TRUE);
+       break;
+    case PROP_MASK_CURVED: ChangeAllSelLineType(pProp->curved, TRUE); break;
+    case PROP_MASK_RCB_RADIUS: ChangeAllSelRCBRadius(pProp->rcb_radius); break;
+    case PROP_MASK_TEXT_JUST: ChangeFontJust(pProp->text_just); break;
+    case PROP_MASK_TEXT_SZ_UNIT:
+       sprintf(szBuf, "%1d", SzUnitToFontSize(pProp->text_sz_unit));
+       SetSelFontSize(szBuf);
+       break;
+    case PROP_MASK_VSPACE: ChangeVSpace(pProp->v_space); break;
+    case PROP_MASK_UNDERLINE_ON: ChangeFontUnderline(pProp->underline_on); break;
+ 
+    case PROP_MASK_TEXT_FONT:
+       ChangeFont(pProp->text_font, TRUE);
+       ChangeFontStyle(pProp->text_style);
+       break;
+ 
+    case PROP_MASK_CTM:
+       if (topSel == NULL) {
+          if (pProp->transformed) {
+             int angle=GetAngleFromCTM(&pProp->ctm);
+ 
+             FormatAngle(angle, szBuf);
+          } else {
+             strcpy(szBuf, "0");
+          }
+          SetTextRotation(szBuf);
+       } else {
+          SetSelCTM(pProp->transformed, &pProp->ctm);
+       }
+       break;
+    }
+ }
+ 
  static char gszPropIniFile[MAXPATHLENGTH];
  
***************
*** 1418,1421 ****
--- 1534,1538 ----
     { PROP_MASK_UNDERLINE_ON, FALSE, NULL, NULL },
     { PROP_MASK_CTM,          FALSE, NULL, NULL },
+    { PROP_MASK_WIDTH_INDEX,  FALSE, NULL, NULL },
     { 0L, FALSE, NULL, NULL }
  };
***************
*** 1422,1426 ****
  
  static struct PropInfoRec gstCompatPropInfo[] = {
!    /* do not translate -- program constants */
     { PROP_MASK_AH,           FALSE, NULL, "arrow height" },
     { PROP_MASK_AW,           FALSE, NULL, "arrow width" },
--- 1539,1550 ----
  
  static struct PropInfoRec gstCompatPropInfo[] = {
!    /*
!     * do not translate -- program constants
!     *
!     * These are used for compatibility reasons.  In an earlier version,
!     *       the keys in "cutpaste.ini" are these strings.  In the current
!     *       version, hex numbers are used.  gstCompatPropInfo are only used
!     *       by UpdateSavedPropKeys() to update the old keys to new ones.
!     */
     { PROP_MASK_AH,           FALSE, NULL, "arrow height" },
     { PROP_MASK_AW,           FALSE, NULL, "arrow width" },
***************
*** 1441,1444 ****
--- 1565,1569 ----
     { PROP_MASK_UNDERLINE_ON, FALSE, NULL, "text underline" },
     { PROP_MASK_CTM,          FALSE, NULL, "transformation matrix" },
+    { 0L, FALSE, NULL, NULL }
  };
  
***************
*** 1894,1897 ****
--- 2019,2025 ----
  
     case PROP_MASK_COLOR: strcat(pszBuf, pProp->color_str); break;
+    case PROP_MASK_WIDTH_INDEX:
+       sprintf(&pszBuf[nLen], "%1d", pProp->width_index);
+       break;
     case PROP_MASK_WIDTH: strcat(pszBuf, pProp->width_spec); break;
     case PROP_MASK_AW: strcat(pszBuf, pProp->aw_spec); break;
***************
*** 2158,2162 ****
        if (ppir->checked) {
           if (pCheckArray->value[0][index]) {
!             DoPasteAProperty(ppir->bit, paste_sel, pProp);
           }
           index++;
--- 2286,2290 ----
        if (ppir->checked) {
           if (pCheckArray->value[0][index]) {
!             DoPasteAProperty(ppir->bit, pProp);
           }
           index++;
***************
*** 2352,2356 ****
     for (ppir=gstPropInfo; ppir->bit != 0L; ppir++) {
        ppir->checked = FALSE;
!       if ((lSkip & ppir->bit) == 0) {
           num_rows++;
        }
--- 2480,2484 ----
     for (ppir=gstPropInfo; ppir->bit != 0L; ppir++) {
        ppir->checked = FALSE;
!       if ((lMask & ppir->bit) != 0L && (lSkip & ppir->bit) == 0) {
           num_rows++;
        }
***************
*** 2449,2457 ****
        SetPropMask(NULL, plMask, plSkip, pProp);
     }
!    *plSkip = ~(*plMask); /* shouldn't do this if we support multiple objects */
  
!    return PrepareToCopyProperties(pProp, *plMask, *plSkip, pCheckArray);
  }
  
  void CopyProperties(nPrompt)
     int nPrompt;
--- 2577,2730 ----
        SetPropMask(NULL, plMask, plSkip, pProp);
     }
!    /* shouldn't do this if we support multiple objects */
!    *plSkip = ~((*plMask) | PROP_MASK_WIDTH_INDEX);
  
!    if (pCheckArray != NULL) {
!       return PrepareToCopyProperties(pProp, *plMask, *plSkip, pCheckArray);
!    }
!    return TRUE;
  }
  
+ static
+ void FixMasksForGetProperty(pProp, plMask, plSkip)
+    struct PropertiesRec *pProp;
+    long *plMask, *plSkip;
+ {
+    long lMask=(*plMask);
+ 
+    *plSkip |= PROP_MASK_CTM;
+ 
+    if ((lMask & PROP_MASK_WIDTH) == PROP_MASK_WIDTH) {
+       int i=0;
+       char *width_spec=pProp->width_spec;
+ 
+       if (((lMask & PROP_MASK_AW) == PROP_MASK_AW) &&
+             ((lMask & PROP_MASK_AH) == PROP_MASK_AH)) {
+          char *aw_spec=pProp->aw_spec;
+          char *ah_spec=pProp->ah_spec;
+ 
+          *plSkip |= (PROP_MASK_WIDTH | PROP_MASK_AW | PROP_MASK_AH);
+          for (i=0; i < maxLineWidths; i++) {
+             if (strcmp(width_spec, curWidthOfLineSpec[i]) == 0 &&
+                   strcmp(aw_spec, curArrowHeadWSpec[i]) == 0 &&
+                   strcmp(ah_spec, curArrowHeadHSpec[i]) == 0) {
+                pProp->width_index = i;
+                *plMask |= PROP_MASK_WIDTH_INDEX;
+                break;
+             }
+          }
+       } else {
+          *plSkip |= (PROP_MASK_WIDTH);
+          for (i=0; i < maxLineWidths; i++) {
+             if (strcmp(width_spec, curWidthOfLineSpec[i]) == 0) {
+                pProp->width_index = i;
+                *plMask |= PROP_MASK_WIDTH_INDEX;
+                break;
+             }
+          }
+       }
+    }
+ }
+ 
+ void DoGetProperty(target_index)
+    int target_index;
+ {
+    struct PropertiesRec properties;
+    struct PropInfoRec *ppir=NULL;
+    long lMask=0L, lSkip=0L;
+    int index=0;
+    struct SelRec *saved_top_sel=NULL, *saved_bot_sel=NULL;
+ 
+    memset(&properties, 0, sizeof(struct PropertiesRec));
+    if (!SetupProperties(&properties, &lMask, &lSkip, NULL, COPY_PROP)) {
+       return;
+    }
+    FixMasksForGetProperty(&properties, &lMask, &lSkip);
+ 
+    HighLightReverse();
+    saved_top_sel = topSel;
+    saved_bot_sel = botSel;
+    topSel = botSel = NULL;
+    UpdSelBBox();
+    for (ppir=gstPropInfo; ppir->bit != 0L; ppir++) {
+       if ((lMask & ppir->bit) != 0L && (lSkip & ppir->bit) == 0) {
+          if (index == target_index) {
+             /* do something */
+             DoGetAProperty(ppir->bit, &properties);
+             break;
+          }
+          index++;
+       }
+    }
+    topSel = saved_top_sel;
+    botSel = saved_bot_sel;
+    UpdSelBBox();
+    HighLightReverse();
+ }
+ 
+ EditAttrInfo *CreateGetPropertyInfo()
+ {
+    struct PropertiesRec properties;
+    struct PropInfoRec *ppir=NULL;
+    EditAttrInfo *pEditAttrInfo=NULL;
+    long lMask=0L, lSkip=0L;
+    int index=0, num_attrs=0;
+    char **attr_strings=NULL, **status_strings=NULL;
+ 
+    pEditAttrInfo = (EditAttrInfo*)malloc(sizeof(EditAttrInfo));
+    if (pEditAttrInfo == NULL) FailAllocMessage();
+    memset(pEditAttrInfo, 0, sizeof(EditAttrInfo));
+ 
+    memset(&properties, 0, sizeof(struct PropertiesRec));
+    if (!SetupProperties(&properties, &lMask, &lSkip, NULL, COPY_PROP)) {
+       return NULL;
+    }
+    FixMasksForGetProperty(&properties, &lMask, &lSkip);
+ 
+    for (ppir=gstPropInfo; ppir->bit != 0L; ppir++) {
+       ppir->checked = FALSE;
+       if ((lMask & ppir->bit) != 0L && (lSkip & ppir->bit) == 0) {
+          num_attrs++;
+       }
+    }
+    attr_strings = (char**)malloc(num_attrs*sizeof(char*));
+    status_strings = (char**)malloc(num_attrs*sizeof(char*));
+    if (attr_strings == NULL || status_strings == NULL) FailAllocMessage();
+    memset(attr_strings, 0, num_attrs*sizeof(char*));
+    memset(status_strings, 0, num_attrs*sizeof(char*));
+ 
+    for (ppir=gstPropInfo, index=0; ppir->bit != 0L; ppir++) {
+       long bit=ppir->bit;
+ 
+       if ((lMask & bit) != 0L && (lSkip & bit) == 0) {
+          char *psz=NULL, szBuf[MAXSTRING];
+ 
+          *szBuf = '\0';
+          FormatPropForDisplay(ppir->bit, &properties, ppir, szBuf);
+          attr_strings[index] = UtilStrDup(szBuf);
+          if (attr_strings[index] == NULL) FailAllocMessage();
+          if ((psz=strchr(szBuf, ':')) != NULL) {
+             *psz++ = '\0';
+             UtilTrimBlanks(psz);
+             sprintf(gszMsgBox,
+                   TgLoadCachedString(CSTID_GET_NAMED_PROP_FROM_SEL_OBJ), szBuf);
+             status_strings[index] = UtilStrDup(gszMsgBox);
+             if (status_strings[index] == NULL) FailAllocMessage();
+          }
+          ppir->checked = TRUE;
+          index++;
+       }
+    }
+    pEditAttrInfo->num_attrs = num_attrs;
+    pEditAttrInfo->fore_colors = NULL;
+    pEditAttrInfo->attr_indices = NULL;
+    pEditAttrInfo->attr_names = NULL;
+    pEditAttrInfo->attr_values = NULL;
+    pEditAttrInfo->attr_strings = attr_strings;
+    pEditAttrInfo->status_strings = status_strings;
+ 
+    return pEditAttrInfo;
+ }
+ 
  void CopyProperties(nPrompt)
     int nPrompt;
***************
*** 3292,3294 ****
--- 3565,3742 ----
     free(ObjPtr->detail.ss);
     free(ObjPtr);
+ }
+ 
+ /* ----------------------- ReplaceGraphic() ----------------------- */
+ 
+ static
+ void UnInheritAllAttrs(obj_ptr)
+    struct ObjRec *obj_ptr;
+ {
+    struct AttrRec *attr_ptr;
+ 
+    for (attr_ptr=obj_ptr->fattr; attr_ptr != NULL; attr_ptr=attr_ptr->next) {
+       if (attr_ptr->inherited) {
+          attr_ptr->inherited = FALSE;
+       }
+    }
+ }
+ 
+ void ReplaceGraphic()
+ {
+    struct SelRec *saved_top_sel=NULL, *saved_bot_sel=NULL, *sel_ptr=NULL;
+    struct SelRec *prev_sel=NULL;
+    struct ObjRec *pasted_top_obj=NULL, *pasted_bot_obj=NULL;
+    struct ObjRec *icon_obj_to_replace=NULL;
+    char *orig_cut_buffer=NULL;
+    int sel_ltx=selLtX, sel_lty=selLtY, sel_rbx=selRbX, sel_rby=selRbY;
+    int len=0, changed=FALSE, icons_converted_to_groups=FALSE, icon_count=0;
+ 
+    if (topSel == NULL) {
+       MsgBox(TgLoadCachedString(CSTID_NO_OBJ_SELECTED), TOOL_NAME, INFO_MB);
+       return;
+    }
+    for (sel_ptr=botSel; sel_ptr != NULL; sel_ptr=sel_ptr->prev) {
+       if (sel_ptr->obj->type == OBJ_ICON) {
+          icon_obj_to_replace = sel_ptr->obj;
+          icon_count++;
+       }
+    }
+    if (icon_count > 1) {
+       MsgBox(TgLoadString(STID_TOO_MANY_ICON_REPLACE_GRAPHIC), TOOL_NAME,
+             INFO_MB);
+       return;
+    }
+    orig_cut_buffer = (char*)FetchCutBuffer(&len);
+    if (len == 0) {
+       MsgBox(TgLoadString(STID_CUT_BUFFER_EMPTY), TOOL_NAME, INFO_MB);
+       return;
+    }
+    if (CutBufferType(orig_cut_buffer) != CBF_TGIF_OBJ) {
+       sprintf(gszMsgBox, TgLoadString(STID_CANT_REPLACE_GRAPHIC_NOT_TGIF),
+             TOOL_NAME);
+       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
+       return;
+    }
+    HighLightReverse();
+    saved_top_sel = topSel;
+    saved_bot_sel = botSel;
+    topSel = botSel = NULL;
+    UpdSelBBox();
+ 
+    if (!GetObjsFromCutBuffer(&orig_cut_buffer[1], len-1, &pasted_top_obj,
+          &pasted_bot_obj)) {
+       XFree(orig_cut_buffer);
+       topSel = saved_top_sel;
+       botSel = saved_bot_sel;
+       UpdSelBBox();
+       HighLightForward();
+       return;
+    }
+    XFree(orig_cut_buffer);
+ 
+    if (pasted_top_obj == NULL || pasted_top_obj != pasted_bot_obj) {
+       MsgBox(TgLoadString(STID_CANT_REPLACE_GRAPHIC_TOO_MANY), TOOL_NAME,
+             INFO_MB);
+       topSel = saved_top_sel;
+       botSel = saved_bot_sel;
+       UpdSelBBox();
+       HighLightForward();
+       return;
+    }
+    if (pasted_top_obj->type == OBJ_SYM || pasted_top_obj->type == OBJ_ICON ||
+          pasted_top_obj->type == OBJ_PIN) {
+       pasted_top_obj->type = OBJ_GROUP;
+    }
+    DelAllAttrs(pasted_top_obj->fattr);
+ 
+    topSel = saved_top_sel;
+    botSel = saved_bot_sel;
+    UpdSelBBox();
+ 
+    StartCompositeCmd();
+    for (sel_ptr=botSel; sel_ptr != NULL; sel_ptr=prev_sel) {
+       struct ObjRec *obj_ptr=sel_ptr->obj, *new_obj_ptr=NULL;
+       int convert_to_group=TRUE;
+ 
+       prev_sel = sel_ptr->prev;
+       if (obj_ptr->type == OBJ_TEXT) continue;
+ 
+       if (obj_ptr->type == OBJ_ICON && obj_ptr == icon_obj_to_replace) {
+          switch (MsgBox(TgLoadString(STID_Q_CVT_ICON_TO_GRP_IN_REPLACE),
+                TOOL_NAME, YNC_MB)) {
+          case MB_ID_YES: break;
+          case MB_ID_NO: convert_to_group = FALSE; break;
+          case MB_ID_CANCEL: continue;
+          }
+       }
+       changed = TRUE;
+ 
+       PrepareToReplaceAnObj(obj_ptr);
+ 
+       new_obj_ptr = DupObj(pasted_top_obj);
+       MoveObj(new_obj_ptr, obj_ptr->obbox.ltx-new_obj_ptr->obbox.ltx,
+             obj_ptr->obbox.lty-new_obj_ptr->obbox.lty);
+ 
+       new_obj_ptr->prev = obj_ptr->prev;
+       new_obj_ptr->next = obj_ptr->next;
+       new_obj_ptr->fattr = obj_ptr->fattr;
+       new_obj_ptr->lattr = obj_ptr->lattr;
+ 
+       obj_ptr->fattr = obj_ptr->lattr = NULL;
+       UnlinkObj(obj_ptr);
+ 
+       if (obj_ptr->type == OBJ_SYM) new_obj_ptr->type = OBJ_SYM;
+ 
+       UpdAttrOwner(new_obj_ptr->fattr, new_obj_ptr);
+       if (new_obj_ptr->prev == NULL) {
+          curPage->top = topObj = new_obj_ptr;
+       } else {
+          new_obj_ptr->prev->next = new_obj_ptr;
+       }
+       if (new_obj_ptr->next == NULL) {
+          curPage->bot = botObj = new_obj_ptr;
+       } else {
+          new_obj_ptr->next->prev = new_obj_ptr;
+       }
+       AdjObjBBox(new_obj_ptr);
+       ExpandCurSelBBoxes(new_obj_ptr);
+ 
+       sel_ptr->obj = new_obj_ptr;
+       if (convert_to_group) {
+          icons_converted_to_groups = TRUE;
+          UnInheritAllAttrs(new_obj_ptr);
+       } else {
+          struct SelRec *tmp_sel=NULL;
+ 
+          saved_top_sel = topSel;
+          saved_bot_sel = botSel;
+          topSel = botSel = tmp_sel = SelectThisObject(new_obj_ptr);
+          UpdSelBBox();
+          MakeIconic(NULL, FALSE);
+          topSel = saved_top_sel;
+          botSel = saved_bot_sel;
+          UpdSelBBox();
+          free(tmp_sel);
+       }
+       RecordReplaceAnObj(new_obj_ptr);
+       FreeObj(obj_ptr);
+    }
+    EndCompositeCmd();
+ 
+    if (changed) {
+       UpdSelBBox();
+       RedrawAreas(botObj, sel_ltx-GRID_ABS_SIZE(1), sel_lty-GRID_ABS_SIZE(1),
+             sel_rbx+GRID_ABS_SIZE(1), sel_rby+GRID_ABS_SIZE(1),
+             selLtX-GRID_ABS_SIZE(1), selLtY-GRID_ABS_SIZE(1),
+             selRbX+GRID_ABS_SIZE(1), selRbY+GRID_ABS_SIZE(1));
+       SetFileModified(TRUE);
+       justDupped = FALSE;
+       if (icons_converted_to_groups) {
+          MsgBox(TgLoadString(STID_REPLACE_GRAPHIC_ICON_TO_GROUP), TOOL_NAME,
+                INFO_MB);
+       } else {
+          Msg(TgLoadString(STID_REPLACE_GRAPHIC_DONE));
+       }
+    }
+    HighLightForward();
  }
*** dialog.c.orig	Tue Apr 18 17:12:36 2000
--- dialog.c	Tue Apr 18 17:12:36 2000
***************
*** 1150,1153 ****
--- 1150,1154 ----
        return rc;
     }
+    EndMeasureTooltip(FALSE);
     while (looping) {
        XEvent input, ev;
***************
*** 1362,1365 ****
--- 1363,1367 ----
        sprintf(real_msg, "%s\n\n%s", Message, Comment);
     }
+    EndMeasureTooltip(FALSE);
     rc = DoDialog(real_msg, ReturnStr);
     free(real_msg);
*** drawing.c.orig	Tue Apr 18 17:12:37 2000
--- drawing.c	Tue Apr 18 17:12:37 2000
***************
*** 1992,1996 ****
        case 'g': /*^#g*/ ToggleSnapOn(); break;
        case 'h': /*^#h*/ HideAllAttrs(); break;
!       case 'i': /*^#i*/ MakeIconic(NULL); break;
        case 'j': /*^#j*/ UnMakeIconic(); break;
        case 'k': /*^#k*/ ToggleColorPostScript(); break;
--- 1992,1996 ----
        case 'g': /*^#g*/ ToggleSnapOn(); break;
        case 'h': /*^#h*/ HideAllAttrs(); break;
!       case 'i': /*^#i*/ MakeIconic(NULL, TRUE); break;
        case 'j': /*^#j*/ UnMakeIconic(); break;
        case 'k': /*^#k*/ ToggleColorPostScript(); break;
***************
*** 2509,2512 ****
--- 2509,2516 ----
              EditIndexedAttrInEditor(atoi(args));
           }
+       } else if (strcmp(name, "GetProperty()") == 0) {
+          if (args != NULL) {
+             GetProperty(atoi(args));
+          }
        } else if (strcmp(name, "SetHtmlExportTemplate()") == 0) {
           SetHtmlExportTemplate();
***************
*** 2523,2526 ****
--- 2527,2534 ----
        } else if (strcmp(name, "MoveEditTextBox()") == 0) {
           MoveEditTextBox();
+       } else if (strcmp(name, "ReplaceGraphic()") == 0) {
+          ReplaceGraphic();
+       } else if (strcmp(name, "ToggleShowMeasurementInTooltip()") == 0) {
+          ToggleShowMeasurementInTooltip();
        }
     }
***************
*** 2902,2905 ****
--- 2910,2914 ----
           gpEditAttrInEditorAttrInfo->num_attrs,
           gpEditAttrInEditorAttrInfo->attr_strings,
+          gpEditAttrInEditorAttrInfo->status_strings,
           gpEditAttrInEditorAttrInfo->fore_colors);
     if (menu != NULL) {
***************
*** 2914,2917 ****
--- 2923,2966 ----
  }
  
+ void GetProperty(index)
+    int index;
+ {
+    DoGetProperty(index);
+ }
+ 
+ TgMenu *CreateGetPropertyMenu(parent_menu, X, Y, menu_info,
+       status_str_xlated)
+    TgMenu *parent_menu;
+    int X, Y;
+    TgMenuInfo *menu_info;
+    int status_str_xlated; /* ignored, always 0 */
+ {
+    TgMenu *menu=NULL;
+ 
+    if (topSel == NULL || topSel != botSel) return NULL;
+ 
+    FreeEditAttrInfo(gpEditAttrInEditorAttrInfo);
+    gpEditAttrInEditorAttrInfo = NULL;
+ 
+    gpEditAttrInEditorAttrInfo = CreateGetPropertyInfo();
+ 
+    if (gpEditAttrInEditorAttrInfo == NULL) return NULL;
+ 
+    menu = CreateAttrMenu(parent_menu, X, Y,
+          gpEditAttrInEditorAttrInfo->num_attrs,
+          gpEditAttrInEditorAttrInfo->attr_strings,
+          gpEditAttrInEditorAttrInfo->status_strings,
+          gpEditAttrInEditorAttrInfo->fore_colors);
+    if (menu != NULL) {
+       int i=0, num_items=menu->num_items;
+       TgMenuItem *menuitems=menu->menuitems;
+ 
+       for (i=0; i < num_items; i++) {
+          menuitems[i].cmdid = CMDID_GETPROPERTY;
+       }
+    }
+    return menu;
+ }
+ 
  int RefreshContextMenu(menu)
     TgMenu *menu;
***************
*** 2921,2924 ****
--- 2970,2977 ----
     if (topSel == NULL || topSel != botSel) return FALSE;
  
+    /* ImageProc submenu */
+    ok &= TgEnableMenuItemById(menu, MENU_IMAGEPROC,
+          topSel->obj->type == OBJ_XPM);
+ 
     /* Edit Attribute In Editor */
     ok &= TgEnableMenuItemBySubMenuInfoPtr(menu, &editAttrInEditorMenuInfo,
***************
*** 2925,2928 ****
--- 2978,2986 ----
           topSel->obj->fattr != NULL);
  
+    /* Get Property */
+    ok &= TgEnableMenuItemBySubMenuInfoPtr(menu, &getPropertyMenuInfo,
+          !(topSel->obj->type == OBJ_XPM || (topSel->obj->type == OBJ_XBM &&
+          topSel->obj->detail.xbm->real_type==XBM_EPS)));
+ 
     return ok;
  }
***************
*** 3300,3303 ****
--- 3358,3364 ----
        ShowCurChoiceMouseStatus(curChoice, 0, FALSE);
        return INVALID;
+    } else if (input->type == LeaveNotify) {
+       EndMeasureTooltip(FALSE);
+       return INVALID;
     } else if (input->type == MotionNotify) {
        HandleMotionInDrawWindow(input);
***************
*** 3308,3311 ****
--- 3369,3373 ----
        int rc=INVALID;
  
+       EndMeasureTooltip(FALSE);
        if (HandlePressInDrawWindow(input, &rc)) {
           return rc;
*** edit.c.orig	Tue Apr 18 17:12:38 2000
--- edit.c	Tue Apr 18 17:12:38 2000
***************
*** 3788,3808 ****
              UnlinkObj(obj_ptr);
              CopyAndUpdateAttrs(new_obj_ptr, obj_ptr);
  
-             if (new_obj_ptr->bbox.ltx < selLtX) selLtX = new_obj_ptr->bbox.ltx;
-             if (new_obj_ptr->bbox.lty < selLtY) selLtY = new_obj_ptr->bbox.lty;
-             if (new_obj_ptr->bbox.rbx < selRbX) selRbX = new_obj_ptr->bbox.rbx;
-             if (new_obj_ptr->bbox.rby < selRbY) selRbY = new_obj_ptr->bbox.rby;
-             if (new_obj_ptr->obbox.ltx < selObjLtX) {
-                selObjLtX = new_obj_ptr->obbox.ltx;
-             }
-             if (new_obj_ptr->obbox.lty < selObjLtY) {
-                selObjLtY = new_obj_ptr->obbox.lty;
-             }
-             if (new_obj_ptr->obbox.rbx < selObjRbX) {
-                selObjRbX = new_obj_ptr->obbox.rbx;
-             }
-             if (new_obj_ptr->obbox.rby < selObjRbY) {
-                selObjRbY = new_obj_ptr->obbox.rby;
-             }
              sel_ptr->obj = new_obj_ptr;
              AssignNewObjIds(new_obj_ptr);
--- 3788,3793 ----
              UnlinkObj(obj_ptr);
              CopyAndUpdateAttrs(new_obj_ptr, obj_ptr);
+             ExpandCurSelBBoxes(new_obj_ptr);
  
              sel_ptr->obj = new_obj_ptr;
              AssignNewObjIds(new_obj_ptr);
*** exec.c.orig	Tue Apr 18 17:12:40 2000
--- exec.c	Tue Apr 18 17:12:40 2000
***************
*** 6754,6758 ****
        return FALSE;
     }
!    if (!MakeIconic(sym_path)) {
        return FALSE;
     }
--- 6754,6758 ----
        return FALSE;
     }
!    if (!MakeIconic(sym_path, TRUE)) {
        return FALSE;
     }
*** grid.c.orig	Tue Apr 18 17:12:42 2000
--- grid.c	Tue Apr 18 17:12:42 2000
***************
*** 1347,1350 ****
--- 1347,1356 ----
     ok &= TgSetMenuItemCheckById(menu, CMDID_TOGGLESHOWMEASUREMENT,
           showMeasurement);
+    if (!showMeasurement) {
+       ok &= TgEnableMenuItemById(menu, CMDID_TOGGLESHOWMEASUREMENTINTT, FALSE);
+    }
+    /* ShowMeasurementInTooltip */
+    ok &= TgSetMenuItemCheckById(menu, CMDID_TOGGLESHOWMEASUREMENTINTT,
+          showMeasurementInTooltip);
     /* ShowMenubar */
     ok &= TgSetMenuItemCheckById(menu, CMDID_TOGGLESHOWMENUBAR, !noMenubar);
*** mainloop.c.orig	Tue Apr 18 17:12:43 2000
--- mainloop.c	Tue Apr 18 17:12:43 2000
***************
*** 344,347 ****
--- 344,348 ----
     CleanUpHtml();
     CleanUpRecentFiles();
+    CleanUpMeasureTooltip();
  
     if (iconWindowCreated) {
*** menuinfo.c.orig	Tue Apr 18 17:12:44 2000
--- menuinfo.c	Tue Apr 18 17:12:44 2000
***************
*** 1029,1032 ****
--- 1029,1035 ----
     { N_("Show Measurement"), NULL,
       N_("Show cursor measurements"), NULL, CMDID_TOGGLESHOWMEASUREMENT },
+    { N_("Show Measurement in Tooltip"), NULL,
+      N_("Show cursor measurements in tooltip"), NULL,
+      CMDID_TOGGLESHOWMEASUREMENTINTT },
     { N_("Set Measure Unit..."), NULL, N_("Set the unit of measurements"), NULL,
       CMDID_SETMEASUREUNIT },
***************
*** 1358,1361 ****
--- 1361,1367 ----
       N_("Save symbol file in a library path within the current domain"), NULL,
       CMDID_SAVESYMINLIBRARY },
+    { N_("Replace Graphic"), NULL,
+      N_("Replace the graphical part of selected objects by the graphical object in the cut buffer"), NULL,
+      CMDID_REPLACEGRAPHIC },
     { TGMUITEM_SEPARATOR, NULL, NULL, NULL, INVALID },
     { N_("Domain"), TGMUITEM_SUBMENU,
***************
*** 1402,1405 ****
--- 1408,1413 ----
                                        CreateEditAttrInEditorMenu };
  
+ TgMenuInfo getPropertyMenuInfo={ TGMUTYPE_TEXT, NULL, CreateGetPropertyMenu };
+ 
  static TgMenuItemInfo baseContextMenuItemInfo[] = {
     { N_("Mode"), TGMUITEM_PINNABLESUBMENU, N_("Mode Menu"), &modeMenuInfo,
***************
*** 1415,1418 ****
--- 1423,1428 ----
     { N_("Properties"), TGMUITEM_PINNABLESUBMENU,
       N_("Properties Menu"), &propertiesMenuInfo, MENU_PROPERTIES },
+    { N_("Image Proc"), TGMUITEM_PINNABLESUBMENU,
+      N_("ImageProc Menu"), &imageProcMenuInfo, MENU_IMAGEPROC },
     { TGMUITEM_SEPARATOR, NULL, NULL, NULL, INVALID },
     { N_("Edit Attribute In Editor"), TGMUITEM_SUBMENU,
***************
*** 1419,1422 ****
--- 1429,1434 ----
       N_("Edit attribute in editor submenu >>>"), &editAttrInEditorMenuInfo,
       INVALID },
+    { N_("Get Property"), TGMUITEM_SUBMENU,
+      N_("Get property submenu >>>"), &getPropertyMenuInfo, INVALID },
     { NULL, NULL, NULL, NULL, INVALID }
  };
*** nkf.c.orig	Tue Apr 18 17:12:45 2000
--- nkf.c	Tue Apr 18 17:12:45 2000
***************
*** 1500,1504 ****
  {
      int             i;
!     if (c > '@')
  	if (c < '[')
  	    i = c - 'A';	/* A..Z 0-25 */
--- 1500,1504 ----
  {
      int             i;
!     if (c > '@') {
  	if (c < '[')
  	    i = c - 'A';	/* A..Z 0-25 */
***************
*** 1505,1509 ****
  	else
  	    i = c - 'G' /* - 'a' + 26 */ ;	/* a..z 26-51 */
!     else if (c > '/')
  	i = c - '0' + '4' /* - '0' + 52 */ ;	/* 0..9 52-61 */
      else if (c == '+')
--- 1505,1509 ----
  	else
  	    i = c - 'G' /* - 'a' + 26 */ ;	/* a..z 26-51 */
!     } else if (c > '/')
  	i = c - '0' + '4' /* - '0' + 52 */ ;	/* 0..9 52-61 */
      else if (c == '+')
*** ruler.c.orig	Tue Apr 18 17:12:46 2000
--- ruler.c	Tue Apr 18 17:12:46 2000
***************
*** 48,51 ****
--- 48,52 ----
  #include "strtbl.e"
  #include "util.e"
+ #include "xpixmap.e"
  
  #define INCH_H (RULER_W-2)
***************
*** 59,64 ****
--- 60,68 ----
  
  int showMeasurement=FALSE;
+ int showMeasurementInTooltip=TRUE;
  int showCrossHair=FALSE;
  
+ static int measureTooltipVerbose=FALSE;
+ 
  static float gfPixelsPerUnit=(float)1.0;
  static float gfNumUnits=(float)1.0;
***************
*** 476,481 ****
        PixelToMeasurementUnit(y_buf, ABS_Y(oldYOff));
        sprintf(buf, "[%s,%s]", x_buf, y_buf);
!       XDrawString(mainDisplay, hRuleWindow, revDefaultGC, 8, 2+defaultFontAsc,
!             buf, strlen(buf));
        hRulerJustRedrawn = TRUE;
     }
--- 480,489 ----
        PixelToMeasurementUnit(y_buf, ABS_Y(oldYOff));
        sprintf(buf, "[%s,%s]", x_buf, y_buf);
!       if (showMeasurementInTooltip) {
!          SetMeasureTooltip(buf);
!       } else {
!          XDrawString(mainDisplay, hRuleWindow, revDefaultGC,
!                8, 2+defaultFontAsc, buf, strlen(buf));
!       }
        hRulerJustRedrawn = TRUE;
     }
***************
*** 510,515 ****
           sprintf(buf, "[%s,%s]", x_buf, y_buf);
        }
!       XDrawString(mainDisplay, hRuleWindow, revDefaultGC, 8, 2+defaultFontAsc,
!             buf, strlen(buf));
     }
     DrawHRuleTick(XOff-1);
--- 518,527 ----
           sprintf(buf, "[%s,%s]", x_buf, y_buf);
        }
!       if (showMeasurementInTooltip) {
!          /* Do nothing here because no XOR needed */
!       } else {
!          XDrawString(mainDisplay, hRuleWindow, revDefaultGC,
!                8, 2+defaultFontAsc, buf, strlen(buf));
!       }
     }
     DrawHRuleTick(XOff-1);
***************
*** 526,531 ****
        PixelToMeasurementUnit(y_buf, ABS_Y(YOff));
        sprintf(buf, "[%s,%s]", x_buf, y_buf);
!       XDrawString(mainDisplay, hRuleWindow, revDefaultGC, 8, 2+defaultFontAsc,
!             buf, strlen(buf));
     }
     oldXOff = XOff;
--- 538,558 ----
        PixelToMeasurementUnit(y_buf, ABS_Y(YOff));
        sprintf(buf, "[%s,%s]", x_buf, y_buf);
!       if (showMeasurementInTooltip) {
!          SetMeasureTooltip(buf);
!       } else {
!          XDrawString(mainDisplay, hRuleWindow, revDefaultGC,
!                8, 2+defaultFontAsc, buf, strlen(buf));
!       }
!    } else if (showMeasurement && showMeasurementInTooltip &&
!          measureTooltipVerbose) {
!       switch (curChoice) {
!       case NOTHING:
!       case DRAWPOLY:
!       case DRAWPOLYGON:
!       case VERTEXMODE:
!          DoIntervalMeasureTooltip(frozenXOff, frozenYOff, XOff, YOff,
!                (frozenXOff+XOff)>>1, (frozenYOff+YOff)>>1);
!          break;
!       }
     }
     oldXOff = XOff;
***************
*** 611,614 ****
--- 638,644 ----
  void FreezeMarkRulerText()
  {
+    if (!freezeMarkRulerText) {
+       EndMeasureTooltip(FALSE);
+    }
     freezeMarkRulerText = TRUE;
     frozenXOff = oldXOff;
***************
*** 665,668 ****
--- 695,701 ----
              ZOOMED_SIZE(drawWinW), oldRbY);
     }
+    if (showMeasurement && showMeasurementInTooltip && measureTooltipVerbose) {
+       DoIntervalMeasureTooltip(oldLtX, oldLtY, oldRbX, oldRbY, oldMdX, oldMdY);
+    }
  }
  
***************
*** 723,727 ****
     MarkRulers(XOff, YOff);
     FreezeMarkRulerText();
!    if (Str != NULL && *Str != '\0') {
        int x=(ExtraSpace ? XOff+18 : XOff+4), y=YOff+defaultFontAsc;
        char *c_ptr=strchr(Str, '\n'), *line=Str;
--- 756,766 ----
     MarkRulers(XOff, YOff);
     FreezeMarkRulerText();
!    if (Str == NULL || *Str == '\0') return;
! 
!    if (showMeasurementInTooltip) {
!       if (!measureTooltipVerbose) {
!          StartMeasureTooltip(Str);
!       }
!    } else {
        int x=(ExtraSpace ? XOff+18 : XOff+4), y=YOff+defaultFontAsc;
        char *c_ptr=strchr(Str, '\n'), *line=Str;
***************
*** 748,752 ****
  {
     if (!showMeasurement) return;
!    if (Str != NULL && *Str != '\0') {
        int x=(ExtraSpace ? XOff+18 : XOff+4), y=YOff+defaultFontAsc;
        char *c_ptr=strchr(Str, '\n'), *line=Str;
--- 787,806 ----
  {
     if (!showMeasurement) return;
!    if (Str == NULL || *Str == '\0') return;
! 
!    if (showMeasurementInTooltip) {
!       if (measureTooltipVerbose) {
!          switch (curChoice) {
!          case DRAWARC:
!          case DRAWEDGEARC:
!          case FREEHAND:
!          case ROTATEMODE:
!             SetMeasureTooltip(Str);
!             break;
!          }
!       } else {
!          SetMeasureTooltip(Str);
!       }
!    } else {
        int x=(ExtraSpace ? XOff+18 : XOff+4), y=YOff+defaultFontAsc;
        char *c_ptr=strchr(Str, '\n'), *line=Str;
***************
*** 773,777 ****
  {
     if (!showMeasurement) return;
!    if (Str != NULL && *Str != '\0') {
        int x=(ExtraSpace ? XOff+18 : XOff+4), y=YOff+defaultFontAsc;
        char *c_ptr=strchr(Str, '\n'), *line=Str;
--- 827,837 ----
  {
     if (!showMeasurement) return;
!    if (Str == NULL || *Str == '\0') return;
! 
!    if (showMeasurementInTooltip) {
!       if (!measureTooltipVerbose) {
!          StartMeasureTooltip(Str);
!       }
!    } else {
        int x=(ExtraSpace ? XOff+18 : XOff+4), y=YOff+defaultFontAsc;
        char *c_ptr=strchr(Str, '\n'), *line=Str;
***************
*** 803,807 ****
        Msg(TgLoadString(STID_SHOW_MEASUREMENT_DISABLED));
     }
-    UpdatePinnedMenu(MENU_LAYOUT);
  }
  
--- 863,1210 ----
        Msg(TgLoadString(STID_SHOW_MEASUREMENT_DISABLED));
     }
  }
  
+ void ToggleShowMeasurementInTooltip()
+ {
+    showMeasurementInTooltip = !showMeasurementInTooltip;
+    RedrawRulers();
+    if (showMeasurementInTooltip) {
+       Msg(TgLoadString(STID_SHOW_MEASUREMENT_IN_TT_ENAB));
+    } else {
+       Msg(TgLoadString(STID_SHOW_MEASUREMENT_IN_TT_DISB));
+    }
+    EndMeasureTooltip(TRUE);
+ }
+ 
+ /* ------------------- Measure Tooltip Related Routines ------------------- */
+ 
+ /*
+  * Some code in the rest of this file is based on the contributed code
+  *       by Raphael Dechenaux <raph_d@club-internet.fr>.
+  */
+ 
+ typedef struct tagMeasureTooltipInfo {
+    int ltx, lty, w, h; /* this is for the window */
+    int bbox_w, bbox_h; /* this is for the text */
+    int x_padding, y_padding; /* padding around the text */
+    Window win;
+    GC gc;
+    /* configuration parameters -- how to display */
+    int x_follow_mouse, y_follow_mouse, position_x, position_y;
+ } MeasureTooltipInfo;
+ 
+ static MeasureTooltipInfo gmti;
+ 
+ static Pixmap tooltipBgPixmap=None;
+ 
+ static
+ void CalcMeasureTooltipPosition()
+ {
+    if (gmti.x_follow_mouse || gmti.y_follow_mouse) {
+       Window root_win=None, child_win=None;
+       unsigned int status;
+       int root_x=0, root_y=0;
+ 
+       XQueryPointer(mainDisplay, rootWindow, &root_win, &child_win,
+             &root_x, &root_y, &gmti.ltx, &gmti.lty, &status);
+       if (gmti.x_follow_mouse) gmti.ltx += 16;
+       if (gmti.y_follow_mouse) gmti.lty += 16;
+       if (gmti.x_follow_mouse && gmti.y_follow_mouse) {
+          return;
+       }
+    }
+    if (!gmti.x_follow_mouse) {
+       int dpy_w=DisplayWidth(mainDisplay,mainScreen);
+ 
+       switch (gmti.position_x) {
+       case ALIGN_L: gmti.ltx = 0; break;
+       case ALIGN_C: gmti.ltx = ((dpy_w-gmti.bbox_w-gmti.x_padding)>>1); break;
+       case ALIGN_R: gmti.ltx = (dpy_w-gmti.bbox_w-(gmti.x_padding<<1)); break;
+       default: gmti.ltx = 0; break;
+       }
+    }
+    if (!gmti.y_follow_mouse) {
+       int dpy_h=DisplayHeight(mainDisplay,mainScreen);
+ 
+       switch (gmti.position_y) {
+       case ALIGN_T: gmti.lty = 0; break;
+       case ALIGN_M: gmti.lty = ((dpy_h-gmti.bbox_h-gmti.y_padding)>>1); break;
+       case ALIGN_B: gmti.lty = (dpy_h-gmti.bbox_h-(gmti.y_padding<<1)); break;
+       default: gmti.lty = 0; break;
+       }
+    }
+ }
+ 
+ static
+ void SetMeasureTooltipBBox(msg)
+    char *msg;
+ {
+    int bbox_w=0, bbox_h=0;
+    char *psz=NULL, *line=NULL;
+ 
+    bbox_h = ((msgFontSet==NULL && msgFontPtr==NULL) ? defaultFontHeight :
+          msgFontHeight);
+    line = msg;
+    psz = strchr(line, '\n');
+    while (line != NULL) {
+       char saved_ch='\0';
+       int len=0, w=0;
+ 
+       if (psz != NULL) {
+          saved_ch = (*psz);
+          *psz = '\0';
+       }
+       len = strlen(line);
+       if (msgFontSet == NULL && msgFontPtr == NULL) {
+          w = (defaultFontWidth*len);
+       } else {
+          w = MsgTextWidth(msgFontPtr, line, len);
+       }
+       if (w > bbox_w) bbox_w = w;
+ 
+       if (psz == NULL) {
+          break;
+       }
+       *psz = saved_ch;
+       line = &psz[1];
+       psz = strchr(line, '\n');
+ 
+       bbox_h += ((msgFontSet==NULL && msgFontPtr==NULL) ? defaultFontHeight :
+             msgFontHeight);
+    }
+    gmti.bbox_w = bbox_w;
+    gmti.bbox_h = bbox_h;
+    gmti.w = bbox_w+((gmti.x_padding)<<1);
+    gmti.h = bbox_h+((gmti.y_padding)<<1);
+ 
+    CalcMeasureTooltipPosition();
+ }
+ 
+ void DoIntervalMeasureTooltip(ltx, lty, rbx, rby, mdx, mdy)
+    int ltx, lty, rbx, rby, mdx, mdy;
+ {
+    char w_buf[80], h_buf[80], buf[256];
+    char lx_buf[80], cx_buf[80], rx_buf[80];
+    char ty_buf[80], my_buf[80], by_buf[80];
+ 
+    PixelToMeasurementUnit(w_buf, ABS_SIZE(abs(rbx-ltx)));
+    PixelToMeasurementUnit(h_buf, ABS_SIZE(abs(rby-lty)));
+    PixelToMeasurementUnit(lx_buf, ABS_X(ltx < rbx ? ltx : rbx));
+    PixelToMeasurementUnit(cx_buf, ABS_X(mdx));
+    PixelToMeasurementUnit(rx_buf, ABS_X(ltx > rbx ? ltx : rbx));
+    PixelToMeasurementUnit(ty_buf, ABS_Y(lty < rby ? lty : rby));
+    PixelToMeasurementUnit(my_buf, ABS_Y(mdy));
+    PixelToMeasurementUnit(by_buf, ABS_Y(lty > rby ? lty : rby));
+    sprintf(buf, "lx=%s cx=%s rx=%s\nty=%s my=%s by=%s\nw=%s h=%s",
+          lx_buf, cx_buf, rx_buf, ty_buf, my_buf, by_buf, w_buf, h_buf);
+    SetMeasureTooltip(buf);
+ }
+ 
+ void StartMeasureTooltip(msg)
+    char *msg;
+ {
+    SetMeasureTooltip(msg);
+ }
+ 
+ void SetMeasureTooltip(msg)
+    char *msg;
+ {
+    int x=0, y=0;
+    char *psz=NULL, *line=NULL;
+ 
+    if (!showMeasurementInTooltip) return;
+ 
+    XMapWindow(mainDisplay, gmti.win);
+    XRaiseWindow(mainDisplay, gmti.win);
+ 
+    SetMeasureTooltipBBox(msg);
+    XMoveResizeWindow(mainDisplay, gmti.win, gmti.ltx, gmti.lty, gmti.w, gmti.h);
+ 
+    XClearWindow(mainDisplay, gmti.win);
+ 
+    x = gmti.x_padding;
+    y = gmti.y_padding + ((msgFontSet==NULL && msgFontPtr==NULL) ?
+          defaultFontAsc : msgFontAsc);;
+    line = msg;
+    psz = strchr(line, '\n');
+    while (line != NULL) {
+       char saved_ch='\0';
+ 
+       if (psz != NULL) {
+          saved_ch = (*psz);
+          *psz = '\0';
+       }
+       DrawMsgString(mainDisplay, gmti.win, gmti.gc, x, y, line, strlen(line));
+       if (psz == NULL) {
+          break;
+       }
+       *psz = saved_ch;
+       line = &psz[1];
+       psz = strchr(line, '\n');
+ 
+       y += ((msgFontSet==NULL && msgFontPtr==NULL) ? defaultFontHeight :
+             msgFontHeight);
+    }
+ }
+ 
+ void EndMeasureTooltip(force)
+    int force;
+ {
+    if (force || (showMeasurement && showMeasurementInTooltip)) {
+       XUnmapWindow(mainDisplay, gmti.win);
+    }
+ }
+ 
+ void CleanUpMeasureTooltip()
+ {
+    if (tooltipBgPixmap != None) {
+       XFreePixmap(mainDisplay, tooltipBgPixmap);
+       tooltipBgPixmap = None;
+    }
+    if (gmti.gc != NULL) {
+       XFreeGC(mainDisplay, gmti.gc);
+    }
+    if (gmti.win != None) {
+       XDestroyWindow(mainDisplay, gmti.win);
+    }
+    memset(&gmti, 0, sizeof(MeasureTooltipInfo));
+    showMeasurementInTooltip = TRUE;
+    gmti.win = None;
+ }
+ 
+ static
+ int CreateMeasureTooltipWindow()
+ {
+    int bg_pixel=(threeDLook ? myLtGryPixel : myBgPixel);
+    XGCValues values;
+    XWMHints wmhints;
+    XSizeHints sizehints;
+    XSetWindowAttributes win_attrs;
+ 
+    if ((gmti.win=XCreateSimpleWindow(mainDisplay, rootWindow, 0, 0, 10, 10,
+          1, myBorderPixel, bg_pixel)) == 0) {
+       return FailToCreateWindowMessage("CreateMeasureTooltipWindow()", NULL,
+             FALSE);
+    }
+    win_attrs.save_under = True;
+    win_attrs.override_redirect = True;
+    win_attrs.colormap = mainColormap;
+    XChangeWindowAttributes(mainDisplay, gmti.win,
+          CWSaveUnder | CWOverrideRedirect | CWColormap, &win_attrs);
+ 
+    wmhints.flags = InputHint | StateHint;
+    wmhints.input = True;
+    wmhints.initial_state = NormalState;
+    XSetWMHints(mainDisplay, gmti.win, &wmhints);
+ 
+    sizehints.flags = PPosition | PSize | USPosition | PMinSize | PMaxSize;
+    sizehints.x = 0;
+    sizehints.y = 0;
+    sizehints.width = sizehints.min_width = sizehints.max_width = 10;
+    sizehints.height = sizehints.min_height = sizehints.max_height = 10;
+ #ifdef NOTR4MODE
+    XSetNormalHints(mainDisplay, gmti.win, &sizehints);
+ #else
+    XSetWMNormalHints(mainDisplay, gmti.win, &sizehints);
+ #endif
+ 
+    XSetTransientForHint(mainDisplay, gmti.win, mainWindow);
+ 
+    values.foreground = myFgPixel;
+    values.background = bg_pixel;
+    values.font = (msgFontPtr==NULL ? defaultFontPtr->fid : msgFontPtr->fid);
+    gmti.gc = XCreateGC(mainDisplay, gmti.win,
+          GCForeground | GCBackground | GCFont, &values);
+    return TRUE;
+ }
+ 
+ static
+ void CreateLightYellowBackgroundPixmapForTooltip()
+ {
+    XImage *image=NULL;
+ 
+    tooltipBgPixmap = XCreatePixmap(mainDisplay, mainWindow, 2, 2, mainDepth);
+    XSetForeground(mainDisplay, xpmGC, myYellowPixel);
+    XFillRectangle(mainDisplay, tooltipBgPixmap, xpmGC, 0, 0, 2, 2);
+    XSetForeground(mainDisplay, xpmGC, myFgPixel);
+    image = XGetImage(mainDisplay, tooltipBgPixmap, 0, 0, 2, 2, AllPlanes,
+          ZPixmap);
+    XPutPixel(image, 0, 0, myWhitePixel);
+    XPutPixel(image, 1, 1, myWhitePixel);
+    XPutImage(mainDisplay, tooltipBgPixmap, xpmGC, image, 0, 0, 0, 0, 2, 2);
+    XDestroyImage(image);
+ 
+    XSetWindowBackgroundPixmap(mainDisplay, gmti.win, tooltipBgPixmap);
+ }
+ 
+ int InitMeasureTooltip()
+ {
+    char *c_ptr=NULL;
+ 
+    tooltipBgPixmap = None;
+ 
+    memset(&gmti, 0, sizeof(MeasureTooltipInfo));
+    gmti.win = None;
+    gmti.x_padding = 4;
+    gmti.y_padding = 2;
+ 
+    showMeasurementInTooltip = TRUE;
+    if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME,
+          "UseMeasureTooltip")) != NULL &&
+          UtilStrICmp(c_ptr, "false") == 0) {
+       showMeasurementInTooltip = FALSE;
+    }
+    measureTooltipVerbose = FALSE;
+    if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME,
+          "MeasureTooltipVerbose")) != NULL &&
+          UtilStrICmp(c_ptr, "true") == 0) {
+       measureTooltipVerbose = TRUE;
+    }
+    gmti.x_follow_mouse = gmti.y_follow_mouse = TRUE;
+    if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME,
+          "MeasureTooltipXFollowMouse")) != NULL &&
+          UtilStrICmp(c_ptr, "false") == 0) {
+       gmti.x_follow_mouse = FALSE;
+    }
+    if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME,
+          "MeasureTooltipYFollowMouse")) != NULL &&
+          UtilStrICmp(c_ptr, "false") == 0) {
+       gmti.y_follow_mouse = FALSE;
+    }
+    gmti.position_y = ALIGN_T;
+    if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME,
+          "MeasureTooltipVerticalPosition")) != NULL) {
+       if (UtilStrICmp(c_ptr, "top") == 0) {
+          gmti.position_y = ALIGN_T;
+       } else if (UtilStrICmp(c_ptr, "middle") == 0) {
+          gmti.position_y = ALIGN_M;
+       } else if (UtilStrICmp(c_ptr, "bottom") == 0) {
+          gmti.position_y = ALIGN_B;
+       } else {
+          fprintf(stderr, TgLoadString(STID_INVALID_XDEF_USE_ALT_STR),
+                TOOL_NAME, "MeasureTooltipVerticalPosition", c_ptr, "Top");
+          fprintf(stderr, "\n");
+       }
+    }
+    gmti.position_x = ALIGN_L;
+    if ((c_ptr=XGetDefault(mainDisplay, TOOL_NAME,
+          "MeasureTooltipHorizontalPosition")) != NULL) {
+       if (UtilStrICmp(c_ptr, "left") == 0) {
+          gmti.position_x = ALIGN_L;
+       } else if (UtilStrICmp(c_ptr, "center") == 0) {
+          gmti.position_x = ALIGN_C;
+       } else if (UtilStrICmp(c_ptr, "right") == 0) {
+          gmti.position_x = ALIGN_R;
+       } else {
+          fprintf(stderr, TgLoadString(STID_INVALID_XDEF_USE_ALT_STR),
+                TOOL_NAME, "MeasureTooltipHorizontalPosition", c_ptr, "Left");
+          fprintf(stderr, "\n");
+       }
+    }
+    if (!CreateMeasureTooltipWindow()) {
+       gmti.win = None;
+    } else if (threeDLook) {
+       CreateLightYellowBackgroundPixmapForTooltip();
+    }
+    return TRUE;
+ }
*** select.c.orig	Tue Apr 18 17:12:47 2000
--- select.c	Tue Apr 18 17:12:47 2000
***************
*** 705,708 ****
--- 705,729 ----
  }
  
+ void ExpandCurSelBBoxes(obj_ptr)
+    struct ObjRec *obj_ptr;
+ {
+    if (obj_ptr->bbox.ltx < selLtX) selLtX = obj_ptr->bbox.ltx;
+    if (obj_ptr->bbox.lty < selLtY) selLtY = obj_ptr->bbox.lty;
+    if (obj_ptr->bbox.rbx < selRbX) selRbX = obj_ptr->bbox.rbx;
+    if (obj_ptr->bbox.rby < selRbY) selRbY = obj_ptr->bbox.rby;
+    if (obj_ptr->obbox.ltx < selObjLtX) {
+       selObjLtX = obj_ptr->obbox.ltx;
+    }
+    if (obj_ptr->obbox.lty < selObjLtY) {
+       selObjLtY = obj_ptr->obbox.lty;
+    }
+    if (obj_ptr->obbox.rbx < selObjRbX) {
+       selObjRbX = obj_ptr->obbox.rbx;
+    }
+    if (obj_ptr->obbox.rby < selObjRbY) {
+       selObjRbY = obj_ptr->obbox.rby;
+    }
+ }
+ 
  static
  void SetNoLockBBox(ObjPtr)
*** setup.c.orig	Tue Apr 18 17:12:49 2000
--- setup.c	Tue Apr 18 17:12:49 2000
***************
*** 234,237 ****
--- 234,238 ----
  int	myDkGryPixel=INVALID;
  int	myVryLtPixel=INVALID;
+ int	myYellowPixel=INVALID;
  int	reverseVideo = FALSE;
  
***************
*** 1763,1766 ****
--- 1764,1768 ----
     InitHtml();
     InitRecentFiles();
+    InitMeasureTooltip();
  
  #ifdef MAPBEFORESELECT
***************
*** 1786,1790 ****
        XSelectInput(mainDisplay, drawWindow, ButtonReleaseMask |
              ButtonPressMask | PointerMotionMask | KeyPressMask |
!             KeyReleaseMask | ExposureMask | EnterWindowMask |
              PropertyChangeMask);
     } else {
--- 1788,1792 ----
        XSelectInput(mainDisplay, drawWindow, ButtonReleaseMask |
              ButtonPressMask | PointerMotionMask | KeyPressMask |
!             KeyReleaseMask | ExposureMask | EnterWindowMask | LeaveWindowMask |
              PropertyChangeMask);
     } else {
***************
*** 1817,1821 ****
        XSelectInput(mainDisplay, drawWindow, ButtonReleaseMask |
              ButtonPressMask | PointerMotionMask | KeyPressMask |
!             KeyReleaseMask | ExposureMask | EnterWindowMask |
              PropertyChangeMask);
  
--- 1819,1823 ----
        XSelectInput(mainDisplay, drawWindow, ButtonReleaseMask |
              ButtonPressMask | PointerMotionMask | KeyPressMask |
!             KeyReleaseMask | ExposureMask | EnterWindowMask | LeaveWindowMask |
              PropertyChangeMask);
  
***************
*** 1880,1884 ****
        XSelectInput(mainDisplay, drawWindow, ButtonReleaseMask |
              ButtonPressMask | PointerMotionMask | KeyPressMask |
!             KeyReleaseMask | ExposureMask | EnterWindowMask |
              PropertyChangeMask);
        XMapWindow(mainDisplay, drawWindow); 
--- 1882,1886 ----
        XSelectInput(mainDisplay, drawWindow, ButtonReleaseMask |
              ButtonPressMask | PointerMotionMask | KeyPressMask |
!             KeyReleaseMask | ExposureMask | EnterWindowMask | LeaveWindowMask |
              PropertyChangeMask);
        XMapWindow(mainDisplay, drawWindow); 
***************
*** 1913,1917 ****
        XSelectInput(mainDisplay, drawWindow, ButtonReleaseMask |
              ButtonPressMask | PointerMotionMask | KeyPressMask |
!             KeyReleaseMask | ExposureMask | EnterWindowMask |
              PropertyChangeMask);
        XMapWindow(mainDisplay, drawWindow); 
--- 1915,1919 ----
        XSelectInput(mainDisplay, drawWindow, ButtonReleaseMask |
              ButtonPressMask | PointerMotionMask | KeyPressMask |
!             KeyReleaseMask | ExposureMask | EnterWindowMask | LeaveWindowMask |
              PropertyChangeMask);
        XMapWindow(mainDisplay, drawWindow); 
*** shortcut.c.orig	Tue Apr 18 17:12:49 2000
--- shortcut.c	Tue Apr 18 17:12:50 2000
***************
*** 375,378 ****
--- 375,379 ----
     { '\0', 0, "ImportPNGFile()", 0, CMDID_IMPORTPNGFILE },
     { '\0', 0, "EditIndexedAttrInEditor()", 0, CMDID_EDITATTRINEDITOR },
+    { '\0', 0, "GetProperty()", 0, CMDID_GETPROPERTY },
     { '\0', 0, "SetHtmlExportTemplate()", 0, CMDID_SETHTMLEXPORTTEMPLATE },
     { '\0', 0, "PrintPages()", 0, CMDID_PRINTPAGES },
***************
*** 381,384 ****
--- 382,388 ----
     { '\0', 0, "OpenARecentlyUsedFile()", 0, CMDID_RECENTLYUSEDFILES },
     { '\0', 0, "MoveEditTextBox()", 0, CMDID_MOVEEDITTEXTBOX },
+    { '\0', 0, "ReplaceGraphic()", 0, CMDID_REPLACEGRAPHIC },
+    { '\0', 0, "ToggleShowMeasurementInTooltip()", 0,
+                CMDID_TOGGLESHOWMEASUREMENTINTT },
     { '\0', 0, "", 0, 0 }
  };
*** special.c.orig	Tue Apr 18 17:12:50 2000
--- special.c	Tue Apr 18 17:12:50 2000
***************
*** 662,667 ****
  }
  
! int MakeIconic(sym_path)
     char *sym_path;
  {
     char icon_name[MAXPATHLENGTH], file_name[MAXPATHLENGTH];
--- 662,668 ----
  }
  
! int MakeIconic(sym_path, record_cmd)
     char *sym_path;
+    int record_cmd;
  {
     char icon_name[MAXPATHLENGTH], file_name[MAXPATHLENGTH];
***************
*** 669,759 ****
     char sym_ext_str[MAXSTRING];
     FILE *fp=NULL;
!    int len, short_name, sym_ext_len, ltx, lty, rbx, rby;
  
!    if (topSel!=NULL && topSel==botSel) {
!       int no_name=FALSE;
! 
!       if (sym_path == NULL) {
!          *icon_name = '\0';
!          Dialog(TgLoadString(STID_ENTER_NAME_FOR_THE_ICON), NULL, icon_name);
!          len = strlen(icon_name);
!          if (*icon_name == '\0') {
!             Msg(TgLoadString(STID_NAME_NOT_SPEC_ICON_NOT_CREATE));
!             return FALSE;
!          }
!       } else {
!          strncpy(icon_name, sym_path, sizeof(icon_name)-1);
!          icon_name[sizeof(icon_name)-1] = '\0';
!          len = strlen(icon_name);
        }
!       sprintf(sym_ext_str, ".%s", SYM_FILE_EXT);
!       sym_ext_len = strlen(sym_ext_str);
  
!       if (FileNameHasExtension(icon_name, OBJ_FILE_TYPE, NULL, NULL)) {
!          MsgBox(TgLoadString(STID_CANT_SAVE_OBJ_ICON_NOT_CREATE), TOOL_NAME,
!                INFO_MB);
!          return FALSE;
!       } else if (FileNameHasExtension(icon_name, SYM_FILE_TYPE, NULL, NULL)) {
!          strcpy(icon_full_name, icon_name);
!          if ((psz=UtilStrRChr(icon_name, '.')) != NULL) {
!             *psz = '\0';
!          } else {
!             TgAssert(FALSE, TgLoadString(STID_CANT_FIND_DOT_IN_ICON_NAME_MI),
!                   NULL);
!             return FALSE;
!          }
!       } else if (FileNameHasExtension(icon_name, PIN_FILE_TYPE, NULL, NULL)) {
!          MsgBox(TgLoadString(STID_CANT_SAVE_PIN_ICON_NOT_CREATE), TOOL_NAME,
!                INFO_MB);
!          return FALSE;
        } else {
!          strcpy(icon_full_name, icon_name);
!          strcat(icon_full_name, sym_ext_str);
!       }
!       if (no_name) {
!          MsgBox(TgLoadString(STID_NO_FILE_NAME_FILE_NOT_SAVED), TOOL_NAME,
!                INFO_MB);
           return FALSE;
        }
!       if (sym_path == NULL) {
!          sprintf(file_name, "%s%c%s", curDir, DIR_SEP, icon_full_name);
!       } else {
!          strcpy(file_name, icon_full_name);
!       }
!       if (!OkayToCreateFile(file_name)) return FALSE;
!       if ((short_name=IsPrefix(bootDir, file_name, &rest))) ++rest;
  
!       if ((fp=fopen(file_name, "w")) == NULL) {
!          sprintf(gszMsgBox, TgLoadString(STID_CANT_OPEN_FOR_WRITE_ICON_CRET),
!                (short_name ? rest : file_name));
!          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
!          return FALSE;
!       }
!       if (sym_path == NULL) {
!          if (!DirInSymPath(curDir)) UpdateSymInfo();
!       }
!       sprintf(gszMsgBox, TgLoadCachedString(CSTID_CREATING_FILE_DOTS),
              (short_name ? rest : file_name));
!       Msg(gszMsgBox);
!       SetStringStatus(gszMsgBox);
  
!       ltx = selLtX; lty = selLtY; rbx = selRbX; rby = selRbY;
  
        PrepareToRecord(CMD_REPLACE, topSel, botSel, numObjSelected);
!       if (topSel->obj->type == OBJ_GROUP || topSel->obj->type == OBJ_SYM ||
!             topSel->obj->type == OBJ_ICON || topSel->obj->type == OBJ_PIN) {
!          JustMoveSelToTop();
!       } else {
!          GroupSingleObj(FALSE);
!          if (topSel->obj->fattr != NULL) {
!             Msg(TgLoadCachedString(CSTID_ATTR_PROMOTED_TO_NEW_ICON));
!          }
        }
  
!       topSel->obj->type = OBJ_SYM;
!       strcpy(topSel->obj->detail.r->s, icon_name);
!       topSel->obj->detail.r->rotate = ROTATE0;
!       topSel->obj->detail.r->flip = NO_FLIP;
!       topSel->obj->detail.r->deck_index = (-1);
  /*
   * Need to check for pins.
--- 670,764 ----
     char sym_ext_str[MAXSTRING];
     FILE *fp=NULL;
!    int len, short_name, sym_ext_len, ltx, lty, rbx, rby, no_name=FALSE;
  
!    if (topSel == NULL || topSel != botSel) {
!       MsgBox(TgLoadString(STID_SEL_ONLY_ONE_FOR_MAKEICONIC), TOOL_NAME,
!             INFO_MB);
!       return FALSE;
!    }
!    if (sym_path == NULL) {
!       *icon_name = '\0';
!       Dialog(TgLoadString(STID_ENTER_NAME_FOR_THE_ICON), NULL, icon_name);
!       len = strlen(icon_name);
!       if (*icon_name == '\0') {
!          Msg(TgLoadString(STID_NAME_NOT_SPEC_ICON_NOT_CREATE));
!          return FALSE;
        }
!    } else {
!       strncpy(icon_name, sym_path, sizeof(icon_name)-1);
!       icon_name[sizeof(icon_name)-1] = '\0';
!       len = strlen(icon_name);
!    }
!    sprintf(sym_ext_str, ".%s", SYM_FILE_EXT);
!    sym_ext_len = strlen(sym_ext_str);
  
!    if (FileNameHasExtension(icon_name, OBJ_FILE_TYPE, NULL, NULL)) {
!       MsgBox(TgLoadString(STID_CANT_SAVE_OBJ_ICON_NOT_CREATE), TOOL_NAME,
!             INFO_MB);
!       return FALSE;
!    } else if (FileNameHasExtension(icon_name, SYM_FILE_TYPE, NULL, NULL)) {
!       strcpy(icon_full_name, icon_name);
!       if ((psz=UtilStrRChr(icon_name, '.')) != NULL) {
!          *psz = '\0';
        } else {
!          TgAssert(FALSE, TgLoadString(STID_CANT_FIND_DOT_IN_ICON_NAME_MI),
!                NULL);
           return FALSE;
        }
!    } else if (FileNameHasExtension(icon_name, PIN_FILE_TYPE, NULL, NULL)) {
!       MsgBox(TgLoadString(STID_CANT_SAVE_PIN_ICON_NOT_CREATE), TOOL_NAME,
!             INFO_MB);
!       return FALSE;
!    } else {
!       strcpy(icon_full_name, icon_name);
!       strcat(icon_full_name, sym_ext_str);
!    }
!    if (no_name) {
!       MsgBox(TgLoadString(STID_NO_FILE_NAME_FILE_NOT_SAVED), TOOL_NAME,
!             INFO_MB);
!       return FALSE;
!    }
!    if (sym_path == NULL) {
!       sprintf(file_name, "%s%c%s", curDir, DIR_SEP, icon_full_name);
!    } else {
!       strcpy(file_name, icon_full_name);
!    }
!    if (!OkayToCreateFile(file_name)) return FALSE;
!    if ((short_name=IsPrefix(bootDir, file_name, &rest))) ++rest;
  
!    if ((fp=fopen(file_name, "w")) == NULL) {
!       sprintf(gszMsgBox, TgLoadString(STID_CANT_OPEN_FOR_WRITE_ICON_CRET),
              (short_name ? rest : file_name));
!       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
!       return FALSE;
!    }
!    if (sym_path == NULL) {
!       if (!DirInSymPath(curDir)) UpdateSymInfo();
!    }
!    sprintf(gszMsgBox, TgLoadCachedString(CSTID_CREATING_FILE_DOTS),
!          (short_name ? rest : file_name));
!    Msg(gszMsgBox);
!    SetStringStatus(gszMsgBox);
  
!    ltx = selLtX; lty = selLtY; rbx = selRbX; rby = selRbY;
  
+    if (record_cmd) {
        PrepareToRecord(CMD_REPLACE, topSel, botSel, numObjSelected);
!    }
!    if (topSel->obj->type == OBJ_GROUP || topSel->obj->type == OBJ_SYM ||
!          topSel->obj->type == OBJ_ICON || topSel->obj->type == OBJ_PIN) {
!       JustMoveSelToTop();
!    } else {
!       GroupSingleObj(FALSE);
!       if (topSel->obj->fattr != NULL) {
!          Msg(TgLoadCachedString(CSTID_ATTR_PROMOTED_TO_NEW_ICON));
        }
+    }
  
!    topSel->obj->type = OBJ_SYM;
!    strcpy(topSel->obj->detail.r->s, icon_name);
!    topSel->obj->detail.r->rotate = ROTATE0;
!    topSel->obj->detail.r->flip = NO_FLIP;
!    topSel->obj->detail.r->deck_index = (-1);
  /*
   * Need to check for pins.
***************
*** 760,788 ****
   * Need to handle the case where connection objects need to be dupped!
   */
!       topSel->obj->detail.r->pin_connected = 0;
!       topSel->obj->detail.r->first_conn = topSel->obj->detail.r->last_conn =
!             NULL;
  
        writeFileFailed = FALSE;
!       Save(fp, topSel->obj, 0, 1);
  
!       if (writeFileFailed) {
!          writeFileFailed = FALSE;
!          FailToWriteFileMessage(file_name);
!          MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
!          unlink(file_name);
!       } else {
!          sprintf(gszMsgBox, TgLoadCachedString(CSTID_NAMED_FILE_CREATED),
!                (short_name ? rest : file_name));
!          Msg(gszMsgBox);
!       }
!       fclose(fp);
! 
        HighLightReverse();
!       topSel->obj->type = OBJ_ICON;
!       topSel->obj->id = objId++;
!       Msg(TgLoadString(STID_SEL_OBJ_IS_NOW_ICONIC));
!       AdjObjBBox(topSel->obj);
!       UpdSelBBox();
        RecordCmd(CMD_REPLACE, NULL, topSel, botSel, numObjSelected);
        ltx = min(ltx,selLtX); lty = min(lty,selLtY);
--- 765,796 ----
   * Need to handle the case where connection objects need to be dupped!
   */
!    topSel->obj->detail.r->pin_connected = 0;
!    topSel->obj->detail.r->first_conn = topSel->obj->detail.r->last_conn =
!          NULL;
  
+    writeFileFailed = FALSE;
+    Save(fp, topSel->obj, 0, 1);
+ 
+    if (writeFileFailed) {
        writeFileFailed = FALSE;
!       FailToWriteFileMessage(file_name);
!       MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
!       unlink(file_name);
!    } else {
!       sprintf(gszMsgBox, TgLoadCachedString(CSTID_NAMED_FILE_CREATED),
!             (short_name ? rest : file_name));
!       Msg(gszMsgBox);
!    }
!    fclose(fp);
  
!    if (record_cmd) {
        HighLightReverse();
!    }
!    topSel->obj->type = OBJ_ICON;
!    topSel->obj->id = objId++;
!    Msg(TgLoadString(STID_SEL_OBJ_IS_NOW_ICONIC));
!    AdjObjBBox(topSel->obj);
!    UpdSelBBox();
!    if (record_cmd) {
        RecordCmd(CMD_REPLACE, NULL, topSel, botSel, numObjSelected);
        ltx = min(ltx,selLtX); lty = min(lty,selLtY);
***************
*** 793,800 ****
        SetFileModified(TRUE);
        justDupped = FALSE;
-       return TRUE;
     }
!    MsgBox(TgLoadString(STID_SEL_ONLY_ONE_FOR_MAKEICONIC), TOOL_NAME, INFO_MB);
!    return FALSE;
  }
  
--- 801,806 ----
        SetFileModified(TRUE);
        justDupped = FALSE;
     }
!    return TRUE;
  }
  
*** strtbl.c.orig	Tue Apr 18 17:12:51 2000
--- strtbl.c	Tue Apr 18 17:12:52 2000
***************
*** 471,474 ****
--- 471,478 ----
     /* CSTID_START_MOVE_EDIT_TEXT_BOX */
     N_("Start moving the edit text box"),
+    /* CSTID_EDIT_ATTR_IN_EDITOR */
+    N_("Edit the value of the '%s' attribute in a text editor"),
+    /* CSTID_GET_NAMED_PROP_FROM_SEL_OBJ */
+    N_("Get the current '%s' property from the selected object"),
     NULL
  };
***************
*** 3105,3109 ****
     N_("Drag the edit text box to move it around..."),
     /* STID_EXCEED_BUF_SIZE_LIMIT_IN_WB */
!    N_("Error: There's a buffer size limitation of %1d bytes in the current implementation of the whiteboard.  The buffer size requirement (%1d bytes) for the operation you just performed has exceeded this limit.\n\nIn order to keep the whiteboard running, the operation in question is cancelled."),
     NULL
  };
--- 3109,3129 ----
     N_("Drag the edit text box to move it around..."),
     /* STID_EXCEED_BUF_SIZE_LIMIT_IN_WB */
!    N_("Error: There's a buffer size limitation of %1d bytes in the current implementation of the whiteboard.  The buffer size requirement (%1d bytes) for the operation you just performed has exceeded this limit.\n\nIn order to keep the whiteboard running, the operation in question is canceled."),
!    /* STID_CANT_REPLACE_GRAPHIC_NOT_TGIF */
!    N_("Cannot replace graphical objects because cut buffer does not contain %s objects."),
!    /* STID_CANT_REPLACE_GRAPHIC_TOO_MANY */
!    N_("Cannot replace graphical objects because cut buffer contain more than one objects."),
!    /* STID_REPLACE_GRAPHIC_ICON_TO_GROUP */
!    N_("Some iconic objects have been converted to grouped objects during Replace Graphic."),
!    /* STID_REPLACE_GRAPHIC_DONE */
!    N_("Graphical part of selected objects have been replaced and updated."),
!    /* STID_TOO_MANY_ICON_REPLACE_GRAPHIC */
!    N_("More than one iconic objects are selected for Replace Graphic."),
!    /* STID_Q_CVT_ICON_TO_GRP_IN_REPLACE */
!    N_("Replacing the graphic of an iconic object...\n\nWould you like to convert the object into a grouped object? [ync](y)\n\n(If you press the No button, you will be prompted with the name of a new symbol file the iconic object.  If you press Cancel, this object will be skipped for Replace Graphic.)"),
!    /* STID_SHOW_MEASUREMENT_IN_TT_ENAB */
!    N_("Showing measurement in tooltip enabled."),
!    /* STID_SHOW_MEASUREMENT_IN_TT_DISB */
!    N_("Showing measurement in tooltip disabled.  Measurement will be shown in the ruler window."),
     NULL
  };
***************
*** 3672,3677 ****
  }
  
! void SetColorMouseStatusStrings(index, shift_or_cntrl_down)
!    int index, shift_or_cntrl_down;
     /*
      * Note: once such a string is loaded, it will never change.
--- 3692,3697 ----
  }
  
! void SetColorMouseStatusStrings(shift_or_cntrl_down, index)
!    int shift_or_cntrl_down, index;
     /*
      * Note: once such a string is loaded, it will never change.
***************
*** 3729,3732 ****
--- 3749,3753 ----
     { PROP_MASK_UNDERLINE_ON, NULL, N_("text underline") },
     { PROP_MASK_CTM,          NULL, N_("transformation matrix") },
+    { PROP_MASK_WIDTH_INDEX,  NULL, N_("line width index") },
     { 0L, NULL, NULL }
  };
*** tangram2.c.orig	Tue Apr 18 17:12:53 2000
--- tangram2.c	Tue Apr 18 17:12:53 2000
***************
*** 42,45 ****
--- 42,46 ----
  #include "cmd.e"
  #include "dialog.e"
+ #include "drawing.e"
  #include "exec.e"
  #include "menu.e"
***************
*** 46,51 ****
--- 47,54 ----
  #include "msg.e"
  #include "miniline.e"
+ #include "move.e"
  #include "obj.e"
  #include "pattern.e"
+ #include "rcbox.e"
  #include "select.e"
  #include "setup.e"
***************
*** 62,65 ****
--- 65,74 ----
     { "Generate Markov Chain", NULL, "Generate Markov Chain", NULL,
       CMDID_TANGRAM2_GENERATE_CHAIN },
+    { "Start Simulator", NULL, "Start Simulation", NULL,
+      CMDID_TANGRAM2_START_SIMULATOR },
+    { "Simulation Step", NULL, "Simulation Step", NULL,
+      CMDID_TANGRAM2_SIMULATION_STEP },
+    { "End Simulator", NULL, "End Simulation", NULL,
+      CMDID_TANGRAM2_END_SIMULATOR },
     { NULL, NULL, NULL, NULL, INVALID }
  };
***************
*** 85,89 ****
  static struct ShortCutRec tangram2ShortCutXlateTbl[] = {
     { '\0', 0, "AboutTangram2()", 0, CMDID_ABOUT_TANGRAM2 },
!    { '\0', 0, "Tangram2GenerateChain()", 0, CMDID_TANGRAM2_GENERATE_CHAIN },
     { '\0', 0, "", 0, 0 }
  };
--- 94,101 ----
  static struct ShortCutRec tangram2ShortCutXlateTbl[] = {
     { '\0', 0, "AboutTangram2()", 0, CMDID_ABOUT_TANGRAM2 },
!    { '\0', 0, "Tangram2GenerateChain()", 1, CMDID_TANGRAM2_GENERATE_CHAIN },
!    { '\0', 0, "Tangram2StartSimulator()", 1, CMDID_TANGRAM2_START_SIMULATOR },
!    { '\0', 0, "Tangram2SimulationStep()", 0, CMDID_TANGRAM2_SIMULATION_STEP },
!    { '\0', 0, "Tangram2EndSimulator()", 0, CMDID_TANGRAM2_END_SIMULATOR },
     { '\0', 0, "", 0, 0 }
  };
***************
*** 162,166 ****
     switch (nCmdId) {
     case CMDID_ABOUT_TANGRAM2: AboutTangram2(); break;
!    case CMDID_TANGRAM2_GENERATE_CHAIN: Tangram2GenerateChain(); break;
     default: break;
     }
--- 174,181 ----
     switch (nCmdId) {
     case CMDID_ABOUT_TANGRAM2: AboutTangram2(); break;
!    case CMDID_TANGRAM2_GENERATE_CHAIN:  Tangram2GenerateChain(args);  break;
!    case CMDID_TANGRAM2_START_SIMULATOR: Tangram2StartSimulator(args); break;
!    case CMDID_TANGRAM2_SIMULATION_STEP: Tangram2SimulationStep();     break;
!    case CMDID_TANGRAM2_END_SIMULATOR:   Tangram2EndSimulator();       break;
     default: break;
     }
***************
*** 223,227 ****
  #define MAXVARS              20
  #define MAXVARNAME          250
! #define MAXCONNECTTRIES      10
  #define PORT               6743
  
--- 238,242 ----
  #define MAXVARS              20
  #define MAXVARNAME          250
! #define MAXCONNECTTRIES       3
  #define PORT               6743
  
***************
*** 245,248 ****
--- 260,266 ----
  
  static int simulator_socket=INVALID;
+ static struct ObjRec *objGC=NULL; /* Generate Chain   button */
+ static struct ObjRec *objSS=NULL; /* Start Simulation button */
+ static struct ObjRec *objSp=NULL; /* Simulation Step  button */
  
  static
***************
*** 263,315 ****
     /* start_simulator(); */
  {
!    char servidor[80];
!    struct sockaddr_in endereco;
!    struct hostent *hptr;
!    int i;
!    
!    memset((char*)(&endereco), 0, sizeof(endereco)); 
  
!    /* get the local host information - use localhost (127.0.0.1)  */
!    /* gethostname(servidor, 80); */
!    strcpy(servidor, "localhost");
!    if ((hptr=gethostbyname(servidor)) != NULL) {
!       memcpy((char*)&endereco.sin_addr, hptr->h_addr, hptr->h_length); 
!    } else {
!       perror("gethostbyname");
!       return;
!    }
! 
!    endereco.sin_family = AF_INET;
!    endereco.sin_port = htons((u_short)PORT);
! 
!    if ((simulator_socket=socket(AF_INET, SOCK_STREAM, 0)) < 0) {
!       perror("socket creation");
!       return; 
!    }
! 
!    /* connect to server. Try for MAXCONNECTTRIES times */
!    i = 0;
!    while (i < MAXCONNECTTRIES)
!       if ((connect(simulator_socket, (struct sockaddr *)(&endereco),
!             sizeof(endereco))) < 0) {
!          perror("connect");
!          printf("Still trying... (%d)\n",MAXCONNECTTRIES-i);
!          close(simulator_socket);
!          if ((simulator_socket=socket(AF_INET, SOCK_STREAM, 0)) < 0) {
!            perror("socket creation");
!            return; 
!          }
!          sleep(3);
!          i++;
!       } else {
!          break;
!       }
!    if (i == MAXCONNECTTRIES) {
!       perror("connect");
!       printf("Bailing out... after %d tries\n", MAXCONNECTTRIES);
!       return;
!    }
! 
!    printf("Cliente Conectado.\n");
  }
  
--- 281,400 ----
     /* start_simulator(); */
  {
!     char host[ 10 ];
!     char *protocol = "udp";
!     struct hostent     *phe;
!     struct servent     *pse;
!     struct protoent    *ppe;
!     struct sockaddr_in  sin;
!     int sin_size;
!     int s, type, max_desc;
!     char buffer[ sizeof( T_Packet ) ];
!     fd_set soc_pool;
!     struct timeval timeout;
!     int one = 1;
!     char *service = "6743";
  
!     strcpy( host, "localhost" );
!     bzero( (char *)&sin, sizeof( sin ) );
!     sin.sin_family = AF_INET;
!     if( (pse = getservbyname( service, protocol )) != NULL )
!         sin.sin_port = pse->s_port;
!     else
!         if( (sin.sin_port = htons( (u_short)atoi( service ) )) == 0 )
!         {
!             fprintf( stderr, "TGIF: Can't get \"%s\" service entry\n", service );
!             return;
!         }
!     
!     if( (phe = gethostbyname( host )) != NULL )
!         bcopy( phe->h_addr, (char *)&sin.sin_addr, phe->h_length );
!     else
!     {
!         sin.sin_addr.s_addr = inet_addr( host );
! #ifdef linux
!         if( sin.sin_addr.s_addr == INADDR_NONE )
!         {
!             fprintf( stderr, "TGIF: Can't get \"%s\" host entry\n", host );
!             return;
!         }
! #endif /* linux */
!     }
!         
!     if( (ppe = getprotobyname( protocol )) == NULL )
!     {
!         fprintf( stderr, "TGIF: Can't get \"%s\" protocol entry\n", protocol );
!         return;
!     }
!     if( strcmp( protocol, "udp" ) == 0 )
!         type = SOCK_DGRAM;
!     else
!         type = SOCK_STREAM;
!         
!     if( (s = socket( PF_INET, type, ppe->p_proto )) < 0 )
!     {
!         fprintf( stderr, "TGIF: Can't create socket\n" );
!         return;
!     }
!     
!     if( setsockopt( s, SOL_SOCKET, SO_REUSEADDR, (char *)&one, sizeof( one ) ) < 0 )
!     {
!         perror( "TGIF: REUSEADDR" );
!         return;
!     }
!     
!     if( bind( s, (struct sockaddr *)&sin, sizeof( sin ) ) < 0 )
!     {
!         perror( "TGIF: bin" );
!         return;
!     }
!     
!     if( type == SOCK_STREAM && listen( s, 0 ) < 0 )
!     {
!         fprintf( stderr, "TGIF: Can't listen on %s port\n", service );
!         return;
!     }
!     
!     FD_ZERO( &soc_pool );
!     FD_SET( s, &soc_pool );
!     max_desc = s + 1;
!     timeout.tv_sec  = 20;
!     timeout.tv_usec = 0;
!     if( select( max_desc, &soc_pool, NULL, NULL, &timeout ) < 0 )
!     {
!         perror( "TGIF: select" );
!         return;
!     }
!     if( FD_ISSET( s, &soc_pool ) )
!     {
!         sin_size = sizeof( sin );
!         if( recvfrom( s, buffer, sizeof( T_Packet ), 0, (struct sockaddr *)&sin, &sin_size ) < 0 )
!         {
!             perror( "TGIF: recv" );
!             return;
!         }
!         
!         if( connect( s, (struct sockaddr *)&sin, sin_size ) < 0 )
!         {
!             fprintf( stderr, "TGIF: Can't connect to %s.%s\n", host, service );
!             return;
!         }
!     
!         sleep( 1 );
!         if( send( s, buffer, sizeof( T_Packet ), 0 ) < 0 )
!         {
!             perror( "TGIF: send" );
!             return;
!         }
!     
!     }
!     else
!     {
!         fprintf( stderr, "TGIF: Timeout expired\n" );
!         return;
!     }
!     
!     simulator_socket = s;
!     
!     printf("TGIF: Cliente Conectado.\n");
  }
  
***************
*** 575,607 ****
  }
  
! /* ======================= Tangram2 Menu Functions ======================= */
  
- void AboutTangram2()
- {
-    sprintf(gszMsgBox, "%s\n\n%s %s.",
-          "Welcome to Tangram-II!",
-          "Brought to you by the Tangram-II team at the",
-          "Universidade Federal do Rio de Janeiro");
-    MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
- }
  
! static char *GenerateChainExec[] = {
!   "disable_undo();",
    "get_current_file(\"str\");",
    "read_file_into_attr(\"| basename $(str) .obj\", \"basename\");",
-   "read_file_into_attr(\"| head -1 $(basename).setup\", \"dbglevel\");",
-   "read_file_into_attr(\"| head -2 $(basename).setup | tail -1\", \"maxstates\");",
-   "read_file_into_attr(\"| tail -2 $(basename).setup | head -1\", \"output\");",
-   "read_file_into_attr(\"| tail -1 $(basename).setup\", \"processID\");",
    "strcpy(file_name, \"$(basename).parser\");",
    "strcpy(str, \" \");",
    "write_attr_into_file(str, $(file_name));",
    "exec(write_model);",
    "exec(write_global_rewards);",
    "exec(write_indep_chains);",
-   "strcpy(command, \"gramatica $(file_name) $(basename) $(dbglevel) > $(output)\");",
-   "launch(command);",
-   "strcpy(command, \"generate_chain $(basename) $(maxstates) $(dbglevel) >> $(output)\");",
-   "launch(command);",
    "enable_undo();",
     NULL
--- 660,681 ----
  }
  
! /* ========================= Tangram2 Menu Data ========================= */
  
  
! static char *GenerateChainInit[] = {
    "get_current_file(\"str\");",
    "read_file_into_attr(\"| basename $(str) .obj\", \"basename\");",
    "strcpy(file_name, \"$(basename).parser\");",
    "strcpy(str, \" \");",
    "write_attr_into_file(str, $(file_name));",
+   NULL
+ };
+ 
+ static char *GenerateChainExec[] = {
+   "disable_undo();",
+   "exec(init);",
    "exec(write_model);",
    "exec(write_global_rewards);",
    "exec(write_indep_chains);",
    "enable_undo();",
     NULL
***************
*** 718,721 ****
--- 792,948 ----
  };
  
+ 
+ static char *StartSimulatorSetModeB[] = {
+   "strcpy(command, \"simulate_chain $(__GENERATE_CHAIN__.basename) B $(__GENERATE_CHAIN__.dbglevel) $(Event) $(Transitions) $(Time) $(Runs) >> $(__GENERATE_CHAIN__.output) & \");",
+   "launch(command);",
+   NULL
+ };
+ 
+ static char *StartSimulatorSetModeI[] = {
+  "strcpy(Transitions, \"0\");",
+  "strcpy(Time, \"0.0\");",
+  "strcpy(command, \"simulate_chain $(__GENERATE_CHAIN__.basename) I $(__GENERATE_CHAIN__.dbglevel) >> $(__GENERATE_CHAIN__.output) & \");",
+  "launch(command);",
+  "start_simulator();",
+   NULL
+ };
+ 
+ static char *StartSimulatorErrorMode[] = {
+  "message_box(NULL,\"Please, Mode has to be I(Interactive) or B(Batch)!\",\"Mode Error\", \"stop\");",
+   NULL
+ };
+ 
+ static char *StartSimulatorExec[] = {
+  "disable_undo();",
+  "show_attr(Transitions);",
+  "show_attr(Time);",
+  "exec(__GENERATE_CHAIN__.init);",
+  "if(\"$(Mode)\"!=\"I\"&&\"$(Mode)\"!=\"B\",error_mode,NULL);"
+  "strcpy(file_name, \"$(__GENERATE_CHAIN__.file_name)\");",
+  "strcpy(str, \" \");",
+  "write_attr_into_file(str, $(file_name));",
+  "exec(__GENERATE_CHAIN__.write_model);"
+  "exec(__GENERATE_CHAIN__.write_global_rewards);"
+  "exec(__GENERATE_CHAIN__.write_indep_chains);",
+  "strcpy(command, \"gramatica $(file_name) $(__GENERATE_CHAIN__.basename) $(__GENERATE_CHAIN__.dbglevel) -nomaxcheck > $(__GENERATE_CHAIN__.output)\");",
+  "launch(command);",
+  "if(\"$(Mode)\"==\"I\",set_mode_I,NULL);",
+  "if(\"$(Mode)\"==\"B\",set_mode_B,NULL);",
+  "enable_undo();",
+  NULL
+ };
+ 
+ static char *SimulationStepWriteVarLine[] = {
+  "tokenize(state_var_tok,$(state_var_line),'=');",
+  "get_line_in_attr(state_var_name,state_var_tok,1);",
+  "get_line_in_attr(state_var_value,state_var_tok,2);",
+  "strcpy(new_line, \"$(cur_obj).$(state_var_name)=$(state_var_value)\");",
+  "strcpy(buffer,\"$(buffer)$(new_line)@\");",
+   NULL
+ };
+ 
+ static char *SimulationStepLoopAnimation[] = {
+  "for_i(Ani_C_Step,1,$(Ani_T_Steps),1,Do_Animation);",
+  "round(sleep_time,$(Time_Scale)*$(step_time)*1000);",
+  "sleep(NULL,$(sleep_time));",
+   NULL
+ };
+ 
+ static char *SimulationStepAnimateObj[] = {
+  "get_line_in_attr(cur_obj,obj_list,$(obj_index));",
+  "exec(\"$(cur_obj).Animation\");",
+   NULL
+ };
+ 
+ static char *SimulationStepDoAnimation[] = {
+  "find_obj_names(obj_list,\"\",\"Animation=*\");",
+  "get_line_in_attr(no_objs,obj_list,0);",
+  "for_i(obj_index,1,$(no_objs),1,Animate_Obj);",
+   NULL
+ };
+ 
+ static char *SimulationStepCallSimulator[] = {
+   "simulate_step();",
+   NULL
+ };
+ 
+ static char *SimulationStepPlayOneStep[] = {
+  "set_allow_interrupt(FALSE);",
+  "exec(step_simulation);",
+  "set_allow_interrupt(TRUE);",
+  "sleep(NULL,$(Delay));",
+   NULL
+ };
+ 
+ static char *SimulationStepUpdateObjects[] = {
+  "tokenize(state_var_list,$(buffer),'@');",
+  "get_line_in_attr(no_state_vars,state_var_list,0);",
+  "for_i(var_index,1,\"$(no_state_vars)-1\",1,update_vars);",
+   NULL
+ };
+ 
+ static char *SimulationStepStop[] = {
+   "stop();",
+   NULL
+ };
+ 
+ static char *SimulationStepStepSimulation[] = {
+  "strcpy(buffer,\"\");",
+  "find_obj_names(obj_list,\"\",\"State_vars=*\");",
+  "get_line_in_attr(no_objs,obj_list,0);",
+  "for_i(obj_index,1,$(no_objs),1,parse_obj);",
+  "exec(call_simulator);",
+  "exec(update_objects);",
+  "redraw_drawing_area();",
+  "if(\"$(Animation)\"==\"ON\",Loop_Animation,NULL);",
+   NULL
+ };
+ 
+ static char *SimulationStepPlaySimulation[] = {
+   "while(1,play_one_step);",
+   NULL
+ };
+ 
+ static char *SimulationStepUpdateVars[] = {
+  "get_line_in_attr(state_var_str,state_var_list,$(var_index));",
+  "tokenize(state_var_tok,$(state_var_str),'.');",
+  "get_line_in_attr(obj_name,state_var_tok,1);",
+  "get_line_in_attr(state_var_str,state_var_tok,2);",
+  "tokenize(state_var_tok,$(state_var_str),'=');",
+  "get_line_in_attr(state_var_name,state_var_tok,1);",
+  "get_line_in_attr(state_var_value,state_var_tok,2);",
+  "append_line_into_attr($(obj_name).State_vars,\" $(state_var_name)=$(state_var_value)\");",
+   NULL
+ };
+ 
+ static char *SimulationStepParseObj[] = {
+  "get_line_in_attr(cur_obj,obj_list,$(obj_index));",
+  "get_number_of_lines_in_attr(no_state_vars,$(cur_obj).State_vars);",
+  "for_i(var_index,1,$(no_state_vars)-1,1,write_vars);",
+  "clear_attr($(cur_obj).State_vars);",
+   NULL
+ };
+ 
+ static char *SimulationStepExec[] = {
+  "disable_undo();",
+  "show_attr(Step);",
+  "show_attr(Delay);",
+  "show_attr(Animation);",
+  "show_attr(Time_Scale);",
+  "if(\"$(Step)\"==\"0\",play_simulation,step_simulation);",
+  "enable_undo();",
+  "redraw_drawing_area();",
+   NULL
+ };
+ 
+ static char *SimulationStepWriteVars[] = {
+  "get_line_in_attr(state_var_line,$(cur_obj).State_vars,$(var_index));",
+  "trim(state_var_line);",
+  "strlen(line_size, $(state_var_line));",
+  "if(\"$(line_size)\">=\"3\",write_var_line,NULL);",
+   NULL
+ };
+ 
+ 
  static
  void AppendLinesToAttr(attr_ptr, ppsz_lines)
***************
*** 739,754 ****
  }
  
! void Tangram2GenerateChain()
  {
-    int saved_fill=objFill, saved_pen=penPat;
     struct ObjRec *tmp_box_obj=NULL;
-    struct AttrRec *exec_attr=NULL;
  
-    MakeQuiescent(); /* select nothing, edit nothing */
- 
-    objFill = penPat = NONEPAT;
     CreateBoxObj(0,0,10,10,TRUE);
-    objFill = saved_fill;
-    penPat = saved_pen;
     tmp_box_obj = topObj;
  
--- 966,979 ----
  }
  
! /* ======================= Tangram2 Auxiliar Functions ======================= */
! 
! struct ObjRec *createGenerateChainButton( dbglevel, maxstates, output )
! char *dbglevel;
! char *maxstates;
! char *output;
  {
     struct ObjRec *tmp_box_obj=NULL;
  
     CreateBoxObj(0,0,10,10,TRUE);
     tmp_box_obj = topObj;
  
***************
*** 755,761 ****
     /* Note: AddAttrByNameAndValue() adds the new object at tmp_box_obj->fattr */
     AddAttrByNameAndValue(tmp_box_obj, "i=", "");
!    AddAttrByNameAndValue(tmp_box_obj, "dbglevel=", "");
!    AddAttrByNameAndValue(tmp_box_obj, "maxstates=", "");
!    AddAttrByNameAndValue(tmp_box_obj, "output=", "");
     AddAttrByNameAndValue(tmp_box_obj, "processID=", "");
     AddAttrByNameAndValue(tmp_box_obj, "name=", "__GENERATE_CHAIN__");
--- 980,986 ----
     /* Note: AddAttrByNameAndValue() adds the new object at tmp_box_obj->fattr */
     AddAttrByNameAndValue(tmp_box_obj, "i=", "");
!    AddAttrByNameAndValue(tmp_box_obj, "dbglevel=", dbglevel);
!    AddAttrByNameAndValue(tmp_box_obj, "maxstates=", maxstates);
!    AddAttrByNameAndValue(tmp_box_obj, "output=", output);
     AddAttrByNameAndValue(tmp_box_obj, "processID=", "");
     AddAttrByNameAndValue(tmp_box_obj, "name=", "__GENERATE_CHAIN__");
***************
*** 770,773 ****
--- 995,1001 ----
     AddAttrByNameAndValue(tmp_box_obj, "obj_list=", "");
  
+    AddAttrByNameAndValue(tmp_box_obj, "init=", "");
+    AppendLinesToAttr(tmp_box_obj->fattr, GenerateChainInit);
+ 
     AddAttrByNameAndValue(tmp_box_obj, "exec=", "");
     AppendLinesToAttr(tmp_box_obj->fattr, GenerateChainExec);
***************
*** 800,810 ****
     AppendLinesToAttr(tmp_box_obj->fattr, GenerateChainAppendIndepChains);
  
!    StartCompositeCmd();
  
     AdjObjBBox(tmp_box_obj);
-    RecordNewObjCmd();
  
     AddNewSelObj(tmp_box_obj);
  
     exec_attr = FindAttrWithName(topSel->obj, "exec=", NULL);
     if (exec_attr != NULL) {
--- 1028,1260 ----
     AppendLinesToAttr(tmp_box_obj->fattr, GenerateChainAppendIndepChains);
  
!    AddNewSelObj(tmp_box_obj);
  
+    return( tmp_box_obj );
+ }
+ 
+ 
+ struct ObjRec *createStartSimulatorButton( runs, event, trans, time, mode )
+ char *runs;
+ char *event;
+ char *trans;
+ char *time;
+ char *mode;
+ {
+    struct ObjRec *tmp_box_obj = NULL;
+    int y = 5;
+ 
+    CreateRCBoxObj(4,y,200,y+40,TRUE);
+    tmp_box_obj = topObj;
+ 
+    tmp_box_obj->color = 9;
+    tmp_box_obj->detail.rcb->width = 2;
+    y += 5;
+ 
+    AddAttrByNameAndValue(tmp_box_obj, "Runs=", runs);
+    AddAttrByNameAndValue(tmp_box_obj, "Event=", event);
+    AddAttrByNameAndValue(tmp_box_obj, "Transitions=", trans);
+    tmp_box_obj->fattr->shown = TRUE;
+    MoveObj(tmp_box_obj->fattr->obj, 20, y - tmp_box_obj->fattr->obj->obbox.lty);
+    y += 14;
+ 
+    AddAttrByNameAndValue(tmp_box_obj, "Time=", time);
+    tmp_box_obj->fattr->shown = TRUE;
+    MoveObj(tmp_box_obj->fattr->obj, 20, y - tmp_box_obj->fattr->obj->obbox.lty);
+    y += 14;
+ 
+    AddAttrByNameAndValue(tmp_box_obj, "Mode=", mode);
+    AddAttrByNameAndValue(tmp_box_obj, "file_name=", "");
+    AddAttrByNameAndValue(tmp_box_obj, "command=", "");
+    AddAttrByNameAndValue(tmp_box_obj, "simulating=", "");
+    AddAttrByNameAndValue(tmp_box_obj, "str=", "");
+    AddAttrByNameAndValue(tmp_box_obj, "name=", "__START_SIMULATOR__");
+ 
+    AddAttrByNameAndValue(tmp_box_obj, "set_mode_B=", "");
+    AppendLinesToAttr(tmp_box_obj->fattr, StartSimulatorSetModeB);
+ 
+    AddAttrByNameAndValue(tmp_box_obj, "set_mode_I=", "");
+    AppendLinesToAttr(tmp_box_obj->fattr, StartSimulatorSetModeI);
+ 
+    AddAttrByNameAndValue(tmp_box_obj, "error_mode=", "");
+    AppendLinesToAttr(tmp_box_obj->fattr, StartSimulatorErrorMode);
+ 
+    AddAttrByNameAndValue(tmp_box_obj, "exec=", "");
+    AppendLinesToAttr(tmp_box_obj->fattr, StartSimulatorExec);
+ 
     AdjObjBBox(tmp_box_obj);
  
     AddNewSelObj(tmp_box_obj);
+    RedrawDrawWindow(botObj);
  
+    return( tmp_box_obj );
+ }
+ 
+ struct ObjRec *createSimulationStepButton( time, anim, delay, step )
+ char *time;
+ char *anim;
+ char *delay;
+ char *step;
+ {
+    struct ObjRec *tmp_box_obj = NULL;
+ 
+    CreateBoxObj(0,0,10,10,TRUE);
+    tmp_box_obj = topObj;
+ 
+    /* Note: AddAttrByNameAndValue() adds the new object at tmp_box_obj->fattr */
+    AddAttrByNameAndValue(tmp_box_obj, "Time_Scale=", time);
+    AddAttrByNameAndValue(tmp_box_obj, "Animation=", anim);
+    AddAttrByNameAndValue(tmp_box_obj, "Delay=", delay);
+    AddAttrByNameAndValue(tmp_box_obj, "Step=", step);
+    AddAttrByNameAndValue(tmp_box_obj, "state_var_str=", "1");
+    AddAttrByNameAndValue(tmp_box_obj, "line_size=", "7");
+    AddAttrByNameAndValue(tmp_box_obj, "obj_list=", "");
+    AddAttrByNameAndValue(tmp_box_obj, "sleep_time=", "2049");
+    AddAttrByNameAndValue(tmp_box_obj, "step_time=", "2049");
+    AddAttrByNameAndValue(tmp_box_obj, "name=", "__SIMULATION_STEP__");
+    AddAttrByNameAndValue(tmp_box_obj, "cur_obj=", "");
+    AddAttrByNameAndValue(tmp_box_obj, "obj_index=", "");
+    AddAttrByNameAndValue(tmp_box_obj, "no_objs=", "");
+    AddAttrByNameAndValue(tmp_box_obj, "Ani_T_Steps=", "10");
+    AddAttrByNameAndValue(tmp_box_obj, "Ani_C_Step=", "11");
+    AddAttrByNameAndValue(tmp_box_obj, "step_index=", "");
+    AddAttrByNameAndValue(tmp_box_obj, "no_state_vars=", "3");
+    AddAttrByNameAndValue(tmp_box_obj, "state_var_value=", "8");
+    AddAttrByNameAndValue(tmp_box_obj, "state_var_name=", "8");
+    AddAttrByNameAndValue(tmp_box_obj, "obj_name=", "");
+    AddAttrByNameAndValue(tmp_box_obj, "new_line=", "");
+    AddAttrByNameAndValue(tmp_box_obj, "buffer=", "");
+    AddAttrByNameAndValue(tmp_box_obj, "state_var_line=", "");
+    AddAttrByNameAndValue(tmp_box_obj, "state_var_list=", "");
+    AddAttrByNameAndValue(tmp_box_obj, "state_var_tok=", "");
+    AddAttrByNameAndValue(tmp_box_obj, "var_index=", "");
+ 
+    AddAttrByNameAndValue(tmp_box_obj, "write_var_line=", "");
+    AppendLinesToAttr(tmp_box_obj->fattr, SimulationStepWriteVarLine);
+ 
+    AddAttrByNameAndValue(tmp_box_obj, "Loop_Animation=", "");
+    AppendLinesToAttr(tmp_box_obj->fattr, SimulationStepLoopAnimation);
+ 
+    AddAttrByNameAndValue(tmp_box_obj, "Animate_Obj=", "");
+    AppendLinesToAttr(tmp_box_obj->fattr, SimulationStepAnimateObj);
+ 
+    AddAttrByNameAndValue(tmp_box_obj, "Do_Animation=", "");
+    AppendLinesToAttr(tmp_box_obj->fattr, SimulationStepDoAnimation);
+ 
+    AddAttrByNameAndValue(tmp_box_obj, "call_simulator=", "");
+    AppendLinesToAttr(tmp_box_obj->fattr, SimulationStepCallSimulator);
+ 
+    AddAttrByNameAndValue(tmp_box_obj, "play_one_step=", "");
+    AppendLinesToAttr(tmp_box_obj->fattr, SimulationStepPlayOneStep);
+ 
+    AddAttrByNameAndValue(tmp_box_obj, "update_objects=", "");
+    AppendLinesToAttr(tmp_box_obj->fattr, SimulationStepUpdateObjects);
+ 
+    AddAttrByNameAndValue(tmp_box_obj, "stop=", "");
+    AppendLinesToAttr(tmp_box_obj->fattr, SimulationStepStop);
+ 
+    AddAttrByNameAndValue(tmp_box_obj, "step_simulation=", "");
+    AppendLinesToAttr(tmp_box_obj->fattr, SimulationStepStepSimulation);
+ 
+    AddAttrByNameAndValue(tmp_box_obj, "play_simulation=", "");
+    AppendLinesToAttr(tmp_box_obj->fattr, SimulationStepPlaySimulation);
+ 
+    AddAttrByNameAndValue(tmp_box_obj, "update_vars=", "");
+    AppendLinesToAttr(tmp_box_obj->fattr, SimulationStepUpdateVars);
+ 
+    AddAttrByNameAndValue(tmp_box_obj, "parse_obj=", "");
+    AppendLinesToAttr(tmp_box_obj->fattr, SimulationStepParseObj);
+ 
+    AddAttrByNameAndValue(tmp_box_obj, "exec=", "");
+    AppendLinesToAttr(tmp_box_obj->fattr, SimulationStepExec);
+ 
+    AddAttrByNameAndValue(tmp_box_obj, "write_vars=", "");
+    AppendLinesToAttr(tmp_box_obj->fattr, SimulationStepWriteVars);
+ 
+    AddNewSelObj(tmp_box_obj);
+ 
+    return( tmp_box_obj );
+ }
+ 
+ /******************************************************************************/
+ /* This function extracts the args that are comma separated in 'args' and     */
+ /* stores them in 'dst'.                                                      */
+ /* return 0 if failed, no_args if success.                                    */
+ /* arguments:                                                                 */
+ /*    args: comma separated list of tokens                                    */
+ /*    dst : char vector pointer where the tokens will be stored               */
+ /*    no_args: number of tokens in 'args'                                     */
+ /*    max_arg_length: max token's size                                        */
+ /******************************************************************************/
+ int parseArgs( args, dst, no_args, max_arg_length )
+ char *args;
+ char *dst;
+ int no_args;
+ int max_arg_length;
+ {
+     int i, j;
+     char *ptr;
+ 
+     bzero( dst, no_args * max_arg_length );    
+     ptr = args;
+     /* Remove leading " and spaces */
+     while( *ptr == '\"' || *ptr == ' ' )
+         ptr++;
+         
+     for( i = 0; i < no_args; i++ )
+     {
+         j = 0;
+         while( *ptr != '\0' && *ptr != ';' && *ptr != '\"' &&
+                j < max_arg_length )
+             *(dst + max_arg_length * i + j++) = *ptr++;
+             
+         if( *ptr == ';' || *ptr == '\"' )
+             ptr++;
+         else
+             if( *ptr != '\0' )
+                 break;
+     }
+     
+     return( i == no_args );
+ }
+ /* ======================= Tangram2 Menu Functions ======================= */
+ 
+ void AboutTangram2()
+ {
+    sprintf(gszMsgBox, "%s\n\n%s %s.",
+          "Welcome to Tangram-II!",
+          "Brought to you by the Tangram-II team at the",
+          "Universidade Federal do Rio de Janeiro");
+    MsgBox(gszMsgBox, TOOL_NAME, INFO_MB);
+ }
+ 
+ /******************************************************************************/
+ /* This function creates a invisible button, executes this button and removes */
+ /* it. This function also needs to extract three arguments that are colapsed  */
+ /* in arg. This is done because tgif supports only one argument functions.    */
+ /******************************************************************************/
+ void Tangram2GenerateChain( args )
+ char *args; /* semi-colon separated list (arg1;arg2;arg3) */
+ {
+    int saved_fill=objFill, saved_pen=penPat;
+    struct ObjRec *tmp_box_obj=NULL;
+    struct AttrRec *exec_attr=NULL;
+    char arg[3][1024];
+ 
+    /* Extracts parameters from args */
+    if( !parseArgs( args, arg, 3, 1024 ) )
+    {
+         fprintf( stderr, "TGIF: Usage Tangram2GenerateChain( \"arg1;arg2;arg3\" )\n" );
+         return;
+    }
+ 
+    MakeQuiescent(); /* select nothing, edit nothing */
+ 
+    objFill = penPat = NONEPAT;
+ 
+    tmp_box_obj = createGenerateChainButton( arg[0], arg[1], arg[2] );
+ 
+    objFill = saved_fill;
+    penPat = saved_pen;
+ 
     exec_attr = FindAttrWithName(topSel->obj, "exec=", NULL);
     if (exec_attr != NULL) {
***************
*** 819,825 ****
     RecordCmd(CMD_DELETE, NULL, NULL, NULL, 0);
  
-    EndCompositeCmd();
  }
  
! #endif /* _TANGRAM_II */
  
--- 1269,1326 ----
     RecordCmd(CMD_DELETE, NULL, NULL, NULL, 0);
  
  }
  
! void Tangram2StartSimulator( args )
! char *args;
! {
!    int saved_fill=objFill, saved_pen=penPat;
!    struct AttrRec *exec_attr=NULL;
!    char arg[12][1024]; /* first 3 for generate_chain */
  
+    /* Extracts parameters from args */
+    if( !parseArgs( args, arg, 12, 1024 ) )
+    {
+         return;
+    }
+ 
+    MakeQuiescent(); /* select nothing, edit nothing */
+    objFill = penPat = NONEPAT;
+ 
+    objGC = createGenerateChainButton( arg[0], arg[1], arg[2] );
+    objSp = createSimulationStepButton( arg[8], arg[9], arg[10], arg[11] );
+ 
+    objFill = saved_fill;
+    penPat = saved_pen;
+    objSS = createStartSimulatorButton( arg[3], arg[4], arg[5], arg[6], arg[7] );
+ 
+    exec_attr = FindAttrWithName(objSS, "exec=", NULL);
+    if (exec_attr != NULL) {
+       DoExecLoop(objSS, exec_attr);
+    }
+ }
+ 
+ void Tangram2SimulationStep()
+ {
+    struct AttrRec *exec_attr=NULL;
+    
+    exec_attr = FindAttrWithName(objSp, "exec=", NULL);
+    if (exec_attr != NULL) {
+       DoExecLoop(objSp, exec_attr);
+    }
+ }
+ 
+ void Tangram2EndSimulator()
+ {
+    ExecEndSimulator( NULL, NULL );
+ 
+    /* Delete all created buttons */
+    MakeQuiescent();
+    AddNewSelObj(objGC);
+    AddNewSelObj(objSS);
+    AddNewSelObj(objSp);
+    DelAllSelObj();
+ 
+    RedrawDrawWindow(botObj);
+ }
+ 
+ #endif /* _TANGRAM_II */
*** xbitmap.c.orig	Tue Apr 18 17:12:55 2000
--- xbitmap.c	Tue Apr 18 17:12:55 2000
***************
*** 5117,5127 ****
     SetCTMPropertyMask(ObjPtr->ctm, plMask, plSkip, pProp);
  
!    SetIntPropertyMask(PROP_MASK_COLOR, ObjPtr->color,
!          colorMenuItems[ObjPtr->color], plMask, plSkip, pProp);
! 
!    SetIntPropertyMask(PROP_MASK_TRANSPAT, ObjPtr->trans_pat, NULL,
!          plMask, plSkip, pProp);
!    SetIntPropertyMask(PROP_MASK_FILL, xbm_ptr->fill, NULL,
!          plMask, plSkip, pProp);
  }
  
--- 5117,5124 ----
     SetCTMPropertyMask(ObjPtr->ctm, plMask, plSkip, pProp);
  
!    if (xbm_ptr->real_type != XBM_EPS) {
!       SetIntPropertyMask(PROP_MASK_COLOR, ObjPtr->color,
!             colorMenuItems[ObjPtr->color], plMask, plSkip, pProp);
!    }
  }
  
*** attr.e.orig	Tue Apr 18 17:12:56 2000
--- attr.e	Tue Apr 18 17:12:56 2000
***************
*** 48,51 ****
--- 48,53 ----
  extern void	FreeAttr ARGS_DECL((struct AttrRec *));
  extern void	UnlinkAttr ARGS_DECL((struct AttrRec *));
+ extern void	UpdAttrOwner ARGS_DECL((struct AttrRec *first_attr,
+ 		                        struct ObjRec *owner_obj));
  extern void	ParseAttrStr ARGS_DECL((char *buf, char *name, int name_sz,
  		                        char *value, int value_sz));
***************
*** 75,80 ****
  extern void	UpdAttr ARGS_DECL((struct AttrRec *));
  extern TgMenu	*CreateAttrMenu ARGS_DECL((TgMenu*, int x, int y, int num_items,
! 		                           char **menu_strings, int *pixels));
  extern void	FreeEditAttrInfo ARGS_DECL((EditAttrInfo*));
  extern EditAttrInfo	*CreateEditAttrInfo ARGS_DECL((struct ObjRec *));
  extern void	MoveAttr ARGS_DECL((void));
--- 77,85 ----
  extern void	UpdAttr ARGS_DECL((struct AttrRec *));
  extern TgMenu	*CreateAttrMenu ARGS_DECL((TgMenu*, int x, int y, int num_items,
! 		                           char **menu_strings,
! 		                           char **status_strings, int *pixels));
  extern void	FreeEditAttrInfo ARGS_DECL((EditAttrInfo*));
+ extern int	HasEditAttrsInContextMenu ARGS_DECL((struct ObjRec *,
+ 		                                     struct AttrRec **));
  extern EditAttrInfo	*CreateEditAttrInfo ARGS_DECL((struct ObjRec *));
  extern void	MoveAttr ARGS_DECL((void));
*** cutpaste.e.orig	Tue Apr 18 17:12:57 2000
--- cutpaste.e	Tue Apr 18 17:12:57 2000
***************
*** 76,79 ****
--- 76,81 ----
  extern void	CleanUpProperties ARGS_DECL((void));
  extern void	InitProperties ARGS_DECL((void));
+ extern void	DoGetProperty ARGS_DECL((int index));
+ extern EditAttrInfo	*CreateGetPropertyInfo ARGS_DECL((void));
  extern void	CopyProperties ARGS_DECL((int nPrompt));
  extern void	SaveProperties ARGS_DECL((void));
***************
*** 101,104 ****
--- 103,108 ----
  extern void	FreeSimpleStringObj ARGS_DECL((struct ObjRec *));
  
+ extern void	ReplaceGraphic ARGS_DECL((void));
+ 
  #ifdef _INCLUDE_FROM_CUTPASTE_C_
  #undef extern
*** drawing.e.orig	Tue Apr 18 17:12:58 2000
--- drawing.e	Tue Apr 18 17:12:58 2000
***************
*** 101,104 ****
--- 101,108 ----
  		                                       TgMenuInfo*,
  		                                       int status_str_xlated));
+ extern void	GetProperty ARGS_DECL((int index));
+ extern TgMenu	*CreateGetPropertyMenu ARGS_DECL((TgMenu*, int X, int Y,
+ 		                                  TgMenuInfo*,
+ 		                                  int status_str_xlated));
  extern int	RefreshContextMenu ARGS_DECL((TgMenu*));
  extern TgMenu	*CreateContextMenu ARGS_DECL((TgMenu*, int X, int Y,
*** menuinfo.e.orig	Tue Apr 18 17:12:58 2000
--- menuinfo.e	Tue Apr 18 17:12:58 2000
***************
*** 78,81 ****
--- 78,82 ----
  
  extern TgMenuInfo	editAttrInEditorMenuInfo;
+ extern TgMenuInfo	getPropertyMenuInfo;
  extern TgMenuInfo	baseContextMenuInfo;
  extern TgMenuInfo	editTextContextMenuInfo;
*** ruler.e.orig	Tue Apr 18 17:12:59 2000
--- ruler.e	Tue Apr 18 17:12:59 2000
***************
*** 36,39 ****
--- 36,40 ----
  
  extern int	showMeasurement;
+ extern int	showMeasurementInTooltip;
  extern int	showCrossHair;
  
***************
*** 74,78 ****
--- 75,88 ----
                                                  int ExtraSpace));
  extern void	ToggleShowMeasurement ARGS_DECL((void));
+ extern void	ToggleShowMeasurementInTooltip ARGS_DECL((void));
  
+ extern void	DoIntervalMeasureTooltip ARGS_DECL((int ltx, int lty, int rbx,
+ 		                                    int rby, int mdx, int mdy));
+ extern void	StartMeasureTooltip ARGS_DECL((char*));
+ extern void	SetMeasureTooltip ARGS_DECL((char*));
+ extern void	EndMeasureTooltip ARGS_DECL((int force));
+ extern void	CleanUpMeasureTooltip ARGS_DECL((void));
+ extern int	InitMeasureTooltip ARGS_DECL((void));
+ 
  #ifdef _INCLUDE_FROM_RULER_C_
  #undef extern
*** select.e.orig	Tue Apr 18 17:13:00 2000
--- select.e	Tue Apr 18 17:13:00 2000
***************
*** 85,88 ****
--- 85,89 ----
  		                  struct SelRec *));
  extern void	AddNewSelObj ARGS_DECL((struct ObjRec *));
+ extern void	ExpandCurSelBBoxes ARGS_DECL((struct ObjRec *));
  extern void	UpdSelBBox ARGS_DECL((void));
  extern void	SelBox ARGS_DECL((Window, GC, int X1, int Y1, int X2, int Y2));
*** setup.e.orig	Tue Apr 18 17:13:01 2000
--- setup.e	Tue Apr 18 17:13:01 2000
***************
*** 132,135 ****
--- 132,136 ----
  extern int	myDkGryPixel;
  extern int	myVryLtPixel;
+ extern int	myYellowPixel;
  extern int	reverseVideo;
  
*** special.e.orig	Tue Apr 18 17:13:02 2000
--- special.e	Tue Apr 18 17:13:02 2000
***************
*** 50,54 ****
  extern void	MakeSymbolic ARGS_DECL((void));
  extern void	UnMakeSymbolic ARGS_DECL((void));
! extern int	MakeIconic ARGS_DECL((char *SymPath));
  extern void	UnMakeIconic ARGS_DECL((void));
  extern void	ImportAttrs ARGS_DECL((void));
--- 50,54 ----
  extern void	MakeSymbolic ARGS_DECL((void));
  extern void	UnMakeSymbolic ARGS_DECL((void));
! extern int	MakeIconic ARGS_DECL((char *SymPath, int record_cmd));
  extern void	UnMakeIconic ARGS_DECL((void));
  extern void	ImportAttrs ARGS_DECL((void));
*** strtbl.e.orig	Tue Apr 18 17:13:02 2000
--- strtbl.e	Tue Apr 18 17:13:03 2000
***************
*** 255,260 ****
  #define CSTID_MOVE_EDIT_TEXT_BOX            307
  #define CSTID_START_MOVE_EDIT_TEXT_BOX      308
  
! #define MAXCACHEDSTIDS 309
  
  /* ===================== Non-cached ===================== */
--- 255,262 ----
  #define CSTID_MOVE_EDIT_TEXT_BOX            307
  #define CSTID_START_MOVE_EDIT_TEXT_BOX      308
+ #define CSTID_EDIT_ATTR_IN_EDITOR           309
+ #define CSTID_GET_NAMED_PROP_FROM_SEL_OBJ   310
  
! #define MAXCACHEDSTIDS 311
  
  /* ===================== Non-cached ===================== */
***************
*** 1544,1549 ****
  #define STID_DRAG_MOUSE_MOVE_EDITTEXT_DOTS 2268
  #define STID_EXCEED_BUF_SIZE_LIMIT_IN_WB   2269
  
! #define MAXNONCACHEDSTIDS 2270
  
  extern struct MouseStatusStrRec	colorMouseStatus[];
--- 1546,1559 ----
  #define STID_DRAG_MOUSE_MOVE_EDITTEXT_DOTS 2268
  #define STID_EXCEED_BUF_SIZE_LIMIT_IN_WB   2269
+ #define STID_CANT_REPLACE_GRAPHIC_NOT_TGIF 2270
+ #define STID_CANT_REPLACE_GRAPHIC_TOO_MANY 2271
+ #define STID_REPLACE_GRAPHIC_ICON_TO_GROUP 2272
+ #define STID_REPLACE_GRAPHIC_DONE          2273
+ #define STID_TOO_MANY_ICON_REPLACE_GRAPHIC 2274
+ #define STID_Q_CVT_ICON_TO_GRP_IN_REPLACE  2275
+ #define STID_SHOW_MEASUREMENT_IN_TT_ENAB   2276
+ #define STID_SHOW_MEASUREMENT_IN_TT_DISB   2277
  
! #define MAXNONCACHEDSTIDS 2278
  
  extern struct MouseStatusStrRec	colorMouseStatus[];
*** tangram2.e.orig	Tue Apr 18 17:13:03 2000
--- tangram2.e	Tue Apr 18 17:13:03 2000
***************
*** 38,45 ****
  #define CMDID_TANGRAM2_BASE 0x4000
  
! #define CMDID_ABOUT_TANGRAM2          (CMDID_TANGRAM2_BASE+0)
! #define CMDID_TANGRAM2_GENERATE_CHAIN (CMDID_TANGRAM2_BASE+1)
  
! #define MAXTANGRAM2CMDIDS (CMDID_ABOUT_TANGRAM2+2)
  
  #ifdef _TANGRAM_II
--- 38,48 ----
  #define CMDID_TANGRAM2_BASE 0x4000
  
! #define CMDID_ABOUT_TANGRAM2           (CMDID_TANGRAM2_BASE+0)
! #define CMDID_TANGRAM2_GENERATE_CHAIN  (CMDID_TANGRAM2_BASE+1)
! #define CMDID_TANGRAM2_START_SIMULATOR (CMDID_TANGRAM2_BASE+2)
! #define CMDID_TANGRAM2_SIMULATION_STEP (CMDID_TANGRAM2_BASE+3)
! #define CMDID_TANGRAM2_END_SIMULATOR   (CMDID_TANGRAM2_BASE+4)
  
! #define MAXTANGRAM2CMDIDS (CMDID_ABOUT_TANGRAM2+5)
  
  #ifdef _TANGRAM_II
***************
*** 87,91 ****
  
  extern void	AboutTangram2 ARGS_DECL((void));
! extern void	Tangram2GenerateChain ARGS_DECL((void));
  
  #endif /* _TANGRAM_II */
--- 90,97 ----
  
  extern void	AboutTangram2 ARGS_DECL((void));
! extern void	Tangram2GenerateChain ARGS_DECL((char*));
! extern void	Tangram2StartSimulator ARGS_DECL((char*));
! extern void	Tangram2SimulationStep ARGS_DECL((void));
! extern void	Tangram2EndSimulator ARGS_DECL((void));
  
  #endif /* _TANGRAM_II */
*** cmdids.h.orig	Tue Apr 18 17:13:04 2000
--- cmdids.h	Tue Apr 18 17:13:04 2000
***************
*** 379,384 ****
  #define CMDID_RECENTLYUSEDFILES            426
  #define CMDID_MOVEEDITTEXTBOX              427
  
! #define MAXCMDIDS 428
  
  #endif /*_CMDIDS_H_*/
--- 379,387 ----
  #define CMDID_RECENTLYUSEDFILES            426
  #define CMDID_MOVEEDITTEXTBOX              427
+ #define CMDID_GETPROPERTY                  428
+ #define CMDID_REPLACEGRAPHIC               429
+ #define CMDID_TOGGLESHOWMEASUREMENTINTT    430
  
! #define MAXCMDIDS 431
  
  #endif /*_CMDIDS_H_*/
*** const.h.orig	Tue Apr 18 17:13:05 2000
--- const.h	Tue Apr 18 17:13:05 2000
***************
*** 967,970 ****
--- 967,971 ----
  #define PROP_MASK_VSPACE	0x00010000
  #define PROP_MASK_UNDERLINE_ON	0x00020000
+ #define PROP_MASK_WIDTH_INDEX	0x00100000 /* GetProperty() only */
  
  #endif /*_TGIF_CONST_H_*/
*** patchlvl.h.orig	Tue Apr 18 17:13:06 2000
--- patchlvl.h	Tue Apr 18 17:13:06 2000
***************
*** 35,39 ****
  #define _TGIF_PATCHLEVEL_H_
  
! #define TGIF_PATCHLEVEL 28
  
  #endif /*_TGIF_PATCHLEVEL_H_*/
--- 35,39 ----
  #define _TGIF_PATCHLEVEL_H_
  
! #define TGIF_PATCHLEVEL 29
  
  #endif /*_TGIF_PATCHLEVEL_H_*/
*** types.h.orig	Tue Apr 18 17:13:06 2000
--- types.h	Tue Apr 18 17:13:07 2000
***************
*** 608,612 ****
  
  typedef struct PropertiesRec {
!    int			color, width, aw, ah;
     char			color_str[40], width_spec[40], aw_spec[40], ah_spec[40];
     int			fill, pen, dash, arrow_style, curved, rcb_radius;
--- 608,612 ----
  
  typedef struct PropertiesRec {
!    int			color, width, aw, ah, width_index;
     char			color_str[40], width_spec[40], aw_spec[40], ah_spec[40];
     int			fill, pen, dash, arrow_style, curved, rcb_radius;
***************
*** 769,773 ****
--- 769,775 ----
     char	**attr_values;
     char	**attr_strings;
+    char	**status_strings;
     int	*fore_colors;
+    int	*attr_indices;
  } EditAttrInfo;
  
*** Imakefile.orig	Tue Apr 18 17:13:07 2000
--- Imakefile	Tue Apr 18 17:13:07 2000
***************
*** 53,57 ****
                    $(MOREDEFINES)
  
! TGIFVERSION	= 4.1.28
  
  XCOMM Things to try to add to the DEFINES line above:
--- 53,57 ----
                    $(MOREDEFINES)
  
! TGIFVERSION	= 4.1.29
  
  XCOMM Things to try to add to the DEFINES line above:
***************
*** 313,318 ****
  SYMDEMO = flip-flop.sym nand2.sym pin.sym tangram.sym $(SPICEDIR)*.sym \
  	  eq4.sym eq4-2x.sym eq4-ps2epsi.sym eq4-epstool.sym
! MISCTAR = /**/*.man README Copyright tgif.pl $(SPICEDIR)*.mod example.tex \
! 		HISTORY /**/*.uu testdrive.pl frontend.pl
  BACKUPDIR = /mnt/halfmoon/home/william/src/tgif/v4/backup
  
--- 313,318 ----
  SYMDEMO = flip-flop.sym nand2.sym pin.sym tangram.sym $(SPICEDIR)*.sym \
  	  eq4.sym eq4-2x.sym eq4-ps2epsi.sym eq4-epstool.sym
! MISCTAR = /**/*.man README README.tgwb Copyright tgif.pl $(SPICEDIR)*.mod \
! 		example.tex HISTORY /**/*.uu testdrive.pl frontend.pl
  BACKUPDIR = /mnt/halfmoon/home/william/src/tgif/v4/backup
  
***************
*** 344,349 ****
  	rm -f tgif-$(TGIFVERSION).tar/**/*
  	tar cvf tgif-$(TGIFVERSION).tar /**/*.c /**/*.e /**/*.h \
! 		Makefile.noimake Imakefile Tgif.tmpl Tgif.tmpl-/**/* \
! 		descrip./**/??? tgif.spec.in tgif.spec \
  		make./**/* VMS_MAKE_TGIF.COM tgificon.obj $(XBMDIR)*.xbm \
  		tgificon.xbm tgificon.xpm tgif.Xdefaults tgificon.eps \
--- 344,349 ----
  	rm -f tgif-$(TGIFVERSION).tar/**/*
  	tar cvf tgif-$(TGIFVERSION).tar /**/*.c /**/*.e /**/*.h \
! 		Makefile.noimake Imakefile Imakefile.tgwb Tgif.tmpl \
! 		Tgif.tmpl-/**/* descrip./**/??? tgif.spec.in tgif.spec \
  		make./**/* VMS_MAKE_TGIF.COM tgificon.obj $(XBMDIR)*.xbm \
  		tgificon.xbm tgificon.xpm tgif.Xdefaults tgificon.eps \
***************
*** 441,443 ****
--- 441,444 ----
  		VMS_MAKE_TGIF.COM launch-demo.obj launch-demo-1.obj \
  		Copyright make./**/* Tgif.tmpl-/**/* tgif.spec.in \
+ 		Imakefile.tgwb README.tgwb \
  		> VersionInfo/Distribution/tgif-$(TGIFVERSION)
*** tgif.man.orig	Tue Apr 18 17:13:08 2000
--- tgif.man	Tue Apr 18 17:13:09 2000
***************
*** 9,13 ****
  .\"
  .\"
! .TH tgif n "Version 4.1 Patchlevel 27 and Above" "Tgif"
  .\"
  .SH NAME
--- 9,13 ----
  .\"
  .\"
! .TH tgif n "Version 4.1 Patchlevel 29 and Above" "Tgif"
  .\"
  .SH NAME
***************
*** 2931,2934 ****
--- 2931,2968 ----
  is opened (unless the file is opened as a result of executing the
  hyperjump_then_exec() internal command).
+ .IP edit_attrs_in_context_menu=...
+ If an object has an attribute named \fIedit_attrs_in_context_menu\fR,
+ the values (starting from the 2nd line and separated by linebreaks)
+ of this attribute are treated as attribute names.  The named attributes
+ will be visible in the Edit Attribute In Editor submenu of the
+ Context Menu.  For example, if an object has the following attributes:
+ .PP
+ .RS
+ .RS
+ edit_attrs_in_context_menu=
+ .br
+ .RS
+ x
+ .br
+ y
+ .br
+ z
+ .RE
+ w=greetings
+ .br
+ x=hello
+ .br
+ y=world
+ .br
+ z=how are you
+ .br
+ good-bye
+ .RE
+ .RE
+ .PP
+ .RS
+ the Edit Attribute In Editor submenu of the Context Menu will only
+ show "x=hello", "y=world", and "z=how are you".
+ .RE
  .\"
  .SH EXPORT TO TABLE
***************
*** 4653,4656 ****
--- 4687,4716 ----
  page when pages are advanced.
  The default is false.
+ .TP
+ .I Tgif.UseMeasureTooltip: [true,false]
+ If set to ``true'', the location of the cursor and the width and height
+ of the object begin drawn/dragged/stretched will be shown in a tooltip
+ window.  This X default only takes effect if Tgif.ShowMeasurement is true.
+ The default is true.
+ .TP
+ .I Tgif.MeasureTooltipXFollowMouse: [true,false]
+ If set to ``true'', the X position of the measurement tooptip will
+ follow the mouse.
+ The default is true.
+ .TP
+ .I Tgif.MeasureTooltipYFollowMouse: [true,false]
+ If set to ``true'', the Y position of the measurement tooptip will
+ follow the mouse.
+ The default is true.
+ .TP
+ .I Tgif.MeasureTooltipHorizontalPosition: [left,center,right]
+ Fix the X position of the measurement tooltip to the left, center, or right.
+ This X default only takes effect if Tgif.MeasureTooltipXFollowMouse is false.
+ The default is left.
+ .TP
+ .I Tgif.MeasureTooltipVerticalPosition: [top,middle,bottom]
+ Fix the Y position of the measurement tooltip to the top, middle, or bottom.
+ This X default only takes effect if Tgif.MeasureTooltipYFollowMouse is false.
+ The default is top.
  .\"
  .\" add new X defaults here
*** HISTORY.orig	Tue Apr 18 17:13:10 2000
--- HISTORY	Tue Apr 18 17:13:10 2000
***************
*** 1,2 ****
--- 1,46 ----
+ -----------------------> tgif-4.1.28 => tgif-4.1.29 <-----------------------
+ 1)  Fix a bug with mouse action status in the color window if Use Color
+     Layers is selected in the Layout Menu.  Thanks to Hal Snyder
+     <hal@vailsys.com> for pointing out the problem.
+ 2)  Add French locale in the distribution.  Thanks to Roland Baudin
+     <roland.baudin@cnet.francetelecom.fr> for the contribution.
+ 3)  Add ImageProc context submenu for an XPM object.
+ 4)  Add Get Property context submenu.
+ 5)  If an object has an attribute called "edit_attrs_in_context_menu=",
+     the values (starting from the 2nd line and separated by linebreaks)
+     of this attribute are treated as attribute names.  The named attributes
+     will be visible in the Edit Attribute In Editor submenu of the
+     Context Menu.
+ 6)  Add Replace Graphic in the Special Menu.  After you have selected
+     a graphical object and copy it into the cut buffer, you can select
+     another object and select Replace Graphic to replace the graphical
+     part of the selected object by what's in the cut buffer.  All
+     attributes of the object will be preserved.
+ 7)  Add tooltip support for Show Measurement.  Thanks to Raphael Dechenaux
+     <raph_d@club-internet.fr> for the contribution.  The following new X
+     defaults are supported (with their default values shown):
+ 
+         Tgif.UseMeasureTooltip: true
+         Tgif.MeasureTooltipXFollowMouse: true
+         Tgif.MeasureTooltipYFollowMouse: true
+         Tgif.MeasureTooltipHorizontalPosition: left
+         Tgif.MeasureTooltipVerticalPosition: top
+ 
+     Please see the man pages for details.
+ 8)  Add README.tgwb and Imakefile.tgwb to make tgif into "tgwb", which is a
+     vector-drawing coorporative whiteboard application based on tgif.
+     Tgwb is tested on Linux and Solaris platforms, and it requires
+     IP-multicast.  Thanks to the team members of the research group lead by
+     Professor Edmundo de Souze e Silva <edmundo@land.ufrj.br> at the
+     Federal University of Rio de Janeiro.
+ 
+     (Please note that the current release of tgwb has a few known bugs.
+     The major ones being that (1) it uses fixed size buffers in communication;
+     therefore, when you operate on a large object, you may get an error
+     message saying that the operation is canceled.  (2) There is no privison
+     made for joining a whileboard in session; the way to get around this
+     problem is to select New from the File Menu of a tgwb to clear all
+     whiteboards.)
+ 
  -----------------------> tgif-4.1.27 => tgif-4.1.28 <-----------------------
  1)  Fix a bug in undoing and redoing delete operations.
*** tgif.Xdefaults.orig	Tue Apr 18 17:13:11 2000
--- tgif.Xdefaults	Tue Apr 18 17:13:11 2000
***************
*** 443,448 ****
  ! Added in version 4.1.26
  !
! Tgif.GoHyperSpaceInSlideShow:	false
! Tgif.LineWidthIndexInSlideShow:	4
! Tgif.MaxRecentFiles:		10
! Tgif.ResetOriginOnAdvancePage:	false
--- 443,456 ----
  ! Added in version 4.1.26
  !
! !Tgif.GoHyperSpaceInSlideShow:	false
! !Tgif.LineWidthIndexInSlideShow:	4
! !Tgif.MaxRecentFiles:		10
! !Tgif.ResetOriginOnAdvancePage:	false
! !
! ! Added in version 4.1.29
! !
! !Tgif.UseMeasureTooltip:	true
! !Tgif.MeasureTooltipXFollowMouse:	true
! !Tgif.MeasureTooltipYFollowMouse:	true
! !Tgif.MeasureTooltipHorizontalPosition:	left/center/right
! !Tgif.MeasureTooltipVerticalPosition:	top/middle/bottom
*** Tgif.tmpl-solaris.orig	Tue Apr 18 17:13:11 2000
--- Tgif.tmpl-solaris	Tue Apr 18 17:13:11 2000
***************
*** 48,52 ****
  LDCOMBINEFLAGS	= -r
  XCOMM -----------------------------------------------
! XCOMM For gcc-2.7.2, you may need -lbind on solaris:
  XCOMM CC		= gcc -Wall
  XCOMM PREPROCESSCMD	= gcc -E $(STD_CPP_DEFINES)
--- 48,52 ----
  LDCOMBINEFLAGS	= -r
  XCOMM -----------------------------------------------
! XCOMM For gcc-2.7.2, you may need -lbind on solaris (before Solaris 2.7):
  XCOMM CC		= gcc -Wall
  XCOMM PREPROCESSCMD	= gcc -E $(STD_CPP_DEFINES)
*** Imakefile.tgwb.orig	Tue Apr 18 17:13:12 2000
--- Imakefile.tgwb	Tue Apr 18 17:13:12 2000
***************
*** 0 ****
--- 1,444 ----
+ #ifndef XCOMM
+ #define XCOMM #
+ #endif
+ 
+ #ifndef NullParameter
+ #define NullParameter
+ #endif
+ 
+ XCOMM -------------------------------------------- XCOMM
+ XCOMM Please make changed in Tgif.tmpl.            XCOMM
+ XCOMM There should be no need to modify this file. XCOMM
+ XCOMM -------------------------------------------- XCOMM
+ 
+ #include <Tgif.tmpl>
+ 
+ XCOMM 
+ XCOMM  Author:      William Chia-Wei Cheng (william@cs.ucla.edu)
+ XCOMM 
+ XCOMM  Copyright (C) 1990-2000, William Chia-Wei Cheng.
+ XCOMM 
+ XCOMM  Permission limited to the use, copy, display, distribute without
+ XCOMM  charging for a fee, and produce derivative works of "tgif" and
+ XCOMM  its documentation for not-for-profit purpose is hereby granted by
+ XCOMM  the Author, provided that the above copyright notice appears in
+ XCOMM  all copies made of "tgif" and that both the copyright notice
+ XCOMM  and this permission notice appear in supporting documentation,
+ XCOMM  and that the name of the Author not be used in advertising or
+ XCOMM  publicity pertaining to distribution of the software without
+ XCOMM  specific, written prior permission.  The Author makes no
+ XCOMM  representations about the suitability of this software for any
+ XCOMM  purpose.  It is provided "as is" without express or implied
+ XCOMM  warranty.  All other rights (including, but not limited to, the
+ XCOMM  right to sell "tgif", the right to sell or distribute derivative
+ XCOMM  works of "tgif", the right to distribute "tgif" for a fee, and
+ XCOMM  the right to include "tgif" or derivative works of "tgif" in a
+ XCOMM  for-sale product or service) are reserved by the Author.
+ XCOMM 
+ XCOMM  THE AUTHOR DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ XCOMM  INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ XCOMM  EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ XCOMM  CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF
+ XCOMM  USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+ XCOMM  OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ XCOMM  PERFORMANCE OF THIS SOFTWARE.
+ XCOMM 
+ XCOMM  @(#)$Header: /mm/src/tgif/v4/RCS/Imakefile.tgwb,v 4.0 2000/04/18 15:12:15 william Exp $
+ XCOMM 
+ 
+ DEFINES		= $(DIRDEFINES) \@@\
+                   $(EXTDEFINES) \@@\
+                   $(XIMPDEFINES) \@@\
+                   $(MISCDEFINES) \@@\
+                   $(MOREDEFINES)
+ 
+ TGIFVERSION	= 4.1.29
+ 
+ XCOMM Things to try to add to the DEFINES line above:
+ XCOMM
+ XCOMM    RS6000:  -D_BSD
+ XCOMM    Solaris: 
+ XCOMM    Irix:    
+ XCOMM    SunOS:   
+ XCOMM    HP-UX:   -D_NO_LOCALE_SUPPORT
+ XCOMM    VMS:     -D_NO_GETTIMEOFDAY
+ XCOMM    Linux:   
+ XCOMM    FreeBSD: 
+ XCOMM    SCO:     -DPRINT_CMD=\""lp -o raw -o nobanner"\"
+ 
+ XCOMM -D_PS_SEVENBIT_DOUBLEBYTE_TEXT
+ XCOMM    Include the above line if bit 7 in both bytes of a double-byte
+ XCOMM    character should be masked out when printing/exporting double-byte
+ XCOMM    text to a PostScript file.
+ XCOMM -D_USE_PS_ADOBE_STRING=\"true\"
+ XCOMM    Include the above line in the DEFINES if you want to configure tgif
+ XCOMM    to use a default Tgif.UsePsAdobeString value.
+ XCOMM -D_MINIMAL_EPS=1
+ XCOMM    Include the above line in the DEFINES if you want to configure tgif
+ XCOMM    to use a default Tgif.MinimalEPS value.
+ XCOMM -DENABLE_NLS
+ XCOMM    Include the above line if you want to enable NLS (Native Language
+ XCOMM    Support).
+ XCOMM -D_DONT_USE_PORTABLE_LOCALE (obsoleted)
+ XCOMM    Include the above line if you don't want to use the portable locale.
+ XCOMM    (Portable locale is "C" for all locale categories.)
+ XCOMM -D_NO_RECURSIVE_EXTERN
+ XCOMM    Include the above line if your C compiler cannot handle
+ XCOMM    "#define extern extern".  The /bin/cc compiler on HP-UX reports a
+ XCOMM    Recursion in macro "extern" when the above define is used.
+ XCOMM -D_DL_EXPORT_UNDERSCORE
+ XCOMM    Include the above line if you use export filters and there is an entry
+ XCOMM    point to an export filter named "_TgifExportFilterMain" (and there's
+ XCOMM    no entry point named "TgifExportFilterMain").  One can see all the
+ XCOMM    entry points to an export filter by running 'nm' against it.
+ XCOMM -D_NO_XCIN
+ XCOMM    Include the above line if you do not want to include the code
+ XCOMM    that handles xcin.  Please also remove "cli_xcin.o" from
+ XCOMM    OBJ1 in Imakefile.
+ XCOMM -D_NO_CHINPUT
+ XCOMM    Include the above line if you do not want to include the code
+ XCOMM    that handles chinput.  Please also remove "chinput.o" from
+ XCOMM    OBJ1 in Imakefile.
+ XCOMM -D_NO_KINPUT
+ XCOMM    Include the above line if you do not want to include the code
+ XCOMM    that handles kinput.  Please also remove "convkinput.o" from
+ XCOMM    OBJ1 in Imakefile.
+ XCOMM -D_NO_XIM
+ XCOMM    Include the above line if you do not want to include the code
+ XCOMM    that handles X Input Method.  Please also remove "convxim.o" from
+ XCOMM    OBJ1 in Imakefile.
+ XCOMM -D_NO_NKF
+ XCOMM    Include the above line if you do not want to include the code
+ XCOMM    that handles Network Kanji Filter (NKF).  Please also remove
+ XCOMM    "nkf.o" from OBJ1 in Imakefile.
+ XCOMM -D_NO_DL_SUPPORT
+ XCOMM    Include the above line if you don't have <dlfcn.h>.  If you define
+ XCOMM    _NO_DL_SUPPORT, please use the SYS_LIBRARIES that does not contain
+ XCOMM    -ldl above.
+ XCOMM -D_NO_LOCALE_SUPPORT
+ XCOMM    Include the above line if you don't have <X11/Xlocale.h>.  If this
+ XCOMM    is the case and you don't have <locale.h>, you must also use
+ XCOMM    -D_NO_XIM because "convxim.c" assumes that you have <locale.h>.
+ XCOMM -D_METRIC_PIX_PER_INCH
+ XCOMM    Include the above line if you want to use 127 pixels per inch
+ XCOMM    when printing in the metric system.  If this line is not
+ XCOMM    included, 128 pixels per inch is used.
+ XCOMM -D_NO_GETTIMEOFDAY
+ XCOMM    Include the above line if you do not have the gettimeofday()
+ XCOMM    function but have the ftime() function.
+ XCOMM -D_TANGRAM_II
+ XCOMM    Include the above line if you want to include the Tangram-II features
+ XCOMM    by Carlos Fisch de Brito, Luiz Rogerio Goncalves de Carvalho, and
+ XCOMM    Denise Jorge de Oliveira <fisch,luiz,dezinha@land.ufrj.br> of the
+ XCOMM    Tangram-II team of the Universidade Federal do Rio de Janeiro.  These
+ XCOMM    features are under development and highly experimental.
+ XCOMM -D_TGIF_WB (obsoleted)
+ XCOMM    Include the above line if you want to include the whiteboard feature
+ XCOMM    by Renato Santana <renato@nce.ufrj.br>.
+ XCOMM -D_TGIF_WB2
+ XCOMM    Include the above line if you want to include the whiteboard feature
+ XCOMM    by Magnos Martinello <magnos@land.ufrj.br> and Raphael S. de Moraes
+ XCOMM    <raphael@land.ufrj.br>.  The whiteboard needs IP multicast support,
+ XCOMM    and therefore, can only run on IP multicast enabled kernels.  This
+ XCOMM    code is experimental and have know bugs (such as buffer overflow) and
+ XCOMM    only runs on Solaris 2.6 or above or Linux 6.x or above.  If you would
+ XCOMM    like to try it, please manipulate only small objects at this time.
+ XCOMM -D_HAS_STREAMS_SUPPORT
+ XCOMM    Include the above line in addition to -D_TGIF_WB2 if you have the
+ XCOMM    /usr/include/stropts.h file (such as Solaris 2.6 or above or Linux
+ XCOMM    6.x or above.
+ XCOMM -DBSD_COMP
+ XCOMM    Include the above line if you are compiling on a Solaris (or
+ XCOMM    possibly an SGI) machine which requires it in <sys/ioctl.h>.
+ XCOMM    (If you see the error that FIONBIO is not defined when compiling
+ XCOMM    tcp.c, then you probably need this.)
+ XCOMM -D_BACKGROUND_DONT_FORK
+ XCOMM    Try the above line if there are defunct tgif child processes.
+ XCOMM -D_NO_LSTAT
+ XCOMM    Include the above line if lstat() is not available.  In this case,
+ XCOMM    using BrowseXBitmap and BrowseXPixmap under the File Menu may cause
+ XCOMM    infinite loop if the directory structure is infinitely recursive.
+ XCOMM -D_USE_XDRAWPOINT_TO_PUT_A_POINT
+ XCOMM    Include the above line if the grid points are not visible.  This can
+ XCOMM    be used to bypass some X server bugs (such as certain Linux X server
+ XCOMM    using VGA16 screen) where the XDrawLine() Xlib call does not work
+ XCOMM    properly.
+ XCOMM -D_NO_EXTERN (obsoleted)
+ XCOMM    Include the above line in the DEFINES if you don't want to include
+ XCOMM    the extern definition for functions defined in a module.  For example,
+ XCOMM    if this option is set, then file "foo.c" will not include "foo.e",
+ XCOMM    and certain other extern definition in "foo.c" will be omitted.
+ XCOMM -D_NO_PROTO
+ XCOMM    Include the above line in the DEFINES if checking for function
+ XCOMM    prototypes is not desired.  Checking for function prototypes
+ XCOMM    are automatically enabled if you are using an ANSI or C++ compilor.
+ XCOMM    However, not all ANSI/C++ compilors are created equal.
+ XCOMM -D_BSD
+ XCOMM    Include the above line in the DEFINES if the select() function can
+ XCOMM    does not be found for AIX systems (such as RS6000).  Also, on AIX
+ XCOMM    systems, if you see garbage file names when you try to open files,
+ XCOMM    try this flag to make direct and dirent equivalent (in <sys/dir.h>).
+ XCOMM -D_NO_RAND48
+ XCOMM    Include the above line in the DEFINES if you do not have the
+ XCOMM    srand48() or drand48() functions in your system's library.
+ XCOMM -DNO_STRSTR
+ XCOMM    Include the above line in the DEFINES if you do not have the strstr()
+ XCOMM    function in your system's string library.
+ XCOMM -DINVERT_CTM_BUG
+ XCOMM    Include the above line in the DEFINES if you are using PostScript
+ XCOMM    utilities which fails when trying to invert non-invertible CTM
+ XCOMM    (e.g., muluti.ps from ftp.ucc.su.oz.au:/pub/ps_printing/multi).
+ XCOMM -DHP_LINE_BUG
+ XCOMM    Include the above line in the DEFINES if two-vertices horizontal and
+ XCOMM    verticle line segments don't draw properly on a buggy HP server.
+ XCOMM -DDONTFREECOLORS
+ XCOMM    Include the above line in the DEFINES if you don't want the black and
+ XCOMM    the white colors to be freed when tgif initializes itself.  You should
+ XCOMM    not need to do this unless you need to get around some server bugs.
+ XCOMM -DUSE_XAPPLRESDIR
+ XCOMM    Include the above line in the DEFINES if $XAPPLRESDIR/Tgif is used to
+ XCOMM    specify the resource file.  If your system does not have putenv()
+ XCOMM    (such as IBM-RT), then this won't work.
+ XCOMM -DXAPPLOADDIR_DEF
+ XCOMM    If you define USE_XAPPLRESDIR, define this to a default directory
+ XCOMM    to use in case $XAPPLRESDIR isn't set.
+ XCOMM -DUSE_XT_INITIALIZE
+ XCOMM    This will cause the XToolkit to be initialized so that the X defaults
+ XCOMM    are obtained from the Xt directories.  This should only be used when
+ XCOMM    USE_XAPPLRESDIR option is NOT used.  Please remember to use the
+ XCOMM    LOCAL_LIBRARIES with $(XTOOLLIB) $(XMULIB) above.
+ XCOMM -DNO_THIN_LINE
+ XCOMM    Include the above line in the DEFINES if a line width of 0 causes
+ XCOMM    your server to crash.  This is to get around a bug in some X servers.
+ XCOMM -DTHIN_OVAL_AND_ARC
+ XCOMM    Include the above line in the DEFINES if you want 0 width arcs to
+ XCOMM    be used when the width of an arc is less than or equal to 1.
+ XCOMM    (Sun3 server has a bug that makes drawing ovals and arcs with
+ XCOMM    width other than 0 VERY slow).
+ XCOMM -DKEEP_WHEN_PRINT
+ XCOMM    Include the above line in the DEFINES if you don't want the temp
+ XCOMM    file to be deleted after sending the print job to the printer.
+ XCOMM    (Some VMS systems might require this flag to be used.)
+ XCOMM -DPRINT_CMD=\"lpr\"
+ XCOMM    Include the above line in the DEFINES if you want to configure tgif
+ XCOMM    to use a default print command.
+ XCOMM -DNOTR4MODE
+ XCOMM    Include the above line in the DEFINES if you are running X11R3.
+ XCOMM    This will cause tgif NOT to use some X11R4 window manager related
+ XCOMM    functions that's not present in R3.
+ XCOMM -DMAPBEFORESELECT
+ XCOMM    Include the above line in the DEFINES to call XMapWindow() before
+ XCOMM    calling XSelectInput().  This might be needed to get around some
+ XCOMM    server bugs.
+ XCOMM -DDONT_FREE_COLORMAP
+ XCOMM    Include the above line in the DEFINES if you don't want the colormap
+ XCOMM    to be freed when tgif exits.
+ XCOMM -DA4PAPER
+ XCOMM    Include the above line in the DEFINES if you want to print on A4 paper
+ XCOMM    (8.25in by 11.7in or about 21cm by 29.7cm).
+ 
+ OBJ1 =	align.o animate.o arc.o attr.o auxtext.o \
+ 	box.o button.o \
+ 	chinput.o choice.o choose.o cli_xcin.o convkinput.o \
+ 	convxim.o cmd.o color.o cutpaste.o cursor.o \
+ 	dialog.o drawing.o dup.o \
+ 	edit.o eps.o exec.o expr.o \
+ 	file.o font.o ftp.o \
+ 	grid.o group.o \
+ 	help.o http.o \
+ 	imgproc.o import.o ini.o inmethod.o \
+ 	mainloop.o mainmenu.o mark.o markup.o menu.o \
+ 		menuinfo.o miniline.o move.o msg.o \
+ 	names.o navigate.o nkf.o \
+ 	obj.o oval.o \
+ 	page.o pattern.o pin.o poly.o polygon.o ps.o \
+ 	raster.o rcbox.o rect.o remote.o ruler.o \
+ 	scroll.o select.o setup.o shape.o shortcut.o \
+ 		special.o spline.o stk.o stream.o stretch.o \
+ 		strtbl.o \
+ 	tangram2.o tgif_dbg.o \
+ 	tcp.o text.o \
+ 	util.o \
+ 	version.o vms_comp.o \
+ 	wb.o wb1.o wb2.o wb3.o wb_buff.o wb_mcast.o \
+ 	xbitmap.o xpixmap.o xprtfltr.o
+ 
+ OBJS1 = tgif.o $(OBJ1)
+ OBJS2 = prtgif.o
+ OBJS3 = testdrive.o $(OBJ1)
+ FRONTENDOBJS = frontend.o $(OBJ1)
+ 
+ CURRENTDIR =./
+ 
+ SRCS1 = $(CURRENTDIR)*.c
+ SRCS2 = 
+ SRCS3 = 
+ 
+ ComplexProgramTarget_1(tgwb,$(LOCAL_LIBRARIES),NullParameter)
+ /*
+  * ComplexProgramTarget_2(prtgif,NullParameter,NullParameter)
+  * ComplexProgramTarget_3(testdrive,$(LOCAL_LIBRARIES),NullParameter)
+  */
+ 
+ /*
+  * NormalRelocatableTarget(frontend11,$(FRONTENDOBJS))
+  */
+ 
+ MakeDirectories(install,$(TGIFDIR))
+ InstallNonExec(tgif.Xdefaults,$(TGIFDIR))
+ InstallNonExec(tgificon.eps,$(TGIFDIR))
+ InstallNonExec(tgificon.obj,$(TGIFDIR))
+ InstallNonExec(tgificon.xbm,$(TGIFDIR))
+ InstallNonExec(tgificon.xpm,$(TGIFDIR))
+ InstallNonExec(tangram.sym,$(TGIFDIR))
+ InstallNonExec(eq4.sym,$(TGIFDIR))
+ InstallNonExec(eq4-2x.sym,$(TGIFDIR))
+ InstallNonExec(eq4-ps2epsi.sym,$(TGIFDIR))
+ InstallNonExec(eq4-epstool.sym,$(TGIFDIR))
+ InstallNonExec(keys.obj,$(TGIFDIR))
+ 
+ .SUFFIXES: .l .man
+ 
+ .l.man:
+ 	rm -f $*.man
+ 	cp $*.l $*.man
+ 
+ .e.o:
+ 
+ SPICEDIR =spice/
+ XBMDIR =xbm/
+ 
+ OBJDEMO = an-sr-flip-flop.obj fonts.obj slide-demo.obj keys.obj \
+ 	  $(SPICEDIR)*.obj launch-demo.obj launch-demo-1.obj
+ SYMDEMO = flip-flop.sym nand2.sym pin.sym tangram.sym $(SPICEDIR)*.sym \
+ 	  eq4.sym eq4-2x.sym eq4-ps2epsi.sym eq4-epstool.sym
+ MISCTAR = /**/*.man README README.tgwb Copyright tgif.pl $(SPICEDIR)*.mod \
+ 		example.tex HISTORY /**/*.uu testdrive.pl frontend.pl
+ BACKUPDIR = /mnt/halfmoon/home/william/src/tgif/v4/backup
+ 
+ distr: tar versioninfo
+ 
+ uu:
+ 	rm -f /**/*.uu /**/*.cat /**/*.cat.Z
+ 	groff -Tascii -man tgif.man > tgif.cat; compress tgif.cat
+ 	groff -Tascii -man prtgif.man > prtgif.cat; compress prtgif.cat
+ 	uuencode tgif.cat.Z tgif.cat.Z > tgif.cat.Z.uu
+ 	uuencode prtgif.cat.Z prtgif.cat.Z > prtgif.cat.Z.uu
+ 	rm -f /**/*.cat.Z
+ 
+ rcstar:
+ 	@rm -f home/RCS3.tar.gz.save
+ 	@if [ -f home/RCS3.tar.gz ]; then \
+ 		mv home/RCS3.tar.gz home/RCS3.tar.gz.save; \
+ 	fi
+ 	tar cf home/RCS3.tar RCS xbm.RCS
+ 	gzip home/RCS3.tar
+ 	ls -l home/RCS3.tar.gz
+ 
+ spec:
+ 	@rm -f tgif.spec
+ 	echo "%define ver	$(TGIFVERSION)" > tgif.spec
+ 	cat tgif.spec.in >> tgif.spec
+ 
+ tar: uu spec
+ 	rm -f tgif-$(TGIFVERSION).tar/**/*
+ 	tar cvf tgif-$(TGIFVERSION).tar /**/*.c /**/*.e /**/*.h \
+ 		Makefile.noimake Imakefile Imakefile.tgwb Tgif.tmpl \
+ 		Tgif.tmpl-/**/* descrip./**/??? tgif.spec.in tgif.spec \
+ 		make./**/* VMS_MAKE_TGIF.COM tgificon.obj $(XBMDIR)*.xbm \
+ 		tgificon.xbm tgificon.xpm tgif.Xdefaults tgificon.eps \
+ 		$(OBJDEMO) \
+ 		$(SYMDEMO) \
+ 		$(MISCTAR) \
+ 		po
+ 	rm -rf tgif-$(TGIFVERSION)
+ 	mkdir tgif-$(TGIFVERSION)
+ 	cd tgif-$(TGIFVERSION); tar xvf ../tgif-$(TGIFVERSION).tar; cd ..
+ 	rm -f tgif-$(TGIFVERSION).tar
+ 	tar cvf tgif-$(TGIFVERSION).tar tgif-$(TGIFVERSION)
+ 	rm -rf tgif-$(TGIFVERSION)
+ 	gzip tgif-$(TGIFVERSION).tar
+ 	rm -f /**/*.cat.Z.uu
+ 
+ rpm-src: tar
+ 	rpm -ta tgif-$(TGIFVERSION).tar.gz
+ 
+ rpm-bin: tar
+ 	rpm -tb tgif-$(TGIFVERSION).tar.gz
+ 
+ backup: distr
+ 	rm -rf $(BACKUPDIR).old
+ 	mv $(BACKUPDIR) $(BACKUPDIR).old
+ 	mkdir $(BACKUPDIR)
+ 	tar cf - RCS VersionInfo tgif-$(TGIFVERSION).tar.gz | \
+ 		(cd $(BACKUPDIR); tar xvpf -)
+ 
+ MAN_1 = README /**/*.man Imakefile Copyright
+ BASIC_1 = Makefile.noimake descrip./**/* make./**/* HISTORY tgif.Xdefaults \
+ 	  Tgif.tmpl Tgif.tmpl-/**/* VMS_MAKE_TGIF.COM
+ 
+ MISC_1 = an-sr-flip-flop.obj fonts.obj slide-demo.obj keys.obj \
+ 	 launch-demo.obj launch-demo-1.obj \
+ 	 flip-flop.sym nand2.sym pin.sym tangram.sym tgificon.xbm \
+ 	 eq4.sym eq4-2x.sym eq4-ps2epsi.sym eq4-epstool.sym
+ MISC_2 = tgif.pl testdrive.pl frontend.pl tgificon.obj example.tex
+ MISC_3 = tgificon.xpm tgificon.eps /**/*.uu
+ SPICE_1 = spice $(SPICEDIR)*.obj $(SPICEDIR)*.sym $(SPICEDIR)*.mod
+ 
+ shar: uu
+ 	rm -f tgif-$(TGIFVERSION).shar./**/*
+ 	shar -otgif-$(TGIFVERSION).shar.1 -n1 -e38 $(MAN_1)
+ 	shar -otgif-$(TGIFVERSION).shar.2 -n2 -e38 $(BASIC_1)
+ 	shar -otgif-$(TGIFVERSION).shar.3 -n3 -e38 a[a-n]/**/*.c
+ 	shar -otgif-$(TGIFVERSION).shar.4 -n4 -e38 a[o-s]/**/*.c
+ 	shar -otgif-$(TGIFVERSION).shar.5 -n5 -e38 a[t-z]/**/*.c
+ 	shar -otgif-$(TGIFVERSION).shar.6 -n6 -e38 b/**/*.c
+ 	shar -otgif-$(TGIFVERSION).shar.7 -n7 -e38 c[a-m]/**/*.c
+ 	shar -otgif-$(TGIFVERSION).shar.8 -n8 -e38 c[n-z]/**/*.c
+ 	shar -otgif-$(TGIFVERSION).shar.9 -n9 -e38 d/**/*.c
+ 	shar -otgif-$(TGIFVERSION).shar.10 -n10 -e38 e[a-d]/**/*.c
+ 	shar -otgif-$(TGIFVERSION).shar.11 -n11 -e38 e[e-z]/**/*.c
+ 	shar -otgif-$(TGIFVERSION).shar.12 -n12 -e38 f[a-i]/**/*.c
+ 	shar -otgif-$(TGIFVERSION).shar.13 -n13 -e38 f[j-z]/**/*.c
+ 	shar -otgif-$(TGIFVERSION).shar.14 -n14 -e38 [g-l]/**/*.c
+ 	shar -otgif-$(TGIFVERSION).shar.15 -n15 -e38 ma/**/*.c
+ 	shar -otgif-$(TGIFVERSION).shar.16 -n16 -e38 m[b-e]/**/*.c
+ 	shar -otgif-$(TGIFVERSION).shar.17 -n17 -e38 m[f-z]/**/*.c
+ 	shar -otgif-$(TGIFVERSION).shar.18 -n18 -e38 n/**/*.c
+ 	shar -otgif-$(TGIFVERSION).shar.19 -n19 -e38 o/**/*.c p[a-n]/**/*.c
+ 	shar -otgif-$(TGIFVERSION).shar.20 -n20 -e38 poly.c
+ 	shar -otgif-$(TGIFVERSION).shar.21 -n21 -e38 polygon.c p[p-z]/**/*.c
+ 	shar -otgif-$(TGIFVERSION).shar.22 -n22 -e38 r[a-c]/**/*.c stk/**/*.c
+ 	shar -otgif-$(TGIFVERSION).shar.23 -n23 -e38 r[d-z]/**/*.c
+ 	shar -otgif-$(TGIFVERSION).shar.24 -n24 -e38 sc/**/*.c sel/**/*.c
+ 	shar -otgif-$(TGIFVERSION).shar.25 -n25 -e38 set/**/*.c s[f-p]/**/*.c
+ 	shar -otgif-$(TGIFVERSION).shar.26 -n26 -e38 str/**/*.c
+ 	shar -otgif-$(TGIFVERSION).shar.27 -n27 -e38 text.c
+ 	shar -otgif-$(TGIFVERSION).shar.28 -n28 -e38 testdrive.c t[f-z]/**/*.c \
+ 				[u-w]/**/*.c
+ 	shar -otgif-$(TGIFVERSION).shar.29 -n29 -e38 x[a-m]/**/*.c
+ 	shar -otgif-$(TGIFVERSION).shar.30 -n30 -e38 x[n-z]/**/*.c
+ 	shar -otgif-$(TGIFVERSION).shar.31 -n31 -e38 [a-n]/**/*.e
+ 	shar -otgif-$(TGIFVERSION).shar.32 -n32 -e38 [o-z]/**/*.e /**/*.h
+ 	shar -otgif-$(TGIFVERSION).shar.33 -n33 -e38 xbm xbm/[a-k]/**/*.xbm \
+ 				xbm/l[a-s]/**/*.xbm
+ 	shar -otgif-$(TGIFVERSION).shar.34 -n34 -e38 xbm/l[t-z]/**/*.xbm \
+ 				xbm/[m-z]/**/*.xbm
+ 	shar -otgif-$(TGIFVERSION).shar.35 -n35 -e38 $(MISC_1)
+ 	shar -otgif-$(TGIFVERSION).shar.36 -n36 -e38 $(MISC_2)
+ 	shar -otgif-$(TGIFVERSION).shar.37 -n37 -e38 $(MISC_3)
+ 	shar -otgif-$(TGIFVERSION).shar.38 -n38 -e38 $(SPICE_1)
+ 
+ versioninfo:
+ 	what .psmac /**/*.c /**/*.e /**/*.h Makefile.noimake Imakefile \
+ 		Tgif.tmpl /**/*.man tgif.pl README example.tex HISTORY \
+ 		tgificon.obj an-sr-flip-flop.obj fonts.obj slide-demo.obj \
+ 		keys.obj flip-flop.sym nand2.sym pin.sym tangram.sym \
+ 		eq4.sym eq4-2x.sym eq4-ps2epsi.sym eq4-epstool.sym \
+ 		$(SPICEDIR)*.obj $(SPICEDIR)*.sym testdrive.pl frontend.pl \
+ 		descrip.mms descrip.opt tgifmacro.ps $(XBMDIR)*.xbm \
+ 		tgificon.xbm tgificon.xpm tgif.Xdefaults tgificon.eps \
+ 		VMS_MAKE_TGIF.COM launch-demo.obj launch-demo-1.obj \
+ 		Copyright make./**/* Tgif.tmpl-/**/* tgif.spec.in \
+ 		Imakefile.tgwb README.tgwb \
+ 		> VersionInfo/Distribution/tgif-$(TGIFVERSION)
*** README.tgwb.orig	Tue Apr 18 17:13:12 2000
--- README.tgwb	Tue Apr 18 17:13:12 2000
***************
*** 0 ****
--- 1,42 ----
+ /*
+  * Author:	William Chia-Wei Cheng (william@cs.ucla.edu)
+  *
+  * @(#)$Header: /mm/src/tgif/v4/RCS/README.tgwb,v 4.4 2000/04/18 21:08:46 william Exp $
+  */
+ 
+ This is the ``tgwb'' README file.
+ 
+ Tgwb is a vector-drawing coorporative whiteboard application based on tgif.
+ Tgwb is tested on Linux and Solaris platforms, and it requires IP-multicast.
+ Thanks to the team members of the research group lead by Professor Edmundo
+ de Souze e Silva <edmundo@land.ufrj.br> at the Federal University of
+ Rio de Janeiro.
+ 
+ (The current release of tgwb has a few known bugs.  The major ones being
+ that (1) it uses fixed size buffers in communication; therefore, when you
+ operate on a large object, you may get an error message saying that the
+ operation is canceled.  (2) There is no privison made for joining a
+ whileboard in session; the way to get around this problem is to select
+ New from the File Menu of a tgwb to clear all whiteboards.)
+ 
+ 1) Please read the "Copyright" file in this distribution for the copyright
+    and licensing information.
+ 
+ 2) Tgwb is basically tgif with 2 noted differences:
+ 
+    a) Please use Imakefile.tgwb instead of Imakefile when compiling tgwb.
+       Please do the following before you install:
+ 
+          mv Imakefile Imakefile.tgif
+          cp Imakefile.tgwb Imakefile
+ 
+    b) Follow the instructions in the README file for tgif.  Make all the
+       selections and modifications you need for Tgif.tmpl.  Right before
+       you build, do the following in Tgif.tmpl:
+ 
+       i)  Replace "tgif" in the PROGRAMS line by "tgwb"
+       ii) Append the following compiler option to the MOREDEFINES line:
+ 
+              -D_TGIF_WB2
+ 
+       Then build tgwb (instead of doing "make tgif", do "make tgwb").