~canonical-dx-team/ubuntu/maverick/gtk+2.0/menuproxy

« back to all changes in this revision

Viewing changes to gtk/gtkclist.c

  • Committer: Bazaar Package Importer
  • Author(s): Sebastien Bacher
  • Date: 2007-05-04 12:24:25 UTC
  • mfrom: (1.1.21 upstream)
  • Revision ID: james.westby@ubuntu.com-20070504122425-0m8midgzrp40y8w2
Tags: 2.10.12-1ubuntu1
* Sync with Debian
* New upstream version:
  Fixed bugs:
  - 379414 file chooser warnings when changing path in the entry
  - 418585 GtkFileChooserDefault sizing code is not DPI independent
  - 419568 Crash in search if start with special letter
  - 435062 build dies with icon cache validation
  - 379399 Segfault to call gtk_print_operation_run twice.
  - 387889 cups backend has problems when there are too many printers
  - 418531 invalid read to gtkicontheme.c gtk_icon_theme_lookup_icon...
  - 423916 crash in color scheme code
  - 424042 Segmentation fault while quickly pressing Alt+arrows
  - 415260 Protect against negative indices when setting values in G...
  - 419171 XGetVisualInfo() may not set nxvisuals
  - 128852 Gdk cursors don't look good on win32
  - 344657 Ctrl-H doesn't toggle "Show Hidden Files" setting
  - 345345 PrintOperation::paginate is not emitted for class handler
  - 347567 GtkPrintOperation::end-print is not emitted if it's cance...
  - 369112 gtk_ui_manager_add_ui should accept unnamed separator
  - 392015 Selected menu item invisible on Windows Vista
  - 399253 MS-Windows Theme Bottom Tab placement rendering glitches
  - 399425 gtk_input_dialog_fill_axes() adds child to gtkscrolledwin...
  - 403251 [patch] little memory leak in GtkPrintJob
  - 403267 [patch] memory leak in GtkPageSetupUnixDialog
  - 403470 MS-Windows Theme tab placement other than on top leaks a ...
  - 404506 Windows system fonts that have multi-byte font names cann...
  - 405089 Incorrect window placement for GtkEventBox private window
  - 405515 Minor leak in gtkfilesystemmodel.c
  - 405539 gdk_pixbuf_save() for PNG saver can return FALSE without ...
  - 415681 gdk_window_clear_area includes an extra line and column o...
  - 418219 GtkRecentChooser should apply filter before sorting and c...
  - 418403 Scroll to printer after selecting it from settings
  - 421985 _gtk_print_operation_platform_backend_launch_preview
  - 421990 gtk_print_job_get_surface
  - 421993 gtk_print_operation_init
  - 423064 Conditional jump or move depends on uninitialised value(s...
  - 423722 Fix printing header in gtk-demo
  - 424168 gtk_print_operation_run on async preview
  - 425655 Don't install gtk+-unix-print-2.0.pc on non-UNIX platforms
  - 425786 GDK segfaults if XineramaQueryScreens fails
  - 428665 Lpr Backend gets stuck in infinite loop during gtk_enumer...
  - 429902 GtkPrintOperation leaks cairo contextes
  - 431997 First delay of GdkPixbufAnimationIter is wrong
  - 433242 Inconsistent scroll arrow position calculations
  - 433972 Placing gtk.Expander inside a gtk.TextView() changes gtk....
  - 434261 _gtk_toolbar_elide_underscores incorrectly handles some s...
  - 383354 ctrl-L should make 'Location' entry disappear
  - 418673 gtk_recent_manager_add_item
  - 429732 gtk_accel_group_finalize accesses invalid memory
  - 435028 WM_CLIENT_LEADER is wrong on the leader_window
  - 431067 Background of the header window is not updated
  - 338843 add recent files support inside the ui manager
  - 148535 add drop shadow to menus, tooltips, etc. under Windows XP
* debian/control.in:
  - Conflicts on ubuntulooks (<= 0.9.11-1)
* debian/patches/15_default-fallback-icon-theme.patch:
  - patch from Debian, fallback on gnome icon theme

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* GTK - The GIMP Toolkit
 
2
 * Copyright (C) 1995-1997 Peter Mattis, Spencer Kimball, Josh MacDonald, 
 
3
 * Copyright (C) 1997-1998 Jay Painter <jpaint@serv.net><jpaint@gimp.org>  
 
4
 *
 
5
 * This library is free software; you can redistribute it and/or
 
6
 * modify it under the terms of the GNU Lesser General Public
 
7
 * License as published by the Free Software Foundation; either
 
8
 * version 2 of the License, or (at your option) any later version.
 
9
 *
 
10
 * This library is distributed in the hope that it will be useful,
 
11
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
12
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 
13
 * Lesser General Public License for more details.
 
14
 *
 
15
 * You should have received a copy of the GNU Lesser General Public
 
16
 * License along with this library; if not, write to the
 
17
 * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
 
18
 * Boston, MA 02111-1307, USA.
 
19
 */
 
20
 
 
21
/*
 
22
 * Modified by the GTK+ Team and others 1997-2000.  See the AUTHORS
 
23
 * file for a list of people on the GTK+ Team.  See the ChangeLog
 
24
 * files for a list of changes.  These files are distributed with
 
25
 * GTK+ at ftp://ftp.gtk.org/pub/gtk/. 
 
26
 */
 
27
 
 
28
#undef GDK_DISABLE_DEPRECATED
 
29
#undef GTK_DISABLE_DEPRECATED
 
30
 
 
31
#include <config.h>
 
32
 
 
33
#include <stdlib.h>
 
34
#include <string.h>
 
35
 
 
36
#include "gtkmain.h"
 
37
#include "gtkobject.h"
 
38
#include "gtkclist.h"
 
39
#include "gtkbindings.h"
 
40
#include "gtkdnd.h"
 
41
#include "gtkmarshalers.h"
 
42
#include "gtkintl.h"
 
43
#include <gdk/gdkkeysyms.h>
 
44
#include "gtkalias.h"
 
45
 
 
46
/* length of button_actions array */
 
47
#define MAX_BUTTON 5
 
48
 
 
49
/* the width of the column resize windows */
 
50
#define DRAG_WIDTH  6
 
51
 
 
52
/* minimum allowed width of a column */
 
53
#define COLUMN_MIN_WIDTH 5
 
54
 
 
55
/* this defigns the base grid spacing */
 
56
#define CELL_SPACING 1
 
57
 
 
58
/* added the horizontal space at the beginning and end of a row*/
 
59
#define COLUMN_INSET 3
 
60
 
 
61
/* used for auto-scrolling */
 
62
#define SCROLL_TIME  100
 
63
 
 
64
/* gives the top pixel of the given row in context of
 
65
 * the clist's voffset */
 
66
#define ROW_TOP_YPIXEL(clist, row) (((clist)->row_height * (row)) + \
 
67
                                    (((row) + 1) * CELL_SPACING) + \
 
68
                                    (clist)->voffset)
 
69
 
 
70
/* returns the row index from a y pixel location in the 
 
71
 * context of the clist's voffset */
 
72
#define ROW_FROM_YPIXEL(clist, y)  (((y) - (clist)->voffset) / \
 
73
                                    ((clist)->row_height + CELL_SPACING))
 
74
 
 
75
/* gives the left pixel of the given column in context of
 
76
 * the clist's hoffset */
 
77
#define COLUMN_LEFT_XPIXEL(clist, colnum)  ((clist)->column[(colnum)].area.x + \
 
78
                                            (clist)->hoffset)
 
79
 
 
80
/* returns the column index from a x pixel location in the 
 
81
 * context of the clist's hoffset */
 
82
static inline gint
 
83
COLUMN_FROM_XPIXEL (GtkCList * clist,
 
84
                    gint x)
 
85
{
 
86
  gint i, cx;
 
87
 
 
88
  for (i = 0; i < clist->columns; i++)
 
89
    if (clist->column[i].visible)
 
90
      {
 
91
        cx = clist->column[i].area.x + clist->hoffset;
 
92
 
 
93
        if (x >= (cx - (COLUMN_INSET + CELL_SPACING)) &&
 
94
            x <= (cx + clist->column[i].area.width + COLUMN_INSET))
 
95
          return i;
 
96
      }
 
97
 
 
98
  /* no match */
 
99
  return -1;
 
100
}
 
101
 
 
102
/* returns the top pixel of the given row in the context of
 
103
 * the list height */
 
104
#define ROW_TOP(clist, row)        (((clist)->row_height + CELL_SPACING) * (row))
 
105
 
 
106
/* returns the left pixel of the given column in the context of
 
107
 * the list width */
 
108
#define COLUMN_LEFT(clist, colnum) ((clist)->column[(colnum)].area.x)
 
109
 
 
110
/* returns the total height of the list */
 
111
#define LIST_HEIGHT(clist)         (((clist)->row_height * ((clist)->rows)) + \
 
112
                                    (CELL_SPACING * ((clist)->rows + 1)))
 
113
 
 
114
 
 
115
/* returns the total width of the list */
 
116
static inline gint
 
117
LIST_WIDTH (GtkCList * clist) 
 
118
{
 
119
  gint last_column;
 
120
 
 
121
  for (last_column = clist->columns - 1;
 
122
       last_column >= 0 && !clist->column[last_column].visible; last_column--);
 
123
 
 
124
  if (last_column >= 0)
 
125
    return (clist->column[last_column].area.x +
 
126
            clist->column[last_column].area.width +
 
127
            COLUMN_INSET + CELL_SPACING);
 
128
  return 0;
 
129
}
 
130
 
 
131
/* returns the GList item for the nth row */
 
132
#define ROW_ELEMENT(clist, row) (((row) == (clist)->rows - 1) ? \
 
133
                                 (clist)->row_list_end : \
 
134
                                 g_list_nth ((clist)->row_list, (row)))
 
135
 
 
136
 
 
137
/* redraw the list if it's not frozen */
 
138
#define CLIST_UNFROZEN(clist)     (((GtkCList*) (clist))->freeze_count == 0)
 
139
#define CLIST_REFRESH(clist)    G_STMT_START { \
 
140
  if (CLIST_UNFROZEN (clist)) \
 
141
    GTK_CLIST_GET_CLASS (clist)->refresh ((GtkCList*) (clist)); \
 
142
} G_STMT_END
 
143
 
 
144
 
 
145
/* Signals */
 
146
enum {
 
147
  SELECT_ROW,
 
148
  UNSELECT_ROW,
 
149
  ROW_MOVE,
 
150
  CLICK_COLUMN,
 
151
  RESIZE_COLUMN,
 
152
  TOGGLE_FOCUS_ROW,
 
153
  SELECT_ALL,
 
154
  UNSELECT_ALL,
 
155
  UNDO_SELECTION,
 
156
  START_SELECTION,
 
157
  END_SELECTION,
 
158
  TOGGLE_ADD_MODE,
 
159
  EXTEND_SELECTION,
 
160
  SCROLL_VERTICAL,
 
161
  SCROLL_HORIZONTAL,
 
162
  ABORT_COLUMN_RESIZE,
 
163
  LAST_SIGNAL
 
164
};
 
165
 
 
166
enum {
 
167
  SYNC_REMOVE,
 
168
  SYNC_INSERT
 
169
};
 
170
 
 
171
enum {
 
172
  ARG_0,
 
173
  ARG_N_COLUMNS,
 
174
  ARG_SHADOW_TYPE,
 
175
  ARG_SELECTION_MODE,
 
176
  ARG_ROW_HEIGHT,
 
177
  ARG_TITLES_ACTIVE,
 
178
  ARG_REORDERABLE,
 
179
  ARG_USE_DRAG_ICONS,
 
180
  ARG_SORT_TYPE
 
181
};
 
182
 
 
183
/* GtkCList Methods */
 
184
static void     gtk_clist_class_init  (GtkCListClass         *klass);
 
185
static void     gtk_clist_init        (GtkCList              *clist);
 
186
static GObject* gtk_clist_constructor (GType                  type,
 
187
                                       guint                  n_construct_properties,
 
188
                                       GObjectConstructParam *construct_params);
 
189
 
 
190
/* GtkObject Methods */
 
191
static void gtk_clist_destroy  (GtkObject *object);
 
192
static void gtk_clist_finalize (GObject   *object);
 
193
static void gtk_clist_set_arg  (GtkObject *object,
 
194
                                GtkArg    *arg,
 
195
                                guint      arg_id);
 
196
static void gtk_clist_get_arg  (GtkObject *object,
 
197
                                GtkArg    *arg,
 
198
                                guint      arg_id);
 
199
 
 
200
/* GtkWidget Methods */
 
201
static void gtk_clist_set_scroll_adjustments (GtkCList      *clist,
 
202
                                              GtkAdjustment *hadjustment,
 
203
                                              GtkAdjustment *vadjustment);
 
204
static void gtk_clist_realize         (GtkWidget        *widget);
 
205
static void gtk_clist_unrealize       (GtkWidget        *widget);
 
206
static void gtk_clist_map             (GtkWidget        *widget);
 
207
static void gtk_clist_unmap           (GtkWidget        *widget);
 
208
static gint gtk_clist_expose          (GtkWidget        *widget,
 
209
                                       GdkEventExpose   *event);
 
210
static gint gtk_clist_button_press    (GtkWidget        *widget,
 
211
                                       GdkEventButton   *event);
 
212
static gint gtk_clist_button_release  (GtkWidget        *widget,
 
213
                                       GdkEventButton   *event);
 
214
static gint gtk_clist_motion          (GtkWidget        *widget, 
 
215
                                       GdkEventMotion   *event);
 
216
static void gtk_clist_size_request    (GtkWidget        *widget,
 
217
                                       GtkRequisition   *requisition);
 
218
static void gtk_clist_size_allocate   (GtkWidget        *widget,
 
219
                                       GtkAllocation    *allocation);
 
220
static void gtk_clist_draw_focus      (GtkWidget        *widget);
 
221
static gint gtk_clist_focus_in        (GtkWidget        *widget,
 
222
                                       GdkEventFocus    *event);
 
223
static gint gtk_clist_focus_out       (GtkWidget        *widget,
 
224
                                       GdkEventFocus    *event);
 
225
static gint gtk_clist_focus           (GtkWidget        *widget,
 
226
                                       GtkDirectionType  direction);
 
227
static void gtk_clist_set_focus_child (GtkContainer     *container,
 
228
                                       GtkWidget        *child);
 
229
static void gtk_clist_style_set       (GtkWidget        *widget,
 
230
                                       GtkStyle         *previous_style);
 
231
static void gtk_clist_drag_begin      (GtkWidget        *widget,
 
232
                                       GdkDragContext   *context);
 
233
static gint gtk_clist_drag_motion     (GtkWidget        *widget,
 
234
                                       GdkDragContext   *context,
 
235
                                       gint              x,
 
236
                                       gint              y,
 
237
                                       guint             time);
 
238
static void gtk_clist_drag_leave      (GtkWidget        *widget,
 
239
                                       GdkDragContext   *context,
 
240
                                       guint             time);
 
241
static void gtk_clist_drag_end        (GtkWidget        *widget,
 
242
                                       GdkDragContext   *context);
 
243
static gboolean gtk_clist_drag_drop   (GtkWidget      *widget,
 
244
                                       GdkDragContext *context,
 
245
                                       gint            x,
 
246
                                       gint            y,
 
247
                                       guint           time);
 
248
static void gtk_clist_drag_data_get   (GtkWidget        *widget,
 
249
                                       GdkDragContext   *context,
 
250
                                       GtkSelectionData *selection_data,
 
251
                                       guint             info,
 
252
                                       guint             time);
 
253
static void gtk_clist_drag_data_received (GtkWidget        *widget,
 
254
                                          GdkDragContext   *context,
 
255
                                          gint              x,
 
256
                                          gint              y,
 
257
                                          GtkSelectionData *selection_data,
 
258
                                          guint             info,
 
259
                                          guint             time);
 
260
 
 
261
/* GtkContainer Methods */
 
262
static void gtk_clist_forall          (GtkContainer  *container,
 
263
                                       gboolean       include_internals,
 
264
                                       GtkCallback    callback,
 
265
                                       gpointer       callback_data);
 
266
 
 
267
/* Selection */
 
268
static void toggle_row                (GtkCList      *clist,
 
269
                                       gint           row,
 
270
                                       gint           column,
 
271
                                       GdkEvent      *event);
 
272
static void real_select_row           (GtkCList      *clist,
 
273
                                       gint           row,
 
274
                                       gint           column,
 
275
                                       GdkEvent      *event);
 
276
static void real_unselect_row         (GtkCList      *clist,
 
277
                                       gint           row,
 
278
                                       gint           column,
 
279
                                       GdkEvent      *event);
 
280
static void update_extended_selection (GtkCList      *clist,
 
281
                                       gint           row);
 
282
static GList *selection_find          (GtkCList      *clist,
 
283
                                       gint           row_number,
 
284
                                       GList         *row_list_element);
 
285
static void real_select_all           (GtkCList      *clist);
 
286
static void real_unselect_all         (GtkCList      *clist);
 
287
static void move_vertical             (GtkCList      *clist,
 
288
                                       gint           row,
 
289
                                       gfloat         align);
 
290
static void move_horizontal           (GtkCList      *clist,
 
291
                                       gint           diff);
 
292
static void real_undo_selection       (GtkCList      *clist);
 
293
static void fake_unselect_all         (GtkCList      *clist,
 
294
                                       gint           row);
 
295
static void fake_toggle_row           (GtkCList      *clist,
 
296
                                       gint           row);
 
297
static void resync_selection          (GtkCList      *clist,
 
298
                                       GdkEvent      *event);
 
299
static void sync_selection            (GtkCList      *clist,
 
300
                                       gint           row,
 
301
                                       gint           mode);
 
302
static void set_anchor                (GtkCList      *clist,
 
303
                                       gboolean       add_mode,
 
304
                                       gint           anchor,
 
305
                                       gint           undo_anchor);
 
306
static void start_selection           (GtkCList      *clist);
 
307
static void end_selection             (GtkCList      *clist);
 
308
static void toggle_add_mode           (GtkCList      *clist);
 
309
static void toggle_focus_row          (GtkCList      *clist);
 
310
static void extend_selection          (GtkCList      *clist,
 
311
                                       GtkScrollType  scroll_type,
 
312
                                       gfloat         position,
 
313
                                       gboolean       auto_start_selection);
 
314
static gint get_selection_info        (GtkCList       *clist,
 
315
                                       gint            x,
 
316
                                       gint            y,
 
317
                                       gint           *row,
 
318
                                       gint           *column);
 
319
 
 
320
/* Scrolling */
 
321
static void move_focus_row     (GtkCList      *clist,
 
322
                                GtkScrollType  scroll_type,
 
323
                                gfloat         position);
 
324
static void scroll_horizontal  (GtkCList      *clist,
 
325
                                GtkScrollType  scroll_type,
 
326
                                gfloat         position);
 
327
static void scroll_vertical    (GtkCList      *clist,
 
328
                                GtkScrollType  scroll_type,
 
329
                                gfloat         position);
 
330
static void move_horizontal    (GtkCList      *clist,
 
331
                                gint           diff);
 
332
static void move_vertical      (GtkCList      *clist,
 
333
                                gint           row,
 
334
                                gfloat         align);
 
335
static gint horizontal_timeout (GtkCList      *clist);
 
336
static gint vertical_timeout   (GtkCList      *clist);
 
337
static void remove_grab        (GtkCList      *clist);
 
338
 
 
339
 
 
340
/* Resize Columns */
 
341
static void draw_xor_line             (GtkCList       *clist);
 
342
static gint new_column_width          (GtkCList       *clist,
 
343
                                       gint            column,
 
344
                                       gint           *x);
 
345
static void column_auto_resize        (GtkCList       *clist,
 
346
                                       GtkCListRow    *clist_row,
 
347
                                       gint            column,
 
348
                                       gint            old_width);
 
349
static void real_resize_column        (GtkCList       *clist,
 
350
                                       gint            column,
 
351
                                       gint            width);
 
352
static void abort_column_resize       (GtkCList       *clist);
 
353
static void cell_size_request         (GtkCList       *clist,
 
354
                                       GtkCListRow    *clist_row,
 
355
                                       gint            column,
 
356
                                       GtkRequisition *requisition);
 
357
 
 
358
/* Buttons */
 
359
static void column_button_create      (GtkCList       *clist,
 
360
                                       gint            column);
 
361
static void column_button_clicked     (GtkWidget      *widget,
 
362
                                       gpointer        data);
 
363
 
 
364
/* Adjustments */
 
365
static void adjust_adjustments        (GtkCList       *clist,
 
366
                                       gboolean        block_resize);
 
367
static void vadjustment_changed       (GtkAdjustment  *adjustment,
 
368
                                       gpointer        data);
 
369
static void vadjustment_value_changed (GtkAdjustment  *adjustment,
 
370
                                       gpointer        data);
 
371
static void hadjustment_changed       (GtkAdjustment  *adjustment,
 
372
                                       gpointer        data);
 
373
static void hadjustment_value_changed (GtkAdjustment  *adjustment,
 
374
                                       gpointer        data);
 
375
 
 
376
/* Drawing */
 
377
static void get_cell_style   (GtkCList      *clist,
 
378
                              GtkCListRow   *clist_row,
 
379
                              gint           state,
 
380
                              gint           column,
 
381
                              GtkStyle     **style,
 
382
                              GdkGC        **fg_gc,
 
383
                              GdkGC        **bg_gc);
 
384
static gint draw_cell_pixmap (GdkWindow     *window,
 
385
                              GdkRectangle  *clip_rectangle,
 
386
                              GdkGC         *fg_gc,
 
387
                              GdkPixmap     *pixmap,
 
388
                              GdkBitmap     *mask,
 
389
                              gint           x,
 
390
                              gint           y,
 
391
                              gint           width,
 
392
                              gint           height);
 
393
static void draw_row         (GtkCList      *clist,
 
394
                              GdkRectangle  *area,
 
395
                              gint           row,
 
396
                              GtkCListRow   *clist_row);
 
397
static void draw_rows        (GtkCList      *clist,
 
398
                              GdkRectangle  *area);
 
399
static void clist_refresh    (GtkCList      *clist);
 
400
static void draw_drag_highlight (GtkCList        *clist,
 
401
                                 GtkCListRow     *dest_row,
 
402
                                 gint             dest_row_number,
 
403
                                 GtkCListDragPos  drag_pos);
 
404
     
 
405
/* Size Allocation / Requisition */
 
406
static void size_allocate_title_buttons (GtkCList *clist);
 
407
static void size_allocate_columns       (GtkCList *clist,
 
408
                                         gboolean  block_resize);
 
409
static gint list_requisition_width      (GtkCList *clist);
 
410
 
 
411
/* Memory Allocation/Distruction Routines */
 
412
static GtkCListColumn *columns_new (GtkCList      *clist);
 
413
static void column_title_new       (GtkCList      *clist,
 
414
                                    gint           column,
 
415
                                    const gchar   *title);
 
416
static void columns_delete         (GtkCList      *clist);
 
417
static GtkCListRow *row_new        (GtkCList      *clist);
 
418
static void row_delete             (GtkCList      *clist,
 
419
                                    GtkCListRow   *clist_row);
 
420
static void set_cell_contents      (GtkCList      *clist,
 
421
                                    GtkCListRow   *clist_row,
 
422
                                    gint           column,
 
423
                                    GtkCellType    type,
 
424
                                    const gchar   *text,
 
425
                                    guint8         spacing,
 
426
                                    GdkPixmap     *pixmap,
 
427
                                    GdkBitmap     *mask);
 
428
static gint real_insert_row        (GtkCList      *clist,
 
429
                                    gint           row,
 
430
                                    gchar         *text[]);
 
431
static void real_remove_row        (GtkCList      *clist,
 
432
                                    gint           row);
 
433
static void real_clear             (GtkCList      *clist);
 
434
 
 
435
/* Sorting */
 
436
static gint default_compare        (GtkCList      *clist,
 
437
                                    gconstpointer  row1,
 
438
                                    gconstpointer  row2);
 
439
static void real_sort_list         (GtkCList      *clist);
 
440
static GList *gtk_clist_merge      (GtkCList      *clist,
 
441
                                    GList         *a,
 
442
                                    GList         *b);
 
443
static GList *gtk_clist_mergesort  (GtkCList      *clist,
 
444
                                    GList         *list,
 
445
                                    gint           num);
 
446
/* Misc */
 
447
static gboolean title_focus_in   (GtkCList *clist,
 
448
                                  gint      dir);
 
449
static gboolean title_focus_move (GtkCList *clist,
 
450
                                  gint      dir);
 
451
 
 
452
static void real_row_move             (GtkCList  *clist,
 
453
                                       gint       source_row,
 
454
                                       gint       dest_row);
 
455
static gint column_title_passive_func (GtkWidget *widget, 
 
456
                                       GdkEvent  *event,
 
457
                                       gpointer   data);
 
458
static void drag_dest_cell            (GtkCList         *clist,
 
459
                                       gint              x,
 
460
                                       gint              y,
 
461
                                       GtkCListDestInfo *dest_info);
 
462
 
 
463
 
 
464
 
 
465
static GtkContainerClass *parent_class = NULL;
 
466
static guint clist_signals[LAST_SIGNAL] = {0};
 
467
 
 
468
static const GtkTargetEntry clist_target_table = { "gtk-clist-drag-reorder", 0, 0};
 
469
 
 
470
GtkType
 
471
gtk_clist_get_type (void)
 
472
{
 
473
  static GtkType clist_type = 0;
 
474
 
 
475
  if (!clist_type)
 
476
    {
 
477
      static const GtkTypeInfo clist_info =
 
478
      {
 
479
        "GtkCList",
 
480
        sizeof (GtkCList),
 
481
        sizeof (GtkCListClass),
 
482
        (GtkClassInitFunc) gtk_clist_class_init,
 
483
        (GtkObjectInitFunc) gtk_clist_init,
 
484
        /* reserved_1 */ NULL,
 
485
        /* reserved_2 */ NULL,
 
486
        (GtkClassInitFunc) NULL,
 
487
      };
 
488
 
 
489
      I_("GtkCList");
 
490
      clist_type = gtk_type_unique (GTK_TYPE_CONTAINER, &clist_info);
 
491
    }
 
492
 
 
493
  return clist_type;
 
494
}
 
495
 
 
496
static void
 
497
gtk_clist_class_init (GtkCListClass *klass)
 
498
{
 
499
  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
 
500
  GtkObjectClass *object_class;
 
501
  GtkWidgetClass *widget_class;
 
502
  GtkContainerClass *container_class;
 
503
  GtkBindingSet *binding_set;
 
504
 
 
505
  gobject_class->constructor = gtk_clist_constructor;
 
506
 
 
507
  object_class = (GtkObjectClass *) klass;
 
508
  widget_class = (GtkWidgetClass *) klass;
 
509
  container_class = (GtkContainerClass *) klass;
 
510
 
 
511
  parent_class = gtk_type_class (GTK_TYPE_CONTAINER);
 
512
 
 
513
  gobject_class->finalize = gtk_clist_finalize;
 
514
  
 
515
  object_class->set_arg = gtk_clist_set_arg;
 
516
  object_class->get_arg = gtk_clist_get_arg;
 
517
  object_class->destroy = gtk_clist_destroy;
 
518
  
 
519
 
 
520
  widget_class->realize = gtk_clist_realize;
 
521
  widget_class->unrealize = gtk_clist_unrealize;
 
522
  widget_class->map = gtk_clist_map;
 
523
  widget_class->unmap = gtk_clist_unmap;
 
524
  widget_class->button_press_event = gtk_clist_button_press;
 
525
  widget_class->button_release_event = gtk_clist_button_release;
 
526
  widget_class->motion_notify_event = gtk_clist_motion;
 
527
  widget_class->expose_event = gtk_clist_expose;
 
528
  widget_class->size_request = gtk_clist_size_request;
 
529
  widget_class->size_allocate = gtk_clist_size_allocate;
 
530
  widget_class->focus_in_event = gtk_clist_focus_in;
 
531
  widget_class->focus_out_event = gtk_clist_focus_out;
 
532
  widget_class->style_set = gtk_clist_style_set;
 
533
  widget_class->drag_begin = gtk_clist_drag_begin;
 
534
  widget_class->drag_end = gtk_clist_drag_end;
 
535
  widget_class->drag_motion = gtk_clist_drag_motion;
 
536
  widget_class->drag_leave = gtk_clist_drag_leave;
 
537
  widget_class->drag_drop = gtk_clist_drag_drop;
 
538
  widget_class->drag_data_get = gtk_clist_drag_data_get;
 
539
  widget_class->drag_data_received = gtk_clist_drag_data_received;
 
540
  widget_class->focus = gtk_clist_focus;
 
541
  
 
542
  /* container_class->add = NULL; use the default GtkContainerClass warning */
 
543
  /* container_class->remove=NULL; use the default GtkContainerClass warning */
 
544
 
 
545
  container_class->forall = gtk_clist_forall;
 
546
  container_class->set_focus_child = gtk_clist_set_focus_child;
 
547
 
 
548
  klass->set_scroll_adjustments = gtk_clist_set_scroll_adjustments;
 
549
  klass->refresh = clist_refresh;
 
550
  klass->select_row = real_select_row;
 
551
  klass->unselect_row = real_unselect_row;
 
552
  klass->row_move = real_row_move;
 
553
  klass->undo_selection = real_undo_selection;
 
554
  klass->resync_selection = resync_selection;
 
555
  klass->selection_find = selection_find;
 
556
  klass->click_column = NULL;
 
557
  klass->resize_column = real_resize_column;
 
558
  klass->draw_row = draw_row;
 
559
  klass->draw_drag_highlight = draw_drag_highlight;
 
560
  klass->insert_row = real_insert_row;
 
561
  klass->remove_row = real_remove_row;
 
562
  klass->clear = real_clear;
 
563
  klass->sort_list = real_sort_list;
 
564
  klass->select_all = real_select_all;
 
565
  klass->unselect_all = real_unselect_all;
 
566
  klass->fake_unselect_all = fake_unselect_all;
 
567
  klass->scroll_horizontal = scroll_horizontal;
 
568
  klass->scroll_vertical = scroll_vertical;
 
569
  klass->extend_selection = extend_selection;
 
570
  klass->toggle_focus_row = toggle_focus_row;
 
571
  klass->toggle_add_mode = toggle_add_mode;
 
572
  klass->start_selection = start_selection;
 
573
  klass->end_selection = end_selection;
 
574
  klass->abort_column_resize = abort_column_resize;
 
575
  klass->set_cell_contents = set_cell_contents;
 
576
  klass->cell_size_request = cell_size_request;
 
577
 
 
578
  gtk_object_add_arg_type ("GtkCList::n-columns",
 
579
                           GTK_TYPE_UINT,
 
580
                           GTK_ARG_READWRITE | GTK_ARG_CONSTRUCT_ONLY | G_PARAM_STATIC_NAME,
 
581
                           ARG_N_COLUMNS);
 
582
  gtk_object_add_arg_type ("GtkCList::shadow-type",
 
583
                           GTK_TYPE_SHADOW_TYPE,
 
584
                           GTK_ARG_READWRITE | G_PARAM_STATIC_NAME,
 
585
                           ARG_SHADOW_TYPE);
 
586
  gtk_object_add_arg_type ("GtkCList::selection-mode",
 
587
                           GTK_TYPE_SELECTION_MODE,
 
588
                           GTK_ARG_READWRITE | G_PARAM_STATIC_NAME,
 
589
                           ARG_SELECTION_MODE);
 
590
  gtk_object_add_arg_type ("GtkCList::row-height",
 
591
                           GTK_TYPE_UINT,
 
592
                           GTK_ARG_READWRITE | G_PARAM_STATIC_NAME,
 
593
                           ARG_ROW_HEIGHT);
 
594
  gtk_object_add_arg_type ("GtkCList::reorderable",
 
595
                           GTK_TYPE_BOOL,
 
596
                           GTK_ARG_READWRITE | G_PARAM_STATIC_NAME,
 
597
                           ARG_REORDERABLE);
 
598
  gtk_object_add_arg_type ("GtkCList::titles-active",
 
599
                           GTK_TYPE_BOOL,
 
600
                           GTK_ARG_READWRITE | G_PARAM_STATIC_NAME,
 
601
                           ARG_TITLES_ACTIVE);
 
602
  gtk_object_add_arg_type ("GtkCList::use-drag-icons",
 
603
                           GTK_TYPE_BOOL,
 
604
                           GTK_ARG_READWRITE | G_PARAM_STATIC_NAME,
 
605
                           ARG_USE_DRAG_ICONS);
 
606
  gtk_object_add_arg_type ("GtkCList::sort-type",
 
607
                           GTK_TYPE_SORT_TYPE,
 
608
                           GTK_ARG_READWRITE | G_PARAM_STATIC_NAME,
 
609
                           ARG_SORT_TYPE);  
 
610
 
 
611
  widget_class->set_scroll_adjustments_signal =
 
612
    gtk_signal_new (I_("set_scroll_adjustments"),
 
613
                    GTK_RUN_LAST,
 
614
                    GTK_CLASS_TYPE (object_class),
 
615
                    GTK_SIGNAL_OFFSET (GtkCListClass, set_scroll_adjustments),
 
616
                    _gtk_marshal_VOID__OBJECT_OBJECT,
 
617
                    GTK_TYPE_NONE, 2, GTK_TYPE_ADJUSTMENT, GTK_TYPE_ADJUSTMENT);
 
618
 
 
619
  clist_signals[SELECT_ROW] =
 
620
    gtk_signal_new (I_("select_row"),
 
621
                    GTK_RUN_FIRST,
 
622
                    GTK_CLASS_TYPE (object_class),
 
623
                    GTK_SIGNAL_OFFSET (GtkCListClass, select_row),
 
624
                    _gtk_marshal_VOID__INT_INT_BOXED,
 
625
                    GTK_TYPE_NONE, 3,
 
626
                    GTK_TYPE_INT,
 
627
                    GTK_TYPE_INT,
 
628
                    GDK_TYPE_EVENT | G_SIGNAL_TYPE_STATIC_SCOPE);
 
629
  clist_signals[UNSELECT_ROW] =
 
630
    gtk_signal_new (I_("unselect_row"),
 
631
                    GTK_RUN_FIRST,
 
632
                    GTK_CLASS_TYPE (object_class),
 
633
                    GTK_SIGNAL_OFFSET (GtkCListClass, unselect_row),
 
634
                    _gtk_marshal_VOID__INT_INT_BOXED,
 
635
                    GTK_TYPE_NONE, 3, GTK_TYPE_INT,
 
636
                    GTK_TYPE_INT, GDK_TYPE_EVENT);
 
637
  clist_signals[ROW_MOVE] =
 
638
    gtk_signal_new (I_("row_move"),
 
639
                    GTK_RUN_LAST,
 
640
                    GTK_CLASS_TYPE (object_class),
 
641
                    GTK_SIGNAL_OFFSET (GtkCListClass, row_move),
 
642
                    _gtk_marshal_VOID__INT_INT,
 
643
                    GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
 
644
  clist_signals[CLICK_COLUMN] =
 
645
    gtk_signal_new (I_("click_column"),
 
646
                    GTK_RUN_FIRST,
 
647
                    GTK_CLASS_TYPE (object_class),
 
648
                    GTK_SIGNAL_OFFSET (GtkCListClass, click_column),
 
649
                    _gtk_marshal_VOID__INT,
 
650
                    GTK_TYPE_NONE, 1, GTK_TYPE_INT);
 
651
  clist_signals[RESIZE_COLUMN] =
 
652
    gtk_signal_new (I_("resize_column"),
 
653
                    GTK_RUN_LAST,
 
654
                    GTK_CLASS_TYPE (object_class),
 
655
                    GTK_SIGNAL_OFFSET (GtkCListClass, resize_column),
 
656
                    _gtk_marshal_VOID__INT_INT,
 
657
                    GTK_TYPE_NONE, 2, GTK_TYPE_INT, GTK_TYPE_INT);
 
658
 
 
659
  clist_signals[TOGGLE_FOCUS_ROW] =
 
660
    gtk_signal_new (I_("toggle_focus_row"),
 
661
                    GTK_RUN_LAST | GTK_RUN_ACTION,
 
662
                    GTK_CLASS_TYPE (object_class),
 
663
                    GTK_SIGNAL_OFFSET (GtkCListClass, toggle_focus_row),
 
664
                    _gtk_marshal_VOID__VOID,
 
665
                    GTK_TYPE_NONE, 0);
 
666
  clist_signals[SELECT_ALL] =
 
667
    gtk_signal_new (I_("select_all"),
 
668
                    GTK_RUN_LAST | GTK_RUN_ACTION,
 
669
                    GTK_CLASS_TYPE (object_class),
 
670
                    GTK_SIGNAL_OFFSET (GtkCListClass, select_all),
 
671
                    _gtk_marshal_VOID__VOID,
 
672
                    GTK_TYPE_NONE, 0);
 
673
  clist_signals[UNSELECT_ALL] =
 
674
    gtk_signal_new (I_("unselect_all"),
 
675
                    GTK_RUN_LAST | GTK_RUN_ACTION,
 
676
                    GTK_CLASS_TYPE (object_class),
 
677
                    GTK_SIGNAL_OFFSET (GtkCListClass, unselect_all),
 
678
                    _gtk_marshal_VOID__VOID,
 
679
                    GTK_TYPE_NONE, 0);
 
680
  clist_signals[UNDO_SELECTION] =
 
681
    gtk_signal_new (I_("undo_selection"),
 
682
                    GTK_RUN_LAST | GTK_RUN_ACTION,
 
683
                    GTK_CLASS_TYPE (object_class),
 
684
                    GTK_SIGNAL_OFFSET (GtkCListClass, undo_selection),
 
685
                    _gtk_marshal_VOID__VOID,
 
686
                    GTK_TYPE_NONE, 0);
 
687
  clist_signals[START_SELECTION] =
 
688
    gtk_signal_new (I_("start_selection"),
 
689
                    GTK_RUN_LAST | GTK_RUN_ACTION,
 
690
                    GTK_CLASS_TYPE (object_class),
 
691
                    GTK_SIGNAL_OFFSET (GtkCListClass, start_selection),
 
692
                    _gtk_marshal_VOID__VOID,
 
693
                    GTK_TYPE_NONE, 0);
 
694
  clist_signals[END_SELECTION] =
 
695
    gtk_signal_new (I_("end_selection"),
 
696
                    GTK_RUN_LAST | GTK_RUN_ACTION,
 
697
                    GTK_CLASS_TYPE (object_class),
 
698
                    GTK_SIGNAL_OFFSET (GtkCListClass, end_selection),
 
699
                    _gtk_marshal_VOID__VOID,
 
700
                    GTK_TYPE_NONE, 0);
 
701
  clist_signals[TOGGLE_ADD_MODE] =
 
702
    gtk_signal_new (I_("toggle_add_mode"),
 
703
                    GTK_RUN_LAST | GTK_RUN_ACTION,
 
704
                    GTK_CLASS_TYPE (object_class),
 
705
                    GTK_SIGNAL_OFFSET (GtkCListClass, toggle_add_mode),
 
706
                    _gtk_marshal_VOID__VOID,
 
707
                    GTK_TYPE_NONE, 0);
 
708
  clist_signals[EXTEND_SELECTION] =
 
709
    gtk_signal_new (I_("extend_selection"),
 
710
                    GTK_RUN_LAST | GTK_RUN_ACTION,
 
711
                    GTK_CLASS_TYPE (object_class),
 
712
                    GTK_SIGNAL_OFFSET (GtkCListClass, extend_selection),
 
713
                    _gtk_marshal_VOID__ENUM_FLOAT_BOOLEAN,
 
714
                    GTK_TYPE_NONE, 3,
 
715
                    GTK_TYPE_SCROLL_TYPE, GTK_TYPE_FLOAT, GTK_TYPE_BOOL);
 
716
  clist_signals[SCROLL_VERTICAL] =
 
717
    gtk_signal_new (I_("scroll_vertical"),
 
718
                    GTK_RUN_LAST | GTK_RUN_ACTION,
 
719
                    GTK_CLASS_TYPE (object_class),
 
720
                    GTK_SIGNAL_OFFSET (GtkCListClass, scroll_vertical),
 
721
                    _gtk_marshal_VOID__ENUM_FLOAT,
 
722
                    GTK_TYPE_NONE, 2, GTK_TYPE_SCROLL_TYPE, GTK_TYPE_FLOAT);
 
723
  clist_signals[SCROLL_HORIZONTAL] =
 
724
    gtk_signal_new (I_("scroll_horizontal"),
 
725
                    GTK_RUN_LAST | GTK_RUN_ACTION,
 
726
                    GTK_CLASS_TYPE (object_class),
 
727
                    GTK_SIGNAL_OFFSET (GtkCListClass, scroll_horizontal),
 
728
                    _gtk_marshal_VOID__ENUM_FLOAT,
 
729
                    GTK_TYPE_NONE, 2, GTK_TYPE_SCROLL_TYPE, GTK_TYPE_FLOAT);
 
730
  clist_signals[ABORT_COLUMN_RESIZE] =
 
731
    gtk_signal_new (I_("abort_column_resize"),
 
732
                    GTK_RUN_LAST | GTK_RUN_ACTION,
 
733
                    GTK_CLASS_TYPE (object_class),
 
734
                    GTK_SIGNAL_OFFSET (GtkCListClass, abort_column_resize),
 
735
                    _gtk_marshal_VOID__VOID,
 
736
                    GTK_TYPE_NONE, 0);
 
737
 
 
738
  binding_set = gtk_binding_set_by_class (klass);
 
739
  gtk_binding_entry_add_signal (binding_set, GDK_Up, 0,
 
740
                                "scroll_vertical", 2,
 
741
                                GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
 
742
                                GTK_TYPE_FLOAT, 0.0);
 
743
  gtk_binding_entry_add_signal (binding_set, GDK_KP_Up, 0,
 
744
                                "scroll_vertical", 2,
 
745
                                GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
 
746
                                GTK_TYPE_FLOAT, 0.0);
 
747
  gtk_binding_entry_add_signal (binding_set, GDK_Down, 0,
 
748
                                "scroll_vertical", 2,
 
749
                                GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
 
750
                                GTK_TYPE_FLOAT, 0.0);
 
751
  gtk_binding_entry_add_signal (binding_set, GDK_KP_Down, 0,
 
752
                                "scroll_vertical", 2,
 
753
                                GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
 
754
                                GTK_TYPE_FLOAT, 0.0);
 
755
  gtk_binding_entry_add_signal (binding_set, GDK_Page_Up, 0,
 
756
                                "scroll_vertical", 2,
 
757
                                GTK_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
 
758
                                GTK_TYPE_FLOAT, 0.0);
 
759
  gtk_binding_entry_add_signal (binding_set, GDK_KP_Page_Up, 0,
 
760
                                "scroll_vertical", 2,
 
761
                                GTK_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
 
762
                                GTK_TYPE_FLOAT, 0.0);
 
763
  gtk_binding_entry_add_signal (binding_set, GDK_Page_Down, 0,
 
764
                                "scroll_vertical", 2,
 
765
                                GTK_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
 
766
                                GTK_TYPE_FLOAT, 0.0);
 
767
  gtk_binding_entry_add_signal (binding_set, GDK_KP_Page_Down, 0,
 
768
                                "scroll_vertical", 2,
 
769
                                GTK_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
 
770
                                GTK_TYPE_FLOAT, 0.0);
 
771
  gtk_binding_entry_add_signal (binding_set, GDK_Home, GDK_CONTROL_MASK,
 
772
                                "scroll_vertical", 2,
 
773
                                GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
 
774
                                GTK_TYPE_FLOAT, 0.0);
 
775
  gtk_binding_entry_add_signal (binding_set, GDK_KP_Home, GDK_CONTROL_MASK,
 
776
                                "scroll_vertical", 2,
 
777
                                GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
 
778
                                GTK_TYPE_FLOAT, 0.0);
 
779
  gtk_binding_entry_add_signal (binding_set, GDK_End, GDK_CONTROL_MASK,
 
780
                                "scroll_vertical", 2,
 
781
                                GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
 
782
                                GTK_TYPE_FLOAT, 1.0);
 
783
  gtk_binding_entry_add_signal (binding_set, GDK_KP_End, GDK_CONTROL_MASK,
 
784
                                "scroll_vertical", 2,
 
785
                                GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
 
786
                                GTK_TYPE_FLOAT, 1.0);
 
787
  
 
788
  gtk_binding_entry_add_signal (binding_set, GDK_Up, GDK_SHIFT_MASK,
 
789
                                "extend_selection", 3,
 
790
                                GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
 
791
                                GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
 
792
  gtk_binding_entry_add_signal (binding_set, GDK_KP_Up, GDK_SHIFT_MASK,
 
793
                                "extend_selection", 3,
 
794
                                GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
 
795
                                GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
 
796
  gtk_binding_entry_add_signal (binding_set, GDK_Down, GDK_SHIFT_MASK,
 
797
                                "extend_selection", 3,
 
798
                                GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
 
799
                                GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
 
800
  gtk_binding_entry_add_signal (binding_set, GDK_KP_Down, GDK_SHIFT_MASK,
 
801
                                "extend_selection", 3,
 
802
                                GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
 
803
                                GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
 
804
  gtk_binding_entry_add_signal (binding_set, GDK_Page_Up, GDK_SHIFT_MASK,
 
805
                                "extend_selection", 3,
 
806
                                GTK_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
 
807
                                GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
 
808
  gtk_binding_entry_add_signal (binding_set, GDK_KP_Page_Up, GDK_SHIFT_MASK,
 
809
                                "extend_selection", 3,
 
810
                                GTK_TYPE_ENUM, GTK_SCROLL_PAGE_BACKWARD,
 
811
                                GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
 
812
  gtk_binding_entry_add_signal (binding_set, GDK_Page_Down, GDK_SHIFT_MASK,
 
813
                                "extend_selection", 3,
 
814
                                GTK_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
 
815
                                GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
 
816
  gtk_binding_entry_add_signal (binding_set, GDK_KP_Page_Down, GDK_SHIFT_MASK,
 
817
                                "extend_selection", 3,
 
818
                                GTK_TYPE_ENUM, GTK_SCROLL_PAGE_FORWARD,
 
819
                                GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
 
820
  gtk_binding_entry_add_signal (binding_set, GDK_Home,
 
821
                                GDK_SHIFT_MASK | GDK_CONTROL_MASK,
 
822
                                "extend_selection", 3,
 
823
                                GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
 
824
                                GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
 
825
  gtk_binding_entry_add_signal (binding_set, GDK_KP_Home,
 
826
                                GDK_SHIFT_MASK | GDK_CONTROL_MASK,
 
827
                                "extend_selection", 3,
 
828
                                GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
 
829
                                GTK_TYPE_FLOAT, 0.0, GTK_TYPE_BOOL, TRUE);
 
830
  gtk_binding_entry_add_signal (binding_set, GDK_End,
 
831
                                GDK_SHIFT_MASK | GDK_CONTROL_MASK,
 
832
                                "extend_selection", 3,
 
833
                                GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
 
834
                                GTK_TYPE_FLOAT, 1.0, GTK_TYPE_BOOL, TRUE);
 
835
  gtk_binding_entry_add_signal (binding_set, GDK_KP_End,
 
836
                                GDK_SHIFT_MASK | GDK_CONTROL_MASK,
 
837
                                "extend_selection", 3,
 
838
                                GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
 
839
                                GTK_TYPE_FLOAT, 1.0, GTK_TYPE_BOOL, TRUE);
 
840
 
 
841
  
 
842
  gtk_binding_entry_add_signal (binding_set, GDK_Left, 0,
 
843
                                "scroll_horizontal", 2,
 
844
                                GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
 
845
                                GTK_TYPE_FLOAT, 0.0);
 
846
  gtk_binding_entry_add_signal (binding_set, GDK_KP_Left, 0,
 
847
                                "scroll_horizontal", 2,
 
848
                                GTK_TYPE_ENUM, GTK_SCROLL_STEP_BACKWARD,
 
849
                                GTK_TYPE_FLOAT, 0.0);
 
850
  
 
851
  gtk_binding_entry_add_signal (binding_set, GDK_Right, 0,
 
852
                                "scroll_horizontal", 2,
 
853
                                GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
 
854
                                GTK_TYPE_FLOAT, 0.0);
 
855
  gtk_binding_entry_add_signal (binding_set, GDK_KP_Right, 0,
 
856
                                "scroll_horizontal", 2,
 
857
                                GTK_TYPE_ENUM, GTK_SCROLL_STEP_FORWARD,
 
858
                                GTK_TYPE_FLOAT, 0.0);
 
859
 
 
860
  gtk_binding_entry_add_signal (binding_set, GDK_Home, 0,
 
861
                                "scroll_horizontal", 2,
 
862
                                GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
 
863
                                GTK_TYPE_FLOAT, 0.0);
 
864
  gtk_binding_entry_add_signal (binding_set, GDK_KP_Home, 0,
 
865
                                "scroll_horizontal", 2,
 
866
                                GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
 
867
                                GTK_TYPE_FLOAT, 0.0);
 
868
  
 
869
  gtk_binding_entry_add_signal (binding_set, GDK_End, 0,
 
870
                                "scroll_horizontal", 2,
 
871
                                GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
 
872
                                GTK_TYPE_FLOAT, 1.0);
 
873
 
 
874
  gtk_binding_entry_add_signal (binding_set, GDK_KP_End, 0,
 
875
                                "scroll_horizontal", 2,
 
876
                                GTK_TYPE_ENUM, GTK_SCROLL_JUMP,
 
877
                                GTK_TYPE_FLOAT, 1.0);
 
878
  
 
879
  gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0,
 
880
                                "undo_selection", 0);
 
881
  gtk_binding_entry_add_signal (binding_set, GDK_Escape, 0,
 
882
                                "abort_column_resize", 0);
 
883
  gtk_binding_entry_add_signal (binding_set, GDK_space, 0,
 
884
                                "toggle_focus_row", 0);
 
885
  gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, 0,
 
886
                                "toggle_focus_row", 0);  
 
887
  gtk_binding_entry_add_signal (binding_set, GDK_space, GDK_CONTROL_MASK,
 
888
                                "toggle_add_mode", 0);
 
889
  gtk_binding_entry_add_signal (binding_set, GDK_KP_Space, GDK_CONTROL_MASK,
 
890
                                "toggle_add_mode", 0);
 
891
  gtk_binding_entry_add_signal (binding_set, GDK_slash, GDK_CONTROL_MASK,
 
892
                                "select_all", 0);
 
893
  gtk_binding_entry_add_signal (binding_set, GDK_KP_Divide, GDK_CONTROL_MASK,
 
894
                                "select_all", 0);
 
895
  gtk_binding_entry_add_signal (binding_set, '\\', GDK_CONTROL_MASK,
 
896
                                "unselect_all", 0);
 
897
  gtk_binding_entry_add_signal (binding_set, GDK_Shift_L,
 
898
                                GDK_RELEASE_MASK | GDK_SHIFT_MASK,
 
899
                                "end_selection", 0);
 
900
  gtk_binding_entry_add_signal (binding_set, GDK_Shift_R,
 
901
                                GDK_RELEASE_MASK | GDK_SHIFT_MASK,
 
902
                                "end_selection", 0);
 
903
  gtk_binding_entry_add_signal (binding_set, GDK_Shift_L,
 
904
                                GDK_RELEASE_MASK | GDK_SHIFT_MASK |
 
905
                                GDK_CONTROL_MASK,
 
906
                                "end_selection", 0);
 
907
  gtk_binding_entry_add_signal (binding_set, GDK_Shift_R,
 
908
                                GDK_RELEASE_MASK | GDK_SHIFT_MASK |
 
909
                                GDK_CONTROL_MASK,
 
910
                                "end_selection", 0);
 
911
}
 
912
 
 
913
static void
 
914
gtk_clist_set_arg (GtkObject      *object,
 
915
                   GtkArg         *arg,
 
916
                   guint           arg_id)
 
917
{
 
918
  GtkCList *clist;
 
919
 
 
920
  clist = GTK_CLIST (object);
 
921
 
 
922
  switch (arg_id)
 
923
    {
 
924
    case ARG_N_COLUMNS: /* only set at construction time */
 
925
      clist->columns = MAX (1, GTK_VALUE_UINT (*arg));
 
926
      break;
 
927
    case ARG_SHADOW_TYPE:
 
928
      gtk_clist_set_shadow_type (clist, GTK_VALUE_ENUM (*arg));
 
929
      break;
 
930
    case ARG_SELECTION_MODE:
 
931
      gtk_clist_set_selection_mode (clist, GTK_VALUE_ENUM (*arg));
 
932
      break;
 
933
    case ARG_ROW_HEIGHT:
 
934
      gtk_clist_set_row_height (clist, GTK_VALUE_UINT (*arg));
 
935
      break;
 
936
    case ARG_REORDERABLE:
 
937
      gtk_clist_set_reorderable (clist, GTK_VALUE_BOOL (*arg));
 
938
      break;
 
939
    case ARG_TITLES_ACTIVE:
 
940
      if (GTK_VALUE_BOOL (*arg))
 
941
        gtk_clist_column_titles_active (clist);
 
942
      else
 
943
        gtk_clist_column_titles_passive (clist);
 
944
      break;
 
945
    case ARG_USE_DRAG_ICONS:
 
946
      gtk_clist_set_use_drag_icons (clist, GTK_VALUE_BOOL (*arg));
 
947
      break;
 
948
    case ARG_SORT_TYPE:
 
949
      gtk_clist_set_sort_type (clist, GTK_VALUE_ENUM (*arg));
 
950
      break;
 
951
    }
 
952
}
 
953
 
 
954
static void
 
955
gtk_clist_get_arg (GtkObject      *object,
 
956
                   GtkArg         *arg,
 
957
                   guint           arg_id)
 
958
{
 
959
  GtkCList *clist;
 
960
 
 
961
  clist = GTK_CLIST (object);
 
962
 
 
963
  switch (arg_id)
 
964
    {
 
965
      guint i;
 
966
 
 
967
    case ARG_N_COLUMNS:
 
968
      GTK_VALUE_UINT (*arg) = clist->columns;
 
969
      break;
 
970
    case ARG_SHADOW_TYPE:
 
971
      GTK_VALUE_ENUM (*arg) = clist->shadow_type;
 
972
      break;
 
973
    case ARG_SELECTION_MODE:
 
974
      GTK_VALUE_ENUM (*arg) = clist->selection_mode;
 
975
      break;
 
976
    case ARG_ROW_HEIGHT:
 
977
      GTK_VALUE_UINT (*arg) = GTK_CLIST_ROW_HEIGHT_SET(clist) ? clist->row_height : 0;
 
978
      break;
 
979
    case ARG_REORDERABLE:
 
980
      GTK_VALUE_BOOL (*arg) = GTK_CLIST_REORDERABLE (clist);
 
981
      break;
 
982
    case ARG_TITLES_ACTIVE:
 
983
      GTK_VALUE_BOOL (*arg) = TRUE;
 
984
      for (i = 0; i < clist->columns; i++)
 
985
        if (clist->column[i].button &&
 
986
            !GTK_WIDGET_SENSITIVE (clist->column[i].button))
 
987
          {
 
988
            GTK_VALUE_BOOL (*arg) = FALSE;
 
989
            break;
 
990
          }
 
991
      break;
 
992
    case ARG_USE_DRAG_ICONS:
 
993
      GTK_VALUE_BOOL (*arg) = GTK_CLIST_USE_DRAG_ICONS (clist);
 
994
      break;
 
995
    case ARG_SORT_TYPE:
 
996
      GTK_VALUE_ENUM (*arg) = clist->sort_type;
 
997
      break;
 
998
    default:
 
999
      arg->type = GTK_TYPE_INVALID;
 
1000
      break;
 
1001
    }
 
1002
}
 
1003
 
 
1004
static void
 
1005
gtk_clist_init (GtkCList *clist)
 
1006
{
 
1007
  clist->flags = 0;
 
1008
 
 
1009
  GTK_WIDGET_UNSET_FLAGS (clist, GTK_NO_WINDOW);
 
1010
  GTK_WIDGET_SET_FLAGS (clist, GTK_CAN_FOCUS);
 
1011
  GTK_CLIST_SET_FLAG (clist, CLIST_DRAW_DRAG_LINE);
 
1012
  GTK_CLIST_SET_FLAG (clist, CLIST_USE_DRAG_ICONS);
 
1013
 
 
1014
  clist->freeze_count = 0;
 
1015
 
 
1016
  clist->rows = 0;
 
1017
  clist->row_height = 0;
 
1018
  clist->row_list = NULL;
 
1019
  clist->row_list_end = NULL;
 
1020
 
 
1021
  clist->columns = 0;
 
1022
 
 
1023
  clist->title_window = NULL;
 
1024
  clist->column_title_area.x = 0;
 
1025
  clist->column_title_area.y = 0;
 
1026
  clist->column_title_area.width = 1;
 
1027
  clist->column_title_area.height = 1;
 
1028
 
 
1029
  clist->clist_window = NULL;
 
1030
  clist->clist_window_width = 1;
 
1031
  clist->clist_window_height = 1;
 
1032
 
 
1033
  clist->hoffset = 0;
 
1034
  clist->voffset = 0;
 
1035
 
 
1036
  clist->shadow_type = GTK_SHADOW_IN;
 
1037
  clist->vadjustment = NULL;
 
1038
  clist->hadjustment = NULL;
 
1039
 
 
1040
  clist->button_actions[0] = GTK_BUTTON_SELECTS | GTK_BUTTON_DRAGS;
 
1041
  clist->button_actions[1] = GTK_BUTTON_IGNORED;
 
1042
  clist->button_actions[2] = GTK_BUTTON_IGNORED;
 
1043
  clist->button_actions[3] = GTK_BUTTON_IGNORED;
 
1044
  clist->button_actions[4] = GTK_BUTTON_IGNORED;
 
1045
 
 
1046
  clist->cursor_drag = NULL;
 
1047
  clist->xor_gc = NULL;
 
1048
  clist->fg_gc = NULL;
 
1049
  clist->bg_gc = NULL;
 
1050
  clist->x_drag = 0;
 
1051
 
 
1052
  clist->selection_mode = GTK_SELECTION_SINGLE;
 
1053
  clist->selection = NULL;
 
1054
  clist->selection_end = NULL;
 
1055
  clist->undo_selection = NULL;
 
1056
  clist->undo_unselection = NULL;
 
1057
 
 
1058
  clist->focus_row = -1;
 
1059
  clist->focus_header_column = -1;
 
1060
  clist->undo_anchor = -1;
 
1061
 
 
1062
  clist->anchor = -1;
 
1063
  clist->anchor_state = GTK_STATE_SELECTED;
 
1064
  clist->drag_pos = -1;
 
1065
  clist->htimer = 0;
 
1066
  clist->vtimer = 0;
 
1067
 
 
1068
  clist->click_cell.row = -1;
 
1069
  clist->click_cell.column = -1;
 
1070
 
 
1071
  clist->compare = default_compare;
 
1072
  clist->sort_type = GTK_SORT_ASCENDING;
 
1073
  clist->sort_column = 0;
 
1074
 
 
1075
  clist->drag_highlight_row = -1;
 
1076
}
 
1077
 
 
1078
/* Constructor */
 
1079
static GObject*
 
1080
gtk_clist_constructor (GType                  type,
 
1081
                       guint                  n_construct_properties,
 
1082
                       GObjectConstructParam *construct_properties)
 
1083
{
 
1084
  GObject *object = G_OBJECT_CLASS (parent_class)->constructor (type,
 
1085
                                                                n_construct_properties,
 
1086
                                                                construct_properties);
 
1087
  GtkCList *clist = GTK_CLIST (object);
 
1088
  
 
1089
  /* allocate memory for columns */
 
1090
  clist->column = columns_new (clist);
 
1091
  
 
1092
  /* there needs to be at least one column button 
 
1093
   * because there is alot of code that will break if it
 
1094
   * isn't there
 
1095
   */
 
1096
  column_button_create (clist, 0);
 
1097
  
 
1098
  return object;
 
1099
}
 
1100
 
 
1101
/* GTKCLIST PUBLIC INTERFACE
 
1102
 *   gtk_clist_new
 
1103
 *   gtk_clist_new_with_titles
 
1104
 *   gtk_clist_set_hadjustment
 
1105
 *   gtk_clist_set_vadjustment
 
1106
 *   gtk_clist_get_hadjustment
 
1107
 *   gtk_clist_get_vadjustment
 
1108
 *   gtk_clist_set_shadow_type
 
1109
 *   gtk_clist_set_selection_mode
 
1110
 *   gtk_clist_freeze
 
1111
 *   gtk_clist_thaw
 
1112
 */
 
1113
GtkWidget*
 
1114
gtk_clist_new (gint columns)
 
1115
{
 
1116
  return gtk_clist_new_with_titles (columns, NULL);
 
1117
}
 
1118
 
 
1119
GtkWidget*
 
1120
gtk_clist_new_with_titles (gint   columns,
 
1121
                           gchar *titles[])
 
1122
{
 
1123
  GtkCList *clist;
 
1124
 
 
1125
  clist = g_object_new (GTK_TYPE_CLIST,
 
1126
                        "n_columns", columns,
 
1127
                        NULL);
 
1128
  if (titles)
 
1129
    {
 
1130
      guint i;
 
1131
 
 
1132
      for (i = 0; i < clist->columns; i++)
 
1133
        gtk_clist_set_column_title (clist, i, titles[i]);
 
1134
      gtk_clist_column_titles_show (clist);
 
1135
    }
 
1136
  else
 
1137
    gtk_clist_column_titles_hide (clist);
 
1138
  
 
1139
  return GTK_WIDGET (clist);
 
1140
}
 
1141
 
 
1142
void
 
1143
gtk_clist_set_hadjustment (GtkCList      *clist,
 
1144
                           GtkAdjustment *adjustment)
 
1145
{
 
1146
  GtkAdjustment *old_adjustment;
 
1147
 
 
1148
  g_return_if_fail (GTK_IS_CLIST (clist));
 
1149
  if (adjustment)
 
1150
    g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
 
1151
  
 
1152
  if (clist->hadjustment == adjustment)
 
1153
    return;
 
1154
  
 
1155
  old_adjustment = clist->hadjustment;
 
1156
 
 
1157
  if (clist->hadjustment)
 
1158
    {
 
1159
      gtk_signal_disconnect_by_data (GTK_OBJECT (clist->hadjustment), clist);
 
1160
      gtk_object_unref (GTK_OBJECT (clist->hadjustment));
 
1161
    }
 
1162
 
 
1163
  clist->hadjustment = adjustment;
 
1164
 
 
1165
  if (clist->hadjustment)
 
1166
    {
 
1167
      g_object_ref_sink (clist->hadjustment);
 
1168
 
 
1169
      gtk_signal_connect (GTK_OBJECT (clist->hadjustment), "changed",
 
1170
                          (GtkSignalFunc) hadjustment_changed,
 
1171
                          (gpointer) clist);
 
1172
      gtk_signal_connect (GTK_OBJECT (clist->hadjustment), "value_changed",
 
1173
                          (GtkSignalFunc) hadjustment_value_changed,
 
1174
                          (gpointer) clist);
 
1175
    }
 
1176
 
 
1177
  if (!clist->hadjustment || !old_adjustment)
 
1178
    gtk_widget_queue_resize (GTK_WIDGET (clist));
 
1179
}
 
1180
 
 
1181
GtkAdjustment *
 
1182
gtk_clist_get_hadjustment (GtkCList *clist)
 
1183
{
 
1184
  g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
 
1185
 
 
1186
  return clist->hadjustment;
 
1187
}
 
1188
 
 
1189
void
 
1190
gtk_clist_set_vadjustment (GtkCList      *clist,
 
1191
                           GtkAdjustment *adjustment)
 
1192
{
 
1193
  GtkAdjustment *old_adjustment;
 
1194
 
 
1195
  g_return_if_fail (GTK_IS_CLIST (clist));
 
1196
  if (adjustment)
 
1197
    g_return_if_fail (GTK_IS_ADJUSTMENT (adjustment));
 
1198
 
 
1199
  if (clist->vadjustment == adjustment)
 
1200
    return;
 
1201
  
 
1202
  old_adjustment = clist->vadjustment;
 
1203
 
 
1204
  if (clist->vadjustment)
 
1205
    {
 
1206
      gtk_signal_disconnect_by_data (GTK_OBJECT (clist->vadjustment), clist);
 
1207
      gtk_object_unref (GTK_OBJECT (clist->vadjustment));
 
1208
    }
 
1209
 
 
1210
  clist->vadjustment = adjustment;
 
1211
 
 
1212
  if (clist->vadjustment)
 
1213
    {
 
1214
      g_object_ref_sink (clist->vadjustment);
 
1215
 
 
1216
      gtk_signal_connect (GTK_OBJECT (clist->vadjustment), "changed",
 
1217
                          (GtkSignalFunc) vadjustment_changed,
 
1218
                          (gpointer) clist);
 
1219
      gtk_signal_connect (GTK_OBJECT (clist->vadjustment), "value_changed",
 
1220
                          (GtkSignalFunc) vadjustment_value_changed,
 
1221
                          (gpointer) clist);
 
1222
    }
 
1223
 
 
1224
  if (!clist->vadjustment || !old_adjustment)
 
1225
    gtk_widget_queue_resize (GTK_WIDGET (clist));
 
1226
}
 
1227
 
 
1228
GtkAdjustment *
 
1229
gtk_clist_get_vadjustment (GtkCList *clist)
 
1230
{
 
1231
  g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
 
1232
 
 
1233
  return clist->vadjustment;
 
1234
}
 
1235
 
 
1236
static void
 
1237
gtk_clist_set_scroll_adjustments (GtkCList      *clist,
 
1238
                                  GtkAdjustment *hadjustment,
 
1239
                                  GtkAdjustment *vadjustment)
 
1240
{
 
1241
  if (clist->hadjustment != hadjustment)
 
1242
    gtk_clist_set_hadjustment (clist, hadjustment);
 
1243
  if (clist->vadjustment != vadjustment)
 
1244
    gtk_clist_set_vadjustment (clist, vadjustment);
 
1245
}
 
1246
 
 
1247
void
 
1248
gtk_clist_set_shadow_type (GtkCList      *clist,
 
1249
                           GtkShadowType  type)
 
1250
{
 
1251
  g_return_if_fail (GTK_IS_CLIST (clist));
 
1252
 
 
1253
  clist->shadow_type = type;
 
1254
 
 
1255
  if (GTK_WIDGET_VISIBLE (clist))
 
1256
    gtk_widget_queue_resize (GTK_WIDGET (clist));
 
1257
}
 
1258
 
 
1259
void
 
1260
gtk_clist_set_selection_mode (GtkCList         *clist,
 
1261
                              GtkSelectionMode  mode)
 
1262
{
 
1263
  g_return_if_fail (GTK_IS_CLIST (clist));
 
1264
  g_return_if_fail (mode != GTK_SELECTION_NONE);
 
1265
 
 
1266
  if (mode == clist->selection_mode)
 
1267
    return;
 
1268
 
 
1269
  clist->selection_mode = mode;
 
1270
  clist->anchor = -1;
 
1271
  clist->anchor_state = GTK_STATE_SELECTED;
 
1272
  clist->drag_pos = -1;
 
1273
  clist->undo_anchor = clist->focus_row;
 
1274
 
 
1275
  g_list_free (clist->undo_selection);
 
1276
  g_list_free (clist->undo_unselection);
 
1277
  clist->undo_selection = NULL;
 
1278
  clist->undo_unselection = NULL;
 
1279
 
 
1280
  switch (mode)
 
1281
    {
 
1282
    case GTK_SELECTION_MULTIPLE:
 
1283
      return;
 
1284
    case GTK_SELECTION_BROWSE:
 
1285
    case GTK_SELECTION_SINGLE:
 
1286
      gtk_clist_unselect_all (clist);
 
1287
      break;
 
1288
    default:
 
1289
      /* Someone set it by hand */
 
1290
      g_assert_not_reached ();
 
1291
    }
 
1292
}
 
1293
 
 
1294
void
 
1295
gtk_clist_freeze (GtkCList *clist)
 
1296
{
 
1297
  g_return_if_fail (GTK_IS_CLIST (clist));
 
1298
 
 
1299
  clist->freeze_count++;
 
1300
}
 
1301
 
 
1302
void
 
1303
gtk_clist_thaw (GtkCList *clist)
 
1304
{
 
1305
  g_return_if_fail (GTK_IS_CLIST (clist));
 
1306
 
 
1307
  if (clist->freeze_count)
 
1308
    {
 
1309
      clist->freeze_count--;
 
1310
      CLIST_REFRESH (clist);
 
1311
    }
 
1312
}
 
1313
 
 
1314
/* PUBLIC COLUMN FUNCTIONS
 
1315
 *   gtk_clist_column_titles_show
 
1316
 *   gtk_clist_column_titles_hide
 
1317
 *   gtk_clist_column_title_active
 
1318
 *   gtk_clist_column_title_passive
 
1319
 *   gtk_clist_column_titles_active
 
1320
 *   gtk_clist_column_titles_passive
 
1321
 *   gtk_clist_set_column_title
 
1322
 *   gtk_clist_get_column_title
 
1323
 *   gtk_clist_set_column_widget
 
1324
 *   gtk_clist_set_column_justification
 
1325
 *   gtk_clist_set_column_visibility
 
1326
 *   gtk_clist_set_column_resizeable
 
1327
 *   gtk_clist_set_column_auto_resize
 
1328
 *   gtk_clist_optimal_column_width
 
1329
 *   gtk_clist_set_column_width
 
1330
 *   gtk_clist_set_column_min_width
 
1331
 *   gtk_clist_set_column_max_width
 
1332
 */
 
1333
void
 
1334
gtk_clist_column_titles_show (GtkCList *clist)
 
1335
{
 
1336
  g_return_if_fail (GTK_IS_CLIST (clist));
 
1337
 
 
1338
  if (!GTK_CLIST_SHOW_TITLES(clist))
 
1339
    {
 
1340
      GTK_CLIST_SET_FLAG (clist, CLIST_SHOW_TITLES);
 
1341
      if (clist->title_window)
 
1342
        gdk_window_show (clist->title_window);
 
1343
      gtk_widget_queue_resize (GTK_WIDGET (clist));
 
1344
    }
 
1345
}
 
1346
 
 
1347
void 
 
1348
gtk_clist_column_titles_hide (GtkCList *clist)
 
1349
{
 
1350
  g_return_if_fail (GTK_IS_CLIST (clist));
 
1351
 
 
1352
  if (GTK_CLIST_SHOW_TITLES(clist))
 
1353
    {
 
1354
      GTK_CLIST_UNSET_FLAG (clist, CLIST_SHOW_TITLES);
 
1355
      if (clist->title_window)
 
1356
        gdk_window_hide (clist->title_window);
 
1357
      gtk_widget_queue_resize (GTK_WIDGET (clist));
 
1358
    }
 
1359
}
 
1360
 
 
1361
void
 
1362
gtk_clist_column_title_active (GtkCList *clist,
 
1363
                               gint      column)
 
1364
{
 
1365
  g_return_if_fail (GTK_IS_CLIST (clist));
 
1366
 
 
1367
  if (column < 0 || column >= clist->columns)
 
1368
    return;
 
1369
  if (!clist->column[column].button || !clist->column[column].button_passive)
 
1370
    return;
 
1371
 
 
1372
  clist->column[column].button_passive = FALSE;
 
1373
 
 
1374
  gtk_signal_disconnect_by_func (GTK_OBJECT (clist->column[column].button),
 
1375
                                 (GtkSignalFunc) column_title_passive_func,
 
1376
                                 NULL);
 
1377
 
 
1378
  GTK_WIDGET_SET_FLAGS (clist->column[column].button, GTK_CAN_FOCUS);
 
1379
  if (GTK_WIDGET_VISIBLE (clist))
 
1380
    gtk_widget_queue_draw (clist->column[column].button);
 
1381
}
 
1382
 
 
1383
void
 
1384
gtk_clist_column_title_passive (GtkCList *clist,
 
1385
                                gint      column)
 
1386
{
 
1387
  GtkButton *button;
 
1388
 
 
1389
  g_return_if_fail (GTK_IS_CLIST (clist));
 
1390
 
 
1391
  if (column < 0 || column >= clist->columns)
 
1392
    return;
 
1393
  if (!clist->column[column].button || clist->column[column].button_passive)
 
1394
    return;
 
1395
 
 
1396
  button = GTK_BUTTON (clist->column[column].button);
 
1397
 
 
1398
  clist->column[column].button_passive = TRUE;
 
1399
 
 
1400
  if (button->button_down)
 
1401
    gtk_button_released (button);
 
1402
  if (button->in_button)
 
1403
    gtk_button_leave (button);
 
1404
 
 
1405
  gtk_signal_connect (GTK_OBJECT (clist->column[column].button), "event",
 
1406
                      (GtkSignalFunc) column_title_passive_func, NULL);
 
1407
 
 
1408
  GTK_WIDGET_UNSET_FLAGS (clist->column[column].button, GTK_CAN_FOCUS);
 
1409
  if (GTK_WIDGET_VISIBLE (clist))
 
1410
    gtk_widget_queue_draw (clist->column[column].button);
 
1411
}
 
1412
 
 
1413
void
 
1414
gtk_clist_column_titles_active (GtkCList *clist)
 
1415
{
 
1416
  gint i;
 
1417
 
 
1418
  g_return_if_fail (GTK_IS_CLIST (clist));
 
1419
 
 
1420
  for (i = 0; i < clist->columns; i++)
 
1421
    gtk_clist_column_title_active (clist, i);
 
1422
}
 
1423
 
 
1424
void
 
1425
gtk_clist_column_titles_passive (GtkCList *clist)
 
1426
{
 
1427
  gint i;
 
1428
 
 
1429
  g_return_if_fail (GTK_IS_CLIST (clist));
 
1430
 
 
1431
  for (i = 0; i < clist->columns; i++)
 
1432
    gtk_clist_column_title_passive (clist, i);
 
1433
}
 
1434
 
 
1435
void
 
1436
gtk_clist_set_column_title (GtkCList    *clist,
 
1437
                            gint         column,
 
1438
                            const gchar *title)
 
1439
{
 
1440
  gint new_button = 0;
 
1441
  GtkWidget *old_widget;
 
1442
  GtkWidget *alignment = NULL;
 
1443
  GtkWidget *label;
 
1444
 
 
1445
  g_return_if_fail (GTK_IS_CLIST (clist));
 
1446
 
 
1447
  if (column < 0 || column >= clist->columns)
 
1448
    return;
 
1449
 
 
1450
  /* if the column button doesn't currently exist,
 
1451
   * it has to be created first */
 
1452
  if (!clist->column[column].button)
 
1453
    {
 
1454
      column_button_create (clist, column);
 
1455
      new_button = 1;
 
1456
    }
 
1457
 
 
1458
  column_title_new (clist, column, title);
 
1459
 
 
1460
  /* remove and destroy the old widget */
 
1461
  old_widget = GTK_BIN (clist->column[column].button)->child;
 
1462
  if (old_widget)
 
1463
    gtk_container_remove (GTK_CONTAINER (clist->column[column].button), old_widget);
 
1464
 
 
1465
  /* create new alignment based no column justification */
 
1466
  switch (clist->column[column].justification)
 
1467
    {
 
1468
    case GTK_JUSTIFY_LEFT:
 
1469
      alignment = gtk_alignment_new (0.0, 0.5, 0.0, 0.0);
 
1470
      break;
 
1471
 
 
1472
    case GTK_JUSTIFY_RIGHT:
 
1473
      alignment = gtk_alignment_new (1.0, 0.5, 0.0, 0.0);
 
1474
      break;
 
1475
 
 
1476
    case GTK_JUSTIFY_CENTER:
 
1477
      alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
 
1478
      break;
 
1479
 
 
1480
    case GTK_JUSTIFY_FILL:
 
1481
      alignment = gtk_alignment_new (0.5, 0.5, 0.0, 0.0);
 
1482
      break;
 
1483
    }
 
1484
 
 
1485
  gtk_widget_push_composite_child ();
 
1486
  label = gtk_label_new (clist->column[column].title);
 
1487
  gtk_widget_pop_composite_child ();
 
1488
  gtk_container_add (GTK_CONTAINER (alignment), label);
 
1489
  gtk_container_add (GTK_CONTAINER (clist->column[column].button), alignment);
 
1490
  gtk_widget_show (label);
 
1491
  gtk_widget_show (alignment);
 
1492
 
 
1493
  /* if this button didn't previously exist, then the
 
1494
   * column button positions have to be re-computed */
 
1495
  if (GTK_WIDGET_VISIBLE (clist) && new_button)
 
1496
    size_allocate_title_buttons (clist);
 
1497
}
 
1498
 
 
1499
gchar *
 
1500
gtk_clist_get_column_title (GtkCList *clist,
 
1501
                            gint      column)
 
1502
{
 
1503
  g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
 
1504
 
 
1505
  if (column < 0 || column >= clist->columns)
 
1506
    return NULL;
 
1507
 
 
1508
  return clist->column[column].title;
 
1509
}
 
1510
 
 
1511
void
 
1512
gtk_clist_set_column_widget (GtkCList  *clist,
 
1513
                             gint       column,
 
1514
                             GtkWidget *widget)
 
1515
{
 
1516
  gint new_button = 0;
 
1517
  GtkWidget *old_widget;
 
1518
 
 
1519
  g_return_if_fail (GTK_IS_CLIST (clist));
 
1520
 
 
1521
  if (column < 0 || column >= clist->columns)
 
1522
    return;
 
1523
 
 
1524
  /* if the column button doesn't currently exist,
 
1525
   * it has to be created first */
 
1526
  if (!clist->column[column].button)
 
1527
    {
 
1528
      column_button_create (clist, column);
 
1529
      new_button = 1;
 
1530
    }
 
1531
 
 
1532
  column_title_new (clist, column, NULL);
 
1533
 
 
1534
  /* remove and destroy the old widget */
 
1535
  old_widget = GTK_BIN (clist->column[column].button)->child;
 
1536
  if (old_widget)
 
1537
    gtk_container_remove (GTK_CONTAINER (clist->column[column].button),
 
1538
                          old_widget);
 
1539
 
 
1540
  /* add and show the widget */
 
1541
  if (widget)
 
1542
    {
 
1543
      gtk_container_add (GTK_CONTAINER (clist->column[column].button), widget);
 
1544
      gtk_widget_show (widget);
 
1545
    }
 
1546
 
 
1547
  /* if this button didn't previously exist, then the
 
1548
   * column button positions have to be re-computed */
 
1549
  if (GTK_WIDGET_VISIBLE (clist) && new_button)
 
1550
    size_allocate_title_buttons (clist);
 
1551
}
 
1552
 
 
1553
GtkWidget *
 
1554
gtk_clist_get_column_widget (GtkCList *clist,
 
1555
                             gint      column)
 
1556
{
 
1557
  g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
 
1558
 
 
1559
  if (column < 0 || column >= clist->columns)
 
1560
    return NULL;
 
1561
 
 
1562
  if (clist->column[column].button)
 
1563
    return GTK_BIN (clist->column[column].button)->child;
 
1564
 
 
1565
  return NULL;
 
1566
}
 
1567
 
 
1568
void
 
1569
gtk_clist_set_column_justification (GtkCList         *clist,
 
1570
                                    gint              column,
 
1571
                                    GtkJustification  justification)
 
1572
{
 
1573
  GtkWidget *alignment;
 
1574
 
 
1575
  g_return_if_fail (GTK_IS_CLIST (clist));
 
1576
 
 
1577
  if (column < 0 || column >= clist->columns)
 
1578
    return;
 
1579
 
 
1580
  clist->column[column].justification = justification;
 
1581
 
 
1582
  /* change the alinment of the button title if it's not a
 
1583
   * custom widget */
 
1584
  if (clist->column[column].title)
 
1585
    {
 
1586
      alignment = GTK_BIN (clist->column[column].button)->child;
 
1587
 
 
1588
      switch (clist->column[column].justification)
 
1589
        {
 
1590
        case GTK_JUSTIFY_LEFT:
 
1591
          gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.0, 0.5, 0.0, 0.0);
 
1592
          break;
 
1593
 
 
1594
        case GTK_JUSTIFY_RIGHT:
 
1595
          gtk_alignment_set (GTK_ALIGNMENT (alignment), 1.0, 0.5, 0.0, 0.0);
 
1596
          break;
 
1597
 
 
1598
        case GTK_JUSTIFY_CENTER:
 
1599
          gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.5, 0.5, 0.0, 0.0);
 
1600
          break;
 
1601
 
 
1602
        case GTK_JUSTIFY_FILL:
 
1603
          gtk_alignment_set (GTK_ALIGNMENT (alignment), 0.5, 0.5, 0.0, 0.0);
 
1604
          break;
 
1605
 
 
1606
        default:
 
1607
          break;
 
1608
        }
 
1609
    }
 
1610
 
 
1611
  if (CLIST_UNFROZEN (clist))
 
1612
    draw_rows (clist, NULL);
 
1613
}
 
1614
 
 
1615
void
 
1616
gtk_clist_set_column_visibility (GtkCList *clist,
 
1617
                                 gint      column,
 
1618
                                 gboolean  visible)
 
1619
{
 
1620
  g_return_if_fail (GTK_IS_CLIST (clist));
 
1621
 
 
1622
  if (column < 0 || column >= clist->columns)
 
1623
    return;
 
1624
  if (clist->column[column].visible == visible)
 
1625
    return;
 
1626
 
 
1627
  /* don't hide last visible column */
 
1628
  if (!visible)
 
1629
    {
 
1630
      gint i;
 
1631
      gint vis_columns = 0;
 
1632
 
 
1633
      for (i = 0, vis_columns = 0; i < clist->columns && vis_columns < 2; i++)
 
1634
        if (clist->column[i].visible)
 
1635
          vis_columns++;
 
1636
 
 
1637
      if (vis_columns < 2)
 
1638
        return;
 
1639
    }
 
1640
 
 
1641
  clist->column[column].visible = visible;
 
1642
 
 
1643
  if (clist->column[column].button)
 
1644
    {
 
1645
      if (visible)
 
1646
        gtk_widget_show (clist->column[column].button);
 
1647
      else
 
1648
        gtk_widget_hide (clist->column[column].button);
 
1649
    }
 
1650
  
 
1651
  gtk_widget_queue_resize (GTK_WIDGET(clist));
 
1652
}
 
1653
 
 
1654
void
 
1655
gtk_clist_set_column_resizeable (GtkCList *clist,
 
1656
                                 gint      column,
 
1657
                                 gboolean  resizeable)
 
1658
{
 
1659
  g_return_if_fail (GTK_IS_CLIST (clist));
 
1660
 
 
1661
  if (column < 0 || column >= clist->columns)
 
1662
    return;
 
1663
  if (clist->column[column].resizeable == resizeable)
 
1664
    return;
 
1665
 
 
1666
  clist->column[column].resizeable = resizeable;
 
1667
  if (resizeable)
 
1668
    clist->column[column].auto_resize = FALSE;
 
1669
 
 
1670
  if (GTK_WIDGET_VISIBLE (clist))
 
1671
    size_allocate_title_buttons (clist);
 
1672
}
 
1673
 
 
1674
void
 
1675
gtk_clist_set_column_auto_resize (GtkCList *clist,
 
1676
                                  gint      column,
 
1677
                                  gboolean  auto_resize)
 
1678
{
 
1679
  g_return_if_fail (GTK_IS_CLIST (clist));
 
1680
 
 
1681
  if (column < 0 || column >= clist->columns)
 
1682
    return;
 
1683
  if (clist->column[column].auto_resize == auto_resize)
 
1684
    return;
 
1685
 
 
1686
  clist->column[column].auto_resize = auto_resize;
 
1687
  if (auto_resize)
 
1688
    {
 
1689
      clist->column[column].resizeable = FALSE;
 
1690
      if (!GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
 
1691
        {
 
1692
          gint width;
 
1693
 
 
1694
          width = gtk_clist_optimal_column_width (clist, column);
 
1695
          gtk_clist_set_column_width (clist, column, width);
 
1696
        }
 
1697
    }
 
1698
 
 
1699
  if (GTK_WIDGET_VISIBLE (clist))
 
1700
    size_allocate_title_buttons (clist);
 
1701
}
 
1702
 
 
1703
gint
 
1704
gtk_clist_columns_autosize (GtkCList *clist)
 
1705
{
 
1706
  gint i;
 
1707
  gint width;
 
1708
 
 
1709
  g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
 
1710
 
 
1711
  gtk_clist_freeze (clist);
 
1712
  width = 0;
 
1713
  for (i = 0; i < clist->columns; i++)
 
1714
    {
 
1715
      gtk_clist_set_column_width (clist, i,
 
1716
                                  gtk_clist_optimal_column_width (clist, i));
 
1717
 
 
1718
      width += clist->column[i].width;
 
1719
    }
 
1720
 
 
1721
  gtk_clist_thaw (clist);
 
1722
  return width;
 
1723
}
 
1724
 
 
1725
gint
 
1726
gtk_clist_optimal_column_width (GtkCList *clist,
 
1727
                                gint      column)
 
1728
{
 
1729
  GtkRequisition requisition;
 
1730
  GList *list;
 
1731
  gint width;
 
1732
 
 
1733
  g_return_val_if_fail (GTK_CLIST (clist), 0);
 
1734
 
 
1735
  if (column < 0 || column >= clist->columns)
 
1736
    return 0;
 
1737
 
 
1738
  if (GTK_CLIST_SHOW_TITLES(clist) && clist->column[column].button)
 
1739
    width = (clist->column[column].button->requisition.width)
 
1740
#if 0
 
1741
             (CELL_SPACING + (2 * COLUMN_INSET)))
 
1742
#endif
 
1743
                ;
 
1744
  else
 
1745
    width = 0;
 
1746
 
 
1747
  for (list = clist->row_list; list; list = list->next)
 
1748
    {
 
1749
  GTK_CLIST_GET_CLASS (clist)->cell_size_request
 
1750
        (clist, GTK_CLIST_ROW (list), column, &requisition);
 
1751
      width = MAX (width, requisition.width);
 
1752
    }
 
1753
 
 
1754
  return width;
 
1755
}
 
1756
 
 
1757
void
 
1758
gtk_clist_set_column_width (GtkCList *clist,
 
1759
                            gint      column,
 
1760
                            gint      width)
 
1761
{
 
1762
  g_return_if_fail (GTK_IS_CLIST (clist));
 
1763
 
 
1764
  if (column < 0 || column >= clist->columns)
 
1765
    return;
 
1766
 
 
1767
  gtk_signal_emit (GTK_OBJECT (clist), clist_signals[RESIZE_COLUMN],
 
1768
                   column, width);
 
1769
}
 
1770
 
 
1771
void
 
1772
gtk_clist_set_column_min_width (GtkCList *clist,
 
1773
                                gint      column,
 
1774
                                gint      min_width)
 
1775
{
 
1776
  g_return_if_fail (GTK_IS_CLIST (clist));
 
1777
 
 
1778
  if (column < 0 || column >= clist->columns)
 
1779
    return;
 
1780
  if (clist->column[column].min_width == min_width)
 
1781
    return;
 
1782
 
 
1783
  if (clist->column[column].max_width >= 0  &&
 
1784
      clist->column[column].max_width < min_width)
 
1785
    clist->column[column].min_width = clist->column[column].max_width;
 
1786
  else
 
1787
    clist->column[column].min_width = min_width;
 
1788
 
 
1789
  if (clist->column[column].area.width < clist->column[column].min_width)
 
1790
    gtk_clist_set_column_width (clist, column,clist->column[column].min_width);
 
1791
}
 
1792
 
 
1793
void
 
1794
gtk_clist_set_column_max_width (GtkCList *clist,
 
1795
                                gint      column,
 
1796
                                gint      max_width)
 
1797
{
 
1798
  g_return_if_fail (GTK_IS_CLIST (clist));
 
1799
 
 
1800
  if (column < 0 || column >= clist->columns)
 
1801
    return;
 
1802
  if (clist->column[column].max_width == max_width)
 
1803
    return;
 
1804
 
 
1805
  if (clist->column[column].min_width >= 0 && max_width >= 0 &&
 
1806
      clist->column[column].min_width > max_width)
 
1807
    clist->column[column].max_width = clist->column[column].min_width;
 
1808
  else
 
1809
    clist->column[column].max_width = max_width;
 
1810
  
 
1811
  if (clist->column[column].area.width > clist->column[column].max_width)
 
1812
    gtk_clist_set_column_width (clist, column,clist->column[column].max_width);
 
1813
}
 
1814
 
 
1815
/* PRIVATE COLUMN FUNCTIONS
 
1816
 *   column_auto_resize
 
1817
 *   real_resize_column
 
1818
 *   abort_column_resize
 
1819
 *   size_allocate_title_buttons
 
1820
 *   size_allocate_columns
 
1821
 *   list_requisition_width
 
1822
 *   new_column_width
 
1823
 *   column_button_create
 
1824
 *   column_button_clicked
 
1825
 *   column_title_passive_func
 
1826
 */
 
1827
static void
 
1828
column_auto_resize (GtkCList    *clist,
 
1829
                    GtkCListRow *clist_row,
 
1830
                    gint         column,
 
1831
                    gint         old_width)
 
1832
{
 
1833
  /* resize column if needed for auto_resize */
 
1834
  GtkRequisition requisition;
 
1835
 
 
1836
  if (!clist->column[column].auto_resize ||
 
1837
      GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
 
1838
    return;
 
1839
 
 
1840
  if (clist_row)
 
1841
    GTK_CLIST_GET_CLASS (clist)->cell_size_request (clist, clist_row,
 
1842
                                                   column, &requisition);
 
1843
  else
 
1844
    requisition.width = 0;
 
1845
 
 
1846
  if (requisition.width > clist->column[column].width)
 
1847
    gtk_clist_set_column_width (clist, column, requisition.width);
 
1848
  else if (requisition.width < old_width &&
 
1849
           old_width == clist->column[column].width)
 
1850
    {
 
1851
      GList *list;
 
1852
      gint new_width = 0;
 
1853
 
 
1854
      /* run a "gtk_clist_optimal_column_width" but break, if
 
1855
       * the column doesn't shrink */
 
1856
      if (GTK_CLIST_SHOW_TITLES(clist) && clist->column[column].button)
 
1857
        new_width = (clist->column[column].button->requisition.width -
 
1858
                     (CELL_SPACING + (2 * COLUMN_INSET)));
 
1859
      else
 
1860
        new_width = 0;
 
1861
 
 
1862
      for (list = clist->row_list; list; list = list->next)
 
1863
        {
 
1864
          GTK_CLIST_GET_CLASS (clist)->cell_size_request
 
1865
            (clist, GTK_CLIST_ROW (list), column, &requisition);
 
1866
          new_width = MAX (new_width, requisition.width);
 
1867
          if (new_width == clist->column[column].width)
 
1868
            break;
 
1869
        }
 
1870
      if (new_width < clist->column[column].width)
 
1871
        gtk_clist_set_column_width
 
1872
          (clist, column, MAX (new_width, clist->column[column].min_width));
 
1873
    }
 
1874
}
 
1875
 
 
1876
static void
 
1877
real_resize_column (GtkCList *clist,
 
1878
                    gint      column,
 
1879
                    gint      width)
 
1880
{
 
1881
  g_return_if_fail (GTK_IS_CLIST (clist));
 
1882
 
 
1883
  if (column < 0 || column >= clist->columns)
 
1884
    return;
 
1885
  
 
1886
  if (width < MAX (COLUMN_MIN_WIDTH, clist->column[column].min_width))
 
1887
    width = MAX (COLUMN_MIN_WIDTH, clist->column[column].min_width);
 
1888
  if (clist->column[column].max_width >= 0 &&
 
1889
      width > clist->column[column].max_width)
 
1890
    width = clist->column[column].max_width;
 
1891
 
 
1892
  clist->column[column].width = width;
 
1893
  clist->column[column].width_set = TRUE;
 
1894
 
 
1895
  /* FIXME: this is quite expensive to do if the widget hasn't
 
1896
   *        been size_allocated yet, and pointless. Should
 
1897
   *        a flag be kept
 
1898
   */
 
1899
  size_allocate_columns (clist, TRUE);
 
1900
  size_allocate_title_buttons (clist);
 
1901
 
 
1902
  CLIST_REFRESH (clist);
 
1903
}
 
1904
 
 
1905
static void
 
1906
abort_column_resize (GtkCList *clist)
 
1907
{
 
1908
  g_return_if_fail (GTK_IS_CLIST (clist));
 
1909
 
 
1910
  if (!GTK_CLIST_IN_DRAG(clist))
 
1911
    return;
 
1912
 
 
1913
  GTK_CLIST_UNSET_FLAG (clist, CLIST_IN_DRAG);
 
1914
  gtk_grab_remove (GTK_WIDGET (clist));
 
1915
  gdk_display_pointer_ungrab (gtk_widget_get_display (GTK_WIDGET (clist)),
 
1916
                              GDK_CURRENT_TIME);
 
1917
  clist->drag_pos = -1;
 
1918
 
 
1919
  if (clist->x_drag >= 0 && clist->x_drag <= clist->clist_window_width - 1)
 
1920
    draw_xor_line (clist);
 
1921
 
 
1922
  if (GTK_CLIST_ADD_MODE(clist))
 
1923
    {
 
1924
      gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_ON_OFF_DASH, 0,0);
 
1925
      gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
 
1926
    }
 
1927
}
 
1928
 
 
1929
static void
 
1930
size_allocate_title_buttons (GtkCList *clist)
 
1931
{
 
1932
  GtkAllocation button_allocation;
 
1933
  gint last_column;
 
1934
  gint last_button = 0;
 
1935
  gint i;
 
1936
 
 
1937
  if (!GTK_WIDGET_REALIZED (clist))
 
1938
    return;
 
1939
 
 
1940
  button_allocation.x = clist->hoffset;
 
1941
  button_allocation.y = 0;
 
1942
  button_allocation.width = 0;
 
1943
  button_allocation.height = clist->column_title_area.height;
 
1944
 
 
1945
  /* find last visible column */
 
1946
  for (last_column = clist->columns - 1; last_column >= 0; last_column--)
 
1947
    if (clist->column[last_column].visible)
 
1948
      break;
 
1949
 
 
1950
  for (i = 0; i < last_column; i++)
 
1951
    {
 
1952
      if (!clist->column[i].visible)
 
1953
        {
 
1954
          last_button = i + 1;
 
1955
          gdk_window_hide (clist->column[i].window);
 
1956
          continue;
 
1957
        }
 
1958
 
 
1959
      button_allocation.width += (clist->column[i].area.width +
 
1960
                                  CELL_SPACING + 2 * COLUMN_INSET);
 
1961
 
 
1962
      if (!clist->column[i + 1].button)
 
1963
        {
 
1964
          gdk_window_hide (clist->column[i].window);
 
1965
          continue;
 
1966
        }
 
1967
 
 
1968
      gtk_widget_size_allocate (clist->column[last_button].button,
 
1969
                                &button_allocation);
 
1970
      button_allocation.x += button_allocation.width;
 
1971
      button_allocation.width = 0;
 
1972
 
 
1973
      if (clist->column[last_button].resizeable)
 
1974
        {
 
1975
          gdk_window_show (clist->column[last_button].window);
 
1976
          gdk_window_move_resize (clist->column[last_button].window,
 
1977
                                  button_allocation.x - (DRAG_WIDTH / 2), 
 
1978
                                  0, DRAG_WIDTH,
 
1979
                                  clist->column_title_area.height);
 
1980
        }
 
1981
      else
 
1982
        gdk_window_hide (clist->column[last_button].window);
 
1983
 
 
1984
      last_button = i + 1;
 
1985
    }
 
1986
 
 
1987
  button_allocation.width += (clist->column[last_column].area.width +
 
1988
                              2 * (CELL_SPACING + COLUMN_INSET));
 
1989
  gtk_widget_size_allocate (clist->column[last_button].button,
 
1990
                            &button_allocation);
 
1991
 
 
1992
  if (clist->column[last_button].resizeable)
 
1993
    {
 
1994
      button_allocation.x += button_allocation.width;
 
1995
 
 
1996
      gdk_window_show (clist->column[last_button].window);
 
1997
      gdk_window_move_resize (clist->column[last_button].window,
 
1998
                              button_allocation.x - (DRAG_WIDTH / 2), 
 
1999
                              0, DRAG_WIDTH, clist->column_title_area.height);
 
2000
    }
 
2001
  else
 
2002
    gdk_window_hide (clist->column[last_button].window);
 
2003
}
 
2004
 
 
2005
static void
 
2006
size_allocate_columns (GtkCList *clist,
 
2007
                       gboolean  block_resize)
 
2008
{
 
2009
  gint xoffset = CELL_SPACING + COLUMN_INSET;
 
2010
  gint last_column;
 
2011
  gint i;
 
2012
 
 
2013
  /* find last visible column and calculate correct column width */
 
2014
  for (last_column = clist->columns - 1;
 
2015
       last_column >= 0 && !clist->column[last_column].visible; last_column--);
 
2016
 
 
2017
  if (last_column < 0)
 
2018
    return;
 
2019
 
 
2020
  for (i = 0; i <= last_column; i++)
 
2021
    {
 
2022
      if (!clist->column[i].visible)
 
2023
        continue;
 
2024
      clist->column[i].area.x = xoffset;
 
2025
      if (clist->column[i].width_set)
 
2026
        {
 
2027
          if (!block_resize && GTK_CLIST_SHOW_TITLES(clist) &&
 
2028
              clist->column[i].auto_resize && clist->column[i].button)
 
2029
            {
 
2030
              gint width;
 
2031
 
 
2032
              width = (clist->column[i].button->requisition.width -
 
2033
                       (CELL_SPACING + (2 * COLUMN_INSET)));
 
2034
 
 
2035
              if (width > clist->column[i].width)
 
2036
                gtk_clist_set_column_width (clist, i, width);
 
2037
            }
 
2038
 
 
2039
          clist->column[i].area.width = clist->column[i].width;
 
2040
          xoffset += clist->column[i].width + CELL_SPACING + (2* COLUMN_INSET);
 
2041
        }
 
2042
      else if (GTK_CLIST_SHOW_TITLES(clist) && clist->column[i].button)
 
2043
        {
 
2044
          clist->column[i].area.width =
 
2045
            clist->column[i].button->requisition.width -
 
2046
            (CELL_SPACING + (2 * COLUMN_INSET));
 
2047
          xoffset += clist->column[i].button->requisition.width;
 
2048
        }
 
2049
    }
 
2050
 
 
2051
  clist->column[last_column].area.width = clist->column[last_column].area.width
 
2052
    + MAX (0, clist->clist_window_width + COLUMN_INSET - xoffset);
 
2053
}
 
2054
 
 
2055
static gint
 
2056
list_requisition_width (GtkCList *clist) 
 
2057
{
 
2058
  gint width = CELL_SPACING;
 
2059
  gint i;
 
2060
 
 
2061
  for (i = clist->columns - 1; i >= 0; i--)
 
2062
    {
 
2063
      if (!clist->column[i].visible)
 
2064
        continue;
 
2065
 
 
2066
      if (clist->column[i].width_set)
 
2067
        width += clist->column[i].width + CELL_SPACING + (2 * COLUMN_INSET);
 
2068
      else if (GTK_CLIST_SHOW_TITLES(clist) && clist->column[i].button)
 
2069
        width += clist->column[i].button->requisition.width;
 
2070
    }
 
2071
 
 
2072
  return width;
 
2073
}
 
2074
 
 
2075
/* this function returns the new width of the column being resized given
 
2076
 * the column and x position of the cursor; the x cursor position is passed
 
2077
 * in as a pointer and automagicly corrected if it's beyond min/max limits */
 
2078
static gint
 
2079
new_column_width (GtkCList *clist,
 
2080
                  gint      column,
 
2081
                  gint     *x)
 
2082
{
 
2083
  gint xthickness = GTK_WIDGET (clist)->style->xthickness;
 
2084
  gint width;
 
2085
  gint cx;
 
2086
  gint dx;
 
2087
  gint last_column;
 
2088
 
 
2089
  /* first translate the x position from widget->window
 
2090
   * to clist->clist_window */
 
2091
  cx = *x - xthickness;
 
2092
 
 
2093
  for (last_column = clist->columns - 1;
 
2094
       last_column >= 0 && !clist->column[last_column].visible; last_column--);
 
2095
 
 
2096
  /* calculate new column width making sure it doesn't end up
 
2097
   * less than the minimum width */
 
2098
  dx = (COLUMN_LEFT_XPIXEL (clist, column) + COLUMN_INSET +
 
2099
        (column < last_column) * CELL_SPACING);
 
2100
  width = cx - dx;
 
2101
 
 
2102
  if (width < MAX (COLUMN_MIN_WIDTH, clist->column[column].min_width))
 
2103
    {
 
2104
      width = MAX (COLUMN_MIN_WIDTH, clist->column[column].min_width);
 
2105
      cx = dx + width;
 
2106
      *x = cx + xthickness;
 
2107
    }
 
2108
  else if (clist->column[column].max_width >= COLUMN_MIN_WIDTH &&
 
2109
           width > clist->column[column].max_width)
 
2110
    {
 
2111
      width = clist->column[column].max_width;
 
2112
      cx = dx + clist->column[column].max_width;
 
2113
      *x = cx + xthickness;
 
2114
    }      
 
2115
 
 
2116
  if (cx < 0 || cx > clist->clist_window_width)
 
2117
    *x = -1;
 
2118
 
 
2119
  return width;
 
2120
}
 
2121
 
 
2122
static void
 
2123
column_button_create (GtkCList *clist,
 
2124
                      gint      column)
 
2125
{
 
2126
  GtkWidget *button;
 
2127
 
 
2128
  gtk_widget_push_composite_child ();
 
2129
  button = clist->column[column].button = gtk_button_new ();
 
2130
  gtk_widget_pop_composite_child ();
 
2131
 
 
2132
  if (GTK_WIDGET_REALIZED (clist) && clist->title_window)
 
2133
    gtk_widget_set_parent_window (clist->column[column].button,
 
2134
                                  clist->title_window);
 
2135
  gtk_widget_set_parent (button, GTK_WIDGET (clist));
 
2136
 
 
2137
  gtk_signal_connect (GTK_OBJECT (button), "clicked",
 
2138
                      (GtkSignalFunc) column_button_clicked,
 
2139
                      (gpointer) clist);
 
2140
  gtk_widget_show (button);
 
2141
}
 
2142
 
 
2143
static void
 
2144
column_button_clicked (GtkWidget *widget,
 
2145
                       gpointer   data)
 
2146
{
 
2147
  gint i;
 
2148
  GtkCList *clist;
 
2149
 
 
2150
  g_return_if_fail (widget != NULL);
 
2151
  g_return_if_fail (GTK_IS_CLIST (data));
 
2152
 
 
2153
  clist = GTK_CLIST (data);
 
2154
 
 
2155
  /* find the column who's button was pressed */
 
2156
  for (i = 0; i < clist->columns; i++)
 
2157
    if (clist->column[i].button == widget)
 
2158
      break;
 
2159
 
 
2160
  gtk_signal_emit (GTK_OBJECT (clist), clist_signals[CLICK_COLUMN], i);
 
2161
}
 
2162
 
 
2163
static gint
 
2164
column_title_passive_func (GtkWidget *widget, 
 
2165
                           GdkEvent  *event,
 
2166
                           gpointer   data)
 
2167
{
 
2168
  g_return_val_if_fail (event != NULL, FALSE);
 
2169
  
 
2170
  switch (event->type)
 
2171
    {
 
2172
    case GDK_MOTION_NOTIFY:
 
2173
    case GDK_BUTTON_PRESS:
 
2174
    case GDK_2BUTTON_PRESS:
 
2175
    case GDK_3BUTTON_PRESS:
 
2176
    case GDK_BUTTON_RELEASE:
 
2177
    case GDK_ENTER_NOTIFY:
 
2178
    case GDK_LEAVE_NOTIFY:
 
2179
      return TRUE;
 
2180
    default:
 
2181
      break;
 
2182
    }
 
2183
  return FALSE;
 
2184
}
 
2185
 
 
2186
 
 
2187
/* PUBLIC CELL FUNCTIONS
 
2188
 *   gtk_clist_get_cell_type
 
2189
 *   gtk_clist_set_text
 
2190
 *   gtk_clist_get_text
 
2191
 *   gtk_clist_set_pixmap
 
2192
 *   gtk_clist_get_pixmap
 
2193
 *   gtk_clist_set_pixtext
 
2194
 *   gtk_clist_get_pixtext
 
2195
 *   gtk_clist_set_shift
 
2196
 */
 
2197
GtkCellType 
 
2198
gtk_clist_get_cell_type (GtkCList *clist,
 
2199
                         gint      row,
 
2200
                         gint      column)
 
2201
{
 
2202
  GtkCListRow *clist_row;
 
2203
 
 
2204
  g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
 
2205
 
 
2206
  if (row < 0 || row >= clist->rows)
 
2207
    return -1;
 
2208
  if (column < 0 || column >= clist->columns)
 
2209
    return -1;
 
2210
 
 
2211
  clist_row = ROW_ELEMENT (clist, row)->data;
 
2212
 
 
2213
  return clist_row->cell[column].type;
 
2214
}
 
2215
 
 
2216
void
 
2217
gtk_clist_set_text (GtkCList    *clist,
 
2218
                    gint         row,
 
2219
                    gint         column,
 
2220
                    const gchar *text)
 
2221
{
 
2222
  GtkCListRow *clist_row;
 
2223
 
 
2224
  g_return_if_fail (GTK_IS_CLIST (clist));
 
2225
 
 
2226
  if (row < 0 || row >= clist->rows)
 
2227
    return;
 
2228
  if (column < 0 || column >= clist->columns)
 
2229
    return;
 
2230
 
 
2231
  clist_row = ROW_ELEMENT (clist, row)->data;
 
2232
 
 
2233
  /* if text is null, then the cell is empty */
 
2234
  GTK_CLIST_GET_CLASS (clist)->set_cell_contents
 
2235
    (clist, clist_row, column, GTK_CELL_TEXT, text, 0, NULL, NULL);
 
2236
 
 
2237
  /* redraw the list if it's not frozen */
 
2238
  if (CLIST_UNFROZEN (clist))
 
2239
    {
 
2240
      if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
 
2241
        GTK_CLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, clist_row);
 
2242
    }
 
2243
}
 
2244
 
 
2245
gint
 
2246
gtk_clist_get_text (GtkCList  *clist,
 
2247
                    gint       row,
 
2248
                    gint       column,
 
2249
                    gchar    **text)
 
2250
{
 
2251
  GtkCListRow *clist_row;
 
2252
 
 
2253
  g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
 
2254
 
 
2255
  if (row < 0 || row >= clist->rows)
 
2256
    return 0;
 
2257
  if (column < 0 || column >= clist->columns)
 
2258
    return 0;
 
2259
 
 
2260
  clist_row = ROW_ELEMENT (clist, row)->data;
 
2261
 
 
2262
  if (clist_row->cell[column].type != GTK_CELL_TEXT)
 
2263
    return 0;
 
2264
 
 
2265
  if (text)
 
2266
    *text = GTK_CELL_TEXT (clist_row->cell[column])->text;
 
2267
 
 
2268
  return 1;
 
2269
}
 
2270
 
 
2271
void
 
2272
gtk_clist_set_pixmap (GtkCList  *clist,
 
2273
                      gint       row,
 
2274
                      gint       column,
 
2275
                      GdkPixmap *pixmap,
 
2276
                      GdkBitmap *mask)
 
2277
{
 
2278
  GtkCListRow *clist_row;
 
2279
 
 
2280
  g_return_if_fail (GTK_IS_CLIST (clist));
 
2281
 
 
2282
  if (row < 0 || row >= clist->rows)
 
2283
    return;
 
2284
  if (column < 0 || column >= clist->columns)
 
2285
    return;
 
2286
 
 
2287
  clist_row = ROW_ELEMENT (clist, row)->data;
 
2288
  
 
2289
  gdk_pixmap_ref (pixmap);
 
2290
  
 
2291
  if (mask) gdk_pixmap_ref (mask);
 
2292
  
 
2293
  GTK_CLIST_GET_CLASS (clist)->set_cell_contents
 
2294
    (clist, clist_row, column, GTK_CELL_PIXMAP, NULL, 0, pixmap, mask);
 
2295
 
 
2296
  /* redraw the list if it's not frozen */
 
2297
  if (CLIST_UNFROZEN (clist))
 
2298
    {
 
2299
      if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
 
2300
        GTK_CLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, clist_row);
 
2301
    }
 
2302
}
 
2303
 
 
2304
gint
 
2305
gtk_clist_get_pixmap (GtkCList   *clist,
 
2306
                      gint        row,
 
2307
                      gint        column,
 
2308
                      GdkPixmap **pixmap,
 
2309
                      GdkBitmap **mask)
 
2310
{
 
2311
  GtkCListRow *clist_row;
 
2312
 
 
2313
  g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
 
2314
 
 
2315
  if (row < 0 || row >= clist->rows)
 
2316
    return 0;
 
2317
  if (column < 0 || column >= clist->columns)
 
2318
    return 0;
 
2319
 
 
2320
  clist_row = ROW_ELEMENT (clist, row)->data;
 
2321
 
 
2322
  if (clist_row->cell[column].type != GTK_CELL_PIXMAP)
 
2323
    return 0;
 
2324
 
 
2325
  if (pixmap)
 
2326
  {
 
2327
    *pixmap = GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap;
 
2328
    /* mask can be NULL */
 
2329
    *mask = GTK_CELL_PIXMAP (clist_row->cell[column])->mask;
 
2330
  }
 
2331
 
 
2332
  return 1;
 
2333
}
 
2334
 
 
2335
void
 
2336
gtk_clist_set_pixtext (GtkCList    *clist,
 
2337
                       gint         row,
 
2338
                       gint         column,
 
2339
                       const gchar *text,
 
2340
                       guint8       spacing,
 
2341
                       GdkPixmap   *pixmap,
 
2342
                       GdkBitmap   *mask)
 
2343
{
 
2344
  GtkCListRow *clist_row;
 
2345
 
 
2346
  g_return_if_fail (GTK_IS_CLIST (clist));
 
2347
 
 
2348
  if (row < 0 || row >= clist->rows)
 
2349
    return;
 
2350
  if (column < 0 || column >= clist->columns)
 
2351
    return;
 
2352
 
 
2353
  clist_row = ROW_ELEMENT (clist, row)->data;
 
2354
  
 
2355
  gdk_pixmap_ref (pixmap);
 
2356
  if (mask) gdk_pixmap_ref (mask);
 
2357
  GTK_CLIST_GET_CLASS (clist)->set_cell_contents
 
2358
    (clist, clist_row, column, GTK_CELL_PIXTEXT, text, spacing, pixmap, mask);
 
2359
 
 
2360
  /* redraw the list if it's not frozen */
 
2361
  if (CLIST_UNFROZEN (clist))
 
2362
    {
 
2363
      if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
 
2364
        GTK_CLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, clist_row);
 
2365
    }
 
2366
}
 
2367
 
 
2368
gint
 
2369
gtk_clist_get_pixtext (GtkCList   *clist,
 
2370
                       gint        row,
 
2371
                       gint        column,
 
2372
                       gchar     **text,
 
2373
                       guint8     *spacing,
 
2374
                       GdkPixmap **pixmap,
 
2375
                       GdkBitmap **mask)
 
2376
{
 
2377
  GtkCListRow *clist_row;
 
2378
 
 
2379
  g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
 
2380
 
 
2381
  if (row < 0 || row >= clist->rows)
 
2382
    return 0;
 
2383
  if (column < 0 || column >= clist->columns)
 
2384
    return 0;
 
2385
 
 
2386
  clist_row = ROW_ELEMENT (clist, row)->data;
 
2387
 
 
2388
  if (clist_row->cell[column].type != GTK_CELL_PIXTEXT)
 
2389
    return 0;
 
2390
 
 
2391
  if (text)
 
2392
    *text = GTK_CELL_PIXTEXT (clist_row->cell[column])->text;
 
2393
  if (spacing)
 
2394
    *spacing = GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing;
 
2395
  if (pixmap)
 
2396
    *pixmap = GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap;
 
2397
 
 
2398
  /* mask can be NULL */
 
2399
  if (mask)
 
2400
    *mask = GTK_CELL_PIXTEXT (clist_row->cell[column])->mask;
 
2401
 
 
2402
  return 1;
 
2403
}
 
2404
 
 
2405
void
 
2406
gtk_clist_set_shift (GtkCList *clist,
 
2407
                     gint      row,
 
2408
                     gint      column,
 
2409
                     gint      vertical,
 
2410
                     gint      horizontal)
 
2411
{
 
2412
  GtkRequisition requisition = { 0 };
 
2413
  GtkCListRow *clist_row;
 
2414
 
 
2415
  g_return_if_fail (GTK_IS_CLIST (clist));
 
2416
 
 
2417
  if (row < 0 || row >= clist->rows)
 
2418
    return;
 
2419
  if (column < 0 || column >= clist->columns)
 
2420
    return;
 
2421
 
 
2422
  clist_row = ROW_ELEMENT (clist, row)->data;
 
2423
 
 
2424
  if (clist->column[column].auto_resize &&
 
2425
      !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
 
2426
    GTK_CLIST_GET_CLASS (clist)->cell_size_request (clist, clist_row,
 
2427
                                                   column, &requisition);
 
2428
 
 
2429
  clist_row->cell[column].vertical = vertical;
 
2430
  clist_row->cell[column].horizontal = horizontal;
 
2431
 
 
2432
  column_auto_resize (clist, clist_row, column, requisition.width);
 
2433
 
 
2434
  if (CLIST_UNFROZEN (clist) && gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
 
2435
    GTK_CLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, clist_row);
 
2436
}
 
2437
 
 
2438
/* PRIVATE CELL FUNCTIONS
 
2439
 *   set_cell_contents
 
2440
 *   cell_size_request
 
2441
 */
 
2442
static void
 
2443
set_cell_contents (GtkCList    *clist,
 
2444
                   GtkCListRow *clist_row,
 
2445
                   gint         column,
 
2446
                   GtkCellType  type,
 
2447
                   const gchar *text,
 
2448
                   guint8       spacing,
 
2449
                   GdkPixmap   *pixmap,
 
2450
                   GdkBitmap   *mask)
 
2451
{
 
2452
  GtkRequisition requisition;
 
2453
  gchar *old_text = NULL;
 
2454
  GdkPixmap *old_pixmap = NULL;
 
2455
  GdkBitmap *old_mask = NULL;
 
2456
  
 
2457
  g_return_if_fail (GTK_IS_CLIST (clist));
 
2458
  g_return_if_fail (clist_row != NULL);
 
2459
 
 
2460
  if (clist->column[column].auto_resize &&
 
2461
      !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
 
2462
    GTK_CLIST_GET_CLASS (clist)->cell_size_request (clist, clist_row,
 
2463
                                                   column, &requisition);
 
2464
 
 
2465
  switch (clist_row->cell[column].type)
 
2466
    {
 
2467
    case GTK_CELL_EMPTY:
 
2468
      break;
 
2469
    case GTK_CELL_TEXT:
 
2470
      old_text = GTK_CELL_TEXT (clist_row->cell[column])->text;
 
2471
      break;
 
2472
    case GTK_CELL_PIXMAP:
 
2473
      old_pixmap = GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap;
 
2474
      old_mask = GTK_CELL_PIXMAP (clist_row->cell[column])->mask;
 
2475
      break;
 
2476
    case GTK_CELL_PIXTEXT:
 
2477
      old_text = GTK_CELL_PIXTEXT (clist_row->cell[column])->text;
 
2478
      old_pixmap = GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap;
 
2479
      old_mask = GTK_CELL_PIXTEXT (clist_row->cell[column])->mask;
 
2480
      break;
 
2481
    case GTK_CELL_WIDGET:
 
2482
      /* unimplemented */
 
2483
      break;
 
2484
    default:
 
2485
      break;
 
2486
    }
 
2487
 
 
2488
  clist_row->cell[column].type = GTK_CELL_EMPTY;
 
2489
 
 
2490
  /* Note that pixmap and mask were already ref'ed by the caller
 
2491
   */
 
2492
  switch (type)
 
2493
    {
 
2494
    case GTK_CELL_TEXT:
 
2495
      if (text)
 
2496
        {
 
2497
          clist_row->cell[column].type = GTK_CELL_TEXT;
 
2498
          GTK_CELL_TEXT (clist_row->cell[column])->text = g_strdup (text);
 
2499
        }
 
2500
      break;
 
2501
    case GTK_CELL_PIXMAP:
 
2502
      if (pixmap)
 
2503
        {
 
2504
          clist_row->cell[column].type = GTK_CELL_PIXMAP;
 
2505
          GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap = pixmap;
 
2506
          /* We set the mask even if it is NULL */
 
2507
          GTK_CELL_PIXMAP (clist_row->cell[column])->mask = mask;
 
2508
        }
 
2509
      break;
 
2510
    case GTK_CELL_PIXTEXT:
 
2511
      if (text && pixmap)
 
2512
        {
 
2513
          clist_row->cell[column].type = GTK_CELL_PIXTEXT;
 
2514
          GTK_CELL_PIXTEXT (clist_row->cell[column])->text = g_strdup (text);
 
2515
          GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing = spacing;
 
2516
          GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap = pixmap;
 
2517
          GTK_CELL_PIXTEXT (clist_row->cell[column])->mask = mask;
 
2518
        }
 
2519
      break;
 
2520
    default:
 
2521
      break;
 
2522
    }
 
2523
 
 
2524
  if (clist->column[column].auto_resize &&
 
2525
      !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
 
2526
    column_auto_resize (clist, clist_row, column, requisition.width);
 
2527
 
 
2528
  if (old_text)
 
2529
    g_free (old_text);
 
2530
  if (old_pixmap)
 
2531
    gdk_pixmap_unref (old_pixmap);
 
2532
  if (old_mask)
 
2533
    gdk_pixmap_unref (old_mask);
 
2534
}
 
2535
 
 
2536
PangoLayout *
 
2537
_gtk_clist_create_cell_layout (GtkCList       *clist,
 
2538
                               GtkCListRow    *clist_row,
 
2539
                               gint            column)
 
2540
{
 
2541
  PangoLayout *layout;
 
2542
  GtkStyle *style;
 
2543
  GtkCell *cell;
 
2544
  gchar *text;
 
2545
  
 
2546
  get_cell_style (clist, clist_row, GTK_STATE_NORMAL, column, &style,
 
2547
                  NULL, NULL);
 
2548
 
 
2549
 
 
2550
  cell = &clist_row->cell[column];
 
2551
  switch (cell->type)
 
2552
    {
 
2553
    case GTK_CELL_TEXT:
 
2554
    case GTK_CELL_PIXTEXT:
 
2555
      text = ((cell->type == GTK_CELL_PIXTEXT) ?
 
2556
              GTK_CELL_PIXTEXT (*cell)->text :
 
2557
              GTK_CELL_TEXT (*cell)->text);
 
2558
 
 
2559
      if (!text)
 
2560
        return NULL;
 
2561
      
 
2562
      layout = gtk_widget_create_pango_layout (GTK_WIDGET (clist),
 
2563
                                               ((cell->type == GTK_CELL_PIXTEXT) ?
 
2564
                                                GTK_CELL_PIXTEXT (*cell)->text :
 
2565
                                                GTK_CELL_TEXT (*cell)->text));
 
2566
      pango_layout_set_font_description (layout, style->font_desc);
 
2567
      
 
2568
      return layout;
 
2569
      
 
2570
    default:
 
2571
      return NULL;
 
2572
    }
 
2573
}
 
2574
 
 
2575
static void
 
2576
cell_size_request (GtkCList       *clist,
 
2577
                   GtkCListRow    *clist_row,
 
2578
                   gint            column,
 
2579
                   GtkRequisition *requisition)
 
2580
{
 
2581
  gint width;
 
2582
  gint height;
 
2583
  PangoLayout *layout;
 
2584
  PangoRectangle logical_rect;
 
2585
 
 
2586
  g_return_if_fail (GTK_IS_CLIST (clist));
 
2587
  g_return_if_fail (requisition != NULL);
 
2588
 
 
2589
  layout = _gtk_clist_create_cell_layout (clist, clist_row, column);
 
2590
  if (layout)
 
2591
    {
 
2592
      pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
 
2593
      
 
2594
      requisition->width = logical_rect.width;
 
2595
      requisition->height = logical_rect.height;
 
2596
      
 
2597
      g_object_unref (G_OBJECT (layout));
 
2598
    }
 
2599
  else
 
2600
    {
 
2601
      requisition->width  = 0;
 
2602
      requisition->height = 0;
 
2603
    }
 
2604
 
 
2605
  if (layout && clist_row->cell[column].type == GTK_CELL_PIXTEXT)
 
2606
    requisition->width += GTK_CELL_PIXTEXT (clist_row->cell[column])->spacing;
 
2607
 
 
2608
  switch (clist_row->cell[column].type)
 
2609
    {
 
2610
    case GTK_CELL_PIXTEXT:
 
2611
      gdk_window_get_size (GTK_CELL_PIXTEXT (clist_row->cell[column])->pixmap,
 
2612
                           &width, &height);
 
2613
      requisition->width += width;
 
2614
      requisition->height = MAX (requisition->height, height);      
 
2615
      break;
 
2616
    case GTK_CELL_PIXMAP:
 
2617
      gdk_window_get_size (GTK_CELL_PIXMAP (clist_row->cell[column])->pixmap,
 
2618
                           &width, &height);
 
2619
      requisition->width += width;
 
2620
      requisition->height = MAX (requisition->height, height);
 
2621
      break;
 
2622
      
 
2623
    default:
 
2624
      break;
 
2625
    }
 
2626
 
 
2627
  requisition->width  += clist_row->cell[column].horizontal;
 
2628
  requisition->height += clist_row->cell[column].vertical;
 
2629
}
 
2630
 
 
2631
/* PUBLIC INSERT/REMOVE ROW FUNCTIONS
 
2632
 *   gtk_clist_prepend
 
2633
 *   gtk_clist_append
 
2634
 *   gtk_clist_insert
 
2635
 *   gtk_clist_remove
 
2636
 *   gtk_clist_clear
 
2637
 */
 
2638
gint
 
2639
gtk_clist_prepend (GtkCList    *clist,
 
2640
                   gchar       *text[])
 
2641
{
 
2642
  g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
 
2643
  g_return_val_if_fail (text != NULL, -1);
 
2644
 
 
2645
  return GTK_CLIST_GET_CLASS (clist)->insert_row (clist, 0, text);
 
2646
}
 
2647
 
 
2648
gint
 
2649
gtk_clist_append (GtkCList    *clist,
 
2650
                  gchar       *text[])
 
2651
{
 
2652
  g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
 
2653
  g_return_val_if_fail (text != NULL, -1);
 
2654
 
 
2655
  return GTK_CLIST_GET_CLASS (clist)->insert_row (clist, clist->rows, text);
 
2656
}
 
2657
 
 
2658
gint
 
2659
gtk_clist_insert (GtkCList    *clist,
 
2660
                  gint         row,
 
2661
                  gchar       *text[])
 
2662
{
 
2663
  g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
 
2664
  g_return_val_if_fail (text != NULL, -1);
 
2665
 
 
2666
  if (row < 0 || row > clist->rows)
 
2667
    row = clist->rows;
 
2668
 
 
2669
  return GTK_CLIST_GET_CLASS (clist)->insert_row (clist, row, text);
 
2670
}
 
2671
 
 
2672
void
 
2673
gtk_clist_remove (GtkCList *clist,
 
2674
                  gint      row)
 
2675
{
 
2676
  GTK_CLIST_GET_CLASS (clist)->remove_row (clist, row);
 
2677
}
 
2678
 
 
2679
void
 
2680
gtk_clist_clear (GtkCList *clist)
 
2681
{
 
2682
  g_return_if_fail (GTK_IS_CLIST (clist));
 
2683
  
 
2684
  GTK_CLIST_GET_CLASS (clist)->clear (clist);
 
2685
}
 
2686
 
 
2687
/* PRIVATE INSERT/REMOVE ROW FUNCTIONS
 
2688
 *   real_insert_row
 
2689
 *   real_remove_row
 
2690
 *   real_clear
 
2691
 *   real_row_move
 
2692
 */
 
2693
static gint
 
2694
real_insert_row (GtkCList *clist,
 
2695
                 gint      row,
 
2696
                 gchar    *text[])
 
2697
{
 
2698
  gint i;
 
2699
  GtkCListRow *clist_row;
 
2700
 
 
2701
  g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
 
2702
  g_return_val_if_fail (text != NULL, -1);
 
2703
 
 
2704
  /* return if out of bounds */
 
2705
  if (row < 0 || row > clist->rows)
 
2706
    return -1;
 
2707
 
 
2708
  /* create the row */
 
2709
  clist_row = row_new (clist);
 
2710
 
 
2711
  /* set the text in the row's columns */
 
2712
  for (i = 0; i < clist->columns; i++)
 
2713
    if (text[i])
 
2714
      GTK_CLIST_GET_CLASS (clist)->set_cell_contents
 
2715
        (clist, clist_row, i, GTK_CELL_TEXT, text[i], 0, NULL ,NULL);
 
2716
 
 
2717
  if (!clist->rows)
 
2718
    {
 
2719
      clist->row_list = g_list_append (clist->row_list, clist_row);
 
2720
      clist->row_list_end = clist->row_list;
 
2721
    }
 
2722
  else
 
2723
    {
 
2724
      if (GTK_CLIST_AUTO_SORT(clist))   /* override insertion pos */
 
2725
        {
 
2726
          GList *work;
 
2727
          
 
2728
          row = 0;
 
2729
          work = clist->row_list;
 
2730
          
 
2731
          if (clist->sort_type == GTK_SORT_ASCENDING)
 
2732
            {
 
2733
              while (row < clist->rows &&
 
2734
                     clist->compare (clist, clist_row,
 
2735
                                     GTK_CLIST_ROW (work)) > 0)
 
2736
                {
 
2737
                  row++;
 
2738
                  work = work->next;
 
2739
                }
 
2740
            }
 
2741
          else
 
2742
            {
 
2743
              while (row < clist->rows &&
 
2744
                     clist->compare (clist, clist_row,
 
2745
                                     GTK_CLIST_ROW (work)) < 0)
 
2746
                {
 
2747
                  row++;
 
2748
                  work = work->next;
 
2749
                }
 
2750
            }
 
2751
        }
 
2752
      
 
2753
      /* reset the row end pointer if we're inserting at the end of the list */
 
2754
      if (row == clist->rows)
 
2755
        clist->row_list_end = (g_list_append (clist->row_list_end,
 
2756
                                              clist_row))->next;
 
2757
      else
 
2758
        clist->row_list = g_list_insert (clist->row_list, clist_row, row);
 
2759
 
 
2760
    }
 
2761
  clist->rows++;
 
2762
 
 
2763
  if (row < ROW_FROM_YPIXEL (clist, 0))
 
2764
    clist->voffset -= (clist->row_height + CELL_SPACING);
 
2765
 
 
2766
  /* syncronize the selection list */
 
2767
  sync_selection (clist, row, SYNC_INSERT);
 
2768
 
 
2769
  if (clist->rows == 1)
 
2770
    {
 
2771
      clist->focus_row = 0;
 
2772
      if (clist->selection_mode == GTK_SELECTION_BROWSE)
 
2773
        gtk_clist_select_row (clist, 0, -1);
 
2774
    }
 
2775
 
 
2776
  /* redraw the list if it isn't frozen */
 
2777
  if (CLIST_UNFROZEN (clist))
 
2778
    {
 
2779
      adjust_adjustments (clist, FALSE);
 
2780
 
 
2781
      if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
 
2782
        draw_rows (clist, NULL);
 
2783
    }
 
2784
 
 
2785
  return row;
 
2786
}
 
2787
 
 
2788
static void
 
2789
real_remove_row (GtkCList *clist,
 
2790
                 gint      row)
 
2791
{
 
2792
  gint was_visible;
 
2793
  GList *list;
 
2794
  GtkCListRow *clist_row;
 
2795
 
 
2796
  g_return_if_fail (GTK_IS_CLIST (clist));
 
2797
 
 
2798
  /* return if out of bounds */
 
2799
  if (row < 0 || row > (clist->rows - 1))
 
2800
    return;
 
2801
 
 
2802
  was_visible = (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE);
 
2803
 
 
2804
  /* get the row we're going to delete */
 
2805
  list = ROW_ELEMENT (clist, row);
 
2806
  g_assert (list != NULL);
 
2807
  clist_row = list->data;
 
2808
 
 
2809
  /* if we're removing a selected row, we have to make sure
 
2810
   * it's properly unselected, and then sync up the clist->selected
 
2811
   * list to reflect the deincrimented indexies of rows after the
 
2812
   * removal */
 
2813
  if (clist_row->state == GTK_STATE_SELECTED)
 
2814
    gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
 
2815
                     row, -1, NULL);
 
2816
 
 
2817
  sync_selection (clist, row, SYNC_REMOVE);
 
2818
 
 
2819
  /* reset the row end pointer if we're removing at the end of the list */
 
2820
  clist->rows--;
 
2821
  if (clist->row_list == list)
 
2822
    clist->row_list = g_list_next (list);
 
2823
  if (clist->row_list_end == list)
 
2824
    clist->row_list_end = g_list_previous (list);
 
2825
  g_list_remove (list, clist_row);
 
2826
 
 
2827
  if (row < ROW_FROM_YPIXEL (clist, 0))
 
2828
    clist->voffset += clist->row_height + CELL_SPACING;
 
2829
 
 
2830
  if (clist->selection_mode == GTK_SELECTION_BROWSE && !clist->selection &&
 
2831
      clist->focus_row >= 0)
 
2832
    gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
 
2833
                     clist->focus_row, -1, NULL);
 
2834
 
 
2835
  /* toast the row */
 
2836
  row_delete (clist, clist_row);
 
2837
 
 
2838
  /* redraw the row if it isn't frozen */
 
2839
  if (CLIST_UNFROZEN (clist))
 
2840
    {
 
2841
      adjust_adjustments (clist, FALSE);
 
2842
 
 
2843
      if (was_visible)
 
2844
        draw_rows (clist, NULL);
 
2845
    }
 
2846
}
 
2847
 
 
2848
static void
 
2849
real_clear (GtkCList *clist)
 
2850
{
 
2851
  GList *list;
 
2852
  GList *free_list;
 
2853
  gint i;
 
2854
 
 
2855
  g_return_if_fail (GTK_IS_CLIST (clist));
 
2856
 
 
2857
  /* free up the selection list */
 
2858
  g_list_free (clist->selection);
 
2859
  g_list_free (clist->undo_selection);
 
2860
  g_list_free (clist->undo_unselection);
 
2861
 
 
2862
  clist->selection = NULL;
 
2863
  clist->selection_end = NULL;
 
2864
  clist->undo_selection = NULL;
 
2865
  clist->undo_unselection = NULL;
 
2866
  clist->voffset = 0;
 
2867
  clist->focus_row = -1;
 
2868
  clist->anchor = -1;
 
2869
  clist->undo_anchor = -1;
 
2870
  clist->anchor_state = GTK_STATE_SELECTED;
 
2871
  clist->drag_pos = -1;
 
2872
 
 
2873
  /* remove all the rows */
 
2874
  GTK_CLIST_SET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
 
2875
  free_list = clist->row_list;
 
2876
  clist->row_list = NULL;
 
2877
  clist->row_list_end = NULL;
 
2878
  clist->rows = 0;
 
2879
  for (list = free_list; list; list = list->next)
 
2880
    row_delete (clist, GTK_CLIST_ROW (list));
 
2881
  g_list_free (free_list);
 
2882
  GTK_CLIST_UNSET_FLAG (clist, CLIST_AUTO_RESIZE_BLOCKED);
 
2883
  for (i = 0; i < clist->columns; i++)
 
2884
    if (clist->column[i].auto_resize)
 
2885
      {
 
2886
        if (GTK_CLIST_SHOW_TITLES(clist) && clist->column[i].button)
 
2887
          gtk_clist_set_column_width
 
2888
            (clist, i, (clist->column[i].button->requisition.width -
 
2889
                        (CELL_SPACING + (2 * COLUMN_INSET))));
 
2890
        else
 
2891
          gtk_clist_set_column_width (clist, i, 0);
 
2892
      }
 
2893
  /* zero-out the scrollbars */
 
2894
  if (clist->vadjustment)
 
2895
    {
 
2896
      gtk_adjustment_set_value (clist->vadjustment, 0.0);
 
2897
      CLIST_REFRESH (clist);
 
2898
    }
 
2899
  else
 
2900
    gtk_widget_queue_resize (GTK_WIDGET (clist));
 
2901
}
 
2902
 
 
2903
static void
 
2904
real_row_move (GtkCList *clist,
 
2905
               gint      source_row,
 
2906
               gint      dest_row)
 
2907
{
 
2908
  GtkCListRow *clist_row;
 
2909
  GList *list;
 
2910
  gint first, last;
 
2911
  gint d;
 
2912
 
 
2913
  g_return_if_fail (GTK_IS_CLIST (clist));
 
2914
 
 
2915
  if (GTK_CLIST_AUTO_SORT(clist))
 
2916
    return;
 
2917
 
 
2918
  if (source_row < 0 || source_row >= clist->rows ||
 
2919
      dest_row   < 0 || dest_row   >= clist->rows ||
 
2920
      source_row == dest_row)
 
2921
    return;
 
2922
 
 
2923
  gtk_clist_freeze (clist);
 
2924
 
 
2925
  /* unlink source row */
 
2926
  clist_row = ROW_ELEMENT (clist, source_row)->data;
 
2927
  if (source_row == clist->rows - 1)
 
2928
    clist->row_list_end = clist->row_list_end->prev;
 
2929
  clist->row_list = g_list_remove (clist->row_list, clist_row);
 
2930
  clist->rows--;
 
2931
 
 
2932
  /* relink source row */
 
2933
  clist->row_list = g_list_insert (clist->row_list, clist_row, dest_row);
 
2934
  if (dest_row == clist->rows)
 
2935
    clist->row_list_end = clist->row_list_end->next;
 
2936
  clist->rows++;
 
2937
 
 
2938
  /* sync selection */
 
2939
  if (source_row > dest_row)
 
2940
    {
 
2941
      first = dest_row;
 
2942
      last  = source_row;
 
2943
      d = 1;
 
2944
    }
 
2945
  else
 
2946
    {
 
2947
      first = source_row;
 
2948
      last  = dest_row;
 
2949
      d = -1;
 
2950
    }
 
2951
 
 
2952
  for (list = clist->selection; list; list = list->next)
 
2953
    {
 
2954
      if (list->data == GINT_TO_POINTER (source_row))
 
2955
        list->data = GINT_TO_POINTER (dest_row);
 
2956
      else if (first <= GPOINTER_TO_INT (list->data) &&
 
2957
               last >= GPOINTER_TO_INT (list->data))
 
2958
        list->data = GINT_TO_POINTER (GPOINTER_TO_INT (list->data) + d);
 
2959
    }
 
2960
  
 
2961
  if (clist->focus_row == source_row)
 
2962
    clist->focus_row = dest_row;
 
2963
  else if (clist->focus_row > first)
 
2964
    clist->focus_row += d;
 
2965
 
 
2966
  gtk_clist_thaw (clist);
 
2967
}
 
2968
 
 
2969
/* PUBLIC ROW FUNCTIONS
 
2970
 *   gtk_clist_moveto
 
2971
 *   gtk_clist_set_row_height
 
2972
 *   gtk_clist_set_row_data
 
2973
 *   gtk_clist_set_row_data_full
 
2974
 *   gtk_clist_get_row_data
 
2975
 *   gtk_clist_find_row_from_data
 
2976
 *   gtk_clist_swap_rows
 
2977
 *   gtk_clist_row_move
 
2978
 *   gtk_clist_row_is_visible
 
2979
 *   gtk_clist_set_foreground
 
2980
 *   gtk_clist_set_background
 
2981
 */
 
2982
void
 
2983
gtk_clist_moveto (GtkCList *clist,
 
2984
                  gint      row,
 
2985
                  gint      column,
 
2986
                  gfloat    row_align,
 
2987
                  gfloat    col_align)
 
2988
{
 
2989
  g_return_if_fail (GTK_IS_CLIST (clist));
 
2990
 
 
2991
  if (row < -1 || row >= clist->rows)
 
2992
    return;
 
2993
  if (column < -1 || column >= clist->columns)
 
2994
    return;
 
2995
 
 
2996
  row_align = CLAMP (row_align, 0, 1);
 
2997
  col_align = CLAMP (col_align, 0, 1);
 
2998
 
 
2999
  /* adjust horizontal scrollbar */
 
3000
  if (clist->hadjustment && column >= 0)
 
3001
    {
 
3002
      gint x;
 
3003
 
 
3004
      x = (COLUMN_LEFT (clist, column) - CELL_SPACING - COLUMN_INSET -
 
3005
           (col_align * (clist->clist_window_width - 2 * COLUMN_INSET -
 
3006
                         CELL_SPACING - clist->column[column].area.width)));
 
3007
      if (x < 0)
 
3008
        gtk_adjustment_set_value (clist->hadjustment, 0.0);
 
3009
      else if (x > LIST_WIDTH (clist) - clist->clist_window_width)
 
3010
        gtk_adjustment_set_value 
 
3011
          (clist->hadjustment, LIST_WIDTH (clist) - clist->clist_window_width);
 
3012
      else
 
3013
        gtk_adjustment_set_value (clist->hadjustment, x);
 
3014
    }
 
3015
 
 
3016
  /* adjust vertical scrollbar */
 
3017
  if (clist->vadjustment && row >= 0)
 
3018
    move_vertical (clist, row, row_align);
 
3019
}
 
3020
 
 
3021
void
 
3022
gtk_clist_set_row_height (GtkCList *clist,
 
3023
                          guint     height)
 
3024
{
 
3025
  GtkWidget *widget;
 
3026
 
 
3027
  g_return_if_fail (GTK_IS_CLIST (clist));
 
3028
 
 
3029
  widget = GTK_WIDGET (clist);
 
3030
 
 
3031
  if (height > 0)
 
3032
    {
 
3033
      clist->row_height = height;
 
3034
      GTK_CLIST_SET_FLAG (clist, CLIST_ROW_HEIGHT_SET);
 
3035
    }
 
3036
  else
 
3037
    {
 
3038
      GTK_CLIST_UNSET_FLAG (clist, CLIST_ROW_HEIGHT_SET);
 
3039
      clist->row_height = 0;
 
3040
    }
 
3041
 
 
3042
  if (widget->style->font_desc)
 
3043
    {
 
3044
      PangoContext *context = gtk_widget_get_pango_context (widget);
 
3045
      PangoFontMetrics *metrics;
 
3046
 
 
3047
      metrics = pango_context_get_metrics (context,
 
3048
                                           widget->style->font_desc,
 
3049
                                           pango_context_get_language (context));
 
3050
      
 
3051
      if (!GTK_CLIST_ROW_HEIGHT_SET(clist))
 
3052
        {
 
3053
          clist->row_height = (pango_font_metrics_get_ascent (metrics) +
 
3054
                               pango_font_metrics_get_descent (metrics));
 
3055
          clist->row_height = PANGO_PIXELS (clist->row_height);
 
3056
        }
 
3057
 
 
3058
      pango_font_metrics_unref (metrics);
 
3059
    }
 
3060
      
 
3061
  CLIST_REFRESH (clist);
 
3062
}
 
3063
 
 
3064
void
 
3065
gtk_clist_set_row_data (GtkCList *clist,
 
3066
                        gint      row,
 
3067
                        gpointer  data)
 
3068
{
 
3069
  gtk_clist_set_row_data_full (clist, row, data, NULL);
 
3070
}
 
3071
 
 
3072
void
 
3073
gtk_clist_set_row_data_full (GtkCList         *clist,
 
3074
                             gint              row,
 
3075
                             gpointer          data,
 
3076
                             GtkDestroyNotify  destroy)
 
3077
{
 
3078
  GtkCListRow *clist_row;
 
3079
 
 
3080
  g_return_if_fail (GTK_IS_CLIST (clist));
 
3081
 
 
3082
  if (row < 0 || row > (clist->rows - 1))
 
3083
    return;
 
3084
 
 
3085
  clist_row = ROW_ELEMENT (clist, row)->data;
 
3086
 
 
3087
  if (clist_row->destroy)
 
3088
    clist_row->destroy (clist_row->data);
 
3089
  
 
3090
  clist_row->data = data;
 
3091
  clist_row->destroy = destroy;
 
3092
}
 
3093
 
 
3094
gpointer
 
3095
gtk_clist_get_row_data (GtkCList *clist,
 
3096
                        gint      row)
 
3097
{
 
3098
  GtkCListRow *clist_row;
 
3099
 
 
3100
  g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
 
3101
 
 
3102
  if (row < 0 || row > (clist->rows - 1))
 
3103
    return NULL;
 
3104
 
 
3105
  clist_row = ROW_ELEMENT (clist, row)->data;
 
3106
  return clist_row->data;
 
3107
}
 
3108
 
 
3109
gint
 
3110
gtk_clist_find_row_from_data (GtkCList *clist,
 
3111
                              gpointer  data)
 
3112
{
 
3113
  GList *list;
 
3114
  gint n;
 
3115
 
 
3116
  g_return_val_if_fail (GTK_IS_CLIST (clist), -1);
 
3117
 
 
3118
  for (n = 0, list = clist->row_list; list; n++, list = list->next)
 
3119
    if (GTK_CLIST_ROW (list)->data == data)
 
3120
      return n;
 
3121
 
 
3122
  return -1;
 
3123
}
 
3124
 
 
3125
void 
 
3126
gtk_clist_swap_rows (GtkCList *clist,
 
3127
                     gint      row1, 
 
3128
                     gint      row2)
 
3129
{
 
3130
  gint first, last;
 
3131
 
 
3132
  g_return_if_fail (GTK_IS_CLIST (clist));
 
3133
  g_return_if_fail (row1 != row2);
 
3134
 
 
3135
  if (GTK_CLIST_AUTO_SORT(clist))
 
3136
    return;
 
3137
 
 
3138
  gtk_clist_freeze (clist);
 
3139
 
 
3140
  first = MIN (row1, row2);
 
3141
  last  = MAX (row1, row2);
 
3142
 
 
3143
  gtk_clist_row_move (clist, last, first);
 
3144
  gtk_clist_row_move (clist, first + 1, last);
 
3145
  
 
3146
  gtk_clist_thaw (clist);
 
3147
}
 
3148
 
 
3149
void
 
3150
gtk_clist_row_move (GtkCList *clist,
 
3151
                    gint      source_row,
 
3152
                    gint      dest_row)
 
3153
{
 
3154
  g_return_if_fail (GTK_IS_CLIST (clist));
 
3155
 
 
3156
  if (GTK_CLIST_AUTO_SORT(clist))
 
3157
    return;
 
3158
 
 
3159
  if (source_row < 0 || source_row >= clist->rows ||
 
3160
      dest_row   < 0 || dest_row   >= clist->rows ||
 
3161
      source_row == dest_row)
 
3162
    return;
 
3163
 
 
3164
  gtk_signal_emit (GTK_OBJECT (clist), clist_signals[ROW_MOVE],
 
3165
                   source_row, dest_row);
 
3166
}
 
3167
 
 
3168
GtkVisibility
 
3169
gtk_clist_row_is_visible (GtkCList *clist,
 
3170
                          gint      row)
 
3171
{
 
3172
  gint top;
 
3173
 
 
3174
  g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
 
3175
 
 
3176
  if (row < 0 || row >= clist->rows)
 
3177
    return GTK_VISIBILITY_NONE;
 
3178
 
 
3179
  if (clist->row_height == 0)
 
3180
    return GTK_VISIBILITY_NONE;
 
3181
 
 
3182
  if (row < ROW_FROM_YPIXEL (clist, 0))
 
3183
    return GTK_VISIBILITY_NONE;
 
3184
 
 
3185
  if (row > ROW_FROM_YPIXEL (clist, clist->clist_window_height))
 
3186
    return GTK_VISIBILITY_NONE;
 
3187
 
 
3188
  top = ROW_TOP_YPIXEL (clist, row);
 
3189
 
 
3190
  if ((top < 0)
 
3191
      || ((top + clist->row_height) >= clist->clist_window_height))
 
3192
    return GTK_VISIBILITY_PARTIAL;
 
3193
 
 
3194
  return GTK_VISIBILITY_FULL;
 
3195
}
 
3196
 
 
3197
void
 
3198
gtk_clist_set_foreground (GtkCList       *clist,
 
3199
                          gint            row,
 
3200
                          const GdkColor *color)
 
3201
{
 
3202
  GtkCListRow *clist_row;
 
3203
 
 
3204
  g_return_if_fail (GTK_IS_CLIST (clist));
 
3205
 
 
3206
  if (row < 0 || row >= clist->rows)
 
3207
    return;
 
3208
 
 
3209
  clist_row = ROW_ELEMENT (clist, row)->data;
 
3210
 
 
3211
  if (color)
 
3212
    {
 
3213
      clist_row->foreground = *color;
 
3214
      clist_row->fg_set = TRUE;
 
3215
      if (GTK_WIDGET_REALIZED (clist))
 
3216
        gdk_color_alloc (gtk_widget_get_colormap (GTK_WIDGET (clist)),
 
3217
                         &clist_row->foreground);
 
3218
    }
 
3219
  else
 
3220
    clist_row->fg_set = FALSE;
 
3221
 
 
3222
  if (CLIST_UNFROZEN (clist) && gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
 
3223
    GTK_CLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, clist_row);
 
3224
}
 
3225
 
 
3226
void
 
3227
gtk_clist_set_background (GtkCList       *clist,
 
3228
                          gint            row,
 
3229
                          const GdkColor *color)
 
3230
{
 
3231
  GtkCListRow *clist_row;
 
3232
 
 
3233
  g_return_if_fail (GTK_IS_CLIST (clist));
 
3234
 
 
3235
  if (row < 0 || row >= clist->rows)
 
3236
    return;
 
3237
 
 
3238
  clist_row = ROW_ELEMENT (clist, row)->data;
 
3239
 
 
3240
  if (color)
 
3241
    {
 
3242
      clist_row->background = *color;
 
3243
      clist_row->bg_set = TRUE;
 
3244
      if (GTK_WIDGET_REALIZED (clist))
 
3245
        gdk_color_alloc (gtk_widget_get_colormap (GTK_WIDGET (clist)),
 
3246
                         &clist_row->background);
 
3247
    }
 
3248
  else
 
3249
    clist_row->bg_set = FALSE;
 
3250
 
 
3251
  if (CLIST_UNFROZEN (clist)
 
3252
      && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
 
3253
    GTK_CLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, clist_row);
 
3254
}
 
3255
 
 
3256
/* PUBLIC ROW/CELL STYLE FUNCTIONS
 
3257
 *   gtk_clist_set_cell_style
 
3258
 *   gtk_clist_get_cell_style
 
3259
 *   gtk_clist_set_row_style
 
3260
 *   gtk_clist_get_row_style
 
3261
 */
 
3262
void
 
3263
gtk_clist_set_cell_style (GtkCList *clist,
 
3264
                          gint      row,
 
3265
                          gint      column,
 
3266
                          GtkStyle *style)
 
3267
{
 
3268
  GtkRequisition requisition = { 0 };
 
3269
  GtkCListRow *clist_row;
 
3270
 
 
3271
  g_return_if_fail (GTK_IS_CLIST (clist));
 
3272
 
 
3273
  if (row < 0 || row >= clist->rows)
 
3274
    return;
 
3275
  if (column < 0 || column >= clist->columns)
 
3276
    return;
 
3277
 
 
3278
  clist_row = ROW_ELEMENT (clist, row)->data;
 
3279
 
 
3280
  if (clist_row->cell[column].style == style)
 
3281
    return;
 
3282
 
 
3283
  if (clist->column[column].auto_resize &&
 
3284
      !GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
 
3285
    GTK_CLIST_GET_CLASS (clist)->cell_size_request (clist, clist_row,
 
3286
                                                   column, &requisition);
 
3287
 
 
3288
  if (clist_row->cell[column].style)
 
3289
    {
 
3290
      if (GTK_WIDGET_REALIZED (clist))
 
3291
        gtk_style_detach (clist_row->cell[column].style);
 
3292
      g_object_unref (clist_row->cell[column].style);
 
3293
    }
 
3294
 
 
3295
  clist_row->cell[column].style = style;
 
3296
 
 
3297
  if (clist_row->cell[column].style)
 
3298
    {
 
3299
      g_object_ref (clist_row->cell[column].style);
 
3300
      
 
3301
      if (GTK_WIDGET_REALIZED (clist))
 
3302
        clist_row->cell[column].style =
 
3303
          gtk_style_attach (clist_row->cell[column].style,
 
3304
                            clist->clist_window);
 
3305
    }
 
3306
 
 
3307
  column_auto_resize (clist, clist_row, column, requisition.width);
 
3308
 
 
3309
  /* redraw the list if it's not frozen */
 
3310
  if (CLIST_UNFROZEN (clist))
 
3311
    {
 
3312
      if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
 
3313
        GTK_CLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, clist_row);
 
3314
    }
 
3315
}
 
3316
 
 
3317
GtkStyle *
 
3318
gtk_clist_get_cell_style (GtkCList *clist,
 
3319
                          gint      row,
 
3320
                          gint      column)
 
3321
{
 
3322
  GtkCListRow *clist_row;
 
3323
 
 
3324
  g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
 
3325
 
 
3326
  if (row < 0 || row >= clist->rows || column < 0 || column >= clist->columns)
 
3327
    return NULL;
 
3328
 
 
3329
  clist_row = ROW_ELEMENT (clist, row)->data;
 
3330
 
 
3331
  return clist_row->cell[column].style;
 
3332
}
 
3333
 
 
3334
void
 
3335
gtk_clist_set_row_style (GtkCList *clist,
 
3336
                         gint      row,
 
3337
                         GtkStyle *style)
 
3338
{
 
3339
  GtkRequisition requisition;
 
3340
  GtkCListRow *clist_row;
 
3341
  gint *old_width;
 
3342
  gint i;
 
3343
 
 
3344
  g_return_if_fail (GTK_IS_CLIST (clist));
 
3345
 
 
3346
  if (row < 0 || row >= clist->rows)
 
3347
    return;
 
3348
 
 
3349
  clist_row = ROW_ELEMENT (clist, row)->data;
 
3350
 
 
3351
  if (clist_row->style == style)
 
3352
    return;
 
3353
 
 
3354
  old_width = g_new (gint, clist->columns);
 
3355
 
 
3356
  if (!GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
 
3357
    {
 
3358
      for (i = 0; i < clist->columns; i++)
 
3359
        if (clist->column[i].auto_resize)
 
3360
          {
 
3361
            GTK_CLIST_GET_CLASS (clist)->cell_size_request (clist, clist_row,
 
3362
                                                           i, &requisition);
 
3363
            old_width[i] = requisition.width;
 
3364
          }
 
3365
    }
 
3366
 
 
3367
  if (clist_row->style)
 
3368
    {
 
3369
      if (GTK_WIDGET_REALIZED (clist))
 
3370
        gtk_style_detach (clist_row->style);
 
3371
      g_object_unref (clist_row->style);
 
3372
    }
 
3373
 
 
3374
  clist_row->style = style;
 
3375
 
 
3376
  if (clist_row->style)
 
3377
    {
 
3378
      g_object_ref (clist_row->style);
 
3379
      
 
3380
      if (GTK_WIDGET_REALIZED (clist))
 
3381
        clist_row->style = gtk_style_attach (clist_row->style,
 
3382
                                             clist->clist_window);
 
3383
    }
 
3384
 
 
3385
  if (GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
 
3386
    for (i = 0; i < clist->columns; i++)
 
3387
      column_auto_resize (clist, clist_row, i, old_width[i]);
 
3388
 
 
3389
  g_free (old_width);
 
3390
 
 
3391
  /* redraw the list if it's not frozen */
 
3392
  if (CLIST_UNFROZEN (clist))
 
3393
    {
 
3394
      if (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
 
3395
        GTK_CLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, clist_row);
 
3396
    }
 
3397
}
 
3398
 
 
3399
GtkStyle *
 
3400
gtk_clist_get_row_style (GtkCList *clist,
 
3401
                         gint      row)
 
3402
{
 
3403
  GtkCListRow *clist_row;
 
3404
 
 
3405
  g_return_val_if_fail (GTK_IS_CLIST (clist), NULL);
 
3406
 
 
3407
  if (row < 0 || row >= clist->rows)
 
3408
    return NULL;
 
3409
 
 
3410
  clist_row = ROW_ELEMENT (clist, row)->data;
 
3411
 
 
3412
  return clist_row->style;
 
3413
}
 
3414
 
 
3415
/* PUBLIC SELECTION FUNCTIONS
 
3416
 *   gtk_clist_set_selectable
 
3417
 *   gtk_clist_get_selectable
 
3418
 *   gtk_clist_select_row
 
3419
 *   gtk_clist_unselect_row
 
3420
 *   gtk_clist_select_all
 
3421
 *   gtk_clist_unselect_all
 
3422
 *   gtk_clist_undo_selection
 
3423
 */
 
3424
void
 
3425
gtk_clist_set_selectable (GtkCList *clist,
 
3426
                          gint      row,
 
3427
                          gboolean  selectable)
 
3428
{
 
3429
  GtkCListRow *clist_row;
 
3430
 
 
3431
  g_return_if_fail (GTK_IS_CLIST (clist));
 
3432
 
 
3433
  if (row < 0 || row >= clist->rows)
 
3434
    return;
 
3435
 
 
3436
  clist_row = ROW_ELEMENT (clist, row)->data;
 
3437
 
 
3438
  if (selectable == clist_row->selectable)
 
3439
    return;
 
3440
 
 
3441
  clist_row->selectable = selectable;
 
3442
 
 
3443
  if (!selectable && clist_row->state == GTK_STATE_SELECTED)
 
3444
    {
 
3445
      if (clist->anchor >= 0 &&
 
3446
          clist->selection_mode == GTK_SELECTION_MULTIPLE)
 
3447
        {
 
3448
          clist->drag_button = 0;
 
3449
          remove_grab (clist);
 
3450
          GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
 
3451
        }
 
3452
      gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
 
3453
                       row, -1, NULL);
 
3454
    }      
 
3455
}
 
3456
 
 
3457
gboolean
 
3458
gtk_clist_get_selectable (GtkCList *clist,
 
3459
                          gint      row)
 
3460
{
 
3461
  g_return_val_if_fail (GTK_IS_CLIST (clist), FALSE);
 
3462
 
 
3463
  if (row < 0 || row >= clist->rows)
 
3464
    return FALSE;
 
3465
 
 
3466
  return GTK_CLIST_ROW (ROW_ELEMENT (clist, row))->selectable;
 
3467
}
 
3468
 
 
3469
void
 
3470
gtk_clist_select_row (GtkCList *clist,
 
3471
                      gint      row,
 
3472
                      gint      column)
 
3473
{
 
3474
  g_return_if_fail (GTK_IS_CLIST (clist));
 
3475
 
 
3476
  if (row < 0 || row >= clist->rows)
 
3477
    return;
 
3478
  if (column < -1 || column >= clist->columns)
 
3479
    return;
 
3480
 
 
3481
  gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
 
3482
                   row, column, NULL);
 
3483
}
 
3484
 
 
3485
void
 
3486
gtk_clist_unselect_row (GtkCList *clist,
 
3487
                        gint      row,
 
3488
                        gint      column)
 
3489
{
 
3490
  g_return_if_fail (GTK_IS_CLIST (clist));
 
3491
 
 
3492
  if (row < 0 || row >= clist->rows)
 
3493
    return;
 
3494
  if (column < -1 || column >= clist->columns)
 
3495
    return;
 
3496
 
 
3497
  gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
 
3498
                   row, column, NULL);
 
3499
}
 
3500
 
 
3501
void
 
3502
gtk_clist_select_all (GtkCList *clist)
 
3503
{
 
3504
  g_return_if_fail (GTK_IS_CLIST (clist));
 
3505
 
 
3506
  GTK_CLIST_GET_CLASS (clist)->select_all (clist);
 
3507
}
 
3508
 
 
3509
void
 
3510
gtk_clist_unselect_all (GtkCList *clist)
 
3511
{
 
3512
  g_return_if_fail (GTK_IS_CLIST (clist));
 
3513
 
 
3514
  GTK_CLIST_GET_CLASS (clist)->unselect_all (clist);
 
3515
}
 
3516
 
 
3517
void
 
3518
gtk_clist_undo_selection (GtkCList *clist)
 
3519
{
 
3520
  g_return_if_fail (GTK_IS_CLIST (clist));
 
3521
 
 
3522
  if (clist->selection_mode == GTK_SELECTION_MULTIPLE &&
 
3523
      (clist->undo_selection || clist->undo_unselection))
 
3524
    gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNDO_SELECTION]);
 
3525
}
 
3526
 
 
3527
/* PRIVATE SELECTION FUNCTIONS
 
3528
 *   selection_find
 
3529
 *   toggle_row
 
3530
 *   fake_toggle_row
 
3531
 *   toggle_focus_row
 
3532
 *   toggle_add_mode
 
3533
 *   real_select_row
 
3534
 *   real_unselect_row
 
3535
 *   real_select_all
 
3536
 *   real_unselect_all
 
3537
 *   fake_unselect_all
 
3538
 *   real_undo_selection
 
3539
 *   set_anchor
 
3540
 *   resync_selection
 
3541
 *   update_extended_selection
 
3542
 *   start_selection
 
3543
 *   end_selection
 
3544
 *   extend_selection
 
3545
 *   sync_selection
 
3546
 */
 
3547
static GList *
 
3548
selection_find (GtkCList *clist,
 
3549
                gint      row_number,
 
3550
                GList    *row_list_element)
 
3551
{
 
3552
  return g_list_find (clist->selection, GINT_TO_POINTER (row_number));
 
3553
}
 
3554
 
 
3555
static void
 
3556
toggle_row (GtkCList *clist,
 
3557
            gint      row,
 
3558
            gint      column,
 
3559
            GdkEvent *event)
 
3560
{
 
3561
  GtkCListRow *clist_row;
 
3562
 
 
3563
  switch (clist->selection_mode)
 
3564
    {
 
3565
    case GTK_SELECTION_MULTIPLE:
 
3566
    case GTK_SELECTION_SINGLE:
 
3567
      clist_row = ROW_ELEMENT (clist, row)->data;
 
3568
 
 
3569
      if (!clist_row)
 
3570
        return;
 
3571
 
 
3572
      if (clist_row->state == GTK_STATE_SELECTED)
 
3573
        {
 
3574
          gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
 
3575
                           row, column, event);
 
3576
          return;
 
3577
        }
 
3578
    case GTK_SELECTION_BROWSE:
 
3579
      gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
 
3580
                       row, column, event);
 
3581
      break;
 
3582
    default:
 
3583
      g_assert_not_reached ();
 
3584
    }
 
3585
}
 
3586
 
 
3587
static void
 
3588
fake_toggle_row (GtkCList *clist,
 
3589
                 gint      row)
 
3590
{
 
3591
  GList *work;
 
3592
 
 
3593
  work = ROW_ELEMENT (clist, row);
 
3594
 
 
3595
  if (!work || !GTK_CLIST_ROW (work)->selectable)
 
3596
    return;
 
3597
  
 
3598
  if (GTK_CLIST_ROW (work)->state == GTK_STATE_NORMAL)
 
3599
    clist->anchor_state = GTK_CLIST_ROW (work)->state = GTK_STATE_SELECTED;
 
3600
  else
 
3601
    clist->anchor_state = GTK_CLIST_ROW (work)->state = GTK_STATE_NORMAL;
 
3602
  
 
3603
  if (CLIST_UNFROZEN (clist) &&
 
3604
      gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
 
3605
    GTK_CLIST_GET_CLASS (clist)->draw_row (clist, NULL, row,
 
3606
                                          GTK_CLIST_ROW (work));
 
3607
}
 
3608
 
 
3609
static gboolean
 
3610
clist_has_grab (GtkCList *clist)
 
3611
{
 
3612
  return (GTK_WIDGET_HAS_GRAB (clist) &&
 
3613
          gdk_display_pointer_is_grabbed (gtk_widget_get_display (GTK_WIDGET (clist))));
 
3614
}
 
3615
 
 
3616
static void
 
3617
toggle_focus_row (GtkCList *clist)
 
3618
{
 
3619
  g_return_if_fail (clist != 0);
 
3620
  g_return_if_fail (GTK_IS_CLIST (clist));
 
3621
 
 
3622
  if (clist_has_grab (clist) ||
 
3623
      clist->focus_row < 0 || clist->focus_row >= clist->rows)
 
3624
    return;
 
3625
 
 
3626
  switch (clist->selection_mode)
 
3627
    {
 
3628
    case  GTK_SELECTION_SINGLE:
 
3629
      toggle_row (clist, clist->focus_row, 0, NULL);
 
3630
      break;
 
3631
    case GTK_SELECTION_MULTIPLE:
 
3632
      g_list_free (clist->undo_selection);
 
3633
      g_list_free (clist->undo_unselection);
 
3634
      clist->undo_selection = NULL;
 
3635
      clist->undo_unselection = NULL;
 
3636
 
 
3637
      clist->anchor = clist->focus_row;
 
3638
      clist->drag_pos = clist->focus_row;
 
3639
      clist->undo_anchor = clist->focus_row;
 
3640
      
 
3641
      if (GTK_CLIST_ADD_MODE(clist))
 
3642
        fake_toggle_row (clist, clist->focus_row);
 
3643
      else
 
3644
        GTK_CLIST_GET_CLASS (clist)->fake_unselect_all (clist,clist->focus_row);
 
3645
 
 
3646
      GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
 
3647
      break;
 
3648
    default:
 
3649
      break;
 
3650
    }
 
3651
}
 
3652
 
 
3653
static void
 
3654
toggle_add_mode (GtkCList *clist)
 
3655
{
 
3656
  g_return_if_fail (clist != 0);
 
3657
  g_return_if_fail (GTK_IS_CLIST (clist));
 
3658
  
 
3659
  if (clist_has_grab (clist) ||
 
3660
      clist->selection_mode != GTK_SELECTION_MULTIPLE)
 
3661
    return;
 
3662
 
 
3663
  gtk_clist_draw_focus (GTK_WIDGET (clist));
 
3664
  if (!GTK_CLIST_ADD_MODE(clist))
 
3665
    {
 
3666
      GTK_CLIST_SET_FLAG (clist, CLIST_ADD_MODE);
 
3667
      gdk_gc_set_line_attributes (clist->xor_gc, 1,
 
3668
                                  GDK_LINE_ON_OFF_DASH, 0, 0);
 
3669
      gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
 
3670
    }
 
3671
  else
 
3672
    {
 
3673
      GTK_CLIST_UNSET_FLAG (clist, CLIST_ADD_MODE);
 
3674
      gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_SOLID, 0, 0);
 
3675
      clist->anchor_state = GTK_STATE_SELECTED;
 
3676
    }
 
3677
  gtk_clist_draw_focus (GTK_WIDGET (clist));
 
3678
}
 
3679
 
 
3680
static void
 
3681
real_select_row (GtkCList *clist,
 
3682
                 gint      row,
 
3683
                 gint      column,
 
3684
                 GdkEvent *event)
 
3685
{
 
3686
  GtkCListRow *clist_row;
 
3687
  GList *list;
 
3688
  gint sel_row;
 
3689
  gboolean row_selected;
 
3690
 
 
3691
  g_return_if_fail (GTK_IS_CLIST (clist));
 
3692
 
 
3693
  if (row < 0 || row > (clist->rows - 1))
 
3694
    return;
 
3695
 
 
3696
  switch (clist->selection_mode)
 
3697
    {
 
3698
    case GTK_SELECTION_SINGLE:
 
3699
    case GTK_SELECTION_BROWSE:
 
3700
 
 
3701
      row_selected = FALSE;
 
3702
      list = clist->selection;
 
3703
 
 
3704
      while (list)
 
3705
        {
 
3706
          sel_row = GPOINTER_TO_INT (list->data);
 
3707
          list = list->next;
 
3708
 
 
3709
          if (row == sel_row)
 
3710
            row_selected = TRUE;
 
3711
          else
 
3712
            gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW], 
 
3713
                             sel_row, column, event);
 
3714
        }
 
3715
 
 
3716
      if (row_selected)
 
3717
        return;
 
3718
      
 
3719
    default:
 
3720
      break;
 
3721
    }
 
3722
 
 
3723
  clist_row = ROW_ELEMENT (clist, row)->data;
 
3724
 
 
3725
  if (clist_row->state != GTK_STATE_NORMAL || !clist_row->selectable)
 
3726
    return;
 
3727
 
 
3728
  clist_row->state = GTK_STATE_SELECTED;
 
3729
  if (!clist->selection)
 
3730
    {
 
3731
      clist->selection = g_list_append (clist->selection,
 
3732
                                        GINT_TO_POINTER (row));
 
3733
      clist->selection_end = clist->selection;
 
3734
    }
 
3735
  else
 
3736
    clist->selection_end = 
 
3737
      g_list_append (clist->selection_end, GINT_TO_POINTER (row))->next;
 
3738
  
 
3739
  if (CLIST_UNFROZEN (clist)
 
3740
      && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
 
3741
    GTK_CLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, clist_row);
 
3742
}
 
3743
 
 
3744
static void
 
3745
real_unselect_row (GtkCList *clist,
 
3746
                   gint      row,
 
3747
                   gint      column,
 
3748
                   GdkEvent *event)
 
3749
{
 
3750
  GtkCListRow *clist_row;
 
3751
 
 
3752
  g_return_if_fail (GTK_IS_CLIST (clist));
 
3753
 
 
3754
  if (row < 0 || row > (clist->rows - 1))
 
3755
    return;
 
3756
 
 
3757
  clist_row = ROW_ELEMENT (clist, row)->data;
 
3758
 
 
3759
  if (clist_row->state == GTK_STATE_SELECTED)
 
3760
    {
 
3761
      clist_row->state = GTK_STATE_NORMAL;
 
3762
 
 
3763
      if (clist->selection_end && 
 
3764
          clist->selection_end->data == GINT_TO_POINTER (row))
 
3765
        clist->selection_end = clist->selection_end->prev;
 
3766
 
 
3767
      clist->selection = g_list_remove (clist->selection,
 
3768
                                        GINT_TO_POINTER (row));
 
3769
      
 
3770
      if (CLIST_UNFROZEN (clist)
 
3771
          && (gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE))
 
3772
        GTK_CLIST_GET_CLASS (clist)->draw_row (clist, NULL, row, clist_row);
 
3773
    }
 
3774
}
 
3775
 
 
3776
static void
 
3777
real_select_all (GtkCList *clist)
 
3778
{
 
3779
  g_return_if_fail (GTK_IS_CLIST (clist));
 
3780
 
 
3781
  if (clist_has_grab (clist))
 
3782
    return;
 
3783
 
 
3784
  switch (clist->selection_mode)
 
3785
    {
 
3786
    case GTK_SELECTION_SINGLE:
 
3787
    case GTK_SELECTION_BROWSE:
 
3788
      return;
 
3789
 
 
3790
    case GTK_SELECTION_MULTIPLE:
 
3791
      g_list_free (clist->undo_selection);
 
3792
      g_list_free (clist->undo_unselection);
 
3793
      clist->undo_selection = NULL;
 
3794
      clist->undo_unselection = NULL;
 
3795
          
 
3796
      if (clist->rows &&
 
3797
          ((GtkCListRow *) (clist->row_list->data))->state !=
 
3798
          GTK_STATE_SELECTED)
 
3799
        fake_toggle_row (clist, 0);
 
3800
 
 
3801
      clist->anchor_state =  GTK_STATE_SELECTED;
 
3802
      clist->anchor = 0;
 
3803
      clist->drag_pos = 0;
 
3804
      clist->undo_anchor = clist->focus_row;
 
3805
      update_extended_selection (clist, clist->rows);
 
3806
      GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
 
3807
      return;
 
3808
    default:
 
3809
      g_assert_not_reached ();
 
3810
    }
 
3811
}
 
3812
 
 
3813
static void
 
3814
real_unselect_all (GtkCList *clist)
 
3815
{
 
3816
  GList *list;
 
3817
  gint i;
 
3818
 
 
3819
  g_return_if_fail (GTK_IS_CLIST (clist));
 
3820
 
 
3821
  if (clist_has_grab (clist))
 
3822
    return;
 
3823
 
 
3824
  switch (clist->selection_mode)
 
3825
    {
 
3826
    case GTK_SELECTION_BROWSE:
 
3827
      if (clist->focus_row >= 0)
 
3828
        {
 
3829
          gtk_signal_emit (GTK_OBJECT (clist),
 
3830
                           clist_signals[SELECT_ROW],
 
3831
                           clist->focus_row, -1, NULL);
 
3832
          return;
 
3833
        }
 
3834
      break;
 
3835
    case GTK_SELECTION_MULTIPLE:
 
3836
      g_list_free (clist->undo_selection);
 
3837
      g_list_free (clist->undo_unselection);
 
3838
      clist->undo_selection = NULL;
 
3839
      clist->undo_unselection = NULL;
 
3840
 
 
3841
      clist->anchor = -1;
 
3842
      clist->drag_pos = -1;
 
3843
      clist->undo_anchor = clist->focus_row;
 
3844
      break;
 
3845
    default:
 
3846
      break;
 
3847
    }
 
3848
 
 
3849
  list = clist->selection;
 
3850
  while (list)
 
3851
    {
 
3852
      i = GPOINTER_TO_INT (list->data);
 
3853
      list = list->next;
 
3854
      gtk_signal_emit (GTK_OBJECT (clist),
 
3855
                       clist_signals[UNSELECT_ROW], i, -1, NULL);
 
3856
    }
 
3857
}
 
3858
 
 
3859
static void
 
3860
fake_unselect_all (GtkCList *clist,
 
3861
                   gint      row)
 
3862
{
 
3863
  GList *list;
 
3864
  GList *work;
 
3865
  gint i;
 
3866
 
 
3867
  if (row >= 0 && (work = ROW_ELEMENT (clist, row)))
 
3868
    {
 
3869
      if (GTK_CLIST_ROW (work)->state == GTK_STATE_NORMAL &&
 
3870
          GTK_CLIST_ROW (work)->selectable)
 
3871
        {
 
3872
          GTK_CLIST_ROW (work)->state = GTK_STATE_SELECTED;
 
3873
          
 
3874
          if (CLIST_UNFROZEN (clist) &&
 
3875
              gtk_clist_row_is_visible (clist, row) != GTK_VISIBILITY_NONE)
 
3876
            GTK_CLIST_GET_CLASS (clist)->draw_row (clist, NULL, row,
 
3877
                                                  GTK_CLIST_ROW (work));
 
3878
        }  
 
3879
    }
 
3880
 
 
3881
  clist->undo_selection = clist->selection;
 
3882
  clist->selection = NULL;
 
3883
  clist->selection_end = NULL;
 
3884
 
 
3885
  for (list = clist->undo_selection; list; list = list->next)
 
3886
    {
 
3887
      if ((i = GPOINTER_TO_INT (list->data)) == row ||
 
3888
          !(work = g_list_nth (clist->row_list, i)))
 
3889
        continue;
 
3890
 
 
3891
      GTK_CLIST_ROW (work)->state = GTK_STATE_NORMAL;
 
3892
      if (CLIST_UNFROZEN (clist) &&
 
3893
          gtk_clist_row_is_visible (clist, i) != GTK_VISIBILITY_NONE)
 
3894
        GTK_CLIST_GET_CLASS (clist)->draw_row (clist, NULL, i,
 
3895
                                              GTK_CLIST_ROW (work));
 
3896
    }
 
3897
}
 
3898
 
 
3899
static void
 
3900
real_undo_selection (GtkCList *clist)
 
3901
{
 
3902
  GList *work;
 
3903
 
 
3904
  g_return_if_fail (GTK_IS_CLIST (clist));
 
3905
 
 
3906
  if (clist_has_grab (clist) ||
 
3907
      clist->selection_mode != GTK_SELECTION_MULTIPLE)
 
3908
    return;
 
3909
 
 
3910
  GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
 
3911
 
 
3912
  if (!(clist->undo_selection || clist->undo_unselection))
 
3913
    {
 
3914
      gtk_clist_unselect_all (clist);
 
3915
      return;
 
3916
    }
 
3917
 
 
3918
  for (work = clist->undo_selection; work; work = work->next)
 
3919
    gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
 
3920
                     GPOINTER_TO_INT (work->data), -1, NULL);
 
3921
 
 
3922
  for (work = clist->undo_unselection; work; work = work->next)
 
3923
    {
 
3924
      /* g_print ("unselect %d\n",GPOINTER_TO_INT (work->data)); */
 
3925
      gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW], 
 
3926
                       GPOINTER_TO_INT (work->data), -1, NULL);
 
3927
    }
 
3928
 
 
3929
  if (GTK_WIDGET_HAS_FOCUS(clist) && clist->focus_row != clist->undo_anchor)
 
3930
    {
 
3931
      gtk_clist_draw_focus (GTK_WIDGET (clist));
 
3932
      clist->focus_row = clist->undo_anchor;
 
3933
      gtk_clist_draw_focus (GTK_WIDGET (clist));
 
3934
    }
 
3935
  else
 
3936
    clist->focus_row = clist->undo_anchor;
 
3937
  
 
3938
  clist->undo_anchor = -1;
 
3939
 
 
3940
  g_list_free (clist->undo_selection);
 
3941
  g_list_free (clist->undo_unselection);
 
3942
  clist->undo_selection = NULL;
 
3943
  clist->undo_unselection = NULL;
 
3944
 
 
3945
  if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
 
3946
      clist->clist_window_height)
 
3947
    gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
 
3948
  else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
 
3949
    gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
 
3950
}
 
3951
 
 
3952
static void
 
3953
set_anchor (GtkCList *clist,
 
3954
            gboolean  add_mode,
 
3955
            gint      anchor,
 
3956
            gint      undo_anchor)
 
3957
{
 
3958
  g_return_if_fail (GTK_IS_CLIST (clist));
 
3959
  
 
3960
  if (clist->selection_mode != GTK_SELECTION_MULTIPLE || clist->anchor >= 0)
 
3961
    return;
 
3962
 
 
3963
  g_list_free (clist->undo_selection);
 
3964
  g_list_free (clist->undo_unselection);
 
3965
  clist->undo_selection = NULL;
 
3966
  clist->undo_unselection = NULL;
 
3967
 
 
3968
  if (add_mode)
 
3969
    fake_toggle_row (clist, anchor);
 
3970
  else
 
3971
    {
 
3972
      GTK_CLIST_GET_CLASS (clist)->fake_unselect_all (clist, anchor);
 
3973
      clist->anchor_state = GTK_STATE_SELECTED;
 
3974
    }
 
3975
 
 
3976
  clist->anchor = anchor;
 
3977
  clist->drag_pos = anchor;
 
3978
  clist->undo_anchor = undo_anchor;
 
3979
}
 
3980
 
 
3981
static void
 
3982
resync_selection (GtkCList *clist,
 
3983
                  GdkEvent *event)
 
3984
{
 
3985
  gint i;
 
3986
  gint e;
 
3987
  gint row;
 
3988
  GList *list;
 
3989
  GtkCListRow *clist_row;
 
3990
 
 
3991
  if (clist->selection_mode != GTK_SELECTION_MULTIPLE)
 
3992
    return;
 
3993
 
 
3994
  if (clist->anchor < 0 || clist->drag_pos < 0)
 
3995
    return;
 
3996
 
 
3997
  gtk_clist_freeze (clist);
 
3998
 
 
3999
  i = MIN (clist->anchor, clist->drag_pos);
 
4000
  e = MAX (clist->anchor, clist->drag_pos);
 
4001
 
 
4002
  if (clist->undo_selection)
 
4003
    {
 
4004
      list = clist->selection;
 
4005
      clist->selection = clist->undo_selection;
 
4006
      clist->selection_end = g_list_last (clist->selection);
 
4007
      clist->undo_selection = list;
 
4008
      list = clist->selection;
 
4009
      while (list)
 
4010
        {
 
4011
          row = GPOINTER_TO_INT (list->data);
 
4012
          list = list->next;
 
4013
          if (row < i || row > e)
 
4014
            {
 
4015
              clist_row = g_list_nth (clist->row_list, row)->data;
 
4016
              if (clist_row->selectable)
 
4017
                {
 
4018
                  clist_row->state = GTK_STATE_SELECTED;
 
4019
                  gtk_signal_emit (GTK_OBJECT (clist),
 
4020
                                   clist_signals[UNSELECT_ROW],
 
4021
                                   row, -1, event);
 
4022
                  clist->undo_selection = g_list_prepend
 
4023
                    (clist->undo_selection, GINT_TO_POINTER (row));
 
4024
                }
 
4025
            }
 
4026
        }
 
4027
    }    
 
4028
 
 
4029
  if (clist->anchor < clist->drag_pos)
 
4030
    {
 
4031
      for (list = g_list_nth (clist->row_list, i); i <= e;
 
4032
           i++, list = list->next)
 
4033
        if (GTK_CLIST_ROW (list)->selectable)
 
4034
          {
 
4035
            if (g_list_find (clist->selection, GINT_TO_POINTER(i)))
 
4036
              {
 
4037
                if (GTK_CLIST_ROW (list)->state == GTK_STATE_NORMAL)
 
4038
                  {
 
4039
                    GTK_CLIST_ROW (list)->state = GTK_STATE_SELECTED;
 
4040
                    gtk_signal_emit (GTK_OBJECT (clist),
 
4041
                                     clist_signals[UNSELECT_ROW],
 
4042
                                     i, -1, event);
 
4043
                    clist->undo_selection =
 
4044
                      g_list_prepend (clist->undo_selection,
 
4045
                                      GINT_TO_POINTER (i));
 
4046
                  }
 
4047
              }
 
4048
            else if (GTK_CLIST_ROW (list)->state == GTK_STATE_SELECTED)
 
4049
              {
 
4050
                GTK_CLIST_ROW (list)->state = GTK_STATE_NORMAL;
 
4051
                clist->undo_unselection =
 
4052
                  g_list_prepend (clist->undo_unselection,
 
4053
                                  GINT_TO_POINTER (i));
 
4054
              }
 
4055
          }
 
4056
    }
 
4057
  else
 
4058
    {
 
4059
      for (list = g_list_nth (clist->row_list, e); i <= e;
 
4060
           e--, list = list->prev)
 
4061
        if (GTK_CLIST_ROW (list)->selectable)
 
4062
          {
 
4063
            if (g_list_find (clist->selection, GINT_TO_POINTER(e)))
 
4064
              {
 
4065
                if (GTK_CLIST_ROW (list)->state == GTK_STATE_NORMAL)
 
4066
                  {
 
4067
                    GTK_CLIST_ROW (list)->state = GTK_STATE_SELECTED;
 
4068
                    gtk_signal_emit (GTK_OBJECT (clist),
 
4069
                                     clist_signals[UNSELECT_ROW],
 
4070
                                     e, -1, event);
 
4071
                    clist->undo_selection =
 
4072
                      g_list_prepend (clist->undo_selection,
 
4073
                                      GINT_TO_POINTER (e));
 
4074
                  }
 
4075
              }
 
4076
            else if (GTK_CLIST_ROW (list)->state == GTK_STATE_SELECTED)
 
4077
              {
 
4078
                GTK_CLIST_ROW (list)->state = GTK_STATE_NORMAL;
 
4079
                clist->undo_unselection =
 
4080
                  g_list_prepend (clist->undo_unselection,
 
4081
                                  GINT_TO_POINTER (e));
 
4082
              }
 
4083
          }
 
4084
    }
 
4085
  
 
4086
  clist->undo_unselection = g_list_reverse (clist->undo_unselection);
 
4087
  for (list = clist->undo_unselection; list; list = list->next)
 
4088
    gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
 
4089
                     GPOINTER_TO_INT (list->data), -1, event);
 
4090
 
 
4091
  clist->anchor = -1;
 
4092
  clist->drag_pos = -1;
 
4093
 
 
4094
  gtk_clist_thaw (clist);
 
4095
}
 
4096
 
 
4097
static void
 
4098
update_extended_selection (GtkCList *clist,
 
4099
                           gint      row)
 
4100
{
 
4101
  gint i;
 
4102
  GList *list;
 
4103
  GdkRectangle area;
 
4104
  gint s1 = -1;
 
4105
  gint s2 = -1;
 
4106
  gint e1 = -1;
 
4107
  gint e2 = -1;
 
4108
  gint y1 = clist->clist_window_height;
 
4109
  gint y2 = clist->clist_window_height;
 
4110
  gint h1 = 0;
 
4111
  gint h2 = 0;
 
4112
  gint top;
 
4113
 
 
4114
  if (clist->selection_mode != GTK_SELECTION_MULTIPLE || clist->anchor == -1)
 
4115
    return;
 
4116
 
 
4117
  if (row < 0)
 
4118
    row = 0;
 
4119
  if (row >= clist->rows)
 
4120
    row = clist->rows - 1;
 
4121
 
 
4122
  /* extending downwards */
 
4123
  if (row > clist->drag_pos && clist->anchor <= clist->drag_pos)
 
4124
    {
 
4125
      s2 = clist->drag_pos + 1;
 
4126
      e2 = row;
 
4127
    }
 
4128
  /* extending upwards */
 
4129
  else if (row < clist->drag_pos && clist->anchor >= clist->drag_pos)
 
4130
    {
 
4131
      s2 = row;
 
4132
      e2 = clist->drag_pos - 1;
 
4133
    }
 
4134
  else if (row < clist->drag_pos && clist->anchor < clist->drag_pos)
 
4135
    {
 
4136
      e1 = clist->drag_pos;
 
4137
      /* row and drag_pos on different sides of anchor :
 
4138
         take back the selection between anchor and drag_pos,
 
4139
         select between anchor and row */
 
4140
      if (row < clist->anchor)
 
4141
        {
 
4142
          s1 = clist->anchor + 1;
 
4143
          s2 = row;
 
4144
          e2 = clist->anchor - 1;
 
4145
        }
 
4146
      /* take back the selection between anchor and drag_pos */
 
4147
      else
 
4148
        s1 = row + 1;
 
4149
    }
 
4150
  else if (row > clist->drag_pos && clist->anchor > clist->drag_pos)
 
4151
    {
 
4152
      s1 = clist->drag_pos;
 
4153
      /* row and drag_pos on different sides of anchor :
 
4154
         take back the selection between anchor and drag_pos,
 
4155
         select between anchor and row */
 
4156
      if (row > clist->anchor)
 
4157
        {
 
4158
          e1 = clist->anchor - 1;
 
4159
          s2 = clist->anchor + 1;
 
4160
          e2 = row;
 
4161
        }
 
4162
      /* take back the selection between anchor and drag_pos */
 
4163
      else
 
4164
        e1 = row - 1;
 
4165
    }
 
4166
 
 
4167
  clist->drag_pos = row;
 
4168
 
 
4169
  area.x = 0;
 
4170
  area.width = clist->clist_window_width;
 
4171
 
 
4172
  /* restore the elements between s1 and e1 */
 
4173
  if (s1 >= 0)
 
4174
    {
 
4175
      for (i = s1, list = g_list_nth (clist->row_list, i); i <= e1;
 
4176
           i++, list = list->next)
 
4177
        if (GTK_CLIST_ROW (list)->selectable)
 
4178
          {
 
4179
            if (GTK_CLIST_GET_CLASS (clist)->selection_find (clist, i, list))
 
4180
              GTK_CLIST_ROW (list)->state = GTK_STATE_SELECTED;
 
4181
            else
 
4182
              GTK_CLIST_ROW (list)->state = GTK_STATE_NORMAL;
 
4183
          }
 
4184
 
 
4185
      top = ROW_TOP_YPIXEL (clist, clist->focus_row);
 
4186
 
 
4187
      if (top + clist->row_height <= 0)
 
4188
        {
 
4189
          area.y = 0;
 
4190
          area.height = ROW_TOP_YPIXEL (clist, e1) + clist->row_height;
 
4191
          draw_rows (clist, &area);
 
4192
          gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
 
4193
        }
 
4194
      else if (top >= clist->clist_window_height)
 
4195
        {
 
4196
          area.y = ROW_TOP_YPIXEL (clist, s1) - 1;
 
4197
          area.height = clist->clist_window_height - area.y;
 
4198
          draw_rows (clist, &area);
 
4199
          gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
 
4200
        }
 
4201
      else if (top < 0)
 
4202
        gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
 
4203
      else if (top + clist->row_height > clist->clist_window_height)
 
4204
        gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
 
4205
 
 
4206
      y1 = ROW_TOP_YPIXEL (clist, s1) - 1;
 
4207
      h1 = (e1 - s1 + 1) * (clist->row_height + CELL_SPACING);
 
4208
    }
 
4209
 
 
4210
  /* extend the selection between s2 and e2 */
 
4211
  if (s2 >= 0)
 
4212
    {
 
4213
      for (i = s2, list = g_list_nth (clist->row_list, i); i <= e2;
 
4214
           i++, list = list->next)
 
4215
        if (GTK_CLIST_ROW (list)->selectable &&
 
4216
            GTK_CLIST_ROW (list)->state != clist->anchor_state)
 
4217
          GTK_CLIST_ROW (list)->state = clist->anchor_state;
 
4218
 
 
4219
      top = ROW_TOP_YPIXEL (clist, clist->focus_row);
 
4220
 
 
4221
      if (top + clist->row_height <= 0)
 
4222
        {
 
4223
          area.y = 0;
 
4224
          area.height = ROW_TOP_YPIXEL (clist, e2) + clist->row_height;
 
4225
          draw_rows (clist, &area);
 
4226
          gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
 
4227
        }
 
4228
      else if (top >= clist->clist_window_height)
 
4229
        {
 
4230
          area.y = ROW_TOP_YPIXEL (clist, s2) - 1;
 
4231
          area.height = clist->clist_window_height - area.y;
 
4232
          draw_rows (clist, &area);
 
4233
          gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
 
4234
        }
 
4235
      else if (top < 0)
 
4236
        gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
 
4237
      else if (top + clist->row_height > clist->clist_window_height)
 
4238
        gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
 
4239
 
 
4240
      y2 = ROW_TOP_YPIXEL (clist, s2) - 1;
 
4241
      h2 = (e2 - s2 + 1) * (clist->row_height + CELL_SPACING);
 
4242
    }
 
4243
 
 
4244
  area.y = MAX (0, MIN (y1, y2));
 
4245
  if (area.y > clist->clist_window_height)
 
4246
    area.y = 0;
 
4247
  area.height = MIN (clist->clist_window_height, h1 + h2);
 
4248
  if (s1 >= 0 && s2 >= 0)
 
4249
    area.height += (clist->row_height + CELL_SPACING);
 
4250
  draw_rows (clist, &area);
 
4251
}
 
4252
 
 
4253
static void
 
4254
start_selection (GtkCList *clist)
 
4255
{
 
4256
  g_return_if_fail (GTK_IS_CLIST (clist));
 
4257
 
 
4258
  if (clist_has_grab (clist))
 
4259
    return;
 
4260
 
 
4261
  set_anchor (clist, GTK_CLIST_ADD_MODE(clist), clist->focus_row,
 
4262
              clist->focus_row);
 
4263
}
 
4264
 
 
4265
static void
 
4266
end_selection (GtkCList *clist)
 
4267
{
 
4268
  g_return_if_fail (GTK_IS_CLIST (clist));
 
4269
 
 
4270
  if (gdk_display_pointer_is_grabbed (gtk_widget_get_display (GTK_WIDGET (clist))) &&
 
4271
      GTK_WIDGET_HAS_FOCUS (clist))
 
4272
    return;
 
4273
 
 
4274
  GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
 
4275
}
 
4276
 
 
4277
static void
 
4278
extend_selection (GtkCList      *clist,
 
4279
                  GtkScrollType  scroll_type,
 
4280
                  gfloat         position,
 
4281
                  gboolean       auto_start_selection)
 
4282
{
 
4283
  g_return_if_fail (GTK_IS_CLIST (clist));
 
4284
 
 
4285
  if (clist_has_grab (clist) ||
 
4286
      clist->selection_mode != GTK_SELECTION_MULTIPLE)
 
4287
    return;
 
4288
 
 
4289
  if (auto_start_selection)
 
4290
    set_anchor (clist, GTK_CLIST_ADD_MODE(clist), clist->focus_row,
 
4291
                clist->focus_row);
 
4292
  else if (clist->anchor == -1)
 
4293
    return;
 
4294
 
 
4295
  move_focus_row (clist, scroll_type, position);
 
4296
 
 
4297
  if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
 
4298
      clist->clist_window_height)
 
4299
    gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
 
4300
  else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
 
4301
    gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
 
4302
 
 
4303
  update_extended_selection (clist, clist->focus_row);
 
4304
}
 
4305
 
 
4306
static void
 
4307
sync_selection (GtkCList *clist,
 
4308
                gint      row,
 
4309
                gint      mode)
 
4310
{
 
4311
  GList *list;
 
4312
  gint d;
 
4313
 
 
4314
  if (mode == SYNC_INSERT)
 
4315
    d = 1;
 
4316
  else
 
4317
    d = -1;
 
4318
      
 
4319
  if (clist->focus_row >= row)
 
4320
    {
 
4321
      if (d > 0 || clist->focus_row > row)
 
4322
        clist->focus_row += d;
 
4323
      if (clist->focus_row == -1 && clist->rows >= 1)
 
4324
        clist->focus_row = 0;
 
4325
      else if (d < 0 && clist->focus_row >= clist->rows - 1)
 
4326
        clist->focus_row = clist->rows - 2;
 
4327
      else if (clist->focus_row >= clist->rows) /* Paranoia */
 
4328
        clist->focus_row = clist->rows - 1;
 
4329
    }
 
4330
 
 
4331
  GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
 
4332
 
 
4333
  g_list_free (clist->undo_selection);
 
4334
  g_list_free (clist->undo_unselection);
 
4335
  clist->undo_selection = NULL;
 
4336
  clist->undo_unselection = NULL;
 
4337
 
 
4338
  clist->anchor = -1;
 
4339
  clist->drag_pos = -1;
 
4340
  clist->undo_anchor = clist->focus_row;
 
4341
 
 
4342
  list = clist->selection;
 
4343
 
 
4344
  while (list)
 
4345
    {
 
4346
      if (GPOINTER_TO_INT (list->data) >= row)
 
4347
        list->data = ((gchar*) list->data) + d;
 
4348
      list = list->next;
 
4349
    }
 
4350
}
 
4351
 
 
4352
/* GTKOBJECT
 
4353
 *   gtk_clist_destroy
 
4354
 *   gtk_clist_finalize
 
4355
 */
 
4356
static void
 
4357
gtk_clist_destroy (GtkObject *object)
 
4358
{
 
4359
  gint i;
 
4360
  GtkCList *clist;
 
4361
 
 
4362
  g_return_if_fail (GTK_IS_CLIST (object));
 
4363
 
 
4364
  clist = GTK_CLIST (object);
 
4365
 
 
4366
  /* freeze the list */
 
4367
  clist->freeze_count++;
 
4368
 
 
4369
  /* get rid of all the rows */
 
4370
  gtk_clist_clear (clist);
 
4371
 
 
4372
  /* Since we don't have a _remove method, unparent the children
 
4373
   * instead of destroying them so the focus will be unset properly.
 
4374
   * (For other containers, the _remove method takes care of the
 
4375
   * unparent) The destroy will happen when the refcount drops
 
4376
   * to zero.
 
4377
   */
 
4378
 
 
4379
  /* unref adjustments */
 
4380
  if (clist->hadjustment)
 
4381
    {
 
4382
      gtk_signal_disconnect_by_data (GTK_OBJECT (clist->hadjustment), clist);
 
4383
      gtk_object_unref (GTK_OBJECT (clist->hadjustment));
 
4384
      clist->hadjustment = NULL;
 
4385
    }
 
4386
  if (clist->vadjustment)
 
4387
    {
 
4388
      gtk_signal_disconnect_by_data (GTK_OBJECT (clist->vadjustment), clist);
 
4389
      gtk_object_unref (GTK_OBJECT (clist->vadjustment));
 
4390
      clist->vadjustment = NULL;
 
4391
    }
 
4392
 
 
4393
  remove_grab (clist);
 
4394
 
 
4395
  /* destroy the column buttons */
 
4396
  for (i = 0; i < clist->columns; i++)
 
4397
    if (clist->column[i].button)
 
4398
      {
 
4399
        gtk_widget_unparent (clist->column[i].button);
 
4400
        clist->column[i].button = NULL;
 
4401
      }
 
4402
 
 
4403
  if (GTK_OBJECT_CLASS (parent_class)->destroy)
 
4404
    (*GTK_OBJECT_CLASS (parent_class)->destroy) (object);
 
4405
}
 
4406
 
 
4407
static void
 
4408
gtk_clist_finalize (GObject *object)
 
4409
{
 
4410
  GtkCList *clist;
 
4411
 
 
4412
  g_return_if_fail (GTK_IS_CLIST (object));
 
4413
 
 
4414
  clist = GTK_CLIST (object);
 
4415
 
 
4416
  columns_delete (clist);
 
4417
 
 
4418
  G_OBJECT_CLASS (parent_class)->finalize (object);
 
4419
}
 
4420
 
 
4421
/* GTKWIDGET
 
4422
 *   gtk_clist_realize
 
4423
 *   gtk_clist_unrealize
 
4424
 *   gtk_clist_map
 
4425
 *   gtk_clist_unmap
 
4426
 *   gtk_clist_expose
 
4427
 *   gtk_clist_style_set
 
4428
 *   gtk_clist_button_press
 
4429
 *   gtk_clist_button_release
 
4430
 *   gtk_clist_motion
 
4431
 *   gtk_clist_size_request
 
4432
 *   gtk_clist_size_allocate
 
4433
 */
 
4434
static void
 
4435
gtk_clist_realize (GtkWidget *widget)
 
4436
{
 
4437
  GtkCList *clist;
 
4438
  GdkWindowAttr attributes;
 
4439
  GdkGCValues values;
 
4440
  GtkCListRow *clist_row;
 
4441
  GList *list;
 
4442
  gint attributes_mask;
 
4443
  gint border_width;
 
4444
  gint i;
 
4445
  gint j;
 
4446
 
 
4447
  g_return_if_fail (GTK_IS_CLIST (widget));
 
4448
 
 
4449
  clist = GTK_CLIST (widget);
 
4450
 
 
4451
  GTK_WIDGET_SET_FLAGS (widget, GTK_REALIZED);
 
4452
 
 
4453
  border_width = GTK_CONTAINER (widget)->border_width;
 
4454
  
 
4455
  attributes.window_type = GDK_WINDOW_CHILD;
 
4456
  attributes.x = widget->allocation.x + border_width;
 
4457
  attributes.y = widget->allocation.y + border_width;
 
4458
  attributes.width = widget->allocation.width - border_width * 2;
 
4459
  attributes.height = widget->allocation.height - border_width * 2;
 
4460
  attributes.wclass = GDK_INPUT_OUTPUT;
 
4461
  attributes.visual = gtk_widget_get_visual (widget);
 
4462
  attributes.colormap = gtk_widget_get_colormap (widget);
 
4463
  attributes.event_mask = gtk_widget_get_events (widget);
 
4464
  attributes.event_mask |= (GDK_EXPOSURE_MASK |
 
4465
                            GDK_BUTTON_PRESS_MASK |
 
4466
                            GDK_BUTTON_RELEASE_MASK |
 
4467
                            GDK_KEY_RELEASE_MASK);
 
4468
  attributes_mask = GDK_WA_X | GDK_WA_Y | GDK_WA_VISUAL | GDK_WA_COLORMAP;
 
4469
 
 
4470
  /* main window */
 
4471
  widget->window = gdk_window_new (gtk_widget_get_parent_window (widget),
 
4472
                                   &attributes, attributes_mask);
 
4473
  gdk_window_set_user_data (widget->window, clist);
 
4474
 
 
4475
  widget->style = gtk_style_attach (widget->style, widget->window);
 
4476
 
 
4477
  gtk_style_set_background (widget->style, widget->window, GTK_STATE_NORMAL);
 
4478
 
 
4479
  /* column-title window */
 
4480
 
 
4481
  attributes.x = clist->column_title_area.x;
 
4482
  attributes.y = clist->column_title_area.y;
 
4483
  attributes.width = clist->column_title_area.width;
 
4484
  attributes.height = clist->column_title_area.height;
 
4485
  
 
4486
  clist->title_window = gdk_window_new (widget->window, &attributes,
 
4487
                                        attributes_mask);
 
4488
  gdk_window_set_user_data (clist->title_window, clist);
 
4489
 
 
4490
  gtk_style_set_background (widget->style, clist->title_window,
 
4491
                            GTK_STATE_NORMAL);
 
4492
  gdk_window_show (clist->title_window);
 
4493
 
 
4494
  /* set things up so column buttons are drawn in title window */
 
4495
  for (i = 0; i < clist->columns; i++)
 
4496
    if (clist->column[i].button)
 
4497
      gtk_widget_set_parent_window (clist->column[i].button,
 
4498
                                    clist->title_window);
 
4499
 
 
4500
  /* clist-window */
 
4501
  attributes.x = (clist->internal_allocation.x +
 
4502
                  widget->style->xthickness);
 
4503
  attributes.y = (clist->internal_allocation.y +
 
4504
                  widget->style->ythickness +
 
4505
                  clist->column_title_area.height);
 
4506
  attributes.width = clist->clist_window_width;
 
4507
  attributes.height = clist->clist_window_height;
 
4508
  
 
4509
  clist->clist_window = gdk_window_new (widget->window, &attributes,
 
4510
                                        attributes_mask);
 
4511
  gdk_window_set_user_data (clist->clist_window, clist);
 
4512
 
 
4513
  gdk_window_set_background (clist->clist_window,
 
4514
                             &widget->style->base[GTK_STATE_NORMAL]);
 
4515
  gdk_window_show (clist->clist_window);
 
4516
  gdk_window_get_size (clist->clist_window, &clist->clist_window_width,
 
4517
                       &clist->clist_window_height);
 
4518
 
 
4519
  /* create resize windows */
 
4520
  attributes.wclass = GDK_INPUT_ONLY;
 
4521
  attributes.event_mask = (GDK_BUTTON_PRESS_MASK |
 
4522
                           GDK_BUTTON_RELEASE_MASK |
 
4523
                           GDK_POINTER_MOTION_MASK |
 
4524
                           GDK_POINTER_MOTION_HINT_MASK);
 
4525
  attributes_mask = GDK_WA_CURSOR;
 
4526
  attributes.cursor = gdk_cursor_new_for_display (gtk_widget_get_display (widget),
 
4527
                                                  GDK_SB_H_DOUBLE_ARROW);
 
4528
  clist->cursor_drag = attributes.cursor;
 
4529
 
 
4530
  attributes.x =  LIST_WIDTH (clist) + 1;
 
4531
  attributes.y = 0;
 
4532
  attributes.width = 0;
 
4533
  attributes.height = 0;
 
4534
 
 
4535
  for (i = 0; i < clist->columns; i++)
 
4536
    {
 
4537
      clist->column[i].window = gdk_window_new (clist->title_window,
 
4538
                                                &attributes, attributes_mask);
 
4539
      gdk_window_set_user_data (clist->column[i].window, clist);
 
4540
    }
 
4541
 
 
4542
  /* This is slightly less efficient than creating them with the
 
4543
   * right size to begin with, but easier
 
4544
   */
 
4545
  size_allocate_title_buttons (clist);
 
4546
 
 
4547
  /* GCs */
 
4548
  clist->fg_gc = gdk_gc_new (widget->window);
 
4549
  clist->bg_gc = gdk_gc_new (widget->window);
 
4550
  
 
4551
  /* We'll use this gc to do scrolling as well */
 
4552
  gdk_gc_set_exposures (clist->fg_gc, TRUE);
 
4553
 
 
4554
  values.foreground = (widget->style->white.pixel==0 ?
 
4555
                       widget->style->black:widget->style->white);
 
4556
  values.function = GDK_XOR;
 
4557
  values.subwindow_mode = GDK_INCLUDE_INFERIORS;
 
4558
  clist->xor_gc = gdk_gc_new_with_values (widget->window,
 
4559
                                          &values,
 
4560
                                          GDK_GC_FOREGROUND |
 
4561
                                          GDK_GC_FUNCTION |
 
4562
                                          GDK_GC_SUBWINDOW);
 
4563
 
 
4564
  /* attach optional row/cell styles, allocate foreground/background colors */
 
4565
  list = clist->row_list;
 
4566
  for (i = 0; i < clist->rows; i++)
 
4567
    {
 
4568
      clist_row = list->data;
 
4569
      list = list->next;
 
4570
 
 
4571
      if (clist_row->style)
 
4572
        clist_row->style = gtk_style_attach (clist_row->style,
 
4573
                                             clist->clist_window);
 
4574
 
 
4575
      if (clist_row->fg_set || clist_row->bg_set)
 
4576
        {
 
4577
          GdkColormap *colormap;
 
4578
 
 
4579
          colormap = gtk_widget_get_colormap (widget);
 
4580
          if (clist_row->fg_set)
 
4581
            gdk_color_alloc (colormap, &clist_row->foreground);
 
4582
          if (clist_row->bg_set)
 
4583
            gdk_color_alloc (colormap, &clist_row->background);
 
4584
        }
 
4585
      
 
4586
      for (j = 0; j < clist->columns; j++)
 
4587
        if  (clist_row->cell[j].style)
 
4588
          clist_row->cell[j].style =
 
4589
            gtk_style_attach (clist_row->cell[j].style, clist->clist_window);
 
4590
    }
 
4591
}
 
4592
 
 
4593
static void
 
4594
gtk_clist_unrealize (GtkWidget *widget)
 
4595
{
 
4596
  gint i;
 
4597
  GtkCList *clist;
 
4598
 
 
4599
  g_return_if_fail (GTK_IS_CLIST (widget));
 
4600
 
 
4601
  clist = GTK_CLIST (widget);
 
4602
 
 
4603
  /* freeze the list */
 
4604
  clist->freeze_count++;
 
4605
 
 
4606
  if (GTK_WIDGET_MAPPED (widget))
 
4607
    gtk_clist_unmap (widget);
 
4608
 
 
4609
  GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
 
4610
 
 
4611
  /* detach optional row/cell styles */
 
4612
  if (GTK_WIDGET_REALIZED (widget))
 
4613
    {
 
4614
      GtkCListRow *clist_row;
 
4615
      GList *list;
 
4616
      gint j;
 
4617
 
 
4618
      list = clist->row_list;
 
4619
      for (i = 0; i < clist->rows; i++)
 
4620
        {
 
4621
          clist_row = list->data;
 
4622
          list = list->next;
 
4623
 
 
4624
          if (clist_row->style)
 
4625
            gtk_style_detach (clist_row->style);
 
4626
          for (j = 0; j < clist->columns; j++)
 
4627
            if  (clist_row->cell[j].style)
 
4628
              gtk_style_detach (clist_row->cell[j].style);
 
4629
        }
 
4630
    }
 
4631
 
 
4632
  gdk_cursor_destroy (clist->cursor_drag);
 
4633
  gdk_gc_destroy (clist->xor_gc);
 
4634
  gdk_gc_destroy (clist->fg_gc);
 
4635
  gdk_gc_destroy (clist->bg_gc);
 
4636
 
 
4637
  for (i = 0; i < clist->columns; i++)
 
4638
    {
 
4639
      if (clist->column[i].button)
 
4640
        gtk_widget_unrealize (clist->column[i].button);
 
4641
      if (clist->column[i].window)
 
4642
        {
 
4643
          gdk_window_set_user_data (clist->column[i].window, NULL);
 
4644
          gdk_window_destroy (clist->column[i].window);
 
4645
          clist->column[i].window = NULL;
 
4646
        }
 
4647
    }
 
4648
 
 
4649
  gdk_window_set_user_data (clist->clist_window, NULL);
 
4650
  gdk_window_destroy (clist->clist_window);
 
4651
  clist->clist_window = NULL;
 
4652
 
 
4653
  gdk_window_set_user_data (clist->title_window, NULL);
 
4654
  gdk_window_destroy (clist->title_window);
 
4655
  clist->title_window = NULL;
 
4656
 
 
4657
  clist->cursor_drag = NULL;
 
4658
  clist->xor_gc = NULL;
 
4659
  clist->fg_gc = NULL;
 
4660
  clist->bg_gc = NULL;
 
4661
 
 
4662
  if (GTK_WIDGET_CLASS (parent_class)->unrealize)
 
4663
    (* GTK_WIDGET_CLASS (parent_class)->unrealize) (widget);
 
4664
}
 
4665
 
 
4666
static void
 
4667
gtk_clist_map (GtkWidget *widget)
 
4668
{
 
4669
  gint i;
 
4670
  GtkCList *clist;
 
4671
 
 
4672
  g_return_if_fail (GTK_IS_CLIST (widget));
 
4673
 
 
4674
  clist = GTK_CLIST (widget);
 
4675
 
 
4676
  if (!GTK_WIDGET_MAPPED (widget))
 
4677
    {
 
4678
      GTK_WIDGET_SET_FLAGS (widget, GTK_MAPPED);
 
4679
 
 
4680
      /* map column buttons */
 
4681
      for (i = 0; i < clist->columns; i++)
 
4682
        {
 
4683
          if (clist->column[i].button &&
 
4684
              GTK_WIDGET_VISIBLE (clist->column[i].button) &&
 
4685
              !GTK_WIDGET_MAPPED (clist->column[i].button))
 
4686
            gtk_widget_map (clist->column[i].button);
 
4687
        }
 
4688
      
 
4689
      for (i = 0; i < clist->columns; i++)
 
4690
        if (clist->column[i].window && clist->column[i].button)
 
4691
          {
 
4692
            gdk_window_raise (clist->column[i].window);
 
4693
            gdk_window_show (clist->column[i].window);
 
4694
          }
 
4695
 
 
4696
      gdk_window_show (clist->title_window);
 
4697
      gdk_window_show (clist->clist_window);
 
4698
      gdk_window_show (widget->window);
 
4699
 
 
4700
      /* unfreeze the list */
 
4701
      clist->freeze_count = 0;
 
4702
    }
 
4703
}
 
4704
 
 
4705
static void
 
4706
gtk_clist_unmap (GtkWidget *widget)
 
4707
{
 
4708
  gint i;
 
4709
  GtkCList *clist;
 
4710
 
 
4711
  g_return_if_fail (GTK_IS_CLIST (widget));
 
4712
 
 
4713
  clist = GTK_CLIST (widget);
 
4714
 
 
4715
  if (GTK_WIDGET_MAPPED (widget))
 
4716
    {
 
4717
      GTK_WIDGET_UNSET_FLAGS (widget, GTK_MAPPED);
 
4718
 
 
4719
      if (clist_has_grab (clist))
 
4720
        {
 
4721
          remove_grab (clist);
 
4722
 
 
4723
          GTK_CLIST_GET_CLASS (widget)->resync_selection (clist, NULL);
 
4724
 
 
4725
          clist->click_cell.row = -1;
 
4726
          clist->click_cell.column = -1;
 
4727
          clist->drag_button = 0;
 
4728
 
 
4729
          if (GTK_CLIST_IN_DRAG(clist))
 
4730
            {
 
4731
              gpointer drag_data;
 
4732
 
 
4733
              GTK_CLIST_UNSET_FLAG (clist, CLIST_IN_DRAG);
 
4734
              drag_data = gtk_object_get_data (GTK_OBJECT (clist),
 
4735
                                               "gtk-site-data");
 
4736
              if (drag_data)
 
4737
                gtk_signal_handler_unblock_by_data (GTK_OBJECT (clist),
 
4738
                                                    drag_data);
 
4739
            }
 
4740
        }
 
4741
 
 
4742
      for (i = 0; i < clist->columns; i++)
 
4743
        if (clist->column[i].window)
 
4744
          gdk_window_hide (clist->column[i].window);
 
4745
 
 
4746
      gdk_window_hide (clist->clist_window);
 
4747
      gdk_window_hide (clist->title_window);
 
4748
      gdk_window_hide (widget->window);
 
4749
 
 
4750
      /* unmap column buttons */
 
4751
      for (i = 0; i < clist->columns; i++)
 
4752
        if (clist->column[i].button &&
 
4753
            GTK_WIDGET_MAPPED (clist->column[i].button))
 
4754
          gtk_widget_unmap (clist->column[i].button);
 
4755
 
 
4756
      /* freeze the list */
 
4757
      clist->freeze_count++;
 
4758
    }
 
4759
}
 
4760
 
 
4761
static gint
 
4762
gtk_clist_expose (GtkWidget      *widget,
 
4763
                  GdkEventExpose *event)
 
4764
{
 
4765
  GtkCList *clist;
 
4766
 
 
4767
  g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
 
4768
  g_return_val_if_fail (event != NULL, FALSE);
 
4769
 
 
4770
  if (GTK_WIDGET_DRAWABLE (widget))
 
4771
    {
 
4772
      clist = GTK_CLIST (widget);
 
4773
 
 
4774
      /* draw border */
 
4775
      if (event->window == widget->window)
 
4776
        gtk_draw_shadow (widget->style, widget->window,
 
4777
                         GTK_STATE_NORMAL, clist->shadow_type,
 
4778
                         0, 0,
 
4779
                         clist->clist_window_width +
 
4780
                         (2 * widget->style->xthickness),
 
4781
                         clist->clist_window_height +
 
4782
                         (2 * widget->style->ythickness) +
 
4783
                         clist->column_title_area.height);
 
4784
 
 
4785
      /* exposure events on the list */
 
4786
      if (event->window == clist->clist_window)
 
4787
        draw_rows (clist, &event->area);
 
4788
 
 
4789
      if (event->window == clist->clist_window &&
 
4790
          clist->drag_highlight_row >= 0)
 
4791
        GTK_CLIST_GET_CLASS (clist)->draw_drag_highlight
 
4792
          (clist, g_list_nth (clist->row_list,
 
4793
                              clist->drag_highlight_row)->data,
 
4794
           clist->drag_highlight_row, clist->drag_highlight_pos);
 
4795
 
 
4796
      if (event->window == clist->title_window)
 
4797
        {
 
4798
          gint i;
 
4799
          
 
4800
          for (i = 0; i < clist->columns; i++)
 
4801
            {
 
4802
              if (clist->column[i].button)
 
4803
                gtk_container_propagate_expose (GTK_CONTAINER (clist),
 
4804
                                                clist->column[i].button,
 
4805
                                                event);
 
4806
            }
 
4807
        }
 
4808
    }
 
4809
 
 
4810
  return FALSE;
 
4811
}
 
4812
 
 
4813
static void
 
4814
gtk_clist_style_set (GtkWidget *widget,
 
4815
                     GtkStyle  *previous_style)
 
4816
{
 
4817
  GtkCList *clist;
 
4818
 
 
4819
  g_return_if_fail (GTK_IS_CLIST (widget));
 
4820
 
 
4821
  if (GTK_WIDGET_CLASS (parent_class)->style_set)
 
4822
    (*GTK_WIDGET_CLASS (parent_class)->style_set) (widget, previous_style);
 
4823
 
 
4824
  clist = GTK_CLIST (widget);
 
4825
 
 
4826
  if (GTK_WIDGET_REALIZED (widget))
 
4827
    {
 
4828
      gtk_style_set_background (widget->style, widget->window, widget->state);
 
4829
      gtk_style_set_background (widget->style, clist->title_window, GTK_STATE_SELECTED);
 
4830
      gdk_window_set_background (clist->clist_window, &widget->style->base[GTK_STATE_NORMAL]);
 
4831
    }
 
4832
 
 
4833
  /* Fill in data after widget has correct style */
 
4834
 
 
4835
  /* text properties */
 
4836
  if (!GTK_CLIST_ROW_HEIGHT_SET(clist))
 
4837
    /* Reset clist->row_height */
 
4838
    gtk_clist_set_row_height (clist, 0);
 
4839
 
 
4840
  /* Column widths */
 
4841
  if (!GTK_CLIST_AUTO_RESIZE_BLOCKED (clist))
 
4842
    {
 
4843
      gint width;
 
4844
      gint i;
 
4845
 
 
4846
      for (i = 0; i < clist->columns; i++)
 
4847
        if (clist->column[i].auto_resize)
 
4848
          {
 
4849
            width = gtk_clist_optimal_column_width (clist, i);
 
4850
            if (width != clist->column[i].width)
 
4851
              gtk_clist_set_column_width (clist, i, width);
 
4852
          }
 
4853
    }
 
4854
}
 
4855
 
 
4856
static gint
 
4857
gtk_clist_button_press (GtkWidget      *widget,
 
4858
                        GdkEventButton *event)
 
4859
{
 
4860
  gint i;
 
4861
  GtkCList *clist;
 
4862
  gint x;
 
4863
  gint y;
 
4864
  gint row;
 
4865
  gint column;
 
4866
  gint button_actions;
 
4867
 
 
4868
  g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
 
4869
  g_return_val_if_fail (event != NULL, FALSE);
 
4870
 
 
4871
  clist = GTK_CLIST (widget);
 
4872
 
 
4873
  button_actions = clist->button_actions[event->button - 1];
 
4874
 
 
4875
  if (button_actions == GTK_BUTTON_IGNORED)
 
4876
    return FALSE;
 
4877
 
 
4878
  /* selections on the list */
 
4879
  if (event->window == clist->clist_window)
 
4880
    {
 
4881
      x = event->x;
 
4882
      y = event->y;
 
4883
 
 
4884
      if (get_selection_info (clist, x, y, &row, &column))
 
4885
        {
 
4886
          gint old_row = clist->focus_row;
 
4887
 
 
4888
          if (clist->focus_row == -1)
 
4889
            old_row = row;
 
4890
 
 
4891
          if (event->type == GDK_BUTTON_PRESS)
 
4892
            {
 
4893
              GdkEventMask mask = ((1 << (4 + event->button)) |
 
4894
                                   GDK_POINTER_MOTION_HINT_MASK |
 
4895
                                   GDK_BUTTON_RELEASE_MASK);
 
4896
 
 
4897
              if (gdk_pointer_grab (clist->clist_window, FALSE, mask,
 
4898
                                    NULL, NULL, event->time))
 
4899
                return FALSE;
 
4900
              gtk_grab_add (widget);
 
4901
 
 
4902
              clist->click_cell.row = row;
 
4903
              clist->click_cell.column = column;
 
4904
              clist->drag_button = event->button;
 
4905
            }
 
4906
          else
 
4907
            {
 
4908
              clist->click_cell.row = -1;
 
4909
              clist->click_cell.column = -1;
 
4910
 
 
4911
              clist->drag_button = 0;
 
4912
              remove_grab (clist);
 
4913
            }
 
4914
 
 
4915
          if (button_actions & GTK_BUTTON_SELECTS)
 
4916
            {
 
4917
              if (GTK_CLIST_ADD_MODE(clist))
 
4918
                {
 
4919
                  GTK_CLIST_UNSET_FLAG (clist, CLIST_ADD_MODE);
 
4920
                  if (GTK_WIDGET_HAS_FOCUS(widget))
 
4921
                    {
 
4922
                      gtk_clist_draw_focus (widget);
 
4923
                      gdk_gc_set_line_attributes (clist->xor_gc, 1,
 
4924
                                                  GDK_LINE_SOLID, 0, 0);
 
4925
                      clist->focus_row = row;
 
4926
                      gtk_clist_draw_focus (widget);
 
4927
                    }
 
4928
                  else
 
4929
                    {
 
4930
                      gdk_gc_set_line_attributes (clist->xor_gc, 1,
 
4931
                                                  GDK_LINE_SOLID, 0, 0);
 
4932
                      clist->focus_row = row;
 
4933
                    }
 
4934
                }
 
4935
              else if (row != clist->focus_row)
 
4936
                {
 
4937
                  if (GTK_WIDGET_HAS_FOCUS(widget))
 
4938
                    {
 
4939
                      gtk_clist_draw_focus (widget);
 
4940
                      clist->focus_row = row;
 
4941
                      gtk_clist_draw_focus (widget);
 
4942
                    }
 
4943
                  else
 
4944
                    clist->focus_row = row;
 
4945
                }
 
4946
            }
 
4947
 
 
4948
          if (!GTK_WIDGET_HAS_FOCUS(widget))
 
4949
            gtk_widget_grab_focus (widget);
 
4950
 
 
4951
          if (button_actions & GTK_BUTTON_SELECTS)
 
4952
            {
 
4953
              switch (clist->selection_mode)
 
4954
                {
 
4955
                case GTK_SELECTION_SINGLE:
 
4956
                  if (event->type != GDK_BUTTON_PRESS)
 
4957
                    {
 
4958
                      gtk_signal_emit (GTK_OBJECT (clist),
 
4959
                                       clist_signals[SELECT_ROW],
 
4960
                                       row, column, event);
 
4961
                      clist->anchor = -1;
 
4962
                    }
 
4963
                  else
 
4964
                    clist->anchor = row;
 
4965
                  break;
 
4966
                case GTK_SELECTION_BROWSE:
 
4967
                  gtk_signal_emit (GTK_OBJECT (clist),
 
4968
                                   clist_signals[SELECT_ROW],
 
4969
                                   row, column, event);
 
4970
                  break;
 
4971
                case GTK_SELECTION_MULTIPLE:
 
4972
                  if (event->type != GDK_BUTTON_PRESS)
 
4973
                    {
 
4974
                      if (clist->anchor != -1)
 
4975
                        {
 
4976
                          update_extended_selection (clist, clist->focus_row);
 
4977
                          GTK_CLIST_GET_CLASS (clist)->resync_selection
 
4978
                            (clist, (GdkEvent *) event);
 
4979
                        }
 
4980
                      gtk_signal_emit (GTK_OBJECT (clist),
 
4981
                                       clist_signals[SELECT_ROW],
 
4982
                                       row, column, event);
 
4983
                      break;
 
4984
                    }
 
4985
              
 
4986
                  if (event->state & GDK_CONTROL_MASK)
 
4987
                    {
 
4988
                      if (event->state & GDK_SHIFT_MASK)
 
4989
                        {
 
4990
                          if (clist->anchor < 0)
 
4991
                            {
 
4992
                              g_list_free (clist->undo_selection);
 
4993
                              g_list_free (clist->undo_unselection);
 
4994
                              clist->undo_selection = NULL;
 
4995
                              clist->undo_unselection = NULL;
 
4996
                              clist->anchor = old_row;
 
4997
                              clist->drag_pos = old_row;
 
4998
                              clist->undo_anchor = old_row;
 
4999
                            }
 
5000
                          update_extended_selection (clist, clist->focus_row);
 
5001
                        }
 
5002
                      else
 
5003
                        {
 
5004
                          if (clist->anchor == -1)
 
5005
                            set_anchor (clist, TRUE, row, old_row);
 
5006
                          else
 
5007
                            update_extended_selection (clist,
 
5008
                                                       clist->focus_row);
 
5009
                        }
 
5010
                      break;
 
5011
                    }
 
5012
 
 
5013
                  if (event->state & GDK_SHIFT_MASK)
 
5014
                    {
 
5015
                      set_anchor (clist, FALSE, old_row, old_row);
 
5016
                      update_extended_selection (clist, clist->focus_row);
 
5017
                      break;
 
5018
                    }
 
5019
 
 
5020
                  if (clist->anchor == -1)
 
5021
                    set_anchor (clist, FALSE, row, old_row);
 
5022
                  else
 
5023
                    update_extended_selection (clist, clist->focus_row);
 
5024
                  break;
 
5025
                default:
 
5026
                  break;
 
5027
                }
 
5028
            }
 
5029
        }
 
5030
      return TRUE;
 
5031
    }
 
5032
 
 
5033
  /* press on resize windows */
 
5034
  for (i = 0; i < clist->columns; i++)
 
5035
    if (clist->column[i].resizeable && clist->column[i].window &&
 
5036
        event->window == clist->column[i].window)
 
5037
      {
 
5038
        gpointer drag_data;
 
5039
 
 
5040
        if (gdk_pointer_grab (clist->column[i].window, FALSE,
 
5041
                              GDK_POINTER_MOTION_HINT_MASK |
 
5042
                              GDK_BUTTON1_MOTION_MASK |
 
5043
                              GDK_BUTTON_RELEASE_MASK,
 
5044
                              NULL, NULL, event->time))
 
5045
          return FALSE;
 
5046
 
 
5047
        gtk_grab_add (widget);
 
5048
        GTK_CLIST_SET_FLAG (clist, CLIST_IN_DRAG);
 
5049
 
 
5050
        /* block attached dnd signal handler */
 
5051
        drag_data = gtk_object_get_data (GTK_OBJECT (clist), "gtk-site-data");
 
5052
        if (drag_data)
 
5053
          gtk_signal_handler_block_by_data (GTK_OBJECT (clist), drag_data);
 
5054
 
 
5055
        if (!GTK_WIDGET_HAS_FOCUS(widget))
 
5056
          gtk_widget_grab_focus (widget);
 
5057
 
 
5058
        clist->drag_pos = i;
 
5059
        clist->x_drag = (COLUMN_LEFT_XPIXEL(clist, i) + COLUMN_INSET +
 
5060
                         clist->column[i].area.width + CELL_SPACING);
 
5061
 
 
5062
        if (GTK_CLIST_ADD_MODE(clist))
 
5063
          gdk_gc_set_line_attributes (clist->xor_gc, 1, GDK_LINE_SOLID, 0, 0);
 
5064
        draw_xor_line (clist);
 
5065
 
 
5066
        return TRUE;
 
5067
      }
 
5068
 
 
5069
  return FALSE;
 
5070
}
 
5071
 
 
5072
static gint
 
5073
gtk_clist_button_release (GtkWidget      *widget,
 
5074
                          GdkEventButton *event)
 
5075
{
 
5076
  GtkCList *clist;
 
5077
  gint button_actions;
 
5078
 
 
5079
  g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
 
5080
  g_return_val_if_fail (event != NULL, FALSE);
 
5081
 
 
5082
  clist = GTK_CLIST (widget);
 
5083
 
 
5084
  button_actions = clist->button_actions[event->button - 1];
 
5085
  if (button_actions == GTK_BUTTON_IGNORED)
 
5086
    return FALSE;
 
5087
 
 
5088
  /* release on resize windows */
 
5089
  if (GTK_CLIST_IN_DRAG(clist))
 
5090
    {
 
5091
      gpointer drag_data;
 
5092
      gint width;
 
5093
      gint x;
 
5094
      gint i;
 
5095
 
 
5096
      i = clist->drag_pos;
 
5097
      clist->drag_pos = -1;
 
5098
 
 
5099
      /* unblock attached dnd signal handler */
 
5100
      drag_data = gtk_object_get_data (GTK_OBJECT (clist), "gtk-site-data");
 
5101
      if (drag_data)
 
5102
        gtk_signal_handler_unblock_by_data (GTK_OBJECT (clist), drag_data);
 
5103
 
 
5104
      GTK_CLIST_UNSET_FLAG (clist, CLIST_IN_DRAG);
 
5105
      gtk_widget_get_pointer (widget, &x, NULL);
 
5106
      gtk_grab_remove (widget);
 
5107
      gdk_display_pointer_ungrab (gtk_widget_get_display (widget), event->time);
 
5108
 
 
5109
      if (clist->x_drag >= 0)
 
5110
        draw_xor_line (clist);
 
5111
 
 
5112
      if (GTK_CLIST_ADD_MODE(clist))
 
5113
        {
 
5114
          gdk_gc_set_line_attributes (clist->xor_gc, 1,
 
5115
                                      GDK_LINE_ON_OFF_DASH, 0, 0);
 
5116
          gdk_gc_set_dashes (clist->xor_gc, 0, "\4\4", 2);
 
5117
        }
 
5118
 
 
5119
      width = new_column_width (clist, i, &x);
 
5120
      gtk_clist_set_column_width (clist, i, width);
 
5121
 
 
5122
      return TRUE;
 
5123
    }
 
5124
 
 
5125
  if (clist->drag_button == event->button)
 
5126
    {
 
5127
      gint row;
 
5128
      gint column;
 
5129
 
 
5130
      clist->drag_button = 0;
 
5131
      clist->click_cell.row = -1;
 
5132
      clist->click_cell.column = -1;
 
5133
 
 
5134
      remove_grab (clist);
 
5135
 
 
5136
      if (button_actions & GTK_BUTTON_SELECTS)
 
5137
        {
 
5138
          switch (clist->selection_mode)
 
5139
            {
 
5140
            case GTK_SELECTION_MULTIPLE:
 
5141
              if (!(event->state & GDK_SHIFT_MASK) ||
 
5142
                  !GTK_WIDGET_CAN_FOCUS (widget) ||
 
5143
                  event->x < 0 || event->x >= clist->clist_window_width ||
 
5144
                  event->y < 0 || event->y >= clist->clist_window_height)
 
5145
                GTK_CLIST_GET_CLASS (clist)->resync_selection
 
5146
                  (clist, (GdkEvent *) event);
 
5147
              break;
 
5148
            case GTK_SELECTION_SINGLE:
 
5149
              if (get_selection_info (clist, event->x, event->y,
 
5150
                                      &row, &column))
 
5151
                {
 
5152
                  if (row >= 0 && row < clist->rows && clist->anchor == row)
 
5153
                    toggle_row (clist, row, column, (GdkEvent *) event);
 
5154
                }
 
5155
              clist->anchor = -1;
 
5156
              break;
 
5157
            default:
 
5158
              break;
 
5159
            }
 
5160
        }
 
5161
 
 
5162
      return TRUE;
 
5163
    }
 
5164
  
 
5165
  return FALSE;
 
5166
}
 
5167
 
 
5168
static gint
 
5169
gtk_clist_motion (GtkWidget      *widget,
 
5170
                  GdkEventMotion *event)
 
5171
{
 
5172
  GtkCList *clist;
 
5173
  gint x;
 
5174
  gint y;
 
5175
  gint row;
 
5176
  gint new_width;
 
5177
  gint button_actions = 0;
 
5178
 
 
5179
  g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
 
5180
 
 
5181
  clist = GTK_CLIST (widget);
 
5182
  if (!clist_has_grab (clist))
 
5183
    return FALSE;
 
5184
 
 
5185
  if (clist->drag_button > 0)
 
5186
    button_actions = clist->button_actions[clist->drag_button - 1];
 
5187
 
 
5188
  if (GTK_CLIST_IN_DRAG(clist))
 
5189
    {
 
5190
      if (event->is_hint || event->window != widget->window)
 
5191
        gtk_widget_get_pointer (widget, &x, NULL);
 
5192
      else
 
5193
        x = event->x;
 
5194
      
 
5195
      new_width = new_column_width (clist, clist->drag_pos, &x);
 
5196
      if (x != clist->x_drag)
 
5197
        {
 
5198
          /* x_drag < 0 indicates that the xor line is already invisible */
 
5199
          if (clist->x_drag >= 0)
 
5200
            draw_xor_line (clist);
 
5201
 
 
5202
          clist->x_drag = x;
 
5203
 
 
5204
          if (clist->x_drag >= 0)
 
5205
            draw_xor_line (clist);
 
5206
        }
 
5207
 
 
5208
      if (new_width <= MAX (COLUMN_MIN_WIDTH + 1,
 
5209
                            clist->column[clist->drag_pos].min_width + 1))
 
5210
        {
 
5211
          if (COLUMN_LEFT_XPIXEL (clist, clist->drag_pos) < 0 && x < 0)
 
5212
            gtk_clist_moveto (clist, -1, clist->drag_pos, 0, 0);
 
5213
          return FALSE;
 
5214
        }
 
5215
      if (clist->column[clist->drag_pos].max_width >= COLUMN_MIN_WIDTH &&
 
5216
          new_width >= clist->column[clist->drag_pos].max_width)
 
5217
        {
 
5218
          if (COLUMN_LEFT_XPIXEL (clist, clist->drag_pos) + new_width >
 
5219
              clist->clist_window_width && x < 0)
 
5220
            move_horizontal (clist,
 
5221
                             COLUMN_LEFT_XPIXEL (clist, clist->drag_pos) +
 
5222
                             new_width - clist->clist_window_width +
 
5223
                             COLUMN_INSET + CELL_SPACING);
 
5224
          return FALSE;
 
5225
        }
 
5226
    }
 
5227
 
 
5228
  if (event->is_hint || event->window != clist->clist_window)
 
5229
    gdk_window_get_pointer (clist->clist_window, &x, &y, NULL);
 
5230
  else
 
5231
    {
 
5232
      x = event->x;
 
5233
      y = event->y;
 
5234
    }
 
5235
 
 
5236
  if (GTK_CLIST_REORDERABLE(clist) && button_actions & GTK_BUTTON_DRAGS)
 
5237
    {
 
5238
      /* delayed drag start */
 
5239
      if (event->window == clist->clist_window &&
 
5240
          clist->click_cell.row >= 0 && clist->click_cell.column >= 0 &&
 
5241
          (y < 0 || y >= clist->clist_window_height ||
 
5242
           x < 0 || x >= clist->clist_window_width  ||
 
5243
           y < ROW_TOP_YPIXEL (clist, clist->click_cell.row) ||
 
5244
           y >= (ROW_TOP_YPIXEL (clist, clist->click_cell.row) +
 
5245
                 clist->row_height) ||
 
5246
           x < COLUMN_LEFT_XPIXEL (clist, clist->click_cell.column) ||
 
5247
           x >= (COLUMN_LEFT_XPIXEL(clist, clist->click_cell.column) + 
 
5248
                 clist->column[clist->click_cell.column].area.width)))
 
5249
        {
 
5250
          GtkTargetList  *target_list;
 
5251
 
 
5252
          target_list = gtk_target_list_new (&clist_target_table, 1);
 
5253
          gtk_drag_begin (widget, target_list, GDK_ACTION_MOVE,
 
5254
                          clist->drag_button, (GdkEvent *)event);
 
5255
 
 
5256
        }
 
5257
      return TRUE;
 
5258
    }
 
5259
 
 
5260
  /* horizontal autoscrolling */
 
5261
  if (clist->hadjustment && LIST_WIDTH (clist) > clist->clist_window_width &&
 
5262
      (x < 0 || x >= clist->clist_window_width))
 
5263
    {
 
5264
      if (clist->htimer)
 
5265
        return FALSE;
 
5266
 
 
5267
      clist->htimer = g_timeout_add
 
5268
        (SCROLL_TIME, (GSourceFunc) horizontal_timeout, clist);
 
5269
 
 
5270
      if (!((x < 0 && clist->hadjustment->value == 0) ||
 
5271
            (x >= clist->clist_window_width &&
 
5272
             clist->hadjustment->value ==
 
5273
             LIST_WIDTH (clist) - clist->clist_window_width)))
 
5274
        {
 
5275
          if (x < 0)
 
5276
            move_horizontal (clist, -1 + (x/2));
 
5277
          else
 
5278
            move_horizontal (clist, 1 + (x - clist->clist_window_width) / 2);
 
5279
        }
 
5280
    }
 
5281
 
 
5282
  if (GTK_CLIST_IN_DRAG(clist))
 
5283
    return FALSE;
 
5284
 
 
5285
  /* vertical autoscrolling */
 
5286
  row = ROW_FROM_YPIXEL (clist, y);
 
5287
 
 
5288
  /* don't scroll on last pixel row if it's a cell spacing */
 
5289
  if (y == clist->clist_window_height - 1 &&
 
5290
      y == ROW_TOP_YPIXEL (clist, row-1) + clist->row_height)
 
5291
    return FALSE;
 
5292
 
 
5293
  if (LIST_HEIGHT (clist) > clist->clist_window_height &&
 
5294
      (y < 0 || y >= clist->clist_window_height))
 
5295
    {
 
5296
      if (clist->vtimer)
 
5297
        return FALSE;
 
5298
 
 
5299
      clist->vtimer = g_timeout_add (SCROLL_TIME,
 
5300
                                     (GSourceFunc) vertical_timeout, clist);
 
5301
 
 
5302
      if (clist->drag_button &&
 
5303
          ((y < 0 && clist->focus_row == 0) ||
 
5304
           (y >= clist->clist_window_height &&
 
5305
            clist->focus_row == clist->rows - 1)))
 
5306
        return FALSE;
 
5307
    }
 
5308
 
 
5309
  row = CLAMP (row, 0, clist->rows - 1);
 
5310
 
 
5311
  if (button_actions & GTK_BUTTON_SELECTS &
 
5312
      !gtk_object_get_data (GTK_OBJECT (widget), "gtk-site-data"))
 
5313
    {
 
5314
      if (row == clist->focus_row)
 
5315
        return FALSE;
 
5316
 
 
5317
      gtk_clist_draw_focus (widget);
 
5318
      clist->focus_row = row;
 
5319
      gtk_clist_draw_focus (widget);
 
5320
 
 
5321
      switch (clist->selection_mode)
 
5322
        {
 
5323
        case GTK_SELECTION_BROWSE:
 
5324
          gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
 
5325
                           clist->focus_row, -1, event);
 
5326
          break;
 
5327
        case GTK_SELECTION_MULTIPLE:
 
5328
          update_extended_selection (clist, clist->focus_row);
 
5329
          break;
 
5330
        default:
 
5331
          break;
 
5332
        }
 
5333
    }
 
5334
  
 
5335
  if (ROW_TOP_YPIXEL(clist, row) < 0)
 
5336
    move_vertical (clist, row, 0);
 
5337
  else if (ROW_TOP_YPIXEL(clist, row) + clist->row_height >
 
5338
           clist->clist_window_height)
 
5339
    move_vertical (clist, row, 1);
 
5340
 
 
5341
  return FALSE;
 
5342
}
 
5343
 
 
5344
static void
 
5345
gtk_clist_size_request (GtkWidget      *widget,
 
5346
                        GtkRequisition *requisition)
 
5347
{
 
5348
  GtkCList *clist;
 
5349
  gint i;
 
5350
 
 
5351
  g_return_if_fail (GTK_IS_CLIST (widget));
 
5352
  g_return_if_fail (requisition != NULL);
 
5353
 
 
5354
  clist = GTK_CLIST (widget);
 
5355
 
 
5356
  requisition->width = 0;
 
5357
  requisition->height = 0;
 
5358
 
 
5359
  /* compute the size of the column title (title) area */
 
5360
  clist->column_title_area.height = 0;
 
5361
  if (GTK_CLIST_SHOW_TITLES(clist))
 
5362
    for (i = 0; i < clist->columns; i++)
 
5363
      if (clist->column[i].button)
 
5364
        {
 
5365
          GtkRequisition child_requisition;
 
5366
          
 
5367
          gtk_widget_size_request (clist->column[i].button,
 
5368
                                   &child_requisition);
 
5369
          clist->column_title_area.height =
 
5370
            MAX (clist->column_title_area.height,
 
5371
                 child_requisition.height);
 
5372
        }
 
5373
  
 
5374
  requisition->width += (widget->style->xthickness +
 
5375
                         GTK_CONTAINER (widget)->border_width) * 2;
 
5376
  requisition->height += (clist->column_title_area.height +
 
5377
                          (widget->style->ythickness +
 
5378
                           GTK_CONTAINER (widget)->border_width) * 2);
 
5379
 
 
5380
  /* if (!clist->hadjustment) */
 
5381
  requisition->width += list_requisition_width (clist);
 
5382
  /* if (!clist->vadjustment) */
 
5383
  requisition->height += LIST_HEIGHT (clist);
 
5384
}
 
5385
 
 
5386
static void
 
5387
gtk_clist_size_allocate (GtkWidget     *widget,
 
5388
                         GtkAllocation *allocation)
 
5389
{
 
5390
  GtkCList *clist;
 
5391
  GtkAllocation clist_allocation;
 
5392
  gint border_width;
 
5393
 
 
5394
  g_return_if_fail (GTK_IS_CLIST (widget));
 
5395
  g_return_if_fail (allocation != NULL);
 
5396
 
 
5397
  clist = GTK_CLIST (widget);
 
5398
  widget->allocation = *allocation;
 
5399
  border_width = GTK_CONTAINER (widget)->border_width;
 
5400
 
 
5401
  if (GTK_WIDGET_REALIZED (widget))
 
5402
    {
 
5403
      gdk_window_move_resize (widget->window,
 
5404
                              allocation->x + border_width,
 
5405
                              allocation->y + border_width,
 
5406
                              allocation->width - border_width * 2,
 
5407
                              allocation->height - border_width * 2);
 
5408
    }
 
5409
 
 
5410
  /* use internal allocation structure for all the math
 
5411
   * because it's easier than always subtracting the container
 
5412
   * border width */
 
5413
  clist->internal_allocation.x = 0;
 
5414
  clist->internal_allocation.y = 0;
 
5415
  clist->internal_allocation.width = MAX (1, (gint)allocation->width -
 
5416
                                          border_width * 2);
 
5417
  clist->internal_allocation.height = MAX (1, (gint)allocation->height -
 
5418
                                           border_width * 2);
 
5419
        
 
5420
  /* allocate clist window assuming no scrollbars */
 
5421
  clist_allocation.x = (clist->internal_allocation.x +
 
5422
                        widget->style->xthickness);
 
5423
  clist_allocation.y = (clist->internal_allocation.y +
 
5424
                        widget->style->ythickness +
 
5425
                        clist->column_title_area.height);
 
5426
  clist_allocation.width = MAX (1, (gint)clist->internal_allocation.width - 
 
5427
                                (2 * (gint)widget->style->xthickness));
 
5428
  clist_allocation.height = MAX (1, (gint)clist->internal_allocation.height -
 
5429
                                 (2 * (gint)widget->style->ythickness) -
 
5430
                                 (gint)clist->column_title_area.height);
 
5431
  
 
5432
  clist->clist_window_width = clist_allocation.width;
 
5433
  clist->clist_window_height = clist_allocation.height;
 
5434
  
 
5435
  if (GTK_WIDGET_REALIZED (widget))
 
5436
    {
 
5437
      gdk_window_move_resize (clist->clist_window,
 
5438
                              clist_allocation.x,
 
5439
                              clist_allocation.y,
 
5440
                              clist_allocation.width,
 
5441
                              clist_allocation.height);
 
5442
    }
 
5443
  
 
5444
  /* position the window which holds the column title buttons */
 
5445
  clist->column_title_area.x = widget->style->xthickness;
 
5446
  clist->column_title_area.y = widget->style->ythickness;
 
5447
  clist->column_title_area.width = clist_allocation.width;
 
5448
  
 
5449
  if (GTK_WIDGET_REALIZED (widget))
 
5450
    {
 
5451
      gdk_window_move_resize (clist->title_window,
 
5452
                              clist->column_title_area.x,
 
5453
                              clist->column_title_area.y,
 
5454
                              clist->column_title_area.width,
 
5455
                              clist->column_title_area.height);
 
5456
    }
 
5457
  
 
5458
  /* column button allocation */
 
5459
  size_allocate_columns (clist, FALSE);
 
5460
  size_allocate_title_buttons (clist);
 
5461
 
 
5462
  adjust_adjustments (clist, TRUE);
 
5463
}
 
5464
 
 
5465
/* GTKCONTAINER
 
5466
 *   gtk_clist_forall
 
5467
 */
 
5468
static void
 
5469
gtk_clist_forall (GtkContainer *container,
 
5470
                  gboolean      include_internals,
 
5471
                  GtkCallback   callback,
 
5472
                  gpointer      callback_data)
 
5473
{
 
5474
  GtkCList *clist;
 
5475
  guint i;
 
5476
 
 
5477
  g_return_if_fail (GTK_IS_CLIST (container));
 
5478
  g_return_if_fail (callback != NULL);
 
5479
 
 
5480
  if (!include_internals)
 
5481
    return;
 
5482
 
 
5483
  clist = GTK_CLIST (container);
 
5484
      
 
5485
  /* callback for the column buttons */
 
5486
  for (i = 0; i < clist->columns; i++)
 
5487
    if (clist->column[i].button)
 
5488
      (*callback) (clist->column[i].button, callback_data);
 
5489
}
 
5490
 
 
5491
/* PRIVATE DRAWING FUNCTIONS
 
5492
 *   get_cell_style
 
5493
 *   draw_cell_pixmap
 
5494
 *   draw_row
 
5495
 *   draw_rows
 
5496
 *   draw_xor_line
 
5497
 *   clist_refresh
 
5498
 */
 
5499
static void
 
5500
get_cell_style (GtkCList     *clist,
 
5501
                GtkCListRow  *clist_row,
 
5502
                gint          state,
 
5503
                gint          column,
 
5504
                GtkStyle    **style,
 
5505
                GdkGC       **fg_gc,
 
5506
                GdkGC       **bg_gc)
 
5507
{
 
5508
  gint fg_state;
 
5509
 
 
5510
  if ((state == GTK_STATE_NORMAL) &&
 
5511
      (GTK_WIDGET (clist)->state == GTK_STATE_INSENSITIVE))
 
5512
    fg_state = GTK_STATE_INSENSITIVE;
 
5513
  else
 
5514
    fg_state = state;
 
5515
 
 
5516
  if (clist_row->cell[column].style)
 
5517
    {
 
5518
      if (style)
 
5519
        *style = clist_row->cell[column].style;
 
5520
      if (fg_gc)
 
5521
        *fg_gc = clist_row->cell[column].style->fg_gc[fg_state];
 
5522
      if (bg_gc) {
 
5523
        if (state == GTK_STATE_SELECTED)
 
5524
          *bg_gc = clist_row->cell[column].style->bg_gc[state];
 
5525
        else
 
5526
          *bg_gc = clist_row->cell[column].style->base_gc[state];
 
5527
      }
 
5528
    }
 
5529
  else if (clist_row->style)
 
5530
    {
 
5531
      if (style)
 
5532
        *style = clist_row->style;
 
5533
      if (fg_gc)
 
5534
        *fg_gc = clist_row->style->fg_gc[fg_state];
 
5535
      if (bg_gc) {
 
5536
        if (state == GTK_STATE_SELECTED)
 
5537
          *bg_gc = clist_row->style->bg_gc[state];
 
5538
        else
 
5539
          *bg_gc = clist_row->style->base_gc[state];
 
5540
      }
 
5541
    }
 
5542
  else
 
5543
    {
 
5544
      if (style)
 
5545
        *style = GTK_WIDGET (clist)->style;
 
5546
      if (fg_gc)
 
5547
        *fg_gc = GTK_WIDGET (clist)->style->fg_gc[fg_state];
 
5548
      if (bg_gc) {
 
5549
        if (state == GTK_STATE_SELECTED)
 
5550
          *bg_gc = GTK_WIDGET (clist)->style->bg_gc[state];
 
5551
        else
 
5552
          *bg_gc = GTK_WIDGET (clist)->style->base_gc[state];
 
5553
      }
 
5554
 
 
5555
      if (state != GTK_STATE_SELECTED)
 
5556
        {
 
5557
          if (fg_gc && clist_row->fg_set)
 
5558
            *fg_gc = clist->fg_gc;
 
5559
          if (bg_gc && clist_row->bg_set)
 
5560
            *bg_gc = clist->bg_gc;
 
5561
        }
 
5562
    }
 
5563
}
 
5564
 
 
5565
static gint
 
5566
draw_cell_pixmap (GdkWindow    *window,
 
5567
                  GdkRectangle *clip_rectangle,
 
5568
                  GdkGC        *fg_gc,
 
5569
                  GdkPixmap    *pixmap,
 
5570
                  GdkBitmap    *mask,
 
5571
                  gint          x,
 
5572
                  gint          y,
 
5573
                  gint          width,
 
5574
                  gint          height)
 
5575
{
 
5576
  gint xsrc = 0;
 
5577
  gint ysrc = 0;
 
5578
 
 
5579
  if (mask)
 
5580
    {
 
5581
      gdk_gc_set_clip_mask (fg_gc, mask);
 
5582
      gdk_gc_set_clip_origin (fg_gc, x, y);
 
5583
    }
 
5584
 
 
5585
  if (x < clip_rectangle->x)
 
5586
    {
 
5587
      xsrc = clip_rectangle->x - x;
 
5588
      width -= xsrc;
 
5589
      x = clip_rectangle->x;
 
5590
    }
 
5591
  if (x + width > clip_rectangle->x + clip_rectangle->width)
 
5592
    width = clip_rectangle->x + clip_rectangle->width - x;
 
5593
 
 
5594
  if (y < clip_rectangle->y)
 
5595
    {
 
5596
      ysrc = clip_rectangle->y - y;
 
5597
      height -= ysrc;
 
5598
      y = clip_rectangle->y;
 
5599
    }
 
5600
  if (y + height > clip_rectangle->y + clip_rectangle->height)
 
5601
    height = clip_rectangle->y + clip_rectangle->height - y;
 
5602
 
 
5603
  gdk_draw_pixmap (window, fg_gc, pixmap, xsrc, ysrc, x, y, width, height);
 
5604
  gdk_gc_set_clip_origin (fg_gc, 0, 0);
 
5605
  if (mask)
 
5606
    gdk_gc_set_clip_mask (fg_gc, NULL);
 
5607
 
 
5608
  return x + MAX (width, 0);
 
5609
}
 
5610
 
 
5611
static void
 
5612
draw_row (GtkCList     *clist,
 
5613
          GdkRectangle *area,
 
5614
          gint          row,
 
5615
          GtkCListRow  *clist_row)
 
5616
{
 
5617
  GtkWidget *widget;
 
5618
  GdkRectangle *rect;
 
5619
  GdkRectangle row_rectangle;
 
5620
  GdkRectangle cell_rectangle;
 
5621
  GdkRectangle clip_rectangle;
 
5622
  GdkRectangle intersect_rectangle;
 
5623
  gint last_column;
 
5624
  gint state;
 
5625
  gint i;
 
5626
 
 
5627
  g_return_if_fail (clist != NULL);
 
5628
 
 
5629
  /* bail now if we arn't drawable yet */
 
5630
  if (!GTK_WIDGET_DRAWABLE (clist) || row < 0 || row >= clist->rows)
 
5631
    return;
 
5632
 
 
5633
  widget = GTK_WIDGET (clist);
 
5634
 
 
5635
  /* if the function is passed the pointer to the row instead of null,
 
5636
   * it avoids this expensive lookup */
 
5637
  if (!clist_row)
 
5638
    clist_row = ROW_ELEMENT (clist, row)->data;
 
5639
 
 
5640
  /* rectangle of the entire row */
 
5641
  row_rectangle.x = 0;
 
5642
  row_rectangle.y = ROW_TOP_YPIXEL (clist, row);
 
5643
  row_rectangle.width = clist->clist_window_width;
 
5644
  row_rectangle.height = clist->row_height;
 
5645
 
 
5646
  /* rectangle of the cell spacing above the row */
 
5647
  cell_rectangle.x = 0;
 
5648
  cell_rectangle.y = row_rectangle.y - CELL_SPACING;
 
5649
  cell_rectangle.width = row_rectangle.width;
 
5650
  cell_rectangle.height = CELL_SPACING;
 
5651
 
 
5652
  /* rectangle used to clip drawing operations, its y and height
 
5653
   * positions only need to be set once, so we set them once here. 
 
5654
   * the x and width are set withing the drawing loop below once per
 
5655
   * column */
 
5656
  clip_rectangle.y = row_rectangle.y;
 
5657
  clip_rectangle.height = row_rectangle.height;
 
5658
 
 
5659
  if (clist_row->state == GTK_STATE_NORMAL)
 
5660
    {
 
5661
      if (clist_row->fg_set)
 
5662
        gdk_gc_set_foreground (clist->fg_gc, &clist_row->foreground);
 
5663
      if (clist_row->bg_set)
 
5664
        gdk_gc_set_foreground (clist->bg_gc, &clist_row->background);
 
5665
    }
 
5666
 
 
5667
  state = clist_row->state;
 
5668
 
 
5669
  /* draw the cell borders and background */
 
5670
  if (area)
 
5671
    {
 
5672
      rect = &intersect_rectangle;
 
5673
      if (gdk_rectangle_intersect (area, &cell_rectangle,
 
5674
                                   &intersect_rectangle))
 
5675
        gdk_draw_rectangle (clist->clist_window,
 
5676
                            widget->style->base_gc[GTK_STATE_NORMAL],
 
5677
                            TRUE,
 
5678
                            intersect_rectangle.x,
 
5679
                            intersect_rectangle.y,
 
5680
                            intersect_rectangle.width,
 
5681
                            intersect_rectangle.height);
 
5682
 
 
5683
      /* the last row has to clear its bottom cell spacing too */
 
5684
      if (clist_row == clist->row_list_end->data)
 
5685
        {
 
5686
          cell_rectangle.y += clist->row_height + CELL_SPACING;
 
5687
 
 
5688
          if (gdk_rectangle_intersect (area, &cell_rectangle,
 
5689
                                       &intersect_rectangle))
 
5690
            gdk_draw_rectangle (clist->clist_window,
 
5691
                                widget->style->base_gc[GTK_STATE_NORMAL],
 
5692
                                TRUE,
 
5693
                                intersect_rectangle.x,
 
5694
                                intersect_rectangle.y,
 
5695
                                intersect_rectangle.width,
 
5696
                                intersect_rectangle.height);
 
5697
        }
 
5698
 
 
5699
      if (!gdk_rectangle_intersect (area, &row_rectangle,&intersect_rectangle))
 
5700
        return;
 
5701
 
 
5702
    }
 
5703
  else
 
5704
    {
 
5705
      rect = &clip_rectangle;
 
5706
      gdk_draw_rectangle (clist->clist_window,
 
5707
                          widget->style->base_gc[GTK_STATE_NORMAL],
 
5708
                          TRUE,
 
5709
                          cell_rectangle.x,
 
5710
                          cell_rectangle.y,
 
5711
                          cell_rectangle.width,
 
5712
                          cell_rectangle.height);
 
5713
 
 
5714
      /* the last row has to clear its bottom cell spacing too */
 
5715
      if (clist_row == clist->row_list_end->data)
 
5716
        {
 
5717
          cell_rectangle.y += clist->row_height + CELL_SPACING;
 
5718
 
 
5719
          gdk_draw_rectangle (clist->clist_window,
 
5720
                              widget->style->base_gc[GTK_STATE_NORMAL],
 
5721
                              TRUE,
 
5722
                              cell_rectangle.x,
 
5723
                              cell_rectangle.y,
 
5724
                              cell_rectangle.width,
 
5725
                              cell_rectangle.height);     
 
5726
        }         
 
5727
    }
 
5728
  
 
5729
  for (last_column = clist->columns - 1;
 
5730
       last_column >= 0 && !clist->column[last_column].visible; last_column--)
 
5731
    ;
 
5732
 
 
5733
  /* iterate and draw all the columns (row cells) and draw their contents */
 
5734
  for (i = 0; i < clist->columns; i++)
 
5735
    {
 
5736
      GtkStyle *style;
 
5737
      GdkGC *fg_gc;
 
5738
      GdkGC *bg_gc;
 
5739
      PangoLayout *layout;
 
5740
      PangoRectangle logical_rect;
 
5741
 
 
5742
      gint width;
 
5743
      gint height;
 
5744
      gint pixmap_width;
 
5745
      gint offset = 0;
 
5746
 
 
5747
      if (!clist->column[i].visible)
 
5748
        continue;
 
5749
 
 
5750
      get_cell_style (clist, clist_row, state, i, &style, &fg_gc, &bg_gc);
 
5751
 
 
5752
      clip_rectangle.x = clist->column[i].area.x + clist->hoffset;
 
5753
      clip_rectangle.width = clist->column[i].area.width;
 
5754
 
 
5755
      /* calculate clipping region clipping region */
 
5756
      clip_rectangle.x -= COLUMN_INSET + CELL_SPACING;
 
5757
      clip_rectangle.width += (2 * COLUMN_INSET + CELL_SPACING +
 
5758
                               (i == last_column) * CELL_SPACING);
 
5759
      
 
5760
      if (area && !gdk_rectangle_intersect (area, &clip_rectangle,
 
5761
                                            &intersect_rectangle))
 
5762
        continue;
 
5763
 
 
5764
      gdk_draw_rectangle (clist->clist_window, bg_gc, TRUE,
 
5765
                          rect->x, rect->y, rect->width, rect->height);
 
5766
 
 
5767
      clip_rectangle.x += COLUMN_INSET + CELL_SPACING;
 
5768
      clip_rectangle.width -= (2 * COLUMN_INSET + CELL_SPACING +
 
5769
                               (i == last_column) * CELL_SPACING);
 
5770
 
 
5771
 
 
5772
      /* calculate real width for column justification */
 
5773
      
 
5774
      layout = _gtk_clist_create_cell_layout (clist, clist_row, i);
 
5775
      if (layout)
 
5776
        {
 
5777
          pango_layout_get_pixel_extents (layout, NULL, &logical_rect);
 
5778
          width = logical_rect.width;
 
5779
        }
 
5780
      else
 
5781
        width = 0;
 
5782
 
 
5783
      pixmap_width = 0;
 
5784
      offset = 0;
 
5785
      switch (clist_row->cell[i].type)
 
5786
        {
 
5787
        case GTK_CELL_PIXMAP:
 
5788
          gdk_window_get_size (GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap,
 
5789
                               &pixmap_width, &height);
 
5790
          width += pixmap_width;
 
5791
          break;
 
5792
        case GTK_CELL_PIXTEXT:
 
5793
          gdk_window_get_size (GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
 
5794
                               &pixmap_width, &height);
 
5795
          width += pixmap_width + GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
 
5796
          break;
 
5797
        default:
 
5798
          break;
 
5799
        }
 
5800
 
 
5801
      switch (clist->column[i].justification)
 
5802
        {
 
5803
        case GTK_JUSTIFY_LEFT:
 
5804
          offset = clip_rectangle.x + clist_row->cell[i].horizontal;
 
5805
          break;
 
5806
        case GTK_JUSTIFY_RIGHT:
 
5807
          offset = (clip_rectangle.x + clist_row->cell[i].horizontal +
 
5808
                    clip_rectangle.width - width);
 
5809
          break;
 
5810
        case GTK_JUSTIFY_CENTER:
 
5811
        case GTK_JUSTIFY_FILL:
 
5812
          offset = (clip_rectangle.x + clist_row->cell[i].horizontal +
 
5813
                    (clip_rectangle.width / 2) - (width / 2));
 
5814
          break;
 
5815
        };
 
5816
 
 
5817
      /* Draw Text and/or Pixmap */
 
5818
      switch (clist_row->cell[i].type)
 
5819
        {
 
5820
        case GTK_CELL_PIXMAP:
 
5821
          draw_cell_pixmap (clist->clist_window, &clip_rectangle, fg_gc,
 
5822
                            GTK_CELL_PIXMAP (clist_row->cell[i])->pixmap,
 
5823
                            GTK_CELL_PIXMAP (clist_row->cell[i])->mask,
 
5824
                            offset,
 
5825
                            clip_rectangle.y + clist_row->cell[i].vertical +
 
5826
                            (clip_rectangle.height - height) / 2,
 
5827
                            pixmap_width, height);
 
5828
          break;
 
5829
        case GTK_CELL_PIXTEXT:
 
5830
          offset =
 
5831
            draw_cell_pixmap (clist->clist_window, &clip_rectangle, fg_gc,
 
5832
                              GTK_CELL_PIXTEXT (clist_row->cell[i])->pixmap,
 
5833
                              GTK_CELL_PIXTEXT (clist_row->cell[i])->mask,
 
5834
                              offset,
 
5835
                              clip_rectangle.y + clist_row->cell[i].vertical+
 
5836
                              (clip_rectangle.height - height) / 2,
 
5837
                              pixmap_width, height);
 
5838
          offset += GTK_CELL_PIXTEXT (clist_row->cell[i])->spacing;
 
5839
 
 
5840
          /* Fall through */
 
5841
        case GTK_CELL_TEXT:
 
5842
          if (layout)
 
5843
            {
 
5844
              gint row_center_offset = (clist->row_height - logical_rect.height - 1) / 2;
 
5845
 
 
5846
              gdk_gc_set_clip_rectangle (fg_gc, &clip_rectangle);
 
5847
              gdk_draw_layout (clist->clist_window, fg_gc,
 
5848
                               offset,
 
5849
                               row_rectangle.y + row_center_offset + clist_row->cell[i].vertical,
 
5850
                               layout);
 
5851
              g_object_unref (G_OBJECT (layout));
 
5852
              gdk_gc_set_clip_rectangle (fg_gc, NULL);
 
5853
            }
 
5854
          break;
 
5855
        default:
 
5856
          break;
 
5857
        }
 
5858
    }
 
5859
 
 
5860
  /* draw focus rectangle */
 
5861
  if (clist->focus_row == row &&
 
5862
      GTK_WIDGET_CAN_FOCUS (widget) && GTK_WIDGET_HAS_FOCUS(widget))
 
5863
    {
 
5864
      if (!area)
 
5865
        gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
 
5866
                            row_rectangle.x, row_rectangle.y,
 
5867
                            row_rectangle.width - 1, row_rectangle.height - 1);
 
5868
      else if (gdk_rectangle_intersect (area, &row_rectangle,
 
5869
                                        &intersect_rectangle))
 
5870
        {
 
5871
          gdk_gc_set_clip_rectangle (clist->xor_gc, &intersect_rectangle);
 
5872
          gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
 
5873
                              row_rectangle.x, row_rectangle.y,
 
5874
                              row_rectangle.width - 1,
 
5875
                              row_rectangle.height - 1);
 
5876
          gdk_gc_set_clip_rectangle (clist->xor_gc, NULL);
 
5877
        }
 
5878
    }
 
5879
}
 
5880
 
 
5881
static void
 
5882
draw_rows (GtkCList     *clist,
 
5883
           GdkRectangle *area)
 
5884
{
 
5885
  GList *list;
 
5886
  GtkCListRow *clist_row;
 
5887
  gint i;
 
5888
  gint first_row;
 
5889
  gint last_row;
 
5890
 
 
5891
  g_return_if_fail (GTK_IS_CLIST (clist));
 
5892
 
 
5893
  if (clist->row_height == 0 ||
 
5894
      !GTK_WIDGET_DRAWABLE (clist))
 
5895
    return;
 
5896
 
 
5897
  if (area)
 
5898
    {
 
5899
      first_row = ROW_FROM_YPIXEL (clist, area->y);
 
5900
      last_row = ROW_FROM_YPIXEL (clist, area->y + area->height);
 
5901
    }
 
5902
  else
 
5903
    {
 
5904
      first_row = ROW_FROM_YPIXEL (clist, 0);
 
5905
      last_row = ROW_FROM_YPIXEL (clist, clist->clist_window_height);
 
5906
    }
 
5907
 
 
5908
  /* this is a small special case which exposes the bottom cell line
 
5909
   * on the last row -- it might go away if I change the wall the cell
 
5910
   * spacings are drawn
 
5911
   */
 
5912
  if (clist->rows == first_row)
 
5913
    first_row--;
 
5914
 
 
5915
  list = ROW_ELEMENT (clist, first_row);
 
5916
  i = first_row;
 
5917
  while (list)
 
5918
    {
 
5919
      clist_row = list->data;
 
5920
      list = list->next;
 
5921
 
 
5922
      if (i > last_row)
 
5923
        return;
 
5924
 
 
5925
      GTK_CLIST_GET_CLASS (clist)->draw_row (clist, area, i, clist_row);
 
5926
      i++;
 
5927
    }
 
5928
 
 
5929
  if (!area)
 
5930
    gdk_window_clear_area (clist->clist_window, 0,
 
5931
                           ROW_TOP_YPIXEL (clist, i), 0, 0);
 
5932
}
 
5933
 
 
5934
static void                          
 
5935
draw_xor_line (GtkCList *clist)
 
5936
{
 
5937
  GtkWidget *widget;
 
5938
 
 
5939
  g_return_if_fail (clist != NULL);
 
5940
 
 
5941
  widget = GTK_WIDGET (clist);
 
5942
 
 
5943
  gdk_draw_line (widget->window, clist->xor_gc,
 
5944
                 clist->x_drag,
 
5945
                 widget->style->ythickness,
 
5946
                 clist->x_drag,
 
5947
                 clist->column_title_area.height +
 
5948
                 clist->clist_window_height + 1);
 
5949
}
 
5950
 
 
5951
static void
 
5952
clist_refresh (GtkCList *clist)
 
5953
{
 
5954
  g_return_if_fail (GTK_IS_CLIST (clist));
 
5955
  
 
5956
  if (CLIST_UNFROZEN (clist))
 
5957
    { 
 
5958
      adjust_adjustments (clist, FALSE);
 
5959
      draw_rows (clist, NULL);
 
5960
    }
 
5961
}
 
5962
 
 
5963
/* get cell from coordinates
 
5964
 *   get_selection_info
 
5965
 *   gtk_clist_get_selection_info
 
5966
 */
 
5967
static gint
 
5968
get_selection_info (GtkCList *clist,
 
5969
                    gint      x,
 
5970
                    gint      y,
 
5971
                    gint     *row,
 
5972
                    gint     *column)
 
5973
{
 
5974
  gint trow, tcol;
 
5975
 
 
5976
  g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
 
5977
 
 
5978
  /* bounds checking, return false if the user clicked 
 
5979
   * on a blank area */
 
5980
  trow = ROW_FROM_YPIXEL (clist, y);
 
5981
  if (trow >= clist->rows)
 
5982
    return 0;
 
5983
 
 
5984
  if (row)
 
5985
    *row = trow;
 
5986
 
 
5987
  tcol = COLUMN_FROM_XPIXEL (clist, x);
 
5988
  if (tcol >= clist->columns)
 
5989
    return 0;
 
5990
 
 
5991
  if (column)
 
5992
    *column = tcol;
 
5993
 
 
5994
  return 1;
 
5995
}
 
5996
 
 
5997
gint
 
5998
gtk_clist_get_selection_info (GtkCList *clist, 
 
5999
                              gint      x, 
 
6000
                              gint      y, 
 
6001
                              gint     *row, 
 
6002
                              gint     *column)
 
6003
{
 
6004
  g_return_val_if_fail (GTK_IS_CLIST (clist), 0);
 
6005
  return get_selection_info (clist, x, y, row, column);
 
6006
}
 
6007
 
 
6008
/* PRIVATE ADJUSTMENT FUNCTIONS
 
6009
 *   adjust_adjustments
 
6010
 *   vadjustment_changed
 
6011
 *   hadjustment_changed
 
6012
 *   vadjustment_value_changed
 
6013
 *   hadjustment_value_changed 
 
6014
 *   check_exposures
 
6015
 */
 
6016
static void
 
6017
adjust_adjustments (GtkCList *clist,
 
6018
                    gboolean  block_resize)
 
6019
{
 
6020
  if (clist->vadjustment)
 
6021
    {
 
6022
      clist->vadjustment->page_size = clist->clist_window_height;
 
6023
      clist->vadjustment->step_increment = clist->row_height;
 
6024
      clist->vadjustment->page_increment =
 
6025
        MAX (clist->vadjustment->page_size - clist->vadjustment->step_increment,
 
6026
             clist->vadjustment->page_size / 2);
 
6027
      clist->vadjustment->lower = 0;
 
6028
      clist->vadjustment->upper = LIST_HEIGHT (clist);
 
6029
 
 
6030
      if (clist->clist_window_height - clist->voffset > LIST_HEIGHT (clist) ||
 
6031
          (clist->voffset + (gint)clist->vadjustment->value) != 0)
 
6032
        {
 
6033
          clist->vadjustment->value = MAX (0, (LIST_HEIGHT (clist) -
 
6034
                                               clist->clist_window_height));
 
6035
          gtk_signal_emit_by_name (GTK_OBJECT (clist->vadjustment),
 
6036
                                   "value_changed");
 
6037
        }
 
6038
      gtk_signal_emit_by_name (GTK_OBJECT (clist->vadjustment), "changed");
 
6039
    }
 
6040
 
 
6041
  if (clist->hadjustment)
 
6042
    {
 
6043
      clist->hadjustment->page_size = clist->clist_window_width;
 
6044
      clist->hadjustment->step_increment = 10;
 
6045
      clist->hadjustment->page_increment =
 
6046
        MAX (clist->hadjustment->page_size - clist->hadjustment->step_increment,
 
6047
             clist->hadjustment->page_size / 2);
 
6048
      clist->hadjustment->lower = 0;
 
6049
      clist->hadjustment->upper = LIST_WIDTH (clist);
 
6050
 
 
6051
      if (clist->clist_window_width - clist->hoffset > LIST_WIDTH (clist) ||
 
6052
          (clist->hoffset + (gint)clist->hadjustment->value) != 0)
 
6053
        {
 
6054
          clist->hadjustment->value = MAX (0, (LIST_WIDTH (clist) -
 
6055
                                               clist->clist_window_width));
 
6056
          gtk_signal_emit_by_name (GTK_OBJECT (clist->hadjustment),
 
6057
                                   "value_changed");
 
6058
        }
 
6059
      gtk_signal_emit_by_name (GTK_OBJECT (clist->hadjustment), "changed");
 
6060
    }
 
6061
 
 
6062
  if (!block_resize && (!clist->vadjustment || !clist->hadjustment))
 
6063
    {
 
6064
      GtkWidget *widget;
 
6065
      GtkRequisition requisition;
 
6066
 
 
6067
      widget = GTK_WIDGET (clist);
 
6068
      gtk_widget_size_request (widget, &requisition);
 
6069
 
 
6070
      if ((!clist->hadjustment &&
 
6071
           requisition.width != widget->allocation.width) ||
 
6072
          (!clist->vadjustment &&
 
6073
           requisition.height != widget->allocation.height))
 
6074
        gtk_widget_queue_resize (widget);
 
6075
    }
 
6076
}
 
6077
 
 
6078
static void
 
6079
vadjustment_changed (GtkAdjustment *adjustment,
 
6080
                     gpointer       data)
 
6081
{
 
6082
  GtkCList *clist;
 
6083
 
 
6084
  g_return_if_fail (adjustment != NULL);
 
6085
  g_return_if_fail (data != NULL);
 
6086
 
 
6087
  clist = GTK_CLIST (data);
 
6088
}
 
6089
 
 
6090
static void
 
6091
hadjustment_changed (GtkAdjustment *adjustment,
 
6092
                     gpointer       data)
 
6093
{
 
6094
  GtkCList *clist;
 
6095
 
 
6096
  g_return_if_fail (adjustment != NULL);
 
6097
  g_return_if_fail (data != NULL);
 
6098
 
 
6099
  clist = GTK_CLIST (data);
 
6100
}
 
6101
 
 
6102
static void
 
6103
vadjustment_value_changed (GtkAdjustment *adjustment,
 
6104
                           gpointer       data)
 
6105
{
 
6106
  GtkCList *clist;
 
6107
  gint dy, value;
 
6108
 
 
6109
  g_return_if_fail (adjustment != NULL);
 
6110
  g_return_if_fail (GTK_IS_CLIST (data));
 
6111
 
 
6112
  clist = GTK_CLIST (data);
 
6113
 
 
6114
  if (adjustment != clist->vadjustment)
 
6115
    return;
 
6116
 
 
6117
  value = -adjustment->value;
 
6118
  dy = value - clist->voffset;
 
6119
  clist->voffset = value;
 
6120
 
 
6121
  if (GTK_WIDGET_DRAWABLE (clist))
 
6122
    {
 
6123
      gdk_window_scroll (clist->clist_window, 0, dy);
 
6124
      gdk_window_process_updates (clist->clist_window, FALSE);
 
6125
    }
 
6126
  
 
6127
  return;
 
6128
}
 
6129
 
 
6130
typedef struct
 
6131
{
 
6132
  GdkWindow *window;
 
6133
  gint dx;
 
6134
} ScrollData;
 
6135
 
 
6136
/* The window to which widget->window is relative */
 
6137
#define ALLOCATION_WINDOW(widget)               \
 
6138
   (GTK_WIDGET_NO_WINDOW (widget) ?             \
 
6139
    (widget)->window :                          \
 
6140
     gdk_window_get_parent ((widget)->window))
 
6141
 
 
6142
static void
 
6143
adjust_allocation_recurse (GtkWidget *widget,
 
6144
                           gpointer   data)
 
6145
{
 
6146
  ScrollData *scroll_data = data;
 
6147
  
 
6148
  if (!GTK_WIDGET_REALIZED (widget))
 
6149
    {
 
6150
      if (GTK_WIDGET_VISIBLE (widget))
 
6151
        {
 
6152
          GdkRectangle tmp_rectangle = widget->allocation;
 
6153
          tmp_rectangle.x += scroll_data->dx;
 
6154
      
 
6155
          gtk_widget_size_allocate (widget, &tmp_rectangle);
 
6156
        }
 
6157
    }
 
6158
  else
 
6159
    {
 
6160
      if (ALLOCATION_WINDOW (widget) == scroll_data->window)
 
6161
        {
 
6162
          widget->allocation.x += scroll_data->dx;
 
6163
 
 
6164
          if (GTK_IS_CONTAINER (widget))
 
6165
            gtk_container_forall (GTK_CONTAINER (widget),
 
6166
                                  adjust_allocation_recurse,
 
6167
                                  data);
 
6168
        }
 
6169
    }
 
6170
}
 
6171
 
 
6172
static void
 
6173
adjust_allocation (GtkWidget *widget,
 
6174
                   gint       dx)
 
6175
{
 
6176
  ScrollData scroll_data;
 
6177
 
 
6178
  if (GTK_WIDGET_REALIZED (widget))
 
6179
    scroll_data.window = ALLOCATION_WINDOW (widget);
 
6180
  else
 
6181
    scroll_data.window = NULL;
 
6182
    
 
6183
  scroll_data.dx = dx;
 
6184
  
 
6185
  adjust_allocation_recurse (widget, &scroll_data);
 
6186
}
 
6187
 
 
6188
static void
 
6189
hadjustment_value_changed (GtkAdjustment *adjustment,
 
6190
                           gpointer       data)
 
6191
{
 
6192
  GtkCList *clist;
 
6193
  GtkContainer *container;
 
6194
  GdkRectangle area;
 
6195
  gint i;
 
6196
  gint y = 0;
 
6197
  gint value;
 
6198
  gint dx;
 
6199
 
 
6200
  g_return_if_fail (adjustment != NULL);
 
6201
  g_return_if_fail (GTK_IS_CLIST (data));
 
6202
 
 
6203
  clist = GTK_CLIST (data);
 
6204
  container = GTK_CONTAINER (data);
 
6205
 
 
6206
  if (adjustment != clist->hadjustment)
 
6207
    return;
 
6208
 
 
6209
  value = adjustment->value;
 
6210
 
 
6211
  dx = -value - clist->hoffset;
 
6212
 
 
6213
  if (GTK_WIDGET_REALIZED (clist))
 
6214
    gdk_window_scroll (clist->title_window, dx, 0);
 
6215
 
 
6216
  /* adjust the column button's allocations */
 
6217
  for (i = 0; i < clist->columns; i++)
 
6218
    if (clist->column[i].button)
 
6219
      adjust_allocation (clist->column[i].button, dx);
 
6220
 
 
6221
  clist->hoffset = -value;
 
6222
 
 
6223
  if (GTK_WIDGET_DRAWABLE (clist))
 
6224
    {
 
6225
      if (GTK_WIDGET_CAN_FOCUS(clist) && GTK_WIDGET_HAS_FOCUS(clist) &&
 
6226
          !container->focus_child && GTK_CLIST_ADD_MODE(clist))
 
6227
        {
 
6228
          y = ROW_TOP_YPIXEL (clist, clist->focus_row);
 
6229
      
 
6230
          gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE, 0, y,
 
6231
                              clist->clist_window_width - 1,
 
6232
                              clist->row_height - 1);
 
6233
        }
 
6234
 
 
6235
      gdk_window_scroll (clist->clist_window, dx, 0);
 
6236
      gdk_window_process_updates (clist->clist_window, FALSE);
 
6237
 
 
6238
      if (GTK_WIDGET_CAN_FOCUS(clist) && GTK_WIDGET_HAS_FOCUS(clist) &&
 
6239
          !container->focus_child)
 
6240
        {
 
6241
          if (GTK_CLIST_ADD_MODE(clist))
 
6242
            {
 
6243
              gint focus_row;
 
6244
          
 
6245
              focus_row = clist->focus_row;
 
6246
              clist->focus_row = -1;
 
6247
              draw_rows (clist, &area);
 
6248
              clist->focus_row = focus_row;
 
6249
          
 
6250
              gdk_draw_rectangle (clist->clist_window, clist->xor_gc,
 
6251
                                  FALSE, 0, y, clist->clist_window_width - 1,
 
6252
                                  clist->row_height - 1);
 
6253
              return;
 
6254
            }
 
6255
          else if (ABS(dx) < clist->clist_window_width - 1)
 
6256
            {
 
6257
              gint x0;
 
6258
              gint x1;
 
6259
          
 
6260
              if (dx > 0)
 
6261
                {
 
6262
                  x0 = clist->clist_window_width - 1;
 
6263
                  x1 = dx;
 
6264
                }
 
6265
              else
 
6266
                {
 
6267
                  x0 = 0;
 
6268
                  x1 = clist->clist_window_width - 1 + dx;
 
6269
                }
 
6270
 
 
6271
              y = ROW_TOP_YPIXEL (clist, clist->focus_row);
 
6272
              gdk_draw_line (clist->clist_window, clist->xor_gc,
 
6273
                             x0, y + 1, x0, y + clist->row_height - 2);
 
6274
              gdk_draw_line (clist->clist_window, clist->xor_gc,
 
6275
                             x1, y + 1, x1, y + clist->row_height - 2);
 
6276
            }
 
6277
        }
 
6278
    }
 
6279
}
 
6280
 
 
6281
/* PRIVATE 
 
6282
 * Memory Allocation/Distruction Routines for GtkCList stuctures
 
6283
 *
 
6284
 * functions:
 
6285
 *   columns_new
 
6286
 *   column_title_new
 
6287
 *   columns_delete
 
6288
 *   row_new
 
6289
 *   row_delete
 
6290
 */
 
6291
static GtkCListColumn *
 
6292
columns_new (GtkCList *clist)
 
6293
{
 
6294
  GtkCListColumn *column;
 
6295
  gint i;
 
6296
 
 
6297
  column = g_new (GtkCListColumn, clist->columns);
 
6298
 
 
6299
  for (i = 0; i < clist->columns; i++)
 
6300
    {
 
6301
      column[i].area.x = 0;
 
6302
      column[i].area.y = 0;
 
6303
      column[i].area.width = 0;
 
6304
      column[i].area.height = 0;
 
6305
      column[i].title = NULL;
 
6306
      column[i].button = NULL;
 
6307
      column[i].window = NULL;
 
6308
      column[i].width = 0;
 
6309
      column[i].min_width = -1;
 
6310
      column[i].max_width = -1;
 
6311
      column[i].visible = TRUE;
 
6312
      column[i].width_set = FALSE;
 
6313
      column[i].resizeable = TRUE;
 
6314
      column[i].auto_resize = FALSE;
 
6315
      column[i].button_passive = FALSE;
 
6316
      column[i].justification = GTK_JUSTIFY_LEFT;
 
6317
    }
 
6318
 
 
6319
  return column;
 
6320
}
 
6321
 
 
6322
static void
 
6323
column_title_new (GtkCList    *clist,
 
6324
                  gint         column,
 
6325
                  const gchar *title)
 
6326
{
 
6327
  if (clist->column[column].title)
 
6328
    g_free (clist->column[column].title);
 
6329
 
 
6330
  clist->column[column].title = g_strdup (title);
 
6331
}
 
6332
 
 
6333
static void
 
6334
columns_delete (GtkCList *clist)
 
6335
{
 
6336
  gint i;
 
6337
 
 
6338
  for (i = 0; i < clist->columns; i++)
 
6339
    if (clist->column[i].title)
 
6340
      g_free (clist->column[i].title);
 
6341
      
 
6342
  g_free (clist->column);
 
6343
}
 
6344
 
 
6345
static GtkCListRow *
 
6346
row_new (GtkCList *clist)
 
6347
{
 
6348
  int i;
 
6349
  GtkCListRow *clist_row;
 
6350
 
 
6351
  clist_row = g_slice_new (GtkCListRow);
 
6352
  clist_row->cell = g_slice_alloc (sizeof (GtkCell) * clist->columns);
 
6353
 
 
6354
  for (i = 0; i < clist->columns; i++)
 
6355
    {
 
6356
      clist_row->cell[i].type = GTK_CELL_EMPTY;
 
6357
      clist_row->cell[i].vertical = 0;
 
6358
      clist_row->cell[i].horizontal = 0;
 
6359
      clist_row->cell[i].style = NULL;
 
6360
    }
 
6361
 
 
6362
  clist_row->fg_set = FALSE;
 
6363
  clist_row->bg_set = FALSE;
 
6364
  clist_row->style = NULL;
 
6365
  clist_row->selectable = TRUE;
 
6366
  clist_row->state = GTK_STATE_NORMAL;
 
6367
  clist_row->data = NULL;
 
6368
  clist_row->destroy = NULL;
 
6369
 
 
6370
  return clist_row;
 
6371
}
 
6372
 
 
6373
static void
 
6374
row_delete (GtkCList    *clist,
 
6375
            GtkCListRow *clist_row)
 
6376
{
 
6377
  gint i;
 
6378
 
 
6379
  for (i = 0; i < clist->columns; i++)
 
6380
    {
 
6381
      GTK_CLIST_GET_CLASS (clist)->set_cell_contents
 
6382
        (clist, clist_row, i, GTK_CELL_EMPTY, NULL, 0, NULL, NULL);
 
6383
      if (clist_row->cell[i].style)
 
6384
        {
 
6385
          if (GTK_WIDGET_REALIZED (clist))
 
6386
            gtk_style_detach (clist_row->cell[i].style);
 
6387
          g_object_unref (clist_row->cell[i].style);
 
6388
        }
 
6389
    }
 
6390
 
 
6391
  if (clist_row->style)
 
6392
    {
 
6393
      if (GTK_WIDGET_REALIZED (clist))
 
6394
        gtk_style_detach (clist_row->style);
 
6395
      g_object_unref (clist_row->style);
 
6396
    }
 
6397
 
 
6398
  if (clist_row->destroy)
 
6399
    clist_row->destroy (clist_row->data);
 
6400
 
 
6401
  g_slice_free1 (sizeof (GtkCell) * clist->columns, clist_row->cell);
 
6402
  g_slice_free (GtkCListRow, clist_row);
 
6403
}
 
6404
 
 
6405
/* FOCUS FUNCTIONS
 
6406
 *   gtk_clist_focus_content_area
 
6407
 *   gtk_clist_focus
 
6408
 *   gtk_clist_draw_focus
 
6409
 *   gtk_clist_focus_in
 
6410
 *   gtk_clist_focus_out
 
6411
 *   title_focus
 
6412
 */
 
6413
static void
 
6414
gtk_clist_focus_content_area (GtkCList *clist)
 
6415
{
 
6416
  if (clist->focus_row < 0)
 
6417
    {
 
6418
      clist->focus_row = 0;
 
6419
      
 
6420
      if ((clist->selection_mode == GTK_SELECTION_BROWSE ||
 
6421
           clist->selection_mode == GTK_SELECTION_MULTIPLE) &&
 
6422
          !clist->selection)
 
6423
        gtk_signal_emit (GTK_OBJECT (clist),
 
6424
                         clist_signals[SELECT_ROW],
 
6425
                         clist->focus_row, -1, NULL);
 
6426
    }
 
6427
  gtk_widget_grab_focus (GTK_WIDGET (clist));
 
6428
}
 
6429
 
 
6430
static gboolean
 
6431
gtk_clist_focus (GtkWidget        *widget,
 
6432
                 GtkDirectionType  direction)
 
6433
{
 
6434
  GtkCList *clist = GTK_CLIST (widget);
 
6435
  GtkWidget *focus_child;
 
6436
  gboolean is_current_focus;
 
6437
 
 
6438
  if (!GTK_WIDGET_IS_SENSITIVE (widget))
 
6439
    return FALSE;
 
6440
 
 
6441
  focus_child = GTK_CONTAINER (widget)->focus_child;
 
6442
  
 
6443
  is_current_focus = gtk_widget_is_focus (GTK_WIDGET (clist));
 
6444
                          
 
6445
  if (focus_child &&
 
6446
      gtk_widget_child_focus (focus_child, direction))
 
6447
    return TRUE;
 
6448
      
 
6449
  switch (direction)
 
6450
    {
 
6451
    case GTK_DIR_LEFT:
 
6452
    case GTK_DIR_RIGHT:
 
6453
      if (focus_child)
 
6454
        {
 
6455
          if (title_focus_move (clist, direction))
 
6456
            return TRUE;
 
6457
        }
 
6458
      else if (!is_current_focus)
 
6459
        {
 
6460
          gtk_clist_focus_content_area (clist);
 
6461
          return TRUE;
 
6462
        }
 
6463
      break;
 
6464
    case GTK_DIR_DOWN:
 
6465
    case GTK_DIR_TAB_FORWARD:
 
6466
      if (!focus_child && !is_current_focus)
 
6467
        {
 
6468
          if (title_focus_in (clist, direction))
 
6469
            return TRUE;
 
6470
        }
 
6471
      
 
6472
      if (!is_current_focus && clist->rows)
 
6473
        {
 
6474
          gtk_clist_focus_content_area (clist);
 
6475
          return TRUE;
 
6476
        }
 
6477
      break;
 
6478
    case GTK_DIR_UP:
 
6479
    case GTK_DIR_TAB_BACKWARD:
 
6480
      if (!focus_child && is_current_focus)
 
6481
        {
 
6482
          if (title_focus_in (clist, direction))
 
6483
            return TRUE;
 
6484
        }
 
6485
      
 
6486
      if (!is_current_focus && !focus_child && clist->rows)
 
6487
        {
 
6488
          gtk_clist_focus_content_area (clist);
 
6489
          return TRUE;
 
6490
        }
 
6491
      break;
 
6492
    default:
 
6493
      break;
 
6494
    }
 
6495
 
 
6496
  return FALSE;
 
6497
}
 
6498
 
 
6499
static void
 
6500
gtk_clist_set_focus_child (GtkContainer *container,
 
6501
                           GtkWidget    *child)
 
6502
{
 
6503
  GtkCList *clist = GTK_CLIST (container);
 
6504
  gint i;
 
6505
 
 
6506
  for (i = 0; i < clist->columns; i++)
 
6507
    if (clist->column[i].button == child)
 
6508
      clist->focus_header_column = i;
 
6509
  
 
6510
  parent_class->set_focus_child (container, child);
 
6511
}
 
6512
 
 
6513
static void
 
6514
gtk_clist_draw_focus (GtkWidget *widget)
 
6515
{
 
6516
  GtkCList *clist;
 
6517
 
 
6518
  g_return_if_fail (GTK_IS_CLIST (widget));
 
6519
 
 
6520
  if (!GTK_WIDGET_DRAWABLE (widget) || !GTK_WIDGET_CAN_FOCUS (widget))
 
6521
    return;
 
6522
 
 
6523
  clist = GTK_CLIST (widget);
 
6524
  if (clist->focus_row >= 0)
 
6525
    gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE,
 
6526
                        0, ROW_TOP_YPIXEL(clist, clist->focus_row),
 
6527
                        clist->clist_window_width - 1,
 
6528
                        clist->row_height - 1);
 
6529
}
 
6530
 
 
6531
static gint
 
6532
gtk_clist_focus_in (GtkWidget     *widget,
 
6533
                    GdkEventFocus *event)
 
6534
{
 
6535
  GtkCList *clist = GTK_CLIST (widget);
 
6536
 
 
6537
  if (clist->selection_mode == GTK_SELECTION_BROWSE &&
 
6538
      clist->selection == NULL && clist->focus_row > -1)
 
6539
    {
 
6540
      GList *list;
 
6541
 
 
6542
      list = g_list_nth (clist->row_list, clist->focus_row);
 
6543
      if (list && GTK_CLIST_ROW (list)->selectable)
 
6544
        gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
 
6545
                         clist->focus_row, -1, event);
 
6546
      else
 
6547
        gtk_clist_draw_focus (widget);
 
6548
    }
 
6549
  else
 
6550
    gtk_clist_draw_focus (widget);
 
6551
 
 
6552
  return FALSE;
 
6553
}
 
6554
 
 
6555
static gint
 
6556
gtk_clist_focus_out (GtkWidget     *widget,
 
6557
                     GdkEventFocus *event)
 
6558
{
 
6559
  GtkCList *clist = GTK_CLIST (widget);
 
6560
 
 
6561
  gtk_clist_draw_focus (widget);
 
6562
  
 
6563
  GTK_CLIST_GET_CLASS (widget)->resync_selection (clist, (GdkEvent *) event);
 
6564
 
 
6565
  return FALSE;
 
6566
}
 
6567
 
 
6568
static gboolean
 
6569
focus_column (GtkCList *clist, gint column, gint dir)
 
6570
{
 
6571
  GtkWidget *child = clist->column[column].button;
 
6572
  
 
6573
  if (gtk_widget_child_focus (child, dir))
 
6574
    {
 
6575
      return TRUE;
 
6576
    }
 
6577
  else if (GTK_WIDGET_CAN_FOCUS (child))
 
6578
    {
 
6579
      gtk_widget_grab_focus (child);
 
6580
      return TRUE;
 
6581
    }
 
6582
 
 
6583
  return FALSE;
 
6584
}
 
6585
 
 
6586
/* Focus moved onto the headers. Focus first focusable and visible child.
 
6587
 * (FIXME: focus the last focused child if visible)
 
6588
 */
 
6589
static gboolean
 
6590
title_focus_in (GtkCList *clist, gint dir)
 
6591
{
 
6592
  gint i;
 
6593
  gint left, right;
 
6594
 
 
6595
  if (!GTK_CLIST_SHOW_TITLES (clist))
 
6596
    return FALSE;
 
6597
 
 
6598
  /* Check last focused column */
 
6599
  if (clist->focus_header_column != -1)
 
6600
    {
 
6601
      i = clist->focus_header_column;
 
6602
      
 
6603
      left = COLUMN_LEFT_XPIXEL (clist, i);
 
6604
      right = left + clist->column[i].area.width;
 
6605
      
 
6606
      if (left >= 0 && right <= clist->clist_window_width)
 
6607
        {
 
6608
          if (focus_column (clist, i, dir))
 
6609
            return TRUE;
 
6610
        }
 
6611
    }
 
6612
 
 
6613
  /* Check fully visible columns */
 
6614
  for (i = 0 ; i < clist->columns ; i++)
 
6615
    {
 
6616
      left = COLUMN_LEFT_XPIXEL (clist, i);
 
6617
      right = left + clist->column[i].area.width;
 
6618
      
 
6619
      if (left >= 0 && right <= clist->clist_window_width)
 
6620
        {
 
6621
          if (focus_column (clist, i, dir))
 
6622
            return TRUE;
 
6623
        }
 
6624
    }
 
6625
 
 
6626
  /* Check partially visible columns */
 
6627
  for (i = 0 ; i < clist->columns ; i++)
 
6628
    {
 
6629
      left = COLUMN_LEFT_XPIXEL (clist, i);
 
6630
      right = left + clist->column[i].area.width;
 
6631
 
 
6632
      if ((left < 0 && right > 0) ||
 
6633
          (left < clist->clist_window_width && right > clist->clist_window_width))
 
6634
        {
 
6635
          if (focus_column (clist, i, dir))
 
6636
            return TRUE;
 
6637
        }
 
6638
    }
 
6639
      
 
6640
  return FALSE;
 
6641
}
 
6642
 
 
6643
/* Move the focus right or left within the title buttons, scrolling
 
6644
 * as necessary to keep the focused child visible.
 
6645
 */
 
6646
static gboolean
 
6647
title_focus_move (GtkCList *clist,
 
6648
                  gint      dir)
 
6649
{
 
6650
  GtkWidget *focus_child;
 
6651
  gboolean return_val = FALSE;
 
6652
  gint d = 0;
 
6653
  gint i = -1;
 
6654
  gint j;
 
6655
 
 
6656
  if (!GTK_CLIST_SHOW_TITLES(clist))
 
6657
    return FALSE;
 
6658
 
 
6659
  focus_child = GTK_CONTAINER (clist)->focus_child;
 
6660
  g_assert (focus_child);
 
6661
 
 
6662
  /* Movement direction within headers
 
6663
   */
 
6664
  switch (dir)
 
6665
    {
 
6666
    case GTK_DIR_RIGHT:
 
6667
      d = 1;
 
6668
      break;
 
6669
    case GTK_DIR_LEFT:
 
6670
      d = -1;
 
6671
      break;
 
6672
    }
 
6673
  
 
6674
  for (i = 0; i < clist->columns; i++)
 
6675
    if (clist->column[i].button == focus_child)
 
6676
      break;
 
6677
  
 
6678
  g_assert (i != -1);           /* Have a starting column */
 
6679
  
 
6680
  j = i + d;
 
6681
  while (!return_val && j >= 0 && j < clist->columns)
 
6682
    {
 
6683
      if (clist->column[j].button &&
 
6684
          GTK_WIDGET_VISIBLE (clist->column[j].button))
 
6685
        {
 
6686
          if (focus_column (clist, j, dir))
 
6687
            {
 
6688
              return_val = TRUE;
 
6689
              break;
 
6690
            }
 
6691
        }
 
6692
      j += d;
 
6693
    }
 
6694
 
 
6695
  /* If we didn't find it, wrap around and keep looking
 
6696
   */
 
6697
  if (!return_val)
 
6698
    {
 
6699
      j = d > 0 ? 0 : clist->columns - 1;
 
6700
 
 
6701
      while (!return_val && j != i)
 
6702
        {
 
6703
          if (clist->column[j].button &&
 
6704
              GTK_WIDGET_VISIBLE (clist->column[j].button))
 
6705
            {
 
6706
              if (focus_column (clist, j, dir))
 
6707
                {
 
6708
                  return_val = TRUE;
 
6709
                  break;
 
6710
                }
 
6711
            }
 
6712
          j += d;
 
6713
        }
 
6714
    }
 
6715
 
 
6716
  /* Scroll horizontally so focused column is visible
 
6717
   */
 
6718
  if (return_val)
 
6719
    {
 
6720
      if (COLUMN_LEFT_XPIXEL (clist, j) < CELL_SPACING + COLUMN_INSET)
 
6721
        gtk_clist_moveto (clist, -1, j, 0, 0);
 
6722
      else if (COLUMN_LEFT_XPIXEL(clist, j) + clist->column[j].area.width >
 
6723
               clist->clist_window_width)
 
6724
        {
 
6725
          gint last_column;
 
6726
          
 
6727
          for (last_column = clist->columns - 1;
 
6728
               last_column >= 0 && !clist->column[last_column].visible; last_column--);
 
6729
 
 
6730
          if (j == last_column)
 
6731
            gtk_clist_moveto (clist, -1, j, 0, 0);
 
6732
          else
 
6733
            gtk_clist_moveto (clist, -1, j, 0, 1);
 
6734
        }
 
6735
    }
 
6736
  return TRUE;                  /* Even if we didn't find a new one, we can keep the
 
6737
                                 * focus in the same place.
 
6738
                                 */
 
6739
}
 
6740
 
 
6741
/* PRIVATE SCROLLING FUNCTIONS
 
6742
 *   move_focus_row
 
6743
 *   scroll_horizontal
 
6744
 *   scroll_vertical
 
6745
 *   move_horizontal
 
6746
 *   move_vertical
 
6747
 *   horizontal_timeout
 
6748
 *   vertical_timeout
 
6749
 *   remove_grab
 
6750
 */
 
6751
static void
 
6752
move_focus_row (GtkCList      *clist,
 
6753
                GtkScrollType  scroll_type,
 
6754
                gfloat         position)
 
6755
{
 
6756
  GtkWidget *widget;
 
6757
 
 
6758
  g_return_if_fail (clist != 0);
 
6759
  g_return_if_fail (GTK_IS_CLIST (clist));
 
6760
 
 
6761
  widget = GTK_WIDGET (clist);
 
6762
 
 
6763
  switch (scroll_type)
 
6764
    {
 
6765
    case GTK_SCROLL_STEP_UP:
 
6766
    case GTK_SCROLL_STEP_BACKWARD:
 
6767
      if (clist->focus_row <= 0)
 
6768
        return;
 
6769
      gtk_clist_draw_focus (widget);
 
6770
      clist->focus_row--;
 
6771
      gtk_clist_draw_focus (widget);
 
6772
      break;
 
6773
 
 
6774
    case GTK_SCROLL_STEP_DOWN:
 
6775
    case GTK_SCROLL_STEP_FORWARD:
 
6776
      if (clist->focus_row >= clist->rows - 1)
 
6777
        return;
 
6778
      gtk_clist_draw_focus (widget);
 
6779
      clist->focus_row++;
 
6780
      gtk_clist_draw_focus (widget);
 
6781
      break;
 
6782
    case GTK_SCROLL_PAGE_UP:
 
6783
    case GTK_SCROLL_PAGE_BACKWARD:
 
6784
      if (clist->focus_row <= 0)
 
6785
        return;
 
6786
      gtk_clist_draw_focus (widget);
 
6787
      clist->focus_row = MAX (0, clist->focus_row -
 
6788
                              (2 * clist->clist_window_height -
 
6789
                               clist->row_height - CELL_SPACING) / 
 
6790
                              (2 * (clist->row_height + CELL_SPACING)));
 
6791
      gtk_clist_draw_focus (widget);
 
6792
      break;
 
6793
    case GTK_SCROLL_PAGE_DOWN:
 
6794
    case GTK_SCROLL_PAGE_FORWARD:
 
6795
      if (clist->focus_row >= clist->rows - 1)
 
6796
        return;
 
6797
      gtk_clist_draw_focus (widget);
 
6798
      clist->focus_row = MIN (clist->rows - 1, clist->focus_row + 
 
6799
                              (2 * clist->clist_window_height -
 
6800
                               clist->row_height - CELL_SPACING) / 
 
6801
                              (2 * (clist->row_height + CELL_SPACING)));
 
6802
      gtk_clist_draw_focus (widget);
 
6803
      break;
 
6804
    case GTK_SCROLL_JUMP:
 
6805
      if (position >= 0 && position <= 1)
 
6806
        {
 
6807
          gtk_clist_draw_focus (widget);
 
6808
          clist->focus_row = position * (clist->rows - 1);
 
6809
          gtk_clist_draw_focus (widget);
 
6810
        }
 
6811
      break;
 
6812
    default:
 
6813
      break;
 
6814
    }
 
6815
}
 
6816
 
 
6817
static void
 
6818
scroll_horizontal (GtkCList      *clist,
 
6819
                   GtkScrollType  scroll_type,
 
6820
                   gfloat         position)
 
6821
{
 
6822
  gint column = 0;
 
6823
  gint last_column;
 
6824
 
 
6825
  g_return_if_fail (clist != 0);
 
6826
  g_return_if_fail (GTK_IS_CLIST (clist));
 
6827
 
 
6828
  if (clist_has_grab (clist))
 
6829
    return;
 
6830
 
 
6831
  for (last_column = clist->columns - 1;
 
6832
       last_column >= 0 && !clist->column[last_column].visible; last_column--)
 
6833
    ;
 
6834
 
 
6835
  switch (scroll_type)
 
6836
    {
 
6837
    case GTK_SCROLL_STEP_BACKWARD:
 
6838
      column = COLUMN_FROM_XPIXEL (clist, 0);
 
6839
      if (COLUMN_LEFT_XPIXEL (clist, column) - CELL_SPACING - COLUMN_INSET >= 0
 
6840
          && column > 0)
 
6841
        column--;
 
6842
      break;
 
6843
    case GTK_SCROLL_STEP_FORWARD:
 
6844
      column = COLUMN_FROM_XPIXEL (clist, clist->clist_window_width);
 
6845
      if (column < 0)
 
6846
        return;
 
6847
      if (COLUMN_LEFT_XPIXEL (clist, column) +
 
6848
          clist->column[column].area.width +
 
6849
          CELL_SPACING + COLUMN_INSET - 1 <= clist->clist_window_width &&
 
6850
          column < last_column)
 
6851
        column++;
 
6852
      break;
 
6853
    case GTK_SCROLL_PAGE_BACKWARD:
 
6854
    case GTK_SCROLL_PAGE_FORWARD:
 
6855
      return;
 
6856
    case GTK_SCROLL_JUMP:
 
6857
      if (position >= 0 && position <= 1)
 
6858
        {
 
6859
          gint vis_columns = 0;
 
6860
          gint i;
 
6861
 
 
6862
          for (i = 0; i <= last_column; i++)
 
6863
            if (clist->column[i].visible)
 
6864
              vis_columns++;
 
6865
 
 
6866
          column = position * vis_columns;
 
6867
 
 
6868
          for (i = 0; i <= last_column && column > 0; i++)
 
6869
            if (clist->column[i].visible)
 
6870
              column--;
 
6871
 
 
6872
          column = i;
 
6873
        }
 
6874
      else
 
6875
        return;
 
6876
      break;
 
6877
    default:
 
6878
      break;
 
6879
    }
 
6880
 
 
6881
  if (COLUMN_LEFT_XPIXEL (clist, column) < CELL_SPACING + COLUMN_INSET)
 
6882
    gtk_clist_moveto (clist, -1, column, 0, 0);
 
6883
  else if (COLUMN_LEFT_XPIXEL (clist, column) + CELL_SPACING + COLUMN_INSET - 1
 
6884
           + clist->column[column].area.width > clist->clist_window_width)
 
6885
    {
 
6886
      if (column == last_column)
 
6887
        gtk_clist_moveto (clist, -1, column, 0, 0);
 
6888
      else
 
6889
        gtk_clist_moveto (clist, -1, column, 0, 1);
 
6890
    }
 
6891
}
 
6892
 
 
6893
static void
 
6894
scroll_vertical (GtkCList      *clist,
 
6895
                 GtkScrollType  scroll_type,
 
6896
                 gfloat         position)
 
6897
{
 
6898
  gint old_focus_row;
 
6899
 
 
6900
  g_return_if_fail (GTK_IS_CLIST (clist));
 
6901
 
 
6902
  if (clist_has_grab (clist))
 
6903
    return;
 
6904
 
 
6905
  switch (clist->selection_mode)
 
6906
    {
 
6907
    case GTK_SELECTION_MULTIPLE:
 
6908
      if (clist->anchor >= 0)
 
6909
        return;
 
6910
    case GTK_SELECTION_BROWSE:
 
6911
 
 
6912
      old_focus_row = clist->focus_row;
 
6913
      move_focus_row (clist, scroll_type, position);
 
6914
 
 
6915
      if (old_focus_row != clist->focus_row)
 
6916
        {
 
6917
          if (clist->selection_mode == GTK_SELECTION_BROWSE)
 
6918
            gtk_signal_emit (GTK_OBJECT (clist), clist_signals[UNSELECT_ROW],
 
6919
                             old_focus_row, -1, NULL);
 
6920
          else if (!GTK_CLIST_ADD_MODE(clist))
 
6921
            {
 
6922
              gtk_clist_unselect_all (clist);
 
6923
              clist->undo_anchor = old_focus_row;
 
6924
            }
 
6925
        }
 
6926
 
 
6927
      switch (gtk_clist_row_is_visible (clist, clist->focus_row))
 
6928
        {
 
6929
        case GTK_VISIBILITY_NONE:
 
6930
          if (old_focus_row != clist->focus_row &&
 
6931
              !(clist->selection_mode == GTK_SELECTION_MULTIPLE &&
 
6932
                GTK_CLIST_ADD_MODE(clist)))
 
6933
            gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
 
6934
                             clist->focus_row, -1, NULL);
 
6935
          switch (scroll_type)
 
6936
            {
 
6937
            case GTK_SCROLL_PAGE_UP:
 
6938
            case GTK_SCROLL_STEP_UP:
 
6939
            case GTK_SCROLL_STEP_BACKWARD:
 
6940
            case GTK_SCROLL_PAGE_BACKWARD:
 
6941
              gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
 
6942
              break;
 
6943
            case GTK_SCROLL_PAGE_DOWN:
 
6944
            case GTK_SCROLL_STEP_DOWN:
 
6945
            case GTK_SCROLL_STEP_FORWARD:
 
6946
            case GTK_SCROLL_PAGE_FORWARD:
 
6947
              gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
 
6948
              break;
 
6949
            case GTK_SCROLL_JUMP:
 
6950
              gtk_clist_moveto (clist, clist->focus_row, -1, 0.5, 0);
 
6951
              break;
 
6952
            default:
 
6953
              break;
 
6954
            }
 
6955
          break;
 
6956
        case GTK_VISIBILITY_PARTIAL:
 
6957
          switch (scroll_type)
 
6958
            {
 
6959
            case GTK_SCROLL_STEP_BACKWARD:
 
6960
            case GTK_SCROLL_PAGE_BACKWARD:
 
6961
              gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
 
6962
              break;
 
6963
            case GTK_SCROLL_STEP_FORWARD:
 
6964
            case GTK_SCROLL_PAGE_FORWARD:
 
6965
              gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
 
6966
              break;
 
6967
            case GTK_SCROLL_JUMP:
 
6968
              gtk_clist_moveto (clist, clist->focus_row, -1, 0.5, 0);
 
6969
              break;
 
6970
            default:
 
6971
              break;
 
6972
            }
 
6973
        default:
 
6974
          if (old_focus_row != clist->focus_row &&
 
6975
              !(clist->selection_mode == GTK_SELECTION_MULTIPLE &&
 
6976
                GTK_CLIST_ADD_MODE(clist)))
 
6977
            gtk_signal_emit (GTK_OBJECT (clist), clist_signals[SELECT_ROW],
 
6978
                             clist->focus_row, -1, NULL);
 
6979
          break;
 
6980
        }
 
6981
      break;
 
6982
    default:
 
6983
      move_focus_row (clist, scroll_type, position);
 
6984
 
 
6985
      if (ROW_TOP_YPIXEL (clist, clist->focus_row) + clist->row_height >
 
6986
          clist->clist_window_height)
 
6987
        gtk_clist_moveto (clist, clist->focus_row, -1, 1, 0);
 
6988
      else if (ROW_TOP_YPIXEL (clist, clist->focus_row) < 0)
 
6989
        gtk_clist_moveto (clist, clist->focus_row, -1, 0, 0);
 
6990
      break;
 
6991
    }
 
6992
}
 
6993
 
 
6994
static void
 
6995
move_horizontal (GtkCList *clist,
 
6996
                 gint      diff)
 
6997
{
 
6998
  gdouble value;
 
6999
 
 
7000
  if (!clist->hadjustment)
 
7001
    return;
 
7002
 
 
7003
  value = CLAMP (clist->hadjustment->value + diff, 0.0,
 
7004
                 clist->hadjustment->upper - clist->hadjustment->page_size);
 
7005
  gtk_adjustment_set_value (clist->hadjustment, value);
 
7006
}
 
7007
 
 
7008
static void
 
7009
move_vertical (GtkCList *clist,
 
7010
               gint      row,
 
7011
               gfloat    align)
 
7012
{
 
7013
  gdouble value;
 
7014
 
 
7015
  if (!clist->vadjustment)
 
7016
    return;
 
7017
 
 
7018
  value = (ROW_TOP_YPIXEL (clist, row) - clist->voffset -
 
7019
           align * (clist->clist_window_height - clist->row_height) +
 
7020
           (2 * align - 1) * CELL_SPACING);
 
7021
 
 
7022
  if (value + clist->vadjustment->page_size > clist->vadjustment->upper)
 
7023
    value = clist->vadjustment->upper - clist->vadjustment->page_size;
 
7024
 
 
7025
  gtk_adjustment_set_value (clist->vadjustment, value);
 
7026
}
 
7027
 
 
7028
static void
 
7029
do_fake_motion (GtkWidget *widget)
 
7030
{
 
7031
  GdkEvent *event = gdk_event_new (GDK_MOTION_NOTIFY);
 
7032
 
 
7033
  event->motion.send_event = TRUE;
 
7034
 
 
7035
  gtk_clist_motion (widget, (GdkEventMotion *)event);
 
7036
  gdk_event_free (event);
 
7037
}
 
7038
 
 
7039
static gint
 
7040
horizontal_timeout (GtkCList *clist)
 
7041
{
 
7042
  GDK_THREADS_ENTER ();
 
7043
 
 
7044
  clist->htimer = 0;
 
7045
  do_fake_motion (GTK_WIDGET (clist));
 
7046
 
 
7047
  GDK_THREADS_LEAVE ();
 
7048
  
 
7049
  return FALSE;
 
7050
}
 
7051
 
 
7052
static gint
 
7053
vertical_timeout (GtkCList *clist)
 
7054
{
 
7055
  GDK_THREADS_ENTER ();
 
7056
 
 
7057
  clist->vtimer = 0;
 
7058
  do_fake_motion (GTK_WIDGET (clist));
 
7059
 
 
7060
  GDK_THREADS_LEAVE ();
 
7061
 
 
7062
  return FALSE;
 
7063
}
 
7064
 
 
7065
static void
 
7066
remove_grab (GtkCList *clist)
 
7067
{
 
7068
  GtkWidget *widget = GTK_WIDGET (clist);
 
7069
  
 
7070
  if (GTK_WIDGET_HAS_GRAB (clist))
 
7071
    {
 
7072
      GdkDisplay *display = gtk_widget_get_display (widget);
 
7073
      
 
7074
      gtk_grab_remove (widget);
 
7075
      if (gdk_display_pointer_is_grabbed (display))
 
7076
        gdk_display_pointer_ungrab (display, GDK_CURRENT_TIME);
 
7077
    }
 
7078
 
 
7079
  if (clist->htimer)
 
7080
    {
 
7081
      g_source_remove (clist->htimer);
 
7082
      clist->htimer = 0;
 
7083
    }
 
7084
 
 
7085
  if (clist->vtimer)
 
7086
    {
 
7087
      g_source_remove (clist->vtimer);
 
7088
      clist->vtimer = 0;
 
7089
    }
 
7090
}
 
7091
 
 
7092
/* PUBLIC SORTING FUNCTIONS
 
7093
 * gtk_clist_sort
 
7094
 * gtk_clist_set_compare_func
 
7095
 * gtk_clist_set_auto_sort
 
7096
 * gtk_clist_set_sort_type
 
7097
 * gtk_clist_set_sort_column
 
7098
 */
 
7099
void
 
7100
gtk_clist_sort (GtkCList *clist)
 
7101
{
 
7102
  g_return_if_fail (GTK_IS_CLIST (clist));
 
7103
 
 
7104
  GTK_CLIST_GET_CLASS (clist)->sort_list (clist);
 
7105
}
 
7106
 
 
7107
void
 
7108
gtk_clist_set_compare_func (GtkCList            *clist,
 
7109
                            GtkCListCompareFunc  cmp_func)
 
7110
{
 
7111
  g_return_if_fail (GTK_IS_CLIST (clist));
 
7112
 
 
7113
  clist->compare = (cmp_func) ? cmp_func : default_compare;
 
7114
}
 
7115
 
 
7116
void       
 
7117
gtk_clist_set_auto_sort (GtkCList *clist,
 
7118
                         gboolean  auto_sort)
 
7119
{
 
7120
  g_return_if_fail (GTK_IS_CLIST (clist));
 
7121
  
 
7122
  if (GTK_CLIST_AUTO_SORT(clist) && !auto_sort)
 
7123
    GTK_CLIST_UNSET_FLAG (clist, CLIST_AUTO_SORT);
 
7124
  else if (!GTK_CLIST_AUTO_SORT(clist) && auto_sort)
 
7125
    {
 
7126
      GTK_CLIST_SET_FLAG (clist, CLIST_AUTO_SORT);
 
7127
      gtk_clist_sort (clist);
 
7128
    }
 
7129
}
 
7130
 
 
7131
void       
 
7132
gtk_clist_set_sort_type (GtkCList    *clist,
 
7133
                         GtkSortType  sort_type)
 
7134
{
 
7135
  g_return_if_fail (GTK_IS_CLIST (clist));
 
7136
  
 
7137
  clist->sort_type = sort_type;
 
7138
}
 
7139
 
 
7140
void
 
7141
gtk_clist_set_sort_column (GtkCList *clist,
 
7142
                           gint      column)
 
7143
{
 
7144
  g_return_if_fail (GTK_IS_CLIST (clist));
 
7145
 
 
7146
  if (column < 0 || column >= clist->columns)
 
7147
    return;
 
7148
 
 
7149
  clist->sort_column = column;
 
7150
}
 
7151
 
 
7152
/* PRIVATE SORTING FUNCTIONS
 
7153
 *   default_compare
 
7154
 *   real_sort_list
 
7155
 *   gtk_clist_merge
 
7156
 *   gtk_clist_mergesort
 
7157
 */
 
7158
static gint
 
7159
default_compare (GtkCList      *clist,
 
7160
                 gconstpointer  ptr1,
 
7161
                 gconstpointer  ptr2)
 
7162
{
 
7163
  char *text1 = NULL;
 
7164
  char *text2 = NULL;
 
7165
 
 
7166
  GtkCListRow *row1 = (GtkCListRow *) ptr1;
 
7167
  GtkCListRow *row2 = (GtkCListRow *) ptr2;
 
7168
 
 
7169
  switch (row1->cell[clist->sort_column].type)
 
7170
    {
 
7171
    case GTK_CELL_TEXT:
 
7172
      text1 = GTK_CELL_TEXT (row1->cell[clist->sort_column])->text;
 
7173
      break;
 
7174
    case GTK_CELL_PIXTEXT:
 
7175
      text1 = GTK_CELL_PIXTEXT (row1->cell[clist->sort_column])->text;
 
7176
      break;
 
7177
    default:
 
7178
      break;
 
7179
    }
 
7180
 
 
7181
  switch (row2->cell[clist->sort_column].type)
 
7182
    {
 
7183
    case GTK_CELL_TEXT:
 
7184
      text2 = GTK_CELL_TEXT (row2->cell[clist->sort_column])->text;
 
7185
      break;
 
7186
    case GTK_CELL_PIXTEXT:
 
7187
      text2 = GTK_CELL_PIXTEXT (row2->cell[clist->sort_column])->text;
 
7188
      break;
 
7189
    default:
 
7190
      break;
 
7191
    }
 
7192
 
 
7193
  if (!text2)
 
7194
    return (text1 != NULL);
 
7195
 
 
7196
  if (!text1)
 
7197
    return -1;
 
7198
 
 
7199
  return strcmp (text1, text2);
 
7200
}
 
7201
 
 
7202
static void
 
7203
real_sort_list (GtkCList *clist)
 
7204
{
 
7205
  GList *list;
 
7206
  GList *work;
 
7207
  gint i;
 
7208
 
 
7209
  g_return_if_fail (GTK_IS_CLIST (clist));
 
7210
 
 
7211
  if (clist->rows <= 1)
 
7212
    return;
 
7213
 
 
7214
  if (clist_has_grab (clist))
 
7215
    return;
 
7216
 
 
7217
  gtk_clist_freeze (clist);
 
7218
 
 
7219
  if (clist->anchor != -1 && clist->selection_mode == GTK_SELECTION_MULTIPLE)
 
7220
    {
 
7221
      GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
 
7222
      g_list_free (clist->undo_selection);
 
7223
      g_list_free (clist->undo_unselection);
 
7224
      clist->undo_selection = NULL;
 
7225
      clist->undo_unselection = NULL;
 
7226
    }
 
7227
   
 
7228
  clist->row_list = gtk_clist_mergesort (clist, clist->row_list, clist->rows);
 
7229
 
 
7230
  work = clist->selection;
 
7231
 
 
7232
  for (i = 0, list = clist->row_list; i < clist->rows; i++, list = list->next)
 
7233
    {
 
7234
      if (GTK_CLIST_ROW (list)->state == GTK_STATE_SELECTED)
 
7235
        {
 
7236
          work->data = GINT_TO_POINTER (i);
 
7237
          work = work->next;
 
7238
        }
 
7239
      
 
7240
      if (i == clist->rows - 1)
 
7241
        clist->row_list_end = list;
 
7242
    }
 
7243
 
 
7244
  gtk_clist_thaw (clist);
 
7245
}
 
7246
 
 
7247
static GList *
 
7248
gtk_clist_merge (GtkCList *clist,
 
7249
                 GList    *a,         /* first list to merge */
 
7250
                 GList    *b)         /* second list to merge */
 
7251
{
 
7252
  GList z = { 0 };                    /* auxiliary node */
 
7253
  GList *c;
 
7254
  gint cmp;
 
7255
 
 
7256
  c = &z;
 
7257
 
 
7258
  while (a || b)
 
7259
    {
 
7260
      if (a && !b)
 
7261
        {
 
7262
          c->next = a;
 
7263
          a->prev = c;
 
7264
          c = a;
 
7265
          a = a->next;
 
7266
          break;
 
7267
        }
 
7268
      else if (!a && b)
 
7269
        {
 
7270
          c->next = b;
 
7271
          b->prev = c;
 
7272
          c = b;
 
7273
          b = b->next;
 
7274
          break;
 
7275
        }
 
7276
      else /* a && b */
 
7277
        {
 
7278
          cmp = clist->compare (clist, GTK_CLIST_ROW (a), GTK_CLIST_ROW (b));
 
7279
          if ((cmp >= 0 && clist->sort_type == GTK_SORT_DESCENDING) ||
 
7280
              (cmp <= 0 && clist->sort_type == GTK_SORT_ASCENDING) ||
 
7281
              (a && !b))
 
7282
            {
 
7283
              c->next = a;
 
7284
              a->prev = c;
 
7285
              c = a;
 
7286
              a = a->next;
 
7287
            }
 
7288
          else
 
7289
            {
 
7290
              c->next = b;
 
7291
              b->prev = c;
 
7292
              c = b;
 
7293
              b = b->next;
 
7294
            }
 
7295
        }
 
7296
    }
 
7297
 
 
7298
  z.next->prev = NULL;
 
7299
  return z.next;
 
7300
}
 
7301
 
 
7302
static GList *
 
7303
gtk_clist_mergesort (GtkCList *clist,
 
7304
                     GList    *list,         /* the list to sort */
 
7305
                     gint      num)          /* the list's length */
 
7306
{
 
7307
  GList *half;
 
7308
  gint i;
 
7309
 
 
7310
  if (num <= 1)
 
7311
    {
 
7312
      return list;
 
7313
    }
 
7314
  else
 
7315
    {
 
7316
      /* move "half" to the middle */
 
7317
      half = list;
 
7318
      for (i = 0; i < num / 2; i++)
 
7319
        half = half->next;
 
7320
 
 
7321
      /* cut the list in two */
 
7322
      half->prev->next = NULL;
 
7323
      half->prev = NULL;
 
7324
 
 
7325
      /* recursively sort both lists */
 
7326
      return gtk_clist_merge (clist,
 
7327
                       gtk_clist_mergesort (clist, list, num / 2),
 
7328
                       gtk_clist_mergesort (clist, half, num - num / 2));
 
7329
    }
 
7330
}
 
7331
 
 
7332
/************************/
 
7333
 
 
7334
static void
 
7335
drag_source_info_destroy (gpointer data)
 
7336
{
 
7337
  GtkCListCellInfo *info = data;
 
7338
 
 
7339
  g_free (info);
 
7340
}
 
7341
 
 
7342
static void
 
7343
drag_dest_info_destroy (gpointer data)
 
7344
{
 
7345
  GtkCListDestInfo *info = data;
 
7346
 
 
7347
  g_free (info);
 
7348
}
 
7349
 
 
7350
static void
 
7351
drag_dest_cell (GtkCList         *clist,
 
7352
                gint              x,
 
7353
                gint              y,
 
7354
                GtkCListDestInfo *dest_info)
 
7355
{
 
7356
  GtkWidget *widget;
 
7357
 
 
7358
  widget = GTK_WIDGET (clist);
 
7359
 
 
7360
  dest_info->insert_pos = GTK_CLIST_DRAG_NONE;
 
7361
 
 
7362
  y -= (GTK_CONTAINER (clist)->border_width +
 
7363
        widget->style->ythickness +
 
7364
        clist->column_title_area.height);
 
7365
 
 
7366
  dest_info->cell.row = ROW_FROM_YPIXEL (clist, y);
 
7367
  if (dest_info->cell.row >= clist->rows)
 
7368
    {
 
7369
      dest_info->cell.row = clist->rows - 1;
 
7370
      y = ROW_TOP_YPIXEL (clist, dest_info->cell.row) + clist->row_height;
 
7371
    }
 
7372
  if (dest_info->cell.row < -1)
 
7373
    dest_info->cell.row = -1;
 
7374
  
 
7375
  x -= GTK_CONTAINER (widget)->border_width + widget->style->xthickness;
 
7376
 
 
7377
  dest_info->cell.column = COLUMN_FROM_XPIXEL (clist, x);
 
7378
 
 
7379
  if (dest_info->cell.row >= 0)
 
7380
    {
 
7381
      gint y_delta;
 
7382
      gint h = 0;
 
7383
 
 
7384
      y_delta = y - ROW_TOP_YPIXEL (clist, dest_info->cell.row);
 
7385
      
 
7386
      if (GTK_CLIST_DRAW_DRAG_RECT(clist))
 
7387
        {
 
7388
          dest_info->insert_pos = GTK_CLIST_DRAG_INTO;
 
7389
          h = clist->row_height / 4;
 
7390
        }
 
7391
      else if (GTK_CLIST_DRAW_DRAG_LINE(clist))
 
7392
        {
 
7393
          dest_info->insert_pos = GTK_CLIST_DRAG_BEFORE;
 
7394
          h = clist->row_height / 2;
 
7395
        }
 
7396
 
 
7397
      if (GTK_CLIST_DRAW_DRAG_LINE(clist))
 
7398
        {
 
7399
          if (y_delta < h)
 
7400
            dest_info->insert_pos = GTK_CLIST_DRAG_BEFORE;
 
7401
          else if (clist->row_height - y_delta < h)
 
7402
            dest_info->insert_pos = GTK_CLIST_DRAG_AFTER;
 
7403
        }
 
7404
    }
 
7405
}
 
7406
 
 
7407
static void
 
7408
gtk_clist_drag_begin (GtkWidget      *widget,
 
7409
                      GdkDragContext *context)
 
7410
{
 
7411
  GtkCList *clist;
 
7412
  GtkCListCellInfo *info;
 
7413
 
 
7414
  g_return_if_fail (GTK_IS_CLIST (widget));
 
7415
  g_return_if_fail (context != NULL);
 
7416
 
 
7417
  clist = GTK_CLIST (widget);
 
7418
 
 
7419
  clist->drag_button = 0;
 
7420
  remove_grab (clist);
 
7421
 
 
7422
  switch (clist->selection_mode)
 
7423
    {
 
7424
    case GTK_SELECTION_MULTIPLE:
 
7425
      update_extended_selection (clist, clist->focus_row);
 
7426
      GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
 
7427
      break;
 
7428
    case GTK_SELECTION_SINGLE:
 
7429
      clist->anchor = -1;
 
7430
    case GTK_SELECTION_BROWSE:
 
7431
      break;
 
7432
    default:
 
7433
      g_assert_not_reached ();
 
7434
    }
 
7435
 
 
7436
  info = g_dataset_get_data (context, "gtk-clist-drag-source");
 
7437
 
 
7438
  if (!info)
 
7439
    {
 
7440
      info = g_new (GtkCListCellInfo, 1);
 
7441
 
 
7442
      if (clist->click_cell.row < 0)
 
7443
        clist->click_cell.row = 0;
 
7444
      else if (clist->click_cell.row >= clist->rows)
 
7445
        clist->click_cell.row = clist->rows - 1;
 
7446
      info->row = clist->click_cell.row;
 
7447
      info->column = clist->click_cell.column;
 
7448
 
 
7449
      g_dataset_set_data_full (context, "gtk-clist-drag-source", info,
 
7450
                               drag_source_info_destroy);
 
7451
    }
 
7452
 
 
7453
  if (GTK_CLIST_USE_DRAG_ICONS (clist))
 
7454
    gtk_drag_set_icon_default (context);
 
7455
}
 
7456
 
 
7457
static void
 
7458
gtk_clist_drag_end (GtkWidget      *widget,
 
7459
                    GdkDragContext *context)
 
7460
{
 
7461
  GtkCList *clist;
 
7462
 
 
7463
  g_return_if_fail (GTK_IS_CLIST (widget));
 
7464
  g_return_if_fail (context != NULL);
 
7465
 
 
7466
  clist = GTK_CLIST (widget);
 
7467
 
 
7468
  clist->click_cell.row = -1;
 
7469
  clist->click_cell.column = -1;
 
7470
}
 
7471
 
 
7472
static void
 
7473
gtk_clist_drag_leave (GtkWidget      *widget,
 
7474
                      GdkDragContext *context,
 
7475
                      guint           time)
 
7476
{
 
7477
  GtkCList *clist;
 
7478
  GtkCListDestInfo *dest_info;
 
7479
 
 
7480
  g_return_if_fail (GTK_IS_CLIST (widget));
 
7481
  g_return_if_fail (context != NULL);
 
7482
 
 
7483
  clist = GTK_CLIST (widget);
 
7484
 
 
7485
  dest_info = g_dataset_get_data (context, "gtk-clist-drag-dest");
 
7486
  
 
7487
  if (dest_info)
 
7488
    {
 
7489
      if (dest_info->cell.row >= 0 &&
 
7490
          GTK_CLIST_REORDERABLE(clist) &&
 
7491
          gtk_drag_get_source_widget (context) == widget)
 
7492
        {
 
7493
          GList *list;
 
7494
          GdkAtom atom = gdk_atom_intern_static_string ("gtk-clist-drag-reorder");
 
7495
 
 
7496
          list = context->targets;
 
7497
          while (list)
 
7498
            {
 
7499
              if (atom == GDK_POINTER_TO_ATOM (list->data))
 
7500
                {
 
7501
                  GTK_CLIST_GET_CLASS (clist)->draw_drag_highlight
 
7502
                    (clist,
 
7503
                     g_list_nth (clist->row_list, dest_info->cell.row)->data,
 
7504
                     dest_info->cell.row, dest_info->insert_pos);
 
7505
                  clist->drag_highlight_row = -1;
 
7506
                  break;
 
7507
                }
 
7508
              list = list->next;
 
7509
            }
 
7510
        }
 
7511
      g_dataset_remove_data (context, "gtk-clist-drag-dest");
 
7512
    }
 
7513
}
 
7514
 
 
7515
static gint
 
7516
gtk_clist_drag_motion (GtkWidget      *widget,
 
7517
                       GdkDragContext *context,
 
7518
                       gint            x,
 
7519
                       gint            y,
 
7520
                       guint           time)
 
7521
{
 
7522
  GtkCList *clist;
 
7523
  GtkCListDestInfo new_info;
 
7524
  GtkCListDestInfo *dest_info;
 
7525
 
 
7526
  g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
 
7527
 
 
7528
  clist = GTK_CLIST (widget);
 
7529
 
 
7530
  dest_info = g_dataset_get_data (context, "gtk-clist-drag-dest");
 
7531
 
 
7532
  if (!dest_info)
 
7533
    {
 
7534
      dest_info = g_new (GtkCListDestInfo, 1);
 
7535
 
 
7536
      dest_info->insert_pos  = GTK_CLIST_DRAG_NONE;
 
7537
      dest_info->cell.row    = -1;
 
7538
      dest_info->cell.column = -1;
 
7539
 
 
7540
      g_dataset_set_data_full (context, "gtk-clist-drag-dest", dest_info,
 
7541
                               drag_dest_info_destroy);
 
7542
    }
 
7543
 
 
7544
  drag_dest_cell (clist, x, y, &new_info);
 
7545
 
 
7546
  if (GTK_CLIST_REORDERABLE (clist))
 
7547
    {
 
7548
      GList *list;
 
7549
      GdkAtom atom = gdk_atom_intern_static_string ("gtk-clist-drag-reorder");
 
7550
 
 
7551
      list = context->targets;
 
7552
      while (list)
 
7553
        {
 
7554
          if (atom == GDK_POINTER_TO_ATOM (list->data))
 
7555
            break;
 
7556
          list = list->next;
 
7557
        }
 
7558
 
 
7559
      if (list)
 
7560
        {
 
7561
          if (gtk_drag_get_source_widget (context) != widget ||
 
7562
              new_info.insert_pos == GTK_CLIST_DRAG_NONE ||
 
7563
              new_info.cell.row == clist->click_cell.row ||
 
7564
              (new_info.cell.row == clist->click_cell.row - 1 &&
 
7565
               new_info.insert_pos == GTK_CLIST_DRAG_AFTER) ||
 
7566
              (new_info.cell.row == clist->click_cell.row + 1 &&
 
7567
               new_info.insert_pos == GTK_CLIST_DRAG_BEFORE))
 
7568
            {
 
7569
              if (dest_info->cell.row < 0)
 
7570
                {
 
7571
                  gdk_drag_status (context, GDK_ACTION_DEFAULT, time);
 
7572
                  return FALSE;
 
7573
                }
 
7574
              return TRUE;
 
7575
            }
 
7576
                
 
7577
          if (new_info.cell.row != dest_info->cell.row ||
 
7578
              (new_info.cell.row == dest_info->cell.row &&
 
7579
               dest_info->insert_pos != new_info.insert_pos))
 
7580
            {
 
7581
              if (dest_info->cell.row >= 0)
 
7582
                GTK_CLIST_GET_CLASS (clist)->draw_drag_highlight
 
7583
                  (clist, g_list_nth (clist->row_list,
 
7584
                                      dest_info->cell.row)->data,
 
7585
                   dest_info->cell.row, dest_info->insert_pos);
 
7586
 
 
7587
              dest_info->insert_pos  = new_info.insert_pos;
 
7588
              dest_info->cell.row    = new_info.cell.row;
 
7589
              dest_info->cell.column = new_info.cell.column;
 
7590
              
 
7591
              GTK_CLIST_GET_CLASS (clist)->draw_drag_highlight
 
7592
                (clist, g_list_nth (clist->row_list,
 
7593
                                    dest_info->cell.row)->data,
 
7594
                 dest_info->cell.row, dest_info->insert_pos);
 
7595
              
 
7596
              clist->drag_highlight_row = dest_info->cell.row;
 
7597
              clist->drag_highlight_pos = dest_info->insert_pos;
 
7598
 
 
7599
              gdk_drag_status (context, context->suggested_action, time);
 
7600
            }
 
7601
          return TRUE;
 
7602
        }
 
7603
    }
 
7604
 
 
7605
  dest_info->insert_pos  = new_info.insert_pos;
 
7606
  dest_info->cell.row    = new_info.cell.row;
 
7607
  dest_info->cell.column = new_info.cell.column;
 
7608
  return TRUE;
 
7609
}
 
7610
 
 
7611
static gboolean
 
7612
gtk_clist_drag_drop (GtkWidget      *widget,
 
7613
                     GdkDragContext *context,
 
7614
                     gint            x,
 
7615
                     gint            y,
 
7616
                     guint           time)
 
7617
{
 
7618
  g_return_val_if_fail (GTK_IS_CLIST (widget), FALSE);
 
7619
  g_return_val_if_fail (context != NULL, FALSE);
 
7620
 
 
7621
  if (GTK_CLIST_REORDERABLE (widget) &&
 
7622
      gtk_drag_get_source_widget (context) == widget)
 
7623
    {
 
7624
      GList *list;
 
7625
      GdkAtom atom = gdk_atom_intern_static_string ("gtk-clist-drag-reorder");
 
7626
 
 
7627
      list = context->targets;
 
7628
      while (list)
 
7629
        {
 
7630
          if (atom == GDK_POINTER_TO_ATOM (list->data))
 
7631
            return TRUE;
 
7632
          list = list->next;
 
7633
        }
 
7634
    }
 
7635
  return FALSE;
 
7636
}
 
7637
 
 
7638
static void
 
7639
gtk_clist_drag_data_received (GtkWidget        *widget,
 
7640
                              GdkDragContext   *context,
 
7641
                              gint              x,
 
7642
                              gint              y,
 
7643
                              GtkSelectionData *selection_data,
 
7644
                              guint             info,
 
7645
                              guint             time)
 
7646
{
 
7647
  GtkCList *clist;
 
7648
 
 
7649
  g_return_if_fail (GTK_IS_CLIST (widget));
 
7650
  g_return_if_fail (context != NULL);
 
7651
  g_return_if_fail (selection_data != NULL);
 
7652
 
 
7653
  clist = GTK_CLIST (widget);
 
7654
 
 
7655
  if (GTK_CLIST_REORDERABLE (clist) &&
 
7656
      gtk_drag_get_source_widget (context) == widget &&
 
7657
      selection_data->target ==
 
7658
      gdk_atom_intern_static_string ("gtk-clist-drag-reorder") &&
 
7659
      selection_data->format == 8 &&
 
7660
      selection_data->length == sizeof (GtkCListCellInfo))
 
7661
    {
 
7662
      GtkCListCellInfo *source_info;
 
7663
 
 
7664
      source_info = (GtkCListCellInfo *)(selection_data->data);
 
7665
      if (source_info)
 
7666
        {
 
7667
          GtkCListDestInfo dest_info;
 
7668
 
 
7669
          drag_dest_cell (clist, x, y, &dest_info);
 
7670
 
 
7671
          if (dest_info.insert_pos == GTK_CLIST_DRAG_AFTER)
 
7672
            dest_info.cell.row++;
 
7673
          if (source_info->row < dest_info.cell.row)
 
7674
            dest_info.cell.row--;
 
7675
          if (dest_info.cell.row != source_info->row)
 
7676
            gtk_clist_row_move (clist, source_info->row, dest_info.cell.row);
 
7677
 
 
7678
          g_dataset_remove_data (context, "gtk-clist-drag-dest");
 
7679
        }
 
7680
    }
 
7681
}
 
7682
 
 
7683
static void  
 
7684
gtk_clist_drag_data_get (GtkWidget        *widget,
 
7685
                         GdkDragContext   *context,
 
7686
                         GtkSelectionData *selection_data,
 
7687
                         guint             info,
 
7688
                         guint             time)
 
7689
{
 
7690
  g_return_if_fail (GTK_IS_CLIST (widget));
 
7691
  g_return_if_fail (context != NULL);
 
7692
  g_return_if_fail (selection_data != NULL);
 
7693
 
 
7694
  if (selection_data->target == gdk_atom_intern_static_string ("gtk-clist-drag-reorder"))
 
7695
    {
 
7696
      GtkCListCellInfo *info;
 
7697
 
 
7698
      info = g_dataset_get_data (context, "gtk-clist-drag-source");
 
7699
 
 
7700
      if (info)
 
7701
        {
 
7702
          GtkCListCellInfo ret_info;
 
7703
 
 
7704
          ret_info.row = info->row;
 
7705
          ret_info.column = info->column;
 
7706
 
 
7707
          gtk_selection_data_set (selection_data, selection_data->target,
 
7708
                                  8, (guchar *) &ret_info,
 
7709
                                  sizeof (GtkCListCellInfo));
 
7710
        }
 
7711
    }
 
7712
}
 
7713
 
 
7714
static void
 
7715
draw_drag_highlight (GtkCList        *clist,
 
7716
                     GtkCListRow     *dest_row,
 
7717
                     gint             dest_row_number,
 
7718
                     GtkCListDragPos  drag_pos)
 
7719
{
 
7720
  gint y;
 
7721
 
 
7722
  y = ROW_TOP_YPIXEL (clist, dest_row_number) - 1;
 
7723
 
 
7724
  switch (drag_pos)
 
7725
    {
 
7726
    case GTK_CLIST_DRAG_NONE:
 
7727
      break;
 
7728
    case GTK_CLIST_DRAG_AFTER:
 
7729
      y += clist->row_height + 1;
 
7730
    case GTK_CLIST_DRAG_BEFORE:
 
7731
      gdk_draw_line (clist->clist_window, clist->xor_gc,
 
7732
                     0, y, clist->clist_window_width, y);
 
7733
      break;
 
7734
    case GTK_CLIST_DRAG_INTO:
 
7735
      gdk_draw_rectangle (clist->clist_window, clist->xor_gc, FALSE, 0, y,
 
7736
                          clist->clist_window_width - 1, clist->row_height);
 
7737
      break;
 
7738
    }
 
7739
}
 
7740
 
 
7741
void
 
7742
gtk_clist_set_reorderable (GtkCList *clist, 
 
7743
                           gboolean  reorderable)
 
7744
{
 
7745
  GtkWidget *widget;
 
7746
 
 
7747
  g_return_if_fail (GTK_IS_CLIST (clist));
 
7748
 
 
7749
  if ((GTK_CLIST_REORDERABLE(clist) != 0) == reorderable)
 
7750
    return;
 
7751
 
 
7752
  widget = GTK_WIDGET (clist);
 
7753
 
 
7754
  if (reorderable)
 
7755
    {
 
7756
      GTK_CLIST_SET_FLAG (clist, CLIST_REORDERABLE);
 
7757
      gtk_drag_dest_set (widget,
 
7758
                         GTK_DEST_DEFAULT_MOTION | GTK_DEST_DEFAULT_DROP,
 
7759
                         &clist_target_table, 1, GDK_ACTION_MOVE);
 
7760
    }
 
7761
  else
 
7762
    {
 
7763
      GTK_CLIST_UNSET_FLAG (clist, CLIST_REORDERABLE);
 
7764
      gtk_drag_dest_unset (GTK_WIDGET (clist));
 
7765
    }
 
7766
}
 
7767
 
 
7768
void
 
7769
gtk_clist_set_use_drag_icons (GtkCList *clist,
 
7770
                              gboolean  use_icons)
 
7771
{
 
7772
  g_return_if_fail (GTK_IS_CLIST (clist));
 
7773
 
 
7774
  if (use_icons != 0)
 
7775
    GTK_CLIST_SET_FLAG (clist, CLIST_USE_DRAG_ICONS);
 
7776
  else
 
7777
    GTK_CLIST_UNSET_FLAG (clist, CLIST_USE_DRAG_ICONS);
 
7778
}
 
7779
 
 
7780
void
 
7781
gtk_clist_set_button_actions (GtkCList *clist,
 
7782
                              guint     button,
 
7783
                              guint8    button_actions)
 
7784
{
 
7785
  g_return_if_fail (GTK_IS_CLIST (clist));
 
7786
  
 
7787
  if (button < MAX_BUTTON)
 
7788
    {
 
7789
      if (gdk_display_pointer_is_grabbed (gtk_widget_get_display (GTK_WIDGET (clist))) || 
 
7790
          GTK_WIDGET_HAS_GRAB (clist))
 
7791
        {
 
7792
          remove_grab (clist);
 
7793
          clist->drag_button = 0;
 
7794
        }
 
7795
 
 
7796
      GTK_CLIST_GET_CLASS (clist)->resync_selection (clist, NULL);
 
7797
 
 
7798
      clist->button_actions[button] = button_actions;
 
7799
    }
 
7800
}
 
7801
 
 
7802
#define __GTK_CLIST_C__
 
7803
#include "gtkaliasdef.c"
 
7804