From 6d99e5326e0e4dd242374233d59c19a047e0a718 Mon Sep 17 00:00:00 2001 From: Tim Edwards Date: Wed, 4 Jan 2023 14:08:39 -0500 Subject: [PATCH] Added a command option "setlabel box" to modify the attachment box of a label from the command line. Also fixed a long-standing irritation that "setlabel" would change the properties of a label in the edit cell but not in the selection itself, which would cause the label to be drawn both with the original properties in the selection and the new properties in the edit cell. Now both views will track the same changes. --- VERSION | 2 +- commands/CmdRS.c | 186 ++++++++++++++++++++++++++++++++++------- commands/CmdSubrs.c | 3 +- doc/html/setlabel.html | 38 +++++---- select/selEnum.c | 63 +++++++++++++- select/select.h | 1 + 6 files changed, 244 insertions(+), 49 deletions(-) diff --git a/VERSION b/VERSION index f5e8a281..e4fb30b5 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.3.358 +8.3.359 diff --git a/commands/CmdRS.c b/commands/CmdRS.c index 14633757..961b701e 100644 --- a/commands/CmdRS.c +++ b/commands/CmdRS.c @@ -1635,17 +1635,18 @@ cmdLabelTextFunc(label, cellUse, transform, text) TxPrintf("%s\n", label->lab_text); #endif } - else + else if (strcmp(text, label->lab_text)) { - if (strcmp(text, label->lab_text)) - { - newlab = DBPutFontLabel(cellDef, &label->lab_rect, label->lab_font, + newlab = DBPutFontLabel(cellDef, &label->lab_rect, label->lab_font, label->lab_size, label->lab_rotate, &label->lab_offset, label->lab_just, text, label->lab_type, label->lab_flags, label->lab_port); - DBEraseLabelsByContent(cellDef, &label->lab_rect, -1, label->lab_text); - DBWLabelChanged(cellDef, newlab, DBW_ALLWINDOWS); - } + DBEraseLabelsByContent(cellDef, &label->lab_rect, -1, label->lab_text); + DBWLabelChanged(cellDef, newlab, DBW_ALLWINDOWS); + DBWHLRedraw(SelectRootDef, &SelectDef->cd_extended, TRUE); + DBWAreaChanged(SelectDef, &SelectDef->cd_extended, DBW_ALLWINDOWS, + &DBAllButSpaceBits); + DBCellSetModified(cellDef, TRUE); } return 0; } @@ -1661,6 +1662,7 @@ cmdLabelRotateFunc(label, cellUse, transform, value) #ifdef MAGIC_WRAPPER Tcl_Obj *lobj; #endif + Rect selarea; if (value == NULL) { @@ -1673,7 +1675,7 @@ cmdLabelRotateFunc(label, cellUse, transform, value) TxPrintf("%d\n", label->lab_rotate); #endif } - else + else if (label->lab_rotate != *value) { DBUndoEraseLabel(cellDef, label); DBWLabelChanged(cellDef, label, DBW_ALLWINDOWS); @@ -1681,6 +1683,7 @@ cmdLabelRotateFunc(label, cellUse, transform, value) DBFontLabelSetBBox(label); DBUndoPutLabel(cellDef, label); DBWLabelChanged(cellDef, label, DBW_ALLWINDOWS); + DBCellSetModified(cellDef, TRUE); } return 0; } @@ -1708,7 +1711,7 @@ cmdLabelSizeFunc(label, cellUse, transform, value) TxPrintf("%g\n", (double)label->lab_size / 8.0); #endif } - else + else if (label->lab_size != *value) { DBUndoEraseLabel(cellDef, label); DBWLabelChanged(cellDef, label, DBW_ALLWINDOWS); @@ -1716,6 +1719,7 @@ cmdLabelSizeFunc(label, cellUse, transform, value) DBFontLabelSetBBox(label); DBUndoPutLabel(cellDef, label); DBWLabelChanged(cellDef, label, DBW_ALLWINDOWS); + DBCellSetModified(cellDef, TRUE); } return 0; } @@ -1743,7 +1747,7 @@ cmdLabelJustFunc(label, cellUse, transform, value) TxPrintf("%s\n", GeoPosToName(label->lab_just)); #endif } - else + else if (label->lab_just != *value) { DBUndoEraseLabel(cellDef, label); DBWLabelChanged(cellDef, label, DBW_ALLWINDOWS); @@ -1751,6 +1755,7 @@ cmdLabelJustFunc(label, cellUse, transform, value) DBFontLabelSetBBox(label); DBUndoPutLabel(cellDef, label); DBWLabelChanged(cellDef, label, DBW_ALLWINDOWS); + DBCellSetModified(cellDef, TRUE); } return 0; } @@ -1828,6 +1833,7 @@ cmdLabelStickyFunc(label, cellUse, transform, value) DBUndoEraseLabel(cellDef, label); label->lab_flags = newvalue; DBUndoPutLabel(cellDef, label); + DBCellSetModified(cellDef, TRUE); } } return 0; @@ -1861,7 +1867,7 @@ cmdLabelOffsetFunc(label, cellUse, transform, point) (double)(label->lab_offset.p_y) / 8.0); #endif } - else + else if (!GEO_SAMEPOINT(label->lab_offset, *point)) { DBUndoEraseLabel(cellDef, label); DBWLabelChanged(cellDef, label, DBW_ALLWINDOWS); @@ -1869,6 +1875,53 @@ cmdLabelOffsetFunc(label, cellUse, transform, point) DBFontLabelSetBBox(label); DBUndoPutLabel(cellDef, label); DBWLabelChanged(cellDef, label, DBW_ALLWINDOWS); + DBCellSetModified(cellDef, TRUE); + } + return 0; +} + +int +cmdLabelRectFunc(label, cellUse, transform, rect) + Label *label; + CellUse *cellUse; + Transform *transform; + Rect *rect; +{ + CellDef *cellDef = cellUse->cu_def; +#ifdef MAGIC_WRAPPER + Tcl_Obj *lobj, *pobj; +#endif + + if (rect == NULL) + { +#ifdef MAGIC_WRAPPER + lobj = Tcl_GetObjResult(magicinterp); + pobj = Tcl_NewListObj(0, NULL); + Tcl_ListObjAppendElement(magicinterp, lobj, pobj); + Tcl_ListObjAppendElement(magicinterp, pobj, + Tcl_NewIntObj((double)label->lab_rect.r_xbot)); + Tcl_ListObjAppendElement(magicinterp, pobj, + Tcl_NewIntObj((double)label->lab_rect.r_ybot)); + Tcl_ListObjAppendElement(magicinterp, pobj, + Tcl_NewIntObj((double)label->lab_rect.r_xtop)); + Tcl_ListObjAppendElement(magicinterp, pobj, + Tcl_NewIntObj((double)label->lab_rect.r_ytop)); + Tcl_SetObjResult(magicinterp, lobj); +#else + TxPrintf("%d %d %d %d\n", + label->lab_rect.r_xbot, label->lab_rect.r_ybot, + label->lab_rect.r_xtop, label->lab_rect.r_ytop); +#endif + } + else if (!GEO_SAMERECT(label->lab_rect, *rect)) + { + DBUndoEraseLabel(cellDef, label); + DBWLabelChanged(cellDef, label, DBW_ALLWINDOWS); + label->lab_rect = *rect; + DBFontLabelSetBBox(label); + DBUndoPutLabel(cellDef, label); + DBWLabelChanged(cellDef, label, DBW_ALLWINDOWS); + DBCellSetModified(cellDef, TRUE); } return 0; } @@ -1902,7 +1955,7 @@ cmdLabelFontFunc(label, cellUse, transform, font) TxPrintf("%s\n", DBFontList[label->lab_font]->mf_name); #endif } - else + else if (label->lab_font != *font) { DBUndoEraseLabel(cellDef, label); DBWLabelChanged(cellDef, label, DBW_ALLWINDOWS); @@ -1911,6 +1964,7 @@ cmdLabelFontFunc(label, cellUse, transform, font) DBFontLabelSetBBox(label); DBUndoPutLabel(cellDef, label); DBWLabelChanged(cellDef, label, DBW_ALLWINDOWS); + DBCellSetModified(cellDef, TRUE); } return 0; } @@ -1952,16 +2006,17 @@ cmdLabelFontFunc(label, cellUse, transform, font) * ---------------------------------------------------------------------------- */ -#define SETLABEL_TEXT 0 +#define SETLABEL_BOX 0 #define SETLABEL_FONT 1 #define SETLABEL_FONTLIST 2 #define SETLABEL_JUSTIFY 3 -#define SETLABEL_SIZE 4 +#define SETLABEL_LAYER 4 #define SETLABEL_OFFSET 5 #define SETLABEL_ROTATE 6 -#define SETLABEL_STICKY 7 -#define SETLABEL_LAYER 8 -#define SETLABEL_HELP 9 +#define SETLABEL_SIZE 7 +#define SETLABEL_STICKY 8 +#define SETLABEL_TEXT 9 +#define SETLABEL_HELP 10 void CmdSetLabel(w, cmd) @@ -1972,6 +2027,7 @@ CmdSetLabel(w, cmd) int locargc, argstart = 1; char **msg; Point offset; + Rect rect; TileType ttype; int option; bool doDefault = FALSE; @@ -1984,15 +2040,16 @@ CmdSetLabel(w, cmd) static char *cmdLabelSetOption[] = { - "text change/get label text", + "box change/get label box", "font change/get label font", "fontlist list available fonts", "justify change/get label justification", - "size change/get label size", + "layer change/get layer type", "offset change/get label offset", "rotate change/get label rotation", + "size change/get label size", "sticky [true|false] change/get sticky property", - "layer change/get layer type", + "text change/get label text", "help print this help info", NULL }; @@ -2021,11 +2078,16 @@ CmdSetLabel(w, cmd) } } - if (locargc < 2 || locargc > 4) + if (locargc < 2) option = SETLABEL_HELP; else option = Lookup(cmd->tx_argv[argstart], cmdLabelSetOption); + if ((option != SETLABEL_BOX) && (locargc > 4)) + option = SETLABEL_HELP; + else if ((option == SETLABEL_BOX) && (locargc > 6)) + option = SETLABEL_HELP; + switch (option) { case SETLABEL_FONTLIST: @@ -2049,7 +2111,7 @@ CmdSetLabel(w, cmd) } else if (EditCellUse) { - SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL, + SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL, cmdLabelTextFunc, (locargc == 3) ? (ClientData)cmd->tx_argv[argstart + 1] : (ClientData)NULL); } @@ -2117,7 +2179,7 @@ CmdSetLabel(w, cmd) } else if (EditCellUse) { - SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL, + SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL, cmdLabelFontFunc, (locargc == 3) ? (ClientData)&font : (ClientData)NULL); } @@ -2147,7 +2209,7 @@ CmdSetLabel(w, cmd) } else if (EditCellUse) { - SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL, + SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL, cmdLabelJustFunc, (locargc == 3) ? (ClientData)&pos : (ClientData)NULL); } @@ -2176,7 +2238,7 @@ CmdSetLabel(w, cmd) } else if (EditCellUse) { - SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL, + SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL, cmdLabelSizeFunc, (locargc == 3) ? (ClientData)&size : (ClientData)NULL); } @@ -2188,8 +2250,9 @@ CmdSetLabel(w, cmd) char *yp; if ((yp = strchr(cmd->tx_argv[argstart + 1], ' ')) != NULL) { + *yp = '\0'; offset.p_x = cmdScaleCoord(w, cmd->tx_argv[argstart + 1], TRUE, TRUE, 8); - offset.p_y = cmdScaleCoord(w, yp, TRUE, FALSE, 8); + offset.p_y = cmdScaleCoord(w, yp + 1, TRUE, FALSE, 8); } else { @@ -2224,12 +2287,79 @@ CmdSetLabel(w, cmd) } else if (EditCellUse) { - SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL, + SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL, cmdLabelOffsetFunc, (locargc != 2) ? (ClientData)&offset : (ClientData)NULL); } break; + case SETLABEL_BOX: + if (doDefault) + { + TxError("Cannot set a default label box.\n"); + } + else if (EditCellUse) + { + if (locargc == 3) + { + /* Useful with [box values] */ + char *yp = cmd->tx_argv[argstart + 1]; + rect.r_xbot = cmdScaleCoord(w, yp, TRUE, TRUE, 1); + yp = strchr(yp, ' '); + if (yp != NULL) + { + *yp = '\0'; + yp++; + while (isspace(*yp) && (*yp != '\0')) yp++; + rect.r_ybot = cmdScaleCoord(w, yp, TRUE, FALSE, 1); + yp = strchr(yp, ' '); + if (yp != NULL) + { + *yp = '\0'; + yp++; + while (isspace(*yp) && (*yp != '\0')) yp++; + rect.r_xtop = cmdScaleCoord(w, yp, TRUE, TRUE, 1); + yp = strchr(yp, ' '); + if (yp != NULL) + { + *yp = '\0'; + yp++; + while (isspace(*yp) && (*yp != '\0')) yp++; + rect.r_ytop = cmdScaleCoord(w, yp, TRUE, FALSE, 1); + } + else + TxError("Label box requires four coordinates.\n"); + } + else + { + rect.r_xtop = rect.r_xbot; + rect.r_ytop = rect.r_ybot; + yp = cmd->tx_argv[argstart + 1]; + } + } + else + TxError("Label box requires four coordinates.\n"); + + if (yp == NULL) break; /* Error condition */ + } + else if (locargc == 6) + { + rect.r_xbot = cmdScaleCoord(w, cmd->tx_argv[argstart + 1], + TRUE, TRUE, 1); + rect.r_ybot = cmdScaleCoord(w, cmd->tx_argv[argstart + 2], + TRUE, FALSE, 1); + rect.r_xtop = cmdScaleCoord(w, cmd->tx_argv[argstart + 3], + TRUE, TRUE, 1); + rect.r_ytop = cmdScaleCoord(w, cmd->tx_argv[argstart + 4], + TRUE, FALSE, 1); + } + SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL, + cmdLabelRectFunc, + ((locargc == 6) || (locargc == 3)) ? + (ClientData)&rect : (ClientData)NULL); + } + break; + case SETLABEL_ROTATE: if (locargc == 3) { @@ -2252,7 +2382,7 @@ CmdSetLabel(w, cmd) } else if (EditCellUse) { - SelEnumLabels(&DBAllTypeBits, TRUE, (bool *)NULL, + SelEnumLabelsMirror(&DBAllTypeBits, TRUE, (bool *)NULL, cmdLabelRotateFunc, (locargc == 3) ? (ClientData)&rotate : (ClientData)NULL); } diff --git a/commands/CmdSubrs.c b/commands/CmdSubrs.c index d7fc1fcd..53feb07f 100644 --- a/commands/CmdSubrs.c +++ b/commands/CmdSubrs.c @@ -201,7 +201,8 @@ cmdScaleCoord(w, arg, is_relative, is_x, scale) return round(dval); } } - dval /= CIFGetOutputScale(mscale); + if (!isspace(*endptr)) + dval /= CIFGetOutputScale(mscale); return round(dval); } diff --git a/doc/html/setlabel.html b/doc/html/setlabel.html index fc49a457..0a7bedbb 100644 --- a/doc/html/setlabel.html +++ b/doc/html/setlabel.html @@ -29,9 +29,10 @@ Manipulate rendered font labels
where option is one of the following:
-
text [string] -
Report the text string of all selected labels, or change - the text string of selected labels to string. +
box [llx lly urx ury] +
Report the bounds of the attachment box for all selected + labels, or set the coordinates of the attachment box to + the indicated values.
font [name [scale]]
Report the font of all selected labels, or set the font to the font named name, where name is one @@ -62,12 +63,13 @@ Manipulate rendered font labels
Report the justification of all selected labels, or change the justification to position, which may be any compass direction or "center". -
size [value] -
Report the size of all selected labels, or change the size of - selected labels to value, which may be given in units - of lambda, or a metric measurement (e.g., "1um"). The - text will be adjusted so that the height of capitalized text - from the text baseline is equal to the requested value. +
layer [name] +
Report the layer type to which the label is attached. + If the optional name is given, and is a valid layer + name, then the label is modified to be attached to that + layer type. Note that if the layer is not also declared + "sticky" (see below), then it is likely to be reattached to + the original layer during certain operations.
offset [x y]
Report the offset of all selected labels (in x y pairs), or change the offset, which is the spacing between the point @@ -88,13 +90,12 @@ Manipulate rendered font labels such that it occupies a specific place with respect to the cell layout, then it will always appear in that same place regardless of how the cell is oriented in the hierarchy of a layout. -
layer [name] -
Report the layer type to which the label is attached. - If the optional name is given, and is a valid layer - name, then the label is modified to be attached to that - layer type. Note that if the layer is not also declared - "sticky" (see below), then it is likely to be reattached to - the original layer during certain operations. +
size [value] +
Report the size of all selected labels, or change the size of + selected labels to value, which may be given in units + of lambda, or a metric measurement (e.g., "1um"). The + text will be adjusted so that the height of capitalized text + from the text baseline is equal to the requested value.
sticky [true|false]
Report the status of the "sticky" flag for the label. Labels which have the "sticky" flag set can only attach to the @@ -104,6 +105,9 @@ Manipulate rendered font labels assigned to "space". Value returned is 1 (true) or 0 (false). If "true" or "false" is specified, then the sticky flag is set or cleared, respectively. +
text [string] +
Report the text string of all selected labels, or change + the text string of selected labels to string.
@@ -125,7 +129,7 @@ Manipulate rendered font labels value of the default is returned. The default values are applied when the "label command is issued without the full set of values. The -default option may be used with any label - property except for text. + property except for text and box.

