Skip to content
Snippets Groups Projects
Forked from mlz / Frida
1048 commits behind the upstream repository.
coord.cpp 4.09 KiB
//**************************************************************************************************
//*  FRIDA: fast reliable interactive data analysis                         
//*  (C) Joachim Wuttke 1990-, v2(C++) 2001-                                
//*  http://apps.jcns.fz-juelich.de/frida                                   
//**************************************************************************************************

//! \file  coord.cpp
//! \brief Coordinates CCoord, numeric parameters CParam.


#include <cstring>
#include <iostream>

#include <../readplus/macro.hpp>

using namespace std;

#include "coord.hpp"

//**************************************************************************************************
//*  class CCoord
//**************************************************************************************************

//! Constructor parsing "name (unit)", where unit may be empty.

CCoord::CCoord( const string in )
{
    int i, j, np, n;
    n = in.size();
    if (in[n-1]!=')')
        throw "input must terminate with ')'";
    for(j=n-2, np=1; j!=(int)-1; j--) {
        if (in[j]==')') 
            np++;
        else if (in[j]=='(') {
            np--;
            if (np==0) break;
        }
    }
    if (np!=0)
        throw "input must contain balanced parentheses";
    for (i=j; i>0 && strchr(" \t",in[i-1]); i--) ;
    if (i==0)
        throw "input must contain a non-empty coordinate name";
    name = in.substr(0,i);
    unit = in.substr(j+1, n-j-2);
}

//! Interactive setting with help functionality.

void CCoord::ask_and_set( const string& quest )
{
    string prompt = quest;
    if( name!="" )
        prompt += " [" + str_std() + "]";
    prompt += " ? ";
    for( ;; ) {
        string resp = NMacro::readln( prompt );
        if        ( resp == "\\q" ) {
            throw "user escape to main menu";
        } else if ( resp == "" ) {
            if ( name!="" )
                return; // keep current value
            cout << "no default available\n";
        } else if ( resp == "?" ) {
            cout << "required input type: coordinate name and unit\n";
            cout << "input must be in the form: name (unit)\n";
            if( name!="" )
                cout << "just press ENTER to let current value unchanged ["
                     << str_std() << "]\n";
        } else {
            int i, j, np, n;
            n = resp.size();
            if (resp[n-1]!=')') {
                cout << "input must terminate with ')'\n";
                continue;
            }
            for(j=n-2, np=1; j!=(int)-1; j--) {
                if (resp[j]==')') 
                    np++;
                else if (resp[j]=='(') {
                    np--;
                    if (np==0) break;
                }
            }
            if (np!=0){
                cout << "input must contain balanced parentheses\n";
                continue;
            }
            for (i=j; i>0 && strchr(" \t",resp[i-1]); i--) ;
            if (i==0){
                cout << "input must contain a non-empty coordinate name\n";
                continue;
            }
            name = resp.substr(0,i);
            unit = resp.substr(j+1, n-j-2);
            return;
        }
    }
}


//! Standard string.

string CCoord::str_std() const
{
    return name + " (" + unit + ")";
}

//! Compact string for use in tables.

string CCoord::str_compact( int maxlen ) const
{
    string ret = name + "(" + unit + ")";
    if ( maxlen==0 || ret.length() <= maxlen )
        return ret;
    ret = name;
    if ( ret.length() <= maxlen )
        return ret;
    if( maxlen>3 )
        return name.substr(0,maxlen-2) + "..";
    return name.substr(0,maxlen);
}

//! String for use in PostScript output.

string CCoord::str_ps() const // two blanks instead of one, and no unit ""
{
    return name + ( unit!="" ? ("  (" + unit + ")") : "");
}

//**************************************************************************************************
//*  outside CCoord
//**************************************************************************************************

ostream& operator<< (ostream &s, CCoord C)
{
    return s << C.str_std();
}