Scrolling causes the hook window-scroll-functions
to be executed. That lets you know when scrolling happens, but as the manual says,
Warning: don’t use this feature to alter the way the window is scrolled. It’s not designed for that, and such use probably won’t work.
It's actually possible to “lock” scrolling by saving window-start
and restoring it inside window-scroll-functions
, but that doesn't mean you should do it. It can cause the point to get out of the scrolling zone; you can fix that by manually clipping the point and the window point to the window area. But that gets really confusing when inserting text at the end of the window, as it causes the cursor to move backwards while inserting text.
You can't prevent a modification that would cause scrolling, because whether to scroll is determined after the modification is made and after things like line wrapping (whether explicit through auto fill mode or visual with visual line mode) have been processed. Once Emacs gets to the bit where it finds out whether it needs to scroll, the modification has already been carried out and the only solution would be to undo it.
A solution would be to keep two identical buffers, try out the modification in one of them, calculate the effect on scrolling (maybe by maintaining a “shadow” window in a hidden frame?), and carrying out the modification in the original buffer only if no scrolling happens. This sounds difficult for what it's worth.
Narrowing, as suggested by Wilfred Hughes, does most of what you want, but doesn't help with text insertions. You might combine narrowing with an entry in window-scroll-functions
, but you need to figure out what you want to do when the text grows too large. You need to have clear requirements before you can start implementing.
I don't think preventing edits makes sense. If you want to maintain a structure overview, do it with two windows: one where you edit text without any length restrictions, and one that shows the structure overview. See How can I get an org-mode outline in a 2nd buffer as a dynamic table of contents?
next-line
to check whether it's going off the screen and aborting would cover most of the use case.window-scroll-functions
. You can change the scroll under Emacs's nose; you aren't supposed to, but it sort-of works. You have to manually move the point back into the window area if it tries to escape. But when you insert text at the end of the window, I couldn't find a decent behavior. In the end, I couldn't find any advantage compared to narrowing, but many downsides: not built in, doesn't work when the same buffer is shown in multiple windows, really confusing with edits, ... In what case isn't narrowing ok, and what precise behavior do you want instead?