vgsiaform.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535
  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. * @DEC_COPYRIGHT@
  32. */
  33. /*
  34. * HISTORY
  35. * $Log$
  36. * Revision 1.1.2.2 1995/06/06 19:39:54 Chris_Beute
  37. * New file added for SIA password expiration forms handling
  38. * [1995/05/31 19:52:41 Chris_Beute]
  39. *
  40. * Revision 1.1.2.2 1995/05/22 18:13:32 Peter_Derr
  41. * Add a Cancel button.
  42. * [1995/05/15 18:06:21 Peter_Derr]
  43. *
  44. * Support SIAMENUONE and SIAMENUANY
  45. * [1995/05/12 20:29:53 Peter_Derr]
  46. *
  47. * SIA form UI
  48. * [1995/05/11 22:09:09 Peter_Derr]
  49. *
  50. * $EndLog$
  51. */
  52. #include "vg.h"
  53. #include "vgmsg.h"
  54. #include <alloca.h>
  55. #include <Xm/Xm.h>
  56. #include <Xm/Form.h>
  57. #include <Xm/Label.h>
  58. #include <Xm/PushB.h>
  59. #include <Xm/RowColumn.h>
  60. #include <Xm/TextF.h>
  61. #include <Xm/ToggleBG.h>
  62. XmString multiline_xmstring(char *);
  63. static void NoEchoCB( Widget, XtPointer, XtPointer);
  64. static void RespondSiaFormCB( Widget, XtPointer, XtPointer);
  65. static void CancelSiaFormCB( Widget, XtPointer, XtPointer);
  66. static void SiaBackspace( Widget, XEvent *, char **, Cardinal *);
  67. static char textEventBindings[] = {
  68. "<Key>Return: next-tab-group()"
  69. };
  70. static char activateBindings[] = {
  71. "<Key>osfActivate: activate()\n\
  72. Ctrl <Key>Return: activate()\n\
  73. <Key>Return: activate()"
  74. };
  75. static char activatePBBindings[] = {
  76. "<Key>osfActivate: ArmAndActivate()\n\
  77. Ctrl <Key>Return: ArmAndActivate()\n\
  78. <Key>Return: ArmAndActivate()"
  79. };
  80. static char noEchoBindings[] = {
  81. "Ctrl<Key>: my-insert()\n\
  82. <Key>osfBackSpace: sia-bksp()\n\
  83. <Key>osfDelete: sia-bksp()"
  84. };
  85. static XtActionsRec textActions[] = {
  86. {"sia-bksp", (XtActionProc)SiaBackspace},
  87. };
  88. SiaFormInfo *globalSiaFormInfo;
  89. /***************************************************************************
  90. *
  91. * SiaForm
  92. *
  93. * Widgets: sia_form, sia_title, sia_prompts
  94. ***************************************************************************/
  95. void
  96. SiaForm(SiaFormInfo *siaFormInfo)
  97. {
  98. int i;
  99. int j;
  100. LoginTextPtr textdata;
  101. XtTranslations textTable;
  102. Widget sia_form, title_label, ok_button, cancel_button, prompts_row_col;
  103. Widget *prompt_labels;
  104. Widget *prompt_answers;
  105. XmString xmstr;
  106. XtTranslations noecho_trans, text_trans, activate_trans, activatePBtrans;
  107. globalSiaFormInfo = siaFormInfo;
  108. siaFormInfo->collect_status = 1;
  109. /*
  110. * XmCreateFormDialog()
  111. * XmCreateLabel()
  112. * XmCreateRowColumn()
  113. * for each prompt
  114. * XmCreateLabel()
  115. * XmCreateTextField()
  116. * if not visible
  117. * add ModifyVerify callback
  118. * XmCreatePushButton
  119. * PB callback will collect answers, send them down the pipe
  120. * and destroy the sia_form.
  121. */
  122. /*
  123. * create the SIA form
  124. */
  125. i = 0;
  126. i = InitArg(Form);
  127. XtSetArg(argt[i], XmNmarginHeight, MBOX_MARGIN_HEIGHT ); i++;
  128. XtSetArg(argt[i], XmNmarginWidth, MBOX_MARGIN_WIDTH ); i++;
  129. XtSetArg(argt[i], XmNshadowThickness, SHADOW_THICKNESS ); i++;
  130. XtSetArg(argt[i], XmNnoResize, False ); i++;
  131. XtSetArg(argt[i], XmNresizePolicy, XmRESIZE_ANY ); i++;
  132. sia_form = XmCreateFormDialog(login_shell, "sia_form", argt, i);
  133. siaFormInfo->sia_form_widget = sia_form;
  134. /*
  135. * create the title label
  136. */
  137. /* i = 0; */
  138. i = InitArg(Label);
  139. XtSetArg(argt[i], XmNlabelString, siaFormInfo->title ); i++;
  140. XtSetArg(argt[i], XmNtraversalOn, False ); i++;
  141. XtSetArg(argt[i], XmNtopAttachment, XmATTACH_FORM ); i++;
  142. XtSetArg(argt[i], XmNleftAttachment, XmATTACH_FORM ); i++;
  143. XtSetArg(argt[i], XmNrightAttachment, XmATTACH_FORM ); i++;
  144. XtSetArg(argt[i], XmNalignment, XmALIGNMENT_CENTER ); i++;
  145. xmstr = multiline_xmstring(siaFormInfo->title);
  146. XtSetArg(argt[i], XmNlabelString, xmstr ); i++;
  147. title_label = XmCreateLabel(sia_form, "title_label", argt, i);
  148. XtManageChild(title_label);
  149. XmStringFree(xmstr);
  150. /* ok button */
  151. activate_trans = XtParseTranslationTable(activateBindings);
  152. activatePBtrans = XtParseTranslationTable(activatePBBindings);
  153. i = InitArg(PushB);
  154. XtSetArg(argt[i], XmNbottomAttachment, XmATTACH_FORM ); i++;
  155. XtSetArg(argt[i], XmNtraversalOn, True ); i++;
  156. xmstr = ReadCatalogXms(MC_LABEL_SET, MC_OK_LABEL, MC_DEF_OK_LABEL );
  157. XtSetArg(argt[i], XmNlabelString, xmstr ); i++;
  158. ok_button = XmCreatePushButton(sia_form, "ok_button", argt, i);
  159. XtOverrideTranslations(ok_button, activatePBtrans);
  160. XmStringFree(xmstr);
  161. XtManageChild(ok_button);
  162. XtAddCallback(ok_button, XmNactivateCallback, RespondSiaFormCB,
  163. siaFormInfo);
  164. /* Cancel button */
  165. i = InitArg(PushB);
  166. XtSetArg(argt[i], XmNbottomAttachment, XmATTACH_FORM ); i++;
  167. XtSetArg(argt[i], XmNtraversalOn, True ); i++;
  168. xmstr = ReadCatalogXms(MC_LABEL_SET, MC_CANCEL_LABEL, MC_DEF_CANCEL_LABEL );
  169. XtSetArg(argt[i], XmNlabelString, xmstr ); i++;
  170. cancel_button = XmCreatePushButton(sia_form, "cancel_button", argt, i);
  171. XmStringFree(xmstr);
  172. XtManageChild(cancel_button);
  173. XtAddCallback(cancel_button, XmNactivateCallback, CancelSiaFormCB,
  174. siaFormInfo);
  175. /*
  176. * create the RowColumn widget for prompts
  177. */
  178. i =0;
  179. XtSetArg(argt[i], XmNorientation, XmHORIZONTAL ); i++;
  180. XtSetArg(argt[i], XmNentryVerticalAlignment, XmALIGNMENT_CENTER ); i++;
  181. XtSetArg(argt[i], XmNrowColumnType, XmWORK_AREA ); i++;
  182. XtSetArg(argt[i], XmNnumColumns, siaFormInfo->num_prompts); i++;
  183. XtSetArg(argt[i], XmNpacking, XmPACK_COLUMN ); i++;
  184. XtSetArg(argt[i], XmNtopAttachment, XmATTACH_WIDGET ); i++;
  185. XtSetArg(argt[i], XmNtopWidget, title_label ); i++;
  186. XtSetArg(argt[i], XmNbottomAttachment, XmATTACH_WIDGET ); i++;
  187. XtSetArg(argt[i], XmNbottomWidget, ok_button ); i++;
  188. XtSetArg(argt[i], XmNleftAttachment, XmATTACH_FORM ); i++;
  189. XtSetArg(argt[i], XmNrightAttachment, XmATTACH_FORM ); i++;
  190. switch (siaFormInfo->rendition)
  191. {
  192. case SIAMENUONE:
  193. XtSetArg(argt[i], XmNradioBehavior, True ); i++;
  194. /* no break */
  195. case SIAMENUANY:
  196. XtSetArg(argt[i], XmNisHomogeneous, True ); i++;
  197. XtSetArg(argt[i], XmNentryClass, xmToggleButtonGadgetClass); i++;
  198. XtSetArg(argt[i], XmNentryAlignment, XmALIGNMENT_BEGINNING ); i++;
  199. break;
  200. case SIAONELINER:
  201. /* no break */
  202. case SIAFORM:
  203. XtSetArg(argt[i], XmNentryAlignment, XmALIGNMENT_END ); i++;
  204. }
  205. prompts_row_col = XmCreateRowColumn(sia_form, "prompts_row_col", argt, i);
  206. XtManageChild(prompts_row_col);
  207. prompt_labels = (Widget *) alloca(sizeof(Widget *) * siaFormInfo->num_prompts);
  208. prompt_answers = siaFormInfo->answer_widgets;
  209. noecho_trans = XtParseTranslationTable(noEchoBindings);
  210. text_trans = XtParseTranslationTable(textEventBindings);
  211. for (j=0; j<siaFormInfo->num_prompts; j++)
  212. {
  213. /*
  214. * create the prompt label
  215. */
  216. char label_name[81];
  217. char answer_name[81];
  218. sprintf(label_name,"Prompt %d",j);
  219. sprintf(answer_name,"Answer %d",j);
  220. xmstr = multiline_xmstring(siaFormInfo->prompts[j]);
  221. switch (siaFormInfo->rendition)
  222. {
  223. case SIAMENUANY:
  224. case SIAMENUONE:
  225. {
  226. /* i = InitArg(ToggleBG); */
  227. i = 0;
  228. XtSetArg(argt[i], XmNtraversalOn, True ); i++;
  229. XtSetArg(argt[i], XmNlabelString, xmstr ); i++;
  230. prompt_answers[j] = XmCreateToggleButtonGadget(prompts_row_col,
  231. answer_name, argt, i);
  232. }
  233. break;
  234. case SIAONELINER:
  235. /* no break */
  236. case SIAFORM:
  237. {
  238. i = 0;
  239. XtSetArg(argt[i], XmNtraversalOn, True ); i++;
  240. XtSetArg(argt[i], XmNlabelString, xmstr ); i++;
  241. prompt_labels[j] = XmCreateLabel(prompts_row_col, label_name,
  242. argt, i);
  243. XtManageChild(prompt_labels[j]);
  244. /*
  245. * create the answer text field
  246. */
  247. i = InitArg(Text);
  248. XtSetArg(argt[i], XmNselectionArrayCount, 1 ); i++;
  249. XtSetArg(argt[i], XmNmaxLength, 80 ); i++;
  250. XtSetArg(argt[i], XmNmappedWhenManaged, True ); i++;
  251. XtAddActions(textActions, 1);
  252. prompt_answers[j] = XmCreateTextField(prompts_row_col,
  253. answer_name, argt, i);
  254. /* Make Return advance to next field. */
  255. XtOverrideTranslations(prompt_answers[j], text_trans);
  256. if (!siaFormInfo->visible[j])
  257. {
  258. /*
  259. * allocate the answer buffer
  260. */
  261. siaFormInfo->answers[j] = XtMalloc(SIAMXPASSWORD+1);
  262. (siaFormInfo->answers[j])[0] = '\0';
  263. XtAddCallback(prompt_answers[j], XmNmodifyVerifyCallback,
  264. NoEchoCB, siaFormInfo);
  265. XtAddCallback(prompt_answers[j], XmNmotionVerifyCallback,
  266. NoEchoCB, siaFormInfo);
  267. /* handle Delete/Backspace in the no-echo case */
  268. XtOverrideTranslations(prompt_answers[j], noecho_trans);
  269. }
  270. }
  271. break;
  272. } /* end switch (siaFormInfo->rendition) */
  273. XtManageChild(prompt_answers[j]);
  274. }
  275. XtManageChild(sia_form);
  276. /*
  277. * Center the OK and Cancel buttons
  278. */
  279. {
  280. Dimension width;
  281. i = 0;
  282. XtSetArg(argt[i], XmNwidth, &width); i++;
  283. XtGetValues(ok_button, argt, i);
  284. i = 0;
  285. XtSetArg(argt[i], XmNleftAttachment, XmATTACH_POSITION); i++;
  286. XtSetArg(argt[i], XmNleftPosition, 33); i++;
  287. XtSetArg(argt[i], XmNleftOffset, -(width/2)); i++;
  288. XtSetValues(ok_button, argt, i);
  289. i = 0;
  290. XtSetArg(argt[i], XmNwidth, &width); i++;
  291. XtGetValues(cancel_button, argt, i);
  292. i = 0;
  293. XtSetArg(argt[i], XmNleftAttachment, XmATTACH_POSITION); i++;
  294. XtSetArg(argt[i], XmNleftPosition, 66); i++;
  295. XtSetArg(argt[i], XmNleftOffset, -(width/2)); i++;
  296. XtSetValues(cancel_button, argt, i);
  297. }
  298. if (siaFormInfo->rendition == SIAONELINER
  299. || siaFormInfo->rendition == SIAFORM)
  300. {
  301. /*
  302. * Make the Return key Activate on the last text field.
  303. */
  304. XtOverrideTranslations(prompt_answers[siaFormInfo->num_prompts - 1],
  305. activate_trans);
  306. XtAddCallback(prompt_answers[siaFormInfo->num_prompts - 1],
  307. XmNactivateCallback, RespondSiaFormCB, siaFormInfo);
  308. XSetInputFocus(XtDisplay(prompt_answers[0]),
  309. XtWindow(prompt_answers[0]), RevertToPointerRoot, CurrentTime);
  310. i = 0;
  311. XtSetArg(argt[i], XmNinitialFocus, prompt_answers[0]); i++;
  312. XtSetValues(sia_form, argt, i);
  313. XmProcessTraversal(prompt_answers[0],XmTRAVERSE_CURRENT);
  314. }
  315. }
  316. /*
  317. *****************
  318. * NoEchoCB
  319. *
  320. * Save the text entered but do not display it
  321. *****************
  322. */
  323. static void NoEchoCB( Widget w, XtPointer client_data, XtPointer call_data )
  324. {
  325. int i;
  326. SiaFormInfo *siaFormInfo;
  327. XmTextVerifyPtr call;
  328. siaFormInfo = (SiaFormInfo *)client_data;
  329. call = (XmTextVerifyPtr) call_data;
  330. if(call->reason == XmCR_MOVING_INSERT_CURSOR)
  331. {
  332. call->doit=False;
  333. return;
  334. }
  335. for (i=0; i<siaFormInfo->num_prompts; i++)
  336. {
  337. if (w == siaFormInfo->answer_widgets[i])
  338. {
  339. if (call->text->ptr)
  340. strcat(siaFormInfo->answers[i], call->text->ptr);
  341. call->text->ptr[0] = '\0';
  342. return;
  343. }
  344. }
  345. }
  346. /*
  347. ************************
  348. * RespondSiaFormCB
  349. *
  350. * PB callback collects answers, sends them down the pipe
  351. * and destroys the sia_form.
  352. ************************
  353. */
  354. static void RespondSiaFormCB( Widget w, XtPointer client_data,
  355. XtPointer call_data )
  356. {
  357. char buf[REQUEST_LIM_MAXLEN];
  358. ResponseForm *r;
  359. int i;
  360. SiaFormInfo *siaFormInfo;
  361. char *answer_ptr;
  362. r = (ResponseForm *)buf;
  363. siaFormInfo = (SiaFormInfo *)client_data;
  364. r->hdr.opcode = REQUEST_OP_FORM;
  365. r->hdr.reserved = 0;
  366. r->hdr.length = sizeof(ResponseForm);
  367. r->collect_status = siaFormInfo->collect_status;
  368. r->num_answers = siaFormInfo->num_prompts;
  369. r->offAnswers = sizeof(ResponseForm);
  370. answer_ptr = buf + sizeof(ResponseForm);
  371. for (i=0; i<siaFormInfo->num_prompts; i++)
  372. {
  373. if (siaFormInfo->rendition == SIAMENUONE
  374. || siaFormInfo->rendition == SIAMENUANY)
  375. {
  376. if (XmToggleButtonGadgetGetState(siaFormInfo->answer_widgets[i]))
  377. siaFormInfo->answers[i] = "X";
  378. else
  379. siaFormInfo->answers[i] = NULL;
  380. }
  381. else if (siaFormInfo->visible[i])
  382. siaFormInfo->answers[i] =
  383. XmTextFieldGetString(siaFormInfo->answer_widgets[i]);
  384. if (!siaFormInfo->answers[i] || (siaFormInfo->answers[i])[0] == '\0')
  385. {
  386. *answer_ptr = '\0';
  387. *answer_ptr++;
  388. r->hdr.length++;
  389. }
  390. else
  391. {
  392. int tmp;
  393. r->hdr.length += strlen(siaFormInfo->answers[i]) + 1;
  394. strcpy(answer_ptr, siaFormInfo->answers[i]);
  395. tmp = strlen(answer_ptr) + 1;
  396. answer_ptr+= tmp;
  397. r->hdr.length += tmp;
  398. }
  399. }
  400. #ifdef DEBUG
  401. for (i=0; i<siaFormInfo->num_prompts; i++)
  402. printf("answer %d : %s\n", i, siaFormInfo->answers[i]);
  403. #else
  404. write(1, buf, r->hdr.length);
  405. #endif
  406. for (i=0; i<siaFormInfo->num_prompts; i++)
  407. {
  408. XtFree(siaFormInfo->answers[i]);
  409. XtFree(siaFormInfo->prompts[i]);
  410. XtFree(siaFormInfo->title);
  411. }
  412. XtDestroyWidget(siaFormInfo->sia_form_widget);
  413. }
  414. /***************************************************************************
  415. *
  416. * SiaBackspace
  417. *
  418. * Local backspace action for the no-echo case text widget.
  419. * Deletes the last character of the string in the
  420. * widget for each backspace key press.
  421. ***************************************************************************/
  422. static void
  423. SiaBackspace( Widget w, XEvent *event, char **params, Cardinal *num_params )
  424. {
  425. int i, len;
  426. for (i=0; i<globalSiaFormInfo->num_prompts; i++)
  427. {
  428. if (globalSiaFormInfo->answer_widgets[i] == w)
  429. {
  430. len = strlen(globalSiaFormInfo->answers[i]);
  431. if (len > 0)
  432. globalSiaFormInfo->answers[i][len-1] = '\0';
  433. return;
  434. }
  435. }
  436. }
  437. /*
  438. ************************
  439. * CancelSiaFormCB
  440. *
  441. * Set collect_status to failure, call RespondSiaFormCB.
  442. *
  443. ************************
  444. */
  445. static void CancelSiaFormCB( Widget w, XtPointer client_data,
  446. XtPointer call_data )
  447. {
  448. SiaFormInfo *siaFormInfo;
  449. siaFormInfo = (SiaFormInfo *)client_data;
  450. siaFormInfo->collect_status = 0;
  451. RespondSiaFormCB(w, client_data, call_data);
  452. }