150276Speter/**************************************************************************** 2184989Srafan * Copyright (c) 1998-2006,2008 Free Software Foundation, Inc. * 350276Speter * * 450276Speter * Permission is hereby granted, free of charge, to any person obtaining a * 550276Speter * copy of this software and associated documentation files (the * 650276Speter * "Software"), to deal in the Software without restriction, including * 750276Speter * without limitation the rights to use, copy, modify, merge, publish, * 850276Speter * distribute, distribute with modifications, sublicense, and/or sell * 950276Speter * copies of the Software, and to permit persons to whom the Software is * 1050276Speter * furnished to do so, subject to the following conditions: * 1150276Speter * * 1250276Speter * The above copyright notice and this permission notice shall be included * 1350276Speter * in all copies or substantial portions of the Software. * 1450276Speter * * 1550276Speter * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS * 1650276Speter * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF * 1750276Speter * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. * 1850276Speter * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, * 1950276Speter * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR * 2050276Speter * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR * 2150276Speter * THE USE OR OTHER DEALINGS IN THE SOFTWARE. * 2250276Speter * * 2350276Speter * Except as contained in this notice, the name(s) of the above copyright * 2450276Speter * holders shall not be used in advertising or otherwise to promote the * 2550276Speter * sale, use or other dealings in this Software without prior written * 2650276Speter * authorization. * 2750276Speter ****************************************************************************/ 2850276Speter 2950276Speter/**************************************************************************** 3050276Speter * Author: Zeyd M. Ben-Halim <zmbenhal@netcom.com> 1992,1995 * 3150276Speter * and: Eric S. Raymond <esr@snark.thyrsus.com> * 32166124Srafan * and: Thomas E. Dickey 1996-on * 3350276Speter ****************************************************************************/ 3450276Speter 3550276Speter/* 3650276Speter * captoinfo.c --- conversion between termcap and terminfo formats 3750276Speter * 3850276Speter * The captoinfo() code was swiped from Ross Ridge's mytinfo package, 3950276Speter * adapted to fit ncurses by Eric S. Raymond <esr@snark.thyrsus.com>. 4050276Speter * 4150276Speter * There is just one entry point: 4250276Speter * 43166124Srafan * char *_nc_captoinfo(n, s, parameterized) 4450276Speter * 4550276Speter * Convert value s for termcap string capability named n into terminfo 4650276Speter * format. 4750276Speter * 4850276Speter * This code recognizes all the standard 4.4BSD %-escapes: 4950276Speter * 5050276Speter * %% output `%' 5150276Speter * %d output value as in printf %d 5250276Speter * %2 output value as in printf %2d 5350276Speter * %3 output value as in printf %3d 5450276Speter * %. output value as in printf %c 5550276Speter * %+x add x to value, then do %. 5650276Speter * %>xy if value > x then add y, no output 5750276Speter * %r reverse order of two parameters, no output 5850276Speter * %i increment by one, no output 5950276Speter * %n exclusive-or all parameters with 0140 (Datamedia 2500) 6050276Speter * %B BCD (16*(value/10)) + (value%10), no output 6150276Speter * %D Reverse coding (value - 2*(value%16)), no output (Delta Data). 6250276Speter * 6350276Speter * Also, %02 and %03 are accepted as synonyms for %2 and %3. 6450276Speter * 6550276Speter * Besides all the standard termcap escapes, this translator understands 6650276Speter * the following extended escapes: 6750276Speter * 6850276Speter * used by GNU Emacs termcap libraries 6950276Speter * %a[+*-/=][cp]x GNU arithmetic. 7050276Speter * %m xor the first two parameters by 0177 7150276Speter * %b backup to previous parameter 7250276Speter * %f skip this parameter 7350276Speter * 7450276Speter * used by the University of Waterloo (MFCF) termcap libraries 7550276Speter * %-x subtract parameter FROM char x and output it as a char 7650276Speter * %ax add the character x to parameter 7750276Speter * 7850276Speter * If #define WATERLOO is on, also enable these translations: 7950276Speter * 8050276Speter * %sx subtract parameter FROM the character x 8150276Speter * 8250276Speter * By default, this Waterloo translations are not compiled in, because 8350276Speter * the Waterloo %s conflicts with the way terminfo uses %s in strings for 8450276Speter * function programming. 8550276Speter * 8650276Speter * Note the two definitions of %a: the GNU definition is translated if the 8750276Speter * characters after the 'a' are valid for it, otherwise the UW definition 8850276Speter * is translated. 8950276Speter */ 9050276Speter 9150276Speter#include <curses.priv.h> 9250276Speter 9350276Speter#include <ctype.h> 9450276Speter#include <tic.h> 9550276Speter 96184989SrafanMODULE_ID("$Id: captoinfo.c,v 1.52 2008/08/16 19:24:51 tom Exp $") 9750276Speter 9850276Speter#define MAX_PUSHED 16 /* max # args we can push onto the stack */ 9950276Speter 10050276Speterstatic int stack[MAX_PUSHED]; /* the stack */ 10150276Speterstatic int stackptr; /* the next empty place on the stack */ 10250276Speterstatic int onstack; /* the top of stack */ 10350276Speterstatic int seenm; /* seen a %m */ 10450276Speterstatic int seenn; /* seen a %n */ 10550276Speterstatic int seenr; /* seen a %r */ 10650276Speterstatic int param; /* current parameter */ 10750276Speterstatic char *dp; /* pointer to end of the converted string */ 10850276Speter 10962449Speterstatic char *my_string; 11050276Speterstatic size_t my_length; 11150276Speter 11262449Speterstatic char * 11362449Speterinit_string(void) 11450276Speter/* initialize 'my_string', 'my_length' */ 11550276Speter{ 11662449Speter if (my_string == 0) 11762449Speter my_string = typeMalloc(char, my_length = 256); 11862449Speter if (my_string == 0) 119166124Srafan _nc_err_abort(MSG_NO_MEMORY); 12050276Speter 12162449Speter *my_string = '\0'; 12262449Speter return my_string; 12350276Speter} 12450276Speter 12562449Speterstatic char * 12662449Spetersave_string(char *d, const char *const s) 12750276Speter{ 12862449Speter size_t have = (d - my_string); 12962449Speter size_t need = have + strlen(s) + 2; 13062449Speter if (need > my_length) { 13162449Speter my_string = (char *) realloc(my_string, my_length = (need + need)); 13262449Speter if (my_string == 0) 133166124Srafan _nc_err_abort(MSG_NO_MEMORY); 13462449Speter d = my_string + have; 13562449Speter } 13662449Speter (void) strcpy(d, s); 13762449Speter return d + strlen(d); 13850276Speter} 13950276Speter 140166124Srafanstatic NCURSES_INLINE char * 141166124Srafansave_char(char *s, int c) 14250276Speter{ 14362449Speter static char temp[2]; 144166124Srafan temp[0] = (char) c; 14562449Speter return save_string(s, temp); 14650276Speter} 14750276Speter 14862449Speterstatic void 14962449Speterpush(void) 15050276Speter/* push onstack on to the stack */ 15150276Speter{ 152184989Srafan if (stackptr >= MAX_PUSHED) 15350276Speter _nc_warning("string too complex to convert"); 15450276Speter else 15550276Speter stack[stackptr++] = onstack; 15650276Speter} 15750276Speter 15862449Speterstatic void 15962449Speterpop(void) 16050276Speter/* pop the top of the stack into onstack */ 16150276Speter{ 16250276Speter if (stackptr == 0) { 16350276Speter if (onstack == 0) 16450276Speter _nc_warning("I'm confused"); 16550276Speter else 16650276Speter onstack = 0; 16762449Speter } else 16850276Speter onstack = stack[--stackptr]; 16950276Speter param++; 17050276Speter} 17150276Speter 17262449Speterstatic int 17362449Spetercvtchar(register const char *sp) 17450276Speter/* convert a character to a terminfo push */ 17550276Speter{ 17650276Speter unsigned char c = 0; 17750276Speter int len; 17850276Speter 17962449Speter switch (*sp) { 18050276Speter case '\\': 18162449Speter switch (*++sp) { 18250276Speter case '\'': 18350276Speter case '$': 18450276Speter case '\\': 18550276Speter case '%': 186184989Srafan c = (unsigned char) (*sp); 18750276Speter len = 2; 18850276Speter break; 18950276Speter case '\0': 19050276Speter c = '\\'; 19150276Speter len = 1; 19250276Speter break; 19350276Speter case '0': 19450276Speter case '1': 19550276Speter case '2': 19650276Speter case '3': 19750276Speter len = 1; 19897049Speter while (isdigit(UChar(*sp))) { 19950276Speter c = 8 * c + (*sp++ - '0'); 20050276Speter len++; 20150276Speter } 20250276Speter break; 20350276Speter default: 204184989Srafan c = (unsigned char) (*sp); 20550276Speter len = 2; 20650276Speter break; 20750276Speter } 20850276Speter break; 20950276Speter case '^': 21050276Speter c = (*++sp & 0x1f); 21150276Speter len = 2; 21250276Speter break; 21350276Speter default: 214184989Srafan c = (unsigned char) (*sp); 21550276Speter len = 1; 21650276Speter } 21750276Speter if (isgraph(c) && c != ',' && c != '\'' && c != '\\' && c != ':') { 21862449Speter dp = save_string(dp, "%\'"); 21962449Speter dp = save_char(dp, c); 22062449Speter dp = save_char(dp, '\''); 22150276Speter } else { 22262449Speter dp = save_string(dp, "%{"); 22350276Speter if (c > 99) 22462449Speter dp = save_char(dp, c / 100 + '0'); 22550276Speter if (c > 9) 22662449Speter dp = save_char(dp, ((int) (c / 10)) % 10 + '0'); 22762449Speter dp = save_char(dp, c % 10 + '0'); 22862449Speter dp = save_char(dp, '}'); 22950276Speter } 23050276Speter return len; 23150276Speter} 23250276Speter 23362449Speterstatic void 23462449Spetergetparm(int parm, int n) 23550276Speter/* push n copies of param on the terminfo stack if not already there */ 23650276Speter{ 23762449Speter if (seenr) { 23862449Speter if (parm == 1) 23962449Speter parm = 2; 24062449Speter else if (parm == 2) 24162449Speter parm = 1; 24262449Speter } 24362449Speter if (onstack == parm) { 24462449Speter if (n > 1) { 24562449Speter _nc_warning("string may not be optimal"); 24662449Speter dp = save_string(dp, "%Pa"); 24762449Speter while (n--) { 24862449Speter dp = save_string(dp, "%ga"); 24962449Speter } 25050276Speter } 25162449Speter return; 25262449Speter } 25362449Speter if (onstack != 0) 25462449Speter push(); 25550276Speter 25662449Speter onstack = parm; 25750276Speter 25862449Speter while (n--) { 25962449Speter dp = save_string(dp, "%p"); 26062449Speter dp = save_char(dp, '0' + parm); 26162449Speter } 26250276Speter 26362449Speter if (seenn && parm < 3) { 26462449Speter dp = save_string(dp, "%{96}%^"); 26562449Speter } 26650276Speter 26762449Speter if (seenm && parm < 3) { 26862449Speter dp = save_string(dp, "%{127}%^"); 26962449Speter } 27050276Speter} 27150276Speter 27276726Speter/* 27376726Speter * Convert a termcap string to terminfo format. 27476726Speter * 'cap' is the relevant terminfo capability index. 27576726Speter * 's' is the string value of the capability. 276166124Srafan * 'parameterized' tells what type of translations to do: 27776726Speter * % translations if 1 27876726Speter * pad translations if >=0 27976726Speter */ 280166124SrafanNCURSES_EXPORT(char *) 281166124Srafan_nc_captoinfo(const char *cap, const char *s, int const parameterized) 28250276Speter{ 28350276Speter const char *capstart; 28450276Speter 28550276Speter stackptr = 0; 28650276Speter onstack = 0; 28750276Speter seenm = 0; 28850276Speter seenn = 0; 28950276Speter seenr = 0; 29050276Speter param = 1; 29150276Speter 29262449Speter dp = init_string(); 29350276Speter 29450276Speter /* skip the initial padding (if we haven't been told not to) */ 29550276Speter capstart = 0; 29650276Speter if (s == 0) 29750276Speter s = ""; 298166124Srafan if (parameterized >= 0 && isdigit(UChar(*s))) 29962449Speter for (capstart = s;; s++) 30097049Speter if (!(isdigit(UChar(*s)) || *s == '*' || *s == '.')) 30150276Speter break; 30250276Speter 30362449Speter while (*s != '\0') { 30462449Speter switch (*s) { 30550276Speter case '%': 30650276Speter s++; 307166124Srafan if (parameterized < 1) { 30862449Speter dp = save_char(dp, '%'); 30950276Speter break; 31050276Speter } 31162449Speter switch (*s++) { 31262449Speter case '%': 31362449Speter dp = save_char(dp, '%'); 31462449Speter break; 31550276Speter case 'r': 31650276Speter if (seenr++ == 1) { 31750276Speter _nc_warning("saw %%r twice in %s", cap); 31850276Speter } 31950276Speter break; 32050276Speter case 'm': 32150276Speter if (seenm++ == 1) { 32250276Speter _nc_warning("saw %%m twice in %s", cap); 32350276Speter } 32450276Speter break; 32550276Speter case 'n': 32650276Speter if (seenn++ == 1) { 32750276Speter _nc_warning("saw %%n twice in %s", cap); 32850276Speter } 32950276Speter break; 33062449Speter case 'i': 33162449Speter dp = save_string(dp, "%i"); 33262449Speter break; 33350276Speter case '6': 33450276Speter case 'B': 33562449Speter getparm(param, 1); 33662449Speter dp = save_string(dp, "%{10}%/%{16}%*"); 33762449Speter getparm(param, 1); 33862449Speter dp = save_string(dp, "%{10}%m%+"); 33950276Speter break; 34050276Speter case '8': 34150276Speter case 'D': 34250276Speter getparm(param, 2); 34362449Speter dp = save_string(dp, "%{2}%*%-"); 34450276Speter break; 34550276Speter case '>': 34650276Speter getparm(param, 2); 34750276Speter /* %?%{x}%>%t%{y}%+%; */ 34862449Speter dp = save_string(dp, "%?"); 34950276Speter s += cvtchar(s); 35062449Speter dp = save_string(dp, "%>%t"); 35150276Speter s += cvtchar(s); 35262449Speter dp = save_string(dp, "%+%;"); 35350276Speter break; 35450276Speter case 'a': 35550276Speter if ((*s == '=' || *s == '+' || *s == '-' 35676726Speter || *s == '*' || *s == '/') 35750276Speter && (s[1] == 'p' || s[1] == 'c') 35850276Speter && s[2] != '\0') { 35950276Speter int l; 36050276Speter l = 2; 36150276Speter if (*s != '=') 36250276Speter getparm(param, 1); 36350276Speter if (s[1] == 'p') { 36450276Speter getparm(param + s[2] - '@', 1); 36550276Speter if (param != onstack) { 36650276Speter pop(); 36750276Speter param--; 36850276Speter } 36950276Speter l++; 37050276Speter } else 37150276Speter l += cvtchar(s + 2); 37262449Speter switch (*s) { 37350276Speter case '+': 37462449Speter dp = save_string(dp, "%+"); 37550276Speter break; 37650276Speter case '-': 37762449Speter dp = save_string(dp, "%-"); 37850276Speter break; 37950276Speter case '*': 38062449Speter dp = save_string(dp, "%*"); 38150276Speter break; 38250276Speter case '/': 38362449Speter dp = save_string(dp, "%/"); 38450276Speter break; 38550276Speter case '=': 38650276Speter if (seenr) { 38750276Speter if (param == 1) 38850276Speter onstack = 2; 38950276Speter else if (param == 2) 39050276Speter onstack = 1; 39150276Speter else 39250276Speter onstack = param; 39362449Speter } else 39450276Speter onstack = param; 39550276Speter break; 39650276Speter } 39750276Speter s += l; 39850276Speter break; 39950276Speter } 40050276Speter getparm(param, 1); 40150276Speter s += cvtchar(s); 40262449Speter dp = save_string(dp, "%+"); 40350276Speter break; 40450276Speter case '+': 40550276Speter getparm(param, 1); 40650276Speter s += cvtchar(s); 40762449Speter dp = save_string(dp, "%+%c"); 40850276Speter pop(); 40950276Speter break; 41050276Speter case 's': 41150276Speter#ifdef WATERLOO 41250276Speter s += cvtchar(s); 41350276Speter getparm(param, 1); 41462449Speter dp = save_string(dp, "%-"); 41550276Speter#else 41650276Speter getparm(param, 1); 41762449Speter dp = save_string(dp, "%s"); 41850276Speter pop(); 41950276Speter#endif /* WATERLOO */ 42050276Speter break; 42150276Speter case '-': 42250276Speter s += cvtchar(s); 42350276Speter getparm(param, 1); 42462449Speter dp = save_string(dp, "%-%c"); 42550276Speter pop(); 42650276Speter break; 42750276Speter case '.': 42850276Speter getparm(param, 1); 42962449Speter dp = save_string(dp, "%c"); 43050276Speter pop(); 43150276Speter break; 43262449Speter case '0': /* not clear any of the historical termcaps did this */ 43350276Speter if (*s == '3') 43450276Speter goto see03; 43550276Speter else if (*s != '2') 43650276Speter goto invalid; 43750276Speter /* FALLTHRU */ 43850276Speter case '2': 43950276Speter getparm(param, 1); 44062449Speter dp = save_string(dp, "%2d"); 44150276Speter pop(); 44250276Speter break; 44362449Speter case '3': 44462449Speter see03: 44550276Speter getparm(param, 1); 44662449Speter dp = save_string(dp, "%3d"); 44750276Speter pop(); 44850276Speter break; 44950276Speter case 'd': 45050276Speter getparm(param, 1); 45162449Speter dp = save_string(dp, "%d"); 45250276Speter pop(); 45350276Speter break; 45450276Speter case 'f': 45550276Speter param++; 45650276Speter break; 45750276Speter case 'b': 45850276Speter param--; 45950276Speter break; 46050276Speter case '\\': 46162449Speter dp = save_string(dp, "%\\"); 46250276Speter break; 46362449Speter default: 46462449Speter invalid: 46562449Speter dp = save_char(dp, '%'); 46650276Speter s--; 46762449Speter _nc_warning("unknown %% code %s (%#x) in %s", 468166124Srafan unctrl((chtype) *s), UChar(*s), cap); 46950276Speter break; 47050276Speter } 47150276Speter break; 47250276Speter#ifdef REVISIBILIZE 47350276Speter case '\\': 47462449Speter dp = save_char(dp, *s++); 47562449Speter dp = save_char(dp, *s++); 47662449Speter break; 47750276Speter case '\n': 47862449Speter dp = save_string(dp, "\\n"); 47962449Speter s++; 48062449Speter break; 48150276Speter case '\t': 48262449Speter dp = save_string(dp, "\\t"); 48362449Speter s++; 48462449Speter break; 48550276Speter case '\r': 48662449Speter dp = save_string(dp, "\\r"); 48762449Speter s++; 48862449Speter break; 48950276Speter case '\200': 49062449Speter dp = save_string(dp, "\\0"); 49162449Speter s++; 49262449Speter break; 49350276Speter case '\f': 49462449Speter dp = save_string(dp, "\\f"); 49562449Speter s++; 49662449Speter break; 49750276Speter case '\b': 49862449Speter dp = save_string(dp, "\\b"); 49962449Speter s++; 50062449Speter break; 50150276Speter case ' ': 50262449Speter dp = save_string(dp, "\\s"); 50362449Speter s++; 50462449Speter break; 50550276Speter case '^': 50662449Speter dp = save_string(dp, "\\^"); 50762449Speter s++; 50862449Speter break; 50950276Speter case ':': 51062449Speter dp = save_string(dp, "\\:"); 51162449Speter s++; 51262449Speter break; 51350276Speter case ',': 51462449Speter dp = save_string(dp, "\\,"); 51562449Speter s++; 51662449Speter break; 51750276Speter default: 51850276Speter if (*s == '\033') { 51962449Speter dp = save_string(dp, "\\E"); 52050276Speter s++; 52150276Speter } else if (*s > 0 && *s < 32) { 52262449Speter dp = save_char(dp, '^'); 52362449Speter dp = save_char(dp, *s + '@'); 52450276Speter s++; 52550276Speter } else if (*s <= 0 || *s >= 127) { 52662449Speter dp = save_char(dp, '\\'); 52762449Speter dp = save_char(dp, ((*s & 0300) >> 6) + '0'); 52862449Speter dp = save_char(dp, ((*s & 0070) >> 3) + '0'); 52962449Speter dp = save_char(dp, (*s & 0007) + '0'); 53050276Speter s++; 53150276Speter } else 53262449Speter dp = save_char(dp, *s++); 53350276Speter break; 53450276Speter#else 53550276Speter default: 53662449Speter dp = save_char(dp, *s++); 53750276Speter break; 53850276Speter#endif 53950276Speter } 54050276Speter } 54150276Speter 54250276Speter /* 54350276Speter * Now, if we stripped off some leading padding, add it at the end 54450276Speter * of the string as mandatory padding. 54550276Speter */ 54662449Speter if (capstart) { 54762449Speter dp = save_string(dp, "$<"); 54862449Speter for (s = capstart;; s++) 54997049Speter if (isdigit(UChar(*s)) || *s == '*' || *s == '.') 55062449Speter dp = save_char(dp, *s); 55150276Speter else 55250276Speter break; 55362449Speter dp = save_string(dp, "/>"); 55450276Speter } 55550276Speter 55662449Speter (void) save_char(dp, '\0'); 55762449Speter return (my_string); 55850276Speter} 55950276Speter 56050276Speter/* 56162449Speter * Check for an expression that corresponds to "%B" (BCD): 56262449Speter * (parameter / 10) * 16 + (parameter % 10) 56362449Speter */ 56462449Speterstatic int 56562449Speterbcd_expression(const char *str) 56662449Speter{ 56762449Speter /* leave this non-const for HPUX */ 56862449Speter static char fmt[] = "%%p%c%%{10}%%/%%{16}%%*%%p%c%%{10}%%m%%+"; 56962449Speter int len = 0; 57062449Speter char ch1, ch2; 57162449Speter 57262449Speter if (sscanf(str, fmt, &ch1, &ch2) == 2 57397049Speter && isdigit(UChar(ch1)) 57497049Speter && isdigit(UChar(ch2)) 57562449Speter && (ch1 == ch2)) { 57662449Speter len = 28; 57762449Speter#ifndef NDEBUG 57862449Speter { 57962449Speter char buffer[80]; 58062449Speter int tst; 58162449Speter sprintf(buffer, fmt, ch1, ch2); 58262449Speter tst = strlen(buffer) - 1; 58362449Speter assert(len == tst); 58462449Speter } 58562449Speter#endif 58662449Speter } 58762449Speter return len; 58862449Speter} 58962449Speter 59062449Speterstatic char * 59162449Spetersave_tc_char(char *bufptr, int c1) 59262449Speter{ 59362449Speter char temp[80]; 59462449Speter 59562449Speter if (is7bits(c1) && isprint(c1)) { 59662449Speter if (c1 == ':' || c1 == '\\') 59762449Speter bufptr = save_char(bufptr, '\\'); 59862449Speter bufptr = save_char(bufptr, c1); 59962449Speter } else { 60062449Speter if (c1 == (c1 & 0x1f)) /* iscntrl() returns T on 255 */ 60176726Speter (void) strcpy(temp, unctrl((chtype) c1)); 60262449Speter else 60362449Speter (void) sprintf(temp, "\\%03o", c1); 60462449Speter bufptr = save_string(bufptr, temp); 60562449Speter } 60662449Speter return bufptr; 60762449Speter} 60862449Speter 60962449Speterstatic char * 61062449Spetersave_tc_inequality(char *bufptr, int c1, int c2) 61162449Speter{ 61262449Speter bufptr = save_string(bufptr, "%>"); 61362449Speter bufptr = save_tc_char(bufptr, c1); 61462449Speter bufptr = save_tc_char(bufptr, c2); 61562449Speter return bufptr; 61662449Speter} 61762449Speter 61862449Speter/* 61950276Speter * Here are the capabilities infotocap assumes it can translate to: 62050276Speter * 62150276Speter * %% output `%' 62250276Speter * %d output value as in printf %d 62350276Speter * %2 output value as in printf %2d 62450276Speter * %3 output value as in printf %3d 62550276Speter * %. output value as in printf %c 62650276Speter * %+c add character c to value, then do %. 62750276Speter * %>xy if value > x then add y, no output 62850276Speter * %r reverse order of two parameters, no output 62950276Speter * %i increment by one, no output 63050276Speter * %n exclusive-or all parameters with 0140 (Datamedia 2500) 63150276Speter * %B BCD (16*(value/10)) + (value%10), no output 63250276Speter * %D Reverse coding (value - 2*(value%16)), no output (Delta Data). 63350276Speter * %m exclusive-or all parameters with 0177 (not in 4.4BSD) 63450276Speter */ 63550276Speter 63676726Speter/* 63776726Speter * Convert a terminfo string to termcap format. Parameters are as in 63876726Speter * _nc_captoinfo(). 63976726Speter */ 640166124SrafanNCURSES_EXPORT(char *) 641166124Srafan_nc_infotocap(const char *cap GCC_UNUSED, const char *str, int const parameterized) 64250276Speter{ 64362449Speter int seenone = 0, seentwo = 0, saw_m = 0, saw_n = 0; 64450276Speter const char *padding; 64550276Speter const char *trimmed = 0; 64650276Speter char ch1 = 0, ch2 = 0; 64750276Speter char *bufptr = init_string(); 64862449Speter int len; 64962449Speter bool syntax_error = FALSE; 65050276Speter 65150276Speter /* we may have to move some trailing mandatory padding up front */ 65250276Speter padding = str + strlen(str) - 1; 653166124Srafan if (padding > str && *padding == '>' && *--padding == '/') { 65450276Speter --padding; 65597049Speter while (isdigit(UChar(*padding)) || *padding == '.' || *padding == '*') 65650276Speter padding--; 657166124Srafan if (padding > str && *padding == '<' && *--padding == '$') 65850276Speter trimmed = padding; 65950276Speter padding += 2; 66050276Speter 66197049Speter while (isdigit(UChar(*padding)) || *padding == '.' || *padding == '*') 66250276Speter bufptr = save_char(bufptr, *padding++); 66350276Speter } 66450276Speter 66562449Speter for (; *str && str != trimmed; str++) { 66662449Speter int c1, c2; 66762449Speter char *cp = 0; 66850276Speter 66962449Speter if (str[0] == '\\' && (str[1] == '^' || str[1] == ',')) { 67050276Speter bufptr = save_char(bufptr, *++str); 67162449Speter } else if (str[0] == '$' && str[1] == '<') { /* discard padding */ 67250276Speter str += 2; 67397049Speter while (isdigit(UChar(*str)) 67476726Speter || *str == '.' 67576726Speter || *str == '*' 67676726Speter || *str == '/' 67776726Speter || *str == '>') 67850276Speter str++; 67950276Speter --str; 68062449Speter } else if (str[0] == '%' && str[1] == '%') { /* escaped '%' */ 68162449Speter bufptr = save_string(bufptr, "%%"); 682166124Srafan ++str; 683166124Srafan } else if (*str != '%' || (parameterized < 1)) { 68450276Speter bufptr = save_char(bufptr, *str); 68562449Speter } else if (sscanf(str, "%%?%%{%d}%%>%%t%%{%d}%%+%%;", &c1, &c2) == 2) { 68650276Speter str = strchr(str, ';'); 68762449Speter bufptr = save_tc_inequality(bufptr, c1, c2); 68862449Speter } else if (sscanf(str, "%%?%%{%d}%%>%%t%%'%c'%%+%%;", &c1, &ch2) == 2) { 68950276Speter str = strchr(str, ';'); 69062449Speter bufptr = save_tc_inequality(bufptr, c1, c2); 69162449Speter } else if (sscanf(str, "%%?%%'%c'%%>%%t%%{%d}%%+%%;", &ch1, &c2) == 2) { 69250276Speter str = strchr(str, ';'); 69362449Speter bufptr = save_tc_inequality(bufptr, c1, c2); 69462449Speter } else if (sscanf(str, "%%?%%'%c'%%>%%t%%'%c'%%+%%;", &ch1, &ch2) == 2) { 69550276Speter str = strchr(str, ';'); 69662449Speter bufptr = save_tc_inequality(bufptr, c1, c2); 69762449Speter } else if ((len = bcd_expression(str)) != 0) { 69862449Speter str += len; 69962449Speter bufptr = save_string(bufptr, "%B"); 70062449Speter } else if ((sscanf(str, "%%{%d}%%+%%c", &c1) == 1 70162449Speter || sscanf(str, "%%'%c'%%+%%c", &ch1) == 1) 70276726Speter && (cp = strchr(str, '+'))) { 70350276Speter str = cp + 2; 70462449Speter bufptr = save_string(bufptr, "%+"); 70550276Speter 70650276Speter if (ch1) 70750276Speter c1 = ch1; 70862449Speter bufptr = save_tc_char(bufptr, c1); 70950276Speter } 71062449Speter /* FIXME: this "works" for 'delta' */ 71162449Speter else if (strncmp(str, "%{2}%*%-", 8) == 0) { 71250276Speter str += 7; 71362449Speter bufptr = save_string(bufptr, "%D"); 71462449Speter } else if (strncmp(str, "%{96}%^", 7) == 0) { 71550276Speter str += 6; 71662449Speter if (saw_m++ == 0) { 71762449Speter bufptr = save_string(bufptr, "%n"); 71850276Speter } 71962449Speter } else if (strncmp(str, "%{127}%^", 8) == 0) { 72050276Speter str += 7; 72162449Speter if (saw_n++ == 0) { 72262449Speter bufptr = save_string(bufptr, "%m"); 72350276Speter } 72462449Speter } else { /* cm-style format element */ 72550276Speter str++; 72650276Speter switch (*str) { 72750276Speter case '%': 72850276Speter bufptr = save_char(bufptr, '%'); 72950276Speter break; 73050276Speter 73150276Speter case '0': 73250276Speter case '1': 73350276Speter case '2': 73450276Speter case '3': 73550276Speter case '4': 73650276Speter case '5': 73750276Speter case '6': 73850276Speter case '7': 73950276Speter case '8': 74050276Speter case '9': 74150276Speter bufptr = save_char(bufptr, '%'); 74297049Speter while (isdigit(UChar(*str))) 74350276Speter bufptr = save_char(bufptr, *str++); 74462449Speter if (strchr("doxX.", *str)) { 74562449Speter if (*str != 'd') /* termcap doesn't have octal, hex */ 74662449Speter return 0; 74762449Speter } 74850276Speter break; 74950276Speter 75050276Speter case 'd': 75162449Speter bufptr = save_string(bufptr, "%d"); 75250276Speter break; 75350276Speter 75450276Speter case 'c': 75562449Speter bufptr = save_string(bufptr, "%."); 75650276Speter break; 75750276Speter 75862449Speter /* 75962449Speter * %s isn't in termcap, but it's convenient to pass it through 76062449Speter * so we can represent things like terminfo pfkey strings in 76162449Speter * termcap notation. 76262449Speter */ 76350276Speter case 's': 76462449Speter bufptr = save_string(bufptr, "%s"); 76550276Speter break; 76650276Speter 76750276Speter case 'p': 76850276Speter str++; 76950276Speter if (*str == '1') 77050276Speter seenone = 1; 77162449Speter else if (*str == '2') { 77262449Speter if (!seenone && !seentwo) { 77362449Speter bufptr = save_string(bufptr, "%r"); 77450276Speter seentwo++; 77550276Speter } 77662449Speter } else if (*str >= '3') 77762449Speter return (0); 77850276Speter break; 77950276Speter 78050276Speter case 'i': 78162449Speter bufptr = save_string(bufptr, "%i"); 78250276Speter break; 78350276Speter 78450276Speter default: 78562449Speter bufptr = save_char(bufptr, *str); 78662449Speter syntax_error = TRUE; 78762449Speter break; 78862449Speter } /* endswitch (*str) */ 78962449Speter } /* endelse (*str == '%') */ 79050276Speter 791184989Srafan /* 792184989Srafan * 'str' always points to the end of what was scanned in this step, 793184989Srafan * but that may not be the end of the string. 794184989Srafan */ 795184989Srafan assert(str != 0); 79650276Speter if (*str == '\0') 79750276Speter break; 79850276Speter 79962449Speter } /* endwhile (*str) */ 80050276Speter 80162449Speter return (syntax_error ? NULL : my_string); 80250276Speter} 80350276Speter 80450276Speter#ifdef MAIN 80550276Speter 80650276Speterint curr_line; 80750276Speter 80862449Speterint 80962449Spetermain(int argc, char *argv[]) 81050276Speter{ 81150276Speter int c, tc = FALSE; 81250276Speter 81350276Speter while ((c = getopt(argc, argv, "c")) != EOF) 81462449Speter switch (c) { 81550276Speter case 'c': 81650276Speter tc = TRUE; 81750276Speter break; 81850276Speter } 81950276Speter 82050276Speter curr_line = 0; 82162449Speter for (;;) { 82262449Speter char buf[BUFSIZ]; 82350276Speter 82450276Speter ++curr_line; 82550276Speter if (fgets(buf, sizeof(buf), stdin) == 0) 82650276Speter break; 82750276Speter buf[strlen(buf) - 1] = '\0'; 82850276Speter _nc_set_source(buf); 82950276Speter 83062449Speter if (tc) { 83162449Speter char *cp = _nc_infotocap("to termcap", buf, 1); 83250276Speter 83350276Speter if (cp) 83450276Speter (void) fputs(cp, stdout); 83562449Speter } else 83650276Speter (void) fputs(_nc_captoinfo("to terminfo", buf, 1), stdout); 83750276Speter (void) putchar('\n'); 83850276Speter } 83962449Speter return (0); 84050276Speter} 84150276Speter#endif /* MAIN */ 84250276Speter 843166124Srafan#if NO_LEAKS 844166124SrafanNCURSES_EXPORT(void) 845166124Srafan_nc_captoinfo_leaks(void) 846166124Srafan{ 847166124Srafan if (my_string != 0) { 848166124Srafan FreeAndNull(my_string); 849166124Srafan } 850166124Srafan my_length = 0; 851166124Srafan} 852166124Srafan#endif 853