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