home *** CD-ROM | disk | FTP | other *** search
/ ftp.wwiv.com / ftp.wwiv.com.zip / ftp.wwiv.com / pub / BBS / DOORL093.ZIP / doorlib-0.9.3.tar.bz2 / doorlib-0.9.3.tar / doorlib-0.9.3 / src / input.c < prev    next >
C/C++ Source or Header  |  2003-12-21  |  10KB  |  495 lines

  1. /*****************************************************************************
  2.  *
  3.  * $Id: input.c,v 1.5 2003/12/21 13:04:15 mbroek Exp $
  4.  * Purpose ...............: Input functions.
  5.  *
  6.  *****************************************************************************
  7.  * Copyright (C) 2003
  8.  *   
  9.  * Michiel Broek        FIDO:        2:280/2802
  10.  * Beekmansbos 10
  11.  * 1971 BV IJmuiden
  12.  * the Netherlands
  13.  *
  14.  * This file is part of doorlib for Unix.
  15.  *
  16.  * This BBS is free software; you can redistribute it and/or modify it
  17.  * under the terms of the GNU General Public License as published by the
  18.  * Free Software Foundation; either version 2, or (at your option) any
  19.  * later version.
  20.  *
  21.  * MBSE BBS is distributed in the hope that it will be useful, but
  22.  * WITHOUT ANY WARRANTY; without even the implied warranty of
  23.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  24.  * General Public License for more details.
  25.  * 
  26.  * You should have received a copy of the GNU General Public License
  27.  * along with MBSE BBS; see the file COPYING.  If not, write to the Free
  28.  * Software Foundation, 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  29.  *****************************************************************************/
  30.  
  31. #include "../config.h"
  32. #include "door.h"
  33.  
  34.  
  35. int rawset = FALSE;
  36.  
  37. extern time_t    game_over;
  38. time_t        time2go = 0;
  39.  
  40.  
  41. /*
  42.  * internal prototypes
  43.  */
  44. void        doorsetraw(void);
  45. void        door_unsetraw(void);
  46. int        Waitchar(unsigned char *, int);
  47. int        Escapechar(unsigned char *);
  48. unsigned char    Readkey(void);
  49.  
  50.  
  51. /*
  52.  * Sets raw mode and saves the terminal setup
  53.  */
  54. void door_setraw(void)
  55. {
  56.     int        rc;
  57.  
  58.     if ((rc = tcgetattr(ttyfd, &tbufs))) {
  59.     perror("");
  60.     fprintf(stderr, "tcgetattr(0, save) return %d\n", rc);
  61.     exit(101);
  62.     }
  63.  
  64.     tbufsavs = tbufs;
  65.     tbufs.c_iflag &= ~(INLCR | ICRNL | ISTRIP | IXON  ); /* IUCLC removed for FreeBSD */
  66.     /*
  67.      *  Map CRNL modes strip control characters and flow control
  68.      */
  69.     tbufs.c_oflag &= ~OPOST;            /* Don't do ouput character translation */
  70.     tbufs.c_lflag &= ~(ICANON | ECHO);  /* No canonical input and no echo       */
  71.     tbufs.c_cc[VMIN] = 1;               /* Receive 1 character at a time        */
  72.     tbufs.c_cc[VTIME] = 0;              /* No time limit per character          */
  73.     
  74.     if ((rc = tcsetattr(ttyfd, TCSADRAIN, &tbufs))) {
  75.     perror("");
  76.     fprintf(stderr, "tcsetattr(%d, TCSADRAIN, raw) return %d\n", ttyfd, rc);
  77.     exit(101);
  78.     }
  79.  
  80.     rawset = TRUE;
  81. }
  82.  
  83.  
  84.  
  85. /*
  86.  * Unsets raw mode and returns state of terminal
  87.  */
  88. void door_unsetraw()
  89. {
  90.     int        rc;
  91.  
  92.     /*
  93.      * Only unset the mode if it is set to raw mode
  94.      */
  95.     if (rawset == TRUE) {
  96.     if ((rc = tcsetattr(ttyfd, TCSAFLUSH, &tbufsavs))) {
  97.         perror("");
  98.         fprintf(stderr, "tcsetattr(%d, TCSAFLUSH, save) return %d\n", ttyfd, rc);
  99.         exit(101);
  100.     }
  101.     }
  102.     rawset = FALSE;
  103. }
  104.  
  105.  
  106.  
  107. /* 
  108.  * This function is used to get a single character from a user ie for a 
  109.  * menu option
  110.  */
  111. unsigned char door_getch(void)
  112. {
  113.     unsigned char   c = 0;
  114.     
  115.     if ((ttyfd = open ("/dev/tty", O_RDWR|O_NONBLOCK)) < 0) {
  116.     perror("door_getch");
  117.     exit(101);
  118.     }
  119.     door_setraw();
  120.  
  121.     c = Readkey();
  122.  
  123.     door_unsetraw();
  124.     close(ttyfd);
  125.     return(c);
  126. }
  127.  
  128.  
  129.  
  130. /*
  131.  *  Wait for a character for a maximum of wtime * 10 mSec.
  132.  */
  133. int Waitchar(unsigned char *ch, int wtime)
  134. {
  135.     int     i, rc = -1;
  136.  
  137.     for (i = 0; i < wtime; i++) {
  138.     rc = read(ttyfd, ch, 1);
  139.     if (rc == 1)
  140.         return rc;
  141.     usleep(10000);
  142.     }
  143.     return rc;
  144. }
  145.  
  146.  
  147.  
  148. int Escapechar(unsigned char *ch)
  149. {
  150.     int             rc;
  151.     unsigned char   c;
  152.                     
  153.     /* 
  154.      * Escape character, if nothing follows within 
  155.      * 50 mSec, the user really pressed <esc>.
  156.      */
  157.     if ((rc = Waitchar(ch, 5)) == -1)
  158.     return rc;
  159.  
  160.     if (*ch == '[') {
  161.     /*
  162.          *  Start of CSI sequence. If nothing follows,
  163.      *  return immediatly.
  164.      */
  165.     if ((rc = Waitchar(ch, 5)) == -1)
  166.         return rc;
  167.  
  168.     /*
  169.      *  Test for the most important keys. Note
  170.      *  that only the cursor movement keys are
  171.      *  guaranteed to work with PC-clients.
  172.      */
  173.     c = *ch;
  174.     if (c == 'A')
  175.         c = KEY_UP;
  176.     if (c == 'B')
  177.         c = KEY_DOWN;
  178.     if (c == 'C')
  179.         c = KEY_RIGHT;
  180.     if (c == 'D')
  181.         c = KEY_LEFT;
  182.     if ((c == '1') || (c == 'H') || (c == 0))
  183.         c = KEY_HOME;
  184.     if ((c == '4') || (c == 'K') || (c == 101) || (c == 144))
  185.         c = KEY_END;
  186.     if (c == '2')
  187.         c = KEY_INS;
  188.     if (c == '3')
  189.         c = KEY_DEL;
  190.     if (c == '5')
  191.         c = KEY_PGUP;
  192.     if (c == '6')
  193.         c = KEY_PGDN;
  194.     memcpy(ch, &c, sizeof(unsigned char));
  195.     return rc;
  196.     }
  197.     return -1;
  198. }
  199.  
  200.  
  201.  
  202. /*
  203.  *  This next function will detect the grey keys on the keyboard for
  204.  *  VT100, VT220, Xterm, PC-ANSI, and Linux console. Works with 
  205.  *  several terminals on serial lines (tested 1200 bps).
  206.  *  If for example cursur keys are detected, this function returns
  207.  *  a translated value.
  208.  */
  209. unsigned char Readkey(void)
  210. {
  211.     unsigned char   ch = 0;
  212.     int             rc = -1;
  213.     time_t        Now;
  214.  
  215.     while (rc == -1) {
  216.     /*
  217.      * Check if we reached the timeout set by the alarm timers.
  218.      */
  219.     Now = time(NULL);
  220.     if (game_over) {
  221.         if (Now >= game_over) {
  222.         door_unsetraw();
  223.         fprintf(stdout, "\rIdle timeout, door finished\n\n");
  224.         fflush(stdout);
  225.         exit(0);
  226.         }
  227.     }
  228.     if (time2go) {
  229.         if (Now >= time2go) {
  230.         door_unsetraw();
  231.         fprintf(stdout, "\rDaily timelimit reached, door finished\n\n");
  232.         fflush(stdout);
  233.         exit(0);
  234.         }
  235.     }
  236.     rc = Waitchar(&ch, 5);
  237.  
  238.     /*
  239.      * If the character is not an Escape character,
  240.      * then this function is finished.
  241.      */
  242.     if ((rc == 1) && (ch != KEY_ESCAPE))
  243.         return ch;
  244.  
  245.     if ((rc == 1) && (ch == KEY_ESCAPE)) {
  246.         rc = Escapechar(&ch);
  247.         if (rc == 1)
  248.         return ch;
  249.         else
  250.         return KEY_ESCAPE;
  251.     }
  252.     }
  253.  
  254.     return(ch);
  255. }
  256.  
  257.  
  258.  
  259. /*
  260.  * Get a character string with cursor position
  261.  */
  262. void door_getstrp(char *sStr, int iMaxLen, int Position)
  263. {
  264.     unsigned char   ch = 0;
  265.     int            iPos = Position;
  266.  
  267.     if ((ttyfd = open("/dev/tty", O_RDWR|O_NONBLOCK)) < 0) {
  268.     perror("door_getstrp");
  269.     return;
  270.     }
  271.     door_setraw();
  272.     door_alarm_on();
  273.  
  274.     while (ch != KEY_ENTER) {
  275.  
  276.     fflush(stdout);
  277.     ch = Readkey();
  278.  
  279.     if ((ch == KEY_BACKSPACE) || (ch == KEY_DEL) || (ch == KEY_RUBOUT)) {
  280.         if (iPos > 0) {
  281.         printf("\b \b");
  282.         sStr[--iPos] = '\0';
  283.         } else
  284.         putchar('\007');
  285.     }
  286.  
  287.     if (ch > 31 && ch < 127) {
  288.         if (iPos <= iMaxLen) {
  289.         iPos++;
  290.         sprintf(sStr, "%s%c", sStr, ch);
  291.         printf("%c", ch);
  292.         } else
  293.         putchar('\007');
  294.     }
  295.     }
  296.  
  297.     door_unsetraw();
  298.     close(ttyfd);
  299.     printf("\n");
  300. }
  301.  
  302.  
  303.  
  304. /*
  305.  * Get a character string
  306.  */
  307. void door_getstr(char *sStr, int iMaxlen)
  308. {
  309.     unsigned char   ch = 0;
  310.     int            iPos = 0;
  311.  
  312.     fflush(stdout);
  313.     if ((ttyfd = open ("/dev/tty", O_RDWR|O_NONBLOCK)) < 0) {
  314.     perror("door_getstr");
  315.     return;
  316.     }
  317.     door_setraw();
  318.     strcpy(sStr, "");
  319.     door_alarm_on();
  320.  
  321.     while (ch != 13) {
  322.  
  323.     fflush(stdout);
  324.     ch = Readkey();
  325.  
  326.     if ((ch == 8) || (ch == KEY_DEL) || (ch == 127)) {
  327.         if (iPos > 0) {
  328.         printf("\b \b");
  329.         sStr[--iPos] = '\0';
  330.         } else
  331.         putchar('\007');
  332.     }
  333.  
  334.     if ((ch > 31) && (ch < 127) && (ch != ',')) {
  335.         if (iPos <= iMaxlen) {
  336.         iPos++;
  337.         sprintf(sStr, "%s%c", sStr, ch);
  338.         printf("%c", ch);
  339.         } else
  340.         putchar('\007');
  341.     }
  342.     }
  343.  
  344.     door_unsetraw();
  345.     close(ttyfd);
  346.     printf("\n");
  347. }
  348.  
  349.  
  350.  
  351. /*
  352.  * Get a username, captitalize first letters.
  353.  */
  354. void door_getname(char *sStr, int iMaxlen)
  355. {
  356.     unsigned char   ch = 0; 
  357.     int             iPos = 0, iNewPos = 0;
  358.  
  359.     fflush(stdout);
  360.     strcpy(sStr, "");
  361.  
  362.     if ((ttyfd = open ("/dev/tty", O_RDWR|O_NONBLOCK)) < 0) {
  363.     perror("door_getname");
  364.     return;
  365.     }
  366.     door_setraw();
  367.     door_alarm_on();
  368.  
  369.     while (ch != 13) {
  370.     fflush(stdout);
  371.     ch = Readkey();
  372.  
  373.     if ((ch == 8) || (ch == KEY_DEL) || (ch == 127)) {
  374.         if (iPos > 0) {
  375.         printf("\b \b");
  376.         sStr[--iPos]='\0';
  377.         } else {
  378.         putchar('\007');
  379.         }
  380.     }
  381.  
  382.     if (ch > 31 && (ch < 127)) {
  383.         if (iPos < iMaxlen) {
  384.         iPos++;
  385.         if (iPos == 1)
  386.             ch = toupper(ch);
  387.  
  388.         if (ch == 32) {
  389.             iNewPos = iPos;
  390.             iNewPos++;
  391.         }
  392.         if (iNewPos == iPos)
  393.             ch = toupper(ch);
  394.         else
  395.             ch = tolower(ch);
  396.         if (iPos == 1)
  397.             ch = toupper(ch);
  398.         sprintf(sStr, "%s%c", sStr, ch);
  399.         printf("%c", ch);
  400.         } else {
  401.         putchar('\007');
  402.         }
  403.     }
  404.     }
  405.  
  406.     door_unsetraw();
  407.     close(ttyfd);
  408.     printf("\n");
  409. }
  410.  
  411.  
  412.  
  413. /*
  414.  * Get a number, allow digits, spaces, minus sign, points and comma's
  415.  */
  416. void door_getnum(char *sStr, int iMaxlen)
  417. {
  418.     unsigned char   ch = 0; 
  419.     int             iPos = 0;
  420.  
  421.     fflush(stdout);
  422.  
  423.     if ((ttyfd = open ("/dev/tty", O_RDWR|O_NONBLOCK)) < 0) {
  424.     perror("door_getnum");
  425.     return;
  426.     }
  427.     door_setraw();
  428.     strcpy(sStr, "");
  429.     door_alarm_on();
  430.  
  431.     while (ch != 13) {
  432.     fflush(stdout);
  433.     ch = Readkey();
  434.     
  435.     if ((ch == 8) || (ch == KEY_DEL) || (ch == 127)) {
  436.         if (iPos > 0) {
  437.         printf("\b \b");
  438.         sStr[--iPos]='\0';
  439.         } else {
  440.         putchar('\007');
  441.         }
  442.     }
  443.  
  444.     if ((ch >= '0' && ch <= '9') || (ch == '-') || (ch == ' ') || (ch == ',') || (ch == '.')) {
  445.         if (iPos <= iMaxlen) {
  446.         iPos++;
  447.         sprintf(sStr, "%s%c", sStr, ch);
  448.         printf("%c", ch);
  449.         } else {
  450.         putchar('\007');
  451.         }
  452.     }
  453.     }
  454.  
  455.     door_unsetraw();
  456.     close(ttyfd);
  457.     printf("\n");
  458. }
  459.  
  460.  
  461.  
  462. void door_waitenter(char *message)
  463. {
  464.     int        i, x;
  465.     char    *string;
  466.  
  467.     door_color(WHITE, BLACK);
  468.     printf("\r");
  469.  
  470.     if (message == NULL)
  471.     string = door_xstrcpy((char *)"Press (Enter) to continue: ");
  472.     else
  473.     string = door_xstrcpy(message);
  474.     
  475.     do {
  476.     fflush(stdout);
  477.     fflush(stdin);
  478.     door_alarm_on();
  479.     i = door_getch();
  480.     } while ((i != '\r') && (i != '\n'));
  481.  
  482.     x = strlen(string);
  483.     for(i = 0; i < x; i++)
  484.     printf("\b");
  485.     for(i = 0; i < x; i++)
  486.     printf(" ");
  487.     for(i = 0; i < x; i++)
  488.     printf("\b");
  489.     fflush(stdout);
  490.  
  491.     free(string);
  492. }
  493.  
  494.  
  495.