How to add timeout to FLTK pop-up dialog - fltk

I am using FLTK library and have used a pop-up function fl_input() from Fl_ask.h. I want a feature that if the user doesn't input and data for 3 seconds, the function should return. How can I make this function return without pressing OK or cancel. Is there anyway to get a handle to this pop-up dialog? This is the code I'm using
const char *message = "Enter name here";
Fl::lock();
char *c = (char*)fl_input(message, "");
if(c == NULL)
c = "";
Fl::unlock();

You can't do this easily using fl_input because there is no handle to the window. Have a look at the fl_input source in src/fl_ask.cxx. You will see it calls input_innards. If you track through to input_innards, you'll see that it calls innards. If you then follow innards, you will find a while loop which reads
while (message_form->shown()) Fl::wait();
Make a copy of fl_ask.cxx, say timed_ask.cxx. Make all the fl_ routines static. Change fl_input as follows:
const char* timed_input(double timeout, const char *fmt, const char *defstr, ...) {
if (avoidRecursion) return 0;
va_list ap;
va_start(ap, defstr);
const char* r = timed_input_innards(timeout, fmt, ap, defstr, FL_NORMAL_INPUT);
va_end(ap);
return r;
}
Make a copy of input_innards and rename the new one to timed_input_innards (this keeps the other fl_routines happy unless you want to delete them).
static const char* timed_input_innards(double timeout, const char* fmt, va_list ap,
const char* defstr, uchar type) {
...
int r = timed_innards(timeout, fmt, ap, fl_cancel, fl_ok, 0);
...
Make a copy of innards and rename the new one to timed_innards
static int timed_innards(double timeout, const char* fmt, va_list ap,
const char *b0,
const char *b1,
const char *b2)
{
...
Fl::add_timeout(timeout, hide_form, message_form);
while (message_form->shown()) Fl::wait();
...
}
Add the timeout routine
void hide_form(void* data)
{
// You could do this or use message_form directly
Fl_Window* form = reinterpret_cast<Fl_Window*>(data);
form->hide();
}
This will cause message_form->shown() to be false and exit the while loop.

Related

Converting between WinRT HttpBufferContent and unmanaged memory in C++cx

As part of a WinRT C++cx component, what's the most efficient way to convert an unmanaged buffer of bytes (say expressed as a std::string) back and forth with a Windows::Web::Http::HttpBufferContent?
This is what I ended up with, but it doesn't seem very optimal:
std::string to HttpBufferContent:
std::string m_body = ...;
auto writer = ref new DataWriter();
writer->WriteBytes(ArrayReference<unsigned char>(reinterpret_cast<unsigned char*>(const_cast<char*>(m_body.data())), m_body.length()));
auto content = ref new HttpBufferContent(writer->DetachBuffer());
HttpBufferContent to std::string:
HttpBufferContent^ content = ...
auto operation = content->ReadAsBufferAsync();
auto task = create_task(operation);
if (task.wait() == task_status::completed) {
auto buffer = task.get();
size_t length = buffer->Length;
if (length > 0) {
unsigned char* storage = static_cast<unsigned char*>(malloc(length));
DataReader::FromBuffer(buffer)->ReadBytes(ArrayReference<unsigned char>(storage, length));
auto m_body = std::string(reinterpret_cast<char*>(storage), length);
free(storage);
}
} else {
abort();
}
UPDATE: Here's the version I ended up using (you can trivially create a HttpBufferContent^ from an Windows::Storage::Streams::IBuffer^):
void IBufferToString(IBuffer^ buffer, std::string& string) {
Array<unsigned char>^ array = nullptr;
CryptographicBuffer::CopyToByteArray(buffer, &array); // TODO: Avoid copy
string.assign(reinterpret_cast<char*>(array->Data), array->Length);
}
IBuffer^ StringToIBuffer(const std::string& string) {
auto array = ArrayReference<unsigned char>(reinterpret_cast<unsigned char*>(const_cast<char*>(string.data())), string.length());
return CryptographicBuffer::CreateFromByteArray(array);
}
I think you are making at least one unnecessary copy of your data in your current approach for HttpBufferContent to std::string, you could improve this by accessing the IBuffer data directly, see the accepted answer here: Getting an array of bytes out of Windows::Storage::Streams::IBuffer
I think it's better to use smart pointer (no memory management needed) :
#include <wrl.h>
#include <robuffer.h>
#include <memory>
using namespace Windows::Storage::Streams;
using namespace Microsoft::WRL;
IBuffer^ buffer;
ComPtr<IBufferByteAccess> byte_access;
reinterpret_cast<IInspectable*>(buffer)->QueryInterface(IID_PPV_ARGS(&byte_access));
std::unique_ptr<byte[]> raw_buffer = std::make_unique<byte[]>(buffer->Length);
byte_access->Buffer(raw_buffer.get());
std::string str(reinterpret_cast<char*>(raw_buffer.get())); // just 1 copy

FLTK Fl_Choice obtain selected item

I want to get the selected item of users but it gives an error on this code:
choice->value();
hopes you kind guys can help me.
Fl_Choice* choice;
int i = 0;
void but_cb(Fl_Button* obj, void*)
{
i = choice->value();
cout<<i;
}
int main (int argc, char* argv[]) {
Fl_Double_Window* win = new Fl_Double_Window(400,400,"Sample");
win->begin();
Fl_Choice* choice = new Fl_Choice(100,100,100,100,"Name");
choice->add("Peter");
choice->add("Tom");
choice->add("Mary");
Fl_Button* but = new Fl_Button(300,300,50,50,"Selected");
but->callback((Fl_Callback*)but_cb);
win->show();
return (Fl::run());
}
I did not spend much time reading the code, so the modified, and commented code below may not be solution to your problem. I believe choice is NULL in but_cb() as you are redefining choice in your main() function, hiding the global 'choice' pointer.
Fl_Choice* choice;
int i = 0;
void but_cb(Fl_Button* obj, void*) {
i = choice->value(); // uses global `choice` pointer to Fl_Choice.
cout << i;
}
int main (int argc, char* argv[]) {
Fl_Double_Window* win = new Fl_Double_Window(400,400,"Sample");
win->begin();
/* You are redefining choice here! BAD, because but_cb uses the global one.
Fl_Choice* choice = new Fl_Choice(100,100,100,100,"Name");
*/
// Good, assigns to the global `choice`, so it won't be NULL when but_cb is called
choice = new Fl_Choice(100,100,100,100,"Name");
choice->add("Peter");
choice->add("Tom");
choice->add("Mary");
Fl_Button* but = new Fl_Button(300,300,50,50,"Selected");
but->callback((Fl_Callback*)but_cb);
win->show();
return (Fl::run());
}

LLVM IR String Initialization

I'm working on a program in LLVM IR, and I am trying to initialize a string that says "Hello World!" but I can't figure out how. The goal of the code is to count the number of characters in the string. Before the string needs to be initialized, and after the headers, I have the following:
int main (int argc, const char *argv[]) {
//Setting up
//Build a pointer to the string - LLVMValueRef *strptr=LLVMBuildGlobalStringPtr(builder, const char *string, const char *name);
LLVMValueRef *strptr;
LLVMContextRef context = LLVMContextCreate();
LLVMBuilderRef builder = LLVMCreateBuilderInContext (context);
LLVMModuleRef module1 = LLVMModuleCreateWithNameInContext("mod", context);
}
The easiest way to see how such things are by using the C++ backend - it generates the C++ API calls that build the module for you. You can see this done online.
"Compile" this code:
const char* foo() {
const char* s = "hello world";
return s;
}
And here are the relevant C++ API calls:
GlobalVariable* gvar_array__str = new GlobalVariable(/*Module=*/*mod,
/*Type=*/ArrayTy_0,
/*isConstant=*/true,
/*Linkage=*/GlobalValue::PrivateLinkage,
/*Initializer=*/0, // has initializer, specified below
/*Name=*/".str");
gvar_array__str->setAlignment(1);
// Constant Definitions
Constant *const_array_4 = ConstantDataArray::getString(mod->getContext(), "hello world", true);
std::vector<Constant*> const_ptr_5_indices;
ConstantInt* const_int64_6 = ConstantInt::get(mod->getContext(), APInt(64, StringRef("0"), 10));
const_ptr_5_indices.push_back(const_int64_6);
const_ptr_5_indices.push_back(const_int64_6);
Constant* const_ptr_5 = ConstantExpr::getGetElementPtr(gvar_array__str, const_ptr_5_indices);
// Global Variable Definitions
gvar_array__str->setInitializer(const_array_4);
// Function Definitions
// Function: foo (func_foo)
{
BasicBlock* label_entry = BasicBlock::Create(mod->getContext(), "entry",func_foo,0);
// Block entry (label_entry)
ReturnInst::Create(mod->getContext(), const_ptr_5, label_entry);
}

Initial assignment a Char Array using a Function in C

as we know it in C, a string defining is,
char string[] = "Hello World";
That is OK,
But I want to use a function and at initial same up,
I tried those, For example;
char * to_string()
{
return "Hello World";
}
Or;
char * to_String(void) // Function
{
char buff[16];
sprintf(buff, "%s", "Hello World");
return buff;
}
main() // main function
{
char Initial_String[] = to_String();
}
How to make this or any idea same another way.
I find what I dont send address of char Initial_String[] to fill into. No. is there Another method.
Thanks.
When you compile this, atleast in GCC, it will give you the following warning:
b.c:9: warning: function returns address of local variable
Why? Because buff[] is a local variable of function to_string(). Its scope is only inside the function to_string(). main() does not have any access to this variable. Try making buff[] a global variable instead.
Second problem: char Initial_String[] = to_String(); cannot be assigned value in this way. to_string() returns a char pointer, hence assign the value thus:
char *Initial_String = to_String();
The code below will work:
char buff[16];
char* to_String(void) // Function
{
//char buff[16]; /*this is a local variable*/
sprintf(buff, "%s", "Hello World");
return buff;
}
int main(void) // main function
{
char *Initial_String = to_String();
printf("%s", Initial_String);
return 0;
}
Yes You are right about local buffer mismake,
But This is not my wanting,
if I edit some differently,
char buff[16];
char* to_String(void) // Function
{
//char buff[16]; /*this is a local variable*/
sprintf(buff, "%s", "Hello World");
return buff;
}
int main(void) // main function
{
char *Initial_String_1 = to_String();
char *Initial_String_2 = to_String();
char *Initial_String_3 = to_String();
printf("%s", Initial_String_1 );
printf("%s", Initial_String_2 );
printf("%s", Initial_String_3 );
in this case, all strings will be same, because They have same buffer address,
I want to open the topic little more.
struct
{
long aaa;
short bbb;
int ccc;
char ddd;
.
.
. // the list goes on
}elements;
typedef struct
{
int lengt;
int *adress;
char name[10];
}_list;
char* to_String(long variable) // Function
{
sprintf(buff, "%ld", variable);
return buff;
}
int main (void)
{
_list My_List[] = {
{ sizeof(elements.aaa), &elements.aaa , to_string( elements.aaa) },
{ sizeof(elements.bbb), &elements.bbb , to_string( elements.bbb) },
{ sizeof(elements.ccc), &elements.ccc , to_string( elements.ddd) },
.
.
. //// the list goes on
};
I do not know, Do I make myself clear.
Here, string must be filled into name array, without assigning it the address.
I may have syntax mistake. the code is not tested with compiler. the idea is for illustrative purposes only.
I am trying to find a method for The purpose.
Thanks.

std::string.c_str() returning a weird characters

In my project, I use to load textures by specifying its file name. Now, I made this function const char* app_dir(std::string fileToAppend); that returns the mains argv[0] and change the application name by the fileToAppend. Since I cannot make the string manipulation easy with a char*, I use the std::string. My texture loader takes a const char* for file name so need to switch back to c_str(), now it generates a sequence of ASCII symbol characters (bug). I already fix the problem by changing the return type of the app_dir() to std::string. But why is that happening?
EDIT
sample code:
//in main I did this
extern std::string app_filepath;
int main(int argc, char** arv) {
app_filepath = argv[0];
//...
}
//on other file
std::string app_filepath;
void remove_exe_name() {
//process the app_filepath to remove the exe name
}
const char* app_dir(std::string fileToAppend) {
string str_app_fp = app_filepath;
return str_app_fp.append(fileToAppend).c_str();
//this is the function the generates the bug
}
I already have the functioning one by changing its return type to std::string as I said earlier.
A big no no :) returning pointer to local objects
return str_app_fp.append(fileToAppend).c_str();
Change your function to
std::string app_dir(const std::string& fileToAppend) {
string str_app_fp = app_filepath + fileToAppend;
return str_app_fp;
}
And on the return value use c_str()
When you using function const char* app_dir(std::string fileToAppend); you get pointer to the memory that allocated on the stack and already deleted when the function ends.

Resources