view libgui/src/m-editor/file-editor-tab.cc @ 19627:446c46af4b42 stable

strip trailing whitespace from most source files * Makefile.am, NEWS, build-aux/common.mk, configure.ac, doc/Makefile.am, doc/doxyhtml/Makefile.am, doc/interpreter/Makefile.am, doc/interpreter/arith.txi, doc/interpreter/audio.txi, doc/interpreter/basics.txi, doc/interpreter/bugs.txi, doc/interpreter/container.txi, doc/interpreter/cp-idx.txi, doc/interpreter/data.txi, doc/interpreter/debug.txi, doc/interpreter/diagperm.txi, doc/interpreter/diffeq.txi, doc/interpreter/doccheck/README, doc/interpreter/doccheck/spellcheck, doc/interpreter/emacs.txi, doc/interpreter/errors.txi, doc/interpreter/eval.txi, doc/interpreter/expr.txi, doc/interpreter/external.txi, doc/interpreter/fn-idx.txi, doc/interpreter/func.txi, doc/interpreter/geometry.txi, doc/interpreter/geometryimages.m, doc/interpreter/gpl.txi, doc/interpreter/grammar.txi, doc/interpreter/gui.txi, doc/interpreter/image.txi, doc/interpreter/install.txi, doc/interpreter/interp.txi, doc/interpreter/interpimages.m, doc/interpreter/intro.txi, doc/interpreter/io.txi, doc/interpreter/java.txi, doc/interpreter/linalg.txi, doc/interpreter/macros.texi, doc/interpreter/matrix.txi, doc/interpreter/munge-texi.pl, doc/interpreter/nonlin.txi, doc/interpreter/numbers.txi, doc/interpreter/obsolete.txi, doc/interpreter/octave-config.1, doc/interpreter/octave.texi, doc/interpreter/oop.txi, doc/interpreter/op-idx.txi, doc/interpreter/optim.txi, doc/interpreter/package.txi, doc/interpreter/plot.txi, doc/interpreter/poly.txi, doc/interpreter/preface.txi, doc/interpreter/quad.txi, doc/interpreter/set.txi, doc/interpreter/signal.txi, doc/interpreter/sparse.txi, doc/interpreter/sparseimages.m, doc/interpreter/splineimages.m, doc/interpreter/stats.txi, doc/interpreter/stmt.txi, doc/interpreter/strings.txi, doc/interpreter/system.txi, doc/interpreter/testfun.txi, doc/interpreter/tips.txi, doc/interpreter/var.txi, doc/interpreter/vectorize.txi, doc/liboctave/Makefile.am, doc/liboctave/array.texi, doc/liboctave/bugs.texi, doc/liboctave/cp-idx.texi, doc/liboctave/dae.texi, doc/liboctave/diffeq.texi, doc/liboctave/error.texi, doc/liboctave/factor.texi, doc/liboctave/fn-idx.texi, doc/liboctave/gpl.texi, doc/liboctave/install.texi, doc/liboctave/intro.texi, doc/liboctave/liboctave.texi, doc/liboctave/matvec.texi, doc/liboctave/nleqn.texi, doc/liboctave/nlfunc.texi, doc/liboctave/ode.texi, doc/liboctave/optim.texi, doc/liboctave/preface.texi, doc/liboctave/quad.texi, doc/liboctave/range.texi, doc/refcard/Makefile.am, doc/refcard/refcard.tex, etc/HACKING, etc/NEWS.1, etc/NEWS.2, etc/NEWS.3, etc/OLD-ChangeLogs/ChangeLog, etc/OLD-ChangeLogs/doc-ChangeLog, etc/OLD-ChangeLogs/scripts-ChangeLog, etc/OLD-ChangeLogs/src-ChangeLog, etc/OLD-ChangeLogs/test-ChangeLog, etc/PROJECTS, etc/README.Cygwin, etc/README.MacOS, etc/README.MinGW, etc/README.gnuplot, etc/gdbinit, etc/icons/Makefile.am, examples/@polynomial/end.m, examples/@polynomial/subsasgn.m, examples/Makefile.am, examples/standalonebuiltin.cc, libgui/Makefile.am, libgui/qterminal/libqterminal/README, libgui/qterminal/libqterminal/unix/BlockArray.cpp, libgui/qterminal/libqterminal/unix/BlockArray.h, libgui/qterminal/libqterminal/unix/Character.h, libgui/qterminal/libqterminal/unix/CharacterColor.h, libgui/qterminal/libqterminal/unix/Emulation.cpp, libgui/qterminal/libqterminal/unix/Emulation.h, libgui/qterminal/libqterminal/unix/Filter.cpp, libgui/qterminal/libqterminal/unix/Filter.h, libgui/qterminal/libqterminal/unix/History.cpp, libgui/qterminal/libqterminal/unix/History.h, libgui/qterminal/libqterminal/unix/KeyboardTranslator.cpp, libgui/qterminal/libqterminal/unix/KeyboardTranslator.h, libgui/qterminal/libqterminal/unix/LineFont.h, libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.cpp, libgui/qterminal/libqterminal/unix/QUnixTerminalImpl.h, libgui/qterminal/libqterminal/unix/Screen.cpp, libgui/qterminal/libqterminal/unix/Screen.h, libgui/qterminal/libqterminal/unix/ScreenWindow.cpp, libgui/qterminal/libqterminal/unix/ScreenWindow.h, libgui/qterminal/libqterminal/unix/TerminalCharacterDecoder.cpp, libgui/qterminal/libqterminal/unix/TerminalCharacterDecoder.h, libgui/qterminal/libqterminal/unix/Vt102Emulation.h, libgui/qterminal/libqterminal/win32/QWinTerminalImpl.cpp, libgui/qterminal/qterminal/main.cpp, libgui/src/m-editor/file-editor-tab.cc, libgui/src/octave-gui.cc, libgui/src/octave-qt-link.cc, libinterp/corefcn/data.cc, libinterp/corefcn/defun-int.h, libinterp/corefcn/det.cc, libinterp/corefcn/gl2ps-renderer.cc, libinterp/corefcn/graphics.cc, libinterp/corefcn/graphics.in.h, libinterp/corefcn/ls-mat5.cc, libinterp/corefcn/lu.cc, libinterp/corefcn/oct-tex-parser.yy, libinterp/corefcn/oct-tex-symbols.in, libinterp/corefcn/quadcc.cc, libinterp/corefcn/zfstream.cc, libinterp/dldfcn/__eigs__.cc, libinterp/dldfcn/__voronoi__.cc, libinterp/gendoc.pl, libinterp/genprops.awk, libinterp/mk-errno-list, libinterp/mk-pkg-add, libinterp/mkbuiltins, libinterp/mkdefs, libinterp/mkdocs, libinterp/mkops, libinterp/octave-value/ov-java.cc, libinterp/parse-tree/lex.ll, libinterp/parse-tree/oct-parse.in.yy, libinterp/parse-tree/octave.gperf, liboctave/Makefile.am, liboctave/array/Array.cc, liboctave/array/module.mk, liboctave/cruft/daspk/datv.f, liboctave/cruft/daspk/dcnst0.f, liboctave/cruft/daspk/dcnstr.f, liboctave/cruft/daspk/ddasic.f, liboctave/cruft/daspk/ddasid.f, liboctave/cruft/daspk/ddasik.f, liboctave/cruft/daspk/ddaspk.f, liboctave/cruft/daspk/ddstp.f, liboctave/cruft/daspk/ddwnrm.f, liboctave/cruft/daspk/dfnrmd.f, liboctave/cruft/daspk/dfnrmk.f, liboctave/cruft/daspk/dhels.f, liboctave/cruft/daspk/dheqr.f, liboctave/cruft/daspk/dinvwt.f, liboctave/cruft/daspk/dlinsd.f, liboctave/cruft/daspk/dlinsk.f, liboctave/cruft/daspk/dmatd.f, liboctave/cruft/daspk/dnedd.f, liboctave/cruft/daspk/dnedk.f, liboctave/cruft/daspk/dnsd.f, liboctave/cruft/daspk/dnsid.f, liboctave/cruft/daspk/dnsik.f, liboctave/cruft/daspk/dnsk.f, liboctave/cruft/daspk/dorth.f, liboctave/cruft/daspk/dslvd.f, liboctave/cruft/daspk/dslvk.f, liboctave/cruft/daspk/dspigm.f, liboctave/cruft/daspk/dyypnw.f, liboctave/cruft/dasrt/ddasrt.f, liboctave/cruft/dasrt/drchek.f, liboctave/cruft/dassl/ddaslv.f, liboctave/cruft/dassl/ddassl.f, liboctave/cruft/misc/blaswrap.c, liboctave/cruft/misc/module.mk, liboctave/cruft/odepack/cfode.f, liboctave/cruft/odepack/dlsode.f, liboctave/cruft/odepack/ewset.f, liboctave/cruft/odepack/intdy.f, liboctave/cruft/odepack/prepj.f, liboctave/cruft/odepack/sintdy.f, liboctave/cruft/odepack/slsode.f, liboctave/cruft/odepack/solsy.f, liboctave/cruft/odepack/ssolsy.f, liboctave/cruft/odepack/stode.f, liboctave/cruft/odepack/vnorm.f, liboctave/cruft/ranlib/Basegen.doc, liboctave/cruft/ranlib/README, liboctave/cruft/ranlib/genbet.f, liboctave/cruft/ranlib/genexp.f, liboctave/cruft/ranlib/gennch.f, liboctave/cruft/ranlib/gennf.f, liboctave/cruft/ranlib/gennor.f, liboctave/cruft/ranlib/getsd.f, liboctave/cruft/ranlib/initgn.f, liboctave/cruft/ranlib/phrtsd.f, liboctave/cruft/ranlib/randlib.fdoc, liboctave/cruft/ranlib/setsd.f, liboctave/cruft/ranlib/tstgmn.for, liboctave/cruft/ranlib/tstmid.for, liboctave/cruft/slatec-fn/atanh.f, liboctave/cruft/slatec-fn/datanh.f, liboctave/cruft/slatec-fn/xgmainc.f, liboctave/cruft/slatec-fn/xsgmainc.f, liboctave/numeric/module.mk, liboctave/operators/mk-ops.awk, liboctave/operators/mx-ops, liboctave/operators/sparse-mk-ops.awk, liboctave/operators/sparse-mx-ops, liboctave/operators/vx-ops, liboctave/util/module.mk, run-octave.in, scripts/@ftp/ftp.m, scripts/audio/wavread.m, scripts/deprecated/java_convert_matrix.m, scripts/deprecated/java_debug.m, scripts/deprecated/java_invoke.m, scripts/deprecated/java_new.m, scripts/deprecated/java_unsigned_conversion.m, scripts/deprecated/javafields.m, scripts/deprecated/javamethods.m, scripts/deprecated/shell_cmd.m, scripts/general/accumarray.m, scripts/general/display.m, scripts/general/fieldnames.m, scripts/general/interp1.m, scripts/general/interp2.m, scripts/general/interp3.m, scripts/general/isa.m, scripts/general/methods.m, scripts/general/sortrows.m, scripts/geometry/convhull.m, scripts/geometry/delaunay.m, scripts/geometry/delaunay3.m, scripts/geometry/delaunayn.m, scripts/geometry/griddata.m, scripts/geometry/griddatan.m, scripts/geometry/voronoi.m, scripts/geometry/voronoin.m, scripts/gui/guihandles.m, scripts/gui/inputdlg.m, scripts/gui/listdlg.m, scripts/gui/msgbox.m, scripts/gui/questdlg.m, scripts/gui/uigetfile.m, scripts/gui/waitbar.m, scripts/gui/warndlg.m, scripts/help/doc.m, scripts/help/help.m, scripts/help/type.m, scripts/image/bone.m, scripts/image/cmpermute.m, scripts/image/cmunique.m, scripts/image/colorcube.m, scripts/image/colormap.m, scripts/image/contrast.m, scripts/image/gray2ind.m, scripts/image/image.m, scripts/image/imshow.m, scripts/image/ind2gray.m, scripts/image/jet.m, scripts/image/rgb2ntsc.m, scripts/image/spinmap.m, scripts/io/importdata.m, scripts/io/strread.m, scripts/io/textread.m, scripts/io/textscan.m, scripts/java/java_get.m, scripts/java/java_set.m, scripts/java/javaaddpath.m, scripts/java/javaclasspath.m, scripts/java/javamem.m, scripts/linear-algebra/linsolve.m, scripts/linear-algebra/qzhess.m, scripts/miscellaneous/debug.m, scripts/miscellaneous/desktop.m, scripts/miscellaneous/dir.m, scripts/miscellaneous/dos.m, scripts/miscellaneous/edit.m, scripts/miscellaneous/fact.m, scripts/miscellaneous/getappdata.m, scripts/miscellaneous/inputname.m, scripts/miscellaneous/license.m, scripts/miscellaneous/ls_command.m, scripts/miscellaneous/run.m, scripts/miscellaneous/setfield.m, scripts/miscellaneous/unix.m, scripts/miscellaneous/ver.m, scripts/mk-pkg-add, scripts/mkdoc.pl, scripts/optimization/fminsearch.m, scripts/optimization/optimset.m, scripts/optimization/sqp.m, scripts/pkg/pkg.m, scripts/pkg/private/create_pkgadddel.m, scripts/pkg/private/fix_depends.m, scripts/pkg/private/install.m, scripts/plot/appearance/axis.m, scripts/plot/appearance/box.m, scripts/plot/appearance/clabel.m, scripts/plot/appearance/daspect.m, scripts/plot/appearance/datetick.m, scripts/plot/appearance/grid.m, scripts/plot/appearance/legend.m, scripts/plot/appearance/orient.m, scripts/plot/appearance/shading.m, scripts/plot/appearance/text.m, scripts/plot/appearance/title.m, scripts/plot/appearance/xlabel.m, scripts/plot/appearance/ylabel.m, scripts/plot/appearance/zlabel.m, scripts/plot/draw/area.m, scripts/plot/draw/bar.m, scripts/plot/draw/barh.m, scripts/plot/draw/colorbar.m, scripts/plot/draw/contour.m, scripts/plot/draw/contour3.m, scripts/plot/draw/contourf.m, scripts/plot/draw/ellipsoid.m, scripts/plot/draw/errorbar.m, scripts/plot/draw/ezcontour.m, scripts/plot/draw/ezcontourf.m, scripts/plot/draw/ezmesh.m, scripts/plot/draw/ezpolar.m, scripts/plot/draw/fill.m, scripts/plot/draw/fplot.m, scripts/plot/draw/hist.m, scripts/plot/draw/meshc.m, scripts/plot/draw/meshz.m, scripts/plot/draw/pareto.m, scripts/plot/draw/patch.m, scripts/plot/draw/peaks.m, scripts/plot/draw/pie.m, scripts/plot/draw/pie3.m, scripts/plot/draw/plot.m, scripts/plot/draw/plotyy.m, scripts/plot/draw/private/__bar__.m, scripts/plot/draw/private/__contour__.m, scripts/plot/draw/private/__errplot__.m, scripts/plot/draw/private/__ezplot__.m, scripts/plot/draw/private/__patch__.m, scripts/plot/draw/private/__stem__.m, scripts/plot/draw/rectangle.m, scripts/plot/draw/ribbon.m, scripts/plot/draw/rose.m, scripts/plot/draw/scatter.m, scripts/plot/draw/scatter3.m, scripts/plot/draw/semilogx.m, scripts/plot/draw/shrinkfaces.m, scripts/plot/draw/sombrero.m, scripts/plot/draw/sphere.m, scripts/plot/draw/stairs.m, scripts/plot/draw/stem.m, scripts/plot/draw/stemleaf.m, scripts/plot/draw/surf.m, scripts/plot/draw/surface.m, scripts/plot/draw/surfc.m, scripts/plot/draw/surfl.m, scripts/plot/draw/surfnorm.m, scripts/plot/draw/tetramesh.m, scripts/plot/draw/trimesh.m, scripts/plot/draw/triplot.m, scripts/plot/draw/trisurf.m, scripts/plot/util/__gnuplot_drawnow__.m, scripts/plot/util/__plt_get_axis_arg__.m, scripts/plot/util/axes.m, scripts/plot/util/clf.m, scripts/plot/util/copyobj.m, scripts/plot/util/figure.m, scripts/plot/util/gcbo.m, scripts/plot/util/graphics_toolkit.m, scripts/plot/util/hggroup.m, scripts/plot/util/meshgrid.m, scripts/plot/util/newplot.m, scripts/plot/util/print.m, scripts/plot/util/private/__add_default_menu__.m, scripts/plot/util/private/__fltk_print__.m, scripts/plot/util/private/__gnuplot_print__.m, scripts/plot/util/private/__print_parse_opts__.m, scripts/plot/util/refreshdata.m, scripts/plot/util/subplot.m, scripts/polynomial/conv.m, scripts/polynomial/poly.m, scripts/polynomial/polyeig.m, scripts/polynomial/polyfit.m, scripts/polynomial/polyval.m, scripts/polynomial/private/__splinefit__.m, scripts/polynomial/spline.m, scripts/prefs/prefdir.m, scripts/prefs/preferences.m, scripts/prefs/private/prefsfile.m, scripts/prefs/rmpref.m, scripts/signal/freqz.m, scripts/signal/module.mk, scripts/sparse/eigs.m, scripts/sparse/pcg.m, scripts/sparse/private/__sprand_impl__.m, scripts/sparse/sprand.m, scripts/sparse/sprandn.m, scripts/sparse/spy.m, scripts/sparse/svds.m, scripts/specfun/expint.m, scripts/specfun/factor.m, scripts/special-matrix/gallery.m, scripts/special-matrix/hankel.m, scripts/special-matrix/toeplitz.m, scripts/startup/inputrc, scripts/statistics/base/kurtosis.m, scripts/statistics/base/moment.m, scripts/statistics/base/qqplot.m, scripts/statistics/base/var.m, scripts/statistics/distributions/betarnd.m, scripts/statistics/distributions/binoinv.m, scripts/statistics/distributions/binopdf.m, scripts/statistics/distributions/binornd.m, scripts/statistics/distributions/cauchy_rnd.m, scripts/statistics/distributions/chi2rnd.m, scripts/statistics/distributions/discrete_pdf.m, scripts/statistics/distributions/discrete_rnd.m, scripts/statistics/distributions/empirical_rnd.m, scripts/statistics/distributions/exprnd.m, scripts/statistics/distributions/frnd.m, scripts/statistics/distributions/gamrnd.m, scripts/statistics/distributions/geornd.m, scripts/statistics/distributions/hygernd.m, scripts/statistics/distributions/kolmogorov_smirnov_cdf.m, scripts/statistics/distributions/laplace_cdf.m, scripts/statistics/distributions/laplace_pdf.m, scripts/statistics/distributions/logistic_cdf.m, scripts/statistics/distributions/logistic_pdf.m, scripts/statistics/distributions/lognrnd.m, scripts/statistics/distributions/nbincdf.m, scripts/statistics/distributions/nbininv.m, scripts/statistics/distributions/nbinpdf.m, scripts/statistics/distributions/nbinrnd.m, scripts/statistics/distributions/normrnd.m, scripts/statistics/distributions/poissinv.m, scripts/statistics/distributions/poissrnd.m, scripts/statistics/distributions/tinv.m, scripts/statistics/distributions/trnd.m, scripts/statistics/distributions/unidcdf.m, scripts/statistics/distributions/unidpdf.m, scripts/statistics/distributions/unidrnd.m, scripts/statistics/distributions/unifrnd.m, scripts/statistics/distributions/wblrnd.m, scripts/statistics/models/module.mk, scripts/statistics/tests/kruskal_wallis_test.m, scripts/strings/base2dec.m, scripts/strings/deblank.m, scripts/strings/dec2base.m, scripts/strings/dec2bin.m, scripts/strings/dec2hex.m, scripts/strings/mat2str.m, scripts/strings/ostrsplit.m, scripts/strings/regexptranslate.m, scripts/strings/str2num.m, scripts/strings/strcat.m, scripts/strings/strjoin.m, scripts/strings/strsplit.m, scripts/strings/strtok.m, scripts/strings/strtrim.m, scripts/strings/strtrunc.m, scripts/strings/substr.m, scripts/testfun/__run_test_suite__.m, scripts/testfun/speed.m, scripts/testfun/test.m, scripts/time/asctime.m, scripts/time/datenum.m, scripts/time/datevec.m, scripts/time/weekday.m, src/Makefile.am, test/Makefile.am, test/build-bc-overload-tests.sh, test/build-sparse-tests.sh, test/jit.tst, test/line-continue.tst: Strip trailing whitespace.
author John W. Eaton <jwe@octave.org>
date Tue, 20 Jan 2015 08:26:57 -0500
parents c766a1f63c40
children fe689210525c
line wrap: on
line source

