Logo Search packages:      
Sourcecode: yics version File versions  Download package

console.c

/*
 * YICS: Connect a FICS interface to the Yahoo! Chess server.
 * Copyright (C) 2004  Chris Howie
 *
 * This program is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License as published by the Free
 * Software Foundation; either version 2 of the License, or (at your option)
 * any later version.
 *
 * This program is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 * more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */

#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>

#include "platform.h"

#if defined(_YICS_WIN32)
#  include <io.h>
#  include <conio.h>
#  include <time.h>
#  include <windows.h>
#  include <process.h>
static int isatty_stdin_cache = -1;
#elif defined(_YICS_POSIX)
#  include <sys/time.h>
#  include <sys/types.h>
#  include <unistd.h>
#endif

#include "types.h"
#include "console.h"
#include "network.h"
#include "debug.h"
#include "globals.h"
#include "vars.h"
#include "lists.h"

static short width_out = 0;
static char buffer_out[100] = "";

bool prompting = false;

void internal_iprint(const char *text, bool system) {
      char *nl;
      char *buf = buffer_out;

      nl = system ? "" : "\\   ";

      while (*buf)
            buf++;

      while (*text) {
            *(buf++) = *text;
            *buf = '\0';
            width_out++;
            if (*text == '\n') {
                  width_out = 0;
                  printf("%s\r", buffer_out);
                  buffer_out[0] = '\0';
                  buf = buffer_out;
            } else if (width_out >= 80) {
                  width_out = (short)(strlen(nl) + strlen(buffer_out));
                  printf("\n\r%s", nl);
            } else if (*text == ' ') {
                  printf("%s", buffer_out);
                  buffer_out[0] = '\0';
                  buf = buffer_out;
            }
            text++;
      }

      if (system)
            fflush(stdout);
}

void iprintf(const char *text, ...) {
      va_list ap;

      va_start(ap, text);
      vsprintf(s_buffer, text, ap);
      va_end(ap);

      internal_iprint(s_buffer, false);
}

void sysiprintf(const char *text, ...) {
      va_list ap;

      va_start(ap, text);
      vsprintf(s_buffer, text, ap);
      va_end(ap);

      internal_iprint(s_buffer, true);
}

void prompt() {
      time_t t;
      struct tm *tv;

      if (prompting) {
            if (variables[VAR_PTIME].number) {
                  t = time(NULL);
                  tv = localtime(&t);
                  printf("%02d:%02d_", tv->tm_hour, tv->tm_min);
            }
            printf("fics%% ");
      }
      fflush(stdout);
}

#if defined(_YICS_WIN32)
struct keyb {
      int head, tail;
      int keys[0x100];
} keycom = { 0, 0 };

void keyfetchthread (void * parm) {
      struct keyb * keycom = (struct keyb *)parm;
      int ret;

      printf ("Key thread started\n");

      for (;;) {
            if (!isatty_stdin_cache) {
                  ret = getc (stdin);
            } else {
                  ret = getche ();
            }
            if (ret == 4) /* ^D ? */
                  ret = -1;

            if (((keycom->head+1) & 0xff) == (keycom->tail & 0xff)) continue;

            keycom->keys[keycom->head & 0xff] = ret;
            keycom->head++;
      }
}

int keyget (struct keyb * keycom) {
      int key, c = 10;
      while (keycom->head == keycom->tail) {
            Sleep (c);
            c += c;
            if (c > 200) c = 200;
      }

      key = keycom->keys[keycom->tail & 0xff];
      keycom->tail++;
      return key;
}

int keyready (struct keyb * keycom) {
      return keycom->head != keycom->tail;
}

void keyinit (struct keyb * keycom) {
      _beginthread (keyfetchthread, 1024, (void *) keycom);
}
#endif

#define DELAY (1000)

