rpc.cmsd: use TIRPC on Linux
[oweals/cde.git] / cde / programs / dtlogin / vgsiaform.c
1 /*
2  * CDE - Common Desktop Environment
3  *
4  * Copyright (c) 1993-2012, The Open Group. All rights reserved.
5  *
6  * These libraries and programs are free software; you can
7  * redistribute them and/or modify them under the terms of the GNU
8  * Lesser General Public License as published by the Free Software
9  * Foundation; either version 2 of the License, or (at your option)
10  * any later version.
11  *
12  * These libraries and programs are distributed in the hope that
13  * they will be useful, but WITHOUT ANY WARRANTY; without even the
14  * implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
15  * PURPOSE. See the GNU Lesser General Public License for more
16  * details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with these libraries and programs; if not, write
20  * to the Free Software Foundation, Inc., 51 Franklin Street, Fifth
21  * Floor, Boston, MA 02110-1301 USA
22  */
23 /* $XConsortium: vgsiaform.c /main/5 1996/05/07 12:22:34 drk $ */
24 /*                                                                      *
25  * (c) Copyright 1993, 1994 Hewlett-Packard Company                     *
26  * (c) Copyright 1993, 1994 International Business Machines Corp.       *
27  * (c) Copyright 1993, 1994 Sun Microsystems, Inc.                      *
28  * (c) Copyright 1993, 1994 Novell, Inc.                                *
29  */
30
31 /*
32  * @DEC_COPYRIGHT@
33  */
34 /*
35  * HISTORY
36  * $Log$
37  * Revision 1.1.2.2  1995/06/06  19:39:54  Chris_Beute
38  *      New file added for SIA password expiration forms handling
39  *      [1995/05/31  19:52:41  Chris_Beute]
40  *
41  * Revision 1.1.2.2  1995/05/22  18:13:32  Peter_Derr
42  *      Add a Cancel button.
43  *      [1995/05/15  18:06:21  Peter_Derr]
44  * 
45  *      Support SIAMENUONE and SIAMENUANY
46  *      [1995/05/12  20:29:53  Peter_Derr]
47  * 
48  *      SIA form UI
49  *      [1995/05/11  22:09:09  Peter_Derr]
50  * 
51  * $EndLog$
52  */
53
54 #include "vg.h"
55 #include "vgmsg.h"
56 #include <alloca.h>
57 #include <Xm/Xm.h>
58 #include <Xm/Form.h>
59 #include <Xm/Label.h>
60 #include <Xm/PushB.h>
61 #include <Xm/RowColumn.h>
62 #include <Xm/TextF.h>
63 #include <Xm/ToggleBG.h>
64
65 XmString multiline_xmstring(char *);
66 static void NoEchoCB( Widget, XtPointer, XtPointer);
67 static void RespondSiaFormCB( Widget, XtPointer, XtPointer);
68 static void CancelSiaFormCB( Widget, XtPointer, XtPointer);
69 static void SiaBackspace( Widget, XEvent *, char **, Cardinal *);
70
71
72 static char textEventBindings[] = {
73 "<Key>Return:                           next-tab-group()"
74 };
75
76 static char activateBindings[] = {
77 "<Key>osfActivate:                      activate()\n\
78   Ctrl <Key>Return:                     activate()\n\
79  <Key>Return:                           activate()"
80 };
81
82 static char activatePBBindings[] = {
83 "<Key>osfActivate:                      ArmAndActivate()\n\
84   Ctrl <Key>Return:                     ArmAndActivate()\n\
85  <Key>Return:                           ArmAndActivate()"
86 };
87
88 static char noEchoBindings[] = {
89 "Ctrl<Key>:                             my-insert()\n\
90  <Key>osfBackSpace:                     sia-bksp()\n\
91  <Key>osfDelete:                        sia-bksp()"
92 };
93
94 static XtActionsRec textActions[] = {
95         {"sia-bksp", (XtActionProc)SiaBackspace},
96     };
97
98
99
100 SiaFormInfo *globalSiaFormInfo;
101
102 /***************************************************************************
103  *
104  *  SiaForm
105  *
106  *  Widgets: sia_form, sia_title, sia_prompts
107  ***************************************************************************/
108
109 void 
110 SiaForm(SiaFormInfo *siaFormInfo)
111 {
112     int i;
113     int j;
114     LoginTextPtr textdata; 
115     XtTranslations      textTable;
116     Widget sia_form, title_label, ok_button, cancel_button, prompts_row_col;
117     Widget *prompt_labels;
118     Widget *prompt_answers;
119     XmString xmstr;
120     XtTranslations noecho_trans, text_trans, activate_trans, activatePBtrans;
121
122     globalSiaFormInfo = siaFormInfo;
123     siaFormInfo->collect_status = 1;
124     /*
125      * XmCreateFormDialog()
126      * XmCreateLabel()
127      * XmCreateRowColumn()
128      *   for each prompt
129      *     XmCreateLabel()
130      *     XmCreateTextField()
131      *     if not visible
132      *          add ModifyVerify callback
133      * XmCreatePushButton
134      *          PB callback will collect answers, send them down the pipe
135      *          and destroy the sia_form.
136      */
137
138
139     /*
140      *  create the SIA form
141      */
142
143     i = 0;
144     i = InitArg(Form); 
145     XtSetArg(argt[i], XmNmarginHeight,          MBOX_MARGIN_HEIGHT      ); i++;
146     XtSetArg(argt[i], XmNmarginWidth,           MBOX_MARGIN_WIDTH       ); i++;
147     XtSetArg(argt[i], XmNshadowThickness,       SHADOW_THICKNESS        ); i++;
148     XtSetArg(argt[i], XmNnoResize,              False                   ); i++;
149     XtSetArg(argt[i], XmNresizePolicy,          XmRESIZE_ANY            ); i++;
150
151     sia_form = XmCreateFormDialog(login_shell, "sia_form", argt, i);
152     siaFormInfo->sia_form_widget = sia_form;
153
154     /*
155      *  create the title label
156      */
157     /* i = 0; */
158     i = InitArg(Label);
159     XtSetArg(argt[i], XmNlabelString,           siaFormInfo->title      ); i++;
160     XtSetArg(argt[i], XmNtraversalOn,           False                   ); i++;
161     XtSetArg(argt[i], XmNtopAttachment,         XmATTACH_FORM           ); i++;
162     XtSetArg(argt[i], XmNleftAttachment,        XmATTACH_FORM           ); i++;
163     XtSetArg(argt[i], XmNrightAttachment,       XmATTACH_FORM           ); i++;
164     XtSetArg(argt[i], XmNalignment,             XmALIGNMENT_CENTER      ); i++;
165     xmstr = multiline_xmstring(siaFormInfo->title);
166     XtSetArg(argt[i], XmNlabelString,           xmstr                   ); i++;
167     
168     title_label = XmCreateLabel(sia_form, "title_label", argt, i);
169     XtManageChild(title_label);
170
171     XmStringFree(xmstr);
172
173
174     /* ok button */
175
176     activate_trans = XtParseTranslationTable(activateBindings);
177     activatePBtrans = XtParseTranslationTable(activatePBBindings);
178     
179     i = InitArg(PushB);
180     XtSetArg(argt[i], XmNbottomAttachment,      XmATTACH_FORM           ); i++;
181     XtSetArg(argt[i], XmNtraversalOn,           True                    ); i++;
182     xmstr = ReadCatalogXms(MC_LABEL_SET, MC_OK_LABEL, MC_DEF_OK_LABEL );
183     XtSetArg(argt[i], XmNlabelString,           xmstr                   ); i++;
184
185     ok_button = XmCreatePushButton(sia_form, "ok_button", argt, i);
186
187     XtOverrideTranslations(ok_button, activatePBtrans);
188
189     XmStringFree(xmstr);
190     XtManageChild(ok_button);
191
192     XtAddCallback(ok_button, XmNactivateCallback, RespondSiaFormCB, 
193                         siaFormInfo);    
194
195
196     /* Cancel button */
197
198     i = InitArg(PushB);
199     XtSetArg(argt[i], XmNbottomAttachment,      XmATTACH_FORM           ); i++;
200     XtSetArg(argt[i], XmNtraversalOn,           True                    ); i++;
201     xmstr = ReadCatalogXms(MC_LABEL_SET, MC_CANCEL_LABEL, MC_DEF_CANCEL_LABEL );
202     XtSetArg(argt[i], XmNlabelString,           xmstr                   ); i++;
203
204     cancel_button = XmCreatePushButton(sia_form, "cancel_button", argt, i);
205
206     XmStringFree(xmstr);
207     XtManageChild(cancel_button);
208
209     XtAddCallback(cancel_button, XmNactivateCallback, CancelSiaFormCB, 
210                         siaFormInfo);    
211
212     /*
213      * create the RowColumn widget for prompts
214      */
215
216     i =0;
217     XtSetArg(argt[i], XmNorientation,           XmHORIZONTAL            ); i++;
218     XtSetArg(argt[i], XmNentryVerticalAlignment, XmALIGNMENT_CENTER     ); i++;
219     XtSetArg(argt[i], XmNrowColumnType,         XmWORK_AREA             ); i++;
220     XtSetArg(argt[i], XmNnumColumns,            siaFormInfo->num_prompts); i++;
221     XtSetArg(argt[i], XmNpacking,               XmPACK_COLUMN           ); i++;
222     XtSetArg(argt[i], XmNtopAttachment,         XmATTACH_WIDGET         ); i++;
223     XtSetArg(argt[i], XmNtopWidget,             title_label             ); i++;
224     XtSetArg(argt[i], XmNbottomAttachment,      XmATTACH_WIDGET         ); i++;
225     XtSetArg(argt[i], XmNbottomWidget,          ok_button               ); i++;
226     XtSetArg(argt[i], XmNleftAttachment,        XmATTACH_FORM           ); i++;
227     XtSetArg(argt[i], XmNrightAttachment,       XmATTACH_FORM           ); i++;
228
229     switch (siaFormInfo->rendition)
230         {
231         case SIAMENUONE:
232             XtSetArg(argt[i], XmNradioBehavior,         True    ); i++;
233             /* no break */
234         case SIAMENUANY:
235             XtSetArg(argt[i], XmNisHomogeneous,         True            ); i++;
236             XtSetArg(argt[i], XmNentryClass,   xmToggleButtonGadgetClass); i++;
237             XtSetArg(argt[i], XmNentryAlignment,  XmALIGNMENT_BEGINNING ); i++;
238             break;
239
240         case SIAONELINER:
241             /* no break */
242         case SIAFORM:
243             XtSetArg(argt[i], XmNentryAlignment,        XmALIGNMENT_END ); i++;
244         }
245
246     prompts_row_col = XmCreateRowColumn(sia_form, "prompts_row_col", argt, i);
247     XtManageChild(prompts_row_col);
248
249     prompt_labels = (Widget *) alloca(sizeof(Widget *) * siaFormInfo->num_prompts);
250     prompt_answers = siaFormInfo->answer_widgets;
251
252     noecho_trans = XtParseTranslationTable(noEchoBindings);
253     text_trans = XtParseTranslationTable(textEventBindings);
254
255     for (j=0; j<siaFormInfo->num_prompts; j++)
256         {
257         /*
258          *  create the prompt label
259          */
260         char label_name[81];
261         char answer_name[81];
262
263         sprintf(label_name,"Prompt %d",j);
264         sprintf(answer_name,"Answer %d",j);
265         xmstr = multiline_xmstring(siaFormInfo->prompts[j]);
266
267         switch (siaFormInfo->rendition)
268             {
269             case SIAMENUANY:
270             case SIAMENUONE:
271                 {
272                 /* i = InitArg(ToggleBG); */
273                 i = 0;
274                 XtSetArg(argt[i], XmNtraversalOn,       True            ); i++;
275                 XtSetArg(argt[i], XmNlabelString,       xmstr           ); i++;
276                 
277                 prompt_answers[j]  = XmCreateToggleButtonGadget(prompts_row_col,
278                                                 answer_name, argt, i);
279                 }
280                 break;
281
282             case SIAONELINER:
283                 /* no break */
284             case SIAFORM:
285                 {
286                 i = 0;
287                 XtSetArg(argt[i], XmNtraversalOn,       True            ); i++;
288                 XtSetArg(argt[i], XmNlabelString,       xmstr           ); i++;
289                 
290                 prompt_labels[j]  = XmCreateLabel(prompts_row_col, label_name, 
291                                                         argt, i);
292                 XtManageChild(prompt_labels[j]);
293
294                 /*
295                  *  create the answer text field
296                  */
297
298                 i = InitArg(Text);
299                 XtSetArg(argt[i], XmNselectionArrayCount,       1       ); i++;
300                 XtSetArg(argt[i], XmNmaxLength,         80              ); i++;
301                 XtSetArg(argt[i], XmNmappedWhenManaged, True            ); i++;
302
303                 XtAddActions(textActions, 1);
304                 prompt_answers[j] = XmCreateTextField(prompts_row_col, 
305                                                     answer_name, argt, i);
306                 /* Make Return advance to next field. */
307                 XtOverrideTranslations(prompt_answers[j], text_trans);
308
309                 if (!siaFormInfo->visible[j])
310                     {
311                     /*
312                      * allocate the answer buffer
313                      */
314                     siaFormInfo->answers[j] = XtMalloc(SIAMXPASSWORD+1);
315                     (siaFormInfo->answers[j])[0] = '\0';
316
317                     XtAddCallback(prompt_answers[j], XmNmodifyVerifyCallback, 
318                                         NoEchoCB, siaFormInfo);
319                     XtAddCallback(prompt_answers[j], XmNmotionVerifyCallback, 
320                                         NoEchoCB, siaFormInfo);
321
322                     /* handle Delete/Backspace in the no-echo case */
323                     XtOverrideTranslations(prompt_answers[j], noecho_trans);
324                     }
325
326                 }
327                 break;
328             } /* end  switch (siaFormInfo->rendition) */
329
330         XtManageChild(prompt_answers[j]);
331         }
332
333
334     XtManageChild(sia_form);
335     /*
336      * Center the OK and Cancel buttons
337      */
338     {
339         Dimension width;
340         i = 0;
341         XtSetArg(argt[i], XmNwidth,  &width);  i++;
342         XtGetValues(ok_button, argt, i);
343         i = 0;
344         XtSetArg(argt[i], XmNleftAttachment,  XmATTACH_POSITION);  i++;
345         XtSetArg(argt[i], XmNleftPosition,  33);  i++;
346         XtSetArg(argt[i], XmNleftOffset,  -(width/2));  i++;
347         XtSetValues(ok_button, argt, i);
348
349         i = 0;
350         XtSetArg(argt[i], XmNwidth,  &width);  i++;
351         XtGetValues(cancel_button, argt, i);
352         i = 0;
353         XtSetArg(argt[i], XmNleftAttachment,  XmATTACH_POSITION);  i++;
354         XtSetArg(argt[i], XmNleftPosition,  66);  i++;
355         XtSetArg(argt[i], XmNleftOffset,  -(width/2));  i++;
356         XtSetValues(cancel_button, argt, i);
357     }
358
359     if (siaFormInfo->rendition == SIAONELINER
360             || siaFormInfo->rendition == SIAFORM)
361         {
362         /*
363          * Make the Return key Activate on the last text field.
364          */
365         XtOverrideTranslations(prompt_answers[siaFormInfo->num_prompts - 1],
366                               activate_trans);
367         XtAddCallback(prompt_answers[siaFormInfo->num_prompts - 1], 
368                 XmNactivateCallback, RespondSiaFormCB, siaFormInfo);    
369         XSetInputFocus(XtDisplay(prompt_answers[0]), 
370                 XtWindow(prompt_answers[0]), RevertToPointerRoot, CurrentTime);
371
372         i = 0;
373         XtSetArg(argt[i], XmNinitialFocus,  prompt_answers[0]);  i++;
374         XtSetValues(sia_form, argt, i);
375         XmProcessTraversal(prompt_answers[0],XmTRAVERSE_CURRENT);
376         }
377 }
378
379 /*
380  *****************
381  * NoEchoCB
382  *
383  * Save the text entered but do not display it
384  *****************
385  */
386
387 static void NoEchoCB( Widget w, XtPointer client_data, XtPointer call_data )
388 {
389     int i;
390     SiaFormInfo *siaFormInfo;
391     XmTextVerifyPtr call;
392
393     siaFormInfo = (SiaFormInfo *)client_data;
394     call = (XmTextVerifyPtr) call_data;
395     if(call->reason == XmCR_MOVING_INSERT_CURSOR)
396         {
397         call->doit=False;
398         return;
399         }
400     for (i=0; i<siaFormInfo->num_prompts; i++)
401         {
402         if (w == siaFormInfo->answer_widgets[i])
403             {
404             if (call->text->ptr)
405                 strcat(siaFormInfo->answers[i], call->text->ptr);
406
407             call->text->ptr[0] = '\0';
408             return;
409             }
410         }
411 }
412
413 /*
414  ************************
415  * RespondSiaFormCB
416  *
417  *      PB callback collects answers, sends them down the pipe
418  *      and destroys the sia_form.
419  ************************
420  */
421
422 static void RespondSiaFormCB( Widget w, XtPointer client_data, 
423                                 XtPointer call_data )
424 {
425     char buf[REQUEST_LIM_MAXLEN];
426     ResponseForm *r;
427     int i;
428     SiaFormInfo *siaFormInfo;
429     char *answer_ptr;
430
431     r = (ResponseForm *)buf;
432     siaFormInfo = (SiaFormInfo *)client_data;
433
434     r->hdr.opcode = REQUEST_OP_FORM;
435     r->hdr.reserved = 0;
436     r->hdr.length = sizeof(ResponseForm);
437
438     r->collect_status = siaFormInfo->collect_status;
439     r->num_answers = siaFormInfo->num_prompts;
440     r->offAnswers = sizeof(ResponseForm);
441
442     answer_ptr = buf + sizeof(ResponseForm);
443
444     for (i=0; i<siaFormInfo->num_prompts; i++)
445         {
446         if (siaFormInfo->rendition == SIAMENUONE
447                 || siaFormInfo->rendition == SIAMENUANY)
448             {
449             if (XmToggleButtonGadgetGetState(siaFormInfo->answer_widgets[i]))
450                 siaFormInfo->answers[i] = "X";
451             else
452                 siaFormInfo->answers[i] = NULL;
453             }
454         else if (siaFormInfo->visible[i])
455             siaFormInfo->answers[i] =
456                         XmTextFieldGetString(siaFormInfo->answer_widgets[i]);
457         if (!siaFormInfo->answers[i] || (siaFormInfo->answers[i])[0] == '\0')
458             {
459             *answer_ptr = '\0';
460             *answer_ptr++;
461             r->hdr.length++;
462             }
463         else
464             {
465             int tmp;
466
467             r->hdr.length += strlen(siaFormInfo->answers[i]) + 1;
468             strcpy(answer_ptr, siaFormInfo->answers[i]);
469             tmp = strlen(answer_ptr) + 1;
470             answer_ptr+= tmp;
471             r->hdr.length += tmp;
472             }
473         }
474 #ifdef DEBUG
475     for (i=0; i<siaFormInfo->num_prompts; i++)
476         printf("answer %d : %s\n", i, siaFormInfo->answers[i]);
477 #else
478     write(1, buf, r->hdr.length);
479 #endif
480
481     for (i=0; i<siaFormInfo->num_prompts; i++)
482         {
483         XtFree(siaFormInfo->answers[i]);
484         XtFree(siaFormInfo->prompts[i]);
485         XtFree(siaFormInfo->title);
486         }
487     XtDestroyWidget(siaFormInfo->sia_form_widget);
488
489 }
490
491 /***************************************************************************
492  *
493  *  SiaBackspace
494  *
495  *  Local backspace action for the no-echo case text widget. 
496  *  Deletes the last character of the string in the 
497  *  widget for each backspace key press.
498  ***************************************************************************/
499
500 static void
501 SiaBackspace( Widget w, XEvent *event, char **params, Cardinal *num_params )
502 {
503     int i, len;
504
505     for (i=0; i<globalSiaFormInfo->num_prompts; i++)
506         {
507         if (globalSiaFormInfo->answer_widgets[i] == w)
508             {
509             len = strlen(globalSiaFormInfo->answers[i]);
510             if (len > 0)
511                 globalSiaFormInfo->answers[i][len-1] = '\0';
512             return;
513             }
514         }
515 }
516
517 /*
518  ************************
519  * CancelSiaFormCB
520  *
521  *      Set collect_status to failure, call RespondSiaFormCB.
522  *
523  ************************
524  */
525
526 static void CancelSiaFormCB( Widget w, XtPointer client_data, 
527                                 XtPointer call_data )
528 {
529     SiaFormInfo *siaFormInfo;
530
531     siaFormInfo = (SiaFormInfo *)client_data;
532     siaFormInfo->collect_status = 0;
533
534     RespondSiaFormCB(w, client_data, call_data);
535 }