Drawing glitches in nano

This might seem like an odd question, but if you have a Ryzen 9xxx series CPU, please let me know, as I might need you to try out a few things in order to find out what causes a bug.

I’ve noticed some redraw artifacts both under Linux and under Haiku; I suspect that there might be issues with the driver (especially if the Haiku GPU driver is insipired by code from Linux).

I need to do further testing on another machine before I post instructions on what to test, but basically it would be something like …

  1. Use the on-chip GPU, not a PCIe graphics card.
  2. Open up the Haiku Terminal.
  3. Set font size to 18pt.
  4. Open up a copy of some 100+ line C-”ish”-source code (I’ll provide a test file later) using tab-size 4.
  5. nano -T sometestfile.c
  6. Press w then press

Bug: The caret should jump backwards (horizontally only) to right after the ‘S’ in “Search”.

This is not so bad in itself, but there are other artifact/redraw problems, which are harder to reproduce. This is likely related.

The actual problem I have, is that bogus-characters appear while I’m editing my C-source files; and on some occasions, the caret either jumps a few characters forward or backward; this makes it difficult to use the editor. I do believe there’s nothing wrong with nano itself, though. It may be the ncurses library, the Terminal or the graphics driver.

(Though the above does not happen for me under Linux, sometimes under debian (XFCE) → Terminal → nano, I see lines not being properly redrawn; I see two gradient-filled triangles the size of a line in the terminal - this is why I suspect the error to be a GPU/driver-related one).

I’ll try the above on a Ryzen 5600g soon, just to see if it’s related to the 9xxx series or if it may be reproducible on other variants.

1 Like

I’ve seen nano have redrawing issues when using it to write commit messages, even when using a GT1030, or under VBox, or VMware. (sometimes it shows the first line of the previous commit message, or fails to “draw” what I type in the first line, until I resize the Terminal window).

Also, Haiku’s radeon_hd driver doesn’t currently supports the iGPU on any modern APU, so… you more than likely are using the “framebuffer” driver (or VESA if not using UEFI boot). So this is not CPU/GPU specific (on Haiku, at least).

2 Likes

Oh, of course, I forgot. Thanks for reminding me - this will likely help finding out what’s actually going wrong. :smiley:

-The issues you mention, are they all under Haiku (eg. none under Linux ?)

Update:

I’ve tested on a Ryzen 5 5600G, the issue also exists there.

On Haiku, yes. I don’t use Linux too often, and don’t even remember using nano there :slight_smile: .

1 Like

OK, then - I think it’s likely that the problem might be in ncurses, especially because I see other style redraw-issues under Linux (not as confusing as those under Haiku).

It might just be something that needs “fine-tuning” in ncurses - perhaps something that gave build-errors and then were fixed in the most sensible way at the time.

-Periodic errors are the worst to find, but most of the time, they have to do with uninitialized variables, but maybe not in this case.

Another thing to consider… Issue might also be with Haiku’s Terminal handling of “escape sequences”.

You could try testing nano using a different Terminal app, like Konsole, for example (I haven’t done so yey, because I try to stay away of larger dependency chains, Qt on this case).

Edit: recategorized the post and changed title, because this doesn’t seems hardware related.

1 Like

:slight_smile: - the same here, I never liked Qt, it ruined an application my team was working on (after I left the company many years ago; my team made it a native Cocoa application on Mac OS X, then those who took over from us replaced Cocoa by Qt and the app was sluggish, ugly and felt incorrect to use, so I never used that version of it).

You’re giving me such good suggestions. Thank you. :slight_smile:

Just thought of one more thing…

When I (from Haiku Terminal) ssh into my Raspberry Pi 4B, the nano there does not cause the glitches I see with the local nano on Haiku.

-Thus, I very much believe it’s not the Terminal that has problems (still I could be wrong).

Warning to the reader: The rest of this is all assumptions, guesswork and opinions - I may be completely wrong. I’ve written it because it may be able to help pinpoint the issue.

I’ve been a little slow on replying to this.

This was actually one of my first thoughts and for a long time, I’ve been convinced that this would be what’s happening.

My most recent discoveries is that if I do a simple …

tabs 4; nano test.txt

… then pressing …

<CTRL>Wt<RETURN>

… will make the caret jump to X position 4 (it’s expected to go to X position 8).

#1: Since this works in all my Linux variants (both Ubuntu and Debian), via SSH and locally, with different versions of nano, I expect that it’s not nano itself that has a problem.

I’m thinking that the command …

tabs 4

… is changing tab sizes for the shell commands; not the ‘edit buffer’.

If for instance Konsole (and my Linux terminals) have two sets of TAB-stops and Haiku’s terminal program only has one, then it makes sense what is happening; because the edit-buffer’s TAB-stops should stay at 8, while the shell’s TAB-stops should be changed to 4 by the ‘tabs 4’ command.

That’s only part of the issue, because I think what happened is that the ncurses library may have been optimized, so that escape-sequences are changed into in case the X position is 8 (because it’s a few bytes shorter and thus quicker).

