|
|
| version 1.7, 2005/03/20 06:09:16 | version 1.8, 2005/04/01 15:35:49 |
|---|---|
| Line 1 | Line 1 |
| #include "compiler.h" | #include "compiler.h" |
| #include "strres.h" | #include "strres.h" |
| #include "dosio.h" | |
| #include "textfile.h" | #include "textfile.h" |
| #if defined(SUPPORT_TEXTCNV) | |
| #include "textcnv.h" | |
| #endif | |
| #include "dosio.h" | |
| enum { | enum { |
| Line 9 enum { | Line 12 enum { |
| TFMODE_WRITE = 0x02 | TFMODE_WRITE = 0x02 |
| }; | }; |
| typedef struct { | struct _textfile; |
| typedef struct _textfile _TEXTFILE; | |
| typedef struct _textfile *TEXTFILE; | |
| typedef BRESULT (*READFN)(TEXTFILE tf, void *buffer, UINT size); | |
| struct _textfile { | |
| UINT8 mode; | UINT8 mode; |
| UINT8 width; | |
| #if defined(SUPPORT_TEXTCNV) | |
| UINT8 access; | UINT8 access; |
| UINT8 srcwidth; | |
| UINT8 xendian; | UINT8 xendian; |
| #endif | |
| FILEH fh; | FILEH fh; |
| long fpos; | long fpos; |
| void *buf; | UINT8 *buf; |
| UINT bufsize; | UINT bufsize; |
| UINT bufpos; | UINT bufpos; |
| UINT bufrem; | UINT bufrem; |
| } _TEXTFILE, *TEXTFILE; | READFN readfn; |
| #if defined(SUPPORT_TEXTCNV) | |
| UINT8 *cnvbuf; | |
| static TEXTFILEH registfile(FILEH fh, UINT buffersize, | UINT cnvbufsize; |
| const UINT8 *hdr, UINT hdrsize) { | TCTOOEM tooem; |
| TCFROMOEM fromoem; | |
| long fpos; | |
| UINT8 srcwidth; | |
| UINT8 xendian; | |
| TEXTFILE ret; | |
| buffersize = buffersize & (~3); | |
| if (buffersize < 256) { | |
| buffersize = 256; | |
| } | |
| fpos = 0; | |
| srcwidth = 1; | |
| xendian = FALSE; | |
| if ((hdrsize >= 3) && | |
| (hdr[0] == 0xef) && (hdr[1] == 0xbb) && (hdr[2] == 0xbf)) { | |
| // UTF-8 | |
| fpos = 3; | |
| } | |
| else if ((hdrsize >= 2) && (hdr[0] == 0xff) && (hdr[1] == 0xfe)) { | |
| // UCSLE | |
| fpos = 2; | |
| srcwidth = 2; | |
| #if defined(BYTESEX_BIG) | |
| xendian = TRUE; | |
| #endif | |
| } | |
| else if ((hdrsize >= 2) && (hdr[0] == 0xfe) && (hdr[1] == 0xff)) { | |
| // UCS2BE | |
| fpos = 2; | |
| srcwidth = 2; | |
| #if defined(BYTESEX_LITTLE) | |
| xendian = TRUE; | |
| #endif | #endif |
| } | }; |
| if (srcwidth != sizeof(OEMCHAR)) { | |
| return(NULL); | |
| } | |
| buffersize = buffersize * sizeof(OEMCHAR); | |
| ret = (TEXTFILE)_MALLOC(sizeof(_TEXTFILE) + buffersize, "TEXTFILE"); | |
| if (ret == NULL) { | |
| return(NULL); | |
| } | |
| ZeroMemory(ret, sizeof(_TEXTFILE)); | |
| // ret->mode = 0; | |
| ret->srcwidth = srcwidth; | |
| ret->xendian = xendian; | |
| ret->fh = fh; | |
| ret->fpos = fpos; | |
| ret->buf = (UINT8 *)(ret + 1); | |
| ret->bufsize = buffersize; | |
| return((TEXTFILEH)ret); | |
| } | |
| static BRESULT flushfile(TEXTFILE tf) { | |
| if (tf->mode & TFMODE_READ) { | |
| tf->fpos -= tf->bufrem * tf->srcwidth; | |
| } | |
| tf->mode = 0; | |
| tf->bufpos = 0; | |
| tf->bufrem = 0; | |
| if (file_seek(tf->fh, tf->fpos, FSEEK_SET) == tf->fpos) { | |
| return(SUCCESS); | |
| } | |
| else { | |
| return(FAILURE); | |
| } | |
| } | |
| // ---- A | // ---- ReadA |
| static UINT fillbufferA(TEXTFILE tf) { | static UINT readbufferA(TEXTFILE tf) { |
| UINT rsize; | UINT rsize; |
| Line 135 const char *src; | Line 79 const char *src; |
| ret = FAILURE; | ret = FAILURE; |
| c = 0; | c = 0; |
| do { | do { |
| if (fillbufferA(tf) == 0) { | if (readbufferA(tf) == 0) { |
| break; | break; |
| } | } |
| ret = SUCCESS; | ret = SUCCESS; |
| Line 158 const char *src; | Line 102 const char *src; |
| tf->bufrem -= pos; | tf->bufrem -= pos; |
| } while(!crlf); | } while(!crlf); |
| if ((crlf) && (c == 0x0d)) { | if ((crlf) && (c == 0x0d)) { |
| if (fillbufferA(tf) != 0) { | if (readbufferA(tf) != 0) { |
| src = (char *)tf->buf; | src = (char *)tf->buf; |
| src += tf->bufpos; | src += tf->bufpos; |
| if (*src == 0x0a) { | if (*src == 0x0a) { |
| Line 174 const char *src; | Line 118 const char *src; |
| } | } |
| // ---- W | // ---- ReadW |
| static UINT fillbufferW(TEXTFILE tf) { | static UINT readbufferW(TEXTFILE tf) { |
| UINT rsize; | UINT rsize; |
| UINT8 *buf; | UINT8 *buf; |
| UINT8 tmp; | |
| if (tf->bufrem == 0) { | if (tf->bufrem == 0) { |
| buf = tf->buf; | buf = tf->buf; |
| Line 189 static UINT fillbufferW(TEXTFILE tf) { | Line 132 static UINT fillbufferW(TEXTFILE tf) { |
| tf->fpos += rsize * sizeof(UINT16); | tf->fpos += rsize * sizeof(UINT16); |
| tf->bufpos = 0; | tf->bufpos = 0; |
| tf->bufrem = rsize; | tf->bufrem = rsize; |
| #if defined(SUPPORT_TEXTCNV) | |
| if (tf->xendian) { | if (tf->xendian) { |
| while(rsize) { | textcnv_swapendian16(buf, rsize); |
| tmp = buf[0]; | |
| buf[0] = buf[1]; | |
| buf[1] = tmp; | |
| buf += 2; | |
| rsize--; | |
| } | |
| } | } |
| #endif // defined(SUPPORT_TEXTCNV) | |
| } | } |
| return(tf->bufrem); | return(tf->bufrem); |
| } | } |
| Line 223 const UINT16 *src; | Line 162 const UINT16 *src; |
| ret = FAILURE; | ret = FAILURE; |
| c = 0; | c = 0; |
| do { | do { |
| if (fillbufferW(tf) == 0) { | if (readbufferW(tf) == 0) { |
| break; | break; |
| } | } |
| ret = SUCCESS; | ret = SUCCESS; |
| Line 246 const UINT16 *src; | Line 185 const UINT16 *src; |
| tf->bufrem -= pos; | tf->bufrem -= pos; |
| } while(!crlf); | } while(!crlf); |
| if ((crlf) && (c == 0x0d)) { | if ((crlf) && (c == 0x0d)) { |
| if (fillbufferW(tf) != 0) { | if (readbufferW(tf) != 0) { |
| src = (UINT16 *)tf->buf; | src = (UINT16 *)tf->buf; |
| src += tf->bufpos; | src += tf->bufpos; |
| if (*src == 0x0a) { | if (*src == 0x0a) { |
| Line 262 const UINT16 *src; | Line 201 const UINT16 *src; |
| } | } |
| // ---- read with convert | |
| #if defined(SUPPORT_TEXTCNV) | |
| static BRESULT readlineAtoOEM(TEXTFILE tf, void *buffer, UINT size) { | |
| BRESULT ret; | |
| ret = readlineA(tf, tf->cnvbuf, tf->cnvbufsize); | |
| if (ret == SUCCESS) { | |
| (tf->tooem)(buffer, size, tf->cnvbuf, (UINT)-1); | |
| } | |
| return(ret); | |
| } | |
| static BRESULT readlineWtoOEM(TEXTFILE tf, void *buffer, UINT size) { | |
| BRESULT ret; | |
| ret = readlineW(tf, tf->cnvbuf, tf->cnvbufsize / 2); | |
| if (ret == SUCCESS) { | |
| (tf->tooem)(buffer, size, tf->cnvbuf, (UINT)-1); | |
| } | |
| return(ret); | |
| } | |
| #endif // defined(SUPPORT_TEXTCNV) | |
| // ---- write | |
| static BRESULT flushwritebuffer(TEXTFILE tf) { | |
| UINT size; | |
| UINT wsize; | |
| if (tf->bufpos) { | |
| size = tf->bufpos * tf->width; | |
| wsize = file_write(tf->fh, tf->buf, size); | |
| tf->fpos += wsize; | |
| if (wsize != size) { | |
| return(FAILURE); | |
| } | |
| } | |
| return(SUCCESS); | |
| } | |
| static BRESULT writebufferA(TEXTFILE tf, const void *buffer, UINT size) { | |
| BRESULT ret; | |
| const UINT8 *p; | |
| UINT wsize; | |
| ret = SUCCESS; | |
| p = (char *)buffer; | |
| while(size) { | |
| wsize = min(size, tf->bufrem); | |
| if (wsize) { | |
| CopyMemory(tf->buf + tf->bufpos, p, wsize); | |
| p += wsize; | |
| size -= wsize; | |
| tf->bufpos += wsize; | |
| tf->bufrem -= wsize; | |
| } | |
| if (tf->bufrem == 0) { | |
| ret = flushwritebuffer(tf); | |
| tf->bufpos = 0; | |
| tf->bufrem = tf->bufsize / sizeof(char); | |
| } | |
| } | |
| return(ret); | |
| } | |
| static BRESULT writebufferW(TEXTFILE tf, const void *buffer, UINT size) { | |
| BRESULT ret; | |
| const UINT8 *p; | |
| UINT8 *q; | |
| UINT wsize; | |
| ret = SUCCESS; | |
| p = (UINT8 *)buffer; | |
| while(size) { | |
| wsize = min(size, tf->bufrem); | |
| if (wsize) { | |
| q = tf->buf + (tf->bufpos * sizeof(UINT16)); | |
| CopyMemory(q, p, wsize * sizeof(UINT16)); | |
| #if defined(SUPPORT_TEXTCNV) | |
| if (tf->xendian) { | |
| textcnv_swapendian16(q, wsize); | |
| } | |
| #endif // defined(SUPPORT_TEXTCNV) | |
| p += wsize * sizeof(UINT16); | |
| size -= wsize; | |
| tf->bufpos += wsize; | |
| tf->bufrem -= wsize; | |
| } | |
| if (tf->bufrem == 0) { | |
| ret = flushwritebuffer(tf); | |
| tf->bufpos = 0; | |
| tf->bufrem = tf->bufsize / sizeof(UINT16); | |
| } | |
| } | |
| return(ret); | |
| } | |
| // ---- | |
| static TEXTFILEH registfile(FILEH fh, UINT buffersize, | |
| const UINT8 *hdr, UINT hdrsize) { | |
| UINT cnvbufsize; | |
| #if defined(SUPPORT_TEXTCNV) | |
| TCINF inf; | |
| #endif | |
| long fpos; | |
| UINT8 width; | |
| READFN readfn; | |
| TEXTFILE ret; | |
| buffersize = buffersize & (~3); | |
| if (buffersize < 256) { | |
| buffersize = 256; | |
| } | |
| cnvbufsize = 0; | |
| #if defined(SUPPORT_TEXTCNV) | |
| if (textcnv_getinfo(&inf, hdr, hdrsize) == 0) { | |
| return(NULL); | |
| } | |
| fpos = inf.hdrsize; | |
| width = inf.width; | |
| if (inf.width == 1) { | |
| readfn = (inf.tooem != NULL)?readlineAtoOEM:readlineA; | |
| } | |
| else if (inf.width == 2) { | |
| buffersize = buffersize * 2; | |
| readfn = (inf.tooem != NULL)?readlineWtoOEM:readlineW; | |
| } | |
| else { | |
| return(NULL); | |
| } | |
| if ((inf.tooem != NULL) || (inf.fromoem != NULL)) { | |
| cnvbufsize = buffersize; | |
| } | |
| #else // defined(SUPPORT_TEXTCNV) | |
| fpos = 0; | |
| width = 1; | |
| if ((hdrsize >= 3) && | |
| (hdr[0] == 0xef) && (hdr[1] == 0xbb) && (hdr[2] == 0xbf)) { | |
| // UTF-8 | |
| fpos = 3; | |
| } | |
| else if ((hdrsize >= 2) && (hdr[0] == 0xff) && (hdr[1] == 0xfe)) { | |
| // UCSLE | |
| fpos = 2; | |
| width = 2; | |
| #if defined(BYTESEX_BIG) | |
| return(NULL); | |
| #endif // defined(BYTESEX_BIG) | |
| } | |
| else if ((hdrsize >= 2) && (hdr[0] == 0xfe) && (hdr[1] == 0xff)) { | |
| // UCS2BE | |
| fpos = 2; | |
| width = 2; | |
| #if defined(BYTESEX_LITTLE) | |
| return(NULL); | |
| #endif // defined(BYTESEX_LITTLE) | |
| } | |
| if (width != sizeof(OEMCHAR)) { | |
| return(NULL); | |
| } | |
| buffersize = buffersize * sizeof(OEMCHAR); | |
| readfn = (width == 2)?readlineW:readlineA; | |
| #endif // defined(SUPPORT_TEXTCNV) | |
| ret = (TEXTFILE)_MALLOC(sizeof(_TEXTFILE) + buffersize + cnvbufsize, | |
| "TEXTFILE"); | |
| if (ret == NULL) { | |
| return(NULL); | |
| } | |
| ZeroMemory(ret, sizeof(_TEXTFILE)); | |
| // ret->mode = 0; | |
| ret->width = width; | |
| ret->fh = fh; | |
| ret->fpos = fpos; | |
| ret->buf = (UINT8 *)(ret + 1); | |
| ret->bufsize = buffersize; | |
| ret->readfn = readfn; | |
| #if defined(SUPPORT_TEXTCNV) | |
| ret->access = inf.caps; | |
| ret->xendian = inf.xendian; | |
| ret->cnvbuf = ret->buf + buffersize; | |
| ret->cnvbufsize = cnvbufsize; | |
| ret->tooem = inf.tooem; | |
| ret->fromoem = inf.fromoem; | |
| #endif // defined(SUPPORT_TEXTCNV) | |
| return((TEXTFILEH)ret); | |
| } | |
| static BRESULT flushfile(TEXTFILE tf) { | |
| BRESULT ret; | |
| long fpos; | |
| UINT size; | |
| UINT wsize; | |
| ret = SUCCESS; | |
| if (tf->mode & TFMODE_READ) { | |
| fpos = tf->fpos - (tf->bufrem * tf->width); | |
| tf->fpos = file_seek(tf->fh, fpos, FSEEK_SET); | |
| if (tf->fpos != fpos) { | |
| ret = FAILURE; | |
| } | |
| } | |
| else if (tf->mode & TFMODE_WRITE) { | |
| if (tf->bufpos) { | |
| size = tf->bufpos * tf->width; | |
| wsize = file_write(tf->fh, tf->buf, size); | |
| if (wsize != size) { | |
| ret = FAILURE; | |
| } | |
| tf->fpos += wsize; | |
| } | |
| } | |
| else { | |
| fpos = file_seek(tf->fh, tf->fpos, FSEEK_SET); | |
| if (tf->fpos != fpos) { | |
| ret = FAILURE; | |
| } | |
| tf->fpos = fpos; | |
| } | |
| tf->mode = 0; | |
| tf->bufpos = 0; | |
| tf->bufrem = 0; | |
| return(ret); | |
| } | |
| // ---- | // ---- |
| TEXTFILEH textfile_open(const OEMCHAR *filename, UINT buffersize) { | TEXTFILEH textfile_open(const OEMCHAR *filename, UINT buffersize) { |
| Line 327 BRESULT textfile_read(TEXTFILEH tfh, OEM | Line 503 BRESULT textfile_read(TEXTFILEH tfh, OEM |
| TEXTFILE tf; | TEXTFILE tf; |
| tf = (TEXTFILE)tfh; | tf = (TEXTFILE)tfh; |
| if (tf) { | if (tf == NULL) { |
| if (!(tf->mode & TFMODE_READ)) { | return(FAILURE); |
| flushfile(tf); | } |
| tf->mode = TFMODE_READ; | #if defined(SUPPORT_TEXTCNV) |
| } | if (!(tf->access & TEXTCNV_READ)) { |
| if (sizeof(OEMCHAR) == 1) { | return(FAILURE); |
| return(readlineA(tf, buffer, size)); | } |
| } | #endif // defined(SUPPORT_TEXTCNV) |
| else if (sizeof(OEMCHAR) == 2) { | if (!(tf->mode & TFMODE_READ)) { |
| return(readlineW(tf, buffer, size)); | flushfile(tf); |
| } | tf->mode = TFMODE_READ; |
| } | } |
| return(FAILURE); | return((tf->readfn)(tf, buffer, size)); |
| } | } |
| BRESULT textfile_write(TEXTFILEH tfh, const OEMCHAR *buffer) { | BRESULT textfile_write(TEXTFILEH tfh, const OEMCHAR *buffer) { |
| TEXTFILE tf; | TEXTFILE tf; |
| const void *buf; | |
| UINT leng; | UINT leng; |
| UINT wsize; | |
| tf = (TEXTFILE)tfh; | tf = (TEXTFILE)tfh; |
| if (tf) { | if (tf == NULL) { |
| if (!(tf->mode & TFMODE_WRITE)) { | return(FAILURE); |
| flushfile(tf); | } |
| tf->mode = TFMODE_WRITE; | #if defined(SUPPORT_TEXTCNV) |
| } | if (!(tf->access & TEXTCNV_WRITE)) { |
| leng = OEMSTRLEN(buffer); | return(FAILURE); |
| leng = leng * sizeof(OEMCHAR); | } |
| wsize = file_write(tf->fh, buffer, leng); | #endif // defined(SUPPORT_TEXTCNV) |
| tf->fpos += wsize; | if (!(tf->mode & TFMODE_WRITE)) { |
| if (wsize == leng) { | flushfile(tf); |
| return(SUCCESS); | tf->mode = TFMODE_WRITE; |
| } | } |
| leng = OEMSTRLEN(buffer); | |
| #if defined(SUPPORT_TEXTCNV) | |
| if (tf->fromoem != NULL) { | |
| leng = (tf->fromoem)(tf->cnvbuf, tf->cnvbufsize / tf->width, | |
| buffer, leng); | |
| buf = tf->cnvbuf; | |
| } | |
| else { | |
| buf = buffer; | |
| } | |
| #else // defined(SUPPORT_TEXTCNV) | |
| buf = buffer; | |
| #endif // defined(SUPPORT_TEXTCNV) | |
| if (tf->width == 1) { | |
| return(writebufferA(tf, buf, leng)); | |
| } | |
| else if (tf->width == 2) { | |
| return(writebufferW(tf, buf, leng)); | |
| } | |
| else { | |
| return(FAILURE); | |
| } | } |
| return(FAILURE); | |
| } | } |
| void textfile_close(TEXTFILEH tfh) { | void textfile_close(TEXTFILEH tfh) { |
| if (tfh) { | TEXTFILE tf; |
| file_close(((TEXTFILE)tfh)->fh); | |
| _MFREE(tfh); | tf = (TEXTFILE)tfh; |
| if (tf) { | |
| if (tf->mode & TFMODE_WRITE) { | |
| flushfile(tf); | |
| } | |
| file_close(tf->fh); | |
| _MFREE(tf); | |
| } | } |
| } | } |