#include <fcntl.h>
#include <unistd.h>
#include <wait.h>
#include <unistd.h>
#include <stdlib.h>
#include <ctype.h>
#include <string.h>
/*  #include <limits.h> */

/*  #define PATH_MAX 4 */

#include "support.h"
#include "perspic.h"

static int
mysys(const char *d,const char *s,const char *f) {

  int pfd[2],status;
  pid_t pid;
  extern char **environ;
  char *argv[4]={"/bin/sh","-e","-c",NULL};

  if (pipe(pfd)) {
    err("Can't make pipe\n");
    return -1;
  }

  switch((pid=fork())) {
  case -1:
    err("Can't fork\n");
    return -1;
  case 0:
    if (dup2(pfd[0],STDIN_FILENO)==-1) {
      err("Cannot dup2 stdin\n");
      exit(255);
    }
    if (dup2(STDERR_FILENO,STDOUT_FILENO)==-1) {
      err("Cannot dup2 stderr\n");
      exit(255);
    }
    if (dup2(pfd[1],STDOUT_FILENO)==-1) {
      err("Cannot dup2 stdout\n");
      exit(255);
    }
    if (close(pfd[0])) {
      err("Cannot close pfd[0]\n");
      exit(255);
    }
    if (close(pfd[1])) {
      err("Cannot close pfd[1]\n");
      exit(255);
    }
  
    argv[3]=map_temp_str("cd %s ; %s %s </dev/null 2>&1",d,s,f);
    execve("/bin/sh",argv,environ);
    exit(255);

    break;

  default:

    if (close(pfd[1])) {
      err("Cannot close pfd[1]\n");
      return -1;
    }
  
    waitpid(pid,&status,0);
    if (WIFSIGNALED(status))
      err("Command terminated on signal %d\n",WTERMSIG(status));
    if (WEXITSTATUS(status) || WIFSIGNALED(status)) {
      Map m={0};
      char b[80];

      err("Cannot run system command %s %s in dir %s\n",s,f,d);
      err("Error output:\n");
      memset(b,0,sizeof(b));
      fcntl(pfd[0],F_SETFL,O_NONBLOCK);
      while (read(pfd[0],b,sizeof(b)-1)>0) {
	map_write(&m,b,strlen(b));
	memset(b,0,sizeof(b));
      }	
      map_write(&m,b,sizeof(*b));
      err(m.m1);
      map_close(&m);
      return -1;
    }
    break;
  }

  return 0;

}


