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