home *** CD-ROM | disk | FTP | other *** search
/ Tricks of the Windows Gam…ming Gurus (2nd Edition) / Disc2.iso / vc98 / crt / src / ungetwc.c < prev    next >
C/C++ Source or Header  |  1998-06-17  |  6KB  |  190 lines

  1. /***
  2. *ungetwc.c - unget a wide character from a stream
  3. *
  4. *       Copyright (c) 1993-1997, Microsoft Corporation. All rights reserved.
  5. *
  6. *Purpose:
  7. *       defines ungetwc() - pushes a wide character back onto an input stream
  8. *
  9. *******************************************************************************/
  10.  
  11.  
  12. #include <cruntime.h>
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <file2.h>
  16. #include <dbgint.h>
  17. #include <internal.h>
  18. #include <mtdll.h>
  19. #include <msdos.h>
  20. #include <errno.h>
  21. #include <wchar.h>
  22. #include <setlocal.h>
  23.  
  24. #ifdef _MT
  25.  
  26. /***
  27. *wint_t ungetwc(ch, stream) - put a wide character back onto a stream
  28. *
  29. *Purpose:
  30. *       Guaranteed one char pushback on a stream as long as open for reading.
  31. *       More than one char pushback in a row is not guaranteed, and will fail
  32. *       if it follows an ungetc which pushed the first char in buffer. Failure
  33. *       causes return of WEOF.
  34. *
  35. *Entry:
  36. *       wint_t ch - wide character to push back
  37. *       FILE *stream - stream to push character onto
  38. *
  39. *Exit:
  40. *       returns ch
  41. *       returns WEOF if tried to push WEOF, stream not opened for reading or
  42. *       or if we have already ungetc'd back to beginning of buffer.
  43. *
  44. *Exceptions:
  45. *
  46. *******************************************************************************/
  47.  
  48. wint_t __cdecl ungetwc (
  49.         REG2 wint_t ch,
  50.         REG1 FILE *stream
  51.         )
  52. {
  53.         wint_t retval;
  54.  
  55.         _ASSERTE(stream != NULL);
  56.  
  57.         _lock_str(stream);
  58.  
  59.         retval = _ungetwc_lk (ch, stream);
  60.  
  61.         _unlock_str(stream);
  62.  
  63.         return(retval);
  64. }
  65.  
  66. /***
  67. *_ungetwc_lk() -  Ungetwc() core routine (locked version)
  68. *
  69. *Purpose:
  70. *       Core ungetwc() routine; assumes stream is already locked.
  71. *
  72. *       [See ungetwc() above for more info.]
  73. *
  74. *Entry: [See ungetwc()]
  75. *
  76. *Exit:  [See ungetwc()]
  77. *
  78. *Exceptions:
  79. *
  80. *******************************************************************************/
  81.  
  82. wint_t __cdecl _ungetwc_lk (
  83.         wint_t ch,
  84.         FILE *str
  85.         )
  86. {
  87.  
  88. #else  /* _MT */
  89.  
  90. wint_t __cdecl ungetwc (
  91.         wint_t ch,
  92.         FILE *str
  93.         )
  94. {
  95.  
  96. #endif  /* _MT */
  97.  
  98.         _ASSERTE(str != NULL);
  99.  
  100.         /*
  101.          * Requirements for success:
  102.          *
  103.          * 1. Character to be pushed back on the stream must not be WEOF.
  104.          *
  105.          * 2. The stream must currently be in read mode, or must be open for
  106.          *    update (i.e., read/write) and must NOT currently be in write
  107.          *    mode.
  108.          */
  109.         if ( (ch != WEOF) &&
  110.              ( (str->_flag & _IOREAD) || ((str->_flag & _IORW) &&
  111.                 !(str->_flag & _IOWRT))
  112.              )
  113.            )
  114.         {
  115.                 /* If stream is unbuffered, get one. */
  116.                 if (str->_base == NULL)
  117.                         _getbuf(str);
  118.  
  119.             if (!(str->_flag & _IOSTRG) && (_osfile_safe(_fileno(str)) &
  120.                   FTEXT))
  121.                 {
  122.                         /*
  123.                          * Text mode, sigh... Convert the wc to a mbc.
  124.                          */
  125.                         int size;
  126.                         char mbc[4];
  127.  
  128.                 if ((size = wctomb(mbc, ch)) == -1)
  129.                         {
  130.                                 /*
  131.                                  * Conversion failed! Set errno and return
  132.                                  * failure.
  133.                                  */
  134.                                 errno = EILSEQ;
  135.                                 return WEOF;
  136.                         }
  137.  
  138.                         /* we know _base != NULL; since file is buffered */
  139.                         if (str->_ptr == str->_base)
  140.                         {
  141.                                 if (str->_cnt)
  142.                                 /* my back is against the wall; i've already done
  143.                                  * ungetwc, and there's no room for this one
  144.                                  */
  145.                                         return WEOF;
  146.                                 str->_ptr += size;
  147.                         }
  148.  
  149.                         if ( size == 1 )
  150.                         {
  151.                                 *--str->_ptr = mbc[0];
  152.                         }
  153.                         else /* size == 2 */
  154.                         {
  155.                                 *--str->_ptr = mbc[1];
  156.                                 *--str->_ptr = mbc[0];
  157.                         }
  158.  
  159.                         str->_cnt += size;
  160.  
  161.                         str->_flag &= ~_IOEOF;
  162.                         str->_flag |= _IOREAD;  /* may already be set */
  163.                         return (wint_t) (0x0ffff & ch);
  164.                 }
  165.                 /*
  166.                  * Binary mode - push back the wide char.
  167.                  */
  168.                 /* we know _base != NULL; since file is buffered */
  169.                 if (str->_ptr == str->_base)
  170.                 {
  171.                         if (str->_cnt)
  172.                                 /* my back is against the wall; i've already done
  173.                                  * ungetc, and there's no room for this one
  174.                                  */
  175.                                 return WEOF;
  176.                         str->_ptr += sizeof(wchar_t);
  177.                 }
  178.  
  179.                 str->_cnt += sizeof(wchar_t);
  180.  
  181.                 str->_flag &= ~_IOEOF;
  182.                 str->_flag |= _IOREAD;  /* may already be set */
  183.  
  184.                 return (wint_t) (*--((wchar_t *)(str->_ptr)) = (wchar_t)(ch & 0xffff));
  185.  
  186.         }
  187.         return WEOF;
  188. }
  189.  
  190.