On Tuesday, 17 December 2024 17:52:50 GMT G. Branden Robinson wrote: > > The fundamental requirement for \X is that it remains in the > > chronology of the output stream. If there is a colour change before \X > > it needs to occur first, if there are word gaps before the \X, they > > should be output first. This is true for any action which changes the > > output, the chronological order of actions in a users document must be > > preserved in the grout. > > > > Conversely .output and \! do not follow chronologically, they pass > > data to grout as soon as they are actioned, even if a partial line is > > being constructed by groff. > > Your statements are a bit too prescriptive for me. They are neither > documented anywhere, nor reasonably inferable from CSTR #54 or #97. > This is simply the way things happen(ed) to work as implemented. I > would not bet any money at all that the assumptions you're stating here > can be expected to hold for Heirloom Doctools or neatroff, for instance. > (I feel no urgency to work up an exhibit with which to test my > suspicion, though. So if someone wants to prove me wrong, here's a > golden opportunity. ) >
The model I use to understand the difference between \X and \! (.device and .output) is that one uses an in-band channel (\X) and the other is side-band. The in-band stream is the majority of data which must be output in chronological order so follows the order of commands in the document, i.e.:- \m[red]Word\m[] Must arrive on the in-band channel in this precise order:- SetCol red Text Word RestoreCol Any other order would be wrong. This is what I mean about maintaining a chronological order. The issue Peter discovered showed the vertical movement which should have appeared in the stream before \X was appearing after it. Conversely sideband instruction are usually treated like an interrupt, they are executed immediately. An example:- $ printf "Init\n.br\n\X'First'Second\n.output x X Third" | test-groff -Z x T ps x res 72000 1 1 x init p1 x font 5 TR f5 s10000 V12000 H72000 md DFd tInit n12000 0 x X Third V24000 H72000 x X First V24000 H72000 tSecond n12000 0 x trailer V792000 x stop You can see that "Third" appears first because it was sent as a side-band message, so I am not concerned with the chronology, I want it to go to the driver right away. It is primarily useful for sending meta-data to the driver. [...] > Your statements are a bit too prescriptive for me. They are neither > documented anywhere, nor reasonably inferable from CSTR #54 or #97. > This is simply the way things happen(ed) to work as implemented. I > would not bet any money at all that the assumptions you're stating here > can be expected to hold for Heirloom Doctools or neatroff, for instance. > (I feel no urgency to work up an exhibit with which to test my > suspicion, though. So if someone wants to prove me wrong, here's a > golden opportunity. :) ) > > As a rule, GNU troff output works like this: > > 0. Text and formatter directives construct node objects. > 1. An output line consists of a sequence of node objects. > 2. When it's time to write out an output line (producing "grout"), each > > node object is read and interpreted. > > a. Some nodes are "printable", and directly produce one or more grout > > commands. > > b. Some nodes are not "printable"; instead they alter internal state > > and don't directly produce grout commands, but can influence > the printing of nodes processed subsequently. > What you are describing here is the in-band processing, you have not covered the side-band processing troff does. Let's look at what .pline tells us:- $ printf "Hello\c\n.output x X You little beauty\nWorld\c\n.pline" | test- groff -Z x T ps x res 72000 1 1 x init p1 x X You little beauty {type: line_start_node, diversion level: 0}, {type: glyph_node, character: "H", diversion level: 0}, {type: glyph_node, character: "e", diversion level: 0}, {type: glyph_node, character: "l", diversion level: 0}, {type: glyph_node, character: "l", diversion level: 0}, {type: glyph_node, character: "o", diversion level: 0}, {type: transparent_dummy_node, diversion level: 0}, {type: kern_pair_node, diversion level: 0}, {type: glyph_node, character: "r", diversion level: 0}, {type: glyph_node, character: "l", diversion level: 0}, {type: glyph_node, character: "d", diversion level: 0} x font 5 TR f5 s10000 V12000 H72000 md DFd tHelloW H102860 torld n12000 0 x trailer V792000 x stop Notice that the .output directive never made it to the node list, because it has been actioned immediately. I hope this model helps you to better understand how the device control commands work in groff. Cheers Deri