4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
22 /* Copyright (c) 1988 AT&T */
23 /* All Rights Reserved */
27 * Copyright (c) 1997, by Sun Microsystems, Inc.
28 * All rights reserved.
31 #pragma ident "%Z%%M% %I% %E% SMI"
35 #include <sys/types.h>
39 #define AT_BOTTOM(f) (Y(f) == Ymax(f) - 1) /* last line */
40 #define AT_END(f) (Y(f) == Ymax(f) - 1 && X(f) == Xmax(f) - 1)
42 #define AT_BEGINNING(f) (Y(f) == 0 && X(f) == 0) /* first char */
45 room_for_line(FORM
*f
)
50 v
= LineBuf(C(f
), Ymax(f
) - 1);
51 return (v
== _data_end(v
, Xmax(f
))); /* check for empty line */
55 room_for_char(FORM
*f
)
60 (void) wmove(w
, Y(f
), Xmax(f
) - 1);
61 c
= (int)(winch(w
) & A_CHARTEXT
);
62 (void) wmove(w
, Y(f
), X(f
));
63 return (c
== Pad(C(f
))); /* check for empty char */
67 extra_padding(char *str
, int nstr
) /* used for word wrapping */
69 int c
= *(str
+ nstr
- 1);
71 if (c
== '"' || c
== '\'')
72 c
= *(str
+ nstr
- 2);
74 return ((c
== '.' || c
== '?' || c
== '!' || c
== ':') ? 2 : 1);
79 _grow_field(FIELD
*c
, int chunks
)
81 /* This function handles the growth of dymanically growable fields */
82 /* Returns TRUE if successful, FALSE otherwise */
86 BOOLEAN current
= Status(f
, POSTED
) && c
== C(f
);
90 int old_len
= BufSize(c
);
96 if (current
&& Status(f
, WIN_CHG
)) {
103 grow
= chunks
* c
->cols
;
106 grow
= MIN(max
- c
->dcols
, grow
);
113 grow
= chunks
* (c
->rows
+ c
->nrow
);
116 grow
= MIN(max
- c
->drows
, grow
);
125 save
= old_buf
= Buf(c
);
126 new_buf
= Buf(c
) = malloc(TotalBuf(c
));
133 for (i
= 0; i
< lcv
; i
++) {
134 (void) memcpy(new_buf
, old_buf
, old_len
);
135 (void) memset(new_buf
+ old_len
, ' ', grow
);
136 old_buf
+= old_len
+ 1;
137 new_buf
+= old_len
+ grow
;
141 free(save
); /* delete old buffer */
145 W(f
) = w
= newwin(c
->drows
, c
->dcols
, 0, 0);
150 wbkgdset(w
, Pad(c
) | Back(c
));
151 (void) wattrset(w
, Fore(c
));
154 (void) untouchwin(w
);
155 (void) wmove(w
, Y(f
), X(f
));
174 insert_str(FORM
*f
, int y
, int off
, int nstr
) /* used for word wrapping */
178 char *vbeg
= LineBuf(c
, y
);
179 char *v
= _data_end(vbeg
, Xmax(f
));
180 int x
= (int)(v
- vbeg
);
182 int pad
= extra_padding(Buf(c
) + off
, nstr
);
183 int siz
= nstr
+ 1 + pad
;
184 int ret
= E_REQUEST_DENIED
;
186 if (n
>= siz
) { /* check for fit on this line */
187 (void) wmove(w
, y
, 0);
188 (void) winsnstr(w
, Buf(c
) + off
, nstr
);
189 (void) wmove(w
, y
, nstr
);
190 (void) winsnstr(w
, " ", pad
);
192 if (y
== Ymax(f
) - 1 && Status(c
, GROWABLE
)) {
193 if (!_grow_field(c
, 1))
194 return (E_SYSTEM_ERROR
);
196 vbeg
= LineBuf(c
, y
); /* grow changes buffer */
197 w
= W(f
); /* grow changes window */
200 v
= _data_beg(vbeg
+ Xmax(f
) - siz
, siz
);
201 v
= _whsp_end(vbeg
, (int)(v
- vbeg
));
205 if (y
< Ymax(f
) - 1 && (ret
=
206 insert_str(f
, y
+1, (int)(v
- Buf(c
)), n
)) == E_OK
) {
207 (void) wmove(w
, y
, x
);
209 (void) wmove(w
, y
, 0);
210 (void) winsnstr(w
, Buf(c
) + off
, nstr
);
211 (void) wmove(w
, y
, nstr
);
212 (void) winsnstr(w
, " ", pad
);
214 return (ret
); /* no room for wrap */
220 wrap_ok(FORM
*f
) /* used for word wrapping */
223 * when this routine is called a char has already been added/inserted
224 * on the screen at Y(f), X(f). this routine checks to see if the current
225 * line needs wrapping and if so attempts the wrap. if unsuccessful
226 * it deletes the char at Y(f), X(f) and returns FALSE.
229 BOOLEAN at_bottom
= AT_BOTTOM(f
);
230 int ret
= E_REQUEST_DENIED
;
232 if (Opt(c
, O_WRAP
) && !OneRow(c
) && !room_for_char(f
) &&
233 (!at_bottom
|| Status(c
, GROWABLE
))) {
239 if (at_bottom
&& !_grow_field(c
, 1))
240 return (E_SYSTEM_ERROR
);
242 vbeg
= LineBuf(c
, Y(f
));
245 _win_to_buf(w
, c
); /* sync buffer without changing flags */
247 v
= _whsp_end(vbeg
, Xmax(f
));
251 if (x
&& (ret
= insert_str(f
, Y(f
)+1, (int)(v
- Buf(c
)), n
)) ==
253 w
= W(f
); /* window may change in insert_str */
254 (void) wmove(w
, Y(f
), x
);
261 } else { /* error condition */
262 if (ret
== E_SYSTEM_ERROR
)
263 return (E_SYSTEM_ERROR
);
265 (void) wmove(w
, Y(f
), X(f
));
266 (void) wdelch(w
); /* delete the char */
267 _win_to_buf(w
, c
); /* restore buffer */
268 return (E_REQUEST_DENIED
);
278 * overloaded operation
280 * if at beginning of field
283 * else if in OVERLAY mode
284 * if on last line of field
285 * clear to eol and move to next field
287 * clear to eol and move to beginning of next line
289 * else if in INSERT mode
290 * if on last line of field
293 * move text from cursor to eol to new line
295 BOOLEAN at_bottom
= AT_BOTTOM(f
);
298 if (Opt(f
, O_NL_OVERLOAD
) && AT_BEGINNING(f
))
299 return (_field_navigation(_next_field
, f
));
302 return (E_REQUEST_DENIED
);
304 if (Status(f
, OVERLAY
)) { /* OVERLAY mode */
305 if (at_bottom
&& (!Status(c
, GROWABLE
) || OneRow(c
))) {
306 if (Opt(f
, O_NL_OVERLOAD
)) {
307 (void) wclrtoeol(W(f
));
309 return (_field_navigation(_next_field
, f
));
311 return (E_REQUEST_DENIED
);
314 if (at_bottom
&& !_grow_field(c
, 1))
315 return (E_SYSTEM_ERROR
);
317 (void) wclrtoeol(W(f
));
319 } else { /* INSERT mode */
322 if (at_bottom
&& (!Status(c
, GROWABLE
) || OneRow(c
))) {
323 if (Opt(f
, O_NL_OVERLOAD
))
324 return (_field_navigation(_next_field
, f
));
326 return (E_REQUEST_DENIED
);
329 room
= !at_bottom
&& room_for_line(f
);
331 if (room
|| Status(c
, GROWABLE
)) {
336 if (!room
&& !_grow_field(c
, 1))
337 return (E_SYSTEM_ERROR
);
340 v
= LineBuf(c
, Y(f
)) + X(f
);
341 vend
= _data_end(v
, Xmax(f
) - X(f
));
345 (void) wmove(w
, Y(f
), X(f
));
347 (void) waddnstr(w
, v
, (int)(vend
- v
));
349 return (E_REQUEST_DENIED
);
355 /* _ins_char - insert blank char with error on overflow */
360 BOOLEAN room
= room_for_char(f
);
362 if (CheckChar(c
, ' ') && (room
|| (OneRow(c
) &&
363 Status(c
, GROWABLE
)))) {
364 if (!room
&& !_grow_field(c
, 1))
365 return (E_SYSTEM_ERROR
);
367 (void) winsch(W(f
), ' ');
371 return (E_REQUEST_DENIED
);
374 /* _ins_line - insert blank line with error on overflow */
378 BOOLEAN room
= !AT_BOTTOM(f
) && room_for_line(f
);
381 if (CheckChar(c
, ' ') && !OneRow(c
) && (room
|| Status(c
, GROWABLE
))) {
382 if (!room
&& !_grow_field(c
, 1))
383 return (E_SYSTEM_ERROR
);
386 (void) winsertln(W(f
));
389 return (E_REQUEST_DENIED
);
392 /* _del_char - delete char at cursor */
404 * overloaded operation
406 * if at beginning of field
407 * move to previous field
409 * else if in OVERLAY mode
410 * if at beginning of line
413 * delete previous char
415 * else if in INSERT mode
416 * if at beginning of line
417 * if current line can fit on preceding
418 * join current line with preceding line
422 * delete previous char
427 if (AT_BEGINNING(f
)) {
428 if (Opt(f
, O_BS_OVERLOAD
))
429 return (_field_navigation(_prev_field
, f
));
431 return (E_REQUEST_DENIED
);
434 return (E_REQUEST_DENIED
);
439 if (Status(f
, OVERLAY
)) /* OVERLAY mode */
440 return (E_REQUEST_DENIED
);
441 else { /* INSERT mode */
442 char *p
= LineBuf(c
, Y(f
) - 1);
443 char *v
= LineBuf(c
, Y(f
));
448 pend
= _data_end(p
, Xmax(f
));
449 vend
= _data_end(v
, Xmax(f
));
451 if ((vend
- v
) > (Xmax(f
) - (pend
- p
)))
452 return (E_REQUEST_DENIED
);
455 _adjust_cursor(f
, pend
);
456 (void) wmove(w
, Y(f
), X(f
));
457 (void) waddnstr(w
, v
, (int)(vend
- v
));
461 (void) wmove(w
, Y(f
), X(f
));
468 /* _del_line - delete current line */
473 (void) wdeleteln(W(f
));
477 /* _del_word - delete word under cursor plus trailing blanks */
483 char *y
= LineBuf(c
, Y(f
));
484 char *t
= y
+ Xmax(f
);
491 return (E_REQUEST_DENIED
);
493 _adjust_cursor(f
, _whsp_end(y
, X(f
)));
494 (void) wmove(w
, Y(f
), X(f
));
497 v
= _whsp_beg(v
, (int)(t
- v
));
498 v
= _data_beg(v
, (int)(t
- v
));
500 if (v
!= x
&& *v
!= ' ')
501 (void) waddnstr(w
, v
, (int)(_data_end(v
, (int)(t
- v
)) - v
));
506 /* _clr_eol - clear to end of line */
510 (void) wclrtoeol(W(f
));
514 /* _clr_eof - clear to end of field */
518 (void) wclrtobot(W(f
));
522 /* _clr_field - clear entire field */
531 /* _ovl_mode - go into overlay mode */
539 /* _ins_mode - go into insert mode */
547 /* _validation - apply validation function associated with field type */
551 return (_validate(f
) ? E_OK
: E_INVALID_FIELD
);
554 /* _next_choice - apply next choice function associated with field type */
556 _next_choice(FORM
*f
)
559 return (NextChoice(C(f
)) ? E_OK
: E_REQUEST_DENIED
);
562 /* _prev_choice - apply previous choice function associated with field type */
564 _prev_choice(FORM
*f
)
567 return (PrevChoice(C(f
)) ? E_OK
: E_REQUEST_DENIED
);
571 * _data_entry - enter printable ascii char ch
572 * in current field at cursor position
575 _data_entry(FORM
*f
, int ch
)
577 FIELD
* c
= C(f
); /* current field */
578 WINDOW
* w
= W(f
); /* field window */
583 return (E_REQUEST_DENIED
);
585 if (AT_BEGINNING(f
) && Opt(c
, O_BLANK
) && ! Status(f
, BUF_CHG
) &&
589 if (Status(f
, OVERLAY
)) /* OVERLAY mode */
590 (void) waddch(w
, (chtype
) ch
);
591 else { /* INSERT mode */
592 BOOLEAN room
= room_for_char(f
);
594 if (room
|| (OneRow(c
) && Status(c
, GROWABLE
))) {
595 if (!room
&& !_grow_field(c
, 1))
596 return (E_SYSTEM_ERROR
);
598 (void) winsch(w
, (chtype
) ch
);
600 return (E_REQUEST_DENIED
);
603 if ((ret
= wrap_ok(f
)) != E_OK
)
610 if (at_end
&& !Status(c
, GROWABLE
) && Opt(c
, O_AUTOSKIP
))
611 return (_field_navigation(_next_field
, f
));
613 if (at_end
&& Status(c
, GROWABLE
) && !_grow_field(c
, 1))
614 return (E_SYSTEM_ERROR
);
616 (void) _next_char(f
);