Add support for tab-completion when selecting by rule
[alpine.git] / pico / region.c
blobf0d8c09cb5c3cf819cf153eb207b257ac840656f
1 /*
2 * ========================================================================
3 * Copyright 2006 University of Washington
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * ========================================================================
15 * Program: Region management routines
17 * The routines in this file
18 * deal with the region, that magic space
19 * between "." and mark. Some functions are
20 * commands. Some functions are just for
21 * internal use.
23 #include "headers.h"
26 * Kill the region. Ask "getregion"
27 * to figure out the bounds of the region.
28 * Move "." to the start, and kill the characters.
29 * Bound to "C-W".
31 int
32 killregion(int f, int n)
34 REGION region;
36 if (curbp->b_mode&MDVIEW) /* don't allow this command if */
37 return(rdonly()); /* we are in read only mode */
39 if (getregion(&region, curwp->w_markp, curwp->w_marko) != TRUE){
40 return (killtext(f, n));
41 }else {
42 mlerase();
45 if ((lastflag&CFKILL) == 0) /* This is a kill type */
46 kdelete(); /* command, so do magic */
48 thisflag |= CFKILL; /* kill buffer stuff. */
49 curwp->w_dotp = region.r_linep;
50 curwp->w_doto = region.r_offset;
51 curwp->w_markp = NULL;
52 #ifdef _WINDOWS
53 mswin_allowcopycut(NULL);
54 #endif
56 if(ldelete(region.r_size, kinsert)){
57 if(curwp->w_dotp == curwp->w_linep && curwp->w_dotp == curbp->b_linep){
58 curwp->w_force = 0; /* Center dot. */
59 curwp->w_flag |= WFFORCE;
62 return(TRUE);
65 return (FALSE);
70 * Blast the region without saving . Ask "getregion"
71 * to figure out the bounds of the region.
72 * Move "." to the start, and kill the characters.
73 * Bound to "C-W".
75 int
76 deleteregion(int f, int n)
78 REGION region;
80 if (curbp->b_mode&MDVIEW) /* don't allow this command if */
81 return(rdonly()); /* we are in read only mode */
83 if (getregion(&region, curwp->w_markp, curwp->w_marko) == TRUE){
84 curwp->w_dotp = region.r_linep;
85 curwp->w_doto = region.r_offset;
86 curwp->w_markp = NULL;
87 #ifdef _WINDOWS
88 mswin_allowcopycut(NULL);
89 #endif
90 if(ldelete(region.r_size, NULL)){
91 if(curwp->w_dotp == curwp->w_linep
92 && curwp->w_dotp == curbp->b_linep){
93 curwp->w_force = 0; /* Center dot. */
94 curwp->w_flag |= WFFORCE;
97 return(TRUE);
101 return (FALSE);
106 * Copy all of the characters in the
107 * region to the kill buffer. Don't move dot
108 * at all. This is a bit like a kill region followed
109 * by a yank. Bound to "M-W".
112 copyregion(int f, int n)
114 register LINE *linep;
115 register int loffs;
116 register int s;
117 REGION region;
119 if ((s=getregion(&region, curwp->w_markp, curwp->w_marko)) != TRUE)
120 return (s);
122 if ((lastflag&CFKILL) == 0) /* Kill type command. */
123 kdelete();
125 thisflag |= CFKILL;
126 linep = region.r_linep; /* Current line. */
127 loffs = region.r_offset; /* Current offset. */
128 while (region.r_size--) {
129 if (loffs == llength(linep)) { /* End of line. */
130 if ((s=kinsert('\n')) != TRUE)
131 return (s);
132 linep = lforw(linep);
133 loffs = 0;
134 } else { /* Middle of line. */
135 if ((s=kinsert(lgetc(linep, loffs).c)) != TRUE)
136 return (s);
137 ++loffs;
141 return (TRUE);
146 * Lower case region. Zap all of the upper
147 * case characters in the region to lower case. Use
148 * the region code to set the limits. Scan the buffer,
149 * doing the changes. Call "lchange" to ensure that
150 * redisplay is done in all buffers. Bound to
151 * "C-X C-L".
154 lowerregion(int f, int n)
156 register LINE *linep;
157 register int loffs;
158 register int c;
159 register int s;
160 REGION region;
161 CELL ac;
163 ac.a = 0;
164 if (curbp->b_mode&MDVIEW) /* don't allow this command if */
165 return(rdonly()); /* we are in read only mode */
167 if ((s=getregion(&region, curwp->w_markp, curwp->w_marko)) != TRUE)
168 return (s);
170 lchange(WFHARD);
171 linep = region.r_linep;
172 loffs = region.r_offset;
173 while (region.r_size--) {
174 if (loffs == llength(linep)) {
175 linep = lforw(linep);
176 loffs = 0;
177 } else {
178 c = lgetc(linep, loffs).c;
179 if (c>='A' && c<='Z'){
180 ac.c = c+'a'-'A';
181 lputc(linep, loffs, ac);
183 ++loffs;
187 return (TRUE);
191 * Upper case region. Zap all of the lower
192 * case characters in the region to upper case. Use
193 * the region code to set the limits. Scan the buffer,
194 * doing the changes. Call "lchange" to ensure that
195 * redisplay is done in all buffers. Bound to
196 * "C-X C-L".
199 upperregion(int f, int n)
201 register LINE *linep;
202 register int loffs;
203 register int c;
204 register int s;
205 REGION region;
206 CELL ac;
208 ac.a = 0;
209 if (curbp->b_mode&MDVIEW) /* don't allow this command if */
210 return(rdonly()); /* we are in read only mode */
212 if ((s=getregion(&region, curwp->w_markp, curwp->w_marko)) != TRUE)
213 return (s);
215 lchange(WFHARD);
216 linep = region.r_linep;
217 loffs = region.r_offset;
218 while (region.r_size--) {
219 if (loffs == llength(linep)) {
220 linep = lforw(linep);
221 loffs = 0;
222 } else {
223 c = lgetc(linep, loffs).c;
224 if (c>='a' && c<='z'){
225 ac.c = c - 'a' + 'A';
226 lputc(linep, loffs, ac);
228 ++loffs;
232 return (TRUE);
236 * This routine figures out the
237 * bounds of the region in the current window, and
238 * fills in the fields of the "REGION" structure pointed
239 * to by "rp". Because the dot and mark are usually very
240 * close together, we scan outward from dot looking for
241 * mark. This should save time. Return a standard code.
242 * Callers of this routine should be prepared to get
243 * an "ABORT" status; we might make this have the
244 * conform thing later.
247 getregion(REGION *rp, LINE *markp, int marko)
249 register LINE *flp;
250 register LINE *blp;
251 long fsize;
252 register long bsize;
254 if (markp == NULL) {
255 return (FALSE);
258 if (curwp->w_dotp == markp) {
259 rp->r_linep = curwp->w_dotp;
260 if (curwp->w_doto < marko) {
261 rp->r_offset = curwp->w_doto;
262 rp->r_size = marko - curwp->w_doto;
263 } else {
264 rp->r_offset = marko;
265 rp->r_size = curwp->w_doto - marko;
267 return (TRUE);
270 blp = curwp->w_dotp;
271 bsize = curwp->w_doto;
272 flp = curwp->w_dotp;
273 fsize = llength(flp)-curwp->w_doto+1;
274 while (flp!=curbp->b_linep || lback(blp)!=curbp->b_linep) {
275 if (flp != curbp->b_linep) {
276 flp = lforw(flp);
277 if (flp == markp) {
278 rp->r_linep = curwp->w_dotp;
279 rp->r_offset = curwp->w_doto;
280 rp->r_size = fsize + marko;
281 return (TRUE);
284 fsize += llength(flp) + 1;
287 if (lback(blp) != curbp->b_linep) {
288 blp = lback(blp);
289 bsize += llength(blp)+1;
290 if (blp == markp) {
291 rp->r_linep = blp;
292 rp->r_offset = marko;
293 rp->r_size = bsize - marko;
294 return (TRUE);
299 emlwrite("Bug: lost mark", NULL);
300 return (FALSE);
305 * set the highlight attribute accordingly on all characters in region
308 markregion(int attr)
310 register LINE *linep;
311 register int loffs;
312 register int s;
313 REGION region;
314 CELL ac;
316 if ((s=getregion(&region, curwp->w_markp, curwp->w_marko)) != TRUE)
317 return (s);
319 lchange(WFHARD);
320 linep = region.r_linep;
321 loffs = region.r_offset;
322 while (region.r_size--) {
323 if (loffs == llength(linep)) {
324 linep = lforw(linep);
325 loffs = 0;
326 } else {
327 ac = lgetc(linep, loffs);
328 ac.a = attr;
329 lputc(linep, loffs, ac);
330 ++loffs;
334 return (TRUE);
339 * clear all the attributes of all the characters in the buffer?
340 * this is real dumb. Movement with mark set needs to be smarter!
342 void
343 unmarkbuffer(void)
345 register LINE *linep;
346 register int n;
347 CELL c;
349 linep = curwp->w_linep;
350 while(lforw(linep) != curwp->w_linep){
351 n = llength(linep);
352 for(n=0; n < llength(linep); n++){
353 c = lgetc(linep, n);
354 c.a = 0;
355 lputc(linep, n, c);
358 linep = lforw(linep);