Explorar o código

fixed unicode writing to stderr/stdout directly on windows

Nicolas Cannasse %!s(int64=6) %!d(string=hai) anos
pai
achega
9ee47aba91
Modificáronse 1 ficheiros con 37 adicións e 0 borrados
  1. 37 0
      src/std/file.c

+ 37 - 0
src/std/file.c

@@ -27,6 +27,8 @@
 #ifdef HL_WIN
 #ifdef HL_WIN_DESKTOP
 #	include <windows.h>
+#	include <io.h>
+#	include <fcntl.h>
 #else
 #	include<xdk.h>
 #endif
@@ -34,10 +36,19 @@
 #	define HL_UFOPEN
 #endif
 
+#ifdef HL_WIN_DESKTOP
+#	define SET_IS_STD(f,b) (f)->is_std = b
+#else
+#	define SET_IS_STD(f,b)
+#endif
+
 typedef struct _hl_fdesc hl_fdesc;
 struct _hl_fdesc {
 	void (*finalize)( hl_fdesc * );
 	FILE *f;
+#	ifdef HL_WIN_DESKTOP
+	bool is_std;
+#	endif
 };
 
 static void fdesc_finalize( hl_fdesc *f ) {
@@ -57,6 +68,7 @@ HL_PRIM hl_fdesc *hl_file_open( vbyte *name, int mode, bool binary ) {
 	fd = (hl_fdesc*)hl_gc_alloc_finalizer(sizeof(hl_fdesc));
 	fd->finalize = fdesc_finalize;
 	fd->f = f;
+	SET_IS_STD(fd, false);
 	return fd;
 }
 
@@ -71,6 +83,21 @@ HL_PRIM int hl_file_write( hl_fdesc *f, vbyte *buf, int pos, int len ) {
 	int ret;
 	if( !f ) return -1;
 	hl_blocking(true);
+#	ifdef HL_WIN_DESKTOP
+	if( f->is_std ) {
+		// except utf8, handle the case where it's not \0 terminated
+		uchar *out = (uchar*)malloc((len+1)*2);
+		vbyte prev = buf[pos+len-1];
+		if( buf[pos+len] ) buf[pos+len-1] = 0;
+		int olen = hl_from_utf8(out,len,(const char*)(buf+pos));
+		buf[pos+len-1] = prev;
+		_setmode(fileno(f->f),_O_U8TEXT);
+		ret = _write(fileno(f->f),out,olen<<1);
+		_setmode(fileno(f->f),_O_TEXT);
+		if( ret > 0 ) ret = len;
+		free(out);
+	} else
+#	endif
 	ret = (int)fwrite(buf+pos,1,len,f->f);
 	hl_blocking(false);
 	return ret;
@@ -90,6 +117,15 @@ HL_PRIM bool hl_file_write_char( hl_fdesc *f, int c ) {
 	unsigned char cc = (unsigned char)c;
 	if( !f ) return false;
 	hl_blocking(true);
+#	ifdef HL_WIN_DESKTOP
+	if( f->is_std ) {
+		uchar wcc = cc;
+		_setmode(fileno(f->f),_O_U8TEXT);
+		ret = _write(fileno(f->f),&wcc,2);
+		_setmode(fileno(f->f),_O_TEXT);
+		if( ret > 0 ) ret = 1;
+	} else
+#	endif
 	ret = fwrite(&cc,1,1,f->f);
 	hl_blocking(false);
 	return ret == 1;
@@ -136,6 +172,7 @@ HL_PRIM bool hl_file_flush( hl_fdesc *f ) {
 		f = (hl_fdesc*)hl_gc_alloc_noptr(sizeof(hl_fdesc)); \
 		f->f = k; \
 		f->finalize = NULL; \
+		SET_IS_STD(f, true); \
 		return f; \
 	}