
/***** Various include *****/

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


/***** Prototypes *****/

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



/*****
 *
 * FUNCTION:	ULONG main(struct PEDWindow *p,LONG ccol,LONG cline,ULONG *start,ULONG *end,char *funcname)
 *
 * AIM:		Find a block enclosed into two brackets '{' and '}' which
 *		is placed at "zero level" (not enclosed in another block).
 *
 * NOTE:	Use always the function geta4() or the directive __saveds!
 *
 * RESULT:	TRUE=block found,FALSE=not found.
 *
 ****/

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;



	/***** Go up to check at which level we are *****/

	curstartline=line=MySearchLine(p->Text->FirstLine,cline);
	n=ccol;
	level=0;
	while(line)
	{
		/***** If we are on a fold -> sure we are at "zero level" *****/
		if (line->Folder)	break;

		/***** Search for a { bracket on the line *****/
		for(i=n;i>=0;i--)
		{
			c=line->Buffer[i];

			/***** If there's a { increment the level *****/
			if (c=='{') level++;

			/***** If there's a } decrement the level *****/
			else if (c=='}') level--;
		}

		/***** Go to previous line *****/
		line=line->PrevLine;
		if (line)	n=strlen(line->Buffer)-1;
	}

	/***** If we are at "zero level" then surely we're not in a function! *****/
	if (!level)	return(FALSE);

	/***** Else go up to search the bracket which lead us to "zero level" *****/
	line=curstartline;
	nline=cline;
	n=ccol;
	lev=level;
	while(line)
	{
		/***** Search for a { bracket on the line *****/
		for(i=n;i>=0;i--)
		{
			c=line->Buffer[i];
			/***** If there's a { decrement the level. If we're
				arrived to "zero level" exit. *****/
			if (c=='{')
			{
				if (!(--lev))	break;
			}

			/***** If there's a } increment the level *****/
			else if (c=='}') lev++;
		}

		/***** If we are arrived at "zero level" exit from this while *****/
		if (i>=0)	break;

		/***** Go to previous line *****/
		line=line->PrevLine;
		nline--;
		if (line)	n=strlen(line->Buffer)-1;
	}

	/***** If line==NULL then there was an error!!!!!!!!!!!!!! *****/
	if (!line)	return(FALSE);

	/***** We found the block start. Store position in (startline,startcol) *****/
	startline=nline;
	startcol=i;

	/***** Starting from this point go down searching for block end *****/
	line=curstartline;
	nline=cline;
	n=ccol+1;
	lev=level;
	while(line)
	{
		/***** Search for a bracket on this line *****/
		for(i=n;i<strlen(line->Buffer);i++)
		{
			c=line->Buffer[i];
			/***** If there's a { increment the level *****/
			if (c=='{')	lev++;
			/***** If there's a } decrement the level. If we are at
				"zero level" exit. *****/
			else if (c=='}') if (!(--lev))	break;
		}

		/***** If we are arrived at "zero level" exit from this while *****/
		if (i<strlen(line->Buffer))	break;

		/***** Go to next line *****/
		line=line->NextLine;
		nline++;
		n=0;
	}

	/***** If line==NULL then there was an error!!!!!!!!!!!!!! *****/
	if (!line)	return(FALSE);

	/***** We found the block end,too. Let's store starting and ending
		positions in output ULONGs (see prototype) *****/
		parametri "start" ed "end". *****/
	*start=startline;
	*end=nline;

	/***** Search for function's name. Search for the first '('
		before the block start. *****/
	line=MySearchLine(p->Text->FirstLine,startline);
	nline=startline;
	n=startcol;
	try=3;	/* <- Search for 3 lines before block start */
	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;
	}

	/***** If line==NULL, or we tried 3 lines, then set an empty
		string as function name and return (ProgED set
		internally the empty string, so we just have to
		return). *****/
	if ((!line)||(!try))	return(TRUE);

	/***** Go back from found '(' trovata building the function's
		name *****/
	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';

	/***** Beware! Function's name is reversed! Invert it! ******/
	MyStrRev(funcname);

	/***** Modify block start to include function name line, too. *****/
	*start=max(0,nline);
	return(TRUE);
}



/*****
 *
 * FUNCTION:	struct Line *MySearchLine(struct Line *line,int y)
 *
 * AIM:		Find the address of the y-th line (0=first) starting
 *		from the first line of file pointed by "line".
 *		NOTE: folded line are used, too.
 *
 * RESULT:	A pointer to wished line.
 *
 ****/

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



/*****
 *
 * FUNCTION:	void MyStrRev(char *p)
 *
 * AIM:		Reverse the string pointed by "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;
	}
}



