2 * Copyright 1998-2002 by Albert Cahalan; all rights resered.
3 * This file may be used subject to the terms and conditions of the
4 * GNU Library General Public License Version 2, or any later version
5 * at your option, as published by the Free Software Foundation.
6 * This program is distributed in the hope that it will be useful,
7 * but WITHOUT ANY WARRANTY; without even the implied warranty of
8 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
9 * GNU Library General Public License for more details.
12 #include <sys/types.h>
18 #if (__GNU_LIBRARY__ >= 6)
21 # include <stdlib.h> /* MB_CUR_MAX */
23 # include <langinfo.h>
26 #if (__GNU_LIBRARY__ >= 6)
27 static int escape_str_utf8(char *restrict dst, const char *restrict src, int bufsize, int *maxcells){
32 memset(&s, 0, sizeof (s));
38 if(my_cells >= *maxcells || my_bytes+1 >= bufsize)
41 if (!(len = mbrtowc (&wc, src, MB_CUR_MAX, &s)))
42 /* 'str' contains \0 */
46 /* invalid multibyte sequence -- zeroize state */
47 memset (&s, 0, sizeof (s));
55 *(dst++) = isprint(*src) ? *src : '?';
60 } else if (!iswprint(wc)) {
61 /* multibyte - no printable */
68 /* multibyte - printable */
69 int wlen = wcwidth(wc);
72 // invisible multibyte -- we don't ignore it, because some terminal
73 // interpret it wrong and more safe is replace it with '?'
79 // multibyte - printable
81 if (my_cells+wlen > *maxcells || my_bytes+1+len >= bufsize) break;
82 // 0x9b is control byte for some terminals
83 if (memchr(src, 0x9B, len)) {
91 memcpy(dst, src, len);
99 //fprintf(stdout, "cells: %d\n", my_cells);
103 // fprintf(stderr, "maxcells: %d, my_cells; %d\n", *maxcells, my_cells);
105 *maxcells -= my_cells;
106 return my_bytes; // bytes of text, excluding the NUL
109 #endif /* __GNU_LIBRARY__ */
111 /* sanitize a string via one-way mangle */
112 int escape_str(char *restrict dst, const char *restrict src, int bufsize, int *maxcells){
117 "Z-------------------------------"
118 "********************************"
119 "********************************"
120 "*******************************-"
121 "--------------------------------"
122 "********************************"
123 "********************************"
124 "********************************";
126 #if (__GNU_LIBRARY__ >= 6)
127 static int utf_init=0;
130 /* first call -- check if UTF stuff is usable */
131 char *enc = nl_langinfo(CODESET);
132 utf_init = enc && strcasecmp(enc, "UTF-8")==0 ? 1 : -1;
136 return escape_str_utf8(dst, src, bufsize, maxcells);
139 if(bufsize > *maxcells+1) bufsize=*maxcells+1; // FIXME: assumes 8-bit locale
142 if(my_cells >= *maxcells || my_bytes+1 >= bufsize)
144 c = (unsigned char) *(src++);
146 if(codes[c]=='-') c='?';
153 *maxcells -= my_cells;
154 return my_bytes; // bytes of text, excluding the NUL
157 /////////////////////////////////////////////////
159 // escape an argv or environment string array
161 // bytes arg means sizeof(buf)
162 int escape_strlist(char *restrict dst, const char *restrict const *restrict src, size_t bytes, int *cells){
166 i += escape_str(dst+i, *src, bytes-i, cells);
167 if(bytes-i < 3) break; // need room for space, a character, and the NUL
169 if(!*src) break; // need something to print
170 if (*cells<=1) break; // need room for printed size of text
174 return i; // bytes, excluding the NUL
177 ///////////////////////////////////////////////////
179 int escape_command(char *restrict const outbuf, const proc_t *restrict const pp, int bytes, int *cells, unsigned flags){
183 if(flags & ESC_ARGS){
184 const char **lc = (const char**)pp->cmdline;
185 if(lc && *lc) return escape_strlist(outbuf, lc, bytes, cells);
187 if(flags & ESC_BRACKETS){
190 if(flags & ESC_DEFUNCT){
191 if(pp->state=='Z') overhead += 10; // chars in " <defunct>"
192 else flags &= ~ESC_DEFUNCT;
194 if(overhead + 1 >= *cells){ // if no room for even one byte of the command name
195 // you'd damn well better have _some_ space
196 // outbuf[0] = '-'; // Oct23
200 if(flags & ESC_BRACKETS){
204 end += escape_str(outbuf+end, pp->cmd, bytes-overhead, cells);
206 // Hmmm, do we want "[foo] <defunct>" or "[foo <defunct>]"?
207 if(flags & ESC_BRACKETS){
210 if(flags & ESC_DEFUNCT){
211 memcpy(outbuf+end, " <defunct>", 10);
215 return end; // bytes, not including the NUL