/*:::::*/ static FB_WCHAR hReadChar( FB_INPUTCTX *ctx ) { /* device? */ if( FB_HANDLE_USED(ctx->handle) ) { int res; FB_WCHAR c; size_t len; res = fb_FileGetDataEx( ctx->handle, 0, &c, 1, &len, FALSE, TRUE ); if( (res != FB_RTERROR_OK) || (len == 0) ) return WEOF; return c; } /* console.. */ else { if( ctx->index >= FB_STRSIZE( &ctx->str.len ) ) return WEOF; else return (unsigned char)ctx->str.data[ctx->index++]; } }
/*:::::*/ int fb_FileGetWstrEx( FB_FILE *handle, fb_off_t pos, FB_WCHAR *dst, int dst_chars, size_t *bytesread ) { int res; if( bytesread ) *bytesread = 0; if( !FB_HANDLE_USED(handle) ) return fb_ErrorSetNum( FB_RTERROR_ILLEGALFUNCTIONCALL ); /* perform call ... but only if there's data ... */ if( (dst != NULL) && (dst_chars > 0) ) { size_t chars; res = fb_FileGetDataEx( handle, pos, (void *)dst, dst_chars, &chars, TRUE, TRUE ); /* add the null-term */ if( res == FB_RTERROR_OK ) dst[chars] = _LC('\0'); if( bytesread ) *bytesread = chars; } else res = fb_ErrorSetNum( FB_RTERROR_ILLEGALFUNCTIONCALL ); return res; }
/*:::::*/ static int hReadChar ( FB_INPUTCTX *ctx ) { /* device? */ if( FB_HANDLE_USED(ctx->handle) ) { int res; int c; size_t len; res = fb_FileGetDataEx( ctx->handle, 0, &c, 1, &len, FALSE, FALSE ); if( (res != FB_RTERROR_OK) || (len == 0) ) return EOF; return c & 0x000000FF; } /* console.. */ else { if( ctx->index >= FB_STRSIZE( &ctx->str ) ) return EOF; else return ctx->str.data[ctx->index++]; } }
int fb_FileSeekEx( FB_FILE *handle, fb_off_t newpos ) { int res; if( !FB_HANDLE_USED(handle) ) return fb_ErrorSetNum( FB_RTERROR_ILLEGALFUNCTIONCALL ); FB_LOCK(); /* clear put back buffer for every modifying non-read operation */ handle->putback_size = 0; /* convert to 0 based file i/o */ --newpos; if( handle->mode == FB_FILE_MODE_RANDOM ) newpos = newpos * handle->len; if (handle->hooks->pfnSeek!=NULL) { res = handle->hooks->pfnSeek(handle, newpos, SEEK_SET ); } else { res = fb_ErrorSetNum( FB_RTERROR_ILLEGALFUNCTIONCALL ); } FB_UNLOCK(); return res; }
FBCALL int fb_FileLineInputWstr( int fnum, FB_WCHAR *dst, ssize_t max_chars ) { FB_FILE *handle = FB_FILE_TO_HANDLE(fnum); if( !FB_HANDLE_USED(handle) ) return fb_ErrorSetNum( FB_RTERROR_ILLEGALFUNCTIONCALL ); if( handle->hooks->pfnReadLineWstr == NULL ) return fb_ErrorSetNum( FB_RTERROR_ILLEGALFUNCTIONCALL ); return handle->hooks->pfnReadLineWstr( handle, dst, max_chars ); }
/*:::::*/ FBCALL int fb_WidthFile( int fnum, int width ) { int cur = width; FB_FILE *handle; FB_LOCK(); handle = FB_HANDLE_DEREF(FB_FILE_TO_HANDLE(fnum)); if( !FB_HANDLE_USED(handle) ) { /* invalid file handle */ FB_UNLOCK(); return fb_ErrorSetNum( FB_RTERROR_ILLEGALFUNCTIONCALL ); } if( handle->hooks==NULL ) { /* not opened yet */ FB_UNLOCK(); return fb_ErrorSetNum( FB_RTERROR_ILLEGALFUNCTIONCALL ); } if( handle==FB_HANDLE_SCREEN ) { /* SCREEN device */ if( width!=-1 ) { fb_Width( width, -1 ); } cur = FB_HANDLE_SCREEN->width; } else { if( width!=-1 ) { handle->width = width; if( handle->hooks->pfnSetWidth!=NULL ) handle->hooks->pfnSetWidth( handle, width ); } cur = handle->width; } FB_UNLOCK(); if( width==-1 ) { return cur; } return fb_ErrorSetNum( FB_RTERROR_OK ); }
/*:::::*/ static int hUnreadChar ( FB_INPUTCTX *ctx, int c ) { /* device? */ if( FB_HANDLE_USED(ctx->handle) ) { return fb_FilePutBackEx( ctx->handle, &c, 1 ); } /* console .. */ else { if( ctx->index <= 0 ) return FALSE; else { --ctx->index; return TRUE; } } }
/*:::::*/ static int hUnreadChar ( FB_INPUTCTX *ctx, FB_WCHAR c ) { /* device? */ if( FB_HANDLE_USED(ctx->handle) ) { return fb_FilePutBackWstrEx( ctx->handle, &c, 1 ); } /* console .. */ else { if( ctx->index <= 0 ) return 0; else { --ctx->index; return 1; } } }
static int fb_hFileLineInputEx ( FB_FILE *handle, void *dst, ssize_t dst_len, int fillrem ) { ssize_t len, readlen; char buffer[BUFFER_LEN]; eInputMode mode = eIM_Invalid; if( !FB_HANDLE_USED(handle) ) return fb_ErrorSetNum( FB_RTERROR_ILLEGALFUNCTIONCALL ); FB_LOCK(); if( handle->hooks->pfnReadLine != NULL ) { mode = eIM_ReadLine; } else if( handle->hooks->pfnRead != NULL && handle->hooks->pfnEof != NULL ) { mode = eIM_Read; } if( mode==eIM_Invalid ) { FB_UNLOCK(); return fb_ErrorSetNum( FB_RTERROR_ILLEGALFUNCTIONCALL ); } switch( mode ) { case eIM_Read: /* This is the VFS-compatible way to read a line ... but it's slow */ len = readlen = 0; while (!handle->hooks->pfnEof(handle)) { int do_add = FALSE, do_break = FALSE; size_t read_len; int res = fb_FileGetDataEx( handle, 0, buffer+len, 1, &read_len, FALSE, FALSE ); if( res==FB_RTERROR_OK && read_len==1) { char ch = buffer[len]; if( ch==13 ) { res = fb_FileGetDataEx( handle, 0, &ch, 1, &read_len, FALSE, FALSE ); if( res==FB_RTERROR_OK && ch!=10 && read_len==1) { fb_FilePutBackEx( handle, &ch, 1 ); } ch = 10; } if( ch==10 ) { do_add = do_break = TRUE; } else { do_add = len==(sizeof(buffer)-1); } } else { do_add = len!=0; } if( do_add || handle->hooks->pfnEof( handle ) ) { /* create temporary string to ensure that NUL's are preserved ... * this function wants the length WITH the NUL character!!! */ buffer[len] = 0; FBSTRING *src = fb_StrAllocTempDescF( buffer, len + 1); if( readlen==0 ) { fb_StrAssign( dst, dst_len, src, -1, fillrem ); } else { fb_StrConcatAssign ( dst, dst_len, src, -1, fillrem ); } readlen += len; len = 0; } else { ++len; } if( res!=FB_RTERROR_OK || do_break ) break; } if( readlen == 0 ) { /* del destine string */ if( dst_len == -1 ) fb_StrDelete( (FBSTRING *)dst ); else *(char *)dst = '\0'; } break; case eIM_ReadLine: /* The read line mode is the most comfortable ... but IMHO it's * only useful for special devices (like SCRN:) */ { /* destine is a var-len string? read directly */ if( dst_len == -1 ) { handle->hooks->pfnReadLine( handle, dst ); } /* fixed-len or unknown size (ie: pointers)? use a temp var-len */ else { FBSTRING str_result = { 0, 0, 0 }; /* read complete line (may include NULs) */ handle->hooks->pfnReadLine( handle, &str_result ); /* add contents of tempporary string to result buffer */ fb_StrAssign( dst, dst_len, (void *)&str_result, -1, fillrem ); /* delete result */ fb_StrDelete( &str_result ); } } break; case eIM_Invalid: /* the "invalid" mode was already handled above ... so we don't * need to do anything here ... */ break; } FB_UNLOCK(); return fb_ErrorSetNum( FB_RTERROR_OK ); }
FBCALL FB_WCHAR *fb_FileWstrInput( ssize_t chars, int fnum ) { FB_FILE *handle; FB_WCHAR *dst; size_t len; int res = FB_RTERROR_OK; fb_DevScrnInit_ReadWstr( ); FB_LOCK(); handle = FB_FILE_TO_HANDLE(fnum); if( !FB_HANDLE_USED(handle) ) { FB_UNLOCK(); return NULL; } dst = fb_wstr_AllocTemp( chars ); if( dst != NULL ) { ssize_t read_chars = 0; if( FB_HANDLE_IS_SCREEN(handle) ) { while( read_chars != chars ) { res = fb_FileGetDataEx( handle, 0, (void *)&dst[read_chars], chars - read_chars, &len, TRUE, TRUE ); if( res != FB_RTERROR_OK ) break; read_chars += len; } } else { res = fb_FileGetDataEx( handle, 0, (void *)dst, chars, &len, TRUE, TRUE ); read_chars = chars; } if( res == FB_RTERROR_OK ) { dst[read_chars] = _LC('\0'); } else { fb_wstr_Del( dst ); dst = NULL; } } else res = FB_RTERROR_OUTOFMEM; FB_UNLOCK(); return dst; }
/*:::::*/ int fb_DevLptOpen( FB_FILE *handle, const char *filename, size_t filename_len ) { DEV_LPT_PROTOCOL *lpt_proto; DEV_LPT_INFO *devInfo; FB_FILE *redir_handle = NULL; FB_FILE *tmp_handle = NULL; int res; if (!fb_DevLptParseProtocol( &lpt_proto, filename, filename_len , TRUE) ) { if( lpt_proto ) free( lpt_proto ); return fb_ErrorSetNum( FB_RTERROR_ILLEGALFUNCTIONCALL ); } FB_LOCK(); /* Determine the port number and a normalized device name */ devInfo = (DEV_LPT_INFO*) calloc(1, sizeof(DEV_LPT_INFO)); devInfo->uiRefCount = 1; devInfo->iPort = lpt_proto->iPort; devInfo->pszDevice = fb_DevLptMakeDeviceName( lpt_proto ); devInfo->driver_opaque = NULL; /* Test if the printer is already open. */ tmp_handle = fb_DevLptFindDeviceByName( devInfo->iPort, devInfo->pszDevice, FALSE ); if( tmp_handle ) { free(devInfo); redir_handle = tmp_handle; devInfo = (DEV_LPT_INFO*) tmp_handle->opaque; ++devInfo->uiRefCount; } /* Open the printer if not opened already */ if( devInfo->driver_opaque == NULL ) { res = fb_PrinterOpen( devInfo, devInfo->iPort, filename ); } else { res = fb_ErrorSetNum( FB_RTERROR_OK ); if( FB_HANDLE_USED(redir_handle) ) { /* We only allow redirection between OPEN "LPT1:" and LPRINT */ if( handle==FB_HANDLE_PRINTER ) { redir_handle->redirection_to = handle; handle->width = redir_handle->width; handle->line_length = redir_handle->line_length; } else { handle->redirection_to = redir_handle; } } else { handle->width = 80; } } if( res == FB_RTERROR_OK ) { handle->hooks = &hooks_dev_lpt; handle->opaque = devInfo; handle->type = FB_FILE_TYPE_PRINTER; } else { if( devInfo->pszDevice ) free( devInfo->pszDevice ); free( devInfo ); } if( lpt_proto ) free( lpt_proto ); FB_UNLOCK(); return res; }
/*:::::*/ int fb_FileGetDataEx( FB_FILE *handle, fb_off_t pos, void *dst, size_t length, size_t *bytesread, int adjust_rec_pos, int is_unicode ) { int res; size_t chars, read_chars; char *pachData = (char *)dst; if( bytesread ) *bytesread = 0; if( !FB_HANDLE_USED(handle) ) return fb_ErrorSetNum( FB_RTERROR_ILLEGALFUNCTIONCALL ); if( pos < 0 ) return fb_ErrorSetNum( FB_RTERROR_ILLEGALFUNCTIONCALL ); FB_LOCK(); res = fb_ErrorSetNum( FB_RTERROR_OK ); chars = length; /* seek to newpos */ if( pos > 0 ) res = fb_FileSeekEx( handle, pos ); /* any data in the put-back buffer? */ if( handle->putback_size != 0 ) { size_t bytes, len; FB_WCHAR *wcp; char *cp; bytes = chars; if( handle->encod != FB_FILE_ENCOD_ASCII ) bytes *= sizeof( FB_WCHAR ); bytes = (handle->putback_size >= bytes? bytes : handle->putback_size); if( !is_unicode ) { if( handle->encod == FB_FILE_ENCOD_ASCII ) memcpy( pachData, handle->putback_buffer, bytes ); else { cp = pachData; wcp = (FB_WCHAR *)handle->putback_buffer; len = bytes; while( len > 0 ) { *cp++ = *wcp++; len -= sizeof( FB_WCHAR ); } } } else { if( handle->encod != FB_FILE_ENCOD_ASCII ) memcpy( pachData, handle->putback_buffer, bytes ); else { cp = pachData; wcp = (FB_WCHAR *)handle->putback_buffer; len = bytes; while( len-- > 0 ) *wcp++ = *cp++; } } handle->putback_size -= bytes; if( handle->putback_size != 0 ) { memmove( handle->putback_buffer, handle->putback_buffer + bytes, handle->putback_size ); } pachData += bytes; if( handle->encod != FB_FILE_ENCOD_ASCII ) bytes /= sizeof( FB_WCHAR ); read_chars = bytes; chars -= bytes; } else read_chars = 0; if ( (res == FB_RTERROR_OK) && (chars != 0) ) { /* do read */ if( !is_unicode ) { if( handle->hooks->pfnRead == NULL ) res = fb_ErrorSetNum( FB_RTERROR_ILLEGALFUNCTIONCALL ); else { res = handle->hooks->pfnRead( handle, pachData, &chars ); read_chars += chars; } } else { if( handle->hooks->pfnReadWstr == NULL ) res = fb_ErrorSetNum( FB_RTERROR_ILLEGALFUNCTIONCALL ); else { res = handle->hooks->pfnReadWstr( handle, (FB_WCHAR *)pachData, &chars ); read_chars += chars; } } } if( handle->mode == FB_FILE_MODE_RANDOM && res == FB_RTERROR_OK && adjust_rec_pos && handle->len != 0 && handle->hooks->pfnSeek != NULL ) { /* if in random mode, reads must be of reclen. * The device must also support the SEEK method and the length * must be non-null */ if( length != handle->len ) res = fb_ErrorSetNum( FB_RTERROR_FILEIO ); size_t skip_size = (handle->len - ((!is_unicode? read_chars: read_chars*sizeof( FB_WCHAR )) % handle->len)) % handle->len; if( skip_size != 0 ) { /* don't forget the put back buffer */ if( skip_size > handle->putback_size ) { skip_size -= handle->putback_size; handle->putback_size = 0; } else { handle->putback_size -= skip_size; skip_size = 0; } } if (skip_size!=0) { /* devices that don't support seek should simulate it with read or never allow to be opened for random access */ handle->hooks->pfnSeek( handle, skip_size, SEEK_CUR ); } } if( bytesread ) *bytesread = read_chars; FB_UNLOCK(); /* set the error code again - handle->hooks->pfnSeek() may have reset it */ return fb_ErrorSetNum( res ); }