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