/***************************************************************************
                          cpp_parser.cpp  -  description
                             -------------------
    begin                : Apr 2 2003
    author               : 2003 Massimo Callegari
    email                : massimocallegari@yahoo.it
 ***************************************************************************/
 /***************************************************************************
 *                                                                         *
 *   This program is free software; you can redistribute it and/or modify  *
 *   it under the terms of the GNU General Public License as published by  *
 *   the Free Software Foundation; either version 2 of the License, or     *
 *   (at your option) any later version.                                   *
 *                                                                         *
 ***************************************************************************/
#include "plugin_katesymbolviewer.h"

void KatePluginSymbolViewerView::parseCppSymbols(void)
{
  if (!win->viewManager()->activeView())
   return;

 QString cl; // Current Line
 QString stripped;
 uint i, j, tmpPos = 0; 
 int par = 0, graph = 0, retry = 0;
 char block = 0, comment = 0, macro = 0, macro_pos = 0;
 bool structure = false;
 QPixmap cls( ( const char** ) class_xpm );
 QPixmap sct( ( const char** ) struct_xpm );
 QPixmap mcr( ( const char** ) macro_xpm );
 QListViewItem *node = NULL;
 QListViewItem *mcrNode = NULL, *sctNode = NULL, *clsNode = NULL;
 QListViewItem *lastMcrNode = NULL, *lastSctNode = NULL, *lastClsNode = NULL;
 
  
 Kate::Document *kv = win->viewManager()->activeView()->getDoc();
 //kdDebug(13000)<<"Lines counted :"<<kv->numLines()<<endl;
 positions.resize(kv->numLines() + 3); // Maximum symbols number o.O
 positions.fill(0);
 if(listMode)
   {
    mcrNode = new QListViewItem(symbols, symbols->lastItem(), i18n("Macros"));
    sctNode = new QListViewItem(symbols, symbols->lastItem(), i18n("Structures"));
    clsNode = new QListViewItem(symbols, symbols->lastItem(), i18n("Functions"));
    lastMcrNode = mcrNode;
    lastSctNode = sctNode;
    lastClsNode = clsNode;
    symbols->setRootIsDecorated(1);
   }
 else symbols->setRootIsDecorated(0);
     
 for (i=0; i<kv->numLines(); i++)
   {
    cl = kv->textLine(i);
    cl = cl.stripWhiteSpace();
    if(cl.at(0) == '/' && cl.at(1) == '/') continue;
    if(cl.find("/*") >= 0 && graph == 0) comment = 1;
    if(cl.find("*/") >= 0 && graph == 0) comment = 0;
    if(cl.find("#") >= 0 && graph == 0 ) macro = 1;
    if (comment != 1)
      {
       /* *********************** MACRO PARSING *****************************/
       if(macro == 1)
         {
          //macro_pos = cl.find("#");
          for (j = 0; j < cl.length(); j++)
             {
              if(cl.at(j)=='/' && cl.at(j+1)=='/') { macro = 0; break; }
              if(  (uint)cl.find("define") == j && 
                 !((uint)cl.find("defined") == j))
                    {
                     macro = 2;
                     j += 6; // skip the word "define"
                    }
              if(macro == 2 && cl.at(j) != ' ') macro = 3;
              if(macro == 3) 
                { 
                 if (cl.at(j) >= 0x20) stripped += cl.at(j);
                 if (cl.at(j) == ' ' || j == cl.length() - 1) 
                         macro = 4;
                }
              //kdDebug(13000)<<"Macro -- Stripped : "<<stripped<<" macro = "<<macro<<endl;
             }
           // I didn't find a valid macro e.g. include
           if(j == cl.length() && macro == 1) macro = 0; 
           if(macro == 4)
             {
              //stripped.replace(0x9, " ");
              stripped = stripped.stripWhiteSpace();
              if (macro_on == true)
                 {
                  if (listMode) 
                    {
                     node = new QListViewItem(mcrNode, lastMcrNode, stripped);
                     lastMcrNode = node;
                    }
                  else node = new QListViewItem(symbols, symbols->lastItem(), stripped);
                  node->setPixmap(0, (const QPixmap &)mcr);
                  positions.at(symbols->itemIndex(node)) = i;
                 }
              macro = 0;
              macro_pos = 0;
              stripped = "";
              //kdDebug(13000)<<"Macro -- Inserted : "<<stripped<<" at row : "<<i<<endl;
              if (cl.at(cl.length() - 1) == '\\') macro = 5; // continue in rows below
              continue;
             }
          }
       if (macro == 5 && cl.at(cl.length() - 1) != '\\') { macro = 0; continue; }
       
       /* ******************************************************************** */
       //if (cl.at(j) == '"' && comment == 2) { comment = 0; j++; }
       //else if (cl.at(j) == '"' && comment == 0) comment = 2;
       
       if(cl.find("(") >= 0 && cl.at(0) != '#' && block == 0 && comment != 2) 
          { structure = false; block = 1; }
       if((cl.find("typedef") >= 0 || cl.find("struct") >= 0) && 
          graph == 0 && block == 0)
         { structure = true; block = 2; stripped = ""; }
       //if(cl.find(";") >= 0 && graph == 0)
       //    block = 0;
       if(block > 0)
         {
          for (j = 0; j < cl.length(); j++)
            {
             if (cl.at(j) == '/' && (cl.at(j + 1) == '*')) comment = 2;
             if (cl.at(j) == '*' && (cl.at(j + 1) == '/')) {  comment = 0; j+=2; }
             if (cl.at(j) == '"' && comment == 2) { comment = 0; j++; }
             else if (cl.at(j) == '"' && comment == 0) comment = 2;
             if(cl.at(j)=='/' && cl.at(j+1)=='/') 
               { if(block == 1 && stripped == "") block = 0; break; }
             if (comment != 2)
               {
                if (block == 1 && graph == 0 ) 
                  {
                   if (cl.at(j) >= 0x20) stripped += cl.at(j);
                   if(cl.at(j) == '(') par++;
                   if(cl.at(j) == ')') 
                     {
                      par--;
                      if(par == 0)
                        {
                         stripped = stripped.stripWhiteSpace();
                         stripped.remove("static ");
                         //kdDebug(13000)<<"Function -- Inserted : "<<stripped<<" at row : "<<i<<endl;
                         block = 2;
                         tmpPos = i;
                        }
                     }
                  } // BLOCK 1
                if(block == 2 && graph == 0)
                  {
                   if(cl.at(j)=='/' && cl.at(j+1)=='/') break;
                   //if(cl.at(j)==':' || cl.at(j)==',') { block = 1; continue; }
                   if(cl.at(j)==':') { block = 1; continue; }
                   if(cl.at(j)==';')
                     {
                      stripped = "";
                      block = 0;
                      structure = false;
                      break;
                     } 
                   
                   if(cl.at(j)=='{' && structure == false && cl.find(";") < 0)
                     {
                      stripped.replace(0x9, " ");
                      if(func_on == true)
                        {
                         if (listMode) 
                           { 
                            node = new QListViewItem(clsNode, lastClsNode, stripped); 
                            lastClsNode = node; 
                           }
                         else node = new QListViewItem(symbols, symbols->lastItem(), stripped);
                         node->setPixmap(0, (const QPixmap &)cls);
                         positions.at(symbols->itemIndex(node)) = tmpPos;
                        }
                      stripped = "";
                      retry = 0;
                      block = 3;
                     }
                   if(cl.at(j)=='{' && structure == true)
                     { 
                      block = 3;
                      tmpPos = i;
                     } 
                   if(cl.at(j)=='(')
                     {
                      retry = 1;
                      block = 0;
                      j = 0; 
                      kdDebug(13000)<<"Restart from the beginnin of line..."<<endl;
                      stripped = "";
                      if (retry == 1) { break; } // Avoid an infinite loop :(
                      else retry = 1;
                     }
                   if(structure == true && cl.at(j) >= 0x20) stripped += cl.at(j);
                  } // BLOCK 2
                
                if (block == 3)
                  {
                   // A comment...there can be anything
                   if(cl.at(j)=='/' && cl.at(j+1)=='/') break;
                   if(cl.at(j)=='{') graph++;
                   if(cl.at(j)=='}') 
                     {
                      graph--;
                      if (graph == 0 && structure == false) block = 0;
                      if (graph == 0 && structure == true) block = 4;
                     }
                  } // BLOCK 3
                
                if (block == 4)
                  {
                   if(cl.at(j) == ';')
                     {
                      //stripped.replace(0x9, " ");
                      stripped.remove('{');
                      stripped.replace('}', " ");
                      if(struct_on == true)
                        {
                         if (listMode) 
                           {
                            node = new QListViewItem(sctNode, lastSctNode, stripped);
                            lastSctNode = node;
                           } 
                         else node = new QListViewItem(symbols, symbols->lastItem(), stripped);
                         node->setPixmap(0, (const QPixmap &)sct);
                         positions.at(symbols->itemIndex(node)) = tmpPos;
                        }
                      //kdDebug(13000)<<"Structure -- Inserted : "<<stripped<<" at row : "<<i<<endl;
                      stripped = "";
                      block = 0;
                      structure = false;
                      //break;
                      continue;
                     }
                   if (cl.at(j) >= 0x20) stripped += cl.at(j);
                  } // BLOCK 4
               } // comment != 2
            } // End of For cycle
         } // BLOCK > 0
      } // Comment != 1
   } // for kv->numlines

 positions.resize(symbols->itemIndex(node) + 1);
 //for (i= 0; i < (symbols->itemIndex(node) + 1); i++)
 //    kdDebug(13000)<<"Symbol row :"<<positions.at(i) <<endl;
}


