ask.C

#include <stdio.h>
#include <string.h>
#include <FL/Fl.H>
#include <FL/Fl_Window.H>
#include <FL/Fl_Input.H>
#include <FL/Fl_Button.H>
#include <FL/Fl_Return_Button.H>

int get_string(char*buffer, const char *from) {
  Fl_Window window(320,75);
  window.set_modal();
  Fl_Input input(60, 40, 250, 25,"Input:"); window.add(input);
  input.value(buffer);
  Fl_Button cancel(60, 10,80, 25,"cancel"); window.add(cancel);
  Fl_Return_Button ok(150, 10,80, 25,"OK"); window.add(ok);
  window.show();
  for (;;) {
    Fl::wait();
    Fl_Object *o;
    while (o = Fl::readqueue()) {
      if (o == &ok) {
	strcpy(buffer, input.value());
	return 1;
      } else if (o == &cancel || o == &window) {
	return 0;
      }
    }
  }
}

int main(int argc, char **argv) {
  char buffer[128];
  if (get_string(buffer, argv[1])) {
    puts(buffer);
    return 0;
  } else {
    return 1; // exit with error
  }
}

Objects don't need to have callback() set. The default callback puts a pointer to the object on a "queue" from which it can later be read with Fl::readqueue(). This was done for Forms compatibility but it is useful for modal windows. In this example the "get_string" function puts up a modal window and loops until one of the buttons is pushed. Each time Fl::wait() is called it may put any number of objects on the queue, and Fl::readqueue() returns these in order, returning null when the queue is empty. If your program wants to read the queue it should always read it until empty and ignore unrecognized objects.

modal() on a window prevents any interaction with other program windows below it, and prevents the user from raising a program window above it (well, it tries, but X is broken). It won't make any difference in this program because there is only one window, but this allows the "get_string" function to be used as subroutine by a larger program and have the expected behavior.

This program also demonstrates that FL objects may be constructed as automatic objects. You have to be careful about destruction, however. Always make sure all automatic children are destructed before the container (by declaring the children after the container), since the destructor for a container will attempt to delete all remaining children, and you don't want to delete automatic objects.

[Next example]
[back to contents]