/*

Copyright (C) 2011-2013 Jacob Dawid

This file is part of Octave.

Octave 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.

Octave 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 Octave; see the file COPYING.  If not, see
<http://www.gnu.org/licenses/>.

*/

#ifdef HAVE_CONFIG_H
#include <config.h>
#endif

#ifdef HAVE_QSCINTILLA

#if defined (HAVE_QSCI_QSCILEXEROCTAVE_H)
#define HAVE_LEXER_OCTAVE
#include <Qsci/qscilexeroctave.h>
#elif defined (HAVE_QSCI_QSCILEXERMATLAB_H)
#define HAVE_LEXER_MATLAB
#include <Qsci/qscilexermatlab.h>
#endif
#include <Qsci/qscilexercpp.h>
#include <Qsci/qscilexerbash.h>
#include <Qsci/qscilexerperl.h>
#include <Qsci/qscilexerbatch.h>
#include <Qsci/qscilexerdiff.h>
#include <Qsci/qsciprinter.h>
#include "resource-manager.h"
#include <QApplication>
#include <QFileDialog>
#include <QMessageBox>
#include <QTextStream>
#include <QVBoxLayout>
#include <QInputDialog>
#include <QPrintDialog>

#include "file-editor-tab.h"
#include "file-editor.h"

#include "file-ops.h"

