1/**************************************************************************** 2 * Copyright (c) 2002-2006,2007 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 * $Id: inserts.c,v 1.18 2007/07/21 17:41:55 tom Exp $ 30 * 31 * Demonstrate the winsstr() and winsch functions. 32 * Thomas Dickey - 2002/10/19 33 */ 34 35#include <test.priv.h> 36 37#if HAVE_WINSSTR 38 39#define InsNStr insnstr 40#define InsStr insstr 41#define MvInsNStr mvinsnstr 42#define MvInsStr mvinsstr 43#define MvWInsNStr mvwinsnstr 44#define MvWInsStr mvwinsstr 45#define WInsNStr winsnstr 46#define WInsStr winsstr 47 48#define InsCh insch 49#define MvInsCh mvinsch 50#define MvWInsCh mvwinsch 51#define WInsCh winsch 52 53#define MY_TABSIZE 8 54 55typedef enum { 56 oDefault = 0, 57 oMove = 1, 58 oWindow = 2, 59 oMoveWindow = 3 60} Options; 61 62static bool m_opt = FALSE; 63static bool w_opt = FALSE; 64static int n_opt = -1; 65 66static void 67legend(WINDOW *win, int level, Options state, char *buffer, int length) 68{ 69 NCURSES_CONST char *showstate; 70 71 switch (state) { 72 default: 73 case oDefault: 74 showstate = ""; 75 break; 76 case oMove: 77 showstate = " (mvXXX)"; 78 break; 79 case oWindow: 80 showstate = " (winXXX)"; 81 break; 82 case oMoveWindow: 83 showstate = " (mvwinXXX)"; 84 break; 85 } 86 87 wmove(win, 0, 0); 88 wprintw(win, 89 "The Strings/Chars displays should match. Enter any characters, except:\n"); 90 wprintw(win, 91 "down-arrow or ^N to repeat on next line, 'w' for inner window, 'q' to exit.\n"); 92 wclrtoeol(win); 93 wprintw(win, "Level %d,%s inserted %d characters <%s>", level, 94 showstate, length, buffer); 95} 96 97static int 98ColOf(char *buffer, int length, int margin) 99{ 100 int n; 101 int result; 102 103 for (n = 0, result = margin + 1; n < length; ++n) { 104 int ch = UChar(buffer[n]); 105 switch (ch) { 106 case '\n': 107 /* actually newline should clear the remainder of the line 108 * and move to the next line - but that seems a little awkward 109 * in this example. 110 */ 111 case '\r': 112 result = 0; 113 break; 114 case '\b': 115 if (result > 0) 116 --result; 117 break; 118 case '\t': 119 result += (MY_TABSIZE - (result % MY_TABSIZE)); 120 break; 121 case '\177': 122 result += 2; 123 break; 124 default: 125 ++result; 126 if (ch < 32) 127 ++result; 128 break; 129 } 130 } 131 return result; 132} 133 134#define LEN(n) ((length - (n) > n_opt) ? n_opt : (length - (n))) 135static void 136test_inserts(int level) 137{ 138 static bool first = TRUE; 139 140 int ch; 141 int limit; 142 int row = 1; 143 int col; 144 int row2, col2; 145 int length; 146 char buffer[BUFSIZ]; 147 WINDOW *look = 0; 148 WINDOW *work = 0; 149 WINDOW *show = 0; 150 int margin = (2 * MY_TABSIZE) - 1; 151 Options option = (Options) ((unsigned) (m_opt 152 ? oMove 153 : oDefault) 154 | (unsigned) ((w_opt || (level > 0)) 155 ? oWindow 156 : oDefault)); 157 158 if (first) { 159 static char cmd[80]; 160 setlocale(LC_ALL, ""); 161 162 putenv(strcpy(cmd, "TABSIZE=8")); 163 164 initscr(); 165 (void) cbreak(); /* take input chars one at a time, no wait for \n */ 166 (void) noecho(); /* don't echo input */ 167 keypad(stdscr, TRUE); 168 } 169 170 limit = LINES - 5; 171 if (level > 0) { 172 look = newwin(limit, COLS - (2 * (level - 1)), 0, level - 1); 173 work = newwin(limit - 2, COLS - (2 * level), 1, level); 174 show = newwin(4, COLS, limit + 1, 0); 175 box(look, 0, 0); 176 wnoutrefresh(look); 177 limit -= 2; 178 } else { 179 work = stdscr; 180 show = derwin(stdscr, 4, COLS, limit + 1, 0); 181 } 182 keypad(work, TRUE); 183 184 for (col = margin + 1; col < COLS; col += MY_TABSIZE) 185 mvwvline(work, row, col, '.', limit - 2); 186 187 mvwvline(work, row, margin, ACS_VLINE, limit - 2); 188 mvwvline(work, row, margin + 1, ACS_VLINE, limit - 2); 189 limit /= 2; 190 191 mvwaddstr(work, 1, 2, "String"); 192 mvwaddstr(work, limit + 1, 2, "Chars"); 193 wnoutrefresh(work); 194 195 buffer[length = 0] = '\0'; 196 legend(show, level, option, buffer, length); 197 wnoutrefresh(show); 198 199 doupdate(); 200 201 /* 202 * Show the characters inserted in color, to distinguish from those that 203 * are shifted. 204 */ 205 if (has_colors()) { 206 start_color(); 207 init_pair(1, COLOR_WHITE, COLOR_BLUE); 208 wbkgdset(work, COLOR_PAIR(1) | ' '); 209 } 210 211 while ((ch = wgetch(work)) != 'q') { 212 if (ch == ERR) { 213 beep(); 214 break; 215 } 216 wmove(work, row, margin + 1); 217 switch (ch) { 218 case 'w': 219 test_inserts(level + 1); 220 221 touchwin(look); 222 touchwin(work); 223 touchwin(show); 224 225 wnoutrefresh(look); 226 wnoutrefresh(work); 227 wnoutrefresh(show); 228 229 doupdate(); 230 break; 231 case CTRL('N'): 232 case KEY_DOWN: 233 if (row < limit) { 234 ++row; 235 /* put the whole string in, all at once */ 236 col2 = margin + 1; 237 switch (option) { 238 case oDefault: 239 if (n_opt > 1) { 240 for (col = 0; col < length; col += n_opt) { 241 col2 = ColOf(buffer, col, margin); 242 if (move(row, col2) != ERR) { 243 InsNStr(buffer + col, LEN(col)); 244 } 245 } 246 } else { 247 if (move(row, col2) != ERR) { 248 InsStr(buffer); 249 } 250 } 251 break; 252 case oMove: 253 if (n_opt > 1) { 254 for (col = 0; col < length; col += n_opt) { 255 col2 = ColOf(buffer, col, margin); 256 MvInsNStr(row, col2, buffer + col, LEN(col)); 257 } 258 } else { 259 MvInsStr(row, col2, buffer); 260 } 261 break; 262 case oWindow: 263 if (n_opt > 1) { 264 for (col = 0; col < length; col += n_opt) { 265 col2 = ColOf(buffer, col, margin); 266 if (wmove(work, row, col2) != ERR) { 267 WInsNStr(work, buffer + col, LEN(col)); 268 } 269 } 270 } else { 271 if (wmove(work, row, col2) != ERR) { 272 WInsStr(work, buffer); 273 } 274 } 275 break; 276 case oMoveWindow: 277 if (n_opt > 1) { 278 for (col = 0; col < length; col += n_opt) { 279 col2 = ColOf(buffer, col, margin); 280 MvWInsNStr(work, row, col2, buffer + col, LEN(col)); 281 } 282 } else { 283 MvWInsStr(work, row, col2, buffer); 284 } 285 break; 286 } 287 288 /* do the corresponding single-character insertion */ 289 row2 = limit + row; 290 for (col = 0; col < length; ++col) { 291 col2 = ColOf(buffer, col, margin); 292 switch (option) { 293 case oDefault: 294 if (move(row2, col2) != ERR) { 295 InsCh(UChar(buffer[col])); 296 } 297 break; 298 case oMove: 299 MvInsCh(row2, col2, UChar(buffer[col])); 300 break; 301 case oWindow: 302 if (wmove(work, row2, col2) != ERR) { 303 WInsCh(work, UChar(buffer[col])); 304 } 305 break; 306 case oMoveWindow: 307 MvWInsCh(work, row2, col2, UChar(buffer[col])); 308 break; 309 } 310 } 311 } else { 312 beep(); 313 } 314 break; 315 case KEY_BACKSPACE: 316 ch = '\b'; 317 /* FALLTHRU */ 318 default: 319 if (ch <= 0 || ch > 255) { 320 beep(); 321 break; 322 } 323 buffer[length++] = ch; 324 buffer[length] = '\0'; 325 326 /* put the string in, one character at a time */ 327 col = ColOf(buffer, length - 1, margin); 328 switch (option) { 329 case oDefault: 330 if (move(row, col) != ERR) { 331 InsStr(buffer + length - 1); 332 } 333 break; 334 case oMove: 335 MvInsStr(row, col, buffer + length - 1); 336 break; 337 case oWindow: 338 if (wmove(work, row, col) != ERR) { 339 WInsStr(work, buffer + length - 1); 340 } 341 break; 342 case oMoveWindow: 343 MvWInsStr(work, row, col, buffer + length - 1); 344 break; 345 } 346 347 /* do the corresponding single-character insertion */ 348 switch (option) { 349 case oDefault: 350 if (move(limit + row, col) != ERR) { 351 InsCh(UChar(ch)); 352 } 353 break; 354 case oMove: 355 MvInsCh(limit + row, col, UChar(ch)); 356 break; 357 case oWindow: 358 if (wmove(work, limit + row, col) != ERR) { 359 WInsCh(work, UChar(ch)); 360 } 361 break; 362 case oMoveWindow: 363 MvWInsCh(work, limit + row, col, UChar(ch)); 364 break; 365 } 366 367 wnoutrefresh(work); 368 369 legend(show, level, option, buffer, length); 370 wnoutrefresh(show); 371 372 doupdate(); 373 break; 374 } 375 } 376 if (level > 0) { 377 delwin(show); 378 delwin(work); 379 delwin(look); 380 } 381} 382 383static void 384usage(void) 385{ 386 static const char *tbl[] = 387 { 388 "Usage: inserts [options]" 389 ,"" 390 ,"Options:" 391 ," -n NUM limit string-inserts to NUM bytes on ^N replay" 392 ," -m perform wmove/move separately from insert-functions" 393 ," -w use window-parameter even when stdscr would be implied" 394 }; 395 unsigned n; 396 for (n = 0; n < SIZEOF(tbl); ++n) 397 fprintf(stderr, "%s\n", tbl[n]); 398 ExitProgram(EXIT_FAILURE); 399} 400 401int 402main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED) 403{ 404 int ch; 405 406 setlocale(LC_ALL, ""); 407 408 while ((ch = getopt(argc, argv, "mn:w")) != -1) { 409 switch (ch) { 410 case 'm': 411 m_opt = TRUE; 412 break; 413 case 'n': 414 n_opt = atoi(optarg); 415 if (n_opt == 0) 416 n_opt = -1; 417 break; 418 case 'w': 419 w_opt = TRUE; 420 break; 421 default: 422 usage(); 423 break; 424 } 425 } 426 if (optind < argc) 427 usage(); 428 429 test_inserts(0); 430 endwin(); 431 ExitProgram(EXIT_SUCCESS); 432} 433#else 434int 435main(void) 436{ 437 printf("This program requires the winsstr function\n"); 438 ExitProgram(EXIT_FAILURE); 439} 440#endif /* HAVE_WINSSTR */ 441