Example #1
0
void Identifier::setFromSql(const wxString& source)
{
    // const wxChar pointers to first and last characters
    const wxChar* p = source.c_str();
    const wxChar* q = p + source.Length() - 1;
    // skip leading and trailing whitespace
    while (q > p && wxIsspace(*p))
        p++;
    while (q > p && wxIsspace(*q))
        q--;
    if (p > q) // p is first, q is last character, so they may be equal...
    {
        textM = wxEmptyString;
        return;
    }
    // strings/quoted identifier -> strip and unescape single/double quotes
    if (*q == *p && (*p == '\"' || *p == '\''))
    {
        // NOTE: first parameter must point to first char, but second parameter
        //       has to point to the char *after* the last char !!!
        textM = wxString(p + 1, q);
        wxString escapedChar(p, 1);
        textM.Replace(escapedChar + escapedChar, escapedChar);
        return;
    }
    // set to uppercased input parameter, no leading and trailing whitespace
    textM = wxString(p, q + 1).Upper();
}
Example #2
0
void wxHtmlWordCell::SetPreviousWord(wxHtmlWordCell *cell)
{
    if ( cell && m_Parent == cell->m_Parent &&
            !wxIsspace(cell->m_Word.Last()) && !wxIsspace(m_Word[0u]) )
    {
        m_allowLinebreak = false;
    }
}
Example #3
0
void SqlTokenizer::whitespaceToken()
{
    sqlTokenTypeM = tkWHITESPACE;
    wxASSERT(wxIsspace(*sqlTokenEndM));
    sqlTokenEndM++;
    // scan until non-whitespace, or until "\0" found
    while (*sqlTokenEndM != 0 && wxIsspace(*sqlTokenEndM))
        sqlTokenEndM++;
}
void CCManager::DoUpdateCallTip(cbEditor* ed)
{
    wxStringVec tips;
    int hlStart = m_CurCallTip->hlStart;
    int hlEnd   = m_CurCallTip->hlEnd;
    size_t sRange = 0;
    size_t eRange = m_CurCallTip->tip.find(wxT('\n'));
    while (eRange != wxString::npos)
    {
        tips.push_back(m_CurCallTip->tip.Mid(sRange, eRange - sRange));
        CCManagerHelper::RipplePts(hlStart, hlEnd, eRange, -1);
        sRange = eRange + 1;
        eRange = m_CurCallTip->tip.find(wxT('\n'), sRange);
    }
    if (sRange < m_CurCallTip->tip.Length())
        tips.push_back(m_CurCallTip->tip.Mid(sRange));
    int offset = 0;
    cbStyledTextCtrl* stc = ed->GetControl();
    if (m_CallTips.size() > 1)
    {
        ++offset;
        if (m_CurCallTip == m_CallTips.begin())
            tips.front().Prepend(wxT('\002')); // down arrow
        else if (m_CurCallTip + 1 == m_CallTips.end())
            tips.front().Prepend(wxT('\001')); // up arrow
        else
        {
            tips.front().Prepend(wxT("\001\002")); // up/down arrows
            ++offset;
        }
        tips.push_back(wxString::Format(wxT("(%d/%u)"), m_CurCallTip - m_CallTips.begin() + 1, m_CallTips.size()));
        // store for better first choice later
        m_CallTipChoiceDict[CCManagerHelper::CallTipToInt(m_CallTips.front().tip, m_CallTips.size())] = m_CurCallTip - m_CallTips.begin();
        // fuzzy store
        int prefixEndPos = m_CallTipActive;
        while (prefixEndPos > 0 && wxIsspace(stc->GetCharAt(prefixEndPos - 1)))
            --prefixEndPos;
        const wxString& prefix = stc->GetTextRange(stc->WordStartPosition(prefixEndPos, true), prefixEndPos);
        m_CallTipFuzzyChoiceDict[CCManagerHelper::CallTipToInt(prefix, m_CallTips.size())] = m_CurCallTip - m_CallTips.begin();
    }
    int pos = stc->GetCurrentPos();
    int lnStart = stc->PositionFromLine(stc->LineFromPosition(pos));
    while (wxIsspace(stc->GetCharAt(lnStart)))
        ++lnStart;
#ifdef __WXMSW__
    m_LastTipPos = wxSCI_INVALID_POSITION; // Windows hack to fix display update
#endif // __WXMSW__
    DoShowTips(tips, stc, std::max(pos, lnStart), m_CallTipActive, hlStart + offset, hlEnd + offset);
}
Example #5
0
void wxStringTokenizer::SetString(const wxString& str,
                                  const wxString& delims,
                                  wxStringTokenizerMode mode)
{
    if ( mode == wxTOKEN_DEFAULT )
    {
        // by default, we behave like strtok() if the delimiters are only
        // whitespace characters and as wxTOKEN_RET_EMPTY otherwise (for
        // whitespace delimiters, strtok() behaviour is better because we want
        // to count consecutive spaces as one delimiter)
        const wxChar *p;
        for ( p = delims.c_str(); *p; p++ )
        {
            if ( !wxIsspace(*p) )
                break;
        }

        if ( *p )
        {
            // not whitespace char in delims
            mode = wxTOKEN_RET_EMPTY;
        }
        else
        {
            // only whitespaces
            mode = wxTOKEN_STRTOK;
        }
    }

    m_delims = delims;
    m_mode = mode;

    Reinit(str);
}
Example #6
0
void SqlTokenizer::defaultToken()
{
    if (wxStricmp(sqlTokenStartM, termM.c_str()) == 0)
    {
        sqlTokenTypeM = tkTERM;
        sqlTokenEndM = sqlTokenStartM + termM.Length();
        return;
    }

    // this is needed for new terminator string
    while (true)
    {
        // increase the size until we hit either whitespace, terminator, EOF
        // or some of significant characters
        sqlTokenEndM++;
        if (*sqlTokenEndM == 0
            || *sqlTokenEndM == ',' || *sqlTokenEndM == '='
            || *sqlTokenEndM == '(' || *sqlTokenEndM == ')'
            || *sqlTokenEndM == '+' || *sqlTokenEndM == '-'
            || *sqlTokenEndM == '/' || *sqlTokenEndM == '*'
            || wxIsspace(*sqlTokenEndM)
            || wxStricmp(sqlTokenEndM, termM.c_str()) == 0  )
        {
            break;
        }
    }
    sqlTokenTypeM = tkUNKNOWN;
}
Example #7
0
bool SqlTokenizer::nextToken()
{
    sqlTokenStartM = sqlTokenEndM;
    if (sqlTokenEndM == 0 || *sqlTokenEndM == 0)
    {
        sqlTokenTypeM = tkEOF;
        return false;
    }
    // use wxChar* member to scan
    wxChar c = *sqlTokenEndM;
    if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))
        keywordIdentifierToken();
    else if (c == '"')
        quotedIdentifierToken();
    else if (c == '\'')
        stringToken();
    else if (c == '(')
        symbolToken(tkPARENOPEN);
    else if (c == ')')
        symbolToken(tkPARENCLOSE);
    else if (c == '=')
        symbolToken(tkEQUALS);
    else if (c == ',')
        symbolToken(tkCOMMA);
    else if (c == '/' && *(sqlTokenEndM + 1) == '*')
        multilineCommentToken();
    else if (c == '-' && *(sqlTokenEndM + 1) == '-')
        singleLineCommentToken();
    else if (wxIsspace(c))
        whitespaceToken();
    else
        defaultToken();
    return true;
}
HighlightLanguage EditorColourSet::AddHighlightLanguage(int lexer, const wxString& name)
{
    if (   lexer <= wxSCI_LEX_NULL
        || lexer >  wxSCI_LEX_LAST // this is a C::B extension to wxscintilla.h
        || name.IsEmpty() )
    {
        return HL_NONE;
    }

    // fix name to be XML compliant
    wxString newID;
    size_t pos = 0;
    while (pos < name.Length())
    {
        wxChar ch = name[pos];
        if      (wxIsalnum(ch) || ch == _T('_'))
            newID.Append(ch); // valid character
        else if (wxIsspace(ch))
            newID.Append(_T('_')); // convert spaces to underscores
        ++pos;
    }
    // make sure it's not starting with a number or underscore.
    // if it is, prepend an 'A'
    if (wxIsdigit(newID.GetChar(0)) || newID.GetChar(0) == _T('_'))
        newID.Prepend(_T('A'));

    if (GetHighlightLanguage(newID) != HL_NONE)
        return HL_NONE;

    m_Sets[newID].m_Langs = name;
    m_Sets[newID].m_Lexers = lexer;
    return newID;
}
Example #9
0
bool wxExtHelpController::ParseMapFileLine(const wxString& line)
{
    const wxChar *p = line.c_str();

    // skip whitespace
    while ( isascii(*p) && wxIsspace(*p) )
        p++;

    // skip empty lines and comments
    if ( *p == wxT('\0') || *p == WXEXTHELP_COMMENTCHAR )
        return true;

    // the line is of the form "num url" so we must have an integer now
    wxChar *end;
    const unsigned long id = wxStrtoul(p, &end, 0);

    if ( end == p )
        return false;

    p = end;
    while ( isascii(*p) && wxIsspace(*p) )
        p++;

    // next should be the URL
    wxString url;
    url.reserve(line.length());
    while ( isascii(*p) && !wxIsspace(*p) )
        url += *p++;

    while ( isascii(*p) && wxIsspace(*p) )
        p++;

    // and finally the optional description of the entry after comment
    wxString doc;
    if ( *p == WXEXTHELP_COMMENTCHAR )
    {
        p++;
        while ( isascii(*p) && wxIsspace(*p) )
            p++;
        doc = p;
    }

    m_MapList->Append(new wxExtHelpMapEntry(id, url, doc));
    m_NumOfEntries++;

    return true;
}
Example #10
0
void ClangCodeCompletion::HighlightOccurrences(cbEditor* ed)
{
    ClTranslUnitId translId = GetCurrentTranslationUnitId();
    cbStyledTextCtrl* stc = ed->GetControl();
    int pos = stc->GetCurrentPos();
    const wxChar ch = stc->GetCharAt(pos);
    if (pos > 0
            && (wxIsspace(ch) || (ch != wxT('_') && wxIspunct(ch)))
            && !wxIsspace(stc->GetCharAt(pos - 1)))
    {
        --pos;
    }

    // chosen a high value for indicator, hoping not to interfere with the indicators used by some lexers
    // if they get updated from deprecated old style indicators someday.
    const int theIndicator = 16;
    stc->SetIndicatorCurrent(theIndicator);

    // Set Styling:
    // clear all style indications set in a previous run (is also done once after text gets unselected)
    stc->IndicatorClearRange(0, stc->GetLength());

    if (stc->GetTextRange(pos - 1, pos + 1).Strip().IsEmpty())
        return;

    // TODO: use independent key
    wxColour highlightColour(Manager::Get()->GetColourManager()->GetColour(wxT("editor_highlight_occurrence")));

    stc->IndicatorSetStyle(theIndicator, wxSCI_INDIC_HIGHLIGHT);
    stc->IndicatorSetForeground(theIndicator, highlightColour);
    stc->IndicatorSetUnder(theIndicator, true);

    const int line = stc->LineFromPosition(pos);
    ClTokenPosition loc(line + 1, pos - stc->PositionFromLine(line) + 1);

    std::vector< std::pair<int, int> > occurrences;
    m_pClangPlugin->GetOccurrencesOf( translId,  ed->GetFilename(), loc, 100, occurrences );

    for (std::vector< std::pair<int, int> >::const_iterator tkn = occurrences.begin();
            tkn != occurrences.end(); ++tkn)
    {
        stc->IndicatorFillRange(tkn->first, tkn->second);
    }
}
Example #11
0
// quote the string before writing it to file
static wxString FilterOutValue(const wxString& str)
{
   if ( !str )
      return str;

  wxString strResult;
  strResult.Alloc(str.Len());

  // quoting is necessary to preserve spaces in the beginning of the string
  bool bQuote = wxIsspace(str[0]) || str[0] == wxT('"');

  if ( bQuote )
    strResult += wxT('"');

  wxChar c;
  for ( size_t n = 0; n < str.Len(); n++ ) {
    switch ( str[n] ) {
      case wxT('\n'):
        c = wxT('n');
        break;

      case wxT('\r'):
        c = wxT('r');
        break;

      case wxT('\t'):
        c = wxT('t');
        break;

      case wxT('\\'):
        c = wxT('\\');
        break;

      case wxT('"'):
        if ( bQuote ) {
          c = wxT('"');
          break;
        }
        //else: fall through

      default:
        strResult += str[n];
        continue;   // nothing special to do
    }

    // we get here only for special characters
    strResult << wxT('\\') << c;
  }

  if ( bQuote )
    strResult += wxT('"');

  return strResult;
}
Example #12
0
void
strutil_delwhitespace(String &str)
{
   String newstr = wxEmptyString;

   const wxChar *cptr = str.c_str();
   while(wxIsspace(*cptr))
      cptr++;
   while(*cptr)
      newstr += *cptr++;
   str = newstr;
}
Example #13
0
bool wxPropertyValidator::StringToLong (wxChar *s, long *number) {
    bool ok = true;
    wxChar *value_ptr;
    *number = wxStrtol (s, &value_ptr, 10);
    if (value_ptr) {
        int len = wxStrlen (value_ptr);
        for (int i = 0; i < len; i++) {
            ok = (wxIsspace (value_ptr[i]) != 0);
            if (!ok) return false;
        }
    }
    return ok;
}
void cbStyledTextCtrl::DoBraceCompletion(const wxChar& ch)
{
    const int pos   = GetCurrentPos();
    const int style = GetStyleAt(pos);
    if (IsComment(style) || IsComment(GetStyleAt(pos - 2)))
        return; // do nothing
    if (ch == wxT('\'') || ch == wxT('"'))
    {
        if (GetCharAt(pos) == ch)
        {
            DeleteBack();
            CharRight();
        }
        else if (!IsString(GetStyleAt(pos - 2)) && !IsCharacter(GetStyleAt(pos - 2)))
            InsertText(pos, ch);
        return; // done
    }

    if (IsString(style) || IsCharacter(style))
        return; // do nothing

    const wxString opBraces(wxT("([{")); const int opBraceIdx = opBraces.Find(ch);
    const wxString clBraces(wxT(")]}")); const int clBraceIdx = clBraces.Find(ch);
    if ( (opBraceIdx != wxNOT_FOUND) || (clBraceIdx != wxNOT_FOUND) )
    {
        if ( GetCharAt(pos) == ch )
        {
            DeleteBack();
            CharRight();
        }
        else if (opBraceIdx != wxNOT_FOUND)
        {
            int nextPos = pos;
            while ( wxIsspace(GetCharAt(nextPos)) && (nextPos < GetLength()) )
                ++nextPos;

            if (   ((wxChar)GetCharAt(nextPos) != clBraces[opBraceIdx])
                || (BraceMatch(nextPos)        != wxNOT_FOUND) )
            {
                InsertText(pos, clBraces[opBraceIdx]);
            }
        }
    }
}
Example #15
0
void wxStringTokenizer::SetString(const wxString& str,
                                  const wxString& delims,
                                  wxStringTokenizerMode mode)
{
    if ( mode == wxTOKEN_DEFAULT )
    {
        // by default, we behave like strtok() if the delimiters are only
        // whitespace characters and as wxTOKEN_RET_EMPTY otherwise (for
        // whitespace delimiters, strtok() behaviour is better because we want
        // to count consecutive spaces as one delimiter)
        wxString::const_iterator p;
        for ( p = delims.begin(); p != delims.end(); ++p )
        {
            if ( !wxIsspace(*p) )
                break;
        }

        if ( p != delims.end() )
        {
            // not whitespace char in delims
            mode = wxTOKEN_RET_EMPTY;
        }
        else
        {
            // only whitespaces
            mode = wxTOKEN_STRTOK;
        }
    }

#if wxUSE_UNICODE // FIXME-UTF8: only wc_str()
    m_delims = delims.wc_str();
#else
    m_delims = delims.mb_str();
#endif
    m_delimsLen = delims.length();

    m_mode = mode;

    Reinit(str);
}
Example #16
0
void Compiler::MakeValidID()
{
    // basically, make it XML-element compatible
    // only allow a-z, 0-9 and _
    // (it is already lowercase)
    // any non-conformant character will be removed

    wxString newID;
    if (m_ID.IsEmpty())
        m_ID = m_Name;

    size_t pos = 0;
    while (pos < m_ID.Length())
    {
        wxChar ch = m_ID[pos];
        if (wxIsalnum(ch) || ch == _T('_')) // valid character
            newID.Append(ch);
        else if (wxIsspace(ch)) // convert spaces to underscores
            newID.Append(_T('_'));
        ++pos;
    }

    // make sure it's not starting with a number.
    // if it is, prepend "cb"
    if (wxIsdigit(newID.GetChar(0)))
        newID.Prepend(_T("cb"));

    if (newID.IsEmpty()) // empty? wtf?
        cbThrow(_T("Can't create a valid compiler ID for ") + m_Name);
    m_ID = newID.Lower();

    // check for unique ID
    if (!IsUniqueID(m_ID))
        cbThrow(_T("Compiler ID already exists for ") + m_Name);
    m_CompilerIDs.Add(m_ID);
}
Example #17
0
std::vector<cbCodeCompletionPlugin::CCToken> ClangCodeCompletion::GetAutocompList(bool isAuto, cbEditor* ed, int& tknStart, int& tknEnd)
{
#ifdef CLANGPLUGIN_TRACE_FUNCTIONS
    fprintf(stdout,"%s isAuto=%d\n", __PRETTY_FUNCTION__,(int)isAuto);
#endif
    std::vector<cbCodeCompletionPlugin::CCToken> tokens;

    int CCOutstanding = m_CCOutstanding;
    if ((CCOutstanding > 0)&&(m_CCOutstandingPos != ed->GetControl()->GetCurrentPos()))
    {
        CCOutstanding = 0;
    }

    m_CCOutstanding = 0;
    ClTranslUnitId translUnitId = m_TranslUnitId;
    if( translUnitId != GetCurrentTranslationUnitId() )
        return tokens;
    if (translUnitId == wxNOT_FOUND)
    {
        Manager::Get()->GetLogManager()->LogWarning(wxT("ClangLib: m_TranslUnitId == wxNOT_FOUND, "
                "cannot complete in file ") + ed->GetFilename());
        return tokens;
    }

    cbStyledTextCtrl* stc = ed->GetControl();
    const int style = stc->GetStyleAt(tknEnd);
    const wxChar curChar = stc->GetCharAt(tknEnd - 1);
    if (isAuto) // filter illogical cases of auto-launch
    {
        if ((curChar == wxT(':') // scope operator
                && stc->GetCharAt(tknEnd - 2) != wxT(':') )
                || ( curChar == wxT('>') // '->'
                        && stc->GetCharAt(tknEnd - 2) != wxT('-') )
                || ( wxString(wxT("<\"/")).Find(curChar) != wxNOT_FOUND // #include directive (TODO: enumerate completable include files)
                        && !stc->IsPreprocessor(style)))
        {
            return tokens;
        }
    }

    const int line = stc->LineFromPosition(tknStart);
/*
    std::map<wxString, wxString> unsavedFiles;
    EditorManager* edMgr = Manager::Get()->GetEditorManager();
    for (int i = 0; i < edMgr->GetEditorsCount(); ++i)
    {
        cbEditor* editor = edMgr->GetBuiltinEditor(i);
        if (editor && editor->GetModified())
            unsavedFiles.insert(std::make_pair(editor->GetFilename(), editor->GetControl()->GetText()));
    }
*/
    const int lnStart = stc->PositionFromLine(line);
    int column = tknStart - lnStart;
    for (; column > 0; --column)
    {
        if (!wxIsspace(stc->GetCharAt(lnStart + column - 1))
                || (column != 1 && !wxIsspace(stc->GetCharAt(lnStart + column - 2))))
        {
            break;
        }
    }

    const wxString& prefix = stc->GetTextRange(tknStart, tknEnd).Lower();
    bool includeCtors = true; // sometimes we get a lot of these
    for (int i = tknStart - 1; i > 0; --i)
    {
        wxChar chr = stc->GetCharAt(i);
        if (!wxIsspace(chr))
        {
            if (chr == wxT(';') || chr == wxT('}')) // last non-whitespace character
                includeCtors = false; // filter out ctors (they are unlikely to be wanted in this situation)
            break;
        }
    }

    std::vector<ClToken> tknResults;
    if ((CCOutstanding == 0)||(m_CCOutstandingResults.size()==0))
    {
        ClTokenPosition loc(line+1, column+1);
        //ClangProxy::CodeCompleteAtJob job( cbEVT_CLANG_SYNCTASK_FINISHED, idClangCodeCompleteTask, isAuto, ed->GetFilename(), loc, m_TranslUnitId, unsavedFiles);
        //m_Proxy.AppendPendingJob(job);
        unsigned long timeout = 40;
        if( !isAuto )
        {
            timeout = 500;
        }
        if( wxCOND_TIMEOUT == m_pClangPlugin->GetCodeCompletionAt(translUnitId, ed->GetFilename(), loc, timeout, tknResults))
        {
            if (wxGetLocalTime() - m_CCOutstandingLastMessageTime > 10)
            {
                //InfoWindow::Display(_("Code completion"), _("Busy parsing the document"), 1000);
                m_CCOutstandingLastMessageTime = wxGetLocalTime();
            }
            //std::cout<<"Timeout waiting for code completion"<<std::endl;
            m_CCOutstanding++;
            m_CCOutstandingPos = ed->GetControl()->GetCurrentPos();
            m_CCOutstandingResults.clear();
            return tokens;
        }
    }
    else
    {
        tknResults = m_CCOutstandingResults;
    }

    //m_Proxy.CodeCompleteAt(isAuto, ed->GetFilename(), line + 1, column + 1,
    //        m_TranslUnitId, unsavedFiles, tknResults);
    if (prefix.Length() > 3) // larger context, match the prefix at any point in the token
    {
        for (std::vector<ClToken>::const_iterator tknIt = tknResults.begin();
                tknIt != tknResults.end(); ++tknIt)
        {
            if (tknIt->name.Lower().Find(prefix) != wxNOT_FOUND && (includeCtors || tknIt->category != tcCtorPublic))
                tokens.push_back(cbCodeCompletionPlugin::CCToken(tknIt->id, tknIt->name, tknIt->name, tknIt->weight, tknIt->category));
        }
    }
    else if (prefix.IsEmpty())
    {
        for (std::vector<ClToken>::const_iterator tknIt = tknResults.begin();
                tknIt != tknResults.end(); ++tknIt)
        {
            // it is rather unlikely for an operator to be the desired completion
            if (!tknIt->name.StartsWith(wxT("operator")) && (includeCtors || tknIt->category != tcCtorPublic))
                tokens.push_back(cbCodeCompletionPlugin::CCToken(tknIt->id, tknIt->name, tknIt->name, tknIt->weight, tknIt->category));
        }
    }
    else // smaller context, only allow matches of the prefix at the beginning of the token
    {
        for (std::vector<ClToken>::const_iterator tknIt = tknResults.begin();
                tknIt != tknResults.end(); ++tknIt)
        {
            if (tknIt->name.Lower().StartsWith(prefix) && (includeCtors || tknIt->category != tcCtorPublic))
                tokens.push_back(cbCodeCompletionPlugin::CCToken(tknIt->id, tknIt->name, tknIt->name, tknIt->weight, tknIt->category));
        }
    }

    if (!tokens.empty())
    {
        if (prefix.IsEmpty() && tokens.size() > 1500) // reduce to give only top matches
        {
            std::partial_sort(tokens.begin(), tokens.begin() + 1000, tokens.end(), PrioritySorter());
            tokens.erase(tokens.begin() + 1000, tokens.end());
        }
        const int imgCount = m_pClangPlugin->GetImageList(translUnitId).GetImageCount();
        for (int i = 0; i < imgCount; ++i)
            stc->RegisterImage(i, m_pClangPlugin->GetImageList(translUnitId).GetBitmap(i));
        bool isPP = stc->GetLine(line).Strip(wxString::leading).StartsWith(wxT("#"));
        std::set<int> usedWeights;
        for (std::vector<cbCodeCompletionPlugin::CCToken>::iterator tknIt = tokens.begin();
                tknIt != tokens.end(); ++tknIt)
        {
            wxStringVec keywords = m_pClangPlugin->GetKeywords(translUnitId);
            usedWeights.insert(tknIt->weight);
            switch (tknIt->category)
            {
            case tcNone:
                if (isPP)
                    tknIt->category = tcMacroDef;
                else if (std::binary_search(keywords.begin(), keywords.end(), GetActualName(tknIt->name)))
                    tknIt->category = tcLangKeyword;
                break;

            case tcClass:
            case tcCtorPublic:
            case tcDtorPublic:
            case tcFuncPublic:
            case tcVarPublic:
            case tcEnum:
            case tcTypedef:
                // TODO
                //m_Proxy.RefineTokenType(m_TranslUnitId, tknIt->id, tknIt->category);
                break;

            default:
                break;
            }
        }
        // Clang sometimes gives many weight values, which can make completion more difficult
        // because results are less alphabetical. Use a compression map on the lower priority
        // values (higher numbers) to reduce the total number of weights used.
        if (usedWeights.size() > 3)
        {
            std::vector<int> weightsVec(usedWeights.begin(), usedWeights.end());
            std::map<int, int> weightCompr;
            weightCompr[weightsVec[0]] = weightsVec[0];
            weightCompr[weightsVec[1]] = weightsVec[1];
            int factor = (weightsVec.size() > 7 ? 3 : 2);
            for (size_t i = 2; i < weightsVec.size(); ++i)
                weightCompr[weightsVec[i]] = weightsVec[(i - 2) / factor + 2];
            for (std::vector<cbCodeCompletionPlugin::CCToken>::iterator tknIt = tokens.begin();
                    tknIt != tokens.end(); ++tknIt)
            {
                tknIt->weight = weightCompr[tknIt->weight];
            }
        }
    }

    std::cout<<"CodeCompletion finished"<<std::endl;
    return tokens;
}
// cbEVT_SHOW_CALL_TIP
void CCManager::OnShowCallTip(CodeBlocksEvent& event)
{
    event.Skip();

    cbEditor* ed = Manager::Get()->GetEditorManager()->GetBuiltinActiveEditor();
    if (!ed)
        return;
    cbCodeCompletionPlugin* ccPlugin = GetProviderFor(ed);
    if (!ccPlugin)
        return;

    cbStyledTextCtrl* stc = ed->GetControl();
    int pos = stc->GetCurrentPos();
    int argsPos = wxSCI_INVALID_POSITION;
    wxString curTip;
    if (!m_CallTips.empty())
        curTip = m_CurCallTip->tip;
    m_CallTips = ccPlugin->GetCallTips(pos, stc->GetStyleAt(pos), ed, argsPos);
    if (!m_CallTips.empty() && (event.GetInt() != FROM_TIMER || argsPos == m_CallTipActive))
    {
        int lnStart = stc->PositionFromLine(stc->LineFromPosition(pos));
        while (wxIsspace(stc->GetCharAt(lnStart)))
            ++lnStart; // do not show too far left on multi-line call tips
        if (   m_CallTips.size() > 1
            && !Manager::Get()->GetConfigManager(wxT("ccmanager"))->ReadBool(wxT("multi_page_tips"), true) )
        {
            wxString tip;
            int hlStart, hlEnd;
            hlStart = hlEnd = wxSCI_INVALID_POSITION;
            for (CallTipVec::const_iterator itr = m_CallTips.begin();
                 itr != m_CallTips.end(); ++itr)
            {
                if (hlStart == hlEnd && itr->hlStart != itr->hlEnd)
                {
                    hlStart = tip.Length() + itr->hlStart;
                    hlEnd   = tip.Length() + itr->hlEnd;
                }
                tip += itr->tip + wxT('\n');
            }
            m_CallTips.clear();
            m_CallTips.push_back(cbCodeCompletionPlugin::CCCallTip(tip.RemoveLast(), hlStart, hlEnd));
        }
        m_CurCallTip = m_CallTips.begin();
        if (m_CallTips.size() > 1)
        {
            // search long term recall
            std::map<int, size_t>::const_iterator choiceItr =
                m_CallTipChoiceDict.find(CCManagerHelper::CallTipToInt(m_CurCallTip->tip, m_CallTips.size()));
            if (choiceItr != m_CallTipChoiceDict.end() && choiceItr->second < m_CallTips.size())
                m_CurCallTip = m_CallTips.begin() + choiceItr->second;
            if (choiceItr == m_CallTipChoiceDict.end() || argsPos == m_CallTipActive)
            {
                int prefixEndPos = argsPos;
                while (prefixEndPos > 0 && wxIsspace(stc->GetCharAt(prefixEndPos - 1)))
                    --prefixEndPos;
                const wxString& prefix = stc->GetTextRange(stc->WordStartPosition(prefixEndPos, true), prefixEndPos);
                choiceItr = m_CallTipFuzzyChoiceDict.find(CCManagerHelper::CallTipToInt(prefix, m_CallTips.size()));
                if (choiceItr != m_CallTipFuzzyChoiceDict.end() && choiceItr->second < m_CallTips.size())
                    m_CurCallTip = m_CallTips.begin() + choiceItr->second;
            }
            // search short term recall
            for (CallTipVec::const_iterator itr = m_CallTips.begin();
                 itr != m_CallTips.end(); ++itr)
            {
                if (itr->tip == curTip)
                {
                    m_CurCallTip = itr;
                    break;
                }
            }
        }
        m_CallTipActive = argsPos;
        DoUpdateCallTip(ed);
    }
    else if (m_CallTipActive != wxSCI_INVALID_POSITION)
    {
        static_cast<wxScintilla*>(stc)->CallTipCancel();
        m_CallTipActive = wxSCI_INVALID_POSITION;
    }
}
wxInt32 NaturalCompare(wxString String1, wxString String2, bool CaseSensitive = false)
{
    wxInt32 StringCounter1 = 0, StringCounter2 = 0;
    wxInt32 String1Zeroes = 0, String2Zeroes = 0;
    wxChar String1Char, String2Char;
    wxInt32 Result;

    if (!CaseSensitive)
    {
        String1.MakeLower();
        String2.MakeLower();
    }

    while (true)
    {
        String1Zeroes = 0;
        String2Zeroes = 0;

        String1Char = String1[StringCounter1];
        String2Char = String2[StringCounter2];

        // skip past whitespace or zeroes in first string
        while (wxIsspace(String1Char) || String1Char == '0' )
        {
            if (String1Char == '0')
            {
                String1Zeroes++;
            }
            else
            {
                String1Zeroes = 0;
            }

            String1Char = String1[++StringCounter1];
        }

        // skip past whitespace or zeroes in second string
        while (wxIsspace(String2Char) || String2Char == '0')
        {
            if (String2Char == '0')
            {
                String2Zeroes++;
            }
            else
            {
                String2Zeroes = 0;
            }

            String2Char = String2[++StringCounter2];
        }

        // We encountered some digits, compare these.
        if (wxIsdigit(String1Char) && wxIsdigit(String2Char))
        {
            if ((Result = NaturalCompareWorker(
                              String1.Mid(StringCounter1),
                              String2.Mid(StringCounter2))) != 0)
            {
                return Result;
            }
        }

        if ((String1Char == 0) && (String2Char == 0))
        {
            return (String1Zeroes - String2Zeroes);
        }

        if (String1Char < String2Char)
        {
            return -1;
        }
        else if (String1Char > String2Char)
        {
            return 1;
        }

        ++StringCounter1;
        ++StringCounter2;
    }
}
Example #20
0
int URLDetector::FindURL(const wxChar *text, int& len)
{
   // offset of the current value of text from the initial one
   int offset = 0;

match:
   int pos = scan(text, len);
   if ( !len )
      return -1;

   // the provisional start and end of the URL, will be changed below
   const wxChar *start = text + pos;
   const wxChar *p = start + len;

   // there are 2 different cases: a mailto: URL or a mail address and
   // anything else which we need to treat differently
   bool isMail = *start == '@';

   if ( isMail )
   {
      // look for the start of the address
      start--;
      while ( start > text && IsLocalPartChar(*start) )
         start--;

      // have we stopped at '<'?
      bool hasAngleBracket = *start == '<';
      if ( !hasAngleBracket )
      {
         if ( !IsLocalPartChar(*start) )
         {
            // we went too far backwards
            start++;
         }
         //else: we stopped at the start of the text
      }
      //else: keep '<' as part of the URL

      // now look for the end of it
      while ( *p && IsDomainChar(*p) )
      {
         p++;
      }

      // finally we should either have the brackets from both sides or none
      // at all
      if ( hasAngleBracket )
      {
         if ( *p == '>' )
         {
            // take the right bracket as well
            p++;
         }
         else
         {
            // forget about the left one
            start++;
         }
      }
   }
   else // !bare mail address
   {
      for ( ;; )
      {
         size_t lenURL = 0;
         while ( IsURLChar(*p) )
         {
            lenURL++;
            p++;
         }

         // URLs are frequently so long that they're spread across multiple
         // lines, so try to see if this might be the case here
         //
         // first of all we need to check whether it is at the end of line but
         // we should allow some trailing spaces
         const wxChar* q = p;
         while ( *q == ' ' )
            q++;

         if ( q[0] != '\r' || q[1] != '\n' )
            break; // not at the line end

         // also check if it's really long enough to be wrapped:
         // the short URLs normally shouldn't be wrapped
         static const size_t URL_WRAP_LEN = 30; // min len of wrapped URL
         if ( lenURL < URL_WRAP_LEN )
            break; // too short

         if ( !IsURLChar(q[2]) )
            break; // doesn't seem to be continued on the next line

         // heuristic text for end of URL detection
         if ( p - start > 5 && !CanBeWrapped(p) )
         {
            // it seems that the URL ends here
            break;
         }

         p = q + 2; // go to the start of next line

         // Check that the beginning of next line is not the start of
         // another URL.
         //
         // Note that although '@' alone is recognized as the beginning
         // of an URL: here it should not be the case.
         int nextlen = 0;
         int nextpos = scan(p, nextlen);
         if ( nextlen && nextpos == 0 && *p != '@')
         {
            p -= 2;

            // The start of the next line being the start of an URL on its own,
            // do not join the two.
            break;
         }

         // check whether the next line starts with a word -- this is a good
         // indication that the URL hasn't wrapped
         q = p;
         while ( wxIsalpha(*q) )
            q++;

         if ( *q == _T(' ') || (wxStrchr(_T(".,:;"), *q) && q[1] == _T(' ')) )
         {
            // looks like we've a word (i.e. sequence of letters terminated by
            // space or punctuation) at the start of the next line
            p -= 2;
            break;
         }

         // another special case: subsequent dashes are very unusual in URLs
         // but often used as separator lines, so we assume that they indicate
         // the end of the URL if we find them on the next line.
         if ( p[0] == '-' && p[1] == '-' )
            break;

         // it might be a wrapped URL but it might be not: it seems like we
         // get way too many false positives if we suppose that it's always
         // the case... so restrict the wrapped URLs detection to the case
         // when they occur at the beginning of the line, possibly after some
         // white space as this is how people usually format them
         q = start;
         while ( q >= text && *q != '\n' )
         {
            q--;

            if ( !wxIsspace(*q) )
               break;
         }

         // Does the URL start at the beginning of the line, or does it have
         // a '<' just in front?
         if ( q >= text && *q != '\n' && *q != '<')
            break;

         // it did occur at the start (or after '<'), suppose the URL is
         // wrapped and so we continue on the next line (and no need to test
         // the first character, it had been already done above)
         p++;
      }
   }

   // truncate any punctuation at the end
   while ( strchr(".:,)]!?", *(p - 1)) )
      p--;

   // additional checks for the matches which didn't have an explicit scheme
   if ( isMail || text[pos + len - 3 /* len of "://" */ ] != _T(':') )
   {
      // '@' matches may result in false positives, as not every '@' character
      // is inside a mailto URL so try to weed them out by requiring that the
      // mail address has a reasonable minimal length ("*****@*****.**" and
      // "www.xy.fr" are probably the shortest ones we can have, hence 8)
      // which at least avoids matching the bare '@'s
      bool good = (p - start) >= 8;

      if ( good )
      {
         // also check that we have at least one dot in the domain part for the
         // mail addresses
         const wxChar *
            pDot = wxTmemchr(text + pos + 1, '.', p - text - pos - 1);
         if ( !pDot )
         {
            good = false;
         }
         else if ( !isMail )
         {
            // and has either two dots or at least a slash the other URLs,
            // otherwise it probably isn't an address/URL neither (stuff like
            // "... using ftp.If you ... " shouldn't be recognized as an URL)
            good = wxTmemchr(pDot + 1, '.', p - pDot - 1) != NULL ||
                     wxTmemchr(pDot + 1, '/', p - pDot - 1) != NULL;
         }
      }

      if ( !good )
      {
         const int offDiff = pos + len;
         offset += offDiff;
         text += offDiff;

         // slightly more efficient than recursion...
         goto match;
      }
   }

   // return the length of the match
   len = p - start;

   return start - text + offset;
}
Example #21
0
std::vector<ClangPlugin::CCToken> ClangPlugin::GetAutocompList(bool isAuto, cbEditor* ed, int& tknStart, int& tknEnd)
{
    std::vector<CCToken> tokens;
    if (ed != m_pLastEditor)
    {
        m_TranslUnitId = m_Proxy.GetTranslationUnitId(ed->GetFilename());
        m_pLastEditor = ed;
    }
    if (m_TranslUnitId == wxNOT_FOUND)
    {
        Manager::Get()->GetLogManager()->LogWarning(wxT("ClangLib: m_TranslUnitId == wxNOT_FOUND, cannot complete in file ") + ed->GetFilename());
        return tokens;
    }

    cbStyledTextCtrl* stc = ed->GetControl();
    const int style = stc->GetStyleAt(tknEnd);
    const wxChar curChar = stc->GetCharAt(tknEnd - 1);
    if (isAuto) // filter illogical cases of auto-launch
    {
        if (   (   curChar == wxT(':') // scope operator
                && stc->GetCharAt(tknEnd - 2) != wxT(':') )
            || (   curChar == wxT('>') // '->'
                && stc->GetCharAt(tknEnd - 2) != wxT('-') )
            || (   wxString(wxT("<\"/")).Find(curChar) != wxNOT_FOUND // #include directive (TODO: enumerate completable include files)
                && !stc->IsPreprocessor(style) ) )
        {
            return tokens;
        }
    }

    std::vector<ClToken> tknResults;
    const int line = stc->LineFromPosition(tknStart);
    std::map<wxString, wxString> unsavedFiles;
    EditorManager* edMgr = Manager::Get()->GetEditorManager();
    for (int i = 0; i < edMgr->GetEditorsCount(); ++i)
    {
        cbEditor* editor = edMgr->GetBuiltinEditor(i);
        if (editor && editor->GetModified())
            unsavedFiles.insert(std::make_pair(editor->GetFilename(), editor->GetControl()->GetText()));
    }
    const int lnStart = stc->PositionFromLine(line);
    int column = tknStart - lnStart;
    for (; column > 0; --column)
    {
        if (   !wxIsspace(stc->GetCharAt(lnStart + column - 1))
            || (column != 1 && !wxIsspace(stc->GetCharAt(lnStart + column - 2))) )
        {
            break;
        }
    }
    m_Proxy.CodeCompleteAt(isAuto, ed->GetFilename(), line + 1, column + 1, m_TranslUnitId, unsavedFiles, tknResults);
    const wxString& prefix = stc->GetTextRange(tknStart, tknEnd).Lower();
    bool includeCtors = true; // sometimes we get a lot of these
    for (int i = tknStart - 1; i > 0; --i)
    {
        wxChar chr = stc->GetCharAt(i);
        if (!wxIsspace(chr))
        {
            if (chr == wxT(';') || chr == wxT('}')) // last non-whitespace character
                includeCtors = false; // filter out ctors (they are unlikely to be wanted in this situation)
            break;
        }
    }
    if (prefix.Length() > 3) // larger context, match the prefix at any point in the token
    {
        for (std::vector<ClToken>::const_iterator tknIt = tknResults.begin();
             tknIt != tknResults.end(); ++tknIt)
        {
            if (tknIt->name.Lower().Find(prefix) != wxNOT_FOUND && (includeCtors || tknIt->category != tcCtorPublic))
                tokens.push_back(CCToken(tknIt->id, tknIt->name, tknIt->name, tknIt->weight, tknIt->category));
        }
    }
    else if (prefix.IsEmpty())
    {
        for (std::vector<ClToken>::const_iterator tknIt = tknResults.begin();
             tknIt != tknResults.end(); ++tknIt)
        {
            if (!tknIt->name.StartsWith(wxT("operator")) && (includeCtors || tknIt->category != tcCtorPublic)) // it is rather unlikely for an operator to be the desired completion
                tokens.push_back(CCToken(tknIt->id, tknIt->name, tknIt->name, tknIt->weight, tknIt->category));
        }
    }
    else // smaller context, only allow matches of the prefix at the beginning of the token
    {
        for (std::vector<ClToken>::const_iterator tknIt = tknResults.begin();
             tknIt != tknResults.end(); ++tknIt)
        {
            if (tknIt->name.Lower().StartsWith(prefix) && (includeCtors || tknIt->category != tcCtorPublic))
                tokens.push_back(CCToken(tknIt->id, tknIt->name, tknIt->name, tknIt->weight, tknIt->category));
        }
    }

    if (!tokens.empty())
    {
        if (prefix.IsEmpty() && tokens.size() > 1500) // reduce to give only top matches
        {
            std::partial_sort(tokens.begin(), tokens.begin() + 1000, tokens.end(), PrioritySorter());
            tokens.erase(tokens.begin() + 1000, tokens.end());
        }
        const int imgCount = m_ImageList.GetImageCount();
        for (int i = 0; i < imgCount; ++i)
            stc->RegisterImage(i, m_ImageList.GetBitmap(i));
        bool isPP = stc->GetLine(line).Strip(wxString::leading).StartsWith(wxT("#"));
        std::set<int> usedWeights;
        for (std::vector<CCToken>::iterator tknIt = tokens.begin();
             tknIt != tokens.end(); ++tknIt)
        {
            usedWeights.insert(tknIt->weight);
            switch (tknIt->category)
            {
                case tcNone:
                    if (isPP)
                        tknIt->category = tcMacroDef;
                    else if (std::binary_search(m_CppKeywords.begin(), m_CppKeywords.end(), GetActualName(tknIt->name)))
                        tknIt->category = tcLangKeyword;
                    break;

                case tcClass:
                case tcCtorPublic:
                case tcDtorPublic:
                case tcFuncPublic:
                case tcVarPublic:
                case tcEnum:
                case tcTypedef:
                    m_Proxy.RefineTokenType(m_TranslUnitId, tknIt->id, tknIt->category);
                    break;

                default:
                    break;
            }
        }
        // Clang sometimes gives many weight values, which can make completion more difficult
        // because results are less alphabetical. Use a compression map on the lower priority
        // values (higher numbers) to reduce the total number of weights used.
        if (usedWeights.size() > 3)
        {
            std::vector<int> weightsVec(usedWeights.begin(), usedWeights.end());
            std::map<int, int> weightCompr;
            weightCompr[weightsVec[0]] = weightsVec[0];
            weightCompr[weightsVec[1]] = weightsVec[1];
            int factor = (weightsVec.size() > 7 ? 3 : 2);
            for (size_t i = 2; i < weightsVec.size(); ++i)
                weightCompr[weightsVec[i]] = weightsVec[(i - 2) / factor + 2];
            for (std::vector<CCToken>::iterator tknIt = tokens.begin();
                 tknIt != tokens.end(); ++tknIt)
            {
                tknIt->weight = weightCompr[tknIt->weight];
            }
        }
    }

    return tokens;
}
Example #22
0
bool EffectNyquist::PromptUser()
{
   if (!SetXlispPath()) {
      return false;
   }

   if (mInteractive) {
      NyquistInputDialog dlog(wxGetTopLevelParent(NULL), -1,
                              _("Nyquist Prompt"),
                              _("Enter Nyquist Command: "),
                              mInputCmd);
      dlog.CentreOnParent();
      int result = dlog.ShowModal();

      if (result == wxID_CANCEL) {
         return false;
      }

      /*if (result == eDebugID) {
         mDebug = true;
      }*/
      mDebug = (result == eDebugID);

      // remember exact input in mInputCmd which will appear in the next
      // NyquistInputDialog. Copy to mCmd for possible embedding in
      // "function main() begin ... end":
      mCmd = mInputCmd = dlog.GetCommand();

      // Is this LISP or SAL? Both allow comments. After comments, LISP
      // must begin with "(". Technically, a LISP expression could be a
      // symbol or number or string, etc., but these are not really 
      // useful expressions. If the input begins with a symbol, number,
      // or string, etc., it is more likely an erroneous attempt to type
      // a SAL expression (which should probably begin with "return"),
      // so we will treat it as SAL.

      // this is a state machine to scan past LISP comments and white
      // space to find the first real character of LISP or SAL. Note
      // that #| ... |# style comments are not valid in SAL, so we do
      // not skip these. Instead, "#|" indicates LISP if found.
      //
      unsigned int i = 0;
      bool inComment = false; // handle "; ... \n" comments
      while (i < mCmd.Len()) {
         if (inComment) {
            inComment = (mCmd[i] != wxT('\n'));
         } else if (mCmd[i] == wxT(';')) {
            inComment = true;
         } else if (!wxIsspace(mCmd[i])) { 
            break; // found the first non-comment, non-space character
         }
         i++;
      }

      // invariant: i == mCmd.Len() | 
      //            mCmd[i] is first non-comment, non-space character
      
      mIsSal = false;
      if (mCmd.Len() > i && mCmd[i] != wxT('(') && 
          (mCmd[i] != wxT('#') || mCmd.Len() <= i + 1 ||
           mCmd[i + 1] != wxT('|'))) {
         mIsSal = true;
         wxString cmdUp = mCmd.Upper();
         int returnLoc = cmdUp.Find(wxT("RETURN"));
         if (returnLoc == wxNOT_FOUND) {
            wxMessageBox(_("Your code looks like SAL syntax, but there is no return statement. Either use a return statement such as\n\treturn s * 0.1\nfor SAL, or begin with an open parenthesis such as\n\t(mult s 0.1)\n for LISP."), _("Error in Nyquist code"), wxOK | wxCENTRE);
            return false;
         }
      }

      return true;
   }

   if (!mExternal) {
      if (mFileName.GetModificationTime().IsLaterThan(mFileModified)) {
         ParseFile();
         mFileModified = mFileName.GetModificationTime();
      }
   }

   if (mControls.GetCount() == 0) {
      return true;
   }

   for (unsigned int i = 0; i < mControls.GetCount(); i++) {
      NyqControl *ctrl = &mControls[i];

      if (ctrl->type == NYQ_CTRL_STRING) {
         continue;
      }

      if (ctrl->val == UNINITIALIZED_CONTROL) {
         ctrl->val = GetCtrlValue(ctrl->valStr);
      }

      if (ctrl->type == NYQ_CTRL_CHOICE) {
         continue;
      }
      
      ctrl->low = GetCtrlValue(ctrl->lowStr);
      ctrl->high = GetCtrlValue(ctrl->highStr);

      if (ctrl->high < ctrl->low) {
         ctrl->high = ctrl->low + 1;
      }

      if (ctrl->val < ctrl->low) {
         ctrl->val = ctrl->low;
      }

      if (ctrl->val > ctrl->high) {
         ctrl->val = ctrl->high;
      }

      ctrl->ticks = 1000;
      if (ctrl->type == NYQ_CTRL_INT &&
          (ctrl->high - ctrl->low < ctrl->ticks)) {
         ctrl->ticks = (int)(ctrl->high - ctrl->low);
      }
   }

   NyquistDialog dlog(mParent, -1, mName, mInfo, &mControls);
   dlog.CentreOnParent();
   int result = dlog.ShowModal();

   if (result == wxID_CANCEL) {
      return false;
   }
   
   /* if (result == eDebugID) {
      mDebug = true;
   } */
   mDebug = (result == eDebugID);

   return true;
}
Example #23
0
wxHtmlTagsCache::wxHtmlTagsCache(const wxString& source)
{
    m_Cache = new wxHtmlTagsCacheData;
    m_CachePos = 0;

    wxChar tagBuffer[256];

    const wxString::const_iterator end = source.end();
    for ( wxString::const_iterator pos = source.begin(); pos < end; ++pos )
    {
        if (*pos != wxT('<'))
            continue;

        // possible tag start found:

        // don't cache comment tags
        if ( wxHtmlParser::SkipCommentTag(pos, end) )
            continue;

        // Remember the starting tag position.
        wxString::const_iterator stpos = pos++;

        // And look for the ending one.
        int i;
        for ( i = 0;
              pos < end && i < (int)WXSIZEOF(tagBuffer) - 1 &&
              *pos != wxT('>') && !wxIsspace(*pos);
              ++i, ++pos )
        {
            tagBuffer[i] = (wxChar)wxToupper(*pos);
        }
        tagBuffer[i] = wxT('\0');

        while (pos < end && *pos != wxT('>'))
            ++pos;

        if ( pos == end )
        {
            // We didn't find a closing bracket, this is not a valid tag after
            // all. Notice that we need to roll back pos to avoid creating an
            // invalid iterator when "++pos" is done in the loop statement.
            --pos;

            continue;
        }

        // We have a valid tag, add it to the cache.
        size_t tg = Cache().size();
        Cache().push_back(wxHtmlCacheItem());
        Cache()[tg].Key = stpos;
        Cache()[tg].Name = new wxChar[i+1];
        memcpy(Cache()[tg].Name, tagBuffer, (i+1)*sizeof(wxChar));

        if ((stpos+1) < end && *(stpos+1) == wxT('/')) // ending tag:
        {
            Cache()[tg].type = wxHtmlCacheItem::Type_EndingTag;
            // find matching begin tag:
            for (i = tg; i >= 0; i--)
            {
                if ((Cache()[i].type == wxHtmlCacheItem::Type_NoMatchingEndingTag) && (wxStrcmp(Cache()[i].Name, tagBuffer+1) == 0))
                {
                    Cache()[i].type = wxHtmlCacheItem::Type_Normal;
                    Cache()[i].End1 = stpos;
                    Cache()[i].End2 = pos + 1;
                    break;
                }
            }
        }
        else
        {
            Cache()[tg].type = wxHtmlCacheItem::Type_NoMatchingEndingTag;

            if (wxIsCDATAElement(tagBuffer))
            {
                // store the orig pos in case we are missing the closing
                // tag (see below)
                const wxString::const_iterator old_pos = pos;
                bool foundCloseTag = false;

                // find next matching tag
                int tag_len = wxStrlen(tagBuffer);
                while (pos < end)
                {
                    // find the ending tag
                    while (pos + 1 < end &&
                           (*pos != '<' || *(pos+1) != '/'))
                        ++pos;
                    if (*pos == '<')
                        ++pos;

                    // see if it matches
                    int match_pos = 0;
                    while (pos < end && match_pos < tag_len )
                    {
                        wxChar c = *pos;
                        if ( c == '>' || c == '<' )
                            break;

                        // cast to wxChar needed to suppress warning in
                        // Unicode build
                        if ((wxChar)wxToupper(c) == tagBuffer[match_pos])
                        {
                            ++match_pos;
                        }
                        else if (c == wxT(' ') || c == wxT('\n') ||
                            c == wxT('\r') || c == wxT('\t'))
                        {
                            // need to skip over these
                        }
                        else
                        {
                            match_pos = 0;
                        }
                        ++pos;
                    }

                    // found a match
                    if (match_pos == tag_len)
                    {
                        pos = pos - tag_len - 3;
                        foundCloseTag = true;
                        break;
                    }
                    else // keep looking for the closing tag
                    {
                        ++pos;
                    }
                }
                if (!foundCloseTag)
                {
                    // we didn't find closing tag; this means the markup
                    // is incorrect and the best thing we can do is to
                    // ignore the unclosed tag and continue parsing as if
                    // it didn't exist:
                    pos = old_pos;
                }
            }
        }
    }

    // ok, we're done, now we'll free .Name members of cache - we don't need it anymore:
    for ( wxHtmlTagsCacheData::iterator i = Cache().begin();
          i != Cache().end(); ++i )
    {
        wxDELETEA(i->Name);
    }
}
long wxExecute( const wxString& command, int flags, wxProcess *process )
{
    wxCHECK_MSG( !command.empty(), 0, wxT("can't exec empty command") );
    wxLogDebug(wxString(wxT("Launching: ")) + command);

#if wxUSE_THREADS
    // fork() doesn't mix well with POSIX threads: on many systems the program
    // deadlocks or crashes for some reason. Probably our code is buggy and
    // doesn't do something which must be done to allow this to work, but I
    // don't know what yet, so for now just warn the user (this is the least we
    // can do) about it
    wxASSERT_MSG( wxThread::IsMain(),
                    _T("wxExecute() can be called only from the main thread") );
#endif // wxUSE_THREADS

    int argc = 0;
    wxChar *argv[WXEXECUTE_NARGS];
    wxString argument;
    const wxChar *cptr = command.c_str();
    wxChar quotechar = wxT('\0'); // is arg quoted?
    bool escaped = false;

    // split the command line in arguments
    do
    {
        argument=wxT("");
        quotechar = wxT('\0');

        // eat leading whitespace:
        while ( wxIsspace(*cptr) )
            cptr++;

        if ( *cptr == wxT('\'') || *cptr == wxT('"') )
            quotechar = *cptr++;

        do
        {
            if ( *cptr == wxT('\\') && ! escaped )
            {
                escaped = true;
                cptr++;
                continue;
            }

            // all other characters:
            argument += *cptr++;
            escaped = false;

            // have we reached the end of the argument?
            if ( (*cptr == quotechar && ! escaped)
                 || (quotechar == wxT('\0') && wxIsspace(*cptr))
                 || *cptr == wxT('\0') )
            {
                wxASSERT_MSG( argc < WXEXECUTE_NARGS,
                              wxT("too many arguments in wxExecute") );

                argv[argc] = new wxChar[argument.length() + 1];
                wxStrcpy(argv[argc], argument.c_str());
                argc++;

                // if not at end of buffer, swallow last character:
                if(*cptr)
                    cptr++;

                break; // done with this one, start over
            }
        } while(*cptr);
    } while(*cptr);
    argv[argc] = NULL;

    long lRc;
#if defined(__DARWIN__)
    // wxMacExecute only executes app bundles.
    // It returns an error code if the target is not an app bundle, thus falling
    // through to the regular wxExecute for non app bundles.
    lRc = wxMacExecute(argv, flags, process);
    if( lRc != ((flags & wxEXEC_SYNC) ? -1 : 0))
        return lRc;
#endif

    // do execute the command
    lRc = wxExecute(argv, flags, process);

    // clean up
    argc = 0;
    while( argv[argc] )
        delete [] argv[argc++];

    return lRc;
}
Example #25
0
wx28HtmlTagsCache::wx28HtmlTagsCache(const wxString& source)
{
    const wxChar *src = source.c_str();
    int lng = source.length();
    wxChar tagBuffer[256];

    m_Cache = NULL;
    m_CacheSize = 0;
    m_CachePos = 0;

    int pos = 0;
    while (pos < lng)
    {
        if (src[pos] == wxT('<'))   // tag found:
        {
            if (m_CacheSize % CACHE_INCREMENT == 0)
                m_Cache = (wx28HtmlCacheItem*) realloc(m_Cache, (m_CacheSize + CACHE_INCREMENT) * sizeof(wx28HtmlCacheItem));
            int tg = m_CacheSize++;
            int stpos = pos++;
            m_Cache[tg].Key = stpos;

            int i;
            for ( i = 0;
                  pos < lng && i < (int)WXSIZEOF(tagBuffer) - 1 &&
                  src[pos] != wxT('>') && !wxIsspace(src[pos]);
                  i++, pos++ )
            {
                tagBuffer[i] = (wxChar)wxToupper(src[pos]);
            }
            tagBuffer[i] = wxT('\0');

            m_Cache[tg].Name = new wxChar[i+1];
            memcpy(m_Cache[tg].Name, tagBuffer, (i+1)*sizeof(wxChar));

            while (pos < lng && src[pos] != wxT('>')) pos++;

            if (src[stpos+1] == wxT('/')) // ending tag:
            {
                m_Cache[tg].End1 = m_Cache[tg].End2 = -2;
                // find matching begin tag:
                for (i = tg; i >= 0; i--)
                    if ((m_Cache[i].End1 == -1) && (wxStrcmp(m_Cache[i].Name, tagBuffer+1) == 0))
                    {
                        m_Cache[i].End1 = stpos;
                        m_Cache[i].End2 = pos + 1;
                        break;
                    }
            }
            else
            {
                m_Cache[tg].End1 = m_Cache[tg].End2 = -1;

                if (wxIsCDATAElement(tagBuffer))
                {
                    // store the orig pos in case we are missing the closing
                    // tag (see below)
                    wxInt32 old_pos = pos;
                    bool foundCloseTag = false;

                    // find next matching tag
                    int tag_len = wxStrlen(tagBuffer);
                    while (pos < lng)
                    {
                        // find the ending tag
                        while (pos + 1 < lng &&
                               (src[pos] != '<' || src[pos+1] != '/'))
                            ++pos;
                        if (src[pos] == '<')
                            ++pos;

                        // see if it matches
                        int match_pos = 0;
                        while (pos < lng && match_pos < tag_len && src[pos] != '>' && src[pos] != '<') {
                            // cast to wxChar needed to suppress warning in
                            // Unicode build
                            if ((wxChar)wxToupper(src[pos]) == tagBuffer[match_pos]) {
                                ++match_pos;
                            }
                            else if (src[pos] == wxT(' ') || src[pos] == wxT('\n') ||
                                src[pos] == wxT('\r') || src[pos] == wxT('\t')) {
                                // need to skip over these
                            }
                            else {
                                match_pos = 0;
                            }
                            ++pos;
                        }

                        // found a match
                        if (match_pos == tag_len)
                        {
                            pos = pos - tag_len - 3;
                            foundCloseTag = true;
                            break;
                        }
                        else // keep looking for the closing tag
                        {
                            ++pos;
                        }
                    }
                    if (!foundCloseTag)
                    {
                        // we didn't find closing tag; this means the markup
                        // is incorrect and the best thing we can do is to
                        // ignore the unclosed tag and continue parsing as if
                        // it didn't exist:
                        pos = old_pos;
                    }
                }
            }
        }

        pos++;
    }

    // ok, we're done, now we'll free .Name members of cache - we don't need it anymore:
    for (int i = 0; i < m_CacheSize; i++)
    {
        delete[] m_Cache[i].Name;
        m_Cache[i].Name = NULL;
    }
}
Example #26
0
void wxFileConfig::Parse(wxTextFile& file, bool bLocal)
{
  const wxChar *pStart;
  const wxChar *pEnd;
  wxString strLine;

  size_t nLineCount = file.GetLineCount();
  for ( size_t n = 0; n < nLineCount; n++ ) {
    strLine = file[n];

    // add the line to linked list
    if ( bLocal )
      LineListAppend(strLine);

    // skip leading spaces
    for ( pStart = strLine; wxIsspace(*pStart); pStart++ )
      ;

    // skip blank/comment lines
    if ( *pStart == wxT('\0')|| *pStart == wxT(';') || *pStart == wxT('#') )
      continue;

    if ( *pStart == wxT('[') ) {          // a new group
      pEnd = pStart;

      while ( *++pEnd != wxT(']') ) {
        if ( *pEnd == wxT('\\') ) {
            // the next char is escaped, so skip it even if it is ']'
            pEnd++;
        }

        if ( *pEnd == wxT('\n') || *pEnd == wxT('\0') ) {
            // we reached the end of line, break out of the loop
            break;
        }
      }

      if ( *pEnd != wxT(']') ) {
        wxLogError(_("file '%s': unexpected character %c at line %d."),
                   file.GetName(), *pEnd, n + 1);
        continue; // skip this line
      }

      // group name here is always considered as abs path
      wxString strGroup;
      pStart++;
      strGroup << wxCONFIG_PATH_SEPARATOR
               << FilterInEntryName(wxString(pStart, pEnd - pStart));

      // will create it if doesn't yet exist
      SetPath(strGroup);

      if ( bLocal )
        m_pCurrentGroup->SetLine(m_linesTail);

      // check that there is nothing except comments left on this line
      bool bCont = TRUE;
      while ( *++pEnd != wxT('\0') && bCont ) {
        switch ( *pEnd ) {
          case wxT('#'):
          case wxT(';'):
            bCont = FALSE;
            break;

          case wxT(' '):
          case wxT('\t'):
            // ignore whitespace ('\n' impossible here)
            break;

          default:
            wxLogWarning(_("file '%s', line %d: '%s' ignored after group header."),
                         file.GetName(), n + 1, pEnd);
            bCont = FALSE;
        }
      }
    }
    else {                        // a key
      const wxChar *pEnd = pStart;
      while ( *pEnd && *pEnd != wxT('=') && !wxIsspace(*pEnd) ) {
        if ( *pEnd == wxT('\\') ) {
          // next character may be space or not - still take it because it's
          // quoted (unless there is nothing)
          pEnd++;
          if ( !*pEnd ) {
            // the error message will be given below anyhow
            break;
          }
        }

        pEnd++;
      }

      wxString strKey(FilterInEntryName(wxString(pStart, pEnd)));

      // skip whitespace
      while ( wxIsspace(*pEnd) )
        pEnd++;

      if ( *pEnd++ != wxT('=') ) {
        wxLogError(_("file '%s', line %d: '=' expected."),
                   file.GetName(), n + 1);
      }
      else {
        ConfigEntry *pEntry = m_pCurrentGroup->FindEntry(strKey);

        if ( pEntry == NULL ) {
          // new entry
          pEntry = m_pCurrentGroup->AddEntry(strKey, n);

          if ( bLocal )
            pEntry->SetLine(m_linesTail);
        }
        else {
          if ( bLocal && pEntry->IsImmutable() ) {
            // immutable keys can't be changed by user
            wxLogWarning(_("file '%s', line %d: value for immutable key '%s' ignored."),
                         file.GetName(), n + 1, strKey.c_str());
            continue;
          }
          // the condition below catches the cases (a) and (b) but not (c):
          //  (a) global key found second time in global file
          //  (b) key found second (or more) time in local file
          //  (c) key from global file now found in local one
          // which is exactly what we want.
          else if ( !bLocal || pEntry->IsLocal() ) {
            wxLogWarning(_("file '%s', line %d: key '%s' was first found at line %d."),
                         file.GetName(), n + 1, strKey.c_str(), pEntry->Line());

            if ( bLocal )
              pEntry->SetLine(m_linesTail);
          }
        }

        // skip whitespace
        while ( wxIsspace(*pEnd) )
          pEnd++;
        
        if ( GetStyle() & wxCONFIG_USE_NO_ESCAPE_CHARACTERS )
            pEntry->SetValue(pEnd, FALSE /* read from file, without escapes */);
        else
            pEntry->SetValue(FilterInValue(pEnd), FALSE /* read from file, with escapes */);
        
        //pEntry->SetValue(FilterInValue(pEnd), FALSE /* read from file */);
      }
    }
  }
}