/* 
 *    Programmed By: Mohammed Isam Mohammed [mohammed_isam1984@yahoo.com]
 *    Copyright 2014 (c)
 * 
 *    file: opensave.c
 *    This file is part of mino (Mino).
 *
 *    mino (Mino) 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 3 of the License, or
 *    (at your option) any later version.
 *
 *    mino (Mino) is distributed in the hope that it will be useful,
 *    but WITHOUT ANY WARRANTY; without even the implied warranty of
 *    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *    GNU General Public License for more details.
 *
 *    You should have received a copy of the GNU General Public License
 *    along with mino (Mino).  If not, see <http://www.gnu.org/licenses/>.
 */    
#include "defs.h"
#include "kbd.h"
#include "options.h"
#include "edit.h"
#include <pwd.h>
#include <string.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <dirent.h>
#include <sys/stat.h>
#include <fcntl.h>

void checkFileExtension();

static int one(const struct dirent *unused) 
{
  return 1;
}

struct passwd *pass;//will be used to find the home dir

//char *cwd;
void findFullFileName(char *f);
char *findFullDirName(char *d);

/*****************************************
 * findFullFileName():
 * Some file names are too long, so we
 * cut them down and put ".." at the end.
 * When we want to open the actual file,
 * we need to find the complete name.
 * This function does that.
 * ***************************************/
void findFullFileName(char *f) 
{
  int n;
  struct dirent **eps;
  struct stat st;
  //remove the ".." at the end
  f[strlen(f)-2] = '\0';
  
  n = scandir(".", &eps, one, alphasort);
  if(n >= 0) 
  {
    int cnt;
    for(cnt = 0; cnt < n; ++cnt) 
    {
      lstat(eps[cnt]->d_name,&st);
      if(S_ISDIR(st.st_mode)) 
      {
      } 
      else 
      {
	if(strstr(eps[cnt]->d_name, f)) 
	{
		strcpy(open_file_name, cwd);
		strcat(open_file_name, "/");
		strcat(open_file_name, eps[cnt]->d_name);
	  //strcpy(open_file_name, eps[cnt]->d_name);
	  return;
	}
      } //end else
    } //end for
 } //end outer if
}

/*****************************************
 * findFullDirName():
 * Some dir names are too long, so we
 * cut them down and put ".." at the end.
 * When we want to open the actual dir,
 * we need to find the complete name.
 * This function does that and returns
 * the full dir name as char pointer.
 * ***************************************/
char *findFullDirName(char *d) 
{
  int n;
  struct dirent **eps;
  struct stat st;
  //remove the ".." at the end
  d[strlen(d)-2] = '\0';

  n = scandir(".", &eps, one, alphasort);
  if(n >= 0) 
  {
    int cnt;
    for(cnt = 0; cnt < n; ++cnt) 
    {
      lstat(eps[cnt]->d_name,&st);
      if(S_ISDIR(st.st_mode)) 
      {
	if(strstr(eps[cnt]->d_name, d))
	  return eps[cnt]->d_name;
      }
    } //end for
  }
  return NULL;
}

/*****************************************
 * openSaveFile():
 * This function shows a dialog box that
 * contains the directory listing of the
 * current dir. It takes over user input
 * to enable navigation through the dir
 * tree and selecting a file to open/save.
 * It then calls _openFile() or _saveFile()
 * to actually open/save the file.
 * ***************************************/
