revert between 56095 -> 55830 in arch
[AROS.git] / workbench / tools / Edit / Cursor.c
blob0ed90264261a0a999b34913ab15364a467ed07be
1 /**************************************************************
2 **** Cursor.c : cursor movement managment. ****
3 **** Free software under GNU license, started on 20.3.2000 ****
4 **** © T.Pierron, C.Guillaume. ****
5 **************************************************************/
7 #include <exec/types.h>
8 #include <graphics/rastport.h>
9 #include "Jed.h"
10 #include "ClipLoc.h"
11 #include "Utility.h"
12 #include "ProtoTypes.h"
14 #define CATCOMP_NUMBERS /* Strings id for err. msg */
15 #include "strings.h"
18 /*** Convert num chars to real column number: ***/
19 ULONG x2pos(LINE *ln, ULONG nb)
21 register ULONG nbrc=0;
22 register UBYTE *str;
23 for(str=ln->stream; nb; nb--, str++)
24 nbrc += (*str=='\t' ? tabstop(nbrc) : 1);
26 return nbrc;
29 /*** Adjust column to an existing one: ***/
30 ULONG adjust_rc(LINE *ln, ULONG rc, ULONG *c, UBYTE atleast)
32 register ULONG nbrc, nbc;
33 register UBYTE *str;
34 for(str=ln->stream, nbrc=nbc=0; nbc<ln->size; str++, nbc++)
36 register ULONG tmp = (*str=='\t' ? tabstop(nbrc) : 1);
37 /* If atleast is TRUE be sure that cursor will be at least at column rc: */
38 if(atleast) if(nbrc<rc) nbrc+=tmp; else break;
39 else if(nbrc+tmp<=rc) nbrc+=tmp; else break;
41 *c=nbc; return nbrc;
44 /*** Returns the characer-index corresponding to the screen column ***/
45 ULONG find_nbc(LINE *ln, ULONG nbrc)
47 register LONG rc, nbc;
48 register UBYTE *str;
49 for(str=ln->stream, rc=0, nbc=ln->size; nbc && rc<nbrc; str++, nbc--)
50 rc += (*str=='\t' ? tabstop(rc) : 1);
51 return ln->size-nbc;
54 /*** Adjust leftpos according to cursor one: ***/
55 LONG adjust_leftpos(Project p, WORD step)
57 LONG x;
58 if(step>=0) x=p->nbrc+step-gui.nbcol+1;
59 else x=p->nbrc+step;
60 return (x<=0 ? 0:x);
63 /*** Search for next available word in the line ***/
64 LONG forward_word(LINE *ln, ULONG pos)
66 UBYTE type;
67 STRPTR str;
68 /* Search next */
69 for(str=ln->stream+pos,type=TypeChar[*str]; pos<ln->size && type==TypeChar[*str]; pos++,str++);
70 /* Skip white spaces */
71 while( pos<ln->size && TypeChar[*str]==SPACE ) str++;
72 return str - ln->stream;
75 /*** Search for previous word in a line ***/
76 LONG backward_word(LINE *ln, ULONG pos)
78 UBYTE type;
79 STRPTR str;
80 /* Skip white spaces */
81 for(str=ln->stream + pos; pos>0 && TypeChar[*str]==SPACE; str--,pos--);
82 /* Search previous */
83 for(type=TypeChar[*str]; ; pos--,str--)
84 if( type != TypeChar[*str] ) { str ++; break; }
85 else if( pos == 0 ) { break; }
86 return str - ln->stream;
89 /*** Display cursor of project p ***/
90 void inv_curs(Project p, BYTE state)
92 if(p->ccp.select)
94 /* Just draw a simple vert bart for selection */
95 WORD y = p->ycurs - BASEL;
96 RectFill(RP,p->xcurs, y, p->xcurs+1, y+YSIZE-1);
97 } else {
98 UBYTE thechar, oldmask = RP->Mask;
99 /* Fully highlight character */
100 RP->Mask = gui.selmask;
101 if(state) SetABPenDrMd(RP,pen.fgfill,pen.bgfill,JAM2);
103 if(state != 0 && p->cursmode) {
104 /* Draw the replacement cursor */
105 SetAPen(RP, pen.bgfill);
106 RectFill(RP,p->xcurs, p->ycurs, p->xcurs+XSIZE-1, p->ycurs-BASEL+YSIZE-1);
107 } else {
108 /* Normal cursor */
109 thechar = (p->nbc < p->edited->size ? p->edited->stream[p->nbc] : ' ');
110 if(thechar == '\t') thechar = ' ';
111 Move(RP,p->xcurs,p->ycurs); Text(RP,&thechar,1);
113 SetABPenDrMd(RP,pen.fg,pen.bg,JAM2);
114 RP->Mask = oldmask;
118 /*** Set cursor to a specified position in file ***/
119 void set_cursor_line(Project p, LONG pos, ULONG top)
121 LINE *ln;
122 /* Adjust all related variables */
123 if(pos < 0) pos = 0;
124 if(pos >= p->max_lines) pos = p->max_lines-1;
125 if(pos < p->nbl) for(ln=p->edited; p->nbl!=pos; ln=ln->prev, p->nbl--);
126 else for(ln=p->edited; p->nbl!=pos; ln=ln->next, p->nbl++);
128 /* Cursor position */
129 p->nbrc = adjust_rc(p->edited=ln, p->nbrwc, &p->nbc, FALSE);
130 p->xcurs = (p->nbrc-p->left_pos)*XSIZE + gui.left;
131 p->ycurs = (p->nbl-top)*YSIZE + gui.topcurs;
132 draw_info( p );
135 /*** Set top-left visible corner ***/
136 void set_top_line(Project p, ULONG top, ULONG left)
138 LINE *ln; LONG nb = top-p->top_line;
139 if(nb < 0) for(ln=p->show; nb++; ln=ln->prev);
140 else for(ln=p->show; nb--; ln=ln->next);
141 p->show = ln;
142 p->top_line = top;
143 p->left_pos = left;
144 p->xcurs = (p->nbrc-p->left_pos) * XSIZE + gui.left;
145 redraw_content(p, ln, gui.topcurs, gui.nbline);
146 prop_adj( p );
149 /*** Move cursor incrementally (paste) ***/
150 void move_cursor(Project p, LONG dx, LONG dy)
152 LINE *ln; LONG nb=dy;
153 inv_curs(p, FALSE);
154 if(nb < 0) for(ln=p->edited; nb++; ln=ln->prev);
155 else for(ln=p->edited; nb--; ln=ln->next);
156 p->edited = ln;
157 p->nbl += dy;
158 p->nbrwc = p->nbrc = x2pos(ln,p->nbc = dx);
160 dx = center_horiz(p);
161 /* Don't scroll if top_line changed! (whole redraw instead) */
162 if(dx != p->left_pos && dy == 0)
163 scroll_xy(p, dx, p->top_line, TRUE);
164 else {
165 nb = center_vert(p) - p->top_line;
166 for(p->top_line += nb,ln=p->show; nb--; ln=ln->next);
167 p->show = ln; p->left_pos = dx;
169 p->ycurs = (p->nbl-p->top_line)*YSIZE + gui.topcurs;
170 p->xcurs = (p->nbrc-p->left_pos)*XSIZE + gui.left;
171 draw_info( p );
174 /*** Move cursor to absolute position ***/
175 void move_to_line(Project p, ULONG nbline, char dirtiness)
177 ULONG newtop;
179 if(!p->ccp.select) inv_curs(p,FALSE);
180 /* Get the new top line */
181 { register ULONG old_nbl = p->nbl;
182 p->nbl = nbline;
183 newtop = center_vert(p);
184 p->nbl = old_nbl;
185 } set_cursor_line(p, nbline, newtop);
187 if(dirtiness == LINE_AS_IS)
188 scroll_xy(p, center_horiz(p), newtop, TRUE);
189 else
191 /* Some lines are modified: redraw in one pass */
192 if( newtop == p->top_line ) {
193 REDRAW_CURLINE(p);
194 if( dirtiness == LINES_DIRTY )
195 scroll_up(p, p->edited->next, p->ycurs, center_horiz(p)),
196 prop_adj(p);
197 else if( p->left_pos != (newtop = center_horiz(p)) )
198 scroll_xy(p, newtop, p->top_line, FALSE);
200 else if( dirtiness == LINE_DIRTY )
201 scroll_xy(p, center_horiz(p), newtop, TRUE);
202 else
203 set_top_line(p, newtop, center_horiz(p));
205 /* Move cursor or selection */
206 if(p->ccp.select) move_selection(p, p->nbrwc, p->nbl);
207 inv_curs(p,TRUE);
208 draw_info( p );
211 /*** Move cursor up ***/
212 void curs_up(Project p)
214 LINE *ln;
215 if( ( ln = p->edited->prev) )
217 LONG newx; BYTE scroll=0;
219 inv_curs(p, FALSE);
220 /* Is the cursor on top of display? */
221 if(p->ycurs > gui.topcurs) p->ycurs -= YSIZE;
222 else scroll=1;
224 p->nbl--; p->edited=ln;
225 p->nbrc = adjust_rc(ln, p->nbrwc, &p->nbc, FALSE);
226 p->xcurs = (p->nbrc-p->left_pos)*XSIZE + gui.left;
228 /* If cursor exits edit area due to horizontal **
229 ** adjustment, scroll the display accordingly: */
230 if((newx=center_horiz(p))!=p->left_pos || scroll)
231 scroll_xy(p, newx, p->top_line-scroll, scroll);
233 /* Update selection */
234 if(p->ccp.select) move_selection(p, p->nbrc, p->nbl);
235 inv_curs(p, TRUE);
236 draw_info( p );
240 /*** Move cursor down ***/
241 void curs_down(Project p)
243 LINE *ln;
244 if( ( ln = p->edited->next) )
246 LONG newx; BYTE scroll=0;
248 inv_curs(p, FALSE);
249 /* Is the cursor at the bottom of the display? */
250 if( p->ycurs < gui.botcurs) p->ycurs += YSIZE;
251 else scroll=1;
253 p->nbl++; p->edited=ln;
254 p->nbrc = adjust_rc(ln, p->nbrwc, &p->nbc, FALSE);
255 p->xcurs = (p->nbrc-p->left_pos)*XSIZE + gui.left;
257 /* Minimise calls to scroll_xy */
258 if((newx=center_horiz(p))!=p->left_pos || scroll)
259 scroll_xy(p, newx, p->top_line+scroll, scroll);
261 /* Update selection */
262 if(p->ccp.select) move_selection(p, p->nbrc, p->nbl);
263 inv_curs(p, TRUE);
264 draw_info( p );
268 /*** Move cursor to the left ***/
269 void curs_left(Project p, BYTE word)
271 register LINE *prev;
272 if(p->nbc != 0)
274 inv_curs(p,FALSE);
275 if(word) p->nbc = backward_word(p->edited, p->nbc-1); else p->nbc--;
276 p->nbrwc = p->nbrc = x2pos(p->edited, p->nbc);
277 p->xcurs = (p->nbrc-p->left_pos) * XSIZE + gui.left;
279 /* Is it gone outside edit area? */
280 if(p->nbrc<p->left_pos)
281 scroll_xy(p, adjust_leftpos(p, -gui.xstep), p->top_line, FALSE);
283 if(p->ccp.select) move_selection(p, p->nbrc, p->nbl);
284 inv_curs(p,TRUE);
285 draw_info( p );
287 } else if( ( prev = p->edited->prev ) ) {
288 /* jump up */
289 p->nbrwc = x2pos(prev, prev->size);
290 curs_up(p);
294 /*** One pos right ***/
295 void curs_right(Project p, BYTE word)
297 if(p->nbc < p->edited->size)
299 inv_curs(p,FALSE);
300 if(word) p->nbc = forward_word(p->edited, p->nbc); else p->nbc++;
301 p->nbrwc = p->nbrc = x2pos(p->edited, p->nbc);
302 p->xcurs = (p->nbrc-p->left_pos) * XSIZE + gui.left;
304 /* Move the cursor */
305 /* Is it gone outside edit area? */
306 if(p->nbrc>=p->left_pos+gui.nbcol)
307 scroll_xy(p, adjust_leftpos(p, gui.xstep), p->top_line, FALSE);
309 if(p->ccp.select) move_selection(p, p->nbrc, p->nbl);
310 inv_curs(p,TRUE);
311 draw_info( p );
313 } else if(p->edited->next) {
314 /* jump down to next line */
315 p->nbrwc = 0;
316 curs_down(p);
320 /*** Jump the cursor far left or far right ***/
321 void jump_horiz(Project p, BYTE dir)
323 if( dir >= 0 )
325 /* If cursor is already at rightmost position, scroll display */
326 if( p->nbrwc == p->left_pos+gui.nbcol-1 )
328 p->nbrwc += gui.nbcol-1;
330 else p->nbrwc = p->left_pos+gui.nbcol-1;
331 } else {
332 /* Check if cursor is already at leftmost position */
333 if( p->nbrwc == p->left_pos )
335 p->nbrwc = p->left_pos - (gui.nbcol-1);
336 if( (LONG)p->nbrwc < 0 ) p->nbrwc = 0;
338 else p->nbrwc = p->left_pos;
341 inv_curs(p,FALSE);
342 p->nbrc = adjust_rc(p->edited, p->nbrwc, &p->nbc, dir<0);
343 p->xcurs = (p->nbrc-p->left_pos)*XSIZE + gui.left;
345 LONG newleft = center_horiz( p );
346 if( newleft != p->left_pos )
347 scroll_xy(p, newleft, p->top_line, 0);
349 /* Move selection or cursor? */
350 if(p->ccp.select) move_selection(p, p->nbrwc, p->nbl);
351 inv_curs(p,TRUE);
352 draw_info( p );
355 /*** Jump cursor to an absolute position in line (ie: beginning or end) ***/
356 void horiz_pos( Project p, ULONG newpos )
358 if( newpos != p->nbrwc )
360 inv_curs(p, FALSE);
361 p->nbrc = adjust_rc(p->edited, p->nbrwc = newpos, &p->nbc, FALSE);
362 scroll_xy(p, center_horiz(p), p->top_line, FALSE);
363 p->xcurs = (p->nbrc-p->left_pos)*XSIZE + gui.left;
364 if(p->ccp.select) move_selection(p, p->nbrwc, p->nbl);
365 inv_curs(p, TRUE);
366 draw_info( p );
370 /*** Jump the cursor at bottom or top of display ***/
371 void jump_vert(Project p, BYTE dir)
373 LONG newline, newtop=p->top_line;
374 if( dir>=0 )
376 /* Move cursor to bottom of display or scroll one page if it's already here */
377 newline=newtop+gui.nbline-1;
378 if( p->nbl==newline )
379 newline+=gui.nbline,
380 newtop+=gui.nbline;
382 /* Want to jump after the last line? */
383 if(newline>=p->max_lines) {
384 newline=p->max_lines-1;
385 newtop=(p->top_line + gui.nbline > p->max_lines ? p->top_line : newline-gui.nbline+1);
386 if(newtop<0) newtop=0;
388 } else {
389 /* Same fight with reverse direction */
390 newline=newtop;
391 if( p->nbl==newline ) {
392 newtop-=gui.nbline;
393 if(newtop<0) newtop=0;
394 newline=newtop;
397 /* Adjust display according to cursor position */
398 if(newline != p->nbl) {
399 inv_curs(p,FALSE);
400 set_cursor_line(p, newline, newtop);
402 /* Set the selection flags before to scroll display */
403 if(p->ccp.select) move_selection(p, p->nbrwc, p->nbl);
404 scroll_xy(p,center_horiz(p), newtop, TRUE);
405 inv_curs(p,TRUE);
406 draw_info( p );
410 /*** Move cursor down/up one page ***/
411 void pg_updown(Project p, BYTE dir)
413 LONG newtop = p->top_line, newcrs;
415 if(dir>0)
416 /* One page down */
417 if(newtop+gui.nbline >= p->max_lines) newcrs = p->max_lines-1;
418 else {
419 newtop += gui.nbline;
420 if(newtop+gui.nbline >= p->max_lines)
421 newtop = p->max_lines - gui.nbline;
422 newcrs = newtop - p->top_line + p->nbl;
424 else
425 /* One page up */
426 if(newtop == 0) newcrs=0;
427 else {
428 newtop -= gui.nbline;
429 if(newtop<0) newtop=0;
430 newcrs = newtop - p->top_line + p->nbl;
432 if(newcrs != p->nbl) inv_curs(p,FALSE),set_cursor_line(p,newcrs,newtop);
433 scroll_xy(p,center_horiz(p),newtop,TRUE);
434 if(p->ccp.select) move_selection(p, p->nbrc, p->nbl);
435 inv_curs(p,TRUE);
436 draw_info( p );
439 /*** Split line ***/
440 void split_curline( Project p )
442 if( split_line(&p->undo, p->edited, p->nbc, &p->nbrwc, prefs.auto_indent) )
444 register LINE *ln = p->edited;
445 /* Redraw line where cursor is */
446 Move(RP,gui.left,p->ycurs);
447 write_text(p, ln);
448 /* A line has been added */
449 p->max_lines++; p->nbrwc = x2pos(ln,p->nbrwc);
450 /* Scroll manually the display and redraw new line */
451 if(p->ycurs < gui.botcurs)
453 ScrollRaster(RP, 0, -YSIZE, gui.left,p->ycurs+YSIZE-BASEL,gui.right,gui.bottom);
454 Move(RP,gui.left,p->ycurs+YSIZE); ln = ln->next;
455 write_text(p, ln);
456 prop_adj(p);
458 /* Go down one line */
459 curs_down(p);
460 } else ThrowError(Wnd, ErrMsg(ERR_NOMEM));
463 /*** Join two lines and strip spaces on the next ***/
464 void join_strip( Project p )
466 LINE *ln;
467 if((ln = p->edited->next) != NULL)
469 STRPTR data; ULONG i;
470 inv_curs(p, FALSE);
471 p->nbc = p->edited->size;
472 for(i=0, data=ln->stream; TypeChar[*data] == SPACE && i<ln->size; i++, data++);
474 reg_group_by(&p->undo);
475 if(i != ln->size)
477 /* Do not add a blank if there is already one */
478 if( p->nbc > 0 && TypeChar[ p->edited->stream[ p->nbc-1 ] ] != SPACE )
479 add_char(&p->undo, p->edited, p->nbc, ' ');
480 if( insert_str(&p->undo, p->edited, p->edited->size, data, ln->size-i) == 0 )
481 ThrowError(Wnd, ErrMsg(ERR_NOMEM));
483 /* ln can't be the first */
484 del_line(&p->undo, NULL, ln); p->max_lines--;
485 reg_group_by(&p->undo);
486 prop_adj(p);
487 /* Refresh screen */
488 p->nbrc = p->nbrwc = x2pos(p->edited, p->nbc);
489 REDRAW_CURLINE( p );
490 draw_info( p );
491 scroll_up(p, p->edited->next, p->ycurs, center_horiz(p));
492 inv_curs(p,TRUE);
496 /*** Remove an entire line ***/
497 void amiga_k(Project p)
499 LINE *del = p->edited;
501 if(p->ccp.select) return;
503 /* In there a next line, move cursor to */
504 if( del->next ) {
505 p->edited=del->next; p->max_lines--;
506 if(p->show==del) p->show=del->next;
507 prop_adj(p);
509 /* Adjust cursor position */
510 inv_curs(p,FALSE);
511 del_line(&p->undo, &p->the_line, del);
512 p->nbrc = adjust_rc(p->edited, p->nbrwc, &p->nbc, FALSE);
513 REDRAW_CURLINE(p);
514 scroll_up(p, p->edited->next, p->ycurs, center_horiz(p));
515 inv_curs(p,TRUE);
518 /*** Remove the char before the cursor ***/
519 void back_space(Project p, BYTE word)
521 if(p->nbc!=0)
523 ULONG nbc = word ? backward_word(p->edited,p->nbc-1) : p->nbc-1;
524 rem_chars(&p->undo, p->edited, nbc, p->nbc-1);
526 /* Set cursor position and redraws it */
527 inv_curs(p,FALSE);
528 REDRAW_CURLINE(p);
529 p->nbrwc = p->nbrc = x2pos(p->edited, p->nbc=nbc);
530 p->xcurs = (p->nbrc-p->left_pos)*XSIZE + gui.left;
531 if( (nbc = center_horiz(p)) != p->left_pos )
532 scroll_xy(p, nbc, p->top_line, FALSE);
533 inv_curs(p,TRUE);
534 draw_info( p );
535 } else if(p->edited->prev != NULL) {
537 p->edited = p->edited->prev;
538 p->nbc = p->edited->size;
539 /* Join previous and current line */
540 if( join_lines(&p->undo, p->edited, p->edited->next) )
542 /* Move cursor to the end of previous line */
543 p->nbrwc = p->nbrc = x2pos(p->edited, p->nbc);
545 p->max_lines--; p->nbl--;
546 /* Require to scroll the display? */
547 inv_curs(p, FALSE);
548 if(p->ycurs>gui.topcurs)
549 scroll_up(p, p->edited->next, p->ycurs-=YSIZE, center_horiz(p));
550 else
551 p->top_line--, p->show = p->edited,
552 p->xcurs = (p->nbrc-p->left_pos)*XSIZE + gui.left;
554 SetAPen(RP, pen.fg);
555 REDRAW_CURLINE(p);
556 /* Redraw the cursor: */
557 inv_curs(p,TRUE);
558 draw_info(p);
559 prop_adj(p);
560 } else ThrowError(Wnd, ErrMsg(ERR_NOMEM));
564 /*** Remove part of a line ***/
565 void cut_line(Project p, BYTE mode)
567 /* Is there something to do? */
568 if( (mode==0 && p->nbc==0) || (mode==1 && p->nbc==p->edited->size)) return;
570 if( rem_chars(&p->undo, p->edited, mode ? p->nbc : 0, (mode ? p->edited->size : p->nbc)-1) )
572 /* Recompute cursor position */
573 if(mode==0)
575 inv_curs(p,FALSE);
576 p->nbc=p->nbrc=p->nbrwc=0;
577 if(p->left_pos!=0) scroll_xy(p, 0, p->top_line, FALSE);
578 p->xcurs=gui.left;
579 draw_info(p);
581 REDRAW_CURLINE(p);
582 inv_curs(p,TRUE);
583 } else ThrowError(Wnd, ErrMsg(ERR_NOMEM));
586 /*** Remove the char under the cursor ***/
587 void del(Project p, BYTE word)
589 if(p->nbc < p->edited->size)
591 ULONG nbc = word ? forward_word(p->edited,p->nbc)-1 : p->nbc;
592 rem_chars(&p->undo, p->edited, p->nbc, nbc);
593 REDRAW_CURLINE(p);
594 inv_curs(p, TRUE);
595 } else if(p->edited->next) {
597 /* Join current and next line: */
598 if( join_lines(&p->undo, p->edited, p->edited->next) )
600 REDRAW_CURLINE(p);
601 /* Is it needed to scroll display? */
602 if(p->ycurs < gui.botcurs)
603 scroll_up(p,p->edited->next,p->ycurs,p->left_pos);
605 /* Redraw the cursor: */
606 inv_curs(p,TRUE);
607 p->max_lines--;
608 prop_adj(p);
609 } else ThrowError(Wnd, ErrMsg(ERR_NOMEM));
613 /*** Move the cursor according to mouse click ***/
614 void click(Project p, WORD x, WORD y, BYTE update)
616 WORD xp = (x-gui.left) / XSIZE,
617 yp = (y-gui.top) / YSIZE;
618 LINE *ln;
620 if(!p->ccp.select) inv_curs(p, FALSE);
622 p->nbl = p->top_line + yp;
623 for(ln=p->show; ln->next && yp; yp--,ln=ln->next);
624 /* There was no lines, where we've clicked */
625 p->nbl -= yp;
626 p->edited = ln;
627 p->nbrwc = p->nbrc = xp+p->left_pos;
629 xp = curs_visible(p,p->top_line);
630 if(xp!=p->left_pos)
631 scroll_xy(p, xp, p->top_line, FALSE);
632 draw_info( p );
633 RP->Mask = gui.selmask;
635 /* Set starting selection point */
636 if( update )
638 ln->flags = FIRSTSEL | LASTSEL;
639 p->ccp.xc = p->ccp.xp = p->ccp.startsel = p->ccp.endsel = p->nbrc;
640 p->ccp.yc = p->ccp.yp = p->nbl;
641 p->ccp.cline = p->ccp.line = ln;
645 /*** User release mouse button ***/
646 void unclick(Project p)
648 /* Is there something selected ? */
649 if( p->ccp.yp!=p->ccp.yc || p->ccp.startsel!=p->ccp.endsel )
650 /* Yes ! */
651 p->edited = p->ccp.cline, p->nbrwc=p->ccp.xc,
652 set_cursor_line(p, p->nbl = p->ccp.yc, p->top_line);
653 else
654 p->edited->flags = 0, p->ccp.select = 0,
655 inv_curs(p, TRUE), RP->Mask = gui.txtmask;