First of all; I think that textui (the stuff in ui-*.[ch] files) is actually a pretty good UI. It performs its functions well, and, IMO, it looks nice (in an old school kind of way ). It's also a rather significant amount of tested, debugged code. Therefore, I think it's desirable to use as much of it as possible. Textui, however, does have significant technical problems. I assume that the readers of this post are well aware of what these problems are.
Here's my tentative plan for textui reform.

(or something like that; note that term_stack is NOT a replacement for angband_term[]; the latter will still exist). Some new functions will be added to ui-term.c (or, perhaps, to ui2-term.c); the main ones are Term_push(term *, struct term_hints *) and Term_pop(void). They will replace two constructions currently used in textui; the first one isa) Term_activate

Code:

term *old = Term;
Term_activate(inv_term);
...
Term_activate(old);

instead, it will become:

Code:

Term_push(inv_term, NULL);
...
Term_pop();

I think this is pretty self-explanatory. Another, much more important role for Term_push() and Term_pop() isb) screen_save and screen_load

Code:

screen_save();
...
menu_select();
...
screen_load();

saving and loading term_screen is used mainly (or exclusively?) by menu code, to draw menus directly on term_screen. If we want to eliminate tile_width/tile_height, menu code cannot use term_screen; the main term should display only one thing - the dungeon. That is, term_screen cannot have messages, sidebars, status lines or menus on it. It's easy to make sidebar or message line just use their own, separate terms (perhaps 'docked' to term_screen). But how to display menus? I propose they also use their own terms:

pushing a NULL term creates a new, termporary, empty term on top of the stack of terms (and a new subwindow appears on display). The menu code can use this term like it uses term_screen currently (Term_get_size(), Term_erase(), Term_gotoxy(), Term_putstr() should all work, and the menu still will be displayed in the new subwindow). Popping this temporary term frees it (and the subwindow disappears).
Why "term_hints"? Well, maybe the new term cannot be centered in term_screen; perhaps term_screen is too small and in the corner of display. Or maybe the frontend (main-something.c) doesn't know how to draw borders. In any case, the frontend should try to display menus in an attractive and useful way, based on information in hints.
I hope this will allow to use current menu code almost as it is; just screen_save() and screen_load() will have to be replaced by Term_push() and Term_pop(), and also stuff like region_erase() won't be necessary. menu_refresh() also does this thing:

term_stack.stack[0] is always term_screen; trying to pop it (making the stack completely empty) is a fatal error. OTOH, pushing term_screen on top of term_screen in the stack is ok (just like currently with term *old = Term; Term_activate(term_screen); Term_activate(old); old can already be term_screen).
That doesn't have to be a big stack. With current textui the max depth of the stack would be what, 3? (term_screen, store interface and item description, for instance)

Term_fresh() reform

Currently, Term_fresh() performs two functions; it flushes term's contents (via Term_fresh_row_*()) and it demands that (as main-xxx.c says) "This action should make sure that all 'output' to the window will actually appear on the window". The latter is impossible. Therefore, Term_fresh() should be split into two functions: Term_fresh() (much like it is now, but without calling Term_xtra()) and Term_redraw_screen():

Code:

void Term_redraw_screen(void)
{
Term_xtra(TERM_XTRA_REDRAW, 0);
}

By far the most useful moment to update the screen is immediately before trying to get user input. That is, before pressing a key the user should know the latest information about the state of the game. In simpler words: Term_redraw_screen() should be called before calling inkey_ex().
Another useful moment to refresh the screen is various animations. Splashscreen ("Initializing monsters" etc) is also an animation in this sense.
In most other situations redrawing the screen is not so useful; in particular, it's not a useful thing to do after updating a single tile of the map.

Colors reform

In text mode, angband's terrain has only 3 different colors, and two of those are used for hybrid_walls/solid_walls. Why doesn't text hook make any use of term_win->vta? Current situation:

The hackery with "a / MAX_COLORS", "a % MAX_COLORS" is just bizarre. Term->text_hook() should get tap and tcp just like pict_hook. Even if it's not very useful now, it may become useful over time. attrs could be something better than ints: for instance, uint32_t (one byte for each of red, green, blue, alpha channels). More colors will allow to achieve some interesting cosmetic effects; slightly transparent clear icky things, lantern light that gradually becomes more dim with the distance from the player, etc. Or how about a DCSS-style minimap?
uint32_t could still be used for the "a / MAX_COLORS" thing in some kind of "low color mode" (perhaps a new grafmode).