int openSaveFile(OPEN_SAVE openSave, int showDialog) 
{
  x = 2; y = 2;
  h = SCREEN_H-1; w = SCREEN_W-1;
  
  char inputName[w-y-9];//the input file name entered in the field
  int selChar;	//the selected char in input field
  int sel;	//0=dir tree, 1=input field
  
  switch(showDialog) 
  {
    case(YES):
      //try to open the document directory, if failed open home directory,
      //if also failed, just open the current working directory.
      if(documentTitle && strrchr(documentTitle, '/')) 
      {
	  char *tmp;
	  tmp = (char *) malloc(strlen(documentTitle));
	  strcpy(tmp, documentTitle);
	  tmp[strrchr(documentTitle, '/')-documentTitle] = '\0';
	  scanDir(tmp);
	  free(tmp);
      } 
      else if((pass = getpwuid(geteuid()))) 
      {
	if(!scanDir(pass->pw_dir)) return 0;
      } 
      else 
      {
	if(!scanDir(".")) return 0;
      }
      sel = (openSave == SAVE) ? 1 : 0;
      if(openSave == OPEN) strcpy(inputName, "");
      else 
      {
	//if there is a document title, save the title without
	//the pathname, if any..
	if(documentTitle) strcpy(inputName, strrchr(documentTitle, '/') ?
					    strrchr(documentTitle, '/')+1 :
					    documentTitle);
	else strcpy(inputName, DEFAULT_TITLE);
      }
      selChar = strlen(inputName);
  
      numVisDirs = h-x-3;
      firstVisDir = 0;
      selectedDir = 0;
      refreshDirView();
      //set the input field
	setScreenColors(FG_COLOR[COLOR_WINDOW], BG_COLOR[COLOR_WINDOW]);
	fprintf(stdout, "\e[%d;%dH", h-2, y+1);
	printf("File: ");
	setScreenColors(FG_COLOR[COLOR_HIGHLIGHT_TEXT], BG_COLOR[COLOR_HIGHLIGHT_TEXT]);
	printf("%s%*s", inputName, w-y-strlen(inputName)-9, " ");
	fprintf(stdout, "\e[%d;%dH", h-2, y+strlen(inputName)+7);
	//reset cursor if it is an OPEN file dialog
	if(openSave == OPEN) 
	{//if #1
	  setScreenColors(FG_COLOR[COLOR_HIGHLIGHT_TEXT], BG_COLOR[COLOR_HIGHLIGHT_TEXT]);
	  int pos = firstVisDir+selectedDir;
	  if(pos >= totalDirs) 
	  {//if #2
	    fprintf(stdout, "\x1b[%d;%dH%s", (selectedDir >= numVisDirs) ? 
		    selectedDir-numVisDirs+3:selectedDir+3,
		    (selectedDir >= numVisDirs) ? x+MAX_DIR_NAME_LEN+1:x+1,
		    files[pos-totalDirs]);
	  } 
	  else 
	  {
	  fprintf(stdout, "\x1b[%d;%dH[%s]", (selectedDir >= numVisDirs) ? 
		    selectedDir-numVisDirs+3:selectedDir+3,
		    (selectedDir >= numVisDirs) ? x+MAX_DIR_NAME_LEN+1:x+1,
		    dirs[pos]);
	  }//end if #2
	}//end if #1
      fflush(stdout);
      /***************************************************/
      //take control over user input
      /***************************************************/
      while(1) 
      {
	char *ch = (char *)malloc(5);
	ch = getKey();
	switch(ch[0]) 
	{
	  case(HOME_KEY):
	    if(sel == 1) 
	    {
	      selChar = 0;
	      fprintf(stdout, "\e[%d;%dH", h-2, y+selChar+7);
	      fflush(stdout);
	    } break;
	  case(END_KEY):
	    if(sel == 1) 
	    {
	      selChar = strlen(inputName);
	      if(sel > w-y-9) sel--;
	      fprintf(stdout, "\e[%d;%dH", h-2, y+selChar+7);
	      fflush(stdout);
	    } break;
	  case(DEL_KEY):
	    if(sel == 1) 
	    {
	      if(selChar == strlen(inputName)) break;
	      int i;
	      for(i = selChar; i < strlen(inputName)-1; i++)
		inputName[i] = inputName[i+1];
	      inputName[i] = '\0';
	      setScreenColors(FG_COLOR[COLOR_HIGHLIGHT_TEXT], BG_COLOR[COLOR_HIGHLIGHT_TEXT]);
	      //setScreenColors(BLUE, BGWHITE);
	      fprintf(stdout, "\e[%d;%dH", h-2, y+7);
	      printf("%*s", w-y-9, " ");
	      fprintf(stdout, "\e[%d;%dH", h-2, y+7);
	      printf("%s", inputName);
	      fprintf(stdout, "\e[%d;%dH", h-2, y+selChar+7);
	      fflush(stdout);
	    } break;
	  /***************************************************/
	  /***************************************************/
	  /***************************************************/
	  case(BACKSPACE_KEY):
	    if(sel == 1) 
	    {
	      if(selChar == 0) break;
	      int i;
	      if(selChar == strlen(inputName)) 
	      {
		i = strlen(inputName)-1;
	      } 
	      else 
	      {
		for(i = selChar; i <= strlen(inputName); i++)
		  inputName[i-1] = inputName[i];
	      }
	      inputName[i] = '\0';
	      selChar--;
	      setScreenColors(FG_COLOR[COLOR_HIGHLIGHT_TEXT], BG_COLOR[COLOR_HIGHLIGHT_TEXT]);
	      //setScreenColors(BLUE, BGWHITE);
	      fprintf(stdout, "\e[%d;%dH", h-2, y+7);
	      printf("%*s", w-y-9, " ");
	      fprintf(stdout, "\e[%d;%dH", h-2, y+7);
	      printf("%s", inputName);
	      fprintf(stdout, "\e[%d;%dH", h-2, y+selChar+7);
	      fflush(stdout);
	    } break;
	  /***************************************************/
	  /***************************************************/
	  /***************************************************/
	  case(TAB_KEY):
	    //if(openSave == SAVE) {
	      sel = (sel == 0) ? 1 : 0;
	      int pos = firstVisDir+selectedDir;
	      if(sel == 1) 
	      {//if #1
		setScreenColors(FG_COLOR[COLOR_HBUTTONS], BG_COLOR[COLOR_WINDOW]);
		//setScreenColors(GREEN, BGBLUE);
		if(pos >= totalDirs) 
		{//if #2
		  fprintf(stdout, "\x1b[%d;%dH%s", (selectedDir >= numVisDirs) ? 
			    selectedDir-numVisDirs+3:selectedDir+3,
			    (selectedDir >= numVisDirs) ? x+MAX_DIR_NAME_LEN+1:x+1,
			    files[pos-totalDirs]);
		} 
		else 
		{
		  fprintf(stdout, "\x1b[%d;%dH[%s]", (selectedDir >= numVisDirs) ? 
			    selectedDir-numVisDirs+3:selectedDir+3,
			    (selectedDir >= numVisDirs) ? x+MAX_DIR_NAME_LEN+1:x+1,
			    dirs[pos]);
		}//if #2
		fprintf(stdout, "\e[%d;%dH", h-2, y+selChar+7);
	      } 
	      else 
	      {
		setScreenColors(FG_COLOR[COLOR_HIGHLIGHT_TEXT], BG_COLOR[COLOR_HIGHLIGHT_TEXT]);
		//setScreenColors(BLUE, BGWHITE);
		if(pos >= totalDirs) 
		{//if #3
		  fprintf(stdout, "\x1b[%d;%dH%s", (selectedDir >= numVisDirs) ? 
			    selectedDir-numVisDirs+3:selectedDir+3,
			    (selectedDir >= numVisDirs) ? x+MAX_DIR_NAME_LEN+1:x+1,
			    files[pos-totalDirs]);
		} 
		else 
		{
		  fprintf(stdout, "\x1b[%d;%dH[%s]", (selectedDir >= numVisDirs) ? 
			    selectedDir-numVisDirs+3:selectedDir+3,
			    (selectedDir >= numVisDirs) ? x+MAX_DIR_NAME_LEN+1:x+1,
			    dirs[pos]);
		}//if #3
	      }//if #1
	    //} 
	    break;
	  /***************************************************/
	  /***************************************************/
	  /***************************************************/
	  case(LEFT_KEY):
	    //if((openSave == SAVE) && (sel == 1)) {
	    if(sel == 1) 
	    {
	      if(selChar == 0) break;
	      selChar--;
	      fprintf(stdout, "\e[%d;%dH", h-2, y+selChar+7);
	      break;
	    }
	    
	    if(selectedDir >= numVisDirs) 
	    {
		int pos = firstVisDir+selectedDir;
		setScreenColors(FG_COLOR[COLOR_HBUTTONS], BG_COLOR[COLOR_WINDOW]);
		//setScreenColors(GREEN, BGBLUE);
		if(pos >= totalDirs) 
		{//if #5
		  fprintf(stdout, "\x1b[%d;%dH%s", (selectedDir >= numVisDirs) ? 
			    selectedDir-numVisDirs+3:selectedDir+3,
			    (selectedDir >= numVisDirs) ? x+MAX_DIR_NAME_LEN+1:x+1,
			    files[pos-totalDirs]);
		} 
		else 
		{
		  fprintf(stdout, "\x1b[%d;%dH[%s]", (selectedDir >= numVisDirs) ? 
			    selectedDir-numVisDirs+3:selectedDir+3,
			    (selectedDir >= numVisDirs) ? x+MAX_DIR_NAME_LEN+1:x+1,
			    dirs[pos]);
		}//end if #5
		selectedDir -= numVisDirs;
		pos -= numVisDirs;
		setScreenColors(FG_COLOR[COLOR_HIGHLIGHT_TEXT], BG_COLOR[COLOR_HIGHLIGHT_TEXT]);
		//setScreenColors(BLUE, BGWHITE);
		if(pos >= totalDirs) 
		{//if #6
		  fprintf(stdout, "\x1b[%d;%dH%s", (selectedDir >= numVisDirs) ? 
			    selectedDir-numVisDirs+3:selectedDir+3,
			    (selectedDir >= numVisDirs) ? x+MAX_DIR_NAME_LEN+1:x+1,
			    files[pos-totalDirs]);
		  if(strstr(files[pos], "..")) 
		  {
		    findFullFileName(files[pos-totalDirs]);
		    strcpy(inputName, open_file_name);
		  } else strcpy(inputName, files[pos-totalDirs]);
		} 
		else 
		{
		  fprintf(stdout, "\x1b[%d;%dH[%s]", (selectedDir >= numVisDirs) ? 
			    selectedDir-numVisDirs+3:selectedDir+3,
			    (selectedDir >= numVisDirs) ? x+MAX_DIR_NAME_LEN+1:x+1,
			    dirs[pos]);
		}//end if #6
	    } 
	    else 
	    {
	      if(firstVisDir == 0) break;
	      selectedDir += numVisDirs;
	      firstVisDir -= numVisDirs;
	      refreshDirView();
	    } 
	      setScreenColors(FG_COLOR[COLOR_WINDOW], BG_COLOR[COLOR_WINDOW]);
	      fprintf(stdout, "\e[%d;%dH", h-2, y+1);
	      printf("File: ");
	      setScreenColors(FG_COLOR[COLOR_HIGHLIGHT_TEXT], BG_COLOR[COLOR_HIGHLIGHT_TEXT]);
	      printf("%s%*s", inputName, w-y-strlen(inputName)-9, " ");
	      if(sel == 1) fprintf(stdout, "\e[%d;%dH", h-2, y+selChar+7);
	    fflush(stdout);
	    break;
	  /***************************************************/
	  /***************************************************/
	  /***************************************************/
	  case(RIGHT_KEY):
	    //if((openSave == SAVE) && (sel == 1)) {
	    if(sel == 1) 
	    {
	      if(selChar == strlen(inputName)) break;
	      if(selChar >= w-y-9) break;
	      selChar++;
	      fprintf(stdout, "\e[%d;%dH", h-2, y+selChar+7);
	      break;
	    }
	    
	    if(selectedDir < numVisDirs) 
	    {
		int pos = firstVisDir+selectedDir;
		setScreenColors(FG_COLOR[COLOR_HBUTTONS], BG_COLOR[COLOR_WINDOW]);
		//setScreenColors(GREEN, BGBLUE);
		if(pos >= totalDirs) 
		{//if #5
		  fprintf(stdout, "\x1b[%d;%dH%s", (selectedDir >= numVisDirs) ? 
			    selectedDir-numVisDirs+3:selectedDir+3,
			    (selectedDir >= numVisDirs) ? x+MAX_DIR_NAME_LEN+1:x+1,
			    files[pos-totalDirs]);
		} 
		else 
		{
		  fprintf(stdout, "\x1b[%d;%dH[%s]", (selectedDir >= numVisDirs) ? 
			    selectedDir-numVisDirs+3:selectedDir+3,
			    (selectedDir >= numVisDirs) ? x+MAX_DIR_NAME_LEN+1:x+1,
			    dirs[pos]);
		}//end if #5
		selectedDir += numVisDirs;
		pos += numVisDirs;
		setScreenColors(FG_COLOR[COLOR_HIGHLIGHT_TEXT], BG_COLOR[COLOR_HIGHLIGHT_TEXT]);
		//setScreenColors(BLUE, BGWHITE);
		if(pos >= totalDirs) 
		{//if #6
		  fprintf(stdout, "\x1b[%d;%dH%s", (selectedDir >= numVisDirs) ? 
			    selectedDir-numVisDirs+3:selectedDir+3,
			    (selectedDir >= numVisDirs) ? x+MAX_DIR_NAME_LEN+1:x+1,
			    files[pos-totalDirs]);
		  if(strstr(files[pos], "..")) 
		  {
		    findFullFileName(files[pos-totalDirs]);
		    strcpy(inputName, open_file_name);
		  } else strcpy(inputName, files[pos-totalDirs]);
		} 
		else 
		{
		  fprintf(stdout, "\x1b[%d;%dH[%s]", (selectedDir >= numVisDirs) ? 
			    selectedDir-numVisDirs+3:selectedDir+3,
			    (selectedDir >= numVisDirs) ? x+MAX_DIR_NAME_LEN+1:x+1,
			    dirs[pos]);
		}//end if #6
	    } 
	    else 
	    {
	      if((firstVisDir+(numVisDirs*2)) >= (totalDirs+totalFiles)) break;
	      selectedDir -= numVisDirs;
	      firstVisDir += numVisDirs;
	      refreshDirView();
	    } 
	    //if SAVE dialog, redraw the input field
	    //if(openSave == SAVE) {
	      setScreenColors(FG_COLOR[COLOR_WINDOW], BG_COLOR[COLOR_WINDOW]);
	      //setScreenColors(WHITE, BGBLUE);
	      fprintf(stdout, "\e[%d;%dH", h-2, y+1);
	      printf("File: ");
	      setScreenColors(FG_COLOR[COLOR_HIGHLIGHT_TEXT], BG_COLOR[COLOR_HIGHLIGHT_TEXT]);
	      //setScreenColors(BLUE, BGWHITE);
	      printf("%s%*s", inputName, w-y-strlen(inputName)-9, " ");
	      if(sel == 1) fprintf(stdout, "\e[%d;%dH", h-2, y+selChar+7);
	    //}
	    fflush(stdout);
	    break;
	  /***************************************************/
	  /***************************************************/
	  /***************************************************/
	  case(ESC_KEY):
	    refreshView();
	    return 0;
	    break;
	  /***************************************************/
	  /***************************************************/
	  /***************************************************/
	  case(ENTER_KEY):
	    if(sel == 1) 
	    {
	      if(openSave == SAVE) 
	      {
		strcpy(open_file_name, cwd);
		strcat(open_file_name, "/");
		strcat(open_file_name, inputName);
		//*****check if the file already exists
		if(fopen(open_file_name, "r")) 
		{
		  int i = msgBox("File already exists. Overwrite?", YES|NO, CONFIRM);
		  if(i == NO) 
		  { 
		    refreshDirView(); 
		    setScreenColors(FG_COLOR[COLOR_WINDOW], BG_COLOR[COLOR_WINDOW]);
	     	    fprintf(stdout, "\e[%d;%dH", h-2, y+1);
		    printf("File: ");
		    setScreenColors(FG_COLOR[COLOR_HIGHLIGHT_TEXT], BG_COLOR[COLOR_HIGHLIGHT_TEXT]);
		    printf("%s%*s", inputName, w-y-strlen(inputName)-9, " ");
		    if(sel == 1) fprintf(stdout, "\e[%d;%dH", h-2, y+selChar+7);
		    fflush(stdout);
		    break; 
		  }
		}/////////////////////////
		if(!_saveFile()) return 0;
		FILE_STATE = SAVED;
		NEW_FILE = 0;
		return 1;
	      }
	      else 
	      {
		strcpy(open_file_name, cwd);
		strcat(open_file_name, "/");
		strcat(open_file_name, inputName);
		if(!_openFile()) return 0;
		FILE_STATE = OPENED;
		NEW_FILE = 0;
		return 1;
	      }
	    }
	    
	    if((firstVisDir+selectedDir) < totalDirs) 
	    {//if #1
	      //selected a directory.. navigate to it
	     if(strcmp(dirs[firstVisDir+selectedDir], "..") == 0) 
	     {//if #2
	       char *tmp2;
	       int i = (strrchr(cwd, '/')-cwd);
	       tmp2 = (char *) malloc(i+2);
	       strncpy(tmp2, cwd, i);
	       //strcat(tmp2, "\0");
	       tmp2[i] = '/';
	       tmp2[i+1] = '\0';
	       scanDir(tmp2);
	       free(tmp2);
	     } 
	     else 
	     {
	      char *tmp;
	      if(strstr(dirs[firstVisDir+selectedDir], "..")) 
	      {//if #3
		char *tmp2;
		tmp2 = findFullDirName(dirs[firstVisDir+selectedDir]);
		tmp = (char *) malloc(strlen(cwd)+strlen(tmp2+2));
		strcpy(tmp, cwd);
		strcat(tmp, "/");
		strcat(tmp, tmp2);
		strcat(tmp, "\0");
		scanDir(tmp);
		free(tmp);
	      } 
	      else 
	      {
		tmp = (char *) malloc(strlen(cwd)+
		      strlen(dirs[firstVisDir+selectedDir])+2);
		strcpy(tmp, cwd);
		strcat(tmp, "/");
		strcat(tmp, dirs[firstVisDir+selectedDir]);
		strcat(tmp, "\0");
		scanDir(tmp);
		free(tmp);
	      }//end if #3
	     }//end if #2
	     firstVisDir = 0;
	     selectedDir = 0;
	     refreshDirView();
	     setScreenColors(FG_COLOR[COLOR_WINDOW], BG_COLOR[COLOR_WINDOW]);
	     //setScreenColors(WHITE, BGBLUE);
	     fprintf(stdout, "\e[%d;%dH", h-2, y+1);
	     printf("File: ");
	     setScreenColors(FG_COLOR[COLOR_HIGHLIGHT_TEXT], BG_COLOR[COLOR_HIGHLIGHT_TEXT]);
	     //setScreenColors(BLUE, BGWHITE);
	     printf("%s%*s", inputName, w-y-strlen(inputName)-9, " ");
	     if(sel == 1) fprintf(stdout, "\e[%d;%dH", h-2, y+selChar+7);
	     fflush(stdout);
	    } 
	    else 
	    {
	      //selected a file.. open/save it
	      if(openSave == OPEN) 
	      {
		if(strstr(files[firstVisDir+selectedDir], ".."))
		  findFullFileName(files[firstVisDir+selectedDir-totalDirs]);
		else 
		{
		  //strcpy(open_file_name, files[firstVisDir+selectedDir-totalDirs]);
		  strcpy(open_file_name, cwd);
		  strcat(open_file_name, "/");
		  strcat(open_file_name, inputName);
		}
		if(!_openFile()) return 0;
		FILE_STATE = OPENED;
		NEW_FILE = 0;
		return 1;
	      } 
	      else 
	      {	//save file
		strcpy(open_file_name, cwd);
		strcat(open_file_name, "/");
		strcat(open_file_name, inputName);
		//*****check if the file already exists
		if(fopen(open_file_name, "r")) 
		{
		  int i = msgBox("File already exists. Overwrite?", YES|NO, CONFIRM);
		  if(i == NO) 
		  { 
		    refreshDirView(); 
		    setScreenColors(FG_COLOR[COLOR_WINDOW], BG_COLOR[COLOR_WINDOW]);
	     	    fprintf(stdout, "\e[%d;%dH", h-2, y+1);
		    printf("File: ");
		    setScreenColors(FG_COLOR[COLOR_HIGHLIGHT_TEXT], BG_COLOR[COLOR_HIGHLIGHT_TEXT]);
		    printf("%s%*s", inputName, w-y-strlen(inputName)-9, " ");
		    if(sel == 1) fprintf(stdout, "\e[%d;%dH", h-2, y+selChar+7);
		    fflush(stdout);
		    break;
		  }
		}/////////////////////////
		if(!_saveFile()) return 0;
		FILE_STATE = SAVED;
		NEW_FILE = 0;
		return 1;
	      }
	    }//end if #1
	    break;
	  /***************************************************/
	  /***************************************************/
	  /***************************************************/
	  //Navigate up through dirs and files
	  case(UP_KEY):
	    //if((openSave == SAVE) && (sel == 1)) break;
	    if(sel == 1) break;
	    //scanDir(".");
	    if(selectedDir == 0) 
	    {//if #1
	      if(firstVisDir == 0) break;
	      firstVisDir -= numVisDirs;
	      selectedDir = numVisDirs-1;
	      refreshDirView();
	    } 
	    else 
	    {
	      int pos = firstVisDir+selectedDir;
		setScreenColors(FG_COLOR[COLOR_HBUTTONS], BG_COLOR[COLOR_WINDOW]);
		//setScreenColors(GREEN, BGBLUE);
		if(pos >= totalDirs) 
		{//if #5
		  fprintf(stdout, "\x1b[%d;%dH%s", (selectedDir >= numVisDirs) ? 
			    selectedDir-numVisDirs+3:selectedDir+3,
			    (selectedDir >= numVisDirs) ? x+MAX_DIR_NAME_LEN+1:x+1,
			    files[pos-totalDirs]);
		} 
		else 
		{
		  fprintf(stdout, "\x1b[%d;%dH[%s]", (selectedDir >= numVisDirs) ? 
			    selectedDir-numVisDirs+3:selectedDir+3,
			    (selectedDir >= numVisDirs) ? x+MAX_DIR_NAME_LEN+1:x+1,
			    dirs[pos]);
		}//end if #5
		selectedDir--; pos--;
		setScreenColors(FG_COLOR[COLOR_HIGHLIGHT_TEXT], BG_COLOR[COLOR_HIGHLIGHT_TEXT]);
		//setScreenColors(BLUE, BGWHITE);
		if(pos >= totalDirs) 
		{//if #6
		  fprintf(stdout, "\x1b[%d;%dH%s", (selectedDir >= numVisDirs) ? 
			    selectedDir-numVisDirs+3:selectedDir+3,
			    (selectedDir >= numVisDirs) ? x+MAX_DIR_NAME_LEN+1:x+1,
			    files[pos-totalDirs]);
		  if(strstr(files[pos], "..")) 
		  {
		    findFullFileName(files[pos-totalDirs]);
		    if(strlen(open_file_name) > w-y-9)
		      strncpy(inputName, open_file_name, w-y-9);
		    else strcpy(inputName, open_file_name);
		  } else strcpy(inputName, files[pos-totalDirs]);
		} 
		else 
		{
		  fprintf(stdout, "\x1b[%d;%dH[%s]", (selectedDir >= numVisDirs) ? 
			    selectedDir-numVisDirs+3:selectedDir+3,
			    (selectedDir >= numVisDirs) ? x+MAX_DIR_NAME_LEN+1:x+1,
			    dirs[pos]);
		}//end if #6
	      //}//end if #2
	    }//end if #1
	    //if SAVE dialog, redraw the input field
	    //if(openSave == SAVE) {
		fprintf(stdout, "\e[%d;%dH", h-2, y+7);
		setScreenColors(FG_COLOR[COLOR_HIGHLIGHT_TEXT], BG_COLOR[COLOR_HIGHLIGHT_TEXT]);
		//setScreenColors(BLUE, BGWHITE);
		printf("%s%*s", inputName, w-y-strlen(inputName)-9, " ");
		if(sel == 1) fprintf(stdout, "\e[%d;%dH", h-2, y+selChar+7);
	    //}
	    fflush(stdout);
	    break;
	  /***************************************************/
	  /***************************************************/
	  /***************************************************/
	  //Navigate down through dirs and files
	  case(DOWN_KEY):
	    //if((openSave == SAVE) && (sel == 1)) break;
	    if(sel == 1) break;
	    //if((firstVisDir+selectedDir) >= (totalDirs+totalFiles)-1) break;
	    //scanDir(".");
	    if(selectedDir == (numVisDirs*2)-1) 
	    {//if #1
	      if((firstVisDir+(numVisDirs*2)) < (totalDirs+totalFiles)) {
		firstVisDir += numVisDirs;
		selectedDir = numVisDirs;
		refreshDirView();
	      //if SAVE dialog, redraw the input field
	      if(openSave == SAVE) 
	      {
		setScreenColors(FG_COLOR[COLOR_WINDOW], BG_COLOR[COLOR_WINDOW]);
		//setScreenColors(WHITE, BGBLUE);
		fprintf(stdout, "\e[%d;%dH", h-2, y+1);
		printf("File: ");
		setScreenColors(FG_COLOR[COLOR_HIGHLIGHT_TEXT], BG_COLOR[COLOR_HIGHLIGHT_TEXT]);
		//setScreenColors(BLUE, BGWHITE);
		printf("%s%*s", inputName, w-y-strlen(inputName)-9, " ");
		fprintf(stdout, "\e[%d;%dH", h-2, y+selChar+7);
	      }
		fflush(stdout);
		break;
	      }
	    } 
	    else 
	    {
		int pos = firstVisDir+selectedDir;
		if(pos >= (totalDirs+totalFiles-1)) break;
		setScreenColors(FG_COLOR[COLOR_HBUTTONS], BG_COLOR[COLOR_WINDOW]);
		//setScreenColors(GREEN, BGBLUE);
		if(pos >= totalDirs) 
		{//if #2
		  fprintf(stdout, "\x1b[%d;%dH%s", (selectedDir >= numVisDirs) ? 
			    selectedDir-numVisDirs+3:selectedDir+3,
			    (selectedDir >= numVisDirs) ? x+MAX_DIR_NAME_LEN+1:x+1,
			    files[pos-totalDirs]);
		} 
		else 
		{
		  fprintf(stdout, "\x1b[%d;%dH[%s]", (selectedDir >= numVisDirs) ? 
			    selectedDir-numVisDirs+3:selectedDir+3,
			    (selectedDir >= numVisDirs) ? x+MAX_DIR_NAME_LEN+1:x+1,
			    dirs[pos]);
		}//end if #2
		selectedDir++; pos++;
		setScreenColors(FG_COLOR[COLOR_HIGHLIGHT_TEXT], BG_COLOR[COLOR_HIGHLIGHT_TEXT]);
		//setScreenColors(BLUE, BGWHITE);
		if(pos >= totalDirs) 
		{//if #3
		  fprintf(stdout, "\x1b[%d;%dH%s", (selectedDir >= numVisDirs) ? 
			    selectedDir-numVisDirs+3:selectedDir+3,
			    (selectedDir >= numVisDirs) ? x+MAX_DIR_NAME_LEN+1:x+1,
			    files[pos-totalDirs]);
		  if(strstr(files[pos], "..")) 
		  {
		    findFullFileName(files[pos-totalDirs]);
		    if(strlen(open_file_name) > w-y-9)
		      strncpy(inputName, open_file_name, w-y-9);
		    else strcpy(inputName, open_file_name);
		  } else strcpy(inputName, files[pos-totalDirs]);
		} 
		else 
		{
		  fprintf(stdout, "\x1b[%d;%dH[%s]", (selectedDir >= numVisDirs) ? 
			    selectedDir-numVisDirs+3:selectedDir+3,
			    (selectedDir >= numVisDirs) ? x+MAX_DIR_NAME_LEN+1:x+1,
			    dirs[pos]);
		}//end if #3
	    }//end if #1
	    //if SAVE dialog, redraw the input field
	    //if(openSave == SAVE) {
		fprintf(stdout, "\e[%d;%dH", h-2, y+7);
		setScreenColors(FG_COLOR[COLOR_HIGHLIGHT_TEXT], BG_COLOR[COLOR_HIGHLIGHT_TEXT]);
		//setScreenColors(BLUE, BGWHITE);
		printf("%s%*s", inputName, w-y-strlen(inputName)-9, " ");
		if(sel == 1) fprintf(stdout, "\e[%d;%dH", h-2, y+selChar+7);
	    //}
	    fflush(stdout);
	    break;
	  default:
	    //if(openSave == SAVE && sel == 1) {
	    if(sel == 1) 
	    {
	      //if((ch >= 'a' && ch <= 'z') || (ch >= 'A' && ch <= 'Z')  ||
		//    (ch >= 32 && ch<= 64) || (ch >=123 && ch <= 126)) {	//if it is alphanumeric
		if(strlen(inputName) >= w-y-9) break;
		int i;
		inputName[strlen(inputName)+1] = '\0';
		for(i = strlen(inputName); i > selChar; i--)
		  inputName[i] = inputName[i-1];
		inputName[selChar++] = (CAPS || SHIFT) ? ch[0]-32 : ch[0];
		fprintf(stdout, "\e[%d;%dH", h-2, y+7);
		setScreenColors(FG_COLOR[COLOR_HIGHLIGHT_TEXT], BG_COLOR[COLOR_HIGHLIGHT_TEXT]);
		//setScreenColors(BLUE, BGWHITE);
		printf("%s%*s", inputName, w-y-strlen(inputName)-9, " ");
		fprintf(stdout, "\e[%d;%dH", h-2, y+selChar+7);
	      //}
	    }
	    break;
	}//end switch
      }//end while
      break;
    case(NO):
      if(openSave == OPEN) 
      {//if #1
	if(!_openFile()) 
	{
	  //msgBox("Failed to open file.", OK, ERROR);
	  return 0;
	} 
	FILE_STATE = OPENED;
	NEW_FILE = 0;
	return 1;
      } 
      else 
      {
	if(!_saveFile()) 
	{
	  return 0;
	} 
	FILE_STATE = SAVED;
	NEW_FILE = 0;
	return 1;
      }//end if #1
      break;
  }//end switch
  return 0;
}//end openSaveFile()


