/* | | Handle file operations for aee. | $Header: /home/hugh/sources/aee/RCS/file.c,v 1.31 2002/07/10 04:47:01 hugh Exp $ | | Copyright (c) 1986 - 1988, 1991 - 1996, 2001 Hugh Mahon. | */ /* | get the full path the the named file */ #include "aee.h" struct menu_entries file_error_menu[] = { {"", NULL, NULL, NULL, NULL, MENU_WARN}, {NULL, NULL, NULL, NULL, NULL, -1}, {NULL, NULL, NULL, NULL, NULL, -1}, {NULL, NULL, NULL, NULL, NULL, -1} }; char *file_being_edited_msg; struct menu_entries file_being_edited_menu[] = { {"", NULL, NULL, NULL, NULL, MENU_WARN}, {NULL, NULL, NULL, NULL, NULL, -1}, {NULL, NULL, NULL, NULL, NULL, -1}, {NULL, NULL, NULL, NULL, NULL, -1} }; char *file_modified_msg; struct menu_entries file_modified_menu[] = { {"", NULL, NULL, NULL, NULL, MENU_WARN}, {NULL, NULL, NULL, NULL, NULL, -1}, {NULL, NULL, NULL, NULL, NULL, -1}, {NULL, NULL, NULL, NULL, NULL, -1}, {NULL, NULL, NULL, NULL, NULL, -1} }; int aee_write_status; void show_pwd() { char buffer[1024]; char *buff; wmove(com_win, 0, 0); werase(com_win); buff = getcwd(buffer, 1024); if (buff != NULL) { wprintw(com_win, "%s", buff); } else wprintw(com_win, "%s", pwd_err_msg); } /* | get_full_path returns the full directory path for a file | If both 'path' and 'orig_path' are NULL then the current directory | is returned. | If orig_path is not NULL and path does not start with '/', then | orig_path is prefixed to 'path'. | | In order to get the 'canonical' path, that is, without any '..' in | the path name, once the path is created by concatenating orig_path | and path, a chdir() is made to the path, the current directory | obtained, then a chdir back to the directory in which the editor | was when get_full_path was called. */ char * get_full_path(path, orig_path) char *path; char *orig_path; { char *buff = path; char long_buffer[1024]; char curr_path[1024]; char base_name[256]; char *tmp; char *tmp2; char *tmp3; if (orig_path != NULL) { strcpy(long_buffer, orig_path); buff = long_buffer; } else buff = getcwd(long_buffer, 1024); if (buff != NULL) { buff = xalloc(strlen(long_buffer) + (path != NULL ? strlen(path) : 0) + 2); strcpy(buff, long_buffer); if (path != NULL) { tmp = getcwd(curr_path, 1024); if (*path != '/') /* a '/' indicates an absolute path */ { strcat(buff, "/"); strcat(buff, path); } else strcpy(buff, path); tmp2 = ae_dirname(buff); if (tmp2 != (char *)NULL) { strcpy(base_name, ae_basename(buff)); chdir(tmp2); tmp3 = getcwd(long_buffer, 1024); chdir(tmp); free(tmp2); strcpy(buff, long_buffer); strcat(buff, "/"); strcat(buff, base_name); } } } else change_dir_allowed = FALSE; return(buff); } char * ae_basename(name) char *name; { char *buff, *base; buff = base = name; while (*buff != (char) NULL) { if (*buff == '/') base = ++buff; else buff++; } return(base); } char * ae_dirname(path) char *path; { char *tmp = NULL; char buffer[1024]; if (strchr(path, '/') != NULL) { strcpy(buffer, path); tmp = strrchr(buffer, '/'); *tmp = (char) NULL; tmp = (char *) malloc(strlen(buffer) + 1); strcpy(tmp, buffer); } return(tmp); } char * buff_name_generator() { char *buffer = (char *)malloc(4); char found; struct bufr *tmp_buff; int i1, i2; found = TRUE; /* | Buffers with the name already existed. */ buffer[3] = 0; buffer[2] = 0; i2 = -1; do { if (i2 >= 0) buffer[2] = i2 + 'A'; buffer[1] = 0; i1 = -1; do { if (i1 >= 0) buffer[1] = i1 + 'A'; buffer[0] = 'A'; do { found = FALSE; tmp_buff = first_buff; while (tmp_buff != NULL) { if (!strcmp(buffer, tmp_buff->name)) found = TRUE; tmp_buff = tmp_buff->next_buff; } if (found) buffer[0]++; } while ((buffer[0] <= 'Z') && (found)); i1++; } while ((buffer[1] <= 'Z') && (found) ); i2++; }while ((buffer[2] <= 'Z') && (found)); return(buffer); } int open_for_edit(string) char *string; { struct bufr *tmp_buff; char *short_name; char buffer[1024]; char found = FALSE; int length = 0; int ret_val; if (restrict_mode()) { return(FALSE); } if ((string != NULL) && (*string != (char)NULL)) { short_name = ae_basename(string); do { tmp_buff = first_buff; found = FALSE; while (tmp_buff != NULL) { if (!strcmp(short_name, tmp_buff->name)) found = TRUE; tmp_buff = tmp_buff->next_buff; } if (found) { if (length == 0) { strcpy(buffer, short_name); strcat(buffer, "A"); length = strlen(buffer); } if (buffer[length-1] <= 'Z') buffer[length-1]++; short_name = buffer; } } while ((found) && (buffer[length-1] <= 'Z')); if ((found) && (buffer[length-1] > 'Z')) { /* | Buffers with the name already existed. */ return(FALSE); } } else { short_name = buff_name_generator(); } chng_buf(short_name); curr_buff->edit_buffer = TRUE; if (*string != (char)NULL) tmp_file = strdup(string); else tmp_file = ""; recv_file = TRUE; input_file = TRUE; ret_val = check_fp(); if (ret_val == FALSE) { del_buf(); } return ( ret_val ); } void recover_op() { struct journal_db *journal_list; struct journal_db *list_tmp; struct menu_entries *recover_tmp; int list_count; int counter; int choice; char *other_choice; struct bufr local_copy; char new_buff = FALSE; /* indicate if a new buffer was created */ /* | If restricted mode, there must have been a file specified on | the invoking command line. */ if ((restrict_mode()) && (top_of_stack == NULL)) { wmove(com_win, 0, 0); werase(com_win); wrefresh(com_win); menu_op(rae_err_menu); return; } journal_list = read_journal_db(); for (list_count = 0, list_tmp = journal_list; list_tmp != NULL; list_count++, list_tmp = list_tmp->next) ; unlock_journal_fd(); /* | Recover from a failed edit session. | 1. Read the file ~/.aeeinfo, get the list of journal files. | 2. Create a menu with names of files according to ~/.aeeinfo. | 3. Menu also has entry 'other journal file', which allows the user | to specify another file. Not yet implemented: | 4. Before creating the menu, the routine checks if the journal file | is currently open (someone is currently editing that file!). | 5. After user selection, present a menu allowing the user to copy | the journal file, or recover directly from the journal (since | starting an edit session from the journal could change it, it | might be nice to just allow the user to 'browse' the file). Implemented: | 5a. If there is only one file in the list, automatically open it. | 6. Call recover_from_journal. | | */ if (list_count == 0) { /* | prompt for name of file to recover */ other_choice = get_string(recover_name_prompt, TRUE); } /* | If there is just one file in the list, we could just put the user | into the one file. I have found that this is not always a good | idea. else if (list_count == 1) other_choice = journal_list->journal_name; | */ else { /* | Construct menu. */ recover_tmp = malloc((3 + list_count) * sizeof(struct menu_entries)); memset(recover_tmp, 0, ((3 + list_count) * sizeof(struct menu_entries))); for (counter = 1, list_tmp = journal_list; (counter <= list_count); list_tmp = list_tmp->next, counter++) { recover_tmp[counter].item_string = (list_tmp->file_name != NULL) ? list_tmp->file_name : ae_basename(list_tmp->journal_name) ; recover_tmp[counter].procedure = NULL; recover_tmp[counter].ptr_argument = NULL; recover_tmp[counter].iprocedure = NULL; recover_tmp[counter].nprocedure = NULL; recover_tmp[counter].argument = -1; } /* | Assign the title of the menu, then add 'other file' to | menu. */ recover_tmp[0].item_string = recover_menu_title; recover_tmp[list_count+1].item_string = other_recover_file_str; recover_tmp[list_count+2].item_string = NULL; /* | Present menu to user. */ choice = menu_op(recover_tmp); free(recover_tmp); if (choice == 0) return; else if (choice == (list_count + 1)) { other_choice = get_string(recover_name_prompt, TRUE); in_file_name = NULL; } else { for (list_count = 1, list_tmp = journal_list; list_count < choice; list_count++, list_tmp = list_tmp->next) ; other_choice = list_tmp->journal_name; in_file_name = list_tmp->file_name; } } /* | take user's choice, fill in data structures, recover, | and return */ /* | Change to a new buffer to make sure we aren't messing | with the user's edit session. */ local_copy.journalling = FALSE; if ((curr_buff->changed == FALSE) && (curr_buff->first_line->next_line == NULL) && (curr_buff->first_line->line_length == 1) && (*curr_buff->full_name == (char)NULL)) { local_copy.journalling = curr_buff->journalling; local_copy.journ_fd = curr_buff->journ_fd; local_copy.journal_file = curr_buff->journal_file; local_copy.full_name = curr_buff->full_name; local_copy.file_name = curr_buff->file_name; local_copy.name = curr_buff->name; } else { chng_buf(buff_name_generator()); new_buff = TRUE; } curr_buff->journal_file = other_choice; if (journ_on) { curr_buff->journalling = TRUE; } if (curr_buff->orig_dir == NULL) { curr_buff->orig_dir = get_full_path(NULL, NULL); } if (recover_from_journal(curr_buff, curr_buff->journal_file) != 0) { if (new_buff) del_buf(); else { curr_buff->journalling = local_copy.journalling; curr_buff->journ_fd = local_copy.journ_fd ; curr_buff->journal_file = local_copy.journal_file ; curr_buff->full_name = local_copy.full_name ; curr_buff->file_name = local_copy.file_name ; curr_buff->name = local_copy.name ; } wmove(com_win,0,0); wclrtoeol(com_win); wprintw(com_win, bad_rcvr_msg); wrefresh(com_win); } else { /* | On success, clear flags and continue edit | session. */ if ((!new_buff) && (local_copy.journalling)) remove_journal_file(&local_copy); curr_buff->edit_buffer = TRUE; curr_buff->curr_line = curr_buff->first_line; curr_buff->pointer = curr_buff->curr_line->line; new_screen(); wmove(com_win,0,0); wclrtoeol(com_win); wprintw(com_win, rcvr_op_comp_msg); wrefresh(com_win); #ifdef XAE if ((curr_buff->main_buffer) && (curr_buff->file_name != NULL)) set_window_name(curr_buff->file_name); #endif /* XAE */ recv_file = FALSE; input_file = FALSE; } } int check_fp() /* open or close files according to flags recv_file, recover, and input_file */ { char *buff; int line_num; char buffer[512]; int value; clr_cmd_line = TRUE; if (recover) /* get data from journal file */ { recover = FALSE; buff = in_file_name = tmp_file; if (journ_on) { curr_buff->journalling = TRUE; } if (curr_buff->orig_dir == NULL) { curr_buff->orig_dir = get_full_path(NULL, NULL); } in_file_name = tmp_file = get_full_path(in_file_name, curr_buff->orig_dir); short_file_name = ae_basename(in_file_name); curr_buff->file_name = short_file_name; curr_buff->full_name = in_file_name; journal_name(curr_buff, in_file_name); if (recover_from_journal(curr_buff, curr_buff->journal_file) != 0) { wmove(com_win,0,0); wclrtoeol(com_win); wprintw(com_win, bad_rcvr_msg); wrefresh(com_win); } else { /* | On success, clear flags and continue edit | session. */ curr_buff->curr_line = curr_buff->first_line; curr_buff->pointer = curr_buff->curr_line->line; midscreen(curr_buff->scr_vert, curr_buff->position); wmove(com_win,0,0); wclrtoeol(com_win); wprintw(com_win, rcvr_op_comp_msg); wrefresh(com_win); #ifdef XAE if (curr_buff->main_buffer) set_window_name(curr_buff->file_name); #endif /* XAE */ recv_file = FALSE; input_file = FALSE; } } if (recv_file) /* read in a file */ { tmp_vert = curr_buff->scr_vert; tmp_horz = curr_buff->scr_horz; tmp_line = curr_buff->curr_line; if (input_file) /* get file on command line */ { /* | We want to do a few things here. First, get | the path of the file we're editing. Second, | find out if we are already editing the file | (compare with files listed in ~/.aeeinfo). | Third get the journal file name. Fourth, | open the journal file for writing. */ buff = short_file_name = in_file_name = tmp_file; if (curr_buff->orig_dir == NULL) curr_buff->orig_dir = get_full_path(NULL, NULL); if (*buff != (char)NULL) { tmp_file = in_file_name = get_full_path(in_file_name, curr_buff->orig_dir); short_file_name = ae_basename(in_file_name); curr_buff->file_name = short_file_name; curr_buff->full_name = in_file_name; } else { recv_file = FALSE; input_file = FALSE; } if (journ_on) { struct journal_db *journal_list; struct journal_db *list_tmp; int match_found = FALSE; journal_list = read_journal_db(); unlock_journal_fd(); for (list_tmp = journal_list; (!match_found) && (list_tmp != NULL); list_tmp = list_tmp->next) { /* | comparing the basename, which | may prove to be an erroneous | match, but more complete match | would be a lot more work */ if (list_tmp->file_name != NULL) { match_found = !strcmp(in_file_name, list_tmp->file_name); } } /* | free the memory allocated for the list */ list_tmp = journal_list; while (list_tmp != NULL) { journal_list = journal_list->next; free (list_tmp); list_tmp = journal_list; } if (match_found) { sprintf(buffer, file_being_edited_msg, short_file_name); file_being_edited_menu[0].item_string = buffer; match_found = menu_op(file_being_edited_menu); if (match_found == 1) { if (curr_buff->main_buffer) quit(""); else { recv_file = FALSE; input_file = FALSE; return(FALSE); } } } curr_buff->journalling = TRUE; journal_name(curr_buff, in_file_name); open_journal_for_write(curr_buff); } #ifdef XAE if ((curr_buff->main_buffer) && (curr_buff->file_name != NULL)) set_window_name(curr_buff->file_name); #endif /* XAE */ if (*buff == (char)NULL) { wmove(com_win,0,0); wclrtoeol(com_win); wprintw(com_win, no_file_string); return(TRUE); } } wmove(com_win,0,0); wclrtoeol(com_win); value = stat(tmp_file, &buf); buf.st_mode &= ~07777; if ((value != -1) && (buf.st_mode != 0100000) && (buf.st_mode != 0)) { if (input_file) { sprintf(buffer, file_is_dir_msg, ae_basename(tmp_file)); file_error_menu[0].item_string = buffer; file_error_menu[1].item_string = continue_prompt; menu_op(file_error_menu); if (curr_buff->main_buffer) quit(""); } else { wprintw(com_win, file_is_dir_msg, tmp_file); wrefresh(com_win); } recv_file = FALSE; input_file = FALSE; return(FALSE); } if ((get_fd = open(tmp_file, O_RDONLY)) == -1) { wmove(com_win,0,0); wclrtoeol(com_win); if (input_file) { if ((get_fp= fopen(tmp_file,"w")) == NULL) { if ((errno == ENOTDIR) || (errno == ENOENT)) { file_error_menu[0].item_string = path_not_a_dir_msg; } else if ((errno == EACCES) || (errno == EROFS) || (errno == ETXTBSY) || (errno == EFAULT)) { sprintf(buffer, access_not_allowed_msg, ae_basename(in_file_name)); file_error_menu[0].item_string = buffer; } file_error_menu[1].item_string = continue_prompt; menu_op(file_error_menu); if (curr_buff->main_buffer) quit(""); recv_file = FALSE; input_file = FALSE; return(FALSE); } else { fclose(get_fp); unlink(tmp_file); wprintw(com_win, new_file_msg, tmp_file); } } else wprintw(com_win, cant_open_msg, tmp_file); wrefresh(com_win); recv_file = FALSE; input_file = FALSE; } else get_file(tmp_file); if (recv_file) /* got a file */ { close(get_fd); recv_file = FALSE; line_num = curr_buff->curr_line->line_number; curr_buff->scr_vert = tmp_vert; curr_buff->scr_horz = tmp_horz; if (input_file) curr_buff->curr_line = curr_buff->first_line; else curr_buff->curr_line = tmp_line; curr_buff->pointer = curr_buff->curr_line->line; midscreen(curr_buff->scr_vert, curr_buff->position); if (input_file) /* get the file on the command line */ { if (access(in_file_name, 2)) { if ((errno == ENOTDIR) || (errno == EACCES) || (errno == EROFS) || (errno == ETXTBSY) || (errno == EFAULT)) wprintw(com_win, ", %s", read_only_msg); } if (start_at_line != NULL) { line_num = atoi(start_at_line) - 1; move_rel("d", line_num); line_num = 0; start_at_line = NULL; } value = stat(tmp_file, &curr_buff->fileinfo); if (value == -1) { curr_buff->fileinfo.st_mtime = 0; curr_buff->fileinfo.st_size = 0; } wrefresh(com_win); input_file = FALSE; } else { wmove(com_win, 0, 0); werase(com_win); wprintw(com_win, fin_read_file_msg, tmp_file); wrefresh(com_win); } in = 0; } } wrefresh(com_win); return(TRUE); } /* | get_file is called from two places: check_fp and sh_command | When called from check_fp, recv_file is set, and input_file may be | set, indicating this is a file to be edited. | When called from sh_command, it is reading from a pipe from a forked | process. */ void get_file(file_name) /* read specified file into current buffer */ char *file_name; { int can_write; /* file mode allows write */ int can_read; /* file has at least one character */ int length; /* length of line read by read */ int append; /* should text be appended to current line */ struct text *temp_line; if (recv_file) /* if reading a file */ { wmove(com_win, 0, 0); wclrtoeol(com_win); wprintw(com_win, reading_file_msg, file_name); if ((can_write = access(file_name, 2))) /* check permission to write */ { if ((errno == ENOTDIR) || (errno == EACCES) || (errno == EROFS) || (errno == ETXTBSY) || (errno == EFAULT)) wprintw(com_win, read_only_msg); } wrefresh(com_win); } if (curr_buff->curr_line->line_length > 1) /* if current line is not blank */ { insert_line(FALSE); left(FALSE); append = FALSE; } else append = TRUE; can_read = FALSE; /* test if file has any characters */ while (((length = read(get_fd, in_string, 512)) != 0) && (length != -1)) { can_read = TRUE; /* if set file has at least 1 character */ get_line(length, in_string, &append); } if ((can_read) && (curr_buff->curr_line->line_length == 1)) { temp_line = curr_buff->curr_line->prev_line; temp_line->next_line = curr_buff->curr_line->next_line; if (temp_line->next_line != NULL) temp_line->next_line->prev_line = temp_line; if (curr_buff->journalling) remove_journ_line(curr_buff, curr_buff->curr_line); free(curr_buff->curr_line); curr_buff->curr_line = temp_line; curr_buff->num_of_lines--; } if (input_file) /* if this is the file to be edited display number of lines */ { wmove(com_win, 0, 0); wclrtoeol(com_win); wprintw(com_win, file_read_lines_msg, in_file_name, curr_buff->curr_line->line_number); wrefresh(com_win); } else curr_buff->changed = TRUE; } void get_line(length, in_string, append) /* read string and split into lines */ int length; /* length of string read by read */ char *in_string; /* string read by read */ int *append; /* TRUE if must append more text to end of current line */ { char *str1; char *str2; int num; /* offset from start of string */ int char_count; /* length of new line (or added portion */ int temp_counter; /* temporary counter value */ struct text *tline; /* temporary pointer to new line */ int first_time; /* if TRUE, the first time through the loop */ static int last_char_cr = FALSE; /* set if the last character of a buffer was a carriage return */ str2 = in_string; num = 0; first_time = TRUE; while (num < length) { if (!first_time) { if (num < length) { str2++; num++; } } else first_time = FALSE; str1 = str2; char_count = 1; /* find end of line */ if (!last_char_cr) { if (text_only) { while ((*str2 != '\n') && (num < length)) { if (((*str2 == '\r') && (*(str2 + 1) == '\n')) || ((*str2 == '\r') && ((num + 1) == length))) { curr_buff->dos_file = TRUE; if ((num + 1) == length) last_char_cr = TRUE; } else char_count++; str2++; num++; } } else { while ((*str2 != '\n') && (num < length)) { char_count++; str2++; num++; } } } else last_char_cr = FALSE; if (!(*append)) /* if not append to current line, insert new one */ { tline = txtalloc(); /* allocate data structure for next line */ tline->line_number = curr_buff->curr_line->line_number + 1; tline->next_line = curr_buff->curr_line->next_line; tline->prev_line = curr_buff->curr_line; curr_buff->curr_line->next_line = tline; if (tline->next_line != NULL) tline->next_line->prev_line = tline; curr_buff->curr_line = tline; curr_buff->num_of_lines++; curr_buff->curr_line->line = curr_buff->pointer = xalloc(char_count); curr_buff->curr_line->line_length = char_count; curr_buff->curr_line->max_length = char_count; } else { curr_buff->pointer = resiz_line(char_count, curr_buff->curr_line, curr_buff->curr_line->line_length); curr_buff->curr_line->line_length += (char_count - 1); } for (temp_counter = 1; temp_counter < char_count; temp_counter++) { *curr_buff->pointer = *str1; curr_buff->pointer++; str1++; } if (((*str2 == '\n') || ((num == length) && (num < 512))) && (curr_buff->journalling)) write_journal(curr_buff, curr_buff->curr_line); *curr_buff->pointer = (char) NULL; *append = FALSE; curr_buff->curr_line->vert_len = (scanline(curr_buff->curr_line, curr_buff->curr_line->line_length) / COLS) + 1; if ((num == length) && (*str2 != '\n')) *append = TRUE; } } char * is_in_string(string, substring) /* a strstr() look-alike for systems without strstr() */ char * string, *substring; { char *full, *sub; for (sub = substring; (sub != NULL) && (*sub != (char)NULL); sub++) { for (full = string; (full != NULL) && (*full != (char)NULL); full++) { if (*sub == *full) return(full); } } return(NULL); } /* | handle names of the form "~/file", "~user/file", | "$HOME/foo", "~/$FOO", etc. */ char * resolve_name(name) char *name; { char long_buffer[1024]; char short_buffer[128]; char *buffer; char *slash; char *tmp; char *start_of_var; int offset; int index; int counter; struct passwd *user; char *name_buffer; name_buffer = (char *) malloc(strlen(name) + 1); strcpy(name_buffer, name); if (name_buffer[0] == '~') { if (name_buffer[1] == '/') { index = getuid(); user = (struct passwd *) getpwuid(index); slash = name_buffer + 1; } else { slash = strchr(name_buffer, '/'); if (slash == NULL) return(name_buffer); *slash = (char) NULL; user = (struct passwd *) getpwnam((name_buffer + 1)); *slash = '/'; } if (user == NULL) { return(name_buffer); } buffer = xalloc(strlen(user->pw_dir) + strlen(slash) + 1); strcpy(buffer, user->pw_dir); strcat(buffer, slash); } else buffer = name_buffer; if (is_in_string(buffer, "$")) { tmp = buffer; index = 0; while ((*tmp != (char) NULL) && (index < 1024)) { while ((*tmp != (char) NULL) && (*tmp != '$') && (index < 1024)) { long_buffer[index] = *tmp; tmp++; index++; } if ((*tmp == '$') && (index < 1024)) { counter = 0; start_of_var = tmp; tmp++; if (*tmp == '{') /* } */ /* bracketed variable name */ { tmp++; /* { */ while ((*tmp != (char) NULL) && (*tmp != '}') && (counter < 128)) { short_buffer[counter] = *tmp; counter++; tmp++; } /* { */ if (*tmp == '}') tmp++; } else { while ((*tmp != (char) NULL) && (*tmp != '/') && (*tmp != '$') && (counter < 128)) { short_buffer[counter] = *tmp; counter++; tmp++; } } short_buffer[counter] = (char) NULL; if ((slash = getenv(short_buffer)) != NULL) { offset = strlen(slash); if ((offset + index) < 1024) strcpy(&long_buffer[index], slash); index += offset; } else { while ((start_of_var != tmp) && (index < 1024)) { long_buffer[index] = *start_of_var; start_of_var++; index++; } } } } if (index == 1024) return(buffer); else long_buffer[index] = (char) NULL; if (name_buffer != buffer) free(buffer); buffer = xalloc(index + 1); strcpy(buffer, long_buffer); } return(buffer); } int write_file(file_name) /* write current buffer to specified file */ char *file_name; { char cr, lf; char *tmp_point; struct text *out_line; int lines, charac; int temp_pos; int write_flag; int can_write; int write_ret = 0; int value; struct stat filestat; char *short_name; char buffer[1024]; clr_cmd_line = TRUE; charac = lines = 0; aee_write_status = FALSE; if ((curr_buff->full_name == NULL) || (strcmp(curr_buff->full_name, file_name))) { wmove(com_win, 0, 0); wclrtoeol(com_win); can_write = access(file_name, 2); if (can_write) { write_flag = FALSE; if (errno == ENOTDIR) wprintw(com_win, path_not_a_dir_msg); else if ((errno == EACCES) || (errno == EROFS) || (errno == ETXTBSY) || (errno == EFAULT)) wprintw(com_win, no_write_access_msg, file_name); else if (errno != ENOENT) { tmp_point = get_string(file_exists_prompt, TRUE); if ((toupper(*tmp_point) == toupper(*no_char)) || (*tmp_point == (char) NULL)) write_flag = FALSE; else write_flag = TRUE; free(tmp_point); } else write_flag = TRUE; } else { tmp_point = get_string(file_exists_prompt, TRUE); if ((toupper(*tmp_point) == toupper(*no_char)) || (*tmp_point == (char) NULL)) write_flag = FALSE; else write_flag = TRUE; free(tmp_point); } wrefresh(com_win); } else { if (!strcmp(curr_buff->full_name, file_name)) { value = stat(file_name, &filestat); if ((value == 0) && ((filestat.st_mtime != curr_buff->fileinfo.st_mtime) || (filestat.st_size != curr_buff->fileinfo.st_size))) { /* | notify user that the file has changed and ask | whether to continue file write or not */ short_name = ae_basename(file_name); sprintf(buffer, file_modified_msg, short_name); file_modified_menu[0].item_string = buffer; value = menu_op(file_modified_menu); if (value == 1) { return(FALSE); } else if (value == 3) { sprintf(buffer, ">first_line; while (out_line != NULL) { temp_pos = 1; tmp_point= out_line->line; while ((temp_pos < out_line->line_length) && (write_ret != EOF)) { write_ret = putc(*tmp_point, write_fp); tmp_point++; temp_pos++; } charac += out_line->line_length; out_line = out_line->next_line; if ((text_only) && (curr_buff->dos_file)) putc(cr, write_fp); putc(lf, write_fp); lines++; } fclose(write_fp); wmove(com_win,0,0); wclrtoeol(com_win); wprintw(com_win, file_written_msg, file_name,lines,charac); if (write_ret == EOF) { wstandout(com_win); wprintw(com_win, write_err_msg); wstandend(com_win); } wrefresh(com_win); value = stat(file_name, &curr_buff->fileinfo); if (value == -1) { curr_buff->fileinfo.st_mtime = 0; curr_buff->fileinfo.st_size = 0; } aee_write_status = TRUE; return(TRUE); } } else return(FALSE); } int file_write_success() { return (aee_write_status); } void diff_file() { char tmp_buff[1024]; char buff_name[512]; struct bufr *tmp; char *curr_name; /* | want to do a diff of the current edit buffer with the | file it is associated with | | another way to deal with buffer names is to use the function | buff_name_generator() */ if ((curr_buff->file_name != (char *)NULL) && (*curr_buff->file_name != (char)NULL)) { curr_name = curr_buff->name; sprintf(buff_name, "%s-diffs", curr_buff->file_name); tmp = first_buff; while ((tmp != NULL) && (strcmp(tmp->name, buff_name))) tmp = tmp->next_buff; if (tmp != NULL) { chng_buf(buff_name); del_buf(); chng_buf(curr_name); } sprintf(tmp_buff, "><%s!diff %s -", buff_name, curr_buff->full_name); command(tmp_buff); } else { wmove(com_win, 0, 0); werase(com_win); wprintw(com_win, no_file_string); } }