/****************************************************************************
**
** Copyright (C) 2010 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
** Contact: Nokia Corporation (qt-info@nokia.com)
**
** This file is part of the examples of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial Usage
** Licensees holding valid Qt Commercial licenses may use this file in
** accordance with the Qt Commercial License Agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Nokia.
**
** GNU Lesser General Public License Usage
** Alternatively, this file may be used under the terms of the GNU Lesser
** General Public License version 2.1 as published by the Free Software
** Foundation and appearing in the file LICENSE.LGPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU Lesser General Public License version 2.1 requirements
** will be met: http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
** In addition, as a special exception, Nokia gives you certain additional
** rights.  These rights are described in the Nokia Qt LGPL Exception
** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
**
** GNU General Public License Usage
** Alternatively, this file may be used under the terms of the GNU
** General Public License version 3.0 as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL included in the
** packaging of this file.  Please review the following information to
** ensure the GNU General Public License version 3.0 requirements will be
** met: http://www.gnu.org/copyleft/gpl.html.
**
** If you have questions regarding the use of this file, please contact
** Nokia at qt-info@nokia.com.
** $QT_END_LICENSE$
**
****************************************************************************/

#include <QtGui>

#include "codeeditor.h"
#include "shx_helper.h"
#include "window.h"
#include "dsrgui.h"
//#include "chgl.h"

CodeEditor::CodeEditor(QWidget *parent) : QPlainTextEdit(parent), c(0){
  lineNumberArea = new LineNumberArea(this);
  lineNumberArea->setObjectName("lineNumberArea");
  afixHighlightArea = new AfixHighlightArea(this);
  afixHighlightArea->setObjectName("afixHighlightArea");
  setMouseTracking(true);
  midCursorpos=0;
  //setTabChangesFocus(true);
  highlighter = new Highlighter(document());
  connect(this, SIGNAL(blockCountChanged(int)), this, SLOT(updateLineNumberAreaWidth(int)));
  connect(this, SIGNAL(updateRequest(QRect,int)), this, SLOT(updateLineNumberArea(QRect,int)));
//  connect(this, SIGNAL(cursorPositionChanged()), this, SLOT(highlightCurrentLine()));
  connect(this, SIGNAL(textChanged()),this,SLOT(updateAfix()));
//  updateLineNumberAreaWidth(0);
  //highlightCurrentLine();

  updateAfix();

    suchbox =  new QGroupBox("Search and Replace",this);
    searchLE = new QLineEdit(suchbox);
    searchLE->setMinimumSize(QSize(150, 0));
    suchbox->setFlat(true);
    slt=new QGridLayout(suchbox);
    hidesearch = new QToolButton(suchbox);
    hidesearch->setIcon(QIcon(":/icons/cancel.png"));
    hidesearch->setAutoRaise(true);
    prev = new QToolButton(suchbox);
    prev->setIcon(QIcon(":/icons/moveleft.png"));
    prev->setText("Previous");
    prev->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
    prev->setAutoRaise(true);
    next = new QToolButton(suchbox);
    next->setIcon(QIcon(":/icons/moveright.png"));
    next->setText("Next");
    next->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
    next->setAutoRaise(true);
    wholeLine = new QCheckBox("Select whole lines",suchbox);
    wholeLine->setChecked(false);

    slt->setSpacing(5);
    slt->setMargin(0);
    slt->addWidget(hidesearch,0,0);
    slt->addWidget(searchLE,0,1);
    slt->addWidget(prev,0,2);
    slt->addWidget(next,0,3);
    slt->setVerticalSpacing (0);
    slt->addWidget(wholeLine,0,4);
   // slt->setColumnStretch(6,10);
    replace = new QLineEdit(suchbox);
    replace->setMinimumSize(QSize(150, 0));

    replaceButton = new QToolButton(suchbox);
    replaceButton->setIcon(QIcon(":/icons/moveright.png"));
    replaceButton->setText("Replace");
    replaceButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
    replaceButton->setAutoRaise(true);

    replacePButton = new QToolButton(suchbox);
    replacePButton->setIcon(QIcon(":/icons/moveleft.png"));
    replacePButton->setText("Replace");
    replacePButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
    replacePButton->setAutoRaise(true);
    replaceAButton= new QToolButton(suchbox);
    //ediVis=oupVis=false;
    replaceAButton->setIcon(QIcon(":/icons/all.png"));
//

    replaceAButton->setText("Replace All!");
    replaceAButton->setToolButtonStyle(Qt::ToolButtonTextBesideIcon);
    replaceAButton->setAutoRaise(true);
    slt->addWidget(replace,1,1);
    slt->addWidget(replacePButton,1,2);
    slt->addWidget(replaceButton,1,3);
    slt->addWidget(replaceAButton,1,4);
    suchbox->setLayout(slt);
    suchbox->hide();
    connect(searchLE, SIGNAL(textChanged(const QString&)),this,SLOT(findText()));
    connect(searchLE, SIGNAL(textChanged(const QString&)),highlighter,SLOT(highlightSearch(const QString &)));
    connect(next, SIGNAL(clicked() ), this, SLOT(findNext()));
    connect(prev, SIGNAL(clicked() ), this, SLOT(findPrev()));
    connect(searchLE, SIGNAL(returnPressed()), this, SLOT(findNext()));
    connect(replaceButton, SIGNAL(clicked() ), this, SLOT(replaceNext()));
    connect(replacePButton, SIGNAL(clicked() ), this, SLOT(replacePrev()));
    connect(replaceAButton, SIGNAL(clicked() ), this, SLOT(replaceAll()));
    connect(hidesearch, SIGNAL(clicked() ), this, SLOT(hideSearch()));

  //
    resiFinder = new QComboBox();
    resiFinder->setSizeAdjustPolicy(QComboBox::AdjustToContents);
    connect(resiFinder, SIGNAL(activated(QString)), this, SLOT(findResi(QString)));
    connect(resiFinder, SIGNAL(destroyed(QObject*)), this, SLOT(resiFinderDestroyed()));
}

CodeEditor::~CodeEditor(){
  printf("CodeEditor will close%d\n",__LINE__);
  disconnect(this);
  //printf("ce%d\n",__LINE__);
  delete lineNumberArea;
  //printf("ce%d\n",__LINE__);
  delete afixHighlightArea;
  //printf("ce%d\n",__LINE__);
  delete highlighter;
  printf("CodeEditor closed. %d %p\n",__LINE__,chgl);

}

int CodeEditor::lineNumberAreaWidth(){
  int digits = 4;//2;
  //int max = qMax(1, blockCount());
  //while (max >= 10) {
  //  max /= 10;
  //  ++digits;
  //}

  int space = 5 + fontMetrics().width(QLatin1Char('9')) * digits;
  return space;
}

void CodeEditor::updateLineNumberAreaWidth(int /* newBlockCount */){ 
    setViewportMargins(lineNumberAreaWidth()+15, 0, 0, 0);
}

void CodeEditor::updateLineNumberArea(const QRect &rect, int dy){
  Q_UNUSED ( rect );
//  printf("updateLineNumberArea\n");
    if (dy){
        lineNumberArea->scroll(0, dy);
        afixHighlightArea->scroll(0,dy);
    }
   /*
    else{
      printf("Area->update1 %d %d\n",rect.x(),rect.y());
    //lineNumberArea->update(0, rect.y(), lineNumberArea->width(), rect.height());
      printf("Area->update2\n");
    //afixHighlightArea->update(0,rect.y(),10,rect.height());
      printf("Area->update3\n");
}*/
  if (rect.contains(viewport()->rect()))
    updateLineNumberAreaWidth(0);
    //*/
}

void CodeEditor::resizeEvent(QResizeEvent *e){
  QPlainTextEdit::resizeEvent(e);
  QRect cr = contentsRect();
  lineNumberArea->setGeometry(QRect(cr.left(), cr.top(), lineNumberAreaWidth(), cr.height()));
  afixHighlightArea->setGeometry(QRect(
      cr.left()+lineNumberAreaWidth()+1,
      cr.top(),
      10,cr.height()
      ));
  e->accept();
}

void CodeEditor::expandGreaterThan(){//!< some SHELXL re- or constrainst use > to specify a range of atoms this is a problem for sorting atoms
    QTextDocument *document = this->document();
    for (int i=0; i<blocks.size(); i++){
        if (blocks.at(i).startsWith("REM",Qt::CaseInsensitive)) continue;
        if (blocks.at(i).contains('>')){
            int comRN=-1,comPart=9999;
            QString comRL="";
            QString orig=blocks.at(i);
            QStringList tokens=orig.split(QRegExp("\\s+"));
            int da=tokens.indexOf(">");
            QRegExp toReplace=QRegExp(QString("%1\\s+>\\s+%2").arg(tokens.at(da-1)).arg(tokens.at(da+1)));
            QString with="";
            if (tokens.at(0).contains("_")){
                QString spec = tokens.at(0).section('_',1,1);
                if (spec.contains(QRegExp("^[0-9]+$"))) comRN=spec.toInt();
                else if (spec.contains(QRegExp("^[A-Z]"))) comRL=spec;
                else if (spec.contains(QRegExp("^[a-z]$"))) comPart=spec.toInt(0,36)-9;
            }
            bool on=false;
            //printf("%d %d \n",comRN,comPart);
            for (int j=0; j< chgl->mol->asymm.size(); j++){
                if (chgl->mol->asymm.at(j).an<1)continue;
                QString s=chgl->mol->asymm.at(j).Label.section(QString::fromUtf8("_"),0,0);
                if ((comRN>0)&&(chgl->mol->asymm.at(j).resiNr!=comRN))continue;
                if ((comPart!=9999)&&((chgl->mol->asymm.at(j).part!=comPart)||(chgl->mol->asymm.at(j).part!=(25-comPart)))) continue;
                if ((!comRL.isEmpty())&&(chgl->mol->asymm.at(j).ResiClass!=comRL))continue;
                if (s==tokens.at(da-1)) on=true;
                if (on) if (!with.contains(s+" ")){
                    with.append(QString("%1 ").arg(s));
                    if (with.section('=',-1,-1).length()>60) with.append(" = \n ");
                }
                if (s==tokens.at(da+1)) on=false;
            }
            //DSRGui::textWrap(buffer)
            //qDebug()<<orig<<toReplace.pattern()<<with;
            QTextCursor cursor = textCursor();
            cursor.movePosition(QTextCursor::Start);
            cursor = document->find(orig,cursor);
            cursor.movePosition(QTextCursor::StartOfLine,QTextCursor::MoveAnchor);
            cursor =document->find(toReplace);
            cursor.insertText(with);
        }
        if (blocks.at(i).contains('<')){
            int comRN=-1,comPart=9999;
            QString comRL="";
            QString orig=blocks.at(i);
            QStringList tokens=orig.split(QRegExp("\\s+"));
            int da=tokens.indexOf("<");
            QRegExp toReplace=QRegExp(QString("%1\\s+<\\s+%2").arg(tokens.at(da-1)).arg(tokens.at(da+1)));
            QString with="";
            if (tokens.at(0).contains("_")){
                QString spec = tokens.at(0).section('_',1,1);
                if (spec.contains(QRegExp("^[0-9]+$"))) comRN=spec.toInt();
                else if (spec.contains(QRegExp("^[A-Z]"))) comRL=spec;
                else if (spec.contains(QRegExp("^[a-z]$"))) comPart=spec.toInt(0,36)-9;
            }
            bool on=false;
            for (int j=chgl->mol->asymm.size()-1; j>=0; j--){
                if (chgl->mol->asymm.at(j).an<1)continue;
                QString s=chgl->mol->asymm.at(j).Label.section(QString::fromUtf8("_"),0,0);
                if ((comRN>0)&&(chgl->mol->asymm.at(j).resiNr!=comRN))continue;
                if ((comPart!=9999)&&((chgl->mol->asymm.at(j).part!=comPart)||(chgl->mol->asymm.at(j).part!=(25-comPart)))) continue;
                if ((!comRL.isEmpty())&&(chgl->mol->asymm.at(j).ResiClass!=comRL))continue;
                if (s==tokens.at(da-1)) on=true;
                if (on) if (!with.contains(s+" ")) {
                    with.append(QString("%1 ").arg(s));
                    if (with.section('=',-1,-1).length()>60) with.append(" = \n ");
                }
                if (s==tokens.at(da+1)) on=false;
            }
            //DSRGui::textWrap(buffer)
            //qDebug()<<orig<<toReplace.pattern()<<with;
            QTextCursor cursor = textCursor();
            cursor.movePosition(QTextCursor::Start);
            cursor = document->find(orig,cursor);
            cursor.movePosition(QTextCursor::StartOfLine,QTextCursor::MoveAnchor);
            cursor =document->find(toReplace);
            cursor.insertText(with);
        }
    }
}

