#include <stdio.h>
#include <string.h>
#ifndef VMS
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#else
#include <unixio.h>
#include <types.h>
#include <stat.h>
#endif

#ifndef O_RDONLY
#define O_RDONLY 0
#endif
  
#include "externs.h"
#include "file.h"
#include "keym.h"  
#include "buffer.h"
#include "window.h"

char *FILE_RING[500];
char C_DIR[80];                 /* current working dir */
int NUM_FILES;

extern int SCREEN_WIDTH;

int insert_file(char *file)
{
    struct stat st;
    int i,n,size, fd, dsize;
    unsigned char *pos;

    if (file[0] == '\0')        /* assume stdin */
      {
          fd = 0;
          strcpy(BUF->file,"(Standard Input)");
      }
    else
      {
          stat(file, &st);
          if (st.st_mode & S_IFDIR)  /* S_IFDIR = 0040000 */
            {
#ifndef VMS
                get_dir(file);
#endif                
                return(1);
            }
          size = st.st_size;
#ifdef VMS          
          /* VMS share options (shr=put) suggested by Henk D. Davids <hdavids@mswe.dnet.ms.philips.nl> */
          /* VMS share options (shr=upi,get,put) suggested by Mark Pizzolato <mark@infocomm.com> */
          fd = open(file,O_RDONLY,"ctx=rec","mbf=8","mbc=16","rop=RAH","shr=upi,get,put");
#else
          fd = open(file,O_RDONLY);
#endif          
      }
    
    
    if (fd >= 0)
      {
          if (!fd) size = 16384;
          BEG = BUF->beg = (unsigned char *) malloc(size);
          n = 0;
          pos = BUF->beg;
          dsize = size;
          while ((i = read(fd, (char *) pos, size - n)) > 0 )
            {
                n += i;
                if ((fd == 0) && (size == n))
                  {
                      size += dsize;
                      BEG = (unsigned char *) realloc(BEG,size * sizeof(char));
                      pos = BEG + n;
                  }
                else pos += i;
            }
          BUF->end = pos;
          BUF->beg = BEG;
          close(fd);
          return (1);
      }
    return(0);
}

int find_file(char *file)
{
    Buffer *new_buf, *old_buf;
    int a,n;
    unsigned char *pos;
    
    
    new_buf = create_buffer(file);
    old_buf = switch_to_buffer(new_buf);
    
    if (insert_file(file) == 0)
      {
          message("File could not be opened.",1);
          BUF->beg = (unsigned char *) "File could Not be opened.";
          BUF->end = BUF->beg + strlen((char *) BUF->beg);
      }
    BEG = BUF->beg;
    EOB = BUF->end;
    if (!MOST_B_OPT && !MOST_K_OPT)
      for (pos = BEG; (pos < (BEG + 32)) && (pos < EOB); pos++)
      {
          if ((*pos == 0) || (*pos > 127)) MOST_B_OPT = 1;
      }
    
    n = count_lines(BEG,EOB);
    
    NUM_LINES = n;
    C_POS = BEG;
    C_LINE = 1;
    COLUMN = 1;
    return(1);
}

/* if the file is visible in a window, move to the window and return 1
   else return 0 */
int file_visible(char *file)
{
    Window *w;
    w = WIN;
    WIN = TOP_WIN;
    do
      {
          if (!strcmp(WIN->buf->file,file))
            {
                set_window(WIN);
                return(1);
            }
          WIN = WIN->next;
      }
    while (WIN != TOP_WIN);
    WIN = w;
    return(0);
}


void find_file_in_window(char *file)
{
    if (file_visible(file)) return;
    
    if (-1 == access(file,0))        /* does it exist? */
      message("File not found.",1);
    else if (-1 == access(file,4))   /* can we read it? */
      message("File exists but not readable.",1);
    else 
      {
          free_window_buffer();
          (void) find_file(file);

          window_buffer();
          CURS_ROW = WIN->curs_line = 1;
          CURS_POS = WIN->curs_pos = C_POS;
          CURS_COL = WIN->curs_col = 1;

          redraw_window();
          update_status(0);
      }
}



