commit 6907eef33bc1f1988b6444dd48963dd0f10fad53
Author:     G. Branden Robinson <g.branden.robinson@gmail.com>
AuthorDate: Thu Jun 8 23:08:53 2023 -0500
Commit:     G. Branden Robinson <g.branden.robinson@gmail.com>
CommitDate: Thu Jun 8 23:32:27 2023 -0500

    [troff, grn, pic]: Fix Savannah #64285.
    
    * src/roff/troff/node.cpp (troff_output_file::determine_line_limits):
      Make 't' drawing command perform no limit check at all.  The limit
      check had the side effect of updating the drawing position.
      Consequently...
    
    * src/preproc/grn/hgraph.cpp (HGSetBrush):
    * src/preproc/pic/troff.cpp (troff_output::line_thickness): Stop
      emitting horizontal motion escape sequences to offset the drawing
      position advancement side effect.
    
    Fixes <https://savannah.gnu.org/bugs/?64155>.  Thanks to Steve Izma for
    the report, which came within 2 days of me removing the verbiage warning
    about this weird side effect from our Texinfo manual.
    
    Tested with
    
    ./build/test-groff -pet -ms -Z doc/pic.ms
    ./build/test-groff -M ./doc -ge -me -Z doc/grnexmpl.me
    
    before and after.  This time there were differences, as we'd expect.
    
    Changes to pic-processed documents look like this:
    
    @@ -1905,7 +1905,6 @@
     V301200
     H97200
     Dt -1000 0
    -h1000
     n12000 0
     V319200
     H97200
    @@ -1927,7 +1926,6 @@
     V301200
     H97200
     Dt 100 0
    -H97200
     n12000 0
     V319200
     H187200
    
    Note the repeated absolute horizontal motion in the second hunk.  In the
    first, a relative horizontal motion has gone entirely missing...but
    immediately prior to a line break documentary command and absolute
    motion in both axes.
    
    Changes to grn-processed documents look like this:
    
    @@ -235,7 +235,7 @@
     H79600
     n14400 0
     V203400
    -H72850
    +H73600
     Dt 750 0
     n14400 0
     V387862
    @@ -347,7 +347,7 @@
     DP 0 3385 -1692 0 -1692 -1692 1692 -1693 1692 0
     n14400 0
     V203400
    -H73150
    +H73600
     Dt 450 0
     n14400 0
     V315093
    
    Here, we see horizontal motions larger by exactly as much as the line
    thickness drawing commands formerly caused.
    
    Moreover, the only differences in PostScript output...
    
    ./build/test-groff -pet -ms doc/pic.ms
    ./build/test-groff -M ./doc -ge -me doc/grnexmpl.me
    
    ...are updates to the "CreationDate" comment.

diff --git a/ChangeLog b/ChangeLog
index a5a38ab35..1cd163738 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,21 @@
+2023-06-08  G. Branden Robinson <g.branden.robinson@gmail.com>
+
+	[troff, grn, pic]: Fix Savannah #64285.
+
+	* src/roff/troff/node.cpp
+	(troff_output_file::determine_line_limits): Make 't' drawing
+	command perform no limit check at all.  The limit check had the
+	side effect of updating the drawing position.  Consequently...
+	* src/preproc/grn/hgraph.cpp (HGSetBrush):
+	* src/preproc/pic/troff.cpp (troff_output::line_thickness):
+	Stop emitting horizontal motion escape sequences to offset the
+	drawing position advancement side effect.
+
+	Fixes <https://savannah.gnu.org/bugs/?64155>.  Thanks to Steve
+	Izma for the report, which came within 2 days of me removing the
+	verbiage warning about this weird side effect from our Texinfo
+	manual.
+
 2023-06-08  G. Branden Robinson <g.branden.robinson@gmail.com>
 
 	* src/roff/troff/node.cpp
diff --git a/src/preproc/grn/hgraph.cpp b/src/preproc/grn/hgraph.cpp
index 9ed81a449..38fc83f8b 100644
--- a/src/preproc/grn/hgraph.cpp
+++ b/src/preproc/grn/hgraph.cpp
@@ -399,7 +399,7 @@ HGSetBrush(int mode)
   }
   if (linethickness != thick[mode]) {
     linethickness = thick[mode];
-    printf("\\h'-%.2fp'\\D't %.2fp'", linethickness, linethickness);
+    printf("\\D't %.2fp'", linethickness);
     printed = 1;
   }
   if (printed)
