5

I'm building an embedded text editor consisting of a keyboard, an LCD display and a PIC32 microcontroller, to be programmed in C. The application should look, for example, like the GNU nano editor. The display is 40x16 characters big.

I'm currently wondering what would be a good abstraction from the display. We could conceptualise a simple terminal as follows:

typedef struct {
    char* content;              // Current and past content
    void (*update)(Terminal);   // Update function
} Terminal;
void append(Terminal, char*);   // Append to content & execute update function
void discard(Terminal, int);    // Discard last n characters & execute update f.

By adding a function pointer to the Terminal type, we basically have a model and a view. The Terminal can be controlled by the append() and discard() functions. With this Terminal we could make a simple terminal with stdin and stdout.

However, that's not enough for a nano-like editor, where text can be inserted and removed anywhere on the screen, not just at the end of the current data.

I have now made up the following type:

typedef struct {
    unsigned short rows, columns,     // Screen size
            first_visible_row, first_visible_column,  // Left-top coordinates
            cursor_x, cursor_y;       // Cursor coordinates
    char* content;                    // Current and off-screen content
    void (*update)(Screen);           // Update function
} Screen;

This Screen holds off-screen content as well, and its visible section is determined by its left-top coordinates. This makes scrolling easier. But, functions to write to this screen at some position would be complicated, because there is no direct relationship between a position in content and its coordinates on the actual display.

An easier to work with type would hold an array of rows char arrays, for different lines on the screen. Then, content would be an array of char arrays, i.e. char** content.


Basically, I'm asking if there are problems with my suggested approach and if there is an easier approach.

To sum up, here are some of the requirements for the screen:

  • Should be easy to scroll in
  • It should be possible to add and remove text at any point on the screen
  • Are you wanting to edit large files, or only 40*16 characters? How large? If they are fitting in PIC, their size would be small, and simple O(n) algorithms could be enough. Perhaps ncurses could be inspirational. – Basile Starynkevitch Sep 5 '15 at 5:56
  • @BasileStarynkevitch the PIC will have external memory and an SD card, so also larger files. Thanks for ncurses, I will have a look! – Keelan Sep 5 '15 at 6:36
  • 1
    Probably studying the source code of existing free software editors (like nano, vim, qemacs, emacs) should help a lot – Basile Starynkevitch Sep 5 '15 at 6:37
1

You might benefit from a double buffer concept where you store lines longer than the display into a larger structure and a zoomed in 40 * 16 array that can move up or down with display events. Provide offset pointers to each start of row and end is determined so arrows move around larger area. Limit shifting to min max. Then cut and paste is line by line segment copy. Multi line area copies would be the hardest to track, you could limit to window to start.

Buffer area into and out of file is a single write at the end of operations.

Display is a custom per string operation.

0

It's a good idea to have a content represented as char*, because that's what it is conceptually.

char** is bad as a model of content, because it's tied to a fixed screen size and line lenght. So it only makes sense as a 'viewmodel' of the screen.

As for the relationships between cursor coordinates and the position within content array, I see two options which should both work fine:

  • have a function that calculates an index into content based on current cursor coordinates and screen position (don't see why it would be too difficult)

  • maintain a two-dimensional array of indexes into content, where each element corresponds to one possible cursor position; it will need to be updated on every update of the screen

  • 1
    If lines could be inserted, an array of lines could be adequate (then char** would be a good idea) – Basile Starynkevitch Sep 5 '15 at 5:57
  • Lines are usually represented by 'newline' characters within a continuos array of chars, not by splitting chars into multiple arrays. So any number of lines is still a single char* that can be inserted into any position within the initial content array. – astreltsov Sep 5 '15 at 10:42

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.