source: trunk/third/x3270/ft.c @ 9081

Revision 9081, 43.3 KB checked in by ghudson, 28 years ago (diff)
This commit was generated by cvs2svn to compensate for changes in r9080, which included commits to RCS files with non-trunk default branches.
Line 
1/*
2 * Modifications Copyright 1996 by Paul Mattes.
3 * Copyright Octover 1995 by Dick Altenbern.
4 * Based in part on code Copyright 1993, 1994, 1995 by Paul Mattes.
5 *  Permission to use, copy, modify, and distribute this software and its
6 *  documentation for any purpose and without fee is hereby granted,
7 *  provided that the above copyright notice appear in all copies and that
8 *  both that copyright notice and this permission notice appear in
9 *  supporting documentation.
10 */
11
12/*
13 *      ft.c
14 *              This module handles the file transfer dialogs.
15 */
16
17#include "globals.h"
18
19#include <X11/StringDefs.h>
20#include <X11/Xaw/Toggle.h>
21#include <X11/Xaw/Command.h>
22#include <X11/Xaw/Form.h>
23#include <X11/Shell.h>
24#include <X11/Xaw/AsciiText.h>
25#include <X11/Xaw/TextSrc.h>
26#include <X11/Xaw/TextSink.h>
27#include <X11/Xaw/AsciiSrc.h>
28#include <X11/Xaw/AsciiSink.h>
29#include <errno.h>
30
31#if XtSpecificationRelease < 5 /*[*/
32#define TOGGLE_HACK 1
33#endif /*]*/
34
35#include "appres.h"
36#include "actionsc.h"
37#include "ft_cutc.h"
38#include "ft_dftc.h"
39#include "ftc.h"
40#include "kybdc.h"
41#include "objects.h"
42#include "popupsc.h"
43#include "telnetc.h"
44#include "utilc.h"
45
46/* Macros. */
47#define eos(s)  strchr((s), '\0')
48
49#define FILE_WIDTH      300     /* width of file name widgets */
50#define MARGIN          3       /* distance from margins to widgets */
51#define CLOSE_VGAP      0       /* distance between paired toggles */
52#define FAR_VGAP        10      /* distance between single toggles and groups */
53#define BUTTON_GAP      5       /* horizontal distance between buttons */
54#define COLUMN_GAP      40      /* distance between columns */
55
56/* Externals. */
57extern Pixmap diamond;
58extern Pixmap no_diamond;
59extern Pixmap null;
60extern Pixmap dot;
61
62/* Globals. */
63enum ft_state ft_state = FT_NONE;       /* File transfer state */
64char *ft_local_filename;                /* Local file to transfer to/from */
65FILE *ft_local_file = (FILE *)NULL;     /* File descriptor for local file */
66Boolean ascii_flag = True;              /* Convert to ascii */
67Boolean cr_flag = True;                 /* Add crlf to each line */
68unsigned long ft_length = 0;            /* Length of transfer */
69
70/* Statics. */
71static Widget ft_dialog, ft_shell, local_file, host_file;
72static Widget lrecl_widget, blksize_widget;
73static Widget primspace_widget, secspace_widget;
74static Widget send_toggle, receive_toggle;
75static Widget vm_toggle, tso_toggle;
76static Widget ascii_toggle, binary_toggle;
77static Widget cr_widget;
78
79static Boolean receive_flag = True;     /* Current transfer is receive */
80static Boolean append_flag = False;     /* Append transfer */
81static Boolean vm_flag = False;         /* VM Transfer flag */
82
83struct toggle_list {                    /* List of toggle widgets */
84        Widget *widgets;
85};
86static Widget recfm_options[5];
87static Widget units_options[5];
88static struct toggle_list recfm_toggles = { recfm_options };
89static struct toggle_list units_toggles = { units_options };
90
91static enum recfm {
92        DEFAULT_RECFM, FIXED, VARIABLE, UNDEFINED
93} recfm = DEFAULT_RECFM;
94static Boolean recfm_default = True;
95static enum recfm r_default_recfm = DEFAULT_RECFM;
96static enum recfm r_fixed = FIXED;
97static enum recfm r_variable = VARIABLE;
98static enum recfm r_undefined = UNDEFINED;
99
100static enum units {
101        DEFAULT_UNITS, TRACKS, CYLINDERS, AVBLOCK
102} units = DEFAULT_UNITS;
103static Boolean units_default = True;
104static enum units u_default_units = DEFAULT_UNITS;
105static enum units u_tracks = TRACKS;
106static enum units u_cylinders = CYLINDERS;
107static enum units u_avblock = AVBLOCK;
108
109typedef enum { T_NUMERIC, T_HOSTFILE, T_UNIXFILE } text_t;
110static text_t t_numeric = T_NUMERIC;
111static text_t t_hostfile = T_HOSTFILE;
112static text_t t_unixfile = T_UNIXFILE;
113
114static Boolean s_true = True;
115static Boolean s_false = False;
116static Boolean allow_overwrite = False;
117typedef struct sr {
118        struct sr *next;
119        Widget w;
120        Boolean *bvar1;
121        Boolean bval1;
122        Boolean *bvar2;
123        Boolean bval2;
124        Boolean *bvar3;
125        Boolean bval3;
126        Boolean is_value;
127        Boolean has_focus;
128} sr_t;
129sr_t *sr = (sr_t *)NULL;
130sr_t *sr_last = (sr_t *)NULL;
131
132static Widget progress_shell, from_file, to_file;
133static Widget ft_status, waiting, aborting;
134static String status_string;
135static struct timeval t0;               /* Starting time */
136static Boolean ft_is_cut;               /* File transfer is CUT-style */
137
138static Widget overwrite_shell;
139
140static void apply_bitmap();
141static void check_sensitivity();
142static void flip_toggles();
143static void focus_next();
144static void ft_cancel();
145static void ft_popup_callback();
146static void ft_popup_init();
147static int ft_start();
148static void ft_start_callback();
149static void match_dimension();
150static void overwrite_cancel_callback();
151static void overwrite_okay_callback();
152static void overwrite_popdown();
153static void overwrite_popup_init();
154static void popup_overwrite();
155static void popup_progress();
156static void progress_cancel_callback();
157static void progress_popup_callback();
158static void progress_popup_init();
159static void recfm_callback();
160static void register_sensitivity();
161static void text_callback();
162static void toggle_append();
163static void toggle_ascii();
164static void toggle_cr();
165static void toggle_receive();
166static void toggle_vm();
167static void units_callback();
168
169/* Main external entry point. */
170
171/* "File Transfer" dialog. */
172
173/*
174 * Pop up the "Transfer" menu.
175 * Called back from the "File Transfer" option on the File menu.
176 */
177void
178popup_ft(w, call_parms, call_data)
179Widget w;
180XtPointer call_parms;
181XtPointer call_data;
182{
183        /* Initialize it. */
184        if (ft_shell == (Widget)NULL)
185                ft_popup_init();
186
187        /* Pop it up. */
188        popup_popup(ft_shell, XtGrabNone);
189}
190
191
192/* Initialize the transfer pop-up. */
193static void
194ft_popup_init()
195{
196        Widget w;
197        Widget cancel_button;
198        Widget local_label, host_label;
199        Widget append_widget;
200        Widget lrecl_label, blksize_label, primspace_label, secspace_label;
201        Widget h_ref = (Widget)NULL;
202        Dimension d1;
203        Dimension maxw = 0;
204        Widget recfm_label, units_label;
205        Widget start_button;
206
207        /* Create the menu shell. */
208        ft_shell = XtVaCreatePopupShell(
209            "ftPopup", transientShellWidgetClass, toplevel,
210            NULL);
211        XtAddCallback(ft_shell, XtNpopupCallback, place_popup,
212            (XtPointer)CenterP);
213        XtAddCallback(ft_shell, XtNpopupCallback, ft_popup_callback,
214            (XtPointer)NULL);
215
216        /* Create the form within the shell. */
217        ft_dialog = XtVaCreateManagedWidget(
218            "dialog", formWidgetClass, ft_shell,
219            NULL);
220
221        /* Create the file name widgets. */
222        local_label = XtVaCreateManagedWidget(
223            "local", labelWidgetClass, ft_dialog,
224            XtNvertDistance, FAR_VGAP,
225            XtNhorizDistance, MARGIN,
226            XtNborderWidth, 0,
227            NULL);
228        local_file = XtVaCreateManagedWidget(
229            "value", asciiTextWidgetClass, ft_dialog,
230            XtNeditType, XawtextEdit,
231            XtNwidth, FILE_WIDTH,
232            XtNvertDistance, FAR_VGAP,
233            XtNfromHoriz, local_label,
234            XtNhorizDistance, 0,
235            NULL);
236        match_dimension(local_label, local_file, XtNheight);
237        w = XawTextGetSource(local_file);
238        if (w == NULL)
239                XtWarning("Cannot find text source in dialog");
240        else
241                XtAddCallback(w, XtNcallback, text_callback,
242                    (XtPointer)&t_unixfile);
243        register_sensitivity(local_file,
244            NULL, NULL,
245            NULL, NULL,
246            NULL, NULL);
247
248        host_label = XtVaCreateManagedWidget(
249            "host", labelWidgetClass, ft_dialog,
250            XtNfromVert, local_label,
251            XtNvertDistance, 3,
252            XtNhorizDistance, MARGIN,
253            XtNborderWidth, 0,
254            NULL);
255        host_file = XtVaCreateManagedWidget(
256            "value", asciiTextWidgetClass, ft_dialog,
257            XtNeditType, XawtextEdit,
258            XtNwidth, FILE_WIDTH,
259            XtNdisplayCaret, False,
260            XtNfromVert, local_label,
261            XtNvertDistance, 3,
262            XtNfromHoriz, host_label,
263            XtNhorizDistance, 0,
264            NULL);
265        match_dimension(host_label, host_file, XtNheight);
266        match_dimension(local_label, host_label, XtNwidth);
267        w = XawTextGetSource(host_file);
268        if (w == NULL)
269                XtWarning("Cannot find text source in dialog");
270        else
271                XtAddCallback(w, XtNcallback, text_callback,
272                    (XtPointer)&t_hostfile);
273        register_sensitivity(host_file,
274            NULL, NULL,
275            NULL, NULL,
276            NULL, NULL);
277
278        /* Create the left column. */
279
280        /* Create send/receive toggles. */
281        send_toggle = XtVaCreateManagedWidget(
282            "send", commandWidgetClass, ft_dialog,
283            XtNfromVert, host_label,
284            XtNvertDistance, FAR_VGAP,
285            XtNhorizDistance, MARGIN,
286            XtNborderWidth, 0,
287            NULL);
288        apply_bitmap(send_toggle, receive_flag ? no_diamond : diamond);
289        XtAddCallback(send_toggle, XtNcallback, toggle_receive,
290            (XtPointer)&s_false);
291        receive_toggle = XtVaCreateManagedWidget(
292            "receive", commandWidgetClass, ft_dialog,
293            XtNfromVert, send_toggle,
294            XtNvertDistance, CLOSE_VGAP,
295            XtNhorizDistance, MARGIN,
296            XtNborderWidth, 0,
297            NULL);
298        apply_bitmap(receive_toggle, receive_flag ? diamond : no_diamond);
299        XtAddCallback(receive_toggle, XtNcallback, toggle_receive,
300            (XtPointer)&s_true);
301
302        /* Create ASCII/binary toggles. */
303        ascii_toggle = XtVaCreateManagedWidget(
304            "ascii", commandWidgetClass, ft_dialog,
305            XtNfromVert, receive_toggle,
306            XtNvertDistance, FAR_VGAP,
307            XtNhorizDistance, MARGIN,
308            XtNborderWidth, 0,
309            NULL);
310        apply_bitmap(ascii_toggle, ascii_flag ? diamond : no_diamond);
311        XtAddCallback(ascii_toggle, XtNcallback, toggle_ascii,
312            (XtPointer)&s_true);
313        binary_toggle = XtVaCreateManagedWidget(
314            "binary", commandWidgetClass, ft_dialog,
315            XtNfromVert, ascii_toggle,
316            XtNvertDistance, CLOSE_VGAP,
317            XtNhorizDistance, MARGIN,
318            XtNborderWidth, 0,
319            NULL);
320        apply_bitmap(binary_toggle, ascii_flag ? no_diamond : diamond);
321        XtAddCallback(binary_toggle, XtNcallback, toggle_ascii,
322            (XtPointer)&s_false);
323
324        /* Create append toggle. */
325        append_widget = XtVaCreateManagedWidget(
326            "append", commandWidgetClass, ft_dialog,
327            XtNfromVert, binary_toggle,
328            XtNvertDistance, FAR_VGAP,
329            XtNhorizDistance, MARGIN,
330            XtNborderWidth, 0,
331            NULL);
332        apply_bitmap(append_widget, append_flag ? dot : null);
333        XtAddCallback(append_widget, XtNcallback, toggle_append, NULL);
334
335        /* Set up the recfm group. */
336        recfm_label = XtVaCreateManagedWidget(
337            "file", labelWidgetClass, ft_dialog,
338            XtNfromVert, append_widget,
339            XtNvertDistance, FAR_VGAP,
340            XtNhorizDistance, MARGIN,
341            XtNborderWidth, 0,
342            NULL);
343        register_sensitivity(recfm_label,
344            &receive_flag, False,
345            NULL, NULL,
346            NULL, NULL);
347
348        recfm_options[0] = XtVaCreateManagedWidget(
349            "recfmDefault", commandWidgetClass, ft_dialog,
350            XtNfromVert, recfm_label,
351            XtNvertDistance, 3,
352            XtNhorizDistance, MARGIN,
353            XtNborderWidth, 0,
354            NULL);
355        apply_bitmap(recfm_options[0],
356            (recfm == DEFAULT_RECFM) ? diamond : no_diamond);
357        XtAddCallback(recfm_options[0], XtNcallback, recfm_callback,
358            (XtPointer)&r_default_recfm);
359        register_sensitivity(recfm_options[0],
360            &receive_flag, False,
361            NULL, NULL,
362            NULL, NULL);
363
364        recfm_options[1] = XtVaCreateManagedWidget(
365            "fixed", commandWidgetClass, ft_dialog,
366            XtNfromVert, recfm_options[0],
367            XtNvertDistance, CLOSE_VGAP,
368            XtNhorizDistance, MARGIN,
369            XtNborderWidth, 0,
370            NULL);
371        apply_bitmap(recfm_options[1],
372            (recfm == FIXED) ? diamond : no_diamond);
373        XtAddCallback(recfm_options[1], XtNcallback, recfm_callback,
374            (XtPointer)&r_fixed);
375        register_sensitivity(recfm_options[1],
376            &receive_flag, False,
377            NULL, NULL,
378            NULL, NULL);
379
380        recfm_options[2] = XtVaCreateManagedWidget(
381            "variable", commandWidgetClass, ft_dialog,
382            XtNfromVert, recfm_options[1],
383            XtNvertDistance, CLOSE_VGAP,
384            XtNhorizDistance, MARGIN,
385            XtNborderWidth, 0,
386            NULL);
387        apply_bitmap(recfm_options[2],
388            (recfm == VARIABLE) ? diamond : no_diamond);
389        XtAddCallback(recfm_options[2], XtNcallback, recfm_callback,
390            (XtPointer)&r_variable);
391        register_sensitivity(recfm_options[2],
392            &receive_flag, False,
393            NULL, NULL,
394            NULL, NULL);
395
396        recfm_options[3] = XtVaCreateManagedWidget(
397            "undefined", commandWidgetClass, ft_dialog,
398            XtNfromVert, recfm_options[2],
399            XtNvertDistance, CLOSE_VGAP,
400            XtNhorizDistance, MARGIN,
401            XtNborderWidth, 0,
402            NULL);
403        apply_bitmap(recfm_options[3],
404            (recfm == UNDEFINED) ? diamond : no_diamond);
405        XtAddCallback(recfm_options[3], XtNcallback, recfm_callback,
406            (XtPointer)&r_undefined);
407        register_sensitivity(recfm_options[3],
408            &receive_flag, False,
409            &vm_flag, False,
410            NULL, NULL);
411
412        lrecl_label = XtVaCreateManagedWidget(
413            "lrecl", labelWidgetClass, ft_dialog,
414            XtNfromVert, recfm_options[3],
415            XtNvertDistance, 3,
416            XtNhorizDistance, MARGIN,
417            XtNborderWidth, 0,
418            NULL);
419        register_sensitivity(lrecl_label,
420            &receive_flag, False,
421            &recfm_default, False,
422            NULL, NULL);
423        lrecl_widget = XtVaCreateManagedWidget(
424            "value", asciiTextWidgetClass, ft_dialog,
425            XtNfromVert, recfm_options[3],
426            XtNvertDistance, 3,
427            XtNfromHoriz, lrecl_label,
428            XtNhorizDistance, MARGIN,
429            XtNwidth, 100,
430            XtNeditType, XawtextEdit,
431            XtNdisplayCaret, False,
432            NULL);
433        match_dimension(lrecl_label, lrecl_widget, XtNheight);
434        w = XawTextGetSource(lrecl_widget);
435        if (w == NULL)
436                XtWarning("Cannot find text source in dialog");
437        else
438                XtAddCallback(w, XtNcallback, text_callback,
439                    (XtPointer)&t_numeric);
440        register_sensitivity(lrecl_widget,
441            &receive_flag, False,
442            &recfm_default, False,
443            NULL, NULL);
444
445        blksize_label = XtVaCreateManagedWidget(
446            "blksize", labelWidgetClass, ft_dialog,
447            XtNfromVert, lrecl_widget,
448            XtNvertDistance, 3,
449            XtNhorizDistance, MARGIN,
450            XtNborderWidth, 0,
451            NULL);
452        match_dimension(blksize_label, lrecl_label, XtNwidth);
453        register_sensitivity(blksize_label,
454            &receive_flag, False,
455            &recfm_default, False,
456            NULL, NULL);
457        blksize_widget = XtVaCreateManagedWidget(
458            "value", asciiTextWidgetClass, ft_dialog,
459            XtNfromVert, lrecl_widget,
460            XtNvertDistance, 3,
461            XtNfromHoriz, blksize_label,
462            XtNhorizDistance, MARGIN,
463            XtNwidth, 100,
464            XtNeditType, XawtextEdit,
465            XtNdisplayCaret, False,
466            NULL);
467        match_dimension(blksize_label, blksize_widget, XtNheight);
468        w = XawTextGetSource(blksize_widget);
469        if (w == NULL)
470                XtWarning("Cannot find text source in dialog");
471        else
472                XtAddCallback(w, XtNcallback, text_callback,
473                    (XtPointer)&t_numeric);
474        register_sensitivity(blksize_widget,
475            &receive_flag, False,
476            &recfm_default, False,
477            NULL, NULL);
478
479
480        /* Find the widest widget in the left column. */
481        XtVaGetValues(send_toggle, XtNwidth, &maxw, NULL);
482        h_ref = send_toggle;
483#define REMAX(w) { \
484                XtVaGetValues((w), XtNwidth, &d1, NULL); \
485                if (d1 > maxw) { \
486                        maxw = d1; \
487                        h_ref = (w); \
488                } \
489        }
490        REMAX(receive_toggle);
491        REMAX(ascii_toggle);
492        REMAX(binary_toggle);
493        REMAX(append_widget);
494#undef REMAX
495
496        /* Create the right column buttons. */
497
498        /* Create VM/TSO toggle. */
499        vm_toggle = XtVaCreateManagedWidget(
500            "vm", commandWidgetClass, ft_dialog,
501            XtNfromVert, host_label,
502            XtNvertDistance, FAR_VGAP,
503            XtNfromHoriz, h_ref,
504            XtNhorizDistance, COLUMN_GAP,
505            XtNborderWidth, 0,
506            NULL);
507        apply_bitmap(vm_toggle, vm_flag ? diamond : no_diamond);
508        XtAddCallback(vm_toggle, XtNcallback, toggle_vm, (XtPointer)&s_true);
509        tso_toggle =  XtVaCreateManagedWidget(
510            "tso", commandWidgetClass, ft_dialog,
511            XtNfromVert, vm_toggle,
512            XtNvertDistance, CLOSE_VGAP,
513            XtNfromHoriz, h_ref,
514            XtNhorizDistance, COLUMN_GAP,
515            XtNborderWidth, 0,
516            NULL);
517        apply_bitmap(tso_toggle, vm_flag ? no_diamond : diamond);
518        XtAddCallback(tso_toggle, XtNcallback, toggle_vm, (XtPointer)&s_false);
519
520        /* Create CR toggle. */
521        cr_widget = XtVaCreateManagedWidget(
522            "cr", commandWidgetClass, ft_dialog,
523            XtNfromVert, tso_toggle,
524            XtNvertDistance, FAR_VGAP,
525            XtNfromHoriz, h_ref,
526            XtNhorizDistance, COLUMN_GAP,
527            XtNborderWidth, 0,
528            NULL);
529        apply_bitmap(cr_widget, cr_flag ? dot : null);
530        XtAddCallback(cr_widget, XtNcallback, toggle_cr, 0);
531        register_sensitivity(cr_widget,
532            &ascii_flag, True,
533            NULL, NULL,
534            NULL, NULL);
535
536        /* Set up the Units group. */
537        units_label = XtVaCreateManagedWidget(
538            "units", labelWidgetClass, ft_dialog,
539            XtNfromVert, append_widget,
540            XtNvertDistance, FAR_VGAP,
541            XtNfromHoriz, h_ref,
542            XtNhorizDistance, COLUMN_GAP,
543            XtNborderWidth, 0,
544            NULL);
545        register_sensitivity(units_label,
546            &receive_flag, False,
547            &vm_flag, False,
548            NULL, NULL);
549
550        units_options[0] = XtVaCreateManagedWidget(
551            "spaceDefault", commandWidgetClass, ft_dialog,
552            XtNfromVert, units_label,
553            XtNvertDistance, 3,
554            XtNfromHoriz, h_ref,
555            XtNhorizDistance, COLUMN_GAP,
556            XtNborderWidth, 0,
557            NULL);
558        apply_bitmap(units_options[0],
559            (units == DEFAULT_UNITS) ? diamond : no_diamond);
560        XtAddCallback(units_options[0], XtNcallback,
561            units_callback, (XtPointer)&u_default_units);
562        register_sensitivity(units_options[0],
563            &receive_flag, False,
564            &vm_flag, False,
565            NULL, NULL);
566
567        units_options[1] = XtVaCreateManagedWidget(
568            "tracks", commandWidgetClass, ft_dialog,
569            XtNfromVert, units_options[0],
570            XtNvertDistance, CLOSE_VGAP,
571            XtNfromHoriz, h_ref,
572            XtNhorizDistance, COLUMN_GAP,
573            XtNborderWidth, 0,
574            NULL);
575        apply_bitmap(units_options[1],
576            (units == TRACKS) ? diamond : no_diamond);
577        XtAddCallback(units_options[1], XtNcallback,
578            units_callback, (XtPointer)&u_tracks);
579        register_sensitivity(units_options[1],
580            &receive_flag, False,
581            &vm_flag, False,
582            NULL, NULL);
583
584        units_options[2] = XtVaCreateManagedWidget(
585            "cylinders", commandWidgetClass, ft_dialog,
586            XtNfromVert, units_options[1],
587            XtNvertDistance, CLOSE_VGAP,
588            XtNfromHoriz, h_ref,
589            XtNhorizDistance, COLUMN_GAP,
590            XtNborderWidth, 0,
591            NULL);
592        apply_bitmap(units_options[2],
593            (units == CYLINDERS) ? diamond : no_diamond);
594        XtAddCallback(units_options[2], XtNcallback,
595            units_callback, (XtPointer)&u_cylinders);
596        register_sensitivity(units_options[2],
597            &receive_flag, False,
598            &vm_flag, False,
599            NULL, NULL);
600
601        units_options[3] = XtVaCreateManagedWidget(
602            "avblock", commandWidgetClass, ft_dialog,
603            XtNfromVert, units_options[2],
604            XtNvertDistance, CLOSE_VGAP,
605            XtNfromHoriz, h_ref,
606            XtNhorizDistance, COLUMN_GAP,
607            XtNborderWidth, 0,
608            NULL);
609        apply_bitmap(units_options[3],
610            (units == AVBLOCK) ? diamond : no_diamond);
611        XtAddCallback(units_options[3], XtNcallback,
612            units_callback, (XtPointer)&u_avblock);
613        register_sensitivity(units_options[3],
614            &receive_flag, False,
615            &vm_flag, False,
616            NULL, NULL);
617
618        primspace_label = XtVaCreateManagedWidget(
619            "primspace", labelWidgetClass, ft_dialog,
620            XtNfromVert, units_options[3],
621            XtNvertDistance, 3,
622            XtNfromHoriz, h_ref,
623            XtNhorizDistance, COLUMN_GAP,
624            XtNborderWidth, 0,
625            NULL);
626        register_sensitivity(primspace_label,
627            &receive_flag, False,
628            &vm_flag, False,
629            &units_default, False);
630        primspace_widget = XtVaCreateManagedWidget(
631            "value", asciiTextWidgetClass, ft_dialog,
632            XtNfromVert, units_options[3],
633            XtNvertDistance, 3,
634            XtNfromHoriz, primspace_label,
635            XtNhorizDistance, 0,
636            XtNwidth, 100,
637            XtNeditType, XawtextEdit,
638            XtNdisplayCaret, False,
639            NULL);
640        match_dimension(primspace_label, primspace_widget, XtNheight);
641        w = XawTextGetSource(primspace_widget);
642        if (w == NULL)
643                XtWarning("Cannot find text source in dialog");
644        else
645                XtAddCallback(w, XtNcallback, text_callback,
646                    (XtPointer)&t_numeric);
647        register_sensitivity(primspace_widget,
648            &receive_flag, False,
649            &vm_flag, False,
650            &units_default, False);
651
652        secspace_label = XtVaCreateManagedWidget(
653            "secspace", labelWidgetClass, ft_dialog,
654            XtNfromVert, primspace_widget,
655            XtNvertDistance, 3,
656            XtNfromHoriz, h_ref,
657            XtNhorizDistance, COLUMN_GAP,
658            XtNborderWidth, 0,
659            NULL);
660        match_dimension(primspace_label, secspace_label, XtNwidth);
661        register_sensitivity(secspace_label,
662            &receive_flag, False,
663            &vm_flag, False,
664            &units_default, False);
665        secspace_widget = XtVaCreateManagedWidget(
666            "value", asciiTextWidgetClass, ft_dialog,
667            XtNfromVert, primspace_widget,
668            XtNvertDistance, 3,
669            XtNfromHoriz, secspace_label,
670            XtNhorizDistance, 0,
671            XtNwidth, 100,
672            XtNeditType, XawtextEdit,
673            XtNdisplayCaret, False,
674            NULL);
675        match_dimension(secspace_label, secspace_widget, XtNheight);
676        w = XawTextGetSource(secspace_widget);
677        if (w == NULL)
678                XtWarning("Cannot find text source in dialog");
679        else
680                XtAddCallback(w, XtNcallback, text_callback,
681                    (XtPointer)&t_numeric);
682        register_sensitivity(secspace_widget,
683            &receive_flag, False,
684            &vm_flag, False,
685            &units_default, False);
686
687        /* Set up the buttons at the bottom. */
688        start_button = XtVaCreateManagedWidget(
689            ObjConfirmButton, commandWidgetClass, ft_dialog,
690            XtNfromVert, blksize_label,
691            XtNvertDistance, FAR_VGAP,
692            XtNhorizDistance, MARGIN,
693            NULL);
694        XtAddCallback(start_button, XtNcallback, ft_start_callback,
695            (XtPointer)NULL);
696
697        cancel_button = XtVaCreateManagedWidget(
698            ObjCancelButton, commandWidgetClass, ft_dialog,
699            XtNfromVert, blksize_label,
700            XtNvertDistance, FAR_VGAP,
701            XtNfromHoriz, start_button,
702            XtNhorizDistance, BUTTON_GAP,
703            NULL);
704        XtAddCallback(cancel_button, XtNcallback, ft_cancel, 0);
705}
706
707
708
709/* Callbacks for all the transfer widgets. */
710
711/* Transfer pop-up popping up. */
712static void
713ft_popup_callback(w, client_data, call_data)
714Widget w;
715XtPointer client_data;
716XtPointer call_data;
717{
718        /* Set the focus to the local file widget. */
719        dialog_focus_action(local_file, (XEvent *)NULL, (String *)NULL,
720            (Cardinal *)NULL);
721
722        /* Disallow overwrites. */
723        allow_overwrite = False;
724}
725
726/* Cancel button pushed. */
727static void
728ft_cancel(w, client_data, call_data)
729Widget w;
730XtPointer client_data;
731XtPointer call_data;
732{
733        XtPopdown(ft_shell);
734}
735
736/* recfm options. */
737static void
738recfm_callback(w, user_data, call_data)
739Widget w;
740XtPointer user_data;
741XtPointer call_data;
742{
743        recfm = *(enum recfm *)user_data;
744        recfm_default = (recfm == DEFAULT_RECFM);
745        check_sensitivity(&recfm_default);
746        flip_toggles(&recfm_toggles, w);
747}
748
749/* Units options. */
750static void
751units_callback(w, user_data, call_data)
752Widget w;
753XtPointer user_data;
754XtPointer call_data;
755{
756        units = *(enum units *)user_data;
757        units_default = (units == DEFAULT_UNITS);
758        check_sensitivity(&units_default);
759        flip_toggles(&units_toggles, w);
760}
761
762/* OK button pushed. */
763static void
764ft_start_callback(w, call_parms, call_data)
765Widget w;
766XtPointer call_parms;
767XtPointer call_data;
768{
769        if (ft_start()) {
770                XtPopdown(ft_shell);
771                popup_progress();
772        }
773}
774
775/* Mark a toggle. */
776static void
777mark_toggle(w, p)
778Widget w;
779Pixmap p;
780{
781#if defined(TOGGLE_HACK) /*[*/
782        String l, nl;
783
784        XtVaGetValues(w, XtNlabel, &l, NULL);
785        nl = XtNewString(l);
786        if (p == diamond)
787                nl[0] = '+';
788        else if (p == no_diamond)
789                nl[0] = '-';
790        else if (p == dot)
791                nl[0] = '*';
792        else if (p == null)
793                nl[0] = ' ';
794        XtVaSetValues(w, XtNlabel, nl, NULL);
795        XtFree(nl);
796#else /*][*/
797        XtVaSetValues(w, XtNleftBitmap, p, NULL);
798#endif /*]*/
799}
800
801/* Send/receive options. */
802static void
803toggle_receive(w, client_data, call_data)
804Widget w;
805XtPointer client_data;
806XtPointer call_data;
807{
808        /* Toggle the flag */
809        receive_flag = *(Boolean *)client_data;
810
811        /* Change the widget states. */
812        mark_toggle(receive_toggle, receive_flag ? diamond : no_diamond);
813        mark_toggle(send_toggle, receive_flag ? no_diamond : diamond);
814        check_sensitivity(&receive_flag);
815}
816
817/* Ascii/binary options. */
818static void
819toggle_ascii(w, client_data, call_data)
820Widget w;
821XtPointer client_data;
822XtPointer call_data;
823{
824        /* Toggle the flag. */
825        ascii_flag = *(Boolean *)client_data;
826
827        /* Change the widget states. */
828        mark_toggle(ascii_toggle, ascii_flag ? diamond : no_diamond);
829        mark_toggle(binary_toggle, ascii_flag ? no_diamond : diamond);
830        cr_flag = ascii_flag;
831        mark_toggle(cr_widget, cr_flag ? dot : null);
832        check_sensitivity(&ascii_flag);
833}
834
835/* CR option. */
836static void
837toggle_cr(w, client_data, call_data)
838Widget w;
839XtPointer client_data;
840XtPointer call_data;
841{
842        /* Toggle the cr flag */
843        cr_flag = !cr_flag;
844
845        mark_toggle(w, cr_flag ? dot : null);
846}
847
848/* Append option. */
849static void
850toggle_append(w, client_data, call_data)
851Widget w;
852XtPointer client_data;
853XtPointer call_data;
854{
855        /* Toggle Append Flag */
856        append_flag = !append_flag;
857
858        mark_toggle(w, append_flag ? dot : null);
859}
860
861/* TSO/VM option. */
862static void
863toggle_vm(w, client_data, call_data)
864Widget w;
865XtPointer client_data;
866XtPointer call_data;
867{
868        /* Toggle the flag. */
869        vm_flag = *(Boolean *)client_data;
870
871        /* Change the widget states. */
872        mark_toggle(vm_toggle, vm_flag ? diamond : no_diamond);
873        mark_toggle(tso_toggle, vm_flag ? no_diamond : diamond);
874
875        if (vm_flag) {
876                if (recfm == UNDEFINED) {
877                        recfm = DEFAULT_RECFM;
878                        recfm_default = True;
879                        flip_toggles(&recfm_toggles,
880                            recfm_toggles.widgets[0]);
881                }
882        }
883        check_sensitivity(&vm_flag);
884}
885
886/*
887 * Begin the transfer.
888 * Returns 1 if the transfer has started, 0 otherwise.
889 */
890static int
891ft_start()
892{
893        char opts[80];
894        char *op = opts + 1;
895        char *cmd;
896        String lrecl, blksize, primspace, secspace;
897        int flen;
898        char *host_filename;
899
900        /* Get the host file from its widget */
901        XtVaGetValues(host_file, XtNstring, &host_filename, NULL);
902        if (!*host_filename)
903                return 0;
904        /* XXX: probably more validation to do here */
905
906        /* Get the local file from it widget */
907        XtVaGetValues(local_file, XtNstring,  &ft_local_filename, NULL);
908        if (!*ft_local_filename)
909                return 0;
910
911        /* See if the local file can be overwritten. */
912        if (receive_flag && !append_flag && !allow_overwrite) {
913                ft_local_file = fopen(ft_local_filename, "r");
914                if (ft_local_file != (FILE *)NULL) {
915                        (void) fclose(ft_local_file);
916                        ft_local_file = (FILE *)NULL;
917                        popup_overwrite();
918                        return 0;
919                }
920        }
921
922        /* Open the local file. */
923        ft_local_file = fopen(ft_local_filename,
924            receive_flag ?
925                (append_flag ? "a" : "w" ) :
926                "r");
927        if (ft_local_file == (FILE *)NULL) {
928                allow_overwrite = False;
929                popup_an_errno(errno, "Open(%s)", ft_local_filename);
930                return 0;
931        }
932
933        /* Build the ind$file command */
934        op[0] = '\0';
935        if (ascii_flag)
936                strcat(op, " ascii");
937        if (cr_flag)
938                strcat(op, " crlf");
939        if (append_flag && !receive_flag)
940                strcat(op, " append");
941        if (!receive_flag) {
942                if (!vm_flag) {
943                        if (recfm != DEFAULT_RECFM) {
944                                /* RECFM Entered, process */
945                                strcat(op, " recfm(");
946                                switch (recfm) {
947                                    case FIXED:
948                                        strcat(op, "f");
949                                        break;
950                                    case VARIABLE:
951                                        strcat(op, "v");
952                                        break;
953                                    case UNDEFINED:
954                                        strcat(op, "u");
955                                        break;
956                                    default:
957                                        break;
958                                };
959                                strcat(op, ")");
960                                XtVaGetValues(lrecl_widget,
961                                    XtNstring, &lrecl,
962                                    NULL);
963                                if (strlen(lrecl) > 0)
964                                        sprintf(eos(op), " lrecl(%s)", lrecl);
965                                XtVaGetValues(blksize_widget,
966                                    XtNstring, &blksize,
967                                    NULL);
968                                if (strlen(blksize) > 0)
969                                        sprintf(eos(op), " blksize(%s)",
970                                            blksize);
971                        }
972                        if (units != DEFAULT_UNITS) {
973                                /* Space Entered, processs it */
974                                switch (units) {
975                                    case TRACKS:
976                                        strcat(op, " tracks");
977                                        break;
978                                    case CYLINDERS:
979                                        strcat(op, " cylinders");
980                                        break;
981                                    case AVBLOCK:
982                                        strcat(op, " avblock");
983                                        break;
984                                    default:
985                                        break;
986                                };
987                                XtVaGetValues(primspace_widget, XtNstring,
988                                    &primspace, NULL);
989                                if (strlen(primspace) > 0) {
990                                        sprintf(eos(op), " space(%s",
991                                            primspace);
992                                        XtVaGetValues(secspace_widget,
993                                            XtNstring, &secspace,
994                                            NULL);
995                                        if (strlen(secspace) > 0)
996                                                sprintf(eos(op), ",%s",
997                                                    secspace);
998                                        strcat(op, ")");
999                                }
1000                        }
1001                } else {
1002                        if (recfm != DEFAULT_RECFM) {
1003                                strcat(op, " recfm ");
1004                                switch (recfm) {
1005                                    case FIXED:
1006                                        strcat(op, "f");
1007                                        break;
1008                                    case VARIABLE:
1009                                        strcat(op, "v");
1010                                        break;
1011                                    default:
1012                                        break;
1013                                };
1014
1015                                XtVaGetValues(lrecl_widget,
1016                                    XtNstring, &lrecl,
1017                                    NULL);
1018                                if (strlen(lrecl) > 0)
1019                                        sprintf(eos(op), " lrecl %s", lrecl);
1020                        }
1021                }
1022        }
1023
1024        /* Insert the '(' for VM options. */
1025        if (strlen(op) > 0 && vm_flag) {
1026                opts[0] = ' ';
1027                opts[1] = '(';
1028                op = opts;
1029        }
1030
1031        /* Build the whole command. */
1032        cmd = xs_buffer("%s %s %s%s\\n",
1033            appres.ft_command,
1034            receive_flag ? "get" : "put", host_filename, op);
1035
1036        /* Erase the line and enter the command. */
1037        flen = kybd_prime();
1038        if (!flen || flen < strlen(cmd) - 1) {
1039                XtFree(cmd);
1040                popup_an_error(get_message("ftUnable"));
1041                allow_overwrite = False;
1042                return 0;
1043        }
1044        (void) emulate_input(cmd, strlen(cmd), False);
1045        XtFree(cmd);
1046
1047        /* Get this thing started. */
1048        ft_state = FT_AWAIT_ACK;
1049        ft_is_cut = False;
1050
1051        return 1;
1052}
1053
1054/* "Transfer in Progress" pop-up. */
1055
1056/* Pop up the "in progress" pop-up. */
1057static void
1058popup_progress()
1059{
1060        /* Initialize it. */
1061        if (progress_shell == (Widget)NULL)
1062                progress_popup_init();
1063
1064        /* Pop it up. */
1065        popup_popup(progress_shell, XtGrabNone);
1066}
1067
1068/* Initialize the "in progress" pop-up. */
1069static void
1070progress_popup_init()
1071{
1072        Widget progress_pop, from_label, to_label, cancel_button;
1073
1074        /* Create the shell. */
1075        progress_shell = XtVaCreatePopupShell(
1076            "ftProgressPopup", transientShellWidgetClass, toplevel,
1077            NULL);
1078        XtAddCallback(progress_shell, XtNpopupCallback, place_popup,
1079            (XtPointer)CenterP);
1080        XtAddCallback(progress_shell, XtNpopupCallback,
1081            progress_popup_callback, (XtPointer)NULL);
1082
1083        /* Create a form structure to contain the other stuff */
1084        progress_pop = XtVaCreateManagedWidget(
1085            "dialog", formWidgetClass, progress_shell,
1086            NULL);
1087
1088        /* Create the widgets. */
1089        from_label = XtVaCreateManagedWidget(
1090            "fromLabel", labelWidgetClass, progress_pop,
1091            XtNvertDistance, FAR_VGAP,
1092            XtNhorizDistance, MARGIN,
1093            XtNborderWidth, 0,
1094            NULL);
1095        from_file = XtVaCreateManagedWidget(
1096            "filename", labelWidgetClass, progress_pop,
1097            XtNwidth, FILE_WIDTH,
1098            XtNvertDistance, FAR_VGAP,
1099            XtNfromHoriz, from_label,
1100            XtNhorizDistance, 0,
1101            NULL);
1102        match_dimension(from_label, from_file, XtNheight);
1103
1104        to_label = XtVaCreateManagedWidget(
1105            "toLabel", labelWidgetClass, progress_pop,
1106            XtNfromVert, from_label,
1107            XtNvertDistance, FAR_VGAP,
1108            XtNhorizDistance, MARGIN,
1109            XtNborderWidth, 0,
1110            NULL);
1111        to_file = XtVaCreateManagedWidget(
1112            "filename", labelWidgetClass, progress_pop,
1113            XtNwidth, FILE_WIDTH,
1114            XtNfromVert, from_label,
1115            XtNvertDistance, FAR_VGAP,
1116            XtNfromHoriz, to_label,
1117            XtNhorizDistance, 0,
1118            NULL);
1119        match_dimension(to_label, to_file, XtNheight);
1120
1121        match_dimension(from_label, to_label, XtNwidth);
1122
1123        waiting = XtVaCreateManagedWidget(
1124            "waiting", labelWidgetClass, progress_pop,
1125            XtNfromVert, to_label,
1126            XtNvertDistance, FAR_VGAP,
1127            XtNhorizDistance, MARGIN,
1128            XtNborderWidth, 0,
1129            XtNmappedWhenManaged, False,
1130            NULL);
1131
1132        ft_status = XtVaCreateManagedWidget(
1133            "status", labelWidgetClass, progress_pop,
1134            XtNfromVert, to_label,
1135            XtNvertDistance, FAR_VGAP,
1136            XtNhorizDistance, MARGIN,
1137            XtNborderWidth, 0,
1138            XtNresizable, True,
1139            XtNmappedWhenManaged, False,
1140            NULL);
1141        XtVaGetValues(ft_status, XtNlabel, &status_string, NULL);
1142        status_string = XtNewString(status_string);
1143
1144        aborting = XtVaCreateManagedWidget(
1145            "aborting", labelWidgetClass, progress_pop,
1146            XtNfromVert, to_label,
1147            XtNvertDistance, FAR_VGAP,
1148            XtNhorizDistance, MARGIN,
1149            XtNborderWidth, 0,
1150            XtNmappedWhenManaged, False,
1151            NULL);
1152
1153        cancel_button = XtVaCreateManagedWidget(
1154            ObjCancelButton, commandWidgetClass, progress_pop,
1155            XtNfromVert, ft_status,
1156            XtNvertDistance, FAR_VGAP,
1157            XtNhorizDistance, MARGIN,
1158            NULL);
1159        XtAddCallback(cancel_button, XtNcallback, progress_cancel_callback,
1160            NULL);
1161}
1162
1163/* Callbacks for the "in progress" pop-up. */
1164
1165/* In-progress pop-up popped up. */
1166static void
1167progress_popup_callback(w, client_data, call_data)
1168Widget w;
1169XtPointer client_data;
1170XtPointer call_data;
1171{
1172        String hf, lf;
1173
1174        XtVaGetValues(host_file, XtNstring, &hf, NULL);
1175        XtVaGetValues(local_file, XtNstring, &lf, NULL);
1176
1177        XtVaSetValues(from_file, XtNlabel, receive_flag ? hf : lf, NULL);
1178        XtVaSetValues(to_file, XtNlabel, receive_flag ? lf : hf, NULL);
1179
1180        switch (ft_state) {
1181            case FT_AWAIT_ACK:
1182                XtUnmapWidget(ft_status);
1183                XtUnmapWidget(aborting);
1184                XtMapWidget(waiting);
1185                break;
1186            case FT_RUNNING:
1187                XtUnmapWidget(waiting);
1188                XtUnmapWidget(aborting);
1189                XtMapWidget(ft_status);
1190                break;
1191            case FT_ABORT_WAIT:
1192            case FT_ABORT_SENT:
1193                XtUnmapWidget(waiting);
1194                XtUnmapWidget(ft_status);
1195                XtMapWidget(aborting);
1196                break;
1197            default:
1198                break;
1199        }
1200}
1201
1202/* In-progress "cancel" button. */
1203static void
1204progress_cancel_callback(w, client_data, call_data)
1205Widget w;
1206XtPointer client_data;
1207XtPointer call_data;
1208{
1209        if (ft_state == FT_RUNNING) {
1210                ft_state = FT_ABORT_WAIT;
1211                XtUnmapWidget(waiting);
1212                XtUnmapWidget(ft_status);
1213                XtMapWidget(aborting);
1214        } else {
1215                /* Impatient user or hung host -- just clean up. */
1216                ft_complete(get_message("ftUserCancel"));
1217        }
1218}
1219
1220/* "Overwrite existing?" pop-up. */
1221
1222/* Pop up the "overwrite" pop-up. */
1223static void
1224popup_overwrite()
1225{
1226        /* Initialize it. */
1227        if (overwrite_shell == (Widget)NULL)
1228                overwrite_popup_init();
1229
1230        /* Pop it up. */
1231        popup_popup(overwrite_shell, XtGrabExclusive);
1232}
1233
1234/* Initialize the "overwrite" pop-up. */
1235static void
1236overwrite_popup_init()
1237{
1238        Widget overwrite_pop, overwrite_name, okay_button, cancel_button;
1239        String overwrite_string, label, lf;
1240        Dimension d;
1241
1242        /* Create the shell. */
1243        overwrite_shell = XtVaCreatePopupShell(
1244            "ftOverwritePopup", transientShellWidgetClass, toplevel,
1245            NULL);
1246        XtAddCallback(overwrite_shell, XtNpopupCallback, place_popup,
1247            (XtPointer)CenterP);
1248        XtAddCallback(overwrite_shell, XtNpopdownCallback, overwrite_popdown,
1249            (XtPointer)NULL);
1250
1251        /* Create a form structure to contain the other stuff */
1252        overwrite_pop = XtVaCreateManagedWidget(
1253            "dialog", formWidgetClass, overwrite_shell,
1254            NULL);
1255
1256        /* Create the widgets. */
1257        overwrite_name = XtVaCreateManagedWidget(
1258            "overwriteName", labelWidgetClass, overwrite_pop,
1259            XtNvertDistance, MARGIN,
1260            XtNhorizDistance, MARGIN,
1261            XtNborderWidth, 0,
1262            XtNresizable, True,
1263            NULL);
1264        XtVaGetValues(overwrite_name, XtNlabel, &overwrite_string, NULL);
1265        XtVaGetValues(local_file, XtNstring, &lf, NULL);
1266        label = xs_buffer(overwrite_string, lf);
1267        XtVaSetValues(overwrite_name, XtNlabel, label, NULL);
1268        XtFree(label);
1269        XtVaGetValues(overwrite_name, XtNwidth, &d, NULL);
1270        if ((Dimension)(d + 20) < 400)
1271                d = 400;
1272        else
1273                d += 20;
1274        XtVaSetValues(overwrite_name, XtNwidth, d, NULL);
1275        XtVaGetValues(overwrite_name, XtNheight, &d, NULL);
1276        XtVaSetValues(overwrite_name, XtNheight, d + 10, NULL);
1277
1278        okay_button = XtVaCreateManagedWidget(
1279            ObjConfirmButton, commandWidgetClass, overwrite_pop,
1280            XtNfromVert, overwrite_name,
1281            XtNvertDistance, FAR_VGAP,
1282            XtNhorizDistance, MARGIN,
1283            NULL);
1284        XtAddCallback(okay_button, XtNcallback, overwrite_okay_callback,
1285            NULL);
1286
1287        cancel_button = XtVaCreateManagedWidget(
1288            ObjCancelButton, commandWidgetClass, overwrite_pop,
1289            XtNfromVert, overwrite_name,
1290            XtNvertDistance, FAR_VGAP,
1291            XtNfromHoriz, okay_button,
1292            XtNhorizDistance, BUTTON_GAP,
1293            NULL);
1294        XtAddCallback(cancel_button, XtNcallback, overwrite_cancel_callback,
1295            NULL);
1296}
1297
1298/* Overwrite "okay" button. */
1299static void
1300overwrite_okay_callback(w, client_data, call_data)
1301Widget w;
1302XtPointer client_data;
1303XtPointer call_data;
1304{
1305        XtPopdown(overwrite_shell);
1306
1307        allow_overwrite = True;
1308        if (ft_start()) {
1309                XtPopdown(ft_shell);
1310                popup_progress();
1311        }
1312}
1313
1314/* Overwrite "cancel" button. */
1315static void
1316overwrite_cancel_callback(w, client_data, call_data)
1317Widget w;
1318XtPointer client_data;
1319XtPointer call_data;
1320{
1321        XtPopdown(overwrite_shell);
1322}
1323
1324/* Overwrite pop-up popped down. */
1325static void
1326overwrite_popdown(w, client_data, call_data)
1327Widget w;
1328XtPointer client_data;
1329XtPointer call_data;
1330{
1331        XtDestroyWidget(overwrite_shell);
1332        overwrite_shell = (Widget)NULL;
1333}
1334
1335/* External entry points called by ft_dft and ft_cut. */
1336
1337/* Pop up a message, end the transfer. */
1338void
1339ft_complete(errmsg)
1340String errmsg;
1341{
1342        /* Close the local file. */
1343        if (ft_local_file != (FILE *)NULL && fclose(ft_local_file) < 0)
1344                popup_an_errno(errno, "close(%s)", ft_local_filename);
1345        ft_local_file = (FILE *)NULL;
1346
1347        /* Clean up the state. */
1348        ft_state = FT_NONE;
1349
1350        /* Pop down the in-progress shell. */
1351        XtPopdown(progress_shell);
1352
1353        /* Pop up the text. */
1354        if (errmsg != (String)NULL) {
1355                /* Make sure the error message will fit on the display. */
1356                if (strlen(errmsg) > 50 && strchr(errmsg, '\n') == CN) {
1357                        char *s = errmsg + 50;
1358
1359                        while (s > errmsg && *s != ' ')
1360                                s--;
1361                        if (s > errmsg)
1362                                *s = '\n';
1363                }
1364                popup_an_error(errmsg);
1365                XtFree(errmsg);
1366        } else {
1367                struct timeval t1;
1368                double kbytes_sec;
1369                char *buf;
1370
1371                (void) gettimeofday(&t1, (struct timezone *)NULL);
1372                kbytes_sec = (double)ft_length / 1024.0 /
1373                        ((double)(t1.tv_sec - t0.tv_sec) +
1374                         (double)(t1.tv_usec - t0.tv_usec) / 1.0e6);
1375                buf = XtMalloc(256);
1376                (void) sprintf(buf, get_message("ftComplete"), ft_length,
1377                    kbytes_sec, ft_is_cut ? "CUT" : "DFT");
1378                popup_an_info(buf);
1379                XtFree(buf);
1380        }
1381}
1382
1383/* Update the bytes-transferred count on the progress pop-up. */
1384void
1385ft_update_length()
1386{
1387        char text_string[80];
1388
1389        /* Format the message */
1390        sprintf(text_string, status_string, ft_length);
1391
1392        XtVaSetValues(ft_status, XtNlabel, text_string, NULL);
1393}
1394
1395/* Process a transfer acknowledgement. */
1396void
1397ft_running(is_cut)
1398Boolean is_cut;
1399{
1400        if (ft_state == FT_AWAIT_ACK)
1401                ft_state = FT_RUNNING;
1402        ft_is_cut = is_cut;
1403        (void) gettimeofday(&t0, (struct timezone *)NULL);
1404        ft_length = 0;
1405
1406        XtUnmapWidget(waiting);
1407        ft_update_length();
1408        XtMapWidget(ft_status);
1409}
1410
1411/* Process a protocol-generated abort. */
1412void
1413ft_aborting()
1414{
1415        if (ft_state == FT_RUNNING || ft_state == FT_ABORT_WAIT) {
1416                ft_state = FT_ABORT_SENT;
1417                XtUnmapWidget(waiting);
1418                XtUnmapWidget(ft_status);
1419                XtMapWidget(aborting);
1420        }
1421}
1422
1423/* Process a disconnect abort. */
1424void
1425ft_disconnected()
1426{
1427        if (ft_state != FT_NONE)
1428                ft_complete(get_message("ftDisconnected"));
1429}
1430
1431/* Process an abort from no longer being in 3270 mode. */
1432void
1433ft_not3270()
1434{
1435        if (ft_state != FT_NONE)
1436                ft_complete(get_message("ftNot3270"));
1437}
1438
1439/* Support functions for dialogs. */
1440
1441/* Match one dimension of two widgets. */
1442static void
1443match_dimension(w1, w2, n)
1444Widget w1;
1445Widget w2;
1446String n;
1447{
1448        Dimension h1, h2;
1449        Dimension b1, b2;
1450
1451        XtVaGetValues(w1, n, &h1, XtNborderWidth, &b1, NULL);
1452        XtVaGetValues(w2, n, &h2, XtNborderWidth, &b2, NULL);
1453        h1 += 2 * b1;
1454        h2 += 2 * b2;
1455        if (h1 > h2)
1456                XtVaSetValues(w2, n, h1 - (2 * b2), NULL);
1457        else if (h2 > h1)
1458                XtVaSetValues(w1, n, h2 - (2 * b1), NULL);
1459}
1460
1461/* Apply a bitmap to a widget. */
1462static void
1463apply_bitmap(w, p)
1464Widget w;
1465Pixmap p;
1466{
1467        Dimension d1;
1468#if defined(TOGGLE_HACK) /*[*/
1469        String l, nl;
1470#endif /*]*/
1471
1472        XtVaGetValues(w, XtNheight, &d1, NULL);
1473        if (d1 < 10)
1474                XtVaSetValues(w, XtNheight, 10, NULL);
1475#if defined(TOGGLE_HACK) /*[*/
1476        XtVaGetValues(w, XtNlabel, &l, NULL);
1477        nl = XtMalloc(strlen(l) + 6);
1478        if (p == diamond)
1479                (void) sprintf(nl, "+  %s", l);
1480        else if (p == dot)
1481                (void) sprintf(nl, "*  %s", l);
1482        else if (p == no_diamond)
1483                (void) sprintf(nl, "-  %s", l);
1484        else if (p == null)
1485                (void) sprintf(nl, "   %s", l);
1486        XtVaSetValues(w,
1487            XtNlabel, nl,
1488            NULL);
1489        XtFree(nl);
1490#else /*][*/
1491        XtVaSetValues(w, XtNleftBitmap, p, NULL);
1492#endif /*]*/
1493}
1494
1495/* Flip a multi-valued toggle. */
1496static void
1497flip_toggles(toggle_list, w)
1498struct toggle_list *toggle_list;
1499Widget w;
1500{
1501        int i;
1502
1503        /* Flip the widget w to on, and the rest to off. */
1504        for (i = 0; toggle_list->widgets[i] != (Widget)NULL; i++) {
1505                /* Process each widget in the list */
1506                mark_toggle(*(toggle_list->widgets+i),
1507                    (*(toggle_list->widgets+i) == w) ? diamond : no_diamond);
1508        }
1509}
1510
1511/*
1512 * Callback for text source changes.  Edits the text to ensure it meets the
1513 * specified criteria.
1514 */
1515static void
1516text_callback(w, client_data, call_data)
1517Widget w;
1518XtPointer client_data;
1519XtPointer call_data;
1520{
1521        XawTextBlock b;         /* firstPos, length, ptr, format */
1522        static XawTextBlock nullb = { 0, 0, NULL };
1523        XawTextPosition pos = 0;
1524        int i;
1525        text_t t = *(text_t *)client_data;
1526        static Boolean called_back = False;
1527
1528        if (called_back)
1529                return;
1530        else
1531                called_back = True;
1532
1533        while (1) {
1534                Boolean replaced = False;
1535
1536                XawTextSourceRead(w, pos, &b, 1024);
1537                if (b.length <= 0)
1538                        break;
1539                nullb.format = b.format;
1540                for (i = 0; i < b.length; i++) {
1541                        Boolean bad = False;
1542                        char c = *(b.ptr + i);
1543
1544                        switch (t) {
1545                            case T_NUMERIC:
1546                                /* Only numbers. */
1547                                bad = !isdigit(c);
1548                                break;
1549                            case T_HOSTFILE:
1550                                /*
1551                                 * Only printing characters and spaces; no
1552                                 * leading or trailing blanks.
1553                                 */
1554                                bad = !isprint(c) || (!pos && !i && c == ' ');
1555                                break;
1556                            case T_UNIXFILE:
1557                                /* Only printing characters. */
1558                                bad = !isgraph(c);
1559                                break;
1560                        }
1561                        if (bad) {
1562                                XawTextSourceReplace(w, pos + i, pos + i + 1,
1563                                    &nullb);
1564                                pos = 0;
1565                                replaced = True;
1566                                break;
1567                        }
1568                }
1569                if (replaced)
1570                        continue; /* rescan the same block */
1571                pos += b.length;
1572                if (b.length < 1024)
1573                        break;
1574        }
1575        called_back = False;
1576}
1577
1578/* Register widget sensitivity, based on zero to three Booleans. */
1579static void
1580register_sensitivity(w, bvar1, bval1, bvar2, bval2, bvar3, bval3)
1581Widget w;
1582Boolean *bvar1;
1583Boolean bval1;
1584Boolean *bvar2;
1585Boolean bval2;
1586Boolean *bvar3;
1587Boolean bval3;
1588{
1589        sr_t *s;
1590        Boolean f;
1591
1592        /* Allocate a structure. */
1593        s = (sr_t *)XtMalloc(sizeof(sr_t));
1594        s->w = w;
1595        s->bvar1 = bvar1;
1596        s->bval1 = bval1;
1597        s->bvar2 = bvar2;
1598        s->bval2 = bval2;
1599        s->bvar3 = bvar3;
1600        s->bval3 = bval3;
1601        s->is_value = !strcmp(XtName(w), "value");
1602        s->has_focus = False;
1603
1604        /* Link it onto the chain. */
1605        s->next = (sr_t *)NULL;
1606        if (sr_last != (sr_t *)NULL)
1607                sr_last->next = s;
1608        else
1609                sr = s;
1610        sr_last = s;
1611
1612        /* Set up the initial widget sensitivity. */
1613        if (bvar1 == (Boolean *)NULL)
1614                f = True;
1615        else {
1616                f = (*bvar1 == bval1);
1617                if (bvar2 != (Boolean *)NULL)
1618                        f &= (*bvar2 == bval2);
1619                if (bvar3 != (Boolean *)NULL)
1620                        f &= (*bvar3 == bval3);
1621        }
1622        XtVaSetValues(w, XtNsensitive, f, NULL);
1623}
1624
1625/* Scan the list of registered widgets for a sensitivity change. */
1626static void
1627check_sensitivity(bvar)
1628Boolean *bvar;
1629{
1630        sr_t *s;
1631
1632        for (s = sr; s != (sr_t *)NULL; s = s->next) {
1633                if (s->bvar1 == bvar || s->bvar2 == bvar || s->bvar3 == bvar) {
1634                        Boolean f;
1635
1636                        f = (s->bvar1 != (Boolean *)NULL &&
1637                             (*s->bvar1 == s->bval1));
1638                        if (s->bvar2 != (Boolean *)NULL)
1639                                f &= (*s->bvar2 == s->bval2);
1640                        if (s->bvar3 != (Boolean *)NULL)
1641                                f &= (*s->bvar3 == s->bval3);
1642                        XtVaSetValues(s->w, XtNsensitive, f, NULL);
1643
1644                        /* If it is now insensitive, move the focus. */
1645                        if (!f && s->is_value && s->has_focus)
1646                                focus_next(s);
1647                }
1648        }
1649}
1650
1651/* Move the input focus to the next sensitive value field. */
1652static void
1653focus_next(s)
1654sr_t *s;
1655{
1656        sr_t *t;
1657        Boolean sen;
1658
1659        /* Defocus this widget. */
1660        s->has_focus = False;
1661        XawTextDisplayCaret(s->w, False);
1662
1663        /* Search after. */
1664        for (t = s->next; t != (sr_t *)NULL; t = t->next) {
1665                if (t->is_value) {
1666                        XtVaGetValues(t->w, XtNsensitive, &sen, NULL);
1667                        if (sen)
1668                                break;
1669                }
1670        }
1671
1672        /* Wrap and search before. */
1673        if (t == (sr_t *)NULL)
1674                for (t = sr; t != s && t != (sr_t *)NULL; t = t->next) {
1675                        if (t->is_value) {
1676                                XtVaGetValues(t->w, XtNsensitive, &sen, NULL);
1677                                if (sen)
1678                                        break;
1679                        }
1680                }
1681
1682        /* Move the focus. */
1683        if (t != (sr_t *)NULL && t != s) {
1684                t->has_focus = True;
1685                XawTextDisplayCaret(t->w, True);
1686                XtSetKeyboardFocus(ft_dialog, t->w);
1687        }
1688}
1689
1690/* Dialog action procedures. */
1691
1692/* Proceed to the next input field. */
1693void
1694dialog_next_action(w, event, parms, num_parms)
1695Widget w;
1696XEvent *event;
1697String *parms;
1698Cardinal *num_parms;
1699{
1700        sr_t *s;
1701
1702        for (s = sr; s != (sr_t *)NULL; s = s->next) {
1703                if (s->w == w) {
1704                        focus_next(s);
1705                        return;
1706                }
1707        }
1708}
1709
1710/* Set keyboard focus to an input field. */
1711void
1712dialog_focus_action(w, event, parms, num_parms)
1713Widget w;
1714XEvent *event;
1715String *parms;
1716Cardinal *num_parms;
1717{
1718        sr_t *s;
1719
1720        /* Remove the focus from the widget that has it now. */
1721        for (s = sr; s != (sr_t *)NULL; s = s->next) {
1722                if (s->has_focus) {
1723                        if (s->w == w)
1724                                return;
1725                        s->has_focus = False;
1726                        XawTextDisplayCaret(s->w, False);
1727                        break;
1728                }
1729        }
1730
1731        /* Find this object. */
1732        for (s = sr; s != (sr_t *)NULL; s = s->next) {
1733                if (s->w == w)
1734                        break;
1735        }
1736        if (s == (sr_t *)NULL)
1737                return;
1738
1739        /* Give it the focus. */
1740        s->has_focus = True;
1741        XawTextDisplayCaret(w, True);
1742        XtSetKeyboardFocus(ft_dialog, w);
1743}
Note: See TracBrowser for help on using the repository browser.