#include "debug.h"
#include "octave-qt-link.h"
#include "version.h"

// Make parent null for the file editor tab so that warning
// WindowModal messages don't affect grandparents.
file_editor_tab::file_editor_tab (const QString& directory_arg)
{
  QString directory = directory_arg;
  _lexer_apis = 0;
  _app_closing = false;

  // Make sure there is a slash at the end of the directory name
  // for identification when saved later.
  if (directory.count () && directory.at (directory.count () - 1) != '/')
    directory.append ("/");

  _file_name = directory;
  _file_system_watcher.setObjectName ("_qt_autotest_force_engine_poller");

  _edit_area = new octave_qscintilla (this);
  // Connect signal for command execution to a slot of this tab which in turn
  // emits a signal connected to the main window.
  // Direct connection is not possible because tab's parent is null.
  connect (_edit_area,
           SIGNAL (execute_command_in_terminal_signal (const QString&)),
           this,
           SLOT (execute_command_in_terminal (const QString&)));

  connect (_edit_area,
           SIGNAL (cursorPositionChanged (int, int)),
           this,
           SLOT (handle_cursor_moved (int,int)));

  // create statusbar for row/col indicator and eol mode
  _status_bar = new QStatusBar (this);

  // eol mode
  _eol_indicator = new QLabel ("",this);
  _eol_indicator->setMinimumSize (35,0);
  _status_bar->addPermanentWidget (_eol_indicator, 0);

  // row- and col-indicator
  _row_indicator = new QLabel ("", this);
  _row_indicator->setMinimumSize (30,0);
  QLabel *row_label = new QLabel (tr ("Line:"), this);
  _col_indicator = new QLabel ("", this);
  _col_indicator->setMinimumSize (25,0);
  QLabel *col_label = new QLabel (tr ("Col:"), this);
  _status_bar->addPermanentWidget (row_label, 0);
  _status_bar->addPermanentWidget (_row_indicator, 0);
  _status_bar->addPermanentWidget (col_label, 0);
  _status_bar->addPermanentWidget (_col_indicator, 0);

  // Leave the find dialog box out of memory until requested.
  _find_dialog = 0;
  _find_dialog_is_visible = false;

  // symbols
  _edit_area->setMarginType (1, QsciScintilla::SymbolMargin);
  _edit_area->setMarginSensitivity (1, true);
  _edit_area->markerDefine (QsciScintilla::RightTriangle, bookmark);
  _edit_area->markerDefine (QPixmap (":/actions/icons/redled.png"),
                            breakpoint);
  _edit_area->markerDefine (QPixmap (":/actions/icons/bookmark.png"),
                            debugger_position);

  connect (_edit_area, SIGNAL (marginClicked (int, int,
                                              Qt::KeyboardModifiers)),
           this, SLOT (handle_margin_clicked (int, int,
                                              Qt::KeyboardModifiers)));

  // line numbers
  _edit_area->setMarginsForegroundColor (QColor (96, 96, 96));
  _edit_area->setMarginsBackgroundColor (QColor (232, 232, 220));
  _edit_area->setMarginType (2, QsciScintilla::TextMargin);

  // code folding
  _edit_area->setMarginType (3, QsciScintilla::SymbolMargin);
  _edit_area->setFolding (QsciScintilla::BoxedTreeFoldStyle , 3);

  // other features
  _edit_area->setBraceMatching (QsciScintilla::StrictBraceMatch);
  _edit_area->setAutoIndent (true);
  _edit_area->setIndentationWidth (2);
  _edit_area->setIndentationsUseTabs (false);

  _edit_area->setUtf8 (true);

  // auto completion
  _edit_area->autoCompleteFromAll ();
  _edit_area->setAutoCompletionSource (QsciScintilla::AcsAll);

  QVBoxLayout *edit_area_layout = new QVBoxLayout ();
  edit_area_layout->addWidget (_edit_area);
  edit_area_layout->addWidget (_status_bar);
  edit_area_layout->setMargin (0);
  setLayout (edit_area_layout);

  // connect modified signal
  connect (_edit_area, SIGNAL (modificationChanged (bool)),
           this, SLOT (update_window_title (bool)));

  connect (_edit_area, SIGNAL (copyAvailable (bool)),
           this, SLOT (handle_copy_available (bool)));

  connect (&_file_system_watcher, SIGNAL (fileChanged (const QString&)),
           this, SLOT (file_has_changed (const QString&)));

  QSettings *settings = resource_manager::get_settings ();
  if (settings)
    notice_settings (settings);
}

