// -*- C++ -*-
// $RCSfile: menuform.C,v $
// $Revision: 1.9 $
// $Author: langer $
// $Date: 2000/11/03 14:46:33 $
/* This software was produced by NIST, an agency of the U.S. government,
* and by statute is not subject to copyright in the United States.
* Recipients of this software assume all responsibilities associated
* with its operation, modification and maintenance. However, to
* facilitate maintenance we ask that before distributing modifed
* versions of this software, you first contact the authors at
* oof_manager@ctcms.nist.gov.
*/
#ifdef MENUGFX
#include "ctype.h"
#include "stdlib.h"
#include <unistd.h>
#include <limits.h>
#include <string.h>
#include <X11/cursorfont.h>
#include "forms.h"
#include "menuDef.h"
#include "menucolor.h"
#include "menuform.h"
#include "varobjects.h"
// General Form methods
Vec<Form*> Form::allforms;
Form::Form(const CharString &nm)
: name(nm),
frozen(0),
the_form(0)
{
allforms.grow(1, this);
}
Form::~Form() {
/* have to reset the event queue here so that after a form is deleted
* it doesn't get any events!
*/
//fl_qreset();
if(the_form->visible) fl_hide_form(the_form);
fl_free_form(the_form);
allforms.remove(this);
}
void Form::gotoform(Form *nextform) {
if(!frozen) {
nextform->show(this); // show new form at old position
hide(); // hide current form
}
else { // don't hide current form
nextform->show(0); // show new form at user-selected position
}
}
/* show form. If the form is already visible, it is brought to the top.
* If it's not visible, and "other" is non-zero, the form takes its position
* from the other form. If other is zero, the mouse is used to place the
* form.
*/
void Form::show(Form *other) {
if(the_form->visible) // get position from self
other = this;
if(other) { // get position from other form
hide(); // hide first, so that "show" raises form to top
sameposition(other);
fl_show_form(the_form, FL_PLACE_GEOMETRY, FL_FULLBORDER, name.charstar());
}
else
#ifdef sgi
// On the SGI, if I use FL_PLACE_FREE instead of FL_PLACE_SIZE
// here, then the new windows aren't placed in the location of the
// old windows. I don't know if this is a problem with the window
// manager or the XForms version. Using FL_PLACE_SIZE sets the
// minimum size of the window to be its initial size, but that's
// easier to deal with than having to place every window by hand
// when changing menus.
fl_show_form(the_form, FL_PLACE_SIZE, FL_FULLBORDER, name.charstar());
#else
fl_show_form(the_form, FL_PLACE_FREE, FL_FULLBORDER, name.charstar());
#endif
Nforms()++; // do this even if form was already showing,
// since it was hidden to enforce a raise.
}
// simply make a form visible if it's not already. Don't bring it to the top.
void Form::makevisible() {
if(the_form->visible) return;
fl_show_form(the_form, FL_PLACE_SIZE, FL_FULLBORDER, name.charstar());
Nforms()++;
}
void Form::hide() {
if(the_form->visible) {
Nforms()--;
fl_hide_form(the_form);
}
}
static int ngeneralforms = 0;
int &Form::Nforms() {
return ngeneralforms;
}
void Form::sameposition(const Form *other) {
// make this form have same position as the other one
FL_FORM *otherform = other->the_form;
long x = otherform->x;
long y = otherform->y;
fl_set_form_position(the_form, x, y);
}
void Form::samesize(const Form *other) {
// make this form have same size as the other one
FL_FORM *otherform = other->the_form;
FL_Coord w = otherform->w;
FL_Coord h = otherform->h;
fl_set_form_size(the_form, w, h);
}
// there's only one formwaiter
// this is set by MenuForm::makeroot()
FormWaiter *Form::the_formwaiter = 0;
FormWaiter &Form::formwaiter() {
return *the_formwaiter;
}
void Form::setinputvar(FL_OBJECT *obj, Variable *var) {
fl_freeze_form(the_form);
if(var) {
CharString str(var->tostring());
// display variable value
fl_set_input(obj, str.charstar());
// change displayed name
str = var->name + " =";
fl_set_object_label(obj, str.charstar());
}
else {
fl_set_input(obj, "");
fl_set_object_label(obj, "");
}
fl_redraw_form(the_form); // or else old var name is still visible
fl_unfreeze_form(the_form);
}
// ----------------------------------------------------------- //
// things that happen to all forms at once
void Form::haltall() {
fl_deactivate_all_forms();
setcursor(XC_watch);
for(int i=0; i<allforms.capacity(); i++)
fl_freeze_form(allforms[i]->the_form);
}
void Form::resumeall() {
setcursor(XC_top_left_arrow); // this is the default xforms cursor
// fl_reset_cursor doesn't seem to work
fl_activate_all_forms();
for(int i=0; i<allforms.capacity(); i++) {
if(allforms[i]->the_form->frozen)
fl_unfreeze_form(allforms[i]->the_form);
}
}
void Form::setcursor(int cursornumber) {
// the cursor isn't actually changed until fl_check_only_forms is called
// (it seems) so we need to stick a call to it here. But we don't want
// events processed here, so the forms are deactivated first.
fl_deactivate_all_forms();
for(int i=0; i<allforms.capacity(); i++) {
if(allforms[i]->the_form->window)
fl_set_cursor(allforms[i]->the_form->window, cursornumber);
}
fl_check_only_forms();
fl_activate_all_forms();
}
// ---------------------------------------------------------- //
int Form::exists(long ptr) {
for(int i=0; i<allforms.capacity(); i++)
if(allforms[i] == (Form*)ptr) return 1;
return 0;
}
// ---------------------------------------------------------- //
// MenuForm specific stuff
// this should be a static member of the MenuForm class
// it's set by MenuForm::makeroot()
static MenuForm *rootform = 0; // there's only one root form
// double click time in seconds. don't exceed 1 second
static const double doubleclicktime = 0.4;
MenuForm::ClickMode MenuForm::clickmode = MenuForm::DOUBLE_NOW;
MenuForm::MenuForm(Menu *menu, const CharString &errhm,
const WordList &cpath,
const CharString &helpstr)
: Form(errhm + cpath.concat()), path(cpath),
selectedvar(-1), isroot(0), the_menu(menu), current_varobj(0)
{
create_form_generic_menu(this, menu->prompt, helpstr);
// stuff added by hand:
// make the browser lists readable
fl_set_browser_fontstyle(MF_submenu_list, FL_BOLD_STYLE);
fl_set_browser_fontstyle(MF_command_list, FL_BOLD_STYLE);
fl_set_browser_fontstyle(MF_variable_list, FL_BOLD_STYLE);
fl_set_browser_fontsize(MF_submenu_list, 12);
fl_set_browser_fontsize(MF_command_list, 12);
fl_set_browser_fontsize(MF_variable_list, 12);
fl_set_object_color(background, COL_BACKGROUND, 0);
fl_set_object_lcol(MF_menu_name, COL_MF_TITLE);
fl_set_object_color(MF_submenu_list, COL_MF_BROWBG, COL_MF_BROWSELECTION);
fl_set_object_color(MF_command_list, COL_MF_BROWBG, COL_MF_BROWSELECTION);
fl_set_object_color(MF_variable_list, COL_MF_BROWBG, COL_MF_BROWSELECTION);
fl_set_object_lcol(MF_submenu_list, COL_MF_BROWTEXT);
fl_set_object_lcol(MF_command_list, COL_MF_BROWTEXT);
fl_set_object_lcol(MF_variable_list, COL_MF_BROWTEXT);
fl_set_object_color(inputregion, COL_MF_INPUTREGION, 0);
fl_set_object_color(MF_frozen, COL_OFF_LIGHT, COL_FREEZE_LIGHT);
fl_set_object_color(MF_record, COL_OFF_LIGHT, COL_MF_RECORD_LIGHT);
fl_set_object_shortcutkey(MF_return_to_home_menu, XK_Home);
fl_set_form_atclose(the_form, closemenuform, this);
fl_set_form_dblbuffer(the_form, 1);
// put the menu entries into the forms
update();
// record this form in the list in the menu
menu->form.grow(1, this);
}
MenuForm::~MenuForm() {
the_menu->form.remove(this);
}
void MenuForm::update() {
fl_freeze_form(the_form);
fl_clear_browser(MF_submenu_list);
fl_clear_browser(MF_command_list);
fl_clear_browser(MF_variable_list);
submenus.resize(0);
variables.resize(0);
commands.resize(0);
for(int i=0; i<the_menu->option.capacity(); i++)
the_menu->option[i]->AddToForm(this);
fl_unfreeze_form(the_form);
}
void MenuForm::makeroot(FormWaiter *w) {
isroot = 1;
rootform = this;
the_formwaiter = w;
fl_set_object_label(MF_back_up, "Quit");
fl_deactivate_object(MF_return_to_home_menu);
fl_set_object_lcol(MF_return_to_home_menu, FL_INACTIVE_COL);
}
static int Nmenuforms = 0;
int &MenuForm::Nforms() {
return Nmenuforms;
}
// --------------------------------------------------------- //
// MenuOption methods for creating browser entries
CharString MenuOption::browserline() const {
static const CharString highlighter("@i"); // italic
static const CharString activator("@C1"); // color 1 = red
CharString line;
if(drawactive) line += activator;
if(highlighted) line += highlighter;
if(drawactive && isdigit(name[0]) && !highlighted) line += " ";
/* have to insert an extra space so that the first digit in the
* name doesn't look like part of the number following the 'C'.
*/
line += name;
return line;
}
void SubMenu::AddToForm(MenuForm *mf) {
if(attribute(MOPT_SECRET)) return;
fl_add_browser_line(mf->MF_submenu_list, browserline().charstar());
SubMenu *thees = this; // some compilers object falsely
mf->submenus.grow(1, thees);
}
void Command::AddToForm(MenuForm *mf) {
if(attribute(MOPT_SECRET)) return;
fl_add_browser_line(mf->MF_command_list, browserline().charstar());
Command *thees = this;
mf->commands.grow(1, thees);
}
void Variable::AddToForm(MenuForm *mf) {
if(attribute(MOPT_SECRET)) return;
CharString line(browserline() + " = " + tostring());
fl_add_browser_line(mf->MF_variable_list, line.charstar());
Variable *thees = this;
mf->variables.grow(1, thees);
if(!varobj) {
fl_freeze_form(mf->the_form);
fl_addto_form(mf->the_form);
varobj = create_varobject(this, mf, VO_PROACTIVE,
mf->dummyinput->x, mf->dummyinput->y,
mf->dummyinput->w, mf->dummyinput->h);
varobj->hide();
fl_end_form();
fl_unfreeze_form(mf->the_form);
}
}
// --------------------------------------------------------- //
// call back routines
// first, a routine that gets the index in the list of menu options,
// taking secret options into account. Also correct for the
// fortran-like indexing of the xforms browser lines.
template <class T>
int optionindex(const Vec<T*> &optionlist, int chosen) {
for(int i=0; i<optionlist.capacity(); i++) {
if(!optionlist[i]->attribute(MOPT_SECRET)) chosen--;
if(chosen == 0) return i;
}
cerr << "Error in optionindex!" << endl;
return -1; // shouldn't ever get here!
}
//-------------------------------------------------------//
// submenu callbacks
void MFCB_submenuhandler(FL_OBJECT *obj, long ptr) {
if(Form::exists(ptr))
((MenuForm *) ptr)->submenuhandler(obj);
}
void MenuForm::submenuhandler(FL_OBJECT *obj) {
int which = optionindex(submenus, fl_get_browser(obj));
if(which < 0) return; // nothing selected
SubMenu *submenu = submenus[which];
if(!submenu->form) // create form if necessary
submenu->form =
new MenuForm(submenu->menu, formwaiter().errhm,
path + submenu->name, submenu->helpstring);
submenu->form->previous = this; // remember where it came from
gotoform(submenu->form);
}
//-------------------------------------------------------//
// command callbacks
/* Check for double clicks on the command list by setting a timer on
* the first click. If the timer expires before another click is
* found, then the click was a single click. If another click is
* found before the timer expires, then it's a double click.
*/
#include <signal.h>
#include <sys/time.h>
// Pass signals along to XForms. This handler is installed by
// interrupt_init(). If interrupt_init() hasn't been called, then
// signals are handled directly by XForms.
#ifdef VARARG_SIGNALS
void MenuForm::signalhandler(int sig, ...) {
fl_signal_caught(sig);
signal(sig, MenuForm::signalhandler); // reinstall handler
}
#else
void MenuForm::signalhandler(int sig) {
fl_signal_caught(sig);
signal(sig, MenuForm::signalhandler); // reinstall handler
}
#endif
void MFCB_commandhandler(FL_OBJECT *obj, long ptr) {
if(Form::exists(ptr))
((MenuForm *) ptr)->commandhandler(obj);
}
static int clickcount = 0; // how many clicks have been processed?
static MenuForm *clickedform = 0;
static int clickedline;
void MenuForm::singleclick_callback(int, void *ptr) {
// timer expired without receiving a second click
((MenuForm*) ptr)->do_click(1);
fl_remove_signal_callback(SIGALRM);
fl_add_signal_callback(SIGALRM, ignorealarm, 0);
clickcount = 0;
clickedform = 0;
clickedline = 0;
}
void MenuForm::ignorealarm(int, void*) {}
void MenuForm::commandhandler(FL_OBJECT *obj) {
struct itimerval timer, oldtimer;
clickcount++;
if(clickcount == 1) { // wait for second click
clickedform = this;
clickedline = fl_get_browser(obj);
timer.it_value.tv_usec = (long) (1000000*doubleclicktime);
timer.it_value.tv_sec = 0;
timer.it_interval.tv_usec = 0;
timer.it_interval.tv_sec = 0;
fl_remove_signal_callback(SIGALRM);
fl_add_signal_callback(SIGALRM, singleclick_callback, this);
setitimer(ITIMER_REAL, &timer, &oldtimer);
}
else { // got second click!
// turn off timer
timer.it_value.tv_usec = 0;
timer.it_value.tv_sec = 0;
setitimer(ITIMER_REAL, &timer, &oldtimer);
fl_remove_signal_callback(SIGALRM);
// sometimes the signal is still generated although the timer has
// supposedly been turned off, so there should always be a signal
// handler installed.
fl_add_signal_callback(SIGALRM, ignorealarm, 0);
int secondline = fl_get_browser(obj);
if(secondline == clickedline && clickedform == this)
do_click(2);
clickedform = 0;
clickedline = 0;
clickcount = 0;
}
}
void MenuForm::do_click(int nclicks) {
if((clickmode == SINGLE_NOW && nclicks == 1)
|| (clickmode == DOUBLE_NOW && nclicks == 2))
execute_fn_now();
else
open_fn_window();
}
void MenuForm::execute_fn_now() {
int which = optionindex(commands, clickedline);
Command *thecmd = commands[which];
thecmd->drawactive = 1;
fl_replace_browser_line(MF_command_list, clickedline,
thecmd->browserline().charstar());
fl_redraw_form(the_form);
XFlush(fl_get_display()); // make sure redrawn line is displayed now
/* when the line is redrawn after the command is finished, we
* can't assume that's it's still in the same location in the
* browser. So we have to save a copy of the line to find out
* which to redraw.
*/
CharString curline(fl_get_browser_line(MF_command_list, clickedline));
// execute command
thecmd->pronto(formwaiter(), path + thecmd->name);
// revert to original color
thecmd->drawactive = 0;
int nlines = fl_get_browser_maxline(MF_command_list);
for(int i=1; i<=nlines; i++) {
if(curline == fl_get_browser_line(MF_command_list, i)) {
fl_replace_browser_line(MF_command_list, i,
thecmd->browserline().charstar());
fl_redraw_form(the_form);
XFlush(fl_get_display());
break;
}
}
}
void MenuForm::open_fn_window() {
int which = optionindex(commands, clickedline);
CommandForm *cmdform = commands[which]->makecmdform(path);
cmdform->show(0);
}
//------------------------------------------------------------//
// variable callbacks
void MFCB_variablehandler(FL_OBJECT *obj, long ptr) {
if(Form::exists(ptr))
((MenuForm *) ptr)->variablehandler(obj);
}
void MenuForm::variablehandler(FL_OBJECT *obj) {
fl_freeze_form(the_form);
// hide last variable's fl_object
if(current_varobj) {
current_varobj->hide();
current_varobj->vsbl = 0;
}
current_varobj = 0;
// get new variable
selectedvar = optionindex(variables, fl_get_browser(obj));
if(selectedvar < 0) { // nothing selected
fl_set_object_label(MF_varhelp, "");
}
else {
Variable *var = variables[selectedvar];
// show new variable's fl_object
current_varobj = var->varobj;
current_varobj->show();
current_varobj->vsbl = 1;
// display help string
fl_set_object_label(MF_varhelp, var->helpstring.charstar());
fl_redraw_form(the_form);
}
fl_unfreeze_form(the_form);
}
// routine called by variable's callback fn
void MenuForm::setvariable(Variable *var, const CharString &val) {
if(formwaiter().macromode) {
formwaiter().record(path.concat() + " " + var->name + "=" + val);
formwaiter().recorddelim();
}
else {
var->fromstring(val, formwaiter());
// update value in variable browser and print to message window
CharString line = updatevariable(var, selectedvar);
// update other instances of this same variable:
VariableRegistry::vr().call_function(var, &Variable::update_forms);
if(formwaiter().echo)
formwaiter().msout << ms_prompt << name << " " << line
<< endl << ms_normal;
if(!var->attribute(MOPT_NOLOG))
formwaiter().log(path.concat() + " " + line);
// call hook function
if(var->hook) {
formwaiter().path = path + line;
formwaiter().makecurrent();
(var->hook)(var->name);
}
}
}
// update varible in browser, when its position in browser is known
CharString MenuForm::updatevariable(Variable *var, int which) {
// use tostring() rather than val to get standard form
CharString line(var->name + " = " + var->tostring());
fl_freeze_form(the_form);
fl_replace_browser_line(MF_variable_list, which+1, line.charstar());
fl_redraw_form(the_form);
fl_unfreeze_form(the_form);
return line;
}
// update variable in browser when its position is not known
void MenuForm::updatevariable(Variable *var) {
for(int i=0; i<variables.capacity(); i++)
if(var == variables[i]) {
updatevariable(var, i);
if(var->varobj->visible())
var->varobj->show(); // refreshes value displayed
return;
}
}
void MFCB_close_form(FL_OBJECT*, long ptr) {
if(Form::exists(ptr))
((MenuForm *) ptr)->close_form();
}
void MenuForm::close_form() {
if(Nforms() == 1) {
if(!isroot)
gotoform(rootform);
}
else {
hide();
}
}
// called when "close" is chosen from the window manager menu
int MenuForm::closemenuform(FL_FORM*, void *ptr) {
((MenuForm *) ptr)->close_form();
return FL_IGNORE;
}
void MFCB_go_back(FL_OBJECT*, long ptr) {
if(Form::exists(ptr))
((MenuForm *) ptr)->go_back();
}
void MenuForm::go_back() {
if(isroot) { // "Back" is "Quit" on the root menu form
if(garcon()->quitcmd) {
if((*garcon()->quitcmd)())
exit(0);
}
else {
if(formwaiter().question("Do you really want to quit?",1))
exit(0);
}
}
else
gotoform(previous);
}
void MFCB_go_home(FL_OBJECT*, long ptr) {
if(Form::exists(ptr))
((MenuForm *) ptr)->go_home();
}
void MenuForm::go_home() {
gotoform(rootform);
}
void MFCB_freeze(FL_OBJECT *obj, long ptr) {
if(Form::exists(ptr))
((MenuForm *) ptr)->freeze(obj);
}
void MFCB_record(FL_OBJECT *obj, long ptr) {
if(Form::exists(ptr)) {
if(fl_get_button(obj))
((MenuForm *) ptr)->record_on(obj);
else
((MenuForm *) ptr)->record_off(obj);
}
}
static int recording = 0;
void MenuForm::record_on(FL_OBJECT *obj) {
if(recording) { // only record on one menu at once
fl_set_button(obj, 0);
}
else {
fl_set_object_label(obj, "Stop");
formwaiter().startmacro(the_menu, path);
recording = 1;
}
}
void MenuForm::record_off(FL_OBJECT *obj) {
if(!recording) { // don't stop if this isn't the right menu
fl_set_button(obj, 1);
}
else {
fl_set_object_label(obj, "Record");
formwaiter().endmacro();
recording = 0;
}
}
// ------------------------------------------------------------ //
static const int DEFAULTFONT = FL_FIXED_STYLE;
static const int DEFAULTSIZE = 12; // in points
const int MessageForm::fudge = 40; // includes width of vertical scroll bar
static FL_OBJECT *fontmenu;
void MessageForm::addfonts(const char *fontname) {
fl_addto_menu(fontmenu, fontname);
}
static int closeit(FL_FORM*, void *ptr) {
((MessageForm*) ptr)->hide();
return FL_IGNORE;
}
Vec<MessageForm*> MessageForm::allmessageforms;
MessageForm::MessageForm(const CharString &nm)
: Form(nm),
lastlinecomplete(1),
selectedfont(DEFAULTFONT),
selectedsize(DEFAULTSIZE)
{
allmessageforms.grow(1, this);
create_form_messageform(this);
fl_set_browser_fontsize(MG_text, selectedsize);
fl_set_browser_fontstyle(MG_text, selectedfont);
fontmenu = MG_font;
fl_enumerate_fonts(addfonts, 1);
fl_set_menu_item_mode(MG_font, selectedfont+1, FL_PUP_CHECK);
fl_set_counter_return(MG_size, FL_RETURN_END_CHANGED);
fl_set_counter_value(MG_size, DEFAULTSIZE);
fl_set_counter_bounds(MG_size, 1.0, 40.0);
fl_set_counter_step(MG_size, 1.0, 1.0);
fl_set_counter_precision(MG_size, 0);
fl_set_object_color(MG_text, COL_MG_TEXTBG, 0);
fl_set_object_lcol(MG_text, COL_MG_TEXT);
fl_set_object_color(background, COL_MG_BACKGROUND, 0);
fl_set_object_shortcutkey(MG_home, XK_Home);
fl_set_form_atclose(this->the_form, closeit, this);
}
MessageForm::~MessageForm() {
allmessageforms.remove(this);
}
void MessageForm::makevisible() {
if(the_form->visible) return;
fl_show_form(the_form, FL_PLACE_FREE, FL_FULLBORDER, name.charstar());
Nforms()++;
}
void MessageForm::addtext(const char *str) {
/* add lines of text. fl_addto_browser doesn't like \n's, so look for
* them and add each bit separately. Furthermore, remember if the last
* line ended with a \n, so it can be appended to if necessary.
*/
fl_freeze_form(the_form);
char line[1024];
int nlines;
if(!lastlinecomplete && (nlines = fl_get_browser_maxline(MG_text))) {
// remove incomplete line from browser and append new string
strcpy(line, fl_get_browser_line(MG_text, nlines));
strcat(line, str);
fl_delete_browser_line(MG_text, nlines);
}
else
strcpy(line, str);
char *ptr = line;
char *newline;
do {
newline = strchr(ptr, '\n');
if(!newline) {
// any remaining stuff in str is an incomplete line
if(*ptr != '\0') {
fl_addto_browser(MG_text, ptr);
lastlinecomplete = 0;
}
}
else {
*newline = '\0';
fl_addto_browser(MG_text, ptr);
lastlinecomplete = 1;
ptr = ++newline; // first char after '\n'
}
} while(newline);
fl_unfreeze_form(the_form);
}
void MessageForm::setcolor(int color) {
if(lastlinecomplete) // only change color at beginning of line!
addtext("@C" + to_charstring(color) + "@N");
// @C changes the color, @N is only used as a terminator so that
// if the next character is a digit it isn't interpreted as part
// of the color.
}
void MGCB_text(FL_OBJECT*, long ptr) {
if(Form::exists(ptr))
((MessageForm *) ptr)->addtext("Shouldn't do this!\n");
}
void MGCB_clear(FL_OBJECT*, long ptr) {
if(Form::exists(ptr))
((MessageForm *) ptr)->cleartext();
}
void MessageForm::cleartext() {
fl_clear_browser(MG_text);
}
void MGCB_close(FL_OBJECT*, long ptr) {
if(Form::exists(ptr))
((MessageForm *) ptr)->hide();
}
void MGCB_save(FL_OBJECT*, long ptr) {
if(Form::exists(ptr))
((MessageForm *) ptr)->save();
}
void MessageForm::save() {
// open a file with the file selection box
static char dir[100] = "";
static char pat[100] = "";
static char dflt[100] = "logfile";
const char *filename = fl_show_file_selector("log file", dir, pat, dflt);
if(!filename) return; // cancelled
FILE *file = fopen(filename, "w");
int nlines = fl_get_browser_maxline(MG_text);
for(int i=1; i<=nlines; i++) {
const char *line = fl_get_browser_line(MG_text, i);
// skip browser formating symbols of the form "@X"
while(line[0] == '@') { // skip @
line++;
if(line[0] == 'C') { // "C<number>" sets the line color
line++;
while(isdigit(line[0]))
line++;
}
else if(line[0] == '@') // "@@" prints as "@"
break;
else
line++; // skip X
}
fprintf(file, "%s\n", line);
}
fclose(file);
}
void MGCB_font(FL_OBJECT*, long ptr) {
if(Form::exists(ptr))
((MessageForm *) ptr)->font();
}
void MessageForm::font() {
fl_freeze_form(the_form);
int which = fl_get_menu(MG_font);
if(which <= 0) return;
fl_set_browser_fontstyle(MG_text, which-1);
fl_set_menu_item_mode(MG_font, selectedfont+1, FL_PUP_NONE);
selectedfont = which-1;
fl_set_menu_item_mode(MG_font, selectedfont+1, FL_PUP_CHECK);
fl_unfreeze_form(the_form);
}
void MGCB_size(FL_OBJECT*, long ptr) {
if(Form::exists(ptr))
((MessageForm *) ptr)->size();
}
void MessageForm::size() {
fl_freeze_form(the_form);
selectedsize = int(fl_get_counter_value(MG_size));
fl_set_browser_fontsize(MG_text, selectedsize);
fl_unfreeze_form(the_form);
}
void MGCB_home(FL_OBJECT*, long ptr) {
if(Form::exists(ptr))
((MessageForm*) ptr)->home();
}
void MessageForm::home() {
formwaiter().show_homeform();
}
// -------------------------------------------------------------- //
/* When using fl_get_input, it is important not to modify the string
* it returns. This routine makes a copy of the string returned from
* fl_get_input, so it's safe.
*/
CharString forminputstring(FL_OBJECT *obj) {
return CharString(fl_get_input(obj));
}
// -------------------------------------------------------------- //
// my own version of fl_question
int FormWaiter::question(const CharString &qstr, int dflt) {
fl_deactivate_all_forms();
QuestionForm qf(qstr, dflt);
qf.makevisible();
do
fl_check_only_forms();
while(!qf.done());
fl_activate_all_forms();
return qf.answer();
}
QuestionForm::QuestionForm(const CharString &question, const TrueFalse &dflt)
: done_(0), Form("?")
{
create_form_questionform(this);
fl_set_object_color(background, COL_BACKGROUND, 0);
fl_set_object_color(question_text, COL_BACKGROUND, 0);
fl_set_object_label(question_text, question);
if(dflt)
fl_set_form_hotobject(the_form, yes_button);
else
fl_set_form_hotobject(the_form, no_button);
}
void QuestionForm::makevisible() {
if(the_form->visible) return;
fl_show_form(the_form, FL_PLACE_HOTSPOT, FL_TRANSIENT, name.charstar());
Nforms()++;
}
void QuestionForm::yes() {
answer_ = 1;
done_ = 1;
}
void QuestionForm::no() {
answer_ = 0;
done_ = 1;
}
void QFCB_yesbutton(FL_OBJECT *, long ptr) {
if(Form::exists(ptr))
((QuestionForm*) ptr)->yes();
}
void QFCB_nobutton(FL_OBJECT *, long ptr) {
if(Form::exists(ptr))
((QuestionForm*) ptr)->no();
}
// -------------------------------------------------------------- //
// my own version of fl_show_input
StringForm::StringForm(const CharString &prompt, const CharString &dflt)
: Form("rsvp"), notyet(1)
{
create_form_stringform(this);
fl_set_object_label(SF_prompt, prompt.charstar());
fl_set_object_color(background, COL_BACKGROUND, 0);
fl_set_input(SF_input, dflt.charstar());
}
void StringForm::makevisible() {
if(the_form->visible) return;
fl_show_form(the_form, FL_PLACE_MOUSE, FL_TRANSIENT, name.charstar());
Nforms()++;
}
void SFCB_okbutton(FL_OBJECT*, long ptr) {
if(Form::exists(ptr))
((StringForm *) ptr)->ok();
}
void StringForm::ok() {
// see comment in commands.C in CommandMForm::perform()
// hitting ok generates an input event, which this line catches:
//(void) fl_check_only_forms();
answer = forminputstring(SF_input);
notyet = 0;
}
#ifdef FORMFORM
CharString FormWaiter::getstring(const CharString &prompt,
const CharString &dflt) {
CharString answer(fl_show_input(prompt.charstar(), dflt.charstar()));
return answer;
}
#endif // FORMFORM
CharString FormWaiter::getstring(const CharString &prompt,
const CharString &dflt) {
fl_deactivate_all_forms();
StringForm sf(prompt, dflt);
sf.makevisible();
do
fl_check_only_forms();
while(sf.notyet);
fl_activate_all_forms();
return sf.answer;
}
//-----------------------------------
PauseForm *PauseForm::pauseform = 0;
void PauseForm::pause() { // static
static PauseForm *pauseform = 0;
fl_deactivate_all_forms();
if(!pauseform) {
pauseform = new PauseForm;
pauseform->show(0);
}
pauseform->wait();
fl_activate_all_forms();
}
// void PauseForm::makevisible() {
// if(fl_form_is_visible(the_form)) return;
// fl_show_form(the_form, FL_PLACE_MOUSE, FL_TRANSIENT, name.charstar());
// Nforms()++;
// }
void PauseForm::wait() {
FL_OBJECT *obj;
fl_activate_form(the_form);
if(!fl_form_is_visible(the_form))
fl_show_form(the_form, FL_PLACE_GEOMETRY, FL_FULLBORDER, name.charstar());
fl_raise_form(the_form);
while(obj = fl_do_forms()) {
if(obj == button_continue) {
fl_deactivate_form(the_form);
fl_hide_form(the_form);
return;
}
}
}
PauseForm::PauseForm()
: Form("pause")
{
create_form_pauseform(this);
}
#endif // MENUGFX
syntax highlighted by Code2HTML, v. 0.9.1