lpbdsn (c, doesn't expire)
/////////////
// HEADERS //
/////////////
#include <curses.h>
#include <locale.h>
#include <stdlib.h>
#include <string.h>


//////////////////////
// GLOBAL VARIABLES //
//////////////////////

// Stores the brush
char *brush = NULL;

// Stores the current coordinates for the cursor
int x, y;

// Stores the dimensions of the window
int maxy, maxx;

// Stores current foreground color
int fg;

// Stores current background color
int bg;

// Stores the current color count
int count = 2;

// Window for the draw area
WINDOW *draw_win;

// Window for status line
WINDOW *status_win;


//////////////////////
// HELPER FUNCTIONS //
//////////////////////

/*
   Creates a new window with dimensions `height` and `width` starting at `starty` and `startx`
*/
WINDOW *create_newwin(int height, int width, int starty, int startx)
{
    WINDOW *local_win;
    local_win = newwin(height, width, starty, startx);
    return local_win;
}


/*
   Creates current_win, preview_win and status_win
*/
void init_windows()
{
    getmaxyx(stdscr, maxy, maxx);
    draw_win = create_newwin(maxy-2, maxx, 0, 0);
    status_win = create_newwin(1, maxx, maxy-1, 0);
    keypad(draw_win, TRUE);
}


/*
    Initializes ncurses
*/
void init_curses()
{
    initscr();
    noecho();
    start_color();
    fg = 1;
    bg = 0;
    init_pair(1, 0, 0);
    init_pair(2, fg, bg);
}


/*
    Prints status line
*/
void printStatus()
{
    werase(status_win);
    wprintw(status_win, "(b)rush: ");
    wattron(status_win, COLOR_PAIR(count));
    wprintw(status_win, "%s",brush);
    wattroff(status_win, COLOR_PAIR(count));
    wprintw(status_win, "  (c)olor: %d  ", fg);
    wprintw(status_win, "(B)ackground: %d", bg);
    //wprintw(status_win, "  (s)ave  (l)oad");
    wrefresh(status_win);
}


/*
    Sets brush to some character
*/
void setBrush(char *newBrush)
{
    if( strcmp(newBrush,"default") == 0 )
    {
        setBrush("█");
        return;
    }
    free(brush);
    int allocSize = snprintf(NULL, 0, "%s", newBrush);
    brush = malloc(allocSize+1);
    snprintf(brush, allocSize+1, "%s", newBrush);
}


/*
    Moves the cursor up
*/
void goUp()
{
    getyx(draw_win, y, x);
    wmove(draw_win, y-1, x);
}


/*
    Moves the cursor down
*/
void goDown()
{
    getyx(draw_win, y, x);
    wmove(draw_win, y+1, x);
}


/*
    Moves the cursor left
*/
void goLeft()
{
    getyx(draw_win, y, x);
    wmove(draw_win, y, x-1);
}


/*
    Moves the cursor right
*/
void goRight()
{
    getyx(draw_win, y, x);
    wmove(draw_win, y, x+1);
}


/*
    Initializes the program
*/
void init()
{
    setlocale(LC_ALL, "");
    setBrush("█");
    init_curses();
    init_windows();
}


///////////////////
// MAIN FUNCTION //
///////////////////

int main()
{
    init();
    int a;
    char temp[10];
    do
    {
        printStatus();
        a = wgetch(draw_win);
        switch(a)
        {
            case KEY_UP:
            case 'k':
                goUp();
                break;

            case KEY_DOWN:
            case 'j':
                goDown();
                break;

            case KEY_LEFT:
            case 'h':
                goLeft();
                break;

            case KEY_RIGHT:
            case 'l':
                goRight();
                break;

            // Draw the brush character
            case 'd':
                getyx(draw_win, y, x);
                wmove(draw_win, y, x);
                wattron(draw_win, COLOR_PAIR(count));
                wprintw(draw_win, "%s", brush);
                wattroff(draw_win, COLOR_PAIR(count));
                wmove(draw_win, y, x+1);
                break;

            // Erase the brush character
            case 'e':
                getyx(draw_win, y, x);
                wmove(draw_win, y, x);
                wprintw(draw_win, "%s", " ");
                wmove(draw_win, y, x+1);
                break;

            // Set new brush character
            case 'b':
                werase(status_win);
                wprintw(status_win, "Enter New Brush Symbol: ");
                echo();
                wgetnstr(status_win, temp, 10);
                noecho();
                setBrush(temp);
                break;

            // Set new foreground color
            case 'c':
                werase(status_win);
                wprintw(status_win, "Enter Shell Color (0-255): ");
                echo();
                wscanw(status_win, "%d", &fg);
                init_pair(++count, fg, bg);
                noecho();
                break;

            // Set new background color
            case 'B':
                werase(status_win);
                wprintw(status_win, "Enter Shell Color (0-255): ");
                echo();
                wscanw(status_win, "%d", &bg);
                init_pair(++count, fg, bg);
                noecho();
                break;

            // Save
            case 's':
                werase(status_win);
                echo();
                wprintw(status_win, "Enter Name of Project: ");

                // For input (stdin & file)
                char *buf = NULL;
                // Stores Filename of save file
                char *filename = NULL;
                // Stores Filename of colors file
                char *colorsfile = NULL;
                // Stores amount to allocate
                int allocSize;

                // Read filename and appropriately set `filename` and `colorsfile`
                buf = malloc(250);
                wgetnstr(status_win, buf, 250);
                allocSize = snprintf(NULL,0,"%s.save",buf);
                filename = malloc(allocSize+1);
                snprintf(filename,allocSize+1,"%s.save",buf);
                colorsfile = malloc(allocSize+1);
                snprintf(colorsfile,allocSize+1,"%s.cols",buf);

                // Save screen output in ``filename
                scr_dump(filename);

                // Write all colors in `colorsfile`
                FILE *f = fopen(colorsfile,"a+");
                for(int i=1; i<=count; i++)
                {
                    short int *a, *b;
                    short int x, y;
                    a = &x;
                    b = &y;
                    pair_content(i, a, b);
                    fprintf(f,"%d %hd %hd\n", i, x, y);
                }

                // Close file and free memory
                fclose(f);
                free(filename);
                free(colorsfile);
                free(buf);
                noecho();
                break;

            // Load
            case 'o':
                werase(status_win);
                echo();
                wprintw(status_win, "Enter Name of Project: ");

                // Take filename input and appropriately set `filename` and `colorsfile`
                buf = malloc(250);
                wgetnstr(status_win, buf, 250);
                allocSize = snprintf(NULL,0,"%s.save",buf);
                filename = malloc(allocSize+1);
                snprintf(filename,allocSize+1,"%s.save",buf);
                colorsfile = malloc(allocSize+1);
                snprintf(colorsfile,allocSize+1,"%s.cols",buf);

                // If colorsfile doesn't exists, free memory and break
                f = fopen(colorsfile,"r");
                if(f == NULL)
                {
                    noecho();
                    free(filename);
                    free(colorsfile);
                    free(buf);
                    break;
                }

                // Remove existing color pairs
                reset_color_pairs();

                // Load color pairs from `colorsfile`
                int i=1;
                while(fgets(buf, 250, (FILE*) f))
                {
                    int n, f, b;
                    sscanf(buf,"%d %d %d", &n, &f, &b);
                    init_pair(n, f, b);
                    count = i++;
                }

                // Restore screen layout
                scr_restore(filename);
                doupdate();

                // CLose file and free memory
                fclose(f);
                noecho();
                free(filename);
                free(colorsfile);
                free(buf);
                break;
        }
    } while(a != 'q');
    endwin();
    free(brush);
    return 0;
}