Jspice3
xeditor.c
Go to the documentation of this file.
1 /*************************************************************************
2 
3  XEDITOR.C -- Simple text editor for JSPICE3
4  Copyright (C) Stephen R. Whiteley 1995, All rights reserved
5  Version 1.0 1/17/95
6 
7  *************************************************************************/
8 
9 #ifdef SPICE_MAKE
10 #include "spice.h"
11 #include "ftedefs.h"
12 #include "spfteext.h"
13 #else
14 #define HAVE_X11
15 #endif
16 
17 #ifdef HAVE_X11
18 
19 #include <stdio.h>
20 #include <signal.h>
21 #include <ctype.h>
22 #include <unistd.h>
23 #include <sys/types.h>
24 #include <sys/stat.h>
25 #include <pwd.h>
26 
27 #include <X11/Intrinsic.h>
28 #include <X11/StringDefs.h>
29 #include <X11/Xaw/Paned.h>
30 #include <X11/Xaw/AsciiText.h>
31 #include <X11/Xaw/Label.h>
32 #include <X11/Xaw/Viewport.h>
33 #include <X11/Xaw/Command.h>
34 #include <X11/Xaw/Box.h>
35 #include <X11/Shell.h>
36 
38 
39 #ifdef STAND_ALONE
40 typedef enum {NOGO, NO_EXIST, READ_OK, WRITE_OK} check_type;
41 typedef struct {
42  Widget shell;
43  Widget form;
44  Widget text;
45  Widget title;
46  Widget butbox;
47  Widget popup;
48  Widget popup_text;
49  Widget message;
50  Atom wm_delete;
51  String *popup_sens_list;
52  Bool TextChanged;
53  event_type Last;
54  String saved_as;
55 } widget_bag;
56 
57 #else
58 #define XEDITOR
59 #include "x11util.h"
60 #endif
61 
62 #ifdef __STDC__
63 extern int xeditor(char*);
64 #else
65 extern int xeditor();
66 #endif
67 
68 #ifdef __STDC__
69 static char *nextarg(void);
70 static int errorhandler(Display*, XErrorEvent*);
71 static void CRaction(Widget, XEvent*, String*, Cardinal*);
72 static void QUaction(Widget, XEvent*, String*, Cardinal*);
73 static void Quit(Widget, XtPointer, XtPointer);
74 static void Save(Widget, XtPointer, XtPointer);
75 static void SaveAs(Widget, XtPointer, XtPointer);
76 static void Source(Widget, XtPointer, XtPointer);
77 static void Load(Widget, XtPointer, XtPointer);
78 static void Change(Widget, XtPointer, XtPointer);
79 static void DoSaveAs(Widget, XtPointer, XtPointer);
80 static Bool same(char*, char*);
81 static void DoLoad(Widget, XtPointer, XtPointer);
82 #ifdef STAND_ALONE
83 static void PopUpInput(String, String, void(*)(), widget_bag*);
84 static void PopDownInput(Widget, XtPointer, XtPointer);
85 static void PopUpMessage(String, widget_bag*);
86 static void PopDownMessage(Widget, XtPointer, XtPointer);
87 static void CenterWidgetOnWidget(Widget, Widget);
88 static check_type CheckFile(char*, int, widget_bag*);
89 static void ToTop(Widget, XtPointer, XEvent*, Boolean*);
90 static char *tilde_expand(char*);
91 #endif
92 static void PopUpHelp(Widget, XtPointer, XtPointer);
93 static void PopDownHelp(Widget, XtPointer, XtPointer);
94 
95 #else
96 
97 static char *nextarg();
98 static int errorhandler();
99 static void CRaction();
100 static void QUaction();
101 static void Quit();
102 static void Save();
103 static void SaveAs();
104 static void Source();
105 static void Load();
106 static void Change();
107 static void DoSaveAs();
108 static Bool same();
109 static void DoLoad();
110 #ifdef STAND_ALONE
111 static void PopUpInput();
112 static void PopDownInput();
113 static void PopUpMessage();
114 static void PopDownMessage();
115 static void CenterWidgetOnWidget();
116 static check_type CheckFile();
117 static void ToTop();
118 static char *tilde_expand();
119 #endif
120 static void PopUpHelp();
121 static void PopDownHelp();
122 #endif
123 
124 #ifdef STAND_ALONE
125 Display *Xdisplay;
126 #else
127 extern Display *Xdisplay;
128 #endif
129 
130 static char *oneLineTranslations =
131  "<Key>Return: cr_action()\n<Key>Delete: delete-next-character()";
132 static char *textTranslations = "<Key>Delete: delete-next-character()";
133 static char *butTranslations = "<Btn1Up>: notify() reset()";
134 static char *wmTranslations = "<Message>WM_PROTOCOLS: quit_action()";
135 static char *sens_list[] = {"save_as", "load", 0};
136 
137 #ifdef STAND_ALONE
138 
139 static String fallback_resources[] = {
140 
141  "xeditor.xeditor.background: lightgrey",
142  "xeditor.xeditor.buttonbox.background: lightblue",
143  "xeditor.xeditor.buttonbox.Command.background: yellow",
144 
145  "xeditor.popup.form.background: lightblue",
146  "xeditor.popup.form.Command.background: yellow",
147  "xeditor.popup.form.Label.background: pink",
148 
149  "xeditor.popup_m.form_m.background: pink",
150  "xeditor.popup_m.form_m.Command.background: yellow",
151 
152  "xeditor.popup_h.form_h.background: lightgrey",
153  "xeditor.popup_h.form_h.buttonbox.background: lightblue",
154  "xeditor.popup_h.form_h.buttonbox.Command.background: yellow",
155  "xeditor.popup_h.form_h.buttonbox.Label.background: pink",
156  NULL
157 };
158 
159 static XtActionsRec actions[] = {
160  {"cr_action", CRaction},
161  {"quit_action", QUaction}
162 };
163 
164 int NumArgs;
165 char **Args;
166 
167 
168 int
169 main(argc, argv)
170 
171 int argc;
172 char **argv;
173 {
174  XtAppContext app_con;
175 
176  /* initialize X toolkit */
177  XtToolkitInitialize();
178  app_con = XtCreateApplicationContext();
179  XtAppSetFallbackResources(app_con, fallback_resources);
180  Xdisplay = XtOpenDisplay(app_con, NULL, NULL, "Xeditor", NULL, 0,
181  &argc, argv);
182  if (!Xdisplay) {
183  fprintf(stderr, "Error: can't open display\n");
184  exit(1);
185  }
186  XtAppAddActions(app_con, actions, XtNumber(actions));
187  XSetErrorHandler(errorhandler);
188 
189  NumArgs = argc;
190  Args = argv;
191  if (NumArgs > 1) {
192  Args++;
193  NumArgs--;
194  xeditor(*Args);
195  }
196  else
197  xeditor(NULL);
198  XtAppMainLoop(app_con);
199  return (0);
200 }
201 
202 
203 static char *
204 nextarg()
205 {
206  if (NumArgs > 1) {
207  Args++;
208  NumArgs--;
209  return (*Args);
210  }
211  return ("");
212 }
213 
214 
215 static int
216 errorhandler(display, errorev)
217 
218 Display *display;
219 XErrorEvent *errorev;
220 {
221  char ErrorMessage[1024];
222 
223  XGetErrorText(display, errorev->error_code, ErrorMessage, 1024);
224  printf(ErrorMessage);
225  return (0);
226 }
227 #endif
228 
229 
230 static void
231 CRaction(caller, call_data, params, numparams)
232 
233 Widget caller;
234 XEvent *call_data;
235 String *params;
236 Cardinal *numparams;
237 {
238  /* simulate a button press when CR entered in text of popup */
239  Widget action = XtNameToWidget(XtParent(caller), "action");
240 
241  if (action)
242  XtCallCallbacks(action, XtNcallback, NULL);
243 }
244 
245 
246 static void
247 QUaction(caller, call_data, params, numparams)
248 
249 Widget caller;
250 XEvent *call_data;
251 String *params;
252 Cardinal *numparams;
253 {
254  /* simulate a Quit button press when DeleteWindow requested */
255  Widget quit;
256 
257  quit = XtNameToWidget(caller, "xeditor.buttonbox.quit");
258  if (!quit)
259  quit = XtNameToWidget(caller, "form.cancel");
260  if (!quit)
261  quit = XtNameToWidget(caller, "form_h.buttonbox.cancel_h");
262  if (!quit)
263  quit = XtNameToWidget(caller, "form_m.cancel_m");
264 
265  if (quit)
266  XtCallCallbacks(quit, XtNcallback, NULL);
267 }
268 
269 
270 int
271 xeditor(fname)
272 char *fname;
273 
274 /* Create a new window... */
275 {
276  Widget button;
277  widget_bag *w;
278  check_type which;
279  char buf[256];
280  static char tmpl[] = "/tmp/xeXXXXXX";
281 
282  /* Assume Xt toolkit is initialized! */
283  w = (widget_bag*) XtMalloc(sizeof(widget_bag));
284 
285  w->shell = XtAppCreateShell(NULL, "Jspice3",
286  applicationShellWidgetClass, Xdisplay, NULL, 0);
287  XtOverrideTranslations(w->shell, XtParseTranslationTable(wmTranslations));
288  w->form = XtVaCreateManagedWidget("xeditor", formWidgetClass,
289  w->shell, NULL);
290 
291  w->butbox = XtVaCreateManagedWidget("buttonbox", boxWidgetClass,
292  w->form,
293  XtNwidth, 650,
294  XtNleft, XtChainLeft,
295  XtNright, XtChainLeft,
296  XtNbottom, XtChainTop,
297  XtNtop, XtChainTop,
298  NULL);
299 
300  w->title = XtVaCreateManagedWidget("titlelabel", labelWidgetClass,
301  w->form,
302  XtNborderWidth, 0,
303  XtNfromHoriz, w->butbox,
304  XtNvertDistance, 10,
305  XtNhorizDistance, 20,
306  XtNleft, XtChainLeft,
307  XtNright, XtChainLeft,
308  XtNbottom, XtChainTop,
309  XtNtop, XtChainTop,
310  XtNresizable, True,
311  NULL);
312 
313  button = XtVaCreateManagedWidget("quit", commandWidgetClass,
314  w->butbox,
315  XtNlabel, "Quit",
316  NULL);
317  XtAddCallback(button, XtNcallback, Quit, (XtPointer)w);
318  XtOverrideTranslations(button, XtParseTranslationTable(butTranslations));
319 
320  button = XtVaCreateManagedWidget("save", commandWidgetClass,
321  w->butbox,
322  XtNlabel, "Save",
323  NULL);
324  XtAddCallback(button, XtNcallback, Save, (XtPointer)w);
325  XtSetSensitive(button, False);
326 
327  button = XtVaCreateManagedWidget("save_as", commandWidgetClass,
328  w->butbox,
329  XtNlabel, "Save as",
330  NULL);
331  XtAddCallback(button, XtNcallback, SaveAs, (XtPointer)w);
332  XtOverrideTranslations(button, XtParseTranslationTable(butTranslations));
333 
334 #ifndef STAND_ALONE
335  button = XtVaCreateManagedWidget("source", commandWidgetClass,
336  w->butbox,
337  XtNlabel, "Source",
338  NULL);
339  XtAddCallback(button, XtNcallback, Source, (XtPointer)w);
340  XtOverrideTranslations(button, XtParseTranslationTable(butTranslations));
341 #endif
342 
343  button = XtVaCreateManagedWidget("load", commandWidgetClass,
344  w->butbox,
345  XtNlabel, "Load",
346  NULL);
347  XtAddCallback(button, XtNcallback, Load, (XtPointer)w);
348  XtOverrideTranslations(button, XtParseTranslationTable(butTranslations));
349 
350  button = XtVaCreateManagedWidget("help", commandWidgetClass,
351  w->butbox,
352  XtNlabel, "Help",
353  NULL);
354 #ifdef STAND_ALONE
355  XtAddCallback(button, XtNcallback, PopUpHelp, (XtPointer)w);
356  XtOverrideTranslations(button, XtParseTranslationTable(butTranslations));
357 #else
358  XtAddCallback(button, XtNcallback, PopUpHelp, (XtPointer)"xeditor");
359 #endif
360 
361  w->text = XtVaCreateManagedWidget("main_text", asciiTextWidgetClass,
362  w->form,
363  XtNtype, XawAsciiFile,
364  XtNeditType, XawtextRead,
365  XtNallowResize, True,
366  XtNscrollHorizontal, XawtextScrollWhenNeeded,
367  XtNscrollVertical, XawtextScrollWhenNeeded,
368  XtNfromVert, w->butbox,
369  XtNwidth, 660,
370  XtNheight, 350,
371  XtNstring, "/dev/null",
372  XtNtop, XtChainTop,
373  NULL);
374  XtAddCallback(XawTextGetSource(w->text), XtNcallback, Change,
375  (XtPointer)w);
376  XtOverrideTranslations(w->text, XtParseTranslationTable(textTranslations));
377 
378  XtRealizeWidget(w->shell);
379  w->wm_delete = XInternAtom(Xdisplay, "WM_DELETE_WINDOW", False);
380  XSetWMProtocols(Xdisplay, XtWindow(w->shell), &w->wm_delete, 1);
381 
382  if (fname && *fname) {
383  strcpy(buf, fname);
384  cp_pathfix(buf);
385  fname = buf;
386  }
387  which = CheckFile(fname, R_OK, w);
388  if (which == NOGO) {
389  fname = (char*)mktemp(tmpl);
390  }
391  else if (which == READ_OK) {
392  XtVaSetValues(w->text, XtNstring, fname, NULL);
393  /* switch to edit mode, file may be read only in which
394  * case the load will fail if in edit mode
395  */
396  XtVaSetValues(w->text, XtNeditType, XawtextEdit, NULL);
397  }
398  XtVaSetValues(w->title, XtNlabel, fname, NULL);
399  w->TextChanged = False;
400  w->popup = NULL;
401  w->saved_as = NULL;
402  w->Last = LOAD;
403  w->popup_sens_list = sens_list;
404 
405  return (0);
406 }
407 
408 
409 /* ARGSUSED */
410 static void
411 Quit(caller, client_data, call_data)
412 
413 Widget caller;
414 XtPointer client_data, call_data;
415 {
416  widget_bag *w = (widget_bag*)client_data;
417 
418  if (w->TextChanged && (w->Last != QUIT)) {
419  w->Last = QUIT;
420  PopUpMessage(
421  "Text has been modified. Hit Quit again to quit", w);
422  return;
423  }
424  XtDestroyWidget(w->shell);
425  XtFree((char*)w);
426 #ifdef STAND_ALONE
427  kill(0,SIGINT);
428 #endif
429 }
430 
431 
432 /* ARGSUSED */
433 static void
434 Save(caller, client_data, call_data)
435 
436 Widget caller;
437 XtPointer client_data, call_data;
438 {
439  widget_bag *w = (widget_bag*)client_data;
440  Arg args[1];
441  String fname;
442 
443  w->Last = SAVE;
444  XtVaGetValues(w->title, XtNlabel, &fname, NULL);
445  if (CheckFile(fname, W_OK, w) == NOGO)
446  return;
447 
448  if (!XawAsciiSaveAsFile(XawTextGetSource(w->text), fname)) {
449  PopUpMessage("Unknown error, text not saved", w);
450  return;
451  }
452  PopUpMessage("Text saved", w);
453  /* This can be called with TextChanged false if we saved
454  * under a new name, and made no subsequent changes.
455  */
456  if (w->TextChanged) {
457  w->TextChanged = False;
458  XtAddCallback(XawTextGetSource(w->text), XtNcallback, Change,
459  (XtPointer)w);
460  }
461  XtSetSensitive(caller, False);
462  if (w->saved_as) {
463  XtFree(w->saved_as);
464  w->saved_as = NULL;
465  }
466 }
467 
468 
469 /* ARGSUSED */
470 static void
471 SaveAs(caller, client_data, call_data)
472 
473 Widget caller;
474 XtPointer client_data, call_data;
475 {
476  widget_bag *w = (widget_bag*)client_data;
477  String fname;
478  XawTextPosition begin, end;
479 
480  w->Last = SAVEAS;
481  XawTextGetSelectionPos(w->text, &begin, &end);
482  if (begin == end) {
483  XtVaGetValues(w->title, XtNlabel, &fname, NULL);
484  PopUpInput(fname, "Save File", DoSaveAs, (widget_bag*)client_data);
485  }
486  else
487  PopUpInput("", "Save Block", DoSaveAs, (widget_bag*)client_data);
488 }
489 
490 
491 #ifndef STAND_ALONE
492 /* ARGSUSED */
493 static void
494 Source(caller, client_data, call_data)
495 
496 Widget caller;
497 XtPointer client_data, call_data;
498 {
499  widget_bag *w = (widget_bag*)client_data;
500  char *fname;
501  FILE *fp;
502 
503  w->Last = SOURCE;
504  if (w->TextChanged) {
505  fname = smktemp("sp");
506  if ((fp = inp_pathopen(fname, "w")) == NULL) {
507  PopUpMessage("Unknown error, can't create temp file", w);
508  return;
509  }
510  fclose(fp);
511  if (!XawAsciiSaveAsFile(XawTextGetSource(w->text), fname)) {
512  PopUpMessage("Unknown error, can't write temp file", w);
513  return;
514  }
515  inp_srcedit(fname, False, False);
516  PopUpMessage("Text sourced (temporary file)", w);
517  }
518  else {
519  if (w->saved_as)
520  fname = w->saved_as;
521  else {
522  XtVaGetValues(w->title, XtNlabel, &fname, NULL);
523  }
524  fname = copy(fname);
525  inp_srcedit(fname, True, False);
526  PopUpMessage("Text sourced (permanent file)", w);
527  }
528 }
529 #endif
530 
531 
532 /* ARGSUSED */
533 static void
534 Load(caller, client_data, call_data)
535 
536 Widget caller;
537 XtPointer client_data, call_data;
538 {
539  widget_bag *w = (widget_bag*)client_data;
540  char *newfname = NULL;
541 
542  if (w->TextChanged && (w->Last != LOAD)) {
543  w->Last = LOAD;
544  PopUpMessage(
545  "Text has been modified. Hit Load again to load", w);
546  return;
547  }
548 #ifdef STAND_ALONE
549  newfname = nextarg();
550 #endif
551  PopUpInput(newfname ? newfname : "", "Load file", DoLoad,
552  (widget_bag*)client_data);
553 }
554 
555 
556 /* ARGSUSED */
557 static void
558 Change(caller, client_data, call_data)
559 
560 Widget caller;
561 XtPointer client_data, call_data;
562 {
563  widget_bag *w = (widget_bag*)client_data;
564 
565  w->Last = TEXTMOD;
566  w->TextChanged = True;
567  XtSetSensitive(XtNameToWidget(w->butbox, "save"), True);
568  XtRemoveCallback(caller, XtNcallback, Change, (XtPointer)w);
569 }
570 
571 
572 /* ARGSUSED */
573 static void
574 DoSaveAs(caller, client_data, call_data)
575 
576 Widget caller;
577 XtPointer client_data, call_data;
578 {
579  String fname, oldfname;
580  widget_bag *w = (widget_bag*)client_data;
581  XawTextPosition begin, end;
582  FILE *fp;
583  String s, string;
584  int len;
585  String mesg;
586  char buf[256];
587 
588  XtVaGetValues(w->popup_text, XtNstring, &fname, NULL);
589  if (fname && *fname) {
590  strcpy(buf, fname);
591  cp_pathfix(buf);
592  fname = buf;
593  }
594  if (CheckFile(fname, W_OK, w) == NOGO)
595  return;
596 
597  XawTextGetSelectionPos(w->text, &begin, &end);
598  if (begin == end) {
599  /* no selected text */
600  if (!XawAsciiSaveAsFile(XawTextGetSource(w->text), fname)) {
601  PopUpMessage("Unknown error, text not saved", w);
602  return;
603  }
604  XtVaGetValues(w->title, XtNlabel, &oldfname, NULL);
605  if (same(fname, oldfname)) {
606  if (!w->TextChanged) {
607  PopUpMessage("Text not modified", w);
608  return;
609  }
610  if (w->saved_as)
611  XtFree(w->saved_as), w->saved_as = NULL;
612  w->TextChanged = False;
613  XtSetSensitive(XtNameToWidget(w->butbox, "save"), False);
614  XtAddCallback(XawTextGetSource(w->text), XtNcallback, Change,
615  (XtPointer)w);
616  mesg = "Text saved";
617  }
618  else {
619  if (w->saved_as)
620  XtFree(w->saved_as);
621  w->saved_as = XtMalloc(strlen(fname) + 1);
622  strcpy(w->saved_as, fname);
623  if (w->TextChanged) {
624  w->TextChanged = False;
625  XtAddCallback(XawTextGetSource(w->text), XtNcallback, Change,
626  (XtPointer)w);
627  }
628  mesg = "Text saved under new name";
629  }
630  }
631  else {
632 
633  if ((fp = fopen(fname, "w")) == NULL) {
634  PopUpMessage("Unknown error, block not saved", w);
635  return;
636  }
637  string = XFetchBytes(Xdisplay, &len);
638  for (s = string; len; s++,len--)
639  putc(*s,fp);
640  fclose(fp);
641  XFree(string);
642  mesg = "Selected block saved";
643  }
644  PopDownInput(caller, client_data, call_data);
645  PopUpMessage(mesg, w);
646 }
647 
648 
649 static Bool
651 
652 char *s, *t;
653 {
654  while (isspace(*s)) s++;
655  while (isspace(*t)) t++;
656  for (; *s && *t; s++, t++)
657  if (*s != *t) return (False);
658  if (*s && !isspace(*s)) return (False);
659  if (*t && !isspace(*t)) return (False);
660  return (True);
661 }
662 
663 
664 /* ARGSUSED */
665 static void
666 DoLoad(caller, client_data, call_data)
667 
668 Widget caller;
669 XtPointer client_data, call_data;
670 {
671  String fname;
672  widget_bag *w = (widget_bag*)client_data;
673  check_type which;
674  char buf[256];
675 
676  XtVaGetValues(w->popup_text, XtNstring, &fname, NULL);
677  if (fname && *fname) {
678  strcpy(buf, fname);
679  cp_pathfix(buf);
680  fname = buf;
681  }
682  which = CheckFile(fname, R_OK, w);
683  if (which == NOGO)
684  return;
685  XtVaSetValues(w->text, XtNeditType, XawtextRead, NULL);
686  if (which == NO_EXIST)
687  XtVaSetValues(w->text, XtNstring, "/dev/null", NULL);
688  else
689  XtVaSetValues(w->text, XtNstring, fname, NULL);
690  XtVaSetValues(w->text, XtNeditType, XawtextEdit, NULL);
691 
692  /* ick! seems to be the only way to guarantee getting the
693  * right label size after a window resize
694  */
695  XtDestroyWidget(w->title);
696  w->title = XtVaCreateManagedWidget("titlelabel", labelWidgetClass,
697  w->form,
698  XtNborderWidth, 0,
699  XtNfromHoriz, w->butbox,
700  XtNvertDistance, 10,
701  XtNhorizDistance, 20,
702  XtNleft, XtChainLeft,
703  XtNright, XtChainLeft,
704  XtNbottom, XtChainTop,
705  XtNtop, XtChainTop,
706  XtNlabel, fname,
707  NULL);
708 
709  PopDownInput(caller, client_data, call_data);
710  if (w->TextChanged) {
711  w->TextChanged = False;
712  XtSetSensitive(XtNameToWidget(w->butbox, "save"), False);
713  XtAddCallback(XawTextGetSource(w->text), XtNcallback, Change,
714  (XtPointer)w);
715  }
716  if (w->saved_as) {
717  XtFree(w->saved_as);
718  w->saved_as = NULL;
719  }
720 }
721 
722 #ifdef STAND_ALONE
723 
724 static void
725 PopUpInput(initial_str, action_str, action_callback, w)
726 
727 String initial_str, action_str;
728 void (*action_callback)();
729 widget_bag *w;
730 {
731  Widget form;
732  Widget label;
733  Widget cancel;
734  Widget action;
735  Dimension width, b_width, d;
736  char **p;
737 
738  w->popup = XtVaCreatePopupShell("popup", transientShellWidgetClass,
739  w->shell, NULL);
740  XtOverrideTranslations(w->popup, XtParseTranslationTable(wmTranslations));
741  XtAddEventHandler(w->popup, VisibilityChangeMask,
742  False, ToTop, (XtPointer)w);
743 
744  form = XtVaCreateManagedWidget("form", formWidgetClass, w->popup,
745  NULL);
746 
747  label = XtVaCreateManagedWidget("label", labelWidgetClass,
748  form,
749  XtNlabel, "Enter filename: ",
750  XtNleft, XtChainLeft,
751  XtNright, XtChainLeft,
752  XtNresizable, TRUE,
753  XtNborderWidth, 0,
754  NULL);
755 
756  w->popup_text = XtVaCreateManagedWidget("text", asciiTextWidgetClass,
757  form,
758  XtNfromVert, label,
759  XtNleft, XtChainLeft,
760  XtNright, XtChainRight,
761  XtNeditType, XawtextEdit,
762  XtNresizable, TRUE,
763  XtNresize, XawtextResizeWidth,
764  XtNstring, initial_str,
765  NULL);
766  XtOverrideTranslations(w->popup_text,
767  XtParseTranslationTable(oneLineTranslations));
768 
769  action = XtVaCreateManagedWidget("action", commandWidgetClass,
770  form,
771  XtNlabel, action_str,
772  XtNfromVert, w->popup_text,
773  XtNleft, XtChainLeft,
774  XtNright, XtChainLeft,
775  NULL);
776  XtOverrideTranslations(action, XtParseTranslationTable(butTranslations));
777 
778  cancel = XtVaCreateManagedWidget("cancel", commandWidgetClass,
779  form,
780  XtNlabel, "Cancel",
781  XtNfromVert, w->popup_text,
782  XtNfromHoriz, action,
783  XtNleft, XtChainLeft,
784  XtNright, XtChainLeft,
785  NULL);
786 
787  XtAddCallback(cancel, XtNcallback, PopDownInput, (XtPointer)w);
788  XtAddCallback(action, XtNcallback, action_callback, (XtPointer)w);
789  XtRealizeWidget(w->popup);
790  XSetWMProtocols(Xdisplay, XtWindow(w->popup), &w->wm_delete, 1);
791  CenterWidgetOnWidget(w->popup,w->shell);
792 
793  XtVaGetValues(form,
794  XtNwidth, &width,
795  XtNborderWidth, &b_width,
796  XtNdefaultDistance, &d,
797  NULL);
798  width -= 2*(b_width + d + 1);
799  XtVaSetValues(w->popup_text, XtNwidth, width, NULL);
800 
801  XtPopup(w->popup, XtGrabNone);
802  XtSetKeyboardFocus(w->popup, w->popup_text);
803  XtSetKeyboardFocus(w->shell, w->popup);
804  for (p = w->popup_sens_list; *p; p++)
805  XtSetSensitive(XtNameToWidget(w->butbox, *p), False);
806 }
807 
808 
809 /* ARGSUSED */
810 static void
811 PopDownInput(caller, client_data, call_data)
812 
813 Widget caller;
814 XtPointer client_data, call_data;
815 {
816  widget_bag *w = (widget_bag*)client_data;
817  char **p;
818 
819  XtSetKeyboardFocus(w->shell, None);
820  XtPopdown(w->popup);
821  for (p = w->popup_sens_list; *p; p++)
822  XtSetSensitive(XtNameToWidget(w->butbox, *p), True);
823  w->popup = NULL;
824 }
825 
826 
827 static void
828 PopUpMessage(message_str, w)
829 
830 String message_str;
831 widget_bag *w;
832 {
833  Widget popup;
834  Widget form;
835  Widget label;
836  Widget cancel;
837  XColor visualcolor, exactcolor;
838 
839  popup = XtVaCreatePopupShell("popup_m", transientShellWidgetClass,
840  w->shell, NULL);
841  XtOverrideTranslations(popup, XtParseTranslationTable(wmTranslations));
842  XtAddEventHandler(popup, VisibilityChangeMask,
843  False, ToTop, (XtPointer)w);
844 
845  form = XtVaCreateManagedWidget("form_m", formWidgetClass, popup,
846  NULL);
847 
848  cancel = XtVaCreateManagedWidget("cancel_m", commandWidgetClass,
849  form,
850  XtNlabel, "OK",
851  XtNleft, XtChainLeft,
852  XtNright, XtChainLeft,
853  NULL);
854 
855  XAllocNamedColor(Xdisplay,
856  DefaultColormap(Xdisplay, DefaultScreen(Xdisplay)),
857  "red", &exactcolor, &visualcolor);
858  label = XtVaCreateManagedWidget("label_m", labelWidgetClass,
859  form,
860  XtNlabel, message_str,
861  XtNleft, XtChainLeft,
862  XtNright, XtChainLeft,
863  XtNfromHoriz, cancel,
864  XtNresizable, TRUE,
865  XtNborderWidth, 2,
866  XtNborderColor, visualcolor.pixel,
867  NULL);
868 
869  w->message = popup;
870  XtAddCallback(cancel, XtNcallback, PopDownMessage, (XtPointer)w);
871  XtAddEventHandler(form, KeyPressMask, False, (XtEventHandler)PopDownMessage,
872  (XtPointer)w);
873  XtRealizeWidget(popup);
874  XSetWMProtocols(Xdisplay, XtWindow(popup), &w->wm_delete, 1);
875  CenterWidgetOnWidget(popup, w->shell);
876  if (w->popup)
877  XtSetSensitive(w->popup, False);
878  XtSetSensitive(w->form, False);
879  XtSetKeyboardFocus(w->shell, form);
880  XtPopup(popup, XtGrabExclusive);
881 }
882 
883 
884 /* ARGSUSED */
885 static void
886 PopDownMessage(caller, client_data, call_data)
887 
888 Widget caller;
889 XtPointer client_data, call_data;
890 {
891  widget_bag *w = (widget_bag*)client_data;
892 
893  if (w->popup) {
894  XtSetKeyboardFocus(w->shell, w->popup);
895  XtPopdown(w->message);
896  XtSetSensitive(w->popup, True);
897  }
898  else {
899  XtSetKeyboardFocus(w->shell, None);
900  XtPopdown(w->message);
901  }
902  XtSetSensitive(w->form, True);
903 }
904 
905 
906 static void
907 CenterWidgetOnWidget(sub, master)
908 
909 Widget sub, master;
910 {
911  Dimension width, height, b_width;
912  Position x, y, max_x, max_y;
913 
914  XtVaGetValues(master,
915  XtNx, &x,
916  XtNy, &y,
917  XtNwidth, &width,
918  XtNheight, &height,
919  XtNborderWidth, &b_width,
920  NULL);
921 
922  width += 2*b_width;
923  height += 2*b_width;
924  height += 2*b_width;
925  x += (Position)width/2;
926  y += (Position)height/2;
927 
928  XtVaGetValues(sub,
929  XtNwidth, &width,
930  XtNheight, &height,
931  XtNborderWidth, &b_width,
932  NULL);
933 
934  width += 2*b_width;
935  height += 2*b_width;
936  x -= (Position)width/2;
937  if (x < 0) x = 0;
938  y -= (Position)height/2;
939  if (y < 0) y = 0;
940  if (y > (max_y = (Position) (XtScreen(sub)->height - height))) y = max_y;
941 
942  XtVaSetValues(sub, XtNx, x, XtNy, y, NULL);
943 }
944 
945 
946 static check_type
947 CheckFile(fname, mode, w)
948 
949 char *fname;
950 int mode;
951 widget_bag *w;
952 {
953  char buf[512];
954  struct stat st;
955  FILE *fp;
956  char *msg = "Error: can't %s file %s";
957 
958  /* check filename */
959  if (!fname) return (NOGO);
960  while (isspace(*fname)) fname++;
961  if (!*fname) return (NOGO);
962 
963  if (!access(fname, F_OK)) {
964  /* named file exists */
965  if (stat(fname, &st))
966  return (NOGO); /* shouldn't happen */
967 
968  if ((st.st_mode&S_IFMT) != S_IFLNK &&
969  (st.st_mode&S_IFMT) != S_IFREG) goto bad;
970  /* not a simple file or symbolic link */
971  }
972 
973  switch (mode) {
974  case R_OK:
975  if (access(fname,R_OK)) {
976  /* can't open for reading */
977  if (!access(fname,F_OK)) goto bad; /* it exists, so error */
978  return (NO_EXIST);
979  }
980  return (READ_OK);
981  case W_OK:
982  if (access(fname,W_OK)) {
983  /* can't open for writing */
984  if (!access(fname,F_OK)) goto bad; /* it exists, so error */
985  fp = fopen(fname,"w");
986  if (!fp) goto bad;
987  fclose(fp);
988  }
989  return (WRITE_OK);
990  }
991 bad:
992  sprintf(buf, msg, (mode == R_OK) ? "read" : "write", fname);
993  PopUpMessage(buf, w);
994  return (NOGO);
995 }
996 
997 
998 /* ARGSUSED */
999 static void
1000 ToTop(caller, clientdata, event, ctd)
1001 
1002 Widget caller;
1003 XtPointer clientdata;
1004 XEvent *event;
1005 Boolean *ctd;
1006 {
1007  /* prevent windows from disappearing */
1008  widget_bag *w = (widget_bag*)clientdata;
1009 
1010  XVisibilityEvent *vev = (XVisibilityEvent*)event;
1011  XWindowChanges xv;
1012 
1013  if (vev->state == VisibilityFullyObscured) {
1014  xv.sibling = XtWindow(w->shell);
1015  xv.stack_mode = Above;
1016  XReconfigureWMWindow(vev->display, vev->window,
1017  DefaultScreen(vev->display), CWSibling|CWStackMode, &xv);
1018  }
1019 }
1020 
1021 
1022 static char help_text[] = "\
1023 Command buttons:\n\
1024  Quit: Exit the editor\n\
1025  Save: Save the current buffer to the named file\n\
1026  Save As: Save the current buffer or marked block to a new file\n\
1027  Load: Input a new text file for editing\n\
1028  Help: Bring up help text\n\n\
1029 Key bindings:\n\
1030  Ctrl-a Beginning Of Line Meta-b Backward Word\n\
1031  Ctrl-b Backward Character Meta-f Forward Word\n\
1032  Ctrl-d Delete Next Character Meta-i Insert File\n\
1033  Ctrl-e End Of Line Meta-k Kill To End Of Paragraph\n\
1034  Ctrl-f Forward Character Meta-q Form Paragraph\n\
1035  Ctrl-g Multiply Reset Meta-v Previous Page\n\
1036  Ctrl-h Delete Previous Character Meta-y Insert Current Selection\n\
1037  Ctrl-j Newline And Indent Meta-z Scroll One Line Down\n\
1038  Ctrl-k Kill To End Of Line Meta-d Delete Next Word\n\
1039  Ctrl-l Redraw Display Meta-D Kill Word\n\
1040  Ctrl-m Newline Meta-h Delete Previous Word\n\
1041  Ctrl-n Next Line Meta-H Backward Kill Word\n\
1042  Ctrl-o Newline And Backup Meta-< Beginning Of File\n\
1043  Ctrl-p Previous Line Meta-> End Of File\n\
1044  Ctrl-r Search/Replace Backward Meta-] Forward Paragraph\n\
1045  Ctrl-s Search/Replace Forward Meta-[ Backward Paragraph\n\
1046  Ctrl-t Transpose Characters Delete Delete next character\n\
1047  Ctrl-u Multiply by 4 Meta-Delete Delete Previous Word\n\
1048  Ctrl-v Next Page Meta-Shift-Delete Kill Previous Word\n\
1049  Ctrl-w Kill Selection Meta-Backspace Delete Previous Word\n\
1050  Ctrl-y Unkill Meta-Shift-Backspace Kill Previous Word\n\
1051  Ctrl-z Scroll One Line Up\n\n\
1052 Pointer button bindings (cut and paste text):\n\
1053  Button 1 Down Start Selection\n\
1054  Button 1 Motion Adjust Selection\n\
1055  Button 1 Up End Selection (cut)\n\n\
1056  Button 2 Down Insert Current Selection (paste)\n\n\
1057  Button 3 Down Extend Current Selection\n\
1058  Button 3 Motion Adjust Selection\n\
1059  Button 3 Up End Selection (cut)\n";
1060 
1061 
1062 
1063 /* ARGSUSED */
1064 static void
1065 PopUpHelp(caller, client_data, call_data)
1066 
1067 Widget caller;
1068 XtPointer client_data, call_data;
1069 {
1070  Widget popup;
1071  Widget form;
1072  Widget butbox;
1073  Widget label;
1074  Widget cancel;
1075  Widget text;
1076  widget_bag *w = (widget_bag*)client_data;
1077  Position x, y;
1078  Widget *wpass;
1079 
1080  XtVaGetValues(w->shell, XtNx, &x, XtNy, &y, NULL);
1081 
1082 
1083  popup = XtVaCreatePopupShell("popup_h", transientShellWidgetClass,
1084  w->shell,
1085  XtNx, x + 50,
1086  XtNy, y + 50,
1087  NULL);
1088  XtOverrideTranslations(popup, XtParseTranslationTable(wmTranslations));
1089 
1090  form = XtVaCreateManagedWidget("form_h", formWidgetClass, popup,
1091  NULL);
1092 
1093  butbox = XtVaCreateManagedWidget("buttonbox", boxWidgetClass,
1094  form,
1095  XtNwidth, 650,
1096  XtNleft, XtChainLeft,
1097  XtNright, XtChainLeft,
1098  XtNbottom, XtChainTop,
1099  XtNtop, XtChainTop,
1100  NULL);
1101 
1102  label = XtVaCreateManagedWidget("label_h", labelWidgetClass,
1103  butbox,
1104  XtNlabel, "Xeditor Help",
1105  XtNborderWidth, 2,
1106  NULL);
1107 
1108  cancel = XtVaCreateManagedWidget("cancel_h", commandWidgetClass,
1109  butbox,
1110  XtNlabel, "Cancel",
1111  XtNfromHoriz, label,
1112  NULL);
1113 
1114  text = XtVaCreateManagedWidget("text_h", asciiTextWidgetClass,
1115  form,
1116  XtNtype, XawAsciiString,
1117  XtNeditType, XawtextRead,
1118  XtNallowResize, True,
1119  XtNscrollHorizontal, XawtextScrollWhenNeeded,
1120  XtNscrollVertical, XawtextScrollWhenNeeded,
1121  XtNfromVert, butbox,
1122  XtNwidth, 600,
1123  XtNheight, 400,
1124  XtNstring, help_text,
1125  XtNdisplayCaret, False,
1126  NULL);
1127 
1128  wpass = (Widget*)XtMalloc(2*sizeof(Widget));
1129  wpass[0] = popup;
1130  wpass[1] = w->butbox;
1131  XtAddCallback(cancel, XtNcallback, PopDownHelp, (XtPointer)wpass);
1132  XtRealizeWidget(popup);
1133  XSetWMProtocols(Xdisplay, XtWindow(popup), &w->wm_delete, 1);
1134  XtPopup(popup, XtGrabNone);
1135  XtSetSensitive(XtNameToWidget(w->butbox, "help"), False);
1136 }
1137 
1138 
1139 /* ARGSUSED */
1140 static void
1141 PopDownHelp(caller, client_data, call_data)
1142 
1143 Widget caller;
1144 XtPointer client_data, call_data;
1145 {
1146  Widget *w = (Widget*)client_data;
1147 
1148  XtPopdown(w[0]);
1149  XtSetSensitive(XtNameToWidget(w[1], "help"), True);
1150  XtFree((char*)w);
1151 }
1152 
1153 
1154 void
1155 cp_pathfix(buf)
1156 
1157 char *buf;
1158 {
1159  char *s;
1160 
1161  if (index(buf,'~')) {
1162  s = tilde_expand(buf);
1163  if (s) {
1164  strcpy(buf,s);
1165  XtFree(s);
1166  }
1167  }
1168 }
1169 
1170 
1171 static char *
1172 tilde_expand(string)
1173 
1174 char *string;
1175 {
1176  struct passwd *pw;
1177  char *tail;
1178  char buf[BSIZE_SP];
1179  char *k, c;
1180  char *ret;
1181 
1182  while (*string && isspace(*string))
1183  string++;
1184 
1185  if (*string != '~') {
1186  ret = XtMalloc(strlen(string) + 1);
1187  strcpy(ret, string);
1188  return (ret);
1189  }
1190 
1191  string += 1;
1192 
1193  if (!*string || *string == '/') {
1194  pw = getpwuid(getuid());
1195  *buf = 0;
1196  }
1197  else {
1198  k = buf;
1199  while ((c = *string) && c != '/')
1200  *k++ = c, string++;
1201  *k = 0;
1202  pw = getpwnam(buf);
1203  }
1204 
1205  if (pw) {
1206  strcpy(buf, pw->pw_dir);
1207  if (*string)
1208  strcat(buf, string);
1209  }
1210  else
1211  return (NULL);
1212 
1213  ret = XtMalloc(strlen(buf) + 1);
1214  strcpy(ret, buf);
1215  return (ret);
1216 }
1217 
1218 
1219 #else /* STAND_ALONE */
1220 
1221 /* ARGSUSED */
1222 static void
1223 PopUpHelp(caller, client_data, call_data)
1224 
1225 Widget caller;
1226 XtPointer client_data, call_data;
1227 {
1228  wordlist wl;
1229 
1230  wl.wl_prev = wl.wl_next = NULL;
1231  wl.wl_word = (char*)client_data;
1232  com_ghelp(&wl);
1233 }
1234 
1235 
1236 void
1238 
1239 wordlist *wl;
1240 {
1241  if (wl)
1242  xeditor(wl->wl_word);
1243  else
1244  xeditor(NULL);
1245 }
1246 
1247 
1248 #endif /* STAND_ALONE */
1249 
1250 #else /* HAVE_X11 */
1251 
1252 #ifdef STAND_ALONE
1253 main()
1254 { printf("This doesn't exist without X!\n"); }
1255 
1256 #else
1257 
1258 /* ARGSUSED */
1259 int
1260 xeditor(s)
1261 char *s;
1262 { return (1); }
1263 
1264 
1265 void
1266 com_xeditor(wl)
1267 
1268 wordlist *wl;
1269 {
1270  fprintf(cp_err, "Xeditor is available under X only\n");
1271 }
1272 
1273 #endif /* STAND_ALONE */
1274 
1275 #endif /* HAVE_X11 */
void cp_pathfix(char *buf)
Definition: help.c:198
static char buf[MAXPROMPT]
Definition: arg.c:18
char * tilde_expand(char *string)
Definition: spiced.c:309
#define BSIZE_SP
Definition: misc.h:19
Definition: outitf.c:1049
static char * sens_list[]
Definition: xeditor.c:135
static void DoSaveAs()
Widget butbox
Definition: x11util.h:15
static void Source()
static char * butTranslations
Definition: xeditor.c:133
char * strcpy()
Widget text
Definition: x11util.h:13
Definition: cddefs.h:119
Definition: xeditor.c:37
static void Quit()
FILE * p
Definition: proc2mod.c:48
static void CRaction()
Definition: cddefs.h:169
static void PopDownHelp()
Definition: library.c:18
#define TRUE
Definition: util.h:27
static void Save()
Definition: bascmd.c:715
char * copy()
FILE * cp_err
Definition: help.c:101
Definition: x11util.h:7
static Bool same()
Widget title
Definition: x11util.h:14
struct wordlist * wl_prev
Definition: cpstd.h:24
Definition: cddefs.h:237
Bool
Definition: mfb.h:18
#define NULL
Definition: spdefs.h:121
static void DoLoad()
FILE * inp_pathopen()
void inp_srcedit()
Widget message
Definition: x11util.h:18
check_type CheckFile()
static char * nextarg()
#define True
Definition: scedstub.c:16
String * popup_sens_list
Definition: x11util.h:20
Widget popup_text
Definition: x11util.h:17
char * smktemp()
int access(char *pth, int m)
Definition: libfuncs.c:75
static double c
Definition: vectors.c:16
static char * textTranslations
Definition: xeditor.c:132
check_type
Definition: x11util.h:7
void PopUpMessage()
Definition: xeditor.c:37
Widget shell
Definition: x11util.h:10
Definition: cpstd.h:21
Definition: xeditor.c:37
Definition: x11util.h:7
void PopDownMessage()
static char * oneLineTranslations
Definition: xeditor.c:130
static void PopUpHelp()
Widget popup
Definition: x11util.h:16
static int errorhandler()
int xeditor()
static void SaveAs()
Widget form
Definition: x11util.h:11
Definition: xeditor.c:37
event_type
Definition: xeditor.c:37
static char * wmTranslations
Definition: xeditor.c:134
void com_ghelp()
void CenterWidgetOnWidget()
Definition: xeditor.c:37
static void message(char *instr, char *outstr)
Definition: hcopy.c:13
char * index(char *s, char c) const
Definition: string.c:294
struct wordlist * wl_next
Definition: cpstd.h:23
char * wl_word
Definition: cpstd.h:22
#define False
Definition: scedstub.c:15
static void Change()
Atom wm_delete
Definition: x11util.h:19
int main(int argc, char **argv)
Definition: help.c:116
char ErrorMessage[]
Definition: error.c:20
void PopDownInput()
Definition: cddefs.h:192
Display * Xdisplay
#define XtNumber(arr)
Definition: display.c:114
static void QUaction()
void com_xeditor(wordlist *wl)
Definition: xeditor.c:1237
void PopUpInput()
static void Load()