-Nothing wrong with doing so and ncurses would be correct if, and only if, the TAB stops have an 8 character spacing. Let’s assume that ncurses is asking about this and getting the answer ‘8’, then it’s doing everything correctly. However, if one of these details have been overlooked when Haiku’s Terminal was written, it can easily be what’s wrong.

So if there should be two sets of TAB-stops and there is only one; there’s a bug in Terminal.

If Terminal is doing everything correctly, then the optimization in ncurses would be incorrect.

… or even both could be incorrect!

-So a bug could surface, even if there’s no change to nano.

Why do I believe the problem is not in nano ? - Because it’s not likely that nano is operating on escape-sequences directly; it makes no sense to use a library for that and then make “special handling” by itself.

Now that we know what’s happening, we can blame the real culprit. Or we will, when someone points at a specification, which I have not searched for. Until then, it could be:

  • Haiku Terminal. Because it sets tab stops when you ask it to, and does so for the terminal and not only for the current buffer. Notice that Terminal is not alone in this and, without an authority saying the set tab stops command must affect only the current buffer (and I’m not saying there’s no such authority), they are right.
  • ncurses. Because it uses hard tabs taking into account the size declared in terminfo, even though the terminal may have correctly set different tab stops. Notice that this behaviour is behind a compile option that we have set, so ncurses can rightly point back at us.
  • nano. Because it doesn’t reset the terminal on init. Notice that if you change tab stops in the alternate buffer, nano will misbehave even in Konsole, at least with an ncurses that uses hard tabs.
  • The user. Because “don’t do that”. Notice the tabs man page does say it.

So we do need someone who really knows this stuff, or a spec to read, hopefully with no leeway for interpretation.

2 Likes

I blame ‘cat’, because you can’t …

cat --tabsize 4

:rofl:

Uhm, I gotta remember that one for when I release software. :wink:

-So yes, I admit, it’s partly my fault as well.

There’s one more candidate; I don’t know how valid it would be, though …

  • Old software, because they use hardware tabs instead of software tabs; they could have used software tabs and taken advantage of hardware tabs in case they were present; thus limiting bugs to the old platform.

All that aside, I think we’re pretty close to pinpointing the exact place where the issue is. :slight_smile:

Good one.

If you are setting tabs just for cat maybe you can assume they are only at the beginning and use something like sed 's/\t/ /g' instead. Or expand -t 4. Or, if it’s for visualization, less -x 4.

Despite being documented, I find it a bit of a lousy excuse. If your program (or, in this case, I’m guessing ncurses) is going to use hard tabs, it should first check that it can (you can disable them with stty -tabs, I guess this part it does check) and then, if the terminal it runs on can change the stops, it should check where they are. With that the warning in tabs manual would be unnecessary.

1 Like

The more I think about it, the more my opionion becomes that ncurses should be responsible (still the Terminal must also behave like other terminals regarding the tabs for consistency).

ncurses could, if the terminal did not supply tab functionality, emulate tabs through escape codes; that would allow for simpler (and slower) implementations.

For instance, nano should not at all touch the tab size (eg. reset tabs to interval 8).

Because nano should not know anything about escape sequences; it should let ncurses handle all that (it should be completely opaque to nano and all other command-line tools using ncurses).

So far, my best working solution is to wrap nano in a function, which selects a --tabsize depending on the file-extensions. (C-family is 4, .txt family is 8, .v is 2, .s is 12).

In my bug-fixed variant of that function, I set ‘tabs -8’ before executing nano, then ‘tabs -4’ after.

Note: undocumented again: ‘tabs’ will reset to 8, ‘tabs 4’ will work just like ‘tabs -4’.

If looking at the top of the man page…

tabs [options] [tabstop-list]

… it doesn’t require arguments, but it does not say what will happen if no arguments are specified, but it does say that it uses clear_all_tabs and set_tab - thus my guess is that it will always start by executing clear_all_tabs.

(I’ve curiously looked in my debian man-page and I can’t find it saying “don’t do that”, so I also suspect that man pages might differ across distributions).

It could still be a bad usage of the library by nano. We won’t know without a good analysis.

It does. Some terminals do that and some others do the other thing. So all terminals behave like other terminals, it’s just that there are two distinct sets. Anyway, that behaviour is not the cause of the issue. Change the tabstops for the alternate buffer in one of the other terminals and nano will misbehave there too.

tabs(1) — ncurses-bin — Debian trixie — Debian Manpages has the same text I quoted in the ticket. The words are not “don’t do that”, but when you read them that’s what they’re saying.

1 Like

As we have seen the bug in some Linux terminals, it means Haiku isn’t alone. That doesn’t necessarily make it right, but maybe the issues should be brought to the attention of ncurses developers. If there is a standard talking about this somewhere, they would be the one who know about it?

1 Like

Yep, that is definitely the right approach.

-Because ncurses need to ask the Terminal what it can do.

Edit: Assuming that it is possible to get that information - otherwise it’s necessary that the terminals provide that information.

I just found out that even when I set ‘tabs 8’ before starting nano, --tabsize 4 still causes problems (mainly junk-characters on the left-hand side of my C-sources).

However, for some reason, it has not been as bad as it used to …