/*:::::*/ 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++]; } }
FBCALL ssize_t fb_StrLen( void *str, ssize_t str_size ) { ssize_t len; if( str == NULL ) return 0; /* is dst var-len? */ if( str_size == -1 ) { len = FB_STRSIZE( str ); /* delete temp? */ fb_hStrDelTemp( (FBSTRING *)str ); } else { /* this routine will never be called for fixed-len strings, as their sizes are known at compiler-time, as such, this must be a zstring, so find out the real len (as in C/PB) */ len = strlen( (char *)str ); } return len; }
/*:::::*/ 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++]; } }
/*:::::*/ FBCALL long long fb_VALLNG ( FBSTRING *str ) { long long val; if( str == NULL ) return 0; if( (str->data == NULL) || (FB_STRSIZE( str ) == 0) ) val = 0; else val = fb_hStr2Longint( str->data, FB_STRSIZE( str ) ); /* del if temp */ fb_hStrDelTemp( str ); return val; }
FBCALL int fb_VALINT ( FBSTRING *str ) { int val; if( str == NULL ) return 0; if( (str->data == NULL) || (FB_STRSIZE( str ) == 0) ) val = 0; else val = fb_hStr2Int( str->data, FB_STRSIZE( str ) ); /* del if temp */ fb_hStrDelTemp( str ); return val; }
/*:::::*/ FBCALL void fb_StrAssignMid ( FBSTRING *dst, int start, int len, FBSTRING *src ) { int src_len, dst_len; FB_STRLOCK(); if( (dst == NULL) || (dst->data == NULL) || (FB_STRSIZE( dst ) == 0) ) { fb_hStrDelTemp_NoLock( src ); fb_hStrDelTemp_NoLock( dst ); FB_STRUNLOCK(); return; } if( (src == NULL) || (src->data == NULL) || (FB_STRSIZE( src ) == 0) ) { fb_hStrDelTemp_NoLock( src ); fb_hStrDelTemp_NoLock( dst ); FB_STRUNLOCK(); return ; } src_len = FB_STRSIZE( src ); dst_len = FB_STRSIZE( dst ); if( (start > 0) && (start <= dst_len) && (len != 0) ) { --start; if( (len < 0) || (len > src_len) ) len = src_len; if( start + len > dst_len ) len = (dst_len - start); memcpy( dst->data + start, src->data, len ); } /* del if temp */ fb_hStrDelTemp_NoLock( src ); fb_hStrDelTemp_NoLock( dst ); FB_STRUNLOCK(); }
/*:::::*/ void fb_PrintStringEx ( FB_FILE *handle, FBSTRING *s, int mask ) { if( (s == NULL) || (s->data == NULL) ) fb_PrintVoidEx( handle, mask ); else fb_hPrintStrEx( handle, s->data, FB_STRSIZE(s), mask ); /* del if temp */ fb_hStrDelTemp( s ); }
/*:::::*/ FBCALL int fb_StrInstrRevAny ( FBSTRING *src, FBSTRING *patt, int start ) { int r = 0; if( (src != NULL) && (src->data != NULL) && (patt != NULL) && (patt->data != NULL) ) { size_t size_src = FB_STRSIZE(src); size_t size_patt = FB_STRSIZE(patt); if( (size_src != 0) && (size_patt != 0) && (start != 0) ) { if( start < 0 ) start = size_src; else if( start > size_src ) start = 0; while( start-- && (r == 0) ) { size_t i; for( i = 0; i != size_patt; ++i ) { if( src->data[start] == patt->data[i] ) { r = start + 1; break; } } } } } FB_STRLOCK(); /* del if temp */ fb_hStrDelTemp_NoLock( src ); fb_hStrDelTemp_NoLock( patt ); FB_STRUNLOCK(); return r; }
FBCALL FBSTRING *fb_StrUcase2( FBSTRING *src, int mode ) { FBSTRING *dst; ssize_t i, len = 0; int c; char *s, *d; if( src == NULL ) return &__fb_ctx.null_desc; FB_STRLOCK(); if( src->data ) { len = FB_STRSIZE( src ); /* alloc temp string */ dst = fb_hStrAllocTemp_NoLock( NULL, len ); } else { dst = NULL; } if( dst ) { s = src->data; d = dst->data; if( mode == 1 ) { for( i = 0; i < len; i++ ) { c = *s++; if( (c >= 97) && (c <= 122) ) c -= 97 - 65; *d++ = c; } } else { for( i = 0; i < len; i++ ) { c = *s++; if( islower( c ) ) c = toupper( c ); *d++ = c; } } /* null char */ *d = '\0'; } else { dst = &__fb_ctx.null_desc; } /* del if temp */ fb_hStrDelTemp_NoLock( src ); FB_STRUNLOCK(); return dst; }
/*:::::*/ int fb_ConsoleLineInputWstr( const FB_WCHAR *text, FB_WCHAR *dst, int max_chars, int addquestion, int addnewline ) { int res; size_t len; int old_x, old_y; /* !!!FIXME!!! no support for unicode input */ fb_PrintBufferEx( NULL, 0, FB_PRINT_FORCE_ADJUST ); fb_GetXY( &old_x, &old_y ); FB_LOCK(); if( text != NULL ) { fb_PrintWstr( 0, text, 0 ); if( addquestion != FB_FALSE ) fb_PrintFixString( 0, pszDefaultQuestion, 0 ); } { FBSTRING str_result = { 0 }; res = fb_DevFileReadLineDumb( stdin, &str_result, hWrapper ); len = FB_STRSIZE(&str_result); if( !addnewline ) { int cols, rows; int old_y; fb_GetSize( &cols, &rows ); fb_GetXY( NULL, &old_y ); old_x += len - 1; old_x %= cols; old_x += 1; old_y -= 1; fb_Locate( old_y, old_x, -1, 0, 0 ); } fb_WstrAssignFromA( dst, max_chars, (void *)&str_result, -1 ); fb_StrDelete( &str_result ); } FB_UNLOCK(); return res; }
FBCALL void fb_GfxSetWindowTitle(FBSTRING *title) { fb_hMemSet(window_title_buff, 0, WINDOW_TITLE_SIZE); fb_hMemCpy(window_title_buff, title->data, MIN(WINDOW_TITLE_SIZE - 1, FB_STRSIZE(title))); __fb_window_title = window_title_buff; if ((__fb_gfx) && (__fb_gfx->driver->set_window_title)) __fb_gfx->driver->set_window_title(__fb_window_title); /* del if temp */ fb_hStrDelTemp( title ); }
FBCALL FBSTRING *fb_StrFill2( ssize_t cnt, FBSTRING *src ) { FBSTRING *dst; int fchar; if( (cnt > 0) && (src != NULL) && (src->data != NULL) && (FB_STRSIZE( src ) > 0) ) { fchar = src->data[0]; dst = fb_StrFill1( cnt, fchar ); } else dst = &__fb_ctx.null_desc; /* del if temp */ fb_hStrDelTemp( src ); return dst; }
/*:::::*/ FBCALL FBSTRING *fb_RTRIM ( FBSTRING *src ) { FBSTRING *dst; int len; if( src == NULL ) return &__fb_ctx.null_desc; FB_STRLOCK(); len = 0; if( src->data != NULL ) { len = FB_STRSIZE( src ); if( len > 0 ) { char *src_ptr = fb_hStrSkipCharRev( src->data, len, 32 ); len = (int)(src_ptr - src->data) + 1; } } if( len > 0 ) { /* alloc temp string */ dst = fb_hStrAllocTemp_NoLock( NULL, len ); if( dst != NULL ) { /* simple copy */ fb_hStrCopy( dst->data, src->data, len ); } else dst = &__fb_ctx.null_desc; } else dst = &__fb_ctx.null_desc; /* del if temp */ fb_hStrDelTemp_NoLock( src ); FB_STRUNLOCK(); return dst; }
FBCALL FBSTRING *fb_StrAllocTempDescV( FBSTRING *str ) { FBSTRING *dsc; FB_STRLOCK(); /* alloc a temporary descriptor */ dsc = fb_hStrAllocTmpDesc( ); FB_STRUNLOCK(); if( dsc == NULL ) return &__fb_ctx.null_desc; dsc->data = str->data; dsc->len = FB_STRSIZE( str ); dsc->size = str->size; return dsc; }
FBCALL FBSTRING *fb_LEFT( FBSTRING *src, ssize_t chars ) { FBSTRING *dst; ssize_t len, src_len; if( src == NULL ) return &__fb_ctx.null_desc; FB_STRLOCK(); src_len = FB_STRSIZE( src ); if( (src->data != NULL) && (chars > 0) && (src_len > 0) ) { if( chars > src_len ) len = src_len; else len = chars; /* alloc temp string */ dst = fb_hStrAllocTemp_NoLock( NULL, len ); if( dst != NULL ) { /* simple copy */ fb_hStrCopy( dst->data, src->data, len ); } else dst = &__fb_ctx.null_desc; } else dst = &__fb_ctx.null_desc; /* del if temp */ fb_hStrDelTemp_NoLock( src ); FB_STRUNLOCK(); return dst; }
/*:::::*/ FBCALL int fb_ExecEx ( FBSTRING *program, FBSTRING *args, int do_fork ) { char buffer[MAX_PATH+1], *application, *arguments; int res = 0, got_program; size_t len_arguments; #ifndef HOST_MINGW size_t len_program; #endif got_program = (program != NULL) && (program->data != NULL); if( !got_program ) { fb_hStrDelTemp( args ); fb_hStrDelTemp( program ); return -1; } application = fb_hGetShortPath( program->data, buffer, MAX_PATH ); DBG_ASSERT( application!=NULL ); if( application==program->data ) { application = buffer; FB_MEMCPY(application, program->data, FB_STRSIZE( program ) ); } #ifdef HOST_MINGW if( args==NULL ) { arguments = ""; } else { len_arguments = FB_STRSIZE( args ); arguments = alloca( len_arguments + 1 ); DBG_ASSERT( arguments!=NULL ); if( len_arguments ) FB_MEMCPY( arguments, args->data, len_arguments ); arguments[len_arguments] = 0; } #else len_program = strlen( buffer ); len_arguments = ( ( args==NULL ) ? 0 : FB_STRSIZE( args ) ); arguments = alloca( len_program + len_arguments + 2 ); DBG_ASSERT( arguments!=NULL ); FB_MEMCPY( arguments, buffer, len_program ); arguments[len_program] = ' '; if( len_arguments!=0 ) FB_MEMCPY( arguments + len_program + 1, args->data, len_arguments ); arguments[len_program + len_arguments + 1] = 0; #endif FB_STRLOCK(); fb_hStrDelTemp_NoLock( args ); fb_hStrDelTemp_NoLock( program ); FB_STRUNLOCK(); FB_CON_CORRECT_POSITION(); { #ifdef HOST_MINGW if( do_fork ) res = _spawnl( _P_WAIT, buffer, buffer, arguments, NULL ); else res = _execl( buffer, buffer, arguments, NULL ); #else STARTUPINFO StartupInfo; PROCESS_INFORMATION ProcessInfo; memset( &StartupInfo, 0, sizeof(StartupInfo) ); StartupInfo.cb = sizeof(StartupInfo); if( !CreateProcess( NULL, /* application name - correct! */ arguments, /* command line */ NULL, NULL, /* default security descriptors */ FALSE, /* don't inherit handles */ CREATE_DEFAULT_ERROR_MODE, /* do we really need this? */ NULL, /* default environment */ NULL, /* current directory */ &StartupInfo, &ProcessInfo ) ) { res = -1; } else { /* Release main thread handle - we're not interested in it */ CloseHandle( ProcessInfo.hThread ); if( do_fork ) { DWORD dwExitCode; WaitForSingleObject( ProcessInfo.hProcess, INFINITE ); if( !GetExitCodeProcess( ProcessInfo.hProcess, &dwExitCode ) ) { res = -1; } else { res = (int) dwExitCode; } CloseHandle( ProcessInfo.hProcess ); } else { res = (int) ProcessInfo.hProcess; } } #endif } return res; }
FBCALL FBSTRING *fb_LTrimAny ( FBSTRING *src, FBSTRING *pattern ) { const char *pachText = NULL; FBSTRING *dst; ssize_t len; if( src == NULL ) { fb_hStrDelTemp( pattern ); return &__fb_ctx.null_desc; } FB_STRLOCK(); len = 0; if( src->data != NULL ) { ssize_t len_pattern = ((pattern != NULL) && (pattern->data != NULL)? FB_STRSIZE( pattern ) : 0); pachText = src->data; len = FB_STRSIZE( src ); if( len_pattern != 0 ) { while ( len != 0 ) { ssize_t i; for( i=0; i!=len_pattern; ++i ) { if( FB_MEMCHR( pattern->data, *pachText, len_pattern )!=NULL ) break; } if( i==len_pattern ) break; --len; ++pachText; } } } if( len > 0 ) { /* alloc temp string */ dst = fb_hStrAllocTemp_NoLock( NULL, len ); if( dst != NULL ) { /* simple copy */ fb_hStrCopy( dst->data, pachText, len ); } else dst = &__fb_ctx.null_desc; } else dst = &__fb_ctx.null_desc; /* del if temp */ fb_hStrDelTemp_NoLock( src ); fb_hStrDelTemp_NoLock( pattern ); FB_STRUNLOCK(); return dst; }
FBCALL FBSTRING *fb_ConReadLine( int soft_cursor ) { FBSTRING result = { 0 }; int current_x, current_y; int cols, rows; size_t pos, len, tmp_buffer_len = 0; int cursor_visible; int k; char ch, tmp_buffer[12]; fb_GetSize(&cols, &rows); cursor_visible = (fb_Locate( 0, 0, -1, 0, 0 ) & 0x10000) != 0; fb_Locate( 0, 0, FALSE, 0, 0 ); pos = len = 0; fb_PrintBufferEx( NULL, 0, 0 ); /* Ensure that the cursor is visible during INPUT */ fb_Locate( 0, 0, (soft_cursor == FALSE), 0, 0 ); do { size_t delete_char_count = 0, add_char = FALSE; FBSTRING *sTmp; fb_GetXY(¤t_x, ¤t_y); if( soft_cursor ) { fb_PrintFixString( 0, "\377", 0 ); fb_Locate( current_y, current_x, FALSE, 0, 0 ); } while( fb_KeyHit( ) == 0 ) { fb_Delay( 25 ); /* release time slice */ } sTmp = fb_Inkey( ); if( sTmp->data != NULL ) { if( FB_STRSIZE(sTmp) == 2 ) { k = FB_MAKE_EXT_KEY(sTmp->data[1]); ch = 0; } else { k = FB_MAKE_KEY(ch = sTmp->data[0]); } fb_hStrDelTemp( sTmp ); } else { k = 0; continue; } if( soft_cursor ) { char mask[2] = { ((result.data != NULL) && (pos < len)? result.data[pos]: ' '), '\0' }; fb_PrintFixString( 0, mask, 0 ); fb_Locate( current_y, current_x, FALSE, 0, 0 ); } switch (k) { case 8: /* DEL */ if (pos!=0) { DoMove( ¤t_x, ¤t_y, -1, 0, cols, rows ); --pos; delete_char_count = 1; } break; case 9: /* TAB */ tmp_buffer_len = ((pos + 8) / 8 * 8) - pos; memset(tmp_buffer, 32, tmp_buffer_len); add_char = TRUE; break; case 27: /* ESC */ DoMove( ¤t_x, ¤t_y, -pos, 0, cols, rows ); pos = 0; delete_char_count = len; break; case FB_MAKE_EXT_KEY(0x53): /* CLeaR */ if( len!=pos ) { delete_char_count = 1; } else { fb_Beep(); } break; case FB_MAKE_EXT_KEY(0x4B): /* Cursor LEFT */ if( pos != 0 ) { DoMove( ¤t_x, ¤t_y, -1, 0, cols, rows ); --pos; } break; case FB_MAKE_EXT_KEY(0x4D): /* Cursor RIGHT */ if( pos != len ) { DoMove( ¤t_x, ¤t_y, 1, 0, cols, rows ); ++pos; } break; case FB_MAKE_EXT_KEY(0x47): /* HOME */ DoMove( ¤t_x, ¤t_y, -pos, 0, cols, rows ); pos = 0; break; case FB_MAKE_EXT_KEY(0x4F): /* END */ DoMove( ¤t_x, ¤t_y, len-pos, 0, cols, rows ); pos = len; break; case FB_MAKE_EXT_KEY(0x48): /* Cursor UP */ if( pos >= cols) { DoMove( ¤t_x, ¤t_y, -cols, 0, cols, rows ); pos -= cols; } break; case FB_MAKE_EXT_KEY(0x50): /* Cursor DOWN */ if( ( pos + cols ) <= len ) { DoMove( ¤t_x, ¤t_y, cols, 0, cols, rows ); pos += cols; } break; default: if( k>=32 && k<=255 ) { tmp_buffer[0] = (char) k; tmp_buffer_len = 1; add_char = TRUE; /* DoMove( ¤t_x, ¤t_y, 1, 0, cols ); */ } break; } if( delete_char_count!=0 || add_char ) { /* Turn off the cursor during output (speed-up) */ fb_Locate( 0, 0, FALSE, 0, 0 ); } if( delete_char_count ) { FBSTRING *str_fill; FBSTRING *str_left = fb_StrMid( &result, 1, pos ); FBSTRING *str_right = fb_StrMid( &result, pos + 1 + delete_char_count, len - pos - delete_char_count); fb_StrAssign( &result, -1, str_left, -1, FALSE ); fb_StrConcatAssign( &result, -1, str_right, -1, FALSE ); len -= delete_char_count; FB_LOCK(); fb_PrintBufferEx( result.data + pos, len - pos, 0 ); /* Overwrite all deleted characters with SPC's */ str_fill = fb_StrFill1 ( delete_char_count, ' ' ); fb_PrintBufferEx( str_fill->data, delete_char_count, 0 ); fb_hStrDelTemp( str_fill ); fb_Locate( current_y, current_x, -1, 0, 0 ); FB_UNLOCK(); } if( add_char ) { tmp_buffer[tmp_buffer_len] = 0; } if( add_char ) { int old_x = current_x, old_y = current_y; FBSTRING *str_add = fb_StrAllocTempDescF( tmp_buffer, tmp_buffer_len + 1 ); FBSTRING *str_left = fb_StrMid( &result, 1, pos ); FBSTRING *str_right = fb_StrMid( &result, pos + 1, len - pos); fb_StrAssign( &result, -1, str_left, -1, FALSE ); fb_StrConcatAssign( &result, -1, str_add, -1, FALSE ); fb_StrConcatAssign( &result, -1, str_right, -1, FALSE ); len += tmp_buffer_len; FB_LOCK(); fb_PrintBufferEx( result.data + pos, len - pos, 0 ); fb_GetXY(¤t_x, ¤t_y); if( pos==(len-tmp_buffer_len) ) { current_x = old_x; current_y = old_y; DoMove( ¤t_x, ¤t_y, tmp_buffer_len, 0, cols, rows ); } else { int tmp_x_2 = old_x, tmp_y_2 = old_y; DoAdjust( &tmp_x_2, &tmp_y_2, len - pos, 0, cols, rows ); if( tmp_y_2 > (rows+1) || (tmp_y_2==(rows+1) && tmp_x_2>1) ) { DoMove( ¤t_x, ¤t_y, -(len - pos - tmp_buffer_len), 0, cols, rows ); } else { current_x = old_x; current_y = old_y; DoMove( ¤t_x, ¤t_y, tmp_buffer_len, 0, cols, rows ); } } pos += tmp_buffer_len; FB_UNLOCK(); } fb_Locate( 0, 0, (soft_cursor == FALSE), 0, 0 ); } while (k!='\r' && k!='\n'); FB_LOCK(); /* set cursor to end of line */ fb_GetXY(¤t_x, ¤t_y); DoMove( ¤t_x, ¤t_y, len - pos, 0, cols, rows ); /* Restore old cursor visibility */ fb_Locate( 0, 0, cursor_visible, 0, 0 ); FB_UNLOCK(); return fb_StrAllocTempResult( &result ); }
/*:::::*/ FBCALL void fb_GfxPaint(void *target, float fx, float fy, unsigned int color, unsigned int border_color, FBSTRING *pattern, int mode, int flags) { FB_GFXCTX *context = fb_hGetContext(); int size, x, y; unsigned char data[256], *dest, *src; SPAN **span, *s, *tail, *head; if (!__fb_gfx) return; fb_hPrepareTarget(context, target); if (flags & DEFAULT_COLOR_1) color = context->fg_color; else color = fb_hFixColor(context->target_bpp, color); if (flags & DEFAULT_COLOR_2) border_color = color; else border_color = fb_hFixColor(context->target_bpp, border_color); fb_hSetPixelTransfer(context,color); fb_hFixRelative(context, flags, &fx, &fy, NULL, NULL); fb_hTranslateCoord(context, fx, fy, &x, &y); fb_hMemSet(data, 0, sizeof(data)); if ((mode == PAINT_TYPE_PATTERN) && (pattern)) { fb_hMemCpy(data, pattern->data, MIN(256, FB_STRSIZE(pattern))); } if (pattern) { /* del if temp */ fb_hStrDelTemp( pattern ); } if ((x < context->view_x) || (x >= context->view_x + context->view_w) || (y < context->view_y) || (y >= context->view_y + context->view_h)) return; if (context->get_pixel(context, x, y) == border_color) return; size = sizeof(SPAN *) * (context->view_y + context->view_h); span = (SPAN **)malloc(size); fb_hMemSet(span, 0, size); tail = head = add_span(context, span, &x, y, border_color); /* Find all spans to paint */ while (tail) { if (tail->y - 1 >= context->view_y) { for (x = tail->x1; x <= tail->x2; x++) { if (context->get_pixel(context, x, tail->y - 1) != border_color) { s = add_span(context, span, &x, tail->y - 1, border_color); if (s) { head->next = s; head = s; } } } } if (tail->y + 1 < context->view_y + context->view_h) { for (x = tail->x1; x <= tail->x2; x++) { if (context->get_pixel(context, x, tail->y + 1) != border_color) { s = add_span(context, span, &x, tail->y + 1, border_color); if (s) { head->next = s; head = s; } } } } tail = tail->next; } DRIVER_LOCK(); /* Fill spans */ for (y = context->view_y; y < context->view_y + context->view_h; y++) { for (s = tail = span[y]; s; s = s->row_next, free(tail), tail = s) { dest = context->line[s->y] + (s->x1 * context->target_bpp); if (mode == PAINT_TYPE_FILL) context->pixel_set(dest, color, s->x2 - s->x1 + 1); else { src = data + (((s->y & 0x7) << 3) * context->target_bpp); if (s->x1 & 0x7) { if ((s->x1 & ~0x7) == (s->x2 & ~0x7)) size = s->x2 - s->x1 + 1; else size = 8 - (s->x1 & 0x7); fb_hPixelCpy(dest, src + ((s->x1 & 0x7) * context->target_bpp), size); dest += size * context->target_bpp; } s->x2++; for (x = (s->x1 + 7) >> 3; x < (s->x2 & ~0x7) >> 3; x++) { fb_hPixelCpy(dest, src, 8); dest += 8 * context->target_bpp; } if ((s->x2 & 0x7) && ((s->x1 & ~0x7) != (s->x2 & ~0x7))) fb_hPixelCpy(dest, src, s->x2 & 0x7); } if (__fb_gfx->framebuffer == context->line[0]) __fb_gfx->dirty[context->view_y + y] = TRUE; } } free(span); DRIVER_UNLOCK(); }
FBCALL FBSTRING *fb_Dir( FBSTRING *filespec, int attrib, int *out_attrib ) { FB_DIRCTX *ctx; FBSTRING *res; ssize_t len; int tmp_attrib; char *name, *p; struct stat info; if( out_attrib == NULL ) out_attrib = &tmp_attrib; len = FB_STRSIZE( filespec ); name = NULL; ctx = FB_TLSGETCTX( DIR ); if( len > 0 ) { /* findfirst */ if( ctx->in_use ) close_dir( ); if( strchr( filespec->data, '*' ) || strchr( filespec->data, '?' ) ) { /* we have a pattern */ p = strrchr( filespec->data, '/' ); if( p ) { strncpy( ctx->filespec, p + 1, MAX_PATH ); ctx->filespec[MAX_PATH-1] = '\0'; len = (p - filespec->data) + 1; if( len > MAX_PATH - 1 ) len = MAX_PATH - 1; memcpy( ctx->dirname, filespec->data, len ); ctx->dirname[len] = '\0'; } else { strncpy( ctx->filespec, filespec->data, MAX_PATH ); ctx->filespec[MAX_PATH-1] = '\0'; strcpy( ctx->dirname, "./"); } /* Make sure these patterns work just like on Win32/DOS */ if( (!strcmp( ctx->filespec, "*.*" )) || (!strcmp( ctx->filespec, "*." )) ) strcpy( ctx->filespec, "*" ); if( (attrib & 0x10) == 0 ) attrib |= 0x20; ctx->attrib = attrib; ctx->dir = opendir( ctx->dirname ); if( ctx->dir ) { name = find_next( out_attrib ); if( name ) ctx->in_use = TRUE; } } else { /* no pattern, use stat on single file */ if( !stat( filespec->data, &info ) ) { tmp_attrib = get_attrib( filespec->data, &info ); if( (tmp_attrib & ~attrib ) == 0 ) { name = strrchr( filespec->data, '/' ); if( !name ) name = filespec->data; else name++; *out_attrib = tmp_attrib; } } } } else { /* findnext */ if( ctx->in_use ) name = find_next( out_attrib ); } FB_STRLOCK(); /* store filename if found */ if( name ) { len = strlen( name ); res = fb_hStrAllocTemp_NoLock( NULL, len ); if( res ) fb_hStrCopy( res->data, name, len ); else res = &__fb_ctx.null_desc; } else { res = &__fb_ctx.null_desc; *out_attrib = 0; } fb_hStrDelTemp_NoLock( filespec ); FB_STRUNLOCK(); return res; }
FBCALL void *fb_WstrAssignToAEx ( void *dst, ssize_t dst_chars, FB_WCHAR *src, int fill_rem, int is_init ) { ssize_t src_chars; if( dst == NULL ) return dst; if( src != NULL ) src_chars = fb_wstr_Len( src ); else src_chars = 0; /* is dst var-len? */ if( dst_chars == -1 ) { /* src NULL? */ if( src_chars == 0 ) { if( is_init == FB_FALSE ) { fb_StrDelete( (FBSTRING *)dst ); } else { ((FBSTRING *)dst)->data = NULL; ((FBSTRING *)dst)->len = 0; ((FBSTRING *)dst)->size = 0; } } else { /* realloc dst if needed and copy src */ if( is_init == FB_FALSE ) { if( FB_STRSIZE( dst ) != src_chars ) fb_hStrRealloc( (FBSTRING *)dst, src_chars, FB_FALSE ); } else { fb_hStrAlloc( (FBSTRING *)dst, src_chars ); } fb_wstr_ConvToA( ((FBSTRING *)dst)->data, src, src_chars ); } } /* fixed-len or zstring.. */ else { /* src NULL? */ if( src_chars == 0 ) { *(char *)dst = '\0'; } else { /* byte ptr? as in C, assume dst is large enough */ if( dst_chars == 0 ) dst_chars = src_chars; fb_wstr_ConvToA( (char *)dst, src, (dst_chars <= src_chars? dst_chars : src_chars) ); } /* fill reminder with null's */ if( fill_rem != 0 ) { dst_chars -= src_chars; if( dst_chars > 0 ) memset( &(((char *)dst)[src_chars]), 0, dst_chars ); } } return dst; }
/*:::::*/ FBCALL int fb_ExecEx ( FBSTRING *program, FBSTRING *args, int do_fork ) { char buffer[MAX_PATH+1], *application, *arguments, **argv, *p; int i, argc = 0, res = -1, status, len_program, len_arguments; pid_t pid; if( (program == NULL) || (program->data == NULL) ) { fb_hStrDelTemp( args ); fb_hStrDelTemp( program ); return -1; } application = fb_hGetShortPath( program->data, buffer, MAX_PATH ); DBG_ASSERT( application!=NULL ); if( application==program->data ) { len_program = FB_STRSIZE( program ); application = buffer; FB_MEMCPY(application, program->data, len_program ); application[len_program] = 0; } fb_hConvertPath( application ); if( args==NULL ) { arguments = ""; } else { len_arguments = FB_STRSIZE( args ); arguments = alloca( len_arguments + 1 ); DBG_ASSERT( arguments!=NULL ); arguments[len_arguments] = 0; if( len_arguments ) argc = fb_hParseArgs( arguments, args->data, len_arguments ); } FB_STRLOCK(); fb_hStrDelTemp_NoLock( args ); fb_hStrDelTemp_NoLock( program ); FB_STRUNLOCK(); if( argc == -1 ) return -1; argc++; /* add 1 for program name */ argv = alloca( sizeof(char*) * (argc + 1 )); DBG_ASSERT( argv!=NULL ); argv[0] = application; /* scan the processed args and set pointers */ p = arguments; for( i=1 ; i<argc; i++) { argv[i] = p; /* set pointer to current argument */ while( *p++ ); /* skip to 1 char past next null char */ } argv[argc] = NULL; /* Launch */ fb_hExitConsole(); if( do_fork ) { pid = fork(); if( pid != -1 ) { if (pid == 0) { /* execvp() only returns if it failed */ execvp( application, argv ); /* HACK: execvp() failed, this must be communiated to the parent process *somehow*, so fb_ExecEx() can return -1 there */ exit( 255 ); /* FIXME: won't be able to tell the difference if the exec'ed program returned 255. Maybe a pipe could be used instead of the 255 exit code? Unless that's too slow/has side-effects */ } else if( (waitpid(pid, &status, 0) > 0) && WIFEXITED(status) ) { res = WEXITSTATUS(status); if( res == 255 ) { /* See the HACK above */ res = -1; } } } } else { res = execvp( application, argv ); } fb_hInitConsole(); return res; }
/*:::::*/ int fb_ConsoleLineInput( FBSTRING *text, void *dst, int dst_len, int fillrem, int addquestion, int addnewline ) { int res; size_t len; int old_x, old_y; fb_PrintBufferEx( NULL, 0, FB_PRINT_FORCE_ADJUST ); fb_GetXY( &old_x, &old_y ); FB_LOCK(); if( text != NULL ) { if( text->data != NULL ) { fb_PrintString( 0, text, 0 ); } /* del if temp */ else { fb_hStrDelTemp( text ); } if( addquestion != FB_FALSE ) { fb_PrintFixString( 0, pszDefaultQuestion, 0 ); } } { /* create temporary string */ FBSTRING str_result = { 0 }; res = fb_DevFileReadLineDumb( stdin, &str_result, hWrapper ); len = FB_STRSIZE(&str_result); /* We have to handle the NEWLINE stuff here because we *REQUIRE* * the *COMPLETE* temporary input string for the correct position * adjustment. */ if( !addnewline ) { /* This is the easy and dumb method to do the position adjustment. * The problem is that it doesn't take TAB's into account. */ int cols, rows; int old_y; fb_GetSize( &cols, &rows ); fb_GetXY( NULL, &old_y ); old_x += len - 1; old_x %= cols; old_x += 1; old_y -= 1; fb_Locate( old_y, old_x, -1, 0, 0 ); } /* add contents of tempporary string to result buffer */ fb_StrAssign( dst, dst_len, (void *)&str_result, -1, fillrem ); fb_StrDelete( &str_result ); } FB_UNLOCK(); return res; }
/*:::::*/ FBCALL FBSTRING *fb_RTrimEx ( FBSTRING *src, FBSTRING *pattern ) { FBSTRING *dst; int len; if( src == NULL ) { fb_hStrDelTemp( pattern ); return &__fb_ctx.null_desc; } FB_STRLOCK(); if( src->data != NULL ) { size_t len_pattern = ((pattern != NULL) && (pattern->data != NULL)? FB_STRSIZE( pattern ) : 0); len = FB_STRSIZE( src ); if( len >= len_pattern ) { if( len_pattern==1 ) { char *src_ptr = fb_hStrSkipCharRev( src->data, len, FB_CHAR_TO_INT(pattern->data[0]) ); len = (int)(src_ptr - src->data) + 1; } else if( len_pattern != 0 ) { char *src_ptr = src->data; size_t test_index = len - len_pattern; while (len >= len_pattern ) { if( FB_MEMCMP( src_ptr + test_index, pattern->data, len_pattern )!=0 ) break; test_index -= len_pattern; } len = test_index + len_pattern; } } } else len = 0; if( len > 0 ) { /* alloc temp string */ dst = fb_hStrAllocTemp_NoLock( NULL, len ); if( dst != NULL ) { /* simple copy */ fb_hStrCopy( dst->data, src->data, len ); } else dst = &__fb_ctx.null_desc; } else dst = &__fb_ctx.null_desc; /* del if temp */ fb_hStrDelTemp_NoLock( src ); fb_hStrDelTemp_NoLock( pattern ); FB_STRUNLOCK(); return dst; }
FBCALL int fb_FileOpenQB ( FBSTRING *str, unsigned int mode, unsigned int access, unsigned int lock, int fnum, int len ) { if( !FB_FILE_INDEX_VALID( fnum ) ) return fb_ErrorSetNum( FB_RTERROR_ILLEGALFUNCTIONCALL ); ssize_t str_len = FB_STRSIZE( str ); if( !str_len || (str->data == NULL) ) return fb_ErrorSetNum( FB_RTERROR_ILLEGALFUNCTIONCALL ); /* serial? */ if( (str_len > 3) && (strncasecmp( str->data, "COM", 3 ) == 0) ) { ssize_t i = 3; while( (i < str_len) && (str->data[i] >= '0') && (str->data[i] <= '9' ) ) ++i; if( str->data[i] == ':' ) { return fb_FileOpenVfsEx( FB_FILE_TO_HANDLE(fnum), str, mode, access, lock, len, FB_FILE_ENCOD_ASCII, fb_DevComOpen ); } } /* parallel? */ else if( (str_len > 3) && (strncasecmp( str->data, "LPT", 3 ) == 0) ) { ssize_t i = 3; while( (i < str_len) && (str->data[i] >= '0') && (str->data[i] <= '9' ) ) ++i; if( str->data[i] == ':' ) { return fb_FileOpenVfsEx( FB_FILE_TO_HANDLE(fnum), str, mode, access, lock, len, FB_FILE_ENCOD_ASCII, fb_DevLptOpen ); } } /* default printer? */ else if( (str_len == 4) && (strcasecmp( str->data, "PRN:" ) == 0) ) { return fb_FileOpenVfsEx( FB_FILE_TO_HANDLE(fnum), str, mode, access, lock, len, FB_FILE_ENCOD_ASCII, fb_DevLptOpen ); } /* console? */ else if( (str_len == 5) && (strcasecmp( str->data, "CONS:" ) == 0) ) { return fb_FileOpenVfsEx( FB_FILE_TO_HANDLE(fnum), str, mode, access, lock, len, FB_FILE_ENCOD_ASCII, fb_DevConsOpen ); } /* screen? */ else if( (str_len == 5) && (strcasecmp( str->data, "SCRN:" ) == 0) ) { fb_DevScrnInit( ); return fb_FileOpenVfsEx( FB_FILE_TO_HANDLE(fnum), str, mode, access, lock, len, FB_FILE_ENCOD_ASCII, fb_DevScrnOpen ); } /* pipe? */ else if( (str_len == 5) && (strcasecmp( str->data, "PIPE:" ) == 0) ) { return fb_FileOpenVfsEx( FB_FILE_TO_HANDLE(fnum), str, mode, access, lock, len, FB_FILE_ENCOD_ASCII, fb_DevPipeOpen ); } /* ordinary file */ return fb_FileOpenEx( FB_FILE_TO_HANDLE(fnum), str, mode, access, lock, len ); }