📄 journal.c
字号:
/* | journal.c | | This file contains the routines for handling the journal file | for ae. | | $Header: /home/hugh/sources/aee/RCS/journal.c,v 1.34 1998/11/08 23:30:37 hugh Exp $ *//* | This file contains routines for performing journalling for aee and | xae. Journalling is writing lines and information about them to a | file when the cursor moves away from them (if they have been changed | during the time the cursor was on the line). | | The data structure ae_file_info contains the information about | locations in the file for where to find the information about the | current line, the information about the previous line, the info | about the next line, and the location of the actual text. The | length of the line (which is important!) is contained in the 'text' | structure for the line. | | The format that the information is written into the file is as | follows: | | +--+--+--+--+ | | | | | | previous line info location | +--+--+--+--+ | | +--+--+--+--+ | | | | | | next line info location | +--+--+--+--+ | | +--+--+--+--+ | | | | | | text location | +--+--+--+--+ | | +--+--+--+--+ | | | | | | text length (in bytes, including terminating NULL) | +--+--+--+--+ | *//* | Also in this file are routines for managing information about what | journal files have been written, and the relationship between the | journal file and the file being journalled. This helps when | recovering from a disaster, and could be used to determine duplicate | edit sessions, or a failed previous session. | | The name of the file is ~/.aeeinfo, and there is a lock file named | ~/.aeeinfo.L. The format of ~/.aeeinfo is as follows: | | 32 30 /home/hugh/sources/aee/journal.c /tmp/hugh/journal/journal.c.rv | | where the first number is the length (decimal) if the full file name, | the second number is the length of the journal file name, followed by | the file name, and the name of the journal file. The fields are | separated by a single space (ASCII 32). | | *//* | | Copyright (c) 1994, 1995, 1996, 1998 Hugh Mahon. | */char *jrn_vers_str = "@(#) journal.c $Revision: 1.34 $";#include "aee.h"#include <time.h>/* | writes the contents of the line, updates the value stored in | memory of where the start of the line is stored in the file */void write_journal(buffer, line)struct bufr *buffer;struct text *line;{ int counter; int ret_val = 0; ret_val = line->file_info.line_location = lseek(buffer->journ_fd, 0, SEEK_END); for (counter = 0; (counter < line->line_length) && (ret_val != -1); counter += min(1024, (line->line_length - counter))) { ret_val = write(buffer->journ_fd, &(line->line[counter]), min(1024, (line->line_length - counter))); } update_journal_entry(buffer, line); line->changed = FALSE;}/* | update the information for a line that has already been written, or | write a line for the first after its values have been initialised | by journ_info_init */void update_journal_entry(buffer, line)struct bufr *buffer;struct text *line;{ int ret_val; if (line->file_info.info_location == NO_FURTHER_LINES) { journ_info_init(buffer, line); return ; } ret_val = lseek(buffer->journ_fd, line->file_info.info_location, SEEK_SET); ret_val |= write(buffer->journ_fd, (char *)&(line->file_info.prev_info), sizeof(unsigned long)); ret_val |= write(buffer->journ_fd, (char *)&(line->file_info.next_info), sizeof(unsigned long)); ret_val |= write(buffer->journ_fd, (char *)&(line->file_info.line_location), sizeof(unsigned long)); ret_val |= write(buffer->journ_fd, (char *)&(line->line_length), sizeof(int));}/* | change journal info at first line if the first line is deleted | while editing */void remove_journ_line(buffer, line)struct bufr *buffer;struct text *line;{ if (line->prev_line == NULL) { /* | This was the first line, now the next line is. */ line->next_line->file_info.info_location = line->file_info.info_location; update_journal_entry(buffer, line->next_line); if (line->next_line->next_line != NULL) { line->next_line->next_line->file_info.prev_info = line->file_info.info_location; update_journal_entry(buffer, line->next_line->next_line); } } else if (line->next_line == NULL) { /* | This was the last line, now the prev line is. */ line->prev_line->file_info.next_info = NO_FURTHER_LINES; update_journal_entry(buffer, line->prev_line); /* | no point in writing to file since no way to | access current line now */ } else { /* | Need to allow previous line to see next line, | vice-versa. */ line->prev_line->file_info.next_info = line->next_line->file_info.info_location; line->next_line->file_info.prev_info = line->prev_line->file_info.info_location; update_journal_entry(buffer, line->next_line); update_journal_entry(buffer, line->prev_line); }}/* | initialize the location of where the information is to reside | (using lseek), initialize information for this line of where the | previous line is, set the information where to find this line for | the previous line, next line then | | update current line (write for the first time) | update the previous line (if prev_line != NULL) | update the next line (if next_line != NULL) | */void journ_info_init(buffer, line)struct bufr *buffer;struct text *line;{ int ret_val; ret_val = line->file_info.info_location = lseek(buffer->journ_fd, 0, SEEK_END); if (line->prev_line != NULL) { line->file_info.prev_info = line->prev_line->file_info.info_location; line->prev_line->file_info.next_info = line->file_info.info_location; } if (line->next_line != NULL) { line->file_info.next_info = line->next_line->file_info.info_location; line->next_line->file_info.prev_info = line->file_info.info_location; } else line->file_info.next_info = NO_FURTHER_LINES; update_journal_entry(buffer, line); if (line->prev_line != NULL) update_journal_entry(buffer, line->prev_line); if ((line->next_line != NULL) && (line->file_info.next_info != NO_FURTHER_LINES)) update_journal_entry(buffer, line->next_line);}/* | read the journal entry from the file */void read_journal_entry(buffer, line)struct bufr *buffer;struct text *line;{ int counter; lseek(buffer->journ_fd, line->file_info.info_location, SEEK_SET); read(buffer->journ_fd, (char *)&(line->file_info.prev_info), sizeof(unsigned long)); read(buffer->journ_fd, (char *)&(line->file_info.next_info), sizeof(unsigned long)); read(buffer->journ_fd, (char *)&(line->file_info.line_location), sizeof(unsigned long)); read(buffer->journ_fd, (char *)&(line->line_length), sizeof(unsigned int)); lseek(buffer->journ_fd, line->file_info.line_location, SEEK_SET); line->line = malloc(line->line_length); for (counter = 0; counter < line->line_length; counter += min(1024, (line->line_length - counter))) { read(buffer->journ_fd, &(line->line[counter]), min(1024, (line->line_length - counter))); }}/* | read the contents of the edited file from the journal file | read the file up to the first '\n' (line feed), which is where | the journal information begins | | This reads the contents of the edited file, plus sets the values | in the data structures to allow continued editing (it is recreated | within the editor, so why not?). */int recover_from_journal(buffer, file_name)struct bufr *buffer;char *file_name;{ int counter = 0; struct text *line; char temp; char done = FALSE; char name[1024]; if ((buffer->journ_fd = open(file_name, O_RDONLY)) == -1) { /* | Unable to open journal file. */ return(1); } memset(name, 0, 1024); /* | get to first record in file (skip the file name) */ do { read(buffer->journ_fd, &temp, 1); if ((counter < 1024) && (temp != '\n')) name[counter] = temp; counter++; } while (temp != '\n'); line = buffer->first_line; /* | set up first entry */ line->file_info.info_location = counter; do { read_journal_entry(buffer, line); line->vert_len = (scanline(line, line->line_length) / COLS) + 1; line->max_length = line->line_length; if (line->file_info.next_info != NO_FURTHER_LINES) { line->next_line = txtalloc(); buffer->num_of_lines++; line->next_line->prev_line = line; line->next_line->next_line = NULL; line->next_line->line_number = line->line_number + 1; line = line->next_line; line->file_info.next_info = 0; line->file_info.info_location = line->prev_line->file_info.next_info; } else done = TRUE; } while (!done); curr_buff->pointer = buffer->first_line->line; close(buffer->journ_fd); change = TRUE; buffer->changed = TRUE; /* | open journal for further changes */ if (buffer->journalling) { if ((buffer->journ_fd = open(buffer->journal_file, O_WRONLY)) == -1) { wprintw(com_win, cant_opn_rcvr_fil_msg); buffer->journalling = FALSE; } } /* | Since the user can specify a journal name without specifying | the name of the file it journalled, use the name stored in | the journal file. */ if ((buffer->full_name == NULL) || (*buffer->full_name == (char) NULL)) { buffer->full_name = (name[0] == (char) NULL) ? NULL : strdup(name); if (buffer->full_name != NULL) { buffer->file_name = ae_basename(buffer->full_name); if (strcmp(main_buffer_name, buffer->name)) buffer->name = strdup(buffer->file_name); } else buffer->file_name = NULL; } /* | Success! */ return(0);}/* | journal database file routines */static char *lock_file_name = NULL;static char *db_file_name = NULL;/* | write a lock file so that another process doesn't try to open | the file | | This is an atomic action since the open should fail if the file | already exists, thus it can't be opened if someone else has a | lock in place. */int lock_journal_fd(){ int counter = 0; int ret_val; if (lock_file_name == NULL) lock_file_name = resolve_name("~/.aeeinfo.L"); /* | At some point may want to put in a check for an old lock file. */
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -