40
static file_format fmt = NIX_FILE;
41
/* The format of the current file. */
43
/* What happens when there is no file to open? aiee! */
46
fileage = make_new_node(NULL);
47
fileage->data = mallocstrcpy(NULL, "");
57
if (!ISSET(NO_COLOR_SYNTAX))
38
/* Add an entry to the openfile openfilestruct. This should only be
39
* called from open_buffer(). */
40
void make_new_buffer(void)
42
/* If there are no entries in openfile, make the first one and
44
if (openfile == NULL) {
45
openfile = make_new_opennode();
46
splice_opennode(openfile, openfile, openfile);
47
/* Otherwise, make a new entry for openfile, splice it in after
48
* the current entry, and move to it. */
50
splice_opennode(openfile, make_new_opennode(), openfile->next);
51
openfile = openfile->next;
54
/* Initialize the new buffer. */
58
/* Initialize the current entry of the openfile openfilestruct. */
59
void initialize_buffer(void)
61
assert(openfile != NULL);
63
openfile->filename = mallocstrcpy(NULL, "");
65
initialize_buffer_text();
67
openfile->current_x = 0;
68
openfile->placewewant = 0;
69
openfile->current_y = 0;
71
openfile->modified = FALSE;
73
openfile->mark_set = FALSE;
75
openfile->mark_begin = NULL;
76
openfile->mark_begin_x = 0;
78
openfile->fmt = NIX_FILE;
80
openfile->current_stat = NULL;
83
openfile->colorstrings = NULL;
87
/* Initialize the text of the current entry of the openfile
89
void initialize_buffer_text(void)
91
assert(openfile != NULL);
93
openfile->fileage = make_new_node(NULL);
94
openfile->fileage->data = mallocstrcpy(NULL, "");
96
openfile->filebot = openfile->fileage;
97
openfile->edittop = openfile->fileage;
98
openfile->current = openfile->fileage;
100
openfile->totsize = 0;
103
/* If it's not "", filename is a file to open. We make a new buffer, if
104
* necessary, and then open and read the file, if applicable. */
105
void open_buffer(const char *filename)
107
bool new_buffer = (openfile == NULL
108
#ifdef ENABLE_MULTIBUFFER
109
|| ISSET(MULTIBUFFER)
112
/* Whether we load into this buffer or a new one. */
115
/* rc == -2 means that we have a new file. -1 means that the
116
* open() failed. 0 means that the open() succeeded. */
118
assert(filename != NULL);
120
#ifndef DISABLE_OPERATINGDIR
121
if (check_operating_dir(filename, FALSE)) {
122
statusbar(_("Can't insert file from outside of %s"),
128
/* If the filename isn't blank, open the file. Otherwise, treat it
130
rc = (filename[0] != '\0') ? open_file(filename, new_buffer, &f) :
133
/* If we're loading into a new buffer, add a new entry to
138
/* If we have a file and we're loading into a new buffer, update the
140
if (rc != -1 && new_buffer)
141
openfile->filename = mallocstrcpy(openfile->filename, filename);
143
/* If we have a non-new file, read it in. Then, if the buffer has
144
* no stat, update the stat, if applicable. */
146
read_file(f, filename);
148
if (openfile->current_stat == NULL) {
149
openfile->current_stat =
150
(struct stat *)nmalloc(sizeof(struct stat));
151
stat(filename, openfile->current_stat);
156
/* If we have a file and we're loading into a new buffer, move back
157
* to the first line of the buffer. */
158
if (rc != -1 && new_buffer)
159
openfile->current = openfile->fileage;
162
/* If we're loading into a new buffer, update the colors to account
163
* for it, if applicable. */
169
/* Update the screen to account for the current buffer. */
170
void display_buffer(void)
172
/* Update the titlebar, since the filename may have changed. */
176
/* Make sure we're using the buffer's associated colors, if
181
/* Update the edit window. */
185
#ifdef ENABLE_MULTIBUFFER
186
/* Switch to the next file buffer if next_buf is TRUE. Otherwise,
187
* switch to the previous file buffer. */
188
void switch_to_prevnext_buffer(bool next_buf)
190
assert(openfile != NULL);
192
/* If only one file buffer is open, indicate it on the statusbar and
194
if (openfile == openfile->next) {
195
statusbar(_("No more open file buffers"));
199
/* Switch to the next or previous file buffer, depending on the
200
* value of next_buf. */
201
openfile = next_buf ? openfile->next : openfile->prev;
204
fprintf(stderr, "filename is %s\n", openfile->filename);
207
/* Update the screen to account for the current buffer. */
210
/* Indicate the switch on the statusbar. */
211
statusbar(_("Switched to %s"),
212
((openfile->filename[0] == '\0') ? _("New Buffer") :
213
openfile->filename));
216
dump_filestruct(openfile->current);
220
/* Switch to the previous entry in the openfile filebuffer. */
221
void switch_to_prev_buffer_void(void)
223
switch_to_prevnext_buffer(FALSE);
226
/* Switch to the next entry in the openfile filebuffer. */
227
void switch_to_next_buffer_void(void)
229
switch_to_prevnext_buffer(TRUE);
232
/* Delete an entry from the openfile filebuffer, and switch to the one
233
* after it. Return TRUE on success, or FALSE if there are no more open
235
bool close_buffer(void)
237
assert(openfile != NULL);
239
/* If only one file buffer is open, get out. */
240
if (openfile == openfile->next)
243
/* Switch to the next file buffer. */
244
switch_to_next_buffer_void();
246
/* Close the file buffer we had open before. */
247
unlink_opennode(openfile->prev);
253
#endif /* ENABLE_MULTIBUFFER */
62
255
/* We make a new line of text from buf. buf is length buf_len. If
63
256
* first_line_ins is TRUE, then we put the new line at the top of the
413
void execute_command(const char *command)
415
#ifdef ENABLE_MULTIBUFFER
416
if (ISSET(MULTIBUFFER)) {
417
/* Update the current entry in the open_files structure. */
423
#endif /* ENABLE_MULTIBUFFER */
425
#ifdef ENABLE_MULTIBUFFER
426
/* Add this new entry to the open_files structure. */
427
if (ISSET(MULTIBUFFER))
429
#endif /* ENABLE_MULTIBUFFER */
431
#endif /* !NANO_SMALL */
433
/* name is a file name to open. We make a new buffer if necessary, then
434
* open and read the file. */
435
void load_buffer(const char *name)
437
bool new_buffer = (fileage == NULL
438
#ifdef ENABLE_MULTIBUFFER
439
|| ISSET(MULTIBUFFER)
442
/* new_buffer says whether we load into this buffer or a new
443
* one. If new_buffer is TRUE, we display "New File" if the
444
* file is not found, and if it is found we set filename and add
445
* a new open_files entry. */
448
/* rc == -2 means that the statusbar displayed "New File". -1
449
* means that the open failed. 0 means success. */
451
#ifndef DISABLE_OPERATINGDIR
452
if (check_operating_dir(name, FALSE)) {
453
statusbar(_("Can't insert file from outside of %s"),
459
#ifdef ENABLE_MULTIBUFFER
460
/* Update the current entry in the open_files structure. */
464
rc = open_file(name, new_buffer, &f);
466
#ifdef ENABLE_MULTIBUFFER
467
if (rc != -1 && ISSET(MULTIBUFFER)) {
475
if (rc != -1 && new_buffer) {
476
filename = mallocstrcpy(filename, name);
481
file_format fmt_save = fmt;
483
read_file(f, filename);
485
/* If we're not loading into a new buffer, preserve the file
491
stat(filename, &originalfilestat);
495
/* Add this new entry to the open_files structure if we have
496
* multibuffer support, or to the main filestruct if we don't. */
497
if (rc != -1 && new_buffer)
501
576
void do_insertfile(
502
577
#ifndef NANO_SMALL
714
795
display_main_list();
717
#ifdef ENABLE_MULTIBUFFER
718
/* Create a new openfilestruct node. */
719
openfilestruct *make_new_opennode(void)
721
openfilestruct *newnode =
722
(openfilestruct *)nmalloc(sizeof(openfilestruct));
723
newnode->filename = NULL;
728
/* Splice a node into an existing openfilestruct. */
729
void splice_opennode(openfilestruct *begin, openfilestruct *newnode,
732
assert(newnode != NULL && begin != NULL);
735
newnode->prev = begin;
736
begin->next = newnode;
741
/* Unlink a node from the rest of the openfilestruct, and delete it. */
742
void unlink_opennode(openfilestruct *fileptr)
744
assert(fileptr != NULL && fileptr->prev != NULL && fileptr->next != NULL && fileptr != fileptr->prev && fileptr != fileptr->next);
746
fileptr->prev->next = fileptr->next;
747
fileptr->next->prev = fileptr->prev;
748
delete_opennode(fileptr);
751
/* Delete a node from the openfilestruct. */
752
void delete_opennode(openfilestruct *fileptr)
754
assert(fileptr != NULL && fileptr->filename != NULL && fileptr->fileage != NULL);
756
free(fileptr->filename);
757
free_filestruct(fileptr->fileage);
762
/* Deallocate all memory associated with this and later files, including
763
* the lines of text. */
764
void free_openfilestruct(openfilestruct *src)
768
while (src != src->next) {
770
delete_opennode(src->prev);
772
delete_opennode(src);
776
/* Add/update an entry to the open_files openfilestruct. If update is
777
* FALSE, a new entry is created; otherwise, the current entry is
779
void add_open_file(bool update)
781
if (update && open_files == NULL)
784
/* If there are no entries in open_files, make the first one. */
785
if (open_files == NULL) {
786
open_files = make_new_opennode();
787
splice_opennode(open_files, open_files, open_files);
788
/* Otherwise, if we're not updating, make a new entry for
789
* open_files and splice it in after the current entry. */
790
} else if (!update) {
791
splice_opennode(open_files, make_new_opennode(),
793
open_files = open_files->next;
796
/* Save the current filename. */
797
open_files->filename = mallocstrcpy(open_files->filename, filename);
800
/* Save the current file's stat. */
801
open_files->originalfilestat = originalfilestat;
804
/* Save the current file buffer. */
805
open_files->fileage = fileage;
806
open_files->filebot = filebot;
808
/* Save the current top of the edit window. */
809
open_files->edittop = edittop;
811
/* Save the current line. */
812
open_files->current = current;
814
/* Save the current cursor position. */
815
open_files->current_x = current_x;
817
/* Save the current place we want. */
818
open_files->placewewant = placewewant;
820
/* Save the current total number of lines. */
821
open_files->totlines = totlines;
823
/* Save the current total size. */
824
open_files->totsize = totsize;
826
/* Start with no flags saved. */
827
open_files->flags = 0;
829
/* Save the current modification status. */
831
open_files->flags |= MODIFIED;
834
/* Save the current marking status and mark, if applicable. */
835
if (ISSET(MARK_ISSET)) {
836
open_files->flags |= MARK_ISSET;
837
open_files->mark_beginbuf = mark_beginbuf;
838
open_files->mark_beginx = mark_beginx;
841
/* Save the current file format. */
842
open_files->fmt = fmt;
846
fprintf(stderr, "filename is %s\n", open_files->filename);
850
/* Read the current entry in the open_files structure and set up the
851
* currently open file buffer using that entry's information. */
852
void load_open_file(void)
854
assert(open_files != NULL);
856
/* Restore the current filename. */
857
filename = mallocstrcpy(filename, open_files->filename);
860
/* Restore the current file's stat. */
861
originalfilestat = open_files->originalfilestat;
864
/* Restore the current file buffer. */
865
fileage = open_files->fileage;
866
filebot = open_files->filebot;
868
/* Restore the current top of the edit window. */
869
edittop = open_files->edittop;
871
/* Restore the current line. */
872
current = open_files->current;
874
/* Restore the current cursor position. */
875
current_x = open_files->current_x;
877
/* Restore the current place we want. */
878
placewewant = open_files->placewewant;
880
/* Restore the current total number of lines. */
881
totlines = open_files->totlines;
883
/* Restore the current total size. */
884
totsize = open_files->totsize;
886
/* Restore the current modification status. */
887
if (open_files->flags & MODIFIED)
893
/* Restore the current marking status and mark, if applicable. */
894
if (open_files->flags & MARK_ISSET) {
895
mark_beginbuf = open_files->mark_beginbuf;
896
mark_beginx = open_files->mark_beginx;
901
/* Restore the current file format. */
902
fmt = open_files->fmt;
910
/* Update the titlebar. */
914
/* Open either the next or previous file buffer. */
915
void open_prevnext_file(bool next_file)
917
assert(open_files != NULL);
921
/* If only one file buffer is open, indicate it on the statusbar and
923
if (open_files == open_files->next) {
924
statusbar(_("No more open file buffers"));
928
/* Switch to the next or previous file, depending on the value of
930
open_files = next_file ? open_files->next : open_files->prev;
933
fprintf(stderr, "filename is %s\n", open_files->filename);
936
/* Load the file we switched to. */
939
/* And indicate the switch on the statusbar. */
940
statusbar(_("Switched to %s"),
941
((open_files->filename[0] == '\0') ? _("New Buffer") :
942
open_files->filename));
945
dump_buffer(current);
949
/* Open the previous entry in the open_files structure. This function
950
* is used by the shortcut list. */
951
void open_prevfile_void(void)
953
open_prevnext_file(FALSE);
956
/* Open the next entry in the open_files structure. This function is
957
* used by the shortcut list. */
958
void open_nextfile_void(void)
960
open_prevnext_file(TRUE);
963
/* Delete an entry from the open_files filestruct. After deletion of an
964
* entry, the next entry is opened. Return TRUE on success or FALSE if
965
* there are no more open file buffers. */
966
bool close_open_file(void)
968
assert(open_files != NULL);
970
/* If only one file is open, get out. */
971
if (open_files == open_files->next)
974
/* Open the next file. */
975
open_nextfile_void();
977
/* Close the file we had open before. */
978
unlink_opennode(open_files->prev);
980
/* Reinitialize the shortcut list. */
981
shortcut_init(FALSE);
986
#endif /* ENABLE_MULTIBUFFER */
988
798
/* When passed "[relative path]" or "[relative path][filename]" in
989
799
* origpath, return "[full path]" or "[full path][filename]" on success,
990
800
* or NULL on error. Do this if the file doesn't exist but the relative
1314
1124
/* Write a file out. If f_open isn't NULL, we assume that it is a
1315
1125
* stream associated with the file, and we don't try to open it
1316
1126
* ourselves. If tmp is TRUE, we set the umask to disallow anyone else
1317
* from accessing the file, we don't set the global variable filename to
1318
* its name, and we don't print out how many lines we wrote on the
1127
* from accessing the file, we don't set the filename to its name, and
1128
* we don't print out how many lines we wrote on the statusbar.
1321
1130
* tmp means we are writing a temporary file in a secure fashion. We
1322
1131
* use it when spell checking or dumping the file on an error.
1324
* append == 1 means we are appending instead of overwriting.
1325
* append == 2 means we are prepending instead of overwriting.
1133
* append == APPEND means we are appending instead of overwriting.
1134
* append == PREPEND means we are prepending instead of overwriting.
1327
1136
* nonamechange means don't change the current filename. It is ignored
1328
1137
* if tmp is FALSE or if we're appending/prepending.
1330
1139
* Return 0 on success or -1 on error. */
1331
int write_file(const char *name, FILE *f_open, bool tmp, int append,
1140
int write_file(const char *name, FILE *f_open, bool tmp, append_type
1141
append, bool nonamechange)
1334
1143
int retval = -1;
1335
1144
/* Instead of returning in this function, you should always
1336
1145
* merely set retval and then goto cleanup_and_exit. */
1337
1146
size_t lineswritten = 0;
1338
const filestruct *fileptr = fileage;
1147
const filestruct *fileptr = openfile->fileage;
1340
1149
/* The file descriptor we use. */
1341
1150
mode_t original_umask = 0;
1763
1583
int do_writeout(bool exiting)
1766
int retval = 0, append = 0;
1586
append_type append = OVERWRITE;
1768
1588
/* The last answer the user typed on the statusbar. */
1769
1589
#ifdef NANO_EXTRA
1770
static bool did_cred = FALSE;
1590
static bool did_credits = FALSE;
1773
1593
currshortcut = writefile_list;
1775
if (exiting && filename[0] != '\0' && ISSET(TEMP_FILE)) {
1776
retval = write_file(filename, NULL, FALSE, 0, FALSE);
1595
if (exiting && openfile->filename[0] != '\0' && ISSET(TEMP_FILE)) {
1596
retval = write_file(openfile->filename, NULL, FALSE, OVERWRITE,
1778
1599
/* Write succeeded. */
1779
1600
if (retval == 0)
1604
ans = mallocstrcpy(NULL,
1783
1605
#ifndef NANO_SMALL
1784
if (ISSET(MARK_ISSET) && !exiting)
1785
ans = mallocstrcpy(NULL, "");
1606
(openfile->mark_set && !exiting) ? "" :
1788
ans = mallocstrcpy(NULL, filename);
1608
openfile->filename);
1791
1611
const char *msg;
1792
1612
#ifndef NANO_SMALL
1793
1613
const char *formatstr, *backupstr;
1795
if (fmt == DOS_FILE)
1796
formatstr = N_(" [DOS Format]");
1797
else if (fmt == MAC_FILE)
1798
formatstr = N_(" [Mac Format]");
1802
if (ISSET(BACKUP_FILE))
1803
backupstr = N_(" [Backup]");
1807
/* Be nice to the translation folks. */
1808
if (ISSET(MARK_ISSET) && !exiting) {
1810
msg = N_("Prepend Selection to File");
1811
else if (append == 1)
1812
msg = N_("Append Selection to File");
1814
msg = N_("Write Selection to File");
1615
formatstr = (openfile->fmt == DOS_FILE) ?
1616
N_(" [DOS Format]") : (openfile->fmt == MAC_FILE) ?
1617
N_(" [Mac Format]") : "";
1619
backupstr = ISSET(BACKUP_FILE) ? N_(" [Backup]") : "";
1621
if (openfile->mark_set && !exiting)
1622
msg = (append == PREPEND) ?
1623
N_("Prepend Selection to File") : (append == APPEND) ?
1624
N_("Append Selection to File") :
1625
N_("Write Selection to File");
1816
1627
#endif /* !NANO_SMALL */
1818
msg = N_("File Name to Prepend to");
1819
else if (append == 1)
1820
msg = N_("File Name to Append to");
1822
msg = N_("File Name to Write");
1628
msg = (append == PREPEND) ? N_("File Name to Prepend to") :
1629
(append == APPEND) ? N_("File Name to Append to") :
1630
N_("File Name to Write");
1824
1632
/* If we're using restricted mode, the filename isn't blank,
1825
1633
* and we're at the "Write File" prompt, disable tab
1826
1634
* completion. */
1827
i = statusq(!ISSET(RESTRICTED) || filename[0] == '\0',
1828
writefile_list, ans,
1635
i = statusq(!ISSET(RESTRICTED) ||
1636
openfile->filename[0] == '\0', writefile_list, ans,
1829
1637
#ifndef NANO_SMALL
1830
1638
NULL, "%s%s%s", _(msg), formatstr, backupstr