diff --git a/src/preproc/pic/troff.cpp b/src/preproc/pic/troff.cpp
index 3dc87a721..00d244c84 100644
--- a/src/preproc/pic/troff.cpp
+++ b/src/preproc/pic/troff.cpp
@@ -475,7 +475,7 @@ void troff_output::line_thickness(double p)
   if (p < 0.0)
     p = RELATIVE_THICKNESS;
   if (driver_extension_flag && p != last_line_thickness) {
-    printf("\\D't %.3fp'\\h'%.3fp'\n.sp -1\n", p, -p);
+    printf("\\D't %.3fp'\n.sp -1\n", p);
     last_line_thickness = p;
   }
 }
diff --git a/src/roff/troff/node.cpp b/src/roff/troff/node.cpp
index b272d040a..fcafcd41d 100644
--- a/src/roff/troff/node.cpp
+++ b/src/roff/troff/node.cpp
@@ -1428,8 +1428,10 @@ void troff_output_file::determine_line_limits(char code, hvpair *point,
     }
     do_generic_limit_check = false;
     break;
-  case 'l':
   case 't':
+    do_generic_limit_check = false;
+    break;
+  case 'l':
   case '~':
     break;
   default:

commit 312c104976594324b5ddd10acd78f47e72203a16
Author:     G. Branden Robinson <g.branden.robinson@gmail.com>
AuthorDate: Thu Jun 8 23:31:26 2023 -0500
Commit:     G. Branden Robinson <g.branden.robinson@gmail.com>
CommitDate: Thu Jun 8 23:32:18 2023 -0500

    [troff]: Warn on unrecognized drawing command.
    
    * src/roff/troff/node.cpp (troff_output_file::determine_line_limits):
      Throw syntax warning if an unrecognized drawing command is
      encountered; it is not ignored, but does use the generic output limit
      check.
    
    * doc/groff.texi (Drawing Geometric Objects):
    * man/groff.7.man (Drawing commands): Document handling of unrecognized
      drawing commands.
    
    * doc/groff.texi (Warnings):
    * src/roff/troff/troff.1.man (Warnings): Document new use of "syntax"
      warning category.

diff --git a/ChangeLog b/ChangeLog
index a240e1468..a5a38ab35 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2023-06-08  G. Branden Robinson <g.branden.robinson@gmail.com>
+
+	* src/roff/troff/node.cpp
+	(troff_output_file::determine_line_limits): Throw syntax warning
+	if an unrecognized drawing command is encountered; it is not
+	ignored, but does use the generic output limit check.
+
 2023-06-08  G. Branden Robinson <g.branden.robinson@gmail.com>
 
 	* src/roff/troff/node.cpp
diff --git a/doc/groff.texi b/doc/groff.texi
index 6372162ac..0e2a0ce09 100644
--- a/doc/groff.texi
+++ b/doc/groff.texi
@@ -14208,6 +14208,14 @@ @node Drawing Geometric Objects
 default.
 @end table
 @endDefesc
+
+Unrecognized drawing commands cause GNU @code{troff} to emit a warning
+in the @code{syntax} category, but are still sent to the output device
+to support device-specific extensions.  Such commands are assumed to
+update the drawing position to the final coordinate pair in their
+argument list.  To override this assumption, wrap such a drawing command
+escape sequence with the @code{\Z} escape sequence.  @xref{Page
+Motions}.
 @c END Keep (roughly) parallel with subsection "Drawing commands" of
 @c groff(7).
 
@@ -16861,8 +16869,9 @@ @node Warnings
 A self-contradictory hyphenation mode was requested; an empty or
 incomplete numeric expression was encountered; an operand to a numeric
 operator was missing; an attempt was made to define a recursive, empty,
