-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathui.c
More file actions
181 lines (155 loc) · 4.46 KB
/
Copy pathui.c
File metadata and controls
181 lines (155 loc) · 4.46 KB
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
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
#include "ui.h"
#include <curses.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#define WIDTH 78
#define CHAT_HEIGHT 24
#define INPUT_HEIGHT 1
#define USERNAME_DISPLAY_MAX 8
WINDOW* mainwin;
WINDOW* chatwin;
WINDOW* inputwin;
char* messages[CHAT_HEIGHT];
size_t num_messages = 0;
/**
* Initialize the chat user interface. Call this once at startup.
*/
void ui_init() {
// Create the main window
mainwin = initscr();
if(mainwin == NULL) {
fprintf(stderr, "Failed to initialize screen\n");
exit(EXIT_FAILURE);
}
// Don't display characters when they're pressed
noecho();
// Create the chat window
chatwin = subwin(mainwin, CHAT_HEIGHT + 2, WIDTH + 2, 0, 0);
box(chatwin, 0, 0);
// Create the input window
inputwin = subwin(mainwin, INPUT_HEIGHT + 2, WIDTH + 2, CHAT_HEIGHT + 2, 0);
box(inputwin, 0, 0);
// Refresh the display
refresh();
}
// Clear the chat window (refresh required)
void ui_clear_chat() {
for(int i=0; i<WIDTH; i++) {
for(int j=0; j<CHAT_HEIGHT; j++) {
mvwaddch(chatwin, 1+j, 1+i, ' ');
}
}
}
/**
* Add a message to the chat window. If username is NULL, the message is
* indented by two spaces.
*
* \param username The username string. Truncated to 8 characters by default.
* This function does *not* take ownership of this memory.
* \param message The message string. This function does *not* take ownership
* of this memory.
*/
void ui_add_message(char* username, char* message) {
// Clear the chat window
ui_clear_chat();
// Free the oldest message if it will be lost
if(num_messages == CHAT_HEIGHT) {
free(messages[CHAT_HEIGHT-1]);
} else {
num_messages++;
}
// Move messages up
memmove(&messages[1], &messages[0], sizeof(char*) * (CHAT_HEIGHT - 1));
// Make space for the username and message
messages[0] = malloc(sizeof(char*) * (WIDTH + 1));
// Keep track of where we are in the message string
size_t offset = 0;
// Add the username, or indent two spaces if there isn't one
if(username == NULL) {
messages[0][0] = ' ';
messages[0][1] = ' ';
offset = 2;
} else if(strlen(username) > USERNAME_DISPLAY_MAX) {
strncpy(messages[0], username, USERNAME_DISPLAY_MAX-3);
offset = USERNAME_DISPLAY_MAX-3;
messages[0][offset++] = '.';
messages[0][offset++] = '.';
messages[0][offset++] = '.';
messages[0][offset++] = ':';
messages[0][offset++] = ' ';
} else {
strcpy(messages[0], username);
offset = strlen(username);
messages[0][offset++] = ':';
messages[0][offset++] = ' ';
}
// If characters remain, add them in another message
if(strlen(message) > WIDTH - offset) {
strncpy(&messages[0][offset], message, WIDTH - offset);
ui_add_message(NULL, &message[WIDTH - offset]);
} else {
strcpy(&messages[0][offset], message);
// Display the messages
for(int i=0; i<num_messages; i++) {
mvwaddstr(chatwin, CHAT_HEIGHT - i, 1, messages[i]);
}
wrefresh(chatwin);
wrefresh(inputwin);
}
}
// Clear the input window (refresh required)
void ui_clear_input() {
for(int i=0; i<WIDTH; i++) {
mvwaddch(inputwin, 1, 1+i, ' ');
}
}
/**
* Read an input line, with some upper bound determined by the UI.
*
* \returns A pointer to allocated memory that holds the line. The caller is
* responsible for freeing this memory.
*/
char* ui_read_input() {
int length = 0;
int c;
// Allocate space to hold an input line
char* buffer = malloc(sizeof(char) * (WIDTH + 1));
buffer[0] = '\0';
// Loop until we get a newline
while((c = getch()) != '\n') {
// Is this a backspace or a new character?
if(c == KEY_BACKSPACE || c == KEY_DC || c == 127) {
// Delete the last character
if(length > 0) {
length--;
buffer[length] = '\0';
}
} else if(length < WIDTH) {
// Add the new character, unless we're at the length limit
buffer[length] = c;
buffer[length+1] = '\0';
length++;
}
// Clear the previous input and re-display it
ui_clear_input();
mvwaddstr(inputwin, 1, 1, buffer);
wrefresh(inputwin);
}
// Clear the input and refresh the display
ui_clear_input();
wrefresh(inputwin);
return buffer;
}
/**
* Shut down the user interface. Call this once during shutdown.
*/
void ui_shutdown() {
// Clean up windows and ncurses stuff
delwin(inputwin);
delwin(chatwin);
delwin(mainwin);
endwin();
refresh();
}