xref: /original-bsd/contrib/ed/m.c (revision 044d1bee)
1 /*-
2  * Copyright (c) 1992 The Regents of the University of California.
3  * All rights reserved.
4  *
5  * This code is derived from software contributed to Berkeley by
6  * Rodney Ruddock of the University of Guelph.
7  *
8  * %sccs.include.redist.c%
9  */
10 
11 #ifndef lint
12 static char sccsid[] = "@(#)m.c	5.2 (Berkeley) 01/23/93";
13 #endif /* not lint */
14 
15 #include <sys/types.h>
16 
17 #include <db.h>
18 #include <regex.h>
19 #include <setjmp.h>
20 #include <stdio.h>
21 #include <string.h>
22 
23 #include "ed.h"
24 #include "extern.h"
25 
26 /*
27  * Move the specified lines to the new location. It's quick 'cause
28  * just a couple of pointers are redirected.
29  */
30 void
31 m(inputt, errnum)
32 	FILE *inputt;
33 	int *errnum;
34 {
35 	LINE *l_dest, *l_old_top, *l_old_bottom;
36 
37 	/* Set l_dest here. */
38 	if (((ss = getc(inputt)) != '\n') && (ss != EOF)) {
39 		for (;;) {
40 			if (ss != ' ') {
41 				ungetc(ss, inputt);
42 				break;
43 			}
44 			ss = getc(inputt);
45 		}
46 		l_dest = address_conv(NULL, inputt, errnum);
47 	} else
48 		(ungetc(ss, inputt), *errnum = -1);
49 	if (sigint_flag)
50 		SIGINT_ACTION;
51 	if (*errnum < 0) {
52 		strcpy(help_msg, "bad destination address");
53 		return;
54 	}
55 	*errnum = 0;
56 	if (rol(inputt, errnum))
57 		return;
58 
59 	if (start_default && End_default)
60 		start = End = current;
61 	else
62 		if (start_default)
63 			start = End;
64 	if (start == NULL) {
65 		strcpy(help_msg, "bad address");
66 		*errnum = -1;
67 		return;
68 	}
69 	start_default = End_default = 0;
70 	if (sigint_flag)
71 		SIGINT_ACTION;
72 
73 	/* Do some address checking. */
74 	if ((l_dest) && ((l_dest == start) ||
75 	    (address_check(l_dest, start) == -1)) &&
76 	    (address_check(End, l_dest) == -1)) {
77 		ungetc(ss, inputt);
78 		*errnum = -1;
79 		strcpy(help_msg, "destination address in address range");
80 		return;
81 	}
82 	change_flag = 1;
83 	if (g_flag == 0)
84 		u_clr_stk();
85 
86 	/*
87 	 * Some more address checking. These are "legal" command constructions
88 	 * but are kind-a useless since the buffer doesn't change.
89 	 */
90 	if ((start == l_dest) || (End == l_dest))
91 		return;
92 	if ((start == top) && (End == bottom))
93 		return;
94 	if ((start == top) && (l_dest == NULL))
95 		return;
96 
97 	l_old_top = top;
98 	l_old_bottom = bottom;
99 
100 	if (start == top) {
101 		top = End->below;
102 		u_add_stk(&(End->below->above));
103 		top->above = NULL;
104 	} else
105 		if (End == bottom) {
106 			bottom = start->above;
107 			u_add_stk(&(start->above->below));
108 			bottom->below = NULL;
109 		} else {
110 			u_add_stk(&(start->above->below));
111 			start->above->below = End->below;
112 			u_add_stk(&(End->below->above));
113 			End->below->above = start->above;
114 		}
115 
116 	if (l_dest == NULL) {
117 		u_add_stk(&(start->above));
118 		start->above = NULL;
119 		u_add_stk(&(End->below));
120 		End->below = l_old_top;
121 		u_add_stk(&(l_old_top->above));
122 		l_old_top->above = End;
123 		top = start;
124 	} else
125 		if (l_dest == l_old_bottom) {
126 			u_add_stk(&(End->below));
127 			End->below = NULL;
128 			u_add_stk(&(start->above));
129 			start->above = l_dest;
130 			u_add_stk(&(l_dest->below));
131 			l_dest->below = start;
132 			bottom = End;
133 		} else {
134 			u_add_stk(&(start->above));
135 			start->above = l_dest;
136 			u_add_stk(&(End->below));
137 			End->below = l_dest->below;
138 			u_add_stk(&(l_dest->below->above));
139 			l_dest->below->above = End;
140 			u_add_stk(&(l_dest->below));
141 			l_dest->below = start;
142 		}
143 
144 	if (l_dest)
145 		l_dest->below = start;
146 	current = start;
147 
148 	*errnum = 1;
149 }
150