1 1.4 simonb /* $NetBSD: cvt.c,v 1.4 2023/10/06 05:49:49 simonb Exp $ */ 2 1.1 tron 3 1.1 tron /* 4 1.4 simonb * Copyright (C) 1984-2023 Mark Nudelman 5 1.1 tron * 6 1.1 tron * You may distribute under the terms of either the GNU General Public 7 1.1 tron * License or the Less License, as specified in the README file. 8 1.1 tron * 9 1.3 tron * For more information, see the README file. 10 1.1 tron */ 11 1.1 tron 12 1.1 tron /* 13 1.1 tron * Routines to convert text in various ways. Used by search. 14 1.1 tron */ 15 1.1 tron 16 1.1 tron #include "less.h" 17 1.1 tron #include "charset.h" 18 1.1 tron 19 1.1 tron extern int utf_mode; 20 1.1 tron 21 1.1 tron /* 22 1.1 tron * Get the length of a buffer needed to convert a string. 23 1.1 tron */ 24 1.4 simonb public int cvt_length(int len, int ops) 25 1.1 tron { 26 1.1 tron if (utf_mode) 27 1.1 tron /* 28 1.1 tron * Just copying a string in UTF-8 mode can cause it to grow 29 1.1 tron * in length. 30 1.1 tron * Four output bytes for one input byte is the worst case. 31 1.1 tron */ 32 1.1 tron len *= 4; 33 1.1 tron return (len + 1); 34 1.1 tron } 35 1.1 tron 36 1.1 tron /* 37 1.1 tron * Allocate a chpos array for use by cvt_text. 38 1.1 tron */ 39 1.4 simonb public int * cvt_alloc_chpos(int len) 40 1.1 tron { 41 1.1 tron int i; 42 1.1 tron int *chpos = (int *) ecalloc(sizeof(int), len); 43 1.1 tron /* Initialize all entries to an invalid position. */ 44 1.1 tron for (i = 0; i < len; i++) 45 1.1 tron chpos[i] = -1; 46 1.1 tron return (chpos); 47 1.1 tron } 48 1.1 tron 49 1.1 tron /* 50 1.1 tron * Convert text. Perform the transformations specified by ops. 51 1.1 tron * Returns converted text in odst. The original offset of each 52 1.1 tron * odst character (when it was in osrc) is returned in the chpos array. 53 1.1 tron */ 54 1.4 simonb public void cvt_text(char *odst, char *osrc, int *chpos, int *lenp, int ops) 55 1.1 tron { 56 1.1 tron char *dst; 57 1.3 tron char *edst = odst; 58 1.1 tron char *src; 59 1.4 simonb char *src_end; 60 1.1 tron LWCHAR ch; 61 1.1 tron 62 1.1 tron if (lenp != NULL) 63 1.1 tron src_end = osrc + *lenp; 64 1.1 tron else 65 1.1 tron src_end = osrc + strlen(osrc); 66 1.1 tron 67 1.1 tron for (src = osrc, dst = odst; src < src_end; ) 68 1.1 tron { 69 1.4 simonb int src_pos = (int) (src - osrc); 70 1.4 simonb int dst_pos = (int) (dst - odst); 71 1.4 simonb struct ansi_state *pansi; 72 1.1 tron ch = step_char(&src, +1, src_end); 73 1.1 tron if ((ops & CVT_BS) && ch == '\b' && dst > odst) 74 1.1 tron { 75 1.1 tron /* Delete backspace and preceding char. */ 76 1.1 tron do { 77 1.1 tron dst--; 78 1.4 simonb } while (dst > odst && utf_mode && 79 1.1 tron !IS_ASCII_OCTET(*dst) && !IS_UTF8_LEAD(*dst)); 80 1.4 simonb } else if ((ops & CVT_ANSI) && (pansi = ansi_start(ch)) != NULL) 81 1.1 tron { 82 1.1 tron /* Skip to end of ANSI escape sequence. */ 83 1.1 tron while (src < src_end) 84 1.4 simonb { 85 1.4 simonb if (ansi_step(pansi, ch) != ANSI_MID) 86 1.1 tron break; 87 1.4 simonb ch = *src++; 88 1.4 simonb } 89 1.4 simonb ansi_done(pansi); 90 1.1 tron } else 91 1.1 tron { 92 1.1 tron /* Just copy the char to the destination buffer. */ 93 1.1 tron if ((ops & CVT_TO_LC) && IS_UPPER(ch)) 94 1.1 tron ch = TO_LOWER(ch); 95 1.1 tron put_wchar(&dst, ch); 96 1.3 tron /* Record the original position of the char. */ 97 1.3 tron if (chpos != NULL) 98 1.1 tron chpos[dst_pos] = src_pos; 99 1.1 tron } 100 1.3 tron if (dst > edst) 101 1.3 tron edst = dst; 102 1.1 tron } 103 1.3 tron if ((ops & CVT_CRLF) && edst > odst && edst[-1] == '\r') 104 1.3 tron edst--; 105 1.3 tron *edst = '\0'; 106 1.1 tron if (lenp != NULL) 107 1.4 simonb *lenp = (int) (edst - odst); 108 1.3 tron /* FIXME: why was this here? if (chpos != NULL) chpos[dst - odst] = src - osrc; */ 109 1.1 tron } 110