| 824 | | static char *sfu_buffer = NULL; |
| 825 | | static size_t sfu_blen = 0; |
| 826 | | static size_t sfu_bp = 0; |
| 827 | | |
| 828 | | static void _state_utf8_flush(STATE *s, CHARSET *chs) |
| | 824 | /* internal use only */ |
| | 825 | |
| | 826 | struct utf8_state |
| | 827 | { |
| | 828 | char *buffer; |
| | 829 | size_t blen; |
| | 830 | size_t bp; |
| | 831 | }; |
| | 832 | |
| | 833 | static struct utf8_state *new_utf8_state (void) |
| | 834 | { |
| | 835 | return safe_calloc (sizeof (struct utf8_state), 1); |
| | 836 | } |
| | 837 | |
| | 838 | static void free_utf8_state (struct utf8_state **sp) |
| | 839 | { |
| | 840 | if (!sp || !*sp) return; |
| | 841 | safe_free ((void **) &(*sp)->buffer); |
| | 842 | safe_free ((void **) sp); |
| | 843 | } |
| | 844 | |
| | 845 | static void _state_utf8_flush(STATE *s, CHARSET *chs, struct utf8_state *sfu) |
| 850 | | void state_fput_utf8(STATE *st, char u, CHARSET *chs) |
| 851 | | { |
| 852 | | if((u & 0x80) == 0 || (sfu_bp && (u & IIOOOOOO) != IOOOOOOO)) |
| 853 | | _state_utf8_flush(st, chs); |
| | 867 | static void state_fput_utf8(STATE *st, char u, CHARSET *chs, struct utf8_state *sfu) |
| | 868 | { |
| | 869 | if((u & 0x80) == 0 || (sfu->bp && (u & IIOOOOOO) != IOOOOOOO)) |
| | 870 | _state_utf8_flush(st, chs, sfu); |
| 861 | | if(sfu_bp + 1 >= sfu_blen) |
| 862 | | { |
| 863 | | sfu_blen = (sfu_blen + 80) * 2; |
| 864 | | safe_realloc((void **) &sfu_buffer, sfu_blen); |
| 865 | | } |
| 866 | | sfu_buffer[sfu_bp++] = u; |
| 867 | | } |
| 868 | | } |
| 869 | | |
| | 878 | if(sfu->bp + 1 >= sfu->blen) |
| | 879 | { |
| | 880 | sfu->blen = (sfu->blen + 80) * 2; |
| | 881 | safe_realloc((void **) &sfu->buffer, sfu->blen); |
| | 882 | } |
| | 883 | sfu->buffer[sfu->bp++] = u; |
| | 884 | } |
| | 885 | } |
| | 886 | |
| | 887 | /* a nicer interface for decoding */ |
| | 888 | |
| | 889 | DECODER *mutt_open_decoder (STATE *s, BODY *b, int istext) |
| | 890 | { |
| | 891 | DECODER *dp = safe_calloc (sizeof (DECODER), 1); |
| | 892 | |
| | 893 | dp->s = s; |
| | 894 | |
| | 895 | if (istext && (s->flags & M_CHARCONV)) |
| | 896 | { |
| | 897 | char *charset = mutt_get_parameter ("charset", b->parameter); |
| | 898 | dp->is_utf8 = mutt_is_utf8 (charset) && !mutt_is_utf8 (Charset); |
| | 899 | |
| | 900 | if (dp->is_utf8) |
| | 901 | { |
| | 902 | dp->sfu = new_utf8_state (); |
| | 903 | dp->chs = mutt_get_charset (Charset); |
| | 904 | } |
| | 905 | else |
| | 906 | dp->map = mutt_get_translation (charset, Charset); |
| | 907 | } |
| | 908 | |
| | 909 | return dp; |
| | 910 | } |
| | 911 | |
| | 912 | void mutt_close_decoder (DECODER **dpp) |
| | 913 | { |
| | 914 | if (!dpp || !*dpp) |
| | 915 | return; |
| | 916 | |
| | 917 | if ((*dpp)->is_utf8) |
| | 918 | { |
| | 919 | _state_utf8_flush ((*dpp)->s, (*dpp)->chs, (*dpp)->sfu); |
| | 920 | free_utf8_state (&(*dpp)->sfu); |
| | 921 | } |
| | 922 | |
| | 923 | safe_free ((void **) dpp); |
| | 924 | } |
| | 925 | |
| | 926 | void mutt_decoder_putc (DECODER *dp, char c) |
| | 927 | { |
| | 928 | if (dp->is_utf8) |
| | 929 | state_fput_utf8 (dp->s, c, dp->chs, dp->sfu); |
| | 930 | else |
| | 931 | state_prefix_putc (mutt_display_char ((unsigned char) c, dp->map), dp->s); |
| | 932 | } |