comparison mcabber/src/screen.c @ 849:42c43a88d823

Status buffer management Create a status window and a status history buffer. This special history buffer is not part of the winbuflst linked list, because it will be used early (for startup logs for example).
author Mikael Berthe <mikael@lilotux.net>
date Mon, 08 May 2006 23:46:18 +0200
parents a9161d2dc414
children d0781ca2dd08
comparison
equal deleted inserted replaced
848:a9161d2dc414 849:42c43a88d823
68 static WINDOW *mainstatusWnd, *chatstatusWnd; 68 static WINDOW *mainstatusWnd, *chatstatusWnd;
69 static PANEL *rosterPanel, *chatPanel, *inputPanel; 69 static PANEL *rosterPanel, *chatPanel, *inputPanel;
70 static PANEL *mainstatusPanel, *chatstatusPanel; 70 static PANEL *mainstatusPanel, *chatstatusPanel;
71 static PANEL *logPanel; 71 static PANEL *logPanel;
72 static int maxY, maxX; 72 static int maxY, maxX;
73 static winbuf *statusWindow;
73 static winbuf *currentWindow; 74 static winbuf *currentWindow;
74 75
75 static int roster_hidden; 76 static int roster_hidden;
76 static int chatmode; 77 static int chatmode;
77 static int multimode; 78 static int multimode;
375 g_free(buffer2); 376 g_free(buffer2);
376 } 377 }
377 g_free(buffer); 378 g_free(buffer);
378 } 379 }
379 380
381 // scr_CreateBuddyPanel(title, dontshow)
382 // Note: title (aka winId) can be NULL for special buffers
380 static winbuf *scr_CreateBuddyPanel(const char *title, int dont_show) 383 static winbuf *scr_CreateBuddyPanel(const char *title, int dont_show)
381 { 384 {
382 int x; 385 int x;
383 int y; 386 int y;
384 int lines; 387 int lines;
411 else 414 else
412 top_panel(chatPanel); 415 top_panel(chatPanel);
413 } 416 }
414 update_panels(); 417 update_panels();
415 418
416 // Load buddy history from file (if enabled) 419 // If title is NULL, this is a special buffer
417 hlog_read_history(title, &tmp->hbuf, maxX - Roster_Width - PREFIX_WIDTH); 420 if (title) {
418 421 // Load buddy history from file (if enabled)
419 winbuflst = g_slist_append(winbuflst, tmp); 422 hlog_read_history(title, &tmp->hbuf, maxX - Roster_Width - PREFIX_WIDTH);
423
424 winbuflst = g_slist_append(winbuflst, tmp);
425 }
420 return tmp; 426 return tmp;
421 } 427 }
422 428
423 static winbuf *scr_SearchWindow(const char *winId) 429 static winbuf *scr_SearchWindow(const char *winId, int special)
424 { 430 {
425 GSList *wblp; 431 GSList *wblp;
426 winbuf *wbp; 432 winbuf *wbp;
427 433
428 if (!winId) return NULL; 434 if (special)
435 return statusWindow; // Only one special window atm.
436
437 if (!winId)
438 return NULL;
429 439
430 for (wblp = winbuflst; wblp; wblp = g_slist_next(wblp)) { 440 for (wblp = winbuflst; wblp; wblp = g_slist_next(wblp)) {
431 wbp = wblp->data; 441 wbp = wblp->data;
432 if (wbp->name) { 442 if (wbp->name) {
433 if (!strcasecmp(wbp->name, winId)) 443 if (!strcasecmp(wbp->name, winId))
437 return NULL; 447 return NULL;
438 } 448 }
439 449
440 bool scr_BuddyBufferExists(const char *jid) 450 bool scr_BuddyBufferExists(const char *jid)
441 { 451 {
442 return (scr_SearchWindow(jid) != NULL); 452 return (scr_SearchWindow(jid, FALSE) != NULL);
443 } 453 }
444 454
445 // scr_UpdateWindow() 455 // scr_UpdateWindow()
446 // (Re-)Display the given chat window. 456 // (Re-)Display the given chat window.
447 static void scr_UpdateWindow(winbuf *win_entry) 457 static void scr_UpdateWindow(winbuf *win_entry)
532 g_free(lines); 542 g_free(lines);
533 } 543 }
534 544
535 // scr_ShowWindow() 545 // scr_ShowWindow()
536 // Display the chat window with the given identifier. 546 // Display the chat window with the given identifier.
537 static void scr_ShowWindow(const char *winId) 547 // "special" must be true if this is a special buffer window.
538 { 548 static void scr_ShowWindow(const char *winId, int special)
539 winbuf *win_entry = scr_SearchWindow(winId); 549 {
540 550 winbuf *win_entry;
541 if (!win_entry) 551
542 win_entry = scr_CreateBuddyPanel(winId, FALSE); 552 win_entry = scr_SearchWindow(winId, special);
553
554 if (!win_entry) {
555 if (special) {
556 if (!statusWindow) {
557 statusWindow = scr_CreateBuddyPanel(NULL, FALSE);
558 // We could set statusWindow->name here...
559 }
560 win_entry = statusWindow;
561 } else {
562 win_entry = scr_CreateBuddyPanel(winId, FALSE);
563 }
564 }
543 565
544 top_panel(win_entry->panel); 566 top_panel(win_entry->panel);
545 currentWindow = win_entry; 567 currentWindow = win_entry;
546 chatmode = TRUE; 568 chatmode = TRUE;
547 roster_msg_setflag(winId, FALSE); 569 if (!special) {
548 roster_setflags(winId, ROSTER_FLAG_LOCK, TRUE); 570 roster_msg_setflag(winId, FALSE);
549 update_roster = TRUE; 571 roster_setflags(winId, ROSTER_FLAG_LOCK, TRUE);
572 update_roster = TRUE;
573 }
550 574
551 // Refresh the window 575 // Refresh the window
552 scr_UpdateWindow(win_entry); 576 scr_UpdateWindow(win_entry);
553 577
554 // Finished :) 578 // Finished :)
561 // Display the chat window buffer for the current buddy. 585 // Display the chat window buffer for the current buddy.
562 void scr_ShowBuddyWindow(void) 586 void scr_ShowBuddyWindow(void)
563 { 587 {
564 const gchar *jid; 588 const gchar *jid;
565 589
566 if (!current_buddy) 590 if (!current_buddy) {
567 jid = NULL; 591 jid = NULL;
568 else 592 } else {
569 jid = CURRENT_JID; 593 jid = CURRENT_JID;
594 if (buddy_gettype(BUDDATA(current_buddy)) & ROSTER_TYPE_SPECIAL) {
595 scr_ShowWindow(buddy_getname(BUDDATA(current_buddy)), TRUE);
596 return;
597 }
598 }
570 599
571 if (!jid) { 600 if (!jid) {
572 top_panel(chatPanel); 601 top_panel(chatPanel);
573 top_panel(inputPanel); 602 top_panel(inputPanel);
574 currentWindow = NULL; 603 currentWindow = NULL;
575 return; 604 return;
576 } 605 }
577 606
578 scr_ShowWindow(jid); 607 scr_ShowWindow(jid, FALSE);
579 } 608 }
580 609
581 // scr_WriteInWindow() 610 // scr_WriteInWindow()
582 // Write some text in the winId window (this usually is a jid). 611 // Write some text in the winId window (this usually is a jid).
612 // Use winId == NULL for the special status buffer.
583 // Lines are splitted when they are too long to fit in the chat window. 613 // Lines are splitted when they are too long to fit in the chat window.
584 // If this window doesn't exist, it is created. 614 // If this window doesn't exist, it is created.
585 void scr_WriteInWindow(const char *winId, const char *text, time_t timestamp, 615 void scr_WriteInWindow(const char *winId, const char *text, time_t timestamp,
586 unsigned int prefix_flags, int force_show) 616 unsigned int prefix_flags, int force_show)
587 { 617 {
588 winbuf *win_entry; 618 winbuf *win_entry;
589 char *text_locale; 619 char *text_locale;
590 int dont_show = FALSE; 620 int dont_show = FALSE;
621 int special;
591 622
592 // Look for the window entry. 623 // Look for the window entry.
593 win_entry = scr_SearchWindow(winId); 624 special = (winId == NULL);
625 win_entry = scr_SearchWindow(winId, special);
594 626
595 // Do we have to really show the window? 627 // Do we have to really show the window?
596 if (!chatmode) 628 if (!chatmode)
597 dont_show = TRUE; 629 dont_show = TRUE;
598 else if ((!force_show) && ((!currentWindow || (currentWindow != win_entry)))) 630 else if ((!force_show) && ((!currentWindow || (currentWindow != win_entry))))
599 dont_show = TRUE; 631 dont_show = TRUE;
600 632
601 // If the window entry doesn't exist yet, let's create it. 633 // If the window entry doesn't exist yet, let's create it.
602 if (win_entry == NULL) { 634 if (!win_entry) {
603 win_entry = scr_CreateBuddyPanel(winId, dont_show); 635 if (special) {
636 if (!statusWindow) {
637 statusWindow = scr_CreateBuddyPanel(NULL, dont_show);
638 // We could set statusWindow->name here...
639 }
640 win_entry = statusWindow;
641 } else {
642 win_entry = scr_CreateBuddyPanel(winId, dont_show);
643 }
604 } 644 }
605 645
606 // The message must be displayed -> update top pointer 646 // The message must be displayed -> update top pointer
607 if (win_entry->cleared) 647 if (win_entry->cleared)
608 win_entry->top = g_list_last(win_entry->hbuf); 648 win_entry->top = g_list_last(win_entry->hbuf);
633 top_panel(win_entry->panel); 673 top_panel(win_entry->panel);
634 scr_UpdateWindow(win_entry); 674 scr_UpdateWindow(win_entry);
635 top_panel(inputPanel); 675 top_panel(inputPanel);
636 update_panels(); 676 update_panels();
637 doupdate(); 677 doupdate();
638 } else if (!(prefix_flags & HBB_PREFIX_NOFLAG)) { 678 } else if (!special && !(prefix_flags & HBB_PREFIX_NOFLAG)) {
639 roster_msg_setflag(winId, TRUE); 679 roster_msg_setflag(winId, TRUE);
640 update_roster = TRUE; 680 update_roster = TRUE;
641 } 681 }
642 } 682 }
643 683
761 logPanel = new_panel(logWnd); 801 logPanel = new_panel(logWnd);
762 chatstatusPanel = new_panel(chatstatusWnd); 802 chatstatusPanel = new_panel(chatstatusWnd);
763 mainstatusPanel = new_panel(mainstatusWnd); 803 mainstatusPanel = new_panel(mainstatusWnd);
764 inputPanel = new_panel(inputWnd); 804 inputPanel = new_panel(inputWnd);
765 805
806 // Build the buddylist at least once, to make sure the special buffer
807 // is added
808 buddylist_build();
809
766 if (utf8_mode) 810 if (utf8_mode)
767 scr_LogPrint(LPRINT_NORMAL, "WARNING: UTF-8 not yet supported!"); 811 scr_LogPrint(LPRINT_NORMAL, "WARNING: UTF-8 not yet supported!");
768 } else { 812 } else {
769 // Update panels 813 // Update panels
770 replace_panel(rosterPanel, rosterWnd); 814 replace_panel(rosterPanel, rosterWnd);
778 // We'll need to redraw the roster 822 // We'll need to redraw the roster
779 update_roster = TRUE; 823 update_roster = TRUE;
780 return; 824 return;
781 } 825 }
782 826
827 static inline void resize_win_buffer(winbuf *wbp, int x, int y,
828 int lines, int cols)
829 {
830 // Resize/move buddy window
831 wresize(wbp->win, lines, cols);
832 mvwin(wbp->win, 0, Roster_Width);
833 werase(wbp->win);
834 // If a panel exists, replace the old window with the new
835 if (wbp->panel)
836 replace_panel(wbp->panel, wbp->win);
837 // Redo line wrapping
838 wbp->top = hbuf_previous_persistent(wbp->top);
839 hbuf_rebuild(&wbp->hbuf, maxX - Roster_Width - PREFIX_WIDTH);
840 }
841
783 // scr_Resize() 842 // scr_Resize()
784 // Function called when the window is resized. 843 // Function called when the window is resized.
785 // - Resize windows 844 // - Resize windows
786 // - Rewrap lines in each buddy buffer 845 // - Rewrap lines in each buddy buffer
787 void scr_Resize() 846 void scr_Resize()
807 cols = maxX - Roster_Width; 866 cols = maxX - Roster_Width;
808 if (cols < 1) cols = 1; 867 if (cols < 1) cols = 1;
809 868
810 for (wblp = winbuflst; wblp; wblp = g_slist_next(wblp)) { 869 for (wblp = winbuflst; wblp; wblp = g_slist_next(wblp)) {
811 wbp = wblp->data; 870 wbp = wblp->data;
812 if (wbp->win) { 871 if (wbp->win)
813 // Resize/move buddy window 872 resize_win_buffer(wbp, x, y, lines, cols);
814 wresize(wbp->win, lines, cols); 873 }
815 mvwin(wbp->win, 0, Roster_Width); 874
816 werase(wbp->win); 875 // Resize/move special status buffer
817 // If a panel exists, replace the old window with the new 876 if (statusWindow)
818 if (wbp->panel) 877 resize_win_buffer(statusWindow, x, y, lines, cols);
819 replace_panel(wbp->panel, wbp->win);
820 // Redo line wrapping
821 wbp->top = hbuf_previous_persistent(wbp->top);
822 hbuf_rebuild(&wbp->hbuf, maxX - Roster_Width - PREFIX_WIDTH);
823 }
824 }
825 878
826 // Refresh current buddy window 879 // Refresh current buddy window
827 if (chatmode) 880 if (chatmode)
828 scr_ShowBuddyWindow(); 881 scr_ShowBuddyWindow();
829 } 882 }
1145 } 1198 }
1146 1199
1147 void scr_WriteOutgoingMessage(const char *jidto, const char *text) 1200 void scr_WriteOutgoingMessage(const char *jidto, const char *text)
1148 { 1201 {
1149 scr_WriteMessage(jidto, text, 0, HBB_PREFIX_OUT|HBB_PREFIX_HLIGHT); 1202 scr_WriteMessage(jidto, text, 0, HBB_PREFIX_OUT|HBB_PREFIX_HLIGHT);
1150 scr_ShowWindow(jidto); 1203 scr_ShowWindow(jidto, FALSE);
1151 } 1204 }
1152 1205
1153 inline void set_autoaway(bool setaway) 1206 inline void set_autoaway(bool setaway)
1154 { 1207 {
1155 static enum imstatus oldstatus; 1208 static enum imstatus oldstatus;
1353 void scr_BufferScrollUpDown(int updown, unsigned int nblines) 1406 void scr_BufferScrollUpDown(int updown, unsigned int nblines)
1354 { 1407 {
1355 winbuf *win_entry; 1408 winbuf *win_entry;
1356 int n, nbl; 1409 int n, nbl;
1357 GList *hbuf_top; 1410 GList *hbuf_top;
1411 guint isspe;
1358 1412
1359 // Get win_entry 1413 // Get win_entry
1360 if (!current_buddy) return; 1414 if (!current_buddy) return;
1361 win_entry = scr_SearchWindow(CURRENT_JID); 1415
1416 isspe = buddy_gettype(BUDDATA(current_buddy)) & ROSTER_TYPE_SPECIAL;
1417 win_entry = scr_SearchWindow(CURRENT_JID, isspe);
1362 if (!win_entry) return; 1418 if (!win_entry) return;
1363 1419
1364 if (!nblines) { 1420 if (!nblines) {
1365 // Scroll half a screen (or less) 1421 // Scroll half a screen (or less)
1366 nbl = CHAT_WIN_HEIGHT/2; 1422 nbl = CHAT_WIN_HEIGHT/2;
1404 // scr_BufferClear() 1460 // scr_BufferClear()
1405 // Clear the current buddy window (used for the /clear command) 1461 // Clear the current buddy window (used for the /clear command)
1406 void scr_BufferClear(void) 1462 void scr_BufferClear(void)
1407 { 1463 {
1408 winbuf *win_entry; 1464 winbuf *win_entry;
1465 guint isspe;
1409 1466
1410 // Get win_entry 1467 // Get win_entry
1411 if (!current_buddy) return; 1468 if (!current_buddy) return;
1412 win_entry = scr_SearchWindow(CURRENT_JID); 1469 isspe = buddy_gettype(BUDDATA(current_buddy)) & ROSTER_TYPE_SPECIAL;
1470 win_entry = scr_SearchWindow(CURRENT_JID, isspe);
1413 if (!win_entry) return; 1471 if (!win_entry) return;
1414 1472
1415 win_entry->cleared = TRUE; 1473 win_entry->cleared = TRUE;
1416 win_entry->top = NULL; 1474 win_entry->top = NULL;
1417 1475
1427 // Jump to the head/tail of the current buddy window 1485 // Jump to the head/tail of the current buddy window
1428 // (top if topbottom == -1, bottom topbottom == 1) 1486 // (top if topbottom == -1, bottom topbottom == 1)
1429 void scr_BufferTopBottom(int topbottom) 1487 void scr_BufferTopBottom(int topbottom)
1430 { 1488 {
1431 winbuf *win_entry; 1489 winbuf *win_entry;
1490 guint isspe;
1432 1491
1433 // Get win_entry 1492 // Get win_entry
1434 if (!current_buddy) return; 1493 if (!current_buddy) return;
1435 win_entry = scr_SearchWindow(CURRENT_JID); 1494 isspe = buddy_gettype(BUDDATA(current_buddy)) & ROSTER_TYPE_SPECIAL;
1495 win_entry = scr_SearchWindow(CURRENT_JID, isspe);
1436 if (!win_entry) return; 1496 if (!win_entry) return;
1437 1497
1438 win_entry->cleared = FALSE; 1498 win_entry->cleared = FALSE;
1439 if (topbottom == 1) 1499 if (topbottom == 1)
1440 win_entry->top = NULL; 1500 win_entry->top = NULL;
1454 // (backward search if direction == -1, forward if topbottom == 1) 1514 // (backward search if direction == -1, forward if topbottom == 1)
1455 void scr_BufferSearch(int direction, const char *text) 1515 void scr_BufferSearch(int direction, const char *text)
1456 { 1516 {
1457 winbuf *win_entry; 1517 winbuf *win_entry;
1458 GList *current_line, *search_res; 1518 GList *current_line, *search_res;
1519 guint isspe;
1459 1520
1460 // Get win_entry 1521 // Get win_entry
1461 if (!current_buddy) return; 1522 if (!current_buddy) return;
1462 win_entry = scr_SearchWindow(CURRENT_JID); 1523 isspe = buddy_gettype(BUDDATA(current_buddy)) & ROSTER_TYPE_SPECIAL;
1524 win_entry = scr_SearchWindow(CURRENT_JID, isspe);
1463 if (!win_entry) return; 1525 if (!win_entry) return;
1464 1526
1465 if (win_entry->top) 1527 if (win_entry->top)
1466 current_line = win_entry->top; 1528 current_line = win_entry->top;
1467 else 1529 else
1487 // Jump to the specified position in the buffer, in % 1549 // Jump to the specified position in the buffer, in %
1488 void scr_BufferPercent(int pc) 1550 void scr_BufferPercent(int pc)
1489 { 1551 {
1490 winbuf *win_entry; 1552 winbuf *win_entry;
1491 GList *search_res; 1553 GList *search_res;
1554 guint isspe;
1492 1555
1493 // Get win_entry 1556 // Get win_entry
1494 if (!current_buddy) return; 1557 if (!current_buddy) return;
1495 win_entry = scr_SearchWindow(CURRENT_JID); 1558 isspe = buddy_gettype(BUDDATA(current_buddy)) & ROSTER_TYPE_SPECIAL;
1559 win_entry = scr_SearchWindow(CURRENT_JID, isspe);
1496 if (!win_entry) return; 1560 if (!win_entry) return;
1497 1561
1498 if (pc < 0 || pc > 100) { 1562 if (pc < 0 || pc > 100) {
1499 scr_LogPrint(LPRINT_NORMAL, "Bad % value"); 1563 scr_LogPrint(LPRINT_NORMAL, "Bad % value");
1500 return; 1564 return;
1518 // t is a date in seconds since `00:00:00 1970-01-01 UTC' 1582 // t is a date in seconds since `00:00:00 1970-01-01 UTC'
1519 void scr_BufferDate(time_t t) 1583 void scr_BufferDate(time_t t)
1520 { 1584 {
1521 winbuf *win_entry; 1585 winbuf *win_entry;
1522 GList *search_res; 1586 GList *search_res;
1587 guint isspe;
1523 1588
1524 // Get win_entry 1589 // Get win_entry
1525 if (!current_buddy) return; 1590 if (!current_buddy) return;
1526 win_entry = scr_SearchWindow(CURRENT_JID); 1591 isspe = buddy_gettype(BUDDATA(current_buddy)) & ROSTER_TYPE_SPECIAL;
1592 win_entry = scr_SearchWindow(CURRENT_JID, isspe);
1527 if (!win_entry) return; 1593 if (!win_entry) return;
1528 1594
1529 search_res = hbuf_jump_date(win_entry->hbuf, t); 1595 search_res = hbuf_jump_date(win_entry->hbuf, t);
1530 1596
1531 win_entry->cleared = FALSE; 1597 win_entry->cleared = FALSE;
1557 // scr_setmsgflag_if_needed(jid) 1623 // scr_setmsgflag_if_needed(jid)
1558 // Set the message flag unless we're already in the jid buffer window 1624 // Set the message flag unless we're already in the jid buffer window
1559 void scr_setmsgflag_if_needed(const char *jid) 1625 void scr_setmsgflag_if_needed(const char *jid)
1560 { 1626 {
1561 const char *current_jid; 1627 const char *current_jid;
1628
1629 if (!jid)
1630 return;
1562 1631
1563 if (current_buddy) 1632 if (current_buddy)
1564 current_jid = buddy_getjid(BUDDATA(current_buddy)); 1633 current_jid = buddy_getjid(BUDDATA(current_buddy));
1565 else 1634 else
1566 current_jid = NULL; 1635 current_jid = NULL;