* Deactivate some color code from Pico (as standalone editor) until
[alpine.git] / pico / random.c
blobeff99ca82122af36778f247a431b6001001eb1f1
1 #if !defined(lint) && !defined(DOS)
2 static char rcsid[] = "$Id: random.c 769 2007-10-24 00:15:40Z hubert@u.washington.edu $";
3 #endif
5 /*
6 * ========================================================================
7 * Copyright 2006-2007 University of Washington
8 * Copyright 2013-2017 Eduardo Chappa
10 * Licensed under the Apache License, Version 2.0 (the "License");
11 * you may not use this file except in compliance with the License.
12 * You may obtain a copy of the License at
14 * http://www.apache.org/licenses/LICENSE-2.0
16 * ========================================================================
20 * Program: Random routines
22 * This file contains the command processing functions for a number of random
23 * commands. There is no functional grouping here, for sure.
26 #include "headers.h"
28 #include "osdep/terminal.h"
30 int worthit(int *);
32 int tabsize; /* Tab size (0: use real tabs) */
36 * Display the current position of the cursor, in origin 1 X-Y coordinates,
37 * the character that is under the cursor (in octal), and the fraction of the
38 * text that is before the cursor. The displayed column is not the current
39 * column, but the column that would be used on an infinite width display.
40 * Normally this is bound to "C-X =".
42 int
43 showcpos(int f, int n)
45 register LINE *clp;
46 register long nch;
47 register int cbo;
48 register long nbc;
49 register int lines;
50 register int thisline;
51 char buffer[80];
53 clp = lforw(curbp->b_linep); /* Grovel the data. */
54 cbo = 0;
55 nch = 0L;
56 lines = 0;
57 for (;;) {
58 if (clp==curwp->w_dotp && cbo==curwp->w_doto) {
59 thisline = lines;
60 nbc = nch;
62 if (cbo == llength(clp)) {
63 if (clp == curbp->b_linep)
64 break;
65 clp = lforw(clp);
66 cbo = 0;
67 lines++;
68 } else
69 ++cbo;
70 ++nch;
73 snprintf(buffer,sizeof(buffer),"line %d of %d (%d%%%%), character %ld of %ld (%d%%%%)",
74 thisline+1, lines+1, (int)((100L*(thisline+1))/(lines+1)),
75 nbc, nch, (nch) ? (int)((100L*nbc)/nch) : 0);
77 emlwrite(buffer, NULL);
78 return (TRUE);
83 * Return current column. Stop at first non-blank given TRUE argument.
85 int
86 getccol(int bflg)
88 UCS c;
89 int i, col;
91 col = 0;
92 for (i=0; i<curwp->w_doto; ++i) {
93 c = lgetc(curwp->w_dotp, i).c;
94 if (c!=' ' && c!='\t' && bflg)
95 break;
97 if (c == '\t'){
98 col |= 0x07;
99 ++col;
101 else if (ISCONTROL(c)){
102 col += 2;
104 else{
105 int ww;
107 ww = wcellwidth(c);
108 col += (ww >= 0 ? ww : 1);
112 return(col);
118 * Set tab size if given non-default argument (n <> 1). Otherwise, insert a
119 * tab into file. If given argument, n, of zero, change to true tabs.
120 * If n > 1, simulate tab stop every n-characters using spaces. This has to be
121 * done in this slightly funny way because the tab (in ASCII) has been turned
122 * into "C-I" (in 10 bit code) already. Bound to "C-I".
125 tab(int f, int n)
127 if (n < 0)
128 return (FALSE);
130 if (n == 0 || n > 1) {
131 tabsize = n;
132 return(TRUE);
135 if (! tabsize)
136 return(linsert(1, '\t'));
138 return(linsert(tabsize - (getccol(FALSE) % tabsize), ' '));
143 * Insert a newline. Bound to "C-M".
146 newline(int f, int n)
148 register int s;
150 if (curbp->b_mode&MDVIEW) /* don't allow this command if */
151 return(rdonly()); /* we are in read only mode */
153 if (n < 0)
154 return (FALSE);
156 if(TERM_OPTIMIZE && (curwp->w_dotp != curwp->w_bufp->b_linep)){
157 int l;
159 if(worthit(&l)){
160 if(curwp->w_doto != 0)
161 l++;
162 scrolldown(curwp, l, n);
166 /* if we are in C mode and this is a default <NL> */
167 /* pico's never in C mode */
169 if(Pmaster && Pmaster->allow_flowed_text && curwp->w_doto
170 && ucs4_isspace(lgetc(curwp->w_dotp, curwp->w_doto - 1).c)
171 && !(curwp->w_doto == 3
172 && lgetc(curwp->w_dotp, 0).c == '-'
173 && lgetc(curwp->w_dotp, 1).c == '-'
174 && lgetc(curwp->w_dotp, 2).c == ' ')){
176 * flowed mode, make the newline a hard one by
177 * stripping trailing space.
179 int i, dellen;
180 for(i = curwp->w_doto - 1;
181 i && ucs4_isspace(lgetc(curwp->w_dotp, i - 1).c);
182 i--);
183 dellen = curwp->w_doto - i;
184 curwp->w_doto = i;
185 ldelete(dellen, NULL);
187 /* insert some lines */
188 while (n--) {
189 if ((s=lnewline()) != TRUE)
190 return (s);
192 return (TRUE);
198 * Delete forward. This is real easy, because the basic delete routine does
199 * all of the work. Watches for negative arguments, and does the right thing.
200 * If any argument is present, it kills rather than deletes, to prevent loss
201 * of text if typed with a big argument. Normally bound to "C-D".
204 forwdel(int f, int n)
206 if (curbp->b_mode&MDVIEW) /* don't allow this command if */
207 return(rdonly()); /* we are in read only mode */
209 if (n < 0)
210 return (backdel(f, -n));
212 if(TERM_OPTIMIZE && (curwp->w_dotp != curwp->w_bufp->b_linep)){
213 int l;
215 if(worthit(&l) && curwp->w_doto == llength(curwp->w_dotp))
216 scrollup(curwp, l+1, 1);
219 if (f != FALSE) { /* Really a kill. */
220 if ((lastflag&CFKILL) == 0)
221 kdelete();
222 thisflag |= CFKILL;
225 return (ldelete((long) n, f ? kinsert : NULL));
231 * Delete backwards. This is quite easy too, because it's all done with other
232 * functions. Just move the cursor back, and delete forwards. Like delete
233 * forward, this actually does a kill if presented with an argument. Bound to
234 * both "RUBOUT" and "C-H".
237 backdel(int f, int n)
239 register int s;
241 if (curbp->b_mode&MDVIEW) /* don't allow this command if */
242 return(rdonly()); /* we are in read only mode */
244 if (n < 0)
245 return (forwdel(f, -n));
247 if(TERM_OPTIMIZE && curwp->w_dotp != curwp->w_bufp->b_linep){
248 int l;
250 if(worthit(&l) && curwp->w_doto == 0 &&
251 lback(curwp->w_dotp) != curwp->w_bufp->b_linep){
252 if(l == curwp->w_toprow)
253 scrollup(curwp, l+1, 1);
254 else if(llength(lback(curwp->w_dotp)) == 0)
255 scrollup(curwp, l-1, 1);
256 else
257 scrollup(curwp, l, 1);
261 if (f != FALSE) { /* Really a kill. */
262 if ((lastflag&CFKILL) == 0)
263 kdelete();
265 thisflag |= CFKILL;
268 if ((s=backchar(f, n)) == TRUE)
269 s = ldelete((long) n, f ? kinsert : NULL);
271 return (s);
277 * killtext - delete the line that the cursor is currently in.
278 * a greatly pared down version of its former self.
281 killtext(int f, int n)
283 register int chunk;
284 int opt_scroll = 0;
286 if (curbp->b_mode&MDVIEW) /* don't allow this command if */
287 return(rdonly()); /* we are in read only mode */
289 if ((lastflag&CFKILL) == 0) /* Clear kill buffer if */
290 kdelete(); /* last wasn't a kill. */
292 if(gmode & MDDTKILL){ /* */
293 if((chunk = llength(curwp->w_dotp) - curwp->w_doto) == 0){
294 chunk = 1;
295 if(TERM_OPTIMIZE)
296 opt_scroll = 1;
299 else{
300 gotobol(FALSE, 1); /* wack from bol past newline */
301 chunk = llength(curwp->w_dotp) + 1;
302 if(TERM_OPTIMIZE)
303 opt_scroll = 1;
306 /* optimize what motion we can */
307 if(opt_scroll && (curwp->w_dotp != curwp->w_bufp->b_linep)){
308 int l;
310 if(worthit(&l))
311 scrollup(curwp, l, 1);
314 thisflag |= CFKILL;
315 return(ldelete((long) chunk, kinsert));
320 * Yank text back from the kill buffer. This is really easy. All of the work
321 * is done by the standard insert routines. All you do is run the loop, and
322 * check for errors. Bound to "C-Y".
325 yank(int f, int n)
327 int c, i;
328 REGION region, *added_region;
329 LINE *dotp;
331 if (curbp->b_mode&MDVIEW) /* don't allow this command if */
332 return(rdonly()); /* we are in read only mode */
334 if (n < 0)
335 return (FALSE);
337 if(TERM_OPTIMIZE && (curwp->w_dotp != curwp->w_bufp->b_linep)){
338 int l;
340 if(worthit(&l) && !(lastflag&CFFILL)){
341 register int t = 0;
342 register int i = 0;
343 register int ch;
345 while((ch=fremove(i++)) >= 0)
346 if(ch == '\n')
347 t++;
348 if(t+l < curwp->w_toprow+curwp->w_ntrows)
349 scrolldown(curwp, l, t);
353 if(lastflag & CFFILL){ /* if last command was fillpara() */
354 if(lastflag & CFFLBF){
355 gotoeob(FALSE, 1);
356 dotp = curwp->w_dotp;
357 gotobob(FALSE, 1);
358 curwp->w_doto = 0;
359 getregion(&region, dotp, llength(dotp));
361 else{
362 added_region = get_last_region_added();
363 if(added_region){
364 curwp->w_dotp = added_region->r_linep;
365 curwp->w_doto = added_region->r_offset;
366 region = (*added_region);
368 else
369 return(FALSE);
372 if(!ldelete(region.r_size, NULL))
373 return(FALSE);
374 } /* then splat out the saved buffer */
376 while (n--) {
377 i = 0;
378 while ((c = ((lastflag&CFFILL)
379 ? ((lastflag & CFFLBF) ? kremove(i) : fremove(i))
380 : kremove(i))) >= 0) {
381 if (c == '\n') {
382 if (lnewline() == FALSE)
383 return (FALSE);
384 } else {
385 if (linsert(1, c) == FALSE)
386 return (FALSE);
389 ++i;
393 if(lastflag&CFFLPA){ /* if last command was fill paragraph */
394 curwp->w_dotp = lforw(curwp->w_dotp);
395 curwp->w_doto = 0;
397 curwp->w_flag |= WFMODE;
399 if(!Pmaster){
400 sgarbk = TRUE;
401 emlwrite("", NULL);
405 return (TRUE);
411 * worthit - generic sort of test to roughly gage usefulness of using
412 * optimized scrolling.
414 * note:
415 * returns the line on the screen, l, that the dot is currently on
418 worthit(int *l)
420 int i; /* l is current line */
421 unsigned below; /* below is avg # of ch/line under . */
423 *l = doton(&i, &below);
424 below = (i > 0) ? below/(unsigned)i : 0;
426 return(below > 3);