update for HEAD-2003021201
[reactos.git] / lib / crtdll / stdio / flsbuf.c
1 /* Copyright (C) 1996 DJ Delorie, see COPYING.DJ for details */
2 /* Copyright (C) 1995 DJ Delorie, see COPYING.DJ for details */
3
4 #include <msvcrt/stdio.h>
5 #include <msvcrt/wchar.h>
6 #include <msvcrt/sys/types.h>
7 #include <msvcrt/stdlib.h>
8 #include <msvcrt/internal/file.h>
9 #include <msvcrt/io.h>
10 #include <msvcrt/errno.h>
11
12
13 int cntcr(char *bufp, int bufsiz);
14 int convert(char *endp, int bufsiz,int n);
15 int _writecnv(int fn, void *buf, size_t bufsiz);
16
17
18 int _flsbuf(int c, FILE *f)
19 {
20   char *base;
21   int n, rn;
22   char c1;
23   int size;
24
25   if (!OPEN4WRITING(f)) {
26         __set_errno (EINVAL);
27         return EOF;
28   }
29
30   // no file associated with buffer, this is a memory stream
31   if (fileno(f) == -1) {
32         return c;
33   }
34
35   /* if the buffer is not yet allocated, allocate it */
36   if ((base = f->_base) == NULL && (f->_flag & _IONBF) == 0) {
37     size = 4096;
38     if ((f->_base = base = malloc (size)) == NULL) {
39       f->_flag |= _IONBF;
40       f->_flag &= ~(_IOFBF|_IOLBF);
41     } else {
42       f->_flag |= _IOMYBUF;
43       f->_cnt = f->_bufsiz = size;
44       f->_ptr = base;
45       rn = 0;
46       if (f == stdout && isatty (fileno (stdout))) {
47             f->_flag |= _IOLBF;
48       }
49     }
50   }
51
52   if (f->_flag & _IOLBF) {
53     /* in line-buffering mode we get here on each character */
54     *f->_ptr++ = c;
55     rn = f->_ptr - base;
56     if (c == '\n' || rn >= f->_bufsiz) {
57       /* time for real flush */
58       f->_ptr = base;
59       f->_cnt = 0;
60     } else {
61       /* we got here because _cnt is wrong, so fix it */
62       /* Negative _cnt causes all output functions to call */
63       /*  _flsbuf for each character, thus realizing line-buffering */
64       f->_cnt = -rn;
65       return c;
66     }
67   } else if (f->_flag & _IONBF) {                   
68     c1 = c;           
69     rn = 1;           
70     base = &c1;       
71     f->_cnt = 0;
72   } else { /* _IOFBF */
73     rn = f->_ptr - base;
74     f->_ptr = base;
75     if ( (f->_flag & _IOAHEAD) == _IOAHEAD )
76         _lseek(fileno(f),-(rn+f->_cnt), SEEK_CUR);
77     f->_cnt = f->_bufsiz;
78     f->_flag &= ~_IOAHEAD;
79   }
80   f->_flag &= ~_IODIRTY;
81   while (rn > 0) {
82     n = _write(fileno(f), base, rn);
83     if (n <= 0) {
84       f->_flag |= _IOERR;
85       return EOF;
86     }
87     rn -= n;
88     base += n;
89   }
90   if ((f->_flag&(_IOLBF|_IONBF)) == 0) {
91     f->_cnt--;
92     *f->_ptr++ = c;
93   }
94   return c;
95 }
96
97 wint_t  _flswbuf(wchar_t c,FILE *fp)
98 {
99     int result;
100
101     result = _flsbuf((int)c, fp);
102     if (result == EOF)
103         return WEOF;
104         return (wint_t)result;
105 }
106
107 int _writecnv(int fn, void *buf, size_t siz)
108 {
109         char *bufp = (char *)buf;
110         int bufsiz = siz;
111     char *tmp;
112         int cr1 = 0;
113         int cr2 = 0;
114         int n;
115
116         cr1 = cntcr(bufp,bufsiz);
117         tmp = malloc(cr1);
118         memcpy(tmp,bufp+bufsiz-cr1,cr1);
119         cr2 = cntcr(tmp,cr1);
120         convert(bufp,bufsiz-cr2,cr1-cr2);
121         n = _write(fn, bufp, bufsiz + cr1);
122         convert(tmp,cr1,cr2);
123         n += _write(fn, tmp, cr1 + cr2);
124         free(tmp);
125         return n;       
126 }
127
128 int convert(char *endp, int bufsiz,int n)
129 {       
130         endp = endp + bufsiz + n;
131         while (bufsiz > 0) {
132                 *endp = *(endp  - n);
133                 if (*endp == '\n') {
134                         *endp--;
135                         n--;
136                         *endp = '\r';
137                 }
138                 endp--;
139                 bufsiz--;
140         }
141         return n;
142 }
143
144 int cntcr(char *bufp, int bufsiz)
145 {
146         int cr = 0; 
147
148         while (bufsiz > 0) {
149         if (*bufp == '\n') {
150                         cr++;
151         }
152                 bufp++;
153                 bufsiz--;
154         }
155         return cr;
156 }