⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fax_list.cpp

📁 用于使用moden进行传真的源代码
💻 CPP
📖 第 1 页 / 共 3 页
字号:
    delete_parms(print_from_stdin_parms);  }  delete_parms(fax_to_ps_parms);}void FaxListDialog::view_fax(void) {   Gtk::TreeModel::iterator row_iter = tree_view.get_selection()->get_selected();  // we do not need a mutex before reading prog_config.ps_view_cmd  // as although read in FaxListDialog::get_ps_viewer_parms(),  // the thread which executes that method is launched below as  // FaxListsDialog::view_fax_thread() and is therefore not running  // at this stage  if (row_iter && !prog_config.ps_view_cmd.empty()) {    // fax_basename_sem is initialised to a count of 1, so this will stop    // fax_basename being overwritten until Sem_sync::post() is called in    // print_fax_thread() or view_fax_thread() or on Glib::ThreadError being    // caught    fax_basename_sem.wait();    fax_basename = prog_config.homedir;    if (mode == received) fax_basename += "/faxin/";    else fax_basename += "/faxsent/";    fax_basename += (*row_iter)[model_columns.fax_name];    fax_basename += '/';    fax_basename += (*row_iter)[model_columns.fax_name];    fax_basename += '.';    // now block off the signals for which we have set handlers so that the socket server    // thread does not receive the signals, otherwise we will have memory synchronisation    // issues in multi-processor systems - we will unblock in the initial (GUI) thread    // as soon as the socket server thread has been launched    sigset_t sig_mask;    sigemptyset(&sig_mask);    sigaddset(&sig_mask, SIGCHLD);    sigaddset(&sig_mask, SIGQUIT);    sigaddset(&sig_mask, SIGTERM);    sigaddset(&sig_mask, SIGINT);    sigaddset(&sig_mask, SIGHUP);#ifdef HAVE_PTHREAD_SIGMASK     pthread_sigmask(SIG_BLOCK, &sig_mask, 0);#else    sigprocmask(SIG_BLOCK, &sig_mask, 0);#endif    try {      Glib::Thread::create(sigc::mem_fun(*this, &FaxListDialog::view_fax_thread), false);    }    catch (Glib::ThreadError&) {      write_error("Cannot start new view fax thread, fax cannot be viewed\n");      fax_basename_sem.post();    }    // now unblock the signals so that the initial (GUI) thread can receive them#ifdef HAVE_PTHREAD_SIGMASK     pthread_sigmask(SIG_UNBLOCK, &sig_mask, 0);#else    sigprocmask(SIG_UNBLOCK, &sig_mask, 0);#endif  }}void FaxListDialog::view_fax_thread(void) {   // get a temporary file  char filename[] = "/tmp/efax-gtk-view.XXXXXX";  int file_fd = mkstemp(filename);  if (file_fd == -1) {    write_error("Failed to make temporary file:\n"		"please check permissions in /tmp directory");    _exit(0);  }  // now create a pipe and proceed to fork to write the postscript to temporary file  Pipe_fifo fork_pipe(Pipe_fifo::block);  // get the arguments for the exec() call to convert the fax files to  // PS format following the next fork() call (because this is a multi-  // threaded program, we must do this before fork()ing because we use  // functions to get the arguments which are not async-signal-safe)  std::pair<const char*, char* const*> fax_to_ps_parms(get_fax_to_ps_parms(fax_basename, false));  // release main GUI thread in print_fax() or view_fax()  // waiting for this use of fax_basename to finish  fax_basename_sem.post();  // now fork to create the process which will write postscript to stdout  pid_t pid = fork();  if (pid == -1) {    write_error("Fork error - exiting\n");    _exit(FORK_ERROR);  }      if (!pid) { // child process which will send postscript to stdout      // this is the child process to write to stdin    // now we have fork()ed we can connect to stderr    connect_to_stderr();    fork_pipe.connect_to_stdout();    execvp(fax_to_ps_parms.first, fax_to_ps_parms.second);    // if we reached this point, then the execvp() call must have failed    // report error and then end process - use _exit(), not exit()    write_error("Can't find the efix-0.9a program - please check your installation\n"		"and the PATH environmental variable\n");    _exit(0);  }  // this is the parent process, which will convert the fax to Postscript  // and then pipe it on stdout to write_from_stdin()      // first, release the memory allocated on the heap for  // the redundant fax_to_ps_parms  // we are in the main parent process here - no worries about  // only being able to use async-signal-safe functions  delete_parms(fax_to_ps_parms);      // now write stdin in (containing the generated PS text) to file  fork_pipe.connect_to_stdin();  write_from_stdin(file_fd);  // the temporary file to be viewed has now been created  // so launch a new process to control the viewing process  // we will reset handlers and then fork() again having done  // so, so that we can wait on the child of child  // first get the arguments for the exec() call to launch the fax  // viewer following the next fork() call (because this is a multi-  // threaded program, we must do this before fork()ing because we use  // functions to get the arguments which are not async-signal-safe)  std::pair<const char*, char* const*> ps_viewer_parms(get_ps_viewer_parms(filename));  if (ps_viewer_parms.first) { // this will be 0 if get_ps_viewer_parms()                               // threw a Glib::ConvertError)        pid = fork();        if (pid == -1) {      write_error("Fork error\n");      std::exit(FORK_ERROR);    }    if (!pid) { // child view-control process          // restore the default SIGCHLD signal handler with SA_RESTART      // for systems (such as Linux) which require it.  Also unblock      // signals in case we are blocking them on launching a thread      // elsewhere in this program (I cannot work out from IEEE 1003.1      // whether all masks are emptied on a fork() in any event)      sigset_t sig_mask;      sigemptyset(&sig_mask);      sigaddset(&sig_mask, SIGCHLD);      sigaddset(&sig_mask, SIGQUIT);      sigaddset(&sig_mask, SIGTERM);      sigaddset(&sig_mask, SIGINT);      sigaddset(&sig_mask, SIGHUP);      // this child process is single threaded, so we can use sigprocmask()      // rather than pthread_sigmask() (and should do so as sigprocmask()      // is guaranteed to be async-signal-safe)      sigprocmask(SIG_UNBLOCK, &sig_mask, 0);      struct sigaction sig_act;      sig_act.sa_handler = SIG_DFL;      sigemptyset(&sig_act.sa_mask);#ifdef SA_RESTART      sig_act.sa_flags = SA_RESTART;#else      sig_act.sa_flags = 0;#endif      sigaction(SIGCHLD, &sig_act, 0);            connect_to_stderr();      // now fork() again      pid_t pid = fork();      if (pid == -1) {	write_error("Fork error - exiting\n");	_exit(FORK_ERROR);      }          if (!pid) { // child process to call ps_viewer() from	  	execvp(ps_viewer_parms.first, ps_viewer_parms.second);	// if we reached this point, then the execvp() call must have failed	// report error and then end process - use _exit(), not exit()	write_error("Can't find the ps viewer program - please check your installation\n"		    "and the PATH environmental variable\n");	_exit(0);      }      // now we are back to the main viewing process again      // delete the temporary file      // first wait till the ps_viewer() process is closed by the user exiting      // the postscript viewing program      wait(0);          unlink(filename);      // now terminate the process      _exit(0);    }    // release the memory allocated on the heap for    // the redundant ps_viewer_parms    // we are in the main parent process here - no worries about    // only being able to use async-signal-safe functions    delete_parms(ps_viewer_parms);  }}void FaxListDialog::delete_parms(std::pair<const char*, char* const*> parms_pair) {  delete[] parms_pair.first;  char* const* temp_pp = parms_pair.second;  for(; *temp_pp != 0; ++temp_pp) {    delete[] *temp_pp;  }  delete[] parms_pair.second;}void FaxListDialog::delete_fax_prompt(void) {  Gtk::TreeModel::iterator row_iter = tree_view.get_selection()->get_selected();  if (row_iter) {    std::string faxnumber((*row_iter)[model_columns.fax_name]);    Glib::ustring msg(gettext("Delete fax "));    msg += faxnumber + (gettext("?"));        PromptDialog* dialog_p = new PromptDialog(msg, gettext("Delete fax"), standard_size, *this);    dialog_p->accepted.connect(sigc::mem_fun(*this, &FaxListDialog::delete_fax));    // there is no memory leak -- the memory will be deleted when PromptDialog closes  }}void FaxListDialog::delete_fax(void) {  Gtk::TreeModel::iterator row_iter = tree_view.get_selection()->get_selected();  if (row_iter) {    // get the name of the fax to be moved and the new name    std::string old_dirname(prog_config.homedir);    std::string new_dirname(prog_config.homedir);    if (mode == received) {      old_dirname += "/faxin/";      new_dirname += "/faxin/oldfax/";    }    else {      old_dirname += "/faxsent/";      new_dirname += "/faxsent/oldfax/";    }    old_dirname += (*row_iter)[model_columns.fax_name];    new_dirname += (*row_iter)[model_columns.fax_name];    // make a new directory to copy the files into    mkdir(new_dirname.c_str(), S_IRUSR | S_IWUSR | S_IXUSR);    // it should be possible to use link()/unlink() as the target and source    // are sub-directories of $HOME/faxin or $HOME/faxsent.  If because of a    // very odd filesystem arrangement this won't work, the method will do nothing    std::vector<std::string> filelist;    struct dirent* direntry;    struct stat statinfo;    DIR* dir_p;    if ((dir_p = opendir(old_dirname.c_str())) == 0) {      std::string msg("Can't open directory ");      msg += old_dirname;      msg += '\n';      write_error(msg.c_str());    }    else {      chdir(old_dirname.c_str());      while ((direntry = readdir(dir_p)) != 0) {	stat(direntry->d_name, &statinfo);	if (S_ISREG(statinfo.st_mode)) {	  filelist.push_back(direntry->d_name);	}      }      closedir(dir_p);      bool failure = false;      std::vector<std::string>::const_iterator iter;      std::string old_filename;      std::string new_filename;      for (iter = filelist.begin(); iter != filelist.end(); ++iter) {	old_filename = old_dirname + '/';	old_filename += *iter;	new_filename = new_dirname + '/';	new_filename += *iter;	if (link(old_filename.c_str(), new_filename.c_str())) {	  failure = true;	  break;	}      }      if (failure) { // recover position	std::vector<std::string>::const_iterator recover_iter;	for (recover_iter = filelist.begin(); recover_iter != iter; ++recover_iter) {	  new_filename = new_dirname + '/';	  new_filename += *recover_iter;	  unlink(new_filename.c_str());	}	rmdir(new_dirname.c_str());	std::string msg("Can't move directory ");	msg += old_dirname;	msg += " to ";	msg += new_dirname;	msg += '\n';	write_error(msg.c_str());      }      else {	for (iter = filelist.begin(); iter != filelist.end(); ++iter) {	  old_filename = old_dirname + '/';	  old_filename += *iter;	  unlink(old_filename.c_str());	}	if (rmdir(old_dirname.c_str())) {	  std::string msg("Can't delete directory ");	  msg += old_dirname;	  msg += "\nThe contents should have been moved to ";	  msg += new_dirname;	  msg += "\nand it should now be empty -- please check\n";	  write_error(msg.c_str());	}	else get_fax_list_rows();      }      // reset current directory      std::string temp(prog_config.homedir + "/faxin");      chdir(temp.c_str());    }  }}void FaxListDialog::refresh_slot(void) {  get_fax_list_rows();  set_buttons_slot();}DescriptionDialog::DescriptionDialog(const int standard_size, const std::string& text, Gtk::Window& window):                             Gtk::Window(Gtk::WINDOW_TOPLEVEL), in_exec_loop(false),			     ok_button(Gtk::Stock::OK), cancel_button(Gtk::Stock::CANCEL),			     button_box(Gtk::BUTTONBOX_END, standard_size/2),			     label(gettext("Fax description?")), table(3, 1, false),                             parent(window) {  button_box.add(cancel_button);  button_box.add(ok_button);  table.attach(label, 0, 1, 0, 1, Gtk::FILL | Gtk::EXPAND,	 Gtk::FILL | Gtk::EXPAND, standard_size/2, standard_size/4);  table.attach(entry, 0, 1, 1, 2, Gtk::FILL | Gtk::EXPAND,	 Gtk::EXPAND, standard_size/2, standard_size/4);  table.attach(button_box, 0, 1, 2, 3, Gtk::FILL | Gtk::EXPAND,	 Gtk::SHRINK, standard_size/2, standard_size/4);  ok_button.signal_clicked().connect(sigc::bind(sigc::mem_fun(*this, &DescriptionDialog::selected), true));  cancel_button.signal_clicked().connect(sigc::bind(sigc::mem_fun(*this, &DescriptionDialog::selected), false));  ok_button.set_flags(Gtk::CAN_DEFAULT);  cancel_button.set_flags(Gtk::CAN_DEFAULT);  add(table);    entry.set_text(text);  set_title(gettext("Fax description"));  set_transient_for(parent);  set_type_hint(Gdk::WINDOW_TYPE_HINT_DIALOG);  parent.set_sensitive(false);  set_modal(true);  entry.set_size_request(standard_size * 9, standard_size);  set_border_width(standard_size/2);  entry.grab_focus();  set_position(Gtk::WIN_POS_CENTER_ON_PARENT);  set_resizable(false);  set_icon(prog_config.window_icon_r);  show_all();  // we now need to deselect what is in the entry  entry.select_region(0,0);}void DescriptionDialog::exec(void) {  in_exec_loop = true;  Gtk::Main::run();}void DescriptionDialog::selected(bool accept) {  parent.set_sensitive(true); // do this before we emit accepted()  hide_all();  if (accept) accepted(entry.get_text());  if (in_exec_loop) Gtk::Main::quit();  // if we have not called exec(), then this dialog is self-owning and it is safe to call `delete this'  else delete this;}bool DescriptionDialog::on_delete_event(GdkEventAny*) {  selected(false);  return true; // returning true prevents destroy sig being emitted}bool DescriptionDialog::on_key_press_event(GdkEventKey* event_p) {  if (event_p->keyval == GDK_Escape) selected(false);  else if (event_p->keyval == GDK_Return && !cancel_button.has_focus()) selected(true);  else Gtk::Window::on_key_press_event(event_p);  return true; // processing ends here}

⌨️ 快捷键说明

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