Mercurial > hg
comparison mcabber/src/screen.c @ 74:b392112ab995
[/trunk] Changeset 88 by mikael
* Switch to using hbuf, the new history buffer implementation.
* I've had to rewrite some parts of the interface, and I have removed
the frames for the roster and the chat window.
* The wrapping is not perfect, as the prefix is not yet treated separately...
* Seems to be a display problem when receiving UTF-8, too. :-(
author | mikael |
---|---|
date | Sat, 16 Apr 2005 16:37:31 +0000 |
parents | a8689087db5c |
children | ff119bb11563 |
comparison
equal
deleted
inserted
replaced
73:1fc66b6c08ef | 74:b392112ab995 |
---|---|
13 #include "buddies.h" | 13 #include "buddies.h" |
14 #include "parsecfg.h" | 14 #include "parsecfg.h" |
15 #include "lang.h" | 15 #include "lang.h" |
16 #include "list.h" | 16 #include "list.h" |
17 #include "utf8.h" | 17 #include "utf8.h" |
18 #include "hbuf.h" | |
18 | 19 |
19 #define window_entry(n) list_entry(n, window_entry_t, list) | 20 #define window_entry(n) list_entry(n, window_entry_t, list) |
20 | 21 |
21 LIST_HEAD(window_list); | 22 LIST_HEAD(window_list); |
22 | 23 |
23 typedef struct _window_entry_t { | 24 typedef struct _window_entry_t { |
24 WINDOW *win; | 25 WINDOW *win; |
25 PANEL *panel; | 26 PANEL *panel; |
26 char *name; | 27 char *name; |
27 int nlines; | 28 GList *hbuf; |
28 char **texto; | |
29 int hidden_msg; | 29 int hidden_msg; |
30 struct list_head list; | 30 struct list_head list; |
31 } window_entry_t; | 31 } window_entry_t; |
32 | 32 |
33 | 33 |
47 static short int inputline_offset; | 47 static short int inputline_offset; |
48 | 48 |
49 | 49 |
50 /* Funciones */ | 50 /* Funciones */ |
51 | 51 |
52 int scr_WindowHeight(WINDOW * win) | 52 int scr_WindowWidth(WINDOW * win) |
53 { | 53 { |
54 int x, y; | 54 int x, y; |
55 getmaxyx(win, y, x); | 55 getmaxyx(win, y, x); |
56 return x; | 56 return x; |
57 } | |
58 | |
59 void scr_clear_box(WINDOW *win, int y, int x, int height, int width, int Color) | |
60 { | |
61 int i, j; | |
62 | |
63 wattrset(win, COLOR_PAIR(Color)); | |
64 for (i = 0; i < height; i++) { | |
65 wmove(win, y + i, x); | |
66 for (j = 0; j < width; j++) | |
67 wprintw(win, " "); | |
68 } | |
57 } | 69 } |
58 | 70 |
59 void scr_draw_box(WINDOW * win, int y, int x, int height, int width, | 71 void scr_draw_box(WINDOW * win, int y, int x, int height, int width, |
60 int Color, chtype box, chtype border) | 72 int Color, chtype box, chtype border) |
61 { | 73 { |
172 tmp->win = newwin(lines, cols, y, x); | 184 tmp->win = newwin(lines, cols, y, x); |
173 tmp->panel = new_panel(tmp->win); | 185 tmp->panel = new_panel(tmp->win); |
174 tmp->name = (char *) calloc(1, 1024); | 186 tmp->name = (char *) calloc(1, 1024); |
175 strncpy(tmp->name, title, 1024); | 187 strncpy(tmp->name, title, 1024); |
176 | 188 |
177 scr_draw_box(tmp->win, 0, 0, lines, cols, COLOR_GENERAL, 0, 0); | 189 //scr_draw_box(tmp->win, 0, 0, lines, cols, COLOR_GENERAL, 0, 0); |
190 scr_clear_box(tmp->win, 0, 0, lines, cols, COLOR_GENERAL); | |
178 //mvwprintw(tmp->win, 0, (cols - (2 + strlen(title))) / 2, " %s ", title); | 191 //mvwprintw(tmp->win, 0, (cols - (2 + strlen(title))) / 2, " %s ", title); |
179 if ((!dont_show)) { | 192 if ((!dont_show)) { |
180 currentWindow = tmp; | 193 currentWindow = tmp; |
181 } else { | 194 } else { |
182 if (currentWindow) | 195 if (currentWindow) |
209 } | 222 } |
210 } | 223 } |
211 return NULL; | 224 return NULL; |
212 } | 225 } |
213 | 226 |
227 void scr_UpdateWindow(window_entry_t *win_entry) | |
228 { | |
229 int n; | |
230 int width; | |
231 char **lines; | |
232 GList *hbuf_head; | |
233 | |
234 // We will show the last CHAT_WIN_HEIGHT lines. | |
235 // Let's find out where it begins. | |
236 win_entry->hbuf = g_list_last(win_entry->hbuf); | |
237 hbuf_head = win_entry->hbuf; | |
238 for (n=0; hbuf_head && n<(CHAT_WIN_HEIGHT-1) && g_list_previous(hbuf_head); n++) | |
239 hbuf_head = g_list_previous(hbuf_head); | |
240 | |
241 // Get the last CHAT_WIN_HEIGHT lines. | |
242 lines = hbuf_get_lines(hbuf_head, CHAT_WIN_HEIGHT); | |
243 | |
244 // Display these lines | |
245 width = scr_WindowWidth(win_entry->win); | |
246 wmove(win_entry->win, 0, 0); | |
247 for (n = 0; n < CHAT_WIN_HEIGHT; n++) { | |
248 int r = width; | |
249 if (*(lines+n)) { | |
250 wprintw(win_entry->win, "%s", *(lines+n)); | |
251 r -= strlen(*(lines+n)); | |
252 }// else | |
253 // wmove(win_entry->win, n, 0); | |
254 for ( ; r>0 ; r--) { | |
255 wprintw(win_entry->win, " "); | |
256 } | |
257 //// wclrtoeol(win_entry->win); does not work :( | |
258 } | |
259 g_free(lines); | |
260 } | |
261 | |
214 void scr_ShowWindow(const char *winId) | 262 void scr_ShowWindow(const char *winId) |
215 { | 263 { |
216 int n, width, i; | 264 window_entry_t *win_entry = scr_SearchWindow(winId); |
217 window_entry_t *tmp = scr_SearchWindow(winId); | 265 |
218 if (tmp != NULL) { | 266 if (win_entry != NULL) { |
219 top_panel(tmp->panel); | 267 top_panel(win_entry->panel); |
220 currentWindow = tmp; | 268 currentWindow = win_entry; |
221 chatmode = TRUE; | 269 chatmode = TRUE; |
222 tmp->hidden_msg = FALSE; | 270 win_entry->hidden_msg = FALSE; |
223 update_roster = TRUE; | 271 update_roster = TRUE; |
224 width = scr_WindowHeight(tmp->win); | 272 |
225 for (n = 0; n < tmp->nlines; n++) { | 273 // Refresh the window entry |
226 mvwprintw(tmp->win, n + 1, 1, ""); | 274 scr_UpdateWindow(win_entry); |
227 for (i = 0; i < width - 2; i++) | 275 |
228 waddch(tmp->win, ' '); | 276 // Finished :) |
229 mvwprintw(tmp->win, n + 1, 1, "%s", tmp->texto[n]); | |
230 } | |
231 //move(CHAT_WIN_HEIGHT - 1, maxX - 1); | |
232 update_panels(); | 277 update_panels(); |
233 doupdate(); | 278 doupdate(); |
234 } else { | 279 } else { |
235 top_panel(chatPanel); | 280 top_panel(chatPanel); |
236 currentWindow = tmp; | 281 currentWindow = win_entry; // == NULL (current window empty) |
237 } | 282 } |
238 } | 283 } |
239 | 284 |
240 void scr_ShowBuddyWindow(void) | 285 void scr_ShowBuddyWindow(void) |
241 { | 286 { |
244 scr_ShowWindow(tmp->jid); | 289 scr_ShowWindow(tmp->jid); |
245 top_panel(inputPanel); | 290 top_panel(inputPanel); |
246 } | 291 } |
247 | 292 |
248 | 293 |
249 void scr_WriteInWindow(const char *winId, char *texto, int TimeStamp, int force_show) | 294 void scr_WriteInWindow(const char *winId, char *text, int TimeStamp, |
250 { | 295 int force_show) |
251 time_t ahora; | 296 { |
252 int n; | 297 char *line; |
253 int i; | 298 window_entry_t *win_entry; |
254 int width; | |
255 window_entry_t *tmp; | |
256 int dont_show = FALSE; | 299 int dont_show = FALSE; |
257 | 300 |
258 tmp = scr_SearchWindow(winId); | 301 line = calloc(1, strlen(text)+16); |
259 | 302 |
303 // Prepare line (timestamp + text) | |
304 // FIXME: actually timestamp and text should not be merged, there is a prefix | |
305 // field in the hbuf_block structure just for that. | |
306 if (TimeStamp) { | |
307 time_t now = time(NULL); | |
308 strftime(line, 12, "[%H:%M] ", localtime(&now)); | |
309 } else { | |
310 strcpy(line, " "); | |
311 } | |
312 strcat(line, text); | |
313 | |
314 // Look for the window entry. | |
315 win_entry = scr_SearchWindow(winId); | |
316 | |
317 // Do we have to really show the window? | |
260 if (!chatmode) | 318 if (!chatmode) |
261 dont_show = TRUE; | 319 dont_show = TRUE; |
262 else if ((!force_show) && ((!currentWindow || (currentWindow != tmp)))) | 320 else if ((!force_show) && ((!currentWindow || (currentWindow != win_entry)))) |
263 dont_show = TRUE; | 321 dont_show = TRUE; |
264 | 322 |
265 if (tmp == NULL) { | 323 // If the window entry doesn't exist yet, let's create it. |
266 tmp = scr_CreatePanel(winId, ROSTER_WEIGHT, 0, CHAT_WIN_HEIGHT, | 324 if (win_entry == NULL) { |
267 maxX - ROSTER_WEIGHT, dont_show); | 325 win_entry = scr_CreatePanel(winId, ROSTER_WIDTH, 0, CHAT_WIN_HEIGHT, |
268 tmp->texto = (char **) calloc((CHAT_WIN_HEIGHT+1) * 3, sizeof(char *)); | 326 maxX - ROSTER_WIDTH, dont_show); |
269 for (n = 0; n < CHAT_WIN_HEIGHT * 3; n++) | 327 } |
270 tmp->texto[n] = (char *) calloc(1, 1024); | 328 |
271 | 329 hbuf_add_line(&win_entry->hbuf, line, |
272 if (TimeStamp) { | 330 maxX - scr_WindowWidth(rosterWnd) - 14); |
273 ahora = time(NULL); | 331 free(line); |
274 strftime(tmp->texto[tmp->nlines], 1024, "[%H:%M] ", | |
275 localtime(&ahora)); | |
276 strcat(tmp->texto[tmp->nlines], texto); | |
277 } else { | |
278 sprintf(tmp->texto[tmp->nlines], " %s", texto); | |
279 } | |
280 tmp->nlines++; | |
281 } else { | |
282 if (tmp->nlines < CHAT_WIN_HEIGHT - 2) { | |
283 if (TimeStamp) { | |
284 ahora = time(NULL); | |
285 strftime(tmp->texto[tmp->nlines], 1024, | |
286 "[%H:%M] ", localtime(&ahora)); | |
287 strcat(tmp->texto[tmp->nlines], texto); | |
288 } else { | |
289 sprintf(tmp->texto[tmp->nlines], " %s", texto); | |
290 } | |
291 tmp->nlines++; | |
292 } else { | |
293 for (n = 0; n < tmp->nlines; n++) { | |
294 memset(tmp->texto[n], 0, 1024); | |
295 strncpy(tmp->texto[n], tmp->texto[n + 1], 1024); | |
296 } | |
297 if (TimeStamp) { | |
298 ahora = time(NULL); | |
299 strftime(tmp->texto[tmp->nlines - 1], 1024, | |
300 "[%H:%M] ", localtime(&ahora)); | |
301 strcat(tmp->texto[tmp->nlines - 1], texto); | |
302 } else { | |
303 sprintf(tmp->texto[tmp->nlines - 1], " %s", texto); | |
304 } | |
305 } | |
306 } | |
307 | 332 |
308 if (!dont_show) { | 333 if (!dont_show) { |
309 top_panel(tmp->panel); | 334 // Show and refresh the window |
310 width = scr_WindowHeight(tmp->win); | 335 top_panel(win_entry->panel); |
311 for (n = 0; n < tmp->nlines; n++) { | 336 scr_UpdateWindow(win_entry); |
312 mvwprintw(tmp->win, n + 1, 1, ""); | |
313 for (i = 0; i < width - 2; i++) | |
314 waddch(tmp->win, ' '); | |
315 mvwprintw(tmp->win, n + 1, 1, "%s", tmp->texto[n]); | |
316 } | |
317 | |
318 update_panels(); | 337 update_panels(); |
319 doupdate(); | 338 doupdate(); |
320 } else { | 339 } else { |
321 tmp->hidden_msg = TRUE; | 340 win_entry->hidden_msg = TRUE; |
322 update_roster = TRUE; | 341 update_roster = TRUE; |
323 } | 342 } |
324 } | 343 } |
325 | 344 |
326 void scr_InitCurses(void) | 345 void scr_InitCurses(void) |
343 return; | 362 return; |
344 } | 363 } |
345 | 364 |
346 void scr_DrawMainWindow(void) | 365 void scr_DrawMainWindow(void) |
347 { | 366 { |
367 int l; | |
368 | |
348 /* Draw main panels */ | 369 /* Draw main panels */ |
349 rosterWnd = newwin(CHAT_WIN_HEIGHT, ROSTER_WEIGHT, 0, 0); | 370 rosterWnd = newwin(CHAT_WIN_HEIGHT, ROSTER_WIDTH, 0, 0); |
350 rosterPanel = new_panel(rosterWnd); | 371 rosterPanel = new_panel(rosterWnd); |
351 scr_draw_box(rosterWnd, 0, 0, CHAT_WIN_HEIGHT, ROSTER_WEIGHT, | 372 scr_clear_box(rosterWnd, 0, 0, CHAT_WIN_HEIGHT, ROSTER_WIDTH, |
352 COLOR_GENERAL, 0, 0); | 373 COLOR_GENERAL); |
353 mvwprintw(rosterWnd, 0, (ROSTER_WEIGHT - strlen(i18n("Roster"))) / 2, | 374 for (l=0 ; l < CHAT_WIN_HEIGHT ; l++) |
354 i18n("Roster")); | 375 mvwaddch(rosterWnd, l, ROSTER_WIDTH-1, ACS_VLINE); |
355 | 376 |
356 chatWnd = newwin(CHAT_WIN_HEIGHT, maxX - ROSTER_WEIGHT, 0, ROSTER_WEIGHT); | 377 chatWnd = newwin(CHAT_WIN_HEIGHT, maxX - ROSTER_WIDTH, 0, ROSTER_WIDTH); |
357 chatPanel = new_panel(chatWnd); | 378 chatPanel = new_panel(chatWnd); |
358 scr_draw_box(chatWnd, 0, 0, CHAT_WIN_HEIGHT, maxX - ROSTER_WEIGHT, | 379 scr_clear_box(chatWnd, 0, 0, CHAT_WIN_HEIGHT, maxX - ROSTER_WIDTH, |
359 COLOR_GENERAL, 0, 0); | 380 COLOR_GENERAL); |
360 mvwprintw(chatWnd, 1, 1, "This is the status window"); | 381 scrollok(chatWnd, TRUE); |
382 mvwprintw(chatWnd, 0, 0, "This is the status window"); | |
361 | 383 |
362 logWnd_border = newwin(LOG_WIN_HEIGHT, maxX, CHAT_WIN_HEIGHT, 0); | 384 logWnd_border = newwin(LOG_WIN_HEIGHT, maxX, CHAT_WIN_HEIGHT, 0); |
363 logPanel_border = new_panel(logWnd_border); | 385 logPanel_border = new_panel(logWnd_border); |
364 scr_draw_box(logWnd_border, 0, 0, LOG_WIN_HEIGHT, maxX, COLOR_GENERAL, 0, 0); | 386 scr_draw_box(logWnd_border, 0, 0, LOG_WIN_HEIGHT, maxX, COLOR_GENERAL, 0, 0); |
365 logWnd = derwin(logWnd_border, LOG_WIN_HEIGHT-2, maxX-2, 1, 1); | 387 logWnd = derwin(logWnd_border, LOG_WIN_HEIGHT-2, maxX-2, 1, 1); |
366 logPanel = new_panel(logWnd); | 388 logPanel = new_panel(logWnd); |
367 wbkgd(logWnd, COLOR_PAIR(COLOR_GENERAL)); | 389 wbkgd(logWnd, COLOR_PAIR(COLOR_GENERAL)); |
368 | 390 |
369 scrollok(logWnd,TRUE); | 391 scrollok(logWnd, TRUE); |
370 | 392 |
371 inputWnd = newwin(1, maxX, maxY-1, 0); | 393 inputWnd = newwin(1, maxX, maxY-1, 0); |
372 inputPanel = new_panel(inputWnd); | 394 inputPanel = new_panel(inputWnd); |
373 | 395 |
374 bud_DrawRoster(rosterWnd); | 396 bud_DrawRoster(rosterWnd); |
383 refresh(); | 405 refresh(); |
384 endwin(); | 406 endwin(); |
385 return; | 407 return; |
386 } | 408 } |
387 | 409 |
410 // XXX This function is almost useless now. Once we handle properly | |
411 // the prefix in scr_WriteInWindow(), we can remove it... | |
388 void scr_WriteMessage(const char *jid, const char *text, char *prefix) | 412 void scr_WriteMessage(const char *jid, const char *text, char *prefix) |
389 { | 413 { |
390 char **submsgs; | 414 char *buffer = (char *) malloc(strlen(prefix) + strlen(text) + 1); |
391 int n, i; | |
392 char *buffer = (char *) malloc(strlen(text) + strlen(text)); | |
393 | 415 |
394 if (prefix) | 416 if (prefix) |
395 strcpy(buffer, prefix); | 417 strcpy(buffer, prefix); |
396 else | 418 else |
397 *buffer = 0; | 419 *buffer = 0; |
398 | 420 |
399 strcat(buffer, text); | 421 strcat(buffer, text); |
400 | 422 |
401 submsgs = | 423 scr_WriteInWindow(jid, buffer, TRUE, FALSE); |
402 ut_SplitMessage(buffer, &n, maxX - scr_WindowHeight(rosterWnd) - 14); | 424 |
403 | |
404 for (i = 0; i < n; i++) { | |
405 if (i == 0) | |
406 scr_WriteInWindow(jid, submsgs[i], TRUE, FALSE); | |
407 else | |
408 scr_WriteInWindow(jid, submsgs[i], FALSE, FALSE); | |
409 } | |
410 | |
411 for (i = 0; i < n; i++) | |
412 free(submsgs[i]); | |
413 free(submsgs); | |
414 free(buffer); | 425 free(buffer); |
415 } | 426 } |
416 | 427 |
417 void scr_WriteIncomingMessage(const char *jidfrom, const char *text) | 428 void scr_WriteIncomingMessage(const char *jidfrom, const char *text) |
418 { | 429 { |
419 char *buffer = utf8_decode(text); | 430 char *buffer = utf8_decode(text); |
431 // FIXME expand tabs... | |
420 scr_WriteMessage(jidfrom, buffer, "<== "); | 432 scr_WriteMessage(jidfrom, buffer, "<== "); |
421 free(buffer); | 433 free(buffer); |
422 top_panel(inputPanel); | 434 top_panel(inputPanel); |
423 update_panels(); | 435 update_panels(); |
424 doupdate(); | 436 doupdate(); |