/src/libs/ncurses/ncurses/tinfo/comp_expand.c

https://github.com/0xffea/haiku · C · 184 lines · 129 code · 12 blank · 43 comment · 108 complexity · d89ccea4eb0c8202bfe6bd1a1599ed58 MD5 · raw file

  1. /****************************************************************************
  2. * Copyright (c) 1998,2000,2001 Free Software Foundation, Inc. *
  3. * *
  4. * Permission is hereby granted, free of charge, to any person obtaining a *
  5. * copy of this software and associated documentation files (the *
  6. * "Software"), to deal in the Software without restriction, including *
  7. * without limitation the rights to use, copy, modify, merge, publish, *
  8. * distribute, distribute with modifications, sublicense, and/or sell *
  9. * copies of the Software, and to permit persons to whom the Software is *
  10. * furnished to do so, subject to the following conditions: *
  11. * *
  12. * The above copyright notice and this permission notice shall be included *
  13. * in all copies or substantial portions of the Software. *
  14. * *
  15. * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS *
  16. * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF *
  17. * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. *
  18. * IN NO EVENT SHALL THE ABOVE COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, *
  19. * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR *
  20. * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR *
  21. * THE USE OR OTHER DEALINGS IN THE SOFTWARE. *
  22. * *
  23. * Except as contained in this notice, the name(s) of the above copyright *
  24. * holders shall not be used in advertising or otherwise to promote the *
  25. * sale, use or other dealings in this Software without prior written *
  26. * authorization. *
  27. ****************************************************************************/
  28. /****************************************************************************
  29. * Author: Thomas E. Dickey <dickey@clark.net> 1998 *
  30. ****************************************************************************/
  31. #include <curses.priv.h>
  32. #include <ctype.h>
  33. #include <tic.h>
  34. MODULE_ID("$Id: comp_expand.c,v 1.17 2001/09/22 19:16:52 tom Exp $")
  35. static int
  36. trailing_spaces(const char *src)
  37. {
  38. while (*src == ' ')
  39. src++;
  40. return *src == 0;
  41. }
  42. /* this deals with differences over whether 0x7f and 0x80..0x9f are controls */
  43. #define REALCTL(s) (UChar(*(s)) < 127 && iscntrl(UChar(*(s))))
  44. #define REALPRINT(s) (UChar(*(s)) < 127 && isprint(UChar(*(s))))
  45. NCURSES_EXPORT(char *)
  46. _nc_tic_expand
  47. (const char *srcp, bool tic_format, int numbers)
  48. {
  49. static char *buffer;
  50. static size_t length;
  51. int bufp;
  52. const char *str = VALID_STRING(srcp) ? srcp : "";
  53. bool islong = (strlen(str) > 3);
  54. size_t need = (2 + strlen(str)) * 4;
  55. int ch;
  56. if (buffer == 0 || need > length) {
  57. if ((buffer = typeRealloc(char, length = need, buffer)) == 0)
  58. return 0;
  59. }
  60. bufp = 0;
  61. while ((ch = UChar(*str)) != 0) {
  62. if (ch == '%' && REALPRINT(str + 1)) {
  63. buffer[bufp++] = *str++;
  64. /*
  65. * Though the character literals are more compact, most
  66. * terminal descriptions use numbers and are not easy
  67. * to read in character-literal form.
  68. */
  69. switch (numbers) {
  70. case -1:
  71. if (str[0] == S_QUOTE
  72. && str[1] != '\\'
  73. && REALPRINT(str + 1)
  74. && str[2] == S_QUOTE) {
  75. sprintf(buffer + bufp, "{%d}", str[1]);
  76. bufp += strlen(buffer + bufp);
  77. str += 2;
  78. } else {
  79. buffer[bufp++] = *str;
  80. }
  81. break;
  82. /*
  83. * If we have a "%{number}", try to translate it into
  84. * a "%'char'" form, since that will run a little faster
  85. * when we're interpreting it. Also, having one form
  86. * for the constant makes it simpler to compare terminal
  87. * descriptions.
  88. */
  89. case 1:
  90. if (str[0] == L_BRACE
  91. && isdigit(UChar(str[1]))) {
  92. char *dst = 0;
  93. long value = strtol(str + 1, &dst, 0);
  94. if (dst != 0
  95. && *dst == R_BRACE
  96. && value < 127
  97. && value != '\\' /* FIXME */
  98. && isprint((int) value)) {
  99. ch = (int) value;
  100. buffer[bufp++] = S_QUOTE;
  101. if (ch == '\\'
  102. || ch == S_QUOTE)
  103. buffer[bufp++] = '\\';
  104. buffer[bufp++] = ch;
  105. buffer[bufp++] = S_QUOTE;
  106. str = dst;
  107. } else {
  108. buffer[bufp++] = *str;
  109. }
  110. } else {
  111. buffer[bufp++] = *str;
  112. }
  113. break;
  114. default:
  115. buffer[bufp++] = *str;
  116. break;
  117. }
  118. } else if (ch == 128) {
  119. buffer[bufp++] = '\\';
  120. buffer[bufp++] = '0';
  121. } else if (ch == '\033') {
  122. buffer[bufp++] = '\\';
  123. buffer[bufp++] = 'E';
  124. } else if (ch == '\\' && tic_format && (str == srcp || str[-1] != '^')) {
  125. buffer[bufp++] = '\\';
  126. buffer[bufp++] = '\\';
  127. } else if (ch == ' ' && tic_format && (str == srcp ||
  128. trailing_spaces(str))) {
  129. buffer[bufp++] = '\\';
  130. buffer[bufp++] = 's';
  131. } else if ((ch == ',' || ch == ':' || ch == '^') && tic_format) {
  132. buffer[bufp++] = '\\';
  133. buffer[bufp++] = ch;
  134. } else if (REALPRINT(str)
  135. && (ch != ','
  136. && ch != ':'
  137. && !(ch == '!' && !tic_format)
  138. && ch != '^'))
  139. buffer[bufp++] = ch;
  140. #if 0 /* FIXME: this would be more readable (in fact the whole 'islong' logic should be removed) */
  141. else if (ch == '\b') {
  142. buffer[bufp++] = '\\';
  143. buffer[bufp++] = 'b';
  144. } else if (ch == '\f') {
  145. buffer[bufp++] = '\\';
  146. buffer[bufp++] = 'f';
  147. } else if (ch == '\t' && islong) {
  148. buffer[bufp++] = '\\';
  149. buffer[bufp++] = 't';
  150. }
  151. #endif
  152. else if (ch == '\r' && (islong || (strlen(srcp) > 2 && str[1] == '\0'))) {
  153. buffer[bufp++] = '\\';
  154. buffer[bufp++] = 'r';
  155. } else if (ch == '\n' && islong) {
  156. buffer[bufp++] = '\\';
  157. buffer[bufp++] = 'n';
  158. }
  159. #define UnCtl(c) ((c) + '@')
  160. else if (REALCTL(str) && ch != '\\'
  161. && (!islong || isdigit(UChar(str[1])))) {
  162. (void) sprintf(&buffer[bufp], "^%c", UnCtl(ch));
  163. bufp += 2;
  164. } else {
  165. (void) sprintf(&buffer[bufp], "\\%03o", ch);
  166. bufp += 4;
  167. }
  168. str++;
  169. }
  170. buffer[bufp] = '\0';
  171. return (buffer);
  172. }