cvt.c revision 1.4 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