QString CodeEditor::selectedRestraintsAtoms(QString buffer, QList<MyAtom> selected, QString resiSpec, bool exclude_H){
  //! Assembles the selected atom names to parameters for the specific restraint.
  for (QList<MyAtom>::iterator atom = selected.begin(); atom != selected.end(); atom++) {
    if((atom->an==0) && (exclude_H)) {//Hydrogen have an == 0 !
      // excludes hydrogen atoms
      continue;
    }
    if (atom->an < 0) {//non atoms have an < 0 
      // excludes q-peaks, even if exclude_H is false
      continue;
    }
    // Do not add atoms outside of the asymmetric unit to the restraints:
    if (atom->symmGroup!=0) {
      continue;
    }
    if ((resiSpec.isEmpty()) && (atom->resiNr > 0)) {//I think 'and' is confusing and I prefere &&
      buffer += (atom->Label.section("_", 0, 0) + QString("_%1").arg(atom->resiNr) + " ");
    } else {
      buffer += (atom->Label.section("_", 0, 0) + " ");
    }
  }
  return buffer + "\n";
}

void CodeEditor::updateWght(){
  if (chgl->mol->asymm.isEmpty()) return;
  QTextDocument *document = this->document();
  QTextCursor cursor = textCursor();
  cursor.beginEditBlock ();
  cursor.movePosition(QTextCursor::End);
  cursor = document->find("WGHT",cursor,QTextDocument::FindBackward);
  if (cursor.isNull()) {
    cursor = textCursor();
    cursor.endEditBlock ();
    return;
  } 
  cursor.movePosition(QTextCursor::StartOfLine,QTextCursor::MoveAnchor);
  cursor.movePosition(QTextCursor::EndOfLine,QTextCursor::KeepAnchor);
  QString newWeight= cursor.selectedText();
  cursor.clearSelection();

  cursor.movePosition(QTextCursor::Up);

  cursor = document->find("WGHT",cursor,QTextDocument::FindBackward);

  cursor.movePosition(QTextCursor::StartOfLine);
  cursor.clearSelection();
  cursor.insertText(" ");
  cursor.movePosition(QTextCursor::Down);
  cursor.insertText(newWeight);
  cursor.insertText("\n");

  cursor.endEditBlock ();
  setTextCursor(cursor);
  centerCursor () ;
  cursor.clearSelection ();
  setFocus () ;
  update();
}


void CodeEditor::insertList6(){
  if (!toPlainText().contains(QRegExp("\nLIST",Qt::CaseInsensitive))){
    QTextDocument *document = this->document();
    QTextCursor cursor = textCursor();
    cursor.movePosition(QTextCursor::Start,QTextCursor::MoveAnchor);
    cursor = document->find(QRegExp("^UNIT",Qt::CaseInsensitive),cursor);
    cursor.movePosition(QTextCursor::StartOfLine,QTextCursor::MoveAnchor);
    cursor.movePosition(QTextCursor::Down,QTextCursor::MoveAnchor);
    cursor.insertText("LIST 6 ! automatically inserted. Change 6 to 4 for CHECKCIF!!\n");
    emit saveMe(true,false);
  }
}

void CodeEditor::insertAnis(){
  QTextDocument *document = this->document();
  QTextCursor cursor = textCursor();
  cursor.movePosition(QTextCursor::Start,QTextCursor::MoveAnchor);
  cursor = document->find(QRegExp("^UNIT",Qt::CaseInsensitive),cursor);
  cursor.movePosition(QTextCursor::StartOfLine,QTextCursor::MoveAnchor);
  cursor.movePosition(QTextCursor::Down,QTextCursor::MoveAnchor);
  cursor.insertText("ANIS ! automatically inserted\n");
}

void CodeEditor::insertActa(){
  QTextDocument *document = this->document();
  QTextCursor cc,cursor = textCursor();
  cursor.movePosition(QTextCursor::Start,QTextCursor::MoveAnchor);

  cc = document->find(QRegExp("^ACTA",Qt::CaseInsensitive),cursor);
  if (cc.isNull()) {
    cursor = textCursor();
    cursor.movePosition(QTextCursor::Start,QTextCursor::MoveAnchor);
  }else return;
  cursor = document->find(QRegExp("^UNIT",Qt::CaseInsensitive),cursor);
  cursor.movePosition(QTextCursor::StartOfLine,QTextCursor::MoveAnchor);
  cursor.movePosition(QTextCursor::Down,QTextCursor::MoveAnchor);
  cursor.insertText("ACTA \n");
}

void CodeEditor::dispFromWave(){
  if (chgl->mol->asymm.isEmpty()) return;
  QFile kis(":kisselwave");
  kis.open(QIODevice::ReadOnly|QIODevice::Text);
  QByteArray ba=kis.readAll();
  QStringList all= QString(ba).split('\n');
  kis.close();
  QTextDocument *document = this->document();
  QTextCursor cursor = textCursor();
  cursor.beginEditBlock();
  replace->setText("REM DISP ");
  searchLE->setText("^DISP ");
  replaceAll();
  replace->setText("");
  searchLE->setText("");
  cursor.movePosition(QTextCursor::Start,QTextCursor::MoveAnchor);
  cursor = document->find("UNIT",cursor);
  cursor.movePosition(QTextCursor::StartOfLine,QTextCursor::MoveAnchor);
  QStringList nn,an;
  QString disp;
  for (int i=0; i<sfac.size();i++){
    double aw=0,w;
    w=aw;

    int x=all.indexOf(QString("#S %1 %2").arg(sfac.at(i)+1,2,10,QChar('0')).arg(chgl->mol->pse(sfac.at(i))));
    for (int j=x+1; j<4000+x; j++){
      an=nn;
      nn=all.at(j).split(" ",QString::SkipEmptyParts);
      aw=w;
      w=nn.at(0).toDouble();
      if ((w!=aw)&&(chgl->mol->cell.wave>w)) {
        double f= (chgl->mol->cell.wave-aw)/(w-aw); 
        //	printf("DISP $%s %f %f\n",chgl->mol->pse(sfac.at(i)).toStdString().c_str(),f*nn.at(1).toDouble()+(1-f)*an.at(1).toDouble(),f*nn.at(2).toDouble()+(1-f)*an.at(2).toDouble());
        disp=QString("DISP $%1 %2 %3 %4!source kissel\n")//REM %5\nREM %6\n")
          .arg(chgl->mol->pse(sfac.at(i)))
          .arg(f*nn.at(1).toDouble()+(1-f)*an.at(1).toDouble(),8,'f',5)
          .arg(f*nn.at(2).toDouble()+(1-f)*an.at(2).toDouble(),8,'f',5)
          .arg(f*nn.at(3).toDouble()+(1-f)*an.at(3).toDouble(),8,'f',5)
          ;
        cursor.insertText(disp);
        j=5000+x;
      }
    }

  }

  cursor.endEditBlock();
}

void CodeEditor::updateUnit(){
  if (chgl->mol->asymm.isEmpty()) return;
  QTextDocument *document = this->document();
  QTextCursor cursor = textCursor();
  cursor.beginEditBlock ();
  cursor.movePosition(QTextCursor::Start);
  cursor = document->find(unitAlt,cursor);
  if (cursor.isNull()) {
    cursor = textCursor();
    cursor.endEditBlock ();
    printf("can't find unit\n");
    update();
    return;
  }
  cursor.movePosition(QTextCursor::StartOfLine,QTextCursor::MoveAnchor);
  cursor.movePosition(QTextCursor::EndOfLine,QTextCursor::KeepAnchor);
  cursor.deleteChar();
  cursor.insertText(unitNeu);
  cursor.endEditBlock ();
  setTextCursor(cursor);
  centerCursor () ;
  cursor.clearSelection ();
  setTextCursor(cursor);
  setFocus () ;
  update();
}

void CodeEditor::weedEmptySfacs(){
  if (chgl->mol->asymm.isEmpty()) return;
  emit saveMe(true,true);
  if (1){//(maybeSave()){
    QMap<int,double> unit;
    for (int i=0; i<chgl->mol->asymm.size(); i++){
      if (chgl->mol->asymm.at(i).an>=0) unit[chgl->mol->asymm.at(i).an]+= chgl->mol->asymm.at(i).sof * chgl->mol->cell.symmops.size();
    }
    unitNeu="UNIT";
    for (int i = 0; i < sfac.size() ; i++){
      if (unit.value(sfac.at(i))) {
        if (unit.value(sfac.at(i))>9999)
          unitNeu.append(QString(" %1").arg((int)unit.value(sfac.at(i)))); else
            unitNeu.append(QString(" %1").arg(unit.value(sfac.at(i)),0,'g'));
      }
      if (unitNeu.split('\n').last().size()>76) unitNeu.append("=\n    ");
    }
    updateUnit();
    QTextDocument *document = this->document();
    QTextCursor cursor = textCursor();
    QTextCursor c=cursor;
    cursor.movePosition(QTextCursor::Start);
    int apos=0,pos=0;
    QList<int> mussweg,newSfac=sfac;
    for (int i = 0; i < sfac.size() ; i++){
      if (unit.value(sfac.at(i))==0) {
        mussweg.append(i);
        newSfac.removeOne(sfac.at(i));
      }
    }
    if (mussweg.isEmpty()) return;
    cursor = document->find(QRegExp("^SFAC"),cursor);
    if (cursor.isNull()){setTextCursor(c);return;}
    cursor.movePosition(QTextCursor::Start);
    while ((!cursor.isNull())&&(pos<sfac.size())){
      cursor = document->find(QRegExp("^SFAC"),cursor);
      cursor.movePosition(QTextCursor::EndOfLine,QTextCursor::KeepAnchor);
      if (cursor.selectedText().contains(QRegExp("[.0-9]+"))){
        bool hatgleich=cursor.selectedText().contains(QRegExp("=\\s*$"));
        cursor.clearSelection();
        cursor.movePosition(QTextCursor::StartOfLine,QTextCursor::MoveAnchor);
        if (mussweg.contains(pos)) {
          cursor.insertText("REM ");
          if (hatgleich) {
            cursor.movePosition(QTextCursor::Down,QTextCursor::MoveAnchor);
            cursor.movePosition(QTextCursor::StartOfLine,QTextCursor::MoveAnchor);
            cursor.insertText("REM ");
          }
        }else if (hatgleich) cursor.movePosition(QTextCursor::Down,QTextCursor::MoveAnchor);
        pos++;
      }
      else {
        pos+=cursor.selectedText().split(" ",QString::SkipEmptyParts).size()-1;
        cursor.deleteChar();
        QString ac;
        for (int i =apos; i<newSfac.size() && i<pos+apos;i++) ac.append(QString("%1 ").arg(chgl->mol->pse(newSfac.at(i))));
        apos=pos;
        cursor.insertText(QString("SFAC %1\n").arg(ac));
      }
    }
    for (int i=0; i<chgl->mol->asymm.size();i++){
      if ((sfac.indexOf(chgl->mol->asymm.at(i).an)>-1)&&
          (newSfac.indexOf(chgl->mol->asymm.at(i).an)>-1)&&
          (sfac.indexOf(chgl->mol->asymm.at(i).an)!=newSfac.indexOf(chgl->mol->asymm.at(i).an))){
        jumpToAtom(i);
        cursor = textCursor();
        cursor.movePosition(QTextCursor::EndOfLine,QTextCursor::KeepAnchor);
        QString repla=cursor.selectedText();
        cursor.deleteChar();
        repla.replace(QString(" %1 ").arg(1+sfac.indexOf(chgl->mol->asymm.at(i).an)), QString(" %1 ").arg(1+newSfac.indexOf(chgl->mol->asymm.at(i).an)));
        cursor.insertText(repla);
        chgl->mol->asymm[i].orginalLine=repla;
      }
    }    
    emit saveMe(true,true);
    document = this->document();
    if(document->toPlainText().contains("DISP"))
      dispFromWave(); 
  }
}