/***************************************************************
 * This function saves the file specified in open_file_name.
 * It is called indirectly through the function openSaveFile().
 * *************************************************************/
int _saveFile() 
{
  //if(!open_file)
    if(!(open_file = fopen(open_file_name, "w+"))) 
    {
      return 0;
    }
    
  int i, j;
  for(i = 0; i < totalLines; i++) 
  {
    for(j = 0; j < strlen(lines[i]); j+=4)
    {
      fputc(lines[i][j], open_file);
      if ((lines[i][j] & mask[0]) == mask[0]) fputc(lines[i][j+1], open_file);
      if ((lines[i][j] & mask[1]) == mask[1]) fputc(lines[i][j+2], open_file);
      if ((lines[i][j] & mask[2]) == mask[2]) fputc(lines[i][j+3], open_file);
    }
    //fputs(lines[i], open_file);
    if(!LINE_IS_LINKED[i]) fputc('\n', open_file);
  }
  FILE_STATE = SAVED;
  if(!documentTitle) documentTitle = (char *) malloc(MAX_FILE_NAME_LEN*4);
  if(strcmp(documentTitle, open_file_name) != 0)
    if(strrchr(open_file_name, '/'))
      strcpy(documentTitle, strrchr(open_file_name, '/')+1);
    else
      strcpy(documentTitle, open_file_name);
  fflush(open_file); 

  checkFileExtension();
  return 1;
}

