Ticket #3259: mc-3259-hex-update-v2.patch

File mc-3259-hex-update-v2.patch, 6.9 KB (added by egmont, 5 years ago)

Fix v2

  • src/viewer/hex.c

    diff --git a/src/viewer/hex.c b/src/viewer/hex.c
    index e355cfb..78e9c90 100644
    a b static const char hex_char[] = "0123456789ABCDEF"; 
    7373/*** file scope functions ************************************************************************/ 
    7474/* --------------------------------------------------------------------------------------------- */ 
    7575 
    76 #ifdef HAVE_CHARSET 
    77 static int 
    78 utf8_to_int (char *str, int *char_width, gboolean * result) 
    79 { 
    80     int res = -1; 
    81     gunichar ch; 
    82     gchar *next_ch = NULL; 
    83     int width = 0; 
    84  
    85     *result = TRUE; 
    86  
    87     if (str == NULL) 
    88     { 
    89         *result = FALSE; 
    90         return 0; 
    91     } 
    92  
    93     res = g_utf8_get_char_validated (str, -1); 
    94  
    95     if (res < 0) 
    96         ch = *str; 
    97     else 
    98     { 
    99         ch = res; 
    100         /* Calculate UTF-8 char width */ 
    101         next_ch = g_utf8_next_char (str); 
    102         if (next_ch) 
    103             width = next_ch - str; 
    104         else 
    105             ch = 0; 
    106     } 
    107     *char_width = width; 
    108     return ch; 
    109 } 
    110 #endif /* HAVE_CHARSET */ 
    111  
    11276/* --------------------------------------------------------------------------------------------- */ 
    11377/** Determine the state of the current byte. 
    11478 * 
    mcview_display_hex (mcview_t * view) 
    146110    const screen_dimen text_start = 8 + 13 * ngroups + 
    147111        ((width < 80) ? 0 : (width == 80) ? (ngroups - 1) : (ngroups - 1 + 1)); 
    148112 
    149     screen_dimen row; 
     113    int row; 
    150114    off_t from; 
    151115    int c; 
    152116    mark_t boldflag = MARK_NORMAL; 
    153117    struct hexedit_change_node *curr = view->change_list; 
    154118#ifdef HAVE_CHARSET 
    155119    int ch = 0; 
     120    int cont_bytes = 0;  /* number of continuation bytes remanining from current UTF-8 */ 
     121    gboolean cjk_right = FALSE;  /* whether the second byte of a CJK is to be processed */ 
    156122#endif /* HAVE_CHARSET */ 
    157123 
    158124    char hex_buff[10];          /* A temporary buffer for sprintf and mvwaddstr */ 
    mcview_display_hex (mcview_t * view) 
    161127    mcview_display_clean (view); 
    162128 
    163129    /* Find the first displayable changed byte */ 
     130    /* In UTF-8 mode, go back by 1 or maybe 2 lines to handle continuation bytes properly. */ 
    164131    from = view->dpy_start; 
     132    row = 0; 
     133#ifdef HAVE_CHARSET 
     134    if (view->utf8) 
     135    { 
     136        if (from >= view->bytes_per_line) { 
     137            row--; 
     138            from -= view->bytes_per_line; 
     139        } 
     140        if (view->bytes_per_line == 4 && from >= view->bytes_per_line) { 
     141            row--; 
     142            from -= view->bytes_per_line; 
     143        } 
     144    } 
     145#endif /* HAVE_CHARSET */ 
    165146    while (curr && (curr->offset < from)) 
    166147    { 
    167148        curr = curr->next; 
    168149    } 
    169150 
    170     for (row = 0; mcview_get_byte (view, from, NULL) == TRUE && row < height; row++) 
     151    for (; mcview_get_byte (view, from, NULL) == TRUE && row < (int) height; row++) 
    171152    { 
    172153        screen_dimen col = 0; 
    173154        size_t i; 
    mcview_display_hex (mcview_t * view) 
    175156        col = 0; 
    176157 
    177158        /* Print the hex offset */ 
    178         g_snprintf (hex_buff, sizeof (hex_buff), "%08" PRIXMAX " ", (uintmax_t) from); 
    179         widget_move (view, top + row, left); 
    180         tty_setcolor (VIEW_BOLD_COLOR); 
    181         for (i = 0; col < width && hex_buff[i] != '\0'; i++) 
    182         { 
    183             tty_print_char (hex_buff[i]); 
    184             /*              tty_print_char(hex_buff[i]); */ 
    185             col += 1; 
     159        if (row >= 0) { 
     160            g_snprintf (hex_buff, sizeof (hex_buff), "%08" PRIXMAX " ", (uintmax_t) from); 
     161            widget_move (view, top + row, left); 
     162            tty_setcolor (VIEW_BOLD_COLOR); 
     163            for (i = 0; col < width && hex_buff[i] != '\0'; i++) 
     164            { 
     165                tty_print_char (hex_buff[i]); 
     166                col += 1; 
     167            } 
     168            tty_setcolor (VIEW_NORMAL_COLOR); 
    186169        } 
    187         tty_setcolor (VIEW_NORMAL_COLOR); 
    188170 
    189171        for (bytes = 0; bytes < view->bytes_per_line; bytes++, from++) 
    190172        { 
    mcview_display_hex (mcview_t * view) 
    192174#ifdef HAVE_CHARSET 
    193175            if (view->utf8) 
    194176            { 
    195                 int cw = 1; 
    196                 gboolean read_res = TRUE; 
    197  
    198                 ch = mcview_get_utf (view, from, &cw, &read_res); 
    199                 if (!read_res) 
    200                     break; 
    201                 /* char width is greater 0 bytes */ 
    202                 if (cw != 0) 
    203                 { 
    204                     int cnt; 
    205                     char corr_buf[UTF8_CHAR_LEN + 1]; 
    206                     struct hexedit_change_node *corr = curr; 
    207                     int res; 
    208  
    209                     res = g_unichar_to_utf8 (ch, (char *) corr_buf); 
    210  
    211                     for (cnt = 0; cnt < cw; cnt++) 
    212                     { 
    213                         if (curr != NULL && from + cnt == curr->offset) 
    214                         { 
    215                             /* replace only changed bytes in array of multibyte char */ 
    216                             corr_buf[cnt] = curr->value; 
    217                             curr = curr->next; 
    218                         } 
     177                int res; 
     178                int j; 
     179                struct hexedit_change_node *corr = curr; 
     180                gchar utf8buf[UTF8_CHAR_LEN + 1]; 
     181 
     182                if (cont_bytes) { 
     183                    /* UTF-8 continuation bytes, print a space (with proper attributes)... */ 
     184                    cont_bytes--; 
     185                    ch = ' '; 
     186                    if (cjk_right) { 
     187                        /* ... except when it'd wipe out the right half of a CJK, then print nothing */ 
     188                        cjk_right = FALSE; 
     189                        ch = -1; 
    219190                    } 
    220                     corr_buf[res] = '\0'; 
    221                     /* Determine the state of the current multibyte char */ 
    222                     ch = utf8_to_int ((char *) corr_buf, &cw, &read_res); 
    223                     curr = corr; 
    224                 } 
     191                } else { 
     192                    for (j = 0; j < UTF8_CHAR_LEN; j++) { 
     193                        if (mcview_get_byte (view, from + j, &res)) 
     194                            utf8buf[j] = res; 
     195                        else 
     196                        { 
     197                            utf8buf[j] = '\0'; 
     198                            break; 
     199                        } 
     200                        if (curr != NULL && from + j == curr->offset) 
     201                            utf8buf[j] = curr->value; 
     202                        if (curr != NULL && from + j >= curr->offset) 
     203                            curr = curr->next; 
     204                    } 
     205                    utf8buf[UTF8_CHAR_LEN] = '\0'; 
     206                    /* Determine the state of the current multibyte char */ 
     207                    ch = g_utf8_get_char_validated (utf8buf, -1); 
     208                    if (ch == -1 || ch == -2) { 
     209                        ch = '.'; 
     210                    } else { 
     211                        gchar *next_ch = g_utf8_next_char (utf8buf); 
     212                        cont_bytes = next_ch - utf8buf - 1; 
     213                        if (g_unichar_iswide(ch)) 
     214                            cjk_right = TRUE; 
     215                    } 
     216                    curr = corr; 
     217                } 
    225218            } 
    226219#endif /* HAVE_CHARSET */ 
     220 
     221            /* For negative rows, the only thing we care about is overflowing 
     222             * UTF-8 continuation bytes which were handled above. */ 
     223            if (row < 0) 
     224            { 
     225                if (curr != NULL && from == curr->offset) 
     226                    curr = curr->next; 
     227                continue; 
     228            } 
     229 
    227230            if (!mcview_get_byte (view, from, &c)) 
    228231                break; 
    229232