commands.c revision f14f4646
15dfecf96Smrg/* $XConsortium: commands.c,v 1.33 91/10/21 14:32:18 eswu Exp $ */ 25dfecf96Smrg 35dfecf96Smrg/* 45dfecf96Smrg * COPYRIGHT 1987 55dfecf96Smrg * DIGITAL EQUIPMENT CORPORATION 65dfecf96Smrg * MAYNARD, MASSACHUSETTS 75dfecf96Smrg * ALL RIGHTS RESERVED. 85dfecf96Smrg * 95dfecf96Smrg * THE INFORMATION IN THIS SOFTWARE IS SUBJECT TO CHANGE WITHOUT NOTICE AND 105dfecf96Smrg * SHOULD NOT BE CONSTRUED AS A COMMITMENT BY DIGITAL EQUIPMENT CORPORATION. 115dfecf96Smrg * DIGITAL MAKES NO REPRESENTATIONS ABOUT THE SUITABILITY OF THIS SOFTWARE FOR 125dfecf96Smrg * ANY PURPOSE. IT IS SUPPLIED "AS IS" WITHOUT EXPRESS OR IMPLIED WARRANTY. 135dfecf96Smrg * 145dfecf96Smrg * IF THE SOFTWARE IS MODIFIED IN A MANNER CREATING DERIVATIVE COPYRIGHT RIGHTS, 155dfecf96Smrg * APPROPRIATE LEGENDS MAY BE PLACED ON THE DERIVATIVE WORK IN ADDITION TO THAT 165dfecf96Smrg * SET FORTH ABOVE. 175dfecf96Smrg * 185dfecf96Smrg * 195dfecf96Smrg * Permission to use, copy, modify, and distribute this software and its 205dfecf96Smrg * documentation for any purpose and without fee is hereby granted, provided 215dfecf96Smrg * that the above copyright notice appear in all copies and that both that 225dfecf96Smrg * copyright notice and this permission notice appear in supporting 235dfecf96Smrg * documentation, and that the name of Digital Equipment Corporation not be 245dfecf96Smrg * used in advertising or publicity pertaining to distribution of the software 255dfecf96Smrg * without specific, written prior permission. 265dfecf96Smrg */ 275dfecf96Smrg/* $XFree86: xc/programs/xedit/commands.c,v 1.29tsi Exp $ */ 285dfecf96Smrg 295dfecf96Smrg#include <X11/Xfuncs.h> 305dfecf96Smrg#include <X11/Xos.h> 315dfecf96Smrg#include "xedit.h" 325dfecf96Smrg#ifdef INCLUDE_XPRINT_SUPPORT 335dfecf96Smrg#include "printdialog.h" 345dfecf96Smrg#include "print.h" 355dfecf96Smrg#endif /* INCLUDE_XPRINT_SUPPORT */ 365dfecf96Smrg#ifdef CRAY 375dfecf96Smrg#include <unistd.h> 385dfecf96Smrg#endif 395dfecf96Smrg#include <stdlib.h> 405dfecf96Smrg#include <stdio.h> 415dfecf96Smrg#include <limits.h> 425dfecf96Smrg#include <string.h> 435dfecf96Smrg#include <dirent.h> 445dfecf96Smrg#include <pwd.h> 455dfecf96Smrg#include <sys/stat.h> 465dfecf96Smrg#include <X11/Xmu/SysUtil.h> 475dfecf96Smrg#include <X11/IntrinsicP.h> 485dfecf96Smrg#include <X11/Xaw/TextSrcP.h> 495dfecf96Smrg 505dfecf96Smrg/* Turn a NULL pointer string into an empty string */ 515dfecf96Smrg#define NULLSTR(x) (((x)!=NULL)?(x):("")) 525dfecf96Smrg 535dfecf96Smrg#define Error(x) { printf x ; exit(EXIT_FAILURE); } 545dfecf96Smrg#define Assertion(expr, msg) { if (!(expr)) { Error msg } } 555dfecf96Smrg#define Log(x) { if (True) printf x; } 565dfecf96Smrg 575dfecf96Smrg#ifdef INCLUDE_XPRINT_SUPPORT 585dfecf96Smrgstatic Widget printdialog_shell = NULL; 595dfecf96Smrgstatic Widget printdialog = NULL; 605dfecf96Smrgstatic char printJobNameBuffer[PATH_MAX+256]; 615dfecf96Smrg#endif /* INCLUDE_XPRINT_SUPPORT */ 625dfecf96Smrg 635dfecf96Smrgvoid ResetSourceChanged(xedit_flist_item*); 645dfecf96Smrgstatic void ResetDC(Widget, XtPointer, XtPointer); 655dfecf96Smrg 665dfecf96Smrgstatic void AddDoubleClickCallback(Widget, Bool); 675dfecf96Smrgstatic Bool ReallyDoLoad(char*, char*); 685dfecf96Smrgstatic char *makeBackupName(String, String, unsigned); 695dfecf96Smrg 70f14f4646Smrg/* 71f14f4646Smrg * External 72f14f4646Smrg */ 73f14f4646Smrgextern void _XawTextShowPosition(TextWidget); 74f14f4646Smrg 755dfecf96Smrgextern Widget scratch, texts[3], labels[3]; 765dfecf96Smrg 77f14f4646Smrg#define DC_UNSAVED (1 << 0) 78f14f4646Smrg#define DC_LOADED (1 << 1) 79f14f4646Smrg#define DC_CLOBBER (1 << 2) 80f14f4646Smrg#define DC_KILL (1 << 3) 81f14f4646Smrg#define DC_SAVE (1 << 4) 82f14f4646Smrg#define DC_NEWER (1 << 5) 835dfecf96Smrgstatic int dc_state; 845dfecf96Smrg 855dfecf96Smrgstatic void 865dfecf96SmrgAddDoubleClickCallback(Widget w, Bool state) 875dfecf96Smrg{ 88f14f4646Smrg if (state) 89f14f4646Smrg XtAddCallback(w, XtNcallback, ResetDC, NULL); 90f14f4646Smrg else 91f14f4646Smrg XtRemoveCallback(w, XtNcallback, ResetDC, NULL); 925dfecf96Smrg} 935dfecf96Smrg 945dfecf96Smrg/* Function Name: ResetDC 955dfecf96Smrg * Description: Resets the double click flag. 965dfecf96Smrg * Arguments: w - the text widget. 975dfecf96Smrg * junk, garbage - *** NOT USED *** 985dfecf96Smrg * Returns: none. 995dfecf96Smrg */ 1005dfecf96Smrg 1015dfecf96Smrg/* ARGSUSED */ 1025dfecf96Smrgstatic void 1035dfecf96SmrgResetDC(Widget w, XtPointer junk, XtPointer garbage) 1045dfecf96Smrg{ 105f14f4646Smrg AddDoubleClickCallback(w, FALSE); 1065dfecf96Smrg} 1075dfecf96Smrg 1085dfecf96Smrg/*ARGSUSED*/ 1095dfecf96Smrgvoid 1105dfecf96SmrgQuitAction(Widget w, XEvent *event, String *params, Cardinal *num_params) 1115dfecf96Smrg{ 1125dfecf96Smrg DoQuit(w, NULL, NULL); 1135dfecf96Smrg} 1145dfecf96Smrg 1155dfecf96Smrg/*ARGSUSED*/ 1165dfecf96Smrgvoid 1175dfecf96SmrgDoQuit(Widget w, XtPointer client_data, XtPointer call_data) 1185dfecf96Smrg{ 1195dfecf96Smrg unsigned i; 1205dfecf96Smrg Bool source_changed = False; 1215dfecf96Smrg 122f14f4646Smrg if (!(dc_state & DC_UNSAVED)) { 1235dfecf96Smrg for (i = 0; i < flist.num_itens; i++) 1245dfecf96Smrg if (flist.itens[i]->flags & CHANGED_BIT) { 1255dfecf96Smrg source_changed = True; 1265dfecf96Smrg break; 1275dfecf96Smrg } 1285dfecf96Smrg } 129f14f4646Smrg if (!source_changed) { 1305dfecf96Smrg#ifndef __UNIXOS2__ 1315dfecf96Smrg XeditLispCleanUp(); 1325dfecf96Smrg#endif 1335dfecf96Smrg exit(0); 1345dfecf96Smrg } 1355dfecf96Smrg 1365dfecf96Smrg XeditPrintf("Unsaved changes. Save them, or Quit again.\n"); 1375dfecf96Smrg Feep(); 138f14f4646Smrg dc_state |= DC_UNSAVED; 1395dfecf96Smrg AddDoubleClickCallback(XawTextGetSource(textwindow), True); 1405dfecf96Smrg} 1415dfecf96Smrg 1425dfecf96Smrgstatic char * 1435dfecf96SmrgmakeBackupName(String buf, String filename, unsigned len) 1445dfecf96Smrg{ 1455dfecf96Smrg if (app_resources.backupNamePrefix 1465dfecf96Smrg && strlen(app_resources.backupNamePrefix)) { 1475dfecf96Smrg if (strchr(app_resources.backupNamePrefix, '/')) 1485dfecf96Smrg XmuSnprintf(buf, len, "%s%s%s", app_resources.backupNamePrefix, 1495dfecf96Smrg filename, app_resources.backupNameSuffix); 1505dfecf96Smrg else { 1515dfecf96Smrg char fname[BUFSIZ]; 1525dfecf96Smrg char *name, ch; 1535dfecf96Smrg 1545dfecf96Smrg strncpy(fname, filename, sizeof(fname) - 1); 1555dfecf96Smrg fname[sizeof(fname) - 1] = '\0'; 1565dfecf96Smrg if ((name = strrchr(fname, '/')) != NULL) 1575dfecf96Smrg ++name; 1585dfecf96Smrg else 1595dfecf96Smrg name = filename; 1605dfecf96Smrg ch = *name; 1615dfecf96Smrg *name = '\0'; 1625dfecf96Smrg ++name; 1635dfecf96Smrg XmuSnprintf(buf, len, "%s%s%c%s%s", 1645dfecf96Smrg fname, app_resources.backupNamePrefix, ch, name, 1655dfecf96Smrg app_resources.backupNameSuffix); 1665dfecf96Smrg } 1675dfecf96Smrg } 1685dfecf96Smrg else 1695dfecf96Smrg XmuSnprintf(buf, len, "%s%s", 1705dfecf96Smrg filename, app_resources.backupNameSuffix); 1715dfecf96Smrg 1725dfecf96Smrg return (strcmp(filename, buf) ? buf : NULL); 1735dfecf96Smrg} 1745dfecf96Smrg 1755dfecf96Smrg#if defined(USG) && !defined(CRAY) 1765dfecf96Smrgint rename (from, to) 1775dfecf96Smrg char *from, *to; 1785dfecf96Smrg{ 1795dfecf96Smrg (void) unlink (to); 1805dfecf96Smrg if (link (from, to) == 0) { 1815dfecf96Smrg unlink (from); 1825dfecf96Smrg return 0; 1835dfecf96Smrg } else { 1845dfecf96Smrg return -1; 1855dfecf96Smrg } 1865dfecf96Smrg} 1875dfecf96Smrg#endif 1885dfecf96Smrg 1895dfecf96Smrg/*ARGSUSED*/ 1905dfecf96Smrgvoid 1915dfecf96SmrgSaveFile(Widget w, XEvent *event, String *params, Cardinal *num_params) 1925dfecf96Smrg{ 193f14f4646Smrg if (line_edit) { 194f14f4646Smrg /* Don't try to save buffer with regex string. 195f14f4646Smrg * Call CancelFindFile() to leave line_edit mode. 196f14f4646Smrg */ 197f14f4646Smrg XeditPrintf("Save: Leaving line edit mode -- nothing saved.\n"); 198f14f4646Smrg CancelFindFile(w, event, params, num_params); 199f14f4646Smrg Feep(); 200f14f4646Smrg } 201f14f4646Smrg else 202f14f4646Smrg DoSave(w, NULL, NULL); 2035dfecf96Smrg} 2045dfecf96Smrg 2055dfecf96Smrg/*ARGSUSED*/ 2065dfecf96Smrgvoid 2075dfecf96SmrgDoSave(Widget w, XtPointer client_data, XtPointer call_data) 2085dfecf96Smrg{ 2095dfecf96Smrg String name = GetString(filenamewindow); 2105dfecf96Smrg String filename = ResolveName(name); 2115dfecf96Smrg FileAccess file_access; 2125dfecf96Smrg xedit_flist_item *item; 2135dfecf96Smrg Boolean exists; 2145dfecf96Smrg Widget source = XawTextGetSource(textwindow); 215f14f4646Smrg char buffer[BUFSIZ]; 216f14f4646Smrg struct stat st; 217f14f4646Smrg static char *nothing_saved = " -- nothing saved.\n"; 2185dfecf96Smrg 2195dfecf96Smrg if (!filename) { 220f14f4646Smrg XmuSnprintf(buffer, sizeof(buffer), "%s%s", 221f14f4646Smrg "Save: Can't resolve pathname", nothing_saved); 222f14f4646Smrg goto error; 2235dfecf96Smrg } 2245dfecf96Smrg else if (*name == '\0') { 225f14f4646Smrg XmuSnprintf(buffer, sizeof(buffer), "%s%s", 226f14f4646Smrg "Save: No filename specified", nothing_saved); 227f14f4646Smrg goto error; 2285dfecf96Smrg } 2295dfecf96Smrg 2305dfecf96Smrg item = FindTextSource(NULL, filename); 2315dfecf96Smrg if (item != NULL && item->source != source) { 232f14f4646Smrg if (!(dc_state & DC_LOADED)) { 233f14f4646Smrg XmuSnprintf(buffer, sizeof(buffer), "%s%s%s%s", 234f14f4646Smrg "Save: file ", name, " is already loaded, " 235f14f4646Smrg "Save again to unload it", nothing_saved); 2365dfecf96Smrg Feep(); 237f14f4646Smrg dc_state |= DC_LOADED; 2385dfecf96Smrg AddDoubleClickCallback(XawTextGetSource(textwindow), True); 239f14f4646Smrg goto error; 240f14f4646Smrg } 241f14f4646Smrg else { 242f14f4646Smrg KillTextSource(item); 243f14f4646Smrg item = FindTextSource(source = XawTextGetSource(textwindow), NULL); 244f14f4646Smrg dc_state &= ~DC_LOADED; 2455dfecf96Smrg } 2465dfecf96Smrg } 2475dfecf96Smrg else if (item && !(item->flags & CHANGED_BIT)) { 248f14f4646Smrg if (!(dc_state & DC_SAVE)) { 249f14f4646Smrg XmuSnprintf(buffer, sizeof(buffer), "%s%s", 250f14f4646Smrg "Save: No changes need to be saved, " 251f14f4646Smrg "save again to override", nothing_saved); 2525dfecf96Smrg Feep(); 253f14f4646Smrg dc_state |= DC_SAVE; 2545dfecf96Smrg AddDoubleClickCallback(XawTextGetSource(textwindow), True); 255f14f4646Smrg goto error; 2565dfecf96Smrg } 257f14f4646Smrg else 258f14f4646Smrg dc_state &= ~DC_SAVE; 2595dfecf96Smrg } 2605dfecf96Smrg 2615dfecf96Smrg file_access = CheckFilePermissions(filename, &exists); 262f14f4646Smrg if (exists) { 263f14f4646Smrg if (stat(filename, &st) != 0) { 264f14f4646Smrg XmuSnprintf(buffer, sizeof(buffer), "%s%s%s", 265f14f4646Smrg "Save: cannot stat ", name, nothing_saved); 266f14f4646Smrg goto error; 267f14f4646Smrg } 268f14f4646Smrg else if (!S_ISREG(st.st_mode)) { 269f14f4646Smrg XmuSnprintf(buffer, sizeof(buffer), "%s%s%s%s", 270f14f4646Smrg "Save: file ", name, "is not a regular file", 271f14f4646Smrg nothing_saved); 272f14f4646Smrg goto error; 273f14f4646Smrg } 274f14f4646Smrg } 275f14f4646Smrg 2765dfecf96Smrg if (!item || strcmp(item->filename, filename)) { 2775dfecf96Smrg if (file_access == WRITE_OK && exists) { 278f14f4646Smrg if (!(dc_state & DC_CLOBBER)) { 279f14f4646Smrg XmuSnprintf(buffer, sizeof(buffer), "%s%s%s%s", 280f14f4646Smrg "Save: file ", name, " already exists, " 281f14f4646Smrg "save again to override", nothing_saved); 2825dfecf96Smrg Feep(); 283f14f4646Smrg dc_state |= DC_CLOBBER; 2845dfecf96Smrg AddDoubleClickCallback(XawTextGetSource(textwindow), True); 285f14f4646Smrg goto error; 2865dfecf96Smrg } 287f14f4646Smrg else 288f14f4646Smrg dc_state &= ~DC_CLOBBER; 2895dfecf96Smrg } 2905dfecf96Smrg if (!item) 2915dfecf96Smrg item = FindTextSource(source, NULL); 2925dfecf96Smrg } 2935dfecf96Smrg 294f14f4646Smrg if (item && item->mtime && exists && item->mtime < st.st_mtime) { 295f14f4646Smrg if (!(dc_state & DC_NEWER)) { 296f14f4646Smrg XmuSnprintf(buffer, sizeof(buffer), "%s%s", 297f14f4646Smrg "Save: Newer file exists, " 298f14f4646Smrg "save again to override", nothing_saved); 299f14f4646Smrg Feep(); 300f14f4646Smrg dc_state |= DC_NEWER; 301f14f4646Smrg AddDoubleClickCallback(XawTextGetSource(textwindow), True); 302f14f4646Smrg goto error; 303f14f4646Smrg } 304f14f4646Smrg else 305f14f4646Smrg dc_state &= DC_NEWER; 306f14f4646Smrg } 307f14f4646Smrg 308f14f4646Smrg if (app_resources.enableBackups && exists) { 309f14f4646Smrg char backup_file[BUFSIZ]; 310f14f4646Smrg 311f14f4646Smrg if (makeBackupName(backup_file, filename, sizeof(backup_file)) == NULL 312f14f4646Smrg || rename(filename, backup_file) != 0) { 313f14f4646Smrg XeditPrintf("Error backing up file: %s\n", filename); 314f14f4646Smrg } 315f14f4646Smrg } 316f14f4646Smrg 317f14f4646Smrg switch (file_access = MaybeCreateFile(filename)) { 318f14f4646Smrg case NO_READ: 319f14f4646Smrg case READ_OK: 320f14f4646Smrg XeditPrintf("File %s could not be opened for writing.\n", name); 321f14f4646Smrg Feep(); 322f14f4646Smrg break; 323f14f4646Smrg case WRITE_OK: 324f14f4646Smrg if (XawAsciiSaveAsFile(source, filename)) { 325f14f4646Smrg int i; 326f14f4646Smrg Arg args[1]; 327f14f4646Smrg 328f14f4646Smrg XmuSnprintf(buffer, sizeof(buffer), 329f14f4646Smrg "%s Read - Write", name); 330f14f4646Smrg XtSetArg(args[0], XtNlabel, buffer); 331f14f4646Smrg for (i = 0; i < 3; i++) 332f14f4646Smrg if (XawTextGetSource(texts[i]) == source) 333f14f4646Smrg XtSetValues(labels[i], args, 1); 334f14f4646Smrg 335f14f4646Smrg XeditPrintf("Saved file: %s\n", name); 336f14f4646Smrg 337f14f4646Smrg if (item && item->source != scratch) { 338f14f4646Smrg XtSetArg(args[0], XtNlabel, filename); 339f14f4646Smrg XtSetValues(item->sme, args, 1); 340f14f4646Smrg 341f14f4646Smrg XtSetArg(args[0], XtNeditType, XawtextEdit); 342f14f4646Smrg XtSetValues(item->source, args, 1); 343f14f4646Smrg 344f14f4646Smrg XtFree(item->name); 345f14f4646Smrg XtFree(item->filename); 346f14f4646Smrg item->name = XtNewString(name); 347f14f4646Smrg item->filename = XtNewString(filename); 348f14f4646Smrg item->flags = EXISTS_BIT; 349f14f4646Smrg } 350f14f4646Smrg else { 351f14f4646Smrg item = flist.itens[0]; 352f14f4646Smrg XtRemoveCallback(scratch, XtNcallback, SourceChanged, 353f14f4646Smrg (XtPointer)item); 354f14f4646Smrg item->source = scratch = 355f14f4646Smrg XtVaCreateWidget("textSource", international ? 356f14f4646Smrg multiSrcObjectClass : 357f14f4646Smrg asciiSrcObjectClass, 358f14f4646Smrg topwindow, 359f14f4646Smrg XtNtype, XawAsciiFile, 360f14f4646Smrg XtNeditType, XawtextEdit, 361f14f4646Smrg NULL, NULL); 362f14f4646Smrg ResetSourceChanged(item); 363f14f4646Smrg XtAddCallback(scratch, XtNcallback, SourceChanged, 364f14f4646Smrg (XtPointer)item); 365f14f4646Smrg 366f14f4646Smrg item = AddTextSource(source, name, filename, EXISTS_BIT, 367f14f4646Smrg file_access); 368f14f4646Smrg XtAddCallback(item->source, XtNcallback, SourceChanged, 369f14f4646Smrg (XtPointer)item); 370f14f4646Smrg } 371f14f4646Smrg 372f14f4646Smrg /* Keep file protection mode */ 373f14f4646Smrg if (item->mode) 374f14f4646Smrg chmod(filename, item->mode); 375f14f4646Smrg 376f14f4646Smrg /* Remember time of last modification */ 377f14f4646Smrg if (stat(filename, &st) == 0) 378f14f4646Smrg item->mtime = st.st_mtime; 379f14f4646Smrg 380f14f4646Smrg item->flags |= EXISTS_BIT; 381f14f4646Smrg ResetSourceChanged(item); 382f14f4646Smrg } 383f14f4646Smrg else { 384f14f4646Smrg XeditPrintf("Error saving file: %s\n", name); 385f14f4646Smrg Feep(); 386f14f4646Smrg } 387f14f4646Smrg break; 388f14f4646Smrg default: 389f14f4646Smrg Feep(); 390f14f4646Smrg break; 3915dfecf96Smrg } 3925dfecf96Smrg 393f14f4646Smrg return; 394f14f4646Smrgerror: 395f14f4646Smrg XeditPrintf("%s", buffer); 396f14f4646Smrg Feep(); 3975dfecf96Smrg} 3985dfecf96Smrg 3995dfecf96Smrg/*ARGSUSED*/ 4005dfecf96Smrgvoid 4015dfecf96SmrgDoLoad(Widget w, XtPointer client_data, XtPointer call_data) 4025dfecf96Smrg{ 4035dfecf96Smrg if (ReallyDoLoad(GetString(filenamewindow), ResolveName(NULL))) { 4045dfecf96Smrg SwitchDirWindow(False); 4055dfecf96Smrg XtSetKeyboardFocus(topwindow, textwindow); 4065dfecf96Smrg } 4075dfecf96Smrg} 4085dfecf96Smrg 409f14f4646SmrgBool 410f14f4646SmrgLoadFileInTextwindow(char *name, char *resolved_name) 411f14f4646Smrg{ 412f14f4646Smrg return (ReallyDoLoad(name, resolved_name)); 413f14f4646Smrg} 414f14f4646Smrg 4155dfecf96Smrgstatic Bool 4165dfecf96SmrgReallyDoLoad(char *name, char *filename) 4175dfecf96Smrg{ 4185dfecf96Smrg Arg args[5]; 4195dfecf96Smrg Cardinal num_args = 0; 4205dfecf96Smrg xedit_flist_item *item; 4215dfecf96Smrg Widget source = XawTextGetSource(textwindow); 4225dfecf96Smrg 4235dfecf96Smrg if (!filename) { 4245dfecf96Smrg XeditPrintf("Load: Can't resolve pathname.\n"); 4255dfecf96Smrg Feep(); 4265dfecf96Smrg return (False); 4275dfecf96Smrg } 4285dfecf96Smrg else if (*name == '\0') { 4295dfecf96Smrg XeditPrintf("Load: No file specified.\n"); 4305dfecf96Smrg Feep(); 4315dfecf96Smrg } 4325dfecf96Smrg if ((item = FindTextSource(NULL, filename)) != NULL) { 4335dfecf96Smrg SwitchTextSource(item); 4345dfecf96Smrg return (True); 4355dfecf96Smrg } 4365dfecf96Smrg else { 4375dfecf96Smrg struct stat st; 4385dfecf96Smrg 4395dfecf96Smrg if (stat(filename, &st) == 0 && !S_ISREG(st.st_mode)) { 4405dfecf96Smrg if (S_ISDIR(st.st_mode)) { 4415dfecf96Smrg char path[BUFSIZ + 1]; 4425dfecf96Smrg 4435dfecf96Smrg strncpy(path, filename, sizeof(path) - 2); 4445dfecf96Smrg path[sizeof(path) - 2] = '\0'; 4455dfecf96Smrg if (*path) { 4465dfecf96Smrg if (path[strlen(path) - 1] != '/') 4475dfecf96Smrg strcat(path, "/"); 4485dfecf96Smrg } 4495dfecf96Smrg else 4505dfecf96Smrg strcpy(path, "./"); 4515dfecf96Smrg XtSetArg(args[0], XtNlabel, ""); 4525dfecf96Smrg XtSetValues(dirlabel, args, 1); 4535dfecf96Smrg SwitchDirWindow(True); 4545dfecf96Smrg DirWindowCB(dirwindow, path, NULL); 4555dfecf96Smrg return (False); 4565dfecf96Smrg } 4575dfecf96Smrg } 4585dfecf96Smrg } 4595dfecf96Smrg 4605dfecf96Smrg { 4615dfecf96Smrg Boolean exists; 4625dfecf96Smrg int flags; 4635dfecf96Smrg FileAccess file_access; 4645dfecf96Smrg 4655dfecf96Smrg switch( file_access = CheckFilePermissions(filename, &exists) ) { 4665dfecf96Smrg case NO_READ: 4675dfecf96Smrg if (exists) 468f14f4646Smrg XeditPrintf("File %s, %s", name, 469f14f4646Smrg "exists, and could not be opened for reading.\n"); 4705dfecf96Smrg else 471f14f4646Smrg XeditPrintf("File %s %s %s", name, 4725dfecf96Smrg "does not exist, and", 473f14f4646Smrg "the directory could not be opened for writing.\n"); 4745dfecf96Smrg 4755dfecf96Smrg Feep(); 4765dfecf96Smrg return (False); 4775dfecf96Smrg case READ_OK: 4785dfecf96Smrg XtSetArg(args[num_args], XtNeditType, XawtextRead); num_args++; 479f14f4646Smrg XeditPrintf("File %s opened READ ONLY.\n", name); 4805dfecf96Smrg break; 4815dfecf96Smrg case WRITE_OK: 4825dfecf96Smrg XtSetArg(args[num_args], XtNeditType, XawtextEdit); num_args++; 483f14f4646Smrg XeditPrintf("File %s opened read - write.\n", name); 4845dfecf96Smrg break; 4855dfecf96Smrg default: 4865dfecf96Smrg Feep(); 4875dfecf96Smrg return (False); 4885dfecf96Smrg } 4895dfecf96Smrg 4905dfecf96Smrg if (exists) { 4915dfecf96Smrg flags = EXISTS_BIT; 4925dfecf96Smrg XtSetArg(args[num_args], XtNstring, filename); num_args++; 4935dfecf96Smrg } 4945dfecf96Smrg else { 4955dfecf96Smrg flags = 0; 4965dfecf96Smrg XtSetArg(args[num_args], XtNstring, NULL); num_args++; 4975dfecf96Smrg } 4985dfecf96Smrg 499f14f4646Smrg source = XtVaCreateWidget("textSource", international ? 500f14f4646Smrg multiSrcObjectClass : 501f14f4646Smrg asciiSrcObjectClass, 5025dfecf96Smrg topwindow, 5035dfecf96Smrg XtNtype, XawAsciiFile, 5045dfecf96Smrg XtNeditType, XawtextEdit, 5055dfecf96Smrg NULL, NULL); 5065dfecf96Smrg XtSetValues(source, args, num_args); 5075dfecf96Smrg 5085dfecf96Smrg item = AddTextSource(source, name, filename, flags, file_access); 5095dfecf96Smrg XtAddCallback(item->source, XtNcallback, SourceChanged, 5105dfecf96Smrg (XtPointer)item); 5115dfecf96Smrg if (exists && file_access == WRITE_OK) { 5125dfecf96Smrg struct stat st; 5135dfecf96Smrg 514f14f4646Smrg if (stat(item->filename, &st) == 0) { 5155dfecf96Smrg item->mode = st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); 516f14f4646Smrg item->mtime = st.st_mtime; 517f14f4646Smrg } 5185dfecf96Smrg } 5195dfecf96Smrg SwitchTextSource(item); 5205dfecf96Smrg ResetSourceChanged(item); 5215dfecf96Smrg } 5225dfecf96Smrg 5235dfecf96Smrg return (True); 5245dfecf96Smrg} 5255dfecf96Smrg 5265dfecf96Smrg#ifdef INCLUDE_XPRINT_SUPPORT 5275dfecf96Smrgstatic void 5285dfecf96SmrgprintshellDestroyXtProc(Widget w, XtPointer client_data, XtPointer callData) 5295dfecf96Smrg{ 5305dfecf96Smrg XawPrintDialogClosePrinterConnection(printdialog, False); 5315dfecf96Smrg} 5325dfecf96Smrg 5335dfecf96Smrgstatic void 5345dfecf96SmrgprintOKXtProc(Widget w, XtPointer client_data, XtPointer callData) 5355dfecf96Smrg{ 5365dfecf96Smrg XawPrintDialogCallbackStruct *pdcs = (XawPrintDialogCallbackStruct *)callData; 5375dfecf96Smrg Cardinal n; 5385dfecf96Smrg Arg args[2]; 5395dfecf96Smrg Widget textsource; 5405dfecf96Smrg 5415dfecf96Smrg Log(("printOKXtProc: OK.\n")); 5425dfecf96Smrg 5435dfecf96Smrg /* Get TextSource object */ 5445dfecf96Smrg n = 0; 5455dfecf96Smrg XtSetArg(args[n], XtNtextSource, &textsource); n++; 5465dfecf96Smrg XtGetValues(textwindow, args, n); 5475dfecf96Smrg 5485dfecf96Smrg Assertion(textsource != NULL, (("printOKXtProc: textsource == NULL.\n"))); 5495dfecf96Smrg 5505dfecf96Smrg /* ||printJobNameBuffer| must live as long the print job prints 5515dfecf96Smrg * because it is used for the job title AND the page headers... */ 5525dfecf96Smrg sprintf(printJobNameBuffer, "Xedit print job"); 5535dfecf96Smrg 5545dfecf96Smrg DoPrintTextSource("Xedit", 5555dfecf96Smrg textsource, topwindow, 5565dfecf96Smrg pdcs->pdpy, pdcs->pcontext, pdcs->colorspace, 5575dfecf96Smrg printshellDestroyXtProc, 5585dfecf96Smrg printJobNameBuffer, 5595dfecf96Smrg pdcs->printToFile?pdcs->printToFileName:NULL); 5605dfecf96Smrg 5615dfecf96Smrg XtPopdown(printdialog_shell); 5625dfecf96Smrg} 5635dfecf96Smrg 5645dfecf96Smrgstatic void 5655dfecf96SmrgprintCancelXtProc(Widget w, XtPointer client_data, XtPointer callData) 5665dfecf96Smrg{ 5675dfecf96Smrg Log(("printCancelXtProc: cancel.\n")); 5685dfecf96Smrg XtPopdown(printdialog_shell); 5695dfecf96Smrg 5705dfecf96Smrg Log(("destroying print dialog shell...\n")); 5715dfecf96Smrg XtDestroyWidget(printdialog_shell); 5725dfecf96Smrg printdialog_shell = NULL; 5735dfecf96Smrg printdialog = NULL; 5745dfecf96Smrg Log(("... done\n")); 5755dfecf96Smrg} 5765dfecf96Smrg 5775dfecf96Smrg 5785dfecf96Smrg/*ARGSUSED*/ 5795dfecf96Smrgvoid 5805dfecf96SmrgPrintFile(Widget w, XEvent *event, String *params, Cardinal *num_params) 5815dfecf96Smrg{ 5825dfecf96Smrg DoPrint(w, NULL, NULL); 5835dfecf96Smrg} 5845dfecf96Smrg 5855dfecf96Smrg/*ARGSUSED*/ 5865dfecf96Smrgvoid 5875dfecf96SmrgDoPrint(Widget w, XtPointer client_data, XtPointer call_data) 5885dfecf96Smrg{ 5895dfecf96Smrg Dimension width, height; 5905dfecf96Smrg Position x, y; 5915dfecf96Smrg Widget parent = topwindow; 5925dfecf96Smrg Log(("print!\n")); 5935dfecf96Smrg 5945dfecf96Smrg if (!printdialog) { 5955dfecf96Smrg int n; 5965dfecf96Smrg Arg args[20]; 5975dfecf96Smrg 5985dfecf96Smrg n = 0; 5995dfecf96Smrg XtSetArg(args[n], XtNallowShellResize, True); n++; 6005dfecf96Smrg printdialog_shell = XtCreatePopupShell("printdialogshell", 6015dfecf96Smrg transientShellWidgetClass, 6025dfecf96Smrg topwindow, args, n); 6035dfecf96Smrg n = 0; 6045dfecf96Smrg printdialog = XtCreateManagedWidget("printdialog", printDialogWidgetClass, 6055dfecf96Smrg printdialog_shell, args, n); 6065dfecf96Smrg XtAddCallback(printdialog, XawNOkCallback, printOKXtProc, NULL); 6075dfecf96Smrg XtAddCallback(printdialog, XawNCancelCallback, printCancelXtProc, NULL); 6085dfecf96Smrg 6095dfecf96Smrg XtRealizeWidget(printdialog_shell); 6105dfecf96Smrg } 6115dfecf96Smrg 6125dfecf96Smrg /* Center dialog */ 6135dfecf96Smrg XtVaGetValues(printdialog_shell, 6145dfecf96Smrg XtNwidth, &width, 6155dfecf96Smrg XtNheight, &height, 6165dfecf96Smrg NULL); 6175dfecf96Smrg 6185dfecf96Smrg x = (Position)(XWidthOfScreen( XtScreen(parent)) - width) / 2; 6195dfecf96Smrg y = (Position)(XHeightOfScreen(XtScreen(parent)) - height) / 3; 6205dfecf96Smrg 6215dfecf96Smrg XtVaSetValues(printdialog_shell, 6225dfecf96Smrg XtNx, x, 6235dfecf96Smrg XtNy, y, 6245dfecf96Smrg NULL); 6255dfecf96Smrg 6265dfecf96Smrg XtPopup(printdialog_shell, XtGrabNonexclusive); 6275dfecf96Smrg} 6285dfecf96Smrg#endif /* INCLUDE_XPRINT_SUPPORT */ 6295dfecf96Smrg 6305dfecf96Smrg/* Function Name: SourceChanged 6315dfecf96Smrg * Description: A callback routine called when the source has changed. 6325dfecf96Smrg * Arguments: w - the text source that has changed. 6335dfecf96Smrg * client_data - xedit_flist_item associated with text buffer. 6345dfecf96Smrg * call_data - NULL is unchanged 6355dfecf96Smrg * Returns: none. 6365dfecf96Smrg */ 6375dfecf96Smrg/*ARGSUSED*/ 6385dfecf96Smrgvoid 6395dfecf96SmrgSourceChanged(Widget w, XtPointer client_data, XtPointer call_data) 6405dfecf96Smrg{ 6415dfecf96Smrg xedit_flist_item *item = (xedit_flist_item*)client_data; 6425dfecf96Smrg Bool changed = (Bool)(long)call_data; 6435dfecf96Smrg 6445dfecf96Smrg if (changed) { 6455dfecf96Smrg if (item->flags & CHANGED_BIT) 6465dfecf96Smrg return; 6475dfecf96Smrg item->flags |= CHANGED_BIT; 6485dfecf96Smrg } 6495dfecf96Smrg else { 6505dfecf96Smrg if (item->flags & CHANGED_BIT) 6515dfecf96Smrg ResetSourceChanged(item); 6525dfecf96Smrg return; 6535dfecf96Smrg } 6545dfecf96Smrg 6555dfecf96Smrg if (flist.pixmap) { 6565dfecf96Smrg Arg args[1]; 6575dfecf96Smrg Cardinal num_args; 6585dfecf96Smrg int i; 6595dfecf96Smrg 6605dfecf96Smrg num_args = 0; 6615dfecf96Smrg XtSetArg(args[num_args], XtNleftBitmap, flist.pixmap); ++num_args; 6625dfecf96Smrg XtSetValues(item->sme, args, num_args); 6635dfecf96Smrg 6645dfecf96Smrg for (i = 0; i < 3; i++) 6655dfecf96Smrg if (XawTextGetSource(texts[i]) == item->source) 6665dfecf96Smrg XtSetValues(labels[i], args, num_args); 6675dfecf96Smrg } 6685dfecf96Smrg} 6695dfecf96Smrg 6705dfecf96Smrg/* Function Name: ResetSourceChanged. 6715dfecf96Smrg * Description: Sets the source changed to FALSE, and 6725dfecf96Smrg * registers a callback to set it to TRUE when 6735dfecf96Smrg * the source has changed. 6745dfecf96Smrg * Arguments: item - item with widget to register the callback on. 6755dfecf96Smrg * Returns: none. 6765dfecf96Smrg */ 6775dfecf96Smrg 6785dfecf96Smrgvoid 6795dfecf96SmrgResetSourceChanged(xedit_flist_item *item) 6805dfecf96Smrg{ 6815dfecf96Smrg Arg args[1]; 6825dfecf96Smrg Cardinal num_args; 6835dfecf96Smrg int i; 6845dfecf96Smrg 6855dfecf96Smrg num_args = 0; 6865dfecf96Smrg XtSetArg(args[num_args], XtNleftBitmap, None); ++num_args; 6875dfecf96Smrg XtSetValues(item->sme, args, num_args); 6885dfecf96Smrg 6895dfecf96Smrg dc_state = 0; 6905dfecf96Smrg for (i = 0; i < 3; i++) { 6915dfecf96Smrg if (XawTextGetSource(texts[i]) == item->source) 6925dfecf96Smrg XtSetValues(labels[i], args, num_args); 6935dfecf96Smrg AddDoubleClickCallback(XawTextGetSource(texts[i]), False); 6945dfecf96Smrg } 6955dfecf96Smrg 6965dfecf96Smrg num_args = 0; 6975dfecf96Smrg XtSetArg(args[num_args], XtNsourceChanged, False); ++num_args; 6985dfecf96Smrg XtSetValues(item->source, args, num_args); 6995dfecf96Smrg 7005dfecf96Smrg item->flags &= ~CHANGED_BIT; 7015dfecf96Smrg} 7025dfecf96Smrg 7035dfecf96Smrg/*ARGSUSED*/ 7045dfecf96Smrgvoid 7055dfecf96SmrgKillFile(Widget w, XEvent *event, String *params, Cardinal *num_params) 7065dfecf96Smrg{ 7075dfecf96Smrg xedit_flist_item *item = FindTextSource(XawTextGetSource(textwindow), NULL); 7085dfecf96Smrg 7095dfecf96Smrg if (item->source == scratch) { 7105dfecf96Smrg Feep(); 7115dfecf96Smrg return; 7125dfecf96Smrg } 7135dfecf96Smrg 7145dfecf96Smrg if (item->flags & CHANGED_BIT) { 715f14f4646Smrg if (!(dc_state & DC_KILL)) { 7165dfecf96Smrg XeditPrintf("Kill: Unsaved changes. Kill again to override.\n"); 7175dfecf96Smrg Feep(); 718f14f4646Smrg dc_state |= DC_KILL; 7195dfecf96Smrg AddDoubleClickCallback(XawTextGetSource(textwindow), True); 7205dfecf96Smrg return; 7215dfecf96Smrg } 722f14f4646Smrg dc_state &= ~DC_KILL; 7235dfecf96Smrg } 7245dfecf96Smrg KillTextSource(item); 7255dfecf96Smrg} 7265dfecf96Smrg 7275dfecf96Smrg/*ARGSUSED*/ 7285dfecf96Smrgvoid 7295dfecf96SmrgFindFile(Widget w, XEvent *event, String *params, Cardinal *num_params) 7305dfecf96Smrg{ 731f14f4646Smrg char *string; 732f14f4646Smrg char *slash; 7335dfecf96Smrg XawTextBlock block; 7345dfecf96Smrg XawTextPosition end = XawTextSourceScan(XawTextGetSource(filenamewindow), 7355dfecf96Smrg 0, XawstAll, XawsdRight, 1, True); 7365dfecf96Smrg 737f14f4646Smrg if (!line_edit) { 738f14f4646Smrg string = GetString(filenamewindow); 739f14f4646Smrg if (string) 740f14f4646Smrg slash = strrchr(string, '/'); 741f14f4646Smrg } 742f14f4646Smrg else { 743f14f4646Smrg string = ""; 744f14f4646Smrg slash = NULL; 745f14f4646Smrg line_edit = False; 746f14f4646Smrg } 747f14f4646Smrg 7485dfecf96Smrg block.firstPos = 0; 7495dfecf96Smrg block.format = FMT8BIT; 7505dfecf96Smrg block.ptr = string; 7515dfecf96Smrg block.length = slash ? slash - string + 1 : 0; 7525dfecf96Smrg 7535dfecf96Smrg if (block.length != end) 7545dfecf96Smrg XawTextReplace(filenamewindow, 0, end, &block); 7555dfecf96Smrg XawTextSetInsertionPoint(filenamewindow, end); 7565dfecf96Smrg XtSetKeyboardFocus(topwindow, filenamewindow); 7575dfecf96Smrg} 7585dfecf96Smrg 7595dfecf96Smrg/*ARGSUSED*/ 7605dfecf96Smrgvoid 7615dfecf96SmrgLoadFile(Widget w, XEvent *event, String *params, Cardinal *num_params) 7625dfecf96Smrg{ 7635dfecf96Smrg if (line_edit) 7645dfecf96Smrg LineEdit(textwindow); 7655dfecf96Smrg else if (ReallyDoLoad(GetString(filenamewindow), ResolveName(NULL))) { 7665dfecf96Smrg SwitchDirWindow(False); 7675dfecf96Smrg XtSetKeyboardFocus(topwindow, textwindow); 7685dfecf96Smrg } 7695dfecf96Smrg} 7705dfecf96Smrg 7715dfecf96Smrg/*ARGSUSED*/ 7725dfecf96Smrgvoid 7735dfecf96SmrgCancelFindFile(Widget w, XEvent *event, String *params, Cardinal *num_params) 7745dfecf96Smrg{ 7755dfecf96Smrg Arg args[1]; 7765dfecf96Smrg xedit_flist_item *item; 7775dfecf96Smrg 7785dfecf96Smrg XtSetKeyboardFocus(topwindow, textwindow); 7795dfecf96Smrg 7805dfecf96Smrg item = FindTextSource(XawTextGetSource(textwindow), NULL); 7815dfecf96Smrg 7825dfecf96Smrg if (item->source != scratch) 7835dfecf96Smrg XtSetArg(args[0], XtNstring, item->name); 7845dfecf96Smrg else 7855dfecf96Smrg XtSetArg(args[0], XtNstring, NULL); 7865dfecf96Smrg 7875dfecf96Smrg XtSetValues(filenamewindow, args, 1); 788f14f4646Smrg /* XXX This probably should be done by the TextWidget, i.e. notice 789f14f4646Smrg * if the cursor became inivisible due to an horizontal scroll */ 790f14f4646Smrg _XawTextShowPosition((TextWidget)filenamewindow); 7915dfecf96Smrg 7925dfecf96Smrg if (XtIsManaged(XtParent(dirwindow))) 7935dfecf96Smrg SwitchDirWindow(False); 7945dfecf96Smrg 7955dfecf96Smrg line_edit = False; 7965dfecf96Smrg} 7975dfecf96Smrg 7985dfecf96Smrgstatic int 7995dfecf96Smrgcompar(_Xconst void *a, _Xconst void *b) 8005dfecf96Smrg{ 8015dfecf96Smrg return (strcmp(*(char **)a, *(char **)b)); 8025dfecf96Smrg} 8035dfecf96Smrg 8045dfecf96Smrg/*ARGSUSED*/ 8055dfecf96Smrgvoid 8065dfecf96SmrgFileCompletion(Widget w, XEvent *event, String *params, Cardinal *num_params) 8075dfecf96Smrg{ 8085dfecf96Smrg XawTextBlock block; 8095dfecf96Smrg String text; 8105dfecf96Smrg int length; 8115dfecf96Smrg char **matches, *save, *dir_name, *file_name, match[257]; 8125dfecf96Smrg unsigned n_matches, len, mlen, buflen; 8135dfecf96Smrg DIR *dir; 8145dfecf96Smrg Bool changed, slash = False, has_dot = False; 8155dfecf96Smrg#define SM_NEVER 0 8165dfecf96Smrg#define SM_HINT 1 8175dfecf96Smrg#define SM_ALWAYS 2 8185dfecf96Smrg int show_matches; 8195dfecf96Smrg 8205dfecf96Smrg text = GetString(filenamewindow); 8215dfecf96Smrg 8225dfecf96Smrg if (!text) { 8235dfecf96Smrg Feep(); 8245dfecf96Smrg return; 8255dfecf96Smrg } 8265dfecf96Smrg else if (line_edit) { 8275dfecf96Smrg Feep(); 8285dfecf96Smrg line_edit = 0; 8295dfecf96Smrg } 8305dfecf96Smrg 8315dfecf96Smrg { 8325dfecf96Smrg XawTextPosition pos = XawTextGetInsertionPoint(w); 8335dfecf96Smrg char *cslash = strchr(&text[pos], '/'), *cdot = strchr(&text[pos], '.'); 8345dfecf96Smrg 8355dfecf96Smrg if (cslash != NULL || cdot != NULL) { 8365dfecf96Smrg if (cslash != NULL && (cdot == NULL || cdot > cslash)) { 8375dfecf96Smrg length = cslash - text; 8385dfecf96Smrg slash = True; 8395dfecf96Smrg } 8405dfecf96Smrg else { 8415dfecf96Smrg length = cdot - text; 8425dfecf96Smrg has_dot = True; 8435dfecf96Smrg } 8445dfecf96Smrg } 8455dfecf96Smrg else 8465dfecf96Smrg length = strlen(text); 8475dfecf96Smrg } 8485dfecf96Smrg 8495dfecf96Smrg if (*num_params == 1 && length == strlen(text)) { 8505dfecf96Smrg switch (params[0][0]) { 8515dfecf96Smrg case 'n': /* Never */ 8525dfecf96Smrg case 'N': 8535dfecf96Smrg show_matches = SM_NEVER; 8545dfecf96Smrg break; 8555dfecf96Smrg case 'h': /* Hint */ 8565dfecf96Smrg case 'H': 8575dfecf96Smrg show_matches = SM_HINT; 8585dfecf96Smrg break; 8595dfecf96Smrg case 'a': /* Always */ 8605dfecf96Smrg case 'A': 8615dfecf96Smrg show_matches = SM_ALWAYS; 8625dfecf96Smrg break; 8635dfecf96Smrg default: 8645dfecf96Smrg show_matches = SM_NEVER; 8655dfecf96Smrg XtAppWarning(XtWidgetToApplicationContext(w), 8665dfecf96Smrg "Bad argument to file-completion, " 8675dfecf96Smrg "must be Never, Hint or Always"); 8685dfecf96Smrg break; 8695dfecf96Smrg } 8705dfecf96Smrg } 8715dfecf96Smrg else 8725dfecf96Smrg show_matches = SM_NEVER; 8735dfecf96Smrg 8745dfecf96Smrg matches = NULL; 8755dfecf96Smrg n_matches = buflen = 0; 8765dfecf96Smrg save = XtMalloc(length + 1); 8775dfecf96Smrg memmove(save, text, length); 8785dfecf96Smrg save[length] = '\0'; 8795dfecf96Smrg 8805dfecf96Smrg if (save[0] == '~' && save[1]) { 8815dfecf96Smrg char *slash2 = strchr(save, '/'); 8825dfecf96Smrg 8835dfecf96Smrg if (slash2) { 8845dfecf96Smrg struct passwd *pw; 8855dfecf96Smrg char home[BUFSIZ]; 8865dfecf96Smrg char *name; 8875dfecf96Smrg int slen = strlen(save), diff = slash2 - save; 8885dfecf96Smrg 8895dfecf96Smrg *slash2 = '\0'; 8905dfecf96Smrg name = save + 1; 8915dfecf96Smrg if (strlen(name) != 0) 8925dfecf96Smrg pw = getpwnam(name); 8935dfecf96Smrg else 8945dfecf96Smrg pw = getpwuid(getuid()); 8955dfecf96Smrg 8965dfecf96Smrg if (pw) { 8975dfecf96Smrg char fname[BUFSIZ]; 8985dfecf96Smrg int hlen; 8995dfecf96Smrg 9005dfecf96Smrg strncpy(home, pw->pw_dir, sizeof(home) - 1); 9015dfecf96Smrg home[sizeof(home) - 1] = '\0'; 9025dfecf96Smrg hlen = strlen(home); 9035dfecf96Smrg strncpy(fname, slash2 + 1, sizeof(fname) - 1); 9045dfecf96Smrg fname[sizeof(fname) - 1] = '\0'; 9055dfecf96Smrg save = XtRealloc(save, slen - diff + hlen + 2); 9065dfecf96Smrg (void)memmove(save, home, hlen); 9075dfecf96Smrg save[hlen] = '/'; 9085dfecf96Smrg strcpy(&save[hlen + 1], fname); 9095dfecf96Smrg 9105dfecf96Smrg /* expand directory */ 9115dfecf96Smrg block.length = strlen(save); 9125dfecf96Smrg block.ptr = save; 9135dfecf96Smrg block.firstPos = 0; 9145dfecf96Smrg block.format = FMT8BIT; 9155dfecf96Smrg XawTextReplace(filenamewindow, 0, length, &block); 9165dfecf96Smrg XawTextSetInsertionPoint(filenamewindow, length = block.length); 9175dfecf96Smrg } 9185dfecf96Smrg else 9195dfecf96Smrg *slash2 = '/'; 9205dfecf96Smrg } 9215dfecf96Smrg } 9225dfecf96Smrg 9235dfecf96Smrg if ((file_name = strrchr(save, '/')) != NULL) { 9245dfecf96Smrg *file_name = '\0'; 9255dfecf96Smrg ++file_name; 9265dfecf96Smrg dir_name = save; 9275dfecf96Smrg if (!file_name[0]) 9285dfecf96Smrg slash = True; 9295dfecf96Smrg if (!dir_name[0]) 9305dfecf96Smrg dir_name = "/"; 9315dfecf96Smrg } 9325dfecf96Smrg else { 9335dfecf96Smrg dir_name = "."; 9345dfecf96Smrg file_name = save; 9355dfecf96Smrg } 9365dfecf96Smrg len = strlen(file_name); 9375dfecf96Smrg 9385dfecf96Smrg if ((dir = opendir(dir_name)) != NULL) { 9395dfecf96Smrg char path[BUFSIZ], *pptr; 9405dfecf96Smrg struct dirent *ent; 9415dfecf96Smrg int isdir = 0, first = 1, bytes; 9425dfecf96Smrg 9435dfecf96Smrg XmuSnprintf(path, sizeof(path), "%s/", dir_name); 9445dfecf96Smrg pptr = path + strlen(path); 9455dfecf96Smrg bytes = sizeof(path) - (pptr - path) - 1; 9465dfecf96Smrg 9475dfecf96Smrg mlen = 0; 9485dfecf96Smrg match[0] = '\0'; 9495dfecf96Smrg while ((ent = readdir(dir)) != NULL) { 9505dfecf96Smrg unsigned d_namlen = strlen(ent->d_name); 9515dfecf96Smrg 952f14f4646Smrg if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) 953f14f4646Smrg continue; 9545dfecf96Smrg if (d_namlen >= len && strncmp(ent->d_name, file_name, len) == 0) { 9555dfecf96Smrg char *tmp = &(ent->d_name[len]), *mat = match; 9565dfecf96Smrg struct stat st; 9575dfecf96Smrg Bool is_dir = FALSE; 9585dfecf96Smrg 9595dfecf96Smrg strncpy(pptr, ent->d_name, bytes); 9605dfecf96Smrg pptr[bytes] = '\0'; 9615dfecf96Smrg if (stat(path, &st) != 0) 9625dfecf96Smrg /* Should check errno, may be a broken symbolic link 9635dfecf96Smrg * a directory with r-- permission, etc */ 9645dfecf96Smrg continue; 9655dfecf96Smrg else if (first || show_matches != SM_NEVER) { 9665dfecf96Smrg is_dir = S_ISDIR(st.st_mode); 9675dfecf96Smrg } 9685dfecf96Smrg 9695dfecf96Smrg if (first) { 9705dfecf96Smrg strncpy(match, tmp, sizeof(match) - 1); 9715dfecf96Smrg match[sizeof(match) - 2] = '\0'; 9725dfecf96Smrg mlen = strlen(match); 9735dfecf96Smrg first = 0; 9745dfecf96Smrg isdir = is_dir; 9755dfecf96Smrg } 9765dfecf96Smrg else { 9775dfecf96Smrg while (*tmp && *mat && *tmp++ == *mat) 9785dfecf96Smrg ++mat; 9795dfecf96Smrg if (mlen > mat - match) { 9805dfecf96Smrg mlen = mat - match; 9815dfecf96Smrg match[mlen] = '\0'; 9825dfecf96Smrg } 9835dfecf96Smrg } 9845dfecf96Smrg if (show_matches != SM_NEVER) { 9855dfecf96Smrg matches = (char **)XtRealloc((char*)matches, sizeof(char**) 9865dfecf96Smrg * (n_matches + 1)); 9875dfecf96Smrg buflen += d_namlen + 1; 9885dfecf96Smrg if (is_dir) { 9895dfecf96Smrg matches[n_matches] = XtMalloc(d_namlen + 2); 9905dfecf96Smrg strcpy(matches[n_matches], ent->d_name); 9915dfecf96Smrg strcat(matches[n_matches], "/"); 9925dfecf96Smrg ++buflen; 9935dfecf96Smrg } 9945dfecf96Smrg else 9955dfecf96Smrg matches[n_matches] = XtNewString(ent->d_name); 9965dfecf96Smrg } 9975dfecf96Smrg else if (mlen == 0 && n_matches >= 1) { 9985dfecf96Smrg ++n_matches; 9995dfecf96Smrg break; 10005dfecf96Smrg } 10015dfecf96Smrg ++n_matches; 10025dfecf96Smrg } 10035dfecf96Smrg } 10045dfecf96Smrg 10055dfecf96Smrg closedir(dir); 10065dfecf96Smrg changed = mlen != 0; 10075dfecf96Smrg 1008f14f4646Smrg if (first || n_matches) { 10095dfecf96Smrg Bool free_matches = True, add_slash = n_matches == 1 && isdir && !slash; 10105dfecf96Smrg 10115dfecf96Smrg if (mlen && has_dot && match[mlen - 1] == '.') 10125dfecf96Smrg --mlen; 10135dfecf96Smrg 10145dfecf96Smrg if (mlen || add_slash) { 10155dfecf96Smrg XawTextPosition pos; 10165dfecf96Smrg 10175dfecf96Smrg block.firstPos = 0; 10185dfecf96Smrg block.format = FMT8BIT; 10195dfecf96Smrg if (mlen) { 10205dfecf96Smrg pos = length; 10215dfecf96Smrg block.length = mlen; 10225dfecf96Smrg block.ptr = match; 10235dfecf96Smrg XawTextReplace(filenamewindow, pos, pos, &block); 10245dfecf96Smrg XawTextSetInsertionPoint(filenamewindow, pos + block.length); 10255dfecf96Smrg } 10265dfecf96Smrg if (add_slash) { 10275dfecf96Smrg XawTextPosition actual = XawTextGetInsertionPoint(w); 10285dfecf96Smrg 10295dfecf96Smrg pos = XawTextSourceScan(XawTextGetSource(w), 0, XawstAll, 10305dfecf96Smrg XawsdRight, 1, True); 10315dfecf96Smrg block.length = 1; 10325dfecf96Smrg block.ptr = "/"; 10335dfecf96Smrg XawTextReplace(filenamewindow, pos, pos, &block); 10345dfecf96Smrg if (actual == pos) 10355dfecf96Smrg XawTextSetInsertionPoint(filenamewindow, pos + 1); 10365dfecf96Smrg } 10375dfecf96Smrg } 10385dfecf96Smrg else if (n_matches != 1 || isdir) { 10395dfecf96Smrg if (show_matches == SM_NEVER) 10405dfecf96Smrg Feep(); 10415dfecf96Smrg } 10425dfecf96Smrg 10435dfecf96Smrg if (show_matches != SM_NEVER) { 10445dfecf96Smrg if (show_matches == SM_ALWAYS || (!changed && n_matches != 1)) { 10455dfecf96Smrg char **list = NULL, *label; 10465dfecf96Smrg int n_list; 10475dfecf96Smrg Arg args[2]; 10485dfecf96Smrg 10495dfecf96Smrg XtSetArg(args[0], XtNlist, &list); 10505dfecf96Smrg XtSetArg(args[1], XtNnumberStrings, &n_list); 10515dfecf96Smrg XtGetValues(dirwindow, args, 2); 10525dfecf96Smrg 10535dfecf96Smrg matches = (char **)XtRealloc((char*)matches, sizeof(char**) 10545dfecf96Smrg * (n_matches + 2)); 10555dfecf96Smrg matches[n_matches++] = XtNewString("./"); 10565dfecf96Smrg matches[n_matches++] = XtNewString("../"); 10575dfecf96Smrg qsort(matches, n_matches, sizeof(char*), compar); 10585dfecf96Smrg XtSetArg(args[0], XtNlist, matches); 10595dfecf96Smrg XtSetArg(args[1], XtNnumberStrings, n_matches); 10605dfecf96Smrg XtSetValues(dirwindow, args, 2); 10615dfecf96Smrg if (n_list > 0 10625dfecf96Smrg && (n_list != 1 || list[0] != XtName(dirwindow))) { 10635dfecf96Smrg while (--n_list > -1) 10645dfecf96Smrg XtFree(list[n_list]); 10655dfecf96Smrg XtFree((char*)list); 10665dfecf96Smrg } 10675dfecf96Smrg 10685dfecf96Smrg label = ResolveName(dir_name); 10695dfecf96Smrg XtSetArg(args[0], XtNlabel, label); 10705dfecf96Smrg XtSetValues(dirlabel, args, 1); 10715dfecf96Smrg SwitchDirWindow(True); 10725dfecf96Smrg free_matches = False; 10735dfecf96Smrg } 10745dfecf96Smrg } 10755dfecf96Smrg if (free_matches && matches) { 10765dfecf96Smrg while (--n_matches > -1) 10775dfecf96Smrg XtFree(matches[n_matches]); 10785dfecf96Smrg XtFree((char*)matches); 10795dfecf96Smrg } 10805dfecf96Smrg } 10815dfecf96Smrg else 10825dfecf96Smrg Feep(); 10835dfecf96Smrg } 10845dfecf96Smrg else 10855dfecf96Smrg Feep(); 10865dfecf96Smrg 10875dfecf96Smrg XtFree(save); 10885dfecf96Smrg} 10895dfecf96Smrg 10905dfecf96Smrg/*ARGSUSED*/ 10915dfecf96Smrgvoid 10925dfecf96SmrgDirWindowCB(Widget w, XtPointer user_data, XtPointer call_data) 10935dfecf96Smrg{ 10945dfecf96Smrg XawListReturnStruct *file_info = (XawListReturnStruct *)call_data; 10955dfecf96Smrg char *dir_name, *string, path[BUFSIZ]; 10965dfecf96Smrg Arg args[2]; 10975dfecf96Smrg 10985dfecf96Smrg if (file_info == NULL) 10995dfecf96Smrg string = (char *)user_data; 11005dfecf96Smrg else 11015dfecf96Smrg string = file_info->string; 11025dfecf96Smrg 11035dfecf96Smrg XtSetArg(args[0], XtNlabel, &dir_name); 11045dfecf96Smrg XtGetValues(dirlabel, args, 1); 11055dfecf96Smrg if (*dir_name == '\0') { 11065dfecf96Smrg strncpy(path, string, sizeof(path) - 1); 11075dfecf96Smrg path[sizeof(path) - 1] = '\0'; 11085dfecf96Smrg } 11095dfecf96Smrg else if (strcmp(dir_name, "/") == 0) 11105dfecf96Smrg XmuSnprintf(path, sizeof(path), "/%s", string); 11115dfecf96Smrg else 11125dfecf96Smrg XmuSnprintf(path, sizeof(path), "%s/%s", dir_name, string); 11135dfecf96Smrg 11145dfecf96Smrg if (*string && string[strlen(string) - 1] == '/') { 11155dfecf96Smrg DIR *dir; 11165dfecf96Smrg 11175dfecf96Smrg if ((dir = opendir(path)) != NULL) { 11185dfecf96Smrg struct dirent *ent; 11195dfecf96Smrg struct stat st; 11205dfecf96Smrg unsigned d_namlen; 11215dfecf96Smrg Bool isdir; 11225dfecf96Smrg char **entries = NULL, **list = NULL; 11235dfecf96Smrg int n_entries = 0, n_list = 0; 11245dfecf96Smrg char *label, *pptr = path + strlen(path); 11255dfecf96Smrg int bytes = sizeof(path) - (pptr - path) - 1; 11265dfecf96Smrg 11275dfecf96Smrg while ((ent = readdir(dir)) != NULL) { 11285dfecf96Smrg d_namlen = strlen(ent->d_name); 11295dfecf96Smrg strncpy(pptr, ent->d_name, bytes); 11305dfecf96Smrg pptr[bytes] = '\0'; 11315dfecf96Smrg if (stat(path, &st) != 0) 11325dfecf96Smrg /* Should check errno, may be a broken symbolic link 11335dfecf96Smrg * a directory with r-- permission, etc */ 11345dfecf96Smrg continue; 11355dfecf96Smrg else 11365dfecf96Smrg isdir = S_ISDIR(st.st_mode); 11375dfecf96Smrg 11385dfecf96Smrg entries = (char **)XtRealloc((char*)entries, sizeof(char*) 11395dfecf96Smrg * (n_entries + 1)); 11405dfecf96Smrg if (isdir) { 11415dfecf96Smrg entries[n_entries] = XtMalloc(d_namlen + 2); 11425dfecf96Smrg strcpy(entries[n_entries], ent->d_name); 11435dfecf96Smrg strcat(entries[n_entries], "/"); 11445dfecf96Smrg } 11455dfecf96Smrg else 11465dfecf96Smrg entries[n_entries] = XtNewString(ent->d_name); 11475dfecf96Smrg ++n_entries; 11485dfecf96Smrg } 11495dfecf96Smrg closedir(dir); 11505dfecf96Smrg 11515dfecf96Smrg XtSetArg(args[0], XtNlist, &list); 11525dfecf96Smrg XtSetArg(args[1], XtNnumberStrings, &n_list); 11535dfecf96Smrg XtGetValues(dirwindow, args, 2); 11545dfecf96Smrg 11555dfecf96Smrg if (n_entries == 0) { 11565dfecf96Smrg entries = (char**)XtMalloc(sizeof(char*) * 2); 11575dfecf96Smrg /* Directory has read but not execute permission? */ 11585dfecf96Smrg entries[n_entries++] = XtNewString("./"); 11595dfecf96Smrg entries[n_entries++] = XtNewString("../"); 11605dfecf96Smrg } 11615dfecf96Smrg qsort(entries, n_entries, sizeof(char*), compar); 11625dfecf96Smrg XtSetArg(args[0], XtNlist, entries); 11635dfecf96Smrg XtSetArg(args[1], XtNnumberStrings, n_entries); 11645dfecf96Smrg XtSetValues(dirwindow, args, 2); 11655dfecf96Smrg if (n_list > 0 11665dfecf96Smrg && (n_list != 1 || list[0] != XtName(dirwindow))) { 11675dfecf96Smrg while (--n_list > -1) 11685dfecf96Smrg XtFree(list[n_list]); 11695dfecf96Smrg XtFree((char*)list); 11705dfecf96Smrg } 11715dfecf96Smrg 11725dfecf96Smrg *pptr = '\0'; 11735dfecf96Smrg if ((label = ResolveName(path)) == NULL) { 11745dfecf96Smrg Feep(); 11755dfecf96Smrg label = path; 11765dfecf96Smrg } 11775dfecf96Smrg XtSetArg(args[0], XtNlabel, label); 11785dfecf96Smrg XtSetValues(dirlabel, args, 1); 11795dfecf96Smrg 11805dfecf96Smrg strncpy(path, label, sizeof(path) - 2); 11815dfecf96Smrg if (*path && path[strlen(path) - 1] != '/') 11825dfecf96Smrg strcat(path, "/"); 11835dfecf96Smrg XtSetArg(args[0], XtNstring, path); 11845dfecf96Smrg XtSetValues(filenamewindow, args, 1); 11855dfecf96Smrg XtSetKeyboardFocus(topwindow, filenamewindow); 11865dfecf96Smrg XawTextSetInsertionPoint(filenamewindow, strlen(path)); 11875dfecf96Smrg } 11885dfecf96Smrg else 11895dfecf96Smrg Feep(); 11905dfecf96Smrg } 11915dfecf96Smrg else { 11925dfecf96Smrg (void)ReallyDoLoad(path, path); 11935dfecf96Smrg SwitchDirWindow(False); 11945dfecf96Smrg XtSetKeyboardFocus(topwindow, textwindow); 11955dfecf96Smrg } 11965dfecf96Smrg} 1197