void
on_save_quotation2_activate            (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{

  GtkWidget *w,*t,*m;
  Hit *h;
  char *c,b[200];
  const char *z,*z1,*z2,*z3;
  int n,bp,bv,ep,ev,esc;
  static int nq,ip;

  m=lookup_widget(GTK_WIDGET(menuitem),"menu2");
  c=gtk_object_get_data(GTK_OBJECT(m),"text_selection");
  w=gtk_object_get_data(GTK_OBJECT(m),"text_widget");
  h=gtk_object_get_data(GTK_OBJECT(w),"hit");
  t=lookup_widget(w,"window1");
  w=gtk_object_get_data(GTK_OBJECT(t),"window3");
  t=lookup_widget(w,"text3");
  n=gtk_text_get_length(GTK_TEXT(t));
  gtk_text_freeze(GTK_TEXT(t));
  if (!nq++) {

    Map m={0};
    void *d;

    if (map_open(&m,"/usr/lib/perspic/perspic.tex",0)) {
      map_get(&m,0,m.size);

      gtk_text_insert(GTK_TEXT(t),NULL,NULL,NULL,m.m1,m.size);
      d=strstr(m.m1,"\\end{document}\n");
      n+=m.size;
      ip=n-(d-m.m1);
      map_close(&m);
    }
  }

  gtk_text_set_point(GTK_TEXT(t),n-ip);
  gtk_text_insert(GTK_TEXT(t),NULL,NULL,NULL,"\\begin{myquote}{",-1);

  z1=strstr(h->b,c);
  for (z=z1,bp=bv=0;z>=h->b;z--) {
    if (*z=='+' && z[1]=='P') {
      bp=atoi(z+2);
      break;
    }
    if ((*z==':' || *z=='.') && isdigit(z[1])) {
      bv=atoi(z+1);
      break;
    }
  }
  if (!bv && !bp) 
    for (z=z1,bp=bv=0;z<h->be;z++) {
      if (*z=='+' && z[1]=='P') {
	bp=atoi(z+2)-1;
	break;
      }
      if ((*z==':' || *z=='.') && isdigit(z[1])) {
	bv=atoi(z+1)-1;
	break;
      }
    }

  z2=z1+strlen(c);
  for (z=z1,ep=bp,ev=bv;z<z2;z++) {
    if (*z=='+' && z[1]=='P') 
      ep=atoi(z+2);
    if ((*z==':' || *z=='.') && isdigit(z[1])) 
      ev=atoi(z+1);
  }

  if (bp) {
    if (ep>bp) {
      snprintf(b,sizeof(b),"pp. %d--%d}{",bp,ep);
      gtk_text_insert(GTK_TEXT(t),NULL,NULL,NULL,b,-1);
    } else {
      snprintf(b,sizeof(b),"p. %d}{",bp);
      gtk_text_insert(GTK_TEXT(t),NULL,NULL,NULL,b,-1);
    }
  }

  if (bv) {
    if (ev>bv) {
      snprintf(b,sizeof(b),"verses %d--%d}{",bv,ev);
      gtk_text_insert(GTK_TEXT(t),NULL,NULL,NULL,b,-1);
    } else {
      snprintf(b,sizeof(b),"v. %d}{",bv);
      gtk_text_insert(GTK_TEXT(t),NULL,NULL,NULL,b,-1);
    }
  }  

  if (!bp && !bv) 
    gtk_text_insert(GTK_TEXT(t),NULL,NULL,NULL,"}{",-1);

  z=h->f+strlen(h->f);
  for (;--z>=h->f && *z!='/';);
  z++;
  z3=z;
  z1=strstr(z,".txt");
  z1=z1 ? z1 : z+strlen(z);
  for (z2=z+1;z2<z1;z=z2,z2++) {
    for (;z2<z1 && islower(*z2);z2++);
    gtk_text_insert(GTK_TEXT(t),NULL,NULL,NULL,z,z2-z);
    gtk_text_insert(GTK_TEXT(t),NULL,NULL,NULL," ",1);
  }
  z=z3;
    
  gtk_text_insert(GTK_TEXT(t),NULL,NULL,NULL,"}{",-1);
  if (z>h->f) {
    for (z--;--z>=h->f && *z!='/';);
    z++;
    if (isupper(*z)) {
      z1=strchr(z,'/');
      gtk_text_insert(GTK_TEXT(t),NULL,NULL,NULL,z,z1-z);
    }
  }
  gtk_text_insert(GTK_TEXT(t),NULL,NULL,NULL,"}\n\n",-1);

  esc=1;
  for (z=c;*z;) {
    for (z1=z,z2=NULL;*z1 && !z2;)
      switch(*z1) {
      case '&': case '_': case '%': case '#': case '$': /*  case '\\': */
      case '@':
	if (esc) 
	  z2=z1;
	else
	  z1++;
	break;
      case '\\':
	if (esc && strncmp(z1,"\\sv",3)) 
	  z2=z1;
	else
	  z1++;
	break;
      case '{':
	esc=0;
	z1++;
	break;
      case '}':
	esc=1;
	z1++;
	break;
      default:
	z1++;
	break;
      }
    gtk_text_insert(GTK_TEXT(t),NULL,NULL,NULL,z,z1-z);
    if (z2)
      gtk_text_insert(GTK_TEXT(t),NULL,NULL,NULL,"\\",1);
    z=z1;
    if (*z1) {
      gtk_text_insert(GTK_TEXT(t),NULL,NULL,NULL,z1,1);
      z++;
    }
  }
  gtk_text_insert(GTK_TEXT(t),NULL,NULL,NULL,"\n\n\\end{myquote}\n\n",-1);
  g_free(c);
  gtk_editable_paste_clipboard(GTK_EDITABLE(t));
  gtk_text_thaw(GTK_TEXT(t));
  gtk_adjustment_set_value(GTK_ADJUSTMENT(GTK_TEXT(t)->vadj),
			   (GTK_TEXT(t)->vadj->upper-GTK_TEXT(t)->vadj->lower)*
			   (gfloat)1.0 -
			   0.5*(GTK_TEXT(t)->vadj->page_size));
  gtk_widget_show(w);

  

}


void
on_save1_activate                      (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{

  GtkWidget *w,*f;

  w=lookup_widget(GTK_WIDGET(menuitem),"window3");
  f=gtk_object_get_data(GTK_OBJECT(w),"fileselection2");
  gtk_widget_show(f);

}


void
on_ok_button3_pressed                  (GtkButton       *button,
                                        gpointer         user_data)
{

  GtkWidget *f,*w,*t;
  Map m={0};
  char *c;
  int n;

  f=lookup_widget(GTK_WIDGET(button),"fileselection2");
  gtk_widget_hide(f);
  w=gtk_object_get_data(GTK_OBJECT(f),"window3");
  c=gtk_file_selection_get_filename(GTK_FILE_SELECTION(f));
  if (!map_open(&m,c,1)) {
    err("Can't open %s\n",c);
    return;
  }
  t=lookup_widget(w,"text3");
  n=gtk_text_get_length(GTK_TEXT(t));
  if (!map_get(&m,0,n)) {
    err("Can't expand file %s to %d\n",c,n);
    map_close(&m);
    return;
  }
  c=gtk_editable_get_chars(GTK_EDITABLE(t),0,n);
  map_write_string(&m,c);
  g_free(c);
  if (!map_true(&m)) {
    err("Can't true map\n");
    return;
  }
  m.m--;

  if (!map_close(&m)) {
    err("Can't close map\n");
    return;
  }
  
    

}


void
on_cancel_button3_pressed              (GtkButton       *button,
                                        gpointer         user_data)
{
  GtkWidget *f;

  f=lookup_widget(GTK_WIDGET(button),"fileselection2");
  gtk_widget_hide(f);

}

void
on_save_as_1_activate                  (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{

}

static char name_buf[PATH_MAX];

void
on_print1_activate                     (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{

  Map m={0};
  const char *s;
  const char *home;
  GtkWidget *t;
  int n;
  char *c;

  home=getenv("HOME");
/*    s=tempnam(home,NULL); */
  if (snprintf(name_buf,sizeof(name_buf),"%s/perspic_print",home)<=0) {
    err("Cannot write temp filename for printing\n");
    return;
  }
  s=name_buf;
  if (!map_open(&m,s,1)) {
    err("Can't open %s\n",s);
    return;
  }
  t=lookup_widget(GTK_WIDGET(menuitem),"text3");
  n=gtk_text_get_length(GTK_TEXT(t));
  if (!map_get(&m,0,n)) {
    err("Can't get %d chars in %s\n",n,s);
    return;
  }
  c=gtk_editable_get_chars(GTK_EDITABLE(t),0,n);
  map_write_string(&m,c);
  if (!map_true(&m)) {
    err("Can't true map\n");
    return;
  }
  m.m--;

  if (!map_close(&m)) {
    err("Can't close map\n");
    return;
  }

  if (mysys(home,"latex --interaction=nonstopmode",s)) {
    err("Error running latex\n");
    return;
  }
      
  if (mysys(home,"dvips -o '|lpr'",s)) {
    err("Error running dvips\n");
    return;
  }
      

  if (unlink(s) ||
      unlink(map_temp_str("%s.aux",s)) ||
      unlink(map_temp_str("%s.log",s)) ||
      unlink(map_temp_str("%s.dvi",s))) {
    err("Can't unlink files %s*\n",s);
    return;
  }

}


void
on_print_setup_1_activate              (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{

}


void
on_close1_activate                     (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{

  GtkWidget *w;

  w=lookup_widget(GTK_WIDGET(menuitem),"window3");
  gtk_widget_hide(w);


}


void
on_cut1_activate                       (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{

}


void
on_copy2_activate                      (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{

}


void
on_paste2_activate                     (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{

}


void
on_find2_activate                      (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{

  


}


void
on_find_again2_activate                (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{

}


void
on_font3_activate                      (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{

}

void
on_preview1_activate                   (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{

  Map m={0};
  const char *s,*home;
  GtkWidget *t;
  int n;
  char *c;

  if (!(home=getenv("HOME"))) {
    err("HOME environment variable unset\n");
    return;
  }
/*    s=tempnam(home,NULL); */
  if (snprintf(name_buf,sizeof(name_buf),"%s/perspic_preview",home)<=0) {
    err("Cannot write temp filename for previewing\n");
    return;
  }
  s=name_buf;
  if (!map_open(&m,s,1)) {
    err("Can't open %s\n",s);
    return;
  }
  t=lookup_widget(GTK_WIDGET(menuitem),"text3");
  n=gtk_text_get_length(GTK_TEXT(t));
  if (!map_get(&m,0,n)) {
    err("Can't get %d chars in %s\n",n,s);
    return;
  }
  c=gtk_editable_get_chars(GTK_EDITABLE(t),0,n);
  map_write_string(&m,c);
  if (!map_close(&m)) {
    err("Can't close map\n");
    return;
  }

  if (mysys(home,"latex --interaction=nonstopmode",s)) {
    err("Error running latex\n");
    return;
  }
      
  if (mysys(home,"xdvi",s)) {
    err("Error running xdvi\n");
    return;
  }
      

  if (unlink(s) ||
      unlink(map_temp_str("%s.aux",s)) ||
      unlink(map_temp_str("%s.log",s)) ||
      unlink(map_temp_str("%s.dvi",s))) {
    err("Can't unlink files %s*\n",s);
    return;
  }

    
}


void
on_arabtex1_activate                   (GtkMenuItem     *menuitem,
                                        gpointer         user_data)
{

}



void
on_arabtex1_toggled                    (GtkCheckMenuItem *checkmenuitem,
                                        gpointer         user_data)
{

  GtkWidget *t;
  char *c,*z,*z1;
  int n;
  static int tg;

  t=lookup_widget(GTK_WIDGET(checkmenuitem),"text3");
  n=gtk_text_get_length(GTK_TEXT(t));
  c=gtk_editable_get_chars(GTK_EDITABLE(t),0,n);
  gtk_text_set_point(GTK_TEXT(t),0);
  gtk_text_forward_delete(GTK_TEXT(t),n);
  z=strstr(c,"%begin arabtex section");
  z1=strstr(z,"\n%end arabtex section");
  if (tg) {
/*      gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(checkmenuitem),0); */
    tg=0;
    for (;(z=strstr(z,"\n ")) && z<z1;)
      z[1]='%';
  } else {  
/*      gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(checkmenuitem),1); */
    tg=1;
    for (;(z=strstr(z,"\n%")) && z<z1;)
      z[1]=' ';
  }
  gtk_text_freeze(GTK_TEXT(t));
  gtk_text_insert(GTK_TEXT(t),NULL,NULL,NULL,c,-1);
  g_free(c);
  gtk_text_thaw(GTK_TEXT(t));

}

