1 /********************************************************************
2 This file is part of the abs 0.907 distribution.  abs is a spreadsheet
3 with graphical user interface.
4 
5 Copyright (C) 1998-2001  Andr� Bertin (Andre.Bertin@ping.be)
6 
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version if in the same spirit as version 2.
11 
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15 GNU General Public License for more details.
16 
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 
21 Concact: abs@pi.be
22          http://home.pi.be/bertin/abs.shtml
23 
24 *********************************************************************/
25 
26 
27 
28 
29 
30 
31 
32 
33 
34 
35 
36 
37 
38 
39 
40 
41 
42 
43 
44 
45 
46 
47 
48 
49 
50 
51 
52 
53 #include <stdio.h>
54 #include <sys/types.h>
55 #include <sys/stat.h>
56 
57 #ifndef _HPUX_SOURCE
58 #include <dirent.h>
59 #define DIRSTRUCT struct dirent
60 #endif
61 
62 #ifdef _HPUX_SOURCE
63 #define DIRSTRUCT struct direct
64 #include <sys/dir.h>
65 #ifndef S_IFDIR
66 #define S_IFDIR  0040000
67 #endif
68 #endif
69 
70 #include <unistd.h>
71 
72 
73 #include "param.h"
74 #include "file_selector.h"
75 #include "memory.h"
76 
77 #include "gr_interf.h"
78 #include "entrypop.h"
79 #include "info_dialog.h"
80 
81 static Widget promptShell = NULL;
82 static Widget promptDialog;
83 static Widget valueWidget;
84 static Widget dirvalueWidget;
85 
86 static Widget list;
87 static Widget dirlist;
88 
89 static Entry_Pop *filter;
90 
91 
92 
93 static char dialogTranslation[] = "\
94 <Key>Return: Accept()\n\
95 ";
96 
97 static XtActionsRec dialogactionsTable[] =
98 {
99   {"Accept", AcceptAction},
100 };
101 
102 
103 static void (*promptfunction) ();
104 
105 extern Widget gettop ();
106 
107 static char curdir[512];
108 
109 static char **labels = NULL;
110 static char **dirlabels = NULL;
111 
112 void
set_filename(Widget w,XtPointer closure,XtPointer call_data)113 set_filename (Widget w, XtPointer closure, XtPointer call_data)
114 {
115   Arg arglist[1];
116   XawListReturnStruct *item = (XawListReturnStruct *) call_data;
117   XtSetArg (arglist[0], XtNstring, item->string);
118   XtSetValues (valueWidget, arglist, 1);
119 
120 }
121 
122 void
MakeFullPath(char * root,char * filename,char * pathname)123 MakeFullPath (char *root, char *filename, char *pathname)
124 {
125   strcpy (pathname, root);
126   strcat (pathname, "/");
127   strcat (pathname, filename);
128 }
129 
130 void
change_dir(Widget w,XtPointer closure,XtPointer call_data)131 change_dir (Widget w, XtPointer closure, XtPointer call_data)
132 {
133   char backupdir[512];
134   int len = strlen (curdir);
135   int backuplen = len;
136   DIR *dir;
137 
138   XawListReturnStruct *item = (XawListReturnStruct *) call_data;
139 
140   strncpy (backupdir, curdir, 511);
141 
142   if (strcmp (item->string, "..") == 0)
143     {
144       if (len <= 1)
145 	return;
146 
147       while (len > 1 && curdir[len - 1] == '/')
148 	len--;
149 
150       while (len > 1 && curdir[len - 1] != '/')
151 	len--;
152 
153       if (len > 1)
154 	{
155 	  curdir[len] = '\0';
156 	}
157       else
158 	{
159 	  sprintf (curdir, "/");
160 	}
161 
162     }
163   else
164     {
165       if (strcmp (item->string, ".") != 0)
166 	{
167 	  if (len > 1 && curdir[len - 1] != '/')
168 	    strcat (curdir, "/");
169 	  strcat (curdir, item->string);
170 	}
171     }
172 
173   dir = opendir (curdir);
174   if (dir == NULL)
175     {
176       char message[600];
177       sprintf (message, "impossible to open dir (%s)", curdir);
178       Inform (message, NULL);
179       strncpy (curdir, backupdir, backuplen);
180       curdir[backuplen] = '\0';
181       return;
182     }
183 
184   freelist ();
185   remake_list ();
186   w_n = 0;
187   XtSetArg (w_args[w_n], XtNstring, curdir);
188   w_n++;
189   XtSetValues (dirvalueWidget, w_args, w_n);
190 
191 }
192 
193 
194 void
cb_Cancel(Widget w,XtPointer client_data,XtPointer call_data)195 cb_Cancel (Widget w, XtPointer client_data, XtPointer call_data)
196 {
197   if (promptShell)
198     {
199       freelist ();
200       XtPopdown (promptShell);
201     }
202   reactivate_zoom ();
203 }
204 
205 void
CancelAction(Widget w,XEvent * event,String * params,Cardinal * num_params)206 CancelAction (Widget w, XEvent * event, String * params, Cardinal * num_params)
207 {
208   cb_Cancel (w, NULL, NULL);
209 }
210 
211 void
cb_Rescan(Widget w,XtPointer client_data,XtPointer call_data)212 cb_Rescan (Widget w, XtPointer client_data, XtPointer call_data)
213 {
214   char *str;
215   Arg arglist[1];
216   XtSetArg (arglist[0], XtNstring, &str);
217 
218 
219   freelist ();
220   remake_list ();
221 }
222 
223 void
RescanAction(Widget w,XEvent * event,String * params,Cardinal * num_params)224 RescanAction (Widget w, XEvent * event, String * params, Cardinal * num_params)
225 {
226   cb_Rescan (w, NULL, NULL);
227 }
228 
229 void
cb_Accept(Widget w,XtPointer client_data,XtPointer call_data)230 cb_Accept (Widget w, XtPointer client_data, XtPointer call_data)
231 {
232   char *filename;
233   char *str;
234   Arg arglist[1];
235   int len = 2;
236   XtSetArg (arglist[0], XtNstring, &str);
237   XtGetValues (valueWidget, arglist, 1);
238   if (curdir != NULL)
239     len += strlen (curdir);
240   if (str != NULL)
241     len += strlen (str);
242   filename = (char *) absmalloc (sizeof (char) * len, "AcceptAction:filename");
243   sprintf (filename, "%s/%s", curdir, str);
244 
245   cb_Cancel (w, client_data, call_data);
246   (*promptfunction) (filename);
247   absfree (filename, "AcceptAction:filename");
248 }
249 
250 void
AcceptAction(Widget w,XEvent * event,String * params,Cardinal * num_params)251 AcceptAction (Widget w, XEvent * event, String * params, Cardinal * num_params)
252 {
253   cb_Accept (w, NULL, NULL);
254 }
255 
256 int
MakePrompt(Widget centerw,char * prompt,void (* func)(),char * def)257 MakePrompt (Widget centerw, char *prompt, void (*func) (), char *def)
258 {
259 
260   Arg centerArgs[2];
261   Arg args[20];
262   int n;
263   Position source_x, source_y;
264   Position dest_x, dest_y;
265   Dimension center_width, center_height;
266   Dimension prompt_width, prompt_height;
267 
268   XtTranslations dialog_trans_table;
269 
270   Widget cancel, ok, rescan, filterlabel, filename, dirname, viewport1,
271     viewport2, box;
272   Widget vsrl;
273 
274 
275 
276   desactivate_zoom ();
277 
278   if (promptShell == NULL)
279     {
280       n = 0;
281       XtSetArg (args[n], XtNinput, True);
282       n++;
283       XtSetArg (args[n], XtNwidth, 540);
284       n++;
285       XtSetArg (args[n], XtNheight, 350);
286       n++;
287       promptShell = XtCreatePopupShell
288 	("promptShell", transientShellWidgetClass, gettop (), args, 3);
289 
290 
291 
292       n = 0;
293       XtSetArg (args[n], XtNwidth, 540);
294       n++;
295       XtSetArg (args[n], XtNheight, 350);
296       n++;
297       promptDialog = XtCreateManagedWidget ("promptDialog", formWidgetClass,
298 					    promptShell, args, n);
299       n = 0;
300       XtSetArg (args[n], XtNwidth, 540);
301       n++;
302       XtSetArg (args[n], XtNheight, 1);
303       n++;
304       XtSetArg (args[n], XtNborderWidth, 0);
305       n++;
306       box = XtCreateManagedWidget ("promptDialog", formWidgetClass,
307 				   promptDialog, args, n);
308       n = 0;
309       XtSetArg (args[n], XtNwidth, 1);
310       n++;
311       XtSetArg (args[n], XtNheight, 350);
312       n++;
313       XtSetArg (args[n], XtNborderWidth, 0);
314       n++;
315       box = XtCreateManagedWidget ("promptDialog", formWidgetClass,
316 				   promptDialog, args, n);
317 
318       w_n = 0;
319       w_dim (200, 20);
320       w_rel (NULL, 9, 5);
321       w_bord (0);
322       XtSetArg (w_args[w_n], XtNlabel, "File name:");
323       w_n++;
324       XtSetArg (w_args[w_n], XtNjustify, XtJustifyLeft);
325       w_n++;
326       filename = XtCreateManagedWidget
327 	("Filename", labelWidgetClass, promptDialog, w_args, w_n);
328 
329 
330       w_n = 0;
331       w_dim (130, 20);
332       w_rel (filename, 20, -20);
333       XtSetArg (w_args[w_n], XtNborderWidth, 0);
334       w_n++;
335       XtSetArg (w_args[w_n], XtNlabel, "Directory:");
336       w_n++;
337       XtSetArg (w_args[w_n], XtNjustify, XtJustifyLeft);
338       w_n++;
339       dirname = XtCreateManagedWidget
340 	("Dirname", labelWidgetClass, promptDialog, w_args, w_n);
341 
342       w_n = 0;
343       w_dim (200, 20);
344       w_bord (0);
345       w_rel (filename, -200, 2);
346       XtSetArg (w_args[w_n], XtNstring, "");
347       w_n++;
348       XtSetArg (w_args[w_n], XtNeditType, XawtextEdit);
349       w_n++;
350       w_bONw ();
351       valueWidget = XtCreateManagedWidget
352 	("text", asciiTextWidgetClass, promptDialog, w_args, w_n);
353       addshadow (valueWidget, 3);
354 
355       w_n = 0;
356       w_dim (290, 20);
357       w_rel (dirname, -130, 2);
358       w_bord (0);
359       XtSetArg (w_args[w_n], XtNlabel, "");
360       w_n++;
361       XtSetArg (w_args[w_n], XtNborderWidth, 0);
362       w_n++;
363       XtSetArg (w_args[w_n], XtNjustify, XtJustifyLeft);
364       w_n++;
365       w_bONw ();
366       dirvalueWidget = XtCreateManagedWidget
367 	("dirtext", labelWidgetClass, promptDialog, w_args, w_n);
368 
369 
370       w_n = 0;
371       w_bord (0);
372       w_dim (200, 240);
373       w_rel (valueWidget, -200, 9);
374       XtSetArg (w_args[w_n], XtNuseRight, True);
375       w_n++;
376       XtSetArg (w_args[w_n], XtNallowVert, True);
377       w_n++;
378       XtSetArg (w_args[w_n], XtNforceBars, True);
379       w_n++;
380 
381       viewport1 = XtCreateManagedWidget ("viewport1",
382 			    viewportWidgetClass, promptDialog, w_args, w_n);
383       vsrl = XtNameToWidget (viewport1, "vertical");
384       if (vsrl != (Widget) NULL)
385 	{
386 	  modscroll (vsrl);
387 	}
388 
389       addshadow (viewport1, 6);
390 
391       w_n = 0;
392       w_bord (0);
393       XtSetArg (w_args[w_n], XtNdefaultColumns, 1);
394       w_n++;
395       XtSetArg (w_args[w_n], XtNforceColumns, True);
396       w_n++;
397       w_bONw ();
398       list = XtCreateManagedWidget ("list", listWidgetClass,
399 				    viewport1, w_args, w_n);
400       XtAddCallback (list, XtNcallback, set_filename, NULL);
401       addshadow (list, 6);
402 
403 
404       w_n = 0;
405       w_bord (0);
406       w_dim (200, 240);
407       w_rel (dirvalueWidget, -290, 9);
408       w_bord (0);
409       XtSetArg (w_args[w_n], XtNuseRight, True);
410       w_n++;
411       XtSetArg (w_args[w_n], XtNallowVert, True);
412       w_n++;
413       XtSetArg (w_args[w_n], XtNforceBars, True);
414       w_n++;
415       viewport2 = XtCreateManagedWidget ("viewport2",
416 			    viewportWidgetClass, promptDialog, w_args, w_n);
417       vsrl = XtNameToWidget (viewport2, "vertical");
418       if (vsrl != (Widget) NULL)
419 	{
420 	  modscroll (vsrl);
421 	}
422       addshadow (viewport2, 6);
423 
424       w_n = 0;
425       w_bord (0);
426       XtSetArg (w_args[w_n], XtNdefaultColumns, 1);
427       w_n++;
428       XtSetArg (w_args[w_n], XtNforceColumns, True);
429       w_n++;
430       w_bONw ();
431       dirlist = XtCreateManagedWidget ("dirlist", listWidgetClass,
432 				       viewport2, w_args, w_n);
433       XtAddCallback (dirlist, XtNcallback, change_dir, NULL);
434       addshadow (dirlist, 5);
435 
436       w_n = 0;
437       w_dim (200, 20);
438       w_rel (viewport1, -200, 9);
439       w_bord (0);
440       XtSetArg (w_args[w_n], XtNlabel, "Filter:");
441       w_n++;
442       XtSetArg (w_args[w_n], XtNjustify, XtJustifyLeft);
443       w_n++;
444       filterlabel = XtCreateManagedWidget
445 	("Filter", labelWidgetClass, promptDialog, w_args, w_n);
446 
447       filter = newentrypop (promptDialog, "printerpop", popdown, 200, 20);
448       entrypop_add_item (filter, "*.abs");
449       entrypop_add_item (filter, "*.txt");
450       entrypop_add_item (filter, "*.*");
451       entrypop_add_item (filter, "*");
452       entrypop_init_val (filter, "*.abs");
453       entrypop_callback (filter, cb_Rescan);
454       w_n = 0;
455       w_rel (filterlabel, -200, 0);
456       w_set (filter->baseform);
457 
458 
459 
460 
461 
462 
463 
464 
465 
466 
467 
468 
469 
470 
471 
472 
473 
474 
475 
476 
477       w_n = 0;
478       w_dim (85, 20);
479       w_rel (NULL, 435, 80);
480       ok = XtCreateManagedWidget
481 	("Ok", commandWidgetClass, promptDialog, w_args, w_n);
482       XtAddCallback (ok, XtNcallback, cb_Accept, (XtPointer) NULL);
483 
484       w_n = 0;
485       w_dim (85, 20);
486       w_rel (NULL, 435, 115);
487       rescan = XtCreateManagedWidget
488 	("Rescan", commandWidgetClass, promptDialog, w_args, w_n);
489       XtAddCallback (rescan, XtNcallback, cb_Rescan, (XtPointer) NULL);
490 
491       w_n = 0;
492       w_dim (85, 20);
493       w_rel (NULL, 435, 150);
494       cancel = XtCreateManagedWidget
495 	("Cancel", commandWidgetClass, promptDialog, w_args, w_n);
496       XtAddCallback (cancel, XtNcallback, cb_Cancel, (XtPointer) NULL);
497 
498 
499 
500       XtAppAddActions (XtWidgetToApplicationContext (gettop ()),
501 		       dialogactionsTable, XtNumber (dialogactionsTable));
502 
503       dialog_trans_table = XtParseTranslationTable (dialogTranslation);
504       XtOverrideTranslations (promptDialog, dialog_trans_table);
505       XtOverrideTranslations (valueWidget, dialog_trans_table);
506 
507       XtRealizeWidget (promptShell);
508       if (getcwd (curdir, 511) == NULL)
509 	sprintf (curdir, ".");
510     }
511 
512 
513 
514   XtSetArg (centerArgs[0], XtNwidth, &center_width);
515   XtSetArg (centerArgs[1], XtNheight, &center_height);
516   XtGetValues (centerw, centerArgs, 2);
517   XtSetArg (centerArgs[0], XtNwidth, &prompt_width);
518   XtSetArg (centerArgs[1], XtNheight, &prompt_height);
519   XtGetValues (promptShell, centerArgs, 2);
520   source_x = (int) (center_width - prompt_width) / 2;
521   source_y = (int) (center_height - prompt_height) / 3;
522   XtTranslateCoords (centerw, source_x, source_y, &dest_x, &dest_y);
523   XtSetArg (centerArgs[0], XtNx, dest_x);
524   XtSetArg (centerArgs[1], XtNy, dest_y);
525   XtSetValues (promptShell, centerArgs, 2);
526 
527 
528 
529 
530 
531 
532   XtPopup (promptShell, XtGrabNone);
533 
534   promptfunction = func;
535   remake_list ();
536   return 0;
537 }
538 
539 
540 
541 
542 
543 
544 
545 
546 
547 Boolean
IsDirectory(char * root,char * path)548 IsDirectory (char *root, char *path)
549 {
550   char fullpath[512];
551   struct stat statbuf;
552 
553   if (path == NULL)
554     return (False);
555   MakeFullPath (root, path, fullpath);
556   if (stat (fullpath, &statbuf))
557     return (False);
558 
559   if (statbuf.st_mode & S_IFDIR)
560     return (True);
561   else
562     return (False);
563 }
564 
565 
566 int
pass_filter(char * file,char * mask)567 pass_filter (char *file, char *mask)
568 {
569   int masklen, filelen;
570   int m = 0;
571   int f = 0;
572   int tm;
573   int matched = 0;
574   char tomatch = '\0';
575   int allok = 0;
576 
577   if (file == NULL)
578     return 0;
579   if (mask == NULL)
580     return 1;
581 
582   filelen = strlen (file);
583   masklen = strlen (mask);
584 
585   while (m < masklen && f < filelen)
586     {
587       allok = 0;
588       while (mask[m] == '*' && m < masklen)
589 	{
590 	  allok = 1;
591 	  m++;
592 	}
593 
594       if (m < masklen)
595 	{
596 	  tomatch = mask[m];
597 	  tm = 1;
598 	}
599       else
600 	{
601 	  tm = 0;
602 	}
603 
604       if (allok)
605 	{
606 	  if (tm)
607 	    {
608 	      matched = 0;
609 	      while (f < filelen && !matched)
610 		{
611 		  if (file[f] == tomatch)
612 		    matched = 1;
613 		  else
614 		    f++;
615 		}
616 	      if (!matched)
617 		return 0;
618 	    }
619 	  else
620 	    {
621 	      return 1;
622 	    }
623 	}
624       else
625 	{
626 	  if (file[f] == mask[m])
627 	    {
628 	      m++;
629 	      f++;
630 	    }
631 	  else
632 	    {
633 	      return 0;
634 	    }
635 	}
636     }
637 
638   if (f < filelen)
639     return 0;
640   return 1;
641 }
642 
643 
644 void
remake_list()645 remake_list ()
646 {
647   int n;
648   int len;
649 
650   DIR *dir;
651   DIRSTRUCT *entry;
652   int i, diri;
653   int j, k;
654   char *tmp;
655   char *mask;
656 
657   w_n = 0;
658   XtSetArg (w_args[w_n], XtNlabel, curdir);
659   w_n++;
660   XtSetValues (dirvalueWidget, w_args, w_n);
661 
662   mask = entrypop_gettext (filter);
663 
664   dir = opendir (curdir);
665   if (dir == NULL)
666     {
667       fprintf (stderr, "impossible to open dir (%s)\n", curdir);
668       return;
669     }
670 
671   n = 0;
672   while (readdir (dir) != NULL)
673     n++;
674 
675   rewinddir (dir);
676 
677   labels = (char **) absmalloc ((n + 3) * sizeof (char *), "remake_list:labels ");
678   dirlabels = (char **) absmalloc ((n + 3) * sizeof (char *), "remake_list:dirlabels ");
679 
680   i = 0;
681   diri = 0;
682   while ((entry = readdir (dir)) != NULL)
683     {
684 
685 
686       len = 256;
687 
688       if (IsDirectory (curdir, entry->d_name) && diri < n + 2)
689 	{
690 	  len = strlen (entry->d_name);
691 
692 	  dirlabels[diri] = (char *) absmalloc (sizeof (char) * (len + 1), "remake_list:dirlabels[diri] ");
693 	  strcpy (dirlabels[diri], entry->d_name);
694 	  diri++;
695 	}
696       else
697 	{
698 	  if (strncmp (entry->d_name, ".", 1) && i < n + 2)
699 	    {
700 
701 	      if (pass_filter (entry->d_name, mask))
702 		{
703 		  len = strlen (entry->d_name);
704 
705 		  labels[i] = (char *) absmalloc (sizeof (char) * (len + 1), "remake_list:labels[i] ");
706 		  strcpy (labels[i], entry->d_name);
707 		  i++;
708 		}
709 	    }
710 	}
711     }
712   closedir (dir);
713 
714   labels[i] = NULL;
715   dirlabels[diri] = NULL;
716 
717   if (i < 500)
718     for (j = 0; j < i; j++)
719       for (k = j + 1; k < i; k++)
720 	if (strcmp (labels[j], labels[k]) > 0)
721 	  {
722 	    tmp = labels[j];
723 	    labels[j] = labels[k];
724 	    labels[k] = tmp;
725 	  }
726 
727   if (diri < 500)
728     for (j = 0; j < diri; j++)
729       for (k = j + 1; k < diri; k++)
730 	if (strcmp (dirlabels[j], dirlabels[k]) > 0)
731 	  {
732 	    tmp = dirlabels[j];
733 	    dirlabels[j] = dirlabels[k];
734 	    dirlabels[k] = tmp;
735 	  }
736 
737 
738 
739 
740   XawListChange (list, labels, 0, 0, True);
741   XawListChange (dirlist, dirlabels, 0, 0, True);
742 
743   return;
744 
745 }
746 
747 void
freelist()748 freelist ()
749 {
750   int i;
751 
752   if (labels != NULL)
753     {
754       i = 0;
755       while (labels[i] != NULL)
756 	{
757 
758 	  absfree (labels[i], "freelist:labels[i] ");
759 	  i++;
760 	}
761       absfree (labels, "freelist:labels ");
762       labels = NULL;
763     }
764   if (dirlabels != NULL)
765     {
766       i = 0;
767       while (dirlabels[i] != NULL)
768 	{
769 
770 	  absfree (dirlabels[i], "freelist:dirlabels[i] ");
771 	  i++;
772 	}
773       absfree (dirlabels, "freelist:dirlabels ");
774       dirlabels = NULL;
775     }
776 }
777