diff options
Diffstat (limited to 'src/ui/messages.c')
-rw-r--r-- | src/ui/messages.c | 209 |
1 files changed, 192 insertions, 17 deletions
diff --git a/src/ui/messages.c b/src/ui/messages.c index 780dd45..79a7cab 100644 --- a/src/ui/messages.c +++ b/src/ui/messages.c | |||
@@ -25,56 +25,231 @@ | |||
25 | #include "messages.h" | 25 | #include "messages.h" |
26 | 26 | ||
27 | #include "../application.h" | 27 | #include "../application.h" |
28 | #include "../util.h" | ||
29 | |||
30 | void | ||
31 | _messages_iterate(UI_MESSAGES_Handle *messages, | ||
32 | const struct GNUNET_CHAT_Message *message) | ||
33 | { | ||
34 | const bool selected = (messages->line_selected == messages->line_index); | ||
35 | |||
36 | messages->line_index++; | ||
37 | |||
38 | if (selected) | ||
39 | messages->selected = message; | ||
40 | } | ||
28 | 41 | ||
29 | void | 42 | void |
30 | messages_event(UI_MESSAGES_Handle *messages, | 43 | messages_event(UI_MESSAGES_Handle *messages, |
31 | struct MESSENGER_Application *app, | 44 | MESSENGER_Application *app, |
32 | int key) | 45 | int key) |
33 | { | 46 | { |
34 | // TODO | 47 | messages->line_index = 0; |
48 | messages->selected = NULL; | ||
49 | |||
50 | int count = 0; | ||
51 | |||
52 | UI_MESSAGES_List *element = messages->head; | ||
53 | while (element) | ||
54 | { | ||
55 | _messages_iterate(messages, element->message); | ||
56 | count++; | ||
57 | |||
58 | element = element->next; | ||
59 | } | ||
60 | |||
61 | switch (key) | ||
62 | { | ||
63 | case 27: | ||
64 | case KEY_EXIT: | ||
65 | { | ||
66 | app->chat.context = NULL; | ||
67 | break; | ||
68 | } | ||
69 | case KEY_UP: | ||
70 | { | ||
71 | messages->line_selected--; | ||
72 | break; | ||
73 | } | ||
74 | case KEY_DOWN: | ||
75 | { | ||
76 | messages->line_selected++; | ||
77 | break; | ||
78 | } | ||
79 | case '\n': | ||
80 | case KEY_ENTER: | ||
81 | { | ||
82 | if (messages->selected) | ||
83 | GNUNET_CHAT_message_delete( | ||
84 | messages->selected, | ||
85 | GNUNET_TIME_relative_get_zero_() | ||
86 | ); | ||
87 | |||
88 | break; | ||
89 | } | ||
90 | default: | ||
91 | break; | ||
92 | } | ||
93 | |||
94 | if (messages->line_selected < 0) | ||
95 | messages->line_selected = 0; | ||
96 | else if (messages->line_selected >= count) | ||
97 | messages->line_selected = count - 1; | ||
98 | |||
99 | if (!(messages->window)) | ||
100 | return; | ||
101 | |||
102 | const int height = getmaxy(messages->window) - getbegy(messages->window); | ||
103 | const int y = messages->line_selected - messages->line_offset; | ||
104 | |||
105 | if (y < 0) | ||
106 | messages->line_offset += y; | ||
107 | else if (y + 1 >= height) | ||
108 | messages->line_offset += y + 1 - height; | ||
109 | |||
110 | if (messages->line_offset < 0) | ||
111 | messages->line_offset = 0; | ||
112 | else if (messages->line_offset >= count) | ||
113 | messages->line_offset = count - 1; | ||
35 | } | 114 | } |
36 | 115 | ||
37 | int | 116 | void |
38 | _messages_iterate_print(void *cls, | 117 | _messages_iterate_print(UI_MESSAGES_Handle *messages, |
39 | struct GNUNET_CHAT_Context *context, | ||
40 | const struct GNUNET_CHAT_Message *message) | 118 | const struct GNUNET_CHAT_Message *message) |
41 | { | 119 | { |
42 | UI_MESSAGES_Handle *messages = cls; | 120 | const bool selected = (messages->line_selected == messages->line_index); |
121 | const int y = messages->line_index - messages->line_offset; | ||
122 | |||
123 | messages->line_index++; | ||
124 | |||
125 | if (y < 0) | ||
126 | return; | ||
43 | 127 | ||
44 | const int y = messages->line_index++; | 128 | const int height = getmaxy(messages->window) - getbegy(messages->window); |
129 | |||
130 | if (y >= height) | ||
131 | return; | ||
45 | 132 | ||
46 | enum GNUNET_CHAT_MessageKind kind = GNUNET_CHAT_message_get_kind(message); | 133 | enum GNUNET_CHAT_MessageKind kind = GNUNET_CHAT_message_get_kind(message); |
134 | struct GNUNET_CHAT_Contact *sender = GNUNET_CHAT_message_get_sender(message); | ||
135 | |||
136 | const char *name = sender? GNUNET_CHAT_contact_get_name(sender) : NULL; | ||
47 | const char *text = GNUNET_CHAT_message_get_text(message); | 137 | const char *text = GNUNET_CHAT_message_get_text(message); |
48 | 138 | ||
49 | struct GNUNET_TIME_Absolute timestamp = GNUNET_CHAT_message_get_timestamp( | 139 | struct GNUNET_TIME_Absolute timestamp = GNUNET_CHAT_message_get_timestamp( |
50 | message | 140 | message |
51 | ); | 141 | ); |
52 | 142 | ||
143 | const int attrs_select = A_BOLD; | ||
144 | |||
145 | if (selected) wattron(messages->window, attrs_select); | ||
146 | |||
53 | wmove(messages->window, y, 0); | 147 | wmove(messages->window, y, 0); |
54 | wprintw( | 148 | wprintw( |
55 | messages->window, | 149 | messages->window, |
56 | "%s | [%d]: %s", | 150 | "%s | [%d] %s: %s", |
57 | GNUNET_TIME_absolute2s(timestamp), | 151 | GNUNET_TIME_absolute2s(timestamp), |
58 | (int) kind, | 152 | (int) kind, |
153 | name, | ||
59 | text | 154 | text |
60 | ); | 155 | ); |
61 | 156 | ||
62 | return GNUNET_YES; | 157 | if (selected) wattroff(messages->window, attrs_select); |
63 | } | 158 | } |
64 | 159 | ||
65 | void | 160 | void |
66 | messages_print(UI_MESSAGES_Handle *messages, | 161 | messages_print(UI_MESSAGES_Handle *messages) |
67 | struct MESSENGER_Application *app) | ||
68 | { | 162 | { |
69 | if (!(messages->window)) | 163 | if (!(messages->window)) |
70 | return; | 164 | return; |
71 | 165 | ||
72 | struct GNUNET_CHAT_Context *context = app->chat.context; | ||
73 | |||
74 | messages->line_index = 0; | 166 | messages->line_index = 0; |
75 | GNUNET_CHAT_context_iterate_messages( | 167 | werase(messages->window); |
76 | context, | 168 | |
77 | _messages_iterate_print, | 169 | UI_MESSAGES_List *element = messages->head; |
78 | messages | 170 | while (element) |
171 | { | ||
172 | _messages_iterate_print(messages, element->message); | ||
173 | element = element->next; | ||
174 | } | ||
175 | } | ||
176 | |||
177 | void | ||
178 | messages_clear(UI_MESSAGES_Handle *messages) | ||
179 | { | ||
180 | UI_MESSAGES_List *element; | ||
181 | while (messages->head) | ||
182 | { | ||
183 | element = messages->head; | ||
184 | |||
185 | GNUNET_CONTAINER_DLL_remove( | ||
186 | messages->head, | ||
187 | messages->tail, | ||
188 | element | ||
189 | ); | ||
190 | |||
191 | GNUNET_free(element); | ||
192 | } | ||
193 | } | ||
194 | |||
195 | static int | ||
196 | _message_compare_timestamps(UNUSED void *cls, | ||
197 | UI_MESSAGES_List *list0, | ||
198 | UI_MESSAGES_List *list1) | ||
199 | { | ||
200 | struct GNUNET_TIME_Absolute time0, time1; | ||
201 | |||
202 | if ((!list0) || (!list1)) | ||
203 | return 0; | ||
204 | |||
205 | time0 = GNUNET_CHAT_message_get_timestamp(list0->message); | ||
206 | time1 = GNUNET_CHAT_message_get_timestamp(list1->message); | ||
207 | |||
208 | if (GNUNET_TIME_absolute_cmp(time0, >, time1)) | ||
209 | return -1; | ||
210 | else if (GNUNET_TIME_absolute_cmp(time0, <, time1)) | ||
211 | return +1; | ||
212 | else | ||
213 | return 0; | ||
214 | } | ||
215 | |||
216 | void | ||
217 | messages_add(UI_MESSAGES_Handle *messages, | ||
218 | const struct GNUNET_CHAT_Message *message) | ||
219 | { | ||
220 | if (GNUNET_CHAT_KIND_DELETION == GNUNET_CHAT_message_get_kind(message)) | ||
221 | return; | ||
222 | |||
223 | UI_MESSAGES_List *element = GNUNET_new(UI_MESSAGES_List); | ||
224 | element->message = message; | ||
225 | |||
226 | GNUNET_CONTAINER_DLL_insert_sorted( | ||
227 | UI_MESSAGES_List, | ||
228 | _message_compare_timestamps, | ||
229 | NULL, | ||
230 | messages->head, | ||
231 | messages->tail, | ||
232 | element | ||
79 | ); | 233 | ); |
80 | } | 234 | } |
235 | |||
236 | void | ||
237 | messages_remove(UI_MESSAGES_Handle *messages, | ||
238 | const struct GNUNET_CHAT_Message *message) | ||
239 | { | ||
240 | UI_MESSAGES_List *element = messages->head; | ||
241 | while (element) | ||
242 | { | ||
243 | if (element->message == message) | ||
244 | break; | ||
245 | |||
246 | element = element->next; | ||
247 | } | ||
248 | |||
249 | if (element) | ||
250 | GNUNET_CONTAINER_DLL_remove( | ||
251 | messages->head, | ||
252 | messages->tail, | ||
253 | element | ||
254 | ); | ||
255 | } | ||