/***************************************************************
 * This function opens the file specified in open_file_name.
 * It is called indirectly through the function openSaveFile().
 * *************************************************************/
int _openFile() 
{
  if(!(open_file = fopen(open_file_name, "r+"))) 
  {
    return 0;
  }
  //make a backup copy of the opened file, so if things went
  //wrong, we don't lose our original file!!
  char *backup_file_name = (char *) malloc(strlen(open_file_name)+2);
  strcpy(backup_file_name, open_file_name);
  strcat(backup_file_name, "~\0");
  FILE *backup_file = fopen(backup_file_name, "w");
  
  total_tabs = 0;
  char buf[(MAX_CHARS_PER_LINE*4)+1];
  int j = 0;
  int i = 0;
  totalLines = 0;

  for(i = 0; i < MAX_LINES; i++) 
  {
    if(!lines[i]) lines[i] = (char *) 
	  malloc((MAX_CHARS_PER_LINE+TAB_CHARS)*4);
    strcpy(lines[i], "\0");
  }//end for
  i = 0;
  while(fgets(buf, sizeof(buf), open_file)) 
  {
    fputs(buf, backup_file);
    if(totalLines >= MAX_LINES) break;
      //if this line contains only \n and last line is linked to it,
      //this means it is the remnant of last line and need not be added
      if((strlen(buf) == 1) && buf[0] == '\n' && LINE_IS_LINKED[i-1])
      { LINE_IS_LINKED[i-1] = 0; continue; }
      int k = 0;
      if((strlen(buf)+strlen(lines[i])) > MAX_CHARS_PER_LINE) 
      {
	k = MAX_CHARS_PER_LINE-strlen(lines[i]);
	strncat(lines[i], buf, k);
	//buf += k;
	LINE_IS_LINKED[i] = 1;
	totalLines++; i++;
      }
      if(buf[strlen(buf)-1] == '\n') 
      {//if ends in \n, remove it
	strncat(lines[i], buf+k, strlen(buf)-k-1);
	LINE_IS_LINKED[i] = 0;
      } 
      else 
      {
	strncat(lines[i], buf+k, strlen(buf)-k);
	LINE_IS_LINKED[i] = 1;
      }
      totalCharsInLine[i] = strlen(lines[i]);
      totalLines++; i++;
    //}
  }//end while
  //fclose(open_file);
  fflush(backup_file);
  
  char *t = (char *)malloc(MAX_CHARS_PER_LINE*4);
  for(i = 0; i < totalLines; i++) 
  {
    /////////////////////////////////////////////////////////
    //we will expand all chars in line into 4-byte length..
    /////////////////////////////////////////////////////////
    int x, z;
    for(x = 0; x < strlen(lines[i]); x++) 
    {
      z = 1;
      if ((lines[i][x] & mask[0]) == mask[0]) z++;
      if ((lines[i][x] & mask[1]) == mask[1]) z++;
      if ((lines[i][x] & mask[2]) == mask[2]) z++;
      strcpy(t, lines[i]+x+z);
      int w;
      for(w = z; w < 4; w++) lines[i][x+w] = ' ';
      lines[i][x+w] = '\0';
      strcat(lines[i], t);
      x += (w-1);
    }
    ///////////////////////////////////////////////////
    
    if(strlen(lines[i])/4 > MAX_CHARS_PER_LINE) 
    {
      if(LINE_IS_LINKED[i])
      {
	char *tmp = (char *) malloc(MAX_CHARS_PER_LINE*4);
	strcpy(tmp, lines[i+1]);
	strcpy(lines[i+1], lines[i]+(MAX_CHARS_PER_LINE*4));
	lines[i][MAX_CHARS_PER_LINE*4] = '\0';
	strcat(lines[i+1], tmp);
	free(tmp);
      } 
      else 
      {
	for(j = totalLines; j > i+1; j--) 
	{
	  strcpy(lines[j], lines[j-1]);
	  totalCharsInLine[j] = strlen(lines[j])/4;
	  LINE_IS_LINKED[j] = LINE_IS_LINKED[j-1];
	}
	strcpy(lines[i+1], lines[i]+(MAX_CHARS_PER_LINE*4));
	lines[i][MAX_CHARS_PER_LINE*4] = '\0';
	totalLines++;
      }
      //lines[i][MAX_CHARS_PER_LINE] = '\0';
      LINE_IS_LINKED[i] = 1;
      //shiftAllTabs(i+2, 1);
    }
    totalCharsInLine[i] = strlen(lines[i])/4;
  }
  free(t);
  
  if(!documentTitle) documentTitle = (char *) malloc(MAX_FILE_NAME_LEN*4);
  if(strrchr(open_file_name, '/'))
    strcpy(documentTitle, strrchr(open_file_name, '/')+1);
  else
    strcpy(documentTitle, open_file_name);
  firstVisLine = 0;
  selectedLine = 0;
  selectedChar = 0;

  if(backup_file) fclose(backup_file);
  free(backup_file_name);
  
  checkFileExtension();
  return 1;
}