file_editor_tab::~file_editor_tab (void)
{
  // Destroy items attached to _edit_area.
  QsciLexer *lexer = _edit_area->lexer ();
  if (lexer)
    {
      delete lexer;
      _edit_area->setLexer (0);
    }
  if (_find_dialog)
    {
      delete _find_dialog;
      _find_dialog = 0;
    }

  // Destroy _edit_area.
  delete _edit_area;
}

void
file_editor_tab::closeEvent (QCloseEvent *e)
{
  // ignore close event if file is not saved and user cancels
  // closing this window
  if (check_file_modified () == QMessageBox::Cancel)
    e->ignore ();
  else
    e->accept ();
}

void
file_editor_tab::execute_command_in_terminal (const QString& command)
{
  emit execute_command_in_terminal_signal (command); // connected to main window
}

void
file_editor_tab::set_file_name (const QString& fileName)
{
  // update tracked file if we really have a file on disk
  QStringList trackedFiles = _file_system_watcher.files ();
  if (!trackedFiles.isEmpty ())
    _file_system_watcher.removePath (_file_name);
  if (!fileName.isEmpty ())
    _file_system_watcher.addPath (fileName);
  _file_name = fileName;

  // update lexer after _file_name change
  update_lexer ();

  // update the file editor with current editing directory
  emit editor_state_changed (_copy_available, _file_name);
  // add the new file to the mru list

  emit mru_add_file (_file_name);
}

// valid_file_name (file): checks whether "file" names a file
// by default, "file" is empty, then _file_name is checked
bool
file_editor_tab::valid_file_name (const QString& file)
{
  QString file_name;
  if (file.isEmpty ())
    file_name = _file_name;
  else
    file_name = file;
  return (! file_name.isEmpty ()
          && file_name.at (file_name.count () - 1) != '/');
}

void
file_editor_tab::handle_margin_clicked (int margin, int line,
                                        Qt::KeyboardModifiers state)
{
  if (margin == 1)
    {
      unsigned int markers_mask = _edit_area->markersAtLine (line);

      if (state & Qt::ControlModifier)
        {
          if (markers_mask && (1 << bookmark))
            _edit_area->markerDelete (line, bookmark);
          else
            _edit_area->markerAdd (line, bookmark);
        }
      else
        {
          if (markers_mask && (1 << breakpoint))
            request_remove_breakpoint (line);
          else
            request_add_breakpoint (line);
        }
    }
}

void
file_editor_tab::update_lexer ()
{
  if (_lexer_apis)
    _lexer_apis->cancelPreparation ();  // stop preparing if apis exists

  QsciLexer *lexer = _edit_area->lexer ();
  delete lexer;
  lexer = 0;

  if (_file_name.endsWith (".m")
      || _file_name.endsWith ("octaverc"))
    {
#if defined (HAVE_LEXER_OCTAVE)
      lexer = new QsciLexerOctave ();
#elif defined (HAVE_LEXER_MATLAB)
      lexer = new QsciLexerMatlab ();
#endif
    }

  if (! lexer)
    {
      if (_file_name.endsWith (".c")
          || _file_name.endsWith (".cc")
          || _file_name.endsWith (".cpp")
          || _file_name.endsWith (".cxx")
          || _file_name.endsWith (".c++")
          || _file_name.endsWith (".h")
          || _file_name.endsWith (".hh")
          || _file_name.endsWith (".hpp")
          || _file_name.endsWith (".h++"))
        {
          lexer = new QsciLexerCPP ();
        }
      else if (_file_name.endsWith (".pl"))
        {
          lexer = new QsciLexerPerl ();
        }
      else if (_file_name.endsWith (".bat"))
        {
          lexer = new QsciLexerBatch ();
        }
      else if (_file_name.endsWith (".diff"))
        {
          lexer = new QsciLexerDiff ();
        }
      else if (! valid_file_name ())
        {
          // new, no yet named file: let us assume it is octave
#if defined (HAVE_LEXER_OCTAVE)
          lexer = new QsciLexerOctave ();
#elif defined (HAVE_LEXER_MATLAB)
          lexer = new QsciLexerMatlab ();
#else
          lexer = new QsciLexerBash ();
#endif
        }
      else
        {
          // other or no extension
          lexer = new QsciLexerBash ();
        }
    }

  _lexer_apis = new QsciAPIs(lexer);
  if (_lexer_apis)
    {
      // get path to prepared api info
      QDesktopServices desktopServices;
      QString prep_apis_path
        = desktopServices.storageLocation (QDesktopServices::HomeLocation)
          + "/.config/octave/"  + QString(OCTAVE_VERSION) + "/qsci/";
      _prep_apis_file = prep_apis_path + lexer->lexer () + ".pap";

      if (!_lexer_apis->loadPrepared (_prep_apis_file))
        {
          // no prepared info loaded, prepare and save if possible

          // create raw apis info
          QString keyword;
          QStringList keyword_list;
          int i,j;
          for (i=1; i<=3; i++) // test the first 5 keyword sets
            {
              keyword = QString(lexer->keywords (i));           // get list
              keyword_list = keyword.split (QRegExp ("\\s+"));  // split
              for (j = 0; j < keyword_list.size (); j++)        // add to API
                _lexer_apis->add (keyword_list.at (j));
            }

          // dsiconnect slot for saving prepared info if already connected
          disconnect (_lexer_apis, SIGNAL (apiPreparationFinished ()), 0, 0);
          // check whether path for prepared info exists or can be created
          if (QDir("/").mkpath (prep_apis_path))
            {
              // path exists, apis info can be saved there
              connect (_lexer_apis, SIGNAL (apiPreparationFinished ()),
                       this, SLOT (save_apis_info ()));
            }
          _lexer_apis->prepare ();  // prepare apis info
        }
    }

  QSettings *settings = resource_manager::get_settings ();
  if (settings)
    lexer->readSettings (*settings);

  _edit_area->setLexer (lexer);

  // fix line number width with respect to the font size of the lexer
  if (settings->value ("editor/showLineNumbers", true).toBool ())
    auto_margin_width ();
  else
    _edit_area->setMarginWidth (2,0);

}