void CodeEditor::jumpToAtom(int index){
  QString label = chgl->mol->showatoms.at(index).orginalLine.left(80).trimmed();
  //  qDebug()<<index<<chgl->mol->showatoms.at(index).Label<<label;
  QTextDocument *document = this->document();
  QTextCursor cursor = textCursor();
  cursor.movePosition(QTextCursor::Start);
  cursor = document->find(label,cursor);
  if (cursor.isNull()){
    cursor = textCursor();    
    cursor.movePosition(QTextCursor::Start);
    label.chop(10);
    cursor = document->find(label,cursor);
    if (cursor.isNull()) cursor = textCursor();
    cursor.movePosition(QTextCursor::Start);
    label = chgl->mol->showatoms.at(index).orginalLine.left(80).simplified();
    cursor = document->find(label,cursor);
    if (cursor.isNull()) cursor = textCursor();
  }
  cursor.movePosition(QTextCursor::StartOfLine);
  setTextCursor(cursor);
  centerCursor();
  cursor.clearSelection();
  setTextCursor(cursor);
  setFocus();
}

void CodeEditor::insertANIS(QList<MyAtom> selected){
  QTextDocument *document = this->document();
  QTextCursor cursor = textCursor();
  cursor.movePosition(QTextCursor::Start,QTextCursor::MoveAnchor);
  cursor = document->find(QRegExp("^UNIT",Qt::CaseInsensitive),cursor);
  cursor.movePosition(QTextCursor::StartOfLine,QTextCursor::MoveAnchor);
  cursor.movePosition(QTextCursor::Down,QTextCursor::MoveAnchor);
  QString buffer("ANIS ");
  buffer = selectedRestraintsAtoms(buffer, selected, "", true);
  cursor.insertText(DSRGui::textWrap(buffer));
}

void CodeEditor::insertDFIX(double value, double esd, QList<MyAtom> selected, QString resiSpec){

  QTextDocument *document = this->document();
  QTextCursor cursor = textCursor();
  cursor.movePosition(QTextCursor::Start,QTextCursor::MoveAnchor);
  cursor = document->find(QRegExp("^UNIT",Qt::CaseInsensitive),cursor);
  cursor.movePosition(QTextCursor::StartOfLine,QTextCursor::MoveAnchor);
  cursor.movePosition(QTextCursor::Down,QTextCursor::MoveAnchor);
  QString buffer = QString("DFIX%1 %2 %3 ").arg((resiSpec.isEmpty())?"":"_"+resiSpec).arg(value).arg(esd);
  buffer = selectedRestraintsAtoms(buffer, selected, resiSpec);
  cursor.insertText(DSRGui::textWrap(buffer));
}

void CodeEditor::insertDANG(double value, double esd, QList<MyAtom> selected, QString resiSpec){

  QTextDocument *document = this->document();
  QTextCursor cursor = textCursor();
  cursor.movePosition(QTextCursor::Start,QTextCursor::MoveAnchor);
  cursor = document->find(QRegExp("^UNIT",Qt::CaseInsensitive),cursor);
  cursor.movePosition(QTextCursor::StartOfLine,QTextCursor::MoveAnchor);
  cursor.movePosition(QTextCursor::Down,QTextCursor::MoveAnchor);
  QString buffer =QString("DANG%1 %2 %3 ").arg((resiSpec.isEmpty())?"":"_"+resiSpec).arg(value).arg(esd);
  buffer = selectedRestraintsAtoms(buffer, selected, resiSpec);
  cursor.insertText(DSRGui::textWrap(buffer));
}

void CodeEditor::insertFLAT(double esd, QList<MyAtom> selected, QString resiSpec){
  QTextDocument *document = this->document();
  QTextCursor cursor = textCursor();
  cursor.movePosition(QTextCursor::Start,QTextCursor::MoveAnchor);
  cursor = document->find(QRegExp("^UNIT",Qt::CaseInsensitive),cursor);
  cursor.movePosition(QTextCursor::StartOfLine,QTextCursor::MoveAnchor);
  cursor.movePosition(QTextCursor::Down,QTextCursor::MoveAnchor);
  QString buffer =QString("FLAT%1 %2 ").arg((resiSpec.isEmpty())?"":"_"+resiSpec).arg(esd);
  buffer = selectedRestraintsAtoms(buffer, selected, resiSpec);
  cursor.insertText(DSRGui::textWrap(buffer));
}

void CodeEditor::insertEXYZ(QList<MyAtom> selected, QString resiSpec){
  QTextDocument *document = this->document();
  QTextCursor cursor = textCursor();
  cursor.movePosition(QTextCursor::Start,QTextCursor::MoveAnchor);
  cursor = document->find(QRegExp("^UNIT",Qt::CaseInsensitive),cursor);
  cursor.movePosition(QTextCursor::StartOfLine,QTextCursor::MoveAnchor);
  cursor.movePosition(QTextCursor::Down,QTextCursor::MoveAnchor);
  QString buffer =QString("EXYZ%1 ").arg((resiSpec.isEmpty())?"":"_"+resiSpec);
  buffer = selectedRestraintsAtoms(buffer, selected, resiSpec);
  cursor.insertText(DSRGui::textWrap(buffer));
}

void CodeEditor::jumpToError(){
  QTextCursor c = textCursor();
  if (!errorInLine.isEmpty()){
    c.movePosition(QTextCursor::Start,QTextCursor::MoveAnchor);
    c.movePosition(QTextCursor::Down,QTextCursor::MoveAnchor,errorInLine.first());
    setTextCursor(c);
    ensureCursorVisible ();
  }
}

void CodeEditor::findResi(QString index){
  if (!index.isEmpty()) {
    QTextCursor c=this->document()->find(index);
    if (!c.isNull()) {
      c.movePosition(QTextCursor::StartOfLine);
      setTextCursor(c);
      centerCursor();
      c.clearSelection ();
      //QTextBlock b =c.block();
      QStringList tt=index.split(QRegExp("\\s+"),QString::SkipEmptyParts);

      int nr=0;
      if ((tt.size()>1)&&(tt.at(1).indexOf(QRegExp("^[0-9]+"))!=-1))
        nr=tt.at(1).toInt();
      else if (tt.size()>2) nr=tt.at(2).toInt();
      //QString tt = index.section(QRegExp("\\s+"),1,1).toInt();
      chgl->selectResiByNr(nr);
      setTextCursor(c);
      setFocus () ;
    }
  }
}

void CodeEditor::increaseEdtiorFont(){
  QFont f =font();
  f.setPointSize(qMin(f.pointSize()+1,24));
  setFont(f);
  update();
}

void CodeEditor::decreaseEdtiorFont(){
  QFont f =font();
  f.setPointSize(qMax(f.pointSize()-1,6));
  setFont(f);
  update();
}

void CodeEditor::hideSearch(){
  searchLE->clear();
  suchbox->hide();
}

void CodeEditor::showSearch(){
  suchbox->show();
  if (isReadOnly()){
    replace->hide(); 
    replaceButton->hide(); 
    replacePButton->hide(); 
    replaceAButton->hide(); 
  }else{
    replace->show(); 
    replaceButton->show(); 
    replacePButton->show(); 
    replaceAButton->show(); 
  }
  suchbox->setTitle(QString("Search and Replace:")); 
  searchLE->setFocus();
}

void CodeEditor::findNext(){
  suchbox->show();
  if (isReadOnly()){
    replace->hide(); 
    replaceButton->hide(); 
    replacePButton->hide(); 
    replaceAButton->hide(); 
  }else{
    replace->show(); 
    replaceButton->show(); 
    replacePButton->show(); 
    replaceAButton->show(); 
  }
  suchbox->setTitle(QString("Search and Replace:")); 
  searchchanged(false,false);
}

void CodeEditor::findPrev(){
  suchbox->show();
  if (isReadOnly()){
    replace->hide(); 
    replaceButton->hide(); 
    replacePButton->hide(); 
    replaceAButton->hide(); 
  }else{
    replace->show(); 
    replaceButton->show(); 
    replacePButton->show(); 
    replaceAButton->show(); 
  }
  suchbox->setTitle(QString("Search and Replace:")); 
  searchchanged(false,true);
}

void CodeEditor::findText(){
  searchchanged(true,false);
}

void CodeEditor::searchchanged(bool current,bool back){
  QRegExp searchString = QRegExp(searchLE->text(),Qt::CaseInsensitive);
  QPalette p = searchLE->palette();
  p.setBrush(QPalette::Active,QPalette::Base,Qt::white);
  QTextDocument *document;
  QTextCursor cursor;

  document = this->document();
  cursor = textCursor();

  if (!searchString.isEmpty()){
    if (cursor.hasSelection())
      cursor.setPosition((current|back)?cursor.anchor():cursor.position(), QTextCursor::MoveAnchor);
    QTextDocument::FindFlags options;
    if (back) options|=QTextDocument::FindBackward;
    cursor=document->find(searchString,cursor,options);
    if (cursor.isNull()){
      QTextCursor ac(document);
      ac.movePosition(options & QTextDocument::FindBackward
          ? QTextCursor::End : QTextCursor::Start);
      cursor = document->find(searchString, ac,options);
      if (cursor.isNull()){
        p.setBrush(QPalette::Active,QPalette::Base,QColor(205,100,100));
        cursor = textCursor();
        cursor.movePosition(QTextCursor::Start);
      }
    }
    if ((!cursor.isNull())&&(wholeLine->isChecked())){
      cursor.movePosition(QTextCursor::StartOfLine,QTextCursor::MoveAnchor);
      cursor.movePosition(QTextCursor::EndOfLine,QTextCursor::KeepAnchor);
    }
  }
  else cursor.movePosition(QTextCursor::Start);

  setTextCursor(cursor);
  searchLE->setPalette(p);
}

