1 1.27 dholland /* $NetBSD: io.c,v 1.27 2012/10/13 20:36:06 dholland Exp $ */ 2 1.7 cgd 3 1.7 cgd /*- 4 1.7 cgd * Copyright (c) 1980, 1993 5 1.7 cgd * The Regents of the University of California. All rights reserved. 6 1.1 cgd * 7 1.1 cgd * Redistribution and use in source and binary forms, with or without 8 1.1 cgd * modification, are permitted provided that the following conditions 9 1.1 cgd * are met: 10 1.1 cgd * 1. Redistributions of source code must retain the above copyright 11 1.1 cgd * notice, this list of conditions and the following disclaimer. 12 1.1 cgd * 2. Redistributions in binary form must reproduce the above copyright 13 1.1 cgd * notice, this list of conditions and the following disclaimer in the 14 1.1 cgd * documentation and/or other materials provided with the distribution. 15 1.16 agc * 3. Neither the name of the University nor the names of its contributors 16 1.1 cgd * may be used to endorse or promote products derived from this software 17 1.1 cgd * without specific prior written permission. 18 1.1 cgd * 19 1.1 cgd * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 20 1.1 cgd * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 21 1.1 cgd * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 22 1.1 cgd * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 23 1.1 cgd * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 24 1.1 cgd * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 25 1.1 cgd * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 26 1.1 cgd * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 27 1.1 cgd * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 28 1.1 cgd * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 29 1.1 cgd * SUCH DAMAGE. 30 1.1 cgd */ 31 1.1 cgd 32 1.10 lukem #include <sys/cdefs.h> 33 1.1 cgd #ifndef lint 34 1.7 cgd #if 0 35 1.7 cgd static char sccsid[] = "@(#)io.c 8.1 (Berkeley) 5/31/93"; 36 1.7 cgd #else 37 1.27 dholland __RCSID("$NetBSD: io.c,v 1.27 2012/10/13 20:36:06 dholland Exp $"); 38 1.7 cgd #endif 39 1.1 cgd #endif /* not lint */ 40 1.1 cgd 41 1.7 cgd #include <ctype.h> 42 1.7 cgd #include <curses.h> 43 1.7 cgd #include <signal.h> 44 1.15 wiz #include <stdarg.h> 45 1.7 cgd #include <stdlib.h> 46 1.7 cgd #include <string.h> 47 1.7 cgd #include <termios.h> 48 1.7 cgd #include <unistd.h> 49 1.7 cgd 50 1.7 cgd #include "deck.h" 51 1.7 cgd #include "cribbage.h" 52 1.7 cgd #include "cribcur.h" 53 1.1 cgd 54 1.7 cgd #define LINESIZE 128 55 1.1 cgd 56 1.7 cgd #ifdef CTRL 57 1.7 cgd #undef CTRL 58 1.7 cgd #endif 59 1.7 cgd #define CTRL(X) (X - 'A' + 1) 60 1.6 mycroft 61 1.24 dholland static int msgcrd(CARD, BOOLEAN, const char *, BOOLEAN); 62 1.27 dholland static void printcard(WINDOW *, unsigned, CARD, BOOLEAN); 63 1.24 dholland static int incard(CARD *); 64 1.24 dholland static void wait_for(int); 65 1.24 dholland static int readchar(void); 66 1.6 mycroft 67 1.24 dholland static char linebuf[LINESIZE]; 68 1.24 dholland 69 1.24 dholland static const char *const rankname[RANKS] = { 70 1.7 cgd "ACE", "TWO", "THREE", "FOUR", "FIVE", "SIX", "SEVEN", 71 1.7 cgd "EIGHT", "NINE", "TEN", "JACK", "QUEEN", "KING" 72 1.7 cgd }; 73 1.6 mycroft 74 1.24 dholland static const char *const rankchar[RANKS] = { 75 1.7 cgd "A", "2", "3", "4", "5", "6", "7", "8", "9", "T", "J", "Q", "K" 76 1.7 cgd }; 77 1.6 mycroft 78 1.24 dholland static const char *const suitname[SUITS] = { 79 1.24 dholland "SPADES", "HEARTS", "DIAMONDS", "CLUBS" 80 1.24 dholland }; 81 1.6 mycroft 82 1.24 dholland static const char *const suitchar[SUITS] = {"S", "H", "D", "C"}; 83 1.6 mycroft 84 1.6 mycroft /* 85 1.1 cgd * msgcard: 86 1.1 cgd * Call msgcrd in one of two forms 87 1.1 cgd */ 88 1.7 cgd int 89 1.25 joerg msgcard(CARD c, BOOLEAN brief) 90 1.1 cgd { 91 1.1 cgd if (brief) 92 1.7 cgd return (msgcrd(c, TRUE, NULL, TRUE)); 93 1.1 cgd else 94 1.7 cgd return (msgcrd(c, FALSE, " of ", FALSE)); 95 1.1 cgd } 96 1.1 cgd 97 1.1 cgd /* 98 1.1 cgd * msgcrd: 99 1.1 cgd * Print the value of a card in ascii 100 1.1 cgd */ 101 1.24 dholland static int 102 1.20 jmc msgcrd(CARD c, BOOLEAN brfrank, const char *mid, BOOLEAN brfsuit) 103 1.1 cgd { 104 1.1 cgd if (c.rank == EMPTY || c.suit == EMPTY) 105 1.7 cgd return (FALSE); 106 1.1 cgd if (brfrank) 107 1.7 cgd addmsg("%1.1s", rankchar[c.rank]); 108 1.1 cgd else 109 1.26 joerg addmsg("%s", rankname[c.rank]); 110 1.1 cgd if (mid != NULL) 111 1.26 joerg addmsg("%s", mid); 112 1.1 cgd if (brfsuit) 113 1.7 cgd addmsg("%1.1s", suitchar[c.suit]); 114 1.1 cgd else 115 1.26 joerg addmsg("%s", suitname[c.suit]); 116 1.7 cgd return (TRUE); 117 1.1 cgd } 118 1.1 cgd 119 1.1 cgd /* 120 1.1 cgd * printcard: 121 1.1 cgd * Print out a card. 122 1.1 cgd */ 123 1.24 dholland static void 124 1.27 dholland printcard(WINDOW *win, unsigned cardno, CARD c, BOOLEAN blank) 125 1.1 cgd { 126 1.1 cgd prcard(win, cardno * 2, cardno, c, blank); 127 1.1 cgd } 128 1.1 cgd 129 1.1 cgd /* 130 1.1 cgd * prcard: 131 1.1 cgd * Print out a card on the window at the specified location 132 1.1 cgd */ 133 1.7 cgd void 134 1.20 jmc prcard(WINDOW *win, int y, int x, CARD c, BOOLEAN blank) 135 1.1 cgd { 136 1.1 cgd if (c.rank == EMPTY) 137 1.7 cgd return; 138 1.7 cgd 139 1.1 cgd mvwaddstr(win, y + 0, x, "+-----+"); 140 1.1 cgd mvwaddstr(win, y + 1, x, "| |"); 141 1.1 cgd mvwaddstr(win, y + 2, x, "| |"); 142 1.1 cgd mvwaddstr(win, y + 3, x, "| |"); 143 1.1 cgd mvwaddstr(win, y + 4, x, "+-----+"); 144 1.1 cgd if (!blank) { 145 1.1 cgd mvwaddch(win, y + 1, x + 1, rankchar[c.rank][0]); 146 1.1 cgd waddch(win, suitchar[c.suit][0]); 147 1.1 cgd mvwaddch(win, y + 3, x + 4, rankchar[c.rank][0]); 148 1.1 cgd waddch(win, suitchar[c.suit][0]); 149 1.1 cgd } 150 1.1 cgd } 151 1.1 cgd 152 1.1 cgd /* 153 1.1 cgd * prhand: 154 1.1 cgd * Print a hand of n cards 155 1.1 cgd */ 156 1.7 cgd void 157 1.27 dholland prhand(const CARD h[], unsigned n, WINDOW *win, BOOLEAN blank) 158 1.1 cgd { 159 1.27 dholland unsigned i; 160 1.1 cgd 161 1.1 cgd werase(win); 162 1.1 cgd for (i = 0; i < n; i++) 163 1.7 cgd printcard(win, i, *h++, blank); 164 1.1 cgd wrefresh(win); 165 1.1 cgd } 166 1.1 cgd 167 1.1 cgd /* 168 1.1 cgd * infrom: 169 1.1 cgd * reads a card, supposedly in hand, accepting unambigous brief 170 1.1 cgd * input, returns the index of the card found... 171 1.1 cgd */ 172 1.7 cgd int 173 1.20 jmc infrom(const CARD hand[], int n, const char *prompt) 174 1.1 cgd { 175 1.10 lukem int i, j; 176 1.7 cgd CARD crd; 177 1.1 cgd 178 1.1 cgd if (n < 1) { 179 1.7 cgd printf("\nINFROM: %d = n < 1!!\n", n); 180 1.7 cgd exit(74); 181 1.1 cgd } 182 1.1 cgd for (;;) { 183 1.26 joerg msg("%s", prompt); 184 1.7 cgd if (incard(&crd)) { /* if card is full card */ 185 1.14 jsm if (!is_one(crd, hand, n)) 186 1.7 cgd msg("That's not in your hand"); 187 1.7 cgd else { 188 1.7 cgd for (i = 0; i < n; i++) 189 1.7 cgd if (hand[i].rank == crd.rank && 190 1.7 cgd hand[i].suit == crd.suit) 191 1.7 cgd break; 192 1.7 cgd if (i >= n) { 193 1.14 jsm printf("\nINFROM: is_one or something messed up\n"); 194 1.7 cgd exit(77); 195 1.7 cgd } 196 1.7 cgd return (i); 197 1.7 cgd } 198 1.7 cgd } else /* if not full card... */ 199 1.7 cgd if (crd.rank != EMPTY) { 200 1.7 cgd for (i = 0; i < n; i++) 201 1.7 cgd if (hand[i].rank == crd.rank) 202 1.7 cgd break; 203 1.7 cgd if (i >= n) 204 1.7 cgd msg("No such rank in your hand"); 205 1.7 cgd else { 206 1.7 cgd for (j = i + 1; j < n; j++) 207 1.7 cgd if (hand[j].rank == crd.rank) 208 1.7 cgd break; 209 1.7 cgd if (j < n) 210 1.7 cgd msg("Ambiguous rank"); 211 1.7 cgd else 212 1.7 cgd return (i); 213 1.7 cgd } 214 1.7 cgd } else 215 1.7 cgd msg("Sorry, I missed that"); 216 1.1 cgd } 217 1.1 cgd /* NOTREACHED */ 218 1.1 cgd } 219 1.1 cgd 220 1.1 cgd /* 221 1.1 cgd * incard: 222 1.1 cgd * Inputs a card in any format. It reads a line ending with a CR 223 1.1 cgd * and then parses it. 224 1.1 cgd */ 225 1.24 dholland static int 226 1.20 jmc incard(CARD *crd) 227 1.1 cgd { 228 1.10 lukem int i; 229 1.7 cgd int rnk, sut; 230 1.7 cgd char *line, *p, *p1; 231 1.7 cgd BOOLEAN retval; 232 1.1 cgd 233 1.1 cgd retval = FALSE; 234 1.1 cgd rnk = sut = EMPTY; 235 1.23 roy if (!(line = get_line())) 236 1.1 cgd goto gotit; 237 1.1 cgd p = p1 = line; 238 1.8 pk while (*p1 != ' ' && *p1 != '\0') 239 1.7 cgd ++p1; 240 1.8 pk *p1++ = '\0'; 241 1.8 pk if (*p == '\0') 242 1.7 cgd goto gotit; 243 1.7 cgd 244 1.7 cgd /* IMPORTANT: no real card has 2 char first name */ 245 1.7 cgd if (strlen(p) == 2) { /* check for short form */ 246 1.7 cgd rnk = EMPTY; 247 1.7 cgd for (i = 0; i < RANKS; i++) { 248 1.7 cgd if (*p == *rankchar[i]) { 249 1.7 cgd rnk = i; 250 1.7 cgd break; 251 1.7 cgd } 252 1.1 cgd } 253 1.7 cgd if (rnk == EMPTY) 254 1.7 cgd goto gotit; /* it's nothing... */ 255 1.7 cgd ++p; /* advance to next char */ 256 1.7 cgd sut = EMPTY; 257 1.7 cgd for (i = 0; i < SUITS; i++) { 258 1.7 cgd if (*p == *suitchar[i]) { 259 1.7 cgd sut = i; 260 1.7 cgd break; 261 1.7 cgd } 262 1.1 cgd } 263 1.7 cgd if (sut != EMPTY) 264 1.7 cgd retval = TRUE; 265 1.7 cgd goto gotit; 266 1.1 cgd } 267 1.1 cgd rnk = EMPTY; 268 1.7 cgd for (i = 0; i < RANKS; i++) { 269 1.7 cgd if (!strcmp(p, rankname[i]) || !strcmp(p, rankchar[i])) { 270 1.7 cgd rnk = i; 271 1.7 cgd break; 272 1.7 cgd } 273 1.1 cgd } 274 1.7 cgd if (rnk == EMPTY) 275 1.7 cgd goto gotit; 276 1.1 cgd p = p1; 277 1.8 pk while (*p1 != ' ' && *p1 != '\0') 278 1.7 cgd ++p1; 279 1.8 pk *p1++ = '\0'; 280 1.8 pk if (*p == '\0') 281 1.7 cgd goto gotit; 282 1.7 cgd if (!strcmp("OF", p)) { 283 1.7 cgd p = p1; 284 1.8 pk while (*p1 != ' ' && *p1 != '\0') 285 1.7 cgd ++p1; 286 1.8 pk *p1++ = '\0'; 287 1.8 pk if (*p == '\0') 288 1.7 cgd goto gotit; 289 1.1 cgd } 290 1.1 cgd sut = EMPTY; 291 1.7 cgd for (i = 0; i < SUITS; i++) { 292 1.7 cgd if (!strcmp(p, suitname[i]) || !strcmp(p, suitchar[i])) { 293 1.7 cgd sut = i; 294 1.7 cgd break; 295 1.7 cgd } 296 1.1 cgd } 297 1.7 cgd if (sut != EMPTY) 298 1.7 cgd retval = TRUE; 299 1.1 cgd gotit: 300 1.1 cgd (*crd).rank = rnk; 301 1.1 cgd (*crd).suit = sut; 302 1.7 cgd return (retval); 303 1.1 cgd } 304 1.1 cgd 305 1.1 cgd /* 306 1.1 cgd * getuchar: 307 1.1 cgd * Reads and converts to upper case 308 1.1 cgd */ 309 1.7 cgd int 310 1.20 jmc getuchar(void) 311 1.1 cgd { 312 1.10 lukem int c; 313 1.1 cgd 314 1.1 cgd c = readchar(); 315 1.1 cgd if (islower(c)) 316 1.7 cgd c = toupper(c); 317 1.1 cgd waddch(Msgwin, c); 318 1.7 cgd return (c); 319 1.1 cgd } 320 1.1 cgd 321 1.1 cgd /* 322 1.1 cgd * number: 323 1.1 cgd * Reads in a decimal number and makes sure it is between "lo" and 324 1.1 cgd * "hi" inclusive. 325 1.1 cgd */ 326 1.7 cgd int 327 1.20 jmc number(int lo, int hi, const char *prompt) 328 1.1 cgd { 329 1.10 lukem char *p; 330 1.10 lukem int sum; 331 1.1 cgd 332 1.7 cgd for (sum = 0;;) { 333 1.26 joerg msg("%s", prompt); 334 1.23 roy if (!(p = get_line()) || *p == '\0') { 335 1.7 cgd msg(quiet ? "Not a number" : 336 1.7 cgd "That doesn't look like a number"); 337 1.7 cgd continue; 338 1.1 cgd } 339 1.7 cgd sum = 0; 340 1.1 cgd 341 1.18 dsl if (!isdigit((unsigned char)*p)) 342 1.7 cgd sum = lo - 1; 343 1.7 cgd else 344 1.18 dsl while (isdigit((unsigned char)*p)) { 345 1.7 cgd sum = 10 * sum + (*p - '0'); 346 1.7 cgd ++p; 347 1.7 cgd } 348 1.7 cgd 349 1.8 pk if (*p != ' ' && *p != '\t' && *p != '\0') 350 1.7 cgd sum = lo - 1; 351 1.7 cgd if (sum >= lo && sum <= hi) 352 1.7 cgd break; 353 1.7 cgd if (sum == lo - 1) 354 1.7 cgd msg("that doesn't look like a number, try again --> "); 355 1.7 cgd else 356 1.1 cgd msg("%d is not between %d and %d inclusive, try again --> ", 357 1.7 cgd sum, lo, hi); 358 1.1 cgd } 359 1.7 cgd return (sum); 360 1.1 cgd } 361 1.1 cgd 362 1.1 cgd /* 363 1.7 cgd * msg: 364 1.7 cgd * Display a message at the top of the screen. 365 1.1 cgd */ 366 1.24 dholland static char Msgbuf[BUFSIZ] = {'\0'}; 367 1.24 dholland static int Mpos = 0; 368 1.7 cgd static int Newpos = 0; 369 1.7 cgd 370 1.7 cgd void 371 1.7 cgd msg(const char *fmt, ...) 372 1.1 cgd { 373 1.7 cgd va_list ap; 374 1.1 cgd 375 1.7 cgd va_start(ap, fmt); 376 1.22 dholland (void)vsnprintf(&Msgbuf[Newpos], sizeof(Msgbuf)-Newpos, fmt, ap); 377 1.9 phil Newpos = strlen(Msgbuf); 378 1.7 cgd va_end(ap); 379 1.7 cgd endmsg(); 380 1.1 cgd } 381 1.7 cgd 382 1.7 cgd /* 383 1.7 cgd * addmsg: 384 1.7 cgd * Add things to the current message 385 1.7 cgd */ 386 1.7 cgd void 387 1.7 cgd addmsg(const char *fmt, ...) 388 1.7 cgd { 389 1.7 cgd va_list ap; 390 1.7 cgd 391 1.7 cgd va_start(ap, fmt); 392 1.22 dholland (void)vsnprintf(&Msgbuf[Newpos], sizeof(Msgbuf)-Newpos, fmt, ap); 393 1.9 phil Newpos = strlen(Msgbuf); 394 1.7 cgd va_end(ap); 395 1.7 cgd } 396 1.7 cgd 397 1.7 cgd /* 398 1.7 cgd * endmsg: 399 1.7 cgd * Display a new msg. 400 1.7 cgd */ 401 1.24 dholland static int Lineno = 0; 402 1.7 cgd 403 1.7 cgd void 404 1.20 jmc endmsg(void) 405 1.7 cgd { 406 1.7 cgd static int lastline = 0; 407 1.10 lukem int len; 408 1.10 lukem char *mp, *omp; 409 1.7 cgd 410 1.7 cgd /* All messages should start with uppercase */ 411 1.7 cgd mvaddch(lastline + Y_MSG_START, SCORE_X, ' '); 412 1.18 dsl if (islower((unsigned char)Msgbuf[0]) && Msgbuf[1] != ')') 413 1.18 dsl Msgbuf[0] = toupper((unsigned char)Msgbuf[0]); 414 1.7 cgd mp = Msgbuf; 415 1.7 cgd len = strlen(mp); 416 1.7 cgd if (len / MSG_X + Lineno >= MSG_Y) { 417 1.7 cgd while (Lineno < MSG_Y) { 418 1.7 cgd wmove(Msgwin, Lineno++, 0); 419 1.7 cgd wclrtoeol(Msgwin); 420 1.7 cgd } 421 1.7 cgd Lineno = 0; 422 1.7 cgd } 423 1.7 cgd mvaddch(Lineno + Y_MSG_START, SCORE_X, '*'); 424 1.7 cgd lastline = Lineno; 425 1.7 cgd do { 426 1.7 cgd mvwaddstr(Msgwin, Lineno, 0, mp); 427 1.7 cgd if ((len = strlen(mp)) > MSG_X) { 428 1.7 cgd omp = mp; 429 1.7 cgd for (mp = &mp[MSG_X - 1]; *mp != ' '; mp--) 430 1.7 cgd continue; 431 1.7 cgd while (*mp == ' ') 432 1.7 cgd mp--; 433 1.7 cgd mp++; 434 1.7 cgd wmove(Msgwin, Lineno, mp - omp); 435 1.7 cgd wclrtoeol(Msgwin); 436 1.7 cgd } 437 1.7 cgd if (++Lineno >= MSG_Y) 438 1.7 cgd Lineno = 0; 439 1.7 cgd } while (len > MSG_X); 440 1.7 cgd wclrtoeol(Msgwin); 441 1.7 cgd Mpos = len; 442 1.7 cgd Newpos = 0; 443 1.7 cgd wrefresh(Msgwin); 444 1.7 cgd refresh(); 445 1.7 cgd wrefresh(Msgwin); 446 1.7 cgd } 447 1.1 cgd 448 1.1 cgd /* 449 1.1 cgd * do_wait: 450 1.1 cgd * Wait for the user to type ' ' before doing anything else 451 1.1 cgd */ 452 1.7 cgd void 453 1.20 jmc do_wait(void) 454 1.1 cgd { 455 1.11 jsm static const char prompt[] = {'-', '-', 'M', 'o', 'r', 'e', '-', '-', '\0'}; 456 1.1 cgd 457 1.13 jsm if ((int)(Mpos + sizeof prompt) < MSG_X) 458 1.7 cgd wmove(Msgwin, Lineno > 0 ? Lineno - 1 : MSG_Y - 1, Mpos); 459 1.7 cgd else { 460 1.7 cgd mvwaddch(Msgwin, Lineno, 0, ' '); 461 1.7 cgd wclrtoeol(Msgwin); 462 1.7 cgd if (++Lineno >= MSG_Y) 463 1.7 cgd Lineno = 0; 464 1.7 cgd } 465 1.7 cgd waddstr(Msgwin, prompt); 466 1.7 cgd wrefresh(Msgwin); 467 1.7 cgd wait_for(' '); 468 1.1 cgd } 469 1.1 cgd 470 1.1 cgd /* 471 1.1 cgd * wait_for 472 1.1 cgd * Sit around until the guy types the right key 473 1.1 cgd */ 474 1.24 dholland static void 475 1.20 jmc wait_for(int ch) 476 1.1 cgd { 477 1.19 rillig int c; 478 1.1 cgd 479 1.7 cgd if (ch == '\n') 480 1.7 cgd while ((c = readchar()) != '\n') 481 1.7 cgd continue; 482 1.7 cgd else 483 1.7 cgd while (readchar() != ch) 484 1.7 cgd continue; 485 1.1 cgd } 486 1.1 cgd 487 1.1 cgd /* 488 1.1 cgd * readchar: 489 1.1 cgd * Reads and returns a character, checking for gross input errors 490 1.1 cgd */ 491 1.24 dholland static int 492 1.20 jmc readchar(void) 493 1.1 cgd { 494 1.10 lukem int cnt; 495 1.19 rillig unsigned char c; 496 1.1 cgd 497 1.1 cgd over: 498 1.7 cgd cnt = 0; 499 1.19 rillig while (read(STDIN_FILENO, &c, sizeof(unsigned char)) <= 0) 500 1.7 cgd if (cnt++ > 100) { /* if we are getting infinite EOFs */ 501 1.7 cgd bye(); /* quit the game */ 502 1.7 cgd exit(1); 503 1.7 cgd } 504 1.7 cgd if (c == CTRL('L')) { 505 1.7 cgd wrefresh(curscr); 506 1.7 cgd goto over; 507 1.7 cgd } 508 1.7 cgd if (c == '\r') 509 1.7 cgd return ('\n'); 510 1.7 cgd else 511 1.7 cgd return (c); 512 1.1 cgd } 513 1.1 cgd 514 1.1 cgd /* 515 1.23 roy * get_line: 516 1.1 cgd * Reads the next line up to '\n' or EOF. Multiple spaces are 517 1.1 cgd * compressed to one space; a space is inserted before a ',' 518 1.1 cgd */ 519 1.1 cgd char * 520 1.23 roy get_line(void) 521 1.1 cgd { 522 1.27 dholland size_t pos; 523 1.10 lukem int c, oy, ox; 524 1.10 lukem WINDOW *oscr; 525 1.7 cgd 526 1.7 cgd oscr = stdscr; 527 1.7 cgd stdscr = Msgwin; 528 1.7 cgd getyx(stdscr, oy, ox); 529 1.7 cgd refresh(); 530 1.7 cgd /* loop reading in the string, and put it in a temporary buffer */ 531 1.27 dholland for (pos = 0; (c = readchar()) != '\n'; clrtoeol(), refresh()) { 532 1.7 cgd if (c == erasechar()) { /* process erase character */ 533 1.27 dholland if (pos > 0) { 534 1.10 lukem int i; 535 1.7 cgd 536 1.27 dholland pos--; 537 1.27 dholland for (i = strlen(unctrl(linebuf[pos])); i; i--) 538 1.7 cgd addch('\b'); 539 1.7 cgd } 540 1.7 cgd continue; 541 1.7 cgd } else 542 1.7 cgd if (c == killchar()) { /* process kill 543 1.7 cgd * character */ 544 1.27 dholland pos = 0; 545 1.7 cgd move(oy, ox); 546 1.7 cgd continue; 547 1.7 cgd } else 548 1.27 dholland if (pos == 0 && c == ' ') 549 1.7 cgd continue; 550 1.27 dholland if (pos >= LINESIZE - 1 || !(isprint(c) || c == ' ')) 551 1.7 cgd putchar(CTRL('G')); 552 1.7 cgd else { 553 1.7 cgd if (islower(c)) 554 1.7 cgd c = toupper(c); 555 1.27 dholland linebuf[pos++] = c; 556 1.7 cgd addstr(unctrl(c)); 557 1.7 cgd Mpos++; 558 1.7 cgd } 559 1.1 cgd } 560 1.27 dholland linebuf[pos] = '\0'; 561 1.7 cgd stdscr = oscr; 562 1.7 cgd return (linebuf); 563 1.1 cgd } 564 1.1 cgd 565 1.7 cgd void 566 1.21 perry receive_intr(int signo __unused) 567 1.1 cgd { 568 1.1 cgd bye(); 569 1.1 cgd exit(1); 570 1.1 cgd } 571 1.1 cgd 572 1.1 cgd /* 573 1.1 cgd * bye: 574 1.1 cgd * Leave the program, cleaning things up as we go. 575 1.1 cgd */ 576 1.7 cgd void 577 1.20 jmc bye(void) 578 1.1 cgd { 579 1.1 cgd signal(SIGINT, SIG_IGN); 580 1.1 cgd mvcur(0, COLS - 1, LINES - 1, 0); 581 1.1 cgd fflush(stdout); 582 1.1 cgd endwin(); 583 1.1 cgd putchar('\n'); 584 1.1 cgd } 585