/*:::::*/ 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; }
void fb_DevScrnInit_Screen( void ) { int cols; DEV_SCRN_INFO *info = (DEV_SCRN_INFO*) malloc(sizeof(DEV_SCRN_INFO)); fb_GetSize( &cols, NULL ); info->length = 0; FB_HANDLE_SCREEN->opaque = info; FB_HANDLE_SCREEN->line_length = fb_GetX() - 1; FB_HANDLE_SCREEN->width = cols; }
FBCALL void fb_PrintSPC( int fnum, ssize_t n ) { FB_FILE *handle; int col, row, cols, rows, newcol; if( n==0 ) return; fb_DevScrnInit_NoOpen( ); FB_LOCK(); handle = FB_FILE_TO_HANDLE(fnum); if( FB_HANDLE_IS_SCREEN(handle) || handle->type == FB_FILE_TYPE_CONSOLE ) { if( n == 0 ) return; if( handle->type == FB_FILE_TYPE_CONSOLE ) { if( handle->hooks && handle->hooks->pfnFlush ) handle->hooks->pfnFlush( handle ); } /* Ensure that we get the "real" cursor position - this quirk is * required for cursor positions at the right bottom of the screen */ fb_PrintBufferEx( NULL, 0, FB_PRINT_FORCE_ADJUST ); fb_GetXY( &col, &row ); fb_GetSize( &cols, &rows ); newcol = col + n; if( newcol > cols ) { fb_PrintVoidEx ( handle, FB_PRINT_NEWLINE ); newcol %= cols; } fb_Locate( 0, newcol, -1, 0, 0 ); } else { fb_PrintStringEx( handle, fb_StrFill1( n, ' ' ), 0 ); } FB_UNLOCK(); }
FBCALL void fb_PrintTab( int fnum, int newcol ) { FB_FILE *handle; int col, row, cols, rows; fb_DevScrnInit_NoOpen( ); FB_LOCK(); handle = FB_FILE_TO_HANDLE(fnum); if( FB_HANDLE_IS_SCREEN(handle) || handle->type == FB_FILE_TYPE_CONSOLE ) { if( handle->type == FB_FILE_TYPE_CONSOLE ) { if( handle->hooks && handle->hooks->pfnFlush ) handle->hooks->pfnFlush( handle ); } /* Ensure that we get the "real" cursor position - this quirk is * required for cursor positions at the right bottom of the screen */ fb_PrintBufferEx( NULL, 0, FB_PRINT_FORCE_ADJUST ); fb_GetXY( &col, &row ); fb_GetSize( &cols, &rows ); if( newcol > cols ) newcol %= cols; if( col > newcol ) { fb_PrintVoidEx ( handle, FB_PRINT_NEWLINE ); fb_Locate( 0, newcol, -1, 0, 0 ); } else if( newcol < 1 ) fb_Locate( 0, 1, -1, 0, 0 ); else fb_Locate( 0, newcol, -1, 0, 0 ); } else { if( handle->type==FB_FILE_TYPE_PIPE ) { fb_PrintPadEx ( handle, 0 ); } else { if( (newcol >= 0) && ((unsigned int)newcol > handle->line_length) ) { fb_PrintStringEx( handle, fb_StrFill1( newcol - handle->line_length - 1, ' ' ), 0 ); } else { if( handle->mode==FB_FILE_MODE_BINARY ) { fb_PrintStringEx( handle, fb_StrAllocTempDescF( FB_BINARY_NEWLINE, sizeof( FB_BINARY_NEWLINE ) ), 0 ); } else { fb_PrintStringEx( handle, fb_StrAllocTempDescF( FB_NEWLINE, sizeof( FB_NEWLINE ) ), 0 ); } if( newcol > 0 ) { fb_PrintStringEx( handle, fb_StrFill1( newcol - 1, ' ' ), 0 ); } } } } FB_UNLOCK(); }
void fb_GfxPrintBufferEx( const void *buffer, size_t len, int mask ) { FB_GFXCTX *context; const char *pachText = (const char *) buffer; int win_left, win_top, win_cols, win_rows; int view_top, view_bottom; fb_PrintInfo info; fb_ConHooks hooks; FB_GRAPHICS_LOCK( ); /* Do we want to correct the console cursor position? */ if( (mask & FB_PRINT_FORCE_ADJUST)==0 ) { /* No, we can check for the length to avoid unnecessary stuff ... */ if( len==0 ) { FB_GRAPHICS_UNLOCK( ); return; } } context = fb_hGetContext( ); fb_hPrepareTarget(context, NULL); fb_hSetPixelTransfer(context, MASK_A_32); DRIVER_LOCK(); fb_GetSize( &win_cols, &win_rows ); fb_ConsoleGetView( &view_top, &view_bottom ); win_left = win_top = 0; hooks.Opaque = &info; hooks.Scroll = fb_hHookConScroll; hooks.Write = fb_hHookConWrite; hooks.Border.Left = win_left; hooks.Border.Top = win_top + view_top - 1; hooks.Border.Right = win_left + win_cols - 1; hooks.Border.Bottom = win_top + view_bottom - 1; info.context = context; info.dirty_start = info.dirty_end = 0; { hooks.Coord.X = __fb_gfx->cursor_x; hooks.Coord.Y = __fb_gfx->cursor_y; if( __fb_gfx->flags & PRINT_SCROLL_WAS_OFF ) { __fb_gfx->flags &= ~PRINT_SCROLL_WAS_OFF; ++hooks.Coord.Y; hooks.Coord.X = hooks.Border.Left; fb_hConCheckScroll( &hooks ); } fb_ConPrintTTY( &hooks, pachText, len, TRUE ); if( hooks.Coord.X != hooks.Border.Left || hooks.Coord.Y != (hooks.Border.Bottom+1) ) { fb_hConCheckScroll( &hooks ); } else { __fb_gfx->flags |= PRINT_SCROLL_WAS_OFF; hooks.Coord.X = hooks.Border.Right; hooks.Coord.Y = hooks.Border.Bottom; } fb_GfxLocateRaw( hooks.Coord.Y, hooks.Coord.X, -1 ); } SET_DIRTY(context, info.dirty_start, info.dirty_end - info.dirty_start); DRIVER_UNLOCK(); FB_GRAPHICS_UNLOCK( ); }
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 ); }
/*:::::*/ 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; }