/[LeafOK_CVS]/lbbs/src/str_process.c
ViewVC logotype

Contents of /lbbs/src/str_process.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.24 - (show annotations)
Tue Nov 4 14:58:56 2025 UTC (4 months, 1 week ago) by sysadm
Branch: MAIN
Changes since 1.23: +1 -1 lines
Content type: text/x-csrc
Refine file header information comments

1 /* SPDX-License-Identifier: GPL-3.0-or-later */
2 /*
3 * str_process
4 * - common string processing features with UTF-8 support
5 *
6 * Copyright (C) 2004-2025 Leaflet <leaflet@leafok.com>
7 */
8
9 #include "common.h"
10 #include "log.h"
11 #include "str_process.h"
12 #include <ctype.h>
13 #include <stdio.h>
14 #include <string.h>
15
16 int str_length(const char *str, int skip_ctrl_seq)
17 {
18 int i;
19 char c;
20 int ret = 0;
21
22 for (i = 0; str[i] != '\0'; i++)
23 {
24 c = str[i];
25
26 if (c == '\r' || c == '\7') // skip
27 {
28 continue;
29 }
30
31 if (skip_ctrl_seq && c == '\033' && str[i + 1] == '[') // Skip control sequence
32 {
33 for (i = i + 2; isdigit(str[i]) || str[i] == ';' || str[i] == '?'; i++)
34 ;
35
36 if (str[i] == 'm') // valid
37 {
38 // skip
39 }
40 else if (isalpha(str[i]))
41 {
42 // unsupported ANSI CSI command
43 }
44 else
45 {
46 i--;
47 }
48
49 continue;
50 }
51
52 // Process UTF-8 Chinese characters
53 if (c & 0x80) // head of multi-byte character
54 {
55 c = (c & 0x70) << 1;
56 while (c & 0x80)
57 {
58 i++;
59 c = (c & 0x7f) << 1;
60 }
61
62 ret += 2;
63 }
64 else
65 {
66 ret++;
67 }
68 }
69
70 return ret;
71 }
72
73 int split_line(const char *buffer, int max_display_len, int *p_eol, int *p_display_len, int skip_ctrl_seq)
74 {
75 int i;
76 *p_eol = 0;
77 *p_display_len = 0;
78 char c;
79
80 for (i = 0; buffer[i] != '\0'; i++)
81 {
82 c = buffer[i];
83
84 if (c == '\r' || c == '\7') // skip
85 {
86 continue;
87 }
88
89 if (skip_ctrl_seq && c == '\033' && buffer[i + 1] == '[') // Skip control sequence
90 {
91 i += 2;
92 while (buffer[i] != '\0' && buffer[i] != 'm')
93 {
94 i++;
95 }
96 continue;
97 }
98
99 if (c & 0x80) // head of multi-byte character
100 {
101 if (*p_display_len + 2 > max_display_len)
102 {
103 break;
104 }
105
106 c = (c & 0x70) << 1;
107 while (c & 0x80)
108 {
109 i++;
110 c = (c & 0x7f) << 1;
111 }
112
113 (*p_display_len) += 2;
114 }
115 else
116 {
117 if (*p_display_len + 1 > max_display_len)
118 {
119 break;
120 }
121 (*p_display_len)++;
122
123 // \n is regarded as 1 character wide in terminal editor, which is different from Web version
124 if (c == '\n')
125 {
126 i++;
127 *p_eol = 1;
128 break;
129 }
130 }
131 }
132
133 return i;
134 }
135
136 long split_data_lines(const char *p_buf, int max_display_len, long *p_line_offsets, long line_offsets_count,
137 int skip_ctrl_seq, int *p_line_widths)
138 {
139 int line_cnt = 0;
140 int len;
141 int end_of_line = 0;
142 int display_len = 0;
143
144 p_line_offsets[line_cnt] = 0L;
145
146 do
147 {
148 len = split_line(p_buf, max_display_len, &end_of_line, &display_len, skip_ctrl_seq);
149
150 if (p_line_widths)
151 {
152 p_line_widths[line_cnt] = display_len;
153 }
154
155 // Exceed max_line_cnt
156 if (line_cnt + 1 >= line_offsets_count)
157 {
158 // log_error("Line count %d reaches limit %d\n", line_cnt + 1, line_offsets_count);
159 return line_cnt;
160 }
161
162 p_line_offsets[line_cnt + 1] = p_line_offsets[line_cnt] + len;
163 line_cnt++;
164 p_buf += len;
165 } while (p_buf[0] != '\0');
166
167 return line_cnt;
168 }
169
170 int str_filter(char *buffer, int skip_ctrl_seq)
171 {
172 int i;
173 int j;
174
175 for (i = 0, j = 0; buffer[i] != '\0'; i++)
176 {
177 if (buffer[i] == '\r' || buffer[i] == '\7') // skip
178 {
179 continue;
180 }
181
182 if (skip_ctrl_seq && buffer[i] == '\033' && buffer[i + 1] == '[') // Skip control sequence
183 {
184 i += 2;
185 while (buffer[i] != '\0' && buffer[i] != 'm')
186 {
187 i++;
188 }
189 continue;
190 }
191
192 buffer[j] = buffer[i];
193 j++;
194 }
195
196 buffer[j] = '\0';
197
198 return j;
199 }

webmaster@leafok.com
ViewVC Help
Powered by ViewVC 1.3.0-beta1