Mercurial > mplayer.hg
annotate libmenu/menu_list.c @ 22188:b9fa8b0ddab9
strncat() misuses, may have been exploitable.
Reported by Sascha Sommer.
author | rtogni |
---|---|
date | Sun, 11 Feb 2007 18:00:06 +0000 |
parents | ac69ba536915 |
children | 476d4922566a |
rev | line source |
---|---|
8197 | 1 |
2 #include <stdlib.h> | |
3 #include <stdio.h> | |
4 #include <ctype.h> | |
8623
440301fef3fe
Added/reordered #includes to silence warnings about "implicit declaration".
rathann
parents:
8197
diff
changeset
|
5 #include <string.h> |
8197 | 6 |
16862 | 7 #include "config.h" |
8197 | 8 |
19431
ac69ba536915
Explicitly include libmpcodecs/img_format.h and libvo/fastmemcpy.h.
diego
parents:
18204
diff
changeset
|
9 #include "libmpcodecs/img_format.h" |
ac69ba536915
Explicitly include libmpcodecs/img_format.h and libvo/fastmemcpy.h.
diego
parents:
18204
diff
changeset
|
10 #include "libmpcodecs/mp_image.h" |
8197 | 11 |
12 #include "m_struct.h" | |
13 #include "menu.h" | |
14 | |
16862 | 15 #include "libvo/font_load.h" |
16 #include "osdep/keycodes.h" | |
8197 | 17 |
18 #define IMPL 1 | |
19 #include "menu_list.h" | |
20 | |
21 #define mpriv (menu->priv) | |
22 | |
23 void menu_list_draw(menu_t* menu,mp_image_t* mpi) { | |
24 int x = mpriv->x; | |
25 int y = mpriv->y; | |
26 int i; | |
27 int h = mpriv->h; | |
28 int w = mpriv->w; | |
29 int dh = 0,dw = 0; | |
30 int dy = 0; | |
17946
0afe12256464
Allow hiding list elements and disableing the pointer.
albeu
parents:
17945
diff
changeset
|
31 int need_h = 0,need_w = 0,ptr_l,sidx = 0; |
0afe12256464
Allow hiding list elements and disableing the pointer.
albeu
parents:
17945
diff
changeset
|
32 int th,count = 0; |
17993
98eb966a4024
Add a function to draw flat boxes and use it to make the list
albeu
parents:
17980
diff
changeset
|
33 int bg_w; |
8197 | 34 list_entry_t* m; |
35 | |
36 if(mpriv->count < 1) | |
37 return; | |
38 | |
39 if(h <= 0) h = mpi->height; | |
40 if(w <= 0) w = mpi->width; | |
41 dh = h - 2*mpriv->minb; | |
42 dw = w - 2*mpriv->minb; | |
17946
0afe12256464
Allow hiding list elements and disableing the pointer.
albeu
parents:
17945
diff
changeset
|
43 ptr_l = mpriv->ptr ? menu_text_length(mpriv->ptr) : 0; |
8197 | 44 // mpi is too small |
45 if(h - vo_font->height <= 0 || w - ptr_l <= 0 || dw <= 0 || dh <= 0) | |
46 return; | |
47 | |
48 th = menu_text_num_lines(mpriv->title,dw) * (mpriv->vspace + vo_font->height) + mpriv->vspace; | |
49 | |
17946
0afe12256464
Allow hiding list elements and disableing the pointer.
albeu
parents:
17945
diff
changeset
|
50 // the selected item is hidden, find a visible one |
0afe12256464
Allow hiding list elements and disableing the pointer.
albeu
parents:
17945
diff
changeset
|
51 if(mpriv->current->hide) { |
0afe12256464
Allow hiding list elements and disableing the pointer.
albeu
parents:
17945
diff
changeset
|
52 // try the next |
0afe12256464
Allow hiding list elements and disableing the pointer.
albeu
parents:
17945
diff
changeset
|
53 for(m = mpriv->current->next ; m ; m = m->next) |
0afe12256464
Allow hiding list elements and disableing the pointer.
albeu
parents:
17945
diff
changeset
|
54 if(!m->hide) break; |
0afe12256464
Allow hiding list elements and disableing the pointer.
albeu
parents:
17945
diff
changeset
|
55 if(!m) // or the previous |
0afe12256464
Allow hiding list elements and disableing the pointer.
albeu
parents:
17945
diff
changeset
|
56 for(m = mpriv->current->prev ; m ; m = m->prev) |
0afe12256464
Allow hiding list elements and disableing the pointer.
albeu
parents:
17945
diff
changeset
|
57 if(!m->hide) break; |
0afe12256464
Allow hiding list elements and disableing the pointer.
albeu
parents:
17945
diff
changeset
|
58 if(m) mpriv->current = m; |
0afe12256464
Allow hiding list elements and disableing the pointer.
albeu
parents:
17945
diff
changeset
|
59 else ptr_l = 0; |
0afe12256464
Allow hiding list elements and disableing the pointer.
albeu
parents:
17945
diff
changeset
|
60 } |
0afe12256464
Allow hiding list elements and disableing the pointer.
albeu
parents:
17945
diff
changeset
|
61 |
8197 | 62 for(i = 0, m = mpriv->menu ; m ; m = m->next, i++) { |
17946
0afe12256464
Allow hiding list elements and disableing the pointer.
albeu
parents:
17945
diff
changeset
|
63 int ll; |
0afe12256464
Allow hiding list elements and disableing the pointer.
albeu
parents:
17945
diff
changeset
|
64 if(m->hide) continue; |
0afe12256464
Allow hiding list elements and disableing the pointer.
albeu
parents:
17945
diff
changeset
|
65 ll = menu_text_length(m->txt); |
8197 | 66 if(ptr_l + ll > need_w) need_w = ptr_l + ll; |
67 if(m == mpriv->current) sidx = i; | |
17946
0afe12256464
Allow hiding list elements and disableing the pointer.
albeu
parents:
17945
diff
changeset
|
68 count++; |
8197 | 69 } |
70 if(need_w > dw) need_w = dw; | |
71 if(x > 0) | |
72 x += mpriv->minb; | |
73 if(y > 0) | |
74 y += mpriv->minb; | |
75 else | |
76 y = mpriv->minb; | |
77 | |
17946
0afe12256464
Allow hiding list elements and disableing the pointer.
albeu
parents:
17945
diff
changeset
|
78 need_h = count * (mpriv->vspace + vo_font->height) - mpriv->vspace; |
8197 | 79 if( need_h + th > dh) { |
80 int start,end; | |
81 int maxl = (dh + mpriv->vspace - th) / (mpriv->vspace + vo_font->height); | |
82 if(maxl < 4) { | |
83 th = 0; | |
84 maxl = (dh + mpriv->vspace) / ( vo_font->height + mpriv->vspace); | |
85 } | |
86 // Too smoll | |
87 if(maxl < 1) return; | |
88 need_h = maxl*(mpriv->vspace + vo_font->height) - mpriv->vspace; | |
89 | |
90 start = sidx - (maxl/2); | |
91 if(start < 0) start = 0; | |
92 end = start + maxl; | |
17946
0afe12256464
Allow hiding list elements and disableing the pointer.
albeu
parents:
17945
diff
changeset
|
93 if(end > count) { |
0afe12256464
Allow hiding list elements and disableing the pointer.
albeu
parents:
17945
diff
changeset
|
94 end = count; |
8197 | 95 if(end - start < maxl) |
96 start = end - maxl < 0 ? 0 : end - maxl; | |
97 } | |
98 m = mpriv->menu; | |
17946
0afe12256464
Allow hiding list elements and disableing the pointer.
albeu
parents:
17945
diff
changeset
|
99 for(i = 0 ; m->next && i < start ; ) { |
0afe12256464
Allow hiding list elements and disableing the pointer.
albeu
parents:
17945
diff
changeset
|
100 if(!m->hide) i++; |
8197 | 101 m = m->next; |
17946
0afe12256464
Allow hiding list elements and disableing the pointer.
albeu
parents:
17945
diff
changeset
|
102 } |
8197 | 103 } else |
104 m = mpriv->menu; | |
105 | |
17993
98eb966a4024
Add a function to draw flat boxes and use it to make the list
albeu
parents:
17980
diff
changeset
|
106 bg_w = need_w+2*mpriv->minb; |
8197 | 107 if(th > 0) { |
17993
98eb966a4024
Add a function to draw flat boxes and use it to make the list
albeu
parents:
17980
diff
changeset
|
108 if(mpriv->title_bg >= 0) { |
98eb966a4024
Add a function to draw flat boxes and use it to make the list
albeu
parents:
17980
diff
changeset
|
109 int tw,th2; |
98eb966a4024
Add a function to draw flat boxes and use it to make the list
albeu
parents:
17980
diff
changeset
|
110 menu_text_size(mpriv->title,dw,mpriv->vspace,1,&tw,&th2); |
98eb966a4024
Add a function to draw flat boxes and use it to make the list
albeu
parents:
17980
diff
changeset
|
111 if(tw+2*mpriv->minb > bg_w) bg_w = tw+2*mpriv->minb; |
98eb966a4024
Add a function to draw flat boxes and use it to make the list
albeu
parents:
17980
diff
changeset
|
112 menu_draw_box(mpi,mpriv->title_bg,mpriv->title_bg_alpha, |
18204 | 113 x < 0 ? (mpi->w-bg_w)/2 : x-mpriv->minb,dy+y-mpriv->vspace/2,bg_w,th); |
17993
98eb966a4024
Add a function to draw flat boxes and use it to make the list
albeu
parents:
17980
diff
changeset
|
114 } |
8197 | 115 menu_draw_text_full(mpi,mpriv->title, |
116 x < 0 ? mpi->w / 2 : x, | |
117 dy+y,dw,0, | |
118 mpriv->vspace,1, | |
119 MENU_TEXT_TOP|MENU_TEXT_HCENTER, | |
120 MENU_TEXT_TOP|(x < 0 ? MENU_TEXT_HCENTER :MENU_TEXT_LEFT)); | |
121 dy += th; | |
122 } | |
123 | |
124 for( ; m != NULL && dy + vo_font->height < dh ; m = m->next ) { | |
17946
0afe12256464
Allow hiding list elements and disableing the pointer.
albeu
parents:
17945
diff
changeset
|
125 if(m->hide) continue; |
17993
98eb966a4024
Add a function to draw flat boxes and use it to make the list
albeu
parents:
17980
diff
changeset
|
126 if(m == mpriv->current) { |
98eb966a4024
Add a function to draw flat boxes and use it to make the list
albeu
parents:
17980
diff
changeset
|
127 if(mpriv->ptr_bg >= 0) |
98eb966a4024
Add a function to draw flat boxes and use it to make the list
albeu
parents:
17980
diff
changeset
|
128 menu_draw_box(mpi,mpriv->ptr_bg,mpriv->ptr_bg_alpha, |
18204 | 129 x < 0 ? (mpi->w-bg_w)/2 : x-mpriv->minb,dy+y-mpriv->vspace/2, |
17993
98eb966a4024
Add a function to draw flat boxes and use it to make the list
albeu
parents:
17980
diff
changeset
|
130 bg_w,vo_font->height + mpriv->vspace); |
98eb966a4024
Add a function to draw flat boxes and use it to make the list
albeu
parents:
17980
diff
changeset
|
131 if(ptr_l > 0) |
98eb966a4024
Add a function to draw flat boxes and use it to make the list
albeu
parents:
17980
diff
changeset
|
132 menu_draw_text_full(mpi,mpriv->ptr, |
98eb966a4024
Add a function to draw flat boxes and use it to make the list
albeu
parents:
17980
diff
changeset
|
133 x < 0 ? (mpi->w - need_w) / 2 + ptr_l : x, |
98eb966a4024
Add a function to draw flat boxes and use it to make the list
albeu
parents:
17980
diff
changeset
|
134 dy+y,dw,dh - dy, |
98eb966a4024
Add a function to draw flat boxes and use it to make the list
albeu
parents:
17980
diff
changeset
|
135 mpriv->vspace,0, |
98eb966a4024
Add a function to draw flat boxes and use it to make the list
albeu
parents:
17980
diff
changeset
|
136 MENU_TEXT_TOP|(x < 0 ? MENU_TEXT_RIGHT :MENU_TEXT_LEFT) , |
98eb966a4024
Add a function to draw flat boxes and use it to make the list
albeu
parents:
17980
diff
changeset
|
137 MENU_TEXT_TOP|(x < 0 ? MENU_TEXT_RIGHT :MENU_TEXT_LEFT)); |
98eb966a4024
Add a function to draw flat boxes and use it to make the list
albeu
parents:
17980
diff
changeset
|
138 } else if(mpriv->item_bg >= 0) |
98eb966a4024
Add a function to draw flat boxes and use it to make the list
albeu
parents:
17980
diff
changeset
|
139 menu_draw_box(mpi,mpriv->item_bg,mpriv->item_bg_alpha, |
18204 | 140 x < 0 ? (mpi->w-bg_w)/2 : x-mpriv->minb,dy+y-mpriv->vspace/2, |
17993
98eb966a4024
Add a function to draw flat boxes and use it to make the list
albeu
parents:
17980
diff
changeset
|
141 bg_w,vo_font->height + mpriv->vspace); |
8197 | 142 menu_draw_text_full(mpi,m->txt, |
143 x < 0 ? (mpi->w - need_w) / 2 + ptr_l : x + ptr_l, | |
144 dy+y,dw-ptr_l,dh - dy, | |
145 mpriv->vspace,0, | |
146 MENU_TEXT_TOP|MENU_TEXT_LEFT, | |
147 MENU_TEXT_TOP|MENU_TEXT_LEFT); | |
148 dy += vo_font->height + mpriv->vspace; | |
149 } | |
150 | |
151 } | |
152 | |
153 void menu_list_read_cmd(menu_t* menu,int cmd) { | |
154 switch(cmd) { | |
155 case MENU_CMD_UP: | |
17980 | 156 while(mpriv->current->prev) { |
157 mpriv->current = mpriv->current->prev; | |
17946
0afe12256464
Allow hiding list elements and disableing the pointer.
albeu
parents:
17945
diff
changeset
|
158 if(!mpriv->current->hide) return; |
0afe12256464
Allow hiding list elements and disableing the pointer.
albeu
parents:
17945
diff
changeset
|
159 } |
17980 | 160 for( ; mpriv->current->next != NULL ; mpriv->current = mpriv->current->next) |
161 /* NOTHING */; | |
162 if(!mpriv->current->hide) return; | |
17946
0afe12256464
Allow hiding list elements and disableing the pointer.
albeu
parents:
17945
diff
changeset
|
163 while(mpriv->current->prev) { |
0afe12256464
Allow hiding list elements and disableing the pointer.
albeu
parents:
17945
diff
changeset
|
164 mpriv->current = mpriv->current->prev; |
0afe12256464
Allow hiding list elements and disableing the pointer.
albeu
parents:
17945
diff
changeset
|
165 if(!mpriv->current->hide) return; |
0afe12256464
Allow hiding list elements and disableing the pointer.
albeu
parents:
17945
diff
changeset
|
166 } |
0afe12256464
Allow hiding list elements and disableing the pointer.
albeu
parents:
17945
diff
changeset
|
167 break; |
8197 | 168 case MENU_CMD_DOWN: |
17980 | 169 while(mpriv->current->next) { |
170 mpriv->current = mpriv->current->next; | |
17946
0afe12256464
Allow hiding list elements and disableing the pointer.
albeu
parents:
17945
diff
changeset
|
171 if(!mpriv->current->hide) return; |
0afe12256464
Allow hiding list elements and disableing the pointer.
albeu
parents:
17945
diff
changeset
|
172 } |
17980 | 173 mpriv->current = mpriv->menu; |
174 if(!mpriv->current->hide) return; | |
17946
0afe12256464
Allow hiding list elements and disableing the pointer.
albeu
parents:
17945
diff
changeset
|
175 while(mpriv->current->next) { |
8197 | 176 mpriv->current = mpriv->current->next; |
17946
0afe12256464
Allow hiding list elements and disableing the pointer.
albeu
parents:
17945
diff
changeset
|
177 if(!mpriv->current->hide) return; |
0afe12256464
Allow hiding list elements and disableing the pointer.
albeu
parents:
17945
diff
changeset
|
178 } |
0afe12256464
Allow hiding list elements and disableing the pointer.
albeu
parents:
17945
diff
changeset
|
179 break; |
17945
98f4e3704a76
Allow 6 ways (up/down/left/right/ok/cancel) navigation.
albeu
parents:
16862
diff
changeset
|
180 case MENU_CMD_LEFT: |
8197 | 181 case MENU_CMD_CANCEL: |
182 menu->show = 0; | |
183 menu->cl = 1; | |
184 break; | |
185 } | |
186 } | |
187 | |
188 void menu_list_jump_to_key(menu_t* menu,int c) { | |
10935
ec8a1e6443d5
Fix long-known bug with handling 'down key' in lists.
lumag
parents:
9380
diff
changeset
|
189 if(c < 256 && isalnum(c)) { |
8197 | 190 list_entry_t* e = mpriv->current; |
191 if(e->txt[0] == c) e = e->next; | |
192 for( ; e ; e = e->next) { | |
193 if(e->txt[0] == c) { | |
194 mpriv->current = e; | |
195 return; | |
196 } | |
197 } | |
198 for(e = mpriv->menu ; e ; e = e->next) { | |
199 if(e->txt[0] == c) { | |
200 mpriv->current = e; | |
201 return; | |
202 } | |
203 } | |
204 } else | |
205 menu_dflt_read_key(menu,c); | |
206 } | |
207 | |
208 void menu_list_read_key(menu_t* menu,int c,int jump_to) { | |
209 list_entry_t* m; | |
210 int i; | |
211 switch(c) { | |
212 case KEY_HOME: | |
213 mpriv->current = mpriv->menu; | |
214 break; | |
215 case KEY_END: | |
216 for(m = mpriv->current ; m && m->next ; m = m->next) | |
217 /**/; | |
218 if(m) | |
219 mpriv->current = m; | |
220 break; | |
221 case KEY_PAGE_UP: | |
222 for(i = 0, m = mpriv->current ; m && m->prev && i < 10 ; m = m->prev, i++) | |
223 /**/; | |
224 if(m) | |
225 mpriv->current = m; | |
226 break; | |
227 case KEY_PAGE_DOWN: | |
228 for(i = 0, m = mpriv->current ; m && m->next && i < 10 ; m = m->next, i++) | |
229 /**/; | |
230 if(m) | |
231 mpriv->current = m; | |
232 break; | |
233 default: | |
234 if(jump_to) | |
235 menu_list_jump_to_key(menu,c); | |
236 else | |
237 menu_dflt_read_key(menu,c); | |
238 } | |
239 } | |
240 | |
241 void menu_list_add_entry(menu_t* menu,list_entry_t* entry) { | |
242 list_entry_t* l; | |
243 mpriv->count++; | |
244 | |
245 if(mpriv->menu == NULL) { | |
246 mpriv->menu = mpriv->current = entry; | |
247 return; | |
248 } | |
249 | |
250 for(l = mpriv->menu ; l->next != NULL ; l = l->next) | |
251 /* NOP */; | |
252 l->next = entry; | |
253 entry->prev = l; | |
254 } | |
255 | |
256 void menu_list_init(menu_t* menu) { | |
257 if(!mpriv) | |
258 mpriv = calloc(1,sizeof(struct menu_priv_s)); | |
259 | |
260 } | |
261 | |
262 void menu_list_uninit(menu_t* menu,free_entry_t free_func) { | |
263 list_entry_t *i,*j; | |
264 | |
265 if(!free_func) free_func = (free_entry_t)free; | |
266 | |
267 for(i = mpriv->menu ; i != NULL ; ) { | |
268 j = i->next; | |
269 free_func(i); | |
270 i = j; | |
271 } | |
272 | |
273 mpriv->menu = mpriv->current = NULL; | |
274 | |
275 } | |
17945
98f4e3704a76
Allow 6 ways (up/down/left/right/ok/cancel) navigation.
albeu
parents:
16862
diff
changeset
|
276 |