Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add support for the rectangular area operations (#14285)
## Summary of the Pull Request This PR adds support for the rectangular area escape sequences: `DECCRA`, `DECFRA`, `DECERA`, `DECSERA`, `DECCARA`, `DECRARA`, and `DECSACE`. They provide VT applications with an efficient way to copy, fill, erase, or change the attributes in a rectangular area of the screen. ## PR Checklist * [x] Closes #14112 * [x] CLA signed. * [x] Tests added/passed * [ ] Documentation updated. * [ ] Schema updated. * [x] I've discussed this with core contributors already. Issue number where discussion took place: #14112 ## Detailed Description of the Pull Request / Additional comments All of these operations take a rectangle, defined by four coordinates. These need to have defaults applied, potentially need to be clipped and/or clamped within the active margins, and finally converted to absolute buffer coordinates. To avoid having to repeat that boilerplate code everywhere, I've pulled that functionality out into a shared method which they all use. With that out of the way, operations like `DECFRA` (fill), `DECERA` (erase), and `DECSERA` (selective erase) are fairly simple. They're just filling the given rectangle using the existing methods `_FillRect` and `_SelectiveEraseRect`. `DECCRA` (copy) is a little more work, because we didn't have existing code for that in `AdaptDispatch`, but it's mostly just cloned from the conhost `_CopyRectangle` function. The `DECCARA` (change attributes) and `DECRARA` (reverse attributes) operations are different though. Their coordinates can be interpreted as either a rectangle, or a stream of character positions (determined by the `DECSACE` escape sequence), and they both deal with attribute manipulation of the target area. So again I've pulled out that common functionality into some shared methods. They both also take a list of `SGR` options which define the attribute changes that they need to apply to the target area. To parse that data, I've had to refactor the `SGR` decoder from the `SetGraphicsRendition` method so it could be used with a given `TextAttribute` instance instead of just modifying the active attributes. The way that works in `DECCARA`, we apply the `SGR` options to two `TextAttribute` instances - one with all rendition bits on, and one with all off - producing a pair of bit masks. Then by `AND`ing the target attributes with the first bit mask, and `OR`ing them with the second, we can efficiently achieve the same effect as if we'd applied each `SGR` option to our target cells one by one. In the case of `DECRARA`, we only need to create a single bit mask to achieve the "reverse attribute" effect. That bit mask is applied to the target cells with an `XOR` operation. ## Validation Steps Performed Thanks to @KalleOlaviNiemitalo, we've been able to run a series of tests on a real VT420, so we have a good idea of how these ops are intended to work. Our implementation does a reasonably good job of matching that behavior, but we don't yet support paging, so we don't have the `DECCRA` ability to copy between pages, and we also don't have the concept of "unoccupied" cells, so we can't support that aspect of the streaming operations. It's also worth mentioning that the VT420 doesn't have colors, so we can't be sure exactly how they are meant to interpreted. However, based on the way the other attribute are handled, and what we know from the DEC STD 070 documentation, I think it's fair to assume that our handling of colors is also reasonable.
- Loading branch information