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

File mc-3259-hex-update-v3.patch, 10.1 KB (added by egmont, 10 years ago)

Fix v3

  • src/viewer/hex.c

    diff --git a/src/viewer/hex.c b/src/viewer/hex.c
    index e355cfb..608bf94 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 * 
    utf8_to_int (char *str, int *char_width, gboolean * result) 
    11882 */ 
    11983 
    12084static mark_t 
    121 mcview_hex_calculate_boldflag (mcview_t * view, off_t from, struct hexedit_change_node *curr) 
     85mcview_hex_calculate_boldflag (mcview_t * view, off_t from, struct hexedit_change_node *curr, 
     86                               gboolean force_changed) 
    12287{ 
    12388    return (from == view->hex_cursor) ? MARK_CURSOR 
    124         : (curr != NULL && from == curr->offset) ? MARK_CHANGED 
     89        : ((curr != NULL && from == curr->offset) || force_changed) ? MARK_CHANGED 
    12590        : (view->search_start <= from && from < view->search_end) ? MARK_SELECTED : MARK_NORMAL; 
    12691} 
    12792 
    mcview_display_hex (mcview_t * view) 
    146111    const screen_dimen text_start = 8 + 13 * ngroups + 
    147112        ((width < 80) ? 0 : (width == 80) ? (ngroups - 1) : (ngroups - 1 + 1)); 
    148113 
    149     screen_dimen row; 
     114    int row; 
    150115    off_t from; 
    151116    int c; 
    152     mark_t boldflag = MARK_NORMAL; 
     117    mark_t boldflag_byte = MARK_NORMAL, boldflag_char = MARK_NORMAL; 
    153118    struct hexedit_change_node *curr = view->change_list; 
    154119#ifdef HAVE_CHARSET 
    155120    int ch = 0; 
     121    int cont_bytes = 0;  /* number of continuation bytes remanining from current UTF-8 */ 
     122    gboolean cjk_right = FALSE;  /* whether the second byte of a CJK is to be processed */ 
    156123#endif /* HAVE_CHARSET */ 
     124    gboolean utf8_changed = FALSE;  /* whether any of the bytes in the UTF-8 were changed */ 
    157125 
    158126    char hex_buff[10];          /* A temporary buffer for sprintf and mvwaddstr */ 
    159127    int bytes;                  /* Number of bytes already printed on the line */ 
    mcview_display_hex (mcview_t * view) 
    161129    mcview_display_clean (view); 
    162130 
    163131    /* Find the first displayable changed byte */ 
     132    /* In UTF-8 mode, go back by 1 or maybe 2 lines to handle continuation bytes properly. */ 
    164133    from = view->dpy_start; 
     134    row = 0; 
     135#ifdef HAVE_CHARSET 
     136    if (view->utf8) 
     137    { 
     138        if (from >= view->bytes_per_line) { 
     139            row--; 
     140            from -= view->bytes_per_line; 
     141        } 
     142        if (view->bytes_per_line == 4 && from >= view->bytes_per_line) { 
     143            row--; 
     144            from -= view->bytes_per_line; 
     145        } 
     146    } 
     147#endif /* HAVE_CHARSET */ 
    165148    while (curr && (curr->offset < from)) 
    166149    { 
    167150        curr = curr->next; 
    168151    } 
    169152 
    170     for (row = 0; mcview_get_byte (view, from, NULL) == TRUE && row < height; row++) 
     153    for (; mcview_get_byte (view, from, NULL) == TRUE && row < (int) height; row++) 
    171154    { 
    172155        screen_dimen col = 0; 
    173156        size_t i; 
    mcview_display_hex (mcview_t * view) 
    175158        col = 0; 
    176159 
    177160        /* 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; 
     161        if (row >= 0) { 
     162            g_snprintf (hex_buff, sizeof (hex_buff), "%08" PRIXMAX " ", (uintmax_t) from); 
     163            widget_move (view, top + row, left); 
     164            tty_setcolor (VIEW_BOLD_COLOR); 
     165            for (i = 0; col < width && hex_buff[i] != '\0'; i++) 
     166            { 
     167                tty_print_char (hex_buff[i]); 
     168                col += 1; 
     169            } 
     170            tty_setcolor (VIEW_NORMAL_COLOR); 
    186171        } 
    187         tty_setcolor (VIEW_NORMAL_COLOR); 
    188172 
    189173        for (bytes = 0; bytes < view->bytes_per_line; bytes++, from++) 
    190174        { 
    mcview_display_hex (mcview_t * view) 
    192176#ifdef HAVE_CHARSET 
    193177            if (view->utf8) 
    194178            { 
    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                         } 
     179                int res; 
     180                int j; 
     181                struct hexedit_change_node *corr = curr; 
     182                gchar utf8buf[UTF8_CHAR_LEN + 1]; 
     183 
     184                if (cont_bytes) { 
     185                    /* UTF-8 continuation bytes, print a space (with proper attributes)... */ 
     186                    cont_bytes--; 
     187                    ch = ' '; 
     188                    if (cjk_right) { 
     189                        /* ... except when it'd wipe out the right half of a CJK, then print nothing */ 
     190                        cjk_right = FALSE; 
     191                        ch = -1; 
    219192                    } 
    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                 } 
     193                } else { 
     194                    int first_changed = -1; 
     195                    for (j = 0; j < UTF8_CHAR_LEN; j++) { 
     196                        if (mcview_get_byte (view, from + j, &res)) 
     197                            utf8buf[j] = res; 
     198                        else 
     199                        { 
     200                            utf8buf[j] = '\0'; 
     201                            break; 
     202                        } 
     203                        if (curr != NULL && from + j == curr->offset) { 
     204                            utf8buf[j] = curr->value; 
     205                            if (first_changed == -1) 
     206                                first_changed = j; 
     207                        } 
     208                        if (curr != NULL && from + j >= curr->offset) 
     209                            curr = curr->next; 
     210                    } 
     211                    utf8buf[UTF8_CHAR_LEN] = '\0'; 
     212                    /* Determine the state of the current multibyte char */ 
     213                    ch = g_utf8_get_char_validated (utf8buf, -1); 
     214                    if (ch == -1 || ch == -2) { 
     215                        ch = '.'; 
     216                    } else { 
     217                        gchar *next_ch = g_utf8_next_char (utf8buf); 
     218                        cont_bytes = next_ch - utf8buf - 1; 
     219                        if (g_unichar_iswide(ch)) 
     220                            cjk_right = TRUE; 
     221                    } 
     222                    utf8_changed = (first_changed >= 0 && first_changed <= cont_bytes); 
     223                    curr = corr; 
     224                } 
    225225            } 
    226226#endif /* HAVE_CHARSET */ 
     227 
     228            /* For negative rows, the only thing we care about is overflowing 
     229             * UTF-8 continuation bytes which were handled above. */ 
     230            if (row < 0) 
     231            { 
     232                if (curr != NULL && from == curr->offset) 
     233                    curr = curr->next; 
     234                continue; 
     235            } 
     236 
    227237            if (!mcview_get_byte (view, from, &c)) 
    228238                break; 
    229239 
    mcview_display_hex (mcview_t * view) 
    235245            } 
    236246 
    237247            /* Determine the state of the current byte */ 
    238             boldflag = mcview_hex_calculate_boldflag (view, from, curr); 
     248            boldflag_byte = mcview_hex_calculate_boldflag (view, from, curr, FALSE); 
     249            boldflag_char = mcview_hex_calculate_boldflag (view, from, curr, utf8_changed); 
    239250 
    240251            /* Determine the value of the current byte */ 
    241252            if (curr != NULL && from == curr->offset) 
    mcview_display_hex (mcview_t * view) 
    245256            } 
    246257 
    247258            /* Select the color for the hex number */ 
    248             tty_setcolor (boldflag == MARK_NORMAL ? VIEW_NORMAL_COLOR : 
    249                           boldflag == MARK_SELECTED ? VIEW_BOLD_COLOR : 
    250                           boldflag == MARK_CHANGED ? VIEW_UNDERLINED_COLOR : 
    251                           /* boldflag == MARK_CURSOR */ 
     259            tty_setcolor (boldflag_byte == MARK_NORMAL ? VIEW_NORMAL_COLOR : 
     260                          boldflag_byte == MARK_SELECTED ? VIEW_BOLD_COLOR : 
     261                          boldflag_byte == MARK_CHANGED ? VIEW_UNDERLINED_COLOR : 
     262                          /* boldflag_byte == MARK_CURSOR */ 
    252263                          view->hexview_in_text ? VIEW_SELECTED_COLOR : VIEW_UNDERLINED_COLOR); 
    253264 
    254265            /* Print the hex number */ 
    mcview_display_hex (mcview_t * view) 
    292303 
    293304            /* Select the color for the character; this differs from the 
    294305             * hex color when boldflag == MARK_CURSOR */ 
    295             tty_setcolor (boldflag == MARK_NORMAL ? VIEW_NORMAL_COLOR : 
    296                           boldflag == MARK_SELECTED ? VIEW_BOLD_COLOR : 
    297                           boldflag == MARK_CHANGED ? VIEW_UNDERLINED_COLOR : 
    298                           /* boldflag == MARK_CURSOR */ 
     306            tty_setcolor (boldflag_char == MARK_NORMAL ? VIEW_NORMAL_COLOR : 
     307                          boldflag_char == MARK_SELECTED ? VIEW_BOLD_COLOR : 
     308                          boldflag_char == MARK_CHANGED ? VIEW_UNDERLINED_COLOR : 
     309                          /* boldflag_char == MARK_CURSOR */ 
    299310                          view->hexview_in_text ? VIEW_SELECTED_COLOR : MARKED_SELECTED_COLOR); 
    300311 
    301312