// Compile with one of
// gcc -I/usr/local/include -o tooltip tooltip.c -L/usr/local/lib -lforms -lm
//
// cc -I/usr/local/include -o tooltip tooltip.c -L/usr/local/lib \
//                                                     -lforms -lformssnp -lm

#include "X11/forms.h"
#include <stdio.h>
#include <stdlib.h>

typedef struct {
	FL_FORM   * form;
	FL_OBJECT * tabfolder;
} TabbedDialog;

// This should be in forms.h but isn't
extern void fl_hide_tooltip();


// This prehandler is used to work-around an xforms bug.
// Switching tabfolders like this updates the form->x, form->y coords of
// the active tabfolder.
int tabfolder_prehandler(FL_OBJECT * obj, int event,
			 FL_Coord mousex, FL_Coord mousey, int key, void * ev)
{
	if (!obj || obj->objclass != FL_TABFOLDER)
		return 0;

	// This is very odd:
	// event == FL_LEAVE when the mouse enters the folder and
	// event == FL_ENTER are it leaves!
	if (event == FL_LEAVE) {
		int const numfolders = fl_get_tabfolder_numfolders(obj);
		int const current = fl_get_active_folder_number(obj);
		int const next = (current == 1) ? numfolders : 1;

		if (current != next) {
			// Using fl_freeze_form here corrupts the display.
			fl_set_folder_bynumber(obj, next);
			fl_set_folder_bynumber(obj, current);
		}
	}

	return 0;
}


void button_cb(FL_OBJECT * obj, long data)
{
	printf("Fooled you! I don't do anything at all!\n");
}


void exit_cb(FL_OBJECT * obj, long data)
{
	fl_hide_tooltip();
	fl_hide_form(obj->form);
}


FL_FORM * create_tab()
{
	FL_FORM * tab;
	FL_OBJECT * obj;

	tab = fl_bgn_form(FL_NO_BOX, 300, 120);
	obj = fl_add_box(FL_FLAT_BOX, 0, 0, 300, 120, "");

	obj = fl_add_button(FL_NORMAL_BUTTON, 120, 35, 80, 30, "Press me!");
	fl_set_object_callback(obj, button_cb, 0);
	fl_set_object_helper(obj, "A nice helpful tooltip");

	fl_end_form();

	return tab;
}


TabbedDialog * create_dialog()
{
	TabbedDialog * dialog;
	FL_OBJECT * obj;

	// Two identical tabs
	FL_FORM * const tab_form1 = create_tab();
	FL_FORM * const tab_form2 = create_tab();

	// Main dialog
	dialog = (TabbedDialog *) malloc(sizeof(TabbedDialog));

	dialog->form = fl_bgn_form(FL_NO_BOX, 320, 190);
	obj = fl_add_box(FL_FLAT_BOX, 0, 0, 320, 190, "");

	dialog->tabfolder = obj =
		fl_add_tabfolder(FL_TOP_TABFOLDER, 5, 5, 310, 130, "");
	fl_set_object_boxtype(obj, FL_UP_BOX);

	fl_set_object_prehandler(obj, tabfolder_prehandler);
	obj->u_vdata = dialog;

	fl_addto_tabfolder(obj, "Tab 1", tab_form1);
	fl_addto_tabfolder(obj, "Tab 2", tab_form2);

	obj = fl_add_button(FL_NORMAL_BUTTON, 235, 150, 80, 30, "Exit");
	fl_set_object_callback(obj, exit_cb, 0);
	fl_set_button_shortcut(obj, "#E", 1);

	fl_end_form();

	return dialog;
}


int main(int argc, char *argv[])
{
	XEvent ev;
	TabbedDialog * dialog1 = 0;
	TabbedDialog * dialog2 = 0;

	int const place  = FL_PLACE_MOUSE | FL_FREE_SIZE;
	int const border = FL_TRANSIENT;

	fl_initialize(&argc, argv, "Demo", 0, 0);

	dialog1 = create_dialog();
	dialog2 = create_dialog();

	fl_show_form(dialog1->form, place, border, "Demo1");
	fl_show_form(dialog2->form, place, border, "Demo2");

	while (dialog1->form->visible || dialog2->form->visible) {
		if (fl_check_forms() == FL_EVENT) {
			fl_XNextEvent(&ev);
			printf("Received unhandled X11 event\n"
			       "Type: %d Target: 0x%x\n",
			       ev.xany.type, (int) ev.xany.window);;
		}
	}

	fl_free_form(dialog1->form);
	fl_free_form(dialog2->form);

	free(dialog1);
	free(dialog2);

	return 0;
}
