1 #if !defined(lint) && !defined(DOS)
2 static char rcsid
[] = "$Id: random.c 769 2007-10-24 00:15:40Z hubert@u.washington.edu $";
6 * ========================================================================
7 * Copyright 2006-2007 University of Washington
8 * Copyright 2013-2016 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.
28 #include "osdep/terminal.h"
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 =".
43 showcpos(int f
, int n
)
50 register int thisline
;
53 clp
= lforw(curbp
->b_linep
); /* Grovel the data. */
58 if (clp
==curwp
->w_dotp
&& cbo
==curwp
->w_doto
) {
62 if (cbo
== llength(clp
)) {
63 if (clp
== curbp
->b_linep
)
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
);
83 * Return current column. Stop at first non-blank given TRUE argument.
92 for (i
=0; i
<curwp
->w_doto
; ++i
) {
93 c
= lgetc(curwp
->w_dotp
, i
).c
;
94 if (c
!=' ' && c
!='\t' && bflg
)
101 else if (ISCONTROL(c
)){
108 col
+= (ww
>= 0 ? ww
: 1);
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".
130 if (n
== 0 || n
> 1) {
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
)
150 if (curbp
->b_mode
&MDVIEW
) /* don't allow this command if */
151 return(rdonly()); /* we are in read only mode */
156 if(TERM_OPTIMIZE
&& (curwp
->w_dotp
!= curwp
->w_bufp
->b_linep
)){
160 if(curwp
->w_doto
!= 0)
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.
180 for(i
= curwp
->w_doto
- 1;
181 i
&& ucs4_isspace(lgetc(curwp
->w_dotp
, i
- 1).c
);
183 dellen
= curwp
->w_doto
- i
;
185 ldelete(dellen
, NULL
);
187 /* insert some lines */
189 if ((s
=lnewline()) != 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 */
210 return (backdel(f
, -n
));
212 if(TERM_OPTIMIZE
&& (curwp
->w_dotp
!= curwp
->w_bufp
->b_linep
)){
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)
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
)
241 if (curbp
->b_mode
&MDVIEW
) /* don't allow this command if */
242 return(rdonly()); /* we are in read only mode */
245 return (forwdel(f
, -n
));
247 if(TERM_OPTIMIZE
&& curwp
->w_dotp
!= curwp
->w_bufp
->b_linep
){
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);
257 scrollup(curwp
, l
, 1);
261 if (f
!= FALSE
) { /* Really a kill. */
262 if ((lastflag
&CFKILL
) == 0)
268 if ((s
=backchar(f
, n
)) == TRUE
)
269 s
= ldelete((long) n
, f
? kinsert
: NULL
);
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
)
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){
300 gotobol(FALSE
, 1); /* wack from bol past newline */
301 chunk
= llength(curwp
->w_dotp
) + 1;
306 /* optimize what motion we can */
307 if(opt_scroll
&& (curwp
->w_dotp
!= curwp
->w_bufp
->b_linep
)){
311 scrollup(curwp
, l
, 1);
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".
328 REGION region
, *added_region
;
331 if (curbp
->b_mode
&MDVIEW
) /* don't allow this command if */
332 return(rdonly()); /* we are in read only mode */
337 if(TERM_OPTIMIZE
&& (curwp
->w_dotp
!= curwp
->w_bufp
->b_linep
)){
340 if(worthit(&l
) && !(lastflag
&CFFILL
)){
345 while((ch
=fremove(i
++)) >= 0)
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
){
356 dotp
= curwp
->w_dotp
;
359 getregion(®ion
, dotp
, llength(dotp
));
362 added_region
= get_last_region_added();
364 curwp
->w_dotp
= added_region
->r_linep
;
365 curwp
->w_doto
= added_region
->r_offset
;
366 region
= (*added_region
);
372 if(!ldelete(region
.r_size
, NULL
))
374 } /* then splat out the saved buffer */
378 while ((c
= ((lastflag
&CFFILL
)
379 ? ((lastflag
& CFFLBF
) ? kremove(i
) : fremove(i
))
380 : kremove(i
))) >= 0) {
382 if (lnewline() == FALSE
)
385 if (linsert(1, c
) == FALSE
)
393 if(lastflag
&CFFLPA
){ /* if last command was fill paragraph */
394 curwp
->w_dotp
= lforw(curwp
->w_dotp
);
397 curwp
->w_flag
|= WFMODE
;
411 * worthit - generic sort of test to roughly gage usefulness of using
412 * optimized scrolling.
415 * returns the line on the screen, l, that the dot is currently on
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;