You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

sidebar-utf8.patch 4.8KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132
  1. From: Antonio Radici <antonio@debian.org>
  2. Date: Tue, 4 Mar 2014 15:39:14 +0100
  3. Subject: sidebar-utf8
  4. This patch fixes a problem with utf-8 strings and the sidebar,
  5. it rewrites entirely make_sidebar_entry so it also fixes some
  6. segfaults due to misallocations and overflows.
  7. See:
  8. http://bugs.debian.org/584581
  9. http://bugs.debian.org/603287
  10. Gbp-Pq: Topic mutt-patched
  11. ---
  12. sidebar.c | 97 +++++++++++++++++++++++++++++++++++++++++++--------------------
  13. 1 file changed, 67 insertions(+), 30 deletions(-)
  14. diff --git a/sidebar.c b/sidebar.c
  15. index 4356ffc..8f58f85 100644
  16. --- a/sidebar.c
  17. +++ b/sidebar.c
  18. @@ -30,6 +30,7 @@
  19. #include <libgen.h>
  20. #include "keymap.h"
  21. #include <stdbool.h>
  22. +#include <wchar.h>
  23. /*BUFFY *CurBuffy = 0;*/
  24. static BUFFY *TopBuffy = 0;
  25. @@ -82,36 +83,72 @@ void calc_boundaries (int menu)
  26. char *make_sidebar_entry(char *box, int size, int new, int flagged)
  27. {
  28. - static char *entry = 0;
  29. - char *c;
  30. - int i = 0;
  31. - int delim_len = strlen(SidebarDelim);
  32. -
  33. - c = realloc(entry, SidebarWidth - delim_len + 2);
  34. - if ( c ) entry = c;
  35. - entry[SidebarWidth - delim_len + 1] = 0;
  36. - for (; i < SidebarWidth - delim_len + 1; entry[i++] = ' ' );
  37. - i = strlen(box);
  38. - strncpy( entry, box, i < (SidebarWidth - delim_len + 1) ? i : (SidebarWidth - delim_len + 1) );
  39. -
  40. - if (size == -1)
  41. - sprintf(entry + SidebarWidth - delim_len - 3, "?");
  42. - else if ( new ) {
  43. - if (flagged > 0) {
  44. - sprintf(
  45. - entry + SidebarWidth - delim_len - 5 - quick_log10(size) - quick_log10(new) - quick_log10(flagged),
  46. - "% d(%d)[%d]", size, new, flagged);
  47. - } else {
  48. - sprintf(
  49. - entry + SidebarWidth - delim_len - 3 - quick_log10(size) - quick_log10(new),
  50. - "% d(%d)", size, new);
  51. - }
  52. - } else if (flagged > 0) {
  53. - sprintf( entry + SidebarWidth - delim_len - 3 - quick_log10(size) - quick_log10(flagged), "% d[%d]", size, flagged);
  54. - } else {
  55. - sprintf( entry + SidebarWidth - delim_len - 1 - quick_log10(size), "% d", size);
  56. - }
  57. - return entry;
  58. + char int_store[20]; // up to 64 bits integers
  59. + int right_width, left_width;
  60. + int box_len, box_bytes;
  61. + int int_len;
  62. + int right_offset = 0;
  63. + int delim_len = strlen(SidebarDelim);
  64. + static char *entry;
  65. +
  66. + right_width = left_width = 0;
  67. + box_len = box_bytes = 0;
  68. +
  69. + // allocate an entry big enough to contain SidebarWidth wide chars
  70. + entry = malloc((SidebarWidth*4)+1); // TODO: error check
  71. +
  72. + // determine the right space (i.e.: how big are the numbers that we want to print)
  73. + if ( size > 0 ) {
  74. + int_len = snprintf(int_store, sizeof(int_store), "%d", size);
  75. + right_width += int_len;
  76. + } else {
  77. + right_width = 1; // to represent 0
  78. + }
  79. + if ( new > 0 ) {
  80. + int_len = snprintf(int_store, sizeof(int_store), "%d", new);
  81. + right_width += int_len + 2; // 2 is for ()
  82. + }
  83. + if ( flagged > 0 ) {
  84. + int_len = snprintf(int_store, sizeof(int_store), "%d", flagged);
  85. + right_width += int_len + 2; // 2 is for []
  86. + }
  87. +
  88. + // determine how much space we have for *box and its padding (if any)
  89. + left_width = SidebarWidth - right_width - 1 - delim_len; // 1 is for the space
  90. + //fprintf(stdout, "left_width: %d right_width: %d\n", left_width, right_width);
  91. + // right side overflow case
  92. + if ( left_width <= 0 ) {
  93. + snprintf(entry, SidebarWidth*4, "%-*.*s ...", SidebarWidth-4-delim_len, SidebarWidth-4-delim_len, box);
  94. + return entry;
  95. + }
  96. + right_width -= delim_len;
  97. +
  98. + // to support utf-8 chars we need to add enough space padding in case there
  99. + // are less chars than bytes in *box
  100. + box_len = mbstowcs(NULL, box, 0);
  101. + box_bytes = strlen(box);
  102. + // debug
  103. + //fprintf(stdout, "box_len: %d box_bytes: %d (diff: %d)\n", box_len, box_bytes, (box_bytes-box_len));
  104. + // if there is less string than the space we allow, then we will add the
  105. + // spaces
  106. + if ( box_len != -1 && box_len < left_width ) {
  107. + left_width += (box_bytes - box_len);
  108. + }
  109. + // otherwise sprintf will truncate the string for us (therefore, no else case)
  110. +
  111. + // print the sidebar entry (without new and flagged messages, at the moment)
  112. + //fprintf(stdout, "left_width: %d right_width: %d\n", left_width, right_width);
  113. + right_offset = snprintf(entry, SidebarWidth*4, "%-*.*s %d", left_width, left_width, box, size);
  114. +
  115. + // then pad new and flagged messages if any
  116. + if ( new > 0 ) {
  117. + right_offset += snprintf(entry+right_offset, SidebarWidth*4-right_offset, "(%d)", new);
  118. + }
  119. + if ( flagged > 0 ) {
  120. + right_offset += snprintf(entry+right_offset, SidebarWidth*4-right_offset, "[%d]", flagged);
  121. + }
  122. +
  123. + return entry;
  124. }
  125. void set_curbuffy(char buf[LONG_STRING])