cs.cpp

来自「FreeFem++可以生成高质量的有限元网格。可以用于流体力学」· C++ 代码 · 共 804 行 · 第 1/2 页

CPP
804
字号
// Integrated Development Environment for FreeFEM++ - Client/Server version// ------------------------------------------------------------------------// Antoine Le Hyaric - LJLL Paris 6 - lehyaric@ann.jussieu.fr - 21/10/04// $Id: cs.cpp,v 1.77 2005/07/15 12:11:48 lehyaric Exp $#ifdef CLIENT#include <FL/x.H>#endif#include <unistd.h>#include <cassert>#include <list>#include <iostream>using namespace std;// Graphical widgets are only needed in the client#ifdef CLIENT#include <FL/Fl_Round_Button.H>#include <FL/Fl_Menu_Bar.H>#include <FL/Fl_File_Chooser.H>#include "editor.hpp"#include "spawn.hpp"#include "images.hpp"#include "draw.hpp"#include "commands.hpp"#ifdef WIN32#include "windres.h"#endif#if defined(__linux__)#include <X11/xpm.h>#endif#include "highlight.hpp"#endif // CLIENT#ifdef SERVER#include "server.hpp"#endif#ifndef NOSOCKETS#include "socket.hpp"#endif#include "../fflib/strversionnumber.hpp"// Client-side// -----------// To display more messages about the client/server dialog on cerr//#define DIALOG_DEBUG#ifdef CLIENT// Takes care of all the bits and pieces of the graphical window when// redrawing the graphics.void flushgraphics(){  Fl::lock();  flushdrawings();  graphics->redraw();    // Graphics toolbar only useful if there is an image!  if(drawings.size()!=0) graphicstoolbar->activate();  else graphicstoolbar->deactivate();  graphicstoolbar->redraw();  Fl::unlock();  // awake() is necessary to make the main thread aware that the  // window should be updated.  Fl::awake();}// Separate thread to communicate with the server through a socketTHREADFUNC(talktoserver,){#ifndef NDEBUG  cout<<"client: talktoserver started id="<<talktoserverid<<endl;#endif  // Catches many exceptions to prevent the IDE from crashing without  // explanation. There should not be any error exit in the whole  // IDE client code after the windows are displayed.  bool error=false;  bool stop=false;  try{    // Create socket comunications#ifndef NOSOCKETS    newswitchboard();#endif    // Spawn a server process once we know that sockets work ok.    assert(runserverprocessid==0);    runserverprocessid=Thread::Start(runserverprocess,NULL);    // Activate job control buttons only when we know what to control    Fl::lock();    pausebutton->activate();    stopbutton->activate();    Fl::unlock();    Fl::awake();    freefemthreadcomm.WAIT();    freefemrunning=true;    talkingthreadsetup=false;    freefemthreadcomm.Free();    // Wait for that server to come online and talk to him only (the    // socket code is able to talk to several processes through several    // threads at once, but we don't need that yet).#ifndef NOSOCKETS    clientsocket=switchboard->Listen();#endif    // Past that point, this thread should be treatly humanly    // (i.e. not killed) otherwise we risk leaving some semaphores in    // a bizarre state.    freefemthreadcomm.WAIT();    talkingthreadsetup=true;    freefemthreadcomm.Free();    string message;#ifndef NOSOCKETS    if(clientsocket.getremotehostname()=="unknown")      message="FreeFem++ server connected\n";    else message=string("FreeFem++ server on ")	   +clientsocket.getremotehostname()	   +" connected\n";#else      message="FreeFem++ server connected\n";#endif //NOSOCKETS    Fl::lock();    output->insert(message.c_str());    output->show_insert_position();    messagebar->value("FreeFem++ server running...");    Fl::unlock();    // Loop on all messages sent by the server through the open socket    // (this is mainly about drawing graphical objects).#ifdef DIALOG_DEBUG    cerr<<"client: starting listening loop"<<endl;#endif    // Pause and stop buttons management    freefemthreadcomm.WAIT();    stop=freefemstop;    freefemthreadcomm.Free();    resetzoomcenter();    bool serverended=false;    // Loop waiting for commands coming from the server through a    // socket#ifdef NOSOCKETS    // If the server does not use sockets, we just wait for it to end    freefemserverended.Decr();    freefemserverended.Incr();#else    // When not in debug mode, try and reduce the amount of data    // exchanged to a minimum.    CMD_TYPE cmd;    clientsocket>>cmd;    while(!clientsocket.ateof() && !stop && !serverended){#ifdef DIALOG_DEBUG      cerr<<"client: received command \""<<cmd<<"\""<<endl;#endif      // Send the program text to the server when it asks for it.      if(cmd==CMD_PROGRAM){#ifdef DIALOG_DEBUG	cerr<<"client: sending program text"<<endl;#endif	clientsocket<<cmd_program();	clientsocket.writeflush();      }      // Detailing all possible graphical commands. The constructor of      // each of the graphical objects below is able to read the      // object's characteristics from the input socket.      else if(cmd==CMD_COLOR){	// Read a color coming from the server. We need to store it	// because FreeFem++ sets the color _before_ clearing the	// graphics, and clearing the graphics in the client means	// using the default color, which is white!	color *c=new color;	defaultcolor=new color(*c);	backdrawings.push_back(c);      }      else if(cmd==CMD_POINT) backdrawings.push_back(new point);      else if(cmd==CMD_LINE) backdrawings.push_back(new line);      else if(cmd==CMD_TEXT) backdrawings.push_back(new text);      else if(cmd==CMD_PEN) backdrawings.push_back(new pen);      else if(cmd==CMD_POLYGON) backdrawings.push_back(new polygon);      else if(cmd==CMD_CIRCLE) backdrawings.push_back(new circle);      // Graphical queries      else if(cmd==CMD_CLEAR) cmd_clear();      else if(cmd==CMD_FLUSH) cmd_flush();      else if(cmd==CMD_LINE_WIDTH){	string s;	clientsocket>>s;	clientsocket<<cmd_line_width(s);	clientsocket.writeflush();      }      else if(cmd==CMD_LINE_HEIGHT){	clientsocket<<cmd_line_height();	clientsocket.writeflush();      }      else if(cmd==CMD_PAUSE){	cmd_pause();	clientsocket<<CMD_RESUME;	clientsocket.writeflush();      }      // Printing a message from the server process in the output window      else if(cmd==CMD_STDOUT){	string message;	clientsocket>>message;	cmd_stdout(message);      }      // Final handshake      else if(cmd==CMD_SERVER_DONE){	serverended=true;	// Make sure that the server does not exit before we have read	// all its output, otherwise we could face a "Connection reset	// by peer" error.	clientsocket<<"ok";	clientsocket.writeflush();      }      else if(cmd==CMD_ERROR){	// Record the error code, just to let the user know	string message;	clientsocket>>message;	throw message;      }      else{	throw string("Received unknown command from server: \"")	  +tostring(cmd)+"\"";      }      // Checks that we don't need to pause or stop (try and refrain      // from throwing any exception from here, or we will have to      // remember mutex states!)      freefempause.Decr();      freefempause.Incr();      freefemthreadcomm.WAIT();      stop=freefemstop;      freefemstop=false;      freefemthreadcomm.Free();      // Wait for next command from the server      if(!serverended) clientsocket>>cmd;    }#endif // NOSOCKETS  }  catch(string explanation){    cmd_error(explanation);    error=true;  }  // User-required stop#ifdef NOSOCKETS  fl_alert("FreeFem++: User stop not implemented yet");#else  // If we are stopping because the user asked so, we need to close  // the socket to let the server know that we are not listening  // anymore.  // When we close the communication socket, this will in turn provoke  // an internal error in the server, which will then shut down.  clientsocket.Close();  // WIN32 does not like to close "switchboard" once clientsocket is  // closed (strange! aren't they supposed to be different?).#ifndef __MINGW32__  switchboard->Close();#endif  switchboard=NULL;#endif  // Update IDE to reflect the fact that the computational server is  // no more.  Fl::lock();  if(error) messagebar->value("FreeFem++ computation ended with an error");  else if(stop) messagebar->value("FreeFem++ killed on request");  else messagebar->value("FreeFem++ computation ended");  // Deactivate job control buttons  runbutton->activate();  pausebutton->deactivate();  pausebutton->clear();  stopbutton->deactivate();  freefemthreadcomm.WAIT();  freefemrunning=false;  talkingthreadsetup=false;  freefemthreadcomm.Free();  Fl::unlock();  Fl::awake();  // When the server is finished, this thread has no reason to carry  // on.#ifndef NDEBUG  cout<<"client: talktoserver ended id="<<talktoserverid<<endl;#endif  talktoserverid=0;  return 0;}// Called when the user clicks on the "Run FreeFEM++" button.void startfreefemserver(Fl_Widget*,void*){  // Can only run one server at a time (for the moment)  runbutton->deactivate();  // Tell the user what is happening  messagebar->value("FreeFem++ server starting...");  // Remove all previous outputs (for simplicity)  outputbuffer->remove(0,outputbuffer->length());  // Remove any previous drawings (because it could very well be an  // unfinished drawing from a previously killed computation). Call  // flushdrawings() twice to empty both the front and the back  // buffer.  clearlist(drawings);  clearlist(backdrawings);  graphics->redraw();  // Leave first line blank, because characters are sometimes too high  // and they bump into the top edge of the text widget.  output->insert("\n");  // Communicates with the server in a different thread, to avoid any  // delay in redrawing the windows.  assert(talktoserverid==0);  talktoserverid=Thread::Start(talktoserver,NULL);}void pausefreefemserver(Fl_Widget*,void*){  // Simply locks a mutex, blocking any reception of data from the socket.  freefemthreadcomm.WAIT();  if(freefempaused) freefempause.Incr();  else freefempause.Decr();  freefempaused=!freefempaused;  if(freefempaused) messagebar->value("FreeFem++ computation paused");  else messagebar->value("FreeFem++ computation resumed");  freefemthreadcomm.Free();}void stopfreefemserver(Fl_Widget*,void*){  freefemthreadcomm.WAIT();  // How to stop the server depends on what level of setup it has  // reached  if(talkingthreadsetup){    // Un-pause the server if necessary    if(freefempaused) freefempause.Incr();    freefempaused=false;    // Just stops the freefem server thread. The socket will be closed    // and the server will shut down automatically.    freefemstop=true;  }  else{    // In this situation, the server is not properly started up yet,    // we need to kill off everything brutally and get back to a clean    // state.    mayday();  }  freefemthreadcomm.Free();}// Syntax highlighting stylesFl_Text_Display::Style_Table_Entry styletable[]={  {FL_BLACK,FL_COURIER,FL_NORMAL_SIZE}, // A=plain  {FL_DARK_GREEN,FL_COURIER_ITALIC,FL_NORMAL_SIZE}, // B=comments  {FL_BLACK,FL_COURIER_BOLD,FL_NORMAL_SIZE}, // C=macros  {FL_BLUE,FL_COURIER,FL_NORMAL_SIZE}, // D=strings  {FL_DARK_GREEN,FL_COURIER_BOLD,FL_NORMAL_SIZE}, // E=parameters  {FL_DARK_RED,FL_COURIER_BOLD,FL_NORMAL_SIZE}, // F=types  {FL_BLUE,FL_COURIER_BOLD,FL_NORMAL_SIZE}, // G=keywords  {FL_DARK_MAGENTA,FL_COURIER_BOLD,FL_NORMAL_SIZE}, // H=globals

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?