int next_file(int *j)
{
    char mbuf[132], ch, *curr_file;
    int i;
    
    mbuf[0] = '\0';
    select_minibuffer();
    delete_line(1);

    for (i = 0; i < SCREEN_WIDTH; i++) MINI_BUF[i] = ' ';

    if (*j >= NUM_FILES) *j = 0;
    curr_file = FILE_RING[*j];
    strcat(mbuf,"Next file: ");
    strcat(mbuf, curr_file);
    fputs(mbuf,stdout);
    fputc('\r',stdout);
    fflush(stdout);
    while(ch = mbuf[i], ch != '\0') i++;
    while(i < SCREEN_WIDTH) mbuf[i++] = ' ';
    mbuf[i] = '\0';
    strcpy((char *) MINI_BUF,mbuf);
    while (1)
      {
          ch = getkey();
          if (ch != '\033') break;
          if (ch = getkey(), (ch != 'O') && (ch != '[')) continue;
          if (ch = getkey(), (ch != 'A') && (ch != 'B')) continue;
          
          if (ch == 'B')
            {
                if (*j == 0) *j = NUM_FILES;
                (*j)--;
            }
          else  /* ch == 'A' */
            {
                (*j)++;
                if (*j == NUM_FILES) *j = 0;
            }
          curr_file = FILE_RING[*j];
          mbuf[0] = '\0';
          strcat(mbuf,"Next file: ");
          strcat(mbuf, curr_file);
          i = 0;
          while(ch = mbuf[i], ch != '\0') i++;
          while(i < SCREEN_WIDTH) mbuf[i++] = ' ';
          mbuf[i] = '\0';
          
          smart_puts(mbuf,MINI_BUF,stdout);
          fputc('\r',stdout);
          strcpy((char *) MINI_BUF,mbuf);
          fflush(stdout);
      }
    delete_line(1);
    exit_minibuffer();
    MINI_BUF[0] = 0;
    (*j)++;
    if ((ch == 'Q') || (ch == 'q')) return(-1);
    
    find_file_in_window(curr_file);
    return(0);
}

/* extracts directory from file string, returns false if no dir */
int head(char *file, char *dir)
{
    int n;
    (void) strcpy(dir,file);
    n = strlen(file) - 1;
#ifdef VMS    
    while((n > -1) && (file[n] != ']') && (file[n] != ':')) n--;
#else    
    while((n > -1) && file[n] != '/') n--;
#endif
    n++;
    dir[n] = '\0';
    return(n);
}

/* returns a pointer to the tail of file */
int tail(char *filed, char **filep)
{
    int n;
    n = strlen(filed) - 1;
#ifdef VMS    
    while((n > -1) && (filed[n] != ']') || (filed[n] != ':')) n--;
#else    
    while((n > -1) && filed[n] != '/') n--;
#endif
    n++;
    *filep = (filed + n);
    return(n);
}

/* assume path is big enough to hold new expanded version */
int expand_path(char *path)
{
    int n;
    /* really cheat here-- let system do it.  The path must exist!! */
    if (chdir(path))
      {
          message(path,1);
          return(0);
      }
    else
      {
          get_cdir(path);
          chdir(C_DIR);
#ifndef VMS
          n = strlen(path);
          if (path[n-1] == '/') return(1);
          path[n++] = '/'; path[n] = 0;
#endif
      }
    return(1);
}



void cd()
{
    char tmp_dir[80];
    int n;
    
    strcpy(tmp_dir,C_DIR);
    if (read_from_minibuffer("cd: ",C_DIR) == -1) return;
    if (!chdir(C_DIR))
      {
          get_cdir(C_DIR);         /* expands ../ etc... */
          n = strlen(C_DIR);
#ifndef VMS
          if (C_DIR[n-1] == '/') return;
          C_DIR[n++] = '/'; C_DIR[n] = 0;
#endif          
          return;
      }
    strcpy(C_DIR,tmp_dir);
    chdir(C_DIR);
    message("Unable to change directory.",1);
}

void user_get_file()
{
    char path[80], file[80], *name;
    
    if (!head(WIN->buf->file,file))
      strcpy(file,C_DIR);

    if (read_from_minibuffer("Find File: ",file) == -1) return;

    if (head(file,path))
      {
          expand_path(path);
          tail(file,&name);
          strcat(path,name);
          name = path;
      }
    else name = file;
    find_file_in_window(name);
}


