Add GNU LGPL headers to all .c .C and .h files
[oweals/cde.git] / cde / lib / tt / demo / edit_demo / edit.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 librararies 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 /*%%  (c) Copyright 1993, 1994 Hewlett-Packard Company                   */
24 /*%%  (c) Copyright 1993, 1994 International Business Machines Corp.     */
25 /*%%  (c) Copyright 1993, 1994 Sun Microsystems, Inc.                    */
26 /*%%  (c) Copyright 1993, 1994 Novell, Inc.                              */
27 /*%%  $XConsortium: edit.c /main/3 1995/10/23 09:46:34 rswiston $                                                        */
28 /*
29  * edit.c
30  *
31  * Copyright (c) 1993 by Sun Microsystems, Inc.
32  */
33
34 /* 
35  * Implementation of a simple "remote-control" editor. Accepts requests
36  * to edit, save, and close files as well as hilite "objects" created in
37  * the file. Objects are kept track of by wrapping them in C-style
38  * comments with their respective object ids. 
39  */
40 #include <stdio.h>
41 #include <stdlib.h>
42 #include <unistd.h>
43 #include <string.h>
44 #include <sys/param.h>
45 #include <sys/types.h>
46 #include <sys/stat.h>
47 #include <Xm/Xm.h>
48 #include <Xm/Label.h>
49 #include <Xm/Form.h>
50 #include <Xm/PushB.h>
51 #include <Xm/Text.h>
52 #include <desktop/tt_c.h>
53 #include "Sun_EditDemo_opnums.h"
54
55 Display *dpy;
56 XtAppContext app;
57 char current_file[MAXPATHLEN];
58 int do_close = 0;
59 int text_modified = -1;
60
61 Widget  edit_ui_base_window;
62 Widget  edit_ui_textpane;
63 Widget  edit_ui_panel;
64 Widget  edit_ui_obj_button;
65 Widget  edit_ui_message;
66
67
68 void
69 main(argc, argv)
70         int             argc;
71         char            **argv;
72 {
73         char    *dfile;
74
75         /*
76          * Initialize Motif.
77          */
78         XtToolkitInitialize();
79         app = XtCreateApplicationContext();
80         dpy = XtOpenDisplay(app, 0, 0, "edit", 0, 0, &argc, argv );
81         
82         /*
83          * Initialize user interface components.
84          */
85         edit_ui_initialize();
86         if (! edit_init_tt()) {
87                 fprintf(stderr,"%s: Can't initialize ToolTalk\n", argv[0]);
88                 exit(1);
89         }
90         /*
91          * Turn control over to Motif.
92          */
93         while (! do_close) {
94                 XEvent event;
95                 XtAppNextEvent(app, &event);
96                 XtDispatchEvent(&event);
97         }
98         if ((dfile = tt_default_file()) != (char *)0) {
99                 tt_file_quit(dfile);
100         }
101         tt_close();
102         exit(0);
103 }
104
105
106 void
107 write_footer(message)
108         char *message;
109 {
110         XmString label;
111
112         label = XmStringCreateSimple(message);
113         XtVaSetValues(edit_ui_message, XmNlabelString, label, 0);
114         XmStringFree(label);
115 }
116
117
118 Tt_status
119 read_file(widget, file)
120         Widget widget;
121         char    *file;
122 {
123         char buf[BUFSIZ], *text;
124         struct stat statb;
125         int len;
126         FILE *fp;
127         Tt_status status;
128
129         /*
130          * Make sure the file is a regular text file and open it.
131          */
132
133         if (stat(file, &statb) == -1 || (statb.st_mode & S_IFMT) != S_IFREG ||
134                  !(fp = fopen(file, "r"))) {
135                 perror(file);
136                 return TT_ERR_FILE;
137         }
138            
139         /*
140          * Put the contents of the file in the Text widget by allocating
141          * enough space for the entire file, reading the file into the space,
142          * and using XmTextSetString() to show the file.
143          */
144
145         strcpy(current_file, file);
146         len = (int) statb.st_size;
147         if (!(text = XtMalloc((unsigned)(len+1)))) {
148                 sprintf(buf, "%s: XtMalloc(%ld) failed", file, len);
149                 XmTextSetString(widget, buf);
150         } else {
151                 if (fread(text, sizeof(char), len, fp) != len) {
152                         status = TT_ERR_FILE;
153                 } else {
154                         status = TT_OK;
155                         text[len] = 0;
156                         XmTextSetString(widget, text);
157                 }
158         }
159         XtFree(text);
160         fclose(fp);
161         return status;
162 }
163
164
165 /* Write the contents of a text widget to a file. */
166
167 Tt_status
168 write_file(widget, file)
169         Widget  widget;
170         char    *file;
171 {
172         char *text;
173         int len;
174         FILE *fp;
175         Tt_status status;
176
177         if (!(fp = fopen(file, "w"))) {
178                 perror(file);
179                 return TT_ERR_FILE;
180         }
181
182 /* Saving -- get text from the text widget. */
183
184         text = XmTextGetString(widget);
185         len = (int) XmTextGetLastPosition(widget);
186             
187 /* Write it to file (check for error). */
188             
189         if (fwrite(text, sizeof(char), len, fp) != len) {
190                 status = TT_ERR_FILE;
191         } else {
192                 status = TT_OK;
193         }
194         fclose(fp);
195         return status;
196 }
197
198
199 /* 
200  * Initialize our ToolTalk environment.
201  */
202 int
203 edit_init_tt()
204 {
205         int     mark;
206         char    *procid = tt_open();
207         int     ttfd;
208         void    edit_receive_tt_message();
209
210         mark = tt_mark();
211
212         if (tt_pointer_error(procid) != TT_OK) {
213                 return 0;
214         }
215         if (tt_ptype_declare("Sun_EditDemo") != TT_OK) {
216                 fprintf(stderr,"Sun_EditDemo is not an installed ptype.\n");
217                 return 0;
218         }
219         ttfd = tt_fd();
220         XtAppAddInput(app, ttfd, (XtPointer) XtInputReadMask,
221                       edit_receive_tt_message, 0);
222
223         tt_session_join(tt_default_session());
224
225         /*
226          * Note that without tt_mark() and tt_release(), the above
227          * combination would leak storage -- tt_default_session() returns
228          * a copy owned by the application, but since we don't assign the
229          * pointer to a variable we could not free it explicitly.
230          */
231
232         tt_release(mark);
233         return 1;
234 }
235
236
237 /* 
238  * Handle any incoming ToolTalk messages.
239  */
240 void
241 edit_receive_tt_message(client_data, fid, id)
242         XtPointer client_data;
243         int *fid;
244         XtInputId *id;
245 {
246         Tt_message              msg_in;
247         int                     opnum;
248         int                     opstatus;
249         char                    *file;
250
251         msg_in = tt_message_receive();
252         if (msg_in == NULL) return;
253         if (tt_pointer_error(msg_in) == TT_ERR_NOMP) {
254                 fprintf(stderr,"ToolTalk server down.\n");
255                 exit(0);
256         }
257         switch (tt_message_opnum(msg_in)) {
258               case SUN_EDITDEMO_EDIT:
259                 opstatus = edit_edit(msg_in);
260                 break;
261               case SUN_EDITDEMO_SAVE:
262                 opstatus = edit_save(msg_in);
263                 break;
264               case SUN_EDITDEMO_SAVE_AS:
265                 opstatus = edit_save(msg_in);
266                 break;
267               case SUN_EDITDEMO_CLOSE:
268                 opstatus = edit_close(msg_in);
269                 break;
270               case SUN_EDITDEMO_HILITE_OBJ:
271                 opstatus = edit_hilite_obj(msg_in);
272                 break;
273               default:
274                 /* don't know what else to do with this message */
275                 tt_message_reject(msg_in);
276                 break;
277         }
278         if (opstatus == 0) {
279                 tt_message_fail(msg_in);
280         } else {
281                 tt_message_reply(msg_in);
282         }
283         tt_message_destroy(msg_in);
284
285         return;
286 }
287
288
289 /* 
290  * Handle the "edit" op.
291  */
292 int
293 edit_edit(msg)
294      Tt_message msg;
295 {
296         int     mark = tt_mark();
297         char    *file = tt_message_file(msg);
298         char    *dfile = tt_default_file();
299         char    buf[255];
300
301         if (access(file, R_OK) != 0) {
302                 tt_message_status_set(msg, TT_ERR_FILE);
303                 tt_message_status_string_set(msg,"Can't open file for read.");
304                 tt_release(mark);
305                 return 0;
306         } else {
307                 if (dfile == (char *)0 || 0 != strcmp(dfile, file)) {
308                         /* if not already editing this file, load it */
309                         /* in. */
310                         tt_default_file_set(file);
311                         tt_file_join(file);
312                         read_file(edit_ui_textpane, file);
313                         sprintf(buf,"Sun_EditDemo_edit: (%s)", file);
314                         XtVaSetValues(edit_ui_base_window,
315                                       XmNtitle, buf, 0);
316                 }
317                 tt_release(mark);
318                 return 1;
319         }
320         
321 }
322
323
324 /* 
325  * Handle the "save" op.
326  */
327 int
328 edit_save(msg)
329      Tt_message msg;
330 {
331         int             mark = tt_mark();
332         char            *new_file;
333
334         if (text_modified == 0) {
335                 /* no save is needed */
336                 tt_release(mark);
337                 return 1;
338         } 
339
340         if (tt_message_opnum(msg) == SUN_EDITDEMO_SAVE) {
341                 if (write_file(edit_ui_textpane, current_file) == TT_OK) {
342                         text_modified = 0;
343                         tt_message_reply(msg);
344                         tt_release(mark);
345                         return 1;
346                 }
347         } else {
348                 /* handle SAVE_AS */
349                 new_file = tt_message_arg_val(msg, 0);
350                 if (write_file(edit_ui_textpane, new_file) == TT_OK) {
351                         tt_file_quit(tt_default_file());
352                         tt_default_file_set(new_file);
353                         tt_file_join(new_file);
354                         read_file(edit_ui_textpane, new_file);
355                         tt_release(mark);
356                         return 1;
357                 }
358         }
359
360         /* couldn't complete operation */
361         tt_message_status_set(msg, TT_ERR_FILE);
362         tt_message_status_string_set(msg, "Couldn't save file");
363         tt_release(mark);
364         return 0;
365 }
366
367
368 /* 
369  * Handle the "close" op.
370  */
371 int
372 edit_close(msg)
373      Tt_message msg;
374 {
375         Atom wmchs;
376         Window w;
377         XClientMessageEvent xev;
378
379         if (text_modified > 0) {
380                 tt_message_status_set(msg, TT_ERR_FILE);
381                 tt_message_status_string_set(msg, "File has been modified");
382                 return 0;
383         } else {
384                 do_close = 1;
385
386 /* Send an event to force the event loop to "click on" and quit the program. */
387
388                 w = XtWindow(edit_ui_base_window);
389                 wmchs = XInternAtom(dpy, "WM_CHANGE_STATE", True);
390                 xev.type         = ClientMessage;
391                 xev.message_type = wmchs;
392                 xev.window       = w;
393                 xev.format       = 32;
394                 xev.data.l[0]    = IconicState;
395                 XSendEvent(dpy, w, True, (SubstructureRedirectMask |
396                            SubstructureNotifyMask), &xev) ;
397                 XFlush(dpy);
398                 return 1;
399         }
400 }
401
402 /* 
403  * Handle the "hilite_obj" op.
404  */
405 int
406 edit_hilite_obj(msg)
407      Tt_message msg;
408 {
409         int     mark = tt_mark();
410         char    *objid = tt_message_arg_val(msg, 0);
411         char    obj_start_text[100];
412         char    obj_end_text[100];
413
414         if (tt_message_status(msg) == TT_WRN_START_MESSAGE
415             && edit_edit(msg) == 0) {
416                 /* we were started to hilite an object but couldn't load the */
417                 /* file into the textpane. */
418                 tt_release(mark);
419                 return 0;
420         }
421
422         /* expect objects to be wrapped by appropiately formatted */
423         /* C-style comments. */
424
425         sprintf(obj_start_text," /* begin_object(%s) */", objid);
426         sprintf(obj_end_text,"  /* end_object(%s) */", objid);
427
428         if (select_region(edit_ui_textpane,
429                           obj_start_text,
430                           obj_end_text) == 1) {
431                 tt_release(mark);
432                 return 1;
433         } else {
434                 tt_message_status_set(msg, TT_ERR_OBJID);
435                 tt_message_status_string_set(msg,"Couldn't find object");
436
437                 tt_release(mark);
438                 return 0;
439         }
440 }
441
442
443 /* 
444  * Make a ToolTalk spec out of the selected text in this textpane. Once
445  * the spec is succesfully created and written to a database, wrap the
446  * text with C-style comments in order to delimit the object and send out
447  * a notification that an object has been created in this file.
448  */
449 void
450 edit_ui_make_object(widget, client_data, call_data)
451         Widget widget;
452         XtPointer  client_data, call_data;
453 {
454         int             mark = tt_mark();
455         char            *objid;
456         char            *file;
457         char            *sel;
458         XmTextPosition  first, last;
459         char            obj_start_text[100];
460         char            obj_end_text[100];
461         Tt_message      msg;
462
463         if (! get_selection(edit_ui_textpane, &sel, &first, &last)) {
464                 write_footer("First select some text");
465                 tt_release(mark);
466                 return;
467         }
468         file = tt_default_file();
469
470         if (file == (char *)0) {
471                 write_footer("Not editing any file");
472                 tt_release(mark);
473                 return;
474         }
475
476         /* create a new spec */
477
478         objid = tt_spec_create(tt_default_file());
479         if (tt_pointer_error(objid) != TT_OK) {
480                 write_footer("Couldn't create object");
481                 tt_release(mark);
482                 return;
483         }
484
485
486         /* set its otype */
487
488         tt_spec_type_set(objid, "Sun_EditDemo_object");
489         if (tt_spec_write(objid) != TT_OK) {
490                 write_footer("Couldn't write out object");
491                 tt_release(mark);
492                 return;
493         }
494
495         /* wrap spec's contents (the selected text) with C-style */
496         /* comments. */
497
498         sprintf(obj_start_text," /* begin_object(%s) */", objid);
499         sprintf(obj_end_text,"  /* end_object(%s) */", objid);
500         (void)wrap_selection(edit_ui_textpane,
501                              obj_start_text, obj_end_text);
502         
503         /* now send out a notification that we've added a new object */
504
505         msg = tt_pnotice_create(TT_FILE_IN_SESSION,"Sun_EditDemo_new_object");
506         tt_message_file_set(msg, file);
507         tt_message_send(msg);
508
509         tt_release(mark);
510         return;
511 }
512
513
514
515 /* 
516  * Get the current selection. Returns 1 if the selection is in the passed
517  * in textsw.
518  */
519 int
520 get_selection(widget, selection, first_ptr, last_ptr)
521         Widget          widget;
522         char            **selection;
523         XmTextPosition  *first_ptr, *last_ptr;
524 {
525         char                    *ptr;
526
527         ptr = XmTextGetSelection(widget);
528         if (ptr == NULL) return 0;
529         *selection = malloc(strlen(ptr) + 1);
530         if (*selection == (char *)0) {
531                 return -1;
532         }
533         (void)strcpy(*selection, ptr);
534         XmTextGetSelectionPosition(widget, first_ptr, last_ptr);
535
536         return 1;
537 }
538
539
540
541 void
542 reverse_str(str)
543         char *str;
544 {
545         char c;
546         int i, n;
547
548         n = strlen(str);
549         for (i = 0; i < n/2; i++) {
550                 c = str[i];
551                 str[i] = str[n-i];
552                 str[n-i] = c;
553         }
554 }
555
556
557 int
558 text_find_bytes(widget, first, last, str, reverse)
559         Widget widget;
560         XmTextPosition *first, *last;
561         int reverse;
562         char *str;
563 {
564         char *ptr, *text;
565         int n;
566
567         text = XmTextGetString(widget);
568         if (reverse) {
569                 reverse_str(text);
570                 reverse_str(str);
571         }
572         ptr = strstr(&text[*first], str);
573         if (ptr == NULL) return -1;
574         n = strlen(str);
575         if (reverse) {
576                 *last  = (XmTextPosition) ptr;
577                 *first = (XmTextPosition) ptr - n;
578         } else {
579                 *first = (XmTextPosition) ptr;
580                 *last  = (XmTextPosition) ptr + n;
581         }
582         return 0;
583 }
584
585
586 /* 
587  * Selects region between "begin" and "end" in textsw. Returns 1 if
588  * successful. 
589  */
590 int
591 select_region(widget, begin, end)
592      Widget             widget;
593      char               *begin;
594      char               *end;
595 {
596         XmTextPosition          bfirst, blast, efirst, elast;
597         XmTextPosition          inspoint;
598         int                     status;
599
600         inspoint = XmTextGetInsertionPosition(widget);
601         /* Find the "begin" text */
602
603         /* first search forward */
604         bfirst = inspoint;
605         status = text_find_bytes(widget, &bfirst, &blast, begin, 0);
606         if (status == -1) {
607                 bfirst = inspoint;
608                 /* search failed, search backwards */
609                 status = text_find_bytes(widget, &bfirst, &blast, begin, 1);
610                 if (status == -1) {
611                         return 0;
612                 }
613         }
614
615         /* Find the "end" text */
616
617         efirst = inspoint;
618         /* first search forward */
619         status = text_find_bytes(widget, &efirst, &elast, end, 0);
620         if (status == -1) {
621                 efirst = inspoint;
622                 /* search failed, search backwards */
623                 status = text_find_bytes(widget, &efirst, &elast, end, 1);
624                 if (status == -1) {
625                         return 0;
626                 }
627         }
628         XmTextSetSelection(widget,
629                            (inspoint = (blast < elast) ? blast : elast),
630                            (efirst > bfirst) ? efirst : bfirst,
631                            CurrentTime);
632
633         XmTextSetInsertionPosition(widget, inspoint);
634         XmTextShowPosition(widget, inspoint);
635         return 1;
636 }
637
638 /* 
639  * Wraps the selected text in textsw with the begin and end strings
640  * supplied. Returns 1 if successful.
641  */
642 int
643 wrap_selection(widget, begin, end)
644      Widget             widget;
645      char               *begin;
646      char               *end;
647 {
648         char                    *buf;
649         char                    *sel;
650         XmTextPosition          sel_first, sel_last;
651         int                     sel_status;
652
653         if (! (sel_status = get_selection(widget,
654                                           &sel, &sel_first, &sel_last))) {
655                 return sel_status;
656         }
657                 
658         buf = malloc(strlen(sel) + strlen(begin) + strlen(end) + 3);
659         if (buf == (char *)0) {
660                 return -1;
661         }
662         sprintf(buf,"%s\n%s\n%s", begin, sel, end);
663         XmTextReplace(widget, sel_first, sel_last + 1, buf);
664         free(buf);
665         free(sel);
666         
667         return sel_status;
668 }
669
670
671 /*
672  *  Increment a flag every time this routine is called. Note that it's
673  *  called once, when the text is initially loaded, so the flag is initially
674  *  -1, to counter this.
675  */
676 text_modify(widget, client_data, cbs)
677         Widget widget;
678         XtPointer client_data;
679         XmTextVerifyCallbackStruct *cbs;
680 {
681         text_modified++;
682 }
683
684
685 /* 
686  * Initialize our ui environment.
687  */
688 edit_ui_initialize()
689 {
690         Arg args[20];
691         Pixmap icon;
692         XmString label;
693         int n, screen;
694
695         static unsigned short   icon_bits[] = {
696         0x3FFF,0xFF00,
697         0x2000,0x0180,
698         0x2000,0x0140,
699         0x2000,0x0120,
700         0x2000,0x0110,
701         0x2000,0x0108,
702         0x2000,0x0104,
703         0x2000,0x01FE,
704         0x2000,0x0006,
705         0x2000,0x0006,
706         0x2000,0x0006,
707         0x2000,0x0006,
708         0x2000,0x0006,
709         0x2000,0x0006,
710         0x2000,0x0006,
711         0x2000,0x0006,
712         0x2000,0x0006,
713         0x2000,0x0006,
714         0x2000,0x0006,
715         0x2000,0x0006,
716         0x2000,0x0006,
717         0x2000,0x0006,
718         0x2000,0x0006,
719         0x2000,0x0006,
720         0x2000,0x0006,
721         0x2000,0x0006,
722         0x2000,0x0006,
723         0x2000,0x0006,
724         0x2000,0x0006,
725         0x2000,0x0006,
726         0x3FFF,0xFFFE,
727         0x1FFF,0xFFFE
728         };
729
730         edit_ui_base_window = XtAppCreateShell(0, "base_frame",
731                                 applicationShellWidgetClass, dpy, 0, 0 );
732         screen = DefaultScreen(dpy);
733         icon = XCreatePixmapFromBitmapData(dpy, RootWindow(dpy, screen),
734                                       (char *) icon_bits, 32, 32, 1, 0, 1);
735         XtVaSetValues(edit_ui_base_window,
736                       XmNwidth,      509,
737                       XmNheight,     420,
738                       XmNtitle,      "Sun_EditDemo_edit",
739                       XmNiconName,   "Sun_EditDemo_edit",
740                       XmNiconPixmap, icon,
741                       0);
742         
743         edit_ui_panel = XtVaCreateManagedWidget("panel",
744                                   xmFormWidgetClass, edit_ui_base_window, 0);
745
746         label = XmStringCreateSimple("Make object");
747         edit_ui_obj_button = XtVaCreateManagedWidget("button",
748                 xmPushButtonWidgetClass, edit_ui_panel,
749                 XmNtopAttachment,    XmATTACH_FORM,
750                 XmNtopOffset,        5,  
751                 XmNleftAttachment,   XmATTACH_FORM,
752                 XmNleftOffset,       5,
753                 XmNlabelString,      label,
754                 0);          
755         XmStringFree(label); 
756         XtAddCallback(edit_ui_obj_button,
757                   XmNactivateCallback, edit_ui_make_object, 0);
758
759         XtManageChild(edit_ui_panel);
760
761         n = 0;
762         XtSetArg(args[n], XmNeditMode,         XmMULTI_LINE_EDIT);  n++;
763         XtSetArg(args[n], XmNresizable,        True);               n++;
764         XtSetArg(args[n], XmNtopAttachment,    XmATTACH_WIDGET);    n++;
765         XtSetArg(args[n], XmNtopWidget,        edit_ui_obj_button); n++;
766         XtSetArg(args[n], XmNleftAttachment,   XmATTACH_FORM);      n++;
767         XtSetArg(args[n], XmNrightAttachment,  XmATTACH_FORM);      n++;
768         XtSetArg(args[n], XmNleftOffset,       5);                  n++;
769         XtSetArg(args[n], XmNrightOffset,      5);                  n++;
770         XtSetArg(args[n], XmNtopOffset,        5);                  n++;
771         XtSetArg(args[n], XmNrows,             24);                 n++;
772         XtSetArg(args[n], XmNcolumns,          80);                 n++;
773         edit_ui_textpane = XmCreateScrolledText(edit_ui_panel, "textpane",
774                                                 args, n);
775
776         XtAddCallback(edit_ui_textpane, XmNmodifyVerifyCallback,
777                       text_modify, 0);
778         edit_ui_message = XtVaCreateManagedWidget("message",
779                                  xmLabelWidgetClass,  edit_ui_panel,
780                                  XmNtopAttachment,    XmATTACH_WIDGET,
781                                  XmNtopWidget,        edit_ui_textpane,
782                                  XmNtopOffset,        10, 
783                                  XmNleftAttachment,   XmATTACH_FORM,
784                                  XmNleftOffset,       5, 
785                                  XmNrightAttachment,  XmATTACH_FORM,
786                                  XmNrightOffset,      5, 
787                                  XmNbottomAttachment, XmATTACH_FORM,
788                                  XmNbottomOffset,     5, 
789                                  0);
790         label = XmStringCreateSimple("");
791         XtVaSetValues(edit_ui_message, XmNlabelString, label, 0);
792         XmStringFree(label);
793
794         XtManageChild(edit_ui_textpane);
795         XtRealizeWidget(edit_ui_base_window);
796 }