void CodeEditor::replaceNext(){
  suchbox->setTitle(QString("Search and Replace:")); 
  QRegExp searchString = QRegExp(searchLE->text(),Qt::CaseInsensitive);
  QPalette p = searchLE->palette();
  p.setBrush(QPalette::Active,QPalette::Base,Qt::white);
  QTextDocument *document;
  QTextCursor cursor;

  document = this->document();
  cursor = textCursor();

  if (!searchString.isEmpty()){
    if (cursor.hasSelection()){
      cursor.beginEditBlock();
      if (wholeLine->isChecked()){
        cursor.movePosition(QTextCursor::StartOfLine,QTextCursor::MoveAnchor);
        cursor.movePosition(QTextCursor::EndOfLine,QTextCursor::KeepAnchor);
      }
      cursor.deleteChar();
      if (replace->text().isEmpty())cursor.deleteChar();
      else cursor.insertText(replace->text());
      cursor.endEditBlock();
      cursor.setPosition(cursor.position(), QTextCursor::MoveAnchor);
    }
    cursor=document->find(searchString,cursor);
    if (cursor.isNull()){
      QTextCursor ac(document);
      ac.movePosition(QTextCursor::Start);
      cursor = document->find(searchString, ac);
      if (cursor.isNull()){
        p.setBrush(QPalette::Active,QPalette::Base,QColor(205,100,100));
      }
    }
    if ((!cursor.isNull())&&(wholeLine->isChecked())){
      cursor.movePosition(QTextCursor::StartOfLine,QTextCursor::MoveAnchor);
      cursor.movePosition(QTextCursor::EndOfLine,QTextCursor::KeepAnchor);
    }
  }
  else cursor.movePosition(QTextCursor::Start);
  setTextCursor(cursor);
  searchLE->setPalette(p);
  centerCursor();
  return;
}

void CodeEditor::replaceAll(){
  suchbox->setTitle(QString("Search and Replace:")); 
  QRegExp searchString = QRegExp(searchLE->text(),Qt::CaseInsensitive);
  QPalette p = searchLE->palette();
  p.setBrush(QPalette::Active,QPalette::Base,Qt::white);
  QTextDocument *document;
  QTextCursor cursor;

  document = this->document();
  cursor = textCursor();
  int occurrence=0;
  cursor.beginEditBlock();
  cursor.movePosition(QTextCursor::Start);
  if (!searchString.isEmpty()){
    do {
      cursor=document->find(searchString,cursor);
      if (cursor.hasSelection()){
        cursor.beginEditBlock();
        if (wholeLine->isChecked()){
          cursor.movePosition(QTextCursor::StartOfLine,QTextCursor::MoveAnchor);
          cursor.movePosition(QTextCursor::EndOfLine,QTextCursor::KeepAnchor);
        }
        cursor.deleteChar();
        if (replace->text().isEmpty())cursor.deleteChar();
        else cursor.insertText(replace->text());
        cursor.endEditBlock();
        cursor.setPosition(cursor.position(), QTextCursor::MoveAnchor);
        occurrence++;
      }
    }
    while (!cursor.isNull());
  }

  cursor = textCursor();
  cursor.endEditBlock();
  setTextCursor(cursor);
  searchLE->setPalette(p);
  centerCursor();
  if (occurrence){
    suchbox->setTitle(QString("Search and Replace: Replaced %1 occurrencies of '%2' by '%3'.").arg(occurrence).arg(searchString.pattern()).arg(replace->text()));
  }  
  return;
}

void CodeEditor::replacePrev(){
  suchbox->setTitle(QString("Search and Replace:")); 
  QRegExp searchString = QRegExp(searchLE->text(),Qt::CaseInsensitive);

  QPalette p = searchLE->palette();
  p.setBrush(QPalette::Active,QPalette::Base,Qt::white);
  QTextDocument *document;
  QTextCursor cursor;

  document = this->document();
  cursor = textCursor();

  if (!searchString.isEmpty()){
    if (cursor.hasSelection()){
      cursor.beginEditBlock();
      if (wholeLine->isChecked()){
        cursor.movePosition(QTextCursor::StartOfLine,QTextCursor::MoveAnchor);
        cursor.movePosition(QTextCursor::EndOfLine,QTextCursor::KeepAnchor);
      }
      cursor.deleteChar();
      if (replace->text().isEmpty())cursor.deleteChar();
      else cursor.insertText(replace->text());
      cursor.endEditBlock();
      cursor.setPosition(cursor.anchor(), QTextCursor::MoveAnchor);
    }
    cursor=document->find(searchString,cursor,QTextDocument::FindBackward);
    if (cursor.isNull()){
      QTextCursor ac(document);
      ac.movePosition(QTextCursor::End);
      cursor = document->find(searchString, ac,QTextDocument::FindBackward);
      if (cursor.isNull()){
        p.setBrush(QPalette::Active,QPalette::Base,QColor(205,100,100));
      }
    }
  }
  else cursor.movePosition(QTextCursor::Start);
  setTextCursor(cursor);
  searchLE->setPalette(p);
  centerCursor();
  searchchanged(false,true);
  return;
}

void CodeEditor::resiFinderDestroyed(){
  resiFinder = NULL;
}

void CodeEditor::changeSortierWeise(QAction* action){
  int index = action->data().toInt();
  sortierWeise = index;
  chgl->mol->einstellung->beginGroup("Sorting");
  chgl->mol->einstellung->setValue("SortingOption",sortierWeise);
  chgl->mol->einstellung->endGroup();
}

QString CodeEditor::sortLabelList(CEnvironment &asymm, MyAtom &tatze){
    if (asymm.isEmpty()) return "HKLF";
    QMap<long double,MyAtom> atomSortMap;
    long double lodo=0.0l;
    int amax = asymm.size();

    int t1=0,t2=0;
    for (int i=0; i < asymm.size(); i++){
      if (asymm.at(i).an<0) continue;
      t1++;
      QString s1 = asymm.at(i).Label.section('_',0,0);
      s1.remove(0,chgl->mol->pse(asymm.at(i).an).size());
      int n1 = s1.section(QRegExp("\\D"),0,0).toInt();
      int r1 = 0 ;
      char cc[10];
      strncpy(cc,s1.section(QRegExp("\\d+"),1,-1).toStdString().c_str(),4);
      for (size_t k=0; k<strlen(cc);k++) {r1*=256;r1+=(size_t)cc[k];}
      switch (sortierWeise){
        case 1:
          lodo=asymm.at(i).resiNr*99*amax+
                  asymm.at(i).part*amax+
                  n1+
                  ((110-asymm.at(i).an)/220.0l)+
                  (r1 / 50000.0l);//46656
          atomSortMap.insertMulti(lodo,asymm.at(i));
          break;
        case 2:
          lodo=asymm.at(i).resiNr*99*amax+
                  asymm.at(i).part*amax+
                  n1/999.0l+
                  ((110-asymm.at(i).an))+
                  (r1 / 50000.0l);//46656

          atomSortMap.insertMulti(lodo,asymm.at(i));
          //printf("##= %Lf %d %d %d %d %d\n",lodo,asymm.at(i).resiNr,asymm.at(i).part,n1,(110-asymm.at(i).an),r1);
          break;
        case 3:
          lodo=  asymm.at(i).resiNr*99*amax+
                  asymm.at(i).part*amax+
                  n1/999.0l+
                  sfac.indexOf(asymm.at(i).an)*10+
                  (r1 / 50000.0l);//46656
          atomSortMap.insertMulti(lodo,asymm.at(i));
          break;
        case 4:
          lodo=
          asymm.at(i).resiNr*99*amax+
          asymm.at(i).part*amax+
          n1/50000.0l+
          ((110-asymm.at(i).an)/220)+
          (r1 );//46656
          atomSortMap.insertMulti(lodo,asymm.at(i));
          t2++;
          break;
        case 5:
          lodo=
          asymm.at(i).molindex*9999*amax+
          asymm.at(i).resiNr*99*amax+
          asymm.at(i).part*amax+
          n1/999.0l+
          ((110-asymm.at(i).an))+
          (r1 / 50000.0l);//46656
          atomSortMap.insertMulti(lodo,asymm.at(i));
          /*printf("%s %g\n", asymm.at(i).Label.toStdString().c_str(),asymm.at(i).molindex*9999*amax+
              asymm.at(i).resiNr*99*amax+
              asymm.at(i).part*amax+
              n1/999.0+
              ((110-asymm.at(i).an))+
              (r1 / 50000.0));*/
          break;
        case 6:
            lodo=  asymm.at(i).resiNr*99*amax+
                    asymm.at(i).part*amax+
                    chgl->mol->ueq(asymm.at(i).uf);

        atomSortMap.insertMulti(lodo,asymm.at(i));
        break;
        default:
          atomSortMap.insert(i, asymm.at(i));
          break;
      }
    }
    {
        QString s1 = tatze.Label.section('_',0,0);
        s1.remove(0,chgl->mol->pse(tatze.an).size());
        int n1 = s1.section(QRegExp("\\D"),0,0).toInt();
        int r1 = 0 ;
        char cc[10];
        strncpy(cc,s1.section(QRegExp("\\d+"),1,-1).toStdString().c_str(),4);
        for (size_t k=0; k<strlen(cc);k++) {r1*=256;r1+=(size_t)cc[k];}
        //printf("VV= %Lf %d %d %d %d %d\n",lodo,tatze.resiNr,tatze.part,n1,(110-tatze.an),r1);
    switch (sortierWeise){
      case 1:
        lodo=tatze.resiNr*99*amax+
                tatze.part*amax+
                n1+
                ((110-tatze.an)/220.0l)+
                (r1 / 50000.0l);//46656
        break;
      case 2:
        lodo=tatze.resiNr*99*amax+
                tatze.part*amax+
                n1/999.0l+
                ((110-tatze.an))+
                (r1 / 50000.0l);//46656
        break;
      case 3:
        lodo=  tatze.resiNr*99*amax+
                tatze.part*amax+
                n1/999.0l+
                sfac.indexOf(tatze.an)*10+
                (r1 / 50000.0l);//46656
        break;
      case 4:
        lodo=
        tatze.resiNr*99*amax+
        tatze.part*amax+
        n1/50000.0l+
        ((110-tatze.an)/220)+
        (r1 );//46656
        break;
      case 5:
        lodo=
        tatze.molindex*9999*amax+
        tatze.resiNr*99*amax+
        tatze.part*amax+
        n1/999.0l+
        ((110-tatze.an))+
        (r1 / 50000.0l);//46656
        break;
    case 6:
        lodo=  tatze.resiNr*99*amax+
               tatze.part*amax+
               chgl->mol->ueq(tatze.uf);
        break;
    }
    }
    QList<long double> kys = atomSortMap.keys();
    long double fi = kys.first();//, la = kys.last();
    QString l="HKLF";
    //printf("value = %Lf first = %Lf last = %Lf\n", lodo, fi, la);
    if ((lodo>=fi)) {//
        CEnvironment asymm2    =  atomSortMap.values();
        int idx=0;
        for (; (idx<kys.size())&& (lodo>kys.at(idx)); idx++){}
        if (idx>0) idx--;
      //  printf("idx %d\n",idx);
        l = asymm2.at(idx).orginalLine.left(80).trimmed();
        asymm2.clear();
    }else{
        QTextDocument *doc = this->document();
        QTextCursor cursor = textCursor();
        cursor.movePosition(QTextCursor::Start);
        l=asymm.first().orginalLine.left(80).trimmed();
        cursor=doc->find(l, cursor);
        cursor.movePosition(QTextCursor::StartOfLine,QTextCursor::MoveAnchor);
        cursor.movePosition(QTextCursor::Up,QTextCursor::MoveAnchor);
        cursor.movePosition(QTextCursor::EndOfLine,QTextCursor::KeepAnchor);
        l=cursor.selectedText();
        cursor.clearSelection();
        cursor.movePosition(QTextCursor::StartOfLine,QTextCursor::MoveAnchor);
    }
    kys.clear();
    atomSortMap.clear();
    return l;
}

