Edit

IABSD.fr/xenocara/app/xedit/xedit.c

Branch :

  • Show log

    Commit

  • Author : matthieu
    Date : 2010-10-31 19:19:11
    Hash : f1c430b3
    Message : Update to xedit 1.2.0

  • app/xedit/xedit.c
  • /* $XConsortium: xedit.c,v 1.28 94/03/26 17:06:28 rws Exp $ */
     
    /*
     *			  COPYRIGHT 1987
     *		   DIGITAL EQUIPMENT CORPORATION
     *		       MAYNARD, MASSACHUSETTS
     *			ALL RIGHTS RESERVED.
     *
     * THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND
     * SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION.
     * DIGITAL MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR
     * ANY PURPOSE.  IT IS SUPPLIED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
     *
     * IF THE SOFTWARE IS MODIFIED IN A MANNER CREATING DERIVATIVE COPYRIGHT RIGHTS,
     * APPROPRIATE LEGENDS MAY BE PLACED ON THE DERIVATIVE WORK IN ADDITION TO THAT
     * SET FORTH ABOVE.
     *
     *
     * Permission to use, copy, modify, and distribute this software and its
     * documentation for any purpose and without fee is hereby granted, provided
     * that the above copyright notice appear in all copies and that both that
     * copyright notice and this permission notice appear in supporting
     * documentation, and that the name of Digital Equipment Corporation not be 
     * used in advertising or publicity pertaining to distribution of the software
     * without specific, written prior permission.
     */
    /* $XFree86: xc/programs/xedit/xedit.c,v 1.17 2002/09/22 07:09:05 paulo Exp $ */
    
    #include "xedit.h"
    #include <X11/Xaw/SmeBSB.h>
    #include <time.h>
    #include <sys/stat.h>
    #include <X11/CoreP.h>
    
    #include <stdlib.h> 
    
    #define randomize()	srand((unsigned)time((time_t*)NULL))
    
    static XtActionsRec actions[] = {
    {"quit", QuitAction},
    {"save-file", SaveFile},
    {"load-file", LoadFile},
    {"find-file", FindFile},
    {"cancel-find-file", CancelFindFile},
    {"file-completion", FileCompletion},
    {"popup-menu", PopupMenu},
    {"kill-file", KillFile},
    {"split-window", SplitWindow},
    {"dir-window", DirWindow},
    {"delete-window", DeleteWindow},
    {"xedit-focus", XeditFocus},
    {"other-window", OtherWindow},
    {"switch-source", SwitchSource},
    #ifndef __UNIXOS2__
    {"lisp-eval", XeditLispEval},
    {"xedit-print-lisp-eval", XeditPrintLispEval},
    {"xedit-keyboard-reset",XeditKeyboardReset},
    #endif
    {"ispell", IspellAction},
    {"line-edit", LineEditAction},
    {"tags", TagsAction}
    };
    
    #define DEF_HINT_INTERVAL	300	/* in seconds, 5 minutes */
    
    static Atom wm_delete_window;
    static Widget hintswindow;
    static int position_format_mask;
    static XawTextPositionInfo infos[3];
    
    Widget topwindow, textwindow, messwidget, labelwindow, filenamewindow;
    Widget scratch, hpane, vpanes[2], labels[3], texts[3], forms[3], positions[3];
    Widget options_popup, dirlabel, dirwindow;
    Boolean international;
    Boolean line_edit;
    XawTextWrapMode wrapmodes[3];
    
    extern void ResetSourceChanged(xedit_flist_item*);
    
    static void makeButtonsAndBoxes(Widget);
    static void HintsTimer(XtPointer, XtIntervalId*);
    static void PositionChanged(Widget, XtPointer, XtPointer);
    static void StartFormatPosition(void);
    static void StartHints(void);
    
    Display *CurDpy;
    
    struct _app_resources app_resources;
    struct _xedit_flist flist;
    
    #define Offset(field) XtOffsetOf(struct _app_resources, field)
    
    static XtResource resources[] = {
       {"enableBackups", "EnableBackups", XtRBoolean, sizeof(Boolean),
             Offset(enableBackups), XtRImmediate, FALSE},
       {"backupNamePrefix", "BackupNamePrefix", XtRString, sizeof(char *),
             Offset(backupNamePrefix),XtRString, ""},
       {"backupNameSuffix", "BackupNameSuffix", XtRString, sizeof(char *),
             Offset(backupNameSuffix),XtRString, ".BAK"},
       {"hints", "Hint", XtRString, sizeof(char *),
    	 Offset(hints.resource), XtRImmediate, NULL},
       {"hintsInterval", XtCInterval, XtRInt, sizeof(long),
    	 Offset(hints.interval), XtRImmediate, (XtPointer)DEF_HINT_INTERVAL},
       {"changedBitmap", XtRBitmap, XtRString, sizeof(char*),
    	 Offset(changed_pixmap_name), XtRString, "dot"},
       {"positionFormat", "Format", XtRString, sizeof(char*),
    	 Offset(position_format), XtRString, "L%l"},
       {"autoReplace", "Replace", XtRString, sizeof(char*),
    	 Offset(auto_replace), XtRImmediate, NULL},
       {"tagsName", "TagsName", XtRString, sizeof(char *),
             Offset(tagsName), XtRString, "tags"},
       {"loadTags", "LoadTags", XtRBoolean, sizeof(Boolean),
    	 Offset(loadTags), XtRImmediate, (XtPointer)TRUE},
    };
    
    #undef Offset
    
    int
    main(int argc, char *argv[])
    {
        Boolean		exists;
        char		*filename;
        FileAccess		file_access;
        Widget		source;
        XtAppContext	appcon;
        Boolean		show_dir;
        xedit_flist_item	*first_item;
        unsigned int	i, lineno;
    
        lineno = 0;
        show_dir = FALSE;
        first_item = NULL;
    
        topwindow = XtAppInitialize(&appcon, "Xedit", NULL, 0, &argc, argv,
    				NULL,
    				NULL, 0);
    
        XtAppAddActions(appcon, actions, XtNumber(actions));
        XtOverrideTranslations(topwindow,
    			   XtParseTranslationTable("<Message>WM_PROTOCOLS: quit()"));
    
        XtGetApplicationResources(topwindow, (XtPointer) &app_resources, resources,
    			      XtNumber(resources), NULL, 0);
    
        CurDpy = XtDisplay(topwindow);
        XawSimpleMenuAddGlobalActions(appcon);
        XtRegisterGrabAction(PopupMenu, True,
    			 ButtonPressMask | ButtonReleaseMask,
    			 GrabModeAsync, GrabModeAsync);
    
        makeButtonsAndBoxes(topwindow);
    
        StartHints();
        StartFormatPosition();
        (void)StartHooks(appcon);
        if (position_format_mask == 0) {
    	for (i = 0; i < 3; i++)
    	    XtRemoveCallback(texts[i], XtNpositionCallback,
    			     PositionChanged, NULL);
        }
        XtRealizeWidget(topwindow);
    
    #ifndef __UNIXOS2__
        XeditLispInitialize();
    #endif
    
        options_popup = XtCreatePopupShell("optionsMenu", simpleMenuWidgetClass,
    				       topwindow, NULL, 0);
        XtRealizeWidget(options_popup);
        XtAddCallback(XtCreateManagedWidget("ispell", smeBSBObjectClass,
    					options_popup, NULL, 0),
    		  XtNcallback, IspellCallback, NULL);
        CreateEditPopup();
    
        wm_delete_window = XInternAtom(XtDisplay(topwindow), "WM_DELETE_WINDOW",
    				   False);
        (void)XSetWMProtocols(XtDisplay(topwindow), XtWindow(topwindow),
    			  &wm_delete_window, 1);
    
        /* This first call is just to save the default font and colors */
        UpdateTextProperties(0);
    
        if (argc > 1) {
    	xedit_flist_item	*item;
    	Arg			args[2];
    	unsigned int		num_args;
    
    	for (i = 1; i < argc; i++) {
    	    struct stat st;
    
    	    if (argv[i][0] == '+') {
    		char	*endptr;
    
    		lineno = strtol(argv[i], &endptr, 10);
    		/* Don't warn about incorrect input? */
    		if (*endptr)
    		    lineno = 0;
    		continue;
    	    }
    
    	    filename = ResolveName(argv[i]);
    	    if (filename == NULL || FindTextSource(NULL, filename) != NULL)
    		continue;
    
    	    num_args = 0;
    	    if (stat(filename, &st) == 0 && !S_ISREG(st.st_mode)) {
    		if (S_ISDIR(st.st_mode)) {
    		    if (!first_item) {
    			char path[BUFSIZ + 1];
    
    			strncpy(path, filename, sizeof(path) - 2);
    			path[sizeof(path) - 2] = '\0';
    			if (*path) {
    			    if (path[strlen(path) - 1] != '/')
    				strcat(path, "/");
    			}
    			else
    			    strcpy(path, "./");
    			XtSetArg(args[0], XtNlabel, "");
    			XtSetValues(dirlabel, args, 1);
    			SwitchDirWindow(True);
    			DirWindowCB(dirwindow, path, NULL);
    			show_dir = True;
    		    }
    		    continue;
    		}
    	    }
    
    	    switch (file_access = CheckFilePermissions(filename, &exists)) {
    	    case NO_READ:
    		if (exists)
    		    XeditPrintf("File %s exists, and could not be opened for "
    				"reading.\n", argv[i]);
    		else
    		    XeditPrintf("File %s does not exist, and the directory "
    				"could not be opened for writing.\n", argv[i]);
    		break;
    	    case READ_OK:
    		XtSetArg(args[num_args], XtNeditType, XawtextRead); num_args++;
    		XeditPrintf("File %s opened READ ONLY.\n", argv[i]);
    		break;
    	    case WRITE_OK:
    		XtSetArg(args[num_args], XtNeditType, XawtextEdit); num_args++;
    		XeditPrintf("File %s opened read - write.\n", argv[i]);
    		break;
    	    }
    	    if (file_access != NO_READ) {
    		int flags;
    
    		if (exists) {
    		    flags = EXISTS_BIT;
    		    XtSetArg(args[num_args], XtNstring, filename);num_args++;
    		}
    		else {
    		    flags = 0;
    		    XtSetArg(args[num_args], XtNstring, NULL);	  num_args++;
    		}
    		source = XtVaCreateWidget("textSource", international ?
    					  multiSrcObjectClass
    					  : asciiSrcObjectClass, topwindow,
    					  XtNtype, XawAsciiFile,
    					  XtNeditType, XawtextEdit,
    					  NULL, NULL);
    		XtSetValues(source, args, num_args);
    		item = AddTextSource(source, argv[i], filename,
    				     flags, file_access);
    		XtAddCallback(item->source, XtNcallback, SourceChanged,
    			      (XtPointer)item);
    		if (exists && file_access == WRITE_OK) {
    		    item->mode = st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
    		    item->mtime = st.st_mtime;
    		}
    		if (!first_item && !show_dir)
    		    first_item = item;
    		ResetSourceChanged(item);
    	    }
    	}
        }
    
        if (!flist.pixmap && strlen(app_resources.changed_pixmap_name)) {
    	XrmValue from, to;
    
    	from.size = strlen(app_resources.changed_pixmap_name);
    	from.addr = app_resources.changed_pixmap_name;
    	to.size = sizeof(Pixmap);
    	to.addr = (XtPointer)&(flist.pixmap);
    
    	XtConvertAndStore(flist.popup, XtRString, &from, XtRBitmap, &to);
        }
    
        if (first_item == NULL) {
    	XtSetKeyboardFocus(topwindow, filenamewindow);
    	XtVaSetValues(textwindow, XtNwrap, XawtextWrapLine, NULL);
        }
        else {
    	SwitchTextSource(first_item);
    	XtSetKeyboardFocus(topwindow, textwindow);
    	if (lineno) {
    	    XawTextPosition position;
    
    	    source = XawTextGetSource(textwindow);
    	    position = RSCAN(XawTextGetInsertionPoint(textwindow),
    			     lineno, False);
    	    position = LSCAN(position, 1, False);
    	    XawTextSetInsertionPoint(textwindow, position);
    	}
        }
    
        XtAppMainLoop(appcon);
        return EXIT_SUCCESS;
    }
    
    static void
    makeButtonsAndBoxes(Widget parent)
    {
        Widget outer, b_row, viewport;
        Arg arglist[10];
        Cardinal num_args;
        xedit_flist_item *item;
        static char *labelWindow = "labelWindow", *editWindow = "editWindow";
        static char *formWindow = "formWindow", *positionWindow = "positionWindow";
    
        outer = XtCreateManagedWidget("paned", panedWidgetClass, parent,
    				  NULL, ZERO);
     
        b_row = XtCreateManagedWidget("buttons", panedWidgetClass, outer, NULL, ZERO);
        {
    	MakeCommandButton(b_row, "quit", DoQuit);
    	MakeCommandButton(b_row, "save", DoSave);
    	MakeCommandButton(b_row, "load", DoLoad);
    	filenamewindow = MakeStringBox(b_row, "filename", NULL);
        }
        hintswindow = XtCreateManagedWidget("bc_label", labelWidgetClass,
    					outer, NULL, ZERO);
    
        num_args = 0;
        XtSetArg(arglist[num_args], XtNeditType, XawtextEdit);		++num_args;
        messwidget = XtCreateManagedWidget("messageWindow", asciiTextWidgetClass,
    				       outer, arglist, num_args);
    
        num_args = 0;
        XtSetArg(arglist[num_args], XtNorientation, XtorientHorizontal);	++num_args;
        hpane = XtCreateManagedWidget("hpane", panedWidgetClass, outer,
    				  arglist, num_args);
    
        num_args = 0;
        XtSetArg(arglist[num_args], XtNorientation, XtorientVertical);	++num_args;
        vpanes[0] = XtCreateManagedWidget("vpane", panedWidgetClass, hpane,
    				      arglist, num_args);
        XtSetArg(arglist[num_args], XtNheight, 1);				++num_args;
        XtSetArg(arglist[num_args], XtNwidth, 1);				++num_args;
        vpanes[1] = XtCreateWidget("vpane", panedWidgetClass, hpane,
    			       arglist, num_args);
    
        forms[0] = XtCreateManagedWidget(formWindow, formWidgetClass,
    				     vpanes[0], NULL, 0);
        labelwindow = XtCreateManagedWidget(labelWindow,labelWidgetClass,
    					forms[0], NULL, 0);
        labels[0] = labelwindow;
        positions[0] = XtCreateManagedWidget(positionWindow,labelWidgetClass,
    					 forms[0], NULL, 0);
    
        forms[2] = XtCreateWidget(formWindow, formWidgetClass,
    			      vpanes[1], NULL, 0);
        labels[2] = XtCreateManagedWidget(labelWindow,labelWidgetClass,
    				      forms[2], NULL, 0);
        positions[2] = XtCreateManagedWidget(positionWindow,labelWidgetClass,
    					 forms[2], NULL, 0);
    
        num_args = 0;
        XtSetArg(arglist[num_args], XtNtype, XawAsciiFile);			++num_args;
        XtSetArg(arglist[num_args], XtNeditType, XawtextEdit);		++num_args;
        textwindow =  XtCreateManagedWidget(editWindow, asciiTextWidgetClass,
    					vpanes[0], arglist, num_args);
    
        /* Get international resource value form the textwindow */
        num_args = 0;
        XtSetArg(arglist[num_args], XtNinternational, &international);	++num_args;
        XtGetValues(textwindow, arglist, num_args);
    
        num_args = 0;
        XtSetArg(arglist[num_args], XtNtype, XawAsciiFile);			++num_args;
        XtSetArg(arglist[num_args], XtNeditType, XawtextEdit);		++num_args;
        scratch = XtVaCreateWidget("textSource", international ?
    			       multiSrcObjectClass :
    			       asciiSrcObjectClass, topwindow,
    			       XtNtype, XawAsciiFile,
    			       XtNeditType, XawtextEdit,
    			       NULL, NULL);
        XtSetValues(scratch, arglist, num_args);
    
        num_args = 0;
        XtSetArg(arglist[num_args], XtNtextSource, scratch);		++num_args;
        XtSetValues(textwindow, arglist, num_args);
    
        texts[0] = textwindow;
        num_args = 0;
        XtSetArg(arglist[num_args], XtNtextSource, scratch);		++num_args;
        XtSetArg(arglist[num_args], XtNdisplayCaret, False);		++num_args;
        texts[2] = XtCreateWidget(editWindow, asciiTextWidgetClass,
    			      vpanes[1], arglist, num_args);
    
        forms[1] = XtCreateWidget(formWindow, formWidgetClass,
    			      vpanes[0], NULL, 0);
        labels[1] = XtCreateManagedWidget(labelWindow,labelWidgetClass,
    				      forms[1], NULL, 0);
        positions[1] = XtCreateManagedWidget(positionWindow,labelWidgetClass,
    					 forms[1], NULL, 0);
    
        texts[1] = XtCreateWidget(editWindow, asciiTextWidgetClass,
    			      vpanes[0], arglist, num_args);
    
        dirlabel = XtCreateWidget("dirlabel", labelWidgetClass,
    			      vpanes[1], NULL, 0);
        num_args = 0;
        XtSetArg(arglist[num_args], XtNheight, 1);				++num_args;
        XtSetArg(arglist[num_args], XtNwidth, 1);				++num_args;
        viewport = XtCreateWidget("viewport", viewportWidgetClass,
    			      vpanes[1], arglist, num_args);
        dirwindow = XtCreateManagedWidget("dirwindow", listWidgetClass,
    				      viewport, NULL, 0);
    
        item = AddTextSource(scratch, "*scratch*", "*scratch*",
    			 0, WRITE_OK);
        item->wrap = XawtextWrapLine;
        item->flags |= WRAP_BIT;
        XtAddCallback(item->source, XtNcallback, SourceChanged,
    		  (XtPointer)item);
        ResetSourceChanged(item);
        flist.current = item;
    
        for (num_args = 0; num_args < 3; num_args++)
    	XtAddCallback(texts[num_args], XtNpositionCallback, PositionChanged, NULL);
    
        for (num_args = 0; num_args < 3; num_args++) {
    	XtSetArg(arglist[0], XtNwrap, &wrapmodes[num_args]);
    	XtGetValues(texts[num_args], arglist, 1);
        }
    
        XtAddCallback(dirwindow, XtNcallback, DirWindowCB, NULL);
    }
    
    /*	Function Name: Feep
     *	Description: feeps the bell.
     *	Arguments: none.
     *	Returns: none.
     */
    
    void
    Feep(void)
    {
      XBell(CurDpy, 0);
    }
    
    #define	l_BIT		0x01
    #define	c_BIT		0x02
    #define	p_BIT		0x04
    #define	s_BIT		0x08
    #define MAX_FMT_LEN	30
    
    static void
    StartFormatPosition(void)
    {
        char *fmt = app_resources.position_format;
    
        if (fmt)
    	while (*fmt)
    	    if (*fmt++ == '%') {
    		int len = 0;
    
    		if (*fmt == '-') {
    		    ++fmt;
    		    ++len;
    		}
    		while (*fmt >= '0' && *fmt <= '9') {
    		    ++fmt;
    		    if (++len >= MAX_FMT_LEN) {
    			XtAppWarning(XtWidgetToApplicationContext(topwindow),
    				     "Format too large to formatPosition");
    			position_format_mask = 0;
    			return;
    		    }
    		}
    		switch (*fmt++) {
    		    case 'l':	position_format_mask |= l_BIT;	break;
    		    case 'c':	position_format_mask |= c_BIT;	break;
    		    case 'p':	position_format_mask |= p_BIT;	break;
    		    case 's':	position_format_mask |= s_BIT;	break;
    		    case '%':	break;
    		    default: {
    			char msg[256];
    
    			XmuSnprintf(msg, sizeof(msg),
    				    "Unknown format \"%%%c\" in positionFormat",
    				    fmt[-1]);
    			XtAppWarning(XtWidgetToApplicationContext(topwindow),
    				     msg);
    			position_format_mask = 0;
    			return;
    		    }
    		}
    	    }
    }
    
    /*ARGSUSED*/
    static void
    PositionChanged(Widget w, XtPointer client_data, XtPointer call_data)
    {
        int idx;
        XawTextPositionInfo *info = (XawTextPositionInfo*)call_data;
    
        for (idx = 0; idx < 3; idx++)
    	if (w == texts[idx])
    	    break;
        if (idx > 2)
    	return;
    
        if (((position_format_mask & l_BIT)
    	  && infos[idx].line_number != info->line_number)
    	|| ((position_format_mask & c_BIT)
    	    && infos[idx].column_number != info->column_number)
    	|| ((position_format_mask & p_BIT)
    	    && infos[idx].insert_position != info->insert_position)
    	|| ((position_format_mask & s_BIT)
    	    && infos[idx].last_position != info->last_position)
    	|| infos[idx].overwrite_mode != info->overwrite_mode) {
    	int len = 6;
    	Arg args[1];
    	char buffer[256], *str = app_resources.position_format;
    	char fmt_buf[MAX_FMT_LEN + 2], *fmt;
    
    	memcpy(&infos[idx], info, sizeof(XawTextPositionInfo));
    	if (info->overwrite_mode)
    	    strcpy(buffer, "Ovrwt ");
    	else
    	    strcpy(buffer, "      ");
    	while (*str) {
    	    switch (*str) {
    		case '%':
    		    fmt = fmt_buf;
    		    *fmt++ = *str++;
    		    if (*str == '-')
    			*fmt++ = *str++;
    		    /*CONSTCOND*/
    		    while (*str >= '0' && *str <= '9') {
    			/* StartPositionFormat() already checked the format
    			 * length.
    			 */
    			*fmt++ = *str++;
    		    }
    		    *fmt++ = 'd';
    		    *fmt = '\0';
    		    switch (*str) {
    			case 'l':
    			    XmuSnprintf(&buffer[len], sizeof(buffer) - len,
    					fmt_buf, info->line_number);
    			    break;
    			case 'c':
    			    XmuSnprintf(&buffer[len], sizeof(buffer) - len,
    					fmt_buf, info->column_number);
    			    break;
    			case 'p':
    			    XmuSnprintf(&buffer[len], sizeof(buffer) - len,
    					fmt_buf, info->insert_position);
    			    break;
    			case 's':
    			    XmuSnprintf(&buffer[len], sizeof(buffer) - len,
    					fmt_buf, info->last_position);
    			    break;
    			case '%':
    			    strcpy(&buffer[len], "%");
    			    break;
    		    }
    		    len += strlen(&buffer[len]);
    		    break;
    		default:
    		    buffer[len++] = *str;
    		    break;
    	    }
    	    if (len >= sizeof(buffer) - 1)
    		break;
    	    ++str;
    	}
    	buffer[len] = '\0';
    
    	XtSetArg(args[0], XtNlabel, buffer);
    	XtSetValues(positions[idx], args, 1);
        }
    }
    
    /*ARGSUSED*/
    static void
    HintsTimer(XtPointer closure, XtIntervalId *id)
    {
        Arg args[1];
        xedit_hints *hints = (xedit_hints*)closure;
    
        hints->cur_hint = rand() % hints->num_hints;
    
        XtSetArg(args[0], XtNlabel, hints->hints[hints->cur_hint]);
        XtSetValues(hintswindow, args, 1);
    
        hints->timer = XtAppAddTimeOut(XtWidgetToApplicationContext(topwindow),
    				   hints->interval, HintsTimer, closure);
    }
    
    #define MAX_HINT_LEN		255
    #define MIN_HINT_INTERVAL	5
    static void
    StartHints(void)
    {
        char *str, *p;
        unsigned i, len;
        xedit_hints *hints = &(app_resources.hints);
    
        /* if resource was not set, or was overriden */
        if (hints->resource == NULL || !*hints->resource)
    	return;
    
        randomize();
    
        if (hints->interval < MIN_HINT_INTERVAL)
    	hints->interval = DEF_HINT_INTERVAL;
        hints->interval *= 1000;
        hints->hints = (char**)XtMalloc(sizeof(char*));
        hints->hints[hints->cur_hint = 0] = p = hints->resource;
        hints->num_hints = 1;
    
        while ((p = strchr(p, '\n')) != NULL) {
    	if (*++p == '\0')
    	    break;
    	hints->hints = (char**)
    	    XtRealloc((char*)hints->hints,
    		      sizeof(char*) * (hints->num_hints + 1));
    	hints->hints[hints->num_hints++] = p;
        }
    
        /* make a private copy of the resource values, so that one can change
         * the Xrm database safely.
         */
        for (i = 0; i < hints->num_hints; i++) {
    	if ((p = strchr(hints->hints[i], '\n')) != NULL)
    	    len = p - hints->hints[i];
    	else
    	    len = strlen(hints->hints[i]);
    	if (len > MAX_HINT_LEN)
    	    len = MAX_HINT_LEN;
    	str = XtMalloc(len + 1);
    	strncpy(str, hints->hints[i], len);
    	str[len] = '\0';
    	hints->hints[i] = str;
        }
    
        hints->timer = XtAppAddTimeOut(XtWidgetToApplicationContext(topwindow),
    				   hints->interval, HintsTimer,
    				   (XtPointer)hints);
    }