;;; ---------------------------------------------------------------------------
;;; HideSection.lsp
;;; code compiled by YZ August 2026
;;; ---------------------------------------------------------------------------
;;; Breaks an object at two points and puts the middle section on a HIDDEN
;;; layer - showing concealed detail in one operation.
;;;
;;; Done by hand this is genuinely tedious: break the object twice, hunt for
;;; the middle fragment, select it, change its properties. Worse, a CIRCLE or
;;; full ELLIPSE cannot be broken at a single point at all, so the hidden
;;; portion has to be redrawn from scratch. This handles all of it.
;;;
;;; COMMANDS
;;;   HIDESECTION    - pick the object at the part to hide, then two break
;;;                    points
;;;   HIDESECTIONAT  - pick the object at the part to hide, then a second
;;;                    object that crosses it. The break points are the two
;;;                    intersections either side of where you picked.
;;;
;;; HIDESECTIONAT is usually the one you want: pick the pipe where it passes
;;; behind the wall, pick the wall, and the crossing section is hidden exactly
;;; at the wall faces.
;;;
;;; Works with lines, arcs, circles, ellipses, elliptical arcs and polylines,
;;; including polylines with varying width and arc segments, in any UCS.
;;;
;;; WHERE YOU PICK THE OBJECT MATTERS
;;; The point at which you select the object identifies WHICH of the three
;;; resulting pieces is the hidden one. Pick on the part that should be hidden,
;;; not on the part that stays visible.
;;;
;;; CONFIGURING THE HIDDEN PROPERTIES
;;; HideSection:Properties below lists what is applied to the hidden section.
;;; Delete a line to leave that property inherited from the original object -
;;; so removing the colour line means the hidden portion keeps the original's
;;; colour and only changes layer.
;;; ---------------------------------------------------------------------------

(vl-load-com)

;;; ---------------------------------------------------------------------------
;;; PROPERTIES APPLIED TO THE HIDDEN SECTION
;;; Omit any line to inherit that property from the original object instead.
;;; ---------------------------------------------------------------------------
(setq HideSection:Properties
   '(
        (006 . "BYLAYER")   ; linetype - must already be loaded
        (008 . "HIDDEN")    ; layer - created automatically if absent
        (039 . 0.0)         ; thickness
        (048 . 1.0)         ; linetype scale
        (062 . 256)         ; colour: 0 = BYBLOCK, 256 = BYLAYER
        (370 . -1)          ; lineweight: -1 BYLAYER, -2 BYBLOCK, -3 default
    )
)

;; Object types this routine can break.
(setq HideSection:Types "ARC,LINE,CIRCLE,ELLIPSE,LWPOLYLINE")

;; ---------------------------------------------------------------------------
;; HideSection:Doc  -  cached active document
;; ---------------------------------------------------------------------------
(defun HideSection:Doc nil
    (eval (list 'defun 'HideSection:Doc 'nil
                (vla-get-activedocument (vlax-get-acad-object))
          )
    )
    (HideSection:Doc)
)

;; ---------------------------------------------------------------------------
;; HideSection:Tan
;; ---------------------------------------------------------------------------
;; Tangent of x, returning nil at the asymptotes rather than throwing.
;; Namespaced - the original defined a bare global "tan".
;; ---------------------------------------------------------------------------
(defun HideSection:Tan ( x )
    (if (not (equal 0.0 (cos x) 1e-8))
        (/ (sin x) (cos x))
    )
)

;; ---------------------------------------------------------------------------
;; HideSection:Normalise
;; ---------------------------------------------------------------------------
;; Returns an angle in the range 0 to 2*pi.
;; ---------------------------------------------------------------------------
(defun HideSection:Normalise ( a )
    (cond
        ((equal (+ pi pi) a 1e-8) a)
        ((minusp a) (HideSection:Normalise (+ a pi pi)))
        ((rem a (+ pi pi)))
    )
)

;; ---------------------------------------------------------------------------
;; HideSection:Vertices
;; ---------------------------------------------------------------------------
;; Returns a polyline's vertices as sublists of their four defining groups:
;; 10 position, 40 start width, 41 end width, 42 bulge.
;; ---------------------------------------------------------------------------
(defun HideSection:Vertices ( enx )
    (if (setq enx (member (assoc 10 enx) enx))
        (cons (list (assoc 10 enx) (assoc 40 enx) (assoc 41 enx) (assoc 42 enx))
              (HideSection:Vertices (cdr enx))
        )
    )
)

