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#include <stdlib.h> 335dfecf96Smrg#include <stdio.h> 345dfecf96Smrg#include <limits.h> 355dfecf96Smrg#include <string.h> 365dfecf96Smrg#include <dirent.h> 375dfecf96Smrg#include <pwd.h> 385dfecf96Smrg#include <sys/stat.h> 395dfecf96Smrg#include <X11/Xmu/SysUtil.h> 405dfecf96Smrg#include <X11/IntrinsicP.h> 415dfecf96Smrg#include <X11/Xaw/TextSrcP.h> 425dfecf96Smrg 435dfecf96Smrg/* Turn a NULL pointer string into an empty string */ 445dfecf96Smrg#define NULLSTR(x) (((x)!=NULL)?(x):("")) 455dfecf96Smrg 465dfecf96Smrg#define Error(x) { printf x ; exit(EXIT_FAILURE); } 475dfecf96Smrg#define Assertion(expr, msg) { if (!(expr)) { Error msg } } 485dfecf96Smrg#define Log(x) { if (True) printf x; } 495dfecf96Smrg 505dfecf96Smrgvoid ResetSourceChanged(xedit_flist_item*); 515dfecf96Smrgstatic void ResetDC(Widget, XtPointer, XtPointer); 525dfecf96Smrg 535dfecf96Smrgstatic void AddDoubleClickCallback(Widget, Bool); 545dfecf96Smrgstatic Bool ReallyDoLoad(char*, char*); 555dfecf96Smrgstatic char *makeBackupName(String, String, unsigned); 565dfecf96Smrg 57f14f4646Smrg/* 58f14f4646Smrg * External 59f14f4646Smrg */ 60f14f4646Smrgextern void _XawTextShowPosition(TextWidget); 61f14f4646Smrg 625dfecf96Smrgextern Widget scratch, texts[3], labels[3]; 635dfecf96Smrg 64f14f4646Smrg#define DC_UNSAVED (1 << 0) 65f14f4646Smrg#define DC_LOADED (1 << 1) 66f14f4646Smrg#define DC_CLOBBER (1 << 2) 67f14f4646Smrg#define DC_KILL (1 << 3) 68f14f4646Smrg#define DC_SAVE (1 << 4) 69f14f4646Smrg#define DC_NEWER (1 << 5) 705dfecf96Smrgstatic int dc_state; 715dfecf96Smrg 725dfecf96Smrgstatic void 735dfecf96SmrgAddDoubleClickCallback(Widget w, Bool state) 745dfecf96Smrg{ 75f14f4646Smrg if (state) 76f14f4646Smrg XtAddCallback(w, XtNcallback, ResetDC, NULL); 77f14f4646Smrg else 78f14f4646Smrg XtRemoveCallback(w, XtNcallback, ResetDC, NULL); 795dfecf96Smrg} 805dfecf96Smrg 815dfecf96Smrg/* Function Name: ResetDC 825dfecf96Smrg * Description: Resets the double click flag. 835dfecf96Smrg * Arguments: w - the text widget. 845dfecf96Smrg * junk, garbage - *** NOT USED *** 855dfecf96Smrg * Returns: none. 865dfecf96Smrg */ 875dfecf96Smrg 885dfecf96Smrg/* ARGSUSED */ 895dfecf96Smrgstatic void 905dfecf96SmrgResetDC(Widget w, XtPointer junk, XtPointer garbage) 915dfecf96Smrg{ 92f14f4646Smrg AddDoubleClickCallback(w, FALSE); 935dfecf96Smrg} 945dfecf96Smrg 955dfecf96Smrg/*ARGSUSED*/ 965dfecf96Smrgvoid 975dfecf96SmrgQuitAction(Widget w, XEvent *event, String *params, Cardinal *num_params) 985dfecf96Smrg{ 995dfecf96Smrg DoQuit(w, NULL, NULL); 1005dfecf96Smrg} 1015dfecf96Smrg 1025dfecf96Smrg/*ARGSUSED*/ 1035dfecf96Smrgvoid 1045dfecf96SmrgDoQuit(Widget w, XtPointer client_data, XtPointer call_data) 1055dfecf96Smrg{ 1065dfecf96Smrg unsigned i; 1075dfecf96Smrg Bool source_changed = False; 1085dfecf96Smrg 109f14f4646Smrg if (!(dc_state & DC_UNSAVED)) { 1105dfecf96Smrg for (i = 0; i < flist.num_itens; i++) 1115dfecf96Smrg if (flist.itens[i]->flags & CHANGED_BIT) { 1125dfecf96Smrg source_changed = True; 1135dfecf96Smrg break; 1145dfecf96Smrg } 1155dfecf96Smrg } 116f14f4646Smrg if (!source_changed) { 1175dfecf96Smrg XeditLispCleanUp(); 1185dfecf96Smrg exit(0); 1195dfecf96Smrg } 1205dfecf96Smrg 1215dfecf96Smrg XeditPrintf("Unsaved changes. Save them, or Quit again.\n"); 1225dfecf96Smrg Feep(); 123f14f4646Smrg dc_state |= DC_UNSAVED; 1245dfecf96Smrg AddDoubleClickCallback(XawTextGetSource(textwindow), True); 1255dfecf96Smrg} 1265dfecf96Smrg 1275dfecf96Smrgstatic char * 1285dfecf96SmrgmakeBackupName(String buf, String filename, unsigned len) 1295dfecf96Smrg{ 1305dfecf96Smrg if (app_resources.backupNamePrefix 1315dfecf96Smrg && strlen(app_resources.backupNamePrefix)) { 1325dfecf96Smrg if (strchr(app_resources.backupNamePrefix, '/')) 1335dfecf96Smrg XmuSnprintf(buf, len, "%s%s%s", app_resources.backupNamePrefix, 1345dfecf96Smrg filename, app_resources.backupNameSuffix); 1355dfecf96Smrg else { 1365dfecf96Smrg char fname[BUFSIZ]; 1375dfecf96Smrg char *name, ch; 1385dfecf96Smrg 1395dfecf96Smrg strncpy(fname, filename, sizeof(fname) - 1); 1405dfecf96Smrg fname[sizeof(fname) - 1] = '\0'; 1415dfecf96Smrg if ((name = strrchr(fname, '/')) != NULL) 1425dfecf96Smrg ++name; 1435dfecf96Smrg else 1445dfecf96Smrg name = filename; 1455dfecf96Smrg ch = *name; 1465dfecf96Smrg *name = '\0'; 1475dfecf96Smrg ++name; 1485dfecf96Smrg XmuSnprintf(buf, len, "%s%s%c%s%s", 1495dfecf96Smrg fname, app_resources.backupNamePrefix, ch, name, 1505dfecf96Smrg app_resources.backupNameSuffix); 1515dfecf96Smrg } 1525dfecf96Smrg } 1535dfecf96Smrg else 1545dfecf96Smrg XmuSnprintf(buf, len, "%s%s", 1555dfecf96Smrg filename, app_resources.backupNameSuffix); 1565dfecf96Smrg 1575dfecf96Smrg return (strcmp(filename, buf) ? buf : NULL); 1585dfecf96Smrg} 1595dfecf96Smrg 1605dfecf96Smrg/*ARGSUSED*/ 1615dfecf96Smrgvoid 1625dfecf96SmrgSaveFile(Widget w, XEvent *event, String *params, Cardinal *num_params) 1635dfecf96Smrg{ 164f14f4646Smrg if (line_edit) { 165f14f4646Smrg /* Don't try to save buffer with regex string. 166f14f4646Smrg * Call CancelFindFile() to leave line_edit mode. 167f14f4646Smrg */ 168f14f4646Smrg XeditPrintf("Save: Leaving line edit mode -- nothing saved.\n"); 169f14f4646Smrg CancelFindFile(w, event, params, num_params); 170f14f4646Smrg Feep(); 171f14f4646Smrg } 172f14f4646Smrg else 173f14f4646Smrg DoSave(w, NULL, NULL); 1745dfecf96Smrg} 1755dfecf96Smrg 1765dfecf96Smrg/*ARGSUSED*/ 1775dfecf96Smrgvoid 1785dfecf96SmrgDoSave(Widget w, XtPointer client_data, XtPointer call_data) 1795dfecf96Smrg{ 1805dfecf96Smrg String name = GetString(filenamewindow); 1815dfecf96Smrg String filename = ResolveName(name); 1825dfecf96Smrg FileAccess file_access; 1835dfecf96Smrg xedit_flist_item *item; 1845dfecf96Smrg Boolean exists; 1855dfecf96Smrg Widget source = XawTextGetSource(textwindow); 186f14f4646Smrg char buffer[BUFSIZ]; 187f14f4646Smrg struct stat st; 188f765521fSmrg static const char *nothing_saved = " -- nothing saved.\n"; 1895dfecf96Smrg 1905dfecf96Smrg if (!filename) { 191f14f4646Smrg XmuSnprintf(buffer, sizeof(buffer), "%s%s", 192f14f4646Smrg "Save: Can't resolve pathname", nothing_saved); 193f14f4646Smrg goto error; 1945dfecf96Smrg } 1955dfecf96Smrg else if (*name == '\0') { 196f14f4646Smrg XmuSnprintf(buffer, sizeof(buffer), "%s%s", 197f14f4646Smrg "Save: No filename specified", nothing_saved); 198f14f4646Smrg goto error; 1995dfecf96Smrg } 2005dfecf96Smrg 2015dfecf96Smrg item = FindTextSource(NULL, filename); 2025dfecf96Smrg if (item != NULL && item->source != source) { 203f14f4646Smrg if (!(dc_state & DC_LOADED)) { 204f14f4646Smrg XmuSnprintf(buffer, sizeof(buffer), "%s%s%s%s", 205f14f4646Smrg "Save: file ", name, " is already loaded, " 206f14f4646Smrg "Save again to unload it", nothing_saved); 2075dfecf96Smrg Feep(); 208f14f4646Smrg dc_state |= DC_LOADED; 2095dfecf96Smrg AddDoubleClickCallback(XawTextGetSource(textwindow), True); 210f14f4646Smrg goto error; 211f14f4646Smrg } 212f14f4646Smrg else { 213f14f4646Smrg KillTextSource(item); 214f14f4646Smrg item = FindTextSource(source = XawTextGetSource(textwindow), NULL); 215f14f4646Smrg dc_state &= ~DC_LOADED; 2165dfecf96Smrg } 2175dfecf96Smrg } 2185dfecf96Smrg else if (item && !(item->flags & CHANGED_BIT)) { 219f14f4646Smrg if (!(dc_state & DC_SAVE)) { 220f14f4646Smrg XmuSnprintf(buffer, sizeof(buffer), "%s%s", 221f14f4646Smrg "Save: No changes need to be saved, " 222f14f4646Smrg "save again to override", nothing_saved); 2235dfecf96Smrg Feep(); 224f14f4646Smrg dc_state |= DC_SAVE; 2255dfecf96Smrg AddDoubleClickCallback(XawTextGetSource(textwindow), True); 226f14f4646Smrg goto error; 2275dfecf96Smrg } 228f14f4646Smrg else 229f14f4646Smrg dc_state &= ~DC_SAVE; 2305dfecf96Smrg } 2315dfecf96Smrg 2325dfecf96Smrg file_access = CheckFilePermissions(filename, &exists); 233f14f4646Smrg if (exists) { 234f14f4646Smrg if (stat(filename, &st) != 0) { 235f14f4646Smrg XmuSnprintf(buffer, sizeof(buffer), "%s%s%s", 236f14f4646Smrg "Save: cannot stat ", name, nothing_saved); 237f14f4646Smrg goto error; 238f14f4646Smrg } 239f14f4646Smrg else if (!S_ISREG(st.st_mode)) { 240f14f4646Smrg XmuSnprintf(buffer, sizeof(buffer), "%s%s%s%s", 241f14f4646Smrg "Save: file ", name, "is not a regular file", 242f14f4646Smrg nothing_saved); 243f14f4646Smrg goto error; 244f14f4646Smrg } 245f14f4646Smrg } 246f14f4646Smrg 2475dfecf96Smrg if (!item || strcmp(item->filename, filename)) { 2485dfecf96Smrg if (file_access == WRITE_OK && exists) { 249f14f4646Smrg if (!(dc_state & DC_CLOBBER)) { 250f14f4646Smrg XmuSnprintf(buffer, sizeof(buffer), "%s%s%s%s", 251f14f4646Smrg "Save: file ", name, " already exists, " 252f14f4646Smrg "save again to override", nothing_saved); 2535dfecf96Smrg Feep(); 254f14f4646Smrg dc_state |= DC_CLOBBER; 2555dfecf96Smrg AddDoubleClickCallback(XawTextGetSource(textwindow), True); 256f14f4646Smrg goto error; 2575dfecf96Smrg } 258f14f4646Smrg else 259f14f4646Smrg dc_state &= ~DC_CLOBBER; 2605dfecf96Smrg } 2615dfecf96Smrg if (!item) 2625dfecf96Smrg item = FindTextSource(source, NULL); 2635dfecf96Smrg } 2645dfecf96Smrg 265f14f4646Smrg if (item && item->mtime && exists && item->mtime < st.st_mtime) { 266f14f4646Smrg if (!(dc_state & DC_NEWER)) { 267f14f4646Smrg XmuSnprintf(buffer, sizeof(buffer), "%s%s", 268f14f4646Smrg "Save: Newer file exists, " 269f14f4646Smrg "save again to override", nothing_saved); 270f14f4646Smrg Feep(); 271f14f4646Smrg dc_state |= DC_NEWER; 272f14f4646Smrg AddDoubleClickCallback(XawTextGetSource(textwindow), True); 273f14f4646Smrg goto error; 274f14f4646Smrg } 275f14f4646Smrg else 276f14f4646Smrg dc_state &= DC_NEWER; 277f14f4646Smrg } 278f14f4646Smrg 279f14f4646Smrg if (app_resources.enableBackups && exists) { 280f14f4646Smrg char backup_file[BUFSIZ]; 281f14f4646Smrg 282f14f4646Smrg if (makeBackupName(backup_file, filename, sizeof(backup_file)) == NULL 283f14f4646Smrg || rename(filename, backup_file) != 0) { 284f14f4646Smrg XeditPrintf("Error backing up file: %s\n", filename); 285f14f4646Smrg } 286f14f4646Smrg } 287f14f4646Smrg 288f14f4646Smrg switch (file_access = MaybeCreateFile(filename)) { 289f14f4646Smrg case NO_READ: 290f14f4646Smrg case READ_OK: 291f14f4646Smrg XeditPrintf("File %s could not be opened for writing.\n", name); 292f14f4646Smrg Feep(); 293f14f4646Smrg break; 294f14f4646Smrg case WRITE_OK: 295f14f4646Smrg if (XawAsciiSaveAsFile(source, filename)) { 296f14f4646Smrg int i; 297f14f4646Smrg Arg args[1]; 298f14f4646Smrg 299f14f4646Smrg XmuSnprintf(buffer, sizeof(buffer), 300f14f4646Smrg "%s Read - Write", name); 301f14f4646Smrg XtSetArg(args[0], XtNlabel, buffer); 302f14f4646Smrg for (i = 0; i < 3; i++) 303f14f4646Smrg if (XawTextGetSource(texts[i]) == source) 304f14f4646Smrg XtSetValues(labels[i], args, 1); 305f14f4646Smrg 306f14f4646Smrg XeditPrintf("Saved file: %s\n", name); 307f14f4646Smrg 308f14f4646Smrg if (item && item->source != scratch) { 309f14f4646Smrg XtSetArg(args[0], XtNlabel, filename); 310f14f4646Smrg XtSetValues(item->sme, args, 1); 311f14f4646Smrg 312f14f4646Smrg XtSetArg(args[0], XtNeditType, XawtextEdit); 313f14f4646Smrg XtSetValues(item->source, args, 1); 314f14f4646Smrg 315f14f4646Smrg XtFree(item->name); 316f14f4646Smrg XtFree(item->filename); 317f14f4646Smrg item->name = XtNewString(name); 318f14f4646Smrg item->filename = XtNewString(filename); 319f14f4646Smrg item->flags = EXISTS_BIT; 320f14f4646Smrg } 321f14f4646Smrg else { 322f14f4646Smrg item = flist.itens[0]; 323f14f4646Smrg XtRemoveCallback(scratch, XtNcallback, SourceChanged, 324f14f4646Smrg (XtPointer)item); 325f14f4646Smrg item->source = scratch = 326f14f4646Smrg XtVaCreateWidget("textSource", international ? 327f14f4646Smrg multiSrcObjectClass : 328f14f4646Smrg asciiSrcObjectClass, 329f14f4646Smrg topwindow, 330f14f4646Smrg XtNtype, XawAsciiFile, 331f14f4646Smrg XtNeditType, XawtextEdit, 332f14f4646Smrg NULL, NULL); 333f14f4646Smrg ResetSourceChanged(item); 334f14f4646Smrg XtAddCallback(scratch, XtNcallback, SourceChanged, 335f14f4646Smrg (XtPointer)item); 336f14f4646Smrg 337f14f4646Smrg item = AddTextSource(source, name, filename, EXISTS_BIT, 338f14f4646Smrg file_access); 339f14f4646Smrg XtAddCallback(item->source, XtNcallback, SourceChanged, 340f14f4646Smrg (XtPointer)item); 341f14f4646Smrg } 342f14f4646Smrg 343f14f4646Smrg /* Keep file protection mode */ 344f14f4646Smrg if (item->mode) 345f14f4646Smrg chmod(filename, item->mode); 346f14f4646Smrg 347f14f4646Smrg /* Remember time of last modification */ 348f14f4646Smrg if (stat(filename, &st) == 0) 349f14f4646Smrg item->mtime = st.st_mtime; 350f14f4646Smrg 351f14f4646Smrg item->flags |= EXISTS_BIT; 352f14f4646Smrg ResetSourceChanged(item); 353f14f4646Smrg } 354f14f4646Smrg else { 355f14f4646Smrg XeditPrintf("Error saving file: %s\n", name); 356f14f4646Smrg Feep(); 357f14f4646Smrg } 358f14f4646Smrg break; 359f14f4646Smrg default: 360f14f4646Smrg Feep(); 361f14f4646Smrg break; 3625dfecf96Smrg } 3635dfecf96Smrg 364f14f4646Smrg return; 365f14f4646Smrgerror: 366f14f4646Smrg XeditPrintf("%s", buffer); 367f14f4646Smrg Feep(); 3685dfecf96Smrg} 3695dfecf96Smrg 3705dfecf96Smrg/*ARGSUSED*/ 3715dfecf96Smrgvoid 3725dfecf96SmrgDoLoad(Widget w, XtPointer client_data, XtPointer call_data) 3735dfecf96Smrg{ 3745dfecf96Smrg if (ReallyDoLoad(GetString(filenamewindow), ResolveName(NULL))) { 3755dfecf96Smrg SwitchDirWindow(False); 3765dfecf96Smrg XtSetKeyboardFocus(topwindow, textwindow); 3775dfecf96Smrg } 3785dfecf96Smrg} 3795dfecf96Smrg 380f14f4646SmrgBool 381f14f4646SmrgLoadFileInTextwindow(char *name, char *resolved_name) 382f14f4646Smrg{ 383f14f4646Smrg return (ReallyDoLoad(name, resolved_name)); 384f14f4646Smrg} 385f14f4646Smrg 3865dfecf96Smrgstatic Bool 3875dfecf96SmrgReallyDoLoad(char *name, char *filename) 3885dfecf96Smrg{ 3895dfecf96Smrg Arg args[5]; 3905dfecf96Smrg Cardinal num_args = 0; 3915dfecf96Smrg xedit_flist_item *item; 3925dfecf96Smrg Widget source = XawTextGetSource(textwindow); 3935dfecf96Smrg 3945dfecf96Smrg if (!filename) { 3955dfecf96Smrg XeditPrintf("Load: Can't resolve pathname.\n"); 3965dfecf96Smrg Feep(); 3975dfecf96Smrg return (False); 3985dfecf96Smrg } 3995dfecf96Smrg else if (*name == '\0') { 4005dfecf96Smrg XeditPrintf("Load: No file specified.\n"); 4015dfecf96Smrg Feep(); 4025dfecf96Smrg } 4035dfecf96Smrg if ((item = FindTextSource(NULL, filename)) != NULL) { 4045dfecf96Smrg SwitchTextSource(item); 4055dfecf96Smrg return (True); 4065dfecf96Smrg } 4075dfecf96Smrg else { 4085dfecf96Smrg struct stat st; 4095dfecf96Smrg 4105dfecf96Smrg if (stat(filename, &st) == 0 && !S_ISREG(st.st_mode)) { 4115dfecf96Smrg if (S_ISDIR(st.st_mode)) { 4125dfecf96Smrg char path[BUFSIZ + 1]; 4135dfecf96Smrg 4145dfecf96Smrg strncpy(path, filename, sizeof(path) - 2); 4155dfecf96Smrg path[sizeof(path) - 2] = '\0'; 4165dfecf96Smrg if (*path) { 4175dfecf96Smrg if (path[strlen(path) - 1] != '/') 4185dfecf96Smrg strcat(path, "/"); 4195dfecf96Smrg } 4205dfecf96Smrg else 4215dfecf96Smrg strcpy(path, "./"); 4225dfecf96Smrg XtSetArg(args[0], XtNlabel, ""); 4235dfecf96Smrg XtSetValues(dirlabel, args, 1); 4245dfecf96Smrg SwitchDirWindow(True); 4255dfecf96Smrg DirWindowCB(dirwindow, path, NULL); 4265dfecf96Smrg return (False); 4275dfecf96Smrg } 4285dfecf96Smrg } 4295dfecf96Smrg } 4305dfecf96Smrg 4315dfecf96Smrg { 4325dfecf96Smrg Boolean exists; 4335dfecf96Smrg int flags; 4345dfecf96Smrg FileAccess file_access; 4355dfecf96Smrg 4365dfecf96Smrg switch( file_access = CheckFilePermissions(filename, &exists) ) { 4375dfecf96Smrg case NO_READ: 4385dfecf96Smrg if (exists) 439f14f4646Smrg XeditPrintf("File %s, %s", name, 440f14f4646Smrg "exists, and could not be opened for reading.\n"); 4415dfecf96Smrg else 442f14f4646Smrg XeditPrintf("File %s %s %s", name, 4435dfecf96Smrg "does not exist, and", 444f14f4646Smrg "the directory could not be opened for writing.\n"); 4455dfecf96Smrg 4465dfecf96Smrg Feep(); 4475dfecf96Smrg return (False); 4485dfecf96Smrg case READ_OK: 4495dfecf96Smrg XtSetArg(args[num_args], XtNeditType, XawtextRead); num_args++; 450f14f4646Smrg XeditPrintf("File %s opened READ ONLY.\n", name); 4515dfecf96Smrg break; 4525dfecf96Smrg case WRITE_OK: 4535dfecf96Smrg XtSetArg(args[num_args], XtNeditType, XawtextEdit); num_args++; 454f14f4646Smrg XeditPrintf("File %s opened read - write.\n", name); 4555dfecf96Smrg break; 4565dfecf96Smrg default: 4575dfecf96Smrg Feep(); 4585dfecf96Smrg return (False); 4595dfecf96Smrg } 4605dfecf96Smrg 4615dfecf96Smrg if (exists) { 4625dfecf96Smrg flags = EXISTS_BIT; 4635dfecf96Smrg XtSetArg(args[num_args], XtNstring, filename); num_args++; 4645dfecf96Smrg } 4655dfecf96Smrg else { 4665dfecf96Smrg flags = 0; 4675dfecf96Smrg XtSetArg(args[num_args], XtNstring, NULL); num_args++; 4685dfecf96Smrg } 4695dfecf96Smrg 470f14f4646Smrg source = XtVaCreateWidget("textSource", international ? 471f14f4646Smrg multiSrcObjectClass : 472f14f4646Smrg asciiSrcObjectClass, 4735dfecf96Smrg topwindow, 4745dfecf96Smrg XtNtype, XawAsciiFile, 4755dfecf96Smrg XtNeditType, XawtextEdit, 4765dfecf96Smrg NULL, NULL); 4775dfecf96Smrg XtSetValues(source, args, num_args); 4785dfecf96Smrg 4795dfecf96Smrg item = AddTextSource(source, name, filename, flags, file_access); 4805dfecf96Smrg XtAddCallback(item->source, XtNcallback, SourceChanged, 4815dfecf96Smrg (XtPointer)item); 4825dfecf96Smrg if (exists && file_access == WRITE_OK) { 4835dfecf96Smrg struct stat st; 4845dfecf96Smrg 485f14f4646Smrg if (stat(item->filename, &st) == 0) { 4865dfecf96Smrg item->mode = st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); 487f14f4646Smrg item->mtime = st.st_mtime; 488f14f4646Smrg } 4895dfecf96Smrg } 4905dfecf96Smrg SwitchTextSource(item); 4915dfecf96Smrg ResetSourceChanged(item); 4925dfecf96Smrg } 4935dfecf96Smrg 4945dfecf96Smrg return (True); 4955dfecf96Smrg} 4965dfecf96Smrg 4975dfecf96Smrg/* Function Name: SourceChanged 4985dfecf96Smrg * Description: A callback routine called when the source has changed. 4995dfecf96Smrg * Arguments: w - the text source that has changed. 5005dfecf96Smrg * client_data - xedit_flist_item associated with text buffer. 5015dfecf96Smrg * call_data - NULL is unchanged 5025dfecf96Smrg * Returns: none. 5035dfecf96Smrg */ 5045dfecf96Smrg/*ARGSUSED*/ 5055dfecf96Smrgvoid 5065dfecf96SmrgSourceChanged(Widget w, XtPointer client_data, XtPointer call_data) 5075dfecf96Smrg{ 5085dfecf96Smrg xedit_flist_item *item = (xedit_flist_item*)client_data; 5095dfecf96Smrg Bool changed = (Bool)(long)call_data; 5105dfecf96Smrg 5115dfecf96Smrg if (changed) { 5125dfecf96Smrg if (item->flags & CHANGED_BIT) 5135dfecf96Smrg return; 5145dfecf96Smrg item->flags |= CHANGED_BIT; 5155dfecf96Smrg } 5165dfecf96Smrg else { 5175dfecf96Smrg if (item->flags & CHANGED_BIT) 5185dfecf96Smrg ResetSourceChanged(item); 5195dfecf96Smrg return; 5205dfecf96Smrg } 5215dfecf96Smrg 5225dfecf96Smrg if (flist.pixmap) { 5235dfecf96Smrg Arg args[1]; 5245dfecf96Smrg Cardinal num_args; 5255dfecf96Smrg int i; 5265dfecf96Smrg 5275dfecf96Smrg num_args = 0; 5285dfecf96Smrg XtSetArg(args[num_args], XtNleftBitmap, flist.pixmap); ++num_args; 5295dfecf96Smrg XtSetValues(item->sme, args, num_args); 5305dfecf96Smrg 5315dfecf96Smrg for (i = 0; i < 3; i++) 5325dfecf96Smrg if (XawTextGetSource(texts[i]) == item->source) 5335dfecf96Smrg XtSetValues(labels[i], args, num_args); 5345dfecf96Smrg } 5355dfecf96Smrg} 5365dfecf96Smrg 5375dfecf96Smrg/* Function Name: ResetSourceChanged. 5385dfecf96Smrg * Description: Sets the source changed to FALSE, and 5395dfecf96Smrg * registers a callback to set it to TRUE when 5405dfecf96Smrg * the source has changed. 5415dfecf96Smrg * Arguments: item - item with widget to register the callback on. 5425dfecf96Smrg * Returns: none. 5435dfecf96Smrg */ 5445dfecf96Smrg 5455dfecf96Smrgvoid 5465dfecf96SmrgResetSourceChanged(xedit_flist_item *item) 5475dfecf96Smrg{ 5485dfecf96Smrg Arg args[1]; 5495dfecf96Smrg Cardinal num_args; 5505dfecf96Smrg int i; 5515dfecf96Smrg 5525dfecf96Smrg num_args = 0; 5535dfecf96Smrg XtSetArg(args[num_args], XtNleftBitmap, None); ++num_args; 5545dfecf96Smrg XtSetValues(item->sme, args, num_args); 5555dfecf96Smrg 5565dfecf96Smrg dc_state = 0; 5575dfecf96Smrg for (i = 0; i < 3; i++) { 5585dfecf96Smrg if (XawTextGetSource(texts[i]) == item->source) 5595dfecf96Smrg XtSetValues(labels[i], args, num_args); 5605dfecf96Smrg AddDoubleClickCallback(XawTextGetSource(texts[i]), False); 5615dfecf96Smrg } 5625dfecf96Smrg 5635dfecf96Smrg num_args = 0; 5645dfecf96Smrg XtSetArg(args[num_args], XtNsourceChanged, False); ++num_args; 5655dfecf96Smrg XtSetValues(item->source, args, num_args); 5665dfecf96Smrg 5675dfecf96Smrg item->flags &= ~CHANGED_BIT; 5685dfecf96Smrg} 5695dfecf96Smrg 5705dfecf96Smrg/*ARGSUSED*/ 5715dfecf96Smrgvoid 5725dfecf96SmrgKillFile(Widget w, XEvent *event, String *params, Cardinal *num_params) 5735dfecf96Smrg{ 5745dfecf96Smrg xedit_flist_item *item = FindTextSource(XawTextGetSource(textwindow), NULL); 5755dfecf96Smrg 5765dfecf96Smrg if (item->source == scratch) { 5775dfecf96Smrg Feep(); 5785dfecf96Smrg return; 5795dfecf96Smrg } 5805dfecf96Smrg 5815dfecf96Smrg if (item->flags & CHANGED_BIT) { 582f14f4646Smrg if (!(dc_state & DC_KILL)) { 5835dfecf96Smrg XeditPrintf("Kill: Unsaved changes. Kill again to override.\n"); 5845dfecf96Smrg Feep(); 585f14f4646Smrg dc_state |= DC_KILL; 5865dfecf96Smrg AddDoubleClickCallback(XawTextGetSource(textwindow), True); 5875dfecf96Smrg return; 5885dfecf96Smrg } 589f14f4646Smrg dc_state &= ~DC_KILL; 5905dfecf96Smrg } 5915dfecf96Smrg KillTextSource(item); 5925dfecf96Smrg} 5935dfecf96Smrg 5945dfecf96Smrg/*ARGSUSED*/ 5955dfecf96Smrgvoid 5965dfecf96SmrgFindFile(Widget w, XEvent *event, String *params, Cardinal *num_params) 5975dfecf96Smrg{ 598f14f4646Smrg char *string; 599f14f4646Smrg char *slash; 6005dfecf96Smrg XawTextBlock block; 6015dfecf96Smrg XawTextPosition end = XawTextSourceScan(XawTextGetSource(filenamewindow), 6025dfecf96Smrg 0, XawstAll, XawsdRight, 1, True); 6035dfecf96Smrg 604c05e22d7Smrg slash = NULL; 605f14f4646Smrg if (!line_edit) { 606f14f4646Smrg string = GetString(filenamewindow); 607f14f4646Smrg if (string) 608f14f4646Smrg slash = strrchr(string, '/'); 609f14f4646Smrg } 610f14f4646Smrg else { 611f14f4646Smrg string = ""; 612f14f4646Smrg line_edit = False; 613f14f4646Smrg } 614f14f4646Smrg 6155dfecf96Smrg block.firstPos = 0; 6165dfecf96Smrg block.format = FMT8BIT; 6175dfecf96Smrg block.ptr = string; 6185dfecf96Smrg block.length = slash ? slash - string + 1 : 0; 6195dfecf96Smrg 6205dfecf96Smrg if (block.length != end) 6215dfecf96Smrg XawTextReplace(filenamewindow, 0, end, &block); 6225dfecf96Smrg XawTextSetInsertionPoint(filenamewindow, end); 6235dfecf96Smrg XtSetKeyboardFocus(topwindow, filenamewindow); 6245dfecf96Smrg} 6255dfecf96Smrg 6265dfecf96Smrg/*ARGSUSED*/ 6275dfecf96Smrgvoid 6285dfecf96SmrgLoadFile(Widget w, XEvent *event, String *params, Cardinal *num_params) 6295dfecf96Smrg{ 6305dfecf96Smrg if (line_edit) 6315dfecf96Smrg LineEdit(textwindow); 6325dfecf96Smrg else if (ReallyDoLoad(GetString(filenamewindow), ResolveName(NULL))) { 6335dfecf96Smrg SwitchDirWindow(False); 6345dfecf96Smrg XtSetKeyboardFocus(topwindow, textwindow); 6355dfecf96Smrg } 6365dfecf96Smrg} 6375dfecf96Smrg 6385dfecf96Smrg/*ARGSUSED*/ 6395dfecf96Smrgvoid 6405dfecf96SmrgCancelFindFile(Widget w, XEvent *event, String *params, Cardinal *num_params) 6415dfecf96Smrg{ 6425dfecf96Smrg Arg args[1]; 6435dfecf96Smrg xedit_flist_item *item; 6445dfecf96Smrg 6455dfecf96Smrg XtSetKeyboardFocus(topwindow, textwindow); 6465dfecf96Smrg 6475dfecf96Smrg item = FindTextSource(XawTextGetSource(textwindow), NULL); 6485dfecf96Smrg 6495dfecf96Smrg if (item->source != scratch) 6505dfecf96Smrg XtSetArg(args[0], XtNstring, item->name); 6515dfecf96Smrg else 6525dfecf96Smrg XtSetArg(args[0], XtNstring, NULL); 6535dfecf96Smrg 6545dfecf96Smrg XtSetValues(filenamewindow, args, 1); 655f14f4646Smrg /* XXX This probably should be done by the TextWidget, i.e. notice 656f14f4646Smrg * if the cursor became inivisible due to an horizontal scroll */ 657f14f4646Smrg _XawTextShowPosition((TextWidget)filenamewindow); 6585dfecf96Smrg 6595dfecf96Smrg if (XtIsManaged(XtParent(dirwindow))) 6605dfecf96Smrg SwitchDirWindow(False); 6615dfecf96Smrg 6625dfecf96Smrg line_edit = False; 6635dfecf96Smrg} 6645dfecf96Smrg 6655dfecf96Smrgstatic int 6665dfecf96Smrgcompar(_Xconst void *a, _Xconst void *b) 6675dfecf96Smrg{ 6685dfecf96Smrg return (strcmp(*(char **)a, *(char **)b)); 6695dfecf96Smrg} 6705dfecf96Smrg 6715dfecf96Smrg/*ARGSUSED*/ 6725dfecf96Smrgvoid 6735dfecf96SmrgFileCompletion(Widget w, XEvent *event, String *params, Cardinal *num_params) 6745dfecf96Smrg{ 6755dfecf96Smrg XawTextBlock block; 6765dfecf96Smrg String text; 6775dfecf96Smrg int length; 6785dfecf96Smrg char **matches, *save, *dir_name, *file_name, match[257]; 6795dfecf96Smrg unsigned n_matches, len, mlen, buflen; 6805dfecf96Smrg DIR *dir; 6815dfecf96Smrg Bool changed, slash = False, has_dot = False; 6825dfecf96Smrg#define SM_NEVER 0 6835dfecf96Smrg#define SM_HINT 1 6845dfecf96Smrg#define SM_ALWAYS 2 6855dfecf96Smrg int show_matches; 6865dfecf96Smrg 6875dfecf96Smrg text = GetString(filenamewindow); 6885dfecf96Smrg 6895dfecf96Smrg if (!text) { 6905dfecf96Smrg Feep(); 6915dfecf96Smrg return; 6925dfecf96Smrg } 6935dfecf96Smrg else if (line_edit) { 6945dfecf96Smrg Feep(); 6955dfecf96Smrg line_edit = 0; 6965dfecf96Smrg } 6975dfecf96Smrg 6985dfecf96Smrg { 6995dfecf96Smrg XawTextPosition pos = XawTextGetInsertionPoint(w); 7005dfecf96Smrg char *cslash = strchr(&text[pos], '/'), *cdot = strchr(&text[pos], '.'); 7015dfecf96Smrg 7025dfecf96Smrg if (cslash != NULL || cdot != NULL) { 7035dfecf96Smrg if (cslash != NULL && (cdot == NULL || cdot > cslash)) { 7045dfecf96Smrg length = cslash - text; 7055dfecf96Smrg slash = True; 7065dfecf96Smrg } 7075dfecf96Smrg else { 7085dfecf96Smrg length = cdot - text; 7095dfecf96Smrg has_dot = True; 7105dfecf96Smrg } 7115dfecf96Smrg } 7125dfecf96Smrg else 7135dfecf96Smrg length = strlen(text); 7145dfecf96Smrg } 7155dfecf96Smrg 7165dfecf96Smrg if (*num_params == 1 && length == strlen(text)) { 7175dfecf96Smrg switch (params[0][0]) { 7185dfecf96Smrg case 'n': /* Never */ 7195dfecf96Smrg case 'N': 7205dfecf96Smrg show_matches = SM_NEVER; 7215dfecf96Smrg break; 7225dfecf96Smrg case 'h': /* Hint */ 7235dfecf96Smrg case 'H': 7245dfecf96Smrg show_matches = SM_HINT; 7255dfecf96Smrg break; 7265dfecf96Smrg case 'a': /* Always */ 7275dfecf96Smrg case 'A': 7285dfecf96Smrg show_matches = SM_ALWAYS; 7295dfecf96Smrg break; 7305dfecf96Smrg default: 7315dfecf96Smrg show_matches = SM_NEVER; 7325dfecf96Smrg XtAppWarning(XtWidgetToApplicationContext(w), 7335dfecf96Smrg "Bad argument to file-completion, " 7345dfecf96Smrg "must be Never, Hint or Always"); 7355dfecf96Smrg break; 7365dfecf96Smrg } 7375dfecf96Smrg } 7385dfecf96Smrg else 7395dfecf96Smrg show_matches = SM_NEVER; 7405dfecf96Smrg 7415dfecf96Smrg matches = NULL; 7425dfecf96Smrg n_matches = buflen = 0; 7435dfecf96Smrg save = XtMalloc(length + 1); 7445dfecf96Smrg memmove(save, text, length); 7455dfecf96Smrg save[length] = '\0'; 7465dfecf96Smrg 7475dfecf96Smrg if (save[0] == '~' && save[1]) { 7485dfecf96Smrg char *slash2 = strchr(save, '/'); 7495dfecf96Smrg 7505dfecf96Smrg if (slash2) { 7515dfecf96Smrg struct passwd *pw; 7525dfecf96Smrg char home[BUFSIZ]; 7535dfecf96Smrg char *name; 7545dfecf96Smrg int slen = strlen(save), diff = slash2 - save; 7555dfecf96Smrg 7565dfecf96Smrg *slash2 = '\0'; 7575dfecf96Smrg name = save + 1; 7585dfecf96Smrg if (strlen(name) != 0) 7595dfecf96Smrg pw = getpwnam(name); 7605dfecf96Smrg else 7615dfecf96Smrg pw = getpwuid(getuid()); 7625dfecf96Smrg 7635dfecf96Smrg if (pw) { 7645dfecf96Smrg char fname[BUFSIZ]; 7655dfecf96Smrg int hlen; 7665dfecf96Smrg 7675dfecf96Smrg strncpy(home, pw->pw_dir, sizeof(home) - 1); 7685dfecf96Smrg home[sizeof(home) - 1] = '\0'; 7695dfecf96Smrg hlen = strlen(home); 7705dfecf96Smrg strncpy(fname, slash2 + 1, sizeof(fname) - 1); 7715dfecf96Smrg fname[sizeof(fname) - 1] = '\0'; 7725dfecf96Smrg save = XtRealloc(save, slen - diff + hlen + 2); 7735dfecf96Smrg (void)memmove(save, home, hlen); 7745dfecf96Smrg save[hlen] = '/'; 7755dfecf96Smrg strcpy(&save[hlen + 1], fname); 7765dfecf96Smrg 7775dfecf96Smrg /* expand directory */ 7785dfecf96Smrg block.length = strlen(save); 7795dfecf96Smrg block.ptr = save; 7805dfecf96Smrg block.firstPos = 0; 7815dfecf96Smrg block.format = FMT8BIT; 7825dfecf96Smrg XawTextReplace(filenamewindow, 0, length, &block); 7835dfecf96Smrg XawTextSetInsertionPoint(filenamewindow, length = block.length); 7845dfecf96Smrg } 7855dfecf96Smrg else 7865dfecf96Smrg *slash2 = '/'; 7875dfecf96Smrg } 7885dfecf96Smrg } 7895dfecf96Smrg 7905dfecf96Smrg if ((file_name = strrchr(save, '/')) != NULL) { 7915dfecf96Smrg *file_name = '\0'; 7925dfecf96Smrg ++file_name; 7935dfecf96Smrg dir_name = save; 7945dfecf96Smrg if (!file_name[0]) 7955dfecf96Smrg slash = True; 7965dfecf96Smrg if (!dir_name[0]) 7975dfecf96Smrg dir_name = "/"; 7985dfecf96Smrg } 7995dfecf96Smrg else { 8005dfecf96Smrg dir_name = "."; 8015dfecf96Smrg file_name = save; 8025dfecf96Smrg } 8035dfecf96Smrg len = strlen(file_name); 8045dfecf96Smrg 8055dfecf96Smrg if ((dir = opendir(dir_name)) != NULL) { 8065dfecf96Smrg char path[BUFSIZ], *pptr; 8075dfecf96Smrg struct dirent *ent; 8085dfecf96Smrg int isdir = 0, first = 1, bytes; 8095dfecf96Smrg 8105dfecf96Smrg XmuSnprintf(path, sizeof(path), "%s/", dir_name); 8115dfecf96Smrg pptr = path + strlen(path); 8125dfecf96Smrg bytes = sizeof(path) - (pptr - path) - 1; 8135dfecf96Smrg 8145dfecf96Smrg mlen = 0; 8155dfecf96Smrg match[0] = '\0'; 8165dfecf96Smrg while ((ent = readdir(dir)) != NULL) { 8175dfecf96Smrg unsigned d_namlen = strlen(ent->d_name); 8185dfecf96Smrg 819f14f4646Smrg if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) 820f14f4646Smrg continue; 8215dfecf96Smrg if (d_namlen >= len && strncmp(ent->d_name, file_name, len) == 0) { 8225dfecf96Smrg char *tmp = &(ent->d_name[len]), *mat = match; 8235dfecf96Smrg struct stat st; 8245dfecf96Smrg Bool is_dir = FALSE; 8255dfecf96Smrg 8265dfecf96Smrg strncpy(pptr, ent->d_name, bytes); 8275dfecf96Smrg pptr[bytes] = '\0'; 8285dfecf96Smrg if (stat(path, &st) != 0) 8295dfecf96Smrg /* Should check errno, may be a broken symbolic link 8305dfecf96Smrg * a directory with r-- permission, etc */ 8315dfecf96Smrg continue; 8325dfecf96Smrg else if (first || show_matches != SM_NEVER) { 8335dfecf96Smrg is_dir = S_ISDIR(st.st_mode); 8345dfecf96Smrg } 8355dfecf96Smrg 8365dfecf96Smrg if (first) { 8375dfecf96Smrg strncpy(match, tmp, sizeof(match) - 1); 8385dfecf96Smrg match[sizeof(match) - 2] = '\0'; 8395dfecf96Smrg mlen = strlen(match); 8405dfecf96Smrg first = 0; 8415dfecf96Smrg isdir = is_dir; 8425dfecf96Smrg } 8435dfecf96Smrg else { 8445dfecf96Smrg while (*tmp && *mat && *tmp++ == *mat) 8455dfecf96Smrg ++mat; 8465dfecf96Smrg if (mlen > mat - match) { 8475dfecf96Smrg mlen = mat - match; 8485dfecf96Smrg match[mlen] = '\0'; 8495dfecf96Smrg } 8505dfecf96Smrg } 8515dfecf96Smrg if (show_matches != SM_NEVER) { 8525dfecf96Smrg matches = (char **)XtRealloc((char*)matches, sizeof(char**) 8535dfecf96Smrg * (n_matches + 1)); 8545dfecf96Smrg buflen += d_namlen + 1; 8555dfecf96Smrg if (is_dir) { 8565dfecf96Smrg matches[n_matches] = XtMalloc(d_namlen + 2); 8575dfecf96Smrg strcpy(matches[n_matches], ent->d_name); 8585dfecf96Smrg strcat(matches[n_matches], "/"); 8595dfecf96Smrg ++buflen; 8605dfecf96Smrg } 8615dfecf96Smrg else 8625dfecf96Smrg matches[n_matches] = XtNewString(ent->d_name); 8635dfecf96Smrg } 8645dfecf96Smrg else if (mlen == 0 && n_matches >= 1) { 8655dfecf96Smrg ++n_matches; 8665dfecf96Smrg break; 8675dfecf96Smrg } 8685dfecf96Smrg ++n_matches; 8695dfecf96Smrg } 8705dfecf96Smrg } 8715dfecf96Smrg 8725dfecf96Smrg closedir(dir); 8735dfecf96Smrg changed = mlen != 0; 8745dfecf96Smrg 875f14f4646Smrg if (first || n_matches) { 8765dfecf96Smrg Bool free_matches = True, add_slash = n_matches == 1 && isdir && !slash; 8775dfecf96Smrg 8785dfecf96Smrg if (mlen && has_dot && match[mlen - 1] == '.') 8795dfecf96Smrg --mlen; 8805dfecf96Smrg 8815dfecf96Smrg if (mlen || add_slash) { 8825dfecf96Smrg XawTextPosition pos; 8835dfecf96Smrg 8845dfecf96Smrg block.firstPos = 0; 8855dfecf96Smrg block.format = FMT8BIT; 8865dfecf96Smrg if (mlen) { 8875dfecf96Smrg pos = length; 8885dfecf96Smrg block.length = mlen; 8895dfecf96Smrg block.ptr = match; 8905dfecf96Smrg XawTextReplace(filenamewindow, pos, pos, &block); 8915dfecf96Smrg XawTextSetInsertionPoint(filenamewindow, pos + block.length); 8925dfecf96Smrg } 8935dfecf96Smrg if (add_slash) { 8945dfecf96Smrg XawTextPosition actual = XawTextGetInsertionPoint(w); 8955dfecf96Smrg 8965dfecf96Smrg pos = XawTextSourceScan(XawTextGetSource(w), 0, XawstAll, 8975dfecf96Smrg XawsdRight, 1, True); 8985dfecf96Smrg block.length = 1; 8995dfecf96Smrg block.ptr = "/"; 9005dfecf96Smrg XawTextReplace(filenamewindow, pos, pos, &block); 9015dfecf96Smrg if (actual == pos) 9025dfecf96Smrg XawTextSetInsertionPoint(filenamewindow, pos + 1); 9035dfecf96Smrg } 9045dfecf96Smrg } 9055dfecf96Smrg else if (n_matches != 1 || isdir) { 9065dfecf96Smrg if (show_matches == SM_NEVER) 9075dfecf96Smrg Feep(); 9085dfecf96Smrg } 9095dfecf96Smrg 9105dfecf96Smrg if (show_matches != SM_NEVER) { 9115dfecf96Smrg if (show_matches == SM_ALWAYS || (!changed && n_matches != 1)) { 9125dfecf96Smrg char **list = NULL, *label; 9135dfecf96Smrg int n_list; 9145dfecf96Smrg Arg args[2]; 9155dfecf96Smrg 9165dfecf96Smrg XtSetArg(args[0], XtNlist, &list); 9175dfecf96Smrg XtSetArg(args[1], XtNnumberStrings, &n_list); 9185dfecf96Smrg XtGetValues(dirwindow, args, 2); 9195dfecf96Smrg 9205dfecf96Smrg matches = (char **)XtRealloc((char*)matches, sizeof(char**) 9215dfecf96Smrg * (n_matches + 2)); 9225dfecf96Smrg matches[n_matches++] = XtNewString("./"); 9235dfecf96Smrg matches[n_matches++] = XtNewString("../"); 9245dfecf96Smrg qsort(matches, n_matches, sizeof(char*), compar); 9255dfecf96Smrg XtSetArg(args[0], XtNlist, matches); 9265dfecf96Smrg XtSetArg(args[1], XtNnumberStrings, n_matches); 9275dfecf96Smrg XtSetValues(dirwindow, args, 2); 9285dfecf96Smrg if (n_list > 0 9295dfecf96Smrg && (n_list != 1 || list[0] != XtName(dirwindow))) { 9305dfecf96Smrg while (--n_list > -1) 9315dfecf96Smrg XtFree(list[n_list]); 9325dfecf96Smrg XtFree((char*)list); 9335dfecf96Smrg } 9345dfecf96Smrg 9355dfecf96Smrg label = ResolveName(dir_name); 9365dfecf96Smrg XtSetArg(args[0], XtNlabel, label); 9375dfecf96Smrg XtSetValues(dirlabel, args, 1); 9385dfecf96Smrg SwitchDirWindow(True); 9395dfecf96Smrg free_matches = False; 9405dfecf96Smrg } 9415dfecf96Smrg } 9425dfecf96Smrg if (free_matches && matches) { 9435dfecf96Smrg while (--n_matches > -1) 9445dfecf96Smrg XtFree(matches[n_matches]); 9455dfecf96Smrg XtFree((char*)matches); 9465dfecf96Smrg } 9475dfecf96Smrg } 9485dfecf96Smrg else 9495dfecf96Smrg Feep(); 9505dfecf96Smrg } 9515dfecf96Smrg else 9525dfecf96Smrg Feep(); 9535dfecf96Smrg 9545dfecf96Smrg XtFree(save); 9555dfecf96Smrg} 9565dfecf96Smrg 9575dfecf96Smrg/*ARGSUSED*/ 9585dfecf96Smrgvoid 9595dfecf96SmrgDirWindowCB(Widget w, XtPointer user_data, XtPointer call_data) 9605dfecf96Smrg{ 9615dfecf96Smrg XawListReturnStruct *file_info = (XawListReturnStruct *)call_data; 9625dfecf96Smrg char *dir_name, *string, path[BUFSIZ]; 9635dfecf96Smrg Arg args[2]; 9645dfecf96Smrg 9655dfecf96Smrg if (file_info == NULL) 9665dfecf96Smrg string = (char *)user_data; 9675dfecf96Smrg else 9685dfecf96Smrg string = file_info->string; 9695dfecf96Smrg 9705dfecf96Smrg XtSetArg(args[0], XtNlabel, &dir_name); 9715dfecf96Smrg XtGetValues(dirlabel, args, 1); 9725dfecf96Smrg if (*dir_name == '\0') { 9735dfecf96Smrg strncpy(path, string, sizeof(path) - 1); 9745dfecf96Smrg path[sizeof(path) - 1] = '\0'; 9755dfecf96Smrg } 9765dfecf96Smrg else if (strcmp(dir_name, "/") == 0) 9775dfecf96Smrg XmuSnprintf(path, sizeof(path), "/%s", string); 9785dfecf96Smrg else 9795dfecf96Smrg XmuSnprintf(path, sizeof(path), "%s/%s", dir_name, string); 9805dfecf96Smrg 9815dfecf96Smrg if (*string && string[strlen(string) - 1] == '/') { 9825dfecf96Smrg DIR *dir; 9835dfecf96Smrg 9845dfecf96Smrg if ((dir = opendir(path)) != NULL) { 9855dfecf96Smrg struct dirent *ent; 9865dfecf96Smrg struct stat st; 9875dfecf96Smrg unsigned d_namlen; 9885dfecf96Smrg Bool isdir; 9895dfecf96Smrg char **entries = NULL, **list = NULL; 9905dfecf96Smrg int n_entries = 0, n_list = 0; 9915dfecf96Smrg char *label, *pptr = path + strlen(path); 9925dfecf96Smrg int bytes = sizeof(path) - (pptr - path) - 1; 9935dfecf96Smrg 9945dfecf96Smrg while ((ent = readdir(dir)) != NULL) { 9955dfecf96Smrg d_namlen = strlen(ent->d_name); 9965dfecf96Smrg strncpy(pptr, ent->d_name, bytes); 9975dfecf96Smrg pptr[bytes] = '\0'; 9985dfecf96Smrg if (stat(path, &st) != 0) 9995dfecf96Smrg /* Should check errno, may be a broken symbolic link 10005dfecf96Smrg * a directory with r-- permission, etc */ 10015dfecf96Smrg continue; 10025dfecf96Smrg else 10035dfecf96Smrg isdir = S_ISDIR(st.st_mode); 10045dfecf96Smrg 10055dfecf96Smrg entries = (char **)XtRealloc((char*)entries, sizeof(char*) 10065dfecf96Smrg * (n_entries + 1)); 10075dfecf96Smrg if (isdir) { 10085dfecf96Smrg entries[n_entries] = XtMalloc(d_namlen + 2); 10095dfecf96Smrg strcpy(entries[n_entries], ent->d_name); 10105dfecf96Smrg strcat(entries[n_entries], "/"); 10115dfecf96Smrg } 10125dfecf96Smrg else 10135dfecf96Smrg entries[n_entries] = XtNewString(ent->d_name); 10145dfecf96Smrg ++n_entries; 10155dfecf96Smrg } 10165dfecf96Smrg closedir(dir); 10175dfecf96Smrg 10185dfecf96Smrg XtSetArg(args[0], XtNlist, &list); 10195dfecf96Smrg XtSetArg(args[1], XtNnumberStrings, &n_list); 10205dfecf96Smrg XtGetValues(dirwindow, args, 2); 10215dfecf96Smrg 10225dfecf96Smrg if (n_entries == 0) { 10235dfecf96Smrg entries = (char**)XtMalloc(sizeof(char*) * 2); 10245dfecf96Smrg /* Directory has read but not execute permission? */ 10255dfecf96Smrg entries[n_entries++] = XtNewString("./"); 10265dfecf96Smrg entries[n_entries++] = XtNewString("../"); 10275dfecf96Smrg } 10285dfecf96Smrg qsort(entries, n_entries, sizeof(char*), compar); 10295dfecf96Smrg XtSetArg(args[0], XtNlist, entries); 10305dfecf96Smrg XtSetArg(args[1], XtNnumberStrings, n_entries); 10315dfecf96Smrg XtSetValues(dirwindow, args, 2); 10325dfecf96Smrg if (n_list > 0 10335dfecf96Smrg && (n_list != 1 || list[0] != XtName(dirwindow))) { 10345dfecf96Smrg while (--n_list > -1) 10355dfecf96Smrg XtFree(list[n_list]); 10365dfecf96Smrg XtFree((char*)list); 10375dfecf96Smrg } 10385dfecf96Smrg 10395dfecf96Smrg *pptr = '\0'; 10405dfecf96Smrg if ((label = ResolveName(path)) == NULL) { 10415dfecf96Smrg Feep(); 10425dfecf96Smrg label = path; 10435dfecf96Smrg } 10445dfecf96Smrg XtSetArg(args[0], XtNlabel, label); 10455dfecf96Smrg XtSetValues(dirlabel, args, 1); 10465dfecf96Smrg 10475dfecf96Smrg strncpy(path, label, sizeof(path) - 2); 10485dfecf96Smrg if (*path && path[strlen(path) - 1] != '/') 10495dfecf96Smrg strcat(path, "/"); 10505dfecf96Smrg XtSetArg(args[0], XtNstring, path); 10515dfecf96Smrg XtSetValues(filenamewindow, args, 1); 10525dfecf96Smrg XtSetKeyboardFocus(topwindow, filenamewindow); 10535dfecf96Smrg XawTextSetInsertionPoint(filenamewindow, strlen(path)); 10545dfecf96Smrg } 10555dfecf96Smrg else 10565dfecf96Smrg Feep(); 10575dfecf96Smrg } 10585dfecf96Smrg else { 1059c05e22d7Smrg (void)ReallyDoLoad(path, ResolveName(path)); 10605dfecf96Smrg SwitchDirWindow(False); 10615dfecf96Smrg XtSetKeyboardFocus(topwindow, textwindow); 10625dfecf96Smrg } 10635dfecf96Smrg} 1064