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