1195902Sdelphij/* 2240121Sdelphij * Copyright (C) 1984-2012 Mark Nudelman 3195902Sdelphij * 4195902Sdelphij * You may distribute under the terms of either the GNU General Public 5195902Sdelphij * License or the Less License, as specified in the README file. 6195902Sdelphij * 7240121Sdelphij * For more information, see the README file. 8195902Sdelphij */ 9195902Sdelphij 10195902Sdelphij/* 11195902Sdelphij * Routines to convert text in various ways. Used by search. 12195902Sdelphij */ 13195902Sdelphij 14195902Sdelphij#include "less.h" 15195902Sdelphij#include "charset.h" 16195902Sdelphij 17195902Sdelphijextern int utf_mode; 18195902Sdelphij 19195902Sdelphij/* 20195902Sdelphij * Get the length of a buffer needed to convert a string. 21195902Sdelphij */ 22195902Sdelphij public int 23195902Sdelphijcvt_length(len, ops) 24195902Sdelphij int len; 25195902Sdelphij int ops; 26195902Sdelphij{ 27195902Sdelphij if (utf_mode) 28195902Sdelphij /* 29195902Sdelphij * Just copying a string in UTF-8 mode can cause it to grow 30195902Sdelphij * in length. 31195902Sdelphij * Four output bytes for one input byte is the worst case. 32195902Sdelphij */ 33195902Sdelphij len *= 4; 34195902Sdelphij return (len + 1); 35195902Sdelphij} 36195902Sdelphij 37195902Sdelphij/* 38195902Sdelphij * Allocate a chpos array for use by cvt_text. 39195902Sdelphij */ 40195902Sdelphij public int * 41195902Sdelphijcvt_alloc_chpos(len) 42195902Sdelphij int len; 43195902Sdelphij{ 44195902Sdelphij int i; 45195902Sdelphij int *chpos = (int *) ecalloc(sizeof(int), len); 46195902Sdelphij /* Initialize all entries to an invalid position. */ 47195902Sdelphij for (i = 0; i < len; i++) 48195902Sdelphij chpos[i] = -1; 49195902Sdelphij return (chpos); 50195902Sdelphij} 51195902Sdelphij 52195902Sdelphij/* 53195902Sdelphij * Convert text. Perform the transformations specified by ops. 54195902Sdelphij * Returns converted text in odst. The original offset of each 55195902Sdelphij * odst character (when it was in osrc) is returned in the chpos array. 56195902Sdelphij */ 57195902Sdelphij public void 58195902Sdelphijcvt_text(odst, osrc, chpos, lenp, ops) 59195902Sdelphij char *odst; 60195902Sdelphij char *osrc; 61195902Sdelphij int *chpos; 62195902Sdelphij int *lenp; 63195902Sdelphij int ops; 64195902Sdelphij{ 65195902Sdelphij char *dst; 66240121Sdelphij char *edst = odst; 67195902Sdelphij char *src; 68195902Sdelphij register char *src_end; 69195902Sdelphij LWCHAR ch; 70195902Sdelphij 71195902Sdelphij if (lenp != NULL) 72195902Sdelphij src_end = osrc + *lenp; 73195902Sdelphij else 74195902Sdelphij src_end = osrc + strlen(osrc); 75195902Sdelphij 76195902Sdelphij for (src = osrc, dst = odst; src < src_end; ) 77195902Sdelphij { 78195902Sdelphij int src_pos = src - osrc; 79195902Sdelphij int dst_pos = dst - odst; 80195902Sdelphij ch = step_char(&src, +1, src_end); 81195902Sdelphij if ((ops & CVT_BS) && ch == '\b' && dst > odst) 82195902Sdelphij { 83195902Sdelphij /* Delete backspace and preceding char. */ 84195902Sdelphij do { 85195902Sdelphij dst--; 86195902Sdelphij } while (dst > odst && 87195902Sdelphij !IS_ASCII_OCTET(*dst) && !IS_UTF8_LEAD(*dst)); 88195902Sdelphij } else if ((ops & CVT_ANSI) && IS_CSI_START(ch)) 89195902Sdelphij { 90195902Sdelphij /* Skip to end of ANSI escape sequence. */ 91195902Sdelphij src++; /* skip the CSI start char */ 92195902Sdelphij while (src < src_end) 93195902Sdelphij if (!is_ansi_middle(*src++)) 94195902Sdelphij break; 95195902Sdelphij } else 96195902Sdelphij { 97195902Sdelphij /* Just copy the char to the destination buffer. */ 98195902Sdelphij if ((ops & CVT_TO_LC) && IS_UPPER(ch)) 99195902Sdelphij ch = TO_LOWER(ch); 100195902Sdelphij put_wchar(&dst, ch); 101240121Sdelphij /* Record the original position of the char. */ 102240121Sdelphij if (chpos != NULL) 103195902Sdelphij chpos[dst_pos] = src_pos; 104195902Sdelphij } 105240121Sdelphij if (dst > edst) 106240121Sdelphij edst = dst; 107195902Sdelphij } 108240121Sdelphij if ((ops & CVT_CRLF) && edst > odst && edst[-1] == '\r') 109240121Sdelphij edst--; 110240121Sdelphij *edst = '\0'; 111195902Sdelphij if (lenp != NULL) 112240121Sdelphij *lenp = edst - odst; 113240121Sdelphij /* FIXME: why was this here? if (chpos != NULL) chpos[dst - odst] = src - osrc; */ 114195902Sdelphij} 115