Contents in 1999-06-04-13 of release-21-2.
[chise/xemacs-chise.git.1] / src / tparam.c
1 /* Merge parameters into a termcap entry string.
2    Copyright (C) 1985, 1987, 1992, 1993, 1994 Free Software Foundation, Inc.
3
4 This file is part of XEmacs.
5
6 XEmacs is free software; you can redistribute it and/or modify it
7 under the terms of the GNU General Public License as published by the
8 Free Software Foundation; either version 2, or (at your option) any
9 later version.
10
11 XEmacs is distributed in the hope that it will be useful, but WITHOUT
12 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with XEmacs; see the file COPYING.  If not, write to
18 the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
19 Boston, MA 02111-1307, USA.  */
20
21 /* Synched up with: Not synched with FSF. */
22
23 /* config.h may rename various library functions such as malloc.  */
24 #ifdef emacs
25
26 #include <config.h>
27
28 #include <string.h>
29
30 #define realloc xrealloc
31 #define malloc xmalloc
32 #define free xfree
33 extern void *xmalloc (int size);
34 extern void *xrealloc (void *, int size);
35
36 #else /* emacs */
37
38 #ifdef STDC_HEADERS
39 #include <stdlib.h>
40 #include <string.h>
41 #else
42 extern char *malloc ();
43 extern char *realloc ();
44 #endif
45
46 #endif /* !emacs */
47
48 /* Assuming STRING is the value of a termcap string entry
49    containing `%' constructs to expand parameters,
50    merge in parameter values and store result in block OUTSTRING points to.
51    LEN is the length of OUTSTRING.  If more space is needed,
52    a block is allocated with `malloc'.
53
54    The value returned is the address of the resulting string.
55    This may be OUTSTRING or may be the address of a block got with `malloc'.
56    In the latter case, the caller must free the block.
57
58    The fourth and following args to tparam serve as the parameter values.  */
59
60 static char *tparam1 (CONST char *string, char *outstring, int len,
61                       CONST char *up, CONST char *left, 
62                       int *argp);
63
64 /* XEmacs: renamed this function because just tparam() conflicts with
65    ncurses */
66 char *emacs_tparam (CONST char *string, char *outstring, int len, int arg0,
67                     int arg1, int arg2, int arg3);
68 char *
69 emacs_tparam (CONST char *string, char *outstring, int len, int arg0,
70               int arg1, int arg2, int arg3)
71 {
72   int arg[4];
73   arg[0] = arg0;
74   arg[1] = arg1;
75   arg[2] = arg2;
76   arg[3] = arg3;
77   return tparam1 (string, outstring, len, 0, 0, arg);
78 }
79
80 CONST char *BC;
81 CONST char *UP;
82
83 static char tgoto_buf[50];
84
85 char *tgoto (CONST char *cm, int hpos, int vpos);
86 char *
87 tgoto (CONST char *cm, int hpos, int vpos)
88 {
89   int args[2];
90   if (!cm)
91     return 0;
92   args[0] = vpos;
93   args[1] = hpos;
94   return tparam1 (cm, tgoto_buf, 50, UP, BC, args);
95 }
96
97 static char *
98 tparam1 (CONST char *string, char *outstring, int len, CONST char *up,
99          CONST char *left, int *argp)
100 {
101   int c;
102   CONST char *p = string;
103   char *op = outstring;
104   char *outend;
105   int outlen = 0;
106
107   int tem;
108   int *old_argp = argp;
109   int doleft = 0;
110   int doup = 0;
111
112   outend = outstring + len;
113
114   while (1)
115     {
116       /* If the buffer might be too short, make it bigger.  */
117       if (op + 5 >= outend)
118         {
119           char *new;
120           if (outlen == 0)
121             {
122               outlen = len + 40;
123               new = (char *) malloc (outlen);
124               outend += 40;
125               memcpy (new, outstring, op - outstring);
126             }
127           else
128             {
129               outend += outlen;
130               outlen *= 2;
131               new = (char *) realloc (outstring, outlen);
132             }
133           op += new - outstring;
134           outend += new - outstring;
135           outstring = new;
136         }
137       c = *p++;
138       if (!c)
139         break;
140       if (c == '%')
141         {
142           c = *p++;
143           tem = *argp;
144           switch (c)
145             {
146             case 'd':           /* %d means output in decimal.  */
147               if (tem < 10)
148                 goto onedigit;
149               if (tem < 100)
150                 goto twodigit;
151             case '3':           /* %3 means output in decimal, 3 digits.  */
152               if (tem > 999)
153                 {
154                   *op++ = tem / 1000 + '0';
155                   tem %= 1000;
156                 }
157               *op++ = tem / 100 + '0';
158             case '2':           /* %2 means output in decimal, 2 digits.  */
159             twodigit:
160               tem %= 100;
161               *op++ = tem / 10 + '0';
162             onedigit:
163               *op++ = tem % 10 + '0';
164               argp++;
165               break;
166
167             case 'C':
168               /* For c-100: print quotient of value by 96, if nonzero,
169                  then do like %+.  */
170               if (tem >= 96)
171                 {
172                   *op++ = tem / 96;
173                   tem %= 96;
174                 }
175             case '+':           /* %+x means add character code of char x.  */
176               tem += *p++;
177             case '.':           /* %. means output as character.  */
178               if (left)
179                 {
180                   /* If want to forbid output of 0 and \n and \t,
181                      and this is one of them, increment it.  */
182                   while (tem == 0 || tem == '\n' || tem == '\t')
183                     {
184                       tem++;
185                       if (argp == old_argp)
186                         doup++, outend -= strlen (up);
187                       else
188                         doleft++, outend -= strlen (left);
189                     }
190                 }
191               *op++ = tem | 0200;
192             case 'f':           /* %f means discard next arg.  */
193               argp++;
194               break;
195
196             case 'b':           /* %b means back up one arg (and re-use it). */
197               argp--;
198               break;
199
200             case 'r':           /* %r means interchange following two args. */
201               argp[0] = argp[1];
202               argp[1] = tem;
203               old_argp++;
204               break;
205
206             case '>':           /* %>xy means if arg is > char code of x, */
207               if (argp[0] > *p++) /* then add char code of y to the arg, */
208                 argp[0] += *p;  /* and in any case don't output. */
209               p++;              /* Leave the arg to be output later. */
210               break;
211
212             case 'a':           /* %a means arithmetic. */
213               /* Next character says what operation.
214                  Add or subtract either a constant or some other arg. */
215               /* First following character is + to add or - to subtract
216                  or = to assign.  */
217               /* Next following char is 'p' and an arg spec
218                  (0100 plus position of that arg relative to this one)
219                  or 'c' and a constant stored in a character. */
220               tem = p[2] & 0177;
221               if (p[1] == 'p')
222                 tem = argp[tem - 0100];
223               if (p[0] == '-')
224                 argp[0] -= tem;
225               else if (p[0] == '+')
226                 argp[0] += tem;
227               else if (p[0] == '*')
228                 argp[0] *= tem;
229               else if (p[0] == '/')
230                 argp[0] /= tem;
231               else
232                 argp[0] = tem;
233
234               p += 3;
235               break;
236
237             case 'i':           /* %i means add one to arg, */
238               argp[0] ++;       /* and leave it to be output later. */
239               argp[1] ++;       /* Increment the following arg, too!  */
240               break;
241
242             case '%':           /* %% means output %; no arg. */
243               goto ordinary;
244
245             case 'n':           /* %n means xor each of next two args with 140. */
246               argp[0] ^= 0140;
247               argp[1] ^= 0140;
248               break;
249
250             case 'm':           /* %m means xor each of next two args with 177. */
251               argp[0] ^= 0177;
252               argp[1] ^= 0177;
253               break;
254
255             case 'B':           /* %B means express arg as BCD char code. */
256               argp[0] += 6 * (tem / 10);
257               break;
258
259             case 'D':           /* %D means weird Delta Data transformation. */
260               argp[0] -= 2 * (tem % 16);
261               break;
262             }
263         }
264       else
265         /* Ordinary character in the argument string.  */
266       ordinary:
267         *op++ = c;
268     }
269   *op = 0;
270   while (doup-- > 0)
271     strcat (op, up);
272   while (doleft-- > 0)
273     strcat (op, left);
274   return outstring;
275 }
276 \f
277 #ifdef DEBUG
278
279 main (argc, argv)
280      int argc;
281      char **argv;
282 {
283   char buf[50];
284   int args[3];
285   args[0] = atoi (argv[2]);
286   args[1] = atoi (argv[3]);
287   args[2] = atoi (argv[4]);
288   tparam1 (argv[1], buf, "LEFT", "UP", args);
289   printf ("%s\n", buf);
290   return 0;
291 }
292
293 #endif /* DEBUG */