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