void checkFileExtension() 
{
  int i = strlen(open_file_name);
  //is it a C source/header file?
  if((open_file_name[i-1] == 'c' && open_file_name[i-2] == '.') ||
     (open_file_name[i-1] == 'h' && open_file_name[i-2] == '.')) 
  {
    AUTO_HIGHLIGHTING = 1; BG_COLOR[COLOR_WINDOW] = COLOR_HWINDOW;
    HIGHLIGHT_MODE = C_MODE;
  //is it a C++ source/header file?
  } 
  else if((open_file_name[i-1] == 'C' && open_file_name[i-2] == '.') ||
	  (open_file_name[i-1] == 'p' && open_file_name[i-2] == 'p' 
	  && open_file_name[i-3] == 'c' && open_file_name[i-4] == '.') ||
	  (open_file_name[i-1] == 'P' && open_file_name[i-2] == 'P' 
	  && open_file_name[i-3] == 'C' && open_file_name[i-4] == '.') ||
	  (open_file_name[i-1] == 'c' && open_file_name[i-2] == 'c' 
	  && open_file_name[i-3] == '.') ||
	  (open_file_name[i-1] == '+' && open_file_name[i-2] == '+' 
	  && open_file_name[i-3] == 'c' && open_file_name[i-4] == '.') ||
	  (open_file_name[i-1] == 'x' && open_file_name[i-2] == 'x' 
	  && open_file_name[i-3] == 'c' && open_file_name[i-4] == '.') ||
	  (open_file_name[i-1] == 'p' && open_file_name[i-2] == 'p' 
	  && open_file_name[i-3] == 'h' && open_file_name[i-4] == '.') ||
	  (open_file_name[i-1] == 'p' && open_file_name[i-2] == 'c' 
	  && open_file_name[i-3] == '.')) 
  {
    AUTO_HIGHLIGHTING = 1; BG_COLOR[COLOR_WINDOW] = COLOR_HWINDOW;
    HIGHLIGHT_MODE = CPP_MODE;
  //is it a shell script file?
  } 
  else if((open_file_name[i-1] == 'h' && open_file_name[i-2] == 's' 
    && open_file_name[i-3] == '.') ||
	    (strstr(lines[0], "/bin/csh")) || (strstr(lines[0], "/bin/ksh")) ||
	    (strstr(lines[0], "/bin/sh")) || (strstr(lines[0], "/bin/bash"))) 
  {
    AUTO_HIGHLIGHTING = 1; BG_COLOR[COLOR_WINDOW] = COLOR_HWINDOW;
    HIGHLIGHT_MODE = SHELL_MODE;
  //is it a PERL script file?
  } 
  else if((open_file_name[i-1] == 'l' && open_file_name[i-2] == 'p' 
    && open_file_name[i-3] == '.') ||
	    (strstr(lines[0], "/bin/perl"))) 
  {
    AUTO_HIGHLIGHTING = 1; BG_COLOR[COLOR_WINDOW] = COLOR_HWINDOW;
    HIGHLIGHT_MODE = PERL_MODE;
  //NONE of the above...
  } 
  else 
  { 
    AUTO_HIGHLIGHTING = 0; BG_COLOR[COLOR_WINDOW] = old_window_color;
    HIGHLIGHT_MODE = NO_MODE;
  }//end if
  
  if(AUTO_HIGHLIGHTING) loadKeywords(HIGHLIGHT_MODE);
}