-or nonsensical character class; or a @code{groff} extension conditional
-expression operator was used while in compatibility mode.
+or nonsensical character class; an unrecognized drawing command was
+encountered; or a @code{groff} extension conditional expression operator
+was used while in compatibility mode.
 
 @item di
 @itemx 256
diff --git a/man/groff.7.man b/man/groff.7.man
index 40ca41297..78c22fa3b 100644
--- a/man/groff.7.man
+++ b/man/groff.7.man
@@ -5541,6 +5541,25 @@ .SS "Drawing commands"
 selects a thickness proportional to the type size;
 this is the default.
 .LE
+.
+.
+.P
+Unrecognized drawing commands cause GNU
+.I troff \" GNU
+to emit a warning in the
+.B syntax
+category,
+but are still sent to the output device to support device-specific
+extensions.
+.
+Such commands are assumed to update the drawing position to the final
+coordinate pair in their argument list.
+.
+To override this assumption,
+wrap such a drawing command escape sequence with the
+.B \[rs]Z
+escape sequence.
+.\" @xref{Page Motions}.
 .\" END Keep (roughly) parallel with groff.texi node "Drawing
 .\" commands".
 .
diff --git a/src/roff/troff/node.cpp b/src/roff/troff/node.cpp
index 82f487fee..b272d040a 100644
--- a/src/roff/troff/node.cpp
+++ b/src/roff/troff/node.cpp
@@ -1433,6 +1433,7 @@ void troff_output_file::determine_line_limits(char code, hvpair *point,
   case '~':
     break;
   default:
+    warning(WARN_SYNTAX, "unrecognized drawing command '%1'", code);
     break;
   }
 
diff --git a/src/roff/troff/troff.1.man b/src/roff/troff/troff.1.man
index d83c4a515..03815da01 100644
--- a/src/roff/troff/troff.1.man
+++ b/src/roff/troff/troff.1.man
@@ -744,6 +744,7 @@ .SH Warnings
 an attempt was made to define a recursive,
 empty,
 or nonsensical character class;
+an unrecognized drawing command was encountered;
 or a
 .I groff
 extension conditional expression operator was used while in

commit 342452d25d2ff0123dd415c64ae184d3b87da3d5
Author:     G. Branden Robinson <g.branden.robinson@gmail.com>
AuthorDate: Thu Jun 8 20:11:09 2023 -0500
Commit:     G. Branden Robinson <g.branden.robinson@gmail.com>
CommitDate: Thu Jun 8 23:28:57 2023 -0500

    [troff]: Refactor to clarify.
    
    * src/roff/troff/node.cpp (troff_output_file::determine_line_limits):
      Make the 'l', 't', and '~' commands (more clearly) use the generic
      output limit check.  More clearly make the 'a' command not use it.
    
    Tested with
    
    ./build/test-groff -pet -ms -Z doc/pic.ms
    ./build/test-groff -M ./doc -ge -me -Z doc/grnexmpl.me
    
    before and after.  No change.

diff --git a/ChangeLog b/ChangeLog
index c2774fbba..a240e1468 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2023-06-08  G. Branden Robinson <g.branden.robinson@gmail.com>
+
+	* src/roff/troff/node.cpp
+	(troff_output_file::determine_line_limits): Make the 'l', 't',
+	and '~' commands (more clearly) use the generic output limit
+	check.  More clearly make the 'a' command not use it.
+
 2023-06-08  G. Branden Robinson <g.branden.robinson@gmail.com>
 
 	* src/roff/troff/node.cpp
diff --git a/src/roff/troff/node.cpp b/src/roff/troff/node.cpp
index bca8a3f7e..82f487fee 100644
--- a/src/roff/troff/node.cpp
+++ b/src/roff/troff/node.cpp
@@ -1408,8 +1408,6 @@ void troff_output_file::determine_line_limits(char code, hvpair *point,
     }
     do_generic_limit_check = false;
     break;
-  case 't':
-    break;
   case 'a':
     double c[2];
     int p[4];
@@ -1427,12 +1425,13 @@ void troff_output_file::determine_line_limits(char code, hvpair *point,
 			      &minx, &maxx, &miny, &maxy);
       check_output_limits(minx, miny);
       check_output_limits(maxx, maxy);
-      break;
     }
