summaryrefslogtreecommitdiff
path: root/client/client.c
blob: 2b2bb681cb17707d95a8cb0e4b522fbad1bd8f15 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
/**
 * @file client.c
 *
 * Sample client using the libbemenu.
 * Also usable as dmenu replacement.
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <stddef.h>
#include <assert.h>
#include <bemenu.h>

static ptrdiff_t getLine(char **outLine, size_t *outAllocated, FILE *stream)
{
    size_t len = 0, allocated;
    char *s, *buffer;

    assert(outLine != NULL);
    assert(outAllocated != NULL);

    if (stream == NULL || feof(stream) || ferror(stream))
        return -1;

    allocated = *outAllocated;
    buffer = *outLine;

    if (buffer == NULL || allocated == 0) {
        if (!(buffer = calloc(1, (allocated = 1024) + 1)))
            return -1;
    }

    for (s = buffer;;) {
        if (fgets(s, allocated - (s - buffer), stream) == NULL)
            return -1;

        len = strlen(s);
        if (feof(stream))
            break;

        if (len > 0 && s[len - 1] == '\n')
            break;

        if (len + 1 >= allocated - (s - buffer)) {
            void *tmp = realloc(buffer, 2 * allocated);
            if (!tmp)
                break;

            buffer = tmp;
            s = buffer + allocated - 1;
            memset(s, 0, allocated - (s - buffer));
            allocated *= 2;
        } else {
            s += len;
        }
    }

    *outAllocated = allocated;
    *outLine = buffer;

    if (s[len - 1] == '\n')
        s[len - 1] = 0;

    return s - buffer + len;
}

static void readItemsToMenuFromStdin(bmMenu *menu)
{
    ptrdiff_t len;
    size_t size;
    char *line = NULL;

    while ((len = getLine(&line, &size, stdin)) != -1) {
        bmItem *item = bmItemNew((len > 0 ? line : NULL));
        if (!item)
            break;

        bmMenuAddItem(menu, item);
    }

    if (line)
        free(line);
}

/**
 * Main method
 *
 * This function gives and takes the life of our program.
 *
 * @param argc Number of arguments from command line
 * @param argv Pointer to array of the arguments
 * @return exit status of the program
 */
int main(int argc, char **argv)
{
    (void)argc, (void)argv;

    bmMenu *menu = bmMenuNew(BM_DRAW_MODE_CURSES);

    if (!menu)
        return EXIT_FAILURE;

    bmMenuSetTitle(menu, "bemenu");
    readItemsToMenuFromStdin(menu);

    bmKey key;
    unsigned int unicode;
    int status = 0;
    do {
        bmMenuRender(menu);
        key = bmMenuGetKey(menu, &unicode);
    } while ((status = bmMenuRunWithKey(menu, key, unicode)) == BM_RUN_RESULT_RUNNING);

    if (status == BM_RUN_RESULT_SELECTED) {
        bmItem *item = bmMenuGetSelectedItem(menu);

        if (item)
            printf("%s\n", bmItemGetText(item));
    }

    bmMenuFree(menu);

    return (status == BM_RUN_RESULT_SELECTED ? EXIT_SUCCESS : EXIT_FAILURE);
}

/* vim: set ts=8 sw=4 tw=0 :*/