commands.c revision 5dfecf96
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 705dfecf96Smrgextern Widget scratch, texts[3], labels[3]; 715dfecf96Smrgstatic Boolean double_click = FALSE; 725dfecf96Smrg 735dfecf96Smrg#define DC_UNSAVED 1 745dfecf96Smrg#define DC_LOADED 2 755dfecf96Smrg#define DC_CLOBBER 3 765dfecf96Smrg#define DC_KILL 4 775dfecf96Smrg#define DC_SAVE 5 785dfecf96Smrgstatic int dc_state; 795dfecf96Smrg 805dfecf96Smrg/* Function Name: AddDoubleClickCallback(w) 815dfecf96Smrg * Description: Adds a callback that will reset the double_click flag 825dfecf96Smrg * to false when the text is changed. 835dfecf96Smrg * Arguments: w - widget to set callback upon. 845dfecf96Smrg * state - If true add the callback, else remove it. 855dfecf96Smrg * Returns: none. 865dfecf96Smrg */ 875dfecf96Smrgstatic void 885dfecf96SmrgAddDoubleClickCallback(Widget w, Bool state) 895dfecf96Smrg{ 905dfecf96Smrg Arg args[1]; 915dfecf96Smrg static XtCallbackRec cb[] = { {NULL, NULL}, {NULL, NULL} }; 925dfecf96Smrg 935dfecf96Smrg if (XtIsSubclass(w, asciiSrcObjectClass)) { 945dfecf96Smrg if (state) 955dfecf96Smrg XtAddCallback(w, XtNcallback, ResetDC, NULL); 965dfecf96Smrg else 975dfecf96Smrg XtRemoveCallback(w, XtNcallback, ResetDC, NULL); 985dfecf96Smrg } 995dfecf96Smrg else { 1005dfecf96Smrg if (state) 1015dfecf96Smrg cb[0].callback = ResetDC; 1025dfecf96Smrg else 1035dfecf96Smrg cb[0].callback = NULL; 1045dfecf96Smrg 1055dfecf96Smrg XtSetArg(args[0], XtNcallback, cb); 1065dfecf96Smrg XtSetValues(w, args, ONE); 1075dfecf96Smrg } 1085dfecf96Smrg} 1095dfecf96Smrg 1105dfecf96Smrg/* Function Name: ResetDC 1115dfecf96Smrg * Description: Resets the double click flag. 1125dfecf96Smrg * Arguments: w - the text widget. 1135dfecf96Smrg * junk, garbage - *** NOT USED *** 1145dfecf96Smrg * Returns: none. 1155dfecf96Smrg */ 1165dfecf96Smrg 1175dfecf96Smrg/* ARGSUSED */ 1185dfecf96Smrgstatic void 1195dfecf96SmrgResetDC(Widget w, XtPointer junk, XtPointer garbage) 1205dfecf96Smrg{ 1215dfecf96Smrg double_click = FALSE; 1225dfecf96Smrg 1235dfecf96Smrg AddDoubleClickCallback(w, FALSE); 1245dfecf96Smrg} 1255dfecf96Smrg 1265dfecf96Smrg/*ARGSUSED*/ 1275dfecf96Smrgvoid 1285dfecf96SmrgQuitAction(Widget w, XEvent *event, String *params, Cardinal *num_params) 1295dfecf96Smrg{ 1305dfecf96Smrg DoQuit(w, NULL, NULL); 1315dfecf96Smrg} 1325dfecf96Smrg 1335dfecf96Smrg/*ARGSUSED*/ 1345dfecf96Smrgvoid 1355dfecf96SmrgDoQuit(Widget w, XtPointer client_data, XtPointer call_data) 1365dfecf96Smrg{ 1375dfecf96Smrg unsigned i; 1385dfecf96Smrg Bool source_changed = False; 1395dfecf96Smrg 1405dfecf96Smrg if (!double_click || (dc_state && dc_state != DC_UNSAVED)) { 1415dfecf96Smrg for (i = 0; i < flist.num_itens; i++) 1425dfecf96Smrg if (flist.itens[i]->flags & CHANGED_BIT) { 1435dfecf96Smrg source_changed = True; 1445dfecf96Smrg break; 1455dfecf96Smrg } 1465dfecf96Smrg } 1475dfecf96Smrg if(!source_changed) { 1485dfecf96Smrg#ifndef __UNIXOS2__ 1495dfecf96Smrg XeditLispCleanUp(); 1505dfecf96Smrg#endif 1515dfecf96Smrg exit(0); 1525dfecf96Smrg } 1535dfecf96Smrg 1545dfecf96Smrg XeditPrintf("Unsaved changes. Save them, or Quit again.\n"); 1555dfecf96Smrg Feep(); 1565dfecf96Smrg double_click = TRUE; 1575dfecf96Smrg dc_state = DC_UNSAVED; 1585dfecf96Smrg AddDoubleClickCallback(XawTextGetSource(textwindow), True); 1595dfecf96Smrg} 1605dfecf96Smrg 1615dfecf96Smrgstatic char * 1625dfecf96SmrgmakeBackupName(String buf, String filename, unsigned len) 1635dfecf96Smrg{ 1645dfecf96Smrg if (app_resources.backupNamePrefix 1655dfecf96Smrg && strlen(app_resources.backupNamePrefix)) { 1665dfecf96Smrg if (strchr(app_resources.backupNamePrefix, '/')) 1675dfecf96Smrg XmuSnprintf(buf, len, "%s%s%s", app_resources.backupNamePrefix, 1685dfecf96Smrg filename, app_resources.backupNameSuffix); 1695dfecf96Smrg else { 1705dfecf96Smrg char fname[BUFSIZ]; 1715dfecf96Smrg char *name, ch; 1725dfecf96Smrg 1735dfecf96Smrg strncpy(fname, filename, sizeof(fname) - 1); 1745dfecf96Smrg fname[sizeof(fname) - 1] = '\0'; 1755dfecf96Smrg if ((name = strrchr(fname, '/')) != NULL) 1765dfecf96Smrg ++name; 1775dfecf96Smrg else 1785dfecf96Smrg name = filename; 1795dfecf96Smrg ch = *name; 1805dfecf96Smrg *name = '\0'; 1815dfecf96Smrg ++name; 1825dfecf96Smrg XmuSnprintf(buf, len, "%s%s%c%s%s", 1835dfecf96Smrg fname, app_resources.backupNamePrefix, ch, name, 1845dfecf96Smrg app_resources.backupNameSuffix); 1855dfecf96Smrg } 1865dfecf96Smrg } 1875dfecf96Smrg else 1885dfecf96Smrg XmuSnprintf(buf, len, "%s%s", 1895dfecf96Smrg filename, app_resources.backupNameSuffix); 1905dfecf96Smrg 1915dfecf96Smrg return (strcmp(filename, buf) ? buf : NULL); 1925dfecf96Smrg} 1935dfecf96Smrg 1945dfecf96Smrg#if defined(USG) && !defined(CRAY) 1955dfecf96Smrgint rename (from, to) 1965dfecf96Smrg char *from, *to; 1975dfecf96Smrg{ 1985dfecf96Smrg (void) unlink (to); 1995dfecf96Smrg if (link (from, to) == 0) { 2005dfecf96Smrg unlink (from); 2015dfecf96Smrg return 0; 2025dfecf96Smrg } else { 2035dfecf96Smrg return -1; 2045dfecf96Smrg } 2055dfecf96Smrg} 2065dfecf96Smrg#endif 2075dfecf96Smrg 2085dfecf96Smrg/*ARGSUSED*/ 2095dfecf96Smrgvoid 2105dfecf96SmrgSaveFile(Widget w, XEvent *event, String *params, Cardinal *num_params) 2115dfecf96Smrg{ 2125dfecf96Smrg DoSave(w, NULL, NULL); 2135dfecf96Smrg} 2145dfecf96Smrg 2155dfecf96Smrg/*ARGSUSED*/ 2165dfecf96Smrgvoid 2175dfecf96SmrgDoSave(Widget w, XtPointer client_data, XtPointer call_data) 2185dfecf96Smrg{ 2195dfecf96Smrg String name = GetString(filenamewindow); 2205dfecf96Smrg String filename = ResolveName(name); 2215dfecf96Smrg char buf[BUFSIZ]; 2225dfecf96Smrg FileAccess file_access; 2235dfecf96Smrg xedit_flist_item *item; 2245dfecf96Smrg Boolean exists; 2255dfecf96Smrg Widget source = XawTextGetSource(textwindow); 2265dfecf96Smrg 2275dfecf96Smrg if (!filename) { 2285dfecf96Smrg XeditPrintf("Save: Can't resolve pathname -- nothing saved.\n"); 2295dfecf96Smrg Feep(); 2305dfecf96Smrg return; 2315dfecf96Smrg } 2325dfecf96Smrg else if (*name == '\0') { 2335dfecf96Smrg XeditPrintf("Save: No filename specified -- nothing saved.\n"); 2345dfecf96Smrg Feep(); 2355dfecf96Smrg return; 2365dfecf96Smrg } 2375dfecf96Smrg else { 2385dfecf96Smrg struct stat st; 2395dfecf96Smrg 2405dfecf96Smrg if (stat(filename, &st) == 0 && !S_ISREG(st.st_mode)) { 2415dfecf96Smrg XmuSnprintf(buf, sizeof(buf), 2425dfecf96Smrg "Save: file %s is not a regular file -- nothing saved.\n", 2435dfecf96Smrg name); 2445dfecf96Smrg XeditPrintf(buf); 2455dfecf96Smrg Feep(); 2465dfecf96Smrg return; 2475dfecf96Smrg } 2485dfecf96Smrg } 2495dfecf96Smrg 2505dfecf96Smrg item = FindTextSource(NULL, filename); 2515dfecf96Smrg if (item != NULL && item->source != source) { 2525dfecf96Smrg if (!double_click || (dc_state && dc_state != DC_LOADED)) { 2535dfecf96Smrg XmuSnprintf(buf, sizeof(buf), 2545dfecf96Smrg "Save: file %s is already loaded, " 2555dfecf96Smrg "Save again to unload it -- nothing saved.\n", 2565dfecf96Smrg name); 2575dfecf96Smrg XeditPrintf(buf); 2585dfecf96Smrg Feep(); 2595dfecf96Smrg double_click = TRUE; 2605dfecf96Smrg dc_state = DC_LOADED; 2615dfecf96Smrg AddDoubleClickCallback(XawTextGetSource(textwindow), True); 2625dfecf96Smrg return; 2635dfecf96Smrg } 2645dfecf96Smrg KillTextSource(item); 2655dfecf96Smrg item = FindTextSource(source = XawTextGetSource(textwindow), NULL); 2665dfecf96Smrg double_click = FALSE; 2675dfecf96Smrg dc_state = 0; 2685dfecf96Smrg } 2695dfecf96Smrg else if (item && !(item->flags & CHANGED_BIT)) { 2705dfecf96Smrg if (!double_click || (dc_state && dc_state != DC_SAVE)) { 2715dfecf96Smrg XeditPrintf("Save: No changes need to be saved, " 2725dfecf96Smrg "Save again to override.\n"); 2735dfecf96Smrg Feep(); 2745dfecf96Smrg double_click = TRUE; 2755dfecf96Smrg dc_state = DC_SAVE; 2765dfecf96Smrg AddDoubleClickCallback(XawTextGetSource(textwindow), True); 2775dfecf96Smrg return; 2785dfecf96Smrg } 2795dfecf96Smrg double_click = FALSE; 2805dfecf96Smrg dc_state = 0; 2815dfecf96Smrg } 2825dfecf96Smrg 2835dfecf96Smrg file_access = CheckFilePermissions(filename, &exists); 2845dfecf96Smrg if (!item || strcmp(item->filename, filename)) { 2855dfecf96Smrg if (file_access == WRITE_OK && exists) { 2865dfecf96Smrg if (!double_click || (dc_state && dc_state != DC_CLOBBER)) { 2875dfecf96Smrg XmuSnprintf(buf, sizeof(buf), 2885dfecf96Smrg "Save: file %s already exists, " 2895dfecf96Smrg "Save again to overwrite it -- nothing saved.\n", 2905dfecf96Smrg name); 2915dfecf96Smrg XeditPrintf(buf); 2925dfecf96Smrg Feep(); 2935dfecf96Smrg double_click = TRUE; 2945dfecf96Smrg dc_state = DC_CLOBBER; 2955dfecf96Smrg AddDoubleClickCallback(XawTextGetSource(textwindow), True); 2965dfecf96Smrg return; 2975dfecf96Smrg } 2985dfecf96Smrg double_click = FALSE; 2995dfecf96Smrg dc_state = 0; 3005dfecf96Smrg } 3015dfecf96Smrg if (!item) 3025dfecf96Smrg item = FindTextSource(source, NULL); 3035dfecf96Smrg } 3045dfecf96Smrg 3055dfecf96Smrg if (app_resources.enableBackups && exists) { 3065dfecf96Smrg char backup_file[BUFSIZ]; 3075dfecf96Smrg 3085dfecf96Smrg if (makeBackupName(backup_file, filename, sizeof(backup_file)) == NULL 3095dfecf96Smrg || rename(filename, backup_file) != 0) { 3105dfecf96Smrg XmuSnprintf(buf, sizeof(buf),"error backing up file: %s\n", 3115dfecf96Smrg filename); 3125dfecf96Smrg XeditPrintf(buf); 3135dfecf96Smrg } 3145dfecf96Smrg } 3155dfecf96Smrg 3165dfecf96Smrg switch( file_access = MaybeCreateFile(filename)) { 3175dfecf96Smrg case NO_READ: 3185dfecf96Smrg case READ_OK: 3195dfecf96Smrg XmuSnprintf(buf, sizeof(buf), 3205dfecf96Smrg "File %s could not be opened for writing.\n", name); 3215dfecf96Smrg Feep(); 3225dfecf96Smrg break; 3235dfecf96Smrg case WRITE_OK: 3245dfecf96Smrg if ( XawAsciiSaveAsFile(source, filename) ) { 3255dfecf96Smrg int i; 3265dfecf96Smrg Arg args[1]; 3275dfecf96Smrg char label_buf[BUFSIZ]; 3285dfecf96Smrg 3295dfecf96Smrg /* Keep file protection mode */ 3305dfecf96Smrg if (item && item->mode) 3315dfecf96Smrg chmod(filename, item->mode); 3325dfecf96Smrg 3335dfecf96Smrg XmuSnprintf(label_buf, sizeof(label_buf), 3345dfecf96Smrg "%s Read - Write", name); 3355dfecf96Smrg XtSetArg(args[0], XtNlabel, label_buf); 3365dfecf96Smrg for (i = 0; i < 3; i++) 3375dfecf96Smrg if (XawTextGetSource(texts[i]) == source) 3385dfecf96Smrg XtSetValues(labels[i], args, 1); 3395dfecf96Smrg 3405dfecf96Smrg XmuSnprintf(buf, sizeof(buf), "Saved file: %s\n", name); 3415dfecf96Smrg 3425dfecf96Smrg if (item && item->source != scratch) { 3435dfecf96Smrg XtSetArg(args[0], XtNlabel, filename); 3445dfecf96Smrg XtSetValues(item->sme, args, 1); 3455dfecf96Smrg 3465dfecf96Smrg XtSetArg(args[0], XtNeditType, XawtextEdit); 3475dfecf96Smrg XtSetValues(item->source, args, 1); 3485dfecf96Smrg 3495dfecf96Smrg XtFree(item->name); 3505dfecf96Smrg XtFree(item->filename); 3515dfecf96Smrg item->name = XtNewString(name); 3525dfecf96Smrg item->filename = XtNewString(filename); 3535dfecf96Smrg item->flags = EXISTS_BIT; 3545dfecf96Smrg } 3555dfecf96Smrg else { 3565dfecf96Smrg item = flist.itens[0]; 3575dfecf96Smrg XtRemoveCallback(scratch, XtNcallback, SourceChanged, 3585dfecf96Smrg (XtPointer)item); 3595dfecf96Smrg item->source = scratch = 3605dfecf96Smrg XtVaCreateWidget("textSource", 3615dfecf96Smrg multiSrcObjectClass, 3625dfecf96Smrg topwindow, 3635dfecf96Smrg XtNtype, XawAsciiFile, 3645dfecf96Smrg XtNeditType, XawtextEdit, 3655dfecf96Smrg NULL, NULL); 3665dfecf96Smrg ResetSourceChanged(item); 3675dfecf96Smrg XtAddCallback(scratch, XtNcallback, SourceChanged, 3685dfecf96Smrg (XtPointer)item); 3695dfecf96Smrg 3705dfecf96Smrg item = AddTextSource(source, name, filename, EXISTS_BIT, 3715dfecf96Smrg file_access); 3725dfecf96Smrg XtAddCallback(item->source, XtNcallback, SourceChanged, 3735dfecf96Smrg (XtPointer)item); 3745dfecf96Smrg } 3755dfecf96Smrg item->flags |= EXISTS_BIT; 3765dfecf96Smrg ResetSourceChanged(item); 3775dfecf96Smrg } 3785dfecf96Smrg else { 3795dfecf96Smrg XmuSnprintf(buf, sizeof(buf), "Error saving file: %s\n", name); 3805dfecf96Smrg Feep(); 3815dfecf96Smrg } 3825dfecf96Smrg break; 3835dfecf96Smrg default: 3845dfecf96Smrg XmuSnprintf(buf, sizeof(buf), "%s %s", 3855dfecf96Smrg "Internal function MaybeCreateFile()", 3865dfecf96Smrg "returned unexpected value.\n"); 3875dfecf96Smrg Feep(); 3885dfecf96Smrg break; 3895dfecf96Smrg } 3905dfecf96Smrg 3915dfecf96Smrg XeditPrintf(buf); 3925dfecf96Smrg} 3935dfecf96Smrg 3945dfecf96Smrg/*ARGSUSED*/ 3955dfecf96Smrgvoid 3965dfecf96SmrgDoLoad(Widget w, XtPointer client_data, XtPointer call_data) 3975dfecf96Smrg{ 3985dfecf96Smrg if (ReallyDoLoad(GetString(filenamewindow), ResolveName(NULL))) { 3995dfecf96Smrg SwitchDirWindow(False); 4005dfecf96Smrg XtSetKeyboardFocus(topwindow, textwindow); 4015dfecf96Smrg } 4025dfecf96Smrg} 4035dfecf96Smrg 4045dfecf96Smrgstatic Bool 4055dfecf96SmrgReallyDoLoad(char *name, char *filename) 4065dfecf96Smrg{ 4075dfecf96Smrg Arg args[5]; 4085dfecf96Smrg Cardinal num_args = 0; 4095dfecf96Smrg char buf[BUFSIZ]; 4105dfecf96Smrg xedit_flist_item *item; 4115dfecf96Smrg Widget source = XawTextGetSource(textwindow); 4125dfecf96Smrg 4135dfecf96Smrg if (!filename) { 4145dfecf96Smrg XeditPrintf("Load: Can't resolve pathname.\n"); 4155dfecf96Smrg Feep(); 4165dfecf96Smrg return (False); 4175dfecf96Smrg } 4185dfecf96Smrg else if (*name == '\0') { 4195dfecf96Smrg XeditPrintf("Load: No file specified.\n"); 4205dfecf96Smrg Feep(); 4215dfecf96Smrg } 4225dfecf96Smrg if ((item = FindTextSource(NULL, filename)) != NULL) { 4235dfecf96Smrg SwitchTextSource(item); 4245dfecf96Smrg return (True); 4255dfecf96Smrg } 4265dfecf96Smrg else { 4275dfecf96Smrg struct stat st; 4285dfecf96Smrg 4295dfecf96Smrg if (stat(filename, &st) == 0 && !S_ISREG(st.st_mode)) { 4305dfecf96Smrg if (S_ISDIR(st.st_mode)) { 4315dfecf96Smrg char path[BUFSIZ + 1]; 4325dfecf96Smrg 4335dfecf96Smrg strncpy(path, filename, sizeof(path) - 2); 4345dfecf96Smrg path[sizeof(path) - 2] = '\0'; 4355dfecf96Smrg if (*path) { 4365dfecf96Smrg if (path[strlen(path) - 1] != '/') 4375dfecf96Smrg strcat(path, "/"); 4385dfecf96Smrg } 4395dfecf96Smrg else 4405dfecf96Smrg strcpy(path, "./"); 4415dfecf96Smrg XtSetArg(args[0], XtNlabel, ""); 4425dfecf96Smrg XtSetValues(dirlabel, args, 1); 4435dfecf96Smrg SwitchDirWindow(True); 4445dfecf96Smrg DirWindowCB(dirwindow, path, NULL); 4455dfecf96Smrg return (False); 4465dfecf96Smrg } 4475dfecf96Smrg } 4485dfecf96Smrg } 4495dfecf96Smrg 4505dfecf96Smrg { 4515dfecf96Smrg Boolean exists; 4525dfecf96Smrg int flags; 4535dfecf96Smrg FileAccess file_access; 4545dfecf96Smrg 4555dfecf96Smrg switch( file_access = CheckFilePermissions(filename, &exists) ) { 4565dfecf96Smrg case NO_READ: 4575dfecf96Smrg if (exists) 4585dfecf96Smrg XmuSnprintf(buf, sizeof(buf), "File %s, %s", name, 4595dfecf96Smrg "exists, and could not be opened for reading.\n"); 4605dfecf96Smrg else 4615dfecf96Smrg XmuSnprintf(buf, sizeof(buf), "File %s %s %s", name, 4625dfecf96Smrg "does not exist, and", 4635dfecf96Smrg "the directory could not be opened for writing.\n"); 4645dfecf96Smrg 4655dfecf96Smrg XeditPrintf(buf); 4665dfecf96Smrg Feep(); 4675dfecf96Smrg return (False); 4685dfecf96Smrg case READ_OK: 4695dfecf96Smrg XtSetArg(args[num_args], XtNeditType, XawtextRead); num_args++; 4705dfecf96Smrg XmuSnprintf(buf, sizeof(buf), "File %s opened READ ONLY.\n", 4715dfecf96Smrg name); 4725dfecf96Smrg break; 4735dfecf96Smrg case WRITE_OK: 4745dfecf96Smrg XtSetArg(args[num_args], XtNeditType, XawtextEdit); num_args++; 4755dfecf96Smrg XmuSnprintf(buf, sizeof(buf), "File %s opened read - write.\n", 4765dfecf96Smrg name); 4775dfecf96Smrg break; 4785dfecf96Smrg default: 4795dfecf96Smrg XmuSnprintf(buf, sizeof(buf), "%s %s", 4805dfecf96Smrg "Internal function MaybeCreateFile()", 4815dfecf96Smrg "returned unexpected value.\n"); 4825dfecf96Smrg XeditPrintf(buf); 4835dfecf96Smrg Feep(); 4845dfecf96Smrg return (False); 4855dfecf96Smrg } 4865dfecf96Smrg 4875dfecf96Smrg XeditPrintf(buf); 4885dfecf96Smrg 4895dfecf96Smrg if (exists) { 4905dfecf96Smrg flags = EXISTS_BIT; 4915dfecf96Smrg XtSetArg(args[num_args], XtNstring, filename); num_args++; 4925dfecf96Smrg } 4935dfecf96Smrg else { 4945dfecf96Smrg flags = 0; 4955dfecf96Smrg XtSetArg(args[num_args], XtNstring, NULL); num_args++; 4965dfecf96Smrg } 4975dfecf96Smrg 4985dfecf96Smrg source = XtVaCreateWidget("textSource", 4995dfecf96Smrg multiSrcObjectClass, 5005dfecf96Smrg topwindow, 5015dfecf96Smrg XtNtype, XawAsciiFile, 5025dfecf96Smrg XtNeditType, XawtextEdit, 5035dfecf96Smrg NULL, NULL); 5045dfecf96Smrg XtSetValues(source, args, num_args); 5055dfecf96Smrg 5065dfecf96Smrg item = AddTextSource(source, name, filename, flags, file_access); 5075dfecf96Smrg XtAddCallback(item->source, XtNcallback, SourceChanged, 5085dfecf96Smrg (XtPointer)item); 5095dfecf96Smrg if (exists && file_access == WRITE_OK) { 5105dfecf96Smrg struct stat st; 5115dfecf96Smrg 5125dfecf96Smrg if (stat(filename, &st) == 0) 5135dfecf96Smrg item->mode = st.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); 5145dfecf96Smrg } 5155dfecf96Smrg SwitchTextSource(item); 5165dfecf96Smrg ResetSourceChanged(item); 5175dfecf96Smrg } 5185dfecf96Smrg 5195dfecf96Smrg return (True); 5205dfecf96Smrg} 5215dfecf96Smrg 5225dfecf96Smrg#ifdef INCLUDE_XPRINT_SUPPORT 5235dfecf96Smrgstatic void 5245dfecf96SmrgprintshellDestroyXtProc(Widget w, XtPointer client_data, XtPointer callData) 5255dfecf96Smrg{ 5265dfecf96Smrg XawPrintDialogClosePrinterConnection(printdialog, False); 5275dfecf96Smrg} 5285dfecf96Smrg 5295dfecf96Smrgstatic void 5305dfecf96SmrgprintOKXtProc(Widget w, XtPointer client_data, XtPointer callData) 5315dfecf96Smrg{ 5325dfecf96Smrg XawPrintDialogCallbackStruct *pdcs = (XawPrintDialogCallbackStruct *)callData; 5335dfecf96Smrg Cardinal n; 5345dfecf96Smrg Arg args[2]; 5355dfecf96Smrg Widget textsource; 5365dfecf96Smrg 5375dfecf96Smrg Log(("printOKXtProc: OK.\n")); 5385dfecf96Smrg 5395dfecf96Smrg /* Get TextSource object */ 5405dfecf96Smrg n = 0; 5415dfecf96Smrg XtSetArg(args[n], XtNtextSource, &textsource); n++; 5425dfecf96Smrg XtGetValues(textwindow, args, n); 5435dfecf96Smrg 5445dfecf96Smrg Assertion(textsource != NULL, (("printOKXtProc: textsource == NULL.\n"))); 5455dfecf96Smrg 5465dfecf96Smrg /* ||printJobNameBuffer| must live as long the print job prints 5475dfecf96Smrg * because it is used for the job title AND the page headers... */ 5485dfecf96Smrg sprintf(printJobNameBuffer, "Xedit print job"); 5495dfecf96Smrg 5505dfecf96Smrg DoPrintTextSource("Xedit", 5515dfecf96Smrg textsource, topwindow, 5525dfecf96Smrg pdcs->pdpy, pdcs->pcontext, pdcs->colorspace, 5535dfecf96Smrg printshellDestroyXtProc, 5545dfecf96Smrg printJobNameBuffer, 5555dfecf96Smrg pdcs->printToFile?pdcs->printToFileName:NULL); 5565dfecf96Smrg 5575dfecf96Smrg XtPopdown(printdialog_shell); 5585dfecf96Smrg} 5595dfecf96Smrg 5605dfecf96Smrgstatic void 5615dfecf96SmrgprintCancelXtProc(Widget w, XtPointer client_data, XtPointer callData) 5625dfecf96Smrg{ 5635dfecf96Smrg Log(("printCancelXtProc: cancel.\n")); 5645dfecf96Smrg XtPopdown(printdialog_shell); 5655dfecf96Smrg 5665dfecf96Smrg Log(("destroying print dialog shell...\n")); 5675dfecf96Smrg XtDestroyWidget(printdialog_shell); 5685dfecf96Smrg printdialog_shell = NULL; 5695dfecf96Smrg printdialog = NULL; 5705dfecf96Smrg Log(("... done\n")); 5715dfecf96Smrg} 5725dfecf96Smrg 5735dfecf96Smrg 5745dfecf96Smrg/*ARGSUSED*/ 5755dfecf96Smrgvoid 5765dfecf96SmrgPrintFile(Widget w, XEvent *event, String *params, Cardinal *num_params) 5775dfecf96Smrg{ 5785dfecf96Smrg DoPrint(w, NULL, NULL); 5795dfecf96Smrg} 5805dfecf96Smrg 5815dfecf96Smrg/*ARGSUSED*/ 5825dfecf96Smrgvoid 5835dfecf96SmrgDoPrint(Widget w, XtPointer client_data, XtPointer call_data) 5845dfecf96Smrg{ 5855dfecf96Smrg Dimension width, height; 5865dfecf96Smrg Position x, y; 5875dfecf96Smrg Widget parent = topwindow; 5885dfecf96Smrg Log(("print!\n")); 5895dfecf96Smrg 5905dfecf96Smrg if (!printdialog) { 5915dfecf96Smrg int n; 5925dfecf96Smrg Arg args[20]; 5935dfecf96Smrg 5945dfecf96Smrg n = 0; 5955dfecf96Smrg XtSetArg(args[n], XtNallowShellResize, True); n++; 5965dfecf96Smrg printdialog_shell = XtCreatePopupShell("printdialogshell", 5975dfecf96Smrg transientShellWidgetClass, 5985dfecf96Smrg topwindow, args, n); 5995dfecf96Smrg n = 0; 6005dfecf96Smrg printdialog = XtCreateManagedWidget("printdialog", printDialogWidgetClass, 6015dfecf96Smrg printdialog_shell, args, n); 6025dfecf96Smrg XtAddCallback(printdialog, XawNOkCallback, printOKXtProc, NULL); 6035dfecf96Smrg XtAddCallback(printdialog, XawNCancelCallback, printCancelXtProc, NULL); 6045dfecf96Smrg 6055dfecf96Smrg XtRealizeWidget(printdialog_shell); 6065dfecf96Smrg } 6075dfecf96Smrg 6085dfecf96Smrg /* Center dialog */ 6095dfecf96Smrg XtVaGetValues(printdialog_shell, 6105dfecf96Smrg XtNwidth, &width, 6115dfecf96Smrg XtNheight, &height, 6125dfecf96Smrg NULL); 6135dfecf96Smrg 6145dfecf96Smrg x = (Position)(XWidthOfScreen( XtScreen(parent)) - width) / 2; 6155dfecf96Smrg y = (Position)(XHeightOfScreen(XtScreen(parent)) - height) / 3; 6165dfecf96Smrg 6175dfecf96Smrg XtVaSetValues(printdialog_shell, 6185dfecf96Smrg XtNx, x, 6195dfecf96Smrg XtNy, y, 6205dfecf96Smrg NULL); 6215dfecf96Smrg 6225dfecf96Smrg XtPopup(printdialog_shell, XtGrabNonexclusive); 6235dfecf96Smrg} 6245dfecf96Smrg#endif /* INCLUDE_XPRINT_SUPPORT */ 6255dfecf96Smrg 6265dfecf96Smrg/* Function Name: SourceChanged 6275dfecf96Smrg * Description: A callback routine called when the source has changed. 6285dfecf96Smrg * Arguments: w - the text source that has changed. 6295dfecf96Smrg * client_data - xedit_flist_item associated with text buffer. 6305dfecf96Smrg * call_data - NULL is unchanged 6315dfecf96Smrg * Returns: none. 6325dfecf96Smrg */ 6335dfecf96Smrg/*ARGSUSED*/ 6345dfecf96Smrgvoid 6355dfecf96SmrgSourceChanged(Widget w, XtPointer client_data, XtPointer call_data) 6365dfecf96Smrg{ 6375dfecf96Smrg xedit_flist_item *item = (xedit_flist_item*)client_data; 6385dfecf96Smrg Bool changed = (Bool)(long)call_data; 6395dfecf96Smrg 6405dfecf96Smrg if (changed) { 6415dfecf96Smrg if (item->flags & CHANGED_BIT) 6425dfecf96Smrg return; 6435dfecf96Smrg item->flags |= CHANGED_BIT; 6445dfecf96Smrg } 6455dfecf96Smrg else { 6465dfecf96Smrg if (item->flags & CHANGED_BIT) 6475dfecf96Smrg ResetSourceChanged(item); 6485dfecf96Smrg return; 6495dfecf96Smrg } 6505dfecf96Smrg 6515dfecf96Smrg if (flist.pixmap) { 6525dfecf96Smrg Arg args[1]; 6535dfecf96Smrg Cardinal num_args; 6545dfecf96Smrg int i; 6555dfecf96Smrg 6565dfecf96Smrg num_args = 0; 6575dfecf96Smrg XtSetArg(args[num_args], XtNleftBitmap, flist.pixmap); ++num_args; 6585dfecf96Smrg XtSetValues(item->sme, args, num_args); 6595dfecf96Smrg 6605dfecf96Smrg for (i = 0; i < 3; i++) 6615dfecf96Smrg if (XawTextGetSource(texts[i]) == item->source) 6625dfecf96Smrg XtSetValues(labels[i], args, num_args); 6635dfecf96Smrg } 6645dfecf96Smrg} 6655dfecf96Smrg 6665dfecf96Smrg/* Function Name: ResetSourceChanged. 6675dfecf96Smrg * Description: Sets the source changed to FALSE, and 6685dfecf96Smrg * registers a callback to set it to TRUE when 6695dfecf96Smrg * the source has changed. 6705dfecf96Smrg * Arguments: item - item with widget to register the callback on. 6715dfecf96Smrg * Returns: none. 6725dfecf96Smrg */ 6735dfecf96Smrg 6745dfecf96Smrgvoid 6755dfecf96SmrgResetSourceChanged(xedit_flist_item *item) 6765dfecf96Smrg{ 6775dfecf96Smrg Arg args[1]; 6785dfecf96Smrg Cardinal num_args; 6795dfecf96Smrg int i; 6805dfecf96Smrg 6815dfecf96Smrg num_args = 0; 6825dfecf96Smrg XtSetArg(args[num_args], XtNleftBitmap, None); ++num_args; 6835dfecf96Smrg XtSetValues(item->sme, args, num_args); 6845dfecf96Smrg 6855dfecf96Smrg dc_state = 0; 6865dfecf96Smrg double_click = FALSE; 6875dfecf96Smrg for (i = 0; i < 3; i++) { 6885dfecf96Smrg if (XawTextGetSource(texts[i]) == item->source) 6895dfecf96Smrg XtSetValues(labels[i], args, num_args); 6905dfecf96Smrg AddDoubleClickCallback(XawTextGetSource(texts[i]), False); 6915dfecf96Smrg } 6925dfecf96Smrg 6935dfecf96Smrg num_args = 0; 6945dfecf96Smrg XtSetArg(args[num_args], XtNsourceChanged, False); ++num_args; 6955dfecf96Smrg XtSetValues(item->source, args, num_args); 6965dfecf96Smrg 6975dfecf96Smrg item->flags &= ~CHANGED_BIT; 6985dfecf96Smrg} 6995dfecf96Smrg 7005dfecf96Smrg/*ARGSUSED*/ 7015dfecf96Smrgvoid 7025dfecf96SmrgKillFile(Widget w, XEvent *event, String *params, Cardinal *num_params) 7035dfecf96Smrg{ 7045dfecf96Smrg xedit_flist_item *item = FindTextSource(XawTextGetSource(textwindow), NULL); 7055dfecf96Smrg 7065dfecf96Smrg if (item->source == scratch) { 7075dfecf96Smrg Feep(); 7085dfecf96Smrg return; 7095dfecf96Smrg } 7105dfecf96Smrg 7115dfecf96Smrg if (item->flags & CHANGED_BIT) { 7125dfecf96Smrg if (!double_click || (dc_state && dc_state != DC_KILL)) { 7135dfecf96Smrg XeditPrintf("Kill: Unsaved changes. Kill again to override.\n"); 7145dfecf96Smrg Feep(); 7155dfecf96Smrg double_click = TRUE; 7165dfecf96Smrg dc_state = DC_KILL; 7175dfecf96Smrg AddDoubleClickCallback(XawTextGetSource(textwindow), True); 7185dfecf96Smrg return; 7195dfecf96Smrg } 7205dfecf96Smrg double_click = FALSE; 7215dfecf96Smrg dc_state = 0; 7225dfecf96Smrg } 7235dfecf96Smrg KillTextSource(item); 7245dfecf96Smrg} 7255dfecf96Smrg 7265dfecf96Smrg/*ARGSUSED*/ 7275dfecf96Smrgvoid 7285dfecf96SmrgFindFile(Widget w, XEvent *event, String *params, Cardinal *num_params) 7295dfecf96Smrg{ 7305dfecf96Smrg char *string = GetString(filenamewindow); 7315dfecf96Smrg char *slash = NULL; 7325dfecf96Smrg XawTextBlock block; 7335dfecf96Smrg XawTextPosition end = XawTextSourceScan(XawTextGetSource(filenamewindow), 7345dfecf96Smrg 0, XawstAll, XawsdRight, 1, True); 7355dfecf96Smrg 7365dfecf96Smrg if (string) 7375dfecf96Smrg slash = strrchr(string, '/'); 7385dfecf96Smrg block.firstPos = 0; 7395dfecf96Smrg block.format = FMT8BIT; 7405dfecf96Smrg block.ptr = string; 7415dfecf96Smrg block.length = slash ? slash - string + 1 : 0; 7425dfecf96Smrg 7435dfecf96Smrg if (block.length != end) 7445dfecf96Smrg XawTextReplace(filenamewindow, 0, end, &block); 7455dfecf96Smrg XawTextSetInsertionPoint(filenamewindow, end); 7465dfecf96Smrg XtSetKeyboardFocus(topwindow, filenamewindow); 7475dfecf96Smrg line_edit = False; 7485dfecf96Smrg} 7495dfecf96Smrg 7505dfecf96Smrg/*ARGSUSED*/ 7515dfecf96Smrgvoid 7525dfecf96SmrgLoadFile(Widget w, XEvent *event, String *params, Cardinal *num_params) 7535dfecf96Smrg{ 7545dfecf96Smrg if (line_edit) 7555dfecf96Smrg LineEdit(textwindow); 7565dfecf96Smrg else if (ReallyDoLoad(GetString(filenamewindow), ResolveName(NULL))) { 7575dfecf96Smrg SwitchDirWindow(False); 7585dfecf96Smrg XtSetKeyboardFocus(topwindow, textwindow); 7595dfecf96Smrg } 7605dfecf96Smrg} 7615dfecf96Smrg 7625dfecf96Smrg/*ARGSUSED*/ 7635dfecf96Smrgvoid 7645dfecf96SmrgCancelFindFile(Widget w, XEvent *event, String *params, Cardinal *num_params) 7655dfecf96Smrg{ 7665dfecf96Smrg Arg args[1]; 7675dfecf96Smrg xedit_flist_item *item; 7685dfecf96Smrg 7695dfecf96Smrg XtSetKeyboardFocus(topwindow, textwindow); 7705dfecf96Smrg 7715dfecf96Smrg item = FindTextSource(XawTextGetSource(textwindow), NULL); 7725dfecf96Smrg 7735dfecf96Smrg if (item->source != scratch) 7745dfecf96Smrg XtSetArg(args[0], XtNstring, item->name); 7755dfecf96Smrg else 7765dfecf96Smrg XtSetArg(args[0], XtNstring, NULL); 7775dfecf96Smrg 7785dfecf96Smrg XtSetValues(filenamewindow, args, 1); 7795dfecf96Smrg 7805dfecf96Smrg if (XtIsManaged(XtParent(dirwindow))) 7815dfecf96Smrg SwitchDirWindow(False); 7825dfecf96Smrg 7835dfecf96Smrg line_edit = False; 7845dfecf96Smrg} 7855dfecf96Smrg 7865dfecf96Smrgstatic int 7875dfecf96Smrgcompar(_Xconst void *a, _Xconst void *b) 7885dfecf96Smrg{ 7895dfecf96Smrg return (strcmp(*(char **)a, *(char **)b)); 7905dfecf96Smrg} 7915dfecf96Smrg 7925dfecf96Smrg/*ARGSUSED*/ 7935dfecf96Smrgvoid 7945dfecf96SmrgFileCompletion(Widget w, XEvent *event, String *params, Cardinal *num_params) 7955dfecf96Smrg{ 7965dfecf96Smrg XawTextBlock block; 7975dfecf96Smrg String text; 7985dfecf96Smrg int length; 7995dfecf96Smrg char **matches, *save, *dir_name, *file_name, match[257]; 8005dfecf96Smrg unsigned n_matches, len, mlen, buflen; 8015dfecf96Smrg DIR *dir; 8025dfecf96Smrg Bool changed, slash = False, has_dot = False; 8035dfecf96Smrg#define SM_NEVER 0 8045dfecf96Smrg#define SM_HINT 1 8055dfecf96Smrg#define SM_ALWAYS 2 8065dfecf96Smrg int show_matches; 8075dfecf96Smrg 8085dfecf96Smrg text = GetString(filenamewindow); 8095dfecf96Smrg 8105dfecf96Smrg if (!text) { 8115dfecf96Smrg Feep(); 8125dfecf96Smrg return; 8135dfecf96Smrg } 8145dfecf96Smrg else if (line_edit) { 8155dfecf96Smrg Feep(); 8165dfecf96Smrg line_edit = 0; 8175dfecf96Smrg } 8185dfecf96Smrg 8195dfecf96Smrg { 8205dfecf96Smrg XawTextPosition pos = XawTextGetInsertionPoint(w); 8215dfecf96Smrg char *cslash = strchr(&text[pos], '/'), *cdot = strchr(&text[pos], '.'); 8225dfecf96Smrg 8235dfecf96Smrg if (cslash != NULL || cdot != NULL) { 8245dfecf96Smrg if (cslash != NULL && (cdot == NULL || cdot > cslash)) { 8255dfecf96Smrg length = cslash - text; 8265dfecf96Smrg slash = True; 8275dfecf96Smrg } 8285dfecf96Smrg else { 8295dfecf96Smrg length = cdot - text; 8305dfecf96Smrg has_dot = True; 8315dfecf96Smrg } 8325dfecf96Smrg } 8335dfecf96Smrg else 8345dfecf96Smrg length = strlen(text); 8355dfecf96Smrg } 8365dfecf96Smrg 8375dfecf96Smrg if (*num_params == 1 && length == strlen(text)) { 8385dfecf96Smrg switch (params[0][0]) { 8395dfecf96Smrg case 'n': /* Never */ 8405dfecf96Smrg case 'N': 8415dfecf96Smrg show_matches = SM_NEVER; 8425dfecf96Smrg break; 8435dfecf96Smrg case 'h': /* Hint */ 8445dfecf96Smrg case 'H': 8455dfecf96Smrg show_matches = SM_HINT; 8465dfecf96Smrg break; 8475dfecf96Smrg case 'a': /* Always */ 8485dfecf96Smrg case 'A': 8495dfecf96Smrg show_matches = SM_ALWAYS; 8505dfecf96Smrg break; 8515dfecf96Smrg default: 8525dfecf96Smrg show_matches = SM_NEVER; 8535dfecf96Smrg XtAppWarning(XtWidgetToApplicationContext(w), 8545dfecf96Smrg "Bad argument to file-completion, " 8555dfecf96Smrg "must be Never, Hint or Always"); 8565dfecf96Smrg break; 8575dfecf96Smrg } 8585dfecf96Smrg } 8595dfecf96Smrg else 8605dfecf96Smrg show_matches = SM_NEVER; 8615dfecf96Smrg 8625dfecf96Smrg matches = NULL; 8635dfecf96Smrg n_matches = buflen = 0; 8645dfecf96Smrg save = XtMalloc(length + 1); 8655dfecf96Smrg memmove(save, text, length); 8665dfecf96Smrg save[length] = '\0'; 8675dfecf96Smrg 8685dfecf96Smrg if (save[0] == '~' && save[1]) { 8695dfecf96Smrg char *slash2 = strchr(save, '/'); 8705dfecf96Smrg 8715dfecf96Smrg if (slash2) { 8725dfecf96Smrg struct passwd *pw; 8735dfecf96Smrg char home[BUFSIZ]; 8745dfecf96Smrg char *name; 8755dfecf96Smrg int slen = strlen(save), diff = slash2 - save; 8765dfecf96Smrg 8775dfecf96Smrg *slash2 = '\0'; 8785dfecf96Smrg name = save + 1; 8795dfecf96Smrg if (strlen(name) != 0) 8805dfecf96Smrg pw = getpwnam(name); 8815dfecf96Smrg else 8825dfecf96Smrg pw = getpwuid(getuid()); 8835dfecf96Smrg 8845dfecf96Smrg if (pw) { 8855dfecf96Smrg char fname[BUFSIZ]; 8865dfecf96Smrg int hlen; 8875dfecf96Smrg 8885dfecf96Smrg strncpy(home, pw->pw_dir, sizeof(home) - 1); 8895dfecf96Smrg home[sizeof(home) - 1] = '\0'; 8905dfecf96Smrg hlen = strlen(home); 8915dfecf96Smrg strncpy(fname, slash2 + 1, sizeof(fname) - 1); 8925dfecf96Smrg fname[sizeof(fname) - 1] = '\0'; 8935dfecf96Smrg save = XtRealloc(save, slen - diff + hlen + 2); 8945dfecf96Smrg (void)memmove(&save[hlen], slash2, slen - diff + 1); 8955dfecf96Smrg (void)memmove(save, home, hlen); 8965dfecf96Smrg save[hlen] = '/'; 8975dfecf96Smrg strcpy(&save[hlen + 1], fname); 8985dfecf96Smrg 8995dfecf96Smrg /* expand directory */ 9005dfecf96Smrg block.length = strlen(save); 9015dfecf96Smrg block.ptr = save; 9025dfecf96Smrg block.firstPos = 0; 9035dfecf96Smrg block.format = FMT8BIT; 9045dfecf96Smrg XawTextReplace(filenamewindow, 0, length, &block); 9055dfecf96Smrg XawTextSetInsertionPoint(filenamewindow, length = block.length); 9065dfecf96Smrg } 9075dfecf96Smrg else 9085dfecf96Smrg *slash2 = '/'; 9095dfecf96Smrg } 9105dfecf96Smrg } 9115dfecf96Smrg 9125dfecf96Smrg if ((file_name = strrchr(save, '/')) != NULL) { 9135dfecf96Smrg *file_name = '\0'; 9145dfecf96Smrg ++file_name; 9155dfecf96Smrg dir_name = save; 9165dfecf96Smrg if (!file_name[0]) 9175dfecf96Smrg slash = True; 9185dfecf96Smrg if (!dir_name[0]) 9195dfecf96Smrg dir_name = "/"; 9205dfecf96Smrg } 9215dfecf96Smrg else { 9225dfecf96Smrg dir_name = "."; 9235dfecf96Smrg file_name = save; 9245dfecf96Smrg } 9255dfecf96Smrg len = strlen(file_name); 9265dfecf96Smrg 9275dfecf96Smrg if ((dir = opendir(dir_name)) != NULL) { 9285dfecf96Smrg char path[BUFSIZ], *pptr; 9295dfecf96Smrg struct dirent *ent; 9305dfecf96Smrg int isdir = 0, first = 1, bytes; 9315dfecf96Smrg 9325dfecf96Smrg XmuSnprintf(path, sizeof(path), "%s/", dir_name); 9335dfecf96Smrg pptr = path + strlen(path); 9345dfecf96Smrg bytes = sizeof(path) - (pptr - path) - 1; 9355dfecf96Smrg 9365dfecf96Smrg mlen = 0; 9375dfecf96Smrg match[0] = '\0'; 9385dfecf96Smrg (void)readdir(dir); /* "." */ 9395dfecf96Smrg (void)readdir(dir); /* ".." */ 9405dfecf96Smrg while ((ent = readdir(dir)) != NULL) { 9415dfecf96Smrg unsigned d_namlen = strlen(ent->d_name); 9425dfecf96Smrg 9435dfecf96Smrg if (d_namlen >= len && strncmp(ent->d_name, file_name, len) == 0) { 9445dfecf96Smrg char *tmp = &(ent->d_name[len]), *mat = match; 9455dfecf96Smrg struct stat st; 9465dfecf96Smrg Bool is_dir = FALSE; 9475dfecf96Smrg 9485dfecf96Smrg strncpy(pptr, ent->d_name, bytes); 9495dfecf96Smrg pptr[bytes] = '\0'; 9505dfecf96Smrg if (stat(path, &st) != 0) 9515dfecf96Smrg /* Should check errno, may be a broken symbolic link 9525dfecf96Smrg * a directory with r-- permission, etc */ 9535dfecf96Smrg continue; 9545dfecf96Smrg else if (first || show_matches != SM_NEVER) { 9555dfecf96Smrg is_dir = S_ISDIR(st.st_mode); 9565dfecf96Smrg } 9575dfecf96Smrg 9585dfecf96Smrg if (first) { 9595dfecf96Smrg strncpy(match, tmp, sizeof(match) - 1); 9605dfecf96Smrg match[sizeof(match) - 2] = '\0'; 9615dfecf96Smrg mlen = strlen(match); 9625dfecf96Smrg first = 0; 9635dfecf96Smrg isdir = is_dir; 9645dfecf96Smrg } 9655dfecf96Smrg else { 9665dfecf96Smrg while (*tmp && *mat && *tmp++ == *mat) 9675dfecf96Smrg ++mat; 9685dfecf96Smrg if (mlen > mat - match) { 9695dfecf96Smrg mlen = mat - match; 9705dfecf96Smrg match[mlen] = '\0'; 9715dfecf96Smrg } 9725dfecf96Smrg } 9735dfecf96Smrg if (show_matches != SM_NEVER) { 9745dfecf96Smrg matches = (char **)XtRealloc((char*)matches, sizeof(char**) 9755dfecf96Smrg * (n_matches + 1)); 9765dfecf96Smrg buflen += d_namlen + 1; 9775dfecf96Smrg if (is_dir) { 9785dfecf96Smrg matches[n_matches] = XtMalloc(d_namlen + 2); 9795dfecf96Smrg strcpy(matches[n_matches], ent->d_name); 9805dfecf96Smrg strcat(matches[n_matches], "/"); 9815dfecf96Smrg ++buflen; 9825dfecf96Smrg } 9835dfecf96Smrg else 9845dfecf96Smrg matches[n_matches] = XtNewString(ent->d_name); 9855dfecf96Smrg } 9865dfecf96Smrg else if (mlen == 0 && n_matches >= 1) { 9875dfecf96Smrg ++n_matches; 9885dfecf96Smrg break; 9895dfecf96Smrg } 9905dfecf96Smrg ++n_matches; 9915dfecf96Smrg } 9925dfecf96Smrg } 9935dfecf96Smrg 9945dfecf96Smrg closedir(dir); 9955dfecf96Smrg changed = mlen != 0; 9965dfecf96Smrg 9975dfecf96Smrg if (n_matches) { 9985dfecf96Smrg Bool free_matches = True, add_slash = n_matches == 1 && isdir && !slash; 9995dfecf96Smrg 10005dfecf96Smrg if (mlen && has_dot && match[mlen - 1] == '.') 10015dfecf96Smrg --mlen; 10025dfecf96Smrg 10035dfecf96Smrg if (mlen || add_slash) { 10045dfecf96Smrg XawTextPosition pos; 10055dfecf96Smrg 10065dfecf96Smrg block.firstPos = 0; 10075dfecf96Smrg block.format = FMT8BIT; 10085dfecf96Smrg if (mlen) { 10095dfecf96Smrg pos = length; 10105dfecf96Smrg block.length = mlen; 10115dfecf96Smrg block.ptr = match; 10125dfecf96Smrg XawTextReplace(filenamewindow, pos, pos, &block); 10135dfecf96Smrg XawTextSetInsertionPoint(filenamewindow, pos + block.length); 10145dfecf96Smrg } 10155dfecf96Smrg if (add_slash) { 10165dfecf96Smrg XawTextPosition actual = XawTextGetInsertionPoint(w); 10175dfecf96Smrg 10185dfecf96Smrg pos = XawTextSourceScan(XawTextGetSource(w), 0, XawstAll, 10195dfecf96Smrg XawsdRight, 1, True); 10205dfecf96Smrg block.length = 1; 10215dfecf96Smrg block.ptr = "/"; 10225dfecf96Smrg XawTextReplace(filenamewindow, pos, pos, &block); 10235dfecf96Smrg if (actual == pos) 10245dfecf96Smrg XawTextSetInsertionPoint(filenamewindow, pos + 1); 10255dfecf96Smrg } 10265dfecf96Smrg } 10275dfecf96Smrg else if (n_matches != 1 || isdir) { 10285dfecf96Smrg if (show_matches == SM_NEVER) 10295dfecf96Smrg Feep(); 10305dfecf96Smrg } 10315dfecf96Smrg 10325dfecf96Smrg if (show_matches != SM_NEVER) { 10335dfecf96Smrg if (show_matches == SM_ALWAYS || (!changed && n_matches != 1)) { 10345dfecf96Smrg char **list = NULL, *label; 10355dfecf96Smrg int n_list; 10365dfecf96Smrg Arg args[2]; 10375dfecf96Smrg 10385dfecf96Smrg XtSetArg(args[0], XtNlist, &list); 10395dfecf96Smrg XtSetArg(args[1], XtNnumberStrings, &n_list); 10405dfecf96Smrg XtGetValues(dirwindow, args, 2); 10415dfecf96Smrg 10425dfecf96Smrg matches = (char **)XtRealloc((char*)matches, sizeof(char**) 10435dfecf96Smrg * (n_matches + 2)); 10445dfecf96Smrg matches[n_matches++] = XtNewString("./"); 10455dfecf96Smrg matches[n_matches++] = XtNewString("../"); 10465dfecf96Smrg qsort(matches, n_matches, sizeof(char*), compar); 10475dfecf96Smrg XtSetArg(args[0], XtNlist, matches); 10485dfecf96Smrg XtSetArg(args[1], XtNnumberStrings, n_matches); 10495dfecf96Smrg XtSetValues(dirwindow, args, 2); 10505dfecf96Smrg if (n_list > 0 10515dfecf96Smrg && (n_list != 1 || list[0] != XtName(dirwindow))) { 10525dfecf96Smrg while (--n_list > -1) 10535dfecf96Smrg XtFree(list[n_list]); 10545dfecf96Smrg XtFree((char*)list); 10555dfecf96Smrg } 10565dfecf96Smrg 10575dfecf96Smrg label = ResolveName(dir_name); 10585dfecf96Smrg XtSetArg(args[0], XtNlabel, label); 10595dfecf96Smrg XtSetValues(dirlabel, args, 1); 10605dfecf96Smrg SwitchDirWindow(True); 10615dfecf96Smrg free_matches = False; 10625dfecf96Smrg } 10635dfecf96Smrg } 10645dfecf96Smrg if (free_matches && matches) { 10655dfecf96Smrg while (--n_matches > -1) 10665dfecf96Smrg XtFree(matches[n_matches]); 10675dfecf96Smrg XtFree((char*)matches); 10685dfecf96Smrg } 10695dfecf96Smrg } 10705dfecf96Smrg else 10715dfecf96Smrg Feep(); 10725dfecf96Smrg } 10735dfecf96Smrg else 10745dfecf96Smrg Feep(); 10755dfecf96Smrg 10765dfecf96Smrg XtFree(save); 10775dfecf96Smrg} 10785dfecf96Smrg 10795dfecf96Smrg/*ARGSUSED*/ 10805dfecf96Smrgvoid 10815dfecf96SmrgDirWindowCB(Widget w, XtPointer user_data, XtPointer call_data) 10825dfecf96Smrg{ 10835dfecf96Smrg XawListReturnStruct *file_info = (XawListReturnStruct *)call_data; 10845dfecf96Smrg char *dir_name, *string, path[BUFSIZ]; 10855dfecf96Smrg Arg args[2]; 10865dfecf96Smrg 10875dfecf96Smrg if (file_info == NULL) 10885dfecf96Smrg string = (char *)user_data; 10895dfecf96Smrg else 10905dfecf96Smrg string = file_info->string; 10915dfecf96Smrg 10925dfecf96Smrg XtSetArg(args[0], XtNlabel, &dir_name); 10935dfecf96Smrg XtGetValues(dirlabel, args, 1); 10945dfecf96Smrg if (*dir_name == '\0') { 10955dfecf96Smrg strncpy(path, string, sizeof(path) - 1); 10965dfecf96Smrg path[sizeof(path) - 1] = '\0'; 10975dfecf96Smrg } 10985dfecf96Smrg else if (strcmp(dir_name, "/") == 0) 10995dfecf96Smrg XmuSnprintf(path, sizeof(path), "/%s", string); 11005dfecf96Smrg else 11015dfecf96Smrg XmuSnprintf(path, sizeof(path), "%s/%s", dir_name, string); 11025dfecf96Smrg 11035dfecf96Smrg if (*string && string[strlen(string) - 1] == '/') { 11045dfecf96Smrg DIR *dir; 11055dfecf96Smrg 11065dfecf96Smrg if ((dir = opendir(path)) != NULL) { 11075dfecf96Smrg struct dirent *ent; 11085dfecf96Smrg struct stat st; 11095dfecf96Smrg unsigned d_namlen; 11105dfecf96Smrg Bool isdir; 11115dfecf96Smrg char **entries = NULL, **list = NULL; 11125dfecf96Smrg int n_entries = 0, n_list = 0; 11135dfecf96Smrg char *label, *pptr = path + strlen(path); 11145dfecf96Smrg int bytes = sizeof(path) - (pptr - path) - 1; 11155dfecf96Smrg 11165dfecf96Smrg while ((ent = readdir(dir)) != NULL) { 11175dfecf96Smrg d_namlen = strlen(ent->d_name); 11185dfecf96Smrg strncpy(pptr, ent->d_name, bytes); 11195dfecf96Smrg pptr[bytes] = '\0'; 11205dfecf96Smrg if (stat(path, &st) != 0) 11215dfecf96Smrg /* Should check errno, may be a broken symbolic link 11225dfecf96Smrg * a directory with r-- permission, etc */ 11235dfecf96Smrg continue; 11245dfecf96Smrg else 11255dfecf96Smrg isdir = S_ISDIR(st.st_mode); 11265dfecf96Smrg 11275dfecf96Smrg entries = (char **)XtRealloc((char*)entries, sizeof(char*) 11285dfecf96Smrg * (n_entries + 1)); 11295dfecf96Smrg if (isdir) { 11305dfecf96Smrg entries[n_entries] = XtMalloc(d_namlen + 2); 11315dfecf96Smrg strcpy(entries[n_entries], ent->d_name); 11325dfecf96Smrg strcat(entries[n_entries], "/"); 11335dfecf96Smrg } 11345dfecf96Smrg else 11355dfecf96Smrg entries[n_entries] = XtNewString(ent->d_name); 11365dfecf96Smrg ++n_entries; 11375dfecf96Smrg } 11385dfecf96Smrg closedir(dir); 11395dfecf96Smrg 11405dfecf96Smrg XtSetArg(args[0], XtNlist, &list); 11415dfecf96Smrg XtSetArg(args[1], XtNnumberStrings, &n_list); 11425dfecf96Smrg XtGetValues(dirwindow, args, 2); 11435dfecf96Smrg 11445dfecf96Smrg if (n_entries == 0) { 11455dfecf96Smrg entries = (char**)XtMalloc(sizeof(char*) * 2); 11465dfecf96Smrg /* Directory has read but not execute permission? */ 11475dfecf96Smrg entries[n_entries++] = XtNewString("./"); 11485dfecf96Smrg entries[n_entries++] = XtNewString("../"); 11495dfecf96Smrg } 11505dfecf96Smrg qsort(entries, n_entries, sizeof(char*), compar); 11515dfecf96Smrg XtSetArg(args[0], XtNlist, entries); 11525dfecf96Smrg XtSetArg(args[1], XtNnumberStrings, n_entries); 11535dfecf96Smrg XtSetValues(dirwindow, args, 2); 11545dfecf96Smrg if (n_list > 0 11555dfecf96Smrg && (n_list != 1 || list[0] != XtName(dirwindow))) { 11565dfecf96Smrg while (--n_list > -1) 11575dfecf96Smrg XtFree(list[n_list]); 11585dfecf96Smrg XtFree((char*)list); 11595dfecf96Smrg } 11605dfecf96Smrg 11615dfecf96Smrg *pptr = '\0'; 11625dfecf96Smrg if ((label = ResolveName(path)) == NULL) { 11635dfecf96Smrg Feep(); 11645dfecf96Smrg label = path; 11655dfecf96Smrg } 11665dfecf96Smrg XtSetArg(args[0], XtNlabel, label); 11675dfecf96Smrg XtSetValues(dirlabel, args, 1); 11685dfecf96Smrg 11695dfecf96Smrg strncpy(path, label, sizeof(path) - 2); 11705dfecf96Smrg if (*path && path[strlen(path) - 1] != '/') 11715dfecf96Smrg strcat(path, "/"); 11725dfecf96Smrg XtSetArg(args[0], XtNstring, path); 11735dfecf96Smrg XtSetValues(filenamewindow, args, 1); 11745dfecf96Smrg XtSetKeyboardFocus(topwindow, filenamewindow); 11755dfecf96Smrg XawTextSetInsertionPoint(filenamewindow, strlen(path)); 11765dfecf96Smrg } 11775dfecf96Smrg else 11785dfecf96Smrg Feep(); 11795dfecf96Smrg } 11805dfecf96Smrg else { 11815dfecf96Smrg (void)ReallyDoLoad(path, path); 11825dfecf96Smrg SwitchDirWindow(False); 11835dfecf96Smrg XtSetKeyboardFocus(topwindow, textwindow); 11845dfecf96Smrg } 11855dfecf96Smrg} 1186