1/*
2 * CDDL HEADER START
3 *
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
7 * with the License.
8 *
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.
13 *
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]
19 *
20 * CDDL HEADER END
21 */
22/*	Copyright (c) 1988 AT&T	*/
23/*	  All Rights Reserved  	*/
24
25
26/*
27 * Copyright (c) 1997, by Sun Mircrosystems, Inc.
28 * All rights reserved.
29 */
30
31#pragma	ident	"%Z%%M%	%I%	%E% SMI"	/* SVr4.0 1.13	*/
32
33/*LINTLIBRARY*/
34
35#include <sys/types.h>
36#include <ctype.h>
37#include "private.h"
38
39static int
40substr(MENU *m, char *s1, char *s2)
41{
42	if (IgnoreCase(m)) {
43		while (*s1 && *s2) {
44			if (toupper(*s1++) != toupper(*s2++)) {
45				return (FALSE);
46			}
47		}
48	} else {
49		while (*s1 && *s2) {
50			if (*s1++ != *s2++) {
51				return (FALSE);
52			}
53		}
54	}
55	if (*s1) {
56		return (FALSE);
57	}
58	return (TRUE);
59}
60
61int
62_match(MENU *m, char c, ITEM **current)
63{
64	int i, j;
65	int found;
66	/*
67	 * Indicates search has cycled past the current item.  If the current
68	 * item is matched after cycled is true then NO_MATCH results.
69	 */
70	int cycled;
71
72	/* If a backspace is encountered then search backward from the */
73	/* current item.  Otherwise, search forward from the current item. */
74
75	i = Index(*current);
76	if (c && c != '\b') {		/* c could be null */
77		if (Pindex(m)+1 > MaxName(m)) {
78			return (E_NO_MATCH);
79		}
80		IthPattern(m, Pindex(m)) = c;
81		IthPattern(m, ++Pindex(m)) = '\0';
82		if (--i < 0) {
83			i = Nitems(m)-1;
84		}
85	}
86
87	j = i;
88	found = FALSE;
89	cycled = FALSE;
90
91	do {
92		if (c == '\b') {
93			if (--i < 0) {
94				i = Nitems(m)-1;
95			}
96		} else {
97			if (++i >= Nitems(m)) {
98				i = 0;
99			}
100		}
101		if (substr(m, Pattern(m), Name(IthItem(m, i)))) {
102			found = TRUE;
103			break;
104		}
105		cycled = TRUE;
106	} while (i != j);
107
108	if (found) {
109		if (i == Index(*current) && cycled) {
110			return (E_NO_MATCH);
111		}
112		*current = IthItem(m, i);
113	} else {
114		if (c && c != '\b') {
115			Pindex(m) -= 1;
116			IthPattern(m, Pindex(m)) = '\0';
117		}
118		return (E_NO_MATCH);
119	}
120	return (E_OK);
121}
122
123char *
124menu_pattern(MENU *m)
125{
126	if (m) {
127		if (Pattern(m)) {
128			return (Pattern(m));
129		} else {
130			return ("");
131		}
132	} else {
133		return (NULL);
134	}
135}
136
137int
138set_menu_pattern(MENU *m, char *s)
139{
140	int top;
141	ITEM *current;
142
143	if (!m || !s) {
144		return (E_BAD_ARGUMENT);
145	}
146	if (!Items(m)) {
147		return (E_NOT_CONNECTED);
148	}
149	if (Indriver(m)) {
150		return (E_BAD_STATE);
151	}
152
153	IthPattern(m, 0) = '\0';
154	Pindex(m) = 0;
155
156	if (*s == '\0') {
157		_position_cursor(m);
158		return (E_OK);
159	}
160	if (LinkNeeded(m)) {
161		_link_items(m);
162	}
163
164	top = Top(m);
165	current = Current(m);
166
167	for (; *s; s++) {
168		if (_match(m, *s, &current) != E_OK) {
169			IthPattern(m, 0) = '\0';
170			Pindex(m) = 0;
171			_position_cursor(m);
172			return (E_NO_MATCH);
173		}
174	}
175	_chk_current(m, &top, current);
176	_affect_change(m, top, current);
177	return (E_OK);
178}
179