// -*- mode:C++ ; compile-command: "g++-3.4 -I. -I.. -g -c Xcas1.cc -Wall -DHAVE_CONFIG_H -DIN_GIAC" -*-
/*
* Copyright (C) 2005,2014 B. Parisse, Institut Fourier, 38402 St Martin d'Heres
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see .
*/
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifndef IN_GIAC
#include
#else
#include "first.h"
#endif
#include
#ifdef HAVE_LIBFLTK
#include
#include
#include
#include
#include
#include
#include
#include
#include
#endif
#include "Xcas1.h"
#include "Input.h"
#include "Equation.h"
#include "Graph.h"
#include "Graph3d.h"
#include "Tableur.h"
#include "Editeur.h"
#include "Print.h"
#include
#include
#ifdef HAVE_SSTREAM
#include
#else
#include
#endif
#include
#include
#include
#include
#include
#include // auto-recovery function
#ifdef HAVE_SYS_TIME_H
#include
#endif
#ifdef HAVE_LIBPTHREAD
#include
#endif
#ifdef HAVE_PTHREAD_H
#include
#endif
#ifndef IN_GIAC
#include
#include
#include
#else
#include "global.h"
#include "misc.h"
#include "gen.h"
#endif
using namespace std;
using namespace giac;
#ifndef NO_NAMESPACE_XCAS
namespace xcas {
#endif // ndef NO_NAMESPACE_XCAS
#ifdef HAVE_LIBFLTK
bool interrupt_button = true ;
bool geo_run=false;
bool sheet_run=false;
bool recovery_mode=false;
int fonts_available=1;
void (*initialize_function)()=0;
Xcas_config_type Xcas_config;
void (* menu2rpn_callback)(Fl_Widget *,void *)=0;
Enlargable_Multiline_Output *Xcas_help_output =0 ;
xcas::Graph2d *Xcas_DispG=0;
xcas::Equation * Xcas_PrintG=0;
int show_xcas_dispg=0,redraw_turtle=0;
std::string xcas_paused="";
int xcas_dispg_entries=0;
Fl_Window * Xcas_DispG_Window=0;
Fl_Window * Xcas_Main_Window=0;
Fl_Button *Xcas_DispG_Cancel=0;
Fl_Button *Xcas_Cancel=0;
bool file_save_context=true;
void xcas_gprintf(unsigned special,const std::string & format,const vecteur & v,GIAC_CONTEXT){
if (Xcas_PrintG){
Fl::lock();
gen g=Xcas_PrintG->get_data();
Fl::unlock();
vecteur w=makevecteur(string2gen("",false),string2gen("Step by step console",false));
if (g.type==_VECT) w=*g._VECTptr;
// add format,v at the end of w
int posnl=0;
unsigned i=0;
for (;posnl=int(format.size());
if (finish)
curs=format.substr(posnl,format.size()-posnl);
else {
curs=format.substr(posnl,nl-posnl);
posnl=nl+1;
}
vecteur cur;
for (;i=int(curs.size()))
break;
string cursp=curs.substr(0,p);
if (!cursp.empty())
cur.push_back(string2gen(cursp,false));
cur.push_back(v[i]);
curs=curs.substr(p+4,curs.size()-p-4);
}
if (!curs.empty())
cur.push_back(string2gen(curs,false));
if (cur.empty())
continue;
if (cur.size()==1)
w.push_back(cur.front());
else
w.push_back(gen(cur,_SEQ__VECT));
if (finish)
break;
}
g=gen(w,_HIST__VECT);
Fl::lock();
Xcas_PrintG->set_data(g);
Fl::unlock();
}
}
// debugger variables
int xcas_debug_ok,xcas_current_instruction;
Fl_Double_Window * Xcas_Debug_Window=0;
Fl_Tile* Xcas_debug_tile =0;
Fl_Browser* Xcas_source_browser =0;
xcas::Multiline_Input_tab* Xcas_debug_input =0;
Fl_Output* Xcas_debug_messages =0;
Fl_Group* Xcas_debug_buttons =0;
Fl_Button* Xcas_sst_button=0,*Xcas_sst_in_button=0,*Xcas_cont_button=0,* Xcas_kill_button =0, * Xcas_break_button=0,* Xcas_rmbrk_button=0,*Xcas_watch_button =0,*Xcas_rmwatch_button=0;
Fl_Browser* Xcas_variable_browser=0;
static void cb_Xcas_source_browser(Fl_Browser*, void* user) {
std::string s("breakpoint(");
giac::context * contextptr =(giac::context *) user;
s += giac::debug_ptr(contextptr)->debug_prog_name->print();
s += ',';
s += giac::print_INT_(Xcas_source_browser->value());
s += ')';
Xcas_debug_input->value(s.c_str());
Xcas_debug_input->position(s.size()-1,s.size()-1);
Fl::focus(Xcas_debug_input);
Fl::flush();
usleep(200000);
Xcas_source_browser->value(xcas_current_instruction);
}
static void cb_Xcas_debug_input(xcas::Multiline_Input_tab*, void*) {
xcas_debug_ok=true;
}
static void cb_Xcas_sst_button(Fl_Button*, void*) {
Xcas_debug_input->value("sst");
xcas_debug_ok=true;
}
static void cb_Xcas_sst_in_button(Fl_Button*, void*) {
Xcas_debug_input->value("sst_in");
xcas_debug_ok=true;
}
static void cb_Xcas_cont_button(Fl_Button*, void*) {
Xcas_debug_input->value("cont");
xcas_debug_ok=true;
}
static void cb_Xcas_kill_button(Fl_Button*, void*) {
Xcas_debug_input->value("kill");
Xcas_debug_input->position(4,4);
Fl::focus(Xcas_debug_input);
}
static void cb_Xcas_break_button(Fl_Button*, void* user) {
string s("breakpoint(");
giac::context * contextptr =(giac::context *) user;
s += giac::debug_ptr(contextptr)->debug_prog_name->print();
s += ',';
s += giac::print_INT_(Xcas_source_browser->value());
s += ')';
Xcas_debug_input->value(s.c_str());
Xcas_debug_input->position(s.size()-1,s.size()-1);
Fl::focus(Xcas_debug_input);
}
static void cb_Xcas_rmbrk_button(Fl_Button*, void* user) {
string s("rmbreakpoint(");
giac::context * contextptr =(giac::context *) user;
s += giac::debug_ptr(contextptr)->debug_prog_name->print();
s += ',';
s += giac::print_INT_(Xcas_source_browser->value());
s += ')';
Xcas_debug_input->value(s.c_str());
Xcas_debug_input->position(s.size()-1,s.size()-1);
Fl::focus(Xcas_debug_input);
}
static void cb_Xcas_watch_button(Fl_Button*, void*) {
Xcas_debug_input->value("watch(");
Xcas_debug_input->position(6,6);
Fl::focus(Xcas_debug_input);
}
static void cb_Xcas_rmwatch_button(Fl_Button*, void*) {
Xcas_debug_input->value("rmwatch(");
Xcas_debug_input->position(8,8);
Fl::focus(Xcas_debug_input);
}
static void cb_Xcas_variable_browser(Fl_Browser*, void*) {
Xcas_debug_input->insert(Xcas_variable_browser->text(Xcas_variable_browser->value()));
}
// end debugger callbacks and defs
int autosave_time = 60 ; /* default save session every 60 seconds */
bool autosave_disabled = false;
bool find_fold_autosave_function(bool warn_user){
History_Fold * hf=0;
Fl_Widget * w = xcas::Xcas_input_focus;
for (;w;){
if ( (hf=dynamic_cast(w)) )
break;
w=w->parent();
}
if (hf)
return hf->autosave(warn_user);
else
return false;
}
bool (*autosave_function)(bool) = find_fold_autosave_function ;
void (*idle_function)()=0;
unsigned max_debug_printsize=1000;
void Xcas_debugguer(int status,giac::context * contextptr){
if (debug_ptr(contextptr) && debug_ptr(contextptr)->debug_contextptr)
contextptr = debug_ptr(contextptr)->debug_contextptr;
// 2 -> debug, 3 ->wait click
if (status==3){
vecteur v(gen2vecteur(Xcas_DispG?Xcas_DispG->waiting_click_value:undef));
if (v.empty()){
if (Xcas_DispG_Window) Xcas_DispG_Window->show();
if (Xcas_DispG_Cancel) Xcas_DispG_Cancel->show();
if (Xcas_DispG) Xcas_DispG->waiting_click=true;
for (;;) {
Fl::wait();
if (Xcas_DispG_Window && !Xcas_DispG_Window->visible()){
Xcas_DispG->waiting_click=false;
Xcas_DispG->waiting_click_value=undef;
}
bool wait=Xcas_DispG?Xcas_DispG->waiting_click:false;
if (!wait)
break;
}
if (Xcas_DispG) Xcas_DispG->waiting_click=false;
if (Xcas_DispG_Cancel) Xcas_DispG_Cancel->hide();
thread_eval_status(1,contextptr);
return;
}
v=inputform_pre_analysis(v,contextptr);
gen res=makeform(v,contextptr);
if (Xcas_DispG)
Xcas_DispG->waiting_click_value=inputform_post_analysis(v,res,contextptr);
thread_eval_status(1,contextptr);
return;
}
if (status==2){
if (!Xcas_Debug_Window){
int dx,dy;
if (xcas::Xcas_input_focus && xcas::Xcas_input_focus->window()){
dx=8*(2*xcas::Xcas_input_focus->window()->w()/24);
dy=11*(2*xcas::Xcas_input_focus->window()->h()/30);
}
else {
dx=400;
dy=500;
}
Fl_Double_Window* o = Xcas_Debug_Window = new Fl_Double_Window(dx,dy, gettext("Xcas Debug Window"));
{
Fl_Tile* o = Xcas_debug_tile = new Fl_Tile(0, 0, dx,dy);
o->box(FL_FLAT_BOX);
{ Fl_Browser* o = Xcas_source_browser = new Fl_Browser(0,0,dx,4*dy/11);
o->tooltip(gettext("Show the source of the program"));
o->type(2);
o->callback((Fl_Callback*)cb_Xcas_source_browser);
}
{ xcas::Multiline_Input_tab* o = Xcas_debug_input = new xcas::Multiline_Input_tab(dx/8,4*dy/11, dx-dx/8,dy/11, gettext("eval"));
o->type(4);
o->box(FL_DOWN_BOX);
o->color(FL_BACKGROUND2_COLOR);
o->selection_color(FL_SELECTION_COLOR);
o->labeltype(FL_NORMAL_LABEL);
o->labelfont(0);
o->labelsize(14);
o->labelcolor(FL_FOREGROUND_COLOR);
o->textcolor(1);
o->callback((Fl_Callback*)cb_Xcas_debug_input);
o->align(FL_ALIGN_LEFT);
o->when(FL_WHEN_ENTER_KEY);
}
{ Fl_Output* o = Xcas_debug_messages = new Fl_Output(0,5*dy/11,dx,2*dy/11);
o->type(12);
o->labelcolor(FL_FOREGROUND_COLOR);
o->textcolor(4);
}
{ Fl_Group* o = Xcas_debug_buttons = new Fl_Group(0,7*dy/11,dx,dy/11);
{ Fl_Button* o = Xcas_sst_button = new Fl_Button(0,7*dy/11,dx/8,dy/11, gettext("sst F5"));
o->tooltip(gettext("Execute current line, skip function"));
o->callback((Fl_Callback*)cb_Xcas_sst_button);
o->shortcut(0xffc2);
}
{ Fl_Button* o = Xcas_sst_in_button = new Fl_Button(dx/8,7*dy/11, dx/8, dy/11, gettext("in F6"));
o->tooltip(gettext("Execute current line, step in function"));
o->callback((Fl_Callback*)cb_Xcas_sst_in_button);
o->shortcut(0xffc3);
}
{ Fl_Button* o = Xcas_cont_button = new Fl_Button(2*dx/8,7*dy/11, dx/8, dy/11, gettext("cont F7"));
o->tooltip(gettext("Continue execution until next breakpoint"));
o->callback((Fl_Callback*)cb_Xcas_cont_button);
o->shortcut(0xffc4);
}
{ Fl_Button* o = Xcas_kill_button = new Fl_Button(3*dx/8,7*dy/11, dx/8, dy/11, gettext("kill"));
o->tooltip(gettext("Kill current program"));
o->callback((Fl_Callback*)cb_Xcas_kill_button);
}
{ Fl_Button* o = Xcas_break_button = new Fl_Button(4*dx/8,7*dy/11, dx/8, dy/11, gettext("break"));
o->tooltip(gettext("Add a breakpoint"));
o->callback((Fl_Callback*)cb_Xcas_break_button);
}
{ Fl_Button* o = Xcas_rmbrk_button = new Fl_Button(5*dx/8,7*dy/11, dx/8, dy/11, gettext("rmbrk"));
o->tooltip(gettext("Remove a breakpoint"));
o->callback((Fl_Callback*)cb_Xcas_rmbrk_button);
}
{ Fl_Button* o = Xcas_watch_button = new Fl_Button(6*dx/8,7*dy/11,dx/8, dy/11, gettext("watch"));
o->tooltip(gettext("Add a variable name to the watch"));
o->callback((Fl_Callback*)cb_Xcas_watch_button);
}
{ Fl_Button* o = Xcas_rmwatch_button = new Fl_Button(7*dx/8,7*dy/11,dx/8, dy/11, gettext("rmwtch"));
o->tooltip(gettext("Add a variable name to the watch"));
o->callback((Fl_Callback*)cb_Xcas_rmwatch_button);
}
o->end();
}
{ Fl_Browser* o = Xcas_variable_browser = new Fl_Browser(0,8*dy/11,dx,3*dy/11);
o->tooltip(gettext("Show watch variables"));
o->type(2);
o->callback((Fl_Callback*)cb_Xcas_variable_browser);
}
o->end();
}
o->end();
o->resizable(o);
}
Xcas_source_browser->user_data( (void *) contextptr);
Xcas_break_button->user_data( (void *) contextptr);
Xcas_rmbrk_button->user_data( (void *) contextptr);
if (Xcas_Main_Window && Xcas_Debug_Window)
change_group_fontsize(Xcas_Debug_Window,Xcas_Main_Window->labelsize());
if (Xcas_Debug_Window){
Xcas_Debug_Window->show();
// Xcas_Debug_Window->set_modal();
Xcas_debug_input->when(FL_WHEN_ENTER_KEY|FL_WHEN_NOT_CHANGED);
}
// Debugging mode
// cerr << "Debugging" << endl;
debug_struct * dbgptr=debug_ptr(contextptr);
if (dbgptr){
if (dbgptr->debug_info_ptr && dbgptr->debug_info_ptr->type==_VECT){
vecteur & w =*dbgptr->debug_info_ptr->_VECTptr;
// w[0]=function, args,
// w[1]=breakpoints
// w[2] = instruction evaled or program source
// w[3]= evaluation result
// w[4]= current instruction number
// w[5] = watch vector, w[6] = watch values
string msg;
msg += "eval("+w[2].print(contextptr) + ")= " + w[3].print(contextptr) + '\n';
msg += "Stopped in ";
if ( w[0].type==_VECT && !w[0]._VECTptr->empty() ){
if (!dbgptr->debug_prog_name)
dbgptr->debug_prog_name=new gen;
if (*dbgptr->debug_prog_name!=w[0]._VECTptr->front()){
gen prog=w[0]._VECTptr->front();
*dbgptr->debug_prog_name=prog;
if (prog.type==_IDNT)
prog=prog.eval(1,contextptr);
if (prog.is_symb_of_sommet(at_program) && prog.type==_VECT && prog._VECTptr->size()==3 )
prog=prog._VECTptr->back();
if (prog.type==_SYMB)
prog=prog._SYMBptr->feuille;
if (prog.type==_VECT && prog._VECTptr->size()==3)
prog=prog._VECTptr->back();
w[2]=prog;
Xcas_source_browser->clear();
vector vs;
if (w[2].type==_VECT)
debug_print(*w[2]._VECTptr,vs,contextptr);
else
debug_print(w[2],vs,contextptr);
vector::iterator it=vs.begin(),itend=vs.end();
for (;it!=itend;++it){
Xcas_source_browser->add(it->c_str());
}
}
msg += dbgptr->debug_prog_name->print(contextptr) + "(" + gen(vecteur(w[0]._VECTptr->begin()+1,w[0]._VECTptr->end()),_SEQ__VECT).print(contextptr)+")";
msg += ",\nbreakpoint "+w[1].print(contextptr);
} // if (w[0].type==_VECT)
else
msg += w[0].print(contextptr);
msg += ",\nline " + w[4].print(contextptr);
Xcas_debug_messages->value(msg.c_str());
gen w_in(w[5]),w_out(w[6]);
if ( (w_in.type==_VECT) && (w_out.type==_VECT) ){
int pos=max(Xcas_variable_browser->value(),1);
Xcas_variable_browser->clear();
const_iterateur it=w_in._VECTptr->begin(),itend=w_in._VECTptr->end();
const_iterateur jt=w_out._VECTptr->begin(),jtend=w_out._VECTptr->end();
for (;(it!=itend)&&(jt!=jtend);++it,++jt){
string tmps = replace(jt->print(contextptr),'\n',' ');
if (tmps.size()>max_debug_printsize)
tmps=tmps.substr(0,max_debug_printsize);
Xcas_variable_browser->add( (it->print(contextptr) + " := " + tmps ).c_str());
}
Xcas_variable_browser->value(giacmin(pos,w_in._VECTptr->size()));
}
xcas_current_instruction=w[4].val;
Xcas_source_browser->value(w[4].val);
/* console mode debugging
if (dbgptr->debug_refresh){
if (dbgptr->fast_debug_info_ptr)
cerr << *dbgptr->fast_debug_info_ptr << endl;
}
else {
if (dbgptr->debug_info_ptr)
cerr << *dbgptr->debug_info_ptr << endl;
}
*/
}
}
gen g(at_sst);
gen nxt;
xcas_debug_ok=false;
while (Xcas_Debug_Window->shown() && !xcas_debug_ok){
Fl::wait();
int cs=context_list().size(),ci=0,status=0;
for (;civisible())
g=at_kill;
else {
string buf(Xcas_debug_input->value());
if (!buf.empty()){
try {
g=gen(buf,contextptr);
}
catch (std::runtime_error & err){
cerr << err.what();
}
}
}
*dbgptr->fast_debug_info_ptr = g;
thread_eval_status(1,contextptr);
}
}
void Xcas_idle_function(void * dontcheck){
static int initialized=-1;
static time_t last_save=time(0);
int cs=context_list().size(),ci=0,status=0;
context * cptr=0;
for (;ci1)
break;
}
if (cishown()){
if (cptr){
usleep(100000);
status=check_thread(cptr);
}
if (status<2)
Xcas_Debug_Window->hide();
else
return; // moved from below otherwise after debugging STOP button is always on
}
}
if (Xcas_DispG_Window){
if (show_xcas_dispg){
if (show_xcas_dispg & 2){
if (!Xcas_DispG_Window->visible())
Xcas_DispG->autoscale();
if (show_xcas_dispg & 1){
Xcas_DispG_Window->show();
Xcas_DispG_Window->iconize();
}
else
Xcas_DispG_Window->show();
}
else
Xcas_DispG_Window->hide();
show_xcas_dispg=0;
}
}
if (xcas_paused!=""){
Xcas_Main_Window->redraw();
if (Xcas_DispG) Xcas_DispG->redraw();
fl_message("%s",xcas_paused.c_str());
xcas_paused="";
}
++initialized;
if (initialized % 5){
Fl::unlock();
#ifdef WIN32
usleep(10000);
#else
usleep(1000);
#endif
Fl::lock();
return;
}
if (!initialized && initialize_function)
initialize_function();
if (
#ifdef WIN32
!(initialized%20) &&
#endif
idle_function
)
idle_function();
/* autosave */
time_t current=time(0);
if (!autosave_disabled && autosave_function && double(current-last_save)>autosave_time){
if (autosave_function(false))
last_save=current;
else
last_save=current-autosave_time/2;
}
struct timeval cur;
struct timezone tz;
gettimeofday(&cur,&tz);
vector::const_iterator it=animations.begin(),itend=animations.end();
for (;it!=itend;++it){
Graph2d3d * gr = *it;
if (!gr->paused && gr->animation_dt>0){
double dt=cur.tv_sec-gr->animation_last.tv_sec+double(cur.tv_usec-gr->animation_last.tv_usec)/1e6;
if (dt>gr->animation_dt){
gr->redraw();
}
}
}
}
bool operator < (const time_string & ts1,const time_string & ts2){
if (ts1.t!=ts2.t)
return ts1.t < ts2.t;
else
return ts1.s < ts2.s;
}
// Check for auto-recovery data in directory s
bool has_autorecover_data(const string & s_orig,vector & newest){
DIR *dp;
struct dirent *ep;
string s=s_orig;
if (!s.empty() && s[s.size()-1]!='/')
s += '/';
else
s += '/';
dp = opendir (s.c_str());
if (dp != NULL){
while ( (ep = readdir (dp)) ){
string cur(ep->d_name);
if (cur.size()>13&& cur.substr(0,10)=="xcas_auto_"){
string curext=cur.substr(cur.size()-3,3);
if (curext=="xws"){
struct stat st;
if (!stat((s+ep->d_name).c_str(),&st)){
time_t & t=st.st_mtime; // last modif
newest.push_back(time_string(t,s+cur));
}
}
}
}
(void) closedir (dp);
if (newest.size()==0) // no file
return false;
return true;
}
else
return false; // Couldn't open the directory
}
bool stream_copy(std::istream & in,std::ostream & out) {
char c;
while (in){
if (!out){
return false;
}
c=in.get();
if (in.eof()){
return true;
}
out << c ;
}
return false;
}
bool add_user_menu(Fl_Menu_ *m,const string & s, const string & doc_prefix,Fl_Callback * cb){
string menufile;
bool menufile_found=false;
if (is_file_available(s.c_str())){
menufile_found=true;
menufile=s;
}
else {
if (getenv("XCAS_HELP")){
menufile=getenv("XCAS_HELP");
int ms=menufile.size();
for (--ms;ms>0;--ms){
if (menufile[ms]=='/')
break;
}
if (ms)
menufile=menufile.substr(0,ms+1)+doc_prefix+s;
}
else
menufile=giac::giac_aide_dir()+doc_prefix+s;
menufile_found=is_file_available(menufile.c_str());
}
if (!menufile_found){
cerr << "// Unable to open menu file "<< menufile << endl;
return false;
}
cerr << "// Using menu file " << menufile << endl;
// Now reading commandnames from file for menus
// Syntax is menu/submenu/item, callback inserts item name
ifstream in(menufile.c_str());
string lu;
int BUFSIZE=10000,endpos;
char buf[BUFSIZE+1];
while (in){
in.getline(buf,BUFSIZE,'\n');
endpos=strlen(buf);
if (endpos){
if (buf[endpos-1]=='\n')
buf[endpos-1]=0;
lu=buf;
}
if (in.eof())
break;
m->add(lu.c_str(),0,cb);
}
return true;
}
void nextfl_menu(Fl_Menu_Item * & m){
if (m->submenu()){
++m;
for (;m->text;)
nextfl_menu(m);
}
++m;
}
void copy_menu(Fl_Menu_ * menu,const string & prefix,Fl_Menu_Item * & m){
for (;m->text;++m){
if (m->submenu()){
string prefix2=prefix+m->label();
prefix2 += '/';
++m;
copy_menu(menu,prefix2,m);
}
else
menu->add((prefix+m->text).c_str(),m->shortcut_,m->callback_,m->user_data_,m->flags);
}
}
vecteur fl_menu2rpn_menu(Fl_Menu_Item * & m){
vecteur res;
++m;
for (;m->text;++m){
if (m->submenu()){
string s=m->label();
vecteur tmp(fl_menu2rpn_menu(m));
if (!tmp.empty())
res.push_back(makevecteur(string2gen(s,false),tmp));
}
else {
gen g;
if (m->callback_==menu2rpn_callback){
find_or_make_symbol(m->label(),g,0,false,context0);
// g=gen(string("'")+m->label()+string("'"));
if (g.is_symb_of_sommet(at_quote))
g=g._SYMBptr->feuille;
res.push_back(g);
}
}
}
return res;
}
void change_menu_fontsize(Fl_Menu * & m,int labelfontsize){
if (!m->text)
return;
m->labelsize(labelfontsize);
if (m->submenu()){
++m;
for (;m->text;++m)
change_menu_fontsize(m,labelfontsize);
}
}
void change_menu_fontsize(Fl_Menu_Item * m,int n,int labelfontsize){
for (int i=0;iattr.fontsize==labelfontsize)
return;
eq->attr.fontsize=labelfontsize;
eq->labelsize(labelfontsize);
eq->resize(eq->x(),eq->y(),eq->w(),eq->h());
eq->set_data(eq->get_data());
eq->adjust_widget_size();
}
void change_group_fontsize(Fl_Widget * w,int labelfontsize){
w->labelsize(labelfontsize);
w->redraw();
if (Equation * eq=dynamic_cast(w)){
change_equation_fontsize(eq,labelfontsize);
return;
}
Fl_Group * g = dynamic_cast(w);
if (!g)
return;
Fl_Font police=g->labelfont();
Fl_Widget * o;
Fl_Widget * const * ptr= g->array();
int n=g->children();
for (int i=0;ilabelfont()!=FL_SYMBOL)
o->labelfont(police);
if (Fl_Menu * m=dynamic_cast(o)){
change_menu_fontsize(m,labelfontsize);
continue;
}
if (Fl_Menu_ * mb=dynamic_cast(o)){
Fl_Menu_Item * mm=(Fl_Menu_Item *)mb->menu();
for (;mm->text;++mm)
change_menu_fontsize(mm,labelfontsize);
}
if (Fl_Input_ * in=dynamic_cast(o)){
in->textsize(labelfontsize);
in->textfont(police);
}
if (Equation * eq=dynamic_cast(o)){
eq->labelfont(police);
change_equation_fontsize(eq,labelfontsize);
}
if (Xcas_Text_Editor * xed=dynamic_cast(o)){
xed->Fl_Text_Display::textsize(labelfontsize);
xed->Fl_Text_Display::textfont(labelfontsize);
vector & v=xed->styletable;
for (unsigned i=0;ilabelsize(labelfontsize);
Editeur * ed =dynamic_cast(xed->parent());
if (!ed && !xed->tableur)
xed->resize_nl_before(1);
xed->redraw();
}
if (Fl_Value_Input * v=dynamic_cast(o))
v->textsize(labelfontsize);
if (Fl_Browser * b=dynamic_cast(o))
b->textsize(labelfontsize);
if (Fl_Counter * cc=dynamic_cast(o))
cc->textsize(labelfontsize);
if (Fl_Group * og=dynamic_cast(o))
change_group_fontsize(og,labelfontsize);
if (HScroll * os =dynamic_cast(o)){
// resize childs according to new scrollbar width
os->resize(os->x(),os->y(),os->w(),os->h());
}
if (Flv_Table_Gen * fl = dynamic_cast(o)){
fl->global_style.font_size(labelfontsize);
fl->global_style.height(labelfontsize+4);
fl->redraw();
}
o->labelsize(labelfontsize);
if (Graph2d3d * gr=dynamic_cast(o))
if (gr->parent() && !dynamic_cast