-    // fall through
-  case 'l':
     do_generic_limit_check = false;
     break;
+  case 'l':
+  case 't':
+  case '~':
+    break;
   default:
     break;
   }

commit 89c9ca9eaff009ef005409295c50ef9137bb4b00
Author:     G. Branden Robinson <g.branden.robinson@gmail.com>
AuthorDate: Thu Jun 8 19:46:29 2023 -0500
Commit:     G. Branden Robinson <g.branden.robinson@gmail.com>
CommitDate: Thu Jun 8 22:43:50 2023 -0500

    [troff]: Slightly refactor.
    
    * src/roff/troff/node.cpp (troff_output_file::determine_line_limits):
      Slightly refactor.  Stop repeating code.  Add new Boolean,
      `do_generic_limit_check`, defaulting true.  In the switch that handles
      various drawing commands, set it false for those that perform
      specialized output limit checks.
    
    Tested with
    
    ./build/test-groff -pet -ms -Z doc/pic.ms
    ./build/test-groff -M ./doc -ge -me -Z doc/grnexmpl.me
    
    before and after.  No change.

diff --git a/ChangeLog b/ChangeLog
index 3156b69b2..c2774fbba 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,12 @@
+2023-06-08  G. Branden Robinson <g.branden.robinson@gmail.com>
+
+	* src/roff/troff/node.cpp
+	(troff_output_file::determine_line_limits): Slightly refactor.
+	Stop repeating code.  Add new Boolean, `do_generic_limit_check`,
+	defaulting true.  In the switch that handles various drawing
+	commands, set it false for those that perform specialized output
+	limit checks.
+
 2023-06-08  G. Branden Robinson <g.branden.robinson@gmail.com>
 
 	[man, mdoc]: Parameterize page offset.
diff --git a/src/roff/troff/node.cpp b/src/roff/troff/node.cpp
index 4d872189e..bca8a3f7e 100644
--- a/src/roff/troff/node.cpp
+++ b/src/roff/troff/node.cpp
@@ -1373,6 +1373,7 @@ void troff_output_file::determine_line_limits(char code, hvpair *point,
 					      int npoints)
 {
   int i, x, y;
+  bool do_generic_limit_check = true;
 
   if (!is_on())
     return;
@@ -1385,6 +1386,7 @@ void troff_output_file::determine_line_limits(char code, hvpair *point,
 			output_vpos - point[0].h.to_units()/2);
     check_output_limits(output_hpos + point[0].h.to_units(),
 			output_vpos + point[0].h.to_units()/2);
+    do_generic_limit_check = false;
     break;
   case 'E':
   case 'e':
@@ -1392,6 +1394,7 @@ void troff_output_file::determine_line_limits(char code, hvpair *point,
 			output_vpos - point[0].v.to_units()/2);
     check_output_limits(output_hpos + point[0].h.to_units(),
 			output_vpos + point[0].v.to_units()/2);
+    do_generic_limit_check = false;
     break;
   case 'P':
   case 'p':
@@ -1403,15 +1406,9 @@ void troff_output_file::determine_line_limits(char code, hvpair *point,
       y += point[i].v.to_units();
       check_output_limits(x, y);
     }
+    do_generic_limit_check = false;
     break;
   case 't':
-    x = output_hpos;
-    y = output_vpos;
-    for (i = 0; i < npoints; i++) {
-      x += point[i].h.to_units();
-      y += point[i].v.to_units();
-      check_output_limits(x, y);
-    }
     break;
   case 'a':
     double c[2];
@@ -1434,16 +1431,13 @@ void troff_output_file::determine_line_limits(char code, hvpair *point,
     }
     // fall through
   case 'l':
-    x = output_hpos;
-    y = output_vpos;
-    check_output_limits(x, y);
-    for (i = 0; i < npoints; i++) {
-      x += point[i].h.to_units();
-      y += point[i].v.to_units();
-      check_output_limits(x, y);
-    }
+    do_generic_limit_check = false;
     break;
   default:
+    break;
+  }
+
+  if (do_generic_limit_check) {
     x = output_hpos;
     y = output_vpos;
     for (i = 0; i < npoints; i++) {
