t* sacc + cursorline and uri preview
       
   URI git clone git://git.codevoid.de/sacc-sdk
   DIR Log
   DIR Files
   DIR Refs
   DIR LICENSE
       ---
   DIR commit 7917802325a6f61b516986192096781c27e3bba9
   DIR parent 01e24f0999841a8cdfa99027e2be90963742cef0
   URI Author: Quentin Rameau <quinq@fifth.space>
       Date:   Fri, 30 Jun 2017 17:39:41 +0200
       
       Add screen-oriented (via terminfo) UI
       
       Diffstat:
         M common.h                            |       1 +
         M config.mk                           |      10 +++++++---
         M sacc.c                              |       2 ++
         A ui_ti.c                             |     173 +++++++++++++++++++++++++++++++
       
       4 files changed, 183 insertions(+), 3 deletions(-)
       ---
   DIR diff --git a/common.h b/common.h
       t@@ -9,6 +9,7 @@ struct item {
                char *port;
                char *raw;
                size_t printoff;
       +        size_t curline;
                Item *entry;
                Dir  *dir;
        };
   DIR diff --git a/config.mk b/config.mk
       t@@ -1,12 +1,16 @@
        # Install paths
        PREFIX = /usr/local
        
       -# UI type, txt
       +# UI type
       +# txt (textual)
        UI=txt
       +# ti (screen-oriented)
       +#UI=ti
       +#UIFLAGS=-lcurses
        
        # Stock FLAGS
       -SACCCFLAGS = -D_POSIX_C_SOURCE=200809L $(CFLAGS)
       -SACCLDFLAGS = $(LDFLAGS)
       +SACCCFLAGS = -D_POSIX_C_SOURCE=200809L -D_DEFAULT_SOURCE $(CFLAGS)
       +SACCLDFLAGS = $(UIFLAGS) $(LDFLAGS)
        
        .c.o:
                $(CC) $(SACCCFLAGS) -c $<
   DIR diff --git a/sacc.c b/sacc.c
       t@@ -170,6 +170,7 @@ molditem(char **raw)
                item->dir = NULL;
                item->entry = NULL;
                item->printoff = 0;
       +        item->curline = 0;
        
                return item;
        }
       t@@ -406,6 +407,7 @@ moldentry(char *url)
                entry->port = port;
                entry->entry = entry;
                entry->printoff = 0;
       +        entry->curline = 0;
                entry->raw = NULL;
                entry->dir = NULL;
        
   DIR diff --git a/ui_ti.c b/ui_ti.c
       t@@ -0,0 +1,172 @@
       +#include <stdio.h>
       +#include <term.h>
       +#include <termios.h>
       +#include <unistd.h>
       +#include <sys/types.h>
       +
       +#include "common.h"
       +
       +static struct termios tsave;
       +
       +void
       +uisetup(void)
       +{
       +        struct termios traw;
       +
       +        tcgetattr(0, &tsave);
       +        traw = tsave;
       +        cfmakeraw(&traw);
       +        tcsetattr(0, TCSAFLUSH, &traw);
       +
       +        setupterm(NULL, 1, NULL);
       +}
       +
       +void
       +uicleanup(void)
       +{
       +        tcsetattr(0, TCSAFLUSH, &tsave);
       +        putp(tparm(clear_screen));
       +}
       +
       +static void
       +printitem(Item *item)
       +{
       +        printf("%-4s%c %s\r",
       +               item->type != 'i' ? typedisplay(item->type) : "",
       +               item->type > '1' ? '|' : '+', item->username);
       +}
       +
       +static void
       +help(void)
       +{
       +        return;
       +}
       +
       +void
       +display(Item *item)
       +{
       +        Item **items;
       +        size_t i, curln, lastln, nitems, printoff;
       +
       +        if (item->type > '1')
       +                return;
       +
       +        putp(tparm(clear_screen));
       +        putp(tparm(save_cursor));
       +
       +        switch (item->type) {
       +        case '0':
       +                puts(item->raw);
       +                break;
       +        case '1':
       +                items = item->dir->items;
       +                nitems = item->dir->nitems;
       +                printoff = item->printoff;
       +                curln = item->curline;
       +                lastln = printoff + lines;
       +
       +                for (i = printoff; i < nitems && i < lastln; ++i) {
       +                        if (item = items[i]) {
       +                                if (i != printoff)
       +                                        putp(tparm(cursor_down));
       +                                if (i == curln) {
       +                                        putp(tparm(save_cursor));
       +                                        putp(tparm(enter_standout_mode));
       +                                }
       +                                printitem(item);
       +                                putp(tparm(column_address, 0));
       +                                if (i == curln)
       +                                        putp(tparm(exit_standout_mode));
       +                        }
       +                }
       +                break;
       +        }
       +
       +        putp(tparm(restore_cursor));
       +}
       +
       +static void
       +movecurline(Item *item, int l)
       +{
       +        size_t nitems;
       +        ssize_t curline, offline;
       +
       +        if (item->dir == NULL)
       +                return;
       +
       +        curline = item->curline + l;
       +        nitems = item->dir->nitems;
       +        if (curline < 0 || curline >= nitems)
       +                return;
       +
       +        printitem(item->dir->items[item->curline]);
       +        item->curline = curline;
       +
       +        if (l > 0) {
       +                offline = item->printoff + lines;
       +                if (curline - item->printoff >= lines / 2 && offline < nitems) {
       +                        putp(tparm(save_cursor));
       +
       +                        putp(tparm(cursor_address, lines, 0));
       +                        putp(tparm(scroll_forward));
       +                        printitem(item->dir->items[offline]);
       +
       +                        putp(tparm(restore_cursor));
       +                        item->printoff += l;
       +                }
       +        } else {
       +                offline = item->printoff + l;
       +                if (curline - offline <= lines / 2 && offline >= 0) {
       +                        putp(tparm(save_cursor));
       +
       +                        putp(tparm(cursor_address, 0, 0));
       +                        putp(tparm(scroll_reverse));
       +                        printitem(item->dir->items[offline]);
       +                        putchar('\n');
       +
       +                        putp(tparm(restore_cursor));
       +                        item->printoff += l;
       +                }
       +        }
       +        
       +        putp(tparm(cursor_address, curline - item->printoff, 0));
       +        putp(tparm(enter_standout_mode));
       +        printitem(item->dir->items[curline]);
       +        putp(tparm(exit_standout_mode));
       +}
       +
       +Item *
       +selectitem(Item *entry)
       +{
       +        char c;
       +        Item *hole;
       +        int item, nitems;
       +
       +        for (;;) {
       +                switch (c = getchar()) {
       +                case 'b':
       +                        return entry->entry;
       +                case 'g':
       +                        if (entry->dir->items[entry->curline]->type < '2')
       +                                return entry->dir->items[entry->curline];
       +                        continue;
       +                case 'n':
       +                        movecurline(entry, 1);
       +                        continue;
       +                case 'p':
       +                        movecurline(entry, -1);
       +                        continue;
       +                case 'q':
       +                        return NULL;
       +                case '!':
       +                        if (entry->raw)
       +                                continue;
       +                        return entry;
       +                case 'h': /* FALLTHROUGH */
       +                        help();
       +                default:
       +                        continue;
       +
       +                }
       +        }
       +}
       +\ No newline at end of file