/* -*- mode: C; mode: fold; -*- */ /* * Copyright (c) 1992, 1995 John E. Davis (davis@space.mit.edu) * All Rights Reserved. */ #include "config.h" #include "jed-feat.h" /*{{{ Include Files */ #include #include #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 /*{{{ Spot/Mark Functions */ static void init_mark (Mark *m, unsigned int flags) /*{{{*/ { m->line = CLine; m->point = Point; m->n = LineNum + CBuf->nup; m->flags = flags; } /*}}}*/ #if JED_HAS_SAVE_NARROW static Mark *create_mark (unsigned int flags) /*{{{*/ { Mark *m; if (NULL == (m = (Mark *) SLmalloc (sizeof(Mark)))) { exit_error("create-mark: malloc error", 0); } init_mark (m, flags); return m; } /*}}}*/ #endif /* with prefix argument, pop marks */ int set_mark_cmd (void) /*{{{*/ { 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; init_mark (m, m->flags); 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); } /*}}}*/ static Mark *allocate_mark (Jed_Mark_Array_Type **ap, Mark **mp, unsigned int flags) /*{{{*/ { Jed_Mark_Array_Type *a, *b; Mark *m; a = *ap; if ((a == NULL) || (a->num_marks == JED_MAX_MARK_ARRAY_SIZE)) { if (NULL == (b = (Jed_Mark_Array_Type *) SLmalloc (sizeof(Jed_Mark_Array_Type)))) { exit_error("allocate_mark: malloc error", 0); } memset ((char *) b, 0, sizeof (Jed_Mark_Array_Type)); b->next = a; a = b; *ap = a; } m = &a->marks[a->num_marks]; a->num_marks += 1; m->next = *mp; *mp = m; init_mark (m, flags); return m; } /*}}}*/ static void deallocate_mark (Jed_Mark_Array_Type **ap, Mark **mp) /*{{{*/ { Jed_Mark_Array_Type *a; Mark *m; m = *mp; *mp = m->next; a = *ap; a->num_marks -= 1; if (a->num_marks == 0) { *ap = a->next; SLfree ((char *)a); } } /*}}}*/ int push_spot() /*{{{*/ { (void) allocate_mark (&CBuf->spot_array, &CBuf->spots, 0); return 1; } /*}}}*/ int push_mark() /*{{{*/ { (void) allocate_mark (&CBuf->mark_array, &CBuf->marks, 0); return 1; } /*}}}*/ int goto_mark(Mark *m) /*{{{*/ { Line *l; int ret = -1; 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; ret = 0; } return ret; } /*}}}*/ 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(); } deallocate_mark (&CBuf->mark_array, &CBuf->marks); 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); deallocate_mark (&CBuf->spot_array, &CBuf->spots); 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); } /*}}}*/ /*}}}*/ /*{{{ Narrow/Widen/Region Functions */ /*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); } /*}}}*/ static 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 ((char *)n); switch_to_buffer(save); return(1); } /*}}}*/ int widen_buffer (Buffer *b) /*{{{*/ { unsigned int flags; #if JED_HAS_LINE_ATTRIBUTES unsigned int line_flags; #endif 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; if (b != CBuf) switch_to_buffer (b); push_spot (); bob (); push_spot (); eob (); widen_buffer_lines (CBuf); #if JED_HAS_LINE_ATTRIBUTES line_flags = CLine->flags; CLine->flags &= ~JED_LINE_READONLY; #endif del (); #if JED_HAS_LINE_ATTRIBUTES CLine->flags = line_flags; #endif pop_spot (); prevline (&Number_One); #if JED_HAS_LINE_ATTRIBUTES line_flags = CLine->flags; CLine->flags &= ~JED_LINE_READONLY; #endif del (); #if JED_HAS_LINE_ATTRIBUTES CLine->flags = line_flags; #endif pop_spot (); if (save != CBuf) switch_to_buffer (save); b->flags = flags; return 1; } /*}}}*/ int narrow_to_region (void) /*{{{*/ { int pnt; Line *line; unsigned int flags; #if JED_HAS_LINE_ATTRIBUTES unsigned int line_flags; #endif 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 (); #if JED_HAS_LINE_ATTRIBUTES line_flags = CLine->flags; CLine->flags &= ~JED_LINE_READONLY; #endif newline (); #if JED_HAS_LINE_ATTRIBUTES CLine->prev->flags = line_flags; #endif push_mark (); newline (); #if JED_HAS_LINE_ATTRIBUTES CLine->flags = line_flags; #endif prevline (&Number_One); #if JED_HAS_LINE_ATTRIBUTES CLine->flags = line_flags; #endif if (narrow_to_lines ()) CBuf->narrow->is_region = 1; } else { #if JED_HAS_LINE_ATTRIBUTES line_flags = CLine->flags; CLine->flags &= ~JED_LINE_READONLY; #endif newline (); #if JED_HAS_LINE_ATTRIBUTES CLine->flags = line_flags; CLine->prev->flags = line_flags; #endif push_mark (); pop_spot (); #if JED_HAS_LINE_ATTRIBUTES line_flags = CLine->flags; CLine->flags &= ~JED_LINE_READONLY; #endif newline (); #if JED_HAS_LINE_ATTRIBUTES CLine->flags = line_flags; #endif prevline (&Number_One); #if JED_HAS_LINE_ATTRIBUTES CLine->flags = line_flags; #endif 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)))) { 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); } /*}}}*/ /*}}}*/ /*{{{ Pastebuffer, Delete Region functions */ 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 (" ", NULL, NULL); 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); } /*}}}*/ /*}}}*/ /*{{{ Rectangle Functions */ 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 (" ", NULL, NULL); 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++ = ' '; */ SLMEMSET ((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++; */ SLMEMCPY((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 (" ", NULL, NULL); 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++ = ' '; */ SLMEMSET((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); SLMEMCPY((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 Mark Functions */ typedef struct /*{{{*/ { Mark m; /* MUST be the first */ Buffer *b; } /*}}}*/ User_Mark_Type; static void free_user_mark (unsigned char type, VOID_STAR um_alias) /*{{{*/ { Mark *m, *m1; Buffer *b; User_Mark_Type *um; (void) type; um = (User_Mark_Type *) um_alias; 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 JED_HAS_LINE_MARKS if (m1->flags & JED_LINE_MARK) touch_screen (); #endif if (m == m1) b->user_marks = m1->next; else { while (m->next != m1) m = m->next; m->next = m1->next; } } SLfree ((char *)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 (SLang_MMT_Type *mmt) /*{{{*/ { User_Mark_Type *um; Mark *m; um = (User_Mark_Type *) SLang_object_from_mmt (mmt); 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) /*{{{*/ { SLang_MMT_Type *mmt; if (NULL == (mmt = SLang_pop_mmt (JED_MARK_TYPE))) return; (void) jed_move_user_object_mark (mmt); SLang_free_mmt (mmt); } /*}}}*/ static int x_user_mark_fun (int (*xfun)(Mark *)) /*{{{*/ { SLang_MMT_Type *mmt; User_Mark_Type *um; int ret = -1; if (NULL == (mmt = SLang_pop_mmt (JED_MARK_TYPE))) return -1; um = (User_Mark_Type *) SLang_object_from_mmt (mmt); if (mark_valid (&um->m)) { if (CBuf != um->b) msg_error ("Mark not in buffer."); else ret = (*xfun) (&um->m); } SLang_free_mmt (mmt); return ret; } /*}}}*/ /* It is up to calling routine to ensure that mark is in buffer. */ static int is_mark_in_narrow (Mark *m) { return ((m->n > CBuf->nup) && (m->n <= CBuf->nup + Max_LineNum)); } int jed_is_user_mark_in_narrow (void) { return x_user_mark_fun (is_mark_in_narrow); } void goto_user_mark (void) { (void) x_user_mark_fun (goto_mark); } SLang_MMT_Type *jed_make_user_object_mark (void) /*{{{*/ { User_Mark_Type *um; SLang_MMT_Type *mmt; Mark *m; if (NULL == (um = (User_Mark_Type *) SLmalloc (sizeof(User_Mark_Type)))) return NULL; if (NULL == (mmt = SLang_create_mmt (JED_MARK_TYPE, (VOID_STAR) um))) { SLfree ((char *) um); return NULL; } m = &um->m; init_mark (m, 0); m->next = CBuf->user_marks; CBuf->user_marks = m; um->b = CBuf; return mmt; } /*}}}*/ void create_user_mark (void) /*{{{*/ { SLang_MMT_Type *mmt; if (NULL != (mmt = jed_make_user_object_mark ())) { if (-1 == SLang_push_mmt (mmt)) SLang_free_mmt (mmt); } } /*}}}*/ char *user_mark_buffer (void) /*{{{*/ { SLang_MMT_Type *mmt; User_Mark_Type *um; char *s = ""; if (NULL == (mmt = SLang_pop_mmt (JED_MARK_TYPE))) return s; um = (User_Mark_Type *) SLang_object_from_mmt (mmt); if (mark_valid (&um->m)) { s = um->b->name; } SLang_free_mmt (mmt); return s; } /*}}}*/ static int user_mark_bin_op_result (int op, unsigned char a, unsigned char b, unsigned char *c) { (void) a; (void) b; switch (op) { default: return 0; case SLANG_GT: case SLANG_GE: case SLANG_LT: case SLANG_LE: case SLANG_EQ: case SLANG_NE: *c = SLANG_INT_TYPE; break; } return 1; } static int user_mark_bin_op (int op, unsigned char a_type, VOID_STAR ap, unsigned int na, unsigned char b_type, VOID_STAR bp, unsigned int nb, VOID_STAR cp) { int *ic; unsigned int n, n_max; unsigned int da, db; SLang_MMT_Type **a, **b; (void) a_type; (void) b_type; if (na == 1) da = 0; else da = 1; if (nb == 1) db = 0; else db = 1; if (na > nb) n_max = na; else n_max = nb; a = (SLang_MMT_Type **) ap; b = (SLang_MMT_Type **) bp; ic = (int *) cp; for (n = 0; n < n_max; n++) { User_Mark_Type *ua, *ub; Buffer *ba, *bb; int pa, pb; unsigned int la, lb; ua = ub = NULL; ba = bb = NULL; pa = pb = 0; la = lb = 0; if ((*a != NULL) && (NULL != (ua = (User_Mark_Type *) SLang_object_from_mmt (*a)))) { la = ua->m.n; pa = ua->m.point; ba = ua->b; } if ((*b != NULL) && (NULL != (ub = (User_Mark_Type *) SLang_object_from_mmt (*b)))) { lb = ub->m.n; pb = ub->m.point; bb = ub->b; } if ((ba == NULL) || (bb == NULL)) { ic[n] = 0; a += da; b += db; continue; } switch (op) { case SLANG_GT: ic[n] = ((la > lb) || ((la == lb) && (pa > pb))); break; case SLANG_GE: ic[n] = ((la > lb) || ((la == lb) && (pa >= pb))); break; case SLANG_LT: ic[n] = ((la < lb) || ((la == lb) && (pa < pb))); break; case SLANG_LE: ic[n] = ((la < lb) || ((la == lb) && (pa <= pb))); break; case SLANG_EQ: ic[n] = ((ba == bb) && (la == lb) && (pa == pb)); break; case SLANG_NE: ic[n] = ((ba != bb) || (la != lb) || (pa != pb)); break; default: return 0; } a += da; b += db; } return 1; } /*}}}*/ #if JED_HAS_LINE_MARKS void jed_create_line_mark (int *color) /*{{{*/ { SLang_MMT_Type *mmt; User_Mark_Type *um; if (NULL == (mmt = jed_make_user_object_mark ())) return; um = (User_Mark_Type *) SLang_object_from_mmt (mmt); um->m.flags |= JED_LINE_MARK | (*color & MARK_COLOR_MASK); if (-1 == SLang_push_mmt (mmt)) SLang_free_mmt (mmt); } /*}}}*/ #endif int register_jed_classes (void) /*{{{*/ { SLang_Class_Type *cl; cl = SLclass_allocate_class ("Mark_Type"); if (cl == NULL) return -1; (void) SLclass_set_destroy_function (cl, free_user_mark); if (-1 == SLclass_register_class (cl, JED_MARK_TYPE, sizeof (User_Mark_Type), SLANG_CLASS_TYPE_MMT)) return -1; if (-1 == SLclass_add_binary_op (JED_MARK_TYPE, JED_MARK_TYPE, user_mark_bin_op, user_mark_bin_op_result)) return -1; return 0; } /*}}}*/ void jed_widen_whole_buffer (Buffer *b) /*{{{*/ { while (b->narrow != NULL) widen_buffer (b); } /*}}}*/ #if JED_HAS_SAVE_NARROW static void restore_saved_narrow (void) /*{{{*/ { Mark *beg, *end; Jed_Save_Narrow_Type *save_narrow; if (NULL == (save_narrow = CBuf->save_narrow)) return; push_spot (); /* remove current restriction */ jed_widen_whole_buffer (CBuf); beg = save_narrow->beg; end = save_narrow->end; while (beg != NULL) { goto_mark (beg); push_mark (); goto_mark (end); if (end->flags & NARROW_REGION_MARK) narrow_to_region (); else narrow_to_lines (); beg = beg->next; end = end->next; } pop_spot (); } /*}}}*/ static void free_mark_chain (Mark *m) /*{{{*/ { Mark *next; while (m != NULL) { next = m->next; SLfree ((char *)m); m = next; } } /*}}}*/ void jed_free_saved_narrow (void) /*{{{*/ { Jed_Save_Narrow_Type *save_narrow; save_narrow = CBuf->save_narrow; if (save_narrow == NULL) return; CBuf->save_narrow = save_narrow->next; free_mark_chain (save_narrow->beg); free_mark_chain (save_narrow->end); SLfree ((char *)save_narrow); } /*}}}*/ void jed_push_narrow (void) /*{{{*/ { Jed_Save_Narrow_Type *save_narrow; if (NULL == (save_narrow = (Jed_Save_Narrow_Type *) SLmalloc (sizeof (Jed_Save_Narrow_Type)))) { exit_error ("push_narrow: malloc error.", 0); } save_narrow->beg = save_narrow->end = NULL; save_narrow->next = CBuf->save_narrow; CBuf->save_narrow = save_narrow; push_spot (); while (CBuf->narrow != NULL) { Mark *m; bob (); m = create_mark (0); m->next = save_narrow->beg; save_narrow->beg = m; eob (); m = create_mark (CBuf->narrow->is_region ? NARROW_REGION_MARK : 0); m->next = save_narrow->end; save_narrow->end = m; widen_buffer (CBuf); } restore_saved_narrow (); pop_spot (); } /*}}}*/ void jed_pop_narrow (void) /*{{{*/ { restore_saved_narrow (); jed_free_saved_narrow (); } /*}}}*/ #endif int jed_count_narrows (void) /*{{{*/ { int n = 0; Narrow_Type *nt = CBuf->narrow; while (nt != NULL) { n++; nt = nt->next; } return n; } /*}}}*/