From ceba050a21276a929373ee3d8e3513160f6c0f6d Mon Sep 17 00:00:00 2001 From: "R. Timothy Edwards" Date: Sat, 4 Apr 2026 20:47:04 -0400 Subject: [PATCH] Fixed the mess that is the "expand"/"unexpand" command set. This had numerous problems, the main one being that each of the three commands was inconsistent: "expand toggle" inverts the expansion of the selection and syncs with the layout. But "expand" expands the layout where instances overlap the box and does not sync to the selection, and "unexpand" unexpands the layout where the box completely surrounds instances. Added a set of options to "expand" and "unexpand" so that these functions can be made consistent with each other. All varieties of the function now always sync the selection and the layout. --- VERSION | 2 +- commands/CmdE.c | 149 +++++++++++++++++++++++++++++++----- commands/CmdLQ.c | 6 +- commands/CmdSubrs.c | 4 +- commands/CmdTZ.c | 82 +++++++++++++++++--- database/DBexpand.c | 122 +++++++++++++---------------- database/DBio.c | 9 +-- database/database.h.in | 13 ++++ dbwind/DBWprocs.c | 4 +- select/selOps.c | 170 ++++++++++++++++++++++++++++++++++------- windows/windCmdSZ.c | 2 +- 11 files changed, 427 insertions(+), 136 deletions(-) diff --git a/VERSION b/VERSION index 48221040..24bead74 100644 --- a/VERSION +++ b/VERSION @@ -1 +1 @@ -8.3.631 +8.3.632 diff --git a/commands/CmdE.c b/commands/CmdE.c index b83b2b14..6d3c156e 100644 --- a/commands/CmdE.c +++ b/commands/CmdE.c @@ -781,39 +781,82 @@ cmdEraseCellsFunc( * Implement the "expand" command. * * Usage: - * expand - * expand toggle + * expand [selection|surround|overlap|all] [toggle] + * + * "selection" expands cells in the selection. All other options + * expand cells in the layout. "all" expands all cells in the + * layout. "surround" expands cells which the cursor box + * surrounds completely, and "overlap" expands cells which the + * cursor box overlaps. + * + * If "toggle" is specified, flips the expanded/unexpanded status. + * Cells which were expanded are unexpanded, and cells which were + * unexpanded are expanded. + * + * For backwards compatibility: + * "expand" alone implements "expand overlap". + * "expand toggle" implements "expand selection toggle". + * + * Also see: CmdUnexpand * * Results: * None. * * Side effects: - * If "toggle" is specified, flips the expanded/unexpanded status - * of all selected cells. Otherwise, aren't any unexpanded cells - * left under the box. May read cells in from disk, and updates - * bounding boxes that have changed. + * Expansion state of cells is changed. May read cells in from + * disk, and update bounding boxes that have changed. * * ---------------------------------------------------------------------------- */ +#define EXPAND_SELECTION 0 +#define EXPAND_SURROUND 1 +#define EXPAND_OVERLAP 2 +#define EXPAND_ALL 3 +#define EXPAND_HELP 4 + void CmdExpand( MagWindow *w, TxCommand *cmd) { - int windowMask, boxMask, d; + int windowMask, boxMask, d, option; + bool doToggle = FALSE; + const char * const *msg; Rect rootRect; CellUse *rootBoxUse; CellDef *rootBoxDef; + int cmdExpandFunc(CellUse *use, int windowMask); /* Forward reference. */ - if (cmd->tx_argc > 2 || (cmd->tx_argc == 2 - && (strncmp(cmd->tx_argv[1], "toggle", strlen(cmd->tx_argv[1])) != 0))) + static const char * const cmdExpandOption[] = { + "selection expand cell instances in the selection", + "surround expand cell instances which the cursor box surrounds", + "overlap expand cell instances which the cursor box overlaps", + "all expand all cell instances", + NULL + }; + + if (cmd->tx_argc > 1) { - TxError("Usage: %s or %s toggle\n", cmd->tx_argv[0], cmd->tx_argv[0]); - return; + if (!strncmp(cmd->tx_argv[cmd->tx_argc - 1], "toggle", + strlen(cmd->tx_argv[cmd->tx_argc - 1]))) + { + doToggle = TRUE; + cmd->tx_argc--; + } } + if (cmd->tx_argc > 1) + { + option = Lookup(cmd->tx_argv[1], cmdExpandOption); + if (option < 0) option = EXPAND_HELP; + } + else + option = EXPAND_OVERLAP; + + if (option == EXPAND_HELP) goto badusage; + windCheckOnlyWindow(&w, DBWclientID); if (w == (MagWindow *) NULL) { @@ -844,23 +887,95 @@ CmdExpand( WindScale(d, 1); TxPrintf("expand: rescaled by %d\n", d); d = DBLambda[1]; - if (cmd->tx_argc == 2) break; /* Don't toggle twice */ + if (doToggle) break; /* Don't toggle twice */ } (void) ToolGetBoxWindow(&rootRect, &boxMask); - if (cmd->tx_argc == 2) - SelectExpand(windowMask); - else + if (option != EXPAND_SELECTION) { if ((boxMask & windowMask) != windowMask) { TxError("The box isn't in the same window as the cursor.\n"); return; } - DBExpandAll(rootBoxUse, &rootRect, windowMask, - TRUE, cmdExpandFunc, (ClientData)(pointertype) windowMask); + } + + switch (option) + { + case EXPAND_SELECTION: + SelectExpand(windowMask, + (doToggle) ? DB_EXPAND_TOGGLE : DB_EXPAND, + (Rect *)NULL, FALSE); + break; + case EXPAND_OVERLAP: + if (doToggle) + { + DBExpandAll(rootBoxUse, &rootRect, windowMask, + DB_EXPAND_TOGGLE | DB_EXPAND_OVERLAP, + cmdExpandFunc, (ClientData)(pointertype)windowMask); + SelectExpand(windowMask, + DB_EXPAND_TOGGLE | DB_EXPAND_OVERLAP, + &rootRect, FALSE); + } + else + { + DBExpandAll(rootBoxUse, &rootRect, windowMask, + DB_EXPAND | DB_EXPAND_OVERLAP, + cmdExpandFunc, (ClientData)(pointertype)windowMask); + SelectExpand(windowMask, + DB_EXPAND | DB_EXPAND_OVERLAP, + &rootRect, FALSE); + } + break; + case EXPAND_SURROUND: + if (doToggle) + { + DBExpandAll(rootBoxUse, &rootRect, windowMask, + DB_EXPAND_TOGGLE | DB_EXPAND_SURROUND, + cmdExpandFunc, (ClientData)(pointertype)windowMask); + SelectExpand(windowMask, + DB_EXPAND_TOGGLE | DB_EXPAND_SURROUND, + &rootRect, TRUE); + } + else + { + DBExpandAll(rootBoxUse, &rootRect, windowMask, + DB_EXPAND | DB_EXPAND_SURROUND, + cmdExpandFunc, (ClientData)(pointertype)windowMask); + SelectExpand(windowMask, + DB_EXPAND | DB_EXPAND_SURROUND, + &rootRect, TRUE); + } + break; + case EXPAND_ALL: + if (doToggle) + { + DBExpandAll(rootBoxUse, &TiPlaneRect, windowMask, + DB_EXPAND | DB_EXPAND_OVERLAP, + cmdExpandFunc, (ClientData)(pointertype)windowMask); + SelectExpand(windowMask, + DB_EXPAND | DB_EXPAND_OVERLAP, + (Rect *)NULL, FALSE); + } + else + { + DBExpandAll(rootBoxUse, &TiPlaneRect, windowMask, + DB_EXPAND | DB_EXPAND_OVERLAP, + cmdExpandFunc, (ClientData)(pointertype)windowMask); + SelectExpand(windowMask, + DB_EXPAND | DB_EXPAND_OVERLAP, + (Rect *)NULL, FALSE); + } + break; } } while (d != DBLambda[1]); + + return; + +badusage: + for (msg = &(cmdExpandOption[0]); *msg != NULL; msg++) + TxPrintf(" %s\n", *msg); + TxPrintf(" toggle Toggle the visibility of cell instances.\n"); } /* This function is called for each cell whose expansion status changed. diff --git a/commands/CmdLQ.c b/commands/CmdLQ.c index 349a1164..2c9006d2 100644 --- a/commands/CmdLQ.c +++ b/commands/CmdLQ.c @@ -517,14 +517,14 @@ CmdLoad( DBExpandAll(topuse, &(topuse->cu_bbox), ((DBWclientRec *)w->w_clientData)->dbw_bitmask, - TRUE, keepGoing, NULL); + DB_EXPAND, keepGoing, NULL); DBExpandAll(topuse, &(topuse->cu_bbox), ((DBWclientRec *)w->w_clientData)->dbw_bitmask, - FALSE, keepGoing, NULL); + DB_UNEXPAND, keepGoing, NULL); DBExpand(topuse, ((DBWclientRec *)w->w_clientData)->dbw_bitmask, - TRUE); + DB_EXPAND); /* We don't want to save and restore DBLambda, because */ /* loading the file may change their values. Instead, we */ diff --git a/commands/CmdSubrs.c b/commands/CmdSubrs.c index 5ff6d199..7a12c979 100644 --- a/commands/CmdSubrs.c +++ b/commands/CmdSubrs.c @@ -1239,7 +1239,7 @@ cmdExpandOneLevel( extern int cmdExpand1func(CellUse *cu, ClientData bitmask); /* first, expand this cell use */ - DBExpand(cu, bitmask, expand); + DBExpand(cu, bitmask, expand ? DB_EXPAND : DB_UNEXPAND); /* now, unexpand its direct children (ONE LEVEL ONLY) */ if (expand) @@ -1251,7 +1251,7 @@ cmdExpand1func( CellUse *cu, ClientData bitmask) { - DBExpand(cu, (int)CD2INT(bitmask), FALSE); + DBExpand(cu, (int)CD2INT(bitmask), DB_UNEXPAND); return 0; } diff --git a/commands/CmdTZ.c b/commands/CmdTZ.c index f14b6eab..b6c56300 100644 --- a/commands/CmdTZ.c +++ b/commands/CmdTZ.c @@ -702,32 +702,62 @@ CmdTool( * Implement the "unexpand" command. * * Usage: - * unexpand + * unexpand [selection|surround|overlap|all] + * + * "selection" unexpands (hides) cells in the selection. All + * other options unexpand cells in the layout. "all" unexpands + * all cells in the layout. "surround" unexpannds cells which + * the cursor box surrounds completely, and "overlap" unexpands + * cells which the cursor box overlaps. + * + * For backwards compatibility: + * "unexpand" alone implements "unexpand surround". + * + * Also see: CmdExpand * * Results: * None. * * Side effects: - * Unexpands all cells under the box that don't completely - * contain the box. + * Changes the expansion state of cells. * * ---------------------------------------------------------------------------- */ +#define UNEXPAND_SELECTION 0 +#define UNEXPAND_SURROUND 1 +#define UNEXPAND_OVERLAP 2 +#define UNEXPAND_ALL 3 +#define UNEXPAND_HELP 4 + void CmdUnexpand( MagWindow *w, TxCommand *cmd) { - int windowMask, boxMask; + int windowMask, boxMask, option; + const char * const *msg; Rect rootRect; + int cmdUnexpandFunc(CellUse *use, int windowMask); /* Forward reference. */ - if (cmd->tx_argc != 1) + static const char * const cmdUnexpandOption[] = { + "selection expand cell instances in the selection", + "surround expand cell instances which the cursor box surrounds", + "overlap expand cell instances which the cursor box overlaps", + "all expand all cell instances", + NULL + }; + + if (cmd->tx_argc > 1) { - TxError("Usage: %s\n", cmd->tx_argv[0]); - return; + option = Lookup(cmd->tx_argv[1], cmdUnexpandOption); + if (option < 0) option = UNEXPAND_HELP; } + else + option = UNEXPAND_SURROUND; + + if (option == UNEXPAND_HELP) goto badusage; windCheckOnlyWindow(&w, DBWclientID); if (w == (MagWindow *) NULL) @@ -743,8 +773,42 @@ CmdUnexpand( TxError("The box isn't in the same window as the cursor.\n"); return; } - DBExpandAll(((CellUse *) w->w_surfaceID), &rootRect, windowMask, - FALSE, cmdUnexpandFunc, (ClientData)(pointertype) windowMask); + + switch (option) + { + case UNEXPAND_SELECTION: + SelectExpand(windowMask, DB_UNEXPAND, (Rect *)NULL, FALSE); + break; + case UNEXPAND_OVERLAP: + DBExpandAll(((CellUse *)w->w_surfaceID), &rootRect, windowMask, + DB_UNEXPAND | DB_EXPAND_OVERLAP, + cmdUnexpandFunc, (ClientData)(pointertype)windowMask); + SelectExpand(windowMask, + DB_UNEXPAND | DB_EXPAND_OVERLAP, + &rootRect, FALSE); + break; + case UNEXPAND_SURROUND: + DBExpandAll(((CellUse *)w->w_surfaceID), &rootRect, windowMask, + DB_UNEXPAND | DB_EXPAND_SURROUND, + cmdUnexpandFunc, (ClientData)(pointertype)windowMask); + SelectExpand(windowMask, + DB_UNEXPAND | DB_EXPAND_SURROUND, + &rootRect, TRUE); + break; + case UNEXPAND_ALL: + DBExpandAll(((CellUse *)w->w_surfaceID), &TiPlaneRect, windowMask, + DB_UNEXPAND | DB_EXPAND_OVERLAP, + cmdUnexpandFunc, (ClientData)(pointertype)windowMask); + SelectExpand(windowMask, + DB_UNEXPAND | DB_EXPAND_OVERLAP, + (Rect *)NULL); + break; + } + return; + +badusage: + for (msg = &(cmdUnexpandOption[0]); *msg != NULL; msg++) + TxPrintf(" %s\n", *msg); } /* This function is called for each cell whose expansion status changed. diff --git a/database/DBexpand.c b/database/DBexpand.c index d1ba588a..d547cf5f 100644 --- a/database/DBexpand.c +++ b/database/DBexpand.c @@ -39,6 +39,7 @@ struct expandArg { bool ea_deref; /* TRUE if root def dereference flag is set */ int ea_xmask; /* Expand mask. */ + int ea_type; /* Expand, unexpand, or toggle */ int (*ea_func)(); /* Function to call for each cell whose * status is changed. */ @@ -67,15 +68,22 @@ struct expandArg */ void -DBExpand(cellUse, expandMask, expandFlag) +DBExpand(cellUse, expandMask, expandType) CellUse *cellUse; int expandMask; - bool expandFlag; + int expandType; { CellDef *def; - - if (DBDescendSubcell(cellUse, expandMask) == expandFlag) - return; + bool expandFlag, expandTest; + + expandTest = DBDescendSubcell(cellUse, expandMask); + if ((expandType & DB_EXPAND_MASK) == DB_EXPAND_TOGGLE) + expandFlag = expandTest; + else + { + expandFlag = ((expandType & DB_EXPAND_MASK) == DB_EXPAND) ? TRUE : FALSE; + if (expandFlag == expandTest) return; + } if (expandFlag) { @@ -130,17 +138,17 @@ DBExpand(cellUse, expandMask, expandFlag) */ void -DBExpandAll(rootUse, rootRect, expandMask, expandFlag, func, cdarg) +DBExpandAll(rootUse, rootRect, expandMask, expandType, func, cdarg) CellUse *rootUse; /* Root cell use from which search begins */ Rect *rootRect; /* Area to be expanded, in root coordinates */ int expandMask; /* Window mask in which cell is to be expanded */ - bool expandFlag; /* TRUE => expand, FALSE => unexpand */ + int expandType; /* DB_EXPAND, DB_UNEXPAND, DB_EXPAND_TOGGLE */ int (*func)(); /* Function to call for each cell whose expansion * status is modified. NULL means don't call anyone. */ ClientData cdarg; /* Argument to pass to func. */ { - int dbExpandFunc(), dbUnexpandFunc(); + int dbExpandFunc(); SearchContext scontext; struct expandArg arg; @@ -148,29 +156,26 @@ DBExpandAll(rootUse, rootRect, expandMask, expandFlag, func, cdarg) (void) DBCellRead(rootUse->cu_def, TRUE, TRUE, NULL); /* - * Walk through the area and set the expansion state - * appropriately. + * Walk through the area and set the expansion state appropriately. */ arg.ea_xmask = expandMask; arg.ea_func = func; arg.ea_arg = cdarg; + arg.ea_type = expandType; arg.ea_deref = (rootUse->cu_def->cd_flags & CDDEREFERENCE) ? TRUE : FALSE; scontext.scx_use = rootUse; scontext.scx_trans = GeoIdentityTransform; scontext.scx_area = *rootRect; - if (expandFlag) - DBCellSrArea(&scontext, dbExpandFunc, (ClientData) &arg); - else - DBCellSrArea(&scontext, dbUnexpandFunc, (ClientData) &arg); + DBCellSrArea(&scontext, dbExpandFunc, (ClientData) &arg); } /* * dbExpandFunc -- * * Filter function called by DBCellSrArea on behalf of DBExpandAll above - * when cells are being expanded. + * when cells are being expanded, unexpanded, or toggled. */ int @@ -184,68 +189,55 @@ dbExpandFunc(scx, arg) { CellUse *childUse = scx->scx_use; int n = DBLambda[1]; + int expandTest; + int expandType = (arg->ea_type & DB_EXPAND_MASK); + int expandSurround = (arg->ea_type & DB_EXPAND_SURROUND_MASK); + bool surround; + + expandTest = DBDescendSubcell(childUse, arg->ea_xmask); /* * Change the expansion status of this cell if necessary. Call the * client's function if the expansion status has changed. */ - if (!DBDescendSubcell(childUse, arg->ea_xmask)) + if (!expandTest && ((expandType == DB_EXPAND) || (expandType == DB_EXPAND_TOGGLE))) { - /* If the cell is unavailable, then don't expand it. - */ - if ((childUse->cu_def->cd_flags & CDAVAILABLE) == 0) + surround = (!GEO_SURROUND(&childUse->cu_def->cd_bbox, &scx->scx_area) + || GEO_SURROUND(&scx->scx_area, &childUse->cu_def->cd_bbox)); + if (surround || (expandSurround == DB_EXPAND_OVERLAP)) { - /* If the parent is dereferenced, then the child should be, too */ - if (arg->ea_deref) childUse->cu_def->cd_flags |= CDDEREFERENCE; - if(!DBCellRead(childUse->cu_def, TRUE, TRUE, NULL)) + /* If the cell is unavailable, then don't expand it. + */ + if ((childUse->cu_def->cd_flags & CDAVAILABLE) == 0) { - TxError("Cell %s is unavailable. It could not be expanded.\n", - childUse->cu_def->cd_name); - return 2; + /* If the parent is dereferenced, then the child should be, too */ + if (arg->ea_deref) childUse->cu_def->cd_flags |= CDDEREFERENCE; + if (!DBCellRead(childUse->cu_def, TRUE, TRUE, NULL)) + { + TxError("Cell %s is unavailable. It could not be expanded.\n", + childUse->cu_def->cd_name); + return 2; + } + } + + childUse->cu_expandMask |= arg->ea_xmask; + expandTest = TRUE; + if (arg->ea_func != NULL) + { + if ((*arg->ea_func)(childUse, arg->ea_arg) != 0) return 1; } } - - childUse->cu_expandMask |= arg->ea_xmask; - if (arg->ea_func != NULL) - { - if ((*arg->ea_func)(childUse, arg->ea_arg) != 0) return 1; - } } - - if (DBCellSrArea(scx, dbExpandFunc, (ClientData) arg)) - return 1; - return 2; -} - -/* - * dbUnexpandFunc -- - * - * Filter function called by DBCellSrArea on behalf of DBExpandAll above - * when cells are being unexpanded. - */ - -int -dbUnexpandFunc(scx, arg) - SearchContext *scx; /* Pointer to search context containing - * child use, search area in coor- - * dinates of the child use, and - * transform back to "root". - */ - struct expandArg *arg; /* Client data from caller */ -{ - CellUse *childUse = scx->scx_use; - - /* - * Change the expansion status of this cell if necessary. - */ - - if (DBDescendSubcell(childUse, arg->ea_xmask)) + else if (expandTest && ((expandType == DB_UNEXPAND) || + (expandType == DB_EXPAND_TOGGLE))) { - if (!GEO_SURROUND(&childUse->cu_def->cd_bbox, &scx->scx_area) - || GEO_SURROUND(&scx->scx_area, &childUse->cu_def->cd_bbox)) + surround = (!GEO_SURROUND(&childUse->cu_def->cd_bbox, &scx->scx_area) + || GEO_SURROUND(&scx->scx_area, &childUse->cu_def->cd_bbox)); + if (surround || (expandSurround == DB_EXPAND_OVERLAP)) { childUse->cu_expandMask &= ~arg->ea_xmask; + expandTest = FALSE; /* Call the client's function, if there is one. */ @@ -256,11 +248,7 @@ dbUnexpandFunc(scx, arg) } } - /* Don't recursively search things that aren't already expanded. */ - - else return 2; - - if (DBCellSrArea(scx, dbUnexpandFunc, (ClientData) arg)) + if (DBCellSrArea(scx, dbExpandFunc, (ClientData) arg)) return 1; return 2; } diff --git a/database/DBio.c b/database/DBio.c index 22e81bdd..c8173d9f 100644 --- a/database/DBio.c +++ b/database/DBio.c @@ -4418,7 +4418,7 @@ DBCellWriteCommandFile(cellDef, f) } else { - fprintf(f, "label %s %s %d %d %d %d %s %s\n", + fprintf(f, "label %s %s %d %d %d %d %s %s%s\n", lab->lab_text, DBFontList[lab->lab_font]->mf_name, lab->lab_size >> 3, @@ -4426,15 +4426,10 @@ DBCellWriteCommandFile(cellDef, f) lab->lab_offset.p_x, lab->lab_offset.p_y, directionNames[lab->lab_just], + (lab->lab_flags & LABEL_STICKY) ? "-" : "", DBTypeLongName(lab->lab_type)); } - if (lab->lab_flags & LABEL_STICKY) - { - fprintf(f, "select area label\n"); - fprintf(f, "setlabel sticky true\n"); - } - if (lab->lab_flags & PORT_DIR_MASK) { if (!(lab->lab_flags & LABEL_STICKY)) diff --git a/database/database.h.in b/database/database.h.in index b879aa71..d1e7385b 100644 --- a/database/database.h.in +++ b/database/database.h.in @@ -1062,6 +1062,19 @@ extern unsigned char DBVerbose; /* If 0, don't print any messages */ #define DB_VERBOSE_WARN 2 #define DB_VERBOSE_ALL 3 +/* ---------- Definitions for expanding/unexpanding cells --------------*/ + +/* Selection expansion flags */ +#define DB_EXPAND_MASK 3 /* 1 = expand, 0 = unexpand, 2 = toggle */ +#define DB_EXPAND_SURROUND_MASK 4 /* 1 = surround, 0 = touch */ + +/* Selection expansion values */ +#define DB_EXPAND 0 +#define DB_UNEXPAND 1 +#define DB_EXPAND_TOGGLE 2 +#define DB_EXPAND_SURROUND 4 +#define DB_EXPAND_OVERLAP 0 + /* ------------------ Exported technology variables ------------------- */ /*** diff --git a/dbwind/DBWprocs.c b/dbwind/DBWprocs.c index cb3cdeb3..d9ef5945 100644 --- a/dbwind/DBWprocs.c +++ b/dbwind/DBWprocs.c @@ -546,12 +546,12 @@ DBWloadWindow(window, name, flags) newEditUse = DBCellNewUse(newEditDef, (char *) NULL); (void) StrDup(&(newEditUse->cu_id), "Topmost cell in the window"); DBExpand(newEditUse, - ((DBWclientRec *)window->w_clientData)->dbw_bitmask, TRUE); + ((DBWclientRec *)window->w_clientData)->dbw_bitmask, DB_EXPAND); if (expand) DBExpandAll(newEditUse, &(newEditUse->cu_bbox), ((DBWclientRec *)window->w_clientData)->dbw_bitmask, - FALSE, UnexpandFunc, + DB_UNEXPAND, UnexpandFunc, INT2CD(((DBWclientRec *)window->w_clientData)->dbw_bitmask)); if (newEdit) diff --git a/select/selOps.c b/select/selOps.c index 59ce84be..91cbeeb2 100644 --- a/select/selOps.c +++ b/select/selOps.c @@ -1216,13 +1216,21 @@ SelectTransform(transform) SelectAndCopy2(EditRootDef); } +/* Client data used by SelectExpand */ + +typedef struct selExpData { + int sed_mask; /* window mask */ + int sed_type; /* DB_EXPAND, etc. */ + Rect *sed_box; /* selection box if used, or NULL */ +} SelExpData; + /* * ---------------------------------------------------------------------------- * * SelectExpand -- * - * Expand all of the selected cells that are unexpanded, and - * unexpand all of those that are expanded. + * Expand or unexpand all of the selected cells according to + * expandType. * * Results: * None. @@ -1230,58 +1238,166 @@ SelectTransform(transform) * Side effects: * The contents of the selected cells will become visible or * invisible on the display in the indicated window(s). + * Both the cell in the layout and the selection are updated + * so that they are synchonized with respect to the state of + * visibility. * * ---------------------------------------------------------------------------- */ void -SelectExpand(mask) +SelectExpand(mask, expandType, rootBox) int mask; /* Bits of this word indicate which * windows the selected cells will be * expanded in. */ + int expandType; /* Operation to perform: Expand, + * unexpand, or expand toggle. + */ + Rect *rootBox; /* Area of root box, if selecting by + * cursor box area. + */ { - extern int selExpandFunc(); /* Forward reference. */ + /* Forward references */ + extern int selExpandFunc(); - (void) SelEnumCells(FALSE, (bool *) NULL, (SearchContext *) NULL, - selExpandFunc, INT2CD(mask)); + SelExpData sed; + + sed.sed_type = expandType; + sed.sed_box = rootBox; + sed.sed_mask = mask; + + if (rootBox != NULL) + { + SearchContext scx; + + scx.scx_use = SelectUse; + scx.scx_area = *rootBox; + scx.scx_trans = GeoIdentityTransform; + + SelEnumCells(FALSE, (bool *) NULL, &scx, selExpandFunc, &sed); + return; + } + + SelEnumCells(FALSE, (bool *) NULL, (SearchContext *)NULL, + selExpandFunc, &sed); } /* ARGSUSED */ int -selExpandFunc(selUse, use, transform, mask) +selExpandFunc(selUse, use, transform, sed) CellUse *selUse; /* Use from selection. */ CellUse *use; /* Use to expand (in actual layout). */ Transform *transform; /* Not used. */ - int mask; /* Windows in which to expand. */ + SelExpData *sed; /* Information for expansion */ { - /* Don't change expansion status of root cell: screws up - * DBWAreaChanged (need to always have at least top-level - * cell be expanded). - */ + int expandType = sed->sed_type; + int mask = sed->sed_mask; + Rect *rootBox = sed->sed_box; - if (use->cu_parent == NULL) + /* If a rootBox is provided, then we are here trying to sync the + * cells in the selection to those in the edit cell. Need to + * follow the policy of expandType: If DB_EXPAND_SURROUND, then + * selUse must be inside the rootBox. If DB_EXPAND_OVERLAP, then + * selUse must ovelap the rootBox. + */ + if (rootBox != NULL) { - TxError("Can't unexpand root cell of window.\n"); - return 0; + if ((expandType & DB_EXPAND_SURROUND_MASK) == DB_EXPAND_OVERLAP) + { + if (!GEO_OVERLAP(rootBox, &selUse->cu_bbox)) + return 0; + } + else /* (expandType & DB_EXPAND_SURROUND_MASK) == DB_EXPAND_SURROUND */ + { + if (!GEO_SURROUND(rootBox, &selUse->cu_bbox)) + return 0; + } } - /* Be sure to modify the expansion bit in the selection as well as - * the one in the layout in order to keep them consistent. + /* If a rootBox was given, then the expansion is being done in the + * edit cell, and the selection is being updated to reflect any + * changes there, so only handle the selection. Otherwise, we + * have to sync the corresponding cells in the edit def here. */ - - if (DBDescendSubcell(use, mask)) + if ((expandType & DB_EXPAND_MASK) == DB_EXPAND) { - DBExpand(selUse, mask, FALSE); - DBExpand(use, mask, FALSE); - DBWAreaChanged(use->cu_parent, &use->cu_bbox, mask, - (TileTypeBitMask *) NULL); + /* Be sure to modify the expansion bit in the selection as well as + * the one in the layout in order to keep them consistent. + */ + DBExpand(selUse, mask, DB_EXPAND); + if (!rootBox) + { + DBExpand(use, mask, DB_EXPAND); + if (use->cu_parent == NULL) + DBWAreaChanged(use->cu_def, &use->cu_bbox, mask, &DBAllButSpaceBits); + else + DBWAreaChanged(use->cu_parent, &use->cu_bbox, mask, &DBAllButSpaceBits); + } } - else + else if ((expandType & DB_EXPAND_MASK) == DB_UNEXPAND) { - DBExpand(selUse, mask, TRUE); - DBExpand(use, mask, TRUE); - DBWAreaChanged(use->cu_parent, &use->cu_bbox, mask, &DBAllButSpaceBits); + /* Don't change expansion status of root cell: screws up + * DBWAreaChanged (need to always have at least top-level + * cell be expanded). + */ + + if ((use->cu_parent == NULL) && !rootBox) + { + TxError("Can't unexpand root cell of window.\n"); + return 0; + } + + if (use->cu_parent != NULL) + { + /* Be sure to modify the expansion bit in the selection as well as + * the one in the layout in order to keep them consistent. + */ + DBExpand(selUse, mask, DB_UNEXPAND); + if (!rootBox) + { + DBExpand(use, mask, DB_UNEXPAND); + DBWAreaChanged(use->cu_parent, &use->cu_bbox, mask, + (TileTypeBitMask *) NULL); + } + } + } + else /* (expandType & DB_EXPAND_MASK) == DB_EXPAND_TOGGLE */ + { + /* Don't change expansion status of root cell: screws up + * DBWAreaChanged (need to always have at least top-level + * cell be expanded). + */ + + if (use->cu_parent == NULL) + { + if (!rootBox) TxError("Can't unexpand root cell of window.\n"); + return 0; + } + + /* Be sure to modify the expansion bit in the selection as well as + * the one in the layout in order to keep them consistent. + */ + + if (DBDescendSubcell(selUse, mask)) + { + DBExpand(selUse, mask, DB_UNEXPAND); + if (!rootBox) + { + DBExpand(use, mask, DB_UNEXPAND); + DBWAreaChanged(use->cu_parent, &use->cu_bbox, mask, + (TileTypeBitMask *) NULL); + } + } + else + { + DBExpand(selUse, mask, DB_EXPAND); + if (!rootBox) + { + DBExpand(use, mask, DB_EXPAND); + DBWAreaChanged(use->cu_parent, &use->cu_bbox, mask, &DBAllButSpaceBits); + } + } } return 0; } diff --git a/windows/windCmdSZ.c b/windows/windCmdSZ.c index 3190708d..63bd3e6e 100644 --- a/windows/windCmdSZ.c +++ b/windows/windCmdSZ.c @@ -954,7 +954,7 @@ windXviewCmd(w, cmd) celluse = (CellUse *) (w->w_surfaceID); DBExpandAll(celluse, &(celluse->cu_bbox), - ((DBWclientRec *)w->w_clientData)->dbw_bitmask, FALSE, + ((DBWclientRec *)w->w_clientData)->dbw_bitmask, DB_UNEXPAND, ViewUnexpandFunc, (ClientData)(pointertype) (((DBWclientRec *)w->w_clientData)->dbw_bitmask));