void CodeEditor::sortAtoms(){
  if (chgl->mol->asymm.isEmpty()) return;

  const QString sicher = toPlainText();
  //find atomranges
  if (sicher.contains(QRegExp("[<>]"))){
    //QStringList ranges;
    /*QStringList lines = sicher.split('\n');
    for (int i=0; (i<lines.size()); i++){
      if (lines.at(i).startsWith(' ')) continue;
      if (lines.at(i).startsWith("REM",Qt::CaseInsensitive)) continue;
      if (lines.at(i).startsWith("HKLF",Qt::CaseInsensitive)) break;
      if (lines.at(i).contains(QRegExp("[<>]"))) ranges.append(QString("LINE %1: %2")
          .arg(i+1)
          .arg(lines.at(i)));
    }*/
    expandGreaterThan();
    /*if (!ranges.isEmpty()){
      QMessageBox::information(0,"information",QString("<h3>Atom ranges detected! %1 "
            " can not sort here without destroying functionality of the file.</h3 <pre>%2 </pre>").arg(PROGRAM_NAME).arg(ranges.join("\n")));
      return;
    }*/
  }
  QMap<long double,MyAtom> atomSortMap;

  int amax = chgl->mol->asymm.size();
  int t1=0,t2=0;
  for (int i=0; i < chgl->mol->asymm.size(); i++){
    if (chgl->mol->asymm.at(i).an<0) continue;
    t1++;
    QString s1 = chgl->mol->asymm.at(i).Label;
    s1.remove(0,chgl->mol->pse(chgl->mol->asymm.at(i).an).size());
    int n1 = s1.section(QRegExp("\\D"),0,0).toInt();
    int r1 = 0 ;
    char cc[10];
    strncpy(cc,s1.section(QRegExp("\\d+"),1,-1).toStdString().c_str(),4);
    for (size_t k=0; k<strlen(cc);k++) {r1*=256;r1+=(size_t)cc[k];}
    switch (sortierWeise){
      case 1:
        atomSortMap.insertMulti(
            chgl->mol->asymm.at(i).resiNr*99*amax+
            chgl->mol->asymm.at(i).part*amax+
            n1+
            ((110-chgl->mol->asymm.at(i).an)/220.0)+
            (r1 / 50000.0)//46656
            ,chgl->mol->asymm.at(i));
        break;
      case 2:
        atomSortMap.insertMulti(
            chgl->mol->asymm.at(i).resiNr*99*amax+
            chgl->mol->asymm.at(i).part*amax+
            n1/999.0+
            ((110-chgl->mol->asymm.at(i).an))+
            (r1 / 50000.0)//46656
            ,chgl->mol->asymm.at(i));
        break;
      case 3:
        atomSortMap.insertMulti(
            chgl->mol->asymm.at(i).resiNr*99*amax+
            chgl->mol->asymm.at(i).part*amax+
            n1/999.0+
            sfac.indexOf(chgl->mol->asymm.at(i).an)*10+
            (r1 / 50000.0)//46656
            ,chgl->mol->asymm.at(i));
        break;
      case 4:
        atomSortMap.insertMulti(
            chgl->mol->asymm.at(i).resiNr*99*amax+
            chgl->mol->asymm.at(i).part*amax+
            n1/50000.0+
            ((110-chgl->mol->asymm.at(i).an)/220)+
            (r1 )//46656
            ,chgl->mol->asymm.at(i));
        t2++;
        break;
      case 5:
        atomSortMap.insertMulti(
            chgl->mol->asymm.at(i).molindex*9999*amax+
            chgl->mol->asymm.at(i).resiNr*99*amax+
            chgl->mol->asymm.at(i).part*amax+
            n1/999.0+
            ((110-chgl->mol->asymm.at(i).an))+
            (r1 / 50000.0)//46656
            ,chgl->mol->asymm.at(i));
        printf("%s %g\n", chgl->mol->asymm.at(i).Label.toStdString().c_str(),chgl->mol->asymm.at(i).molindex*9999*amax+
            chgl->mol->asymm.at(i).resiNr*99*amax+
            chgl->mol->asymm.at(i).part*amax+
            n1/999.0+
            ((110-chgl->mol->asymm.at(i).an))+
            (r1 / 50000.0));
        break;

    case 6:{
        long double lodo=0.0l;
        lodo=  chgl->mol->asymm.at(i).resiNr*99*amax+
                chgl->mol->asymm.at(i).part*amax+
                chgl->mol->ueq(chgl->mol->asymm.at(i).uf);
        atomSortMap.insertMulti(lodo,chgl->mol->asymm.at(i));
    }
    break;
      default:
        atomSortMap.insert(i
            ,chgl->mol->asymm.at(i));
        break;
    }
  }
  CEnvironment asymm2=
    atomSortMap.values();

  QTextDocument *document = this->document();
  QTextCursor cursor = textCursor();
  wholeLine->setChecked(false);
  replace->setText("");
  searchLE->setText("^part.*$");
  replaceAll();
  replace->setText("");
  searchLE->setText("^resi.*$");
  replaceAll();
  cursor.beginEditBlock();
  cursor.movePosition(QTextCursor::Start);
  cursor = document->find("HKLF",cursor);
  cursor.movePosition(QTextCursor::StartOfLine,QTextCursor::MoveAnchor);
  cursor.movePosition(QTextCursor::Up,QTextCursor::KeepAnchor);
  if (parenthesis.at(cursor.blockNumber())){
    cursor.select(QTextCursor::WordUnderCursor);
    if ((cursor.selectedText().contains("RESI",Qt::CaseInsensitive))||(cursor.selectedText().contains("PART",Qt::CaseInsensitive)))
      cursor.movePosition(QTextCursor::Up,QTextCursor::KeepAnchor);
    cursor.select(QTextCursor::WordUnderCursor);
    if ((cursor.selectedText().contains("RESI",Qt::CaseInsensitive))||(cursor.selectedText().contains("PART",Qt::CaseInsensitive)))
      cursor.movePosition(QTextCursor::Up,QTextCursor::KeepAnchor);
    cursor.movePosition(QTextCursor::Down,QTextCursor::MoveAnchor);
    cursor.clearSelection();
    cursor.insertText("AFIX 0 \n");
  }

  QProgressDialog progress("Sorting atoms in Editor", QString(), 0, asymm2.size(), this);
  progress.setWindowModality(Qt::WindowModal);
  int ares=0, apart=0;
  for (int i=0; i < asymm2.size(); i++){
    progress.setValue(i);
    QString  label = asymm2.at(i).orginalLine.left(80).trimmed();
    cursor.movePosition(QTextCursor::Start);
    cursor = document->find(label,cursor);
    if (cursor.isNull()){
      cursor = textCursor();
      cursor.movePosition(QTextCursor::Start);
      label.chop(10);
      cursor = document->find(label,cursor);
      if (cursor.isNull()) {
        cursor = textCursor();
        printf("hab was nicht %d %s\n",i,label.toStdString().c_str());
        continue;
      }
    }

    if (parenthesis.at(cursor.blockNumber()))continue;//Afix not sorted here
    QString vorherig,neues;
    cursor.movePosition(QTextCursor::StartOfLine,QTextCursor::MoveAnchor);
    cursor.movePosition(QTextCursor::EndOfLine,QTextCursor::KeepAnchor);
    while (cursor.selectedText().endsWith("=")) {
      cursor.movePosition(QTextCursor::Down,QTextCursor::KeepAnchor);
      cursor.movePosition(QTextCursor::EndOfLine,QTextCursor::KeepAnchor);
    }
    while (parenthesis.at(cursor.blockNumber()+1)){
      cursor.movePosition(QTextCursor::Down,QTextCursor::KeepAnchor);
      cursor.movePosition(QTextCursor::EndOfLine,QTextCursor::KeepAnchor);
    }
    neues = vorherig= cursor.selectedText();
    cursor.deleteChar();
    cursor.deleteChar();
    cursor = textCursor();
    cursor.movePosition(QTextCursor::Start);
    cursor = document->find("HKLF",cursor);
    cursor.clearSelection();
    cursor.movePosition(QTextCursor::StartOfLine);
    if ((asymm2.at(i).resiNr!=ares))
      cursor.insertText(QString("RESI %1 %2\n")
          .arg(asymm2.at(i).resiNr)
          .arg(asymm2.at(i).ResiClass));
    if ((asymm2.at(i).part!=apart))
      cursor.insertText(QString("PART %1\n")
          .arg(asymm2.at(i).part));
    cursor.insertText(neues);
    cursor.insertText("\n");
    ares = asymm2.at(i).resiNr;
    apart = asymm2.at(i).part;
    updateAfix();
  }
  cursor = document->find("HKLF",cursor);
  cursor.clearSelection();
  cursor.movePosition(QTextCursor::StartOfLine);
  if ((0!=apart)) cursor.insertText(QString("PART 0\n"));
  if ((0!=ares)) cursor.insertText(QString("RESI 0\n"));
  cursor.endEditBlock ();
  emit updateLabel();

  chgl->disSelection();
  if (chgl->fuse->isVisible())chgl->mol->grow();
  else  chgl->mol->fuse();
  chgl->murx=__LINE__;
  setUndoRedoEnabled ( true );
  chgl->updateGL();
  searchLE->setText("");
  replace->setText("");
  wholeLine->setChecked(false);
  setTextCursor(cursor);

  progress.setValue(asymm2.size());
}