void
file_editor_tab::save_apis_info ()
{
  _lexer_apis->savePrepared (_prep_apis_file);
}

QString
file_editor_tab::comment_string (const QString& lexer)
{
  if (lexer == "octave" || lexer == "matlab")
    return QString("%");
  else if (lexer == "perl" || lexer == "bash" || lexer == "diff")
    return QString("#");
  else if (lexer == "cpp")
    return ("//");
  else if (lexer == "batch")
    return ("REM ");
  else
    return ("%");  // should never happen
}

// slot for fetab_set_focus: sets the focus to the current edit area
void
file_editor_tab::set_focus (const QWidget *ID)
{
  if (ID != this)
    return;
  _edit_area->setFocus ();
}

void
file_editor_tab::undo (const QWidget *ID)
{
  if (ID != this)
    return;

  _edit_area->undo ();
}

void
file_editor_tab::redo (const QWidget *ID)
{
  if (ID != this)
    return;

  _edit_area->redo ();
}

void
file_editor_tab::copy (const QWidget *ID)
{
  if (ID != this)
    return;

  _edit_area->copy ();
}

void
file_editor_tab::cut (const QWidget *ID)
{
  if (ID != this)
    return;

  _edit_area->cut ();
}

void
file_editor_tab::paste (const QWidget *ID)
{
  if (ID != this)
    return;

  _edit_area->paste ();
}

void
file_editor_tab::context_help (const QWidget *ID, bool doc)
{
  if (ID != this)
    return;

  _edit_area->context_help_doc (doc);
}

void
file_editor_tab::context_edit (const QWidget *ID)
{
  if (ID != this)
    return;

  _edit_area->context_edit ();
}

void
file_editor_tab::save_file (const QWidget *ID)
{
  if (ID != this)
    return;

  save_file (_file_name);
}
void

file_editor_tab::save_file (const QWidget *ID, const QString& fileName,
                            bool remove_on_success)
{
  if (ID != this)
    return;

  save_file (fileName, remove_on_success);
}

void
file_editor_tab::save_file_as (const QWidget *ID)
{
  if (ID != this)
    return;

  save_file_as ();
}

void
file_editor_tab::print_file (const QWidget *ID)
{
  if (ID != this)
    return;

  QsciPrinter *printer = new QsciPrinter (QPrinter::HighResolution);

  QPrintDialog printDlg (printer, this);

  if (printDlg.exec () == QDialog::Accepted)
    printer->printRange (_edit_area);

  delete printer;
}

void
file_editor_tab::run_file (const QWidget *ID)
{
  if (ID != this)
    return;

  if (_edit_area->isModified ())
    save_file (_file_name);

  QFileInfo info (_file_name);
  emit run_file_signal (info);
}

void
file_editor_tab::context_run (const QWidget *ID)
{
  if (ID != this)
    return;

  _edit_area->context_run ();
}

void
file_editor_tab::toggle_bookmark (const QWidget *ID)
{
  if (ID != this)
    return;

  int line, cur;
  _edit_area->getCursorPosition (&line, &cur);

  if (_edit_area->markersAtLine (line) && (1 << bookmark))
    _edit_area->markerDelete (line, bookmark);
  else
    _edit_area->markerAdd (line, bookmark);
}

void
file_editor_tab::next_bookmark (const QWidget *ID)
{
  if (ID != this)
    return;

  int line, cur;
  _edit_area->getCursorPosition (&line, &cur);

  if (_edit_area->markersAtLine (line) && (1 << bookmark))
    line++; // we have a breakpoint here, so start search from next line

  int nextline = _edit_area->markerFindNext (line, (1 << bookmark));

  _edit_area->setCursorPosition (nextline, 0);
}

void
file_editor_tab::previous_bookmark (const QWidget *ID)
{
  if (ID != this)
    return;

  int line, cur;
  _edit_area->getCursorPosition (&line, &cur);

  if (_edit_area->markersAtLine (line) && (1 << bookmark))
    line--; // we have a breakpoint here, so start search from prev line

  int prevline = _edit_area->markerFindPrevious (line, (1 << bookmark));

  _edit_area->setCursorPosition (prevline, 0);
}

void
file_editor_tab::remove_bookmark (const QWidget *ID)
{
  if (ID != this)
    return;

  _edit_area->markerDeleteAll (bookmark);
}

void
file_editor_tab::add_breakpoint_callback (const bp_info& info)
{
  bp_table::intmap line_info;
  line_info[0] = info.line;

  if (octave_qt_link::file_in_path (info.file, info.dir))
    bp_table::add_breakpoint (info.function_name, line_info);
}

void
file_editor_tab::remove_breakpoint_callback (const bp_info& info)
{
  bp_table::intmap line_info;
  line_info[0] = info.line;

  if (octave_qt_link::file_in_path (info.file, info.dir))
    bp_table::remove_breakpoint (info.function_name, line_info);
}

void
file_editor_tab::remove_all_breakpoints_callback (const bp_info& info)
{
  if (octave_qt_link::file_in_path (info.file, info.dir))
    bp_table::remove_all_breakpoints_in_file (info.function_name, true);
}

file_editor_tab::bp_info::bp_info (const QString& fname, int l)
  : line (l), file (fname.toStdString ())
{
  QFileInfo file_info (fname);

  QString q_dir = file_info.absolutePath ();
  QString q_function_name = file_info.fileName ();

  // We have to cut off the suffix, because octave appends it.
  q_function_name.chop (file_info.suffix ().length () + 1);

  dir = q_dir.toStdString ();
  function_name = q_function_name.toStdString ();

  // Is the last component of DIR @foo?  If so, strip it and prepend it
  // to the name of the function.

  size_t pos = dir.rfind (file_ops::dir_sep_chars ());

  if (pos != std::string::npos && pos < dir.length () - 1)
    {
      if (dir[pos+1] == '@')
        {
          function_name = file_ops::concat (dir.substr (pos+1), function_name);

          dir = dir.substr (0, pos);
        }
    }
}

void
file_editor_tab::request_add_breakpoint (int line)
{
  bp_info info (_file_name, line+1);

  octave_link::post_event
    (this, &file_editor_tab::add_breakpoint_callback, info);
}

void
file_editor_tab::request_remove_breakpoint (int line)
{
  bp_info info (_file_name, line+1);

  octave_link::post_event
    (this, &file_editor_tab::remove_breakpoint_callback, info);
}

void
file_editor_tab::toggle_breakpoint (const QWidget *ID)
{
  if (ID != this)
    return;

  int line, cur;
  _edit_area->getCursorPosition (&line, &cur);

  if (_edit_area->markersAtLine (line) && (1 << breakpoint))
    request_remove_breakpoint (line);
  else
    request_add_breakpoint (line);
}

void
file_editor_tab::next_breakpoint (const QWidget *ID)
{
  if (ID != this)
    return;

  int line, cur;
  _edit_area->getCursorPosition (&line, &cur);

  if (_edit_area->markersAtLine (line) && (1 << breakpoint))
    line++; // we have a breakpoint here, so start search from next line

  int nextline = _edit_area->markerFindNext (line, (1 << breakpoint));

  _edit_area->setCursorPosition (nextline, 0);
}

