/* $Id: w3mimgdisplay.c,v 1.1.4.22 2002/11/05 12:44:36 suto Exp $ */
#include "w3mimg/w3mimg.h"
#include "w3mimgdisplay.h"

w3mimg_opts w3mimg_stdopts;
w3mimg_desc w3mimg_stddesc;
w3mimg_line w3mimg_stdline;

static void ClearImageAndExit(void);
static MySignalHandler ExitBySignal(SIGNAL_ARG);

int
main(int argc, char **argv)
{
  struct timeval itv, *p_itv;
  fd_set fds, wfds;
  int nfd, n;
  W3MImage img;

  w3mimg_get_option(argc, argv, &w3mimg_stddesc, &w3mimg_stdopts);

  if (!w3mimg_open(&w3mimg_stddesc, &w3mimg_stdopts)) {
    if (errno)
      w3mimg_exit(1, stderr, "w3mimg_open(): %s\n", strerror(errno));
    else
      exit(0);
  }

  if (w3mimg_stdopts.defined_test)
    w3mimg_exit(0, stdout, "%d;%d;\n",
	   w3mimg_stddesc.width - w3mimg_stddesc.offset_x,
	   w3mimg_stddesc.height - w3mimg_stddesc.offset_y);

  if (!w3mimg_stddesc.flush_delay)
    w3mimg_stddesc.flush_delay = 1 + w3mimg_stddesc.width * w3mimg_stddesc.height / (1024 * 768);

  FD_ZERO(&fds);
  FD_ZERO(&wfds);
  w3mimg_stddesc.stdin_fd = fileno(stdin);
  nfd = w3mimg_stddesc.stdin_fd > w3mimg_stddesc.serv_fd ? w3mimg_stddesc.stdin_fd + 1 : w3mimg_stddesc.serv_fd + 1;
  signal(SIGHUP, ExitBySignal);
  signal(SIGTERM, ExitBySignal);
  signal(SIGINT, SIG_IGN);
  signal(SIGQUIT, SIG_IGN);

  for (;;) {
    if (w3mimg_stddesc.serv_idle) {
#if CLOCKS_PER_SEC > 1
      itv.tv_usec = 1000000 / CLOCKS_PER_SEC;
      itv.tv_sec = 0;
#else
      itv.tv_usec = 10000;
      itv.tv_sec = 0;
#endif
      p_itv = &itv;
    }
    else
      p_itv = NULL;

    FD_SET(w3mimg_stddesc.stdin_fd, &fds);

    if (w3mimg_stddesc.serv_fd >= 0) {
      if (w3mimg_stddesc.serv_read)
	FD_SET(w3mimg_stddesc.serv_fd, &fds);

      if (w3mimg_stddesc.serv_write && w3mimg_stddesc.flush_dirty)
	FD_SET(w3mimg_stddesc.serv_fd, &wfds);
      else
	FD_CLR(w3mimg_stddesc.serv_fd, &wfds);
    }

    if ((n = select(nfd, &fds, &wfds, NULL, p_itv)) > 0) {
      if (w3mimg_stddesc.serv_fd >= 0) {
	if (FD_ISSET(w3mimg_stddesc.serv_fd, &wfds))
	  w3mimg_stddesc.serv_write(&w3mimg_stddesc);

	if (FD_ISSET(w3mimg_stddesc.serv_fd, &fds))
	  w3mimg_stddesc.serv_read(&w3mimg_stddesc);
      }

      if (FD_ISSET(w3mimg_stddesc.stdin_fd, &fds)) {
	int doread = 1, eof = 0;
      line_processing:
	switch (w3mimg_gets(&w3mimg_stddesc, &w3mimg_stdline, doread)) {
	case w3mimg_line_eof:
	  eof = 1;
	case w3mimg_line_eol:
	  if (w3mimg_stdline.n > 1 && w3mimg_stdline.v[1] == ';')
	    switch (w3mimg_stdline.v[0] - '0') {
	    case IMGDISPLAY_DRAW:
	      w3mimg_draw(&w3mimg_stddesc, &w3mimg_stdline.v[2]);
	      break;
	    case IMGDISPLAY_CLIP:
	      if (w3mimg_stddesc.clip_func)
		w3mimg_stddesc.clip_func(&w3mimg_stddesc, &w3mimg_stdline.v[2]);

	      break;
	    case IMGDISPLAY_CLEAR:
	      w3mimg_clear(&w3mimg_stddesc);
	      break;
	    case IMGDISPLAY_XSYNC:
	      w3mimg_stddesc.serv_sync(&w3mimg_stddesc);
	      break;
	    case IMGDISPLAY_CLRIMG:
	      w3mimg_clear_one(&w3mimg_stdline.v[2]);
	      break;
	    case IMGDISPLAY_SIZE:
	      w3mimg_stddesc.init_func(&w3mimg_stddesc);

	      if (!w3mimg_stddesc.priv) {
		if (errno)
		  w3mimg_exit(1, stderr, "w3mimg_stddesc.init_func(): %s\n", strerror(errno));
		else
		  exit(0);
	      }

	      memset(&img, 0, sizeof(img));
	      w3mimg_stddesc.load_func(&w3mimg_stddesc, &img, &w3mimg_stdline.v[2], -1, -1);

	      if (img.pixmap) {
		printf("%d %d\n", img.width, img.height);
		w3mimg_stddesc.free_func(&w3mimg_stddesc, &img);
	      }
	      else
		putchar('\n');

	      fflush(stdout);
	      break;
	    default:
	      putchar(w3mimg_stdline.v[0]);
	      putchar('\n');
	      fflush(stdout);
	      break;
	    }

	  if (eof)
	    goto end;

	  w3mimg_stdline.n = 0;
	  doread = 0;
	  goto line_processing;
	default:
	  break;
	}
      }
    }
    else if (!n) {
      if (w3mimg_stddesc.serv_idle && !w3mimg_stddesc.flush_dirty)
	w3mimg_stddesc.serv_idle(&w3mimg_stddesc);
    }
    else if (errno != EINTR)
      w3mimg_exit(1, stderr, "select(): %s\n", strerror(errno));
  }
end:
  ClearImageAndExit();
  return 0;
}

void
ClearImageAndExit(void)
{
  signal(SIGHUP, SIG_IGN);
  w3mimg_clear(&w3mimg_stddesc);

  if (w3mimg_stddesc.serv_close)
    w3mimg_stddesc.serv_close(&w3mimg_stddesc);

  exit(0);
}

MySignalHandler
ExitBySignal(SIGNAL_ARG)
{
  ClearImageAndExit();
  SIGNAL_RETURN;
}
