2 * CDE - Common Desktop Environment
4 * Copyright (c) 1993-2012, The Open Group. All rights reserved.
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)
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
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
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 $ */
31 * Copyright (c) 1993 by Sun Microsystems, Inc.
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.
44 #include <sys/param.h>
45 #include <sys/types.h>
52 #include <desktop/tt_c.h>
53 #include "Sun_EditDemo_opnums.h"
57 char current_file[MAXPATHLEN];
59 int text_modified = -1;
61 Widget edit_ui_base_window;
62 Widget edit_ui_textpane;
64 Widget edit_ui_obj_button;
65 Widget edit_ui_message;
78 XtToolkitInitialize();
79 app = XtCreateApplicationContext();
80 dpy = XtOpenDisplay(app, 0, 0, "edit", 0, 0, &argc, argv );
83 * Initialize user interface components.
86 if (! edit_init_tt()) {
87 fprintf(stderr,"%s: Can't initialize ToolTalk\n", argv[0]);
91 * Turn control over to Motif.
95 XtAppNextEvent(app, &event);
96 XtDispatchEvent(&event);
98 if ((dfile = tt_default_file()) != (char *)0) {
107 write_footer(message)
112 label = XmStringCreateSimple(message);
113 XtVaSetValues(edit_ui_message, XmNlabelString, label, 0);
119 read_file(widget, file)
123 char buf[BUFSIZ], *text;
130 * Make sure the file is a regular text file and open it.
133 if (stat(file, &statb) == -1 || (statb.st_mode & S_IFMT) != S_IFREG ||
134 !(fp = fopen(file, "r"))) {
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.
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);
151 if (fread(text, sizeof(char), len, fp) != len) {
152 status = TT_ERR_FILE;
156 XmTextSetString(widget, text);
165 /* Write the contents of a text widget to a file. */
168 write_file(widget, file)
177 if (!(fp = fopen(file, "w"))) {
182 /* Saving -- get text from the text widget. */
184 text = XmTextGetString(widget);
185 len = (int) XmTextGetLastPosition(widget);
187 /* Write it to file (check for error). */
189 if (fwrite(text, sizeof(char), len, fp) != len) {
190 status = TT_ERR_FILE;
200 * Initialize our ToolTalk environment.
206 char *procid = tt_open();
208 void edit_receive_tt_message();
212 if (tt_pointer_error(procid) != TT_OK) {
215 if (tt_ptype_declare("Sun_EditDemo") != TT_OK) {
216 fprintf(stderr,"Sun_EditDemo is not an installed ptype.\n");
220 XtAppAddInput(app, ttfd, (XtPointer) XtInputReadMask,
221 edit_receive_tt_message, 0);
223 tt_session_join(tt_default_session());
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.
238 * Handle any incoming ToolTalk messages.
241 edit_receive_tt_message(client_data, fid, id)
242 XtPointer client_data;
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");
257 switch (tt_message_opnum(msg_in)) {
258 case SUN_EDITDEMO_EDIT:
259 opstatus = edit_edit(msg_in);
261 case SUN_EDITDEMO_SAVE:
262 opstatus = edit_save(msg_in);
264 case SUN_EDITDEMO_SAVE_AS:
265 opstatus = edit_save(msg_in);
267 case SUN_EDITDEMO_CLOSE:
268 opstatus = edit_close(msg_in);
270 case SUN_EDITDEMO_HILITE_OBJ:
271 opstatus = edit_hilite_obj(msg_in);
274 /* don't know what else to do with this message */
275 tt_message_reject(msg_in);
279 tt_message_fail(msg_in);
281 tt_message_reply(msg_in);
283 tt_message_destroy(msg_in);
290 * Handle the "edit" op.
296 int mark = tt_mark();
297 char *file = tt_message_file(msg);
298 char *dfile = tt_default_file();
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.");
307 if (dfile == (char *)0 || 0 != strcmp(dfile, file)) {
308 /* if not already editing this file, load it */
310 tt_default_file_set(file);
312 read_file(edit_ui_textpane, file);
313 sprintf(buf,"Sun_EditDemo_edit: (%s)", file);
314 XtVaSetValues(edit_ui_base_window,
325 * Handle the "save" op.
331 int mark = tt_mark();
334 if (text_modified == 0) {
335 /* no save is needed */
340 if (tt_message_opnum(msg) == SUN_EDITDEMO_SAVE) {
341 if (write_file(edit_ui_textpane, current_file) == TT_OK) {
343 tt_message_reply(msg);
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);
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");
369 * Handle the "close" op.
377 XClientMessageEvent xev;
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");
386 /* Send an event to force the event loop to "click on" and quit the program. */
388 w = XtWindow(edit_ui_base_window);
389 wmchs = XInternAtom(dpy, "WM_CHANGE_STATE", True);
390 xev.type = ClientMessage;
391 xev.message_type = wmchs;
394 xev.data.l[0] = IconicState;
395 XSendEvent(dpy, w, True, (SubstructureRedirectMask |
396 SubstructureNotifyMask), &xev) ;
403 * Handle the "hilite_obj" op.
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];
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. */
422 /* expect objects to be wrapped by appropiately formatted */
423 /* C-style comments. */
425 sprintf(obj_start_text," /* begin_object(%s) */", objid);
426 sprintf(obj_end_text," /* end_object(%s) */", objid);
428 if (select_region(edit_ui_textpane,
430 obj_end_text) == 1) {
434 tt_message_status_set(msg, TT_ERR_OBJID);
435 tt_message_status_string_set(msg,"Couldn't find object");
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.
450 edit_ui_make_object(widget, client_data, call_data)
452 XtPointer client_data, call_data;
454 int mark = tt_mark();
458 XmTextPosition first, last;
459 char obj_start_text[100];
460 char obj_end_text[100];
463 if (! get_selection(edit_ui_textpane, &sel, &first, &last)) {
464 write_footer("First select some text");
468 file = tt_default_file();
470 if (file == (char *)0) {
471 write_footer("Not editing any file");
476 /* create a new spec */
478 objid = tt_spec_create(tt_default_file());
479 if (tt_pointer_error(objid) != TT_OK) {
480 write_footer("Couldn't create object");
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");
495 /* wrap spec's contents (the selected text) with C-style */
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);
503 /* now send out a notification that we've added a new object */
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);
516 * Get the current selection. Returns 1 if the selection is in the passed
520 get_selection(widget, selection, first_ptr, last_ptr)
523 XmTextPosition *first_ptr, *last_ptr;
527 ptr = XmTextGetSelection(widget);
528 if (ptr == NULL) return 0;
529 *selection = malloc(strlen(ptr) + 1);
530 if (*selection == (char *)0) {
533 (void)strcpy(*selection, ptr);
534 XmTextGetSelectionPosition(widget, first_ptr, last_ptr);
549 for (i = 0; i < n/2; i++) {
558 text_find_bytes(widget, first, last, str, reverse)
560 XmTextPosition *first, *last;
567 text = XmTextGetString(widget);
572 ptr = strstr(&text[*first], str);
573 if (ptr == NULL) return -1;
576 *last = (XmTextPosition) ptr;
577 *first = (XmTextPosition) ptr - n;
579 *first = (XmTextPosition) ptr;
580 *last = (XmTextPosition) ptr + n;
587 * Selects region between "begin" and "end" in textsw. Returns 1 if
591 select_region(widget, begin, end)
596 XmTextPosition bfirst, blast, efirst, elast;
597 XmTextPosition inspoint;
600 inspoint = XmTextGetInsertionPosition(widget);
601 /* Find the "begin" text */
603 /* first search forward */
605 status = text_find_bytes(widget, &bfirst, &blast, begin, 0);
608 /* search failed, search backwards */
609 status = text_find_bytes(widget, &bfirst, &blast, begin, 1);
615 /* Find the "end" text */
618 /* first search forward */
619 status = text_find_bytes(widget, &efirst, &elast, end, 0);
622 /* search failed, search backwards */
623 status = text_find_bytes(widget, &efirst, &elast, end, 1);
628 XmTextSetSelection(widget,
629 (inspoint = (blast < elast) ? blast : elast),
630 (efirst > bfirst) ? efirst : bfirst,
633 XmTextSetInsertionPosition(widget, inspoint);
634 XmTextShowPosition(widget, inspoint);
639 * Wraps the selected text in textsw with the begin and end strings
640 * supplied. Returns 1 if successful.
643 wrap_selection(widget, begin, end)
650 XmTextPosition sel_first, sel_last;
653 if (! (sel_status = get_selection(widget,
654 &sel, &sel_first, &sel_last))) {
658 buf = malloc(strlen(sel) + strlen(begin) + strlen(end) + 3);
659 if (buf == (char *)0) {
662 sprintf(buf,"%s\n%s\n%s", begin, sel, end);
663 XmTextReplace(widget, sel_first, sel_last + 1, buf);
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.
676 text_modify(widget, client_data, cbs)
678 XtPointer client_data;
679 XmTextVerifyCallbackStruct *cbs;
686 * Initialize our ui environment.
695 static unsigned short icon_bits[] = {
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,
738 XmNtitle, "Sun_EditDemo_edit",
739 XmNiconName, "Sun_EditDemo_edit",
743 edit_ui_panel = XtVaCreateManagedWidget("panel",
744 xmFormWidgetClass, edit_ui_base_window, 0);
746 label = XmStringCreateSimple("Make object");
747 edit_ui_obj_button = XtVaCreateManagedWidget("button",
748 xmPushButtonWidgetClass, edit_ui_panel,
749 XmNtopAttachment, XmATTACH_FORM,
751 XmNleftAttachment, XmATTACH_FORM,
753 XmNlabelString, label,
756 XtAddCallback(edit_ui_obj_button,
757 XmNactivateCallback, edit_ui_make_object, 0);
759 XtManageChild(edit_ui_panel);
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",
776 XtAddCallback(edit_ui_textpane, XmNmodifyVerifyCallback,
778 edit_ui_message = XtVaCreateManagedWidget("message",
779 xmLabelWidgetClass, edit_ui_panel,
780 XmNtopAttachment, XmATTACH_WIDGET,
781 XmNtopWidget, edit_ui_textpane,
783 XmNleftAttachment, XmATTACH_FORM,
785 XmNrightAttachment, XmATTACH_FORM,
787 XmNbottomAttachment, XmATTACH_FORM,
790 label = XmStringCreateSimple("");
791 XtVaSetValues(edit_ui_message, XmNlabelString, label, 0);
794 XtManageChild(edit_ui_textpane);
795 XtRealizeWidget(edit_ui_base_window);