
/***** Include vari *****/

#include "/triton/ped/Ped.h"
#include <strings.h>
#include <math.h>


/***** Prototipi delle due funzioni che si trovano in fondo al programma.
	Cio' e' necessario per far si che la funzione principale sia la
	prima nel codice! *****/

struct Line *MySearchLine( struct Line * , int );
void MyStrRev( char * );



/*****
 *
 * FUNZIONE:	ULONG main(struct PEDWindow *p,LONG ccol,LONG cline,ULONG *start,ULONG *end,char *funcname)
 *
 * SCOPO:	Cerca un blocco racchiuso dalle parentesi '{' e '}' che si
 *		trovi a livello 0 (non racchiuso da un altro blocco dello
 *		stesso tipo).
 *
 * NOTA:	Utilizza SEMPRE la funzione geta4() o la direttiva __saveds!
 *
 * RESTITUISCE: TRUE=blocco trovato,FALSE=non trovato.
 *
 ****/

ULONG ASM SAVEDS main(RG(a0) struct PEDWindow *p,RG(d0) LONG ccol,RG(d1) LONG cline,RG(a1) ULONG *start,RG(a2) ULONG *end,RG(a3) char *funcname)
{
	struct Line	*line,
			*curstartline;
	int		 i,
			 n,
			 num,
			 level,
			 lev,
			 nline,
			 startline,
			 startcol,
			 try;
	char		 c,
			*pun;



	/***** Scorri dal cursore in su per capire a che livello (di
		parentesi graffe) siamo *****/

	curstartline=line=MySearchLine(p->Text->FirstLine,cline);
	n=ccol;
	level=0;
	while(line)
	{
		/***** Se trovo un FOLD certamente sono a livello 0 *****/
		if (line->Folder)	break;

		/***** Cerca una graffa sulla riga *****/
		for(i=n;i>=0;i--)
		{
			c=line->Buffer[i];

			/***** Se c'e' una { aumenta il livello *****/
			if (c=='{') level++;

			/***** Se c'e' una } diminuisci il livello *****/
			else if (c=='}') level--;
		}

		/***** Passiamo alla linea precedente *****/
		line=line->PrevLine;
		if (line)	n=strlen(line->Buffer)-1;
	}

	/***** Se sei a livello 0, certamente non sei in una funzione! *****/
	if (!level)	return(FALSE);

	/***** Altrimenti scorri dal cursore in su fino a scendere al
		livello 0 *****/
	line=curstartline;
	nline=cline;
	n=ccol;
	lev=level;
	while(line)
	{
		/***** Cerca una graffa sulla riga *****/
		for(i=n;i>=0;i--)
		{
			c=line->Buffer[i];
			/***** Se c'e' una { diminuisci il livello. Se sei
				arrivato a livello 0 esci dal ciclo. *****/
			if (c=='{')
			{
				if (!(--lev))	break;
			}

			/***** Se c'e' una } aumenta il livello *****/
			else if (c=='}') lev++;
		}

		/***** Se siamo arrivati al livello 0 esci da quest'altro
			ciclo *****/
		if (i>=0)	break;

		/***** Passiamo alla linea precedente *****/
		line=line->PrevLine;
		nline--;
		if (line)	n=strlen(line->Buffer)-1;
	}

	/***** Se line==NULL allora c'e' stato un'errore!!!!!!!!!!!!!! *****/
	if (!line)	return(FALSE);

	/***** Abbiamo trovato l'inizio del blocco. Memorizza la posizione in
		(startline,startcol) *****/
	startline=nline;
	startcol=i;

	/***** Partiamo di nuovo dal punto iniziale e scorriamo verso il basso
		fino a scendere al livello 0 (dove termina il blocco). *****/
	line=curstartline;
	nline=cline;
	n=ccol+1;
	lev=level;
	while(line)
	{
		/***** Cerca una graffa sulla riga *****/
		for(i=n;i<strlen(line->Buffer);i++)
		{
			c=line->Buffer[i];
			/***** Se c'e' una { aumenta di livello *****/
			if (c=='{')	lev++;
			/***** Se c'e' una } diminuisci di livello. Se siamo
				a livello 0 esci da questo ciclo. *****/
			else if (c=='}') if (!(--lev))	break;
		}

		/***** Se siamo arrivati al livello 0 esci da quest'altro
			ciclo *****/
		if (i<strlen(line->Buffer))	break;

		/***** Passiamo alla linea successiva *****/
		line=line->NextLine;
		nline++;
		n=0;
	}

	/***** Se line==NULL allora c'e' stato un'errore!!!!!!!!!!!!!! *****/
	if (!line)	return(FALSE);

	/***** Abbiamo trovato anche la fine del blocco. Memorizza le righe
		iniziali e finali del blocco nelle LONG a cui puntato i
		parametri "start" ed "end". *****/
	*start=startline;
	*end=nline;

	/***** Cerchiamo il nome della funzione,ora. Trova la prima '('
		prima dell'inizio del blocco.*****/
	line=MySearchLine(p->Text->FirstLine,startline);
	nline=startline;
	n=startcol;
	try=3;	/* <- Cerchiamo per 3 linee prima dell'inizio del blocco */
	while(line)
	{
		for(i=n;i>=0;i--)	if (line->Buffer[i]=='(')	break;

		if (i>=0)	break;

		line=line->PrevLine;
		nline--;

		if (!(--try))	break;

		if (line)	n=strlen(line->Buffer)-1;
	}

	/***** Se line==NULL o hai superato le 3 linee permesse allora
		restituisci una stringa nulla come nome della funzione
		(Basta ritornare perche' la stringa nulla e' il nome
		di default fornito da ProgED). *****/
	if ((!line)||(!try))	return(TRUE);

	/***** Torna indietro dalla '(' trovata ricostruendo il nome
		della funzione. *****/
	num=0;
	pun=funcname;
	for(i--;i>=0;i--)
	{
		c=line->Buffer[i];
		if (
			((c>='a')&&(c<='z'))
			||
			((c>='A')&&(c<='Z'))
			||
			((c>='0')&&(c<='9'))
			||
			(c=='_')
		)	*pun++=c;
		else break;
	}
	*pun='\0';

	/***** Il nome, pero', e' scritto al contrario! Invertilo! ******/
	MyStrRev(funcname);

	/***** Aggiusta l'inizio del blocco fino ad includere la riga su
		cui si trovava il nome della funzione e ritorna TRUE. ******/
	*start=max(0,nline);
	return(TRUE);
}



/*****
 *
 * FUNZIONE:	struct Line *MySearchLine(struct Line *line,int y)
 *
 * SCOPO:	Cerca l'indirizzo della linea "y-esima" (0=prima) a partire
 *		dalla prima linea del file data da line.
 *		NB: NON tiene conto dei FOLDS.
 *
 * RESTITUISCE: Un puntatore alla linea cercata.
 *
 ****/

struct Line *MySearchLine(struct Line *line,int y)
{
	while(((y--)>0)&&(line))	line=line->NextLine;
	return(line);
}



/*****
 *
 * FUNZIONE:	void MyStrRev(char *p)
 *
 * SCOPO:	Inverte la stringa puntata da p.
 *
 * RESTITUISCE: -
 *
 ****/

void MyStrRev(char *p)
{
	char	c;
	int	i,
		n;

	n=strlen(p);
	for(i=0;i<n/2;i++)
	{
		c=p[i];
		p[i]=p[n-1-i];
		p[n-1-i]=c;
	}
}



