xref: /illumos-gate/usr/src/lib/libeti/menu/common/link.c (revision 20a7641f9918de8574b8b3b47dbe35c4bfc78df1)
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 "private.h"
35 
36 static void
37 link_col_major(MENU *m)
38 {
39 	ITEM *i;
40 	int n;
41 	short c, r;
42 	int left, up;
43 
44 	r = 0;
45 	c = 0;
46 	for (i = IthItem(m, 0), n = 0; i; i = IthItem(m, ++n)) {
47 		X(i) = c;
48 		Y(i) = r;
49 		Left(i) = c ? IthItem(m, n-Rows(m)) : (ITEM *) NULL;
50 		if (n + Rows(m) >= Nitems(m)) {
51 			Right(i) = (ITEM *) NULL;
52 		} else {
53 			Right(i) = IthItem(m, n + Rows(m));
54 		}
55 		Up(i) = r ? IthItem(m, n-1) : (ITEM *) NULL;
56 		Down(i) = (r == Rows(m)-1) ? (ITEM *)0 : IthItem(m, n+1);
57 		if (++r == Rows(m)) {
58 			r = 0;
59 			c += 1;
60 		}
61 	}
62 	if (r) {
63 		Down(IthItem(m, n-1)) = IthItem(m, n - Rows(m));
64 	}
65 
66 	if (Cyclic(m)) {
67 		/* Set up left and right links at edge of menu */
68 
69 		r = Rows(m) * (Nitems(m)/Rows(m));
70 		for (n = 0; n < Rows(m); n++) {
71 			left = n + r;
72 			if (left >= Nitems(m)) {
73 				left -= Rows(m);
74 			}
75 			Left(IthItem(m, n)) = IthItem(m, left);
76 			Right(IthItem(m, left)) = IthItem(m, n);
77 		}
78 
79 		/* Setup up and down links at edge of menu */
80 
81 		for (n = 0; n < Nitems(m); n += Rows(m)) {
82 			up = n + Rows(m) - 1;
83 			if (up >= Nitems(m)) {
84 				Up(IthItem(m, n)) = IthItem(m, n-1);
85 			} else {
86 				Up(IthItem(m, n)) = IthItem(m, up);
87 				Down(IthItem(m, up)) = IthItem(m, n);
88 			}
89 		}
90 	}
91 }
92 
93 static void
94 link_row_major(MENU *m)
95 {
96 	int n;
97 	short c, r;
98 	ITEM *i;
99 	int left, up;
100 
101 	r = 0;
102 	c = 0;
103 	for (i = IthItem(m, 0), n = 0; i; i = IthItem(m, ++n)) {
104 		X(i) = c;
105 		Y(i) = r;
106 		Left(i) = c ? IthItem(m, n-1) : (ITEM *) NULL;
107 		Right(i) = (c == Cols(m)-1 || n == Nitems(m)-1) ? (ITEM *)0 :
108 				IthItem(m, n+1);
109 		Up(i) = r ? IthItem(m, n-Cols(m)) : (ITEM *) NULL;
110 
111 		if (n+Cols(m) < Nitems(m)) {
112 			Down(i) = IthItem(m, n + Cols(m));
113 		} else {
114 			if (r == Rows(m)-1) {
115 				/* Down is undefined if this is a complete */
116 				/* last column */
117 				Down(i) = (ITEM *) NULL;
118 			} else {
119 				/* Down is set to last item if the last */
120 				/* column isn't full */
121 				Down(i) = IthItem(m, Nitems(m)-1);
122 			}
123 		}
124 		if (++c == Cols(m)) {
125 			c = 0;
126 			r += 1;
127 		}
128 	}
129 
130 	if (Cyclic(m)) {
131 
132 		/* Setup left and right links at edge of menu */
133 
134 		for (n = 0; n < Nitems(m); n += Cols(m)) {
135 			left = n + Cols(m) - 1;
136 			if (left >= Nitems(m)) {
137 				left = Nitems(m) - 1;
138 			}
139 			Left(IthItem(m, n)) = IthItem(m, left);
140 			Right(IthItem(m, left)) = IthItem(m, n);
141 		}
142 
143 		/* Setup up and down links at edge of menu */
144 
145 		r = (Rows(m) - 1) * Cols(m);
146 		for (n = 0; n < Cols(m); n++) {
147 			up = n + r;
148 
149 			/* If there is an incomplete line below this one */
150 			/* the point to the last item in the menu. */
151 
152 			if (up >= Nitems(m)) {
153 				Up(IthItem(m, n)) = IthItem(m, Nitems(m)-1);
154 			} else {
155 				Up(IthItem(m, n)) = IthItem(m, up);
156 				Down(IthItem(m, up)) = IthItem(m, n);
157 			}
158 		}
159 	}
160 }
161 
162 void
163 _link_items(MENU *m)
164 {
165 	if (Items(m) && IthItem(m, 0)) {
166 		ResetLink(m);
167 		if (RowMajor(m)) {
168 			link_row_major(m);
169 		} else {
170 			link_col_major(m);
171 		}
172 	}
173 }
174