void CodeEditor::sortSelectedRegion(){

  QTextCursor cursor = textCursor();
  int sta=cursor.selectionStart();
  int end=cursor.selectionEnd();
  cursor.setPosition(sta);    
  cursor.movePosition(QTextCursor::StartOfLine);
  cursor.setPosition(end, QTextCursor::KeepAnchor);    
  cursor.movePosition(QTextCursor::EndOfLine, QTextCursor::KeepAnchor);
  if (cursor.selectedText().endsWith("=")) cursor.movePosition(QTextCursor::Down, QTextCursor::KeepAnchor);
  //cursor.movePosition(QTextCursor::StartOfLine);
  QString sel=cursor.selectedText();
  CEnvironment toms;
  for (int i=0; i<chgl->mol->asymm.size(); i++){
    if (chgl->mol->asymm.at(i).afix!=0) continue;
    if (chgl->mol->asymm.at(i).orginalLine.size()<30) continue;
    if (sel.contains(chgl->mol->asymm.at(i).orginalLine,Qt::CaseInsensitive)){
      toms.append(chgl->mol->asymm[i]);
    }
  }
  int amax = toms.size();
  //int zeilen=sel.count(QChar::ParagraphSeparator);
  if (amax <3) {
    toms.clear();
    cursor.clearSelection ();
    setTextCursor(cursor);
    update();
    qDebug()<<"not enough atoms selected!";
    return;
  }
  int t1=0,t2=0;
  QMap<long double,MyAtom> atomSortMap;
  QMap<long double,int> atomSortMapi;
  for (int i=0; i < amax; i++){
    if (toms.at(i).an<0) continue;
    t1++;
    QString s1 = toms.at(i).Label;
    s1.remove(0,chgl->mol->pse(toms.at(i).an).size());
    int n1 = s1.section(QRegExp("\\D"),0,0).toInt();
    int r1 = 0 ;
    char cc[10];
    strncpy(cc,s1.section(QRegExp("\\d+"),1,-1).toStdString().c_str(),4);
    for (size_t k=0; k<strlen(cc);k++) {r1*=256;r1+=(size_t)cc[k];}
    switch (sortierWeise){
      case 1:
        atomSortMap.insertMulti(
            toms.at(i).resiNr*99*amax+
            toms.at(i).part*amax+
            n1+
            ((110-toms.at(i).an)/220.0)+
            (r1 / 50000.0)//46656
            ,toms.at(i));
        atomSortMapi.insertMulti(
            toms.at(i).resiNr*99*amax+
            toms.at(i).part*amax+
            n1+
            ((110-toms.at(i).an)/220.0)+
            (r1 / 50000.0)//46656
            ,i);
        break;
      case 2:
        atomSortMap.insertMulti(
            toms.at(i).resiNr*99*amax+
            toms.at(i).part*amax+
            n1/999.0+
            ((110-toms.at(i).an))+
            (r1 / 50000.0)//46656
            ,toms.at(i));
        atomSortMapi.insertMulti(
            toms.at(i).resiNr*99*amax+
            toms.at(i).part*amax+
            n1/999.0+
            ((110-toms.at(i).an))+
            (r1 / 50000.0)//46656
            ,i);
        break;
      case 3:
        atomSortMap.insertMulti(
            toms.at(i).resiNr*99*amax+
            toms.at(i).part*amax+
            n1/999.0+
            sfac.indexOf(toms.at(i).an)*10+
            (r1 / 50000.0)//46656
            ,toms.at(i));
        atomSortMapi.insertMulti(
            toms.at(i).resiNr*99*amax+
            toms.at(i).part*amax+
            n1/999.0+
            sfac.indexOf(toms.at(i).an)*10+
            (r1 / 50000.0)//46656
            ,i);
        break;
      case 4:
        atomSortMap.insertMulti(
            toms.at(i).resiNr*99*amax+
            toms.at(i).part*amax+
            n1/50000.0+
            ((110-toms.at(i).an)/220)+
            (r1 )//46656
            ,toms.at(i));
        atomSortMapi.insertMulti(
            toms.at(i).resiNr*99*amax+
            toms.at(i).part*amax+
            n1/50000.0+
            ((110-toms.at(i).an)/220)+
            (r1 )//46656
            ,i);
        t2++;
        break;
      case 5:
        atomSortMap.insertMulti(
            toms.at(i).molindex*9999*amax+
            toms.at(i).resiNr*99*amax+
            toms.at(i).part*amax+
            n1/999.0+
            ((110-toms.at(i).an))+
            (r1 / 50000.0)//46656
            ,toms.at(i));
        atomSortMapi.insertMulti(
            toms.at(i).molindex*9999*amax+
            toms.at(i).resiNr*99*amax+
            toms.at(i).part*amax+
            n1/999.0+
            ((110-toms.at(i).an))+
            (r1 / 50000.0)//46656
            ,i);
        /*		printf("%s %g\n", chgl->mol->asymm.at(i).Label.toStdString().c_str(),chgl->mol->asymm.at(i).molindex*9999*amax+
                        chgl->mol->asymm.at(i).resiNr*99*amax+
                        chgl->mol->asymm.at(i).part*amax+
                        n1/999.0+
                        ((110-chgl->mol->asymm.at(i).an))+
                        (r1 / 50000.0));*/
        break;
      default:
        atomSortMap.insert(i
            ,toms.at(i));
        atomSortMapi.insert(i
            ,i);
        break;
    }
  }
  CEnvironment asymm2=
    atomSortMap.values();
  QList<int> kk=atomSortMapi.values();
  cursor.beginEditBlock ();
  cursor.removeSelectedText ();

  QStringList neu,li= sel.split(QChar::ParagraphSeparator);

  QRegExp sep=QRegExp("\\s+");
  QString neues;
  bool fix=false;
  for (int i=0; i<li.size(); i++){
    int cmd=Window::isacommand(li.at(i).section(sep,0,0));
    switch (cmd){
      case 1:fix=true;
             printf("afix\n");
             // intentional fall-through !
      case -1: 
             if ((!fix)&&(cmd==-1)&&(!li.at(i).startsWith(" "))&&(!neues.isEmpty())){ 
               neu.append(neues);
               neues.clear();
             } 
             neues.append('\n');
             neues.append(li.at(i));
             if (li.at(i).contains (QRegExp("AFIX\\s+0", Qt::CaseInsensitive))){ 
               neu.append(neues);
               neues.clear();
               fix=false;
             }
             break; 
      case 51:
      case 58:break;
      default:
              if (!neues.isEmpty()){ 
                neu.append(neues);
                neues.clear();
              } 
              cursor.insertText(li.at(i));
              cursor.insertText("\n");
    }

  }
  if (!neues.isEmpty()){ 
    neu.append(neues);
    neues.clear();
  } 
  //qDebug()<<neu<<neu.size()<<kk;
  int ares=0, apart=0;
  for (int i=0; i < asymm2.size(); i++){
    if ((asymm2.at(i).resiNr!=ares))
      cursor.insertText(QString("RESI %1 %2\n")
          .arg(asymm2.at(i).resiNr)
          .arg(asymm2.at(i).ResiClass));
    if ((asymm2.at(i).part!=apart))
      cursor.insertText(QString("PART %1\n")
          .arg(asymm2.at(i).part));
    cursor.insertText(neu.at(kk.at(i)));
    ares = asymm2.at(i).resiNr;
    apart = asymm2.at(i).part;
  }
  cursor.endEditBlock ();
  updateAfix();
  //todo editieren!!
}

void CodeEditor::insertEADP(QList<MyAtom> selected, QString resiSpec){
  QTextDocument *document = this->document();
  QTextCursor cursor = textCursor();
  cursor.movePosition(QTextCursor::Start,QTextCursor::MoveAnchor);
  cursor = document->find(QRegExp("^UNIT",Qt::CaseInsensitive),cursor);
  cursor.movePosition(QTextCursor::StartOfLine,QTextCursor::MoveAnchor);
  cursor.movePosition(QTextCursor::Down,QTextCursor::MoveAnchor);
  QString buffer =QString("EADP%1 ").arg((resiSpec.isEmpty())?"":"_"+resiSpec);
  buffer = selectedRestraintsAtoms(buffer, selected, resiSpec);
  cursor.insertText(DSRGui::textWrap(buffer));
}

void CodeEditor::insertDELU(double esd1, double esd2, QList<MyAtom> selected, QString resiSpec){
  QTextDocument *document = this->document();
  QTextCursor cursor = textCursor();
  cursor.movePosition(QTextCursor::Start,QTextCursor::MoveAnchor);
  cursor = document->find(QRegExp("^UNIT",Qt::CaseInsensitive),cursor);
  cursor.movePosition(QTextCursor::StartOfLine,QTextCursor::MoveAnchor);
  cursor.movePosition(QTextCursor::Down,QTextCursor::MoveAnchor);
  QString buffer = QString("DELU%1 %2 %3 ").arg((resiSpec.isEmpty())?"":"_"+resiSpec).arg(esd1).arg(esd2);
  buffer = selectedRestraintsAtoms(buffer, selected, resiSpec);
  cursor.insertText(DSRGui::textWrap(buffer));
}

void CodeEditor::insertSIMU(double esd1, double esd2, double dmax, QList<MyAtom> selected, QString resiSpec){
  QTextDocument *document = this->document();
  QTextCursor cursor = textCursor();
  cursor.movePosition(QTextCursor::Start,QTextCursor::MoveAnchor);
  cursor = document->find(QRegExp("^UNIT",Qt::CaseInsensitive),cursor);
  cursor.movePosition(QTextCursor::StartOfLine,QTextCursor::MoveAnchor);
  cursor.movePosition(QTextCursor::Down,QTextCursor::MoveAnchor);
  QString buffer =QString("SIMU%1 %2 %3 %4 ").arg((resiSpec.isEmpty())?"":"_"+resiSpec).arg(esd1).arg(esd2).arg(dmax);
  buffer = selectedRestraintsAtoms(buffer, selected, resiSpec);
  cursor.insertText(DSRGui::textWrap(buffer));
}

void CodeEditor::insertISOR(double esd1, double esd2, QList<MyAtom> selected, QString resiSpec){
  QTextDocument *document = this->document();
  QTextCursor cursor = textCursor();
  cursor.movePosition(QTextCursor::Start,QTextCursor::MoveAnchor);
  cursor = document->find(QRegExp("^UNIT",Qt::CaseInsensitive),cursor);
  cursor.movePosition(QTextCursor::StartOfLine,QTextCursor::MoveAnchor);
  cursor.movePosition(QTextCursor::Down,QTextCursor::MoveAnchor);
  QString buffer =QString("ISOR%1 %2 %3 ").arg((resiSpec.isEmpty())?"":"_"+resiSpec).arg(esd1).arg(esd2);
  buffer = selectedRestraintsAtoms(buffer, selected, resiSpec);
  cursor.insertText(DSRGui::textWrap(buffer));
}

void CodeEditor::insertRIGU(double esd1, double esd2, QList<MyAtom> selected, QString resiSpec){
  QTextDocument *document = this->document();
  QTextCursor cursor = textCursor();
  cursor.movePosition(QTextCursor::Start,QTextCursor::MoveAnchor);
  cursor = document->find(QRegExp("^UNIT",Qt::CaseInsensitive),cursor);
  cursor.movePosition(QTextCursor::StartOfLine,QTextCursor::MoveAnchor);
  cursor.movePosition(QTextCursor::Down,QTextCursor::MoveAnchor);
  QString buffer =QString("RIGU%1 %2 %3 ").arg((resiSpec.isEmpty())?"":"_"+resiSpec).arg(esd1).arg(esd2);
  buffer = selectedRestraintsAtoms(buffer, selected, resiSpec);
  cursor.insertText(DSRGui::textWrap(buffer));
}

void CodeEditor::insertCHIV(double vol, double esd1, QList<MyAtom> selected, QString resiSpec){
  QTextDocument *document = this->document();
  QTextCursor cursor = textCursor();
  cursor.movePosition(QTextCursor::Start,QTextCursor::MoveAnchor);
  cursor = document->find(QRegExp("^UNIT",Qt::CaseInsensitive),cursor);
  cursor.movePosition(QTextCursor::StartOfLine,QTextCursor::MoveAnchor);
  cursor.movePosition(QTextCursor::Down,QTextCursor::MoveAnchor);
  QString buffer =QString("CHIV%1 %2 %3 ").arg((resiSpec.isEmpty())?"":"_"+resiSpec).arg(vol).arg(esd1);
  buffer = selectedRestraintsAtoms(buffer, selected, resiSpec);
  cursor.insertText(DSRGui::textWrap(buffer));
}

void CodeEditor::omitsome(const QString &s){
  //qDebug()<<"omi->t"<<s.size();
  QList<Omit> schonWeg;        
  Omit o;
  QTextDocument *document = this->document();
  QTextCursor cursor = textCursor();
  cursor.movePosition(QTextCursor::Start,QTextCursor::MoveAnchor);
  QStringList sli;
  while (!cursor.isNull()){
    cursor = document->find(QRegExp("OMIT\\s+\\d+\\s+\\d+\\s+\\d+"),cursor);
    if (!cursor.isNull()){
      sli=cursor.selectedText().split(" ",QString::SkipEmptyParts);
      o.h=sli.at(1).toInt();
      o.k=sli.at(2).toInt();
      o.l=sli.at(3).toInt();
      schonWeg.append(o);
    }
  }
  QString sm=s;
  for (int i=0; i<schonWeg.size(); i++){
    sm.remove(QString("OMIT %1 %2 %3\n").arg(schonWeg.at(i).h).arg(schonWeg.at(i).k).arg(schonWeg.at(i).l)); 
  }
  cursor = textCursor();
  cursor.movePosition(QTextCursor::Start,QTextCursor::MoveAnchor);
  if (!sm.isEmpty()){
    cursor = document->find("UNIT",cursor);
    cursor.movePosition(QTextCursor::StartOfLine,QTextCursor::MoveAnchor);
    cursor.movePosition(QTextCursor::Down,QTextCursor::MoveAnchor);
    cursor.insertText(sm);
    emit saveMe(true, true);
  }
}