void
file_editor_tab::previous_breakpoint (const QWidget *ID)
{
  if (ID != this)
    return;

  int line, cur, prevline;
  _edit_area->getCursorPosition (&line, &cur);

  if (_edit_area->markersAtLine (line) && (1 << breakpoint))
    line--; // we have a breakpoint here, so start search from prev line

  prevline = _edit_area->markerFindPrevious (line, (1 << breakpoint));

  _edit_area->setCursorPosition (prevline, 0);
}

void
file_editor_tab::remove_all_breakpoints (const QWidget *ID)
{
  if (ID != this)
    return;

  bp_info info (_file_name);

  octave_link::post_event
    (this, &file_editor_tab::remove_all_breakpoints_callback, info);
}

void
file_editor_tab::comment_selected_text (const QWidget *ID)
{
  if (ID != this)
    return;

  do_comment_selected_text (true);
}

void
file_editor_tab::uncomment_selected_text (const QWidget *ID)
{
  if (ID != this)
    return;

  do_comment_selected_text (false);
}

void
file_editor_tab::handle_find_dialog_finished (int)
{
  // Find dialog is going to hide.  Save location of window for
  // when it is reshown.
  _find_dialog_geometry = _find_dialog->geometry ();
  _find_dialog_is_visible = false;
}

void
file_editor_tab::find (const QWidget *ID)
{
  if (ID != this)
    return;

  // The find_dialog feature doesn't need a slot for return info.
  // Rather than Qt::DeleteOnClose, let the find feature hang about
  // in case it contains useful information like previous searches
  // and so on.  Perhaps one find dialog for the whole editor is
  // better, but individual find dialogs has the nice feature of
  // retaining position per file editor tabs, which can be undocked.

  if (!_find_dialog)
    {
      _find_dialog = new find_dialog (_edit_area,
                                      qobject_cast<QWidget *> (sender ()));
      connect (_find_dialog, SIGNAL (finished (int)),
               this, SLOT (handle_find_dialog_finished (int)));
      _find_dialog->setWindowModality (Qt::NonModal);
      _find_dialog_geometry = _find_dialog->geometry ();
    }

  if (!_find_dialog->isVisible ())
    {
      _find_dialog->setGeometry (_find_dialog_geometry);
      _find_dialog->show ();
      _find_dialog_is_visible = true;
    }

  _find_dialog->activateWindow ();
  _find_dialog->init_search_text ();

}

void
file_editor_tab::goto_line (const QWidget *ID, int line)
{
  if (ID != this)
    return;

  if (line <= 0)  // ask for desired line
    {
      bool ok = false;
      int index;
      _edit_area->getCursorPosition (&line, &index);
      line = QInputDialog::getInt (_edit_area, tr ("Goto line"),
                                   tr ("Line number"), line+1, 1,
                                   _edit_area->lines (), 1, &ok);
      if (ok)
        {
          _edit_area->setCursorPosition (line-1, 0);
          center_current_line ();
        }
    }
  else  // go to given line without dialog
    _edit_area->setCursorPosition (line-1, 0);
}


void
file_editor_tab::do_comment_selected_text (bool comment)
{
  QString comment_str = comment_string (_edit_area->lexer ()->lexer ());
  _edit_area->beginUndoAction ();

  if (_edit_area->hasSelectedText ())
    {
      int lineFrom, lineTo, colFrom, colTo;
      _edit_area->getSelection (&lineFrom, &colFrom, &lineTo, &colTo);

      if (colTo == 0)  // the beginning of last line is not selected
        lineTo--;        // stop at line above

      for (int i = lineFrom; i <= lineTo; i++)
        {
          if (comment)
            _edit_area->insertAt (comment_str, i, 0);
          else
            {
              QString line (_edit_area->text (i));
              if (line.startsWith (comment_str))
                {
                  _edit_area->setSelection (i, 0, i, comment_str.length ());
                  _edit_area->removeSelectedText ();
                }
            }
        }
      //set selection on (un)commented section
      _edit_area->setSelection (lineFrom, 0, lineTo,
                                _edit_area->text (lineTo).length ());
    }
  else
    {
      int cpline, col;
      _edit_area->getCursorPosition (&cpline, &col);
      if (comment)
        _edit_area->insertAt (comment_str, cpline, 0);
      else
        {
          QString line (_edit_area->text (cpline));
          if (line.startsWith (comment_str))
            {
              _edit_area->setSelection (cpline, 0, cpline, comment_str.length ());
              _edit_area->removeSelectedText ();
            }
        }
    }
  _edit_area->endUndoAction ();
}

void
file_editor_tab::update_window_title (bool modified)
{
  QString title ("");
  QString tooltip ("");

  if (! valid_file_name ())
    title = tr ("<unnamed>");
  else
    {
      if (_long_title)
        title = _file_name;
      else
        {
          QFileInfo file (_file_name);
          title = file.fileName ();
          tooltip = _file_name;
        }
    }

  if (modified)
    emit file_name_changed (title.prepend ("* "), tooltip);
  else
    emit file_name_changed (title, tooltip);
}

void
file_editor_tab::handle_copy_available (bool enableCopy)
{
  _copy_available = enableCopy;
  emit editor_state_changed (_copy_available, QDir::cleanPath (_file_name));
}

// show_dialog: shows a modal or non modal dialog depeding on the closing
//              of the app
void
file_editor_tab::show_dialog (QDialog *dlg)
{
  dlg->setAttribute (Qt::WA_DeleteOnClose);
  if (_app_closing)
    dlg->exec ();
  else
    {
      dlg->setWindowModality (Qt::WindowModal);
      dlg->show ();
    }
}

int
file_editor_tab::check_file_modified ()
{
  int decision = QMessageBox::Yes;
  if (_edit_area->isModified ())
    {
      activateWindow ();
      raise ();
      // File is modified but not saved, ask user what to do.  The file
      // editor tab can't be made parent because it may be deleted depending
      // upon the response.  Instead, change the _edit_area to read only.
      QMessageBox::StandardButtons buttons = QMessageBox::Save |
                                             QMessageBox::Discard;
      QString available_actions;

      if (_app_closing)
        available_actions = tr ("Do you want to save or discard the changes?");
      else
        {
          buttons = buttons | QMessageBox::Cancel;  // cancel is allowed
          available_actions
            = tr ("Do you want to cancel closing, save or discard the changes?");
        }

      QString file;
      if (valid_file_name ())
          file = _file_name;
      else
          file = tr ("<unnamed>");

      QMessageBox* msgBox
        = new QMessageBox (QMessageBox::Warning, tr ("Octave Editor"),
                           tr ("The file\n"
                               "%1\n"
                               "is about to be closed but has been modified.\n"
                               "%2").
                           arg (file). arg (available_actions),
                           buttons, qobject_cast<QWidget *> (parent ()));

      msgBox->setDefaultButton (QMessageBox::Save);
      _edit_area->setReadOnly (true);
      connect (msgBox, SIGNAL (finished (int)),
               this, SLOT (handle_file_modified_answer (int)));

      show_dialog (msgBox);

      return QMessageBox::Cancel;
    }
  else
    {
      // Nothing was modified, just remove from editor.
      emit tab_remove_request ();
    }

  return decision;
}

void
file_editor_tab::handle_file_modified_answer (int decision)
{
  if (decision == QMessageBox::Save)
    {
      // Save file, then remove from editor.
      save_file (_file_name, true);
    }
  else if (decision == QMessageBox::Discard)
    {
      // User doesn't want to save, just remove from editor.
      emit tab_remove_request ();
    }
  else
    {
      // User canceled, allow editing again.
      _edit_area->setReadOnly (false);
    }
}

void
file_editor_tab::set_modified (bool modified)
{
  _edit_area->setModified (modified);
}

