branch update for HEAD-2003021201
[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 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 }