void CodeEditor::lineNumberAreaPaintEvent(QPaintEvent *event){
  QPainter painter(lineNumberArea);
  int current = textCursor().blockNumber();
  painter.fillRect(event->rect(), QColor("#eeeeee"));
  QTextBlock block = firstVisibleBlock();
 // printf("edidor Font: %s italic%d bold %d point %d pixel %d height %d\n",fontInfo().family().toStdString().c_str(),fontInfo().italic (),fontInfo().bold (),fontInfo().pointSize (),fontInfo().pixelSize (),fontMetrics().height());
//   printf("lineNumberAreaPaintEvent\n");
  int blockNumber = block.blockNumber();
  int top = (int) blockBoundingGeometry(block).translated(contentOffset()).top();
  int bottom = top + (int) blockBoundingRect(block).height();
  // printf ("line %d %d\n",top,bottom);
  int minbl=8888888,maxbl=0;
  while (block.isValid() && top <= event->rect().bottom()) {
    if (block.isVisible() && bottom >= event->rect().top()) {
      QString number = QString::number(blockNumber + 1);
      bool iscurrent=(blockNumber==current);
      if (blockNumber%2) painter.fillRect(0, top,
                                      lineNumberArea->width(),
                                      fontMetrics().height(),QColor("#dddddd"));
      if (iscurrent) painter.fillRect(0, top,
                                      lineNumberArea->width(),
                                      fontMetrics().height(),QColor("#242424"));
      // /*
      QFont f=painter.font();
      if (errorInLine.contains(blockNumber)) {
	painter.fillRect(0, top,
			lineNumberArea->width(),
			fontMetrics().height(),QColor("#aa0000"));
	iscurrent=true;
      }
      if (comment.at(blockNumber)) {
    painter.fillRect(5, top+2,
			3,//lineNumberArea->width()
            fontMetrics().height()-4,(iscurrent)?QColor("#99aaff"):QColor("#0000aa"));
      }
      
      
      //printf("edidor Font: %s %d %d %d\n",f.family().toStdString().c_str(),f.pointSize(),fontMetrics().height(),fontMetrics().lineSpacing ());
      f.setWeight((iscurrent)?QFont::Black:QFont::Light);
      painter.setFont(f);
      // */
      painter.setPen((iscurrent)?Qt::white:Qt::darkGray);
      painter.drawText(0, top,
		      lineNumberArea->width(), 
                      fontMetrics().lineSpacing () ,
                      Qt::AlignRight, number);
      minbl=qMin(minbl,blockNumber + 1);
      maxbl=qMax(maxbl,blockNumber + 1);
    }
    if (ListFile)
    midCursorpos=(minbl+maxbl)/2;
    block = block.next();
    top = bottom;
    bottom = top + (int) blockBoundingRect(block).height();
    ++blockNumber;
  }


  //updateAfix();
  //afixHighlightArea->update();
  event->accept();
}

void CodeEditor::lineNumberToggled(QMouseEvent *event){
    QTextBlock block=firstVisibleBlock();
    int top = (int) blockBoundingGeometry(block).translated(contentOffset()).top();
    int bn=firstVisibleBlock().blockNumber();
    int idx=(int)  (event->y()-top)/ ((int) blockBoundingRect(block).height()) + bn + 1;
//    printf("remark->  idx-1 %d  event.y %d top %d first %d height %g\n",idx-1,event->y(),top,bn,blockBoundingRect(block).height());
    remark(idx-1);
}

void CodeEditor::updateAfix(){
 // printf("updateAfix\n");
  blocks=toPlainText().split('\n');

  /*printf("test die Zeilenanzahl ist jetzt %d %d\n",  
		  blocks.size(),
		  blockCount()
		  );*/
  parenthesis.clear();
  parenthesis2.clear();
  comment.clear();
  int probe=0,aprobe=0,amn=0;
  bool kommentar=false;
  for (int i=0; i<blocks.size();i++){
    kommentar =  (blocks.at(i).contains(QRegExp("^REM",Qt::CaseInsensitive)));
    comment.append(kommentar);
      if (blocks.at(i).contains(QRegExp("^AFIX\\s+0",Qt::CaseInsensitive))) {
          probe=0;
          amn=0;
      }
    else {
      if (blocks.at(i).contains(QRegExp("^AFIX\\s+\\d+",Qt::CaseInsensitive))) {
	probe++;
	int m=blocks.at(i).section(QRegExp("\\s+"),1,1,QString::SectionSkipEmpty).toInt()/10;
        int n=blocks.at(i).section(QRegExp("\\s+"),1,1,QString::SectionSkipEmpty).toInt()%10;
        if (amn==(m*10+n)) {
            probe--;
            parenthesis.last()=2;
        }
	if (n==5) {
//	  printf("%d be---\n",probe);
	  probe=(qMax(probe-2,0));
//	  printf("%d----\n",probe);
	}
        amn=m*10+n;
      }
    }
    if (blocks.at(i).contains(QRegExp("^HKLF",Qt::CaseInsensitive))) {probe=aprobe=0;}
    parenthesis.append(qMax(probe,aprobe));
    aprobe=probe;
  }
  probe=0;
  for (int i=0; i<blocks.size();i++){
    if (blocks.at(i).contains(QRegExp("^PART\\s+0",Qt::CaseInsensitive))) probe=0;
    else if (blocks.at(i).contains(QRegExp("^PART\\s+[-0-9]{1,}",Qt::CaseInsensitive)))
      probe=blocks.at(i).section(' ',1,1,QString::SectionSkipEmpty).toInt();
    if (blocks.at(i).contains(QRegExp("^HKLF",Qt::CaseInsensitive))) {probe=0;}
    parenthesis2.append(probe);
  }
  afixHighlightArea->update();
}

void CodeEditor::remark(int line){
  if (isReadOnly ())return;
  if (blocks.size()<=line) return;
  QString zeile=blocks.at(line).simplified();
  bool cont= blocks.at(qMax(0,line-1)).contains(QRegExp("=\\s*$"));
  if (zeile.contains(QRegExp("^REM",Qt::CaseInsensitive))) {
    zeile=zeile.remove(0,4);
    if (cont) zeile.prepend(' ');
  }
  else zeile.prepend("REM ");  
  QTextCursor cu=textCursor ();
  cu.movePosition(QTextCursor::Start);
  cu.movePosition(QTextCursor::Down,QTextCursor::MoveAnchor,line);
  cu.movePosition(QTextCursor::StartOfLine,QTextCursor::MoveAnchor);
  cu.movePosition(QTextCursor::EndOfLine,QTextCursor::KeepAnchor);
  if (!cu.selectedText().isEmpty()) cu.deleteChar();
  cu.insertText(zeile);
  //qDebug()<<zeile;

}

void CodeEditor::toggleRemarks(){
QTextCursor cu=textCursor();
if (!cu.hasSelection())return;
cu.beginEditBlock();
int start=-1,end=-1,hilf=0;
start=cu.selectionStart();
end=cu.selectionEnd();
cu.setPosition(start);
start=cu.blockNumber();
cu.setPosition(end);
end=cu.blockNumber();
printf("start %d end %d\n",start,end);
hilf=start;
start=qMin(start,end);
end=qMax(hilf,end);
if (end!=start) {
cu.clearSelection();
for (int i=start; i<=end; i++) remark(i);
//qDebug()<<cu.selectedText()<<"\n"<<start<<end;
}
cu.endEditBlock();
cu.clearSelection();
cu.movePosition(QTextCursor::StartOfLine,QTextCursor::MoveAnchor);

if (!cu.isNull()) setTextCursor(cu);
}

void CodeEditor::afixHighlightAreaPaintEvent(QPaintEvent *event){
//   printf("\nafixHighlightAreaPaintEvent\n");
  QPainter apainter(afixHighlightArea);
  apainter.fillRect(afixHighlightArea->rect(), QColor("#fafaf0"));
  QTextBlock block = firstVisibleBlock();
  QColor color;
  QColor pcolor;
  int blockNumber = block.blockNumber();


  int top = (int) blockBoundingGeometry(block).translated(contentOffset()).top();
  int bottom = top + (int) blockBoundingRect(block).height();
  //printf ("afix %d %d %d %d \n",top,bottom,block.isVisible(),event->rect().top());
  while (block.isValid() && top <= event->rect().bottom()) {
  switch (parenthesis.at(blockNumber)){ 
  case 0: color=QColor("#fafaf0");
      //          Qt::white;
          break;
  case 1: color=Qt::darkGreen;break;
  default: 
          color=QColor("blueviolet");
          break;
  }
  switch (parenthesis2.at(blockNumber)){ 
  case 0: pcolor=QColor("#fafaf0");
              //Qt::white;
              break;
  case 1: pcolor=QColor("lightskyblue");break;
  case 2: pcolor=QColor("darkgoldenrod");break;
  case 3: pcolor=Qt::green;break;
  case 4: pcolor=Qt::yellow;break;
  case 5: pcolor=QColor("orange");break;
  case 6: pcolor=Qt::black;break;
  case 7: pcolor=QColor("lightsalmon");break;
  case 8: pcolor=QColor("lightseagreen");break;
  case -1: pcolor=QColor("aquamarine");break;
  case -2: pcolor=QColor("olive");break;
  case -3: pcolor=QColor("bisque");break;
  default: if (parenthesis2.at(blockNumber)>0)
          pcolor=QColor::colorNames().at(qMin(parenthesis2.at(blockNumber),QColor::colorNames().size()-1));
      else pcolor=Qt::magenta;
  }

    if (block.isVisible() && bottom >= event->rect().top()) {
    //  printf("%d %d %d %d %d %d\n",0,top, 4,fontMetrics().height(),parenthesis.at(blockNumber),blockNumber);
      apainter.fillRect(5,top, 4,fontMetrics().lineSpacing (),color);
      apainter.fillRect(0,top, 4,fontMetrics().lineSpacing (),pcolor);
     }
    block = block.next();
    blockNumber = block.blockNumber();
    top = bottom;
    bottom = top + (int) blockBoundingRect(block).height();
  } 
  event->accept();
}

