xref: /netbsd-src/lib/libedit/literal.c (revision da23886665bcc74d461a1457b051c5e7c8da9abe)
1*da238866Schristos /*	$NetBSD: literal.c,v 1.6 2024/12/05 22:21:53 christos Exp $	*/
29abf018dSchristos 
39abf018dSchristos /*-
49abf018dSchristos  * Copyright (c) 2017 The NetBSD Foundation, Inc.
59abf018dSchristos  * All rights reserved.
69abf018dSchristos  *
79abf018dSchristos  * This code is derived from software contributed to The NetBSD Foundation
89abf018dSchristos  * by Christos Zoulas.
99abf018dSchristos  *
109abf018dSchristos  * Redistribution and use in source and binary forms, with or without
119abf018dSchristos  * modification, are permitted provided that the following conditions
129abf018dSchristos  * are met:
139abf018dSchristos  * 1. Redistributions of source code must retain the above copyright
149abf018dSchristos  *    notice, this list of conditions and the following disclaimer.
159abf018dSchristos  * 2. Redistributions in binary form must reproduce the above copyright
169abf018dSchristos  *    notice, this list of conditions and the following disclaimer in the
179abf018dSchristos  *    documentation and/or other materials provided with the distribution.
189abf018dSchristos  *
199abf018dSchristos  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
209abf018dSchristos  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
219abf018dSchristos  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
229abf018dSchristos  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
239abf018dSchristos  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
249abf018dSchristos  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
259abf018dSchristos  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
269abf018dSchristos  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
279abf018dSchristos  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
289abf018dSchristos  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
299abf018dSchristos  * SUCH DAMAGE.
309abf018dSchristos  */
319abf018dSchristos 
329abf018dSchristos #include "config.h"
339abf018dSchristos #if !defined(lint) && !defined(SCCSID)
34*da238866Schristos __RCSID("$NetBSD: literal.c,v 1.6 2024/12/05 22:21:53 christos Exp $");
359abf018dSchristos #endif /* not lint && not SCCSID */
369abf018dSchristos 
379abf018dSchristos /*
389abf018dSchristos  * literal.c: Literal sequences handling.
399abf018dSchristos  */
409abf018dSchristos #include <assert.h>
419abf018dSchristos #include <stdio.h>
429abf018dSchristos #include <stdlib.h>
439abf018dSchristos #include <string.h>
449abf018dSchristos #include "el.h"
459abf018dSchristos 
469abf018dSchristos libedit_private void
479abf018dSchristos literal_init(EditLine *el)
489abf018dSchristos {
499abf018dSchristos 	el_literal_t *l = &el->el_literal;
50e3112e6cSkre 
519abf018dSchristos 	memset(l, 0, sizeof(*l));
529abf018dSchristos }
539abf018dSchristos 
549abf018dSchristos libedit_private void
559abf018dSchristos literal_end(EditLine *el)
569abf018dSchristos {
579abf018dSchristos 	literal_clear(el);
589abf018dSchristos }
599abf018dSchristos 
609abf018dSchristos libedit_private void
619abf018dSchristos literal_clear(EditLine *el)
629abf018dSchristos {
639abf018dSchristos 	el_literal_t *l = &el->el_literal;
649abf018dSchristos 	size_t i;
65e3112e6cSkre 
66e3112e6cSkre 	if (l->l_len == 0)
67e3112e6cSkre 		return;
68e3112e6cSkre 
692977f431Skre 	for (i = 0; i < l->l_idx; i++)
709abf018dSchristos 		el_free(l->l_buf[i]);
71e3112e6cSkre 	el_free(l->l_buf);
72e3112e6cSkre 	l->l_buf = NULL;
739abf018dSchristos 	l->l_len = 0;
749abf018dSchristos 	l->l_idx = 0;
759abf018dSchristos }
769abf018dSchristos 
779abf018dSchristos libedit_private wint_t
78e3112e6cSkre literal_add(EditLine *el, const wchar_t *buf, const wchar_t *end, int *wp)
799abf018dSchristos {
809abf018dSchristos 	el_literal_t *l = &el->el_literal;
819abf018dSchristos 	size_t i, len;
82e3112e6cSkre 	ssize_t w, n;
839abf018dSchristos 	char *b;
849abf018dSchristos 
85e3112e6cSkre 	w = wcwidth(end[1]);	/* column width of the visible char */
86e3112e6cSkre 	*wp = (int)w;
87e3112e6cSkre 
88*da238866Schristos 	if (w < 0)		/* non-printable characters are negative */
89e3112e6cSkre 		return 0;
90e3112e6cSkre 
919abf018dSchristos 	len = (size_t)(end - buf);
92e3112e6cSkre 	for (w = 0, i = 0; i < len; i++)
93e3112e6cSkre 		w += ct_enc_width(buf[i]);
94e3112e6cSkre 	w += ct_enc_width(end[1]);
95e3112e6cSkre 
96e3112e6cSkre 	b = el_malloc((size_t)(w + 1));
979abf018dSchristos 	if (b == NULL)
989abf018dSchristos 		return 0;
99e3112e6cSkre 
100755b7030Schristos 	for (n = 0, i = 0; i < len; i++)
101113f06a3Schristos 		n += ct_encode_char(b + n, (size_t)(w - n), buf[i]);
102113f06a3Schristos 	n += ct_encode_char(b + n, (size_t)(w - n), end[1]);
103e3112e6cSkre 	b[n] = '\0';
104e3112e6cSkre 
105e3112e6cSkre 	/*
106e3112e6cSkre 	 * Then save this literal string in the list of such strings,
107e3112e6cSkre 	 * and return a "magic character" to put into the terminal buffer.
108e3112e6cSkre 	 * When that magic char is 'printed' the saved string (which includes
109e3112e6cSkre 	 * the char that belongs in that position) gets sent instead.
110e3112e6cSkre 	 */
1119abf018dSchristos 	if (l->l_idx == l->l_len) {
112e3112e6cSkre 		char **bp;
113e3112e6cSkre 
114e3112e6cSkre 		l->l_len += 4;
115e3112e6cSkre 		bp = el_realloc(l->l_buf, sizeof(*l->l_buf) * l->l_len);
1169abf018dSchristos 		if (bp == NULL) {
1179abf018dSchristos 			free(b);
118e3112e6cSkre 			l->l_len -= 4;
1199abf018dSchristos 			return 0;
1209abf018dSchristos 		}
1219abf018dSchristos 		l->l_buf = bp;
1229abf018dSchristos 	}
1239abf018dSchristos 	l->l_buf[l->l_idx++] = b;
1249abf018dSchristos 	return EL_LITERAL | (wint_t)(l->l_idx - 1);
1259abf018dSchristos }
1269abf018dSchristos 
1279abf018dSchristos libedit_private const char *
1289abf018dSchristos literal_get(EditLine *el, wint_t idx)
1299abf018dSchristos {
1309abf018dSchristos 	el_literal_t *l = &el->el_literal;
131e3112e6cSkre 
1329abf018dSchristos 	assert(idx & EL_LITERAL);
1339abf018dSchristos 	idx &= ~EL_LITERAL;
1349abf018dSchristos 	assert(l->l_idx > (size_t)idx);
1359abf018dSchristos 	return l->l_buf[idx];
1369abf018dSchristos }
137