bool stdin_ready() {
#if defined(_YICS_WIN32)
      clock_t curr, timeout;

      if (isatty_stdin_cache == -1) {
            isatty_stdin_cache = isatty(fileno(stdin)) != 0;
            keyinit (&keycom);
      }

      /* if (!isatty_stdin_cache) return true; */
      timeout = clock() + (clock_t)((CLOCKS_PER_SEC * DELAY) / 1000000.0);
      do {
            if (keyready (&keycom)) return true;
            curr = clock();
      } while ((int)(timeout - curr) > 0);
#elif defined(_YICS_POSIX)
      fd_set sl;
      struct timeval tv;

      FD_ZERO(&sl);
      FD_SET(0, &sl);
      tv.tv_sec = 0;
      tv.tv_usec = DELAY;

      if (select(1, &sl, NULL, NULL, &tv))
            return true;
#endif
      return false;
}     

bool stdin_getchar(char *c) {
      int ret;
#if defined(_YICS_WIN32)
      if (isatty_stdin_cache == -1) {
            isatty_stdin_cache = isatty(fileno(stdin)) != 0;
            keyinit (&keycom);
      }

      ret = keyget (&keycom);
      if (ret < 0)
            return false;

      if (ret == '\r') {
            ret = '\n';
            printf("\n");
      }
      *c = (char)ret;
#elif defined(_YICS_POSIX)
      ret = read(0, c, 1);
      if (ret != 1)
            return false;
#endif
      return true;
}

void die(char *err) {
      int i;
      List *list;
      Variable *var;

      if (err[0] != '\0')
            printf("ERROR: %s\n", err);

      /* clean up everything */
      for (i = 0; i < TABLE_MAX; i++) {
            if (tables[i] != NULL) {
                  destroyOptions(tables[i]->options);
                  free(tables[i]);
                  tables[i] = NULL;
            }
      }

      for (i = 0; i < PLAYER_MAX; i++) {
            if (players[i] != NULL) {
                  free(players[i]->handle);
                  free(players[i]->lhandle);
                  if (players[i] == pme)
                        pme = NULL;
                  players[i] = NULL;
            }
      }

      for (list = lists; list->name != NULL; list++) {
            for (i = 0; i < list->size; i++)
                  free(list->contents[i]);
            free(list->contents);
            list->contents = NULL;
      }

      for (var = variables; var->type != VAR_END; var++)
            if (var->string != NULL)
                  StringFree(var->string);

      if (pme != NULL) {
            free(pme->handle);
            free(pme->lhandle);
            free(pme);
            pme = NULL;
      }

      destroyOptions(clientOptions);
      clientOptions = NULL;
      destroyInvite();

#if MEMDEBUG
      if (string_count != 0) {
            printf("WARNING: Memory leak detected while cleaning up!  "
                   "There are %d Strings still allocated.\n",
                   string_count);
      }

      if (option_count != 0) {
            printf("WARNING: Memory leak detected while cleaning up!  "
                   "There are %d Options still allocated.\n",
                   option_count);
      }

      if ((string_count == 0) && (option_count == 0))
            printf("No memory leaks detected!\n");
#endif

      nclose();
      exit(1);
}

void dief(char *err, ...) {
      va_list ap;

      va_start(ap, err);
      vsprintf(s_buffer, err, ap);
      va_end(ap);

      die(s_buffer);
}

#ifdef _YICS_POSIX
/*
 * Mixing stdio functions (e.g. fgets) with unistd functions (e.g. read)
 * causes problems when mixing them on continuous input (e.g. WinBoard/xboard
 * -icslogon parameter).  So we provide our own fgets that uses unistd.
 */
char *mfgets(char *s, int size, FILE *stream) {
      int i = 0;
      int fd = fileno(stream);
      char *si = s;

      /* Leave room for the null. */
      size--;

      while (i < size) {
            if (read(fd, si, 1) < 1)
                  break;

            i++;
            if ((*(si++) == '\n') || (*si == '\r'))
                  break;
      }

      *si = '\0';

      if ((i == 0) && (size < 0))
            return NULL;

      return s;
}
#endif

Generated by  Doxygen 1.6.0   Back to index