Home | History | Annotate | Line # | Download | only in dist
      1 /* $XConsortium: util.c,v 1.16 92/08/12 16:46:22 converse Exp $ */
      2 
      3 /*
      4  *			  COPYRIGHT 1987
      5  *		   DIGITAL EQUIPMENT CORPORATION
      6  *		       MAYNARD, MASSACHUSETTS
      7  *			ALL RIGHTS RESERVED.
      8  *
      9  * THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND
     10  * SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION.
     11  * DIGITAL MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR
     12  * ANY PURPOSE.  IT IS SUPPLIED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY.
     13  *
     14  * IF THE SOFTWARE IS MODIFIED IN A MANNER CREATING DERIVATIVE COPYRIGHT RIGHTS,
     15  * APPROPRIATE LEGENDS MAY BE PLACED ON THE DERIVATIVE WORK IN ADDITION TO THAT
     16  * SET FORTH ABOVE.
     17  *
     18  *
     19  * Permission to use, copy, modify, and distribute this software and its
     20  * documentation for any purpose and without fee is hereby granted, provided
     21  * that the above copyright notice appear in all copies and that both that
     22  * copyright notice and this permission notice appear in supporting
     23  * documentation, and that the name of Digital Equipment Corporation not be
     24  * used in advertising or publicity pertaining to distribution of the software
     25  * without specific, written prior permission.
     26  */
     27 /* $XFree86: xc/programs/xedit/util.c,v 1.26 2003/05/07 20:54:43 herrb Exp $ */
     28 
     29 #include <stdio.h>
     30 #include <stdarg.h>
     31 
     32 #include <libgen.h>		/* POSIX basename() */
     33 #include <stdlib.h>		/* for realpath() */
     34 #include <errno.h>		/* for ENOENT */
     35 #include "xedit.h"
     36 
     37 #include <X11/Xfuncs.h>
     38 #include <X11/Xos.h>		/* for types.h */
     39 
     40 #include <sys/stat.h>
     41 #include <X11/Xmu/CharSet.h>
     42 #include <X11/Xaw/SmeBSB.h>
     43 #include <X11/Xaw/SimpleMenu.h>
     44 
     45 /*
     46  * Prototypes
     47  */
     48 static void SwitchSourceCallback(Widget, XtPointer, XtPointer);
     49 static int WindowIndex(Widget);
     50 static void ChangeTextWindow(Widget);
     51 
     52 /*
     53  * External
     54  */
     55 extern void _XawTextShowPosition(TextWidget);
     56 
     57 /*
     58  * Initialization
     59  */
     60 extern Widget scratch;
     61 extern Widget vpanes[2], labels[3], texts[3], forms[3];
     62 extern XawTextWrapMode wrapmodes[3];
     63 
     64 #ifndef va_copy
     65 # ifdef __va_copy
     66 #  define va_copy __va_copy
     67 # else
     68 #  error "no working va_copy was found"
     69 # endif
     70 #endif
     71 
     72 /*
     73  * Implementation
     74  */
     75 void
     76 XeditPrintf(const char *format, ...)
     77 {
     78     static struct {
     79 	XawTextPosition	last;
     80 	int		size;
     81 	int		length;
     82 	int		repeat;
     83 	char		*buffer;
     84     } info;
     85 
     86     size_t		size;
     87     va_list		va;
     88     XawTextBlock	text;
     89     XawTextPosition	left, right;
     90     char		buffer[BUFSIZ];
     91     char		*string, rbuffer[32];
     92 
     93     va_start(va, format);
     94     size = vsnprintf(buffer, sizeof(buffer), format, va);
     95     va_end(va);
     96 
     97     /* Should never happen... */
     98     if (size >= sizeof(buffer)) {
     99 	strcpy(buffer + sizeof(buffer) - 5, "...\n");
    100 	size = sizeof(buffer) - 1;
    101     }
    102     else if (size) {
    103 	left = right = XawTextSourceScan(XawTextGetSource(messwidget),
    104 					 0, XawstAll, XawsdRight, 1, True);
    105 
    106 	if (left == info.last &&
    107 	    info.buffer &&
    108 	    strcmp(buffer, info.buffer) == 0) {
    109 	    string = rbuffer;
    110 	    if (info.repeat == 1)
    111 		left -= info.buffer[strlen(info.buffer) - 1] == '\n';
    112 	    else
    113 		left -= info.length;
    114 	    size = info.length = XmuSnprintf(rbuffer, sizeof(rbuffer),
    115 					     " [%d times]\n", ++info.repeat);
    116 	}
    117 	else {
    118 	    string = buffer;
    119 	    if (size >= info.size)
    120 		info.buffer = XtMalloc(size + 1);
    121 	    strcpy(info.buffer, buffer);
    122 	    info.repeat = 1;
    123 	}
    124 
    125 	text.length = size;
    126 	text.ptr = string;
    127 	text.firstPos = 0;
    128 	text.format = FMT8BIT;
    129 
    130 	XawTextReplace(messwidget, left, right, &text);
    131 
    132 	info.last = left + text.length;
    133 	XawTextSetInsertionPoint(messwidget, info.last);
    134     }
    135 }
    136 
    137 Widget
    138 MakeCommandButton(Widget box, char *name, XtCallbackProc function)
    139 {
    140   Widget w = XtCreateManagedWidget(name, commandWidgetClass, box, NULL, ZERO);
    141   if (function != NULL)
    142     XtAddCallback(w, XtNcallback, function, (caddr_t) NULL);
    143   else
    144     XtVaSetValues(w, XtNsensitive, False, NULL);
    145   return w;
    146 }
    147 
    148 Widget
    149 MakeStringBox(Widget parent, String name, String string)
    150 {
    151   Arg args[5];
    152   Cardinal numargs = 0;
    153   Widget StringW;
    154 
    155   XtSetArg(args[numargs], XtNeditType, XawtextEdit); numargs++;
    156   XtSetArg(args[numargs], XtNstring, string); numargs++;
    157 
    158   StringW = XtCreateManagedWidget(name, asciiTextWidgetClass,
    159 				  parent, args, numargs);
    160   return(StringW);
    161 }
    162 
    163 /*	Function Name: GetString
    164  *	Description: retrieves the string from a asciiText widget.
    165  *	Arguments: w - the ascii text widget.
    166  *	Returns: the filename.
    167  */
    168 
    169 String
    170 GetString(Widget w)
    171 {
    172   String str;
    173   Arg arglist[1];
    174 
    175   XtSetArg(arglist[0], XtNstring, &str);
    176   XtGetValues( w, arglist, ONE);
    177   return(str);
    178 }
    179 
    180 /*	Function Name: MaybeCreateFile
    181  *	Description: Checks to see if file exists, and if not, creates it.
    182  *	Arguments: file - name of file to check.
    183  *	Returns: permissions status
    184  */
    185 
    186 FileAccess
    187 MaybeCreateFile(const char *file)
    188 {
    189     Boolean exists;
    190     int fd;
    191 
    192     if (access(file, F_OK) != 0) {
    193 	fd = creat(file, 0666);
    194 	if (fd != -1)
    195 	    close(fd);
    196     }
    197 
    198     return(CheckFilePermissions(file, &exists));
    199 }
    200 
    201 
    202 FileAccess
    203 CheckFilePermissions(const char *file, Boolean *exists)
    204 {
    205     char temp[BUFSIZ], *ptr;
    206 
    207     if (access(file, F_OK) == 0) {
    208 	*exists = TRUE;
    209 
    210 	if (access(file, R_OK) != 0)
    211 	    return(NO_READ);
    212 
    213 	if (access(file, R_OK | W_OK) == 0)
    214 	    return(WRITE_OK);
    215 	return(READ_OK);
    216     }
    217 
    218     *exists = FALSE;
    219 
    220     strncpy(temp, file, sizeof(temp) - 1);
    221     temp[sizeof(temp) - 1] = '\0';
    222     if ( (ptr = rindex(temp, '/')) == NULL)
    223 	strcpy(temp, ".");
    224     else
    225 	*ptr = '\0';
    226 
    227     if (access(temp, R_OK | W_OK | X_OK) == 0)
    228 	return(WRITE_OK);
    229     return(NO_READ);
    230 }
    231 
    232 xedit_flist_item *
    233 AddTextSource(Widget source, const char *name, const char *filename, int flags,
    234 	      FileAccess file_access)
    235 {
    236     xedit_flist_item *item;
    237     char *wid_name;
    238 
    239     item = (xedit_flist_item*)XtMalloc(sizeof(xedit_flist_item));
    240     item->source = source;
    241     item->name = XtNewString(name);
    242     item->filename = XtNewString(filename);
    243     item->flags = flags;
    244     item->file_access = file_access;
    245     item->display_position = item->insert_position = 0;
    246     item->mode = 0;
    247     item->mtime = 0;
    248     item->properties = NULL;
    249     item->xldata = NULL;
    250     /* Try to load associated tags file */
    251     SearchTagsFile(item);
    252 
    253     flist.itens = (xedit_flist_item**)
    254 	XtRealloc((char*)flist.itens, sizeof(xedit_flist_item*)
    255 		  * (flist.num_itens + 1));
    256 
    257     flist.itens[flist.num_itens++] = item;
    258 
    259     if (!flist.popup) {
    260 	flist.popup = XtCreatePopupShell("fileMenu", simpleMenuWidgetClass,
    261 					 topwindow, NULL, 0);
    262 	/* XXX hack: this don't allow setting the geometry of the popup widget
    263 	 * as it will override any settings when a menu entry is inserted
    264 	 * or deleted, but saves us the trouble generated by a resource
    265 	 * setting like: '*geometry: <width>x<height>'
    266 	 */
    267 	XtRealizeWidget(flist.popup);
    268     }
    269     if ((wid_name = strrchr(item->name, '/')) == NULL)
    270 	wid_name = item->name;
    271     else
    272 	++wid_name;
    273     item->sme = XtVaCreateManagedWidget(wid_name, smeBSBObjectClass,
    274 					flist.popup, XtNlabel, item->filename,
    275 					NULL, NULL);
    276     XtAddCallback(item->sme, XtNcallback,
    277 		  SwitchSourceCallback, (XtPointer)item);
    278 
    279     SetTextProperties(item);
    280 
    281     return (item);
    282 }
    283 
    284 Bool
    285 KillTextSource(xedit_flist_item *item)
    286 {
    287     xedit_flist_item *nitem = NULL;
    288     unsigned idx, i;
    289     Arg targs[3];
    290     Cardinal tnum_args;
    291     Arg largs[2];
    292     Cardinal lnum_args;
    293     char label_buf[BUFSIZ];
    294 
    295     for (idx = 0; idx < flist.num_itens; idx++)
    296 	if (flist.itens[idx] == item) {
    297 	    if (idx + 1 < flist.num_itens)
    298 		nitem = flist.itens[idx + 1];
    299 	    else if (idx >= 1)
    300 		nitem = flist.itens[idx - 1];
    301 	    break;
    302 	}
    303 
    304     if (idx >= flist.num_itens)
    305 	return (False);
    306 
    307     flist.current = nitem;
    308     if (item == flist.other)
    309 	flist.other = NULL;
    310 
    311     if (nitem->file_access == READ_OK)
    312 	XmuSnprintf(label_buf, sizeof(label_buf), "%s       READ ONLY",
    313 		    nitem->name);
    314     else if (nitem->file_access == WRITE_OK)
    315 	XmuSnprintf(label_buf, sizeof(label_buf), "%s       Read - Write",
    316 		    nitem->name);
    317     lnum_args = 0;
    318     XtSetArg(largs[lnum_args], XtNlabel, label_buf);		++lnum_args;
    319     if (nitem->flags & CHANGED_BIT)
    320 	XtSetArg(largs[lnum_args], XtNleftBitmap, flist.pixmap);
    321     else
    322 	XtSetArg(largs[lnum_args], XtNleftBitmap, None);
    323     ++lnum_args;
    324 
    325     tnum_args = 0;
    326     XtSetArg(targs[tnum_args], XtNtextSource,
    327 	     nitem->source);				++tnum_args;
    328     XtSetArg(targs[tnum_args], XtNdisplayPosition,
    329 	     nitem->display_position);			++tnum_args;
    330     XtSetArg(targs[tnum_args], XtNinsertPosition,
    331 	     nitem->insert_position);			++tnum_args;
    332     for (i = 0; i < 3; i++)
    333 	if (XawTextGetSource(texts[i]) == item->source) {
    334 	    XtSetValues(labels[i], largs, lnum_args);
    335 	    XawTextDisableRedisplay(texts[i]);
    336 	    XtSetValues(texts[i], targs, tnum_args);
    337 
    338 	    UpdateTextProperties(0);
    339 
    340 	    _XawTextShowPosition((TextWidget)texts[i]);
    341 	    XawTextEnableRedisplay(texts[i]);
    342 	    if (texts[i] == textwindow) {
    343 		Arg args[1];
    344 
    345 		if (nitem->source != scratch)
    346 		    XtSetArg(args[0], XtNstring, nitem->name);
    347 		else
    348 		    XtSetArg(args[0], XtNstring, NULL);
    349 		XtSetValues(filenamewindow, args, 1);
    350 	    }
    351 	}
    352 
    353     UnsetTextProperties(item);
    354     XtFree(item->name);
    355     XtFree(item->filename);
    356     XtDestroyWidget(item->sme);
    357     XtDestroyWidget(item->source);
    358     XtFree((char*)item);
    359 
    360     if (idx < flist.num_itens - 1)
    361 	memmove(&flist.itens[idx], &flist.itens[idx + 1],
    362 		(flist.num_itens - idx) * sizeof(xedit_flist_item*));
    363 
    364     --flist.num_itens;
    365 
    366     return (True);
    367 }
    368 
    369 xedit_flist_item *
    370 FindTextSource(Widget source, const char *filename)
    371 {
    372     unsigned i;
    373 
    374     if (source) {
    375 	for (i = 0; i < flist.num_itens; i++)
    376 	    if (flist.itens[i]->source == source)
    377 		return (flist.itens[i]);
    378     }
    379     else if (filename) {
    380 	for (i = 0; i < flist.num_itens; i++)
    381 	    if (strcmp(flist.itens[i]->filename, filename) == 0)
    382 		return (flist.itens[i]);
    383     }
    384 
    385     return (NULL);
    386 }
    387 
    388 void
    389 SwitchTextSource(xedit_flist_item *item)
    390 {
    391     Arg args[4];
    392     Cardinal num_args;
    393     char label_buf[BUFSIZ];
    394     xedit_flist_item *old_item =
    395 	FindTextSource(XawTextGetSource(textwindow), NULL);
    396     int i;
    397 
    398     if (old_item != item)
    399 	flist.other = old_item;
    400     flist.current = item;
    401 
    402     XawTextDisableRedisplay(textwindow);
    403     if (item->file_access == READ_OK)
    404 	XmuSnprintf(label_buf, sizeof(label_buf), "%s       READ ONLY",
    405 		    item->name);
    406     else if (item->file_access == WRITE_OK)
    407 	XmuSnprintf(label_buf, sizeof(label_buf), "%s       Read - Write",
    408 		    item->name);
    409     num_args = 0;
    410     XtSetArg(args[num_args], XtNlabel, label_buf);		++num_args;
    411     if (item->flags & CHANGED_BIT)
    412 	XtSetArg(args[num_args], XtNleftBitmap, flist.pixmap);
    413     else
    414 	XtSetArg(args[num_args], XtNleftBitmap, None);
    415     ++num_args;
    416     XtSetValues(labelwindow, args, num_args);
    417 
    418     for (i = 0; i < 3; i++)
    419 	if (XawTextGetSource(texts[i]) == item->source
    420 	    && XtIsManaged(texts[i]))
    421 	    break;
    422 
    423     if (i < 3) {
    424 	num_args = 0;
    425 	XtSetArg(args[num_args], XtNdisplayPosition,
    426 	     &(item->display_position));			++num_args;
    427 	XtSetArg(args[num_args], XtNinsertPosition,
    428 	     &(item->insert_position));				++num_args;
    429 	XtGetValues(texts[i], args, num_args);
    430     }
    431     if (old_item != item) {
    432 	int count, idx = 0;
    433 
    434 	num_args = 0;
    435 	XtSetArg(args[num_args], XtNdisplayPosition,
    436 	     &(old_item->display_position));			++num_args;
    437 	XtSetArg(args[num_args], XtNinsertPosition,
    438 	     &(old_item->insert_position));			++num_args;
    439 	XtGetValues(textwindow, args, num_args);
    440 
    441 	for (count = 0, i = 0; i < 3; i++)
    442 	    if (XawTextGetSource(texts[i]) == old_item->source
    443 		&& XtIsManaged(texts[i])) {
    444 		if (++count > 1)
    445 		    break;
    446 		idx = i;
    447 	    }
    448 
    449 	if (count == 1) {
    450 	    num_args = 0;
    451 	    XtSetArg(args[num_args], XtNdisplayPosition,
    452 		     &(old_item->display_position));		++num_args;
    453 		XtSetArg(args[num_args], XtNinsertPosition,
    454 		     &(old_item->insert_position));		++num_args;
    455 	    XtGetValues(texts[idx], args, num_args);
    456 	}
    457     }
    458 
    459     num_args = 0;
    460     XtSetArg(args[num_args], XtNtextSource, item->source);	++num_args;
    461     XtSetArg(args[num_args], XtNdisplayPosition, item->display_position);
    462     ++num_args;
    463     XtSetArg(args[num_args], XtNinsertPosition, item->insert_position);
    464     ++num_args;
    465     if (item->flags & WRAP_BIT)
    466 	XtSetArg(args[num_args], XtNwrap, item->wrap);
    467     else
    468 	XtSetArg(args[num_args], XtNwrap, wrapmodes[WindowIndex(textwindow)]);
    469     ++num_args;
    470     XtSetValues(textwindow, args, num_args);
    471 
    472     UpdateTextProperties(0);
    473 
    474     _XawTextShowPosition((TextWidget)textwindow);
    475     XawTextEnableRedisplay(textwindow);
    476 
    477     num_args = 0;
    478     if (item->source != scratch) {
    479 	XtSetArg(args[num_args], XtNstring, item->name);	++num_args;
    480     }
    481     else {
    482 	XtSetArg(args[num_args], XtNstring, NULL);		++num_args;
    483     }
    484     XtSetValues(filenamewindow, args, num_args);
    485     /* XXX This probably should be done by the TextWidget, i.e. notice
    486      * if the cursor became inivisible due to an horizontal scroll */
    487     _XawTextShowPosition((TextWidget)filenamewindow);
    488 }
    489 
    490 char *
    491 ResolveName(char *filename)
    492 {
    493     static char *name;
    494     char	*result, *tmp = name;
    495 
    496     if (filename == NULL)
    497 	filename = GetString(filenamewindow);
    498 
    499     /* Ensure not passing the same pointer again to realpath */
    500     name = XtMalloc(BUFSIZ);
    501     XtFree(tmp);
    502     result = realpath(filename, name);
    503 
    504     if (result == NULL && errno == ENOENT) {
    505 	int	length;
    506 	char	*dir, *file, *fname;
    507 
    508 	length = strlen(filename);
    509 	tmp = dir = XtMalloc(length + 1);
    510 	strcpy(dir, filename);
    511 	fname = strdup(filename);
    512 
    513 	file = basename(fname);
    514 	dir = dirname(tmp);
    515 
    516 	/* Creating a new file? */
    517 	if (dir && file && strcmp(dir, file) &&
    518 	    access(dir, F_OK) == 0 &&
    519 	    (result = realpath(dir, name)) == name) {
    520 	    int	length = strlen(result);
    521 
    522 	    XmuSnprintf(result + length, BUFSIZ - length, "%s%s",
    523 			result[length - 1] == '/' ? "" : "/", file);
    524 	}
    525 
    526 	XtFree(tmp);
    527 	free(fname);
    528     }
    529 
    530     return (result);
    531 }
    532 
    533 static void
    534 ChangeTextWindow(Widget w)
    535 {
    536     Arg args[1];
    537 
    538     if (textwindow != w) {
    539 	xedit_flist_item *other, *current;
    540 
    541 	other = FindTextSource(XawTextGetSource(textwindow), NULL);
    542 	current = FindTextSource(XawTextGetSource(w), NULL);
    543 	if (other != current)
    544 	    flist.other = other;
    545 	if (current)
    546 	    flist.current = current;
    547 	XtSetArg(args[0], XtNdisplayCaret, False);
    548 	XtSetValues(textwindow, args, 1);
    549 	XtSetArg(args[0], XtNdisplayCaret, True);
    550 	XtSetValues(w, args, 1);
    551 	XawTextUnsetSelection(textwindow);
    552 	textwindow = w;
    553     }
    554 }
    555 
    556 /*ARGSUSED*/
    557 void
    558 XeditFocus(Widget w, XEvent *event, String *params, Cardinal *num_params)
    559 {
    560     Arg args[1];
    561     xedit_flist_item *item;
    562     int idx = WindowIndex(w);
    563 
    564     XtSetKeyboardFocus(topwindow, w);
    565 
    566     ChangeTextWindow(w);
    567 
    568     labelwindow = labels[idx];
    569     item = FindTextSource(XawTextGetSource(textwindow), NULL);
    570 
    571     if (item->source != scratch)
    572 	XtSetArg(args[0], XtNstring, item->name);
    573     else
    574 	XtSetArg(args[0], XtNstring, NULL);
    575 
    576     XtSetValues(filenamewindow, args, 1);
    577 
    578     line_edit = False;
    579 }
    580 
    581 void
    582 PopupMenu(Widget w, XEvent *event, String *params, Cardinal *num_params)
    583 {
    584     Cardinal n_params = num_params ? *num_params : 0;
    585 
    586     if (*num_params && XmuCompareISOLatin1(*params, "editMenu") == 0)
    587 	SetEditMenu();
    588 
    589     XtCallActionProc(w, "XawPositionSimpleMenu", event, params, n_params);
    590     XtCallActionProc(w, "XtMenuPopup", event, params, n_params);
    591 }
    592 
    593 /*ARGSUSED*/
    594 static void
    595 SwitchSourceCallback(Widget entry, XtPointer client_data, XtPointer call_data)
    596 {
    597     SwitchTextSource((xedit_flist_item*)client_data);
    598 }
    599 
    600 static int
    601 WindowIndex(Widget w)
    602 {
    603     int i;
    604 
    605     for (i = 0; i < 3; i++)
    606 	if (texts[i] == w)
    607 	    return (i);
    608 
    609     return (-1);
    610 }
    611 
    612 void
    613 DeleteWindow(Widget w, XEvent *event, String *params, Cardinal *num_params)
    614 {
    615     Widget unmanage[2];
    616     int idx = WindowIndex(w), uidx;
    617     Bool current = False;
    618 
    619     if (*num_params == 1 && (*params[0] == 'd' || *params[0] == 'D')) {
    620 	if (XtIsManaged(XtParent(dirwindow)))
    621 	    SwitchDirWindow(False);
    622 	return;
    623     }
    624 
    625     if (idx < 0 || (!XtIsManaged(texts[1]) && !XtIsManaged(texts[2]))) {
    626 	Feep();
    627 	return;
    628     }
    629 
    630     if (num_params && *num_params == 1 &&
    631 	(*params[0] == 'o' || *params[0] == 'O'))
    632 	current = True;
    633 
    634     uidx = XtIsManaged(texts[1]) ? 1 : 2;
    635 
    636     unmanage[0] = forms[uidx];
    637     unmanage[1] = texts[uidx];
    638     XtUnmanageChildren(unmanage, 2);
    639 
    640     if (!XtIsManaged(texts[2]))
    641 	XtUnmanageChild(vpanes[1]);
    642 
    643     if ((!current && idx == 0) || (current && idx != 0)) {
    644 	Arg args[4];
    645 	Cardinal num_args;
    646 	String label_str;
    647 	Pixmap label_pix;
    648 	XawTextPosition d_pos, i_pos;
    649 	Widget source;
    650 	xedit_flist_item *item;
    651 
    652 	num_args = 0;
    653 	XtSetArg(args[num_args], XtNlabel, &label_str);		++num_args;
    654 	XtSetArg(args[num_args], XtNleftBitmap, &label_pix);	++num_args;
    655 	XtGetValues(labels[current ? idx : uidx], args, num_args);
    656 
    657 	num_args = 0;
    658 	XtSetArg(args[num_args], XtNlabel, label_str);		++num_args;
    659 	XtSetArg(args[num_args], XtNleftBitmap, label_pix);	++num_args;
    660 	XtSetValues(labels[0], args, num_args);
    661 
    662 	num_args = 0;
    663 	XtSetArg(args[num_args], XtNdisplayPosition, &d_pos);	++num_args;
    664 	XtSetArg(args[num_args], XtNinsertPosition, &i_pos);	++num_args;
    665 	XtSetArg(args[num_args], XtNtextSource, &source);	++num_args;
    666 	XtGetValues(texts[current ? idx : uidx], args, num_args);
    667 
    668 	num_args = 0;
    669 	XtSetArg(args[num_args], XtNdisplayPosition, d_pos);	++num_args;
    670 	XtSetArg(args[num_args], XtNinsertPosition, i_pos);	++num_args;
    671 	XtSetArg(args[num_args], XtNtextSource, source);	++num_args;
    672 
    673 	item = FindTextSource(source, NULL);
    674 	if (item && (item->flags & WRAP_BIT))
    675 	    XtSetArg(args[num_args], XtNwrap, item->wrap);
    676 	else
    677 	    XtSetArg(args[num_args], XtNwrap,
    678 		     wrapmodes[WindowIndex(texts[current ? idx : uidx])]);
    679 	XtSetValues(texts[0], args, num_args);
    680 
    681 	UpdateTextProperties(0);
    682     }
    683 
    684     labelwindow = labels[0];
    685     XeditFocus(texts[0], NULL, NULL, NULL);
    686 }
    687 
    688 void
    689 SwitchSource(Widget w, XEvent *event, String *params, Cardinal *num_params)
    690 {
    691     int idx = WindowIndex(w);
    692     Widget source;
    693     int i;
    694 
    695     if (idx < 0 || textwindow != texts[idx]) {
    696 	Feep();
    697 	return;
    698     }
    699 
    700     source = XawTextGetSource(textwindow);
    701 
    702     for (i = 0; i < flist.num_itens; i++)
    703 	if (flist.itens[i]->source == source) {
    704 	    if (i > 0 && i == flist.num_itens - 1)
    705 		i = 0;
    706 	    else if (i < flist.num_itens - 1)
    707 		++i;
    708 	    else {
    709 		Feep();
    710 		return;
    711 	    }
    712 	    break;
    713 	}
    714 
    715     if (i >= flist.num_itens) {
    716 	Feep();
    717 	return;
    718     }
    719 
    720     SwitchTextSource(flist.itens[i]);
    721 }
    722 
    723 void
    724 OtherWindow(Widget w, XEvent *event, String *params, Cardinal *num_params)
    725 {
    726     int oidx, idx = WindowIndex(w);
    727 
    728     if (idx < 0 || (!XtIsManaged(texts[1]) && !XtIsManaged(texts[2]))) {
    729 	Feep();
    730 	return;
    731     }
    732 
    733     if (idx == 0)
    734 	oidx = XtIsManaged(texts[1]) ? 1 : 2;
    735     else
    736 	oidx = 0;
    737 
    738     XeditFocus(texts[oidx], event, params, num_params);
    739 }
    740 
    741 void
    742 SplitWindow(Widget w, XEvent *event, String *params, Cardinal *num_params)
    743 {
    744     Arg args[6];
    745     Cardinal num_args;
    746     Widget nlabel, ntext, source, sink, manage[2];
    747     Dimension width, height, bw;
    748     XawTextPosition i_pos, d_pos;
    749     String label_str;
    750     Pixmap label_pix;
    751     int idx = WindowIndex(w), dimension;
    752     Bool vert = True;
    753     xedit_flist_item *item;
    754 
    755     if (num_params && *num_params == 1
    756 	&& (*params[0] == 'h' || *params[0] == 'H'))
    757 	vert = False;
    758 
    759     if (idx < 0
    760 	|| (vert && XtIsManaged(texts[1]))
    761 	|| (!vert && XtIsManaged(vpanes[1]))) {
    762 	Feep();
    763 	return;
    764     }
    765 
    766     if (vert) {
    767 	nlabel = labels[1];
    768 	ntext = texts[1];
    769     }
    770     else {
    771 	nlabel = labels[2];
    772 	ntext = texts[2];
    773     }
    774     ChangeTextWindow(texts[idx]);
    775     labelwindow = labels[idx];
    776 
    777     num_args = 0;
    778     XtSetArg(args[num_args], XtNinsertPosition, &i_pos);	++num_args;
    779     XtSetArg(args[num_args], XtNdisplayPosition, &d_pos);	++num_args;
    780     XtSetArg(args[num_args], XtNtextSource, &source);		++num_args;
    781     XtSetArg(args[num_args], XtNtextSink, &sink);		++num_args;
    782     XtSetArg(args[num_args], XtNwidth, &width);			++num_args;
    783     XtSetArg(args[num_args], XtNheight, &height);		++num_args;
    784     XtGetValues(w, args, num_args);
    785 
    786     num_args = 0;
    787     XtSetArg(args[num_args], XtNinternalBorderWidth, &bw);	++num_args;
    788     XtGetValues(XtParent(w), args, num_args);
    789 
    790     if (vert) {
    791 	dimension = (int)height - (((int)bw) << 1);
    792 	num_args = 0;
    793 	XtSetArg(args[num_args], XtNheight, &height);		++num_args;
    794 	XtGetValues(labelwindow, args, num_args);
    795 	dimension -= (int)height;
    796     }
    797     else
    798 	dimension = (int)width - (int)bw;
    799 
    800     dimension >>= 1;
    801 
    802     if (dimension <= 0 || dimension < XawTextSinkMaxHeight(sink, 3)) {
    803 	Feep();
    804 	return;
    805     }
    806 
    807     num_args = 0;
    808     XtSetArg(args[num_args], XtNlabel, &label_str);		++num_args;
    809     XtSetArg(args[num_args], XtNleftBitmap, &label_pix);	++num_args;
    810     XtGetValues(labelwindow, args, num_args);
    811 
    812     if (vert) {
    813 	if (XtIsManaged(texts[2])) {
    814 	    manage[0] = forms[2];
    815 	    manage[1] = texts[2];
    816 	    XtUnmanageChildren(manage, 2);
    817 	    XtUnmanageChild(vpanes[1]);
    818 	}
    819     }
    820     else {
    821 	if (XtIsManaged(texts[1])) {
    822 	    manage[0] = forms[1];
    823 	    manage[1] = texts[1];
    824 	    XtUnmanageChildren(manage, 2);
    825 	}
    826     }
    827 
    828     XawTextDisableRedisplay(texts[0]);
    829     XawTextDisableRedisplay(ntext);
    830     if (textwindow == texts[1] || textwindow == texts[2]) {
    831 	num_args = 0;
    832 	XtSetArg(args[num_args], XtNdisplayPosition, d_pos);	++num_args;
    833 	XtSetArg(args[num_args], XtNinsertPosition, i_pos);	++num_args;
    834 	XtSetArg(args[num_args], XtNtextSource, source);	++num_args;
    835 	ChangeTextWindow(texts[0]);
    836 	XtSetValues(textwindow, args, num_args);
    837 	XtSetKeyboardFocus(topwindow, textwindow);
    838 
    839 	num_args = 0;
    840 	XtSetArg(args[num_args], XtNlabel, label_str);		++num_args;
    841 	XtSetArg(args[num_args], XtNleftBitmap, label_pix);	++num_args;
    842 	XtSetValues(labelwindow = labels[0], args, num_args);
    843     }
    844 
    845     num_args = 0;
    846     XtSetArg(args[num_args], XtNlabel, label_str);		++num_args;
    847     XtSetArg(args[num_args], XtNleftBitmap, label_pix);		++num_args;
    848     XtSetValues(nlabel, args, num_args);
    849 
    850     num_args = 0;
    851     XtSetArg(args[num_args], XtNmin, dimension);		++num_args;
    852     XtSetArg(args[num_args], XtNmax, dimension);		++num_args;
    853     if (!vert)
    854 	XtSetValues(vpanes[1], args, num_args);
    855     else
    856 	XtSetValues(ntext, args, num_args);
    857 
    858     manage[0] = XtParent(nlabel);
    859     manage[1] = ntext;
    860     XtManageChildren(manage, 2);
    861     if (!vert)
    862 	XtManageChild(vpanes[1]);
    863 
    864     num_args = 0;
    865     XtSetArg(args[num_args], XtNmin, 1);			++num_args;
    866     XtSetArg(args[num_args], XtNmax, 65535);			++num_args;
    867     if (!vert) {
    868 	XtSetValues(vpanes[1], args, num_args);
    869 	num_args = 0;
    870     }
    871     XtSetArg(args[num_args], XtNtextSource, source);		++num_args;
    872     XtSetArg(args[num_args], XtNdisplayPosition, d_pos);	++num_args;
    873     XtSetArg(args[num_args], XtNinsertPosition, i_pos);		++num_args;
    874     item = FindTextSource(source, NULL);
    875     if (item && (item->flags & WRAP_BIT))
    876 	XtSetArg(args[num_args], XtNwrap, item->wrap);
    877     else
    878 	XtSetArg(args[num_args], XtNwrap, wrapmodes[WindowIndex(ntext)]);
    879     ++num_args;
    880     XtSetValues(ntext, args, num_args);
    881 
    882     UpdateTextProperties(0);
    883 
    884     _XawTextShowPosition((TextWidget)textwindow);
    885     _XawTextShowPosition((TextWidget)ntext);
    886 
    887     XawTextEnableRedisplay(textwindow);
    888     XawTextEnableRedisplay(ntext);
    889 }
    890 
    891 void
    892 SwitchDirWindow(Bool show)
    893 {
    894     static int map;	/* There must be one instance of this
    895 			 * variable per top level window */
    896     Widget manage[2];
    897 
    898     if (!show && XtIsManaged(XtParent(dirwindow))) {
    899 	manage[0] = dirlabel;
    900 	manage[1] = XtParent(dirwindow);
    901 	XtUnmanageChildren(manage, 2);
    902 	XtUnmanageChild(vpanes[1]);
    903 
    904 	XtManageChild(vpanes[0]);
    905 	if (map == 2) {
    906 	    Arg args[2];
    907 	    Dimension width, bw;
    908 
    909 	    XtSetArg(args[0], XtNwidth, &width);
    910 	    XtGetValues(texts[0], args, 1);
    911 	    XtSetArg(args[0], XtNinternalBorderWidth, &bw);
    912 	    XtGetValues(XtParent(texts[0]), args, 1);
    913 	    width = (width - bw) >> 1;
    914 	    XtSetArg(args[0], XtNmin, width);
    915 	    XtSetArg(args[0], XtNmax, width);
    916 	    XtSetValues(vpanes[0], args, 1);
    917 	    manage[0] = forms[2];
    918 	    manage[1] = texts[2];
    919 	    XtManageChildren(manage, 2);
    920 	    XtManageChild(vpanes[1]);
    921 	    XtSetArg(args[0], XtNmin, 1);
    922 	    XtSetArg(args[0], XtNmax, 65535);
    923 	    XtSetValues(vpanes[0], args, 1);
    924 	}
    925     }
    926     else if (show && !XtIsManaged(XtParent(dirwindow))) {
    927 	XtUnmanageChild(vpanes[0]);
    928 	if (XtIsManaged(texts[2])) {
    929 	    manage[0] = forms[2];
    930 	    manage[1] = texts[2];
    931 	    XtUnmanageChildren(manage, 2);
    932 	    map = 2;
    933 	}
    934 	else {
    935 	    map = XtIsManaged(texts[1]);
    936 	    XtManageChild(vpanes[1]);
    937 	}
    938 
    939 	manage[0] = dirlabel;
    940 	manage[1] = XtParent(dirwindow);
    941 	XtManageChildren(manage, 2);
    942     }
    943 }
    944 
    945 /*ARGSUSED*/
    946 void
    947 DirWindow(Widget w, XEvent *event, String *params, Cardinal *num_params)
    948 {
    949     Arg args[1];
    950     char path[BUFSIZ + 1], *dir;
    951 
    952     if (XtIsManaged(XtParent(dirwindow)))
    953 	return;
    954 
    955     if (*num_params == 1) {
    956 	strncpy(path, params[0], sizeof(path) - 2);
    957 	path[sizeof(path) - 2] = '\0';
    958     }
    959     else {
    960 	char *slash;
    961 	xedit_flist_item *item = FindTextSource(XawTextGetSource(textwindow), NULL);
    962 
    963 	if (item == NULL || item->source == scratch
    964 	    || (slash = rindex(item->filename, '/')) == NULL)
    965 	    strcpy(path, "./");
    966 	else {
    967 	    int len = slash - item->filename + 1;
    968 
    969 	    if (len > sizeof(path) - 2)
    970 		len = sizeof(path) - 2;
    971 	    strncpy(path, item->filename, len);
    972 	    path[len] = '\0';
    973 	}
    974     }
    975 
    976     dir = ResolveName(path);
    977     if (dir != NULL) {
    978 	strncpy(path, dir, sizeof(path) - 2);
    979 	path[sizeof(path) - 2] = '\0';
    980 	if (*path && path[strlen(path) - 1] != '/')
    981 	    strcat(path, "/");
    982 
    983 	XtSetArg(args[0], XtNlabel, "");
    984 	XtSetValues(dirlabel, args, 1);
    985 
    986 	SwitchDirWindow(True);
    987 	DirWindowCB(dirwindow, path, NULL);
    988     }
    989     else
    990 	Feep();
    991 }
    992