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