git.cappig.dev / apheleiaOS.git master

1
#include <stdio.h>
2
#include <stdlib.h>
3
#include <string.h>
4
5
#define DEFAULT_MESSAGE "hello from apheleiaOS"
6
#define BUBBLE_WIDTH    60
7
8
static void print_line(char left, char mid, char right, size_t width) {
9
    putchar(left);
10
11
    for (size_t i = 0; i < width + 2; i++) {
12
        putchar(mid);
13
    }
14
15
    putchar(right);
16
    putchar('\n');
17
}
18
19
static char *make_message(int argc, char **argv) {
20
    if (argc <= 1) {
21
        size_t len = strlen(DEFAULT_MESSAGE);
22
        char *msg = malloc(len + 1);
23
24
        if (msg) {
25
            memcpy(msg, DEFAULT_MESSAGE, len + 1);
26
        }
27
28
        return msg;
29
    }
30
31
    size_t len = 0;
32
33
    for (int i = 1; i < argc; i++) {
34
        if (i > 1) {
35
            len++;
36
        }
37
38
        len += strlen(argv[i]);
39
    }
40
41
    char *msg = malloc(len + 1);
42
    if (!msg) {
43
        return NULL;
44
    }
45
46
    char *out = msg;
47
48
    for (int i = 1; i < argc; i++) {
49
        if (i > 1) {
50
            *out++ = ' ';
51
        }
52
53
        size_t arg_len = strlen(argv[i]);
54
        memcpy(out, argv[i], arg_len);
55
        out += arg_len;
56
    }
57
58
    *out = '\0';
59
    return msg;
60
}
61
62
static size_t next_piece(const char *msg, size_t pos, size_t len, size_t *start_out, size_t *next_out) {
63
    while (pos < len && msg[pos] == ' ') {
64
        pos++;
65
    }
66
67
    if (pos >= len) {
68
        *start_out = pos;
69
        *next_out = pos;
70
        return 0;
71
    }
72
73
    *start_out = pos;
74
75
    size_t left = len - pos;
76
    size_t take = left < BUBBLE_WIDTH ? left : BUBBLE_WIDTH;
77
78
    if (left > BUBBLE_WIDTH) {
79
        size_t split = pos + take;
80
81
        for (size_t i = pos + take; i > pos; i--) {
82
            if (msg[i - 1] == ' ') {
83
                split = i - 1;
84
                break;
85
            }
86
        }
87
88
        if (split > pos) {
89
            take = split - pos;
90
        }
91
    }
92
93
    *next_out = pos + take;
94
    return take;
95
}
96
97
static size_t wrapped_width(const char *msg) {
98
    size_t len = strlen(msg);
99
    size_t pos = 0;
100
    size_t width = 0;
101
102
    while (pos < len) {
103
        size_t start = 0;
104
        size_t next = 0;
105
        size_t take = next_piece(msg, pos, len, &start, &next);
106
107
        if (take > width) {
108
            width = take;
109
        }
110
111
        pos = next;
112
    }
113
114
    return width ? width : 1;
115
}
116
117
static void print_wrapped(const char *msg, size_t width) {
118
    size_t len = strlen(msg);
119
    size_t pos = 0;
120
121
    if (!len) {
122
        fputs("<   >\n", stdout);
123
        return;
124
    }
125
126
    while (pos < len) {
127
        size_t start = 0;
128
        size_t next = 0;
129
        size_t take = next_piece(msg, pos, len, &start, &next);
130
131
        fputs("< ", stdout);
132
        fwrite(msg + start, 1, take, stdout);
133
134
        for (size_t i = take; i < width; i++) {
135
            putchar(' ');
136
        }
137
138
        fputs(" >\n", stdout);
139
        pos = next;
140
    }
141
}
142
143
int main(int argc, char **argv) {
144
    char *msg = make_message(argc, argv);
145
    if (!msg) {
146
        return 1;
147
    }
148
149
    size_t width = wrapped_width(msg);
150
151
    print_line(' ', '_', ' ', width);
152
153
    print_wrapped(msg, width);
154
155
    print_line(' ', '-', ' ', width);
156
157
    puts("        \\   ^__^");
158
    puts("         \\  (oo)\\_______");
159
    puts("            (__)\\       )\\/\\");
160
    puts("                ||----w |");
161
    puts("                ||     ||");
162
163
    free(msg);
164
    return 0;
165
}