;; ---------------------------------------------------------------------------
;; HideSection:DefaultProps
;; ---------------------------------------------------------------------------
;; Returns common property groups for the entity, substituting AutoCAD's
;; defaults where the entity omits one.
;;
;; Necessary because an object on layer 0 with BYLAYER colour carries no group
;; 8 or 62 at all - the absence IS the default - so the visible fragments would
;; not inherit them without this.
;; ---------------------------------------------------------------------------
(defun HideSection:DefaultProps ( elist )
    (mapcar
        (function
            (lambda ( pair ) (cond ((assoc (car pair) elist)) ( pair )))
        )
       '(
            (008 . "0")
            (006 . "BYLAYER")
            (039 . 0.0)
            (048 . 1.0)
            (062 . 256)
            (370 . -1)
        )
    )
)

;; ---------------------------------------------------------------------------
;; HideSection:PointToParam
;; ---------------------------------------------------------------------------
;; Returns the ellipse parameter corresponding to a point on an ellipse.
;;
;; An ellipse is not parameterised by angle - a point at 45 degrees is not at
;; parameter 45 degrees unless the ellipse happens to be a circle. The relation
;; is ratio * tan(parameter) = tan(angle), where ratio is the minor-to-major
;; axis ratio held in DXF group 40. Rearranging gives the atan expression below.
;;
;; Angles are measured relative to the major axis direction (group 11), not to
;; world X, which is what makes this correct for a rotated ellipse.
;; ---------------------------------------------------------------------------
(defun HideSection:PointToParam ( dxf pnt / ang ocs )
    (setq ocs (cdr (assoc 210 dxf))
          ang (- (angle (trans (cdr (assoc 10 dxf)) 0 ocs) (trans pnt 0 ocs))
                 (angle '(0.0 0.0) (trans (cdr (assoc 11 dxf)) 0 ocs))
              )
    )
    (HideSection:Normalise (atan (sin ang) (* (cdr (assoc 40 dxf)) (cos ang))))
)

;; ---------------------------------------------------------------------------
;; HideSection:Select
;; ---------------------------------------------------------------------------
;; Prompts until a supported object is picked at the section to hide.
;; Returns the entsel result (entity and pick point), or nil.
;; ---------------------------------------------------------------------------
(defun HideSection:Select ( / sel )
    (while
        (progn
            (setvar 'errno 0)
            (setq sel (entsel "\nSelect object AT the section to be hidden: "))
            (cond
                (   (= 7 (getvar 'errno))
                    (princ "\nMissed, try again.")
                )
                (   sel
                    (if (not (wcmatch (cdr (assoc 0 (entget (car sel)))) HideSection:Types))
                        (princ "\nThat object type cannot be broken - try a line, arc, circle, ellipse or polyline.")
                    )
                )
            )
        )
    )
    sel
)

;; ---------------------------------------------------------------------------
;; HideSection:Break
;; ---------------------------------------------------------------------------
;; Breaks an object at two points and applies the hidden properties to whichever
;; resulting fragment contains the third point.
;;
;; The object is REPLACED: the fragments are created as new entities and the
;; original deleted. That is what allows a circle to be split into two arcs,
;; which no amount of breaking could achieve.
;;
;; THE SHARED STRUCTURE
;; Each entity type sets up two things and then hands over to common code:
;;
;;   lst - the list of break positions, in order along the object
;;   fnc - a function that creates ONE fragment from the head of lst using the
;;         head of dxf as its properties
;;
;; The loop at the end then calls fnc, drops the head of lst, and REVERSES dxf.
;; Reversing is what alternates the properties between visible and hidden: with
;; three fragments the pattern runs normal, hidden, normal; with two - a closed
;; object - it runs hidden, normal.
;;
;; ent     - [ename] object to break
;; pt1,pt2 - [list] WCS break points
;; bpt     - [list] WCS point identifying the fragment to hide
;; dxf     - [list] properties for the hidden fragment
;; ---------------------------------------------------------------------------
(defun HideSection:Break ( ent pt1 pt2 bpt dxf / bul cen def enx fnc hed lst ocs
                                                 pa1 pa2 typ vl1 vl2 vtx vx1 wid )

    (setq enx (entget ent)
          ;; Snap both break points exactly onto the curve.
          pt1 (vlax-curve-getclosestpointto ent pt1)
          pt2 (vlax-curve-getclosestpointto ent pt2)
          pa1 (vlax-curve-getparamatpoint ent pt1)
          pa2 (vlax-curve-getparamatpoint ent pt2)
          def (HideSection:DefaultProps enx)
          ;; Fill any property the user omitted from the configuration with the
          ;; original object's own value.
          dxf (mapcar (function (lambda ( x ) (cond ((assoc (car x) dxf)) ( x )))) def)
    )

    ;; Put the break points in order along the object, so the arithmetic below
    ;; can assume pa1 comes first.
    (if (< pa2 pa1)
        (mapcar 'set '(pt1 pt2 pa1 pa2) (list pt2 pt1 pa2 pa1))
    )

    ;; Decide whether the MIDDLE fragment is the hidden one, by testing whether
    ;; the pick point falls between the two break parameters. The dxf list is
    ;; ordered accordingly, and the loop's reversal does the rest.
    (if (< pa1 (vlax-curve-getparamatpoint ent (vlax-curve-getclosestpointto ent bpt)) pa2)
        (setq dxf (list (HideSection:DefaultProps enx) dxf))
        (setq dxf (list dxf (HideSection:DefaultProps enx)))
    )

    (if
        (cond

            ;; ---------------------------------------------------------------
            ;; CIRCLE - becomes two arcs. Three angles are needed because the
            ;; circle wraps: the list is (a2 a1 a2), giving arcs a2-to-a1 and
            ;; a1-to-a2, which between them cover the whole circle.
            ;;
            ;; The stripped groups are those that belong to a circle rather than
            ;; an arc, plus the property groups that will be supplied fresh.
            ;; ---------------------------------------------------------------
            (   (= "CIRCLE" (setq typ (cdr (assoc 0 enx))))
                (setq cen (cdr (assoc 10 enx))
                      lst (list (angle cen (trans pt1 0 ent)) (angle cen (trans pt2 0 ent)))
                      lst (cons (cadr lst) lst)
                      enx (vl-remove-if
                              (function (lambda ( x ) (member (car x) '(-1 0 5 6 8 39 48 62 100 102 330 370))))
                              enx
                          )
                )
                (setq fnc
                    (lambda ( )
                        (entmake (append '((0 . "ARC")) (car dxf) (mapcar 'cons '(50 51) lst) enx))
                    )
                )
            )

            ;; ---------------------------------------------------------------
            ;; ELLIPSE - groups 41 and 42 are the start and end parameters.
            ;; A FULL ellipse spans exactly 2*pi and wraps like a circle, so its
            ;; parameter list is built the same way; an elliptical ARC keeps its
            ;; original ends and gains the two break parameters between them.
            ;; ---------------------------------------------------------------
            (   (= "ELLIPSE" typ)
                (setq pa1 (HideSection:Normalise (cdr (assoc 41 enx)))
                      pa2 (HideSection:Normalise (cdr (assoc 42 enx)))
                      lst (list (HideSection:PointToParam enx pt1)
                                (HideSection:PointToParam enx pt2)
                          )
                      enx (vl-remove-if
                              (function (lambda ( x ) (member (car x) '(-1 5 6 8 39 41 42 48 62 102 330 370))))
                              enx
                          )
                )
                (if (equal (+ pi pi) (- pa2 pa1) 1e-8)
                    (setq lst (cons (cadr lst) lst))
                    (setq lst (append (list pa1) lst (list pa2)))
                )
                (setq fnc
                    (lambda ( )
                        ;; A zero-length fragment is skipped rather than created.
                        (if (not (equal (car lst) (cadr lst) 1e-8))
                            (entmake (append enx (car dxf) (mapcar 'cons '(41 42) lst)))
                        )
                    )
                )
            )

            ;; ---------------------------------------------------------------
            ;; LINE - four points give three segments.
            ;; ---------------------------------------------------------------
            (   (= "LINE" typ)
                (setq lst (list (cdr (assoc 10 enx)) pt1 pt2 (cdr (assoc 11 enx))))
                (setq fnc
                    (lambda ( )
                        (if (not (equal (car lst) (cadr lst) 1e-8))
                            (entmake (append '((0 . "LINE")) (car dxf) (mapcar 'cons '(10 11) lst)))
                        )
                    )
                )
            )

            ;; ---------------------------------------------------------------
            ;; ARC - four angles give three arcs.
            ;; ---------------------------------------------------------------
            (   (= "ARC" typ)
                (setq cen (cdr (assoc 10 enx))
                      lst (list (cdr (assoc 50 enx))
                                (angle cen (trans pt1 0 ent))
                                (angle cen (trans pt2 0 ent))
                                (cdr (assoc 51 enx))
                          )
                      enx (vl-remove-if
                              (function (lambda ( x ) (member (car x) '(-1 5 6 8 39 48 62 102 330 370))))
                              enx
                          )
                )
                (setq fnc
                    (lambda ( )
                        (if (not (equal (car lst) (cadr lst) 1e-8))
                            (entmake (append enx (car dxf) (mapcar 'cons '(50 51) lst)))
                        )
                    )
                )
            )

            ;; ---------------------------------------------------------------
            ;; LWPOLYLINE - much the most involved, because each fragment is a
            ;; whole polyline that must be assembled vertex by vertex, and a
            ;; break falling mid-segment has to divide that segment's WIDTH and
            ;; CURVATURE proportionally.
            ;;
            ;; Width divides linearly. Curvature does not: bulge is the tangent
            ;; of a quarter of the included angle, so it is converted to an
            ;; angle with atan, split in proportion, and converted back with
            ;; tan. Get that wrong and an arc segment silently straightens.
            ;;
            ;; The closed flag is cleared from the header, since every fragment
            ;; of a broken polyline is open.
            ;; ---------------------------------------------------------------
            (   (= "LWPOLYLINE" typ)
                (setq hed (reverse (member (assoc 39 enx) (reverse enx)))
                      hed (subst (cons 70 (logand (cdr (assoc 70 hed)) (~ 1))) (assoc 70 hed) hed)
                      hed (vl-remove-if
                              (function (lambda ( x ) (member (car x) '(-1 5 6 8 39 48 62 102 330 370))))
                              hed
                          )
                      vtx (HideSection:Vertices enx)
                      ocs (assoc 210 enx)
                )

                ;; Peel off the vertices before the first break.
                (repeat (fix pa1)
                    (setq vl1 (cons (car vtx) vl1)
                          vtx (cdr vtx)
                    )
                )

                ;; First break mid-segment: close off the leading fragment at
                ;; the break point, and start the middle fragment there.
                (if (not (equal pa1 (fix pa1) 1e-8))
                    (setq
                        vx1 (car vtx)
                        wid (cdr (assoc 40 vx1))
                        wid (+ wid (* (- pa1 (fix pa1)) (- (cdr (assoc 41 vx1)) wid)))
                        bul (atan (cdr (assoc 42 vx1)))
                        vl1
                        (vl-list*
                            ;; Terminating vertex: zero widths and bulge, since
                            ;; those describe the segment LEAVING a vertex and
                            ;; there is none.
                            (list (cons 10 (trans pt1 0 (cdr ocs)))
                                 '(40 . 0.0) '(41 . 0.0) '(42 . 0.0)
                            )
                            (list (assoc 10 vx1)
                                  (assoc 40 vx1)
                                  (cons  41 wid)
                                  (cons  42 (HideSection:Tan (* (- pa1 (fix pa1)) bul)))
                            )
                            vl1
                        )
                        vtx
                        (cons
                            (list (cons  10 (trans pt1 0 (cdr ocs)))
                                  (cons  40 wid)
                                  (assoc 41 vx1)
                                  ;; The min handles both breaks falling within
                                  ;; the SAME segment.
                                  (cons  42 (HideSection:Tan (* (- (min pa2 (1+ (fix pa1))) pa1) bul)))
                            )
                            (cdr vtx)
                        )
                    )
                    (setq vl1 (cons (car vtx) vl1))
                )

                ;; Work from the far end for the second break.
                (setq vtx (reverse vtx))
                (repeat (+ (length vtx) (fix pa1) (- (fix pa2)) -1)
                    (setq vl2 (cons (car vtx) vl2)
                          vtx (cdr vtx)
                    )
                )

                (if (not (equal pa2 (fix pa2) 1e-8))
                    (setq
                        vx1 (car vtx)
                        wid (cdr (assoc 40 vx1))
                        wid (+ wid (* (/ (- pa2 (max pa1 (fix pa2)))
                                         (- (1+ (fix pa2)) (max pa1 (fix pa2)))
                                      )
                                      (- (cdr (assoc 41 vx1)) wid)
                                   )
                            )
                        bul (atan (cdr (assoc 42 vx1)))
                        vl2
                        (cons
                            (list (cons  10 (trans pt2 0 (cdr ocs)))
                                  (cons  40 wid)
                                  (assoc 41 vx1)
                                  (cons  42 (HideSection:Tan
                                                (* (/ (- (1+ (fix pa2)) pa2)
                                                      (if (< (fix pa2) pa1) (- pa2 pa1) 1.0)
                                                   )
                                                   bul
                                                )
                                            )
                                  )
                            )
                            vl2
                        )
                        vtx
                        (vl-list*
                            (list (cons 10 (trans pt2 0 (cdr ocs)))
                                 '(40 . 0.0) '(41 . 0.0) '(42 . 0.0)
                            )
                            (list (assoc 10 vx1)
                                  (assoc 40 vx1)
                                  (cons  41 wid)
                                  (cons  42 (HideSection:Tan
                                                (* (if (< (fix pa2) pa1) 1.0 (- pa2 (fix pa2))) bul)
                                            )
                                  )
                            )
                            (cdr vtx)
                        )
                    )
                    (setq vl2 (cons (car vtx) vl2))
                )

                ;; A CLOSED polyline yields two fragments, the two open ends
                ;; joining round the back; an open one yields three.
                (if (vlax-curve-isclosed ent)
                    (setq lst (list (append vl2 (reverse vl1)) (reverse vtx)))
                    (setq lst (list (reverse vl1) (reverse vtx) vl2))
                )

                (setq fnc
                    (lambda ( )
                        ;; A single-vertex fragment is not a polyline; skipped.
                        (if (cdar lst)
                            (entmake
                                (append
                                    (subst (cons 90 (length (car lst))) (assoc 90 hed) hed)
                                    (car dxf)
                                    (apply 'append (car lst))
                                    (list ocs)
                                )
                            )
                        )
                    )
                )
            )
        )

        (progn
            ;; Two fragments for a closed object, three for an open one. The
            ;; reversal of dxf on each pass alternates hidden and visible.
            (repeat (if (vlax-curve-isclosed ent) 2 3)
                (fnc)
                (setq dxf (reverse dxf)
                      lst (cdr lst)
                )
            )
            (entdel ent)
            t
        )
    )
)

;; ---------------------------------------------------------------------------
;; HideSection:Restore
;; ---------------------------------------------------------------------------
(defun HideSection:Restore ( vars vals )
    (mapcar 'setvar vars vals)
    (while (= 8 (logand 8 (getvar 'undoctl)))
        (command "_.UNDO" "_End")
        (vl-catch-all-apply '(lambda ( ) (*pop-error-mode*)) '())
    )
    (princ)
)

;; ---------------------------------------------------------------------------
;; c:HIDESECTION  -  break at two picked points
;; ---------------------------------------------------------------------------
(defun c:HIDESECTION ( / *error* vars vals pt1 pt2 sel )

    (setq vars '("CMDECHO")
          vals (mapcar 'getvar vars)
    )

    (defun *error* ( msg )
        (HideSection:Restore vars vals)
        (if (and msg (not (wcmatch (strcase msg t) "*break*,*cancel*,*exit*")))
            (princ (strcat "\n** HIDESECTION error: " msg " **"))
        )
        (princ)
    )

    (setvar "CMDECHO" 0)

    (if (and (setq sel (HideSection:Select))
             (setq pt1 (getpoint "\nPick first break point: "))
             (progn
                 ;; Two coincident break points would produce a zero-length
                 ;; hidden section.
                 (while (equal pt1 (setq pt2 (getpoint pt1 "\nPick second break point: ")) 1e-8)
                     (princ "\nThe two points must be distinct.")
                 )
                 pt2
             )
        )
        (progn
            ;; AutoCAD 2015 and later refuse (command) inside an *error* handler
            ;; unless the routine says up front that it will use one. Restore does,
            ;; to close this undo group. The declaring call is absent on older
            ;; releases, so it is wrapped rather than tested for.
            (vl-catch-all-apply '(lambda ( ) (*push-error-using-command*)) '())
            (command "_.UNDO" "_Begin")
            (if (HideSection:Break (car sel)
                    (trans pt1 1 0) (trans pt2 1 0) (trans (cadr sel) 1 0)
                    HideSection:Properties
                )
                (princ "\nSection hidden.")
                (princ "\nThe object could not be broken.")
            )
        )
        (princ "\n*Cancelled*")
    )

    (HideSection:Restore vars vals)
    (princ)
)

;; ---------------------------------------------------------------------------
;; c:HIDESECTIONAT  -  break at intersections with another object
;; ---------------------------------------------------------------------------
(defun c:HIDESECTIONAT ( / *error* vars vals ent lst ls1 ls2 obj pa1 par sel tmp )

    (setq vars '("CMDECHO")
          vals (mapcar 'getvar vars)
    )

    (defun *error* ( msg )
        (HideSection:Restore vars vals)
        (if (and msg (not (wcmatch (strcase msg t) "*break*,*cancel*,*exit*")))
            (princ (strcat "\n** HIDESECTIONAT error: " msg " **"))
        )
        (princ)
    )

    (setvar "CMDECHO" 0)

    (if (setq sel (HideSection:Select))
        (while
            (progn
                (setvar 'errno 0)
                (setq obj (car (entsel "\nSelect the crossing object: ")))
                (cond
                    (   (= 7 (getvar 'errno))
                        (princ "\nMissed, try again.")
                    )
                    (   (= 'ename (type obj))
                        (setq obj (vlax-ename->vla-object obj)
                              ent (car sel)
                        )
                        (cond
                            (   (not (vlax-method-applicable-p obj 'intersectwith))
                                (princ "\nThat object type cannot be intersected.")
                            )

                            ;; IntersectWith returns a flat list of X Y Z
                            ;; triples, so fewer than four elements means fewer
                            ;; than two intersection points.
                            (   (not (cdddr (setq tmp (vlax-invoke obj 'intersectwith
                                                          (vlax-ename->vla-object ent)
                                                          acextendnone
                                                      )
                                            )
                                     )
                                )
                                (princ "\nThose objects do not cross in at least two places.")
                            )

                            (   t
                                ;; Unpack the flat triples into points, snapped
                                ;; onto the object being broken.
                                (setq lst nil)
                                (repeat (/ (length tmp) 3)
                                    (setq lst (cons (vlax-curve-getclosestpointto ent
                                                        (list (car tmp) (cadr tmp) (caddr tmp)))
                                                    lst
                                              )
                                          tmp (cdddr tmp)
                                    )
                                )

                                ;; ---------------------------------------------
                                ;; More than two intersections: choose the
                                ;; NEAREST one on each side of where the user
                                ;; picked, so the hidden section is the one they
                                ;; actually pointed at rather than the whole run.
                                ;;
                                ;; Intersections are split by the sign of their
                                ;; offset from the pick parameter, each side
                                ;; sorted, and the closest of each taken. The
                                ;; fallbacks handle a pick beyond every
                                ;; intersection, where one side is empty.
                                ;; ---------------------------------------------
                                (if (< 2 (length lst))
                                    (progn
                                        (setq par (vlax-curve-getparamatpoint ent
                                                      (vlax-curve-getclosestpointto ent (trans (cadr sel) 1 0))
                                                  )
                                              ls1 nil
                                              ls2 nil
                                        )
                                        (foreach pnt lst
                                            (if (minusp (setq pa1 (- par (vlax-curve-getparamatpoint ent pnt))))
                                                (setq ls1 (cons (list pa1 pnt) ls1))
                                                (setq ls2 (cons (list pa1 pnt) ls2))
                                            )
                                        )
                                        (setq ls1 (vl-sort ls1 (function (lambda ( a b ) (> (car a) (car b)))))
                                              ls2 (vl-sort ls2 (function (lambda ( a b ) (< (car a) (car b)))))
                                              lst (list (cond ((cadar ls1)) ((cadr (last ls2))))
                                                        (cond ((cadar ls2)) ((cadr (last ls1))))
                                                  )
                                        )
                                    )
                                )

                                ;; AutoCAD 2015 and later refuse (command) inside an *error* handler
                                ;; unless the routine says up front that it will use one. Restore does,
                                ;; to close this undo group. The declaring call is absent on older
                                ;; releases, so it is wrapped rather than tested for.
                                (vl-catch-all-apply '(lambda ( ) (*push-error-using-command*)) '())
                                (command "_.UNDO" "_Begin")
                                (if (HideSection:Break ent (car lst) (cadr lst)
                                        (trans (cadr sel) 1 0)
                                        HideSection:Properties
                                    )
                                    (princ "\nSection hidden at the crossing.")
                                    (princ "\nThe object could not be broken.")
                                )
                                nil
                            )
                        )
                    )
                )
            )
        )
        (princ "\n*Cancelled*")
    )

    (HideSection:Restore vars vals)
    (princ)
)

(princ)
