This is paste.c in view mode; [Download] [Up]
/* * Copyright (c) 1992, 1995 John E. Davis (davis@space.mit.edu) * All Rights Reserved. */ #include <config.h> #include <stdio.h> #include <string.h> #include "buffer.h" #include "ins.h" #include "line.h" #include "paste.h" #include "screen.h" #include "misc.h" #include "cmds.h" /* SLang user object be larger than 128 */ #define JED_MARK_TYPE 128 Buffer *Paste_Buffer; Buffer *Rectangle_Buffer; /* This is used by the narrow command so that multiple windows are * handled properly. The assumption is that we are dealing with a canonical * region */ static void touch_windows(void) { Window_Type *w; Line *l; unsigned int n; w = JWindow; JWindow = JWindow->next; while (JWindow != w) { if (CBuf == JWindow->buffer) { /* The mark is set with line at top of buffer */ l = CBuf->marks->line; n = CBuf->marks->n; while ((l != NULL) && (l != JWindow->mark.line)) l = l->next, n++; if (l == NULL) { JWindow->mark.line = CLine; JWindow->mark.point = Point; JWindow->mark.n = n - 1; } touch_window(); } JWindow = JWindow->next; } pop_mark(&Number_Zero); } #if 0 static int line_in_buffer(Line *line) { Line *l; l = CBuf->beg; while (l != NULL) if (l == line) return(1); else l = l->next; return(0); } #endif /* with prefix argument, pop marks */ int set_mark_cmd() { Mark *m; if (Repeat_Factor != NULL) { while (CBuf->marks != NULL) pop_mark(&Number_Zero); Repeat_Factor = NULL; return(1); } if (CBuf->marks == NULL) { push_mark(); } m = CBuf->marks; m->line = CLine; m->point = Point; m->n = LineNum + CBuf->nup; if ((m->flags & VISIBLE_MARK) == 0) { m->flags |= VISIBLE_MARK; CBuf->vis_marks++; } /* if (m != CBuf->marks) m->next = CBuf->marks; CBuf->marks = m; */ if (Last_Key_Function == (FVOID_STAR) set_mark_cmd) message("Mark Set."); return(1); } int push_spot() { Mark *m; if (CBuf->spot_ptr < SPOT_ARRAY_SIZE) { m = &CBuf->spot_array[CBuf->spot_ptr++]; } else if (NULL == (m = (Mark *) SLMALLOC(sizeof(Mark)))) { exit_error("push_spot: malloc error!", 0); } m->line = CLine; m->point = Point; m->n = LineNum + CBuf->nup; m->next = CBuf->spots; CBuf->spots = m; return(1); } int push_mark() { Mark *m; if (CBuf->mark_ptr < SPOT_ARRAY_SIZE) { m = &CBuf->mark_array[CBuf->mark_ptr++]; } else if (NULL == (m = (Mark *) SLMALLOC(sizeof(Mark)))) { exit_error("push_mark: malloc error!", 0); } /* if (NULL == (m = (Mark *) SLMALLOC(sizeof(Mark)))) { msg_error("push_mark: malloc error!"); return(0); } */ m->line = CLine; m->point = Point; m->n = LineNum + CBuf->nup; m->next = CBuf->marks; m->flags = 0; CBuf->marks = m; return(1); } void goto_mark(Mark *m) { Line *l; l = m->line; LineNum = m->n; if (LineNum <= CBuf->nup) bob(); else if (LineNum > CBuf->nup + Max_LineNum) eob(); else { CLine = l; Point = m->point; LineNum -= CBuf->nup; } } int pop_mark(int *go) { Mark *m; m = CBuf->marks; if (m == NULL) return(0); if (*go) goto_mark(m); if (m->flags & VISIBLE_MARK) { CBuf->vis_marks--; /* touch screen since region may be highlighted */ if (CBuf->vis_marks == 0) touch_screen(); } CBuf->marks = m->next; if (m == &CBuf->mark_array[CBuf->mark_ptr - 1]) { CBuf->mark_ptr--; } else SLFREE(m); return(1); } int mark_spot() { push_spot(); message("Spot Marked."); return(1); } static int pop_spot_go (int go) { Mark *m; m = CBuf->spots; if (m == NULL) return(0); if (go) goto_mark (m); CBuf->spots = m->next; if (m == &CBuf->spot_array[CBuf->spot_ptr - 1]) { CBuf->spot_ptr--; } else SLFREE(m); return(1); } int pop_spot () { return pop_spot_go (1); } int exchange_point_mark(void) { Line *save_line; int save_point; unsigned int save_n; Mark *m; if ((m = CBuf->marks) == NULL) return(0); save_point = Point; save_line = CLine; save_n = LineNum + CBuf->nup; goto_mark (m); m->point = save_point; m->line = save_line; m->n = save_n; return(1); } /*returns 0 if the mark is not set and gives error. Exchanges point and mark * to produce valid region. A valid region is one with mark * earlier in the buffer than point. Always call this if using a region * which reqires point > mark. Also, push spot first then pop at end. */ int check_region(int *push) { register Line *beg, *tthis = CLine; int pbeg; if (CBuf->marks == NULL) { msg_error("Set mark first."); return(0); } if (*push) push_spot(); beg = CBuf->marks->line; pbeg = CBuf->marks->point; if (beg == CLine) { if (pbeg <= Point) return(1); } else { while((beg != NULL) && (beg != tthis)) beg = beg->next; if (beg == tthis) return(1); } exchange_point_mark(); return(1); } int widen_buffer_lines (Buffer *b) { Narrow_Type *n; Buffer *save = CBuf; if (NULL == (n = b->narrow)) return(0); /* make sure buffer ends in final newline */ switch_to_buffer(b); push_spot(); eob(); if ((n->end != NULL) && (!CLine->len || ('\n' != *(CLine->data + (CLine->len - 1))))) { unsigned int flags = CBuf->flags; ins('\n'); CBuf->flags = flags; } pop_spot(); if (n->end != NULL) n->end->prev = b->end; if (n->beg != NULL) n->beg->next = b->beg; b->end->next = n->end; b->beg->prev = n->beg; b->beg = n->beg1; if (n->end != NULL) b->end = n->end1; Max_LineNum += n->ndown + n->nup; LineNum += n->nup; /* adjust absolute offsets */ b->nup -= n->nup; b->ndown -= n->ndown; b->narrow = n->next; SLFREE(n); switch_to_buffer(save); return(1); } int widen_buffer (Buffer *b) { unsigned int flags; Buffer *save; if (b->narrow == NULL) return 0; if (b->narrow->is_region == 0) return widen_buffer_lines (b); flags = b->flags; b->flags &= ~READ_ONLY; save = CBuf; switch_to_buffer (b); push_spot (); bob (); push_spot (); eob (); widen_buffer_lines (CBuf); del (); pop_spot (); prevline (&Number_One); del (); pop_spot (); switch_to_buffer (save); b->flags = flags; return 1; } int narrow_to_region (void) { int pnt; Line *line; unsigned int flags; if (0 == check_region (&Number_One))/* spot pushed */ return 0; flags = CBuf->flags; CBuf->flags &= ~READ_ONLY; push_spot (); line = CLine; pnt = Point; pop_mark (&Number_One); /* Special case if region is empty */ if ((CLine == line) && (pnt == Point)) { pop_spot (); pop_spot (); newline (); push_mark (); newline (); prevline (&Number_One); if (narrow_to_lines ()) CBuf->narrow->is_region = 1; } else { newline (); push_mark (); pop_spot (); newline (); prevline (&Number_One); if (narrow_to_lines ()) CBuf->narrow->is_region = 1; pop_spot (); } CBuf->flags = flags; return 1; } int widen () { return widen_buffer_lines (CBuf); } int widen_region (void) { return widen_buffer (CBuf); } /* not really a region of points but a region of lines. */ int narrow_to_lines () { Line *beg; Narrow_Type *nt; if (NULL == (nt = (Narrow_Type *) SLMALLOC(sizeof(Narrow_Type)))) { msg_error("Malloc Error during narrow."); return(0); } if (!check_region(&Number_One)) return(0); /* spot pushed */ push_spot(); pop_mark(&Number_One); push_mark(); /* popped and used in touch_windows! */ beg = CLine; nt->nup = LineNum - 1; pop_spot(); /* eor now */ nt->ndown = Max_LineNum - LineNum; Max_LineNum = LineNum = LineNum - nt->nup; CBuf->nup += nt->nup; CBuf->ndown += nt->ndown; nt->next = CBuf->narrow; CBuf->narrow = nt; nt->beg = beg->prev; nt->end = CLine->next; nt->beg1 = CBuf->beg; nt->end1 = CBuf->end; nt->is_region = 0; CBuf->beg = beg; CBuf->end = CLine; beg->prev = NULL; CLine->next = NULL; if (CLine->len && (CLine->data[CLine->len - 1] == '\n')) { /* I do not think that this will affect undo. */ CLine->len--; } pop_spot(); touch_windows(); return(1); } int yank() { CHECK_READ_ONLY if (Paste_Buffer == NULL) return(0); insert_buffer(Paste_Buffer); return(1); } int copy_region_to_buffer(Buffer *b) { int first_point, last_point, n, tmpm; Line *first, *last; Buffer *save_buffer; if (b->flags & READ_ONLY) { msg_error(Read_Only_Error); return (0); } if (!check_region(&Number_One)) return(0); /* spot pushed */ last = CLine; last_point = Point; tmpm = 1; pop_mark(&tmpm); if (b == CBuf) { msg_error("A buffer cannot be inserted upon itself."); pop_spot(); return(0); } first = CLine; first_point = Point; save_buffer = CBuf; switch_to_buffer(b); /* go through standard routines for undo comapatability */ Suspend_Screen_Update = 1; if (first == last) { n = last_point - first_point; if (save_buffer == MiniBuffer) { ins_chars(first->data + first_point, n); } else quick_insert(first->data + first_point, n); } else { n = first->len - first_point; quick_insert(first->data + first_point, n); while (first = first->next, first != last) { quick_insert(first->data, first->len); } quick_insert(first->data, last_point); } switch_to_buffer(save_buffer); pop_spot(); return(1); } int copy_to_pastebuffer() { /* delete paste buffer */ if (Paste_Buffer != NULL) delete_buffer(Paste_Buffer); Paste_Buffer = make_buffer(); strcpy(Paste_Buffer->name, " <paste>"); copy_region_to_buffer(Paste_Buffer); return(0); } int delete_region (void) { int beg_point, tmpm, end_point, n; Line *beg, *end; CHECK_READ_ONLY if (!check_region(&Number_Zero)) return(0); /* make this go through standard ins/del routines to ensure undo */ end = CLine; end_point = Point; push_spot(); tmpm = 1; pop_mark(&tmpm); beg = CLine; beg_point = Point; pop_spot(); Point = 0; if (end != beg) { deln(&end_point); /* go back because we do not want to mess with Line structures changing on us --- shouldn't happen anyway */ while (CLine = CLine->prev, LineNum--, CLine != beg) { eol(); n = Point + 1; Point = 0; generic_deln(&n); } eol(); n = Point - beg_point + 1; /* the \n char */ Point = beg_point; } else { Point = beg_point; n = end_point - Point; } generic_deln(&n); return(1); } int kill_region() { int tmpm = 1; CHECK_READ_ONLY /* need two marks for this one */ push_spot(); if (!pop_mark(&tmpm)) { check_region(&Number_Zero); pop_spot(); return(0); } push_mark(); push_mark(); pop_spot(); copy_to_pastebuffer(); delete_region(); return(1); } static char *Rect_Error = "Rectangle has 0 width."; int insert_rectangle() { int c1; Line *rline; CHECK_READ_ONLY if (Rectangle_Buffer == NULL) return(0); Suspend_Screen_Update = 1; c1 = calculate_column(); rline = Rectangle_Buffer->beg; if (rline != NULL) while (1) { goto_column(&c1); quick_insert(rline->data, rline->len); rline = rline->next; if (rline == NULL) break; if (CLine->next == NULL) { eol(); newline(); } else { CLine = CLine->next; LineNum++; } } return(1); } int open_rectangle() { int c1, n, c2, tmpm; Line *save_line; CHECK_READ_ONLY if (!check_region(&Number_One)) return(0); /* push_spot(); performed */ c1 = calculate_column(); save_line = CLine; tmpm = 1; pop_mark(&tmpm); c2 = calculate_column(); n = c2 - c1; if (n < 0) { n = -n; c1 = c2; } Suspend_Screen_Update = 1; while(1) { goto_column(&c1); ins_char_n_times(' ', n); if (CLine == save_line) break; CLine = CLine->next; LineNum++; } pop_spot(); return(1); } /* rectangle commands */ int copy_rectangle() { Line *save_line, *line, *beg; int c1, c2, dc, tmp, tmpm, dc_malloc; unsigned char *p1, *p2, *data; if (!check_region(&Number_One)) return(0); /* spot pushed */ /* delete Rectangle buffer */ if (Rectangle_Buffer != NULL) delete_buffer(Rectangle_Buffer); Rectangle_Buffer = make_buffer(); strcpy(Rectangle_Buffer->name, " <rect>"); c2 = calculate_column(); save_line = CLine; tmpm = 1; pop_mark(&tmpm); c1 = calculate_column(); if (c1 == c2) { msg_error(Rect_Error); pop_spot(); return(0); } if (c1 > c2) { tmp = c1; c1 = c2; c2 = tmp; goto_column(&c1); } /* go through the region copying rectanglar blocks to Rectanglebuffer */ dc = c2 - c1; if (dc == 1) dc_malloc = 2; else dc_malloc = dc; line = beg = make_line1(dc_malloc); beg->prev = NULL; while (1) { data = line->data; /* p1 = data; p2 = data + dc; while (p1 < p2) *p1++ = ' '; */ MEMSET ((char *) data, ' ', dc); line->len = dc; if (c1 == goto_column1(&c1)) { p1 = CLine->data + Point; (void) goto_column1(&c2); p2 = CLine->data + Point; /* while(p1 < p2) *data++ = *p1++; */ MEMCPY((char *) data, (char *) p1, (int) (p2 - p1)); } if (CLine == save_line) break; CLine = CLine->next; LineNum++; line->next = make_line1(dc_malloc); line->next->prev = line; line = line->next; } line->next = NULL; Rectangle_Buffer->line = Rectangle_Buffer->beg = beg; Rectangle_Buffer->end = line; Rectangle_Buffer->point = 0; pop_spot(); return(0); } int kill_rectangle() { Line *save_line, *line, *beg; int c1, c2, dc, tmp, n, tmpm, dc_malloc; unsigned char *p1, *p2, *data; CHECK_READ_ONLY if (!check_region(&Number_One)) return(0); /* delete Rectangle buffer */ if (Rectangle_Buffer != NULL) delete_buffer(Rectangle_Buffer); Rectangle_Buffer = make_buffer(); strcpy(Rectangle_Buffer->name, " <rect>"); c2 = calculate_column(); save_line = CLine; tmpm = 1; pop_mark(&tmpm); c1 = calculate_column(); if (c1 == c2) { msg_error(Rect_Error); pop_spot(); return(0); } if (c1 > c2) { tmp = c1; c1 = c2; c2 = tmp; goto_column(&c1); } Suspend_Screen_Update = 1; /* go through the region copying rectanglar blocks to Rectanglebuffer */ dc = c2 - c1; if (dc == 1) dc_malloc = 2; else dc_malloc = dc; /* length of 1 not usable here. * See makeline1 to see why */ line = beg = make_line1(dc_malloc); beg->prev = NULL; while (1) { data = line->data; /* p2 = data + dc; p1 = data; while (p1 < p2) *p1++ = ' '; */ MEMSET((char *) data, ' ', dc); line->len = dc; if (c1 == goto_column1(&c1)) { p1 = CLine->data + Point; (void) goto_column1(&c2); p2 = CLine->data + Point; Point = (int) (p1 - CLine->data); n = (int) (p2 - p1); MEMCPY((char *) data, (char *) p1, n); deln (&n); /* while(n-- > 0) { *data++ = *p1; del(); } */ } if (CLine == save_line) break; CLine = CLine->next; LineNum++; line->next = make_line1(dc_malloc); line->next->prev = line; line = line->next; } line->next = NULL; Rectangle_Buffer->line = Rectangle_Buffer->beg = beg; Rectangle_Buffer->end = line; Rectangle_Buffer->point = 0; pop_spot(); return(0); } int blank_rectangle() { int c1, n, c2, pnt, tmpm; Line *save_line; int nn; CHECK_READ_ONLY if (!check_region(&Number_One)) return(0); /* push_spot(); performed */ c1 = calculate_column(); save_line = CLine; tmpm = 1; pop_mark(&tmpm); c2 = calculate_column(); n = c2 - c1; if (n < 0) { n = -n; c1 = c2; } Suspend_Screen_Update = 1; while(1) { goto_column(&c1); pnt = Point; eol(); nn = Point - pnt; if (nn > n) nn = n; Point = pnt; deln(&nn); ins_char_n_times( ' ', nn); if (CLine == save_line) break; CLine = CLine->next; LineNum++; } pop_spot(); /* mark_buffer_modified(&Number_One); */ return(1); } /* User Marks */ typedef struct { Mark m; /* MUST be the first */ Buffer *b; } User_Mark_Type; static void free_user_mark (User_Mark_Type *um) { Mark *m, *m1; Buffer *b; m1 = &um->m; /* The mark is only valid if the buffer that it was created for still * exists. */ if ((m1->flags & MARK_INVALID) == 0) { /* Unlink the mark from the chain. */ b = um->b; m = b->user_marks; if (m == m1) b->user_marks = m1->next; else { while (m->next != m1) m = m->next; m->next = m1->next; } } SLFREE (um); } void free_user_marks (Buffer *b) { Mark *m = b->user_marks; while (m != NULL) { m->flags |= MARK_INVALID; m = m->next; } } static int mark_valid (Mark *m) { if (m->flags & MARK_INVALID) { msg_error ("Mark is invalid."); return 0; } return 1; } int jed_move_user_object_mark (SLuser_Object_Type *uo) { User_Mark_Type *um; Mark *m; um = (User_Mark_Type *) uo->obj; m = &um->m; if (!mark_valid (m)) return 0; if (CBuf != um->b) { msg_error ("Mark not in buffer."); return 0; } m->line = CLine; m->point = Point; m->n = LineNum + CBuf->nup; return 1; } void move_user_mark (void) { SLuser_Object_Type *uo; if ((uo = SLang_pop_user_object (JED_MARK_TYPE)) == NULL) return; (void) jed_move_user_object_mark (uo); SLang_free_user_object (uo); } void goto_user_mark (void) { SLuser_Object_Type *uo; User_Mark_Type *um; if ((uo = SLang_pop_user_object (JED_MARK_TYPE)) == NULL) return; um = (User_Mark_Type *) uo->obj; if (mark_valid (&um->m)) { if (CBuf != um->b) msg_error ("Mark not in buffer."); else goto_mark (&um->m); } SLang_free_user_object (uo); } SLuser_Object_Type *jed_make_user_object_mark (int main_type) { User_Mark_Type *um; SLuser_Object_Type *uo; Mark *m; uo = SLang_create_user_object (JED_MARK_TYPE); if (uo == NULL) return NULL; uo->main_type = main_type; if (NULL == (um = (User_Mark_Type *) SLMALLOC (sizeof(User_Mark_Type)))) { SLang_Error = SL_MALLOC_ERROR; SLFREE (uo); return NULL; } m = &um->m; m->line = CLine; m->point = Point; m->n = LineNum + CBuf->nup; m->next = CBuf->user_marks; m->flags = 0; CBuf->user_marks = m; um->b = CBuf; uo->obj = (long *) um; return uo; } void jed_free_user_object_mark (SLuser_Object_Type *uo) { /* let slang handle this. */ uo->main_type = SLANG_DATA; SLang_free_user_object (uo); } void create_user_mark (void) { SLuser_Object_Type *uo = jed_make_user_object_mark (SLANG_DATA); if (uo != NULL) SLang_push_user_object (uo); } char *user_mark_buffer (void) { SLuser_Object_Type *uo; User_Mark_Type *um; char *s = ""; if (NULL == (uo = SLang_pop_user_object (JED_MARK_TYPE))) return s; um = (User_Mark_Type *) uo->obj; if (mark_valid (&um->m)) { s = um->b->name; } SLang_free_user_object (uo); return s; } int register_jed_classes (void) { return SLang_register_class (JED_MARK_TYPE, (FVOID_STAR) free_user_mark, NULL); }
These are the contents of the former NiCE NeXT User Group NeXTSTEP/OpenStep software archive, currently hosted by Netfuture.ch.