QString
file_editor_tab::load_file (const QString& fileName)
{
  // get the absolute path
  QFileInfo file_info = QFileInfo (fileName);
  QString file_to_load;
  if (file_info.exists ())
    file_to_load = file_info.canonicalFilePath ();
  else
    file_to_load = fileName;
  QFile file (file_to_load);
  if (!file.open (QFile::ReadOnly))
    return file.errorString ();

  QTextStream in (&file);
  QApplication::setOverrideCursor (Qt::WaitCursor);
  _edit_area->setText (in.readAll ());
  _edit_area->setEolMode (detect_eol_mode ());
  QApplication::restoreOverrideCursor ();

  _copy_available = false;     // no selection yet available
  set_file_name (file_to_load);
  update_window_title (false); // window title (no modification)
  _edit_area->setModified (false); // loaded file is not modified yet

  update_eol_indicator ();

  return QString ();
}

QsciScintilla::EolMode
file_editor_tab::detect_eol_mode ()
{
  char *text = _edit_area->text ().toAscii ().data ();
  int text_size = _edit_area->text ().length ();

  char eol_lf = 0x0a;
  char eol_cr = 0x0d;

  int count_lf = 0;
  int count_cr = 0;
  int count_crlf = 0;

  for (int i = 0; i < text_size; i++)
    {
      if (text[i] == eol_lf)
        {
          count_lf++;
        }
      else
        {
          if (text[i] == eol_cr)
            {
              if ((i < text_size -1) && text[i+1] == eol_lf)
                {
                  count_crlf++;
                  i++;
                }
              else
                count_cr++;
            }
        }
    }

  QsciScintilla::EolMode eol_mode = QsciScintilla::EolUnix;
  int count_max = count_lf;

  if (count_cr > count_max)
    {
      eol_mode = QsciScintilla::EolMac;
      count_max = count_cr;
    }
  if (count_crlf > count_max)
    {
      eol_mode = QsciScintilla::EolWindows;
    }

  return eol_mode;
}

void
file_editor_tab::update_eol_indicator ()
{
  switch (_edit_area->eolMode ())
    {
      case QsciScintilla::EolWindows:
        _eol_indicator->setText ("CRLF");
        break;
      case QsciScintilla::EolMac:
        _eol_indicator->setText ("CR");
        break;
      case QsciScintilla::EolUnix:
        _eol_indicator->setText ("LF");
        break;
    }
}

void
file_editor_tab::new_file (const QString &commands)
{
  update_window_title (false); // window title (no modification)
  _edit_area->setText (commands);
  _edit_area->setModified (false); // new file is not modified yet
  update_eol_indicator ();
}

void
file_editor_tab::save_file (const QString& saveFileName, bool remove_on_success)
{
  // If it is a new file with no name, signal that saveFileAs
  // should be performed.
  if (! valid_file_name (saveFileName))
    {
      save_file_as (remove_on_success);
      return;
    }
  // get the absolute path (if existing)
  QFileInfo file_info = QFileInfo (saveFileName);
  QString file_to_save;
  if (file_info.exists ())
    file_to_save = file_info.canonicalFilePath ();
  else
    file_to_save = saveFileName;
  QFile file (file_to_save);

  // stop watching file
  QStringList trackedFiles = _file_system_watcher.files ();
  if (trackedFiles.contains (file_to_save))
    _file_system_watcher.removePath (file_to_save);

  // open the file for writing
  if (!file.open (QIODevice::WriteOnly))
    {
      // Unsuccessful, begin watching file again if it was being
      // watched previously.
      if (trackedFiles.contains (file_to_save))
        _file_system_watcher.addPath (file_to_save);

      // Create a NonModal message about error.
      QMessageBox* msgBox
        = new QMessageBox (QMessageBox::Critical,
                           tr ("Octave Editor"),
                           tr ("Could not open file %1 for write:\n%2.").
                           arg (file_to_save).arg (file.errorString ()),
                           QMessageBox::Ok, 0);
      show_dialog (msgBox);

      return;
    }

  // save the contents into the file
  QTextStream out (&file);
  QApplication::setOverrideCursor (Qt::WaitCursor);
  out << _edit_area->text ();
  out.flush ();
  QApplication::restoreOverrideCursor ();
  file.flush ();
  file.close ();

  // file exists now
  file_info = QFileInfo (file);
  file_to_save = file_info.canonicalFilePath ();

  // save file name after closing file as set_file_name starts watching again
  set_file_name (file_to_save);   // make absolute

  // set the window title to actual file name (not modified)
  update_window_title (false);

  // files is save -> not modified
  _edit_area->setModified (false);

  if (remove_on_success)
    {
      emit tab_remove_request ();
      return;  // Don't touch member variables after removal
    }
}

void
file_editor_tab::save_file_as (bool remove_on_success)
{
  // Simply put up the file chooser dialog box with a slot connection
  // then return control to the system waiting for a file selection.

  // If the tab is removed in response to a QFileDialog signal, the tab
  // can't be a parent.
  QFileDialog* fileDialog;
  if (remove_on_success)
    {
      // If tab is closed, "this" cannot be parent in which case modality
      // has no effect.  Disable editing instead.
      _edit_area->setReadOnly (true);
      fileDialog = new QFileDialog ();
    }
  else
    fileDialog = new QFileDialog (this);

  // Giving trouble under KDE (problem is related to Qt signal handling on unix,
  // see https://bugs.kde.org/show_bug.cgi?id=260719 ,
  // it had/has no effect on Windows, though)
  fileDialog->setOption(QFileDialog::DontUseNativeDialog, true);

  if (valid_file_name ())
    {
      fileDialog->selectFile (_file_name);
    }
  else
    {
      fileDialog->selectFile ("");

      if (_file_name.isEmpty ())
        fileDialog->setDirectory (QDir::currentPath ());
      else
        {
          // The file name is actually the directory name from the
          // constructor argument.
          fileDialog->setDirectory (_file_name);
        }
    }

  fileDialog->setNameFilter (tr ("Octave Files (*.m);;All Files (*)"));
  fileDialog->setDefaultSuffix ("m");
  fileDialog->setAcceptMode (QFileDialog::AcceptSave);
  fileDialog->setViewMode (QFileDialog::Detail);

  if (remove_on_success)
    {
      connect (fileDialog, SIGNAL (fileSelected (const QString&)),
               this, SLOT (handle_save_file_as_answer_close (const QString&)));

      connect (fileDialog, SIGNAL (rejected ()),
               this, SLOT (handle_save_file_as_answer_cancel ()));
    }
  else
    {
      connect (fileDialog, SIGNAL (fileSelected (const QString&)),
               this, SLOT (handle_save_file_as_answer (const QString&)));
    }

  show_dialog (fileDialog);
}

void
file_editor_tab::handle_save_file_as_answer (const QString& saveFileName)
{
  if (saveFileName == _file_name)
    {
      // same name as actual file, save it as "save" would do
      save_file (saveFileName);
    }
  else
    {
      // Have editor check for conflict, do not delete tab after save.
      emit editor_check_conflict_save (saveFileName, false);
    }
}

void
file_editor_tab::handle_save_file_as_answer_close (const QString& saveFileName)
{
  // saveFileName == _file_name can not happen, because we only can get here
  // when we close a tab and _file_name is not a valid file name yet

  // Have editor check for conflict, delete tab after save.
  emit editor_check_conflict_save (saveFileName, true);
}

void
file_editor_tab::handle_save_file_as_answer_cancel ()
{
  // User canceled, allow editing again.
  _edit_area->setReadOnly (false);
}

