]> Pileus Git - ~andy/gtk/blob - gtk/gtkmenuitem.c
Use common marshalling routines instead of having widget-private ones. It
[~andy/gtk] / gtk / gtkmenuitem.c
1 /* GTK - The GIMP Toolkit
2  * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball and Josh MacDonald
3  *
4  * This library is free software; you can redistribute it and/or
5  * modify it under the terms of the GNU Library General Public
6  * License as published by the Free Software Foundation; either
7  * version 2 of the License, or (at your option) any later version.
8  *
9  * This library is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
12  * Library General Public License for more details.
13  *
14  * You should have received a copy of the GNU Library General Public
15  * License along with this library; if not, write to the
16  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
17  * Boston, MA 02111-1307, USA.
18  */
19 #include <string.h>
20 #include "gtkaccellabel.h"
21 #include "gtkmain.h"
22 #include "gtkmenu.h"
23 #include "gtkmenuitem.h"
24 #include "gtksignal.h"
25
26
27 #define BORDER_SPACING  3
28 #define SELECT_TIMEOUT  20
29
30 #define MENU_ITEM_CLASS(w)  GTK_MENU_ITEM_CLASS (GTK_OBJECT (w)->klass)
31
32
33 enum {
34   ACTIVATE,
35   LAST_SIGNAL
36 };
37
38
39 static void gtk_menu_item_class_init     (GtkMenuItemClass *klass);
40 static void gtk_menu_item_init           (GtkMenuItem      *menu_item);
41 static void gtk_menu_item_destroy        (GtkObject        *object);
42 static void gtk_menu_item_size_request   (GtkWidget        *widget,
43                                           GtkRequisition   *requisition);
44 static void gtk_menu_item_size_allocate  (GtkWidget        *widget,
45                                           GtkAllocation    *allocation);
46 static void gtk_menu_item_paint          (GtkWidget        *widget,
47                                           GdkRectangle     *area);
48 static void gtk_menu_item_draw           (GtkWidget        *widget,
49                                           GdkRectangle     *area);
50 static gint gtk_menu_item_expose         (GtkWidget        *widget,
51                                           GdkEventExpose   *event);
52 static void gtk_real_menu_item_select    (GtkItem          *item);
53 static void gtk_real_menu_item_deselect  (GtkItem          *item);
54 static gint gtk_menu_item_select_timeout (gpointer          data);
55 static void gtk_menu_item_position_menu  (GtkMenu          *menu,
56                                           gint             *x,
57                                           gint             *y,
58                                           gpointer          user_data);
59 static void gtk_menu_item_show_all       (GtkWidget        *widget);
60 static void gtk_menu_item_hide_all       (GtkWidget        *widget);
61
62 static GtkItemClass *parent_class;
63 static guint menu_item_signals[LAST_SIGNAL] = { 0 };
64
65
66 GtkType
67 gtk_menu_item_get_type (void)
68 {
69   static GtkType menu_item_type = 0;
70
71   if (!menu_item_type)
72     {
73       GtkTypeInfo menu_item_info =
74       {
75         "GtkMenuItem",
76         sizeof (GtkMenuItem),
77         sizeof (GtkMenuItemClass),
78         (GtkClassInitFunc) gtk_menu_item_class_init,
79         (GtkObjectInitFunc) gtk_menu_item_init,
80         /* reserved_1 */ NULL,
81         /* reserved_2 */ NULL,
82         (GtkClassInitFunc) NULL,
83       };
84
85       menu_item_type = gtk_type_unique (gtk_item_get_type (), &menu_item_info);
86       gtk_type_set_chunk_alloc (menu_item_type, 16);
87     }
88
89   return menu_item_type;
90 }
91
92 static void
93 gtk_menu_item_class_init (GtkMenuItemClass *klass)
94 {
95   GtkObjectClass *object_class;
96   GtkWidgetClass *widget_class;
97   GtkItemClass *item_class;
98
99   object_class = (GtkObjectClass*) klass;
100   widget_class = (GtkWidgetClass*) klass;
101   item_class = (GtkItemClass*) klass;
102
103   parent_class = gtk_type_class (gtk_item_get_type ());
104
105   menu_item_signals[ACTIVATE] =
106     gtk_signal_new ("activate",
107                     GTK_RUN_FIRST,
108                     object_class->type,
109                     GTK_SIGNAL_OFFSET (GtkMenuItemClass, activate),
110                     gtk_marshal_NONE__NONE,
111                     GTK_TYPE_NONE, 0);
112
113   gtk_object_class_add_signals (object_class, menu_item_signals, LAST_SIGNAL);
114
115   object_class->destroy = gtk_menu_item_destroy;
116
117   widget_class->activate_signal = menu_item_signals[ACTIVATE];
118   widget_class->size_request = gtk_menu_item_size_request;
119   widget_class->size_allocate = gtk_menu_item_size_allocate;
120   widget_class->draw = gtk_menu_item_draw;
121   widget_class->expose_event = gtk_menu_item_expose;
122   widget_class->show_all = gtk_menu_item_show_all;
123   widget_class->hide_all = gtk_menu_item_hide_all;  
124
125   item_class->select = gtk_real_menu_item_select;
126   item_class->deselect = gtk_real_menu_item_deselect;
127
128   klass->activate = NULL;
129
130   klass->toggle_size = 0;
131 }
132
133 static void
134 gtk_menu_item_init (GtkMenuItem *menu_item)
135 {
136   menu_item->submenu = NULL;
137   menu_item->accelerator_signal = menu_item_signals[ACTIVATE];
138   menu_item->toggle_size = 0;
139   menu_item->accelerator_width = 0;
140   menu_item->show_toggle_indicator = FALSE;
141   menu_item->show_submenu_indicator = FALSE;
142   menu_item->submenu_direction = GTK_DIRECTION_RIGHT;
143   menu_item->submenu_placement = GTK_TOP_BOTTOM;
144   menu_item->right_justify = FALSE;
145
146   menu_item->timer = 0;
147 }
148
149 GtkWidget*
150 gtk_menu_item_new (void)
151 {
152   return GTK_WIDGET (gtk_type_new (gtk_menu_item_get_type ()));
153 }
154
155 GtkWidget*
156 gtk_menu_item_new_with_label (const gchar *label)
157 {
158   GtkWidget *menu_item;
159   GtkWidget *accel_label;
160
161   menu_item = gtk_menu_item_new ();
162   accel_label = gtk_accel_label_new (label);
163   gtk_misc_set_alignment (GTK_MISC (accel_label), 0.0, 0.5);
164
165   gtk_container_add (GTK_CONTAINER (menu_item), accel_label);
166   gtk_accel_label_set_accel_widget (GTK_ACCEL_LABEL (accel_label), menu_item);
167   gtk_widget_show (accel_label);
168
169   return menu_item;
170 }
171
172 static void
173 gtk_menu_item_destroy (GtkObject *object)
174 {
175   GtkMenuItem *menu_item;
176
177   g_return_if_fail (object != NULL);
178   g_return_if_fail (GTK_IS_MENU_ITEM (object));
179
180   menu_item = GTK_MENU_ITEM (object);
181
182   if (menu_item->submenu)
183     gtk_widget_destroy (menu_item->submenu);
184
185   if (GTK_OBJECT_CLASS (parent_class)->destroy)
186     (* GTK_OBJECT_CLASS (parent_class)->destroy) (object);
187 }
188
189 static void
190 gtk_menu_item_detacher (GtkWidget     *widget,
191                         GtkMenu       *menu)
192 {
193   GtkMenuItem *menu_item;
194
195   g_return_if_fail (widget != NULL);
196   g_return_if_fail (GTK_IS_MENU_ITEM (widget));
197
198   menu_item = GTK_MENU_ITEM (widget);
199   g_return_if_fail (menu_item->submenu == (GtkWidget*) menu);
200
201   menu_item->submenu = NULL;
202 }
203
204 void
205 gtk_menu_item_set_submenu (GtkMenuItem *menu_item,
206                            GtkWidget   *submenu)
207 {
208   g_return_if_fail (menu_item != NULL);
209   g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
210   
211   if (menu_item->submenu != submenu)
212     {
213       gtk_menu_item_remove_submenu (menu_item);
214       
215       menu_item->submenu = submenu;
216       gtk_menu_attach_to_widget (GTK_MENU (submenu),
217                                  GTK_WIDGET (menu_item),
218                                  gtk_menu_item_detacher);
219       
220       if (GTK_WIDGET (menu_item)->parent)
221         gtk_widget_queue_resize (GTK_WIDGET (menu_item));
222     }
223 }
224
225 void
226 gtk_menu_item_remove_submenu (GtkMenuItem         *menu_item)
227 {
228   g_return_if_fail (menu_item != NULL);
229   g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
230       
231   if (menu_item->submenu)
232     gtk_menu_detach (GTK_MENU (menu_item->submenu));
233 }
234
235 void
236 gtk_menu_item_set_placement (GtkMenuItem         *menu_item,
237                              GtkSubmenuPlacement  placement)
238 {
239   g_return_if_fail (menu_item != NULL);
240   g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
241
242   menu_item->submenu_placement = placement;
243 }
244
245 void
246 gtk_menu_item_configure (GtkMenuItem *menu_item,
247                          gint         show_toggle_indicator,
248                          gint         show_submenu_indicator)
249 {
250   g_return_if_fail (menu_item != NULL);
251   g_return_if_fail (GTK_IS_MENU_ITEM (menu_item));
252
253   menu_item->show_toggle_indicator = (show_toggle_indicator == TRUE);
254   menu_item->show_submenu_indicator = (show_submenu_indicator == TRUE);
255 }
256
257 void
258 gtk_menu_item_select (GtkMenuItem *menu_item)
259 {
260   gtk_item_select (GTK_ITEM (menu_item));
261 }
262
263 void
264 gtk_menu_item_deselect (GtkMenuItem *menu_item)
265 {
266   gtk_item_deselect (GTK_ITEM (menu_item));
267 }
268
269 void
270 gtk_menu_item_activate (GtkMenuItem *menu_item)
271 {
272   gtk_signal_emit (GTK_OBJECT (menu_item), menu_item_signals[ACTIVATE]);
273 }
274
275 static void
276 gtk_menu_item_accel_width_foreach (GtkWidget *widget,
277                                    gpointer data)
278 {
279   guint *width = data;
280
281   if (GTK_IS_ACCEL_LABEL (widget))
282     {
283       guint w;
284
285       w = gtk_accel_label_accelerator_width (GTK_ACCEL_LABEL (widget));
286       *width = MAX (*width, w);
287     }
288   else if (GTK_IS_CONTAINER (widget))
289     gtk_container_foreach (GTK_CONTAINER (widget),
290                            gtk_menu_item_accel_width_foreach,
291                            data);
292 }
293
294 static void
295 gtk_menu_item_size_request (GtkWidget      *widget,
296                             GtkRequisition *requisition)
297 {
298   GtkMenuItem *menu_item;
299   GtkBin *bin;
300   guint accel_width;
301
302   g_return_if_fail (widget != NULL);
303   g_return_if_fail (GTK_IS_MENU_ITEM (widget));
304   g_return_if_fail (requisition != NULL);
305
306   bin = GTK_BIN (widget);
307   menu_item = GTK_MENU_ITEM (widget);
308
309   requisition->width = (GTK_CONTAINER (widget)->border_width +
310                         widget->style->klass->xthickness +
311                         BORDER_SPACING) * 2;
312   requisition->height = (GTK_CONTAINER (widget)->border_width +
313                          widget->style->klass->ythickness) * 2;
314
315   if (bin->child && GTK_WIDGET_VISIBLE (bin->child))
316     {
317       gtk_widget_size_request (bin->child, &bin->child->requisition);
318
319       requisition->width += bin->child->requisition.width;
320       requisition->height += bin->child->requisition.height;
321     }
322
323   if (menu_item->submenu && menu_item->show_submenu_indicator)
324     requisition->width += 21;
325
326   accel_width = 0;
327   gtk_container_foreach (GTK_CONTAINER (menu_item),
328                          gtk_menu_item_accel_width_foreach,
329                          &accel_width);
330   menu_item->accelerator_width = accel_width;
331 }
332
333 static void
334 gtk_menu_item_size_allocate (GtkWidget     *widget,
335                              GtkAllocation *allocation)
336 {
337   GtkMenuItem *menu_item;
338   GtkBin *bin;
339   GtkAllocation child_allocation;
340
341   g_return_if_fail (widget != NULL);
342   g_return_if_fail (GTK_IS_MENU_ITEM (widget));
343   g_return_if_fail (allocation != NULL);
344
345   menu_item = GTK_MENU_ITEM (widget);
346   bin = GTK_BIN (widget);
347   
348   widget->allocation = *allocation;
349
350   if (bin->child)
351     {
352       child_allocation.x = (GTK_CONTAINER (widget)->border_width +
353                             widget->style->klass->xthickness +
354                             BORDER_SPACING);
355       child_allocation.y = (GTK_CONTAINER (widget)->border_width +
356                             widget->style->klass->ythickness);
357       child_allocation.width = MAX (1, allocation->width - child_allocation.x * 2);
358       child_allocation.height = MAX (1, allocation->height - child_allocation.y * 2);
359       child_allocation.x += GTK_MENU_ITEM (widget)->toggle_size;
360       child_allocation.width -= GTK_MENU_ITEM (widget)->toggle_size;
361       if (menu_item->submenu && menu_item->show_submenu_indicator)
362         child_allocation.width -= 21;
363       
364       gtk_widget_size_allocate (bin->child, &child_allocation);
365     }
366
367   if (GTK_WIDGET_REALIZED (widget))
368     gdk_window_move_resize (widget->window,
369                             allocation->x, allocation->y,
370                             allocation->width, allocation->height);
371
372   if (menu_item->submenu)
373     gtk_menu_reposition (GTK_MENU (menu_item->submenu));
374 }
375
376 static void
377 gtk_menu_item_paint (GtkWidget    *widget,
378                      GdkRectangle *area)
379 {
380   GtkMenuItem *menu_item;
381   GtkStateType state_type;
382   GtkShadowType shadow_type;
383   gint width, height;
384   gint x, y;
385
386   g_return_if_fail (widget != NULL);
387   g_return_if_fail (GTK_IS_MENU_ITEM (widget));
388
389   if (GTK_WIDGET_DRAWABLE (widget))
390     {
391       menu_item = GTK_MENU_ITEM (widget);
392
393       state_type = widget->state;
394       if (!GTK_WIDGET_IS_SENSITIVE (widget))
395         state_type = GTK_STATE_INSENSITIVE;
396
397       gtk_style_set_background (widget->style, widget->window, state_type);
398       gdk_window_clear_area (widget->window, area->x, area->y, area->width, area->height);
399
400       x = GTK_CONTAINER (menu_item)->border_width;
401       y = GTK_CONTAINER (menu_item)->border_width;
402       width = widget->allocation.width - x * 2;
403       height = widget->allocation.height - y * 2;
404
405       if ((state_type == GTK_STATE_PRELIGHT) &&
406           (GTK_BIN (menu_item)->child))
407         gtk_draw_shadow (widget->style,
408                          widget->window,
409                          GTK_STATE_PRELIGHT,
410                          GTK_SHADOW_OUT,
411                          x, y, width, height);
412
413       if (menu_item->submenu && menu_item->show_submenu_indicator)
414         {
415           shadow_type = GTK_SHADOW_OUT;
416           if (state_type == GTK_STATE_PRELIGHT)
417             shadow_type = GTK_SHADOW_IN;
418
419           gtk_draw_arrow (widget->style, widget->window,
420                           state_type, shadow_type, GTK_ARROW_RIGHT, FALSE,
421                           x + width - 15, y + height / 2 - 5, 10, 10);
422         }
423       else if (!GTK_BIN (menu_item)->child)
424         {
425           gtk_draw_hline (widget->style, widget->window, GTK_STATE_NORMAL,
426                           0, widget->allocation.width, 0);
427         }
428     }
429 }
430
431 static void
432 gtk_menu_item_draw (GtkWidget    *widget,
433                     GdkRectangle *area)
434 {
435   GtkBin *bin;
436   GdkRectangle child_area;
437
438   g_return_if_fail (widget != NULL);
439   g_return_if_fail (GTK_IS_MENU_ITEM (widget));
440   g_return_if_fail (area != NULL);
441
442   if (GTK_WIDGET_DRAWABLE (widget))
443     {
444       gtk_menu_item_paint (widget, area);
445
446       bin = GTK_BIN (widget);
447
448       if (bin->child)
449         {
450           if (gtk_widget_intersect (bin->child, area, &child_area))
451             gtk_widget_draw (bin->child, &child_area);
452         }
453     }
454 }
455
456 static gint
457 gtk_menu_item_expose (GtkWidget      *widget,
458                       GdkEventExpose *event)
459 {
460   GtkBin *bin;
461   GdkEventExpose child_event;
462
463   g_return_val_if_fail (widget != NULL, FALSE);
464   g_return_val_if_fail (GTK_IS_MENU_ITEM (widget), FALSE);
465   g_return_val_if_fail (event != NULL, FALSE);
466
467   if (GTK_WIDGET_DRAWABLE (widget))
468     {
469       gtk_menu_item_paint (widget, &event->area);
470
471       bin = GTK_BIN (widget);
472
473       if (bin->child)
474         {
475           child_event = *event;
476
477           if (GTK_WIDGET_NO_WINDOW (bin->child) &&
478               gtk_widget_intersect (bin->child, &event->area, &child_event.area))
479             gtk_widget_event (bin->child, (GdkEvent*) &child_event);
480         }
481     }
482
483   return FALSE;
484 }
485
486 static void
487 gtk_real_menu_item_select (GtkItem *item)
488 {
489   GtkMenuItem *menu_item;
490
491   g_return_if_fail (item != NULL);
492   g_return_if_fail (GTK_IS_MENU_ITEM (item));
493
494   menu_item = GTK_MENU_ITEM (item);
495
496   if (menu_item->submenu && !GTK_WIDGET_VISIBLE (menu_item->submenu))
497     menu_item->timer = gtk_timeout_add (SELECT_TIMEOUT, gtk_menu_item_select_timeout, menu_item);
498
499   gtk_widget_set_state (GTK_WIDGET (menu_item), GTK_STATE_PRELIGHT);
500   gtk_widget_draw (GTK_WIDGET (menu_item), NULL);
501 }
502
503 static void
504 gtk_real_menu_item_deselect (GtkItem *item)
505 {
506   GtkMenuItem *menu_item;
507
508   g_return_if_fail (item != NULL);
509   g_return_if_fail (GTK_IS_MENU_ITEM (item));
510
511   menu_item = GTK_MENU_ITEM (item);
512
513   if (menu_item->submenu)
514     {
515       if (menu_item->timer)
516         gtk_timeout_remove (menu_item->timer);
517       else
518         gtk_menu_popdown (GTK_MENU (menu_item->submenu));
519     }
520
521   gtk_widget_set_state (GTK_WIDGET (menu_item), GTK_STATE_NORMAL);
522   gtk_widget_draw (GTK_WIDGET (menu_item), NULL);
523 }
524
525 static gint
526 gtk_menu_item_select_timeout (gpointer data)
527 {
528   GtkMenuItem *menu_item;
529
530   menu_item = GTK_MENU_ITEM (data);
531   menu_item->timer = 0;
532
533   gtk_menu_popup (GTK_MENU (menu_item->submenu),
534                   GTK_WIDGET (menu_item)->parent,
535                   GTK_WIDGET (menu_item),
536                   gtk_menu_item_position_menu,
537                   menu_item,
538                   GTK_MENU_SHELL (GTK_WIDGET (menu_item)->parent)->button,
539                   0);
540
541   return FALSE;
542 }
543
544 static void
545 gtk_menu_item_position_menu (GtkMenu  *menu,
546                              gint     *x,
547                              gint     *y,
548                              gpointer  user_data)
549 {
550   GtkMenuItem *menu_item;
551   GtkWidget *parent_menu_item;
552   gint screen_width;
553   gint screen_height;
554   gint twidth, theight;
555   gint tx, ty;
556
557   g_return_if_fail (menu != NULL);
558   g_return_if_fail (x != NULL);
559   g_return_if_fail (y != NULL);
560
561   menu_item = GTK_MENU_ITEM (user_data);
562
563   twidth = GTK_WIDGET (menu)->requisition.width;
564   theight = GTK_WIDGET (menu)->requisition.height;
565
566   screen_width = gdk_screen_width ();
567   screen_height = gdk_screen_height ();
568
569   if (!gdk_window_get_origin (GTK_WIDGET (menu_item)->window, &tx, &ty))
570     {
571       g_warning ("Menu not on screen");
572       return;
573     }
574
575   switch (menu_item->submenu_placement)
576     {
577     case GTK_TOP_BOTTOM:
578       if ((ty + GTK_WIDGET (menu_item)->allocation.height + theight) <= screen_height)
579         ty += GTK_WIDGET (menu_item)->allocation.height;
580       else if ((ty - theight) >= 0)
581         ty -= theight;
582       else
583         ty += GTK_WIDGET (menu_item)->allocation.height;
584
585       if ((tx + twidth) > screen_width)
586         {
587           tx -= ((tx + twidth) - screen_width);
588           if (tx < 0)
589             tx = 0;
590         }
591       break;
592
593     case GTK_LEFT_RIGHT:
594       menu_item->submenu_direction = GTK_DIRECTION_RIGHT;
595       parent_menu_item = GTK_MENU (GTK_WIDGET (menu_item)->parent)->parent_menu_item;
596       if (parent_menu_item)
597         menu_item->submenu_direction = GTK_MENU_ITEM (parent_menu_item)->submenu_direction;
598
599       switch (menu_item->submenu_direction)
600         {
601         case GTK_DIRECTION_LEFT:
602           if ((tx - twidth) >= 0)
603             tx -= twidth;
604           else
605             {
606               menu_item->submenu_direction = GTK_DIRECTION_RIGHT;
607               tx += GTK_WIDGET (menu_item)->allocation.width - 5;
608             }
609           break;
610
611         case GTK_DIRECTION_RIGHT:
612           if ((tx + GTK_WIDGET (menu_item)->allocation.width + twidth - 5) <= screen_width)
613             tx += GTK_WIDGET (menu_item)->allocation.width - 5;
614           else
615             {
616               menu_item->submenu_direction = GTK_DIRECTION_LEFT;
617               tx -= twidth;
618             }
619           break;
620         }
621
622       if ((ty + GTK_WIDGET (menu_item)->allocation.height / 4 + theight) <= screen_height)
623         ty += GTK_WIDGET (menu_item)->allocation.height / 4;
624       else
625         {
626           ty -= ((ty + theight) - screen_height);
627           if (ty < 0)
628             ty = 0;
629         }
630       break;
631     }
632
633   *x = tx;
634   *y = ty;
635 }
636
637 void
638 gtk_menu_item_right_justify(GtkMenuItem *menuitem)
639 {
640   g_return_if_fail (menuitem != NULL);
641   g_return_if_fail (GTK_IS_MENU_ITEM (menuitem));
642
643   menuitem->right_justify = 1;
644 }
645
646 static void
647 gtk_menu_item_show_all (GtkWidget *widget)
648 {
649   GtkContainer *container;
650   GtkMenuItem  *menu_item;
651
652   g_return_if_fail (widget != NULL);
653   g_return_if_fail (GTK_IS_MENU_ITEM (widget));
654   container = GTK_CONTAINER (widget);
655   menu_item = GTK_MENU_ITEM (widget);
656
657   /* Show children, traverse to submenu, show self. */
658   gtk_container_foreach (container, (GtkCallback) gtk_widget_show_all, NULL);
659   if (menu_item->submenu)
660     gtk_widget_show_all (menu_item->submenu);
661   gtk_widget_show (widget);
662 }
663
664
665 static void
666 gtk_menu_item_hide_all (GtkWidget *widget)
667 {
668   GtkContainer *container;
669   GtkMenuItem  *menu_item;
670
671   g_return_if_fail (widget != NULL);
672   g_return_if_fail (GTK_IS_MENU_ITEM (widget));
673   container = GTK_CONTAINER (widget);
674   menu_item = GTK_MENU_ITEM (widget);
675
676   /* Reverse order of gtk_menu_item_show_all */
677   gtk_widget_hide (widget);
678   if (menu_item->submenu)
679     gtk_widget_hide_all (menu_item->submenu);
680   gtk_container_foreach (container, (GtkCallback) gtk_widget_hide_all, NULL);
681 }