1/**************************************************************************** 2 * Copyright (c) 2006-2007,2008 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: chgat.c,v 1.8 2008/02/09 23:19:13 tom Exp $ 30 * 31 * test-driver for chgat/wchgat/mvchgat/mvwchgat 32 */ 33 34#include <test.priv.h> 35 36#if HAVE_CHGAT 37 38#define SHOW(n) ((n) == ERR ? "ERR" : "OK") 39#define COLOR_DEFAULT (-1) 40 41#if defined(NCURSES_VERSION_PATCH) && NCURSES_VERSION_PATCH < 20060715 42#define touch_if_needed(win, row) touchline(win, row, 1) 43#else 44#define touch_if_needed(win, row) /* nothing */ 45#endif 46 47typedef struct { 48 unsigned c; 49 unsigned v; 50 int pair; 51 unsigned attr; 52 int count; 53 int ch; 54 const char *c_msg; 55 const char *v_msg; 56 int y_val; 57 int x_val; 58 int y_beg, x_beg; 59 int y_max, x_max; 60} STATUS; 61 62static const char * 63color_params(unsigned state, int *pair) 64{ 65 /* *INDENT-OFF* */ 66 static struct { 67 int pair; 68 int fg, bg; 69 const char *msg; 70 } table[] = { 71 { 0, COLOR_DEFAULT, COLOR_DEFAULT, "default" }, 72 { 1, COLOR_RED, COLOR_BLACK, "red/black" }, 73 { 2, COLOR_WHITE, COLOR_BLUE, "white/blue" }, 74 }; 75 /* *INDENT-ON* */ 76 77 static bool first = TRUE; 78 const char *result = 0; 79 80 if (has_colors()) { 81 if (first) { 82 unsigned n; 83 84 start_color(); 85 for (n = 0; n < SIZEOF(table); ++n) { 86 init_pair(table[n].pair, table[n].fg, table[n].bg); 87 } 88 } 89 if (state < SIZEOF(table)) { 90 *pair = table[state].pair; 91 result = table[state].msg; 92 } 93 } 94 return result; 95} 96 97static const char * 98video_params(unsigned state, unsigned *attr) 99{ 100 /* *INDENT-OFF* */ 101 static struct { 102 unsigned attr; 103 const char *msg; 104 } table[] = { 105 { A_NORMAL, "normal" }, 106 { A_BOLD, "bold" }, 107 { A_REVERSE, "reverse" }, 108 { A_UNDERLINE, "underline" }, 109 { A_BLINK, "blink" }, 110 }; 111 /* *INDENT-ON* */ 112 113 const char *result = 0; 114 115 if (state < SIZEOF(table)) { 116 *attr = table[state].attr; 117 result = table[state].msg; 118 } 119 return result; 120} 121 122/* fill the window with a test-pattern */ 123static void 124fill_window(WINDOW *win) 125{ 126 int y, x; 127 128 getyx(win, y, x); 129 wmove(win, 0, 0); 130 while (waddstr(win, "0123456789 abcdefghijklmnopqrstuvwxyz ") != ERR) { 131 } 132 wmove(win, y, x); 133} 134 135static void 136show_status(WINDOW *win, STATUS * sp) 137{ 138 int y, x; 139 140 getyx(win, y, x); 141 wmove(win, 0, 0); 142 wprintw(win, "Count %d", sp->count); 143 if (sp->v_msg != 0) 144 wprintw(win, " Video %s", sp->v_msg); 145 if (sp->c_msg != 0) 146 wprintw(win, " Color %s", sp->c_msg); 147 wclrtoeol(win); 148 wmove(win, y, x); 149} 150 151static void 152do_subwindow(WINDOW *win, STATUS * sp, void func(WINDOW *)) 153{ 154 WINDOW *win1 = newwin(sp->y_max - 2, sp->x_max - 2, 155 sp->y_beg + 1, sp->x_beg + 1); 156 157 if (win1 != 0 && sp->y_max > 4 && sp->x_max > 4) { 158 WINDOW *win2 = derwin(win1, sp->y_max - 4, sp->x_max - 4, 1, 1); 159 160 if (win2 != 0) { 161 box(win1, 0, 0); 162 wrefresh(win1); 163 func(win2); 164 165 delwin(win2); 166 } else { 167 beep(); 168 } 169 delwin(win1); 170 touchwin(win); 171 } else { 172 beep(); 173 } 174} 175 176static void 177init_status(WINDOW *win, STATUS * sp) 178{ 179 memset(sp, 0, sizeof(*sp)); 180 sp->c = 99; 181 sp->v = 99; 182 sp->ch = ' '; 183 184 keypad(win, TRUE); 185 fill_window(win); 186 187 getbegyx(win, sp->y_beg, sp->x_beg); 188 getmaxyx(win, sp->y_max, sp->x_max); 189} 190 191static void 192show_help(WINDOW *win) 193{ 194 static const char *table[] = 195 { 196 "Basic commands:" 197 ,"Use h/j/k/l or arrow keys to move the cursor." 198 ,"Set the count parameter for chgat by entering digits 0-9." 199 ,"" 200 ,"Other commands:" 201 ,"space toggles through the set of video attributes and colors." 202 ,"t touches (forces repaint) of the current line." 203 ,". calls *chgat at the current position with the given count." 204 ,", calls *chgat at the window beginning with the given count." 205 ,"= resets count to zero." 206 ,"- negates count." 207 ,"? shows this help-window" 208 ,"" 209 ,"" 210 }; 211 212 int y_max, x_max; 213 int row; 214 215 getmaxyx(win, y_max, x_max); 216 for (row = 0; row < (int) SIZEOF(table) && row < y_max; ++row) { 217 mvwprintw(win, row, 0, "%.*s", x_max, table[row]); 218 } 219 while (wgetch(win) != 'q') 220 beep(); 221} 222 223static void 224update_status(WINDOW *win, STATUS * sp) 225{ 226 switch (sp->ch) { 227 case ' ': /* next test-iteration */ 228 if (has_colors()) { 229 if ((sp->c_msg = color_params(++(sp->c), &(sp->pair))) == 0) { 230 sp->c_msg = color_params(sp->c = 0, &(sp->pair)); 231 if ((sp->v_msg = video_params(++(sp->v), &(sp->attr))) == 0) { 232 sp->v_msg = video_params(sp->v = 0, &(sp->attr)); 233 } 234 } 235 } else { 236 if ((sp->v_msg = video_params(++(sp->v), &(sp->attr))) == 0) { 237 sp->v_msg = video_params(sp->v = 0, &(sp->attr)); 238 } 239 } 240 sp->count = 0; 241 show_status(win, sp); 242 break; 243 case KEY_LEFT: 244 case 'h': 245 if (sp->x_val > 0) 246 wmove(win, sp->y_val, --(sp->x_val)); 247 break; 248 case KEY_DOWN: 249 case 'j': 250 if (sp->y_val < sp->y_max) 251 wmove(win, ++(sp->y_val), sp->x_val); 252 break; 253 case KEY_UP: 254 case 'k': 255 if (sp->y_val > 0) 256 wmove(win, --(sp->y_val), sp->x_val); 257 break; 258 case KEY_RIGHT: 259 case 'l': 260 if (sp->x_val < sp->x_max) 261 wmove(win, sp->y_val, ++(sp->x_val)); 262 break; 263 case 't': 264 touchline(win, sp->y_val, 1); 265 break; 266 case '=': 267 sp->count = 0; 268 show_status(win, sp); 269 break; 270 case '-': 271 sp->count = -(sp->count); 272 show_status(win, sp); 273 break; 274 case '?': 275 do_subwindow(win, sp, show_help); 276 break; 277 default: 278 if (isdigit(sp->ch)) { 279 sp->count = (sp->count * 10) + (sp->ch - '0'); 280 show_status(win, sp); 281 } else { 282 beep(); 283 } 284 break; 285 } 286} 287 288static void 289test_wchgat(WINDOW *win) 290{ 291 STATUS st; 292 293 init_status(win, &st); 294 295 do { 296 switch (st.ch) { 297 case '.': /* change from current position */ 298 wchgat(win, st.count, st.attr, st.pair, (void *) 0); 299 touch_if_needed(win, st.y_val); 300 break; 301 case ',': /* change from beginning of window */ 302 mvwchgat(win, 0, 0, st.count, st.attr, st.pair, (void *) 0); 303 touch_if_needed(win, 0); 304 wmove(win, st.y_val, st.x_val); 305 break; 306 case 'w': 307 do_subwindow(win, &st, test_wchgat); 308 break; 309 case 'q': 310 return; 311 default: 312 update_status(win, &st); 313 break; 314 } 315 } while ((st.ch = wgetch(win)) != ERR); 316} 317 318static void 319test_chgat(void) 320{ 321 STATUS st; 322 323 init_status(stdscr, &st); 324 325 do { 326 switch (st.ch) { 327 case '.': /* change from current position */ 328 chgat(st.count, st.attr, st.pair, (void *) 0); 329 touch_if_needed(stdscr, st.y_val); 330 break; 331 case ',': /* change from beginning of window */ 332 mvchgat(0, 0, st.count, st.attr, st.pair, (void *) 0); 333 touch_if_needed(stdscr, 0); 334 move(st.y_val, st.x_val); 335 break; 336 case 'w': 337 do_subwindow(stdscr, &st, test_wchgat); 338 break; 339 case 'q': 340 return; 341 default: 342 update_status(stdscr, &st); 343 break; 344 } 345 } while ((st.ch = getch()) != ERR); 346} 347 348int 349main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED) 350{ 351 initscr(); 352 cbreak(); 353 noecho(); 354 355 test_chgat(); 356 endwin(); 357 358 ExitProgram(EXIT_SUCCESS); 359} 360 361#else 362int 363main(void) 364{ 365 printf("This program requires the curses chgat function\n"); 366 ExitProgram(EXIT_FAILURE); 367} 368#endif 369