⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 ps_impl.c

📁 操作系统SunOS 4.1.3版本的源码
💻 C
📖 第 1 页 / 共 4 页
字号:
	} else {	    INVALIDATE_CURRENT(private);	    delta = get_current_offset(private);	    current = private->current;	    if (delta == 0) {		at_end_of_stream = 0;	    } else {		at_end_of_stream = (delta == pieces[current].length);		/*		 * Split the current piece at the insert point.		 * This creates a zero length piece iff at_end_of_stream.		 */		pieces = split_piece(&private->pieces, current, delta);		current++;	    }	}#ifdef DEBUG	long_temp = pieces[current].pos;#endif	/* Do the insert and associated bookkeeping */	ft_shift_up(&private->pieces, current, current+last_valid+1,			last_valid+1);	pieces = PIECES_IN_TABLE(private);	copy_pieces(&private->pieces, current, rep, 0, last_valid+1);	ASSERT(allock());	/* Offset inserted pieces so they match the insertion point.	 * BUG ALERT: need version of ft_add_delta that takes stop index,	 *	but for now, monkey with the piece table itself.	 */	save_last_plus_one = private->pieces.last_plus_one;	private->pieces.last_plus_one = current+last_valid+1;	ft_add_delta(private->pieces, current,		     private->position - rep->seq[0]);	private->pieces.last_plus_one = save_last_plus_one;	ASSERT(long_temp == pieces[current+last_valid+1].pos);	/* Write header info to scratch. */	scratch_length = es_set_position(scratch, ES_INFINITY);	es_temp = write_record_header(scratch, private, private->position,				      last_valid+1);	if (es_temp != ES_CANNOT_SET) {	    /* Can modify private->... iff es_replace succeeds */	    private->rec_insert = es_temp;	    private->rec_start = scratch_length;	    if (private->oldest_not_undone_mark == ES_INFINITY)		private->oldest_not_undone_mark = scratch_length;	}	delta = record_deleted_pieces(			scratch, private, pieces,			current, current+last_valid+1,			&private->rec_insert);	long_temp = 0;	(void) es_replace(scratch, ES_INFINITY,			  sizeof(long_temp), (char *)&long_temp,			  &replace_used);	ASSERT(allock());	/* Adjust position, etc. to reflect the overall replace */	if (at_end_of_stream) {	    /* Flush the extraneous zero length piece we created. */	    ASSERT(pieces[current+last_valid+1].length == 0);	    pieces[current+last_valid+1].pos = ES_INFINITY;	} else {	    ft_add_delta(private->pieces, current+last_valid+1, delta);	}	private->last_write_plus_one = ES_INFINITY;	private->length += delta;	SET_POSITION(private, private->position + delta);}static Es_indexadjust_pos_after_edit(pos, start, delta)	register Es_index	pos, start, delta;{	if (delta > 0)	    return((start <= pos) ? pos+delta : pos);	else if (start < pos)	    return((start-delta < pos) ? pos+delta : start);	else	    return(pos);}static voidps_undo_to_mark(esh, mark, notify_proc, notify_data)	Es_handle	  esh;	Es_index	  mark;	int		(*notify_proc)();	caddr_t		  notify_data;/* * The notify_proc gets called with the notify_data, the start of the affected *   range, and the delta.  Thus a negative delta means [start..start-delta) *   contains the affected positions, while a positive delta indicates an *   insertion of entities to fill the range [start..start+delta). */{	register Piece_table		private = ABS_TO_REP(esh);	register Es_handle		scratch = private->scratch;	register Piece			pieces, this_piece;	register Es_index		current_pos, scratch_pos,					save_pos = private->position;	Es_index			delta,					mark_pos = mark;	struct piece_record_header	r_header;	struct deleted_piece		d_header;	int				current, i, read;	long int			insert_len;	if (es_get_length(scratch) == 0)	    return;	/* For a bounded scratch stream, the mark_pos may now be invalid and	 * need to be adjusted.  The new value need not be exactly at a record	 * header (luckily, else all of the record headers would have to be	 * read twice). 	 */	if (SCRATCH_HAS_WRAPPED(private) &&	    mark_pos < SCRATCH_FIRST_VALID(private)) {	    mark_pos = SCRATCH_FIRST_VALID(private);	}	/* Read back the information from the scratch source and undo it */	for (; (private->rec_start != ES_INFINITY) &&		 (private->rec_start >= mark_pos);	    private->rec_start = r_header.pos_prev_rec) {	    (void) es_set_position(scratch, private->rec_start);	    (void) es_read(scratch, sizeof(r_header),			   (char *)&r_header, &read);	    ASSUME(read == sizeof(r_header));	    /* Check to see if piece is flagged as already undone.	     * If not, make sure it is flagged now.	     */	    if (r_header.flags & PS_ALREADY_UNDONE)		continue;	    r_header.flags |= PS_ALREADY_UNDONE;	    (void) es_set_position(scratch, private->rec_start);	    (void) es_replace(scratch, private->rec_start+sizeof(r_header),			      sizeof(r_header), (char *)&r_header, &read);	    ASSUME(read == sizeof(r_header));	    if (private->oldest_not_undone_mark == private->rec_start)	        private->oldest_not_undone_mark = ES_INFINITY;	    current_pos = r_header.start;	    SET_POSITION(private, current_pos);	    if (private->length == 0 &&	        PIECES_IN_TABLE(private)[0].pos == ES_INFINITY) {		/* Special case occurs when nothing replaced everything.		 * BUG ALERT: later on, we depend on the [0].pos being left		 *   as ES_INFINITY, else the ft_shift_up corrupts the		 *   piece table.		 */		current = 0;		delta = 0;	    } else {		delta = get_current_offset(private);		current = private->current;	    }	    if ((r_header.start == r_header.stop_plus_one) &&		(r_header.dp_count != 0)) {		/* Remove the inserted pieces.		 *   Since ps_replace does NOT coalesce pieces, a single		 * inserted piece may be turned into multiple pieces via		 * sequences of "type-in edit-chars-deleting type-in", and		 * UNDO of those sequences also does NOT coalesce the pieces,		 * so when we go to UNDO the original insert we must not rely		 * on a one-to-one mapping of the pieces.		 */		int	piece_length, piece_count = 0;		ASSERT(delta == 0);		pieces = PIECES_IN_TABLE(private);		this_piece = &pieces[current];		for (i = r_header.dp_count; i > 0; i--) {		    (void) es_read(scratch, sizeof(d_header),				   (char *)&d_header, &read);		    ASSERT(this_piece->pos == current_pos-delta);		    ASSERT(this_piece->source_and_pos == d_header.source_and_pos);		    delta -= d_header.length;		    for (piece_length = d_header.length; piece_length > 0;			piece_count++) {			ASSERT(this_piece->length <= piece_length);			piece_length -= this_piece->length;			this_piece++;		    }		}		ft_shift_out(&private->pieces, current,			     current+piece_count);		ft_add_delta(private->pieces, current, delta);		save_pos = adjust_pos_after_edit(save_pos, current_pos, delta);		private->length += delta;		if (notify_proc) {		    scratch_pos = es_get_position(scratch);		    notify_proc(notify_data, current_pos, delta);		    (void) es_set_position(scratch, scratch_pos);		}	    } else {		/* Put back the deleted pieces */		if (delta == 0) {		    ft_add_delta(private->pieces, current,			(long)(r_header.stop_plus_one-r_header.start));		} else {		    ASSERT(PS_IS_AT_END(private, delta, current));		    current++;		}		ft_shift_up(&private->pieces, current,			    (int)(current+r_header.dp_count),			    (int)r_header.dp_count);		pieces = PIECES_IN_TABLE(private);		this_piece = &pieces[current];		delta = r_header.stop_plus_one-current_pos;		save_pos = adjust_pos_after_edit(save_pos, current_pos, delta);		for (i = 0; i < r_header.dp_count; i++, this_piece++) {		    (void) es_read(scratch, sizeof(d_header),				   (char *)&d_header, &read);		    this_piece->pos = current_pos;		    this_piece->length = d_header.length;		    this_piece->source_and_pos = d_header.source_and_pos;		    current_pos += d_header.length;		}		ASSERT(current_pos == r_header.stop_plus_one);		if (delta != 0) {	/* 0 iff no deleted pieces. */		    private->length += delta;		    if (notify_proc) {			scratch_pos = es_get_position(scratch);			notify_proc(notify_data, r_header.start, delta);			(void) es_set_position(scratch, scratch_pos);		    }		}	    }	    (void) es_read(scratch, sizeof(insert_len),			   (char *)&insert_len, &read);	    if (insert_len > 0) {		/*		 * Remove the inserted text.		 * Note that the user sequence: type-in edit-char type-in ...		 *   can cause this insert to span multiple pieces in the		 *   piece table.		 */		current += r_header.dp_count;		this_piece = &pieces[current];		for (delta = 0, i = 0; delta < insert_len;		     delta += this_piece->length, this_piece++) {		    ASSERT(this_piece->pos == current_pos+delta);		    ASSERT(this_piece->length <= insert_len-delta);		    i++;		}		ft_shift_out(&private->pieces, current, current+i);		ft_add_delta(private->pieces, current, -insert_len);		save_pos =		    adjust_pos_after_edit(save_pos, current_pos, -insert_len);		private->length -= insert_len;		if (notify_proc)		    notify_proc(notify_data, current_pos, -insert_len);	    }	    ASSUME(ps_pieces_are_consistent(private));	}	(void) es_set_position(scratch, ES_INFINITY);	SET_POSITION(private, save_pos);	private->last_write_plus_one = ES_INFINITY;}static caddr_tps_get(esh, attribute, va_alist)	Es_handle		esh;	Es_attribute		attribute;	va_dcl{	register Piece_table	private = ABS_TO_REP(esh);	Es_index		first, last_plus_one;	Es_handle		pieces_for_span, to_recycle;	va_list			args;	if ((private->magic != PS_MAGIC) && (attribute != ES_TYPE))	    return((caddr_t)0);	switch (attribute) {	  case ES_CLIENT_DATA:	    return(private->client_data);	  case ES_UNDO_MARK:	    private->last_write_plus_one = ES_INFINITY;	    /* +1 below is because 0 == ES_NULL_UNDO_MARK */	    return((caddr_t)(es_get_length(private->scratch)+1));	  case ES_HANDLE_FOR_SPAN:	    va_start(args);#ifdef lint	    first = (args ? 0 : 0);	    last_plus_one = 0;	    to_recycle = 0;#else	    first = va_arg(args, Es_index);	    last_plus_one = va_arg(args, Es_index);	    to_recycle = va_arg(args, Es_handle);#endif	    pieces_for_span = 		   ps_pieces_for_span(esh, first, last_plus_one, to_recycle);	    va_end(args);	    return((caddr_t)pieces_for_span);	  case ES_HAS_EDITS:	    return((caddr_t)(private->oldest_not_undone_mark != ES_INFINITY));	  case ES_PS_ORIGINAL:	    return((caddr_t)(private->original));	  case ES_PS_SCRATCH:	    return((caddr_t)(private->scratch));	  case ES_PS_SCRATCH_MAX_LEN:	    return((caddr_t)(private->scratch_max_len));  	  case ES_STATUS:	    return((caddr_t)(private->status));	  case ES_SIZE_OF_ENTITY:	    return(es_get(private->original, ES_SIZE_OF_ENTITY));	  case ES_TYPE:	    return((caddr_t)ES_TYPE_PIECE);	  default:	    return(0);	}}static intps_set(esh, attrs)	Es_handle	 esh;	caddr_t		*attrs;{	register Piece_table	  private = ABS_TO_REP(esh);	int			(*notify_proc)() = (int (*)())0;	caddr_t			  notify_data = 0;	Es_index		  undo_mark;	Es_index		  first;	Es_handle		  to_recycle;	Es_status		  status_dummy = ES_SUCCESS;	register Es_status	 *status;	status = &status_dummy;	if (private->magic != PS_MAGIC)	    *status = ES_INVALID_TYPE;	for (; *attrs && (*status == ES_SUCCESS); attrs = attr_next(attrs)) {	    switch ((Es_attribute)*attrs) {	      case ES_CLIENT_DATA:		private->client_data = attrs[1];		break;	      case ES_HANDLE_TO_INSERT:		to_recycle = (Es_handle)LINT_CAST(attrs[1]);		if (private->scratch_max_len == ES_INFINITY) {		    ps_insert_pieces(esh, to_recycle);		} else {		    /* When scratch is bounded, copy contents, not pieces. */		    *status = es_copy(to_recycle, esh, FALSE);		}		break;	      case ES_PS_ORIGINAL:		/* Caller should destroy the old private->original iff		 * return value is ES_SUCCESS, allowing for caller to		 * recover in case of errors.		 */		to_recycle = (Es_handle)LINT_CAST(attrs[1]);		first = es_get_position(private->original);		if (to_recycle == ES_NULL) {		    *status = ES_INVALID_HANDLE;		} else if (es_get_length(private->original) !=			   es_get_length(to_recycle)) {		    *status = ES_INCONSISTENT_LENGTH;		} else if (first != es_set_position(to_recycle, first)) {		    *status = ES_INCONSISTENT_POS;		} else {		    private->original = to_recycle;		}		break;	      case ES_PS_SCRATCH_MAX_LEN:		first = (Es_index)LINT_CAST(attrs[1]);		if (first < SCRATCH_MIN_LEN ||		    first < es_get_length(private->scratch)) {		    *status = ES_INCONSISTENT_LENGTH;		} else if (first >= ES_INFINITY) {		    if (private->scratch_max_len != ES_INFINITY) {			*status = ES_INCONSISTENT_LENGTH;		    }		} else {		    if (private->scratch_max_len == ES_INFINITY) {			es_set(private->scratch, ES_CLIENT_DATA, esh, 0);			private->scratch_max_len = first;			private->scratch_length =				es_get_length(private->scratch);			private->scratch_position =				es_get_position(private->scratch);			/* Modify the scratch ops vector. */			private->scratch_ops = private->scratch->ops;			private->scratch->ops =				(Es_ops)sv_malloc(sizeof(struct es_ops));			*private->scratch->ops = *private->scratch_ops;			private->scratch->ops->destroy = ps_scratch_destroy;			private->scratch->ops->get_length =				ps_scratch_get_length;			private->scratch->ops->get_position =				ps_scratch_get_position;			private->scratch->ops->set_position =				ps_scratch_set_position;			private->scratch->ops->read = ps_scratch_read;			private->scratch->ops->replace = ps_scratch_replace;		    }		}		break;	      case ES_STATUS:		private->status = (Es_status)LINT_CAST(attrs[1]);		break;	      case ES_STATUS_PTR:		status = (Es_status *)LINT_CAST(attrs[1]);		*status = status_dummy;		break;	      case ES_UNDO_MARK:		/* -1 below is because 0 == ES_NULL_UNDO_MARK */		undo_mark = ((Es_index)LINT_CAST(attrs[1]))-1;		ps_undo_to_mark(esh, undo_mark, notify_proc, notify_data);		break;	      case ES_UNDO_NOTIFY_PAIR:		notify_proc = (int (*)())LINT_CAST(attrs[1]);		notify_data = attrs[2];		break;	      default:		break;	    }	}	return((*status == ES_SUCCESS));}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -