text: /*
   *  newdemo.c	-	A demo program using PDCurses. The program illustrate
   *  	 		the use of colours for text output.
   *
   * $Id: newdemo.c,v 1.36 2012/06/09 19:17:29 tom Exp $
   */
  
  #include <test.priv.h>
  
  #include <time.h>
  
  /*
   *  The Australian map
   */
  static CONST_MENUS char *AusMap[16] =
  {
      "           A           A ",
      "    N.T. AAAAA       AAAA ",
      "     AAAAAAAAAAA  AAAAAAAA ",
      "   AAAAAAAAAAAAAAAAAAAAAAAAA Qld.",
      "AAAAAAAAAAAAAAAAAAAAAAAAAAAAA ",
      "AAAAAAAAAAAAAAAAAAAAAAAAAAAAAA ",
      " AAAAAAAAAAAAAAAAAAAAAAAAAAAA ",
      "   AAAAAAAAAAAAAAAAAAAAAAAAA N.S.W.",
      "W.A. AAAAAAAAA      AAAAAA Vic.",
      "       AAA   S.A.     AA",
      "                       A  Tas.",
      ""
  };
  
  /*
   *  Funny messages
   */
  #define NMESSAGES   6
  
  static const char *messages[] =
  {
      "Hello from the Land Down Under",
      "The Land of crocs. and a big Red Rock",
      "Where the sunflower runs along the highways",
      "the dusty red roads lead one to loneliness",
      "Blue sky in the morning and",
      "freezing nights and twinkling stars",
      ""
  };
  
  /*
   *  Trap interrupt
   */
  static RETSIGTYPE
  trap(int sig GCC_UNUSED)
  {
      endwin();
      ExitProgram(EXIT_FAILURE);
  }
  
  /*
   *  Wait for user
   */
  static int
  WaitForUser(WINDOW *win)
  {
      time_t t;
      chtype key;
  
      nodelay(win, TRUE);
      t = time((time_t *) 0);
      while (1) {
  	if ((int) (key = (chtype) wgetch(win)) != ERR) {
  	    if (key == 'q' || key == 'Q')
  		return 1;
  	    else
  		return 0;
  	}
  	if (time((time_t *) 0) - t > 5)
  	    return 0;
      }
  }
  
  static void
  set_colors(WINDOW *win, int pair, int foreground, int background)
  {
      if (has_colors()) {
  	if (pair > COLOR_PAIRS)
  	    pair = COLOR_PAIRS;
  	init_pair((short) pair, (short) foreground, (short) background);
  	(void) wattrset(win, (int) COLOR_PAIR(pair));
      }
  }
  
  static chtype
  use_colors(WINDOW *win, int pair, chtype attrs)
  {
      if (has_colors()) {
  	if (pair > COLOR_PAIRS)
  	    pair = COLOR_PAIRS;
  	attrs |= (chtype) COLOR_PAIR(pair);
      }
      (void) wattrset(win, (int) attrs);
      return attrs;
  }
  
  /*
   * Test sub windows
   */
  static int
  SubWinTest(WINDOW *win)
  {
      int w, h, sw, sh, bx, by;
      WINDOW *swin1, *swin2, *swin3;
  
      getmaxyx(win, h, w);
      getbegyx(win, by, bx);
      sw = w / 3;
      sh = h / 3;
      if ((swin1 = subwin(win, sh, sw, by + 3, bx + 5)) == NULL)
  	return 1;
      if ((swin2 = subwin(win, sh, sw, by + 4, bx + 8)) == NULL)
  	return 1;
      if ((swin3 = subwin(win, sh, sw, by + 5, bx + 11)) == NULL)
  	return 1;
  
      set_colors(swin1, 8, COLOR_RED, COLOR_BLUE);
      werase(swin1);
      MvWAddStr(swin1, 0, 3, "Sub-window 1");
      wrefresh(swin1);
  
      set_colors(swin2, 9, COLOR_CYAN, COLOR_MAGENTA);
      werase(swin2);
      MvWAddStr(swin2, 0, 3, "Sub-window 2");
      wrefresh(swin2);
  
      set_colors(swin3, 10, COLOR_YELLOW, COLOR_GREEN);
      werase(swin3);
      MvWAddStr(swin3, 0, 3, "Sub-window 3");
      wrefresh(swin3);
  
      delwin(swin1);
      delwin(swin2);
      delwin(swin3);
      WaitForUser(win);
      return 0;
  }
  
  static int
  bounce(int n, int *dir, int len)
  {
      if (*dir > 0)
  	++n;
      else
  	--n;
      if (n <= 1 || n >= len - 2)
  	*dir = *dir ? 0 : 1;
      return n;
  }
  
  /*
   *  Bouncing balls
   */
  static int
  BouncingBalls(WINDOW *win)
  {
      int w, h;
      int x1, y1, xd1, yd1;
      int x2, y2, xd2, yd2;
      int x3, y3, xd3, yd3;
  
      getmaxyx(win, h, w);
  
      x1 = 2 + rand() % (w - 4);
      y1 = 2 + rand() % (h - 4);
      x2 = 2 + rand() % (w - 4);
      y2 = 2 + rand() % (h - 4);
      x3 = 2 + rand() % (w - 4);
      y3 = 2 + rand() % (h - 4);
  
      xd1 = 1;
      yd1 = 1;
      xd2 = 1;
      yd2 = 0;
      xd3 = 0;
      yd3 = 1;
  
      nodelay(win, TRUE);
  
      while (wgetch(win) == ERR) {
  	x1 = bounce(x1, &xd1, w);
  	y1 = bounce(y1, &yd1, h);
  	x2 = bounce(x2, &xd2, w);
  	y2 = bounce(y2, &yd2, h);
  	x3 = bounce(x3, &xd3, w);
  	y3 = bounce(y3, &yd3, h);
  
  	set_colors(win, 11, COLOR_RED, COLOR_BLUE);
  	MvWAddCh(win, y1, x1, 'O');
  
  	set_colors(win, 12, COLOR_BLUE, COLOR_RED);
  	MvWAddCh(win, y2, x2, '*');
  
  	set_colors(win, 13, COLOR_YELLOW, COLOR_WHITE);
  	MvWAddCh(win, y3, x3, '@');
  
  	wmove(win, 0, 0);
  	wrefresh(win);
  	delay_output(100);
      }
      return 0;
  }
  
  /*
   *  Main driver
   */
  int
  main(int argc GCC_UNUSED, char *argv[]GCC_UNUSED)
  {
      WINDOW *win;
      int w, x, y, i, j, k;
      char buffer[200];
      const char *message;
      int width, height;
      chtype save[80];
      chtype c;
  
      setlocale(LC_ALL, "");
  
      CATCHALL(trap);
  
      initscr();
      if (has_colors())
  	start_color();
      cbreak();
      curs_set(0);
      width = 48;
      height = 14;		/* Create a drawing window */
      win = newwin(height, width, (LINES - height) / 2, (COLS - width) / 2);
      if (win == NULL) {
  	endwin();
  	ExitProgram(EXIT_FAILURE);
      }
  
      while (1) {
  	set_colors(win, 1, COLOR_WHITE, COLOR_BLUE);
  	werase(win);
  
  	set_colors(win, 2, COLOR_RED, COLOR_RED);
  	box(win, ACS_VLINE, ACS_HLINE);
  	wrefresh(win);
  	/* Do ramdom output of a character */
  	use_colors(win, 1, A_NORMAL);
  	c = 'a';
  	for (i = 0; i < 5000; ++i) {
  	    x = rand() % (width - 2) + 1;
  	    y = rand() % (height - 2) + 1;
  	    MvWAddCh(win, y, x, c);
  	    wrefresh(win);
  	    nodelay(win, TRUE);
  	    if (wgetch(win) != ERR)
  		break;
  	    if (i == 2000) {
  		c = 'b';
  		set_colors(win, 3, COLOR_CYAN, COLOR_YELLOW);
  	    }
  	}
  
  	SubWinTest(win);
  	/* Erase and draw green window */
  	set_colors(win, 4, COLOR_YELLOW, COLOR_GREEN);
  	wbkgd(win, use_colors(win, 4, A_BOLD));
  	werase(win);
  	wrefresh(win);
  	/* Draw RED bounding box */
  	use_colors(win, 2, A_NORMAL);
  	box(win, ' ', ' ');
  	wrefresh(win);
  	/* Display Australia map */
  	use_colors(win, 4, A_BOLD);
  	i = 0;
  	while (*AusMap[i]) {
  	    MvWAddStr(win, i + 1, 8, AusMap[i]);
  	    wrefresh(win);
  	    delay_output(50);
  	    ++i;
  	}
  
  	set_colors(win, 5, COLOR_BLUE, COLOR_WHITE);
  	use_colors(win, 5, A_BLINK);
  	MvWAddStr(win, height - 2, 6, " PDCurses 2.1 for DOS, OS/2 and Unix");
  	wrefresh(win);
  
  	/* Draw running messages */
  	set_colors(win, 6, COLOR_YELLOW, COLOR_WHITE);
  	message = messages[j = 0];
  	i = 1;
  	w = width - 2;
  	strcpy(buffer, message);
  	while (j < NMESSAGES) {
  	    while ((int) strlen(buffer) < w) {
  		strcat(buffer, " ... ");
  		strcat(buffer, messages[++j % NMESSAGES]);
  	    }
  
  	    if (i < w)
  		(void) mvwaddnstr(win, height / 2, w - i, buffer, i);
  	    else
  		(void) mvwaddnstr(win, height / 2, 1, buffer, w);
  
  	    wrefresh(win);
  	    nodelay(win, TRUE);
  	    if (wgetch(win) != ERR) {
  		flushinp();
  		break;
  	    }
  	    if (i++ >= w) {
  		for (k = 0; (buffer[k] = buffer[k + 1]) != '\0'; k++) ;
  	    }
  	    delay_output(100);
  	}
  
  	j = 0;
  	/*  Draw running As across in RED */
  	set_colors(win, 7, COLOR_RED, COLOR_GREEN);
  	memset(save, ' ', sizeof(save));
  	for (i = 2; i < width - 4; ++i) {
  	    k = (int) mvwinch(win, 4, i);
  	    if (k == ERR)
  		break;
  	    save[j++] = c = (chtype) k;
  	    c &= A_CHARTEXT;
  	    MvWAddCh(win, 4, i, c);
  	}
  	wrefresh(win);
  
  	/* Put a message up wait for a key */
  	i = height - 2;
  	use_colors(win, 5, A_NORMAL);
  	MvWAddStr(win, i, 5, " Type a key to continue or 'Q' to quit ");
  	wrefresh(win);
  
  	if (WaitForUser(win) == 1)
  	    break;
  
  	j = 0;			/* Restore the old line */
  	for (i = 2; i < width - 4; ++i)
  	    MvWAddCh(win, 4, i, save[j++]);
  	wrefresh(win);
  
  	BouncingBalls(win);
  	/* Put a message up wait for a key */
  	i = height - 2;
  	use_colors(win, 5, A_NORMAL);
  	MvWAddStr(win, i, 5, " Type a key to continue or 'Q' to quit ");
  	wrefresh(win);
  	if (WaitForUser(win) == 1)
  	    break;
      }
      endwin();
      ExitProgram(EXIT_SUCCESS);
  }
  