Tilesets

Note that if term_screen can only ever have either tiles or text, the job of ui2-term.c is significantly simplified:

The frontend will have to read all .png files, create an array of pixels, fill it with contents of files (in this particular order) and remember offsets into it. ui-prefs.c will ignore the file name part (*.png), and use the file number part (that precedes the file name) as char. attr then could be used for color moding the tile, or just be unused.
Actually, the file number part is just for illustration; it's not even necessary.
Well, tilesets currently work ok so I guess that's not that urgent.

Input

Why do terms have key_queue at all? Only one term ever does something with it. term_screen's key_queue may just as well be separated from term_screen and become its own thing.

So that't my current plan for textui reform. The main change is that any frontend is assumed to be capable of creating and destroying subwindows at will; I know that at least one official frontend can do it (main-sdl.c), and of course main-sdl2.c doesn't have any problems with that either. I don't see why any graphical frontend would find it too difficult. Ncurses, OTOH, needs the functionality of Term_load() and Term_save(). It's probably possible to implement fallback to term_win_copy() for backwards compatibility, but right now that doesn't concern me.

@t4nk--
You have to be able to mix tiles and characters for any monster or object missing a tile. This happens more than you might think

Also, I have no idea if people do this with gfx enabled, but I have a pref file that turns the extra valuable scrolls pink. (Rune, Banishment, Mass Banishment, *Destruction*), and some lesser ones like *enchant weapon* yellow. It'd be impossible to do this without mixing tile and character.

@t4nk--
You have to be able to mix tiles and characters for any monster or object missing a tile. This happens more than you might think

Wow, don't agree. Bugs, such as missing tiles, should be fixed, not worked around. It's just too annoying to add tiles to existing huge monolithic tilesets! But otherwise you gave me an idea I don't know why separate arrays for attrs and chars should exist at all. This would be a more useful construct:

Then term_win could be full of these things, and pict_hook() and text_hook() just eliminated and replaced with a single draw_hook(). The interpretation of ch, attr and flags would be left to the frontend.

Quote:

Also, I have no idea if people do this with gfx enabled, but I have a pref file that turns the extra valuable scrolls pink. (Rune, Banishment, Mass Banishment, *Destruction*), and some lesser ones like *enchant weapon* yellow. It'd be impossible to do this without mixing tile and character.

It's called 'color modulation' and it's an easy thing to do actually (with tiles). Although that seems like an obscure feature that few players would miss.

Quote:

Originally Posted by Nick

My feeling is that the lower level code needed a refresh, but I wasn't prpared to go down that rabbit hole at the moment. If you are, that's great

Hey, I think this is smart work and mostly makes sense to me. I have some suggestions/ideas that I think would improve but don't have time to reply more fully right now. Will collect my thoughts over the next couple of days and write a longer reply

Wow, don't agree. Bugs, such as missing tiles, should be fixed, not worked around.

It's not a bug as such. Certain users like to fiddle with the game, adding things that the maintainers didn't plan for. Unless you're going to generate a tile for them, you're going to need a backup and that;s text.

Hey, I think this is smart work and mostly makes sense to me. I have some suggestions/ideas that I think would improve but don't have time to reply more fully right now. Will collect my thoughts over the next couple of days and write a longer reply

Looking forward to it! I'm not sure how to handle various prompts...

Quote:

Originally Posted by Carnivean

It's not a bug as such. Certain users like to fiddle with the game, adding things that the maintainers didn't plan for. Unless you're going to generate a tile for them, you're going to need a backup and that;s text.

We'll see. It's not actually difficult to do, I just don't feel the need to support all users and all uses. I do have a backup - THEY will generate a tile

Nick, do you want patches for current textui?
Also, I'm afraid this will be a rather substantial rewrite I'm still hoping to keep menu code, it's a good code... but the stuff like ui-input.c really makes me RAGE and why does it display messages?

edit: well, to be fair, it's really inkey() stuff that is so outrageous. That might be the single worst thing in angband's codebase...