/*    Matricurses  Copyright (C) 2008  Giovanni Santostefano
    This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
    This is free software, and you are welcome to redistribute it
    under certain conditions; type `show c' for details.

The hypothetical commands `show w' and `show c' should show the appropriate
parts of the General Public License.  Of course, your program's commands
might be different; for a GUI interface, you would use an "about box".

  You should also get your employer (if you work as a programmer) or school,
if any, to sign a "copyright disclaimer" for the program, if necessary.
For more information on this, and how to apply and follow the GNU GPL, see
<http://www.gnu.org/licenses/>.

  The GNU General Public License does not permit incorporating your program
into proprietary programs.  If your program is a subroutine library, you
may consider it more useful to permit linking proprietary applications with
the library.  If this is what you want to do, use the GNU Lesser General
Public License instead of this License.  But first, please read
<http://www.gnu.org/philosophy/why-not-lgpl.html>.
*/

/* Console Matrix ScreenSaver (alpha)
 * Developed by Giovanni Santostefano
 * 
 * change DELAY to speed up or slow down the animation
 * if you don't see the white characters decrease the DELAY
 * 
 * Compile: gcc -o matricurses -lncurses matrix.c
 */


#include <stdlib.h>
#include <curses.h>
#include <string.h>

/*Matrix screen saver*/
void Matrix(int delay)
{
   int i,j,k; /*guest indexes*/
   char c; /*the randomized char*/
   int *ypoint; /*the y position of each column*/
   int *ystart;
   char *prevchar; /*register the last char to change the color*/
   
   /*ncurses initialization*/
   initscr();
   noecho();
   curs_set(0);
   start_color();
   init_pair(1,COLOR_WHITE,COLOR_BLACK);
   init_pair(2,COLOR_GREEN,COLOR_BLACK);
   
   ypoint=malloc(sizeof(int)*COLS);
   ystart=malloc(sizeof(int)*COLS);
   prevchar=malloc(sizeof(char)*COLS);
   
   /*character position initialization*/
   for(i=0;i<COLS;i++)
     {
	ypoint[i]=(int)(rand()%(LINES-2));
	ystart[i]=0;
     }
   
   /*Enter the Matrix :P */
   while(1)
     {
	for(i=0; i<COLS;i++)
	  {
	     /*if a line is complete reset the line*/
	     if(ypoint[i]>LINES+20)
	       {
		  attron(COLOR_PAIR(2));
		  mvaddch(ypoint[i]-1,i,prevchar[i]);
		  ystart[i]=0;
		  ypoint[i]=(int)(rand()%(LINES-2));
	       }
	     
	     /*if is not complete we continue to print the line*/
	     
	     /*set green the prev char*/
	     if(ystart[i]==1)
	       {
		  attron(COLOR_PAIR(2));
		  mvaddch(ypoint[i]-1,i,prevchar[i]);
	       }
	     
	     /*take a new white char*/
	     c=(char)((rand()%100)+20);
	     j--;
	     if(j<0)
	       {
		  j=(int)((rand()%50));
		  c=' ';
	       }
	     
	     attron(COLOR_PAIR(1));
	     mvaddch(ypoint[i],i,c);
	    
	     k=ypoint[i]-(LINES/4);
	     if(k<0) k=LINES-k;
	     mvaddch(k,i,' ');
	     
	     prevchar[i]=c;
	     ypoint[i]++;
	     ystart[i]=1;
	     
	  }
	usleep(delay);
	refresh();
	
     }
   
   endwin();
   
   free(ystart);
   ystart=NULL;
   free(ypoint);
   ypoint=NULL;
   free(prevchar);
   prevchar=NULL;
   
}



int main(int argc, char** argv)
{
   time_t t;
   int delay=42100;
   srand((unsigned)time(&t));
   
   if(argc>1)
     {
	if(argc>2 || strcmp(argv[1],"-h")==0)
	   {
	      printf("Matricurses: A Console Matrix ScreenSaver\n");
	      printf("Developed by Giovanni Santostefano\n\n\n");
	      printf("Usage: matricurses [-h] <delay>\n");
	      printf(" -h  show this help\n");
	      printf(" <delay> is the matrix slow down (default 42100)\n");
	      exit(0);
	   }
	 else
	   {
	      printf("Resetting delay\n");
	      delay=atoi(argv[1]);
	   }
	   
	   
     }
   
   
   Matrix(delay);
  
   return 0;
}