bool CodeEditor::viewportEvent(QEvent *event){
//  printf("lala %d\n",event->type());
if (!isVisible()) {event->ignore(); return false;}
if (event->type() == QEvent::ToolTip) {
  QHelpEvent *helpEvent = static_cast<QHelpEvent *>(event);
  QTextCursor cursor = cursorForPosition( helpEvent->pos());
  if(cursor.block().text().isEmpty()) return true;
  QStringList block=shxToolTips.filter(cursor.block().text().left(4),Qt::CaseInsensitive);
  if (block.size())
    QToolTip::showText(helpEvent->globalPos(),block.first());
  int lnr=cursor.block().blockNumber()+1;
  QRegExp re=QRegExp("[-]*\\d{2,}\\.\\d+");
  double fvar=6666.6666;
  QString fvs;
  QString msg;
  int pos=0,len=0;
  if ((block.isEmpty())&&(!highlighter->outputStyle())&&(cursor.block().blockNumber() > fvMinLine)){
    while (-1 != (pos=re.indexIn(cursor.block().text(),pos+len+1))){
      fvs=re.cap(0);
      len=fvs.size();
      fvar=fvs.toDouble();
      if (fvar!=6666.6666) {
        double av=qAbs(fvar),res=0.0,var=1.0;
        int m=0;
        while ((-10*m+av) > 5){m++;}
        if ((m>1)&&(m<=fv.size())) var = fv.at(m-1);
        if (!m) res = fvar;
        else if (fvar>0) res = (av-(10*m))*var;
        else res = (av-(10*m))*(1.0-var);
        //qDebug()<<v<<res<<m;
        // std::cout<< av <<"abs  v"<< v <<" m ="<< m << " var =" << var <<" res = "<<res<< std::endl ;
        //return res;
        if ((m)>fv.size()){
          if (m>1) msg+=QString("<font color=\"red\">Error in line %2!<br>Free Variable %1 is not defined yet!</font><hr>")
          .arg(m).arg(lnr);}
        else
          msg+=QString("Line <b>%3</b>: Free Variable <b>%1</b> gives <b> %2</b> here.<hr>")
               .arg(m).arg(res).arg(lnr);
      }
    }
    QToolTip::showText(helpEvent->globalPos(),msg);
    //  printf("shxToolTips size+%d %d %f\n", shxToolTips.size(),block.size(),fvar);
  }
  event->accept();
  return true;
}
return QAbstractScrollArea::viewportEvent ( event);
}

void  CodeEditor::contextMenuEvent(QContextMenuEvent *event) {
     //QMenu *menu = new QMenu();//createStandardContextMenu();
     QMenu *menu = createStandardContextMenu();
     QAction *a;
     QTextCursor cursor = cursorForPosition( event->pos());
     QTextBlock block=cursor.block();
     QString aname=block.text().section(" ",0,0);
     QStringList bfl=shxToolTips.filter(QRegExp(QString("^%1\\b").arg(aname)));
     if (bfl.isEmpty()){
        QString data=block.text().remove("=").trimmed();                                      // findInStructure
        if (data.startsWith("+")) a=menu->addAction(QString("+Open inluded file '%1'").arg(data) ,this,SLOT(openAnIncludeFile()));
        else a=menu->addAction(QString("locate %1 in structure").arg(aname) ,this,SLOT(searchInStructure()));
        a->setData(data);
     }//else {qDebug()<<bfl;}

     if (textCursor().hasSelection()){
         a=menu->addAction(QString("select atoms in structure found in selected text"),
                         this, SLOT(selectInStructure()));
         a->setData(textCursor().selectedText());
         a=menu->addAction(QString("sort atoms found in selected text"),
                         this, SLOT(sortSelectedRegion()));
         a->setData(textCursor().selectedText());
	 a=menu->addAction(QString("toggle remarks states of selected text"),
			 this,SLOT(toggleRemarks()));
     }
     //...
     menu->exec(event->globalPos());
     delete menu;

     event->accept();
 }

void CodeEditor::diffTo(QString org){
    QList<QTextEdit::ExtraSelection> extraSelections;
    QTextEdit::ExtraSelection selection;
    QStringList orgZ = org.split('\n');
    QColor lineColor = QColor("#ffddaa");
    setReadOnly(false);
    selection.cursor = textCursor();
    selection.cursor.clearSelection();
    selection.cursor.movePosition(QTextCursor::Start);

    selection.format.setBackground(lineColor);
    selection.format.setProperty(QTextFormat::FullWidthSelection, true);

    QTextBlock b = selection.cursor.block();
    int i=0;
    while (b.isValid()){
        if (b.text()!=orgZ.at(i)){
           /* printf(">>%s!\n<<%s!%d\n",
                   b.text().toStdString().c_str(),
                   orgZ.at(i).toStdString().c_str(),b.position()
                   );// */
            selection.cursor.clearSelection();
            selection.cursor.setPosition(b.position());
            selection.cursor.movePosition(QTextCursor::StartOfLine,QTextCursor::MoveAnchor);
            selection.cursor.movePosition(QTextCursor::EndOfLine,QTextCursor::MoveAnchor);

            extraSelections.append(selection);
        }
        b=b.next();
        int j=orgZ.indexOf(b.text(),i);
        i=(j<0)?i+1:j;
        i=qMin(i,orgZ.size()-1);
    }
    setExtraSelections(extraSelections);
    setReadOnly(true);
    update();
}

void CodeEditor::searchInStructure(){
    QAction *action = qobject_cast<QAction *>(sender());
    if (action)
        emit findInStructure(action->data().toString());

}

void CodeEditor::openAnIncludeFile(){
    QAction *action = qobject_cast<QAction *>(sender());
    if (action)
        emit openIncludeFile(action->data().toString());

}

void CodeEditor::selectInStructure(){
    QAction *action = qobject_cast<QAction *>(sender());
    if (action)
        emit electInStructure(action->data().toString());

}

void CodeEditor::setCompleter(QCompleter *completer){
    //printf("setCompleter %p %p\n",c,completer);
    if (c)
        QObject::disconnect(c, 0, this, 0);

    c = completer;

    if (!c)
        return;

    c->setWidget(this);
    //c->setMaxVisibleItems(13);
    c->setCompletionMode(QCompleter::PopupCompletion);
    c->setCaseSensitivity(Qt::CaseInsensitive);
    QObject::connect(c, SIGNAL(activated(QString)),
                     this, SLOT(insertCompletion(QString)));
}

QCompleter *CodeEditor::completer() const{
    return c;
}

void CodeEditor::insertCompletion(const QString& completion){
    if (c->widget() != this)
        return;
    QTextCursor tc = textCursor();
    tc.joinPreviousEditBlock ();
    //int extra = completion.length() - c->completionPrefix().length();
    //tc.movePosition(QTextCursor::Left);
//    int p=tc.selectionStart()- tc.block().position();
    tc.movePosition(QTextCursor::EndOfWord,QTextCursor::MoveAnchor);
    tc.movePosition(QTextCursor::StartOfLine,QTextCursor::KeepAnchor);
    QString extra = tc.selectedText();
    //extra.remove(0,1);
    extra.remove(QRegExp("^[a-z]+"));
    if ((completion!="REM "))extra.clear();
    tc.deleteChar();
    tc.insertText(completion+" "+extra);
    tc.endEditBlock();
    setTextCursor(tc);
}

QString CodeEditor::textUnderCursor() const{
    QTextCursor tc = textCursor();
    tc.select(QTextCursor::WordUnderCursor);
    if (tc.selectedText().contains("_")) return "";
    int si=tc.selectedText().size();
    //if (tc.selectedText().startsWith('r',Qt::CaseSensitive))
    //    return tc.selectedText().section(QRegExp("[A-Z]+",Qt::CaseSensitive),0,0).toUpper();
    //    printf("%d %d\n", (tc.selectionStart ()  - tc.block().position()) ,si);
    if (((tc.selectionStart () - tc.block().position())<4)&&(si>4)) return tc.selectedText().left(si-4);
    if ((tc.position() - tc.block().position())>2) return "";
    return tc.selectedText();
}

void CodeEditor::focusInEvent(QFocusEvent *e){

//    printf("focusInEvent %p \n",c);
    if (c)
        c->setWidget(this);
    QPlainTextEdit::focusInEvent(e);
    e->accept();
    //e->ignore();
    //setFocus(Qt::MouseFocusReason);
}

void CodeEditor::insertFree(){
  if (chgl->mol->selectedatoms.size()!=2) return;
  QAction *action = qobject_cast<QAction *>(sender());
  if (action){
    int index=  action->data().toInt();
    QString frei=QString("FREE %1 %2 !experimental does not work with EQIV AND PART\n")
      .arg(chgl->mol->selectedatoms.at(0).Label.section(QString::fromUtf8("»"),0,0))
      .arg(chgl->mol->selectedatoms.at(1).Label.section(QString::fromUtf8("»"),0,0));

    QTextDocument *document = this->document();
    QTextCursor cursor = textCursor();
    cursor.beginEditBlock();
    cursor = document->find("HKLF",cursor);
    cursor.movePosition(QTextCursor::StartOfLine,QTextCursor::MoveAnchor);
    cursor.insertText(frei);
    cursor.endEditBlock();
    chgl->disConnectSelection(index);
  }
}

void CodeEditor::insertBind(){
  if (chgl->mol->selectedatoms.size()!=2) return;
  QString binde=QString("BIND %1 %2 !experimental does not work with EQIV AND PART\n")
    .arg(chgl->mol->selectedatoms.at(0).Label.section(QString::fromUtf8("»"),0,0))
    .arg(chgl->mol->selectedatoms.at(1).Label.section(QString::fromUtf8("»"),0,0));
  QTextDocument *document = this->document();
  QTextCursor cursor = textCursor();
  cursor.beginEditBlock();
  cursor = document->find("HKLF",cursor);
  cursor.movePosition(QTextCursor::StartOfLine,QTextCursor::MoveAnchor);
  cursor.insertText(binde);
  cursor.endEditBlock();
  chgl->connectSelection();
}

void CodeEditor::keyPressEvent(QKeyEvent *e){
//    printf("kp\n");
//    if (!chgl->mol->selectedatoms.isEmpty()){
  // Pressing F1 when the mouse cursor is over a SHELX command will
  // open the SHELXL help text:
  if (e->key() == Qt::Key_F1) {
    QTextCursor tc = textCursor();
    //tc.select(QTextCursor::WordUnderCursor);
    tc.select(QTextCursor::LineUnderCursor);
    QString txt = tc.selectedText().toUpper().left(4).trimmed();
    printf("%s\n",txt.toStdString().c_str());
    if ( Window::isacommand(txt) >= 0 ) {
      QUrl help_url = QString("http://shelx.uni-goettingen.de/shelxl_html.php#%1").arg(txt);
      QDesktopServices::openUrl(help_url);
    }
  }
  if ((e->modifiers() & Qt::ControlModifier)&&(e->key()==Qt::Key_Delete)) {
      	e->ignore();
        emit deleteSelected();
    return;
    }
    //}
    if (c && c->popup()->isVisible()) {
        // The following keys are forwarded by the completer to the widget
       switch (e->key()) {
       case Qt::Key_Enter:
       case Qt::Key_Return:
       case Qt::Key_Escape:
       case Qt::Key_Tab:
      // case Qt::Key_Left:
      // case Qt::Key_Right:
       case Qt::Key_Backtab:
            e->ignore();
            return; // let the completer do default behavior
       default:
           break;
       }
    }

   // bool isShortcut = ((e->modifiers() & Qt::ControlModifier) && e->key() == Qt::Key_E); // CTRL+E
   // if (!c) // do not process the shortcut when we have a completer
        QPlainTextEdit::keyPressEvent(e);

    const bool ctrlOrShift = e->modifiers() & (Qt::ControlModifier | Qt::ShiftModifier);
    if (!c || (ctrlOrShift && e->text().isEmpty()))
        return;

    static QString eow("!"); // end of word
    bool hasModifier = (e->modifiers() != Qt::NoModifier) && !ctrlOrShift;
    QString completionPrefix = textUnderCursor();
    if ((hasModifier || e->text().isEmpty()|| completionPrefix.length() < 1
                      || eow.contains(e->text().right(1)))) {
        c->popup()->hide();
        return;
    }

    if (completionPrefix != c->completionPrefix()) {
        c->setCompletionPrefix(completionPrefix);
        c->popup()->setCurrentIndex(c->completionModel()->index(0, 0));
    }
    QRect cr = cursorRect();
    cr.moveRight(lineNumberAreaWidth()+11);;
    cr.setWidth(c->popup()->sizeHintForColumn(0)
                + c->popup()->verticalScrollBar()->sizeHint().width());
    c->complete(cr); // popup it up!
}