The default values, if not changed by using the -default option, diff --git a/select/selEnum.c b/select/selEnum.c index 28e4cc52..b59b0964 100644 --- a/select/selEnum.c +++ b/select/selEnum.c @@ -733,7 +733,7 @@ selEnumCFunc2(scx, arg) /* * ---------------------------------------------------------------------------- * - * SelEnumLabels -- + * SelEnumLabelsBase -- * * Find all selected labels, and call the client's procedure for * each label found. Only consider labels attached to "layers", @@ -771,11 +771,14 @@ selEnumCFunc2(scx, arg) */ int -SelEnumLabels(layers, editOnly, foundNonEdit, func, clientData) +SelEnumLabelsBase(layers, editOnly, doMirror, foundNonEdit, func, clientData) TileTypeBitMask *layers; /* Find labels on these layers. */ bool editOnly; /* TRUE means only find labels that are * both selected and in the edit cell. */ + bool doMirror; /* If TRUE, apply the function to both the + * label in the selection and in the edit cell. + */ bool *foundNonEdit; /* If non-NULL, this word is set to TRUE * if there are selected labels that aren't * in the edit cell, FALSE otherwise. @@ -837,11 +840,67 @@ SelEnumLabels(layers, editOnly, foundNonEdit, func, clientData) if ((*func)(arg.sea_foundLabel, arg.sea_foundUse, &arg.sea_foundTrans, clientData) != 0) return 1; + + if (doMirror) + (*func)(selLabel, SelectUse, &SelectUse->cu_transform, clientData); } return 0; } +/* + * ---------------------------------------------------------------------------- + * SelEnumLabels -- + * + * Wrapper for SelEnumLabelsBase() with doMirror set to FALSE. + * + * ---------------------------------------------------------------------------- + */ + +int +SelEnumLabels(layers, editOnly, foundNonEdit, func, clientData) + TileTypeBitMask *layers; /* Find labels on these layers. */ + bool editOnly; /* TRUE means only find labels that are + * both selected and in the edit cell. + */ + bool *foundNonEdit; /* If non-NULL, this word is set to TRUE + * if there are selected labels that aren't + * in the edit cell, FALSE otherwise. + */ + int (*func)(); /* Function to call for each label found. */ + ClientData clientData; /* Argument to pass through to func. */ +{ + return SelEnumLabelsBase(layers, editOnly, FALSE, foundNonEdit, func, clientData); +} + +/* + * ---------------------------------------------------------------------------- + * SelEnumLabelsMirror -- + * + * Wrapper for SelEnumLabelsBase() with doMirror set to TRUE. Function + * "func" is applied to both the label in the edit cell and in the + * selection. Used when modifying labels so that the selection view + * tracks the changes made to each label. + * + * ---------------------------------------------------------------------------- + */ + +int +SelEnumLabelsMirror(layers, editOnly, foundNonEdit, func, clientData) + TileTypeBitMask *layers; /* Find labels on these layers. */ + bool editOnly; /* TRUE means only find labels that are + * both selected and in the edit cell. + */ + bool *foundNonEdit; /* If non-NULL, this word is set to TRUE + * if there are selected labels that aren't + * in the edit cell, FALSE otherwise. + */ + int (*func)(); /* Function to call for each label found. */ + ClientData clientData; /* Argument to pass through to func. */ +{ + return SelEnumLabelsBase(layers, editOnly, TRUE, foundNonEdit, func, clientData); +} + /* Search function for label enumeration: make sure that this label * matches the one we're looking for. If it does, then record * information about it and return right away. diff --git a/select/select.h b/select/select.h index e7dbc999..7a3c1c29 100644 --- a/select/select.h +++ b/select/select.h @@ -46,6 +46,7 @@ extern ExtRectList *SelectShort(); extern int SelEnumPaint(); extern int SelEnumCells(); extern int SelEnumLabels(); +extern int SelEnumLabelsMirror(); /* Procedures to operate on the selection. */