void
file_editor_tab::file_has_changed (const QString&)
{
  // Prevent popping up multiple message boxes when the file has
  // been changed multiple times by temporarily removing from the
  // file watcher.
  QStringList trackedFiles = _file_system_watcher.files ();
  if (!trackedFiles.isEmpty ())
    _file_system_watcher.removePath (_file_name);

  if (QFile::exists (_file_name))
    {
      // Create a WindowModal message that blocks the edit area
      // by making _edit_area parent.
      QMessageBox* msgBox
        = new QMessageBox (QMessageBox::Warning,
                           tr ("Octave Editor"),
                           tr ("It seems that \'%1\' has been modified by another application. Do you want to reload it?").
                           arg (_file_name),
                           QMessageBox::Yes | QMessageBox::No, this);

      connect (msgBox, SIGNAL (finished (int)),
               this, SLOT (handle_file_reload_answer (int)));

      msgBox->setWindowModality (Qt::WindowModal);
      msgBox->setAttribute (Qt::WA_DeleteOnClose);
      msgBox->show ();
    }
  else
    {
      QString modified = "";
      if (_edit_area->isModified ())
        modified = tr ("\n\nWarning: The contents in the editor is modified!");

      // Create a WindowModal message. The file editor tab can't be made
      // parent because it may be deleted depending upon the response.
      // Instead, change the _edit_area to read only.
      QMessageBox* msgBox
        = new QMessageBox (QMessageBox::Warning, tr ("Octave Editor"),
                           tr ("It seems that the file\n"
                               "%1\n"
                               "has been deleted or renamed. Do you want to save it now?%2").
                           arg (_file_name).arg (modified),
                           QMessageBox::Save | QMessageBox::Close, 0);

      _edit_area->setReadOnly (true);

      connect (msgBox, SIGNAL (finished (int)),
               this, SLOT (handle_file_resave_answer (int)));

      msgBox->setWindowModality (Qt::WindowModal);
      msgBox->setAttribute (Qt::WA_DeleteOnClose);
      msgBox->show ();
    }
}

void
file_editor_tab::notice_settings (const QSettings *settings)
{
  // QSettings pointer is checked before emitting.

  update_lexer ();

  //highlight current line color
  QVariant default_var = QColor (240, 240, 240);
  QColor setting_color = settings->value ("editor/highlight_current_line_color",
                                          default_var).value<QColor> ();
  _edit_area->setCaretLineBackgroundColor (setting_color);
  _edit_area->setCaretLineVisible
    (settings->value ("editor/highlightCurrentLine", true).toBool ());

  if (settings->value ("editor/codeCompletion", true).toBool ())  // auto compl.
    {
      bool match_keywords = settings->value
                            ("editor/codeCompletion_keywords",true).toBool ();
      bool match_document = settings->value
                            ("editor/codeCompletion_document",true).toBool ();

      QsciScintilla::AutoCompletionSource source = QsciScintilla::AcsNone;
      if (match_keywords)
        if (match_document)
          source = QsciScintilla::AcsAll;
        else
          source = QsciScintilla::AcsAPIs;
      else if (match_document)
        source = QsciScintilla::AcsDocument;
      _edit_area->setAutoCompletionSource (source);

      _edit_area->setAutoCompletionReplaceWord
        (settings->value ("editor/codeCompletion_replace",false).toBool ());
      _edit_area->setAutoCompletionCaseSensitivity
        (settings->value ("editor/codeCompletion_case",true).toBool ());
      _edit_area->setAutoCompletionThreshold
        (settings->value ("editor/codeCompletion_threshold",2).toInt ());
    }
  else
    _edit_area->setAutoCompletionThreshold (-1);

  if (settings->value ("editor/show_white_space",false).toBool ())
    if (settings->value ("editor/show_white_space_indent",false).toBool ())
      _edit_area->setWhitespaceVisibility (QsciScintilla::WsVisibleAfterIndent);
    else
      _edit_area->setWhitespaceVisibility (QsciScintilla::WsVisible);
  else
    _edit_area->setWhitespaceVisibility (QsciScintilla::WsInvisible);

  if (settings->value ("editor/showLineNumbers", true).toBool ())
    {
      _edit_area->setMarginLineNumbers (2, true);
      auto_margin_width ();
      connect (_edit_area, SIGNAL (linesChanged ()),
               this, SLOT (auto_margin_width ()));
    }
  else
    {
      _edit_area->setMarginLineNumbers (2, false);
      disconnect (_edit_area, SIGNAL (linesChanged ()), 0, 0);
    }

  _edit_area->setAutoIndent
        (settings->value ("editor/auto_indent",true).toBool ());
  _edit_area->setTabIndents
        (settings->value ("editor/tab_indents_line",false).toBool ());
  _edit_area->setBackspaceUnindents
        (settings->value ("editor/backspace_unindents_line",false).toBool ());
  _edit_area->setIndentationGuides
        (settings->value ("editor/show_indent_guides",false).toBool ());

  _edit_area->setTabWidth
        (settings->value ("editor/tab_width",2).toInt ());

  _long_title = settings->value ("editor/longWindowTitle", false).toBool ();
  update_window_title (_edit_area->isModified ());

}

void
file_editor_tab::auto_margin_width ()
{
  _edit_area->setMarginWidth (2, "1"+QString::number (_edit_area->lines ()));
}

void
file_editor_tab::conditional_close (const QWidget *ID, bool app_closing)
{
  if (ID != this)
    return;

  _app_closing = app_closing;
  close ();
}

void
file_editor_tab::change_editor_state (const QWidget *ID)
{
  if (ID != this)
    {
      // Widget may be going out of focus.  If so, record location.
      if (_find_dialog)
        {
          if (_find_dialog->isVisible ())
            {
              _find_dialog_geometry = _find_dialog->geometry ();
              _find_dialog->hide ();
            }
        }
      return;
    }

  if (_find_dialog && _find_dialog_is_visible)
    {
      _find_dialog->setGeometry (_find_dialog_geometry);
      _find_dialog->show ();
    }

  emit editor_state_changed (_copy_available, QDir::cleanPath (_file_name));
}

void
file_editor_tab::file_name_query (const QWidget *ID)
{
  // A zero (null pointer) means that all file editor tabs
  // should respond, otherwise just the desired file editor tab.
  if (ID != this && ID != 0)
    return;

  // Unnamed files shouldn't be transmitted.
  if (!_file_name.isEmpty ())
    emit add_filename_to_list (_file_name, this);
}

void
file_editor_tab::handle_file_reload_answer (int decision)
{
  if (decision == QMessageBox::Yes)
    {
      // reload: file is readded to the file watcher in set_file_name ()
      load_file (_file_name);
    }
  else
    {
      // do not reload: readd to the file watche
      _file_system_watcher.addPath (_file_name);
    }
}

void
file_editor_tab::handle_file_resave_answer (int decision)
{
  // check decision of user in dialog
  if (decision == QMessageBox::Save)
    {
      save_file (_file_name);  // readds file to watcher in set_file_name ()
      _edit_area->setReadOnly (false);  // delete read only flag
    }
  else
    {
      // Definitely close the file.
      // Set modified to false to prevent the dialog box when the close event
      // is posted. If the user cancels the close in this dialog the tab is
      // left open with a non-existing file.
      _edit_area->setModified (false);
      close ();
    }
}

void
file_editor_tab::insert_debugger_pointer (const QWidget *ID, int line)
{
  if (ID != this || ID == 0)
    return;

  if (line > 0)
    {
      _edit_area->markerAdd (line-1, debugger_position);
      center_current_line ();
    }
}

void
file_editor_tab::delete_debugger_pointer (const QWidget *ID, int line)
{
  if (ID != this || ID == 0)
    return;

  if (line > 0)
    _edit_area->markerDelete (line-1, debugger_position);
}

void
file_editor_tab::do_breakpoint_marker (bool insert, const QWidget *ID, int line)
{
  if (ID != this || ID == 0)
    return;

  if (line > 0)
    {
      if (insert)
        _edit_area->markerAdd (line-1, breakpoint);
      else
        _edit_area->markerDelete (line-1, breakpoint);
    }
}


void
file_editor_tab::center_current_line ()
{
  long int visible_lines
    = _edit_area->SendScintilla (QsciScintillaBase::SCI_LINESONSCREEN);

  if (visible_lines > 2)
    {
      int line, index;
      _edit_area->getCursorPosition (&line, &index);

      int first_line = _edit_area->firstVisibleLine ();
      first_line = first_line + (line - first_line - (visible_lines-1)/2);

      _edit_area->SendScintilla (2613,first_line); // SCI_SETFIRSTVISIBLELINE
    }
}

void
file_editor_tab::handle_cursor_moved (int line, int col)
{
  _row_indicator->setNum (line+1);
  _col_indicator->setNum (col+1);
}

#endif