Improved unicode fileio support.
[reactos.git] / reactos / 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 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 }