Okay. Unfortunately the situation is a bit more complex than I had thought. Apparently we are still missing the record tables for land and land textures.

We have an old WIP PR for land records: https://github.com/OpenMW/openmw/pull/929. Probably needs more work, but it is a starting point. The guy who worked on that is still around. I don't know how many further contributions we can expect from him but it might still be a good idea to coordinate with him.

There are also some other sub-tasks that can be completed without the missing tables. Maybe you should start there. I will add a couple of issues to the tracker and then post a bit of background information on how the terrain system works. That should be enough to get you started.

Terrain data is stored in a pair of records (LAND and LTEX) per cell. Land contains all the bitmaps. The value of the texture bitmap is an index into the table defined in LTEX, which contains the name of the actual texture.
Note that both records need to come from the same content file, i.e. if you modify one of the records that have Base state you need to set both to Modified state. A LAND record can not reference a table entry in a LTEX record from another content file.

Now the first thing you should do is to make a new editing mode class (TerrainTextureMode) derived from CSVRender::EditMode (see CSVRender::InstanceMode for an example). This can be a mostly empty class for now. This class will contain the bulk of the editing functionality you are going to implement.
Then you need to insert your new class in CSVRender::PagedWorldspaceWidget::addEditModeSelectorButtons.

From here on you can pick different tasks. The selection one is obvious since it does not require the record tables to work. The brush button would also be an option (mostly GUI work, for everything else placeholders can be used).
Or you could have a go at the tables. That would also be a good starting point, especially the LTEX table. The implementation we have in the pull request above seems to be a bit basic and I am also not sure if it is fully functional (you will have to test that yourself). A good way to get started with LTEX would be to expose the actual data of the record as a sub.-table that can then be edited in a dialogue subview.
It is important to check if the rendered terrain updates with the changes made in the dialogue subview. I suspect it will not, because the terrain component does not know about the record table update mechanism. If it does not, you will need to find a solution for that.

btw. the pull request is pretty old. Might be a good idea to check that it still can be merged with the current code base.

I've made a start on the texture selection feature, but I'm having trouble deciding which class should keep track of the selected terrain. CSVRender::Cell seems like the best place to put it, but that would make it tricky to manage selection across cell borders, and when vertex selection is added, edges and corners might cause problems. Putting it in the terrain texture mode class itself won't work either if the selection is to be preserved when switching modes. The only other place I can think to put it is PagedWorldspaceWidget, but it doesn't really seem to fit there either.

Also, how should the visual effect to show the terrain is highlighted be implemented? I thought about adding functions to the CellBorder class to show an outline around the selected section, but the terrain itself would also need to be highlighted, which I'm not sure how to do.

Selection state goes into CVSRender::Cell. This is where we store the instance selection data, so it is an obvious choice. The situation regarding crossing cell borders is the same for instances and terrain (since terrain is also cell specific and does not cross cell borders). There shouldn't be any additional issues.

The CellBorder class is for the cell border, not the terrain. You may be able to re-use some of the implementation though. That's all the advice I have regarding how to implement the visual part of the selection. Scrawl can give you a couple of pointers. Maybe throw him a PM?

Wait, I'm a bit confused. I just want to clarify whether terrain selection will be confined to a single cell at a time (like pathgrid editing mode) or across cells (like instance editing mode). Either way, it looks like at least some information (e.g. a pointer to the currently selected cell(s)) must be shared between editing modes if converting selection data between selection modes (as mentioned here https://bugs.openmw.org/issues/3871) is to be added, so that any cells with selected terrain in them can be updated after switching to a new mode. Where can this go? Is it OK to add it as a static data member in the Cell class?

It seems we still don't have fully working LAND and LTEX tables. For anything beyond the selection mechanism (and probably some of the GUI) this feature is a prerequisite. If you are still interested in this task, I suggest you start with that (more information a few posts up here in this thread).

I've assigned myself the LTEX table feature. The LAND texture feature is still assigned to pi03k though. I got some basic table views up and running, but it seems there will be a bit of work gluing the two together and handling creation.

Note that both records need to come from the same content file, i.e. if you modify one of the records that have Base state you need to set both to Modified state. A LAND record can not reference a table entry in a LTEX record from another content file.

So, if a LAND record is modified, then every LTEX it references needs to be marked as modified, right?
If a LTEX is deleted, what does that mean for the LAND records that reference it? Should we just not allow deleting base LTEX records?

Edit: Perhaps base LTEX records should be untouchable, and any modified LAND records should have the LTEX records referenced added (instead of modified).

Currently LTEX and LAND records can be created and deleted separately. That is indeed a problem; at least for the UI. Not sure how it handle that without creating some ugly special cases.

When implicitly creating LTEX or LAND records (e.g. modifying a record that was base before or reverting such a modification) that other one of the pair (LTEX when modifying LAND and LAND when modifying LTEX) needs to be created/deleted automatically.

Edit: Another idea. A bit radical, but probably usable. We could merge LTEX and LAND into a single record within the editor. Requires some reorganisation and a rewrite but would solve all our problems.